KiCad PCB EDA Suite
DXF_plotter.cpp
Go to the documentation of this file.
1 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, you may find one here:
22  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23  * or you may search the http://www.gnu.org website for the version 2 license,
24  * or you may write to the Free Software Foundation, Inc.,
25  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26  */
27 
28 
29 #include <fctsys.h>
30 #include <gr_basic.h>
31 #include <trigo.h>
32 #include <eda_base_frame.h>
33 #include <base_struct.h>
34 #include <plotter.h>
35 #include <macros.h>
36 #include <kicad_string.h>
38 
43 static const double DXF_OBLIQUE_ANGLE = 15;
44 
45 /* The layer/colors palette. The acad/DXF palette is divided in 3 zones:
46 
47  - The primary colors (1 - 9)
48  - An HSV zone (10-250, 5 values x 2 saturations x 10 hues
49  - Greys (251 - 255)
50 
51  There is *no* black... the white does it on paper, usually, and
52  anyway it depends on the plotter configuration, since DXF colors
53  are meant to be logical only (they represent *both* line color and
54  width); later version with plot styles only complicate the matter!
55 
56  As usual, brown and magenta/purple are difficult to place since
57  they are actually variations of other colors.
58  */
59 static const struct
60 {
61  const char *name;
62  int color;
64 {
65  { "BLACK", 7 }, // In DXF, color 7 is *both* white and black!
66  { "GRAY1", 251 },
67  { "GRAY2", 8 },
68  { "GRAY3", 9 },
69  { "WHITE", 7 },
70  { "LYELLOW", 51 },
71  { "BLUE1", 178 },
72  { "GREEN1", 98 },
73  { "CYAN1", 138 },
74  { "RED1", 18 },
75  { "MAGENTA1", 228 },
76  { "BROWN1", 58 },
77  { "BLUE2", 5 },
78  { "GREEN2", 3 },
79  { "CYAN2", 4 },
80  { "RED2", 1 },
81  { "MAGENTA2", 6 },
82  { "BROWN2", 54 },
83  { "BLUE3", 171 },
84  { "GREEN3", 91 },
85  { "CYAN3", 131 },
86  { "RED3", 11 },
87  { "MAGENTA3", 221 },
88  { "YELLOW3", 2 },
89  { "BLUE4", 5 },
90  { "GREEN4", 3 },
91  { "CYAN4", 4 },
92  { "RED4", 1 },
93  { "MAGENTA4", 6 },
94  { "YELLOW4", 2 }
95 };
96 
97 
98 static const char* getDXFLineType( PlotDashType aType )
99 {
100  switch( aType )
101  {
102  case PLOTDASHTYPE_SOLID: return "CONTINUOUS";
103  case PLOTDASHTYPE_DASH: return "DASHED";
104  case PLOTDASHTYPE_DOT: return "DOTTED";
105  case PLOTDASHTYPE_DASHDOT: return "DASHDOT";
106  }
107 
108  wxFAIL_MSG( "Unhandled PlotDashType" );
109  return "CONTINUOUS";
110 }
111 
112 
113 // A helper function to create a color name acceptable in DXF files
114 // DXF files do not use a RGB definition
115 static wxString getDXFColorName( COLOR4D aColor )
116 {
117  EDA_COLOR_T color = ColorFindNearest( int( aColor.r*255 ),
118  int( aColor.g*255 ),
119  int( aColor.b*255 ) );
120  wxString cname( dxf_layer[color].name );
121  return cname;
122 }
123 
129 void DXF_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
130  double aScale, bool aMirror )
131 {
132  plotOffset = aOffset;
133  plotScale = aScale;
134 
135  /* DXF paper is 'virtual' so there is no need of a paper size.
136  Also this way we can handle the aux origin which can be useful
137  (for example when aligning to a mechanical drawing) */
138  paperSize.x = 0;
139  paperSize.y = 0;
140 
141  /* Like paper size DXF units are abstract too. Anyway there is a
142  * system variable (MEASUREMENT) which will be set to 1 to indicate
143  * metric units */
144  m_IUsPerDecimil = aIusPerDecimil;
145  iuPerDeviceUnit = 1.0 / aIusPerDecimil; // Gives a DXF in decimils
146  iuPerDeviceUnit *= 0.00254; // ... now in mm
147 
148  SetDefaultLineWidth( 0 ); // No line width on DXF
149  m_plotMirror = false; // No mirroring on DXF
151 }
152 
157 {
158  wxASSERT( outputFile );
159 
160  // DXF HEADER - Boilerplate
161  // Defines the minimum for drawing i.e. the angle system and the
162  // 4 linetypes (CONTINUOUS, DOTDASH, DASHED and DOTTED)
163  fputs( " 0\n"
164  "SECTION\n"
165  " 2\n"
166  "HEADER\n"
167  " 9\n"
168  "$ANGBASE\n"
169  " 50\n"
170  "0.0\n"
171  " 9\n"
172  "$ANGDIR\n"
173  " 70\n"
174  " 1\n"
175  " 9\n"
176  "$MEASUREMENT\n"
177  " 70\n"
178  "0\n"
179  " 0\n" // This means 'metric units'
180  "ENDSEC\n"
181  " 0\n"
182  "SECTION\n"
183  " 2\n"
184  "TABLES\n"
185  " 0\n"
186  "TABLE\n"
187  " 2\n"
188  "LTYPE\n"
189  " 70\n"
190  "4\n"
191  " 0\n"
192  "LTYPE\n"
193  " 5\n"
194  "40F\n"
195  " 2\n"
196  "CONTINUOUS\n"
197  " 70\n"
198  "0\n"
199  " 3\n"
200  "Solid line\n"
201  " 72\n"
202  "65\n"
203  " 73\n"
204  "0\n"
205  " 40\n"
206  "0.0\n"
207  " 0\n"
208  "LTYPE\n"
209  " 5\n"
210  "410\n"
211  " 2\n"
212  "DASHDOT\n"
213  " 70\n"
214  "0\n"
215  " 3\n"
216  "Dash Dot ____ _ ____ _\n"
217  " 72\n"
218  "65\n"
219  " 73\n"
220  "4\n"
221  " 40\n"
222  "2.0\n"
223  " 49\n"
224  "1.25\n"
225  " 49\n"
226  "-0.25\n"
227  " 49\n"
228  "0.25\n"
229  " 49\n"
230  "-0.25\n"
231  " 0\n"
232  "LTYPE\n"
233  " 5\n"
234  "411\n"
235  " 2\n"
236  "DASHED\n"
237  " 70\n"
238  "0\n"
239  " 3\n"
240  "Dashed __ __ __ __ __\n"
241  " 72\n"
242  "65\n"
243  " 73\n"
244  "2\n"
245  " 40\n"
246  "0.75\n"
247  " 49\n"
248  "0.5\n"
249  " 49\n"
250  "-0.25\n"
251  " 0\n"
252  "LTYPE\n"
253  " 5\n"
254  "43B\n"
255  " 2\n"
256  "DOTTED\n"
257  " 70\n"
258  "0\n"
259  " 3\n"
260  "Dotted . . . .\n"
261  " 72\n"
262  "65\n"
263  " 73\n"
264  "2\n"
265  " 40\n"
266  "0.2\n"
267  " 49\n"
268  "0.0\n"
269  " 49\n"
270  "-0.2\n"
271  " 0\n"
272  "ENDTAB\n",
273  outputFile );
274 
275  // Text styles table
276  // Defines 4 text styles, one for each bold/italic combination
277  fputs( " 0\n"
278  "TABLE\n"
279  " 2\n"
280  "STYLE\n"
281  " 70\n"
282  "4\n", outputFile );
283 
284  static const char *style_name[4] = {"KICAD", "KICADB", "KICADI", "KICADBI"};
285  for(int i = 0; i < 4; i++ )
286  {
287  fprintf( outputFile,
288  " 0\n"
289  "STYLE\n"
290  " 2\n"
291  "%s\n" // Style name
292  " 70\n"
293  "0\n" // Standard flags
294  " 40\n"
295  "0\n" // Non-fixed height text
296  " 41\n"
297  "1\n" // Width factor (base)
298  " 42\n"
299  "1\n" // Last height (mandatory)
300  " 50\n"
301  "%g\n" // Oblique angle
302  " 71\n"
303  "0\n" // Generation flags (default)
304  " 3\n"
305  // The standard ISO font (when kicad is build with it
306  // the dxf text in acad matches *perfectly*)
307  "isocp.shx\n", // Font name (when not bigfont)
308  // Apply a 15 degree angle to italic text
309  style_name[i], i < 2 ? 0 : DXF_OBLIQUE_ANGLE );
310  }
311 
312 
313  // Layer table - one layer per color
314  fprintf( outputFile,
315  " 0\n"
316  "ENDTAB\n"
317  " 0\n"
318  "TABLE\n"
319  " 2\n"
320  "LAYER\n"
321  " 70\n"
322  "%d\n", NBCOLORS );
323 
324  /* The layer/colors palette. The acad/DXF palette is divided in 3 zones:
325 
326  - The primary colors (1 - 9)
327  - An HSV zone (10-250, 5 values x 2 saturations x 10 hues
328  - Greys (251 - 255)
329  */
330 
331  for( EDA_COLOR_T i = BLACK; i < NBCOLORS; i = NextColor(i) )
332  {
333  fprintf( outputFile,
334  " 0\n"
335  "LAYER\n"
336  " 2\n"
337  "%s\n" // Layer name
338  " 70\n"
339  "0\n" // Standard flags
340  " 62\n"
341  "%d\n" // Color number
342  " 6\n"
343  "CONTINUOUS\n",// Linetype name
345  }
346 
347  // End of layer table, begin entities
348  fputs( " 0\n"
349  "ENDTAB\n"
350  " 0\n"
351  "ENDSEC\n"
352  " 0\n"
353  "SECTION\n"
354  " 2\n"
355  "ENTITIES\n", outputFile );
356 
357  return true;
358 }
359 
360 
362 {
363  wxASSERT( outputFile );
364 
365  // DXF FOOTER
366  fputs( " 0\n"
367  "ENDSEC\n"
368  " 0\n"
369  "EOF\n", outputFile );
370  fclose( outputFile );
371  outputFile = NULL;
372 
373  return true;
374 }
375 
376 
381 {
382  if( ( colorMode )
383  || ( color == COLOR4D::BLACK )
384  || ( color == COLOR4D::WHITE ) )
385  {
387  }
388  else
390 }
391 
395 void DXF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width )
396 {
397  wxASSERT( outputFile );
398  MoveTo( p1 );
399  LineTo( wxPoint( p1.x, p2.y ) );
400  LineTo( wxPoint( p2.x, p2.y ) );
401  LineTo( wxPoint( p2.x, p1.y ) );
402  FinishTo( wxPoint( p1.x, p1.y ) );
403 }
404 
405 
412 void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_T fill, int width )
413 {
414  wxASSERT( outputFile );
415  double radius = userToDeviceSize( diameter / 2 );
416  DPOINT centre_dev = userToDeviceCoordinates( centre );
417  if( radius > 0 )
418  {
419  wxString cname = getDXFColorName( m_currentColor );
420 
421  if( !fill )
422  {
423  fprintf( outputFile, "0\nCIRCLE\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n",
424  TO_UTF8( cname ),
425  centre_dev.x, centre_dev.y, radius );
426  }
427 
428  if( fill == FILLED_SHAPE )
429  {
430  double r = radius*0.5;
431  fprintf( outputFile, "0\nPOLYLINE\n");
432  fprintf( outputFile, "8\n%s\n66\n1\n70\n1\n", TO_UTF8( cname ));
433  fprintf( outputFile, "40\n%g\n41\n%g\n", radius, radius);
434  fprintf( outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname ));
435  fprintf( outputFile, "10\n%g\n 20\n%g\n42\n1.0\n",
436  centre_dev.x-r, centre_dev.y );
437  fprintf( outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname ));
438  fprintf( outputFile, "10\n%g\n 20\n%g\n42\n1.0\n",
439  centre_dev.x+r, centre_dev.y );
440  fprintf( outputFile, "0\nSEQEND\n");
441  }
442  }
443 }
444 
445 
452 void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
453  FILL_T aFill, int aWidth, void * aData )
454 {
455  if( aCornerList.size() <= 1 )
456  return;
457 
458  unsigned last = aCornerList.size() - 1;
459 
460  // Plot outlines with lines (thickness = 0) to define the polygon
461  if( aWidth <= 0 )
462  {
463  MoveTo( aCornerList[0] );
464 
465  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
466  LineTo( aCornerList[ii] );
467 
468  // Close polygon if 'fill' requested
469  if( aFill )
470  {
471  if( aCornerList[last] != aCornerList[0] )
472  LineTo( aCornerList[0] );
473  }
474 
475  PenFinish();
476 
477  return;
478  }
479 
480 
481  // if the polygon outline has thickness, and is not filled
482  // (i.e. is a polyline) plot outlines with thick segments
483  if( aWidth > 0 && !aFill )
484  {
485  MoveTo( aCornerList[0] );
486 
487  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
488  ThickSegment( aCornerList[ii-1], aCornerList[ii],
489  aWidth, FILLED, NULL );
490 
491  return;
492  }
493 
494  // The polygon outline has thickness, and is filled
495  // Build and plot the polygon which contains the initial
496  // polygon and its thick outline
497  SHAPE_POLY_SET bufferOutline;
498  SHAPE_POLY_SET bufferPolybase;
499  const int circleToSegmentsCount = 16;
500 
501  bufferPolybase.NewOutline();
502 
503  // enter outline as polygon:
504  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
505  {
507  aCornerList[ii-1], aCornerList[ii], circleToSegmentsCount, aWidth );
508  }
509 
510  // enter the initial polygon:
511  for( unsigned ii = 0; ii < aCornerList.size(); ii++ )
512  {
513  bufferPolybase.Append( aCornerList[ii] );
514  }
515 
516  // Merge polygons to build the polygon which contains the initial
517  // polygon and its thick outline
518 
519  // create the outline which contains thick outline:
520  bufferPolybase.BooleanAdd( bufferOutline, SHAPE_POLY_SET::PM_FAST );
521  bufferPolybase.Fracture( SHAPE_POLY_SET::PM_FAST );
522 
523  if( bufferPolybase.OutlineCount() < 1 ) // should not happen
524  return;
525 
526  const SHAPE_LINE_CHAIN& path = bufferPolybase.COutline( 0 );
527 
528  if( path.PointCount() < 2 ) // should not happen
529  return;
530 
531  // Now, output the final polygon to DXF file:
532  last = path.PointCount() - 1;
533  VECTOR2I point = path.CPoint( 0 );
534 
535  wxPoint startPoint( point.x, point.y );
536  MoveTo( startPoint );
537 
538  for( int ii = 1; ii < path.PointCount(); ii++ )
539  {
540  point = path.CPoint( ii );
541  LineTo( wxPoint( point.x, point.y ) );
542  }
543 
544  // Close polygon, if needed
545  point = path.CPoint( last );
546  wxPoint endPoint( point.x, point.y );
547 
548  if( endPoint != startPoint )
549  LineTo( startPoint );
550 
551  PenFinish();
552 }
553 
554 
555 void DXF_PLOTTER::PenTo( const wxPoint& pos, char plume )
556 {
557  wxASSERT( outputFile );
558  if( plume == 'Z' )
559  {
560  return;
561  }
562  DPOINT pos_dev = userToDeviceCoordinates( pos );
563  DPOINT pen_lastpos_dev = userToDeviceCoordinates( penLastpos );
564 
565  if( penLastpos != pos && plume == 'D' )
566  {
567  wxASSERT( m_currentLineType >= 0 && m_currentLineType < 4 );
568  // DXF LINE
569  wxString cname = getDXFColorName( m_currentColor );
570  const char *lname = getDXFLineType( (PlotDashType) m_currentLineType );
571  fprintf( outputFile, "0\nLINE\n8\n%s\n6\n%s\n10\n%g\n20\n%g\n11\n%g\n21\n%g\n",
572  TO_UTF8( cname ), lname,
573  pen_lastpos_dev.x, pen_lastpos_dev.y, pos_dev.x, pos_dev.y );
574  }
575  penLastpos = pos;
576 }
577 
578 
579 void DXF_PLOTTER::SetDash( int dashed )
580 {
581  wxASSERT( dashed >= 0 && dashed < 4 );
582  m_currentLineType = dashed;
583 }
584 
585 
586 void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int aWidth,
587  EDA_DRAW_MODE_T aPlotMode, void* aData )
588 {
589  if( aPlotMode == SKETCH )
590  {
591  std::vector<wxPoint> cornerList;
592  SHAPE_POLY_SET outlineBuffer;
593  TransformOvalClearanceToPolygon( outlineBuffer,
594  aStart, aEnd, aWidth, 32 , 1.0 );
595  const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline(0 );
596 
597  for( int jj = 0; jj < path.PointCount(); jj++ )
598  cornerList.push_back( wxPoint( path.CPoint( jj ).x , path.CPoint( jj ).y ) );
599 
600  // Ensure the polygon is closed
601  if( cornerList[0] != cornerList[cornerList.size() - 1] )
602  cornerList.push_back( cornerList[0] );
603 
604  PlotPoly( cornerList, NO_FILL );
605  }
606  else
607  {
608  MoveTo( aStart );
609  FinishTo( aEnd );
610  }
611 }
612 
613 /* Plot an arc in DXF format
614  * Filling is not supported
615  */
616 void DXF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
617  FILL_T fill, int width )
618 {
619  wxASSERT( outputFile );
620 
621  if( radius <= 0 )
622  return;
623 
624  // In DXF, arcs are drawn CCW.
625  // In Kicad, arcs are CW or CCW
626  // If StAngle > EndAngle, it is CW. So transform it to CCW
627  if( StAngle > EndAngle )
628  {
629  std::swap( StAngle, EndAngle );
630  }
631 
632  DPOINT centre_dev = userToDeviceCoordinates( centre );
633  double radius_dev = userToDeviceSize( radius );
634 
635  // Emit a DXF ARC entity
636  wxString cname = getDXFColorName( m_currentColor );
637  fprintf( outputFile,
638  "0\nARC\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n50\n%g\n51\n%g\n",
639  TO_UTF8( cname ),
640  centre_dev.x, centre_dev.y, radius_dev,
641  StAngle / 10.0, EndAngle / 10.0 );
642 }
643 
647 void DXF_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient,
648  EDA_DRAW_MODE_T trace_mode, void* aData )
649 {
650  wxASSERT( outputFile );
651  wxSize size( aSize );
652 
653  /* The chip is reduced to an oval tablet with size.y > size.x
654  * (Oval vertical orientation 0) */
655  if( size.x > size.y )
656  {
657  std::swap( size.x, size.y );
658  orient = AddAngles( orient, 900 );
659  }
660 
661  sketchOval( pos, size, orient, -1 );
662 }
663 
664 
669 void DXF_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre,
670  EDA_DRAW_MODE_T trace_mode, void* aData )
671 {
672  wxASSERT( outputFile );
673  Circle( pos, diametre, NO_FILL );
674 }
675 
676 
680 void DXF_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize,
681  double orient, EDA_DRAW_MODE_T trace_mode, void* aData )
682 {
683  wxASSERT( outputFile );
684  wxSize size;
685  int ox, oy, fx, fy;
686 
687  size.x = padsize.x / 2;
688  size.y = padsize.y / 2;
689 
690  if( size.x < 0 )
691  size.x = 0;
692  if( size.y < 0 )
693  size.y = 0;
694 
695  // If a dimension is zero, the trace is reduced to 1 line
696  if( size.x == 0 )
697  {
698  ox = pos.x;
699  oy = pos.y - size.y;
700  RotatePoint( &ox, &oy, pos.x, pos.y, orient );
701  fx = pos.x;
702  fy = pos.y + size.y;
703  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
704  MoveTo( wxPoint( ox, oy ) );
705  FinishTo( wxPoint( fx, fy ) );
706  return;
707  }
708  if( size.y == 0 )
709  {
710  ox = pos.x - size.x;
711  oy = pos.y;
712  RotatePoint( &ox, &oy, pos.x, pos.y, orient );
713  fx = pos.x + size.x;
714  fy = pos.y;
715  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
716  MoveTo( wxPoint( ox, oy ) );
717  FinishTo( wxPoint( fx, fy ) );
718  return;
719  }
720 
721  ox = pos.x - size.x;
722  oy = pos.y - size.y;
723  RotatePoint( &ox, &oy, pos.x, pos.y, orient );
724  MoveTo( wxPoint( ox, oy ) );
725 
726  fx = pos.x - size.x;
727  fy = pos.y + size.y;
728  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
729  LineTo( wxPoint( fx, fy ) );
730 
731  fx = pos.x + size.x;
732  fy = pos.y + size.y;
733  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
734  LineTo( wxPoint( fx, fy ) );
735 
736  fx = pos.x + size.x;
737  fy = pos.y - size.y;
738  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
739  LineTo( wxPoint( fx, fy ) );
740 
741  FinishTo( wxPoint( ox, oy ) );
742 }
743 
744 void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
745  int aCornerRadius, double aOrient,
746  EDA_DRAW_MODE_T aTraceMode, void* aData )
747 {
748  SHAPE_POLY_SET outline;
749  const int segmentToCircleCount = 64;
750  TransformRoundRectToPolygon( outline, aPadPos, aSize, aOrient,
751  aCornerRadius, segmentToCircleCount );
752 
753  // TransformRoundRectToPolygon creates only one convex polygon
754  SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
755 
756  MoveTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
757 
758  for( int ii = 1; ii < poly.PointCount(); ++ii )
759  LineTo( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) );
760 
761  FinishTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
762 }
763 
764 void DXF_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize,
765  SHAPE_POLY_SET* aPolygons,
766  EDA_DRAW_MODE_T aTraceMode, void* aData )
767 {
768  for( int cnt = 0; cnt < aPolygons->OutlineCount(); ++cnt )
769  {
770  SHAPE_LINE_CHAIN& poly = aPolygons->Outline( cnt );
771 
772  MoveTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
773 
774  for( int ii = 1; ii < poly.PointCount(); ++ii )
775  LineTo( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) );
776 
777  FinishTo(wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
778  }
779 }
780 
781 
785 void DXF_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
786  double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData )
787 {
788  wxASSERT( outputFile );
789  wxPoint coord[4]; /* coord actual corners of a trapezoidal trace */
790 
791  for( int ii = 0; ii < 4; ii++ )
792  {
793  coord[ii] = aCorners[ii];
794  RotatePoint( &coord[ii], aPadOrient );
795  coord[ii] += aPadPos;
796  }
797 
798  // Plot edge:
799  MoveTo( coord[0] );
800  LineTo( coord[1] );
801  LineTo( coord[2] );
802  LineTo( coord[3] );
803  FinishTo( coord[0] );
804 }
805 
814 bool containsNonAsciiChars( const wxString& string )
815 {
816  for( unsigned i = 0; i < string.length(); i++ )
817  {
818  wchar_t ch = string[i];
819  if( ch > 255 )
820  return true;
821  }
822  return false;
823 }
824 
825 void DXF_PLOTTER::Text( const wxPoint& aPos,
826  COLOR4D aColor,
827  const wxString& aText,
828  double aOrient,
829  const wxSize& aSize,
830  enum EDA_TEXT_HJUSTIFY_T aH_justify,
831  enum EDA_TEXT_VJUSTIFY_T aV_justify,
832  int aWidth,
833  bool aItalic,
834  bool aBold,
835  bool aMultilineAllowed,
836  void* aData )
837 {
838  // Fix me: see how to use DXF text mode for multiline texts
839  if( aMultilineAllowed && !aText.Contains( wxT( "\n" ) ) )
840  aMultilineAllowed = false; // the text has only one line.
841 
842  if( textAsLines || containsNonAsciiChars( aText ) || aMultilineAllowed )
843  {
844  // output text as graphics.
845  // Perhaps multiline texts could be handled as DXF text entity
846  // but I do not want spend time about this (JPC)
847  PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify,
848  aWidth, aItalic, aBold, aMultilineAllowed );
849  }
850  else
851  {
852  /* Emit text as a text entity. This loses formatting and shape but it's
853  more useful as a CAD object */
854  DPOINT origin_dev = userToDeviceCoordinates( aPos );
855  SetColor( aColor );
856  wxString cname = getDXFColorName( m_currentColor );
857  DPOINT size_dev = userToDeviceSize( aSize );
858  int h_code = 0, v_code = 0;
859  switch( aH_justify )
860  {
862  h_code = 0;
863  break;
865  h_code = 1;
866  break;
868  h_code = 2;
869  break;
870  }
871  switch( aV_justify )
872  {
874  v_code = 3;
875  break;
877  v_code = 2;
878  break;
880  v_code = 1;
881  break;
882  }
883 
884  // Position, size, rotation and alignment
885  // The two alignment point usages is somewhat idiot (see the DXF ref)
886  // Anyway since we don't use the fit/aligned options, they're the same
887  fprintf( outputFile,
888  " 0\n"
889  "TEXT\n"
890  " 7\n"
891  "%s\n" // Text style
892  " 8\n"
893  "%s\n" // Layer name
894  " 10\n"
895  "%g\n" // First point X
896  " 11\n"
897  "%g\n" // Second point X
898  " 20\n"
899  "%g\n" // First point Y
900  " 21\n"
901  "%g\n" // Second point Y
902  " 40\n"
903  "%g\n" // Text height
904  " 41\n"
905  "%g\n" // Width factor
906  " 50\n"
907  "%g\n" // Rotation
908  " 51\n"
909  "%g\n" // Oblique angle
910  " 71\n"
911  "%d\n" // Mirror flags
912  " 72\n"
913  "%d\n" // H alignment
914  " 73\n"
915  "%d\n", // V alignment
916  aBold ? (aItalic ? "KICADBI" : "KICADB")
917  : (aItalic ? "KICADI" : "KICAD"),
918  TO_UTF8( cname ),
919  origin_dev.x, origin_dev.x,
920  origin_dev.y, origin_dev.y,
921  size_dev.y, fabs( size_dev.x / size_dev.y ),
922  aOrient / 10.0,
923  aItalic ? DXF_OBLIQUE_ANGLE : 0,
924  size_dev.x < 0 ? 2 : 0, // X mirror flag
925  h_code, v_code );
926 
927  /* There are two issue in emitting the text:
928  - Our overline character (~) must be converted to the appropriate
929  control sequence %%O or %%o
930  - Text encoding in DXF is more or less unspecified since depends on
931  the DXF declared version, the acad version reading it *and* some
932  system variables to be put in the header handled only by newer acads
933  Also before R15 unicode simply is not supported (you need to use
934  bigfonts which are a massive PITA). Common denominator solution:
935  use Latin1 (and however someone could choke on it, anyway). Sorry
936  for the extended latin people. If somewant want to try fixing this
937  recent version seems to use UTF-8 (and not UCS2 like the rest of
938  Windows)
939 
940  XXX Actually there is a *third* issue: older DXF formats are limited
941  to 255 bytes records (it was later raised to 2048); since I'm lazy
942  and text so long is not probable I just don't implement this rule.
943  If someone is interested in fixing this, you have to emit the first
944  partial lines with group code 3 (max 250 bytes each) and then finish
945  with a group code 1 (less than 250 bytes). The DXF refs explains it
946  in no more details...
947  */
948 
949  bool overlining = false;
950  fputs( " 1\n", outputFile );
951  for( unsigned i = 0; i < aText.length(); i++ )
952  {
953  /* Here I do a bad thing: writing the output one byte at a time!
954  but today I'm lazy and I have no idea on how to coerce a Unicode
955  wxString to spit out latin1 encoded text ...
956 
957  Atleast stdio is *supposed* to do output buffering, so there is
958  hope is not too slow */
959  wchar_t ch = aText[i];
960  if( ch > 255 )
961  {
962  // I can't encode this...
963  putc( '?', outputFile );
964  }
965  else
966  {
967  if( ch == '~' )
968  {
969  // Handle the overline toggle
970  fputs( overlining ? "%%o" : "%%O", outputFile );
971  overlining = !overlining;
972  }
973  else
974  {
975  putc( ch, outputFile );
976  }
977  }
978  }
979  putc( '\n', outputFile );
980  }
981 }
982 
void TransformRoundedEndsSegmentToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aStart, wxPoint aEnd, int aCircleToSegmentsCount, int aWidth)
Function TransformRoundedEndsSegmentToPolygon convert a segment with rounded ends to a polygon Conver...
void FinishTo(const wxPoint &pos)
Definition: plotter.h:251
virtual void PlotPoly(const std::vector< wxPoint > &aCornerList, FILL_T aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=NULL) override
DXF polygon: doesn&#39;t fill it but at least it close the filled ones DXF does not know thick outline...
EDA_COLOR_T
NOTE: EDA_COLOR_T is deprecated and is kept around for compatibility with legacy canvas.
Definition: colors.h:42
EDA_COLOR_T ColorFindNearest(const wxColour &aColor)
Find the nearest color match.
Definition: colors.cpp:96
EDA_TEXT_HJUSTIFY_T
Definition: eda_text.h:62
void PenFinish()
Definition: plotter.h:257
virtual void Text(const wxPoint &aPos, const COLOR4D aColor, const wxString &aText, double aOrient, const wxSize &aSize, enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, bool aBold, bool aMultilineAllowed=false, void *aData=NULL) override
Draws text with the plotter.
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset union For aFastMode meaning, see function booleanOp
virtual void SetViewport(const wxPoint &aOffset, double aIusPerDecimil, double aScale, bool aMirror) override
Set the scale/position for the DXF plot The DXF engine doesn&#39;t support line widths and mirroring...
int PointCount() const
Function PointCount()
bool containsNonAsciiChars(const wxString &string)
Checks if a given string contains non-ASCII characters.
bool textAsLines
Definition: plotter.h:1323
static wxString getDXFColorName(COLOR4D aColor)
virtual void FlashPadTrapez(const wxPoint &aPadPos, const wxPoint *aCorners, double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void *aData) override
DXF trapezoidal pad: only sketch mode is supported.
void TransformRoundRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, int aCircleToSegmentsCount)
Function TransformRoundRectToPolygon convert a rectangle with rounded corners to a polygon Convert ar...
int color
Definition: DXF_plotter.cpp:62
virtual void FlashPadCustom(const wxPoint &aPadPos, const wxSize &aSize, SHAPE_POLY_SET *aPolygons, EDA_DRAW_MODE_T aTraceMode, void *aData) override
virtual function FlashPadCustom
virtual void PenTo(const wxPoint &pos, char plume) override
moveto/lineto primitive, moves the &#39;pen&#39; to the specified direction
double g
Green component.
Definition: color4d.h:288
bool colorMode
Definition: plotter.h:557
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
COLOR4D m_currentColor
Definition: plotter.h:1324
void TransformOvalClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aStart, wxPoint aEnd, int aWidth, int aCircleToSegmentsCount, double aCorrectionFactor)
convert a oblong shape to a polygon, using multiple segments It is similar to TransformRoundedEndsSeg...
int OutlineCount() const
Returns the number of outlines in the set
double m_IUsPerDecimil
Definition: plotter.h:539
wxPoint plotOffset
Plot offset (in IUs)
Definition: plotter.h:545
wxPoint penLastpos
Last pen positions; set to -1,-1 when the pen is at rest.
Definition: plotter.h:564
double b
Blue component.
Definition: color4d.h:289
This file contains miscellaneous commonly used macros and functions.
virtual void Text(const wxPoint &aPos, const COLOR4D aColor, const wxString &aText, double aOrient, const wxSize &aSize, enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, bool aBold, bool aMultilineAllowed=false, void *aData=NULL)
Draws text with the plotter.
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
virtual void ThickSegment(const wxPoint &start, const wxPoint &end, int width, EDA_DRAW_MODE_T tracemode, void *aData) override
static const double DXF_OBLIQUE_ANGLE
Oblique angle for DXF native text (I don&#39;t remember if 15 degrees is the ISO value...
Definition: DXF_plotter.cpp:43
void LineTo(const wxPoint &pos)
Definition: plotter.h:246
bool m_plotMirror
X axis orientation (SVG) and plot mirrored (only for PS, PDF HPGL and SVG)
Definition: plotter.h:549
virtual bool StartPlot() override
Opens the DXF plot with a skeleton header.
T AddAngles(T a1, T2 a2)
Add two angles (keeping the result normalized). T2 is here.
Definition: trigo.h:288
Class SHAPE_POLY_SET.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
EDA_DRAW_MODE_T
Definition: eda_text.h:77
Base window classes and related definitions.
double plotScale
Plot scale - chosen by the user (even implicitly with &#39;fit in a4&#39;)
Definition: plotter.h:533
virtual bool EndPlot() override
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
virtual void Rect(const wxPoint &p1, const wxPoint &p2, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH) override
DXF rectangle: fill not supported.
virtual void FlashPadCircle(const wxPoint &pos, int diametre, EDA_DRAW_MODE_T trace_mode, void *aData) override
DXF round pad: always done in sketch mode; it could be filled but it isn&#39;t pretty if other kinds of p...
int m_currentLineType
Definition: plotter.h:1325
virtual DPOINT userToDeviceSize(const wxSize &size)
Modifies size according to the plotter scale factors (wxSize version, returns a DPOINT) ...
Definition: plotter.cpp:121
int NewOutline()
Creates a new empty polygon in the set and returns its index
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
virtual void Circle(const wxPoint &pos, int diametre, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH) override
DXF circle: full functionality; it even does &#39;fills&#39; drawing a circle with a dual-arc polyline wide a...
virtual void FlashPadRect(const wxPoint &pos, const wxSize &size, double orient, EDA_DRAW_MODE_T trace_mode, void *aData) override
DXF rectangular pad: alwayd done in sketch mode.
EDA_TEXT_VJUSTIFY_T
Definition: eda_text.h:69
void MoveTo(const wxPoint &pos)
Definition: plotter.h:241
virtual DPOINT userToDeviceCoordinates(const wxPoint &aCoordinate)
Modifies coordinates according to the orientation, scale factor, and offsets trace.
Definition: plotter.cpp:96
static const struct @42 dxf_layer[NBCOLORS]
const char * name
Definition: DXF_plotter.cpp:61
Class SHAPE_LINE_CHAIN.
virtual void SetDefaultLineWidth(int width) override
Set the default line width.
Definition: plotter.h:1270
PlotDashType
Enum for choosing dashed line type.
Definition: plotter.h:84
size_t i
Definition: json11.cpp:597
FILE * outputFile
true if the Y axis is top to bottom (SVG)
Definition: plotter.h:554
virtual void SetColor(COLOR4D color) override
The DXF exporter handles &#39;colors&#39; as layers...
virtual void SetDash(int dashed) override
Definition: colors.h:49
virtual void FlashPadOval(const wxPoint &pos, const wxSize &size, double orient, EDA_DRAW_MODE_T trace_mode, void *aData) override
DXF oval pad: always done in sketch mode.
FILL_T
Enum FILL_T is the set of fill types used in plotting or drawing enclosed areas.
Definition: base_struct.h:54
VECTOR2I & Point(int aIndex)
Function Point()
Definition: colors.h:45
double r
Red component.
Definition: color4d.h:287
Basic classes for most KiCad items.
virtual void Arc(const wxPoint &centre, double StAngle, double EndAngle, int rayon, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH) override
Generic fallback: arc rendered as a polyline.
double iuPerDeviceUnit
Device scale (from IUs to plotter device units - usually decimils)
Definition: plotter.h:542
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
Number of colors.
Definition: colors.h:75
void sketchOval(const wxPoint &pos, const wxSize &size, double orient, int width)
Definition: plotter.cpp:408
virtual void FlashPadRoundRect(const wxPoint &aPadPos, const wxSize &aSize, int aCornerRadius, double aOrient, EDA_DRAW_MODE_T aTraceMode, void *aData) override
virtual function FlashPadRoundRect
wxSize paperSize
Paper size in IU - not in mils.
Definition: plotter.h:570
static const char * getDXFLineType(PlotDashType aType)
Definition: DXF_plotter.cpp:98
EDA_COLOR_T NextColor(EDA_COLOR_T &aColor)
Definition: colors.h:87
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline) ...
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39