G3dEdgeBlt.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Frank Crow, April 20, 1989 2:05:11 pm PDT
A general-purpose Bresenham incrementer.
DIRECTORY Rope;
G3dEdgeBlt: CEDAR DEFINITIONS
~ BEGIN
Type Definitions
ROPE:   TYPE ~ Rope.ROPE;
EdgeDesc: TYPE ~ RECORD [
val:     INT32,    -- current value for incrementation, byte address or value
stepsLeft:    WORD ← 0,  -- number of increments remaining
length:    WORD ← 0,  -- total number of increments to make 
hiccups:    WORD ← 0,  -- number of offsets (hiccups) to make
lngthIncr:   INT16 ← 0, -- amount to increment by
hicIncr:    INT16 ← 0, -- amount to offset at hiccup
bias:     INT16 ← 0, -- change to # of increments to first offset (for wizards)
indirect:    BOOLTRUE, -- incrementing addresses if TRUE, else values
nextEdge:    CARD16 ← 0 -- next edge if part of a chain of edges (index in sequence)
];
EdgeSequence:  TYPE ~ RECORD [
length:      CARDINAL ← 0,
element:      SEQUENCE maxLength: CARDINAL OF EdgeDesc];
EdgeBltOptions: TYPE ~ RECORD [
includeStart:      BOOLTRUE,   -- include start point
includeEnd:      BOOLTRUE    -- include endpoint
];  
defaultOptions:  EdgeBltOptions ~ [TRUE, TRUE];
EdgeBltTable: TYPE ~ RECORD [
dst, src:      EdgeDesc,
options:      EdgeBltOptions ← defaultOptions
];
Error: SIGNAL [code: ATOM, reason: ROPE];
Basic Procedures
The fractional increment Dy/Dx must be added to y for every new position x. Whenever the fraction overflows, y is incremented, effectively subtracting 1 from the fraction. By removing the fractional part from y, we can instead increment by Dy until Dx is reached. To center the positions of the y-increments along x, the incrementation by Dy should be started at Dx/2. To further simplify, decrement by 2Dy and start at Dx, testing for < 0. In the following read Dx as longSize and Dy as shortSize.
Incr: PROC [edge: EdgeDesc, array: REF EdgeSequence ← NIL] RETURNS [EdgeDesc];
Increments EdgeDesc once unless runToHiccup is set.
Blt: PROC [ebt: EdgeBltTable];
END.