<> <> <> <> <<(0.5 micron) as required by rectangles. This was chosen (instead of 1/16 MEBES units as>> <> <> 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] = <> 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; <> y1 _ StripeMinY + stripeHeight; h _ y1 - Y1; WriteStripedTrapezoid[ StripeMin, Layer, Width, h, X1, Y1 - StripeMinY, dX1, dX2]; <> 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; <> 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.