PROCEDURE Stroke( v: Leaf;
READONLY clip: Rect.T; path: Path.T;
width: CARDINAL := 0; end := EndStyle.Round; join := JoinStyle.Round;
op: PaintOp.T := PaintOp.BgFg; src: Pixmap.T := Pixmap.Solid;
READONLY delta := Point.Origin); <* LL.sup < v *>
Paint the intersection ofclipand the stroke determined bypath,end, and
joinwith the texturesrc+deltausing the operationop.
The exact results ofStrokeare different on different Trestle implementations. The approximate specification is like PostScript:
Ifend = Roundandjoin = Round, the path is drawn by a circular brush of diameterwidththat traverses the path.
Ifend = Butt, then the ends of unclosed trails in the path are stroked by a line segment of lengthwidthcentered and perpendicular to the path in the neighborhood of the endpoint. Ifend = Square, the path is extended at the endpoint by a straight line segment of lengthwidth/2tangent to the path and a butt end is drawn.
Ifjoin = Bevel, the joint between two patches is constructed by usingButt
endstyles for them and then filling the triangular notch that remains. If join = Miter, then instead of just filling the triangular notch, the outer edges of the two lines are extended to meet at a point, and the resulting quadrilateral is filled.
Ifwidth = 0,joinis ignored andenddetermines whether the final endpoint of an open subpath should be drawn: ifendisButt, the final endpoint is omitted, otherwise it is drawn.
Finally, there is a convenience procedure for stroking a path containing a single straight line segment:
PROCEDURE Line( v: Leaf;
READONLY clip: Rect.T; p, q: Point.T;
width: CARDINAL := 0; end := EndStyle.Round;
op: PaintOp.T := PaintOp.BgFg; src: Pixmap.T := Pixmap.Solid;
READONLY delta := Point.Origin); <* LL.sup < v *>
LikeStrokeapplied to the path containing the segment(p,q).
2.20
Painting pixmaps
PROCEDURE PaintPixmap( v: Leaf;
READONLY clip: Rect.T := Rect.Full; op: PaintOp.T := PaintOp.BgFg; src: Pixmap.T;
READONLY delta: Point.T); <* LL.sup < v *>
Translate the pixmapsrcbydeltaand paint it on the screen ofv, using the operationopand clipping to the rectangleclip.
More precisely,PaintPixmap(v, clip, op, src, delta)is equivalent to for each pair of pointsp,qsuch that
p is in clip,
q is in Domain(src), and
p = q + delta,
assign
v[p] := op(v[p], src[q])
Since aPixmap.Tis a screen-independent resource, you can’t read its domain without specifying theVBTit is to be used on:
PROCEDURE PixmapDomain(v: T; pix: Pixmap.T): Rect.T; <* LL.sup < v *>
Return the domain ofpixon the screentype ofv.
It is also possible to paint screen-dependent pixmaps:
PROCEDURE PaintScrnPixmap( v: Leaf;
READONLY clip: Rect.T := Rect.Full; op: PaintOp.T := PaintOp.Copy; src: ScrnPixmap.T;
READONLY delta: Point.T); <* LL.sup < v *>
Like PaintPixmap, but with a screen-dependent pixmap instead of a screen-independent pixmap.
Ifsrcdoes not have an appropriate screentype forv, the effect of the procedure is undefined but limited to the clipping region.
Because Trestle batches painting operations, the pixmapsrcmust be regarded as still in use afterPaintScrnPixmapreturns. If you wish to free the pixmap by calling
src.free(), you should first callVBT.Sync(v).
2.21
Painting text
The text painting procedures take an optional array of displacements, whose entries have the following type:
2.21 Painting text 27
TYPE
DeltaH = [-512 .. 511]; Displacement =
RECORD index: CARDINAL; dh: DeltaH END;
A displacementdcauses all characters whose index in the text isd.indexor greater to be displacedd.dhpixels to the right. The first character has index0. Thed.index
values in an array of displacements must be non-decreasing.
PROCEDURE PaintText( v: Leaf;
READONLY clip: Rect.T := Rect.Full; READONLY pt: Point.T;
fnt: Font.T := Font.BuiltIn; t: TEXT;
op: PaintOp.T := PaintOp.TransparentFg; READONLY dl := ARRAY OF Displacement{}); <* LL.sup < v *>
Paint the texttonto the screen ofv, starting at positionpt, using the fontfnt, the operationop, and the displacement listdl.
The arguments toPaintTextmust satisfy at least one of the following two conditions: the background operation is transparent; that is,op(p, 0) = pfor any pixelp,
or
the font is self-clearing (see below) anddlis empty.
If neither condition is true, the effect ofPaintTextis implementation-dependent, but is confined to the clipping rectangle.
TheScrnFontinterface defines the properties of fonts. Here we introduce names for the properties needed to explainPaintText. Iffis a font andchis a character, then
printWidth(ch, f) is the printing width of ch; that is, the amount to increment the reference point whenchis printed in fontf;
bits(ch, f)is the bitmap forchinf, which is positioned withch’s reference point at the origin;
height(ch, f)is the height ofchabove the baseline; that is, the number of rows of bits(ch, f)whose v-coordinate is at most zero; anddepth(ch, fnt)is the number of rows ofbits(ch, f)whosev-coordinate exceeds zero; ascent(f)anddescent(f)are the logical extent offabove and below the
baseline. Some characters may extend higher or lower. A font is self-clearing if
each character’sprintWidthequals the width of its bitmap and each character’s reference point is at the west boundary of its bitmap (or each character’s
printWidthequals the negative of the width of its bitmap and each character’s reference point is at the east boundary of its bitmap).
The call toPaintTextis equivalent to the following loop:
rp := pt; i := 0; LOOP
IF dl # NIL THEN
FOR j := 0 TO HIGH(dl^) DO
IF dl[j].index = i THEN INC(rp.h, dl[j].dh) END END
END;
IF i = Text.Length(t) THEN EXIT END;
PaintPixmap(v, clip, op, bits(t[i], fnt), rp); rp.h := rp.h + PrintWidth(t[i], fnt);
i := i + 1 END
The following two procedures are useful for computing the sizes of texts. Since fonts are screen-independent, they take theVBTwhose screentype is to be used:
PROCEDURE BoundingBox
(v: Leaf; txt: TEXT; fnt: Font.T): Rect.T; <* LL.sup < v *>
Return the bounding box of the texttxtif it were painted at the origin on the screen ofv.
More precisely, letrbe the smallest rectangle that contains the bounding boxes of the characters oftxtiftxtwere painted onvin the fontfntwithtxt’s reference point at the origin. ThenBoundingBoxreturns a rectangle with the same horizontal extent asr, but whose height and depth are the maximum height and depth of any character in the font.
PROCEDURE TextWidth
(v: Leaf; txt: TEXT; fnt: Font.T): INTEGER; <* LL.sup < v *>
Return the sum of the printing widths of the characters intxtin the fontfnt.
TextWidthreturns the displacement of the reference point that would occur ift
were painted onvin fontfnt. It may differ from the width ofBoundingBox(txt, fnt), since the printing width of the last character can be different from the width of its bounding box, and the reference point for the first character might not be at the left edge oftxt’s bounding box.