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