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 m_plotter->MarkFootprintPlotted( aPad->GetParentFootprint() );
163
164 bool plotOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
165 bool plotOnExternalCopperLayer = ( m_layerMask & LSET::ExternalCuMask() ).any();
166
167 // Pad not on the solder mask layer cannot be soldered.
168 // therefore it can have a specific aperture attribute.
169 // Not yet in use.
170 // bool isPadOnBoardTechLayers = ( aPad->GetLayerSet() & LSET::AllBoardTechMask() ).any();
171
172 metadata.SetCmpReference( aPad->GetParentFootprint()->GetReference() );
173
174 if( plotOnCopperLayer )
175 {
177 metadata.SetCopper( true );
178
179 // Gives a default attribute, for instance for pads used as tracks in net ties:
180 // Connector pads and SMD pads are on external layers
181 // if on internal layers, they are certainly used as net tie
182 // and are similar to tracks: just conductor items
184
185 const bool useUTF8 = false;
186 const bool useQuoting = false;
187 metadata.SetPadName( aPad->GetNumber(), useUTF8, useQuoting );
188
189 if( !aPad->GetNumber().IsEmpty() )
190 metadata.SetPadPinFunction( aPad->GetPinFunction(), useUTF8, useQuoting );
191
192 metadata.SetNetName( aPad->GetNetname() );
193
194 // Some pads are mechanical pads ( through hole or smd )
195 // when this is the case, they have no pad name and/or are not plated.
196 // In this case gerber files have slightly different attributes.
197 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH || aPad->GetNumber().IsEmpty() )
198 metadata.m_NetlistMetadata.m_NotInNet = true;
199
200 if( !plotOnExternalCopperLayer )
201 {
202 // the .P object attribute (GBR_NETLIST_METADATA::GBR_NETINFO_PAD)
203 // is used on outer layers, unless the component is embedded
204 // or a "etched" component (fp only drawn, not a physical component)
205 // Currently, Pcbnew does not handle embedded component, so we disable the .P
206 // attribute on internal layers
207 // Note the Gerber doc is not really clear about through holes pads about the .P
210
211 }
212
213 // Some attributes are reserved to the external copper layers:
214 // GBR_APERTURE_ATTRIB_CONNECTORPAD and GBR_APERTURE_ATTRIB_SMDPAD_CUDEF
215 // for instance.
216 // Pad with type PAD_ATTRIB::CONN or PAD_ATTRIB::SMD that is not on outer layer
217 // has its aperture attribute set to GBR_APERTURE_ATTRIB_CONDUCTOR
218 switch( aPad->GetAttribute() )
219 {
220 case PAD_ATTRIB::NPTH: // Mechanical pad through hole
222 break;
223
224 case PAD_ATTRIB::PTH : // Pad through hole, a hole is also expected
226 break;
227
228 case PAD_ATTRIB::CONN: // Connector pads, no solder paste but with solder mask.
229 if( plotOnExternalCopperLayer )
231 break;
232
233 case PAD_ATTRIB::SMD: // SMD pads (on external copper layer only)
234 // with solder paste and mask
235 if( plotOnExternalCopperLayer )
237 break;
238 }
239
240 // Fabrication properties can have specific GBR_APERTURE_METADATA options
241 // that replace previous aperture attribute:
242 switch( aPad->GetProperty() )
243 {
244 case PAD_PROP::BGA: // Only applicable to outer layers
245 if( plotOnExternalCopperLayer )
247 break;
248
251 break;
252
255 break;
256
257 case PAD_PROP::TESTPOINT: // Only applicable to outer layers
258 if( plotOnExternalCopperLayer )
260 break;
261
264 break;
265
268 break;
269
270 case PAD_PROP::PRESSFIT: // used only in drill files
271 case PAD_PROP::NONE:
273 break;
274 }
275
276 // Ensure NPTH pads have *always* the GBR_APERTURE_ATTRIB_WASHERPAD attribute
277 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
279 }
280 else
281 {
283 }
284
285 // Set plot color (change WHITE to LIGHTGRAY because
286 // the white items are not seen on a white paper or screen
287 m_plotter->SetColor( aColor != WHITE ? aColor : LIGHTGRAY );
288
289 if( aSketchMode )
290 {
291 switch( aPad->GetShape( aLayer ) )
292 {
294 m_plotter->ThickCircle( shape_pos, aPad->GetSize( aLayer ).x, GetSketchPadLineWidth(),
295 nullptr );
296 break;
297
298 case PAD_SHAPE::OVAL:
299 {
300 m_plotter->ThickOval( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(),
301 GetSketchPadLineWidth(), nullptr );
302 break;
303 }
304
310 {
311 SHAPE_POLY_SET outline;
312 aPad->TransformShapeToPolygon( outline, aLayer, 0, m_plotter->GetPlotterArcHighDef(),
313 ERROR_INSIDE, false );
314
315 m_plotter->ThickPoly( outline, GetSketchPadLineWidth(), nullptr );
316 break;
317 }
318
319 default:
321 }
322
323 return;
324 }
325
326 switch( aPad->GetShape( aLayer ) )
327 {
329 m_plotter->FlashPadCircle( shape_pos, aPad->GetSize( aLayer ).x, &metadata );
330 break;
331
332 case PAD_SHAPE::OVAL:
333 m_plotter->FlashPadOval( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(), &metadata );
334 break;
335
337 m_plotter->FlashPadRect( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(), &metadata );
338 break;
339
341 m_plotter->FlashPadRoundRect( shape_pos, aPad->GetSize( aLayer ),
342 aPad->GetRoundRectCornerRadius( aLayer ),
343 aPad->GetOrientation(), &metadata );
344 break;
345
347 {
348 // Build the pad polygon in coordinates relative to the pad
349 // (i.e. for a pad at pos 0,0, rot 0.0). Needed to use aperture macros,
350 // to be able to create a pattern common to all trapezoid pads having the same shape
351 VECTOR2I coord[4];
352
353 // Order is lower left, lower right, upper right, upper left.
354 VECTOR2I half_size = aPad->GetSize( aLayer ) / 2;
355 VECTOR2I trap_delta = aPad->GetDelta( aLayer ) / 2;
356
357 coord[0] = VECTOR2I( -half_size.x - trap_delta.y, half_size.y + trap_delta.x );
358 coord[1] = VECTOR2I( half_size.x + trap_delta.y, half_size.y - trap_delta.x );
359 coord[2] = VECTOR2I( half_size.x - trap_delta.y, -half_size.y + trap_delta.x );
360 coord[3] = VECTOR2I( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x );
361
362 m_plotter->FlashPadTrapez( shape_pos, coord, aPad->GetOrientation(), &metadata );
363 break;
364 }
365
367 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
368 {
369 GERBER_PLOTTER* gerberPlotter = static_cast<GERBER_PLOTTER*>( m_plotter );
370
371 gerberPlotter->FlashPadChamferRoundRect( shape_pos, aPad->GetSize( aLayer ),
372 aPad->GetRoundRectCornerRadius( aLayer ),
373 aPad->GetChamferRectRatio( aLayer ),
374 aPad->GetChamferPositions( aLayer ),
375 aPad->GetOrientation(), &metadata );
376 break;
377 }
378
380
381 default:
383 {
384 const std::shared_ptr<SHAPE_POLY_SET>& polygons = aPad->GetEffectivePolygon( aLayer, ERROR_INSIDE );
385
386 if( polygons->OutlineCount() )
387 {
388 m_plotter->FlashPadCustom( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(),
389 polygons.get(), &metadata );
390 }
391 }
392 break;
393 }
394}
395
396
398{
399 if( !GetPlotFPText() )
400 return;
401
402 const wxString variantName = m_board ? m_board->GetCurrentVariant() : wxString();
403 const bool dnp = aFootprint->GetDNPForVariant( variantName );
404
405 const PCB_TEXT* reference = &aFootprint->Reference();
406 PCB_LAYER_ID refLayer = reference->GetLayer();
407
408 // Reference and value have special controls for forcing their plotting
409 if( GetPlotReference()
410 && m_layerMask[refLayer]
411 && reference->IsVisible()
412 && !( dnp && hideDNPItems( refLayer ) ) )
413 {
414 m_plotter->MarkFootprintPlotted( aFootprint );
415 PlotText( reference, refLayer, reference->IsKnockout(), reference->GetFontMetrics(),
416 dnp && crossoutDNPItems( refLayer ) );
417 }
418
419 const PCB_TEXT* value = &aFootprint->Value();
420 PCB_LAYER_ID valueLayer = value->GetLayer();
421
422 if( GetPlotValue()
423 && m_layerMask[valueLayer]
424 && value->IsVisible()
425 && !( dnp && hideDNPItems( valueLayer ) ) )
426 {
427 m_plotter->MarkFootprintPlotted( aFootprint );
428 PlotText( value, valueLayer, value->IsKnockout(), value->GetFontMetrics(), false );
429 }
430
431 std::vector<PCB_TEXT*> texts;
432
433 // Skip the reference and value texts that are handled specially
434 for( PCB_FIELD* field : aFootprint->GetFields() )
435 {
436 wxCHECK2( field, continue );
437
438 if( field->IsReference() || field->IsValue() )
439 continue;
440
441 if( field->IsVisible() )
442 texts.push_back( field );
443 }
444
445 for( BOARD_ITEM* item : aFootprint->GraphicalItems() )
446 {
447 if( PCB_TEXT* textItem = dynamic_cast<PCB_TEXT*>( item ) )
448 texts.push_back( textItem );
449 }
450
451 for( const PCB_TEXT* text : texts )
452 {
453 PCB_LAYER_ID textLayer = text->GetLayer();
454 bool strikeout = false;
455
456 if( textLayer == Edge_Cuts || textLayer >= PCB_LAYER_ID_COUNT )
457 continue;
458
459 if( dnp && hideDNPItems( textLayer ) )
460 continue;
461
462 if( !m_layerMask[textLayer] || aFootprint->GetPrivateLayers().test( textLayer ) )
463 continue;
464
465 if( text->GetText() == wxT( "${REFERENCE}" ) )
466 {
467 if( !GetPlotReference() )
468 continue;
469
470 strikeout = dnp && crossoutDNPItems( textLayer );
471 }
472
473 if( text->GetText() == wxT( "${VALUE}" ) )
474 {
475 if( !GetPlotValue() )
476 continue;
477 }
478
479 m_plotter->MarkFootprintPlotted( aFootprint );
480 PlotText( text, textLayer, text->IsKnockout(), text->GetFontMetrics(), strikeout );
481 }
482}
483
484
486{
487 switch( item->Type() )
488 {
489 case PCB_SHAPE_T:
490 PlotShape( static_cast<const PCB_SHAPE*>( item ) );
491 break;
492
493 case PCB_TEXT_T:
494 {
495 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( item );
496 PlotText( text, text->GetLayer(), text->IsKnockout(), text->GetFontMetrics() );
497 break;
498 }
499
500 case PCB_TEXTBOX_T:
501 {
502 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
503
504 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( item );
505 PlotText( textbox, textbox->GetLayer(), textbox->IsKnockout(), textbox->GetFontMetrics() );
506
507 if( textbox->IsBorderEnabled() )
508 {
509 // PlotShape works only for textbox rotated by 0 or 180 degrees.
510 // This is not always the case so use the polygonal shape of the box of the text box.
512 PlotShape( &dummy );
513 }
514
515 m_plotter->SetTextMode( GetTextMode() );
516 break;
517 }
518
519 case PCB_BARCODE_T:
520 PlotBarCode( static_cast<const PCB_BARCODE*>( item ) );
521 break;
522
523 case PCB_TABLE_T:
525 {
526 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( item );
527
528 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
529
530 for( const PCB_TABLECELL* cell : table->GetCells() )
531 PlotText( cell, cell->GetLayer(), cell->IsKnockout(), cell->GetFontMetrics() );
532
534
535 if( item->Type() == PCB_DRILL_CHART_T )
536 PlotChartSymbols( static_cast<const PCB_DRILL_CHART*>( item ) );
537
538 m_plotter->SetTextMode( GetTextMode() );
539 break;
540 }
541
543 case PCB_DIM_CENTER_T:
544 case PCB_DIM_RADIAL_T:
546 case PCB_DIM_LEADER_T:
547 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
548
549 PlotDimension( static_cast<const PCB_DIMENSION_BASE*>( item ) );
550
551 m_plotter->SetTextMode( GetTextMode() );
552 break;
553
554 case PCB_TARGET_T:
555 PlotPcbTarget( static_cast<const PCB_TARGET*>( item ) );
556 break;
557
558 default:
559 break;
560 }
561}
562
563
565{
566 if( !m_layerMask[aDim->GetLayer()] )
567 return;
568
569 COLOR4D color = ColorSettings()->GetColor( aDim->GetLayer() );
570
571 // Set plot color (change WHITE to LIGHTGRAY because
572 // the white items are not seen on a white paper or screen
573 m_plotter->SetColor( color != WHITE ? color : LIGHTGRAY);
574
575 PlotText( aDim, aDim->GetLayer(), false, aDim->GetFontMetrics() );
576
577 PCB_SHAPE temp_item;
578
580 temp_item.SetLayer( aDim->GetLayer() );
581
582 for( const std::shared_ptr<SHAPE>& shape : aDim->GetShapes() )
583 {
584 switch( shape->Type() )
585 {
586 case SH_SEGMENT:
587 {
588 const SEG& seg = static_cast<const SHAPE_SEGMENT*>( shape.get() )->GetSeg();
589
590 temp_item.SetShape( SHAPE_T::SEGMENT );
591 temp_item.SetStart( seg.A );
592 temp_item.SetEnd( seg.B );
593
594 PlotShape( &temp_item );
595 break;
596 }
597
598 case SH_CIRCLE:
599 {
600 VECTOR2I start( shape->Centre() );
601 int radius = static_cast<const SHAPE_CIRCLE*>( shape.get() )->GetRadius();
602
603 temp_item.SetShape( SHAPE_T::CIRCLE );
604 temp_item.SetFilled( false );
605 temp_item.SetStart( start );
606 temp_item.SetEnd( VECTOR2I( start.x + radius, start.y ) );
607
608 PlotShape( &temp_item );
609 break;
610 }
611
612 default:
613 break;
614 }
615 }
616}
617
618
620{
621 int dx1, dx2, dy1, dy2, radius;
622
623 if( !m_layerMask[aMire->GetLayer()] )
624 return;
625
626 m_plotter->SetColor( getColor( aMire->GetLayer() ) );
627
628 PCB_SHAPE temp_item;
629
630 temp_item.SetShape( SHAPE_T::CIRCLE );
631 temp_item.SetFilled( false );
632 temp_item.SetStroke( STROKE_PARAMS( aMire->GetWidth(), LINE_STYLE::SOLID ) );
633 temp_item.SetLayer( aMire->GetLayer() );
634 temp_item.SetStart( aMire->GetPosition() );
635 radius = aMire->GetSize() / 3;
636
637 if( aMire->GetShape() ) // temp_item X
638 radius = aMire->GetSize() / 2;
639
640 // Draw the circle
641 temp_item.SetEnd( VECTOR2I( temp_item.GetStart().x + radius, temp_item.GetStart().y ) );
642
643 PlotShape( &temp_item );
644
645 temp_item.SetShape( SHAPE_T::SEGMENT );
646
647 radius = aMire->GetSize() / 2;
648 dx1 = radius;
649 dy1 = 0;
650 dx2 = 0;
651 dy2 = radius;
652
653 if( aMire->GetShape() ) // Shape X
654 {
655 dx1 = dy1 = radius;
656 dx2 = dx1;
657 dy2 = -dy1;
658 }
659
660 VECTOR2I mirePos( aMire->GetPosition() );
661
662 // Draw the X or + temp_item:
663 temp_item.SetStart( VECTOR2I( mirePos.x - dx1, mirePos.y - dy1 ) );
664 temp_item.SetEnd( VECTOR2I( mirePos.x + dx1, mirePos.y + dy1 ) );
665 PlotShape( &temp_item );
666
667 temp_item.SetStart( VECTOR2I( mirePos.x - dx2, mirePos.y - dy2 ) );
668 temp_item.SetEnd( VECTOR2I( mirePos.x + dx2, mirePos.y + dy2 ) );
669 PlotShape( &temp_item );
670}
671
672
674{
675 const wxString variantName = m_board ? m_board->GetCurrentVariant() : wxString();
676 const bool dnp = aFootprint->GetDNPForVariant( variantName );
677
678 for( const BOARD_ITEM* item : aFootprint->GraphicalItems() )
679 {
680 PCB_LAYER_ID itemLayer = item->GetLayer();
681
682 if( aFootprint->GetPrivateLayers().test( itemLayer ) )
683 continue;
684
685 if( dnp && hideDNPItems( itemLayer ) )
686 continue;
687
688 if( !( m_layerMask & item->GetLayerSet() ).any() )
689 continue;
690
691 m_plotter->MarkFootprintPlotted( aFootprint );
692
693 switch( item->Type() )
694 {
695 case PCB_SHAPE_T:
696 PlotShape( static_cast<const PCB_SHAPE*>( item ) );
697 break;
698
699 case PCB_TEXTBOX_T:
700 {
701 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( item );
702
703 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
704
705 PlotText( textbox, textbox->GetLayer(), textbox->IsKnockout(),
706 textbox->GetFontMetrics() );
707
708 if( textbox->IsBorderEnabled() )
709 {
710 // PlotShape works only for textbox rotated by 0 or 180 degrees.
711 // This is not always the case so use the polygonal shape
713 PlotShape( &dummy );
714 }
715
716 m_plotter->SetTextMode( GetTextMode() );
717 break;
718 }
719
720 case PCB_BARCODE_T:
721 PlotBarCode( static_cast<const PCB_BARCODE*>( item ) );
722 break;
723
724 case PCB_TABLE_T:
726 {
727 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( item );
728
729 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
730
731 for( const PCB_TABLECELL* cell : table->GetCells() )
732 PlotText( cell, cell->GetLayer(), cell->IsKnockout(), cell->GetFontMetrics() );
733
735
736 m_plotter->SetTextMode( GetTextMode() );
737 break;
738 }
739
741 case PCB_DIM_CENTER_T:
742 case PCB_DIM_RADIAL_T:
744 case PCB_DIM_LEADER_T:
745 PlotDimension( static_cast<const PCB_DIMENSION_BASE*>( item ) );
746 break;
747
748 case PCB_TEXT_T:
749 // Plotted in PlotFootprintTextItems()
750 break;
751
753 // Not plotted at all
754 break;
755
756 default:
757 UNIMPLEMENTED_FOR( item->GetClass() );
758 }
759 }
760}
761
762
763#define getMetadata() ( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER ? (void*) &gbr_metadata \
764 : m_plotter->GetPlotterType() == PLOT_FORMAT::DXF ? (void*) this \
765 : (void*) nullptr )
766
767
768void BRDITEMS_PLOTTER::PlotText( const EDA_TEXT* aText, PCB_LAYER_ID aLayer, bool aIsKnockout,
769 const KIFONT::METRICS& aFontMetrics, bool aStrikeout )
770{
771 int maxError = m_board->GetDesignSettings().m_MaxError;
772 KIFONT::FONT* font = aText->GetDrawFont( m_plotter->RenderSettings() );
773 wxString shownText( aText->GetShownText( FOR_CANVAS ) );
774
775 const PCB_TEXTBOX* knockoutBox = aIsKnockout ? dynamic_cast<const PCB_TEXTBOX*>( aText ) : nullptr;
776
777 if( shownText.IsEmpty() && !knockoutBox )
778 return;
779
780 if( !m_layerMask[aLayer] )
781 return;
782
783 GBR_METADATA gbr_metadata;
784
785 if( IsCopperLayer( aLayer ) )
787
788 COLOR4D color = getColor( aLayer );
789 m_plotter->SetColor( color );
790
791 const VECTOR2I& pos = aText->GetTextPos();
792
793 TEXT_ATTRIBUTES attrs = aText->GetAttributes();
794 attrs.m_Size = aText->GetTextSize();
796 attrs.m_Angle = aText->GetDrawRotation();
797 attrs.m_Multiline = false;
798
799 m_plotter->SetCurrentLineWidth( attrs.m_StrokeWidth );
800
801 auto strikeoutText =
802 [&]( const PCB_TEXT* text )
803 {
804 SHAPE_POLY_SET textPoly;
805
806 text->TransformTextToPolySet( textPoly, 0, ARC_LOW_DEF, ERROR_INSIDE );
807 textPoly.Rotate( -text->GetDrawRotation(), text->GetDrawPos() );
808
809 BOX2I rect = textPoly.BBox();
810 VECTOR2I start( rect.GetLeft() - attrs.m_StrokeWidth,
811 ( rect.GetTop() + rect.GetBottom() ) / 2 );
812 VECTOR2I end( rect.GetRight() + attrs.m_StrokeWidth,
813 ( rect.GetTop() + rect.GetBottom() ) / 2 );
814
815 RotatePoint( start, text->GetDrawPos(), text->GetDrawRotation() );
816 RotatePoint( end, text->GetDrawPos(), text->GetDrawRotation() );
817
818 m_plotter->ThickSegment( start, end, attrs.m_StrokeWidth, getMetadata() );
819 };
820
821 if( aIsKnockout )
822 {
823 SHAPE_POLY_SET finalPoly;
824
825 if( knockoutBox )
826 knockoutBox->TransformTextToPolySet( finalPoly, 0, maxError, ERROR_INSIDE );
827 else if( const PCB_TEXT* text = dynamic_cast<const PCB_TEXT*>( aText ) )
828 text->TransformTextToPolySet( finalPoly, 0, maxError, ERROR_INSIDE );
829
830 finalPoly.Fracture();
831
832 for( int ii = 0; ii < finalPoly.OutlineCount(); ++ii )
833 m_plotter->PlotPoly( finalPoly.Outline( ii ), FILL_T::FILLED_SHAPE, 0, getMetadata() );
834 }
835 else
836 {
837 if( font->IsOutline() && !m_board->GetEmbeddedFiles()->GetAreFontsEmbedded() )
838 {
840
841 CALLBACK_GAL callback_gal( empty_opts,
842 // Stroke callback
843 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
844 {
845 m_plotter->ThickSegment( aPt1, aPt2, attrs.m_StrokeWidth, getMetadata() );
846 },
847 // Polygon callback
848 [&]( const SHAPE_LINE_CHAIN& aPoly )
849 {
850 m_plotter->PlotPoly( aPoly, FILL_T::FILLED_SHAPE, 0, getMetadata() );
851 } );
852
853 callback_gal.DrawGlyphs( *aText->GetRenderCache( font, shownText ) );
854 }
855 else if( aText->IsMultilineAllowed() )
856 {
857 std::vector<VECTOR2I> positions;
858 wxArrayString strings_list;
859 wxStringSplit( shownText, strings_list, '\n' );
860 positions.reserve( strings_list.Count() );
861
862 aText->GetLinePositions( m_plotter->RenderSettings(), positions, (int) strings_list.Count() );
863
864 for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
865 {
866 wxString& txt = strings_list.Item( ii );
867 m_plotter->PlotText( positions[ii], color, txt, attrs, font, aFontMetrics, getMetadata() );
868 }
869
870 if( aStrikeout && strings_list.Count() == 1 )
871 strikeoutText( static_cast<const PCB_TEXT*>( aText ) );
872 }
873 else
874 {
875 m_plotter->PlotText( pos, color, shownText, attrs, font, aFontMetrics, getMetadata() );
876
877 if( aStrikeout )
878 strikeoutText( static_cast<const PCB_TEXT*>( aText ) );
879 }
880 }
881}
882
883
884void BRDITEMS_PLOTTER::PlotZone( const ZONE* aZone, PCB_LAYER_ID aLayer, const SHAPE_POLY_SET& aPolysList )
885{
886 if( aPolysList.IsEmpty() )
887 return;
888
889 GBR_METADATA gbr_metadata;
890
891 if( aZone->IsOnCopperLayer() )
892 {
893 gbr_metadata.SetNetName( aZone->GetNetname() );
894 gbr_metadata.SetCopper( true );
895
896 // Zones with no net name can exist.
897 // they are not used to connect items, so the aperture attribute cannot
898 // be set as conductor
899 if( aZone->GetNetname().IsEmpty() )
900 {
902 }
903 else
904 {
907 }
908 }
909
910 m_plotter->SetColor( getColor( aLayer ) );
911
912 m_plotter->StartBlock( nullptr ); // Clean current object attributes
913
914 /*
915 * In non filled mode the outline is plotted, but not the filling items
916 */
917
918 for( int idx = 0; idx < aPolysList.OutlineCount(); ++idx )
919 {
920 const SHAPE_LINE_CHAIN& outline = aPolysList.Outline( idx );
921
922 // Plot the current filled area (as region for Gerber plotter to manage attributes)
923 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
924 {
925 static_cast<GERBER_PLOTTER*>( m_plotter )->PlotGerberRegion( outline, &gbr_metadata );
926 }
927 else if( m_plotter->GetPlotterType() == PLOT_FORMAT::DXF )
928 {
929 if( GetDXFPlotMode() == FILLED )
930 m_plotter->PlotPoly( outline, FILL_T::FILLED_SHAPE, 0, getMetadata() );
931 }
932 else
933 {
934 m_plotter->PlotPoly( outline, FILL_T::FILLED_SHAPE, 0, getMetadata() );
935 }
936 }
937
938 m_plotter->EndBlock( nullptr ); // Clear object attributes
939}
940
941
943{
944 if( !( m_layerMask & aShape->GetLayerSet() ).any() )
945 return;
946
947 int thickness = aShape->GetWidth();
948 int margin = thickness; // unclamped thickness (can be negative)
949 LINE_STYLE lineStyle = aShape->GetStroke().GetLineStyle();
950 bool onCopperLayer = ( LSET::AllCuMask() & m_layerMask ).any();
951 bool onSolderMaskLayer = ( LSET( { F_Mask, B_Mask } ) & m_layerMask ).any();
952 bool isSolidFill = aShape->IsSolidFill();
953 bool isHatchedFill = aShape->IsHatchedFill();
954
955 if( onSolderMaskLayer
956 && aShape->HasSolderMask()
957 && IsExternalCopperLayer( aShape->GetLayer() ) )
958 {
959 margin += 2 * aShape->GetSolderMaskExpansion();
960 thickness = std::max( margin, 0 );
961
962 if( isHatchedFill )
963 {
964 isSolidFill = true;
965 isHatchedFill = false;
966 }
967 }
968
969 m_plotter->SetColor( getColor( aShape->GetLayer() ) );
970
971 const FOOTPRINT* parentFP = aShape->GetParentFootprint();
972 GBR_METADATA gbr_metadata;
973 const wxString variantName = m_board ? m_board->GetCurrentVariant() : wxString();
974 const bool parentDnp = parentFP ? parentFP->GetDNPForVariant( variantName ) : false;
975
976 if( parentFP )
977 {
978 gbr_metadata.SetCmpReference( parentFP->GetReference() );
980 }
981
982 if( parentFP && parentDnp && GetSketchDNPFPsOnFabLayers() )
983 {
984 if( aShape->GetLayer() == F_Fab || aShape->GetLayer() == B_Fab )
985 {
986 thickness = GetSketchPadLineWidth();
987 isSolidFill = false;
988 isHatchedFill = false;
989 }
990 }
991
992 if( aShape->GetLayer() == Edge_Cuts )
993 {
995 }
996 else if( onCopperLayer )
997 {
998 if( parentFP )
999 {
1001 gbr_metadata.SetCopper( true );
1002 }
1003 else if( aShape->GetNetCode() > 0 )
1004 {
1005 gbr_metadata.SetCopper( true );
1008 gbr_metadata.SetNetName( aShape->GetNetname() );
1009 }
1010 else
1011 {
1012 // Graphic items (PCB_SHAPE, TEXT) having no net have the NonConductor attribute
1013 // Graphic items having a net have the Conductor attribute, but are not (yet?)
1014 // supported in Pcbnew
1016 }
1017 }
1018
1019 if( lineStyle <= LINE_STYLE::FIRST_TYPE )
1020 {
1021 switch( aShape->GetShape() )
1022 {
1023 case SHAPE_T::SEGMENT:
1024 {
1025 VECTOR2I segStart = aShape->GetStart();
1026 VECTOR2I segEnd = aShape->GetEnd();
1027
1028 if( EDA_SHAPE::ShortenSegmentForEndings( segStart, segEnd, aShape->GetStartEnding(), aShape->GetEndEnding(),
1029 thickness ) )
1030 {
1031 m_plotter->ThickSegment( segStart, segEnd, thickness, getMetadata() );
1032 }
1033
1034 break;
1035 }
1036
1037 case SHAPE_T::CIRCLE:
1038 if( isSolidFill )
1039 {
1040 int diameter = aShape->GetRadius() * 2 + thickness;
1041
1042 if( margin < 0 )
1043 {
1044 diameter += margin;
1045 diameter = std::max( diameter, 0 );
1046 }
1047
1048 m_plotter->FilledCircle( aShape->GetStart(), diameter, getMetadata() );
1049 }
1050 else
1051 {
1052 m_plotter->ThickCircle( aShape->GetStart(), aShape->GetRadius() * 2, thickness, getMetadata() );
1053 }
1054
1055 break;
1056
1057 case SHAPE_T::ARC:
1058 {
1059 // when startAngle == endAngle ThickArc() doesn't know whether it's 0 deg and 360 deg
1060 // but it is a circle
1061 if( std::abs( aShape->GetArcAngle().AsDegrees() ) == 360.0 )
1062 {
1063 m_plotter->ThickCircle( aShape->GetCenter(), aShape->GetRadius() * 2, thickness, getMetadata() );
1064 }
1065 else
1066 {
1067 EDA_ANGLE startAngle;
1068 EDA_ANGLE endAngle;
1069 aShape->CalcArcAngles( startAngle, endAngle );
1070
1071 EDA_ANGLE arcAngle = endAngle - startAngle;
1072
1073 if( aShape->ShortenArcForEndings( startAngle, arcAngle, aShape->GetRadius(), thickness ) )
1074 {
1075 m_plotter->ThickArc( VECTOR2D( aShape->GetCenter() ), startAngle, arcAngle, aShape->GetRadius(),
1076 thickness, getMetadata() );
1077 }
1078 }
1079
1080 break;
1081 }
1082
1083 case SHAPE_T::BEZIER:
1084 if( std::optional<BEZIER<double>> curve = aShape->ShortenedBezierCurve( thickness ) )
1085 {
1086 if( m_plotter->GetPlotterType() == PLOT_FORMAT::SVG )
1087 {
1088 m_plotter->BezierCurve( VECTOR2I( curve->Start ), VECTOR2I( curve->C1 ), VECTOR2I( curve->C2 ),
1089 VECTOR2I( curve->End ), aShape->GetMaxError(), thickness );
1090 }
1091 else
1092 {
1093 std::vector<VECTOR2D> pts = aShape->ShortenedBezierPolyline( thickness );
1094
1095 for( size_t i = 0; i + 1 < pts.size(); i++ )
1096 m_plotter->ThickSegment( VECTOR2I( pts[i] ), VECTOR2I( pts[i + 1] ), thickness, getMetadata() );
1097 }
1098 }
1099
1100 break;
1101
1102 case SHAPE_T::POLY:
1103 if( aShape->IsPolyShapeValid() )
1104 {
1105 auto plotStrokeOutline =
1106 [&]( const SHAPE_LINE_CHAIN& aOutline, int aOutlineIdx )
1107 {
1108 if( aOutline.PointCount() < 2 )
1109 return;
1110
1111 if( aShape->GetStartEnding().GetShortenDepth( thickness ) > 0
1112 || aShape->GetEndEnding().GetShortenDepth( thickness ) > 0 )
1113 {
1114 std::vector<VECTOR2I> pts;
1115
1116 if( !aShape->GetShortenedBodyPolyPoints( aOutline, aOutlineIdx, pts, thickness ) )
1117 return;
1118
1119 SHAPE_LINE_CHAIN shortened;
1120
1121 for( const VECTOR2I& pt : pts )
1122 shortened.Append( pt );
1123
1124 shortened.SetClosed( aOutline.IsClosed() );
1125 m_plotter->PlotPoly( shortened, FILL_T::NO_FILL, thickness, getMetadata() );
1126 }
1127 else
1128 {
1129 m_plotter->PlotPoly( aOutline, FILL_T::NO_FILL, thickness, getMetadata() );
1130 }
1131 };
1132
1133 if( m_plotter->GetPlotterType() == PLOT_FORMAT::DXF && GetDXFPlotMode() == SKETCH )
1134 {
1135 m_plotter->ThickPoly( aShape->GetPolyShape(), thickness, getMetadata() );
1136 }
1137 else
1138 {
1139 m_plotter->SetCurrentLineWidth( thickness, &gbr_metadata );
1140
1141 const SHAPE_POLY_SET& origPoly = aShape->GetPolyShape();
1142
1143 // Stroke the unfractured outline so degenerate near-zero-width
1144 // spikes (which Fracture() collapses but the editor still draws as
1145 // thick lines) are preserved in the plot output (issue #24143).
1146 if( thickness > 0 )
1147 {
1148 for( int jj = 0; jj < origPoly.OutlineCount(); ++jj )
1149 plotStrokeOutline( origPoly.COutline( jj ), jj );
1150 }
1151
1152 if( !isSolidFill )
1153 break;
1154
1155 // Fracture before plotting the fill to avoid invalid gerber regions
1156 // from self-intersecting or overlapping outlines.
1157 SHAPE_POLY_SET tmpPoly = origPoly.CloneDropTriangulation();
1158 tmpPoly.Fracture();
1159
1160 if( margin < 0 )
1161 tmpPoly.Inflate( margin / 2, CORNER_STRATEGY::ROUND_ALL_CORNERS, aShape->GetMaxError() );
1162
1163 for( int jj = 0; jj < tmpPoly.OutlineCount(); ++jj )
1164 {
1165 SHAPE_LINE_CHAIN& poly = tmpPoly.Outline( jj );
1166 poly.SetClosed( true );
1167
1168 // Width 0; the stroke was already plotted from the unfractured outline.
1169 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1170 {
1171 GERBER_PLOTTER* gbr_plotter = static_cast<GERBER_PLOTTER*>( m_plotter );
1172 gbr_plotter->PlotPolyAsRegion( poly, FILL_T::FILLED_SHAPE, 0, &gbr_metadata );
1173 }
1174 else
1175 {
1176 m_plotter->PlotPoly( poly, FILL_T::FILLED_SHAPE, 0, getMetadata() );
1177 }
1178 }
1179 }
1180 }
1181
1182 break;
1183
1184 case SHAPE_T::RECTANGLE:
1185 {
1186 int radius = aShape->GetCornerRadius();
1187
1188 if( radius == 0 && m_plotter->GetPlotterType() == PLOT_FORMAT::DXF && GetDXFPlotMode() == SKETCH )
1189 {
1190 std::vector<VECTOR2I> pts = aShape->GetRectCorners();
1191 m_plotter->ThickRect( pts[0], pts[2], thickness, getMetadata() );
1192 }
1193 else
1194 {
1195 BOX2I box( aShape->GetStart(), VECTOR2I( aShape->GetEnd().x - aShape->GetStart().x,
1196 aShape->GetEnd().y - aShape->GetStart().y ) );
1197 box.Normalize();
1198
1199 if( margin < 0 )
1200 {
1201 box.Inflate( margin );
1202 radius += margin;
1203 }
1204
1205 SHAPE_RECT rect( box );
1206 rect.SetRadius( radius );
1207
1208 SHAPE_LINE_CHAIN outline = rect.Outline();
1209 SHAPE_POLY_SET poly( outline );
1210
1211 FILL_T fill_mode = isSolidFill ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL;
1212
1213 if( poly.OutlineCount() > 0 )
1214 {
1215 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1216 {
1217 GERBER_PLOTTER* gbr_plotter = static_cast<GERBER_PLOTTER*>( m_plotter );
1218 gbr_plotter->PlotPolyAsRegion( poly.COutline( 0 ), fill_mode, thickness, &gbr_metadata );
1219 }
1220 else
1221 {
1222 // TODO: PlotPoly needs to handle arcs...
1223 m_plotter->PlotPoly( poly.COutline( 0 ), fill_mode, thickness, getMetadata() );
1224 }
1225 }
1226 }
1227
1228 break;
1229 }
1230
1231 case SHAPE_T::ELLIPSE:
1233 {
1234 const bool isClosed = ( aShape->GetShape() == SHAPE_T::ELLIPSE );
1235
1236 SHAPE_ELLIPSE e = isClosed ? SHAPE_ELLIPSE( aShape->GetEllipseCenter(), aShape->GetEllipseMajorRadius(),
1237 aShape->GetEllipseMinorRadius(), aShape->GetEllipseRotation() )
1239 aShape->GetEllipseMinorRadius(), aShape->GetEllipseRotation(),
1240 aShape->GetEllipseStartAngle(), aShape->GetEllipseEndAngle() );
1241
1243
1244 if( isClosed )
1245 chain.SetClosed( true );
1246
1247 FILL_T fill = ( isClosed && isSolidFill ) ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL;
1248
1249 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER && isClosed )
1250 {
1251 GERBER_PLOTTER* gbr_plotter = static_cast<GERBER_PLOTTER*>( m_plotter );
1252 gbr_plotter->PlotPolyAsRegion( chain, fill, thickness, &gbr_metadata );
1253 }
1254 else
1255 {
1256 m_plotter->PlotPoly( chain, fill, thickness, getMetadata() );
1257 }
1258
1259 break;
1260 }
1261
1262 default:
1264 }
1265 }
1266 else
1267 {
1268 std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapesForStroking( thickness );
1269
1270 for( SHAPE* shape : shapes )
1271 {
1272 STROKE_PARAMS::Stroke( shape, lineStyle, aShape->GetWidth(),
1273 m_plotter->RenderSettings(),
1274 [&]( const VECTOR2I& a, const VECTOR2I& b )
1275 {
1276 m_plotter->ThickSegment( a, b, thickness, getMetadata() );
1277 } );
1278 }
1279
1280 for( SHAPE* shape : shapes )
1281 delete shape;
1282 }
1283
1284 // Plot line endings for open shapes.
1287 {
1288 EDA_ANGLE startTangent, endTangent;
1289 aShape->GetEndingTangents( startTangent, endTangent, thickness );
1290
1291 VECTOR2I startPt, endPt;
1292
1293 if( aShape->GetLineEndingEndpoints( startPt, endPt ) )
1294 {
1295 aShape->GetStartEnding().Plot( m_plotter, startPt, startTangent, thickness, getMetadata() );
1296 aShape->GetEndEnding().Plot( m_plotter, endPt, endTangent, thickness, getMetadata() );
1297 }
1298 }
1299
1300 if( isHatchedFill )
1301 {
1302 for( int ii = 0; ii < aShape->GetHatching().OutlineCount(); ++ii )
1303 {
1304 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1305 {
1306 GERBER_PLOTTER* gbr_plotter = static_cast<GERBER_PLOTTER*>( m_plotter );
1307 gbr_plotter->PlotPolyAsRegion( aShape->GetHatching().Outline( ii ), FILL_T::FILLED_SHAPE, 0,
1308 &gbr_metadata );
1309 }
1310 else
1311 {
1312 m_plotter->PlotPoly( aShape->GetHatching().Outline( ii ), FILL_T::FILLED_SHAPE, 0, getMetadata() );
1313 }
1314 }
1315 }
1316}
1317
1318
1320{
1321 if( !m_layerMask[aBarCode->GetLayer()] )
1322 return;
1323
1324 // To avoid duplicate code, build a PCB_SHAPE to plot the polygon shape
1325 PCB_SHAPE dummy( aBarCode->GetParent(), SHAPE_T::POLY );
1326 dummy.SetLayer( aBarCode->GetLayer() );
1327 dummy.SetFillMode( FILL_T::FILLED_SHAPE );
1328 dummy.SetWidth( 0 );
1329
1330 SHAPE_POLY_SET shape;
1331 aBarCode->TransformShapeToPolySet( shape, aBarCode->GetLayer(), 0, 0, ERROR_INSIDE );
1332 dummy.SetPolyShape( shape );
1333
1334 PlotShape( &dummy );
1335}
1336
1337
1339{
1340 if( !m_layerMask[aTable->GetLayer()] )
1341 return;
1342
1343 GBR_METADATA gbr_metadata;
1344
1345 if( const FOOTPRINT* parentFP = aTable->GetParentFootprint() )
1346 {
1347 gbr_metadata.SetCmpReference( parentFP->GetReference() );
1349 }
1350
1351 aTable->DrawBorders(
1352 [&]( const VECTOR2I& ptA, const VECTOR2I& ptB, const STROKE_PARAMS& stroke )
1353 {
1354 int lineWidth = stroke.GetWidth();
1355 LINE_STYLE lineStyle = stroke.GetLineStyle();
1356
1357 if( lineStyle <= LINE_STYLE::FIRST_TYPE )
1358 {
1359 m_plotter->ThickSegment( ptA, ptB, lineWidth, getMetadata() );
1360 }
1361 else
1362 {
1363 SHAPE_SEGMENT seg( ptA, ptB );
1364
1365 STROKE_PARAMS::Stroke( &seg, lineStyle, lineWidth, m_plotter->RenderSettings(),
1366 [&]( const VECTOR2I& a, const VECTOR2I& b )
1367 {
1368 m_plotter->ThickSegment( a, b, lineWidth, getMetadata() );
1369 } );
1370 }
1371 } );
1372}
1373
1374
1376 const VECTOR2I& aDrillSize, const VECTOR2I& aPadSize,
1377 const EDA_ANGLE& aOrientation, int aSmallDrill )
1378{
1379 VECTOR2I drillSize = aDrillSize;
1380
1381 // Small drill marks have no significance when applied to slots
1382 if( aSmallDrill && aDrillShape == PAD_DRILL_SHAPE::CIRCLE )
1383 drillSize.x = std::min( aSmallDrill, drillSize.x );
1384
1385 // Round holes only have x diameter, slots have both
1386 drillSize.x -= getFineWidthAdj();
1387 drillSize.x = std::clamp( drillSize.x, 1, aPadSize.x - 1 );
1388
1389 if( aDrillShape == PAD_DRILL_SHAPE::OBLONG )
1390 {
1391 drillSize.y -= getFineWidthAdj();
1392 drillSize.y = std::clamp( drillSize.y, 1, aPadSize.y - 1 );
1393
1394 m_plotter->FlashPadOval( aDrillPos, drillSize, aOrientation, nullptr );
1395 }
1396 else
1397 {
1398 m_plotter->FlashPadCircle( aDrillPos, drillSize.x, nullptr );
1399 }
1400}
1401
1402
1404{
1405 int smallDrill = 0;
1406
1408 smallDrill = pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize );
1409
1410 /* Drill marks are drawn white-on-black to knock-out the underlying pad. This works only
1411 * for drivers supporting color change, obviously... it means that:
1412 - PS, SVG and PDF output is correct (i.e. you have a 'donut' pad)
1413 - In gerbers you can't see them. This is arguably the right thing to do since having
1414 drill marks and high speed drill stations is a sure recipe for broken tools and angry
1415 manufacturers. If you *really* want them you could start a layer with negative
1416 polarity to knock-out the film.
1417 - In DXF they go into the 'WHITE' layer. This could be useful.
1418 */
1419 if( m_plotter->GetPlotterType() != PLOT_FORMAT::DXF || GetDXFPlotMode() == FILLED )
1420 m_plotter->SetColor( WHITE );
1421
1422 for( PCB_TRACK* track : m_board->Tracks() )
1423 {
1424 if( track->Type() == PCB_VIA_T )
1425 {
1426 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
1427
1428 // Via are not always on all layers
1429 if( ( via->GetLayerSet() & m_layerMask ).none() )
1430 continue;
1431
1433 VECTOR2I( via->GetDrillValue(), 0 ),
1434 VECTOR2I( via->GetWidth( PADSTACK::TEMP_ALL_LAYERS ), 0 ),
1435 ANGLE_0, smallDrill );
1436 }
1437 }
1438
1439 for( FOOTPRINT* footprint : m_board->Footprints() )
1440 {
1441 for( PAD* pad : footprint->Pads() )
1442 {
1443 if( pad->GetDrillSize().x == 0 )
1444 continue;
1445
1446 // Skip marks on layers the pad isn't on for Gerber only (24416). Other
1447 // formats keep them as a drill map, e.g. Edge.Cuts (24867).
1448 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER && ( pad->GetLayerSet() & m_layerMask ).none() )
1449 continue;
1450
1451 if( m_plotter->GetPlotterType() != PLOT_FORMAT::DXF || GetDXFPlotMode() == FILLED )
1452 {
1453 // Drill mark is in black unless we can find something to knock it out of
1454 m_plotter->SetColor( BLACK );
1455
1456 for( PCB_LAYER_ID layer : m_layerMask )
1457 {
1458 if( !pad->IsOnLayer( layer ) )
1459 continue;
1460
1461 VECTOR2I padSize = pad->GetSize( layer );
1462
1463 if( padSize.x > pad->GetDrillSizeX() || padSize.y > pad->GetDrillSizeY() )
1464 {
1465 m_plotter->SetColor( WHITE );
1466 break;
1467 }
1468 }
1469 }
1470
1471 plotOneDrillMark( pad->GetDrillShape(), pad->GetPosition(), pad->GetDrillSize(),
1472 pad->GetSize( PADSTACK::TEMP_ALL_LAYERS ), pad->GetOrientation(), smallDrill );
1473 }
1474 }
1475
1476 if( m_plotter->GetPlotterType() != PLOT_FORMAT::DXF || GetDXFPlotMode() == FILLED )
1477 m_plotter->SetColor( BLACK );
1478}
1479
1480
1482{
1483 const std::vector<const PCB_DRILL_MAP*> maps = m_board->DrillMapsOnLayer( aLayer );
1484
1485 if( maps.empty() )
1486 return;
1487
1488 const DRILL_SYMBOL_PROFILE& profile = m_board->GetDesignSettings().GetDrillSymbolProfile();
1489
1490 // Resolved rather than read straight from the profile, so a map drawn without any chart
1491 // ever having been placed still shows marks
1492 const std::shared_ptr<const DRILL_SYMBOL_CACHE> cache = m_board->DrillSymbolCache();
1493
1494 // DXF reads its sketch/filled mode back out of this. Without it every stroked mark is
1495 // emitted filled no matter what the user asked for
1496 GBR_METADATA gbr_metadata;
1497
1498 m_plotter->SetColor( getColor( aLayer ) );
1499 m_plotter->SetCurrentLineWidth( profile.GetSymbolWidth() );
1500
1501 DRILL_QUERY query;
1502 query.m_MergePTHNPTH = true;
1503
1504 // Several maps can share a layer. The UI prevents it but a parsed, pasted or
1505 // API-created board need not
1506 for( const PCB_DRILL_MAP* map : maps )
1507 {
1508
1509 const std::shared_ptr<const SHAPE_POLY_SET> outlines = map->GetBoardOutlines();
1510
1511 for( int ii = 0; ii < outlines->OutlineCount(); ++ii )
1512 {
1513 m_plotter->PlotPoly( outlines->COutline( ii ), FILL_T::NO_FILL, profile.GetSymbolWidth(),
1514 getMetadata() );
1515
1516 for( int jj = 0; jj < outlines->HoleCount( ii ); ++jj )
1517 {
1518 m_plotter->PlotPoly( outlines->CHole( ii, jj ), FILL_T::NO_FILL, profile.GetSymbolWidth(),
1519 getMetadata() );
1520 }
1521 }
1522
1523 for( const DRILL_SPAN& span : EnumerateDrillSpans( *m_board ) )
1524 {
1525 // The map's own span filter, so a backdrill map does not print every other hole too
1526 if( !map->GetAllSpans() && !( span == map->GetSpan() ) )
1527 continue;
1528
1529 query.m_Span = span;
1530
1531 for( const DRILL_OPERATION& op : EnumerateDrillOperations( *m_board, query ) )
1532 {
1533 // The map is a set of marks on the holes, displaced as a whole. The holes
1534 // themselves never move
1535 const VECTOR2I pos = op.m_Position + map->GetOffset();
1536
1537 const auto it = cache->m_ByGroup.find( profile.GroupKeyString( op ) );
1538
1539 if( it == cache->m_ByGroup.end() )
1540 continue;
1541
1542 const DRILL_SYMBOL_ASSIGNMENT& assignment = it->second;
1543
1544 if( assignment.m_MarkMode == DRILL_MARK_MODE::SHAPE )
1545 {
1546 m_plotter->Marker( pos, map->GetSymbolSize(),
1548 }
1549 else
1550 {
1551 const wxString text =
1553 ? assignment.m_Letter
1554 : wxString::Format( wxT( "%.2f" ),
1555 pcbIUScale.IUTomm( op.m_Diameter ) );
1556
1557 TEXT_ATTRIBUTES attrs;
1558 attrs.m_Size = VECTOR2I( map->GetSymbolSize(), map->GetSymbolSize() );
1559 attrs.m_StrokeWidth = profile.GetSymbolWidth();
1562
1563 m_plotter->PlotText( pos, getColor( aLayer ), text, attrs, nullptr,
1565 }
1566
1567 if( map->GetGuideCross() )
1568 {
1569 const int reach = map->GetSymbolSize();
1570
1571 m_plotter->ThickSegment( pos - VECTOR2I( reach, 0 ),
1572 pos + VECTOR2I( reach, 0 ),
1573 profile.GetSymbolWidth(), getMetadata() );
1574 m_plotter->ThickSegment( pos - VECTOR2I( 0, reach ),
1575 pos + VECTOR2I( 0, reach ),
1576 profile.GetSymbolWidth(), getMetadata() );
1577 }
1578
1579 // A slot's true extent is the cost driver, so it is drawn as well as marked
1580 if( map->GetOutlineSlots() && op.m_IsSlot )
1581 {
1582 m_plotter->ThickOval( pos, op.m_SizeXY, op.m_Orientation,
1583 profile.GetSymbolWidth(), getMetadata() );
1584 }
1585 }
1586 }
1587 }
1588
1589 m_plotter->SetCurrentLineWidth( PLOTTER::USE_DEFAULT_LINE_WIDTH );
1590}
1591
1592
1594{
1595
1596 if( aChart->GetSymbolColumn() < 0 || aChart->RowShapes().empty() )
1597 return;
1598
1599 const DRILL_SYMBOL_PROFILE& profile = m_board->GetDesignSettings().GetDrillSymbolProfile();
1600
1601 m_plotter->SetColor( getColor( aChart->GetLayer() ) );
1602 m_plotter->SetCurrentLineWidth( profile.GetSymbolWidth() );
1603
1604 for( const auto& [row, shapeIndex] : aChart->RowShapes() )
1605 {
1606 const PCB_TABLECELL* cell = aChart->GetCell( row, aChart->GetSymbolColumn() );
1607
1608 if( !cell )
1609 continue;
1610
1611 const BOX2I box = cell->GetBoundingBox();
1612
1613 // Same fit as the painter, so the plotted chart matches what was on screen
1614 const int size = std::min<int>( profile.GetSymbolSize(),
1615 std::min( box.GetWidth(), box.GetHeight() ) * 2 / 3 );
1616
1617 if( size > 0 )
1618 m_plotter->Marker( box.GetCenter(), size, DRILL_MARKERS::CuratedShape( shapeIndex ) );
1619 }
1620
1621 m_plotter->SetCurrentLineWidth( PLOTTER::USE_DEFAULT_LINE_WIDTH );
1622}
@ ERROR_INSIDE
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
constexpr int ARC_LOW_DEF
Definition base_units.h:143
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
Generic cubic Bezier representation.
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:422
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:559
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:403
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:115
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:401
const VECTOR2I & GetEllipseCenter() const
Definition eda_shape.h:383
const SHAPE_POLY_SET & GetHatching() const
EDA_ANGLE GetEllipseEndAngle() const
Definition eda_shape.h:429
int GetEllipseMajorRadius() const
Definition eda_shape.h:392
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:410
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:331
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:281
std::vector< VECTOR2I > GetRectCorners() const
EDA_ANGLE GetEllipseStartAngle() const
Definition eda_shape.h:420
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:183
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:683
virtual EDA_ANGLE GetDrawRotation() const
Definition eda_text.h:425
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:647
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:427
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:931
PCB_FIELD & Value()
read/write accessors:
Definition footprint.h:947
LSET GetPrivateLayers() const
Definition footprint.h:345
PCB_FIELD & Reference()
Definition footprint.h:948
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:909
DRAWINGS & GraphicalItems()
Definition footprint.h:408
@ 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.
int GetShortenDepth(int aLineWidth) const
Return how far the line should be shortened at this ending.
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:563
static wxString ShowPadShape(PAD_SHAPE aShape)
Definition pad.cpp:2558
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:375
int GetRoundRectCornerRadius(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1182
const BOX2I GetBoundingBox() const override
The bounding box is cached, so this will be efficient most of the time.
Definition pad.cpp:1635
PAD_ATTRIB GetAttribute() const
Definition pad.h:560
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:307
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc=ERROR_INSIDE, bool aIgnoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
Definition pad.cpp:3067
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition pad.h:205
VECTOR2I GetSize(PCB_LAYER_ID aLayer) const
Definition pad.cpp:298
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition pad.cpp:1757
int GetChamferPositions(PCB_LAYER_ID aLayer) const
Definition pad.h:852
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(PCB_LAYER_ID aLayer, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Definition pad.cpp:1240
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
Definition pad.h:834
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1868
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:344
int GetSolderMaskExpansion() const
void SetShape(SHAPE_T aShape) override
Definition pcb_shape.h:209
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:155
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
Tests whether the border is disabled, as configured by the stroke.
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Convert the text to a polygonSet describing the actual character strokes (one per segment).
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
PCB_SHAPE GetPolygonalBoxShape() const
static const int USE_DEFAULT_LINE_WIDTH
Definition plotter.h:142
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:201
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)
EDA_ORIENTATION m_Angle
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:615
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:90
@ ROUND_ALL_CORNERS
All angles are rounded.
std::vector< DRILL_SPAN > EnumerateDrillSpans(const BOARD &aBoard, bool aPadBackdrills)
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:448
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:450
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:437
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:83
@ 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:227
@ 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:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707