CDCSUtilImpl.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
Jacobi, December 12, 1985 2:19:57 pm PST
Jacobi, March 19, 1986 10:22:51 am 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] =
BEGIN
plane ← CStitching.NewTesselation[data, stopFlag];
CStitching.ChangeRect[plane, CDBasics.universe, filledWith];
END;
Dispose: PUBLIC PROC [basis: Tesselation] =
BEGIN
IF basis#NIL THEN CStitching.ChangeRect[basis, CDBasics.universe];
CStitching.FreeTesselation[basis, FALSE];
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: 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 [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
CStitching.ChangeRect[plane: sl.first.plane, rect: CDBasics.Extend[rect, sl.first.delta], new: $covered]
ENDLOOP;
};
END;
Make: PUBLIC PROC [what: CDWorld, layers: Layers, into: Tesselation←NIL] RETURNS [Tesselation] =
BEGIN
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,
interestClip: what.clip,
contextFilter: cf
]];
state: REF StateRec;
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] ← 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.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: Tesselation, msg: Rope.ROPE, owner: ATOMNIL, dispose: BOOLTRUE, remFirst: BOOLTRUE, except: REFNIL] RETURNS [num: INT𡤀] =
BEGIN
InternalMsg: CStitching.TileProc =
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
CStitching.EnumerateArea[plane: x, rect: GoodScaleCsFromCDRect[what.clip, what.off, what.scaleNum, what.scaleDenom], eachTile: InternalMsg, data: what, skip: except ! didStop => CONTINUE];
CDOps.DoTheDelayedRedraws[what.design]; --helps debugging and backgrounders
IF dispose THEN Dispose[x];
END;
Fill: PUBLIC PROC [x: Tesselation, into: Tesselation←NIL, except: REFNIL, dispose: BOOLFALSE] RETURNS [Tesselation] =
--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 {
CStitching.EnumerateArea[plane: x, rect: CDBasics.universe, eachTile: InternalFillTTile, data: into, skip: except];
};
IF dispose THEN Dispose[x];
RETURN [into]
END;
InternalFillTTile: CStitching.TileProc =
BEGIN
into: Tesselation ← NARROW[data];
CStitching.ChangeRect[plane: into, rect: CStitching.Area[tile], new: $covered]
END;
Rem: PUBLIC PROC [x: Tesselation, into: Tesselation←NIL, except: REFNIL, dispose: BOOLFALSE] RETURNS [Tesselation] =
--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 {
CStitching.EnumerateArea[plane: x, rect: CDBasics.universe, eachTile: InternalRemTTile, data: into, skip: except];
};
IF dispose THEN Dispose[x];
RETURN [into];
END;
InternalRemTTile: CStitching.TileProc =
BEGIN
into: CStitching.TesselationNARROW[data];
CStitching.ChangeRect[plane: into, rect: CStitching.Area[tile], new: NIL]
END;
FillGrow: PUBLIC PROC [x: Tesselation, grow: INT𡤀, into: Tesselation←NIL, except: REFNIL, use: REF←$covered, dispose: BOOLFALSE] RETURNS [Tesselation] =
--fills "into" with "use" except where "x" has "except"
--NIL "into" creates new tesselation filled with NIL
BEGIN
InternalGrowTTile: CStitching.TileProc =
BEGIN
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;
END;
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];
END;
Copy: PUBLIC PROC [x: Tesselation, into: Tesselation←NIL, dispose: BOOLFALSE] RETURNS [Tesselation] =
--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 {
CStitching.EnumerateArea[plane: x, rect: CDBasics.universe, eachTile: InternalCopyTile, data: into];
};
IF dispose THEN Dispose[x];
RETURN [into]
END;
InternalCopyTile: CStitching.TileProc =
BEGIN
into: CStitching.TesselationNARROW[data];
CStitching.ChangeRect[plane: into, rect: CStitching.Area[tile], new: tile.value]
END;
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.