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