DIRECTORY Basics USING [ BITSHIFT, BytePair, DoubleAnd, DoubleShiftRight, LongNumber ], EdgeBlt USING [ EdgeBltTable, EdgeBltOptions, EdgeDesc,EdgeSequence, ErrorDesc ]; EdgeBltImpl: CEDAR PROGRAM IMPORTS Basics EXPORTS EdgeBlt ~ BEGIN LongNumber: TYPE ~ Basics.LongNumber; BytePair: TYPE ~ Basics.BytePair; EdgeDesc: TYPE ~ EdgeBlt.EdgeDesc; EdgeSequence: TYPE ~ EdgeBlt.EdgeSequence; EdgeBltTable: TYPE ~ EdgeBlt.EdgeBltTable; EdgeBltOptions: TYPE ~ EdgeBlt.EdgeBltOptions; EdgeBltError: PUBLIC SIGNAL [reason: EdgeBlt.ErrorDesc] = CODE; longZero: LongNumber ~ [lc[0]]; longOne: LongNumber ~ [lc[1]]; Incr: PUBLIC PROC[edge: EdgeDesc, array: REF EdgeSequence _ NIL] RETURNS[EdgeDesc] ~ { edge.val _ edge.val + edge.lngthIncr; edge.bias _ edge.bias - 2*edge.hiccups; IF edge.bias <= 0 THEN { edge.val _ edge.val + edge.hicIncr; edge.bias _ edge.bias + 2*edge.length; }; edge.stepsLeft _ edge.stepsLeft - 1; IF edge.stepsLeft <= 0 -- Get next linked edge if this one exhausted THEN IF edge.nextEdge # 0 THEN edge _ array[edge.nextEdge]; RETURN[edge]; }; InlineIncr: PROC[edge: EdgeDesc, array: REF EdgeSequence _ NIL] RETURNS[EdgeDesc] ~ INLINE { edge.val _ edge.val + edge.lngthIncr; edge.bias _ edge.bias - 2*edge.hiccups; IF edge.bias <= 0 THEN { edge.val _ edge.val + edge.hicIncr; edge.bias _ edge.bias + 2*edge.length; }; edge.stepsLeft _ edge.stepsLeft - 1; IF edge.stepsLeft <= 0 -- Get next linked edge if this one exhausted THEN IF edge.nextEdge # 0 THEN edge _ array[edge.nextEdge]; RETURN[edge]; }; Blt: PUBLIC PROC[ebt: EdgeBltTable] ~ { DoByte: PROC[] ~ INLINE { dstAddr: LONG POINTER _ LOOPHOLE[Basics.DoubleShiftRight[LOOPHOLE[dst.val], 1]]; srcValue: BYTE; IF src.indirect THEN TRUSTED { -- get lo byte of word srcAddr: LONG POINTER _ LOOPHOLE[Basics.DoubleShiftRight[LOOPHOLE[src.val], 1]]; srcValue _ LOOPHOLE[srcAddr^, BytePair].low } ELSE srcValue _ LOOPHOLE[src.val, LongNumber.bytes].ll; -- lo byte, lo half of long IF Basics.DoubleAnd[LOOPHOLE[dst.val], longOne] # longZero -- lo byte? (right pixel) THEN TRUSTED { LOOPHOLE[dstAddr^, BytePair].low _ srcValue; } -- right pixel ELSE TRUSTED { LOOPHOLE[dstAddr^, BytePair].high _ srcValue; }; -- left pixel }; dst: EdgeDesc _ ebt.dst; src: EdgeDesc _ ebt.src; options: EdgeBltOptions _ ebt.options; IF NOT dst.indirect THEN EdgeBltError[[$Fatal, "Destination value must be address"]]; dst.bias _ dst.bias + dst.length; -- initial bias to center hiccups src.bias _ src.bias + src.length; dst.stepsLeft _ dst.length; -- set stepsLeft for count down src.stepsLeft _ src.length; IF options.includeStart THEN DoByte[]; FOR i: CARDINAL IN (0 .. dst.length) DO dst _ InlineIncr[dst]; IF src.length > 0 THEN src _ InlineIncr[src]; DoByte[]; ENDLOOP; IF options.includeEnd THEN { dst _ InlineIncr[dst]; IF src.length > 0 THEN src _ InlineIncr[src]; DoByte[]; }; }; END. jEdgeBltImpl.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. Frank Crow, July 2, 1987 4:01:00 pm PDT A general-purpose Bresenham incrementer. Type Definitions 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: INTEGER _ 0, -- amount to increment by hicIncr: INTEGER _ 0, -- amount to offset at hiccup bias: INTEGER _ 0, -- change to number of increments to first offset (for wizards) indirect: BOOLEAN _ TRUE, -- incrementing addresses if TRUE, else values nextEdge: CARD16 _ 0 -- next edge if part of a chain of edges (index in Sequence) ]; RECORD [length: NAT _ 0, s: SEQUENCE maxLength: NAT OF EdgeDesc]; Constants Basic Procedures The fractional increment Dx/Dy 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. Κ}˜Ihead2šœ™šœ<™˜YJš œ œœ œœ  œ ˜^——šœ œ˜Jšœ˜Jšœ˜Jšœ˜—šœ™Idefaultšœ œ˜%Lšœ œ˜!L˜šœ œ˜"šœ™LšœœΟc>™JLšœ œž!™7Lšœœž&™:Lšœ œž'™;Lšœ œž™1Lšœ œž™4Lšœœž?™TLšœ œœž.™HLšœ œž<™QLšœ™——šœœ˜*Lš œ œ œ œœ ™B—Iašœœ˜*Mšœœ˜/Mšœœœœ˜?—™ Lšœœ˜Lšœœ˜—™LšœΟgœŸœΥŸœŸœZŸœŸœ)ŸœŸœ+ŸœŸœ™ψš Οnœœœœœœ˜VLšœ%˜%Lšœ'˜'šœœ˜Lšœ#˜#Lšœ&˜&L˜—Lšœ#˜$šœž-˜KLšœœœ˜;—Lšœ˜ Lšœ˜—š   œœœœœ œ˜aLšœ%˜%Lšœ'˜'šœœ˜Lšœ#˜#Lšœ&˜&L˜—Lšœ#˜$šœž-˜KLšœœœ˜;—Lšœ˜ Lšœ˜—š œ œ˜'š œœœ˜Lš œ œœœœ˜PLšœ œ˜šœ ˜šœœž˜1Lš œ œœœœ˜PLšœ œ˜,Lšœ˜—Lšœ  œ œž˜S—šœœž˜TLš œœœž ˜OLšœœœ*ž ˜O—Lšœ˜—Lšœ˜Lšœ˜Lšœ'˜'Lšœœœ=˜ULšœ#ž!˜DLšœ!˜!Lšœž˜>Lšœ˜Lšœœ ˜&šœœœ˜'Lšœœœ$˜TLšœ˜—šœœ˜Lšœœœ&˜VLšœ˜—L˜—L˜—Jšœ˜—…— nU