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