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
49void GenerateLayerPoly( SHAPE_POLY_SET* aResult, BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
50 bool aPlotFPText, bool aPlotReferences, bool aPlotValues );
51
52
53void PlotLayer( BOARD* aBoard, PLOTTER* aPlotter, const LSET& layerMask,
54 const PCB_PLOT_PARAMS& plotOpts )
55{
56 // PlotLayerOutlines() is designed only for DXF plotters.
57 if( plotOpts.GetFormat() == PLOT_FORMAT::DXF && plotOpts.GetDXFPlotPolygonMode() )
58 PlotLayerOutlines( aBoard, aPlotter, layerMask, plotOpts );
59 else
60 PlotStandardLayer( aBoard, aPlotter, layerMask, plotOpts );
61};
62
63
64void PlotPolySet( BOARD* aBoard, PLOTTER* aPlotter, const PCB_PLOT_PARAMS& aPlotOpt,
65 SHAPE_POLY_SET* aPolySet, PCB_LAYER_ID aLayer )
66{
67 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
68 LSET layers = { aLayer };
69
70 itemplotter.SetLayerSet( layers );
71
72 // To avoid a lot of code, use a ZONE to handle and plot polygons, because our polygons look
73 // exactly like filled areas in zones.
74 // Note, also this code is not optimized: it creates a lot of copy/duplicate data.
75 // However it is not complex, and fast enough for plot purposes (copy/convert data is only a
76 // very small calculation time for these calculations).
77 ZONE zone( aBoard );
78 zone.SetMinThickness( 0 );
79 zone.SetLayer( aLayer );
80
81 aPolySet->Fracture();
82 itemplotter.PlotZone( &zone, aLayer, *aPolySet );
83}
84
85
92void PlotSolderMaskLayer( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMask,
93 const PCB_PLOT_PARAMS& aPlotOpt )
94{
95 if( aBoard->GetDesignSettings().m_SolderMaskMinWidth == 0 )
96 {
97 PlotLayer( aBoard, aPlotter, aLayerMask, aPlotOpt );
98 return;
99 }
100
101 SHAPE_POLY_SET solderMask;
102 PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask;
103
104 GenerateLayerPoly( &solderMask, aBoard, aPlotter, layer, aPlotOpt.GetPlotFPText(),
105 aPlotOpt.GetPlotReference(), aPlotOpt.GetPlotValue() );
106
107 PlotPolySet( aBoard, aPlotter, aPlotOpt, &solderMask, layer );
108}
109
110
111void PlotClippedSilkLayer( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMask,
112 const PCB_PLOT_PARAMS& aPlotOpt )
113{
114 SHAPE_POLY_SET silkscreen, solderMask;
115 PCB_LAYER_ID silkLayer = aLayerMask[F_SilkS] ? F_SilkS : B_SilkS;
116 PCB_LAYER_ID maskLayer = aLayerMask[F_SilkS] ? F_Mask : B_Mask;
117
118 GenerateLayerPoly( &silkscreen, aBoard, aPlotter, silkLayer, aPlotOpt.GetPlotFPText(),
119 aPlotOpt.GetPlotReference(), aPlotOpt.GetPlotValue() );
120 GenerateLayerPoly( &solderMask, aBoard, aPlotter, maskLayer, aPlotOpt.GetPlotFPText(),
121 aPlotOpt.GetPlotReference(), aPlotOpt.GetPlotValue() );
122
123 silkscreen.BooleanSubtract( solderMask );
124 PlotPolySet( aBoard, aPlotter, aPlotOpt, &silkscreen, silkLayer );
125}
126
127
128void PlotBoardLayers( BOARD* aBoard, PLOTTER* aPlotter, const LSEQ& aLayers,
129 const PCB_PLOT_PARAMS& aPlotOptions )
130{
131 if( !aBoard || !aPlotter || aLayers.empty() )
132 return;
133
134 for( PCB_LAYER_ID layer : aLayers )
135 PlotOneBoardLayer( aBoard, aPlotter, layer, aPlotOptions, layer == aLayers[0] );
136
137 // Drill marks are plotted in white to knockout the pad if any layers of the pad are
138 // being plotted, and in black if the pad is not being plotted. For the former, this
139 // must happen after all other layers are plotted.
140 if( aPlotOptions.GetDrillMarksType() != DRILL_MARKS::NO_DRILL_SHAPE )
141 {
142 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOptions );
143 itemplotter.SetLayerSet( aLayers );
144 itemplotter.PlotDrillMarks();
145 }
146}
147
148
149void PlotInteractiveLayer( BOARD* aBoard, PLOTTER* aPlotter, const PCB_PLOT_PARAMS& aPlotOpt )
150{
151 for( const FOOTPRINT* fp : aBoard->Footprints() )
152 {
153 if( fp->GetLayer() == F_Cu && !aPlotOpt.m_PDFFrontFPPropertyPopups )
154 continue;
155
156 if( fp->GetLayer() == B_Cu && !aPlotOpt.m_PDFBackFPPropertyPopups )
157 continue;
158
159 std::vector<wxString> properties;
160
161 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
162 _( "Reference designator" ),
163 fp->Reference().GetShownText( false ) ) );
164
165 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
166 _( "Value" ),
167 fp->Value().GetShownText( false ) ) );
168
169 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
170 _( "Footprint" ),
171 fp->GetFPID().GetUniStringLibItemName() ) );
172
173 for( const PCB_FIELD* field : fp->GetFields() )
174 {
175 if( field->IsReference() || field->IsValue() )
176 continue;
177
178 if( field->GetText().IsEmpty() )
179 continue;
180
181 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
182 field->GetName(),
183 field->GetText() ) );
184 }
185
186 // These 2 properties are not very useful in a plot file (like a PDF)
187#if 0
188 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Library Description" ),
189 fp->GetLibDescription() ) );
190
191 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Keywords" ),
192 fp->GetKeywords() ) );
193#endif
194 // Draw items are plotted with a position offset. So we need to move
195 // our boxes (which are not plotted) by the same offset.
196 VECTOR2I offset = -aPlotter->GetPlotOffsetUserUnits();
197
198 // Use a footprint bbox without texts to create the hyperlink area
199 BOX2I bbox = fp->GetBoundingBox( false );
200 bbox.Move( offset );
201 aPlotter->HyperlinkMenu( bbox, properties );
202
203 // Use a footprint bbox with visible texts only to create the bookmark area
204 // which is the area to zoom on ft selection
205 // However the bbox need to be inflated for a better look.
206 bbox = fp->GetBoundingBox( true );
207 bbox.Move( offset );
208 bbox.Inflate( bbox.GetWidth() /2, bbox.GetHeight() /2 );
209 aPlotter->Bookmark( bbox, fp->GetReference(), _( "Footprints" ) );
210 }
211}
212
213
214void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
215 const PCB_PLOT_PARAMS& aPlotOpt, bool isPrimaryLayer )
216{
217 PCB_PLOT_PARAMS plotOpt = aPlotOpt;
218
219 // Set a default color and the text mode for this layer
220 aPlotter->SetColor( BLACK );
221 aPlotter->SetTextMode( aPlotOpt.GetTextMode() );
222
223 // Specify that the contents of the "Edges Pcb" layer are to be plotted in addition to the
224 // contents of the currently specified layer.
225 LSET layer_mask( { aLayer } );
226
227 if( IsCopperLayer( aLayer ) )
228 {
229 // Skip NPTH pads on copper layers ( only if hole size == pad size ):
230 // Drill mark will be plotted if drill mark is SMALL_DRILL_SHAPE or FULL_DRILL_SHAPE
231 if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
232 plotOpt.SetDXFPlotPolygonMode( true );
233 else
234 plotOpt.SetSkipPlotNPTH_Pads( true );
235
236 PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
237 }
238 else
239 {
240 switch( aLayer )
241 {
242 case B_Mask:
243 case F_Mask:
244 // Use outline mode for DXF
245 plotOpt.SetDXFPlotPolygonMode( true );
246
247 // Plot solder mask:
248 PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt );
249
250 break;
251
252 case B_Adhes:
253 case F_Adhes:
254 case B_Paste:
255 case F_Paste:
256 // Disable plot pad holes
258
259 // Use outline mode for DXF
260 plotOpt.SetDXFPlotPolygonMode( true );
261
262 PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
263
264 break;
265
266 case F_SilkS:
267 case B_SilkS:
268 if( plotOpt.GetSubtractMaskFromSilk() )
269 {
270 if( aPlotter->GetPlotterType() == PLOT_FORMAT::GERBER && isPrimaryLayer )
271 {
272 // Use old-school, positive/negative mask plotting which preserves utilization
273 // of Gerber aperture masks. This method can only be used when the given silk
274 // layer is the primary layer as the negative mask will also knockout any other
275 // (non-silk) layers that were plotted before the silk layer.
276
277 PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
278
279 // Create the mask to subtract by creating a negative layer polarity
280 aPlotter->SetLayerPolarity( false );
281
282 // Disable plot pad holes
284
285 // Plot the mask
286 layer_mask = ( aLayer == F_SilkS ) ? LSET( { F_Mask } ) : LSET( { B_Mask } );
287 PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt );
288
289 // Disable the negative polarity
290 aPlotter->SetLayerPolarity( true );
291 }
292 else
293 {
294 PlotClippedSilkLayer( aBoard, aPlotter, layer_mask, plotOpt );
295 }
296
297 break;
298 }
299
300 PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
301 break;
302
303 case Dwgs_User:
304 case Cmts_User:
305 case Eco1_User:
306 case Eco2_User:
307 case Edge_Cuts:
308 case Margin:
309 case F_CrtYd:
310 case B_CrtYd:
311 case F_Fab:
312 case B_Fab:
313 default:
314 PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
315 break;
316 }
317 }
318}
319
320
324void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMask,
325 const PCB_PLOT_PARAMS& aPlotOpt )
326{
327 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
328 int maxError = aBoard->GetDesignSettings().m_MaxError;
329
330 itemplotter.SetLayerSet( aLayerMask );
331
332 bool onCopperLayer = ( LSET::AllCuMask() & aLayerMask ).any();
333 bool onSolderMaskLayer = ( LSET( { F_Mask, B_Mask } ) & aLayerMask ).any();
334 bool onSolderPasteLayer = ( LSET( { F_Paste, B_Paste } ) & aLayerMask ).any();
335 bool onFrontFab = ( LSET( { F_Fab } ) & aLayerMask ).any();
336 bool onBackFab = ( LSET( { B_Fab } ) & aLayerMask ).any();
337 bool sketchPads = ( onFrontFab || onBackFab ) && aPlotOpt.GetSketchPadsOnFabLayers();
338
339 // Plot edge layer and graphic items
340 for( const BOARD_ITEM* item : aBoard->Drawings() )
341 itemplotter.PlotBoardGraphicItem( item );
342
343 // Draw footprint texts:
344 for( const FOOTPRINT* footprint : aBoard->Footprints() )
345 itemplotter.PlotFootprintTextItems( footprint );
346
347 // Draw footprint other graphic items:
348 for( const FOOTPRINT* footprint : aBoard->Footprints() )
349 itemplotter.PlotFootprintGraphicItems( footprint );
350
351 // Plot footprint pads
352 for( FOOTPRINT* footprint : aBoard->Footprints() )
353 {
354 aPlotter->StartBlock( nullptr );
355
356 for( PAD* pad : footprint->Pads() )
357 {
358 bool doSketchPads = false;
359
360 if( !( pad->GetLayerSet() & aLayerMask ).any() )
361 {
362 if( sketchPads && ( ( onFrontFab && pad->GetLayerSet().Contains( F_Cu ) )
363 || ( onBackFab && pad->GetLayerSet().Contains( B_Cu ) ) ) )
364 {
365 doSketchPads = true;
366 }
367 else
368 {
369 continue;
370 }
371 }
372
373 if( onCopperLayer && !pad->IsOnCopperLayer() )
374 continue;
375
377 if( onCopperLayer && !pad->FlashLayer( aLayerMask ) )
378 continue;
379
380 // TODO(JE) padstacks - different behavior for single layer or multilayer
381
382 COLOR4D color = COLOR4D::BLACK;
383
384 // If we're plotting a single layer, the color for that layer can be used directly.
385 if( aLayerMask.count() == 1 )
386 {
387 color = aPlotOpt.ColorSettings()->GetColor( aLayerMask.Seq()[0] );
388 }
389 else
390 {
391 if( ( pad->GetLayerSet() & aLayerMask )[B_Cu] )
392 color = aPlotOpt.ColorSettings()->GetColor( B_Cu );
393
394 if( ( pad->GetLayerSet() & aLayerMask )[F_Cu] )
395 color = color.LegacyMix( aPlotOpt.ColorSettings()->GetColor( F_Cu ) );
396
397 if( sketchPads && aLayerMask[F_Fab] )
398 color = aPlotOpt.ColorSettings()->GetColor( F_Fab );
399 else if( sketchPads && aLayerMask[B_Fab] )
400 color = aPlotOpt.ColorSettings()->GetColor( B_Fab );
401 }
402
403 if( sketchPads && ( ( onFrontFab && pad->GetLayerSet().Contains( F_Cu ) )
404 || ( onBackFab && pad->GetLayerSet().Contains( B_Cu ) ) ) )
405 {
406 if( aPlotOpt.GetPlotPadNumbers() )
407 itemplotter.PlotPadNumber( pad, color );
408 }
409
410 auto plotPadLayer =
411 [&]( PCB_LAYER_ID aLayer )
412 {
413 VECTOR2I margin;
414 int width_adj = 0;
415
416 if( onCopperLayer )
417 width_adj = itemplotter.getFineWidthAdj();
418
419 if( onSolderMaskLayer )
420 margin.x = margin.y = pad->GetSolderMaskExpansion( aLayer );
421
422 if( onSolderPasteLayer )
423 margin = pad->GetSolderPasteMargin( aLayer );
424
425 // not all shapes can have a different margin for x and y axis
426 // in fact only oval and rect shapes can have different values.
427 // Round shape have always the same x,y margin
428 // so define a unique value for other shapes that do not support different values
429 int mask_clearance = margin.x;
430 // When clearance is same for x and y pad axis, calculations are more easy
431 bool sameXYClearance = margin.x == margin.y;
432
433 // Now offset the pad size by margin + width_adj
434 VECTOR2I padPlotsSize = pad->GetSize( aLayer ) + margin * 2 + VECTOR2I( width_adj, width_adj );
435
436 // Store these parameters that can be modified to plot inflated/deflated pads shape
437 PAD_SHAPE padShape = pad->GetShape( aLayer );
438 VECTOR2I padSize = pad->GetSize( aLayer );
439 VECTOR2I padDelta = pad->GetDelta( aLayer ); // has meaning only for trapezoidal pads
440 // CornerRadius and CornerRadiusRatio can be modified
441 // the radius is built from the ratio, so saving/restoring the ratio is enough
442 double padCornerRadiusRatio = pad->GetRoundRectRadiusRatio( aLayer );
443
444 // Don't draw a 0 sized pad.
445 // Note: a custom pad can have its pad anchor with size = 0
446 if( padShape != PAD_SHAPE::CUSTOM
447 && ( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 ) )
448 {
449 return;
450 }
451
452 switch( padShape )
453 {
455 case PAD_SHAPE::OVAL:
456 pad->SetSize( aLayer, padPlotsSize );
457
458 if( aPlotOpt.GetSkipPlotNPTH_Pads() &&
460 ( pad->GetSize(aLayer ) == pad->GetDrillSize() ) &&
461 ( pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
462 {
463 break;
464 }
465
466 itemplotter.PlotPad( pad, aLayer, color, doSketchPads );
467 break;
468
470 pad->SetSize( aLayer, padPlotsSize );
471
472 if( mask_clearance > 0 )
473 {
474 pad->SetShape( aLayer, PAD_SHAPE::ROUNDRECT );
475 pad->SetRoundRectCornerRadius( aLayer, mask_clearance );
476 }
477
478 itemplotter.PlotPad( pad, aLayer, color, doSketchPads );
479 break;
480
482 // inflate/deflate a trapezoid is a bit complex.
483 // so if the margin is not null, build a similar polygonal pad shape,
484 // and inflate/deflate the polygonal shape
485 // because inflating/deflating using different values for y and y
486 // we are using only margin.x as inflate/deflate value
487 if( mask_clearance == 0 )
488 {
489 itemplotter.PlotPad( pad, aLayer, color, doSketchPads );
490 }
491 else
492 {
493 PAD dummy( *pad );
494 dummy.SetAnchorPadShape( aLayer, PAD_SHAPE::CIRCLE );
495 dummy.SetShape( aLayer, PAD_SHAPE::CUSTOM );
496 SHAPE_POLY_SET outline;
497 outline.NewOutline();
498 int dx = padSize.x / 2;
499 int dy = padSize.y / 2;
500 int ddx = padDelta.x / 2;
501 int ddy = padDelta.y / 2;
502
503 outline.Append( -dx - ddy, dy + ddx );
504 outline.Append( dx + ddy, dy - ddx );
505 outline.Append( dx - ddy, -dy + ddx );
506 outline.Append( -dx + ddy, -dy - ddx );
507
508 // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
509 // which can create bad shapes if margin.x is < 0
511 maxError );
512 dummy.DeletePrimitivesList();
513 dummy.AddPrimitivePoly( aLayer, outline, 0, true );
514
515 // Be sure the anchor pad is not bigger than the deflated shape because this
516 // anchor will be added to the pad shape when plotting the pad. So now the
517 // polygonal shape is built, we can clamp the anchor size
518 dummy.SetSize( aLayer, VECTOR2I( 0, 0 ) );
519
520 itemplotter.PlotPad( &dummy, aLayer, color, doSketchPads );
521 }
522
523 break;
524
526 {
527 // rounding is stored as a percent, but we have to update this ratio
528 // to force recalculation of other values after size changing (we do not
529 // really change the rounding percent value)
530 double radius_ratio = pad->GetRoundRectRadiusRatio( aLayer );
531 pad->SetSize( aLayer, padPlotsSize );
532 pad->SetRoundRectRadiusRatio( aLayer, radius_ratio );
533
534 itemplotter.PlotPad( pad, aLayer, color, doSketchPads );
535 break;
536 }
537
539 // for smaller/same rect size than initial shape (i.e. mask_clearance <= 0)
540 // use the rect with size set to padPlotsSize. It gives a good shape
541 if( mask_clearance <= 0 )
542 {
543 // the size can be slightly inflated by width_adj (PS/PDF only)
544 pad->SetSize( aLayer, padPlotsSize );
545 itemplotter.PlotPad( pad, aLayer, color, doSketchPads );
546 }
547 else
548 {
549 // Due to the polygonal shape of a CHAMFERED_RECT pad, the best way is to
550 // convert the pad shape to a full polygon and inflate it
551 // and use a dummy CUSTOM pad to plot the final shape.
552 // However one can inflate polygon only if X,Y has same inflate value
553 // if not the case, just use a rectangle having the padPlotsSize new size
554 PAD dummy( *pad );
555 // Build the dummy pad outline with coordinates relative to the pad position
556 // pad offset and orientation 0. The actual pos, offset and rotation will be
557 // taken in account later by the plot function
558 dummy.SetPosition( VECTOR2I( 0, 0 ) );
559 dummy.SetOffset( aLayer, VECTOR2I( 0, 0 ) );
560
561 if( !sameXYClearance )
562 dummy.SetSize( aLayer, padPlotsSize );
563
564 dummy.SetOrientation( ANGLE_0 );
565 SHAPE_POLY_SET outline;
566 dummy.TransformShapeToPolygon( outline, aLayer, 0, maxError, ERROR_INSIDE );
567
568 if( sameXYClearance )
570 maxError );
571
572 // Initialize the dummy pad shape:
573 dummy.SetAnchorPadShape( aLayer, PAD_SHAPE::CIRCLE );
574 dummy.SetShape( aLayer, PAD_SHAPE::CUSTOM );
575 dummy.DeletePrimitivesList();
576 dummy.AddPrimitivePoly( aLayer, outline, 0, true );
577
578 // Be sure the anchor pad is not bigger than the deflated shape because this
579 // anchor will be added to the pad shape when plotting the pad.
580 // So we set the anchor size to 0
581 dummy.SetSize( aLayer, VECTOR2I( 0, 0 ) );
582 // Restore pad position and offset
583 dummy.SetPosition( pad->GetPosition() );
584 dummy.SetOffset( aLayer, pad->GetOffset( aLayer ) );
585 dummy.SetOrientation( pad->GetOrientation() );
586
587 itemplotter.PlotPad( &dummy, aLayer, color, doSketchPads );
588 }
589
590 break;
591
593 {
594 // inflate/deflate a custom shape is a bit complex.
595 // so build a similar pad shape, and inflate/deflate the polygonal shape
596 PAD dummy( *pad );
597 dummy.SetParentGroup( nullptr );
598
599 SHAPE_POLY_SET shape;
600 pad->MergePrimitivesAsPolygon( aLayer, &shape );
601
602 // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
603 // which can create bad shapes if margin.x is < 0
604 shape.InflateWithLinkedHoles( mask_clearance,
606 dummy.DeletePrimitivesList();
607 dummy.AddPrimitivePoly( aLayer, shape, 0, true );
608
609 // Be sure the anchor pad is not bigger than the deflated shape because this
610 // anchor will be added to the pad shape when plotting the pad. So now the
611 // polygonal shape is built, we can clamp the anchor size
612 if( mask_clearance < 0 ) // we expect margin.x = margin.y for custom pads
613 {
614 dummy.SetSize( aLayer, VECTOR2I( std::max( 0, padPlotsSize.x ),
615 std::max( 0, padPlotsSize.y ) ) );
616 }
617
618 itemplotter.PlotPad( &dummy, aLayer, color, doSketchPads );
619 break;
620 }
621 }
622
623 // Restore the pad parameters modified by the plot code
624 pad->SetSize( aLayer, padSize );
625 pad->SetDelta( aLayer, padDelta );
626 pad->SetShape( aLayer, padShape );
627 pad->SetRoundRectRadiusRatio( aLayer, padCornerRadiusRatio );
628 };
629
630 for( PCB_LAYER_ID layer : aLayerMask.SeqStackupForPlotting() )
631 plotPadLayer( layer );
632 }
633
634 if( footprint->IsDNP()
635 && !itemplotter.GetHideDNPFPsOnFabLayers()
636 && itemplotter.GetCrossoutDNPFPsOnFabLayers()
637 && ( ( onFrontFab && footprint->GetLayer() == F_Cu )
638 || ( onBackFab && footprint->GetLayer() == B_Cu ) ) )
639 {
640 BOX2I rect;
641 const SHAPE_POLY_SET& courtyard = footprint->GetCourtyard( footprint->GetLayer() );
642
643 if( courtyard.IsEmpty() )
644 rect = footprint->GetEffectiveShape()->BBox();
645 else
646 rect = courtyard.BBox();
647
648 int width = aBoard->GetDesignSettings().m_LineThickness[ LAYER_CLASS_FAB ];
649
650 aPlotter->ThickSegment( rect.GetOrigin(), rect.GetEnd(), width, nullptr );
651 aPlotter->ThickSegment( VECTOR2I( rect.GetLeft(), rect.GetBottom() ),
652 VECTOR2I( rect.GetRight(), rect.GetTop() ),
653 width, nullptr );
654 }
655
656 aPlotter->EndBlock( nullptr );
657 }
658
659 // Plot vias on copper layers, and if aPlotOpt.GetPlotViaOnMaskLayer() is true,
660
661 GBR_METADATA gbr_metadata;
662
663 if( onCopperLayer )
664 {
667 }
668
669 auto getMetadata =
670 [&]()
671 {
672 if( aPlotter->GetPlotterType() == PLOT_FORMAT::GERBER )
673 return (void*) &gbr_metadata;
674 else if( aPlotter->GetPlotterType() == PLOT_FORMAT::DXF )
675 return (void*) &aPlotOpt;
676 else
677 return (void*) nullptr;
678 };
679
680 aPlotter->StartBlock( nullptr );
681
682 for( const PCB_TRACK* track : aBoard->Tracks() )
683 {
684 if( track->Type() != PCB_VIA_T )
685 continue;
686
687 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
688
689 // vias are not plotted if not on selected layer
690 LSET via_mask_layer = via->GetLayerSet();
691
692 if( !( via_mask_layer & aLayerMask ).any() )
693 continue;
694
695 int via_margin = 0;
696 double width_adj = 0;
697
698 // TODO(JE) padstacks - separate top/bottom margin
699 if( onSolderMaskLayer )
700 via_margin = via->GetSolderMaskExpansion();
701
702 if( ( aLayerMask & LSET::AllCuMask() ).any() )
703 width_adj = itemplotter.getFineWidthAdj();
704
706 if( onCopperLayer && !via->FlashLayer( aLayerMask ) )
707 continue;
708
709 int diameter = 0;
710
711 for( PCB_LAYER_ID layer : aLayerMask )
712 diameter = std::max( diameter, via->GetWidth( layer ) );
713
714 diameter += 2 * via_margin + width_adj;
715
716 // Don't draw a null size item :
717 if( diameter <= 0 )
718 continue;
719
720 // Some vias can be not connected (no net).
721 // Set the m_NotInNet for these vias to force a empty net name in gerber file
722 gbr_metadata.m_NetlistMetadata.m_NotInNet = via->GetNetname().IsEmpty();
723
724 gbr_metadata.SetNetName( via->GetNetname() );
725
726 COLOR4D color;
727
728 // If we're plotting a single layer, the color for that layer can be used directly.
729 if( aLayerMask.count() == 1 )
730 color = aPlotOpt.ColorSettings()->GetColor( aLayerMask.Seq()[0] );
731 else
732 color = aPlotOpt.ColorSettings()->GetColor( LAYER_VIAS + static_cast<int>( via->GetViaType() ) );
733
734 // Change UNSPECIFIED or WHITE to LIGHTGRAY because the white items are not seen on a
735 // white paper or screen
736 if( color == COLOR4D::UNSPECIFIED || color == WHITE )
737 color = LIGHTGRAY;
738
739 aPlotter->SetColor( color );
740 aPlotter->FlashPadCircle( via->GetStart(), diameter, getMetadata() );
741 }
742
743 aPlotter->EndBlock( nullptr );
744 aPlotter->StartBlock( nullptr );
745
746 if( onCopperLayer )
747 {
750 }
751 else
752 {
753 // Reset attributes if non-copper (soldermask) layer
756 }
757
758 // Plot tracks (not vias) :
759 for( const PCB_TRACK* track : aBoard->Tracks() )
760 {
761 if( track->Type() == PCB_VIA_T )
762 continue;
763
764 if( !( aLayerMask & track->GetLayerSet() ).any() )
765 continue;
766
767 // Some track segments can be not connected (no net).
768 // Set the m_NotInNet for these segments to force a empty net name in gerber file
769 gbr_metadata.m_NetlistMetadata.m_NotInNet = track->GetNetname().IsEmpty();
770
771 gbr_metadata.SetNetName( track->GetNetname() );
772
773 int margin = 0;
774
775 if( onSolderMaskLayer )
776 margin = track->GetSolderMaskExpansion();
777
778 int width = track->GetWidth() + 2 * margin + itemplotter.getFineWidthAdj();
779
780 aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) );
781
782 if( track->Type() == PCB_ARC_T )
783 {
784 const PCB_ARC* arc = static_cast<const PCB_ARC*>( track );
785
786 // Too small arcs cannot be really handled: arc center (and arc radius)
787 // cannot be safely computed
788 if( !arc->IsDegenerated( 10 /* in IU */ ) )
789 {
790 aPlotter->ThickArc( arc->GetCenter(), arc->GetArcAngleStart(), arc->GetAngle(),
791 arc->GetRadius(), width, getMetadata() );
792 }
793 else
794 {
795 // Approximate this very small arc by a segment.
796 aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, getMetadata() );
797 }
798 }
799 else
800 {
801 aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, getMetadata() );
802 }
803 }
804
805 aPlotter->EndBlock( nullptr );
806
807 // Plot filled ares
808 aPlotter->StartBlock( nullptr );
809
810 NETINFO_ITEM nonet( aBoard );
811
812 for( const ZONE* zone : aBoard->Zones() )
813 {
814 if( zone->GetIsRuleArea() )
815 continue;
816
817 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
818 {
819 if( !aLayerMask[layer] )
820 continue;
821
822 SHAPE_POLY_SET mainArea = zone->GetFilledPolysList( layer )->CloneDropTriangulation();
823 SHAPE_POLY_SET islands;
824
825 for( int i = mainArea.OutlineCount() - 1; i >= 0; i-- )
826 {
827 if( zone->IsIsland( layer, i ) )
828 {
829 islands.AddOutline( mainArea.CPolygon( i )[0] );
830 mainArea.DeletePolygon( i );
831 }
832 }
833
834 itemplotter.PlotZone( zone, layer, mainArea );
835
836 if( !islands.IsEmpty() )
837 {
838 ZONE dummy( *zone );
839 dummy.SetNet( &nonet );
840 itemplotter.PlotZone( &dummy, layer, islands );
841 }
842 }
843 }
844
845 aPlotter->EndBlock( nullptr );
846}
847
848
852void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMask,
853 const PCB_PLOT_PARAMS& aPlotOpt )
854{
855 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
856 itemplotter.SetLayerSet( aLayerMask );
857
858 int smallDrill = pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize );
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, aPlotter->RenderSettings() );
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
882 }
883 }
884
885 // Plot pad holes
887 {
888 for( FOOTPRINT* footprint : aBoard->Footprints() )
889 {
890 for( PAD* pad : footprint->Pads() )
891 {
892 if( pad->HasHole() )
893 {
894 if( pad->GetDrillSizeX() == pad->GetDrillSizeY() )
895 {
896 int drill = pad->GetDrillSizeX();
897
899 drill = std::min( smallDrill, drill );
900
901 aPlotter->ThickCircle( pad->ShapePos( layer ), drill,
903 }
904 else
905 {
906 // Note: small drill marks have no significance when applied to slots
907
908 aPlotter->ThickOval( pad->ShapePos( layer ), pad->GetSize( layer ),
909 pad->GetOrientation(), PLOTTER::USE_DEFAULT_LINE_WIDTH,
910 nullptr );
911 }
912 }
913 }
914 }
915 }
916
917 // Plot vias holes
918 for( PCB_TRACK* track : aBoard->Tracks() )
919 {
920 if( track->Type() != PCB_VIA_T )
921 continue;
922
923 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
924
925 if( via->GetLayerSet().Contains( layer ) ) // via holes can be not through holes
926 {
927 aPlotter->Circle( via->GetPosition(), via->GetDrillValue(), FILL_T::NO_FILL,
929 }
930 }
931 }
932}
933
934
938void GenerateLayerPoly( SHAPE_POLY_SET* aResult, BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
939 bool aPlotFPText, bool aPlotReferences, bool aPlotValues )
940{
941 int maxError = aBoard->GetDesignSettings().m_MaxError;
942 SHAPE_POLY_SET buffer;
943 int inflate = 0;
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->TransformShapeToPolySet( exactPolys, aLayer, 0, maxError, ERROR_OUTSIDE,
1055 aPlotter->RenderSettings() );
1056
1057 item->TransformShapeToPolySet( *aResult, aLayer, inflate, maxError,
1058 ERROR_OUTSIDE, aPlotter->RenderSettings() );
1059 }
1060 }
1061 }
1062
1063 // Add filled zone areas.
1064 for( ZONE* zone : aBoard->Zones() )
1065 {
1066 if( zone->GetIsRuleArea() )
1067 continue;
1068
1069 if( !zone->IsOnLayer( aLayer ) )
1070 continue;
1071
1072 SHAPE_POLY_SET area = *zone->GetFill( aLayer );
1073
1074 if( inflate != 0 )
1075 exactPolys.Append( area );
1076
1077 area.Inflate( inflate, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
1078 aResult->Append( area );
1079 }
1080 }
1081
1082 // Merge all polygons
1083 aResult->Simplify();
1084
1085 if( inflate != 0 )
1086 {
1087 aResult->Deflate( inflate, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
1088 // Add back in the exact polys. This is mandatory because inflate/deflate transform is
1089 // not perfect, and we want the initial areas perfectly kept.
1090 aResult->BooleanAdd( exactPolys );
1091 }
1092#undef ERROR
1093}
1094
1095
1102static void initializePlotter( PLOTTER* aPlotter, const BOARD* aBoard, const PCB_PLOT_PARAMS* aPlotOpts )
1103{
1104 PAGE_INFO pageA4( PAGE_SIZE_TYPE::A4 );
1105 const PAGE_INFO& pageInfo = aBoard->GetPageSettings();
1106 const PAGE_INFO* sheet_info;
1107 double paperscale; // Page-to-paper ratio
1108 VECTOR2I paperSizeIU;
1109 VECTOR2I pageSizeIU( pageInfo.GetSizeIU( pcbIUScale.IU_PER_MILS ) );
1110 bool autocenter = false;
1111
1112 // Special options: to fit the sheet to an A4 sheet replace the paper size. However there
1113 // is a difference between the autoscale and the a4paper option:
1114 // - Autoscale fits the board to the paper size
1115 // - A4paper fits the original paper size to an A4 sheet
1116 // - Both of them fit the board to an A4 sheet
1117 if( aPlotOpts->GetA4Output() )
1118 {
1119 sheet_info = &pageA4;
1120 paperSizeIU = pageA4.GetSizeIU( pcbIUScale.IU_PER_MILS );
1121 paperscale = (double) paperSizeIU.x / pageSizeIU.x;
1122 autocenter = true;
1123 }
1124 else
1125 {
1126 sheet_info = &pageInfo;
1127 paperSizeIU = pageSizeIU;
1128 paperscale = 1;
1129
1130 // Need autocentering only if scale is not 1:1
1131 autocenter = (aPlotOpts->GetScale() != 1.0) || aPlotOpts->GetAutoScale();
1132 }
1133
1134 BOX2I bbox = aBoard->ComputeBoundingBox( false );
1135 VECTOR2I boardCenter = bbox.Centre();
1136 VECTOR2I boardSize = bbox.GetSize();
1137
1138 double compound_scale;
1139
1140 // Fit to 80% of the page if asked; it could be that the board is empty, in this case
1141 // regress to 1:1 scale
1142 if( aPlotOpts->GetAutoScale() && boardSize.x > 0 && boardSize.y > 0 )
1143 {
1144 double xscale = (paperSizeIU.x * 0.8) / boardSize.x;
1145 double yscale = (paperSizeIU.y * 0.8) / boardSize.y;
1146
1147 compound_scale = std::min( xscale, yscale ) * paperscale;
1148 }
1149 else
1150 {
1151 compound_scale = aPlotOpts->GetScale() * paperscale;
1152 }
1153
1154 // For the plot offset we have to keep in mind the auxiliary origin too: if autoscaling is
1155 // off we check that plot option (i.e. autoscaling overrides auxiliary origin)
1156 VECTOR2I offset( 0, 0);
1157
1158 if( autocenter )
1159 {
1160 offset.x = KiROUND( boardCenter.x - ( paperSizeIU.x / 2.0 ) / compound_scale );
1161 offset.y = KiROUND( boardCenter.y - ( paperSizeIU.y / 2.0 ) / compound_scale );
1162 }
1163 else
1164 {
1165 if( aPlotOpts->GetUseAuxOrigin() )
1166 offset = aBoard->GetDesignSettings().GetAuxOrigin();
1167 }
1168
1169 aPlotter->SetPageSettings( *sheet_info );
1170
1171 aPlotter->SetViewport( offset, pcbIUScale.IU_PER_MILS/10, compound_scale, aPlotOpts->GetMirror() );
1172
1173 // Has meaning only for gerber plotter. Must be called only after SetViewport
1174 aPlotter->SetGerberCoordinatesFormat( aPlotOpts->GetGerberPrecision() );
1175
1176 // Has meaning only for SVG plotter. Must be called only after SetViewport
1177 aPlotter->SetSvgCoordinatesFormat( aPlotOpts->GetSvgPrecision() );
1178
1179 aPlotter->SetCreator( wxT( "PCBNEW" ) );
1180 aPlotter->SetColorMode( !aPlotOpts->GetBlackAndWhite() ); // default is plot in Black and White.
1181 aPlotter->SetTextMode( aPlotOpts->GetTextMode() );
1182}
1183
1184
1188static void FillNegativeKnockout( PLOTTER *aPlotter, const BOX2I &aBbbox )
1189{
1190 const int margin = 5 * pcbIUScale.IU_PER_MM; // Add a 5 mm margin around the board
1191 aPlotter->SetNegative( true );
1192 aPlotter->SetColor( WHITE ); // Which will be plotted as black
1193
1194 BOX2I area = aBbbox;
1195 area.Inflate( margin );
1196 aPlotter->Rect( area.GetOrigin(), area.GetEnd(), FILL_T::FILLED_SHAPE, 0, 0 );
1197 aPlotter->SetColor( BLACK );
1198}
1199
1200
1201static void plotPdfBackground( BOARD* aBoard, const PCB_PLOT_PARAMS* aPlotOpts, PLOTTER* aPlotter )
1202{
1203 if( aPlotter->GetColorMode()
1204 && aPlotOpts->GetPDFBackgroundColor() != COLOR4D::UNSPECIFIED )
1205 {
1206 aPlotter->SetColor( aPlotOpts->GetPDFBackgroundColor() );
1207
1208 // Use page size selected in pcb to know the schematic bg area
1209 const PAGE_INFO& actualPage = aBoard->GetPageSettings();
1210
1211 VECTOR2I end( actualPage.GetWidthIU( pcbIUScale.IU_PER_MILS ),
1212 actualPage.GetHeightIU( pcbIUScale.IU_PER_MILS ) );
1213
1214 aPlotter->Rect( VECTOR2I( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 );
1215 }
1216}
1217
1218
1225PLOTTER* StartPlotBoard( BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aLayer,
1226 const wxString& aLayerName, const wxString& aFullFileName,
1227 const wxString& aSheetName, const wxString& aSheetPath,
1228 const wxString& aPageName, const wxString& aPageNumber,
1229 const int aPageCount )
1230{
1231 wxCHECK( aBoard && aPlotOpts, nullptr );
1232
1233 // Create the plotter driver and set the few plotter specific options
1234 PLOTTER* plotter = nullptr;
1235
1236 switch( aPlotOpts->GetFormat() )
1237 {
1238 case PLOT_FORMAT::DXF:
1239 DXF_PLOTTER* DXF_plotter;
1240 DXF_plotter = new DXF_PLOTTER();
1241 DXF_plotter->SetUnits( aPlotOpts->GetDXFPlotUnits() );
1242
1243 plotter = DXF_plotter;
1244
1245 if( !aPlotOpts->GetLayersToExport().empty() )
1246 plotter->SetLayersToExport( aPlotOpts->GetLayersToExport() );
1247 break;
1248
1249 case PLOT_FORMAT::POST:
1250 PS_PLOTTER* PS_plotter;
1251 PS_plotter = new PS_PLOTTER();
1252 PS_plotter->SetScaleAdjust( aPlotOpts->GetFineScaleAdjustX(),
1253 aPlotOpts->GetFineScaleAdjustY() );
1254 plotter = PS_plotter;
1255 break;
1256
1257 case PLOT_FORMAT::PDF:
1258 plotter = new PDF_PLOTTER( aBoard->GetProject() );
1259 break;
1260
1261 case PLOT_FORMAT::HPGL:
1262 wxLogError( _( "HPGL plotting is no longer supported as of KiCad 10.0" ) );
1263 return nullptr;
1264
1266 // For Gerber plotter, a valid board layer must be set, in order to create a valid
1267 // Gerber header, especially the TF.FileFunction and .FilePolarity data
1268 if( aLayer < PCBNEW_LAYER_ID_START || aLayer >= PCB_LAYER_ID_COUNT )
1269 {
1270 wxLogError( wxString::Format( "Invalid board layer %d, cannot build a valid Gerber file header",
1271 aLayer ) );
1272 }
1273
1274 plotter = new GERBER_PLOTTER();
1275 break;
1276
1277 case PLOT_FORMAT::SVG:
1278 plotter = new SVG_PLOTTER();
1279 break;
1280
1281 default:
1282 wxASSERT( false );
1283 return nullptr;
1284 }
1285
1287 renderSettings->LoadColors( aPlotOpts->ColorSettings() );
1288 renderSettings->SetDefaultPenWidth( pcbIUScale.mmToIU( 0.0212 ) ); // Hairline at 1200dpi
1289 renderSettings->SetLayerName( aLayerName );
1290
1291 plotter->SetRenderSettings( renderSettings );
1292
1293 // Compute the viewport and set the other options
1294
1295 // page layout is not mirrored, so temporarily change mirror option for the page layout
1296 PCB_PLOT_PARAMS plotOpts = *aPlotOpts;
1297
1298 if( plotOpts.GetPlotFrameRef() )
1299 {
1300 if( plotOpts.GetMirror() )
1301 plotOpts.SetMirror( false );
1302 if( plotOpts.GetScale() != 1.0 )
1303 plotOpts.SetScale( 1.0 );
1304 if( plotOpts.GetAutoScale() )
1305 plotOpts.SetAutoScale( false );
1306 }
1307
1308 initializePlotter( plotter, aBoard, &plotOpts );
1309
1310 if( plotter->OpenFile( aFullFileName ) )
1311 {
1312 plotter->ClearHeaderLinesList();
1313
1314 // For the Gerber "file function" attribute, set the layer number
1315 if( plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1316 {
1317 bool useX2mode = plotOpts.GetUseGerberX2format();
1318
1319 GERBER_PLOTTER* gbrplotter = static_cast <GERBER_PLOTTER*> ( plotter );
1320 gbrplotter->DisableApertMacros( plotOpts.GetDisableGerberMacros() );
1321 gbrplotter->UseX2format( useX2mode );
1322 gbrplotter->UseX2NetAttributes( plotOpts.GetIncludeGerberNetlistInfo() );
1323
1324 // Attributes can be added using X2 format or as comment (X1 format)
1325 AddGerberX2Attribute( plotter, aBoard, aLayer, not useX2mode );
1326 }
1327
1328 bool startPlotSuccess = false;
1329 try
1330 {
1331 if( plotter->GetPlotterType() == PLOT_FORMAT::PDF )
1332 startPlotSuccess = static_cast<PDF_PLOTTER*>( plotter )->StartPlot( aPageNumber, aPageName );
1333 else
1334 startPlotSuccess = plotter->StartPlot( aPageName );
1335 }
1336 catch( ... )
1337 {
1338 startPlotSuccess = false;
1339 }
1340
1341
1342 if( startPlotSuccess )
1343 {
1344 if( aPlotOpts->GetFormat() == PLOT_FORMAT::PDF )
1345 plotPdfBackground( aBoard, aPlotOpts, plotter );
1346
1347 // Plot the frame reference if requested
1348 if( aPlotOpts->GetPlotFrameRef() )
1349 {
1350 PlotDrawingSheet( plotter, aBoard->GetProject(), aBoard->GetTitleBlock(),
1351 aBoard->GetPageSettings(), &aBoard->GetProperties(), aPageNumber,
1352 aPageCount, aSheetName, aSheetPath, aBoard->GetFileName(),
1353 renderSettings->GetLayerColor( LAYER_DRAWINGSHEET ) );
1354
1355 if( aPlotOpts->GetMirror() || aPlotOpts->GetScale() != 1.0 || aPlotOpts->GetAutoScale() )
1356 initializePlotter( plotter, aBoard, aPlotOpts );
1357 }
1358
1359 // When plotting a negative board: draw a black rectangle (background for plot board
1360 // in white) and switch the current color to WHITE; note the color inversion is actually
1361 // done in the driver (if supported)
1362 if( aPlotOpts->GetNegative() )
1363 {
1364 BOX2I bbox = aBoard->ComputeBoundingBox( false );
1365 FillNegativeKnockout( plotter, bbox );
1366 }
1367
1368 return plotter;
1369 }
1370 }
1371
1372 delete plotter->RenderSettings();
1373 delete plotter;
1374 return nullptr;
1375}
1376
1377
1378void setupPlotterNewPDFPage( PLOTTER* aPlotter, BOARD* aBoard, PCB_PLOT_PARAMS* aPlotOpts,
1379 const wxString& aLayerName, const wxString& aSheetName,
1380 const wxString& aSheetPath, const wxString& aPageNumber,
1381 int aPageCount )
1382{
1383 plotPdfBackground( aBoard, aPlotOpts, aPlotter );
1384
1385 aPlotter->RenderSettings()->SetLayerName( aLayerName );
1386
1387 // Plot the frame reference if requested
1388 if( aPlotOpts->GetPlotFrameRef() )
1389 {
1390 // Mirror and scale shouldn't be applied to the drawing sheet
1391 bool revertOps = false;
1392 bool oldMirror = aPlotOpts->GetMirror();
1393 bool oldAutoScale = aPlotOpts->GetAutoScale();
1394 double oldScale = aPlotOpts->GetScale();
1395
1396 if( oldMirror || oldAutoScale || oldScale != 1.0 )
1397 {
1398 aPlotOpts->SetMirror( false );
1399 aPlotOpts->SetScale( 1.0 );
1400 aPlotOpts->SetAutoScale( false );
1401 initializePlotter( aPlotter, aBoard, aPlotOpts );
1402 revertOps = true;
1403 }
1404
1405 PlotDrawingSheet( aPlotter, aBoard->GetProject(), aBoard->GetTitleBlock(),
1406 aBoard->GetPageSettings(), &aBoard->GetProperties(), aPageNumber,
1407 aPageCount,
1408 aSheetName, aSheetPath, aBoard->GetFileName(),
1410
1411 if( revertOps )
1412 {
1413 aPlotOpts->SetMirror( oldMirror );
1414 aPlotOpts->SetScale( oldScale );
1415 aPlotOpts->SetAutoScale( oldAutoScale );
1416 initializePlotter( aPlotter, aBoard, aPlotOpts );
1417 }
1418 }
1419}
@ ERROR_OUTSIDE
@ ERROR_INSIDE
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
@ LAYER_CLASS_FAB
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
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:83
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
void ConvertBrdLayerToPolygonalContours(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aOutlines, KIGFX::RENDER_SETTINGS *aRenderSettings=nullptr) const
Build a set of polygons which are the outlines of copper items (pads, tracks, vias,...
Definition board.cpp:3238
const PAGE_INFO & GetPageSettings() const
Definition board.h:758
const ZONES & Zones() const
Definition board.h:367
TITLE_BLOCK & GetTitleBlock()
Definition board.h:764
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition board.cpp:2076
const std::map< wxString, wxString > & GetProperties() const
Definition board.h:400
const FOOTPRINTS & Footprints() const
Definition board.h:363
const TRACKS & Tracks() const
Definition board.h:361
const wxString & GetFileName() const
Definition board.h:359
PROJECT * GetProject() const
Definition board.h:554
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1069
const DRAWINGS & Drawings() const
Definition board.h:365
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:87
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:78
void PlotFootprintGraphicItems(const FOOTPRINT *aFootprint)
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:399
static const COLOR4D BLACK
Definition color4d.h:403
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).
@ GBR_APERTURE_ATTRIB_VIAPAD
Aperture used for vias.
@ GBR_APERTURE_ATTRIB_NONE
uninitialized attribute.
Metadata which can be added in a gerber file as attribute in X2 format.
void SetNetName(const wxString &aNetname)
void SetApertureAttrib(GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB aApertAttribute)
GBR_NETLIST_METADATA m_NetlistMetadata
An item to handle object attribute.
void SetNetAttribType(int aNetAttribType)
@ 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:105
COLOR4D LegacyMix(const COLOR4D &aColor) const
Mix this COLOR4D with an input COLOR4D using the OR-mixing of legacy canvas.
Definition color4d.cpp:231
PCB specific render settings.
Definition pcb_painter.h:82
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(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition lset.cpp:582
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:591
Handle the data for a net.
Definition netinfo.h:54
Definition pad.h:55
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition page_info.h:79
int GetHeightIU(double aIUScale) const
Gets the page height in IU.
Definition page_info.h:168
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition page_info.h:177
int GetWidthIU(double aIUScale) const
Gets the page width in IU.
Definition page_info.h:159
bool IsDegenerated(int aThreshold=5) const
EDA_ANGLE GetArcAngleStart() const
double GetRadius() const
EDA_ANGLE GetAngle() const
virtual VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition pcb_track.h:354
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
std::vector< std::pair< PCB_LAYER_ID, wxString > > GetLayersToExport() const
COLOR_SETTINGS * ColorSettings() const
Base plotter engine class.
Definition plotter.h:136
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:77
virtual void SetNegative(bool aNegative)
Definition plotter.h:156
virtual void SetSvgCoordinatesFormat(unsigned aPrecision)
Set the number of digits for mantissa in coordinates in mm for SVG plotter.
Definition plotter.h:578
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition plotter.h:169
void SetRenderSettings(RENDER_SETTINGS *aSettings)
Definition plotter.h:166
static const int USE_DEFAULT_LINE_WIDTH
Definition plotter.h:140
virtual void ThickOval(const VECTOR2I &aPos, const VECTOR2I &aSize, const EDA_ANGLE &aOrient, int aWidth, void *aData)
Definition plotter.cpp:487
virtual bool StartPlot(const wxString &aPageNumber)=0
void SetLayersToExport(const std::vector< std::pair< PCB_LAYER_ID, wxString > > &aLayersToExport)
Sets the list of layers to export to the specified vector.
Definition plotter.h:234
RENDER_SETTINGS * RenderSettings()
Definition plotter.h:167
virtual void SetGerberCoordinatesFormat(int aResolution, bool aUseInches=false)
Definition plotter.h:572
virtual void Bookmark(const BOX2I &aBox, const wxString &aName, const wxString &aGroupName=wxEmptyString)
Create a bookmark to a symbol.
Definition plotter.h:528
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:562
virtual void SetTextMode(PLOT_TEXT_MODE mode)
Change the current text mode.
Definition plotter.h:567
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width, int aCornerRadius=0)=0
virtual void SetCreator(const wxString &aCreator)
Definition plotter.h:188
VECTOR2I GetPlotOffsetUserUnits()
Definition plotter.h:604
void ClearHeaderLinesList()
Remove all lines from the list of free lines to print at the beginning of the file.
Definition plotter.h:206
bool GetColorMode() const
Definition plotter.h:164
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:163
virtual void StartBlock(void *aData)
calling this function allows one to define the beginning of a group of drawing items,...
Definition plotter.h:590
virtual void ThickSegment(const VECTOR2I &start, const VECTOR2I &end, int width, void *aData)
Definition plotter.cpp:540
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:517
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:557
virtual void ThickCircle(const VECTOR2I &pos, int diametre, int width, void *aData)
Definition plotter.cpp:593
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:599
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:298
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition zone.cpp:517
A type-safe container of any type.
Definition ki_any.h:93
constexpr any() noexcept
Default constructor, creates an empty object.
Definition ki_any.h:156
@ 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
@ NO_FILL
Definition eda_shape.h:57
@ FILLED_SHAPE
Fill with object color.
Definition eda_shape.h:58
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:677
@ LAYER_DRAWINGSHEET
Sheet frame and title block.
Definition layer_ids.h:278
@ 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
Definition padstack.h:103
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
Definition padstack.h:52
@ CHAMFERED_RECT
Definition padstack.h:60
@ ROUNDRECT
Definition padstack.h:57
@ TRAPEZOID
Definition padstack.h:56
@ RECTANGLE
Definition padstack.h:54
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
void GenerateLayerPoly(SHAPE_POLY_SET *aResult, BOARD *aBoard, PLOTTER *aPlotter, PCB_LAYER_ID aLayer, bool aPlotFPText, bool aPlotReferences, bool aPlotValues)
Generates a SHAPE_POLY_SET representing the plotted items on a layer.
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 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
std::string path
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