--TSSDFontImpl.mesa --sd font manager -- Michael Plass, June 24, 1982 3:27 pm DIRECTORY Rope USING[ROPE], TSBcplFontFile USING [SplineCommandPtr, SplineDataPtr, GetSplineCommands, OpenSDFontFile, CloseSDFontFile], IO USING[Error], Heap USING[MakeNode,FreeNode,systemZone], Real, TSSDFont; TSSDFontImpl: MONITOR IMPORTS TSBcplFontFile, Heap, IO, Real EXPORTS TSSDFont = BEGIN OPEN TSSDFont; -- First some copied routines for converting to bezier points. Vec: TYPE = RECORD [x,y: REAL]; VecAdd: PROC [a: Vec, b: Vec] RETURNS[Vec] = INLINE {RETURN[[a.x+b.x,a.y+b.y]]}; VecSub: PROC [a: Vec, b: Vec] RETURNS[Vec] = INLINE {RETURN[[a.x-b.x,a.y-b.y]]}; VecDiv: PROC [a: Vec, s: REAL] RETURNS[Vec] = INLINE {RETURN[[a.x/s,a.y/s]]}; Coeffs: TYPE = RECORD[c0,c1,c2,c3: Vec]; Bezier: TYPE = RECORD[b0,b1,b2,b3: Vec]; CoeffsToBezier: PROC [c: Coeffs] RETURNS[b: Bezier] = { OPEN b,c; b0_c0; b1_VecAdd[c0,VecDiv[c1,3]]; b2_VecAdd[b1,VecDiv[VecAdd[c1,c2],3]]; b3_VecAdd[VecAdd[VecAdd[c0,c1],c2],c3]; }; Load: PUBLIC ENTRY PROCEDURE [sdName: ROPE] RETURNS [fontSplines: FontSplines _ NIL] = { TSBcplFontFile.OpenSDFontFile[sdName ! IO.Error => GOTO Quit]; fontSplines _ NEW[FontSplinesRec[256]]; fontSplines.bc _ 0; FOR i: NAT IN [0..256) DO fontSplines[i] _ LoadSDChar[LOOPHOLE[i]]; ENDLOOP; TSBcplFontFile.CloseSDFontFile[]; EXITS Quit => {}; }; LoadSDChar: PROC [char: CHARACTER] RETURNS [charSplines: CharSplines] = { unit: REAL; pos: Vec _ [0,0]; largestDimension: REAL _ 1.0/(1.0+LAST[INT]); nextSlot: NAT _ 0; size: NAT _ 0; IncSize: PROC [d: NAT] = INLINE {size _ size + d}; TakeMax: PROC [t: REAL] = {largestDimension _ MAX[largestDimension, ABS[t]]}; ProduceMoveTo: PROC = {charSplines[nextSlot] _ moveToCode; nextSlot _ nextSlot + 1}; Produce: PROC [t: REAL] = {charSplines[nextSlot] _ Real.RoundI[t/unit]; nextSlot _ nextSlot + 1}; tscp,scp:TSBcplFontFile.SplineCommandPtr; splineDataPtr:TSBcplFontFile.SplineDataPtr; [splineDataPtr,scp]_TSBcplFontFile.GetSplineCommands[char, Allocate]; tscp_scp; UNTIL scp = NIL DO WITH scp SELECT FROM MoveTo => {TakeMax[x]; TakeMax[y]; IncSize[3]; pos _ [x,y]}; DrawTo => {TakeMax[x]; TakeMax[y]; IncSize[6]; pos _ [x,y]}; DrawCurve => { b: Bezier _ CoeffsToBezier[[c3:[x2,y2],c2:[x1,y1],c1:[x0,y0],c0:pos]]; TakeMax[b.b0.x]; TakeMax[b.b0.y]; TakeMax[b.b1.x]; TakeMax[b.b1.y]; TakeMax[b.b2.x]; TakeMax[b.b2.y]; TakeMax[b.b3.x]; TakeMax[b.b3.y]; IncSize[6]; pos _ b.b3; }; NewObject => NULL; EndDefinition => EXIT; ENDCASE; scp_scp.next; ENDLOOP; charSplines _ NEW[CharSplinesRec[size]]; charSplines.unit _ unit _ (largestDimension*1.125)/LAST[INTEGER]; scp_tscp; pos _ [0,0]; UNTIL scp = NIL DO WITH scp SELECT FROM MoveTo => { ProduceMoveTo[]; Produce[x]; Produce[y]; pos _ [x,y]; }; DrawTo => { Produce[(pos.x+pos.x+x)/3.0]; Produce[(pos.y+pos.y+y)/3.0]; Produce[(pos.x+x+x)/3.0]; Produce[(pos.y+y+y)/3.0]; Produce[x]; Produce[y]; pos _ [x,y]; }; DrawCurve => { b: Bezier _ CoeffsToBezier[[c3:[x2,y2],c2:[x1,y1],c1:[x0,y0],c0:pos]]; Produce[b.b1.x]; Produce[b.b1.y]; Produce[b.b2.x]; Produce[b.b2.y]; Produce[b.b3.x]; Produce[b.b3.y]; pos _ b.b3; }; NewObject => NULL; EndDefinition => EXIT; ENDCASE; scp_scp.next; ENDLOOP; scp_tscp; UNTIL (scp_tscp) = NIL DO tscp_scp.next; Heap.FreeNode[Heap.systemZone,scp]; ENDLOOP; }; Allocate: PROC[nwords: INTEGER] RETURNS[LONG POINTER] = {RETURN[Heap.MakeNode[Heap.systemZone,nwords]]}; END. -- Michael Plass, June 24, 1982 3:27 pm. Cedar 3.2 conversion.