/********************************/ /* 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 true; #define WHEN_INSIDE /** * Function clip_line * @return bool - true when WHEN_OUTSIDE fires, else false. */ static inline bool clip_line( int& x1, int& y1, int& x2, int& y2 ) { int temp; 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; } } return false; } 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 ) ); }