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 <tomasz.wlostowski@cern.ch>
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 
30 #include <bezier_curves.h>
31 #include <class_library.h>
32 #include <connection_graph.h>
36 #include <gr_text.h>
37 #include <lib_arc.h>
38 #include <lib_bezier.h>
39 #include <lib_circle.h>
40 #include <lib_field.h>
41 #include <lib_item.h>
42 #include <lib_pin.h>
43 #include <lib_polyline.h>
44 #include <lib_rectangle.h>
45 #include <lib_text.h>
46 #include <math/util.h>
47 #include <plotter.h>
48 #include <sch_bitmap.h>
49 #include <sch_bus_entry.h>
50 #include <sch_symbol.h>
51 #include <sch_edit_frame.h>
52 #include <sch_field.h>
53 #include <sch_junction.h>
54 #include <sch_line.h>
55 #include <sch_marker.h>
56 #include <sch_no_connect.h>
57 #include <sch_sheet.h>
58 #include <sch_text.h>
59 #include <schematic.h>
61 #include <view/view.h>
62 #include <kiface_i.h>
63 #include <default_values.h>
64 #include <advanced_config.h>
65 #include "sch_painter.h"
66 
67 namespace KIGFX
68 {
69 
71  m_ShowUnit( 0 ),
72  m_ShowConvert( 0 ),
73  m_ShowHiddenText( true ),
74  m_ShowHiddenPins( true ),
75  m_ShowPinsElectricalType( true ),
76  m_ShowDisabled( false ),
77  m_ShowGraphicsDisabled( false ),
78  m_ShowUmbilicals( true ),
79  m_OverrideItemColors( false ),
80  m_TextOffsetRatio( 0.08 ),
81  m_DefaultWireThickness( DEFAULT_WIRE_THICKNESS * IU_PER_MILS ),
82  m_DefaultBusThickness( DEFAULT_BUS_THICKNESS * IU_PER_MILS ),
83  m_PinSymbolSize( DEFAULT_TEXT_SIZE * IU_PER_MILS / 2 ),
84  m_JunctionSize( DEFAULT_JUNCTION_DIAM * IU_PER_MILS )
85 {
87 
89 }
90 
91 
93 {
94  for( int layer = SCH_LAYER_ID_START; layer < SCH_LAYER_ID_END; layer ++)
95  m_layerColors[ layer ] = aSettings->GetColor( layer );
96 
97  for( int layer = GAL_LAYER_ID_START; layer < GAL_LAYER_ID_END; layer ++)
98  m_layerColors[ layer ] = aSettings->GetColor( layer );
99 
101 
103 
105 }
106 
107 
108 COLOR4D SCH_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) const
109 {
110  return m_layerColors[ aLayer ];
111 }
112 
113 
115 {
116  return dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
117 }
118 
119 
133 static LIB_PART* dummy()
134 {
135  static LIB_PART* part;
136 
137  if( !part )
138  {
139  part = new LIB_PART( wxEmptyString );
140 
141  LIB_RECTANGLE* square = new LIB_RECTANGLE( part );
142 
143  square->MoveTo( wxPoint( Mils2iu( -200 ), Mils2iu( 200 ) ) );
144  square->SetEndPosition( wxPoint( Mils2iu( 200 ), Mils2iu( -200 ) ) );
145 
146  LIB_TEXT* text = new LIB_TEXT( part );
147 
148  text->SetTextSize( wxSize( Mils2iu( 150 ), Mils2iu( 150 ) ) );
149  text->SetText( wxString( wxT( "??" ) ) );
150 
151  part->AddDrawItem( square );
152  part->AddDrawItem( text );
153  }
154 
155  return part;
156 }
157 
158 
160  KIGFX::PAINTER( aGal ),
161  m_schematic( nullptr )
162 { }
163 
164 
165 #define HANDLE_ITEM( type_id, type_name ) \
166  case type_id: draw( (type_name *) item, aLayer ); break
167 
168 
169 bool SCH_PAINTER::Draw( const VIEW_ITEM *aItem, int aLayer )
170 {
171  const auto item = dynamic_cast<const EDA_ITEM*>( aItem );
172 
173  if( !item )
174  return false;
175 
176 #ifdef CONNECTIVITY_DEBUG
177 
178  auto sch_item = dynamic_cast<const SCH_ITEM*>( item );
179  auto conn = sch_item ? sch_item->Connection( *g_CurrentSheet ) : nullptr;
180 
181  if( conn )
182  {
183  auto pos = item->GetBoundingBox().Centre();
184  auto label = conn->Name( true );
185 
189  m_gal->SetLineWidth( Mils2ui( 2 ) );
190  m_gal->SetGlyphSize( VECTOR2D( Mils2ui( 20 ), Mils2ui( 20 ) ) );
191  m_gal->StrokeText( conn->Name( true ), pos, 0.0, 0 );
192  }
193 
194 #endif
195 
197  {
198  BOX2I box = item->GetBoundingBox();
199 
200  if( item->Type() == SCH_COMPONENT_T )
201  box = static_cast<const SCH_COMPONENT*>( item )->GetBodyBoundingBox();
202 
203  m_gal->SetIsFill( false );
204  m_gal->SetIsStroke( true );
205  m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) :
206  COLOR4D( 0.2, 0.2, 0.2, 1 ) );
207  m_gal->SetLineWidth( Mils2iu( 3 ) );
208  m_gal->DrawRectangle( box.GetOrigin(), box.GetEnd() );
209  }
210 
211  switch( item->Type() )
212  {
237 
238  default: return false;
239  }
240 
241  return false;
242 }
243 
244 
246 {
247  if( m_schSettings.m_ShowUnit // showing a specific unit
248  && aItem->GetUnit() // item is unit-specific
249  && aItem->GetUnit() != m_schSettings.m_ShowUnit )
250  {
251  return false;
252  }
253 
254  if( m_schSettings.m_ShowConvert // showing a specific conversion
255  && aItem->GetConvert() // item is conversion-specific
256  && aItem->GetConvert() != m_schSettings.m_ShowConvert )
257  {
258  return false;
259  }
260 
261  return true;
262 }
263 
264 
266 {
267  const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
268 
269  // For best visuals the selection width must be a cross between the zoom level and the
270  // default line width.
271  return (float) std::fabs( matrix.GetScale().x * 2.75 ) + Mils2iu( eeconfig()->m_Selection.thickness );
272 }
273 
274 
275 COLOR4D SCH_PAINTER::getRenderColor( const EDA_ITEM* aItem, int aLayer, bool aDrawingShadows ) const
276 {
278 
279  if( aItem->Type() == SCH_LINE_T )
280  {
281  COLOR4D lineColor = static_cast<const SCH_LINE*>( aItem )->GetLineColor();
282 
283  if( lineColor != COLOR4D::UNSPECIFIED )
284  color = lineColor;
285  }
286  else if( aItem->Type() == SCH_BUS_WIRE_ENTRY_T )
287  {
288  COLOR4D busEntryColor = static_cast<const SCH_BUS_WIRE_ENTRY*>( aItem )->GetStrokeColor();
289 
290  if( busEntryColor != COLOR4D::UNSPECIFIED )
291  color = busEntryColor;
292  }
293  else if( aItem->Type() == SCH_JUNCTION_T )
294  {
295  COLOR4D junctionColor = static_cast<const SCH_JUNCTION*>( aItem )->GetJunctionColor();
296 
297  if( junctionColor != COLOR4D::UNSPECIFIED )
298  color = junctionColor;
299  }
300  else if( aItem->Type() == SCH_SHEET_T )
301  {
302  SCH_SHEET* sheet = (SCH_SHEET*) aItem;
303 
305  color = m_schSettings.GetLayerColor( aLayer );
306  else if( aLayer == LAYER_SHEET )
307  color = sheet->GetBorderColor();
308  else if( aLayer == LAYER_SHEET_BACKGROUND )
309  color = sheet->GetBackgroundColor();
310 
311  if( color == COLOR4D::UNSPECIFIED )
312  color = m_schSettings.GetLayerColor( aLayer );
313  }
314 
315  if( aItem->IsBrightened() && !aDrawingShadows ) // Selection disambiguation, etc.
316  {
318 
319  if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_SHEET_BACKGROUND )
320  color = color.WithAlpha( 0.2 );
321  }
322  else if( aItem->IsSelected() )
323  {
324  if( aDrawingShadows )
326  }
327 
329  || ( m_schSettings.m_ShowGraphicsDisabled && aItem->Type() != LIB_FIELD_T ) )
330  {
331  color = color.Darken( 0.5f );
332  }
333 
334  return color;
335 }
336 
337 
338 float SCH_PAINTER::getLineWidth( const LIB_ITEM* aItem, bool aDrawingShadows ) const
339 {
340  float width = (float) std::max( aItem->GetPenWidth(), m_schSettings.GetDefaultPenWidth() );
341 
342  if( aItem->IsSelected() && aDrawingShadows )
343  width += getShadowWidth();
344 
345  return width;
346 }
347 
348 
349 float SCH_PAINTER::getLineWidth( const SCH_ITEM* aItem, bool aDrawingShadows ) const
350 {
351  wxCHECK( aItem, static_cast<float>( m_schSettings.m_DefaultWireThickness ) );
352 
353  float width = (float) aItem->GetPenWidth();
354 
355  if( aItem->IsSelected() && aDrawingShadows )
356  width += getShadowWidth();
357 
358  return std::max( width, 1.0f );
359 }
360 
361 
362 float SCH_PAINTER::getTextThickness( const SCH_TEXT* aItem, bool aDrawingShadows ) const
363 {
364  float width = (float) aItem->GetEffectiveTextPenWidth( m_schSettings.GetDefaultPenWidth() );
365 
366  if( aItem->IsSelected() && aDrawingShadows )
367  width += getShadowWidth();
368 
369  return width;
370 }
371 
372 
373 float SCH_PAINTER::getTextThickness( const SCH_FIELD* aItem, bool aDrawingShadows ) const
374 {
375  float width = (float) aItem->GetEffectiveTextPenWidth( m_schSettings.GetDefaultPenWidth() );
376 
377  if( aItem->IsSelected() && aDrawingShadows )
378  width += getShadowWidth();
379 
380  return width;
381 }
382 
383 
384 float SCH_PAINTER::getTextThickness( const LIB_FIELD* aItem, bool aDrawingShadows ) const
385 {
386  float width = (float) std::max( aItem->GetEffectiveTextPenWidth(),
388 
389  if( aItem->IsSelected() && aDrawingShadows )
390  width += getShadowWidth();
391 
392  return width;
393 }
394 
395 
396 float SCH_PAINTER::getTextThickness( const LIB_TEXT* aItem, bool aDrawingShadows ) const
397 {
398  float width = (float) std::max( aItem->GetEffectiveTextPenWidth(),
400 
401  if( aItem->IsSelected() && aDrawingShadows )
402  width += getShadowWidth();
403 
404  return width;
405 }
406 
407 
408 void SCH_PAINTER::strokeText( const wxString& aText, const VECTOR2D& aPosition, double aAngle )
409 {
410  m_gal->StrokeText( aText, aPosition, aAngle );
411 }
412 
413 
414 void SCH_PAINTER::draw( const LIB_PART *aPart, int aLayer, bool aDrawFields, int aUnit, int aConvert )
415 {
416  if( !aUnit )
417  aUnit = m_schSettings.m_ShowUnit;
418 
419  if( !aConvert )
420  aConvert = m_schSettings.m_ShowConvert;
421 
422  std::unique_ptr< LIB_PART > tmpPart;
423  const LIB_PART* drawnPart = aPart;
424 
425  if( aPart->IsAlias() )
426  {
427  tmpPart = aPart->Flatten();
428  drawnPart = tmpPart.get();
429  }
430 
431  for( const LIB_ITEM& item : drawnPart->GetDrawItems() )
432  {
433  if( !aDrawFields && item.Type() == LIB_FIELD_T )
434  continue;
435 
436  if( aUnit && item.GetUnit() && aUnit != item.GetUnit() )
437  continue;
438 
439  if( aConvert && item.GetConvert() && aConvert != item.GetConvert() )
440  continue;
441 
442  Draw( &item, aLayer );
443  }
444 }
445 
446 
447 static VECTOR2D mapCoords( const wxPoint& aCoord )
448 {
449  return VECTOR2D( aCoord.x, -aCoord.y );
450 }
451 
452 
453 void SCH_PAINTER::triLine( const VECTOR2D &a, const VECTOR2D &b, const VECTOR2D &c )
454 {
455  m_gal->DrawLine( a, b );
456  m_gal->DrawLine( b, c );
457 }
458 
459 
460 bool SCH_PAINTER::setDeviceColors( const LIB_ITEM* aItem, int aLayer )
461 {
462  switch( aLayer )
463  {
465  if( aItem->IsSelected() )
466  {
467  m_gal->SetIsFill( false );
468  m_gal->SetIsStroke( true );
469  m_gal->SetLineWidth( getLineWidth( aItem, true ) );
470  m_gal->SetStrokeColor( getRenderColor( aItem, LAYER_DEVICE, true ) );
471  m_gal->SetFillColor( getRenderColor( aItem, LAYER_DEVICE, true ) );
472  return true;
473  }
474 
475  return false;
476 
479  {
480  COLOR4D fillColor = getRenderColor( aItem, LAYER_DEVICE_BACKGROUND, false );
481 
482  // These actions place the item over others, so allow a modest transparency here
483  if( aItem->IsMoving() || aItem->IsDragging() || aItem->IsResized() )
484  fillColor = fillColor.WithAlpha( 0.75 );
485 
487  m_gal->SetFillColor( fillColor );
488  m_gal->SetIsStroke( false );
489  return true;
490  }
491 
492  return false;
493 
494  case LAYER_DEVICE:
496  m_gal->SetFillColor( getRenderColor( aItem, LAYER_DEVICE, false ) );
497 
498  if( aItem->GetPenWidth() > 0 || aItem->GetFillMode() == FILL_TYPE::NO_FILL )
499  {
500  m_gal->SetIsStroke( true );
501  m_gal->SetLineWidth( getLineWidth( aItem, false ) );
502  m_gal->SetStrokeColor( getRenderColor( aItem, LAYER_DEVICE, false ) );
503  }
504  else
505  {
506  m_gal->SetIsStroke( false );
507  }
508 
509  return true;
510 
511  default:
512  return false;
513  }
514 }
515 
516 
518 {
519  if( aLayer == LAYER_SELECTION_SHADOWS && eeconfig()->m_Selection.fill_shapes )
520  m_gal->SetIsFill( true );
521 }
522 
523 
524 void SCH_PAINTER::draw( const LIB_RECTANGLE *aRect, int aLayer )
525 {
526  if( !isUnitAndConversionShown( aRect ) )
527  return;
528 
529  if( setDeviceColors( aRect, aLayer ) )
530  {
531  fillIfSelection( aLayer );
532  m_gal->DrawRectangle( mapCoords( aRect->GetPosition() ), mapCoords( aRect->GetEnd() ) );
533  }
534 }
535 
536 
537 void SCH_PAINTER::draw( const LIB_CIRCLE *aCircle, int aLayer )
538 {
539  if( !isUnitAndConversionShown( aCircle ) )
540  return;
541 
542  if( setDeviceColors( aCircle, aLayer ) )
543  {
544  fillIfSelection( aLayer );
545  m_gal->DrawCircle( mapCoords( aCircle->GetPosition() ), aCircle->GetRadius() );
546  }
547 }
548 
549 
550 void SCH_PAINTER::draw( const LIB_ARC *aArc, int aLayer )
551 {
552  if( !isUnitAndConversionShown( aArc ) )
553  return;
554 
555  if( setDeviceColors( aArc, aLayer ) )
556  {
557  int sai = aArc->GetFirstRadiusAngle();
558  int eai = aArc->GetSecondRadiusAngle();
559 
570  if( !TRANSFORM().MapAngles( &sai, &eai ) )
571  {
572  LIB_ARC new_arc( *aArc );
573 
574  new_arc.SetStart( aArc->GetEnd() );
575  new_arc.SetEnd( aArc->GetStart() );
576  new_arc.CalcRadiusAngles();
577  sai = new_arc.GetFirstRadiusAngle();
578  eai = new_arc.GetSecondRadiusAngle();
579  TRANSFORM().MapAngles( &sai, &eai );
580  }
581 
582  double sa = (double) sai * M_PI / 1800.0;
583  double ea = (double) eai * M_PI / 1800.0 ;
584 
585  VECTOR2D pos = mapCoords( aArc->GetPosition() );
586 
587  m_gal->DrawArc( pos, aArc->GetRadius(), sa, ea );
588  }
589 }
590 
591 
592 void SCH_PAINTER::draw( const LIB_POLYLINE *aLine, int aLayer )
593 {
594  if( !isUnitAndConversionShown( aLine ) )
595  return;
596 
597  if( setDeviceColors( aLine, aLayer ) )
598  {
599  const std::vector<wxPoint>& pts = aLine->GetPolyPoints();
600  std::deque<VECTOR2D> vtx;
601 
602  for( auto p : pts )
603  vtx.push_back( mapCoords( p ) );
604 
605  fillIfSelection( aLayer );
606  m_gal->DrawPolygon( vtx );
607  }
608 }
609 
610 
611 void SCH_PAINTER::draw( const LIB_FIELD *aField, int aLayer )
612 {
613  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
614 
615  if( drawingShadows && !aField->IsSelected() )
616  return;
617 
618  if( !isUnitAndConversionShown( aField ) )
619  return;
620 
621  // Must check layer as fields are sometimes drawn by their parent rather than
622  // directly from the view.
623  int layers[KIGFX::VIEW::VIEW_MAX_LAYERS];
624  int layers_count;
625  bool foundLayer = false;
626 
627  aField->ViewGetLayers( layers, layers_count );
628 
629  for( int i = 0; i < layers_count; ++i )
630  {
631  if( layers[i] == aLayer )
632  foundLayer = true;
633  }
634 
635  if( !foundLayer )
636  return;
637 
638  COLOR4D color = getRenderColor( aField, aLayer, drawingShadows );
639 
640  if( !( aField->IsVisible() || aField->IsForceVisible() ) )
641  {
643  color = getRenderColor( aField, LAYER_HIDDEN, drawingShadows );
644  else
645  return;
646  }
647 
648  m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
649  m_gal->SetIsFill( false );
650  m_gal->SetIsStroke( true );
652 
653  auto pos = mapCoords( aField->GetPosition() );
654 
655  if( drawingShadows && eeconfig()->m_Selection.text_as_box )
656  {
657  EDA_RECT boundaryBox = aField->GetBoundingBox();
658 
659  m_gal->SetIsFill( true );
661  m_gal->SetLineWidth( m_gal->GetLineWidth() * 0.5 );
662  boundaryBox.RevertYAxis();
663 
664  m_gal->DrawRectangle( mapCoords( boundaryBox.GetPosition() ),
665  mapCoords( boundaryBox.GetEnd() ) );
666  }
667  else
668  {
669  m_gal->SetGlyphSize( VECTOR2D( aField->GetTextSize() ) );
670  m_gal->SetFontItalic( aField->IsItalic() );
671 
674 
675  double orient = aField->GetTextAngleRadians();
676 
677  strokeText( aField->GetText(), pos, orient );
678  }
679 
680  // Draw the umbilical line
681  if( aField->IsMoving() && m_schSettings.m_ShowUmbilicals )
682  {
684  m_gal->SetStrokeColor( COLOR4D( 0.0, 0.0, 1.0, 1.0 ) );
685  m_gal->DrawLine( pos, wxPoint( 0, 0 ) );
686  }
687 }
688 
689 
690 void SCH_PAINTER::draw( const LIB_TEXT *aText, int aLayer )
691 {
692  if( !isUnitAndConversionShown( aText ) )
693  return;
694 
695  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
696 
697  if( drawingShadows && !aText->IsSelected() )
698  return;
699 
700  COLOR4D color = getRenderColor( aText, LAYER_DEVICE, drawingShadows );
701 
702  if( !aText->IsVisible() )
703  {
705  color = getRenderColor( aText, LAYER_HIDDEN, drawingShadows );
706  else
707  return;
708  }
709 
710  EDA_RECT bBox = aText->GetBoundingBox();
711  bBox.RevertYAxis();
712  VECTOR2D pos = mapCoords( bBox.Centre() );
713  double orient = aText->GetTextAngleRadians();
714 
717  m_gal->SetLineWidth( getTextThickness( aText, drawingShadows ) );
718  m_gal->SetIsFill( false );
719  m_gal->SetIsStroke( true );
721  m_gal->SetGlyphSize( VECTOR2D( aText->GetTextSize() ) );
722  m_gal->SetFontBold( aText->IsBold() );
723  m_gal->SetFontItalic( aText->IsItalic() );
724  m_gal->SetFontUnderlined( false );
725  strokeText( aText->GetText(), pos, orient );
726 }
727 
728 
730 {
733 
734  return aPin.GetNameTextSize() != 0 ? aPin.GetNameTextSize() / 2 : aPin.GetNumberTextSize() / 2;
735 }
736 
737 
738 // Utility for getting the size of the 'external' pin decorators (as a radius)
739 // i.e. the negation circle, the polarity 'slopes' and the nonlogic marker
741 {
744 
745  return aPin.GetNumberTextSize() / 2;
746 }
747 
748 
749 // Draw the target (an open circle) for a pin which has no connection or is being moved.
750 void SCH_PAINTER::drawPinDanglingSymbol( const VECTOR2I& aPos, bool aDrawingShadows )
751 {
752  m_gal->SetIsFill( false );
753  m_gal->SetIsStroke( true );
754  m_gal->SetLineWidth( aDrawingShadows ? getShadowWidth()
756 
758 }
759 
760 
761 void SCH_PAINTER::draw( LIB_PIN *aPin, int aLayer )
762 {
763  if( !isUnitAndConversionShown( aPin ) )
764  return;
765 
766  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
767 
768  if( drawingShadows && !aPin->IsSelected() )
769  return;
770 
771  VECTOR2I pos = mapCoords( aPin->GetPosition() );
772  COLOR4D color = getRenderColor( aPin, LAYER_PIN, drawingShadows );
773 
774  if( !aPin->IsVisible() )
775  {
777  {
778  color = getRenderColor( aPin, LAYER_HIDDEN, drawingShadows );
779  }
780  else
781  {
782  if( aPin->HasFlag( IS_DANGLING ) && aPin->IsPowerConnection() )
783  drawPinDanglingSymbol( pos, drawingShadows );
784 
785  return;
786  }
787  }
788 
789  VECTOR2I p0;
790  VECTOR2I dir;
791  int len = aPin->GetLength();
792  int orient = aPin->GetOrientation();
793 
794  switch( orient )
795  {
796  case PIN_UP:
797  p0 = VECTOR2I( pos.x, pos.y - len );
798  dir = VECTOR2I( 0, 1 );
799  break;
800 
801  case PIN_DOWN:
802  p0 = VECTOR2I( pos.x, pos.y + len );
803  dir = VECTOR2I( 0, -1 );
804  break;
805 
806  case PIN_LEFT:
807  p0 = VECTOR2I( pos.x - len, pos.y );
808  dir = VECTOR2I( 1, 0 );
809  break;
810 
811  default:
812  case PIN_RIGHT:
813  p0 = VECTOR2I( pos.x + len, pos.y );
814  dir = VECTOR2I( -1, 0 );
815  break;
816  }
817 
818  VECTOR2D pc;
819 
820  m_gal->SetIsStroke( true );
821  m_gal->SetIsFill( false );
822  m_gal->SetLineWidth( getLineWidth( aPin, drawingShadows ) );
824  m_gal->SetFontBold( false );
825  m_gal->SetFontUnderlined( false );
826  m_gal->SetFontItalic( false );
827 
828  const int radius = externalPinDecoSize( *aPin );
829  const int diam = radius*2;
830  const int clock_size = internalPinDecoSize( *aPin );
831 
832  if( aPin->GetType() == ELECTRICAL_PINTYPE::PT_NC ) // Draw a N.C. symbol
833  {
834  m_gal->DrawLine( p0, pos );
835 
836  m_gal->DrawLine( pos + VECTOR2D( -1, -1 ) * TARGET_PIN_RADIUS,
837  pos + VECTOR2D( 1, 1 ) * TARGET_PIN_RADIUS );
838  m_gal->DrawLine( pos + VECTOR2D( 1, -1 ) * TARGET_PIN_RADIUS ,
839  pos + VECTOR2D( -1, 1 ) * TARGET_PIN_RADIUS );
840 
841  aPin->ClearFlags( IS_DANGLING ); // PIN_NC pin type is always not connected and dangling.
842  }
843  else
844  {
845  switch( aPin->GetShape() )
846  {
848  m_gal->DrawLine( p0, pos );
849  break;
850 
852  m_gal->DrawCircle( p0 + dir * radius, radius );
853  m_gal->DrawLine( p0 + dir * ( diam ), pos );
854  break;
855 
857  pc = p0 - dir * clock_size ;
858 
859  triLine( p0 + VECTOR2D( dir.y, -dir.x) * clock_size,
860  pc,
861  p0 + VECTOR2D( -dir.y, dir.x) * clock_size );
862 
863  m_gal->DrawCircle( p0 + dir * radius, radius );
864  m_gal->DrawLine( p0 + dir * ( diam ), pos );
865  break;
866 
869  pc = p0 - dir * clock_size ;
870 
871  triLine( p0 + VECTOR2D( dir.y, -dir.x) * clock_size,
872  pc,
873  p0 + VECTOR2D( -dir.y, dir.x) * clock_size );
874 
875  if( !dir.y )
876  {
877  triLine( p0 + VECTOR2D(dir.x, 0) * diam,
878  p0 + VECTOR2D(dir.x, -1) * diam,
879  p0 );
880  }
881  else /* MapX1 = 0 */
882  {
883  triLine( p0 + VECTOR2D( 0, dir.y) * diam,
884  p0 + VECTOR2D(-1, dir.y) * diam,
885  p0 );
886  }
887 
888  m_gal->DrawLine( p0, pos );
889  break;
890 
892  m_gal->DrawLine( p0, pos );
893 
894  if( !dir.y )
895  {
896  triLine( p0 + VECTOR2D( 0, clock_size ),
897  p0 + VECTOR2D( -dir.x * clock_size, 0 ),
898  p0 + VECTOR2D( 0, -clock_size ) );
899  }
900  else
901  {
902  triLine( p0 + VECTOR2D( clock_size, 0 ),
903  p0 + VECTOR2D( 0, -dir.y * clock_size ),
904  p0 + VECTOR2D( -clock_size, 0 ) );
905  }
906  break;
907 
909  m_gal->DrawLine( p0, pos );
910 
911  if( !dir.y )
912  {
913  triLine( p0 + VECTOR2D(dir.x, 0) * diam,
914  p0 + VECTOR2D(dir.x, -1) * diam,
915  p0 );
916  }
917  else /* MapX1 = 0 */
918  {
919  triLine( p0 + VECTOR2D( 0, dir.y) * diam,
920  p0 + VECTOR2D(-1, dir.y) * diam,
921  p0 );
922  }
923  break;
924 
925  case GRAPHIC_PINSHAPE::OUTPUT_LOW: // IEEE symbol "Active Low Output"
926  m_gal->DrawLine( p0, pos );
927 
928  if( !dir.y ) // Horizontal pin
929  m_gal->DrawLine( p0 - VECTOR2D( 0, diam ), p0 + VECTOR2D( dir.x, 0 ) * diam );
930  else // Vertical pin
931  m_gal->DrawLine( p0 - VECTOR2D( diam, 0 ), p0 + VECTOR2D( 0, dir.y ) * diam );
932  break;
933 
934  case GRAPHIC_PINSHAPE::NONLOGIC: // NonLogic pin symbol
935  m_gal->DrawLine( p0, pos );
936 
937  m_gal->DrawLine( p0 - VECTOR2D( dir.x + dir.y, dir.y - dir.x ) * radius,
938  p0 + VECTOR2D( dir.x + dir.y, dir.y - dir.x ) * radius );
939  m_gal->DrawLine( p0 - VECTOR2D( dir.x - dir.y, dir.x + dir.y ) * radius,
940  p0 + VECTOR2D( dir.x - dir.y, dir.x + dir.y ) * radius );
941  break;
942  }
943  }
944 
945 
946  if( aPin->HasFlag( IS_DANGLING ) && ( aPin->IsVisible() || aPin->IsPowerConnection() ) )
947  drawPinDanglingSymbol( pos, drawingShadows );
948 
949  LIB_PART* libEntry = aPin->GetParent();
950 
951  // Draw the labels
952  if( drawingShadows && ( libEntry->Type() == LIB_PART_T || libEntry->IsSelected() )
954  return;
955 
956  int textOffset = libEntry->GetPinNameOffset();
957 
958  float nameLineWidth = getLineWidth( aPin, drawingShadows );
959  nameLineWidth = Clamp_Text_PenSize( nameLineWidth, aPin->GetNameTextSize(), false );
960  float numLineWidth = getLineWidth( aPin, drawingShadows );
961  numLineWidth = Clamp_Text_PenSize( numLineWidth, aPin->GetNumberTextSize(), false );
962 
963  #define PIN_TEXT_MARGIN 4.0
964 
965  // Four locations around a pin where text can be drawn
966  enum { INSIDE = 0, OUTSIDE, ABOVE, BELOW };
967  int size[4] = { 0, 0, 0, 0 };
968  float thickness[4] = { numLineWidth, numLineWidth, numLineWidth, numLineWidth };
969  COLOR4D colour[4];
970  wxString text[4];
971 
972  // TextOffset > 0 means pin NAMES on inside, pin NUMBERS above and nothing below
973  if( textOffset )
974  {
975  size [INSIDE] = libEntry->ShowPinNames() ? aPin->GetNameTextSize() : 0;
976  thickness[INSIDE] = nameLineWidth;
977  colour [INSIDE] = getRenderColor( aPin, LAYER_PINNAM, drawingShadows );
978  text [INSIDE] = aPin->GetName();
979 
980  size [ABOVE] = libEntry->ShowPinNumbers() ? aPin->GetNumberTextSize() : 0;
981  thickness[ABOVE] = numLineWidth;
982  colour [ABOVE] = getRenderColor( aPin, LAYER_PINNUM, drawingShadows );
983  text [ABOVE] = aPin->GetNumber();
984  }
985  // Otherwise pin NAMES go above and pin NUMBERS go below
986  else
987  {
988  size [ABOVE] = libEntry->ShowPinNames() ? aPin->GetNameTextSize() : 0;
989  thickness[ABOVE] = nameLineWidth;
990  colour [ABOVE] = getRenderColor( aPin, LAYER_PINNAM, drawingShadows );
991  text [ABOVE] = aPin->GetName();
992 
993  size [BELOW] = libEntry->ShowPinNumbers() ? aPin->GetNumberTextSize() : 0;
994  thickness[BELOW] = numLineWidth;
995  colour [BELOW] = getRenderColor( aPin, LAYER_PINNUM, drawingShadows );
996  text [BELOW] = aPin->GetNumber();
997  }
998 
1000  {
1001  size [OUTSIDE] = std::max( aPin->GetNameTextSize() * 3 / 4, Millimeter2iu( 0.7 ) );
1002  thickness[OUTSIDE] = float( size[OUTSIDE] ) / 6.0F;
1003  colour [OUTSIDE] = getRenderColor( aPin, LAYER_NOTES, drawingShadows );
1004  text [OUTSIDE] = aPin->GetElectricalTypeName();
1005  }
1006 
1007  if( !aPin->IsVisible() )
1008  {
1009  for( COLOR4D& c : colour )
1010  c = getRenderColor( aPin, LAYER_HIDDEN, drawingShadows );
1011  }
1012 
1013  int insideOffset = textOffset;
1014  int outsideOffset = 10;
1015  float lineThickness = (float) m_schSettings.GetDefaultPenWidth();
1016  float aboveOffset = Mils2iu( PIN_TEXT_MARGIN ) + ( thickness[ABOVE] + lineThickness ) / 2.0;
1017  float belowOffset = Mils2iu( PIN_TEXT_MARGIN ) + ( thickness[BELOW] + lineThickness ) / 2.0;
1018 
1019  if( drawingShadows )
1020  {
1021  for( float& t : thickness )
1022  t += getShadowWidth();
1023 
1024  insideOffset -= KiROUND( getShadowWidth() / 2 );
1025  outsideOffset -= KiROUND( getShadowWidth() / 2 );
1026  }
1027 
1028  #define SET_DC( i ) \
1029  m_gal->SetGlyphSize( VECTOR2D( size[i], size[i] ) ); \
1030  m_gal->SetLineWidth( thickness[i] ); \
1031  m_gal->SetStrokeColor( colour[i] )
1032 
1033  switch( orient )
1034  {
1035  case PIN_LEFT:
1036  if( size[INSIDE] )
1037  {
1038  SET_DC( INSIDE );
1041  strokeText( text[INSIDE], pos + VECTOR2D( -insideOffset - len, 0 ), 0 );
1042  }
1043  if( size[OUTSIDE] )
1044  {
1045  SET_DC( OUTSIDE );
1048  strokeText( text[OUTSIDE], pos + VECTOR2D( outsideOffset, 0 ), 0 );
1049  }
1050  if( size[ABOVE] )
1051  {
1052  SET_DC( ABOVE );
1055  strokeText( text[ABOVE], pos + VECTOR2D( -len / 2.0, -aboveOffset ), 0 );
1056  }
1057  if( size[BELOW] )
1058  {
1059  SET_DC( BELOW );
1062  strokeText( text[BELOW], pos + VECTOR2D( -len / 2.0, belowOffset ), 0 );
1063  }
1064  break;
1065 
1066  case PIN_RIGHT:
1067  if( size[INSIDE] )
1068  {
1069  SET_DC( INSIDE );
1073  strokeText( text[INSIDE], pos + VECTOR2D( insideOffset + len, 0 ), 0 );
1074  }
1075  if( size[OUTSIDE] )
1076  {
1077  SET_DC( OUTSIDE );
1080  strokeText( text[OUTSIDE], pos + VECTOR2D( -outsideOffset, 0 ), 0 );
1081  }
1082  if( size[ABOVE] )
1083  {
1084  SET_DC( ABOVE );
1087  strokeText( text[ABOVE], pos + VECTOR2D( len / 2.0, -aboveOffset ), 0 );
1088  }
1089  if( size[BELOW] )
1090  {
1091  SET_DC( BELOW );
1094  strokeText( text[BELOW], pos + VECTOR2D( len / 2.0, belowOffset ), 0 );
1095  }
1096  break;
1097 
1098  case PIN_DOWN:
1099  if( size[INSIDE] )
1100  {
1101  SET_DC( INSIDE );
1104  strokeText( text[INSIDE], pos + VECTOR2D( 0, insideOffset + len ), M_PI / 2 );
1105  }
1106  if( size[OUTSIDE] )
1107  {
1108  SET_DC( OUTSIDE );
1111  strokeText( text[OUTSIDE], pos + VECTOR2D( 0, -outsideOffset ), M_PI / 2 );
1112  }
1113  if( size[ABOVE] )
1114  {
1115  SET_DC( ABOVE );
1118  strokeText( text[ABOVE], pos + VECTOR2D( -aboveOffset, len / 2.0 ), M_PI / 2 );
1119  }
1120  if( size[BELOW] )
1121  {
1122  SET_DC( BELOW );
1125  strokeText( text[BELOW], pos + VECTOR2D( belowOffset, len / 2.0 ), M_PI / 2 );
1126  }
1127  break;
1128 
1129  case PIN_UP:
1130  if( size[INSIDE] )
1131  {
1132  SET_DC( INSIDE );
1135  strokeText( text[INSIDE], pos + VECTOR2D( 0, -insideOffset - len ), M_PI / 2 );
1136  }
1137  if( size[OUTSIDE] )
1138  {
1139  SET_DC( OUTSIDE );
1142  strokeText( text[OUTSIDE], pos + VECTOR2D( 0, outsideOffset ), M_PI / 2 );
1143  }
1144  if( size[ABOVE] )
1145  {
1146  SET_DC( ABOVE );
1149  strokeText( text[ABOVE], pos + VECTOR2D( -aboveOffset, -len / 2.0 ), M_PI / 2 );
1150  }
1151  if( size[BELOW] )
1152  {
1153  SET_DC( BELOW );
1156  strokeText( text[BELOW], pos + VECTOR2D( belowOffset, -len / 2.0 ), M_PI / 2 );
1157  }
1158  break;
1159 
1160  default:
1161  wxFAIL_MSG( "Unknown pin orientation" );
1162  }
1163 }
1164 
1165 
1166 void SCH_PAINTER::draw( const LIB_BEZIER *aCurve, int aLayer )
1167 {
1168  if( !isUnitAndConversionShown( aCurve ) )
1169  return;
1170 
1171  if( setDeviceColors( aCurve, aLayer ) )
1172  {
1173  BEZIER_POLY poly ( aCurve->GetPoints() );
1174  std::vector<wxPoint> pts;
1175  std::deque<VECTOR2D> pts_xformed;
1176  poly.GetPoly( pts );
1177 
1178  for( const wxPoint &p : pts )
1179  pts_xformed.push_back( mapCoords( p ) );
1180 
1181  m_gal->DrawPolygon( pts_xformed );
1182  }
1183 }
1184 
1185 
1186 // Draw the target (an open square) for a wire or label which has no connection or is
1187 // being moved.
1188 void SCH_PAINTER::drawDanglingSymbol( const wxPoint& aPos, int aWidth, bool aDrawingShadows )
1189 {
1190  wxPoint radius( aWidth + Mils2iu( DANGLING_SYMBOL_SIZE / 2 ),
1191  aWidth + Mils2iu( DANGLING_SYMBOL_SIZE /2 ) );
1192 
1193  m_gal->SetIsStroke( true );
1194  m_gal->SetIsFill( false );
1195  m_gal->SetLineWidth( aDrawingShadows ? getShadowWidth()
1197 
1198  m_gal->DrawRectangle( aPos - radius, aPos + radius );
1199 }
1200 
1201 
1202 void SCH_PAINTER::draw( const SCH_JUNCTION *aJct, int aLayer )
1203 {
1204  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1205 
1206  if( drawingShadows && !aJct->IsSelected() )
1207  return;
1208 
1209  COLOR4D color = getRenderColor( aJct, aJct->GetLayer(), drawingShadows );
1210 
1211  int junctionSize = aJct->GetDiameter() / 2;
1212 
1213  if( junctionSize > 1 )
1214  {
1215  m_gal->SetIsStroke( drawingShadows );
1216  m_gal->SetLineWidth( getLineWidth( aJct, drawingShadows ) );
1218  m_gal->SetIsFill( !drawingShadows );
1219  m_gal->SetFillColor( color );
1220  m_gal->DrawCircle( aJct->GetPosition(), junctionSize );
1221  }
1222 }
1223 
1224 
1225 void SCH_PAINTER::draw( const SCH_LINE *aLine, int aLayer )
1226 {
1227  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1228 
1229  if( drawingShadows && !aLine->IsSelected() )
1230  return;
1231 
1232  COLOR4D color = getRenderColor( aLine, aLine->GetLayer(), drawingShadows );
1233  float width = getLineWidth( aLine, drawingShadows );
1234  PLOT_DASH_TYPE lineStyle = aLine->GetEffectiveLineStyle();
1235 
1236  m_gal->SetIsStroke( true );
1238  m_gal->SetLineWidth( width );
1239 
1240  if( lineStyle <= PLOT_DASH_TYPE::FIRST_TYPE || drawingShadows )
1241  {
1242  m_gal->DrawLine( aLine->GetStartPoint(), aLine->GetEndPoint() );
1243  }
1244  else
1245  {
1246  VECTOR2D start = aLine->GetStartPoint();
1247  VECTOR2D end = aLine->GetEndPoint();
1248 
1249  EDA_RECT clip( (wxPoint)start, wxSize( end.x - start.x, end.y - start.y ) );
1250  clip.Normalize();
1251 
1252  double theta = atan2( end.y - start.y, end.x - start.x );
1253  double strokes[] = { 1.0, DASH_GAP_LEN( width ), 1.0, DASH_GAP_LEN( width ) };
1254 
1255  switch( lineStyle )
1256  {
1257  default:
1258  case PLOT_DASH_TYPE::DASH:
1259  strokes[0] = strokes[2] = DASH_MARK_LEN( width );
1260  break;
1261  case PLOT_DASH_TYPE::DOT:
1262  strokes[0] = strokes[2] = DOT_MARK_LEN( width );
1263  break;
1265  strokes[0] = DASH_MARK_LEN( width );
1266  strokes[2] = DOT_MARK_LEN( width );
1267  break;
1268  }
1269 
1270  for( size_t i = 0; i < 10000; ++i )
1271  {
1272  // Calculations MUST be done in doubles to keep from accumulating rounding
1273  // errors as we go.
1274  VECTOR2D next( start.x + strokes[ i % 4 ] * cos( theta ),
1275  start.y + strokes[ i % 4 ] * sin( theta ) );
1276 
1277  // Drawing each segment can be done rounded to ints.
1278  wxPoint segStart( KiROUND( start.x ), KiROUND( start.y ) );
1279  wxPoint segEnd( KiROUND( next.x ), KiROUND( next.y ) );
1280 
1281  if( ClipLine( &clip, segStart.x, segStart.y, segEnd.x, segEnd.y ) )
1282  break;
1283  else if( i % 2 == 0 )
1284  m_gal->DrawLine( segStart, segEnd );
1285 
1286  start = next;
1287  }
1288  }
1289 
1290  if( aLine->IsStartDangling() && aLine->IsWire() )
1291  {
1292  drawDanglingSymbol( aLine->GetStartPoint(), getLineWidth( aLine, drawingShadows ),
1293  drawingShadows );
1294  }
1295 
1296  if( aLine->IsEndDangling() && aLine->IsWire() )
1297  {
1298  drawDanglingSymbol( aLine->GetEndPoint(), getLineWidth( aLine, drawingShadows ),
1299  drawingShadows );
1300  }
1301 }
1302 
1303 
1304 void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
1305 {
1306  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1307 
1308  if( drawingShadows && !aText->IsSelected() )
1309  return;
1310 
1311  switch( aText->Type() )
1312  {
1313  case SCH_SHEET_PIN_T: aLayer = LAYER_SHEETLABEL; break;
1314  case SCH_HIER_LABEL_T: aLayer = LAYER_HIERLABEL; break;
1315  case SCH_GLOBAL_LABEL_T: aLayer = LAYER_GLOBLABEL; break;
1316  case SCH_LABEL_T: aLayer = LAYER_LOCLABEL; break;
1317  default: aLayer = LAYER_NOTES; break;
1318  }
1319 
1320  COLOR4D color = getRenderColor( aText, aLayer, drawingShadows );
1321 
1322  if( m_schematic )
1323  {
1324  SCH_CONNECTION* conn = aText->Connection();
1325 
1326  if( conn && conn->IsBus() )
1327  color = getRenderColor( aText, LAYER_BUS, drawingShadows );
1328  }
1329 
1330  if( !( aText->IsVisible() || aText->IsForceVisible() ) )
1331  {
1333  color = getRenderColor( aText, LAYER_HIDDEN, drawingShadows );
1334  else
1335  return;
1336  }
1337 
1338  m_gal->SetIsFill( false );
1339  m_gal->SetIsStroke( true );
1340  m_gal->SetLineWidth( getTextThickness( aText, drawingShadows ) );
1342  m_gal->SetTextAttributes( aText );
1343  m_gal->SetFontUnderlined( false );
1344 
1345  VECTOR2D text_offset = aText->GetTextPos() + aText->GetSchematicTextOffset( &m_schSettings );
1346  wxString shownText( aText->GetShownText() );
1347 
1348  if( drawingShadows )
1349  {
1351  {
1352  EDA_RECT bBox = aText->GetBoundingBox();
1353 
1354  m_gal->SetIsFill( true );
1355  m_gal->SetFillColor( color );
1356  m_gal->SetLineWidth( m_gal->GetLineWidth() * 0.5 );
1357  bBox.RevertYAxis();
1358 
1359  m_gal->DrawRectangle( mapCoords( bBox.GetPosition() ), mapCoords( bBox.GetEnd() ) );
1360  return;
1361  }
1362 
1363  switch( aText->GetLabelSpinStyle() )
1364  {
1365  case LABEL_SPIN_STYLE::LEFT: text_offset.x += getShadowWidth() / 2; break;
1366  case LABEL_SPIN_STYLE::UP: text_offset.y += getShadowWidth() / 2; break;
1367  case LABEL_SPIN_STYLE::RIGHT: text_offset.x -= getShadowWidth() / 2; break;
1368  case LABEL_SPIN_STYLE::BOTTOM: text_offset.y -= getShadowWidth() / 2; break;
1369  }
1370  }
1371 
1372  if( !shownText.IsEmpty() )
1373  {
1374  strokeText( shownText, text_offset, aText->GetTextAngleRadians() );
1375  }
1376 
1377  if( aText->IsDangling() )
1378  {
1379  drawDanglingSymbol( aText->GetTextPos(), Mils2iu( DANGLING_SYMBOL_SIZE / 2 ),
1380  drawingShadows );
1381  }
1382 
1383 }
1384 
1385 
1386 static void orientPart( LIB_PART* part, int orientation )
1387 {
1388  struct ORIENT
1389  {
1390  int flag;
1391  int n_rots;
1392  int mirror_x;
1393  int mirror_y;
1394  }
1395  orientations[] =
1396  {
1397  { CMP_ORIENT_0, 0, 0, 0 },
1398  { CMP_ORIENT_90, 1, 0, 0 },
1399  { CMP_ORIENT_180, 2, 0, 0 },
1400  { CMP_ORIENT_270, 3, 0, 0 },
1401  { CMP_MIRROR_X + CMP_ORIENT_0, 0, 1, 0 },
1402  { CMP_MIRROR_X + CMP_ORIENT_90, 1, 1, 0 },
1403  { CMP_MIRROR_Y, 0, 0, 1 },
1404  { CMP_MIRROR_X + CMP_ORIENT_270, 3, 1, 0 },
1405  { CMP_MIRROR_Y + CMP_ORIENT_0, 0, 0, 1 },
1406  { CMP_MIRROR_Y + CMP_ORIENT_90, 1, 0, 1 },
1407  { CMP_MIRROR_Y + CMP_ORIENT_180, 2, 0, 1 },
1408  { CMP_MIRROR_Y + CMP_ORIENT_270, 3, 0, 1 }
1409  };
1410 
1411  ORIENT o = orientations[ 0 ];
1412 
1413  for( auto& i : orientations )
1414  {
1415  if( i.flag == orientation )
1416  {
1417  o = i;
1418  break;
1419  }
1420  }
1421 
1422  for( auto& item : part->GetDrawItems() )
1423  {
1424  for( int i = 0; i < o.n_rots; i++ )
1425  item.Rotate( wxPoint(0, 0 ), true );
1426 
1427  if( o.mirror_x )
1428  item.MirrorVertical( wxPoint( 0, 0 ) );
1429 
1430  if( o.mirror_y )
1431  item.MirrorHorizontal( wxPoint( 0, 0 ) );
1432  }
1433 }
1434 
1435 
1436 void SCH_PAINTER::draw( SCH_COMPONENT *aSymbol, int aLayer )
1437 {
1438  int unit = aSymbol->GetUnitSelection( &m_schematic->CurrentSheet() );
1439  int convert = aSymbol->GetConvert();
1440 
1441  // Use dummy part if the actual couldn't be found (or couldn't be locked).
1442  LIB_PART* originalPart = aSymbol->GetPartRef() ? aSymbol->GetPartRef().get() : dummy();
1443  LIB_PINS originalPins;
1444  originalPart->GetPins( originalPins, unit, convert );
1445 
1446  // Copy the source so we can re-orient and translate it.
1447  LIB_PART tempPart( *originalPart );
1448  LIB_PINS tempPins;
1449  tempPart.GetPins( tempPins, unit, convert );
1450 
1451  tempPart.SetFlags( aSymbol->GetFlags() );
1452 
1453  orientPart( &tempPart, aSymbol->GetOrientation() );
1454 
1455  for( auto& tempItem : tempPart.GetDrawItems() )
1456  {
1457  tempItem.SetFlags( aSymbol->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED
1458  tempItem.MoveTo( tempItem.GetPosition() + (wxPoint) mapCoords( aSymbol->GetPosition() ) );
1459  }
1460 
1461  // Copy the pin info from the symbol to the temp pins
1462  for( unsigned i = 0; i < tempPins.size(); ++ i )
1463  {
1464  SCH_PIN* symbolPin = aSymbol->GetPin( originalPins[ i ] );
1465  LIB_PIN* tempPin = tempPins[ i ];
1466 
1467  tempPin->ClearFlags();
1468  tempPin->SetFlags( symbolPin->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED
1469 
1470  tempPin->SetName( symbolPin->GetName() );
1471  tempPin->SetType( symbolPin->GetType() );
1472  tempPin->SetShape( symbolPin->GetShape() );
1473 
1474  if( symbolPin->IsDangling() )
1475  tempPin->SetFlags( IS_DANGLING );
1476  }
1477 
1478  draw( &tempPart, aLayer, false, aSymbol->GetUnit(), aSymbol->GetConvert() );
1479 
1480  // The fields are SCH_COMPONENT-specific so don't need to be copied/oriented/translated
1481  for( const SCH_FIELD& field : aSymbol->GetFields() )
1482  draw( &field, aLayer );
1483 }
1484 
1485 
1486 void SCH_PAINTER::draw( const SCH_FIELD *aField, int aLayer )
1487 {
1488  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1489 
1490  if( drawingShadows && !aField->IsSelected() )
1491  return;
1492 
1493  aLayer = aField->GetLayer();
1494 
1495  COLOR4D color = getRenderColor( aField, aLayer, drawingShadows );
1496 
1497  if( !( aField->IsVisible() || aField->IsForceVisible() ) )
1498  {
1500  color = getRenderColor( aField, LAYER_HIDDEN, drawingShadows );
1501  else
1502  return;
1503  }
1504 
1505  if( aField->IsVoid() )
1506  return;
1507 
1508  if( drawingShadows && aField->GetParent()->IsSelected()
1510  {
1511  return;
1512  }
1513 
1514  bool underline = false;
1515 
1516  if( aField->IsHypertext() && ( aField->GetFlags() & IS_ROLLOVER ) > 0 )
1517  {
1518  color = PUREBLUE;
1519  underline = true;
1520  }
1521 
1522  // Calculate the text orientation according to the parent orientation.
1523  int orient = (int) aField->GetTextAngle();
1524 
1525  if( aField->GetParent() && aField->GetParent()->Type() == SCH_COMPONENT_T )
1526  {
1527  if( static_cast<SCH_COMPONENT*>( aField->GetParent() )->GetTransform().y1 )
1528  {
1529  // Rotate symbol 90 degrees.
1530  if( orient == TEXT_ANGLE_HORIZ )
1531  orient = TEXT_ANGLE_VERT;
1532  else
1533  orient = TEXT_ANGLE_HORIZ;
1534  }
1535  }
1536 
1537  /*
1538  * Calculate the text justification, according to the symbol orientation/mirror.
1539  * This is a bit complicated due to cumulative calculations:
1540  * - numerous cases (mirrored or not, rotation)
1541  * - the DrawGraphicText function recalculate also H and H justifications according to the
1542  * text orientation.
1543  * - when symbol is mirrored, the text is not mirrored and justifications are complicated
1544  * to calculate so the easier way is to use no justifications (centered text) and use
1545  * GetBoundingBox to know the text coordinate considered as centered
1546  */
1547  EDA_RECT boundaryBox = aField->GetBoundingBox();
1548  wxPoint textpos = boundaryBox.Centre();
1549 
1551  m_gal->SetIsStroke( true );
1552 
1553  if( drawingShadows && eeconfig()->m_Selection.text_as_box )
1554  {
1555  m_gal->SetIsFill( true );
1556  m_gal->SetFillColor( color );
1557  m_gal->SetLineWidth( m_gal->GetLineWidth() * 0.5 );
1558  boundaryBox.RevertYAxis();
1559 
1560  m_gal->DrawRectangle( mapCoords( boundaryBox.GetPosition() ),
1561  mapCoords( boundaryBox.GetEnd() ) );
1562  }
1563  else
1564  {
1567  m_gal->SetIsFill( false );
1568  m_gal->SetGlyphSize( VECTOR2D( aField->GetTextSize() ) );
1569  m_gal->SetFontBold( aField->IsBold() );
1570  m_gal->SetFontItalic( aField->IsItalic() );
1571  m_gal->SetFontUnderlined( underline );
1572  m_gal->SetTextMirrored( aField->IsMirrored() );
1573  m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
1574 
1575  strokeText( aField->GetShownText(), textpos, orient == TEXT_ANGLE_VERT ? M_PI / 2 : 0 );
1576  }
1577 
1578  // Draw the umbilical line
1579  if( aField->IsMoving() )
1580  {
1581  wxPoint parentPos = aField->GetParentPosition();
1582 
1584  m_gal->SetStrokeColor( COLOR4D( 0.0, 0.0, 1.0, 1.0 ) );
1585  m_gal->DrawLine( textpos, parentPos );
1586  }
1587 }
1588 
1589 
1590 void SCH_PAINTER::draw( SCH_GLOBALLABEL *aLabel, int aLayer )
1591 {
1592  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1593 
1594  if( !drawingShadows || aLabel->IsSelected() )
1595  {
1596  COLOR4D color = getRenderColor( aLabel, LAYER_GLOBLABEL, drawingShadows );
1597 
1598  std::vector<wxPoint> pts;
1599  std::deque<VECTOR2D> pts2;
1600 
1601  aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() );
1602 
1603  for( const wxPoint& p : pts )
1604  pts2.emplace_back( VECTOR2D( p.x, p.y ) );
1605 
1606  // The text is drawn inside the graphic shape.
1607  // On Cairo the graphic shape is filled by the background before drawing the text.
1608  // However if the text is selected, it is draw twice: first on LAYER_SELECTION_SHADOWS
1609  // and second on the text layer. The second must not erase the first drawing.
1610  bool fillBg = ( aLayer == LAYER_SELECTION_SHADOWS ) || !aLabel->IsSelected();
1611  m_gal->SetIsFill( fillBg );
1613  m_gal->SetIsStroke( true );
1614  m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) );
1616  m_gal->DrawPolyline( pts2 );
1617 
1618  draw( static_cast<SCH_TEXT*>( aLabel ), aLayer );
1619  }
1620 
1621  if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children || !aLabel->IsSelected() )
1622  {
1623  draw( aLabel->GetIntersheetRefs(), aLayer );
1624  }
1625 }
1626 
1627 
1628 void SCH_PAINTER::draw( SCH_HIERLABEL *aLabel, int aLayer )
1629 {
1630  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1631 
1632  if( drawingShadows && !aLabel->IsSelected() )
1633  return;
1634 
1635  COLOR4D color = getRenderColor( aLabel, LAYER_SHEETLABEL, drawingShadows );
1636 
1637  if( m_schematic )
1638  {
1639  SCH_CONNECTION* conn = aLabel->Connection();
1640 
1641  if( conn && conn->IsBus() )
1642  color = getRenderColor( aLabel, LAYER_BUS, drawingShadows );
1643  }
1644 
1645  std::vector<wxPoint> pts;
1646  std::deque<VECTOR2D> pts2;
1647 
1648  aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() );
1649 
1650  for( auto p : pts )
1651  pts2.emplace_back( VECTOR2D( p.x, p.y ) );
1652 
1653  m_gal->SetIsFill( true );
1655  m_gal->SetIsStroke( true );
1656  m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) );
1658  m_gal->DrawPolyline( pts2 );
1659 
1660  draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer );
1661 }
1662 
1663 
1664 void SCH_PAINTER::draw( const SCH_SHEET *aSheet, int aLayer )
1665 {
1666  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1667 
1668  if( aLayer == LAYER_HIERLABEL || aLayer == LAYER_SELECTION_SHADOWS )
1669  {
1670  for( SCH_SHEET_PIN* sheetPin : aSheet->GetPins() )
1671  {
1672  if( drawingShadows && !aSheet->IsSelected() && !sheetPin->IsSelected() )
1673  continue;
1674 
1675  if( drawingShadows && aSheet->IsSelected()
1677  {
1678  break;
1679  }
1680 
1681  int width = std::max( aSheet->GetPenWidth(), m_schSettings.GetDefaultPenWidth() );
1682  wxPoint initial_pos = sheetPin->GetTextPos();
1683  wxPoint offset_pos = initial_pos;
1684 
1685  // For aesthetic reasons, the SHEET_PIN is drawn with a small offset of width / 2
1686  switch( sheetPin->GetEdge() )
1687  {
1688  case SHEET_TOP_SIDE: offset_pos.y += KiROUND( width / 2.0 ); break;
1689  case SHEET_BOTTOM_SIDE: offset_pos.y -= KiROUND( width / 2.0 ); break;
1690  case SHEET_RIGHT_SIDE: offset_pos.x -= KiROUND( width / 2.0 ); break;
1691  case SHEET_LEFT_SIDE: offset_pos.x += KiROUND( width / 2.0 ); break;
1692  default: break;
1693  }
1694 
1695  sheetPin->SetTextPos( offset_pos );
1696  draw( static_cast<SCH_HIERLABEL*>( sheetPin ), aLayer );
1697  m_gal->DrawLine( offset_pos, initial_pos );
1698  sheetPin->SetTextPos( initial_pos );
1699  }
1700  }
1701 
1702  VECTOR2D pos = aSheet->GetPosition();
1703  VECTOR2D size = aSheet->GetSize();
1704 
1705  if( aLayer == LAYER_SHEET_BACKGROUND )
1706  {
1708  m_gal->SetIsFill( true );
1709  m_gal->SetIsStroke( false );
1710 
1711  m_gal->DrawRectangle( pos, pos + size );
1712  }
1713 
1714  if( aLayer == LAYER_SHEET || aLayer == LAYER_SELECTION_SHADOWS )
1715  {
1716  m_gal->SetStrokeColor( getRenderColor( aSheet, LAYER_SHEET, drawingShadows ) );
1717  m_gal->SetIsStroke( true );
1718  m_gal->SetLineWidth( getLineWidth( aSheet, drawingShadows ) );
1719  m_gal->SetIsFill( false );
1720 
1721  m_gal->DrawRectangle( pos, pos + size );
1722 
1723  if( drawingShadows && !eeconfig()->m_Selection.draw_selected_children && aSheet->IsSelected() )
1724  return;
1725 
1726  for( const SCH_FIELD& field : aSheet->GetFields() )
1727  draw( &field, aLayer );
1728  }
1729 }
1730 
1731 
1732 void SCH_PAINTER::draw( const SCH_NO_CONNECT *aNC, int aLayer )
1733 {
1734  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1735 
1736  if( drawingShadows && !aNC->IsSelected() )
1737  return;
1738 
1739  m_gal->SetIsStroke( true );
1740  m_gal->SetLineWidth( getLineWidth( aNC, drawingShadows ) );
1741  m_gal->SetStrokeColor( getRenderColor( aNC, LAYER_NOCONNECT, drawingShadows ) );
1742  m_gal->SetIsFill( false );
1743 
1744  VECTOR2D p = aNC->GetPosition();
1745  int delta = std::max( aNC->GetSize(), m_schSettings.GetDefaultPenWidth() * 3 ) / 2;
1746 
1747  m_gal->DrawLine( p + VECTOR2D( -delta, -delta ), p + VECTOR2D( delta, delta ) );
1748  m_gal->DrawLine( p + VECTOR2D( -delta, delta ), p + VECTOR2D( delta, -delta ) );
1749 }
1750 
1751 
1752 void SCH_PAINTER::draw( const SCH_BUS_ENTRY_BASE *aEntry, int aLayer )
1753 {
1754  SCH_LINE line;
1755  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1756 
1757  if( drawingShadows && !aEntry->IsSelected() )
1758  return;
1759 
1760  line.SetLayer( aEntry->Type() == SCH_BUS_WIRE_ENTRY_T ? LAYER_WIRE : LAYER_BUS );
1761 
1762  if( aEntry->IsSelected() )
1763  line.SetSelected();
1764  else if( aEntry->IsBrightened() )
1765  line.SetBrightened();
1766 
1767  line.SetStartPoint( aEntry->GetPosition() );
1768  line.SetEndPoint( aEntry->GetEnd() );
1769  line.SetStroke( aEntry->GetStroke() );
1770 
1771  COLOR4D color = getRenderColor( aEntry, LAYER_WIRE, drawingShadows );
1772 
1773  if( aEntry->Type() == SCH_BUS_BUS_ENTRY_T )
1774  color = getRenderColor( aEntry, LAYER_BUS, drawingShadows );
1775 
1776  line.SetLineColor( color );
1777  line.SetLineStyle( aEntry->GetStrokeStyle() );
1778 
1779  draw( &line, aLayer );
1780 
1781  m_gal->SetIsFill( false );
1782  m_gal->SetIsStroke( true );
1783  m_gal->SetLineWidth( drawingShadows ? getShadowWidth() : 1.0F );
1784 
1785  if( aEntry->IsDanglingStart() )
1786  m_gal->DrawCircle( aEntry->GetPosition(),
1787  aEntry->GetPenWidth() + ( TARGET_BUSENTRY_RADIUS / 2 ) );
1788 
1789  if( aEntry->IsDanglingEnd() )
1790  m_gal->DrawCircle( aEntry->GetEnd(),
1791  aEntry->GetPenWidth() + ( TARGET_BUSENTRY_RADIUS / 2 ) );
1792 }
1793 
1794 
1795 void SCH_PAINTER::draw( const SCH_BITMAP *aBitmap, int aLayer )
1796 {
1797  m_gal->Save();
1798  m_gal->Translate( aBitmap->GetPosition() );
1799 
1800  // When the image scale factor is not 1.0, we need to modify the actual as the image scale
1801  // factor is similar to a local zoom
1802  double img_scale = aBitmap->GetImageScale();
1803 
1804  if( img_scale != 1.0 )
1805  m_gal->Scale( VECTOR2D( img_scale, img_scale ) );
1806 
1807  if( aLayer == LAYER_DRAW_BITMAPS )
1808  {
1809  m_gal->DrawBitmap( *aBitmap->GetImage() );
1810  }
1811 
1812  if( aLayer == LAYER_SELECTION_SHADOWS )
1813  {
1814  if( aBitmap->IsSelected() || aBitmap->IsBrightened() )
1815  {
1816  COLOR4D color = getRenderColor( aBitmap, LAYER_DRAW_BITMAPS, true );
1817  m_gal->SetIsStroke( true );
1820  m_gal->SetIsFill( false );
1821 
1822  // Draws a bounding box.
1823  VECTOR2D bm_size( aBitmap->GetSize() );
1824  // bm_size is the actual image size in UI.
1825  // but m_gal scale was previously set to img_scale
1826  // so recalculate size relative to this image size.
1827  bm_size.x /= img_scale;
1828  bm_size.y /= img_scale;
1829  VECTOR2D origin( -bm_size.x / 2.0, -bm_size.y / 2.0 );
1830  VECTOR2D end = origin + bm_size;
1831 
1832  m_gal->DrawRectangle( origin, end );
1833  }
1834  }
1835 
1836  m_gal->Restore();
1837 }
1838 
1839 
1840 void SCH_PAINTER::draw( const SCH_MARKER *aMarker, int aLayer )
1841 {
1842  bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1843 
1844  if( drawingShadows && !aMarker->IsSelected() )
1845  return;
1846 
1847  COLOR4D color = getRenderColor( aMarker, aMarker->GetColorLayer(), drawingShadows );
1848 
1849  m_gal->Save();
1850  m_gal->Translate( aMarker->GetPosition() );
1851  m_gal->SetIsFill( !drawingShadows );
1852  m_gal->SetFillColor( color );
1853  m_gal->SetIsStroke( drawingShadows );
1854  m_gal->SetLineWidth( getLineWidth( aMarker, drawingShadows ) );
1856 
1857  SHAPE_LINE_CHAIN polygon;
1858  aMarker->ShapeToPolygon( polygon );
1859 
1860  m_gal->DrawPolygon( polygon );
1861  m_gal->Restore();
1862 }
1863 
1864 
1865 }; // 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.
bool IsDangling() const override
Definition: sch_text.h:303
SCH_PAINTER(GAL *aGal)
CITER next(CITER it)
Definition: ptree.cpp:126
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
#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:50
void draw(const LIB_RECTANGLE *aRect, int aLayer)
virtual void DrawPolyline(const std::deque< VECTOR2D > &aPointList)
Draw a polyline.
bool IsBold() const
Definition: eda_text.h:190
virtual int GetPenWidth() const =0
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:51
SCHEMATIC * m_schematic
Definition: sch_painter.h:203
float GetLineWidth() const
Get the line width.
#define TARGET_BUSENTRY_RADIUS
Definition: sch_bus_entry.h:36
void drawDanglingSymbol(const wxPoint &aPos, int aWidth, bool aDrawingShadows)
virtual void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a rectangle.
Plot settings, and plotting engines (PostScript, Gerber, HPGL and DXF)
EDA_TEXT_VJUSTIFY_T GetVertJustify() const
Definition: eda_text.h:206
bool IsMirrored() const
Definition: eda_text.h:196
int GetPinNameOffset()
Definition: lib_symbol.h:554
SCH_LAYER_ID GetColorLayer() const
Definition: sch_marker.cpp:122
int GetOrientation()
Get the display symbol orientation.
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:175
wxPoint GetStartPoint() const
Definition: sch_line.h:94
bool IsWire() const
Returns true if the line is a wire.
Definition: sch_line.cpp:915
bool IsSelected() const
Definition: eda_item.h:172
wxPoint GetEnd() const
Definition: lib_rectangle.h:89
const MATRIX3x3D & GetScreenWorldMatrix() const
Get the screen <-> world transformation matrix.
void drawPinDanglingSymbol(const VECTOR2I &aPos, bool aDrawingShadows)
const Vec GetEnd() const
Definition: box2.h:195
wxPoint GetPosition() const override
Definition: lib_field.h:180
wxPoint GetPosition() const override
to handle and draw images bitmaps
COLOR4D m_layerColors[LAYER_ID_COUNT]
Define a symbol library graphical text item.
Definition: lib_text.h:40
int GetOrientation() const
Definition: lib_pin.h:125
virtual STROKE_PARAMS GetStroke() const override
Definition: sch_bus_entry.h:69
static constexpr double IU_PER_MM
Mock up a conversion function.
LIB_PART * GetParent() const
Definition: lib_item.h:149
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:56
wxPoint GetPosition() const override
Definition: sch_marker.h:104
void GetPoly(std::vector< wxPoint > &aOutput, int aMinSegLen=0)
Convert a Bezier curve to a polygon.
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: lib_pin.h:129
virtual void SetTextAttributes(const EDA_TEXT *aText)
Loads attributes of the given text (bold/italic/underline/mirrored and so on).
bool IsVisible() const
Definition: eda_text.h:193
GRAPHIC_PINSHAPE GetShape() const
Definition: lib_pin.h:128
virtual void DrawArc(const VECTOR2D &aCenterPoint, double aRadius, double aStartAngle, double aEndAngle)
Draw an arc.
bool IsMoving() const
Definition: eda_item.h:169
int color
Definition: DXF_plotter.cpp:60
Field object used in symbol libraries.
Definition: lib_field.h:59
float getTextThickness(const SCH_TEXT *aItem, bool aDrawingShadows) const
bool setDeviceColors(const LIB_ITEM *aItem, int aLayer)
bool isUnitAndConversionShown(const LIB_ITEM *aItem) const
void SetBrightened()
Definition: eda_item.h:179
virtual void DrawBitmap(const BITMAP_BASE &aBitmap)
Draw a bitmap image.
bool IsHypertext() const override
Allows items to support hypertext actions when hovered/clicked.
Definition: sch_field.h:95
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
double GetTextAngle() const
Definition: eda_text.h:181
wxPoint GetPosition() const override
Definition: lib_circle.h:72
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:300
void CreateGraphicShape(const RENDER_SETTINGS *aRenderSettings, std::vector< wxPoint > &aPoints, const wxPoint &aPos) override
Calculate the graphic shape (a polygon) associated to the text.
Definition: sch_text.cpp:1218
void CalcRadiusAngles()
Calculate the radius and angle of an arc using the start, end, and center points.
Definition: lib_arc.cpp:537
int GetDiameter() const
#define DASH_MARK_LEN(aLineWidth)
KIGFX::COLOR4D GetBorderColor() const
Definition: sch_sheet.h:293
bool IsBrightened() const
Definition: eda_item.h:175
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 IS_ROLLOVER
Rollover active. Used for hyperlink highlighting.
Definition: eda_item.h:129
#define DEFAULT_JUNCTION_DIAM
The default bus and wire enty size in mils.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:244
Definition: lib_pin.h:50
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: lib_field.cpp:313
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape.
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:81
wxPoint GetPosition() const override
Definition: sch_bitmap.h:140
virtual void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a line.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
void RevertYAxis()
Mirror the rectangle from the X axis (negate Y pos and size).
Definition: eda_rect.h:203
float getShadowWidth() const
virtual wxPoint GetSchematicTextOffset(const RENDER_SETTINGS *aSettings) const
Definition: sch_text.cpp:176
EESCHEMA_SETTINGS * eeconfig()
bool IsDangling() const override
Definition: sch_pin.h:96
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
Definition: matrix3x3.h:269
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.
#define SET_DC(i)
wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: sch_field.cpp:104
bool IsVoid() const
Function IsVoid returns true if the field is either empty or holds "~".
Definition: sch_field.cpp:321
void fillIfSelection(int aLayer)
bool IsDanglingEnd() const
Definition: sch_bus_entry.h:48
bool IsDragging() const
Definition: eda_item.h:170
static constexpr int VIEW_MAX_LAYERS
maximum number of layers that may be shown
Definition: view.h:700
GAL * m_gal
Instance of graphic abstraction layer that gives an interface to call commands used to draw (eg.
Definition: painter.h:101
The base class for drawable items used by schematic library components.
Definition: lib_item.h:62
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:234
int GetEffectiveTextPenWidth(int aDefaultWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultWidth.
Definition: eda_text.cpp:157
virtual void SetLineWidth(float aLineWidth)
Set the line width.
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populates a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:717
void SetEndPoint(const wxPoint &aPosition)
Definition: sch_line.h:98
KIGFX::COLOR4D GetBackgroundColor() const
Definition: sch_sheet.h:296
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:131
Base class for a bus or wire entry.
Definition: sch_bus_entry.h:42
void AddDrawItem(LIB_ITEM *aItem)
Add a new draw aItem to the draw object list.
Definition: lib_symbol.cpp:648
bool IsItalic() const
Definition: eda_text.h:187
const std::vector< wxPoint > & GetPolyPoints() const
Definition: lib_polyline.h:60
PLOT_DASH_TYPE GetStrokeStyle() const
void GetPins(LIB_PINS &aList, int aUnit=0, int aConvert=0)
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:686
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:270
void CreateGraphicShape(const RENDER_SETTINGS *aSettings, std::vector< wxPoint > &aPoints, const wxPoint &Pos) override
Calculate the graphic shape (a polygon) associated to the text.
Definition: sch_text.cpp:1426
bool ShowPinNames()
Definition: lib_symbol.h:562
int GetSecondRadiusAngle() const
Definition: lib_arc.h:109
const wxPoint GetEnd() const
Definition: eda_rect.h:108
void SetFontBold(const bool aBold)
Set bold property of current font.
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:338
FILL_TYPE GetFillMode() const
Definition: lib_item.h:268
int GetUnit() const
Definition: lib_item.h:262
int GetUnit() const
Definition: sch_symbol.h:237
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:238
bool ShowPinNumbers()
Definition: lib_symbol.h:570
void SetType(ELECTRICAL_PINTYPE aType)
Definition: lib_pin.h:135
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)
Function Clamp_Text_PenSize Don't allow text to become cluttered up in its own fatness.
Definition: gr_text.cpp:69
Auxiliary items (guides, rule, etc)
bool IsDanglingStart() const
Definition: sch_bus_entry.h:47
void SetEnd(const wxPoint &aPoint)
Definition: lib_arc.h:115
void SetFlags(STATUS_FLAGS aMask)
Definition: eda_item.h:202
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:205
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:121
VECTOR2< double > VECTOR2D
Definition: vector2d.h:622
void SetSelected()
Definition: eda_item.h:178
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
BITMAP_BASE * GetImage() const
Definition: sch_bitmap.h:59
#define DANGLING_SYMBOL_SIZE
wxPoint GetPosition() const override
Definition: sch_junction.h:96
wxString const GetElectricalTypeName() const
Definition: lib_pin.h:142
const wxString & GetName() const
Definition: lib_pin.h:156
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:466
bool IsEndDangling() const
Definition: sch_line.h:214
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:245
int GetPenWidth() const override
Definition: sch_sheet.cpp:510
const wxPoint GetPosition() const
Definition: eda_rect.h:107
void SetStartPoint(const wxPoint &aPosition)
Definition: sch_line.h:95
void SetLayer(SCH_LAYER_ID aLayer)
Set the layer this item is on.
Definition: sch_item.h:294
bool IsResized() const
Definition: eda_item.h:174
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
int GetSize() const
wxPoint GetStart() const
Definition: lib_arc.h:111
float GetDanglineSymbolThickness() const
Definition: sch_painter.h:101
#define DOT_MARK_LEN(aLineWidth)
Define a library symbol object.
Definition: lib_symbol.h:93
void strokeText(const wxString &aText, const VECTOR2D &aPosition, double aRotationAngle)
EDA_ITEM * GetParent() const
Definition: eda_item.h:164
const std::vector< wxPoint > & GetPoints() const
Definition: lib_bezier.h:68
void triLine(const VECTOR2D &a, const VECTOR2D &b, const VECTOR2D &c)
a few functions useful in geometry calculations.
Text appears outside the dimension line (default)
#define F(x, y, z)
Definition: md5_hash.cpp:15
LABEL_SPIN_STYLE GetLabelSpinStyle() const
Definition: sch_text.h:233
void SetLineColor(const COLOR4D &aColor)
Definition: sch_line.cpp:188
bool IsVisible() const
Definition: lib_pin.h:147
GRAPHIC_PINSHAPE GetShape() const
Definition: sch_pin.cpp:97
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet.h:85
void SetTextMirrored(const bool aMirrored)
Set a mirrored property of text.
int GetRadius() const
Definition: lib_circle.h:88
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_text.cpp:463
std::unique_ptr< LIB_PART > & GetPartRef()
Definition: sch_symbol.h:206
int GetNameTextSize() const
Definition: lib_pin.h:174
std::unique_ptr< LIB_PART > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:327
void SetVerticalJustify(const EDA_TEXT_VJUSTIFY_T aVerticalJustify)
Set the vertical justify for text drawing.
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:508
wxPoint GetPosition() const override
Definition: sch_sheet.h:572
void SetFontItalic(bool aItalic)
Set italic property of current font.
int GetConvert() const
Definition: lib_item.h:265
#define DEFAULT_LINE_THICKNESS
The default wire width in mils. (can be changed in preference menu)
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:42
virtual int GetPenWidth() const
Definition: sch_item.h:304
virtual void Scale(const VECTOR2D &aScale)
Scale the context.
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:219
PLOT_DASH_TYPE
Dashed line types.
Definition: plotter.h:104
#define DEFAULT_BUS_THICKNESS
The default noconnect size in mils.
int GetRadius() const
Definition: lib_arc.h:103
wxPoint GetPosition() const override
Definition: lib_pin.h:258
static void orientPart(LIB_PART *part, int orientation)
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:287
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:365
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:184
void Normalize()
Ensures that the height ant width are positive.
Definition: eda_rect.cpp:35
SCH_FIELD * GetIntersheetRefs()
Definition: sch_text.h:442
int externalPinDecoSize(const LIB_PIN &aPin)
const wxString & GetNumber() const
Definition: lib_pin.h:165
ELECTRICAL_PINTYPE GetType() const
Definition: lib_pin.h:134
void LoadColors(const COLOR_SETTINGS *aSettings) override
Definition: sch_painter.cpp:92
COLOR4D GetColor(int aLayer) const
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
Bezier curves to polygon converter.
Definition: bezier_curves.h:36
void SetGlyphSize(const VECTOR2D aSize)
Set the font glyph size.
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: sch_line.h:129
bool IsForceVisible() const
Definition: eda_item.h:255
int GetNumberTextSize() const
Definition: lib_pin.h:177
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:157
void SetFontUnderlined(bool aUnderlined)
PLOT_DASH_TYPE GetEffectiveLineStyle() const
Definition: sch_line.cpp:256
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.
const EDA_RECT GetBoundingBox() const override
Definition: lib_text.cpp:356
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_field.cpp:262
int GetLength() const
Definition: lib_pin.h:131
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
SHAPE_LINE_CHAIN.
wxSize GetSize() const
Definition: sch_sheet.h:287
int internalPinDecoSize(const LIB_PIN &aPin)
#define HANDLE_ITEM(type_id, type_name)
#define DEFAULT_WIRE_THICKNESS
The default bus width in mils. (can be changed in preference menu)
ELECTRICAL_PINTYPE GetType() const
Definition: sch_pin.cpp:88
bool IsStartDangling() const
Definition: sch_line.h:213
double GetImageScale() const
Definition: sch_bitmap.h:71
bool IsAlias() const
Definition: lib_symbol.h:168
wxPoint GetEnd() const
Definition: lib_arc.h:114
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:364
Schematic symbol object.
Definition: sch_symbol.h:79
wxPoint GetPosition() const override
Definition: sch_symbol.h:666
#define IU_PER_MILS
Definition: plotter.cpp:137
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:68
#define DASH_GAP_LEN(aLineWidth)
#define TARGET_PIN_RADIUS
Definition: lib_pin.h:38
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:149
wxPoint Centre() const
Definition: eda_rect.h:60
COLOR4D getRenderColor(const EDA_ITEM *aItem, int aLayer, bool aDrawingShadows) const
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:203
int GetDefaultPenWidth() const
Color settings are a bit different than most of the settings objects in that there can be more than o...
const wxPoint & GetTextPos() const
Definition: eda_text.h:254
int GetFirstRadiusAngle() const
Definition: lib_arc.h:106
void SetStart(const wxPoint &aPoint)
Definition: lib_arc.h:112
#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
#define IS_DANGLING
indicates a pin is dangling
Definition: eda_item.h:136
double square(double x)
int GetConvert() const
Definition: sch_symbol.h:265
#define TEXT_ANGLE_VERT
Definition: eda_text.h:51
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:81
Definition for part library class.
const Vec & GetOrigin() const
Definition: box2.h:193
float getLineWidth(const LIB_ITEM *aItem, bool aDrawingShadows) const
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:141
void SetDefaultPenWidth(int aWidth)
not connected (must be left open)
bool IsBus() const
wxPoint GetParentPosition() const
Definition: sch_field.cpp:687
STATUS_FLAGS GetFlags() const
Definition: eda_item.h:204
virtual void Translate(const VECTOR2D &aTranslation)
Translate the context.
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
#define PIN_TEXT_MARGIN
static constexpr int Millimeter2iu(double mm)
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:196
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:133
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Definition: sch_symbol.cpp:545
wxPoint GetPosition() const override
Definition: lib_rectangle.h:76
wxString GetName() const
Definition: sch_pin.cpp:79
bool HasFlag(STATUS_FLAGS aFlag) const
Definition: eda_item.h:205
SCH_RENDER_SETTINGS m_schSettings
Definition: sch_painter.h:201
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:162
Abstract interface for drawing on a 2D-surface.
wxPoint GetEnd() const
Define a bezier curve graphic body item.
Definition: lib_bezier.h:34
wxPoint GetPosition() const override
Definition: lib_arc.h:90
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:98
wxPoint GetPosition() const override
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
Definition: sch_symbol.cpp:830
wxPoint GetEndPoint() const
Definition: sch_line.h:97