NStripe.mesa
Last edited: December 17, 1980 2:46 PM
Last Edited by: McCreight, July 3, 1985 2:26:35 pm PDT
Note on units: This module assumes that input coordinates are in MEBES address units,
(0.5 micron) as required by rectangles. This was chosen (instead of 1/16 MEBES units as
required by abscissa components of parallelograms and trapezoids) since rectangle
is the common case.
DIRECTORY
Basics,
NStripeDefs,
PartitionDefs,
Real;
NStripe: CEDAR PROGRAM IMPORTS Basics, PartitionDefs, Real EXPORTS NStripeDefs =
BEGIN OPEN NStripeDefs;
Rect: TYPE = RECORD [x1, y1, x2, y2: INT];
OutOfBoundsNumber: PUBLIC ERROR = CODE;
half: REAL ← 0.5;
stripeHeight: CARDINAL = 256;
MaxX, MaxY: INT;
Round: PROCEDURE [x: REAL] RETURNS [INT] = INLINE
BEGIN RETURN[Real.Fix[x + half]]; END;
InitStripe: PUBLIC PROCEDURE [x: CARDINAL, y: CARDINAL] =
Set drawing limits in Mebes units
BEGIN MaxX ← x; MaxY ← y; END;
WriteRectangle: PUBLIC PROCEDURE [
Layer: PartitionDefs.layerNumber, Width, Height, X1, Y1: REAL] =
BEGIN
clipped: BOOL;
r: Rect;
stripe, stripeMax: PartitionDefs.stripeNumber;
stripeY: INT;
[clipped, r] ← RoundRect[X1, Y1, X1+Width, Y1+Height];
stripe ← Basics.LowHalf[r.y1/stripeHeight]; --number of lowest stripe
stripeMax ← Basics.LowHalf[r.y2/stripeHeight]; --number of highest stripe
stripeY ← INT[stripe]*INT[stripeHeight];
WHILE stripe <= stripeMax DO
WriteStripedRectangle[stripe, Layer,
[x1: r.x1, y1: MAX[r.y1-stripeY, 0], x2: r.x2, y2: MIN[stripeHeight, r.y2-stripeY]]];
stripe ← stripe+1;
stripeY ← stripeY+stripeHeight;
ENDLOOP;
IF clipped THEN ERROR OutOfBoundsNumber;
END;
RoundRect: PROC [x1, y1, x2, y2: REAL] RETURNS [clipped: BOOL, r: Rect] =
BEGIN
clipped ← FALSE;
IF ((r.x1 ← Round[x1]) < 0) THEN {r.x1 ← 0; clipped ← TRUE};
IF ((r.y1 ← Round[y1]) < 0) THEN {r.y1 ← 0; clipped ← TRUE};
IF ((r.x2 ← Round[x2]) > MaxX) THEN {r.x2 ← MaxX; clipped ← TRUE};
IF ((r.y2 ← Round[y2]) > MaxY) THEN {r.y2 ← MaxY; clipped ← TRUE};
END;
rectangle: REF Rectangle ← NEW[Rectangle];
WriteStripedRectangle: PROCEDURE [
Stripe: PartitionDefs.stripeNumber, Layer: PartitionDefs.layerNumber, r: Rect ] =
BEGIN
IF r.y1 < r.y2 AND r.x1 < r.x2 THEN
BEGIN
rectangle^ ← [
code: rectangleCode,
H: r.y2-r.y1,
W: r.x2-r.x1,
X1: r.x1,
Y1: r.y1];
TRUSTED {PartitionDefs.SendObjectToPartition[Stripe, Layer, [LOOPHOLE[rectangle], 0, Basics.bytesPerWord*SIZE[Rectangle]]]};
END;
END;
WriteTrapezoid: PUBLIC PROCEDURE [
Layer: PartitionDefs.layerNumber, Width, Height, X1, Y1, dX1, dX2: REAL] =
BEGIN
YMax: REAL ← Y1 + Height;
iY1: INT = Round[Y1];
iYMax: INT = Round[YMax];
StripeMin: PartitionDefs.stripeNumber ← Basics.LowHalf[iY1/stripeHeight]; --number of lowest stripe
StripeMax: PartitionDefs.stripeNumber ← Basics.LowHalf[iYMax/stripeHeight]; --number of highest stripe
StripeMinY: REAL = Real.Float[StripeMin]*Real.Float[stripeHeight];
IF Y1 < 0 OR iYMax > MaxY THEN ERROR OutOfBoundsNumber; --Xcheck in WriteStripedTrapezoid
IF StripeMin = StripeMax --check for simple common case
THEN
WriteStripedTrapezoid[
StripeMin, Layer, Width, Height, X1, Y1 - StripeMinY, dX1, dX2]
ELSE
BEGIN
X2: REAL ← X1 + Width; --the right end of the base
x1, y1, x2: REAL; --updated values of X1,Y1,X2
h: REAL; --the traversed height
Stripe: PartitionDefs.stripeNumber;
first fragment
y1 ← StripeMinY + stripeHeight;
h ← y1 - Y1;
WriteStripedTrapezoid[
StripeMin, Layer, Width, h, X1, Y1 - StripeMinY, dX1, dX2];
middle fragments
x1 ← X1 + dX1*h;
x2 ← X2 + dX2*h;
FOR Stripe IN (StripeMin..StripeMax) DO
WriteStripedTrapezoid[
Stripe, Layer, x2 - x1, stripeHeight, x1, 0, dX1, dX2];
y1 ← y1 + stripeHeight;
h ← y1 - Y1;
x1 ← X1 + dX1*h;
x2 ← X2 + dX2*h;
ENDLOOP;
last fragment
WriteStripedTrapezoid[
StripeMax, Layer, x2 - x1, YMax - y1, x1, 0, dX1, dX2];
END;
END;
WriteStripedTrapezoid: PROCEDURE [
Stripe: PartitionDefs.stripeNumber, Layer: PartitionDefs.layerNumber,
mWidth, Height, mX1, Y1, mdX1, mdX2: REAL] =
BEGIN
Width: REAL = mWidth*16; --Convert abscissa info to 1/16 address units
dX1: REAL = mdX1*16; --ditto
dX2: REAL = mdX2*16; --ditto
X1: REAL = mX1*16; --ditto
X2: REAL = X1 + Width; --X coord of right end of base
Y2: REAL = Y1 + Height; --Y coord of top
iX1, iY2, iWidth, idX1, idX2: INT;
ciHeight, ciY1: CARDINAL;
ciY1 ← Round[Y1];
iX1 ← Round[X1];
iWidth ← Round[X2] - iX1;
iY2 ← Round[Y2];
ciHeight ← iY2 - ciY1;
idX1 ← Round[X1 + dX1*Height] - iX1;
idX2 ← Round[X2 + dX2*Height] - (iX1 + iWidth);
IF idX1 = 0 AND idX2 = 0 THEN
BEGIN -- it's a rectangle
clipped: BOOL;
r: Rect;
[clipped, r] ← RoundRect[mX1, Y1, mX1+mWidth, Y1+Height];
WriteStripedRectangle[Stripe, Layer, r];
IF clipped THEN ERROR OutOfBoundsNumber;
END
ELSE
BEGIN -- it's a non-rectangle form of trapezoid
IF iX1 < 0 OR iX1 + idX1 < 0 OR iX1 + iWidth > MaxX*16
OR iX1 + iWidth + idX2 > MaxX*16 THEN ERROR OutOfBoundsNumber;
IF (iWidth = 0 AND idX1 = idX2) OR ciHeight = 0 THEN RETURN;
SELECT TRUE FROM
idX1 = idX2 =>
WriteStripedParallelogram[
Stripe, Layer, iWidth, ciHeight, iX1, ciY1, idX1];
idX2 = 0 =>
WriteStripedTrapezoid1[Stripe, Layer, iWidth, ciHeight, iX1, ciY1, idX1];
idX1 = 0 =>
WriteStripedTrapezoid2[Stripe, Layer, iWidth, ciHeight, iX1, ciY1, idX2];
ENDCASE =>
WriteStripedTrapezoid3[
Stripe, Layer, iWidth, ciHeight, iX1, ciY1, idX1, idX2];
END;
END;
Low: PROC [ i: INT ] RETURNS [ n: CARDINAL ] =
{RETURN[Basics.LowHalf[LOOPHOLE[i]]]};
High: PROC [ i: INT ] RETURNS [ n: [0..100B) ] =
BEGIN
hi: INTEGER;
TRUSTED {hi ← LOOPHOLE[Basics.HighHalf[i]]};
IF ~ (hi IN [-40B..40B) ) THEN ERROR;
RETURN[IF hi>=0 THEN hi ELSE hi+100B];
END;
quad: REF BasicQuadrilateral ← NEW[BasicQuadrilateral];
WriteStripedParallelogram: PROCEDURE [
Stripe: PartitionDefs.stripeNumber, Layer: PartitionDefs.layerNumber, Width: LONG CARDINAL,
Height: CARDINAL, X1: LONG CARDINAL, Y1: CARDINAL, dX: INT] =
TRUSTED BEGIN
quad^ ← [
code: parallelogramCode,
H: Height,
W: Low[Width],
X1: Low[X1],
Y1: Y1,
DX: Low[dX],
DXHigh: High[dX],
X1High: High[X1],
WHigh: High[Width]];
PartitionDefs.SendObjectToPartition[Stripe, Layer, [LOOPHOLE[quad], 0, Basics.bytesPerWord*SIZE[BasicQuadrilateral]]];
END;
WriteStripedTrapezoid1: PROCEDURE [
Stripe: PartitionDefs.stripeNumber, Layer: PartitionDefs.layerNumber, Width: LONG CARDINAL,
Height: CARDINAL, X1: LONG CARDINAL, Y1: CARDINAL, dX: INT] =
TRUSTED BEGIN
quad^ ← [
code: trapezoid1Code,
H: Height,
W: Low[Width],
X1: Low[X1],
Y1: Y1,
DX: Low[dX],
DXHigh: High[dX],
X1High: High[X1],
WHigh: High[Width]];
PartitionDefs.SendObjectToPartition[Stripe, Layer, [LOOPHOLE[quad], 0, Basics.bytesPerWord*SIZE[BasicQuadrilateral]]];
END;
WriteStripedTrapezoid2: PROCEDURE [
Stripe: PartitionDefs.stripeNumber, Layer: PartitionDefs.layerNumber, Width: LONG CARDINAL,
Height: CARDINAL, X1: LONG CARDINAL, Y1: CARDINAL, dX: INT] =
TRUSTED BEGIN
quad^ ← [
code: trapezoid2Code,
H: Height,
W: Low[Width],
X1: Low[X1],
Y1: Y1,
DX: Low[dX],
DXHigh: High[dX],
X1High: High[X1],
WHigh: High[Width]];
PartitionDefs.SendObjectToPartition[Stripe, Layer, [LOOPHOLE[quad], 0, Basics.bytesPerWord*SIZE[BasicQuadrilateral]]];
END;
trapezoid3: REF Trapezoid3 ← NEW[Trapezoid3];
WriteStripedTrapezoid3: PROCEDURE [
Stripe: PartitionDefs.stripeNumber, Layer: PartitionDefs.layerNumber, Width: LONG CARDINAL,
Height: CARDINAL, X1: LONG CARDINAL, Y1: CARDINAL, dX1: INT,
dX2: INT] =
TRUSTED BEGIN
trapezoid3^ ← [
code: trapezoid3Code,
H: Height,
W: Low[Width],
X1: Low[X1],
DX2High: High[dX2],
Y1: Y1,
DX1: Low[dX1],
DX2: Low[dX2],
DX1High: High[dX1],
X1High: High[X1],
WHigh: High[Width]];
PartitionDefs.SendObjectToPartition[Stripe, Layer, [LOOPHOLE[trapezoid3], 0, Basics.bytesPerWord*SIZE[Trapezoid3]]];
END;
END.