KiCad PCB EDA Suite
pcb_painter.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) 2013-2019 CERN
5 * Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Tomasz Wlostowski <[email protected]>
8 * @author Maciej Suminski <[email protected]>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, you may find one here:
22 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23 * or you may search the http://www.gnu.org website for the version 2 license,
24 * or you may write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
28#include <board.h>
30#include <pcb_track.h>
31#include <pcb_group.h>
32#include <footprint.h>
33#include <fp_textbox.h>
34#include <pad.h>
35#include <pcb_shape.h>
36#include <string_utils.h>
37#include <zone.h>
38#include <pcb_bitmap.h>
39#include <pcb_text.h>
40#include <pcb_textbox.h>
41#include <pcb_marker.h>
42#include <pcb_dimension.h>
43#include <pcb_target.h>
44
45#include <layer_ids.h>
46#include <pcb_painter.h>
47#include <pcb_display_options.h>
53#include <pcbnew_settings.h>
54
57#include <callback_gal.h>
60#include <geometry/shape_rect.h>
64#include <bezier_curves.h>
65#include <kiface_base.h>
66#include <gr_text.h>
67#include <pgm_base.h>
68
69using namespace KIGFX;
70
71
73{
74 return dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() );
75}
76
77// Helpers for display options existing in Cvpcb and Pcbnew
78// Note, when running Cvpcb, pcbconfig() returns nullptr and viewer_settings()
79// returns the viewer options existing to Cvpcb and Pcbnew
80PCB_VIEWERS_SETTINGS_BASE* PCB_PAINTER::viewer_settings()
81{
82 switch( m_frameType )
83 {
88 default:
89 return Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
90
94 case FRAME_CVPCB:
96 return Pgm().GetSettingsManager().GetAppSettings<CVPCB_SETTINGS>();
97 }
98}
99
100
102{
103 m_backgroundColor = COLOR4D( 0.0, 0.0, 0.0, 1.0 );
107
108 m_trackOpacity = 1.0;
109 m_viaOpacity = 1.0;
110 m_padOpacity = 1.0;
111 m_zoneOpacity = 1.0;
112 m_imageOpacity = 1.0;
113
115
116 m_PadEditModePad = nullptr;
117
118 SetDashLengthRatio( 12 ); // From ISO 128-2
119 SetGapLengthRatio( 3 ); // From ISO 128-2
120
121 update();
122}
123
124
126{
128
129 // Init board layers colors:
130 for( int i = 0; i < PCB_LAYER_ID_COUNT; i++ )
131 {
132 m_layerColors[i] = aSettings->GetColor( i );
133
134 // Guard: if the alpha channel is too small, the layer is not visible.
135 if( m_layerColors[i].a < 0.2 )
136 m_layerColors[i].a = 0.2;
137 }
138
139 // Init specific graphic layers colors:
140 for( int i = GAL_LAYER_ID_START; i < GAL_LAYER_ID_END; i++ )
141 m_layerColors[i] = aSettings->GetColor( i );
142
143 // Colors for layers that aren't theme-able
145 m_layerColors[LAYER_VIA_NETNAMES] = COLOR4D( 0.2, 0.2, 0.2, 0.9 );
146 m_layerColors[LAYER_PAD_NETNAMES] = COLOR4D( 1.0, 1.0, 1.0, 0.9 );
147 m_layerColors[LAYER_PAD_FR] = aSettings->GetColor( F_Cu );
148 m_layerColors[LAYER_PAD_BK] = aSettings->GetColor( B_Cu );
149 m_layerColors[LAYER_PAD_FR_NETNAMES] = COLOR4D( 1.0, 1.0, 1.0, 0.9 );
150 m_layerColors[LAYER_PAD_BK_NETNAMES] = COLOR4D( 1.0, 1.0, 1.0, 0.9 );
151
152 // Netnames for copper layers
153 for( LSEQ cu = LSET::AllCuMask().CuStack(); cu; ++cu )
154 {
155 const COLOR4D lightLabel( 1.0, 1.0, 1.0, 0.7 );
156 const COLOR4D darkLabel = lightLabel.Inverted();
157 PCB_LAYER_ID layer = *cu;
158
159 if( m_layerColors[layer].GetBrightness() > 0.5 )
160 m_layerColors[GetNetnameLayer( layer )] = darkLabel;
161 else
162 m_layerColors[GetNetnameLayer( layer )] = lightLabel;
163 }
164
165 if( PgmOrNull() ) // can be null if used without project (i.e. from python script)
166 m_hiContrastFactor = 1.0f - Pgm().GetCommonSettings()->m_Appearance.hicontrast_dimming_factor;
167 else
168 m_hiContrastFactor = 1.0f - 0.8f; // default value
169
170 update();
171}
172
173
175{
180
182 m_viaOpacity = aOptions.m_ViaOpacity;
183 m_padOpacity = aOptions.m_PadOpacity;
184 m_zoneOpacity = aOptions.m_ZoneOpacity;
186}
187
188
189COLOR4D PCB_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) const
190{
191 const EDA_ITEM* item = dynamic_cast<const EDA_ITEM*>( aItem );
192 const BOARD_CONNECTED_ITEM* conItem = dynamic_cast<const BOARD_CONNECTED_ITEM*> ( aItem );
193 int netCode = -1;
194 int originalLayer = aLayer;
195
196 // Marker shadows
197 if( aLayer == LAYER_MARKER_SHADOWS )
198 return m_backgroundColor.WithAlpha( 0.6 );
199
200 if( IsHoleLayer( aLayer ) && m_isPrinting )
201 {
202 // Careful that we don't end up with the same colour for the annular ring and the hole
203 // when printing in B&W.
204 const PAD* pad = dynamic_cast<const PAD*>( item );
205 const PCB_VIA* via = dynamic_cast<const PCB_VIA*>( item );
206 int holeLayer = aLayer;
207 int annularRingLayer = UNDEFINED_LAYER;
208
209 if( pad && pad->GetAttribute() == PAD_ATTRIB::PTH )
210 annularRingLayer = LAYER_PADS_TH;
211 else if( via && via->GetViaType() == VIATYPE::MICROVIA )
212 annularRingLayer = LAYER_VIA_MICROVIA;
213 else if( via && via->GetViaType() == VIATYPE::BLIND_BURIED )
214 annularRingLayer = LAYER_VIA_BBLIND;
215 else if( via && via->GetViaType() == VIATYPE::THROUGH )
216 annularRingLayer = LAYER_VIA_THROUGH;
217
218 if( annularRingLayer != UNDEFINED_LAYER
219 && m_layerColors[ holeLayer ] == m_layerColors[ annularRingLayer ] )
220 {
221 aLayer = LAYER_PCB_BACKGROUND;
222 }
223 }
224
225 // Zones should pull from the copper layer
226 if( item && ( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T ) )
227 {
228 if( IsZoneFillLayer( aLayer ) )
229 aLayer = aLayer - LAYER_ZONE_START;
230 }
231
232 // Hole walls should pull from the copper layer
233 if( aLayer == LAYER_PAD_HOLEWALLS )
234 aLayer = LAYER_PADS_TH;
235 else if( aLayer == LAYER_VIA_HOLEWALLS )
236 aLayer = LAYER_VIA_THROUGH;
237
238 // Normal path: get the layer base color
239 COLOR4D color = m_layerColors[aLayer];
240
241 if( !item )
242 return m_layerColors[aLayer];
243
244 // Selection disambiguation
245 if( item->IsBrightened() )
246 return color.Brightened( m_selectFactor ).WithAlpha( 0.8 );
247
248 // Normal selection
249 if( item->IsSelected() )
250 color = m_layerColorsSel[aLayer];
251
252 // Try to obtain the netcode for the item
253 if( conItem )
254 netCode = conItem->GetNetCode();
255
256 bool highlighted = m_highlightEnabled && m_highlightNetcodes.count( netCode );
257 bool selected = item->IsSelected();
258
259 // Apply net color overrides
260 if( conItem && m_netColorMode == NET_COLOR_MODE::ALL && IsNetCopperLayer( aLayer ) )
261 {
262 COLOR4D netColor = COLOR4D::UNSPECIFIED;
263
264 auto ii = m_netColors.find( netCode );
265
266 if( ii != m_netColors.end() )
267 netColor = ii->second;
268
269 if( netColor == COLOR4D::UNSPECIFIED )
270 {
271 auto jj = m_netclassColors.find( conItem->GetNetClassName() );
272
273 if( jj != m_netclassColors.end() )
274 netColor = jj->second;
275 }
276
277 if( netColor == COLOR4D::UNSPECIFIED )
278 netColor = color;
279
280 if( selected )
281 {
282 // Selection brightening overrides highlighting
283 netColor.Brighten( m_selectFactor );
284 }
285 else if( m_highlightEnabled )
286 {
287 // Highlight brightens objects on all layers and darkens everything else for contrast
288 if( highlighted )
289 netColor.Brighten( m_highlightFactor );
290 else
291 netColor.Darken( 1.0 - m_highlightFactor );
292 }
293
294 color = netColor;
295 }
296 else if( !selected && m_highlightEnabled )
297 {
298 // Single net highlight mode
299 color = m_highlightNetcodes.count( netCode ) ? m_layerColorsHi[aLayer]
300 : m_layerColorsDark[aLayer];
301 }
302
303 // Apply high-contrast dimming
304 if( m_hiContrastEnabled && m_highContrastLayers.size() && !highlighted && !selected )
305 {
307 bool isActive = m_highContrastLayers.count( aLayer );
308 bool hide = false;
309
310 switch( originalLayer )
311 {
312 case LAYER_PADS_TH:
313 {
314 const PAD* pad = static_cast<const PAD*>( item );
315
316 if( !pad->FlashLayer( primary ) )
317 {
318 isActive = false;
319
320 if( IsCopperLayer( primary ) )
321 hide = true;
322 }
323
325 isActive = false;
326
327 break;
328 }
329
330 case LAYER_VIA_BBLIND:
332 {
333 const PCB_VIA* via = static_cast<const PCB_VIA*>( item );
334
335 // Target graphic is active if the via crosses the primary layer
336 if( via->GetLayerSet().test( primary ) == 0 )
337 {
338 isActive = false;
339 hide = true;
340 }
341
342 break;
343 }
344
346 {
347 const PCB_VIA* via = static_cast<const PCB_VIA*>( item );
348
349 if( !via->FlashLayer( primary ) )
350 {
351 isActive = false;
352
353 if( IsCopperLayer( primary ) )
354 hide = true;
355 }
356
357 break;
358 }
359
363 // Pad holes are active is any physical layer is active
364 if( LSET::PhysicalLayersMask().test( primary ) == 0 )
365 isActive = false;
366
367 break;
368
369 case LAYER_VIA_HOLES:
371 {
372 const PCB_VIA* via = static_cast<const PCB_VIA*>( item );
373
374 if( via->GetViaType() == VIATYPE::BLIND_BURIED
375 || via->GetViaType() == VIATYPE::MICROVIA )
376 {
377 // A blind or micro via's hole is active if it crosses the primary layer
378 if( via->GetLayerSet().test( primary ) == 0 )
379 isActive = false;
380 }
381 else
382 {
383 // A through via's hole is active if any physical layer is active
384 if( LSET::PhysicalLayersMask().test( primary ) == 0 )
385 isActive = false;
386 }
387
388 break;
389 }
390
391 default:
392 break;
393 }
394
395 if( !isActive )
396 {
398 || IsNetnameLayer( aLayer )
399 || hide )
400 {
402 }
403 else
404 {
406
407 // Bitmaps can't have their color mixed so just reduce the opacity a bit so they
408 // show through less
409 if( item->Type() == PCB_BITMAP_T )
411 }
412 }
413 }
414 else if( originalLayer == LAYER_VIA_BBLIND || originalLayer == LAYER_VIA_MICROVIA )
415 {
416 const PCB_VIA* via = static_cast<const PCB_VIA*>( item );
417 const BOARD* board = via->GetBoard();
418 LSET visibleLayers = board->GetVisibleLayers() & board->GetEnabledLayers();
419
420 // Target graphic is visible if the via crosses a visible layer
421 if( ( via->GetLayerSet() & visibleLayers ).none() )
423 }
424
425 // Apply per-type opacity overrides
426 if( item->Type() == PCB_TRACE_T || item->Type() == PCB_ARC_T )
428 else if( item->Type() == PCB_VIA_T )
429 color.a *= m_viaOpacity;
430 else if( item->Type() == PCB_PAD_T )
431 color.a *= m_padOpacity;
432 else if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
433 color.a *= m_zoneOpacity;
434 else if( item->Type() == PCB_BITMAP_T )
436
437 // No special modifiers enabled
438 return color;
439}
440
441
443{
444 return pcbconfig() && pcbconfig()->m_ShowPageLimits;
445}
446
447
449 PAINTER( aGal ),
450 m_frameType( aFrameType ),
451 m_maxError( ARC_HIGH_DEF ),
452 m_holePlatingThickness( 0 ),
453 m_lockedShadowMargin( 0 )
454{
455}
456
457
458int PCB_PAINTER::getLineThickness( int aActualThickness ) const
459{
460 // if items have 0 thickness, draw them with the outline
461 // width, otherwise respect the set value (which, no matter
462 // how small will produce something)
463 if( aActualThickness == 0 )
465
466 return aActualThickness;
467}
468
469
470int PCB_PAINTER::getDrillShape( const PAD* aPad ) const
471{
472 return aPad->GetDrillShape();
473}
474
475
477{
478 SHAPE_SEGMENT segm = *aPad->GetEffectiveHoleShape().get();
479 return segm;
480}
481
482
483int PCB_PAINTER::getViaDrillSize( const PCB_VIA* aVia ) const
484{
485 return aVia->GetDrillValue();
486}
487
488
489bool PCB_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer )
490{
491 const BOARD_ITEM* item = dynamic_cast<const BOARD_ITEM*>( aItem );
492
493 if( !item )
494 return false;
495
496 if( const BOARD* board = item->GetBoard() )
497 {
498 BOARD_DESIGN_SETTINGS& bds = board->GetDesignSettings();
502
503 if( item->GetParentFootprint() && !board->IsFootprintHolder() )
504 {
505 FOOTPRINT* parentFP = static_cast<FOOTPRINT*>( item->GetParentFootprint() );
506
507 // Never draw footprint bitmaps on board
508 if( item->Type() == PCB_BITMAP_T )
509 return false;
510 else if( item->GetLayerSet().count() > 1 )
511 {
512 // For multi-layer objects, exclude only those layers that are private
513 if( IsPcbLayer( aLayer ) && parentFP->GetPrivateLayers().test( aLayer ) )
514 return false;
515 }
516 else if( item->GetLayerSet().count() == 1 )
517 {
518 // For single-layer objects, exclude all layers including ancillary layers
519 // such as holes, netnames, etc.
520 PCB_LAYER_ID singleLayer = item->GetLayerSet().Seq()[0];
521
522 if( parentFP->GetPrivateLayers().test( singleLayer ) )
523 return false;
524 }
525 }
526 }
527 else
528 {
531 }
532
533 // the "cast" applied in here clarifies which overloaded draw() is called
534 switch( item->Type() )
535 {
536 case PCB_TRACE_T:
537 draw( static_cast<const PCB_TRACK*>( item ), aLayer );
538 break;
539
540 case PCB_ARC_T:
541 draw( static_cast<const PCB_ARC*>( item ), aLayer );
542 break;
543
544 case PCB_VIA_T:
545 draw( static_cast<const PCB_VIA*>( item ), aLayer );
546 break;
547
548 case PCB_PAD_T:
549 draw( static_cast<const PAD*>( item ), aLayer );
550 break;
551
552 case PCB_SHAPE_T:
553 case PCB_FP_SHAPE_T:
554 draw( static_cast<const PCB_SHAPE*>( item ), aLayer );
555 break;
556
557 case PCB_BITMAP_T:
558 draw( static_cast<const PCB_BITMAP*>( item ), aLayer );
559 break;
560
561 case PCB_TEXT_T:
562 draw( static_cast<const PCB_TEXT*>( item ), aLayer );
563 break;
564
565 case PCB_TEXTBOX_T:
566 draw( static_cast<const PCB_TEXTBOX*>( item ), aLayer );
567 break;
568
569 case PCB_FP_TEXT_T:
570 draw( static_cast<const FP_TEXT*>( item ), aLayer );
571 break;
572
573 case PCB_FP_TEXTBOX_T:
574 draw( static_cast<const FP_TEXTBOX*>( item ), aLayer );
575 break;
576
577 case PCB_FOOTPRINT_T:
578 draw( static_cast<const FOOTPRINT*>( item ), aLayer );
579 break;
580
581 case PCB_GROUP_T:
582 draw( static_cast<const PCB_GROUP*>( item ), aLayer );
583 break;
584
585 case PCB_ZONE_T:
586 case PCB_FP_ZONE_T:
587 draw( static_cast<const ZONE*>( item ), aLayer );
588 break;
589
591 case PCB_DIM_CENTER_T:
592 case PCB_DIM_RADIAL_T:
594 case PCB_DIM_LEADER_T:
600 draw( static_cast<const PCB_DIMENSION_BASE*>( item ), aLayer );
601 break;
602
603 case PCB_TARGET_T:
604 draw( static_cast<const PCB_TARGET*>( item ) );
605 break;
606
607 case PCB_MARKER_T:
608 draw( static_cast<const PCB_MARKER*>( item ), aLayer );
609 break;
610
611 default:
612 // Painter does not know how to draw the object
613 return false;
614 }
615
616 // Draw bounding boxes after drawing objects so they can be seen.
618 {
619 // Show bounding boxes of painted objects for debugging.
620 BOX2I box = item->GetBoundingBox();
621
622 m_gal->SetIsFill( false );
623 m_gal->SetIsStroke( true );
624
625 if( item->Type() == PCB_FOOTPRINT_T )
626 {
627 m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) :
628 COLOR4D( MAGENTA ) );
629 }
630 else
631 {
632 m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) :
633 COLOR4D( 0.4, 0.4, 0.4, 1 ) );
634 }
635
636 m_gal->SetLineWidth( 1 );
637 m_gal->DrawRectangle( box.GetOrigin(), box.GetEnd() );
638
639 if( item->Type() == PCB_FOOTPRINT_T )
640 {
641 m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) :
642 COLOR4D( CYAN ) );
643
644 const FOOTPRINT* fp = static_cast<const FOOTPRINT*>( item );
645
646 if( fp )
647 {
648 const SHAPE_POLY_SET& convex = fp->GetBoundingHull();
649
650 m_gal->DrawPolyline( convex.COutline( 0 ) );
651 }
652 }
653 }
654
655 return true;
656}
657
658
659void PCB_PAINTER::draw( const PCB_TRACK* aTrack, int aLayer )
660{
661 VECTOR2I start( aTrack->GetStart() );
662 VECTOR2I end( aTrack->GetEnd() );
663 int track_width = aTrack->GetWidth();
664 COLOR4D color = m_pcbSettings.GetColor( aTrack, aLayer );
665
666 if( IsNetnameLayer( aLayer ) )
667 {
668 if( !pcbconfig() || pcbconfig()->m_Display.m_NetNames < 2 )
669 return;
670
671 if( aTrack->GetNetCode() <= NETINFO_LIST::UNCONNECTED )
672 return;
673
674 // When drawing netnames, clip the track to the viewport
675 BOX2D viewport;
676 VECTOR2D screenSize = m_gal->GetScreenPixelSize();
677 const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
678
679 viewport.SetOrigin( VECTOR2D( matrix * VECTOR2D( 0, 0 ) ) );
680 viewport.SetEnd( VECTOR2D( matrix * screenSize ) );
681 viewport.Normalize();
682
683 BOX2I clipBox( viewport.GetOrigin(), viewport.GetSize() );
684 SEG visibleSeg( start, end );
685
686 ClipLine( &clipBox, visibleSeg.A.x, visibleSeg.A.y, visibleSeg.B.x, visibleSeg.B.y );
687
688 wxString netName = aTrack->GetUnescapedShortNetname();
689 size_t num_char = netName.size();
690
691 // Check if the track is long enough to have a netname displayed
692 int seg_minlength = track_width * num_char;
693
694 if( visibleSeg.Length() < seg_minlength )
695 return;
696
697 double textSize = track_width;
698 double penWidth = textSize / 12.0;
699 EDA_ANGLE textOrientation;
700 int num_names = 1;
701
702 if( end.y == start.y ) // horizontal
703 {
704 textOrientation = ANGLE_HORIZONTAL;
705 num_names = std::max( num_names,
706 static_cast<int>( aTrack->GetLength() / viewport.GetWidth() ) );
707 }
708 else if( end.x == start.x ) // vertical
709 {
710 textOrientation = ANGLE_VERTICAL;
711 num_names = std::max( num_names,
712 static_cast<int>( aTrack->GetLength() / viewport.GetHeight() ) );
713 }
714 else
715 {
716 textOrientation = -EDA_ANGLE( visibleSeg.B - visibleSeg.A );
717 textOrientation.Normalize90();
718
719 double min_size = std::min( viewport.GetWidth(), viewport.GetHeight() );
720 num_names = std::max( num_names,
721 static_cast<int>( aTrack->GetLength() / ( M_SQRT2 * min_size ) ) );
722 }
723
724 m_gal->SetIsStroke( true );
725 m_gal->SetIsFill( false );
727 m_gal->SetLineWidth( penWidth );
728 m_gal->SetFontBold( false );
729 m_gal->SetFontItalic( false );
730 m_gal->SetFontUnderlined( false );
731 m_gal->SetTextMirrored( false );
732 m_gal->SetGlyphSize( VECTOR2D( textSize * 0.55, textSize * 0.55 ) );
735
736 for( int ii = 0; ii < num_names; ++ii )
737 {
738 VECTOR2I textPosition =
739 VECTOR2D( start ) * static_cast<double>( num_names - ii ) / ( num_names + 1 )
740 + VECTOR2D( end ) * static_cast<double>( ii + 1 ) / ( num_names + 1 );
741
742 if( clipBox.Contains( textPosition ) )
743 m_gal->BitmapText( netName, textPosition, textOrientation );
744 }
745
746 return;
747 }
748 else if( IsCopperLayer( aLayer ) || aLayer == LAYER_LOCKED_ITEM_SHADOW )
749 {
750 // Draw a regular track
751 bool outline_mode = pcbconfig()
753 && aLayer != LAYER_LOCKED_ITEM_SHADOW;
756 m_gal->SetIsStroke( outline_mode );
757 m_gal->SetIsFill( not outline_mode );
759
760 if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
761 track_width = track_width + m_lockedShadowMargin;
762
763 m_gal->DrawSegment( start, end, track_width );
764 }
765
766 // Clearance lines
767 if( pcbconfig() && pcbconfig()->m_Display.m_TrackClearance == SHOW_WITH_VIA_ALWAYS
769 {
770 int clearance = aTrack->GetOwnClearance( m_pcbSettings.GetActiveLayer() );
771
773 m_gal->SetIsFill( false );
774 m_gal->SetIsStroke( true );
776 m_gal->DrawSegment( start, end, track_width + clearance * 2 );
777 }
778}
779
780
781void PCB_PAINTER::draw( const PCB_ARC* aArc, int aLayer )
782{
783 VECTOR2D center( aArc->GetCenter() );
784 int width = aArc->GetWidth();
785 COLOR4D color = m_pcbSettings.GetColor( aArc, aLayer );
786 double radius = aArc->GetRadius();
787 EDA_ANGLE start_angle = aArc->GetArcAngleStart();
788 EDA_ANGLE angle = aArc->GetAngle();
789
790 if( IsNetnameLayer( aLayer ) )
791 {
792 // Ummm, yeah. Anyone fancy implementing text on a path?
793 return;
794 }
795 else if( IsCopperLayer( aLayer ) || aLayer == LAYER_LOCKED_ITEM_SHADOW )
796 {
797 // Draw a regular track
798 bool outline_mode = pcbconfig()
800 && aLayer != LAYER_LOCKED_ITEM_SHADOW;
803 m_gal->SetIsStroke( outline_mode );
804 m_gal->SetIsFill( not outline_mode );
806
807 if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
808 width = width + m_lockedShadowMargin;
809
810 m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle, width,
811 m_maxError );
812 }
813
814 // Clearance lines
815 if( pcbconfig() && pcbconfig()->m_Display.m_TrackClearance == SHOW_WITH_VIA_ALWAYS
817 {
818 int clearance = aArc->GetOwnClearance( m_pcbSettings.GetActiveLayer() );
819
821 m_gal->SetIsFill( false );
822 m_gal->SetIsStroke( true );
824
825 m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle,
826 width + clearance * 2, m_maxError );
827 }
828
829// Debug only: enable this code only to test the TransformArcToPolygon function
830// and display the polygon outline created by it.
831// arcs on F_Cu are approximated with ERROR_INSIDE, others with ERROR_OUTSIDE
832#if 0
833 SHAPE_POLY_SET cornerBuffer;
835 TransformArcToPolygon( cornerBuffer, aArc->GetStart(), aArc->GetMid(), aArc->GetEnd(), width,
836 m_maxError, errorloc );
838 m_gal->SetIsFill( false );
839 m_gal->SetIsStroke( true );
840 m_gal->SetStrokeColor( COLOR4D( 0, 0, 1.0, 1.0 ) );
841 m_gal->DrawPolygon( cornerBuffer );
842#endif
843
844// Debug only: enable this code only to test the SHAPE_ARC::ConvertToPolyline function
845// and display the polyline created by it.
846#if 0
847 SHAPE_ARC arc( aArc->GetCenter(), aArc->GetStart(), aArc->GetAngle() / 10.0, aArc->GetWidth() );
850 m_gal->SetIsFill( false );
851 m_gal->SetIsStroke( true );
852 m_gal->SetStrokeColor( COLOR4D( 0.3, 0.2, 0.5, 1.0 ) );
853
854 for( int idx = 1; idx < arcSpine.PointCount(); idx++ )
855 m_gal->DrawSegment( arcSpine.CPoint( idx-1 ), arcSpine.CPoint( idx ), aArc->GetWidth() );
856#endif
857}
858
859
860void PCB_PAINTER::draw( const PCB_VIA* aVia, int aLayer )
861{
862 const BOARD* board = aVia->GetBoard();
863 COLOR4D color = m_pcbSettings.GetColor( aVia, aLayer );
864 VECTOR2D center( aVia->GetStart() );
865
866 if( color == COLOR4D::CLEAR )
867 return;
868
869 // Draw description layer
870 if( IsNetnameLayer( aLayer ) )
871 {
872 VECTOR2D position( center );
873
874 // Is anything that we can display enabled (netname and/or layers ids)?
875 bool showNets = pcbconfig() && pcbconfig()->m_Display.m_NetNames != 0
876 && !aVia->GetNetname().empty();
877 bool showLayers = aVia->GetViaType() != VIATYPE::THROUGH;
878
879 if( !showNets && !showLayers )
880 return;
881
882 double maxSize = PCB_RENDER_SETTINGS::MAX_FONT_SIZE;
883 double size = aVia->GetWidth();
884
885 // Font size limits
886 if( size > maxSize )
887 size = maxSize;
888
889 m_gal->Save();
890 m_gal->Translate( position );
891
892 // Default font settings
896 m_gal->SetFontBold( false );
897 m_gal->SetFontItalic( false );
898 m_gal->SetFontUnderlined( false );
899 m_gal->SetTextMirrored( false );
900 m_gal->SetStrokeColor( m_pcbSettings.GetColor( nullptr, aLayer ) );
901 m_gal->SetIsStroke( true );
902 m_gal->SetIsFill( false );
903
904 // Set the text position via position. if only one text, it is on the via position
905 // For 2 lines, the netname is slightly below the center, and the layer IDs above
906 // the netname
907 VECTOR2D textpos( 0.0, 0.0 );
908
909 wxString netname = aVia->GetUnescapedShortNetname();
910
911 int topLayer = aVia->TopLayer() + 1;
912 int bottomLayer = std::min( aVia->BottomLayer() + 1, board->GetCopperLayerCount() );
913
914 wxString layerIds;
915 layerIds.Printf( wxT( "%d-%d" ), topLayer, bottomLayer );
916
917 // a good size is set room for at least 6 chars, to be able to print 2 lines of text,
918 // or at least 3 chars for only the netname
919 // (The layerIds string has 5 chars max)
920 int minCharCnt = showLayers ? 6 : 3;
921
922 // approximate the size of netname and layerIds text:
923 double tsize = 1.5 * size / std::max( PrintableCharCount( netname ), minCharCnt );
924 tsize = std::min( tsize, size );
925
926 // Use a smaller text size to handle interline, pen size..
927 tsize *= 0.75;
928 VECTOR2D namesize( tsize, tsize );
929
930 // For 2 lines, adjust the text pos (move it a small amount to the bottom)
931 if( showLayers )
932 textpos.y += tsize/5;
933
934 m_gal->SetGlyphSize( namesize );
935 m_gal->SetLineWidth( namesize.x / 10.0 );
936
937 if( showNets )
938 m_gal->BitmapText( netname, textpos, ANGLE_HORIZONTAL );
939
940 if( showLayers )
941 {
942 if( showNets )
943 textpos.y -= tsize * 1.3;
944
945 m_gal->BitmapText( layerIds, textpos, ANGLE_HORIZONTAL );
946 }
947
948 m_gal->Restore();
949
950 return;
951 }
952
953 bool outline_mode = pcbconfig() && !pcbconfig()->m_Display.m_DisplayViaFill;
954
957 m_gal->SetIsStroke( true );
958 m_gal->SetIsFill( false );
959
960 if( outline_mode )
962
963 if( aLayer == LAYER_VIA_HOLEWALLS )
964 {
965 double radius = ( getViaDrillSize( aVia ) / 2.0 ) + m_holePlatingThickness;
966
967 if( !outline_mode )
968 {
970 radius -= m_holePlatingThickness / 2.0;
971 }
972
973 m_gal->DrawCircle( center, radius );
974 }
975 else if( aLayer == LAYER_VIA_HOLES )
976 {
977 m_gal->SetIsStroke( false );
978 m_gal->SetIsFill( true );
979 m_gal->DrawCircle( center, getViaDrillSize( aVia ) / 2.0 );
980 }
981 else if( aLayer == LAYER_VIA_THROUGH || m_pcbSettings.IsPrinting() )
982 {
983 int annular_width = ( aVia->GetWidth() - getViaDrillSize( aVia ) ) / 2.0;
984 double radius = aVia->GetWidth() / 2.0;
985 bool draw = false;
986
988 {
990 }
991 else if( aVia->FlashLayer( board->GetVisibleLayers() & board->GetEnabledLayers() ) )
992 {
993 draw = true;
994 }
995 else if( aVia->IsSelected() )
996 {
997 draw = true;
998 outline_mode = true;
1000 }
1001
1002 if( !outline_mode )
1003 {
1004 m_gal->SetLineWidth( annular_width );
1005 radius -= annular_width / 2.0;
1006 }
1007
1008 if( draw )
1009 m_gal->DrawCircle( center, radius );
1010 }
1011 else if( aLayer == LAYER_VIA_BBLIND || aLayer == LAYER_VIA_MICROVIA )
1012 {
1013 int annular_width = ( aVia->GetWidth() - getViaDrillSize( aVia ) ) / 2.0;
1014 double radius = aVia->GetWidth() / 2.0;
1015
1016 // Outer circles of blind/buried and micro-vias are drawn in a special way to indicate the
1017 // top and bottom layers
1018 PCB_LAYER_ID layerTop, layerBottom;
1019 aVia->LayerPair( &layerTop, &layerBottom );
1020
1021 if( !outline_mode )
1022 {
1023 m_gal->SetIsStroke( false );
1024 m_gal->SetIsFill( true );
1025 }
1026
1027 m_gal->SetStrokeColor( m_pcbSettings.GetColor( aVia, layerTop ) );
1028 m_gal->SetFillColor( m_pcbSettings.GetColor( aVia, layerTop ) );
1029 m_gal->DrawArc( center, radius, EDA_ANGLE( 240, DEGREES_T ), EDA_ANGLE( 300, DEGREES_T ) );
1030
1031 m_gal->SetStrokeColor( m_pcbSettings.GetColor( aVia, layerBottom ) );
1032 m_gal->SetFillColor( m_pcbSettings.GetColor( aVia, layerBottom ) );
1033 m_gal->DrawArc( center, radius, EDA_ANGLE( 60, DEGREES_T ), EDA_ANGLE( 120, DEGREES_T ) );
1034
1037 m_gal->SetIsStroke( true );
1038 m_gal->SetIsFill( false );
1039
1040 if( !outline_mode )
1041 {
1042 m_gal->SetLineWidth( annular_width );
1043 radius -= annular_width / 2.0;
1044 }
1045
1046 m_gal->DrawCircle( center, radius );
1047 }
1048 else if( aLayer == LAYER_LOCKED_ITEM_SHADOW ) // draw a ring around the via
1049 {
1051
1052 m_gal->DrawCircle( center, ( aVia->GetWidth() + m_lockedShadowMargin ) / 2.0 );
1053 }
1054
1055 // Clearance lines
1057 && aLayer != LAYER_VIA_HOLES
1059 {
1061 double radius;
1062
1063 if( aVia->FlashLayer( activeLayer ) )
1064 radius = aVia->GetWidth() / 2.0;
1065 else
1066 radius = getViaDrillSize( aVia ) / 2.0 + m_holePlatingThickness;
1067
1069 m_gal->SetIsFill( false );
1070 m_gal->SetIsStroke( true );
1072 m_gal->DrawCircle( center, radius + aVia->GetOwnClearance( activeLayer ) );
1073 }
1074}
1075
1076
1077void PCB_PAINTER::draw( const PAD* aPad, int aLayer )
1078{
1079 const BOARD* board = aPad->GetBoard();
1080 COLOR4D color = m_pcbSettings.GetColor( aPad, aLayer );
1081
1082 if( IsNetnameLayer( aLayer ) )
1083 {
1084 PCBNEW_SETTINGS::DISPLAY_OPTIONS* displayOpts = pcbconfig() ? &pcbconfig()->m_Display : nullptr;
1085 wxString netname;
1086 wxString padNumber;
1087
1088 if( viewer_settings()->m_ViewersDisplay.m_DisplayPadNumbers )
1089 {
1090 padNumber = UnescapeString( aPad->GetNumber() );
1091
1092 if( dynamic_cast<CVPCB_SETTINGS*>( viewer_settings() ) )
1093 netname = aPad->GetUnescapedShortNetname();
1094 }
1095
1096 if( displayOpts )
1097 {
1098 if( displayOpts->m_NetNames == 1 || displayOpts->m_NetNames == 3 )
1099 netname = aPad->GetUnescapedShortNetname();
1100
1101 if( aPad->IsNoConnectPad() )
1102 netname = wxT( "x" );
1103 else if( aPad->IsFreePad() )
1104 netname = wxT( "*" );
1105 }
1106
1107 if( netname.IsEmpty() && padNumber.IsEmpty() )
1108 return;
1109
1110 BOX2I padBBox = aPad->GetBoundingBox();
1111 VECTOR2D position = padBBox.Centre();
1112 VECTOR2D padsize = VECTOR2D( padBBox.GetSize() );
1113
1114 if( aPad->GetFlags() & ENTERED )
1115 {
1116 FOOTPRINT* fp = static_cast<FOOTPRINT*>( aPad->GetParentFootprint() );
1117
1118 // Find the number box
1119 for( const BOARD_ITEM* aItem : fp->GraphicalItems() )
1120 {
1121 if( aItem->Type() == PCB_FP_SHAPE_T )
1122 {
1123 const FP_SHAPE* shape = static_cast<const FP_SHAPE*>( aItem );
1124
1125 if( shape->IsAnnotationProxy() )
1126 {
1127 position = shape->GetCenter();
1128 padsize = shape->GetBotRight() - shape->GetTopLeft();
1129
1130 // We normally draw a bit outside the pad, but this will be somewhat
1131 // unexpected when the user has drawn a box.
1132 padsize *= 0.9;
1133
1134 break;
1135 }
1136 }
1137 }
1138 }
1139 else if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
1140 {
1141 // See if we have a number box
1142 for( const std::shared_ptr<PCB_SHAPE>& primitive : aPad->GetPrimitives() )
1143 {
1144 if( primitive->IsAnnotationProxy() )
1145 {
1146 position = aPad->GetPosition() + primitive->GetCenter();
1147 padsize.x = abs( primitive->GetBotRight().x - primitive->GetTopLeft().x );
1148 padsize.y = abs( primitive->GetBotRight().y - primitive->GetTopLeft().y );
1149
1150 // We normally draw a bit outside the pad, but this will be somewhat
1151 // unexpected when the user has drawn a box.
1152 padsize *= 0.9;
1153
1154 break;
1155 }
1156 }
1157 }
1158
1159 if( aPad->GetShape() != PAD_SHAPE::CUSTOM )
1160 {
1161 // Don't allow a 45° rotation to bloat a pad's bounding box unnecessarily
1162 double limit = std::min( aPad->GetSize().x, aPad->GetSize().y ) * 1.1;
1163
1164 if( padsize.x > limit && padsize.y > limit )
1165 {
1166 padsize.x = limit;
1167 padsize.y = limit;
1168 }
1169 }
1170
1171 double maxSize = PCB_RENDER_SETTINGS::MAX_FONT_SIZE;
1172 double size = padsize.y;
1173
1174 m_gal->Save();
1175 m_gal->Translate( position );
1176
1177 // Keep the size ratio for the font, but make it smaller
1178 if( padsize.x < ( padsize.y * 0.95 ) )
1179 {
1181 size = padsize.x;
1182 std::swap( padsize.x, padsize.y );
1183 }
1184
1185 // Font size limits
1186 if( size > maxSize )
1187 size = maxSize;
1188
1189 // Default font settings
1193 m_gal->SetFontBold( false );
1194 m_gal->SetFontItalic( false );
1195 m_gal->SetFontUnderlined( false );
1196 m_gal->SetTextMirrored( false );
1197 m_gal->SetStrokeColor( m_pcbSettings.GetColor( aPad, aLayer ) );
1198 m_gal->SetIsStroke( true );
1199 m_gal->SetIsFill( false );
1200
1201 // We have already translated the GAL to be centered at the center of the pad's
1202 // bounding box
1203 VECTOR2I textpos( 0, 0 );
1204
1205 // Divide the space, to display both pad numbers and netnames and set the Y text
1206 // offset position to display 2 lines
1207 int Y_offset_numpad = 0;
1208 int Y_offset_netname = 0;
1209
1210 if( !netname.IsEmpty() && !padNumber.IsEmpty() )
1211 {
1212 // The magic numbers are defined experimentally for a better look.
1213 size = size / 2.5;
1214 Y_offset_netname = size / 1.4; // netname size is usually smaller than num pad
1215 // so the offset can be smaller
1216 Y_offset_numpad = size / 1.7;
1217 }
1218
1219 // We are using different fonts to display names, depending on the graphic
1220 // engine (OpenGL or Cairo).
1221 // Xscale_for_stroked_font adjust the text X size for cairo (stroke fonts) engine
1222 const double Xscale_for_stroked_font = 0.9;
1223
1224 if( !netname.IsEmpty() )
1225 {
1226 // approximate the size of net name text:
1227 // We use a size for at least 5 chars, to give a good look even for short names
1228 // (like VCC, GND...)
1229 double tsize = 1.5 * padsize.x / std::max( PrintableCharCount( netname )+1, 5 );
1230 tsize = std::min( tsize, size );
1231
1232 // Use a smaller text size to handle interline, pen size...
1233 tsize *= 0.85;
1234
1235 // Round and oval pads have less room to display the net name than other
1236 // (i.e RECT) shapes, so reduce the text size for these shapes
1237 if( aPad->GetShape() == PAD_SHAPE::CIRCLE || aPad->GetShape() == PAD_SHAPE::OVAL )
1238 tsize *= 0.9;
1239
1240 VECTOR2D namesize( tsize*Xscale_for_stroked_font, tsize );
1241 textpos.y = std::min( tsize * 1.4, double( Y_offset_netname ) );
1242
1243 m_gal->SetGlyphSize( namesize );
1244 m_gal->SetLineWidth( namesize.x / 6.0 );
1245 m_gal->SetFontBold( true );
1246 m_gal->BitmapText( netname, textpos, ANGLE_HORIZONTAL );
1247 }
1248
1249 if( !padNumber.IsEmpty() )
1250 {
1251 // approximate the size of the pad number text:
1252 // We use a size for at least 3 chars, to give a good look even for short numbers
1253 double tsize = 1.5 * padsize.x / std::max( PrintableCharCount( padNumber ), 3 );
1254 tsize = std::min( tsize, size );
1255
1256 // Use a smaller text size to handle interline, pen size...
1257 tsize *= 0.85;
1258 tsize = std::min( tsize, size );
1259 VECTOR2D numsize( tsize*Xscale_for_stroked_font, tsize );
1260 textpos.y = -Y_offset_numpad;
1261
1262 m_gal->SetGlyphSize( numsize );
1263 m_gal->SetLineWidth( numsize.x / 6.0 );
1264 m_gal->SetFontBold( true );
1265 m_gal->BitmapText( padNumber, textpos, ANGLE_HORIZONTAL );
1266 }
1267
1268 m_gal->Restore();
1269
1270 return;
1271 }
1272 else if( aLayer == LAYER_PAD_HOLEWALLS )
1273 {
1274 m_gal->SetIsFill( false );
1275 m_gal->SetIsStroke( true );
1278
1279 std::shared_ptr<SHAPE_SEGMENT> slot = aPad->GetEffectiveHoleShape();
1280 int holeSize = slot->GetWidth() + m_holePlatingThickness;
1281
1282 if( slot->GetSeg().A == slot->GetSeg().B ) // Circular hole
1283 m_gal->DrawCircle( slot->GetSeg().A, KiROUND( holeSize / 2.0 ) );
1284 else
1285 m_gal->DrawSegment( slot->GetSeg().A, slot->GetSeg().B, holeSize );
1286
1287 return;
1288 }
1289
1290 bool outline_mode = !viewer_settings()->m_ViewersDisplay.m_DisplayPadFill;
1291
1293 outline_mode = true;
1294
1295 if( outline_mode )
1296 {
1297 // Outline mode
1298 m_gal->SetIsFill( false );
1299 m_gal->SetIsStroke( true );
1302 }
1303 else
1304 {
1305 // Filled mode
1306 m_gal->SetIsFill( true );
1307 m_gal->SetIsStroke( false );
1309 }
1310
1311 bool drawShape = false;
1312
1313 if( aLayer == LAYER_PAD_PLATEDHOLES || aLayer == LAYER_NON_PLATEDHOLES )
1314 {
1315 SHAPE_SEGMENT slot = getPadHoleShape( aPad );
1316
1317 if( slot.GetSeg().A == slot.GetSeg().B ) // Circular hole
1318 m_gal->DrawCircle( slot.GetSeg().A, slot.GetWidth() / 2.0 );
1319 else
1320 m_gal->DrawSegment( slot.GetSeg().A, slot.GetSeg().B, slot.GetWidth() );
1321 }
1322 else if( m_pcbSettings.IsPrinting() )
1323 {
1324 drawShape = aPad->FlashLayer( m_pcbSettings.GetPrintLayers() );
1325 }
1326 else if( aPad->FlashLayer( board->GetVisibleLayers() & board->GetEnabledLayers() ) )
1327 {
1328 drawShape = true;
1329 }
1330 else if( aPad->IsSelected() )
1331 {
1332 drawShape = true;
1333 outline_mode = true;
1334 }
1335
1336 if( outline_mode )
1337 {
1338 // Outline mode
1339 m_gal->SetIsFill( false );
1340 m_gal->SetIsStroke( true );
1343 }
1344
1345 if( drawShape )
1346 {
1347 VECTOR2I pad_size = aPad->GetSize();
1348 VECTOR2I margin;
1349
1350 switch( aLayer )
1351 {
1352 case F_Mask:
1353 case B_Mask:
1354 margin.x = margin.y = aPad->GetSolderMaskExpansion();
1355 break;
1356
1357 case F_Paste:
1358 case B_Paste:
1359 margin = aPad->GetSolderPasteMargin();
1360 break;
1361
1362 default:
1363 margin.x = margin.y = 0;
1364 break;
1365 }
1366
1367 std::unique_ptr<PAD> dummyPad;
1368 std::shared_ptr<SHAPE_COMPOUND> shapes;
1369
1370 // Drawing components of compound shapes in outline mode produces a mess.
1371 bool simpleShapes = !outline_mode;
1372
1373 if( simpleShapes )
1374 {
1375 if( ( margin.x != margin.y && aPad->GetShape() != PAD_SHAPE::CUSTOM )
1376 || ( aPad->GetShape() == PAD_SHAPE::ROUNDRECT && ( margin.x < 0 || margin.y < 0 ) ) )
1377 {
1378 // Our algorithms below (polygon inflation in particular) can't handle differential
1379 // inflation along separate axes. So for those cases we build a dummy pad instead,
1380 // and inflate it.
1381
1382 // Margin is added to both sides. If the total margin is larger than the pad
1383 // then don't display this layer
1384 if( pad_size.x + 2 * margin.x <= 0 || pad_size.y + 2 * margin.y <= 0 )
1385 return;
1386
1387 dummyPad.reset( static_cast<PAD*>( aPad->Duplicate() ) );
1388
1389 if( dummyPad->GetParentGroup() )
1390 dummyPad->GetParentGroup()->RemoveItem( dummyPad.get() );
1391
1392 int initial_radius = dummyPad->GetRoundRectCornerRadius();
1393
1394 dummyPad->SetSize( pad_size + margin + margin );
1395
1396 if( dummyPad->GetShape() == PAD_SHAPE::ROUNDRECT )
1397 {
1398 // To keep the right margin around the corners, we need to modify the corner radius.
1399 // We must have only one radius correction, so use the smallest absolute margin.
1400 int radius_margin = std::max( margin.x, margin.y ); // radius_margin is < 0
1401 dummyPad->SetRoundRectCornerRadius( std::max( initial_radius + radius_margin, 0 ) );
1402 }
1403
1404 shapes = std::dynamic_pointer_cast<SHAPE_COMPOUND>( dummyPad->GetEffectiveShape() );
1405 margin.x = margin.y = 0;
1406 }
1407 else
1408 {
1409 shapes = std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
1410 }
1411
1412 if( aPad->GetShape() == PAD_SHAPE::CUSTOM && ( margin.x || margin.y ) )
1413 {
1414 // We can't draw as shapes because we don't know which edges are internal and which
1415 // are external (so we don't know when to apply the margin and when not to).
1416 simpleShapes = false;
1417 }
1418
1419 for( const SHAPE* shape : shapes->Shapes() )
1420 {
1421 if( !simpleShapes )
1422 break;
1423
1424 switch( shape->Type() )
1425 {
1426 case SH_SEGMENT:
1427 case SH_CIRCLE:
1428 case SH_RECT:
1429 case SH_SIMPLE:
1430 // OK so far
1431 break;
1432
1433 default:
1434 // Not OK
1435 simpleShapes = false;
1436 break;
1437 }
1438 }
1439 }
1440
1441 if( simpleShapes )
1442 {
1443 for( const SHAPE* shape : shapes->Shapes() )
1444 {
1445 switch( shape->Type() )
1446 {
1447 case SH_SEGMENT:
1448 {
1449 const SHAPE_SEGMENT* seg = (const SHAPE_SEGMENT*) shape;
1450 int effectiveWidth = seg->GetWidth() + 2 * margin.x;
1451
1452 if( effectiveWidth > 0 )
1453 m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, effectiveWidth );
1454
1455 break;
1456 }
1457
1458 case SH_CIRCLE:
1459 {
1460 const SHAPE_CIRCLE* circle = (const SHAPE_CIRCLE*) shape;
1461 int effectiveRadius = circle->GetRadius() + margin.x;
1462
1463 if( effectiveRadius > 0 )
1464 m_gal->DrawCircle( circle->GetCenter(), effectiveRadius );
1465
1466 break;
1467 }
1468
1469 case SH_RECT:
1470 {
1471 const SHAPE_RECT* r = (const SHAPE_RECT*) shape;
1472 VECTOR2I pos = r->GetPosition();
1473 VECTOR2I effectiveMargin = margin;
1474
1475 if( effectiveMargin.x < 0 )
1476 {
1477 // A negative margin just produces a smaller rect.
1478 VECTOR2I effectiveSize = r->GetSize() + effectiveMargin;
1479
1480 if( effectiveSize.x > 0 && effectiveSize.y > 0 )
1481 m_gal->DrawRectangle( pos - effectiveMargin, pos + effectiveSize );
1482 }
1483 else if( effectiveMargin.x > 0 )
1484 {
1485 // A positive margin produces a larger rect, but with rounded corners
1486 m_gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() );
1487
1488 // Use segments to produce the margin with rounded corners
1489 m_gal->DrawSegment( pos,
1490 pos + VECTOR2I( r->GetWidth(), 0 ),
1491 effectiveMargin.x * 2 );
1492 m_gal->DrawSegment( pos + VECTOR2I( r->GetWidth(), 0 ),
1493 pos + r->GetSize(),
1494 effectiveMargin.x * 2 );
1495 m_gal->DrawSegment( pos + r->GetSize(),
1496 pos + VECTOR2I( 0, r->GetHeight() ),
1497 effectiveMargin.x * 2 );
1498 m_gal->DrawSegment( pos + VECTOR2I( 0, r->GetHeight() ),
1499 pos,
1500 effectiveMargin.x * 2 );
1501 }
1502 else
1503 {
1504 m_gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() );
1505 }
1506
1507 break;
1508 }
1509
1510 case SH_SIMPLE:
1511 {
1512 const SHAPE_SIMPLE* poly = static_cast<const SHAPE_SIMPLE*>( shape );
1513
1514 if( poly->PointCount() < 2 ) // Careful of empty pads
1515 break;
1516
1517 if( margin.x < 0 ) // The poly shape must be deflated
1518 {
1519 int numSegs = GetArcToSegmentCount( -margin.x, m_maxError, FULL_CIRCLE );
1520 SHAPE_POLY_SET outline;
1521 outline.NewOutline();
1522
1523 for( int ii = 0; ii < poly->PointCount(); ++ii )
1524 outline.Append( poly->CPoint( ii ) );
1525
1526 outline.Deflate( -margin.x, numSegs );
1527
1528 m_gal->DrawPolygon( outline );
1529 }
1530 else
1531 {
1532 m_gal->DrawPolygon( poly->Vertices() );
1533 }
1534
1535 // Now add on a rounded margin (using segments) if the margin > 0
1536 if( margin.x > 0 )
1537 {
1538 for( size_t ii = 0; ii < poly->GetSegmentCount(); ++ii )
1539 {
1540 SEG seg = poly->GetSegment( ii );
1541 m_gal->DrawSegment( seg.A, seg.B, margin.x * 2 );
1542 }
1543 }
1544
1545 break;
1546 }
1547
1548 default:
1549 // Better not get here; we already pre-flighted the shapes...
1550 break;
1551 }
1552 }
1553 }
1554 else
1555 {
1556 // This is expensive. Avoid if possible.
1557 SHAPE_POLY_SET polySet;
1558 aPad->TransformShapeToPolygon( polySet, ToLAYER_ID( aLayer ), margin.x, m_maxError,
1559 ERROR_INSIDE );
1560 m_gal->DrawPolygon( polySet );
1561 }
1562 }
1563
1564 if( pcbconfig() && pcbconfig()->m_Display.m_PadClearance
1565 && ( aLayer == LAYER_PAD_FR || aLayer == LAYER_PAD_BK || aLayer == LAYER_PADS_TH )
1567 {
1568 /* Showing the clearance area is not obvious.
1569 * - A pad can be removed from some copper layers.
1570 * - For non copper layers, what is the clearance area?
1571 * So for copper layers, the clearance area is the shape if the pad is flashed on this
1572 * layer and the hole clearance area for other copper layers.
1573 * For other layers, use the pad shape, although one can use an other criteria,
1574 * depending on the non copper layer.
1575 */
1576 int activeLayer = m_pcbSettings.GetActiveLayer();
1577 bool flashActiveLayer = true;
1578
1579 if( IsCopperLayer( activeLayer ) )
1580 flashActiveLayer = aPad->FlashLayer( activeLayer );
1581
1582 if( !board->GetVisibleLayers().test( activeLayer ) )
1583 flashActiveLayer = false;
1584
1585 if( flashActiveLayer || aPad->GetDrillSize().x )
1586 {
1587 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
1589
1591 m_gal->SetIsStroke( true );
1592 m_gal->SetIsFill( false );
1594
1595 int clearance = aPad->GetOwnClearance( m_pcbSettings.GetActiveLayer() );
1596
1597 if( flashActiveLayer && clearance > 0 )
1598 {
1599 auto shape = std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
1600
1601 if( shape && shape->Size() == 1 && shape->Shapes()[0]->Type() == SH_SEGMENT )
1602 {
1603 const SHAPE_SEGMENT* seg = (SHAPE_SEGMENT*) shape->Shapes()[0];
1604 m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B,
1605 seg->GetWidth() + 2 * clearance );
1606 }
1607 else if( shape && shape->Size() == 1 && shape->Shapes()[0]->Type() == SH_CIRCLE )
1608 {
1609 const SHAPE_CIRCLE* circle = (SHAPE_CIRCLE*) shape->Shapes()[0];
1610 m_gal->DrawCircle( circle->GetCenter(), circle->GetRadius() + clearance );
1611 }
1612 else
1613 {
1614 SHAPE_POLY_SET polySet;
1615
1616 // Use ERROR_INSIDE because it avoids Clipper and is therefore much faster.
1617 aPad->TransformShapeToPolygon( polySet, ToLAYER_ID( aLayer ), clearance,
1619
1620 if( polySet.Outline( 0 ).PointCount() > 2 ) // Careful of empty pads
1621 m_gal->DrawPolygon( polySet );
1622 }
1623 }
1624 else if( aPad->GetEffectiveHoleShape() && clearance > 0 )
1625 {
1626 clearance += m_holePlatingThickness;
1627
1628 std::shared_ptr<SHAPE_SEGMENT> slot = aPad->GetEffectiveHoleShape();
1629 m_gal->DrawSegment( slot->GetSeg().A, slot->GetSeg().B,
1630 slot->GetWidth() + 2 * clearance );
1631 }
1632 }
1633 }
1634}
1635
1636
1637void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
1638{
1639 COLOR4D color = m_pcbSettings.GetColor( aShape, aShape->GetLayer() );
1641 int thickness = getLineThickness( aShape->GetWidth() );
1642 PLOT_DASH_TYPE lineStyle = aShape->GetStroke().GetPlotStyle();
1643
1644 if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
1645 {
1646 color = m_pcbSettings.GetColor( aShape, aLayer );
1647 thickness = thickness + m_lockedShadowMargin;
1648 }
1649
1650 if( outline_mode )
1651 {
1652 m_gal->SetIsFill( false );
1653 m_gal->SetIsStroke( true );
1655 }
1656
1659
1660 if( lineStyle <= PLOT_DASH_TYPE::FIRST_TYPE )
1661 {
1662 switch( aShape->GetShape() )
1663 {
1664 case SHAPE_T::SEGMENT:
1665 if( outline_mode )
1666 {
1667 m_gal->DrawSegment( aShape->GetStart(), aShape->GetEnd(), thickness );
1668 }
1669 else
1670 {
1671 m_gal->SetIsFill( true );
1672 m_gal->SetIsStroke( false );
1673
1674 m_gal->DrawSegment( aShape->GetStart(), aShape->GetEnd(), thickness );
1675 }
1676
1677 break;
1678
1679 case SHAPE_T::RECT:
1680 {
1681 std::vector<VECTOR2I> pts = aShape->GetRectCorners();
1682
1683 if( aShape->IsAnnotationProxy() )
1684 {
1685 m_gal->DrawSegment( pts[0], pts[1], thickness );
1686 m_gal->DrawSegment( pts[1], pts[2], thickness );
1687 m_gal->DrawSegment( pts[2], pts[3], thickness );
1688 m_gal->DrawSegment( pts[3], pts[0], thickness );
1689 m_gal->DrawSegment( pts[0], pts[2], thickness );
1690 m_gal->DrawSegment( pts[1], pts[3], thickness );
1691 }
1692 else if( outline_mode )
1693 {
1694 m_gal->DrawSegment( pts[0], pts[1], thickness );
1695 m_gal->DrawSegment( pts[1], pts[2], thickness );
1696 m_gal->DrawSegment( pts[2], pts[3], thickness );
1697 m_gal->DrawSegment( pts[3], pts[0], thickness );
1698 }
1699 else
1700 {
1701 m_gal->SetIsFill( true );
1702 m_gal->SetIsStroke( false );
1703
1704 if( thickness > 0 )
1705 {
1706 m_gal->DrawSegment( pts[0], pts[1], thickness );
1707 m_gal->DrawSegment( pts[1], pts[2], thickness );
1708 m_gal->DrawSegment( pts[2], pts[3], thickness );
1709 m_gal->DrawSegment( pts[3], pts[0], thickness );
1710 }
1711
1712 if( aShape->IsFilled() )
1713 {
1714 SHAPE_POLY_SET poly;
1715 poly.NewOutline();
1716
1717 for( const VECTOR2I& pt : pts )
1718 poly.Append( pt );
1719
1720 m_gal->DrawPolygon( poly );
1721 }
1722 }
1723
1724 break;
1725 }
1726
1727 case SHAPE_T::ARC:
1728 {
1729 EDA_ANGLE startAngle;
1730 EDA_ANGLE endAngle;
1731 aShape->CalcArcAngles( startAngle, endAngle );
1732
1733 if( outline_mode )
1734 {
1735 m_gal->DrawArcSegment( aShape->GetCenter(), aShape->GetRadius(), startAngle,
1736 endAngle, thickness, m_maxError );
1737 }
1738 else
1739 {
1740 m_gal->SetIsFill( true );
1741 m_gal->SetIsStroke( false );
1742
1743 m_gal->DrawArcSegment( aShape->GetCenter(), aShape->GetRadius(), startAngle,
1744 endAngle, thickness, m_maxError );
1745 }
1746 break;
1747 }
1748
1749 case SHAPE_T::CIRCLE:
1750 if( outline_mode )
1751 {
1752 m_gal->DrawCircle( aShape->GetStart(), aShape->GetRadius() - thickness / 2 );
1753 m_gal->DrawCircle( aShape->GetStart(), aShape->GetRadius() + thickness / 2 );
1754 }
1755 else
1756 {
1757 m_gal->SetIsFill( aShape->IsFilled() );
1758 m_gal->SetIsStroke( thickness > 0 );
1759 m_gal->SetLineWidth( thickness );
1760
1761 m_gal->DrawCircle( aShape->GetStart(), aShape->GetRadius() );
1762 }
1763 break;
1764
1765 case SHAPE_T::POLY:
1766 {
1767 SHAPE_POLY_SET& shape = const_cast<PCB_SHAPE*>( aShape )->GetPolyShape();
1768 const FOOTPRINT* parentFootprint = aShape->GetParentFootprint();
1769
1770 if( shape.OutlineCount() == 0 )
1771 break;
1772
1773 if( parentFootprint )
1774 {
1775 m_gal->Save();
1776 m_gal->Translate( parentFootprint->GetPosition() );
1777 m_gal->Rotate( -parentFootprint->GetOrientation().AsRadians() );
1778 }
1779
1780 if( outline_mode )
1781 {
1782 for( int ii = 0; ii < shape.OutlineCount(); ++ii )
1783 m_gal->DrawSegmentChain( shape.Outline( ii ), thickness );
1784 }
1785 else
1786 {
1787 m_gal->SetIsFill( true );
1788 m_gal->SetIsStroke( false );
1789
1790 if( thickness > 0 )
1791 {
1792 for( int ii = 0; ii < shape.OutlineCount(); ++ii )
1793 m_gal->DrawSegmentChain( shape.Outline( ii ), thickness );
1794 }
1795
1796 if( aShape->IsFilled() )
1797 {
1798 // On Opengl, a not convex filled polygon is usually drawn by using triangles
1799 // as primitives. CacheTriangulation() can create basic triangle primitives to
1800 // draw the polygon solid shape on Opengl. GLU tessellation is much slower,
1801 // so currently we are using our tessellation.
1802 if( m_gal->IsOpenGlEngine() && !shape.IsTriangulationUpToDate() )
1803 shape.CacheTriangulation( true, true );
1804
1805 m_gal->DrawPolygon( shape );
1806 }
1807 }
1808
1809 if( parentFootprint )
1810 m_gal->Restore();
1811
1812 break;
1813 }
1814
1815 case SHAPE_T::BEZIER:
1816 if( outline_mode )
1817 {
1818 std::vector<VECTOR2D> output;
1819 std::vector<VECTOR2D> pointCtrl;
1820
1821 pointCtrl.push_back( aShape->GetStart() );
1822 pointCtrl.push_back( aShape->GetBezierC1() );
1823 pointCtrl.push_back( aShape->GetBezierC2() );
1824 pointCtrl.push_back( aShape->GetEnd() );
1825
1826 BEZIER_POLY converter( pointCtrl );
1827 converter.GetPoly( output, thickness );
1828
1829 m_gal->DrawSegmentChain( output, thickness );
1830 }
1831 else
1832 {
1833 m_gal->SetIsFill( aShape->IsFilled() );
1834 m_gal->SetIsStroke( thickness > 0 );
1835 m_gal->SetLineWidth( thickness );
1836
1837 // Use thickness as filter value to convert the curve to polyline when the curve
1838 // is not supported
1839 m_gal->DrawCurve( VECTOR2D( aShape->GetStart() ),
1840 VECTOR2D( aShape->GetBezierC1() ),
1841 VECTOR2D( aShape->GetBezierC2() ),
1842 VECTOR2D( aShape->GetEnd() ), thickness );
1843 }
1844
1845 break;
1846
1847 case SHAPE_T::LAST:
1848 break;
1849 }
1850 }
1851 else
1852 {
1853 if( !outline_mode )
1854 {
1855 m_gal->SetIsFill( true );
1856 m_gal->SetIsStroke( false );
1857 }
1858
1859 std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapes( true );
1860
1861 for( SHAPE* shape : shapes )
1862 {
1863 STROKE_PARAMS::Stroke( shape, lineStyle, thickness, &m_pcbSettings,
1864 [&]( const VECTOR2I& a, const VECTOR2I& b )
1865 {
1866 m_gal->DrawSegment( a, b, thickness );
1867 } );
1868 }
1869
1870 for( SHAPE* shape : shapes )
1871 delete shape;
1872 }
1873}
1874
1875
1876void PCB_PAINTER::strokeText( const wxString& aText, const VECTOR2I& aPosition,
1877 const TEXT_ATTRIBUTES& aAttrs )
1878{
1879 KIFONT::FONT* font = aAttrs.m_Font;
1880
1881 if( !font )
1882 font = KIFONT::FONT::GetFont( wxEmptyString, aAttrs.m_Bold, aAttrs.m_Italic );
1883
1884 m_gal->SetIsFill( font->IsOutline() );
1885 m_gal->SetIsStroke( font->IsStroke() );
1886
1887 font->Draw( m_gal, aText, aPosition, aAttrs );
1888}
1889
1890
1891void PCB_PAINTER::draw( const PCB_BITMAP* aBitmap, int aLayer )
1892{
1893 m_gal->Save();
1894 m_gal->Translate( aBitmap->GetPosition() );
1895
1896 // When the image scale factor is not 1.0, we need to modify the actual as the image scale
1897 // factor is similar to a local zoom
1898 double img_scale = aBitmap->GetImageScale();
1899
1900 if( img_scale != 1.0 )
1901 m_gal->Scale( VECTOR2D( img_scale, img_scale ) );
1902
1903 if( aBitmap->IsSelected() || aBitmap->IsBrightened() )
1904 {
1906 m_gal->SetIsStroke( true );
1909 m_gal->SetIsFill( false );
1910
1911 // Draws a bounding box.
1912 VECTOR2D bm_size( aBitmap->GetSize() );
1913 // bm_size is the actual image size in UI.
1914 // but m_gal scale was previously set to img_scale
1915 // so recalculate size relative to this image size.
1916 bm_size.x /= img_scale;
1917 bm_size.y /= img_scale;
1918 VECTOR2D origin( -bm_size.x / 2.0, -bm_size.y / 2.0 );
1919 VECTOR2D end = origin + bm_size;
1920
1921 m_gal->DrawRectangle( origin, end );
1922
1923 // Hard code bitmaps as opaque when selected. Otherwise cached layers
1924 // will not be rendered under the selected bitmap because cached layers
1925 // are rendered after non-cached layers (e.g. bitmaps), which will have
1926 // a closer Z order.
1927 m_gal->DrawBitmap( *aBitmap->GetImage(), 1.0 );
1928 }
1929 else
1930 m_gal->DrawBitmap( *aBitmap->GetImage(),
1931 m_pcbSettings.GetColor( aBitmap, aBitmap->GetLayer() ).a );
1932
1933
1934 m_gal->Restore();
1935}
1936
1937
1938void PCB_PAINTER::draw( const PCB_TEXT* aText, int aLayer )
1939{
1940 wxString resolvedText( aText->GetShownText() );
1941
1942 if( resolvedText.Length() == 0 )
1943 return;
1944
1945 if( aLayer == LAYER_LOCKED_ITEM_SHADOW ) // happens only if locked
1946 {
1947 const COLOR4D color = m_pcbSettings.GetColor( aText, aLayer );
1948
1949 m_gal->SetIsFill( true );
1950 m_gal->SetIsStroke( true );
1953
1954 SHAPE_POLY_SET poly;
1955 aText->TransformShapeToPolygon( poly, aText->GetLayer(), 0, m_maxError, ERROR_OUTSIDE );
1956 m_gal->DrawPolygon( poly );
1957
1958 return;
1959 }
1960
1961 TEXT_ATTRIBUTES attrs = aText->GetAttributes();
1962 const COLOR4D& color = m_pcbSettings.GetColor( aText, aText->GetLayer() );
1963 bool outline_mode = !viewer_settings()->m_ViewersDisplay.m_DisplayTextFill;
1964
1965 KIFONT::FONT* font = aText->GetFont();
1966
1967 if( !font )
1968 {
1970 aText->IsItalic() );
1971 }
1972
1975
1976 if( aText->IsKnockout() )
1977 {
1978 KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
1979 SHAPE_POLY_SET knockouts;
1980
1981 CALLBACK_GAL callback_gal( empty_opts,
1982 // Polygon callback
1983 [&]( const SHAPE_LINE_CHAIN& aPoly )
1984 {
1985 knockouts.AddOutline( aPoly );
1986 } );
1987
1989
1990 callback_gal.SetIsFill( font->IsOutline() );
1991 callback_gal.SetIsStroke( font->IsStroke() );
1992 callback_gal.SetLineWidth( attrs.m_StrokeWidth );
1993 font->Draw( &callback_gal, resolvedText, aText->GetDrawPos(), attrs );
1994
1995 SHAPE_POLY_SET finalPoly;
1996 int margin = attrs.m_StrokeWidth * 1.5
1997 + GetKnockoutTextMargin( attrs.m_Size, attrs.m_StrokeWidth );
1998
1999 aText->TransformBoundingBoxToPolygon( &finalPoly, margin );
2000 finalPoly.BooleanSubtract( knockouts, SHAPE_POLY_SET::PM_FAST );
2001 finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
2002
2003 m_gal->SetIsStroke( false );
2004 m_gal->SetIsFill( true );
2005 m_gal->DrawPolygon( finalPoly );
2006 }
2007 else
2008 {
2009 if( outline_mode )
2011 else
2013
2014 if( m_gal->IsFlippedX() && !( aText->GetLayerSet() & LSET::SideSpecificMask() ).any() )
2015 {
2016 attrs.m_Mirrored = !attrs.m_Mirrored;
2017 attrs.m_Halign = static_cast<GR_TEXT_H_ALIGN_T>( -attrs.m_Halign );
2018 }
2019
2020 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
2021
2022 if( font->IsOutline() )
2023 cache = aText->GetRenderCache( font, resolvedText );
2024
2025 if( cache )
2026 m_gal->DrawGlyphs( *cache );
2027 else
2028 strokeText( resolvedText, aText->GetTextPos(), attrs );
2029 }
2030}
2031
2032
2033void PCB_PAINTER::draw( const PCB_TEXTBOX* aTextBox, int aLayer )
2034{
2035 const COLOR4D& color = m_pcbSettings.GetColor( aTextBox, aLayer );
2036 int thickness = getLineThickness( aTextBox->GetWidth() );
2037 PLOT_DASH_TYPE lineStyle = aTextBox->GetStroke().GetPlotStyle();
2038 wxString resolvedText( aTextBox->GetShownText() );
2039
2040 KIFONT::FONT* font = aTextBox->GetFont();
2041
2042 if( !font )
2043 {
2045 aTextBox->IsItalic() );
2046 }
2047
2048 if( aLayer == LAYER_LOCKED_ITEM_SHADOW ) // happens only if locked
2049 {
2050 const COLOR4D sh_color = m_pcbSettings.GetColor( aTextBox, aLayer );
2051
2052 m_gal->SetIsFill( true );
2053 m_gal->SetIsStroke( false );
2054 m_gal->SetFillColor( sh_color );
2055 m_gal->SetStrokeColor( sh_color );
2056
2057 // Draw the box with a larger thickness than box thickness to show
2058 // the shadow mask
2059 std::vector<VECTOR2I> pts = aTextBox->GetCorners();
2060 int line_thickness = std::max( thickness*3, pcbIUScale.mmToIU( 0.2 ) );
2061
2062 for( size_t ii = 0; ii < pts.size(); ++ii )
2063 m_gal->DrawSegment( pts[ ii ], pts[ (ii + 1) % pts.size() ], line_thickness );
2064 }
2065
2068 m_gal->SetIsFill( true );
2069 m_gal->SetIsStroke( false );
2070
2071 if( lineStyle <= PLOT_DASH_TYPE::FIRST_TYPE )
2072 {
2073 if( thickness > 0 )
2074 {
2075 std::vector<VECTOR2I> pts = aTextBox->GetCorners();
2076
2077 for( size_t ii = 0; ii < pts.size(); ++ii )
2078 m_gal->DrawSegment( pts[ ii ], pts[ (ii + 1) % pts.size() ], thickness );
2079 }
2080 }
2081 else
2082 {
2083 std::vector<SHAPE*> shapes = aTextBox->MakeEffectiveShapes( true );
2084
2085 for( SHAPE* shape : shapes )
2086 {
2087 STROKE_PARAMS::Stroke( shape, lineStyle, thickness, &m_pcbSettings,
2088 [&]( const VECTOR2I& a, const VECTOR2I& b )
2089 {
2090 m_gal->DrawSegment( a, b, thickness );
2091 } );
2092 }
2093
2094 for( SHAPE* shape : shapes )
2095 delete shape;
2096 }
2097
2098 if( resolvedText.Length() == 0 )
2099 return;
2100
2101 TEXT_ATTRIBUTES attrs = aTextBox->GetAttributes();
2103
2104 if( m_gal->IsFlippedX() && !( aTextBox->GetLayerSet() & LSET::SideSpecificMask() ).any() )
2105 {
2106 attrs.m_Mirrored = !attrs.m_Mirrored;
2107 attrs.m_Halign = static_cast<GR_TEXT_H_ALIGN_T>( -attrs.m_Halign );
2108 }
2109
2110 if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
2111 {
2112 const COLOR4D sh_color = m_pcbSettings.GetColor( aTextBox, aLayer );
2113 m_gal->SetFillColor( sh_color );
2114 m_gal->SetStrokeColor( sh_color );
2116 }
2117
2118 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
2119
2120 if( font->IsOutline() )
2121 cache = aTextBox->GetRenderCache( font, resolvedText );
2122
2123 if( cache )
2124 m_gal->DrawGlyphs( *cache );
2125 else
2126 strokeText( resolvedText, aTextBox->GetDrawPos(), attrs );
2127}
2128
2129
2130void PCB_PAINTER::draw( const FP_TEXT* aText, int aLayer )
2131{
2132 wxString resolvedText( aText->GetShownText() );
2133
2134 if( resolvedText.Length() == 0 )
2135 return;
2136
2137 const COLOR4D& color = m_pcbSettings.GetColor( aText, aLayer );
2138 bool outline_mode = !viewer_settings()->m_ViewersDisplay.m_DisplayTextFill;
2139 TEXT_ATTRIBUTES attrs = aText->GetAttributes();
2140
2141 KIFONT::FONT* font = aText->GetFont();
2142
2143 if( !font )
2144 {
2146 aText->IsItalic() );
2147 }
2148
2151 attrs.m_Angle = aText->GetDrawRotation();
2152
2153 if( aText->IsKnockout() )
2154 {
2155 KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
2156 SHAPE_POLY_SET knockouts;
2157
2158 CALLBACK_GAL callback_gal( empty_opts,
2159 // Polygon callback
2160 [&]( const SHAPE_LINE_CHAIN& aPoly )
2161 {
2162 knockouts.AddOutline( aPoly );
2163 } );
2164
2166
2167 callback_gal.SetIsFill( font->IsOutline() );
2168 callback_gal.SetIsStroke( font->IsStroke() );
2169 callback_gal.SetLineWidth( attrs.m_StrokeWidth );
2170 font->Draw( &callback_gal, resolvedText, aText->GetDrawPos(), attrs );
2171
2172 SHAPE_POLY_SET finalPoly;
2173 int margin = attrs.m_StrokeWidth * 1.5
2174 + GetKnockoutTextMargin( attrs.m_Size, attrs.m_StrokeWidth );
2175
2176 aText->TransformBoundingBoxToPolygon( &finalPoly, margin );
2177 finalPoly.BooleanSubtract( knockouts, SHAPE_POLY_SET::PM_FAST );
2178 finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
2179
2180 m_gal->SetIsStroke( false );
2181 m_gal->SetIsFill( true );
2182 m_gal->DrawPolygon( finalPoly );
2183 }
2184 else
2185 {
2186 if( outline_mode )
2188 else
2190
2191 if( m_gal->IsFlippedX() && !( aText->GetLayerSet() & LSET::SideSpecificMask() ).any() )
2192 {
2193 attrs.m_Mirrored = !attrs.m_Mirrored;
2194 attrs.m_Halign = static_cast<GR_TEXT_H_ALIGN_T>( -attrs.m_Halign );
2195 }
2196
2197 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
2198
2199 if( font->IsOutline() )
2200 cache = aText->GetRenderCache( font, resolvedText );
2201
2202 if( cache )
2203 m_gal->DrawGlyphs( *cache );
2204 else
2205 strokeText( resolvedText, aText->GetTextPos(), attrs );
2206 }
2207
2208 // Draw the umbilical line
2209 if( aText->IsSelected() )
2210 {
2213 m_gal->DrawLine( aText->GetTextPos(), aText->GetParent()->GetPosition() );
2214 }
2215}
2216
2217
2218void PCB_PAINTER::draw( const FP_TEXTBOX* aTextBox, int aLayer )
2219{
2220 const COLOR4D& color = m_pcbSettings.GetColor( aTextBox, aTextBox->GetLayer() );
2221 int thickness = getLineThickness( aTextBox->GetWidth() );
2222 PLOT_DASH_TYPE lineStyle = aTextBox->GetStroke().GetPlotStyle();
2223
2226 m_gal->SetIsFill( true );
2227 m_gal->SetIsStroke( false );
2228
2229 if( thickness > 0 )
2230 {
2231 if( lineStyle <= PLOT_DASH_TYPE::FIRST_TYPE )
2232 {
2233 std::vector<VECTOR2I> pts = aTextBox->GetCorners();
2234
2235 for( size_t ii = 0; ii < pts.size(); ++ii )
2236 m_gal->DrawSegment( pts[ ii ], pts[ (ii + 1) % pts.size() ], thickness );
2237 }
2238 else
2239 {
2240 std::vector<SHAPE*> shapes = aTextBox->MakeEffectiveShapes( true );
2241
2242 for( SHAPE* shape : shapes )
2243 {
2244 STROKE_PARAMS::Stroke( shape, lineStyle, thickness, &m_pcbSettings,
2245 [&]( const VECTOR2I& a, const VECTOR2I& b )
2246 {
2247 m_gal->DrawSegment( a, b, thickness );
2248 } );
2249 }
2250
2251 for( SHAPE* shape : shapes )
2252 delete shape;
2253 }
2254 }
2255
2256 wxString resolvedText( aTextBox->GetShownText() );
2257
2258 if( resolvedText.Length() == 0 )
2259 return;
2260
2261 TEXT_ATTRIBUTES attrs = aTextBox->GetAttributes();
2262 attrs.m_Angle = aTextBox->GetDrawRotation();
2264
2265 if( m_gal->IsFlippedX() && !( aTextBox->GetLayerSet() & LSET::SideSpecificMask() ).any() )
2266 {
2267 attrs.m_Mirrored = !attrs.m_Mirrored;
2268 attrs.m_Halign = static_cast<GR_TEXT_H_ALIGN_T>( -attrs.m_Halign );
2269 }
2270
2271 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
2272
2273 if( aTextBox->GetFont() && aTextBox->GetFont()->IsOutline() )
2274 cache = aTextBox->GetRenderCache( aTextBox->GetFont(), resolvedText );
2275
2276 if( cache )
2277 m_gal->DrawGlyphs( *cache );
2278 else
2279 strokeText( resolvedText, aTextBox->GetDrawPos(), attrs );
2280}
2281
2282
2283void PCB_PAINTER::draw( const FOOTPRINT* aFootprint, int aLayer )
2284{
2285 if( aLayer == LAYER_ANCHOR )
2286 {
2287 const COLOR4D color = m_pcbSettings.GetColor( aFootprint, aLayer );
2288
2289 // Keep the size and width constant, not related to the scale because the anchor
2290 // is just a marker on screen
2291 double anchorSize = 5.0 / m_gal->GetWorldScale(); // 5 pixels size
2292 double anchorThickness = 1.0 / m_gal->GetWorldScale(); // 1 pixels width
2293
2294 // Draw anchor
2295 m_gal->SetIsFill( false );
2296 m_gal->SetIsStroke( true );
2298 m_gal->SetLineWidth( anchorThickness );
2299
2300 VECTOR2D center = aFootprint->GetPosition();
2301 m_gal->DrawLine( center - VECTOR2D( anchorSize, 0 ), center + VECTOR2D( anchorSize, 0 ) );
2302 m_gal->DrawLine( center - VECTOR2D( 0, anchorSize ), center + VECTOR2D( 0, anchorSize ) );
2303 }
2304
2305 if( aLayer == LAYER_LOCKED_ITEM_SHADOW && m_frameType == FRAME_PCB_EDITOR ) // happens only if locked
2306 {
2307 const COLOR4D color = m_pcbSettings.GetColor( aFootprint, aLayer );
2308
2309 m_gal->SetIsFill( true );
2310 m_gal->SetIsStroke( false );
2312
2313#if 0 // GetBoundingHull() can be very slow, especially for logos imported from graphics
2314 const SHAPE_POLY_SET& poly = aFootprint->GetBoundingHull();
2315 m_gal->DrawPolygon( poly );
2316#else
2317 BOX2I bbox = aFootprint->GetBoundingBox( false, false );
2318 VECTOR2I topLeft = bbox.GetPosition();
2319 VECTOR2I botRight = bbox.GetPosition() + bbox.GetSize();
2320
2321 m_gal->DrawRectangle( topLeft, botRight );
2322
2323 // Use segments to produce a margin with rounded corners
2324 m_gal->DrawSegment( topLeft, VECTOR2I( botRight.x, topLeft.y ), m_lockedShadowMargin );
2325 m_gal->DrawSegment( VECTOR2I( botRight.x, topLeft.y ), botRight, m_lockedShadowMargin );
2326 m_gal->DrawSegment( botRight, VECTOR2I( topLeft.x, botRight.y ), m_lockedShadowMargin );
2327 m_gal->DrawSegment( VECTOR2I( topLeft.x, botRight.y ), topLeft, m_lockedShadowMargin );
2328#endif
2329 }
2330
2331 if( aLayer == LAYER_CONFLICTS_SHADOW )
2332 {
2333 const SHAPE_POLY_SET& frontpoly = aFootprint->GetCourtyard( F_CrtYd );
2334 const SHAPE_POLY_SET& backpoly = aFootprint->GetCourtyard( B_CrtYd );
2335
2336 const COLOR4D color = m_pcbSettings.GetColor( aFootprint, aLayer );
2337
2338 m_gal->SetIsFill( true );
2339 m_gal->SetIsStroke( false );
2341
2342 if( frontpoly.OutlineCount() > 0 )
2343 m_gal->DrawPolygon( frontpoly );
2344
2345 if( backpoly.OutlineCount() > 0 )
2346 m_gal->DrawPolygon( backpoly );
2347 }
2348}
2349
2350
2351void PCB_PAINTER::draw( const PCB_GROUP* aGroup, int aLayer )
2352{
2353 if( aLayer == LAYER_ANCHOR )
2354 {
2355 if( aGroup->IsSelected() && !( aGroup->GetParent() && aGroup->GetParent()->IsSelected() ) )
2356 {
2357 // Selected on our own; draw enclosing box
2358 }
2359 else if( aGroup->IsEntered() )
2360 {
2361 // Entered group; draw enclosing box
2362 }
2363 else
2364 {
2365 // Neither selected nor entered; draw nothing at the group level (ie: only draw
2366 // its members)
2367 return;
2368 }
2369
2370 const COLOR4D color = m_pcbSettings.GetColor( aGroup, LAYER_ANCHOR );
2371
2374
2375 BOX2I bbox = aGroup->GetBoundingBox();
2376 VECTOR2I topLeft = bbox.GetPosition();
2377 VECTOR2I width = VECTOR2I( bbox.GetWidth(), 0 );
2378 VECTOR2I height = VECTOR2I( 0, bbox.GetHeight() );
2379
2380 m_gal->DrawLine( topLeft, topLeft + width );
2381 m_gal->DrawLine( topLeft + width, topLeft + width + height );
2382 m_gal->DrawLine( topLeft + width + height, topLeft + height );
2383 m_gal->DrawLine( topLeft + height, topLeft );
2384
2385 wxString name = aGroup->GetName();
2386
2387 if( name.IsEmpty() )
2388 return;
2389
2390 int ptSize = 12;
2391 int scaledSize = abs( KiROUND( m_gal->GetScreenWorldMatrix().GetScale().x * ptSize ) );
2392 int unscaledSize = pcbIUScale.MilsToIU( ptSize );
2393
2394 // Scale by zoom a bit, but not too much
2395 int textSize = ( scaledSize + ( unscaledSize * 2 ) ) / 3;
2396 VECTOR2I textOffset = VECTOR2I( width.x / 2, -KiROUND( textSize * 0.5 ) );
2397 VECTOR2I titleHeight = VECTOR2I( 0, KiROUND( textSize * 2.0 ) );
2398
2399 if( PrintableCharCount( name ) * textSize < bbox.GetWidth() )
2400 {
2401 m_gal->DrawLine( topLeft, topLeft - titleHeight );
2402 m_gal->DrawLine( topLeft - titleHeight, topLeft + width - titleHeight );
2403 m_gal->DrawLine( topLeft + width - titleHeight, topLeft + width );
2404
2405 TEXT_ATTRIBUTES attrs;
2406 attrs.m_Italic = true;
2409 attrs.m_Size = VECTOR2I( textSize, textSize );
2410 attrs.m_StrokeWidth = GetPenSizeForNormal( textSize );
2411
2412 KIFONT::FONT::GetFont()->Draw( m_gal, aGroup->GetName(), topLeft + textOffset, attrs );
2413 }
2414 }
2415}
2416
2417
2418void PCB_PAINTER::draw( const ZONE* aZone, int aLayer )
2419{
2420 if( aLayer == LAYER_CONFLICTS_SHADOW )
2421 {
2422 COLOR4D color = m_pcbSettings.GetColor( aZone, aLayer );
2423
2424 m_gal->SetIsFill( true );
2425 m_gal->SetIsStroke( false );
2427
2428 m_gal->DrawPolygon( aZone->Outline()->Outline( 0 ) );
2429 return;
2430 }
2431
2432 /*
2433 * aLayer will be the virtual zone layer (LAYER_ZONE_START, ... in GAL_LAYER_ID)
2434 * This is used for draw ordering in the GAL.
2435 * The color for the zone comes from the associated copper layer ( aLayer - LAYER_ZONE_START )
2436 * and the visibility comes from the combination of that copper layer and LAYER_ZONES
2437 */
2438 PCB_LAYER_ID layer;
2439
2440 if( IsZoneFillLayer( aLayer ) )
2441 layer = ToLAYER_ID( aLayer - LAYER_ZONE_START );
2442 else
2443 layer = ToLAYER_ID( aLayer );
2444
2445 if( !aZone->IsOnLayer( layer ) )
2446 return;
2447
2448 COLOR4D color = m_pcbSettings.GetColor( aZone, layer );
2449 std::deque<VECTOR2D> corners;
2451
2452 // Draw the outline
2453 if( !IsZoneFillLayer( aLayer ) )
2454 {
2455 const SHAPE_POLY_SET* outline = aZone->Outline();
2456
2457 if( !m_pcbSettings.m_isPrinting && outline && outline->OutlineCount() > 0 )
2458 {
2459 m_gal->SetStrokeColor( color.a > 0.0 ? color.WithAlpha( 1.0 ) : color );
2460 m_gal->SetIsFill( false );
2461 m_gal->SetIsStroke( true );
2463
2464 // Draw each contour (main contour and holes)
2465
2466 /*
2467 * m_gal->DrawPolygon( *outline );
2468 * should be enough, but currently does not work to draw holes contours in a complex
2469 * polygon so each contour is draw as a simple polygon
2470 */
2471
2472 // Draw the main contour(s?)
2473 for( int ii = 0; ii < outline->OutlineCount(); ++ii )
2474 {
2475 m_gal->DrawPolyline( outline->COutline( ii ) );
2476
2477 // Draw holes
2478 int holes_count = outline->HoleCount( ii );
2479
2480 for( int jj = 0; jj < holes_count; ++jj )
2481 m_gal->DrawPolyline( outline->CHole( ii, jj ) );
2482 }
2483
2484 // Draw hatch lines
2485 for( const SEG& hatchLine : aZone->GetHatchLines() )
2486 m_gal->DrawLine( hatchLine.A, hatchLine.B );
2487 }
2488 }
2489
2490 // Draw the filling
2491 if( IsZoneFillLayer( aLayer )
2492 && ( displayMode == ZONE_DISPLAY_MODE::SHOW_FILLED
2494 || displayMode == ZONE_DISPLAY_MODE::SHOW_TRIANGULATION ) )
2495 {
2496 const std::shared_ptr<SHAPE_POLY_SET>& polySet = aZone->GetFilledPolysList( layer );
2497
2498 if( polySet->OutlineCount() == 0 ) // Nothing to draw
2499 return;
2500
2503 m_gal->SetLineWidth( 0 );
2504
2505 if( displayMode == ZONE_DISPLAY_MODE::SHOW_FILLED )
2506 {
2507 m_gal->SetIsFill( true );
2508 m_gal->SetIsStroke( false );
2509 }
2510 else
2511 {
2512 m_gal->SetIsFill( false );
2513 m_gal->SetIsStroke( true );
2514 }
2515
2516 m_gal->DrawPolygon( *polySet, displayMode == ZONE_DISPLAY_MODE::SHOW_TRIANGULATION );
2517 }
2518}
2519
2520
2521void PCB_PAINTER::draw( const PCB_DIMENSION_BASE* aDimension, int aLayer )
2522{
2523 const COLOR4D& color = m_pcbSettings.GetColor( aDimension, aLayer );
2524
2527 m_gal->SetIsFill( false );
2528 m_gal->SetIsStroke( true );
2529
2531
2532 if( outline_mode )
2534 else
2536
2537 // Draw dimension shapes
2538 // TODO(JE) lift this out
2539 for( const std::shared_ptr<SHAPE>& shape : aDimension->GetShapes() )
2540 {
2541 switch( shape->Type() )
2542 {
2543 case SH_SEGMENT:
2544 {
2545 const SEG& seg = static_cast<const SHAPE_SEGMENT*>( shape.get() )->GetSeg();
2546 m_gal->DrawLine( seg.A, seg.B );
2547 break;
2548 }
2549
2550 case SH_CIRCLE:
2551 {
2552 int radius = static_cast<const SHAPE_CIRCLE*>( shape.get() )->GetRadius();
2553 m_gal->DrawCircle( shape->Centre(), radius );
2554 break;
2555 }
2556
2557 default:
2558 break;
2559 }
2560 }
2561
2562 // Draw text
2563 wxString resolvedText = aDimension->GetShownText();
2564 TEXT_ATTRIBUTES attrs = aDimension->GetAttributes();
2565
2566 if( m_gal->IsFlippedX() && !( aDimension->GetLayerSet() & LSET::SideSpecificMask() ).any() )
2567 attrs.m_Mirrored = !attrs.m_Mirrored;
2568
2569 if( outline_mode )
2571 else
2573
2574 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
2575
2576 if( aDimension->GetFont() && aDimension->GetFont()->IsOutline() )
2577 cache = aDimension->GetRenderCache( aDimension->GetFont(), resolvedText );
2578
2579 if( cache )
2580 {
2581 for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
2582 m_gal->DrawGlyph( *glyph.get() );
2583 }
2584 else
2585 {
2586 strokeText( resolvedText, aDimension->GetTextPos(), attrs );
2587 }
2588}
2589
2590
2591void PCB_PAINTER::draw( const PCB_TARGET* aTarget )
2592{
2593 const COLOR4D& strokeColor = m_pcbSettings.GetColor( aTarget, aTarget->GetLayer() );
2594 VECTOR2D position( aTarget->GetPosition() );
2595 double size, radius;
2596
2597 m_gal->SetLineWidth( getLineThickness( aTarget->GetWidth() ) );
2598 m_gal->SetStrokeColor( strokeColor );
2599 m_gal->SetIsFill( false );
2600 m_gal->SetIsStroke( true );
2601
2602 m_gal->Save();
2603 m_gal->Translate( position );
2604
2605 if( aTarget->GetShape() )
2606 {
2607 // shape x
2608 m_gal->Rotate( M_PI / 4.0 );
2609 size = 2.0 * aTarget->GetSize() / 3.0;
2610 radius = aTarget->GetSize() / 2.0;
2611 }
2612 else
2613 {
2614 // shape +
2615 size = aTarget->GetSize() / 2.0;
2616 radius = aTarget->GetSize() / 3.0;
2617 }
2618
2619 m_gal->DrawLine( VECTOR2D( -size, 0.0 ), VECTOR2D( size, 0.0 ) );
2620 m_gal->DrawLine( VECTOR2D( 0.0, -size ), VECTOR2D( 0.0, size ) );
2621 m_gal->DrawCircle( VECTOR2D( 0.0, 0.0 ), radius );
2622
2623 m_gal->Restore();
2624}
2625
2626
2627void PCB_PAINTER::draw( const PCB_MARKER* aMarker, int aLayer )
2628{
2629 bool isShadow = aLayer == LAYER_MARKER_SHADOWS;
2630
2631 // Don't paint shadows for invisible markers.
2632 // It would be nice to do this through layer dependencies but we can't do an "or" there today
2633 if( isShadow && aMarker->GetBoard()
2634 && !aMarker->GetBoard()->IsElementVisible( aMarker->GetColorLayer() ) )
2635 {
2636 return;
2637 }
2638
2639 const_cast<PCB_MARKER*>( aMarker )->SetZoom( 1.0 / sqrt( m_gal->GetZoomFactor() ) );
2640
2641 SHAPE_LINE_CHAIN polygon;
2642 aMarker->ShapeToPolygon( polygon );
2643
2645 : aMarker->GetColorLayer() );
2646
2647 m_gal->Save();
2648 m_gal->Translate( aMarker->GetPosition() );
2649
2650 if( isShadow )
2651 {
2653 m_gal->SetIsStroke( true );
2654 m_gal->SetLineWidth( aMarker->MarkerScale() );
2655 }
2656 else
2657 {
2659 m_gal->SetIsFill( true );
2660 }
2661
2662 m_gal->DrawPolygon( polygon );
2663 m_gal->Restore();
2664}
2665
2666
int color
Definition: DXF_plotter.cpp:57
const char * name
Definition: DXF_plotter.cpp:56
constexpr int ARC_HIGH_DEF
Definition: base_units.h:121
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
@ NORMAL
Inactive layers are shown normally (no high-contrast mode)
@ HIDDEN
Inactive layers are hidden.
@ RATSNEST
Net/netclass colors are shown on ratsnest lines only.
@ ALL
Net/netclass colors are shown on all net copper.
Bezier curves to polygon converter.
Definition: bezier_curves.h:38
void GetPoly(std::vector< VECTOR2I > &aOutput, int aMinSegLen=0, int aMaxSegCount=32)
Convert a Bezier curve to a polygon.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
wxString GetNetClassName() const
Returns the name of the effective netclass.
virtual int GetOwnClearance(PCB_LAYER_ID aLayer, wxString *aSource=nullptr) const
Return an item's "own" clearance in internal units.
wxString GetUnescapedShortNetname() const
Container for design settings for a BOARD object.
int GetHolePlatingThickness() const
Pad & via drills are finish size.
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:70
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:192
virtual bool IsKnockout() const
Definition: board_item.h:262
virtual BOARD_ITEM * Duplicate() const
Create a copy of this BOARD_ITEM.
Definition: board_item.cpp:184
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:43
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:197
BOARD_ITEM_CONTAINER * GetParentFootprint() const
Definition: board_item.cpp:239
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:175
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:269
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:587
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:601
bool IsElementVisible(GAL_LAYER_ID aLayer) const
Test whether a given element category is visible.
Definition: board.cpp:653
int GetCopperLayerCount() const
Definition: board.cpp:563
void SetOrigin(const Vec &pos)
Definition: box2.h:202
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:119
const Vec & GetPosition() const
Definition: box2.h:184
const Vec & GetOrigin() const
Definition: box2.h:183
coord_type GetHeight() const
Definition: box2.h:188
coord_type GetWidth() const
Definition: box2.h:187
const Vec GetEnd() const
Definition: box2.h:185
bool Contains(const Vec &aPoint) const
Definition: box2.h:141
Vec Centre() const
Definition: box2.h:70
const Vec & GetSize() const
Definition: box2.h:179
void SetEnd(coord_type x, coord_type y)
Definition: box2.h:255
Color settings are a bit different than most of the settings objects in that there can be more than o...
COLOR4D GetColor(int aLayer) const
EDA_ANGLE Normalize90()
Definition: eda_angle.h:277
double AsRadians() const
Definition: eda_angle.h:153
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:249
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
bool IsEntered() const
Definition: eda_item.h:107
bool IsSelected() const
Definition: eda_item.h:106
bool IsBrightened() const
Definition: eda_item.h:108
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:142
const VECTOR2I & GetBezierC2() const
Definition: eda_shape.h:179
virtual VECTOR2I GetTopLeft() const
Definition: eda_shape.h:167
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition: eda_shape.h:289
bool IsFilled() const
Definition: eda_shape.h:90
void CalcArcAngles(EDA_ANGLE &aStartAngle, EDA_ANGLE &aEndAngle) const
Calc arc start and end angles such that aStartAngle < aEndAngle.
Definition: eda_shape.cpp:502
int GetRadius() const
Definition: eda_shape.cpp:523
SHAPE_T GetShape() const
Definition: eda_shape.h:113
virtual VECTOR2I GetBotRight() const
Definition: eda_shape.h:168
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:145
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:120
std::vector< VECTOR2I > GetRectCorners() const
Definition: eda_shape.cpp:1035
int GetWidth() const
Definition: eda_shape.h:109
const VECTOR2I & GetBezierC1() const
Definition: eda_shape.h:176
bool IsAnnotationProxy() const
Definition: eda_shape.h:87
void TransformBoundingBoxToPolygon(SHAPE_POLY_SET *aBuffer, int aClearance) const
Convert the text bounding box to a rectangular polygon depending on the text orientation,...
Definition: eda_text.cpp:947
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:208
bool IsItalic() const
Definition: eda_text.h:130
KIFONT::FONT * GetFont() const
Definition: eda_text.h:188
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:453
virtual VECTOR2I GetDrawPos() const
Definition: eda_text.h:318
const TEXT_ATTRIBUTES & GetAttributes() const
Definition: eda_text.h:172
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition: eda_text.cpp:299
bool IsBold() const
Definition: eda_text.h:133
EDA_ANGLE GetOrientation() const
Definition: footprint.h:191
LSET GetPrivateLayers() const
Definition: footprint.h:120
SHAPE_POLY_SET GetBoundingHull() const
Return a bounding polygon for the shapes and pads in the footprint.
Definition: footprint.cpp:944
const SHAPE_POLY_SET & GetCourtyard(PCB_LAYER_ID aLayer) const
Used in DRC to test the courtyard area (a complex polygon).
Definition: footprint.cpp:2233
VECTOR2I GetPosition() const override
Definition: footprint.h:188
DRAWINGS & GraphicalItems()
Definition: footprint.h:173
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: footprint.cpp:806
virtual wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
Definition: fp_textbox.cpp:424
VECTOR2I GetDrawPos() const override
Definition: fp_textbox.cpp:213
virtual EDA_ANGLE GetDrawRotation() const override
Definition: fp_textbox.cpp:162
std::vector< VECTOR2I > GetCorners() const override
Return 4 corners for a rectangle or rotated rectangle (stored as a poly).
Definition: fp_textbox.cpp:143
virtual EDA_ANGLE GetDrawRotation() const override
Definition: fp_text.cpp:247
virtual wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
Definition: fp_text.cpp:415
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:95
FONT is an abstract base class for both outline and stroke fonts.
Definition: font.h:105
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false)
Definition: font.cpp:138
void Draw(KIGFX::GAL *aGal, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aCursor, const TEXT_ATTRIBUTES &aAttrs) const
Draw a string.
Definition: font.cpp:232
virtual bool IsStroke() const
Definition: font.h:112
virtual bool IsOutline() const
Definition: font.h:113
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:102
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:309
static const COLOR4D CLEAR
Definition: color4d.h:383
COLOR4D & Darken(double aFactor)
Makes the color darker by a given factor.
Definition: color4d.h:224
COLOR4D Inverted() const
Returns an inverted color, alpha remains the same.
Definition: color4d.h:321
COLOR4D & Brighten(double aFactor)
Makes the color brighter by a given factor.
Definition: color4d.h:207
double a
Alpha component.
Definition: color4d.h:375
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition: color4d.h:378
Abstract interface for drawing on a 2D-surface.
virtual void DrawPolygon(const std::deque< VECTOR2D > &aPointList)
Draw a polygon.
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
virtual void DrawGlyph(const KIFONT::GLYPH &aGlyph, int aNth=0, int aTotal=1)
Draw a polygon representing a font glyph.
virtual void Rotate(double aAngle)
Rotate the context.
virtual void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a rectangle.
void SetVerticalJustify(const GR_TEXT_V_ALIGN_T aVerticalJustify)
void SetFontBold(const bool aBold)
void SetFontUnderlined(bool aUnderlined)
void SetHorizontalJustify(const GR_TEXT_H_ALIGN_T aHorizontalJustify)
double GetZoomFactor() const
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
virtual void Translate(const VECTOR2D &aTranslation)
Translate the context.
const MATRIX3x3D & GetScreenWorldMatrix() const
Get the screen <-> world transformation matrix.
virtual void DrawCircle(const VECTOR2D &aCenterPoint, double aRadius)
Draw a circle using world coordinates.
virtual void Restore()
Restore the context.
virtual bool IsOpenGlEngine()
Return true if the GAL engine is a OpenGL based type.
void ResetTextAttributes()
Reset text attributes to default styling.
virtual void SetLineWidth(float aLineWidth)
Set the line width.
void SetTextMirrored(const bool aMirrored)
virtual void DrawPolyline(const std::deque< VECTOR2D > &aPointList)
Draw a polyline.
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
virtual void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a line.
void SetGlyphSize(const VECTOR2I aSize)
virtual void DrawGlyphs(const std::vector< std::unique_ptr< KIFONT::GLYPH > > &aGlyphs)
Draw polygons representing font glyphs.
virtual void Scale(const VECTOR2D &aScale)
Scale the context.
virtual void DrawCurve(const VECTOR2D &startPoint, const VECTOR2D &controlPointA, const VECTOR2D &controlPointB, const VECTOR2D &endPoint, double aFilterValue=0.0)
Draw a cubic bezier spline.
void SetFontItalic(bool aItalic)
virtual void DrawBitmap(const BITMAP_BASE &aBitmap, double alphaBlend=1.0)
Draw a bitmap image.
virtual void DrawSegment(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint, double aWidth)
Draw a rounded segment.
virtual void BitmapText(const wxString &aText, const VECTOR2I &aPosition, const EDA_ANGLE &aAngle)
Draw a text using a bitmap font.
const VECTOR2I & GetScreenPixelSize() const
Return GAL canvas size in pixels.
virtual void Save()
Save the context.
virtual void DrawSegmentChain(const std::vector< VECTOR2D > &aPointList, double aWidth)
Draw a chain of rounded segments.
double GetWorldScale() const
Get the world scale.
virtual void DrawArcSegment(const VECTOR2D &aCenterPoint, double aRadius, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aEndAngle, double aWidth, double aMaxError)
Draw an arc segment.
virtual void DrawArc(const VECTOR2D &aCenterPoint, double aRadius, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aEndAngle)
Draw an arc.
Contains all the knowledge about how to draw graphical object onto any particular output device.
Definition: painter.h:58
GAL * m_gal
Instance of graphic abstraction layer that gives an interface to call commands used to draw (eg.
Definition: painter.h:101
virtual SHAPE_SEGMENT getPadHoleShape(const PAD *aPad) const
Return hole shape for a pad (internal units).
PCB_PAINTER(GAL *aGal, FRAME_T aFrameType)
int getLineThickness(int aActualThickness) const
Get the thickness to draw for a line (e.g.
PCB_VIEWERS_SETTINGS_BASE * viewer_settings()
Definition: pcb_painter.cpp:80
void draw(const PCB_TRACK *aTrack, int aLayer)
void strokeText(const wxString &aText, const VECTOR2I &aPosition, const TEXT_ATTRIBUTES &aAttrs)
virtual int getDrillShape(const PAD *aPad) const
Return drill shape of a pad.
PCB_RENDER_SETTINGS m_pcbSettings
Definition: pcb_painter.h:219
virtual int getViaDrillSize(const PCB_VIA *aVia) const
Return drill diameter for a via (internal units).
virtual bool Draw(const VIEW_ITEM *aItem, int aLayer) override
Takes an instance of VIEW_ITEM and passes it to a function that knows how to draw the item.
double m_zoneOpacity
Opacity override for filled zones.
Definition: pcb_painter.h:149
double m_trackOpacity
Opacity override for all tracks.
Definition: pcb_painter.h:146
double m_imageOpacity
Opacity override for user images.
Definition: pcb_painter.h:150
double m_viaOpacity
Opacity override for all types of via.
Definition: pcb_painter.h:147
ZONE_DISPLAY_MODE m_ZoneDisplayMode
Definition: pcb_painter.h:124
void LoadColors(const COLOR_SETTINGS *aSettings) override
double m_padOpacity
Opacity override for SMD pads and PTHs.
Definition: pcb_painter.h:148
void SetBackgroundColor(const COLOR4D &aColor) override
Set the background color.
Definition: pcb_painter.h:102
COLOR4D GetColor(const VIEW_ITEM *aItem, int aLayer) const override
Returns the color that should be used to draw the specific VIEW_ITEM on the specific layer using curr...
HIGH_CONTRAST_MODE m_ContrastModeDisplay
Definition: pcb_painter.h:125
std::map< int, KIGFX::COLOR4D > m_netColors
Set of net codes that should not have their ratsnest displayed.
Definition: pcb_painter.h:140
NET_COLOR_MODE m_netColorMode
Overrides for specific netclass colors.
Definition: pcb_painter.h:134
static const double MAX_FONT_SIZE
< Maximum font size for netnames (and other dynamically shown strings)
Definition: pcb_painter.h:131
std::map< wxString, KIGFX::COLOR4D > m_netclassColors
Overrides for specific net colors, stored as netcodes for the ratsnest to access easily.
Definition: pcb_painter.h:137
bool GetShowPageLimits() const override
void LoadDisplayOptions(const PCB_DISPLAY_OPTIONS &aOptions)
Load settings related to display options (high-contrast mode, full or outline modes for vias/pads/tra...
PCB_LAYER_ID GetPrimaryHighContrastLayer() const
Return the board layer which is in high-contrast mode.
void SetGapLengthRatio(double aRatio)
const wxString & GetDefaultFont() const
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
PCB_LAYER_ID GetActiveLayer() const
COLOR4D m_layerColorsDark[LAYER_ID_COUNT]
COLOR4D m_layerColorsSel[LAYER_ID_COUNT]
COLOR4D m_layerColorsHi[LAYER_ID_COUNT]
virtual void update()
Precalculates extra colors for layers (e.g.
void SetDashLengthRatio(double aRatio)
COLOR4D m_layerColors[LAYER_ID_COUNT]
std::set< int > m_highlightNetcodes
std::set< int > m_highContrastLayers
bool m_hiContrastEnabled
Parameters for display modes.
bool GetDrawBoundingBoxes() const
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:77
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:493
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:532
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
static LSET SideSpecificMask()
Definition: lset.cpp:908
static LSET PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition: lset.cpp:870
int MarkerScale() const
The scaling factor to convert polygonal shape coordinates to internal units.
Definition: marker_base.h:68
void ShapeToPolygon(SHAPE_LINE_CHAIN &aPolygon, int aScale=-1) const
Return the shape polygon in internal units in a SHAPE_LINE_CHAIN the coordinates are relatives to the...
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
Definition: matrix3x3.h:295
static const int UNCONNECTED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
Definition: netinfo.h:387
Definition: pad.h:60
int GetOwnClearance(PCB_LAYER_ID aLayer, wxString *aSource=nullptr) const override
Return an item's "own" clearance in internal units.
Definition: pad.cpp:808
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: pad.h:384
bool FlashLayer(int aLayer, bool aOnlyCheckIfPermitted=false) const
Check to see whether the pad should be flashed on the specific layer.
Definition: pad.cpp:267
const BOX2I GetBoundingBox() const override
The bounding box is cached, so this will be efficient most of the time.
Definition: pad.cpp:635
int GetSolderMaskExpansion() const
Definition: pad.cpp:834
const VECTOR2I & GetDrillSize() const
Definition: pad.h:268
PAD_ATTRIB GetAttribute() const
Definition: pad.h:401
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
Definition: pad.cpp:1586
const wxString & GetNumber() const
Definition: pad.h:136
VECTOR2I GetPosition() const override
Definition: pad.h:203
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives() const
Accessor to the basic shape list for custom-shaped pads.
Definition: pad.h:331
bool IsNoConnectPad() const
Definition: pad.cpp:182
bool IsFreePad() const
Definition: pad.cpp:189
PAD_SHAPE GetShape() const
Definition: pad.h:195
VECTOR2I GetSolderPasteMargin() const
Usually < 0 (mask shape smaller than pad)because the margin can be dependent on the pad size,...
Definition: pad.cpp:879
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING flashPTHPads=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: pad.cpp:370
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition: pad.cpp:407
const VECTOR2I & GetSize() const
Definition: pad.h:258
DISPLAY_OPTIONS m_Display
EDA_ANGLE GetArcAngleStart() const
Definition: pcb_track.cpp:1155
double GetRadius() const
Definition: pcb_track.cpp:1140
EDA_ANGLE GetAngle() const
Definition: pcb_track.cpp:1146
const VECTOR2I & GetMid() const
Definition: pcb_track.h:313
virtual VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_track.h:322
Object to handle a bitmap image that can be inserted in a PCB.
Definition: pcb_bitmap.h:42
VECTOR2I GetPosition() const override
Definition: pcb_bitmap.h:127
double GetImageScale() const
Definition: pcb_bitmap.h:75
const VECTOR2I GetSize() const
Definition: pcb_bitmap.cpp:160
const BITMAP_BASE * GetImage() const
Definition: pcb_bitmap.h:53
Abstract dimension API.
int GetLineThickness() const
const std::vector< std::shared_ptr< SHAPE > > & GetShapes() const
double m_TrackOpacity
Opacity override for all tracks.
double m_ZoneOpacity
Opacity override for filled zone areas.
double m_ImageOpacity
Opacity override for user images.
double m_PadOpacity
Opacity override for SMD pads and PTHs.
double m_ViaOpacity
Opacity override for all types of via.
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
NET_COLOR_MODE m_NetColorMode
How to use color overrides on specific nets and netclasses.
ZONE_DISPLAY_MODE m_ZoneDisplayMode
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:51
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: pcb_group.cpp:276
wxString GetName() const
Definition: pcb_group.h:65
GAL_LAYER_ID GetColorLayer() const
Definition: pcb_marker.cpp:310
VECTOR2I GetPosition() const override
Definition: pcb_marker.h:68
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_shape.h:67
FOOTPRINT * GetParentFootprint() const
Return the parent footprint or NULL if PCB_SHAPE does not belong to a footprint.
Definition: pcb_shape.cpp:252
virtual std::vector< VECTOR2I > GetCorners() const
Return 4 corners for a rectangle or rotated rectangle (stored as a poly).
Definition: pcb_shape.cpp:133
STROKE_PARAMS GetStroke() const override
Definition: pcb_shape.h:71
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
VECTOR2I GetDrawPos() const override
wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth=false) const override
Convert the item shape to a closed polygon.
Definition: pcb_text.cpp:325
wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
Definition: pcb_text.cpp:55
virtual double GetLength() const
Function GetLength returns the length of the track using the hypotenuse calculation.
Definition: pcb_track.cpp:314
int GetWidth() const
Definition: pcb_track.h:108
const VECTOR2I & GetStart() const
Definition: pcb_track.h:114
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:111
PCB_LAYER_ID BottomLayer() const
Definition: pcb_track.cpp:599
bool FlashLayer(int aLayer) const
Checks to see whether the via should have a pad on the specific layer.
Definition: pcb_track.cpp:630
PCB_LAYER_ID TopLayer() const
Definition: pcb_track.cpp:593
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
Definition: pcb_track.cpp:221
VIATYPE GetViaType() const
Definition: pcb_track.h:394
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
Definition: pcb_track.cpp:571
VIEWERS_DISPLAY_OPTIONS m_ViewersDisplay
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
int Length() const
Return the length (this).
Definition: seg.h:326
const SHAPE_LINE_CHAIN ConvertToPolyline(double aAccuracy=DefaultAccuracyForPCB(), double *aEffectiveAccuracy=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
Definition: shape_arc.cpp:470
int GetRadius() const
Definition: shape_circle.h:108
const VECTOR2I GetCenter() const
Definition: shape_circle.h:113
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
void Fracture(POLYGON_MODE aFastMode)
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
bool IsTriangulationUpToDate() const
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new hole to the given outline (default: last) and returns its index.
void CacheTriangulation(bool aPartition=true, bool aSimplify=false)
Build a polygon triangulation, needed to draw a polygon on OpenGL and in some other calculations.
void Deflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=CHAMFER_ALL_CORNERS)
int HoleCount(int aOutline) const
Return the reference to aIndex-th outline in the set.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Add a new vertex to the contour indexed by aOutline and aHole (defaults to the outline of the last po...
SHAPE_LINE_CHAIN & Outline(int aIndex)
int NewOutline()
Creates a new hole in a given outline.
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
int OutlineCount() const
Return the number of vertices in a given outline/hole.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
const int GetHeight() const
Definition: shape_rect.h:151
const int GetWidth() const
Definition: shape_rect.h:143
const VECTOR2I & GetPosition() const
Definition: shape_rect.h:127
const VECTOR2I GetSize() const
Definition: shape_rect.h:135
const SEG & GetSeg() const
int GetWidth() const
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
Definition: shape_simple.h:42
const SHAPE_LINE_CHAIN & Vertices() const
Return the list of vertices defining this simple polygon.
Definition: shape_simple.h:124
virtual const SEG GetSegment(int aIndex) const override
Definition: shape_simple.h:174
const VECTOR2I & CPoint(int aIndex) const
Return a const reference to a given point in the polygon.
Definition: shape_simple.h:102
int PointCount() const
Return the number of points (vertices) in this polygon.
Definition: shape_simple.h:88
virtual size_t GetSegmentCount() const override
Definition: shape_simple.h:176
An abstract shape on 2D plane.
Definition: shape.h:124
static void Stroke(const SHAPE *aShape, PLOT_DASH_TYPE aLineStyle, int aWidth, const KIGFX::RENDER_SETTINGS *aRenderSettings, std::function< void(const VECTOR2I &a, const VECTOR2I &b)> aStroker)
PLOT_DASH_TYPE GetPlotStyle() const
GR_TEXT_H_ALIGN_T m_Halign
GR_TEXT_V_ALIGN_T m_Valign
KIFONT::FONT * m_Font
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
const std::vector< SEG > & GetHatchLines() const
Definition: zone.h:767
virtual bool IsOnLayer(PCB_LAYER_ID, bool aIncludeCourtyards=false) const override
Test to see if this object is on the given layer.
Definition: zone.cpp:323
const std::shared_ptr< SHAPE_POLY_SET > & GetFilledPolysList(PCB_LAYER_ID aLayer) const
Definition: zone.h:608
SHAPE_POLY_SET * Outline()
Definition: zone.h:318
@ MAGENTA
Definition: color4d.h:58
@ CYAN
Definition: color4d.h:56
void TransformArcToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc)
Convert arc to multiple straight segments.
PGM_BASE * PgmOrNull()
similar to PGM_BASE& Pgm(), but return a reference that can be nullptr when running a shared lib from...
Definition: cvpcb.cpp:125
static constexpr EDA_ANGLE & ANGLE_HORIZONTAL
Definition: eda_angle.h:425
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE & ANGLE_VERTICAL
Definition: eda_angle.h:426
static constexpr EDA_ANGLE & FULL_CIRCLE
Definition: eda_angle.h:427
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:431
#define ENTERED
indicates a group has been entered
@ LAST
marker for list end
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition: frame_type.h:33
@ FRAME_PCB_EDITOR
Definition: frame_type.h:40
@ FRAME_FOOTPRINT_VIEWER_MODAL
Definition: frame_type.h:43
@ FRAME_CVPCB_DISPLAY
Definition: frame_type.h:49
@ FRAME_FOOTPRINT_VIEWER
Definition: frame_type.h:42
@ FRAME_FOOTPRINT_WIZARD
Definition: frame_type.h:44
@ FRAME_FOOTPRINT_PREVIEW
Definition: frame_type.h:46
@ FRAME_FOOTPRINT_EDITOR
Definition: frame_type.h:41
@ FRAME_PCB_DISPLAY3D
Definition: frame_type.h:45
@ FRAME_CVPCB
Definition: frame_type.h:48
a few functions useful in geometry calculations.
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ ERROR_OUTSIDE
@ ERROR_INSIDE
bool ClipLine(const BOX2I *aClipBox, int &x1, int &y1, int &x2, int &y2)
Test if any part of a line falls within the bounds of a rectangle.
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
int GetPenSizeForNormal(int aTextSize)
Definition: gr_text.cpp:64
int GetKnockoutTextMargin(const VECTOR2I &aSize, int aThickness)
Returns the margin for knocking out text.
Definition: gr_text.h:104
@ LAYER_PAD_FR_NETNAMES
Additional netnames layers (not associated with a PCB layer)
Definition: layer_ids.h:165
@ LAYER_PAD_BK_NETNAMES
Definition: layer_ids.h:166
@ LAYER_PAD_NETNAMES
Definition: layer_ids.h:167
@ LAYER_VIA_NETNAMES
Definition: layer_ids.h:168
bool IsPcbLayer(int aLayer)
Test whether a layer is a valid layer for Pcbnew.
Definition: layer_ids.h:816
bool IsNetCopperLayer(int aLayer)
Checks if the given layer is "net copper", meaning it is eligible for net coloring.
Definition: layer_ids.h:1016
int GetNetnameLayer(int aLayer)
Returns a netname layer corresponding to the given layer.
Definition: layer_ids.h:968
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:827
@ GAL_LAYER_ID_START
Definition: layer_ids.h:191
@ LAYER_LOCKED_ITEM_SHADOW
shadow layer for locked items
Definition: layer_ids.h:239
@ LAYER_VIA_HOLEWALLS
Definition: layer_ids.h:234
@ LAYER_CONFLICTS_SHADOW
shadow layer for items flagged conficting
Definition: layer_ids.h:241
@ LAYER_NON_PLATEDHOLES
handle color for not plated holes (holes, not pads)
Definition: layer_ids.h:197
@ LAYER_PAD_FR
smd pads, front layer
Definition: layer_ids.h:202
@ LAYER_PCB_BACKGROUND
PCB background color.
Definition: layer_ids.h:220
@ LAYER_PAD_PLATEDHOLES
to draw pad holes (plated)
Definition: layer_ids.h:214
@ GAL_LAYER_ID_END
Definition: layer_ids.h:260
@ LAYER_ZONE_START
Virtual layers for stacking zones and tracks on a given copper layer.
Definition: layer_ids.h:253
@ LAYER_ANCHOR
anchor of items having an anchor point (texts, footprints)
Definition: layer_ids.h:201
@ LAYER_PAD_BK
smd pads, back layer
Definition: layer_ids.h:203
@ LAYER_PADS_TH
multilayer pads, usually with holes
Definition: layer_ids.h:213
@ LAYER_MARKER_SHADOWS
shadows for drc markers
Definition: layer_ids.h:237
@ LAYER_VIA_HOLES
to draw via holes (pad holes do not use this layer)
Definition: layer_ids.h:215
@ LAYER_VIA_MICROVIA
to draw micro vias
Definition: layer_ids.h:194
@ LAYER_VIA_THROUGH
to draw usual through hole vias
Definition: layer_ids.h:196
@ LAYER_VIA_BBLIND
to draw blind/buried vias
Definition: layer_ids.h:195
@ LAYER_PAD_HOLEWALLS
Definition: layer_ids.h:233
bool IsNetnameLayer(int aLayer)
Test whether a layer is a netname layer.
Definition: layer_ids.h:991
bool IsHoleLayer(int aLayer)
Definition: layer_ids.h:866
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ F_CrtYd
Definition: layer_ids.h:117
@ F_Paste
Definition: layer_ids.h:101
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ F_Mask
Definition: layer_ids.h:107
@ B_Paste
Definition: layer_ids.h:100
@ F_SilkS
Definition: layer_ids.h:104
@ B_CrtYd
Definition: layer_ids.h:116
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
@ PCB_LAYER_ID_COUNT
Definition: layer_ids.h:137
@ F_Cu
Definition: layer_ids.h:64
bool IsZoneFillLayer(int aLayer)
Definition: layer_ids.h:997
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:932
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:246
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:418
@ NPTH
like PAD_PTH, but not plated
@ PTH
Plated through hole pad.
PCBNEW_SETTINGS * pcbconfig()
Definition: pcb_painter.cpp:72
@ BLIND_BURIED
@ SHOW_WITH_VIA_ALWAYS
see class PGM_BASE
@ SH_RECT
axis-aligned rectangle
Definition: shape.h:45
@ SH_CIRCLE
circle
Definition: shape.h:48
@ SH_SIMPLE
simple polygon
Definition: shape.h:49
@ SH_SEGMENT
line segment
Definition: shape.h:46
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
wxString UnescapeString(const wxString &aSource)
int PrintableCharCount(const wxString &aString)
Return the number of printable (ie: non-formatting) chars.
PLOT_DASH_TYPE
Dashed line types.
Definition: stroke_params.h:48
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
TRACK_CLEARANCE_MODE m_TrackClearance
GR_TEXT_H_ALIGN_T
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ PCB_FP_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition: typeinfo.h:95
@ 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:110
@ PCB_FP_SHAPE_T
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:94
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:107
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:102
@ PCB_FP_TEXTBOX_T
class FP_TEXTBOX, wrapped text in a footprint
Definition: typeinfo.h:93
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:108
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:115
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:91
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:112
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:90
@ PCB_FP_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:97
@ PCB_MARKER_T
class PCB_MARKER, a marker used to show something
Definition: typeinfo.h:104
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:111
@ PCB_FP_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:99
@ PCB_FP_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:96
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition: typeinfo.h:106
@ PCB_FP_ZONE_T
class ZONE, managed by a footprint
Definition: typeinfo.h:100
@ PCB_BITMAP_T
class PCB_BITMAP, bitmap on a layer
Definition: typeinfo.h:89
@ PCB_FP_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition: typeinfo.h:98
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_FP_TEXT_T
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:103
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:101
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition: typeinfo.h:109
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< double > VECTOR2D
Definition: vector2d.h:589
VECTOR2< int > VECTOR2I
Definition: vector2d.h:590