KiCad PCB EDA Suite
Loading...
Searching...
No Matches
plot_brditems_plotter.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, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <algorithm> // for min
21#include <bitset> // for bitset, operator&, __bi...
22#include <math.h> // for abs
23
24#include <geometry/seg.h> // for SEG
27#include <geometry/shape_line_chain.h> // for SHAPE_LINE_CHAIN
28#include <geometry/shape_poly_set.h> // for SHAPE_POLY_SET, SHAPE_P...
29#include <geometry/shape_rect.h>
31#include <string_utils.h>
32#include <macros.h>
33#include <math/util.h> // for KiROUND
34#include <math/vector2d.h> // for VECTOR2I
36#include <trigo.h>
37#include <font/stroke_font.h>
39#include <callback_gal.h>
40#include <core/typeinfo.h> // for dyn_cast, PCB_DIMENSION_T
41#include <gbr_metadata.h>
42#include <gbr_netlist_metadata.h> // for GBR_NETLIST_METADATA
43#include <layer_ids.h> // for LSET, IsCopperLayer
44#include <lset.h>
50#include <pcb_drill_chart.h>
51#include <pcb_drill_map.h>
52#include <pcbplot.h>
53#include <pcb_plot_params.h> // for PCB_PLOT_PARAMS, PCB_PL...
54#include <advanced_config.h>
55
56#include <line_ending.h>
57#include <pcb_dimension.h>
58#include <pcb_shape.h>
59#include <footprint.h>
60#include <pcb_track.h>
61#include <pad.h>
62#include <pcb_target.h>
63#include <pcb_text.h>
64#include <pcb_textbox.h>
65#include <pcb_tablecell.h>
66#include <pcb_table.h>
67#include <zone.h>
68#include <pcb_barcode.h>
69
70#include <wx/debug.h> // for wxASSERT_MSG
71
72
74{
75 COLOR4D color = ColorSettings()->GetColor( aLayer );
76
77 // A hack to avoid plotting a white item in white color on white paper
78 if( color == COLOR4D::WHITE )
79 color = COLOR4D( LIGHTGRAY );
80
81 return color;
82}
83
84
85void BRDITEMS_PLOTTER::PlotPadNumber( const PAD* aPad, const COLOR4D& aColor )
86{
87 wxString padNumber = UnescapeString( aPad->GetNumber() );
88
89 if( padNumber.IsEmpty() )
90 return;
91
92 BOX2I padBBox = aPad->GetBoundingBox();
93 VECTOR2I position = padBBox.Centre();
94 VECTOR2I padsize = padBBox.GetSize();
95
96 // TODO(JE) padstacks
98 {
99 // See if we have a number box
100 for( const std::shared_ptr<PCB_SHAPE>& primitive : aPad->GetPrimitives( PADSTACK::TEMP_ALL_LAYERS ) )
101 {
102 if( primitive->IsProxyItem() && primitive->GetShape() == SHAPE_T::RECTANGLE )
103 {
104 position = primitive->GetCenter();
105 RotatePoint( position, aPad->GetOrientation() );
106 position += aPad->ShapePos( PADSTACK::TEMP_ALL_LAYERS );
107
108 padsize.x = abs( primitive->GetBotRight().x - primitive->GetTopLeft().x );
109 padsize.y = abs( primitive->GetBotRight().y - primitive->GetTopLeft().y );
110
111 break;
112 }
113 }
114 }
115
117 {
118 // Don't allow a 45° rotation to bloat a pad's bounding box unnecessarily
119 int limit = KiROUND( std::min( aPad->GetSize( PADSTACK::TEMP_ALL_LAYERS ).x,
120 aPad->GetSize( PADSTACK::TEMP_ALL_LAYERS ).y ) * 1.1 );
121
122 if( padsize.x > limit && padsize.y > limit )
123 {
124 padsize.x = limit;
125 padsize.y = limit;
126 }
127 }
128
129 TEXT_ATTRIBUTES textAttrs;
130
131 textAttrs.m_Mirrored = m_plotter->GetPlotMirrored();
132
133 if( padsize.x < ( padsize.y * 0.95 ) )
134 {
135 textAttrs.m_Angle = ANGLE_90;
136 std::swap( padsize.x, padsize.y );
137 }
138
139 // approximate the size of the pad number text:
140 // We use a size for at least 3 chars, to give a good look even for short numbers
141 int tsize = KiROUND( padsize.x / std::max( PrintableCharCount( padNumber ), 3 ) );
142 tsize = std::min( tsize, padsize.y );
143
144 // enforce a max size
145 tsize = std::min( tsize, pcbIUScale.mmToIU( 5.0 ) );
146
147 textAttrs.m_Size = VECTOR2I( tsize, tsize );
148
149 // use a somewhat spindly font to go with the outlined pads
150 textAttrs.m_StrokeWidth = KiROUND( tsize / 12.0 );
151
152 m_plotter->PlotText( position, aColor, padNumber, textAttrs );
153}
154
155
156void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, PCB_LAYER_ID aLayer, const COLOR4D& aColor,
157 bool aSketchMode )
158{
159 VECTOR2I shape_pos = aPad->ShapePos( aLayer );
160 GBR_METADATA metadata;
161
162 bool plotOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
163 bool plotOnExternalCopperLayer = ( m_layerMask & LSET::ExternalCuMask() ).any();
164
165 // Pad not on the solder mask layer cannot be soldered.
166 // therefore it can have a specific aperture attribute.
167 // Not yet in use.
168 // bool isPadOnBoardTechLayers = ( aPad->GetLayerSet() & LSET::AllBoardTechMask() ).any();
169
170 metadata.SetCmpReference( aPad->GetParentFootprint()->GetReference() );
171
172 if( plotOnCopperLayer )
173 {
175 metadata.SetCopper( true );
176
177 // Gives a default attribute, for instance for pads used as tracks in net ties:
178 // Connector pads and SMD pads are on external layers
179 // if on internal layers, they are certainly used as net tie
180 // and are similar to tracks: just conductor items
182
183 const bool useUTF8 = false;
184 const bool useQuoting = false;
185 metadata.SetPadName( aPad->GetNumber(), useUTF8, useQuoting );
186
187 if( !aPad->GetNumber().IsEmpty() )
188 metadata.SetPadPinFunction( aPad->GetPinFunction(), useUTF8, useQuoting );
189
190 metadata.SetNetName( aPad->GetNetname() );
191
192 // Some pads are mechanical pads ( through hole or smd )
193 // when this is the case, they have no pad name and/or are not plated.
194 // In this case gerber files have slightly different attributes.
195 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH || aPad->GetNumber().IsEmpty() )
196 metadata.m_NetlistMetadata.m_NotInNet = true;
197
198 if( !plotOnExternalCopperLayer )
199 {
200 // the .P object attribute (GBR_NETLIST_METADATA::GBR_NETINFO_PAD)
201 // is used on outer layers, unless the component is embedded
202 // or a "etched" component (fp only drawn, not a physical component)
203 // Currently, Pcbnew does not handle embedded component, so we disable the .P
204 // attribute on internal layers
205 // Note the Gerber doc is not really clear about through holes pads about the .P
208
209 }
210
211 // Some attributes are reserved to the external copper layers:
212 // GBR_APERTURE_ATTRIB_CONNECTORPAD and GBR_APERTURE_ATTRIB_SMDPAD_CUDEF
213 // for instance.
214 // Pad with type PAD_ATTRIB::CONN or PAD_ATTRIB::SMD that is not on outer layer
215 // has its aperture attribute set to GBR_APERTURE_ATTRIB_CONDUCTOR
216 switch( aPad->GetAttribute() )
217 {
218 case PAD_ATTRIB::NPTH: // Mechanical pad through hole
220 break;
221
222 case PAD_ATTRIB::PTH : // Pad through hole, a hole is also expected
224 break;
225
226 case PAD_ATTRIB::CONN: // Connector pads, no solder paste but with solder mask.
227 if( plotOnExternalCopperLayer )
229 break;
230
231 case PAD_ATTRIB::SMD: // SMD pads (on external copper layer only)
232 // with solder paste and mask
233 if( plotOnExternalCopperLayer )
235 break;
236 }
237
238 // Fabrication properties can have specific GBR_APERTURE_METADATA options
239 // that replace previous aperture attribute:
240 switch( aPad->GetProperty() )
241 {
242 case PAD_PROP::BGA: // Only applicable to outer layers
243 if( plotOnExternalCopperLayer )
245 break;
246
249 break;
250
253 break;
254
255 case PAD_PROP::TESTPOINT: // Only applicable to outer layers
256 if( plotOnExternalCopperLayer )
258 break;
259
262 break;
263
266 break;
267
268 case PAD_PROP::PRESSFIT: // used only in drill files
269 case PAD_PROP::NONE:
271 break;
272 }
273
274 // Ensure NPTH pads have *always* the GBR_APERTURE_ATTRIB_WASHERPAD attribute
275 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
277 }
278 else
279 {
281 }
282
283 // Set plot color (change WHITE to LIGHTGRAY because
284 // the white items are not seen on a white paper or screen
285 m_plotter->SetColor( aColor != WHITE ? aColor : LIGHTGRAY );
286
287 if( aSketchMode )
288 {
289 switch( aPad->GetShape( aLayer ) )
290 {
292 m_plotter->ThickCircle( shape_pos, aPad->GetSize( aLayer ).x, GetSketchPadLineWidth(),
293 nullptr );
294 break;
295
296 case PAD_SHAPE::OVAL:
297 {
298 m_plotter->ThickOval( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(),
299 GetSketchPadLineWidth(), nullptr );
300 break;
301 }
302
308 {
309 SHAPE_POLY_SET outline;
310 aPad->TransformShapeToPolygon( outline, aLayer, 0, m_plotter->GetPlotterArcHighDef(),
311 ERROR_INSIDE, false );
312
313 m_plotter->ThickPoly( outline, GetSketchPadLineWidth(), nullptr );
314 break;
315 }
316
317 default:
319 }
320
321 return;
322 }
323
324 switch( aPad->GetShape( aLayer ) )
325 {
327 m_plotter->FlashPadCircle( shape_pos, aPad->GetSize( aLayer ).x, &metadata );
328 break;
329
330 case PAD_SHAPE::OVAL:
331 m_plotter->FlashPadOval( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(), &metadata );
332 break;
333
335 m_plotter->FlashPadRect( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(), &metadata );
336 break;
337
339 m_plotter->FlashPadRoundRect( shape_pos, aPad->GetSize( aLayer ),
340 aPad->GetRoundRectCornerRadius( aLayer ),
341 aPad->GetOrientation(), &metadata );
342 break;
343
345 {
346 // Build the pad polygon in coordinates relative to the pad
347 // (i.e. for a pad at pos 0,0, rot 0.0). Needed to use aperture macros,
348 // to be able to create a pattern common to all trapezoid pads having the same shape
349 VECTOR2I coord[4];
350
351 // Order is lower left, lower right, upper right, upper left.
352 VECTOR2I half_size = aPad->GetSize( aLayer ) / 2;
353 VECTOR2I trap_delta = aPad->GetDelta( aLayer ) / 2;
354
355 coord[0] = VECTOR2I( -half_size.x - trap_delta.y, half_size.y + trap_delta.x );
356 coord[1] = VECTOR2I( half_size.x + trap_delta.y, half_size.y - trap_delta.x );
357 coord[2] = VECTOR2I( half_size.x - trap_delta.y, -half_size.y + trap_delta.x );
358 coord[3] = VECTOR2I( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x );
359
360 m_plotter->FlashPadTrapez( shape_pos, coord, aPad->GetOrientation(), &metadata );
361 break;
362 }
363
365 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
366 {
367 GERBER_PLOTTER* gerberPlotter = static_cast<GERBER_PLOTTER*>( m_plotter );
368
369 gerberPlotter->FlashPadChamferRoundRect( shape_pos, aPad->GetSize( aLayer ),
370 aPad->GetRoundRectCornerRadius( aLayer ),
371 aPad->GetChamferRectRatio( aLayer ),
372 aPad->GetChamferPositions( aLayer ),
373 aPad->GetOrientation(), &metadata );
374 break;
375 }
376
378
379 default:
381 {
382 const std::shared_ptr<SHAPE_POLY_SET>& polygons = aPad->GetEffectivePolygon( aLayer, ERROR_INSIDE );
383
384 if( polygons->OutlineCount() )
385 {
386 m_plotter->FlashPadCustom( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(),
387 polygons.get(), &metadata );
388 }
389 }
390 break;
391 }
392}
393
394
396{
397 if( !GetPlotFPText() )
398 return;
399
400 const wxString variantName = m_board ? m_board->GetCurrentVariant() : wxString();
401 const bool dnp = aFootprint->GetDNPForVariant( variantName );
402
403 const PCB_TEXT* reference = &aFootprint->Reference();
404 PCB_LAYER_ID refLayer = reference->GetLayer();
405
406 // Reference and value have special controls for forcing their plotting
407 if( GetPlotReference()
408 && m_layerMask[refLayer]
409 && reference->IsVisible()
410 && !( dnp && hideDNPItems( refLayer ) ) )
411 {
412 PlotText( reference, refLayer, reference->IsKnockout(), reference->GetFontMetrics(),
413 dnp && crossoutDNPItems( refLayer ) );
414 }
415
416 const PCB_TEXT* value = &aFootprint->Value();
417 PCB_LAYER_ID valueLayer = value->GetLayer();
418
419 if( GetPlotValue()
420 && m_layerMask[valueLayer]
421 && value->IsVisible()
422 && !( dnp && hideDNPItems( valueLayer ) ) )
423 {
424 PlotText( value, valueLayer, value->IsKnockout(), value->GetFontMetrics(), false );
425 }
426
427 std::vector<PCB_TEXT*> texts;
428
429 // Skip the reference and value texts that are handled specially
430 for( PCB_FIELD* field : aFootprint->GetFields() )
431 {
432 wxCHECK2( field, continue );
433
434 if( field->IsReference() || field->IsValue() )
435 continue;
436
437 if( field->IsVisible() )
438 texts.push_back( field );
439 }
440
441 for( BOARD_ITEM* item : aFootprint->GraphicalItems() )
442 {
443 if( PCB_TEXT* textItem = dynamic_cast<PCB_TEXT*>( item ) )
444 texts.push_back( textItem );
445 }
446
447 for( const PCB_TEXT* text : texts )
448 {
449 PCB_LAYER_ID textLayer = text->GetLayer();
450 bool strikeout = false;
451
452 if( textLayer == Edge_Cuts || textLayer >= PCB_LAYER_ID_COUNT )
453 continue;
454
455 if( dnp && hideDNPItems( textLayer ) )
456 continue;
457
458 if( !m_layerMask[textLayer] || aFootprint->GetPrivateLayers().test( textLayer ) )
459 continue;
460
461 if( text->GetText() == wxT( "${REFERENCE}" ) )
462 {
463 if( !GetPlotReference() )
464 continue;
465
466 strikeout = dnp && crossoutDNPItems( textLayer );
467 }
468
469 if( text->GetText() == wxT( "${VALUE}" ) )
470 {
471 if( !GetPlotValue() )
472 continue;
473 }
474
475 PlotText( text, textLayer, text->IsKnockout(), text->GetFontMetrics(), strikeout );
476 }
477}
478
479
481{
482 switch( item->Type() )
483 {
484 case PCB_SHAPE_T:
485 PlotShape( static_cast<const PCB_SHAPE*>( item ) );
486 break;
487
488 case PCB_TEXT_T:
489 {
490 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( item );
491 PlotText( text, text->GetLayer(), text->IsKnockout(), text->GetFontMetrics() );
492 break;
493 }
494
495 case PCB_TEXTBOX_T:
496 {
497 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
498
499 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( item );
500 PlotText( textbox, textbox->GetLayer(), textbox->IsKnockout(), textbox->GetFontMetrics() );
501
502 if( textbox->IsBorderEnabled() )
503 PlotShape( textbox );
504
505 m_plotter->SetTextMode( GetTextMode() );
506 break;
507 }
508
509 case PCB_BARCODE_T:
510 PlotBarCode( static_cast<const PCB_BARCODE*>( item ) );
511 break;
512
513 case PCB_TABLE_T:
515 {
516 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( item );
517
518 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
519
520 for( const PCB_TABLECELL* cell : table->GetCells() )
521 PlotText( cell, cell->GetLayer(), cell->IsKnockout(), cell->GetFontMetrics() );
522
524
525 if( item->Type() == PCB_DRILL_CHART_T )
526 PlotChartSymbols( static_cast<const PCB_DRILL_CHART*>( item ) );
527
528 m_plotter->SetTextMode( GetTextMode() );
529 break;
530 }
531
533 case PCB_DIM_CENTER_T:
534 case PCB_DIM_RADIAL_T:
536 case PCB_DIM_LEADER_T:
537 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
538
539 PlotDimension( static_cast<const PCB_DIMENSION_BASE*>( item ) );
540
541 m_plotter->SetTextMode( GetTextMode() );
542 break;
543
544 case PCB_TARGET_T:
545 PlotPcbTarget( static_cast<const PCB_TARGET*>( item ) );
546 break;
547
548 default:
549 break;
550 }
551}
552
553
555{
556 if( !m_layerMask[aDim->GetLayer()] )
557 return;
558
559 COLOR4D color = ColorSettings()->GetColor( aDim->GetLayer() );
560
561 // Set plot color (change WHITE to LIGHTGRAY because
562 // the white items are not seen on a white paper or screen
563 m_plotter->SetColor( color != WHITE ? color : LIGHTGRAY);
564
565 PlotText( aDim, aDim->GetLayer(), false, aDim->GetFontMetrics() );
566
567 PCB_SHAPE temp_item;
568
570 temp_item.SetLayer( aDim->GetLayer() );
571
572 for( const std::shared_ptr<SHAPE>& shape : aDim->GetShapes() )
573 {
574 switch( shape->Type() )
575 {
576 case SH_SEGMENT:
577 {
578 const SEG& seg = static_cast<const SHAPE_SEGMENT*>( shape.get() )->GetSeg();
579
580 temp_item.SetShape( SHAPE_T::SEGMENT );
581 temp_item.SetStart( seg.A );
582 temp_item.SetEnd( seg.B );
583
584 PlotShape( &temp_item );
585 break;
586 }
587
588 case SH_CIRCLE:
589 {
590 VECTOR2I start( shape->Centre() );
591 int radius = static_cast<const SHAPE_CIRCLE*>( shape.get() )->GetRadius();
592
593 temp_item.SetShape( SHAPE_T::CIRCLE );
594 temp_item.SetFilled( false );
595 temp_item.SetStart( start );
596 temp_item.SetEnd( VECTOR2I( start.x + radius, start.y ) );
597
598 PlotShape( &temp_item );
599 break;
600 }
601
602 default:
603 break;
604 }
605 }
606}
607
608
610{
611 int dx1, dx2, dy1, dy2, radius;
612
613 if( !m_layerMask[aMire->GetLayer()] )
614 return;
615
616 m_plotter->SetColor( getColor( aMire->GetLayer() ) );
617
618 PCB_SHAPE temp_item;
619
620 temp_item.SetShape( SHAPE_T::CIRCLE );
621 temp_item.SetFilled( false );
622 temp_item.SetStroke( STROKE_PARAMS( aMire->GetWidth(), LINE_STYLE::SOLID ) );
623 temp_item.SetLayer( aMire->GetLayer() );
624 temp_item.SetStart( aMire->GetPosition() );
625 radius = aMire->GetSize() / 3;
626
627 if( aMire->GetShape() ) // temp_item X
628 radius = aMire->GetSize() / 2;
629
630 // Draw the circle
631 temp_item.SetEnd( VECTOR2I( temp_item.GetStart().x + radius, temp_item.GetStart().y ) );
632
633 PlotShape( &temp_item );
634
635 temp_item.SetShape( SHAPE_T::SEGMENT );
636
637 radius = aMire->GetSize() / 2;
638 dx1 = radius;
639 dy1 = 0;
640 dx2 = 0;
641 dy2 = radius;
642
643 if( aMire->GetShape() ) // Shape X
644 {
645 dx1 = dy1 = radius;
646 dx2 = dx1;
647 dy2 = -dy1;
648 }
649
650 VECTOR2I mirePos( aMire->GetPosition() );
651
652 // Draw the X or + temp_item:
653 temp_item.SetStart( VECTOR2I( mirePos.x - dx1, mirePos.y - dy1 ) );
654 temp_item.SetEnd( VECTOR2I( mirePos.x + dx1, mirePos.y + dy1 ) );
655 PlotShape( &temp_item );
656
657 temp_item.SetStart( VECTOR2I( mirePos.x - dx2, mirePos.y - dy2 ) );
658 temp_item.SetEnd( VECTOR2I( mirePos.x + dx2, mirePos.y + dy2 ) );
659 PlotShape( &temp_item );
660}
661
662
664{
665 const wxString variantName = m_board ? m_board->GetCurrentVariant() : wxString();
666 const bool dnp = aFootprint->GetDNPForVariant( variantName );
667
668 for( const BOARD_ITEM* item : aFootprint->GraphicalItems() )
669 {
670 PCB_LAYER_ID itemLayer = item->GetLayer();
671
672 if( aFootprint->GetPrivateLayers().test( itemLayer ) )
673 continue;
674
675 if( dnp && hideDNPItems( itemLayer ) )
676 continue;
677
678 if( !( m_layerMask & item->GetLayerSet() ).any() )
679 continue;
680
681 switch( item->Type() )
682 {
683 case PCB_SHAPE_T:
684 PlotShape( static_cast<const PCB_SHAPE*>( item ) );
685 break;
686
687 case PCB_TEXTBOX_T:
688 {
689 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( item );
690
691 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
692
693 PlotText( textbox, textbox->GetLayer(), textbox->IsKnockout(),
694 textbox->GetFontMetrics() );
695
696 if( textbox->IsBorderEnabled() )
697 PlotShape( textbox );
698
699 m_plotter->SetTextMode( GetTextMode() );
700 break;
701 }
702
703 case PCB_BARCODE_T:
704 PlotBarCode( static_cast<const PCB_BARCODE*>( item ) );
705 break;
706
707 case PCB_TABLE_T:
709 {
710 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( item );
711
712 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
713
714 for( const PCB_TABLECELL* cell : table->GetCells() )
715 PlotText( cell, cell->GetLayer(), cell->IsKnockout(), cell->GetFontMetrics() );
716
718
719 m_plotter->SetTextMode( GetTextMode() );
720 break;
721 }
722
724 case PCB_DIM_CENTER_T:
725 case PCB_DIM_RADIAL_T:
727 case PCB_DIM_LEADER_T:
728 PlotDimension( static_cast<const PCB_DIMENSION_BASE*>( item ) );
729 break;
730
731 case PCB_TEXT_T:
732 // Plotted in PlotFootprintTextItems()
733 break;
734
736 // Not plotted at all
737 break;
738
739 default:
740 UNIMPLEMENTED_FOR( item->GetClass() );
741 }
742 }
743}
744
745
746#define getMetadata() ( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER ? (void*) &gbr_metadata \
747 : m_plotter->GetPlotterType() == PLOT_FORMAT::DXF ? (void*) this \
748 : (void*) nullptr )
749
750
751void BRDITEMS_PLOTTER::PlotText( const EDA_TEXT* aText, PCB_LAYER_ID aLayer, bool aIsKnockout,
752 const KIFONT::METRICS& aFontMetrics, bool aStrikeout )
753{
754 int maxError = m_board->GetDesignSettings().m_MaxError;
755 KIFONT::FONT* font = aText->GetDrawFont( m_plotter->RenderSettings() );
756 wxString shownText( aText->GetShownText( FOR_CANVAS ) );
757
758 const PCB_TEXTBOX* knockoutBox = aIsKnockout ? dynamic_cast<const PCB_TEXTBOX*>( aText ) : nullptr;
759
760 if( shownText.IsEmpty() && !knockoutBox )
761 return;
762
763 if( !m_layerMask[aLayer] )
764 return;
765
766 GBR_METADATA gbr_metadata;
767
768 if( IsCopperLayer( aLayer ) )
770
771 COLOR4D color = getColor( aLayer );
772 m_plotter->SetColor( color );
773
774 const VECTOR2I& pos = aText->GetTextPos();
775
776 TEXT_ATTRIBUTES attrs = aText->GetAttributes();
777 attrs.m_Size = aText->GetTextSize();
779 attrs.m_Angle = aText->GetDrawRotation();
780 attrs.m_Multiline = false;
781
782 m_plotter->SetCurrentLineWidth( attrs.m_StrokeWidth );
783
784 auto strikeoutText =
785 [&]( const PCB_TEXT* text )
786 {
787 SHAPE_POLY_SET textPoly;
788
789 text->TransformTextToPolySet( textPoly, 0, ARC_LOW_DEF, ERROR_INSIDE );
790 textPoly.Rotate( -text->GetDrawRotation(), text->GetDrawPos() );
791
792 BOX2I rect = textPoly.BBox();
793 VECTOR2I start( rect.GetLeft() - attrs.m_StrokeWidth,
794 ( rect.GetTop() + rect.GetBottom() ) / 2 );
795 VECTOR2I end( rect.GetRight() + attrs.m_StrokeWidth,
796 ( rect.GetTop() + rect.GetBottom() ) / 2 );
797
798 RotatePoint( start, text->GetDrawPos(), text->GetDrawRotation() );
799 RotatePoint( end, text->GetDrawPos(), text->GetDrawRotation() );
800
801 m_plotter->ThickSegment( start, end, attrs.m_StrokeWidth, getMetadata() );
802 };
803
804 if( aIsKnockout )
805 {
806 SHAPE_POLY_SET finalPoly;
807
808 if( knockoutBox )
809 knockoutBox->TransformTextToPolySet( finalPoly, 0, maxError, ERROR_INSIDE );
810 else if( const PCB_TEXT* text = dynamic_cast<const PCB_TEXT*>( aText ) )
811 text->TransformTextToPolySet( finalPoly, 0, maxError, ERROR_INSIDE );
812
813 finalPoly.Fracture();
814
815 for( int ii = 0; ii < finalPoly.OutlineCount(); ++ii )
816 m_plotter->PlotPoly( finalPoly.Outline( ii ), FILL_T::FILLED_SHAPE, 0, getMetadata() );
817 }
818 else
819 {
820 if( font->IsOutline() && !m_board->GetEmbeddedFiles()->GetAreFontsEmbedded() )
821 {
823
824 CALLBACK_GAL callback_gal( empty_opts,
825 // Stroke callback
826 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
827 {
828 m_plotter->ThickSegment( aPt1, aPt2, attrs.m_StrokeWidth, getMetadata() );
829 },
830 // Polygon callback
831 [&]( const SHAPE_LINE_CHAIN& aPoly )
832 {
833 m_plotter->PlotPoly( aPoly, FILL_T::FILLED_SHAPE, 0, getMetadata() );
834 } );
835
836 callback_gal.DrawGlyphs( *aText->GetRenderCache( font, shownText ) );
837 }
838 else if( aText->IsMultilineAllowed() )
839 {
840 std::vector<VECTOR2I> positions;
841 wxArrayString strings_list;
842 wxStringSplit( shownText, strings_list, '\n' );
843 positions.reserve( strings_list.Count() );
844
845 aText->GetLinePositions( m_plotter->RenderSettings(), positions, (int) strings_list.Count() );
846
847 for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
848 {
849 wxString& txt = strings_list.Item( ii );
850 m_plotter->PlotText( positions[ii], color, txt, attrs, font, aFontMetrics, getMetadata() );
851 }
852
853 if( aStrikeout && strings_list.Count() == 1 )
854 strikeoutText( static_cast<const PCB_TEXT*>( aText ) );
855 }
856 else
857 {
858 m_plotter->PlotText( pos, color, shownText, attrs, font, aFontMetrics, getMetadata() );
859
860 if( aStrikeout )
861 strikeoutText( static_cast<const PCB_TEXT*>( aText ) );
862 }
863 }
864}
865
866
867void BRDITEMS_PLOTTER::PlotZone( const ZONE* aZone, PCB_LAYER_ID aLayer, const SHAPE_POLY_SET& aPolysList )
868{
869 if( aPolysList.IsEmpty() )
870 return;
871
872 GBR_METADATA gbr_metadata;
873
874 if( aZone->IsOnCopperLayer() )
875 {
876 gbr_metadata.SetNetName( aZone->GetNetname() );
877 gbr_metadata.SetCopper( true );
878
879 // Zones with no net name can exist.
880 // they are not used to connect items, so the aperture attribute cannot
881 // be set as conductor
882 if( aZone->GetNetname().IsEmpty() )
883 {
885 }
886 else
887 {
890 }
891 }
892
893 m_plotter->SetColor( getColor( aLayer ) );
894
895 m_plotter->StartBlock( nullptr ); // Clean current object attributes
896
897 /*
898 * In non filled mode the outline is plotted, but not the filling items
899 */
900
901 for( int idx = 0; idx < aPolysList.OutlineCount(); ++idx )
902 {
903 const SHAPE_LINE_CHAIN& outline = aPolysList.Outline( idx );
904
905 // Plot the current filled area (as region for Gerber plotter to manage attributes)
906 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
907 {
908 static_cast<GERBER_PLOTTER*>( m_plotter )->PlotGerberRegion( outline, &gbr_metadata );
909 }
910 else if( m_plotter->GetPlotterType() == PLOT_FORMAT::DXF )
911 {
912 if( GetDXFPlotMode() == FILLED )
913 m_plotter->PlotPoly( outline, FILL_T::FILLED_SHAPE, 0, getMetadata() );
914 }
915 else
916 {
917 m_plotter->PlotPoly( outline, FILL_T::FILLED_SHAPE, 0, getMetadata() );
918 }
919 }
920
921 m_plotter->EndBlock( nullptr ); // Clear object attributes
922}
923
924
926{
927 if( !( m_layerMask & aShape->GetLayerSet() ).any() )
928 return;
929
930 int thickness = aShape->GetWidth();
931 int margin = thickness; // unclamped thickness (can be negative)
932 LINE_STYLE lineStyle = aShape->GetStroke().GetLineStyle();
933 bool onCopperLayer = ( LSET::AllCuMask() & m_layerMask ).any();
934 bool onSolderMaskLayer = ( LSET( { F_Mask, B_Mask } ) & m_layerMask ).any();
935 bool isSolidFill = aShape->IsSolidFill();
936 bool isHatchedFill = aShape->IsHatchedFill();
937
938 if( onSolderMaskLayer
939 && aShape->HasSolderMask()
940 && IsExternalCopperLayer( aShape->GetLayer() ) )
941 {
942 margin += 2 * aShape->GetSolderMaskExpansion();
943 thickness = std::max( margin, 0 );
944
945 if( isHatchedFill )
946 {
947 isSolidFill = true;
948 isHatchedFill = false;
949 }
950 }
951
952 m_plotter->SetColor( getColor( aShape->GetLayer() ) );
953
954 const FOOTPRINT* parentFP = aShape->GetParentFootprint();
955 GBR_METADATA gbr_metadata;
956 const wxString variantName = m_board ? m_board->GetCurrentVariant() : wxString();
957 const bool parentDnp = parentFP ? parentFP->GetDNPForVariant( variantName ) : false;
958
959 if( parentFP )
960 {
961 gbr_metadata.SetCmpReference( parentFP->GetReference() );
963 }
964
965 if( parentFP && parentDnp && GetSketchDNPFPsOnFabLayers() )
966 {
967 if( aShape->GetLayer() == F_Fab || aShape->GetLayer() == B_Fab )
968 {
969 thickness = GetSketchPadLineWidth();
970 isSolidFill = false;
971 isHatchedFill = false;
972 }
973 }
974
975 if( aShape->GetLayer() == Edge_Cuts )
976 {
978 }
979 else if( onCopperLayer )
980 {
981 if( parentFP )
982 {
984 gbr_metadata.SetCopper( true );
985 }
986 else if( aShape->GetNetCode() > 0 )
987 {
988 gbr_metadata.SetCopper( true );
991 gbr_metadata.SetNetName( aShape->GetNetname() );
992 }
993 else
994 {
995 // Graphic items (PCB_SHAPE, TEXT) having no net have the NonConductor attribute
996 // Graphic items having a net have the Conductor attribute, but are not (yet?)
997 // supported in Pcbnew
999 }
1000 }
1001
1002 if( lineStyle <= LINE_STYLE::FIRST_TYPE )
1003 {
1004 switch( aShape->GetShape() )
1005 {
1006 case SHAPE_T::SEGMENT:
1007 {
1008 VECTOR2I segStart = aShape->GetStart();
1009 VECTOR2I segEnd = aShape->GetEnd();
1010
1011 if( EDA_SHAPE::ShortenSegmentForEndings( segStart, segEnd, aShape->GetStartEnding(), aShape->GetEndEnding(),
1012 thickness ) )
1013 {
1014 m_plotter->ThickSegment( segStart, segEnd, thickness, getMetadata() );
1015 }
1016
1017 break;
1018 }
1019
1020 case SHAPE_T::CIRCLE:
1021 if( isSolidFill )
1022 {
1023 int diameter = aShape->GetRadius() * 2 + thickness;
1024
1025 if( margin < 0 )
1026 {
1027 diameter += margin;
1028 diameter = std::max( diameter, 0 );
1029 }
1030
1031 m_plotter->FilledCircle( aShape->GetStart(), diameter, getMetadata() );
1032 }
1033 else
1034 {
1035 m_plotter->ThickCircle( aShape->GetStart(), aShape->GetRadius() * 2, thickness,
1036 getMetadata() );
1037 }
1038
1039 break;
1040
1041 case SHAPE_T::ARC:
1042 {
1043 // when startAngle == endAngle ThickArc() doesn't know whether it's 0 deg and 360 deg
1044 // but it is a circle
1045 if( std::abs( aShape->GetArcAngle().AsDegrees() ) == 360.0 )
1046 {
1047 m_plotter->ThickCircle( aShape->GetCenter(), aShape->GetRadius() * 2, thickness,
1048 getMetadata() );
1049 }
1050 else if( aShape->GetStartEnding().GetStyle() != LINE_ENDING_STYLE::NONE
1052 {
1053 EDA_ANGLE startAngle;
1054 EDA_ANGLE endAngle;
1055 aShape->CalcArcAngles( startAngle, endAngle );
1056
1057 EDA_ANGLE arcAngle = endAngle - startAngle;
1058 if( aShape->ShortenArcForEndings( startAngle, arcAngle, aShape->GetRadius(), thickness ) )
1059 {
1060 m_plotter->ThickArc( VECTOR2D( aShape->GetCenter() ), startAngle, arcAngle, aShape->GetRadius(),
1061 thickness, getMetadata() );
1062 }
1063 }
1064 else
1065 {
1066 m_plotter->ThickArc( *aShape, getMetadata(), thickness );
1067 }
1068
1069 break;
1070 }
1071
1072 case SHAPE_T::BEZIER:
1073 {
1074 std::optional<BEZIER<double>> curve = aShape->ShortenedBezierCurve( thickness );
1075
1076 if( curve && m_plotter->GetPlotterType() == PLOT_FORMAT::SVG )
1077 {
1078 m_plotter->BezierCurve( VECTOR2I( curve->Start ), VECTOR2I( curve->C1 ), VECTOR2I( curve->C2 ),
1079 VECTOR2I( curve->End ), aShape->GetMaxError(), thickness );
1080 }
1081 else
1082 {
1083 std::vector<VECTOR2D> pts = aShape->ShortenedBezierPolyline( thickness );
1084
1085 for( size_t i = 0; i + 1 < pts.size(); i++ )
1086 {
1087 m_plotter->ThickSegment( VECTOR2I( pts[i] ), VECTOR2I( pts[i + 1] ), thickness, getMetadata() );
1088 }
1089 }
1090
1091 break;
1092 }
1093
1094 case SHAPE_T::POLY:
1095 if( aShape->IsPolyShapeValid() )
1096 {
1097 bool hasEndings = aShape->GetStartEnding().GetStyle() != LINE_ENDING_STYLE::NONE
1099
1100 auto plotStrokeOutline = [&]( const SHAPE_LINE_CHAIN& aOutline, int aOutlineIdx )
1101 {
1102 if( aOutline.PointCount() < 2 )
1103 return;
1104
1105 if( hasEndings )
1106 {
1107 std::vector<VECTOR2I> pts;
1108
1109 if( !aShape->GetShortenedBodyPolyPoints( aOutline, aOutlineIdx, pts, thickness ) )
1110 return;
1111
1112 SHAPE_LINE_CHAIN shortened;
1113
1114 for( const VECTOR2I& pt : pts )
1115 shortened.Append( pt );
1116
1117 shortened.SetClosed( aOutline.IsClosed() );
1118 m_plotter->PlotPoly( shortened, FILL_T::NO_FILL, thickness, getMetadata() );
1119 return;
1120 }
1121
1122 m_plotter->PlotPoly( aOutline, FILL_T::NO_FILL, thickness, getMetadata() );
1123 };
1124
1125 if( !hasEndings && m_plotter->GetPlotterType() == PLOT_FORMAT::DXF && GetDXFPlotMode() == SKETCH )
1126 {
1127 m_plotter->ThickPoly( aShape->GetPolyShape(), thickness, getMetadata() );
1128 }
1129 else
1130 {
1131 m_plotter->SetCurrentLineWidth( thickness, &gbr_metadata );
1132
1133 const SHAPE_POLY_SET& origPoly = aShape->GetPolyShape();
1134
1135 // Stroke the unfractured outline so degenerate near-zero-width
1136 // spikes (which Fracture() collapses but the editor still draws as
1137 // thick lines) are preserved in the plot output (issue #24143).
1138 if( thickness > 0 )
1139 {
1140 for( int jj = 0; jj < origPoly.OutlineCount(); ++jj )
1141 plotStrokeOutline( origPoly.COutline( jj ), jj );
1142 }
1143
1144 if( !isSolidFill )
1145 break;
1146
1147 // Fracture before plotting the fill to avoid invalid gerber regions
1148 // from self-intersecting or overlapping outlines.
1149 SHAPE_POLY_SET tmpPoly = origPoly.CloneDropTriangulation();
1150 tmpPoly.Fracture();
1151
1152 if( margin < 0 )
1153 tmpPoly.Inflate( margin / 2, CORNER_STRATEGY::ROUND_ALL_CORNERS, aShape->GetMaxError() );
1154
1155 for( int jj = 0; jj < tmpPoly.OutlineCount(); ++jj )
1156 {
1157 SHAPE_LINE_CHAIN& poly = tmpPoly.Outline( jj );
1158 poly.SetClosed( true );
1159
1160 // Width 0; the stroke was already plotted from the unfractured outline.
1161 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1162 {
1163 GERBER_PLOTTER* gbr_plotter = static_cast<GERBER_PLOTTER*>( m_plotter );
1164 gbr_plotter->PlotPolyAsRegion( poly, FILL_T::FILLED_SHAPE, 0,
1165 &gbr_metadata );
1166 }
1167 else
1168 {
1169 m_plotter->PlotPoly( poly, FILL_T::FILLED_SHAPE, 0, getMetadata() );
1170 }
1171 }
1172 }
1173 }
1174
1175 break;
1176
1177 case SHAPE_T::RECTANGLE:
1178 {
1179 int radius = aShape->GetCornerRadius();
1180
1181 if( radius == 0 && m_plotter->GetPlotterType() == PLOT_FORMAT::DXF &&
1182 GetDXFPlotMode() == SKETCH )
1183 {
1184 std::vector<VECTOR2I> pts = aShape->GetRectCorners();
1185 m_plotter->ThickRect( pts[0], pts[2], thickness, getMetadata() );
1186 }
1187 else
1188 {
1189 BOX2I box( aShape->GetStart(), VECTOR2I( aShape->GetEnd().x - aShape->GetStart().x,
1190 aShape->GetEnd().y - aShape->GetStart().y ) );
1191 box.Normalize();
1192
1193 if( margin < 0 )
1194 {
1195 box.Inflate( margin );
1196 radius += margin;
1197 }
1198
1199 SHAPE_RECT rect( box );
1200 rect.SetRadius( radius );
1201
1202 SHAPE_LINE_CHAIN outline = rect.Outline();
1203 SHAPE_POLY_SET poly( outline );
1204
1205 FILL_T fill_mode = isSolidFill ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL;
1206
1207 if( poly.OutlineCount() > 0 )
1208 {
1209 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1210 {
1211 GERBER_PLOTTER* gbr_plotter = static_cast<GERBER_PLOTTER*>( m_plotter );
1212 gbr_plotter->PlotPolyAsRegion( poly.COutline( 0 ), fill_mode, thickness, &gbr_metadata );
1213 }
1214 else
1215 {
1216 // TODO: PlotPoly needs to handle arcs...
1217 m_plotter->PlotPoly( poly.COutline( 0 ), fill_mode, thickness, getMetadata() );
1218 }
1219 }
1220 }
1221
1222 break;
1223 }
1224
1225 case SHAPE_T::ELLIPSE:
1227 {
1228 const bool isClosed = ( aShape->GetShape() == SHAPE_T::ELLIPSE );
1229
1230 SHAPE_ELLIPSE e = isClosed ? SHAPE_ELLIPSE( aShape->GetEllipseCenter(), aShape->GetEllipseMajorRadius(),
1231 aShape->GetEllipseMinorRadius(), aShape->GetEllipseRotation() )
1233 aShape->GetEllipseMinorRadius(), aShape->GetEllipseRotation(),
1234 aShape->GetEllipseStartAngle(), aShape->GetEllipseEndAngle() );
1235
1237
1238 if( isClosed )
1239 chain.SetClosed( true );
1240
1241 FILL_T fill = ( isClosed && isSolidFill ) ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL;
1242
1243 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER && isClosed )
1244 {
1245 GERBER_PLOTTER* gbr_plotter = static_cast<GERBER_PLOTTER*>( m_plotter );
1246 gbr_plotter->PlotPolyAsRegion( chain, fill, thickness, &gbr_metadata );
1247 }
1248 else
1249 {
1250 m_plotter->PlotPoly( chain, fill, thickness, getMetadata() );
1251 }
1252
1253 break;
1254 }
1255
1256 default:
1258 }
1259 }
1260 else
1261 {
1262 std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapesForStroking( thickness );
1263
1264 for( SHAPE* shape : shapes )
1265 {
1266 STROKE_PARAMS::Stroke( shape, lineStyle, aShape->GetWidth(),
1267 m_plotter->RenderSettings(),
1268 [&]( const VECTOR2I& a, const VECTOR2I& b )
1269 {
1270 m_plotter->ThickSegment( a, b, thickness, getMetadata() );
1271 } );
1272 }
1273
1274 for( SHAPE* shape : shapes )
1275 delete shape;
1276 }
1277
1278 // Plot line endings for open shapes.
1281 {
1282 EDA_ANGLE startTangent, endTangent;
1283 aShape->GetEndingTangents( startTangent, endTangent, thickness );
1284
1285 VECTOR2I startPt, endPt;
1286
1287 if( aShape->GetLineEndingEndpoints( startPt, endPt ) )
1288 {
1289 aShape->GetStartEnding().Plot( m_plotter, startPt, startTangent, thickness, getMetadata() );
1290 aShape->GetEndEnding().Plot( m_plotter, endPt, endTangent, thickness, getMetadata() );
1291 }
1292 }
1293
1294 if( isHatchedFill )
1295 {
1296 for( int ii = 0; ii < aShape->GetHatching().OutlineCount(); ++ii )
1297 {
1298 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1299 {
1300 GERBER_PLOTTER* gbr_plotter = static_cast<GERBER_PLOTTER*>( m_plotter );
1301 gbr_plotter->PlotPolyAsRegion( aShape->GetHatching().Outline( ii ),
1302 FILL_T::FILLED_SHAPE, 0, &gbr_metadata );
1303 }
1304 else
1305 {
1306 m_plotter->PlotPoly( aShape->GetHatching().Outline( ii ), FILL_T::FILLED_SHAPE,
1307 0, getMetadata() );
1308 }
1309 }
1310 }
1311}
1312
1313
1315{
1316 if( !m_layerMask[aBarCode->GetLayer()] )
1317 return;
1318
1319 // To avoid duplicate code, build a PCB_SHAPE to plot the polygon shape
1320 PCB_SHAPE dummy( aBarCode->GetParent(), SHAPE_T::POLY );
1321 dummy.SetLayer( aBarCode->GetLayer() );
1322 dummy.SetFillMode( FILL_T::FILLED_SHAPE );
1323 dummy.SetWidth( 0 );
1324
1325 SHAPE_POLY_SET shape;
1326 aBarCode->TransformShapeToPolySet( shape, aBarCode->GetLayer(), 0, 0, ERROR_INSIDE );
1327 dummy.SetPolyShape( shape );
1328
1329 PlotShape( &dummy );
1330}
1331
1332
1334{
1335 if( !m_layerMask[aTable->GetLayer()] )
1336 return;
1337
1338 GBR_METADATA gbr_metadata;
1339
1340 if( const FOOTPRINT* parentFP = aTable->GetParentFootprint() )
1341 {
1342 gbr_metadata.SetCmpReference( parentFP->GetReference() );
1344 }
1345
1346 aTable->DrawBorders(
1347 [&]( const VECTOR2I& ptA, const VECTOR2I& ptB, const STROKE_PARAMS& stroke )
1348 {
1349 int lineWidth = stroke.GetWidth();
1350 LINE_STYLE lineStyle = stroke.GetLineStyle();
1351
1352 if( lineStyle <= LINE_STYLE::FIRST_TYPE )
1353 {
1354 m_plotter->ThickSegment( ptA, ptB, lineWidth, getMetadata() );
1355 }
1356 else
1357 {
1358 SHAPE_SEGMENT seg( ptA, ptB );
1359
1360 STROKE_PARAMS::Stroke( &seg, lineStyle, lineWidth, m_plotter->RenderSettings(),
1361 [&]( const VECTOR2I& a, const VECTOR2I& b )
1362 {
1363 m_plotter->ThickSegment( a, b, lineWidth, getMetadata() );
1364 } );
1365 }
1366 } );
1367}
1368
1369
1371 const VECTOR2I& aDrillSize, const VECTOR2I& aPadSize,
1372 const EDA_ANGLE& aOrientation, int aSmallDrill )
1373{
1374 VECTOR2I drillSize = aDrillSize;
1375
1376 // Small drill marks have no significance when applied to slots
1377 if( aSmallDrill && aDrillShape == PAD_DRILL_SHAPE::CIRCLE )
1378 drillSize.x = std::min( aSmallDrill, drillSize.x );
1379
1380 // Round holes only have x diameter, slots have both
1381 drillSize.x -= getFineWidthAdj();
1382 drillSize.x = std::clamp( drillSize.x, 1, aPadSize.x - 1 );
1383
1384 if( aDrillShape == PAD_DRILL_SHAPE::OBLONG )
1385 {
1386 drillSize.y -= getFineWidthAdj();
1387 drillSize.y = std::clamp( drillSize.y, 1, aPadSize.y - 1 );
1388
1389 m_plotter->FlashPadOval( aDrillPos, drillSize, aOrientation, nullptr );
1390 }
1391 else
1392 {
1393 m_plotter->FlashPadCircle( aDrillPos, drillSize.x, nullptr );
1394 }
1395}
1396
1397
1399{
1400 int smallDrill = 0;
1401
1403 smallDrill = pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize );
1404
1405 /* Drill marks are drawn white-on-black to knock-out the underlying pad. This works only
1406 * for drivers supporting color change, obviously... it means that:
1407 - PS, SVG and PDF output is correct (i.e. you have a 'donut' pad)
1408 - In gerbers you can't see them. This is arguably the right thing to do since having
1409 drill marks and high speed drill stations is a sure recipe for broken tools and angry
1410 manufacturers. If you *really* want them you could start a layer with negative
1411 polarity to knock-out the film.
1412 - In DXF they go into the 'WHITE' layer. This could be useful.
1413 */
1414 if( m_plotter->GetPlotterType() != PLOT_FORMAT::DXF || GetDXFPlotMode() == FILLED )
1415 m_plotter->SetColor( WHITE );
1416
1417 for( PCB_TRACK* track : m_board->Tracks() )
1418 {
1419 if( track->Type() == PCB_VIA_T )
1420 {
1421 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
1422
1423 // Via are not always on all layers
1424 if( ( via->GetLayerSet() & m_layerMask ).none() )
1425 continue;
1426
1428 VECTOR2I( via->GetDrillValue(), 0 ),
1429 VECTOR2I( via->GetWidth( PADSTACK::TEMP_ALL_LAYERS ), 0 ),
1430 ANGLE_0, smallDrill );
1431 }
1432 }
1433
1434 for( FOOTPRINT* footprint : m_board->Footprints() )
1435 {
1436 for( PAD* pad : footprint->Pads() )
1437 {
1438 if( pad->GetDrillSize().x == 0 )
1439 continue;
1440
1441 // Skip marks on layers the pad isn't on for Gerber only (24416). Other
1442 // formats keep them as a drill map, e.g. Edge.Cuts (24867).
1443 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER && ( pad->GetLayerSet() & m_layerMask ).none() )
1444 continue;
1445
1446 if( m_plotter->GetPlotterType() != PLOT_FORMAT::DXF || GetDXFPlotMode() == FILLED )
1447 {
1448 // Drill mark is in black unless we can find something to knock it out of
1449 m_plotter->SetColor( BLACK );
1450
1451 for( PCB_LAYER_ID layer : m_layerMask )
1452 {
1453 if( !pad->IsOnLayer( layer ) )
1454 continue;
1455
1456 VECTOR2I padSize = pad->GetSize( layer );
1457
1458 if( padSize.x > pad->GetDrillSizeX() || padSize.y > pad->GetDrillSizeY() )
1459 {
1460 m_plotter->SetColor( WHITE );
1461 break;
1462 }
1463 }
1464 }
1465
1466 plotOneDrillMark( pad->GetDrillShape(), pad->GetPosition(), pad->GetDrillSize(),
1467 pad->GetSize( PADSTACK::TEMP_ALL_LAYERS ), pad->GetOrientation(), smallDrill );
1468 }
1469 }
1470
1471 if( m_plotter->GetPlotterType() != PLOT_FORMAT::DXF || GetDXFPlotMode() == FILLED )
1472 m_plotter->SetColor( BLACK );
1473}
1474
1475
1477{
1478 const std::vector<const PCB_DRILL_MAP*> maps = m_board->DrillMapsOnLayer( aLayer );
1479
1480 if( maps.empty() )
1481 return;
1482
1483 const DRILL_SYMBOL_PROFILE& profile = m_board->GetDesignSettings().GetDrillSymbolProfile();
1484
1485 // Resolved rather than read straight from the profile, so a map drawn without any chart
1486 // ever having been placed still shows marks
1487 const std::shared_ptr<const DRILL_SYMBOL_CACHE> cache = m_board->DrillSymbolCache();
1488
1489 // DXF reads its sketch/filled mode back out of this. Without it every stroked mark is
1490 // emitted filled no matter what the user asked for
1491 GBR_METADATA gbr_metadata;
1492
1493 m_plotter->SetColor( getColor( aLayer ) );
1494 m_plotter->SetCurrentLineWidth( profile.GetSymbolWidth() );
1495
1496 DRILL_QUERY query;
1497 query.m_MergePTHNPTH = true;
1498
1499 // Several maps can share a layer. The UI prevents it but a parsed, pasted or
1500 // API-created board need not
1501 for( const PCB_DRILL_MAP* map : maps )
1502 {
1503
1504 const std::shared_ptr<const SHAPE_POLY_SET> outlines = map->GetBoardOutlines();
1505
1506 for( int ii = 0; ii < outlines->OutlineCount(); ++ii )
1507 {
1508 m_plotter->PlotPoly( outlines->COutline( ii ), FILL_T::NO_FILL, profile.GetSymbolWidth(),
1509 getMetadata() );
1510
1511 for( int jj = 0; jj < outlines->HoleCount( ii ); ++jj )
1512 {
1513 m_plotter->PlotPoly( outlines->CHole( ii, jj ), FILL_T::NO_FILL, profile.GetSymbolWidth(),
1514 getMetadata() );
1515 }
1516 }
1517
1518 for( const DRILL_SPAN& span : EnumerateDrillSpans( *m_board ) )
1519 {
1520 // The map's own span filter, so a backdrill map does not print every other hole too
1521 if( !map->GetAllSpans() && !( span == map->GetSpan() ) )
1522 continue;
1523
1524 query.m_Span = span;
1525
1526 for( const DRILL_OPERATION& op : EnumerateDrillOperations( *m_board, query ) )
1527 {
1528 // The map is a set of marks on the holes, displaced as a whole. The holes
1529 // themselves never move
1530 const VECTOR2I pos = op.m_Position + map->GetOffset();
1531
1532 const auto it = cache->m_ByGroup.find( profile.GroupKeyString( op ) );
1533
1534 if( it == cache->m_ByGroup.end() )
1535 continue;
1536
1537 const DRILL_SYMBOL_ASSIGNMENT& assignment = it->second;
1538
1539 if( assignment.m_MarkMode == DRILL_MARK_MODE::SHAPE )
1540 {
1541 m_plotter->Marker( pos, map->GetSymbolSize(),
1543 }
1544 else
1545 {
1546 const wxString text =
1548 ? assignment.m_Letter
1549 : wxString::Format( wxT( "%.2f" ),
1550 pcbIUScale.IUTomm( op.m_Diameter ) );
1551
1552 TEXT_ATTRIBUTES attrs;
1553 attrs.m_Size = VECTOR2I( map->GetSymbolSize(), map->GetSymbolSize() );
1554 attrs.m_StrokeWidth = profile.GetSymbolWidth();
1557
1558 m_plotter->PlotText( pos, getColor( aLayer ), text, attrs, nullptr,
1560 }
1561
1562 if( map->GetGuideCross() )
1563 {
1564 const int reach = map->GetSymbolSize();
1565
1566 m_plotter->ThickSegment( pos - VECTOR2I( reach, 0 ),
1567 pos + VECTOR2I( reach, 0 ),
1568 profile.GetSymbolWidth(), getMetadata() );
1569 m_plotter->ThickSegment( pos - VECTOR2I( 0, reach ),
1570 pos + VECTOR2I( 0, reach ),
1571 profile.GetSymbolWidth(), getMetadata() );
1572 }
1573
1574 // A slot's true extent is the cost driver, so it is drawn as well as marked
1575 if( map->GetOutlineSlots() && op.m_IsSlot )
1576 {
1577 m_plotter->ThickOval( pos, op.m_SizeXY, op.m_Orientation,
1578 profile.GetSymbolWidth(), getMetadata() );
1579 }
1580 }
1581 }
1582 }
1583
1584 m_plotter->SetCurrentLineWidth( PLOTTER::USE_DEFAULT_LINE_WIDTH );
1585}
1586
1587
1589{
1590
1591 if( aChart->GetSymbolColumn() < 0 || aChart->RowShapes().empty() )
1592 return;
1593
1594 const DRILL_SYMBOL_PROFILE& profile = m_board->GetDesignSettings().GetDrillSymbolProfile();
1595
1596 m_plotter->SetColor( getColor( aChart->GetLayer() ) );
1597 m_plotter->SetCurrentLineWidth( profile.GetSymbolWidth() );
1598
1599 for( const auto& [row, shapeIndex] : aChart->RowShapes() )
1600 {
1601 const PCB_TABLECELL* cell = aChart->GetCell( row, aChart->GetSymbolColumn() );
1602
1603 if( !cell )
1604 continue;
1605
1606 const BOX2I box = cell->GetBoundingBox();
1607
1608 // Same fit as the painter, so the plotted chart matches what was on screen
1609 const int size = std::min<int>( profile.GetSymbolSize(),
1610 std::min( box.GetWidth(), box.GetHeight() ) * 2 / 3 );
1611
1612 if( size > 0 )
1613 m_plotter->Marker( box.GetCenter(), size, DRILL_MARKERS::CuratedShape( shapeIndex ) );
1614 }
1615
1616 m_plotter->SetCurrentLineWidth( PLOTTER::USE_DEFAULT_LINE_WIDTH );
1617}
@ ERROR_INSIDE
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
constexpr int ARC_LOW_DEF
Definition base_units.h:136
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:995
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
virtual bool IsKnockout() const
Definition board_item.h:413
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
FOOTPRINT * GetParentFootprint() const
virtual void TransformShapeToPolySet(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, KIGFX::RENDER_SETTINGS *aRenderSettings=nullptr) const
Convert the item shape to a polyset.
Definition board_item.h:542
const KIFONT::METRICS & GetFontMetrics() const
BOARD_ITEM_CONTAINER * GetParent() const
Definition board_item.h:266
int GetMaxError() const
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:553
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:143
constexpr size_type GetWidth() const
Definition box2.h:211
constexpr Vec Centre() const
Definition box2.h:94
constexpr const Vec GetCenter() const
Definition box2.h:227
constexpr size_type GetHeight() const
Definition box2.h:212
constexpr coord_type GetLeft() const
Definition box2.h:225
constexpr coord_type GetRight() const
Definition box2.h:214
constexpr const SizeVec & GetSize() const
Definition box2.h:203
constexpr coord_type GetTop() const
Definition box2.h:226
constexpr coord_type GetBottom() const
Definition box2.h:219
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 PlotChartSymbols(const PCB_DRILL_CHART *aChart)
Shape marks in a chart's symbol column, which carry no cell text of their own.
void PlotPad(const PAD *aPad, PCB_LAYER_ID aLayer, const COLOR4D &aColor, bool aSketchMode)
Plot a pad.
void PlotDimension(const PCB_DIMENSION_BASE *aDim)
void PlotText(const EDA_TEXT *aText, PCB_LAYER_ID aLayer, bool aIsKnockout, const KIFONT::METRICS &aFontMetrics, bool aStrikeout=false)
BOARD * m_board
Definition pcbplot.h:162
void PlotShape(const PCB_SHAPE *aShape)
PLOTTER * m_plotter
Definition pcbplot.h:161
bool crossoutDNPItems(PCB_LAYER_ID aLayer)
Definition pcbplot.h:147
void PlotBarCode(const PCB_BARCODE *aBarCode)
COLOR4D getColor(int aLayer) const
White color is special because it cannot be seen on a white paper in B&W mode.
void PlotPcbTarget(const PCB_TARGET *aMire)
void PlotTableBorders(const PCB_TABLE *aTable)
void PlotFootprintTextItems(const FOOTPRINT *aFootprint)
int getFineWidthAdj() const
Definition pcbplot.h:75
void PlotDrillSymbols(PCB_LAYER_ID aLayer)
Draw each hole's chart symbol on aLayer, from the board's shared symbol profile.
void plotOneDrillMark(PAD_DRILL_SHAPE aDrillShape, const VECTOR2I &aDrillPos, const VECTOR2I &aDrillSize, const VECTOR2I &aPadSize, const EDA_ANGLE &aOrientation, int aSmallDrill)
Helper function to plot a single drill mark.
bool hideDNPItems(PCB_LAYER_ID aLayer)
Definition pcbplot.h:142
void PlotFootprintGraphicItems(const FOOTPRINT *aFootprint)
static const COLOR4D WHITE
Definition color4d.h:402
COLOR4D GetColor(int aLayer) const
Grouping rules and symbol assignments, shared by reference so a chart and its map can never disagree ...
std::string GroupKeyString(const DRILL_OPERATION &aOperation) const
Stable identity for a group under the currently enabled keys.
double AsDegrees() const
Definition eda_angle.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
static bool ShortenSegmentForEndings(VECTOR2I &aStart, VECTOR2I &aEnd, const LINE_ENDING &aStartEnding, const LINE_ENDING &aEndEnding, int aLineWidth)
Shorten a segment body for line endings.
EDA_ANGLE GetArcAngle() const
int GetEllipseMinorRadius() const
Definition eda_shape.h:395
const VECTOR2I & GetEllipseCenter() const
Definition eda_shape.h:377
const SHAPE_POLY_SET & GetHatching() const
EDA_ANGLE GetEllipseEndAngle() const
Definition eda_shape.h:423
int GetEllipseMajorRadius() const
Definition eda_shape.h:386
SHAPE_POLY_SET & GetPolyShape()
void GetEndingTangents(EDA_ANGLE &aStartTangent, EDA_ANGLE &aEndTangent, int aLineWidth=0) const
Compute outward-facing tangent angles at the start and end of the shape.
void CalcArcAngles(EDA_ANGLE &aStartAngle, EDA_ANGLE &aEndAngle) const
Calc arc start and end angles such that aStartAngle < aEndAngle.
EDA_ANGLE GetEllipseRotation() const
Definition eda_shape.h:404
int GetRadius() const
SHAPE_T GetShape() const
Definition eda_shape.h:175
std::vector< SHAPE * > MakeEffectiveShapesForStroking(int aLineWidth=-1) const
Make a set of SHAPE objects to hand to STROKE_PARAMS::Stroke().
bool GetShortenedBodyPolyPoints(const SHAPE_LINE_CHAIN &aOutline, int aOutlineIdx, std::vector< VECTOR2I > &aPoints, int aLineWidth) const
Copy an outline and apply line-ending body shortening when applicable.
bool IsHatchedFill() const
Definition eda_shape.h:130
bool GetLineEndingEndpoints(VECTOR2I &aStartPoint, VECTOR2I &aEndPoint) const
Return the source endpoints used to place line endings.
virtual void SetFilled(bool aFlag)
Definition eda_shape.h:142
bool IsSolidFill() const
Definition eda_shape.h:123
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:325
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:275
std::vector< VECTOR2I > GetRectCorners() const
EDA_ANGLE GetEllipseStartAngle() const
Definition eda_shape.h:414
const LINE_ENDING & GetStartEnding() const
Definition eda_shape.h:177
wxString SHAPE_T_asString() const
std::optional< BEZIER< double > > ShortenedBezierCurve(int aLineWidth) const
Return the cubic Bezier curve shortened for line endings.
bool ShortenArcForEndings(EDA_ANGLE &aStartAngle, EDA_ANGLE &aArcAngle, double aRadius, int aLineWidth) const
Shorten an arc body for line endings.
std::vector< VECTOR2D > ShortenedBezierPolyline(int aLineWidth) const
Return the flattened Bezier polyline after line-ending shortening.
const LINE_ENDING & GetEndEnding() const
Definition eda_shape.h:180
int GetCornerRadius() const
bool IsPolyShapeValid() const
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
virtual VECTOR2I GetTextSize() const
Definition eda_text.h:301
virtual VECTOR2I GetTextPos() const
Definition eda_text.h:313
bool IsMultilineAllowed() const
Definition eda_text.h:236
virtual bool IsVisible() const
Definition eda_text.h:226
std::vector< std::unique_ptr< KIFONT::GLYPH > > * GetRenderCache(const KIFONT::FONT *aFont, const wxString &forResolvedText, const VECTOR2I &aOffset={ 0, 0 }) const
Definition eda_text.cpp:666
virtual EDA_ANGLE GetDrawRotation() const
Definition eda_text.h:419
virtual wxString GetShownText(RESOLUTION_CONTEXT aContext, int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition eda_text.h:128
virtual KIFONT::FONT * GetDrawFont(const RENDER_SETTINGS *aSettings) const
Definition eda_text.cpp:630
const TEXT_ATTRIBUTES & GetAttributes() const
Definition eda_text.h:270
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition eda_text.cpp:422
void GetLinePositions(const RENDER_SETTINGS *aSettings, std::vector< VECTOR2I > &aPositions, int aLineCount) const
Populate aPositions with the position of each line of a multiline text, according to the vertical jus...
Definition eda_text.cpp:914
PCB_FIELD & Value()
read/write accessors:
Definition footprint.h:939
LSET GetPrivateLayers() const
Definition footprint.h:344
PCB_FIELD & Reference()
Definition footprint.h:940
bool GetDNPForVariant(const wxString &aVariantName) const
Get the DNP status for a specific variant.
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
const wxString & GetReference() const
Definition footprint.h:901
DRAWINGS & GraphicalItems()
Definition footprint.h:407
@ GBR_APERTURE_ATTRIB_CONDUCTOR
Aperture used for connected items like tracks (not vias).
@ GBR_APERTURE_ATTRIB_ETCHEDCMP
Aperture used for etched components.
@ GBR_APERTURE_ATTRIB_BGAPAD_CUDEF
Aperture used for BGA pad with a solder mask defined by the solder mask.
@ GBR_APERTURE_ATTRIB_HEATSINKPAD
Aperture used for heat sink pad (typically for SMDs).
@ GBR_APERTURE_ATTRIB_TESTPOINT
Aperture used for test point pad (outer layers).
@ GBR_APERTURE_ATTRIB_SMDPAD_CUDEF
Aperture used for SMD pad with a solder mask defined by the solder mask.
@ GBR_APERTURE_ATTRIB_CONNECTORPAD
Aperture used for edge connector pad (outer layers).
@ GBR_APERTURE_ATTRIB_NONCONDUCTOR
Aperture used for not connected items (texts, outlines on copper).
@ GBR_APERTURE_ATTRIB_WASHERPAD
Aperture used for mechanical pads (NPTH).
@ GBR_APERTURE_ATTRIB_COMPONENTPAD
Aperture used for through hole component on outer layer.
@ GBR_APERTURE_ATTRIB_FIDUCIAL_GLBL
Aperture used for fiducial pad (outer layers), at board level.
@ GBR_APERTURE_ATTRIB_CASTELLATEDPAD
Aperture used for castellated pads in copper layer files.
@ GBR_APERTURE_ATTRIB_FIDUCIAL_LOCAL
Aperture used for fiducial pad (outer layers), at footprint level.
@ GBR_APERTURE_ATTRIB_EDGECUT
Aperture used for board cutout,.
Metadata which can be added in a gerber file as attribute in X2 format.
void SetCopper(bool aValue)
void SetCmpReference(const wxString &aComponentRef)
void SetNetName(const wxString &aNetname)
void SetPadPinFunction(const wxString &aPadPinFunction, bool aUseUTF8, bool aEscapeString)
void SetApertureAttrib(GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB aApertAttribute)
GBR_NETLIST_METADATA m_NetlistMetadata
An item to handle object attribute.
void SetNetAttribType(int aNetAttribType)
void SetPadName(const wxString &aPadname, bool aUseUTF8=false, bool aEscapeString=false)
@ GBR_NETINFO_NET
print info associated to a net (TO.N attribute)
@ GBR_NETINFO_CMP
print info associated to a component (TO.C 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 FlashPadChamferRoundRect(const VECTOR2I &aShapePos, const VECTOR2I &aPadSize, int aCornerRadius, double aChamferRatio, int aChamferPositions, const EDA_ANGLE &aPadOrient, void *aData)
Flash a chamfered round rect pad.
void PlotPolyAsRegion(const SHAPE_LINE_CHAIN &aPoly, FILL_T aFill, int aWidth, GBR_METADATA *aGbrMetadata)
Similar to PlotPoly(), plot a filled polygon using Gerber region, therefore adding X2 attributes to t...
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:94
virtual bool IsOutline() const
Definition font.h:102
static const METRICS & Default()
Definition font.cpp:48
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
virtual void DrawGlyphs(const std::vector< std::unique_ptr< KIFONT::GLYPH > > &aGlyphs)
Draw polygons representing font glyphs.
LINE_ENDING_STYLE GetStyle() const
Definition line_ending.h:81
void Plot(PLOTTER *aPlotter, const VECTOR2I &aPoint, const EDA_ANGLE &aTangent, int aLineWidth, void *aData=nullptr) const
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:604
static const LSET & ExternalCuMask()
Return a mask holding the Front and Bottom layers.
Definition lset.cpp:630
static constexpr PCB_LAYER_ID TEMP_ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:176
Definition pad.h:61
PAD_PROP GetProperty() const
Definition pad.h:561
static wxString ShowPadShape(PAD_SHAPE aShape)
Definition pad.cpp:2540
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives(PCB_LAYER_ID aLayer) const
Accessor to the basic shape list for custom-shaped pads.
Definition pad.h:373
int GetRoundRectCornerRadius(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1170
const BOX2I GetBoundingBox() const override
The bounding box is cached, so this will be efficient most of the time.
Definition pad.cpp:1623
PAD_ATTRIB GetAttribute() const
Definition pad.h:558
const wxString & GetPinFunction() const
Definition pad.h:154
const wxString & GetNumber() const
Definition pad.h:143
const VECTOR2I & GetDelta(PCB_LAYER_ID aLayer) const
Definition pad.h:305
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition pad.h:205
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc=ERROR_INSIDE, bool ignoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
Definition pad.cpp:3010
VECTOR2I GetSize(PCB_LAYER_ID aLayer) const
Definition pad.cpp:288
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition pad.cpp:1747
int GetChamferPositions(PCB_LAYER_ID aLayer) const
Definition pad.h:847
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(PCB_LAYER_ID aLayer, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Definition pad.cpp:1228
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
Definition pad.h:830
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1855
Abstract dimension API.
int GetLineThickness() const
const std::vector< std::shared_ptr< SHAPE > > & GetShapes() const
A drill chart placed on the board, kept in step with the holes.
const std::map< int, int > & RowShapes() const
Curated shape index for each generated row, by table row.
int GetSymbolColumn() const
Table column the symbol is drawn in, or -1 when the chart has no symbol column.
Turns on drill symbols at the holes, for one layer.
bool GetSketchDNPFPsOnFabLayers() const
PLOT_TEXT_MODE GetTextMode() const override
bool GetPlotReference() const
DXF_OUTLINE_MODE GetDXFPlotMode() const override
int GetSketchPadLineWidth() const
DRILL_MARKS GetDrillMarksType() const
bool GetPlotValue() const
bool GetPlotFPText() const
COLOR_SETTINGS * ColorSettings() const
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition pcb_shape.h:78
int GetWidth() const override
bool HasSolderMask() const
Definition pcb_shape.h:336
int GetSolderMaskExpansion() const
void SetShape(SHAPE_T aShape) override
Definition pcb_shape.h:207
void SetEnd(const VECTOR2I &aEnd) override
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
STROKE_PARAMS GetStroke() const override
void SetStart(const VECTOR2I &aStart) override
void SetStroke(const STROKE_PARAMS &aStroke) override
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition pcb_shape.h:68
PCB_TABLECELL * GetCell(int aRow, int aCol) const
Definition pcb_table.h:150
void DrawBorders(const std::function< void(const VECTOR2I &aPt1, const VECTOR2I &aPt2, const STROKE_PARAMS &aStroke)> &aCallback) const
int GetShape() const
Definition pcb_target.h:54
int GetWidth() const
Definition pcb_target.h:60
int GetSize() const
Definition pcb_target.h:57
VECTOR2I GetPosition() const override
Definition pcb_target.h:51
bool IsBorderEnabled() const
Disables the border, this is done by changing the stroke internally.
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
static const int USE_DEFAULT_LINE_WIDTH
Definition plotter.h:140
Definition seg.h:38
VECTOR2I A
Definition seg.h:45
VECTOR2I B
Definition seg.h:46
int GetRadius() const
SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError) const
Build a polyline approximation of the ellipse or arc.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool IsClosed() const override
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int OutlineCount() const
Return the number of outlines in the set.
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
SHAPE_POLY_SET CloneDropTriangulation() 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.
const SHAPE_LINE_CHAIN Outline() const
void SetRadius(int aRadius)
Definition shape_rect.h:202
const SEG & GetSeg() const
An abstract shape on 2D plane.
Definition shape.h:124
Simple container to manage line stroke parameters.
int GetWidth() const
LINE_STYLE GetLineStyle() const
static void Stroke(const SHAPE *aShape, LINE_STYLE aLineStyle, int aWidth, const KIGFX::RENDER_SETTINGS *aRenderSettings, const std::function< void(const VECTOR2I &a, const VECTOR2I &b)> &aStroker)
GR_TEXT_H_ALIGN_T m_Halign
GR_TEXT_V_ALIGN_T m_Valign
Handle a list of polygons defining a copper zone.
Definition zone.h:70
bool IsOnCopperLayer() const override
Definition zone.cpp:616
A type-safe container of any type.
Definition ki_any.h:92
constexpr any() noexcept
Default constructor, creates an empty object.
Definition ki_any.h:155
@ WHITE
Definition color4d.h:44
@ LIGHTGRAY
Definition color4d.h:43
@ BLACK
Definition color4d.h:40
@ FOR_CANVAS
Definition common.h:88
@ ROUND_ALL_CORNERS
All angles are rounded.
std::vector< DRILL_SPAN > EnumerateDrillSpans(const BOARD &aBoard)
Every drill span present on the board, through-holes first.
std::vector< DRILL_OPERATION > EnumerateDrillOperations(const BOARD &aBoard, const DRILL_QUERY &aQuery)
The one place that decides what the board's holes are.
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:422
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:424
FILL_T
Definition eda_fill.h:29
@ NO_FILL
Definition eda_fill.h:30
@ FILLED_SHAPE
Fill with object color.
Definition eda_fill.h:31
@ ELLIPSE
Definition eda_shape.h:62
@ SEGMENT
Definition eda_shape.h:56
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:57
@ ELLIPSE_ARC
Definition eda_shape.h:63
Handle special data (items attributes) during plot.
#define GBR_NETINFO_ALL
static const bool FILLED
Definition gr_basic.cpp:30
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:703
bool IsExternalCopperLayer(int aLayerId)
Test whether a layer is an external (F_Cu or B_Cu) copper layer.
Definition layer_ids.h:714
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ Edge_Cuts
Definition layer_ids.h:108
@ B_Mask
Definition layer_ids.h:94
@ F_Mask
Definition layer_ids.h:93
@ F_Fab
Definition layer_ids.h:115
@ PCB_LAYER_ID_COUNT
Definition layer_ids.h:167
@ B_Fab
Definition layer_ids.h:114
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition macros.h:79
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:92
unsigned CuratedShape(int aIndex)
Pattern index for the nth curated mark.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:411
PAD_DRILL_SHAPE
The set of pad drill shapes, used with PAD::{Set,Get}DrillShape()
Definition padstack.h:68
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:102
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:98
@ PTH
Plated through hole pad.
Definition padstack.h:97
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
Definition padstack.h:99
@ CHAMFERED_RECT
Definition padstack.h:59
@ ROUNDRECT
Definition padstack.h:56
@ TRAPEZOID
Definition padstack.h:55
@ RECTANGLE
Definition padstack.h:53
@ FIDUCIAL_LOCAL
a fiducial (usually a smd) local to the parent footprint
Definition padstack.h:117
@ FIDUCIAL_GLBL
a fiducial (usually a smd) for the full board
Definition padstack.h:116
@ MECHANICAL
a pad used for mechanical support
Definition padstack.h:121
@ PRESSFIT
a PTH with a hole diameter with tight tolerances for press fit pin
Definition padstack.h:122
@ HEATSINK
a pad used as heat sink, usually in SMD footprints
Definition padstack.h:119
@ NONE
no special fabrication property
Definition padstack.h:114
@ TESTPOINT
a test point pad
Definition padstack.h:118
@ CASTELLATED
a pad with a castellated through hole
Definition padstack.h:120
@ BGA
Smd pad, used in BGA footprints.
Definition padstack.h:115
BARCODE class definition.
#define getMetadata()
@ SKETCH
Definition plotter.h:81
@ SH_CIRCLE
circle
Definition shape.h:46
@ SH_SEGMENT
line segment
Definition shape.h:44
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
int PrintableCharCount(const wxString &aString)
Return the number of printable (ie: non-formatting) chars.
LINE_STYLE
Dashed line types.
One machining action, which is also one NC hit and one tool assignment.
Selects which operations EnumerateDrillOperations() returns.
bool m_MergePTHNPTH
Emit plated and non-plated together, as the merged drill file does.
DRILL_SPAN m_Span
const SHAPE_LINE_CHAIN chain
int radius
VECTOR2I end
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_CENTER
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:225
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:80
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition typeinfo.h:98
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:95
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:89
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition typeinfo.h:96
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:85
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:84
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
Definition typeinfo.h:81
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:93
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition typeinfo.h:99
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:94
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition typeinfo.h:86
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition typeinfo.h:97
@ PCB_DRILL_CHART_T
class PCB_DRILL_CHART, a live drill chart derived from PCB_TABLE
Definition typeinfo.h:239
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682