-- TAGraphicsHacksImpl.mesa
-- Rick Beach, June 30, 1982 10:15 pm
-- Maureen Stone October 22, 1982 3:01 pm
DIRECTORY
CGArea USING [Empty, Ref, Remove],
CGContext USING [Rep],
CGDevice USING [Ref, Rep],
CGMatrix USING [Make, Ref],
CGSource USING [Ref],
CGStorage USING [qZone],
Graphics USING [Box, Context, NewContext],
GraphicsBasic USING [Trap],
JaMFnsDefs USING [PushReal, Register],
TJaMGraphics USING [Painter],
JaMOps USING [defaultFrame],
Real,
TAGraphicsHacks,
TJaMGraphicsPrivate USING [EstablishNonViewerContext, ForgetNonViewerContext];
TAGraphicsHacksImpl: PROGRAM
IMPORTS CGArea, CGMatrix, CGStorage, Graphics, JaMFnsDefs, TJaMGraphics, JaMOps, TJaMGraphicsPrivate
EXPORTS GraphicsBasic, TAGraphicsHacks = {
-- convince the world that I know what is in these opaque types
DeviceObject: PUBLIC TYPE = CGDevice.Rep;
ContextObject: PUBLIC TYPE = CGContext.Rep;
-- a global bounds box
boundsBox: Graphics.Box;
nullBoundsBox: Graphics.Box = [Real.LargestNumber, Real.LargestNumber, -Real.LargestNumber, -Real.LargestNumber];
Data: TYPE = REF DataRep;
DataRep: TYPE = RECORD [
matrix: CGMatrix.Ref ← NIL -- base transformation matrix
];
dataZone: ZONE = CGStorage.qZone;
repZone: ZONE = CGStorage.qZone;
NewBoxerDevice: PUBLIC PROCEDURE RETURNS[CGDevice.Ref] = {
data: Data ← dataZone.NEW[DataRep];
data.matrix ← CGMatrix.Make[[1,0,0,1,0,0]];
boundsBox ← nullBoundsBox;
RETURN[repZone.NEW[CGDevice.Rep ← [
GetMatrix: GetMatrix, GetBounds: GetBounds, Show: BoxerShow,
GetRaster: BoxerGetRaster, data: data]]];
};
GetMatrix: SAFE PROC[self: CGDevice.Ref] RETURNS[CGMatrix.Ref] = TRUSTED {
data: Data ← NARROW[self.data];
RETURN[data.matrix];
};
GetBounds: SAFE PROC[self: CGDevice.Ref] RETURNS[Graphics.Box] = TRUSTED {
RETURN[[0.1, 0.1, 4000-.1, 4000-.1]]};
BoxerShow: SAFE PROC[self: CGDevice.Ref, area: CGArea.Ref, src: CGSource.Ref, map: CGMatrix.Ref] = TRUSTED {
-- extract the bounding box from the area and update the context bbox
UNTIL CGArea.Empty[area] DO
trap: GraphicsBasic.Trap ← CGArea.Remove[area];
{ OPEN boundsBox, trap;
xmin ← MIN[xmin, xbotL];
xmin ← MIN[xmin, xtopL];
ymin ← MIN[ymin, ybot];
xmax ← MAX[xmax, xbotR];
xmax ← MAX[xmax, xtopR];
ymax ← MAX[ymax, ytop]};
ENDLOOP;
};
BoxerGetRaster: SAFE PROC[self: CGDevice.Ref] RETURNS[LONG POINTER,CARDINAL] = TRUSTED {
-- no raster for this device (sic!)
RETURN[NIL,0];
};
JBeginBox: PROCEDURE[] = {
-- JaM callable procedure to begin bounding boxing
context: Graphics.Context ← Graphics.NewContext[NewBoxerDevice[]];
TJaMGraphicsPrivate.EstablishNonViewerContext[JaMOps.defaultFrame, context];
};
JEndBox: PROCEDURE[] = {
-- JaM callable procedure to return the bounding box
paint: PROC [context: Graphics.Context] = {box ← EndBox[context]};
box: Graphics.Box;
TJaMGraphics.Painter[paint];
TJaMGraphicsPrivate.ForgetNonViewerContext[JaMOps.defaultFrame];
JaMFnsDefs.PushReal[box.xmin];
JaMFnsDefs.PushReal[box.ymin];
JaMFnsDefs.PushReal[box.xmax];
JaMFnsDefs.PushReal[box.ymax];
};
EndBox: PUBLIC PROCEDURE[self: Graphics.Context] RETURNS[Graphics.Box] = {
-- reset the context device pointer and return the bounding box on the JaM stack
IF boundsBox=nullBoundsBox THEN RETURN[[0,0,0,0]]
ELSE RETURN[boundsBox] };
JaMFnsDefs.Register[".beginbox", JBeginBox];
JaMFnsDefs.Register[".endbox", JEndBox];
}.