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