GGCircleCacheImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Created by: Ken Pier, August 14, 1986
Last Edited By: Ken Pier, August 19, 1986 3:53:47 pm PDT
Bier, February 11, 1987 11:03:26 pm PST
DIRECTORY
FunctionCache, GGBasicTypes, GGCircles, GGCircleCache, GGShapes, Imager, ImagerBackdoor, ImagerBitmapContext, ImagerSample, Real;
GGCircleCacheImpl: CEDAR PROGRAM
IMPORTS FunctionCache, GGCircles, GGShapes, Imager, ImagerBackdoor, ImagerBitmapContext, ImagerSample, Real
EXPORTS GGCircleCache = BEGIN
Bitmap: TYPE = Imager.SampleMap;
Cache: TYPE = FunctionCache.Cache;
CachedCircle: TYPE = REF CachedCircleObj;
CachedCircleObj: TYPE = GGCircleCache.CachedCircleObj;
Context: TYPE = Imager.Context;
Point: TYPE = GGBasicTypes.Point;
Range: TYPE = FunctionCache.Range;
alignmentColor: Imager.Color ← ImagerBackdoor.MakeStipple[145065B]; -- stolen from GGGravityImpl
Create: PUBLIC PROC [] RETURNS [Cache] = {
RETURN [FunctionCache.GlobalCache[] ];
};
Insert: PUBLIC PROC [x: Cache, radius: REAL] = {
IF Lookup[x, radius]#NIL OR radius NOT IN [1.0..512.0] THEN RETURN
ELSE {
context: Imager.Context;
argument: REF REALNEW[REAL ← radius];
circle: GGBasicTypes.Circle;
dummySize: NAT ← 0;
side: INT ← 2*(Real.Fix[radius+1.0]+1); -- round up and add 1
bitmap: Bitmap ← ImagerSample.NewSampleMap[[max: [side, side]]];
cachedCircle: CachedCircle ← NEW[CachedCircleObj ← [bitmap: bitmap, cw: side, ch: side]];
pixelmapRepRef: PixelMapRepRef ← NEW[PixelMapRep ← [
ref: bitmap.ref, pointer: bitmap.base, words: LONG[bitmap.wordsPerLine]*bitmap.height,
lgBitsPerPixel: 0, rast: bitmap.wordsPerLine, lines: bitmap.height
]];
pixelmapRef: PixelMapRef ← NEW[PixelMap ← [
sOrigin: 0, fOrigin: 0, sMin: 0, fMin: 0,
sSize: bitmap.height, fSize: bitmap.width, refRep: pixelmapRepRef
] ];
ImagerPixelMap.Clear[pixelmapRef^];
context ← ImagerBitmapContext.Create[[side, side], [down, right], [72.0, 72.0], TRUE];
ImagerBitmapContext.SetBitmap[context, bitmap];
context.SetColor[Imager.white];
context.MaskRectangle[ImagerBackdoor.GetBounds[context]];
context.SetColor[alignmentColor];
context.SetStrokeWidth[1.0];
circle ← GGCircles.CircleFromPointAndRadius[ [side/2, side/2], radius];
GGShapes.DrawCircle[dc: context, circle: circle ];
FunctionCache.Insert[x: x, argument: argument, value: pixelmapRef, size: pixelmapRepRef.words, clientID: $GGCircle];
FunctionCache.Insert[x: x, argument: argument, value: cachedCircle, size: ImagerSample.WordsForMap[[side, side], 1] + 2, clientID: $GGCircle];
};
};
Lookup: PUBLIC PROC [x: Cache, radius: REAL] RETURNS [CachedCircle] = {
Returns NIL if lookup fails
FindRadius: FunctionCache.CompareProc = {
arg: REALNARROW[argument, REF REAL]^;
RETURN [ABS[arg-radius] < 1.0E-3];
};
value: Range;
ok: BOOL;
[value, ok] ← FunctionCache.Lookup[x: x, compare: FindRadius, clientID: $GGCircle];
RETURN [IF ok THEN NARROW[value] ELSE NIL];
};
Remove: PUBLIC PROC [x: Cache, radius: REAL] = {
FindRadius: FunctionCache.CompareProc = {
arg: REALNARROW[argument, REF REAL]^;
RETURN [ABS[arg- radius] < 1.0E-3];
};
[] ← FunctionCache.Obtain[x: x, compare: FindRadius, limit: 1, clientID: $GGCircle];
};
RemoveAll: PUBLIC PROC [x: Cache] = {
list: LIST OF FunctionCache.CacheEntry ← FunctionCache.Obtain[x: x, compare: FunctionCache.Any, limit: LAST[INT], clientID: $GGCircle];
UNTIL list=NIL DO
list ← FunctionCache.Obtain[x: x, compare: FunctionCache.Any, limit: LAST[INT], clientID: $GGCircle];
ENDLOOP;
};
DrawCachedCircle: PUBLIC PROC [context: Context, point: Point, circle: CachedCircle] = {
DoDrawCachedCircle: PROC = {
context.SetColor[Imager.black];
Imager.MaskBitmap[context: context, base: circle.refRep.pointer, wordsPerLine: circle.refRep.rast, sMin: 0, fMin: 0, sSize: circle.sSize, fSize: circle.fSize, tx: Real.RoundI[point.x]-(circle.fSize/2), ty: Real.RoundI[point.y]+(circle.sSize/2)];
Imager.MaskBitmap[
context: context,
bitmap: circle.bitmap,
referencePoint: [circle.ch, 0],
position: [Real.Round[point.x]-(circle.cw/2),
Real.Round[point.y]-(circle.ch/2)]
];
};
Imager.DoSaveAll[context, DoDrawCachedCircle];
};
END.