RETURNS [
BOOLEAN, IntVec, IntVec] = {
Out: TYPE = RECORD[bottom, top, left, right: BOOLEAN];
noneOut: Out = [FALSE, FALSE, FALSE, FALSE];
Code:
PROC [x, y:
INTEGER]
RETURNS [Out] =
INLINE {
OPEN clipper;
out: Out ← noneOut;
IF x < xMin THEN out.left ← TRUE; IF x > xMax THEN out.right ← TRUE;
IF y > yMax THEN out.top ← TRUE; IF y < yMin THEN out.bottom ← TRUE;
RETURN [ out ];
};
ClipY:
PROC [a, b: IntVec, xPos:
INTEGER]
RETURNS [
INTEGER] =
INLINE {
t: Environment.LongNumber;
t.high ← LOOPHOLE[xPos - a.x]; t.low ← LOOPHOLE[0];
RETURN[ a.y +
LOOPHOLE[
Inline.HighHalf[ LOOPHOLE[t, LONG INTEGER] / (b.x - a.x) * (b.y - a.y)], INTEGER] ];
};
ClipX:
PROC [a, b: IntVec, yPos:
INTEGER]
RETURNS [
INTEGER] =
INLINE {
t: Environment.LongNumber;
t.high ← LOOPHOLE[yPos - a.y]; t.low ← LOOPHOLE[0];
RETURN[ a.x +
LOOPHOLE[
Inline.HighHalf[ LOOPHOLE[t, LONG INTEGER] / (b.y - a.y) * (b.x - a.x)], INTEGER] ];
};
aCode, bCode, out: Out;
c: IntVec;
WHILE
TRUE
DO
aCode ← Code[a.x, a.y]; bCode ← Code[b.x, b.y];
Trivial acceptance test
IF Inline.BITOR[LOOPHOLE[aCode], LOOPHOLE[bCode]] = LOOPHOLE[0]
THEN
RETURN[
TRUE, a, b];
Trivial rejection test
IF Inline.BITAND[LOOPHOLE[aCode], LOOPHOLE[bCode]] # LOOPHOLE[0]
THEN
RETURN[
FALSE, a, b];
Actual clipping necessary
out ← IF aCode # noneOut THEN aCode ELSE bCode;
SELECT TRUE FROM
out.left => { c.x ← clipper.xMin;
c.y ← ClipY[a, b, clipper.xMin]; };
out.right => { c.x ← clipper.xMax;
c.y ← ClipY[a, b, clipper.xMax]; };
out.bottom => { c.y ← clipper.yMin;
c.x ← ClipX[a, b, clipper.yMin]; };
out.top => { c.y ← clipper.yMax;
c.x ← ClipX[a, b, clipper.yMax]; }
ENDCASE;
IF aCode = out THEN a ← c ELSE b ← c;
ENDLOOP;
ERROR; -- can't get here, supposedly
};