KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
plot_board_layers.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <wx/log.h>
25#include <eda_item.h>
26#include <layer_ids.h>
27#include <lset.h>
30#include <pcb_base_frame.h>
31#include <math/util.h> // for KiROUND
32#include <board.h>
33#include <footprint.h>
34#include <pcb_track.h>
35#include <pad.h>
36#include <zone.h>
37#include <pcb_shape.h>
38#include <pcb_target.h>
39#include <pcb_dimension.h>
40#include <pcbplot.h>
45#include <pcb_painter.h>
46#include <gbr_metadata.h>
47#include <advanced_config.h>
48
49
50void GenerateLayerPoly( SHAPE_POLY_SET* aResult, BOARD *aBoard, PCB_LAYER_ID aLayer,
51 bool aPlotFPText, bool aPlotReferences, bool aPlotValues );
52
53
54void PlotLayer( BOARD* aBoard, PLOTTER* aPlotter, const LSET& layerMask,
55 const PCB_PLOT_PARAMS& plotOpts )
56{
57 // PlotLayerOutlines() is designed only for DXF plotters.
58 if( plotOpts.GetFormat() == PLOT_FORMAT::DXF && plotOpts.GetDXFPlotPolygonMode() )
59 PlotLayerOutlines( aBoard, aPlotter, layerMask, plotOpts );
60 else
61 PlotStandardLayer( aBoard, aPlotter, layerMask, plotOpts );
62};
63
64
65void PlotPolySet( BOARD* aBoard, PLOTTER* aPlotter, const PCB_PLOT_PARAMS& aPlotOpt,
66 SHAPE_POLY_SET* aPolySet, PCB_LAYER_ID aLayer )
67{
68 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
69 LSET layers = { aLayer };
70
71 itemplotter.SetLayerSet( layers );
72
73 // To avoid a lot of code, use a ZONE to handle and plot polygons, because our polygons look
74 // exactly like filled areas in zones.
75 // Note, also this code is not optimized: it creates a lot of copy/duplicate data.
76 // However it is not complex, and fast enough for plot purposes (copy/convert data is only a
77 // very small calculation time for these calculations).
78 ZONE zone( aBoard );
79 zone.SetMinThickness( 0 );
80 zone.SetLayer( aLayer );
81
82 aPolySet->Fracture();
83 itemplotter.PlotZone( &zone, aLayer, *aPolySet );
84}
85
86
93void PlotSolderMaskLayer( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMask,
94 const PCB_PLOT_PARAMS& aPlotOpt )
95{
96 if( aBoard->GetDesignSettings().m_SolderMaskMinWidth == 0 )
97 {
98 PlotLayer( aBoard, aPlotter, aLayerMask, aPlotOpt );
99 return;
100 }
101
102 SHAPE_POLY_SET solderMask;
103 PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask;
104
105 GenerateLayerPoly( &solderMask, aBoard, layer, aPlotOpt.GetPlotFPText(),
106 aPlotOpt.GetPlotReference(), aPlotOpt.GetPlotValue() );
107
108 PlotPolySet( aBoard, aPlotter, aPlotOpt, &solderMask, layer );
109}
110
111
112void PlotClippedSilkLayer( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMask,
113 const PCB_PLOT_PARAMS& aPlotOpt )
114{
115 SHAPE_POLY_SET silkscreen, solderMask;
116 PCB_LAYER_ID silkLayer = aLayerMask[F_SilkS] ? F_SilkS : B_SilkS;
117 PCB_LAYER_ID maskLayer = aLayerMask[F_SilkS] ? F_Mask : B_Mask;
118
119 GenerateLayerPoly( &silkscreen, aBoard, silkLayer, aPlotOpt.GetPlotFPText(),
120 aPlotOpt.GetPlotReference(), aPlotOpt.GetPlotValue() );
121 GenerateLayerPoly( &solderMask, aBoard, maskLayer, aPlotOpt.GetPlotFPText(),
122 aPlotOpt.GetPlotReference(), aPlotOpt.GetPlotValue() );
123
124 silkscreen.BooleanSubtract( solderMask );
125 PlotPolySet( aBoard, aPlotter, aPlotOpt, &silkscreen, silkLayer );
126}
127
128
129void PlotBoardLayers( BOARD* aBoard, PLOTTER* aPlotter, const LSEQ& aLayers,
130 const PCB_PLOT_PARAMS& aPlotOptions )
131{
132 if( !aBoard || !aPlotter || aLayers.empty() )
133 return;
134
135 // if a drill mark must be plotted,it must be plotted as a filled
136 // white shape *after* all other shapes are plotted, provided that
137 // the other shapes are not copper layers
138 int copperLayers = 0;
139 int nonCopperLayers = 0;
140
141 for( PCB_LAYER_ID layer : aLayers )
142 {
143 if( IsCopperLayer( layer ) )
144 copperLayers++;
145 else
146 nonCopperLayers++;
147 }
148
149 bool plot_mark = ( aPlotOptions.GetDrillMarksType() != DRILL_MARKS::NO_DRILL_SHAPE
150 && copperLayers > 0 && nonCopperLayers > 0 );
151
152 for( PCB_LAYER_ID layer : aLayers )
153 PlotOneBoardLayer( aBoard, aPlotter, layer, aPlotOptions, layer == aLayers[0] );
154
155 if( plot_mark )
156 {
157 aPlotter->SetColor( WHITE );
158 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOptions );
159 itemplotter.PlotDrillMarks();
160 }
161}
162
163
164void PlotInteractiveLayer( BOARD* aBoard, PLOTTER* aPlotter, const PCB_PLOT_PARAMS& aPlotOpt )
165{
166 for( const FOOTPRINT* fp : aBoard->Footprints() )
167 {
168 if( fp->GetLayer() == F_Cu && !aPlotOpt.m_PDFFrontFPPropertyPopups )
169 continue;
170
171 if( fp->GetLayer() == B_Cu && !aPlotOpt.m_PDFBackFPPropertyPopups )
172 continue;
173
174 std::vector<wxString> properties;
175
176 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
177 _( "Reference designator" ),
178 fp->Reference().GetShownText( false ) ) );
179
180 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
181 _( "Value" ),
182 fp->Value().GetShownText( false ) ) );
183
184 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
185 _( "Footprint" ),
186 fp->GetFPID().GetUniStringLibItemName() ) );
187
188 for( const PCB_FIELD* field : fp->GetFields() )
189 {
190 if( field->IsReference() || field->IsValue() )
191 continue;
192
193 if( field->GetText().IsEmpty() )
194 continue;
195
196 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
197 field->GetName(),
198 field->GetText() ) );
199 }
200
201 // These 2 properties are not very useful in a plot file (like a PDF)
202#if 0
203 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Library Description" ),
204 fp->GetLibDescription() ) );
205
206 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Keywords" ),
207 fp->GetKeywords() ) );
208#endif
209 // Draw items are plotted with a position offset. So we need to move
210 // our boxes (which are not plotted) by the same offset.
211 VECTOR2I offset = -aPlotter->GetPlotOffsetUserUnits();
212
213 // Use a footprint bbox without texts to create the hyperlink area
214 BOX2I bbox = fp->GetBoundingBox( false );
215 bbox.Move( offset );
216 aPlotter->HyperlinkMenu( bbox, properties );
217
218 // Use a footprint bbox with visible texts only to create the bookmark area
219 // which is the area to zoom on ft selection
220 // However the bbox need to be inflated for a better look.
221 bbox = fp->GetBoundingBox( true );
222 bbox.Move( offset );
223 bbox.Inflate( bbox.GetWidth() /2, bbox.GetHeight() /2 );
224 aPlotter->Bookmark( bbox, fp->GetReference(), _( "Footprints" ) );
225 }
226}
227
228
229void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
230 const PCB_PLOT_PARAMS& aPlotOpt, bool isPrimaryLayer )
231{
232 PCB_PLOT_PARAMS plotOpt = aPlotOpt;
233
234 // Set a default color and the text mode for this layer
235 aPlotter->SetColor( BLACK );
236 aPlotter->SetTextMode( aPlotOpt.GetTextMode() );
237
238 // Specify that the contents of the "Edges Pcb" layer are to be plotted in addition to the
239 // contents of the currently specified layer.
240 LSET layer_mask( { aLayer } );
241
242 if( IsCopperLayer( aLayer ) )
243 {
244 // Skip NPTH pads on copper layers ( only if hole size == pad size ):
245 // Drill mark will be plotted if drill mark is SMALL_DRILL_SHAPE or FULL_DRILL_SHAPE
246 if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
247 plotOpt.SetDXFPlotPolygonMode( true );
248 else
249 plotOpt.SetSkipPlotNPTH_Pads( true );
250
251 PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
252 }
253 else
254 {
255 switch( aLayer )
256 {
257 case B_Mask:
258 case F_Mask:
259 // Disable plot pad holes
261
262 // Use outline mode for DXF
263 plotOpt.SetDXFPlotPolygonMode( true );
264
265 // Plot solder mask:
266 PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt );
267
268 break;
269
270 case B_Adhes:
271 case F_Adhes:
272 case B_Paste:
273 case F_Paste:
274 // Disable plot pad holes
276
277 // Use outline mode for DXF
278 plotOpt.SetDXFPlotPolygonMode( true );
279
280 PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
281
282 break;
283
284 case F_SilkS:
285 case B_SilkS:
286 if( plotOpt.GetSubtractMaskFromSilk() )
287 {
288 if( aPlotter->GetPlotterType() == PLOT_FORMAT::GERBER && isPrimaryLayer )
289 {
290 // Use old-school, positive/negative mask plotting which preserves utilization
291 // of Gerber aperture masks. This method can only be used when the given silk
292 // layer is the primary layer as the negative mask will also knockout any other
293 // (non-silk) layers that were plotted before the silk layer.
294
295 PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
296
297 // Create the mask to subtract by creating a negative layer polarity
298 aPlotter->SetLayerPolarity( false );
299
300 // Disable plot pad holes
302
303 // Plot the mask
304 layer_mask = ( aLayer == F_SilkS ) ? LSET( { F_Mask } ) : LSET( { B_Mask } );
305 PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt );
306
307 // Disable the negative polarity
308 aPlotter->SetLayerPolarity( true );
309 }
310 else
311 {
312 PlotClippedSilkLayer( aBoard, aPlotter, layer_mask, plotOpt );
313 }
314
315 break;
316 }
317
318 PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
319 break;
320
321 case Dwgs_User:
322 case Cmts_User:
323 case Eco1_User:
324 case Eco2_User:
325 case Edge_Cuts:
326 case Margin:
327 case F_CrtYd:
328 case B_CrtYd:
329 case F_Fab:
330 case B_Fab:
331 default:
332 PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
333 break;
334 }
335 }
336}
337
338
342void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMask,
343 const PCB_PLOT_PARAMS& aPlotOpt )
344{
345 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
346 int maxError = aBoard->GetDesignSettings().m_MaxError;
347
348 itemplotter.SetLayerSet( aLayerMask );
349
350 OUTLINE_MODE plotMode = aPlotOpt.GetPlotMode();
351 bool onCopperLayer = ( LSET::AllCuMask() & aLayerMask ).any();
352 bool onSolderMaskLayer = ( LSET( { F_Mask, B_Mask } ) & aLayerMask ).any();
353 bool onSolderPasteLayer = ( LSET( { F_Paste, B_Paste } ) & aLayerMask ).any();
354 bool onFrontFab = ( LSET( { F_Fab } ) & aLayerMask ).any();
355 bool onBackFab = ( LSET( { B_Fab } ) & aLayerMask ).any();
356 bool sketchPads = ( onFrontFab || onBackFab ) && aPlotOpt.GetSketchPadsOnFabLayers();
357
358 // Plot edge layer and graphic items
359 for( const BOARD_ITEM* item : aBoard->Drawings() )
360 itemplotter.PlotBoardGraphicItem( item );
361
362 // Draw footprint texts:
363 for( const FOOTPRINT* footprint : aBoard->Footprints() )
364 itemplotter.PlotFootprintTextItems( footprint );
365
366 // Draw footprint other graphic items:
367 for( const FOOTPRINT* footprint : aBoard->Footprints() )
368 itemplotter.PlotFootprintGraphicItems( footprint );
369
370 // Plot footprint pads
371 for( FOOTPRINT* footprint : aBoard->Footprints() )
372 {
373 aPlotter->StartBlock( nullptr );
374
375 for( PAD* pad : footprint->Pads() )
376 {
377 OUTLINE_MODE padPlotMode = plotMode;
378
379 if( !( pad->GetLayerSet() & aLayerMask ).any() )
380 {
381 if( sketchPads &&
382 ( ( onFrontFab && pad->GetLayerSet().Contains( F_Cu ) ) ||
383 ( onBackFab && pad->GetLayerSet().Contains( B_Cu ) ) ) )
384 {
385 padPlotMode = SKETCH;
386 }
387 else
388 {
389 continue;
390 }
391 }
392
393 if( onCopperLayer && !pad->IsOnCopperLayer() )
394 continue;
395
397 if( onCopperLayer && !pad->FlashLayer( aLayerMask ) )
398 continue;
399
400 // TODO(JE) padstacks - different behavior for single layer or multilayer
401
403
404 // If we're plotting a single layer, the color for that layer can be used directly.
405 if( aLayerMask.count() == 1 )
406 {
407 color = aPlotOpt.ColorSettings()->GetColor( aLayerMask.Seq()[0] );
408 }
409 else
410 {
411 if( ( pad->GetLayerSet() & aLayerMask )[B_Cu] )
412 color = aPlotOpt.ColorSettings()->GetColor( B_Cu );
413
414 if( ( pad->GetLayerSet() & aLayerMask )[F_Cu] )
415 color = color.LegacyMix( aPlotOpt.ColorSettings()->GetColor( F_Cu ) );
416
417 if( sketchPads && aLayerMask[F_Fab] )
418 color = aPlotOpt.ColorSettings()->GetColor( F_Fab );
419 else if( sketchPads && aLayerMask[B_Fab] )
420 color = aPlotOpt.ColorSettings()->GetColor( B_Fab );
421 }
422
423 if( sketchPads &&
424 ( ( onFrontFab && pad->GetLayerSet().Contains( F_Cu ) ) ||
425 ( onBackFab && pad->GetLayerSet().Contains( B_Cu ) ) ) )
426 {
427 if( aPlotOpt.GetPlotPadNumbers() )
428 itemplotter.PlotPadNumber( pad, color );
429 }
430
431 auto plotPadLayer =
432 [&]( PCB_LAYER_ID aLayer )
433 {
434 VECTOR2I margin;
435 int width_adj = 0;
436
437 if( onCopperLayer )
438 width_adj = itemplotter.getFineWidthAdj();
439
440 if( onSolderMaskLayer )
441 margin.x = margin.y = pad->GetSolderMaskExpansion( aLayer );
442
443 if( onSolderPasteLayer )
444 margin = pad->GetSolderPasteMargin( aLayer );
445
446 // not all shapes can have a different margin for x and y axis
447 // in fact only oval and rect shapes can have different values.
448 // Round shape have always the same x,y margin
449 // so define a unique value for other shapes that do not support different values
450 int mask_clearance = margin.x;
451
452 // Now offset the pad size by margin + width_adj
453 VECTOR2I padPlotsSize =
454 pad->GetSize( aLayer ) + margin * 2 + VECTOR2I( width_adj, width_adj );
455
456 // Store these parameters that can be modified to plot inflated/deflated pads shape
457 PAD_SHAPE padShape = pad->GetShape( aLayer );
458 VECTOR2I padSize = pad->GetSize( aLayer );
459 VECTOR2I padDelta = pad->GetDelta( aLayer ); // has meaning only for trapezoidal pads
460 // CornerRadius and CornerRadiusRatio can be modified
461 // the radius is built from the ratio, so saving/restoring the ratio is enough
462 double padCornerRadiusRatio = pad->GetRoundRectRadiusRatio( aLayer );
463
464 // Don't draw a 0 sized pad.
465 // Note: a custom pad can have its pad anchor with size = 0
466 if( padShape != PAD_SHAPE::CUSTOM
467 && ( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 ) )
468 {
469 return;
470 }
471
472 switch( padShape )
473 {
475 case PAD_SHAPE::OVAL:
476 pad->SetSize( aLayer, padPlotsSize );
477
478 if( aPlotOpt.GetSkipPlotNPTH_Pads() &&
480 ( pad->GetSize(aLayer ) == pad->GetDrillSize() ) &&
481 ( pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
482 {
483 break;
484 }
485
486 itemplotter.PlotPad( pad, aLayer, color, padPlotMode );
487 break;
488
490 pad->SetSize( aLayer, padPlotsSize );
491
492 if( mask_clearance > 0 )
493 {
494 pad->SetShape( aLayer, PAD_SHAPE::ROUNDRECT );
495 pad->SetRoundRectCornerRadius( aLayer, mask_clearance );
496 }
497
498 itemplotter.PlotPad( pad, aLayer, color, padPlotMode );
499 break;
500
502 // inflate/deflate a trapezoid is a bit complex.
503 // so if the margin is not null, build a similar polygonal pad shape,
504 // and inflate/deflate the polygonal shape
505 // because inflating/deflating using different values for y and y
506 // we are using only margin.x as inflate/deflate value
507 if( mask_clearance == 0 )
508 {
509 itemplotter.PlotPad( pad, aLayer, color, padPlotMode );
510 }
511 else
512 {
513 PAD dummy( *pad );
514 dummy.SetAnchorPadShape( aLayer, PAD_SHAPE::CIRCLE );
515 dummy.SetShape( aLayer, PAD_SHAPE::CUSTOM );
516 SHAPE_POLY_SET outline;
517 outline.NewOutline();
518 int dx = padSize.x / 2;
519 int dy = padSize.y / 2;
520 int ddx = padDelta.x / 2;
521 int ddy = padDelta.y / 2;
522
523 outline.Append( -dx - ddy, dy + ddx );
524 outline.Append( dx + ddy, dy - ddx );
525 outline.Append( dx - ddy, -dy + ddx );
526 outline.Append( -dx + ddy, -dy - ddx );
527
528 // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
529 // which can create bad shapes if margin.x is < 0
530 outline.InflateWithLinkedHoles( mask_clearance,
532 dummy.DeletePrimitivesList();
533 dummy.AddPrimitivePoly( aLayer, outline, 0, true );
534
535 // Be sure the anchor pad is not bigger than the deflated shape because this
536 // anchor will be added to the pad shape when plotting the pad. So now the
537 // polygonal shape is built, we can clamp the anchor size
538 dummy.SetSize( aLayer, VECTOR2I( 0, 0 ) );
539
540 itemplotter.PlotPad( &dummy, aLayer, color, padPlotMode );
541 }
542
543 break;
544
546 {
547 // rounding is stored as a percent, but we have to update this ratio
548 // to force recalculation of other values after size changing (we do not
549 // really change the rounding percent value)
550 double radius_ratio = pad->GetRoundRectRadiusRatio( aLayer );
551 pad->SetSize( aLayer, padPlotsSize );
552 pad->SetRoundRectRadiusRatio( aLayer, radius_ratio );
553
554 itemplotter.PlotPad( pad, aLayer, color, padPlotMode );
555 break;
556 }
557
559 if( mask_clearance == 0 )
560 {
561 // the size can be slightly inflated by width_adj (PS/PDF only)
562 pad->SetSize( aLayer, padPlotsSize );
563 itemplotter.PlotPad( pad, aLayer, color, padPlotMode );
564 }
565 else
566 {
567 // Due to the polygonal shape of a CHAMFERED_RECT pad, the best way is to
568 // convert the pad shape to a full polygon, inflate/deflate the polygon
569 // and use a dummy CUSTOM pad to plot the final shape.
570 PAD dummy( *pad );
571 // Build the dummy pad outline with coordinates relative to the pad position
572 // pad offset and orientation 0. The actual pos, offset and rotation will be
573 // taken in account later by the plot function
574 dummy.SetPosition( VECTOR2I( 0, 0 ) );
575 dummy.SetOffset( aLayer, VECTOR2I( 0, 0 ) );
576 dummy.SetOrientation( ANGLE_0 );
577 SHAPE_POLY_SET outline;
578 dummy.TransformShapeToPolygon( outline, UNDEFINED_LAYER, 0, maxError,
579 ERROR_INSIDE );
580 outline.InflateWithLinkedHoles( mask_clearance,
582
583 // Initialize the dummy pad shape:
584 dummy.SetAnchorPadShape( aLayer, PAD_SHAPE::CIRCLE );
585 dummy.SetShape( aLayer, PAD_SHAPE::CUSTOM );
586 dummy.DeletePrimitivesList();
587 dummy.AddPrimitivePoly( aLayer, outline, 0, true );
588
589 // Be sure the anchor pad is not bigger than the deflated shape because this
590 // anchor will be added to the pad shape when plotting the pad.
591 // So we set the anchor size to 0
592 dummy.SetSize( aLayer, VECTOR2I( 0, 0 ) );
593 // Restore pad position and offset
594 dummy.SetPosition( pad->GetPosition() );
595 dummy.SetOffset( aLayer, pad->GetOffset( aLayer ) );
596 dummy.SetOrientation( pad->GetOrientation() );
597
598 itemplotter.PlotPad( &dummy, aLayer, color, padPlotMode );
599 }
600
601 break;
602
604 {
605 // inflate/deflate a custom shape is a bit complex.
606 // so build a similar pad shape, and inflate/deflate the polygonal shape
607 PAD dummy( *pad );
608 dummy.SetParentGroup( nullptr );
609
610 SHAPE_POLY_SET shape;
611 pad->MergePrimitivesAsPolygon( aLayer, &shape );
612
613 // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
614 // which can create bad shapes if margin.x is < 0
615 shape.InflateWithLinkedHoles( mask_clearance,
617 dummy.DeletePrimitivesList();
618 dummy.AddPrimitivePoly( aLayer, shape, 0, true );
619
620 // Be sure the anchor pad is not bigger than the deflated shape because this
621 // anchor will be added to the pad shape when plotting the pad. So now the
622 // polygonal shape is built, we can clamp the anchor size
623 if( mask_clearance < 0 ) // we expect margin.x = margin.y for custom pads
624 dummy.SetSize( aLayer, VECTOR2I( std::max( 0, padPlotsSize.x ),
625 std::max( 0, padPlotsSize.y ) ) );
626
627 itemplotter.PlotPad( &dummy, aLayer, color, padPlotMode );
628 break;
629 }
630 }
631
632 // Restore the pad parameters modified by the plot code
633 pad->SetSize( aLayer, padSize );
634 pad->SetDelta( aLayer, padDelta );
635 pad->SetShape( aLayer, padShape );
636 pad->SetRoundRectRadiusRatio( aLayer, padCornerRadiusRatio );
637 };
638
639 for( PCB_LAYER_ID layer : aLayerMask.SeqStackupForPlotting() )
640 plotPadLayer( layer );
641 }
642
643 if( footprint->IsDNP()
644 && !itemplotter.GetHideDNPFPsOnFabLayers()
645 && itemplotter.GetCrossoutDNPFPsOnFabLayers()
646 && ( ( onFrontFab && footprint->GetLayer() == F_Cu ) ||
647 ( onBackFab && footprint->GetLayer() == B_Cu ) ) )
648 {
649 BOX2I rect = footprint->GetBoundingHull().BBox();
650 int width = aBoard->GetDesignSettings().m_LineThickness[ LAYER_CLASS_FAB ];
651
652 aPlotter->ThickSegment( rect.GetOrigin(), rect.GetEnd(), width, FILLED, nullptr );
653 aPlotter->ThickSegment( VECTOR2I( rect.GetLeft(), rect.GetBottom() ),
654 VECTOR2I( rect.GetRight(), rect.GetTop() ),
655 width, FILLED, nullptr );
656 }
657
658 aPlotter->EndBlock( nullptr );
659 }
660
661 // Plot vias on copper layers, and if aPlotOpt.GetPlotViaOnMaskLayer() is true,
662
663 GBR_METADATA gbr_metadata;
664
665 if( onCopperLayer )
666 {
669 }
670
671 aPlotter->StartBlock( nullptr );
672
673 for( const PCB_TRACK* track : aBoard->Tracks() )
674 {
675 if( track->Type() != PCB_VIA_T )
676 continue;
677
678 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
679
680 // vias are not plotted if not on selected layer
681 LSET via_mask_layer = via->GetLayerSet();
682
683 if( !( via_mask_layer & aLayerMask ).any() )
684 continue;
685
686 int via_margin = 0;
687 double width_adj = 0;
688
689 // TODO(JE) padstacks - separate top/bottom margin
690 if( onSolderMaskLayer )
691 via_margin = via->GetSolderMaskExpansion();
692
693 if( ( aLayerMask & LSET::AllCuMask() ).any() )
694 width_adj = itemplotter.getFineWidthAdj();
695
697 if( onCopperLayer && !via->FlashLayer( aLayerMask ) )
698 continue;
699
700 int diameter = 0;
701
702 for( PCB_LAYER_ID layer : aLayerMask.Seq() )
703 diameter = std::max( diameter, via->GetWidth( layer ) );
704
705 diameter += 2 * via_margin + width_adj;
706
707 // Don't draw a null size item :
708 if( diameter <= 0 )
709 continue;
710
711 // Some vias can be not connected (no net).
712 // Set the m_NotInNet for these vias to force a empty net name in gerber file
713 gbr_metadata.m_NetlistMetadata.m_NotInNet = via->GetNetname().IsEmpty();
714
715 gbr_metadata.SetNetName( via->GetNetname() );
716
718
719 // If we're plotting a single layer, the color for that layer can be used directly.
720 if( aLayerMask.count() == 1 )
721 {
722 color = aPlotOpt.ColorSettings()->GetColor( aLayerMask.Seq()[0] );
723 }
724 else
725 {
726 color = aPlotOpt.ColorSettings()->GetColor(
727 LAYER_VIAS + static_cast<int>( via->GetViaType() ) );
728 }
729
730 // Change UNSPECIFIED or WHITE to LIGHTGRAY because the white items are not seen on a
731 // white paper or screen
734
735 aPlotter->SetColor( color );
736 aPlotter->FlashPadCircle( via->GetStart(), diameter, plotMode, &gbr_metadata );
737 }
738
739 aPlotter->EndBlock( nullptr );
740 aPlotter->StartBlock( nullptr );
741
742 if( onCopperLayer )
743 {
746 }
747 else
748 {
749 // Reset attributes if non-copper (soldermask) layer
752 }
753
754 // Plot tracks (not vias) :
755 for( const PCB_TRACK* track : aBoard->Tracks() )
756 {
757 if( track->Type() == PCB_VIA_T )
758 continue;
759
760 if( !( aLayerMask & track->GetLayerSet() ).any() )
761 continue;
762
763 // Some track segments can be not connected (no net).
764 // Set the m_NotInNet for these segments to force a empty net name in gerber file
765 gbr_metadata.m_NetlistMetadata.m_NotInNet = track->GetNetname().IsEmpty();
766
767 gbr_metadata.SetNetName( track->GetNetname() );
768
769 int margin = 0;
770
771 if( onSolderMaskLayer )
772 margin = track->GetSolderMaskExpansion();
773
774 int width = track->GetWidth() + 2 * margin + itemplotter.getFineWidthAdj();
775
776 aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) );
777
778 if( track->Type() == PCB_ARC_T )
779 {
780 const PCB_ARC* arc = static_cast<const PCB_ARC*>( track );
781
782 // Too small arcs cannot be really handled: arc center (and arc radius)
783 // cannot be safely computed
784 if( !arc->IsDegenerated( 10 /* in IU */ ) )
785 {
786 aPlotter->ThickArc( arc->GetCenter(), arc->GetArcAngleStart(), arc->GetAngle(),
787 arc->GetRadius(), width, plotMode, &gbr_metadata );
788 }
789 else
790 {
791 // Approximate this very small arc by a segment.
792 aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode,
793 &gbr_metadata );
794 }
795 }
796 else
797 {
798 aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode,
799 &gbr_metadata );
800 }
801 }
802
803 aPlotter->EndBlock( nullptr );
804
805 // Plot filled ares
806 aPlotter->StartBlock( nullptr );
807
808 NETINFO_ITEM nonet( aBoard );
809
810 for( const ZONE* zone : aBoard->Zones() )
811 {
812 if( zone->GetIsRuleArea() )
813 continue;
814
815 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
816 {
817 if( !aLayerMask[layer] )
818 continue;
819
820 SHAPE_POLY_SET mainArea = zone->GetFilledPolysList( layer )->CloneDropTriangulation();
821 SHAPE_POLY_SET islands;
822
823 for( int i = mainArea.OutlineCount() - 1; i >= 0; i-- )
824 {
825 if( zone->IsIsland( layer, i ) )
826 {
827 islands.AddOutline( mainArea.CPolygon( i )[0] );
828 mainArea.DeletePolygon( i );
829 }
830 }
831
832 itemplotter.PlotZone( zone, layer, mainArea );
833
834 if( !islands.IsEmpty() )
835 {
836 ZONE dummy( *zone );
837 dummy.SetNet( &nonet );
838 itemplotter.PlotZone( &dummy, layer, islands );
839 }
840 }
841 }
842
843 aPlotter->EndBlock( nullptr );
844
845 // Adding drill marks, if required and if the plotter is able to plot them:
847 itemplotter.PlotDrillMarks();
848}
849
850
854void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMask,
855 const PCB_PLOT_PARAMS& aPlotOpt )
856{
857 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
858 itemplotter.SetLayerSet( aLayerMask );
859
860 SHAPE_POLY_SET outlines;
861
862 for( PCB_LAYER_ID layer : aLayerMask.Seq( aLayerMask.SeqStackupForPlotting() ) )
863 {
864 outlines.RemoveAllContours();
865 aBoard->ConvertBrdLayerToPolygonalContours( layer, outlines );
866
867 outlines.Simplify();
868
869 // Plot outlines
870 std::vector<VECTOR2I> cornerList;
871
872 // Now we have one or more basic polygons: plot each polygon
873 for( int ii = 0; ii < outlines.OutlineCount(); ii++ )
874 {
875 for( int kk = 0; kk <= outlines.HoleCount(ii); kk++ )
876 {
877 cornerList.clear();
878 const SHAPE_LINE_CHAIN& path = ( kk == 0 ) ? outlines.COutline( ii )
879 : outlines.CHole( ii, kk - 1 );
880
881 aPlotter->PlotPoly( path, FILL_T::NO_FILL );
882 }
883 }
884
885 // Plot pad holes
887 {
888 int smallDrill = ( aPlotOpt.GetDrillMarksType() == DRILL_MARKS::SMALL_DRILL_SHAPE )
890 : INT_MAX;
891
892 for( FOOTPRINT* footprint : aBoard->Footprints() )
893 {
894 for( PAD* pad : footprint->Pads() )
895 {
896 if( pad->HasHole() )
897 {
898 std::shared_ptr<SHAPE_SEGMENT> slot = pad->GetEffectiveHoleShape();
899
900 if( slot->GetSeg().A == slot->GetSeg().B ) // circular hole
901 {
902 int drill = std::min( smallDrill, slot->GetWidth() );
903 aPlotter->Circle( pad->GetPosition(), drill, FILL_T::NO_FILL );
904 }
905 else
906 {
907 // Note: small drill marks have no significance when applied to slots
908 aPlotter->ThickSegment( slot->GetSeg().A, slot->GetSeg().B,
909 slot->GetWidth(), SKETCH, nullptr );
910 }
911 }
912 }
913 }
914 }
915
916 // Plot vias holes
917 for( PCB_TRACK* track : aBoard->Tracks() )
918 {
919 if( track->Type() != PCB_VIA_T )
920 continue;
921
922 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
923
924 if( via->GetLayerSet().Contains( layer ) ) // via holes can be not through holes
925 aPlotter->Circle( via->GetPosition(), via->GetDrillValue(), FILL_T::NO_FILL );
926 }
927 }
928}
929
930
934void GenerateLayerPoly( SHAPE_POLY_SET* aResult, BOARD *aBoard, PCB_LAYER_ID aLayer,
935 bool aPlotFPText, bool aPlotReferences, bool aPlotValues )
936{
937 int maxError = aBoard->GetDesignSettings().m_MaxError;
938 SHAPE_POLY_SET buffer;
939 SHAPE_POLY_SET* boardOutline = nullptr;
940 int inflate = 0;
941
942 if( aBoard->GetBoardPolygonOutlines( buffer ) )
943 boardOutline = &buffer;
944
945 if( aLayer == F_Mask || aLayer == B_Mask )
946 {
947 // We remove 1nm as we expand both sides of the shapes, so allowing for a strictly greater
948 // than or equal comparison in the shape separation (boolean add)
949 inflate = aBoard->GetDesignSettings().m_SolderMaskMinWidth / 2 - 1;
950 }
951
952 // Build polygons for each pad shape. The size of the shape on solder mask should be size
953 // of pad + clearance around the pad, where clearance = solder mask clearance + extra margin.
954 // Extra margin is half the min width for solder mask, which is used to merge too-close shapes
955 // (distance < SolderMaskMinWidth).
956
957 // Will contain exact shapes of all items on solder mask. We add this back in at the end just
958 // to make sure that any artefacts introduced by the inflate/deflate don't remove parts of the
959 // individual shapes.
960 SHAPE_POLY_SET exactPolys;
961
962 auto handleFPTextItem =
963 [&]( const PCB_TEXT& aText )
964 {
965 if( !aPlotFPText )
966 return;
967
968 if( aText.GetText() == wxT( "${REFERENCE}" ) && !aPlotReferences )
969 return;
970
971 if( aText.GetText() == wxT( "${VALUE}" ) && !aPlotValues )
972 return;
973
974 if( inflate != 0 )
975 aText.TransformTextToPolySet( exactPolys, 0, maxError, ERROR_OUTSIDE );
976
977 aText.TransformTextToPolySet( *aResult, inflate, maxError, ERROR_OUTSIDE );
978 };
979
980 // Generate polygons with arcs inside the shape or exact shape to minimize shape changes
981 // created by arc to segment size correction.
983 {
984 // Plot footprint pads and graphics
985 for( const FOOTPRINT* footprint : aBoard->Footprints() )
986 {
987 if( inflate != 0 )
988 footprint->TransformPadsToPolySet( exactPolys, aLayer, 0, maxError, ERROR_OUTSIDE );
989
990 footprint->TransformPadsToPolySet( *aResult, aLayer, inflate, maxError, ERROR_OUTSIDE );
991
992 for( const PCB_FIELD* field : footprint->GetFields() )
993 {
994 if( field->IsReference() && !aPlotReferences )
995 continue;
996
997 if( field->IsValue() && !aPlotValues )
998 continue;
999
1000 if( field->IsVisible() && field->IsOnLayer( aLayer ) )
1001 handleFPTextItem( static_cast<const PCB_TEXT&>( *field ) );
1002 }
1003
1004 for( const BOARD_ITEM* item : footprint->GraphicalItems() )
1005 {
1006 if( item->IsOnLayer( aLayer ) )
1007 {
1008 if( item->Type() == PCB_TEXT_T )
1009 {
1010 handleFPTextItem( static_cast<const PCB_TEXT&>( *item ) );
1011 }
1012 else
1013 {
1014 if( inflate != 0 )
1015 item->TransformShapeToPolySet( exactPolys, aLayer, 0, maxError, ERROR_OUTSIDE );
1016
1017 item->TransformShapeToPolySet( *aResult, aLayer, inflate, maxError, ERROR_OUTSIDE );
1018 }
1019 }
1020 }
1021 }
1022
1023 // Plot untented vias and tracks
1024 for( const PCB_TRACK* track : aBoard->Tracks() )
1025 {
1026 // Note: IsOnLayer() checks relevant mask layers of untented vias and tracks
1027 if( !track->IsOnLayer( aLayer ) )
1028 continue;
1029
1030 int clearance = track->GetSolderMaskExpansion();
1031
1032 if( inflate != 0 )
1033 track->TransformShapeToPolygon( exactPolys, aLayer, clearance, maxError, ERROR_OUTSIDE );
1034
1035 track->TransformShapeToPolygon( *aResult, aLayer, clearance + inflate, maxError, ERROR_OUTSIDE );
1036 }
1037
1038 for( const BOARD_ITEM* item : aBoard->Drawings() )
1039 {
1040 if( item->IsOnLayer( aLayer ) )
1041 {
1042 if( item->Type() == PCB_TEXT_T )
1043 {
1044 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( item );
1045
1046 if( inflate != 0 )
1047 text->TransformTextToPolySet( exactPolys, 0, maxError, ERROR_OUTSIDE );
1048
1049 text->TransformTextToPolySet( *aResult, inflate, maxError, ERROR_OUTSIDE );
1050 }
1051 else
1052 {
1053 if( inflate != 0 )
1054 item->TransformShapeToPolygon( exactPolys, aLayer, 0, maxError, ERROR_OUTSIDE );
1055
1056 item->TransformShapeToPolygon( *aResult, aLayer, inflate, maxError, ERROR_OUTSIDE );
1057 }
1058 }
1059 }
1060
1061 // Add filled zone areas.
1062 for( ZONE* zone : aBoard->Zones() )
1063 {
1064 if( zone->GetIsRuleArea() )
1065 continue;
1066
1067 if( !zone->IsOnLayer( aLayer ) )
1068 continue;
1069
1070 if( inflate != 0 )
1071 zone->TransformSmoothedOutlineToPolygon( exactPolys, 0, maxError, ERROR_OUTSIDE, boardOutline );
1072
1073 zone->TransformSmoothedOutlineToPolygon( *aResult, inflate, maxError, ERROR_OUTSIDE, boardOutline );
1074 }
1075 }
1076
1077 // Merge all polygons
1078 aResult->Simplify();
1079
1080 if( inflate != 0 )
1081 {
1082 aResult->Deflate( inflate, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
1083 // Add back in the exact polys. This is mandatory because inflate/deflate transform is
1084 // not perfect, and we want the initial areas perfectly kept.
1085 aResult->BooleanAdd( exactPolys );
1086 }
1087#undef ERROR
1088}
1089
1090
1097static void initializePlotter( PLOTTER* aPlotter, const BOARD* aBoard,
1098 const PCB_PLOT_PARAMS* aPlotOpts )
1099{
1100 PAGE_INFO pageA4( wxT( "A4" ) );
1101 const PAGE_INFO& pageInfo = aBoard->GetPageSettings();
1102 const PAGE_INFO* sheet_info;
1103 double paperscale; // Page-to-paper ratio
1104 VECTOR2I paperSizeIU;
1105 VECTOR2I pageSizeIU( pageInfo.GetSizeIU( pcbIUScale.IU_PER_MILS ) );
1106 bool autocenter = false;
1107
1108 // Special options: to fit the sheet to an A4 sheet replace the paper size. However there
1109 // is a difference between the autoscale and the a4paper option:
1110 // - Autoscale fits the board to the paper size
1111 // - A4paper fits the original paper size to an A4 sheet
1112 // - Both of them fit the board to an A4 sheet
1113 if( aPlotOpts->GetA4Output() )
1114 {
1115 sheet_info = &pageA4;
1116 paperSizeIU = pageA4.GetSizeIU( pcbIUScale.IU_PER_MILS );
1117 paperscale = (double) paperSizeIU.x / pageSizeIU.x;
1118 autocenter = true;
1119 }
1120 else
1121 {
1122 sheet_info = &pageInfo;
1123 paperSizeIU = pageSizeIU;
1124 paperscale = 1;
1125
1126 // Need autocentering only if scale is not 1:1
1127 autocenter = (aPlotOpts->GetScale() != 1.0);
1128 }
1129
1130 BOX2I bbox = aBoard->ComputeBoundingBox( false );
1131 VECTOR2I boardCenter = bbox.Centre();
1132 VECTOR2I boardSize = bbox.GetSize();
1133
1134 double compound_scale;
1135
1136 // Fit to 80% of the page if asked; it could be that the board is empty, in this case
1137 // regress to 1:1 scale
1138 if( aPlotOpts->GetAutoScale() && boardSize.x > 0 && boardSize.y > 0 )
1139 {
1140 double xscale = (paperSizeIU.x * 0.8) / boardSize.x;
1141 double yscale = (paperSizeIU.y * 0.8) / boardSize.y;
1142
1143 compound_scale = std::min( xscale, yscale ) * paperscale;
1144 }
1145 else
1146 {
1147 compound_scale = aPlotOpts->GetScale() * paperscale;
1148 }
1149
1150 // For the plot offset we have to keep in mind the auxiliary origin too: if autoscaling is
1151 // off we check that plot option (i.e. autoscaling overrides auxiliary origin)
1152 VECTOR2I offset( 0, 0);
1153
1154 if( autocenter )
1155 {
1156 offset.x = KiROUND( boardCenter.x - ( paperSizeIU.x / 2.0 ) / compound_scale );
1157 offset.y = KiROUND( boardCenter.y - ( paperSizeIU.y / 2.0 ) / compound_scale );
1158 }
1159 else
1160 {
1161 if( aPlotOpts->GetUseAuxOrigin() )
1162 offset = aBoard->GetDesignSettings().GetAuxOrigin();
1163 }
1164
1165 aPlotter->SetPageSettings( *sheet_info );
1166
1167 aPlotter->SetViewport( offset, pcbIUScale.IU_PER_MILS/10, compound_scale, aPlotOpts->GetMirror() );
1168
1169 // Has meaning only for gerber plotter. Must be called only after SetViewport
1170 aPlotter->SetGerberCoordinatesFormat( aPlotOpts->GetGerberPrecision() );
1171
1172 // Has meaning only for SVG plotter. Must be called only after SetViewport
1173 aPlotter->SetSvgCoordinatesFormat( aPlotOpts->GetSvgPrecision() );
1174
1175 aPlotter->SetCreator( wxT( "PCBNEW" ) );
1176 aPlotter->SetColorMode( !aPlotOpts->GetBlackAndWhite() ); // default is plot in Black and White.
1177 aPlotter->SetTextMode( aPlotOpts->GetTextMode() );
1178}
1179
1180
1184static void FillNegativeKnockout( PLOTTER *aPlotter, const BOX2I &aBbbox )
1185{
1186 const int margin = 5 * pcbIUScale.IU_PER_MM; // Add a 5 mm margin around the board
1187 aPlotter->SetNegative( true );
1188 aPlotter->SetColor( WHITE ); // Which will be plotted as black
1189
1190 BOX2I area = aBbbox;
1191 area.Inflate( margin );
1192 aPlotter->Rect( area.GetOrigin(), area.GetEnd(), FILL_T::FILLED_SHAPE );
1193 aPlotter->SetColor( BLACK );
1194}
1195
1196
1200static void ConfigureHPGLPenSizes( HPGL_PLOTTER *aPlotter, const PCB_PLOT_PARAMS *aPlotOpts )
1201{
1202 // Compute penDiam (the value is given in mils) in pcb units, with plot scale (if Scale is 2,
1203 // penDiam value is always m_HPGLPenDiam so apparent penDiam is actually penDiam / Scale
1204 int penDiam = KiROUND( aPlotOpts->GetHPGLPenDiameter() * pcbIUScale.IU_PER_MILS / aPlotOpts->GetScale() );
1205
1206 // Set HPGL-specific options and start
1207 aPlotter->SetPenSpeed( aPlotOpts->GetHPGLPenSpeed() );
1208 aPlotter->SetPenNumber( aPlotOpts->GetHPGLPenNum() );
1209 aPlotter->SetPenDiameter( penDiam );
1210}
1211
1212
1219PLOTTER* StartPlotBoard( BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aLayer,
1220 const wxString& aLayerName, const wxString& aFullFileName,
1221 const wxString& aSheetName, const wxString& aSheetPath,
1222 const wxString& aPageName, const wxString& aPageNumber,
1223 const int aPageCount )
1224{
1225 wxCHECK( aBoard && aPlotOpts, nullptr );
1226
1227 // Create the plotter driver and set the few plotter specific options
1228 PLOTTER* plotter = nullptr;
1229
1230 switch( aPlotOpts->GetFormat() )
1231 {
1232 case PLOT_FORMAT::DXF:
1233 DXF_PLOTTER* DXF_plotter;
1234 DXF_plotter = new DXF_PLOTTER();
1235 DXF_plotter->SetUnits( aPlotOpts->GetDXFPlotUnits() );
1236
1237 plotter = DXF_plotter;
1238 break;
1239
1240 case PLOT_FORMAT::POST:
1241 PS_PLOTTER* PS_plotter;
1242 PS_plotter = new PS_PLOTTER();
1243 PS_plotter->SetScaleAdjust( aPlotOpts->GetFineScaleAdjustX(),
1244 aPlotOpts->GetFineScaleAdjustY() );
1245 plotter = PS_plotter;
1246 break;
1247
1248 case PLOT_FORMAT::PDF:
1249 plotter = new PDF_PLOTTER( aBoard->GetProject() );
1250 break;
1251
1252 case PLOT_FORMAT::HPGL:
1253 HPGL_PLOTTER* HPGL_plotter;
1254 HPGL_plotter = new HPGL_PLOTTER();
1255
1256 // HPGL options are a little more convoluted to compute, so they get their own function
1257 ConfigureHPGLPenSizes( HPGL_plotter, aPlotOpts );
1258 plotter = HPGL_plotter;
1259 break;
1260
1262 // For Gerber plotter, a valid board layer must be set, in order to create a valid
1263 // Gerber header, especially the TF.FileFunction and .FilePolarity data
1264 if( aLayer < PCBNEW_LAYER_ID_START || aLayer >= PCB_LAYER_ID_COUNT )
1265 {
1266 wxLogError( wxString::Format(
1267 "Invalid board layer %d, cannot build a valid Gerber file header",
1268 aLayer ) );
1269 }
1270
1271 plotter = new GERBER_PLOTTER();
1272 break;
1273
1274 case PLOT_FORMAT::SVG:
1275 plotter = new SVG_PLOTTER();
1276 break;
1277
1278 default:
1279 wxASSERT( false );
1280 return nullptr;
1281 }
1282
1284 renderSettings->LoadColors( aPlotOpts->ColorSettings() );
1285 renderSettings->SetDefaultPenWidth( pcbIUScale.mmToIU( 0.0212 ) ); // Hairline at 1200dpi
1286 renderSettings->SetLayerName( aLayerName );
1287
1288 plotter->SetRenderSettings( renderSettings );
1289
1290 // Compute the viewport and set the other options
1291
1292 // page layout is not mirrored, so temporarily change mirror option for the page layout
1293 PCB_PLOT_PARAMS plotOpts = *aPlotOpts;
1294
1295 if( plotOpts.GetPlotFrameRef() && plotOpts.GetMirror() )
1296 plotOpts.SetMirror( false );
1297
1298 initializePlotter( plotter, aBoard, &plotOpts );
1299
1300 if( plotter->OpenFile( aFullFileName ) )
1301 {
1302 plotter->ClearHeaderLinesList();
1303
1304 // For the Gerber "file function" attribute, set the layer number
1305 if( plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1306 {
1307 bool useX2mode = plotOpts.GetUseGerberX2format();
1308
1309 GERBER_PLOTTER* gbrplotter = static_cast <GERBER_PLOTTER*> ( plotter );
1310 gbrplotter->DisableApertMacros( plotOpts.GetDisableGerberMacros() );
1311 gbrplotter->UseX2format( useX2mode );
1312 gbrplotter->UseX2NetAttributes( plotOpts.GetIncludeGerberNetlistInfo() );
1313
1314 // Attributes can be added using X2 format or as comment (X1 format)
1315 AddGerberX2Attribute( plotter, aBoard, aLayer, not useX2mode );
1316 }
1317
1318 bool startPlotSuccess = false;
1319 try
1320 {
1321 if( plotter->GetPlotterType() == PLOT_FORMAT::PDF )
1322 {
1323 startPlotSuccess =
1324 static_cast<PDF_PLOTTER*>( plotter )->StartPlot( aPageNumber, aPageName );
1325 }
1326 else
1327 {
1328 startPlotSuccess = plotter->StartPlot( aPageName );
1329 }
1330 }
1331 catch( ... )
1332 {
1333 startPlotSuccess = false;
1334 }
1335
1336
1337 if( startPlotSuccess )
1338 {
1339 // Plot the frame reference if requested
1340 if( aPlotOpts->GetPlotFrameRef() )
1341 {
1342 PlotDrawingSheet( plotter, aBoard->GetProject(), aBoard->GetTitleBlock(),
1343 aBoard->GetPageSettings(), &aBoard->GetProperties(), aPageNumber,
1344 aPageCount, aSheetName, aSheetPath, aBoard->GetFileName(),
1345 renderSettings->GetLayerColor( LAYER_DRAWINGSHEET ) );
1346
1347 if( aPlotOpts->GetMirror() )
1348 initializePlotter( plotter, aBoard, aPlotOpts );
1349 }
1350
1351 // When plotting a negative board: draw a black rectangle (background for plot board
1352 // in white) and switch the current color to WHITE; note the color inversion is actually
1353 // done in the driver (if supported)
1354 if( aPlotOpts->GetNegative() )
1355 {
1356 BOX2I bbox = aBoard->ComputeBoundingBox( false );
1357 FillNegativeKnockout( plotter, bbox );
1358 }
1359
1360 return plotter;
1361 }
1362 }
1363
1364 delete plotter->RenderSettings();
1365 delete plotter;
1366 return nullptr;
1367}
1368
1369void setupPlotterNewPDFPage( PLOTTER* aPlotter, BOARD* aBoard, const PCB_PLOT_PARAMS* aPlotOpts,
1370 const wxString& aLayerName, const wxString& aSheetName,
1371 const wxString& aSheetPath, const wxString& aPageNumber,
1372 int aPageCount )
1373{
1374 // Plot the frame reference if requested
1375 if( aPlotOpts->GetPlotFrameRef() )
1376 {
1377 PlotDrawingSheet( aPlotter, aBoard->GetProject(), aBoard->GetTitleBlock(),
1378 aBoard->GetPageSettings(), &aBoard->GetProperties(), aPageNumber,
1379 aPageCount,
1380 aSheetName, aSheetPath, aBoard->GetFileName(),
1382
1383 if( aPlotOpts->GetMirror() )
1384 initializePlotter( aPlotter, aBoard, aPlotOpts );
1385 }
1386
1387 aPlotter->RenderSettings()->SetLayerName( aLayerName );
1388}
int color
Definition: DXF_plotter.cpp:60
@ ERROR_OUTSIDE
Definition: approximation.h:33
@ ERROR_INSIDE
Definition: approximation.h:34
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
@ LAYER_CLASS_FAB
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
const VECTOR2I & GetAuxOrigin() const
int m_LineThickness[LAYER_CLASS_COUNT]
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:78
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:297
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false, bool aIncludeNPTHAsOutlines=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:2531
const PAGE_INFO & GetPageSettings() const
Definition: board.h:715
const ZONES & Zones() const
Definition: board.h:342
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,...
Definition: board.cpp:2967
TITLE_BLOCK & GetTitleBlock()
Definition: board.h:721
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1763
const std::map< wxString, wxString > & GetProperties() const
Definition: board.h:369
const FOOTPRINTS & Footprints() const
Definition: board.h:338
const TRACKS & Tracks() const
Definition: board.h:336
const wxString & GetFileName() const
Definition: board.h:334
PROJECT * GetProject() const
Definition: board.h:511
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:946
const DRAWINGS & Drawings() const
Definition: board.h:340
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:558
constexpr const Vec GetEnd() const
Definition: box2.h:212
constexpr size_type GetWidth() const
Definition: box2.h:214
constexpr Vec Centre() const
Definition: box2.h:97
constexpr size_type GetHeight() const
Definition: box2.h:215
constexpr coord_type GetLeft() const
Definition: box2.h:228
constexpr void Move(const Vec &aMoveVector)
Move the rectangle by the aMoveVector.
Definition: box2.h:138
constexpr const Vec & GetOrigin() const
Definition: box2.h:210
constexpr coord_type GetRight() const
Definition: box2.h:217
constexpr const SizeVec & GetSize() const
Definition: box2.h:206
constexpr coord_type GetTop() const
Definition: box2.h:229
constexpr coord_type GetBottom() const
Definition: box2.h:222
void SetLayerSet(const LSET &aLayerMask)
Definition: pcbplot.h:86
void PlotDrillMarks()
Draw a drill mark for pads and vias.
void PlotZone(const ZONE *aZone, PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPolysList)
void PlotPadNumber(const PAD *aPad, const COLOR4D &aColor)
void PlotBoardGraphicItem(const BOARD_ITEM *item)
Plot items like text and graphics but not tracks and footprints.
void PlotPad(const PAD *aPad, PCB_LAYER_ID aLayer, const COLOR4D &aColor, OUTLINE_MODE aPlotMode)
Plot a pad.
COLOR4D getColor(int aLayer) const
White color is special because it cannot be seen on a white paper in B&W mode.
void PlotFootprintTextItems(const FOOTPRINT *aFootprint)
int getFineWidthAdj() const
Definition: pcbplot.h:77
void PlotFootprintGraphicItems(const FOOTPRINT *aFootprint)
COLOR4D GetColor(int aLayer) const
When creating polygons to create a clearance polygonal area, the polygon must be same or bigger than ...
void SetUnits(DXF_UNITS aUnit)
Set the units to use for plotting the DXF file.
@ GBR_APERTURE_ATTRIB_CONDUCTOR
Aperture used for connected items like tracks (not vias).
Definition: gbr_metadata.h:98
@ GBR_APERTURE_ATTRIB_VIAPAD
Aperture used for vias.
Definition: gbr_metadata.h:103
@ GBR_APERTURE_ATTRIB_NONE
uninitialized attribute.
Definition: gbr_metadata.h:94
Metadata which can be added in a gerber file as attribute in X2 format.
Definition: gbr_metadata.h:211
void SetNetName(const wxString &aNetname)
Definition: gbr_metadata.h:243
void SetApertureAttrib(GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB aApertAttribute)
Definition: gbr_metadata.h:215
GBR_NETLIST_METADATA m_NetlistMetadata
An item to handle object attribute.
Definition: gbr_metadata.h:276
void SetNetAttribType(int aNetAttribType)
Definition: gbr_metadata.h:233
@ GBR_NETINFO_NET
print info associated to a net (TO.N attribute)
@ GBR_NETINFO_UNSPECIFIED
idle command (no command)
bool m_NotInNet
true if a pad of a footprint cannot be connected (for instance a mechanical NPTH, ot a not named pad)...
void UseX2format(bool aEnable)
void UseX2NetAttributes(bool aEnable)
void DisableApertMacros(bool aDisable)
Disable Aperture Macro (AM) command, only for broken Gerber Readers.
virtual void SetPenSpeed(int speed)
Definition: plotter_hpgl.h:88
virtual void SetPenNumber(int number)
Definition: plotter_hpgl.h:93
virtual void SetPenDiameter(double diameter)
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition: color4d.h:398
static const COLOR4D BLACK
Definition: color4d.h:402
PCB specific render settings.
Definition: pcb_painter.h:79
void LoadColors(const COLOR_SETTINGS *aSettings) override
void SetDefaultPenWidth(int aWidth)
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
void SetLayerName(const wxString &aLayerName)
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: lseq.h:47
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
LSEQ SeqStackupForPlotting() const
Return the sequence that is typical for a bottom-to-top stack-up.
Definition: lset.cpp:388
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:572
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:297
Handle the data for a net.
Definition: netinfo.h:56
Definition: pad.h:54
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:59
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition: page_info.h:171
bool IsDegenerated(int aThreshold=5) const
Definition: pcb_track.cpp:2068
EDA_ANGLE GetArcAngleStart() const
Definition: pcb_track.cpp:2050
double GetRadius() const
Definition: pcb_track.cpp:2033
EDA_ANGLE GetAngle() const
Definition: pcb_track.cpp:2040
virtual VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_track.h:344
Parameters and options when plotting/printing a board.
bool GetNegative() const
PLOT_FORMAT GetFormat() const
bool GetSkipPlotNPTH_Pads() const
void SetDrillMarksType(DRILL_MARKS aVal)
bool GetUseAuxOrigin() const
bool GetHideDNPFPsOnFabLayers() const
void SetSkipPlotNPTH_Pads(bool aSkip)
bool GetMirror() const
DXF_UNITS GetDXFPlotUnits() const
bool GetAutoScale() const
PLOT_TEXT_MODE GetTextMode() const
bool GetCrossoutDNPFPsOnFabLayers() const
void SetDXFPlotPolygonMode(bool aFlag)
double GetHPGLPenDiameter() const
unsigned GetSvgPrecision() const
unsigned GetBlackAndWhite() const
double GetScale() const
bool GetDXFPlotPolygonMode() const
bool GetPlotReference() const
bool m_PDFFrontFPPropertyPopups
Generate PDF property popup menus for footprints.
void SetMirror(bool aFlag)
bool GetSketchPadsOnFabLayers() const
bool GetSubtractMaskFromSilk() const
int GetGerberPrecision() const
int GetHPGLPenSpeed() const
double GetFineScaleAdjustY() const
bool GetPlotPadNumbers() const
bool GetA4Output() const
int GetHPGLPenNum() const
DRILL_MARKS GetDrillMarksType() const
bool GetUseGerberX2format() const
bool GetPlotValue() const
bool GetIncludeGerberNetlistInfo() const
double GetFineScaleAdjustX() const
bool m_PDFBackFPPropertyPopups
on front and/or back of board
bool GetPlotFPText() const
bool GetPlotFrameRef() const
bool GetDisableGerberMacros() const
OUTLINE_MODE GetPlotMode() const
COLOR_SETTINGS * ColorSettings() const
Base plotter engine class.
Definition: plotter.h:105
virtual void ThickArc(const EDA_SHAPE &aArcShape, OUTLINE_MODE aTraceMode, void *aData, int aWidth)
Definition: plotter.cpp:596
virtual void ThickSegment(const VECTOR2I &start, const VECTOR2I &end, int width, OUTLINE_MODE tracemode, void *aData)
Definition: plotter.cpp:553
virtual void Circle(const VECTOR2I &pos, int diametre, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH)=0
virtual bool OpenFile(const wxString &aFullFilename)
Open or create the plot file aFullFilename.
Definition: plotter.cpp:75
virtual void SetNegative(bool aNegative)
Definition: plotter.h:125
virtual void SetSvgCoordinatesFormat(unsigned aPrecision)
Set the number of digits for mantissa in coordinates in mm for SVG plotter.
Definition: plotter.h:531
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: plotter.h:138
void SetRenderSettings(RENDER_SETTINGS *aSettings)
Definition: plotter.h:135
virtual bool StartPlot(const wxString &aPageNumber)=0
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:136
virtual void SetGerberCoordinatesFormat(int aResolution, bool aUseInches=false)
Definition: plotter.h:525
virtual void Bookmark(const BOX2I &aBox, const wxString &aName, const wxString &aGroupName=wxEmptyString)
Create a bookmark to a symbol.
Definition: plotter.h:481
virtual PLOT_FORMAT GetPlotterType() const =0
Return the effective plot engine in use.
virtual void SetTextMode(PLOT_TEXT_MODE mode)
Change the current text mode.
Definition: plotter.h:520
virtual void SetCreator(const wxString &aCreator)
Definition: plotter.h:157
VECTOR2I GetPlotOffsetUserUnits()
Definition: plotter.h:557
void ClearHeaderLinesList()
Remove all lines from the list of free lines to print at the beginning of the file.
Definition: plotter.h:175
virtual void FlashPadCircle(const VECTOR2I &aPadPos, int aDiameter, OUTLINE_MODE aTraceMode, void *aData)=0
virtual void SetViewport(const VECTOR2I &aOffset, double aIusPerDecimil, double aScale, bool aMirror)=0
Set the plot offset and scaling for the current plot.
virtual void SetColorMode(bool aColorMode)
Plot in B/W or color.
Definition: plotter.h:132
virtual void StartBlock(void *aData)
calling this function allows one to define the beginning of a group of drawing items,...
Definition: plotter.h:543
virtual void PlotPoly(const std::vector< VECTOR2I > &aCornerList, FILL_T aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=nullptr)=0
Draw a polygon ( filled or not ).
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition: plotter.h:470
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:510
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH)=0
virtual void SetColor(const COLOR4D &color)=0
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:552
void SetScaleAdjust(double scaleX, double scaleY)
Set the 'fine' scaling for the postscript engine.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void DeletePolygon(int aIdx)
Delete aIdx-th polygon from the set.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
void Fracture()
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
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)
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
int OutlineCount() const
Return the number of outlines in the set.
void InflateWithLinkedHoles(int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError)
Perform outline inflation/deflation, using round corners.
SHAPE_POLY_SET CloneDropTriangulation() const
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
const POLYGON & CPolygon(int aIndex) const
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Handle a list of polygons defining a copper zone.
Definition: zone.h:74
void SetMinThickness(int aMinThickness)
Definition: zone.h:302
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: zone.cpp:527
@ WHITE
Definition: color4d.h:48
@ LIGHTGRAY
Definition: color4d.h:47
@ BLACK
Definition: color4d.h:44
void PlotDrawingSheet(PLOTTER *plotter, const PROJECT *aProject, const TITLE_BLOCK &aTitleBlock, const PAGE_INFO &aPageInfo, const std::map< wxString, wxString > *aProperties, const wxString &aSheetNumber, int aSheetCount, const wxString &aSheetName, const wxString &aSheetPath, const wxString &aFilename, COLOR4D aColor, bool aIsFirstPage)
@ CHAMFER_ALL_CORNERS
All angles are chamfered.
@ ROUND_ALL_CORNERS
All angles are rounded.
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:401
@ FILLED_SHAPE
Fill with object color.
Handle special data (items attributes) during plot.
a few functions useful in geometry calculations.
static const bool FILLED
Definition: gr_basic.cpp:30
double m_SmallDrillMarkSize
The diameter of the drill marks on print and plot outputs (in mm) when the "Drill marks" option is se...
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:663
@ LAYER_DRAWINGSHEET
Sheet frame and title block.
Definition: layer_ids.h:277
@ LAYER_VIAS
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:232
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ F_CrtYd
Definition: layer_ids.h:116
@ B_Adhes
Definition: layer_ids.h:103
@ Edge_Cuts
Definition: layer_ids.h:112
@ Dwgs_User
Definition: layer_ids.h:107
@ F_Paste
Definition: layer_ids.h:104
@ Cmts_User
Definition: layer_ids.h:108
@ F_Adhes
Definition: layer_ids.h:102
@ B_Mask
Definition: layer_ids.h:98
@ B_Cu
Definition: layer_ids.h:65
@ Eco1_User
Definition: layer_ids.h:109
@ F_Mask
Definition: layer_ids.h:97
@ B_Paste
Definition: layer_ids.h:105
@ F_Fab
Definition: layer_ids.h:119
@ Margin
Definition: layer_ids.h:113
@ F_SilkS
Definition: layer_ids.h:100
@ B_CrtYd
Definition: layer_ids.h:115
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ Eco2_User
Definition: layer_ids.h:110
@ B_SilkS
Definition: layer_ids.h:101
@ PCB_LAYER_ID_COUNT
Definition: layer_ids.h:171
@ F_Cu
Definition: layer_ids.h:64
@ B_Fab
Definition: layer_ids.h:118
OUTLINE_MODE
Definition: outline_mode.h:25
@ SKETCH
Definition: outline_mode.h:26
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
Definition: padstack.h:52
void AddGerberX2Attribute(PLOTTER *aPlotter, const BOARD *aBoard, int aLayer, bool aUseX1CompatibilityMode)
Calculate some X2 attributes as defined in the Gerber file format specification and add them to the g...
Definition: pcbplot.cpp:360
static void FillNegativeKnockout(PLOTTER *aPlotter, const BOX2I &aBbbox)
Prefill in black an area a little bigger than the board to prepare for the negative plot.
void PlotClippedSilkLayer(BOARD *aBoard, PLOTTER *aPlotter, const LSET &aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
void PlotBoardLayers(BOARD *aBoard, PLOTTER *aPlotter, const LSEQ &aLayers, const PCB_PLOT_PARAMS &aPlotOptions)
Plot a sequence of board layer IDs.
void PlotStandardLayer(BOARD *aBoard, PLOTTER *aPlotter, const LSET &aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
Plot any layer EXCEPT a solder-mask with an enforced minimum width.
PLOTTER * StartPlotBoard(BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aLayer, const wxString &aLayerName, const wxString &aFullFileName, const wxString &aSheetName, const wxString &aSheetPath, const wxString &aPageName, const wxString &aPageNumber, const int aPageCount)
Open a new plotfile using the options (and especially the format) specified in the options and prepar...
void GenerateLayerPoly(SHAPE_POLY_SET *aResult, BOARD *aBoard, PCB_LAYER_ID aLayer, bool aPlotFPText, bool aPlotReferences, bool aPlotValues)
Generates a SHAPE_POLY_SET representing the plotted items on a layer.
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.
void PlotPolySet(BOARD *aBoard, PLOTTER *aPlotter, const PCB_PLOT_PARAMS &aPlotOpt, SHAPE_POLY_SET *aPolySet, PCB_LAYER_ID aLayer)
void PlotSolderMaskLayer(BOARD *aBoard, PLOTTER *aPlotter, const LSET &aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
Plot a solder mask layer.
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...
void PlotInteractiveLayer(BOARD *aBoard, PLOTTER *aPlotter, const PCB_PLOT_PARAMS &aPlotOpt)
Plot interactive items (hypertext links, properties, etc.).
void PlotOneBoardLayer(BOARD *aBoard, PLOTTER *aPlotter, PCB_LAYER_ID aLayer, const PCB_PLOT_PARAMS &aPlotOpt, bool isPrimaryLayer)
Plot one copper or technical layer.
void setupPlotterNewPDFPage(PLOTTER *aPlotter, BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, const wxString &aLayerName, const wxString &aSheetName, const wxString &aSheetPath, const wxString &aPageNumber, int aPageCount)
void PlotLayer(BOARD *aBoard, PLOTTER *aPlotter, const LSET &layerMask, const PCB_PLOT_PARAMS &plotOpts)
void PlotLayerOutlines(BOARD *aBoard, PLOTTER *aPlotter, const LSET &aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
Plot outlines.
Plotting engine (HPGL)
Plotting engines similar to ps (PostScript, Gerber, svg)
std::vector< FAB_LAYER_COLOR > dummy
const double IU_PER_MM
Definition: base_units.h:76
const double IU_PER_MILS
Definition: base_units.h:77
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
int clearance
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695