/**************************************************************************

    TRI.CPP - Simple triangle rasterizer

 **************************************************************************/
/**************************************************************************

    (C) Copyright 1995-1996 Microsoft Corp.  All rights reserved.

    You have a royalty-free right to use, modify, reproduce and 
    distribute the Sample Files (and/or any modified version) in 
    any way you find useful, provided that you agree that 
    Microsoft has no warranty obligations or liability for any 
    Sample Application Files which are modified. 

 **************************************************************************/

#include <windows.h>
#include "Fixed.h"

#define SWAP(x,y)   ((x)^=(y)^=(x)^=(y))
#define SWAPPT(a,b) (SWAP(a.y,b.y), SWAP(a.x,b.x))

/**************************************************************************

    FillScan8

    fill a scan from x0 to x1 (inclusive) with color c

    does optimal DWORD writes, making sure to stay aligned so
    it is safe for video memory.

 **************************************************************************/
inline void FillScan8(BYTE *p, int x0, int x1, DWORD c)
{
    int dx;
    int z;

    dx = x1-x0+1;
    p += x0;

    if (dx > 4)
    {
        if (z = (DWORD)p & 0x03)
        {
            while (z++ < 4)
            {
                *p++ = (BYTE)c;
                dx--;
            }
        }

        while (dx >= 4)
        {
            *((DWORD*)p) = c;
            p += 4;
            dx -= 4;
        }
    }

    while (dx-- > 0)
    {
        *p++ = (BYTE)c;
    }
}

/**************************************************************************

    Triangle8

    rasterize a solid color triangle into a 8bpp memory buffer.

    NOTE this code does no clipping you better pass

    rasterizes a solid color triangle into a memory buffer with any pitch
    also is careful to always write DWORD aligned, so it is safe to be
    used on video memory (and faster too...)

 **************************************************************************/

void Triangle8(BYTE *p, int next_scan, POINT P0, POINT P1, POINT P2, DWORD c)
{
    Fixed   d,d0;
    Fixed   x,x0;
    int     y;

    //
    // expand the color to a DWORD
    //
    c |= c<<8;
    c |= c<<16;

    //
    //  sort points so P0.y <= P1.y <= P2.y
    //
    if (P0.y > P1.y) SWAPPT(P0,P1);
    if (P1.y > P2.y) SWAPPT(P1,P2);
    if (P0.y > P1.y) SWAPPT(P0,P1);

    //
    //  check for quick out?
    //
    if (P2.y - P0.y == 0)
    {
        return;
    }

    //
    //  compute "long" side walk from P0 to P2
    //
    d = (Fixed)(P2.x - P0.x) / (Fixed)(P2.y - P0.y);

    x  = P0.x;
    y  = P0.y;
    p += P0.y * next_scan;   // point p to correct scan.

    //
    //  do the top
    //
    if (P0.y < P1.y)
    {
        d0 = (Fixed)(P1.x - P0.x) / (Fixed)(P1.y - P0.y);
        x0 = P0.x;

        //
        // check for left or right fill
        //
        if (d < d0)
        {
            while (y < P1.y)
            {
                FillScan8(p, x, x0, c);
                y++;
                p  += next_scan;
                x  += d;
                x0 += d0;
            }
        }
        else
        {
            while (y < P1.y)
            {
                FillScan8(p, x0, x, c);
                y++;
                p  += next_scan;
                x  += d;
                x0 += d0;
            }
        }
    }

    //
    // do the bottom.
    //
    
    if (P2.y - P1.y == 0)
    {
        return;
    }

    d0 = (Fixed)(P2.x - P1.x) / (Fixed)(P2.y - P1.y);
    x0 = P1.x;

    //
    // check for left or right fill
    //
    if (x < x0)
    {
        while (y < P2.y)
        {
            FillScan8(p, x, x0, c);
            y++;
            p  += next_scan;
            x  += d;
            x0 += d0;
        }
    }
    else
    {
        while (y < P2.y)
        {
            FillScan8(p, x0, x, c);
            y++;
            p  += next_scan;
            x  += d;
            x0 += d0;
        }
    }
}
