	/********************************/
	/* Low level graphics routines  */
	/********************************/


#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"

#ifdef PCBNEW
#include "pcbnew.h"
#endif

#ifdef EESCHEMA
#include "program.h"
#include "libcmp.h"
#include "general.h"
#endif

#ifdef CVPCB
#include "pcbnew.h"
#include "cvpcb.h"
#endif

#include "trigo.h"

#ifndef FILLED
#define FILLED 1
#endif

#ifndef EXCHG
#define EXCHG(a,b) { int __temp__ = (a); (a) = (b); (b) = __temp__; }
#endif

/* Variables locales */
static int GRLastMoveToX , GRLastMoveToY;
static int Text_Color = LIGHTGRAY;

static int PenMinWidth = 1;		/* largeur minimum de la plume (DOIT etre > 0)
							(utile pour trace sur imprimante) */
static int ForceBlackPen;	/* si != 0 : traces en noir (utilise pour trace
							sur imprimante */
static int xcliplo = 0,
	ycliplo = 0,
	xcliphi = 2000,
	ycliphi = 2000;	/* coord de la surface de trace */
static int lastcolor = -1;
static int lastwidth = -1;
static wxDC * lastDC = NULL;

/*
	Macro de clipping du trace d'une ligne:
	la ligne (x1,y1 x2,y2) est clippee pour rester dans le cadre
	(xcliplo,ycliplo xcliphi,ycliphi) (variables globales,locales a ce fichier)
	Ceci est necessaire sous WIN95 car les coord de trace
	(bien que en int 32bits) sont tronquees en 16 bits (stupide BG)
*/
#ifndef us
#define us unsigned int
#endif

static inline int USCALE(us arg, us num, us den)
	{
	int ii;

	ii = (int)( ((float) arg * num) / den);
	return( ii );
	}


#ifdef WX_ZOOM
#define GET_ZOOM 1
#else
#define GET_ZOOM ActiveScreen->GetZoom()
#endif

static int inline ZoomValue(int value_to_zoom)
{
int zoom = GET_ZOOM;
	if ( value_to_zoom >= 0 )
		return( (value_to_zoom + (zoom >> 1 ) ) /zoom );
	else
		return( (value_to_zoom - (zoom >> 1 ) ) /zoom );
}	
	
/****************************************/
/* External reference for the mappings. */
/****************************************/
int GRMapX(int x)
{
int coord = x - ActiveScreen->m_DrawOrg.x;

#ifndef WX_ZOOM
 	coord = ZoomValue(coord);
	coord -= ActiveScreen->m_StartVisu.x;
#endif

	return coord;
}

int GRMapY(int y)
{
int coord = y - ActiveScreen->m_DrawOrg.y;

#ifndef WX_ZOOM
 	coord = ZoomValue(coord);
	coord -= ActiveScreen->m_StartVisu.y;
#endif

	return coord;
}



#define WHEN_OUTSIDE return
#define WHEN_INSIDE 

#define CLIP_LINE(x1,y1,x2,y2) \
{\
int temp;\
do {\
	if(x1 > x2) { EXCHG(x1,x2); EXCHG(y1,y2); }\
	if((x2 < xcliplo) || (x1 > xcliphi)) { WHEN_OUTSIDE; }\
	if(y1 < y2)\
		{\
		if((y2 < ycliplo) || (y1 > ycliphi)) { WHEN_OUTSIDE;}\
		if(y1 < ycliplo)\
			{\
			temp = USCALE((x2 - x1),(ycliplo - y1),(y2 - y1));\
			if((x1 += temp) > xcliphi) { WHEN_OUTSIDE; }\
			y1 = ycliplo;\
			WHEN_INSIDE;\
			}\
		if(y2 > ycliphi)\
			{\
			temp = USCALE((x2 - x1),(y2 - ycliphi),(y2 - y1));\
			if((x2 -= temp) < xcliplo) { WHEN_OUTSIDE; }\
			y2 = ycliphi;\
			WHEN_INSIDE;\
			}\
		if(x1 < xcliplo)\
			{\
			temp = USCALE((y2 - y1),(xcliplo - x1),(x2 - x1));\
			y1 += temp; x1 = xcliplo;\
			WHEN_INSIDE;\
			}\
		if(x2 > xcliphi)\
			{\
			temp = USCALE((y2 - y1),(x2 - xcliphi),(x2 - x1));\
			y2 -= temp; x2 = xcliphi;\
			WHEN_INSIDE;\
			}\
		}\
	else\
		{\
		if((y1 < ycliplo) || (y2 > ycliphi)) { WHEN_OUTSIDE; }\
		if(y1 > ycliphi)\
			{\
			temp = USCALE((x2 - x1),(y1 - ycliphi),(y1 - y2));\
			if((x1 += temp) > xcliphi) { WHEN_OUTSIDE; }\
			y1 = ycliphi;\
			WHEN_INSIDE;\
			}\
		if(y2 < ycliplo)\
			{\
			temp = USCALE((x2 - x1),(ycliplo - y2),(y1 - y2));\
			if((x2 -= temp) < xcliplo) { WHEN_OUTSIDE; }\
			y2 = ycliplo;\
			WHEN_INSIDE;\
			}\
		if(x1 < xcliplo)\
			{\
			temp = USCALE((y1 - y2),(xcliplo - x1),(x2 - x1));\
			y1 -= temp; x1 = xcliplo;\
			WHEN_INSIDE;\
			}\
		if(x2 > xcliphi)\
			{\
			temp = USCALE((y1 - y2),(x2 - xcliphi),(x2 - x1));\
			y2 += temp; x2 = xcliphi;\
			WHEN_INSIDE;\
			}\
		}\
	} while(0);\
}

static void WinClipAndDrawLine(EDA_Rect * ClipBox, wxDC * DC,
			int x1, int y1, int x2, int y2,
			int Color, int width = 1 )
{
	GRLastMoveToX = x2;
	GRLastMoveToY = y2;

	if ( ClipBox )
		{
		xcliplo = ClipBox->GetX();
		ycliplo = ClipBox->GetY();
		xcliphi = ClipBox->GetRight();
		ycliphi = ClipBox->GetBottom();

		xcliplo -= width;
		ycliplo -= width;

		xcliphi += width;
		ycliphi += width;

		CLIP_LINE(x1, y1, x2, y2);
		}

	GRSetColorPen(DC, Color, width);
	DC->DrawLine(x1, y1, x2, y2);
}


/* Routine de forcage de la reinit de la plume courante.
	Doit etre appelee par securite apres changement de contexte graphique
	avant tout trace
 */
void GRResetPenAndBrush(wxDC * DC)
{
	lastcolor = -1;
	GRSetBrush(DC, BLACK);	// Force no fill
	lastDC = NULL;
}

/* routine d'ajustage de la largeur mini de plume */
void SetPenMinWidth(int minwidth)
{
	PenMinWidth = minwidth;
	if( PenMinWidth < 1 ) PenMinWidth = 1;
}


/* Routine de changement de couleurs et epaisseur de la plume courante */
void GRSetColorPen(wxDC * DC, int Color , int width)
{
	Color  &= MASKCOLOR;	// Pour 32 couleurs Max

	if(width < PenMinWidth) width = PenMinWidth;

	if( ForceBlackPen && Color != WHITE ) Color = BLACK;

	if( (lastcolor != Color) || (lastwidth != width) || (lastDC != DC ) )
		{
		DrawPen->SetColour(
						ColorRefs[Color].m_Red,
						ColorRefs[Color].m_Green,
						ColorRefs[Color].m_Blue
						);

		DrawPen->SetWidth(width);
		if ( &DC->GetPen() != DrawPen ) DC->SetPen(*DrawPen);
		lastcolor = Color; lastwidth = width; lastDC = DC;
		}
}

/***********************************************/
void GRSetBrush(wxDC * DC, int Color , int fill)
/***********************************************/
{
	Color &= MASKCOLOR;	// Pour 32 couleurs Max
	if( ForceBlackPen && Color != WHITE ) Color = BLACK;
	DrawBrush->SetColour(
						ColorRefs[Color].m_Red,
						ColorRefs[Color].m_Green,
						ColorRefs[Color].m_Blue
						);

	if ( fill ) DrawBrush->SetStyle(wxSOLID);
	else DrawBrush->SetStyle(wxTRANSPARENT);
	if ( &DC->GetBrush() != DrawBrush ) DC->SetBrush(*DrawBrush);
}

/*************************************/
void GRForceBlackPen(bool flagforce )
/*************************************/
{
	ForceBlackPen = flagforce;
}


/************************************************************/
/* routines de controle et positionnement du curseur souris */
/************************************************************/
/* positionne la souris au point de coord pos */
void GRMouseWarp(WinEDA_DrawPanel * panel, const wxPoint& pos)
{
	if( panel == NULL ) return;
	panel->WarpPointer(pos.x, pos.y);
}

/**********************************************/
/* Routine pour selectionner le mode de trace */
/**********************************************/
void GRSetDrawMode(wxDC * DC, int draw_mode)
{
	if( draw_mode & GR_OR ) DC->SetLogicalFunction(wxOR);
	else if( draw_mode & GR_XOR ) DC->SetLogicalFunction(wxXOR);
	else if( draw_mode & GR_NXOR ) DC->SetLogicalFunction(wxEQUIV);
	else DC->SetLogicalFunction(wxCOPY);
}


/*********************************************************************/
void GRPutPixel(EDA_Rect * ClipBox, wxDC * DC, int x, int y, int Color)
/*********************************************************************/
{
	GRSPutPixel(ClipBox, DC, GRMapX(x), GRMapY(y), Color);
}


/********************************************************************/
void GRSPutPixel(EDA_Rect * ClipBox, wxDC * DC, int x, int y, int Color)
/********************************************************************/
{

	if ( ClipBox )	/* suppression des pixels hors ecran */
		{
		if ( x < ClipBox->GetX() ) return;
		if ( y < ClipBox->GetY() ) return;
		if ( x > (ClipBox->GetRight()) ) return;
		if ( y > (ClipBox->GetBottom()) ) return;
		}
	GRSetColorPen(DC, Color );
	DC->DrawPoint( x, y);
}

	/*******************************************/
	/* int GRGetPixel(wxDC * DC, int x, int y) */
	/*******************************************/

int GRGetPixel(wxDC * DC, int x, int y)
{
wxColour colour;
unsigned char r, g, b;
int ii;

	DC->GetPixel( (long)x, (long)y, &colour);
	r = colour.Red();
	b = colour.Blue();
	g = colour.Green();
	for ( ii = 0; ii < NBCOLOR; ii++ )
		{
		if( ( r == ColorRefs[ii].m_Red ) &&
			( g == ColorRefs[ii].m_Green ) &&
			( b == ColorRefs[ii].m_Blue ) )
			break;
		}

	return ii;
}



/****************************************************************************
* Routine to draw a line, in Object spaces.						  *
****************************************************************************/
void GRLine(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2, int Color)
{
	GRSLine(ClipBox, DC, GRMapX(x1), GRMapY(y1), GRMapX(x2), GRMapY(y2), Color);
}

/***************************************************/
/* Routine to draw a Dashed line, in Screen space. */
/***************************************************/
void GRSDashedLine(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2, int Color)
{
	GRLastMoveToX = x2;
	GRLastMoveToY = y2;
	lastcolor = -1;
	DrawPen->SetStyle(wxSHORT_DASH);
	GRSLine(ClipBox, DC, x1, y1, x2, y2, Color);
	lastcolor = -1;
	DrawPen->SetStyle(wxSOLID);
}

void GRSDashedLineTo(EDA_Rect * ClipBox,wxDC * DC, int x2, int y2, int Color)
{
	lastcolor = -1;
	DrawPen->SetStyle(wxSHORT_DASH);
	GRSLine(ClipBox, DC, GRLastMoveToX, GRLastMoveToY, x2, y2, Color);
	lastcolor = -1;
	DrawPen->SetStyle(wxSOLID);
	GRLastMoveToX = x2;
	GRLastMoveToY = y2;
}
/****************************************************************************
* Routine to draw a Dashed line, in Object spaces.						  *
****************************************************************************/
void GRDashedLineTo(EDA_Rect * ClipBox,wxDC * DC,int x2, int y2, int Color)
{
	GRSDashedLineTo(ClipBox, DC, GRMapX(x2), GRMapY(y2), Color);
}

void GRDashedLine(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2, int Color)
{
	GRSDashedLine(ClipBox, DC, GRMapX(x1), GRMapY(y1), GRMapX(x2), GRMapY(y2), Color);
}


/*************************************************/
/* Routine to draw a Bus line, in Object spaces. */
/*************************************************/

void GRBusLine(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2, int Color)
{
	x1 = GRMapX(x1); x2 = GRMapX(x2);
	y1 = GRMapY(y1); y2 = GRMapY(y2);
	GRSBusLine(ClipBox, DC, x1, y1, x2, y2, Color);
}

/****************************************************************
* Routine to draw a Bus Line, in Screen (pixels) space.			 *
****************************************************************************/
void GRSBusLine(EDA_Rect * ClipBox, wxDC * DC, int x1, int y1, int x2, int y2, int Color)
{
	GRSFillCSegm(ClipBox, DC, x1, y1, x2, y2, 3*PenMinWidth, Color);
	GRLastMoveToX = x2;
	GRLastMoveToY = y2;
}


/****************************************************************************
* Routine to move to a new position, in Object space.				*
****************************************************************************/
void GRMoveTo(int x, int y)
{
	GRLastMoveToX = GRMapX(x);
	GRLastMoveToY = GRMapY(y);
}

/*******************************************************/
/* Routine to draw to a new position, in Object space. */
/*******************************************************/
void GRLineTo(EDA_Rect * ClipBox,wxDC * DC, int x, int y, int Color)
{
int GRLineToX, GRLineToY;

	GRLineToX = GRMapX(x); GRLineToY = GRMapY(y);
	GRSLine(ClipBox, DC, GRLastMoveToX, GRLastMoveToY, GRLineToX, GRLineToY, Color);
}

/*************************************************/
/* Routine to draw a Mixed line, in Object space */
/*************************************************/
void GRMixedLine(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2, int Color)
{
	GRSMixedLine(ClipBox, DC, GRMapX(x1), GRMapY(y1), GRMapX(x2), GRMapY(y2), Color);
}

/***********************************************************/
/* Routine to draw a Mixed line, in Screen (Pixels)  space */
/***********************************************************/
void GRSMixedLine(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2, int Color)
{
	DrawPen->SetStyle(wxDOT_DASH);
	GRSLine(ClipBox, DC, x1, y1, x2, y2, Color);
	DrawPen->SetStyle(wxSOLID);
}

/*******************************************************************/
/* Routine to draw a Bus line to a new position, in Object spaces. */
/*******************************************************************/
void GRBusLineTo(EDA_Rect * ClipBox,wxDC * DC, int x, int y, int Color)
{
int GRLineToX, GRLineToY;

	GRLineToX = GRMapX(x); GRLineToY = GRMapY(y);

	GRSBusLine(ClipBox, DC, GRLastMoveToX, GRLastMoveToY, GRLineToX, GRLineToY,
						Color);
	GRLastMoveToX = GRLineToX;
	GRLastMoveToY = GRLineToY;
}

/****************************************************************************
* Routine to move to a new position, in Screen (pixels) space.			*
****************************************************************************/
void GRSMoveTo(int x, int y)
{
	GRLastMoveToX = x;
	GRLastMoveToY = y;
}

/****************************************************************************
* Routine to draw to a new position, in Screen (pixels) space.			*
****************************************************************************/
void GRSLineTo(EDA_Rect * ClipBox, wxDC * DC, int x, int y, int Color)
{
	GRSLine(ClipBox, DC, GRLastMoveToX, GRLastMoveToY, x, y, Color);
	GRLastMoveToX = x; GRLastMoveToY = y;
}

/****************************************************************************
* Routine to draw to a new position, in Screen (pixels) space.			*
****************************************************************************/
void GRSLine(EDA_Rect * ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int Color)
{
	WinClipAndDrawLine(ClipBox, DC, x1, y1, x2, y2, Color);
	GRLastMoveToX = x2; GRLastMoveToY = y2;
}

/****************************************************************************/
/* Routine to move to a new position relative to current one, as in Object	*/
/* space.																	*/
/****************************************************************************/
void GRMoveRel(int x, int y)
{
	GRLastMoveToX += ZoomValue(x);
	GRLastMoveToY += ZoomValue(y);
}

/****************************************************************************
* Routine to line to a new position relative to current one, as in Object	*
* space.									*
****************************************************************************/
void GRLineRel(EDA_Rect * ClipBox,wxDC * DC, int x, int y, int Color)
{
int GRLineToX = GRLastMoveToX,
	GRLineToY = GRLastMoveToY;

	GRLineToX += ZoomValue(x);
	GRLineToY += ZoomValue(y);

	GRSLine(ClipBox, DC, GRLastMoveToX, GRLastMoveToY, GRLineToX, GRLineToY, Color);
}

/****************************************************************************
* Routine to move to a new position relative to current one, as in Screen	*
* space (pixel coords.).							  *
****************************************************************************/
void GRSMoveRel(int x, int y)
{
	GRLastMoveToX += x;
	GRLastMoveToY += y;
}

/****************************************************************************
* Routine to line to a new position relative to current one, as in Screen	*
* space (pixel coords.).							  *
****************************************************************************/
void GRSLineRel(EDA_Rect * ClipBox,wxDC * DC, int x, int y, int Color)
{
long GRLineToX = GRLastMoveToX + x,
	GRLineToY = GRLastMoveToY + y;

	GRSLine(ClipBox, DC, GRLastMoveToX, GRLastMoveToY, GRLineToX, GRLineToY, Color);
	GRLastMoveToX = GRLineToX;
	GRLastMoveToY = GRLineToY;
}

/**************************************************/
/* Routine de trace d'un segment a bouts arrondis */
/* Object space  = real coords.).				  */
/**************************************************/
void GRCSegm(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2,
			int width, int Color)
{
	GRSCSegm(ClipBox, DC, GRMapX(x1), GRMapY(y1), GRMapX(x2), GRMapY(y2),
				ZoomValue(width), Color);
}

/*******************************************************************
* Routine de trace d'un segment (plein) a bouts arrondis in Object *
* space (real coords.).												 *
********************************************************************/
void GRFillCSegm(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2,
			int width, int Color)
{
	GRSFillCSegm(ClipBox, DC, GRMapX(x1), GRMapY(y1), GRMapX(x2), GRMapY(y2),
				ZoomValue(width), Color);
}


	/**********************************************************/
	/* Routine de trace d'un segment (plein) a bouts arrondis */
	/* ( Screen  space = pixel coords.).					  */
	/**********************************************************/

void GRSFillCSegm(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2, int width, int Color)
{
	WinClipAndDrawLine(ClipBox, DC, x1,y1,x2,y2, Color, width);
}


/****************************************************************/
/* Routine de trace d'un segment a bouts arrondis (Mode SKETCH) */
/* Screen space (pixel coords.).								*/
/****************************************************************/
void GRSCSegm(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2, int width, int Color)
{
long rayon, dwx, dwy;
long dx, dy, dwx2, dwy2;
long sx1, sy1, ex1, ey1; /* coord du 1er bord */
long sx2, sy2, ex2, ey2; /* coord du 1eme bord */
bool swap_ends = FALSE;


	GRLastMoveToX = x2;
	GRLastMoveToY = y2;

	if ( ClipBox )
		{
		xcliplo = ClipBox->GetX();
		ycliplo = ClipBox->GetY();
		xcliphi = ClipBox->GetRight();
		ycliphi = ClipBox->GetHeight();

		xcliplo -= width;
		ycliplo -= width;

		xcliphi += width;
		ycliphi += width;

		CLIP_LINE(x1, y1, x2, y2);
		}


	if ( width <= 2 )	/* ligne simple ou epaisse de 2 pixels*/
		{
		GRSetColorPen(DC, Color, width );
		DC->DrawLine(x1, y1, x2, y2);
		return;
		}

	GRSetColorPen(DC, Color );
	GRSetBrush(DC,Color,FALSE);

	rayon = (width+1) >> 1;
	dx = x2 - x1; dy = y2 - y1;
	if ( dx == 0 )  /* segment vertical */
	{
		dwx = rayon;
		if ( dy >= 0 ) dwx = -dwx;
		sx1 = x1 - dwx; sy1 = y1;
		ex1 = x2 - dwx; ey1 = y2;
		DC->DrawLine(sx1 , sy1, ex1, ey1);

		sx2 = x1 + dwx; sy2 = y1;
		ex2 = x2 + dwx; ey2 = y2;
		DC->DrawLine(sx2, sy2, ex2, ey2);
	}

	else if ( dy == 0 ) /* segment horizontal */
	{
		dwy = rayon;
		if ( dx < 0 ) dwy = -dwy;
		sx1 = x1, sy1 = y1 - dwy;
		ex1 = x2; ey1 = y2 - dwy;
		DC->DrawLine(sx1, sy1, ex1 , ey1);

		sx2 = x1; sy2 = y1 + dwy;
		ex2 = x2; ey2 = y2 + dwy;
		DC->DrawLine(sx2, sy2, ex2 , ey2);
	}

	else
	{
		if ( ABS(dx) == ABS(dy) ) /* segment a 45 degre */
		{
			dwx = dwy = ((width * 5)+ 4) / 7;	// = width/2 * 0.707
			if ( dy < 0 )
			{
				if ( dx <= 0 )
				{
					dwx = -dwx; swap_ends = TRUE;
				}
			}
			else
			{
				if( dx > 0 )
				{
					dwy = -dwy; swap_ends = TRUE;
				}
			}
		}

		else
		{
			int delta_angle = ArcTangente(dy, dx);
			dwx = 0; dwy = width;
			RotatePoint( (int*)&dwx, (int*)&dwy, -delta_angle);
		}
		dwx2 = dwx >> 1; dwy2 = dwy >> 1;
		sx1 = x1 - dwx2; sy1 = y1 - dwy2;
		ex1 = x2 - dwx2; ey1 = y2 - dwy2;
		DC->DrawLine(sx1, sy1, ex1, ey1);

		sx2 = x1 + dwx2; sy2 = y1 + dwy2;
		ex2 = x2 + dwx2; ey2 = y2 + dwy2;
		DC->DrawLine(sx2, sy2, ex2, ey2);
	}

	if ( swap_ends )
	{
		DC->DrawArc(sx2, sy2, sx1 , sy1, x1, y1);
		DC->DrawArc(ex1, ey1, ex2, ey2, x2, y2);
	}
	else
	{
		DC->DrawArc(sx1, sy1, sx2 , sy2, x1, y1);
		DC->DrawArc(ex2, ey2, ex1, ey1, x2, y2);
	}
}



static bool IsGRSPolyDrawable( EDA_Rect * ClipBox,int n, int *Points)
{
int ii;
int Xmin, Xmax, Ymin, Ymax;

	Xmin = Xmax = Points[0];
	Ymin = Ymax = Points[1];

	for ( ii = 1; ii < n; ii++) 	// calcul du rectangle d'encadrement
		{
		int jj = ii * 2;
		Xmin = MIN(Xmin,Points[jj]);
		Xmax = MAX(Xmax,Points[jj]);
		Ymin = MIN(Ymin,Points[jj+1]);
		Ymax = MAX(Ymax,Points[jj+1]);
		}

	xcliplo = ClipBox->GetX();
	ycliplo = ClipBox->GetY();
	xcliphi = ClipBox->GetRight();
	ycliphi = ClipBox->GetHeight();

	if ( Xmax < xcliplo ) return FALSE;
	if ( Xmin > xcliphi ) return FALSE;
	if ( Ymax < ycliplo ) return FALSE;
	if ( Ymin > ycliphi ) return FALSE;

	return TRUE;

}
/************************************************************************/
/* Routine to draw a new polyline and fill it if Fill, in screen space. */
/************************************************************************/
void GRSPoly(EDA_Rect * ClipBox,wxDC * DC, int n, int *Points, int Fill,
			int Color, int BgColor)
{
int startx, starty;

	if ( ! IsGRSPolyDrawable(ClipBox, n, Points) ) return;

	GRSetColorPen(DC, Color );

	if( Fill && ( n > 2 ) )
		{
		GRSetBrush(DC, BgColor, FILLED);
		DC->DrawPolygon(n, (wxPoint*)Points);
		}
	else
		{
		startx = Points[n * 2 - 2]; starty = Points[n * 2 - 1];
		GRSetBrush(DC, Color);
		DC->DrawLines(n, (wxPoint*)Points);
		}
}

/************************************************************************/
/* Routine to draw a new polyline (line width = Width), in screen space. */
/************************************************************************/
void GRSPolyLines(EDA_Rect * ClipBox,wxDC * DC, int n, int *Points,
			int Color, int BgColor, int Width)
{
int startx, starty;

	if ( ! IsGRSPolyDrawable(ClipBox, n, Points) ) return;

	GRSetColorPen(DC, Color, Width );

	startx = Points[n * 2 - 2]; starty = Points[n * 2 - 1];
	GRSetBrush(DC, Color);
	DC->DrawLines(n, (wxPoint*)Points);
}

/******************************************************************************/
/* Routine to draw a new closed polyline and fill it if Fill, in screen space */
/******************************************************************************/
void GRSClosedPoly(EDA_Rect * ClipBox,wxDC * DC, int n, int *Points,
	int Fill, int Color, int BgColor)
{
int startx, starty;

	if ( ! IsGRSPolyDrawable(ClipBox, n, Points) ) return;

	GRSetColorPen(DC, Color );

	if( Fill && ( n > 2 ) )
		{
		GRSMoveTo(Points[n * 2 - 2], Points[n * 2 - 1]);
		GRSetBrush(DC, BgColor, FILLED);
		DC->DrawPolygon(n, (wxPoint*) Points, 0, 0,wxODDEVEN_RULE );
		}
	else
		{
		startx = Points[n * 2 - 2]; starty = Points[n * 2 - 1];
		GRSetBrush(DC, BgColor);
		DC->DrawLines(n, (wxPoint*)Points);

		/* Fermeture du polygone */
		if( (startx != Points[0]) || (starty != Points[1]) )
			{
			GRSLine(ClipBox, DC, Points[0], Points[1], startx, starty, Color);
			}
		}
}


/************************************************************************/
/* Routine to draw a new polyline and fill it if Fill, in drawing space. */
/************************************************************************/
void GRPoly(EDA_Rect * ClipBox, wxDC * DC, int n, int *Points,
	int Fill, int Color, int BgColor)
{
int ii, jj;

	for (ii = 0; ii < n; ii++)
		{
		jj = ii << 1;
		Points[jj] = GRMapX(Points[jj]);
		jj++;
		Points[jj] = GRMapY(Points[jj]);
		}
	GRSPoly(ClipBox, DC, n, Points, Fill, Color, BgColor);
}

void GRPolyLines(EDA_Rect * ClipBox, wxDC * DC, int n, int *Points,
		int Color, int BgColor, int width)
{
int ii, jj;

	width = ZoomValue(width);
	
	for (ii = 0; ii < n; ii++)
		{
		jj = ii << 1;
		Points[jj] = GRMapX(Points[jj]);
		jj++;
		Points[jj] = GRMapY(Points[jj]);
		}
	if ( width <= 1 ) GRSPoly(ClipBox, DC, n, Points, 0, Color, BgColor);
	else GRSPolyLines(ClipBox, DC, n, Points, Color, BgColor, width);
}
/**************************************************************************/
/* Routine to draw a closed polyline and fill it if Fill, in object space */
/**************************************************************************/
void GRClosedPoly(EDA_Rect * ClipBox,wxDC * DC, int n, int *Points,
		int Fill, int Color, int BgColor)
{
int ii, jj;

	for (ii = 0; ii < n; ii++)
		{
		jj = ii << 1;
		Points[jj] = GRMapX(Points[jj]);
		jj++;
		Points[jj] = GRMapY(Points[jj]);
		}
	GRSClosedPoly(ClipBox, DC, n, Points, Fill, Color, BgColor);
}

/***********************************************/
/* Routine to draw a circle, in object space. */
/***********************************************/
void GRCircle(EDA_Rect * ClipBox,wxDC * DC, int x, int y, int r, int Color)
{
int cx = GRMapX(x);
int cy = GRMapY(y);
int rayon = ZoomValue(r);

	GRSCircle(ClipBox, DC, cx, cy, rayon, Color );
}

/*****************************************************/
/* Routine to draw a Filled circle, in object space. */
/*****************************************************/
void GRFilledCircle(EDA_Rect * ClipBox,wxDC * DC, int x, int y, int r,
		int Color, int BgColor)
{
	r = ZoomValue(r);
	GRSFilledCircle(ClipBox, DC, GRMapX(x), GRMapY(y), r, Color, BgColor );
}

/***********************************************************/
/* Routine to draw un anneau, epaisseur w, in object space. */
/***********************************************************/
void GRCircle(EDA_Rect * ClipBox,  wxDC * DC, int x, int y, int r, int width, int Color)
{
	r = ZoomValue(r);
	width = ZoomValue(width);
	GRSCircle(ClipBox, DC, GRMapX(x), GRMapY(y), r, width, Color);
}


/***********************************************/
/* Routine to draw a circle, in drawing space. */
/***********************************************/
void GRSCircle(EDA_Rect * ClipBox, wxDC * DC, int x, int y, int r, int Color)
{
int d = r + r;

	/* suppression des cercles hors ecran */
	if ( ClipBox )
		{
		int x0, y0, xm, ym;
		x0 = ClipBox->GetX();
		y0 = ClipBox->GetY();
		xm = ClipBox->GetRight();
		ym = ClipBox->GetBottom();
		if ( x < (x0-r) ) return;
		if ( y < (y0-r) ) return;
		if ( x > (r+xm) ) return;
		if ( y > (r+ym) ) return;
		}

	GRSetColorPen(DC, Color);
	GRSetBrush(DC,Color,FALSE);
	DC->DrawEllipse(x-r,y-r, d, d);
}

/******************************************************/
/* Routine to draw a FILLED circle, in drawing space. */
/******************************************************/
void GRSFilledCircle(EDA_Rect * ClipBox, wxDC * DC, int x, int y, int r,
	int Color, int BgColor)
{
	/* suppression des cercles hors ecran */
	if ( ClipBox )
		{
		int x0, y0, xm, ym;
		x0 = ClipBox->GetX();
		y0 = ClipBox->GetY();
		xm = ClipBox->GetRight();
		ym = ClipBox->GetBottom();
		if ( x < (x0-r) ) return;
		if ( y < (y0-r) ) return;
		if ( x > (r+xm) ) return;
		if ( y > (r+ym) ) return;
		}

	GRSetColorPen(DC, Color );
	GRSetBrush(DC, BgColor, FILLED);
	DC->DrawEllipse(x-r, y-r, r+r, r+r);
}

	/***********************************************************************/
	/* Routine de trace d'un cercle epais ( Screen  space = pixel coords.) */
	/***********************************************************************/

void GRSCircle(EDA_Rect * ClipBox,wxDC * DC, int xc, int yc, int r, int width, int Color)
{
	/* suppression des cercles hors ecran */
	if ( ClipBox )
		{
		int x0, y0, xm, ym;
		x0 = ClipBox->GetX();
		y0 = ClipBox->GetY();
		xm = ClipBox->GetRight();
		ym = ClipBox->GetBottom();
		if ( xc < (x0-r - width) ) return;
		if ( yc < (y0-r - width) ) return;
		if ( xc > (r+xm + width) ) return;
		if ( yc > (r+ym + width) ) return;
		}

	GRSetColorPen(DC, Color, width);
	GRSetBrush(DC, Color, FALSE);
	DC->DrawEllipse(xc-r, yc-r, r+r, r+r);
}


/************************************************/
/* Routine to draw an arc, in USER space.		*/
/* Debut et fin de l'arc donnes par leur coord. */
/************************************************/
void GRArc1(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2,
			int xc, int yc, int Color)
{
	GRSArc1(ClipBox, DC,
			GRMapX(x1), GRMapY(y1), GRMapX(x2), GRMapY(y2),
			GRMapX(xc), GRMapY(yc), Color);
}

/************************************************/
/* Routine to draw an arc, width = width in USER space.		*/
/* Debut et fin de l'arc donnes par leur coord. */
/************************************************/
void GRArc1(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2,
			int xc, int yc, int width, int Color)
{
	GRSArc1(ClipBox, DC,
			GRMapX(x1), GRMapY(y1), GRMapX(x2), GRMapY(y2),
			GRMapX(xc), GRMapY(yc), ZoomValue(width), Color);
}

/************************************************/
/* Routine to draw an arc, in screen space.		*/
/* Debut et fin de l'arc donnes par leur coord. */
/************************************************/
void GRSArc1(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2,
			int xc, int yc, int Color)
{
	/* suppression des cercles hors ecran */
	if ( ClipBox )
		{
		int x0, y0, xm, ym, r;
		x0 = ClipBox->GetX();
		y0 = ClipBox->GetY();
		xm = ClipBox->GetRight();
		ym = ClipBox->GetBottom();
		r = (int)hypot(x1-xc, y1-yc);
		if ( xc < (x0-r) ) return;
		if ( yc < (y0-r) ) return;
		if ( xc > (r+xm) ) return;
		if ( yc > (r+ym) ) return;
		}

	GRSetColorPen(DC, Color );
	GRSetBrush(DC,Color,FALSE);
	DC->DrawArc(x1, y1, x2, y2, xc, yc);
}

/************************************************/
/* Routine to draw an arc, width = width, in screen space.		*/
/* Debut et fin de l'arc donnes par leur coord. */
/************************************************/
void GRSArc1(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2,
			int xc, int yc, int width, int Color)
{
	/* suppression des cercles hors ecran */
	if ( ClipBox )
		{
		int x0, y0, xm, ym, r;
		x0 = ClipBox->GetX();
		y0 = ClipBox->GetY();
		xm = ClipBox->GetRight();
		ym = ClipBox->GetBottom();
		r = (int)hypot(x1-xc, y1-yc);
		if ( xc < (x0-r) ) return;
		if ( yc < (y0-r) ) return;
		if ( xc > (r+xm) ) return;
		if ( yc > (r+ym) ) return;
		}

	GRSetColorPen(DC, Color , width);
	GRSetBrush(DC, Color);
	DC->DrawArc(x1, y1, x2, y2, xc, yc);
}

/********************************************************************/
/* Routine to draw an arc, in screen space.							*/
/* As the Y axe is inverted the Angles should be inverted as well. */
/********************************************************************/
void GRSArc(EDA_Rect * ClipBox,wxDC * DC, int xc, int yc,
			int StAngle, int EndAngle, int r, int Color)
{
int x1, y1, x2, y2;

	/* suppression des cercles hors ecran */
	if ( ClipBox )
		{
		int x0, y0, xm, ym;
		x0 = ClipBox->GetX();
		y0 = ClipBox->GetY();
		xm = ClipBox->GetRight();
		ym = ClipBox->GetBottom();
		if ( xc < (x0-r - 1) ) return;
		if ( yc < (y0-r - 1) ) return;
		if ( xc > (r+xm + 1) ) return;
		if ( yc > (r+ym + 1) ) return;
		}

	x1 = r; y1 = 0;
	RotatePoint( &x1, & y1, EndAngle);

	x2 = r; y2 = 0;
	RotatePoint( &x2, & y2, StAngle);

	GRSetColorPen(DC, Color);
	GRSetBrush(DC,Color,FALSE);
	DC->DrawArc(xc + x1, yc - y1, xc + x2, yc - y2, xc, yc);
}

/********************************************************************/
/* Routine to draw an arc, width = width, in screen space.			*/
/* As the Y axe is inverted the Angles should be inverted as well. */
/********************************************************************/
void GRSArc(EDA_Rect * ClipBox,wxDC * DC, int xc, int yc, int StAngle, int EndAngle,
					int r, int width, int Color)
{
int x1, y1, x2, y2;

	/* suppression des cercles hors ecran */
	if ( ClipBox )
		{
		int x0, y0, xm, ym;
		x0 = ClipBox->GetX();
		y0 = ClipBox->GetY();
		xm = ClipBox->GetRight();
		ym = ClipBox->GetBottom();
		if ( xc < (x0-r - width) ) return;
		if ( yc < (y0-r - width) ) return;
		if ( xc > (r+xm + width) ) return;
		if ( yc > (r+ym + width) ) return;
		}

	x1 = r; y1 = 0;
	RotatePoint( &x1, & y1, EndAngle);

	x2 = r; y2 = 0;
	RotatePoint( &x2, & y2, StAngle);

	GRSetColorPen(DC, Color , width);
	GRSetBrush(DC, Color);
	DC->DrawArc(xc + x1, yc - y1, xc + x2, yc - y2, xc, yc);
}

/********************************************************************/
/* Routine to draw an Filled arc, in screen space.					*/
/* As the Y axes is inverted the Angles should be inverted as well. */
/********************************************************************/
void GRSFilledArc(EDA_Rect * ClipBox,wxDC * DC, int xc, int yc,
				int StAngle, int EndAngle, int r, int Color, int BgColor)
{
int x1, y1, x2, y2;

	/* suppression des cercles hors ecran */
	if ( ClipBox )
		{
		int x0, y0, xm, ym;
		x0 = ClipBox->GetX();
		y0 = ClipBox->GetY();
		xm = ClipBox->GetRight();
		ym = ClipBox->GetBottom();
		if ( xc < (x0-r - 1) ) return;
		if ( yc < (y0-r - 1) ) return;
		if ( xc > (r+xm + 1) ) return;
		if ( yc > (r+ym + 1) ) return;
		}

	x1 = r; y1 = 0;
	RotatePoint( &x1, & y1, EndAngle);

	x2 = r; y2 = 0;
	RotatePoint( &x2, & y2, StAngle);

	GRSetBrush(DC, BgColor, FILLED);
	GRSetColorPen(DC, Color);
	DC->DrawArc(xc + x1, yc - y1, xc + x2, yc - y2, xc, yc);
}

/********************************************************************/
/* Routine to draw a Filled arc, in drawing space.						  */
/* As the Y axes is inverted the Angles should be inverted as well. */
/********************************************************************/
void GRFilledArc(EDA_Rect * ClipBox,wxDC * DC, int x, int y,
		int StAngle, int EndAngle, int r, int Color, int BgColor)
{
	GRSFilledArc(ClipBox, DC, GRMapX(x), GRMapY(y),
					StAngle, EndAngle,
					ZoomValue(r), Color, BgColor);
}

/********************************************************************/
/* Routine to draw an arc, in drawing space.						*/
/* As the Y axes is inverted the Angles should be inverted as well. */
/********************************************************************/
void GRArc(EDA_Rect * ClipBox,wxDC * DC, int xc, int yc, int StAngle,
			int EndAngle, int r, int Color)
{
int x1, y1, x2, y2;

	/* suppression des cercles hors ecran */
	if ( ClipBox )
		{
		int rayon = ZoomValue(r) + 1;
		int x0, y0, xm, ym, x, y;
		x0 = ClipBox->GetX();
		y0 = ClipBox->GetY();
		xm = ClipBox->GetRight();
		ym = ClipBox->GetBottom();
		x = GRMapX(xc); y = GRMapY(yc);
		if ( x < (x0 - rayon) ) return;
		if ( y < (y0 - rayon) ) return;
		if ( x > (xm + rayon) ) return;
		if ( y > (ym + rayon) ) return;
		}

	x1 = r; y1 = 0;
	RotatePoint( &x1, & y1, EndAngle);

	x2 = r; y2 = 0;
	RotatePoint( &x2, & y2, StAngle);

	GRSetColorPen(DC, Color);
	GRSetBrush(DC,Color,FALSE);
	DC->DrawArc(GRMapX(xc + x1), GRMapY(yc - y1),
				GRMapX(xc + x2), GRMapY(yc - y2),
				GRMapX(xc), GRMapY(yc) );
}

/********************************************************************/
/* Routine to draw an arc, width = width, in drawing space.						*/
/* As the Y axes is inverted the Angles should be inverted as well. */
/********************************************************************/
void GRArc(EDA_Rect * ClipBox, wxDC * DC, int x, int y, int StAngle, int EndAngle,
						 int r, int width, int Color)
{
	GRSArc(ClipBox, DC, GRMapX(x), GRMapY(y),
			StAngle, EndAngle,
			ZoomValue(r),
			ZoomValue(width),
			Color);
}

/**************************************************/
/* Routine to draw a Rectangle, in drawing space. */
/**************************************************/
void GRRect(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2, int Color)
{
	x1 = GRMapX(x1); y1 = GRMapY(y1);
	x2 = GRMapX(x2); y2 = GRMapY(y2);

	GRSRect(ClipBox, DC, x1, y1, x2, y2, Color );
}

/************************************************************************************/
void GRFilledRect(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2,
				int Color, int BgColor)
/************************************************************************************/
/* Routine to draw a Rectangle (filled with AreaColor), in drawing space. */
{
	x1 = GRMapX(x1); y1 = GRMapY(y1);
	x2 = GRMapX(x2); y2 = GRMapY(y2);

	GRSFilledRect(ClipBox, DC, x1, y1, x2, y2, Color, BgColor );
}


/*************************************************/
/* Routine to draw a Rectangle, in screen space. */
/*************************************************/
void GRSRect(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2, int Color)
{
	if(x1 > x2) EXCHG(x1,x2);
	if(y1 > y2) EXCHG(y1,y2);

	/* Clipping des coordonnees */
	if ( ClipBox )
		{
		int xmin = ClipBox->GetX();
		int ymin = ClipBox->GetY();
		int xmax = ClipBox->GetRight();
		int ymax = ClipBox->GetBottom();

		if ( x1 > xmax ) return;
		if ( x2 < xmin ) return;
		if ( y1 > ymax ) return;
		if ( y2 < ymin ) return;
		}

	GRSetColorPen(DC, Color );
	if ( (x1 == x2) || (y1 == y2) ) DC->DrawLine(x1, y1, x2, y2);
	else
	{
		GRSetBrush(DC, BLACK );
		DC->DrawRectangle(x1, y1, x2 - x1, y2 - y1);
	}
}


/***************************************************************************************/
void GRSFilledRect(EDA_Rect * ClipBox,wxDC * DC, int x1, int y1, int x2, int y2,
			int Color, int BgColor)
/***************************************************************************************/
/* Routine to draw a Filled Rectangle, in screen space. */
{
	if(x1 > x2) EXCHG(x1,x2);
	if(y1 > y2) EXCHG(y1,y2);
	if ( ClipBox )
		{
		int xmin = ClipBox->GetX();
		int ymin = ClipBox->GetY();
		int xmax = ClipBox->GetRight();
		int ymax = ClipBox->GetBottom();

		if ( x1 > xmax ) return;
		if ( x2 < xmin ) return;
		if ( y1 > ymax ) return;
		if ( y2 < ymin ) return;

		// Clipping des coordonnees
		if ( x1 < xmin )x1 = xmin -1;
		if ( y1 < ymin )y1 = ymin -1;
		if ( x2 > xmax ) x2 = xmax +1;
		if ( y2 > ymax ) y2 = ymax +1;
		}

	GRSetColorPen(DC, Color );
	if ( (x1 == x2) || (y1 == y2) ) DC->DrawLine(x1, y1, x2, y2);
	else
	{
		GRSetBrush(DC, BgColor, FILLED);
		DC->DrawRectangle(x1, y1, x2 - x1, y2 - y1);
	}
}


	/****************************************/
	/* Routines relatives au trace de texte */
	/****************************************/

	/*********************************************/
	/* Routine de selection de la fonte courante */
	/*********************************************/

void GRSetFont(wxDC * DC, wxFont * Font)
{
	DC->SetFont(*Font);
}

	/*********************************************************/
	/* void GRSetTextFgColor(wxFont * Font, int Color) */
	/*********************************************************/

/* Mise a la valeur Color des textes a afficher */
void GRSetTextFgColor(wxDC * DC, int Color)
{
	DC->SetTextForeground(wxColour(
						ColorRefs[Color].m_Red,
						ColorRefs[Color].m_Green,
						ColorRefs[Color].m_Blue)
						);
}

/* Mise a la valeur Color des textes a afficher */
void GRSetTextFgColor(wxDC * DC, wxFont *, int Color)
{
	DC->SetTextForeground(wxColour(
						ColorRefs[Color].m_Red,
						ColorRefs[Color].m_Green,
						ColorRefs[Color].m_Blue)
						);
}


/*****************************************************************************/
void GRGetTextExtent(wxDC * DC, const wxChar * Text, long * width, long * height)
/*****************************************************************************/
/* donne la taille du rectangle d'encadrement du texte Text
*/
{
long w = 0, h = 0;

	if ( Text )
		{
		DC->GetTextExtent(Text, &w, &h );
		}
	if ( width ) *width = w;
	if ( height ) * height = h;
}

	/********************************/
	/* void GRReseTextFgColor() */
	/********************************/

/* Mise a la couleur par defaut des textes a afficher */
void GRResetTextFgColor(wxDC * DC)
{
	GRSetTextFgColor(DC, Text_Color);
}


	/*********************************************************/
	/* void GRSetTextBgColor(wxFont * Font, int Color) */
	/*********************************************************/

/* Mise a la valeur Color du fond pour les textes a afficher */
void GRSetTextBgColor(wxDC * DC, int Color)
{
	Color &= MASKCOLOR;	// Pour 32 couleurs Max
	DC->SetTextBackground(wxColour(
						ColorRefs[Color].m_Red,
						ColorRefs[Color].m_Green,
						ColorRefs[Color].m_Blue)
						);
}

void GRSetTextBgColor(wxDC * DC, wxFont *, int Color)
{
	Color &= MASKCOLOR;	// Pour 32 couleurs Max
	DC->SetTextBackground(wxColour(
						ColorRefs[Color].m_Red,
						ColorRefs[Color].m_Green,
						ColorRefs[Color].m_Blue)
						);
}

