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-2022 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 <symbol_library.h>
31#include <connection_graph.h>
35#include <gr_text.h>
36#include <lib_shape.h>
37#include <lib_field.h>
38#include <lib_item.h>
39#include <lib_pin.h>
40#include <lib_text.h>
41#include <lib_textbox.h>
42#include <math/util.h>
43#include <sch_bitmap.h>
44#include <sch_bus_entry.h>
45#include <sch_symbol.h>
46#include <sch_edit_frame.h>
47#include <sch_field.h>
48#include <sch_junction.h>
49#include <sch_line.h>
50#include <sch_marker.h>
51#include <sch_no_connect.h>
52#include <sch_sheet.h>
53#include <sch_sheet_pin.h>
54#include <sch_text.h>
55#include <sch_textbox.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 <stroke_params.h>
64#include "sch_painter.h"
65#include "sch_shape.h"
66
67
68namespace KIGFX
69{
70
72{
73 return dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
74}
75
76
77std::vector<KICAD_T> SCH_PAINTER::g_ScaledSelectionTypes = {
90};
91
92
94 m_IsSymbolEditor( false ),
95 m_ShowUnit( 0 ),
96 m_ShowConvert( 0 ),
97 m_ShowPinsElectricalType( true ),
98 m_ShowPinNumbers( false ),
99 m_ShowDisabled( false ),
100 m_ShowGraphicsDisabled( false ),
101 m_OverrideItemColors( false ),
102 m_LabelSizeRatio( DEFAULT_LABEL_SIZE_RATIO ),
103 m_TextOffsetRatio( DEFAULT_TEXT_OFFSET_RATIO ),
104 m_PinSymbolSize( DEFAULT_TEXT_SIZE * schIUScale.IU_PER_MILS / 2 )
105{
107 SetDashLengthRatio( 12 ); // From ISO 128-2
108 SetGapLengthRatio( 3 ); // From ISO 128-2
109
111}
112
113
115{
116 for( int layer = SCH_LAYER_ID_START; layer < SCH_LAYER_ID_END; layer ++)
117 m_layerColors[ layer ] = aSettings->GetColor( layer );
118
119 for( int layer = GAL_LAYER_ID_START; layer < GAL_LAYER_ID_END; layer ++)
120 m_layerColors[ layer ] = aSettings->GetColor( layer );
121
123
125
127}
128
129
130COLOR4D SCH_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) const
131{
132 return m_layerColors[ aLayer ];
133}
134
135
137{
139}
140
141
156{
157 static LIB_SYMBOL* symbol;
158
159 if( !symbol )
160 {
161 symbol = new LIB_SYMBOL( wxEmptyString );
162
163 LIB_SHAPE* square = new LIB_SHAPE( symbol, SHAPE_T::RECT );
164
165 square->MoveTo( VECTOR2I( schIUScale.MilsToIU( -200 ), schIUScale.MilsToIU( 200 ) ) );
166 square->SetEnd( VECTOR2I( schIUScale.MilsToIU( 200 ), schIUScale.MilsToIU( -200 ) ) );
167
168 LIB_TEXT* text = new LIB_TEXT( symbol );
169
170 text->SetTextSize( wxSize( schIUScale.MilsToIU( 150 ), schIUScale.MilsToIU( 150 ) ) );
171 text->SetText( wxString( wxT( "??" ) ) );
172
173 symbol->AddDrawItem( square );
174 symbol->AddDrawItem( text );
175 }
176
177 return symbol;
178}
179
180
182 KIGFX::PAINTER( aGal ),
183 m_schematic( nullptr )
184{ }
185
186bool SCH_PAINTER::Draw( const VIEW_ITEM *aItem, int aLayer )
187{
188 const EDA_ITEM* item = dynamic_cast<const EDA_ITEM*>( aItem );
189
190 if( !item )
191 return false;
192
193 draw( item, aLayer, false );
194
195 return false;
196}
197
198void SCH_PAINTER::draw( const EDA_ITEM *aItem, int aLayer, bool aDimmed )
199{
200
201#ifdef CONNECTIVITY_DEBUG
202
203 auto sch_item = dynamic_cast<const SCH_ITEM*>( aItem );
204 auto conn = sch_item ? sch_item->Connection( *g_CurrentSheet ) : nullptr;
205
206 if( conn )
207 {
208 auto pos = aItem->GetBoundingBox().Centre();
209 auto label = conn->Name( true );
210
214 m_gal->SetLineWidth( Mils2ui( 2 ) );
215 m_gal->SetGlyphSize( VECTOR2D( Mils2ui( 20 ), Mils2ui( 20 ) ) );
216 m_gal->StrokeText( conn->Name( true ), pos, 0.0, 0 );
217 }
218
219#endif
220
222 {
223 BOX2I box = aItem->GetBoundingBox();
224
225 if( aItem->Type() == SCH_SYMBOL_T )
226 box = static_cast<const SCH_SYMBOL*>( aItem )->GetBodyBoundingBox();
227
228 m_gal->SetIsFill( false );
229 m_gal->SetIsStroke( true );
230 m_gal->SetStrokeColor( aItem->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 )
231 : COLOR4D( 0.2, 0.2, 0.2, 1 ) );
233 m_gal->DrawRectangle( box.GetOrigin(), box.GetEnd() );
234 }
235
236 switch( aItem->Type() )
237 {
238 case LIB_SYMBOL_T:
239 draw( static_cast<const LIB_SYMBOL*>( aItem ), aLayer );
240 break;
241 case LIB_SHAPE_T:
242 draw( static_cast<const LIB_SHAPE*>( aItem ), aLayer, aDimmed );
243 break;
244 case LIB_PIN_T:
245 draw( static_cast<const LIB_PIN*>( aItem ), aLayer, aDimmed );
246 break;
247 case LIB_FIELD_T:
248 draw( static_cast<const LIB_FIELD*>( aItem ), aLayer, aDimmed );
249 break;
250 case LIB_TEXT_T:
251 draw( static_cast<const LIB_TEXT*>( aItem ), aLayer, aDimmed );
252 break;
253 case LIB_TEXTBOX_T:
254 draw( static_cast<const LIB_TEXTBOX*>( aItem ), aLayer, aDimmed );
255 break;
256 case SCH_SYMBOL_T:
257 draw( static_cast<const SCH_SYMBOL*>( aItem ), aLayer );
258 break;
259 case SCH_JUNCTION_T:
260 draw( static_cast<const SCH_JUNCTION*>( aItem ), aLayer );
261 break;
262 case SCH_LINE_T:
263 draw( static_cast<const SCH_LINE*>( aItem ), aLayer );
264 break;
265 case SCH_SHAPE_T:
266 draw( static_cast<const SCH_SHAPE*>( aItem ), aLayer );
267 break;
268 case SCH_TEXT_T:
269 draw( static_cast<const SCH_TEXT*>( aItem ), aLayer );
270 break;
271 case SCH_TEXTBOX_T:
272 draw( static_cast<const SCH_TEXTBOX*>( aItem ), aLayer );
273 break;
274 case SCH_LABEL_T:
275 draw( static_cast<const SCH_LABEL*>( aItem ), aLayer );
276 break;
278 draw( static_cast<const SCH_DIRECTIVE_LABEL*>( aItem ), aLayer );
279 break;
280 case SCH_FIELD_T:
281 draw( static_cast<const SCH_FIELD*>( aItem ), aLayer, aDimmed );
282 break;
283 case SCH_HIER_LABEL_T:
284 draw( static_cast<const SCH_HIERLABEL*>( aItem ), aLayer );
285 break;
287 draw( static_cast<const SCH_GLOBALLABEL*>( aItem ), aLayer );
288 break;
289 case SCH_SHEET_T:
290 draw( static_cast<const SCH_SHEET*>( aItem ), aLayer );
291 break;
292 case SCH_SHEET_PIN_T:
293 draw( static_cast<const SCH_HIERLABEL*>( aItem ), aLayer );
294 break;
295 case SCH_NO_CONNECT_T:
296 draw( static_cast<const SCH_NO_CONNECT*>( aItem ), aLayer );
297 break;
299 draw( static_cast<const SCH_BUS_ENTRY_BASE*>( aItem ), aLayer );
300 break;
302 draw( static_cast<const SCH_BUS_ENTRY_BASE*>( aItem ), aLayer );
303 break;
304 case SCH_BITMAP_T:
305 draw( static_cast<const SCH_BITMAP*>( aItem ), aLayer );
306 break;
307 case SCH_MARKER_T:
308 draw( static_cast<const SCH_MARKER*>( aItem ), aLayer );
309 break;
310
311 default: return;
312 }
313}
314
315
317{
318 // TODO: it would be nice to have a more definitive test for this, but we've currently got
319 // no access to the VIEW_GROUP to see if it's cached or not.
320 return aItem->IsSelected();
321}
322
323
325{
326 if( m_schSettings.m_ShowUnit // showing a specific unit
327 && aItem->GetUnit() // item is unit-specific
328 && aItem->GetUnit() != m_schSettings.m_ShowUnit )
329 {
330 return false;
331 }
332
333 if( m_schSettings.m_ShowConvert // showing a specific conversion
334 && aItem->GetConvert() // item is conversion-specific
335 && aItem->GetConvert() != m_schSettings.m_ShowConvert )
336 {
337 return false;
338 }
339
340 return true;
341}
342
343
344float SCH_PAINTER::getShadowWidth( bool aForHighlight ) const
345{
346 const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
347
348 int milsWidth = aForHighlight ? eeconfig()->m_Selection.highlight_thickness
350
351 // For best visuals the selection width must be a cross between the zoom level and the
352 // default line width.
353 return (float) std::fabs( matrix.GetScale().x * milsWidth ) + schIUScale.MilsToIU( milsWidth );
354}
355
356
357COLOR4D SCH_PAINTER::getRenderColor( const EDA_ITEM *aItem, int aLayer, bool aDrawingShadows,
358 bool aDimmed ) const
359{
361
362 if( aItem->Type() == SCH_LINE_T )
363 {
364 color = static_cast<const SCH_LINE*>( aItem )->GetLineColor();
365 }
366 else if( aItem->Type() == SCH_BUS_WIRE_ENTRY_T )
367 {
368 color = static_cast<const SCH_BUS_WIRE_ENTRY*>( aItem )->GetBusEntryColor();
369 }
370 else if( aItem->Type() == SCH_JUNCTION_T )
371 {
372 color = static_cast<const SCH_JUNCTION*>( aItem )->GetJunctionColor();
373 }
375 {
376 if( aItem->Type() == SCH_SHEET_T )
377 {
378 const SCH_SHEET* sheet = static_cast<const SCH_SHEET*>( aItem );
379
380 if( aLayer == LAYER_SHEET_BACKGROUND )
381 color = sheet->GetBackgroundColor();
382 else
383 color = sheet->GetBorderColor();
384 }
385 else if( aItem->Type() == SCH_SHAPE_T )
386 {
387 const SCH_SHAPE* shape = static_cast<const SCH_SHAPE*>( aItem );
388
389 if( aLayer == LAYER_NOTES_BACKGROUND )
390 color = shape->GetFillColor();
391 else
392 color = shape->GetStroke().GetColor();
393
394 // A filled shape means filled; if they didn't specify a fill colour then use the
395 // border colour.
398 }
399 else if( aItem->Type() == LIB_SHAPE_T )
400 {
401 const LIB_SHAPE* shape = static_cast<const LIB_SHAPE*>( aItem );
402
403 if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_NOTES_BACKGROUND )
404 color = shape->GetFillColor();
405 else
406 color = shape->GetStroke().GetColor();
407 }
408 else if( aItem->IsType( { SCH_LABEL_LOCATE_ANY_T } ) )
409 {
410 color = static_cast<const SCH_LABEL_BASE*>( aItem )->GetLabelColor();
411 }
412 else if( aItem->Type() == SCH_FIELD_T )
413 {
414 color = static_cast<const SCH_FIELD*>( aItem )->GetFieldColor();
415 }
416 else if( aItem->Type() == SCH_TEXTBOX_T )
417 {
418 const SCH_TEXTBOX* textBox = static_cast<const SCH_TEXTBOX*>( aItem );
419
420 if( aLayer == LAYER_NOTES_BACKGROUND )
421 color = textBox->GetFillColor();
422 else
423 color = textBox->GetTextColor();
424 }
425 else if( aItem->Type() == LIB_TEXTBOX_T )
426 {
427 const LIB_TEXTBOX* textBox = static_cast<const LIB_TEXTBOX*>( aItem );
428
429 if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_NOTES_BACKGROUND )
430 color = textBox->GetFillColor();
431 else
432 color = textBox->GetTextColor();
433 }
434 else if( const EDA_TEXT* otherTextItem = dynamic_cast<const EDA_TEXT*>( aItem ) )
435 {
436 color = otherTextItem->GetTextColor();
437 }
438 }
439
441 color = m_schSettings.GetLayerColor( aLayer );
442
443 if( aItem->IsBrightened() ) // Selection disambiguation, net highlighting, etc.
444 {
445 color = m_schSettings.GetLayerColor( LAYER_BRIGHTENED );
446
447 if( aDrawingShadows )
448 {
449 if( aItem->IsSelected() )
450 color = m_schSettings.GetLayerColor( LAYER_SELECTION_SHADOWS );
451 else
452 color = color.WithAlpha( 0.15 );
453 }
454 else if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_SHEET_BACKGROUND )
455 {
456 color = color.WithAlpha( 0.2 );
457 }
458 }
459 else if( aItem->IsSelected() && aDrawingShadows )
460 {
461 if( aDrawingShadows )
462 color = m_schSettings.GetLayerColor( LAYER_SELECTION_SHADOWS );
463 }
464
465 if( m_schSettings.m_ShowDisabled
466 || ( m_schSettings.m_ShowGraphicsDisabled && aItem->Type() != LIB_FIELD_T ) )
467 {
468 color = color.Darken( 0.5f );
469 }
470
471 if( aDimmed )
472 {
473 COLOR4D sheetColour = m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND );
474 color = color.Mix( sheetColour, 0.5f );
475 }
476
477 return color;
478}
479
480
481float SCH_PAINTER::getLineWidth( const EDA_ITEM* aItem, bool aDrawingShadows ) const
482{
483 wxCHECK( aItem, static_cast<float>( schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS ) ) );
484
485 int pen = 0;
486
487 if( dynamic_cast<const LIB_ITEM*>( aItem ) )
488 pen = static_cast<const LIB_ITEM*>( aItem )->GetEffectivePenWidth( &m_schSettings );
489 else if( dynamic_cast<const SCH_ITEM*>( aItem ) )
490 pen = static_cast<const SCH_ITEM*>( aItem )->GetPenWidth();
491 else
492 UNIMPLEMENTED_FOR( aItem->GetClass() );
493
494 float width = pen;
495
496 if( aItem->IsBrightened() || aItem->IsSelected() )
497 {
498 if( aDrawingShadows && aItem->IsType( g_ScaledSelectionTypes ) )
499 width += getShadowWidth( aItem->IsBrightened() );
500 }
501
502 return width;
503}
504
505
506float SCH_PAINTER::getTextThickness( const EDA_ITEM* aItem ) const
507{
508 int pen = m_schSettings.GetDefaultPenWidth();
509
510 switch( aItem->Type() )
511 {
512 case SCH_FIELD_T:
513 pen = static_cast<const SCH_FIELD*>( aItem )->GetEffectiveTextPenWidth( pen );
514 break;
515
516 case SCH_TEXT_T:
517 pen = static_cast<const SCH_TEXT*>( aItem )->GetEffectiveTextPenWidth( pen );
518 break;
519
520 case SCH_LABEL_T:
523 case SCH_HIER_LABEL_T:
524 case SCH_SHEET_PIN_T:
525 pen = static_cast<const SCH_LABEL_BASE*>( aItem )->GetEffectiveTextPenWidth( pen );
526 break;
527
528 case SCH_TEXTBOX_T:
529 pen = static_cast<const SCH_TEXTBOX*>( aItem )->GetEffectiveTextPenWidth( pen );
530 break;
531
532 case LIB_FIELD_T:
533 pen = std::max( pen, static_cast<const LIB_FIELD*>( aItem )->GetEffectiveTextPenWidth() );
534 break;
535
536 case LIB_TEXT_T:
537 pen = std::max( pen, static_cast<const LIB_TEXT*>( aItem )->GetEffectiveTextPenWidth() );
538 break;
539
540 case LIB_TEXTBOX_T:
541 pen = std::max( pen, static_cast<const LIB_TEXTBOX*>( aItem )->GetEffectiveTextPenWidth() );
542 break;
543
544 default:
545 UNIMPLEMENTED_FOR( aItem->GetClass() );
546 }
547
548 return (float) pen;
549}
550
551
552static VECTOR2D mapCoords( const VECTOR2D& aCoord )
553{
554 return VECTOR2D( aCoord.x, -aCoord.y );
555}
556
557
558static bool isFieldsLayer( int aLayer )
559{
560 return aLayer == LAYER_REFERENCEPART
561 || aLayer == LAYER_VALUEPART
562 || aLayer == LAYER_INTERSHEET_REFS
563 || aLayer == LAYER_NETCLASS_REFS
564 || aLayer == LAYER_FIELDS
565 || aLayer == LAYER_SHEETNAME
566 || aLayer == LAYER_SHEETFILENAME
567 || aLayer == LAYER_SHEETFIELDS;
568}
569
570
571void SCH_PAINTER::strokeText( const wxString& aText, const VECTOR2D& aPosition,
572 const TEXT_ATTRIBUTES& aAttrs )
573{
574 KIFONT::FONT* font = aAttrs.m_Font;
575
576 if( !font )
577 {
578 font = KIFONT::FONT::GetFont( eeconfig()->m_Appearance.default_font, aAttrs.m_Bold,
579 aAttrs.m_Italic );
580 }
581
582 m_gal->SetIsFill( font->IsOutline() );
583 m_gal->SetIsStroke( font->IsStroke() );
584
585 font->Draw( m_gal, aText, aPosition, aAttrs );
586}
587
588
589void SCH_PAINTER::bitmapText( const wxString& aText, const VECTOR2D& aPosition,
590 const TEXT_ATTRIBUTES& aAttrs )
591{
592 // Bitmap font has different metrics from the stroke font so we compensate a bit before
593 // stroking
594 m_gal->SetGlyphSize( VECTOR2I( aAttrs.m_Size.x, aAttrs.m_Size.y * 1.05 ) );
595 m_gal->SetLineWidth( aAttrs.m_StrokeWidth * 1.35 );
596
597 m_gal->SetHorizontalJustify( aAttrs.m_Halign );
598 m_gal->SetVerticalJustify( aAttrs.m_Valign );
599
600 m_gal->BitmapText( aText, aPosition, aAttrs.m_Angle );
601}
602
603
604void SCH_PAINTER::boxText( const wxString& aText, const VECTOR2D& aPosition,
605 const TEXT_ATTRIBUTES& aAttrs )
606{
607 KIFONT::FONT* font = aAttrs.m_Font;
608
609 if( !font )
610 {
611 font = KIFONT::FONT::GetFont( eeconfig()->m_Appearance.default_font, aAttrs.m_Bold,
612 aAttrs.m_Italic );
613 }
614
615 VECTOR2I extents = font->StringBoundaryLimits( aText, aAttrs.m_Size, aAttrs.m_StrokeWidth,
616 aAttrs.m_Bold, aAttrs.m_Italic );
617 BOX2I box( aPosition, VECTOR2I( extents.x, aAttrs.m_Size.y ) );
618
619 switch( aAttrs.m_Halign )
620 {
621 case GR_TEXT_H_ALIGN_LEFT: break;
622 case GR_TEXT_H_ALIGN_CENTER: box.SetX( box.GetX() - box.GetWidth() / 2 ); break;
623 case GR_TEXT_H_ALIGN_RIGHT: box.SetX( box.GetX() - box.GetWidth() ); break;
624 }
625
626 switch( aAttrs.m_Valign )
627 {
628 case GR_TEXT_V_ALIGN_TOP: break;
629 case GR_TEXT_V_ALIGN_CENTER: box.SetY( box.GetY() - box.GetHeight() / 2 ); break;
630 case GR_TEXT_V_ALIGN_BOTTOM: box.SetY( box.GetY() - box.GetHeight() ); break;
631 }
632
633 // Give the highlight a bit of margin.
634 box.Inflate( 0, aAttrs.m_StrokeWidth * 2 );
635
636 box.Normalize(); // Make h and v sizes always >= 0
637 box = box.GetBoundingBoxRotated( (VECTOR2I) aPosition, aAttrs.m_Angle );
638 box.RevertYAxis();
639
640 m_gal->SetIsFill( true );
641 m_gal->SetIsStroke( false );
642 m_gal->DrawRectangle( mapCoords( box.GetOrigin() ), mapCoords( box.GetEnd() ) );
643}
644
645
646void SCH_PAINTER::triLine( const VECTOR2D &a, const VECTOR2D &b, const VECTOR2D &c )
647{
648 m_gal->DrawLine( a, b );
649 m_gal->DrawLine( b, c );
650}
651
652
653void SCH_PAINTER::draw( const LIB_SYMBOL *aSymbol, int aLayer, bool aDrawFields, int aUnit,
654 int aConvert, bool aDimmed )
655{
656 if( !aUnit )
657 aUnit = m_schSettings.m_ShowUnit;
658
659 if( !aConvert )
660 aConvert = m_schSettings.m_ShowConvert;
661
662 std::unique_ptr< LIB_SYMBOL > tmpSymbol;
663 const LIB_SYMBOL* drawnSymbol = aSymbol;
664
665 if( aSymbol->IsAlias() )
666 {
667 tmpSymbol = aSymbol->Flatten();
668 drawnSymbol = tmpSymbol.get();
669 }
670
671 for( const LIB_ITEM& item : drawnSymbol->GetDrawItems() )
672 {
673 if( !aDrawFields && item.Type() == LIB_FIELD_T )
674 continue;
675
676 if( aUnit && item.GetUnit() && aUnit != item.GetUnit() )
677 continue;
678
679 if( aConvert && item.GetConvert() && aConvert != item.GetConvert() )
680 continue;
681
682 draw( &item, aLayer, aDimmed );
683 }
684}
685
686
687bool SCH_PAINTER::setDeviceColors( const LIB_ITEM* aItem, int aLayer, bool aDimmed )
688{
689 const EDA_SHAPE* shape = dynamic_cast<const EDA_SHAPE*>( aItem );
690
691 switch( aLayer )
692 {
694 if( aItem->IsBrightened() || aItem->IsSelected() )
695 {
696 m_gal->SetIsFill( false );
697 m_gal->SetIsStroke( true );
698 m_gal->SetLineWidth( getLineWidth( aItem, true ) );
699 m_gal->SetStrokeColor( getRenderColor( aItem, LAYER_DEVICE, true, aDimmed ) );
700 m_gal->SetFillColor( getRenderColor( aItem, LAYER_DEVICE, true, aDimmed ) );
701 return true;
702 }
703
704 return false;
705
708 if( shape )
709 {
711 {
712 return false; // FILLED_SHAPE and FILLED_WITH_COLOR rendered below on
713 // LAYER_NOTES or LAYER_DEVICE
714 }
715
716 m_gal->SetIsFill( true );
717 m_gal->SetFillColor( getRenderColor( aItem, LAYER_DEVICE_BACKGROUND, false, aDimmed ) );
718 m_gal->SetIsStroke( false );
719 return true;
720 }
721
722 return false;
723
724 case LAYER_NOTES:
726 case LAYER_DEVICE:
727 m_gal->SetIsFill( shape && ( shape->GetFillMode() == FILL_T::FILLED_SHAPE
728 || shape->GetFillMode() == FILL_T::FILLED_WITH_COLOR ) );
729
730 if( shape && shape->GetFillMode() == FILL_T::FILLED_SHAPE )
731 {
732 m_gal->SetFillColor( getRenderColor( aItem, LAYER_DEVICE, false, aDimmed ) );
733 }
734 else if( shape && shape->GetFillMode() == FILL_T::FILLED_WITH_COLOR )
735 {
736 COLOR4D fillColour = shape->GetFillColor();
737
738 if( aDimmed )
739 {
740 fillColour = fillColour.Mix(
741 m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ), 0.5f );
742 }
743
744 m_gal->SetFillColor( fillColour );
745 }
746
747 if( aItem->GetPenWidth() >= 0 || !shape || !shape->IsFilled() )
748 {
749 m_gal->SetIsStroke( true );
750 m_gal->SetLineWidth( getLineWidth( aItem, false ) );
751 m_gal->SetStrokeColor( getRenderColor( aItem, aLayer, false, aDimmed ) );
752 }
753 else
754 {
755 m_gal->SetIsStroke( false );
756 }
757
758 return true;
759
760 default:
761 return false;
762 }
763}
764
765
766void SCH_PAINTER::draw( const LIB_SHAPE *aShape, int aLayer, bool aDimmed )
767{
768 if( !isUnitAndConversionShown( aShape ) )
769 return;
770
771 if( aShape->IsPrivate() && !m_schSettings.m_IsSymbolEditor )
772 return;
773
774 if( !setDeviceColors( aShape, aLayer, aDimmed ) )
775 return;
776
777 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
778 PLOT_DASH_TYPE lineStyle = aShape->GetStroke().GetPlotStyle();
779 COLOR4D color = getRenderColor( aShape, aLayer, drawingShadows, aDimmed );
780
781 auto drawShape =
782 [&]( const LIB_SHAPE* shape )
783 {
784 switch( shape->GetShape() )
785 {
786 case SHAPE_T::ARC:
787 {
788 EDA_ANGLE startAngle;
789 EDA_ANGLE endAngle;
790 shape->CalcArcAngles( startAngle, endAngle );
791
792 TRANSFORM().MapAngles( &startAngle, &endAngle );
793
794 m_gal->DrawArc( mapCoords( shape->GetCenter() ), shape->GetRadius(),
795 startAngle, endAngle );
796 }
797 break;
798
799 case SHAPE_T::CIRCLE:
800 m_gal->DrawCircle( mapCoords( shape->GetPosition() ), shape->GetRadius() );
801 break;
802
803 case SHAPE_T::RECT:
804 m_gal->DrawRectangle( mapCoords( shape->GetPosition() ),
805 mapCoords( shape->GetEnd() ) );
806 break;
807
808 case SHAPE_T::POLY:
809 {
810 const SHAPE_LINE_CHAIN poly = shape->GetPolyShape().Outline( 0 );
811 std::deque<VECTOR2D> mappedPts;
812
813 for( const VECTOR2I& pt : poly.CPoints() )
814 mappedPts.push_back( mapCoords( pt ) );
815
816 m_gal->DrawPolygon( mappedPts );
817 }
818 break;
819
820 case SHAPE_T::BEZIER:
821 {
822 std::deque<VECTOR2D> mappedPts;
823
824 for( const VECTOR2I& p : shape->GetBezierPoints() )
825 mappedPts.push_back( mapCoords( p ) );
826
827 m_gal->DrawPolygon( mappedPts );
828 }
829 break;
830
831 default:
832 UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
833 }
834 };
835
836 if( aLayer == LAYER_SELECTION_SHADOWS )
837 {
838 if( eeconfig()->m_Selection.fill_shapes )
839 {
840 // Consider a NAND gate. We have no idea which side of the arc is "inside"
841 // so we can't reliably fill.
842 if( aShape->GetShape() == SHAPE_T::ARC )
843 m_gal->SetIsFill( aShape->IsFilled() );
844 else
845 m_gal->SetIsFill( true );
846 }
847 else
848 {
849 m_gal->SetIsStroke( true );
850 m_gal->SetIsFill( false );
851 m_gal->SetLineWidth( getLineWidth( aShape, true ) );
852 m_gal->SetStrokeColor( color );
853 }
854
855 drawShape( aShape );
856 }
857 else if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_NOTES_BACKGROUND )
858 {
860 || aShape->GetFillMode() == FILL_T::FILLED_WITH_COLOR )
861 {
862 m_gal->SetIsFill( true );
863 m_gal->SetIsStroke( false );
864 drawShape( aShape );
865 }
866 }
867 else if( aLayer == LAYER_DEVICE || aLayer == LAYER_PRIVATE_NOTES )
868 {
869 if( aShape->GetFillMode() == FILL_T::FILLED_SHAPE
870 || aShape->GetFillMode() == FILL_T::FILLED_WITH_COLOR )
871 {
872 m_gal->SetIsFill( true );
873 m_gal->SetIsStroke( false );
874 drawShape( aShape );
875 }
876
877 int lineWidth = getLineWidth( aShape, drawingShadows );
878
879 if( lineWidth > 0 )
880 {
881 m_gal->SetIsFill( false );
882 m_gal->SetIsStroke( true );
883 m_gal->SetLineWidth( lineWidth );
884 m_gal->SetStrokeColor( color );
885
886 if( lineStyle <= PLOT_DASH_TYPE::FIRST_TYPE || drawingShadows )
887 {
888 drawShape( aShape );
889 }
890 else
891 {
892 std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapes( true );
893
894 for( SHAPE* shape : shapes )
895 {
896 STROKE_PARAMS::Stroke( shape, lineStyle, lineWidth, &m_schSettings,
897 [&]( const VECTOR2I& a, const VECTOR2I& b )
898 {
899 // DrawLine has problem with 0 length lines so enforce minimum
900 if( a == b )
901 m_gal->DrawLine( mapCoords( a+1 ), mapCoords( b ) );
902 else
903 m_gal->DrawLine( mapCoords( a ), mapCoords( b ) );
904 } );
905 }
906
907 for( SHAPE* shape : shapes )
908 delete shape;
909 }
910 }
911 }
912}
913
914
915void SCH_PAINTER::draw( const LIB_FIELD *aField, int aLayer, bool aDimmed )
916{
917 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
918
919 if( drawingShadows && !( aField->IsBrightened() || aField->IsSelected() ) )
920 return;
921
922 if( !isUnitAndConversionShown( aField ) )
923 return;
924
925 // Must check layer as fields are sometimes drawn by their parent rather than
926 // directly from the view.
928 int layers_count;
929 bool foundLayer = false;
930
931 aField->ViewGetLayers( layers, layers_count );
932
933 for( int i = 0; i < layers_count; ++i )
934 {
935 if( layers[i] == aLayer )
936 foundLayer = true;
937 }
938
939 if( !foundLayer )
940 return;
941
942 COLOR4D color = getRenderColor( aField, aLayer, drawingShadows, aDimmed );
943
944 if( !( aField->IsVisible() || aField->IsForceVisible() ) )
945 {
946 if( m_schSettings.m_IsSymbolEditor || eeconfig()->m_Appearance.show_hidden_fields )
947 color = getRenderColor( aField, LAYER_HIDDEN, drawingShadows, aDimmed );
948 else
949 return;
950 }
951
952 m_gal->SetStrokeColor( color );
953 m_gal->SetFillColor( color );
954
955 BOX2I bbox = aField->GetBoundingBox();
956
957 if( drawingShadows )
958 {
959 bbox.Inflate( getTextThickness( aField ) * 2 );
960
961 m_gal->SetIsStroke( false );
962 m_gal->SetIsFill( true );
963 m_gal->DrawRectangle( bbox.GetPosition(), bbox.GetEnd() );
964 }
965 else
966 {
967 VECTOR2I textpos = bbox.Centre();
968 TEXT_ATTRIBUTES attrs( aField->GetAttributes() );
969
972 attrs.m_StrokeWidth = getTextThickness( aField );
973
974 strokeText( UnescapeString( aField->GetShownText() ), textpos, attrs );
975 }
976
977 // Draw the umbilical line when in the schematic editor
978 if( aField->IsMoving() && m_schematic )
979 {
980 m_gal->SetLineWidth( m_schSettings.m_outlineWidth );
981 m_gal->SetStrokeColor( getRenderColor( aField, LAYER_SCHEMATIC_ANCHOR, drawingShadows ) );
982 m_gal->DrawLine( bbox.Centre(), VECTOR2I( 0, 0 ) );
983 }
984}
985
986
987void SCH_PAINTER::draw( const LIB_TEXT* aText, int aLayer, bool aDimmed )
988{
989 if( !isUnitAndConversionShown( aText ) )
990 return;
991
992 if( aText->IsPrivate() && !m_schSettings.m_IsSymbolEditor )
993 return;
994
995 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
996
997 if( drawingShadows && !( aText->IsBrightened() || aText->IsSelected() ) )
998 return;
999
1000 COLOR4D color = getRenderColor( aText, aLayer, drawingShadows, aDimmed );
1001
1002 if( !aText->IsVisible() )
1003 {
1004 if( !m_schematic || eeconfig()->m_Appearance.show_hidden_fields )
1005 color = getRenderColor( aText, LAYER_HIDDEN, drawingShadows, aDimmed );
1006 else
1007 return;
1008 }
1009
1010 BOX2I bBox = aText->GetBoundingBox();
1011
1012 m_gal->SetFillColor( color );
1013 m_gal->SetStrokeColor( color );
1014
1015 if( drawingShadows )
1016 {
1017 bBox.Inflate( getTextThickness( aText ) * 2 );
1018
1019 m_gal->SetIsStroke( false );
1020 m_gal->SetIsFill( true );
1021 m_gal->DrawRectangle( bBox.GetPosition(), bBox.GetEnd() );
1022 }
1023 else
1024 {
1025 wxString shownText( aText->GetShownText() );
1026 VECTOR2D pos = bBox.Centre();
1027 TEXT_ATTRIBUTES attrs = aText->GetAttributes();
1028
1029 attrs.m_StrokeWidth = getTextThickness( aText );
1030
1031 if( attrs.m_Angle == ANGLE_VERTICAL )
1032 {
1033 switch( attrs.m_Halign )
1034 {
1035 case GR_TEXT_H_ALIGN_LEFT: pos.y = bBox.GetBottom(); break;
1036 case GR_TEXT_H_ALIGN_CENTER: pos.y = ( bBox.GetTop() + bBox.GetBottom() ) / 2; break;
1037 case GR_TEXT_H_ALIGN_RIGHT: pos.y = bBox.GetTop(); break;
1038 }
1039 }
1040 else
1041 {
1042 switch( attrs.m_Halign )
1043 {
1044 case GR_TEXT_H_ALIGN_LEFT: pos.x = bBox.GetLeft(); break;
1045 case GR_TEXT_H_ALIGN_CENTER: pos.x = ( bBox.GetLeft() + bBox.GetRight() ) / 2; break;
1046 case GR_TEXT_H_ALIGN_RIGHT: pos.x = bBox.GetRight(); break;
1047 }
1048 }
1049
1050 // Because the text vertical position is the bounding box center, the text is drawn as
1051 // vertically centered.
1053
1054 strokeText( shownText, pos, attrs );
1055 }
1056}
1057
1058
1059void SCH_PAINTER::draw( const LIB_TEXTBOX* aTextBox, int aLayer, bool aDimmed )
1060{
1061 if( !isUnitAndConversionShown( aTextBox ) )
1062 return;
1063
1064 if( aTextBox->IsPrivate() && !m_schSettings.m_IsSymbolEditor )
1065 return;
1066
1067 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1068
1069 if( drawingShadows && !( aTextBox->IsBrightened() || aTextBox->IsSelected() ) )
1070 return;
1071
1072 COLOR4D bg = m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND );
1073 COLOR4D color = getRenderColor( aTextBox, aLayer, drawingShadows, aDimmed );
1074 float borderWidth = getLineWidth( aTextBox, drawingShadows );
1075
1076 auto drawText =
1077 [&]()
1078 {
1079 wxString shownText = aTextBox->GetShownText();
1080 TEXT_ATTRIBUTES attrs = aTextBox->GetAttributes();
1081
1082 attrs.m_Angle = aTextBox->GetDrawRotation();
1083 attrs.m_StrokeWidth = getTextThickness( aTextBox );
1084
1085 strokeText( shownText, aTextBox->GetDrawPos(), attrs );
1086 };
1087
1088 m_gal->SetStrokeColor( color );
1089 m_gal->SetFillColor( color );
1090
1091 if( aLayer == LAYER_SELECTION_SHADOWS )
1092 {
1093 m_gal->SetIsFill( true );
1094 m_gal->SetIsStroke( false );
1095 m_gal->SetLineWidth( borderWidth );
1096
1097 m_gal->DrawRectangle( mapCoords( aTextBox->GetPosition() ),
1098 mapCoords( aTextBox->GetEnd() ) );
1099 }
1100 else if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_NOTES_BACKGROUND )
1101 {
1102 if( aTextBox->IsFilled() )
1103 {
1104 m_gal->SetIsFill( true );
1105 m_gal->SetIsStroke( false );
1106 m_gal->SetLineWidth( borderWidth );
1107
1108 m_gal->DrawRectangle( mapCoords( aTextBox->GetPosition() ),
1109 mapCoords( aTextBox->GetEnd() ) );
1110 }
1111 }
1112 else if( aLayer == LAYER_DEVICE || aLayer == LAYER_PRIVATE_NOTES )
1113 {
1114 drawText();
1115
1116 if( borderWidth > 0 )
1117 {
1118 COLOR4D borderColor = aTextBox->GetStroke().GetColor();
1119 PLOT_DASH_TYPE borderStyle = aTextBox->GetStroke().GetPlotStyle();
1120
1121 if( m_schSettings.m_OverrideItemColors || aTextBox->IsBrightened()
1122 || borderColor == COLOR4D::UNSPECIFIED )
1123 {
1124 borderColor = m_schSettings.GetLayerColor( aLayer );
1125 }
1126
1127 if( aDimmed )
1128 borderColor = borderColor.Mix( bg, 0.5f );
1129
1130 m_gal->SetIsFill( false );
1131 m_gal->SetIsStroke( true );
1132 m_gal->SetStrokeColor( borderColor );
1133 m_gal->SetLineWidth( borderWidth );
1134
1135 if( borderStyle <= PLOT_DASH_TYPE::FIRST_TYPE || drawingShadows )
1136 {
1137 m_gal->DrawRectangle( mapCoords( aTextBox->GetPosition() ),
1138 mapCoords( aTextBox->GetEnd() ) );
1139 }
1140 else
1141 {
1142 std::vector<SHAPE*> shapes = aTextBox->MakeEffectiveShapes( true );
1143
1144 for( SHAPE* shape : shapes )
1145 {
1146 STROKE_PARAMS::Stroke( shape, borderStyle, borderWidth, &m_schSettings,
1147 [&]( const VECTOR2I& a, const VECTOR2I& b )
1148 {
1149 // DrawLine has problem with 0 length lines so enforce minimum
1150 if( a == b )
1151 m_gal->DrawLine( mapCoords( a+1 ), mapCoords( b ) );
1152 else
1153 m_gal->DrawLine( mapCoords( a ), mapCoords( b ) );
1154 } );
1155 }
1156
1157 for( SHAPE* shape : shapes )
1158 delete shape;
1159 }
1160 }
1161 }
1162}
1163
1164
1166{
1167 if( m_schSettings.m_PinSymbolSize > 0 )
1168 return m_schSettings.m_PinSymbolSize;
1169
1170 return aPin.GetNameTextSize() != 0 ? aPin.GetNameTextSize() / 2 : aPin.GetNumberTextSize() / 2;
1171}
1172
1173
1174// Utility for getting the size of the 'external' pin decorators (as a radius)
1175// i.e. the negation circle, the polarity 'slopes' and the nonlogic marker
1177{
1178 if( m_schSettings.m_PinSymbolSize > 0 )
1179 return m_schSettings.m_PinSymbolSize;
1180
1181 return aPin.GetNumberTextSize() / 2;
1182}
1183
1184
1185// Draw the target (an open circle) for a pin which has no connection or is being moved.
1186void SCH_PAINTER::drawPinDanglingSymbol( const VECTOR2I& aPos, const COLOR4D& aColor,
1187 bool aDrawingShadows, bool aBrightened )
1188{
1189 // Dangling symbols must be drawn in a slightly different colour so they can be seen when
1190 // they overlap with a junction dot.
1191 m_gal->SetStrokeColor( aColor.Brightened( 0.3 ) );
1192
1193 m_gal->SetIsFill( false );
1194 m_gal->SetIsStroke( true );
1195 m_gal->SetLineWidth( aDrawingShadows ? getShadowWidth( aBrightened )
1196 : m_schSettings.GetDanglineSymbolThickness() );
1197
1198 m_gal->DrawCircle( aPos, TARGET_PIN_RADIUS );
1199}
1200
1201
1202void SCH_PAINTER::draw( const LIB_PIN *aPin, int aLayer, bool aDimmed )
1203{
1204 if( !isUnitAndConversionShown( aPin ) )
1205 return;
1206
1207 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1208 bool drawingDangling = aLayer == LAYER_DANGLING;
1209 bool isDangling = m_schSettings.m_IsSymbolEditor || aPin->HasFlag( IS_DANGLING );
1210
1211 if( drawingShadows && !( aPin->IsBrightened() || aPin->IsSelected() ) )
1212 return;
1213
1214 VECTOR2I pos = mapCoords( aPin->GetPosition() );
1215 COLOR4D color = getRenderColor( aPin, LAYER_PIN, drawingShadows, aDimmed );
1216
1217 if( !aPin->IsVisible() )
1218 {
1219 if( !m_schematic || eeconfig()->m_Appearance.show_hidden_pins )
1220 {
1221 color = getRenderColor( aPin, LAYER_HIDDEN, drawingShadows, aDimmed );
1222 }
1223 else
1224 {
1225 if( drawingDangling && isDangling && aPin->IsPowerConnection() )
1226 drawPinDanglingSymbol( pos, color, drawingShadows, aPin->IsBrightened() );
1227
1228 return;
1229 }
1230 }
1231
1232 if( drawingDangling )
1233 {
1234 if( isDangling )
1235 drawPinDanglingSymbol( pos, color, drawingShadows, aPin->IsBrightened() );
1236
1237 return;
1238 }
1239
1240 VECTOR2I p0;
1241 VECTOR2I dir;
1242 int len = aPin->GetLength();
1243 int orient = aPin->GetOrientation();
1244
1245 switch( orient )
1246 {
1247 case PIN_UP:
1248 p0 = VECTOR2I( pos.x, pos.y - len );
1249 dir = VECTOR2I( 0, 1 );
1250 break;
1251
1252 case PIN_DOWN:
1253 p0 = VECTOR2I( pos.x, pos.y + len );
1254 dir = VECTOR2I( 0, -1 );
1255 break;
1256
1257 case PIN_LEFT:
1258 p0 = VECTOR2I( pos.x - len, pos.y );
1259 dir = VECTOR2I( 1, 0 );
1260 break;
1261
1262 default:
1263 case PIN_RIGHT:
1264 p0 = VECTOR2I( pos.x + len, pos.y );
1265 dir = VECTOR2I( -1, 0 );
1266 break;
1267 }
1268
1269 VECTOR2D pc;
1270
1271 m_gal->SetIsStroke( true );
1272 m_gal->SetIsFill( false );
1273 m_gal->SetLineWidth( getLineWidth( aPin, drawingShadows ) );
1274 m_gal->SetStrokeColor( color );
1275 m_gal->SetFontBold( false );
1276 m_gal->SetFontUnderlined( false );
1277 m_gal->SetFontItalic( false );
1278
1279 const int radius = externalPinDecoSize( *aPin );
1280 const int diam = radius*2;
1281 const int clock_size = internalPinDecoSize( *aPin );
1282
1283 if( aPin->GetType() == ELECTRICAL_PINTYPE::PT_NC ) // Draw a N.C. symbol
1284 {
1285 m_gal->DrawLine( p0, pos );
1286
1287 m_gal->DrawLine( pos + VECTOR2D( -1, -1 ) * TARGET_PIN_RADIUS,
1288 pos + VECTOR2D( 1, 1 ) * TARGET_PIN_RADIUS );
1289 m_gal->DrawLine( pos + VECTOR2D( 1, -1 ) * TARGET_PIN_RADIUS ,
1290 pos + VECTOR2D( -1, 1 ) * TARGET_PIN_RADIUS );
1291 }
1292 else
1293 {
1294 switch( aPin->GetShape() )
1295 {
1297 m_gal->DrawLine( p0, pos );
1298 break;
1299
1301 m_gal->DrawCircle( p0 + dir * radius, radius );
1302 m_gal->DrawLine( p0 + dir * ( diam ), pos );
1303 break;
1304
1306 pc = p0 - dir * clock_size ;
1307
1308 triLine( p0 + VECTOR2D( dir.y, -dir.x) * clock_size,
1309 pc,
1310 p0 + VECTOR2D( -dir.y, dir.x) * clock_size );
1311
1312 m_gal->DrawCircle( p0 + dir * radius, radius );
1313 m_gal->DrawLine( p0 + dir * ( diam ), pos );
1314 break;
1315
1318 pc = p0 - dir * clock_size ;
1319
1320 triLine( p0 + VECTOR2D( dir.y, -dir.x) * clock_size,
1321 pc,
1322 p0 + VECTOR2D( -dir.y, dir.x) * clock_size );
1323
1324 if( !dir.y )
1325 {
1326 triLine( p0 + VECTOR2D(dir.x, 0) * diam,
1327 p0 + VECTOR2D(dir.x, -1) * diam,
1328 p0 );
1329 }
1330 else /* MapX1 = 0 */
1331 {
1332 triLine( p0 + VECTOR2D( 0, dir.y) * diam,
1333 p0 + VECTOR2D(-1, dir.y) * diam,
1334 p0 );
1335 }
1336
1337 m_gal->DrawLine( p0, pos );
1338 break;
1339
1341 m_gal->DrawLine( p0, pos );
1342
1343 if( !dir.y )
1344 {
1345 triLine( p0 + VECTOR2D( 0, clock_size ),
1346 p0 + VECTOR2D( -dir.x * clock_size, 0 ),
1347 p0 + VECTOR2D( 0, -clock_size ) );
1348 }
1349 else
1350 {
1351 triLine( p0 + VECTOR2D( clock_size, 0 ),
1352 p0 + VECTOR2D( 0, -dir.y * clock_size ),
1353 p0 + VECTOR2D( -clock_size, 0 ) );
1354 }
1355 break;
1356
1358 m_gal->DrawLine( p0, pos );
1359
1360 if( !dir.y )
1361 {
1362 triLine( p0 + VECTOR2D(dir.x, 0) * diam,
1363 p0 + VECTOR2D(dir.x, -1) * diam,
1364 p0 );
1365 }
1366 else /* MapX1 = 0 */
1367 {
1368 triLine( p0 + VECTOR2D( 0, dir.y) * diam,
1369 p0 + VECTOR2D(-1, dir.y) * diam,
1370 p0 );
1371 }
1372 break;
1373
1374 case GRAPHIC_PINSHAPE::OUTPUT_LOW: // IEEE symbol "Active Low Output"
1375 m_gal->DrawLine( p0, pos );
1376
1377 if( !dir.y ) // Horizontal pin
1378 m_gal->DrawLine( p0 - VECTOR2D( 0, diam ), p0 + VECTOR2D( dir.x, 0 ) * diam );
1379 else // Vertical pin
1380 m_gal->DrawLine( p0 - VECTOR2D( diam, 0 ), p0 + VECTOR2D( 0, dir.y ) * diam );
1381 break;
1382
1383 case GRAPHIC_PINSHAPE::NONLOGIC: // NonLogic pin symbol
1384 m_gal->DrawLine( p0, pos );
1385
1386 m_gal->DrawLine( p0 - VECTOR2D( dir.x + dir.y, dir.y - dir.x ) * radius,
1387 p0 + VECTOR2D( dir.x + dir.y, dir.y - dir.x ) * radius );
1388 m_gal->DrawLine( p0 - VECTOR2D( dir.x - dir.y, dir.x + dir.y ) * radius,
1389 p0 + VECTOR2D( dir.x - dir.y, dir.x + dir.y ) * radius );
1390 break;
1391 }
1392 }
1393
1394 LIB_SYMBOL* libEntry = aPin->GetParent();
1395
1396 // Draw the labels
1397
1398 if( libEntry->Type() == LIB_SYMBOL_T )
1399 {
1400 if( drawingShadows && !eeconfig()->m_Selection.draw_selected_children )
1401 return;
1402 }
1403
1404 float penWidth = (float) m_schSettings.GetDefaultPenWidth();
1405 int textOffset = libEntry->GetPinNameOffset();
1406 float nameStrokeWidth = getLineWidth( aPin, drawingShadows );
1407 float numStrokeWidth = getLineWidth( aPin, drawingShadows );
1408 bool showPinNames = libEntry->ShowPinNames();
1409 bool showPinNumbers = m_schSettings.m_ShowPinNumbers || libEntry->ShowPinNumbers();
1410
1411 nameStrokeWidth = Clamp_Text_PenSize( nameStrokeWidth, aPin->GetNameTextSize(), true );
1412 numStrokeWidth = Clamp_Text_PenSize( numStrokeWidth, aPin->GetNumberTextSize(), true );
1413
1414 int PIN_TEXT_MARGIN = KiROUND( 24 * m_schSettings.m_TextOffsetRatio );
1415
1416 // Four locations around a pin where text can be drawn
1417 enum { INSIDE = 0, OUTSIDE, ABOVE, BELOW };
1418 int size[4] = { 0, 0, 0, 0 };
1419 float thickness[4] = { numStrokeWidth, numStrokeWidth, numStrokeWidth, numStrokeWidth };
1420 COLOR4D colour[4];
1421 wxString text[4];
1422
1423 // TextOffset > 0 means pin NAMES on inside, pin NUMBERS above and nothing below
1424 if( textOffset )
1425 {
1426 size [INSIDE] = showPinNames ? aPin->GetNameTextSize() : 0;
1427 thickness[INSIDE] = nameStrokeWidth;
1428 colour [INSIDE] = getRenderColor( aPin, LAYER_PINNAM, drawingShadows, aDimmed );
1429 text [INSIDE] = aPin->GetShownName();
1430
1431 size [ABOVE] = showPinNumbers ? aPin->GetNumberTextSize() : 0;
1432 thickness[ABOVE] = numStrokeWidth;
1433 colour [ABOVE] = getRenderColor( aPin, LAYER_PINNUM, drawingShadows, aDimmed );
1434 text [ABOVE] = aPin->GetShownNumber();
1435 }
1436 // Otherwise pin NAMES go above and pin NUMBERS go below
1437 else
1438 {
1439 size [ABOVE] = showPinNames ? aPin->GetNameTextSize() : 0;
1440 thickness[ABOVE] = nameStrokeWidth;
1441 colour [ABOVE] = getRenderColor( aPin, LAYER_PINNAM, drawingShadows, aDimmed );
1442 text [ABOVE] = aPin->GetShownName();
1443
1444 size [BELOW] = showPinNumbers ? aPin->GetNumberTextSize() : 0;
1445 thickness[BELOW] = numStrokeWidth;
1446 colour [BELOW] = getRenderColor( aPin, LAYER_PINNUM, drawingShadows, aDimmed );
1447 text [BELOW] = aPin->GetShownNumber();
1448 }
1449
1450 if( m_schSettings.m_ShowPinsElectricalType )
1451 {
1452 size[OUTSIDE] = std::max( aPin->GetNameTextSize() * 3 / 4, schIUScale.mmToIU( 0.7 ) );
1453 thickness[OUTSIDE] = float( size[OUTSIDE] ) / 8.0F;
1454 colour [OUTSIDE] = getRenderColor( aPin, LAYER_PRIVATE_NOTES, drawingShadows, aDimmed );
1456 }
1457
1458 // Rendering text is expensive (particularly when using outline fonts). At small effective
1459 // sizes (ie: zoomed out) the visual differences between outline and/or stroke fonts and the
1460 // bitmap font becomes immaterial, and there's often more to draw when zoomed out so the
1461 // performance gain becomes more significant.
1462 #define BITMAP_FONT_SIZE_THRESHOLD 3.5
1463
1464 bool renderTextAsBitmap = size[0] * m_gal->GetWorldScale() < BITMAP_FONT_SIZE_THRESHOLD
1465 && size[1] * m_gal->GetWorldScale() < BITMAP_FONT_SIZE_THRESHOLD
1466 && size[2] * m_gal->GetWorldScale() < BITMAP_FONT_SIZE_THRESHOLD
1467 && size[3] * m_gal->GetWorldScale() < BITMAP_FONT_SIZE_THRESHOLD;
1468
1469 if( !aPin->IsVisible() )
1470 {
1471 for( COLOR4D& c : colour )
1472 c = getRenderColor( aPin, LAYER_HIDDEN, drawingShadows, aDimmed );
1473 }
1474
1475 float insideOffset = textOffset - thickness[INSIDE] / 2.0;
1476 float outsideOffset = schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + TARGET_PIN_RADIUS - thickness[OUTSIDE] / 2.0;
1477 float aboveOffset = schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + penWidth / 2.0 + thickness[ABOVE] / 2.0;
1478 float belowOffset = schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + penWidth / 2.0 + thickness[BELOW] / 2.0;
1479
1480 if( isDangling )
1481 outsideOffset += TARGET_PIN_RADIUS / 2.0;
1482
1483 if( drawingShadows )
1484 {
1485 float shadowWidth = getShadowWidth( aPin->IsBrightened() );
1486
1487 for( float& t : thickness )
1488 t += shadowWidth;
1489 }
1490
1491 auto drawText =
1492 [&]( int i, const VECTOR2D& aPos, GR_TEXT_H_ALIGN_T hAlign, GR_TEXT_V_ALIGN_T vAlign,
1493 const EDA_ANGLE& aAngle )
1494 {
1495 if( text[i].IsEmpty() )
1496 return;
1497
1498 // Which of these gets used depends on the font technology, so set both
1499 m_gal->SetStrokeColor( colour[i] );
1500 m_gal->SetFillColor( colour[i] );
1501
1502 TEXT_ATTRIBUTES attrs;
1503 attrs.m_Size = VECTOR2I( size[i], size[i] );
1504 attrs.m_Halign = hAlign;
1505 attrs.m_Valign = vAlign;
1506 attrs.m_Angle = aAngle;
1507 attrs.m_StrokeWidth = thickness[i];
1508
1509 if( drawingShadows )
1510 {
1511 boxText( text[i], aPos, attrs );
1512 }
1513 else if( nonCached( aPin ) && renderTextAsBitmap )
1514 {
1515 bitmapText( text[i], aPos, attrs );
1516 const_cast<LIB_PIN*>( aPin )->SetFlags( IS_SHOWN_AS_BITMAP );
1517 }
1518 else
1519 {
1520 strokeText( text[i], aPos, attrs );
1521 const_cast<LIB_PIN*>( aPin )->SetFlags( IS_SHOWN_AS_BITMAP );
1522 }
1523 };
1524
1525 switch( orient )
1526 {
1527 case PIN_LEFT:
1528 if( size[INSIDE] )
1529 {
1530 drawText( INSIDE, pos + VECTOR2D( -insideOffset - len, 0 ),
1532 }
1533 if( size[OUTSIDE] )
1534 {
1535 drawText( OUTSIDE, pos + VECTOR2D( outsideOffset, 0 ),
1537 }
1538 if( size[ABOVE] )
1539 {
1540 drawText( ABOVE, pos + VECTOR2D( -len / 2.0, -aboveOffset ),
1542 }
1543 if( size[BELOW] )
1544 {
1545 drawText( BELOW, pos + VECTOR2D( -len / 2.0, belowOffset ),
1547 }
1548 break;
1549
1550 case PIN_RIGHT:
1551 if( size[INSIDE] )
1552 {
1553 drawText( INSIDE, pos + VECTOR2D( insideOffset + len, 0 ),
1555 }
1556 if( size[OUTSIDE] )
1557 {
1558 drawText( OUTSIDE, pos + VECTOR2D( -outsideOffset, 0 ),
1560 }
1561 if( size[ABOVE] )
1562 {
1563 drawText( ABOVE, pos + VECTOR2D( len / 2.0, -aboveOffset ),
1565 }
1566 if( size[BELOW] )
1567 {
1568 drawText( BELOW, pos + VECTOR2D( len / 2.0, belowOffset ),
1570 }
1571 break;
1572
1573 case PIN_DOWN:
1574 if( size[INSIDE] )
1575 {
1576 drawText( INSIDE, pos + VECTOR2D( 0, insideOffset + len ),
1578 }
1579 if( size[OUTSIDE] )
1580 {
1581 drawText( OUTSIDE, pos + VECTOR2D( 0, -outsideOffset ),
1583 }
1584 if( size[ABOVE] )
1585 {
1586 drawText( ABOVE, pos + VECTOR2D( -aboveOffset, len / 2.0 ),
1588 }
1589 if( size[BELOW] )
1590 {
1591 drawText( BELOW, pos + VECTOR2D( belowOffset, len / 2.0 ),
1593 }
1594 break;
1595
1596 case PIN_UP:
1597 if( size[INSIDE] )
1598 {
1599 drawText( INSIDE, pos + VECTOR2D( 0, -insideOffset - len ),
1601 }
1602 if( size[OUTSIDE] )
1603 {
1604 drawText( OUTSIDE, pos + VECTOR2D( 0, outsideOffset ),
1606 }
1607 if( size[ABOVE] )
1608 {
1609 drawText( ABOVE, pos + VECTOR2D( -aboveOffset, -len / 2.0 ),
1611 }
1612 if( size[BELOW] )
1613 {
1614 drawText( BELOW, pos + VECTOR2D( belowOffset, -len / 2.0 ),
1616 }
1617 break;
1618
1619 default:
1620 wxFAIL_MSG( "Unknown pin orientation" );
1621 }
1622}
1623
1624
1625// Draw the target (an open square) for a wire or label which has no connection or is
1626// being moved.
1627void SCH_PAINTER::drawDanglingSymbol( const VECTOR2I& aPos, const COLOR4D& aColor, int aWidth,
1628 bool aDrawingShadows, bool aBrightened )
1629{
1630 VECTOR2I radius( aWidth + schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE / 2 ),
1631 aWidth + schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE / 2 ) );
1632
1633 // Dangling symbols must be drawn in a slightly different colour so they can be seen when
1634 // they overlap with a junction dot.
1635 m_gal->SetStrokeColor( aColor.Brightened( 0.3 ) );
1636 m_gal->SetIsStroke( true );
1637 m_gal->SetIsFill( false );
1638 m_gal->SetLineWidth( aDrawingShadows ? getShadowWidth( aBrightened )
1639 : m_schSettings.GetDanglineSymbolThickness() );
1640
1641 m_gal->DrawRectangle( aPos - radius, aPos + radius );
1642}
1643
1644
1645void SCH_PAINTER::draw( const SCH_JUNCTION *aJct, int aLayer )
1646{
1647 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1648
1649 if( drawingShadows && !( aJct->IsBrightened() || aJct->IsSelected() ) )
1650 return;
1651
1652 COLOR4D color = getRenderColor( aJct, aJct->GetLayer(), drawingShadows );
1653
1654 int junctionSize = aJct->GetEffectiveDiameter() / 2;
1655
1656 if( junctionSize > 1 )
1657 {
1658 m_gal->SetIsStroke( drawingShadows );
1659 m_gal->SetLineWidth( getLineWidth( aJct, drawingShadows ) );
1660 m_gal->SetStrokeColor( color );
1661 m_gal->SetIsFill( !drawingShadows );
1662 m_gal->SetFillColor( color );
1663 m_gal->DrawCircle( aJct->GetPosition(), junctionSize );
1664 }
1665}
1666
1667
1668void SCH_PAINTER::draw( const SCH_LINE *aLine, int aLayer )
1669{
1670 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1671 bool drawingDangling = aLayer == LAYER_DANGLING;
1672
1673 if( drawingShadows && !( aLine->IsBrightened() || aLine->IsSelected() ) )
1674 return;
1675
1676 // Line end dangling status isn't updated until the line is finished drawing,
1677 // so don't warn them about ends that are probably connected
1678 if( aLine->IsNew() && drawingDangling )
1679 return;
1680
1681 COLOR4D color = getRenderColor( aLine, aLine->GetLayer(), drawingShadows );
1682 float width = getLineWidth( aLine, drawingShadows );
1683 PLOT_DASH_TYPE lineStyle = aLine->GetEffectiveLineStyle();
1684
1685 if( drawingDangling || drawingShadows )
1686 {
1687 if( aLine->IsStartDangling() && aLine->IsWire() )
1688 {
1689 COLOR4D danglingColor =
1690 ( drawingShadows && !aLine->HasFlag( STARTPOINT ) ) ? color.Inverted() : color;
1691 drawDanglingSymbol( aLine->GetStartPoint(), danglingColor,
1692 getLineWidth( aLine, drawingShadows ), drawingShadows,
1693 aLine->IsBrightened() );
1694 }
1695
1696 if( aLine->IsEndDangling() && aLine->IsWire() )
1697 {
1698 COLOR4D danglingColor =
1699 ( drawingShadows && !aLine->HasFlag( ENDPOINT ) ) ? color.Inverted() : color;
1700 drawDanglingSymbol( aLine->GetEndPoint(), danglingColor,
1701 getLineWidth( aLine, drawingShadows ), drawingShadows,
1702 aLine->IsBrightened() );
1703 }
1704
1705 if( drawingDangling )
1706 return;
1707 }
1708
1709 m_gal->SetIsStroke( true );
1710 m_gal->SetStrokeColor( color );
1711 m_gal->SetLineWidth( width );
1712
1713 if( lineStyle <= PLOT_DASH_TYPE::FIRST_TYPE || drawingShadows )
1714 {
1715 m_gal->DrawLine( aLine->GetStartPoint(), aLine->GetEndPoint() );
1716 }
1717 else
1718 {
1719 SHAPE_SEGMENT line( aLine->GetStartPoint(), aLine->GetEndPoint() );
1720
1721 STROKE_PARAMS::Stroke( &line, lineStyle, width, &m_schSettings,
1722 [&]( const VECTOR2I& a, const VECTOR2I& b )
1723 {
1724 // DrawLine has problem with 0 length lines
1725 // so draw a line with a minimal length
1726 if( a == b )
1727 m_gal->DrawLine( a+1, b );
1728 else
1729 m_gal->DrawLine( a, b );
1730 } );
1731 }
1732}
1733
1734
1735void SCH_PAINTER::draw( const SCH_SHAPE* aShape, int aLayer )
1736{
1737 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1738 PLOT_DASH_TYPE lineStyle = aShape->GetEffectiveLineStyle();
1739 COLOR4D color = getRenderColor( aShape, aLayer, drawingShadows );
1740
1741 if( drawingShadows && !( aShape->IsBrightened() || aShape->IsSelected() ) )
1742 return;
1743
1744 auto drawShape =
1745 [&]( const SCH_SHAPE* shape )
1746 {
1747 switch( shape->GetShape() )
1748 {
1749 case SHAPE_T::ARC:
1750 {
1751 EDA_ANGLE startAngle;
1752 EDA_ANGLE endAngle;
1753 aShape->CalcArcAngles( startAngle, endAngle );
1754
1755 m_gal->DrawArc( aShape->GetCenter(), aShape->GetRadius(), startAngle,
1756 endAngle );
1757 break;
1758 }
1759
1760 case SHAPE_T::CIRCLE:
1761 m_gal->DrawCircle( shape->GetPosition(), shape->GetRadius() );
1762 break;
1763
1764 case SHAPE_T::RECT:
1765 m_gal->DrawRectangle( shape->GetPosition(), shape->GetEnd() );
1766 break;
1767
1768 case SHAPE_T::POLY:
1769 {
1770 std::deque<VECTOR2D> pts;
1771
1772 for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
1773 pts.push_back( pt );
1774
1775 m_gal->DrawPolygon( pts );
1776 break;
1777 }
1778
1779 case SHAPE_T::BEZIER:
1780 {
1781 std::deque<VECTOR2D> pts;
1782
1783 for( const VECTOR2I &p : shape->GetPolyShape().Outline( 0 ).CPoints() )
1784 pts.push_back( p );
1785
1786 m_gal->DrawPolygon( pts );
1787 break;
1788 }
1789
1790 default:
1791 UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
1792 }
1793 };
1794
1795 if( aLayer == LAYER_SELECTION_SHADOWS )
1796 {
1797 if( eeconfig()->m_Selection.fill_shapes )
1798 {
1799 // Consider a NAND gate. We have no idea which side of the arc is "inside"
1800 // so we can't reliably fill.
1801 if( aShape->GetShape() == SHAPE_T::ARC )
1802 m_gal->SetIsFill( aShape->IsFilled() );
1803 else
1804 m_gal->SetIsFill( true );
1805
1806 m_gal->SetIsStroke( false );
1807 m_gal->SetFillColor( color );
1808 }
1809 else
1810 {
1811 m_gal->SetIsStroke( true );
1812 m_gal->SetIsFill( false );
1813 m_gal->SetLineWidth( getLineWidth( aShape, true ) );
1814 m_gal->SetStrokeColor( color );
1815 }
1816
1817 drawShape( aShape );
1818 }
1819 else if( aLayer == LAYER_NOTES_BACKGROUND )
1820 {
1821 if( aShape->IsFilled() )
1822 {
1823 m_gal->SetIsFill( true );
1824 m_gal->SetIsStroke( false );
1825 m_gal->SetFillColor( color );
1826
1827 drawShape( aShape );
1828 }
1829 }
1830 else if( aLayer == LAYER_NOTES )
1831 {
1832 int lineWidth = getLineWidth( aShape, drawingShadows );
1833
1834 if( lineWidth > 0 )
1835 {
1836 m_gal->SetIsFill( false );
1837 m_gal->SetIsStroke( true );
1838 m_gal->SetLineWidth( lineWidth );
1839 m_gal->SetStrokeColor( color );
1840
1841 if( lineStyle <= PLOT_DASH_TYPE::FIRST_TYPE || drawingShadows )
1842 {
1843 drawShape( aShape );
1844 }
1845 else
1846 {
1847 std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapes( true );
1848
1849 for( SHAPE* shape : shapes )
1850 {
1851 STROKE_PARAMS::Stroke( shape, lineStyle, lineWidth, &m_schSettings,
1852 [&]( const VECTOR2I& a, const VECTOR2I& b )
1853 {
1854 // DrawLine has problem with 0 length lines so enforce minimum
1855 if( a == b )
1856 m_gal->DrawLine( a+1, b );
1857 else
1858 m_gal->DrawLine( a, b );
1859 } );
1860 }
1861
1862 for( SHAPE* shape : shapes )
1863 delete shape;
1864 }
1865 }
1866 }
1867}
1868
1869
1870void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
1871{
1872 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1873 bool drawingDangling = aLayer == LAYER_DANGLING;
1874
1875 if( drawingShadows && !( aText->IsBrightened() || aText->IsSelected() ) )
1876 return;
1877
1878 switch( aText->Type() )
1879 {
1880 case SCH_SHEET_PIN_T: aLayer = LAYER_SHEETLABEL; break;
1881 case SCH_HIER_LABEL_T: aLayer = LAYER_HIERLABEL; break;
1882 case SCH_GLOBAL_LABEL_T: aLayer = LAYER_GLOBLABEL; break;
1883 case SCH_DIRECTIVE_LABEL_T: aLayer = LAYER_NETCLASS_REFS; break;
1884 case SCH_LABEL_T: aLayer = LAYER_LOCLABEL; break;
1885 default: aLayer = LAYER_NOTES; break;
1886 }
1887
1888 COLOR4D color = getRenderColor( aText, aLayer, drawingShadows );
1889
1890 if( m_schematic )
1891 {
1892 SCH_CONNECTION* conn = nullptr;
1893
1894 if( !aText->IsConnectivityDirty() )
1895 conn = aText->Connection();
1896
1897 if( conn && conn->IsBus() )
1898 color = getRenderColor( aText, LAYER_BUS, drawingShadows );
1899 }
1900
1901 if( !( aText->IsVisible() || aText->IsForceVisible() ) )
1902 {
1903 if( !m_schematic || eeconfig()->m_Appearance.show_hidden_fields )
1904 color = getRenderColor( aText, LAYER_HIDDEN, drawingShadows );
1905 else
1906 return;
1907 }
1908
1909 if( drawingDangling )
1910 {
1911 if( aText->IsDangling() )
1912 {
1913 drawDanglingSymbol( aText->GetTextPos(), color,
1914 schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE / 2 ), drawingShadows,
1915 aText->IsBrightened() );
1916 }
1917
1918 return;
1919 }
1920
1921 m_gal->SetStrokeColor( color );
1922 m_gal->SetFillColor( color );
1923
1924 if( drawingShadows )
1925 {
1926 BOX2I bBox = aText->GetBoundingBox();
1927 bBox.Inflate( getTextThickness( aText ) * 2 );
1928 bBox.RevertYAxis();
1929
1930 m_gal->SetIsStroke( false );
1931 m_gal->SetIsFill( true );
1932 m_gal->DrawRectangle( mapCoords( bBox.GetPosition() ), mapCoords( bBox.GetEnd() ) );
1933 }
1934 else
1935 {
1936 wxString shownText( aText->GetShownText() );
1937 VECTOR2I text_offset = aText->GetSchematicTextOffset( &m_schSettings );
1938 TEXT_ATTRIBUTES attrs = aText->GetAttributes();
1939
1940 attrs.m_Angle = aText->GetDrawRotation();
1941 attrs.m_StrokeWidth = getTextThickness( aText );
1942
1943 if( aText->IsHypertext() && aText->IsRollover() )
1944 {
1945 m_gal->SetStrokeColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
1946 m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
1947 attrs.m_Underlined = true;
1948 }
1949
1950 KIFONT::FONT* font = aText->GetFont();
1951
1952 if( !font )
1953 {
1954 font = KIFONT::FONT::GetFont( m_schSettings.GetDefaultFont(), aText->IsBold(),
1955 aText->IsItalic() );
1956 }
1957
1958 // Adjust text drawn in an outline font to more closely mimic the positioning of
1959 // SCH_FIELD text.
1960 if( font->IsOutline() && aText->Type() == SCH_TEXT_T )
1961 {
1962 BOX2I firstLineBBox = aText->GetTextBox( 0 );
1963 int sizeDiff = firstLineBBox.GetHeight() - aText->GetTextSize().y;
1964 int adjust = KiROUND( sizeDiff * 0.4 );
1965 VECTOR2I adjust_offset( 0, - adjust );
1966
1967 RotatePoint( adjust_offset, aText->GetDrawRotation() );
1968 text_offset += adjust_offset;
1969 }
1970
1971 if( nonCached( aText )
1972 && aText->RenderAsBitmap( m_gal->GetWorldScale() )
1973 && !shownText.Contains( wxT( "\n" ) ) )
1974 {
1975 bitmapText( shownText, aText->GetDrawPos() + text_offset, attrs );
1976 const_cast<SCH_TEXT*>( aText )->SetFlags( IS_SHOWN_AS_BITMAP );
1977 }
1978 else
1979 {
1980 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
1981
1982 if( !aText->IsHypertext() && font->IsOutline() )
1983 cache = aText->GetRenderCache( font, shownText, text_offset );
1984
1985 if( cache )
1986 {
1987 for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
1988 m_gal->DrawGlyph( *glyph.get() );
1989 }
1990 else
1991 {
1992 strokeText( shownText, aText->GetDrawPos() + text_offset, attrs );
1993 }
1994
1995 const_cast<SCH_TEXT*>( aText )->ClearFlags( IS_SHOWN_AS_BITMAP );
1996 }
1997 }
1998}
1999
2000
2001void SCH_PAINTER::draw( const SCH_TEXTBOX* aTextBox, int aLayer )
2002{
2003 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2004 COLOR4D color = getRenderColor( aTextBox, aLayer, drawingShadows );
2005 float borderWidth = getLineWidth( aTextBox, drawingShadows );
2006
2007 KIFONT::FONT* font = aTextBox->GetFont();
2008
2009 if( !font )
2010 {
2011 font = KIFONT::FONT::GetFont( m_schSettings.GetDefaultFont(), aTextBox->IsBold(),
2012 aTextBox->IsItalic() );
2013 }
2014
2015 auto drawText =
2016 [&]()
2017 {
2018 wxString shownText = aTextBox->GetShownText();
2019 TEXT_ATTRIBUTES attrs = aTextBox->GetAttributes();
2020
2021 attrs.m_Angle = aTextBox->GetDrawRotation();
2022 attrs.m_StrokeWidth = getTextThickness( aTextBox );
2023
2024 if( aTextBox->IsHypertext() && aTextBox->IsRollover() )
2025 {
2026 m_gal->SetStrokeColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
2027 m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
2028 attrs.m_Underlined = true;
2029 }
2030
2031 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
2032
2033 if( !aTextBox->IsHypertext() && font->IsOutline() )
2034 cache = aTextBox->GetRenderCache( font, shownText );
2035
2036 if( cache )
2037 {
2038 for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
2039 m_gal->DrawGlyph( *glyph.get() );
2040 }
2041 else
2042 {
2043 strokeText( shownText, aTextBox->GetDrawPos(), attrs );
2044 }
2045 };
2046
2047 if( drawingShadows && !( aTextBox->IsBrightened() || aTextBox->IsSelected() ) )
2048 return;
2049
2050 m_gal->SetFillColor( color );
2051 m_gal->SetStrokeColor( color );
2052
2053 if( aLayer == LAYER_SELECTION_SHADOWS )
2054 {
2055 m_gal->SetIsFill( true );
2056 m_gal->SetIsStroke( false );
2057 m_gal->SetLineWidth( borderWidth );
2058
2059 m_gal->DrawRectangle( aTextBox->GetPosition(), aTextBox->GetEnd() );
2060 }
2061 else if( aLayer == LAYER_NOTES_BACKGROUND )
2062 {
2063 if( aTextBox->IsFilled() )
2064 {
2065 m_gal->SetIsFill( true );
2066 m_gal->SetIsStroke( false );
2067 m_gal->SetLineWidth( borderWidth );
2068
2069 m_gal->DrawRectangle( aTextBox->GetPosition(), aTextBox->GetEnd() );
2070 }
2071 }
2072 else if( aLayer == LAYER_NOTES )
2073 {
2074 drawText();
2075
2076 if( borderWidth > 0 )
2077 {
2078 COLOR4D borderColor = aTextBox->GetStroke().GetColor();
2079 PLOT_DASH_TYPE borderStyle = aTextBox->GetEffectiveLineStyle();
2080
2081 if( m_schSettings.m_OverrideItemColors || aTextBox->IsBrightened()
2082 || borderColor == COLOR4D::UNSPECIFIED )
2083 {
2084 borderColor = m_schSettings.GetLayerColor( aLayer );
2085 }
2086
2087 m_gal->SetIsFill( false );
2088 m_gal->SetIsStroke( true );
2089 m_gal->SetStrokeColor( borderColor );
2090 m_gal->SetLineWidth( borderWidth );
2091
2092 if( borderStyle <= PLOT_DASH_TYPE::FIRST_TYPE || drawingShadows )
2093 {
2094 m_gal->DrawRectangle( aTextBox->GetPosition(), aTextBox->GetEnd() );
2095 }
2096 else
2097 {
2098 std::vector<SHAPE*> shapes = aTextBox->MakeEffectiveShapes( true );
2099
2100 for( SHAPE* shape : shapes )
2101 {
2102 STROKE_PARAMS::Stroke( shape, borderStyle, borderWidth, &m_schSettings,
2103 [&]( const VECTOR2I& a, const VECTOR2I& b )
2104 {
2105 // DrawLine has problem with 0 length lines so enforce minimum
2106 if( a == b )
2107 m_gal->DrawLine( a+1, b );
2108 else
2109 m_gal->DrawLine( a, b );
2110 } );
2111 }
2112
2113 for( SHAPE* shape : shapes )
2114 delete shape;
2115 }
2116 }
2117 }
2118}
2119
2120
2121static void orientSymbol( LIB_SYMBOL* symbol, int orientation )
2122{
2123 struct ORIENT
2124 {
2125 int flag;
2126 int n_rots;
2127 int mirror_x;
2128 int mirror_y;
2129 }
2130 orientations[] =
2131 {
2132 { SYM_ORIENT_0, 0, 0, 0 },
2133 { SYM_ORIENT_90, 1, 0, 0 },
2134 { SYM_ORIENT_180, 2, 0, 0 },
2135 { SYM_ORIENT_270, 3, 0, 0 },
2136 { SYM_MIRROR_X + SYM_ORIENT_0, 0, 1, 0 },
2137 { SYM_MIRROR_X + SYM_ORIENT_90, 1, 1, 0 },
2138 { SYM_MIRROR_Y, 0, 0, 1 },
2139 { SYM_MIRROR_X + SYM_ORIENT_270, 3, 1, 0 },
2140 { SYM_MIRROR_Y + SYM_ORIENT_0, 0, 0, 1 },
2141 { SYM_MIRROR_Y + SYM_ORIENT_90, 1, 0, 1 },
2142 { SYM_MIRROR_Y + SYM_ORIENT_180, 2, 0, 1 },
2143 { SYM_MIRROR_Y + SYM_ORIENT_270, 3, 0, 1 }
2144 };
2145
2146 ORIENT o = orientations[ 0 ];
2147
2148 for( ORIENT& i : orientations )
2149 {
2150 if( i.flag == orientation )
2151 {
2152 o = i;
2153 break;
2154 }
2155 }
2156
2157 for( LIB_ITEM& item : symbol->GetDrawItems() )
2158 {
2159 for( int i = 0; i < o.n_rots; i++ )
2160 item.Rotate( VECTOR2I(0, 0 ), true );
2161
2162 if( o.mirror_x )
2163 item.MirrorVertical( VECTOR2I( 0, 0 ) );
2164
2165 if( o.mirror_y )
2166 item.MirrorHorizontal( VECTOR2I( 0, 0 ) );
2167 }
2168}
2169
2170
2171void SCH_PAINTER::draw( const SCH_SYMBOL* aSymbol, int aLayer )
2172{
2173 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2174
2175 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2176 {
2177 for( const SCH_FIELD& field : aSymbol->GetFields() )
2178 draw( &field, aLayer, aSymbol->GetDNP() );
2179 }
2180
2181 if( isFieldsLayer( aLayer ) )
2182 return;
2183
2184 if( drawingShadows && !( aSymbol->IsBrightened() || aSymbol->IsSelected() ) )
2185 {
2186 // Don't exit here; symbol may still have selected pins
2187 // return;
2188 }
2189
2190 int unit = aSymbol->GetUnitSelection( &m_schematic->CurrentSheet() );
2191 int convert = aSymbol->GetConvert();
2192
2193 // Use dummy symbol if the actual couldn't be found (or couldn't be locked).
2194 LIB_SYMBOL* originalSymbol = aSymbol->GetLibSymbolRef() ?
2195 aSymbol->GetLibSymbolRef().get() : dummy();
2196 LIB_PINS originalPins;
2197 originalSymbol->GetPins( originalPins, unit, convert );
2198
2199 // Copy the source so we can re-orient and translate it.
2200 LIB_SYMBOL tempSymbol( *originalSymbol );
2201 LIB_PINS tempPins;
2202 tempSymbol.GetPins( tempPins, unit, convert );
2203
2204 tempSymbol.SetFlags( aSymbol->GetFlags() );
2205
2206 orientSymbol( &tempSymbol, aSymbol->GetOrientation() );
2207
2208 for( LIB_ITEM& tempItem : tempSymbol.GetDrawItems() )
2209 {
2210 tempItem.SetFlags( aSymbol->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED,
2211 tempItem.MoveTo( tempItem.GetPosition() + (VECTOR2I) mapCoords( aSymbol->GetPosition() ) );
2212 }
2213
2214 // Copy the pin info from the symbol to the temp pins
2215 for( unsigned i = 0; i < tempPins.size(); ++ i )
2216 {
2217 SCH_PIN* symbolPin = aSymbol->GetPin( originalPins[ i ] );
2218 LIB_PIN* tempPin = tempPins[ i ];
2219
2220 tempPin->ClearFlags();
2221 tempPin->SetFlags( symbolPin->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED,
2222 // IS_SHOWN_AS_BITMAP
2223
2224 tempPin->SetName( symbolPin->GetShownName() );
2225 tempPin->SetType( symbolPin->GetType() );
2226 tempPin->SetShape( symbolPin->GetShape() );
2227
2228 if( symbolPin->IsDangling() )
2229 tempPin->SetFlags( IS_DANGLING );
2230 else
2231 tempPin->ClearFlags( IS_DANGLING );
2232 }
2233
2234 draw( &tempSymbol, aLayer, false, aSymbol->GetUnit(), aSymbol->GetConvert(),
2235 aSymbol->GetDNP() );
2236
2237 for( unsigned i = 0; i < tempPins.size(); ++i )
2238 {
2239 SCH_PIN* symbolPin = aSymbol->GetPin( originalPins[ i ] );
2240 LIB_PIN* tempPin = tempPins[ i ];
2241
2242 symbolPin->ClearFlags();
2243 tempPin->ClearFlags( IS_DANGLING ); // Clear this temporary flag
2244 symbolPin->SetFlags( tempPin->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED,
2245 // IS_SHOWN_AS_BITMAP
2246 }
2247}
2248
2249
2250void SCH_PAINTER::draw( const SCH_FIELD* aField, int aLayer, bool aDimmed )
2251{
2252 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2253
2254 if( drawingShadows && !( aField->IsBrightened() || aField->IsSelected() ) )
2255 return;
2256
2257 if( !drawingShadows && aField->GetLayer() != aLayer )
2258 return;
2259
2260 aLayer = aField->GetLayer();
2261
2262 COLOR4D color = getRenderColor( aField, aLayer, drawingShadows, aDimmed );
2263
2264 if( !( aField->IsVisible() || aField->IsForceVisible() ) )
2265 {
2266 if( !m_schematic || eeconfig()->m_Appearance.show_hidden_fields )
2267 color = getRenderColor( aField, LAYER_HIDDEN, drawingShadows, aDimmed );
2268 else
2269 return;
2270 }
2271
2272 wxString shownText = aField->GetShownText();
2273
2274 if( shownText.IsEmpty() )
2275 return;
2276
2277 if( drawingShadows && !eeconfig()->m_Selection.draw_selected_children )
2278 return;
2279
2280 // Calculate the text orientation according to the parent orientation.
2281 EDA_ANGLE orient = aField->GetTextAngle();
2282
2283 if( aField->GetParent() && aField->GetParent()->Type() == SCH_SYMBOL_T )
2284 {
2285 if( static_cast<SCH_SYMBOL*>( aField->GetParent() )->GetTransform().y1 )
2286 {
2287 // Rotate symbol 90 degrees.
2288 if( orient.IsHorizontal() )
2289 orient = ANGLE_VERTICAL;
2290 else
2291 orient = ANGLE_HORIZONTAL;
2292 }
2293 }
2294
2295 /*
2296 * Calculate the text justification, according to the symbol orientation/mirror.
2297 * This is a bit complicated due to cumulative calculations:
2298 * - numerous cases (mirrored or not, rotation)
2299 * - the DrawGraphicText function recalculate also H and H justifications according to the
2300 * text orientation.
2301 * - when symbol is mirrored, the text is not mirrored and justifications are complicated
2302 * to calculate so the easier way is to use no justifications (centered text) and use
2303 * GetBoundingBox to know the text coordinate considered as centered
2304 */
2305 BOX2I bbox = aField->GetBoundingBox();
2306
2307 if( aField->GetParent() && aField->GetParent()->Type() == SCH_GLOBAL_LABEL_T )
2308 {
2309 SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( aField->GetParent() );
2310 bbox.Offset( label->GetSchematicTextOffset( &m_schSettings ) );
2311 }
2312
2313 m_gal->SetStrokeColor( color );
2314 m_gal->SetFillColor( color );
2315
2316 if( drawingShadows )
2317 {
2318 BOX2I shadow_box = bbox;
2319 shadow_box.Inflate( getTextThickness( aField ) * 2 );
2320 shadow_box.RevertYAxis();
2321
2322 m_gal->SetIsStroke( false );
2323 m_gal->SetIsFill( true );
2324 m_gal->DrawRectangle( mapCoords( shadow_box.GetPosition() ), mapCoords( shadow_box.GetEnd() ) );
2325 }
2326 else
2327 {
2328 VECTOR2I textpos = bbox.Centre();
2329 TEXT_ATTRIBUTES attributes = aField->GetAttributes();
2330
2331 attributes.m_Halign = GR_TEXT_H_ALIGN_CENTER;
2332 attributes.m_Valign = GR_TEXT_V_ALIGN_CENTER;
2333 attributes.m_StrokeWidth = getTextThickness( aField );
2334 attributes.m_Angle = orient;
2335
2336 if( aField->IsHypertext() && aField->IsRollover() )
2337 {
2338 m_gal->SetStrokeColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
2339 m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
2340 attributes.m_Underlined = true;
2341 }
2342
2343 if( nonCached( aField ) && aField->RenderAsBitmap( m_gal->GetWorldScale() ) )
2344 {
2345 bitmapText( shownText, textpos, attributes );
2346 const_cast<SCH_FIELD*>( aField )->SetFlags( IS_SHOWN_AS_BITMAP );
2347 }
2348 else
2349 {
2350 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
2351
2352 if( !aField->IsHypertext() )
2353 cache = aField->GetRenderCache( shownText, textpos, attributes );
2354
2355 if( cache )
2356 {
2357 for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
2358 m_gal->DrawGlyph( *glyph.get() );
2359 }
2360 else
2361 {
2362 strokeText( shownText, textpos, attributes );
2363 }
2364
2365 const_cast<SCH_FIELD*>( aField )->ClearFlags( IS_SHOWN_AS_BITMAP );
2366 }
2367 }
2368
2369 // Draw the umbilical line
2370 if( aField->IsMoving() )
2371 {
2372 VECTOR2I parentPos = aField->GetParentPosition();
2373
2374 m_gal->SetLineWidth( m_schSettings.m_outlineWidth );
2375 m_gal->SetStrokeColor( getRenderColor( aField, LAYER_SCHEMATIC_ANCHOR, drawingShadows ) );
2376 m_gal->DrawLine( bbox.Centre(), parentPos );
2377 }
2378}
2379
2380
2381void SCH_PAINTER::draw( const SCH_GLOBALLABEL *aLabel, int aLayer )
2382{
2383 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2384
2385 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2386 {
2387 for( const SCH_FIELD& field : aLabel->GetFields() )
2388 draw( &field, aLayer, false );
2389 }
2390
2391 if( isFieldsLayer( aLayer ) )
2392 return;
2393
2394 if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
2395 return;
2396
2397 COLOR4D color = getRenderColor( aLabel, LAYER_GLOBLABEL, drawingShadows );
2398
2399 std::vector<VECTOR2I> pts;
2400 std::deque<VECTOR2D> pts2;
2401
2402 aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() );
2403
2404 for( const VECTOR2I& p : pts )
2405 pts2.emplace_back( VECTOR2D( p.x, p.y ) );
2406
2407 // The text is drawn inside the graphic shape.
2408 // On Cairo the graphic shape is filled by the background before drawing the text.
2409 // However if the text is selected, it is draw twice: first on LAYER_SELECTION_SHADOWS
2410 // and second on the text layer. The second must not erase the first drawing.
2411 bool fillBg = ( ( aLayer == LAYER_SELECTION_SHADOWS ) || !aLabel->IsSelected() )
2412 && aLayer != LAYER_DANGLING;
2413 m_gal->SetIsFill( fillBg );
2414 m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
2415 m_gal->SetIsStroke( true );
2416 m_gal->SetLineWidth( getTextThickness( aLabel ) );
2417 m_gal->SetStrokeColor( color );
2418 m_gal->DrawPolyline( pts2 );
2419
2420 draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer );
2421}
2422
2423
2424void SCH_PAINTER::draw( const SCH_LABEL *aLabel, int aLayer )
2425{
2426 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2427
2428 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2429 {
2430 for( const SCH_FIELD& field : aLabel->GetFields() )
2431 draw( &field, aLayer, false );
2432 }
2433
2434 if( isFieldsLayer( aLayer ) )
2435 return;
2436
2437 if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
2438 return;
2439
2440 draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer );
2441}
2442
2443
2444void SCH_PAINTER::draw( const SCH_HIERLABEL *aLabel, int aLayer )
2445{
2446 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2447
2448 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2449 {
2450 for( const SCH_FIELD& field : aLabel->GetFields() )
2451 draw( &field, aLayer, false );
2452 }
2453
2454 if( isFieldsLayer( aLayer ) )
2455 return;
2456
2457 if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
2458 return;
2459
2460 COLOR4D color = getRenderColor( aLabel, LAYER_HIERLABEL, drawingShadows );
2461
2462 if( m_schematic )
2463 {
2464 SCH_CONNECTION* conn = nullptr;
2465
2466 if( !aLabel->IsConnectivityDirty() )
2467 conn = aLabel->Connection();
2468
2469 if( conn && conn->IsBus() )
2470 color = getRenderColor( aLabel, LAYER_BUS, drawingShadows );
2471 }
2472
2473 std::vector<VECTOR2I> pts;
2474 std::deque<VECTOR2D> pts2;
2475
2476 aLabel->CreateGraphicShape( &m_schSettings, pts, (VECTOR2I)aLabel->GetTextPos() );
2477
2478 for( const VECTOR2I& p : pts )
2479 pts2.emplace_back( VECTOR2D( p.x, p.y ) );
2480
2481 m_gal->SetIsFill( true );
2482 m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
2483 m_gal->SetIsStroke( true );
2484 m_gal->SetLineWidth( getTextThickness( aLabel ) );
2485 m_gal->SetStrokeColor( color );
2486 m_gal->DrawPolyline( pts2 );
2487
2488 draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer );
2489}
2490
2491
2492void SCH_PAINTER::draw( const SCH_DIRECTIVE_LABEL *aLabel, int aLayer )
2493{
2494 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2495
2496 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2497 {
2498 for( const SCH_FIELD& field : aLabel->GetFields() )
2499 draw( &field, aLayer, false );
2500 }
2501
2502 if( isFieldsLayer( aLayer ) )
2503 return;
2504
2505 if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
2506 return;
2507
2508 COLOR4D color = getRenderColor( aLabel, LAYER_NETCLASS_REFS, drawingShadows );
2509
2510 if( aLayer == LAYER_DANGLING )
2511 {
2512 if( aLabel->IsDangling() )
2513 {
2514 drawDanglingSymbol( aLabel->GetTextPos(), color, schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE / 2 ),
2515 drawingShadows, aLabel->IsBrightened() );
2516 }
2517
2518 return;
2519 }
2520
2521 std::vector<VECTOR2I> pts;
2522 std::deque<VECTOR2D> pts2;
2523
2524 aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() );
2525
2526 for( const VECTOR2I& p : pts )
2527 pts2.emplace_back( VECTOR2D( p.x, p.y ) );
2528
2529 m_gal->SetIsFill( false );
2530 m_gal->SetFillColor( color );
2531 m_gal->SetIsStroke( true );
2532 m_gal->SetLineWidth( getLineWidth( aLabel, drawingShadows ) );
2533 m_gal->SetStrokeColor( color );
2534
2535 if( aLabel->GetShape() == LABEL_FLAG_SHAPE::F_DOT )
2536 {
2537 m_gal->DrawLine( pts2[0], pts2[1] );
2538 m_gal->SetIsFill( true );
2539 m_gal->DrawCircle( pts2[2], ( pts2[2] - pts2[1] ).EuclideanNorm() );
2540 }
2541 else if( aLabel->GetShape() == LABEL_FLAG_SHAPE::F_ROUND )
2542 {
2543 m_gal->DrawLine( pts2[0], pts2[1] );
2544 m_gal->DrawCircle( pts2[2], ( pts2[2] - pts2[1] ).EuclideanNorm() );
2545 }
2546 else
2547 {
2548 m_gal->DrawPolyline( pts2 );
2549 }
2550}
2551
2552
2553void SCH_PAINTER::draw( const SCH_SHEET *aSheet, int aLayer )
2554{
2555 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2556
2557 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2558 {
2559 for( const SCH_FIELD& field : aSheet->GetFields() )
2560 draw( &field, aLayer, false );
2561 }
2562
2563 if( aLayer == LAYER_HIERLABEL || aLayer == LAYER_SELECTION_SHADOWS )
2564 {
2565 for( SCH_SHEET_PIN* sheetPin : aSheet->GetPins() )
2566 {
2567 if( drawingShadows )
2568 {
2569 if( ( aSheet->IsBrightened() || aSheet->IsSelected() )
2570 && eeconfig()->m_Selection.draw_selected_children )
2571 {
2572 // fall through to draw
2573 }
2574 else if( sheetPin->IsBrightened() || sheetPin->IsSelected() )
2575 {
2576 // fall through to draw
2577 }
2578 else
2579 {
2580 continue;
2581 }
2582 }
2583
2584 int width = std::max( aSheet->GetPenWidth(), m_schSettings.GetDefaultPenWidth() );
2585 VECTOR2I initial_pos = sheetPin->GetTextPos();
2586 VECTOR2I offset_pos = initial_pos;
2587
2588 // For aesthetic reasons, the SHEET_PIN is drawn with a small offset of width / 2
2589 switch( sheetPin->GetSide() )
2590 {
2591 case SHEET_SIDE::TOP: offset_pos.y += KiROUND( width / 2.0 ); break;
2592 case SHEET_SIDE::BOTTOM: offset_pos.y -= KiROUND( width / 2.0 ); break;
2593 case SHEET_SIDE::RIGHT: offset_pos.x -= KiROUND( width / 2.0 ); break;
2594 case SHEET_SIDE::LEFT: offset_pos.x += KiROUND( width / 2.0 ); break;
2595 default: break;
2596 }
2597
2598 sheetPin->SetTextPos( offset_pos );
2599 draw( static_cast<SCH_HIERLABEL*>( sheetPin ), aLayer );
2600 m_gal->DrawLine( offset_pos, initial_pos );
2601 sheetPin->SetTextPos( initial_pos );
2602 }
2603 }
2604
2605 VECTOR2D pos = aSheet->GetPosition();
2606 VECTOR2D size = aSheet->GetSize();
2607
2608 if( aLayer == LAYER_SHEET_BACKGROUND )
2609 {
2610 m_gal->SetFillColor( getRenderColor( aSheet, LAYER_SHEET_BACKGROUND, true ) );
2611 m_gal->SetIsFill( true );
2612 m_gal->SetIsStroke( false );
2613
2614 m_gal->DrawRectangle( pos, pos + size );
2615 }
2616
2617 if( aLayer == LAYER_SHEET || aLayer == LAYER_SELECTION_SHADOWS )
2618 {
2619 m_gal->SetStrokeColor( getRenderColor( aSheet, LAYER_SHEET, drawingShadows ) );
2620 m_gal->SetIsStroke( true );
2621 m_gal->SetLineWidth( getLineWidth( aSheet, drawingShadows ) );
2622 m_gal->SetIsFill( false );
2623
2624 m_gal->DrawRectangle( pos, pos + size );
2625 }
2626}
2627
2628
2629void SCH_PAINTER::draw( const SCH_NO_CONNECT *aNC, int aLayer )
2630{
2631 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2632
2633 if( drawingShadows && !( aNC->IsBrightened() || aNC->IsSelected() ) )
2634 return;
2635
2636 m_gal->SetIsStroke( true );
2637 m_gal->SetLineWidth( getLineWidth( aNC, drawingShadows ) );
2638 m_gal->SetStrokeColor( getRenderColor( aNC, LAYER_NOCONNECT, drawingShadows ) );
2639 m_gal->SetIsFill( false );
2640
2641 VECTOR2D p = aNC->GetPosition();
2642 int delta = std::max( aNC->GetSize(), m_schSettings.GetDefaultPenWidth() * 3 ) / 2;
2643
2644 m_gal->DrawLine( p + VECTOR2D( -delta, -delta ), p + VECTOR2D( delta, delta ) );
2645 m_gal->DrawLine( p + VECTOR2D( -delta, delta ), p + VECTOR2D( delta, -delta ) );
2646}
2647
2648
2649void SCH_PAINTER::draw( const SCH_BUS_ENTRY_BASE *aEntry, int aLayer )
2650{
2652 SCH_LINE line( VECTOR2I(), layer );
2653 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2654 bool drawingDangling = aLayer == LAYER_DANGLING;
2655
2656 if( drawingShadows && !( aEntry->IsBrightened() || aEntry->IsSelected() ) )
2657 return;
2658
2659 if( aEntry->IsSelected() )
2660 line.SetSelected();
2661 else if( aEntry->IsBrightened() )
2662 line.SetBrightened();
2663
2664 line.SetStartPoint( aEntry->GetPosition() );
2665 line.SetEndPoint( aEntry->GetEnd() );
2666 line.SetStroke( aEntry->GetStroke() );
2667 line.SetLineWidth( getLineWidth( aEntry, drawingShadows ) );
2668
2669 COLOR4D color = getRenderColor( aEntry, LAYER_WIRE, drawingShadows );
2670
2671 if( aEntry->Type() == SCH_BUS_BUS_ENTRY_T )
2672 color = getRenderColor( aEntry, LAYER_BUS, drawingShadows );
2673
2674 if( drawingDangling )
2675 {
2676 m_gal->SetIsFill( false );
2677 m_gal->SetIsStroke( true );
2678 m_gal->SetStrokeColor( color.Brightened( 0.3 ) );
2679 m_gal->SetLineWidth( drawingShadows ? getShadowWidth( aEntry->IsBrightened() )
2680 : m_schSettings.GetDanglineSymbolThickness() );
2681
2682 if( aEntry->IsDanglingStart() )
2683 {
2684 m_gal->DrawCircle( aEntry->GetPosition(),
2685 aEntry->GetPenWidth() + ( TARGET_BUSENTRY_RADIUS / 2 ) );
2686 }
2687
2688 if( aEntry->IsDanglingEnd() )
2689 {
2690 m_gal->DrawCircle( aEntry->GetEnd(),
2691 aEntry->GetPenWidth() + ( TARGET_BUSENTRY_RADIUS / 2 ) );
2692 }
2693 }
2694 else
2695 {
2696 line.SetLineColor( color );
2697 line.SetLineStyle( aEntry->GetLineStyle() );
2698
2699 draw( &line, aLayer );
2700 }
2701}
2702
2703
2704void SCH_PAINTER::draw( const SCH_BITMAP *aBitmap, int aLayer )
2705{
2706 m_gal->Save();
2707 m_gal->Translate( aBitmap->GetPosition() );
2708
2709 // When the image scale factor is not 1.0, we need to modify the actual as the image scale
2710 // factor is similar to a local zoom
2711 double img_scale = aBitmap->GetImageScale();
2712
2713 if( img_scale != 1.0 )
2714 m_gal->Scale( VECTOR2D( img_scale, img_scale ) );
2715
2716 if( aLayer == LAYER_DRAW_BITMAPS )
2717 {
2718 m_gal->DrawBitmap( *aBitmap->GetImage() );
2719 }
2720
2721 if( aLayer == LAYER_SELECTION_SHADOWS )
2722 {
2723 if( aBitmap->IsSelected() || aBitmap->IsBrightened() )
2724 {
2725 COLOR4D color = getRenderColor( aBitmap, LAYER_DRAW_BITMAPS, true );
2726 m_gal->SetIsStroke( true );
2727 m_gal->SetStrokeColor( color );
2728 m_gal->SetLineWidth ( getShadowWidth( aBitmap->IsBrightened() ) );
2729 m_gal->SetIsFill( false );
2730
2731 // Draws a bounding box.
2732 VECTOR2D bm_size( aBitmap->GetSize() );
2733 // bm_size is the actual image size in UI.
2734 // but m_gal scale was previously set to img_scale
2735 // so recalculate size relative to this image size.
2736 bm_size.x /= img_scale;
2737 bm_size.y /= img_scale;
2738 VECTOR2D origin( -bm_size.x / 2.0, -bm_size.y / 2.0 );
2739 VECTOR2D end = origin + bm_size;
2740
2741 m_gal->DrawRectangle( origin, end );
2742 }
2743 }
2744
2745 m_gal->Restore();
2746}
2747
2748
2749void SCH_PAINTER::draw( const SCH_MARKER *aMarker, int aLayer )
2750{
2751 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2752
2753 if( drawingShadows && !( aMarker->IsBrightened() || aMarker->IsSelected() ) )
2754 return;
2755
2756 COLOR4D color = getRenderColor( aMarker, aMarker->GetColorLayer(), drawingShadows );
2757
2758 m_gal->Save();
2759 m_gal->Translate( aMarker->GetPosition() );
2760 m_gal->SetIsFill( !drawingShadows );
2761 m_gal->SetFillColor( color );
2762 m_gal->SetIsStroke( drawingShadows );
2763 m_gal->SetLineWidth( getLineWidth( aMarker, drawingShadows ) );
2764 m_gal->SetStrokeColor( color );
2765
2766 SHAPE_LINE_CHAIN polygon;
2767 aMarker->ShapeToPolygon( polygon );
2768
2769 m_gal->DrawPolygon( polygon );
2770 m_gal->Restore();
2771}
2772
2773
2774}; // namespace KIGFX
int color
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
double square(double x)
double m_MinPlotPenWidth
Sets an absolute minimum pen width for plotting.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:119
const Vec & GetPosition() const
Definition: box2.h:184
const Vec & GetOrigin() const
Definition: box2.h:183
void Offset(coord_type dx, coord_type dy)
Definition: box2.h:224
void RevertYAxis()
Mirror the rectangle from the X axis (negate Y pos and size).
Definition: box2.h:689
void SetX(coord_type val)
Definition: box2.h:235
void SetY(coord_type val)
Definition: box2.h:240
coord_type GetTop() const
Definition: box2.h:194
coord_type GetHeight() const
Definition: box2.h:188
coord_type GetY() const
Definition: box2.h:181
coord_type GetWidth() const
Definition: box2.h:187
const Vec GetEnd() const
Definition: box2.h:185
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
coord_type GetX() const
Definition: box2.h:180
Vec Centre() const
Definition: box2.h:70
coord_type GetRight() const
Definition: box2.h:189
coord_type GetLeft() const
Definition: box2.h:193
const BOX2< Vec > GetBoundingBoxRotated(const VECTOR2I &aRotCenter, const EDA_ANGLE &aAngle) const
Useful to calculate bounding box of rotated items, when rotation is not cardinal.
Definition: box2.h:650
coord_type GetBottom() const
Definition: box2.h:190
Color settings are a bit different than most of the settings objects in that there can be more than o...
bool GetOverrideSchItemColors() const
COLOR4D GetColor(int aLayer) const
bool IsHorizontal() const
Definition: eda_angle.h:174
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:142
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:143
bool IsSelected() const
Definition: eda_item.h:107
void SetSelected()
Definition: eda_item.h:118
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition: eda_item.h:183
void SetBrightened()
Definition: eda_item.h:119
EDA_ITEM * GetParent() const
Definition: eda_item.h:99
bool IsRollover() const
Definition: eda_item.h:112
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:145
bool IsBrightened() const
Definition: eda_item.h:110
virtual wxString GetClass() const =0
Return the class name.
bool IsForceVisible() const
Definition: eda_item.h:203
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:144
bool IsMoving() const
Definition: eda_item.h:104
bool IsNew() const
Definition: eda_item.h:103
FILL_T GetFillMode() const
Definition: eda_shape.h:101
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition: eda_shape.h:285
bool IsFilled() const
Definition: eda_shape.h:90
void CalcArcAngles(EDA_ANGLE &aStartAngle, EDA_ANGLE &aEndAngle) const
Calc arc start and end angles such that aStartAngle < aEndAngle.
Definition: eda_shape.cpp:458
int GetRadius() const
Definition: eda_shape.cpp:479
SHAPE_T GetShape() const
Definition: eda_shape.h:111
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:141
COLOR4D GetFillColor() const
Definition: eda_shape.h:103
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:72
BOX2I GetTextBox(int aLine=-1, bool aInvertY=false) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:503
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:201
COLOR4D GetTextColor() const
Definition: eda_text.h:198
bool IsItalic() const
Definition: eda_text.h:123
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:120
virtual bool IsVisible() const
Definition: eda_text.h:129
KIFONT::FONT * GetFont() const
Definition: eda_text.h:181
std::vector< std::unique_ptr< KIFONT::GLYPH > > * GetRenderCache(const KIFONT::FONT *aFont, const wxString &forResolvedText, const VECTOR2I &aOffset={ 0, 0 }) const
Definition: eda_text.cpp:451
virtual EDA_ANGLE GetDrawRotation() const
Definition: eda_text.h:310
virtual VECTOR2I GetDrawPos() const
Definition: eda_text.h:311
const TEXT_ATTRIBUTES & GetAttributes() const
Definition: eda_text.h:165
bool IsBold() const
Definition: eda_text.h:126
virtual wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const
Return the string actually shown after processing of the base text.
Definition: eda_text.h:98
VECTOR2I GetTextSize() const
Definition: eda_text.h:189
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:93
FONT is an abstract base class for both outline and stroke fonts.
Definition: font.h:105
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false)
Definition: font.cpp:65
void Draw(KIGFX::GAL *aGal, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aCursor, const TEXT_ATTRIBUTES &aAttrs) const
Draw a string.
Definition: font.cpp:159
virtual bool IsStroke() const
Definition: font.h:112
virtual bool IsOutline() const
Definition: font.h:113
VECTOR2I StringBoundaryLimits(const wxString &aText, const VECTOR2I &aSize, int aThickness, bool aBold, bool aItalic) const
Compute the boundary limits of aText (the bounding box of all shapes).
Definition: font.cpp:271
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
COLOR4D Brightened(double aFactor) const
Return a color that is brighter by a given factor, without modifying object.
Definition: color4d.h:278
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition: color4d.h:390
COLOR4D Mix(const COLOR4D &aColor, double aFactor) const
Return a color that is mixed with the input by a factor.
Definition: color4d.h:305
Abstract interface for drawing on a 2D-surface.
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
virtual void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a rectangle.
void SetVerticalJustify(const GR_TEXT_V_ALIGN_T aVerticalJustify)
void SetHorizontalJustify(const GR_TEXT_H_ALIGN_T aHorizontalJustify)
const MATRIX3x3D & GetScreenWorldMatrix() const
Get the screen <-> world transformation matrix.
virtual void SetLineWidth(float aLineWidth)
Set the line width.
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
void SetGlyphSize(const VECTOR2I aSize)
Contains all the knowledge about how to draw graphical object onto any particular output device.
Definition: painter.h:58
GAL * m_gal
Instance of graphic abstraction layer that gives an interface to call commands used to draw (eg.
Definition: painter.h:101
void SetDefaultPenWidth(int aWidth)
void SetGapLengthRatio(double aRatio)
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
void SetDashLengthRatio(double aRatio)
COLOR4D m_layerColors[LAYER_ID_COUNT]
bool GetDrawBoundingBoxes() const
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.
float getShadowWidth(bool aForHighlight) const
void draw(const EDA_ITEM *, int, bool aDimmed)
bool isUnitAndConversionShown(const LIB_ITEM *aItem) const
static std::vector< KICAD_T > g_ScaledSelectionTypes
Definition: sch_painter.h:201
COLOR4D getRenderColor(const EDA_ITEM *aItem, int aLayer, bool aDrawingShadows, bool aDimmed=false) const
SCH_RENDER_SETTINGS m_schSettings
Definition: sch_painter.h:204
bool nonCached(const EDA_ITEM *aItem)
SCH_PAINTER(GAL *aGal)
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...
void LoadColors(const COLOR_SETTINGS *aSettings) override
bool GetShowPageLimits() const override
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:77
static constexpr int VIEW_MAX_LAYERS
Rendering order modifier for layers that are marked as top layers.
Definition: view.h:720
Field object used in symbol libraries.
Definition: lib_field.h:60
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:444
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: lib_field.cpp:419
wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
Definition: lib_field.cpp:408
The base class for drawable items used by schematic library symbols.
Definition: lib_item.h:61
bool IsPrivate() const
Definition: lib_item.h:279
virtual int GetPenWidth() const =0
int GetUnit() const
Definition: lib_item.h:273
int GetConvert() const
Definition: lib_item.h:276
LIB_SYMBOL * GetParent() const
Definition: lib_item.h:168
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: lib_pin.h:78
int GetLength() const
Definition: lib_pin.h:80
ELECTRICAL_PINTYPE GetType() const
Definition: lib_pin.h:90
int GetOrientation() const
Definition: lib_pin.h:74
void SetName(const wxString &aName)
Definition: lib_pin.h:114
void SetType(ELECTRICAL_PINTYPE aType)
Definition: lib_pin.h:91
wxString GetShownNumber() const
Definition: lib_pin.h:123
int GetNumberTextSize() const
Definition: lib_pin.h:135
wxString GetShownName() const
Definition: lib_pin.cpp:175
VECTOR2I GetPosition() const override
Definition: lib_pin.h:222
wxString const GetElectricalTypeName() const
Definition: lib_pin.h:98
GRAPHIC_PINSHAPE GetShape() const
Definition: lib_pin.h:77
bool IsVisible() const
Definition: lib_pin.h:103
int GetNameTextSize() const
Definition: lib_pin.h:132
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:197
STROKE_PARAMS GetStroke() const
Definition: lib_shape.h:52
VECTOR2I GetPosition() const override
Definition: lib_shape.h:85
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const override
Make a set of SHAPE objects representing the LIB_SHAPE.
Definition: lib_shape.h:96
Define a library symbol object.
Definition: lib_symbol.h:98
int GetPinNameOffset() const
Definition: lib_symbol.h:628
bool IsAlias() const
Definition: lib_symbol.h:183
bool ShowPinNames() const
Definition: lib_symbol.h:636
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:519
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:816
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:856
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:460
bool ShowPinNumbers() const
Definition: lib_symbol.h:644
VECTOR2I GetDrawPos() const override
wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
Define a symbol library graphical text item.
Definition: lib_text.h:40
const BOX2I GetBoundingBox() const override
Definition: lib_text.cpp:426
void ShapeToPolygon(SHAPE_LINE_CHAIN &aPolygon, int aScale=-1) const
Return the shape polygon in internal units in a SHAPE_LINE_CHAIN the coordinates are relatives to the...
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
Definition: matrix3x3.h:265
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:41
double GetImageScale() const
Definition: sch_bitmap.h:66
VECTOR2I GetPosition() const override
Definition: sch_bitmap.h:136
BITMAP_BASE * GetImage() const
Definition: sch_bitmap.h:54
VECTOR2I GetSize() const
Definition: sch_bitmap.cpp:125
Base class for a bus or wire entry.
Definition: sch_bus_entry.h:38
PLOT_DASH_TYPE GetLineStyle() const
VECTOR2I GetPosition() const override
bool IsDanglingStart() const
Definition: sch_bus_entry.h:43
virtual STROKE_PARAMS GetStroke() const override
Definition: sch_bus_entry.h:77
bool IsDanglingEnd() const
Definition: sch_bus_entry.h:44
VECTOR2I GetEnd() const
Class for a wire to bus entry.
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
bool IsBus() const
void CreateGraphicShape(const RENDER_SETTINGS *aSettings, std::vector< VECTOR2I > &aPoints, const VECTOR2I &aPos) const override
Calculate the graphic shape (a polygon) associated to the text.
Definition: sch_label.cpp:1114
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:50
wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
Definition: sch_field.cpp:169
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_field.cpp:462
bool IsHypertext() const override
Allow items to support hypertext actions when hovered/clicked.
Definition: sch_field.h:92
std::vector< std::unique_ptr< KIFONT::GLYPH > > * GetRenderCache(const wxString &forResolvedText, const VECTOR2I &forPosition, TEXT_ATTRIBUTES &aAttrs) const
Definition: sch_field.cpp:295
VECTOR2I GetParentPosition() const
Definition: sch_field.cpp:1086
void CreateGraphicShape(const RENDER_SETTINGS *aRenderSettings, std::vector< VECTOR2I > &aPoints, const VECTOR2I &aPos) const override
Calculate the graphic shape (a polygon) associated to the text.
Definition: sch_label.cpp:1447
VECTOR2I GetSchematicTextOffset(const RENDER_SETTINGS *aSettings) const override
This offset depends on the orientation, the type of text, and the area required to draw the associate...
Definition: sch_label.cpp:1271
void CreateGraphicShape(const RENDER_SETTINGS *aSettings, std::vector< VECTOR2I > &aPoints, const VECTOR2I &aPos) const override
Calculate the graphic shape (a polygon) associated to the text.
Definition: sch_label.cpp:1543
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
virtual int GetPenWidth() const
Definition: sch_item.h:263
virtual bool IsDangling() const
Definition: sch_item.h:342
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:246
bool RenderAsBitmap(double aWorldScale) const override
Definition: sch_item.cpp:294
bool IsConnectivityDirty() const
Definition: sch_item.h:413
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:146
int GetEffectiveDiameter() const
VECTOR2I GetPosition() const override
Definition: sch_junction.h:102
bool IsDangling() const override
Definition: sch_label.h:177
LABEL_FLAG_SHAPE GetShape() const override
Definition: sch_label.h:73
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:90
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
void SetStartPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:133
bool IsWire() const
Return true if the line is a wire.
Definition: sch_line.cpp:925
bool IsStartDangling() const
Definition: sch_line.h:236
void SetLineColor(const COLOR4D &aColor)
Definition: sch_line.cpp:213
void SetLineWidth(const int aSize)
Definition: sch_line.cpp:285
VECTOR2I GetEndPoint() const
Definition: sch_line.h:137
VECTOR2I GetStartPoint() const
Definition: sch_line.h:132
bool IsEndDangling() const
Definition: sch_line.h:237
void SetLineStyle(const PLOT_DASH_TYPE aStyle)
Definition: sch_line.cpp:256
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: sch_line.h:171
PLOT_DASH_TYPE GetEffectiveLineStyle() const
Definition: sch_line.cpp:272
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:138
SCH_LAYER_ID GetColorLayer() const
Definition: sch_marker.cpp:136
VECTOR2I GetPosition() const override
Definition: sch_marker.h:104
int GetSize() const
VECTOR2I GetPosition() const override
bool IsDangling() const override
Definition: sch_pin.h:103
wxString GetShownName() const
Definition: sch_pin.cpp:94
GRAPHIC_PINSHAPE GetShape() const
Definition: sch_pin.cpp:126
ELECTRICAL_PINTYPE GetType() const
Definition: sch_pin.cpp:117
PLOT_DASH_TYPE GetEffectiveLineStyle() const
Definition: sch_shape.h:67
VECTOR2I GetCenter() const
Definition: sch_shape.h:80
STROKE_PARAMS GetStroke() const override
Definition: sch_shape.h:64
VECTOR2I GetPosition() const override
Definition: sch_shape.h:77
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:66
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:55
int GetPenWidth() const override
Definition: sch_sheet.cpp:578
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:91
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:365
wxSize GetSize() const
Definition: sch_sheet.h:105
KIGFX::COLOR4D GetBorderColor() const
Definition: sch_sheet.h:111
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:172
KIGFX::COLOR4D GetBackgroundColor() const
Definition: sch_sheet.h:114
Schematic symbol object.
Definition: sch_symbol.h:80
int GetUnit() const
Definition: sch_symbol.h:225
int GetConvert() const
Definition: sch_symbol.h:267
VECTOR2I GetPosition() const override
Definition: sch_symbol.h:718
TRANSFORM & GetTransform()
Definition: sch_symbol.h:275
int GetOrientation() const
Get the display symbol orientation.
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
Definition: sch_symbol.cpp:728
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:931
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:189
BOX2I GetBodyBoundingBox() const
Return a bounding box for the symbol body but not the pins or fields.
bool GetDNP() const
Definition: sch_symbol.h:751
VECTOR2I GetDrawPos() const override
bool IsHypertext() const override
Allow items to support hypertext actions when hovered/clicked.
Definition: sch_textbox.h:60
wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
bool IsHypertext() const override
Allow items to support hypertext actions when hovered/clicked.
Definition: sch_text.h:133
wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
Definition: sch_text.cpp:342
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_text.cpp:321
virtual VECTOR2I 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:134
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const std::vector< VECTOR2I > & CPoints() const
An abstract shape on 2D plane.
Definition: shape.h:123
static void Stroke(const SHAPE *aShape, PLOT_DASH_TYPE aLineStyle, int aWidth, const KIGFX::RENDER_SETTINGS *aRenderSettings, std::function< void(const VECTOR2I &a, const VECTOR2I &b)> aStroker)
KIGFX::COLOR4D GetColor() const
PLOT_DASH_TYPE GetPlotStyle() const
GR_TEXT_H_ALIGN_T m_Halign
GR_TEXT_V_ALIGN_T m_Valign
KIFONT::FONT * m_Font
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:47
int y1
Definition: transform.h:50
bool MapAngles(EDA_ANGLE *aAngle1, EDA_ANGLE *aAngle2) const
Calculate new angles according to the transform.
Definition: transform.cpp:78
@ LIGHTRED
Definition: color4d.h:65
#define DEFAULT_LABEL_SIZE_RATIO
The offset of the pin name string from the end of the pin in mils.
#define DANGLING_SYMBOL_SIZE
< The size of the rectangle indicating an unconnected wire or label
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
#define DEFAULT_TEXT_OFFSET_RATIO
Ratio of the font height to space around global labels.
#define DEFAULT_TEXT_SIZE
Ratio of the font height to the baseline of the text above the wire.
static constexpr EDA_ANGLE & ANGLE_HORIZONTAL
Definition: eda_angle.h:408
static constexpr EDA_ANGLE & ANGLE_VERTICAL
Definition: eda_angle.h:409
#define IS_SHOWN_AS_BITMAP
#define ENDPOINT
ends. (Used to support dragging.)
#define IS_DANGLING
indicates a pin is dangling
#define STARTPOINT
When a line is selected, these flags indicate which.
@ FILLED_WITH_COLOR
@ FILLED_WITH_BG_BODYCOLOR
@ FILLED_SHAPE
int Clamp_Text_PenSize(int aPenSize, int aSize, bool aStrict)
Pen width should not allow characters to become cluttered up in their own fatness.
Definition: gr_text.cpp:75
@ GAL_LAYER_ID_START
Definition: layer_ids.h:191
@ LAYER_DRAW_BITMAPS
to handle and draw images bitmaps
Definition: layer_ids.h:223
@ GAL_LAYER_ID_END
Definition: layer_ids.h:260
@ LAYER_AUX_ITEMS
Auxiliary items (guides, rule, etc)
Definition: layer_ids.h:222
SCH_LAYER_ID
Eeschema drawing layers.
Definition: layer_ids.h:341
@ LAYER_DANGLING
Definition: layer_ids.h:368
@ LAYER_SHEETNAME
Definition: layer_ids.h:363
@ LAYER_SCHEMATIC_ANCHOR
Definition: layer_ids.h:386
@ LAYER_SHEETLABEL
Definition: layer_ids.h:366
@ LAYER_PINNUM
Definition: layer_ids.h:350
@ LAYER_DEVICE
Definition: layer_ids.h:357
@ LAYER_SHEET_BACKGROUND
Definition: layer_ids.h:373
@ LAYER_BRIGHTENED
Definition: layer_ids.h:379
@ LAYER_HIDDEN
Definition: layer_ids.h:380
@ LAYER_HIERLABEL
Definition: layer_ids.h:349
@ LAYER_PINNAM
Definition: layer_ids.h:351
@ LAYER_PRIVATE_NOTES
Definition: layer_ids.h:359
@ LAYER_HOVERED
Definition: layer_ids.h:378
@ LAYER_GLOBLABEL
Definition: layer_ids.h:348
@ LAYER_WIRE
Definition: layer_ids.h:344
@ LAYER_NOTES
Definition: layer_ids.h:358
@ LAYER_PIN
Definition: layer_ids.h:361
@ LAYER_VALUEPART
Definition: layer_ids.h:353
@ LAYER_BUS
Definition: layer_ids.h:345
@ SCH_LAYER_ID_END
Definition: layer_ids.h:388
@ LAYER_FIELDS
Definition: layer_ids.h:354
@ LAYER_DEVICE_BACKGROUND
Definition: layer_ids.h:372
@ SCH_LAYER_ID_START
Definition: layer_ids.h:342
@ LAYER_LOCLABEL
Definition: layer_ids.h:347
@ LAYER_SHEETFIELDS
Definition: layer_ids.h:365
@ LAYER_REFERENCEPART
Definition: layer_ids.h:352
@ LAYER_NETCLASS_REFS
Definition: layer_ids.h:356
@ LAYER_NOTES_BACKGROUND
Definition: layer_ids.h:360
@ LAYER_SHEET
Definition: layer_ids.h:362
@ LAYER_SELECTION_SHADOWS
Definition: layer_ids.h:381
@ LAYER_SCHEMATIC_BACKGROUND
Definition: layer_ids.h:376
@ LAYER_SCHEMATIC_AUX_ITEMS
Definition: layer_ids.h:385
@ LAYER_INTERSHEET_REFS
Definition: layer_ids.h:355
@ LAYER_SHEETFILENAME
Definition: layer_ids.h:364
@ LAYER_NOCONNECT
Definition: layer_ids.h:367
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:54
#define PIN_TEXT_MARGIN
Definition: lib_pin.cpp:41
static int externalPinDecoSize(const RENDER_SETTINGS *aSettings, const LIB_PIN &aPin)
Utility for getting the size of the 'external' pin decorators (as a radius)
Definition: lib_pin.cpp:86
static int internalPinDecoSize(const RENDER_SETTINGS *aSettings, const LIB_PIN &aPin)
Utility for getting the size of the 'internal' pin decorators (as a radius)
Definition: lib_pin.cpp:73
@ PIN_LEFT
Definition: lib_pin.h:46
@ PIN_RIGHT
Definition: lib_pin.h:45
@ PIN_UP
Definition: lib_pin.h:47
@ PIN_DOWN
Definition: lib_pin.h:48
#define TARGET_PIN_RADIUS
Definition: lib_pin.h:35
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:120
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:266
static LIB_SYMBOL * dummy()
Used when a LIB_SYMBOL is not found in library to draw a dummy shape.
EESCHEMA_SETTINGS * eeconfig()
Definition: sch_painter.cpp:71
static VECTOR2D mapCoords(const VECTOR2D &aCoord)
static bool isFieldsLayer(int aLayer)
static void orientSymbol(LIB_SYMBOL *symbol, int orientation)
@ OUTSIDE
Text appears outside the dimension line (default)
@ PT_NC
not connected (must be left open)
#define IU_PER_MILS
Definition: plotter.cpp:128
#define TARGET_BUSENTRY_RADIUS
Definition: sch_bus_entry.h:31
@ SYM_ORIENT_270
@ SYM_MIRROR_Y
@ SYM_ORIENT_180
@ SYM_MIRROR_X
@ SYM_ORIENT_90
@ SYM_ORIENT_0
#define BITMAP_FONT_SIZE_THRESHOLD
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:74
@ F_DOT
Definition: sch_text.h:104
@ F_ROUND
Definition: sch_text.h:105
wxString UnescapeString(const wxString &aSource)
PLOT_DASH_TYPE
Dashed line types.
Definition: stroke_params.h:48
const double IU_PER_MM
Definition: base_units.h:77
const double IU_PER_MILS
Definition: base_units.h:78
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
Definition for symbol library class.
constexpr int delta
GR_TEXT_H_ALIGN_T
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
GR_TEXT_V_ALIGN_T
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129
@ SCH_LINE_T
Definition: typeinfo.h:146
@ LIB_SYMBOL_T
Definition: typeinfo.h:198
@ SCH_NO_CONNECT_T
Definition: typeinfo.h:143
@ LIB_TEXT_T
Definition: typeinfo.h:201
@ SCH_SYMBOL_T
Definition: typeinfo.h:156
@ LIB_TEXTBOX_T
Definition: typeinfo.h:202
@ SCH_FIELD_T
Definition: typeinfo.h:155
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:154
@ SCH_LABEL_T
Definition: typeinfo.h:151
@ SCH_SHEET_T
Definition: typeinfo.h:158
@ LIB_SHAPE_T
Definition: typeinfo.h:200
@ SCH_MARKER_T
Definition: typeinfo.h:141
@ SCH_SHAPE_T
Definition: typeinfo.h:147
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:153
@ SCH_BUS_BUS_ENTRY_T
Definition: typeinfo.h:145
@ LIB_PIN_T
Definition: typeinfo.h:203
@ SCH_LABEL_LOCATE_ANY_T
Definition: typeinfo.h:175
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:157
@ SCH_TEXT_T
Definition: typeinfo.h:150
@ LIB_FIELD_T
Definition: typeinfo.h:209
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:144
@ SCH_BITMAP_T
Definition: typeinfo.h:148
@ SCH_TEXTBOX_T
Definition: typeinfo.h:149
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:152
@ SCH_JUNCTION_T
Definition: typeinfo.h:142
@ SCH_PIN_T
Definition: typeinfo.h:159
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< double > VECTOR2D
Definition: vector2d.h:617
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618