KiCad PCB EDA Suite
common_plotDXF_functions.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) 2016 KiCad Developers, see CHANGELOG.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 <wxstruct.h>
33 #include <base_struct.h>
34 #include <plot_common.h>
35 #include <macros.h>
36 #include <kicad_string.h>
38 
43 static const double DXF_OBLIQUE_ANGLE = 15;
44 
50 void DXF_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
51  double aScale, bool aMirror )
52 {
53  wxASSERT( !outputFile );
54  plotOffset = aOffset;
55  plotScale = aScale;
56 
57  /* DXF paper is 'virtual' so there is no need of a paper size.
58  Also this way we can handle the aux origin which can be useful
59  (for example when aligning to a mechanical drawing) */
60  paperSize.x = 0;
61  paperSize.y = 0;
62 
63  /* Like paper size DXF units are abstract too. Anyway there is a
64  * system variable (MEASUREMENT) which will be set to 1 to indicate
65  * metric units */
66  m_IUsPerDecimil = aIusPerDecimil;
67  iuPerDeviceUnit = 1.0 / aIusPerDecimil; // Gives a DXF in decimils
68  iuPerDeviceUnit *= 0.00254; // ... now in mm
69 
70  SetDefaultLineWidth( 0 ); // No line width on DXF
71  m_plotMirror = false; // No mirroring on DXF
73 }
74 
79 {
80  wxASSERT( outputFile );
81 
82  // DXF HEADER - Boilerplate
83  // Defines the minimum for drawing i.e. the angle system and the
84  // continuous linetype
85  fputs( " 0\n"
86  "SECTION\n"
87  " 2\n"
88  "HEADER\n"
89  " 9\n"
90  "$ANGBASE\n"
91  " 50\n"
92  "0.0\n"
93  " 9\n"
94  "$ANGDIR\n"
95  " 70\n"
96  " 1\n"
97  " 9\n"
98  "$MEASUREMENT\n"
99  " 70\n"
100  "0\n"
101  " 0\n" // This means 'metric units'
102  "ENDSEC\n"
103  " 0\n"
104  "SECTION\n"
105  " 2\n"
106  "TABLES\n"
107  " 0\n"
108  "TABLE\n"
109  " 2\n"
110  "LTYPE\n"
111  " 70\n"
112  "1\n"
113  " 0\n"
114  "LTYPE\n"
115  " 2\n"
116  "CONTINUOUS\n"
117  " 70\n"
118  "0\n"
119  " 3\n"
120  "Solid line\n"
121  " 72\n"
122  "65\n"
123  " 73\n"
124  "0\n"
125  " 40\n"
126  "0.0\n"
127  " 0\n"
128  "ENDTAB\n",
129  outputFile );
130 
131  // Text styles table
132  // Defines 4 text styles, one for each bold/italic combination
133  fputs( " 0\n"
134  "TABLE\n"
135  " 2\n"
136  "STYLE\n"
137  " 70\n"
138  "4\n", outputFile );
139 
140  static const char *style_name[4] = {"KICAD", "KICADB", "KICADI", "KICADBI"};
141  for(int i = 0; i < 4; i++ )
142  {
143  fprintf( outputFile,
144  " 0\n"
145  "STYLE\n"
146  " 2\n"
147  "%s\n" // Style name
148  " 70\n"
149  "0\n" // Standard flags
150  " 40\n"
151  "0\n" // Non-fixed height text
152  " 41\n"
153  "1\n" // Width factor (base)
154  " 42\n"
155  "1\n" // Last height (mandatory)
156  " 50\n"
157  "%g\n" // Oblique angle
158  " 71\n"
159  "0\n" // Generation flags (default)
160  " 3\n"
161  // The standard ISO font (when kicad is build with it
162  // the dxf text in acad matches *perfectly*)
163  "isocp.shx\n", // Font name (when not bigfont)
164  // Apply a 15 degree angle to italic text
165  style_name[i], i < 2 ? 0 : DXF_OBLIQUE_ANGLE );
166  }
167 
168 
169  // Layer table - one layer per color
170  fprintf( outputFile,
171  " 0\n"
172  "ENDTAB\n"
173  " 0\n"
174  "TABLE\n"
175  " 2\n"
176  "LAYER\n"
177  " 70\n"
178  "%d\n", NBCOLORS );
179 
180  /* The layer/colors palette. The acad/DXF palette is divided in 3 zones:
181 
182  - The primary colors (1 - 9)
183  - An HSV zone (10-250, 5 values x 2 saturations x 10 hues
184  - Greys (251 - 255)
185 
186  There is *no* black... the white does it on paper, usually, and
187  anyway it depends on the plotter configuration, since DXF colors
188  are meant to be logical only (they represent *both* line color and
189  width); later version with plot styles only complicate the matter!
190 
191  As usual, brown and magenta/purple are difficult to place since
192  they are actually variations of other colors.
193  */
194  static const struct {
195  const char *name;
196  int color;
197  } dxf_layer[NBCOLORS] = {
198  { "BLACK", 7 }, // In DXF, color 7 is *both* white and black!
199  { "GRAY1", 251 },
200  { "GRAY2", 8 },
201  { "GRAY3", 9 },
202  { "WHITE", 7 },
203  { "LYELLOW", 51 },
204  { "BLUE1", 178 },
205  { "GREEN1", 98 },
206  { "CYAN1", 138 },
207  { "RED1", 18 },
208  { "MAGENTA1", 228 },
209  { "BROWN1", 58 },
210  { "BLUE2", 5 },
211  { "GREEN2", 3 },
212  { "CYAN2", 4 },
213  { "RED2", 1 },
214  { "MAGENTA2", 6 },
215  { "BROWN2", 54 },
216  { "BLUE3", 171 },
217  { "GREEN3", 91 },
218  { "CYAN3", 131 },
219  { "RED3", 11 },
220  { "MAGENTA3", 221 },
221  { "YELLOW3", 2 },
222  { "BLUE4", 5 },
223  { "GREEN4", 3 },
224  { "CYAN4", 4 },
225  { "RED4", 1 },
226  { "MAGENTA4", 6 },
227  { "YELLOW4", 2 }
228  };
229 
230  for( EDA_COLOR_T i = BLACK; i < NBCOLORS; i = NextColor(i) )
231  {
232  fprintf( outputFile,
233  " 0\n"
234  "LAYER\n"
235  " 2\n"
236  "%s\n" // Layer name
237  " 70\n"
238  "0\n" // Standard flags
239  " 62\n"
240  "%d\n" // Color number
241  " 6\n"
242  "CONTINUOUS\n",// Linetype name
243  dxf_layer[i].name, dxf_layer[i].color );
244  }
245 
246  // End of layer table, begin entities
247  fputs( " 0\n"
248  "ENDTAB\n"
249  " 0\n"
250  "ENDSEC\n"
251  " 0\n"
252  "SECTION\n"
253  " 2\n"
254  "ENTITIES\n", outputFile );
255 
256  return true;
257 }
258 
259 
261 {
262  wxASSERT( outputFile );
263 
264  // DXF FOOTER
265  fputs( " 0\n"
266  "ENDSEC\n"
267  " 0\n"
268  "EOF\n", outputFile );
269  fclose( outputFile );
270  outputFile = NULL;
271 
272  return true;
273 }
274 
275 
280 {
281  wxASSERT( outputFile );
282  if( ( colorMode )
283  || ( color == COLOR4D::BLACK )
284  || ( color == COLOR4D::WHITE ) )
285  {
286  m_currentColor = color;
287  }
288  else
290 }
291 
295 void DXF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width )
296 {
297  wxASSERT( outputFile );
298  MoveTo( p1 );
299  LineTo( wxPoint( p1.x, p2.y ) );
300  LineTo( wxPoint( p2.x, p2.y ) );
301  LineTo( wxPoint( p2.x, p1.y ) );
302  FinishTo( wxPoint( p1.x, p1.y ) );
303 }
304 
305 
312 void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_T fill, int width )
313 {
314  wxASSERT( outputFile );
315  double radius = userToDeviceSize( diameter / 2 );
316  DPOINT centre_dev = userToDeviceCoordinates( centre );
317  if( radius > 0 )
318  {
319  wxString cname( m_currentColor.ToColour().GetAsString( wxC2S_CSS_SYNTAX ) );
320 
321  if( !fill )
322  {
323  fprintf( outputFile, "0\nCIRCLE\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n",
324  TO_UTF8( cname ),
325  centre_dev.x, centre_dev.y, radius );
326  }
327 
328  if( fill == FILLED_SHAPE )
329  {
330  double r = radius*0.5;
331  fprintf( outputFile, "0\nPOLYLINE\n");
332  fprintf( outputFile, "8\n%s\n66\n1\n70\n1\n", TO_UTF8( cname ));
333  fprintf( outputFile, "40\n%g\n41\n%g\n", radius, radius);
334  fprintf( outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname ));
335  fprintf( outputFile, "10\n%g\n 20\n%g\n42\n1.0\n",
336  centre_dev.x-r, centre_dev.y );
337  fprintf( outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname ));
338  fprintf( outputFile, "10\n%g\n 20\n%g\n42\n1.0\n",
339  centre_dev.x+r, centre_dev.y );
340  fprintf( outputFile, "0\nSEQEND\n");
341  }
342  }
343 }
344 
345 
352 void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
353  FILL_T aFill, int aWidth, void * aData )
354 {
355  if( aCornerList.size() <= 1 )
356  return;
357 
358  unsigned last = aCornerList.size() - 1;
359 
360  // Plot outlines with lines (thickness = 0) to define the polygon
361  if( aWidth <= 0 )
362  {
363  MoveTo( aCornerList[0] );
364 
365  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
366  LineTo( aCornerList[ii] );
367 
368  // Close polygon if 'fill' requested
369  if( aFill )
370  {
371  if( aCornerList[last] != aCornerList[0] )
372  LineTo( aCornerList[0] );
373  }
374 
375  PenFinish();
376 
377  return;
378  }
379 
380 
381  // if the polygon outline has thickness, and is not filled
382  // (i.e. is a polyline) plot outlines with thick segments
383  if( aWidth > 0 && !aFill )
384  {
385  MoveTo( aCornerList[0] );
386 
387  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
388  ThickSegment( aCornerList[ii-1], aCornerList[ii],
389  aWidth, FILLED, NULL );
390 
391  return;
392  }
393 
394  // The polygon outline has thickness, and is filled
395  // Build and plot the polygon which contains the initial
396  // polygon and its thick outline
397  SHAPE_POLY_SET bufferOutline;
398  SHAPE_POLY_SET bufferPolybase;
399  const int circleToSegmentsCount = 16;
400 
401  bufferPolybase.NewOutline();
402 
403  // enter outline as polygon:
404  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
405  {
407  aCornerList[ii-1], aCornerList[ii], circleToSegmentsCount, aWidth );
408  }
409 
410  // enter the initial polygon:
411  for( unsigned ii = 0; ii < aCornerList.size(); ii++ )
412  {
413  bufferPolybase.Append( aCornerList[ii] );
414  }
415 
416  // Merge polygons to build the polygon which contains the initial
417  // polygon and its thick outline
418 
419  // create the outline which contains thick outline:
420  bufferPolybase.BooleanAdd( bufferOutline, SHAPE_POLY_SET::PM_FAST );
421  bufferPolybase.Fracture( SHAPE_POLY_SET::PM_FAST );
422 
423  if( bufferPolybase.OutlineCount() < 1 ) // should not happen
424  return;
425 
426  const SHAPE_LINE_CHAIN& path = bufferPolybase.COutline( 0 );
427 
428  if( path.PointCount() < 2 ) // should not happen
429  return;
430 
431  // Now, output the final polygon to DXF file:
432  last = path.PointCount() - 1;
433  VECTOR2I point = path.CPoint( 0 );
434 
435  wxPoint startPoint( point.x, point.y );
436  MoveTo( startPoint );
437 
438  for( int ii = 1; ii < path.PointCount(); ii++ )
439  {
440  point = path.CPoint( ii );
441  LineTo( wxPoint( point.x, point.y ) );
442  }
443 
444  // Close polygon, if needed
445  point = path.CPoint( last );
446  wxPoint endPoint( point.x, point.y );
447 
448  if( endPoint != startPoint )
449  LineTo( startPoint );
450 
451  PenFinish();
452 }
453 
454 
455 void DXF_PLOTTER::PenTo( const wxPoint& pos, char plume )
456 {
457  wxASSERT( outputFile );
458  if( plume == 'Z' )
459  {
460  return;
461  }
462  DPOINT pos_dev = userToDeviceCoordinates( pos );
463  DPOINT pen_lastpos_dev = userToDeviceCoordinates( penLastpos );
464 
465  if( penLastpos != pos && plume == 'D' )
466  {
467  // DXF LINE
468  wxString cname( m_currentColor.ToColour().GetAsString( wxC2S_CSS_SYNTAX ) );
469  fprintf( outputFile, "0\nLINE\n8\n%s\n10\n%g\n20\n%g\n11\n%g\n21\n%g\n",
470  TO_UTF8( cname ),
471  pen_lastpos_dev.x, pen_lastpos_dev.y, pos_dev.x, pos_dev.y );
472  }
473  penLastpos = pos;
474 }
475 
476 
480 void DXF_PLOTTER::SetDash( bool dashed )
481 {
482  // NOP for now
483 }
484 
485 
486 void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int aWidth,
487  EDA_DRAW_MODE_T aPlotMode, void* aData )
488 {
489  segmentAsOval( aStart, aEnd, aWidth, aPlotMode );
490 }
491 
492 /* Plot an arc in DXF format
493  * Filling is not supported
494  */
495 void DXF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
496  FILL_T fill, int width )
497 {
498  wxASSERT( outputFile );
499 
500  if( radius <= 0 )
501  return;
502 
503  // In DXF, arcs are drawn CCW.
504  // In Kicad, arcs are CW or CCW
505  // If StAngle > EndAngle, it is CW. So transform it to CCW
506  if( StAngle > EndAngle )
507  {
508  std::swap( StAngle, EndAngle );
509  }
510 
511  DPOINT centre_dev = userToDeviceCoordinates( centre );
512  double radius_dev = userToDeviceSize( radius );
513 
514  // Emit a DXF ARC entity
515  wxString cname( m_currentColor.ToColour().GetAsString( wxC2S_CSS_SYNTAX ) );
516  fprintf( outputFile,
517  "0\nARC\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n50\n%g\n51\n%g\n",
518  TO_UTF8( cname ),
519  centre_dev.x, centre_dev.y, radius_dev,
520  StAngle / 10.0, EndAngle / 10.0 );
521 }
522 
526 void DXF_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient,
527  EDA_DRAW_MODE_T trace_mode, void* aData )
528 {
529  wxASSERT( outputFile );
530  wxSize size( aSize );
531 
532  /* The chip is reduced to an oval tablet with size.y > size.x
533  * (Oval vertical orientation 0) */
534  if( size.x > size.y )
535  {
536  std::swap( size.x, size.y );
537  orient = AddAngles( orient, 900 );
538  }
539 
540  sketchOval( pos, size, orient, -1 );
541 }
542 
543 
548 void DXF_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre,
549  EDA_DRAW_MODE_T trace_mode, void* aData )
550 {
551  wxASSERT( outputFile );
552  Circle( pos, diametre, NO_FILL );
553 }
554 
555 
559 void DXF_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize,
560  double orient, EDA_DRAW_MODE_T trace_mode, void* aData )
561 {
562  wxASSERT( outputFile );
563  wxSize size;
564  int ox, oy, fx, fy;
565 
566  size.x = padsize.x / 2;
567  size.y = padsize.y / 2;
568 
569  if( size.x < 0 )
570  size.x = 0;
571  if( size.y < 0 )
572  size.y = 0;
573 
574  // If a dimension is zero, the trace is reduced to 1 line
575  if( size.x == 0 )
576  {
577  ox = pos.x;
578  oy = pos.y - size.y;
579  RotatePoint( &ox, &oy, pos.x, pos.y, orient );
580  fx = pos.x;
581  fy = pos.y + size.y;
582  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
583  MoveTo( wxPoint( ox, oy ) );
584  FinishTo( wxPoint( fx, fy ) );
585  return;
586  }
587  if( size.y == 0 )
588  {
589  ox = pos.x - size.x;
590  oy = pos.y;
591  RotatePoint( &ox, &oy, pos.x, pos.y, orient );
592  fx = pos.x + size.x;
593  fy = pos.y;
594  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
595  MoveTo( wxPoint( ox, oy ) );
596  FinishTo( wxPoint( fx, fy ) );
597  return;
598  }
599 
600  ox = pos.x - size.x;
601  oy = pos.y - size.y;
602  RotatePoint( &ox, &oy, pos.x, pos.y, orient );
603  MoveTo( wxPoint( ox, oy ) );
604 
605  fx = pos.x - size.x;
606  fy = pos.y + size.y;
607  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
608  LineTo( wxPoint( fx, fy ) );
609 
610  fx = pos.x + size.x;
611  fy = pos.y + size.y;
612  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
613  LineTo( wxPoint( fx, fy ) );
614 
615  fx = pos.x + size.x;
616  fy = pos.y - size.y;
617  RotatePoint( &fx, &fy, pos.x, pos.y, orient );
618  LineTo( wxPoint( fx, fy ) );
619 
620  FinishTo( wxPoint( ox, oy ) );
621 }
622 
623 void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
624  int aCornerRadius, double aOrient,
625  EDA_DRAW_MODE_T aTraceMode, void* aData )
626 {
627  SHAPE_POLY_SET outline;
628  const int segmentToCircleCount = 64;
629  TransformRoundRectToPolygon( outline, aPadPos, aSize, aOrient,
630  aCornerRadius, segmentToCircleCount );
631 
632  // TransformRoundRectToPolygon creates only one convex polygon
633  SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
634 
635  MoveTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
636 
637  for( int ii = 1; ii < poly.PointCount(); ++ii )
638  LineTo( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) );
639 
640  FinishTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
641 }
642 
643 void DXF_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize,
644  SHAPE_POLY_SET* aPolygons,
645  EDA_DRAW_MODE_T aTraceMode, void* aData )
646 {
647  for( int cnt = 0; cnt < aPolygons->OutlineCount(); ++cnt )
648  {
649  SHAPE_LINE_CHAIN& poly = aPolygons->Outline( cnt );
650 
651  MoveTo( wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
652 
653  for( int ii = 1; ii < poly.PointCount(); ++ii )
654  LineTo( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) );
655 
656  FinishTo(wxPoint( poly.Point( 0 ).x, poly.Point( 0 ).y ) );
657  }
658 }
659 
660 
664 void DXF_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
665  double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData )
666 {
667  wxASSERT( outputFile );
668  wxPoint coord[4]; /* coord actual corners of a trapezoidal trace */
669 
670  for( int ii = 0; ii < 4; ii++ )
671  {
672  coord[ii] = aCorners[ii];
673  RotatePoint( &coord[ii], aPadOrient );
674  coord[ii] += aPadPos;
675  }
676 
677  // Plot edge:
678  MoveTo( coord[0] );
679  LineTo( coord[1] );
680  LineTo( coord[2] );
681  LineTo( coord[3] );
682  FinishTo( coord[0] );
683 }
684 
693 bool containsNonAsciiChars( const wxString& string )
694 {
695  for( unsigned i = 0; i < string.length(); i++ )
696  {
697  wchar_t ch = string[i];
698  if( ch > 255 )
699  return true;
700  }
701  return false;
702 }
703 
704 void DXF_PLOTTER::Text( const wxPoint& aPos,
705  COLOR4D aColor,
706  const wxString& aText,
707  double aOrient,
708  const wxSize& aSize,
709  enum EDA_TEXT_HJUSTIFY_T aH_justify,
710  enum EDA_TEXT_VJUSTIFY_T aV_justify,
711  int aWidth,
712  bool aItalic,
713  bool aBold,
714  bool aMultilineAllowed,
715  void* aData )
716 {
717  // Fix me: see how to use DXF text mode for multiline texts
718  if( aMultilineAllowed && !aText.Contains( wxT( "\n" ) ) )
719  aMultilineAllowed = false; // the text has only one line.
720 
721  if( textAsLines || containsNonAsciiChars( aText ) || aMultilineAllowed )
722  {
723  // output text as graphics.
724  // Perhaps miltiline texts could be handled as DXF text entity
725  // but I do not want spend time about this (JPC)
726  PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify,
727  aWidth, aItalic, aBold, aMultilineAllowed );
728  }
729  else
730  {
731  /* Emit text as a text entity. This loses formatting and shape but it's
732  more useful as a CAD object */
733  DPOINT origin_dev = userToDeviceCoordinates( aPos );
734  SetColor( aColor );
735  wxString cname( m_currentColor.ToColour().GetAsString( wxC2S_CSS_SYNTAX ) );
736  DPOINT size_dev = userToDeviceSize( aSize );
737  int h_code = 0, v_code = 0;
738  switch( aH_justify )
739  {
741  h_code = 0;
742  break;
744  h_code = 1;
745  break;
747  h_code = 2;
748  break;
749  }
750  switch( aV_justify )
751  {
753  v_code = 3;
754  break;
756  v_code = 2;
757  break;
759  v_code = 1;
760  break;
761  }
762 
763  // Position, size, rotation and alignment
764  // The two alignment point usages is somewhat idiot (see the DXF ref)
765  // Anyway since we don't use the fit/aligned options, they're the same
766  fprintf( outputFile,
767  " 0\n"
768  "TEXT\n"
769  " 7\n"
770  "%s\n" // Text style
771  " 8\n"
772  "%s\n" // Layer name
773  " 10\n"
774  "%g\n" // First point X
775  " 11\n"
776  "%g\n" // Second point X
777  " 20\n"
778  "%g\n" // First point Y
779  " 21\n"
780  "%g\n" // Second point Y
781  " 40\n"
782  "%g\n" // Text height
783  " 41\n"
784  "%g\n" // Width factor
785  " 50\n"
786  "%g\n" // Rotation
787  " 51\n"
788  "%g\n" // Oblique angle
789  " 71\n"
790  "%d\n" // Mirror flags
791  " 72\n"
792  "%d\n" // H alignment
793  " 73\n"
794  "%d\n", // V alignment
795  aBold ? (aItalic ? "KICADBI" : "KICADB")
796  : (aItalic ? "KICADI" : "KICAD"),
797  TO_UTF8( cname ),
798  origin_dev.x, origin_dev.x,
799  origin_dev.y, origin_dev.y,
800  size_dev.y, fabs( size_dev.x / size_dev.y ),
801  aOrient / 10.0,
802  aItalic ? DXF_OBLIQUE_ANGLE : 0,
803  size_dev.x < 0 ? 2 : 0, // X mirror flag
804  h_code, v_code );
805 
806  /* There are two issue in emitting the text:
807  - Our overline character (~) must be converted to the appropriate
808  control sequence %%O or %%o
809  - Text encoding in DXF is more or less unspecified since depends on
810  the DXF declared version, the acad version reading it *and* some
811  system variables to be put in the header handled only by newer acads
812  Also before R15 unicode simply is not supported (you need to use
813  bigfonts which are a massive PITA). Common denominator solution:
814  use Latin1 (and however someone could choke on it, anyway). Sorry
815  for the extended latin people. If somewant want to try fixing this
816  recent version seems to use UTF-8 (and not UCS2 like the rest of
817  Windows)
818 
819  XXX Actually there is a *third* issue: older DXF formats are limited
820  to 255 bytes records (it was later raised to 2048); since I'm lazy
821  and text so long is not probable I just don't implement this rule.
822  If someone is interested in fixing this, you have to emit the first
823  partial lines with group code 3 (max 250 bytes each) and then finish
824  with a group code 1 (less than 250 bytes). The DXF refs explains it
825  in no more details...
826  */
827 
828  bool overlining = false;
829  fputs( " 1\n", outputFile );
830  for( unsigned i = 0; i < aText.length(); i++ )
831  {
832  /* Here I do a bad thing: writing the output one byte at a time!
833  but today I'm lazy and I have no idea on how to coerce a Unicode
834  wxString to spit out latin1 encoded text ...
835 
836  Atleast stdio is *supposed* to do output buffering, so there is
837  hope is not too slow */
838  wchar_t ch = aText[i];
839  if( ch > 255 )
840  {
841  // I can't encode this...
842  putc( '?', outputFile );
843  }
844  else
845  {
846  if( ch == '~' )
847  {
848  // Handle the overline toggle
849  fputs( overlining ? "%%o" : "%%O", outputFile );
850  overlining = !overlining;
851  }
852  else
853  {
854  putc( ch, outputFile );
855  }
856  }
857  }
858  putc( '\n', outputFile );
859  }
860 }
861 
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: plot_common.h:241
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...
EDA_COLOR_T
NOTE: EDA_COLOR_T is deprecated and is kept around for compatibility with legacy canvas.
Definition: colors.h:42
EDA_TEXT_HJUSTIFY_T
Definition: eda_text.h:47
void PenFinish()
Definition: plot_common.h:247
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't support line widths and mirroring...
int PointCount() const
Function PointCount()
bool textAsLines
Definition: plot_common.h:1296
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...
virtual void SetDash(bool dashed) override
Dashed lines are not (yet) supported by DXF_PLOTTER.
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
static const double DXF_OBLIQUE_ANGLE
Oblique angle for DXF native text (I don't remember if 15 degrees is the ISO value...
bool colorMode
Definition: plot_common.h:537
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
COLOR4D m_currentColor
Definition: plot_common.h:1297
int OutlineCount() const
Returns the number of outlines in the set
double m_IUsPerDecimil
Definition: plot_common.h:519
wxPoint plotOffset
Plot offset (in IUs)
Definition: plot_common.h:525
wxPoint penLastpos
Last pen positions; set to -1,-1 when the pen is at rest.
Definition: plot_common.h:544
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.
Definition: drawtxt.cpp:227
#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
void LineTo(const wxPoint &pos)
Definition: plot_common.h:236
bool m_plotMirror
X axis orientation (SVG) and plot mirrored (only for PS, PDF HPGL and SVG)
Definition: plot_common.h:529
virtual bool StartPlot() override
Opens the DXF plot with a skeleton header.
bool containsNonAsciiChars(const wxString &string)
Checks if a given string contains non-ASCII characters.
int Append(int x, int y, int aOutline=-1, int aHole=-1)
Appends a vertex at the end of the given outline/hole (default: the last outline) ...
T AddAngles(T a1, T2 a2)
Add two angles (keeping the result normalized). T2 is here.
Definition: trigo.h:246
Class SHAPE_POLY_SET.
Base window classes and related definitions.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
virtual void FlashPadTrapez(const wxPoint &aPadPos, const wxPoint *aCorners, double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void *aData) override
DXF trapezoidal pad: only sketch mode is supported.
EDA_DRAW_MODE_T
Definition: eda_text.h:62
double plotScale
Plot scale - chosen by the user (even implicitly with 'fit in a4')
Definition: plot_common.h:513
virtual bool EndPlot() override
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Common plot library Plot settings, and plotting engines (Postscript, Gerber, HPGL and DXF) ...
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...
virtual DPOINT userToDeviceSize(const wxSize &size)
Modifies size according to the plotter scale factors (wxSize version, returns a DPOINT) ...
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:54
void MoveTo(const wxPoint &pos)
Definition: plot_common.h:231
virtual DPOINT userToDeviceCoordinates(const wxPoint &aCoordinate)
Modifies coordinates according to the orientation, scale factor, and offsets trace.
Class SHAPE_LINE_CHAIN.
virtual void SetDefaultLineWidth(int width) override
Set the default line width.
Definition: plot_common.h:1243
FILE * outputFile
true if the Y axis is top to bottom (SVG)
Definition: plot_common.h:534
virtual void SetColor(COLOR4D color) override
The DXF exporter handles 'colors' as layers...
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:56
VECTOR2I & Point(int aIndex)
Function Point()
Definition: colors.h:45
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: plot_common.h:522
void segmentAsOval(const wxPoint &start, const wxPoint &end, int width, EDA_DRAW_MODE_T tracemode)
Cdonvert a thick segment and plot it as an oval.
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)
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: plot_common.h:550
EDA_COLOR_T NextColor(EDA_COLOR_T &aColor)
Definition: colors.h:87
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39