CDVScaleImpl.mesa
Copyright © 1983, 1984 by Xerox Corporation. All rights reserved.
by Christian Jacobi, August 5, 1983 11:07 am
redesigned by Christian Jacobi August 28, 1984 9:19:36 am PDT
last edited by Christian Jacobi September 4, 1985 6:43:24 pm PDT
DIRECTORY
CD, CDVScale;
CDVScaleImpl: CEDAR PROGRAM
IMPORTS CDVScale
EXPORTS CDVScale =
BEGIN
ScaleRange: TYPE = CDVScale.ScaleRange;
ScaleRec: TYPE = CDVScale.ScaleRec;
MakeScale: PUBLIC PROC [off: CD.Position←[0, 0], nscale: ScaleRange𡤄, grid: INTEGER←-1] RETURNS [s: ScaleRec] =
--given the grid, offset and nscale; makes a correctly gridded and initialized ScaleRec
BEGIN
--explanation of crazy scaling procedure for ScaleViewerToDesign
--v * scale + offset :: ideal
--v* s1/s2 + offset :: integer arithmetic
--(v*s1 + s2/2) / s2 + offset :: correct round of screen point
--( (v*s1 + s2/2) / s2) + grid/2) / grid * grid + offset :: introduce grid
--(v*s1 + s2/2 + grid/2*s2 ) / s2 / grid * grid + offset
--(v*s1 + s2/2 + grid/2*s2 ) / (s2*grid) * grid + offset
sE: INTEGER;
noDivisionScale: ScaleRange = 8;
scaleE: ARRAY ScaleRange OF INTEGER = --scale for factors
[24, 16, 12, 8, 6, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
scaleF: ARRAY ScaleRange OF INTEGER = --scale for divisors
[1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024];
scaleS: ARRAY ScaleRange OF NAT = --scale for shifts
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
s.nscale ← nscale; --MIN[MAX[nscale, 0], CDVScale.scaleNum-1];
s.grid ← MAX[1, grid];
sE ← scaleE[s.nscale];
s.sA ← scaleF[s.nscale];
s.sB ← (s.grid/2)*sE+sE/2;
s.sC ← sE*s.grid;
s.sD ← s.grid;
s.sS ← scaleS[s.nscale];
s.off.x ← off.x/s.grid*s.grid;
s.off.y ← off.y/s.grid*s.grid;
IF s.useMultiply ← s.nscale<noDivisionScale THEN {
s.xx ← sE;
s.designToViewerFactor ← sE;
}
ELSE {
s.xx ← s.sA;
s.designToViewerFactor ← 1.0/s.sA;
};
END;
GetClipRecord: PUBLIC PROC[scale: ScaleRec, highX, highY: CARDINAL]
RETURNS [CD.Rect] =
--given the index of the (high-most) pixel in the viewer, compute an outside clipping
--rectangle in design coordinates; (such that all outside the clipping area is invisible).
BEGIN
UnGridedScaleViewerToDesignUp: PROC [scale: ScaleRec, v: LONG CARDINAL] RETURNS [CD.Number] = INLINE {
sE: INTEGER = IF scale.useMultiply THEN scale.xx ELSE 1;
RETURN [LOOPHOLE[(v*scale.sA+sE+sE)/sE, CD.Number]]
};
RETURN [CD.Rect[
x1: CDVScale.ViewerToDesignScalar[scale, 0]+scale.off.x,
y1: CDVScale.ViewerToDesignScalar[scale, 0]+scale.off.y,
x2: UnGridedScaleViewerToDesignUp[scale, highX+1]+scale.off.x,
y2: UnGridedScaleViewerToDesignUp[scale, highY+1]+scale.off.y]
]
END;
END.