DoItSmooth:
PROC[] ~ {
segPtr: ARRAY [0..5) OF LONG POINTER;
wdsPerLine: ARRAY [0..5) OF CARDINAL;
wrdPtr: ARRAY [0..5) OF LONG POINTER;
SetUpScanSeg:
PROC[yPosn:
NAT] ~
TRUSTED {
addOn: NAT ← IF alpha # NIL THEN 1 ELSE 0; -- make room for alpha buffer
FOR i:
NAT
IN [0 .. buf.pixels.length - addOn)
DO
wdsPerLine[i] ← buf.pixels[i].subMap.sampleMap.bitsPerLine / bitsPerWord;
segPtr[i] ← buf.pixels[i].subMap.sampleMap.base.word
+ Basics.LongMult[yPosn, wdsPerLine[i]];
ENDLOOP;
};
PutScanSeg:
PROC[ left, lftR, lftG, lftB, lftZ, right, rgtR, rgtG, rgtB, rgtZ:
INTEGER ] ~
TRUSTED {
doIt: BOOLEAN ← TRUE;
red, grn, blu, z: IncrementalDesc;
EvalDepth:
PROC[] ~
TRUSTED {
IF
LOOPHOLE[wrdPtr[depth^]^,
CARDINAL] >
CARDINAL[z.val]
THEN {
LOOPHOLE[wrdPtr[depth^]^,
CARDINAL] ← z.val;
doIt ← TRUE; }
ELSE doIt ← FALSE;
z ← UpdateIncr[z];
wrdPtr[depth^] ← wrdPtr[depth^] + 1;
};
IF left > right THEN [left, right] ← Swap[left, right];
red ← GetSlopeIncr[ [lftR, left], [rgtR, right] ];
grn ← GetSlopeIncr[ [lftG, left], [rgtG, right] ];
blu ← GetSlopeIncr[ [lftB, left], [rgtB, right] ];
IF depth #
NIL
THEN {
z ← GetSlopeIncr[ [lftZ, left], [rgtZ, right] ];
wrdPtr[depth^] ← segPtr[depth^] + left;
};
SELECT renderMode
FROM
$Dithered, $PseudoColor => {
wrdPtr[0] ← segPtr[0] + Basics.BITSHIFT[left,-1];
FOR x:
INTEGER
IN [left..right]
DO
value: INTEGER ← DitheredRGB[renderMode, x, yPosn, red.val, grn.val, blu.val];
IF depth # NIL THEN EvalDepth[]; -- sets/clears doIt based on depth
IF Basics.
BITAND[x,1] = 0
THEN { IF doIt THEN LOOPHOLE[wrdPtr[0]^, BytePair].high ← value; }
ELSE { IF doIt THEN LOOPHOLE[wrdPtr[0]^, BytePair].low ← value;
wrdPtr[0] ← wrdPtr[0] + 1; }; -- odd, low byte, incr. to next
red ← UpdateIncr[red]; grn ← UpdateIncr[grn]; blu ← UpdateIncr[blu];
ENDLOOP;
};
$Grey => {
wrdPtr[0] ← segPtr[0] + Basics.BITSHIFT[left,-1];
FOR x:
INTEGER
IN [left..right]
DO
IF depth # NIL THEN EvalDepth[]; -- sets/clears doIt based on depth
IF Basics.
BITAND[x,1] = 0
THEN { IF doIt THEN LOOPHOLE[wrdPtr[0]^, BytePair].high ← red.val; }
ELSE { IF doIt THEN LOOPHOLE[wrdPtr[0]^, BytePair].low ← red.val;
wrdPtr[0] ← wrdPtr[0] + 1; }; -- odd, low byte, incr. to next
red ← UpdateIncr[red];
ENDLOOP;
};
$FullColor, $Dorado24 => {
wrdPtr[0] ← segPtr[0] + left; wrdPtr[2] ← segPtr[2] + Basics.BITSHIFT[left,-1];
FOR x:
INTEGER
IN [left..right]
DO
IF depth # NIL THEN EvalDepth[]; -- sets/clears doIt based on depth
IF doIt THEN wrdPtr[0]^ ← Basics.BITSHIFT[red.val, 8] + grn.val;
wrdPtr[0] ← wrdPtr[0] + 1;
IF Basics.
BITAND[x,1] = 0
THEN { IF doIt THEN LOOPHOLE[wrdPtr[2]^, BytePair].high ← blu.val; }
ELSE { IF doIt THEN LOOPHOLE[wrdPtr[2]^, BytePair].low ← blu.val;
wrdPtr[2] ← wrdPtr[2] + 1; }; -- odd, low byte, incr. to next
red ← UpdateIncr[red]; grn ← UpdateIncr[grn]; blu ← UpdateIncr[blu];
ENDLOOP;
segPtr[2] ← segPtr[2] + wdsPerLine[2];
};
ENDCASE => SIGNAL ScanConvertError[$BadRenderMode];
IF depth # NIL THEN segPtr[depth^] ← segPtr[depth^] + wdsPerLine[depth^];
segPtr[0] ← segPtr[0] + wdsPerLine[0];
};
GetColor:
PROC[color:
REF RealSequence]
RETURNS[outClr: IntRGBZ] ~ {
SELECT color.length
FROM
1 => outClr ← [Real.RoundC[color[0]*255.0], 0, 0, 0 ];
2 => outClr ← [Real.RoundC[color[0]*255.0], 0, 0, Real.RoundC[color[1]*255.0] ];
3 => outClr ← [Real.RoundC[color[0]*255.0], Real.RoundC[color[1]*255.0],
Real.RoundC[color[2]*255.0], 0];
4 => outClr ← [Real.RoundC[color[0]*255.0], Real.RoundC[color[1]*255.0],
Real.RoundC[color[2]*255.0], Real.RoundC[color[3]] ];
ENDCASE => SIGNAL ScanConvertError[$BadLength];
};
yPosn: NAT; -- current scan line
left, lftR, lftG, lftB, lftZ, right, rgtR, rgtG, rgtB, rgtZ: IncrementalDesc; -- edge description
nxtLVtx, nxtRVtx, rVtx, lVtx, nxtRHeight, nxtLHeight: NAT ← 0;
clr, nxtClr: IntRGBZ;
bytePtr: LONG POINTER TO rawBytes;
IncrementalDesc: TYPE ~ RECORD[val, intInc, intSgn, fracInc, fracRng, fracPos: INTEGER];
nxtLVtx ← nxtRVtx ← rVtx ← lVtx ← firstVtx; -- set pointers to bottom vertex
yPosn ← nxtRHeight ← nxtLHeight ← lowest;
SetUpScanSeg[yPosn];
WHILE yPosn < highest
DO
-- work up through vertices
WHILE yPosn >= nxtLHeight
DO
-- next left vertex reached?
lVtx ← nxtLVtx; nxtLVtx ← (lVtx + plygn.length - 1) MOD plygn.length;
nxtLHeight ← plygn[nxtLVtx].y;
left ← GetSlopeIncr[
[plygn[lVtx].x, plygn[lVtx].y], [plygn[nxtLVtx].x, plygn[nxtLVtx].y] ];
clr ← GetColor[plygn[lVtx].val];
nxtClr ← GetColor[plygn[nxtLVtx].val];
lftR ← GetSlopeIncr[ [clr.r, plygn[lVtx].y], [nxtClr.r, plygn[nxtLVtx].y] ];
lftG ← GetSlopeIncr[ [clr.g, plygn[lVtx].y], [nxtClr.g, plygn[nxtLVtx].y] ];
lftB ← GetSlopeIncr[ [clr.b, plygn[lVtx].y], [nxtClr.b, plygn[nxtLVtx].y] ];
IF depth #
NIL
THEN
lftZ ← GetSlopeIncr[ [clr.z, plygn[lVtx].y], [nxtClr.z, plygn[nxtLVtx].y] ];
ENDLOOP;
WHILE yPosn >= nxtRHeight
DO
-- next right vertex reached?
rVtx ← nxtRVtx; nxtRVtx ← (rVtx + 1) MOD plygn.length;
nxtRHeight ← plygn[nxtRVtx].y;
right ← GetSlopeIncr[
[plygn[rVtx].x, plygn[rVtx].y], [plygn[nxtRVtx].x, plygn[nxtRVtx].y] ];
clr ← GetColor[plygn[rVtx].val];
nxtClr ← GetColor[plygn[nxtRVtx].val];
rgtR ← GetSlopeIncr[ [clr.r, plygn[rVtx].y], [nxtClr.r, plygn[nxtRVtx].y] ];
rgtG ← GetSlopeIncr[ [clr.g, plygn[rVtx].y], [nxtClr.g, plygn[nxtRVtx].y] ];
rgtB ← GetSlopeIncr[ [clr.b, plygn[rVtx].y], [nxtClr.b, plygn[nxtRVtx].y] ];
IF depth #
NIL
THEN
rgtZ ← GetSlopeIncr[ [clr.z, plygn[rVtx].y], [nxtClr.z, plygn[nxtRVtx].y] ];
ENDLOOP;
PutScanSeg[ left.val, lftR.val, lftG.val, lftB.val, lftZ.val,
right.val, rgtR.val, rgtG.val, rgtB.val, rgtZ.val ];
left ← UpdateIncr[left];
lftR ← UpdateIncr[lftR]; lftG ← UpdateIncr[lftG]; lftB ← UpdateIncr[lftB];
right ← UpdateIncr[right];
rgtR ← UpdateIncr[rgtR]; rgtG ← UpdateIncr[rgtG]; rgtB ← UpdateIncr[rgtB];
IF depth # NIL THEN { lftZ ← UpdateIncr[lftZ]; rgtZ ← UpdateIncr[rgtZ]; };
yPosn ← yPosn + 1; -- update scan line
ENDLOOP;
Write top segment (polygon includes all its edges)
IF yPosn > lowest
THEN PutScanSeg[ left.val, lftR.val, lftG.val, lftB.val, lftZ.val,
right.val, rgtR.val, rgtG.val, rgtB.val, rgtZ.val ];
};
Proc Body Starts Here!!!!