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 <string_utils.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 
44 #include <layer_ids.h>
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] = aSettings->GetColor( F_Cu );
113  m_layerColors[LAYER_PAD_BK] = aSettings->GetColor( B_Cu );
114  m_layerColors[LAYER_PAD_FR_NETNAMES] = COLOR4D( 1.0, 1.0, 1.0, 0.9 );
115  m_layerColors[LAYER_PAD_BK_NETNAMES] = COLOR4D( 1.0, 1.0, 1.0, 0.9 );
116 
117  // Netnames for copper layers
118  for( LSEQ cu = LSET::AllCuMask().CuStack(); cu; ++cu )
119  {
120  const COLOR4D lightLabel( 0.8, 0.8, 0.8, 0.7 );
121  const COLOR4D darkLabel = lightLabel.Inverted();
122  PCB_LAYER_ID layer = *cu;
123 
124  if( m_layerColors[layer].GetBrightness() > 0.5 )
125  m_layerColors[GetNetnameLayer( layer )] = darkLabel;
126  else
127  m_layerColors[GetNetnameLayer( layer )] = lightLabel;
128  }
129 
130  update();
131 }
132 
133 
135  bool aShowPageLimits )
136 {
139  m_padNumbers = aOptions.m_DisplayPadNum;
141  m_sketchText = !aOptions.m_DisplayTextFill;
144 
145  // Whether to draw tracks, vias & pads filled or as outlines
151 
152  // Net names display settings
153  switch( aOptions.m_DisplayNetNamesMode )
154  {
155  case 0:
156  m_netNamesOnPads = false;
157  m_netNamesOnTracks = false;
158  m_netNamesOnVias = false;
159  break;
160 
161  case 1:
162  m_netNamesOnPads = true;
163  m_netNamesOnTracks = false;
164  m_netNamesOnVias = true; // Follow pads or tracks? For now we chose pads....
165  break;
166 
167  case 2:
168  m_netNamesOnPads = false;
169  m_netNamesOnTracks = true;
170  m_netNamesOnVias = false; // Follow pads or tracks? For now we chose pads....
171  break;
172 
173  case 3:
174  m_netNamesOnPads = true;
175  m_netNamesOnTracks = true;
176  m_netNamesOnVias = true;
177  break;
178  }
179 
180  // Zone display settings
182 
183  // Clearance settings
184  switch( aOptions.m_ShowTrackClearanceMode )
185  {
188  break;
189 
192  break;
193 
196  break;
197 
200  break;
201 
204  break;
205  }
206 
207  if( aOptions.m_DisplayPadClearance )
209 
211 
212  m_netColorMode = aOptions.m_NetColorMode;
213 
215 
216  m_trackOpacity = aOptions.m_TrackOpacity;
217  m_viaOpacity = aOptions.m_ViaOpacity;
218  m_padOpacity = aOptions.m_PadOpacity;
219  m_zoneOpacity = aOptions.m_ZoneOpacity;
220 
221  m_showPageLimits = aShowPageLimits;
222 }
223 
224 
225 COLOR4D PCB_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) const
226 {
227  const EDA_ITEM* item = dynamic_cast<const EDA_ITEM*>( aItem );
228  const BOARD_CONNECTED_ITEM* conItem = dynamic_cast<const BOARD_CONNECTED_ITEM*> ( aItem );
229  int netCode = -1;
230  int originalLayer = aLayer;
231 
232  // Marker shadows
233  if( aLayer == LAYER_MARKER_SHADOWS )
234  return m_backgroundColor.WithAlpha( 0.6 );
235 
236  if( IsHoleLayer( aLayer ) && m_isPrinting )
237  {
238  // Careful that we don't end up with the same colour for the annular ring and the hole
239  // when printing in B&W.
240  const PAD* pad = dynamic_cast<const PAD*>( item );
241  const PCB_VIA* via = dynamic_cast<const PCB_VIA*>( item );
242  int holeLayer = aLayer;
243  int annularRingLayer = UNDEFINED_LAYER;
244 
245  if( pad && pad->GetAttribute() == PAD_ATTRIB::PTH )
246  annularRingLayer = LAYER_PADS_TH;
247  else if( via && via->GetViaType() == VIATYPE::MICROVIA )
248  annularRingLayer = LAYER_VIA_MICROVIA;
249  else if( via && via->GetViaType() == VIATYPE::BLIND_BURIED )
250  annularRingLayer = LAYER_VIA_BBLIND;
251  else if( via && via->GetViaType() == VIATYPE::THROUGH )
252  annularRingLayer = LAYER_VIA_THROUGH;
253 
254  if( annularRingLayer != UNDEFINED_LAYER
255  && m_layerColors[ holeLayer ] == m_layerColors[ annularRingLayer ] )
256  {
257  aLayer = LAYER_PCB_BACKGROUND;
258  }
259  }
260 
261  // Zones should pull from the copper layer
262  if( item && ( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T ) )
263  {
264  if( IsZoneLayer( aLayer ) )
265  aLayer = aLayer - LAYER_ZONE_START;
266  }
267 
268  // Hole walls should pull from the copper layer
269  if( aLayer == LAYER_PAD_HOLEWALLS )
270  aLayer = LAYER_PADS_TH;
271  else if( aLayer == LAYER_VIA_HOLEWALLS )
272  aLayer = LAYER_VIA_THROUGH;
273 
274  // Normal path: get the layer base color
275  COLOR4D color = m_layerColors[aLayer];
276 
277  if( !item )
278  return m_layerColors[aLayer];
279 
280  // Selection disambiguation
281  if( item->IsBrightened() )
282  return color.Brightened( m_selectFactor ).WithAlpha( 0.8 );
283 
284  // Normal selection
285  if( item->IsSelected() )
286  color = m_layerColorsSel[aLayer];
287 
288  // Try to obtain the netcode for the item
289  if( conItem )
290  netCode = conItem->GetNetCode();
291 
292  bool highlighted = m_highlightEnabled && m_highlightNetcodes.count( netCode );
293  bool selected = item->IsSelected();
294 
295  // Apply net color overrides
296  if( conItem && m_netColorMode == NET_COLOR_MODE::ALL && IsNetCopperLayer( aLayer ) )
297  {
298  COLOR4D netColor = COLOR4D::UNSPECIFIED;
299 
300  auto ii = m_netColors.find( netCode );
301 
302  if( ii != m_netColors.end() )
303  netColor = ii->second;
304 
305  if( netColor == COLOR4D::UNSPECIFIED )
306  {
307  auto jj = m_netclassColors.find( conItem->GetNetClassName() );
308 
309  if( jj != m_netclassColors.end() )
310  netColor = jj->second;
311  }
312 
313  if( netColor == COLOR4D::UNSPECIFIED )
314  {
315  netColor = color;
316  }
317  else if( selected )
318  {
319  // Selection brightening overrides highlighting
320  netColor.Brighten( m_selectFactor );
321  }
322  else if( m_highlightEnabled )
323  {
324  // Highlight brightens objects on all layers and darkens everything else for contrast
325  if( highlighted )
326  netColor.Brighten( m_highlightFactor );
327  else
328  netColor.Darken( 1.0 - m_highlightFactor );
329  }
330 
331  color = netColor;
332  }
333  else if( !selected && m_highlightEnabled )
334  {
335  // Single net highlight mode
336  color = m_highlightNetcodes.count( netCode ) ? m_layerColorsHi[aLayer]
337  : m_layerColorsDark[aLayer];
338  }
339 
340  // Apply high-contrast dimming
341  if( m_hiContrastEnabled && m_highContrastLayers.size() && !highlighted && !selected )
342  {
344  bool isActive = m_highContrastLayers.count( aLayer );
345 
346  switch( originalLayer )
347  {
348  case LAYER_PADS_TH:
349  if( !static_cast<const PAD*>( item )->FlashLayer( primary ) )
350  isActive = false;
351 
352  break;
353 
354  case LAYER_VIA_BBLIND:
355  case LAYER_VIA_MICROVIA:
356  // Target graphic is active if the via crosses the primary layer
357  if( static_cast<const PCB_VIA*>( item )->GetLayerSet().test( primary ) == 0 )
358  isActive = false;
359 
360  break;
361 
362  case LAYER_VIA_THROUGH:
363  if( !static_cast<const PCB_VIA*>( item )->FlashLayer( primary ) )
364  isActive = false;
365 
366  break;
367 
369  case LAYER_PAD_HOLEWALLS:
371  // Pad holes are active is any physical layer is active
372  if( LSET::PhysicalLayersMask().test( primary ) == 0 )
373  isActive = false;
374 
375  break;
376 
377  case LAYER_VIA_HOLES:
378  case LAYER_VIA_HOLEWALLS:
379  if( static_cast<const PCB_VIA*>( item )->GetViaType() == VIATYPE::BLIND_BURIED
380  || static_cast<const PCB_VIA*>( item )->GetViaType() == VIATYPE::MICROVIA )
381  {
382  // A blind or micro via's hole is active if it crosses the primary layer
383  if( static_cast<const PCB_VIA*>( item )->GetLayerSet().test( primary ) == 0 )
384  isActive = false;
385  }
386  else
387  {
388  // A through via's hole is active if any physical layer is active
389  if( LSET::PhysicalLayersMask().test( primary ) == 0 )
390  isActive = false;
391  }
392 
393  break;
394 
395  default:
396  break;
397  }
398 
399  if( !isActive )
400  {
403  else
405  }
406  }
407 
408  // Apply per-type opacity overrides
409  if( item->Type() == PCB_TRACE_T || item->Type() == PCB_ARC_T )
410  color.a *= m_trackOpacity;
411  else if( item->Type() == PCB_VIA_T )
412  color.a *= m_viaOpacity;
413  else if( item->Type() == PCB_PAD_T )
414  color.a *= m_padOpacity;
415  else if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
416  color.a *= m_zoneOpacity;
417 
418  // No special modifiers enabled
419  return color;
420 }
421 
422 
424  PAINTER( aGal ),
425  m_maxError( ARC_HIGH_DEF ),
426  m_holePlatingThickness( 0 )
427 {
428 }
429 
430 
431 int PCB_PAINTER::getLineThickness( int aActualThickness ) const
432 {
433  // if items have 0 thickness, draw them with the outline
434  // width, otherwise respect the set value (which, no matter
435  // how small will produce something)
436  if( aActualThickness == 0 )
438 
439  return aActualThickness;
440 }
441 
442 
443 int PCB_PAINTER::getDrillShape( const PAD* aPad ) const
444 {
445  return aPad->GetDrillShape();
446 }
447 
448 
450 {
451  return VECTOR2D( aPad->GetDrillSize() );
452 }
453 
454 
455 int PCB_PAINTER::getDrillSize( const PCB_VIA* aVia ) const
456 {
457  return aVia->GetDrillValue();
458 }
459 
460 
461 bool PCB_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer )
462 {
463  const BOARD_ITEM* item = dynamic_cast<const BOARD_ITEM*>( aItem );
464 
465  if( !item )
466  return false;
467 
468  if( const BOARD* board = item->GetBoard() )
469  {
470  BOARD_DESIGN_SETTINGS& bds = board->GetDesignSettings();
471  m_maxError = bds.m_MaxError;
473  }
474  else
475  {
476  m_maxError = ARC_HIGH_DEF;
478  }
479 
480  // the "cast" applied in here clarifies which overloaded draw() is called
481  switch( item->Type() )
482  {
483  case PCB_TRACE_T:
484  draw( static_cast<const PCB_TRACK*>( item ), aLayer );
485  break;
486 
487  case PCB_ARC_T:
488  draw( static_cast<const PCB_ARC*>( item ), aLayer );
489  break;
490 
491  case PCB_VIA_T:
492  draw( static_cast<const PCB_VIA*>( item ), aLayer );
493  break;
494 
495  case PCB_PAD_T:
496  draw( static_cast<const PAD*>( item ), aLayer );
497  break;
498 
499  case PCB_SHAPE_T:
500  case PCB_FP_SHAPE_T:
501  draw( static_cast<const PCB_SHAPE*>( item ), aLayer );
502  break;
503 
504  case PCB_TEXT_T:
505  draw( static_cast<const PCB_TEXT*>( item ), aLayer );
506  break;
507 
508  case PCB_FP_TEXT_T:
509  draw( static_cast<const FP_TEXT*>( item ), aLayer );
510  break;
511 
512  case PCB_FOOTPRINT_T:
513  draw( static_cast<const FOOTPRINT*>( item ), aLayer );
514  break;
515 
516  case PCB_GROUP_T:
517  draw( static_cast<const PCB_GROUP*>( item ), aLayer );
518  break;
519 
520  case PCB_ZONE_T:
521  draw( static_cast<const ZONE*>( item ), aLayer );
522  break;
523 
524  case PCB_FP_ZONE_T:
525  draw( static_cast<const ZONE*>( item ), aLayer );
526  break;
527 
528  case PCB_DIM_ALIGNED_T:
529  case PCB_DIM_CENTER_T:
531  case PCB_DIM_LEADER_T:
532  draw( static_cast<const PCB_DIMENSION_BASE*>( item ), aLayer );
533  break;
534 
535  case PCB_TARGET_T:
536  draw( static_cast<const PCB_TARGET*>( item ) );
537  break;
538 
539  case PCB_MARKER_T:
540  draw( static_cast<const PCB_MARKER*>( item ), aLayer );
541  break;
542 
543  default:
544  // Painter does not know how to draw the object
545  return false;
546  }
547 
548  // Draw bounding boxes after drawing objects so they can be seen.
549  if( ADVANCED_CFG::GetCfg().m_DrawBoundingBoxes )
550  {
551  // Show bounding boxes of painted objects for debugging.
552  EDA_RECT box = item->GetBoundingBox();
553  m_gal->SetIsFill( false );
554  m_gal->SetIsStroke( true );
555 
556  if( item->Type() == PCB_FOOTPRINT_T )
557  m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) :
558  COLOR4D( MAGENTA ) );
559  else
560  m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) :
561  COLOR4D( 0.2, 0.2, 0.2, 1 ) );
562 
563  m_gal->SetLineWidth( 1.5 / m_gal->GetWorldScale() );
564  m_gal->DrawRectangle( box.GetOrigin(), box.GetEnd() );
565 
566  if( item->Type() == PCB_FOOTPRINT_T )
567  {
568  m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) :
569  COLOR4D( CYAN ) );
570 
571  const FOOTPRINT* fp = static_cast<const FOOTPRINT*>( item );
572 
573  if( fp )
574  {
575  SHAPE_POLY_SET convex = fp->GetBoundingHull();
576 
577  m_gal->DrawPolyline( convex.COutline( 0 ) );
578  }
579  }
580  }
581 
582  return true;
583 }
584 
585 
586 void PCB_PAINTER::draw( const PCB_TRACK* aTrack, int aLayer )
587 {
588  VECTOR2D start( aTrack->GetStart() );
589  VECTOR2D end( aTrack->GetEnd() );
590  int width = aTrack->GetWidth();
591  COLOR4D color = m_pcbSettings.GetColor( aTrack, aLayer );
592 
593  if( IsNetnameLayer( aLayer ) )
594  {
596  return;
597 
598  if( aTrack->GetNetCode() <= NETINFO_LIST::UNCONNECTED )
599  return;
600 
601  VECTOR2D line = ( end - start );
602  double length = line.EuclideanNorm();
603 
604  // Check if the track is long enough to have a netname displayed
605  if( length < 10 * width )
606  return;
607 
608  const wxString& netName = UnescapeString( aTrack->GetShortNetname() );
609  double textSize = width;
610  double penWidth = width / 12.0;
611  VECTOR2D textPosition = start + line / 2.0; // center of the track
612  double textOrientation;
613 
614  if( end.y == start.y ) // horizontal
615  {
616  textOrientation = 0;
617  textPosition.y += penWidth;
618  }
619  else if( end.x == start.x ) // vertical
620  {
621  textOrientation = M_PI / 2;
622  textPosition.x += penWidth;
623  }
624  else
625  {
626  textOrientation = -atan( line.y / line.x );
627  textPosition.x += penWidth / 1.4;
628  textPosition.y += penWidth / 1.4;
629  }
630 
631 
632  m_gal->SetIsStroke( true );
633  m_gal->SetIsFill( false );
635  m_gal->SetLineWidth( penWidth );
636  m_gal->SetFontBold( false );
637  m_gal->SetFontItalic( false );
638  m_gal->SetFontUnderlined( false );
639  m_gal->SetTextMirrored( false );
640  m_gal->SetGlyphSize( VECTOR2D( textSize * 0.55, textSize * 0.55 ) );
643  m_gal->BitmapText( netName, textPosition, textOrientation );
644 
645  return;
646  }
647  else if( IsCopperLayer( aLayer ) )
648  {
649  // Draw a regular track
650  bool outline_mode = m_pcbSettings.m_sketchMode[LAYER_TRACKS];
653  m_gal->SetIsStroke( outline_mode );
654  m_gal->SetIsFill( not outline_mode );
656 
657  m_gal->DrawSegment( start, end, width );
658  }
659 
660  // Clearance lines
661  constexpr int clearanceFlags = PCB_RENDER_SETTINGS::CL_EXISTING
663 
664  if( ( m_pcbSettings.m_clearanceDisplayFlags & clearanceFlags ) == clearanceFlags )
665  {
666  int clearance = aTrack->GetOwnClearance( m_pcbSettings.GetActiveLayer() );
667 
669  m_gal->SetIsFill( false );
670  m_gal->SetIsStroke( true );
672  m_gal->DrawSegment( start, end, width + clearance * 2 );
673  }
674 }
675 
676 
677 void PCB_PAINTER::draw( const PCB_ARC* aArc, int aLayer )
678 {
679  VECTOR2D center( aArc->GetCenter() );
680  int width = aArc->GetWidth();
681  COLOR4D color = m_pcbSettings.GetColor( aArc, aLayer );
682  double radius = aArc->GetRadius();
683  double start_angle = DECIDEG2RAD( aArc->GetArcAngleStart() );
684  double angle = DECIDEG2RAD( aArc->GetAngle() );
685 
686  if( IsNetnameLayer( aLayer ) )
687  {
688  // Ummm, yeah. Anyone fancy implementing text on a path?
689  return;
690  }
691  else if( IsCopperLayer( aLayer ) )
692  {
693  // Draw a regular track
694  bool outline_mode = m_pcbSettings.m_sketchMode[LAYER_TRACKS];
697  m_gal->SetIsStroke( outline_mode );
698  m_gal->SetIsFill( not outline_mode );
700 
701  m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle, width, m_maxError );
702  }
703 
704  // Clearance lines
705  constexpr int clearanceFlags = PCB_RENDER_SETTINGS::CL_EXISTING
707 
708  if( ( m_pcbSettings.m_clearanceDisplayFlags & clearanceFlags ) == clearanceFlags )
709  {
710  int clearance = aArc->GetOwnClearance( m_pcbSettings.GetActiveLayer() );
711 
713  m_gal->SetIsFill( false );
714  m_gal->SetIsStroke( true );
716 
717  m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle,
718  width + clearance * 2, m_maxError );
719  }
720 
721 // Debug only: enable this code only to test the TransformArcToPolygon function
722 // and display the polygon outline created by it.
723 // arcs on F_Cu are approximated with ERROR_INSIDE, others with ERROR_OUTSIDE
724 #if 0
725  SHAPE_POLY_SET cornerBuffer;
727  TransformArcToPolygon( cornerBuffer, aArc->GetStart(), aArc->GetMid(), aArc->GetEnd(), width,
728  m_maxError, errorloc );
730  m_gal->SetIsFill( false );
731  m_gal->SetIsStroke( true );
732  m_gal->SetStrokeColor( COLOR4D( 0, 0, 1.0, 1.0 ) );
733  m_gal->DrawPolygon( cornerBuffer );
734 #endif
735 
736 // Debug only: enable this code only to test the SHAPE_ARC::ConvertToPolyline function
737 // and display the polyline created by it.
738 #if 0
739  SHAPE_ARC arc( aArc->GetCenter(), aArc->GetStart(), aArc->GetAngle() / 10.0, aArc->GetWidth() );
740  SHAPE_LINE_CHAIN arcSpine = arc.ConvertToPolyline( m_maxError );
742  m_gal->SetIsFill( false );
743  m_gal->SetIsStroke( true );
744  m_gal->SetStrokeColor( COLOR4D( 0.3, 0.2, 0.5, 1.0 ) );
745 
746  for( int idx = 1; idx < arcSpine.PointCount(); idx++ )
747  m_gal->DrawSegment( arcSpine.CPoint( idx-1 ), arcSpine.CPoint( idx ), aArc->GetWidth() );
748 #endif
749 }
750 
751 
752 void PCB_PAINTER::draw( const PCB_VIA* aVia, int aLayer )
753 {
754  COLOR4D color = m_pcbSettings.GetColor( aVia, aLayer );
755  VECTOR2D center( aVia->GetStart() );
756 
757  if( color == COLOR4D::CLEAR )
758  return;
759 
760  // Draw description layer
761  if( IsNetnameLayer( aLayer ) )
762  {
763  VECTOR2D position( center );
764 
765  // Is anything that we can display enabled?
766  if( !m_pcbSettings.m_netNamesOnVias || aVia->GetNetname().empty() )
767  return;
768 
769  double maxSize = PCB_RENDER_SETTINGS::MAX_FONT_SIZE;
770  double size = aVia->GetWidth();
771 
772  // Font size limits
773  if( size > maxSize )
774  size = maxSize;
775 
776  m_gal->Save();
777  m_gal->Translate( position );
778 
779  // Default font settings
781  m_gal->SetStrokeColor( m_pcbSettings.GetColor( nullptr, aLayer ) );
782 
783  // Set the text position to the pad shape position (the pad position is not the best place)
784  VECTOR2D textpos( 0.0, 0.0 );
785 
786  wxString netname = UnescapeString( aVia->GetShortNetname() );
787 
788  // approximate the size of net name text:
789  double tsize = 1.5 * size / std::max( PrintableCharCount( netname ), 1 );
790  tsize = std::min( tsize, size );
791 
792  // Use a smaller text size to handle interline, pen size..
793  tsize *= 0.7;
794  VECTOR2D namesize( tsize, tsize );
795 
796  m_gal->SetGlyphSize( namesize );
797  m_gal->SetLineWidth( namesize.x / 12.0 );
798  m_gal->BitmapText( netname, textpos, 0.0 );
799 
800  m_gal->Restore();
801 
802  return;
803  }
804  else if( aLayer == LAYER_VIA_HOLEWALLS )
805  {
806  m_gal->SetIsFill( false );
807  m_gal->SetIsStroke( true );
810 
811  m_gal->DrawCircle( center, ( getDrillSize( aVia ) + m_holePlatingThickness ) / 2.0 );
812 
813  return;
814  }
815 
816  bool sketchMode = false;
817 
818  switch( aVia->GetViaType() )
819  {
823  default: wxASSERT( false ); break;
824  }
825 
826  if( sketchMode )
827  {
828  // Outline mode
829  m_gal->SetIsStroke( true );
830  m_gal->SetIsFill( false );
833  }
834  else
835  {
836  // Filled mode
837  m_gal->SetIsFill( true );
838  m_gal->SetIsStroke( false );
840  }
841 
842  if( aLayer == LAYER_VIA_HOLES )
843  {
844  m_gal->DrawCircle( center, getDrillSize( aVia ) / 2.0 );
845  }
847  {
848  m_gal->DrawCircle( center, aVia->GetWidth() / 2.0 );
849  }
850  else if( aLayer == LAYER_VIA_BBLIND || aLayer == LAYER_VIA_MICROVIA )
851  {
852  // Outer circles of blind/buried and micro-vias are drawn in a special way to indicate the
853  // top and bottom layers
854  PCB_LAYER_ID layerTop, layerBottom;
855  aVia->LayerPair( &layerTop, &layerBottom );
856 
857  double radius = aVia->GetWidth() / 2.0;
858 
859  if( !sketchMode )
860  m_gal->SetLineWidth( ( aVia->GetWidth() - aVia->GetDrillValue() ) / 2.0 );
861 
862  m_gal->DrawArc( center, radius, M_PI * -0.375, M_PI * 0.375 );
863  m_gal->DrawArc( center, radius, M_PI * 0.625, M_PI * 1.375 );
864 
865  if( sketchMode )
866  m_gal->SetStrokeColor( m_pcbSettings.GetColor( aVia, layerTop ) );
867  else
868  m_gal->SetFillColor( m_pcbSettings.GetColor( aVia, layerTop ) );
869 
870  m_gal->DrawArc( center, radius, M_PI * 1.375, M_PI * 1.625 );
871 
872  if( sketchMode )
873  m_gal->SetStrokeColor( m_pcbSettings.GetColor( aVia, layerBottom ) );
874  else
875  m_gal->SetFillColor( m_pcbSettings.GetColor( aVia, layerBottom ) );
876 
877  m_gal->DrawArc( center, radius, M_PI * 0.375, M_PI * 0.625 );
878  }
879 
880  // Clearance lines
881  constexpr int clearanceFlags = PCB_RENDER_SETTINGS::CL_EXISTING | PCB_RENDER_SETTINGS::CL_VIAS;
882 
883  if( ( m_pcbSettings.m_clearanceDisplayFlags & clearanceFlags ) == clearanceFlags
884  && aLayer != LAYER_VIA_HOLES )
885  {
886  PCB_LAYER_ID activeLayer = m_pcbSettings.GetActiveLayer();
887  double radius;
888 
889  if( aVia->FlashLayer( activeLayer ) )
890  radius = aVia->GetWidth() / 2.0;
891  else
892  radius = getDrillSize( aVia ) / 2.0 + m_holePlatingThickness;
893 
895  m_gal->SetIsFill( false );
896  m_gal->SetIsStroke( true );
898  m_gal->DrawCircle( center, radius + aVia->GetOwnClearance( activeLayer ) );
899  }
900 }
901 
902 
903 void PCB_PAINTER::draw( const PAD* aPad, int aLayer )
904 {
905  COLOR4D color = m_pcbSettings.GetColor( aPad, aLayer );
906 
907  if( IsNetnameLayer( aLayer ) )
908  {
909  // Is anything that we can display enabled?
911  {
912  bool displayNetname = ( m_pcbSettings.m_netNamesOnPads && !aPad->GetNetname().empty() );
913  EDA_RECT padBBox = aPad->GetBoundingBox();
914  VECTOR2D position = padBBox.Centre();
915  VECTOR2D padsize = VECTOR2D( padBBox.GetSize() );
916 
917  if( aPad->GetShape() != PAD_SHAPE::CUSTOM )
918  {
919  // Don't allow a 45ยบ rotation to bloat a pad's bounding box unnecessarily
920  double limit = std::min( aPad->GetSize().x, aPad->GetSize().y ) * 1.1;
921 
922  if( padsize.x > limit && padsize.y > limit )
923  {
924  padsize.x = limit;
925  padsize.y = limit;
926  }
927  }
928 
929  double maxSize = PCB_RENDER_SETTINGS::MAX_FONT_SIZE;
930  double size = padsize.y;
931 
932  m_gal->Save();
933  m_gal->Translate( position );
934 
935  // Keep the size ratio for the font, but make it smaller
936  if( padsize.x < padsize.y )
937  {
938  m_gal->Rotate( DECIDEG2RAD( -900.0 ) );
939  size = padsize.x;
940  std::swap( padsize.x, padsize.y );
941  }
942 
943  // Font size limits
944  if( size > maxSize )
945  size = maxSize;
946 
947  // Default font settings
950  m_gal->SetFontBold( false );
951  m_gal->SetFontItalic( false );
952  m_gal->SetFontUnderlined( false );
953  m_gal->SetTextMirrored( false );
954  m_gal->SetStrokeColor( m_pcbSettings.GetColor( aPad, aLayer ) );
955  m_gal->SetIsStroke( true );
956  m_gal->SetIsFill( false );
957 
958  // We have already translated the GAL to be centered at the center of the pad's
959  // bounding box
960  VECTOR2D textpos( 0.0, 0.0 );
961 
962  // Divide the space, to display both pad numbers and netnames and set the Y text
963  // position to display 2 lines
964  if( displayNetname && m_pcbSettings.m_padNumbers )
965  {
966  size = size / 2.5;
967  textpos.y = size / 1.7;
968  }
969 
970  if( displayNetname )
971  {
972  wxString netname = UnescapeString( aPad->GetShortNetname() );
973  wxString pinType = aPad->GetPinType();
974 
975  if( pinType == wxT( "no_connect" ) || pinType.EndsWith( wxT( "+no_connect" ) ) )
976  netname = "x";
977  else if( pinType == wxT( "free" ) && netname.StartsWith( wxT( "unconnected-(" ) ) )
978  netname = "*";
979 
980  // approximate the size of net name text:
981  double tsize = 1.5 * padsize.x / std::max( PrintableCharCount( netname ), 1 );
982  tsize = std::min( tsize, size );
983 
984  // Use a smaller text size to handle interline, pen size...
985  tsize *= 0.7;
986  VECTOR2D namesize( tsize, tsize );
987 
988  m_gal->SetGlyphSize( namesize );
989  m_gal->SetLineWidth( namesize.x / 12.0 );
990  m_gal->BitmapText( netname, textpos, 0.0 );
991  }
992 
994  {
995  const wxString& padNumber = aPad->GetNumber();
996  textpos.y = -textpos.y;
997 
998  // approximate the size of the pad number text:
999  double tsize = 1.5 * padsize.x / std::max( PrintableCharCount( padNumber ), 1 );
1000  tsize = std::min( tsize, size );
1001 
1002  // Use a smaller text size to handle interline, pen size...
1003  tsize *= 0.7;
1004  tsize = std::min( tsize, size );
1005  VECTOR2D numsize( tsize, tsize );
1006 
1007  m_gal->SetGlyphSize( numsize );
1008  m_gal->SetLineWidth( numsize.x / 12.0 );
1009  m_gal->BitmapText( padNumber, textpos, 0.0 );
1010  }
1011 
1012  m_gal->Restore();
1013  }
1014 
1015  return;
1016  }
1017  else if( aLayer == LAYER_PAD_HOLEWALLS )
1018  {
1019  m_gal->SetIsFill( false );
1020  m_gal->SetIsStroke( true );
1023 
1024  const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape();
1025  int holeSize = seg->GetWidth() + m_holePlatingThickness;
1026 
1027  if( seg->GetSeg().A == seg->GetSeg().B ) // Circular hole
1028  m_gal->DrawCircle( seg->GetSeg().A, holeSize / 2 );
1029  else
1030  m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, holeSize );
1031 
1032  return;
1033  }
1034 
1036  {
1037  // Outline mode
1038  m_gal->SetIsFill( false );
1039  m_gal->SetIsStroke( true );
1042  }
1043  else
1044  {
1045  // Filled mode
1046  m_gal->SetIsFill( true );
1047  m_gal->SetIsStroke( false );
1048  m_gal->SetFillColor( color );
1049  }
1050 
1051  if( aLayer == LAYER_PAD_PLATEDHOLES || aLayer == LAYER_NON_PLATEDHOLES )
1052  {
1053  const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape();
1054 
1055  if( seg->GetSeg().A == seg->GetSeg().B ) // Circular hole
1056  m_gal->DrawCircle( seg->GetSeg().A, getDrillSize( aPad ).x / 2 );
1057  else
1058  m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, seg->GetWidth() );
1059  }
1060  else
1061  {
1062  wxSize pad_size = aPad->GetSize();
1063  wxSize margin;
1064 
1065  switch( aLayer )
1066  {
1067  case F_Mask:
1068  case B_Mask:
1069  margin.x = margin.y = aPad->GetSolderMaskMargin();
1070  break;
1071 
1072  case F_Paste:
1073  case B_Paste:
1074  margin = aPad->GetSolderPasteMargin();
1075  break;
1076 
1077  default:
1078  margin.x = margin.y = 0;
1079  break;
1080  }
1081 
1082  std::unique_ptr<PAD> dummyPad;
1083  std::shared_ptr<SHAPE_COMPOUND> shapes;
1084 
1085  // Drawing components of compound shapes in outline mode produces a mess.
1086  bool simpleShapes = !m_pcbSettings.m_sketchMode[LAYER_PADS_TH];
1087 
1088  if( simpleShapes )
1089  {
1090  if( ( margin.x != margin.y && aPad->GetShape() != PAD_SHAPE::CUSTOM )
1091  || ( aPad->GetShape() == PAD_SHAPE::ROUNDRECT && ( margin.x < 0 || margin.y < 0 ) ) )
1092  {
1093  // Our algorithms below (polygon inflation in particular) can't handle differential
1094  // inflation along separate axes. So for those cases we build a dummy pad instead,
1095  // and inflate it.
1096 
1097  // Margin is added to both sides. If the total margin is larger than the pad
1098  // then don't display this layer
1099  if( pad_size.x + 2 * margin.x <= 0 || pad_size.y + 2 * margin.y <= 0 )
1100  return;
1101 
1102  dummyPad.reset( static_cast<PAD*>( aPad->Duplicate() ) );
1103  int initial_radius = dummyPad->GetRoundRectCornerRadius();
1104 
1105  dummyPad->SetSize( pad_size + margin + margin );
1106 
1107  if( dummyPad->GetShape() == PAD_SHAPE::ROUNDRECT )
1108  {
1109  // To keep the right margin around the corners, we need to modify the corner radius.
1110  // We must have only one radius correction, so use the smallest absolute margin.
1111  int radius_margin = std::max( margin.x, margin.y ); // radius_margin is < 0
1112  dummyPad->SetRoundRectCornerRadius( std::max( initial_radius + radius_margin, 0 ) );
1113  }
1114 
1115  shapes = std::dynamic_pointer_cast<SHAPE_COMPOUND>( dummyPad->GetEffectiveShape() );
1116  margin.x = margin.y = 0;
1117  }
1118  else
1119  {
1120  shapes = std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
1121  }
1122 
1123  if( aPad->GetShape() == PAD_SHAPE::CUSTOM && ( margin.x || margin.y ) )
1124  {
1125  // We can't draw as shapes because we don't know which edges are internal and which
1126  // are external (so we don't know when to apply the margin and when not to).
1127  simpleShapes = false;
1128  }
1129 
1130  for( const SHAPE* shape : shapes->Shapes() )
1131  {
1132  if( !simpleShapes )
1133  break;
1134 
1135  switch( shape->Type() )
1136  {
1137  case SH_SEGMENT:
1138  case SH_CIRCLE:
1139  case SH_RECT:
1140  case SH_SIMPLE:
1141  // OK so far
1142  break;
1143 
1144  default:
1145  // Not OK
1146  simpleShapes = false;
1147  break;
1148  }
1149  }
1150  }
1151 
1152  if( simpleShapes )
1153  {
1154  for( const SHAPE* shape : shapes->Shapes() )
1155  {
1156  switch( shape->Type() )
1157  {
1158  case SH_SEGMENT:
1159  {
1160  const SHAPE_SEGMENT* seg = (const SHAPE_SEGMENT*) shape;
1161  int effectiveWidth = seg->GetWidth() + 2 * margin.x;
1162 
1163  if( effectiveWidth > 0 )
1164  m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, effectiveWidth );
1165 
1166  break;
1167  }
1168 
1169  case SH_CIRCLE:
1170  {
1171  const SHAPE_CIRCLE* circle = (const SHAPE_CIRCLE*) shape;
1172  int effectiveRadius = circle->GetRadius() + margin.x;
1173 
1174  if( effectiveRadius > 0 )
1175  m_gal->DrawCircle( circle->GetCenter(), effectiveRadius );
1176 
1177  break;
1178  }
1179 
1180  case SH_RECT:
1181  {
1182  const SHAPE_RECT* r = (const SHAPE_RECT*) shape;
1183  VECTOR2I pos = r->GetPosition();
1184  VECTOR2I effectiveMargin = margin;
1185 
1186  if( effectiveMargin.x < 0 )
1187  {
1188  // A negative margin just produces a smaller rect.
1189  VECTOR2I effectiveSize = r->GetSize() + effectiveMargin;
1190 
1191  if( effectiveSize.x > 0 && effectiveSize.y > 0 )
1192  m_gal->DrawRectangle( pos - effectiveMargin, pos + effectiveSize );
1193  }
1194  else if( effectiveMargin.x > 0 )
1195  {
1196  // A positive margin produces a larger rect, but with rounded corners
1197  m_gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() );
1198 
1199  // Use segments to produce the margin with rounded corners
1200  m_gal->DrawSegment( pos,
1201  pos + VECTOR2I( r->GetWidth(), 0 ),
1202  effectiveMargin.x * 2 );
1203  m_gal->DrawSegment( pos + VECTOR2I( r->GetWidth(), 0 ),
1204  pos + r->GetSize(),
1205  effectiveMargin.x * 2 );
1206  m_gal->DrawSegment( pos + r->GetSize(),
1207  pos + VECTOR2I( 0, r->GetHeight() ),
1208  effectiveMargin.x * 2 );
1209  m_gal->DrawSegment( pos + VECTOR2I( 0, r->GetHeight() ),
1210  pos,
1211  effectiveMargin.x * 2 );
1212  }
1213  else
1214  {
1215  m_gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() );
1216  }
1217 
1218  break;
1219  }
1220 
1221  case SH_SIMPLE:
1222  {
1223  const SHAPE_SIMPLE* poly = static_cast<const SHAPE_SIMPLE*>( shape );
1224 
1225  if( margin.x < 0 ) // The poly shape must be deflated
1226  {
1227  int numSegs = GetArcToSegmentCount( -margin.x, m_maxError, 360.0 );
1228  SHAPE_POLY_SET outline;
1229  outline.NewOutline();
1230 
1231  for( int ii = 0; ii < poly->PointCount(); ++ii )
1232  outline.Append( poly->CPoint( ii ) );
1233 
1234  outline.Deflate( -margin.x, numSegs );
1235 
1236  m_gal->DrawPolygon( outline );
1237  }
1238  else
1239  {
1240  m_gal->DrawPolygon( poly->Vertices() );
1241  }
1242 
1243  // Now add on a rounded margin (using segments) if the margin > 0
1244  if( margin.x > 0 )
1245  {
1246  for( size_t ii = 0; ii < poly->GetSegmentCount(); ++ii )
1247  {
1248  SEG seg = poly->GetSegment( ii );
1249  m_gal->DrawSegment( seg.A, seg.B, margin.x * 2 );
1250  }
1251  }
1252 
1253  break;
1254  }
1255 
1256  default:
1257  // Better not get here; we already pre-flighted the shapes...
1258  break;
1259  }
1260  }
1261  }
1262  else
1263  {
1264  // This is expensive. Avoid if possible.
1265  SHAPE_POLY_SET polySet;
1266  aPad->TransformShapeWithClearanceToPolygon( polySet, ToLAYER_ID( aLayer ), margin.x,
1268  m_gal->DrawPolygon( polySet );
1269  }
1270  }
1271 
1272  constexpr int clearanceFlags = PCB_RENDER_SETTINGS::CL_PADS;
1273 
1274  if( ( m_pcbSettings.m_clearanceDisplayFlags & clearanceFlags ) == clearanceFlags
1275  && ( aLayer == LAYER_PAD_FR || aLayer == LAYER_PAD_BK || aLayer == LAYER_PADS_TH ) )
1276  {
1277  /* Showing the clearance area is not obvious.
1278  * - A pad can be removed from some copper layers.
1279  * - For non copper layers, what is the clearance area?
1280  * So for copper layers, the clearance area is the shape if the pad is flashed on this
1281  * layer and the hole clearance area for other copper layers.
1282  * For other layers, use the pad shape, although one can use an other criteria,
1283  * depending on the non copper layer.
1284  */
1285  int activeLayer = m_pcbSettings.GetActiveLayer();
1286  bool flashActiveLayer = true;
1287 
1288  if( IsCopperLayer( activeLayer ) )
1289  flashActiveLayer = aPad->FlashLayer( activeLayer );
1290 
1291  if( flashActiveLayer || aPad->GetDrillSize().x )
1292  {
1294  m_gal->SetIsStroke( true );
1295  m_gal->SetIsFill( false );
1297 
1298  int clearance = aPad->GetOwnClearance( m_pcbSettings.GetActiveLayer() );
1299 
1300  if( flashActiveLayer && clearance > 0 )
1301  {
1302  auto shape = std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
1303 
1304  if( shape && shape->Size() == 1 && shape->Shapes()[0]->Type() == SH_SEGMENT )
1305  {
1306  const SHAPE_SEGMENT* seg = (SHAPE_SEGMENT*) shape->Shapes()[0];
1307  m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B,
1308  seg->GetWidth() + 2 * clearance );
1309  }
1310  else if( shape && shape->Size() == 1 && shape->Shapes()[0]->Type() == SH_CIRCLE )
1311  {
1312  const SHAPE_CIRCLE* circle = (SHAPE_CIRCLE*) shape->Shapes()[0];
1313  m_gal->DrawCircle( circle->GetCenter(), circle->GetRadius() + clearance );
1314  }
1315  else
1316  {
1317  SHAPE_POLY_SET polySet;
1318 
1319  // Use ERROR_INSIDE because it avoids Clipper and is therefore much faster.
1320  aPad->TransformShapeWithClearanceToPolygon( polySet, ToLAYER_ID( aLayer ),
1321  clearance, m_maxError, ERROR_INSIDE );
1322  m_gal->DrawPolygon( polySet );
1323  }
1324  }
1325  else if( aPad->GetEffectiveHoleShape() && clearance > 0 )
1326  {
1327  clearance += m_holePlatingThickness;
1328 
1329  const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape();
1330  m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B,
1331  seg->GetWidth() + 2 * clearance );
1332  }
1333  }
1334  }
1335 }
1336 
1337 
1338 void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
1339 {
1340  const COLOR4D& color = m_pcbSettings.GetColor( aShape, aShape->GetLayer() );
1341  bool sketch = m_pcbSettings.m_sketchGraphics;
1342  int thickness = getLineThickness( aShape->GetWidth() );
1343  VECTOR2D start( aShape->GetStart() );
1344  VECTOR2D end( aShape->GetEnd() );
1345 
1346  if( sketch )
1347  {
1348  m_gal->SetIsFill( false );
1349  m_gal->SetIsStroke( true );
1351  }
1352 
1353  m_gal->SetFillColor( color );
1355 
1356  switch( aShape->GetShape() )
1357  {
1358  case SHAPE_T::SEGMENT:
1359  if( sketch )
1360  {
1361  m_gal->DrawSegment( start, end, thickness );
1362  }
1363  else
1364  {
1365  m_gal->SetIsFill( true );
1366  m_gal->SetIsStroke( false );
1367 
1368  m_gal->DrawSegment( start, end, thickness );
1369  }
1370 
1371  break;
1372 
1373  case SHAPE_T::RECT:
1374  {
1375  std::vector<wxPoint> pts = aShape->GetRectCorners();
1376 
1377  if( sketch )
1378  {
1379  m_gal->DrawSegment( pts[0], pts[1], thickness );
1380  m_gal->DrawSegment( pts[1], pts[2], thickness );
1381  m_gal->DrawSegment( pts[2], pts[3], thickness );
1382  m_gal->DrawSegment( pts[3], pts[0], thickness );
1383  }
1384  else
1385  {
1386  m_gal->SetIsFill( true );
1387  m_gal->SetIsStroke( false );
1388 
1389  if( thickness > 0 )
1390  {
1391  m_gal->DrawSegment( pts[0], pts[1], thickness );
1392  m_gal->DrawSegment( pts[1], pts[2], thickness );
1393  m_gal->DrawSegment( pts[2], pts[3], thickness );
1394  m_gal->DrawSegment( pts[3], pts[0], thickness );
1395  }
1396 
1397  if( aShape->IsFilled() )
1398  {
1399  SHAPE_POLY_SET poly;
1400  poly.NewOutline();
1401 
1402  for( const wxPoint& pt : pts )
1403  poly.Append( pt );
1404 
1405  m_gal->DrawPolygon( poly );
1406  }
1407  }
1408 
1409  break;
1410  }
1411 
1412  case SHAPE_T::ARC:
1413  if( sketch )
1414  {
1415  m_gal->DrawArcSegment( start, aShape->GetRadius(),
1416  DECIDEG2RAD( aShape->GetArcAngleStart() ),
1417  DECIDEG2RAD( aShape->GetArcAngleStart() + aShape->GetAngle() ), // Change this
1418  thickness, m_maxError );
1419  }
1420  else
1421  {
1422  m_gal->SetIsFill( true );
1423  m_gal->SetIsStroke( false );
1424 
1425  m_gal->DrawArcSegment( start, aShape->GetRadius(),
1426  DECIDEG2RAD( aShape->GetArcAngleStart() ),
1427  DECIDEG2RAD( aShape->GetArcAngleStart() + aShape->GetAngle() ), // Change this
1428  thickness, m_maxError );
1429  }
1430  break;
1431 
1432  case SHAPE_T::CIRCLE:
1433  if( sketch )
1434  {
1435  m_gal->DrawCircle( start, aShape->GetRadius() - thickness / 2 );
1436  m_gal->DrawCircle( start, aShape->GetRadius() + thickness / 2 );
1437  }
1438  else
1439  {
1440  m_gal->SetIsFill( aShape->IsFilled() );
1441  m_gal->SetIsStroke( thickness > 0 );
1442  m_gal->SetLineWidth( thickness );
1443 
1444  m_gal->DrawCircle( start, aShape->GetRadius() );
1445  }
1446  break;
1447 
1448  case SHAPE_T::POLY:
1449  {
1450  SHAPE_POLY_SET& shape = const_cast<PCB_SHAPE*>( aShape )->GetPolyShape();
1451  const FOOTPRINT* parentFootprint = aShape->GetParentFootprint();
1452 
1453  if( shape.OutlineCount() == 0 )
1454  break;
1455 
1456  if( parentFootprint )
1457  {
1458  m_gal->Save();
1459  m_gal->Translate( parentFootprint->GetPosition() );
1460  m_gal->Rotate( -parentFootprint->GetOrientationRadians() );
1461  }
1462 
1463  if( sketch )
1464  {
1465  for( int ii = 0; ii < shape.Outline( 0 ).SegmentCount(); ++ii )
1466  {
1467  SEG seg = shape.Outline( 0 ).Segment( ii );
1468  m_gal->DrawSegment( seg.A, seg.B, thickness );
1469  }
1470  }
1471  else
1472  {
1473  m_gal->SetIsFill( true );
1474  m_gal->SetIsStroke( false );
1475 
1476  if( thickness > 0 )
1477  {
1478  for( int ii = 0; ii < shape.Outline( 0 ).SegmentCount(); ++ii )
1479  {
1480  SEG seg = shape.Outline( 0 ).Segment( ii );
1481  m_gal->DrawSegment( seg.A, seg.B, thickness );
1482  }
1483  }
1484 
1485  if( aShape->IsFilled() )
1486  {
1487  // On Opengl, a not convex filled polygon is usually drawn by using triangles
1488  // as primitives. CacheTriangulation() can create basic triangle primitives to
1489  // draw the polygon solid shape on Opengl. GLU tessellation is much slower, so
1490  // currently we are using our tessellation.
1491  if( m_gal->IsOpenGlEngine() && !shape.IsTriangulationUpToDate() )
1492  shape.CacheTriangulation();
1493 
1494  m_gal->DrawPolygon( shape );
1495  }
1496  }
1497 
1498  if( parentFootprint )
1499  m_gal->Restore();
1500 
1501  break;
1502  }
1503 
1504  case SHAPE_T::BEZIER:
1505  if( sketch )
1506  {
1507  // Use thickness as filter value to convert the curve to polyline when the curve
1508  // is not supported
1509  m_gal->DrawCurve( VECTOR2D( aShape->GetStart() ),
1510  VECTOR2D( aShape->GetBezierC1() ),
1511  VECTOR2D( aShape->GetBezierC2() ),
1512  VECTOR2D( aShape->GetEnd() ), thickness );
1513  }
1514  else
1515  {
1516  m_gal->SetIsFill( aShape->IsFilled() );
1517  m_gal->SetIsStroke( thickness > 0 );
1518  m_gal->SetLineWidth( thickness );
1519 
1520  // Use thickness as filter value to convert the curve to polyline when the curve
1521  // is not supported
1522  m_gal->DrawCurve( VECTOR2D( aShape->GetStart() ),
1523  VECTOR2D( aShape->GetBezierC1() ),
1524  VECTOR2D( aShape->GetBezierC2() ),
1525  VECTOR2D( aShape->GetEnd() ), thickness );
1526  }
1527 
1528  break;
1529 
1530  case SHAPE_T::LAST:
1531  break;
1532  }
1533 }
1534 
1535 
1536 void PCB_PAINTER::draw( const PCB_TEXT* aText, int aLayer )
1537 {
1538  wxString shownText( aText->GetShownText() );
1539 
1540  if( shownText.Length() == 0 )
1541  return;
1542 
1543  const COLOR4D& color = m_pcbSettings.GetColor( aText, aText->GetLayer() );
1544  VECTOR2D position( aText->GetTextPos().x, aText->GetTextPos().y );
1545 
1547  {
1548  // Outline mode
1550  }
1551  else
1552  {
1553  // Filled mode
1555  }
1556 
1558  m_gal->SetIsFill( false );
1559  m_gal->SetIsStroke( true );
1560  m_gal->SetTextAttributes( aText );
1561  m_gal->StrokeText( shownText, position, aText->GetTextAngleRadians() );
1562 }
1563 
1564 
1565 void PCB_PAINTER::draw( const FP_TEXT* aText, int aLayer )
1566 {
1567  wxString shownText( aText->GetShownText() );
1568 
1569  if( shownText.Length() == 0 )
1570  return;
1571 
1572  const COLOR4D& color = m_pcbSettings.GetColor( aText, aLayer );
1573  VECTOR2D position( aText->GetTextPos().x, aText->GetTextPos().y );
1574 
1576  {
1577  // Outline mode
1579  }
1580  else
1581  {
1582  // Filled mode
1584  }
1585 
1587  m_gal->SetIsFill( false );
1588  m_gal->SetIsStroke( true );
1589  m_gal->SetTextAttributes( aText );
1590  m_gal->StrokeText( shownText, position, aText->GetDrawRotationRadians() );
1591 
1592  // Draw the umbilical line
1593  if( aText->IsSelected() )
1594  {
1597  m_gal->DrawLine( position, aText->GetParent()->GetPosition() );
1598  }
1599 }
1600 
1601 
1602 void PCB_PAINTER::draw( const FOOTPRINT* aFootprint, int aLayer )
1603 {
1604  if( aLayer == LAYER_ANCHOR )
1605  {
1606  const COLOR4D color = m_pcbSettings.GetColor( aFootprint, aLayer );
1607 
1608  // Keep the size and width constant, not related to the scale because the anchor
1609  // is just a marker on screen
1610  double anchorSize = 5.0 / m_gal->GetWorldScale(); // 5 pixels size
1611  double anchorThickness = 1.0 / m_gal->GetWorldScale(); // 1 pixels width
1612 
1613  // Draw anchor
1614  m_gal->SetIsFill( false );
1615  m_gal->SetIsStroke( true );
1617  m_gal->SetLineWidth( anchorThickness );
1618 
1619  VECTOR2D center = aFootprint->GetPosition();
1620  m_gal->DrawLine( center - VECTOR2D( anchorSize, 0 ), center + VECTOR2D( anchorSize, 0 ) );
1621  m_gal->DrawLine( center - VECTOR2D( 0, anchorSize ), center + VECTOR2D( 0, anchorSize ) );
1622  }
1623 }
1624 
1625 
1626 void PCB_PAINTER::draw( const PCB_GROUP* aGroup, int aLayer )
1627 {
1628  if( aLayer == LAYER_ANCHOR )
1629  {
1630  if( aGroup->IsSelected() && !( aGroup->GetParent() && aGroup->GetParent()->IsSelected() ) )
1631  {
1632  // Selected on our own; draw enclosing box
1633  }
1634  else if( aGroup->IsEntered() )
1635  {
1636  // Entered group; draw enclosing box
1637  }
1638  else
1639  {
1640  // Neither selected nor entered; draw nothing at the group level (ie: only draw
1641  // its members)
1642  return;
1643  }
1644 
1645  const COLOR4D color = m_pcbSettings.GetColor( aGroup, LAYER_ANCHOR );
1646 
1647  EDA_RECT bbox = aGroup->GetBoundingBox();
1650  wxPoint topLeft = bbox.GetPosition();
1651  wxPoint width = wxPoint( bbox.GetWidth(), 0 );
1652  wxPoint height = wxPoint( 0, bbox.GetHeight() );
1653 
1654  m_gal->DrawLine( topLeft, topLeft + width );
1655  m_gal->DrawLine( topLeft + width, topLeft + width + height );
1656  m_gal->DrawLine( topLeft + width + height, topLeft + height );
1657  m_gal->DrawLine( topLeft + height, topLeft );
1658 
1659  wxString name = aGroup->GetName();
1660 
1661  if( name.IsEmpty() )
1662  return;
1663 
1664  int ptSize = 12;
1665  int scaledSize = abs( KiROUND( m_gal->GetScreenWorldMatrix().GetScale().x * ptSize ) );
1666  int unscaledSize = Mils2iu( ptSize );
1667 
1668  // Scale by zoom a bit, but not too much
1669  int textSize = ( scaledSize + ( unscaledSize * 2 ) ) / 3;
1670  int penWidth = textSize / 10;
1671  wxPoint textOffset = wxPoint( width.x / 2, - KiROUND( textSize * 0.5 ) );
1672  wxPoint titleHeight = wxPoint( 0, KiROUND( textSize * 2.0 ) );
1673 
1674  if( PrintableCharCount( name ) * textSize < bbox.GetWidth() )
1675  {
1676  m_gal->DrawLine( topLeft, topLeft - titleHeight );
1677  m_gal->DrawLine( topLeft - titleHeight, topLeft + width - titleHeight );
1678  m_gal->DrawLine( topLeft + width - titleHeight, topLeft + width );
1679 
1680  m_gal->SetFontBold( false );
1681  m_gal->SetFontItalic( true );
1682  m_gal->SetFontUnderlined( false );
1686  m_gal->SetIsFill( false );
1687  m_gal->SetGlyphSize( VECTOR2D( textSize, textSize ) );
1688  m_gal->SetLineWidth( penWidth );
1689  m_gal->StrokeText( aGroup->GetName(), topLeft + textOffset, 0.0 );
1690  }
1691  }
1692 }
1693 
1694 
1695 void PCB_PAINTER::draw( const ZONE* aZone, int aLayer )
1696 {
1697  /*
1698  * aLayer will be the virtual zone layer (LAYER_ZONE_START, ... in GAL_LAYER_ID)
1699  * This is used for draw ordering in the GAL.
1700  * The color for the zone comes from the associated copper layer ( aLayer - LAYER_ZONE_START )
1701  * and the visibility comes from the combination of that copper layer and LAYER_ZONES
1702  */
1703  wxASSERT( IsZoneLayer( aLayer ) );
1704  PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( aLayer - LAYER_ZONE_START );
1705 
1706  if( !aZone->IsOnLayer( layer ) )
1707  return;
1708 
1709  COLOR4D color = m_pcbSettings.GetColor( aZone, layer );
1710  std::deque<VECTOR2D> corners;
1712 
1713  // Draw the outline
1714  const SHAPE_POLY_SET* outline = aZone->Outline();
1715 
1716  if( m_pcbSettings.m_zoneOutlines && outline && outline->OutlineCount() > 0 )
1717  {
1718  m_gal->SetStrokeColor( color.a > 0.0 ? color.WithAlpha( 1.0 ) : color );
1719  m_gal->SetIsFill( false );
1720  m_gal->SetIsStroke( true );
1722 
1723  // Draw each contour (main contour and holes)
1724 
1725  /* This line:
1726  * m_gal->DrawPolygon( *outline );
1727  * should be enough, but currently does not work to draw holes contours in a complex polygon
1728  * so each contour is draw as a simple polygon
1729  */
1730 
1731  // Draw the main contour
1732  m_gal->DrawPolyline( outline->COutline( 0 ) );
1733 
1734  // Draw holes
1735  int holes_count = outline->HoleCount( 0 );
1736 
1737  for( int ii = 0; ii < holes_count; ++ii )
1738  m_gal->DrawPolyline( outline->CHole( 0, ii ) );
1739 
1740  // Draw hatch lines
1741  for( const SEG& hatchLine : aZone->GetHatchLines() )
1742  m_gal->DrawLine( hatchLine.A, hatchLine.B );
1743  }
1744 
1745  // Draw the filling
1746  if( displayMode == ZONE_DISPLAY_MODE::SHOW_FILLED
1748  || displayMode == ZONE_DISPLAY_MODE::SHOW_TRIANGULATION )
1749  {
1750  const SHAPE_POLY_SET& polySet = aZone->GetFilledPolysList( layer );
1751 
1752  if( polySet.OutlineCount() == 0 ) // Nothing to draw
1753  return;
1754 
1755  // Set up drawing options
1756  int outline_thickness = 0;
1757 
1758  if( aZone->GetFilledPolysUseThickness( layer ) )
1759  outline_thickness = aZone->GetMinThickness();
1760 
1762  m_gal->SetFillColor( color );
1763  m_gal->SetLineWidth( outline_thickness );
1764 
1765  if( displayMode == ZONE_DISPLAY_MODE::SHOW_FILLED )
1766  {
1767  m_gal->SetIsFill( true );
1768  m_gal->SetIsStroke( outline_thickness > 0 );
1769  }
1770  else
1771  {
1772  m_gal->SetIsFill( false );
1773  m_gal->SetIsStroke( true );
1774  }
1775 
1776  m_gal->DrawPolygon( polySet, displayMode == ZONE_DISPLAY_MODE::SHOW_TRIANGULATION );
1777  }
1778 }
1779 
1780 
1781 void PCB_PAINTER::draw( const PCB_DIMENSION_BASE* aDimension, int aLayer )
1782 {
1783  const COLOR4D& strokeColor = m_pcbSettings.GetColor( aDimension, aLayer );
1784 
1785  m_gal->SetStrokeColor( strokeColor );
1786  m_gal->SetIsFill( false );
1787  m_gal->SetIsStroke( true );
1788 
1790  {
1791  // Outline mode
1793  }
1794  else
1795  {
1796  // Filled mode
1797  m_gal->SetLineWidth( getLineThickness( aDimension->GetLineThickness() ) );
1798  }
1799 
1800  // Draw dimension shapes
1801  // TODO(JE) lift this out
1802  for( const std::shared_ptr<SHAPE>& shape : aDimension->GetShapes() )
1803  {
1804  switch( shape->Type() )
1805  {
1806  case SH_SEGMENT:
1807  {
1808  const SEG& seg = static_cast<const SHAPE_SEGMENT*>( shape.get() )->GetSeg();
1809  m_gal->DrawLine( seg.A, seg.B );
1810  break;
1811  }
1812 
1813  case SH_CIRCLE:
1814  {
1815  int radius = static_cast<const SHAPE_CIRCLE*>( shape.get() )->GetRadius();
1816  m_gal->DrawCircle( shape->Centre(), radius );
1817  break;
1818  }
1819 
1820  default:
1821  break;
1822  }
1823  }
1824 
1825  // Draw text
1826  const PCB_TEXT& text = aDimension->Text();
1827  VECTOR2D position( text.GetTextPos().x, text.GetTextPos().y );
1828 
1830  {
1831  // Outline mode
1833  }
1834  else
1835  {
1836  // Filled mode
1837  m_gal->SetLineWidth( getLineThickness( text.GetEffectiveTextPenWidth() ) );
1838  }
1839 
1841  m_gal->StrokeText( text.GetShownText(), position, text.GetTextAngleRadians() );
1842 }
1843 
1844 
1845 void PCB_PAINTER::draw( const PCB_TARGET* aTarget )
1846 {
1847  const COLOR4D& strokeColor = m_pcbSettings.GetColor( aTarget, aTarget->GetLayer() );
1848  VECTOR2D position( aTarget->GetPosition() );
1849  double size, radius;
1850 
1851  m_gal->SetLineWidth( getLineThickness( aTarget->GetWidth() ) );
1852  m_gal->SetStrokeColor( strokeColor );
1853  m_gal->SetIsFill( false );
1854  m_gal->SetIsStroke( true );
1855 
1856  m_gal->Save();
1857  m_gal->Translate( position );
1858 
1859  if( aTarget->GetShape() )
1860  {
1861  // shape x
1862  m_gal->Rotate( M_PI / 4.0 );
1863  size = 2.0 * aTarget->GetSize() / 3.0;
1864  radius = aTarget->GetSize() / 2.0;
1865  }
1866  else
1867  {
1868  // shape +
1869  size = aTarget->GetSize() / 2.0;
1870  radius = aTarget->GetSize() / 3.0;
1871  }
1872 
1873  m_gal->DrawLine( VECTOR2D( -size, 0.0 ), VECTOR2D( size, 0.0 ) );
1874  m_gal->DrawLine( VECTOR2D( 0.0, -size ), VECTOR2D( 0.0, size ) );
1875  m_gal->DrawCircle( VECTOR2D( 0.0, 0.0 ), radius );
1876 
1877  m_gal->Restore();
1878 }
1879 
1880 
1881 void PCB_PAINTER::draw( const PCB_MARKER* aMarker, int aLayer )
1882 {
1883  bool isShadow = aLayer == LAYER_MARKER_SHADOWS;
1884 
1885  // Don't paint shadows for invisible markers.
1886  // It would be nice to do this through layer dependencies but we can't do an "or" there today
1887  if( isShadow && aMarker->GetBoard()
1888  && !aMarker->GetBoard()->IsElementVisible( aMarker->GetColorLayer() ) )
1889  {
1890  return;
1891  }
1892 
1893  SHAPE_LINE_CHAIN polygon;
1894  aMarker->ShapeToPolygon( polygon );
1895 
1897  : aMarker->GetColorLayer() );
1898 
1899  m_gal->Save();
1900  m_gal->Translate( aMarker->GetPosition() );
1901 
1902  if( isShadow )
1903  {
1905  m_gal->SetIsStroke( true );
1906  m_gal->SetLineWidth( aMarker->MarkerScale() );
1907  }
1908  else
1909  {
1910  m_gal->SetFillColor( color );
1911  m_gal->SetIsFill( true );
1912  }
1913 
1914  m_gal->DrawPolygon( polygon );
1915  m_gal->Restore();
1916 }
1917 
1918 
1919 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:174
virtual void DrawPolyline(const std::deque< VECTOR2D > &aPointList)
Draw a polyline.
smd pads, front layer
Definition: layer_ids.h:197
to draw micro vias
Definition: layer_ids.h:189
virtual wxPoint GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_track.h:282
virtual void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a rectangle.
Arcs (with rounded ends)
bool IsFilled() const
Definition: pcb_shape.h:75
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
Definition: shape_simple.h:41
Bezier Curve.
SHAPE_POLY_SET GetBoundingHull() const
Return a bounding polygon for the shapes and pads in the footprint.
Definition: footprint.cpp:787
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
Return a const reference to a given point in the polygon.
Definition: shape_simple.h:102
double GetOrientationRadians() const
Definition: footprint.h:192
int OutlineCount() const
Return the number of vertices in a given outline/hole.
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
polygon (not yet used for tracks, but could be in microwave apps)
COLOR4D Inverted() const
Returns an inverted color, alpha remains the same.
Definition: color4d.h:320
int GetRadius() const
Definition: shape_circle.h:107
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:236
COLOR4D & Brighten(double aFactor)
Makes the color brighter by a given factor.
Definition: color4d.h:212
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
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
virtual void BitmapText(const wxString &aText, const VECTOR2D &aPosition, double aRotationAngle)
Draw a text using a bitmap font.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:80
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
SHAPE_T GetShape() const
Definition: pcb_shape.h:110
VIATYPE GetViaType() const
Definition: pcb_track.h:354
double m_TrackOpacity
Opacity override for all tracks.
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:50
PCB_TEXT & Text()
int GetSize() const
Definition: pcb_target.h:62
bool IsFlippedX() const
Return true if flip flag for the X axis is set.
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:320
int GetRadius() const
Return the radius of this item.
Definition: pcb_shape.cpp:487
smd pads, back layer
Definition: layer_ids.h:198
int color
Definition: DXF_plotter.cpp:57
std::vector< wxPoint > GetRectCorners() const
Definition: pcb_shape.cpp:1048
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:457
Additional netnames layers (not associated with a PCB layer)
Definition: layer_ids.h:160
const wxPoint & GetBezierC2() const
Definition: pcb_shape.h:116
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
usual segment : line with rounded ends
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
anchor of items having an anchor point (texts, footprints)
Definition: layer_ids.h:196
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:308
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:306
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
Abstract dimension API.
Definition: pcb_dimension.h:95
const SHAPE_POLY_SET & GetFilledPolysList(PCB_LAYER_ID aLayer) const
Definition: zone.h:635
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
last value for this list
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,...
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
Definition: matrix3x3.h:265
to draw via holes (pad holes do not use this layer)
Definition: layer_ids.h:210
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.
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
virtual VECTOR2D getDrillSize(const PAD *aPad) const
Return drill size for a pad (internal units).
int GetNetnameLayer(int aLayer)
Returns a netname layer corresponding to the given layer.
Definition: layer_ids.h:932
to draw usual through hole vias
Definition: layer_ids.h:191
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
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
bool IsNetCopperLayer(LAYER_NUM aLayer)
Checks if the given layer is "net copper", meaning it is eligible for net coloring.
Definition: layer_ids.h:981
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:243
Container for display options like enable/disable some optional drawings.
bool IsHoleLayer(LAYER_NUM aLayer)
Definition: layer_ids.h:826
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:374
bool FlashLayer(int aLayer) const
Check to see whether the pad should be flashed on the specific layer.
Definition: pad.cpp:223
bool IsEntered() const
Definition: eda_item.h:124
int getLineThickness(int aActualThickness) const
Get the thickness to draw for a line (e.g.
handle color for not plated holes (holes, not pads)
Definition: layer_ids.h:192
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:244
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:800
wxString GetShortNetname() const
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:986
int PrintableCharCount(const wxString &aString)
Return the number of printable (ie: non-formatting) chars.
Represent a set of closed polygons.
static const COLOR4D CLEAR
Definition: color4d.h:382
SHAPE_LINE_CHAIN & Outline(int aIndex)
const wxPoint GetOrigin() const
Definition: eda_rect.h:101
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.
shadows for drc markers
Definition: layer_ids.h:232
double GetRadius() const
Definition: pcb_track.cpp:968
const wxPoint GetPosition() const
Definition: eda_rect.h:102
void SetBackgroundColor(const COLOR4D &aColor) override
Set the background color.
Definition: pcb_painter.h:150
const wxSize & GetSize() const
Definition: pad.h:233
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
void Deflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
const EDA_RECT GetBoundingBox() const override
The bounding box is cached, so this will be efficient most of the time.
Definition: pad.cpp:536
const wxPoint & GetBezierC1() const
Definition: pcb_shape.h:113
const wxString & GetNumber() const
Definition: pad.h:129
Virtual layers for stacking zones and tracks on a given copper layer.
Definition: layer_ids.h:241
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:146
PAD_SHAPE GetShape() const
Definition: pad.h:170
const SHAPE_LINE_CHAIN & Vertices() const
Return the list of vertices defining this simple polygon.
Definition: shape_simple.h:124
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:297
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:56
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
Return the number of segments in this line chain.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:463
int GetHeight() const
Definition: eda_rect.h:110
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:787
wxString UnescapeString(const wxString &aSource)
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:532
int GetSolderMaskMargin() const
Definition: pad.cpp:711
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:176
double GetTextAngleRadians() const
Definition: eda_text.h:177
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)
Return a copy of the aIndex-th segment in the line chain.
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:974
class PCB_MARKER, a marker used to show something
Definition: typeinfo.h:98
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.
void SetFontUnderlined(bool aUnderlined)
multilayer pads, usually with holes
Definition: layer_ids.h:208
const char * name
Definition: DXF_plotter.cpp:56
to draw blind/buried vias
Definition: layer_ids.h:190
wxSize GetSolderPasteMargin() const
Usually < 0 (mask shape smaller than pad)because the margin can be dependent on the pad size,...
Definition: pad.cpp:756
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:532
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: pad.h:354
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
Represent a polyline (an zero-thickness chain of connected line segments).
bool IsNetnameLayer(LAYER_NUM aLayer)
Test whether a layer is a netname layer.
Definition: layer_ids.h:955
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:64
COLOR4D & Darken(double aFactor)
Makes the color darker by a given factor.
Definition: color4d.h:229
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...
Definition: layer_ids.h:70
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
Return the number of points (vertices) in this polygon.
Definition: shape_simple.h:88
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:377
double DECIDEG2RAD(double deg)
Definition: trigo.h:233
ZONE_DISPLAY_MODE m_ZoneDisplayMode
int GetShape() const
Definition: pcb_target.h:59
HIGH_CONTRAST_MODE m_contrastModeDisplay
Definition: pcb_painter.h:213
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:73
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:186
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 background color.
Definition: layer_ids.h:215
PCB_PAINTER(GAL *aGal)
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:247
void TransformArcToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aStart, const wxPoint &aMid, const wxPoint &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc)
Convert arc to multiple straight segments.
to draw pad holes (plated)
Definition: layer_ids.h:209
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:50
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)
bool IsZoneLayer(LAYER_NUM aLayer)
Definition: layer_ids.h:962
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
segment with non rounded ends
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.
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
Definition of PCB_DISPLAY_OPTIONS class.
const wxPoint & GetMid() const
Definition: pcb_track.h:273
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)
virtual void DrawArcSegment(const VECTOR2D &aCenterPoint, double aRadius, double aStartAngle, double aEndAngle, double aWidth, double aMaxError)
Draw an arc segment.
const wxPoint & GetStart() const
Definition: pcb_track.h:108
COLOR4D m_layerColorsSel[LAYER_ID_COUNT]
const wxSize GetSize() const
Definition: eda_rect.h:91
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:689
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