PressFontReaderJaM:
CEDAR PROGRAM
IMPORTS AIS, GraphicsOps, CGScreen, JaM, PressFontReader, Real, Rope, TJaMGraphics, TJaMGraphicsContexts
= BEGIN
ROPE: TYPE = Rope.ROPE;
Frame: TYPE = JaM.State;
fontFile: PressFontReader.Handle;
font: PressFontReader.Font;
OpenFontFile:
PROCEDURE [f: Frame] = {
fileName: ROPE ← JaM.PopRope[f];
IF fontFile # NIL THEN fontFile.Close[];
fontFile ← PressFontReader.FromFile[fileName];
font ← fontFile.FirstFont[];
};
CloseFontFile:
PROCEDURE [f: Frame] = {
IF fontFile # NIL THEN fontFile.Close[];
fontFile ← NIL;
};
flushPathObject: Rope.ROPE ← ".flushpath";
moveToObject: Rope.ROPE ← ".movetonext";
lineToObject: Rope.ROPE ← ".lineto";
curveToObject: Rope.ROPE ← ".curveto";
drawAreaObject: Rope.ROPE ← ".draweoarea";
bboxObject: Rope.ROPE ← ".bbox";
widthObject: Rope.ROPE ← ".width";
translateObject: Rope.ROPE ← ".translate";
ExecuteRope:
PROC [f: Frame, r: Rope.
ROPE] = {
JaM.ExecuteRope[f, r! JaM.Stop => CONTINUE]};
DrawSplineChar:
PROCEDURE [f: Frame]= {
moveToProc: PressFontReader.MoveToProc = {
JaM.PushReal[f, x];
JaM.PushReal[f, y];
ExecuteRope[f, moveToObject];
};
lineToProc: PressFontReader.LineToProc = {
JaM.PushReal[f, x];
JaM.PushReal[f, y];
ExecuteRope[f, lineToObject];
};
curveToProc: PressFontReader.CurveToProc = {
JaM.PushReal[f, x1];
JaM.PushReal[f, y1];
JaM.PushReal[f, x2];
JaM.PushReal[f, y2];
JaM.PushReal[f, x3];
JaM.PushReal[f, y3];
ExecuteRope[f, curveToObject];
};
drawAreaProc: PressFontReader.DrawAreaProc = {
ExecuteRope[f, drawAreaObject];
};
char: CHAR← 0C+JaM.PopInt[f];
info: PressFontReader.CharInfo ← PressFontReader.GetCharInfo[font, char];
JaM.PushReal[f, info.widthX];
JaM.PushReal[f, info.widthY];
ExecuteRope[f, widthObject];
JaM.PushReal[f, info.minX];
JaM.PushReal[f, info.minY];
JaM.PushReal[f, info.maxX];
JaM.PushReal[f, info.maxY];
ExecuteRope[f, bboxObject];
ExecuteRope[f, flushPathObject];
PressFontReader.GetCharOutline[font, char, moveToProc, lineToProc, curveToProc, drawAreaProc];
JaM.PushReal[f, info.widthX];
JaM.PushReal[f, info.widthY];
ExecuteRope[f, translateObject];
};
DrawRasterChars:
PROCEDURE [f: Frame]= {
Paint:
PROCEDURE [context: Graphics.Context] = {
FOR i: NAT
IN [0..rope.Length[])
DO
PressFontReader.DrawCharRaster[context, font, rope.Fetch[i]];
ENDLOOP
};
rope: ROPE ← PopRope[f];
TJaMGraphics.Painter[Paint];
};
DrawChars:
PROCEDURE [f: Frame] = {
Paint:
PROCEDURE [context: Graphics.Context] = {
FOR i: NAT
IN [0..rope.Length[])
DO
PressFontReader.DrawChar[context, font, rope.Fetch[i]];
ENDLOOP
};
rope: ROPE ← PopRope[f];
TJaMGraphics.Painter[Paint];
};
CharDimensions:
PROCEDURE [f: Frame]= {
char: CHAR ← 0C+JaM.PopInt[f];
info: PressFontReader.CharInfo ← PressFontReader.GetCharInfo[font, char];
JaM.PushReal[f, info.widthX];
JaM.PushReal[f, info.widthY];
JaM.PushReal[f, info.minX];
JaM.PushReal[f, info.minY];
JaM.PushReal[f, info.maxX];
JaM.PushReal[f, info.maxY];
};
AllocateBitmap:
PROCEDURE [f: Frame] = {
-- allocates a bitmap large enough to use for the current raster font.
minX, minY, maxX, maxY: REAL ← 0;
scale: REAL ← (font.info.size*font.info.xRes)/0.0254;
height, width: NAT;
FOR char:
CHAR
IN [font.info.bc..font.info.ec]
DO
info: PressFontReader.CharInfo ← PressFontReader.GetCharInfo[font, char];
minX ← MIN[minX, info.minX];
minY ← MIN[minY, info.minY];
maxX ← MAX[maxX, info.maxX];
maxY ← MAX[maxY, info.maxY];
ENDLOOP;
height ← Real.RoundI[(maxY-minY)*scale] + 3;
width ← Real.RoundI[(maxX-minX)*scale] + 3;
orgX ← Real.RoundI[-minX*scale] + 1;
orgY ← Real.RoundI[-minY*scale] + 1;
bitmap ← GraphicsOps.NewBitmap[width, height];
bitmapDescriptor ← DescriptorFor[bitmap];
};
DrawBitmap:
PROCEDURE [f: Frame] = {
Paint:
PROCEDURE [context: Graphics.Context] = {
GraphicsOps.DrawBitmap[self: context, bitmap: bitmap, w: bitmap.width, h: bitmap.height, x: 0, y: 0, xorigin: 0, yorigin: bitmap.height];
};
TJaMGraphics.Painter[Paint];
};
BitMapContext:
PROCEDURE
RETURNS[Graphics.Context] = {
bitmapContext ← GraphicsOps.NewContextFromBitmap[bitmap];
RETURN [bitmapContext];
};
UseBitmap:
PROCEDURE [f: Frame] = {
TJaMGraphicsContexts.AddContext[f, BitMapContext, $PressFontReaderJaM, TRUE, TRUE];
TJaMGraphicsContexts.DisableViewer[f];
};
UseScreen:
PROCEDURE [f: Frame] = {
TJaMGraphicsContexts.DisableContext[f, $PressFontReaderJaM];
TJaMGraphicsContexts.EnableViewer[f];
};
GetBit:
PROCEDURE [f: Frame] = {
i, j: NAT;
j ← JaM.PopInt[f];
i ← JaM.PopInt[f];
JaM.PushInt[f, bitmapDescriptor[i][j]];
};
StoreBit:
PROCEDURE [f: Frame] = {
i, j: NAT;
j ← JaM.PopInt[f];
i ← JaM.PopInt[f];
bitmapDescriptor[i][j] ← JaM.PopInt[f];
};
BitmapOrigin:
PROCEDURE [f: Frame] = {
JaM.PushInt[f, orgX];
JaM.PushInt[f, orgY];
};
BitmapSize:
PROCEDURE [f: Frame] = {
JaM.PushInt[f, bitmap.width];
JaM.PushInt[f, bitmap.height];
};
orgX, orgY: NAT ← 0;
bitmap: GraphicsOps.BitmapRef;
bitmapDescriptor: BitmapDescriptor;
bitmapContext: Graphics.Context;
BitmapDescriptor: PUBLIC TYPE = REF READONLY BitmapDescriptorRec;
BitmapDescriptorRec:
PUBLIC
TYPE =
RECORD[
bitmapRef: GraphicsOps.BitmapRef,
lines: SEQUENCE height: NAT OF LONG DESCRIPTOR FOR PACKED ARRAY OF [0..1]
];
DescriptorFor:
PUBLIC
PROCEDURE [bitmap: GraphicsOps.BitmapRef]
RETURNS [BitmapDescriptor] = {
bitmapDescriptor: REF BitmapDescriptorRec ← NEW[BitmapDescriptorRec[bitmap.height]];
raster: NAT ← bitmap.raster;
p: LONG POINTER ← LOOPHOLE[bitmap.base];
IF p=NIL THEN [base: p, raster: raster] ← CGScreen.Bits[];
FOR i:
NAT
IN [0..bitmap.height)
DO
bitmapDescriptor[i] ← DESCRIPTOR[p, bitmap.width];
p ← p + raster;
ENDLOOP;
bitmapDescriptor.bitmapRef ← bitmap;
RETURN[bitmapDescriptor];
};
DescBase:
PUBLIC
PROCEDURE [d:
LONG
DESCRIPTOR
FOR
PACKED
ARRAY
OF [0..1]]
RETURNS [LONG POINTER] = {RETURN[BASE[d]]};
DescLength:
PUBLIC
PROCEDURE [d:
LONG
DESCRIPTOR
FOR
PACKED
ARRAY
OF [0..1]]
RETURNS [INT] = {RETURN[LENGTH[d]]};
WriteAISTemp:
PROCEDURE [f: Frame] = {
aisFile: AIS.FRef;
aisWindow: AIS.WRef;
raster: AIS.RasterPart;
raster.scanCount ← bitmap.height;
raster.scanLength ← bitmap.width;
raster.scanMode ← rd;
raster.bitsPerPixel ← 1;
raster.linesPerBlock ← -1;
raster.paddingPerBlock ← 0;
aisFile ← AIS.CreateFile[name: "AISTemp.ais", raster: @raster, overwrite: TRUE];
aisWindow ← AIS.OpenWindow[aisFile];
FOR i: NAT IN [0..bitmap.height)
DO
FOR j: NAT
IN [0..bitmap.width)
DO
AIS.WriteSample[aisWindow, 1-bitmapDescriptor[i][j], i, j];
ENDLOOP
ENDLOOP;
AIS.CloseWindow[aisWindow];
AIS.CloseFile[aisFile];
};
Init: JaM.InitProc = {
JaM.Register[State, "PressFont.Open", OpenFontFile];
JaM.Register[State, "PressFont.Close", CloseFontFile];
JaM.Register[State, "PressFont.DrawSplineChar", DrawSplineChar];
JaM.Register[State, "PressFont.DrawRasterChars", DrawRasterChars];
JaM.Register[State, "PressFont.DrawChars", DrawChars];
JaM.Register[State, "PressFont.CharDimensions", CharDimensions];
JaM.Register[State, "PressFont.AllocateBitmap", AllocateBitmap];
JaM.Register[State, "PressFont.DrawBitmap", DrawBitmap];
JaM.Register[State, "PressFont.GetBit", GetBit];
JaM.Register[State, "PressFont.StoreBit", StoreBit];
JaM.Register[State, "PressFont.UseBitmap", UseBitmap];
JaM.Register[State, "PressFont.UseScreen", UseScreen];
JaM.Register[State, "PressFont.WriteAISTemp", WriteAISTemp];
JaM.Register[State, "PressFont.BitmapOrigin", BitmapOrigin];
JaM.Register[State, "PressFont.BitmapSize", BitmapSize];
};
JaM.RegisterInit["PressFontReaderJaM",Init];
END.