Source/SR_Rasterizers.c

/******************************************************************************
 **                                                                          **
 **     Module:     SR_Rasterizers.c                                         **
 **                                                                          **
 **                                                                          **
 **     Purpose:    Sample Renderer rasterizer routines                      **
 **                                                                          **
 **                                                                          **
 **                                                                          **
 **     Copyright (C) 1996 Apple Computer, Inc.  All rights reserved.        **
 **                                                                          **
 **                                                                          **
 *****************************************************************************/
#include "QD3D.h"
#include "QD3DRenderer.h"
 
#include "SR.h"
#include "SR_Rasterizers.h"
 
 
/******************************************************************************
 **                                                                          **
 **                         Sample Renderer routines                         **
 **                                                                          **
 *****************************************************************************/
 
 
/*===========================================================================*\
 *
 *  Routine:    SRLine_Rasterize_32()
 *
 *  Comments:   2D line rasterizer for 32-bit color frame buffers.
 *
\*===========================================================================*/
 
TQ3Status SRLine_Rasterize_32(
    const struct TSRPrivate *srPrivate, 
    const TQ3Point3D        *pt0, 
    const TQ3Point3D        *pt1, 
    const TQ3ColorRGB        *lineColorRGB)
{
    long            rowBytes;
    unsigned long   *cBuffer;
    float           x0, y0;
    float           x1, y1;
    float           dx, dy;
    long            lx0, ly0;
    long            lx1, ly1;
    long            dlx, dly;
    long            count;
    unsigned long   lineColor;
    
    const TQ3XDrawRegionDescriptor  *descriptor;
    void                            *image;
    
    descriptor = srPrivate->descriptor;
    image = srPrivate->image;
    rowBytes = descriptor->rowBytes;
                
    COLOR_TO_PIXEL(
        lineColor, 
        srPrivate->drawRegion,
        descriptor->pixelType,
        lineColorRGB->r,
        lineColorRGB->g,
        lineColorRGB->b);
 
    /* Load points in device coordinates */
    x0 = pt0->x;
    y0 = pt0->y;
    
    x1 = pt1->x;
    y1 = pt1->y;
    
    dx = x1 - x0;
    dy = y1 - y0;
    
    /* Round points to nearest grid location */
    lx0 = FLOAT_ROUND_TO_LONG_POSITIVE(x0);
    ly0 = FLOAT_ROUND_TO_LONG_POSITIVE(y0);
    lx1 = FLOAT_ROUND_TO_LONG_POSITIVE(x1);
    ly1 = FLOAT_ROUND_TO_LONG_POSITIVE(y1);
    
    dlx = lx1 - lx0;
    dly = ly1 - ly0;
    
    /* Separate X-major and Y-major cases */
    if (ABS(dlx) >= ABS(dly)) {
        long    xStep;
        
        /* X major */
 
        if (dx >= 0.0) {
            /* Left to right */
            xStep = sizeof(long);
            count = lx1 - lx0 + 1;
        } else {
            /* Right to left */
            xStep = -sizeof(long);
            count = lx0 - lx1 + 1;
        }
 
        /* Color buffer address of (lx0, ly0) */
        cBuffer = (unsigned long *)((unsigned char *)image +
                                    ((ly0 * rowBytes) + lx0 * sizeof(long)));
 
        if (ly0 == ly1) {
            /* Special case: horizontal line */
            do {
                *cBuffer = lineColor;
                cBuffer = (unsigned long *)((unsigned char *)cBuffer + xStep);
            } while (--count);
        } else {
            long    fDeltaY;
            long    fError;
            long    yStep;
 
            fDeltaY = (long)
                        ((float)((1 << 24) - 1) * dy / (float) (count - 1));
            
            if (fDeltaY >= 0) {
                /* Top to bottom */
                fError = (long)((y0 - 
                            (float)ly0 + 0.5) * (float)((1 << 24) - 1));
                yStep = rowBytes;
            } else {
                /* Bottom to top */
                fDeltaY = -fDeltaY;
                fError = ((1 << 24) - 1) - 
                            (long)((y0 - (float)ly0 + 0.5) * (float)((1 << 24) - 1));
                yStep = -rowBytes;
            }
 
            do {
                *cBuffer = lineColor;
                cBuffer = (unsigned long *)((unsigned char *)cBuffer + xStep);
                fError += fDeltaY;
                if (fError >= (1 << 24)) {
                    fError = fError - (1 << 24);
                    cBuffer = (unsigned long *)
                                ((unsigned char *)cBuffer + yStep);
                }
            } while (--count);
        }
    } else {
        long    yStep;
        
        /* Y major */
        
        if (dy >= 0.0) {
            /* Top to bottom */
            yStep = rowBytes;
            count = ly1 - ly0 + 1;
        } else {
            /* Bottom to top */
            yStep = -rowBytes;
            count = ly0 - ly1 + 1;
        }
 
        /* Color buffer address of (lx0, ly0) */
        cBuffer = (unsigned long *)((unsigned char *)image +
                                    ((ly0 * rowBytes) + lx0 * sizeof(long)));
 
        if (lx0 == lx1) {
            /* Special case: vertical line */
            do {
                *cBuffer = lineColor;
                cBuffer = (unsigned long *)((unsigned char *)cBuffer + yStep);
            } while (--count);
        } else {
            long    fDeltaX;
            long    fError;
            long    xStep;
 
            fDeltaX = (long)
                        ((float)((1 << 24) - 1) * dx / (float) (count - 1));
            
            if (fDeltaX >= 0) {
                /* Left to right */
                fError = (long)
                            ((x0 - (float)lx0 + 0.5) * (float)((1 << 24) - 1));
                xStep = sizeof(long);
            } else {
                /* Right to left */
                fDeltaX = -fDeltaX;
                fError = ((1 << 24) - 1) - 
                            (long)((x0 - (float)lx0 + 0.5) * (float)((1 << 24) - 1));
                xStep = -sizeof(long);
            }
            
            do {
                *cBuffer = lineColor;
                cBuffer = (unsigned long *)((unsigned char *)cBuffer + yStep);
                fError += fDeltaX;
                if (fError >= (1 << 24)) {
                    fError = fError - (1 << 24);
                    cBuffer = (unsigned long *)
                                ((unsigned char *)cBuffer + xStep);
                }
            } while (--count);
        }
    }
    
    return (kQ3Success);
}
 
 
/*===========================================================================*\
 *
 *  Routine:    SRLine_Rasterize_32_WClip()
 *
 *  Comments:   2D line rasterizer with window clipping for 32-bit color 
 *              frame buffers.
 *
\*===========================================================================*/
 
TQ3Status SRLine_Rasterize_32_WClip(
    const struct TSRPrivate *srPrivate, 
    const TQ3Point3D        *pt0, 
    const TQ3Point3D        *pt1, 
    const TQ3ColorRGB        *lineColorRGB)
{
    unsigned long   *cBuffer;
    float           x0, y0;
    float           x1, y1;
    float           dx, dy;
    long            lx0, ly0;
    long            lx1, ly1;
    long            dlx, dly;
    long            count;
    unsigned long   lineColor;
    long            clipX, clipY;
    TQ3Bitmap       *clipMask = NULL;
    unsigned long   *clipMaskPtr, clipBits, clipXMask;
    unsigned long   clipMaskRowBytes;
    float           upperLeftX, upperLeftY;
    const TQ3XDrawRegionDescriptor  *descriptor;
    void                            *image;
    long            rowBytes;
 
 
    if (Q3XDrawRegion_GetClipMask(srPrivate->drawRegion, &clipMask) == kQ3Failure) {
        return (kQ3Failure);
    }
    if (clipMask == NULL) {
        return (kQ3Failure);
    }
        
    descriptor = srPrivate->descriptor;
    image = srPrivate->image;
    rowBytes = descriptor->rowBytes;
 
    COLOR_TO_PIXEL(
        lineColor, 
        srPrivate->drawRegion,
        descriptor->pixelType,
        lineColorRGB->r,
        lineColorRGB->g,
        lineColorRGB->b);
 
    /* Load points in device coordinates */
    x0 = pt0->x;
    y0 = pt0->y;
    
    x1 = pt1->x;
    y1 = pt1->y;
    
    dx = x1 - x0;
    dy = y1 - y0;
    
    /* Set up window clipping values */
    clipMaskRowBytes = clipMask->rowBytes;
    Q3XDrawRegion_GetDeviceOffsetX(srPrivate->drawRegion, &upperLeftX);
    Q3XDrawRegion_GetDeviceOffsetY(srPrivate->drawRegion, &upperLeftY);
 
    /* Round points to nearest grid location */
    lx0 = FLOAT_ROUND_TO_LONG_POSITIVE(x0);
    ly0 = FLOAT_ROUND_TO_LONG_POSITIVE(y0);
    lx1 = FLOAT_ROUND_TO_LONG_POSITIVE(x1);
    ly1 = FLOAT_ROUND_TO_LONG_POSITIVE(y1);
    
    dlx = lx1 - lx0;
    dly = ly1 - ly0;
    
    /* Separate X-major and Y-major cases */
    if (ABS(dlx) >= ABS(dly)) {
        long    xStep;
        
        /* X major */
 
        if (dx >= 0.0) {
            /* Left to right */
            xStep = sizeof(long);
            count = lx1 - lx0 + 1;
        } else {
            /* Right to left */
            xStep = -sizeof(long);
            count = lx0 - lx1 + 1;
        }
 
        /* Color buffer address of (lx0, ly0) */
        cBuffer = (unsigned long *)((unsigned char *)image +
                                    ((ly0 * rowBytes) + lx0 * sizeof(long)));
 
        /* Window clip mask values */
        clipX = lx0 - upperLeftX;
        clipY = ly0 - upperLeftY;
        clipMaskPtr = (unsigned long *)((unsigned char *)clipMask->image +
                                        (clipY * clipMaskRowBytes) + ((clipX >> 5) << 2));
        clipBits = *clipMaskPtr;
        clipXMask = (unsigned long)(1 << (0x1f - (clipX & 0x1f))); 
        
        if (ly0 == ly1) {
            /* Special case: horizonal line */
            if (xStep > 0 ) {
                /* Left to right */
                do {
                    /* Write visible pixels only */
                    if (clipBits & clipXMask) {
                        *cBuffer = lineColor;
                    }
                    
                    /* Update color buffer and clip mask pointers by x step */
                    cBuffer = (unsigned long *)((unsigned char *)cBuffer + xStep);
                    clipXMask >>= 1;
                    if (clipXMask == 0) {
                        clipMaskPtr++;
                        clipXMask = (unsigned long)(1 << 0x1f);
                        clipBits = *clipMaskPtr;
                    }
                } while (--count);
            } else {
                /* Right to left */
                do {
                    /* Write visible pixels only */
                    if (clipBits & clipXMask) {
                        *cBuffer = lineColor;
                    }
                    
                    /* Update color buffer and clip mask pointers by x step */
                    cBuffer = (unsigned long *)((unsigned char *)cBuffer + xStep);
                    clipXMask <<= 1;
                    if (clipXMask == 0) {
                        clipMaskPtr--;
                        clipXMask = 1;
                        clipBits = *clipMaskPtr;
                    }
                } while (--count);
            }
        } else {
            long    fDeltaY;
            long    fError;
            long    yStep;
            long    clipYStep;
 
            fDeltaY = (long)((float)((1 << 24) - 1) * dy / (float) (count - 1));
            
            if (fDeltaY >= 0) {
                /* Top to bottom */
                fError = (long)((y0 - (float)ly0 + 0.5) * (float)((1 << 24) - 1));
                yStep = rowBytes;
                clipYStep = clipMaskRowBytes;
            } else {
                /* Bottom to top */
                fDeltaY = -fDeltaY;
                fError = ((1 << 24) - 1) - (long)((y0 - (float)ly0 + 0.5) * (float)((1 << 24) - 1));
                yStep = -rowBytes;
                clipYStep = -clipMaskRowBytes;
            }
 
            if (xStep > 0 ) {
                /* Left to right */
                do {
                    /* Write visible pixels only */
                    if (clipBits & clipXMask) {
                        *cBuffer = lineColor;
                    }
                    
                    /* Update color buffer and clip mask pointers by x step */
                    cBuffer = (unsigned long *)((unsigned char *)cBuffer + xStep);
                    clipXMask >>= 1;
                    if (clipXMask == 0) {
                        clipMaskPtr++;
                        clipXMask = (unsigned long)(1 << 0x1f);
                        clipBits = *clipMaskPtr;
                    }
                    
                    /* Update color buffer and clip mask pointers by y step */
                    fError += fDeltaY;
                    if (fError >= (1 << 24)) {
                        fError = fError - (1 << 24);
                        cBuffer = (unsigned long *)((unsigned char *)cBuffer + yStep);
                        clipMaskPtr = (unsigned long *)((unsigned char *)clipMaskPtr + clipYStep);
                        clipBits = *clipMaskPtr;
                    }
                } while (--count);
            } else {
                /* Right to left */
                do {
                    /* Write visible pixels only */
                    if (clipBits & clipXMask) {
                        *cBuffer = lineColor;
                    }
                    
                    /* Update color buffer and clip mask pointers by x step */
                    cBuffer = (unsigned long *)((unsigned char *)cBuffer + xStep);
                    clipXMask <<= 1;
                    if (clipXMask == 0) {
                        clipMaskPtr--;
                        clipXMask = 1;
                        clipBits = *clipMaskPtr;
                    }
                    
                    /* Update color buffer and clip mask pointers by y step */
                    fError += fDeltaY;
                    if (fError >= (1 << 24)) {
                        fError = fError - (1 << 24);
                        cBuffer = (unsigned long *)((unsigned char *)cBuffer + yStep);
                        clipMaskPtr = (unsigned long *)((unsigned char *)clipMaskPtr + clipYStep);
                        clipBits = *clipMaskPtr;
                    }
                } while (--count);
            }
        }
    } else {
        long    yStep;
        long    clipYStep;
        
        /* Y major */
        
        if (dy >= 0.0) {
            /* Top to bottom */
            yStep = rowBytes;
            count = ly1 - ly0 + 1;
            clipYStep = clipMaskRowBytes;
        } else {
            /* Bottom to top */
            yStep = -rowBytes;
            count = ly0 - ly1 + 1;
            clipYStep = -clipMaskRowBytes;
        }
 
        /* Color buffer address of (lx0, ly0) */
        cBuffer = (unsigned long *)((unsigned char *)image +
                                    ((ly0 * rowBytes) + lx0 * sizeof(long)));
 
        /* Window clip mask values */
        clipX = lx0 - upperLeftX;
        clipY = ly0 - upperLeftY;
        clipMaskPtr = (unsigned long *)((unsigned char *)clipMask->image +
                                        (clipY * clipMaskRowBytes) + ((clipX >> 5) << 2));
        clipXMask = (unsigned long)(1 << (0x1f - (clipX & 0x1f))); 
        
        if (lx0 == lx1) {
            /* Special case: vertical line */
            do {
                /* Write visible pixels only */
                if (*clipMaskPtr & clipXMask) {
                    *cBuffer = lineColor;
                }
                
                /* Update color buffer and clip mask pointers by y step */
                cBuffer = (unsigned long *)((unsigned char *)cBuffer + yStep);
                clipMaskPtr = (unsigned long *)((unsigned char *)clipMaskPtr + clipYStep);
            } while (--count);
        } else {
            long    fDeltaX;
            long    fError;
            long    xStep;
 
            fDeltaX = (long)((float)((1 << 24) - 1) * dx / (float) (count - 1));
            
            if (fDeltaX >= 0) {
                /* Left to right */
                fError = (long)((x0 - (float)lx0 + 0.5) * (float)((1 << 24) - 1));
                xStep = sizeof(long);
 
                do {
                    /* Write visible pixels only */
                    if (*clipMaskPtr & clipXMask) {
                        *cBuffer = lineColor;
                    }
                    
                    /* Update color buffer and clip mask pointers by y step */
                    cBuffer = (unsigned long *)((unsigned char *)cBuffer + yStep);
                    clipMaskPtr = (unsigned long *)((unsigned char *)clipMaskPtr + clipYStep);
                    
                    /* Update color buffer and clip mask pointers by x step */
                    fError += fDeltaX;
                    if (fError >= (1 << 24)) {
                        fError = fError - (1 << 24);
                        cBuffer = (unsigned long *)((unsigned char *)cBuffer + xStep);
                        clipXMask >>= 1;
                        if (clipXMask == 0) {
                            clipMaskPtr++;
                            clipXMask = (unsigned long)(1 << 0x1f);
                        }
                    }
                } while (--count);
            } else {
                /* Right to left */
                fDeltaX = -fDeltaX;
                fError = ((1 << 24) - 1) - (long)((x0 - (float)lx0 + 0.5) * 
                            (float)((1 << 24) - 1));
                xStep = -sizeof(long);
 
                do {
                    /* Write visible pixels only */
                    if (*clipMaskPtr & clipXMask) {
                        *cBuffer = lineColor;
                    }
                    
                    /* Update color buffer and clip mask pointers by y step */
                    cBuffer = (unsigned long *)((unsigned char *)cBuffer + yStep);
                    clipMaskPtr = (unsigned long *)((unsigned char *)clipMaskPtr + clipYStep);
                    
                    /* Update color buffer and clip mask pointers by x step */
                    fError += fDeltaX;
                    if (fError >= (1 << 24)) {
                        fError = fError - (1 << 24);
                        cBuffer = (unsigned long *)((unsigned char *)cBuffer + xStep);
                        clipXMask <<= 1;
                        if (clipXMask == 0) {
                            clipMaskPtr--;
                            clipXMask = 1;
                        }
                    }
                } while (--count);
            }
        }
    }
    
    return (kQ3Success);
}
 
 
/*===========================================================================*\
 *
 *  Routine:    SRPoint_Rasterize_32()
 *
 *  Comments:   2D point rasterizer for 32-bit color frame buffers.
 *
\*===========================================================================*/
 
TQ3Status SRPoint_Rasterize_32(
    const struct TSRPrivate *srPrivate, 
    const TQ3Point3D        *pt0, 
    const TQ3ColorRGB        *pointColorRGB)
{
    unsigned long   *cBuffer;
    unsigned long   pointColor;
    
    const TQ3XDrawRegionDescriptor  *descriptor;
    void                            *image;
    long            rowBytes;
 
    
    descriptor = srPrivate->descriptor;
    image = srPrivate->image;
    rowBytes = descriptor->rowBytes;
 
    COLOR_TO_PIXEL(
        pointColor, 
        srPrivate->drawRegion,
        descriptor->pixelType,
        pointColorRGB->r,
        pointColorRGB->g,
        pointColorRGB->b);
 
    cBuffer = (unsigned long *)((unsigned char *)image +
                    ((FLOAT_ROUND_TO_LONG_POSITIVE(pt0->y) * rowBytes) + 
                      FLOAT_ROUND_TO_LONG_POSITIVE(pt0->x) * sizeof(long)));
 
    *cBuffer = pointColor;
    
    return (kQ3Success);
}
 
 
/*===========================================================================*\
 *
 *  Routine:    SRPoint_Rasterize_32_WClip()
 *
 *  Comments:   2D point rasterizer with window clipping for 32-bit color 
 *              frame buffers.
 *
\*===========================================================================*/
 
TQ3Status SRPoint_Rasterize_32_WClip(
    const struct TSRPrivate *srPrivate, 
    const TQ3Point3D        *pt0, 
    const TQ3ColorRGB       *pointColorRGB)
{
    long                longX, longY;
    float               upperLeftX, upperLeftY;
    unsigned long       *cBuffer;
    TQ3Bitmap           *clipMask = NULL;
    unsigned long       *clipMaskPtr, clipBits, clipXMask;
    unsigned long       clipMaskRowBytes;
    unsigned long       pointColor;
    long                rowBytes;
    
    const TQ3XDrawRegionDescriptor  *descriptor;
    void                            *image;
 
    descriptor = srPrivate->descriptor;
    image = srPrivate->image;
    rowBytes = descriptor->rowBytes;
 
    COLOR_TO_PIXEL(
        pointColor, 
        srPrivate->drawRegion,
        descriptor->pixelType,
        pointColorRGB->r,
        pointColorRGB->g,
        pointColorRGB->b);
 
 
    if (Q3XDrawRegion_GetClipMask(srPrivate->drawRegion, &clipMask) == kQ3Failure) {
        return (kQ3Failure);
    }
    if (clipMask == NULL) {
        return (kQ3Failure);
    }
 
    longX = FLOAT_ROUND_TO_LONG_POSITIVE(pt0->x);
    longY = FLOAT_ROUND_TO_LONG_POSITIVE(pt0->y);
 
    cBuffer = (unsigned long *)((unsigned char *)image +
                    (((long)longY * rowBytes) + (long)longX * sizeof(long)));
 
    clipMaskRowBytes = clipMask->rowBytes;
 
    Q3XDrawRegion_GetDeviceOffsetX(srPrivate->drawRegion, &upperLeftX);
    Q3XDrawRegion_GetDeviceOffsetY(srPrivate->drawRegion, &upperLeftY);
    longX -= upperLeftX;
    longY -= upperLeftY;
 
    clipMaskPtr = (unsigned long *)((unsigned char *)clipMask->image +
                        (longY * clipMaskRowBytes) + ((longX >> 5) << 2));
    clipBits = *clipMaskPtr;
    clipXMask = (unsigned long)(1 << (0x1f - (longX & 0x1f))); 
 
    if (clipBits & clipXMask) {
        *cBuffer = pointColor;
    }
    
    return (kQ3Success);
}
 
 
/*===========================================================================*\
 *
 *  Routine:    SRLine_Rasterize_8()
 *
 *  Comments:   
 *
\*===========================================================================*/
 
TQ3Status SRLine_Rasterize_8(
    const struct TSRPrivate *srPrivate, 
    const TQ3Point3D        *pt0, 
    const TQ3Point3D        *pt1, 
    const TQ3ColorRGB       *lineColorRGB)
{
    unsigned char   *cBuffer;
    float           x0, y0;
    float           x1, y1;
    float           dx, dy;
    long            lx0, ly0;
    long            lx1, ly1;
    long            dlx, dly;
    long            count;
    unsigned char   lineColor;
    long            rowBytes;
    const TQ3XDrawRegionDescriptor  *descriptor;
    void            *image;
 
    descriptor = srPrivate->descriptor;
    image = srPrivate->image;
    rowBytes = descriptor->rowBytes;
 
    COLOR_TO_PIXEL(
        lineColor, 
        srPrivate->drawRegion,
        descriptor->pixelType,
        lineColorRGB->r,
        lineColorRGB->g,
                   lineColorRGB->b);
 
    /* Load points in device coordinates */
    x0 = pt0->x;
    y0 = pt0->y;
    
    x1 = pt1->x;
    y1 = pt1->y;
    
    dx = x1 - x0;
    dy = y1 - y0;
    
    /* Round points to nearest grid location */
    lx0 = FLOAT_ROUND_TO_LONG_POSITIVE(x0);
    ly0 = FLOAT_ROUND_TO_LONG_POSITIVE(y0);
    lx1 = FLOAT_ROUND_TO_LONG_POSITIVE(x1);
    ly1 = FLOAT_ROUND_TO_LONG_POSITIVE(y1);
    
    dlx = lx1 - lx0;
    dly = ly1 - ly0;
    
    /* Separate X-major and Y-major cases */
    if (ABS(dlx) >= ABS(dly)) {
        long    xStep;
        
        /* X major */
 
        if (dx >= 0.0) {
            /* Left to right */
            xStep = sizeof(char);
            count = lx1 - lx0 + 1;
        } else {
            /* Right to left */
            xStep = -sizeof(char);
            count = lx0 - lx1 + 1;
        }
 
        /* Color buffer address of (lx0, ly0) */
        cBuffer = (unsigned char *)((unsigned char *)image +
                                    ((ly0 * rowBytes) + lx0 * sizeof(char)));
 
        if (ly0 == ly1) {
            /* Special case: horizonal line */
            do {
                *cBuffer = lineColor;
                cBuffer = (unsigned char *)((unsigned char *)cBuffer + xStep);
            } while (--count);
        } else {
            long    fDeltaY;
            long    fError;
            long    yStep;
 
            fDeltaY = (long)((float)((1 << 24) - 1) * dy / (float) (count - 1));
            
            if (fDeltaY >= 0) {
                /* Top to bottom */
                fError = (long)((y0 - (float)ly0 + 0.5) * (float)((1 << 24) - 1));
                yStep = rowBytes;
            } else {
                /* Bottom to top */
                fDeltaY = -fDeltaY;
                fError = ((1 << 24) - 1) - (long)((y0 - (float)ly0 + 0.5) * (float)((1 << 24) - 1));
                yStep = -rowBytes;
            }
 
            do {
                *cBuffer = lineColor;
                cBuffer = (unsigned char *)((unsigned char *)cBuffer + xStep);
                fError += fDeltaY;
                if (fError >= (1 << 24)) {
                    fError = fError - (1 << 24);
                    cBuffer = (unsigned char *)((unsigned char *)cBuffer + yStep);
                }
            } while (--count);
        }
    } else {
        long    yStep;
        
        /* Y major */
        
        if (dy >= 0.0) {
            /* Top to bottom */
            yStep = rowBytes;
            count = ly1 - ly0 + 1;
        } else {
            /* Bottom to top */
            yStep = -rowBytes;
            count = ly0 - ly1 + 1;
        }
 
        /* Color buffer address of (lx0, ly0) */
        cBuffer = (unsigned char *)((unsigned char *)image +
                                    ((ly0 * rowBytes) + lx0 * sizeof(char)));
 
        if (lx0 == lx1) {
            /* Special case: vertical line */
            do {
                *cBuffer = lineColor;
                cBuffer = (unsigned char *)((unsigned char *)cBuffer + yStep);
            } while (--count);
        } else {
            long    fDeltaX;
            long    fError;
            long    xStep;
 
            fDeltaX = (long)((float)((1 << 24) - 1) * dx / (float) (count - 1));
            
            if (fDeltaX >= 0) {
                /* Left to right */
                fError = (long)((x0 - (float)lx0 + 0.5) * (float)((1 << 24) - 1));
                xStep = sizeof(char);
            } else {
                /* Right to left */
                fDeltaX = -fDeltaX;
                fError = ((1 << 24) - 1) - (long)((x0 - (float)lx0 + 0.5) * (float)((1 << 24) - 1));
                xStep = -sizeof(char);
            }
            
            do {
                *cBuffer = lineColor;
                cBuffer = (unsigned char *)((unsigned char *)cBuffer + yStep);
                fError += fDeltaX;
                if (fError >= (1 << 24)) {
                    fError = fError - (1 << 24);
                    cBuffer = (unsigned char *)((unsigned char *)cBuffer + xStep);
                }
            } while (--count);
        }
    }
 
    return (kQ3Success);
}
 
 
/*===========================================================================*\
 *
 *  Routine:    SRLine_Rasterize_8_WClip()
 *
 *  Comments:   
 *
\*===========================================================================*/
 
TQ3Status SRLine_Rasterize_8_WClip(
    const struct TSRPrivate *srPrivate, 
    const TQ3Point3D        *pt0, 
    const TQ3Point3D        *pt1, 
    const TQ3ColorRGB       *lineColorRGB)
{
    unsigned char   *cBuffer;
    float           x0, y0;
    float           x1, y1;
    float           dx, dy;
    long            lx0, ly0;
    long            lx1, ly1;
    long            dlx, dly;
    long            count;
    unsigned char   lineColor;
    long            clipX, clipY;
    TQ3Bitmap       *clipMask = NULL;
    unsigned long   *clipMaskPtr, clipBits, clipXMask;
    unsigned long   clipMaskRowBytes;
    float           upperLeftX, upperLeftY;
 
    long            rowBytes;
    const TQ3XDrawRegionDescriptor  *descriptor;
    void                            *image;
 
    if (Q3XDrawRegion_GetClipMask(srPrivate->drawRegion, &clipMask) == kQ3Failure) {
        return (kQ3Failure);
    }
    if (clipMask == NULL) {
        return (kQ3Failure);
    }
 
    descriptor = srPrivate->descriptor;
    image = srPrivate->image;
    rowBytes = descriptor->rowBytes;
    
    COLOR_TO_PIXEL(
        lineColor, 
        srPrivate->drawRegion,
        descriptor->pixelType,
        lineColorRGB->r,
        lineColorRGB->g,
        lineColorRGB->b);
 
    /* Load points in device coordinates */
    x0 = pt0->x;
    y0 = pt0->y;
    
    x1 = pt1->x;
    y1 = pt1->y;
    
    dx = x1 - x0;
    dy = y1 - y0;
    
    /* Set up window clipping values */
    clipMaskRowBytes = clipMask->rowBytes;
    Q3XDrawRegion_GetDeviceOffsetX(srPrivate->drawRegion, &upperLeftX);
    Q3XDrawRegion_GetDeviceOffsetY(srPrivate->drawRegion, &upperLeftY);
 
    /* Round points to nearest grid location */
    lx0 = FLOAT_ROUND_TO_LONG_POSITIVE(x0);
    ly0 = FLOAT_ROUND_TO_LONG_POSITIVE(y0);
    lx1 = FLOAT_ROUND_TO_LONG_POSITIVE(x1);
    ly1 = FLOAT_ROUND_TO_LONG_POSITIVE(y1);
    
    dlx = lx1 - lx0;
    dly = ly1 - ly0;
    
    /* Separate X-major and Y-major cases */
    if (ABS(dlx) >= ABS(dly)) {
        long    xStep;
        
        /* X major */
 
        if (dx >= 0.0) {
            /* Left to right */
            xStep = sizeof(char);
            count = lx1 - lx0 + 1;
        } else {
            /* Right to left */
            xStep = -sizeof(char);
            count = lx0 - lx1 + 1;
        }
 
        /* Color buffer address of (lx0, ly0) */
        cBuffer = (unsigned char *)((unsigned char *)image +
                                    ((ly0 * rowBytes) + lx0 * sizeof(char)));
 
        /* Window clip mask values */
        clipX = lx0 - upperLeftX;
        clipY = ly0 - upperLeftY;
        clipMaskPtr = (unsigned long *)((unsigned char *)clipMask->image +
                                        (clipY * clipMaskRowBytes) + ((clipX >> 5) << 2));
        clipBits = *clipMaskPtr;
        clipXMask = (unsigned long)(1 << (0x1f - (clipX & 0x1f))); 
        
        if (ly0 == ly1) {
            /* Special case: horizonal line */
            if (xStep > 0 ) {
                /* Left to right */
                do {
                    /* Write visible pixels only */
                    if (clipBits & clipXMask) {
                        *cBuffer = lineColor;
                    }
                    
                    /* Update color buffer and clip mask pointers by x step */
                    cBuffer = (unsigned char *)((unsigned char *)cBuffer + xStep);
                    clipXMask >>= 1;
                    if (clipXMask == 0) {
                        clipMaskPtr++;
                        clipXMask = (unsigned long)(1 << 0x1f);
                        clipBits = *clipMaskPtr;
                    }
                } while (--count);
            } else {
                /* Right to left */
                do {
                    /* Write visible pixels only */
                    if (clipBits & clipXMask) {
                        *cBuffer = lineColor;
                    }
                    
                    /* Update color buffer and clip mask pointers by x step */
                    cBuffer = (unsigned char *)((unsigned char *)cBuffer + xStep);
                    clipXMask <<= 1;
                    if (clipXMask == 0) {
                        clipMaskPtr--;
                        clipXMask = 1;
                        clipBits = *clipMaskPtr;
                    }
                } while (--count);
            }
        } else {
            long    fDeltaY;
            long    fError;
            long    yStep;
            long    clipYStep;
 
            fDeltaY = (long)((float)((1 << 24) - 1) * dy / (float) (count - 1));
            
            if (fDeltaY >= 0) {
                /* Top to bottom */
                fError = (long)((y0 - (float)ly0 + 0.5) * (float)((1 << 24) - 1));
                yStep = rowBytes;
                clipYStep = clipMaskRowBytes;
            } else {
                /* Bottom to top */
                fDeltaY = -fDeltaY;
                fError = ((1 << 24) - 1) - (long)((y0 - (float)ly0 + 0.5) * (float)((1 << 24) - 1));
                yStep = -rowBytes;
                clipYStep = -clipMaskRowBytes;
            }
 
            if (xStep > 0 ) {
                /* Left to right */
                do {
                    /* Write visible pixels only */
                    if (clipBits & clipXMask) {
                        *cBuffer = lineColor;
                    }
                    
                    /* Update color buffer and clip mask pointers by x step */
                    cBuffer = (unsigned char *)((unsigned char *)cBuffer + xStep);
                    clipXMask >>= 1;
                    if (clipXMask == 0) {
                        clipMaskPtr++;
                        clipXMask = (unsigned long)(1 << 0x1f);
                        clipBits = *clipMaskPtr;
                    }
                    
                    /* Update color buffer and clip mask pointers by y step */
                    fError += fDeltaY;
                    if (fError >= (1 << 24)) {
                        fError = fError - (1 << 24);
                        cBuffer = (unsigned char *)((unsigned char *)cBuffer + yStep);
                        clipMaskPtr = (unsigned long *)((unsigned char *)clipMaskPtr + clipYStep);
                        clipBits = *clipMaskPtr;
                    }
                } while (--count);
            } else {
                /* Right to left */
                do {
                    /* Write visible pixels only */
                    if (clipBits & clipXMask) {
                        *cBuffer = lineColor;
                    }
                    
                    /* Update color buffer and clip mask pointers by x step */
                    cBuffer = (unsigned char *)((unsigned char *)cBuffer + xStep);
                    clipXMask <<= 1;
                    if (clipXMask == 0) {
                        clipMaskPtr--;
                        clipXMask = 1;
                        clipBits = *clipMaskPtr;
                    }
                    
                    /* Update color buffer and clip mask pointers by y step */
                    fError += fDeltaY;
                    if (fError >= (1 << 24)) {
                        fError = fError - (1 << 24);
                        cBuffer = (unsigned char *)((unsigned char *)cBuffer + yStep);
                        clipMaskPtr = (unsigned long *)((unsigned char *)clipMaskPtr + clipYStep);
                        clipBits = *clipMaskPtr;
                    }
                } while (--count);
            }
        }
    } else {
        long    yStep;
        long    clipYStep;
        
        /* Y major */
        
        if (dy >= 0.0) {
            /* Top to bottom */
            yStep = rowBytes;
            count = ly1 - ly0 + 1;
            clipYStep = clipMaskRowBytes;
        } else {
            /* Bottom to top */
            yStep = -rowBytes;
            count = ly0 - ly1 + 1;
            clipYStep = -clipMaskRowBytes;
        }
 
        /* Color buffer address of (lx0, ly0) */
        cBuffer = (unsigned char *)((unsigned char *)image +
                                    ((ly0 * rowBytes) + lx0 * sizeof(char)));
 
        /* Window clip mask values */
        clipX = lx0 - upperLeftX;
        clipY = ly0 - upperLeftY;
        clipMaskPtr = (unsigned long *)((unsigned char *)clipMask->image +
                                        (clipY * clipMaskRowBytes) + ((clipX >> 5) << 2));
        clipXMask = (unsigned long)(1 << (0x1f - (clipX & 0x1f))); 
        
        if (lx0 == lx1) {
            /* Special case: vertical line */
            do {
                /* Write visible pixels only */
                if (*clipMaskPtr & clipXMask) {
                    *cBuffer = lineColor;
                }
                
                /* Update color buffer and clip mask pointers by y step */
                cBuffer = (unsigned char *)((unsigned char *)cBuffer + yStep);
                clipMaskPtr = (unsigned long *)((unsigned char *)clipMaskPtr + clipYStep);
            } while (--count);
        } else {
            long    fDeltaX;
            long    fError;
            long    xStep;
 
            fDeltaX = (long)((float)((1 << 24) - 1) * dx / (float) (count - 1));
            
            if (fDeltaX >= 0) {
                /* Left to right */
                fError = (long)((x0 - (float)lx0 + 0.5) * (float)((1 << 24) - 1));
                xStep = sizeof(char);
 
                do {
                    /* Write visible pixels only */
                    if (*clipMaskPtr & clipXMask) {
                        *cBuffer = lineColor;
                    }
                    
                    /* Update color buffer and clip mask pointers by y step */
                    cBuffer = (unsigned char *)((unsigned char *)cBuffer + yStep);
                    clipMaskPtr = (unsigned long *)((unsigned char *)clipMaskPtr + clipYStep);
                    
                    /* Update color buffer and clip mask pointers by x step */
                    fError += fDeltaX;
                    if (fError >= (1 << 24)) {
                        fError = fError - (1 << 24);
                        cBuffer = (unsigned char *)((unsigned char *)cBuffer + xStep);
                        clipXMask >>= 1;
                        if (clipXMask == 0) {
                            clipMaskPtr++;
                            clipXMask = (unsigned long)(1 << 0x1f);
                        }
                    }
                } while (--count);
            } else {
                /* Right to left */
                fDeltaX = -fDeltaX;
                fError = ((1 << 24) - 1) - (long)((x0 - (float)lx0 + 0.5) * (float)((1 << 24) - 1));
                xStep = -sizeof(char);
 
                do {
                    /* Write visible pixels only */
                    if (*clipMaskPtr & clipXMask) {
                        *cBuffer = lineColor;
                    }
                    
                    /* Update color buffer and clip mask pointers by y step */
                    cBuffer = (unsigned char *)((unsigned char *)cBuffer + yStep);
                    clipMaskPtr = (unsigned long *)((unsigned char *)clipMaskPtr + clipYStep);
                    
                    /* Update color buffer and clip mask pointers by x step */
                    fError += fDeltaX;
                    if (fError >= (1 << 24)) {
                        fError = fError - (1 << 24);
                        cBuffer = (unsigned char *)((unsigned char *)cBuffer + xStep);
                        clipXMask <<= 1;
                        if (clipXMask == 0) {
                            clipMaskPtr--;
                            clipXMask = 1;
                        }
                    }
                } while (--count);
            }
        }
    }
 
    return (kQ3Success);
}
 
 
/*===========================================================================*\
 *
 *  Routine:    SRPoint_Rasterize_8()
 *
 *  Comments:   
 *
\*===========================================================================*/
 
TQ3Status SRPoint_Rasterize_8(
    const struct TSRPrivate *srPrivate, 
    const TQ3Point3D        *pt0, 
    const TQ3ColorRGB       *pointColorRGB)
{
    unsigned char   *cBuffer;
    unsigned char   pointColor;
    long                            rowBytes;
    const TQ3XDrawRegionDescriptor  *descriptor;
    void                            *image;
 
    descriptor = srPrivate->descriptor;
    image = srPrivate->image;
    rowBytes = descriptor->rowBytes;
 
    COLOR_TO_PIXEL(
        pointColor, 
        srPrivate->drawRegion,
        descriptor->pixelType,
        pointColorRGB->r,
        pointColorRGB->g,
        pointColorRGB->b);
 
    cBuffer = (unsigned char *)((unsigned char *)image +
        ((FLOAT_ROUND_TO_LONG_POSITIVE(pt0->y) * rowBytes) + 
          FLOAT_ROUND_TO_LONG_POSITIVE(pt0->x) * sizeof(char)));
 
    *cBuffer = (unsigned char)pointColor;
 
    return (kQ3Success);
}
 
 
/*===========================================================================*\
 *
 *  Routine:    SRPoint_Rasterize_8_WClip()
 *
 *  Comments:   
 *
\*===========================================================================*/
 
TQ3Status SRPoint_Rasterize_8_WClip(
    const struct TSRPrivate *srPrivate, 
    const TQ3Point3D        *pt0, 
    const TQ3ColorRGB        *pointColorRGB)
{
    long            longX, longY;
    float           upperLeftX, upperLeftY;
    unsigned char   *cBuffer;
    TQ3Bitmap       *clipMask = NULL;
    unsigned long   *clipMaskPtr, clipBits, clipXMask;
    unsigned long   clipMaskRowBytes;
    unsigned char   pointColor;
    
    long                            rowBytes;
    const TQ3XDrawRegionDescriptor  *descriptor;
    void                            *image;
 
 
    if (Q3XDrawRegion_GetClipMask(srPrivate->drawRegion, &clipMask) == kQ3Failure) {
        return (kQ3Failure);
    }
    if (clipMask == NULL) {
        return (kQ3Failure);
    }
 
    descriptor = srPrivate->descriptor;
    image = srPrivate->image;
    rowBytes = descriptor->rowBytes;
 
    COLOR_TO_PIXEL(
        pointColor,
        srPrivate->drawRegion,
        descriptor->pixelType,
        pointColorRGB->r,
        pointColorRGB->g,
        pointColorRGB->b);
 
    longX = FLOAT_ROUND_TO_LONG_POSITIVE(pt0->x);
    longY = FLOAT_ROUND_TO_LONG_POSITIVE(pt0->y);
 
    cBuffer = (unsigned char *)((unsigned char *)image +
        (((long)longY * rowBytes) + (long)longX * sizeof(char)));
 
    clipMaskRowBytes = clipMask->rowBytes;
 
    Q3XDrawRegion_GetDeviceOffsetX(srPrivate->drawRegion, &upperLeftX);
    Q3XDrawRegion_GetDeviceOffsetY(srPrivate->drawRegion, &upperLeftY);
    longX -= upperLeftX;
    longY -= upperLeftY;
 
    clipMaskPtr = (unsigned long *)((unsigned char *)clipMask->image +
        (longY * clipMaskRowBytes) + ((longX >> 5) << 2));
    clipBits = *clipMaskPtr;
    clipXMask = (unsigned long)(1 << (0x1F - (longX & 0x1F))); 
 
    if (clipBits & clipXMask) {
        *cBuffer = (unsigned char)pointColor;
    }
 
    return (kQ3Success);
}
 
 
/*===========================================================================*\
 *
 *  Routine:    SRLine_Rasterize_Null()
 *
 *  Comments:   
 *
\*===========================================================================*/
 
TQ3Status SRLine_Rasterize_Null(
    const struct TSRPrivate *srPrivate, 
    const TQ3Point3D        *pt0, 
    const TQ3Point3D        *pt1, 
    const TQ3ColorRGB       *lineColorRGB)
{
    UNUSED(srPrivate);
    UNUSED(pt0);
    UNUSED(pt1);
    UNUSED(lineColorRGB);
 
    return (kQ3Success);
}
 
 
/*===========================================================================*\
 *
 *  Routine:    SRPoint_Rasterize_Null()
 *
 *  Comments:   
 *
\*===========================================================================*/
 
TQ3Status SRPoint_Rasterize_Null(
    const struct TSRPrivate *srPrivate, 
    const TQ3Point3D        *pt0, 
    const TQ3ColorRGB       *pointColorRGB)
{
    UNUSED(srPrivate);
    UNUSED(pt0);
    UNUSED(pointColorRGB);
 
    return (kQ3Success);
}
 
 
/*===========================================================================*\
 *
 *  Routine:    SRMarker_Rasterize_Null()
 *
 *  Comments:   
 *
\*===========================================================================*/
 
TQ3Status SRMarker_Rasterize_Null(
    const struct TSRPrivate     *srPrivate, 
    const TQ3Point3D            *pt0, 
    const TSRMarkerRasterData   *bitmap, 
    const TQ3ColorRGB           *pointColorRGB)
{
    UNUSED(srPrivate);
    UNUSED(pt0);
    UNUSED(bitmap);
    UNUSED(pointColorRGB);
 
    return (kQ3Success);
}
 
 
/*===========================================================================*\
 *
 *  Routine:    SRPixmapMarker_Rasterize_Null()
 *
 *  Comments:   
 *
\*===========================================================================*/
 
TQ3Status SRPixmapMarker_Rasterize_Null(
    const struct TSRPrivate     *srPrivate, 
    const TQ3Point3D                *pt0, 
    const TSRPixmapMarkerRasterData *pixmap,
    const TQ3ColorRGB               *highlightColor)
{
    UNUSED(srPrivate);
    UNUSED(pt0);
    UNUSED(pixmap);
    UNUSED(highlightColor);
 
    return (kQ3Success);
}