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-2019 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 <fctsys.h>
33 #include <common.h>
34 #include <plotter.h>
35 #include <base_struct.h>
36 #include <gr_text.h>
38 #include <trigo.h>
39 #include <pcb_base_frame.h>
40 #include <macros.h>
41 #include <math/util.h> // for KiROUND
42 
43 #include <class_board.h>
44 #include <class_module.h>
45 #include <class_track.h>
46 #include <class_edge_mod.h>
47 #include <class_pcb_text.h>
48 #include <class_zone.h>
49 #include <class_drawsegment.h>
50 #include <class_pcb_target.h>
51 #include <class_dimension.h>
52 
53 #include <pcbnew.h>
54 #include <pcbplot.h>
55 #include <gbr_metadata.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  * Creates the plot for silkscreen layers. Silkscreen layers have specific requirement for
66  * pads (not filled) and texts (with option to remove them from some copper areas (pads...)
67  */
68 void PlotSilkScreen( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
69  const PCB_PLOT_PARAMS& aPlotOpt )
70 {
71  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
72  itemplotter.SetLayerSet( aLayerMask );
73 
74  // Plot edge layer and graphic items
75  itemplotter.PlotBoardGraphicItems();
76 
77  // Plot footprint outlines :
78  itemplotter.Plot_Edges_Modules();
79 
80  // Plot pads (creates pads outlines, for pads on silkscreen layers)
81  LSET layersmask_plotpads = aLayerMask;
82 
83  // Calculate the mask layers of allowed layers for pads
84 
85  if( !aPlotOpt.GetPlotPadsOnSilkLayer() ) // Do not plot pads on silk screen layers
86  layersmask_plotpads.set( B_SilkS, false ).set( F_SilkS, false );
87 
88  if( layersmask_plotpads.any() )
89  {
90  for( auto Module : aBoard->Modules() )
91  {
92  aPlotter->StartBlock( NULL );
93 
94  for( auto pad : Module->Pads() )
95  {
96  // See if the pad is on this layer
97  LSET masklayer = pad->GetLayerSet();
98  if( !( masklayer & layersmask_plotpads ).any() )
99  continue;
100 
102 
103  if( layersmask_plotpads[B_SilkS] )
104  color = aPlotter->ColorSettings()->GetColor( B_SilkS );
105 
106  if( layersmask_plotpads[F_SilkS] )
107  {
108  color = ( color == COLOR4D::BLACK ) ?
109  aPlotter->ColorSettings()->GetColor( F_SilkS ) : color;
110  }
111 
112  itemplotter.PlotPad( pad, color, SKETCH );
113  }
114 
115  aPlotter->EndBlock( NULL );
116  }
117  }
118 
119  // Plot footprints fields (ref, value ...)
120  for( auto module : aBoard->Modules() )
121  {
122  if( ! itemplotter.PlotAllTextsModule( module ) )
123  {
124  wxLogMessage( _( "Your BOARD has a bad layer number for footprint %s" ),
125  module->GetReference() );
126  }
127  }
128 
129  // Plot filled areas
130  aPlotter->StartBlock( NULL );
131 
132  // Plot all zones together so we don't end up with divots where zones touch each other.
133  ZONE_CONTAINER* zone = nullptr;
134  SHAPE_POLY_SET aggregateArea;
135 
136  for( ZONE_CONTAINER* candidate : aBoard->Zones() )
137  {
138  if( !aLayerMask[ candidate->GetLayer() ] )
139  continue;
140 
141  if( !zone )
142  zone = candidate;
143 
144  aggregateArea.BooleanAdd( candidate->GetFilledPolysList(), SHAPE_POLY_SET::PM_FAST );
145  }
146 
147  if( zone )
148  {
150  itemplotter.PlotFilledAreas( zone, aggregateArea );
151  }
152 
153  aPlotter->EndBlock( NULL );
154 }
155 
156 void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
157  const PCB_PLOT_PARAMS& aPlotOpt )
158 {
159  PCB_PLOT_PARAMS plotOpt = aPlotOpt;
160  int soldermask_min_thickness = aBoard->GetDesignSettings().m_SolderMaskMinWidth;
161 
162  // Set a default color and the text mode for this layer
163  aPlotter->SetColor( aPlotOpt.GetColor() );
164  aPlotter->SetTextMode( aPlotOpt.GetTextMode() );
165 
166  // Specify that the contents of the "Edges Pcb" layer are to be plotted in addition to the
167  // contents of the currently specified layer.
168  LSET layer_mask( aLayer );
169 
170  if( !aPlotOpt.GetExcludeEdgeLayer() )
171  layer_mask.set( Edge_Cuts );
172 
173  if( IsCopperLayer( aLayer ) )
174  {
175  // Skip NPTH pads on copper layers ( only if hole size == pad size ):
176  // Drill mark will be plotted if drill mark is SMALL_DRILL_SHAPE or FULL_DRILL_SHAPE
177  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
178  {
179  plotOpt.SetSkipPlotNPTH_Pads( false );
180  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
181  }
182  else
183  {
184  plotOpt.SetSkipPlotNPTH_Pads( true );
185  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
186  }
187  }
188  else
189  {
190  switch( aLayer )
191  {
192  case B_Mask:
193  case F_Mask:
194  plotOpt.SetSkipPlotNPTH_Pads( false );
195  // Disable plot pad holes
197 
198  // Plot solder mask:
199  if( soldermask_min_thickness == 0 )
200  {
201  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
202  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
203  else
204  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
205  }
206  else
207  PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt,
208  soldermask_min_thickness );
209 
210  break;
211 
212  case B_Adhes:
213  case F_Adhes:
214  case B_Paste:
215  case F_Paste:
216  plotOpt.SetSkipPlotNPTH_Pads( false );
217  // Disable plot pad holes
219 
220  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
221  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
222  else
223  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
224  break;
225 
226  case F_SilkS:
227  case B_SilkS:
228  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF && plotOpt.GetDXFPlotPolygonMode() )
229  // PlotLayerOutlines() is designed only for DXF plotters.
230  // and must not be used for other plot formats
231  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
232  else
233  PlotSilkScreen( aBoard, aPlotter, layer_mask, plotOpt );
234 
235  // Gerber: Subtract soldermask from silkscreen if enabled
236  if( aPlotter->GetPlotterType() == PLOT_FORMAT::GERBER
237  && plotOpt.GetSubtractMaskFromSilk() )
238  {
239  if( aLayer == F_SilkS )
240  layer_mask = LSET( F_Mask );
241  else
242  layer_mask = LSET( B_Mask );
243 
244  // Create the mask to subtract by creating a negative layer polarity
245  aPlotter->SetLayerPolarity( false );
246 
247  // Disable plot pad holes
249 
250  // Plot the mask
251  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
252  }
253  break;
254 
255  // These layers are plotted like silk screen layers.
256  // Mainly, pads on these layers are not filled.
257  // This is not necessary the best choice.
258  case Dwgs_User:
259  case Cmts_User:
260  case Eco1_User:
261  case Eco2_User:
262  case Edge_Cuts:
263  case Margin:
264  case F_CrtYd:
265  case B_CrtYd:
266  case F_Fab:
267  case B_Fab:
268  plotOpt.SetSkipPlotNPTH_Pads( false );
270 
271  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF && plotOpt.GetDXFPlotPolygonMode() )
272  // PlotLayerOutlines() is designed only for DXF plotters.
273  // and must not be used for other plot formats
274  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
275  else
276  PlotSilkScreen( aBoard, aPlotter, layer_mask, plotOpt );
277  break;
278 
279  default:
280  plotOpt.SetSkipPlotNPTH_Pads( false );
282 
283  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF && plotOpt.GetDXFPlotPolygonMode() )
284  // PlotLayerOutlines() is designed only for DXF plotters.
285  // and must not be used for other plot formats
286  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
287  else
288  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
289  break;
290  }
291  }
292 }
293 
294 
295 /* Plot a copper layer or mask.
296  * Silk screen layers are not plotted here.
297  */
298 void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter,
299  LSET aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt )
300 {
301  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
302 
303  itemplotter.SetLayerSet( aLayerMask );
304 
305  EDA_DRAW_MODE_T plotMode = aPlotOpt.GetPlotMode();
306 
307  // Plot edge layer and graphic items
308  itemplotter.PlotBoardGraphicItems();
309 
310  // Draw footprint texts:
311  for( auto module : aBoard->Modules() )
312  {
313  if( ! itemplotter.PlotAllTextsModule( module ) )
314  {
315  wxLogMessage( _( "Your BOARD has a bad layer number for footprint %s" ),
316  module->GetReference() );
317  }
318  }
319 
320  // Draw footprint other graphic items:
321  for( auto module : aBoard->Modules() )
322  {
323  for( auto item : module->GraphicalItems() )
324  {
325  if( item->Type() == PCB_MODULE_EDGE_T && aLayerMask[ item->GetLayer() ] )
326  itemplotter.Plot_1_EdgeModule( (EDGE_MODULE*) item );
327  }
328  }
329 
330  // Plot footprint pads
331  for( auto module : aBoard->Modules() )
332  {
333  aPlotter->StartBlock( NULL );
334 
335  for( auto pad : module->Pads() )
336  {
337  if( (pad->GetLayerSet() & aLayerMask) == 0 )
338  continue;
339 
340  wxSize margin;
341  double width_adj = 0;
342 
343  if( ( aLayerMask & LSET::AllCuMask() ).any() )
344  width_adj = itemplotter.getFineWidthAdj();
345 
346  static const LSET speed( 4, B_Mask, F_Mask, B_Paste, F_Paste );
347 
348  LSET anded = ( speed & aLayerMask );
349 
350  if( anded == LSET( F_Mask ) || anded == LSET( B_Mask ) )
351  {
352  margin.x = margin.y = pad->GetSolderMaskMargin();
353  }
354  else if( anded == LSET( F_Paste ) || anded == LSET( B_Paste ) )
355  {
356  margin = pad->GetSolderPasteMargin();
357  }
358 
359  // Now offset the pad size by margin + width_adj
360  // this is easy for most shapes, but not for a trapezoid or a custom shape
361  wxSize padPlotsSize;
362  wxSize extraSize = margin * 2;
363  extraSize.x += width_adj;
364  extraSize.y += width_adj;
365  wxSize deltaSize = pad->GetDelta(); // has meaning only for trapezoidal pads
366 
367  if( pad->GetShape() == PAD_SHAPE_TRAPEZOID )
368  { // The easy way is to use BuildPadPolygon to calculate
369  // size and delta of the trapezoidal pad after offseting:
370  wxPoint coord[4];
371  pad->BuildPadPolygon( coord, extraSize/2, 0.0 );
372  // Calculate the size and delta from polygon corners coordinates:
373  // coord[0] is the lower left
374  // coord[1] is the upper left
375  // coord[2] is the upper right
376  // coord[3] is the lower right
377 
378  // the size is the distance between middle of segments
379  // (left/right or top/bottom)
380  // size X is the dist between left and right middle points:
381  padPlotsSize.x = ( ( -coord[0].x + coord[3].x ) // the lower segment X length
382  + ( -coord[1].x + coord[2].x ) ) // the upper segment X length
383  / 2; // the Y size is the half sum
384  // size Y is the dist between top and bottom middle points:
385  padPlotsSize.y = ( ( coord[0].y - coord[1].y ) // the left segment Y lenght
386  + ( coord[3].y - coord[2].y ) ) // the right segment Y lenght
387  / 2; // the Y size is the half sum
388 
389  // calculate the delta ( difference of lenght between 2 opposite edges )
390  // The delta.x is the delta along the X axis, therefore the delta of Y lenghts
391  wxSize delta;
392 
393  if( coord[0].y != coord[3].y )
394  delta.x = coord[0].y - coord[3].y;
395  else
396  delta.y = coord[1].x - coord[0].x;
397 
398  pad->SetDelta( delta );
399  }
400  else
401  padPlotsSize = pad->GetSize() + extraSize;
402 
403  // Don't draw a null size item :
404  if( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 )
405  continue;
406 
408 
409  if( pad->GetLayerSet()[B_Cu] )
410  color = aPlotOpt.ColorSettings()->GetColor( LAYER_PAD_BK );
411 
412  if( pad->GetLayerSet()[F_Cu] )
413  color = color.LegacyMix( aPlotOpt.ColorSettings()->GetColor( LAYER_PAD_FR ) );
414 
415  // Temporary set the pad size to the required plot size:
416  wxSize tmppadsize = pad->GetSize();
417 
418  switch( pad->GetShape() )
419  {
420  case PAD_SHAPE_CIRCLE:
421  case PAD_SHAPE_OVAL:
422  pad->SetSize( padPlotsSize );
423 
424  if( aPlotOpt.GetSkipPlotNPTH_Pads() &&
426  ( pad->GetSize() == pad->GetDrillSize() ) &&
427  ( pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED ) )
428  break;
429 
430  itemplotter.PlotPad( pad, color, plotMode );
431  break;
432 
433  case PAD_SHAPE_TRAPEZOID:
434  case PAD_SHAPE_RECT:
435  case PAD_SHAPE_ROUNDRECT:
437  pad->SetSize( padPlotsSize );
438  itemplotter.PlotPad( pad, color, plotMode );
439  break;
440 
441  case PAD_SHAPE_CUSTOM:
442  {
443  // inflate/deflate a custom shape is a bit complex.
444  // so build a similar pad shape, and inflate/deflate the polygonal shape
445  D_PAD dummy( *pad );
446  SHAPE_POLY_SET shape;
447  pad->MergePrimitivesAsPolygon( &shape );
448  // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
449  // which can create bad shapes if margin.x is < 0
450  int maxError = aBoard->GetDesignSettings().m_MaxError;
451  int numSegs = std::max( GetArcToSegmentCount( margin.x, maxError, 360.0 ), 6 );
452  shape.InflateWithLinkedHoles( margin.x, numSegs, SHAPE_POLY_SET::PM_FAST );
453  dummy.DeletePrimitivesList();
454  dummy.AddPrimitivePoly( shape, 0, false );
455  dummy.MergePrimitivesAsPolygon();
456 
457  // Be sure the anchor pad is not bigger than the deflated shape because this
458  // anchor will be added to the pad shape when plotting the pad. So now the
459  // polygonal shape is built, we can clamp the anchor size
460  if( margin.x < 0 ) // we expect margin.x = margin.y for custom pads
461  dummy.SetSize( padPlotsSize );
462 
463  itemplotter.PlotPad( &dummy, color, plotMode );
464  }
465  break;
466  }
467 
468  pad->SetSize( tmppadsize ); // Restore the pad size
469  pad->SetDelta( deltaSize );
470  }
471 
472  aPlotter->EndBlock( NULL );
473  }
474 
475  // Plot vias on copper layers, and if aPlotOpt.GetPlotViaOnMaskLayer() is true,
476  // plot them on solder mask
477 
478  GBR_METADATA gbr_metadata;
479 
480  bool isOnCopperLayer = ( aLayerMask & LSET::AllCuMask() ).any();
481 
482  if( isOnCopperLayer )
483  {
486  }
487 
488  aPlotter->StartBlock( NULL );
489 
490  for( auto track : aBoard->Tracks() )
491  {
492  const VIA* Via = dyn_cast<const VIA*>( track );
493 
494  if( !Via )
495  continue;
496 
497  // vias are not plotted if not on selected layer, but if layer is SOLDERMASK_LAYER_BACK
498  // or SOLDERMASK_LAYER_FRONT, vias are drawn only if they are on the corresponding
499  // external copper layer
500  LSET via_mask_layer = Via->GetLayerSet();
501 
502  if( aPlotOpt.GetPlotViaOnMaskLayer() )
503  {
504  if( via_mask_layer[B_Cu] )
505  via_mask_layer.set( B_Mask );
506 
507  if( via_mask_layer[F_Cu] )
508  via_mask_layer.set( F_Mask );
509  }
510 
511  if( !( via_mask_layer & aLayerMask ).any() )
512  continue;
513 
514  int via_margin = 0;
515  double width_adj = 0;
516 
517  // If the current layer is a solder mask, use the global mask clearance for vias
518  if( aLayerMask[B_Mask] || aLayerMask[F_Mask] )
519  via_margin = aBoard->GetDesignSettings().m_SolderMaskMargin;
520 
521  if( ( aLayerMask & LSET::AllCuMask() ).any() )
522  width_adj = itemplotter.getFineWidthAdj();
523 
524  int diameter = Via->GetWidth() + 2 * via_margin + width_adj;
525 
526  // Don't draw a null size item :
527  if( diameter <= 0 )
528  continue;
529 
530  // Some vias can be not connected (no net).
531  // Set the m_NotInNet for these vias to force a empty net name in gerber file
532  gbr_metadata.m_NetlistMetadata.m_NotInNet = Via->GetNetname().IsEmpty();
533 
534  gbr_metadata.SetNetName( Via->GetNetname() );
535 
536  COLOR4D color = aPlotOpt.ColorSettings()->GetColor(
537  LAYER_VIAS + static_cast<int>( Via->GetViaType() ) );
538  // Set plot color (change WHITE to LIGHTGRAY because the white items are not seen on a
539  // white paper or screen
540  aPlotter->SetColor( color != WHITE ? color : LIGHTGRAY );
541  aPlotter->FlashPadCircle( Via->GetStart(), diameter, plotMode, &gbr_metadata );
542  }
543 
544  aPlotter->EndBlock( NULL );
545  aPlotter->StartBlock( NULL );
547 
548  // Plot tracks (not vias) :
549  for( auto track : aBoard->Tracks() )
550  {
551  if( track->Type() == PCB_VIA_T )
552  continue;
553 
554  if( !aLayerMask[track->GetLayer()] )
555  continue;
556 
557  // Some track segments can be not connected (no net).
558  // Set the m_NotInNet for these segments to force a empty net name in gerber file
559  gbr_metadata.m_NetlistMetadata.m_NotInNet = track->GetNetname().IsEmpty();
560 
561  gbr_metadata.SetNetName( track->GetNetname() );
562  int width = track->GetWidth() + itemplotter.getFineWidthAdj();
563  aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) );
564  aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode, &gbr_metadata );
565  }
566 
567  aPlotter->EndBlock( NULL );
568 
569  // Plot filled ares
570  aPlotter->StartBlock( NULL );
571 
572  // Plot all zones of the same layer & net together so we don't end up with divots where
573  // zones touch each other.
574  std::set<ZONE_CONTAINER*> plotted;
575 
576  for( ZONE_CONTAINER* zone : aBoard->Zones() )
577  {
578  if( !aLayerMask[ zone->GetLayer() ] || plotted.count( zone ) )
579  continue;
580 
581  plotted.insert( zone );
582 
583  SHAPE_POLY_SET aggregateArea = zone->GetFilledPolysList();
584  bool needFracture = false; // If 2 or more filled areas are combined, resulting
585  // aggregateArea will be simplified and fractured
586  // (Long calculation time)
587 
588  for( ZONE_CONTAINER* candidate : aBoard->Zones() )
589  {
590  if( !aLayerMask[ candidate->GetLayer() ] || plotted.count( candidate ) )
591  continue;
592 
593  if( candidate->GetNetCode() != zone->GetNetCode() )
594  continue;
595 
596  // Merging zones of the same net can be done only for areas
597  // having compatible settings for drawings:
598  // use or not outline thickness, and if using outline thickness,
599  // having the same thickness
600  // because after merging only one outline thickness is used
601  if( candidate->GetFilledPolysUseThickness() != zone->GetFilledPolysUseThickness() )
602  // Should not happens, because usually the same option is used for filling
603  continue;
604 
605  if( zone->GetFilledPolysUseThickness() &&
606  ( candidate->GetMinThickness() != zone->GetMinThickness() ) )
607  continue;
608 
609  plotted.insert( candidate );
610  aggregateArea.Append( candidate->GetFilledPolysList() );
611  needFracture = true;
612  }
613 
614  if( needFracture )
615  {
618  }
619 
620  itemplotter.PlotFilledAreas( zone, aggregateArea );
621  }
622  aPlotter->EndBlock( NULL );
623 
624  // Adding drill marks, if required and if the plotter is able to plot them:
626  itemplotter.PlotDrillMarks();
627 }
628 
629 
630 // Seems like we want to plot from back to front?
631 static const PCB_LAYER_ID plot_seq[] = {
632 
633  B_Adhes, // 32
634  F_Adhes,
635  B_Paste,
636  F_Paste,
637  B_SilkS,
638  B_Mask,
639  F_Mask,
640  Dwgs_User,
641  Cmts_User,
642  Eco1_User,
643  Eco2_User,
644  Edge_Cuts,
645  Margin,
646 
647  F_CrtYd, // CrtYd & Body are footprint only
648  B_CrtYd,
649  F_Fab,
650  B_Fab,
651 
652  B_Cu,
653  In30_Cu,
654  In29_Cu,
655  In28_Cu,
656  In27_Cu,
657  In26_Cu,
658  In25_Cu,
659  In24_Cu,
660  In23_Cu,
661  In22_Cu,
662  In21_Cu,
663  In20_Cu,
664  In19_Cu,
665  In18_Cu,
666  In17_Cu,
667  In16_Cu,
668  In15_Cu,
669  In14_Cu,
670  In13_Cu,
671  In12_Cu,
672  In11_Cu,
673  In10_Cu,
674  In9_Cu,
675  In8_Cu,
676  In7_Cu,
677  In6_Cu,
678  In5_Cu,
679  In4_Cu,
680  In3_Cu,
681  In2_Cu,
682  In1_Cu,
683  F_Cu,
684 
685  F_SilkS,
686 };
687 
688 
689 /*
690  * Plot outlines of copper, for copper layer
691  */
692 void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
693  const PCB_PLOT_PARAMS& aPlotOpt )
694 {
695 
696  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
697  itemplotter.SetLayerSet( aLayerMask );
698 
699  SHAPE_POLY_SET outlines;
700 
701  for( LSEQ seq = aLayerMask.Seq( plot_seq, arrayDim( plot_seq ) ); seq; ++seq )
702  {
703  PCB_LAYER_ID layer = *seq;
704 
705  outlines.RemoveAllContours();
706  aBoard->ConvertBrdLayerToPolygonalContours( layer, outlines );
707 
708  outlines.Simplify( SHAPE_POLY_SET::PM_FAST );
709 
710  // Plot outlines
711  std::vector< wxPoint > cornerList;
712 
713  // Now we have one or more basic polygons: plot each polygon
714  for( int ii = 0; ii < outlines.OutlineCount(); ii++ )
715  {
716  for(int kk = 0; kk <= outlines.HoleCount (ii); kk++ )
717  {
718  cornerList.clear();
719  const SHAPE_LINE_CHAIN& path = (kk == 0) ? outlines.COutline( ii ) : outlines.CHole( ii, kk - 1 );
720 
721  for( int jj = 0; jj < path.PointCount(); jj++ )
722  cornerList.emplace_back( (wxPoint) path.CPoint( jj ) );
723 
724  // Ensure the polygon is closed
725  if( cornerList[0] != cornerList[cornerList.size() - 1] )
726  cornerList.push_back( cornerList[0] );
727 
728  aPlotter->PlotPoly( cornerList, NO_FILL );
729  }
730  }
731 
732  // Plot pad holes
734  {
735  int smallDrill = (aPlotOpt.GetDrillMarksType() == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE)
736  ? SMALL_DRILL : INT_MAX;
737 
738  for( auto module : aBoard->Modules() )
739  {
740  for( auto pad : module->Pads() )
741  {
742  wxSize hole = pad->GetDrillSize();
743 
744  if( hole.x == 0 || hole.y == 0 )
745  continue;
746 
747  if( hole.x == hole.y )
748  {
749  hole.x = std::min( smallDrill, hole.x );
750  aPlotter->Circle( pad->GetPosition(), hole.x, NO_FILL );
751  }
752  else
753  {
754  // Note: small drill marks have no significance when applied to slots
755  wxPoint drl_start, drl_end;
756  int width;
757  pad->GetOblongDrillGeometry( drl_start, drl_end, width );
758  aPlotter->ThickSegment( pad->GetPosition() + drl_start,
759  pad->GetPosition() + drl_end, width, SKETCH, NULL );
760  }
761  }
762  }
763  }
764 
765  // Plot vias holes
766  for( auto track : aBoard->Tracks() )
767  {
768  const VIA* via = dyn_cast<const VIA*>( track );
769 
770  if( via && via->IsOnLayer( layer ) ) // via holes can be not through holes
771  {
772  aPlotter->Circle( via->GetPosition(), via->GetDrillValue(), NO_FILL );
773  }
774  }
775  }
776 }
777 
778 
779 /* Plot a solder mask layer.
780  * Solder mask layers have a minimum thickness value and cannot be drawn like standard layers,
781  * unless the minimum thickness is 0.
782  * Currently the algo is:
783  * 1 - build all pad shapes as polygons with a size inflated by
784  * mask clearance + (min width solder mask /2)
785  * 2 - Merge shapes
786  * 3 - deflate result by (min width solder mask /2)
787  * 4 - ORing result by all pad shapes as polygons with a size inflated by
788  * mask clearance only (because deflate sometimes creates shape artifacts)
789  * 5 - draw result as polygons
790  *
791  * TODO:
792  * make this calculation only for shapes with clearance near than (min width solder mask)
793  * (using DRC algo)
794  * plot all other shapes by flashing the basing shape
795  * (shapes will be better, and calculations faster)
796  */
797 void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
798  const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness )
799 {
800  PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask;
801 
802  // We remove 1nm as we expand both sides of the shapes, so allowing for
803  // a strictly greater than or equal comparison in the shape separation (boolean add)
804  // means that we will end up with separate shapes that then are shrunk
805  int inflate = aMinThickness/2 - 1;
806 
807  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
808  itemplotter.SetLayerSet( aLayerMask );
809 
810  // Plot edge layer and graphic items.
811  // They do not have a solder Mask margin, because they graphic items
812  // on this layer (like logos), not actually areas around pads.
813  itemplotter.PlotBoardGraphicItems();
814 
815  for( auto module : aBoard->Modules() )
816  {
817  for( auto item : module->GraphicalItems() )
818  {
819  itemplotter.PlotAllTextsModule( module );
820 
821  if( item->Type() == PCB_MODULE_EDGE_T && item->GetLayer() == layer )
822  itemplotter.Plot_1_EdgeModule( (EDGE_MODULE*) item );
823  }
824  }
825 
826  // Build polygons for each pad shape. The size of the shape on solder mask should be size
827  // of pad + clearance around the pad, where clearance = solder mask clearance + extra margin.
828  // Extra margin is half the min width for solder mask, which is used to merge too-close shapes
829  // (distance < aMinThickness), and will be removed when creating the actual shapes.
830  SHAPE_POLY_SET areas; // Contains shapes to plot
831  SHAPE_POLY_SET initialPolys; // Contains exact shapes to plot
832 
833  // Plot pads
834  for( auto module : aBoard->Modules() )
835  {
836  // add shapes with exact size
837  module->TransformPadsShapesWithClearanceToPolygon( layer, initialPolys, 0 );
838  // add shapes inflated by aMinThickness/2
839  module->TransformPadsShapesWithClearanceToPolygon( layer, areas, inflate );
840  }
841 
842  // Plot vias on solder masks, if aPlotOpt.GetPlotViaOnMaskLayer() is true,
843  if( aPlotOpt.GetPlotViaOnMaskLayer() )
844  {
845  // The current layer is a solder mask, use the global mask clearance for vias
846  int via_clearance = aBoard->GetDesignSettings().m_SolderMaskMargin;
847  int via_margin = via_clearance + inflate;
848 
849  for( auto track : aBoard->Tracks() )
850  {
851  const VIA* via = dyn_cast<const VIA*>( track );
852 
853  if( !via )
854  continue;
855 
856  // vias are plotted only if they are on the corresponding external copper layer
857  LSET via_set = via->GetLayerSet();
858 
859  if( via_set[B_Cu] )
860  via_set.set( B_Mask );
861 
862  if( via_set[F_Cu] )
863  via_set.set( F_Mask );
864 
865  if( !( via_set & aLayerMask ).any() )
866  continue;
867 
868  via->TransformShapeWithClearanceToPolygon( areas, via_margin );
869  via->TransformShapeWithClearanceToPolygon( initialPolys, via_clearance );
870  }
871  }
872 
873  // Add filled zone areas.
874 #if 0 // Set to 1 if a solder mask margin must be applied to zones on solder mask
875  int zone_margin = aBoard->GetDesignSettings().m_SolderMaskMargin;
876 #else
877  int zone_margin = 0;
878 #endif
879 
880  for( ZONE_CONTAINER* zone : aBoard->Zones() )
881  {
882  if( zone->GetLayer() != layer )
883  continue;
884 
885  // Some intersecting zones, despite being on the same layer with the same net, cannot be
886  // merged due to other parameters such as fillet radius. The copper pour will end up
887  // effectively merged though, so we want to keep the corners of such intersections sharp.
888  std::set<VECTOR2I> colinearCorners;
889  zone->GetColinearCorners( aBoard, colinearCorners );
890 
891  zone->TransformOutlinesShapeWithClearanceToPolygon( areas, inflate + zone_margin, false,
892  &colinearCorners );
893  zone->TransformOutlinesShapeWithClearanceToPolygon( initialPolys, zone_margin, false,
894  &colinearCorners );
895  }
896 
897  // To avoid a lot of code, use a ZONE_CONTAINER to handle and plot polygons, because our
898  // polygons look exactly like filled areas in zones.
899  // Note, also this code is not optimized: it creates a lot of copy/duplicate data.
900  // However it is not complex, and fast enough for plot purposes (copy/convert data is only a
901  // very small calculation time for these calculations).
902  ZONE_CONTAINER zone( aBoard );
903  zone.SetMinThickness( 0 ); // trace polygons only
904  zone.SetLayer( layer );
905  int maxError = aBoard->GetDesignSettings().m_MaxError;
906  int numSegs = std::max( GetArcToSegmentCount( inflate, maxError, 360.0 ), 6 );
907 
908  areas.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST );
909  areas.Deflate( inflate, numSegs );
910 
911  // Combine the current areas to initial areas. This is mandatory because inflate/deflate
912  // transform is not perfect, and we want the initial areas perfectly kept
913  areas.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST );
915 
916  itemplotter.PlotFilledAreas( &zone, areas );
917 }
918 
919 
926 static void initializePlotter( PLOTTER *aPlotter, BOARD * aBoard,
927  PCB_PLOT_PARAMS *aPlotOpts )
928 {
929  PAGE_INFO pageA4( wxT( "A4" ) );
930  const PAGE_INFO& pageInfo = aBoard->GetPageSettings();
931  const PAGE_INFO* sheet_info;
932  double paperscale; // Page-to-paper ratio
933  wxSize paperSizeIU;
934  wxSize pageSizeIU( pageInfo.GetSizeIU() );
935  bool autocenter = false;
936 
937  // Special options: to fit the sheet to an A4 sheet replace the paper size. However there
938  // is a difference between the autoscale and the a4paper option:
939  // - Autoscale fits the board to the paper size
940  // - A4paper fits the original paper size to an A4 sheet
941  // - Both of them fit the board to an A4 sheet
942  if( aPlotOpts->GetA4Output() )
943  {
944  sheet_info = &pageA4;
945  paperSizeIU = pageA4.GetSizeIU();
946  paperscale = (double) paperSizeIU.x / pageSizeIU.x;
947  autocenter = true;
948  }
949  else
950  {
951  sheet_info = &pageInfo;
952  paperSizeIU = pageSizeIU;
953  paperscale = 1;
954 
955  // Need autocentering only if scale is not 1:1
956  autocenter = (aPlotOpts->GetScale() != 1.0);
957  }
958 
959  EDA_RECT bbox = aBoard->ComputeBoundingBox();
960  wxPoint boardCenter = bbox.Centre();
961  wxSize boardSize = bbox.GetSize();
962 
963  double compound_scale;
964 
965  // Fit to 80% of the page if asked; it could be that the board is empty, in this case
966  // regress to 1:1 scale
967  if( aPlotOpts->GetAutoScale() && boardSize.x > 0 && boardSize.y > 0 )
968  {
969  double xscale = (paperSizeIU.x * 0.8) / boardSize.x;
970  double yscale = (paperSizeIU.y * 0.8) / boardSize.y;
971 
972  compound_scale = std::min( xscale, yscale ) * paperscale;
973  }
974  else
975  compound_scale = aPlotOpts->GetScale() * paperscale;
976 
977 
978  // For the plot offset we have to keep in mind the auxiliary origin too: if autoscaling is
979  // off we check that plot option (i.e. autoscaling overrides auxiliary origin)
980  wxPoint offset( 0, 0);
981 
982  if( autocenter )
983  {
984  offset.x = KiROUND( boardCenter.x - ( paperSizeIU.x / 2.0 ) / compound_scale );
985  offset.y = KiROUND( boardCenter.y - ( paperSizeIU.y / 2.0 ) / compound_scale );
986  }
987  else
988  {
989  if( aPlotOpts->GetUseAuxOrigin() )
990  offset = aBoard->GetAuxOrigin();
991  }
992 
993  aPlotter->SetPageSettings( *sheet_info );
994 
995  aPlotter->SetViewport( offset, IU_PER_MILS/10, compound_scale, aPlotOpts->GetMirror() );
996  // Has meaning only for gerber plotter. Must be called only after SetViewport
997  aPlotter->SetGerberCoordinatesFormat( aPlotOpts->GetGerberPrecision() );
998 
999  aPlotter->SetDefaultLineWidth( aPlotOpts->GetLineWidth() );
1000  aPlotter->SetCreator( wxT( "PCBNEW" ) );
1001  aPlotter->SetColorMode( false ); // default is plot in Black and White.
1002  aPlotter->SetTextMode( aPlotOpts->GetTextMode() );
1003 
1004  aPlotter->SetColorSettings( aPlotOpts->ColorSettings() );
1005 }
1006 
1007 
1011 static void FillNegativeKnockout( PLOTTER *aPlotter, const EDA_RECT &aBbbox )
1012 {
1013  const int margin = 5 * IU_PER_MM; // Add a 5 mm margin around the board
1014  aPlotter->SetNegative( true );
1015  aPlotter->SetColor( WHITE ); // Which will be plotted as black
1016  EDA_RECT area = aBbbox;
1017  area.Inflate( margin );
1018  aPlotter->Rect( area.GetOrigin(), area.GetEnd(), FILLED_SHAPE );
1019  aPlotter->SetColor( BLACK );
1020 }
1021 
1022 
1026 static void ConfigureHPGLPenSizes( HPGL_PLOTTER *aPlotter, PCB_PLOT_PARAMS *aPlotOpts )
1027 {
1028  // Compute penDiam (the value is given in mils) in pcb units, with plot scale (if Scale is 2,
1029  // penDiam value is always m_HPGLPenDiam so apparent penDiam is actually penDiam / Scale
1030  int penDiam = KiROUND( aPlotOpts->GetHPGLPenDiameter() * IU_PER_MILS / aPlotOpts->GetScale() );
1031 
1032  // Set HPGL-specific options and start
1033  aPlotter->SetPenSpeed( aPlotOpts->GetHPGLPenSpeed() );
1034  aPlotter->SetPenNumber( aPlotOpts->GetHPGLPenNum() );
1035  aPlotter->SetPenDiameter( penDiam );
1036 }
1037 
1038 
1044 PLOTTER* StartPlotBoard( BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts, int aLayer,
1045  const wxString& aFullFileName, const wxString& aSheetDesc )
1046 {
1047  // Create the plotter driver and set the few plotter specific options
1048  PLOTTER* plotter = NULL;
1049 
1050  switch( aPlotOpts->GetFormat() )
1051  {
1052  case PLOT_FORMAT::DXF:
1053  DXF_PLOTTER* DXF_plotter;
1054  DXF_plotter = new DXF_PLOTTER();
1055  DXF_plotter->SetUnits(
1056  static_cast<DXF_PLOTTER::DXF_UNITS>( aPlotOpts->GetDXFPlotUnits() ) );
1057 
1058  plotter = DXF_plotter;
1059  break;
1060 
1061  case PLOT_FORMAT::POST:
1062  PS_PLOTTER* PS_plotter;
1063  PS_plotter = new PS_PLOTTER();
1064  PS_plotter->SetScaleAdjust( aPlotOpts->GetFineScaleAdjustX(),
1065  aPlotOpts->GetFineScaleAdjustY() );
1066  plotter = PS_plotter;
1067  break;
1068 
1069  case PLOT_FORMAT::PDF:
1070  plotter = new PDF_PLOTTER();
1071  break;
1072 
1073  case PLOT_FORMAT::HPGL:
1074  HPGL_PLOTTER* HPGL_plotter;
1075  HPGL_plotter = new HPGL_PLOTTER();
1076 
1077  // HPGL options are a little more convoluted to compute, so they get their own function
1078  ConfigureHPGLPenSizes( HPGL_plotter, aPlotOpts );
1079  plotter = HPGL_plotter;
1080  break;
1081 
1082  case PLOT_FORMAT::GERBER:
1083  plotter = new GERBER_PLOTTER();
1084  break;
1085 
1086  case PLOT_FORMAT::SVG:
1087  plotter = new SVG_PLOTTER();
1088  break;
1089 
1090  default:
1091  wxASSERT( false );
1092  return NULL;
1093  }
1094 
1095  // Compute the viewport and set the other options
1096 
1097  // page layout is not mirrored, so temporarily change mirror option for the page layout
1098  PCB_PLOT_PARAMS plotOpts = *aPlotOpts;
1099 
1100  if( plotOpts.GetPlotFrameRef() && plotOpts.GetMirror() )
1101  plotOpts.SetMirror( false );
1102 
1103  initializePlotter( plotter, aBoard, &plotOpts );
1104 
1105  if( plotter->OpenFile( aFullFileName ) )
1106  {
1107  plotter->ClearHeaderLinesList();
1108 
1109  // For the Gerber "file function" attribute, set the layer number
1110  if( plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1111  {
1112  bool useX2mode = plotOpts.GetUseGerberX2format();
1113 
1114  GERBER_PLOTTER* gbrplotter = static_cast <GERBER_PLOTTER*> ( plotter );
1115  gbrplotter->UseX2format( useX2mode );
1116  gbrplotter->UseX2NetAttributes( plotOpts.GetIncludeGerberNetlistInfo() );
1117 
1118  // Attributes can be added using X2 format or as comment (X1 format)
1119  AddGerberX2Attribute( plotter, aBoard, aLayer, not useX2mode );
1120  }
1121 
1122  plotter->StartPlot();
1123 
1124  // Plot the frame reference if requested
1125  if( aPlotOpts->GetPlotFrameRef() )
1126  {
1127  PlotWorkSheet( plotter, aBoard->GetTitleBlock(), aBoard->GetPageSettings(),
1128  1, 1, aSheetDesc, aBoard->GetFileName() );
1129 
1130  if( aPlotOpts->GetMirror() )
1131  initializePlotter( plotter, aBoard, aPlotOpts );
1132  }
1133 
1134  // When plotting a negative board: draw a black rectangle (background for plot board
1135  // in white) and switch the current color to WHITE; note the color inversion is actually
1136  // done in the driver (if supported)
1137  if( aPlotOpts->GetNegative() )
1138  {
1139  EDA_RECT bbox = aBoard->ComputeBoundingBox();
1140  FillNegativeKnockout( plotter, bbox );
1141  }
1142 
1143  return plotter;
1144  }
1145 
1146  delete plotter;
1147  return NULL;
1148 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:686
a class to handle special data (items attributes) during plot.
int m_SolderMaskMargin
Solder mask margin.
#define SMALL_DRILL
Definition: pcbplot.h:60
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
const PAGE_INFO & GetPageSettings() const
Definition: class_board.h:527
virtual void SetCreator(const wxString &aCreator)
Definition: plotter.h:180
int OutlineCount() const
Returns the number of outlines in the set
void UseX2NetAttributes(bool aEnable)
Definition: plotter.h:1297
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:497
TEXTE_PCB class definition.
bool GetPlotFrameRef() const
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
bool GetDXFPlotPolygonMode() const
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:66
static void initializePlotter(PLOTTER *aPlotter, BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts)
Set up most plot options for plotting a board (especially the viewport) Important thing: page size is...
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset union For aFastMode meaning, see function booleanOp
virtual bool StartPlot()=0
virtual void SetColor(COLOR4D color)=0
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.
const wxPoint & GetStart() const
Definition: class_track.h:111
void PlotPad(D_PAD *aPad, COLOR4D aColor, EDA_DRAW_MODE_T aPlotMode)
Plot a pad.
virtual bool OpenFile(const wxString &aFullFilename)
Open or create the plot file aFullFilename.
Definition: plotter.cpp:82
void SetNetAttribType(int aNetAttribType)
Definition: gbr_metadata.h:170
virtual void SetColorMode(bool aColorMode)
Plot in B/W or color.
Definition: plotter.h:133
void SetScaleAdjust(double scaleX, double scaleY)
Set the 'fine' scaling for the postscript engine.
Definition: plotter.h:731
virtual void SetLayerPolarity(bool aPositive)
Function SetLayerPolarity sets current Gerber layer polarity to positive or negative by writing %LPD*...
Definition: plotter.h:462
static const PCB_LAYER_ID plot_seq[]
void PlotStandardLayer(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
Function PlotStandardLayer plot copper or technical layers.
int color
Definition: DXF_plotter.cpp:61
void PlotSilkScreen(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
Function PlotSilkScreen plot silkscreen layers which have specific requirements, mainly for pads.
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aClearanceValue, int aError=ARC_HIGH_DEF, bool ignoreLineWidth=false) const override
Function TransformShapeWithClearanceToPolygon Convert the track shape to a closed polygon Used in fil...
void PlotDrillMarks()
Function PlotDrillMarks Draw a drill mark for pads and vias.
void SetMirror(bool aFlag)
virtual void SetPenDiameter(double diameter)
virtual void StartBlock(void *aData)
calling this function allows one to define the beginning of a group of drawing items,...
Definition: plotter.h:488
bool PlotAllTextsModule(MODULE *aModule)
void UseX2format(bool aEnable)
Definition: plotter.h:1296
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:512
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)
Calculates some X2 attributes, as defined in the Gerber file format specification and add them to the...
Definition: pcbplot.cpp:354
void SetUnits(DXF_UNITS aUnit)
Set the units to use for plotting the DXF file.
void SetDrillMarksType(DrillMarksType aVal)
virtual void PlotPoly(const std::vector< wxPoint > &aCornerList, FILL_T aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=NULL)=0
Function PlotPoly.
int PointCount() const
Function PointCount()
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Function Seq returns an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:377
const wxString & GetFileName() const
Definition: class_board.h:218
double GetScale() const
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
void PlotFilledAreas(ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aPolysList)
bool GetUseGerberX2format() const
virtual void SetGerberCoordinatesFormat(int aResolution, bool aUseInches=false)
Definition: plotter.h:476
Definitions for tracks, vias and zones.
This file contains miscellaneous commonly used macros and functions.
bool GetMirror() const
void PlotWorkSheet(PLOTTER *plotter, const TITLE_BLOCK &aTitleBlock, const PAGE_INFO &aPageInfo, int aSheetNumber, int aNumberOfSheets, const wxString &aSheetDesc, const wxString &aFilename, const COLOR4D aColor)
Classes used in Pcbnew, CvPcb and GerbView.
Board plot function definition file.
static void PlotSolderMaskLayer(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt, int aMinThickness)
DIMENSION class definition.
const VECTOR2I & CPoint(int aIndex) const
Function Point()
const wxPoint GetEnd() const
Definition: eda_rect.h:116
virtual void FlashPadCircle(const wxPoint &aPadPos, int aDiameter, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadCircle
void PlotLayerOutlines(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
Function PlotLayerOutlines plot copper outline of a copper layer.
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:98
#define NULL
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
MODULES & Modules()
Definition: class_board.h:229
void PlotOneBoardLayer(BOARD *aBoard, PLOTTER *aPlotter, PCB_LAYER_ID aLayer, const PCB_PLOT_PARAMS &aPlotOpt)
Function PlotOneBoardLayer main function to plot one copper or technical layer.
SHAPE_POLY_SET.
COLOR_SETTINGS * ColorSettings()
Definition: plotter.h:145
const wxPoint GetOrigin() const
Definition: eda_rect.h:114
EDA_DRAW_MODE_T
Definition: eda_text.h:59
virtual PLOT_FORMAT GetPlotterType() const =0
Returns the effective plot engine in use.
PAGE_INFO describes the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
void PlotBoardGraphicItems()
plot items like text and graphics, but not tracks and modules
COLOR4D GetColor() const
virtual void SetPenSpeed(int speed)
Definition: plotter.h:652
bool GetIncludeGerberNetlistInfo() const
void Plot_1_EdgeModule(EDGE_MODULE *aEdge)
virtual void SetTextMode(PLOT_TEXT_MODE mode)
Change the current text mode.
Definition: plotter.h:471
void Deflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
void SetSkipPlotNPTH_Pads(bool aSkip)
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
Definition: class_zone.cpp:240
PLOT_TEXT_MODE GetTextMode() const
void ConvertBrdLayerToPolygonalContours(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aOutlines)
Function ConvertBrdLayerToPolygonalContours Build a set of polygons which are the outlines of copper ...
bool GetSkipPlotNPTH_Pads() const
a few functions useful in geometry calculations.
void Simplify(POLYGON_MODE aFastMode)
Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFast...
static void ConfigureHPGLPenSizes(HPGL_PLOTTER *aPlotter, PCB_PLOT_PARAMS *aPlotOpts)
Calculate the effective size of HPGL pens and set them in the plotter object.
const wxPoint & GetAuxOrigin() const
Definition: class_board.h:335
const wxString & GetNetname() const
Function GetNetname.
bool GetAutoScale() const
PCB_PLOT_PARAMS handles plot parameters and options when plotting/printing a board.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline
const wxPoint GetPosition() const override
Definition: class_track.h:389
PLOTTER * StartPlotBoard(BOARD *aBoard, 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 SetNegative(bool aNegative)
Definition: plotter.h:125
double GetFineScaleAdjustX() const
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
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.
aperture used for connected items like tracks (not vias)
Definition: gbr_metadata.h:84
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:108
virtual void SetDefaultLineWidth(int width)=0
Set the default line width.
int GetLineWidth() const
int GetHPGLPenNum() const
void SetNetName(const wxString &aNetname)
Definition: gbr_metadata.h:180
Base plotter engine class.
Definition: plotter.h:104
COLOR4D GetColor(int aLayer) const
ZONE_CONTAINERS & Zones()
Definition: class_board.h:243
bool GetPlotViaOnMaskLayer() const
smd pads, front layer
TITLE_BLOCK & GetTitleBlock()
Definition: class_board.h:533
int GetWidth() const
Definition: class_track.h:105
Class to handle a graphic segment.
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:163
bool GetSubtractMaskFromSilk() const
#define _(s)
Definition: 3d_actions.cpp:33
SHAPE_LINE_CHAIN.
virtual void ThickSegment(const wxPoint &start, const wxPoint &end, int width, EDA_DRAW_MODE_T tracemode, void *aData)
Definition: plotter.cpp:506
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
virtual void SetPenNumber(int number)
Definition: plotter.h:657
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
double GetHPGLPenDiameter() const
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
VIATYPE GetViaType() const
Definition: class_track.h:416
#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:61
The common library.
void InflateWithLinkedHoles(int aFactor, int aCircleSegmentsCount, POLYGON_MODE aFastMode)
Performs outline inflation/deflation, using round corners.
virtual void Rect(const wxPoint &p1, const wxPoint &p2, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH)=0
void SetColorSettings(COLOR_SETTINGS *aSettings)
Definition: plotter.h:143
wxPoint Centre() const
Definition: eda_rect.h:62
void ClearHeaderLinesList()
Function ClearHeaderLinesList remove all lines from the list of free lines to print at the beginning ...
Definition: plotter.h:204
Definition: colors.h:49
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Function ComputeBoundingBox calculates the bounding box containing all board items (or board edge seg...
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
double GetFineScaleAdjustY() const
bool GetPlotPadsOnSilkLayer() const
PCB_TARGET class definition.
void SetApertureAttrib(GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB aApertAttribute)
Definition: gbr_metadata.h:160
COLOR_SETTINGS * ColorSettings() const
bool m_NotInNet
true if a pad of a footprint cannot be connected (for instance a mechanical NPTH, ot a not named pad)...
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
int getFineWidthAdj()
Definition: pcbplot.h:89
GBR_NETLIST_METADATA m_NetlistMetadata
a item to handle object attribute:
Definition: gbr_metadata.h:212
bool GetNegative() const
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Function IsOnLayer tests to see if this object is on the given layer.
Module description (excepted pads)
Definition: colors.h:45
bool GetUseAuxOrigin() const
EDGE_MODULE class definition.
DXF_PLOTTER::DXF_UNITS GetDXFPlotUnits() const
void SetMinThickness(int aMinThickness)
Definition: class_zone.h:205
DrillMarksType GetDrillMarksType() const
print info associated to a net (TO.N attribute)
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
COLOR4D getColor(LAYER_NUM aLayer)
Function getColor.
TRACKS & Tracks()
Definition: class_board.h:220
virtual void Circle(const wxPoint &pos, int diametre, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH)=0
bool GetExcludeEdgeLayer() const
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
int m_SolderMaskMinWidth
Solder mask min width.
const wxSize GetSize() const
Definition: eda_rect.h:103
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: plotter.h:147
EDA_DRAW_MODE_T GetPlotMode() const
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:40
void Unfracture(POLYGON_MODE aFastMode)
Converts a single outline slitted ("fractured") polygon into a set ouf outlines with holes.