/*
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
*/
/*
 *
 * Graphical routines for drawing polygons.
 *
 */

#ifdef HAVE_CONFIG_H
#include <conf.h>
#endif

#include "u_mem.h"
#include "gr.h"
#include "grdef.h"

//#define USE_POLY_CODE 1

#define MAX_SCAN_LINES 1200

#ifdef USE_POLY_CODE

int y_edge_list[MAX_SCAN_LINES];

void gr_upoly(int nverts, int *vert )
{
	int temp;
	int startx, stopx;  // X coordinates of both ends of current edge.
	int firstx, firsty; // Saved copy of the first vertex to connect later.
	int dx_dy;          // Slope of current edge.
	int miny, maxy;

	int starty, stopy;  // Y coordinates of both ends of current edge.

	int x1, x2, i;

	// Find the min and max rows to clear out the minimun y_edge_list.
	// (Is it worth it?)
	maxy = vert[1];
	miny = vert[1];

	for (i=3; i<(nverts*2); i+=2 )
 {
		if (vert[i]>maxy) maxy=vert[i];
		if (vert[i]<miny) miny=vert[i];
	}

	miny >>= 16;
	miny--;             // -1 to be safe
	maxy >>= 16;
	maxy++;             // +1 to be safe

	// Clear only the part of the y_edge_list that w will be using
	if (miny < 0) miny = 0;
	if (maxy > MAX_SCAN_LINES) maxy = MAX_SCAN_LINES;

	for (i=miny; i<maxy; i++ )
		y_edge_list[i] = -1;

	// Save the first vertex so that we can connect to it at the end.
	firstx = vert[0];
	firsty = vert[1] >> 16;

	do
 {
		nverts--;

		// Get the beginning coordinates of the current edge.
		startx = vert[0];
		starty = vert[1] >> 16;

		// Get the ending coordinates of the current edge.
		if (nverts > 0 ) {
			stopx = vert[2];
			stopy = vert[3] >> 16;
			vert += 2;
		} else  {
			stopx = firstx;     // Last edge, uses first vertex as endpoint
			stopy = firsty;
		}

		if (stopy < starty )    {
			temp = stopy;
			stopy = starty;
			starty = temp;
			temp = stopx;
			stopx = startx;
			startx = temp;
		}

		if (stopy == starty )
	 {
			// Draw a edge going horizontally across screen
			x1 = startx>>16;
			x2 = stopx>>16;

			if (x2 > x1 )
				//gr_uscanline( x1, x2-1, stopy );
				gr_uscanline( x1, x2, stopy );
			else
				//gr_uscanline( x2, x1-1, stopy );
				gr_uscanline( x2, x1, stopy );

		} else {

			dx_dy = (stopx - startx) / (stopy - starty);

			for (; starty < stopy; starty++ )
		 {
				if (y_edge_list[starty]==-1)
					y_edge_list[starty] = startx;
				else    {
					x1 = y_edge_list[starty]>>16;
					x2 = startx>>16;

					if (x2 > x1 )
						//gr_uscanline( x1, x2-1, starty );
						gr_uscanline( x1, x2, starty );
					else
						//gr_uscanline( x2, x1-1, starty );
						gr_uscanline( x2, x1, starty );
				}
				startx += dx_dy;
			}
		}


	} while (nverts > 0);
}


void gr_poly(int nverts, int *vert )
{
	int temp;
	int startx, stopx;  // X coordinates of both ends of current edge.
	int firstx, firsty; // Saved copy of the first vertex to connect later.
	int dx_dy;          // Slope of current edge.
	int miny, maxy;

	int starty, stopy;  // Y coordinates of both ends of current edge.

	int x1, x2, i, j;

	// Find the min and max rows to clear out the minimun y_edge_list.
	// (Is it worth it?)
	maxy = vert[1];
	miny = vert[1];

	j = 0;

	for (i=3; i<(nverts*2); i+=2 )
 {
		if (vert[i]>maxy) {
			if ((maxy=vert[i]) > MAXY) j++;
			//if (j>1) break;
		}

		if (vert[i]<miny) {
			if ((miny=vert[i]) < MINY) j++;
			//if (j>1) break;
		}
	}

	miny >>= 16;
	miny--;         // -1 to be safe
	maxy >>= 16;
	maxy++;          // +1 to be safe

	if (miny < MINY) miny = MINY;
	if (maxy > MAXY) maxy = MAXY+1;

	// Clear only the part of the y_edge_list that w will be using
	for (i=miny; i<maxy; i++ )
	   y_edge_list[i] = -1;

	// Save the first vertex so that we can connect to it at the end.
	firstx = vert[0];
	firsty = vert[1] >> 16;

	do
 {
		nverts--;

		// Get the beginning coordinates of the current edge.
		startx = vert[0];
		starty = vert[1] >> 16;

		// Get the ending coordinates of the current edge.
		if (nverts > 0 ) {
			stopx = vert[2];
			stopy = vert[3] >> 16;
			vert += 2;
		} else  {
			stopx = firstx;     // Last edge, uses first vertex as endpoint
			stopy = firsty;
		}


		if (stopy < starty ) {
			temp = stopy;
			stopy = starty;
			starty = temp;
			temp = stopx;
			stopx = startx;
			startx = temp;
		}

		if (stopy == starty )
	 {
			// Draw a edge going horizontally across screen
			if ((stopy >= MINY) && (stopy <=MAXY )) {
				x1 = startx>>16;
				x2 = stopx>>16;

				if (x1 > x2 ) {
					temp = x2;
					x2 = x1;
					x1 = temp;
				}

				if ((x1 <= MAXX ) && (x2 >= MINX))
			 {
					if (x1 < MINX ) x1 = MINX;
					if (x2 > MAXX ) x2 = MAXX+1;
					//gr_uscanline( x1, x2-1, stopy );
					GrScanLine( x1, x2, stopy );
				}
			}
		} else {

			dx_dy = (stopx - startx) / (stopy - starty);

			if (starty < MINY ) {
				startx = dx_dy*(MINY-starty)+startx;
				starty = MINY;
			}

			if (stopy > MAXY ) {
				stopx = dx_dy*(MAXY-starty)+startx;
				stopy = MAXY+1;
			}

			for (; starty < stopy; starty++ )
		 {   if (y_edge_list[starty]==-1)
					y_edge_list[starty] = startx;
				else {
					x1 = y_edge_list[starty]>>16;
					x2 = startx>>16;

					if (x1 > x2 ) {
						temp = x2;
						x2 = x1;
						x1 = temp;
					}

					if ((x1 <= MAXX ) && (x2 >= MINX))
				 {
						if (x1 < MINX ) x1 = MINX;
						if (x2 > MAXX ) x2 = MAXX+1;
						//gr_uscanline( x1, x2-1, starty );
						GrScanLine( x1, x2, starty );
					}
				}
				startx += dx_dy;
			}
		}


	} while (nverts > 0);
}

#endif
