KiCad PCB EDA Suite
GERBER_plotter.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
30 #include <fctsys.h>
31 #include <gr_basic.h>
32 #include <trigo.h>
33 #include <eda_base_frame.h>
34 #include <base_struct.h>
35 #include <common.h>
36 #include <plotter.h>
37 #include <macros.h>
38 #include <kicad_string.h>
40 #include <math/util.h> // for KiROUND
41 
42 #include <build_version.h>
43 
44 #include <gbr_metadata.h>
45 
46 
48 {
49  workFile = NULL;
50  finalFile = NULL;
53 
54  // number of digits after the point (number of digits of the mantissa
55  // Be carefull: the Gerber coordinates are stored in an integer
56  // so 6 digits (inches) or 5 digits (mm) is a good value
57  // To avoid overflow, 7 digits (inches) or 6 digits is a max.
58  // with lower values than 6 digits (inches) or 5 digits (mm),
59  // Creating self-intersecting polygons from non-intersecting polygons
60  // happen easily.
61  m_gerberUnitInch = false;
62  m_gerberUnitFmt = 6;
63  m_useX2format = true;
64  m_useNetAttributes = true;
65 }
66 
67 
68 void GERBER_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
69  double aScale, bool aMirror )
70 {
71  wxASSERT( aMirror == false );
72  m_plotMirror = false;
73  plotOffset = aOffset;
74  wxASSERT( aScale == 1 ); // aScale parameter is not used in Gerber
75  plotScale = 1; // Plot scale is *always* 1.0
76 
77  m_IUsPerDecimil = aIusPerDecimil;
78  // gives now a default value to iuPerDeviceUnit (because the units of the caller is now known)
79  // which could be modified later by calling SetGerberCoordinatesFormat()
80  iuPerDeviceUnit = pow( 10.0, m_gerberUnitFmt ) / ( m_IUsPerDecimil * 10000.0 );
81 
82  // We don't handle the filmbox, and it's more useful to keep the
83  // origin at the origin
84  paperSize.x = 0;
85  paperSize.y = 0;
86  SetDefaultLineWidth( 100 * aIusPerDecimil ); // Arbitrary default
87 }
88 
89 
90 void GERBER_PLOTTER::SetGerberCoordinatesFormat( int aResolution, bool aUseInches )
91 {
92  m_gerberUnitInch = aUseInches;
93  m_gerberUnitFmt = aResolution;
94 
95  iuPerDeviceUnit = pow( 10.0, m_gerberUnitFmt ) / ( m_IUsPerDecimil * 10000.0 );
96 
97  if( ! m_gerberUnitInch )
98  iuPerDeviceUnit *= 25.4; // gerber output in mm
99 }
100 
101 
102 void GERBER_PLOTTER::emitDcode( const DPOINT& pt, int dcode )
103 {
104 
105  fprintf( outputFile, "X%dY%dD%02d*\n", KiROUND( pt.x ), KiROUND( pt.y ), dcode );
106 }
107 
109 {
110  // Remove all attributes from object attributes dictionary (TO. and TA commands)
111  if( m_useX2format )
112  fputs( "%TD*%\n", outputFile );
113  else
114  fputs( "G04 #@! TD*\n", outputFile );
115 
117 }
118 
119 
121 {
122  // disable a Gerber net attribute (exists only in X2 with net attributes mode).
123  if( m_objectAttributesDictionnary.empty() ) // No net attribute or not X2 mode
124  return;
125 
126  // Remove all net attributes from object attributes dictionary
127  if( m_useX2format )
128  fputs( "%TD*%\n", outputFile );
129  else
130  fputs( "G04 #@! TD*\n", outputFile );
131 
133 }
134 
135 
136 void GERBER_PLOTTER::StartBlock( void* aData )
137 {
138  // Currently, it is the same as EndBlock(): clear all aperture net attributes
139  EndBlock( aData );
140 }
141 
142 
143 void GERBER_PLOTTER::EndBlock( void* aData )
144 {
145  // Remove all net attributes from object attributes dictionary
147 }
148 
149 
151 {
152  // print a Gerber net attribute record.
153  // it is added to the object attributes dictionary
154  // On file, only modified or new attributes are printed.
155  if( aData == NULL )
156  return;
157 
158  if( !m_useNetAttributes )
159  return;
160 
161  bool useX1StructuredComment = !m_useX2format;
162 
163  bool clearDict;
164  std::string short_attribute_string;
165 
166  if( !FormatNetAttribute( short_attribute_string, m_objectAttributesDictionnary,
167  aData, clearDict, useX1StructuredComment ) )
168  return;
169 
170  if( clearDict )
172 
173  if( !short_attribute_string.empty() )
174  fputs( short_attribute_string.c_str(), outputFile );
175 
176  if( m_useX2format && !aData->m_ExtraData.IsEmpty() )
177  {
178  std::string extra_data = TO_UTF8( aData->m_ExtraData );
179  fputs( extra_data.c_str(), outputFile );
180  }
181 }
182 
183 
185 {
186  wxASSERT( outputFile );
187 
188  finalFile = outputFile; // the actual gerber file will be created later
189 
190  // Create a temporary filename to store gerber file
191  // note tmpfile() does not work under Vista and W7 in user mode
192  m_workFilename = filename + wxT(".tmp");
193  workFile = wxFopen( m_workFilename, wxT( "wt" ));
195  wxASSERT( outputFile );
196 
197  if( outputFile == NULL )
198  return false;
199 
200  for( unsigned ii = 0; ii < m_headerExtraLines.GetCount(); ii++ )
201  {
202  if( ! m_headerExtraLines[ii].IsEmpty() )
203  fprintf( outputFile, "%s\n", TO_UTF8( m_headerExtraLines[ii] ) );
204  }
205 
206  // Set coordinate format to 3.6 or 4.5 absolute, leading zero omitted
207  // the number of digits for the integer part of coordinates is needed
208  // in gerber format, but is not very important when omitting leading zeros
209  // It is fixed here to 3 (inch) or 4 (mm), but is not actually used
210  int leadingDigitCount = m_gerberUnitInch ? 3 : 4;
211 
212  fprintf( outputFile, "%%FSLAX%d%dY%d%d*%%\n",
213  leadingDigitCount, m_gerberUnitFmt,
214  leadingDigitCount, m_gerberUnitFmt );
215  fprintf( outputFile,
216  "G04 Gerber Fmt %d.%d, Leading zero omitted, Abs format (unit %s)*\n",
217  leadingDigitCount, m_gerberUnitFmt,
218  m_gerberUnitInch ? "inch" : "mm" );
219 
220  wxString Title = creator + wxT( " " ) + GetBuildVersion();
221  // In gerber files, ASCII7 chars only are allowed.
222  // So use a ISO date format (using a space as separator between date and time),
223  // not a localized date format
224  wxDateTime date = wxDateTime::Now();
225  fprintf( outputFile, "G04 Created by KiCad (%s) date %s*\n",
226  TO_UTF8( Title ), TO_UTF8( date.FormatISOCombined( ' ') ) );
227 
228  /* Mass parameter: unit = INCHES/MM */
229  if( m_gerberUnitInch )
230  fputs( "%MOIN*%\n", outputFile );
231  else
232  fputs( "%MOMM*%\n", outputFile );
233 
234  // Be sure the usual dark polarity is selected:
235  fputs( "%LPD*%\n", outputFile );
236 
237  // Set initial interpolation mode: always G01 (linear):
238  fputs( "G01*\n", outputFile );
239 
240  // Set aperture list starting point:
241  fputs( "G04 APERTURE LIST*\n", outputFile );
242 
243  return true;
244 }
245 
246 
248 {
249  char line[1024];
250  wxString msg;
251 
252  wxASSERT( outputFile );
253 
254  /* Outfile is actually a temporary file i.e. workFile */
255  fputs( "M02*\n", outputFile );
256  fflush( outputFile );
257 
258  fclose( workFile );
259  workFile = wxFopen( m_workFilename, wxT( "rt" ));
260  wxASSERT( workFile );
262 
263  // Placement of apertures in RS274X
264  while( fgets( line, 1024, workFile ) )
265  {
266  fputs( line, outputFile );
267 
268  char* substr = strtok( line, "\n\r" );
269 
270  if( substr && strcmp( substr, "G04 APERTURE LIST*" ) == 0 )
271  {
273  fputs( "G04 APERTURE END LIST*\n", outputFile );
274  }
275  }
276 
277  fclose( workFile );
278  fclose( finalFile );
279  ::wxRemoveFile( m_workFilename );
280  outputFile = 0;
281 
282  return true;
283 }
284 
285 
287 {
288  defaultPenWidth = width;
290 }
291 
292 
293 void GERBER_PLOTTER::SetCurrentLineWidth( int width, void* aData )
294 {
295  if( width == DO_NOT_SET_LINE_WIDTH )
296  return;
297 
298  int pen_width;
299 
300  if( width > 0 )
301  pen_width = width;
302  else
303  pen_width = defaultPenWidth;
304 
305  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
306  int aperture_attribute = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
307 
308  selectAperture( wxSize( pen_width, pen_width ), APERTURE::AT_PLOTTING, aperture_attribute );
309  currentPenWidth = pen_width;
310 }
311 
312 
313 int GERBER_PLOTTER::GetOrCreateAperture( const wxSize& aSize,
314  APERTURE::APERTURE_TYPE aType, int aApertureAttribute )
315 {
316  int last_D_code = 9;
317 
318  // Search an existing aperture
319  for( int idx = 0; idx < (int)m_apertures.size(); ++idx )
320  {
321  APERTURE* tool = &m_apertures[idx];
322  last_D_code = tool->m_DCode;
323 
324  if( (tool->m_Type == aType) && (tool->m_Size == aSize) &&
325  (tool->m_ApertureAttribute == aApertureAttribute) )
326  return idx;
327  }
328 
329  // Allocate a new aperture
330  APERTURE new_tool;
331  new_tool.m_Size = aSize;
332  new_tool.m_Type = aType;
333  new_tool.m_DCode = last_D_code + 1;
334  new_tool.m_ApertureAttribute = aApertureAttribute;
335 
336  m_apertures.push_back( new_tool );
337 
338  return m_apertures.size() - 1;
339 }
340 
341 
342 void GERBER_PLOTTER::selectAperture( const wxSize& aSize,
344  int aApertureAttribute )
345 {
346  bool change = ( m_currentApertureIdx < 0 ) ||
347  ( m_apertures[m_currentApertureIdx].m_Type != aType ) ||
348  ( m_apertures[m_currentApertureIdx].m_Size != aSize );
349 
350  if( !change )
351  change = m_apertures[m_currentApertureIdx].m_ApertureAttribute != aApertureAttribute;
352 
353  if( change )
354  {
355  // Pick an existing aperture or create a new one
356  m_currentApertureIdx = GetOrCreateAperture( aSize, aType, aApertureAttribute );
357  fprintf( outputFile, "D%d*\n", m_apertures[m_currentApertureIdx].m_DCode );
358  }
359 }
360 
361 void GERBER_PLOTTER::selectAperture( int aDiameter, double aPolygonRotation,
362  APERTURE::APERTURE_TYPE aType, int aApertureAttribute )
363 {
364  // Pick an existing aperture or create a new one, matching the
365  // aDiameter, aPolygonRotation, type and attributes for type =
366  // AT_REGULAR_POLY3 to AT_REGULAR_POLY12
367 
368  wxASSERT( aType>= APERTURE::APERTURE_TYPE::AT_REGULAR_POLY3 &&
369  aType <= APERTURE::APERTURE_TYPE::AT_REGULAR_POLY12 );
370 
371  // To use selectAperture( size, ... ) calculate a equivalent aperture size:
372  // for AT_REGULAR_POLYxx the parameter APERTURE::m_Size contains
373  // aDiameter (in m_Size.x) and aPolygonRotation in 1/1000 degree (in m_Size.y)
374  wxSize size( aDiameter, (int)( aPolygonRotation * 1000.0 ) );
375  selectAperture( size, aType, aApertureAttribute );
376 }
377 
379 {
380  wxASSERT( outputFile );
381  char cbuf[1024];
382 
383  bool useX1StructuredComment = false;
384 
385  if( !m_useX2format )
386  useX1StructuredComment = true;
387 
388  // Init
389  for( APERTURE& tool : m_apertures )
390  {
391  // apertude sizes are in inch or mm, regardless the
392  // coordinates format
393  double fscale = 0.0001 * plotScale / m_IUsPerDecimil; // inches
394 
395  if(! m_gerberUnitInch )
396  fscale *= 25.4; // size in mm
397 
398  int attribute = tool.m_ApertureAttribute;
399 
400  if( attribute != m_apertureAttribute )
401  {
404  useX1StructuredComment ).c_str(), outputFile );
405  }
406 
407  char* text = cbuf + sprintf( cbuf, "%%ADD%d", tool.m_DCode );
408 
409  /* Please note: the Gerber specs for mass parameters say that
410  exponential syntax is *not* allowed and the decimal point should
411  also be always inserted. So the %g format is ruled out, but %f is fine
412  (the # modifier forces the decimal point). Sadly the %f formatter
413  can't remove trailing zeros but thats not a problem, since nothing
414  forbid it (the file is only slightly longer) */
415 
416  switch( tool.m_Type )
417  {
418  case APERTURE::AT_CIRCLE:
419  sprintf( text, "C,%#f*%%\n", tool.GetDiameter() * fscale );
420  break;
421 
422  case APERTURE::AT_RECT:
423  sprintf( text, "R,%#fX%#f*%%\n", tool.m_Size.x * fscale,
424  tool.m_Size.y * fscale );
425  break;
426 
428  sprintf( text, "C,%#f*%%\n", tool.m_Size.x * fscale );
429  break;
430 
431  case APERTURE::AT_OVAL:
432  sprintf( text, "O,%#fX%#f*%%\n", tool.m_Size.x * fscale,
433  tool.m_Size.y * fscale );
434  break;
435 
447  sprintf( text, "P,%#fX%dX%#f*%%\n", tool.GetDiameter() * fscale,
448  tool.GetVerticeCount(), tool.GetRotation() );
449  break;
450  }
451 
452  fputs( cbuf, outputFile );
453 
454  m_apertureAttribute = attribute;
455 
456  // Currently reset the aperture attribute. Perhaps a better optimization
457  // is to store the last attribute
458  if( attribute )
459  {
460  if( m_useX2format )
461  fputs( "%TD*%\n", outputFile );
462  else
463  fputs( "G04 #@! TD*\n", outputFile );
464 
466  }
467 
468  }
469 }
470 
471 
472 void GERBER_PLOTTER::PenTo( const wxPoint& aPos, char plume )
473 {
474  wxASSERT( outputFile );
475  DPOINT pos_dev = userToDeviceCoordinates( aPos );
476 
477  switch( plume )
478  {
479  case 'Z':
480  break;
481 
482  case 'U':
483  emitDcode( pos_dev, 2 );
484  break;
485 
486  case 'D':
487  emitDcode( pos_dev, 1 );
488  }
489 
490  penState = plume;
491 }
492 
493 
494 void GERBER_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width )
495 {
496  std::vector< wxPoint > cornerList;
497 
498  // Build corners list
499  cornerList.push_back( p1 );
500  wxPoint corner(p1.x, p2.y);
501  cornerList.push_back( corner );
502  cornerList.push_back( p2 );
503  corner.x = p2.x;
504  corner.y = p1.y;
505  cornerList.push_back( corner );
506  cornerList.push_back( p1 );
507 
508  PlotPoly( cornerList, fill, width );
509 }
510 
511 
512 void GERBER_PLOTTER::Circle( const wxPoint& aCenter, int aDiameter, FILL_T aFill, int aWidth )
513 {
514  Arc( aCenter, 0, 3600, aDiameter / 2, aFill, aWidth );
515 }
516 
517 
518 void GERBER_PLOTTER::Arc( const wxPoint& aCenter, double aStAngle, double aEndAngle,
519  int aRadius, FILL_T aFill, int aWidth )
520 {
521  SetCurrentLineWidth( aWidth );
522 
523  wxPoint start, end;
524  start.x = aCenter.x + KiROUND( cosdecideg( aRadius, aStAngle ) );
525  start.y = aCenter.y - KiROUND( sindecideg( aRadius, aStAngle ) );
526  MoveTo( start );
527  end.x = aCenter.x + KiROUND( cosdecideg( aRadius, aEndAngle ) );
528  end.y = aCenter.y - KiROUND( sindecideg( aRadius, aEndAngle ) );
529  DPOINT devEnd = userToDeviceCoordinates( end );
530  DPOINT devCenter = userToDeviceCoordinates( aCenter ) - userToDeviceCoordinates( start );
531 
532  fprintf( outputFile, "G75*\n" ); // Multiquadrant (360 degrees) mode
533 
534  if( aStAngle < aEndAngle )
535  fprintf( outputFile, "G03*\n" ); // Active circular interpolation, CCW
536  else
537  fprintf( outputFile, "G02*\n" ); // Active circular interpolation, CW
538 
539  fprintf( outputFile, "X%dY%dI%dJ%dD01*\n",
540  KiROUND( devEnd.x ), KiROUND( devEnd.y ),
541  KiROUND( devCenter.x ), KiROUND( devCenter.y ) );
542 
543  fprintf( outputFile, "G01*\n" ); // Back to linear interpol (perhaps useless here).
544 }
545 
546 
547 void GERBER_PLOTTER::PlotGerberRegion( const std::vector< wxPoint >& aCornerList,
548  void * aData )
549 {
550  if( aCornerList.size() <= 2 )
551  return;
552 
553  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
554 
555  bool clearTA_AperFunction = false; // true if a TA.AperFunction is used
556 
557  if( gbr_metadata )
558  {
559  std::string attrib = gbr_metadata->m_ApertureMetadata.FormatAttribute( !m_useX2format );
560 
561  if( !attrib.empty() )
562  {
563  fputs( attrib.c_str(), outputFile );
564  clearTA_AperFunction = true;
565  }
566  }
567 
568  PlotPoly( aCornerList, FILLED_SHAPE, 0 , gbr_metadata );
569 
570  // Clear the TA attribute, to avoid the next item to inherit it:
571  if( clearTA_AperFunction )
572  {
573  if( m_useX2format )
574  {
575  fputs( "%TD.AperFunction*%\n", outputFile );
576  }
577  else
578  {
579  fputs( "G04 #@! TD.AperFunction*\n", outputFile );
580  }
581  }
582 }
583 
584 void GERBER_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
585  FILL_T aFill, int aWidth, void * aData )
586 {
587  if( aCornerList.size() <= 1 )
588  return;
589 
590  // Gerber format does not know filled polygons with thick outline
591  // Therefore, to plot a filled polygon with outline having a thickness,
592  // one should plot outline as thick segments
593  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
594 
595  if( gbr_metadata )
596  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
597 
598  if( aFill )
599  {
600  fputs( "G36*\n", outputFile );
601 
602  MoveTo( aCornerList[0] );
603  fputs( "G01*\n", outputFile ); // Set linear interpolation.
604 
605  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
606  LineTo( aCornerList[ii] );
607 
608  // If the polygon is not closed, close it:
609  if( aCornerList[0] != aCornerList[aCornerList.size()-1] )
610  FinishTo( aCornerList[0] );
611 
612  fputs( "G37*\n", outputFile );
613  }
614 
615  if( aWidth > 0 ) // Draw the polyline/polygon outline
616  {
617  SetCurrentLineWidth( aWidth, gbr_metadata );
618 
619  MoveTo( aCornerList[0] );
620 
621  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
622  LineTo( aCornerList[ii] );
623 
624  // Ensure the thick outline is closed for filled polygons
625  // (if not filled, could be only a polyline)
626  if( aFill && ( aCornerList[aCornerList.size()-1] != aCornerList[0] ) )
627  LineTo( aCornerList[0] );
628 
629  PenFinish();
630  }
631 }
632 
633 
634 void GERBER_PLOTTER::ThickSegment( const wxPoint& start, const wxPoint& end, int width,
635  EDA_DRAW_MODE_T tracemode, void* aData )
636 {
637  if( tracemode == FILLED )
638  {
639  GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
640  SetCurrentLineWidth( width, gbr_metadata );
641 
642  if( gbr_metadata )
643  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
644 
645  MoveTo( start );
646  FinishTo( end );
647  }
648  else
649  {
651  segmentAsOval( start, end, width, tracemode );
652  }
653 }
654 
655 void GERBER_PLOTTER::ThickArc( const wxPoint& centre, double StAngle, double EndAngle,
656  int radius, int width, EDA_DRAW_MODE_T tracemode, void* aData )
657 {
658  GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
659  SetCurrentLineWidth( width, gbr_metadata );
660 
661  if( gbr_metadata )
662  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
663 
664  if( tracemode == FILLED )
665  Arc( centre, StAngle, EndAngle, radius, NO_FILL, DO_NOT_SET_LINE_WIDTH );
666  else
667  {
669  Arc( centre, StAngle, EndAngle,
670  radius - ( width - currentPenWidth ) / 2,
672  Arc( centre, StAngle, EndAngle,
673  radius + ( width - currentPenWidth ) / 2, NO_FILL,
675  }
676 }
677 
678 
679 void GERBER_PLOTTER::ThickRect( const wxPoint& p1, const wxPoint& p2, int width,
680  EDA_DRAW_MODE_T tracemode, void* aData )
681 {
682  GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
683  SetCurrentLineWidth( width, gbr_metadata );
684 
685  if( gbr_metadata )
686  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
687 
688  if( tracemode == FILLED )
689  Rect( p1, p2, NO_FILL, DO_NOT_SET_LINE_WIDTH );
690  else
691  {
693  wxPoint offsetp1( p1.x - (width - currentPenWidth) / 2,
694  p1.y - (width - currentPenWidth) / 2 );
695  wxPoint offsetp2( p2.x + (width - currentPenWidth) / 2,
696  p2.y + (width - currentPenWidth) / 2 );
697  Rect( offsetp1, offsetp2, NO_FILL, -1 );
698  offsetp1.x += (width - currentPenWidth);
699  offsetp1.y += (width - currentPenWidth);
700  offsetp2.x -= (width - currentPenWidth);
701  offsetp2.y -= (width - currentPenWidth);
702  Rect( offsetp1, offsetp2, NO_FILL, DO_NOT_SET_LINE_WIDTH );
703  }
704 }
705 
706 
707 void GERBER_PLOTTER::ThickCircle( const wxPoint& pos, int diametre, int width,
708  EDA_DRAW_MODE_T tracemode, void* aData )
709 {
710  GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
711  SetCurrentLineWidth( width, gbr_metadata );
712 
713  if( gbr_metadata )
714  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
715 
716  if( tracemode == FILLED )
717  Circle( pos, diametre, NO_FILL, DO_NOT_SET_LINE_WIDTH );
718  else
719  {
721  Circle( pos, diametre - (width - currentPenWidth),
723  Circle( pos, diametre + (width - currentPenWidth),
725  }
726 }
727 
728 
729 void GERBER_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, EDA_DRAW_MODE_T trace_mode, void* aData )
730 {
731  wxSize size( diametre, diametre );
732  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
733 
734  if( trace_mode == SKETCH )
735  {
737 
738  if( gbr_metadata )
739  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
740 
742  }
743  else
744  {
745  DPOINT pos_dev = userToDeviceCoordinates( pos );
746 
747  int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
748  selectAperture( size, APERTURE::AT_CIRCLE, aperture_attrib );
749 
750  if( gbr_metadata )
751  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
752 
753  emitDcode( pos_dev, 3 );
754  }
755 }
756 
757 
758 void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient,
759  EDA_DRAW_MODE_T trace_mode, void* aData )
760 {
761  wxASSERT( outputFile );
762  wxSize size( aSize );
763  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
764 
765  // Flash a vertical or horizontal shape (this is a basic aperture).
766  if( ( orient == 0 || orient == 900 || orient == 1800 || orient == 2700 )
767  && trace_mode == FILLED )
768  {
769  if( orient == 900 || orient == 2700 ) /* orientation turned 90 deg. */
770  std::swap( size.x, size.y );
771 
772  DPOINT pos_dev = userToDeviceCoordinates( pos );
773  int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
774  selectAperture( size, APERTURE::AT_OVAL, aperture_attrib );
775 
776  if( gbr_metadata )
777  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
778 
779  emitDcode( pos_dev, 3 );
780  }
781  else // Plot pad as region.
782  // Only regions and flashed items accept a object attribute TO.P for the pin name
783  {
784  if( size.x > size.y )
785  {
786  std::swap( size.x, size.y );
787 
788  if( orient < 2700 )
789  orient += 900;
790  else
791  orient -= 2700;
792  }
793 
794  if( trace_mode == FILLED )
795  {
796  // TODO: use an aperture macro to declare the rotated pad
797  // to be able to flash the shape
798  // For now, the pad is drawn as thick segment (painted with only one segment)
799 
800  // The pad is reduced to an segment with dy > dx
801  int delta = size.y - size.x;
802  wxPoint p0( 0, -delta / 2 );
803  wxPoint p1( 0, delta / 2 );
804  RotatePoint( &p0.x, &p0.y, orient );
805  RotatePoint( &p1.x, &p1.y, orient );
806 
807  ThickSegment( pos + p0, pos + p1, size.x, trace_mode, gbr_metadata );
808  }
809  else
810  sketchOval( pos, size, orient, -1 );
811  }
812 }
813 
814 
815 void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize,
816  double orient, EDA_DRAW_MODE_T trace_mode, void* aData )
817 
818 {
819  wxASSERT( outputFile );
820  wxSize size( aSize );
821  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
822 
823  // Plot as an aperture flash
824  switch( int( orient ) )
825  {
826  case 900:
827  case 2700: // rotation of 90 degrees or 270 swaps sizes
828  std::swap( size.x, size.y );
829  // Intentionally fall through
830  case 0:
831  case 1800:
832  if( trace_mode == SKETCH )
833  {
835 
836  if( gbr_metadata )
837  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
838 
839  Rect( wxPoint( pos.x - (size.x - currentPenWidth) / 2,
840  pos.y - (size.y - currentPenWidth) / 2 ),
841  wxPoint( pos.x + (size.x - currentPenWidth) / 2,
842  pos.y + (size.y - currentPenWidth) / 2 ),
844  }
845  else
846  {
847  DPOINT pos_dev = userToDeviceCoordinates( pos );
848  int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
849  selectAperture( size, APERTURE::AT_RECT, aperture_attrib );
850 
851  if( gbr_metadata )
852  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
853 
854  emitDcode( pos_dev, 3 );
855  }
856  break;
857 
858  default: // plot pad shape as polygon
859  {
860  // XXX to do: use an aperture macro to declare the rotated pad
861  wxPoint coord[4];
862  // coord[0] is assumed the lower left
863  // coord[1] is assumed the upper left
864  // coord[2] is assumed the upper right
865  // coord[3] is assumed the lower right
866 
867  /* Trace the outline. */
868  coord[0].x = -size.x/2; // lower left
869  coord[0].y = size.y/2;
870  coord[1].x = -size.x/2; // upper left
871  coord[1].y = -size.y/2;
872  coord[2].x = size.x/2; // upper right
873  coord[2].y = -size.y/2;
874  coord[3].x = size.x/2; // lower right
875  coord[3].y = size.y/2;
876 
877  FlashPadTrapez( pos, coord, orient, trace_mode, aData );
878  }
879  break;
880  }
881 }
882 
883 void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
884  int aCornerRadius, double aOrient,
885  EDA_DRAW_MODE_T aTraceMode, void* aData )
886 
887 {
888  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
889 
890  // Currently, a Pad RoundRect is plotted as polygon.
891  // TODO: use Aperture macro and flash it
892  SHAPE_POLY_SET outline;
893  TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient,
894  aCornerRadius, 0.0, 0, GetPlotterArcHighDef() );
895 
896  if( aTraceMode != FILLED )
897  {
899  outline.Inflate( -GetCurrentLineWidth()/2, 16 );
900  }
901 
902  std::vector< wxPoint > cornerList;
903  // TransformRoundRectToPolygon creates only one convex polygon
904  SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
905  cornerList.reserve( poly.PointCount() + 1 );
906 
907  for( int ii = 0; ii < poly.PointCount(); ++ii )
908  cornerList.emplace_back( poly.CPoint( ii ).x, poly.CPoint( ii ).y );
909 
910  // Close polygon
911  cornerList.push_back( cornerList[0] );
912 
913  if( aTraceMode == SKETCH )
914  PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), gbr_metadata );
915  else
916  PlotGerberRegion( cornerList, gbr_metadata );
917 }
918 
919 void GERBER_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize,
920  SHAPE_POLY_SET* aPolygons,
921  EDA_DRAW_MODE_T aTraceMode, void* aData )
922 
923 {
924  // A Pad custom is plotted as polygon (a region in Gerber language).
925 
926  GBR_METADATA gbr_metadata;
927 
928  if( aData )
929  gbr_metadata = *static_cast<GBR_METADATA*>( aData );
930 
931  SHAPE_POLY_SET polyshape = *aPolygons;
932 
933  if( aTraceMode != FILLED )
934  {
936  polyshape.Inflate( -GetCurrentLineWidth()/2, 16 );
937  }
938 
939  std::vector< wxPoint > cornerList;
940 
941  for( int cnt = 0; cnt < polyshape.OutlineCount(); ++cnt )
942  {
943  SHAPE_LINE_CHAIN& poly = polyshape.Outline( cnt );
944 
945  cornerList.clear();
946 
947  for( int ii = 0; ii < poly.PointCount(); ++ii )
948  cornerList.emplace_back( poly.CPoint( ii ).x, poly.CPoint( ii ).y );
949 
950  // Close polygon
951  cornerList.push_back( cornerList[0] );
952 
953  if( aTraceMode == SKETCH )
954  PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), &gbr_metadata );
955  else
956  PlotGerberRegion( cornerList, &gbr_metadata );
957  }
958 }
959 
960 
961 void GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCorners,
962  double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData )
963 
964 {
965  // TODO: use Aperture macro and flash it
966 
967  // polygon corners list
968  std::vector<wxPoint> cornerList = { aCorners[0], aCorners[1], aCorners[2], aCorners[3] };
969 
970  // Draw the polygon and fill the interior as required
971  for( unsigned ii = 0; ii < 4; ii++ )
972  {
973  RotatePoint( &cornerList[ii], aPadOrient );
974  cornerList[ii] += aPadPos;
975  }
976 
977  // Close the polygon
978  cornerList.push_back( cornerList[0] );
979  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
980 
981  GBR_METADATA metadata;
982 
983  if( gbr_metadata )
984  metadata = *gbr_metadata;
985 
986  if( aTrace_Mode == SKETCH )
988  &metadata );
989  else
990  PlotGerberRegion( cornerList, &metadata );
991 }
992 
993 
995  int aDiameter, int aCornerCount,
996  double aOrient, EDA_DRAW_MODE_T aTraceMode,
997  void* aData )
998 {
999  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
1000 
1001  if( aTraceMode == SKETCH )
1002  {
1003  // Build the polygon:
1004  std::vector< wxPoint > cornerList;
1005 
1006  double angle_delta = 3600.0 / aCornerCount; // in 0.1 degree
1007 
1008  for( int ii = 0; ii < aCornerCount; ii++ )
1009  {
1010  double rot = aOrient + (angle_delta*ii);
1011  wxPoint vertice( aDiameter/2, 0 );
1012  RotatePoint( &vertice, rot );
1013  vertice += aShapePos;
1014  cornerList.push_back( vertice );
1015  }
1016 
1017  cornerList.push_back( cornerList[0] ); // Close the shape
1018 
1019  SetCurrentLineWidth( aDiameter/8, gbr_metadata );
1020  PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), gbr_metadata );
1021  }
1022  else
1023  {
1024  DPOINT pos_dev = userToDeviceCoordinates( aShapePos );
1025 
1026  int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
1027 
1028  APERTURE::APERTURE_TYPE apert_type =
1030  selectAperture( aDiameter, aOrient, apert_type, aperture_attrib );
1031 
1032  if( gbr_metadata )
1033  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
1034 
1035  emitDcode( pos_dev, 3 );
1036  }
1037 }
1038 
1039 
1040 void GERBER_PLOTTER::Text( const wxPoint& aPos, const COLOR4D aColor,
1041  const wxString& aText, double aOrient, const wxSize& aSize,
1042  enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify,
1043  int aWidth, bool aItalic, bool aBold, bool aMultilineAllowed,
1044  void* aData )
1045 {
1046  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
1047 
1048  if( gbr_metadata )
1049  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
1050 
1051  PLOTTER::Text( aPos, aColor, aText, aOrient, aSize,
1052  aH_justify, aV_justify, aWidth, aItalic, aBold, aMultilineAllowed, aData );
1053 }
1054 
1055 
1056 void GERBER_PLOTTER::SetLayerPolarity( bool aPositive )
1057 {
1058  if( aPositive )
1059  fprintf( outputFile, "%%LPD*%%\n" );
1060  else
1061  fprintf( outputFile, "%%LPC*%%\n" );
1062 }
virtual void SetDefaultLineWidth(int width) override
Set the default line width.
void FinishTo(const wxPoint &pos)
Definition: plotter.h:283
virtual void FlashPadRoundRect(const wxPoint &aPadPos, const wxSize &aSize, int aCornerRadius, double aOrient, EDA_DRAW_MODE_T aTraceMode, void *aData) override
Roundrect pad at the moment are not handled as aperture, since they require aperture macros TODO: alw...
a class to handle special data (items attributes) during plot.
void writeApertureList()
Generate the table of D codes.
void clearNetAttribute()
clear a Gerber net attribute record (clear object attribute dictionary) and output the clear object a...
EDA_TEXT_HJUSTIFY_T
Definition: eda_text.h:44
virtual void ThickSegment(const wxPoint &start, const wxPoint &end, int width, EDA_DRAW_MODE_T tracemode, void *aData) override
virtual void PenTo(const wxPoint &pos, char plume) override
moveto/lineto primitive, moves the 'pen' to the specified direction
void PenFinish()
Definition: plotter.h:289
virtual void FlashPadTrapez(const wxPoint &aPadPos, const wxPoint *aCorners, double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void *aData) override
Trapezoidal pad at the moment are never handled as aperture, since they require aperture macros TODO:...
int OutlineCount() const
Returns the number of outlines in the set
int GetOrCreateAperture(const wxSize &aSize, APERTURE::APERTURE_TYPE aType, int aApertureAttribute)
virtual void SetLayerPolarity(bool aPositive) override
Change the plot polarity and begin a new layer Used to 'scratch off' silk screen away from solder mas...
APERTURE_TYPE
Definition: plotter.h:1073
virtual void EndBlock(void *aData) override
calling this function allows one to define the end of a group of drawing items the group is started b...
APERTURE_TYPE m_Type
Definition: plotter.h:1139
wxSize m_Size
Definition: plotter.h:1144
bool m_useNetAttributes
Definition: plotter.h:1400
void formatNetAttribute(GBR_NETLIST_METADATA *aData)
print a Gerber net attribute object record.
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 FlashRegularPolygon(const wxPoint &aShapePos, int aDiameter, int aCornerCount, double aOrient, EDA_DRAW_MODE_T aTraceMode, void *aData) override
Flash a regular polygon.
bool FormatNetAttribute(std::string &aPrintedText, std::string &aLastNetAttributes, GBR_NETLIST_METADATA *aData, bool &aClearPreviousAttributes, bool aUseX1StructuredComment)
Generates the string to print to a gerber file, to set a net attribute for a graphic object.
void selectAperture(const wxSize &aSize, APERTURE::APERTURE_TYPE aType, int aApertureAttribute)
Pick an existing aperture or create a new one, matching the size, type and attributes.
char penState
Current pen state: 'U', 'D' or 'Z' (see PenTo)
Definition: plotter.h:605
this class handle info which can be added in a gerber file as attribute of an object the GBR_INFO_TYP...
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
double m_IUsPerDecimil
Definition: plotter.h:582
void Inflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Performs outline inflation/deflation.
bool m_gerberUnitInch
Definition: plotter.h:1394
int PointCount() const
Function PointCount()
wxArrayString m_headerExtraLines
Definition: plotter.h:615
virtual void FlashPadOval(const wxPoint &pos, const wxSize &size, double orient, EDA_DRAW_MODE_T trace_mode, void *aData) override
Filled oval flashes are handled as aperture in the 90 degree positions only.
wxPoint plotOffset
Plot offset (in IUs)
Definition: plotter.h:588
virtual bool StartPlot() override
Function StartPlot Write GERBER header to file initialize global variable g_Plot_PlotOutputFile.
This file contains miscellaneous commonly used macros and functions.
virtual void ThickRect(const wxPoint &p1, const wxPoint &p2, int width, EDA_DRAW_MODE_T tracemode, void *aData) override
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:232
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.
virtual int GetCurrentLineWidth() const
Definition: plotter.h:171
#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
const VECTOR2I & CPoint(int aIndex) const
Function Point()
wxString m_ExtraData
a string to print after TO object attributes, if not empty it is printed "as this"
void LineTo(const wxPoint &pos)
Definition: plotter.h:278
virtual void Rect(const wxPoint &p1, const wxPoint &p2, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH) override
static const int USE_DEFAULT_LINE_WIDTH
Definition: plotter.h:109
virtual void PlotPoly(const std::vector< wxPoint > &aCornerList, FILL_T aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=nullptr) override
Gerber polygon: they can (and should) be filled with the appropriate G36/G37 sequence.
std::vector< APERTURE > m_apertures
Definition: plotter.h:1391
bool m_plotMirror
X axis orientation (SVG) and plot mirrored (only for PS, PDF HPGL and SVG)
Definition: plotter.h:592
void ClearAllAttributes()
Remove (clear) all attributes from object attributes dictionary (TO.
#define NULL
virtual void SetCurrentLineWidth(int width, void *aData=NULL) override
Set the line width for the next drawing.
wxString GetBuildVersion()
Get the full KiCad version string.
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
int m_gerberUnitFmt
Definition: plotter.h:1395
Base window classes and related definitions.
double plotScale
Plot scale - chosen by the user (even implicitly with 'fit in a4')
Definition: plotter.h:576
virtual void SetViewport(const wxPoint &aOffset, double aIusPerDecimil, double aScale, bool aMirror) override
Set the plot offset and scaling for the current plot.
GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB GetApertureAttrib()
Definition: gbr_metadata.h:165
void emitDcode(const DPOINT &pt, int dcode)
Emit a D-Code record, using proper conversions to format a leading zero omitted gerber coordinate (fo...
virtual void ThickArc(const wxPoint &centre, double StAngle, double EndAngle, int rayon, int width, EDA_DRAW_MODE_T tracemode, void *aData) override
FILE * finalFile
Definition: plotter.h:1383
virtual void FlashPadCircle(const wxPoint &pos, int diametre, EDA_DRAW_MODE_T trace_mode, void *aData) override
Filled circular flashes are stored as apertures.
EDA_TEXT_VJUSTIFY_T
Definition: eda_text.h:51
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aApproxErrorMax, int aMinSegPerCircleCount=16)
convert a rectangle with rounded corners and/or chamfered corners to a polygon Convert rounded corner...
void MoveTo(const wxPoint &pos)
Definition: plotter.h:273
bool m_useX2format
Definition: plotter.h:1397
virtual DPOINT userToDeviceCoordinates(const wxPoint &aCoordinate)
Modifies coordinates according to the orientation, scale factor, and offsets trace.
Definition: plotter.cpp:99
static std::string FormatAttribute(GBR_APERTURE_ATTRIB aAttribute, bool aUseX1StructuredComment)
double cosdecideg(double r, double a)
Circle generation utility: computes r * cos(a) Where a is in decidegrees, not in radians.
Definition: trigo.h:408
double sindecideg(double r, double a)
Circle generation utility: computes r * sin(a) Where a is in decidegrees, not in radians.
Definition: trigo.h:399
virtual void StartBlock(void *aData) override
calling this function allows one to define the beginning of a group of drawing items (used in X2 form...
virtual void Arc(const wxPoint &aCenter, double aStAngle, double aEndAngle, int aRadius, FILL_T aFill, int aWidth=USE_DEFAULT_LINE_WIDTH) override
Generic fallback: arc rendered as a polyline.
int currentPenWidth
Definition: plotter.h:603
void PlotGerberRegion(const std::vector< wxPoint > &aCornerList, void *aData=NULL)
Plot a Gerber region: similar to PlotPoly but plot only filled polygon, and add the TA....
int defaultPenWidth
true to generate a negative image (PS mode mainly)
Definition: plotter.h:602
virtual bool EndPlot() override
SHAPE_LINE_CHAIN.
FILE * outputFile
true if the Y axis is top to bottom (SVG)
Definition: plotter.h:597
std::string m_objectAttributesDictionnary
Definition: plotter.h:1377
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:61
The common library.
int GetPlotterArcHighDef() const
Definition: plotter.h:239
virtual void SetGerberCoordinatesFormat(int aResolution, bool aUseInches=false) override
Function SetGerberCoordinatesFormat selection of Gerber units and resolution (number of digits in man...
FILL_T
Enum FILL_T is the set of fill types used in plotting or drawing enclosed areas.
Definition: base_struct.h:42
virtual void FlashPadRect(const wxPoint &pos, const wxSize &size, double orient, EDA_DRAW_MODE_T trace_mode, void *aData) override
Filled rect flashes are handled as aperture in the 0 90 180 or 270 degree orientation only and as pol...
wxString m_workFilename
Definition: plotter.h:1384
GBR_NETLIST_METADATA m_NetlistMetadata
a item to handle object attribute:
Definition: gbr_metadata.h:212
int m_apertureAttribute
Definition: plotter.h:1380
virtual void Circle(const wxPoint &pos, int diametre, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH) override
int m_DCode
Definition: plotter.h:1147
int m_ApertureAttribute
Definition: plotter.h:1152
FILE * workFile
Definition: plotter.h:1382
double iuPerDeviceUnit
Device scale (from IUs to plotter device units - usually decimils)
Definition: plotter.h:585
static const int DO_NOT_SET_LINE_WIDTH
Definition: plotter.h:108
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.
Definition: plotter.cpp:437
wxString filename
Definition: plotter.h:609
virtual void ThickCircle(const wxPoint &pos, int diametre, int width, EDA_DRAW_MODE_T tracemode, void *aData) override
void sketchOval(const wxPoint &pos, const wxSize &size, double orient, int width)
Definition: plotter.cpp:458
wxString creator
Definition: plotter.h:608
wxSize paperSize
Paper size in IU - not in mils.
Definition: plotter.h:613
GBR_APERTURE_METADATA m_ApertureMetadata
a item to handle aperture attribute:
Definition: gbr_metadata.h:207
int m_currentApertureIdx
Definition: plotter.h:1392
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:40