KiCad PCB EDA Suite
pcb_painter.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2013-2019 CERN
5  * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
8  * @author Maciej Suminski <maciej.suminski@cern.ch>
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>
29 #include <board_design_settings.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 <kicad_string.h>
36 #include <zone.h>
37 #include <pcb_text.h>
38 #include <pcb_marker.h>
39 #include <pcb_dimension.h>
40 #include <pcb_target.h>
41 #include <advanced_config.h>
42 #include <core/arraydim.h>
43 
45 #include <pcb_painter.h>
46 #include <pcb_display_options.h>
47 #include <project/net_settings.h>
49 
54 #include <geometry/shape_rect.h>
55 #include <geometry/shape_segment.h>
56 #include <geometry/shape_simple.h>
57 #include <geometry/shape_circle.h>
58 
59 using namespace KIGFX;
60 
62 {
63  m_backgroundColor = COLOR4D( 0.0, 0.0, 0.0, 1.0 );
64  m_padNumbers = true;
65  m_netNamesOnPads = true;
66  m_netNamesOnTracks = true;
67  m_netNamesOnVias = true;
68  m_zoneOutlines = true;
71  m_sketchGraphics = false;
72  m_sketchText = false;
76 
77  m_trackOpacity = 1.0;
78  m_viaOpacity = 1.0;
79  m_padOpacity = 1.0;
80  m_zoneOpacity = 1.0;
81 
82  // By default everything should be displayed as filled
83  for( unsigned int i = 0; i < arrayDim( m_sketchMode ); ++i )
84  m_sketchMode[i] = false;
85 
86  update();
87 }
88 
89 
91 {
93 
94  // Init board layers colors:
95  for( int i = 0; i < PCB_LAYER_ID_COUNT; i++ )
96  {
97  m_layerColors[i] = aSettings->GetColor( i );
98 
99  // Guard: if the alpha channel is too small, the layer is not visible.
100  if( m_layerColors[i].a < 0.2 )
101  m_layerColors[i].a = 0.2;
102  }
103 
104  // Init specific graphic layers colors:
105  for( int i = GAL_LAYER_ID_START; i < GAL_LAYER_ID_END; i++ )
106  m_layerColors[i] = aSettings->GetColor( i );
107 
108  // Colors for layers that aren't theme-able
110  m_layerColors[LAYER_VIA_NETNAMES] = COLOR4D( 0.2, 0.2, 0.2, 0.9 );
111  m_layerColors[LAYER_PAD_NETNAMES] = COLOR4D( 1.0, 1.0, 1.0, 0.9 );
112  m_layerColors[LAYER_PAD_FR_NETNAMES] = COLOR4D( 1.0, 1.0, 1.0, 0.9 );
113  m_layerColors[LAYER_PAD_BK_NETNAMES] = COLOR4D( 1.0, 1.0, 1.0, 0.9 );
114 
115  // Netnames for copper layers
116  for( LSEQ cu = LSET::AllCuMask().CuStack(); cu; ++cu )
117  {
118  const COLOR4D lightLabel( 0.8, 0.8, 0.8, 0.7 );
119  const COLOR4D darkLabel = lightLabel.Inverted();
120  PCB_LAYER_ID layer = *cu;
121 
122  if( m_layerColors[layer].GetBrightness() > 0.5 )
123  m_layerColors[GetNetnameLayer( layer )] = darkLabel;
124  else
125  m_layerColors[GetNetnameLayer( layer )] = lightLabel;
126  }
127 
128  update();
129 }
130 
131 
133  bool aShowPageLimits )
134 {
137  m_padNumbers = aOptions.m_DisplayPadNum;
139  m_sketchText = !aOptions.m_DisplayTextFill;
142 
143  // Whether to draw tracks, vias & pads filled or as outlines
149 
150  // Net names display settings
151  switch( aOptions.m_DisplayNetNamesMode )
152  {
153  case 0:
154  m_netNamesOnPads = false;
155  m_netNamesOnTracks = false;
156  m_netNamesOnVias = false;
157  break;
158 
159  case 1:
160  m_netNamesOnPads = true;
161  m_netNamesOnTracks = false;
162  m_netNamesOnVias = true; // Follow pads or tracks? For now we chose pads....
163  break;
164 
165  case 2:
166  m_netNamesOnPads = false;
167  m_netNamesOnTracks = true;
168  m_netNamesOnVias = false; // Follow pads or tracks? For now we chose pads....
169  break;
170 
171  case 3:
172  m_netNamesOnPads = true;
173  m_netNamesOnTracks = true;
174  m_netNamesOnVias = true;
175  break;
176  }
177 
178  // Zone display settings
180 
181  // Clearance settings
182  switch( aOptions.m_ShowTrackClearanceMode )
183  {
186  break;
187 
190  break;
191 
194  break;
195 
198  break;
199 
202  break;
203  }
204 
205  if( aOptions.m_DisplayPadClearance )
207 
209 
210  m_netColorMode = aOptions.m_NetColorMode;
211 
213 
214  m_trackOpacity = aOptions.m_TrackOpacity;
215  m_viaOpacity = aOptions.m_ViaOpacity;
216  m_padOpacity = aOptions.m_PadOpacity;
217  m_zoneOpacity = aOptions.m_ZoneOpacity;
218 
219  m_showPageLimits = aShowPageLimits;
220 }
221 
222 
223 COLOR4D PCB_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) const
224 {
225  const EDA_ITEM* item = dynamic_cast<const EDA_ITEM*>( aItem );
226  const BOARD_CONNECTED_ITEM* conItem = dynamic_cast<const BOARD_CONNECTED_ITEM*> ( aItem );
227  int netCode = -1;
228  int originalLayer = aLayer;
229 
230  // Marker shadows
231  if( aLayer == LAYER_MARKER_SHADOWS )
232  return m_backgroundColor.WithAlpha( 0.6 );
233 
234  if( IsHoleLayer( aLayer ) && m_isPrinting )
235  {
236  // Careful that we don't end up with the same colour for the annular ring and the hole
237  // when printing in B&W.
238  const PAD* pad = dynamic_cast<const PAD*>( item );
239  const PCB_VIA* via = dynamic_cast<const PCB_VIA*>( item );
240  int holeLayer = aLayer;
241  int annularRingLayer = UNDEFINED_LAYER;
242 
243  if( pad && pad->GetAttribute() == PAD_ATTRIB::PTH )
244  annularRingLayer = LAYER_PADS_TH;
245  else if( via && via->GetViaType() == VIATYPE::MICROVIA )
246  annularRingLayer = LAYER_VIA_MICROVIA;
247  else if( via && via->GetViaType() == VIATYPE::BLIND_BURIED )
248  annularRingLayer = LAYER_VIA_BBLIND;
249  else if( via && via->GetViaType() == VIATYPE::THROUGH )
250  annularRingLayer = LAYER_VIA_THROUGH;
251 
252  if( annularRingLayer != UNDEFINED_LAYER
253  && m_layerColors[ holeLayer ] == m_layerColors[ annularRingLayer ] )
254  {
255  aLayer = LAYER_PCB_BACKGROUND;
256  }
257  }
258 
259  // Zones should pull from the copper layer
260  if( item && ( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T ) )
261  {
262  if( IsZoneLayer( aLayer ) )
263  aLayer = aLayer - LAYER_ZONE_START;
264  }
265 
266  // Hole walls should pull from the copper layer
267  if( aLayer == LAYER_PAD_HOLEWALLS )
268  aLayer = LAYER_PADS_TH;
269  else if( aLayer == LAYER_VIA_HOLEWALLS )
270  aLayer = LAYER_VIA_THROUGH;
271 
272  // Normal path: get the layer base color
273  COLOR4D color = m_layerColors[aLayer];
274 
275  if( !item )
276  return m_layerColors[aLayer];
277 
278  // Selection disambiguation
279  if( item->IsBrightened() )
280  return color.Brightened( m_selectFactor ).WithAlpha( 0.8 );
281 
282  // Normal selection
283  if( item->IsSelected() )
284  color = m_layerColorsSel[aLayer];
285 
286  // Try to obtain the netcode for the item
287  if( conItem )
288  netCode = conItem->GetNetCode();
289 
290  bool highlighted = m_highlightEnabled && m_highlightNetcodes.count( netCode );
291  bool selected = item->IsSelected();
292 
293  // Apply net color overrides
294  if( conItem && m_netColorMode == NET_COLOR_MODE::ALL && IsNetCopperLayer( aLayer ) )
295  {
296  COLOR4D netColor = COLOR4D::UNSPECIFIED;
297 
298  auto ii = m_netColors.find( netCode );
299 
300  if( ii != m_netColors.end() )
301  netColor = ii->second;
302 
303  if( netColor == COLOR4D::UNSPECIFIED )
304  {
305  auto jj = m_netclassColors.find( conItem->GetNetClassName() );
306 
307  if( jj != m_netclassColors.end() )
308  netColor = jj->second;
309  }
310 
311  if( netColor == COLOR4D::UNSPECIFIED )
312  netColor = color;
313 
314  if( selected )
315  {
316  // Selection brightening overrides highlighting
317  netColor.Brighten( m_selectFactor );
318  }
319  else if( m_highlightEnabled )
320  {
321  // Highlight brightens objects on all layers and darkens everything else for contrast
322  if( highlighted )
323  netColor.Brighten( m_highlightFactor );
324  else
325  netColor.Darken( 1.0 - m_highlightFactor );
326  }
327 
328  color = netColor;
329  }
330  else if( !selected && m_highlightEnabled )
331  {
332  // Single net highlight mode
333  color = m_highlightNetcodes.count( netCode ) ? m_layerColorsHi[aLayer]
334  : m_layerColorsDark[aLayer];
335  }
336 
337  // Apply high-contrast dimming
338  if( m_hiContrastEnabled && m_highContrastLayers.size() && !highlighted && !selected )
339  {
341  bool isActive = m_highContrastLayers.count( aLayer );
342 
343  switch( originalLayer )
344  {
345  case LAYER_PADS_TH:
346  if( !static_cast<const PAD*>( item )->FlashLayer( primary ) )
347  isActive = false;
348 
349  break;
350 
351  case LAYER_VIA_BBLIND:
352  case LAYER_VIA_MICROVIA:
353  // Target graphic is active if the via crosses the primary layer
354  if( static_cast<const PCB_VIA*>( item )->GetLayerSet().test( primary ) == 0 )
355  isActive = false;
356 
357  break;
358 
359  case LAYER_VIA_THROUGH:
360  if( !static_cast<const PCB_VIA*>( item )->FlashLayer( primary ) )
361  isActive = false;
362 
363  break;
364 
366  case LAYER_PAD_HOLEWALLS:
368  // Pad holes are active is any physical layer is active
369  if( LSET::PhysicalLayersMask().test( primary ) == 0 )
370  isActive = false;
371 
372  break;
373 
374  case LAYER_VIA_HOLES:
375  case LAYER_VIA_HOLEWALLS:
376  if( static_cast<const PCB_VIA*>( item )->GetViaType() == VIATYPE::BLIND_BURIED
377  || static_cast<const PCB_VIA*>( item )->GetViaType() == VIATYPE::MICROVIA )
378  {
379  // A blind or micro via's hole is active if it crosses the primary layer
380  if( static_cast<const PCB_VIA*>( item )->GetLayerSet().test( primary ) == 0 )
381  isActive = false;
382  }
383  else
384  {
385  // A through via's hole is active if any physical layer is active
386  if( LSET::PhysicalLayersMask().test( primary ) == 0 )
387  isActive = false;
388  }
389 
390  break;
391 
392  default:
393  break;
394  }
395 
396  if( !isActive )
397  {
400  else
402  }
403  }
404 
405  // Apply per-type opacity overrides
406  if( item->Type() == PCB_TRACE_T || item->Type() == PCB_ARC_T )
407  color.a *= m_trackOpacity;
408  else if( item->Type() == PCB_VIA_T )
409  color.a *= m_viaOpacity;
410  else if( item->Type() == PCB_PAD_T )
411  color.a *= m_padOpacity;
412  else if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
413  color.a *= m_zoneOpacity;
414 
415  // No special modificators enabled
416  return color;
417 }
418 
419 
421  PAINTER( aGal )
422 {
423 }
424 
425 
426 int PCB_PAINTER::getLineThickness( int aActualThickness ) const
427 {
428  // if items have 0 thickness, draw them with the outline
429  // width, otherwise respect the set value (which, no matter
430  // how small will produce something)
431  if( aActualThickness == 0 )
433 
434  return aActualThickness;
435 }
436 
437 
438 int PCB_PAINTER::getDrillShape( const PAD* aPad ) const
439 {
440  return aPad->GetDrillShape();
441 }
442 
443 
445 {
446  return VECTOR2D( aPad->GetDrillSize() );
447 }
448 
449 
450 int PCB_PAINTER::getDrillSize( const PCB_VIA* aVia ) const
451 {
452  return aVia->GetDrillValue();
453 }
454 
455 
456 bool PCB_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer )
457 {
458  const EDA_ITEM* item = dynamic_cast<const EDA_ITEM*>( aItem );
459 
460  if( !item )
461  return false;
462 
463  // the "cast" applied in here clarifies which overloaded draw() is called
464  switch( item->Type() )
465  {
466  case PCB_TRACE_T:
467  draw( static_cast<const PCB_TRACK*>( item ), aLayer );
468  break;
469 
470  case PCB_ARC_T:
471  draw( static_cast<const PCB_ARC*>( item ), aLayer );
472  break;
473 
474  case PCB_VIA_T:
475  draw( static_cast<const PCB_VIA*>( item ), aLayer );
476  break;
477 
478  case PCB_PAD_T:
479  draw( static_cast<const PAD*>( item ), aLayer );
480  break;
481 
482  case PCB_SHAPE_T:
483  case PCB_FP_SHAPE_T:
484  draw( static_cast<const PCB_SHAPE*>( item ), aLayer );
485  break;
486 
487  case PCB_TEXT_T:
488  draw( static_cast<const PCB_TEXT*>( item ), aLayer );
489  break;
490 
491  case PCB_FP_TEXT_T:
492  draw( static_cast<const FP_TEXT*>( item ), aLayer );
493  break;
494 
495  case PCB_FOOTPRINT_T:
496  draw( static_cast<const FOOTPRINT*>( item ), aLayer );
497  break;
498 
499  case PCB_GROUP_T:
500  draw( static_cast<const PCB_GROUP*>( item ), aLayer );
501  break;
502 
503  case PCB_ZONE_T:
504  draw( static_cast<const ZONE*>( item ), aLayer );
505  break;
506 
507  case PCB_FP_ZONE_T:
508  draw( static_cast<const ZONE*>( item ), aLayer );
509  break;
510 
511  case PCB_DIM_ALIGNED_T:
512  case PCB_DIM_CENTER_T:
514  case PCB_DIM_LEADER_T:
515  draw( static_cast<const PCB_DIMENSION_BASE*>( item ), aLayer );
516  break;
517 
518  case PCB_TARGET_T:
519  draw( static_cast<const PCB_TARGET*>( item ) );
520  break;
521 
522  case PCB_MARKER_T:
523  draw( static_cast<const PCB_MARKER*>( item ), aLayer );
524  break;
525 
526  default:
527  // Painter does not know how to draw the object
528  return false;
529  }
530 
531  // Draw bounding boxes after drawing objects so they can be seen.
532  if( ADVANCED_CFG::GetCfg().m_DrawBoundingBoxes )
533  {
534  // Show bounding boxes of painted objects for debugging.
535  EDA_RECT box = item->GetBoundingBox();
536  m_gal->SetIsFill( false );
537  m_gal->SetIsStroke( true );
538 
539  if( item->Type() == PCB_FOOTPRINT_T )
540  m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) :
541  COLOR4D( MAGENTA ) );
542  else
543  m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) :
544  COLOR4D( 0.2, 0.2, 0.2, 1 ) );
545 
546  m_gal->SetLineWidth( 1.5 / m_gal->GetWorldScale() );
547  m_gal->DrawRectangle( box.GetOrigin(), box.GetEnd() );
548 
549  if( item->Type() == PCB_FOOTPRINT_T )
550  {
551  m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) :
552  COLOR4D( CYAN ) );
553 
554  const FOOTPRINT* fp = static_cast<const FOOTPRINT*>( item );
555 
556  if( fp )
557  {
558  SHAPE_POLY_SET convex = fp->GetBoundingHull();
559 
560  m_gal->DrawPolyline( convex.COutline( 0 ) );
561  }
562  }
563  }
564 
565  return true;
566 }
567 
568 
569 void PCB_PAINTER::draw( const PCB_TRACK* aTrack, int aLayer )
570 {
571  VECTOR2D start( aTrack->GetStart() );
572  VECTOR2D end( aTrack->GetEnd() );
573  int width = aTrack->GetWidth();
574  COLOR4D color = m_pcbSettings.GetColor( aTrack, aLayer );
575 
576  if( IsNetnameLayer( aLayer ) )
577  {
579  return;
580 
581  if( aTrack->GetNetCode() <= NETINFO_LIST::UNCONNECTED )
582  return;
583 
584  VECTOR2D line = ( end - start );
585  double length = line.EuclideanNorm();
586 
587  // Check if the track is long enough to have a netname displayed
588  if( length < 10 * width )
589  return;
590 
591  const wxString& netName = UnescapeString( aTrack->GetShortNetname() );
592  double textSize = width;
593  double penWidth = width / 12.0;
594  VECTOR2D textPosition = start + line / 2.0; // center of the track
595  double textOrientation;
596 
597  if( end.y == start.y ) // horizontal
598  {
599  textOrientation = 0;
600  textPosition.y += penWidth;
601  }
602  else if( end.x == start.x ) // vertical
603  {
604  textOrientation = M_PI / 2;
605  textPosition.x += penWidth;
606  }
607  else
608  {
609  textOrientation = -atan( line.y / line.x );
610  textPosition.x += penWidth / 1.4;
611  textPosition.y += penWidth / 1.4;
612  }
613 
614 
615  m_gal->SetIsStroke( true );
616  m_gal->SetIsFill( false );
618  m_gal->SetLineWidth( penWidth );
619  m_gal->SetFontBold( false );
620  m_gal->SetFontItalic( false );
621  m_gal->SetFontUnderlined( false );
622  m_gal->SetTextMirrored( false );
623  m_gal->SetGlyphSize( VECTOR2D( textSize * 0.55, textSize * 0.55 ) );
626  m_gal->BitmapText( netName, textPosition, textOrientation );
627 
628  return;
629  }
630  else if( IsCopperLayer( aLayer ) )
631  {
632  // Draw a regular track
633  bool outline_mode = m_pcbSettings.m_sketchMode[LAYER_TRACKS];
636  m_gal->SetIsStroke( outline_mode );
637  m_gal->SetIsFill( not outline_mode );
639 
640  m_gal->DrawSegment( start, end, width );
641  }
642 
643  // Clearance lines
644  constexpr int clearanceFlags = PCB_RENDER_SETTINGS::CL_EXISTING
646 
647  if( ( m_pcbSettings.m_clearanceDisplayFlags & clearanceFlags ) == clearanceFlags )
648  {
649  int clearance = aTrack->GetOwnClearance( m_pcbSettings.GetActiveLayer() );
650 
652  m_gal->SetIsFill( false );
653  m_gal->SetIsStroke( true );
655  m_gal->DrawSegment( start, end, width + clearance * 2 );
656  }
657 }
658 
659 
660 void PCB_PAINTER::draw( const PCB_ARC* aArc, int aLayer )
661 {
662  VECTOR2D center( aArc->GetCenter() );
663  int width = aArc->GetWidth();
664  COLOR4D color = m_pcbSettings.GetColor( aArc, aLayer );
665  double radius = aArc->GetRadius();
666  double start_angle = DECIDEG2RAD( aArc->GetArcAngleStart() );
667  double angle = DECIDEG2RAD( aArc->GetAngle() );
668 
669  if( IsNetnameLayer( aLayer ) )
670  {
671  // Ummm, yeah. Anyone fancy implementing text on a path?
672  return;
673  }
674  else if( IsCopperLayer( aLayer ) )
675  {
676  // Draw a regular track
677  bool outline_mode = m_pcbSettings.m_sketchMode[LAYER_TRACKS];
680  m_gal->SetIsStroke( outline_mode );
681  m_gal->SetIsFill( not outline_mode );
683 
684  m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle, width );
685  }
686 
687  // Clearance lines
688  constexpr int clearanceFlags = PCB_RENDER_SETTINGS::CL_EXISTING
690 
691  if( ( m_pcbSettings.m_clearanceDisplayFlags & clearanceFlags ) == clearanceFlags )
692  {
693  int clearance = aArc->GetOwnClearance( m_pcbSettings.GetActiveLayer() );
694 
696  m_gal->SetIsFill( false );
697  m_gal->SetIsStroke( true );
699 
700  m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle,
701  width + clearance * 2 );
702  }
703 }
704 
705 
706 void PCB_PAINTER::draw( const PCB_VIA* aVia, int aLayer )
707 {
708  BOARD* board = aVia->GetBoard();
710  COLOR4D color = m_pcbSettings.GetColor( aVia, aLayer );
711  VECTOR2D center( aVia->GetStart() );
712 
713  if( color == COLOR4D::CLEAR )
714  return;
715 
716  // Draw description layer
717  if( IsNetnameLayer( aLayer ) )
718  {
719  VECTOR2D position( center );
720 
721  // Is anything that we can display enabled?
722  if( !m_pcbSettings.m_netNamesOnVias || aVia->GetNetname().empty() )
723  return;
724 
725  double maxSize = PCB_RENDER_SETTINGS::MAX_FONT_SIZE;
726  double size = aVia->GetWidth();
727 
728  // Font size limits
729  if( size > maxSize )
730  size = maxSize;
731 
732  m_gal->Save();
733  m_gal->Translate( position );
734 
735  // Default font settings
738 
739  // Set the text position to the pad shape position (the pad position is not the best place)
740  VECTOR2D textpos( 0.0, 0.0 );
741 
742  wxString netname = UnescapeString( aVia->GetShortNetname() );
743 
744  // calculate the size of net name text:
745  double tsize = 1.5 * size / netname.Length();
746  tsize = std::min( tsize, size );
747 
748  // Use a smaller text size to handle interline, pen size..
749  tsize *= 0.7;
750  VECTOR2D namesize( tsize, tsize );
751 
752  m_gal->SetGlyphSize( namesize );
753  m_gal->SetLineWidth( namesize.x / 12.0 );
754  m_gal->BitmapText( netname, textpos, 0.0 );
755 
756  m_gal->Restore();
757 
758  return;
759  }
760  else if( aLayer == LAYER_VIA_HOLEWALLS )
761  {
762  int platingThickness = bds.GetHolePlatingThickness();
763 
764  m_gal->SetIsFill( false );
765  m_gal->SetIsStroke( true );
767  m_gal->SetLineWidth( platingThickness );
768 
769  m_gal->DrawCircle( center, ( getDrillSize( aVia ) + platingThickness ) / 2.0 );
770 
771  return;
772  }
773 
774  bool sketchMode = false;
775 
776  switch( aVia->GetViaType() )
777  {
781  default: wxASSERT( false ); break;
782  }
783 
784  if( sketchMode )
785  {
786  // Outline mode
787  m_gal->SetIsStroke( true );
788  m_gal->SetIsFill( false );
791  }
792  else
793  {
794  // Filled mode
795  m_gal->SetIsFill( true );
796  m_gal->SetIsStroke( false );
798  }
799 
800  if( aLayer == LAYER_VIA_HOLES )
801  {
802  m_gal->DrawCircle( center, getDrillSize( aVia ) / 2.0 );
803  }
805  {
806  m_gal->DrawCircle( center, aVia->GetWidth() / 2.0 );
807  }
808  else if( aLayer == LAYER_VIA_BBLIND || aLayer == LAYER_VIA_MICROVIA )
809  {
810  // Outer circles of blind/buried and micro-vias are drawn in a special way to indicate the
811  // top and bottom layers
812  PCB_LAYER_ID layerTop, layerBottom;
813  aVia->LayerPair( &layerTop, &layerBottom );
814 
815  double radius = aVia->GetWidth() / 2.0;
816 
817  if( !sketchMode )
818  m_gal->SetLineWidth( ( aVia->GetWidth() - aVia->GetDrillValue() ) / 2.0 );
819 
820  m_gal->DrawArc( center, radius, M_PI * -0.375, M_PI * 0.375 );
821  m_gal->DrawArc( center, radius, M_PI * 0.625, M_PI * 1.375 );
822 
823  if( sketchMode )
824  m_gal->SetStrokeColor( m_pcbSettings.GetColor( aVia, layerTop ) );
825  else
826  m_gal->SetFillColor( m_pcbSettings.GetColor( aVia, layerTop ) );
827 
828  m_gal->DrawArc( center, radius, M_PI * 1.375, M_PI * 1.625 );
829 
830  if( sketchMode )
831  m_gal->SetStrokeColor( m_pcbSettings.GetColor( aVia, layerBottom ) );
832  else
833  m_gal->SetFillColor( m_pcbSettings.GetColor( aVia, layerBottom ) );
834 
835  m_gal->DrawArc( center, radius, M_PI * 0.375, M_PI * 0.625 );
836  }
837 
838  // Clearance lines
839  constexpr int clearanceFlags = PCB_RENDER_SETTINGS::CL_EXISTING | PCB_RENDER_SETTINGS::CL_VIAS;
840 
841  if( ( m_pcbSettings.m_clearanceDisplayFlags & clearanceFlags ) == clearanceFlags
842  && aLayer != LAYER_VIA_HOLES )
843  {
844  PCB_LAYER_ID activeLayer = m_pcbSettings.GetActiveLayer();
845  double radius;
846 
847  if( aVia->FlashLayer( activeLayer ) )
848  radius = aVia->GetWidth() / 2.0;
849  else
850  radius = getDrillSize( aVia ) / 2.0 + bds.GetHolePlatingThickness();
851 
853  m_gal->SetIsFill( false );
854  m_gal->SetIsStroke( true );
856  m_gal->DrawCircle( center, radius + aVia->GetOwnClearance( activeLayer ) );
857  }
858 }
859 
860 
861 void PCB_PAINTER::draw( const PAD* aPad, int aLayer )
862 {
863  BOARD* board = aPad->GetBoard();
865  COLOR4D color = m_pcbSettings.GetColor( aPad, aLayer );
866 
867  if( IsNetnameLayer( aLayer ) )
868  {
869  // Is anything that we can display enabled?
871  {
872  bool displayNetname = ( m_pcbSettings.m_netNamesOnPads && !aPad->GetNetname().empty() );
873  EDA_RECT padBBox = aPad->GetBoundingBox();
874  VECTOR2D position = padBBox.Centre();
875  VECTOR2D padsize = VECTOR2D( padBBox.GetSize() );
876 
877  if( aPad->GetShape() != PAD_SHAPE::CUSTOM )
878  {
879  // Don't allow a 45ยบ rotation to bloat a pad's bounding box unnecessarily
880  double limit = std::min( aPad->GetSize().x, aPad->GetSize().y ) * 1.1;
881 
882  if( padsize.x > limit && padsize.y > limit )
883  {
884  padsize.x = limit;
885  padsize.y = limit;
886  }
887  }
888 
889  double maxSize = PCB_RENDER_SETTINGS::MAX_FONT_SIZE;
890  double size = padsize.y;
891 
892  m_gal->Save();
893  m_gal->Translate( position );
894 
895  // Keep the size ratio for the font, but make it smaller
896  if( padsize.x < padsize.y )
897  {
898  m_gal->Rotate( DECIDEG2RAD( -900.0 ) );
899  size = padsize.x;
900  std::swap( padsize.x, padsize.y );
901  }
902 
903  // Font size limits
904  if( size > maxSize )
905  size = maxSize;
906 
907  // Default font settings
910  m_gal->SetFontBold( false );
911  m_gal->SetFontItalic( false );
912  m_gal->SetFontUnderlined( false );
913  m_gal->SetTextMirrored( false );
914  m_gal->SetStrokeColor( m_pcbSettings.GetColor( aPad, aLayer ) );
915  m_gal->SetIsStroke( true );
916  m_gal->SetIsFill( false );
917 
918  // We have already translated the GAL to be centered at the center of the pad's
919  // bounding box
920  VECTOR2D textpos( 0.0, 0.0 );
921 
922  // Divide the space, to display both pad numbers and netnames and set the Y text
923  // position to display 2 lines
924  if( displayNetname && m_pcbSettings.m_padNumbers )
925  {
926  size = size / 2.0;
927  textpos.y = size / 2.0;
928  }
929 
930  if( displayNetname )
931  {
932  wxString netname = UnescapeString( aPad->GetShortNetname() );
933  wxString pinType = aPad->GetPinType();
934 
935  if( pinType == wxT( "no_connect" ) || pinType.EndsWith( wxT( "+no_connect" ) ) )
936  netname = "x";
937  else if( pinType == wxT( "free" ) && netname.StartsWith( wxT( "unconnected-(" ) ) )
938  netname = "*";
939 
940  // calculate the size of net name text:
941  double tsize = 1.5 * padsize.x / netname.Length();
942  tsize = std::min( tsize, size );
943 
944  // Use a smaller text size to handle interline, pen size..
945  tsize *= 0.7;
946  VECTOR2D namesize( tsize, tsize );
947 
948  m_gal->SetGlyphSize( namesize );
949  m_gal->SetLineWidth( namesize.x / 12.0 );
950  m_gal->BitmapText( netname, textpos, 0.0 );
951  }
952 
954  {
955  const wxString& padName = aPad->GetName();
956  textpos.y = -textpos.y;
957  double tsize = 1.5 * padsize.x / padName.Length();
958  tsize = std::min( tsize, size );
959 
960  // Use a smaller text size to handle interline, pen size..
961  tsize *= 0.7;
962  tsize = std::min( tsize, size );
963  VECTOR2D numsize( tsize, tsize );
964 
965  m_gal->SetGlyphSize( numsize );
966  m_gal->SetLineWidth( numsize.x / 12.0 );
967  m_gal->BitmapText( padName, textpos, 0.0 );
968  }
969 
970  m_gal->Restore();
971  }
972  return;
973  }
974  else if( aLayer == LAYER_PAD_HOLEWALLS )
975  {
976  int platingThickness = bds.GetHolePlatingThickness();
977 
978  m_gal->SetIsFill( false );
979  m_gal->SetIsStroke( true );
980  m_gal->SetLineWidth( platingThickness );
982 
983  const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape();
984  int holeSize = seg->GetWidth() + platingThickness;
985 
986  if( seg->GetSeg().A == seg->GetSeg().B ) // Circular hole
987  m_gal->DrawCircle( seg->GetSeg().A, holeSize / 2 );
988  else
989  m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, holeSize );
990 
991  return;
992  }
993 
995  {
996  // Outline mode
997  m_gal->SetIsFill( false );
998  m_gal->SetIsStroke( true );
1001  }
1002  else
1003  {
1004  // Filled mode
1005  m_gal->SetIsFill( true );
1006  m_gal->SetIsStroke( false );
1007  m_gal->SetFillColor( color );
1008  }
1009 
1010  if( aLayer == LAYER_PAD_PLATEDHOLES || aLayer == LAYER_NON_PLATEDHOLES )
1011  {
1012  const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape();
1013 
1014  if( seg->GetSeg().A == seg->GetSeg().B ) // Circular hole
1015  m_gal->DrawCircle( seg->GetSeg().A, getDrillSize( aPad ).x / 2 );
1016  else
1017  m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, seg->GetWidth() );
1018  }
1019  else
1020  {
1021  wxSize pad_size = aPad->GetSize();
1022  wxSize margin;
1023 
1024  switch( aLayer )
1025  {
1026  case F_Mask:
1027  case B_Mask:
1028  margin.x = margin.y = aPad->GetSolderMaskMargin();
1029  break;
1030 
1031  case F_Paste:
1032  case B_Paste:
1033  margin = aPad->GetSolderPasteMargin();
1034  break;
1035 
1036  default:
1037  margin.x = margin.y = 0;
1038  break;
1039  }
1040 
1041  std::unique_ptr<PAD> dummyPad;
1042  std::shared_ptr<SHAPE_COMPOUND> shapes;
1043  bool simpleShapes = true;
1044 
1045  if( ( margin.x != margin.y && aPad->GetShape() != PAD_SHAPE::CUSTOM )
1046  || ( aPad->GetShape() == PAD_SHAPE::ROUNDRECT && ( margin.x < 0 || margin.y < 0 ) ) )
1047  {
1048  // Our algorithms below (polygon inflation in particular) can't handle differential
1049  // inflation along separate axes. So for those cases we build a dummy pad instead,
1050  // and inflate it.
1051 
1052  // Margin is added to both sides. If the total margin is larger than the pad
1053  // then don't display this layer
1054  if( pad_size.x + 2 * margin.x <= 0 || pad_size.y + 2 * margin.y <= 0 )
1055  return;
1056 
1057  dummyPad.reset( static_cast<PAD*>( aPad->Duplicate() ) );
1058  int initial_radius = dummyPad->GetRoundRectCornerRadius();
1059 
1060  dummyPad->SetSize( pad_size + margin + margin );
1061 
1062  if( dummyPad->GetShape() == PAD_SHAPE::ROUNDRECT )
1063  {
1064  // To keep the right margin around the corners, we need to modify the corner radius.
1065  // We must have only one radius correction, so use the smallest absolute margin.
1066  int radius_margin = std::max( margin.x, margin.y ); // radius_margin is < 0
1067  dummyPad->SetRoundRectCornerRadius( std::max( initial_radius + radius_margin, 0 ) );
1068  }
1069 
1070  shapes = std::dynamic_pointer_cast<SHAPE_COMPOUND>( dummyPad->GetEffectiveShape() );
1071  margin.x = margin.y = 0;
1072  }
1073  else
1074  {
1075  shapes = std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
1076  }
1077 
1078  if( aPad->GetShape() == PAD_SHAPE::CUSTOM && ( margin.x || margin.y ) )
1079  {
1080  // We can't draw as shapes because we don't know which edges are internal and which
1081  // are external (so we don't know when to apply the margin and when not to).
1082  simpleShapes = false;
1083  }
1084 
1085  for( const SHAPE* shape : shapes->Shapes() )
1086  {
1087  // Drawing components of compound shapes in outline mode produces a mess.
1089  simpleShapes = false;
1090 
1091  if( !simpleShapes )
1092  break;
1093 
1094  switch( shape->Type() )
1095  {
1096  case SH_SEGMENT:
1097  case SH_CIRCLE:
1098  case SH_RECT:
1099  case SH_SIMPLE:
1100  // OK so far
1101  break;
1102 
1103  default:
1104  // Not OK
1105  simpleShapes = false;
1106  break;
1107  }
1108  }
1109 
1110  if( simpleShapes )
1111  {
1112  for( const SHAPE* shape : shapes->Shapes() )
1113  {
1114  switch( shape->Type() )
1115  {
1116  case SH_SEGMENT:
1117  {
1118  const SHAPE_SEGMENT* seg = (const SHAPE_SEGMENT*) shape;
1119  int effectiveWidth = seg->GetWidth() + 2 * margin.x;
1120 
1121  if( effectiveWidth > 0 )
1122  m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, effectiveWidth );
1123  }
1124  break;
1125 
1126  case SH_CIRCLE:
1127  {
1128  const SHAPE_CIRCLE* circle = (const SHAPE_CIRCLE*) shape;
1129  int effectiveRadius = circle->GetRadius() + margin.x;
1130 
1131  if( effectiveRadius > 0 )
1132  m_gal->DrawCircle( circle->GetCenter(), effectiveRadius );
1133  }
1134  break;
1135 
1136  case SH_RECT:
1137  {
1138  const SHAPE_RECT* r = (const SHAPE_RECT*) shape;
1139  VECTOR2I pos = r->GetPosition();
1140  VECTOR2I effectiveMargin = margin;
1141 
1142  if( effectiveMargin.x < 0 )
1143  {
1144  // A negative margin just produces a smaller rect.
1145  VECTOR2I effectiveSize = r->GetSize() + effectiveMargin;
1146 
1147  if( effectiveSize.x > 0 && effectiveSize.y > 0 )
1148  m_gal->DrawRectangle( pos - effectiveMargin, pos + effectiveSize );
1149  }
1150  else if( effectiveMargin.x > 0 )
1151  {
1152  // A positive margin produces a larger rect, but with rounded corners
1153  m_gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() );
1154 
1155  // Use segments to produce the margin with rounded corners
1156  m_gal->DrawSegment( pos,
1157  pos + VECTOR2I( r->GetWidth(), 0 ),
1158  effectiveMargin.x * 2 );
1159  m_gal->DrawSegment( pos + VECTOR2I( r->GetWidth(), 0 ),
1160  pos + r->GetSize(),
1161  effectiveMargin.x * 2 );
1162  m_gal->DrawSegment( pos + r->GetSize(),
1163  pos + VECTOR2I( 0, r->GetHeight() ),
1164  effectiveMargin.x * 2 );
1165  m_gal->DrawSegment( pos + VECTOR2I( 0, r->GetHeight() ),
1166  pos,
1167  effectiveMargin.x * 2 );
1168  }
1169  else
1170  {
1171  m_gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() );
1172  }
1173  }
1174  break;
1175 
1176  case SH_SIMPLE:
1177  {
1178  const SHAPE_SIMPLE* poly = static_cast<const SHAPE_SIMPLE*>( shape );
1179 
1180  if( margin.x < 0 ) // The poly shape must be deflated
1181  {
1182  int maxError = bds.m_MaxError;
1183  int numSegs = GetArcToSegmentCount( -margin.x, maxError, 360.0 );
1184  SHAPE_POLY_SET outline;
1185  outline.NewOutline();
1186 
1187  for( int ii = 0; ii < poly->PointCount(); ++ii )
1188  outline.Append( poly->CPoint( ii ) );
1189 
1190  outline.Deflate( -margin.x, numSegs );
1191 
1192  m_gal->DrawPolygon( outline );
1193  }
1194  else
1195  {
1196  m_gal->DrawPolygon( poly->Vertices() );
1197  }
1198 
1199  // Now add on a rounded margin (using segments) if the margin > 0
1200  if( margin.x > 0 )
1201  {
1202  for( size_t ii = 0; ii < poly->GetSegmentCount(); ++ii )
1203  {
1204  SEG seg = poly->GetSegment( ii );
1205  m_gal->DrawSegment( seg.A, seg.B, margin.x * 2 );
1206  }
1207  }
1208  }
1209  break;
1210 
1211  default:
1212  // Better not get here; we already pre-flighted the shapes...
1213  break;
1214  }
1215  }
1216  }
1217  else
1218  {
1219  // This is expensive. Avoid if possible.
1220  SHAPE_POLY_SET polySet;
1221  aPad->TransformShapeWithClearanceToPolygon( polySet, ToLAYER_ID( aLayer ), margin.x,
1222  bds.m_MaxError, ERROR_INSIDE );
1223  m_gal->DrawPolygon( polySet );
1224  }
1225  }
1226 
1227  constexpr int clearanceFlags = PCB_RENDER_SETTINGS::CL_PADS;
1228 
1229  if( ( m_pcbSettings.m_clearanceDisplayFlags & clearanceFlags ) == clearanceFlags
1230  && ( aLayer == LAYER_PAD_FR || aLayer == LAYER_PAD_BK || aLayer == LAYER_PADS_TH ) )
1231  {
1232  /* Showing the clearance area is not obvious.
1233  * - A pad can be removed from some copper layers.
1234  * - For non copper layers, what is the clearance area?
1235  * So for copper layers, the clearance area is the shape if the pad is flashed on this
1236  * layer and the hole clearance area for other copper layers.
1237  * For other layers, use the pad shape, although one can use an other criteria,
1238  * depending on the non copper layer.
1239  */
1240  int activeLayer = m_pcbSettings.GetActiveLayer();
1241  bool flashActiveLayer = IsCopperLayer( activeLayer ) ?
1242  aPad->FlashLayer( activeLayer ) : true;
1243 
1244  if( flashActiveLayer || aPad->GetDrillSize().x )
1245  {
1247  m_gal->SetIsStroke( true );
1248  m_gal->SetIsFill( false );
1250 
1251  int clearance = aPad->GetOwnClearance( m_pcbSettings.GetActiveLayer() );
1252 
1253  if( flashActiveLayer && clearance > 0 )
1254  {
1255  auto shape = std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
1256 
1257  if( shape && shape->Size() == 1 && shape->Shapes()[0]->Type() == SH_SEGMENT )
1258  {
1259  const SHAPE_SEGMENT* seg = (SHAPE_SEGMENT*) shape->Shapes()[0];
1260  m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B,
1261  seg->GetWidth() + 2 * clearance );
1262  }
1263  else if( shape && shape->Size() == 1 && shape->Shapes()[0]->Type() == SH_CIRCLE )
1264  {
1265  const SHAPE_CIRCLE* circle = (SHAPE_CIRCLE*) shape->Shapes()[0];
1266  m_gal->DrawCircle( circle->GetCenter(), circle->GetRadius() + clearance );
1267  }
1268  else
1269  {
1270  SHAPE_POLY_SET polySet;
1271 
1272  // Use ERROR_INSIDE because it avoids Clipper and is therefore much faster.
1273  aPad->TransformShapeWithClearanceToPolygon( polySet, ToLAYER_ID( aLayer ),
1274  clearance,
1275  bds.m_MaxError, ERROR_INSIDE );
1276  m_gal->DrawPolygon( polySet );
1277  }
1278  }
1279  else if( aPad->GetEffectiveHoleShape() && clearance > 0 )
1280  {
1281  clearance += bds.GetHolePlatingThickness();
1282 
1283  const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape();
1284  m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B,
1285  seg->GetWidth() + 2 * clearance );
1286  }
1287  }
1288  }
1289 }
1290 
1291 
1292 void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
1293 {
1294  const COLOR4D& color = m_pcbSettings.GetColor( aShape, aShape->GetLayer() );
1295  bool sketch = m_pcbSettings.m_sketchGraphics;
1296  int thickness = getLineThickness( aShape->GetWidth() );
1297  VECTOR2D start( aShape->GetStart() );
1298  VECTOR2D end( aShape->GetEnd() );
1299 
1300  if( sketch )
1301  {
1302  m_gal->SetIsFill( false );
1303  m_gal->SetIsStroke( true );
1305  }
1306 
1307  m_gal->SetFillColor( color );
1309 
1310  switch( aShape->GetShape() )
1311  {
1313  if( sketch )
1314  {
1315  m_gal->DrawSegment( start, end, thickness );
1316  }
1317  else
1318  {
1319  m_gal->SetIsFill( true );
1320  m_gal->SetIsStroke( false );
1321 
1322  m_gal->DrawSegment( start, end, thickness );
1323  }
1324  break;
1325 
1326  case PCB_SHAPE_TYPE::RECT:
1327  {
1328  std::vector<wxPoint> pts = aShape->GetRectCorners();
1329 
1330  if( sketch )
1331  {
1332  m_gal->DrawSegment( pts[0], pts[1], thickness );
1333  m_gal->DrawSegment( pts[1], pts[2], thickness );
1334  m_gal->DrawSegment( pts[2], pts[3], thickness );
1335  m_gal->DrawSegment( pts[3], pts[0], thickness );
1336  }
1337  else
1338  {
1339  m_gal->SetIsFill( true );
1340  m_gal->SetIsStroke( false );
1341 
1342  if( thickness > 0 )
1343  {
1344  m_gal->DrawSegment( pts[0], pts[1], thickness );
1345  m_gal->DrawSegment( pts[1], pts[2], thickness );
1346  m_gal->DrawSegment( pts[2], pts[3], thickness );
1347  m_gal->DrawSegment( pts[3], pts[0], thickness );
1348  }
1349 
1350  if( aShape->IsFilled() )
1351  {
1352  SHAPE_POLY_SET poly;
1353  poly.NewOutline();
1354 
1355  for( const wxPoint& pt : pts )
1356  poly.Append( pt );
1357 
1358  m_gal->DrawPolygon( poly );
1359  }
1360  }
1361  }
1362  break;
1363 
1364  case PCB_SHAPE_TYPE::ARC:
1365  if( sketch )
1366  {
1367  m_gal->DrawArcSegment( start, aShape->GetRadius(),
1368  DECIDEG2RAD( aShape->GetArcAngleStart() ),
1369  DECIDEG2RAD( aShape->GetArcAngleStart() + aShape->GetAngle() ), // Change this
1370  thickness );
1371  }
1372  else
1373  {
1374  m_gal->SetIsFill( true );
1375  m_gal->SetIsStroke( false );
1376 
1377  m_gal->DrawArcSegment( start, aShape->GetRadius(),
1378  DECIDEG2RAD( aShape->GetArcAngleStart() ),
1379  DECIDEG2RAD( aShape->GetArcAngleStart() + aShape->GetAngle() ), // Change this
1380  thickness );
1381  }
1382  break;
1383 
1385  if( sketch )
1386  {
1387  m_gal->DrawCircle( start, aShape->GetRadius() - thickness / 2 );
1388  m_gal->DrawCircle( start, aShape->GetRadius() + thickness / 2 );
1389  }
1390  else
1391  {
1392  m_gal->SetIsFill( aShape->IsFilled() );
1393  m_gal->SetIsStroke( thickness > 0 );
1394  m_gal->SetLineWidth( thickness );
1395 
1396  m_gal->DrawCircle( start, aShape->GetRadius() );
1397  }
1398  break;
1399 
1401  {
1402  SHAPE_POLY_SET& shape = const_cast<PCB_SHAPE*>( aShape )->GetPolyShape();
1403  const FOOTPRINT* parentFootprint = aShape->GetParentFootprint();
1404 
1405  if( shape.OutlineCount() == 0 )
1406  break;
1407 
1408  if( parentFootprint )
1409  {
1410  m_gal->Save();
1411  m_gal->Translate( parentFootprint->GetPosition() );
1412  m_gal->Rotate( -parentFootprint->GetOrientationRadians() );
1413  }
1414 
1415  if( sketch )
1416  {
1417  for( int ii = 0; ii < shape.Outline( 0 ).SegmentCount(); ++ii )
1418  {
1419  SEG seg = shape.Outline( 0 ).Segment( ii );
1420  m_gal->DrawSegment( seg.A, seg.B, thickness );
1421  }
1422  }
1423  else
1424  {
1425  m_gal->SetIsFill( true );
1426  m_gal->SetIsStroke( false );
1427 
1428  if( thickness > 0 )
1429  {
1430  for( int ii = 0; ii < shape.Outline( 0 ).SegmentCount(); ++ii )
1431  {
1432  SEG seg = shape.Outline( 0 ).Segment( ii );
1433  m_gal->DrawSegment( seg.A, seg.B, thickness );
1434  }
1435  }
1436 
1437  if( aShape->IsFilled() )
1438  {
1439  // On Opengl, a not convex filled polygon is usually drawn by using triangles
1440  // as primitives. CacheTriangulation() can create basic triangle primitives to
1441  // draw the polygon solid shape on Opengl. GLU tessellation is much slower, so
1442  // currently we are using our tessellation.
1443  if( m_gal->IsOpenGlEngine() && !shape.IsTriangulationUpToDate() )
1444  shape.CacheTriangulation();
1445 
1446  m_gal->DrawPolygon( shape );
1447  }
1448  }
1449 
1450  if( parentFootprint )
1451  m_gal->Restore();
1452  }
1453  break;
1454 
1455  case PCB_SHAPE_TYPE::CURVE:
1456  if( sketch )
1457  {
1458  // Use thickness as filter value to convert the curve to polyline when the curve
1459  // is not supported
1460  m_gal->DrawCurve( VECTOR2D( aShape->GetStart() ),
1461  VECTOR2D( aShape->GetBezControl1() ),
1462  VECTOR2D( aShape->GetBezControl2() ),
1463  VECTOR2D( aShape->GetEnd() ), thickness );
1464  }
1465  else
1466  {
1467  m_gal->SetIsFill( aShape->IsFilled() );
1468  m_gal->SetIsStroke( thickness > 0 );
1469  m_gal->SetLineWidth( thickness );
1470 
1471  // Use thickness as filter value to convert the curve to polyline when the curve
1472  // is not supported
1473  m_gal->DrawCurve( VECTOR2D( aShape->GetStart() ),
1474  VECTOR2D( aShape->GetBezControl1() ),
1475  VECTOR2D( aShape->GetBezControl2() ),
1476  VECTOR2D( aShape->GetEnd() ), thickness );
1477  }
1478  break;
1479 
1480  case PCB_SHAPE_TYPE::LAST:
1481  break;
1482  }
1483 }
1484 
1485 
1486 void PCB_PAINTER::draw( const PCB_TEXT* aText, int aLayer )
1487 {
1488  wxString shownText( aText->GetShownText() );
1489 
1490  if( shownText.Length() == 0 )
1491  return;
1492 
1493  const COLOR4D& color = m_pcbSettings.GetColor( aText, aText->GetLayer() );
1494  VECTOR2D position( aText->GetTextPos().x, aText->GetTextPos().y );
1495 
1497  {
1498  // Outline mode
1500  }
1501  else
1502  {
1503  // Filled mode
1505  }
1506 
1508  m_gal->SetIsFill( false );
1509  m_gal->SetIsStroke( true );
1510  m_gal->SetTextAttributes( aText );
1511  m_gal->StrokeText( shownText, position, aText->GetTextAngleRadians() );
1512 }
1513 
1514 
1515 void PCB_PAINTER::draw( const FP_TEXT* aText, int aLayer )
1516 {
1517  wxString shownText( aText->GetShownText() );
1518 
1519  if( shownText.Length() == 0 )
1520  return;
1521 
1522  const COLOR4D& color = m_pcbSettings.GetColor( aText, aLayer );
1523  VECTOR2D position( aText->GetTextPos().x, aText->GetTextPos().y );
1524 
1526  {
1527  // Outline mode
1529  }
1530  else
1531  {
1532  // Filled mode
1534  }
1535 
1537  m_gal->SetIsFill( false );
1538  m_gal->SetIsStroke( true );
1539  m_gal->SetTextAttributes( aText );
1540  m_gal->StrokeText( shownText, position, aText->GetDrawRotationRadians() );
1541 
1542  // Draw the umbilical line
1543  if( aText->IsSelected() )
1544  {
1547  m_gal->DrawLine( position, aText->GetParent()->GetPosition() );
1548  }
1549 }
1550 
1551 
1552 void PCB_PAINTER::draw( const FOOTPRINT* aFootprint, int aLayer )
1553 {
1554  if( aLayer == LAYER_ANCHOR )
1555  {
1556  const COLOR4D color = m_pcbSettings.GetColor( aFootprint, aLayer );
1557 
1558  // Keep the size and width constant, not related to the scale because the anchor
1559  // is just a marker on screen
1560  double anchorSize = 5.0 / m_gal->GetWorldScale(); // 5 pixels size
1561  double anchorThickness = 1.0 / m_gal->GetWorldScale(); // 1 pixels width
1562 
1563  // Draw anchor
1564  m_gal->SetIsFill( false );
1565  m_gal->SetIsStroke( true );
1567  m_gal->SetLineWidth( anchorThickness );
1568 
1569  VECTOR2D center = aFootprint->GetPosition();
1570  m_gal->DrawLine( center - VECTOR2D( anchorSize, 0 ), center + VECTOR2D( anchorSize, 0 ) );
1571  m_gal->DrawLine( center - VECTOR2D( 0, anchorSize ), center + VECTOR2D( 0, anchorSize ) );
1572  }
1573 }
1574 
1575 
1576 void PCB_PAINTER::draw( const PCB_GROUP* aGroup, int aLayer )
1577 {
1578  if( aLayer == LAYER_ANCHOR )
1579  {
1580  if( aGroup->IsSelected() && !( aGroup->GetParent() && aGroup->GetParent()->IsSelected() ) )
1581  {
1582  // Selected on our own; draw enclosing box
1583  }
1584  else if( aGroup->IsEntered() )
1585  {
1586  // Entered group; draw enclosing box
1587  }
1588  else
1589  {
1590  return;
1591  }
1592 
1593  const COLOR4D color = m_pcbSettings.GetColor( aGroup, LAYER_ANCHOR );
1594 
1595  EDA_RECT bbox = aGroup->GetBoundingBox();
1598  wxPoint topLeft = bbox.GetPosition();
1599  wxPoint width = wxPoint( bbox.GetWidth(), 0 );
1600  wxPoint height = wxPoint( 0, bbox.GetHeight() );
1601 
1602  m_gal->DrawLine( topLeft, topLeft + width );
1603  m_gal->DrawLine( topLeft + width, topLeft + width + height );
1604  m_gal->DrawLine( topLeft + width + height, topLeft + height );
1605  m_gal->DrawLine( topLeft + height, topLeft );
1606 
1607  wxString name = aGroup->GetName();
1608 
1609  int ptSize = 12;
1610  int scaledSize = abs( KiROUND( m_gal->GetScreenWorldMatrix().GetScale().x * ptSize ) );
1611  int unscaledSize = Mils2iu( ptSize );
1612 
1613  // Scale by zoom a bit, but not too much
1614  int textSize = ( scaledSize + ( unscaledSize * 2 ) ) / 3;
1615  int penWidth = textSize / 10;
1616  wxPoint textOffset = wxPoint( width.x / 2, - KiROUND( textSize * 0.5 ) );
1617  wxPoint titleHeight = wxPoint( 0, KiROUND( textSize * 2.0 ) );
1618 
1619  if( !name.IsEmpty() && (int) aGroup->GetName().Length() * textSize < bbox.GetWidth() )
1620  {
1621  m_gal->DrawLine( topLeft, topLeft - titleHeight );
1622  m_gal->DrawLine( topLeft - titleHeight, topLeft + width - titleHeight );
1623  m_gal->DrawLine( topLeft + width - titleHeight, topLeft + width );
1624 
1625  m_gal->SetFontBold( false );
1626  m_gal->SetFontItalic( true );
1627  m_gal->SetFontUnderlined( false );
1631  m_gal->SetIsFill( false );
1632  m_gal->SetGlyphSize( VECTOR2D( textSize, textSize ) );
1633  m_gal->SetLineWidth( penWidth );
1634  m_gal->StrokeText( aGroup->GetName(), topLeft + textOffset, 0.0 );
1635  }
1636  }
1637 }
1638 
1639 
1640 void PCB_PAINTER::draw( const ZONE* aZone, int aLayer )
1641 {
1642  /*
1643  * aLayer will be the virtual zone layer (LAYER_ZONE_START, ... in GAL_LAYER_ID)
1644  * This is used for draw ordering in the GAL.
1645  * The color for the zone comes from the associated copper layer ( aLayer - LAYER_ZONE_START )
1646  * and the visibility comes from the combination of that copper layer and LAYER_ZONES
1647  */
1648  wxASSERT( IsZoneLayer( aLayer ) );
1649  PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( aLayer - LAYER_ZONE_START );
1650 
1651  if( !aZone->IsOnLayer( layer ) )
1652  return;
1653 
1654  COLOR4D color = m_pcbSettings.GetColor( aZone, layer );
1655  std::deque<VECTOR2D> corners;
1657 
1658  // Draw the outline
1659  const SHAPE_POLY_SET* outline = aZone->Outline();
1660 
1661  if( m_pcbSettings.m_zoneOutlines && outline && outline->OutlineCount() > 0 )
1662  {
1664  m_gal->SetIsFill( false );
1665  m_gal->SetIsStroke( true );
1667 
1668  // Draw each contour (main contour and holes)
1669 
1670  /* This line:
1671  * m_gal->DrawPolygon( *outline );
1672  * should be enough, but currently does not work to draw holes contours in a complex polygon
1673  * so each contour is draw as a simple polygon
1674  */
1675 
1676  // Draw the main contour
1677  m_gal->DrawPolyline( outline->COutline( 0 ) );
1678 
1679  // Draw holes
1680  int holes_count = outline->HoleCount( 0 );
1681 
1682  for( int ii = 0; ii < holes_count; ++ii )
1683  m_gal->DrawPolyline( outline->CHole( 0, ii ) );
1684 
1685  // Draw hatch lines
1686  for( const SEG& hatchLine : aZone->GetHatchLines() )
1687  m_gal->DrawLine( hatchLine.A, hatchLine.B );
1688  }
1689 
1690  // Draw the filling
1691  if( displayMode == ZONE_DISPLAY_MODE::SHOW_FILLED
1692  || displayMode == ZONE_DISPLAY_MODE::SHOW_FILLED_OUTLINE )
1693  {
1694  const SHAPE_POLY_SET& polySet = aZone->GetFilledPolysList( layer );
1695 
1696  if( polySet.OutlineCount() == 0 ) // Nothing to draw
1697  return;
1698 
1699  // Set up drawing options
1700  int outline_thickness = 0;
1701 
1702  if( aZone->GetFilledPolysUseThickness( layer ) )
1703  outline_thickness = aZone->GetMinThickness();
1704 
1706  m_gal->SetFillColor( color );
1707  m_gal->SetLineWidth( outline_thickness );
1708 
1709  if( displayMode == ZONE_DISPLAY_MODE::SHOW_FILLED )
1710  {
1711  m_gal->SetIsFill( true );
1712  m_gal->SetIsStroke( outline_thickness > 0 );
1713  }
1714  else if( displayMode == ZONE_DISPLAY_MODE::SHOW_FILLED_OUTLINE )
1715  {
1716  m_gal->SetIsFill( false );
1717  m_gal->SetIsStroke( true );
1718  }
1719 
1720  m_gal->DrawPolygon( polySet );
1721  }
1722 }
1723 
1724 
1725 void PCB_PAINTER::draw( const PCB_DIMENSION_BASE* aDimension, int aLayer )
1726 {
1727  const COLOR4D& strokeColor = m_pcbSettings.GetColor( aDimension, aLayer );
1728 
1729  m_gal->SetStrokeColor( strokeColor );
1730  m_gal->SetIsFill( false );
1731  m_gal->SetIsStroke( true );
1732 
1734  {
1735  // Outline mode
1737  }
1738  else
1739  {
1740  // Filled mode
1741  m_gal->SetLineWidth( getLineThickness( aDimension->GetLineThickness() ) );
1742  }
1743 
1744  // Draw dimension shapes
1745  // TODO(JE) lift this out
1746  for( const std::shared_ptr<SHAPE>& shape : aDimension->GetShapes() )
1747  {
1748  switch( shape->Type() )
1749  {
1750  case SH_SEGMENT:
1751  {
1752  const SEG& seg = static_cast<const SHAPE_SEGMENT*>( shape.get() )->GetSeg();
1753  m_gal->DrawLine( seg.A, seg.B );
1754  break;
1755  }
1756 
1757  case SH_CIRCLE:
1758  {
1759  int radius = static_cast<const SHAPE_CIRCLE*>( shape.get() )->GetRadius();
1760  m_gal->DrawCircle( shape->Centre(), radius );
1761  break;
1762  }
1763 
1764  default:
1765  break;
1766  }
1767  }
1768 
1769  // Draw text
1770  const PCB_TEXT& text = aDimension->Text();
1771  VECTOR2D position( text.GetTextPos().x, text.GetTextPos().y );
1772 
1774  {
1775  // Outline mode
1777  }
1778  else
1779  {
1780  // Filled mode
1781  m_gal->SetLineWidth( getLineThickness( text.GetEffectiveTextPenWidth() ) );
1782  }
1783 
1785  m_gal->StrokeText( text.GetShownText(), position, text.GetTextAngleRadians() );
1786 }
1787 
1788 
1789 void PCB_PAINTER::draw( const PCB_TARGET* aTarget )
1790 {
1791  const COLOR4D& strokeColor = m_pcbSettings.GetColor( aTarget, aTarget->GetLayer() );
1792  VECTOR2D position( aTarget->GetPosition() );
1793  double size, radius;
1794 
1795  m_gal->SetLineWidth( getLineThickness( aTarget->GetWidth() ) );
1796  m_gal->SetStrokeColor( strokeColor );
1797  m_gal->SetIsFill( false );
1798  m_gal->SetIsStroke( true );
1799 
1800  m_gal->Save();
1801  m_gal->Translate( position );
1802 
1803  if( aTarget->GetShape() )
1804  {
1805  // shape x
1806  m_gal->Rotate( M_PI / 4.0 );
1807  size = 2.0 * aTarget->GetSize() / 3.0;
1808  radius = aTarget->GetSize() / 2.0;
1809  }
1810  else
1811  {
1812  // shape +
1813  size = aTarget->GetSize() / 2.0;
1814  radius = aTarget->GetSize() / 3.0;
1815  }
1816 
1817  m_gal->DrawLine( VECTOR2D( -size, 0.0 ), VECTOR2D( size, 0.0 ) );
1818  m_gal->DrawLine( VECTOR2D( 0.0, -size ), VECTOR2D( 0.0, size ) );
1819  m_gal->DrawCircle( VECTOR2D( 0.0, 0.0 ), radius );
1820 
1821  m_gal->Restore();
1822 }
1823 
1824 
1825 void PCB_PAINTER::draw( const PCB_MARKER* aMarker, int aLayer )
1826 {
1827  bool isShadow = aLayer == LAYER_MARKER_SHADOWS;
1828 
1829  // Don't paint shadows for invisible markers.
1830  // It would be nice to do this through layer dependencies but we can't do an "or" there today
1831  if( isShadow && aMarker->GetBoard()
1832  && !aMarker->GetBoard()->IsElementVisible( aMarker->GetColorLayer() ) )
1833  {
1834  return;
1835  }
1836 
1837  SHAPE_LINE_CHAIN polygon;
1838  aMarker->ShapeToPolygon( polygon );
1839 
1841  : aMarker->GetColorLayer() );
1842 
1843  m_gal->Save();
1844  m_gal->Translate( aMarker->GetPosition() );
1845 
1846  if( isShadow )
1847  {
1849  m_gal->SetIsStroke( true );
1850  m_gal->SetLineWidth( aMarker->MarkerScale() );
1851  }
1852  else
1853  {
1854  m_gal->SetFillColor( color );
1855  m_gal->SetIsFill( true );
1856  }
1857 
1858  m_gal->DrawPolygon( polygon );
1859  m_gal->Restore();
1860 }
1861 
1862 
1863 const double PCB_RENDER_SETTINGS::MAX_FONT_SIZE = Millimeter2iu( 10.0 );
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
virtual const SEG GetSegment(int aIndex) const override
Definition: shape_simple.h:185
virtual void DrawPolyline(const std::deque< VECTOR2D > &aPointList)
Draw a polyline.
Virtual layers for stacking zones and tracks on a given copper layer.
Filled polygons are shown.
virtual wxPoint GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_track.h:282
to draw blind/buried vias
virtual void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a rectangle.
bool IsFilled() const
Definition: pcb_shape.h:75
SHAPE_SIMPLE.
Definition: shape_simple.h:43
SHAPE_POLY_SET GetBoundingHull() const
Return a bounding polygon for the shapes and pads in the footprint.
Definition: footprint.cpp:746
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition: typeinfo.h:100
virtual void LoadColors(const COLOR_SETTINGS *aSettings) override
Definition: pcb_painter.cpp:90
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:101
const VECTOR2I & CPoint(int aIndex) const
Function Point()
Definition: shape_simple.h:107
double GetOrientationRadians() const
Definition: footprint.h:183
int OutlineCount() const
Return the number of vertices in a given outline/hole.
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
COLOR4D Inverted() const
Returns an inverted color, alpha remains the same.
Definition: color4d.h:317
int GetRadius() const
Definition: shape_circle.h:107
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:194
COLOR4D & Brighten(double aFactor)
Makes the color brighter by a given factor.
Definition: color4d.h:209
bool IsSelected() const
Definition: eda_item.h:123
bool FlashLayer(int aLayer) const
Checks to see whether the via should have a pad on the specific layer.
Definition: pcb_track.cpp:520
const wxPoint & GetEnd() const
Definition: pcb_track.h:105
multilayer pads, usually with holes
const MATRIX3x3D & GetScreenWorldMatrix() const
Get the screen <-> world transformation matrix.
const wxPoint & GetEnd() const
Return the ending point of the graphic.
Definition: pcb_shape.h:134
int GetNetnameLayer(int aLayer)
Returns a netname layer corresponding to the given layer.
virtual void BitmapText(const wxString &aText, const VECTOR2D &aPosition, double aRotationAngle)
Draw a text using a bitmap font.
double m_zoneOpacity
Opacity override for filled zones.
Definition: pcb_painter.h:234
COLOR4D m_layerColorsHi[LAYER_ID_COUNT]
COLOR4D m_layerColors[LAYER_ID_COUNT]
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:108
VIATYPE GetViaType() const
Definition: pcb_track.h:354
Outlines of filled polygons are shown.
double m_TrackOpacity
Opacity override for all tracks.
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:50
to draw via holes (pad holes do not use this layer)
PCB_TEXT & Text()
handle color for not plated holes (holes, not pads)
anchor of items having an anchor point (texts, footprints)
int GetSize() const
Definition: pcb_target.h:62
bool IsFlippedX() const
Return true if flip flag for the X axis is set.
PCB_SHAPE_TYPE GetShape() const
Definition: pcb_shape.h:110
virtual void SetTextAttributes(const EDA_TEXT *aText)
Loads attributes of the given text (bold/italic/underline/mirrored and so on).
int GetHolePlatingThickness() const
Pad & via drills are finish size.
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:102
virtual void DrawArc(const VECTOR2D &aCenterPoint, double aRadius, double aStartAngle, double aEndAngle)
Draw an arc.
bool m_sketchMode[GAL_LAYER_ID_END]
Definition: pcb_painter.h:196
SHAPE_POLY_SET * Outline()
Definition: zone.h:317
int GetRadius() const
Return the radius of this item.
Definition: pcb_shape.cpp:445
int color
Definition: DXF_plotter.cpp:60
std::vector< wxPoint > GetRectCorners() const
Definition: pcb_shape.cpp:998
int GetWidth() const
Definition: pcb_shape.h:97
double m_ViaOpacity
Opacity override for all types of via.
double GetArcAngleStart() const
Definition: pcb_shape.cpp:416
void SetFontBold(bool aBold)
Set bold property of current font.
Net/netclass colors are shown on all net copper.
Net/netclass colors are shown on ratsnest lines only.
int GetWidth() const
Definition: eda_rect.h:109
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:305
const std::vector< std::shared_ptr< SHAPE > > & GetShapes() const
const SHAPE_SEGMENT * GetEffectiveHoleShape() const
Return a SHAPE object representing the pad's hole.
Definition: pad.cpp:289
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Test to see if this object is on the given layer.
Definition: zone.cpp:316
bool IsBrightened() const
Definition: eda_item.h:126
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
class PAD, a pad in a footprint
Definition: typeinfo.h:89
bool IsNetCopperLayer(LAYER_NUM aLayer)
Checks if the given layer is "net copper", meaning it is eligible for net coloring.
Abstract dimension API.
Definition: pcb_dimension.h:95
const SHAPE_POLY_SET & GetFilledPolysList(PCB_LAYER_ID aLayer) const
Definition: zone.h:632
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
const VECTOR2I GetCenter() const
Definition: shape_circle.h:112
int GetWidth() const
Definition: pcb_track.h:102
PCB_RENDER_SETTINGS m_pcbSettings
Definition: pcb_painter.h:295
const EDA_RECT GetBoundingBox() const override
May be re-implemented for each derived class in order to handle all the types given by its member dat...
Definition: pcb_group.cpp:210
virtual wxPoint GetPosition() const
Definition: eda_item.h:252
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:81
virtual void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a line.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:588
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
Definition: matrix3x3.h:269
bool IsTriangulationUpToDate() const
virtual wxString GetNetClassName() const
Returns the netclass of the zone.
std::set< unsigned int > m_highContrastLayers
GAL * m_gal
Instance of graphic abstraction layer that gives an interface to call commands used to draw (eg.
Definition: painter.h:101
const SEG & GetSeg() const
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
int GetEffectiveTextPenWidth(int aDefaultWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultWidth.
Definition: eda_text.cpp:149
virtual void SetLineWidth(float aLineWidth)
Set the line width.
virtual void Rotate(double aAngle)
Rotate the context.
Ratsnest lines are drawn to items on all layers (default)
TRACE_CLEARANCE_DISPLAY_MODE_T m_ShowTrackClearanceMode
How trace clearances are displayed.
Plated through hole pad.
virtual VECTOR2D getDrillSize(const PAD *aPad) const
Return drill size for a pad (internal units).
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:222
const VECTOR2I GetSize() const
Definition: shape_rect.h:124
polygon (not yet used for tracks, but could be in microwave apps)
wxPoint GetPosition() const override
Definition: pcb_target.h:56
NET_COLOR_MODE m_netColorMode
Overrides for specific netclass colors.
Definition: pcb_painter.h:219
wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: pcb_text.cpp:56
const wxPoint GetEnd() const
Definition: eda_rect.h:103
RATSNEST_MODE m_RatsnestMode
Ratsnest draw mode (all layers vs only visible layers)
int GetWidth() const
Definition: pcb_target.h:65
const wxSize & GetDrillSize() const
Definition: pad.h:239
Container for display options like enable/disable some optional drawings.
PCB_LAYER_ID
A quick note on layer IDs:
Contains all the knowledge about how to draw graphical object onto any particular output device.
Definition: painter.h:57
double a
Alpha component.
Definition: color4d.h:366
bool FlashLayer(int aLayer) const
Check to see whether the pad should be flashed on the specific layer.
Definition: pad.cpp:206
bool IsEntered() const
Definition: eda_item.h:124
int getLineThickness(int aActualThickness) const
Get the thickness to draw for a line (e.g.
double GetDrawRotationRadians() const
Definition: fp_text.h:175
bool GetDrawIndividualViaLayers() const
Definition: pcb_painter.h:174
COLOR4D m_layerColorsDark[LAYER_ID_COUNT]
int GetMinThickness() const
Definition: zone.h:241
virtual void DrawSegment(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint, double aWidth)
Draw a rounded segment.
void ResetTextAttributes()
Reset text attributes to default styling.
const std::vector< SEG > & GetHatchLines() const
Definition: zone.h:797
wxString GetShortNetname() const
#define NULL
VECTOR2< double > VECTOR2D
Definition: vector2d.h:622
static const double MAX_FONT_SIZE
< Maximum font size for netnames (and other dynamically shown strings)
Definition: pcb_painter.h:194
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
wxString GetName() const
Definition: pcb_group.h:65
bool m_hiContrastEnabled
Parameters for display modes.
virtual void update()
Precalculates extra colors for layers (e.g.
double GetArcAngleStart() const
Definition: pcb_track.cpp:988
Represent a set of closed polygons.
static const COLOR4D CLEAR
Definition: color4d.h:374
SHAPE_LINE_CHAIN & Outline(int aIndex)
const wxPoint GetOrigin() const
Definition: eda_rect.h:101
bool IsZoneLayer(LAYER_NUM aLayer)
const VECTOR2I & GetPosition() const
Definition: shape_rect.h:116
virtual void StrokeText(const wxString &aText, const VECTOR2D &aPosition, double aRotationAngle)
Draw a vector type text using preloaded Newstroke font.
double GetRadius() const
Definition: pcb_track.cpp:970
const wxPoint GetPosition() const
Definition: eda_rect.h:102
void SetBackgroundColor(const COLOR4D &aColor) override
Set the background color.
Definition: pcb_painter.h:150
segment with non rounded ends
const wxSize & GetSize() const
Definition: pad.h:229
to draw usual through hole vias
Inactive layers are shown normally (no high-contrast mode)
const wxPoint & GetStart() const
Return the starting point of the graphic.
Definition: pcb_shape.h:124
virtual BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:50
const wxString & GetName() const
Definition: pad.h:130
void Deflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
last value for this list
const EDA_RECT GetBoundingBox() const override
The bounding box is cached, so this will be efficient most of the time.
Definition: pad.cpp:521
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
Definition: pcb_track.cpp:461
RATSNEST_MODE m_ratsnestDisplayMode
Definition: pcb_painter.h:214
const wxString & GetPinType() const
Definition: pad.h:142
PAD_SHAPE GetShape() const
Definition: pad.h:166
const SHAPE_LINE_CHAIN & Vertices() const
Function Vertices()
Definition: shape_simple.h:133
Definition: color4d.h:58
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: pad.cpp:280
virtual bool IsOpenGlEngine()
Return true if the GAL engine is a OpenGL based type.
a few functions useful in geometry calculations.
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
class ZONE, a copper pour area
Definition: typeinfo.h:105
An abstract shape on 2D plane.
Definition: shape.h:116
double m_viaOpacity
Opacity override for all types of via.
Definition: pcb_painter.h:232
void SetVerticalJustify(const EDA_TEXT_VJUSTIFY_T aVerticalJustify)
Set the vertical justify for text drawing.
void SetFontItalic(bool aItalic)
Set italic property of current font.
GAL_LAYER_ID GetColorLayer() const
Definition: pcb_marker.cpp:180
int NewOutline()
Creates a new hole in a given outline.
int HoleCount(int aOutline) const
Return the reference to aIndex-th outline in the set.
int SegmentCount() const
Function SegmentCount()
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
int GetHeight() const
Definition: eda_rect.h:110
circle
Definition: shape.h:46
double m_ZoneOpacity
Opacity override for filled zone areas.
void SetGlyphSize(const VECTOR2D &aSize)
Set the font glyph size.
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:104
int m_clearanceDisplayFlags
How to display nets and netclasses with color overrides.
Definition: pcb_painter.h:216
class FOOTPRINT, a footprint
Definition: typeinfo.h:88
bool IsElementVisible(GAL_LAYER_ID aLayer) const
Test whether a given element category is visible.
Definition: board.cpp:531
int GetSolderMaskMargin() const
Definition: pad.cpp:700
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...
Definition: seg.h:40
virtual size_t GetSegmentCount() const override
Definition: shape_simple.h:187
double GetTextAngleRadians() const
Definition: eda_text.h:184
void SetTextMirrored(bool aMirrored)
Set a mirrored property of text.
static LSET PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition: lset.cpp:849
int MarkerScale() const
The scaling factor to convert polygonal shape coordinates to internal units.
Definition: marker_base.h:66
COLOR4D GetColor(int aLayer) const
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aMaxError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
SEG Segment(int aIndex)
Function Segment()
double m_trackOpacity
Opacity override for all tracks.
Definition: pcb_painter.h:231
double m_PadOpacity
Opacity override for SMD pads and PTHs.
double GetAngle() const
Definition: pcb_track.cpp:976
class PCB_MARKER, a marker used to show something
Definition: typeinfo.h:98
smd pads, front layer
virtual void Restore()
Restore the context.
std::map< int, KIGFX::COLOR4D > m_netColors
Set of net codes that should not have their ratsnest displayed.
Definition: pcb_painter.h:225
virtual void DrawPolygon(const std::deque< VECTOR2D > &aPointList)
Draw a polygon.
Board layer functions and definitions.
void SetFontUnderlined(bool aUnderlined)
const char * name
Definition: DXF_plotter.cpp:59
wxSize GetSolderPasteMargin() const
Usually < 0 (mask shape smaller than pad)because the margin can be dependent on the pad size,...
Definition: pad.cpp:745
virtual void DrawCircle(const VECTOR2D &aCenterPoint, double aRadius)
Draw a circle using world coordinates.
FOOTPRINT * GetParentFootprint() const
Return the parent footprint or NULL if PCB_SHAPE does not belong to a footprint.
Definition: pcb_shape.cpp:490
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: pad.h:351
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
SHAPE_LINE_CHAIN.
COLOR4D & Darken(double aFactor)
Makes the color darker by a given factor.
Definition: color4d.h:226
wxString UnescapeString(const wxString &aSource)
Definition: string.cpp:214
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
void LoadDisplayOptions(const PCB_DISPLAY_OPTIONS &aOptions, bool aShowPageLimits)
Load settings related to display options (high-contrast mode, full or outline modes for vias/pads/tra...
const wxPoint & GetBezControl2() const
Definition: pcb_shape.h:116
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
virtual 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...
class ZONE, managed by a footprint
Definition: typeinfo.h:94
VECTOR2I A
Definition: seg.h:48
int PointCount() const
Function PointCount()
Definition: shape_simple.h:93
double GetAngle() const
Definition: pcb_shape.h:107
Handle the component boundary box.
Definition: eda_rect.h:42
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition: color4d.h:369
double DECIDEG2RAD(double deg)
Definition: trigo.h:235
bool IsHoleLayer(LAYER_NUM aLayer)
ZONE_DISPLAY_MODE m_ZoneDisplayMode
int GetShape() const
Definition: pcb_target.h:59
HIGH_CONTRAST_MODE m_contrastModeDisplay
Definition: pcb_painter.h:213
usual segment : line with rounded ends
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:70
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
PCB_LAYER_ID GetActiveLayer() const
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.
wxPoint GetPosition() const override
Definition: footprint.h:177
virtual int GetOwnClearance(PCB_LAYER_ID aLayer, wxString *aSource=nullptr) const
Return an item's "own" clearance in internal units.
wxPoint Centre() const
Definition: eda_rect.h:55
PCB_PAINTER(GAL *aGal)
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Color settings are a bit different than most of the settings objects in that there can be more than o...
double m_padOpacity
Opacity override for SMD pads and PTHs.
Definition: pcb_painter.h:233
const wxPoint & GetTextPos() const
Definition: eda_text.h:254
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
virtual void DrawArcSegment(const VECTOR2D &aCenterPoint, double aRadius, double aStartAngle, double aEndAngle, double aWidth)
Draw an arc segment.
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
Definition: pcb_track.cpp:193
virtual BOARD_ITEM * Duplicate() const
Create a copy of this BOARD_ITEM.
Definition: board_item.h:200
const int GetHeight() const
Definition: shape_rect.h:140
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:103
void CacheTriangulation(bool aPartition=true)
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293
axis-aligned rectangle
Definition: shape.h:43
Inactive layers are hidden.
PCB_LAYER_ID GetPrimaryHighContrastLayer() const
Return the board layer which is in high-contrast mode.
virtual void Save()
Save the context.
void SetHorizontalJustify(const EDA_TEXT_HJUSTIFY_T aHorizontalJustify)
Set the horizontal justify for text drawing.
virtual const EDA_RECT GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:75
const int GetWidth() const
Definition: shape_rect.h:132
Definition: pad.h:57
virtual int getDrillShape(const PAD *aPad) const
Return drill shape of a pad.
Arcs (with rounded ends)
double GetWorldScale() const
Get the world scale.
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:166
virtual void Translate(const VECTOR2D &aTranslation)
Translate 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 SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
virtual wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: fp_text.cpp:414
int GetWidth() const
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
wxPoint GetPosition() const override
Definition: pcb_marker.h:67
static constexpr int Millimeter2iu(double mm)
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:171
static const int UNCONNECTED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
Definition: netinfo.h:365
std::set< int > m_highlightNetcodes
const wxPoint & GetBezControl1() const
Definition: pcb_shape.h:113
Definition of PCB_DISPLAY_OPTIONS class.
simple polygon
Definition: shape.h:47
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
ZONE_DISPLAY_MODE m_zoneDisplayMode
Definition: pcb_painter.h:212
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:905
int GetLineThickness() const
void draw(const PCB_TRACK *aTrack, int aLayer)
Additional netnames layers (not associated with a PCB layer)
const wxPoint & GetStart() const
Definition: pcb_track.h:108
COLOR4D m_layerColorsSel[LAYER_ID_COUNT]
const wxSize GetSize() const
Definition: eda_rect.h:91
bool IsNetnameLayer(LAYER_NUM aLayer)
Test whether a layer is a netname layer.
NET_COLOR_MODE m_NetColorMode
How to use color overrides on specific nets and netclasses.
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
line segment
Definition: shape.h:44
Abstract interface for drawing on a 2D-surface.
bool GetFilledPolysUseThickness() const
Definition: zone.h:686
Container for design settings for a BOARD object.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Add a new vertex to the contour indexed by aOutline and aHole (defaults to the outline of the last po...
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103
VECTOR2I B
Definition: seg.h:49