KiCad PCB EDA Suite
sch_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) 2014 CERN
5  * Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * @author Tomasz Wlostowski <[email protected]>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 
28 #include <sch_item.h>
29 #include <trigo.h>
30 #include <bezier_curves.h>
31 #include <symbol_library.h>
32 #include <connection_graph.h>
36 #include <gr_text.h>
37 #include <lib_shape.h>
38 #include <lib_field.h>
39 #include <lib_item.h>
40 #include <lib_pin.h>
41 #include <lib_text.h>
42 #include <math/util.h>
43 #include <plotters/plotter.h>
44 #include <sch_bitmap.h>
45 #include <sch_bus_entry.h>
46 #include <sch_symbol.h>
47 #include <sch_edit_frame.h>
48 #include <sch_field.h>
49 #include <sch_junction.h>
50 #include <sch_line.h>
51 #include <sch_marker.h>
52 #include <sch_no_connect.h>
53 #include <sch_sheet.h>
54 #include <sch_sheet_pin.h>
55 #include <sch_text.h>
56 #include <schematic.h>
58 #include <view/view.h>
59 #include <kiface_base.h>
60 #include <default_values.h>
61 #include <advanced_config.h>
62 #include <string_utils.h>
63 #include "sch_painter.h"
64 
65 namespace KIGFX
66 {
67 
69  m_IsSymbolEditor( false ),
70  m_ShowUnit( 0 ),
71  m_ShowConvert( 0 ),
72  m_ShowHiddenText( true ),
73  m_ShowHiddenPins( true ),
74  m_ShowPinsElectricalType( true ),
75  m_ShowDisabled( false ),
76  m_ShowGraphicsDisabled( false ),
77  m_ShowUmbilicals( true ),
78  m_OverrideItemColors( false ),
79  m_LabelSizeRatio( DEFAULT_LABEL_SIZE_RATIO ),
80  m_TextOffsetRatio( DEFAULT_TEXT_OFFSET_RATIO ),
81  m_PinSymbolSize( DEFAULT_TEXT_SIZE * IU_PER_MILS / 2 ),
82  m_JunctionSize( DEFAULT_JUNCTION_DIAM * IU_PER_MILS )
83 {
85 
87 }
88 
89 
91 {
92  for( int layer = SCH_LAYER_ID_START; layer < SCH_LAYER_ID_END; layer ++)
93  m_layerColors[ layer ] = aSettings->GetColor( layer );
94 
95  for( int layer = GAL_LAYER_ID_START; layer < GAL_LAYER_ID_END; layer ++)
96  m_layerColors[ layer ] = aSettings->GetColor( layer );
97 
99 
101 
103 }
104 
105 
106 COLOR4D SCH_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) const
107 {
108  return m_layerColors[ aLayer ];
109 }
110 
111 
113 {
114  return dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
115 }
116 
117 
131 static LIB_SYMBOL* dummy()
132 {
133  static LIB_SYMBOL* symbol;
134 
135  if( !symbol )
136  {
137  symbol = new LIB_SYMBOL( wxEmptyString );
138 
139  LIB_SHAPE* square = new LIB_SHAPE( symbol, SHAPE_T::RECT );
140 
141  square->MoveTo( wxPoint( Mils2iu( -200 ), Mils2iu( 200 ) ) );
142  square->SetEnd( wxPoint( Mils2iu( 200 ), Mils2iu( -200 ) ) );
143 
144  LIB_TEXT* text = new LIB_TEXT( symbol );
145 
146  text->SetTextSize( wxSize( Mils2iu( 150 ), Mils2iu( 150 ) ) );
147  text->SetText( wxString( wxT( "??" ) ) );
148 
149  symbol->AddDrawItem( square );
150  symbol->AddDrawItem( text );
151  }
152 
153  return symbol;
154 }
155 
156 
158  KIGFX::PAINTER( aGal ),
159  m_schematic( nullptr )
160 { }
161 
162 
163 #define HANDLE_ITEM( type_id, type_name ) \
164  case type_id: draw( (type_name *) item, aLayer ); break
165 
166 
167 bool SCH_PAINTER::Draw( const VIEW_ITEM *aItem, int aLayer )
168 {
169  const auto item = dynamic_cast<const EDA_ITEM*>( aItem );
170 
171  if( !item )
172  return false;
173 
174 #ifdef CONNECTIVITY_DEBUG
175 
176  auto sch_item = dynamic_cast<const SCH_ITEM*>( item );
177  auto conn = sch_item ? sch_item->Connection( *g_CurrentSheet ) : nullptr;
178 
179  if( conn )
180  {
181  auto pos = item->GetBoundingBox().Centre();
182  auto label = conn->Name( true );
183 
187  m_gal->SetLineWidth( Mils2ui( 2 ) );
188  m_gal->SetGlyphSize( VECTOR2D( Mils2ui( 20 ), Mils2ui( 20 ) ) );
189  m_gal->StrokeText( conn->Name( true ), pos, 0.0, 0 );
190  }
191 
192 #endif
193 
195  {
196  BOX2I box = item->GetBoundingBox();
197 
198  if( item->Type() == SCH_SYMBOL_T )
199  box = static_cast<const SCH_SYMBOL*>( item )->GetBodyBoundingBox();
200 
201  m_gal->SetIsFill( false );
202  m_gal->SetIsStroke( true );
203  m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 )
204  : COLOR4D( 0.2, 0.2, 0.2, 1 ) );
205  m_gal->SetLineWidth( Mils2iu( 3 ) );
206  m_gal->DrawRectangle( box.GetOrigin(), box.GetEnd() );
207  }
208 
209  switch( item->Type() )
210  {
231 
232  default: return false;
233  }
234 
235  return false;
236 }
237 
238 
240 {
241  if( m_schSettings.m_ShowUnit // showing a specific unit
242  && aItem->GetUnit() // item is unit-specific
243  && aItem->GetUnit() != m_schSettings.m_ShowUnit )
244  {
245  return false;
246  }
247 
248  if( m_schSettings.m_ShowConvert // showing a specific conversion
249  && aItem->GetConvert() // item is conversion-specific
250  && aItem->GetConvert() != m_schSettings.m_ShowConvert )
251  {
252  return false;
253  }
254 
255  return true;
256 }
257 
258 
260 {
261  const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
262 
263  // For best visuals the selection width must be a cross between the zoom level and the
264  // default line width.
265  return (float) std::fabs( matrix.GetScale().x * 2.75 ) +
266  Mils2iu( eeconfig()->m_Selection.thickness );
267 }
268 
269 
270 COLOR4D SCH_PAINTER::getRenderColor( const EDA_ITEM* aItem, int aLayer, bool aDrawingShadows ) const
271 {
273 
274  if( aItem->Type() == SCH_LINE_T )
275  {
276  COLOR4D lineColor = static_cast<const SCH_LINE*>( aItem )->GetLineColor();
277 
278  if( lineColor != COLOR4D::UNSPECIFIED )
279  color = lineColor;
280  }
281  else if( aItem->Type() == SCH_BUS_WIRE_ENTRY_T )
282  {
283  COLOR4D busEntryColor = static_cast<const SCH_BUS_WIRE_ENTRY*>( aItem )->GetStrokeColor();
284 
285  if( busEntryColor != COLOR4D::UNSPECIFIED )
286  color = busEntryColor;
287  }
288  else if( aItem->Type() == SCH_JUNCTION_T )
289  {
290  COLOR4D junctionColor = static_cast<const SCH_JUNCTION*>( aItem )->GetJunctionColor();
291 
292  if( junctionColor != COLOR4D::UNSPECIFIED )
293  color = junctionColor;
294  }
295  else if( aItem->Type() == SCH_SHEET_T )
296  {
297  SCH_SHEET* sheet = (SCH_SHEET*) aItem;
298 
300  color = m_schSettings.GetLayerColor( aLayer );
301  else if( aLayer == LAYER_SHEET )
302  color = sheet->GetBorderColor();
303  else if( aLayer == LAYER_SHEET_BACKGROUND )
304  color = sheet->GetBackgroundColor();
305 
306  if( color == COLOR4D::UNSPECIFIED )
307  color = m_schSettings.GetLayerColor( aLayer );
308  }
309 
310  if( aItem->IsBrightened() && !aDrawingShadows ) // Selection disambiguation, etc.
311  {
313 
314  if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_SHEET_BACKGROUND )
315  color = color.WithAlpha( 0.2 );
316  }
317  else if( aItem->IsSelected() )
318  {
319  if( aDrawingShadows )
321  }
322 
324  || ( m_schSettings.m_ShowGraphicsDisabled && aItem->Type() != LIB_FIELD_T ) )
325  {
326  color = color.Darken( 0.5f );
327  }
328 
329  return color;
330 }
331 
332 
333 float SCH_PAINTER::getLineWidth( const LIB_ITEM* aItem, bool aDrawingShadows ) const
334 {
335  float width = (float) aItem->GetEffectivePenWidth( &m_schSettings );
336 
337  if( aItem->IsSelected() && aDrawingShadows )
338  width += getShadowWidth();
339 
340  return width;
341 }
342 
343 
344 float SCH_PAINTER::getLineWidth( const SCH_ITEM* aItem, bool aDrawingShadows ) const
345 {
346  wxCHECK( aItem, static_cast<float>( Mils2iu( DEFAULT_WIRE_WIDTH_MILS ) ) );
347 
348  float width = (float) aItem->GetPenWidth();
349 
350  if( aItem->IsSelected() && aDrawingShadows )
351  width += getShadowWidth();
352 
353  return std::max( width, 1.0f );
354 }
355 
356 
357 float SCH_PAINTER::getTextThickness( const SCH_TEXT* aItem, bool aDrawingShadows ) const
358 {
359  float width = (float) aItem->GetEffectiveTextPenWidth( m_schSettings.GetDefaultPenWidth() );
360 
361  if( aItem->IsSelected() && aDrawingShadows )
362  width += getShadowWidth();
363 
364  return width;
365 }
366 
367 
368 float SCH_PAINTER::getTextThickness( const SCH_FIELD* aItem, bool aDrawingShadows ) const
369 {
370  float width = (float) aItem->GetEffectiveTextPenWidth( m_schSettings.GetDefaultPenWidth() );
371 
372  if( aItem->IsSelected() && aDrawingShadows )
373  width += getShadowWidth();
374 
375  return width;
376 }
377 
378 
379 float SCH_PAINTER::getTextThickness( const LIB_FIELD* aItem, bool aDrawingShadows ) const
380 {
381  float width = (float) std::max( aItem->GetEffectiveTextPenWidth(),
383 
384  if( aItem->IsSelected() && aDrawingShadows )
385  width += getShadowWidth();
386 
387  return width;
388 }
389 
390 
391 float SCH_PAINTER::getTextThickness( const LIB_TEXT* aItem, bool aDrawingShadows ) const
392 {
393  float width = (float) std::max( aItem->GetEffectiveTextPenWidth(),
395 
396  if( aItem->IsSelected() && aDrawingShadows )
397  width += getShadowWidth();
398 
399  return width;
400 }
401 
402 
403 static VECTOR2D mapCoords( const wxPoint& aCoord )
404 {
405  return VECTOR2D( aCoord.x, -aCoord.y );
406 }
407 
408 
409 void SCH_PAINTER::strokeText( const wxString& aText, const VECTOR2D& aPosition, double aAngle )
410 {
411  m_gal->StrokeText( aText, VECTOR2D( aPosition.x, aPosition.y ), aAngle );
412 }
413 
414 
415 void SCH_PAINTER::boxText( const wxString& aText, const VECTOR2D& aPosition, double aAngle )
416 {
417  const STROKE_FONT& font = m_gal->GetStrokeFont();
418  VECTOR2D extents = font.ComputeStringBoundaryLimits( aText, m_gal->GetGlyphSize(),
419  m_gal->GetLineWidth() );
420  EDA_RECT box( (wxPoint) aPosition, wxSize( extents.x, extents.y ) );
421 
423  box.SetX( box.GetX() - ( box.GetWidth() / 2) );
425  box.SetX( box.GetX() - box.GetWidth() );
426 
428  box.SetY( box.GetY() - ( box.GetHeight() / 2) );
430  box.SetY( box.GetY() - box.GetHeight() );
431 
432  box.Normalize(); // Make h and v sizes always >= 0
433  box = box.GetBoundingBoxRotated((wxPoint) aPosition, RAD2DECIDEG( aAngle ) );
434  box.RevertYAxis();
435  m_gal->DrawRectangle( mapCoords( box.GetOrigin() ), mapCoords( box.GetEnd() ) );
436 }
437 
438 
439 void SCH_PAINTER::triLine( const VECTOR2D &a, const VECTOR2D &b, const VECTOR2D &c )
440 {
441  m_gal->DrawLine( a, b );
442  m_gal->DrawLine( b, c );
443 }
444 
445 
446 void SCH_PAINTER::draw( const LIB_SYMBOL *aSymbol, int aLayer, bool aDrawFields, int aUnit, int aConvert )
447 {
448  if( !aUnit )
449  aUnit = m_schSettings.m_ShowUnit;
450 
451  if( !aConvert )
452  aConvert = m_schSettings.m_ShowConvert;
453 
454  std::unique_ptr< LIB_SYMBOL > tmpSymbol;
455  const LIB_SYMBOL* drawnSymbol = aSymbol;
456 
457  if( aSymbol->IsAlias() )
458  {
459  tmpSymbol = aSymbol->Flatten();
460  drawnSymbol = tmpSymbol.get();
461  }
462 
463  for( const LIB_ITEM& item : drawnSymbol->GetDrawItems() )
464  {
465  if( !aDrawFields && item.Type() == LIB_FIELD_T )
466  continue;
467 
468  if( aUnit && item.GetUnit() && aUnit != item.GetUnit() )
469  continue;
470 
471  if( aConvert && item.GetConvert() && aConvert != item.GetConvert() )
472  continue;
473 
474  Draw( &item, aLayer );
475  }
476 }
477 
478 
479 bool SCH_PAINTER::setDeviceColors( const LIB_ITEM* aItem, int aLayer )
480 {
481  const EDA_SHAPE* shape = dynamic_cast<const EDA_SHAPE*>( aItem );
482 
483  switch( aLayer )
484  {
486  if( aItem->IsSelected() )
487  {
488  m_gal->SetIsFill( false );
489  m_gal->SetIsStroke( true );
490  m_gal->SetLineWidth( getLineWidth( aItem, true ) );
491  m_gal->SetStrokeColor( getRenderColor( aItem, LAYER_DEVICE, true ) );
492  m_gal->SetFillColor( getRenderColor( aItem, LAYER_DEVICE, true ) );
493  return true;
494  }
495 
496  return false;
497 
499  if( shape && shape->GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
500  {
501  COLOR4D fillColor = getRenderColor( aItem, LAYER_DEVICE_BACKGROUND, false );
502 
504  m_gal->SetFillColor( fillColor );
505  m_gal->SetIsStroke( false );
506  return true;
507  }
508 
509  return false;
510 
511  case LAYER_DEVICE:
512  m_gal->SetIsFill( shape && shape->GetFillType() == FILL_T::FILLED_SHAPE );
513  m_gal->SetFillColor( getRenderColor( aItem, LAYER_DEVICE, false ) );
514 
515  if( aItem->GetPenWidth() >= 0 || !shape || !shape->IsFilled() )
516  {
517  m_gal->SetIsStroke( true );
518  m_gal->SetLineWidth( getLineWidth( aItem, false ) );
519  m_gal->SetStrokeColor( getRenderColor( aItem, LAYER_DEVICE, false ) );
520  }
521  else
522  {
523  m_gal->SetIsStroke( false );
524  }
525 
526  return true;
527 
528  default:
529  return false;
530  }
531 }
532 
533 
534 void SCH_PAINTER::draw( const LIB_SHAPE *aShape, int aLayer )
535 {
536  if( !isUnitAndConversionShown( aShape ) )
537  return;
538 
539  if( setDeviceColors( aShape, aLayer ) )
540  {
541  if( aLayer == LAYER_SELECTION_SHADOWS && eeconfig()->m_Selection.fill_shapes )
542  {
543  // Consider a NAND gate. We have no idea which side of the arc is "inside" so
544  // we can't reliably fill.
545 
546  if( aShape->GetShape() == SHAPE_T::ARC )
547  m_gal->SetIsFill( aShape->IsFilled() );
548  else
549  m_gal->SetIsFill( true );
550  }
551 
552  switch( aShape->GetShape() )
553  {
554  case SHAPE_T::ARC:
555  {
556  int startAngle;
557  int endAngle;
558  aShape->CalcArcAngles( startAngle, endAngle );
559 
560  TRANSFORM().MapAngles( &startAngle, &endAngle );
561 
562  m_gal->DrawArc( mapCoords( aShape->GetCenter() ), aShape->GetRadius(),
563  DECIDEG2RAD( startAngle ), DECIDEG2RAD( endAngle ) );
564  }
565  break;
566 
567  case SHAPE_T::CIRCLE:
568  m_gal->DrawCircle( mapCoords( aShape->GetPosition() ), aShape->GetRadius() );
569  break;
570 
571  case SHAPE_T::RECT:
572  m_gal->DrawRectangle( mapCoords( aShape->GetPosition() ),
573  mapCoords( aShape->GetEnd() ) );
574  break;
575 
576  case SHAPE_T::POLY:
577  {
578  const SHAPE_LINE_CHAIN poly = aShape->GetPolyShape().Outline( 0 );
579  std::deque<VECTOR2D> mappedPts;
580 
581  for( const VECTOR2I& pt : poly.CPoints() )
582  mappedPts.push_back( mapCoords( (wxPoint) pt ) );
583 
584  m_gal->DrawPolygon( mappedPts );
585  }
586  break;
587 
588  case SHAPE_T::BEZIER:
589  {
590  std::deque<VECTOR2D> mappedPts;
591 
592  for( const wxPoint& p : aShape->GetBezierPoints() )
593  mappedPts.push_back( mapCoords( p ) );
594 
595  m_gal->DrawPolygon( mappedPts );
596  }
597  break;
598 
599  default:
600  wxFAIL_MSG( wxT( "SCH_PAINTER::draw not implemented for " ) + aShape->SHAPE_T_asString() );
601  }
602  }
603 }
604 
605 
606 void SCH_PAINTER::draw( const LIB_FIELD *aField, int aLayer )
607 {
608  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
609 
610  if( drawingShadows && !aField->IsSelected() )
611  return;
612 
613  if( !isUnitAndConversionShown( aField ) )
614  return;
615 
616  // Must check layer as fields are sometimes drawn by their parent rather than
617  // directly from the view.
618  int layers[KIGFX::VIEW::VIEW_MAX_LAYERS];
619  int layers_count;
620  bool foundLayer = false;
621 
622  aField->ViewGetLayers( layers, layers_count );
623 
624  for( int i = 0; i < layers_count; ++i )
625  {
626  if( layers[i] == aLayer )
627  foundLayer = true;
628  }
629 
630  if( !foundLayer )
631  return;
632 
633  COLOR4D color = getRenderColor( aField, aLayer, drawingShadows );
634 
635  if( !( aField->IsVisible() || aField->IsForceVisible() ) )
636  {
638  color = getRenderColor( aField, LAYER_HIDDEN, drawingShadows );
639  else
640  return;
641  }
642 
643  m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
644  m_gal->SetIsFill( false );
645  m_gal->SetIsStroke( true );
647 
648  EDA_RECT bbox = aField->GetBoundingBox();
649  wxPoint textpos = bbox.Centre();
650 
651  if( drawingShadows && eeconfig()->m_Selection.text_as_box )
652  {
653  m_gal->SetIsFill( true );
655  m_gal->SetLineWidth( m_gal->GetLineWidth() * 0.5 );
656  bbox.RevertYAxis();
657 
658  m_gal->DrawRectangle( mapCoords( bbox.GetPosition() ), mapCoords( bbox.GetEnd() ) );
659  }
660  else
661  {
664  m_gal->SetGlyphSize( VECTOR2D( aField->GetTextSize() ) );
665  m_gal->SetFontItalic( aField->IsItalic() );
666 
667  strokeText( UnescapeString( aField->GetText() ), textpos, aField->GetTextAngleRadians() );
668  }
669 
670  // Draw the umbilical line
671  if( aField->IsMoving() && m_schSettings.m_ShowUmbilicals )
672  {
674  m_gal->SetStrokeColor( getRenderColor( aField, LAYER_SCHEMATIC_ANCHOR, drawingShadows ) );
675  m_gal->DrawLine( textpos, wxPoint( 0, 0 ) );
676  }
677 }
678 
679 
680 void SCH_PAINTER::draw( const LIB_TEXT *aText, int aLayer )
681 {
682  if( !isUnitAndConversionShown( aText ) )
683  return;
684 
685  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
686 
687  if( drawingShadows && !aText->IsSelected() )
688  return;
689 
690  COLOR4D color = getRenderColor( aText, LAYER_DEVICE, drawingShadows );
691 
692  if( !aText->IsVisible() )
693  {
695  color = getRenderColor( aText, LAYER_HIDDEN, drawingShadows );
696  else
697  return;
698  }
699 
700  EDA_RECT bBox = aText->GetBoundingBox();
701  bBox.RevertYAxis();
702  VECTOR2D pos = mapCoords( bBox.Centre() );
703  double orient = aText->GetTextAngleRadians();
704 
707  m_gal->SetLineWidth( getTextThickness( aText, drawingShadows ) );
708  m_gal->SetIsFill( false );
709  m_gal->SetIsStroke( true );
711  m_gal->SetGlyphSize( VECTOR2D( aText->GetTextSize() ) );
712  m_gal->SetFontBold( aText->IsBold() );
713  m_gal->SetFontItalic( aText->IsItalic() );
714  m_gal->SetFontUnderlined( false );
715  strokeText( aText->GetText(), pos, orient );
716 }
717 
718 
720 {
723 
724  return aPin.GetNameTextSize() != 0 ? aPin.GetNameTextSize() / 2 : aPin.GetNumberTextSize() / 2;
725 }
726 
727 
728 // Utility for getting the size of the 'external' pin decorators (as a radius)
729 // i.e. the negation circle, the polarity 'slopes' and the nonlogic marker
731 {
734 
735  return aPin.GetNumberTextSize() / 2;
736 }
737 
738 
739 // Draw the target (an open circle) for a pin which has no connection or is being moved.
740 void SCH_PAINTER::drawPinDanglingSymbol( const VECTOR2I& aPos, const COLOR4D& aColor,
741  bool aDrawingShadows )
742 {
743  // Dangling symbols must be drawn in a slightly different colour so they can be seen when
744  // they overlap with a junction dot.
745  m_gal->SetStrokeColor( aColor.Brightened( 0.3 ) );
746 
747  m_gal->SetIsFill( false );
748  m_gal->SetIsStroke( true );
749  m_gal->SetLineWidth( aDrawingShadows ? getShadowWidth()
751 
753 }
754 
755 
756 void SCH_PAINTER::draw( LIB_PIN *aPin, int aLayer )
757 {
758  if( !isUnitAndConversionShown( aPin ) )
759  return;
760 
761  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
762  bool drawingDangling = aLayer == LAYER_DANGLING;
763  bool isDangling = m_schSettings.m_IsSymbolEditor || aPin->HasFlag( IS_DANGLING );
764 
765  if( drawingShadows && !aPin->IsSelected() )
766  return;
767 
768  VECTOR2I pos = mapCoords( aPin->GetPosition() );
769  COLOR4D color = getRenderColor( aPin, LAYER_PIN, drawingShadows );
770 
771  if( !aPin->IsVisible() )
772  {
774  {
775  color = getRenderColor( aPin, LAYER_HIDDEN, drawingShadows );
776  }
777  else
778  {
779  if( drawingDangling && isDangling && aPin->IsPowerConnection() )
780  drawPinDanglingSymbol( pos, color, drawingShadows );
781 
782  return;
783  }
784  }
785 
786  if( drawingDangling )
787  {
788  if( isDangling )
789  drawPinDanglingSymbol( pos, color, drawingShadows );
790 
791  return;
792  }
793 
794  VECTOR2I p0;
795  VECTOR2I dir;
796  int len = aPin->GetLength();
797  int orient = aPin->GetOrientation();
798 
799  switch( orient )
800  {
801  case PIN_UP:
802  p0 = VECTOR2I( pos.x, pos.y - len );
803  dir = VECTOR2I( 0, 1 );
804  break;
805 
806  case PIN_DOWN:
807  p0 = VECTOR2I( pos.x, pos.y + len );
808  dir = VECTOR2I( 0, -1 );
809  break;
810 
811  case PIN_LEFT:
812  p0 = VECTOR2I( pos.x - len, pos.y );
813  dir = VECTOR2I( 1, 0 );
814  break;
815 
816  default:
817  case PIN_RIGHT:
818  p0 = VECTOR2I( pos.x + len, pos.y );
819  dir = VECTOR2I( -1, 0 );
820  break;
821  }
822 
823  VECTOR2D pc;
824 
825  m_gal->SetIsStroke( true );
826  m_gal->SetIsFill( false );
827  m_gal->SetLineWidth( getLineWidth( aPin, drawingShadows ) );
829  m_gal->SetFontBold( false );
830  m_gal->SetFontUnderlined( false );
831  m_gal->SetFontItalic( false );
832 
833  const int radius = externalPinDecoSize( *aPin );
834  const int diam = radius*2;
835  const int clock_size = internalPinDecoSize( *aPin );
836 
837  if( aPin->GetType() == ELECTRICAL_PINTYPE::PT_NC ) // Draw a N.C. symbol
838  {
839  m_gal->DrawLine( p0, pos );
840 
841  m_gal->DrawLine( pos + VECTOR2D( -1, -1 ) * TARGET_PIN_RADIUS,
842  pos + VECTOR2D( 1, 1 ) * TARGET_PIN_RADIUS );
843  m_gal->DrawLine( pos + VECTOR2D( 1, -1 ) * TARGET_PIN_RADIUS ,
844  pos + VECTOR2D( -1, 1 ) * TARGET_PIN_RADIUS );
845  }
846  else
847  {
848  switch( aPin->GetShape() )
849  {
851  m_gal->DrawLine( p0, pos );
852  break;
853 
855  m_gal->DrawCircle( p0 + dir * radius, radius );
856  m_gal->DrawLine( p0 + dir * ( diam ), pos );
857  break;
858 
860  pc = p0 - dir * clock_size ;
861 
862  triLine( p0 + VECTOR2D( dir.y, -dir.x) * clock_size,
863  pc,
864  p0 + VECTOR2D( -dir.y, dir.x) * clock_size );
865 
866  m_gal->DrawCircle( p0 + dir * radius, radius );
867  m_gal->DrawLine( p0 + dir * ( diam ), pos );
868  break;
869 
872  pc = p0 - dir * clock_size ;
873 
874  triLine( p0 + VECTOR2D( dir.y, -dir.x) * clock_size,
875  pc,
876  p0 + VECTOR2D( -dir.y, dir.x) * clock_size );
877 
878  if( !dir.y )
879  {
880  triLine( p0 + VECTOR2D(dir.x, 0) * diam,
881  p0 + VECTOR2D(dir.x, -1) * diam,
882  p0 );
883  }
884  else /* MapX1 = 0 */
885  {
886  triLine( p0 + VECTOR2D( 0, dir.y) * diam,
887  p0 + VECTOR2D(-1, dir.y) * diam,
888  p0 );
889  }
890 
891  m_gal->DrawLine( p0, pos );
892  break;
893 
895  m_gal->DrawLine( p0, pos );
896 
897  if( !dir.y )
898  {
899  triLine( p0 + VECTOR2D( 0, clock_size ),
900  p0 + VECTOR2D( -dir.x * clock_size, 0 ),
901  p0 + VECTOR2D( 0, -clock_size ) );
902  }
903  else
904  {
905  triLine( p0 + VECTOR2D( clock_size, 0 ),
906  p0 + VECTOR2D( 0, -dir.y * clock_size ),
907  p0 + VECTOR2D( -clock_size, 0 ) );
908  }
909  break;
910 
912  m_gal->DrawLine( p0, pos );
913 
914  if( !dir.y )
915  {
916  triLine( p0 + VECTOR2D(dir.x, 0) * diam,
917  p0 + VECTOR2D(dir.x, -1) * diam,
918  p0 );
919  }
920  else /* MapX1 = 0 */
921  {
922  triLine( p0 + VECTOR2D( 0, dir.y) * diam,
923  p0 + VECTOR2D(-1, dir.y) * diam,
924  p0 );
925  }
926  break;
927 
928  case GRAPHIC_PINSHAPE::OUTPUT_LOW: // IEEE symbol "Active Low Output"
929  m_gal->DrawLine( p0, pos );
930 
931  if( !dir.y ) // Horizontal pin
932  m_gal->DrawLine( p0 - VECTOR2D( 0, diam ), p0 + VECTOR2D( dir.x, 0 ) * diam );
933  else // Vertical pin
934  m_gal->DrawLine( p0 - VECTOR2D( diam, 0 ), p0 + VECTOR2D( 0, dir.y ) * diam );
935  break;
936 
937  case GRAPHIC_PINSHAPE::NONLOGIC: // NonLogic pin symbol
938  m_gal->DrawLine( p0, pos );
939 
940  m_gal->DrawLine( p0 - VECTOR2D( dir.x + dir.y, dir.y - dir.x ) * radius,
941  p0 + VECTOR2D( dir.x + dir.y, dir.y - dir.x ) * radius );
942  m_gal->DrawLine( p0 - VECTOR2D( dir.x - dir.y, dir.x + dir.y ) * radius,
943  p0 + VECTOR2D( dir.x - dir.y, dir.x + dir.y ) * radius );
944  break;
945  }
946  }
947 
948  LIB_SYMBOL* libEntry = aPin->GetParent();
949 
950  // Draw the labels
951  if( drawingShadows
952  && ( libEntry->Type() == LIB_SYMBOL_T || libEntry->IsSelected() )
954  {
955  return;
956  }
957 
958  float penWidth = (float) m_schSettings.GetDefaultPenWidth();
959  int textOffset = libEntry->GetPinNameOffset();
960  float nameStrokeWidth = getLineWidth( aPin, drawingShadows );
961  float numStrokeWidth = getLineWidth( aPin, drawingShadows );
962 
963  nameStrokeWidth = Clamp_Text_PenSize( nameStrokeWidth, aPin->GetNameTextSize(), false );
964  numStrokeWidth = Clamp_Text_PenSize( numStrokeWidth, aPin->GetNumberTextSize(), false );
965 
967 
968  // Four locations around a pin where text can be drawn
969  enum { INSIDE = 0, OUTSIDE, ABOVE, BELOW };
970  int size[4] = { 0, 0, 0, 0 };
971  float thickness[4] = { numStrokeWidth, numStrokeWidth, numStrokeWidth, numStrokeWidth };
972  COLOR4D colour[4];
973  wxString text[4];
974 
975  // TextOffset > 0 means pin NAMES on inside, pin NUMBERS above and nothing below
976  if( textOffset )
977  {
978  size [INSIDE] = libEntry->ShowPinNames() ? aPin->GetNameTextSize() : 0;
979  thickness[INSIDE] = nameStrokeWidth;
980  colour [INSIDE] = getRenderColor( aPin, LAYER_PINNAM, drawingShadows );
981  text [INSIDE] = aPin->GetShownName();
982 
983  size [ABOVE] = libEntry->ShowPinNumbers() ? aPin->GetNumberTextSize() : 0;
984  thickness[ABOVE] = numStrokeWidth;
985  colour [ABOVE] = getRenderColor( aPin, LAYER_PINNUM, drawingShadows );
986  text [ABOVE] = aPin->GetShownNumber();
987  }
988  // Otherwise pin NAMES go above and pin NUMBERS go below
989  else
990  {
991  size [ABOVE] = libEntry->ShowPinNames() ? aPin->GetNameTextSize() : 0;
992  thickness[ABOVE] = nameStrokeWidth;
993  colour [ABOVE] = getRenderColor( aPin, LAYER_PINNAM, drawingShadows );
994  text [ABOVE] = aPin->GetShownName();
995 
996  size [BELOW] = libEntry->ShowPinNumbers() ? aPin->GetNumberTextSize() : 0;
997  thickness[BELOW] = numStrokeWidth;
998  colour [BELOW] = getRenderColor( aPin, LAYER_PINNUM, drawingShadows );
999  text [BELOW] = aPin->GetShownNumber();
1000  }
1001 
1003  {
1004  size [OUTSIDE] = std::max( aPin->GetNameTextSize() * 3 / 4, Millimeter2iu( 0.7 ) );
1005  thickness[OUTSIDE] = float( size[OUTSIDE] ) / 6.0F;
1006  colour [OUTSIDE] = getRenderColor( aPin, LAYER_NOTES, drawingShadows );
1007  text [OUTSIDE] = aPin->GetElectricalTypeName();
1008  }
1009 
1010  if( !aPin->IsVisible() )
1011  {
1012  for( COLOR4D& c : colour )
1013  c = getRenderColor( aPin, LAYER_HIDDEN, drawingShadows );
1014  }
1015 
1016  float insideOffset = textOffset - thickness[INSIDE] / 2.0;
1017  float outsideOffset = Mils2iu( PIN_TEXT_MARGIN ) + TARGET_PIN_RADIUS - thickness[OUTSIDE] / 2.0;
1018  float aboveOffset = Mils2iu( PIN_TEXT_MARGIN ) + penWidth / 2.0 + thickness[ABOVE] / 2.0;
1019  float belowOffset = Mils2iu( PIN_TEXT_MARGIN ) + penWidth / 2.0 + thickness[BELOW] / 2.0;
1020 
1021  if( isDangling )
1022  outsideOffset += TARGET_PIN_RADIUS / 2.0;
1023 
1024  if( drawingShadows )
1025  {
1026  float shadowWidth = getShadowWidth();
1027 
1028  if( eeconfig()->m_Selection.text_as_box )
1029  {
1030  insideOffset -= thickness[INSIDE] / 2.0;
1031  outsideOffset -= thickness[OUTSIDE] / 2.0;
1032  aboveOffset -= thickness[ABOVE] + penWidth;
1033  belowOffset -= thickness[BELOW] + penWidth;
1034  }
1035 
1036  for( float& t : thickness )
1037  t += shadowWidth;
1038 
1039  insideOffset -= shadowWidth / 2.0;
1040  outsideOffset -= shadowWidth / 2.0;
1041  }
1042 
1043  auto setupDC =
1044  [&]( int i )
1045  {
1046  m_gal->SetGlyphSize( VECTOR2D( size[i], size[i] ) );
1047  m_gal->SetIsStroke( !( drawingShadows && eeconfig()->m_Selection.text_as_box ) );
1048  m_gal->SetLineWidth( thickness[i] );
1049  m_gal->SetStrokeColor( colour[i] );
1050  m_gal->SetIsFill( drawingShadows && eeconfig()->m_Selection.text_as_box );
1051  m_gal->SetFillColor( colour[i] );
1052  };
1053 
1054  auto drawText =
1055  [&]( const wxString& aText, const VECTOR2D& aPos, double aAngle )
1056  {
1057  if( aText.IsEmpty() )
1058  return;
1059 
1060  if( drawingShadows && eeconfig()->m_Selection.text_as_box )
1061  boxText( aText, aPos, aAngle );
1062  else
1063  strokeText( aText, aPos, aAngle );
1064  };
1065 
1066  switch( orient )
1067  {
1068  case PIN_LEFT:
1069  if( size[INSIDE] )
1070  {
1071  setupDC( INSIDE );
1074  drawText( text[INSIDE], pos + VECTOR2D( -insideOffset - len, 0 ), 0 );
1075  }
1076  if( size[OUTSIDE] )
1077  {
1078  setupDC( OUTSIDE );
1081  drawText( text[OUTSIDE], pos + VECTOR2D( outsideOffset, 0 ), 0 );
1082  }
1083  if( size[ABOVE] )
1084  {
1085  setupDC( ABOVE );
1088  drawText( text[ABOVE], pos + VECTOR2D( -len / 2.0, -aboveOffset ), 0 );
1089  }
1090  if( size[BELOW] )
1091  {
1092  setupDC( BELOW );
1095  drawText( text[BELOW], pos + VECTOR2D( -len / 2.0, belowOffset ), 0 );
1096  }
1097  break;
1098 
1099  case PIN_RIGHT:
1100  if( size[INSIDE] )
1101  {
1102  setupDC( INSIDE );
1106  drawText( text[INSIDE], pos + VECTOR2D( insideOffset + len, 0 ), 0 );
1107  }
1108  if( size[OUTSIDE] )
1109  {
1110  setupDC( OUTSIDE );
1113  drawText( text[OUTSIDE], pos + VECTOR2D( -outsideOffset, 0 ), 0 );
1114  }
1115  if( size[ABOVE] )
1116  {
1117  setupDC( ABOVE );
1120  drawText( text[ABOVE], pos + VECTOR2D( len / 2.0, -aboveOffset ), 0 );
1121  }
1122  if( size[BELOW] )
1123  {
1124  setupDC( BELOW );
1127  drawText( text[BELOW], pos + VECTOR2D( len / 2.0, belowOffset ), 0 );
1128  }
1129  break;
1130 
1131  case PIN_DOWN:
1132  if( size[INSIDE] )
1133  {
1134  setupDC( INSIDE );
1137  drawText( text[INSIDE], pos + VECTOR2D( 0, insideOffset + len ), M_PI / 2 );
1138  }
1139  if( size[OUTSIDE] )
1140  {
1141  setupDC( OUTSIDE );
1144  drawText( text[OUTSIDE], pos + VECTOR2D( 0, -outsideOffset ), M_PI / 2 );
1145  }
1146  if( size[ABOVE] )
1147  {
1148  setupDC( ABOVE );
1151  drawText( text[ABOVE], pos + VECTOR2D( -aboveOffset, len / 2.0 ), M_PI / 2 );
1152  }
1153  if( size[BELOW] )
1154  {
1155  setupDC( BELOW );
1158  drawText( text[BELOW], pos + VECTOR2D( belowOffset, len / 2.0 ), M_PI / 2 );
1159  }
1160  break;
1161 
1162  case PIN_UP:
1163  if( size[INSIDE] )
1164  {
1165  setupDC( INSIDE );
1168  drawText( text[INSIDE], pos + VECTOR2D( 0, -insideOffset - len ), M_PI / 2 );
1169  }
1170  if( size[OUTSIDE] )
1171  {
1172  setupDC( OUTSIDE );
1175  drawText( text[OUTSIDE], pos + VECTOR2D( 0, outsideOffset ), M_PI / 2 );
1176  }
1177  if( size[ABOVE] )
1178  {
1179  setupDC( ABOVE );
1182  drawText( text[ABOVE], pos + VECTOR2D( -aboveOffset, -len / 2.0 ), M_PI / 2 );
1183  }
1184  if( size[BELOW] )
1185  {
1186  setupDC( BELOW );
1189  drawText( text[BELOW], pos + VECTOR2D( belowOffset, -len / 2.0 ), M_PI / 2 );
1190  }
1191  break;
1192 
1193  default:
1194  wxFAIL_MSG( wxT( "Unknown pin orientation" ) );
1195  }
1196 }
1197 
1198 
1199 // Draw the target (an open square) for a wire or label which has no connection or is
1200 // being moved.
1201 void SCH_PAINTER::drawDanglingSymbol( const wxPoint& aPos, const COLOR4D& aColor, int aWidth,
1202  bool aDrawingShadows )
1203 {
1204  wxPoint radius( aWidth + Mils2iu( DANGLING_SYMBOL_SIZE / 2 ),
1205  aWidth + Mils2iu( DANGLING_SYMBOL_SIZE / 2 ) );
1206 
1207  // Dangling symbols must be drawn in a slightly different colour so they can be seen when
1208  // they overlap with a junction dot.
1209  m_gal->SetStrokeColor( aColor.Brightened( 0.3 ) );
1210  m_gal->SetIsStroke( true );
1211  m_gal->SetIsFill( false );
1212  m_gal->SetLineWidth( aDrawingShadows ? getShadowWidth()
1214 
1215  m_gal->DrawRectangle( aPos - radius, aPos + radius );
1216 }
1217 
1218 
1219 void SCH_PAINTER::draw( const SCH_JUNCTION *aJct, int aLayer )
1220 {
1221  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1222 
1223  if( drawingShadows && !aJct->IsSelected() )
1224  return;
1225 
1226  COLOR4D color = getRenderColor( aJct, aJct->GetLayer(), drawingShadows );
1227 
1228  int junctionSize = aJct->GetEffectiveDiameter() / 2;
1229 
1230  if( junctionSize > 1 )
1231  {
1232  m_gal->SetIsStroke( drawingShadows );
1233  m_gal->SetLineWidth( getLineWidth( aJct, drawingShadows ) );
1235  m_gal->SetIsFill( !drawingShadows );
1236  m_gal->SetFillColor( color );
1237  m_gal->DrawCircle( aJct->GetPosition(), junctionSize );
1238  }
1239 }
1240 
1241 
1242 void SCH_PAINTER::draw( const SCH_LINE *aLine, int aLayer )
1243 {
1244  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1245  bool drawingDangling = aLayer == LAYER_DANGLING;
1246 
1247  if( drawingShadows && !aLine->IsSelected() )
1248  return;
1249 
1250  COLOR4D color = getRenderColor( aLine, aLine->GetLayer(), drawingShadows );
1251  float width = getLineWidth( aLine, drawingShadows );
1252  PLOT_DASH_TYPE lineStyle = aLine->GetEffectiveLineStyle();
1253 
1254  if( drawingDangling || drawingShadows )
1255  {
1256  if( aLine->IsStartDangling() && aLine->IsWire() )
1257  {
1259  getLineWidth( aLine, drawingShadows ), drawingShadows );
1260  }
1261 
1262  if( aLine->IsEndDangling() && aLine->IsWire() )
1263  {
1265  getLineWidth( aLine, drawingShadows ), drawingShadows );
1266  }
1267 
1268  if( drawingDangling )
1269  return;
1270  }
1271 
1272  m_gal->SetIsStroke( true );
1274  m_gal->SetLineWidth( width );
1275 
1276  if( lineStyle <= PLOT_DASH_TYPE::FIRST_TYPE || drawingShadows )
1277  {
1278  m_gal->DrawLine( aLine->GetStartPoint(), aLine->GetEndPoint() );
1279  }
1280  else
1281  {
1282  VECTOR2D start = aLine->GetStartPoint();
1283  VECTOR2D end = aLine->GetEndPoint();
1284 
1285  EDA_RECT clip( (wxPoint)start, wxSize( end.x - start.x, end.y - start.y ) );
1286  clip.Normalize();
1287 
1288  double theta = atan2( end.y - start.y, end.x - start.x );
1289  double strokes[] = { 1.0, dash_gap_len( width ), 1.0, dash_gap_len( width ) };
1290 
1291  switch( lineStyle )
1292  {
1293  default:
1294  case PLOT_DASH_TYPE::DASH:
1295  strokes[0] = strokes[2] = dash_mark_len( width );
1296  break;
1297  case PLOT_DASH_TYPE::DOT:
1298  strokes[0] = strokes[2] = dot_mark_len( width );
1299  break;
1301  strokes[0] = dash_mark_len( width );
1302  strokes[2] = dot_mark_len( width );
1303  break;
1304  }
1305 
1306  for( size_t i = 0; i < 10000; ++i )
1307  {
1308  // Calculations MUST be done in doubles to keep from accumulating rounding
1309  // errors as we go.
1310  VECTOR2D next( start.x + strokes[ i % 4 ] * cos( theta ),
1311  start.y + strokes[ i % 4 ] * sin( theta ) );
1312 
1313  // Drawing each segment can be done rounded to ints.
1314  wxPoint segStart( KiROUND( start.x ), KiROUND( start.y ) );
1315  wxPoint segEnd( KiROUND( next.x ), KiROUND( next.y ) );
1316 
1317  if( ClipLine( &clip, segStart.x, segStart.y, segEnd.x, segEnd.y ) )
1318  break;
1319  else if( i % 2 == 0 )
1320  m_gal->DrawLine( segStart, segEnd );
1321 
1322  start = next;
1323  }
1324  }
1325 }
1326 
1327 
1328 void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
1329 {
1330  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1331  bool drawingDangling = aLayer == LAYER_DANGLING;
1332 
1333  if( drawingShadows && !aText->IsSelected() )
1334  return;
1335 
1336  switch( aText->Type() )
1337  {
1338  case SCH_SHEET_PIN_T: aLayer = LAYER_SHEETLABEL; break;
1339  case SCH_HIER_LABEL_T: aLayer = LAYER_HIERLABEL; break;
1340  case SCH_GLOBAL_LABEL_T: aLayer = LAYER_GLOBLABEL; break;
1341  case SCH_LABEL_T: aLayer = LAYER_LOCLABEL; break;
1342  default: aLayer = LAYER_NOTES; break;
1343  }
1344 
1345  COLOR4D color = getRenderColor( aText, aLayer, drawingShadows );
1346 
1347  if( m_schematic )
1348  {
1349  SCH_CONNECTION* conn = nullptr;
1350 
1351  if( !aText->IsConnectivityDirty() )
1352  conn = aText->Connection();
1353 
1354  if( conn && conn->IsBus() )
1355  color = getRenderColor( aText, LAYER_BUS, drawingShadows );
1356  }
1357 
1358  if( !( aText->IsVisible() || aText->IsForceVisible() ) )
1359  {
1361  color = getRenderColor( aText, LAYER_HIDDEN, drawingShadows );
1362  else
1363  return;
1364  }
1365 
1366  if( drawingDangling )
1367  {
1368  if( aText->IsDangling() )
1369  {
1370  drawDanglingSymbol( aText->GetTextPos(), color, Mils2iu( DANGLING_SYMBOL_SIZE / 2 ),
1371  drawingShadows );
1372  }
1373 
1374  return;
1375  }
1376 
1377  m_gal->SetIsFill( false );
1378  m_gal->SetIsStroke( true );
1379  m_gal->SetLineWidth( getTextThickness( aText, drawingShadows ) );
1381 
1382  VECTOR2D text_offset = aText->GetTextPos() + aText->GetSchematicTextOffset( &m_schSettings );
1383  wxString shownText( aText->GetShownText() );
1384 
1385  if( drawingShadows )
1386  {
1388  {
1389  EDA_RECT bBox = aText->GetBoundingBox();
1390 
1391  m_gal->SetIsFill( true );
1392  m_gal->SetFillColor( color );
1393  m_gal->SetLineWidth( m_gal->GetLineWidth() * 0.5 );
1394  bBox.RevertYAxis();
1395 
1396  m_gal->DrawRectangle( mapCoords( bBox.GetPosition() ), mapCoords( bBox.GetEnd() ) );
1397  return;
1398  }
1399 
1400  switch( aText->GetLabelSpinStyle() )
1401  {
1402  case LABEL_SPIN_STYLE::LEFT: text_offset.x += getShadowWidth() / 2; break;
1403  case LABEL_SPIN_STYLE::UP: text_offset.y += getShadowWidth() / 2; break;
1404  case LABEL_SPIN_STYLE::RIGHT: text_offset.x -= getShadowWidth() / 2; break;
1405  case LABEL_SPIN_STYLE::BOTTOM: text_offset.y -= getShadowWidth() / 2; break;
1406  }
1407  }
1408 
1409  if( !shownText.IsEmpty() )
1410  {
1411  m_gal->SetTextAttributes( aText );
1412  m_gal->SetFontUnderlined( false );
1413 
1414  strokeText( shownText, text_offset, aText->GetTextAngleRadians() );
1415  }
1416 }
1417 
1418 
1419 static void orientSymbol( LIB_SYMBOL* symbol, int orientation )
1420 {
1421  struct ORIENT
1422  {
1423  int flag;
1424  int n_rots;
1425  int mirror_x;
1426  int mirror_y;
1427  }
1428  orientations[] =
1429  {
1430  { SYM_ORIENT_0, 0, 0, 0 },
1431  { SYM_ORIENT_90, 1, 0, 0 },
1432  { SYM_ORIENT_180, 2, 0, 0 },
1433  { SYM_ORIENT_270, 3, 0, 0 },
1434  { SYM_MIRROR_X + SYM_ORIENT_0, 0, 1, 0 },
1435  { SYM_MIRROR_X + SYM_ORIENT_90, 1, 1, 0 },
1436  { SYM_MIRROR_Y, 0, 0, 1 },
1437  { SYM_MIRROR_X + SYM_ORIENT_270, 3, 1, 0 },
1438  { SYM_MIRROR_Y + SYM_ORIENT_0, 0, 0, 1 },
1439  { SYM_MIRROR_Y + SYM_ORIENT_90, 1, 0, 1 },
1440  { SYM_MIRROR_Y + SYM_ORIENT_180, 2, 0, 1 },
1441  { SYM_MIRROR_Y + SYM_ORIENT_270, 3, 0, 1 }
1442  };
1443 
1444  ORIENT o = orientations[ 0 ];
1445 
1446  for( auto& i : orientations )
1447  {
1448  if( i.flag == orientation )
1449  {
1450  o = i;
1451  break;
1452  }
1453  }
1454 
1455  for( auto& item : symbol->GetDrawItems() )
1456  {
1457  for( int i = 0; i < o.n_rots; i++ )
1458  item.Rotate( wxPoint(0, 0 ), true );
1459 
1460  if( o.mirror_x )
1461  item.MirrorVertical( wxPoint( 0, 0 ) );
1462 
1463  if( o.mirror_y )
1464  item.MirrorHorizontal( wxPoint( 0, 0 ) );
1465  }
1466 }
1467 
1468 
1469 void SCH_PAINTER::draw( SCH_SYMBOL* aSymbol, int aLayer )
1470 {
1471  int unit = aSymbol->GetUnitSelection( &m_schematic->CurrentSheet() );
1472  int convert = aSymbol->GetConvert();
1473 
1474  // Use dummy symbol if the actual couldn't be found (or couldn't be locked).
1475  LIB_SYMBOL* originalSymbol = aSymbol->GetLibSymbolRef() ?
1476  aSymbol->GetLibSymbolRef().get() : dummy();
1477  LIB_PINS originalPins;
1478  originalSymbol->GetPins( originalPins, unit, convert );
1479 
1480  // Copy the source so we can re-orient and translate it.
1481  LIB_SYMBOL tempSymbol( *originalSymbol );
1482  LIB_PINS tempPins;
1483  tempSymbol.GetPins( tempPins, unit, convert );
1484 
1485  tempSymbol.SetFlags( aSymbol->GetFlags() );
1486 
1487  orientSymbol( &tempSymbol, aSymbol->GetOrientation() );
1488 
1489  for( auto& tempItem : tempSymbol.GetDrawItems() )
1490  {
1491  tempItem.SetFlags( aSymbol->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED
1492  tempItem.MoveTo( tempItem.GetPosition() + (wxPoint) mapCoords( aSymbol->GetPosition() ) );
1493  }
1494 
1495  // Copy the pin info from the symbol to the temp pins
1496  for( unsigned i = 0; i < tempPins.size(); ++ i )
1497  {
1498  SCH_PIN* symbolPin = aSymbol->GetPin( originalPins[ i ] );
1499  LIB_PIN* tempPin = tempPins[ i ];
1500 
1501  tempPin->ClearFlags();
1502  tempPin->SetFlags( symbolPin->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED
1503 
1504  tempPin->SetName( symbolPin->GetShownName() );
1505  tempPin->SetType( symbolPin->GetType() );
1506  tempPin->SetShape( symbolPin->GetShape() );
1507 
1508  if( symbolPin->IsDangling() )
1509  tempPin->SetFlags( IS_DANGLING );
1510  }
1511 
1512  draw( &tempSymbol, aLayer, false, aSymbol->GetUnit(), aSymbol->GetConvert() );
1513 
1514  // The fields are SCH_SYMBOL-specific so don't need to be copied/oriented/translated
1515  for( const SCH_FIELD& field : aSymbol->GetFields() )
1516  draw( &field, aLayer );
1517 }
1518 
1519 
1520 void SCH_PAINTER::draw( const SCH_FIELD *aField, int aLayer )
1521 {
1522  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1523 
1524  if( drawingShadows && !aField->IsSelected() )
1525  return;
1526 
1527  aLayer = aField->GetLayer();
1528 
1529  COLOR4D color = getRenderColor( aField, aLayer, drawingShadows );
1530 
1531  if( !( aField->IsVisible() || aField->IsForceVisible() ) )
1532  {
1534  color = getRenderColor( aField, LAYER_HIDDEN, drawingShadows );
1535  else
1536  return;
1537  }
1538 
1539  if( aField->IsVoid() )
1540  return;
1541 
1542  if( drawingShadows && aField->GetParent()->IsSelected()
1544  {
1545  return;
1546  }
1547 
1548  bool underline = false;
1549 
1550  if( aField->IsHypertext() && ( aField->GetFlags() & IS_ROLLOVER ) > 0
1551  && !drawingShadows && !aField->IsMoving() )
1552  {
1553  color = PUREBLUE;
1554  underline = true;
1555  }
1556 
1557  // Calculate the text orientation according to the parent orientation.
1558  int orient = (int) aField->GetTextAngle();
1559 
1560  if( aField->GetParent() && aField->GetParent()->Type() == SCH_SYMBOL_T )
1561  {
1562  if( static_cast<SCH_SYMBOL*>( aField->GetParent() )->GetTransform().y1 )
1563  {
1564  // Rotate symbol 90 degrees.
1565  if( orient == TEXT_ANGLE_HORIZ )
1566  orient = TEXT_ANGLE_VERT;
1567  else
1568  orient = TEXT_ANGLE_HORIZ;
1569  }
1570  }
1571 
1572  /*
1573  * Calculate the text justification, according to the symbol orientation/mirror.
1574  * This is a bit complicated due to cumulative calculations:
1575  * - numerous cases (mirrored or not, rotation)
1576  * - the DrawGraphicText function recalculate also H and H justifications according to the
1577  * text orientation.
1578  * - when symbol is mirrored, the text is not mirrored and justifications are complicated
1579  * to calculate so the easier way is to use no justifications (centered text) and use
1580  * GetBoundingBox to know the text coordinate considered as centered
1581  */
1582  EDA_RECT bbox = aField->GetBoundingBox();
1583  wxPoint textpos = bbox.Centre();
1584 
1586  m_gal->SetIsStroke( true );
1587 
1588  if( drawingShadows && eeconfig()->m_Selection.text_as_box )
1589  {
1590  m_gal->SetIsFill( true );
1591  m_gal->SetFillColor( color );
1592  m_gal->SetLineWidth( m_gal->GetLineWidth() * 0.5 );
1593  bbox.RevertYAxis();
1594 
1595  m_gal->DrawRectangle( mapCoords( bbox.GetPosition() ), mapCoords( bbox.GetEnd() ) );
1596  }
1597  else
1598  {
1601  m_gal->SetIsFill( false );
1602  m_gal->SetGlyphSize( VECTOR2D( aField->GetTextSize() ) );
1603  m_gal->SetFontBold( aField->IsBold() );
1604  m_gal->SetFontItalic( aField->IsItalic() );
1605  m_gal->SetFontUnderlined( underline );
1606  m_gal->SetTextMirrored( aField->IsMirrored() );
1607  m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
1608 
1609  strokeText( aField->GetShownText(), textpos, orient == TEXT_ANGLE_VERT ? M_PI / 2 : 0 );
1610  }
1611 
1612  // Draw the umbilical line
1613  if( aField->IsMoving() )
1614  {
1615  wxPoint parentPos = aField->GetParentPosition();
1616 
1618  m_gal->SetStrokeColor( getRenderColor( aField, LAYER_SCHEMATIC_ANCHOR, drawingShadows ) );
1619  m_gal->DrawLine( textpos, parentPos );
1620  }
1621 }
1622 
1623 
1624 void SCH_PAINTER::draw( SCH_GLOBALLABEL *aLabel, int aLayer )
1625 {
1626  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1627 
1628  if( !drawingShadows || aLabel->IsSelected() )
1629  {
1630  COLOR4D color = getRenderColor( aLabel, LAYER_GLOBLABEL, drawingShadows );
1631 
1632  std::vector<wxPoint> pts;
1633  std::deque<VECTOR2D> pts2;
1634 
1635  aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() );
1636 
1637  for( const wxPoint& p : pts )
1638  pts2.emplace_back( VECTOR2D( p.x, p.y ) );
1639 
1640  // The text is drawn inside the graphic shape.
1641  // On Cairo the graphic shape is filled by the background before drawing the text.
1642  // However if the text is selected, it is draw twice: first on LAYER_SELECTION_SHADOWS
1643  // and second on the text layer. The second must not erase the first drawing.
1644  bool fillBg = ( ( aLayer == LAYER_SELECTION_SHADOWS ) || !aLabel->IsSelected() )
1645  && aLayer != LAYER_DANGLING;
1646  m_gal->SetIsFill( fillBg );
1648  m_gal->SetIsStroke( true );
1649  m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) );
1651  m_gal->DrawPolyline( pts2 );
1652 
1653  draw( static_cast<SCH_TEXT*>( aLabel ), aLayer );
1654  }
1655 
1656  if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children || !aLabel->IsSelected() )
1657  {
1658  draw( aLabel->GetIntersheetRefs(), aLayer );
1659  }
1660 }
1661 
1662 
1663 void SCH_PAINTER::draw( SCH_HIERLABEL *aLabel, int aLayer )
1664 {
1665  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1666 
1667  if( drawingShadows && !aLabel->IsSelected() )
1668  return;
1669 
1670  COLOR4D color = getRenderColor( aLabel, LAYER_HIERLABEL, drawingShadows );
1671 
1672  if( m_schematic )
1673  {
1674  SCH_CONNECTION* conn = nullptr;
1675 
1676  if( !aLabel->IsConnectivityDirty() )
1677  conn = aLabel->Connection();
1678 
1679  if( conn && conn->IsBus() )
1680  color = getRenderColor( aLabel, LAYER_BUS, drawingShadows );
1681  }
1682 
1683  std::vector<wxPoint> pts;
1684  std::deque<VECTOR2D> pts2;
1685 
1686  aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() );
1687 
1688  for( const wxPoint& p : pts )
1689  pts2.emplace_back( VECTOR2D( p.x, p.y ) );
1690 
1691  m_gal->SetIsFill( true );
1693  m_gal->SetIsStroke( true );
1694  m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) );
1696  m_gal->DrawPolyline( pts2 );
1697 
1698  draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer );
1699 }
1700 
1701 
1702 void SCH_PAINTER::draw( const SCH_SHEET *aSheet, int aLayer )
1703 {
1704  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1705 
1706  if( aLayer == LAYER_HIERLABEL || aLayer == LAYER_SELECTION_SHADOWS )
1707  {
1708  for( SCH_SHEET_PIN* sheetPin : aSheet->GetPins() )
1709  {
1710  if( drawingShadows && !aSheet->IsSelected() && !sheetPin->IsSelected() )
1711  continue;
1712 
1713  if( drawingShadows && aSheet->IsSelected()
1715  {
1716  break;
1717  }
1718 
1719  int width = std::max( aSheet->GetPenWidth(), m_schSettings.GetDefaultPenWidth() );
1720  wxPoint initial_pos = sheetPin->GetTextPos();
1721  wxPoint offset_pos = initial_pos;
1722 
1723  // For aesthetic reasons, the SHEET_PIN is drawn with a small offset of width / 2
1724  switch( sheetPin->GetSide() )
1725  {
1726  case SHEET_SIDE::TOP: offset_pos.y += KiROUND( width / 2.0 ); break;
1727  case SHEET_SIDE::BOTTOM: offset_pos.y -= KiROUND( width / 2.0 ); break;
1728  case SHEET_SIDE::RIGHT: offset_pos.x -= KiROUND( width / 2.0 ); break;
1729  case SHEET_SIDE::LEFT: offset_pos.x += KiROUND( width / 2.0 ); break;
1730  default: break;
1731  }
1732 
1733  sheetPin->SetTextPos( offset_pos );
1734  draw( static_cast<SCH_HIERLABEL*>( sheetPin ), aLayer );
1735  m_gal->DrawLine( offset_pos, initial_pos );
1736  sheetPin->SetTextPos( initial_pos );
1737  }
1738  }
1739 
1740  VECTOR2D pos = aSheet->GetPosition();
1741  VECTOR2D size = aSheet->GetSize();
1742 
1743  if( aLayer == LAYER_SHEET_BACKGROUND )
1744  {
1746  m_gal->SetIsFill( true );
1747  m_gal->SetIsStroke( false );
1748 
1749  m_gal->DrawRectangle( pos, pos + size );
1750  }
1751 
1752  if( aLayer == LAYER_SHEET || aLayer == LAYER_SELECTION_SHADOWS )
1753  {
1754  m_gal->SetStrokeColor( getRenderColor( aSheet, LAYER_SHEET, drawingShadows ) );
1755  m_gal->SetIsStroke( true );
1756  m_gal->SetLineWidth( getLineWidth( aSheet, drawingShadows ) );
1757  m_gal->SetIsFill( false );
1758 
1759  m_gal->DrawRectangle( pos, pos + size );
1760 
1761  if( drawingShadows && !eeconfig()->m_Selection.draw_selected_children && aSheet->IsSelected() )
1762  return;
1763 
1764  for( const SCH_FIELD& field : aSheet->GetFields() )
1765  draw( &field, aLayer );
1766  }
1767 }
1768 
1769 
1770 void SCH_PAINTER::draw( const SCH_NO_CONNECT *aNC, int aLayer )
1771 {
1772  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1773 
1774  if( drawingShadows && !aNC->IsSelected() )
1775  return;
1776 
1777  m_gal->SetIsStroke( true );
1778  m_gal->SetLineWidth( getLineWidth( aNC, drawingShadows ) );
1779  m_gal->SetStrokeColor( getRenderColor( aNC, LAYER_NOCONNECT, drawingShadows ) );
1780  m_gal->SetIsFill( false );
1781 
1782  VECTOR2D p = aNC->GetPosition();
1783  int delta = std::max( aNC->GetSize(), m_schSettings.GetDefaultPenWidth() * 3 ) / 2;
1784 
1785  m_gal->DrawLine( p + VECTOR2D( -delta, -delta ), p + VECTOR2D( delta, delta ) );
1786  m_gal->DrawLine( p + VECTOR2D( -delta, delta ), p + VECTOR2D( delta, -delta ) );
1787 }
1788 
1789 
1790 void SCH_PAINTER::draw( const SCH_BUS_ENTRY_BASE *aEntry, int aLayer )
1791 {
1792  SCH_LAYER_ID layer = aEntry->Type() == SCH_BUS_WIRE_ENTRY_T ? LAYER_WIRE : LAYER_BUS;
1793  SCH_LINE line( wxPoint(), layer );
1794  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1795  bool drawingDangling = aLayer == LAYER_DANGLING;
1796 
1797  if( drawingShadows && !aEntry->IsSelected() )
1798  return;
1799 
1800  if( aEntry->IsSelected() )
1801  line.SetSelected();
1802  else if( aEntry->IsBrightened() )
1803  line.SetBrightened();
1804 
1805  line.SetStartPoint( aEntry->GetPosition() );
1806  line.SetEndPoint( aEntry->GetEnd() );
1807  line.SetStroke( aEntry->GetStroke() );
1808  line.SetLineWidth( getLineWidth( aEntry, drawingShadows ) );
1809 
1810  COLOR4D color = getRenderColor( aEntry, LAYER_WIRE, drawingShadows );
1811 
1812  if( aEntry->Type() == SCH_BUS_BUS_ENTRY_T )
1813  color = getRenderColor( aEntry, LAYER_BUS, drawingShadows );
1814 
1815  if( drawingDangling )
1816  {
1817  m_gal->SetIsFill( false );
1818  m_gal->SetIsStroke( true );
1819  m_gal->SetStrokeColor( color.Brightened( 0.3 ) );
1821 
1822  if( aEntry->IsDanglingStart() )
1823  {
1824  m_gal->DrawCircle( aEntry->GetPosition(),
1825  aEntry->GetPenWidth() + ( TARGET_BUSENTRY_RADIUS / 2 ) );
1826  }
1827 
1828  if( aEntry->IsDanglingEnd() )
1829  {
1830  m_gal->DrawCircle( aEntry->GetEnd(),
1831  aEntry->GetPenWidth() + ( TARGET_BUSENTRY_RADIUS / 2 ) );
1832  }
1833  }
1834  else
1835  {
1836  line.SetLineColor( color );
1837  line.SetLineStyle( aEntry->GetStrokeStyle() );
1838 
1839  draw( &line, aLayer );
1840  }
1841 }
1842 
1843 
1844 void SCH_PAINTER::draw( const SCH_BITMAP *aBitmap, int aLayer )
1845 {
1846  m_gal->Save();
1847  m_gal->Translate( aBitmap->GetPosition() );
1848 
1849  // When the image scale factor is not 1.0, we need to modify the actual as the image scale
1850  // factor is similar to a local zoom
1851  double img_scale = aBitmap->GetImageScale();
1852 
1853  if( img_scale != 1.0 )
1854  m_gal->Scale( VECTOR2D( img_scale, img_scale ) );
1855 
1856  if( aLayer == LAYER_DRAW_BITMAPS )
1857  {
1858  m_gal->DrawBitmap( *aBitmap->GetImage() );
1859  }
1860 
1861  if( aLayer == LAYER_SELECTION_SHADOWS )
1862  {
1863  if( aBitmap->IsSelected() || aBitmap->IsBrightened() )
1864  {
1865  COLOR4D color = getRenderColor( aBitmap, LAYER_DRAW_BITMAPS, true );
1866  m_gal->SetIsStroke( true );
1869  m_gal->SetIsFill( false );
1870 
1871  // Draws a bounding box.
1872  VECTOR2D bm_size( aBitmap->GetSize() );
1873  // bm_size is the actual image size in UI.
1874  // but m_gal scale was previously set to img_scale
1875  // so recalculate size relative to this image size.
1876  bm_size.x /= img_scale;
1877  bm_size.y /= img_scale;
1878  VECTOR2D origin( -bm_size.x / 2.0, -bm_size.y / 2.0 );
1879  VECTOR2D end = origin + bm_size;
1880 
1881  m_gal->DrawRectangle( origin, end );
1882  }
1883  }
1884 
1885  m_gal->Restore();
1886 }
1887 
1888 
1889 void SCH_PAINTER::draw( const SCH_MARKER *aMarker, int aLayer )
1890 {
1891  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1892 
1893  if( drawingShadows && !aMarker->IsSelected() )
1894  return;
1895 
1896  COLOR4D color = getRenderColor( aMarker, aMarker->GetColorLayer(), drawingShadows );
1897 
1898  m_gal->Save();
1899  m_gal->Translate( aMarker->GetPosition() );
1900  m_gal->SetIsFill( !drawingShadows );
1901  m_gal->SetFillColor( color );
1902  m_gal->SetIsStroke( drawingShadows );
1903  m_gal->SetLineWidth( getLineWidth( aMarker, drawingShadows ) );
1905 
1906  SHAPE_LINE_CHAIN polygon;
1907  aMarker->ShapeToPolygon( polygon );
1908 
1909  m_gal->DrawPolygon( polygon );
1910  m_gal->Restore();
1911 }
1912 
1913 
1914 }; // namespace KIGFX
virtual bool Draw(const VIEW_ITEM *, int) override
Takes an instance of VIEW_ITEM and passes it to a function that knows how to draw the item.
const STROKE_FONT & GetStrokeFont() const
bool IsDangling() const override
Definition: sch_text.h:230
SCH_PAINTER(GAL *aGal)
CITER next(CITER it)
Definition: ptree.cpp:126
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
void CalcArcAngles(int &aStartAngle, int &aEndAngle) const
Definition: lib_shape.cpp:430
#define TEXT_ANGLE_HORIZ
Frequent text rotations, used with {Set,Get}TextAngle(), in 0.1 degrees for now, hoping to migrate to...
Definition: eda_text.h:71
virtual void DrawPolyline(const std::deque< VECTOR2D > &aPointList)
Draw a polyline.
bool IsBold() const
Definition: eda_text.h:204
virtual int GetPenWidth() const =0
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:49
#define DEFAULT_LABEL_SIZE_RATIO
The offset of the pin name string from the end of the pin in mils.
SCHEMATIC * m_schematic
Definition: sch_painter.h:197
void GetPins(LIB_PINS &aList, int aUnit=0, int aConvert=0) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:756
int GetPinNameOffset() const
Definition: lib_symbol.h:572
float GetLineWidth() const
Get the line width.
#define TARGET_BUSENTRY_RADIUS
Definition: sch_bus_entry.h:36
wxString GetShownNumber() const
Definition: lib_pin.h:117
virtual void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a rectangle.
const std::vector< wxPoint > & GetBezierPoints() const
Definition: eda_shape.h:210
Auxiliary items (guides, rule, etc)
Definition: layer_ids.h:229
Plot settings, and plotting engines (PostScript, Gerber, HPGL and DXF)
bool IsMirrored() const
Definition: eda_text.h:210
SCH_LAYER_ID GetColorLayer() const
Definition: sch_marker.cpp:122
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:243
wxPoint GetStartPoint() const
Definition: sch_line.h:90
bool IsWire() const
Return true if the line is a wire.
Definition: sch_line.cpp:972
bool IsSelected() const
Definition: eda_item.h:122
const MATRIX3x3D & GetScreenWorldMatrix() const
Get the screen <-> world transformation matrix.
#define DEFAULT_WIRE_WIDTH_MILS
The default bus width in mils. (can be changed in preference menu)
const Vec GetEnd() const
Definition: box2.h:178
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
wxPoint GetPosition() const override
COLOR4D m_layerColors[LAYER_ID_COUNT]
Define a symbol library graphical text item.
Definition: lib_text.h:39
int GetOrientation() const
Definition: lib_pin.h:75
int GetX() const
Definition: eda_rect.h:107
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
virtual STROKE_PARAMS GetStroke() const override
Definition: sch_bus_entry.h:81
static constexpr double IU_PER_MM
Mock up a conversion function.
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:55
wxPoint GetPosition() const override
Definition: sch_marker.h:101
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: lib_pin.h:79
virtual void SetTextAttributes(const EDA_TEXT *aText)
Loads attributes of the given text (bold/italic/underline/mirrored and so on).
void SetLineWidth(const int aSize)
Definition: sch_line.cpp:305
GRAPHIC_PINSHAPE GetShape() const
Definition: lib_pin.h:78
virtual void DrawArc(const VECTOR2D &aCenterPoint, double aRadius, double aStartAngle, double aEndAngle)
Draw an arc.
bool IsMoving() const
Definition: eda_item.h:119
int color
Definition: DXF_plotter.cpp:57
Field object used in symbol libraries.
Definition: lib_field.h:59
float getTextThickness(const SCH_TEXT *aItem, bool aDrawingShadows) const
bool IsAlias() const
Definition: lib_symbol.h:172
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:155
bool setDeviceColors(const LIB_ITEM *aItem, int aLayer)
bool isUnitAndConversionShown(const LIB_ITEM *aItem) const
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:741
void SetFontBold(bool aBold)
Set bold property of current font.
bool ShowPinNumbers() const
Definition: lib_symbol.h:588
int GetWidth() const
Definition: eda_rect.h:118
void SetBrightened()
Definition: eda_item.h:129
virtual void DrawBitmap(const BITMAP_BASE &aBitmap)
Draw a bitmap image.
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:152
bool IsHypertext() const override
Allow items to support hypertext actions when hovered/clicked.
Definition: sch_field.h:89
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
double GetTextAngle() const
Definition: eda_text.h:195
double RAD2DECIDEG(double rad)
Definition: trigo.h:234
KIGFX::COLOR4D GetBorderColor() const
Definition: sch_sheet.h:110
bool IsBrightened() const
Definition: eda_item.h:125
Text appears outside the dimension line (default)
virtual int GetEffectivePenWidth(const RENDER_SETTINGS *aSettings) const
Definition: lib_item.h:153
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...
#define DEFAULT_JUNCTION_DIAM
The default bus and wire entry size in mils.
Definition: lib_pin.h:48
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: lib_field.cpp:342
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:76
wxPoint GetPosition() const override
Definition: sch_bitmap.h:136
virtual void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a line.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:622
Define a library symbol object.
Definition: lib_symbol.h:96
void RevertYAxis()
Mirror the rectangle from the X axis (negate Y pos and size).
Definition: eda_rect.h:207
float getShadowWidth() const
EDA_TEXT_HJUSTIFY_T GetHorizontalJustify() const
Return current text horizontal justification setting.
virtual wxPoint GetSchematicTextOffset(const RENDER_SETTINGS *aSettings) const
This offset depends on the orientation, the type of text, and the area required to draw the associate...
Definition: sch_text.cpp:258
EESCHEMA_SETTINGS * eeconfig()
bool IsDangling() const override
Definition: sch_pin.h:91
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:380
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
Definition: matrix3x3.h:265
bool ClipLine(const EDA_RECT *aClipBox, int &x1, int &y1, int &x2, int &y2)
Test if any part of a line falls within the bounds of a rectangle.
bool IsConnectivityDirty() const
Definition: sch_item.h:413
wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: sch_field.cpp:105
void boxText(const wxString &aText, const VECTOR2D &aPosition, double aAngle)
bool IsVoid() const
Definition: sch_field.cpp:421
bool IsDanglingEnd() const
Definition: sch_bus_entry.h:48
static constexpr int VIEW_MAX_LAYERS
maximum number of layers that may be shown
Definition: view.h:711
GAL * m_gal
Instance of graphic abstraction layer that gives an interface to call commands used to draw (eg.
Definition: painter.h:101
wxString GetShownName() const
Definition: sch_pin.cpp:90
The base class for drawable items used by schematic library symbols.
Definition: lib_item.h:61
bool IsPowerConnection() const
Return whether this pin forms an implicit power connection: i.e., is hidden and of type POWER_IN.
Definition: lib_pin.h:188
int GetEffectiveTextPenWidth(int aDefaultWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultWidth.
Definition: eda_text.cpp:159
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:165
virtual void SetLineWidth(float aLineWidth)
Set the line width.
void SetEndPoint(const wxPoint &aPosition)
Definition: sch_line.h:94
KIGFX::COLOR4D GetBackgroundColor() const
Definition: sch_sheet.h:113
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
Definition: sch_item.cpp:138
Base class for a bus or wire entry.
Definition: sch_bus_entry.h:42
bool IsFilled() const
Definition: eda_shape.h:90
const VECTOR2D & GetGlyphSize() const
COLOR4D Brightened(double aFactor) const
Return a color that is brighter by a given factor, without modifying object.
Definition: color4d.h:278
bool IsItalic() const
Definition: eda_text.h:201
PLOT_DASH_TYPE GetStrokeStyle() const
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:90
void drawDanglingSymbol(const wxPoint &aPos, const COLOR4D &aColor, int aWidth, bool aDrawingShadows)
const wxPoint GetEnd() const
Definition: eda_rect.h:112
void ViewGetLayers(int aLayers[], int &aCount) const override
Return the all the layers within the VIEW the object is painted on.
Definition: lib_field.cpp:367
int GetUnit() const
Definition: lib_item.h:266
Contains all the knowledge about how to draw graphical object onto any particular output device.
Definition: painter.h:57
void SetLineStyle(const PLOT_DASH_TYPE aStyle)
Definition: sch_line.cpp:269
const wxPoint & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:131
void SetType(ELECTRICAL_PINTYPE aType)
Definition: lib_pin.h:85
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
wxSize GetSize() const
Definition: sch_bitmap.cpp:125
int Clamp_Text_PenSize(int aPenSize, int aSize, bool aBold)
Don't allow text to become cluttered up in its own fatness.
Definition: gr_text.cpp:67
#define IS_DANGLING
indicates a pin is dangling
bool IsDanglingStart() const
Definition: sch_bus_entry.h:47
VECTOR2< double > VECTOR2D
Definition: vector2d.h:621
void SetSelected()
Definition: eda_item.h:128
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
const std::vector< VECTOR2I > & CPoints() const
BITMAP_BASE * GetImage() const
Definition: sch_bitmap.h:54
SCH_LAYER_ID
Eeschema drawing layers.
Definition: layer_ids.h:335
#define DANGLING_SYMBOL_SIZE
< The size of the rectangle indicating an unconnected wire or label
wxPoint GetPosition() const override
Definition: sch_junction.h:103
wxString const GetElectricalTypeName() const
Definition: lib_pin.h:92
SHAPE_LINE_CHAIN & Outline(int aIndex)
virtual bool IsVisible() const
Definition: eda_text.h:207
constexpr double dot_mark_len(double aLineWidth)
Dashed and dotted line patterns.
const wxPoint GetOrigin() const
Definition: eda_rect.h:110
bool IsEndDangling() const
Definition: sch_line.h:212
virtual void StrokeText(const wxString &aText, const VECTOR2D &aPosition, double aRotationAngle)
Draw a vector type text using preloaded Newstroke font.
const wxSize & GetTextSize() const
Definition: eda_text.h:259
int GetPenWidth() const override
Definition: sch_sheet.cpp:567
const wxPoint GetPosition() const
Definition: eda_rect.h:111
void SetStartPoint(const wxPoint &aPosition)
Definition: sch_line.h:91
int GetSize() const
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
Definition: sch_symbol.cpp:554
float GetDanglineSymbolThickness() const
Definition: sch_painter.h:95
void strokeText(const wxString &aText, const VECTOR2D &aPosition, double aRotationAngle)
Definition for symbol library class.
EDA_ITEM * GetParent() const
Definition: eda_item.h:114
bool ShowPinNames() const
Definition: lib_symbol.h:580
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:153
void SetX(int val)
Definition: eda_rect.h:167
void triLine(const VECTOR2D &a, const VECTOR2D &b, const VECTOR2D &c)
a few functions useful in geometry calculations.
void CreateGraphicShape(const RENDER_SETTINGS *aSettings, std::vector< wxPoint > &aPoints, const wxPoint &aPos) const override
Calculate the graphic shape (a polygon) associated to the text.
Definition: sch_text.cpp:1625
void AddDrawItem(LIB_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
Definition: lib_symbol.cpp:716
LABEL_SPIN_STYLE GetLabelSpinStyle() const
Definition: sch_text.h:159
void SetLineColor(const COLOR4D &aColor)
Definition: sch_line.cpp:213
bool IsVisible() const
Definition: lib_pin.h:97
GRAPHIC_PINSHAPE GetShape() const
Definition: sch_pin.cpp:122
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:65
to handle and draw images bitmaps
Definition: layer_ids.h:230
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_text.cpp:555
int GetNameTextSize() const
Definition: lib_pin.h:126
wxPoint GetCenter() const
Definition: lib_shape.h:90
VECTOR2D ComputeStringBoundaryLimits(const UTF8 &aText, const VECTOR2D &aGlyphSize, double aGlyphThickness) const
Compute the boundary limits of aText (the bounding box of all shapes).
constexpr double dash_gap_len(double aLineWidth)
wxString GetShownName() const
Definition: lib_pin.cpp:172
void SetVerticalJustify(const EDA_TEXT_VJUSTIFY_T aVerticalJustify)
Set the vertical justify for text drawing.
wxString SHAPE_T_asString() const
Definition: eda_shape.cpp:71
static VECTOR2D mapCoords(const wxPoint &aCoord)
wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: sch_text.cpp:600
wxPoint GetPosition() const override
Definition: sch_sheet.h:379
void SetFontItalic(bool aItalic)
Set italic property of current font.
int GetConvert() const
Definition: lib_item.h:269
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:484
static LIB_SYMBOL * dummy()
Used when a LIB_SYMBOL is not found in library to draw a dummy shape.
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:40
int GetHeight() const
Definition: eda_rect.h:119
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:227
wxString UnescapeString(const wxString &aSource)
void SetGlyphSize(const VECTOR2D &aSize)
Set the font glyph size.
void SetY(int val)
Definition: eda_rect.h:173
virtual int GetPenWidth() const
Definition: sch_item.h:276
virtual void Scale(const VECTOR2D &aScale)
Scale the context.
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:154
double m_MinPlotPenWidth
Sets an absolute minimum pen width for plotting.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:54
PLOT_DASH_TYPE
Dashed line types.
Definition: plotter.h:104
wxPoint GetPosition() const override
Definition: lib_pin.h:212
void draw(LIB_PIN *aPin, int aLayer)
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:259
static void orientSymbol(LIB_SYMBOL *symbol, int orientation)
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:183
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...
double GetTextAngleRadians() const
Definition: eda_text.h:198
void Normalize()
Ensures that the height ant width are positive.
Definition: eda_rect.cpp:35
SCH_FIELD * GetIntersheetRefs()
Definition: sch_text.h:415
int externalPinDecoSize(const LIB_PIN &aPin)
void SetTextMirrored(bool aMirrored)
Set a mirrored property of text.
ELECTRICAL_PINTYPE GetType() const
Definition: lib_pin.h:84
LIB_SYMBOL * GetParent() const
Definition: lib_item.h:164
void LoadColors(const COLOR_SETTINGS *aSettings) override
Definition: sch_painter.cpp:90
COLOR4D GetColor(int aLayer) const
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: sch_line.h:137
bool IsForceVisible() const
Definition: eda_item.h:205
int GetNumberTextSize() const
Definition: lib_pin.h:129
virtual void Restore()
Restore the context.
bool m_DrawBoundingBoxes
Draw GAL bounding boxes in painters.
virtual void DrawPolygon(const std::deque< VECTOR2D > &aPointList)
Draw a polygon.
void SetName(const wxString &aName)
Definition: lib_pin.h:108
void SetFontUnderlined(bool aUnderlined)
Schematic symbol object.
Definition: sch_symbol.h:78
PLOT_DASH_TYPE GetEffectiveLineStyle() const
Definition: sch_line.cpp:287
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
virtual void DrawCircle(const VECTOR2D &aCenterPoint, double aRadius)
Draw a circle using world coordinates.
void CreateGraphicShape(const RENDER_SETTINGS *aRenderSettings, std::vector< wxPoint > &aPoints, const wxPoint &aPos) const override
Calculate the graphic shape (a polygon) associated to the text.
Definition: sch_text.cpp:1344
const EDA_RECT GetBoundingBox() const override
Definition: lib_text.cpp:377
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_field.cpp:305
int GetLength() const
Definition: lib_pin.h:81
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
EDA_TEXT_VJUSTIFY_T GetVerticalJustify() const
Returns current text vertical justification setting.
wxSize GetSize() const
Definition: sch_sheet.h:104
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int internalPinDecoSize(const LIB_PIN &aPin)
#define IS_ROLLOVER
Rollover active. Used for hyperlink highlighting.
#define HANDLE_ITEM(type_id, type_name)
#define PIN_TEXT_MARGIN
Definition: lib_pin.cpp:38
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
Definition: sch_symbol.cpp:870
ELECTRICAL_PINTYPE GetType() const
Definition: sch_pin.cpp:113
bool IsStartDangling() const
Definition: sch_line.h:211
double GetImageScale() const
Definition: sch_bitmap.h:66
int GetEffectiveDiameter() const
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:390
double DECIDEG2RAD(double deg)
Definition: trigo.h:233
#define IU_PER_MILS
Definition: plotter.cpp:130
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
int GetY() const
Definition: eda_rect.h:108
#define TARGET_PIN_RADIUS
Definition: lib_pin.h:36
wxPoint GetPosition() const override
Definition: sch_symbol.h:645
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:99
wxPoint Centre() const
Definition: eda_rect.h:64
COLOR4D getRenderColor(const EDA_ITEM *aItem, int aLayer, bool aDrawingShadows) const
int GetDefaultPenWidth() const
Color settings are a bit different than most of the settings objects in that there can be more than o...
int GetOrientation()
Get the display symbol orientation.
const wxPoint & GetTextPos() const
Definition: eda_text.h:268
constexpr int delta
#define DEFAULT_TEXT_SIZE
Ratio of the font height to the baseline of the text above the wire.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
bool GetOverrideSchItemColors() const
double square(double x)
#define TEXT_ANGLE_VERT
Definition: eda_text.h:72
SHAPE_T GetShape() const
Definition: eda_shape.h:101
virtual void Save()
Save the context.
void SetHorizontalJustify(const EDA_TEXT_HJUSTIFY_T aHorizontalJustify)
Set the horizontal justify for text drawing.
bool MapAngles(int *aAngle1, int *aAngle2) const
Calculate new angles according to the transform.
Definition: transform.cpp:79
const Vec & GetOrigin() const
Definition: box2.h:176
int GetUnit() const
Definition: sch_symbol.h:196
float getLineWidth(const LIB_ITEM *aItem, bool aDrawingShadows) const
const EDA_RECT GetBoundingBoxRotated(const wxPoint &aRotCenter, double aAngle) const
Useful to calculate bounding box of rotated items, when rotation if not k*90 degrees.
Definition: eda_rect.cpp:513
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:121
int GetRadius() const
Definition: eda_shape.cpp:472
void SetDefaultPenWidth(int aWidth)
not connected (must be left open)
bool IsBus() const
wxPoint GetPosition() const override
Definition: lib_shape.h:87
wxPoint GetParentPosition() const
Definition: sch_field.cpp:858
virtual void Translate(const VECTOR2D &aTranslation)
Translate the context.
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
static constexpr int Millimeter2iu(double mm)
int GetConvert() const
Definition: sch_symbol.h:224
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:182
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:154
Implement a stroke font drawing.
Definition: stroke_font.h:54
constexpr double dash_mark_len(double aLineWidth)
FILL_T GetFillType() const
Definition: eda_shape.h:88
#define DEFAULT_TEXT_OFFSET_RATIO
Ratio of the font height to space around global labels.
SCH_RENDER_SETTINGS m_schSettings
Definition: sch_painter.h:195
void drawPinDanglingSymbol(const VECTOR2I &aPos, const COLOR4D &aColor, bool aDrawingShadows)
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:112
Abstract interface for drawing on a 2D-surface.
wxPoint GetEnd() const
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103
wxPoint GetPosition() const override
wxPoint GetEndPoint() const
Definition: sch_line.h:93