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