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 
124 
126 {
127  m_plotUnits = aUnit;
128 
129  switch( aUnit )
130  {
132  m_unitScalingFactor = 0.00254;
134  break;
135 
136  case DXF_UNIT_INCHES:
137  default:
138  m_unitScalingFactor = 0.0001;
140  }
141 }
142 
143 
149 void DXF_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
150  double aScale, bool aMirror )
151 {
152  plotOffset = aOffset;
153  plotScale = aScale;
154 
155  /* DXF paper is 'virtual' so there is no need of a paper size.
156  Also this way we can handle the aux origin which can be useful
157  (for example when aligning to a mechanical drawing) */
158  paperSize.x = 0;
159  paperSize.y = 0;
160 
161  /* Like paper size DXF units are abstract too. Anyway there is a
162  * system variable (MEASUREMENT) which will be set to 0 to indicate
163  * english units */
164  m_IUsPerDecimil = aIusPerDecimil;
165  iuPerDeviceUnit = 1.0 / aIusPerDecimil; // Gives a DXF in decimils
166  iuPerDeviceUnit *= GetUnitScaling(); // Get the scaling factor for the current units
167 
168  SetDefaultLineWidth( 0 ); // No line width on DXF
169  m_plotMirror = false; // No mirroring on DXF
171 }
172 
177 {
178  wxASSERT( outputFile );
179 
180  // DXF HEADER - Boilerplate
181  // Defines the minimum for drawing i.e. the angle system and the
182  // 4 linetypes (CONTINUOUS, DOTDASH, DASHED and DOTTED)
183  fprintf( outputFile,
184  " 0\n"
185  "SECTION\n"
186  " 2\n"
187  "HEADER\n"
188  " 9\n"
189  "$ANGBASE\n"
190  " 50\n"
191  "0.0\n"
192  " 9\n"
193  "$ANGDIR\n"
194  " 70\n"
195  "1\n"
196  " 9\n"
197  "$MEASUREMENT\n"
198  " 70\n"
199  "%u\n"
200  " 0\n"
201  "ENDSEC\n"
202  " 0\n"
203  "SECTION\n"
204  " 2\n"
205  "TABLES\n"
206  " 0\n"
207  "TABLE\n"
208  " 2\n"
209  "LTYPE\n"
210  " 70\n"
211  "4\n"
212  " 0\n"
213  "LTYPE\n"
214  " 5\n"
215  "40F\n"
216  " 2\n"
217  "CONTINUOUS\n"
218  " 70\n"
219  "0\n"
220  " 3\n"
221  "Solid line\n"
222  " 72\n"
223  "65\n"
224  " 73\n"
225  "0\n"
226  " 40\n"
227  "0.0\n"
228  " 0\n"
229  "LTYPE\n"
230  " 5\n"
231  "410\n"
232  " 2\n"
233  "DASHDOT\n"
234  " 70\n"
235  "0\n"
236  " 3\n"
237  "Dash Dot ____ _ ____ _\n"
238  " 72\n"
239  "65\n"
240  " 73\n"
241  "4\n"
242  " 40\n"
243  "2.0\n"
244  " 49\n"
245  "1.25\n"
246  " 49\n"
247  "-0.25\n"
248  " 49\n"
249  "0.25\n"
250  " 49\n"
251  "-0.25\n"
252  " 0\n"
253  "LTYPE\n"
254  " 5\n"
255  "411\n"
256  " 2\n"
257  "DASHED\n"
258  " 70\n"
259  "0\n"
260  " 3\n"
261  "Dashed __ __ __ __ __\n"
262  " 72\n"
263  "65\n"
264  " 73\n"
265  "2\n"
266  " 40\n"
267  "0.75\n"
268  " 49\n"
269  "0.5\n"
270  " 49\n"
271  "-0.25\n"
272  " 0\n"
273  "LTYPE\n"
274  " 5\n"
275  "43B\n"
276  " 2\n"
277  "DOTTED\n"
278  " 70\n"
279  "0\n"
280  " 3\n"
281  "Dotted . . . .\n"
282  " 72\n"
283  "65\n"
284  " 73\n"
285  "2\n"
286  " 40\n"
287  "0.2\n"
288  " 49\n"
289  "0.0\n"
290  " 49\n"
291  "-0.2\n"
292  " 0\n"
293  "ENDTAB\n",
295 
296  // Text styles table
297  // Defines 4 text styles, one for each bold/italic combination
298  fputs( " 0\n"
299  "TABLE\n"
300  " 2\n"
301  "STYLE\n"
302  " 70\n"
303  "4\n", outputFile );
304 
305  static const char *style_name[4] = {"KICAD", "KICADB", "KICADI", "KICADBI"};
306  for(int i = 0; i < 4; i++ )
307  {
308  fprintf( outputFile,
309  " 0\n"
310  "STYLE\n"
311  " 2\n"
312  "%s\n" // Style name
313  " 70\n"
314  "0\n" // Standard flags
315  " 40\n"
316  "0\n" // Non-fixed height text
317  " 41\n"
318  "1\n" // Width factor (base)
319  " 42\n"
320  "1\n" // Last height (mandatory)
321  " 50\n"
322  "%g\n" // Oblique angle
323  " 71\n"
324  "0\n" // Generation flags (default)
325  " 3\n"
326  // The standard ISO font (when kicad is build with it
327  // the dxf text in acad matches *perfectly*)
328  "isocp.shx\n", // Font name (when not bigfont)
329  // Apply a 15 degree angle to italic text
330  style_name[i], i < 2 ? 0 : DXF_OBLIQUE_ANGLE );
331  }
332 
333  EDA_COLOR_T numLayers = NBCOLORS;
334 
335  // If printing in monochrome, only output the black layer
336  if( !GetColorMode() )
337  numLayers = static_cast<EDA_COLOR_T>( 1 );
338 
339  // Layer table - one layer per color
340  fprintf( outputFile,
341  " 0\n"
342  "ENDTAB\n"
343  " 0\n"
344  "TABLE\n"
345  " 2\n"
346  "LAYER\n"
347  " 70\n"
348  "%d\n", numLayers );
349 
350  /* The layer/colors palette. The acad/DXF palette is divided in 3 zones:
351 
352  - The primary colors (1 - 9)
353  - An HSV zone (10-250, 5 values x 2 saturations x 10 hues
354  - Greys (251 - 255)
355  */
356 
357  for( EDA_COLOR_T i = BLACK; i < numLayers; i = NextColor(i) )
358  {
359  fprintf( outputFile,
360  " 0\n"
361  "LAYER\n"
362  " 2\n"
363  "%s\n" // Layer name
364  " 70\n"
365  "0\n" // Standard flags
366  " 62\n"
367  "%d\n" // Color number
368  " 6\n"
369  "CONTINUOUS\n",// Linetype name
371  }
372 
373  // End of layer table, begin entities
374  fputs( " 0\n"
375  "ENDTAB\n"
376  " 0\n"
377  "ENDSEC\n"
378  " 0\n"
379  "SECTION\n"
380  " 2\n"
381  "ENTITIES\n", outputFile );
382 
383  return true;
384 }
385 
386 
388 {
389  wxASSERT( outputFile );
390 
391  // DXF FOOTER
392  fputs( " 0\n"
393  "ENDSEC\n"
394  " 0\n"
395  "EOF\n", outputFile );
396  fclose( outputFile );
397  outputFile = NULL;
398 
399  return true;
400 }
401 
402 
407 {
408  if( ( colorMode )
409  || ( color == COLOR4D::BLACK )
410  || ( color == COLOR4D::WHITE ) )
411  {
413  }
414  else
416 }
417 
421 void DXF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width )
422 {
423  wxASSERT( outputFile );
424  MoveTo( p1 );
425  LineTo( wxPoint( p1.x, p2.y ) );
426  LineTo( wxPoint( p2.x, p2.y ) );
427  LineTo( wxPoint( p2.x, p1.y ) );
428  FinishTo( wxPoint( p1.x, p1.y ) );
429 }
430 
431 
438 void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_T fill, int width )
439 {
440  wxASSERT( outputFile );
441  double radius = userToDeviceSize( diameter / 2 );
442  DPOINT centre_dev = userToDeviceCoordinates( centre );
443  if( radius > 0 )
444  {
445  wxString cname = getDXFColorName( m_currentColor );
446 
447  if( !fill )
448  {
449  fprintf( outputFile, "0\nCIRCLE\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n",
450  TO_UTF8( cname ),
451  centre_dev.x, centre_dev.y, radius );
452  }
453 
454  if( fill == FILLED_SHAPE )
455  {
456  double r = radius*0.5;
457  fprintf( outputFile, "0\nPOLYLINE\n");
458  fprintf( outputFile, "8\n%s\n66\n1\n70\n1\n", TO_UTF8( cname ));
459  fprintf( outputFile, "40\n%g\n41\n%g\n", radius, radius);
460  fprintf( outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname ));
461  fprintf( outputFile, "10\n%g\n 20\n%g\n42\n1.0\n",
462  centre_dev.x-r, centre_dev.y );
463  fprintf( outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname ));
464  fprintf( outputFile, "10\n%g\n 20\n%g\n42\n1.0\n",
465  centre_dev.x+r, centre_dev.y );
466  fprintf( outputFile, "0\nSEQEND\n");
467  }
468  }
469 }
470 
471 
478 void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
479  FILL_T aFill, int aWidth, void * aData )
480 {
481  if( aCornerList.size() <= 1 )
482  return;
483 
484  unsigned last = aCornerList.size() - 1;
485 
486  // Plot outlines with lines (thickness = 0) to define the polygon
487  if( aWidth <= 0 )
488  {
489  MoveTo( aCornerList[0] );
490 
491  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
492  LineTo( aCornerList[ii] );
493 
494  // Close polygon if 'fill' requested
495  if( aFill )
496  {
497  if( aCornerList[last] != aCornerList[0] )
498  LineTo( aCornerList[0] );
499  }
500 
501  PenFinish();
502 
503  return;
504  }
505 
506 
507  // if the polygon outline has thickness, and is not filled
508  // (i.e. is a polyline) plot outlines with thick segments
509  if( aWidth > 0 && !aFill )
510  {
511  MoveTo( aCornerList[0] );
512 
513  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
514  ThickSegment( aCornerList[ii-1], aCornerList[ii],
515  aWidth, FILLED, NULL );
516 
517  return;
518  }
519 
520  // The polygon outline has thickness, and is filled
521  // Build and plot the polygon which contains the initial
522  // polygon and its thick outline
523  SHAPE_POLY_SET bufferOutline;
524  SHAPE_POLY_SET bufferPolybase;
525 
526  bufferPolybase.NewOutline();
527 
528  // enter outline as polygon:
529  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
530  {
531  TransformSegmentToPolygon( bufferOutline,
532  aCornerList[ ii - 1 ], aCornerList[ ii ], GetPlotterArcHighDef(), aWidth );
533  }
534 
535  // enter the initial polygon:
536  for( unsigned ii = 0; ii < aCornerList.size(); ii++ )
537  {
538  bufferPolybase.Append( aCornerList[ii] );
539  }
540 
541  // Merge polygons to build the polygon which contains the initial
542  // polygon and its thick outline
543 
544  // create the outline which contains thick outline:
545  bufferPolybase.BooleanAdd( bufferOutline, SHAPE_POLY_SET::PM_FAST );
546  bufferPolybase.Fracture( SHAPE_POLY_SET::PM_FAST );
547 
548  if( bufferPolybase.OutlineCount() < 1 ) // should not happen
549  return;
550 
551  const SHAPE_LINE_CHAIN& path = bufferPolybase.COutline( 0 );
552 
553  if( path.PointCount() < 2 ) // should not happen
554  return;
555 
556  // Now, output the final polygon to DXF file:
557  last = path.PointCount() - 1;
558  VECTOR2I point = path.CPoint( 0 );
559 
560  wxPoint startPoint( point.x, point.y );
561  MoveTo( startPoint );
562 
563  for( int ii = 1; ii < path.PointCount(); ii++ )
564  {
565  point = path.CPoint( ii );
566  LineTo( wxPoint( point.x, point.y ) );
567  }
568 
569  // Close polygon, if needed
570  point = path.CPoint( last );
571  wxPoint endPoint( point.x, point.y );
572 
573  if( endPoint != startPoint )
574  LineTo( startPoint );
575 
576  PenFinish();
577 }
578 
579 
580 void DXF_PLOTTER::PenTo( const wxPoint& pos, char plume )
581 {
582  wxASSERT( outputFile );
583  if( plume == 'Z' )
584  {
585  return;
586  }
587  DPOINT pos_dev = userToDeviceCoordinates( pos );
588  DPOINT pen_lastpos_dev = userToDeviceCoordinates( penLastpos );
589 
590  if( penLastpos != pos && plume == 'D' )
591  {
592  wxASSERT( m_currentLineType >= 0 && m_currentLineType < 4 );
593  // DXF LINE
594  wxString cname = getDXFColorName( m_currentColor );
595  const char *lname = getDXFLineType( (PlotDashType) m_currentLineType );
596  fprintf( outputFile, "0\nLINE\n8\n%s\n6\n%s\n10\n%g\n20\n%g\n11\n%g\n21\n%g\n",
597  TO_UTF8( cname ), lname,
598  pen_lastpos_dev.x, pen_lastpos_dev.y, pos_dev.x, pos_dev.y );
599  }
600  penLastpos = pos;
601 }
602 
603 
604 void DXF_PLOTTER::SetDash( int dashed )
605 {
606  wxASSERT( dashed >= 0 && dashed < 4 );
607  m_currentLineType = dashed;
608 }
609 
610 
611 void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int aWidth,
612  EDA_DRAW_MODE_T aPlotMode, void* aData )
613 {
614  if( aPlotMode == SKETCH )
615  {
616  std::vector<wxPoint> cornerList;
617  SHAPE_POLY_SET outlineBuffer;
618  TransformOvalToPolygon( outlineBuffer, aStart, aEnd, aWidth, GetPlotterArcHighDef());
619  const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline(0 );
620 
621  for( int jj = 0; jj < path.PointCount(); jj++ )
622  cornerList.push_back( wxPoint( path.CPoint( jj ).x , path.CPoint( jj ).y ) );
623 
624  // Ensure the polygon is closed
625  if( cornerList[0] != cornerList[cornerList.size() - 1] )
626  cornerList.push_back( cornerList[0] );
627 
628  PlotPoly( cornerList, NO_FILL );
629  }
630  else
631  {
632  MoveTo( aStart );
633  FinishTo( aEnd );
634  }
635 }
636 
637 /* Plot an arc in DXF format
638  * Filling is not supported
639  */
640 void DXF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
641  FILL_T fill, int width )
642 {
643  wxASSERT( outputFile );
644 
645  if( radius <= 0 )
646  return;
647 
648  // In DXF, arcs are drawn CCW.
649  // In Kicad, arcs are CW or CCW
650  // If StAngle > EndAngle, it is CW. So transform it to CCW
651  if( StAngle > EndAngle )
652  {
653  std::swap( StAngle, EndAngle );
654  }
655 
656  DPOINT centre_dev = userToDeviceCoordinates( centre );
657  double radius_dev = userToDeviceSize( radius );
658 
659  // Emit a DXF ARC entity
660  wxString cname = getDXFColorName( m_currentColor );
661  fprintf( outputFile,
662  "0\nARC\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n50\n%g\n51\n%g\n",
663  TO_UTF8( cname ),
664  centre_dev.x, centre_dev.y, radius_dev,
665  StAngle / 10.0, EndAngle / 10.0 );
666 }
667 
671 void DXF_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient,
672  EDA_DRAW_MODE_T trace_mode, void* aData )
673 {
674  wxASSERT( outputFile );
675  wxSize size( aSize );
676 
677  /* The chip is reduced to an oval tablet with size.y > size.x
678  * (Oval vertical orientation 0) */
679  if( size.x > size.y )
680  {
681  std::swap( size.x, size.y );
682  orient = AddAngles( orient, 900 );
683  }
684 
685  sketchOval( pos, size, orient, -1 );
686 }
687 
688 
693 void DXF_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre,
694  EDA_DRAW_MODE_T trace_mode, void* aData )
695 {
696  wxASSERT( outputFile );
697  Circle( pos, diametre, NO_FILL );
698 }
699 
700 
704 void DXF_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize,
705  double orient, EDA_DRAW_MODE_T trace_mode, void* aData )
706 {
707  wxASSERT( outputFile );
708  wxSize size;
709  int ox, oy, fx, fy;
710 
711  size.x = padsize.x / 2;
712  size.y = padsize.y / 2;
713 
714  if( size.x < 0 )
715  size.x = 0;
716  if( size.y < 0 )
717  size.y = 0;
718 
719  // If a dimension is zero, the trace is reduced to 1 line
720  if( size.x == 0 )
721  {
722  ox = pos.x;
723  oy = pos.y - size.y;
724  RotatePoint( &ox, &oy, pos.x, pos.y, orient );
725  fx = pos.x;
726  fy = pos.y + size.y;
727  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
728  MoveTo( wxPoint( ox, oy ) );
729  FinishTo( wxPoint( fx, fy ) );
730  return;
731  }
732  if( size.y == 0 )
733  {
734  ox = pos.x - size.x;
735  oy = pos.y;
736  RotatePoint( &ox, &oy, pos.x, pos.y, orient );
737  fx = pos.x + size.x;
738  fy = pos.y;
739  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
740  MoveTo( wxPoint( ox, oy ) );
741  FinishTo( wxPoint( fx, fy ) );
742  return;
743  }
744 
745  ox = pos.x - size.x;
746  oy = pos.y - size.y;
747  RotatePoint( &ox, &oy, pos.x, pos.y, orient );
748  MoveTo( wxPoint( ox, oy ) );
749 
750  fx = pos.x - size.x;
751  fy = pos.y + size.y;
752  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
753  LineTo( wxPoint( fx, fy ) );
754 
755  fx = pos.x + size.x;
756  fy = pos.y + size.y;
757  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
758  LineTo( wxPoint( fx, fy ) );
759 
760  fx = pos.x + size.x;
761  fy = pos.y - size.y;
762  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
763  LineTo( wxPoint( fx, fy ) );
764 
765  FinishTo( wxPoint( ox, oy ) );
766 }
767 
768 void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
769  int aCornerRadius, double aOrient,
770  EDA_DRAW_MODE_T aTraceMode, void* aData )
771 {
772  SHAPE_POLY_SET outline;
773  TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient,
774  aCornerRadius, 0.0, 0, GetPlotterArcHighDef() );
775 
776  // TransformRoundRectToPolygon creates only one convex polygon
777  SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
778 
779  MoveTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
780 
781  for( int ii = 1; ii < poly.PointCount(); ++ii )
782  LineTo( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) );
783 
784  FinishTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
785 }
786 
787 void DXF_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize,
788  SHAPE_POLY_SET* aPolygons,
789  EDA_DRAW_MODE_T aTraceMode, void* aData )
790 {
791  for( int cnt = 0; cnt < aPolygons->OutlineCount(); ++cnt )
792  {
793  SHAPE_LINE_CHAIN& poly = aPolygons->Outline( cnt );
794 
795  MoveTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
796 
797  for( int ii = 1; ii < poly.PointCount(); ++ii )
798  LineTo( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) );
799 
800  FinishTo(wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
801  }
802 }
803 
804 
808 void DXF_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
809  double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData )
810 {
811  wxASSERT( outputFile );
812  wxPoint coord[4]; /* coord actual corners of a trapezoidal trace */
813 
814  for( int ii = 0; ii < 4; ii++ )
815  {
816  coord[ii] = aCorners[ii];
817  RotatePoint( &coord[ii], aPadOrient );
818  coord[ii] += aPadPos;
819  }
820 
821  // Plot edge:
822  MoveTo( coord[0] );
823  LineTo( coord[1] );
824  LineTo( coord[2] );
825  LineTo( coord[3] );
826  FinishTo( coord[0] );
827 }
828 
829 
830 void DXF_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos,
831  int aRadius, int aCornerCount,
832  double aOrient, EDA_DRAW_MODE_T aTraceMode, void* aData )
833 {
834  // Do nothing
835  wxASSERT( 0 );
836 }
837 
838 
847 bool containsNonAsciiChars( const wxString& string )
848 {
849  for( unsigned i = 0; i < string.length(); i++ )
850  {
851  wchar_t ch = string[i];
852  if( ch > 255 )
853  return true;
854  }
855  return false;
856 }
857 
858 void DXF_PLOTTER::Text( const wxPoint& aPos,
859  COLOR4D aColor,
860  const wxString& aText,
861  double aOrient,
862  const wxSize& aSize,
863  enum EDA_TEXT_HJUSTIFY_T aH_justify,
864  enum EDA_TEXT_VJUSTIFY_T aV_justify,
865  int aWidth,
866  bool aItalic,
867  bool aBold,
868  bool aMultilineAllowed,
869  void* aData )
870 {
871  // Fix me: see how to use DXF text mode for multiline texts
872  if( aMultilineAllowed && !aText.Contains( wxT( "\n" ) ) )
873  aMultilineAllowed = false; // the text has only one line.
874 
875  if( textAsLines || containsNonAsciiChars( aText ) || aMultilineAllowed )
876  {
877  // output text as graphics.
878  // Perhaps multiline texts could be handled as DXF text entity
879  // but I do not want spend time about this (JPC)
880  PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify,
881  aWidth, aItalic, aBold, aMultilineAllowed );
882  }
883  else
884  {
885  /* Emit text as a text entity. This loses formatting and shape but it's
886  more useful as a CAD object */
887  DPOINT origin_dev = userToDeviceCoordinates( aPos );
888  SetColor( aColor );
889  wxString cname = getDXFColorName( m_currentColor );
890  DPOINT size_dev = userToDeviceSize( aSize );
891  int h_code = 0, v_code = 0;
892  switch( aH_justify )
893  {
895  h_code = 0;
896  break;
898  h_code = 1;
899  break;
901  h_code = 2;
902  break;
903  }
904  switch( aV_justify )
905  {
907  v_code = 3;
908  break;
910  v_code = 2;
911  break;
913  v_code = 1;
914  break;
915  }
916 
917  // Position, size, rotation and alignment
918  // The two alignment point usages is somewhat idiot (see the DXF ref)
919  // Anyway since we don't use the fit/aligned options, they're the same
920  fprintf( outputFile,
921  " 0\n"
922  "TEXT\n"
923  " 7\n"
924  "%s\n" // Text style
925  " 8\n"
926  "%s\n" // Layer name
927  " 10\n"
928  "%g\n" // First point X
929  " 11\n"
930  "%g\n" // Second point X
931  " 20\n"
932  "%g\n" // First point Y
933  " 21\n"
934  "%g\n" // Second point Y
935  " 40\n"
936  "%g\n" // Text height
937  " 41\n"
938  "%g\n" // Width factor
939  " 50\n"
940  "%g\n" // Rotation
941  " 51\n"
942  "%g\n" // Oblique angle
943  " 71\n"
944  "%d\n" // Mirror flags
945  " 72\n"
946  "%d\n" // H alignment
947  " 73\n"
948  "%d\n", // V alignment
949  aBold ? (aItalic ? "KICADBI" : "KICADB")
950  : (aItalic ? "KICADI" : "KICAD"),
951  TO_UTF8( cname ),
952  origin_dev.x, origin_dev.x,
953  origin_dev.y, origin_dev.y,
954  size_dev.y, fabs( size_dev.x / size_dev.y ),
955  aOrient / 10.0,
956  aItalic ? DXF_OBLIQUE_ANGLE : 0,
957  size_dev.x < 0 ? 2 : 0, // X mirror flag
958  h_code, v_code );
959 
960  /* There are two issue in emitting the text:
961  - Our overline character (~) must be converted to the appropriate
962  control sequence %%O or %%o
963  - Text encoding in DXF is more or less unspecified since depends on
964  the DXF declared version, the acad version reading it *and* some
965  system variables to be put in the header handled only by newer acads
966  Also before R15 unicode simply is not supported (you need to use
967  bigfonts which are a massive PITA). Common denominator solution:
968  use Latin1 (and however someone could choke on it, anyway). Sorry
969  for the extended latin people. If somewant want to try fixing this
970  recent version seems to use UTF-8 (and not UCS2 like the rest of
971  Windows)
972 
973  XXX Actually there is a *third* issue: older DXF formats are limited
974  to 255 bytes records (it was later raised to 2048); since I'm lazy
975  and text so long is not probable I just don't implement this rule.
976  If someone is interested in fixing this, you have to emit the first
977  partial lines with group code 3 (max 250 bytes each) and then finish
978  with a group code 1 (less than 250 bytes). The DXF refs explains it
979  in no more details...
980  */
981 
982  bool overlining = false;
983  fputs( " 1\n", outputFile );
984  for( unsigned i = 0; i < aText.length(); i++ )
985  {
986  /* Here I do a bad thing: writing the output one byte at a time!
987  but today I'm lazy and I have no idea on how to coerce a Unicode
988  wxString to spit out latin1 encoded text ...
989 
990  Atleast stdio is *supposed* to do output buffering, so there is
991  hope is not too slow */
992  wchar_t ch = aText[i];
993  if( ch > 255 )
994  {
995  // I can't encode this...
996  putc( '?', outputFile );
997  }
998  else
999  {
1000  if( ch == '~' )
1001  {
1002  // Handle the overline toggle
1003  fputs( overlining ? "%%o" : "%%O", outputFile );
1004  overlining = !overlining;
1005  }
1006  else
1007  {
1008  putc( ch, outputFile );
1009  }
1010  }
1011  }
1012  putc( '\n', outputFile );
1013  }
1014 }
1015 
void FinishTo(const wxPoint &pos)
Definition: plotter.h:264
virtual void PlotPoly(const std::vector< wxPoint > &aCornerList, FILL_T aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=NULL) override
DXF polygon: doesn't fill it but at least it close the filled ones DXF does not know thick outline.
double m_unitScalingFactor
Definition: plotter.h:1530
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:44
void PenFinish()
Definition: plotter.h:270
int OutlineCount() const
Returns the number of outlines in the set
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
unsigned int m_measurementDirective
Definition: plotter.h:1531
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't support line widths and mirroring.
bool containsNonAsciiChars(const wxString &string)
Checks if a given string contains non-ASCII characters.
bool textAsLines
Definition: plotter.h:1525
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 TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aApproxErrorMax, int aMinSegPerCircleCount)
convert a rectangle with rounded corners and/or chamfered corners to a polygon Convert rounded corner...
DXF_UNITS m_plotUnits
Definition: plotter.h:1529
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 'pen' to the specified direction
double g
Green component.
Definition: color4d.h:302
bool colorMode
Definition: plotter.h:581
void SetUnits(DXF_UNITS aUnit)
Set the units to use for plotting the DXF file.
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:206
COLOR4D m_currentColor
Definition: plotter.h:1526
double m_IUsPerDecimil
Definition: plotter.h:563
int PointCount() const
Function PointCount()
wxPoint plotOffset
Plot offset (in IUs)
Definition: plotter.h:569
wxPoint penLastpos
Last pen positions; set to -1,-1 when the pen is at rest.
Definition: plotter.h:588
double b
Blue component.
Definition: color4d.h:303
This file contains miscellaneous commonly used macros and functions.
static const struct @45 dxf_layer[NBCOLORS]
double GetUnitScaling() const
Get the scale factor to apply to convert the device units to be in the currently set units.
Definition: plotter.h:1509
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.
Definition: gr_text.cpp:215
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:48
virtual void ThickSegment(const wxPoint &start, const wxPoint &end, int width, EDA_DRAW_MODE_T tracemode, void *aData) override
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
static const double DXF_OBLIQUE_ANGLE
Oblique angle for DXF native text (I don't remember if 15 degrees is the ISO value....
Definition: DXF_plotter.cpp:43
void LineTo(const wxPoint &pos)
Definition: plotter.h:259
bool m_plotMirror
X axis orientation (SVG) and plot mirrored (only for PS, PDF HPGL and SVG)
Definition: plotter.h:573
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:299
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:59
virtual void FlashRegularPolygon(const wxPoint &aShapePos, int aDiameter, int aCornerCount, double aOrient, EDA_DRAW_MODE_T aTraceMode, void *aData) override
Flash a regular polygon.
Base window classes and related definitions.
double plotScale
Plot scale - chosen by the user (even implicitly with 'fit in a4')
Definition: plotter.h:557
virtual bool EndPlot() override
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't pretty if other kinds of p...
int m_currentLineType
Definition: plotter.h:1527
virtual DPOINT userToDeviceSize(const wxSize &size)
Modifies size according to the plotter scale factors (wxSize version, returns a DPOINT)
Definition: plotter.cpp:123
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 'fills' 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:51
void MoveTo(const wxPoint &pos)
Definition: plotter.h:254
virtual DPOINT userToDeviceCoordinates(const wxPoint &aCoordinate)
Modifies coordinates according to the orientation, scale factor, and offsets trace.
Definition: plotter.cpp:98
unsigned int GetMeasurementDirective() const
Get the correct value for the $MEASUREMENT field given the current units.
Definition: plotter.h:1519
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:1424
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
PlotDashType
Enum for choosing dashed line type.
Definition: plotter.h:84
void TransformSegmentToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aStart, wxPoint aEnd, int aError, int aWidth)
Function TransformRoundedEndsSegmentToPolygon convert a segment with rounded ends to a polygon Conver...
size_t i
Definition: json11.cpp:649
void TransformOvalToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aStart, wxPoint aEnd, int aWidth, int aError)
convert a oblong shape to a polygon, using multiple segments It is similar to TransformRoundedEndsSeg...
FILE * outputFile
true if the Y axis is top to bottom (SVG)
Definition: plotter.h:578
virtual void SetColor(COLOR4D color) override
The DXF exporter handles 'colors' as layers...
int GetPlotterArcHighDef() const
Definition: plotter.h:220
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:42
VECTOR2I & Point(int aIndex)
Function Point()
Definition: colors.h:45
double r
Red component.
Definition: color4d.h:301
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:566
Number of colors.
Definition: colors.h:75
void sketchOval(const wxPoint &pos, const wxSize &size, double orient, int width)
Definition: plotter.cpp:457
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:594
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
bool GetColorMode() const
Definition: plotter.h:131