Annotation of ntddk/src/video/displays/s3/lines.cxx, revision 1.1.1.1

1.1       root        1: /*************************************************************************\
                      2: * Module Name: Lines.cxx
                      3: *
                      4: * C template for the ASM version of the line DDA calculator.
                      5: *
                      6: * Copyright (c) 1990-1993 Microsoft Corporation
                      7: * Copyright (c) 1992 Digital Equipment Corporation
                      8: \**************************************************************************/
                      9: 
                     10: #define __CPLUSPLUS
                     11: #include "driver.h"
                     12: #include "lines.h"
                     13: #include "equad.hxx"
                     14: 
                     15: #define SWAPL(x,y,t)        {t = x; x = y; y = t;} // from wingdip.h
                     16: #define ROR_BYTE(x) ((((x) >> 1) & 0x7f) | (((x) & 0x01) << 7))
                     17: #define ROL_BYTE(x) ((((x) << 1) & 0xfe) | (((x) & 0x80) >> 7))
                     18: #define MIN(a, b) ((a) < (b) ? (a) : (b))
                     19: #define ABS(a)    ((a) < 0 ? -(a) : (a))
                     20: 
                     21: FLONG gaflRound[] = {
                     22:     FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // no flips
                     23:     FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // FL_FLIP_D
                     24:     FL_H_ROUND_DOWN,                   // FL_FLIP_V
                     25:     FL_V_ROUND_DOWN,                   // FL_FLIP_V | FL_FLIP_D
                     26:     FL_V_ROUND_DOWN,                   // FL_FLIP_SLOPE_ONE
                     27:     0xbaadf00d,                        // FL_FLIP_SLOPE_ONE | FL_FLIP_D
                     28:     FL_H_ROUND_DOWN,                   // FL_FLIP_SLOPE_ONE | FL_FLIP_V
                     29:     0xbaadf00d                         // FL_FLIP_SLOPE_ONE | FL_FLIP_V
                     30: | FL_FLIP_D
                     31: };
                     32: 
                     33: extern "C"
                     34: BOOL
                     35: bIntegerLine (
                     36:              PPDEV     ppdev,
                     37:              ULONG     X1,
                     38:              ULONG     Y1,
                     39:              ULONG     X2,
                     40:              ULONG     Y2
                     41: );
                     42: 
                     43: /******************************Public*Routine******************************\
                     44: * BOOL bLines(ppdev, pptfxFirst, pptfxBuf, cptfx, pls,
                     45: *                   prclClip, apfn[], flStart)
                     46: *
                     47: * Computes the DDA for the line and gets ready to draw it.  Puts the
                     48: * pixel data into an array of strips, and calls a strip routine to
                     49: * do the actual drawing.
                     50: *
                     51: * Doing Lines Right
                     52: * -----------------
                     53: *
                     54: * In NT, all lines are given to the device driver in fractional
                     55: * coordinates, in a 28.4 fixed point format.  The lower 4 bits are
                     56: * fractional for sub-pixel positioning.
                     57: *
                     58: * Note that you CANNOT! just round the coordinates to integers
                     59: * and pass the results to your favorite integer Bresenham routine!!
                     60: * (Unless, of course, you have such a high resolution device that
                     61: * nobody will notice -- not likely for a display device.)  The
                     62: * fractions give a more accurate rendering of the line -- this is
                     63: * important for things like our Bezier curves, which would have 'kinks'
                     64: * if the points in its polyline approximation were rounded to integers.
                     65: *
                     66: * Unfortunately, for fractional lines there is more setup work to do
                     67: * a DDA than for integer lines.  However, the main loop is exactly
                     68: * the same (and can be done entirely with 32 bit math).
                     69: *
                     70: * If You've Got Hardware That Does Bresenham
                     71: * ------------------------------------------
                     72: *
                     73: * A lot of hardware limits DDA error terms to 'n' bits.  With fractional
                     74: * coordinates, 4 bits are given to the fractional part, letting
                     75: * you draw in hardware only those lines that lie entirely in a 2^(n-4)
                     76: * by 2^(n-4) pixel space.
                     77: *
                     78: * And you still have to correctly draw those lines with coordinates
                     79: * outside that space!  Remember that the screen is only a viewport
                     80: * onto a 28.4 by 28.4 space -- if any part of the line is visible
                     81: * you MUST render it precisely, regardless of where the end points lie.
                     82: * So even if you do it in software, somewhere you'll have to have a
                     83: * 32 bit DDA routine.
                     84: *
                     85: * Our Implementation
                     86: * ------------------
                     87: *
                     88: * We employ a run length slice algorithm: our DDA calculates the
                     89: * number of pixels that are in each row (or 'strip') of pixels.
                     90: *
                     91: * We've separated the running of the DDA and the drawing of pixels:
                     92: * we run the DDA for several iterations and store the results in
                     93: * a 'strip' buffer (which are the lengths of consecutive pixel rows of
                     94: * the line), then we crank up a 'strip drawer' that will draw all the
                     95: * strips in the buffer.
                     96: *
                     97: * We also employ a 'half-flip' to reduce the number of strip
                     98: * iterations we need to do in the DDA and strip drawing loops: when a
                     99: * (normalized) line's slope is more than 1/2, we do a final flip
                    100: * about the line y = (1/2)x.  So now, instead of each strip being
                    101: * consecutive horizontal or vertical pixel rows, each strip is composed
                    102: * of those pixels aligned in 45 degree rows.  So a line like (0, 0) to
                    103: * (128, 128) would generate only one strip.
                    104: *
                    105: * We also always draw only left-to-right.
                    106: *
                    107: * Style lines may have arbitrary style patterns.  We specially
                    108: * optimize the default patterns (and call them 'masked' styles).
                    109: *
                    110: * The DDA Derivation
                    111: * ------------------
                    112: *
                    113: * Here is how I like to think of the DDA calculation.
                    114: *
                    115: * We employ Knuth's "diamond rule": rendering a one-pixel-wide line
                    116: * can be thought of as dragging a one-pixel-wide by one-pixel-high
                    117: * diamond along the true line.  Pixel centers lie on the integer
                    118: * coordinates, and so we light any pixel whose center gets covered
                    119: * by the "drag" region (John D. Hobby, Journal of the Association
                    120: * for Computing Machinery, Vol. 36, No. 2, April 1989, pp. 209-229).
                    121: *
                    122: * We must define which pixel gets lit when the true line falls
                    123: * exactly half-way between two pixels.  In this case, we follow
                    124: * the rule: when two pels are equidistant, the upper or left pel
                    125: * is illuminated, unless the slope is exactly one, in which case
                    126: * the upper or right pel is illuminated.  (So we make the edges
                    127: * of the diamond exclusive, except for the top and left vertices,
                    128: * which are inclusive, unless we have slope one.)
                    129: *
                    130: * This metric decides what pixels should be on any line BEFORE it is
                    131: * flipped around for our calculation.  Having a consistent metric
                    132: * this way will let our lines blend nicely with our curves.  The
                    133: * metric also dictates that we will never have one pixel turned on
                    134: * directly above another that's turned on.  We will also never have
                    135: * a gap; i.e., there will be exactly one pixel turned on for each
                    136: * column between the start and end points.  All that remains to be
                    137: * done is to decide how many pixels should be turned on for each row.
                    138: *
                    139: * So lines we draw will consist of varying numbers of pixels on
                    140: * successive rows, for example:
                    141: *
                    142: *       ******
                    143: *             *****
                    144: *                  ******
                    145: *                        *****
                    146: *
                    147: * We'll call each set of pixels on a row a "strip".
                    148: *
                    149: * (Please remember that our coordinate space has the origin as the
                    150: * upper left pixel on the screen; postive y is down and positive x
                    151: * is right.)
                    152: *
                    153: * Device coordinates are specified as fixed point 28.4 numbers,
                    154: * where the first 28 bits are the integer coordinate, and the last
                    155: * 4 bits are the fraction.  So coordinates may be thought of as
                    156: * having the form (x, y) = (M/F, N/F) where F is the constant scaling
                    157: * factor F = 2^4 = 16, and M and N are 32 bit integers.
                    158: *
                    159: * Consider the line from (M0/F, N0/F) to (M1/F, N1/F) which runs
                    160: * left-to-right and whose slope is in the first octant, and let
                    161: * dM = M1 - M0 and dN = N1 - N0.  Then dM >= 0, dN >= 0 and dM >= dN.
                    162: *
                    163: * Since the slope of the line is less than 1, the edges of the
                    164: * drag region are created by the top and bottom vertices of the
                    165: * diamond.  At any given pixel row y of the line, we light those
                    166: * pixels whose centers are between the left and right edges.
                    167: *
                    168: * Let mL(n) denote the line representing the left edge of the drag
                    169: * region.  On pixel row j, the column of the first pixel to be
                    170: * lit is
                    171: *
                    172: *       iL(j) = ceiling( mL(j * F) / F)
                    173: *
                    174: * Since the line's slope is less than one:
                    175: *
                    176: *       iL(j) = ceiling( mL([j + 1/2] F) / F )
                    177: *
                    178: * Recall the formula for our line:
                    179: *
                    180: *       n(m) = (dN / dM) (m - M0) + N0
                    181: *
                    182: *       m(n) = (dM / dN) (n - N0) + M0
                    183: *
                    184: * Since the line's slope is less than one, the line representing
                    185: * the left edge of the drag region is the original line offset
                    186: * by 1/2 pixel in the y direction:
                    187: *
                    188: *       mL(n) = (dM / dN) (n - F/2 - N0) + M0
                    189: *
                    190: * From this we can figure out the column of the first pixel that
                    191: * will be lit on row j, being careful of rounding (if the left
                    192: * edge lands exactly on an integer point, the pixel at that
                    193: * point is not lit because of our rounding convention):
                    194: *
                    195: *       iL(j) = floor( mL(j F) / F ) + 1
                    196: *
                    197: *             = floor( ((dM / dN) (j F - F/2 - N0) + M0) / F ) + 1
                    198: *
                    199: *             = floor( F dM j - F/2 dM - N0 dM + dN M0) / F dN ) + 1
                    200: *
                    201: *                      F dM j - [ dM (N0 + F/2) - dN M0 ]
                    202: *             = floor( ---------------------------------- ) + 1
                    203: *                                   F dN
                    204: *
                    205: *                      dM j - [ dM (N0 + F/2) - dN M0 ] / F
                    206: *             = floor( ------------------------------------ ) + 1       (1)
                    207: *                                     dN
                    208: *
                    209: *             = floor( (dM j + alpha) / dN ) + 1
                    210: *
                    211: * where
                    212: *
                    213: *       alpha = - [ dM (N0 + F/2) - dN M0 ] / F
                    214: *
                    215: * We use equation (1) to calculate the DDA: there are iL(j+1) - iL(j)
                    216: * pixels in row j.  Because we are always calculating iL(j) for
                    217: * integer quantities of j, we note that the only fractional term
                    218: * is constant, and so we can 'throw away' the fractional bits of
                    219: * alpha:
                    220: *
                    221: *       beta = floor( - [ dM (N0 + F/2) - dN M0 ] / F )                 (2)
                    222: *
                    223: * so
                    224: *
                    225: *       iL(j) = floor( (dM j + beta) / dN ) + 1                         (3)
                    226: *
                    227: * for integers j.
                    228: *
                    229: * Note if iR(j) is the line's rightmost pixel on row j, that
                    230: * iR(j) = iL(j + 1) - 1.
                    231: *
                    232: * Similarly, rewriting equation (1) as a function of column i,
                    233: * we can determine, given column i, on which pixel row j is the line
                    234: * lit:
                    235: *
                    236: *                       dN i + [ dM (N0 + F/2) - dN M0 ] / F
                    237: *       j(i) = ceiling( ------------------------------------ ) - 1
                    238: *                                       dM
                    239: *
                    240: * Floors are easier to compute, so we can rewrite this:
                    241: *
                    242: *                     dN i + [ dM (N0 + F/2) - dN M0 ] / F + dM - 1/F
                    243: *       j(i) = floor( ----------------------------------------------- ) - 1
                    244: *                                       dM
                    245: *
                    246: *                     dN i + [ dM (N0 + F/2) - dN M0 ] / F + dM - 1/F - dM
                    247: *            = floor( ---------------------------------------------------- )
                    248: *                                       dM
                    249: *
                    250: *                     dN i + [ dM (N0 + F/2) - dN M0 - 1 ] / F
                    251: *            = floor( ---------------------------------------- )
                    252: *                                       dM
                    253: *
                    254: * We can once again wave our hands and throw away the fractional bits
                    255: * of the remainder term:
                    256: *
                    257: *       j(i) = floor( (dN i + gamma) / dM )                             (4)
                    258: *
                    259: * where
                    260: *
                    261: *       gamma = floor( [ dM (N0 + F/2) - dN M0 - 1 ] / F )              (5)
                    262: *
                    263: * We now note that
                    264: *
                    265: *       beta = -gamma - 1 = ~gamma                                      (6)
                    266: *
                    267: * To draw the pixels of the line, we could evaluate (3) on every scan
                    268: * line to determine where the strip starts.  Of course, we don't want
                    269: * to do that because that would involve a multiply and divide for every
                    270: * scan.  So we do everything incrementally.
                    271: *
                    272: * We would like to easily compute c , the number of pixels on scan j:
                    273: *                                  j
                    274: *
                    275: *    c  = iL(j + 1) - iL(j)
                    276: *     j
                    277: *
                    278: *       = floor((dM (j + 1) + beta) / dN) - floor((dM j + beta) / dN)   (7)
                    279: *
                    280: * This may be rewritten as
                    281: *
                    282: *    c  = floor(i    + r    / dN) - floor(i  + r  / dN)                 (8)
                    283: *     j          j+1    j+1                j    j
                    284: *
                    285: * where i , i    are integers and r  < dN, r    < dN.
                    286: *        j   j+1                   j        j+1
                    287: *
                    288: * Rewriting (7) again:
                    289: *
                    290: *    c  = floor(i  + r  / dN + dM / dN) - floor(i  + r  / dN)
                    291: *     j          j    j                          j    j
                    292: *
                    293: *
                    294: *       = floor((r  + dM) / dN) - floor(r  / dN)
                    295: *                 j                      j
                    296: *
                    297: * This may be rewritten as
                    298: *
                    299: *    c  = dI + floor((r  + dR) / dN) - floor(r  / dN)
                    300: *     j                j                      j
                    301: *
                    302: * where dI + dR / dN = dM / dN, dI is an integer and dR < dN.
                    303: *
                    304: * r  is the remainder (or "error") term in the DDA loop: r  / dN
                    305: *  j                                                      j
                    306: * is the exact fraction of a pixel at which the strip ends.  To go
                    307: * on to the next scan and compute c    we need to know r   .
                    308: *                                  j+1                  j+1
                    309: *
                    310: * So in the main loop of the DDA:
                    311: *
                    312: *    c  = dI + floor((r  + dR) / dN) and r    = (r  + dR) % dN
                    313: *     j                j                  j+1     j
                    314: *
                    315: * and we know r  < dN, r    < dN, and dR < dN.
                    316: *              j        j+1
                    317: *
                    318: * We have derived the DDA only for lines in the first octant; to
                    319: * handle other octants we do the common trick of flipping the line
                    320: * to the first octant by first making the line left-to-right by
                    321: * exchanging the end-points, then flipping about the lines y = 0 and
                    322: * y = x, as necessary.  We must record the transformation so we can
                    323: * undo them later.
                    324: *
                    325: * We must also be careful of how the flips affect our rounding.  If
                    326: * to get the line to the first octant we flipped about x = 0, we now
                    327: * have to be careful to round a y value of 1/2 up instead of down as
                    328: * we would for a line originally in the first octant (recall that
                    329: * "In the case where two pels are equidistant, the upper or left
                    330: * pel is illuminated...").
                    331: *
                    332: * To account for this rounding when running the DDA, we shift the line
                    333: * (or not) in the y direction by the smallest amount possible.  That
                    334: * takes care of rounding for the DDA, but we still have to be careful
                    335: * about the rounding when determining the first and last pixels to be
                    336: * lit in the line.
                    337: *
                    338: * Determining The First And Last Pixels In The Line
                    339: * -------------------------------------------------
                    340: *
                    341: * Fractional coordinates also make it harder to determine which pixels
                    342: * will be the first and last ones in the line.  We've already taken
                    343: * the fractional coordinates into account in calculating the DDA, but
                    344: * the DDA cannot tell us which are the end pixels because it is quite
                    345: * happy to calculate pixels on the line from minus infinity to positive
                    346: * infinity.
                    347: *
                    348: * The diamond rule determines the start and end pixels.  (Recall that
                    349: * the sides are exclusive except for the left and top vertices.)
                    350: * This convention can be thought of in another way: there are diamonds
                    351: * around the pixels, and wherever the true line crosses a diamond,
                    352: * that pel is illuminated.
                    353: *
                    354: * Consider a line where we've done the flips to the first octant, and the
                    355: * floor of the start coordinates is the origin:
                    356: *
                    357: *        +-----------------------> +x
                    358: *        |
                    359: *        | 0                     1
                    360: *        |     0123456789abcdef
                    361: *        |
                    362: *        |   0 00000000?1111111
                    363: *        |   1 00000000 1111111
                    364: *        |   2 0000000   111111
                    365: *        |   3 000000     11111
                    366: *        |   4 00000    ** 1111
                    367: *        |   5 0000       ****1
                    368: *        |   6 000           1***
                    369: *        |   7 00             1  ****
                    370: *        |   8 ?                     ***
                    371: *        |   9 22             3         ****
                    372: *        |   a 222           33             ***
                    373: *        |   b 2222         333                ****
                    374: *        |   c 22222       3333                    **
                    375: *        |   d 222222     33333
                    376: *        |   e 2222222   333333
                    377: *        |   f 22222222 3333333
                    378: *        |
                    379: *        | 2                     3
                    380: *        v
                    381: *        +y
                    382: *
                    383: * If the start of the line lands on the diamond around pixel 0 (shown by
                    384: * the '0' region here), pixel 0 is the first pel in the line.  The same
                    385: * is true for the other pels.
                    386: *
                    387: * A little more work has to be done if the line starts in the
                    388: * 'nether-land' between the diamonds (as illustrated by the '*' line):
                    389: * the first pel lit is the first diamond crossed by the line (pixel 1 in
                    390: * our example).  This calculation is determined by the DDA or slope of
                    391: * the line.
                    392: *
                    393: * If the line starts exactly half way between two adjacent pixels
                    394: * (denoted here by the '?' spots), the first pixel is determined by our
                    395: * round-down convention (and is dependent on the flips done to
                    396: * normalize the line).
                    397: *
                    398: * Last Pel Exclusive
                    399: * ------------------
                    400: *
                    401: * To eliminate repeatedly lit pels between continuous connected lines,
                    402: * we employ a last-pel exclusive convention: if the line ends exactly on
                    403: * the diamond around a pel, that pel is not lit.  (This eliminates the
                    404: * checks we had in the old code to see if we were re-lighting pels.)
                    405: *
                    406: * The Half Flip
                    407: * -------------
                    408: *
                    409: * To make our run length algorithm more efficient, we employ a "half
                    410: * flip".  If after normalizing to the first octant, the slope is more
                    411: * than 1/2, we subtract the y coordinate from the x coordinate.  This
                    412: * has the effect of reflecting the coordinates through the line of slope
                    413: * 1/2.  Note that the diagonal gets mapped into the x-axis after a half
                    414: * flip.
                    415: *
                    416: * How Many Bits Do We Need, Anyway?
                    417: * ---------------------------------
                    418: *
                    419: * Note that if the line is visible on your screen, you must light up
                    420: * exactly the correct pixels, no matter where in the 28.4 x 28.4 device
                    421: * space the end points of the line lie (meaning you must handle 32 bit
                    422: * DDAs, you can certainly have optimized cases for lesser DDAs).
                    423: *
                    424: * We move the origin to (floor(M0 / F), floor(N0 / F)), so when we
                    425: * calculate gamma from (5), we know that 0 <= M0, N0 < F.  And we
                    426: * are in the first octant, so dM >= dN.  Then we know that gamma can
                    427: * be in the range [(-1/2)dM, (3/2)dM].  The DDI guarantees us that
                    428: * valid lines will have dM and dN values at most 31 bits (unsigned)
                    429: * of significance.  So gamma requires 33 bits of significance (we store
                    430: * this as a 64 bit number for convenience).
                    431: *
                    432: * When running through the DDA loop, r  + dR can have a value in the
                    433: *                                     j
                    434: * range 0 <= r  < 2 dN; thus the result must be a 32 bit unsigned value.
                    435: *             j
                    436: *
                    437: * Testing Lines
                    438: * -------------
                    439: *
                    440: * To be NT compliant, a display driver must exactly adhere to GIQ,
                    441: * which means that for any given line, the driver must light exactly
                    442: * the same pels as does GDI.  This can be tested using the Guiman tool
                    443: * provided elsewhere in the DDK, and 'ZTest', which draws random lines
                    444: * on the screen and to a bitmap, and compares the results.
                    445: *
                    446: * If You've Got Line Hardware
                    447: * ---------------------------
                    448: *
                    449: * If your hardware already adheres to GIQ, you're all set.  Otherwise
                    450: * you'll want to look at the S3 sample code and read the following:
                    451: *
                    452: * 1) You'll want to special case integer-only lines, since they require
                    453: *    less processing time and are more common (CAD programs will probably
                    454: *    only ever give integer lines).  GDI does not provide a flag saying
                    455: *    that all lines in a path are integer lines; consequently, you will
                    456: *    have to explicitly check every line.
                    457: *
                    458: * 2) You are required to correctly draw any line in the 28.4 device
                    459: *    space that intersects the viewport.  If you have less than 32 bits
                    460: *    of significance in the hardware for the Bresenham terms, extremely
                    461: *    long lines would overflow the hardware.  For such (rare) cases, you
                    462: *    can fall back to strip-drawing code, of which there is a C version in
                    463: *    the S3's lines.cxx (or if your display is a frame buffer, fall back
                    464: *    to the engine).
                    465: *
                    466: * 3) If you can explicitly set the Bresenham terms in your hardware, you
                    467: *    can draw non-integer lines using the hardware.  If your hardware has
                    468: *    'n' bits of precision, you can draw GIQ lines that are up to 2^(n-5)
                    469: *    pels long (4 bits are required for the fractional part, and one bit is
                    470: *    used as a sign bit).  Note that integer lines don't require the 4
                    471: *    fractional bits, so if you special case them as in 1), you can do
                    472: *    integer lines that are up to 2^(n - 1) pels long.  See the S3's
                    473: *    fastline.asm for an example.
                    474: *
                    475: \**************************************************************************/
                    476: 
                    477: 
                    478: BOOL bLines(
                    479: PPDEV     ppdev,
                    480: POINTFIX*  pptfxFirst,  // Start of first line
                    481: POINTFIX*  pptfxBuf,    // Pointer to buffer of all remaining lines
                    482: RUN*       prun,        // Pointer to runs if doing complex clipping
                    483: ULONG      cptfx,       // Number of points in pptfxBuf or number of runs
                    484:                         // in prun
                    485: LINESTATE* pls,         // Color and style info
                    486: RECTL*     prclClip,    // Pointer to clip rectangle if doing simple clipping
                    487: PFNSTRIP   apfn[],      // Array of strip functions
                    488: FLONG      flStart)     // Flags for each line
                    489: {
                    490: 
                    491:     ULONG     M0;
                    492:     ULONG     dM;
                    493:     ULONG     N0;
                    494:     ULONG     dN;
                    495:     ULONG     dN_Original;
                    496:     FLONG     fl;
                    497:     LONG      x;
                    498:     LONG      y;
                    499:     EQUAD     eqBeta;
                    500:     EQUAD     eqGamma;
                    501:     EQUAD     euq;
                    502:     EQUAD     eq;
                    503:     ULONG     ulDelta;
                    504: 
                    505:     ULONG     x0;
                    506:     ULONG     y0;
                    507:     ULONG     x1;
                    508:     ULONG     cStylePels;    // Major length of line in pixels for styling
                    509:     ULONG     xStart;
                    510:     POINTL    ptlStart;
                    511:     STRIP     strip;
                    512:     PFNSTRIP  pfn;
                    513:     LONG      cPels;
                    514:     LONG*     plStrip;
                    515:     LONG*     plStripEnd;
                    516:     LONG      cStripsInNextRun;
                    517: 
                    518:     POINTFIX* pptfxBufEnd = pptfxBuf + cptfx; // Last point in path record
                    519:     STYLEPOS  spThis;                         // Style pos for this line
                    520: 
                    521: 
                    522:     do {
                    523: 
                    524: /***********************************************************************\
                    525: * Start the DDA calculations.                                           *
                    526: \***********************************************************************/
                    527: 
                    528:         M0 = (LONG) pptfxFirst->x;
                    529:         dM = (LONG) pptfxBuf->x;
                    530: 
                    531:         N0 = (LONG) pptfxFirst->y;
                    532:         dN = (LONG) pptfxBuf->y;
                    533: 
                    534:         fl = flStart;
                    535: 
                    536:        // Check for non-clipped, non-styled integer endpoint lines - ECR
                    537: 
                    538:         if ( ( (fl & (FL_CLIP | FL_STYLED))  == 0 ) &&
                    539:             ( ((M0 | dM | N0 | dN) & (F-1)) == 0 ) )
                    540:        {
                    541:           if (bIntegerLine(ppdev, M0, N0, dM, dN))
                    542:           {
                    543:             goto Next_Line;
                    544:           }
                    545:         }
                    546:        
                    547:         if ((LONG) M0 > (LONG) dM)
                    548:         {
                    549:         // Ensure that we run left-to-right:
                    550: 
                    551:             register ULONG ulTmp;
                    552:             SWAPL(M0, dM, ulTmp);
                    553:             SWAPL(N0, dN, ulTmp);
                    554:             fl |= FL_FLIP_H;
                    555:         }
                    556: 
                    557:     // Compute the deltas:
                    558: 
                    559:         dM -= M0;
                    560:         dN -= N0;
                    561: 
                    562:     // We now have a line running left-to-right from (M0, N0) to
                    563:     // (M0 + dM, N0 + dN):
                    564: 
                    565:         if ((LONG) dN < 0)
                    566:         {
                    567:         // Line runs from bottom to top, so flip across y = 0:
                    568: 
                    569:             N0 = -(LONG) N0;
                    570:             dN = -(LONG) dN;
                    571:             fl |= FL_FLIP_V;
                    572:         }
                    573: 
                    574:         if (dN >= dM)
                    575:         {
                    576:             if (dN == dM)
                    577:             {
                    578:             // Have to special case slopes of one:
                    579: 
                    580:                 fl |= FL_FLIP_SLOPE_ONE;
                    581:             }
                    582:             else
                    583:             {
                    584:             // Since line has slope greater than 1, flip across x = y:
                    585: 
                    586:                 register ULONG ulTmp;
                    587:                 SWAPL(dM, dN, ulTmp);
                    588:                 SWAPL(M0, N0, ulTmp);
                    589:                 fl |= FL_FLIP_D;
                    590:             }
                    591:         }
                    592: 
                    593:         fl |= gaflRound[(fl & FL_ROUND_MASK) >> FL_ROUND_SHIFT];
                    594: 
                    595:         x = LFLOOR((LONG) M0);
                    596:         y = LFLOOR((LONG) N0);
                    597: 
                    598:         M0 = FXFRAC(M0);
                    599:         N0 = FXFRAC(N0);
                    600: 
                    601:     // Calculate the remainder term [ dM * (N0 + F/2) - M0 * dN ]:
                    602: 
                    603:     {
                    604: 
                    605:             eqGamma.vImulInit(dM, N0 + F/2);
                    606:             eq.vImulInit(M0, dN);
                    607: 
                    608:             eqGamma -= eq;
                    609: 
                    610:             if (fl & FL_V_ROUND_DOWN)
                    611:                 eqGamma -= 1L;            // Adjust so y = 1/2 rounds down
                    612: 
                    613:             eqGamma >>= FLOG2;
                    614: 
                    615:             eqBeta.HighPart = ~eqGamma.HighPart;
                    616:             eqBeta.LowPart  = ~eqGamma.LowPart;
                    617: 
                    618:     }
                    619: 
                    620: 
                    621: /***********************************************************************\
                    622: * Figure out which pixels are at the ends of the line.                  *
                    623: \***********************************************************************/
                    624: 
                    625:     // The toughest part of GIQ is determining the start and end pels.
                    626:     //
                    627:     // Our approach here is to calculate x0 and x1 (the inclusive start
                    628:     // and end columns of the line respectively, relative to our normalized
                    629:     // origin).  Then x1 - x0 + 1 is the number of pels in the line.  The
                    630:     // start point is easily calculated by plugging x0 into our line equation
                    631:     // (which takes care of whether y = 1/2 rounds up or down in value)
                    632:     // getting y0, and then undoing the normalizing flips to get back
                    633:     // into device space.
                    634:     //
                    635:     // We look at the fractional parts of the coordinates of the start and
                    636:     // end points, and call them (M0, N0) and (M1, N1) respectively, where
                    637:     // 0 <= M0, N0, M1, N1 < 16.  We plot (M0, N0) on the following grid
                    638:     // to determine x0:
                    639:     //
                    640:     //   +-----------------------> +x
                    641:     //   |
                    642:     //   | 0                     1
                    643:     //   |     0123456789abcdef
                    644:     //   |
                    645:     //   |   0 ........?xxxxxxx
                    646:     //   |   1 ..........xxxxxx
                    647:     //   |   2 ...........xxxxx
                    648:     //   |   3 ............xxxx
                    649:     //   |   4 .............xxx
                    650:     //   |   5 ..............xx
                    651:     //   |   6 ...............x
                    652:     //   |   7 ................
                    653:     //   |   8 ................
                    654:     //   |   9 ......**........
                    655:     //   |   a ........****...x
                    656:     //   |   b ............****
                    657:     //   |   c .............xxx****
                    658:     //   |   d ............xxxx    ****
                    659:     //   |   e ...........xxxxx        ****
                    660:     //   |   f ..........xxxxxx
                    661:     //   |
                    662:     //   | 2                     3
                    663:     //   v
                    664:     //
                    665:     //   +y
                    666:     //
                    667:     // This grid accounts for the appropriate rounding of GIQ and last-pel
                    668:     // exclusion.  If (M0, N0) lands on an 'x', x0 = 2.  If (M0, N0) lands
                    669:     // on a '.', x0 = 1.  If (M0, N0) lands on a '?', x0 rounds up or down,
                    670:     // depending on what flips have been done to normalize the line.
                    671:     //
                    672:     // For the end point, if (M1, N1) lands on an 'x', x1 =
                    673:     // floor((M0 + dM) / 16) + 1.  If (M1, N1) lands on a '.', x1 =
                    674:     // floor((M0 + dM)).  If (M1, N1) lands on a '?', x1 rounds up or down,
                    675:     // depending on what flips have been done to normalize the line.
                    676:     //
                    677:     // Lines of exactly slope one require a special case for both the start
                    678:     // and end.  For example, if the line ends such that (M1, N1) is (9, 1),
                    679:     // the line has gone exactly through (8, 0) -- which may be considered
                    680:     // to be part of 'x' because of rounding!  So slopes of exactly slope
                    681:     // one going through (8, 0) must also be considered as belonging in 'x'.
                    682:     //
                    683:     // For lines that go left-to-right, we have the following grid:
                    684:     //
                    685:     //   +-----------------------> +x
                    686:     //   |
                    687:     //   | 0                     1
                    688:     //   |     0123456789abcdef
                    689:     //   |
                    690:     //   |   0 xxxxxxxx?.......
                    691:     //   |   1 xxxxxxx.........
                    692:     //   |   2 xxxxxx..........
                    693:     //   |   3 xxxxx...........
                    694:     //   |   4 xxxx............
                    695:     //   |   5 xxx.............
                    696:     //   |   6 xx..............
                    697:     //   |   7 x...............
                    698:     //   |   8 x...............
                    699:     //   |   9 x.....**........
                    700:     //   |   a xx......****....
                    701:     //   |   b xxx.........****
                    702:     //   |   c xxxx............****
                    703:     //   |   d xxxxx...........    ****
                    704:     //   |   e xxxxxx..........        ****
                    705:     //   |   f xxxxxxx.........
                    706:     //   |
                    707:     //   | 2                     3
                    708:     //   v
                    709:     //
                    710:     //   +y
                    711:     //
                    712:     // This grid accounts for the appropriate rounding of GIQ and last-pel
                    713:     // exclusion.  If (M0, N0) lands on an 'x', x0 = 0.  If (M0, N0) lands
                    714:     // on a '.', x0 = 1.  If (M0, N0) lands on a '?', x0 rounds up or down,
                    715:     // depending on what flips have been done to normalize the line.
                    716:     //
                    717:     // For the end point, if (M1, N1) lands on an 'x', x1 =
                    718:     // floor((M0 + dM) / 16) - 1.  If (M1, N1) lands on a '.', x1 =
                    719:     // floor((M0 + dM)).  If (M1, N1) lands on a '?', x1 rounds up or down,
                    720:     // depending on what flips have been done to normalize the line.
                    721:     //
                    722:     // Lines of exactly slope one must be handled similarly to the right-to-
                    723:     // left case.
                    724: 
                    725:         {
                    726: 
                    727:         // Calculate x0, x1
                    728: 
                    729:             ULONG N1 = FXFRAC(N0 + dN);
                    730:            ULONG M1 = FXFRAC(M0 + dM);
                    731: 
                    732:            x1 = LFLOOR(M0 + dM);
                    733: 
                    734:             if (fl & FL_FLIP_H)
                    735:             {
                    736:             // ---------------------------------------------------------------
                    737:             // Line runs right-to-left:  <----
                    738: 
                    739:             // Compute x1:
                    740: 
                    741:                 if (N1 == 0)
                    742:                 {
                    743:                     if (LROUND(M1, fl & FL_H_ROUND_DOWN))
                    744:                     {
                    745:                         x1++;
                    746:                     }
                    747:                 }
                    748:                 else if (ABS((LONG) (N1 - F/2)) + M1 > F)
                    749:                 {
                    750:                     x1++;
                    751:                 }
                    752: 
                    753:                 if ((fl & (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
                    754:                        == (FL_FLIP_SLOPE_ONE))
                    755:                 {
                    756:                 // Have to special-case diagonal lines going through our
                    757:                 // the point exactly equidistant between two horizontal
                    758:                 // pixels, if we're supposed to round x=1/2 down:
                    759: 
                    760:                     if ((N1 > 0) && (M1 == N1 + 8))
                    761:                         x1++;
                    762: 
                    763:                 // Don't you love special cases?  Is this a rhetorical question?
                    764: 
                    765:                     if ((M0 > 0) && (N0 == M0 + 8))
                    766:                     {
                    767:                         x0      = 2;
                    768:                         ulDelta = dN;
                    769:                         goto right_to_left_compute_y0;
                    770:                     }
                    771:                 }
                    772: 
                    773:             // Compute x0:
                    774: 
                    775:                 x0      = 1;
                    776:                 ulDelta = 0;
                    777:                 if (N0 == 0)
                    778:                 {
                    779:                     if (LROUND(M0, fl & FL_H_ROUND_DOWN))
                    780:                     {
                    781:                         x0      = 2;
                    782:                         ulDelta = dN;
                    783:                     }
                    784:                 }
                    785:                 else if (ABS((LONG) (N0 - F/2)) + M0 > F)
                    786:                 {
                    787:                     x0      = 2;
                    788:                     ulDelta = dN;
                    789:                 }
                    790: 
                    791:             // Compute y0:
                    792: 
                    793:             right_to_left_compute_y0:
                    794: 
                    795:                 y0 = 0;
                    796:                 eq = eqGamma;
                    797:                 eq += ulDelta;
                    798:                 if (eq.lHigh() >= 0)
                    799:                 {
                    800:                     if (eq.lHigh() > 0 || eq.ulLow() >= 2 * dM - dN)
                    801:                         y0 = 2;
                    802:                     else if (eq.ulLow() >= dM - dN)
                    803:                         y0 = 1;
                    804:                 }
                    805:             }
                    806:             else
                    807:             {
                    808:             // ---------------------------------------------------------------
                    809:             // Line runs left-to-right:  ---->
                    810: 
                    811:             // Compute x1:
                    812: 
                    813:                 x1--;
                    814: 
                    815:                 if (M1 > 0)
                    816:                 {
                    817:                     if (N1 == 0)
                    818:                     {
                    819:                         if (LROUND(M1, fl & FL_H_ROUND_DOWN))
                    820:                             x1++;
                    821:                     }
                    822:                     else if (ABS((LONG) (N1 - F/2)) <= (LONG) M1)
                    823:                     {
                    824:                         x1++;
                    825:                     }
                    826:                 }
                    827: 
                    828:                 if ((fl & (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
                    829:                        == (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
                    830:                 {
                    831:                 // Have to special-case diagonal lines going through our
                    832:                 // the point exactly equidistant between two horizontal
                    833:                 // pixels, if we're supposed to round x=1/2 down:
                    834: 
                    835:                     if ((N1 > 0) && (M1 == N1 + 8))
                    836:                         x1--;
                    837: 
                    838:                     if ((M0 > 0) && (N0 == M0 + 8))
                    839:                     {
                    840:                         x0 = 0;
                    841:                         goto left_to_right_compute_y0;
                    842:                     }
                    843:                 }
                    844: 
                    845:             // Compute x0:
                    846: 
                    847:                 x0 = 0;
                    848:                 if (M0 > 0)
                    849:                 {
                    850:                     if (N0 == 0)
                    851:                     {
                    852:                         if (LROUND(M0, fl & FL_H_ROUND_DOWN))
                    853:                             x0 = 1;
                    854:                     }
                    855:                     else if (ABS((LONG) (N0 - F/2)) <= (LONG) M0)
                    856:                     {
                    857:                         x0 = 1;
                    858:                     }
                    859:                 }
                    860: 
                    861:             // Compute y0:
                    862: 
                    863:             left_to_right_compute_y0:
                    864: 
                    865:                 y0 = 0;
                    866:                 if (eqGamma.lHigh() >= 0 &&
                    867:                     eqGamma.ulLow() >= dM - (dN & (-(LONG) x0)))
                    868:                 {
                    869:                     y0 = 1;
                    870:                 }
                    871:             }
                    872:         }
                    873: 
                    874:         cStylePels = x1 - x0 + 1;
                    875:         if ((LONG) cStylePels <= 0)
                    876:             goto Next_Line;
                    877: 
                    878:         xStart = x0;
                    879: 
                    880: /***********************************************************************\
                    881: * Complex clipping.                                                     *
                    882: \***********************************************************************/
                    883: #ifdef SIMPLE_CLIP
                    884:         if (fl & FL_COMPLEX_CLIP)
                    885: #else
                    886:         if (fl & FL_CLIP)
                    887: #endif // SIMPLE_CLIP
                    888:         {
                    889:             dN_Original = dN;
                    890: 
                    891:         Continue_Complex_Clipping:
                    892: 
                    893:             if (fl & FL_FLIP_H)
                    894:             {
                    895:             // Line runs right-to-left <-----
                    896: 
                    897:                 x0 = xStart + cStylePels - prun->iStop - 1;
                    898:                 x1 = xStart + cStylePels - prun->iStart - 1;
                    899:             }
                    900:             else
                    901:             {
                    902:             // Line runs left-to-right ----->
                    903: 
                    904:                 x0 = xStart + prun->iStart;
                    905:                 x1 = xStart + prun->iStop;
                    906:             }
                    907: 
                    908:             prun++;
                    909: 
                    910:         // Reset some variables we'll nuke a little later:
                    911: 
                    912:             dN          = dN_Original;
                    913:             pls->spNext = pls->spComplex;
                    914: 
                    915:         // No overflow since large integer math is used
                    916: 
                    917:             euq.vMulInit(x0, dN);
                    918:             euq += eqGamma;
                    919: 
                    920:             y0 = euq.ulDiv(dM);
                    921: 
                    922:             ASSERTS3((LONG) y0 >= 0, "y0 weird: Goofed up end pel calc?");
                    923:         }
                    924: 
                    925: /////////////////////////////////////////////////////////////////////////
                    926: // The following clip code works great -- we simply aren't using it yet.
                    927: /////////////////////////////////////////////////////////////////////////
                    928: 
                    929: #ifdef SIMPLE_CLIP
                    930: /***********************************************************************\
                    931: * Simple rectangular clipping.                                          *
                    932: \***********************************************************************/
                    933: 
                    934:         if (fl & FL_SIMPLE_CLIP)
                    935:         {
                    936:             ULONG y1;
                    937:             LONG  xRight;
                    938:             LONG  xLeft;
                    939:             LONG  yBottom;
                    940:             LONG  yTop;
                    941: 
                    942:         // Note that y0 and y1 are actually the lower and upper bounds,
                    943:         // respectively, of the y coordinates of the line (the line may
                    944:         // have actually shrunk due to first/last pel clipping).
                    945:         //
                    946:         // Also note that x0, y0 are not necessarily zero.
                    947: 
                    948:             RECTL* prcl = &prclClip[(fl & FL_RECTLCLIP_MASK) >>
                    949:                                     FL_RECTLCLIP_SHIFT];
                    950: 
                    951:         // Normalize to the same point we've normalized for the DDA
                    952:         // calculations:
                    953: 
                    954:             xRight  = prcl->right  - x;
                    955:             xLeft   = prcl->left   - x;
                    956:             yBottom = prcl->bottom - y;
                    957:             yTop    = prcl->top    - y;
                    958: 
                    959:             if (yBottom <= (LONG) y0 ||
                    960:                 xRight  <= (LONG) x0 ||
                    961:                 xLeft   >  (LONG) x1)
                    962:             {
                    963:             Totally_Clipped:
                    964: 
                    965:                 if (fl & FL_STYLED)
                    966:                 {
                    967:                     pls->spNext += cStylePels;
                    968:                     if (pls->spNext >= pls->spTotal2)
                    969:                         pls->spNext %= pls->spTotal2;
                    970:                 }
                    971: 
                    972:                 goto Next_Line;
                    973:             }
                    974: 
                    975:             if ((LONG) x1 >= xRight)
                    976:                 x1 = xRight - 1;
                    977: 
                    978:         // We have to know the correct y1, which we haven't bothered to
                    979:         // calculate up until now.  This multiply and divide is quite
                    980:         // expensive; we could replace it with code similar to that which
                    981:         // we used for computing y0.
                    982:         //
                    983:         // The reason why we need the actual value, and not an upper
                    984:         // bounds guess like y1 = LFLOOR(dM) + 2 is that we have to be
                    985:         // careful when calculating x(y) that y0 <= y <= y1, otherwise
                    986:         // we can overflow on the divide (which, needless to say, is very
                    987:         // bad).
                    988: 
                    989:             euq.vMulInit(x1, dN);
                    990:             euq += eqGamma;
                    991:             y1 = euq.ulDiv(dM);
                    992: 
                    993:             if (yTop > (LONG) y1)
                    994:                 goto Totally_Clipped;
                    995: 
                    996:             if (yBottom <= (LONG) y1)
                    997:             {
                    998:                 y1 = yBottom;
                    999: 
                   1000:                 euq.vMulInit(y1, dM);
                   1001:                 euq += eqBeta;
                   1002:                 x1 = euq.ulDiv(dN);
                   1003:             }
                   1004: 
                   1005:         // At this point, we've taken care of calculating the intercepts
                   1006:         // with the right and bottom edges.  Now we work on the left and
                   1007:         // top edges:
                   1008: 
                   1009:             if (xLeft > (LONG) x0)
                   1010:             {
                   1011:                 x0 = xLeft;
                   1012: 
                   1013:                 euq.vMulInit(x0, dN);
                   1014:                 euq += eqGamma;
                   1015:                 y0 = euq.ulDiv(dM);
                   1016: 
                   1017:                 if (yBottom <= (LONG) y0)
                   1018:                     goto Totally_Clipped;
                   1019:             }
                   1020: 
                   1021:             if (yTop > (LONG) y0)
                   1022:             {
                   1023:                 y0 = yTop;
                   1024: 
                   1025:                 euq.vMulInit(y0, dM);
                   1026:                 euq += eqBeta;
                   1027:                 x0 = euq.ulDiv(dN) + 1;
                   1028: 
                   1029:                 if (xRight <= (LONG) x0)
                   1030:                     goto Totally_Clipped;
                   1031:             }
                   1032: 
                   1033:             ASSERTS3(x0 <= x1, "Improper rectangle clip");
                   1034:         }
                   1035: #endif // SIMPLE_CLIP
                   1036: 
                   1037: /***********************************************************************\
                   1038: * Done clipping.  Unflip if necessary.                                 *
                   1039: \***********************************************************************/
                   1040: 
                   1041:         ptlStart.x = x + x0;
                   1042:         ptlStart.y = y + y0;
                   1043: 
                   1044:         if (fl & FL_FLIP_D)
                   1045:         {
                   1046:             register LONG lTmp;
                   1047:             SWAPL(ptlStart.x, ptlStart.y, lTmp);
                   1048:         }
                   1049: 
                   1050: 
                   1051:         if (fl & FL_FLIP_V)
                   1052:         {
                   1053:             ptlStart.y = -ptlStart.y;
                   1054:         }
                   1055: 
                   1056:         cPels = x1 - x0 + 1;
                   1057: 
                   1058: /***********************************************************************\
                   1059: * Style calculations.                                                   *
                   1060: \***********************************************************************/
                   1061: 
                   1062:         if (fl & FL_STYLED)
                   1063:         {
                   1064:             STYLEPOS sp;
                   1065: 
                   1066:             spThis       = pls->spNext;
                   1067:             pls->spNext += cStylePels;
                   1068: 
                   1069: #ifdef ALTERNATESTYLED
                   1070:             if (fl & FL_ALTERNATESTYLED)
                   1071:             {
                   1072:                 pls->spNext &= 1;
                   1073:                 if (fl & FL_FLIP_H)
                   1074:                 {
                   1075:                     sp = pls->spNext - x0 + xStart + 1;
                   1076:                 }
                   1077:                 else
                   1078:                 {
                   1079:                     sp = spThis + x0 - xStart;
                   1080:                 }
                   1081:                 pls->ulStyleMask  = (BYTE) (0x55555555L >>
                   1082:                                            (ptlStart.x & 0x7) + (sp & 1));
                   1083: 
                   1084:                 pls->spRemaining = 1;
                   1085:             }
                   1086:             else
                   1087: #endif  // ALTERNATESTYLED
                   1088: 
                   1089:             {
                   1090:                 if (pls->spNext >= pls->spTotal2)
                   1091:                     pls->spNext %= pls->spTotal2;
                   1092: 
                   1093: 
                   1094:                 if (fl & FL_FLIP_H)
                   1095:                     sp = pls->spNext - x0 + xStart;
                   1096:                 else
                   1097:                     sp = spThis + x0 - xStart;
                   1098: #ifdef MASKSTYLED
                   1099:                 if (fl & FL_MASKSTYLED)
                   1100:                 {
                   1101:                     ULONG cShifts;
                   1102:                     ULONG cRemainder;
                   1103:                     ULONG ulStyleMask;
                   1104: 
                   1105:                     if (fl & FL_FLIP_H)
                   1106:                     {
                   1107:                         cShifts           = (sp + 2) / STYLE_DENSITY;
                   1108:                         cRemainder        = (sp + 2) % STYLE_DENSITY;
                   1109:                         cShifts          &= 7L;
                   1110:                         ulStyleMask       = (pls->ulStyleMaskRtoL >> cShifts);
                   1111:                         pls->spRemaining = cRemainder + 1;
                   1112:                     }
                   1113:                     else
                   1114:                     {
                   1115:                         cRemainder        = sp % STYLE_DENSITY;
                   1116:                         cShifts           = sp / STYLE_DENSITY;
                   1117:                         cShifts          &= 7L;
                   1118:                         ulStyleMask       = (pls->ulStyleMaskLtoR >>
                   1119:                                                     (8 - cShifts));
                   1120:                         pls->spRemaining = STYLE_DENSITY - cRemainder;
                   1121:                     }
                   1122: 
                   1123:                     pls->ulStyleMask = (BYTE) (ulStyleMask >>
                   1124:                                                     (ptlStart.x & 0x7));
                   1125:                 }
                   1126:                 else
                   1127: #endif // MASKSTYLED
                   1128:                 {
                   1129:                     ASSERTS3(fl & FL_ARBITRARYSTYLED, "Oops");
                   1130: 
                   1131:                 // Normalize our target style position:
                   1132: 
                   1133:                     if ((sp < 0) || (sp >= pls->spTotal2))
                   1134:                     {
                   1135:                         sp %= pls->spTotal2;
                   1136: 
                   1137:                     // The modulus of a negative number is not well-defined
                   1138:                     // in C -- if it's negative we'll adjust it so that it's
                   1139:                     // back in the range [0, spTotal2):
                   1140: 
                   1141:                         if (sp < 0)
                   1142:                             sp += pls->spTotal2;
                   1143:                     }
                   1144: 
                   1145:                 // Since we always draw the line left-to-right, but styling is
                   1146:                 // always done in the direction of the original line, we have
                   1147:                 // to figure out where we are in the style array for the left
                   1148:                 // edge of this line.
                   1149: 
                   1150:                     if (fl & FL_FLIP_H)
                   1151:                     {
                   1152:                     // Line originally ran right-to-left:
                   1153: 
                   1154:                         sp = -sp;
                   1155:                         if (sp < 0)
                   1156:                             sp += pls->spTotal2;
                   1157: 
                   1158:                         pls->ulStyleMask = ~pls->ulStartMask;
                   1159:                         pls->pspStart    = &pls->aspRtoL[0];
                   1160:                         pls->pspEnd      = &pls->aspRtoL[pls->cStyle - 1];
                   1161:                     }
                   1162:                     else
                   1163:                     {
                   1164:                     // Line originally ran left-to-right:
                   1165: 
                   1166:                         pls->ulStyleMask = pls->ulStartMask;
                   1167:                         pls->pspStart    = &pls->aspLtoR[0];
                   1168:                         pls->pspEnd      = &pls->aspLtoR[pls->cStyle - 1];
                   1169:                     }
                   1170: 
                   1171:                     if (sp >= pls->spTotal)
                   1172:                     {
                   1173:                         sp -= pls->spTotal;
                   1174:                         if (pls->cStyle & 1)
                   1175:                             pls->ulStyleMask = ~pls->ulStyleMask;
                   1176:                     }
                   1177: 
                   1178:                     pls->psp = pls->pspStart;
                   1179:                     while (sp >= *pls->psp)
                   1180:                         sp -= *pls->psp++;
                   1181: 
                   1182:                     ASSERTS3(pls->psp <= pls->pspEnd,
                   1183:                             "Flew off into NeverNeverLand");
                   1184: 
                   1185:                     pls->spRemaining = *pls->psp - sp;
                   1186:                     if ((pls->psp - pls->pspStart) & 1)
                   1187:                         pls->ulStyleMask = ~pls->ulStyleMask;
                   1188:                 }
                   1189:             }
                   1190:         }
                   1191: 
                   1192:         plStrip    = &strip.alStrips[0];
                   1193:         plStripEnd = &strip.alStrips[STRIP_MAX];    // Is exclusive
                   1194:         cStripsInNextRun   = 0x7fffffff;
                   1195: 
                   1196:        strip.ptlStart = ptlStart;
                   1197: 
                   1198:         if (2 * dN > dM &&
                   1199:             !(fl & FL_STYLED) &&        // !!! Remove this! [andrewgo]
                   1200:             !(fl & FL_DONT_DO_HALF_FLIP))
                   1201:         {
                   1202:         // Do a half flip!  Remember that we may doing this on the
                   1203:         // same line multiple times for complex clipping (meaning the
                   1204:         // affected variables should be reset for every clip run):
                   1205: 
                   1206:             fl |= FL_FLIP_HALF;
                   1207: 
                   1208:             eqBeta  = eqGamma;
                   1209:             eqBeta -= dM;
                   1210: 
                   1211:             dN = dM - dN;
                   1212:             y0 = x0 - y0;       // Note this may overflow, but that's okay
                   1213:         }
                   1214: 
                   1215:     // Now, run the DDA starting at (ptlStart.x, ptlStart.y)!
                   1216: 
                   1217:         strip.flFlips = fl;
                   1218:         pfn           = apfn[(fl & FL_STRIP_MASK) >> FL_STRIP_SHIFT];
                   1219: 
                   1220:     // Now calculate the DDA variables needed to figure out how many pixels
                   1221:     // go in the very first strip:
                   1222: 
                   1223:         {
                   1224:             register LONG  i;
                   1225:             register ULONG r;
                   1226:             register ULONG dI;
                   1227:             register ULONG dR;
                   1228: 
                   1229:             if (dN == 0)
                   1230:                 i = 0x7fffffff;
                   1231:             else
                   1232:             {
                   1233:                 euq.vMulInit(y0 + 1, dM);
                   1234:                 euq += eqBeta;
                   1235: 
                   1236:             #ifdef FIREWALLS
                   1237:                 if (euq.bNegative())
                   1238:                 {
                   1239:                     RIP("Oops!");
                   1240:                 }
                   1241:             #endif
                   1242: 
                   1243:                 i = euq.ulDiv(dN, &r) - x0 + 1;
                   1244: 
                   1245:                 dI = dM / dN;
                   1246:                 dR = dM % dN;               // 0 <= dR < dN
                   1247: 
                   1248:                 ASSERTS3(dI > 0, "Weird dI");
                   1249:             }
                   1250: 
                   1251:             ASSERTS3(i > 0 && i <= 0x7fffffff, "Weird initial strip length");
                   1252:             ASSERTS3(cPels > 0, "Zero pel line");
                   1253: 
                   1254: /***********************************************************************\
                   1255: * Run the DDA!                                                          *
                   1256: \***********************************************************************/
                   1257: 
                   1258:             while(TRUE)
                   1259:             {
                   1260:                 cPels -= i;
                   1261:                 if (cPels <= 0)
                   1262:                     break;
                   1263: 
                   1264:                 *plStrip++ = i;
                   1265: 
                   1266:                 if (plStrip == plStripEnd)
                   1267:                 {
                   1268:                     strip.cStrips = plStrip - &strip.alStrips[0];
                   1269:                     (*pfn)(ppdev, &strip, pls);
                   1270:                     plStrip = &strip.alStrips[0];
                   1271:                 }
                   1272: 
                   1273:                 i = dI;
                   1274:                 r += dR;
                   1275: 
                   1276:                 if (r >= dN)
                   1277:                 {
                   1278:                     r -= dN;
                   1279:                     i++;
                   1280:                 }
                   1281:             }
                   1282: 
                   1283:             *plStrip++ = cPels + i;
                   1284: 
                   1285:             strip.cStrips = plStrip - &strip.alStrips[0];
                   1286:             (*pfn)(ppdev, &strip, pls);
                   1287: 
                   1288: 
                   1289:         }
                   1290: 
                   1291:     Next_Line:
                   1292: 
                   1293:         if (fl & FL_COMPLEX_CLIP)
                   1294:         {
                   1295:             cptfx--;
                   1296:             if (cptfx != 0)
                   1297:                 goto Continue_Complex_Clipping;
                   1298: 
                   1299:             break;
                   1300:         }
                   1301:         else
                   1302:         {
                   1303:             pptfxFirst = pptfxBuf;
                   1304:             pptfxBuf++;
                   1305:         }
                   1306: 
                   1307:     } while (pptfxBuf < pptfxBufEnd);
                   1308: 
                   1309:     return(TRUE);
                   1310: 
                   1311: }
                   1312: 
                   1313: #ifdef HARDWAREGIQ
                   1314: 
                   1315: /////////////////////////////////////////////////////////////////////////
                   1316: // The following GIQ code works great -- we simply aren't using it yet.
                   1317: /////////////////////////////////////////////////////////////////////////
                   1318: 
                   1319: typedef struct _DDALINE         /* dl */
                   1320: {
                   1321:     LONG      iDir;
                   1322:     POINTL    ptlStart;
                   1323:     LONG      cPels;
                   1324:     LONG      dMajor;
                   1325:     LONG      dMinor;
                   1326:     LONG      lErrorTerm;
                   1327: } DDALINE;
                   1328: 
                   1329: #define HW_FLIP_D           0x0001L     // Diagonal flip
                   1330: #define HW_FLIP_V           0x0002L     // Vertical flip
                   1331: #define HW_FLIP_H           0x0004L     // Horizontal flip
                   1332: #define HW_FLIP_SLOPE_ONE   0x0008L     // Normalized line has exactly slope one
                   1333: #define HW_FLIP_MASK        (HW_FLIP_D | HW_FLIP_V | HW_FLIP_H)
                   1334: 
                   1335: #define HW_X_ROUND_DOWN     0x0100L     // x = 1/2 rounds down in value
                   1336: #define HW_Y_ROUND_DOWN     0x0200L     // y = 1/2 rounds down in value
                   1337: 
                   1338: LONG gaiDir[] = { 0, 1, 7, 6, 3, 2, 4, 5 };
                   1339: 
                   1340: FLONG gaflHardwareRound[] = {
                   1341:     HW_X_ROUND_DOWN | HW_Y_ROUND_DOWN,  //           |        |        |
                   1342:     HW_X_ROUND_DOWN | HW_Y_ROUND_DOWN,  //           |        |        | FLIP_D
                   1343:     HW_X_ROUND_DOWN,                    //           |        | FLIP_V |
                   1344:     HW_Y_ROUND_DOWN,                    //           |        | FLIP_V | FLIP_D
                   1345:     HW_Y_ROUND_DOWN,                    //           | FLIP_H |        |
                   1346:     HW_X_ROUND_DOWN,                    //           | FLIP_H |        | FLIP_D
                   1347:     0,                                  //           | FLIP_H | FLIP_V |
                   1348:     0,                                  //           | FLIP_H | FLIP_V | FLIP_D
                   1349:     HW_Y_ROUND_DOWN,                    // SLOPE_ONE |        |        |
                   1350:     0xffffffff,                         // SLOPE_ONE |        |        | FLIP_D
                   1351:     HW_X_ROUND_DOWN,                    // SLOPE_ONE |        | FLIP_V |
                   1352:     0xffffffff,                         // SLOPE_ONE |        | FLIP_V | FLIP_D
                   1353:     HW_Y_ROUND_DOWN,                    // SLOPE_ONE | FLIP_H |        |
                   1354:     0xffffffff,                         // SLOPE_ONE | FLIP_H |        | FLIP_D
                   1355:     HW_X_ROUND_DOWN,                    // SLOPE_ONE | FLIP_H | FLIP_V |
                   1356:     0xffffffff                          // SLOPE_ONE | FLIP_H | FLIP_V | FLIP_D
                   1357: };
                   1358: 
                   1359: /******************************Public*Routine******************************\
                   1360: * BOOL bHardwareLine(pptfxStart, pptfxEnd, cBits, pdl)
                   1361: *
                   1362: * This routine is useful for folks who have line drawing hardware where
                   1363: * they can explicitly set the Bresenham terms -- they can use this routine
                   1364: * to draw fractional coordinate GIQ lines with the hardware.
                   1365: *
                   1366: * Fractional coordinate lines require an extra 4 bits of precision in the
                   1367: * Bresenham terms.  For example, if your hardware has 13 bits of precision
                   1368: * for the terms, you can only draw GIQ lines up to 255 pels long using this
                   1369: * routine.
                   1370: *
                   1371: * Input:
                   1372: *   pptfxStart  - Points to GIQ coordinate of start of line
                   1373: *   pptfxEnd    - Points to GIQ coordinate of end of line
                   1374: *   cBits       - The number of bits of precision your hardware can support.
                   1375: *
                   1376: * Output:
                   1377: *   returns     - TRUE if the line can be drawn directly using the line
                   1378: *                 hardware (in which case pdl contains the Bresenham terms
                   1379: *                 for drawing the line).
                   1380: *                 FALSE if the line is too long, and the strips code must be
                   1381: *                 used.
                   1382: *   pdl         - Returns the Bresenham line terms for drawing the line.
                   1383: *
                   1384: * DDALINE:
                   1385: *   iDir        - Direction of the line, as an octant numbered as follows:
                   1386: *
                   1387: *                    \ 5 | 6 /
                   1388: *                     \  |  /
                   1389: *                    4 \ | / 7
                   1390: *                       \ /
                   1391: *                   -----+-----
                   1392: *                       /|\
                   1393: *                    3 / | \ 0
                   1394: *                     /  |  \
                   1395: *                    / 2 | 1 \
                   1396: *
                   1397: *   ptlStart    - Start pixel of line.
                   1398: *   cPels       - # of pels in line.  *NOTE* You must check if this is <= 0!
                   1399: *   dMajor      - Major axis delta.
                   1400: *   dMinor      - Minor axis delta.
                   1401: *   lErrorTerm  - Error term.
                   1402: *
                   1403: * What you do with the last 3 terms may be a little tricky.  They are
                   1404: * actually the terms for the formula of the normalized line
                   1405: *
                   1406: *                     dMinor * x + (lErrorTerm + dMajor)
                   1407: *       y(x) = floor( ---------------------------------- )
                   1408: *                                  dMajor
                   1409: *
                   1410: * where y(x) is the y coordinate of the pixel to be lit as a function of
                   1411: * the x-coordinate.
                   1412: *
                   1413: * Every time the line advances one in the major direction 'x', dMinor
                   1414: * gets added to the current error term.  If the resulting value is >= 0,
                   1415: * we know we have to move one pixel in the minor direction 'y', and
                   1416: * dMajor must be subtracted from the current error term.
                   1417: *
                   1418: * If you're trying to figure out what this means for your hardware, you can
                   1419: * think of the DDALINE terms as having been computed equivalently as
                   1420: * follows:
                   1421: *
                   1422: *     pdl->dMinor     = 2 * (minor axis delta)
                   1423: *     pdl->dMajor     = 2 * (major axis delta)
                   1424: *     pdl->lErrorTerm = - (major axis delta) - fixup
                   1425: *
                   1426: * That is, if your documentation tells you that for integer lines, a
                   1427: * register is supposed to be initialized with the value
                   1428: * '2 * (minor axis delta)', you'll actually use pdl->dMinor.
                   1429: *
                   1430: * Example: Setting up the 8514
                   1431: *
                   1432: *     AXSTPSIGN is supposed to be the axial step constant register, defined
                   1433: *     as 2 * (minor axis delta).  You set:
                   1434: *
                   1435: *           AXSTPSIGN = pdl->dMinor
                   1436: *
                   1437: *     DGSTPSIGN is supposed to be the diagonal step constant register,
                   1438: *     defined as 2 * (minor axis delta) - 2 * (major axis delta).  You set:
                   1439: *
                   1440: *           DGSTPSIGN = pdl->dMinor - pdl->dMajor
                   1441: *
                   1442: *     ERR_TERM is supposed to be the adjusted error term, defined as
                   1443: *     2 * (minor axis delta) - (major axis delta) - fixup.  You set:
                   1444: *
                   1445: *           ERR_TERM = pdl->lErrorTerm + pdl->dMinor
                   1446: *
                   1447: * Implementation:
                   1448: *
                   1449: *     You'll want to special case integer lines before calling this routine
                   1450: *     (since they're very common, take less time to the computation of line
                   1451: *     terms, and can handle longer lines than this routine because 4 bits
                   1452: *     aren't being given to the fraction).
                   1453: *
                   1454: *     If a GIQ line is too long to be handled by this routine, you can just
                   1455: *     use the slower strip routines for that line.  Note that you cannot
                   1456: *     just fail the call -- you must be able to accurately draw any line
                   1457: *     in the 28.4 device space when it intersects the viewport.
                   1458: *
                   1459: * Testing:
                   1460: *
                   1461: *     Use Guiman, or some other test that draws random fractional coordinate
                   1462: *     lines and compares them to what GDI itself draws to a bitmap.
                   1463: *
                   1464: \**************************************************************************/
                   1465: 
                   1466: BOOL bHardwareLine(
                   1467: POINTFIX* pptfxStart,       // Start of line
                   1468: POINTFIX* pptfxEnd,         // End of line
                   1469: LONG      cBits,            // # bits precision in hardware Bresenham terms
                   1470: DDALINE*  pdl)              // Returns Bresenham terms for doing line
                   1471: {
                   1472:     FLONG fl;    // Various flags
                   1473:     ULONG M0;    // Normalized fractional unit x start coordinate (0 <= M0 < F)
                   1474:     ULONG N0;    // Normalized fractional unit y start coordinate (0 <= N0 < F)
                   1475:     ULONG M1;    // Normalized fractional unit x end coordinate (0 <= M1 < F)
                   1476:     ULONG N1;    // Normalized fractional unit x end coordinate (0 <= N1 < F)
                   1477:     ULONG dM;    // Normalized fractional unit x-delta (0 <= dM)
                   1478:     ULONG dN;    // Normalized fractional unit y-delta (0 <= dN <= dM)
                   1479:     LONG  x;     // Normalized x coordinate of origin
                   1480:     LONG  y;     // Normalized y coordinate of origin
                   1481:     LONG  x0;    // Normalized x offset from origin to start pixel (inclusive)
                   1482:     LONG  y0;    // Normalized y offset from origin to start pixel (inclusive)
                   1483:     LONG  x1;    // Normalized x offset from origin to end pixel (inclusive)
                   1484:     LONG  lGamma;// Bresenham error term at origin
                   1485: 
                   1486: /***********************************************************************\
                   1487: * Normalize line to the first octant.
                   1488: \***********************************************************************/
                   1489: 
                   1490:     fl = 0;
                   1491: 
                   1492:     M0 = pptfxStart->x;
                   1493:     dM = pptfxEnd->x;
                   1494: 
                   1495:     if ((LONG) dM < (LONG) M0)
                   1496:     {
                   1497:     // Line runs from right to left, so flip across x = 0:
                   1498: 
                   1499:         M0 = -(LONG) M0;
                   1500:         dM = -(LONG) dM;
                   1501:         fl |= HW_FLIP_H;
                   1502:     }
                   1503: 
                   1504: // Compute the delta.  The DDI says we can never have a valid delta
                   1505: // with a magnitude more than 2^31 - 1, but the engine never actually
                   1506: // checks its transforms.  To ensure that we'll never puke on our shoes,
                   1507: // we check for that case and simply refuse to draw the line:
                   1508: 
                   1509:     dM -= M0;
                   1510:     if ((LONG) dM < 0)
                   1511:         return(FALSE);
                   1512: 
                   1513:     N0 = pptfxStart->y;
                   1514:     dN = pptfxEnd->y;
                   1515: 
                   1516:     if ((LONG) dN < (LONG) N0)
                   1517:     {
                   1518:     // Line runs from bottom to top, so flip across y = 0:
                   1519: 
                   1520:         N0 = -(LONG) N0;
                   1521:         dN = -(LONG) dN;
                   1522:         fl |= HW_FLIP_V;
                   1523:     }
                   1524: 
                   1525: // Compute another delta:
                   1526: 
                   1527:     dN -= N0;
                   1528:     if ((LONG) dN < 0)
                   1529:         return(FALSE);
                   1530: 
                   1531:     if (dN >= dM)
                   1532:     {
                   1533:         if (dN == dM)
                   1534:         {
                   1535:         // Have to special case slopes of one:
                   1536: 
                   1537:             fl |= HW_FLIP_SLOPE_ONE;
                   1538:         }
                   1539:         else
                   1540:         {
                   1541:         // Since line has slope greater than 1, flip across x = y:
                   1542: 
                   1543:             register ULONG ulTmp;
                   1544:             ulTmp = dM; dM = dN; dN = ulTmp;
                   1545:             ulTmp = M0; M0 = N0; N0 = ulTmp;
                   1546:             fl |= HW_FLIP_D;
                   1547:         }
                   1548:     }
                   1549: 
                   1550: // Figure out if we can do the line in hardware, given that we have a
                   1551: // limited number of bits of precision for the Bresenham terms.
                   1552: //
                   1553: // Remember that one bit has to be kept as a sign bit:
                   1554: 
                   1555:     if ((LONG) dM >= (1L << (cBits - 1)))
                   1556:         return(FALSE);
                   1557: 
                   1558:     fl |= gaflHardwareRound[fl];
                   1559: 
                   1560: /***********************************************************************\
                   1561: * Calculate the error term at pixel 0.
                   1562: \***********************************************************************/
                   1563: 
                   1564:     x = LFLOOR((LONG) M0);
                   1565:     y = LFLOOR((LONG) N0);
                   1566: 
                   1567:     M0 = FXFRAC(M0);
                   1568:     N0 = FXFRAC(N0);
                   1569: 
                   1570: // NOTE NOTE NOTE: If this routine were to handle any line in the 28.4
                   1571: // space, it will overflow its math (the following part requires 36 bits
                   1572: // of precision)!  But we get here for lines that the hardware can handle
                   1573: // (see the expression (dM >= (1L << (cBits - 1))) above?), so if cBits
                   1574: // is less than 28, we're safe.
                   1575: //
                   1576: // If you're going to use this routine to handle all lines in the 28.4
                   1577: // device space, you will HAVE to make sure the math doesn't overflow,
                   1578: // otherwise you won't be NT compliant!  (See lines.cxx for an example
                   1579: // how to do that.  You don't have to worry about this if you simply
                   1580: // default to the strips code for long lines, because those routines
                   1581: // already do the math correctly.)
                   1582: 
                   1583: // Calculate the remainder term [ dM * (N0 + F/2) - M0 * dN ].  Note
                   1584: // that M0 and N0 have at most 4 bits of significance (and if the
                   1585: // arguments are properly ordered, on a 486 each multiply would be no
                   1586: // more than 13 cycles):
                   1587: 
                   1588:     lGamma = (N0 + F/2) * dM - M0 * dN;
                   1589: 
                   1590:     if (fl & HW_Y_ROUND_DOWN)
                   1591:         lGamma--;
                   1592: 
                   1593:     lGamma >>= FLOG2;
                   1594: 
                   1595: /***********************************************************************\
                   1596: * Figure out which pixels are at the ends of the line.
                   1597: \***********************************************************************/
                   1598: 
                   1599: // The toughest part of GIQ is determining the start and end pels.
                   1600: //
                   1601: // Our approach here is to calculate x0 and x1 (the inclusive start
                   1602: // and end columns of the line respectively, relative to our normalized
                   1603: // origin).  Then x1 - x0 + 1 is the number of pels in the line.  The
                   1604: // start point is easily calculated by plugging x0 into our line equation
                   1605: // (which takes care of whether y = 1/2 rounds up or down in value)
                   1606: // getting y0, and then undoing the normalizing flips to get back
                   1607: // into device space.
                   1608: //
                   1609: // We look at the fractional parts of the coordinates of the start and
                   1610: // end points, and call them (M0, N0) and (M1, N1) respectively, where
                   1611: // 0 <= M0, N0, M1, N1 < 16.  We plot (M0, N0) on the following grid
                   1612: // to determine x0:
                   1613: //
                   1614: //   +-----------------------> +x
                   1615: //   |
                   1616: //   | 0                     1
                   1617: //   |     0123456789abcdef
                   1618: //   |
                   1619: //   |   0 ........?xxxxxxx
                   1620: //   |   1 ..........xxxxxx
                   1621: //   |   2 ...........xxxxx
                   1622: //   |   3 ............xxxx
                   1623: //   |   4 .............xxx
                   1624: //   |   5 ..............xx
                   1625: //   |   6 ...............x
                   1626: //   |   7 ................
                   1627: //   |   8 ................
                   1628: //   |   9 ......**........
                   1629: //   |   a ........****...x
                   1630: //   |   b ............****
                   1631: //   |   c .............xxx****
                   1632: //   |   d ............xxxx    ****
                   1633: //   |   e ...........xxxxx        ****
                   1634: //   |   f ..........xxxxxx
                   1635: //   |
                   1636: //   | 2                     3
                   1637: //   v
                   1638: //
                   1639: //   +y
                   1640: //
                   1641: // This grid accounts for the appropriate rounding of GIQ and last-pel
                   1642: // exclusion.  If (M0, N0) lands on an 'x', x0 = 2.  If (M0, N0) lands
                   1643: // on a '.', x0 = 1.  If (M0, N0) lands on a '?', x0 rounds up or down,
                   1644: // depending on what flips have been done to normalize the line.
                   1645: //
                   1646: // For the end point, if (M1, N1) lands on an 'x', x1 =
                   1647: // floor((M0 + dM) / 16) + 1.  If (M1, N1) lands on a '.', x1 =
                   1648: // floor((M0 + dM)).  If (M1, N1) lands on a '?', x1 rounds up or down,
                   1649: // depending on what flips have been done to normalize the line.
                   1650: //
                   1651: // Lines of exactly slope one require a special case for both the start
                   1652: // and end.  For example, if the line ends such that (M1, N1) is (9, 1),
                   1653: // the line has gone exactly through (8, 0) -- which may be considered
                   1654: // to be part of 'x' because of rounding!  So slopes of exactly slope
                   1655: // one going through (8, 0) must also be considered as belonging in 'x'
                   1656: // when an x value of 1/2 is supposed to round up in value.
                   1657: 
                   1658: // Calculate x0, x1:
                   1659: 
                   1660:     N1 = FXFRAC(N0 + dN);
                   1661:     M1 = FXFRAC(M0 + dM);
                   1662: 
                   1663:     x1 = LFLOOR(M0 + dM);
                   1664: 
                   1665: // Line runs left-to-right:
                   1666: 
                   1667: // Compute x1:
                   1668: 
                   1669:     x1--;
                   1670:     if (M1 > 0)
                   1671:     {
                   1672:         if (N1 == 0)
                   1673:         {
                   1674:             if (LROUND(M1, fl & HW_X_ROUND_DOWN))
                   1675:                 x1++;
                   1676:         }
                   1677:         else if (ABS((LONG) (N1 - F/2)) <= (LONG) M1)
                   1678:         {
                   1679:             x1++;
                   1680:         }
                   1681:     }
                   1682: 
                   1683:     if ((fl & (HW_FLIP_SLOPE_ONE | HW_X_ROUND_DOWN))
                   1684:            == (HW_FLIP_SLOPE_ONE | HW_X_ROUND_DOWN))
                   1685:     {
                   1686:     // Have to special-case diagonal lines going through our
                   1687:     // the point exactly equidistant between two horizontal
                   1688:     // pixels, if we're supposed to round x=1/2 down:
                   1689: 
                   1690:         if ((N1 > 0) && (M1 == N1 + 8))
                   1691:             x1--;
                   1692: 
                   1693:         if ((M0 > 0) && (N0 == M0 + 8))
                   1694:         {
                   1695:             x0 = 0;
                   1696:             goto left_to_right_compute_y0;
                   1697:         }
                   1698:     }
                   1699: 
                   1700: // Compute x0:
                   1701: 
                   1702:     x0 = 0;
                   1703:     if (M0 > 0)
                   1704:     {
                   1705:         if (N0 == 0)
                   1706:         {
                   1707:             if (LROUND(M0, fl & HW_X_ROUND_DOWN))
                   1708:                 x0 = 1;
                   1709:         }
                   1710:         else if (ABS((LONG) (N0 - F/2)) <= (LONG) M0)
                   1711:         {
                   1712:             x0 = 1;
                   1713:         }
                   1714:     }
                   1715: 
                   1716: left_to_right_compute_y0:
                   1717: 
                   1718: /***********************************************************************\
                   1719: * Calculate the start pixel.
                   1720: \***********************************************************************/
                   1721: 
                   1722: // We now compute y0 and adjust the error term.  We know x0, and we know
                   1723: // the current formula for the pixels to be lit on the line:
                   1724: //
                   1725: //                     dN * x + lGamma
                   1726: //       y(x) = floor( --------------- )
                   1727: //                           dM
                   1728: //
                   1729: // The remainder of this expression is the new error term at (x0, y0).
                   1730: // Since x0 is going to be either 0 or 1, we don't actually have to do a
                   1731: // multiply or divide to compute y0.  Finally, we subtract dM from the
                   1732: // new error term so that it is in the range [-dM, 0).
                   1733: 
                   1734:     y0      = 0;
                   1735:     lGamma += (dN & (-x0));
                   1736:     lGamma -= dM;
                   1737:     if (lGamma >= 0)
                   1738:     {
                   1739:         y0      = 1;
                   1740:         lGamma -= dM;
                   1741:     }
                   1742: 
                   1743: // Undo our flips to get the start coordinate:
                   1744: 
                   1745:     x += x0;
                   1746:     y += y0;
                   1747: 
                   1748:     if (fl & HW_FLIP_D)
                   1749:     {
                   1750:         register LONG lTmp;
                   1751:         lTmp = x; x = y; y = lTmp;
                   1752:     }
                   1753: 
                   1754:     if (fl & HW_FLIP_V)
                   1755:     {
                   1756:         y = -y;
                   1757:     }
                   1758: 
                   1759:     if (fl & HW_FLIP_H)
                   1760:     {
                   1761:         x = -x;
                   1762:     }
                   1763: 
                   1764: /***********************************************************************\
                   1765: * Return the Bresenham terms:
                   1766: \***********************************************************************/
                   1767: 
                   1768:     pdl->iDir       = gaiDir[fl & HW_FLIP_MASK];
                   1769:     pdl->ptlStart.x = x;
                   1770:     pdl->ptlStart.y = y;
                   1771:     pdl->cPels      = x1 - x0 + 1;  // NOTE: You'll have to check if cPels <= 0!
                   1772:     pdl->dMajor     = dM;
                   1773:     pdl->dMinor     = dN;
                   1774:     pdl->lErrorTerm = lGamma;
                   1775: 
                   1776:     return(TRUE);
                   1777: }
                   1778: 
                   1779: #endif // HARDWAREGIQ

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.