KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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>
41#include <plotters/plotter.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 for( PCB_LAYER_ID layer : aLayers )
136 PlotOneBoardLayer( aBoard, aPlotter, layer, aPlotOptions, layer == aLayers[0] );
137
138 // Drill marks are plotted in white to knockout the pad if any layers of the pad are
139 // being plotted, and in black if the pad is not being plotted. For the former, this
140 // must happen after all other layers are plotted.
141 if( aPlotOptions.GetDrillMarksType() != DRILL_MARKS::NO_DRILL_SHAPE )
142 {
143 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOptions );
144 itemplotter.SetLayerSet( aLayers );
145 itemplotter.PlotDrillMarks();
146 }
147}
148
149
150void PlotInteractiveLayer( BOARD* aBoard, PLOTTER* aPlotter, const PCB_PLOT_PARAMS& aPlotOpt )
151{
152 for( const FOOTPRINT* fp : aBoard->Footprints() )
153 {
154 if( fp->GetLayer() == F_Cu && !aPlotOpt.m_PDFFrontFPPropertyPopups )
155 continue;
156
157 if( fp->GetLayer() == B_Cu && !aPlotOpt.m_PDFBackFPPropertyPopups )
158 continue;
159
160 std::vector<wxString> properties;
161
162 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
163 _( "Reference designator" ),
164 fp->Reference().GetShownText( false ) ) );
165
166 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
167 _( "Value" ),
168 fp->Value().GetShownText( false ) ) );
169
170 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
171 _( "Footprint" ),
172 fp->GetFPID().GetUniStringLibItemName() ) );
173
174 for( const PCB_FIELD* field : fp->GetFields() )
175 {
176 if( field->IsReference() || field->IsValue() )
177 continue;
178
179 if( field->GetText().IsEmpty() )
180 continue;
181
182 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
183 field->GetName(),
184 field->GetText() ) );
185 }
186
187 // These 2 properties are not very useful in a plot file (like a PDF)
188#if 0
189 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Library Description" ),
190 fp->GetLibDescription() ) );
191
192 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Keywords" ),
193 fp->GetKeywords() ) );
194#endif
195 // Draw items are plotted with a position offset. So we need to move
196 // our boxes (which are not plotted) by the same offset.
197 VECTOR2I offset = -aPlotter->GetPlotOffsetUserUnits();
198
199 // Use a footprint bbox without texts to create the hyperlink area
200 BOX2I bbox = fp->GetBoundingBox( false );
201 bbox.Move( offset );
202 aPlotter->HyperlinkMenu( bbox, properties );
203
204 // Use a footprint bbox with visible texts only to create the bookmark area
205 // which is the area to zoom on ft selection
206 // However the bbox need to be inflated for a better look.
207 bbox = fp->GetBoundingBox( true );
208 bbox.Move( offset );
209 bbox.Inflate( bbox.GetWidth() /2, bbox.GetHeight() /2 );
210 aPlotter->Bookmark( bbox, fp->GetReference(), _( "Footprints" ) );
211 }
212}
213
214
215void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
216 const PCB_PLOT_PARAMS& aPlotOpt, bool isPrimaryLayer )
217{
218 PCB_PLOT_PARAMS plotOpt = aPlotOpt;
219
220 // Set a default color and the text mode for this layer
221 aPlotter->SetColor( BLACK );
222 aPlotter->SetTextMode( aPlotOpt.GetTextMode() );
223
224 // Specify that the contents of the "Edges Pcb" layer are to be plotted in addition to the
225 // contents of the currently specified layer.
226 LSET layer_mask( { aLayer } );
227
228 if( IsCopperLayer( aLayer ) )
229 {
230 // Skip NPTH pads on copper layers ( only if hole size == pad size ):
231 // Drill mark will be plotted if drill mark is SMALL_DRILL_SHAPE or FULL_DRILL_SHAPE
232 if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
233 plotOpt.SetDXFPlotPolygonMode( true );
234 else
235 plotOpt.SetSkipPlotNPTH_Pads( true );
236
237 PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
238 }
239 else
240 {
241 switch( aLayer )
242 {
243 case B_Mask:
244 case F_Mask:
245 // Use outline mode for DXF
246 plotOpt.SetDXFPlotPolygonMode( true );
247
248 // Plot solder mask:
249 PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt );
250
251 break;
252
253 case B_Adhes:
254 case F_Adhes:
255 case B_Paste:
256 case F_Paste:
257 // Disable plot pad holes
259
260 // Use outline mode for DXF
261 plotOpt.SetDXFPlotPolygonMode( true );
262
263 PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
264
265 break;
266
267 case F_SilkS:
268 case B_SilkS:
269 if( plotOpt.GetSubtractMaskFromSilk() )
270 {
271 if( aPlotter->GetPlotterType() == PLOT_FORMAT::GERBER && isPrimaryLayer )
272 {
273 // Use old-school, positive/negative mask plotting which preserves utilization
274 // of Gerber aperture masks. This method can only be used when the given silk
275 // layer is the primary layer as the negative mask will also knockout any other
276 // (non-silk) layers that were plotted before the silk layer.
277
278 PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
279
280 // Create the mask to subtract by creating a negative layer polarity
281 aPlotter->SetLayerPolarity( false );
282
283 // Disable plot pad holes
285
286 // Plot the mask
287 layer_mask = ( aLayer == F_SilkS ) ? LSET( { F_Mask } ) : LSET( { B_Mask } );
288 PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt );
289
290 // Disable the negative polarity
291 aPlotter->SetLayerPolarity( true );
292 }
293 else
294 {
295 PlotClippedSilkLayer( aBoard, aPlotter, layer_mask, plotOpt );
296 }
297
298 break;
299 }
300
301 PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
302 break;
303
304 case Dwgs_User:
305 case Cmts_User:
306 case Eco1_User:
307 case Eco2_User:
308 case Edge_Cuts:
309 case Margin:
310 case F_CrtYd:
311 case B_CrtYd:
312 case F_Fab:
313 case B_Fab:
314 default:
315 PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
316 break;
317 }
318 }
319}
320
321
325void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMask,
326 const PCB_PLOT_PARAMS& aPlotOpt )
327{
328 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
329 int maxError = aBoard->GetDesignSettings().m_MaxError;
330
331 itemplotter.SetLayerSet( aLayerMask );
332
333 bool onCopperLayer = ( LSET::AllCuMask() & aLayerMask ).any();
334 bool onSolderMaskLayer = ( LSET( { F_Mask, B_Mask } ) & aLayerMask ).any();
335 bool onSolderPasteLayer = ( LSET( { F_Paste, B_Paste } ) & aLayerMask ).any();
336 bool onFrontFab = ( LSET( { F_Fab } ) & aLayerMask ).any();
337 bool onBackFab = ( LSET( { B_Fab } ) & aLayerMask ).any();
338 bool sketchPads = ( onFrontFab || onBackFab ) && aPlotOpt.GetSketchPadsOnFabLayers();
339
340 // Plot edge layer and graphic items
341 for( const BOARD_ITEM* item : aBoard->Drawings() )
342 itemplotter.PlotBoardGraphicItem( item );
343
344 // Draw footprint texts:
345 for( const FOOTPRINT* footprint : aBoard->Footprints() )
346 itemplotter.PlotFootprintTextItems( footprint );
347
348 // Draw footprint other graphic items:
349 for( const FOOTPRINT* footprint : aBoard->Footprints() )
350 itemplotter.PlotFootprintGraphicItems( footprint );
351
352 // Plot footprint pads
353 for( FOOTPRINT* footprint : aBoard->Footprints() )
354 {
355 aPlotter->StartBlock( nullptr );
356
357 for( PAD* pad : footprint->Pads() )
358 {
359 bool doSketchPads = false;
360
361 if( !( pad->GetLayerSet() & aLayerMask ).any() )
362 {
363 if( sketchPads && ( ( onFrontFab && pad->GetLayerSet().Contains( F_Cu ) )
364 || ( onBackFab && pad->GetLayerSet().Contains( B_Cu ) ) ) )
365 {
366 doSketchPads = true;
367 }
368 else
369 {
370 continue;
371 }
372 }
373
374 if( onCopperLayer && !pad->IsOnCopperLayer() )
375 continue;
376
378 if( onCopperLayer && !pad->FlashLayer( aLayerMask ) )
379 continue;
380
381 // TODO(JE) padstacks - different behavior for single layer or multilayer
382
384
385 // If we're plotting a single layer, the color for that layer can be used directly.
386 if( aLayerMask.count() == 1 )
387 {
388 color = aPlotOpt.ColorSettings()->GetColor( aLayerMask.Seq()[0] );
389 }
390 else
391 {
392 if( ( pad->GetLayerSet() & aLayerMask )[B_Cu] )
393 color = aPlotOpt.ColorSettings()->GetColor( B_Cu );
394
395 if( ( pad->GetLayerSet() & aLayerMask )[F_Cu] )
396 color = color.LegacyMix( aPlotOpt.ColorSettings()->GetColor( F_Cu ) );
397
398 if( sketchPads && aLayerMask[F_Fab] )
399 color = aPlotOpt.ColorSettings()->GetColor( F_Fab );
400 else if( sketchPads && aLayerMask[B_Fab] )
401 color = aPlotOpt.ColorSettings()->GetColor( B_Fab );
402 }
403
404 if( sketchPads && ( ( onFrontFab && pad->GetLayerSet().Contains( F_Cu ) )
405 || ( onBackFab && pad->GetLayerSet().Contains( B_Cu ) ) ) )
406 {
407 if( aPlotOpt.GetPlotPadNumbers() )
408 itemplotter.PlotPadNumber( pad, color );
409 }
410
411 auto plotPadLayer =
412 [&]( PCB_LAYER_ID aLayer )
413 {
414 VECTOR2I margin;
415 int width_adj = 0;
416
417 if( onCopperLayer )
418 width_adj = itemplotter.getFineWidthAdj();
419
420 if( onSolderMaskLayer )
421 margin.x = margin.y = pad->GetSolderMaskExpansion( aLayer );
422
423 if( onSolderPasteLayer )
424 margin = pad->GetSolderPasteMargin( aLayer );
425
426 // not all shapes can have a different margin for x and y axis
427 // in fact only oval and rect shapes can have different values.
428 // Round shape have always the same x,y margin
429 // so define a unique value for other shapes that do not support different values
430 int mask_clearance = margin.x;
431
432 // Now offset the pad size by margin + width_adj
433 VECTOR2I padPlotsSize = pad->GetSize( aLayer ) + margin * 2 + VECTOR2I( width_adj, width_adj );
434
435 // Store these parameters that can be modified to plot inflated/deflated pads shape
436 PAD_SHAPE padShape = pad->GetShape( aLayer );
437 VECTOR2I padSize = pad->GetSize( aLayer );
438 VECTOR2I padDelta = pad->GetDelta( aLayer ); // has meaning only for trapezoidal pads
439 // CornerRadius and CornerRadiusRatio can be modified
440 // the radius is built from the ratio, so saving/restoring the ratio is enough
441 double padCornerRadiusRatio = pad->GetRoundRectRadiusRatio( aLayer );
442
443 // Don't draw a 0 sized pad.
444 // Note: a custom pad can have its pad anchor with size = 0
445 if( padShape != PAD_SHAPE::CUSTOM
446 && ( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 ) )
447 {
448 return;
449 }
450
451 switch( padShape )
452 {
454 case PAD_SHAPE::OVAL:
455 pad->SetSize( aLayer, padPlotsSize );
456
457 if( aPlotOpt.GetSkipPlotNPTH_Pads() &&
459 ( pad->GetSize(aLayer ) == pad->GetDrillSize() ) &&
460 ( pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
461 {
462 break;
463 }
464
465 itemplotter.PlotPad( pad, aLayer, color, doSketchPads );
466 break;
467
469 pad->SetSize( aLayer, padPlotsSize );
470
471 if( mask_clearance > 0 )
472 {
473 pad->SetShape( aLayer, PAD_SHAPE::ROUNDRECT );
474 pad->SetRoundRectCornerRadius( aLayer, mask_clearance );
475 }
476
477 itemplotter.PlotPad( pad, aLayer, color, doSketchPads );
478 break;
479
481 // inflate/deflate a trapezoid is a bit complex.
482 // so if the margin is not null, build a similar polygonal pad shape,
483 // and inflate/deflate the polygonal shape
484 // because inflating/deflating using different values for y and y
485 // we are using only margin.x as inflate/deflate value
486 if( mask_clearance == 0 )
487 {
488 itemplotter.PlotPad( pad, aLayer, color, doSketchPads );
489 }
490 else
491 {
492 PAD dummy( *pad );
493 dummy.SetAnchorPadShape( aLayer, PAD_SHAPE::CIRCLE );
494 dummy.SetShape( aLayer, PAD_SHAPE::CUSTOM );
495 SHAPE_POLY_SET outline;
496 outline.NewOutline();
497 int dx = padSize.x / 2;
498 int dy = padSize.y / 2;
499 int ddx = padDelta.x / 2;
500 int ddy = padDelta.y / 2;
501
502 outline.Append( -dx - ddy, dy + ddx );
503 outline.Append( dx + ddy, dy - ddx );
504 outline.Append( dx - ddy, -dy + ddx );
505 outline.Append( -dx + ddy, -dy - ddx );
506
507 // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
508 // which can create bad shapes if margin.x is < 0
510 maxError );
511 dummy.DeletePrimitivesList();
512 dummy.AddPrimitivePoly( aLayer, outline, 0, true );
513
514 // Be sure the anchor pad is not bigger than the deflated shape because this
515 // anchor will be added to the pad shape when plotting the pad. So now the
516 // polygonal shape is built, we can clamp the anchor size
517 dummy.SetSize( aLayer, VECTOR2I( 0, 0 ) );
518
519 itemplotter.PlotPad( &dummy, aLayer, color, doSketchPads );
520 }
521
522 break;
523
525 {
526 // rounding is stored as a percent, but we have to update this ratio
527 // to force recalculation of other values after size changing (we do not
528 // really change the rounding percent value)
529 double radius_ratio = pad->GetRoundRectRadiusRatio( aLayer );
530 pad->SetSize( aLayer, padPlotsSize );
531 pad->SetRoundRectRadiusRatio( aLayer, radius_ratio );
532
533 itemplotter.PlotPad( pad, aLayer, color, doSketchPads );
534 break;
535 }
536
538 if( mask_clearance == 0 )
539 {
540 // the size can be slightly inflated by width_adj (PS/PDF only)
541 pad->SetSize( aLayer, padPlotsSize );
542 itemplotter.PlotPad( pad, aLayer, color, doSketchPads );
543 }
544 else
545 {
546 // Due to the polygonal shape of a CHAMFERED_RECT pad, the best way is to
547 // convert the pad shape to a full polygon, inflate/deflate the polygon
548 // and use a dummy CUSTOM pad to plot the final shape.
549 PAD dummy( *pad );
550 // Build the dummy pad outline with coordinates relative to the pad position
551 // pad offset and orientation 0. The actual pos, offset and rotation will be
552 // taken in account later by the plot function
553 dummy.SetPosition( VECTOR2I( 0, 0 ) );
554 dummy.SetOffset( aLayer, VECTOR2I( 0, 0 ) );
555 dummy.SetOrientation( ANGLE_0 );
556 SHAPE_POLY_SET outline;
557 dummy.TransformShapeToPolygon( outline, aLayer, 0, maxError, ERROR_INSIDE );
559 maxError );
560
561 // Initialize the dummy pad shape:
562 dummy.SetAnchorPadShape( aLayer, PAD_SHAPE::CIRCLE );
563 dummy.SetShape( aLayer, PAD_SHAPE::CUSTOM );
564 dummy.DeletePrimitivesList();
565 dummy.AddPrimitivePoly( aLayer, outline, 0, true );
566
567 // Be sure the anchor pad is not bigger than the deflated shape because this
568 // anchor will be added to the pad shape when plotting the pad.
569 // So we set the anchor size to 0
570 dummy.SetSize( aLayer, VECTOR2I( 0, 0 ) );
571 // Restore pad position and offset
572 dummy.SetPosition( pad->GetPosition() );
573 dummy.SetOffset( aLayer, pad->GetOffset( aLayer ) );
574 dummy.SetOrientation( pad->GetOrientation() );
575
576 itemplotter.PlotPad( &dummy, aLayer, color, doSketchPads );
577 }
578
579 break;
580
582 {
583 // inflate/deflate a custom shape is a bit complex.
584 // so build a similar pad shape, and inflate/deflate the polygonal shape
585 PAD dummy( *pad );
586 dummy.SetParentGroup( nullptr );
587
588 SHAPE_POLY_SET shape;
589 pad->MergePrimitivesAsPolygon( aLayer, &shape );
590
591 // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
592 // which can create bad shapes if margin.x is < 0
593 shape.InflateWithLinkedHoles( mask_clearance,
595 dummy.DeletePrimitivesList();
596 dummy.AddPrimitivePoly( aLayer, shape, 0, true );
597
598 // Be sure the anchor pad is not bigger than the deflated shape because this
599 // anchor will be added to the pad shape when plotting the pad. So now the
600 // polygonal shape is built, we can clamp the anchor size
601 if( mask_clearance < 0 ) // we expect margin.x = margin.y for custom pads
602 {
603 dummy.SetSize( aLayer, VECTOR2I( std::max( 0, padPlotsSize.x ),
604 std::max( 0, padPlotsSize.y ) ) );
605 }
606
607 itemplotter.PlotPad( &dummy, aLayer, color, doSketchPads );
608 break;
609 }
610 }
611
612 // Restore the pad parameters modified by the plot code
613 pad->SetSize( aLayer, padSize );
614 pad->SetDelta( aLayer, padDelta );
615 pad->SetShape( aLayer, padShape );
616 pad->SetRoundRectRadiusRatio( aLayer, padCornerRadiusRatio );
617 };
618
619 for( PCB_LAYER_ID layer : aLayerMask.SeqStackupForPlotting() )
620 plotPadLayer( layer );
621 }
622
623 if( footprint->IsDNP()
624 && !itemplotter.GetHideDNPFPsOnFabLayers()
625 && itemplotter.GetCrossoutDNPFPsOnFabLayers()
626 && ( ( onFrontFab && footprint->GetLayer() == F_Cu )
627 || ( onBackFab && footprint->GetLayer() == B_Cu ) ) )
628 {
629 BOX2I rect;
630 const SHAPE_POLY_SET& courtyard = footprint->GetCourtyard( footprint->GetLayer() );
631
632 if( courtyard.IsEmpty() )
633 rect = footprint->GetEffectiveShape()->BBox();
634 else
635 rect = courtyard.BBox();
636
637 int width = aBoard->GetDesignSettings().m_LineThickness[ LAYER_CLASS_FAB ];
638
639 aPlotter->ThickSegment( rect.GetOrigin(), rect.GetEnd(), width, nullptr );
640 aPlotter->ThickSegment( VECTOR2I( rect.GetLeft(), rect.GetBottom() ),
641 VECTOR2I( rect.GetRight(), rect.GetTop() ),
642 width, nullptr );
643 }
644
645 aPlotter->EndBlock( nullptr );
646 }
647
648 // Plot vias on copper layers, and if aPlotOpt.GetPlotViaOnMaskLayer() is true,
649
650 GBR_METADATA gbr_metadata;
651
652 if( onCopperLayer )
653 {
656 }
657
658 auto getMetadata =
659 [&]()
660 {
661 if( aPlotter->GetPlotterType() == PLOT_FORMAT::GERBER )
662 return (void*) &gbr_metadata;
663 else if( aPlotter->GetPlotterType() == PLOT_FORMAT::DXF )
664 return (void*) &aPlotOpt;
665 else
666 return (void*) nullptr;
667 };
668
669 aPlotter->StartBlock( nullptr );
670
671 for( const PCB_TRACK* track : aBoard->Tracks() )
672 {
673 if( track->Type() != PCB_VIA_T )
674 continue;
675
676 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
677
678 // vias are not plotted if not on selected layer
679 LSET via_mask_layer = via->GetLayerSet();
680
681 if( !( via_mask_layer & aLayerMask ).any() )
682 continue;
683
684 int via_margin = 0;
685 double width_adj = 0;
686
687 // TODO(JE) padstacks - separate top/bottom margin
688 if( onSolderMaskLayer )
689 via_margin = via->GetSolderMaskExpansion();
690
691 if( ( aLayerMask & LSET::AllCuMask() ).any() )
692 width_adj = itemplotter.getFineWidthAdj();
693
695 if( onCopperLayer && !via->FlashLayer( aLayerMask ) )
696 continue;
697
698 int diameter = 0;
699
700 for( PCB_LAYER_ID layer : aLayerMask )
701 diameter = std::max( diameter, via->GetWidth( layer ) );
702
703 diameter += 2 * via_margin + width_adj;
704
705 // Don't draw a null size item :
706 if( diameter <= 0 )
707 continue;
708
709 // Some vias can be not connected (no net).
710 // Set the m_NotInNet for these vias to force a empty net name in gerber file
711 gbr_metadata.m_NetlistMetadata.m_NotInNet = via->GetNetname().IsEmpty();
712
713 gbr_metadata.SetNetName( via->GetNetname() );
714
716
717 // If we're plotting a single layer, the color for that layer can be used directly.
718 if( aLayerMask.count() == 1 )
719 color = aPlotOpt.ColorSettings()->GetColor( aLayerMask.Seq()[0] );
720 else
721 color = aPlotOpt.ColorSettings()->GetColor( LAYER_VIAS + static_cast<int>( via->GetViaType() ) );
722
723 // Change UNSPECIFIED or WHITE to LIGHTGRAY because the white items are not seen on a
724 // white paper or screen
727
728 aPlotter->SetColor( color );
729 aPlotter->FlashPadCircle( via->GetStart(), diameter, getMetadata() );
730 }
731
732 aPlotter->EndBlock( nullptr );
733 aPlotter->StartBlock( nullptr );
734
735 if( onCopperLayer )
736 {
739 }
740 else
741 {
742 // Reset attributes if non-copper (soldermask) layer
745 }
746
747 // Plot tracks (not vias) :
748 for( const PCB_TRACK* track : aBoard->Tracks() )
749 {
750 if( track->Type() == PCB_VIA_T )
751 continue;
752
753 if( !( aLayerMask & track->GetLayerSet() ).any() )
754 continue;
755
756 // Some track segments can be not connected (no net).
757 // Set the m_NotInNet for these segments to force a empty net name in gerber file
758 gbr_metadata.m_NetlistMetadata.m_NotInNet = track->GetNetname().IsEmpty();
759
760 gbr_metadata.SetNetName( track->GetNetname() );
761
762 int margin = 0;
763
764 if( onSolderMaskLayer )
765 margin = track->GetSolderMaskExpansion();
766
767 int width = track->GetWidth() + 2 * margin + itemplotter.getFineWidthAdj();
768
769 aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) );
770
771 if( track->Type() == PCB_ARC_T )
772 {
773 const PCB_ARC* arc = static_cast<const PCB_ARC*>( track );
774
775 // Too small arcs cannot be really handled: arc center (and arc radius)
776 // cannot be safely computed
777 if( !arc->IsDegenerated( 10 /* in IU */ ) )
778 {
779 aPlotter->ThickArc( arc->GetCenter(), arc->GetArcAngleStart(), arc->GetAngle(),
780 arc->GetRadius(), width, getMetadata() );
781 }
782 else
783 {
784 // Approximate this very small arc by a segment.
785 aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, getMetadata() );
786 }
787 }
788 else
789 {
790 aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, getMetadata() );
791 }
792 }
793
794 aPlotter->EndBlock( nullptr );
795
796 // Plot filled ares
797 aPlotter->StartBlock( nullptr );
798
799 NETINFO_ITEM nonet( aBoard );
800
801 for( const ZONE* zone : aBoard->Zones() )
802 {
803 if( zone->GetIsRuleArea() )
804 continue;
805
806 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
807 {
808 if( !aLayerMask[layer] )
809 continue;
810
811 SHAPE_POLY_SET mainArea = zone->GetFilledPolysList( layer )->CloneDropTriangulation();
812 SHAPE_POLY_SET islands;
813
814 for( int i = mainArea.OutlineCount() - 1; i >= 0; i-- )
815 {
816 if( zone->IsIsland( layer, i ) )
817 {
818 islands.AddOutline( mainArea.CPolygon( i )[0] );
819 mainArea.DeletePolygon( i );
820 }
821 }
822
823 itemplotter.PlotZone( zone, layer, mainArea );
824
825 if( !islands.IsEmpty() )
826 {
827 ZONE dummy( *zone );
828 dummy.SetNet( &nonet );
829 itemplotter.PlotZone( &dummy, layer, islands );
830 }
831 }
832 }
833
834 aPlotter->EndBlock( nullptr );
835}
836
837
841void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMask,
842 const PCB_PLOT_PARAMS& aPlotOpt )
843{
844 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
845 itemplotter.SetLayerSet( aLayerMask );
846
847 int smallDrill = pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize );
848
849 SHAPE_POLY_SET outlines;
850
851 for( PCB_LAYER_ID layer : aLayerMask.Seq( aLayerMask.SeqStackupForPlotting() ) )
852 {
853 outlines.RemoveAllContours();
854 aBoard->ConvertBrdLayerToPolygonalContours( layer, outlines );
855
856 outlines.Simplify();
857
858 // Plot outlines
859 std::vector<VECTOR2I> cornerList;
860
861 // Now we have one or more basic polygons: plot each polygon
862 for( int ii = 0; ii < outlines.OutlineCount(); ii++ )
863 {
864 for( int kk = 0; kk <= outlines.HoleCount(ii); kk++ )
865 {
866 cornerList.clear();
867 const SHAPE_LINE_CHAIN& path = ( kk == 0 ) ? outlines.COutline( ii )
868 : outlines.CHole( ii, kk - 1 );
869
871 }
872 }
873
874 // Plot pad holes
876 {
877 for( FOOTPRINT* footprint : aBoard->Footprints() )
878 {
879 for( PAD* pad : footprint->Pads() )
880 {
881 if( pad->HasHole() )
882 {
883 if( pad->GetDrillSizeX() == pad->GetDrillSizeY() )
884 {
885 int drill = pad->GetDrillSizeX();
886
888 drill = std::min( smallDrill, drill );
889
890 aPlotter->ThickCircle( pad->ShapePos( layer ), drill,
892 }
893 else
894 {
895 // Note: small drill marks have no significance when applied to slots
896
897 aPlotter->ThickOval( pad->ShapePos( layer ), pad->GetSize( layer ),
898 pad->GetOrientation(), PLOTTER::USE_DEFAULT_LINE_WIDTH,
899 nullptr );
900 }
901 }
902 }
903 }
904 }
905
906 // Plot vias holes
907 for( PCB_TRACK* track : aBoard->Tracks() )
908 {
909 if( track->Type() != PCB_VIA_T )
910 continue;
911
912 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
913
914 if( via->GetLayerSet().Contains( layer ) ) // via holes can be not through holes
915 {
916 aPlotter->Circle( via->GetPosition(), via->GetDrillValue(), FILL_T::NO_FILL,
918 }
919 }
920 }
921}
922
923
927void GenerateLayerPoly( SHAPE_POLY_SET* aResult, BOARD *aBoard, PCB_LAYER_ID aLayer,
928 bool aPlotFPText, bool aPlotReferences, bool aPlotValues )
929{
930 int maxError = aBoard->GetDesignSettings().m_MaxError;
931 SHAPE_POLY_SET buffer;
932 int inflate = 0;
933
934 if( aLayer == F_Mask || aLayer == B_Mask )
935 {
936 // We remove 1nm as we expand both sides of the shapes, so allowing for a strictly greater
937 // than or equal comparison in the shape separation (boolean add)
938 inflate = aBoard->GetDesignSettings().m_SolderMaskMinWidth / 2 - 1;
939 }
940
941 // Build polygons for each pad shape. The size of the shape on solder mask should be size
942 // of pad + clearance around the pad, where clearance = solder mask clearance + extra margin.
943 // Extra margin is half the min width for solder mask, which is used to merge too-close shapes
944 // (distance < SolderMaskMinWidth).
945
946 // Will contain exact shapes of all items on solder mask. We add this back in at the end just
947 // to make sure that any artefacts introduced by the inflate/deflate don't remove parts of the
948 // individual shapes.
949 SHAPE_POLY_SET exactPolys;
950
951 auto handleFPTextItem =
952 [&]( const PCB_TEXT& aText )
953 {
954 if( !aPlotFPText )
955 return;
956
957 if( aText.GetText() == wxT( "${REFERENCE}" ) && !aPlotReferences )
958 return;
959
960 if( aText.GetText() == wxT( "${VALUE}" ) && !aPlotValues )
961 return;
962
963 if( inflate != 0 )
964 aText.TransformTextToPolySet( exactPolys, 0, maxError, ERROR_OUTSIDE );
965
966 aText.TransformTextToPolySet( *aResult, inflate, maxError, ERROR_OUTSIDE );
967 };
968
969 // Generate polygons with arcs inside the shape or exact shape to minimize shape changes
970 // created by arc to segment size correction.
972 {
973 // Plot footprint pads and graphics
974 for( const FOOTPRINT* footprint : aBoard->Footprints() )
975 {
976 if( inflate != 0 )
977 footprint->TransformPadsToPolySet( exactPolys, aLayer, 0, maxError, ERROR_OUTSIDE );
978
979 footprint->TransformPadsToPolySet( *aResult, aLayer, inflate, maxError, ERROR_OUTSIDE );
980
981 for( const PCB_FIELD* field : footprint->GetFields() )
982 {
983 if( field->IsReference() && !aPlotReferences )
984 continue;
985
986 if( field->IsValue() && !aPlotValues )
987 continue;
988
989 if( field->IsVisible() && field->IsOnLayer( aLayer ) )
990 handleFPTextItem( static_cast<const PCB_TEXT&>( *field ) );
991 }
992
993 for( const BOARD_ITEM* item : footprint->GraphicalItems() )
994 {
995 if( item->IsOnLayer( aLayer ) )
996 {
997 if( item->Type() == PCB_TEXT_T )
998 {
999 handleFPTextItem( static_cast<const PCB_TEXT&>( *item ) );
1000 }
1001 else
1002 {
1003 if( inflate != 0 )
1004 item->TransformShapeToPolySet( exactPolys, aLayer, 0, maxError, ERROR_OUTSIDE );
1005
1006 item->TransformShapeToPolySet( *aResult, aLayer, inflate, maxError, ERROR_OUTSIDE );
1007 }
1008 }
1009 }
1010 }
1011
1012 // Plot untented vias and tracks
1013 for( const PCB_TRACK* track : aBoard->Tracks() )
1014 {
1015 // Note: IsOnLayer() checks relevant mask layers of untented vias and tracks
1016 if( !track->IsOnLayer( aLayer ) )
1017 continue;
1018
1019 int clearance = track->GetSolderMaskExpansion();
1020
1021 if( inflate != 0 )
1022 track->TransformShapeToPolygon( exactPolys, aLayer, clearance, maxError, ERROR_OUTSIDE );
1023
1024 track->TransformShapeToPolygon( *aResult, aLayer, clearance + inflate, maxError, ERROR_OUTSIDE );
1025 }
1026
1027 for( const BOARD_ITEM* item : aBoard->Drawings() )
1028 {
1029 if( item->IsOnLayer( aLayer ) )
1030 {
1031 if( item->Type() == PCB_TEXT_T )
1032 {
1033 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( item );
1034
1035 if( inflate != 0 )
1036 text->TransformTextToPolySet( exactPolys, 0, maxError, ERROR_OUTSIDE );
1037
1038 text->TransformTextToPolySet( *aResult, inflate, maxError, ERROR_OUTSIDE );
1039 }
1040 else
1041 {
1042 if( inflate != 0 )
1043 item->TransformShapeToPolygon( exactPolys, aLayer, 0, maxError, ERROR_OUTSIDE );
1044
1045 item->TransformShapeToPolygon( *aResult, aLayer, inflate, maxError, ERROR_OUTSIDE );
1046 }
1047 }
1048 }
1049
1050 // Add filled zone areas.
1051 for( ZONE* zone : aBoard->Zones() )
1052 {
1053 if( zone->GetIsRuleArea() )
1054 continue;
1055
1056 if( !zone->IsOnLayer( aLayer ) )
1057 continue;
1058
1059 SHAPE_POLY_SET area = *zone->GetFill( aLayer );
1060
1061 if( inflate != 0 )
1062 exactPolys.Append( area );
1063
1064 area.Inflate( inflate, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
1065 aResult->Append( area );
1066 }
1067 }
1068
1069 // Merge all polygons
1070 aResult->Simplify();
1071
1072 if( inflate != 0 )
1073 {
1074 aResult->Deflate( inflate, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
1075 // Add back in the exact polys. This is mandatory because inflate/deflate transform is
1076 // not perfect, and we want the initial areas perfectly kept.
1077 aResult->BooleanAdd( exactPolys );
1078 }
1079#undef ERROR
1080}
1081
1082
1089static void initializePlotter( PLOTTER* aPlotter, const BOARD* aBoard, const PCB_PLOT_PARAMS* aPlotOpts )
1090{
1091 PAGE_INFO pageA4( wxT( "A4" ) );
1092 const PAGE_INFO& pageInfo = aBoard->GetPageSettings();
1093 const PAGE_INFO* sheet_info;
1094 double paperscale; // Page-to-paper ratio
1095 VECTOR2I paperSizeIU;
1096 VECTOR2I pageSizeIU( pageInfo.GetSizeIU( pcbIUScale.IU_PER_MILS ) );
1097 bool autocenter = false;
1098
1099 // Special options: to fit the sheet to an A4 sheet replace the paper size. However there
1100 // is a difference between the autoscale and the a4paper option:
1101 // - Autoscale fits the board to the paper size
1102 // - A4paper fits the original paper size to an A4 sheet
1103 // - Both of them fit the board to an A4 sheet
1104 if( aPlotOpts->GetA4Output() )
1105 {
1106 sheet_info = &pageA4;
1107 paperSizeIU = pageA4.GetSizeIU( pcbIUScale.IU_PER_MILS );
1108 paperscale = (double) paperSizeIU.x / pageSizeIU.x;
1109 autocenter = true;
1110 }
1111 else
1112 {
1113 sheet_info = &pageInfo;
1114 paperSizeIU = pageSizeIU;
1115 paperscale = 1;
1116
1117 // Need autocentering only if scale is not 1:1
1118 autocenter = (aPlotOpts->GetScale() != 1.0) || aPlotOpts->GetAutoScale();
1119 }
1120
1121 BOX2I bbox = aBoard->ComputeBoundingBox( false );
1122 VECTOR2I boardCenter = bbox.Centre();
1123 VECTOR2I boardSize = bbox.GetSize();
1124
1125 double compound_scale;
1126
1127 // Fit to 80% of the page if asked; it could be that the board is empty, in this case
1128 // regress to 1:1 scale
1129 if( aPlotOpts->GetAutoScale() && boardSize.x > 0 && boardSize.y > 0 )
1130 {
1131 double xscale = (paperSizeIU.x * 0.8) / boardSize.x;
1132 double yscale = (paperSizeIU.y * 0.8) / boardSize.y;
1133
1134 compound_scale = std::min( xscale, yscale ) * paperscale;
1135 }
1136 else
1137 {
1138 compound_scale = aPlotOpts->GetScale() * paperscale;
1139 }
1140
1141 // For the plot offset we have to keep in mind the auxiliary origin too: if autoscaling is
1142 // off we check that plot option (i.e. autoscaling overrides auxiliary origin)
1143 VECTOR2I offset( 0, 0);
1144
1145 if( autocenter )
1146 {
1147 offset.x = KiROUND( boardCenter.x - ( paperSizeIU.x / 2.0 ) / compound_scale );
1148 offset.y = KiROUND( boardCenter.y - ( paperSizeIU.y / 2.0 ) / compound_scale );
1149 }
1150 else
1151 {
1152 if( aPlotOpts->GetUseAuxOrigin() )
1153 offset = aBoard->GetDesignSettings().GetAuxOrigin();
1154 }
1155
1156 aPlotter->SetPageSettings( *sheet_info );
1157
1158 aPlotter->SetViewport( offset, pcbIUScale.IU_PER_MILS/10, compound_scale, aPlotOpts->GetMirror() );
1159
1160 // Has meaning only for gerber plotter. Must be called only after SetViewport
1161 aPlotter->SetGerberCoordinatesFormat( aPlotOpts->GetGerberPrecision() );
1162
1163 // Has meaning only for SVG plotter. Must be called only after SetViewport
1164 aPlotter->SetSvgCoordinatesFormat( aPlotOpts->GetSvgPrecision() );
1165
1166 aPlotter->SetCreator( wxT( "PCBNEW" ) );
1167 aPlotter->SetColorMode( !aPlotOpts->GetBlackAndWhite() ); // default is plot in Black and White.
1168 aPlotter->SetTextMode( aPlotOpts->GetTextMode() );
1169}
1170
1171
1175static void FillNegativeKnockout( PLOTTER *aPlotter, const BOX2I &aBbbox )
1176{
1177 const int margin = 5 * pcbIUScale.IU_PER_MM; // Add a 5 mm margin around the board
1178 aPlotter->SetNegative( true );
1179 aPlotter->SetColor( WHITE ); // Which will be plotted as black
1180
1181 BOX2I area = aBbbox;
1182 area.Inflate( margin );
1183 aPlotter->Rect( area.GetOrigin(), area.GetEnd(), FILL_T::FILLED_SHAPE, 0 );
1184 aPlotter->SetColor( BLACK );
1185}
1186
1187
1188static void plotPdfBackground( BOARD* aBoard, const PCB_PLOT_PARAMS* aPlotOpts, PLOTTER* aPlotter )
1189{
1190 if( aPlotter->GetColorMode()
1191 && aPlotOpts->GetPDFBackgroundColor() != COLOR4D::UNSPECIFIED )
1192 {
1193 aPlotter->SetColor( aPlotOpts->GetPDFBackgroundColor() );
1194
1195 // Use page size selected in pcb to know the schematic bg area
1196 const PAGE_INFO& actualPage = aBoard->GetPageSettings();
1197
1199 actualPage.GetHeightIU( pcbIUScale.IU_PER_MILS ) );
1200
1201 aPlotter->Rect( VECTOR2I( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 );
1202 }
1203}
1204
1205
1212PLOTTER* StartPlotBoard( BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aLayer,
1213 const wxString& aLayerName, const wxString& aFullFileName,
1214 const wxString& aSheetName, const wxString& aSheetPath,
1215 const wxString& aPageName, const wxString& aPageNumber,
1216 const int aPageCount )
1217{
1218 wxCHECK( aBoard && aPlotOpts, nullptr );
1219
1220 // Create the plotter driver and set the few plotter specific options
1221 PLOTTER* plotter = nullptr;
1222
1223 switch( aPlotOpts->GetFormat() )
1224 {
1225 case PLOT_FORMAT::DXF:
1226 DXF_PLOTTER* DXF_plotter;
1227 DXF_plotter = new DXF_PLOTTER();
1228 DXF_plotter->SetUnits( aPlotOpts->GetDXFPlotUnits() );
1229
1230 plotter = DXF_plotter;
1231 break;
1232
1233 case PLOT_FORMAT::POST:
1234 PS_PLOTTER* PS_plotter;
1235 PS_plotter = new PS_PLOTTER();
1236 PS_plotter->SetScaleAdjust( aPlotOpts->GetFineScaleAdjustX(),
1237 aPlotOpts->GetFineScaleAdjustY() );
1238 plotter = PS_plotter;
1239 break;
1240
1241 case PLOT_FORMAT::PDF:
1242 plotter = new PDF_PLOTTER( aBoard->GetProject() );
1243 break;
1244
1245 case PLOT_FORMAT::HPGL:
1246 wxLogError( _( "HPGL plotting is no longer supported as of KiCad 10.0" ) );
1247 return nullptr;
1248
1250 // For Gerber plotter, a valid board layer must be set, in order to create a valid
1251 // Gerber header, especially the TF.FileFunction and .FilePolarity data
1252 if( aLayer < PCBNEW_LAYER_ID_START || aLayer >= PCB_LAYER_ID_COUNT )
1253 {
1254 wxLogError( wxString::Format( "Invalid board layer %d, cannot build a valid Gerber file header",
1255 aLayer ) );
1256 }
1257
1258 plotter = new GERBER_PLOTTER();
1259 break;
1260
1261 case PLOT_FORMAT::SVG:
1262 plotter = new SVG_PLOTTER();
1263 break;
1264
1265 default:
1266 wxASSERT( false );
1267 return nullptr;
1268 }
1269
1271 renderSettings->LoadColors( aPlotOpts->ColorSettings() );
1272 renderSettings->SetDefaultPenWidth( pcbIUScale.mmToIU( 0.0212 ) ); // Hairline at 1200dpi
1273 renderSettings->SetLayerName( aLayerName );
1274
1275 plotter->SetRenderSettings( renderSettings );
1276
1277 // Compute the viewport and set the other options
1278
1279 // page layout is not mirrored, so temporarily change mirror option for the page layout
1280 PCB_PLOT_PARAMS plotOpts = *aPlotOpts;
1281
1282 if( plotOpts.GetPlotFrameRef() )
1283 {
1284 if( plotOpts.GetMirror() )
1285 plotOpts.SetMirror( false );
1286 if( plotOpts.GetScale() != 1.0 )
1287 plotOpts.SetScale( 1.0 );
1288 if( plotOpts.GetAutoScale() )
1289 plotOpts.SetAutoScale( false );
1290 }
1291
1292 initializePlotter( plotter, aBoard, &plotOpts );
1293
1294 if( plotter->OpenFile( aFullFileName ) )
1295 {
1296 plotter->ClearHeaderLinesList();
1297
1298 // For the Gerber "file function" attribute, set the layer number
1299 if( plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1300 {
1301 bool useX2mode = plotOpts.GetUseGerberX2format();
1302
1303 GERBER_PLOTTER* gbrplotter = static_cast <GERBER_PLOTTER*> ( plotter );
1304 gbrplotter->DisableApertMacros( plotOpts.GetDisableGerberMacros() );
1305 gbrplotter->UseX2format( useX2mode );
1306 gbrplotter->UseX2NetAttributes( plotOpts.GetIncludeGerberNetlistInfo() );
1307
1308 // Attributes can be added using X2 format or as comment (X1 format)
1309 AddGerberX2Attribute( plotter, aBoard, aLayer, not useX2mode );
1310 }
1311
1312 bool startPlotSuccess = false;
1313 try
1314 {
1315 if( plotter->GetPlotterType() == PLOT_FORMAT::PDF )
1316 startPlotSuccess = static_cast<PDF_PLOTTER*>( plotter )->StartPlot( aPageNumber, aPageName );
1317 else
1318 startPlotSuccess = plotter->StartPlot( aPageName );
1319 }
1320 catch( ... )
1321 {
1322 startPlotSuccess = false;
1323 }
1324
1325
1326 if( startPlotSuccess )
1327 {
1328 if( aPlotOpts->GetFormat() == PLOT_FORMAT::PDF )
1329 plotPdfBackground( aBoard, aPlotOpts, plotter );
1330
1331 // Plot the frame reference if requested
1332 if( aPlotOpts->GetPlotFrameRef() )
1333 {
1334 PlotDrawingSheet( plotter, aBoard->GetProject(), aBoard->GetTitleBlock(),
1335 aBoard->GetPageSettings(), &aBoard->GetProperties(), aPageNumber,
1336 aPageCount, aSheetName, aSheetPath, aBoard->GetFileName(),
1337 renderSettings->GetLayerColor( LAYER_DRAWINGSHEET ) );
1338
1339 if( aPlotOpts->GetMirror() || aPlotOpts->GetScale() != 1.0 || aPlotOpts->GetAutoScale() )
1340 initializePlotter( plotter, aBoard, aPlotOpts );
1341 }
1342
1343 // When plotting a negative board: draw a black rectangle (background for plot board
1344 // in white) and switch the current color to WHITE; note the color inversion is actually
1345 // done in the driver (if supported)
1346 if( aPlotOpts->GetNegative() )
1347 {
1348 BOX2I bbox = aBoard->ComputeBoundingBox( false );
1349 FillNegativeKnockout( plotter, bbox );
1350 }
1351
1352 return plotter;
1353 }
1354 }
1355
1356 delete plotter->RenderSettings();
1357 delete plotter;
1358 return nullptr;
1359}
1360
1361
1362void setupPlotterNewPDFPage( PLOTTER* aPlotter, BOARD* aBoard, PCB_PLOT_PARAMS* aPlotOpts,
1363 const wxString& aLayerName, const wxString& aSheetName,
1364 const wxString& aSheetPath, const wxString& aPageNumber,
1365 int aPageCount )
1366{
1367 plotPdfBackground( aBoard, aPlotOpts, aPlotter );
1368
1369 aPlotter->RenderSettings()->SetLayerName( aLayerName );
1370
1371 // Plot the frame reference if requested
1372 if( aPlotOpts->GetPlotFrameRef() )
1373 {
1374 // Mirror and scale shouldn't be applied to the drawing sheet
1375 bool revertOps = false;
1376 bool oldMirror = aPlotOpts->GetMirror();
1377 bool oldAutoScale = aPlotOpts->GetAutoScale();
1378 double oldScale = aPlotOpts->GetScale();
1379
1380 if( oldMirror || oldAutoScale || oldScale != 1.0 )
1381 {
1382 aPlotOpts->SetMirror( false );
1383 aPlotOpts->SetScale( 1.0 );
1384 aPlotOpts->SetAutoScale( false );
1385 initializePlotter( aPlotter, aBoard, aPlotOpts );
1386 revertOps = true;
1387 }
1388
1389 PlotDrawingSheet( aPlotter, aBoard->GetProject(), aBoard->GetTitleBlock(),
1390 aBoard->GetPageSettings(), &aBoard->GetProperties(), aPageNumber,
1391 aPageCount,
1392 aSheetName, aSheetPath, aBoard->GetFileName(),
1394
1395 if( revertOps )
1396 {
1397 aPlotOpts->SetMirror( oldMirror );
1398 aPlotOpts->SetScale( oldScale );
1399 aPlotOpts->SetAutoScale( oldAutoScale );
1400 initializePlotter( aPlotter, aBoard, aPlotOpts );
1401 }
1402 }
1403}
int color
Definition: DXF_plotter.cpp:63
@ ERROR_OUTSIDE
Definition: approximation.h:33
@ ERROR_INSIDE
Definition: approximation.h:34
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:112
@ 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:79
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:317
const PAGE_INFO & GetPageSettings() const
Definition: board.h:742
const ZONES & Zones() const
Definition: board.h:362
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:3008
TITLE_BLOCK & GetTitleBlock()
Definition: board.h:748
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1851
const std::map< wxString, wxString > & GetProperties() const
Definition: board.h:393
const FOOTPRINTS & Footprints() const
Definition: board.h:358
const TRACKS & Tracks() const
Definition: board.h:356
const wxString & GetFileName() const
Definition: board.h:354
PROJECT * GetProject() const
Definition: board.h:538
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:1024
const DRAWINGS & Drawings() const
Definition: board.h:360
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, bool aSketchMode)
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:215
void SetNetName(const wxString &aNetname)
Definition: gbr_metadata.h:247
void SetApertureAttrib(GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB aApertAttribute)
Definition: gbr_metadata.h:219
GBR_NETLIST_METADATA m_NetlistMetadata
An item to handle object attribute.
Definition: gbr_metadata.h:280
void SetNetAttribType(int aNetAttribType)
Definition: gbr_metadata.h:237
@ 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.
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:80
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:387
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:296
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition: lset.cpp:591
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
int GetHeightIU(double aIUScale) const
Gets the page height in IU.
Definition: page_info.h:162
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition: page_info.h:171
int GetWidthIU(double aIUScale) const
Gets the page width in IU.
Definition: page_info.h:153
bool IsDegenerated(int aThreshold=5) const
Definition: pcb_track.cpp:2176
EDA_ANGLE GetArcAngleStart() const
Definition: pcb_track.cpp:2158
double GetRadius() const
Definition: pcb_track.cpp:2141
EDA_ANGLE GetAngle() const
Definition: pcb_track.cpp:2148
virtual VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_track.h:352
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
bool GetCrossoutDNPFPsOnFabLayers() const
void SetDXFPlotPolygonMode(bool aFlag)
void SetAutoScale(bool aFlag)
unsigned GetSvgPrecision() const
double GetScale() const
PLOT_TEXT_MODE GetTextMode() const override
bool GetDXFPlotPolygonMode() const
bool GetPlotReference() const
bool m_PDFFrontFPPropertyPopups
Generate PDF property popup menus for footprints.
void SetScale(double aVal)
void SetMirror(bool aFlag)
bool GetSketchPadsOnFabLayers() const
bool GetSubtractMaskFromSilk() const
int GetGerberPrecision() const
double GetFineScaleAdjustY() const
bool GetPlotPadNumbers() const
bool GetA4Output() const
DRILL_MARKS GetDrillMarksType() const
bool GetUseGerberX2format() const
bool GetPlotValue() const
bool GetIncludeGerberNetlistInfo() const
double GetFineScaleAdjustX() const
bool GetBlackAndWhite() const
bool m_PDFBackFPPropertyPopups
on front and/or back of board
bool GetPlotFPText() const
bool GetPlotFrameRef() const
COLOR4D GetPDFBackgroundColor() const
bool GetDisableGerberMacros() const
COLOR_SETTINGS * ColorSettings() const
Base plotter engine class.
Definition: plotter.h:121
virtual void Circle(const VECTOR2I &pos, int diametre, FILL_T fill, int 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:141
virtual void SetSvgCoordinatesFormat(unsigned aPrecision)
Set the number of digits for mantissa in coordinates in mm for SVG plotter.
Definition: plotter.h:532
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: plotter.h:154
void SetRenderSettings(RENDER_SETTINGS *aSettings)
Definition: plotter.h:151
static const int USE_DEFAULT_LINE_WIDTH
Definition: plotter.h:125
virtual void ThickOval(const VECTOR2I &aPos, const VECTOR2I &aSize, const EDA_ANGLE &aOrient, int aWidth, void *aData)
Definition: plotter.cpp:485
virtual bool StartPlot(const wxString &aPageNumber)=0
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width)=0
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:152
virtual void SetGerberCoordinatesFormat(int aResolution, bool aUseInches=false)
Definition: plotter.h:526
virtual void Bookmark(const BOX2I &aBox, const wxString &aName, const wxString &aGroupName=wxEmptyString)
Create a bookmark to a symbol.
Definition: plotter.h:482
virtual PLOT_FORMAT GetPlotterType() const =0
Return the effective plot engine in use.
virtual void ThickArc(const EDA_SHAPE &aArcShape, void *aData, int aWidth)
Definition: plotter.cpp:560
virtual void SetTextMode(PLOT_TEXT_MODE mode)
Change the current text mode.
Definition: plotter.h:521
virtual void SetCreator(const wxString &aCreator)
Definition: plotter.h:173
VECTOR2I GetPlotOffsetUserUnits()
Definition: plotter.h:558
void ClearHeaderLinesList()
Remove all lines from the list of free lines to print at the beginning of the file.
Definition: plotter.h:191
bool GetColorMode() const
Definition: plotter.h:149
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:148
virtual void StartBlock(void *aData)
calling this function allows one to define the beginning of a group of drawing items,...
Definition: plotter.h:544
virtual void ThickSegment(const VECTOR2I &start, const VECTOR2I &end, int width, void *aData)
Definition: plotter.cpp:538
virtual void PlotPoly(const std::vector< VECTOR2I > &aCornerList, FILL_T aFill, int aWidth, void *aData)=0
Draw a polygon ( filled or not ).
virtual void FlashPadCircle(const VECTOR2I &aPadPos, int aDiameter, void *aData)=0
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition: plotter.h:471
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:511
virtual void ThickCircle(const VECTOR2I &pos, int diametre, int width, void *aData)
Definition: plotter.cpp:591
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:553
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...
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
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
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
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:505
@ 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:411
@ FILLED_SHAPE
Fill with object color.
Handle special data (items attributes) during plot.
a few functions useful in geometry calculations.
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:665
@ 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
@ 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
@ 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.
void PlotPolySet(BOARD *aBoard, PLOTTER *aPlotter, const PCB_PLOT_PARAMS &aPlotOpt, SHAPE_POLY_SET *aPolySet, PCB_LAYER_ID aLayer)
void setupPlotterNewPDFPage(PLOTTER *aPlotter, BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts, const wxString &aLayerName, const wxString &aSheetName, const wxString &aSheetPath, const wxString &aPageNumber, int aPageCount)
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 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.
static void plotPdfBackground(BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, PLOTTER *aPlotter)
#define getMetadata()
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:92
VECTOR2I end
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