<> <> <> <<>> DIRECTORY FunctionCache, II USING [ClipRectangle, ClipRectangleI, Color, ColorOperator, ConcatT, Context, DoSave, DoSaveAll, DrawSampledColor, Error, MaskBitmap, MaskPixel, MaskRectangleI, Move, Object, PathProc, PixelArray, PixelMap, Rectangle, ROPE, SampleMap, ScanMode, SetColor, SetGray, SetXY, Trans, Transformation, VEC, XChar, XStringProc], IIBackdoor, IIMaskCapture, IIBox USING [Box, BoxFromRectangle, IntersectBox], IIFont USING [MapText], IIPixel USING [MakePixelMap], IIPixelArray USING [FromPixelMap], IIPrivate USING [Class, ClassRep], IISample, IIStroke USING [Dashes], IITransformation, Process USING [CheckForAbort], Real, SF USING [Box, SizeF, SizeS, Vec], Vector2; IIPrivateImpl: CEDAR PROGRAM IMPORTS FunctionCache, II, IIBackdoor, IIBox, IIFont, IIMaskCapture, IIPixel, IIPixelArray, IISample, IIStroke, IITransformation, Process, Real, SF, Vector2 EXPORTS IIPrivate, II ~ BEGIN OPEN II; Class: TYPE ~ IIPrivate.Class; ClassRep: PUBLIC TYPE ~ IIPrivate.ClassRep; -- export to II.ClassRep CoordSys: TYPE ~ IIBackdoor.CoordSys; Visibility: TYPE ~ IIBackdoor.Visibility; noViewOps: ROPE ~ "View operations not implemented for this context"; DefaultShowAndFixedXRel: PUBLIC PROC [context: Context, string: XStringProc, x: REAL] ~ { class: Class ~ context.class; first: BOOL _ TRUE; eachChar: PROC [char: XChar] ~ { thisChar: XStringProc ~ { charAction[char] }; IF first THEN first _ FALSE ELSE class.SetXYRel[context, [x, 0]]; class.Show[context: context, string: thisChar, xrel: FALSE]; }; string[eachChar]; }; DefaultShowText: PUBLIC PROC [context: Context, text: REF READONLY TEXT, start: NAT _ 0, len: NAT _ NAT.LAST, xrel: BOOL _ FALSE] ~ { class: Class ~ context.class; string: XStringProc ~ { IIFont.MapText[text, start, len, charAction] }; Process.CheckForAbort[]; class.Show[context, string, xrel]; }; DefaultMaskRectangleI: PUBLIC PROC [context: Context, x, y, w, h: INTEGER] ~ { class: Class ~ context.class; class.MaskRectangle[context, [x: x, y: y, w: w, h: h]]; }; <<>> DefaultMaskVector: PUBLIC PROC [context: Context, p1, p2: VEC] ~ { class: Class ~ context.class; vectorPath: PathProc ~ { moveTo[p1]; lineTo[p2] }; class.MaskStroke[context: context, path: vectorPath, closed: FALSE]; }; DefaultMaskDashedStroke: PUBLIC PROC [context: Context, path: PathProc, patternLen: NAT, pattern: PROC [NAT] RETURNS [REAL], offset, length: REAL] ~ { class: Class ~ context.class; dashedPath: PathProc ~ { IIStroke.Dashes[path: path, patternLen: patternLen, pattern: pattern, offset: offset, length: length, moveTo: moveTo, lineTo: lineTo, conicTo: conicTo, curveTo: curveTo] }; class.MaskStroke[context: context, path: dashedPath, closed: FALSE]; }; <<>> DefaultMaskBitmap: PUBLIC PROC [context: Context, bitmap: SampleMap, referencePoint: SF.Vec, scanMode: ScanMode, position: VEC] ~ { box: SF.Box ~ IISample.GetBox[bitmap]; pa: PixelArray ~ IIPixelArray.FromPixelMap[pixelMap: IIPixel.MakePixelMap[bitmap], box: box, scanMode: [slow: right, fast: up], immutable: FALSE]; IITransformation.ApplyPreTranslate[pa.m, position]; IITransformation.ApplySFToXY[pa.m, scanMode, 0, 0]; IITransformation.ApplyPreTranslate[pa.m, [box.min.s-referencePoint.s, box.min.f-referencePoint.f]]; MaskPixel[context, pa]; }; DefaultDrawBitmap: PUBLIC PROC [context: Context, bitmap: SampleMap, referencePoint: SF.Vec, scanMode: ScanMode, position: VEC] ~ { proc: PROC ~ { box: SF.Box ~ IISample.GetBox[bitmap]; m: Transformation _ IITransformation.Translate[position]; IITransformation.ApplySFToXY[m, scanMode, 0, 0]; IITransformation.ApplyPreTranslate[m, [-referencePoint.s, -referencePoint.f]]; ConcatT[context, m]; SetGray[context, 0]; MaskRectangleI[context: context, x: box.min.s, y: box.min.f, w: SF.SizeS[box], h: SF.SizeF[box]]; SetGray[context, 1]; MaskBitmap[context: context, bitmap: bitmap, referencePoint: [0, 0], scanMode: [slow: right, fast: up], position: [0, 0]]; }; DoSave[context, proc]; }; DefaultDrawPixels: PUBLIC PROC [context: Context, pixelMap: PixelMap, colorOperator: ColorOperator, referencePoint: SF.Vec, scanMode: ScanMode, position: VEC] ~ { pa: PixelArray ~ IIPixelArray.FromPixelMap[pixelMap: pixelMap, box: pixelMap.box, scanMode: [slow: right, fast: up], immutable: FALSE]; IITransformation.ApplySFToXY[pa.m, scanMode, 0, 0]; IITransformation.ApplyPreTranslate[pa.m, [pixelMap.box.min.s-referencePoint.s, pixelMap.box.min.f-referencePoint.f]]; DrawSampledColor[context: context, pa: pa, colorOperator: colorOperator, m: NIL, position: position]; }; DefaultViewReset: PUBLIC PROC [context: Context] ~ { Error[[$unimplemented, noViewOps]]; }; DefaultViewTranslateI: PUBLIC PROC [context: Context, x, y: INTEGER] ~ { Error[[$unimplemented, noViewOps]]; }; DefaultViewClip: PUBLIC PROC [context: Context, path: PathProc, oddWrap: BOOL, exclude: BOOL] ~ { Error[[$unimplemented, noViewOps]]; }; DefaultViewClipRectangleI: PUBLIC PROC [context: Context, x, y, w, h: INTEGER, exclude: BOOL] ~ { Error[[$unimplemented, noViewOps]]; }; DefaultGetTransformation: PUBLIC PROC [context: Context, from, to: CoordSys] RETURNS [Transformation] ~ { Error[[$unimplemented, noViewOps]]; }; DefaultTransform: PUBLIC PROC [context: Context, v: VEC, from, to: CoordSys, vec: BOOL] RETURNS [VEC] ~ { M: Transformation ~ IIBackdoor.GetTransformation[context: context, from: from, to: to]; vM: VEC ~ (IF vec THEN IITransformation.TransformVec ELSE IITransformation.Transform)[M, v]; IITransformation.Destroy[M]; RETURN [vM]; }; DefaultMoveViewRectangle: PUBLIC PROC [context: Context, width, height, fromX, fromY, toX, toY: INTEGER] ~ { Error[[$unimplemented, noViewOps]]; }; DefaultTestViewRectangle: PUBLIC PROC [context: Context, x, y, w, h: INTEGER] RETURNS [Visibility] ~ { RETURN [part] }; DefaultGetBounds: PUBLIC PROC [context: Context] RETURNS [Rectangle] ~ { Error[[$unimplemented, "GetBounds not implemented for this context"]]; }; DefaultDoIfVisible: PUBLIC PROC [context: Context, r: Rectangle, action: PROC] ~ { class: Class ~ context.class; br: Rectangle _ r; IF class.GetBounds # DefaultGetBounds THEN { br _ class.GetBounds[context ! Error => CONTINUE]; }; { bb: IIBox.Box ~ IIBox.BoxFromRectangle[br]; cb: IIBox.Box ~ IIBox.BoxFromRectangle[r]; ib: IIBox.Box ~ IIBox.IntersectBox[bb, cb]; IF ib.xmin < ib.xmax AND ib.ymin < ib.ymax THEN action[]; }; }; <<>> DefaultDoWithBuffer: PUBLIC PROC [context: Context, action: PROC, x, y, w, h: INTEGER, backgroundColor: Color _ NIL] ~ { paintBack: PROC ~ { SetColor[context, backgroundColor]; MaskRectangleI[context, x, y, w, h]; }; clippedAction: PROC ~ { ClipRectangleI[context, x, y, w, h]; IF backgroundColor # NIL THEN DoSave[context, paintBack]; action[]; }; DoSave[context, clippedAction]; }; DefaultDrawObject: PUBLIC PROC [context: Context, object: Object, position: VEC, interactive: BOOL] ~ { proc: PROC ~ { SetXY[context, position]; IF interactive THEN Trans[context] ELSE Move[context]; ClipRectangle[context, object.clip]; object.draw[object, context] }; DoSaveAll[context, proc]; }; objectCache: FunctionCache.Cache _ FunctionCache.Create[maxEntries: 30, maxTotalSize: 250000]; ObjectCacheData: TYPE ~ REF ObjectCacheDataRep; ObjectCacheDataRep: TYPE ~ RECORD [ object: Object, clientToDevice: Transformation, v: SELECT tag: * FROM notCached => [], bitmap => [bitmap: SampleMap], < [boxes: ManhattanPolygon],>> ENDCASE ]; maxBitsForCachedObject: REAL _ 2000000; RasterDrawObject: PUBLIC PROC [context: Context, object: Object, position: VEC, interactive: BOOL] ~ { contextBox: IIBox.Box ~ IIBox.BoxFromRectangle[IIBackdoor.GetBounds[context]]; objectRect: Rectangle ~ [x: position.x+object.clip.x, y: position.y+object.clip.y, w: object.clip.w, h: object.clip.h]; intersection: IIBox.Box ~ IIBox.IntersectBox[contextBox, IIBox.BoxFromRectangle[objectRect]]; IF intersection.xmax=intersection.xmin THEN RETURN; -- not visible IF interactive THEN { clientToDevice: Transformation ~ IIBackdoor.GetTransformation[context: context, from: client, to: device]; Compare: PROC [argument: REF] RETURNS [BOOL] ~ { key: ObjectCacheData ~ NARROW[argument]; IF object # key.object THEN RETURN [FALSE]; RETURN [IITransformation.CloseToTranslation[key.clientToDevice, clientToDevice]]; }; bounds: II.Rectangle ~ IITransformation.TransformRectangle[clientToDevice, objectRect]; IF ABS[bounds.w*bounds.h] <= maxBitsForCachedObject THEN { objectCacheData: ObjectCacheData _ NARROW [FunctionCache.Lookup[x: objectCache, compare: Compare, clientID: NIL].value]; IF objectCacheData = NIL THEN { bitmap: II.SampleMap _ NIL; size: INT _ 0; ok: BOOL _ TRUE; Op: PROC [c: Context] ~ { ClipRectangle[c, object.clip]; object.draw[object, c] }; bitmap _ IIMaskCapture.CaptureBitmap[Op, clientToDevice, TRUE ! IIMaskCapture.Cant => {ok _ FALSE; CONTINUE}]; IF ok THEN { o: REF ObjectCacheDataRep.bitmap _ NEW[ObjectCacheDataRep.bitmap]; objectCacheData _ o; o.bitmap _ bitmap; size _ IISample.WordsForMap[IISample.GetSize[bitmap]] + 10; } ELSE { objectCacheData _ NEW[ObjectCacheDataRep.notCached]; size _ SIZE[ObjectCacheDataRep.notCached]; }; objectCacheData.object _ object; objectCacheData.clientToDevice _ IITransformation.Copy[clientToDevice]; FunctionCache.Insert[x: objectCache, argument: objectCacheData, value: objectCacheData, size: size, clientID: NIL]; }; WITH objectCacheData SELECT FROM ocd: REF ObjectCacheDataRep.bitmap => { t1: VEC ~ IITransformation.TransformVec[clientToDevice, position]; t2: VEC ~ IITransformation.TransformVec[clientToDevice, [0, 0]]; t3: VEC ~ IITransformation.TransformVec[ocd.clientToDevice, [0, 0]]; t: VEC _ Vector2.Add[t1, Vector2.Sub[t2, t3]]; save: PROC ~ { m: Transformation ~ IIBackdoor.GetTransformation[context: context, from: device, to: view]; IIBackdoor.SetT[context, m]; MaskBitmap[context: context, bitmap: ocd.bitmap, scanMode: [slow: right, fast: up], position: t]; IITransformation.Destroy[m]; }; IF ABS[t.x]+ABS[t.x] < 100000 THEN {t.x _ Real.Round[t.x]; t.y _ Real.Round[t.y]}; -- try to make an integer transformation II.DoSave[context, save]; IITransformation.Destroy[clientToDevice]; RETURN; }; ENDCASE => NULL; }; IITransformation.Destroy[clientToDevice]; }; DefaultDrawObject[context, object, position, interactive]; }; END.