CDCSUtilImpl.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, December 12, 1985 2:19:57 pm PST
Last edited by: Christian Jacobi, December 1, 1986 6:59:31 pm PST
DIRECTORY
CD,
CDBasics,
CDCSUtil,
CDErrors,
CDOps,
CStitching,
D2Basic,
Rope;
CDCSUtilImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDErrors, CDOps, CStitching
EXPORTS CDCSUtil =
BEGIN OPEN CDCSUtil;
didStop: SIGNAL = CODE;
New: PUBLIC PROC [filledWith: REFNIL, data: REFNIL, stopFlag: REF BOOLNIL] RETURNS [plane: Tesselation] = {
plane ← CStitching.NewTesselation[data, stopFlag];
CStitching.ChangeRect[plane, CDBasics.universe, filledWith];
};
Dispose: PUBLIC PROC [basis: Tesselation] = {
IF basis#NIL THEN CStitching.ChangeRect[basis, CDBasics.universe];
};
StateRec: TYPE = RECORD [
scale: Scale,
lLa: ARRAY CD.Layer OF StateLayerList ← ALL[NIL]
];
StateLayerList: TYPE = LIST OF StateLayer ← NIL;
StateLayer: TYPE = RECORD [plane: Tesselation ← 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 [pr: CD.DrawRef, r: CD.Rect, l: CD.Layer] = {
state: REF StateRec ← NARROW[pr.devicePrivate];
IF state.lLa[l]#NIL THEN {
rect: CD.Rect =
IF state.scale.denom=1 THEN UndividedScaleCsFromCDRect[r, state.scale.off, state.scale.num]
ELSE ScaleCsFromCDRect[r, state.scale.off, state.scale.num, state.scale.denom];
FOR sl: StateLayerList ← state.lLa[l], sl.rest WHILE sl#NIL DO
CStitching.ChangeRect[plane: sl.first.plane, rect: CDBasics.Extend[rect, sl.first.delta], new: $covered]
ENDLOOP;
};
};
Make: PUBLIC PROC [what: CDWorld, layers: Layers, into: Tesselation←NIL] RETURNS [Tesselation] = {
cf: REF CD.ContextFilter ← NEW[CD.ContextFilter←ALL[FALSE]];
maxGrow: CD.Number ← 0;
pr: CD.DrawRef ← CD.CreateDrawRef[[
stopFlag: what.stopFlag,
design: what.design,
drawChild: what.drawChild,
drawContext: what.drawContext,
drawRect: MyDrawRect,
contextFilter: cf
]];
state: REF StateRec;
state ← NEW[StateRec←[scale: what.scale]];
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] ← TRUE;
state.lLa[l.first.source] ← CONS[sl, state.lLa[l.first.source]];
maxGrow ← MAX[maxGrow, l.first.growClip];
ENDLOOP;
pr.interestClip ← CDBasics.Extend[what.restrict, MAX[maxGrow, what.minGrowClip]];
IF what.ob#NIL THEN {
CD.DrawOb[pr, what.ob]; --first call is not through what.drawChild
}
ELSE CDOps.DrawDesign[what.design, pr];
RETURN [into];
};
BackRect: PUBLIC PROC [what: CDWorld, csRect: CStitching.Rect] RETURNS [CD.Rect] = {
n: INT = what.scale.num;
RETURN [[
x1: (csRect.x1*what.scale.denom)/n - what.scale.off.x,
x2: (csRect.x2*what.scale.denom+n-1)/n - what.scale.off.x,
y1: (csRect.y1*what.scale.denom)/n - what.scale.off.y,
y2: (csRect.y2*what.scale.denom+n-1)/n - what.scale.off.y
]];
};
ExtractErrors: PUBLIC PROC [what: CDWorld, x: Tesselation, msg: Rope.ROPE, owner: ATOMNIL, dispose: BOOLTRUE, remFirst: BOOLTRUE, except: REFNIL] RETURNS [num: INT𡤀] = {
InternalMsg: CStitching.TileProc = {
csr: CD.Rect ← tile.Area[];
IF x.stopFlag^ THEN SIGNAL didStop;
[] ← CDErrors.IncludeMessage[what.design, what.ob, BackRect[what, csr], msg, owner];
num ← num+1;
};
IF remFirst THEN {
CDErrors.RemoveMessages[what.design, what.ob, owner];
};
IF x#NIL THEN
CStitching.EnumerateArea[plane: x, rect: GoodScaleCsFromCDRect[what.restrict, what.scale.off, what.scale.num, what.scale.denom], eachTile: InternalMsg, data: what, skip: except ! didStop => CONTINUE];
CDOps.DoTheDelayedRedraws[what.design]; --helps debugging and backgrounders
IF dispose THEN Dispose[x];
};
Fill: PUBLIC PROC [x: Tesselation, into: Tesselation←NIL, except: REFNIL, dispose: BOOLFALSE] RETURNS [Tesselation] = {
IF into=NIL THEN into ← New[stopFlag: x.stopFlag];
IF ~x.stopFlag^ AND ~into.stopFlag^ THEN {
CStitching.EnumerateArea[plane: x, rect: CDBasics.universe, eachTile: InternalFillTTile, data: into, skip: except];
};
IF dispose THEN Dispose[x];
RETURN [into]
};
InternalFillTTile: CStitching.TileProc = {
CStitching.ChangeRect[plane: NARROW[data], rect: CStitching.Area[tile], new: $covered]
};
Rem: PUBLIC PROC [x: Tesselation, into: Tesselation←NIL, except: REFNIL, dispose: BOOLFALSE] RETURNS [Tesselation] = {
IF into=NIL THEN into ← New[filledWith: $covered, stopFlag: x.stopFlag];
IF ~x.stopFlag^ AND ~into.stopFlag^ THEN {
CStitching.EnumerateArea[plane: x, rect: CDBasics.universe, eachTile: InternalRemTTile, data: into, skip: except];
};
IF dispose THEN Dispose[x];
RETURN [into];
};
InternalRemTTile: CStitching.TileProc = {
CStitching.ChangeRect[plane: NARROW[data], rect: CStitching.Area[tile], new: NIL]
};
FillGrow: PUBLIC PROC [x: Tesselation, grow: INT𡤀, into: Tesselation←NIL, except: REFNIL, use: REF←$covered, dispose: BOOLFALSE] RETURNS [Tesselation] = {
InternalGrowTTile: CStitching.TileProc = {
r: CD.Rect ← CDBasics.Extend[CDBasics.Intersection[CDBasics.universe, CStitching.Area[tile]], grow];
CStitching.ChangeRect[plane: into, rect: r, new: use];
IF into.stopFlag^ THEN SIGNAL didStop;
};
IF into=NIL THEN into ← New[stopFlag: x.stopFlag];
IF ~x.stopFlag^ AND ~into.stopFlag^ THEN {
CStitching.EnumerateArea[plane: x, rect: CDBasics.universe, eachTile: InternalGrowTTile, data: NIL, skip: except ! didStop => CONTINUE];
};
IF dispose THEN Dispose[x];
RETURN [into];
};
Copy: PUBLIC PROC [x: Tesselation, into: Tesselation←NIL, dispose: BOOLFALSE] RETURNS [Tesselation] = {
IF into=NIL THEN into ← New[stopFlag: x.stopFlag];
IF ~x.stopFlag^ AND ~into.stopFlag^ THEN {
CStitching.EnumerateArea[plane: x, rect: CDBasics.universe, eachTile: InternalCopyTile, data: into];
};
IF dispose THEN Dispose[x];
RETURN [into]
};
InternalCopyTile: CStitching.TileProc = {
CStitching.ChangeRect[plane: NARROW[data], rect: CStitching.Area[tile], new: tile.value]
};
Not: PUBLIC PROC [x: Tesselation, dispose: BOOLFALSE] RETURNS [Tesselation] = {
RETURN [Rem[x: x, into: NIL, except: NIL, dispose: dispose]]
};
AndIn: PUBLIC PROC [x: Tesselation, into: Tesselation, dispose: BOOLFALSE] RETURNS [Tesselation] = {
RETURN [Rem[x: x, into: into, except: $covered, dispose: dispose]]
};
OrIn: PUBLIC PROC [x: Tesselation, into: Tesselation, dispose: BOOLFALSE] RETURNS [Tesselation] = {
RETURN [Fill[x: x, into: into, except: NIL, dispose: dispose]]
};
AndNotIn: PUBLIC PROC [x: Tesselation, into: Tesselation, dispose: BOOLFALSE] RETURNS [Tesselation] = {
RETURN [Rem[x: x, into: into, except: NIL, dispose: dispose]]
};
And: PUBLIC PROC [t1, t2, t3, t4: Tesselation←NIL] RETURNS [into: Tesselation] = {
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: Tesselation←NIL] RETURNS [into: Tesselation] = {
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: Tesselation] RETURNS [Tesselation] = {
--a AND (~n)
RETURN [AndNotIn[n, Copy[a]]];
};
Grow: PUBLIC PROC [x: Tesselation, amount: INT𡤀, dispose: BOOLFALSE] RETURNS [t: Tesselation] = {
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.