KiCad PCB EDA Suite
plot_board_layers.cpp
Go to the documentation of this file.
1 
8 /*
9  * This program source code file is part of KiCad, a free EDA CAD application.
10  *
11  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, you may find one here:
25  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
26  * or you may search the http://www.gnu.org website for the version 2 license,
27  * or you may write to the Free Software Foundation, Inc.,
28  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
29  */
30 
31 
32 #include <eda_item.h>
34 #include <geometry/shape_segment.h>
35 #include <pcb_base_frame.h>
36 #include <math/util.h> // for KiROUND
37 
38 #include <board.h>
39 #include <board_design_settings.h>
40 #include <core/arraydim.h>
41 #include <footprint.h>
42 #include <pcb_track.h>
43 #include <fp_shape.h>
44 #include <pad.h>
45 #include <pcb_text.h>
46 #include <zone.h>
47 #include <pcb_shape.h>
48 #include <pcb_target.h>
49 #include <pcb_dimension.h>
50 
51 #include <pcbplot.h>
52 #include <plotters_specific.h>
53 #include <pcb_painter.h>
54 #include <gbr_metadata.h>
55 #include <advanced_config.h>
56 
57 /*
58  * Plot a solder mask layer. Solder mask layers have a minimum thickness value and cannot be
59  * drawn like standard layers, unless the minimum thickness is 0.
60  */
61 static void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
62  const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness );
63 
64 
65 void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
66  const PCB_PLOT_PARAMS& aPlotOpt )
67 {
68  PCB_PLOT_PARAMS plotOpt = aPlotOpt;
69  int soldermask_min_thickness = aBoard->GetDesignSettings().m_SolderMaskMinWidth;
70 
71  // Set a default color and the text mode for this layer
72  aPlotter->SetColor( BLACK );
73  aPlotter->SetTextMode( aPlotOpt.GetTextMode() );
74 
75  // Specify that the contents of the "Edges Pcb" layer are to be plotted in addition to the
76  // contents of the currently specified layer.
77  LSET layer_mask( aLayer );
78 
79  if( !aPlotOpt.GetExcludeEdgeLayer() )
80  layer_mask.set( Edge_Cuts );
81 
82  if( IsCopperLayer( aLayer ) )
83  {
84  // Skip NPTH pads on copper layers ( only if hole size == pad size ):
85  // Drill mark will be plotted if drill mark is SMALL_DRILL_SHAPE or FULL_DRILL_SHAPE
86  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
87  {
88  plotOpt.SetSkipPlotNPTH_Pads( false );
89  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
90  }
91  else
92  {
93  plotOpt.SetSkipPlotNPTH_Pads( true );
94  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
95  }
96  }
97  else
98  {
99  switch( aLayer )
100  {
101  case B_Mask:
102  case F_Mask:
103  plotOpt.SetSkipPlotNPTH_Pads( false );
104  // Disable plot pad holes
106 
107  // Plot solder mask:
108  if( soldermask_min_thickness == 0 )
109  {
110  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
111  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
112  else
113  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
114  }
115  else
116  {
117  PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt,
118  soldermask_min_thickness );
119  }
120 
121  break;
122 
123  case B_Adhes:
124  case F_Adhes:
125  case B_Paste:
126  case F_Paste:
127  plotOpt.SetSkipPlotNPTH_Pads( false );
128  // Disable plot pad holes
130 
131  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
132  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
133  else
134  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
135 
136  break;
137 
138  case F_SilkS:
139  case B_SilkS:
140  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF && plotOpt.GetDXFPlotPolygonMode() )
141  // PlotLayerOutlines() is designed only for DXF plotters.
142  // and must not be used for other plot formats
143  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
144  else
145  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
146 
147  // Gerber: Subtract soldermask from silkscreen if enabled
148  if( aPlotter->GetPlotterType() == PLOT_FORMAT::GERBER
149  && plotOpt.GetSubtractMaskFromSilk() )
150  {
151  if( aLayer == F_SilkS )
152  layer_mask = LSET( F_Mask );
153  else
154  layer_mask = LSET( B_Mask );
155 
156  // Create the mask to subtract by creating a negative layer polarity
157  aPlotter->SetLayerPolarity( false );
158 
159  // Disable plot pad holes
161 
162  // Plot the mask
163  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
164  }
165 
166  break;
167 
168  // These layers are plotted like silk screen layers.
169  // Mainly, pads on these layers are not filled.
170  // This is not necessary the best choice.
171  case Dwgs_User:
172  case Cmts_User:
173  case Eco1_User:
174  case Eco2_User:
175  case Edge_Cuts:
176  case Margin:
177  case F_CrtYd:
178  case B_CrtYd:
179  case F_Fab:
180  case B_Fab:
181  plotOpt.SetSkipPlotNPTH_Pads( false );
183 
184  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF && plotOpt.GetDXFPlotPolygonMode() )
185  // PlotLayerOutlines() is designed only for DXF plotters.
186  // and must not be used for other plot formats
187  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
188  else
189  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
190 
191  break;
192 
193  default:
194  plotOpt.SetSkipPlotNPTH_Pads( false );
196 
197  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF && plotOpt.GetDXFPlotPolygonMode() )
198  // PlotLayerOutlines() is designed only for DXF plotters.
199  // and must not be used for other plot formats
200  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
201  else
202  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
203 
204  break;
205  }
206  }
207 }
208 
209 
215 void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
216  const PCB_PLOT_PARAMS& aPlotOpt )
217 {
218  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
219 
220  itemplotter.SetLayerSet( aLayerMask );
221 
222  OUTLINE_MODE plotMode = aPlotOpt.GetPlotMode();
223  bool onCopperLayer = ( LSET::AllCuMask() & aLayerMask ).any();
224  bool onSolderMaskLayer = ( LSET( 2, F_Mask, B_Mask ) & aLayerMask ).any();
225  bool onSolderPasteLayer = ( LSET( 2, F_Paste, B_Paste ) & aLayerMask ).any();
226  bool onFrontFab = ( LSET( F_Fab ) & aLayerMask ).any();
227  bool onBackFab = ( LSET( B_Fab ) & aLayerMask ).any();
228  bool sketchPads = ( onFrontFab || onBackFab ) && aPlotOpt.GetSketchPadsOnFabLayers();
229 
230  // Plot edge layer and graphic items
231  itemplotter.PlotBoardGraphicItems();
232 
233  // Draw footprint texts:
234  for( const FOOTPRINT* footprint : aBoard->Footprints() )
235  itemplotter.PlotFootprintTextItems( footprint );
236 
237  // Draw footprint other graphic items:
238  for( const FOOTPRINT* footprint : aBoard->Footprints() )
239  itemplotter.PlotFootprintGraphicItems( footprint );
240 
241  // Plot footprint pads
242  for( FOOTPRINT* footprint : aBoard->Footprints() )
243  {
244  aPlotter->StartBlock( nullptr );
245 
246  for( PAD* pad : footprint->Pads() )
247  {
248  OUTLINE_MODE padPlotMode = plotMode;
249 
250  if( !( pad->GetLayerSet() & aLayerMask ).any() )
251  {
252  if( sketchPads &&
253  ( ( onFrontFab && pad->GetLayerSet().Contains( F_Cu ) ) ||
254  ( onBackFab && pad->GetLayerSet().Contains( B_Cu ) ) ) )
255  {
256  padPlotMode = SKETCH;
257  }
258  else
259  {
260  continue;
261  }
262  }
263 
265  if( onCopperLayer && !pad->FlashLayer( aLayerMask ) )
266  continue;
267 
269 
270  if( pad->GetLayerSet()[B_Cu] )
271  color = aPlotOpt.ColorSettings()->GetColor( LAYER_PAD_BK );
272 
273  if( pad->GetLayerSet()[F_Cu] )
274  color = color.LegacyMix( aPlotOpt.ColorSettings()->GetColor( LAYER_PAD_FR ) );
275 
276  if( sketchPads && aLayerMask[F_Fab] )
277  color = aPlotOpt.ColorSettings()->GetColor( F_Fab );
278  else if( sketchPads && aLayerMask[B_Fab] )
279  color = aPlotOpt.ColorSettings()->GetColor( B_Fab );
280 
281  wxSize margin;
282  int width_adj = 0;
283 
284  if( onCopperLayer )
285  width_adj = itemplotter.getFineWidthAdj();
286 
287  if( onSolderMaskLayer )
288  margin.x = margin.y = pad->GetSolderMaskMargin();
289 
290  if( onSolderPasteLayer )
291  margin = pad->GetSolderPasteMargin();
292 
293  // not all shapes can have a different margin for x and y axis
294  // in fact only oval and rect shapes can have different values.
295  // Round shape have always the same x,y margin
296  // so define a unique value for other shapes that do not support different values
297  int mask_clearance = margin.x;
298 
299  // Now offset the pad size by margin + width_adj
300  wxSize padPlotsSize = pad->GetSize() + margin * 2 + wxSize( width_adj, width_adj );
301 
302  // Store these parameters that can be modified to plot inflated/deflated pads shape
303  PAD_SHAPE padShape = pad->GetShape();
304  wxSize padSize = pad->GetSize();
305  wxSize padDelta = pad->GetDelta(); // has meaning only for trapezoidal pads
306  double padCornerRadius = pad->GetRoundRectCornerRadius();
307 
308  // Don't draw a null size item :
309  if( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 )
310  continue;
311 
312  switch( pad->GetShape() )
313  {
314  case PAD_SHAPE::CIRCLE:
315  case PAD_SHAPE::OVAL:
316  pad->SetSize( padPlotsSize );
317 
318  if( aPlotOpt.GetSkipPlotNPTH_Pads() &&
320  ( pad->GetSize() == pad->GetDrillSize() ) &&
321  ( pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
322  {
323  break;
324  }
325 
326  itemplotter.PlotPad( pad, color, padPlotMode );
327  break;
328 
329  case PAD_SHAPE::RECT:
330  pad->SetSize( padPlotsSize );
331 
332  if( mask_clearance > 0 )
333  {
334  pad->SetShape( PAD_SHAPE::ROUNDRECT );
335  pad->SetRoundRectCornerRadius( mask_clearance );
336  }
337 
338  itemplotter.PlotPad( pad, color, padPlotMode );
339  break;
340 
342  // inflate/deflate a trapezoid is a bit complex.
343  // so if the margin is not null, build a similar polygonal pad shape,
344  // and inflate/deflate the polygonal shape
345  // because inflating/deflating using different values for y and y
346  // we are using only margin.x as inflate/deflate value
347  if( mask_clearance == 0 )
348  {
349  itemplotter.PlotPad( pad, color, padPlotMode );
350  }
351  else
352  {
353  PAD dummy( *pad );
354  dummy.SetAnchorPadShape( PAD_SHAPE::CIRCLE );
355  dummy.SetShape( PAD_SHAPE::CUSTOM );
356  SHAPE_POLY_SET outline;
357  outline.NewOutline();
358  int dx = padSize.x / 2;
359  int dy = padSize.y / 2;
360  int ddx = padDelta.x / 2;
361  int ddy = padDelta.y / 2;
362 
363  outline.Append( -dx - ddy, dy + ddx );
364  outline.Append( dx + ddy, dy - ddx );
365  outline.Append( dx - ddy, -dy + ddx );
366  outline.Append( -dx + ddy, -dy - ddx );
367 
368  // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
369  // which can create bad shapes if margin.x is < 0
370  int maxError = aBoard->GetDesignSettings().m_MaxError;
371  int numSegs = GetArcToSegmentCount( mask_clearance, maxError, 360.0 );
372  outline.InflateWithLinkedHoles( mask_clearance, numSegs,
374  dummy.DeletePrimitivesList();
375  dummy.AddPrimitivePoly( outline, 0, true );
376 
377  // Be sure the anchor pad is not bigger than the deflated shape because this
378  // anchor will be added to the pad shape when plotting the pad. So now the
379  // polygonal shape is built, we can clamp the anchor size
380  dummy.SetSize( wxSize( 0,0 ) );
381 
382  itemplotter.PlotPad( &dummy, color, padPlotMode );
383  }
384 
385  break;
386 
388  {
389  // rounding is stored as a percent, but we have to change the new radius
390  // to initial_radius + clearance to have a inflated/deflated similar shape
391  int initial_radius = pad->GetRoundRectCornerRadius();
392  pad->SetSize( padPlotsSize );
393  pad->SetRoundRectCornerRadius( std::max( initial_radius + mask_clearance, 0 ) );
394 
395  itemplotter.PlotPad( pad, color, padPlotMode );
396  break;
397  }
398 
400  if( mask_clearance == 0 )
401  {
402  // the size can be slightly inflated by width_adj (PS/PDF only)
403  pad->SetSize( padPlotsSize );
404  itemplotter.PlotPad( pad, color, padPlotMode );
405  }
406  else
407  {
408  // Due to the polygonal shape of a CHAMFERED_RECT pad, the best way is to
409  // convert the pad shape to a full polygon, inflate/deflate the polygon
410  // and use a dummy CUSTOM pad to plot the final shape.
411  PAD dummy( *pad );
412  // Build the dummy pad outline with coordinates relative to the pad position
413  // and orientation 0. The actual pos and rotation will be taken in account
414  // later by the plot function
415  dummy.SetPosition( wxPoint( 0, 0 ) );
416  dummy.SetOrientation( 0 );
417  SHAPE_POLY_SET outline;
418  int maxError = aBoard->GetDesignSettings().m_MaxError;
419  int numSegs = GetArcToSegmentCount( mask_clearance, maxError, 360.0 );
420  dummy.TransformShapeWithClearanceToPolygon( outline, UNDEFINED_LAYER, 0,
421  maxError, ERROR_INSIDE );
422  outline.InflateWithLinkedHoles( mask_clearance, numSegs,
424 
425  // Initialize the dummy pad shape:
426  dummy.SetAnchorPadShape( PAD_SHAPE::CIRCLE );
427  dummy.SetShape( PAD_SHAPE::CUSTOM );
428  dummy.DeletePrimitivesList();
429  dummy.AddPrimitivePoly( outline, 0, true );
430 
431  // Be sure the anchor pad is not bigger than the deflated shape because this
432  // anchor will be added to the pad shape when plotting the pad.
433  // So we set the anchor size to 0
434  dummy.SetSize( wxSize( 0,0 ) );
435  dummy.SetPosition( pad->GetPosition() );
436  dummy.SetOrientation( pad->GetOrientation() );
437 
438  itemplotter.PlotPad( &dummy, color, padPlotMode );
439  }
440 
441  break;
442 
443  case PAD_SHAPE::CUSTOM:
444  {
445  // inflate/deflate a custom shape is a bit complex.
446  // so build a similar pad shape, and inflate/deflate the polygonal shape
447  PAD dummy( *pad );
448  SHAPE_POLY_SET shape;
449  pad->MergePrimitivesAsPolygon( &shape, UNDEFINED_LAYER );
450 
451  // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
452  // which can create bad shapes if margin.x is < 0
453  int maxError = aBoard->GetDesignSettings().m_MaxError;
454  int numSegs = GetArcToSegmentCount( mask_clearance, maxError, 360.0 );
455  shape.InflateWithLinkedHoles( mask_clearance, numSegs, SHAPE_POLY_SET::PM_FAST );
456  dummy.DeletePrimitivesList();
457  dummy.AddPrimitivePoly( shape, 0, true );
458 
459  // Be sure the anchor pad is not bigger than the deflated shape because this
460  // anchor will be added to the pad shape when plotting the pad. So now the
461  // polygonal shape is built, we can clamp the anchor size
462  if( mask_clearance < 0 ) // we expect margin.x = margin.y for custom pads
463  dummy.SetSize( padPlotsSize );
464 
465  itemplotter.PlotPad( &dummy, color, padPlotMode );
466  break;
467  }
468  }
469 
470  // Restore the pad parameters modified by the plot code
471  pad->SetSize( padSize );
472  pad->SetDelta( padDelta );
473  pad->SetShape( padShape );
474  pad->SetRoundRectCornerRadius( padCornerRadius );
475  }
476 
477  aPlotter->EndBlock( nullptr );
478  }
479 
480  // Plot vias on copper layers, and if aPlotOpt.GetPlotViaOnMaskLayer() is true,
481  // plot them on solder mask
482 
483  GBR_METADATA gbr_metadata;
484 
485  bool isOnCopperLayer = ( aLayerMask & LSET::AllCuMask() ).any();
486 
487  if( isOnCopperLayer )
488  {
491  }
492 
493  aPlotter->StartBlock( nullptr );
494 
495  for( const PCB_TRACK* track : aBoard->Tracks() )
496  {
497  const PCB_VIA* via = dyn_cast<const PCB_VIA*>( track );
498 
499  if( !via )
500  continue;
501 
502  // vias are not plotted if not on selected layer, but if layer is SOLDERMASK_LAYER_BACK
503  // or SOLDERMASK_LAYER_FRONT, vias are drawn only if they are on the corresponding
504  // external copper layer
505  LSET via_mask_layer = via->GetLayerSet();
506 
507  if( aPlotOpt.GetPlotViaOnMaskLayer() )
508  {
509  if( via_mask_layer[B_Cu] )
510  via_mask_layer.set( B_Mask );
511 
512  if( via_mask_layer[F_Cu] )
513  via_mask_layer.set( F_Mask );
514  }
515 
516  if( !( via_mask_layer & aLayerMask ).any() )
517  continue;
518 
519  int via_margin = 0;
520  double width_adj = 0;
521 
522  // If the current layer is a solder mask, use the global mask clearance for vias
523  if( aLayerMask[B_Mask] || aLayerMask[F_Mask] )
524  via_margin = aBoard->GetDesignSettings().m_SolderMaskMargin;
525 
526  if( ( aLayerMask & LSET::AllCuMask() ).any() )
527  width_adj = itemplotter.getFineWidthAdj();
528 
529  int diameter = via->GetWidth() + 2 * via_margin + width_adj;
530 
532  if( onCopperLayer && !via->FlashLayer( aLayerMask ) )
533  continue;
534 
535  // Don't draw a null size item :
536  if( diameter <= 0 )
537  continue;
538 
539  // Some vias can be not connected (no net).
540  // Set the m_NotInNet for these vias to force a empty net name in gerber file
541  gbr_metadata.m_NetlistMetadata.m_NotInNet = via->GetNetname().IsEmpty();
542 
543  gbr_metadata.SetNetName( via->GetNetname() );
544 
545  COLOR4D color = aPlotOpt.ColorSettings()->GetColor(
546  LAYER_VIAS + static_cast<int>( via->GetViaType() ) );
547 
548  // Set plot color (change WHITE to LIGHTGRAY because the white items are not seen on a
549  // white paper or screen
550  aPlotter->SetColor( color != WHITE ? color : LIGHTGRAY );
551  aPlotter->FlashPadCircle( via->GetStart(), diameter, plotMode, &gbr_metadata );
552  }
553 
554  aPlotter->EndBlock( nullptr );
555  aPlotter->StartBlock( nullptr );
557 
558  // Plot tracks (not vias) :
559  for( const PCB_TRACK* track : aBoard->Tracks() )
560  {
561  if( track->Type() == PCB_VIA_T )
562  continue;
563 
564  if( !aLayerMask[track->GetLayer()] )
565  continue;
566 
567  // Some track segments can be not connected (no net).
568  // Set the m_NotInNet for these segments to force a empty net name in gerber file
569  gbr_metadata.m_NetlistMetadata.m_NotInNet = track->GetNetname().IsEmpty();
570 
571  gbr_metadata.SetNetName( track->GetNetname() );
572  int width = track->GetWidth() + itemplotter.getFineWidthAdj();
573  aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) );
574 
575  if( track->Type() == PCB_ARC_T )
576  {
577  const PCB_ARC* arc = static_cast<const PCB_ARC*>( track );
578  VECTOR2D center( arc->GetCenter() );
579  int radius = arc->GetRadius();
580  double start_angle = arc->GetArcAngleStart();
581  double end_angle = start_angle + arc->GetAngle();
582 
583  aPlotter->ThickArc( wxPoint( center.x, center.y ), -end_angle, -start_angle,
584  radius, width, plotMode, &gbr_metadata );
585  }
586  else
587  {
588  aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode,
589  &gbr_metadata );
590  }
591  }
592 
593  aPlotter->EndBlock( nullptr );
594 
595  // Plot filled ares
596  aPlotter->StartBlock( nullptr );
597 
598  NETINFO_ITEM nonet( aBoard );
599 
600  for( const ZONE* zone : aBoard->Zones() )
601  {
602  for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
603  {
604  if( !aLayerMask[layer] )
605  continue;
606 
607  SHAPE_POLY_SET mainArea = zone->GetFilledPolysList( layer );
608  SHAPE_POLY_SET islands;
609 
610  for( int i = mainArea.OutlineCount() - 1; i >= 0; i-- )
611  {
612  if( zone->IsIsland( layer, i ) )
613  {
614  islands.AddOutline( mainArea.CPolygon( i )[0] );
615  mainArea.DeletePolygon( i );
616  }
617  }
618 
619  itemplotter.PlotFilledAreas( zone, mainArea );
620 
621  if( !islands.IsEmpty() )
622  {
623  ZONE dummy( *zone );
624  dummy.SetNet( &nonet );
625  itemplotter.PlotFilledAreas( &dummy, islands );
626  }
627  }
628  }
629 
630  aPlotter->EndBlock( nullptr );
631 
632  // Adding drill marks, if required and if the plotter is able to plot them:
634  itemplotter.PlotDrillMarks();
635 }
636 
637 
638 // Seems like we want to plot from back to front?
639 static const PCB_LAYER_ID plot_seq[] = {
640 
641  B_Adhes, // 32
642  F_Adhes,
643  B_Paste,
644  F_Paste,
645  B_SilkS,
646  B_Mask,
647  F_Mask,
648  Dwgs_User,
649  Cmts_User,
650  Eco1_User,
651  Eco2_User,
652  Edge_Cuts,
653  Margin,
654 
655  F_CrtYd, // CrtYd & Body are footprint only
656  B_CrtYd,
657  F_Fab,
658  B_Fab,
659 
660  B_Cu,
661  In30_Cu,
662  In29_Cu,
663  In28_Cu,
664  In27_Cu,
665  In26_Cu,
666  In25_Cu,
667  In24_Cu,
668  In23_Cu,
669  In22_Cu,
670  In21_Cu,
671  In20_Cu,
672  In19_Cu,
673  In18_Cu,
674  In17_Cu,
675  In16_Cu,
676  In15_Cu,
677  In14_Cu,
678  In13_Cu,
679  In12_Cu,
680  In11_Cu,
681  In10_Cu,
682  In9_Cu,
683  In8_Cu,
684  In7_Cu,
685  In6_Cu,
686  In5_Cu,
687  In4_Cu,
688  In3_Cu,
689  In2_Cu,
690  In1_Cu,
691  F_Cu,
692 
693  F_SilkS,
694 };
695 
696 
700 void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
701  const PCB_PLOT_PARAMS& aPlotOpt )
702 {
703  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
704  itemplotter.SetLayerSet( aLayerMask );
705 
706  SHAPE_POLY_SET outlines;
707 
708  for( LSEQ seq = aLayerMask.Seq( plot_seq, arrayDim( plot_seq ) ); seq; ++seq )
709  {
710  PCB_LAYER_ID layer = *seq;
711 
712  outlines.RemoveAllContours();
713  aBoard->ConvertBrdLayerToPolygonalContours( layer, outlines );
714 
715  outlines.Simplify( SHAPE_POLY_SET::PM_FAST );
716 
717  // Plot outlines
718  std::vector<wxPoint> cornerList;
719 
720  // Now we have one or more basic polygons: plot each polygon
721  for( int ii = 0; ii < outlines.OutlineCount(); ii++ )
722  {
723  for( int kk = 0; kk <= outlines.HoleCount(ii); kk++ )
724  {
725  cornerList.clear();
726  const SHAPE_LINE_CHAIN& path =
727  ( kk == 0 ) ? outlines.COutline( ii ) : outlines.CHole( ii, kk - 1 );
728 
729  aPlotter->PlotPoly( path, FILL_TYPE::NO_FILL );
730  }
731  }
732 
733  // Plot pad holes
735  {
736  int smallDrill = (aPlotOpt.GetDrillMarksType() == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE)
738 
739  for( FOOTPRINT* footprint : aBoard->Footprints() )
740  {
741  for( PAD* pad : footprint->Pads() )
742  {
743  wxSize hole = pad->GetDrillSize();
744 
745  if( hole.x == 0 || hole.y == 0 )
746  continue;
747 
748  if( hole.x == hole.y )
749  {
750  hole.x = std::min( smallDrill, hole.x );
751  aPlotter->Circle( pad->GetPosition(), hole.x, FILL_TYPE::NO_FILL );
752  }
753  else
754  {
755  // Note: small drill marks have no significance when applied to slots
756  const SHAPE_SEGMENT* seg = pad->GetEffectiveHoleShape();
757  aPlotter->ThickSegment( (wxPoint) seg->GetSeg().A,
758  (wxPoint) seg->GetSeg().B,
759  seg->GetWidth(), SKETCH, nullptr );
760  }
761  }
762  }
763  }
764 
765  // Plot vias holes
766  for( PCB_TRACK* track : aBoard->Tracks() )
767  {
768  const PCB_VIA* via = dyn_cast<const PCB_VIA*>( track );
769 
770  if( via && via->IsOnLayer( layer ) ) // via holes can be not through holes
771  {
772  aPlotter->Circle( via->GetPosition(), via->GetDrillValue(), FILL_TYPE::NO_FILL );
773  }
774  }
775  }
776 }
777 
778 
809 #define NEW_ALGO 1
810 
811 void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
812  const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness )
813 {
814  int maxError = aBoard->GetDesignSettings().m_MaxError;
815  PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask;
816  SHAPE_POLY_SET buffer;
817  SHAPE_POLY_SET* boardOutline = nullptr;
818 
819  if( aBoard->GetBoardPolygonOutlines( buffer ) )
820  boardOutline = &buffer;
821 
822  // We remove 1nm as we expand both sides of the shapes, so allowing for
823  // a strictly greater than or equal comparison in the shape separation (boolean add)
824  // means that we will end up with separate shapes that then are shrunk
825  int inflate = aMinThickness/2 - 1;
826 
827  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
828  itemplotter.SetLayerSet( aLayerMask );
829 
830  // Plot edge layer and graphic items.
831  // They do not have a solder Mask margin, because they are graphic items
832  // on this layer (like logos), not actually areas around pads.
833 
834  itemplotter.PlotBoardGraphicItems();
835 
836  for( FOOTPRINT* footprint : aBoard->Footprints() )
837  {
838  for( BOARD_ITEM* item : footprint->GraphicalItems() )
839  {
840  itemplotter.PlotFootprintTextItems( footprint );
841 
842  if( item->Type() == PCB_FP_SHAPE_T && item->GetLayer() == layer )
843  itemplotter.PlotFootprintGraphicItem( (FP_SHAPE*) item );
844  }
845  }
846 
847  // Build polygons for each pad shape. The size of the shape on solder mask should be size
848  // of pad + clearance around the pad, where clearance = solder mask clearance + extra margin.
849  // Extra margin is half the min width for solder mask, which is used to merge too-close shapes
850  // (distance < aMinThickness), and will be removed when creating the actual shapes.
851 
852  // Will contain shapes inflated by inflate value that will be merged and deflated by
853  // inflate value to build final polygons
854  // After calculations the remaining polygons are polygons to plot
855  SHAPE_POLY_SET areas;
856 
857  // Will contain exact shapes of all items on solder mask
858  SHAPE_POLY_SET initialPolys;
859 
860 #if NEW_ALGO
861  // Generate polygons with arcs inside the shape or exact shape
862  // to minimize shape changes created by arc to segment size correction.
864 #endif
865  {
866  // Plot pads
867  for( FOOTPRINT* footprint : aBoard->Footprints() )
868  {
869  // add shapes with their exact mask layer size in initialPolys
870  footprint->TransformPadsWithClearanceToPolygon( initialPolys, layer, 0, maxError,
871  ERROR_OUTSIDE );
872  // add shapes inflated by aMinThickness/2 in areas
873  footprint->TransformPadsWithClearanceToPolygon( areas, layer, inflate, maxError,
874  ERROR_OUTSIDE );
875  }
876 
877  // Plot vias on solder masks, if aPlotOpt.GetPlotViaOnMaskLayer() is true,
878  if( aPlotOpt.GetPlotViaOnMaskLayer() )
879  {
880  // The current layer is a solder mask, use the global mask clearance for vias
881  int via_clearance = aBoard->GetDesignSettings().m_SolderMaskMargin;
882  int via_margin = via_clearance + inflate;
883 
884  for( PCB_TRACK* track : aBoard->Tracks() )
885  {
886  const PCB_VIA* via = dyn_cast<const PCB_VIA*>( track );
887 
888  if( !via )
889  continue;
890 
891  // vias are plotted only if they are on the corresponding external copper layer
892  LSET via_set = via->GetLayerSet();
893 
894  if( via_set[B_Cu] )
895  via_set.set( B_Mask );
896 
897  if( via_set[F_Cu] )
898  via_set.set( F_Mask );
899 
900  if( !( via_set & aLayerMask ).any() )
901  continue;
902 
903  // add shapes with their exact mask layer size in initialPolys
904  via->TransformShapeWithClearanceToPolygon( initialPolys, layer, via_clearance,
905  maxError, ERROR_OUTSIDE );
906  // add shapes inflated by aMinThickness/2 in areas
907  via->TransformShapeWithClearanceToPolygon( areas, layer, via_margin, maxError,
908  ERROR_OUTSIDE );
909  }
910  }
911 
912  // Add filled zone areas.
913 #if 0 // Set to 1 if a solder mask margin must be applied to zones on solder mask
914  int zone_margin = aBoard->GetDesignSettings().m_SolderMaskMargin;
915 #else
916  int zone_margin = 0;
917 #endif
918 
919  for( ZONE* zone : aBoard->Zones() )
920  {
921  if( zone->GetLayer() != layer )
922  continue;
923 
924  // add shapes inflated by aMinThickness/2 in areas
925  zone->TransformSmoothedOutlineToPolygon( areas, inflate + zone_margin, boardOutline );
926 
927  // add shapes with their exact mask layer size in initialPolys
928  zone->TransformSmoothedOutlineToPolygon( initialPolys, zone_margin, boardOutline );
929  }
930 
931  int numSegs = GetArcToSegmentCount( inflate, maxError, 360.0 );
932 
933  // Merge all polygons: After deflating, not merged (not overlapping) polygons
934  // will have the initial shape (with perhaps small changes due to deflating transform)
936  areas.Deflate( inflate, numSegs );
937  }
938 
939 #if !NEW_ALGO
940  // To avoid a lot of code, use a ZONE to handle and plot polygons, because our polygons look
941  // exactly like filled areas in zones.
942  // Note, also this code is not optimized: it creates a lot of copy/duplicate data.
943  // However it is not complex, and fast enough for plot purposes (copy/convert data is only a
944  // very small calculation time for these calculations).
945  ZONE zone( aBoard );
946  zone.SetMinThickness( 0 ); // trace polygons only
947  zone.SetLayer( layer );
948 
949  // Combine the current areas to initial areas. This is mandatory because inflate/deflate
950  // transform is not perfect, and we want the initial areas perfectly kept
951  areas.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST );
953 
954  itemplotter.PlotFilledAreas( &zone, areas );
955 #else
956 
957  // Remove initial shapes: each shape will be added later, as flashed item or region
958  // with a suitable attribute.
959  // Do not merge pads is mandatory in Gerber files: They must be identified as pads
960 
961  // we deflate areas in polygons, to avoid after subtracting initial shapes
962  // having small artifacts due to approximations during polygon transforms
964 
965  // Slightly inflate polygons to avoid any gap between them and other shapes,
966  // These gaps are created by arc to segments approximations
967  areas.Inflate( Millimeter2iu( 0.002 ),6 );
968 
969  // Now, only polygons with a too small thickness are stored in areas.
971 
972  // Plot each initial shape (pads and polygons on mask layer), with suitable attributes:
973  PlotStandardLayer( aBoard, aPlotter, aLayerMask, aPlotOpt );
974 
975  for( int ii = 0; ii < areas.OutlineCount(); ii++ )
976  {
977  const SHAPE_LINE_CHAIN& path = areas.COutline( ii );
978 
979  // polygon area in mm^2 :
980  double curr_area = path.Area() / ( IU_PER_MM * IU_PER_MM );
981 
982  // Skip very small polygons: they are certainly artifacts created by
983  // arc approximations and polygon transforms
984  // (inflate/deflate transforms)
985  constexpr double poly_min_area_mm2 = 0.01; // 0.01 mm^2 gives a good filtering
986 
987  if( curr_area < poly_min_area_mm2 )
988  continue;
989 
990  aPlotter->PlotPoly( path, FILL_TYPE::FILLED_SHAPE );
991  }
992 #endif
993 }
994 
995 
1002 static void initializePlotter( PLOTTER* aPlotter, const BOARD* aBoard,
1003  const PCB_PLOT_PARAMS* aPlotOpts )
1004 {
1005  PAGE_INFO pageA4( wxT( "A4" ) );
1006  const PAGE_INFO& pageInfo = aBoard->GetPageSettings();
1007  const PAGE_INFO* sheet_info;
1008  double paperscale; // Page-to-paper ratio
1009  wxSize paperSizeIU;
1010  wxSize pageSizeIU( pageInfo.GetSizeIU() );
1011  bool autocenter = false;
1012 
1013  // Special options: to fit the sheet to an A4 sheet replace the paper size. However there
1014  // is a difference between the autoscale and the a4paper option:
1015  // - Autoscale fits the board to the paper size
1016  // - A4paper fits the original paper size to an A4 sheet
1017  // - Both of them fit the board to an A4 sheet
1018  if( aPlotOpts->GetA4Output() )
1019  {
1020  sheet_info = &pageA4;
1021  paperSizeIU = pageA4.GetSizeIU();
1022  paperscale = (double) paperSizeIU.x / pageSizeIU.x;
1023  autocenter = true;
1024  }
1025  else
1026  {
1027  sheet_info = &pageInfo;
1028  paperSizeIU = pageSizeIU;
1029  paperscale = 1;
1030 
1031  // Need autocentering only if scale is not 1:1
1032  autocenter = (aPlotOpts->GetScale() != 1.0);
1033  }
1034 
1035  EDA_RECT bbox = aBoard->ComputeBoundingBox();
1036  wxPoint boardCenter = bbox.Centre();
1037  wxSize boardSize = bbox.GetSize();
1038 
1039  double compound_scale;
1040 
1041  // Fit to 80% of the page if asked; it could be that the board is empty, in this case
1042  // regress to 1:1 scale
1043  if( aPlotOpts->GetAutoScale() && boardSize.x > 0 && boardSize.y > 0 )
1044  {
1045  double xscale = (paperSizeIU.x * 0.8) / boardSize.x;
1046  double yscale = (paperSizeIU.y * 0.8) / boardSize.y;
1047 
1048  compound_scale = std::min( xscale, yscale ) * paperscale;
1049  }
1050  else
1051  {
1052  compound_scale = aPlotOpts->GetScale() * paperscale;
1053  }
1054 
1055  // For the plot offset we have to keep in mind the auxiliary origin too: if autoscaling is
1056  // off we check that plot option (i.e. autoscaling overrides auxiliary origin)
1057  wxPoint offset( 0, 0);
1058 
1059  if( autocenter )
1060  {
1061  offset.x = KiROUND( boardCenter.x - ( paperSizeIU.x / 2.0 ) / compound_scale );
1062  offset.y = KiROUND( boardCenter.y - ( paperSizeIU.y / 2.0 ) / compound_scale );
1063  }
1064  else
1065  {
1066  if( aPlotOpts->GetUseAuxOrigin() )
1067  offset = aBoard->GetDesignSettings().m_AuxOrigin;
1068  }
1069 
1070  aPlotter->SetPageSettings( *sheet_info );
1071 
1072  aPlotter->SetViewport( offset, IU_PER_MILS/10, compound_scale, aPlotOpts->GetMirror() );
1073 
1074  // Has meaning only for gerber plotter. Must be called only after SetViewport
1075  aPlotter->SetGerberCoordinatesFormat( aPlotOpts->GetGerberPrecision() );
1076 
1077  // Has meaning only for SVG plotter. Must be called only after SetViewport
1078  aPlotter->SetSvgCoordinatesFormat( aPlotOpts->GetSvgPrecision(), aPlotOpts->GetSvgUseInch() );
1079 
1080  aPlotter->SetCreator( wxT( "PCBNEW" ) );
1081  aPlotter->SetColorMode( false ); // default is plot in Black and White.
1082  aPlotter->SetTextMode( aPlotOpts->GetTextMode() );
1083 }
1084 
1085 
1089 static void FillNegativeKnockout( PLOTTER *aPlotter, const EDA_RECT &aBbbox )
1090 {
1091  const int margin = 5 * IU_PER_MM; // Add a 5 mm margin around the board
1092  aPlotter->SetNegative( true );
1093  aPlotter->SetColor( WHITE ); // Which will be plotted as black
1094  EDA_RECT area = aBbbox;
1095  area.Inflate( margin );
1096  aPlotter->Rect( area.GetOrigin(), area.GetEnd(), FILL_TYPE::FILLED_SHAPE );
1097  aPlotter->SetColor( BLACK );
1098 }
1099 
1100 
1104 static void ConfigureHPGLPenSizes( HPGL_PLOTTER *aPlotter, const PCB_PLOT_PARAMS *aPlotOpts )
1105 {
1106  // Compute penDiam (the value is given in mils) in pcb units, with plot scale (if Scale is 2,
1107  // penDiam value is always m_HPGLPenDiam so apparent penDiam is actually penDiam / Scale
1108  int penDiam = KiROUND( aPlotOpts->GetHPGLPenDiameter() * IU_PER_MILS / aPlotOpts->GetScale() );
1109 
1110  // Set HPGL-specific options and start
1111  aPlotter->SetPenSpeed( aPlotOpts->GetHPGLPenSpeed() );
1112  aPlotter->SetPenNumber( aPlotOpts->GetHPGLPenNum() );
1113  aPlotter->SetPenDiameter( penDiam );
1114 }
1115 
1116 
1123 PLOTTER* StartPlotBoard( BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aLayer,
1124  const wxString& aFullFileName, const wxString& aSheetDesc )
1125 {
1126  // Create the plotter driver and set the few plotter specific options
1127  PLOTTER* plotter = nullptr;
1128 
1129  switch( aPlotOpts->GetFormat() )
1130  {
1131  case PLOT_FORMAT::DXF:
1132  DXF_PLOTTER* DXF_plotter;
1133  DXF_plotter = new DXF_PLOTTER();
1134  DXF_plotter->SetUnits( aPlotOpts->GetDXFPlotUnits() );
1135 
1136  plotter = DXF_plotter;
1137  break;
1138 
1139  case PLOT_FORMAT::POST:
1140  PS_PLOTTER* PS_plotter;
1141  PS_plotter = new PS_PLOTTER();
1142  PS_plotter->SetScaleAdjust( aPlotOpts->GetFineScaleAdjustX(),
1143  aPlotOpts->GetFineScaleAdjustY() );
1144  plotter = PS_plotter;
1145  break;
1146 
1147  case PLOT_FORMAT::PDF:
1148  plotter = new PDF_PLOTTER();
1149  break;
1150 
1151  case PLOT_FORMAT::HPGL:
1152  HPGL_PLOTTER* HPGL_plotter;
1153  HPGL_plotter = new HPGL_PLOTTER();
1154 
1155  // HPGL options are a little more convoluted to compute, so they get their own function
1156  ConfigureHPGLPenSizes( HPGL_plotter, aPlotOpts );
1157  plotter = HPGL_plotter;
1158  break;
1159 
1160  case PLOT_FORMAT::GERBER:
1161  plotter = new GERBER_PLOTTER();
1162  break;
1163 
1164  case PLOT_FORMAT::SVG:
1165  plotter = new SVG_PLOTTER();
1166  break;
1167 
1168  default:
1169  wxASSERT( false );
1170  return nullptr;
1171  }
1172 
1174  renderSettings->LoadColors( aPlotOpts->ColorSettings() );
1175  renderSettings->SetDefaultPenWidth( Millimeter2iu( 0.0212 ) ); // Hairline at 1200dpi
1176  plotter->SetRenderSettings( renderSettings );
1177 
1178  // Compute the viewport and set the other options
1179 
1180  // page layout is not mirrored, so temporarily change mirror option for the page layout
1181  PCB_PLOT_PARAMS plotOpts = *aPlotOpts;
1182 
1183  if( plotOpts.GetPlotFrameRef() && plotOpts.GetMirror() )
1184  plotOpts.SetMirror( false );
1185 
1186  initializePlotter( plotter, aBoard, &plotOpts );
1187 
1188  if( plotter->OpenFile( aFullFileName ) )
1189  {
1190  plotter->ClearHeaderLinesList();
1191 
1192  // For the Gerber "file function" attribute, set the layer number
1193  if( plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1194  {
1195  bool useX2mode = plotOpts.GetUseGerberX2format();
1196 
1197  GERBER_PLOTTER* gbrplotter = static_cast <GERBER_PLOTTER*> ( plotter );
1198  gbrplotter->DisableApertMacros( plotOpts.GetDisableGerberMacros() );
1199  gbrplotter->UseX2format( useX2mode );
1200  gbrplotter->UseX2NetAttributes( plotOpts.GetIncludeGerberNetlistInfo() );
1201 
1202  // Attributes can be added using X2 format or as comment (X1 format)
1203  AddGerberX2Attribute( plotter, aBoard, aLayer, not useX2mode );
1204  }
1205 
1206  plotter->StartPlot();
1207 
1208  // Plot the frame reference if requested
1209  if( aPlotOpts->GetPlotFrameRef() )
1210  {
1211  PlotDrawingSheet( plotter, aBoard->GetProject(), aBoard->GetTitleBlock(),
1212  aBoard->GetPageSettings(), "1", 1, aSheetDesc,
1213  aBoard->GetFileName() );
1214 
1215  if( aPlotOpts->GetMirror() )
1216  initializePlotter( plotter, aBoard, aPlotOpts );
1217  }
1218 
1219  // When plotting a negative board: draw a black rectangle (background for plot board
1220  // in white) and switch the current color to WHITE; note the color inversion is actually
1221  // done in the driver (if supported)
1222  if( aPlotOpts->GetNegative() )
1223  {
1224  EDA_RECT bbox = aBoard->ComputeBoundingBox();
1225  FillNegativeKnockout( plotter, bbox );
1226  }
1227 
1228  return plotter;
1229  }
1230 
1231  delete plotter->RenderSettings();
1232  delete plotter;
1233  return nullptr;
1234 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
OUTLINE_MODE GetPlotMode() const
Handle special data (items attributes) during plot.
COLOR4D getColor(LAYER_NUM aLayer) const
White color is special because it cannot be seen on a white paper in B&W mode.
OUTLINE_MODE
Definition: outline_mode.h:24
virtual wxPoint GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_track.h:282
const POLYGON & CPolygon(int aIndex) const
const PAGE_INFO & GetPageSettings() const
Definition: board.h:535
virtual void SetCreator(const wxString &aCreator)
Definition: plotter.h:174
virtual void LoadColors(const COLOR_SETTINGS *aSettings) override
Definition: pcb_painter.cpp:90
virtual void PlotPoly(const std::vector< wxPoint > &aCornerList, FILL_TYPE aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=nullptr)=0
Draw a polygon ( filled or not ).
int OutlineCount() const
Return the number of vertices in a given outline/hole.
void UseX2NetAttributes(bool aEnable)
virtual void EndBlock(void *aData)
calling this function allows one to define the end of a group of drawing items for instance in SVG or...
Definition: plotter.h:496
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:1898
ZONES & Zones()
Definition: board.h:239
bool GetPlotFrameRef() const
bool GetDXFPlotPolygonMode() const
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset difference For aFastMode meaning, see function booleanOp.
virtual bool StartPlot()=0
void ConvertBrdLayerToPolygonalContours(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aOutlines) const
Build a set of polygons which are the outlines of copper items (pads, tracks, vias,...
virtual void SetPosition(const wxPoint &aPos)
Definition: eda_item.h:253
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:80
Plotting engines (PostScript, Gerber, HPGL and DXF)
static void FillNegativeKnockout(PLOTTER *aPlotter, const EDA_RECT &aBbbox)
Prefill in black an area a little bigger than the board to prepare for the negative plot.
virtual void Rect(const wxPoint &p1, const wxPoint &p2, FILL_TYPE fill, int width=USE_DEFAULT_LINE_WIDTH)=0
static constexpr double IU_PER_MM
Mock up a conversion function.
virtual bool OpenFile(const wxString &aFullFilename)
Open or create the plot file aFullFilename.
Definition: plotter.cpp:76
void PlotFootprintGraphicItems(const FOOTPRINT *aFootprint)
void SetNetAttribType(int aNetAttribType)
Definition: gbr_metadata.h:219
virtual void SetColorMode(bool aColorMode)
Plot in B/W or color.
Definition: plotter.h:152
bool GetDisableGerberMacros() const
void SetScaleAdjust(double scaleX, double scaleY)
Set the 'fine' scaling for the postscript engine.
virtual void SetLayerPolarity(bool aPositive)
Set the current Gerber layer polarity to positive or negative by writing %LPD*% or %LPC*% to the Gerb...
Definition: plotter.h:456
static const PCB_LAYER_ID plot_seq[]
void PlotStandardLayer(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
Plot a copper layer or mask.
int color
Definition: DXF_plotter.cpp:60
bool IsEmpty() const
void SetRenderSettings(RENDER_SETTINGS *aSettings)
Definition: plotter.h:155
PROJECT * GetProject() const
Definition: board.h:360
void PlotDrillMarks()
Draw a drill mark for pads and vias.
void SetMirror(bool aFlag)
virtual void SetPenDiameter(double diameter)
PLOTTER * StartPlotBoard(BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aLayer, const wxString &aFullFileName, const wxString &aSheetDesc)
Open a new plotfile using the options (and especially the format) specified in the options and prepar...
virtual void StartBlock(void *aData)
calling this function allows one to define the beginning of a group of drawing items,...
Definition: plotter.h:487
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
void UseX2format(bool aEnable)
static void ConfigureHPGLPenSizes(HPGL_PLOTTER *aPlotter, const PCB_PLOT_PARAMS *aPlotOpts)
Calculate the effective size of HPGL pens and set them in the plotter object.
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
int GetHPGLPenSpeed() const
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
void AddGerberX2Attribute(PLOTTER *aPlotter, const BOARD *aBoard, LAYER_NUM aLayer, bool aUseX1CompatibilityMode)
Calculate some X2 attributes as defined in the Gerber file format specification and add them to the g...
Definition: pcbplot.cpp:353
void PlotPad(const PAD *aPad, COLOR4D aColor, OUTLINE_MODE aPlotMode)
Plot a pad.
void SetUnits(DXF_UNITS aUnit)
Set the units to use for plotting the DXF file.
void PlotFootprintGraphicItem(const FP_SHAPE *aShape)
Definition: color4d.h:44
void SetDrillMarksType(DrillMarksType aVal)
double m_SmallDrillMarkSize
The diameter of the drill marks on print and plot outputs (in mm), when the "Drill marks" option is s...
void PlotFootprintTextItems(const FOOTPRINT *aFootprint)
static void initializePlotter(PLOTTER *aPlotter, const BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts)
Set up most plot options for plotting a board (especially the viewport) Important thing: page size is...
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
const wxString & GetFileName() const
Definition: board.h:228
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:588
double GetScale() const
bool GetUseGerberX2format() const
virtual void ThickSegment(const wxPoint &start, const wxPoint &end, int width, OUTLINE_MODE tracemode, void *aData)
Definition: plotter.cpp:522
virtual void SetGerberCoordinatesFormat(int aResolution, bool aUseInches=false)
Definition: plotter.h:470
virtual void SetSvgCoordinatesFormat(unsigned aResolution, bool aUseInches=false)
Definition: plotter.h:475
const SEG & GetSeg() const
bool GetMirror() const
Classes used in Pcbnew, CvPcb and GerbView.
void DeletePolygon(int aIdx)
Board plot function definition file.
static void PlotSolderMaskLayer(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt, int aMinThickness)
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:71
PCB specific render settings.
Definition: pcb_painter.h:64
const wxPoint GetEnd() const
Definition: eda_rect.h:103
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape() DO NOT REORDER, legacy_plugin is dependent on ...
Definition: pad_shapes.h:33
void PlotLayerOutlines(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
Plot outlines of copper layer.
like PAD_PTH, but not plated
PCB_LAYER_ID
A quick note on layer IDs:
bool GetA4Output() const
int GetGerberPrecision() const
LSET is a set of PCB_LAYER_IDs.
PLOT_FORMAT GetFormat() const
void SetLayerSet(LSET aLayerMask)
Definition: pcbplot.h:84
void PlotOneBoardLayer(BOARD *aBoard, PLOTTER *aPlotter, PCB_LAYER_ID aLayer, const PCB_PLOT_PARAMS &aPlotOpt)
Plot one copper or technical layer.
double GetArcAngleStart() const
Definition: pcb_track.cpp:988
Represent a set of closed polygons.
unsigned GetSvgPrecision() const
const wxPoint GetOrigin() const
Definition: eda_rect.h:101
virtual PLOT_FORMAT GetPlotterType() const =0
Returns the effective plot engine in use.
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:53
void PlotBoardGraphicItems()
Plot items like text and graphics but not tracks and footprints.
double GetRadius() const
Definition: pcb_track.cpp:970
virtual void SetPenSpeed(int speed)
Definition: plotter_hpgl.h:86
FOOTPRINTS & Footprints()
Definition: board.h:233
int getFineWidthAdj() const
Definition: pcbplot.h:75
bool GetIncludeGerberNetlistInfo() const
virtual void SetTextMode(PLOT_TEXT_MODE mode)
Change the current text mode.
Definition: plotter.h:465
void Deflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
void SetSkipPlotNPTH_Pads(bool aSkip)
PLOT_TEXT_MODE GetTextMode() const
bool GetSkipPlotNPTH_Pads() const
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
a few functions useful in geometry calculations.
void Simplify(POLYGON_MODE aFastMode)
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
void SetMinThickness(int aMinThickness)
Definition: zone.h:242
Metadata which can be added in a gerber file as attribute in X2 format.
Definition: gbr_metadata.h:204
bool GetAutoScale() const
Parameters and options when plotting/printing a board.
virtual void Circle(const wxPoint &pos, int diametre, FILL_TYPE fill, int width=USE_DEFAULT_LINE_WIDTH)=0
int NewOutline()
Creates a new hole in a given outline.
int HoleCount(int aOutline) const
Return the reference to aIndex-th outline in the set.
virtual void SetNegative(bool aNegative)
Definition: plotter.h:142
double GetFineScaleAdjustX() const
void Fracture(POLYGON_MODE aFastMode)
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
virtual void SetViewport(const wxPoint &aOffset, double aIusPerDecimil, double aScale, bool aMirror)=0
Set the plot offset and scaling for the current plot.
virtual void SetColor(const COLOR4D &color)=0
void PlotFilledAreas(const ZONE *aZone, const SHAPE_POLY_SET &aPolysList)
void Inflate(int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Perform outline inflation/deflation.
Definition: color4d.h:48
int GetHPGLPenNum() const
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new hole to the given outline (default: last) and returns its index.
void DisableApertMacros(bool aDisable)
Disable Aperture Macro (AM) command, only for broken Gerber Readers.
void SetNetName(const wxString &aNetname)
Definition: gbr_metadata.h:229
Base plotter engine class.
Definition: plotter.h:121
COLOR4D GetColor(int aLayer) const
bool GetSketchPadsOnFabLayers() const
Handle the data for a net.
Definition: netinfo.h:64
double GetAngle() const
Definition: pcb_track.cpp:976
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:156
bool GetPlotViaOnMaskLayer() const
smd pads, front layer
TITLE_BLOCK & GetTitleBlock()
Definition: board.h:541
Meta control for all vias opacity/visibility.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
bool GetSubtractMaskFromSilk() const
Represent a polyline (an zero-thickness chain of connected line segments).
When creating polygons to create a clearance polygonal area, the polygon must be same or bigger than ...
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
virtual void SetPenNumber(int number)
Definition: plotter_hpgl.h:91
void PlotDrawingSheet(PLOTTER *plotter, const PROJECT *aProject, const TITLE_BLOCK &aTitleBlock, const PAGE_INFO &aPageInfo, const wxString &aSheetNumber, int aSheetCount, const wxString &aSheetDesc, const wxString &aFilename, COLOR4D aColor, bool aIsFirstPage)
double GetHPGLPenDiameter() const
VECTOR2I A
Definition: seg.h:48
Handle the component boundary box.
Definition: eda_rect.h:42
#define IU_PER_MILS
Definition: plotter.cpp:137
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:73
void InflateWithLinkedHoles(int aFactor, int aCircleSegmentsCount, POLYGON_MODE aFastMode)
Perform outline inflation/deflation, using round corners.
wxPoint Centre() const
Definition: eda_rect.h:55
void ClearHeaderLinesList()
Remove all lines from the list of free lines to print at the beginning of the file.
Definition: plotter.h:191
virtual void ThickArc(const wxPoint &centre, double StAngle, double EndAngle, int rayon, int width, OUTLINE_MODE tracemode, void *aData)
Definition: plotter.cpp:546
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1104
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
double GetFineScaleAdjustY() const
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
void SetApertureAttrib(GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB aApertAttribute)
Definition: gbr_metadata.h:209
COLOR_SETTINGS * ColorSettings() const
DXF_UNITS GetDXFPlotUnits() const
bool m_NotInNet
true if a pad of a footprint cannot be connected (for instance a mechanical NPTH, ot a not named pad)...
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: zone.cpp:238
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
bool GetSvgUseInch() const
GBR_NETLIST_METADATA m_NetlistMetadata
An item to handle object attribute.
Definition: gbr_metadata.h:262
bool GetNegative() const
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
bool GetUseAuxOrigin() const
Definition: pad.h:57
void SetDefaultPenWidth(int aWidth)
DrillMarksType GetDrillMarksType() const
int GetWidth() const
static constexpr int Millimeter2iu(double mm)
print info associated to a net (TO.N attribute)
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
wxPoint m_AuxOrigin
origin for plot exports
TRACKS & Tracks()
Definition: board.h:230
bool GetExcludeEdgeLayer() const
virtual void FlashPadCircle(const wxPoint &aPadPos, int aDiameter, OUTLINE_MODE aTraceMode, void *aData)=0
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Inflate the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:364
const wxSize GetSize() const
Definition: eda_rect.h:91
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: plotter.h:158
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Add a new vertex to the contour indexed by aOutline and aHole (defaults to the outline of the last po...
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103
VECTOR2I B
Definition: seg.h:49