--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.