<> <> <> <> DIRECTORY CD, CDBasics, CDCSUtil, CDErrors, CDOps, CornerStitching, D2Basic, Imager, Rope; CDCSUtilImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDErrors, CDOps, Imager, CornerStitching EXPORTS CDCSUtil = BEGIN OPEN CDCSUtil; didStop: SIGNAL = CODE; New: PUBLIC PROC [filledWith: REF_NIL, data: REF _ NIL, stopFlag: REF BOOL _ NIL] RETURNS [plane: Plane] = BEGIN plane _ CornerStitching.NewTesselation[data, stopFlag]; CornerStitching.ChangeRect[plane, CDBasics.universe, filledWith]; END; Dispose: PUBLIC PROC [basis: Plane] = BEGIN IF basis#NIL THEN CornerStitching.ChangeRect[basis, CDBasics.universe]; <> END; StateRec: TYPE = RECORD [ off: CD.Position _ [0, 0], scaleNum: INT _ 1, scaleDenom: INT _ 1, lLa: ARRAY CD.Layer OF StateLayerList _ ALL[NIL] ]; StateLayerList: TYPE = LIST OF StateLayer _ NIL; StateLayer: TYPE = RECORD [plane: Plane _ NIL, delta: INT _ 0]; UndividedScaleCsFromCDRect: PROC [r: CD.Rect, off: CD.Position, num: INT] RETURNS [rect: D2Basic.Rect] = INLINE { rect _ [ x1: (r.x1+off.x)*num, x2: (r.x2+off.x)*num, y1: (r.y1+off.y)*num, y2: (r.y2+off.y)*num ]; }; ScaleCsFromCDRect: PROC [r: CD.Rect, off: CD.Position, num: INT, denom: INT] RETURNS [rect: D2Basic.Rect] = INLINE { rect _ [ x1: (r.x1+off.x)*num/denom, x2: (r.x2+off.x)*num/denom, y1: (r.y1+off.y)*num/denom, y2: (r.y2+off.y)*num/denom ]; }; GoodScaleCsFromCDRect: PROC [r: CD.Rect, off: CD.Position, num: INT, denom: INT] RETURNS [rect: D2Basic.Rect] = INLINE { max: INT = LAST[INT]/num-1; range: PROC[n: INT] RETURNS [INT] = INLINE { RETURN [MIN[MAX[n, -max], max]] }; rect _ [ x1: range[r.x1+off.x]*num/denom, x2: range[r.x2+off.x]*num/denom, y1: range[r.y1+off.y]*num/denom, y2: range[r.y2+off.y]*num/denom ]; }; MyDrawRect: PROC [r: CD.Rect, l: CD.Layer, pr: CD.DrawRef] = BEGIN state: REF StateRec _ NARROW[pr.devicePrivate]; IF state.lLa[l]#NIL THEN { rect: CD.Rect = IF state.scaleDenom=1 THEN UndividedScaleCsFromCDRect[r, state.off, state.scaleNum] ELSE ScaleCsFromCDRect[r, state.off, state.scaleNum, state.scaleDenom]; FOR sl: StateLayerList _ state.lLa[l], sl.rest WHILE sl#NIL DO CornerStitching.ChangeRect[plane: sl.first.plane, rect: CDBasics.Extend[rect, sl.first.delta], newValue: $covered] ENDLOOP; }; END; Make: PUBLIC PROC [what: CDWorld, layers: Layers, into: Plane_NIL] RETURNS [Plane] = BEGIN cf: REF CD.ContextFilter _ NEW[CD.ContextFilter_ALL[NIL]]; maxGrow: CD.Number _ 0; pr: CD.DrawRef _ CD.CreateDrawRef[what.design]; state: REF StateRec; IF what.stopFlag=NIL THEN what.stopFlag_NEW[BOOL_FALSE]; IF what.drawChild#NIL THEN pr.drawChild _ what.drawChild; IF what.drawContext#NIL THEN pr.drawContext _ what.drawContext; pr.drawRect _ MyDrawRect; pr.stopFlag _ what.stopFlag; pr.interestClip _ what.clip; pr.contextFilter _ cf; state _ NEW[StateRec_[ off: what.off, scaleNum: what.scaleNum, scaleDenom: what.scaleDenom ]]; pr.devicePrivate _ state; IF into=NIL THEN into _ New[stopFlag: pr.stopFlag]; FOR l: Layers _ layers, l.rest WHILE l#NIL DO sl: StateLayer _ [ plane: IF l.first.plane=NIL THEN into ELSE l.first.plane, delta: l.first.deltaDiameter ]; cf[l.first.source] _ Imager.black; state.lLa[l.first.source] _ CONS[sl, state.lLa[l.first.source]]; maxGrow _ MAX[maxGrow, l.first.growClip]; ENDLOOP; pr.interestClip _ CDBasics.Extend[what.clip, MAX[maxGrow, what.minGrowClip]]; IF what.ob#NIL THEN { inst: CD.Instance _ NEW[CD.InstanceRep_[ob: what.ob]]; inst.ob.class.drawMe[inst, [0, 0], CD.original, pr]; --first call is not through what.drawChild } ELSE CDOps.DrawDesign[what.design, pr]; RETURN [into]; END; ExtractErrors: PUBLIC PROC [what: CDWorld, x: Plane, msg: Rope.ROPE, owner: ATOM_NIL, dispose: BOOL_TRUE, remFirst: BOOL_TRUE, except: REF_NIL] RETURNS [num: INT_0] = BEGIN InternalMsg: CornerStitching.PerTileProc = BEGIN csr: CD.Rect _ tile.Area[]; n: INT _ what.scaleNum; r: CD.Rect _ [ x1: (csr.x1*what.scaleDenom)/n - what.off.x, x2: (csr.x2*what.scaleDenom+n-1)/n - what.off.x, y1: (csr.y1*what.scaleDenom)/n - what.off.y, y2: (csr.y2*what.scaleDenom+n-1)/n - what.off.y ]; IF x.stopFlag^ THEN SIGNAL didStop; [] _ CDErrors.IncludeMessage[what.design, what.ob, r, msg, owner]; num _ num+1; END; IF remFirst THEN { CDErrors.RemoveMessages[what.design, what.ob, owner]; }; IF x#NIL THEN CornerStitching.EnumerateArea[plane: x, rect: GoodScaleCsFromCDRect[what.clip, what.off, what.scaleNum, what.scaleDenom], perTile: InternalMsg, data: what, skipValue: except ! didStop => CONTINUE]; CDOps.DoTheDelayedRedraws[what.design]; --helps debugging and backgrounders IF dispose THEN Dispose[x]; END; Fill: PUBLIC PROC [x: Plane, into: Plane_NIL, except: REF_NIL, dispose: BOOL_FALSE] RETURNS [Plane] = <<--fills "into" with $covered except where "x" has "except" >> <<--NIL "into" creates new tesselation filled with NIL >> BEGIN IF into=NIL THEN into _ New[stopFlag: x.stopFlag]; IF ~x.stopFlag^ AND ~into.stopFlag^ THEN { CornerStitching.EnumerateArea[plane: x, rect: CDBasics.universe, perTile: InternalFillTTile, data: into, skipValue: except]; }; IF dispose THEN Dispose[x]; RETURN [into] END; InternalFillTTile: CornerStitching.PerTileProc = BEGIN into: REF CornerStitching.Tesselation _ NARROW[data]; CornerStitching.ChangeRect[plane: into, rect: CornerStitching.Area[tile], newValue: $covered] END; <<>> Rem: PUBLIC PROC [x: Plane, into: Plane_NIL, except: REF_NIL, dispose: BOOL_FALSE] RETURNS [Plane] = <<--fills "into" with NIL except where "x" has "except" >> <<--NIL "into" creates new tesselation filled with $covered >> BEGIN IF into=NIL THEN into _ New[filledWith: $covered, stopFlag: x.stopFlag]; IF ~x.stopFlag^ AND ~into.stopFlag^ THEN { CornerStitching.EnumerateArea[plane: x, rect: CDBasics.universe, perTile: InternalRemTTile, data: into, skipValue: except]; }; IF dispose THEN Dispose[x]; RETURN [into]; END; InternalRemTTile: CornerStitching.PerTileProc = BEGIN into: REF CornerStitching.Tesselation _ NARROW[data]; CornerStitching.ChangeRect[plane: into, rect: CornerStitching.Area[tile], newValue: NIL] END; FillGrow: PUBLIC PROC [x: Plane, grow: INT_0, into: Plane_NIL, except: REF_NIL, use: REF_$covered, dispose: BOOL_FALSE] RETURNS [Plane] = <<--fills "into" with "use" except where "x" has "except" >> <<--NIL "into" creates new tesselation filled with NIL >> BEGIN InternalGrowTTile: CornerStitching.PerTileProc = BEGIN r: CD.Rect _ CDBasics.Extend[CDBasics.Intersection[CDBasics.universe, CornerStitching.Area[tile]], grow]; CornerStitching.ChangeRect[plane: into, rect: r, newValue: use]; IF into.stopFlag^ THEN SIGNAL didStop; END; IF into=NIL THEN into _ New[stopFlag: x.stopFlag]; IF ~x.stopFlag^ AND ~into.stopFlag^ THEN { CornerStitching.EnumerateArea[plane: x, rect: CDBasics.universe, perTile: InternalGrowTTile, data: NIL, skipValue: except ! didStop => CONTINUE]; }; IF dispose THEN Dispose[x]; RETURN [into]; END; <<>> Copy: PUBLIC PROC [x: Plane, into: Plane_NIL, dispose: BOOL_FALSE] RETURNS [Plane] = <<--simple copy operation >> <<--fills "into" with "x" except where "x" is NIL >> <<--NIL "into" creates new tesselation filled with NIL >> BEGIN IF into=NIL THEN into _ New[stopFlag: x.stopFlag]; IF ~x.stopFlag^ AND ~into.stopFlag^ THEN { CornerStitching.EnumerateArea[plane: x, rect: CDBasics.universe, perTile: InternalCopyTile, data: into]; }; IF dispose THEN Dispose[x]; RETURN [into] END; InternalCopyTile: CornerStitching.PerTileProc = BEGIN into: REF CornerStitching.Tesselation _ NARROW[data]; CornerStitching.ChangeRect[plane: into, rect: CornerStitching.Area[tile], newValue: tile.value] END; Not: PUBLIC PROC [x: Plane, dispose: BOOL_FALSE] RETURNS [Plane] = { RETURN [Rem[x: x, into: NIL, except: NIL, dispose: dispose]] }; AndIn: PUBLIC PROC [x: Plane, into: Plane, dispose: BOOL_FALSE] RETURNS [Plane] = { RETURN [Rem[x: x, into: into, except: $covered, dispose: dispose]] }; OrIn: PUBLIC PROC [x: Plane, into: Plane, dispose: BOOL_FALSE] RETURNS [Plane] = { RETURN [Fill[x: x, into: into, except: NIL, dispose: dispose]] }; AndNotIn: PUBLIC PROC [x: Plane, into: Plane, dispose: BOOL_FALSE] RETURNS [Plane] = { RETURN [Rem[x: x, into: into, except: NIL, dispose: dispose]] }; And: PUBLIC PROC [t1, t2, t3, t4: Plane_NIL] RETURNS [into: Plane] = { into _ Copy[t1]; IF t2#NIL THEN into _ AndIn[t2, into]; IF t3#NIL THEN into _ AndIn[t3, into]; IF t4#NIL THEN into _ AndIn[t4, into]; }; Or: PUBLIC PROC [t1, t2, t3, t4: Plane_NIL] RETURNS [into: Plane] = { into _ Copy[t1]; IF t2#NIL THEN into _ OrIn[t2, into]; IF t3#NIL THEN into _ OrIn[t3, into]; IF t4#NIL THEN into _ OrIn[t4, into]; }; AndNot: PUBLIC PROC [a, n: Plane] RETURNS [Plane] = { <<--a AND (~n)>> RETURN [AndNotIn[n, Copy[a]]]; }; Grow: PUBLIC PROC [x: Plane, amount: INT_0, dispose: BOOL_FALSE] RETURNS [t: Plane] = { RETURN [ IF amount>0 THEN FillGrow[x: x, grow: amount, into: New[stopFlag: x.stopFlag], except: NIL, use: $covered, dispose: dispose] ELSE IF amount<0 THEN FillGrow[x: x, grow: -amount, into: New[filledWith: $covered, stopFlag: x.stopFlag], except: $covered, use: NIL, dispose: dispose] ELSE Fill[x: x, into: New[stopFlag: x.stopFlag], except: NIL, dispose: dispose] ] }; END.