KiCad PCB EDA Suite
gr_basic.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software: you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation, either version 3 of the License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 /********************************/
23 /* Low level graphics routines */
24 /********************************/
25 
26 
27 #include <fctsys.h>
28 #include <gr_basic.h>
29 #include <common.h>
30 #include <trigo.h>
31 #include <macros.h>
32 #include <base_struct.h>
33 #include <base_screen.h>
34 #include <bezier_curves.h>
35 #include <math_for_graphics.h>
36 #include <wx/graphics.h>
37 #include <wx/tokenzr.h>
38 #if defined(__WXMAC__) && defined(USE_WX_GRAPHICS_CONTEXT)
39 #include <wx/dcgraph.h>
40 #endif
41 
42 static const bool FILLED = true;
43 static const bool NOT_FILLED = false;
44 
45 /* Important Note:
46  * These drawing functions clip draw item before send these items to wxDC draw
47  * functions. For guy who asks why i did it, see a sample of problems encountered
48  * when pixels
49  * coordinates overflow 16 bits values:
50  * http://trac.wxwidgets.org/ticket/10446
51  * Problems can be found under Windows **and** Linux (mainly when drawing arcs)
52  * (mainly at low zoom values (2, 1 or 0.5), in Pcbnew)
53  * some of these problems could be now fixed in recent distributions.
54  *
55  * Currently (feb 2009) there are overflow problems when drawing solid (filled)
56  * polygons under linux without clipping
57  *
58  * So before removing clipping functions, be aware these bug (they are not in
59  * KiCad or wxWidgets) are fixed by testing how are drawn complex lines arcs
60  * and solid polygons under Windows and Linux and remember users can have old
61  * versions with bugs
62  */
63 
64 
65 /* Definitions for enabling and disabling debugging features in gr_basic.cpp.
66  * Please remember to set these back to 0 before making LAUNCHPAD commits.
67  */
68 #define DEBUG_DUMP_CLIP_ERROR_COORDS 0 // Set to 1 to dump clip algorithm errors.
69 #define DEBUG_DUMP_CLIP_COORDS 0 // Set to 1 to dump clipped coordinates.
70 
71 
72 // For draw mode = XOR GR_XOR or GR_NXOR by background color
74 
75 
76 static void ClipAndDrawPoly( EDA_RECT * ClipBox, wxDC * DC, wxPoint Points[],
77  int n );
78 
79 /* These functions are used by corresponding functions
80  * ( GRSCircle is called by GRCircle for instance) after mapping coordinates
81  * from user units to screen units(pixels coordinates)
82  */
83 static void GRSRect( EDA_RECT* aClipBox, wxDC* aDC, int x1, int y1,
84  int x2, int y2, int aWidth, COLOR4D aColor,
85  wxPenStyle aStyle = wxPENSTYLE_SOLID );
86 
87 
88 
90 static bool s_ForceBlackPen; /* if true: draws in black instead of
91  * color for printing. */
92 static int xcliplo = 0,
93  ycliplo = 0,
94  xcliphi = 2000,
95  ycliphi = 2000;
96 
97 static COLOR4D s_DC_lastcolor( 0, 0, 0, 0 );
98 static COLOR4D s_DC_lastbrushcolor( 0, 0, 0, 0 );
99 static bool s_DC_lastbrushfill = false;
100 static wxDC* s_DC_lastDC = NULL;
101 
102 /***
103  * Utility for the line clipping code, returns the boundary code of
104  * a point. Bit allocation is arbitrary
105  */
106 static inline int clipOutCode( const EDA_RECT *aClipBox, int x, int y )
107 {
108  int code;
109  if( y < aClipBox->GetY() )
110  code = 2;
111  else if( y > aClipBox->GetBottom() )
112  code = 1;
113  else
114  code = 0;
115  if( x < aClipBox->GetX() )
116  code |= 4;
117  else if( x > aClipBox->GetRight() )
118  code |= 8;
119  return code;
120 }
121 
122 
136 static bool clipLine( const EDA_RECT *aClipBox, int &x1, int &y1, int &x2, int &y2 )
137 {
138  // Stock Cohen-Sutherland algorithm; check *any* CG book for details
139  int outcode1 = clipOutCode( aClipBox, x1, y1 );
140  int outcode2 = clipOutCode( aClipBox, x2, y2 );
141 
142  while( outcode1 || outcode2 )
143  {
144  // Fast reject
145  if( outcode1 & outcode2 )
146  return true;
147 
148  // Choose a side to clip
149  int thisoutcode, x, y;
150  if( outcode1 )
151  thisoutcode = outcode1;
152  else
153  thisoutcode = outcode2;
154 
155  /* One clip round
156  * Since we use the full range of 32 bit ints, the proportion
157  * computation has to be done in 64 bits to avoid horrible
158  * results */
159  if( thisoutcode & 1 ) // Clip the bottom
160  {
161  y = aClipBox->GetBottom();
162  x = x1 + (x2 - x1) * int64_t(y - y1) / (y2 - y1);
163  }
164  else if( thisoutcode & 2 ) // Clip the top
165  {
166  y = aClipBox->GetY();
167  x = x1 + (x2 - x1) * int64_t(y - y1) / (y2 - y1);
168  }
169  else if( thisoutcode & 8 ) // Clip the right
170  {
171  x = aClipBox->GetRight();
172  y = y1 + (y2 - y1) * int64_t(x - x1) / (x2 - x1);
173  }
174  else // if( thisoutcode & 4), obviously, clip the left
175  {
176  x = aClipBox->GetX();
177  y = y1 + (y2 - y1) * int64_t(x - x1) / (x2 - x1);
178  }
179 
180  // Put the result back and update the boundary code
181  // No ambiguity, otherwise it would have been a fast reject
182  if( thisoutcode == outcode1 )
183  {
184  x1 = x;
185  y1 = y;
186  outcode1 = clipOutCode( aClipBox, x1, y1 );
187  }
188  else
189  {
190  x2 = x;
191  y2 = y;
192  outcode2 = clipOutCode( aClipBox, x2, y2 );
193  }
194  }
195  return false;
196 }
197 
198 static void WinClipAndDrawLine( EDA_RECT* ClipBox, wxDC* DC, int x1, int y1, int x2, int y2, int width )
199 {
200  GRLastMoveToX = x2;
201  GRLastMoveToY = y2;
202 
203  if( ClipBox )
204  {
205  EDA_RECT clipbox(*ClipBox);
206  clipbox.Inflate(width/2);
207  if( clipLine( &clipbox, x1, y1, x2, y2 ) )
208  return;
209  }
210 
211  DC->DrawLine( x1, y1, x2, y2 );
212 }
213 
214 
215 /* Forcing a reset of the current pen.
216  * Must be called after changing the graphical device before any trace.
217  */
218 void GRResetPenAndBrush( wxDC* DC )
219 {
220  GRSetBrush( DC, BLACK ); // Force no fill
221  s_DC_lastbrushcolor = COLOR4D::UNSPECIFIED;
222  s_DC_lastcolor = COLOR4D::UNSPECIFIED;
223  s_DC_lastDC = NULL;
224 }
225 
226 
231 void GRSetColorPen( wxDC* DC, COLOR4D Color, int width, wxPenStyle style )
232 {
233  wxDash dots[2] = { 1, 3 };
234  // Under OSX and while printing when wxPen is set to 0, renderer follows the request drawing
235  // nothing & in the bitmap world the minimum is enough to light a pixel, in vectorial one not
236  if( width <= 1 )
237  width = DC->DeviceToLogicalXRel( 1 );
238 
239  if( s_ForceBlackPen )
240  Color = COLOR4D::BLACK;
241 
242  const wxPen& curr_pen = DC->GetPen();
243 
244  if( !curr_pen.IsOk() || curr_pen.GetColour() != Color.ToColour()
245  || curr_pen.GetWidth() != width
246  || curr_pen.GetStyle() != style )
247  {
248  wxPen pen;
249  pen.SetColour( Color.ToColour() );
250  if( style == wxPENSTYLE_DOT )
251  {
252  style = wxPENSTYLE_USER_DASH;
253  pen.SetDashes( 2, dots );
254  }
255  pen.SetWidth( width );
256  pen.SetStyle( style );
257  DC->SetPen( pen );
258  }
259  else
260  // Should be not needed, but on Linux, in printing process
261  // the curr pen settings needs to be sometimes re-initialized
262  // Clearly, this is due to a bug, related to SetBrush(),
263  // but we have to live with it, at least on wxWidgets 3.0
264  DC->SetPen( curr_pen );
265 }
266 
267 
268 void GRSetBrush( wxDC* DC, COLOR4D Color, bool fill )
269 {
270  if( s_ForceBlackPen )
271  Color = COLOR4D::BLACK;
272 
273  if( s_DC_lastbrushcolor != Color
274  || s_DC_lastbrushfill != fill
275  || s_DC_lastDC != DC )
276  {
277  wxBrush brush;
278 
279  brush.SetColour( Color.ToColour() );
280 
281  if( fill )
282  brush.SetStyle( wxBRUSHSTYLE_SOLID );
283  else
284  brush.SetStyle( wxBRUSHSTYLE_TRANSPARENT );
285 
286  DC->SetBrush( brush );
287 
288  s_DC_lastbrushcolor = Color;
289  s_DC_lastbrushfill = fill;
290  s_DC_lastDC = DC;
291  }
292 }
293 
294 
299 void GRForceBlackPen( bool flagforce )
300 {
301  s_ForceBlackPen = flagforce;
302 }
303 
304 
310 {
311  return s_ForceBlackPen;
312 }
313 
314 
315 /*************************************/
316 /* Set the device context draw mode. */
317 /*************************************/
318 void GRSetDrawMode( wxDC* DC, GR_DRAWMODE draw_mode )
319 {
320  if( draw_mode & GR_OR )
321 #if defined(__WXMAC__) && (wxMAC_USE_CORE_GRAPHICS || wxCHECK_VERSION( 2, 9, 0 ) )
322 
323  DC->SetLogicalFunction( wxCOPY );
324 #elif defined( USE_WX_GRAPHICS_CONTEXT )
325 
326  DC->SetLogicalFunction( wxCOPY );
327 #else
328 
329  DC->SetLogicalFunction( wxOR );
330 #endif
331  else if( draw_mode & GR_XOR )
332 #if defined( USE_WX_GRAPHICS_CONTEXT )
333 
334  DC->SetLogicalFunction( wxCOPY );
335 #else
336 
337  DC->SetLogicalFunction( wxXOR );
338 #endif
339  else if( draw_mode & GR_NXOR )
340 #if defined(__WXMAC__) && (wxMAC_USE_CORE_GRAPHICS || wxCHECK_VERSION( 2, 9, 0 ) )
341 
342  DC->SetLogicalFunction( wxXOR );
343 #elif defined( USE_WX_GRAPHICS_CONTEXT )
344 
345  DC->SetLogicalFunction( wxCOPY );
346 #else
347 
348  DC->SetLogicalFunction( wxEQUIV );
349 #endif
350  else if( draw_mode & GR_INVERT )
351 #if defined( USE_WX_GRAPHICS_CONTEXT )
352 
353  DC->SetLogicalFunction( wxCOPY );
354 #else
355 
356  DC->SetLogicalFunction( wxINVERT );
357 #endif
358  else if( draw_mode & GR_COPY )
359  DC->SetLogicalFunction( wxCOPY );
360 
361 #ifdef USE_WX_OVERLAY
362  DC->SetLogicalFunction( wxCOPY );
363 #endif
364 }
365 
366 
367 void GRPutPixel( EDA_RECT* ClipBox, wxDC* DC, int x, int y, COLOR4D Color )
368 {
369  if( ClipBox && !ClipBox->Contains( x, y ) )
370  return;
371 
372  GRSetColorPen( DC, Color );
373  DC->DrawPoint( x, y );
374 }
375 
376 
377 /*
378  * Draw a line, in object space.
379  */
380 void GRLine( EDA_RECT* ClipBox,
381  wxDC* DC,
382  int x1,
383  int y1,
384  int x2,
385  int y2,
386  int width,
387  COLOR4D Color,
388  wxPenStyle aStyle)
389 {
390  GRSetColorPen( DC, Color, width, aStyle );
391  WinClipAndDrawLine( ClipBox, DC, x1, y1, x2, y2, width );
392  GRLastMoveToX = x2;
393  GRLastMoveToY = y2;
394 }
395 
396 
397 void GRLine( EDA_RECT* aClipBox, wxDC* aDC, wxPoint aStart, wxPoint aEnd, int aWidth, COLOR4D aColor, wxPenStyle aStyle )
398 {
399  GRLine( aClipBox, aDC, aStart.x, aStart.y, aEnd.x, aEnd.y, aWidth, aColor, aStyle );
400 }
401 
402 
403 void GRDashedLine( EDA_RECT* ClipBox, wxDC* DC,
404  int x1, int y1, int x2, int y2,
405  int width, COLOR4D Color )
406 {
407  GRLine( ClipBox, DC, x1, y1, x2, y2, width, Color, wxPENSTYLE_SHORT_DASH );
408 }
409 
410 
411 void GRDottedLine( EDA_RECT* ClipBox, wxDC* DC,
412  int x1, int y1, int x2, int y2,
413  int width, COLOR4D Color )
414 {
415  GRLine( ClipBox, DC, x1, y1, x2, y2, width, Color, wxPENSTYLE_DOT );
416 }
417 
418 
419 /*
420  * Move to a new position, in object space.
421  */
422 void GRMoveTo( int x, int y )
423 {
424  GRLastMoveToX = x;
425  GRLastMoveToY = y;
426 }
427 
428 
429 /*
430  * Draw line to a new position, in object space.
431  */
432 void GRLineTo( EDA_RECT* ClipBox, wxDC* DC, int x, int y, int width, COLOR4D Color )
433 {
434  GRLine( ClipBox, DC, GRLastMoveToX, GRLastMoveToY, x, y, width, Color );
435 }
436 
437 
438 void GRMixedLine( EDA_RECT* ClipBox, wxDC* DC, int x1, int y1, int x2, int y2,
439  int width, COLOR4D Color )
440 {
441  GRLine( ClipBox, DC, x1, y1, x2, y2, width, Color, wxPENSTYLE_DOT_DASH );
442 }
443 
444 
445 
456 void GRLineArray( EDA_RECT* aClipBox, wxDC* aDC, std::vector<wxPoint>& aLines,
457  int aWidth, COLOR4D aColor )
458 {
459  if( aLines.empty() )
460  return;
461 
462  GRSetColorPen( aDC, aColor, aWidth );
463 
464  if( aClipBox )
465  aClipBox->Inflate( aWidth / 2 );
466 
467 #if defined( __WXMAC__ ) && defined( USE_WX_GRAPHICS_CONTEXT )
468  wxGCDC *gcdc = wxDynamicCast( aDC, wxGCDC );
469  if( gcdc )
470  {
471  wxGraphicsContext *gc = gcdc->GetGraphicsContext();
472 
473  // create path
474  wxGraphicsPath path = gc->CreatePath();
475  for( unsigned i = 0; i < aLines.size(); i += 2 )
476  {
477  int x1 = aLines[i].x;
478  int y1 = aLines[i].y;
479  int x2 = aLines[i+1].x;
480  int y2 = aLines[i+1].y;
481  if( ( aClipBox == NULL ) || !clipLine( aClipBox, x1, y1, x2, y2 ) )
482  {
483  path.MoveToPoint( x1, y1 );
484  path.AddLineToPoint( x2, y2 );
485  }
486  }
487  // draw path
488  gc->StrokePath( path );
489  }
490  else
491 #endif
492  {
493  for( unsigned i = 0; i < aLines.size(); i += 2 )
494  {
495  int x1 = aLines[i].x;
496  int y1 = aLines[i].y;
497  int x2 = aLines[i+1].x;
498  int y2 = aLines[i+1].y;
499  if( ( aClipBox == NULL ) || !clipLine( aClipBox, x1, y1, x2, y2 ) )
500  aDC->DrawLine( x1, y1, x2, y2 );
501  }
502  }
503  GRMoveTo( aLines[aLines.size() - 1].x, aLines[aLines.size() - 1].y );
504 
505  if( aClipBox )
506  aClipBox->Inflate(-aWidth/2);
507 }
508 
509 // Draw the outline of a thick segment wih rounded ends
510 void GRCSegm( EDA_RECT* ClipBox, wxDC* DC, int x1, int y1, int x2, int y2,
511  int width, int aPenSize, COLOR4D Color )
512 {
513  GRLastMoveToX = x2;
514  GRLastMoveToY = y2;
515 
516  if( ClipBox )
517  {
518  EDA_RECT clipbox(*ClipBox);
519  clipbox.Inflate(width/2);
520 
521  if( clipLine( &clipbox, x1, y1, x2, y2 ) )
522  return;
523  }
524 
525 
526  if( width <= 2 ) /* single line or 2 pixels */
527  {
528  GRSetColorPen( DC, Color, width );
529  DC->DrawLine( x1, y1, x2, y2 );
530  return;
531  }
532 
533  GRSetBrush( DC, Color, NOT_FILLED );
534  GRSetColorPen( DC, Color, aPenSize );
535 
536  int radius = (width + 1) >> 1;
537  int dx = x2 - x1;
538  int dy = y2 - y1;
539  double angle = -ArcTangente( dy, dx );
540  wxPoint start;
541  wxPoint end;
542  wxPoint org( x1, y1);
543  int len = (int) hypot( dx, dy );
544 
545  // We know if the DC is mirrored, to draw arcs
546  int slx = DC->DeviceToLogicalX( 1 ) - DC->DeviceToLogicalX( 0 );
547  int sly = DC->DeviceToLogicalY( 1 ) - DC->DeviceToLogicalY( 0 );
548  bool mirrored = (slx > 0 && sly < 0) || (slx < 0 && sly > 0);
549 
550  // first edge
551  start.x = 0;
552  start.y = radius;
553  end.x = len;
554  end.y = radius;
555  RotatePoint( &start, angle);
556  RotatePoint( &end, angle);
557 
558  start += org;
559  end += org;
560 
561  DC->DrawLine( start, end );
562 
563  // first rounded end
564  end.x = 0;
565  end.y = -radius;
566  RotatePoint( &end, angle);
567  end += org;
568 
569  if( !mirrored )
570  DC->DrawArc( end, start, org );
571  else
572  DC->DrawArc( start, end, org );
573 
574 
575  // second edge
576  start.x = len;
577  start.y = -radius;
578  RotatePoint( &start, angle);
579  start += org;
580 
581  DC->DrawLine( start, end );
582 
583  // second rounded end
584  end.x = len;
585  end.y = radius;
586  RotatePoint( &end, angle);
587  end += org;
588 
589  if( !mirrored )
590  DC->DrawArc( end.x, end.y, start.x, start.y, x2, y2 );
591  else
592  DC->DrawArc( start.x, start.y, end.x, end.y, x2, y2 );
593 }
594 
595 
596 void GRCSegm( EDA_RECT* ClipBox, wxDC* DC, int x1, int y1, int x2, int y2,
597  int width, COLOR4D Color )
598 {
599  GRCSegm( ClipBox, DC, x1, y1, x2, y2, width, 0, Color );
600 }
601 
602 
603 void GRCSegm( EDA_RECT* aClipBox, wxDC* aDC, wxPoint aStart, wxPoint aEnd,
604  int aWidth, COLOR4D aColor )
605 {
606  GRCSegm( aClipBox, aDC, aStart.x, aStart.y, aEnd.x, aEnd.y, aWidth, 0, aColor );
607 }
608 
609 
610 /*
611  * Draw segment (full) with rounded ends in object space (real coords.).
612  */
613 void GRFillCSegm( EDA_RECT* ClipBox, wxDC* DC, int x1, int y1, int x2, int y2,
614  int width, COLOR4D Color )
615 {
616  GRSetColorPen( DC, Color, width );
617  WinClipAndDrawLine( ClipBox, DC, x1, y1, x2, y2, width );
618 }
619 
620 
621 void GRFilledSegment( EDA_RECT* aClipBox, wxDC* aDC, wxPoint aStart, wxPoint aEnd,
622  int aWidth, COLOR4D aColor )
623 {
624  GRSetColorPen( aDC, aColor, aWidth );
625  WinClipAndDrawLine( aClipBox, aDC, aStart.x, aStart.y, aEnd.x, aEnd.y, aWidth );
626 }
627 
628 
629 static bool IsGRSPolyDrawable( EDA_RECT* ClipBox, int n, wxPoint Points[] )
630 {
631  if( !ClipBox )
632  return true;
633 
634  if( n <= 0 )
635  return false;
636 
637  int Xmin, Xmax, Ymin, Ymax;
638 
639  Xmin = Xmax = Points[0].x;
640  Ymin = Ymax = Points[0].y;
641 
642  for( int ii = 1; ii < n; ii++ ) // calculate rectangle
643  {
644  Xmin = std::min( Xmin, Points[ii].x );
645  Xmax = std::max( Xmax, Points[ii].x );
646  Ymin = std::min( Ymin, Points[ii].y );
647  Ymax = std::max( Ymax, Points[ii].y );
648  }
649 
650  xcliplo = ClipBox->GetX();
651  ycliplo = ClipBox->GetY();
652  xcliphi = ClipBox->GetRight();
653  ycliphi = ClipBox->GetBottom();
654 
655  if( Xmax < xcliplo )
656  return false;
657  if( Xmin > xcliphi )
658  return false;
659  if( Ymax < ycliplo )
660  return false;
661  if( Ymin > ycliphi )
662  return false;
663 
664  return true;
665 }
666 
667 
668 /*
669  * Draw a new polyline and fill it if Fill, in screen space.
670  */
671 static void GRSPoly( EDA_RECT* ClipBox, wxDC* DC, int n, wxPoint Points[],
672  bool Fill, int width,
673  COLOR4D Color, COLOR4D BgColor )
674 {
675  if( !IsGRSPolyDrawable( ClipBox, n, Points ) )
676  return;
677 
678  if( Fill && ( n > 2 ) )
679  {
680  GRSetBrush( DC, BgColor, FILLED );
681  GRSetColorPen( DC, Color, width );
682 
683  /* clip before send the filled polygon to wxDC, because under linux
684  * (GTK?) polygons having large coordinates are incorrectly drawn
685  * (integer overflow in coordinates, I am guessing)
686  */
687  ClipAndDrawPoly( ClipBox, DC, Points, n );
688  }
689  else
690  {
691 #if defined( __WXMAC__ ) && defined( USE_WX_GRAPHICS_CONTEXT )
692  wxGCDC *gcdc = wxDynamicCast( DC, wxGCDC );
693  if( gcdc )
694  {
695  wxGraphicsContext *gc = gcdc->GetGraphicsContext();
696 
697  // set pen
698  GRSetColorPen( DC, Color, width );
699 
700  // create path
701  wxGraphicsPath path = gc->CreatePath();
702  path.MoveToPoint( Points[0].x, Points[0].y );
703  for( int i = 1; i < n; ++i )
704  {
705  path.AddLineToPoint( Points[i].x, Points[i].y );
706  }
707  // draw path
708  gc->StrokePath( path );
709 
710  // correctly update last position
711  GRMoveTo( Points[n - 1].x, Points[n - 1].y );
712  }
713  else
714 #endif
715  {
716  GRMoveTo( Points[0].x, Points[0].y );
717  for( int i = 1; i < n; ++i )
718  {
719  GRLineTo( ClipBox, DC, Points[i].x, Points[i].y, width, Color );
720  }
721  }
722  }
723 }
724 
725 
726 /*
727  * Draw a new closed polyline and fill it if Fill, in screen space.
728  */
729 static void GRSClosedPoly( EDA_RECT* aClipBox, wxDC* aDC,
730  int aPointCount, wxPoint aPoints[],
731  bool aFill, int aWidth,
732  COLOR4D aColor,
733  COLOR4D aBgColor )
734 {
735  if( !IsGRSPolyDrawable( aClipBox, aPointCount, aPoints ) )
736  return;
737 
738  if( aFill && ( aPointCount > 2 ) )
739  {
740  GRLastMoveToX = aPoints[aPointCount - 1].x;
741  GRLastMoveToY = aPoints[aPointCount - 1].y;
742  GRSetBrush( aDC, aBgColor, FILLED );
743  GRSetColorPen( aDC, aColor, aWidth );
744  ClipAndDrawPoly( aClipBox, aDC, aPoints, aPointCount );
745  }
746  else
747  {
748 #if defined( __WXMAC__ ) && defined( USE_WX_GRAPHICS_CONTEXT )
749  wxGCDC *gcdc = wxDynamicCast( aDC, wxGCDC );
750  if( gcdc )
751  {
752  wxGraphicsContext *gc = gcdc->GetGraphicsContext();
753 
754  // set pen
755  GRSetColorPen( aDC, aColor, aWidth );
756 
757  // create path
758  wxGraphicsPath path = gc->CreatePath();
759  path.MoveToPoint( aPoints[0].x, aPoints[0].y );
760  for( int i = 1; i < aPointCount; ++i )
761  {
762  path.AddLineToPoint( aPoints[i].x, aPoints[i].y );
763  }
764  if( aPoints[aPointCount - 1] != aPoints[0] )
765  path.AddLineToPoint( aPoints[0].x, aPoints[0].y );
766  // draw path
767  gc->StrokePath( path );
768 
769  // correctly update last position
770  GRMoveTo( aPoints[aPointCount - 1].x, aPoints[aPointCount - 1].y );
771  }
772  else
773 #endif
774  {
775  GRMoveTo( aPoints[0].x, aPoints[0].y );
776  for( int i = 1; i < aPointCount; ++i )
777  {
778  GRLineTo( aClipBox, aDC, aPoints[i].x, aPoints[i].y, aWidth, aColor );
779  }
780 
781  int lastpt = aPointCount - 1;
782 
783  // Close the polygon
784  if( aPoints[lastpt] != aPoints[0] )
785  {
786  GRLineTo( aClipBox, aDC, aPoints[0].x, aPoints[0].y, aWidth, aColor );
787  }
788  }
789  }
790 }
791 
792 
793 /*
794  * Draw a new polyline and fill it if Fill, in drawing space.
795  */
796 void GRPoly( EDA_RECT* ClipBox, wxDC* DC, int n, wxPoint Points[],
797  bool Fill, int width, COLOR4D Color, COLOR4D BgColor )
798 {
799  GRSPoly( ClipBox, DC, n, Points, Fill, width, Color, BgColor );
800 }
801 
802 
803 /*
804  * Draw a closed polyline and fill it if Fill, in object space.
805  */
806 void GRClosedPoly( EDA_RECT* ClipBox, wxDC* DC, int n, wxPoint Points[],
807  bool Fill, COLOR4D Color, COLOR4D BgColor )
808 {
809  GRClosedPoly( ClipBox, DC, n, Points, Fill, 0, Color, BgColor );
810 }
811 
812 
813 void GRClosedPoly( EDA_RECT* ClipBox, wxDC* DC, int n, wxPoint Points[],
814  bool Fill, int width, COLOR4D Color, COLOR4D BgColor )
815 {
816  GRSClosedPoly( ClipBox, DC, n, Points, Fill, width, Color, BgColor );
817 }
818 
819 
820 static bool clipCircle( EDA_RECT* aClipBox, int xc, int yc, int r, int aWidth )
821 {
822  // Clip circles that are outside the ClipBox.
823  if( aClipBox )
824  {
825  int x0, y0, xm, ym;
826  x0 = aClipBox->GetX();
827  y0 = aClipBox->GetY();
828  xm = aClipBox->GetRight();
829  ym = aClipBox->GetBottom();
830 
831  r += aWidth;
832 
833  if( xc < ( x0 - r ) )
834  return true;
835 
836  if( yc < ( y0 - r ) )
837  return true;
838 
839  if( xc > ( r + xm ) )
840  return true;
841 
842  if( yc > ( r + ym ) )
843  return true;
844  }
845 
846  return false;
847 }
848 
849 
850 void GRCircle( EDA_RECT* ClipBox, wxDC* DC, int xc, int yc, int r, int width, COLOR4D Color )
851 {
852  if( clipCircle( ClipBox, xc, yc, r, width ) || r <= 0 )
853  return;
854 
855  GRSetBrush( DC, Color, NOT_FILLED );
856  GRSetColorPen( DC, Color, width );
857  DC->DrawEllipse( xc - r, yc - r, r + r, r + r );
858 }
859 
860 
861 void GRCircle( EDA_RECT* ClipBox, wxDC* DC, int x, int y, int r, COLOR4D Color )
862 {
863  GRCircle( ClipBox, DC, x, y, r, 0, Color );
864 }
865 
866 
867 void GRCircle( EDA_RECT* aClipBox, wxDC* aDC, wxPoint aPos, int aRadius, int aWidth, COLOR4D aColor )
868 {
869  GRCircle( aClipBox, aDC, aPos.x, aPos.y, aRadius, aWidth, aColor );
870 }
871 
872 
873 void GRFilledCircle( EDA_RECT* ClipBox, wxDC* DC, int x, int y, int r,
874  int width, COLOR4D Color, COLOR4D BgColor )
875 {
876  if( clipCircle( ClipBox, x, y, r, width ) || r <= 0 )
877  return;
878 
879  GRSetBrush( DC, BgColor, FILLED );
880  GRSetColorPen( DC, Color, width );
881  DC->DrawEllipse( x - r, y - r, r + r, r + r );
882 }
883 
884 
885 void GRFilledCircle( EDA_RECT* aClipBox, wxDC* aDC, wxPoint aPos, int aRadius, COLOR4D aColor )
886 {
887  GRFilledCircle( aClipBox, aDC, aPos.x, aPos.y, aRadius, 0, aColor, aColor );
888 }
889 
890 
891 /*
892  * Draw an arc in user space.
893  */
894 void GRArc1( EDA_RECT* ClipBox, wxDC* DC, int x1, int y1, int x2, int y2,
895  int xc, int yc, COLOR4D Color )
896 {
897  GRArc1( ClipBox, DC, x1, y1, x2, y2, xc, yc, 0, Color );
898 }
899 
900 
901 /*
902  * Draw an arc, width = width in user space.
903  */
904 void GRArc1( EDA_RECT* ClipBox, wxDC* DC, int x1, int y1, int x2, int y2,
905  int xc, int yc, int width, COLOR4D Color )
906 {
907  /* Clip arcs off screen. */
908  if( ClipBox )
909  {
910  int x0, y0, xm, ym, r;
911  x0 = ClipBox->GetX();
912  y0 = ClipBox->GetY();
913  xm = ClipBox->GetRight();
914  ym = ClipBox->GetBottom();
915  r = KiROUND( Distance( x1, y1, xc, yc ) );
916  if( xc < ( x0 - r ) )
917  return;
918  if( yc < ( y0 - r ) )
919  return;
920  if( xc > ( r + xm ) )
921  return;
922  if( yc > ( r + ym ) )
923  return;
924  }
925 
926  GRSetBrush( DC, Color );
927  GRSetColorPen( DC, Color, width );
928  DC->DrawArc( x1, y1, x2, y2, xc, yc );
929 }
930 
931 
932 void GRArc1( EDA_RECT* aClipBox, wxDC* aDC, wxPoint aStart, wxPoint aEnd,
933  wxPoint aCenter, int aWidth, COLOR4D aColor )
934 {
935  GRArc1( aClipBox, aDC, aStart.x, aStart.y, aEnd.x, aEnd.y, aCenter.x, aCenter.y,
936  aWidth, aColor );
937 }
938 
939 
940 /*
941  * Draw a filled arc in drawing space.
942  */
943 void GRFilledArc( EDA_RECT* ClipBox,
944  wxDC* DC,
945  int x,
946  int y,
947  double StAngle,
948  double EndAngle,
949  int r,
950  int width,
951  COLOR4D Color,
952  COLOR4D BgColor )
953 {
954  int x1, y1, x2, y2;
955 
956  /* Clip arcs off screen */
957  if( ClipBox )
958  {
959  int x0, y0, xm, ym;
960  x0 = ClipBox->GetX();
961  y0 = ClipBox->GetY();
962  xm = ClipBox->GetRight();
963  ym = ClipBox->GetBottom();
964 
965  if( x < ( x0 - r - 1 ) )
966  return;
967 
968  if( y < ( y0 - r - 1 ) )
969  return;
970 
971  if( x > ( r + xm + 1 ) )
972  return;
973 
974  if( y > ( r + ym + 1 ) )
975  return;
976  }
977 
978  x1 = r;
979  y1 = 0;
980  RotatePoint( &x1, &y1, EndAngle );
981 
982  x2 = r;
983  y2 = 0;
984  RotatePoint( &x2, &y2, StAngle );
985 
986  GRSetBrush( DC, BgColor, FILLED );
987  GRSetColorPen( DC, Color, width );
988  DC->DrawArc( x + x1, y - y1, x + x2, y - y2, x, y );
989 }
990 
991 
992 void GRFilledArc( EDA_RECT* ClipBox, wxDC* DC, int x, int y,
993  double StAngle, double EndAngle, int r,
994  COLOR4D Color, COLOR4D BgColor )
995 {
996  GRFilledArc( ClipBox, DC, x, y, StAngle, EndAngle, r, 0, Color, BgColor );
997 }
998 
999 
1000 /*
1001  * Draw an arc in drawing space.
1002  */
1003 void GRArc( EDA_RECT* ClipBox, wxDC* DC, int xc, int yc, double StAngle,
1004  double EndAngle, int r, COLOR4D Color )
1005 {
1006  int x1, y1, x2, y2;
1007 
1008  /* Clip arcs off screen */
1009  if( ClipBox )
1010  {
1011  int radius = r + 1;
1012  int x0, y0, xm, ym, x, y;
1013  x0 = ClipBox->GetX();
1014  y0 = ClipBox->GetY();
1015  xm = ClipBox->GetRight();
1016  ym = ClipBox->GetBottom();
1017  x = xc;
1018  y = yc;
1019 
1020  if( x < ( x0 - radius ) )
1021  return;
1022  if( y < ( y0 - radius ) )
1023  return;
1024  if( x > ( xm + radius ) )
1025  return;
1026  if( y > ( ym + radius ) )
1027  return;
1028  }
1029 
1030  x1 = r;
1031  y1 = 0;
1032  RotatePoint( &x1, &y1, EndAngle );
1033 
1034  x2 = r;
1035  y2 = 0;
1036  RotatePoint( &x2, &y2, StAngle );
1037 
1038  GRSetBrush( DC, Color, NOT_FILLED );
1039  GRSetColorPen( DC, Color );
1040  DC->DrawArc( xc + x1, yc - y1, xc + x2, yc - y2, xc, yc );
1041 }
1042 
1043 
1044 /*
1045  * Draw an arc with width = width in drawing space.
1046  */
1047 void GRArc( EDA_RECT* ClipBox,
1048  wxDC* DC,
1049  int x,
1050  int y,
1051  double StAngle,
1052  double EndAngle,
1053  int r,
1054  int width,
1055  COLOR4D Color )
1056 {
1057  int x1, y1, x2, y2;
1058 
1059  /* Clip arcs off screen. */
1060  if( ClipBox )
1061  {
1062  int x0, y0, xm, ym;
1063  x0 = ClipBox->GetX();
1064  y0 = ClipBox->GetY();
1065  xm = ClipBox->GetRight();
1066  ym = ClipBox->GetBottom();
1067 
1068  if( x < ( x0 - r - width ) )
1069  return;
1070 
1071  if( y < ( y0 - r - width ) )
1072  return;
1073 
1074  if( x > ( r + xm + width ) )
1075  return;
1076 
1077  if( y > ( r + ym + width ) )
1078  return;
1079  }
1080 
1081  x1 = r;
1082  y1 = 0;
1083  RotatePoint( &x1, &y1, EndAngle );
1084 
1085  x2 = r;
1086  y2 = 0;
1087  RotatePoint( &x2, &y2, StAngle );
1088 
1089  GRSetBrush( DC, Color );
1090  GRSetColorPen( DC, Color, width );
1091  DC->DrawArc( x + x1, y - y1, x + x2, y - y2, x, y );
1092 }
1093 
1094 
1095 /*
1096  * Draw a rectangle in drawing space.
1097  */
1098 void GRRect( EDA_RECT* aClipBox, wxDC* aDC, int x1, int y1, int x2, int y2, COLOR4D aColor )
1099 {
1100  GRSRect( aClipBox, aDC, x1, y1, x2, y2, 0, aColor );
1101 }
1102 
1103 
1104 void GRRectPs( EDA_RECT* aClipBox, wxDC* aDC, const EDA_RECT& aRect, COLOR4D aColor, wxPenStyle aStyle )
1105 {
1106  int x1 = aRect.GetX();
1107  int y1 = aRect.GetY();
1108  int x2 = aRect.GetRight();
1109  int y2 = aRect.GetBottom();
1110 
1111  GRSRect( aClipBox, aDC, x1, y1, x2, y2, 0, aColor, aStyle );
1112 }
1113 
1114 
1115 /*
1116  * Draw a rectangle (thick lines) in drawing space.
1117  */
1118 void GRRect( EDA_RECT* ClipBox, wxDC* DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color )
1119 {
1120  GRSRect( ClipBox, DC, x1, y1, x2, y2, width, Color );
1121 }
1122 
1123 
1124 void GRRect( EDA_RECT* aClipBox, wxDC* aDC, const EDA_RECT& aRect, int aWidth, COLOR4D aColor )
1125 {
1126  int x1 = aRect.GetX();
1127  int y1 = aRect.GetY();
1128  int x2 = aRect.GetRight();
1129  int y2 = aRect.GetBottom();
1130 
1131  GRSRect( aClipBox, aDC, x1, y1, x2, y2, aWidth, aColor );
1132 }
1133 
1134 
1135 /*
1136  * Draw a rectangle (filled with AreaColor) in drawing space.
1137  */
1138 void GRFilledRect( EDA_RECT* ClipBox, wxDC* DC, int x1, int y1, int x2, int y2,
1139  COLOR4D Color, COLOR4D BgColor )
1140 {
1141  GRSFilledRect( ClipBox, DC, x1, y1, x2, y2, 0, Color, BgColor );
1142 }
1143 
1144 
1145 /*
1146  * Draw a rectangle (filled with AreaColor) in drawing space.
1147  */
1148 void GRFilledRect( EDA_RECT* ClipBox, wxDC* DC, int x1, int y1, int x2, int y2,
1149  int width, COLOR4D Color, COLOR4D BgColor )
1150 {
1151  GRSFilledRect( ClipBox, DC, x1, y1, x2, y2, width, Color, BgColor );
1152 }
1153 
1154 
1155 /*
1156  * Draw a rectangle in screen space.
1157  */
1158 
1159 void GRSRect( EDA_RECT* aClipBox, wxDC* aDC, int x1, int y1, int x2, int y2,
1160  int aWidth, COLOR4D aColor, wxPenStyle aStyle )
1161 {
1162  wxPoint points[5];
1163  points[0] = wxPoint(x1, y1);
1164  points[1] = wxPoint(x1, y2);
1165  points[2] = wxPoint(x2, y2);
1166  points[3] = wxPoint(x2, y1);
1167  points[4] = points[0];
1168  GRSClosedPoly( aClipBox, aDC, 5, points, NOT_FILLED, aWidth,
1169  aColor, aColor );
1170 }
1171 
1172 
1173 void GRSFilledRect( EDA_RECT* aClipBox, wxDC* aDC, int x1, int y1, int x2, int y2,
1174  int aWidth, COLOR4D aColor, COLOR4D aBgColor )
1175 {
1176  wxPoint points[5];
1177  points[0] = wxPoint(x1, y1);
1178  points[1] = wxPoint(x1, y2);
1179  points[2] = wxPoint(x2, y2);
1180  points[3] = wxPoint(x2, y1);
1181  points[4] = points[0];
1182 
1183  GRSetBrush( aDC, aBgColor, FILLED );
1184  GRSetColorPen( aDC, aBgColor, aWidth );
1185 
1186  if( aClipBox && (aWidth > 0) )
1187  {
1188  EDA_RECT clipbox(*aClipBox);
1189  clipbox.Inflate(aWidth);
1190  ClipAndDrawPoly(&clipbox, aDC, points, 5); // polygon approach is more accurate
1191  }
1192  else
1193  ClipAndDrawPoly(aClipBox, aDC, points, 5 );
1194 }
1195 
1206 /* Note: aClipBox == NULL is legal, so if aClipBox == NULL,
1207  * the polygon is drawn, but not clipped
1208  */
1209 #include <SutherlandHodgmanClipPoly.h>
1210 
1211 void ClipAndDrawPoly( EDA_RECT* aClipBox, wxDC* aDC, wxPoint aPoints[], int n )
1212 {
1213  if( aClipBox == NULL )
1214  {
1215  aDC->DrawPolygon( n, aPoints );
1216  return;
1217  }
1218 
1219  // A clip box exists: clip and draw the polygon.
1220  static std::vector<wxPoint> clippedPolygon;
1221  static pointVector inputPolygon, outputPolygon;
1222 
1223  inputPolygon.clear();
1224  outputPolygon.clear();
1225  clippedPolygon.clear();
1226 
1227  for( int ii = 0; ii < n; ii++ )
1228  inputPolygon.push_back( PointF( (REAL) aPoints[ii].x, (REAL) aPoints[ii].y ) );
1229 
1230  RectF window( (REAL) aClipBox->GetX(), (REAL) aClipBox->GetY(),
1231  (REAL) aClipBox->GetWidth(), (REAL) aClipBox->GetHeight() );
1232 
1233  SutherlandHodgman sh( window );
1234  sh.Clip( inputPolygon, outputPolygon );
1235 
1236  for( cpointIterator cit = outputPolygon.begin(); cit != outputPolygon.end(); ++cit )
1237  {
1238  clippedPolygon.push_back( wxPoint( KiROUND( cit->X ), KiROUND( cit->Y ) ) );
1239  }
1240 
1241  if( clippedPolygon.size() )
1242  aDC->DrawPolygon( clippedPolygon.size(), &clippedPolygon[0] );
1243 }
1244 
1245 
1246 void GRBezier( EDA_RECT* ClipBox,
1247  wxDC* DC,
1248  int x1,
1249  int y1,
1250  int x2,
1251  int y2,
1252  int x3,
1253  int y3,
1254  int width,
1255  COLOR4D Color )
1256 {
1257  std::vector<wxPoint> points;
1258 
1259  BEZIER_POLY converter( x1, y1, x2, y2, x3, y3 );
1260  converter.GetPoly( points );
1261 
1262  GRPoly( ClipBox, DC, points.size(), &points[0], false, width, Color, Color );
1263 }
1264 
1265 
1266 void GRBezier( EDA_RECT* ClipBox,
1267  wxDC* DC,
1268  int x1,
1269  int y1,
1270  int x2,
1271  int y2,
1272  int x3,
1273  int y3,
1274  int x4,
1275  int y4,
1276  int width,
1277  COLOR4D Color )
1278 {
1279  std::vector<wxPoint> points;
1280 
1281  BEZIER_POLY converter( x1, y1, x2, y2, x3, y3, x4, y4 );
1282  converter.GetPoly( points );
1283 
1284  GRPoly( ClipBox, DC, points.size(), &points[0], false, width, Color, Color );
1285 }
1286 
1287 
1288 void GRDrawAnchor( EDA_RECT *aClipBox, wxDC *aDC, int x, int y,
1289  int aSize, COLOR4D aColor )
1290 {
1291  int anchor_size = aDC->DeviceToLogicalXRel( aSize );
1292 
1293  GRLine( aClipBox, aDC,
1294  x - anchor_size, y,
1295  x + anchor_size, y, 0, aColor );
1296  GRLine( aClipBox, aDC,
1297  x, y - anchor_size,
1298  x, y + anchor_size, 0, aColor );
1299 }
1300 
1301 
1302 void GRDrawWrappedText( wxDC& aDC, wxString const& aText )
1303 {
1304  wxStringTokenizer tokenizer( aText, " " );
1305  wxSize const dc_size = aDC.GetSize();
1306  wxSize const margin = aDC.GetTextExtent( " " );
1307  std::vector<wxString> lines;
1308  wxString line_accumulator;
1309  int total_height = 0;
1310 
1311  while( tokenizer.HasMoreTokens() )
1312  {
1313  wxString word = tokenizer.GetNextToken();
1314  wxSize linesize = aDC.GetTextExtent( line_accumulator + " " + word );
1315 
1316  if( linesize.x >= dc_size.x - margin.x && !line_accumulator.IsEmpty() )
1317  {
1318  lines.push_back( line_accumulator );
1319  line_accumulator = word;
1320  }
1321  else
1322  {
1323  line_accumulator += " ";
1324  line_accumulator += word;
1325  }
1326  }
1327 
1328  if( !line_accumulator.IsEmpty() )
1329  {
1330  lines.push_back( line_accumulator );
1331  }
1332 
1333  for( auto const& line: lines )
1334  {
1335  wxSize linesize = aDC.GetTextExtent( line );
1336  total_height += linesize.y;
1337  }
1338 
1339  int top = ( dc_size.y - total_height ) / 2;
1340  int pos = top;
1341 
1342  for( auto const& line: lines )
1343  {
1344  wxSize linesize = aDC.GetTextExtent( line );
1345  aDC.DrawText( line, ( dc_size.x - linesize.x ) / 2, pos );
1346  pos += linesize.y;
1347  }
1348 }
GR_DRAWMODE g_XorMode
Definition: gr_basic.cpp:73
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:218
static void ClipAndDrawPoly(EDA_RECT *ClipBox, wxDC *DC, wxPoint Points[], int n)
Function ClipAndDrawPoly Used to clip a polygon and draw it as Filled Polygon uses the Sutherland and...
Definition: gr_basic.cpp:1211
static int ycliplo
Definition: gr_basic.cpp:93
void GRPoly(EDA_RECT *ClipBox, wxDC *DC, int n, wxPoint Points[], bool Fill, int width, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:796
static const bool FILLED
Definition: gr_basic.cpp:42
void GRBezier(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int x3, int y3, int width, COLOR4D Color)
Definition: gr_basic.cpp:1246
void GRSetDrawMode(wxDC *DC, GR_DRAWMODE draw_mode)
Definition: gr_basic.cpp:318
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:107
void GRDrawWrappedText(wxDC &aDC, wxString const &aText)
Draw text centered on a wxDC with wrapping.
Definition: gr_basic.cpp:1302
static int ycliphi
Definition: gr_basic.cpp:95
std::vector< PointF > pointVector
void GRSFilledRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, int aWidth, COLOR4D aColor, COLOR4D aBgColor)
Definition: gr_basic.cpp:1173
bool Contains(const wxPoint &aPoint) const
Function Contains.
static bool clipCircle(EDA_RECT *aClipBox, int xc, int yc, int r, int aWidth)
Definition: gr_basic.cpp:820
void GRFilledRect(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:1138
void GetPoly(std::vector< wxPoint > &aOutput)
Converts Bezier curve to a polygon.
double REAL
int GetHeight() const
Definition: eda_rect.h:118
void GRMixedLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color)
Definition: gr_basic.cpp:438
void GRCSegm(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, int aPenSize, COLOR4D Color)
Definition: gr_basic.cpp:510
void GRDrawAnchor(EDA_RECT *aClipBox, wxDC *aDC, int x, int y, int aSize, COLOR4D aColor)
Definition: gr_basic.cpp:1288
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
static bool IsGRSPolyDrawable(EDA_RECT *ClipBox, int n, wxPoint Points[])
Definition: gr_basic.cpp:629
void GRFilledCircle(EDA_RECT *ClipBox, wxDC *DC, int x, int y, int r, int width, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:873
static int xcliphi
Definition: gr_basic.cpp:94
static int GRLastMoveToX
Definition: gr_basic.cpp:89
void GRClosedPoly(EDA_RECT *ClipBox, wxDC *DC, int n, wxPoint Points[], bool Fill, COLOR4D Color, COLOR4D BgColor)
Function GRClosedPoly draws a closed polygon onto the drawing context aDC and optionally fills and/or...
Definition: gr_basic.cpp:806
std::vector< PointF >::const_iterator cpointIterator
This file contains miscellaneous commonly used macros and functions.
void GRLineTo(EDA_RECT *ClipBox, wxDC *DC, int x, int y, int width, COLOR4D Color)
Definition: gr_basic.cpp:432
static int xcliplo
Definition: gr_basic.cpp:92
static const bool NOT_FILLED
Definition: gr_basic.cpp:43
void GRRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, COLOR4D aColor)
Definition: gr_basic.cpp:1098
static int GRLastMoveToY
Definition: gr_basic.cpp:89
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:271
void GRForceBlackPen(bool flagforce)
Function GRForceBlackPen.
Definition: gr_basic.cpp:299
static void GRSClosedPoly(EDA_RECT *aClipBox, wxDC *aDC, int aPointCount, wxPoint aPoints[], bool aFill, int aWidth, COLOR4D aColor, COLOR4D aBgColor)
Definition: gr_basic.cpp:729
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
Definition: gr_basic.h:37
void GRFillCSegm(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color)
Definition: gr_basic.cpp:613
static void WinClipAndDrawLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width)
Definition: gr_basic.cpp:198
static wxDC * s_DC_lastDC
Definition: gr_basic.cpp:100
void GRArc(EDA_RECT *ClipBox, wxDC *DC, int xc, int yc, double StAngle, double EndAngle, int r, COLOR4D Color)
Definition: gr_basic.cpp:1003
static 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.
Definition: gr_basic.cpp:136
int GetBottom() const
Definition: eda_rect.h:122
int GetRight() const
Definition: eda_rect.h:119
void GRLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color, wxPenStyle aStyle)
Definition: gr_basic.cpp:380
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)
Definition: gr_basic.cpp:943
void GRSetBrush(wxDC *DC, COLOR4D Color, bool fill)
Definition: gr_basic.cpp:268
void GRPutPixel(EDA_RECT *ClipBox, wxDC *DC, int x, int y, COLOR4D Color)
Definition: gr_basic.cpp:367
Definition: gr_basic.h:38
void GRMoveTo(int x, int y)
Definition: gr_basic.cpp:422
static int clipOutCode(const EDA_RECT *aClipBox, int x, int y)
Definition: gr_basic.cpp:106
Bezier curves to polygon converter.
Definition: bezier_curves.h:34
void GRDashedLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color)
Definition: gr_basic.cpp:403
#define max(a, b)
Definition: auxiliary.h:86
static void GRSPoly(EDA_RECT *ClipBox, wxDC *DC, int n, wxPoint Points[], bool Fill, int width, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:671
void GRFilledSegment(EDA_RECT *aClipBox, wxDC *aDC, wxPoint aStart, wxPoint aEnd, int aWidth, COLOR4D aColor)
Definition: gr_basic.cpp:621
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)
Definition: gr_basic.cpp:850
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...
Definition: gr_basic.cpp:231
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
int GetX() const
Definition: eda_rect.h:109
The common library.
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).
Definition: gr_basic.cpp:456
int GetWidth() const
Definition: eda_rect.h:117
int GetY() const
Definition: eda_rect.h:110
static void GRSRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, int aWidth, COLOR4D aColor, wxPenStyle aStyle=wxPENSTYLE_SOLID)
Definition: gr_basic.cpp:1159
void GRDottedLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color)
Definition: gr_basic.cpp:411
Definition: colors.h:45
Basic classes for most KiCad items.
double Distance(double x1, double y1, double x2, double y2)
bool GetGRForceBlackPenState(void)
Function GetGRForceBlackPenState.
Definition: gr_basic.cpp:309
BASE_SCREEN class implementation.
static bool s_DC_lastbrushfill
Definition: gr_basic.cpp:99
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
#define min(a, b)
Definition: auxiliary.h:85
static bool s_ForceBlackPen
Definition: gr_basic.cpp:90
void GRRectPs(EDA_RECT *aClipBox, wxDC *aDC, const EDA_RECT &aRect, COLOR4D aColor, wxPenStyle aStyle)
Definition: gr_basic.cpp:1104
void GRArc1(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int xc, int yc, COLOR4D Color)
Definition: gr_basic.cpp:894
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39