32 #include <math_for_graphics.h> 33 #include <wx/graphics.h> 65 #define DEBUG_DUMP_CLIP_ERROR_COORDS 0 // Set to 1 to dump clip algorithm errors. 66 #define DEBUG_DUMP_CLIP_COORDS 0 // Set to 1 to dump clipped coordinates. 80 int x2,
int y2,
int aWidth,
COLOR4D aColor,
81 wxPenStyle aStyle = wxPENSTYLE_SOLID );
107 if(
ClipLine( &clipbox, x1, y1, x2, y2 ) )
111 DC->DrawLine( x1, y1, x2, y2 );
133 wxDash dots[2] = { 1, 3 };
137 width = DC->DeviceToLogicalXRel( 1 );
142 const wxPen& curr_pen = DC->GetPen();
144 if( !curr_pen.IsOk() || curr_pen.GetColour() != Color.ToColour()
145 || curr_pen.GetWidth() != width
146 || curr_pen.GetStyle() != style )
149 pen.SetColour( Color.ToColour() );
150 if( style == wxPENSTYLE_DOT )
152 style = wxPENSTYLE_USER_DASH;
153 pen.SetDashes( 2, dots );
155 pen.SetWidth( width );
156 pen.SetStyle( style );
164 DC->SetPen( curr_pen );
179 brush.SetColour( Color.ToColour() );
182 brush.SetStyle( wxBRUSHSTYLE_SOLID );
184 brush.SetStyle( wxBRUSHSTYLE_TRANSPARENT );
186 DC->SetBrush( brush );
217 if( ClipBox && !ClipBox->
Contains( x, y ) )
221 DC->DrawPoint( x, y );
245 void GRLine(
EDA_RECT* aClipBox, wxDC* aDC, wxPoint aStart, wxPoint aEnd,
int aWidth,
COLOR4D aColor, wxPenStyle aStyle )
247 GRLine( aClipBox, aDC, aStart.x, aStart.y, aEnd.x, aEnd.y, aWidth, aColor, aStyle );
291 aClipBox->
Inflate( aWidth / 2 );
293 for(
unsigned i = 0; i < aLines.size(); i += 2 )
295 int x1 = aLines[i].x;
296 int y1 = aLines[i].y;
297 int x2 = aLines[i + 1].x;
298 int y2 = aLines[i + 1].y;
299 if( ( aClipBox ==
NULL ) || !
ClipLine( aClipBox, x1, y1, x2, y2 ) )
300 aDC->DrawLine( x1, y1, x2, y2 );
303 GRMoveTo( aLines[aLines.size() - 1].x, aLines[aLines.size() - 1].y );
311 int width,
int aPenSize,
COLOR4D Color )
321 if(
ClipLine( &clipbox, x1, y1, x2, y2 ) )
329 DC->DrawLine( x1, y1, x2, y2 );
336 int radius = (width + 1) >> 1;
342 wxPoint org( x1, y1);
343 int len = (int) hypot( dx, dy );
346 int slx = DC->DeviceToLogicalX( 1 ) - DC->DeviceToLogicalX( 0 );
347 int sly = DC->DeviceToLogicalY( 1 ) - DC->DeviceToLogicalY( 0 );
348 bool mirrored = (slx > 0 && sly < 0) || (slx < 0 && sly > 0);
361 DC->DrawLine( start, end );
370 DC->DrawArc( end, start, org );
372 DC->DrawArc( start, end, org );
381 DC->DrawLine( start, end );
390 DC->DrawArc( end.x, end.y, start.x, start.y, x2, y2 );
392 DC->DrawArc( start.x, start.y, end.x, end.y, x2, y2 );
399 GRCSegm( ClipBox, DC, x1, y1, x2, y2, width, 0, Color );
406 GRCSegm( aClipBox, aDC, aStart.x, aStart.y, aEnd.x, aEnd.y, aWidth, 0, aColor );
437 int Xmin, Xmax, Ymin, Ymax;
439 Xmin = Xmax = Points[0].x;
440 Ymin = Ymax = Points[0].y;
442 for(
int ii = 1; ii < n; ii++ )
444 Xmin = std::min( Xmin, Points[ii].x );
445 Xmax = std::max( Xmax, Points[ii].x );
446 Ymin = std::min( Ymin, Points[ii].y );
447 Ymax = std::max( Ymax, Points[ii].y );
471 static void GRSPoly(
EDA_RECT* ClipBox, wxDC* DC,
int n,
const wxPoint* Points,
bool Fill,
477 if( Fill && ( n > 2 ) )
491 GRMoveTo( Points[0].x, Points[0].y );
492 for(
int i = 1; i < n; ++i )
494 GRLineTo( ClipBox, DC, Points[i].x, Points[i].y, width, Color );
509 if( aFill && ( aPointCount > 2 ) )
520 GRMoveTo( aPoints[0].x, aPoints[0].y );
521 for(
int i = 1; i < aPointCount; ++i )
523 GRLineTo( aClipBox, aDC, aPoints[i].x, aPoints[i].y, aWidth, aColor );
526 int lastpt = aPointCount - 1;
529 if( aPoints[lastpt] != aPoints[0] )
531 GRLineTo( aClipBox, aDC, aPoints[0].x, aPoints[0].y, aWidth, aColor );
540 void GRPoly(
EDA_RECT* ClipBox, wxDC* DC,
int n,
const wxPoint* Points,
bool Fill,
int width,
543 GRSPoly( ClipBox, DC, n, Points, Fill, width, Color, BgColor );
553 GRClosedPoly( ClipBox, DC, n, Points, Fill, 0, Color, BgColor );
560 GRSClosedPoly( ClipBox, DC, n, Points, Fill, width, Color, BgColor );
570 x0 = aClipBox->
GetX();
571 y0 = aClipBox->
GetY();
577 if( xc < ( x0 - r ) )
580 if( yc < ( y0 - r ) )
583 if( xc > ( r + xm ) )
586 if( yc > ( r + ym ) )
596 if(
clipCircle( ClipBox, xc, yc, r, width ) || r <= 0 )
601 DC->DrawEllipse( xc - r, yc - r, r + r, r + r );
607 GRCircle( ClipBox, DC, x, y, r, 0, Color );
613 GRCircle( aClipBox, aDC, aPos.x, aPos.y, aRadius, aWidth, aColor );
620 if(
clipCircle( ClipBox, x, y, r, width ) || r <= 0 )
625 DC->DrawEllipse( x - r, y - r, r + r, r + r );
631 GRFilledCircle( aClipBox, aDC, aPos.x, aPos.y, aRadius, 0, aColor, aColor );
639 int xc,
int yc,
COLOR4D Color )
641 GRArc1( ClipBox, DC, x1, y1, x2, y2, xc, yc, 0, Color );
649 int xc,
int yc,
int width,
COLOR4D Color )
654 int x0, y0, xm, ym, r;
655 x0 = ClipBox->
GetX();
656 y0 = ClipBox->
GetY();
659 r =
KiROUND( Distance( x1, y1, xc, yc ) );
660 if( xc < ( x0 - r ) )
662 if( yc < ( y0 - r ) )
664 if( xc > ( r + xm ) )
666 if( yc > ( r + ym ) )
672 DC->DrawArc( x1, y1, x2, y2, xc, yc );
677 wxPoint aCenter,
int aWidth,
COLOR4D aColor )
679 GRArc1( aClipBox, aDC, aStart.x, aStart.y, aEnd.x, aEnd.y, aCenter.x, aCenter.y,
704 x0 = ClipBox->
GetX();
705 y0 = ClipBox->
GetY();
709 if( x < ( x0 - r - 1 ) )
712 if( y < ( y0 - r - 1 ) )
715 if( x > ( r + xm + 1 ) )
718 if( y > ( r + ym + 1 ) )
732 DC->DrawArc( x + x1, y - y1, x + x2, y - y2, x, y );
737 double StAngle,
double EndAngle,
int r,
740 GRFilledArc( ClipBox, DC, x, y, StAngle, EndAngle, r, 0, Color, BgColor );
748 double EndAngle,
int r,
COLOR4D Color )
756 int x0, y0, xm, ym, x, y;
757 x0 = ClipBox->
GetX();
758 y0 = ClipBox->
GetY();
764 if( x < ( x0 - radius ) )
766 if( y < ( y0 - radius ) )
768 if( x > ( xm + radius ) )
770 if( y > ( ym + radius ) )
784 DC->DrawArc( xc + x1, yc - y1, xc + x2, yc - y2, xc, yc );
807 x0 = ClipBox->
GetX();
808 y0 = ClipBox->
GetY();
812 if( x < ( x0 - r - width ) )
815 if( y < ( y0 - r - width ) )
818 if( x > ( r + xm + width ) )
821 if( y > ( r + ym + width ) )
835 DC->DrawArc( x + x1, y - y1, x + x2, y - y2, x, y );
844 GRSRect( aClipBox, aDC, x1, y1, x2, y2, 0, aColor );
850 int x1 = aRect.
GetX();
851 int y1 = aRect.
GetY();
855 GRSRect( aClipBox, aDC, x1, y1, x2, y2, 0, aColor, aStyle );
864 GRSRect( ClipBox, DC, x1, y1, x2, y2, width, Color );
870 int x1 = aRect.
GetX();
871 int y1 = aRect.
GetY();
875 GRSRect( aClipBox, aDC, x1, y1, x2, y2, aWidth, aColor );
885 GRSFilledRect( ClipBox, DC, x1, y1, x2, y2, 0, Color, BgColor );
895 GRSFilledRect( ClipBox, DC, x1, y1, x2, y2, width, Color, BgColor );
904 int aWidth,
COLOR4D aColor, wxPenStyle aStyle )
907 points[0] = wxPoint(x1, y1);
908 points[1] = wxPoint(x1, y2);
909 points[2] = wxPoint(x2, y2);
910 points[3] = wxPoint(x2, y1);
911 points[4] = points[0];
921 points[0] = wxPoint(x1, y1);
922 points[1] = wxPoint(x1, y2);
923 points[2] = wxPoint(x2, y2);
924 points[3] = wxPoint(x2, y1);
925 points[4] = points[0];
930 if( aClipBox && (aWidth > 0) )
953 #include <SutherlandHodgmanClipPoly.h> 957 if( aClipBox ==
NULL )
959 aDC->DrawPolygon( n, Points );
964 static std::vector<wxPoint> clippedPolygon;
965 static pointVector inputPolygon, outputPolygon;
967 inputPolygon.clear();
968 outputPolygon.clear();
969 clippedPolygon.clear();
971 for(
int ii = 0; ii < n; ii++ )
972 inputPolygon.push_back( PointF( (REAL) Points[ii].x, (REAL) Points[ii].y ) );
974 RectF window( (REAL) aClipBox->
GetX(), (REAL) aClipBox->
GetY(),
977 SutherlandHodgman sh( window );
978 sh.Clip( inputPolygon, outputPolygon );
980 for( cpointIterator cit = outputPolygon.begin(); cit != outputPolygon.end(); ++cit )
982 clippedPolygon.emplace_back(
KiROUND( cit->X ),
KiROUND( cit->Y ) );
985 if( clippedPolygon.size() )
986 aDC->DrawPolygon( clippedPolygon.size(), &clippedPolygon[0] );
991 std::vector<wxPoint>& aPoint,
994 std::vector<wxPoint> output;
997 converter.
GetPoly( output, aWidth );
999 GRPoly( aClipBox, aDC, output.size(), &output[0],
false, aWidth, aColor, aColor );
1006 int anchor_size = aDC->DeviceToLogicalXRel( aSize );
1010 x + anchor_size, y, 0, aColor );
1013 x, y + anchor_size, 0, aColor );
1019 wxStringTokenizer tokenizer( aText,
" " );
1020 wxSize
const dc_size = aDC.GetSize();
1021 wxSize
const margin = aDC.GetTextExtent(
" " );
1022 std::vector<wxString> lines;
1023 wxString line_accumulator;
1024 int total_height = 0;
1026 while( tokenizer.HasMoreTokens() )
1028 wxString word = tokenizer.GetNextToken();
1029 wxSize linesize = aDC.GetTextExtent( line_accumulator +
" " + word );
1031 if( linesize.x >= dc_size.x - margin.x && !line_accumulator.IsEmpty() )
1033 lines.push_back( line_accumulator );
1034 line_accumulator = word;
1038 line_accumulator +=
" ";
1039 line_accumulator += word;
1043 if( !line_accumulator.IsEmpty() )
1045 lines.push_back( line_accumulator );
1048 for(
auto const& line: lines )
1050 wxSize linesize = aDC.GetTextExtent( line );
1051 total_height += linesize.y;
1054 int top = ( dc_size.y - total_height ) / 2;
1057 for(
auto const& line: lines )
1059 wxSize linesize = aDC.GetTextExtent( line );
1060 aDC.DrawText( line, ( dc_size.x - linesize.x ) / 2, pos );
void GRResetPenAndBrush(wxDC *DC)
void GRDrawWrappedText(wxDC &aDC, wxString const &aText)
Draw text centered on a wxDC with wrapping.
void GRSFilledRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, int aWidth, COLOR4D aColor, COLOR4D aBgColor)
static bool clipCircle(EDA_RECT *aClipBox, int xc, int yc, int r, int aWidth)
void GetPoly(std::vector< wxPoint > &aOutput, int aMinSegLen=0)
Converts Bezier curve to a polygon.
void GRPoly(EDA_RECT *ClipBox, wxDC *DC, int n, const wxPoint *Points, bool Fill, int width, COLOR4D Color, COLOR4D BgColor)
void GRBezier(EDA_RECT *aClipBox, wxDC *aDC, std::vector< wxPoint > &aPoint, int aWidth, COLOR4D aColor)
Draw cubic (4 points: start control1, control2, end) bezier curve.
void GRFilledRect(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, COLOR4D Color, COLOR4D BgColor)
static void GRSPoly(EDA_RECT *ClipBox, wxDC *DC, int n, const wxPoint *Points, bool Fill, int width, COLOR4D Color, COLOR4D BgColor)
void GRCSegm(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, int aPenSize, COLOR4D Color)
void GRDrawAnchor(EDA_RECT *aClipBox, wxDC *aDC, int x, int y, int aSize, COLOR4D aColor)
void RotatePoint(int *pX, int *pY, double angle)
void GRFilledCircle(EDA_RECT *ClipBox, wxDC *DC, int x, int y, int r, int width, COLOR4D Color, COLOR4D BgColor)
bool Contains(const wxPoint &aPoint) const
bool ClipLine(const EDA_RECT *aClipBox, int &x1, int &y1, int &x2, int &y2)
Test if any part of a line falls within the bounds of a rectangle.
void GRLineTo(EDA_RECT *ClipBox, wxDC *DC, int x, int y, int width, COLOR4D Color)
static const bool NOT_FILLED
void GRRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, COLOR4D aColor)
void GRForceBlackPen(bool flagforce)
Function GRForceBlackPen.
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
void GRFillCSegm(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color)
static void WinClipAndDrawLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width)
static wxDC * s_DC_lastDC
void GRArc(EDA_RECT *ClipBox, wxDC *DC, int xc, int yc, double StAngle, double EndAngle, int r, COLOR4D Color)
static void GRSClosedPoly(EDA_RECT *aClipBox, wxDC *aDC, int aPointCount, const wxPoint *aPoints, bool aFill, int aWidth, COLOR4D aColor, COLOR4D aBgColor)
a few functions useful in geometry calculations.
static bool IsGRSPolyDrawable(EDA_RECT *ClipBox, int n, const wxPoint *Points)
void GRLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color, wxPenStyle aStyle)
static COLOR4D s_DC_lastbrushcolor(0, 0, 0, 0)
static COLOR4D s_DC_lastcolor(0, 0, 0, 0)
void GRFilledArc(EDA_RECT *ClipBox, wxDC *DC, int x, int y, double StAngle, double EndAngle, int r, int width, COLOR4D Color, COLOR4D BgColor)
void GRSetBrush(wxDC *DC, COLOR4D Color, bool fill)
void GRPutPixel(EDA_RECT *ClipBox, wxDC *DC, int x, int y, COLOR4D Color)
void GRMoveTo(int x, int y)
static void ClipAndDrawPoly(EDA_RECT *ClipBox, wxDC *DC, const wxPoint *Points, int n)
Function ClipAndDrawPoly Used to clip a polygon and draw it as Filled Polygon uses the Sutherland and...
Bezier curves to polygon converter.
void GRFilledSegment(EDA_RECT *aClipBox, wxDC *aDC, wxPoint aStart, wxPoint aEnd, int aWidth, COLOR4D aColor)
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void GRCircle(EDA_RECT *ClipBox, wxDC *DC, int xc, int yc, int r, int width, COLOR4D Color)
void GRSetColorPen(wxDC *DC, COLOR4D Color, int width, wxPenStyle style)
Function GRSetColorPen sets a pen style, width, color, and alpha into the given device context.
Handle the component boundary box.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
void GRLineArray(EDA_RECT *aClipBox, wxDC *aDC, std::vector< wxPoint > &aLines, int aWidth, COLOR4D aColor)
Function GRLineArray draws an array of lines (not a polygon).
static void GRSRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, int aWidth, COLOR4D aColor, wxPenStyle aStyle=wxPENSTYLE_SOLID)
double ArcTangente(int dy, int dx)
bool GetGRForceBlackPenState(void)
Function GetGRForceBlackPenState.
BASE_SCREEN class implementation.
void GRClosedPoly(EDA_RECT *ClipBox, wxDC *DC, int n, const wxPoint *Points, bool Fill, COLOR4D Color, COLOR4D BgColor)
Draw a closed polygon onto the drawing context aDC and optionally fills and/or draws a border around ...
static bool s_DC_lastbrushfill
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Inflate the rectangle horizontally by dx and vertically by dy.
static bool s_ForceBlackPen
void GRRectPs(EDA_RECT *aClipBox, wxDC *aDC, const EDA_RECT &aRect, COLOR4D aColor, wxPenStyle aStyle)
void GRArc1(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int xc, int yc, COLOR4D Color)
A color representation with 4 components: red, green, blue, alpha.