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>
45#include <pcbplot.h>
46#include <pcb_plot_params.h> // for PCB_PLOT_PARAMS, PCB_PL...
47#include <advanced_config.h>
48
49#include <pcb_dimension.h>
50#include <pcb_shape.h>
51#include <footprint.h>
52#include <pcb_track.h>
53#include <pad.h>
54#include <pcb_target.h>
55#include <pcb_text.h>
56#include <pcb_textbox.h>
57#include <pcb_tablecell.h>
58#include <pcb_table.h>
59#include <zone.h>
60#include <pcb_barcode.h>
61
62#include <wx/debug.h> // for wxASSERT_MSG
63
64
66{
67 COLOR4D color = ColorSettings()->GetColor( aLayer );
68
69 // A hack to avoid plotting a white item in white color on white paper
70 if( color == COLOR4D::WHITE )
71 color = COLOR4D( LIGHTGRAY );
72
73 return color;
74}
75
76
77void BRDITEMS_PLOTTER::PlotPadNumber( const PAD* aPad, const COLOR4D& aColor )
78{
79 wxString padNumber = UnescapeString( aPad->GetNumber() );
80
81 if( padNumber.IsEmpty() )
82 return;
83
84 BOX2I padBBox = aPad->GetBoundingBox();
85 VECTOR2I position = padBBox.Centre();
86 VECTOR2I padsize = padBBox.GetSize();
87
88 // TODO(JE) padstacks
90 {
91 // See if we have a number box
92 for( const std::shared_ptr<PCB_SHAPE>& primitive : aPad->GetPrimitives( PADSTACK::ALL_LAYERS ) )
93 {
94 if( primitive->IsProxyItem() && primitive->GetShape() == SHAPE_T::RECTANGLE )
95 {
96 position = primitive->GetCenter();
97 RotatePoint( position, aPad->GetOrientation() );
98 position += aPad->ShapePos( PADSTACK::ALL_LAYERS );
99
100 padsize.x = abs( primitive->GetBotRight().x - primitive->GetTopLeft().x );
101 padsize.y = abs( primitive->GetBotRight().y - primitive->GetTopLeft().y );
102
103 break;
104 }
105 }
106 }
107
109 {
110 // Don't allow a 45° rotation to bloat a pad's bounding box unnecessarily
111 int limit = KiROUND( std::min( aPad->GetSize( PADSTACK::ALL_LAYERS ).x,
112 aPad->GetSize( PADSTACK::ALL_LAYERS ).y ) * 1.1 );
113
114 if( padsize.x > limit && padsize.y > limit )
115 {
116 padsize.x = limit;
117 padsize.y = limit;
118 }
119 }
120
121 TEXT_ATTRIBUTES textAttrs;
122
123 textAttrs.m_Mirrored = m_plotter->GetPlotMirrored();
124
125 if( padsize.x < ( padsize.y * 0.95 ) )
126 {
127 textAttrs.m_Angle = ANGLE_90;
128 std::swap( padsize.x, padsize.y );
129 }
130
131 // approximate the size of the pad number text:
132 // We use a size for at least 3 chars, to give a good look even for short numbers
133 int tsize = KiROUND( padsize.x / std::max( PrintableCharCount( padNumber ), 3 ) );
134 tsize = std::min( tsize, padsize.y );
135
136 // enforce a max size
137 tsize = std::min( tsize, pcbIUScale.mmToIU( 5.0 ) );
138
139 textAttrs.m_Size = VECTOR2I( tsize, tsize );
140
141 // use a somewhat spindly font to go with the outlined pads
142 textAttrs.m_StrokeWidth = KiROUND( tsize / 12.0 );
143
144 m_plotter->PlotText( position, aColor, padNumber, textAttrs );
145}
146
147
148void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, PCB_LAYER_ID aLayer, const COLOR4D& aColor,
149 bool aSketchMode )
150{
151 VECTOR2I shape_pos = aPad->ShapePos( aLayer );
152 GBR_METADATA metadata;
153
154 bool plotOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
155 bool plotOnExternalCopperLayer = ( m_layerMask & LSET::ExternalCuMask() ).any();
156
157 // Pad not on the solder mask layer cannot be soldered.
158 // therefore it can have a specific aperture attribute.
159 // Not yet in use.
160 // bool isPadOnBoardTechLayers = ( aPad->GetLayerSet() & LSET::AllBoardTechMask() ).any();
161
162 metadata.SetCmpReference( aPad->GetParentFootprint()->GetReference() );
163
164 if( plotOnCopperLayer )
165 {
167 metadata.SetCopper( true );
168
169 // Gives a default attribute, for instance for pads used as tracks in net ties:
170 // Connector pads and SMD pads are on external layers
171 // if on internal layers, they are certainly used as net tie
172 // and are similar to tracks: just conductor items
174
175 const bool useUTF8 = false;
176 const bool useQuoting = false;
177 metadata.SetPadName( aPad->GetNumber(), useUTF8, useQuoting );
178
179 if( !aPad->GetNumber().IsEmpty() )
180 metadata.SetPadPinFunction( aPad->GetPinFunction(), useUTF8, useQuoting );
181
182 metadata.SetNetName( aPad->GetNetname() );
183
184 // Some pads are mechanical pads ( through hole or smd )
185 // when this is the case, they have no pad name and/or are not plated.
186 // In this case gerber files have slightly different attributes.
187 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH || aPad->GetNumber().IsEmpty() )
188 metadata.m_NetlistMetadata.m_NotInNet = true;
189
190 if( !plotOnExternalCopperLayer )
191 {
192 // the .P object attribute (GBR_NETLIST_METADATA::GBR_NETINFO_PAD)
193 // is used on outer layers, unless the component is embedded
194 // or a "etched" component (fp only drawn, not a physical component)
195 // Currently, Pcbnew does not handle embedded component, so we disable the .P
196 // attribute on internal layers
197 // Note the Gerber doc is not really clear about through holes pads about the .P
200
201 }
202
203 // Some attributes are reserved to the external copper layers:
204 // GBR_APERTURE_ATTRIB_CONNECTORPAD and GBR_APERTURE_ATTRIB_SMDPAD_CUDEF
205 // for instance.
206 // Pad with type PAD_ATTRIB::CONN or PAD_ATTRIB::SMD that is not on outer layer
207 // has its aperture attribute set to GBR_APERTURE_ATTRIB_CONDUCTOR
208 switch( aPad->GetAttribute() )
209 {
210 case PAD_ATTRIB::NPTH: // Mechanical pad through hole
212 break;
213
214 case PAD_ATTRIB::PTH : // Pad through hole, a hole is also expected
216 break;
217
218 case PAD_ATTRIB::CONN: // Connector pads, no solder paste but with solder mask.
219 if( plotOnExternalCopperLayer )
221 break;
222
223 case PAD_ATTRIB::SMD: // SMD pads (on external copper layer only)
224 // with solder paste and mask
225 if( plotOnExternalCopperLayer )
227 break;
228 }
229
230 // Fabrication properties can have specific GBR_APERTURE_METADATA options
231 // that replace previous aperture attribute:
232 switch( aPad->GetProperty() )
233 {
234 case PAD_PROP::BGA: // Only applicable to outer layers
235 if( plotOnExternalCopperLayer )
237 break;
238
241 break;
242
245 break;
246
247 case PAD_PROP::TESTPOINT: // Only applicable to outer layers
248 if( plotOnExternalCopperLayer )
250 break;
251
254 break;
255
258 break;
259
260 case PAD_PROP::PRESSFIT: // used only in drill files
261 case PAD_PROP::NONE:
263 break;
264 }
265
266 // Ensure NPTH pads have *always* the GBR_APERTURE_ATTRIB_WASHERPAD attribute
267 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
269 }
270 else
271 {
273 }
274
275 // Set plot color (change WHITE to LIGHTGRAY because
276 // the white items are not seen on a white paper or screen
277 m_plotter->SetColor( aColor != WHITE ? aColor : LIGHTGRAY );
278
279 if( aSketchMode )
280 {
281 switch( aPad->GetShape( aLayer ) )
282 {
284 m_plotter->ThickCircle( shape_pos, aPad->GetSize( aLayer ).x, GetSketchPadLineWidth(),
285 nullptr );
286 break;
287
288 case PAD_SHAPE::OVAL:
289 {
290 m_plotter->ThickOval( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(),
291 GetSketchPadLineWidth(), nullptr );
292 break;
293 }
294
300 {
301 SHAPE_POLY_SET outline;
302 aPad->TransformShapeToPolygon( outline, aLayer, 0, m_plotter->GetPlotterArcHighDef(),
303 ERROR_INSIDE, false );
304
305 m_plotter->ThickPoly( outline, GetSketchPadLineWidth(), nullptr );
306 break;
307 }
308
309 default:
311 }
312
313 return;
314 }
315
316 switch( aPad->GetShape( aLayer ) )
317 {
319 m_plotter->FlashPadCircle( shape_pos, aPad->GetSize( aLayer ).x, &metadata );
320 break;
321
322 case PAD_SHAPE::OVAL:
323 m_plotter->FlashPadOval( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(), &metadata );
324 break;
325
327 m_plotter->FlashPadRect( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(), &metadata );
328 break;
329
331 m_plotter->FlashPadRoundRect( shape_pos, aPad->GetSize( aLayer ),
332 aPad->GetRoundRectCornerRadius( aLayer ),
333 aPad->GetOrientation(), &metadata );
334 break;
335
337 {
338 // Build the pad polygon in coordinates relative to the pad
339 // (i.e. for a pad at pos 0,0, rot 0.0). Needed to use aperture macros,
340 // to be able to create a pattern common to all trapezoid pads having the same shape
341 VECTOR2I coord[4];
342
343 // Order is lower left, lower right, upper right, upper left.
344 VECTOR2I half_size = aPad->GetSize( aLayer ) / 2;
345 VECTOR2I trap_delta = aPad->GetDelta( aLayer ) / 2;
346
347 coord[0] = VECTOR2I( -half_size.x - trap_delta.y, half_size.y + trap_delta.x );
348 coord[1] = VECTOR2I( half_size.x + trap_delta.y, half_size.y - trap_delta.x );
349 coord[2] = VECTOR2I( half_size.x - trap_delta.y, -half_size.y + trap_delta.x );
350 coord[3] = VECTOR2I( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x );
351
352 m_plotter->FlashPadTrapez( shape_pos, coord, aPad->GetOrientation(), &metadata );
353 break;
354 }
355
357 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
358 {
359 GERBER_PLOTTER* gerberPlotter = static_cast<GERBER_PLOTTER*>( m_plotter );
360
361 gerberPlotter->FlashPadChamferRoundRect( shape_pos, aPad->GetSize( aLayer ),
362 aPad->GetRoundRectCornerRadius( aLayer ),
363 aPad->GetChamferRectRatio( aLayer ),
364 aPad->GetChamferPositions( aLayer ),
365 aPad->GetOrientation(), &metadata );
366 break;
367 }
368
370
371 default:
373 {
374 const std::shared_ptr<SHAPE_POLY_SET>& polygons = aPad->GetEffectivePolygon( aLayer, ERROR_INSIDE );
375
376 if( polygons->OutlineCount() )
377 {
378 m_plotter->FlashPadCustom( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(),
379 polygons.get(), &metadata );
380 }
381 }
382 break;
383 }
384}
385
386
388{
389 if( !GetPlotFPText() )
390 return;
391
392 const wxString variantName = m_board ? m_board->GetCurrentVariant() : wxString();
393 const bool dnp = aFootprint->GetDNPForVariant( variantName );
394
395 const PCB_TEXT* reference = &aFootprint->Reference();
396 PCB_LAYER_ID refLayer = reference->GetLayer();
397
398 // Reference and value have special controls for forcing their plotting
399 if( GetPlotReference()
400 && m_layerMask[refLayer]
401 && reference->IsVisible()
402 && !( dnp && hideDNPItems( refLayer ) ) )
403 {
404 PlotText( reference, refLayer, reference->IsKnockout(), reference->GetFontMetrics(),
405 dnp && crossoutDNPItems( refLayer ) );
406 }
407
408 const PCB_TEXT* value = &aFootprint->Value();
409 PCB_LAYER_ID valueLayer = value->GetLayer();
410
411 if( GetPlotValue()
412 && m_layerMask[valueLayer]
413 && value->IsVisible()
414 && !( dnp && hideDNPItems( valueLayer ) ) )
415 {
416 PlotText( value, valueLayer, value->IsKnockout(), value->GetFontMetrics(), false );
417 }
418
419 std::vector<PCB_TEXT*> texts;
420
421 // Skip the reference and value texts that are handled specially
422 for( PCB_FIELD* field : aFootprint->GetFields() )
423 {
424 wxCHECK2( field, continue );
425
426 if( field->IsReference() || field->IsValue() )
427 continue;
428
429 if( field->IsVisible() )
430 texts.push_back( field );
431 }
432
433 for( BOARD_ITEM* item : aFootprint->GraphicalItems() )
434 {
435 if( PCB_TEXT* textItem = dynamic_cast<PCB_TEXT*>( item ) )
436 texts.push_back( textItem );
437 }
438
439 for( const PCB_TEXT* text : texts )
440 {
441 PCB_LAYER_ID textLayer = text->GetLayer();
442 bool strikeout = false;
443
444 if( textLayer == Edge_Cuts || textLayer >= PCB_LAYER_ID_COUNT )
445 continue;
446
447 if( dnp && hideDNPItems( textLayer ) )
448 continue;
449
450 if( !m_layerMask[textLayer] || aFootprint->GetPrivateLayers().test( textLayer ) )
451 continue;
452
453 if( text->GetText() == wxT( "${REFERENCE}" ) )
454 {
455 if( !GetPlotReference() )
456 continue;
457
458 strikeout = dnp && crossoutDNPItems( textLayer );
459 }
460
461 if( text->GetText() == wxT( "${VALUE}" ) )
462 {
463 if( !GetPlotValue() )
464 continue;
465 }
466
467 PlotText( text, textLayer, text->IsKnockout(), text->GetFontMetrics(), strikeout );
468 }
469}
470
471
473{
474 switch( item->Type() )
475 {
476 case PCB_SHAPE_T:
477 PlotShape( static_cast<const PCB_SHAPE*>( item ) );
478 break;
479
480 case PCB_TEXT_T:
481 {
482 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( item );
483 PlotText( text, text->GetLayer(), text->IsKnockout(), text->GetFontMetrics() );
484 break;
485 }
486
487 case PCB_TEXTBOX_T:
488 {
489 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
490
491 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( item );
492 PlotText( textbox, textbox->GetLayer(), textbox->IsKnockout(), textbox->GetFontMetrics() );
493
494 if( textbox->IsBorderEnabled() )
495 PlotShape( textbox );
496
497 m_plotter->SetTextMode( GetTextMode() );
498 break;
499 }
500
501 case PCB_BARCODE_T:
502 PlotBarCode( static_cast<const PCB_BARCODE*>( item ) );
503 break;
504
505 case PCB_TABLE_T:
506 {
507 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( item );
508
509 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
510
511 for( const PCB_TABLECELL* cell : table->GetCells() )
512 PlotText( cell, cell->GetLayer(), cell->IsKnockout(), cell->GetFontMetrics() );
513
515
516 m_plotter->SetTextMode( GetTextMode() );
517 break;
518 }
519
521 case PCB_DIM_CENTER_T:
522 case PCB_DIM_RADIAL_T:
524 case PCB_DIM_LEADER_T:
525 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
526
527 PlotDimension( static_cast<const PCB_DIMENSION_BASE*>( item ) );
528
529 m_plotter->SetTextMode( GetTextMode() );
530 break;
531
532 case PCB_TARGET_T:
533 PlotPcbTarget( static_cast<const PCB_TARGET*>( item ) );
534 break;
535
536 default:
537 break;
538 }
539}
540
541
543{
544 if( !m_layerMask[aDim->GetLayer()] )
545 return;
546
547 COLOR4D color = ColorSettings()->GetColor( aDim->GetLayer() );
548
549 // Set plot color (change WHITE to LIGHTGRAY because
550 // the white items are not seen on a white paper or screen
551 m_plotter->SetColor( color != WHITE ? color : LIGHTGRAY);
552
553 PlotText( aDim, aDim->GetLayer(), false, aDim->GetFontMetrics() );
554
555 PCB_SHAPE temp_item;
556
558 temp_item.SetLayer( aDim->GetLayer() );
559
560 for( const std::shared_ptr<SHAPE>& shape : aDim->GetShapes() )
561 {
562 switch( shape->Type() )
563 {
564 case SH_SEGMENT:
565 {
566 const SEG& seg = static_cast<const SHAPE_SEGMENT*>( shape.get() )->GetSeg();
567
568 temp_item.SetShape( SHAPE_T::SEGMENT );
569 temp_item.SetStart( seg.A );
570 temp_item.SetEnd( seg.B );
571
572 PlotShape( &temp_item );
573 break;
574 }
575
576 case SH_CIRCLE:
577 {
578 VECTOR2I start( shape->Centre() );
579 int radius = static_cast<const SHAPE_CIRCLE*>( shape.get() )->GetRadius();
580
581 temp_item.SetShape( SHAPE_T::CIRCLE );
582 temp_item.SetFilled( false );
583 temp_item.SetStart( start );
584 temp_item.SetEnd( VECTOR2I( start.x + radius, start.y ) );
585
586 PlotShape( &temp_item );
587 break;
588 }
589
590 default:
591 break;
592 }
593 }
594}
595
596
598{
599 int dx1, dx2, dy1, dy2, radius;
600
601 if( !m_layerMask[aMire->GetLayer()] )
602 return;
603
604 m_plotter->SetColor( getColor( aMire->GetLayer() ) );
605
606 PCB_SHAPE temp_item;
607
608 temp_item.SetShape( SHAPE_T::CIRCLE );
609 temp_item.SetFilled( false );
610 temp_item.SetStroke( STROKE_PARAMS( aMire->GetWidth(), LINE_STYLE::SOLID ) );
611 temp_item.SetLayer( aMire->GetLayer() );
612 temp_item.SetStart( aMire->GetPosition() );
613 radius = aMire->GetSize() / 3;
614
615 if( aMire->GetShape() ) // temp_item X
616 radius = aMire->GetSize() / 2;
617
618 // Draw the circle
619 temp_item.SetEnd( VECTOR2I( temp_item.GetStart().x + radius, temp_item.GetStart().y ) );
620
621 PlotShape( &temp_item );
622
623 temp_item.SetShape( SHAPE_T::SEGMENT );
624
625 radius = aMire->GetSize() / 2;
626 dx1 = radius;
627 dy1 = 0;
628 dx2 = 0;
629 dy2 = radius;
630
631 if( aMire->GetShape() ) // Shape X
632 {
633 dx1 = dy1 = radius;
634 dx2 = dx1;
635 dy2 = -dy1;
636 }
637
638 VECTOR2I mirePos( aMire->GetPosition() );
639
640 // Draw the X or + temp_item:
641 temp_item.SetStart( VECTOR2I( mirePos.x - dx1, mirePos.y - dy1 ) );
642 temp_item.SetEnd( VECTOR2I( mirePos.x + dx1, mirePos.y + dy1 ) );
643 PlotShape( &temp_item );
644
645 temp_item.SetStart( VECTOR2I( mirePos.x - dx2, mirePos.y - dy2 ) );
646 temp_item.SetEnd( VECTOR2I( mirePos.x + dx2, mirePos.y + dy2 ) );
647 PlotShape( &temp_item );
648}
649
650
652{
653 const wxString variantName = m_board ? m_board->GetCurrentVariant() : wxString();
654 const bool dnp = aFootprint->GetDNPForVariant( variantName );
655
656 for( const BOARD_ITEM* item : aFootprint->GraphicalItems() )
657 {
658 PCB_LAYER_ID itemLayer = item->GetLayer();
659
660 if( aFootprint->GetPrivateLayers().test( itemLayer ) )
661 continue;
662
663 if( dnp && hideDNPItems( itemLayer ) )
664 continue;
665
666 if( !( m_layerMask & item->GetLayerSet() ).any() )
667 continue;
668
669 switch( item->Type() )
670 {
671 case PCB_SHAPE_T:
672 PlotShape( static_cast<const PCB_SHAPE*>( item ) );
673 break;
674
675 case PCB_TEXTBOX_T:
676 {
677 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( item );
678
679 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
680
681 PlotText( textbox, textbox->GetLayer(), textbox->IsKnockout(),
682 textbox->GetFontMetrics() );
683
684 if( textbox->IsBorderEnabled() )
685 PlotShape( textbox );
686
687 m_plotter->SetTextMode( GetTextMode() );
688 break;
689 }
690
691 case PCB_BARCODE_T:
692 PlotBarCode( static_cast<const PCB_BARCODE*>( item ) );
693 break;
694
695 case PCB_TABLE_T:
696 {
697 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( item );
698
699 m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE );
700
701 for( const PCB_TABLECELL* cell : table->GetCells() )
702 PlotText( cell, cell->GetLayer(), cell->IsKnockout(), cell->GetFontMetrics() );
703
705
706 m_plotter->SetTextMode( GetTextMode() );
707 break;
708 }
709
711 case PCB_DIM_CENTER_T:
712 case PCB_DIM_RADIAL_T:
714 case PCB_DIM_LEADER_T:
715 PlotDimension( static_cast<const PCB_DIMENSION_BASE*>( item ) );
716 break;
717
718 case PCB_TEXT_T:
719 // Plotted in PlotFootprintTextItems()
720 break;
721
723 // Not plotted at all
724 break;
725
726 default:
727 UNIMPLEMENTED_FOR( item->GetClass() );
728 }
729 }
730}
731
732
733#define getMetadata() ( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER ? (void*) &gbr_metadata \
734 : m_plotter->GetPlotterType() == PLOT_FORMAT::DXF ? (void*) this \
735 : (void*) nullptr )
736
737
738void BRDITEMS_PLOTTER::PlotText( const EDA_TEXT* aText, PCB_LAYER_ID aLayer, bool aIsKnockout,
739 const KIFONT::METRICS& aFontMetrics, bool aStrikeout )
740{
741 int maxError = m_board->GetDesignSettings().m_MaxError;
742 KIFONT::FONT* font = aText->GetDrawFont( m_plotter->RenderSettings() );
743 wxString shownText( aText->GetShownText( true ) );
744
745 if( shownText.IsEmpty() )
746 return;
747
748 if( !m_layerMask[aLayer] )
749 return;
750
751 GBR_METADATA gbr_metadata;
752
753 if( IsCopperLayer( aLayer ) )
755
756 COLOR4D color = getColor( aLayer );
757 m_plotter->SetColor( color );
758
759 const VECTOR2I& pos = aText->GetTextPos();
760
761 TEXT_ATTRIBUTES attrs = aText->GetAttributes();
762 attrs.m_Size = aText->GetTextSize();
764 attrs.m_Angle = aText->GetDrawRotation();
765 attrs.m_Multiline = false;
766
767 m_plotter->SetCurrentLineWidth( attrs.m_StrokeWidth );
768
769 auto strikeoutText =
770 [&]( const PCB_TEXT* text )
771 {
772 SHAPE_POLY_SET textPoly;
773
774 text->TransformTextToPolySet( textPoly, 0, ARC_LOW_DEF, ERROR_INSIDE );
775 textPoly.Rotate( -text->GetDrawRotation(), text->GetDrawPos() );
776
777 BOX2I rect = textPoly.BBox();
778 VECTOR2I start( rect.GetLeft() - attrs.m_StrokeWidth,
779 ( rect.GetTop() + rect.GetBottom() ) / 2 );
780 VECTOR2I end( rect.GetRight() + attrs.m_StrokeWidth,
781 ( rect.GetTop() + rect.GetBottom() ) / 2 );
782
783 RotatePoint( start, text->GetDrawPos(), text->GetDrawRotation() );
784 RotatePoint( end, text->GetDrawPos(), text->GetDrawRotation() );
785
786 m_plotter->ThickSegment( start, end, attrs.m_StrokeWidth, getMetadata() );
787 };
788
789 if( aIsKnockout )
790 {
791 SHAPE_POLY_SET finalPoly;
792
793 if( const PCB_TEXT* text = dynamic_cast<const PCB_TEXT*>( aText) )
794 text->TransformTextToPolySet( finalPoly, 0, maxError, ERROR_INSIDE );
795 else if( const PCB_TEXTBOX* textbox = dynamic_cast<const PCB_TEXTBOX*>( aText ) )
796 textbox->TransformTextToPolySet( finalPoly, 0, maxError, ERROR_INSIDE );
797
798 finalPoly.Fracture();
799
800 for( int ii = 0; ii < finalPoly.OutlineCount(); ++ii )
801 m_plotter->PlotPoly( finalPoly.Outline( ii ), FILL_T::FILLED_SHAPE, 0, getMetadata() );
802 }
803 else
804 {
805 if( font->IsOutline() && !m_board->GetEmbeddedFiles()->GetAreFontsEmbedded() )
806 {
808
809 CALLBACK_GAL callback_gal( empty_opts,
810 // Stroke callback
811 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
812 {
813 m_plotter->ThickSegment( aPt1, aPt2, attrs.m_StrokeWidth, getMetadata() );
814 },
815 // Polygon callback
816 [&]( const SHAPE_LINE_CHAIN& aPoly )
817 {
818 m_plotter->PlotPoly( aPoly, FILL_T::FILLED_SHAPE, 0, getMetadata() );
819 } );
820
821 callback_gal.DrawGlyphs( *aText->GetRenderCache( font, shownText ) );
822 }
823 else if( aText->IsMultilineAllowed() )
824 {
825 std::vector<VECTOR2I> positions;
826 wxArrayString strings_list;
827 wxStringSplit( shownText, strings_list, '\n' );
828 positions.reserve( strings_list.Count() );
829
830 aText->GetLinePositions( m_plotter->RenderSettings(), positions, (int) strings_list.Count() );
831
832 for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
833 {
834 wxString& txt = strings_list.Item( ii );
835 m_plotter->PlotText( positions[ii], color, txt, attrs, font, aFontMetrics, getMetadata() );
836 }
837
838 if( aStrikeout && strings_list.Count() == 1 )
839 strikeoutText( static_cast<const PCB_TEXT*>( aText ) );
840 }
841 else
842 {
843 m_plotter->PlotText( pos, color, shownText, attrs, font, aFontMetrics, getMetadata() );
844
845 if( aStrikeout )
846 strikeoutText( static_cast<const PCB_TEXT*>( aText ) );
847 }
848 }
849}
850
851
852void BRDITEMS_PLOTTER::PlotZone( const ZONE* aZone, PCB_LAYER_ID aLayer, const SHAPE_POLY_SET& aPolysList )
853{
854 if( aPolysList.IsEmpty() )
855 return;
856
857 GBR_METADATA gbr_metadata;
858
859 if( aZone->IsOnCopperLayer() )
860 {
861 gbr_metadata.SetNetName( aZone->GetNetname() );
862 gbr_metadata.SetCopper( true );
863
864 // Zones with no net name can exist.
865 // they are not used to connect items, so the aperture attribute cannot
866 // be set as conductor
867 if( aZone->GetNetname().IsEmpty() )
868 {
870 }
871 else
872 {
875 }
876 }
877
878 m_plotter->SetColor( getColor( aLayer ) );
879
880 m_plotter->StartBlock( nullptr ); // Clean current object attributes
881
882 /*
883 * In non filled mode the outline is plotted, but not the filling items
884 */
885
886 for( int idx = 0; idx < aPolysList.OutlineCount(); ++idx )
887 {
888 const SHAPE_LINE_CHAIN& outline = aPolysList.Outline( idx );
889
890 // Plot the current filled area (as region for Gerber plotter to manage attributes)
891 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
892 {
893 static_cast<GERBER_PLOTTER*>( m_plotter )->PlotGerberRegion( outline, &gbr_metadata );
894 }
895 else if( m_plotter->GetPlotterType() == PLOT_FORMAT::DXF )
896 {
897 if( GetDXFPlotMode() == FILLED )
898 m_plotter->PlotPoly( outline, FILL_T::FILLED_SHAPE, 0, getMetadata() );
899 }
900 else
901 {
902 m_plotter->PlotPoly( outline, FILL_T::FILLED_SHAPE, 0, getMetadata() );
903 }
904 }
905
906 m_plotter->EndBlock( nullptr ); // Clear object attributes
907}
908
909
911{
912 if( !( m_layerMask & aShape->GetLayerSet() ).any() )
913 return;
914
915 int thickness = aShape->GetWidth();
916 int margin = thickness; // unclamped thickness (can be negative)
917 LINE_STYLE lineStyle = aShape->GetStroke().GetLineStyle();
918 bool onCopperLayer = ( LSET::AllCuMask() & m_layerMask ).any();
919 bool onSolderMaskLayer = ( LSET( { F_Mask, B_Mask } ) & m_layerMask ).any();
920 bool isSolidFill = aShape->IsSolidFill();
921 bool isHatchedFill = aShape->IsHatchedFill();
922
923 if( onSolderMaskLayer
924 && aShape->HasSolderMask()
925 && IsExternalCopperLayer( aShape->GetLayer() ) )
926 {
927 margin += 2 * aShape->GetSolderMaskExpansion();
928 thickness = std::max( margin, 0 );
929
930 if( isHatchedFill )
931 {
932 isSolidFill = true;
933 isHatchedFill = false;
934 }
935 }
936
937 m_plotter->SetColor( getColor( aShape->GetLayer() ) );
938
939 const FOOTPRINT* parentFP = aShape->GetParentFootprint();
940 GBR_METADATA gbr_metadata;
941 const wxString variantName = m_board ? m_board->GetCurrentVariant() : wxString();
942 const bool parentDnp = parentFP ? parentFP->GetDNPForVariant( variantName ) : false;
943
944 if( parentFP )
945 {
946 gbr_metadata.SetCmpReference( parentFP->GetReference() );
948 }
949
950 if( parentFP && parentDnp && GetSketchDNPFPsOnFabLayers() )
951 {
952 if( aShape->GetLayer() == F_Fab || aShape->GetLayer() == B_Fab )
953 {
954 thickness = GetSketchPadLineWidth();
955 isSolidFill = false;
956 isHatchedFill = false;
957 }
958 }
959
960 if( aShape->GetLayer() == Edge_Cuts )
961 {
963 }
964 else if( onCopperLayer )
965 {
966 if( parentFP )
967 {
969 gbr_metadata.SetCopper( true );
970 }
971 else if( aShape->GetNetCode() > 0 )
972 {
973 gbr_metadata.SetCopper( true );
976 gbr_metadata.SetNetName( aShape->GetNetname() );
977 }
978 else
979 {
980 // Graphic items (PCB_SHAPE, TEXT) having no net have the NonConductor attribute
981 // Graphic items having a net have the Conductor attribute, but are not (yet?)
982 // supported in Pcbnew
984 }
985 }
986
987 if( lineStyle <= LINE_STYLE::FIRST_TYPE )
988 {
989 switch( aShape->GetShape() )
990 {
991 case SHAPE_T::SEGMENT:
992 m_plotter->ThickSegment( aShape->GetStart(), aShape->GetEnd(), thickness, getMetadata() );
993 break;
994
995 case SHAPE_T::CIRCLE:
996 if( isSolidFill )
997 {
998 int diameter = aShape->GetRadius() * 2 + thickness;
999
1000 if( margin < 0 )
1001 {
1002 diameter += margin;
1003 diameter = std::max( diameter, 0 );
1004 }
1005
1006 m_plotter->FilledCircle( aShape->GetStart(), diameter, getMetadata() );
1007 }
1008 else
1009 {
1010 m_plotter->ThickCircle( aShape->GetStart(), aShape->GetRadius() * 2, thickness,
1011 getMetadata() );
1012 }
1013
1014 break;
1015
1016 case SHAPE_T::ARC:
1017 {
1018 // when startAngle == endAngle ThickArc() doesn't know whether it's 0 deg and 360 deg
1019 // but it is a circle
1020 if( std::abs( aShape->GetArcAngle().AsDegrees() ) == 360.0 )
1021 {
1022 m_plotter->ThickCircle( aShape->GetCenter(), aShape->GetRadius() * 2, thickness,
1023 getMetadata() );
1024 }
1025 else
1026 {
1027 m_plotter->ThickArc( *aShape, getMetadata(), thickness );
1028 }
1029
1030 break;
1031 }
1032
1033 case SHAPE_T::BEZIER:
1034 m_plotter->BezierCurve( aShape->GetStart(), aShape->GetBezierC1(),
1035 aShape->GetBezierC2(), aShape->GetEnd(), 0, thickness );
1036 break;
1037
1038 case SHAPE_T::POLY:
1039 if( aShape->IsPolyShapeValid() )
1040 {
1041 if( m_plotter->GetPlotterType() == PLOT_FORMAT::DXF && GetDXFPlotMode() == SKETCH )
1042 {
1043 m_plotter->ThickPoly( aShape->GetPolyShape(), thickness, getMetadata() );
1044 }
1045 else
1046 {
1047 m_plotter->SetCurrentLineWidth( thickness, &gbr_metadata );
1048
1049 const SHAPE_POLY_SET& origPoly = aShape->GetPolyShape();
1050
1051 // Stroke the unfractured outline so degenerate near-zero-width
1052 // spikes (which Fracture() collapses but the editor still draws as
1053 // thick lines) are preserved in the plot output (issue #24143).
1054 if( thickness > 0 )
1055 {
1056 for( int jj = 0; jj < origPoly.OutlineCount(); ++jj )
1057 {
1058 m_plotter->PlotPoly( origPoly.COutline( jj ), FILL_T::NO_FILL,
1059 thickness, getMetadata() );
1060 }
1061 }
1062
1063 if( !isSolidFill )
1064 break;
1065
1066 // Fracture before plotting the fill to avoid invalid gerber regions
1067 // from self-intersecting or overlapping outlines.
1068 SHAPE_POLY_SET tmpPoly = origPoly.CloneDropTriangulation();
1069 tmpPoly.Fracture();
1070
1071 if( margin < 0 )
1072 tmpPoly.Inflate( margin / 2, CORNER_STRATEGY::ROUND_ALL_CORNERS, aShape->GetMaxError() );
1073
1074 for( int jj = 0; jj < tmpPoly.OutlineCount(); ++jj )
1075 {
1076 SHAPE_LINE_CHAIN& poly = tmpPoly.Outline( jj );
1077 poly.SetClosed( true );
1078
1079 // Width 0; the stroke was already plotted from the unfractured outline.
1080 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1081 {
1082 GERBER_PLOTTER* gbr_plotter = static_cast<GERBER_PLOTTER*>( m_plotter );
1083 gbr_plotter->PlotPolyAsRegion( poly, FILL_T::FILLED_SHAPE, 0,
1084 &gbr_metadata );
1085 }
1086 else
1087 {
1088 m_plotter->PlotPoly( poly, FILL_T::FILLED_SHAPE, 0, getMetadata() );
1089 }
1090 }
1091 }
1092 }
1093
1094 break;
1095
1096 case SHAPE_T::RECTANGLE:
1097 {
1098 int radius = aShape->GetCornerRadius();
1099
1100 if( radius == 0 && m_plotter->GetPlotterType() == PLOT_FORMAT::DXF &&
1101 GetDXFPlotMode() == SKETCH )
1102 {
1103 std::vector<VECTOR2I> pts = aShape->GetRectCorners();
1104 m_plotter->ThickRect( pts[0], pts[2], thickness, getMetadata() );
1105 }
1106 else
1107 {
1108 BOX2I box( aShape->GetStart(), VECTOR2I( aShape->GetEnd().x - aShape->GetStart().x,
1109 aShape->GetEnd().y - aShape->GetStart().y ) );
1110 box.Normalize();
1111
1112 if( margin < 0 )
1113 {
1114 box.Inflate( margin );
1115 radius += margin;
1116 }
1117
1118 SHAPE_RECT rect( box );
1119 rect.SetRadius( radius );
1120
1121 SHAPE_LINE_CHAIN outline = rect.Outline();
1122 SHAPE_POLY_SET poly( outline );
1123
1124 FILL_T fill_mode = isSolidFill ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL;
1125
1126 if( poly.OutlineCount() > 0 )
1127 {
1128 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1129 {
1130 GERBER_PLOTTER* gbr_plotter = static_cast<GERBER_PLOTTER*>( m_plotter );
1131 gbr_plotter->PlotPolyAsRegion( poly.COutline( 0 ), fill_mode, thickness, &gbr_metadata );
1132 }
1133 else
1134 {
1135 // TODO: PlotPoly needs to handle arcs...
1136 m_plotter->PlotPoly( poly.COutline( 0 ), fill_mode, thickness, getMetadata() );
1137 }
1138 }
1139 }
1140
1141 break;
1142 }
1143
1144 case SHAPE_T::ELLIPSE:
1146 {
1147 const bool isClosed = ( aShape->GetShape() == SHAPE_T::ELLIPSE );
1148
1149 SHAPE_ELLIPSE e = isClosed ? SHAPE_ELLIPSE( aShape->GetEllipseCenter(), aShape->GetEllipseMajorRadius(),
1150 aShape->GetEllipseMinorRadius(), aShape->GetEllipseRotation() )
1152 aShape->GetEllipseMinorRadius(), aShape->GetEllipseRotation(),
1153 aShape->GetEllipseStartAngle(), aShape->GetEllipseEndAngle() );
1154
1156
1157 if( isClosed )
1158 chain.SetClosed( true );
1159
1160 FILL_T fill = ( isClosed && isSolidFill ) ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL;
1161
1162 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER && isClosed )
1163 {
1164 GERBER_PLOTTER* gbr_plotter = static_cast<GERBER_PLOTTER*>( m_plotter );
1165 gbr_plotter->PlotPolyAsRegion( chain, fill, thickness, &gbr_metadata );
1166 }
1167 else
1168 {
1169 m_plotter->PlotPoly( chain, fill, thickness, getMetadata() );
1170 }
1171
1172 break;
1173 }
1174
1175 default:
1177 }
1178 }
1179 else
1180 {
1181 std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapes( true );
1182
1183 for( SHAPE* shape : shapes )
1184 {
1185 STROKE_PARAMS::Stroke( shape, lineStyle, aShape->GetWidth(),
1186 m_plotter->RenderSettings(),
1187 [&]( const VECTOR2I& a, const VECTOR2I& b )
1188 {
1189 m_plotter->ThickSegment( a, b, thickness, getMetadata() );
1190 } );
1191 }
1192
1193 for( SHAPE* shape : shapes )
1194 delete shape;
1195 }
1196
1197 if( isHatchedFill )
1198 {
1199 for( int ii = 0; ii < aShape->GetHatching().OutlineCount(); ++ii )
1200 {
1201 if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1202 {
1203 GERBER_PLOTTER* gbr_plotter = static_cast<GERBER_PLOTTER*>( m_plotter );
1204 gbr_plotter->PlotPolyAsRegion( aShape->GetHatching().Outline( ii ),
1205 FILL_T::FILLED_SHAPE, 0, &gbr_metadata );
1206 }
1207 else
1208 {
1209 m_plotter->PlotPoly( aShape->GetHatching().Outline( ii ), FILL_T::FILLED_SHAPE,
1210 0, getMetadata() );
1211 }
1212 }
1213 }
1214}
1215
1216
1218{
1219 if( !m_layerMask[aBarCode->GetLayer()] )
1220 return;
1221
1222 // To avoid duplicate code, build a PCB_SHAPE to plot the polygon shape
1223 PCB_SHAPE dummy( aBarCode->GetParent(), SHAPE_T::POLY );
1224 dummy.SetLayer( aBarCode->GetLayer() );
1225 dummy.SetFillMode( FILL_T::FILLED_SHAPE );
1226 dummy.SetWidth( 0 );
1227
1228 SHAPE_POLY_SET shape;
1229 aBarCode->TransformShapeToPolySet( shape, aBarCode->GetLayer(), 0, 0, ERROR_INSIDE );
1230 dummy.SetPolyShape( shape );
1231
1232 PlotShape( &dummy );
1233}
1234
1235
1237{
1238 if( !m_layerMask[aTable->GetLayer()] )
1239 return;
1240
1241 GBR_METADATA gbr_metadata;
1242
1243 if( const FOOTPRINT* parentFP = aTable->GetParentFootprint() )
1244 {
1245 gbr_metadata.SetCmpReference( parentFP->GetReference() );
1247 }
1248
1249 aTable->DrawBorders(
1250 [&]( const VECTOR2I& ptA, const VECTOR2I& ptB, const STROKE_PARAMS& stroke )
1251 {
1252 int lineWidth = stroke.GetWidth();
1253 LINE_STYLE lineStyle = stroke.GetLineStyle();
1254
1255 if( lineStyle <= LINE_STYLE::FIRST_TYPE )
1256 {
1257 m_plotter->ThickSegment( ptA, ptB, lineWidth, getMetadata() );
1258 }
1259 else
1260 {
1261 SHAPE_SEGMENT seg( ptA, ptB );
1262
1263 STROKE_PARAMS::Stroke( &seg, lineStyle, lineWidth, m_plotter->RenderSettings(),
1264 [&]( const VECTOR2I& a, const VECTOR2I& b )
1265 {
1266 m_plotter->ThickSegment( a, b, lineWidth, getMetadata() );
1267 } );
1268 }
1269 } );
1270}
1271
1272
1274 const VECTOR2I& aDrillSize, const VECTOR2I& aPadSize,
1275 const EDA_ANGLE& aOrientation, int aSmallDrill )
1276{
1277 VECTOR2I drillSize = aDrillSize;
1278
1279 // Small drill marks have no significance when applied to slots
1280 if( aSmallDrill && aDrillShape == PAD_DRILL_SHAPE::CIRCLE )
1281 drillSize.x = std::min( aSmallDrill, drillSize.x );
1282
1283 // Round holes only have x diameter, slots have both
1284 drillSize.x -= getFineWidthAdj();
1285 drillSize.x = std::clamp( drillSize.x, 1, aPadSize.x - 1 );
1286
1287 if( aDrillShape == PAD_DRILL_SHAPE::OBLONG )
1288 {
1289 drillSize.y -= getFineWidthAdj();
1290 drillSize.y = std::clamp( drillSize.y, 1, aPadSize.y - 1 );
1291
1292 m_plotter->FlashPadOval( aDrillPos, drillSize, aOrientation, nullptr );
1293 }
1294 else
1295 {
1296 m_plotter->FlashPadCircle( aDrillPos, drillSize.x, nullptr );
1297 }
1298}
1299
1300
1302{
1303 int smallDrill = 0;
1304
1306 smallDrill = pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize );
1307
1308 /* Drill marks are drawn white-on-black to knock-out the underlying pad. This works only
1309 * for drivers supporting color change, obviously... it means that:
1310 - PS, SVG and PDF output is correct (i.e. you have a 'donut' pad)
1311 - In gerbers you can't see them. This is arguably the right thing to do since having
1312 drill marks and high speed drill stations is a sure recipe for broken tools and angry
1313 manufacturers. If you *really* want them you could start a layer with negative
1314 polarity to knock-out the film.
1315 - In DXF they go into the 'WHITE' layer. This could be useful.
1316 */
1317 if( m_plotter->GetPlotterType() != PLOT_FORMAT::DXF || GetDXFPlotMode() == FILLED )
1318 m_plotter->SetColor( WHITE );
1319
1320 for( PCB_TRACK* track : m_board->Tracks() )
1321 {
1322 if( track->Type() == PCB_VIA_T )
1323 {
1324 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
1325
1326 // Via are not always on all layers
1327 if( ( via->GetLayerSet() & m_layerMask ).none() )
1328 continue;
1329
1331 VECTOR2I( via->GetDrillValue(), 0 ),
1332 VECTOR2I( via->GetWidth( PADSTACK::ALL_LAYERS ), 0 ),
1333 ANGLE_0, smallDrill );
1334 }
1335 }
1336
1337 for( FOOTPRINT* footprint : m_board->Footprints() )
1338 {
1339 for( PAD* pad : footprint->Pads() )
1340 {
1341 if( pad->GetDrillSize().x == 0 )
1342 continue;
1343
1344 if( ( pad->GetLayerSet() & m_layerMask ).none() )
1345 continue;
1346
1347 if( m_plotter->GetPlotterType() != PLOT_FORMAT::DXF || GetDXFPlotMode() == FILLED )
1348 {
1349 // Drill mark is in black unless we can find something to knock it out of
1350 m_plotter->SetColor( BLACK );
1351
1352 for( PCB_LAYER_ID layer : m_layerMask )
1353 {
1354 if( !pad->IsOnLayer( layer ) )
1355 continue;
1356
1357 VECTOR2I padSize = pad->GetSize( layer );
1358
1359 if( padSize.x > pad->GetDrillSizeX() || padSize.y > pad->GetDrillSizeY() )
1360 {
1361 m_plotter->SetColor( WHITE );
1362 break;
1363 }
1364 }
1365 }
1366
1367 plotOneDrillMark( pad->GetDrillShape(), pad->GetPosition(), pad->GetDrillSize(),
1368 pad->GetSize( PADSTACK::ALL_LAYERS ), pad->GetOrientation(), smallDrill );
1369 }
1370 }
1371
1372 if( m_plotter->GetPlotterType() != PLOT_FORMAT::DXF || GetDXFPlotMode() == FILLED )
1373 m_plotter->SetColor( BLACK );
1374}
@ 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:918
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:986
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:81
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:265
virtual bool IsKnockout() const
Definition board_item.h:352
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:479
const KIFONT::METRICS & GetFontMetrics() const
BOARD_ITEM_CONTAINER * GetParent() const
Definition board_item.h:231
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:554
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:142
constexpr Vec Centre() const
Definition box2.h:93
constexpr coord_type GetLeft() const
Definition box2.h:224
constexpr coord_type GetRight() const
Definition box2.h:213
constexpr const SizeVec & GetSize() const
Definition box2.h:202
constexpr coord_type GetTop() const
Definition box2.h:225
constexpr coord_type GetBottom() const
Definition box2.h:218
void PlotDrillMarks()
Draw a drill mark for pads and vias.
void PlotZone(const ZONE *aZone, PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPolysList)
void PlotPadNumber(const PAD *aPad, const COLOR4D &aColor)
void PlotBoardGraphicItem(const BOARD_ITEM *item)
Plot items like text and graphics but not tracks and footprints.
void PlotPad(const PAD *aPad, PCB_LAYER_ID aLayer, const COLOR4D &aColor, bool aSketchMode)
Plot a pad.
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:151
void PlotShape(const PCB_SHAPE *aShape)
PLOTTER * m_plotter
Definition pcbplot.h:150
bool crossoutDNPItems(PCB_LAYER_ID aLayer)
Definition pcbplot.h:136
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:74
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:131
void PlotFootprintGraphicItems(const FOOTPRINT *aFootprint)
static const COLOR4D WHITE
Definition color4d.h:401
COLOR4D GetColor(int aLayer) const
double AsDegrees() const
Definition eda_angle.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
EDA_ANGLE GetArcAngle() const
int GetEllipseMinorRadius() const
Definition eda_shape.h:310
const VECTOR2I & GetBezierC2() const
Definition eda_shape.h:283
const VECTOR2I & GetEllipseCenter() const
Definition eda_shape.h:292
const SHAPE_POLY_SET & GetHatching() const
EDA_ANGLE GetEllipseEndAngle() const
Definition eda_shape.h:338
int GetEllipseMajorRadius() const
Definition eda_shape.h:301
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition eda_shape.h:462
SHAPE_POLY_SET & GetPolyShape()
EDA_ANGLE GetEllipseRotation() const
Definition eda_shape.h:319
int GetRadius() const
SHAPE_T GetShape() const
Definition eda_shape.h:185
bool IsHatchedFill() const
Definition eda_shape.h:140
virtual void SetFilled(bool aFlag)
Definition eda_shape.h:152
bool IsSolidFill() const
Definition eda_shape.h:133
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:240
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:190
std::vector< VECTOR2I > GetRectCorners() const
EDA_ANGLE GetEllipseStartAngle() const
Definition eda_shape.h:329
wxString SHAPE_T_asString() const
const VECTOR2I & GetBezierC1() const
Definition eda_shape.h:280
int GetCornerRadius() const
bool IsPolyShapeValid() const
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:89
virtual VECTOR2I GetTextSize() const
Definition eda_text.h:282
virtual VECTOR2I GetTextPos() const
Definition eda_text.h:294
bool IsMultilineAllowed() const
Definition eda_text.h:218
virtual bool IsVisible() const
Definition eda_text.h:208
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:703
virtual EDA_ANGLE GetDrawRotation() const
Definition eda_text.h:400
virtual KIFONT::FONT * GetDrawFont(const RENDER_SETTINGS *aSettings) const
Definition eda_text.cpp:667
const TEXT_ATTRIBUTES & GetAttributes() const
Definition eda_text.h:252
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition eda_text.cpp:461
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:943
virtual wxString GetShownText(bool aAllowExtraText, int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition eda_text.h:121
PCB_FIELD & Value()
read/write accessors:
Definition footprint.h:877
LSET GetPrivateLayers() const
Definition footprint.h:315
PCB_FIELD & Reference()
Definition footprint.h:878
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:841
DRAWINGS & GraphicalItems()
Definition footprint.h:378
@ 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
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.
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 ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:177
Definition pad.h:61
PAD_PROP GetProperty() const
Definition pad.h:558
static wxString ShowPadShape(PAD_SHAPE aShape)
Definition pad.cpp:2500
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:370
int GetRoundRectCornerRadius(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1136
const BOX2I GetBoundingBox() const override
The bounding box is cached, so this will be efficient most of the time.
Definition pad.cpp:1599
PAD_ATTRIB GetAttribute() const
Definition pad.h:555
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:302
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition pad.h:202
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:2945
VECTOR2I GetSize(PCB_LAYER_ID aLayer) const
Definition pad.cpp:287
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition pad.cpp:1723
int GetChamferPositions(PCB_LAYER_ID aLayer) const
Definition pad.h:840
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(PCB_LAYER_ID aLayer, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Definition pad.cpp:1194
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
Definition pad.h:823
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1831
Abstract dimension API.
int GetLineThickness() const
const std::vector< std::shared_ptr< SHAPE > > & GetShapes() const
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:329
int GetSolderMaskExpansion() const
void SetShape(SHAPE_T aShape) override
Definition pcb_shape.h:200
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
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.
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...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
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)
Handle a list of polygons defining a copper zone.
Definition zone.h:70
bool IsOnCopperLayer() const override
Definition zone.cpp:574
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
@ ROUND_ALL_CORNERS
All angles are rounded.
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:413
@ ELLIPSE
Definition eda_shape.h:52
@ SEGMENT
Definition eda_shape.h:46
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:47
@ ELLIPSE_ARC
Definition eda_shape.h:53
FILL_T
Definition eda_shape.h:59
@ NO_FILL
Definition eda_shape.h:60
@ FILLED_SHAPE
Fill with object color.
Definition eda_shape.h:61
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:675
bool IsExternalCopperLayer(int aLayerId)
Test whether a layer is an external (F_Cu or B_Cu) copper layer.
Definition layer_ids.h:686
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
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
PAD_DRILL_SHAPE
The set of pad drill shapes, used with PAD::{Set,Get}DrillShape()
Definition padstack.h:69
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:103
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:99
@ PTH
Plated through hole pad.
Definition padstack.h:98
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
Definition padstack.h:100
@ CHAMFERED_RECT
Definition padstack.h:60
@ ROUNDRECT
Definition padstack.h:57
@ TRAPEZOID
Definition padstack.h:56
@ RECTANGLE
Definition padstack.h:54
@ FIDUCIAL_LOCAL
a fiducial (usually a smd) local to the parent footprint
Definition padstack.h:118
@ FIDUCIAL_GLBL
a fiducial (usually a smd) for the full board
Definition padstack.h:117
@ MECHANICAL
a pad used for mechanical support
Definition padstack.h:122
@ PRESSFIT
a PTH with a hole diameter with tight tolerances for press fit pin
Definition padstack.h:123
@ HEATSINK
a pad used as heat sink, usually in SMD footprints
Definition padstack.h:120
@ NONE
no special fabrication property
Definition padstack.h:115
@ TESTPOINT
a test point pad
Definition padstack.h:119
@ CASTELLATED
a pad with a castellated through hole
Definition padstack.h:121
@ BGA
Smd pad, used in BGA footprints.
Definition padstack.h:116
BARCODE class definition.
#define getMetadata()
@ SKETCH
Definition plotter.h:78
@ 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.
std::vector< std::vector< std::string > > table
const SHAPE_LINE_CHAIN chain
int radius
VECTOR2I end
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:81
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition typeinfo.h:99
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:96
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:90
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition typeinfo.h:97
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:86
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:85
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
Definition typeinfo.h:82
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:94
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition typeinfo.h:100
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:95
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition typeinfo.h:87
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition typeinfo.h:98
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683