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) 2020 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 }
87 
88 
89 void GERBER_PLOTTER::SetGerberCoordinatesFormat( int aResolution, bool aUseInches )
90 {
91  m_gerberUnitInch = aUseInches;
92  m_gerberUnitFmt = aResolution;
93 
94  iuPerDeviceUnit = pow( 10.0, m_gerberUnitFmt ) / ( m_IUsPerDecimil * 10000.0 );
95 
96  if( ! m_gerberUnitInch )
97  iuPerDeviceUnit *= 25.4; // gerber output in mm
98 }
99 
100 
101 void GERBER_PLOTTER::emitDcode( const DPOINT& pt, int dcode )
102 {
103 
104  fprintf( outputFile, "X%dY%dD%02d*\n", KiROUND( pt.x ), KiROUND( pt.y ), dcode );
105 }
106 
108 {
109  // Remove all attributes from object attributes dictionary (TO. and TA commands)
110  if( m_useX2format )
111  fputs( "%TD*%\n", outputFile );
112  else
113  fputs( "G04 #@! TD*\n", outputFile );
114 
116 }
117 
118 
120 {
121  // disable a Gerber net attribute (exists only in X2 with net attributes mode).
122  if( m_objectAttributesDictionnary.empty() ) // No net attribute or not X2 mode
123  return;
124 
125  // Remove all net attributes from object attributes dictionary
126  if( m_useX2format )
127  fputs( "%TD*%\n", outputFile );
128  else
129  fputs( "G04 #@! TD*\n", outputFile );
130 
132 }
133 
134 
135 void GERBER_PLOTTER::StartBlock( void* aData )
136 {
137  // Currently, it is the same as EndBlock(): clear all aperture net attributes
138  EndBlock( aData );
139 }
140 
141 
142 void GERBER_PLOTTER::EndBlock( void* aData )
143 {
144  // Remove all net attributes from object attributes dictionary
146 }
147 
148 
150 {
151  // print a Gerber net attribute record.
152  // it is added to the object attributes dictionary
153  // On file, only modified or new attributes are printed.
154  if( aData == NULL )
155  return;
156 
157  if( !m_useNetAttributes )
158  return;
159 
160  bool useX1StructuredComment = !m_useX2format;
161 
162  bool clearDict;
163  std::string short_attribute_string;
164 
165  if( !FormatNetAttribute( short_attribute_string, m_objectAttributesDictionnary,
166  aData, clearDict, useX1StructuredComment ) )
167  return;
168 
169  if( clearDict )
171 
172  if( !short_attribute_string.empty() )
173  fputs( short_attribute_string.c_str(), outputFile );
174 
175  if( m_useX2format && !aData->m_ExtraData.IsEmpty() )
176  {
177  std::string extra_data = TO_UTF8( aData->m_ExtraData );
178  fputs( extra_data.c_str(), outputFile );
179  }
180 }
181 
182 
184 {
185  wxASSERT( outputFile );
186 
187  finalFile = outputFile; // the actual gerber file will be created later
188 
189  // Create a temp file in system temp to avoid potential network share buffer issues for the final read and save
190  m_workFilename = wxFileName::CreateTempFileName( "" );
191  workFile = wxFopen( m_workFilename, wxT( "wt" ));
193  wxASSERT( outputFile );
194 
195  if( outputFile == NULL )
196  return false;
197 
198  for( unsigned ii = 0; ii < m_headerExtraLines.GetCount(); ii++ )
199  {
200  if( ! m_headerExtraLines[ii].IsEmpty() )
201  fprintf( outputFile, "%s\n", TO_UTF8( m_headerExtraLines[ii] ) );
202  }
203 
204  // Set coordinate format to 3.6 or 4.5 absolute, leading zero omitted
205  // the number of digits for the integer part of coordinates is needed
206  // in gerber format, but is not very important when omitting leading zeros
207  // It is fixed here to 3 (inch) or 4 (mm), but is not actually used
208  int leadingDigitCount = m_gerberUnitInch ? 3 : 4;
209 
210  fprintf( outputFile, "%%FSLAX%d%dY%d%d*%%\n",
211  leadingDigitCount, m_gerberUnitFmt,
212  leadingDigitCount, m_gerberUnitFmt );
213  fprintf( outputFile,
214  "G04 Gerber Fmt %d.%d, Leading zero omitted, Abs format (unit %s)*\n",
215  leadingDigitCount, m_gerberUnitFmt,
216  m_gerberUnitInch ? "inch" : "mm" );
217 
218  wxString Title = creator + wxT( " " ) + GetBuildVersion();
219  // In gerber files, ASCII7 chars only are allowed.
220  // So use a ISO date format (using a space as separator between date and time),
221  // not a localized date format
222  wxDateTime date = wxDateTime::Now();
223  fprintf( outputFile, "G04 Created by KiCad (%s) date %s*\n",
224  TO_UTF8( Title ), TO_UTF8( date.FormatISOCombined( ' ') ) );
225 
226  /* Mass parameter: unit = INCHES/MM */
227  if( m_gerberUnitInch )
228  fputs( "%MOIN*%\n", outputFile );
229  else
230  fputs( "%MOMM*%\n", outputFile );
231 
232  // Be sure the usual dark polarity is selected:
233  fputs( "%LPD*%\n", outputFile );
234 
235  // Set initial interpolation mode: always G01 (linear):
236  fputs( "G01*\n", outputFile );
237 
238  // Set aperture list starting point:
239  fputs( "G04 APERTURE LIST*\n", outputFile );
240 
241  return true;
242 }
243 
244 
246 {
247  char line[1024];
248  wxString msg;
249 
250  wxASSERT( outputFile );
251 
252  /* Outfile is actually a temporary file i.e. workFile */
253  fputs( "M02*\n", outputFile );
254  fflush( outputFile );
255 
256  fclose( workFile );
257  workFile = wxFopen( m_workFilename, wxT( "rt" ));
258  wxASSERT( workFile );
260 
261  // Placement of apertures in RS274X
262  while( fgets( line, 1024, workFile ) )
263  {
264  fputs( line, outputFile );
265 
266  char* substr = strtok( line, "\n\r" );
267 
268  if( substr && strcmp( substr, "G04 APERTURE LIST*" ) == 0 )
269  {
271  fputs( "G04 APERTURE END LIST*\n", outputFile );
272  }
273  }
274 
275  fclose( workFile );
276  fclose( finalFile );
277  ::wxRemoveFile( m_workFilename );
278  outputFile = 0;
279 
280  return true;
281 }
282 
283 
284 void GERBER_PLOTTER::SetCurrentLineWidth( int aWidth, void* aData )
285 {
286  if( aWidth == DO_NOT_SET_LINE_WIDTH )
287  return;
288  else if( aWidth == USE_DEFAULT_LINE_WIDTH )
290 
291  wxASSERT_MSG( aWidth >= 0, "Plotter called to set negative pen width" );
292 
293  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
294  int aperture_attribute = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
295 
296  selectAperture( wxSize( aWidth, aWidth ), APERTURE::AT_PLOTTING, aperture_attribute );
297  currentPenWidth = aWidth;
298 }
299 
300 
301 int GERBER_PLOTTER::GetOrCreateAperture( const wxSize& aSize,
302  APERTURE::APERTURE_TYPE aType, int aApertureAttribute )
303 {
304  int last_D_code = 9;
305 
306  // Search an existing aperture
307  for( int idx = 0; idx < (int)m_apertures.size(); ++idx )
308  {
309  APERTURE* tool = &m_apertures[idx];
310  last_D_code = tool->m_DCode;
311 
312  if( (tool->m_Type == aType) && (tool->m_Size == aSize) &&
313  (tool->m_ApertureAttribute == aApertureAttribute) )
314  return idx;
315  }
316 
317  // Allocate a new aperture
318  APERTURE new_tool;
319  new_tool.m_Size = aSize;
320  new_tool.m_Type = aType;
321  new_tool.m_DCode = last_D_code + 1;
322  new_tool.m_ApertureAttribute = aApertureAttribute;
323 
324  m_apertures.push_back( new_tool );
325 
326  return m_apertures.size() - 1;
327 }
328 
329 
330 void GERBER_PLOTTER::selectAperture( const wxSize& aSize,
332  int aApertureAttribute )
333 {
334  bool change = ( m_currentApertureIdx < 0 ) ||
335  ( m_apertures[m_currentApertureIdx].m_Type != aType ) ||
336  ( m_apertures[m_currentApertureIdx].m_Size != aSize );
337 
338  if( !change )
339  change = m_apertures[m_currentApertureIdx].m_ApertureAttribute != aApertureAttribute;
340 
341  if( change )
342  {
343  // Pick an existing aperture or create a new one
344  m_currentApertureIdx = GetOrCreateAperture( aSize, aType, aApertureAttribute );
345  fprintf( outputFile, "D%d*\n", m_apertures[m_currentApertureIdx].m_DCode );
346  }
347 }
348 
349 void GERBER_PLOTTER::selectAperture( int aDiameter, double aPolygonRotation,
350  APERTURE::APERTURE_TYPE aType, int aApertureAttribute )
351 {
352  // Pick an existing aperture or create a new one, matching the
353  // aDiameter, aPolygonRotation, type and attributes for type =
354  // AT_REGULAR_POLY3 to AT_REGULAR_POLY12
355 
356  wxASSERT( aType>= APERTURE::APERTURE_TYPE::AT_REGULAR_POLY3 &&
357  aType <= APERTURE::APERTURE_TYPE::AT_REGULAR_POLY12 );
358 
359  // To use selectAperture( size, ... ) calculate a equivalent aperture size:
360  // for AT_REGULAR_POLYxx the parameter APERTURE::m_Size contains
361  // aDiameter (in m_Size.x) and aPolygonRotation in 1/1000 degree (in m_Size.y)
362  wxSize size( aDiameter, (int)( aPolygonRotation * 1000.0 ) );
363  selectAperture( size, aType, aApertureAttribute );
364 }
365 
367 {
368  wxASSERT( outputFile );
369  char cbuf[1024];
370 
371  bool useX1StructuredComment = false;
372 
373  if( !m_useX2format )
374  useX1StructuredComment = true;
375 
376  // Init
377  for( APERTURE& tool : m_apertures )
378  {
379  // apertude sizes are in inch or mm, regardless the
380  // coordinates format
381  double fscale = 0.0001 * plotScale / m_IUsPerDecimil; // inches
382 
383  if(! m_gerberUnitInch )
384  fscale *= 25.4; // size in mm
385 
386  int attribute = tool.m_ApertureAttribute;
387 
388  if( attribute != m_apertureAttribute )
389  {
392  useX1StructuredComment ).c_str(), outputFile );
393  }
394 
395  char* text = cbuf + sprintf( cbuf, "%%ADD%d", tool.m_DCode );
396 
397  /* Please note: the Gerber specs for mass parameters say that
398  exponential syntax is *not* allowed and the decimal point should
399  also be always inserted. So the %g format is ruled out, but %f is fine
400  (the # modifier forces the decimal point). Sadly the %f formatter
401  can't remove trailing zeros but thats not a problem, since nothing
402  forbid it (the file is only slightly longer) */
403 
404  switch( tool.m_Type )
405  {
406  case APERTURE::AT_CIRCLE:
407  sprintf( text, "C,%#f*%%\n", tool.GetDiameter() * fscale );
408  break;
409 
410  case APERTURE::AT_RECT:
411  sprintf( text, "R,%#fX%#f*%%\n", tool.m_Size.x * fscale,
412  tool.m_Size.y * fscale );
413  break;
414 
416  sprintf( text, "C,%#f*%%\n", tool.m_Size.x * fscale );
417  break;
418 
419  case APERTURE::AT_OVAL:
420  sprintf( text, "O,%#fX%#f*%%\n", tool.m_Size.x * fscale,
421  tool.m_Size.y * fscale );
422  break;
423 
435  sprintf( text, "P,%#fX%dX%#f*%%\n", tool.GetDiameter() * fscale,
436  tool.GetVerticeCount(), tool.GetRotation() );
437  break;
438  }
439 
440  fputs( cbuf, outputFile );
441 
442  m_apertureAttribute = attribute;
443 
444  // Currently reset the aperture attribute. Perhaps a better optimization
445  // is to store the last attribute
446  if( attribute )
447  {
448  if( m_useX2format )
449  fputs( "%TD*%\n", outputFile );
450  else
451  fputs( "G04 #@! TD*\n", outputFile );
452 
454  }
455 
456  }
457 }
458 
459 
460 void GERBER_PLOTTER::PenTo( const wxPoint& aPos, char plume )
461 {
462  wxASSERT( outputFile );
463  DPOINT pos_dev = userToDeviceCoordinates( aPos );
464 
465  switch( plume )
466  {
467  case 'Z':
468  break;
469 
470  case 'U':
471  emitDcode( pos_dev, 2 );
472  break;
473 
474  case 'D':
475  emitDcode( pos_dev, 1 );
476  }
477 
478  penState = plume;
479 }
480 
481 
482 void GERBER_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width )
483 {
484  std::vector< wxPoint > cornerList;
485 
486  // Build corners list
487  cornerList.push_back( p1 );
488  wxPoint corner(p1.x, p2.y);
489  cornerList.push_back( corner );
490  cornerList.push_back( p2 );
491  corner.x = p2.x;
492  corner.y = p1.y;
493  cornerList.push_back( corner );
494  cornerList.push_back( p1 );
495 
496  PlotPoly( cornerList, fill, width );
497 }
498 
499 
500 void GERBER_PLOTTER::Circle( const wxPoint& aCenter, int aDiameter, FILL_T aFill, int aWidth )
501 {
502  Arc( aCenter, 0, 3600, aDiameter / 2, aFill, aWidth );
503 }
504 
505 
506 void GERBER_PLOTTER::Arc( const wxPoint& aCenter, double aStAngle, double aEndAngle,
507  int aRadius, FILL_T aFill, int aWidth )
508 {
509  SetCurrentLineWidth( aWidth );
510 
511  // aFill is not used here.
512  plotArc( aCenter, aStAngle, aEndAngle, aRadius, false );
513 }
514 
515 
516 void GERBER_PLOTTER::plotArc( const wxPoint& aCenter, double aStAngle, double aEndAngle,
517  int aRadius, bool aPlotInRegion )
518 {
519  wxPoint start, end;
520  start.x = aCenter.x + KiROUND( cosdecideg( aRadius, aStAngle ) );
521  start.y = aCenter.y - KiROUND( sindecideg( aRadius, aStAngle ) );
522 
523  if( !aPlotInRegion )
524  MoveTo( start );
525  else
526  LineTo( start );
527 
528  end.x = aCenter.x + KiROUND( cosdecideg( aRadius, aEndAngle ) );
529  end.y = aCenter.y - KiROUND( sindecideg( aRadius, aEndAngle ) );
530  DPOINT devEnd = userToDeviceCoordinates( end );
531  DPOINT devCenter = userToDeviceCoordinates( aCenter ) - userToDeviceCoordinates( start );
532 
533  fprintf( outputFile, "G75*\n" ); // Multiquadrant (360 degrees) mode
534 
535  if( aStAngle < aEndAngle )
536  fprintf( outputFile, "G03*\n" ); // Active circular interpolation, CCW
537  else
538  fprintf( outputFile, "G02*\n" ); // Active circular interpolation, CW
539 
540  fprintf( outputFile, "X%dY%dI%dJ%dD01*\n",
541  KiROUND( devEnd.x ), KiROUND( devEnd.y ),
542  KiROUND( devCenter.x ), KiROUND( devCenter.y ) );
543 
544  fprintf( outputFile, "G01*\n" ); // Back to linear interpol (perhaps useless here).
545 }
546 
547 
548 void GERBER_PLOTTER::PlotGerberRegion( const std::vector< wxPoint >& aCornerList,
549  void * aData )
550 {
551  if( aCornerList.size() <= 2 )
552  return;
553 
554  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
555 
556  bool clearTA_AperFunction = false; // true if a TA.AperFunction is used
557 
558  if( gbr_metadata )
559  {
560  std::string attrib = gbr_metadata->m_ApertureMetadata.FormatAttribute( !m_useX2format );
561 
562  if( !attrib.empty() )
563  {
564  fputs( attrib.c_str(), outputFile );
565  clearTA_AperFunction = true;
566  }
567  }
568 
569  PlotPoly( aCornerList, FILLED_SHAPE, 0 , gbr_metadata );
570 
571  // Clear the TA attribute, to avoid the next item to inherit it:
572  if( clearTA_AperFunction )
573  {
574  if( m_useX2format )
575  {
576  fputs( "%TD.AperFunction*%\n", outputFile );
577  }
578  else
579  {
580  fputs( "G04 #@! TD.AperFunction*\n", outputFile );
581  }
582  }
583 }
584 
585 void GERBER_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
586  FILL_T aFill, int aWidth, void * aData )
587 {
588  if( aCornerList.size() <= 1 )
589  return;
590 
591  // Gerber format does not know filled polygons with thick outline
592  // Therefore, to plot a filled polygon with outline having a thickness,
593  // one should plot outline as thick segments
594  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
595 
596  if( gbr_metadata )
597  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
598 
599  if( aFill )
600  {
601  fputs( "G36*\n", outputFile );
602 
603  MoveTo( aCornerList[0] );
604  fputs( "G01*\n", outputFile ); // Set linear interpolation.
605 
606  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
607  LineTo( aCornerList[ii] );
608 
609  // If the polygon is not closed, close it:
610  if( aCornerList[0] != aCornerList[aCornerList.size()-1] )
611  FinishTo( aCornerList[0] );
612 
613  fputs( "G37*\n", outputFile );
614  }
615 
616  if( aWidth > 0 ) // Draw the polyline/polygon outline
617  {
618  SetCurrentLineWidth( aWidth, gbr_metadata );
619 
620  MoveTo( aCornerList[0] );
621 
622  for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
623  LineTo( aCornerList[ii] );
624 
625  // Ensure the thick outline is closed for filled polygons
626  // (if not filled, could be only a polyline)
627  if( aFill && ( aCornerList[aCornerList.size()-1] != aCornerList[0] ) )
628  LineTo( aCornerList[0] );
629 
630  PenFinish();
631  }
632 }
633 
634 
635 void GERBER_PLOTTER::ThickSegment( const wxPoint& start, const wxPoint& end, int width,
636  EDA_DRAW_MODE_T tracemode, void* aData )
637 {
638  if( tracemode == FILLED )
639  {
640  GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
641  SetCurrentLineWidth( width, gbr_metadata );
642 
643  if( gbr_metadata )
644  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
645 
646  MoveTo( start );
647  FinishTo( end );
648  }
649  else
650  {
652  segmentAsOval( start, end, width, tracemode );
653  }
654 }
655 
656 void GERBER_PLOTTER::ThickArc( const wxPoint& centre, double StAngle, double EndAngle,
657  int radius, int width, EDA_DRAW_MODE_T tracemode, void* aData )
658 {
659  GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
660  SetCurrentLineWidth( width, gbr_metadata );
661 
662  if( gbr_metadata )
663  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
664 
665  if( tracemode == FILLED )
666  Arc( centre, StAngle, EndAngle, radius, NO_FILL, DO_NOT_SET_LINE_WIDTH );
667  else
668  {
670  Arc( centre, StAngle, EndAngle,
671  radius - ( width - currentPenWidth ) / 2,
673  Arc( centre, StAngle, EndAngle,
674  radius + ( width - currentPenWidth ) / 2, NO_FILL,
676  }
677 }
678 
679 
680 void GERBER_PLOTTER::ThickRect( const wxPoint& p1, const wxPoint& p2, int width,
681  EDA_DRAW_MODE_T tracemode, void* aData )
682 {
683  GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
684  SetCurrentLineWidth( width, gbr_metadata );
685 
686  if( gbr_metadata )
687  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
688 
689  if( tracemode == FILLED )
690  Rect( p1, p2, NO_FILL, DO_NOT_SET_LINE_WIDTH );
691  else
692  {
694  wxPoint offsetp1( p1.x - (width - currentPenWidth) / 2,
695  p1.y - (width - currentPenWidth) / 2 );
696  wxPoint offsetp2( p2.x + (width - currentPenWidth) / 2,
697  p2.y + (width - currentPenWidth) / 2 );
698  Rect( offsetp1, offsetp2, NO_FILL, -1 );
699  offsetp1.x += (width - currentPenWidth);
700  offsetp1.y += (width - currentPenWidth);
701  offsetp2.x -= (width - currentPenWidth);
702  offsetp2.y -= (width - currentPenWidth);
703  Rect( offsetp1, offsetp2, NO_FILL, DO_NOT_SET_LINE_WIDTH );
704  }
705 }
706 
707 
708 void GERBER_PLOTTER::ThickCircle( const wxPoint& pos, int diametre, int width,
709  EDA_DRAW_MODE_T tracemode, void* aData )
710 {
711  GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
712  SetCurrentLineWidth( width, gbr_metadata );
713 
714  if( gbr_metadata )
715  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
716 
717  if( tracemode == FILLED )
718  Circle( pos, diametre, NO_FILL, DO_NOT_SET_LINE_WIDTH );
719  else
720  {
722  Circle( pos, diametre - (width - currentPenWidth),
724  Circle( pos, diametre + (width - currentPenWidth),
726  }
727 }
728 
729 
730 void GERBER_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, EDA_DRAW_MODE_T trace_mode, void* aData )
731 {
732  wxSize size( diametre, diametre );
733  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
734 
735  if( trace_mode == SKETCH )
736  {
737  if( gbr_metadata )
738  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
739 
741  }
742  else
743  {
744  DPOINT pos_dev = userToDeviceCoordinates( pos );
745 
746  int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
747  selectAperture( size, APERTURE::AT_CIRCLE, aperture_attrib );
748 
749  if( gbr_metadata )
750  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
751 
752  emitDcode( pos_dev, 3 );
753  }
754 }
755 
756 
757 void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient,
758  EDA_DRAW_MODE_T trace_mode, void* aData )
759 {
760  wxASSERT( outputFile );
761  wxSize size( aSize );
762  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
763 
764  // Flash a vertical or horizontal shape (this is a basic aperture).
765  if( ( orient == 0 || orient == 900 || orient == 1800 || orient == 2700 )
766  && trace_mode == FILLED )
767  {
768  if( orient == 900 || orient == 2700 ) /* orientation turned 90 deg. */
769  std::swap( size.x, size.y );
770 
771  DPOINT pos_dev = userToDeviceCoordinates( pos );
772  int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
773  selectAperture( size, APERTURE::AT_OVAL, aperture_attrib );
774 
775  if( gbr_metadata )
776  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
777 
778  emitDcode( pos_dev, 3 );
779  }
780  else // Plot pad as region.
781  // Only regions and flashed items accept a object attribute TO.P for the pin name
782  {
783  if( trace_mode == FILLED )
784  {
785  // Draw the oval as round rect pad with a radius = 50% min size)
786  // In gerber file, it will be drawn as a region with arcs, and can be
787  // detected as pads (similar to a flashed pad)
788  FlashPadRoundRect( pos, aSize, std::min( aSize.x, aSize.y ) /2,
789  orient, FILLED, aData );
790  }
791  else // Non filled shape: plot outlines:
792  {
793  if( size.x > size.y )
794  {
795  std::swap( size.x, size.y );
796 
797  if( orient < 2700 )
798  orient += 900;
799  else
800  orient -= 2700;
801  }
802 
803  sketchOval( pos, size, orient, -1 );
804  }
805  }
806 }
807 
808 
809 void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize,
810  double orient, EDA_DRAW_MODE_T trace_mode, void* aData )
811 
812 {
813  wxASSERT( outputFile );
814  wxSize size( aSize );
815  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
816 
817  // Plot as an aperture flash
818  switch( int( orient ) )
819  {
820  case 900:
821  case 2700: // rotation of 90 degrees or 270 swaps sizes
822  std::swap( size.x, size.y );
824 
825  case 0:
826  case 1800:
827  if( trace_mode == SKETCH )
828  {
829  if( gbr_metadata )
830  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
831 
832  Rect( wxPoint( pos.x - (size.x - currentPenWidth) / 2,
833  pos.y - (size.y - currentPenWidth) / 2 ),
834  wxPoint( pos.x + (size.x - currentPenWidth) / 2,
835  pos.y + (size.y - currentPenWidth) / 2 ),
837  }
838  else
839  {
840  DPOINT pos_dev = userToDeviceCoordinates( pos );
841  int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
842  selectAperture( size, APERTURE::AT_RECT, aperture_attrib );
843 
844  if( gbr_metadata )
845  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
846 
847  emitDcode( pos_dev, 3 );
848  }
849  break;
850 
851  default: // plot pad shape as Gerber region
852  {
853  wxPoint coord[4];
854  // coord[0] is assumed the lower left
855  // coord[1] is assumed the upper left
856  // coord[2] is assumed the upper right
857  // coord[3] is assumed the lower right
858 
859  coord[0].x = -size.x/2; // lower left
860  coord[0].y = size.y/2;
861  coord[1].x = -size.x/2; // upper left
862  coord[1].y = -size.y/2;
863  coord[2].x = size.x/2; // upper right
864  coord[2].y = -size.y/2;
865  coord[3].x = size.x/2; // lower right
866  coord[3].y = size.y/2;
867 
868  FlashPadTrapez( pos, coord, orient, trace_mode, aData );
869  }
870  break;
871  }
872 }
873 
874 void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
875  int aCornerRadius, double aOrient,
876  EDA_DRAW_MODE_T aTraceMode, void* aData )
877 
878 {
879  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
880 
881  if( aTraceMode != FILLED )
882  {
883  SHAPE_POLY_SET outline;
884  TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient,
885  aCornerRadius, 0.0, 0, GetPlotterArcHighDef() );
886 
888  outline.Inflate( -GetCurrentLineWidth()/2, 16 );
889 
890  std::vector< wxPoint > cornerList;
891  // TransformRoundRectToPolygon creates only one convex polygon
892  SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
893  cornerList.reserve( poly.PointCount() + 1 );
894 
895  for( int ii = 0; ii < poly.PointCount(); ++ii )
896  cornerList.emplace_back( poly.CPoint( ii ).x, poly.CPoint( ii ).y );
897 
898  // Close polygon
899  cornerList.push_back( cornerList[0] );
900 
901  // plot outlines
902  PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), gbr_metadata );
903  }
904  else
905  {
906  // A Pad RoundRect is plotted as a Gerber region.
907  // Initialize region metadata:
908  bool clearTA_AperFunction = false; // true if a TA.AperFunction is used
909 
910  if( gbr_metadata )
911  {
912  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
913  std::string attrib = gbr_metadata->m_ApertureMetadata.FormatAttribute( !m_useX2format );
914 
915  if( !attrib.empty() )
916  {
917  fputs( attrib.c_str(), outputFile );
918  clearTA_AperFunction = true;
919  }
920  }
921 
922  // Plot the region using arcs in corners.
923  plotRoundRectAsRegion( aPadPos, aSize, aCornerRadius, aOrient );
924 
925  // Clear the TA attribute, to avoid the next item to inherit it:
926  if( clearTA_AperFunction )
927  {
928  if( m_useX2format )
929  {
930  fputs( "%TD.AperFunction*%\n", outputFile );
931  }
932  else
933  {
934  fputs( "G04 #@! TD.AperFunction*\n", outputFile );
935  }
936  }
937  }
938 }
939 
940 
941 void GERBER_PLOTTER::plotRoundRectAsRegion( const wxPoint& aRectCenter, const wxSize& aSize,
942  int aCornerRadius, double aOrient )
943 {
944  // The region outline is generated by 4 sides and 4 90 deg arcs
945  // 1 --- 2
946  // | c |
947  // 4 --- 3
948 
949  // Note also in user coordinates the Y axis is from top to bottom
950  // for historical reasons.
951 
952  // A helper structure to handle outlines coordinates (segments and arcs)
953  // in user coordinates
954  struct RR_EDGE
955  {
956  wxPoint m_start;
957  wxPoint m_end;
958  wxPoint m_center;
959  // in decidegrees: angle start. angle end = m_arc_angle_start+arc_angle
960  double m_arc_angle_start;
961  };
962 
963  const double arc_angle = -900.0; // in decidegrees
964  int hsizeX = aSize.x/2;
965  int hsizeY = aSize.y/2;
966 
967  RR_EDGE curr_edge;
968  std::vector<RR_EDGE> rr_outline;
969 
970  // Build outline coordinates, relative to rectangle center, rotation 0:
971 
972  // Top left corner 1 (and 4 to 1 left vertical side @ x=-hsizeX)
973  curr_edge.m_start.x = -hsizeX;
974  curr_edge.m_start.y = hsizeY - aCornerRadius;
975  curr_edge.m_end.x = curr_edge.m_start.x;
976  curr_edge.m_end.y = -hsizeY + aCornerRadius;
977  curr_edge.m_center.x = -hsizeX + aCornerRadius;
978  curr_edge.m_center.y = curr_edge.m_end.y;
979  curr_edge.m_arc_angle_start = aOrient + 1800.0; // En decidegree
980 
981  rr_outline.push_back( curr_edge );
982 
983  // Top right corner 2 (and 1 to 2 top horizontal side @ y=-hsizeY)
984  curr_edge.m_start.x = -hsizeX + aCornerRadius;
985  curr_edge.m_start.y = -hsizeY;
986  curr_edge.m_end.x = hsizeX - aCornerRadius;
987  curr_edge.m_end.y = curr_edge.m_start.y;
988  curr_edge.m_center.x = curr_edge.m_end.x;
989  curr_edge.m_center.y = -hsizeY + aCornerRadius;
990  curr_edge.m_arc_angle_start = aOrient + 900.0; // En decidegree
991 
992  rr_outline.push_back( curr_edge );
993 
994  // bottom right corner 3 (and 2 to 3 right vertical side @ x=hsizeX)
995  curr_edge.m_start.x = hsizeX;
996  curr_edge.m_start.y = -hsizeY + aCornerRadius;
997  curr_edge.m_end.x = curr_edge.m_start.x;
998  curr_edge.m_end.y = hsizeY - aCornerRadius;
999  curr_edge.m_center.x = hsizeX - aCornerRadius;
1000  curr_edge.m_center.y = curr_edge.m_end.y;
1001  curr_edge.m_arc_angle_start = aOrient + 0.0; // En decidegree
1002 
1003  rr_outline.push_back( curr_edge );
1004 
1005  // bottom left corner 4 (and 3 to 4 bottom horizontal side @ y=hsizeY)
1006  curr_edge.m_start.x = hsizeX - aCornerRadius;
1007  curr_edge.m_start.y = hsizeY;
1008  curr_edge.m_end.x = -hsizeX + aCornerRadius;
1009  curr_edge.m_end.y = curr_edge.m_start.y;
1010  curr_edge.m_center.x = curr_edge.m_end.x;
1011  curr_edge.m_center.y = hsizeY - aCornerRadius;
1012  curr_edge.m_arc_angle_start = aOrient - 900.0; // En decidegree
1013 
1014  rr_outline.push_back( curr_edge );
1015 
1016  // Move relative coordinates to the actual location and rotation:
1017  wxPoint arc_last_center;
1018  int arc_last_angle = curr_edge.m_arc_angle_start+arc_angle;
1019 
1020  for( RR_EDGE& rr_edge: rr_outline )
1021  {
1022  RotatePoint( &rr_edge.m_start, aOrient );
1023  RotatePoint( &rr_edge.m_end, aOrient );
1024  RotatePoint( &rr_edge.m_center, aOrient );
1025  rr_edge.m_start += aRectCenter;
1026  rr_edge.m_end += aRectCenter;
1027  rr_edge.m_center += aRectCenter;
1028  arc_last_center = rr_edge.m_center;
1029  }
1030 
1031  // Ensure the region is a closed polygon, i.e. the end point of last segment
1032  // (end of arc) is the same as the first point. Rounding issues can create a
1033  // small difference, mainly for rotated pads.
1034  // calculate last point (end of last arc):
1035  wxPoint last_pt;
1036  last_pt.x = arc_last_center.x + KiROUND( cosdecideg( aCornerRadius, arc_last_angle ) );
1037  last_pt.y = arc_last_center.y - KiROUND( sindecideg( aCornerRadius, arc_last_angle ) );
1038 
1039  wxPoint first_pt = rr_outline[0].m_start;
1040 
1041 #if 0 // For test only:
1042  if( last_pt != first_pt )
1043  wxLogMessage( "first pt %d %d last pt %d %d",
1044  first_pt.x, first_pt.y, last_pt.x, last_pt.y );
1045 #endif
1046 
1047  fputs( "G36*\n", outputFile ); // Start region
1048  fputs( "G01*\n", outputFile ); // Set linear interpolation.
1049  first_pt = last_pt;
1050  MoveTo( first_pt ); // Start point of region, must be same as end point
1051 
1052  for( RR_EDGE& rr_edge: rr_outline )
1053  {
1054  if( aCornerRadius ) // Guard: ensure we do not create arcs with radius = 0
1055  {
1056  // LineTo( rr_edge.m_end ); // made in plotArc()
1057  plotArc( rr_edge.m_center,
1058  rr_edge.m_arc_angle_start, rr_edge.m_arc_angle_start+arc_angle,
1059  aCornerRadius, true );
1060  }
1061  else
1062  LineTo( rr_edge.m_end );
1063  }
1064 
1065  fputs( "G37*\n", outputFile ); // Close region
1066 }
1067 
1068 
1069 void GERBER_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize,
1070  SHAPE_POLY_SET* aPolygons,
1071  EDA_DRAW_MODE_T aTraceMode, void* aData )
1072 
1073 {
1074  // A Pad custom is plotted as polygon (a region in Gerber language).
1075 
1076  GBR_METADATA gbr_metadata;
1077 
1078  if( aData )
1079  gbr_metadata = *static_cast<GBR_METADATA*>( aData );
1080 
1081  SHAPE_POLY_SET polyshape = *aPolygons;
1082 
1083  if( aTraceMode != FILLED )
1084  {
1085  SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &gbr_metadata );
1086  polyshape.Inflate( -GetCurrentLineWidth()/2, 16 );
1087  }
1088 
1089  std::vector< wxPoint > cornerList;
1090 
1091  for( int cnt = 0; cnt < polyshape.OutlineCount(); ++cnt )
1092  {
1093  SHAPE_LINE_CHAIN& poly = polyshape.Outline( cnt );
1094 
1095  cornerList.clear();
1096 
1097  for( int ii = 0; ii < poly.PointCount(); ++ii )
1098  cornerList.emplace_back( poly.CPoint( ii ).x, poly.CPoint( ii ).y );
1099 
1100  // Close polygon
1101  cornerList.push_back( cornerList[0] );
1102 
1103  if( aTraceMode == SKETCH )
1104  PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), &gbr_metadata );
1105  else
1106  PlotGerberRegion( cornerList, &gbr_metadata );
1107  }
1108 }
1109 
1110 
1111 void GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCorners,
1112  double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData )
1113 
1114 {
1115  // TODO: use Aperture macro and flash it
1116 
1117  // polygon corners list
1118  std::vector<wxPoint> cornerList = { aCorners[0], aCorners[1], aCorners[2], aCorners[3] };
1119 
1120  // Draw the polygon and fill the interior as required
1121  for( unsigned ii = 0; ii < 4; ii++ )
1122  {
1123  RotatePoint( &cornerList[ii], aPadOrient );
1124  cornerList[ii] += aPadPos;
1125  }
1126 
1127  // Close the polygon
1128  cornerList.push_back( cornerList[0] );
1129  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
1130 
1131  GBR_METADATA metadata;
1132 
1133  if( gbr_metadata )
1134  metadata = *gbr_metadata;
1135 
1136  if( aTrace_Mode == SKETCH )
1137  PlotPoly( cornerList, NO_FILL, DO_NOT_SET_LINE_WIDTH, &metadata );
1138  else
1139  PlotGerberRegion( cornerList, &metadata );
1140 }
1141 
1142 
1144  int aDiameter, int aCornerCount,
1145  double aOrient, EDA_DRAW_MODE_T aTraceMode,
1146  void* aData )
1147 {
1148  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
1149 
1150  if( aTraceMode == SKETCH )
1151  {
1152  // Build the polygon:
1153  std::vector< wxPoint > cornerList;
1154 
1155  double angle_delta = 3600.0 / aCornerCount; // in 0.1 degree
1156 
1157  for( int ii = 0; ii < aCornerCount; ii++ )
1158  {
1159  double rot = aOrient + (angle_delta*ii);
1160  wxPoint vertice( aDiameter/2, 0 );
1161  RotatePoint( &vertice, rot );
1162  vertice += aShapePos;
1163  cornerList.push_back( vertice );
1164  }
1165 
1166  cornerList.push_back( cornerList[0] ); // Close the shape
1167 
1168  PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), gbr_metadata );
1169  }
1170  else
1171  {
1172  DPOINT pos_dev = userToDeviceCoordinates( aShapePos );
1173 
1174  int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
1175 
1176  APERTURE::APERTURE_TYPE apert_type =
1178  selectAperture( aDiameter, aOrient, apert_type, aperture_attrib );
1179 
1180  if( gbr_metadata )
1181  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
1182 
1183  emitDcode( pos_dev, 3 );
1184  }
1185 }
1186 
1187 
1188 void GERBER_PLOTTER::Text( const wxPoint& aPos, const COLOR4D aColor,
1189  const wxString& aText, double aOrient, const wxSize& aSize,
1190  enum EDA_TEXT_HJUSTIFY_T aH_justify,
1191  enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic,
1192  bool aBold, bool aMultilineAllowed, void* aData )
1193 {
1194  GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
1195 
1196  if( gbr_metadata )
1197  formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
1198 
1199  PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, aWidth, aItalic,
1200  aBold, aMultilineAllowed, aData );
1201 }
1202 
1203 
1204 void GERBER_PLOTTER::SetLayerPolarity( bool aPositive )
1205 {
1206  if( aPositive )
1207  fprintf( outputFile, "%%LPD*%%\n" );
1208  else
1209  fprintf( outputFile, "%%LPC*%%\n" );
1210 }
void FinishTo(const wxPoint &pos)
Definition: plotter.h:267
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:48
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:273
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
void plotRoundRectAsRegion(const wxPoint &aRectCenter, const wxSize &aSize, int aCornerRadius, double aOrient)
Plot a round rect (a round rect shape in fact) as a Gerber region using lines and arcs for corners.
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:1086
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:1152
wxSize m_Size
Definition: plotter.h:1157
bool m_useNetAttributes
Definition: plotter.h:1435
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.
void plotArc(const wxPoint &aCenter, double aStAngle, double aEndAngle, int aRadius, bool aPlotInRegion)
Plot a Gerber arc.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:88
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
Definition: plotter.h:592
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:571
void Inflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Performs outline inflation/deflation.
bool m_gerberUnitInch
Definition: plotter.h:1430
int PointCount() const
Function PointCount()
wxArrayString m_headerExtraLines
Definition: plotter.h:601
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:577
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:222
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:158
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:100
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:262
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:119
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:1427
bool m_plotMirror
X axis orientation (SVG) and plot mirrored (only for PS, PDF HPGL and SVG)
Definition: plotter.h:581
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:63
int m_gerberUnitFmt
Definition: plotter.h:1431
Base window classes and related definitions.
double plotScale
Plot scale - chosen by the user (even implicitly with 'fit in a4')
Definition: plotter.h:565
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
RENDER_SETTINGS * m_renderSettings
Definition: plotter.h:603
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:1419
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:55
void MoveTo(const wxPoint &pos)
Definition: plotter.h:257
bool m_useX2format
Definition: plotter.h:1433
virtual DPOINT userToDeviceCoordinates(const wxPoint &aCoordinate)
Modifies coordinates according to the orientation, scale factor, and offsets trace.
Definition: plotter.cpp:94
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:427
double sindecideg(double r, double a)
Circle generation utility: computes r * sin(a) Where a is in decidegrees, not in radians.
Definition: trigo.h:418
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:591
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....
virtual bool EndPlot() override
SHAPE_LINE_CHAIN.
FILE * outputFile
true if the Y axis is top to bottom (SVG)
Definition: plotter.h:586
std::string m_objectAttributesDictionnary
Definition: plotter.h:1413
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:68
The common library.
int GetPlotterArcHighDef() const
Definition: plotter.h:223
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...
int GetDefaultPenWidth() const
wxString m_workFilename
Definition: plotter.h:1420
GBR_NETLIST_METADATA m_NetlistMetadata
a item to handle object attribute:
Definition: gbr_metadata.h:212
int m_apertureAttribute
Definition: plotter.h:1416
virtual void Circle(const wxPoint &pos, int diametre, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH) override
int m_DCode
Definition: plotter.h:1160
int m_ApertureAttribute
Definition: plotter.h:1165
FILE * workFile
Definition: plotter.h:1418
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aError)
convert a rectangle with rounded corners and/or chamfered corners to a polygon Convert rounded corner...
double iuPerDeviceUnit
Device scale (from IUs to plotter device units - usually decimils)
Definition: plotter.h:574
static const int DO_NOT_SET_LINE_WIDTH
Definition: plotter.h:118
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:438
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:459
wxString creator
Definition: plotter.h:595
wxSize paperSize
Definition: plotter.h:599
GBR_APERTURE_METADATA m_ApertureMetadata
a item to handle aperture attribute:
Definition: gbr_metadata.h:207
int m_currentApertureIdx
Definition: plotter.h:1428
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:99