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  {
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  TransformOvalClearanceToPolygon( outlineBuffer,
619  aStart, aEnd, aWidth, GetPlotterArcHighDef() );
620  const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline(0 );
621 
622  for( int jj = 0; jj < path.PointCount(); jj++ )
623  cornerList.push_back( wxPoint( path.CPoint( jj ).x , path.CPoint( jj ).y ) );
624 
625  // Ensure the polygon is closed
626  if( cornerList[0] != cornerList[cornerList.size() - 1] )
627  cornerList.push_back( cornerList[0] );
628 
629  PlotPoly( cornerList, NO_FILL );
630  }
631  else
632  {
633  MoveTo( aStart );
634  FinishTo( aEnd );
635  }
636 }
637 
638 /* Plot an arc in DXF format
639  * Filling is not supported
640  */
641 void DXF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
642  FILL_T fill, int width )
643 {
644  wxASSERT( outputFile );
645 
646  if( radius <= 0 )
647  return;
648 
649  // In DXF, arcs are drawn CCW.
650  // In Kicad, arcs are CW or CCW
651  // If StAngle > EndAngle, it is CW. So transform it to CCW
652  if( StAngle > EndAngle )
653  {
654  std::swap( StAngle, EndAngle );
655  }
656 
657  DPOINT centre_dev = userToDeviceCoordinates( centre );
658  double radius_dev = userToDeviceSize( radius );
659 
660  // Emit a DXF ARC entity
661  wxString cname = getDXFColorName( m_currentColor );
662  fprintf( outputFile,
663  "0\nARC\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n50\n%g\n51\n%g\n",
664  TO_UTF8( cname ),
665  centre_dev.x, centre_dev.y, radius_dev,
666  StAngle / 10.0, EndAngle / 10.0 );
667 }
668 
672 void DXF_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient,
673  EDA_DRAW_MODE_T trace_mode, void* aData )
674 {
675  wxASSERT( outputFile );
676  wxSize size( aSize );
677 
678  /* The chip is reduced to an oval tablet with size.y > size.x
679  * (Oval vertical orientation 0) */
680  if( size.x > size.y )
681  {
682  std::swap( size.x, size.y );
683  orient = AddAngles( orient, 900 );
684  }
685 
686  sketchOval( pos, size, orient, -1 );
687 }
688 
689 
694 void DXF_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre,
695  EDA_DRAW_MODE_T trace_mode, void* aData )
696 {
697  wxASSERT( outputFile );
698  Circle( pos, diametre, NO_FILL );
699 }
700 
701 
705 void DXF_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize,
706  double orient, EDA_DRAW_MODE_T trace_mode, void* aData )
707 {
708  wxASSERT( outputFile );
709  wxSize size;
710  int ox, oy, fx, fy;
711 
712  size.x = padsize.x / 2;
713  size.y = padsize.y / 2;
714 
715  if( size.x < 0 )
716  size.x = 0;
717  if( size.y < 0 )
718  size.y = 0;
719 
720  // If a dimension is zero, the trace is reduced to 1 line
721  if( size.x == 0 )
722  {
723  ox = pos.x;
724  oy = pos.y - size.y;
725  RotatePoint( &ox, &oy, pos.x, pos.y, orient );
726  fx = pos.x;
727  fy = pos.y + size.y;
728  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
729  MoveTo( wxPoint( ox, oy ) );
730  FinishTo( wxPoint( fx, fy ) );
731  return;
732  }
733  if( size.y == 0 )
734  {
735  ox = pos.x - size.x;
736  oy = pos.y;
737  RotatePoint( &ox, &oy, pos.x, pos.y, orient );
738  fx = pos.x + size.x;
739  fy = pos.y;
740  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
741  MoveTo( wxPoint( ox, oy ) );
742  FinishTo( wxPoint( fx, fy ) );
743  return;
744  }
745 
746  ox = pos.x - size.x;
747  oy = pos.y - size.y;
748  RotatePoint( &ox, &oy, pos.x, pos.y, orient );
749  MoveTo( wxPoint( ox, oy ) );
750 
751  fx = pos.x - size.x;
752  fy = pos.y + size.y;
753  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
754  LineTo( wxPoint( fx, fy ) );
755 
756  fx = pos.x + size.x;
757  fy = pos.y + size.y;
758  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
759  LineTo( wxPoint( fx, fy ) );
760 
761  fx = pos.x + size.x;
762  fy = pos.y - size.y;
763  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
764  LineTo( wxPoint( fx, fy ) );
765 
766  FinishTo( wxPoint( ox, oy ) );
767 }
768 
769 void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
770  int aCornerRadius, double aOrient,
771  EDA_DRAW_MODE_T aTraceMode, void* aData )
772 {
773  SHAPE_POLY_SET outline;
774  TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient,
775  aCornerRadius, 0.0, 0, GetPlotterArcHighDef() );
776 
777  // TransformRoundRectToPolygon creates only one convex polygon
778  SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
779 
780  MoveTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
781 
782  for( int ii = 1; ii < poly.PointCount(); ++ii )
783  LineTo( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) );
784 
785  FinishTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
786 }
787 
788 void DXF_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize,
789  SHAPE_POLY_SET* aPolygons,
790  EDA_DRAW_MODE_T aTraceMode, void* aData )
791 {
792  for( int cnt = 0; cnt < aPolygons->OutlineCount(); ++cnt )
793  {
794  SHAPE_LINE_CHAIN& poly = aPolygons->Outline( cnt );
795 
796  MoveTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
797 
798  for( int ii = 1; ii < poly.PointCount(); ++ii )
799  LineTo( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) );
800 
801  FinishTo(wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
802  }
803 }
804 
805 
809 void DXF_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
810  double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData )
811 {
812  wxASSERT( outputFile );
813  wxPoint coord[4]; /* coord actual corners of a trapezoidal trace */
814 
815  for( int ii = 0; ii < 4; ii++ )
816  {
817  coord[ii] = aCorners[ii];
818  RotatePoint( &coord[ii], aPadOrient );
819  coord[ii] += aPadPos;
820  }
821 
822  // Plot edge:
823  MoveTo( coord[0] );
824  LineTo( coord[1] );
825  LineTo( coord[2] );
826  LineTo( coord[3] );
827  FinishTo( coord[0] );
828 }
829 
838 bool containsNonAsciiChars( const wxString& string )
839 {
840  for( unsigned i = 0; i < string.length(); i++ )
841  {
842  wchar_t ch = string[i];
843  if( ch > 255 )
844  return true;
845  }
846  return false;
847 }
848 
849 void DXF_PLOTTER::Text( const wxPoint& aPos,
850  COLOR4D aColor,
851  const wxString& aText,
852  double aOrient,
853  const wxSize& aSize,
854  enum EDA_TEXT_HJUSTIFY_T aH_justify,
855  enum EDA_TEXT_VJUSTIFY_T aV_justify,
856  int aWidth,
857  bool aItalic,
858  bool aBold,
859  bool aMultilineAllowed,
860  void* aData )
861 {
862  // Fix me: see how to use DXF text mode for multiline texts
863  if( aMultilineAllowed && !aText.Contains( wxT( "\n" ) ) )
864  aMultilineAllowed = false; // the text has only one line.
865 
866  if( textAsLines || containsNonAsciiChars( aText ) || aMultilineAllowed )
867  {
868  // output text as graphics.
869  // Perhaps multiline texts could be handled as DXF text entity
870  // but I do not want spend time about this (JPC)
871  PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify,
872  aWidth, aItalic, aBold, aMultilineAllowed );
873  }
874  else
875  {
876  /* Emit text as a text entity. This loses formatting and shape but it's
877  more useful as a CAD object */
878  DPOINT origin_dev = userToDeviceCoordinates( aPos );
879  SetColor( aColor );
880  wxString cname = getDXFColorName( m_currentColor );
881  DPOINT size_dev = userToDeviceSize( aSize );
882  int h_code = 0, v_code = 0;
883  switch( aH_justify )
884  {
886  h_code = 0;
887  break;
889  h_code = 1;
890  break;
892  h_code = 2;
893  break;
894  }
895  switch( aV_justify )
896  {
898  v_code = 3;
899  break;
901  v_code = 2;
902  break;
904  v_code = 1;
905  break;
906  }
907 
908  // Position, size, rotation and alignment
909  // The two alignment point usages is somewhat idiot (see the DXF ref)
910  // Anyway since we don't use the fit/aligned options, they're the same
911  fprintf( outputFile,
912  " 0\n"
913  "TEXT\n"
914  " 7\n"
915  "%s\n" // Text style
916  " 8\n"
917  "%s\n" // Layer name
918  " 10\n"
919  "%g\n" // First point X
920  " 11\n"
921  "%g\n" // Second point X
922  " 20\n"
923  "%g\n" // First point Y
924  " 21\n"
925  "%g\n" // Second point Y
926  " 40\n"
927  "%g\n" // Text height
928  " 41\n"
929  "%g\n" // Width factor
930  " 50\n"
931  "%g\n" // Rotation
932  " 51\n"
933  "%g\n" // Oblique angle
934  " 71\n"
935  "%d\n" // Mirror flags
936  " 72\n"
937  "%d\n" // H alignment
938  " 73\n"
939  "%d\n", // V alignment
940  aBold ? (aItalic ? "KICADBI" : "KICADB")
941  : (aItalic ? "KICADI" : "KICAD"),
942  TO_UTF8( cname ),
943  origin_dev.x, origin_dev.x,
944  origin_dev.y, origin_dev.y,
945  size_dev.y, fabs( size_dev.x / size_dev.y ),
946  aOrient / 10.0,
947  aItalic ? DXF_OBLIQUE_ANGLE : 0,
948  size_dev.x < 0 ? 2 : 0, // X mirror flag
949  h_code, v_code );
950 
951  /* There are two issue in emitting the text:
952  - Our overline character (~) must be converted to the appropriate
953  control sequence %%O or %%o
954  - Text encoding in DXF is more or less unspecified since depends on
955  the DXF declared version, the acad version reading it *and* some
956  system variables to be put in the header handled only by newer acads
957  Also before R15 unicode simply is not supported (you need to use
958  bigfonts which are a massive PITA). Common denominator solution:
959  use Latin1 (and however someone could choke on it, anyway). Sorry
960  for the extended latin people. If somewant want to try fixing this
961  recent version seems to use UTF-8 (and not UCS2 like the rest of
962  Windows)
963 
964  XXX Actually there is a *third* issue: older DXF formats are limited
965  to 255 bytes records (it was later raised to 2048); since I'm lazy
966  and text so long is not probable I just don't implement this rule.
967  If someone is interested in fixing this, you have to emit the first
968  partial lines with group code 3 (max 250 bytes each) and then finish
969  with a group code 1 (less than 250 bytes). The DXF refs explains it
970  in no more details...
971  */
972 
973  bool overlining = false;
974  fputs( " 1\n", outputFile );
975  for( unsigned i = 0; i < aText.length(); i++ )
976  {
977  /* Here I do a bad thing: writing the output one byte at a time!
978  but today I'm lazy and I have no idea on how to coerce a Unicode
979  wxString to spit out latin1 encoded text ...
980 
981  Atleast stdio is *supposed* to do output buffering, so there is
982  hope is not too slow */
983  wchar_t ch = aText[i];
984  if( ch > 255 )
985  {
986  // I can't encode this...
987  putc( '?', outputFile );
988  }
989  else
990  {
991  if( ch == '~' )
992  {
993  // Handle the overline toggle
994  fputs( overlining ? "%%o" : "%%O", outputFile );
995  overlining = !overlining;
996  }
997  else
998  {
999  putc( ch, outputFile );
1000  }
1001  }
1002  }
1003  putc( '\n', outputFile );
1004  }
1005 }
1006 
void FinishTo(const wxPoint &pos)
Definition: plotter.h:254
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:1397
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:260
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:1398
void TransformOvalClearanceToPolygon(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...
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:1392
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:1396
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:560
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:229
COLOR4D m_currentColor
Definition: plotter.h:1393
double m_IUsPerDecimil
Definition: plotter.h:542
int PointCount() const
Function PointCount()
wxPoint plotOffset
Plot offset (in IUs)
Definition: plotter.h:548
wxPoint penLastpos
Last pen positions; set to -1,-1 when the pen is at rest.
Definition: plotter.h:567
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:1376
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:213
#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:249
bool m_plotMirror
X axis orientation (SVG) and plot mirrored (only for PS, PDF HPGL and SVG)
Definition: plotter.h:552
virtual bool StartPlot() override
Opens the DXF plot with a skeleton header.
void TransformRoundedEndsSegmentToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aStart, wxPoint aEnd, int aError, int aWidth)
Function TransformRoundedEndsSegmentToPolygon convert a segment with rounded ends to a polygon Conver...
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
Base window classes and related definitions.
double plotScale
Plot scale - chosen by the user (even implicitly with 'fit in a4')
Definition: plotter.h:536
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:1394
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 '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:244
virtual DPOINT userToDeviceCoordinates(const wxPoint &aCoordinate)
Modifies coordinates according to the orientation, scale factor, and offsets trace.
Definition: plotter.cpp:96
unsigned int GetMeasurementDirective() const
Get the correct value for the $MEASUREMENT field given the current units.
Definition: plotter.h:1386
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:1293
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
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:557
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:47
VECTOR2I & Point(int aIndex)
Function Point()
Definition: colors.h:45
double r
Red component.
Definition: color4d.h:301
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:545
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:573
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