<> <> <> <> DIRECTORY Atom, CD, CDBasics, CDBasicsInline, CDDefaultProcs, CDDirectory, CDProperties, D2Orient, Imager, ImagerManhattan, ImagerMaskCapture, ImagerTransformation, Real, Rope, TokenIO; CDDefaultProcsImpl: CEDAR PROGRAM IMPORTS Atom, CD, CDBasics, CDBasicsInline, CDDirectory, CDProperties, Imager, ImagerManhattan, ImagerMaskCapture, ImagerTransformation, Real EXPORTS CDDefaultProcs SHARES CD = BEGIN OPEN CD; <<--ObjectClass>> QuickDrawMe: PUBLIC PROC [pr: REF DrawInformation, ob: CD.Object, trans: Transformation, readOnlyInstProps: PropList] = { IF ob.class.drawMe#DrawMe THEN ob.class.drawMe[pr, ob, trans, readOnlyInstProps] ELSE { ob1: CD.Object = CDDirectory.Expand1[ob].new; IF ob1#NIL THEN ob1.class.quickDrawMe[pr, ob1, trans, readOnlyInstProps] ELSE pr.drawRect[pr, CDBasics.MapRect[ob.bbox, trans], CD.shadeLayer] } }; DrawMe: PUBLIC PROC [pr: REF DrawInformation, ob: CD.Object, trans: Transformation, readOnlyInstProps: PropList] = { IF ob.class.quickDrawMe#QuickDrawMe THEN ob.class.quickDrawMe[pr, ob, trans, readOnlyInstProps] ELSE { ob1: CD.Object = CDDirectory.Expand1[ob].new; IF ob1#NIL THEN ob1.class.drawMe[pr, ob1, trans, readOnlyInstProps] ELSE pr.drawRect[pr, CDBasics.MapRect[ob.bbox, trans], CD.shadeLayer] } }; ShowMeSelected: PUBLIC PROC [pr: REF DrawInformation, ob: CD.Object, trans: Transformation, readOnlyInstProps: PropList] = { pr.drawOutLine[pr, CDBasics.MapRect[CD.InterestRect[ob], trans], CD.selectionLayer] }; ShowMeSelectedWithExpand: PUBLIC PROC [pr: REF DrawInformation, ob: CD.Object, trans: Transformation, readOnlyInstProps: PropList] = { ob1: CD.Object = CDDirectory.Expand1[ob].new; IF ob1=NIL THEN pr.drawOutLine[pr, CDBasics.MapRect[CD.InterestRect[ob], trans], CD.selectionLayer] ELSE ob1.class.showMeSelected[pr, ob1, trans, readOnlyInstProps]; }; HitInside: PUBLIC PROC [ob: Object, hitRect: Rect] RETURNS [BOOL] = { RETURN [CDBasics.Intersect[CD.InterestRect[ob], hitRect] ] }; InterestRect: PUBLIC PROC [ob: Object] RETURNS [Rect] = { RETURN [ob.bbox] }; InterestRectWithExpand: PUBLIC PROC [ob: Object] RETURNS [Rect] = { ob1: CD.Object = CDDirectory.Expand1[ob].new; RETURN [(IF ob1#NIL THEN CD.InterestRect[ob1] ELSE ob.bbox)] }; InternalRead: PUBLIC PROC [h: TokenIO.Handle, key: ATOM] RETURNS [Object] = { ERROR }; Describe: PUBLIC PROC [ob: Object, readOnlyInstProps: PropList, verbosity: NAT] RETURNS [Rope.ROPE] = { RETURN [ IF ob.class.description=NIL THEN Atom.GetPName[ob.class.objectType] ELSE ob.class.description ]; }; <<--DrawProcs>> DrawChild: PUBLIC PROC [pr: REF DrawInformation, ob: CD.Object, trans: Transformation, readOnlyInstProps: PropList] = { ob.class.drawMe[pr, ob, trans, readOnlyInstProps] }; IgnoreChild: PUBLIC PROC [pr: REF DrawInformation, ob: CD.Object, trans: Transformation, readOnlyInstProps: PropList] = { }; DrawChildSel: PUBLIC PROC [pr: REF DrawInformation, ob: CD.Object, trans: Transformation, readOnlyInstProps: PropList] = { ob.class.showMeSelected[pr, ob, trans, readOnlyInstProps] }; DrawRect: PUBLIC PROC [pr: DrawRef, r: Rect, l: Layer] = { DrawRectInContext: PROC [context: Imager.Context, ob: CD.Object, layer: CD.Layer] = { Imager.MaskBox[context, [xmin: r.x1, xmax: r.x2, ymin: r.y1, ymax: r.y2]]; }; pr.drawContext[pr, DrawRectInContext, NIL, [[0, 0], original], l] }; IgnoreRect: PUBLIC PROC [pr: DrawRef, r: Rect, l: Layer] = { }; <> <> <> <> <> <> <> <> <<};>> <> <<}; >> <<>> ContextOutLine: PUBLIC PROC [pr: DrawRef, r: Rect, l: Layer] = { ActionWithContext: PROC [] = { Imager.SetColor[pr.deviceContext, pr.contextColors[l]]; Imager.MaskVector[pr.deviceContext, [r.x1, r.y1], [r.x2, r.y1]]; Imager.MaskVector[pr.deviceContext, [r.x2, r.y1], [r.x2, r.y2]]; Imager.MaskVector[pr.deviceContext, [r.x2, r.y2], [r.x1, r.y2]]; Imager.MaskVector[pr.deviceContext, [r.x1, r.y2], [r.x1, r.y1]]; }; IF pr.deviceContext#NIL THEN { IF pr.contextColors[l]#NIL THEN Imager.DoSave[pr.deviceContext, ActionWithContext] } }; DrawComment: PUBLIC PROC [pr: DrawRef, r: Rect, comment: Rope.ROPE] = { }; <<--version with bitmaps>> <<--uncomment carefully; is some releases old>> <> <<--calls proc which may use context; mode and color are set to layer's need>> <<--call is suppressed if layer does not need drawing; this is default.>> <<--on recursive calls, the context may or may not include previous transformations>> <<>> <> <> <> <> <<};>> <<>> <> <> <> <<};>> <> <> <> <<--but not clipping to an object size would kill us!!>> <> <<>> <> <> <<};>> <<>> <> <> <> <> <<};>> <<>> <> <> <> <> <> <<_ LOOPHOLE[bitmap.base, LONG POINTER TO CARDINAL]>> <<+ LONG[y]*bitmap.wordsPerLine>> <<+ LONG[x/Basics.bitsPerWord];>> <> <> <<}>> <> <> <<};>> <<>> <> <> <> <> <> <> <> <> <<};>> <<};>> <<};>> <<>> TransContext: PROC [cont: Imager.Context, trans: Transformation] = INLINE { Imager.TranslateT[cont, [trans.off.x, trans.off.y]]; IF CDBasics.IncludesMirrorX[trans.orient] THEN Imager.Scale2T[cont, [-1, 1]]; SELECT CDBasics.ConcentrateOnRotate90[trans.orient] FROM original => NULL; rotate90 => Imager.RotateT[cont, 90]; rotate180 => Imager.RotateT[cont, 180]; rotate270 => Imager.RotateT[cont, 270]; ENDCASE => ERROR; <<--or Imager.ConcatT[cont, CDBasicsInline.ImagerTransform[trans]]>> }; DrawContext: PUBLIC PROC [pr: DrawRef, proc: DrawContextLayerProc, ob: Object, trans: Transformation, layer: Layer] = { <<--calls proc which may use context; mode and color are set to layer's need>> <<--call is suppressed if layer does not need drawing; this is default.>> <<--on recursive calls, the context may or may not include previous transformations>> ActionWithContext: PROC [] = { TransContext[pr.deviceContext, trans]; Imager.SetColor[pr.deviceContext, pr.contextColors[layer]]; proc[pr.deviceContext, ob, layer]; }; IF pr.deviceContext#NIL THEN { IF pr.contextColors[layer]#NIL THEN Imager.DoSave[pr.deviceContext, ActionWithContext]; RETURN }; IF pr.contextFilter#NIL AND pr.contextFilter[layer] THEN { clip: CD.Rect _ CDBasics.DeMapRect[pr.interestClip, trans].itemInCell; --in object coordinates IF ob#NIL THEN clip _ CDBasics.Intersection[ob.bbox, clip]; IF CDBasics.NonEmpty[clip] THEN { Operator: PROC [context: Imager.Context] = { Imager.SetAmplifySpace[context, 1]; Imager.SetStrokeWidth[context, 1]; Imager.SetStrokeEnd[context, round]; Imager.SetStrokeJoint[context, round]; Imager.ClipRectangle[context, [x: clip.x1, y: clip.y1, w: clip.x2-clip.x1, h: clip.y2-clip.y1]]; proc[context, ob, layer ! ImagerMaskCapture.Cant => REJECT]; }; man: ImagerManhattan.Polygon; man _ ImagerMaskCapture.CaptureManhattan[Operator, CDBasics.ImagerTransform[[orient: rotate90]]]; <<--rotated so that mask capture will returned horizontal patches bottom up>> <<--instead of vertical patches. Using horizontal bands for corner stitching, and, >> <<--using corner stitchings maximal east west property, this gave an improvement >> <<--factor (in the one experimenmt I made) of about 50 (fifty!) >> FOR m: ImagerManhattan.Polygon _ man, m.rest UNTIL m=NIL DO r: CD.Rect _ CDBasics.MapRect[[x1: m.first.min.f, y1: -m.first.max.s, x2: m.first.max.f, y2: -m.first.min.s], trans]; <<--undo rotation! don't use >> <<--[x1: m.first.min.s, y1: m.first.min.f, x2: m.first.max.s, y2: m.first.max.f]>> r _ CDBasics.Intersection[r, pr.interestClip]; IF CDBasics.NonEmpty[r] THEN pr.drawRect[pr, r, layer]; ENDLOOP; ImagerManhattan.Destroy[man]; }; }; }; IgnoreGround: PUBLIC PROC [pr: DrawRef, pushedOut: BOOL] = { }; IgnorePriority: PUBLIC PROC [pr: DrawRef] = { }; DrawExtension: TYPE = RECORD [ dDrawRect: CD.DrawRectProc, dOrigin: CD.Position, scale: REAL ]; ExtendedDrawContext: PROC [pr: DrawRef, proc: DrawContextLayerProc, ob: Object, trans: Transformation, layer: Layer] = { <<--procedure not usefull in case pr.deviceContext#NIL>> IF pr.contextFilter#NIL AND pr.contextFilter[layer] THEN WITH CDProperties.GetPRefProp[pr.properties, $ExtendedDrawContext] SELECT FROM de: REF DrawExtension => { clip: CD.Rect _ CDBasics.DeMapRect[pr.interestClip, trans].itemInCell; --in ob coords IF ob#NIL THEN clip _ CDBasics.Intersection[ob.bbox, clip]; IF CDBasics.NonEmpty[clip] THEN { Operator: PROC [context: Imager.Context] = { Imager.SetAmplifySpace[context, 1]; Imager.SetStrokeWidth[context, 1]; Imager.SetStrokeEnd[context, round]; Imager.SetStrokeJoint[context, round]; Imager.ClipRectangle[context, [x: clip.x1, y: clip.y1, w: clip.x2-clip.x1, h: clip.y2-clip.y1]]; proc[context, ob, layer ! ImagerMaskCapture.Cant => REJECT]; }; t: CD.Transformation = [ off: [ Real.Round[de.scale*(trans.off.x-de.dOrigin.x)], Real.Round[de.scale*(trans.off.y-de.dOrigin.y)]], orient: trans.orient]; man: ImagerManhattan.Polygon; man _ ImagerMaskCapture.CaptureManhattan[Operator, ImagerTransformation.PreScale[CDBasics.ImagerTransform[[orient: rotate90]], de.scale]]; --rotation: see simple case why FOR m: ImagerManhattan.Polygon _ man, m.rest UNTIL m=NIL DO r: CD.Rect _ [x1: m.first.min.f, y1: -m.first.max.s, x2: m.first.max.f, y2: -m.first.min.s]; <<--undo rotation! don't use >> <<--[x1: m.first.min.s, y1: m.first.min.f, x2: m.first.max.s, y2: m.first.max.f]>> IF CDBasics.NonEmpty[r] THEN { <<--we do the translation on the rectangles instead in the Operator because>> <<--that would exceed the range where ImagerMaskCapture works correctly. >> de.dDrawRect[pr, CDBasicsInline.MapRect[r, t], layer]; } ENDLOOP; ImagerManhattan.Destroy[man]; }; }; ENDCASE => ERROR }; ConvertContextsToDeviceRects: PUBLIC PROC [pr: CD.DrawRef, dDrawRect: CD.DrawRectProc, dOrigin: CD.Position_[0, 0], scale: REAL_1] = { de: REF DrawExtension _ NEW[DrawExtension _ [ dDrawRect: dDrawRect, dOrigin: dOrigin, scale: scale ]]; IF pr.deviceContext#NIL THEN ERROR; CDProperties.PutPRefProp[pr.properties, $ExtendedDrawContext, de]; pr.drawContext _ ExtendedDrawContext }; <<>> END. <<>>