KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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 <trigo.h>
29#include <bitmap_base.h>
30#include <connection_graph.h>
32#include <callback_gal.h>
34#include <geometry/shape_rect.h>
36#include <gr_text.h>
37#include <sch_pin.h>
38#include <math/util.h>
39#include <pin_layout_cache.h>
40#include <pgm_base.h>
41#include <sch_bitmap.h>
42#include <sch_bus_entry.h>
43#include <sch_symbol.h>
44#include <sch_edit_frame.h>
45#include <sch_field.h>
46#include <sch_junction.h>
47#include <sch_line.h>
48#include <sch_shape.h>
49#include <sch_marker.h>
50#include <sch_no_connect.h>
51#include <sch_sheet.h>
52#include <sch_sheet_pin.h>
53#include <sch_text.h>
54#include <sch_textbox.h>
55#include <sch_table.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>
63#include <stroke_params.h>
64#include "sch_painter.h"
65#include "common.h"
66
68
69namespace KIGFX
70{
71
73{
74 return dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
75}
76
77
78std::vector<KICAD_T> SCH_PAINTER::g_ScaledSelectionTypes = {
97};
98
99
101 KIGFX::PAINTER( aGal ),
102 m_schematic( nullptr )
103{ }
104
105
106bool SCH_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer )
107{
108 const EDA_ITEM* item = dynamic_cast<const EDA_ITEM*>( aItem );
109
110 if( !item )
111 return false;
112
113 draw( item, aLayer, false );
114
115 return false;
116}
117
118void SCH_PAINTER::draw( const EDA_ITEM* aItem, int aLayer, bool aDimmed )
119{
120
121#ifdef CONNECTIVITY_DEBUG
122
123 auto sch_item = dynamic_cast<const SCH_ITEM*>( aItem );
124 auto conn = sch_item ? sch_item->Connection( *g_CurrentSheet ) : nullptr;
125
126 if( conn )
127 {
128 auto pos = aItem->GetBoundingBox().Centre();
129 auto label = conn->Name( true );
130
134 m_gal->SetLineWidth( Mils2ui( 2 ) );
135 m_gal->SetGlyphSize( VECTOR2D( Mils2ui( 20 ), Mils2ui( 20 ) ) );
136 m_gal->StrokeText( *m_gal, conn->Name( true ), pos, 0.0, 0 );
137 }
138
139#endif
140
141 // Enable draw bounding box on request. Some bboxes are handled locally.
142 bool drawBoundingBox = m_schSettings.GetDrawBoundingBoxes();
143
144 switch( aItem->Type() )
145 {
146 case LIB_SYMBOL_T:
147 draw( static_cast<const LIB_SYMBOL*>( aItem ), aLayer );
148 break;
149 case SCH_PIN_T:
150 drawBoundingBox = false;
151 draw( static_cast<const SCH_PIN*>( aItem ), aLayer, aDimmed );
152 break;
153 case SCH_SYMBOL_T:
154 draw( static_cast<const SCH_SYMBOL*>( aItem ), aLayer );
155 break;
156 case SCH_JUNCTION_T:
157 draw( static_cast<const SCH_JUNCTION*>( aItem ), aLayer );
158 break;
159 case SCH_LINE_T:
160 draw( static_cast<const SCH_LINE*>( aItem ), aLayer );
161 break;
162 case SCH_SHAPE_T:
163 draw( static_cast<const SCH_SHAPE*>( aItem ), aLayer, aDimmed );
164 break;
165 case SCH_RULE_AREA_T:
166 draw( static_cast<const SCH_SHAPE*>( aItem ), aLayer, aDimmed );
167 break;
168 case SCH_TEXT_T:
169 draw( static_cast<const SCH_TEXT*>( aItem ), aLayer, aDimmed );
170 break;
171 case SCH_TEXTBOX_T:
172 draw( static_cast<const SCH_TEXTBOX*>( aItem ), aLayer, aDimmed );
173 break;
174 case SCH_TABLE_T:
175 draw( static_cast<const SCH_TABLE*>( aItem ), aLayer, aDimmed );
176 break;
177 case SCH_LABEL_T:
178 draw( static_cast<const SCH_LABEL*>( aItem ), aLayer );
179 break;
181 draw( static_cast<const SCH_DIRECTIVE_LABEL*>( aItem ), aLayer );
182 break;
183 case SCH_FIELD_T:
184 draw( static_cast<const SCH_FIELD*>( aItem ), aLayer, aDimmed );
185 break;
186 case SCH_HIER_LABEL_T:
187 draw( static_cast<const SCH_HIERLABEL*>( aItem ), aLayer, aDimmed );
188 break;
190 draw( static_cast<const SCH_GLOBALLABEL*>( aItem ), aLayer );
191 break;
192 case SCH_SHEET_T:
193 draw( static_cast<const SCH_SHEET*>( aItem ), aLayer );
194 break;
195 case SCH_SHEET_PIN_T:
196 draw( static_cast<const SCH_HIERLABEL*>( aItem ), aLayer, aDimmed );
197 break;
198 case SCH_NO_CONNECT_T:
199 draw( static_cast<const SCH_NO_CONNECT*>( aItem ), aLayer );
200 break;
202 draw( static_cast<const SCH_BUS_ENTRY_BASE*>( aItem ), aLayer );
203 break;
205 draw( static_cast<const SCH_BUS_ENTRY_BASE*>( aItem ), aLayer );
206 break;
207 case SCH_BITMAP_T:
208 draw( static_cast<const SCH_BITMAP*>( aItem ), aLayer );
209 break;
210 case SCH_MARKER_T:
211 draw( static_cast<const SCH_MARKER*>( aItem ), aLayer );
212 break;
213
214 default: return;
215 }
216
217 if( drawBoundingBox )
218 drawItemBoundingBox( aItem );
219}
220
221
223{
224 if( const SCH_ITEM* item = dynamic_cast<const SCH_ITEM*>( aItem ) )
225 {
226 if( item->IsPrivate() && !m_schSettings.m_IsSymbolEditor )
227 return;
228 }
229
230 BOX2I box = aItem->GetBoundingBox();
231
232 if( aItem->Type() == SCH_SYMBOL_T )
233 box = static_cast<const SCH_SYMBOL*>( aItem )->GetBodyBoundingBox();
234
235 m_gal->SetIsFill( false );
236 m_gal->SetIsStroke( true );
237 m_gal->SetStrokeColor( aItem->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 )
238 : COLOR4D( 0.2, 0.2, 0.2, 1 ) );
240 m_gal->DrawRectangle( box.GetOrigin(), box.GetEnd() );
241}
242
243
245{
246 // TODO: it would be nice to have a more definitive test for this, but we've currently got
247 // no access to the VIEW_GROUP to see if it's cached or not.
248 return aItem->IsSelected();
249}
250
251
253{
254 if( m_schSettings.m_ShowUnit // showing a specific unit
255 && aItem->GetUnit() // item is unit-specific
256 && aItem->GetUnit() != m_schSettings.m_ShowUnit )
257 {
258 return false;
259 }
260
261 if( m_schSettings.m_ShowBodyStyle // showing a specific body style
262 && aItem->GetBodyStyle() // item is body-style-specific
264 {
265 return false;
266 }
267
268 return true;
269}
270
271
273{
274 if( KIFONT::FONT* font = aItem->GetFont() )
275 return font;
276
278 aItem->IsItalic() );
279}
280
281
282float SCH_PAINTER::getShadowWidth( bool aForHighlight ) const
283{
284 const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
285
286 int milsWidth = aForHighlight ? eeconfig()->m_Selection.highlight_thickness
288
289 // For best visuals the selection width must be a cross between the zoom level and the
290 // default line width.
291 return (float) std::fabs( matrix.GetScale().x * milsWidth ) + schIUScale.MilsToIU( milsWidth );
292}
293
294
295COLOR4D SCH_PAINTER::getRenderColor( const SCH_ITEM* aItem, int aLayer, bool aDrawingShadows,
296 bool aDimmed ) const
297{
299 // Graphic items of a SYMBOL frequently use the LAYER_DEVICE layer color
300 // (i.e. when no specific color is set)
301 bool isSymbolChild = aItem->GetParentSymbol() != nullptr;
302
304 {
305 if( aItem->Type() == SCH_LINE_T )
306 {
307 color = static_cast<const SCH_LINE*>( aItem )->GetLineColor();
308 }
309 else if( aItem->Type() == SCH_BUS_WIRE_ENTRY_T )
310 {
311 color = static_cast<const SCH_BUS_WIRE_ENTRY*>( aItem )->GetBusEntryColor();
312 }
313 else if( aItem->Type() == SCH_JUNCTION_T )
314 {
315 color = static_cast<const SCH_JUNCTION*>( aItem )->GetJunctionColor();
316 }
317 else if( aItem->Type() == SCH_SHEET_T )
318 {
319 const SCH_SHEET* sheet = static_cast<const SCH_SHEET*>( aItem );
320
321 if( aLayer == LAYER_SHEET_BACKGROUND )
322 color = sheet->GetBackgroundColor();
323 else
324 color = sheet->GetBorderColor();
325 }
326 else if( aItem->Type() == SCH_SHAPE_T || aItem->Type() == SCH_RULE_AREA_T )
327 {
328 const SCH_SHAPE* shape = static_cast<const SCH_SHAPE*>( aItem );
329
330 if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_NOTES_BACKGROUND
331 || aLayer == LAYER_SHAPES_BACKGROUND )
332 {
333 if( !isSymbolChild || shape->GetFillColor() != COLOR4D::UNSPECIFIED )
334 color = shape->GetFillColor();
335
336 if( isSymbolChild )
337 {
338 if( shape->GetFillMode() == FILL_T::FILLED_SHAPE )
339 color = shape->GetStroke().GetColor();
340 else if( shape->GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
342 }
343 }
344 else
345 {
346 if( !isSymbolChild || shape->GetStroke().GetColor() != COLOR4D::UNSPECIFIED )
347 color = shape->GetStroke().GetColor();
348 }
349
350 // A filled shape means filled; if they didn't specify a fill colour then use the
351 // border colour.
353 {
354 if( aItem->Type() == SCH_RULE_AREA_T )
355 {
357 }
358 else
359 {
361 : LAYER_NOTES );
362 }
363 }
364 }
365 else if( aItem->IsType( { SCH_LABEL_LOCATE_ANY_T } ) )
366 {
367 color = static_cast<const SCH_LABEL_BASE*>( aItem )->GetLabelColor();
368 }
369 else if( aItem->Type() == SCH_FIELD_T )
370 {
371 color = static_cast<const SCH_FIELD*>( aItem )->GetFieldColor();
372 }
373 else if( aItem->Type() == SCH_TEXTBOX_T || aItem->Type() == SCH_TABLECELL_T )
374 {
375 const SCH_TEXTBOX* textBox = dynamic_cast<const SCH_TEXTBOX*>( aItem );
376
377 if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_NOTES_BACKGROUND
378 || aLayer == LAYER_SHAPES_BACKGROUND )
379 color = textBox->GetFillColor();
380 else if( !isSymbolChild || textBox->GetTextColor() != COLOR4D::UNSPECIFIED )
381 color = textBox->GetTextColor();
382 }
383 else if( const EDA_TEXT* otherTextItem = dynamic_cast<const EDA_TEXT*>( aItem ) )
384 {
385 if( !isSymbolChild || otherTextItem->GetTextColor() != COLOR4D::UNSPECIFIED )
386 color = otherTextItem->GetTextColor();
387 }
388 }
389
391 color = m_schSettings.GetLayerColor( aLayer );
392
393 if( aItem->IsBrightened() ) // Selection disambiguation, net highlighting, etc.
394 {
395 color = m_schSettings.GetLayerColor( LAYER_BRIGHTENED );
396
397 if( aDrawingShadows )
398 {
399 if( aItem->IsSelected() )
400 color = m_schSettings.GetLayerColor( LAYER_SELECTION_SHADOWS );
401 else
402 color = color.WithAlpha( 0.15 );
403 }
404 else if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_SHEET_BACKGROUND
405 || aLayer == LAYER_SHAPES_BACKGROUND )
406 {
407 color = color.WithAlpha( 0.2 );
408 }
409 }
410 else if( aItem->IsSelected() && aDrawingShadows )
411 {
412 color = m_schSettings.GetLayerColor( LAYER_SELECTION_SHADOWS );
413 }
414 else if( aItem->IsSelected()
415 && ( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_SHEET_BACKGROUND
416 || aLayer == LAYER_NOTES_BACKGROUND || aLayer == LAYER_SHAPES_BACKGROUND ) )
417 {
418 // Selected items will be painted over all other items, so make backgrounds translucent so
419 // that non-selected overlapping objects are visible
420 color = color.WithAlpha( 0.5 );
421 }
422
423 if( m_schSettings.m_ShowDisabled
424 || ( m_schSettings.m_ShowGraphicsDisabled && aItem->Type() != SCH_FIELD_T ) )
425 {
426 color = color.Darken( 0.5f );
427 }
428
429 if( aDimmed && !( aItem->IsSelected() && aDrawingShadows ) )
430 {
431 COLOR4D sheetColour = m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND );
432 color.Desaturate();
433 color = color.Mix( sheetColour, 0.5f );
434 }
435
436 if( aItem->GetForcedTransparency() > 0.0 )
437 color = color.WithAlpha( color.a * ( 1.0 - aItem->GetForcedTransparency() ) );
438
439 return color;
440}
441
442
443float SCH_PAINTER::getLineWidth( const SCH_ITEM* aItem, bool aDrawingShadows,
444 bool aDrawingWireColorHighlights ) const
445{
446 wxCHECK( aItem, static_cast<float>( schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS ) ) );
447
448 int pen = aItem->GetEffectivePenWidth( &m_schSettings );
449 float width = pen;
450
451 if( aItem->IsBrightened() || aItem->IsSelected() )
452 {
453 if( aDrawingShadows && aItem->IsType( g_ScaledSelectionTypes ) )
454 width += getShadowWidth( aItem->IsBrightened() );
455 }
456
457 if( aDrawingWireColorHighlights )
458 {
459 float colorHighlightWidth = schIUScale.MilsToIU( 15.0 );
460 EESCHEMA_SETTINGS* eeschemaCfg = eeconfig();
461
462 if( eeschemaCfg )
463 {
464 colorHighlightWidth = schIUScale.MilsToIU(
466 }
467
468 width += colorHighlightWidth;
469 }
470
471 return width;
472}
473
474
475float SCH_PAINTER::getTextThickness( const SCH_ITEM* aItem ) const
476{
477 int pen = m_schSettings.GetDefaultPenWidth();
478
479 switch( aItem->Type() )
480 {
481 case SCH_FIELD_T:
482 pen = static_cast<const SCH_FIELD*>( aItem )->GetEffectiveTextPenWidth( pen );
483 break;
484
485 case SCH_TEXT_T:
486 pen = static_cast<const SCH_TEXT*>( aItem )->GetEffectiveTextPenWidth( pen );
487 break;
488
489 case SCH_LABEL_T:
492 case SCH_HIER_LABEL_T:
493 case SCH_SHEET_PIN_T:
494 pen = static_cast<const SCH_LABEL_BASE*>( aItem )->GetEffectiveTextPenWidth( pen );
495 break;
496
497 case SCH_TEXTBOX_T:
498 case SCH_TABLECELL_T:
499 pen = static_cast<const SCH_TEXTBOX*>( aItem )->GetEffectiveTextPenWidth( pen );
500 break;
501
502 default:
503 UNIMPLEMENTED_FOR( aItem->GetClass() );
504 }
505
506 return (float) pen;
507}
508
509
510int SCH_PAINTER::getOperatingPointTextSize() const
511{
512 int docTextSize = schIUScale.MilsToIU( 50 );
513 int screenTextSize = std::abs( (int) m_gal->GetScreenWorldMatrix().GetScale().y * 7 );
514
515 // 66% zoom-relative
516 return KiROUND( ( docTextSize + screenTextSize * 2 ) / 3 );
517}
518
519
520static bool isFieldsLayer( int aLayer )
521{
522 return aLayer == LAYER_REFERENCEPART
523 || aLayer == LAYER_VALUEPART
524 || aLayer == LAYER_INTERSHEET_REFS
525 || aLayer == LAYER_NETCLASS_REFS
526 || aLayer == LAYER_FIELDS
527 || aLayer == LAYER_SHEETNAME
528 || aLayer == LAYER_SHEETFILENAME
529 || aLayer == LAYER_SHEETFIELDS;
530}
531
532
533static BOX2I GetTextExtents( const wxString& aText, const VECTOR2D& aPosition, KIFONT::FONT& aFont,
534 const TEXT_ATTRIBUTES& aAttrs, const KIFONT::METRICS& aFontMetrics )
535{
536 const VECTOR2I extents =
537 aFont.StringBoundaryLimits( aText, aAttrs.m_Size, aAttrs.m_StrokeWidth, aAttrs.m_Bold,
538 aAttrs.m_Italic, aFontMetrics );
539 BOX2I box( aPosition, VECTOR2I( extents.x, aAttrs.m_Size.y ) );
540
541 switch( aAttrs.m_Halign )
542 {
543 case GR_TEXT_H_ALIGN_LEFT: break;
544 case GR_TEXT_H_ALIGN_CENTER: box.SetX( box.GetX() - box.GetWidth() / 2 ); break;
545 case GR_TEXT_H_ALIGN_RIGHT: box.SetX( box.GetX() - box.GetWidth() ); break;
546 case GR_TEXT_H_ALIGN_INDETERMINATE: wxFAIL_MSG( wxT( "Legal only in dialogs" ) ); break;
547 }
548
549 switch( aAttrs.m_Valign )
550 {
551 case GR_TEXT_V_ALIGN_TOP: break;
552 case GR_TEXT_V_ALIGN_CENTER: box.SetY( box.GetY() - box.GetHeight() / 2 ); break;
553 case GR_TEXT_V_ALIGN_BOTTOM: box.SetY( box.GetY() - box.GetHeight() ); break;
554 case GR_TEXT_V_ALIGN_INDETERMINATE: wxFAIL_MSG( wxT( "Legal only in dialogs" ) ); break;
555 }
556
557 box.Normalize(); // Make h and v sizes always >= 0
558 box = box.GetBoundingBoxRotated( aPosition, aAttrs.m_Angle );
559
560 return box;
561}
562
563
564static void strokeText( KIGFX::GAL& aGal, const wxString& aText, const VECTOR2D& aPosition,
565 const TEXT_ATTRIBUTES& aAttrs, const KIFONT::METRICS& aFontMetrics )
566{
567 KIFONT::FONT* font = aAttrs.m_Font;
568
569 if( !font )
570 {
571 font = KIFONT::FONT::GetFont( eeconfig()->m_Appearance.default_font, aAttrs.m_Bold,
572 aAttrs.m_Italic );
573 }
574
575 aGal.SetIsFill( font->IsOutline() );
576 aGal.SetIsStroke( font->IsStroke() );
577
578 font->Draw( &aGal, aText, aPosition, aAttrs, aFontMetrics );
579}
580
581
582static void bitmapText( KIGFX::GAL& aGal, const wxString& aText, const VECTOR2D& aPosition,
583 const TEXT_ATTRIBUTES& aAttrs )
584{
585 // Bitmap font has different metrics from the stroke font so we compensate a bit before
586 // stroking
587 aGal.SetGlyphSize( VECTOR2I( aAttrs.m_Size.x, KiROUND( aAttrs.m_Size.y * 1.05 ) ) );
588 aGal.SetLineWidth( (float) aAttrs.m_StrokeWidth * 1.35f );
589
590 aGal.SetHorizontalJustify( aAttrs.m_Halign );
591 aGal.SetVerticalJustify( aAttrs.m_Valign );
592
593 aGal.BitmapText( aText, aPosition, aAttrs.m_Angle );
594}
595
596
597static void knockoutText( KIGFX::GAL& aGal, const wxString& aText, const VECTOR2D& aPosition,
598 const TEXT_ATTRIBUTES& aAttrs, const KIFONT::METRICS& aFontMetrics )
599{
600 TEXT_ATTRIBUTES attrs( aAttrs );
601 KIFONT::FONT* font = aAttrs.m_Font;
602
603 if( !font )
604 {
605 font = KIFONT::FONT::GetFont( eeconfig()->m_Appearance.default_font, attrs.m_Bold,
606 attrs.m_Italic );
607 }
608
610 SHAPE_POLY_SET knockouts;
611
612 CALLBACK_GAL callback_gal( empty_opts,
613 // Polygon callback
614 [&]( const SHAPE_LINE_CHAIN& aPoly )
615 {
616 knockouts.AddOutline( aPoly );
617 } );
618
619 callback_gal.SetIsFill( false );
620 callback_gal.SetIsStroke( true );
621 callback_gal.SetLineWidth( (float) attrs.m_StrokeWidth );
622 font->Draw( &callback_gal, aText, aPosition, attrs, aFontMetrics );
623
624 BOX2I bbox = knockouts.BBox( attrs.m_StrokeWidth * 2 );
625 SHAPE_POLY_SET finalPoly;
626
627 finalPoly.NewOutline();
628 finalPoly.Append( bbox.GetLeft(), bbox.GetTop() );
629 finalPoly.Append( bbox.GetRight(), bbox.GetTop() );
630 finalPoly.Append( bbox.GetRight(), bbox.GetBottom() );
631 finalPoly.Append( bbox.GetLeft(), bbox.GetBottom() );
632
633 finalPoly.BooleanSubtract( knockouts );
634 finalPoly.Fracture();
635
636 aGal.SetIsStroke( false );
637 aGal.SetIsFill( true );
638 aGal.SetFillColor( attrs.m_Color );
639 aGal.DrawPolygon( finalPoly );
640}
641
642
643static void boxText( KIGFX::GAL& aGal, const wxString& aText, const VECTOR2D& aPosition,
644 const TEXT_ATTRIBUTES& aAttrs, const KIFONT::METRICS& aFontMetrics )
645{
646 KIFONT::FONT* font = aAttrs.m_Font;
647
648 if( !font )
649 {
650 font = KIFONT::FONT::GetFont( eeconfig()->m_Appearance.default_font, aAttrs.m_Bold,
651 aAttrs.m_Italic );
652 }
653
654 BOX2I box = GetTextExtents( aText, aPosition, *font, aAttrs, aFontMetrics );
655
656 // Give the highlight a bit of margin.
657 box.Inflate( 0, aAttrs.m_StrokeWidth * 2 );
658
659 aGal.SetIsFill( true );
660 aGal.SetIsStroke( false );
661 aGal.DrawRectangle( box.GetOrigin(), box.GetEnd() );
662}
663
664
665void SCH_PAINTER::triLine( const VECTOR2D& a, const VECTOR2D& b, const VECTOR2D& c )
666{
667 m_gal->DrawLine( a, b );
668 m_gal->DrawLine( b, c );
669}
670
671
672void SCH_PAINTER::draw( const LIB_SYMBOL* aSymbol, int aLayer, bool aDrawFields, int aUnit,
673 int aBodyStyle, bool aDimmed )
674{
675 if( !aUnit )
676 aUnit = m_schSettings.m_ShowUnit;
677
678 if( !aBodyStyle )
679 aBodyStyle = m_schSettings.m_ShowBodyStyle;
680
681 std::unique_ptr< LIB_SYMBOL > tmpSymbol;
682 const LIB_SYMBOL* drawnSymbol = aSymbol;
683
684 if( aSymbol->IsAlias() )
685 {
686 tmpSymbol = aSymbol->Flatten();
687 drawnSymbol = tmpSymbol.get();
688 }
689
690 // The parent must exist on the union of all its children's draw layers. But that doesn't
691 // mean we want to draw each child on the union.
692 auto childOnLayer =
693 []( const SCH_ITEM& item, int layer )
694 {
695 std::vector<int> layers = item.ViewGetLayers();
696
697 return std::find( layers.begin(), layers.end(), layer ) != layers.end();
698 };
699
700 for( const SCH_ITEM& item : drawnSymbol->GetDrawItems() )
701 {
702 if( !aDrawFields && item.Type() == SCH_FIELD_T )
703 continue;
704
705 if( !childOnLayer( item, aLayer ) )
706 continue;
707
708 if( aUnit && item.GetUnit() && aUnit != item.GetUnit() )
709 continue;
710
711 if( aBodyStyle && item.GetBodyStyle() && aBodyStyle != item.GetBodyStyle() )
712 continue;
713
714 draw( &item, aLayer, aDimmed );
715 }
716}
717
718
719int SCH_PAINTER::internalPinDecoSize( const SCH_PIN &aPin )
720{
721 if( m_schSettings.m_PinSymbolSize > 0 )
722 return m_schSettings.m_PinSymbolSize;
723
724 return aPin.GetNameTextSize() != 0 ? aPin.GetNameTextSize() / 2 : aPin.GetNumberTextSize() / 2;
725}
726
727
728// Utility for getting the size of the 'external' pin decorators (as a radius)
729// i.e. the negation circle, the polarity 'slopes' and the nonlogic marker
730int SCH_PAINTER::externalPinDecoSize( const SCH_PIN &aPin )
731{
732 if( m_schSettings.m_PinSymbolSize > 0 )
733 return m_schSettings.m_PinSymbolSize;
734
735 return aPin.GetNumberTextSize() / 2;
736}
737
738
739// Draw the target (an open circle) for a pin which has no connection or is being moved.
740void SCH_PAINTER::drawPinDanglingIndicator( const SCH_PIN& aPin, const COLOR4D& aColor,
741 bool aDrawingShadows, bool aBrightened )
742{
743 const PIN_LAYOUT_CACHE& plc = aPin.GetLayoutCache();
744 const CIRCLE c = plc.GetDanglingIndicator();
745
746 float lineWidth = aDrawingShadows ? getShadowWidth( aBrightened )
747 : m_schSettings.GetDanglingIndicatorThickness();
748
749 // Dangling symbols must be drawn in a slightly different colour so they can be seen when
750 // they overlap with a junction dot.
751 m_gal->SetStrokeColor( aColor.Brightened( 0.3 ) );
752
753 m_gal->SetIsFill( false );
754 m_gal->SetIsStroke( true );
755 m_gal->SetLineWidth( lineWidth );
756 m_gal->DrawCircle( c.Center, c.Radius );
757}
758
759
763static void drawAltPinModesIcon( GAL& aGal, const VECTOR2D& aPos, double aSize, bool aBaseSelected,
764 bool aRotate, int aExtraLineWidth, const COLOR4D& aColor )
765{
766 aGal.Save();
767
768 aGal.Translate( aPos );
769 if( aRotate )
770 {
771 aGal.Rotate( ANGLE_270.AsRadians() );
772 }
773
774 aGal.SetIsFill( false );
775 aGal.SetIsStroke( true );
776 aGal.SetLineWidth( KiROUND( aSize / 10.0 + aExtraLineWidth ) );
777 aGal.SetStrokeColor( aColor );
778
779 /*
780 * ----------->
781 * + <--center
782 * \------->
783 *
784 * or
785 *
786 * ----- ---->
787 * \
788 * \------>
789 */
790
791 const double lineYOffset = aSize / 4;
792 const double arrowHead = aSize / 8;
793
794 const VECTOR2D topLineREnd = VECTOR2D{ aSize / 2, -lineYOffset };
795 const VECTOR2D btmLineREnd = VECTOR2D{ aSize / 2, lineYOffset };
796
797 // Top line and arrowhead
798 if( aBaseSelected )
799 {
800 // Full top line
801 aGal.DrawLine( topLineREnd, topLineREnd - VECTOR2D{ aSize, 0 } );
802 }
803 else
804 {
805 // Line with a gap
806 aGal.DrawLine( topLineREnd, topLineREnd - VECTOR2D{ aSize / 2, 0 } );
807 aGal.DrawLine( topLineREnd - VECTOR2D{ aSize, 0 },
808 topLineREnd - VECTOR2D{ aSize * 0.7, 0 } );
809 }
810 aGal.DrawLine( topLineREnd, topLineREnd - VECTOR2D{ arrowHead * 1.2, arrowHead } );
811 aGal.DrawLine( topLineREnd, topLineREnd - VECTOR2D{ arrowHead * 1.2, -arrowHead } );
812
813 // Bottom line and arrowhead
814 aGal.DrawLine( btmLineREnd, btmLineREnd - VECTOR2D{ aSize / 2, 0 } );
815 aGal.DrawLine( btmLineREnd, btmLineREnd - VECTOR2D{ arrowHead * 1.2, arrowHead } );
816 aGal.DrawLine( btmLineREnd, btmLineREnd - VECTOR2D{ arrowHead * 1.2, -arrowHead } );
817
818 // Top and bottom 'S' arcs
819 if( !aBaseSelected )
820 {
821 aGal.DrawArc( topLineREnd - VECTOR2D{ aSize, -lineYOffset },
822 lineYOffset, ANGLE_0, -ANGLE_90 );
823 }
824 aGal.DrawArc( topLineREnd - VECTOR2D{ aSize - lineYOffset * 2, -lineYOffset },
825 lineYOffset, ANGLE_180, -ANGLE_90 );
826
827 aGal.Restore();
828};
829
830
831void SCH_PAINTER::draw( const SCH_PIN* aPin, int aLayer, bool aDimmed )
832{
833 // Don't draw pins from a selection view-group. Pins in a schematic must always be drawn
834 // from their parent symbol's m_part.
835 if( dynamic_cast<const SCH_SYMBOL*>( aPin->GetParentSymbol() ) )
836 return;
837
838 if( !isUnitAndConversionShown( aPin ) )
839 return;
840
841 const bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
842
843 if( m_schSettings.IsPrinting() && drawingShadows )
844 return;
845
846 const bool drawingDangling = aLayer == LAYER_DANGLING;
847 const bool drawingOP = aLayer == LAYER_OP_CURRENTS;
848 const bool isDangling = m_schSettings.m_IsSymbolEditor || aPin->HasFlag( IS_DANGLING );
849
850 if( drawingShadows && !( aPin->IsBrightened() || aPin->IsSelected() ) )
851 return;
852
853 const VECTOR2I pos = aPin->GetPosition();
854 COLOR4D color = getRenderColor( aPin, LAYER_PIN, drawingShadows, aDimmed );
855
856 if( !aPin->IsVisible() )
857 {
858 if( m_schSettings.IsPrinting() )
859 return;
860
861 bool force_show = m_schematic ? eeconfig()->m_Appearance.show_hidden_pins
862 : m_schSettings.m_ShowHiddenPins;
863
864 if( force_show )
865 {
866 color = getRenderColor( aPin, LAYER_HIDDEN, drawingShadows, aDimmed );
867 }
868 else
869 {
870 if( drawingDangling && isDangling && aPin->IsGlobalPower() )
871 drawPinDanglingIndicator( *aPin, color, drawingShadows, aPin->IsBrightened() );
872
873 return;
874 }
875 }
876
877 if( drawingDangling )
878 {
879 if( isDangling )
880 drawPinDanglingIndicator( *aPin, color, drawingShadows, aPin->IsBrightened() );
881
882 return;
883 }
884
885 if( m_schSettings.GetDrawBoundingBoxes() )
886 drawItemBoundingBox( aPin );
887
888 const VECTOR2I p0 = aPin->GetPinRoot();
889 const VECTOR2I dir( sign( pos.x - p0.x ), sign( pos.y - p0.y ) );
890 const int len = aPin->GetLength();
891
892 if( drawingOP && !aPin->GetOperatingPoint().IsEmpty() )
893 {
894 int textSize = getOperatingPointTextSize();
895 VECTOR2I mid = ( p0 + pos ) / 2;
896 int textOffset = KiROUND( textSize * 0.22 );
897 TEXT_ATTRIBUTES attrs;
898
899 if( len > textSize )
900 {
901 if( dir.x == 0 )
902 {
903 mid.x += KiROUND( textOffset * 1.2 );
905 }
906 else
907 {
908 mid.y -= KiROUND( textOffset * 1.2 );
909 attrs.m_Angle = ANGLE_VERTICAL;
910 }
911
914
915 attrs.m_Font = KIFONT::FONT::GetFont(); // always use stroke font for performance
916 attrs.m_Size = VECTOR2I( textSize, textSize );
917 attrs.m_StrokeWidth = GetPenSizeForDemiBold( textSize );
918 attrs.m_Color = m_schSettings.GetLayerColor( LAYER_OP_CURRENTS );
919
920 knockoutText( *m_gal, aPin->GetOperatingPoint(), mid, attrs, aPin->GetFontMetrics() );
921 }
922 }
923
924 if( drawingOP )
925 return;
926
927 VECTOR2D pc;
928
929 m_gal->SetIsStroke( true );
930 m_gal->SetIsFill( false );
931 m_gal->SetLineWidth( getLineWidth( aPin, drawingShadows ) );
932 m_gal->SetStrokeColor( color );
933 m_gal->SetFontBold( false );
934 m_gal->SetFontUnderlined( false );
935 m_gal->SetFontItalic( false );
936
937 const int radius = externalPinDecoSize( *aPin );
938 const int diam = radius*2;
939 const int clock_size = internalPinDecoSize( *aPin );
940
941 if( aPin->GetType() == ELECTRICAL_PINTYPE::PT_NC ) // Draw a N.C. symbol
942 {
943 m_gal->DrawLine( p0, pos );
944
945 m_gal->DrawLine( pos + VECTOR2D( -1, -1 ) * TARGET_PIN_RADIUS,
946 pos + VECTOR2D( 1, 1 ) * TARGET_PIN_RADIUS );
947 m_gal->DrawLine( pos + VECTOR2D( 1, -1 ) * TARGET_PIN_RADIUS ,
948 pos + VECTOR2D( -1, 1 ) * TARGET_PIN_RADIUS );
949 }
950 else
951 {
952 switch( aPin->GetShape() )
953 {
954 default:
956 m_gal->DrawLine( p0, pos );
957 break;
958
960 m_gal->DrawCircle( p0 + dir * radius, radius );
961 m_gal->DrawLine( p0 + dir * ( diam ), pos );
962 break;
963
965 pc = p0 - dir * clock_size ;
966
967 triLine( p0 + VECTOR2D( dir.y, -dir.x) * clock_size,
968 pc,
969 p0 + VECTOR2D( -dir.y, dir.x) * clock_size );
970
971 m_gal->DrawCircle( p0 + dir * radius, radius );
972 m_gal->DrawLine( p0 + dir * ( diam ), pos );
973 break;
974
977 pc = p0 - dir * clock_size ;
978
979 triLine( p0 + VECTOR2D( dir.y, -dir.x) * clock_size,
980 pc,
981 p0 + VECTOR2D( -dir.y, dir.x) * clock_size );
982
983 if( !dir.y )
984 {
985 triLine( p0 + VECTOR2D(dir.x, 0) * diam,
986 p0 + VECTOR2D(dir.x, -1) * diam,
987 p0 );
988 }
989 else /* MapX1 = 0 */
990 {
991 triLine( p0 + VECTOR2D( 0, dir.y) * diam,
992 p0 + VECTOR2D(-1, dir.y) * diam,
993 p0 );
994 }
995
996 m_gal->DrawLine( p0, pos );
997 break;
998
1000 m_gal->DrawLine( p0, pos );
1001
1002 if( !dir.y )
1003 {
1004 triLine( p0 + VECTOR2D( 0, clock_size ),
1005 p0 + VECTOR2D( -dir.x * clock_size, 0 ),
1006 p0 + VECTOR2D( 0, -clock_size ) );
1007 }
1008 else
1009 {
1010 triLine( p0 + VECTOR2D( clock_size, 0 ),
1011 p0 + VECTOR2D( 0, -dir.y * clock_size ),
1012 p0 + VECTOR2D( -clock_size, 0 ) );
1013 }
1014 break;
1015
1017 m_gal->DrawLine( p0, pos );
1018
1019 if( !dir.y )
1020 {
1021 triLine( p0 + VECTOR2D(dir.x, 0) * diam,
1022 p0 + VECTOR2D(dir.x, -1) * diam,
1023 p0 );
1024 }
1025 else /* MapX1 = 0 */
1026 {
1027 triLine( p0 + VECTOR2D( 0, dir.y) * diam,
1028 p0 + VECTOR2D(-1, dir.y) * diam,
1029 p0 );
1030 }
1031 break;
1032
1033 case GRAPHIC_PINSHAPE::OUTPUT_LOW: // IEEE symbol "Active Low Output"
1034 m_gal->DrawLine( p0, pos );
1035
1036 if( !dir.y ) // Horizontal pin
1037 m_gal->DrawLine( p0 - VECTOR2D( 0, diam ), p0 + VECTOR2D( dir.x, 0 ) * diam );
1038 else // Vertical pin
1039 m_gal->DrawLine( p0 - VECTOR2D( diam, 0 ), p0 + VECTOR2D( 0, dir.y ) * diam );
1040 break;
1041
1042 case GRAPHIC_PINSHAPE::NONLOGIC: // NonLogic pin symbol
1043 m_gal->DrawLine( p0, pos );
1044
1045 m_gal->DrawLine( p0 - VECTOR2D( dir.x + dir.y, dir.y - dir.x ) * radius,
1046 p0 + VECTOR2D( dir.x + dir.y, dir.y - dir.x ) * radius );
1047 m_gal->DrawLine( p0 - VECTOR2D( dir.x - dir.y, dir.x + dir.y ) * radius,
1048 p0 + VECTOR2D( dir.x - dir.y, dir.x + dir.y ) * radius );
1049 break;
1050 }
1051 }
1052
1053 if( drawingShadows && !eeconfig()->m_Selection.draw_selected_children )
1054 return;
1055
1056 // Draw the labels
1057 float nameStrokeWidth = getLineWidth( aPin, false );
1058 float numStrokeWidth = getLineWidth( aPin, false );
1059
1060 nameStrokeWidth = ClampTextPenSize( nameStrokeWidth, aPin->GetNameTextSize(), true );
1061 numStrokeWidth = ClampTextPenSize( numStrokeWidth, aPin->GetNumberTextSize(), true );
1062
1063 float shadowWidth = 0.0f;
1064
1065 if( drawingShadows )
1066 {
1067 shadowWidth = getShadowWidth( aPin->IsBrightened() );
1068 }
1069
1070 PIN_LAYOUT_CACHE& cache = aPin->GetLayoutCache();
1071 cache.SetRenderParameters( nameStrokeWidth, numStrokeWidth,
1072 m_schSettings.m_ShowPinsElectricalType,
1073 m_schSettings.m_ShowPinAltIcons );
1074
1075 const auto textRendersAsBitmap = [&]( KIGFX::GAL& aGal, int aTextSize )
1076 {
1077 // Rendering text is expensive (particularly when using outline fonts). At small effective
1078 // sizes (ie: zoomed out) the visual differences between outline and/or stroke fonts and the
1079 // bitmap font becomes immaterial, and there's often more to draw when zoomed out so the
1080 // performance gain becomes more significant.
1081 static const float BITMAP_FONT_SIZE_THRESHOLD = 3.5;
1082
1083 // Any text non bitmappable?
1084 return aTextSize * aGal.GetWorldScale() < BITMAP_FONT_SIZE_THRESHOLD;
1085 };
1086
1087 const auto drawTextInfo =
1088 [&]( const PIN_LAYOUT_CACHE::TEXT_INFO& aTextInfo, const COLOR4D& aColor )
1089 {
1090 // const double iconSize = std::min( aPin->GetNameTextSize(), schIUScale.mmToIU( 1.5 ) );
1091 const bool renderTextAsBitmap = textRendersAsBitmap( *m_gal, aTextInfo.m_TextSize );
1092
1093 // Which of these gets used depends on the font technology, so set both
1094 m_gal->SetStrokeColor( aColor );
1095 m_gal->SetFillColor( aColor );
1096
1097 TEXT_ATTRIBUTES attrs;
1098 attrs.m_Font = KIFONT::FONT::GetFont( eeconfig()->m_Appearance.default_font );
1099 attrs.m_Size = VECTOR2I( aTextInfo.m_TextSize, aTextInfo.m_TextSize );
1100 attrs.m_Halign = aTextInfo.m_HAlign;
1101 attrs.m_Valign = aTextInfo.m_VAlign;
1102 attrs.m_Angle = aTextInfo.m_Angle;
1103 attrs.m_StrokeWidth = aTextInfo.m_Thickness;
1104
1105 if( drawingShadows )
1106 {
1107 attrs.m_StrokeWidth += KiROUND( shadowWidth );
1108
1109 if( !attrs.m_Font->IsOutline() )
1110 {
1111 strokeText( *m_gal, aTextInfo.m_Text, aTextInfo.m_TextPosition, attrs,
1112 aPin->GetFontMetrics() );
1113 }
1114 else
1115 {
1116 boxText( *m_gal, aTextInfo.m_Text, aTextInfo.m_TextPosition, attrs,
1117 aPin->GetFontMetrics() );
1118 }
1119 }
1120 else if( nonCached( aPin ) && renderTextAsBitmap )
1121 {
1122 bitmapText( *m_gal, aTextInfo.m_Text, aTextInfo.m_TextPosition, attrs );
1123 const_cast<SCH_PIN*>( aPin )->SetFlags( IS_SHOWN_AS_BITMAP );
1124 }
1125 else
1126 {
1127 strokeText( *m_gal, aTextInfo.m_Text, aTextInfo.m_TextPosition, attrs,
1128 aPin->GetFontMetrics() );
1129 const_cast<SCH_PIN*>( aPin )->SetFlags( IS_SHOWN_AS_BITMAP );
1130 }
1131 };
1132
1133 const auto getColorForLayer = [&]( int aDrawnLayer )
1134 {
1135 if( !aPin->IsVisible() )
1136 return getRenderColor( aPin, LAYER_HIDDEN, drawingShadows, aDimmed );
1137
1138 return getRenderColor( aPin, aDrawnLayer, drawingShadows, aDimmed );
1139 };
1140
1141 // Request text layout infor and draw it
1142
1143 if( std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> numInfo = cache.GetPinNumberInfo( shadowWidth ) )
1144 {
1145 drawTextInfo( *numInfo, getColorForLayer( LAYER_PINNUM ) );
1146 }
1147
1148 if( std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> nameInfo = cache.GetPinNameInfo( shadowWidth ) )
1149 {
1150 drawTextInfo( *nameInfo, getColorForLayer( LAYER_PINNAM ) );
1151
1152 if( OPT_BOX2I altIconBox = cache.GetAltIconBBox() )
1153 {
1154 drawAltPinModesIcon( *m_gal, altIconBox->GetCenter(), altIconBox->GetWidth(),
1155 // Icon style doesn't work due to the tempPin having no alt
1156 // but maybe it's better with just one style anyway.
1157 true, nameInfo->m_Angle == ANGLE_VERTICAL, shadowWidth,
1158 getColorForLayer( LAYER_PINNAM ) );
1159 }
1160 }
1161
1162 if( std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> elecTypeInfo =
1163 cache.GetPinElectricalTypeInfo( shadowWidth ) )
1164 {
1165 drawTextInfo( *elecTypeInfo, getColorForLayer( LAYER_PRIVATE_NOTES ) );
1166 }
1167}
1168
1169
1170// Draw anchor indicating the anchor position of text objects, local labels, or fields.
1171void SCH_PAINTER::drawAnchor( const VECTOR2I& aPos, bool aDrawingShadows )
1172{
1173 if( m_schSettings.IsPrinting() )
1174 return;
1175
1176 // In order for the anchors to be visible but unobtrusive, their size must factor in the
1177 // current zoom level.
1178 const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
1179 int radius = KiROUND( std::fabs( matrix.GetScale().x * TEXT_ANCHOR_SIZE ) / 25 )
1181
1182 COLOR4D color = aDrawingShadows ? m_schSettings.GetLayerColor( LAYER_SELECTION_SHADOWS )
1183 : m_schSettings.GetLayerColor( LAYER_SCHEMATIC_ANCHOR );
1184
1185 m_gal->SetStrokeColor( color );
1186 m_gal->SetIsStroke( true );
1187 m_gal->SetLineWidth( aDrawingShadows ? getShadowWidth( false )
1188 : m_schSettings.GetDanglingIndicatorThickness() );
1189
1190 m_gal->DrawLine( aPos - VECTOR2I( radius, 0 ), aPos + VECTOR2I( radius, 0 ) );
1191 m_gal->DrawLine( aPos - VECTOR2I( 0, radius ), aPos + VECTOR2I( 0, radius ) );
1192}
1193
1194
1195// Draw the target (an open square) for a wire or label which has no connection or is
1196// being moved.
1197void SCH_PAINTER::drawDanglingIndicator( const VECTOR2I& aPos, const COLOR4D& aColor, int aWidth,
1198 bool aDangling, bool aDrawingShadows, bool aBrightened )
1199{
1200 if( m_schSettings.IsPrinting() )
1201 return;
1202
1203 int size = aDangling ? DANGLING_SYMBOL_SIZE : UNSELECTED_END_SIZE;
1204
1205 if( !aDangling )
1206 aWidth /= 2;
1207
1208 VECTOR2I radius( aWidth + schIUScale.MilsToIU( size / 2 ),
1209 aWidth + schIUScale.MilsToIU( size / 2 ) );
1210
1211 // Dangling symbols must be drawn in a slightly different colour so they can be seen when
1212 // they overlap with a junction dot.
1213 m_gal->SetStrokeColor( aColor.Brightened( 0.3 ) );
1214 m_gal->SetIsStroke( true );
1215 m_gal->SetIsFill( false );
1216 m_gal->SetLineWidth( aDrawingShadows ? getShadowWidth( aBrightened )
1217 : m_schSettings.GetDanglingIndicatorThickness() );
1218
1219 m_gal->DrawRectangle( aPos - radius, aPos + radius );
1220}
1221
1222
1223void SCH_PAINTER::draw( const SCH_JUNCTION* aJct, int aLayer )
1224{
1225 bool highlightNetclassColors = false;
1226 EESCHEMA_SETTINGS* eeschemaCfg = eeconfig();
1227
1228 if( eeschemaCfg )
1229 {
1230 highlightNetclassColors = eeschemaCfg->m_Selection.highlight_netclass_colors;
1231 }
1232
1233 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1234
1235 if( m_schSettings.IsPrinting() && drawingShadows )
1236 return;
1237
1238 if( drawingShadows && !( aJct->IsBrightened() || aJct->IsSelected() ) )
1239 return;
1240
1241 COLOR4D color;
1242
1243 if( highlightNetclassColors && aLayer == aJct->GetLayer() )
1244 color = m_schSettings.GetLayerColor( aJct->GetLayer() );
1245 else
1246 color = getRenderColor( aJct, aJct->GetLayer(), drawingShadows );
1247
1248 int junctionSize = aJct->GetEffectiveDiameter() / 2;
1249
1250 if( junctionSize > 1 )
1251 {
1252 m_gal->SetIsStroke( drawingShadows );
1253 m_gal->SetLineWidth( getLineWidth( aJct, drawingShadows ) );
1254 m_gal->SetStrokeColor( color );
1255 m_gal->SetIsFill( !drawingShadows );
1256 m_gal->SetFillColor( color );
1257 m_gal->DrawCircle( aJct->GetPosition(), junctionSize );
1258 }
1259}
1260
1261
1262void SCH_PAINTER::draw( const SCH_LINE* aLine, int aLayer )
1263{
1264 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1265 bool drawingNetColorHighlights = aLayer == LAYER_NET_COLOR_HIGHLIGHT;
1266 bool drawingWires = aLayer == LAYER_WIRE;
1267 bool drawingBusses = aLayer == LAYER_BUS;
1268 bool drawingDangling = aLayer == LAYER_DANGLING;
1269 bool drawingOP = aLayer == LAYER_OP_VOLTAGES;
1270
1271 bool highlightNetclassColors = false;
1272 double highlightAlpha = 0.6;
1273 EESCHEMA_SETTINGS* eeschemaCfg = eeconfig();
1274
1275 if( eeschemaCfg )
1276 {
1277 highlightNetclassColors = eeschemaCfg->m_Selection.highlight_netclass_colors;
1278 highlightAlpha = eeschemaCfg->m_Selection.highlight_netclass_colors_alpha;
1279 }
1280
1281 if( !highlightNetclassColors && drawingNetColorHighlights )
1282 return;
1283
1284 if( m_schSettings.m_OverrideItemColors && drawingNetColorHighlights )
1285 return;
1286
1287 if( m_schSettings.IsPrinting() && drawingShadows )
1288 return;
1289
1290 if( drawingShadows && !( aLine->IsBrightened() || aLine->IsSelected() ) )
1291 return;
1292
1293 // Line end dangling status isn't updated until the line is finished drawing, so don't warn
1294 // them about ends that are probably connected
1295 if( aLine->IsNew() && drawingDangling )
1296 return;
1297
1298 COLOR4D color = getRenderColor( aLine, aLine->GetLayer(), drawingShadows );
1299 float width = getLineWidth( aLine, drawingShadows, drawingNetColorHighlights );
1300 LINE_STYLE lineStyle = aLine->GetEffectiveLineStyle();
1301
1302 if( highlightNetclassColors )
1303 {
1304 // Force default color for nets we are going to highlight
1305 if( drawingWires )
1306 color = m_schSettings.GetLayerColor( LAYER_WIRE );
1307 else if( drawingBusses )
1308 color = m_schSettings.GetLayerColor( LAYER_BUS );
1309 }
1310
1311 if( drawingNetColorHighlights )
1312 {
1313 // Don't draw highlights for default-colored nets
1314 if( ( aLine->IsWire() && color == m_schSettings.GetLayerColor( LAYER_WIRE ) )
1315 || ( aLine->IsBus() && color == m_schSettings.GetLayerColor( LAYER_BUS ) ) )
1316 {
1317 return;
1318 }
1319
1320 color = color.WithAlpha( color.a * highlightAlpha );
1321 }
1322
1323 if( ( drawingDangling || drawingShadows ) && !aLine->IsNew() )
1324 {
1325 if( ( aLine->IsWire() && aLine->IsStartDangling() )
1326 || ( drawingShadows && aLine->IsSelected() && !aLine->HasFlag( STARTPOINT ) ) )
1327 {
1328 COLOR4D indicatorColor( color );
1329
1330 if( drawingShadows && !aLine->HasFlag( STARTPOINT ) )
1331 indicatorColor.Invert();
1332
1333 drawDanglingIndicator( aLine->GetStartPoint(), indicatorColor, KiROUND( width ),
1334 aLine->IsWire() && aLine->IsStartDangling(), drawingShadows,
1335 aLine->IsBrightened() );
1336 }
1337
1338 if( ( aLine->IsWire() && aLine->IsEndDangling() )
1339 || ( drawingShadows && aLine->IsSelected() && !aLine->HasFlag( ENDPOINT ) ) )
1340 {
1341 COLOR4D indicatorColor( color );
1342
1343 if( drawingShadows && !aLine->HasFlag( ENDPOINT ) )
1344 indicatorColor.Invert();
1345
1346 drawDanglingIndicator( aLine->GetEndPoint(), indicatorColor, KiROUND( width ),
1347 aLine->IsWire() && aLine->IsEndDangling(), drawingShadows,
1348 aLine->IsBrightened() );
1349 }
1350 }
1351
1352 if( drawingDangling )
1353 return;
1354
1355 if( drawingOP && !aLine->GetOperatingPoint().IsEmpty() )
1356 {
1357 int textSize = getOperatingPointTextSize();
1358 VECTOR2I pos = aLine->GetMidPoint();
1359 int textOffset = KiROUND( textSize * 0.22 );
1360 TEXT_ATTRIBUTES attrs;
1361
1362 if( aLine->GetStartPoint().y == aLine->GetEndPoint().y )
1363 {
1364 pos.y -= textOffset;
1367 }
1368 else
1369 {
1370 pos.x += KiROUND( textOffset * 1.2 );
1373 }
1374
1375 attrs.m_Font = KIFONT::FONT::GetFont(); // always use stroke font for performance
1376 attrs.m_Size = VECTOR2I( textSize, textSize );
1377 attrs.m_StrokeWidth = GetPenSizeForDemiBold( textSize );
1378 attrs.m_Color = m_schSettings.GetLayerColor( LAYER_OP_VOLTAGES );
1379
1380 knockoutText( *m_gal, aLine->GetOperatingPoint(), pos, attrs, aLine->GetFontMetrics() );
1381 }
1382
1383 if( drawingOP )
1384 return;
1385
1386 m_gal->SetIsStroke( true );
1387 m_gal->SetStrokeColor( color );
1388 m_gal->SetLineWidth( width );
1389
1390 if( lineStyle <= LINE_STYLE::FIRST_TYPE || drawingShadows )
1391 {
1392 m_gal->DrawLine( aLine->GetStartPoint(), aLine->GetEndPoint() );
1393 }
1394 else
1395 {
1396 SHAPE_SEGMENT line( aLine->GetStartPoint(), aLine->GetEndPoint() );
1397
1398 STROKE_PARAMS::Stroke( &line, lineStyle, KiROUND( width ), &m_schSettings,
1399 [&]( const VECTOR2I& a, const VECTOR2I& b )
1400 {
1401 // DrawLine has problem with 0 length lines so enforce minimum
1402 if( a == b )
1403 m_gal->DrawLine( a+1, b );
1404 else
1405 m_gal->DrawLine( a, b );
1406 } );
1407 }
1408}
1409
1410
1411void SCH_PAINTER::draw( const SCH_SHAPE* aShape, int aLayer, bool aDimmed )
1412{
1413 if( !isUnitAndConversionShown( aShape ) )
1414 return;
1415
1416 if( aShape->IsPrivate() && !m_schSettings.m_IsSymbolEditor )
1417 return;
1418
1419 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1420
1421 if( m_schSettings.IsPrinting() && drawingShadows )
1422 return;
1423
1424 LINE_STYLE lineStyle = aShape->GetEffectiveLineStyle();
1425 COLOR4D color = getRenderColor( aShape, aLayer, drawingShadows, aDimmed );
1426
1427 if( drawingShadows && !( aShape->IsBrightened() || aShape->IsSelected() ) )
1428 return;
1429
1430 auto drawShape =
1431 [&]( const SCH_SHAPE* shape )
1432 {
1433 switch( shape->GetShape() )
1434 {
1435 case SHAPE_T::ARC:
1436 {
1437 VECTOR2D start = shape->GetStart();
1438 VECTOR2D mid = shape->GetArcMid();
1439 VECTOR2D end = shape->GetEnd();
1440 VECTOR2D center = CalcArcCenter( start, mid, end );
1441
1442 EDA_ANGLE startAngle( start - center );
1443 EDA_ANGLE midAngle( mid - center );
1444 EDA_ANGLE endAngle( end - center );
1445
1446 EDA_ANGLE angle1 = midAngle - startAngle;
1447 EDA_ANGLE angle2 = endAngle - midAngle;
1448
1449 EDA_ANGLE angle = angle1.Normalize180() + angle2.Normalize180();
1450
1451 m_gal->DrawArc( center, ( start - center ).EuclideanNorm(), startAngle, angle );
1452 break;
1453 }
1454
1455 case SHAPE_T::CIRCLE:
1456 m_gal->DrawCircle( shape->GetPosition(), shape->GetRadius() );
1457 break;
1458
1459 case SHAPE_T::RECTANGLE:
1460 m_gal->DrawRectangle( shape->GetPosition(), shape->GetEnd() );
1461 break;
1462
1463 case SHAPE_T::POLY:
1464 {
1465 const std::vector<SHAPE*> polySegments = shape->MakeEffectiveShapes( true );
1466
1467 if( !polySegments.empty() )
1468 {
1469 std::deque<VECTOR2D> pts;
1470
1471 for( SHAPE* polySegment : polySegments )
1472 pts.push_back( static_cast<SHAPE_SEGMENT*>( polySegment )->GetSeg().A );
1473
1474 pts.push_back(
1475 static_cast<SHAPE_SEGMENT*>( polySegments.back() )->GetSeg().B );
1476
1477 for( SHAPE* polySegment : polySegments )
1478 delete polySegment;
1479
1480 m_gal->DrawPolygon( pts );
1481 }
1482 break;
1483 }
1484
1485 case SHAPE_T::BEZIER:
1486 {
1487 m_gal->DrawCurve( shape->GetStart(), shape->GetBezierC1(),
1488 shape->GetBezierC2(), shape->GetEnd() );
1489 break;
1490 }
1491
1492 default:
1493 UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
1494 }
1495 };
1496
1497 if( aLayer == LAYER_SELECTION_SHADOWS )
1498 {
1499 if( eeconfig()->m_Selection.fill_shapes )
1500 {
1501 // Consider a NAND gate. We have no idea which side of the arc is "inside"
1502 // so we can't reliably fill.
1503 if( aShape->GetShape() == SHAPE_T::ARC )
1504 m_gal->SetIsFill( aShape->IsFilled() );
1505 else
1506 m_gal->SetIsFill( true );
1507
1508 m_gal->SetFillColor( color );
1509 }
1510 else
1511 {
1512 m_gal->SetIsFill( false );
1513 }
1514
1515 // We still always draw the stroke, as otherwise single-segment shapes
1516 // (like a line) don't get a shadow, and special-casing them looks inconsistent.
1517 m_gal->SetIsStroke( true );
1518 m_gal->SetLineWidth( getLineWidth( aShape, true ) );
1519 m_gal->SetStrokeColor( color );
1520
1521 drawShape( aShape );
1522 }
1523 else if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_NOTES_BACKGROUND
1524 || aLayer == LAYER_SHAPES_BACKGROUND )
1525 {
1526 switch( aShape->GetFillMode() )
1527 {
1528 case FILL_T::NO_FILL:
1529 break;
1530
1532 // Fill in the foreground layer
1533 break;
1534
1537 // Do not fill the shape in B&W print mode, to avoid to visible items inside the shape
1538 if( !m_schSettings.PrintBlackAndWhiteReq() )
1539 {
1540 m_gal->SetIsFill( true );
1541 m_gal->SetIsStroke( false );
1542 m_gal->SetFillColor( color );
1543
1544 drawShape( aShape );
1545 }
1546 break;
1547 }
1548 }
1549 else if( aLayer == LAYER_DEVICE || aLayer == LAYER_NOTES || aLayer == LAYER_PRIVATE_NOTES
1550 || aLayer == LAYER_RULE_AREAS )
1551 {
1552 // Shapes filled with the device colour must be filled in the foreground
1553 if( aShape->GetFillMode() == FILL_T::FILLED_SHAPE )
1554 {
1555 m_gal->SetIsFill( true );
1556 m_gal->SetIsStroke( false );
1557 m_gal->SetFillColor( color );
1558
1559 drawShape( aShape );
1560 }
1561
1562 float lineWidth = getLineWidth( aShape, drawingShadows );
1563
1564 if( lineWidth > 0 )
1565 {
1566 m_gal->SetIsFill( false );
1567 m_gal->SetIsStroke( true );
1568 m_gal->SetLineWidth( lineWidth );
1569 m_gal->SetStrokeColor( color );
1570
1571 if( lineStyle <= LINE_STYLE::FIRST_TYPE || drawingShadows )
1572 {
1573 drawShape( aShape );
1574 }
1575 else
1576 {
1577 std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapes( true );
1578
1579 for( SHAPE* shape : shapes )
1580 {
1581 STROKE_PARAMS::Stroke( shape, lineStyle, KiROUND( lineWidth ), &m_schSettings,
1582 [this]( const VECTOR2I& a, const VECTOR2I& b )
1583 {
1584 // DrawLine has problem with 0 length lines so enforce minimum
1585 if( a == b )
1586 m_gal->DrawLine( a+1, b );
1587 else
1588 m_gal->DrawLine( a, b );
1589 } );
1590 }
1591
1592 for( SHAPE* shape : shapes )
1593 delete shape;
1594 }
1595 }
1596 }
1597}
1598
1599
1600void SCH_PAINTER::draw( const SCH_TEXT* aText, int aLayer, bool aDimmed )
1601{
1602 if( !isUnitAndConversionShown( aText ) )
1603 return;
1604
1605 if( aText->IsPrivate() && !m_schSettings.m_IsSymbolEditor )
1606 return;
1607
1608 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1609
1610 if( m_schSettings.IsPrinting() && drawingShadows )
1611 return;
1612
1613 if( drawingShadows && !( aText->IsBrightened() || aText->IsSelected() ) )
1614 return;
1615
1616 switch( aText->Type() )
1617 {
1618 case SCH_SHEET_PIN_T: aLayer = LAYER_SHEETLABEL; break;
1619 case SCH_HIER_LABEL_T: aLayer = LAYER_HIERLABEL; break;
1620 case SCH_GLOBAL_LABEL_T: aLayer = LAYER_GLOBLABEL; break;
1621 case SCH_DIRECTIVE_LABEL_T: aLayer = LAYER_NETCLASS_REFS; break;
1622 case SCH_LABEL_T: aLayer = LAYER_LOCLABEL; break;
1623 case SCH_TEXT_T: aLayer = aText->GetParentSymbol() ? LAYER_DEVICE
1624 : LAYER_NOTES; break;
1625 default: aLayer = LAYER_NOTES; break;
1626 }
1627
1628 COLOR4D color = getRenderColor( aText, aLayer, drawingShadows, aDimmed );
1629
1630 if( m_schematic )
1631 {
1632 SCH_CONNECTION* conn = nullptr;
1633
1634 if( !aText->IsConnectivityDirty() )
1635 conn = aText->Connection();
1636
1637 if( conn && conn->IsBus() )
1638 color = getRenderColor( aText, LAYER_BUS, drawingShadows );
1639 }
1640
1641 if( !( aText->IsVisible() || aText->IsForceVisible() ) )
1642 {
1643 if( m_schSettings.m_IsSymbolEditor || eeconfig()->m_Appearance.show_hidden_fields )
1644 color = getRenderColor( aText, LAYER_HIDDEN, drawingShadows );
1645 else
1646 return;
1647 }
1648
1649 m_gal->SetStrokeColor( color );
1650 m_gal->SetFillColor( color );
1651
1652 wxString shownText( aText->GetShownText( true ) );
1653 VECTOR2I text_offset = aText->GetSchematicTextOffset( &m_schSettings );
1654 TEXT_ATTRIBUTES attrs = aText->GetAttributes();
1655 KIFONT::FONT* font = getFont( aText );
1656
1657 attrs.m_Angle = aText->GetDrawRotation();
1658 attrs.m_StrokeWidth = KiROUND( getTextThickness( aText ) );
1659
1660 if( drawingShadows && font->IsOutline() )
1661 {
1662 BOX2I bBox = aText->GetBoundingBox();
1663 bBox.Inflate( KiROUND( getTextThickness( aText ) * 2 ) );
1664
1665 m_gal->SetIsStroke( false );
1666 m_gal->SetIsFill( true );
1667 m_gal->DrawRectangle( bBox.GetPosition(), bBox.GetEnd() );
1668 }
1669 else if( aText->GetLayer() == LAYER_DEVICE )
1670 {
1671 BOX2I bBox = aText->GetBoundingBox();
1672 VECTOR2D pos = bBox.Centre();
1673
1674 // Due to the fact a shadow text can be drawn left or right aligned, it needs to be
1675 // offset by shadowWidth/2 to be drawn at the same place as normal text.
1676 // For some reason we need to slightly modify this offset for a better look (better
1677 // alignment of shadow shape), for KiCad font only.
1678 double shadowOffset = 0.0;
1679
1680 if( drawingShadows )
1681 {
1682 double shadowWidth = getShadowWidth( !aText->IsSelected() );
1683 attrs.m_StrokeWidth += getShadowWidth( !aText->IsSelected() );
1684
1685 const double adjust = 1.2f; // Value chosen after tests
1686 shadowOffset = shadowWidth/2.0f * adjust;
1687 }
1688
1689 if( attrs.m_Angle == ANGLE_VERTICAL )
1690 {
1691 switch( attrs.m_Halign )
1692 {
1694 pos.y = bBox.GetBottom() + shadowOffset;
1695 break;
1697 pos.y = ( bBox.GetTop() + bBox.GetBottom() ) / 2.0;
1698 break;
1700 pos.y = bBox.GetTop() - shadowOffset;
1701 break;
1703 wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) );
1704 break;
1705 }
1706 }
1707 else
1708 {
1709 switch( attrs.m_Halign )
1710 {
1712 pos.x = bBox.GetLeft() - shadowOffset;
1713 break;
1715 pos.x = ( bBox.GetLeft() + bBox.GetRight() ) / 2.0;
1716 break;
1718 pos.x = bBox.GetRight() + shadowOffset;
1719 break;
1721 wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) );
1722 break;
1723 }
1724 }
1725
1726 // Because the text vertical position is the bounding box center, the text is drawn as
1727 // vertically centered.
1729
1730 strokeText( *m_gal, shownText, pos, attrs, aText->GetFontMetrics() );
1731 }
1732 else if( drawingShadows )
1733 {
1734 m_gal->SetIsFill( false );
1735 m_gal->SetIsStroke( true );
1736 attrs.m_StrokeWidth += KiROUND( getShadowWidth( !aText->IsSelected() ) );
1737 attrs.m_Underlined = false;
1738
1739 // Fudge factors to match 6.0 positioning
1740 // New text stroking has width dependent offset but we need to center the shadow on the
1741 // stroke. NB this offset is in font.cpp also.
1742 int fudge = KiROUND( getShadowWidth( !aText->IsSelected() ) / 1.52 );
1743
1744 if( attrs.m_Halign == GR_TEXT_H_ALIGN_LEFT && attrs.m_Angle == ANGLE_0 )
1745 text_offset.x -= fudge;
1746 else if( attrs.m_Halign == GR_TEXT_H_ALIGN_RIGHT && attrs.m_Angle == ANGLE_90 )
1747 text_offset.y -= fudge;
1748 else if( attrs.m_Halign == GR_TEXT_H_ALIGN_RIGHT && attrs.m_Angle == ANGLE_0 )
1749 text_offset.x += fudge;
1750 else if( attrs.m_Halign == GR_TEXT_H_ALIGN_LEFT && attrs.m_Angle == ANGLE_90 )
1751 text_offset.y += fudge;
1752
1753 strokeText( *m_gal, shownText, aText->GetDrawPos() + text_offset, attrs,
1754 aText->GetFontMetrics() );
1755 }
1756 else
1757 {
1758 if( aText->IsHypertext() && aText->IsRollover() )
1759 {
1760 m_gal->SetStrokeColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
1761 m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
1762 attrs.m_Underlined = true;
1763 }
1764
1765 // Adjust text drawn in an outline font to more closely mimic the positioning of
1766 // SCH_FIELD text.
1767 if( font->IsOutline() && aText->Type() == SCH_TEXT_T )
1768 {
1769 BOX2I firstLineBBox = aText->GetTextBox( 0 );
1770 int sizeDiff = firstLineBBox.GetHeight() - aText->GetTextSize().y;
1771 int adjust = KiROUND( sizeDiff * 0.4 );
1772 VECTOR2I adjust_offset( 0, - adjust );
1773
1774 RotatePoint( adjust_offset, aText->GetDrawRotation() );
1775 text_offset += adjust_offset;
1776 }
1777
1778 if( nonCached( aText )
1779 && aText->RenderAsBitmap( m_gal->GetWorldScale() )
1780 && !shownText.Contains( wxT( "\n" ) ) )
1781 {
1782 bitmapText( *m_gal, shownText, aText->GetDrawPos() + text_offset, attrs );
1783 const_cast<SCH_TEXT*>( aText )->SetFlags( IS_SHOWN_AS_BITMAP );
1784 }
1785 else
1786 {
1787 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
1788
1789 if( !aText->IsHypertext() && font->IsOutline() )
1790 cache = aText->GetRenderCache( font, shownText, text_offset );
1791
1792 if( cache )
1793 {
1794 m_gal->SetLineWidth( attrs.m_StrokeWidth );
1795 m_gal->DrawGlyphs( *cache );
1796 }
1797 else
1798 {
1799 strokeText( *m_gal, shownText, aText->GetDrawPos() + text_offset, attrs,
1800 aText->GetFontMetrics() );
1801 }
1802
1803 const_cast<SCH_TEXT*>( aText )->ClearFlags( IS_SHOWN_AS_BITMAP );
1804 }
1805 }
1806
1807 // Draw anchor
1808 if( aText->IsSelected() )
1809 {
1810 bool showAnchor;
1811
1812 switch( aText->Type() )
1813 {
1814 case SCH_TEXT_T:
1815 showAnchor = true;
1816 break;
1817
1818 case SCH_LABEL_T:
1819 // Don't clutter things up if we're already showing a dangling indicator
1820 showAnchor = !static_cast<const SCH_LABEL*>( aText )->IsDangling();
1821 break;
1822
1824 case SCH_HIER_LABEL_T:
1825 case SCH_GLOBAL_LABEL_T:
1826 case SCH_SHEET_PIN_T:
1827 // These all have shapes and so don't need anchors
1828 showAnchor = false;
1829 break;
1830
1831 default:
1832 showAnchor = false;
1833 break;
1834 }
1835
1836 if( showAnchor )
1837 drawAnchor( aText->GetPosition(), drawingShadows );
1838 }
1839}
1840
1841
1842void SCH_PAINTER::draw( const SCH_TEXTBOX* aTextBox, int aLayer, bool aDimmed )
1843{
1844 if( aTextBox->Type() == SCH_TABLECELL_T )
1845 {
1846 const SCH_TABLECELL* cell = static_cast<const SCH_TABLECELL*>( aTextBox );
1847
1848 if( cell->GetColSpan() == 0 || cell->GetRowSpan() == 0 )
1849 return;
1850 }
1851
1852 if( !isUnitAndConversionShown( aTextBox ) )
1853 return;
1854
1855 if( aTextBox->IsPrivate() && !m_schSettings.m_IsSymbolEditor )
1856 return;
1857
1858 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1859
1860 if( m_schSettings.IsPrinting() && drawingShadows )
1861 return;
1862
1863 COLOR4D color = getRenderColor( aTextBox, aLayer, drawingShadows, aDimmed );
1864 COLOR4D bg = m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND );
1865 float borderWidth = getLineWidth( aTextBox, drawingShadows );
1866 KIFONT::FONT* font = getFont( aTextBox );
1867
1868 auto drawText =
1869 [&]()
1870 {
1871 wxString shownText = aTextBox->GetShownText( true );
1872 TEXT_ATTRIBUTES attrs = aTextBox->GetAttributes();
1873
1874 attrs.m_Angle = aTextBox->GetDrawRotation();
1875 attrs.m_StrokeWidth = KiROUND( getTextThickness( aTextBox ) );
1876
1877 if( aTextBox->IsHypertext() && aTextBox->IsRollover() )
1878 {
1879 m_gal->SetStrokeColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
1880 m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
1881 attrs.m_Underlined = true;
1882 }
1883
1884 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
1885
1886 if( !aTextBox->IsHypertext() && font->IsOutline() )
1887 cache = aTextBox->GetRenderCache( font, shownText );
1888
1889 if( cache )
1890 {
1891 m_gal->SetLineWidth( attrs.m_StrokeWidth );
1892 m_gal->DrawGlyphs( *cache );
1893 }
1894 else
1895 {
1896 strokeText( *m_gal, shownText, aTextBox->GetDrawPos(), attrs,
1897 aTextBox->GetFontMetrics() );
1898 }
1899 };
1900
1901 if( drawingShadows && !( aTextBox->IsBrightened() || aTextBox->IsSelected() ) )
1902 return;
1903
1904 m_gal->SetFillColor( color );
1905 m_gal->SetStrokeColor( color );
1906
1907 if( aLayer == LAYER_SELECTION_SHADOWS )
1908 {
1909 m_gal->SetIsFill( true );
1910 m_gal->SetIsStroke( false );
1911 m_gal->SetLineWidth( borderWidth );
1912
1913 m_gal->DrawRectangle( aTextBox->GetPosition(), aTextBox->GetEnd() );
1914 }
1915 else if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_NOTES_BACKGROUND
1916 || aLayer == LAYER_SHAPES_BACKGROUND )
1917 {
1918 // Do not fill the shape in B&W print mode, to avoid to visible items
1919 // inside the shape
1920 if( aTextBox->IsFilled() && !m_schSettings.PrintBlackAndWhiteReq() )
1921 {
1922 m_gal->SetIsFill( true );
1923 m_gal->SetIsStroke( false );
1924 m_gal->SetLineWidth( borderWidth );
1925
1926 m_gal->DrawRectangle( aTextBox->GetPosition(), aTextBox->GetEnd() );
1927 }
1928 }
1929 else if( aLayer == LAYER_DEVICE || aLayer == LAYER_NOTES || aLayer == LAYER_PRIVATE_NOTES )
1930 {
1931 drawText();
1932
1933 if( aTextBox->Type() != SCH_TABLECELL_T && borderWidth > 0 )
1934 {
1935 COLOR4D borderColor = aTextBox->GetStroke().GetColor();
1936 LINE_STYLE borderStyle = aTextBox->GetEffectiveLineStyle();
1937 double transparency = aTextBox->GetForcedTransparency();
1938
1939 if( m_schSettings.m_OverrideItemColors || aTextBox->IsBrightened()
1940 || borderColor == COLOR4D::UNSPECIFIED )
1941 {
1942 borderColor = m_schSettings.GetLayerColor( aLayer );
1943 }
1944
1945 if( transparency > 0.0 )
1946 borderColor = borderColor.WithAlpha( borderColor.a * ( 1.0 - transparency ) );
1947
1948 if( aDimmed )
1949 {
1950 borderColor = borderColor.Mix( bg, 0.5f );
1951 borderColor.Desaturate( );
1952 }
1953
1954 m_gal->SetIsFill( false );
1955 m_gal->SetIsStroke( true );
1956 m_gal->SetStrokeColor( borderColor );
1957 m_gal->SetLineWidth( borderWidth );
1958
1959 if( borderStyle <= LINE_STYLE::FIRST_TYPE || drawingShadows )
1960 {
1961 m_gal->DrawRectangle( aTextBox->GetPosition(), aTextBox->GetEnd() );
1962 }
1963 else
1964 {
1965 std::vector<SHAPE*> shapes = aTextBox->MakeEffectiveShapes( true );
1966
1967 for( SHAPE* shape : shapes )
1968 {
1969 STROKE_PARAMS::Stroke( shape, borderStyle, KiROUND( borderWidth ),
1970 &m_schSettings,
1971 [this]( const VECTOR2I& a, const VECTOR2I& b )
1972 {
1973 // DrawLine has problem with 0 length lines so enforce minimum
1974 if( a == b )
1975 m_gal->DrawLine( a+1, b );
1976 else
1977 m_gal->DrawLine( a, b );
1978 } );
1979 }
1980
1981 for( SHAPE* shape : shapes )
1982 delete shape;
1983 }
1984 }
1985 }
1986}
1987
1988
1989void SCH_PAINTER::draw( const SCH_TABLE* aTable, int aLayer, bool aDimmed )
1990{
1991 if( aTable->GetCells().empty() )
1992 return;
1993
1994 for( SCH_TABLECELL* cell : aTable->GetCells() )
1995 draw( cell, aLayer, aDimmed );
1996
1997 if( aLayer == LAYER_SELECTION_SHADOWS )
1998 return;
1999
2000 VECTOR2I pos = aTable->GetPosition();
2001 VECTOR2I end = aTable->GetEnd();
2002
2003 int lineWidth;
2004 COLOR4D color;
2005 LINE_STYLE lineStyle;
2006
2007 auto setupStroke =
2008 [&]( const STROKE_PARAMS& stroke )
2009 {
2010 lineWidth = stroke.GetWidth();
2011 color = stroke.GetColor();
2012 lineStyle = stroke.GetLineStyle();
2013
2014 if( lineWidth == 0 )
2015 lineWidth = m_schSettings.GetDefaultPenWidth();
2016
2018 color = m_schSettings.GetLayerColor( LAYER_NOTES );
2019
2020 if( lineStyle == LINE_STYLE::DEFAULT )
2021 lineStyle = LINE_STYLE::SOLID;
2022
2023 m_gal->SetIsFill( false );
2024 m_gal->SetIsStroke( true );
2025 m_gal->SetStrokeColor( color );
2026 m_gal->SetLineWidth( (float) lineWidth );
2027 };
2028
2029 auto strokeShape =
2030 [&]( const SHAPE& shape )
2031 {
2032 STROKE_PARAMS::Stroke( &shape, lineStyle, lineWidth, &m_schSettings,
2033 [&]( const VECTOR2I& a, const VECTOR2I& b )
2034 {
2035 // DrawLine has problem with 0 length lines so enforce minimum
2036 if( a == b )
2037 m_gal->DrawLine( a+1, b );
2038 else
2039 m_gal->DrawLine( a, b );
2040 } );
2041 };
2042
2043 auto strokeLine =
2044 [&]( const VECTOR2I& ptA, const VECTOR2I& ptB )
2045 {
2046 if( lineStyle <= LINE_STYLE::FIRST_TYPE )
2047 {
2048 m_gal->DrawLine( ptA, ptB );
2049 }
2050 else
2051 {
2052 SHAPE_SEGMENT seg( ptA, ptB );
2053 strokeShape( seg );
2054 }
2055 };
2056
2057 auto strokeRect =
2058 [&]( const VECTOR2I& ptA, const VECTOR2I& ptB )
2059 {
2060 if( lineStyle <= LINE_STYLE::FIRST_TYPE )
2061 {
2062 m_gal->DrawRectangle( ptA, ptB );
2063 }
2064 else
2065 {
2066 SHAPE_RECT rect( BOX2I( ptA, ptB - ptA ) );
2067 strokeShape( rect );
2068 }
2069 };
2070
2071 if( aTable->GetSeparatorsStroke().GetWidth() >= 0 )
2072 {
2073 setupStroke( aTable->GetSeparatorsStroke() );
2074
2075 if( aTable->StrokeColumns() )
2076 {
2077 for( int col = 0; col < aTable->GetColCount() - 1; ++col )
2078 {
2079 for( int row = 0; row < aTable->GetRowCount(); ++row )
2080 {
2081 SCH_TABLECELL* cell = aTable->GetCell( row, col );
2082 VECTOR2I topRight( cell->GetEndX(), cell->GetStartY() );
2083
2084 if( !cell->GetTextAngle().IsHorizontal() )
2085 topRight = VECTOR2I( cell->GetStartX(), cell->GetEndY() );
2086
2087 if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 )
2088 strokeLine( topRight, cell->GetEnd() );
2089 }
2090 }
2091 }
2092
2093 if( aTable->StrokeRows() )
2094 {
2095 for( int row = 0; row < aTable->GetRowCount() - 1; ++row )
2096 {
2097 for( int col = 0; col < aTable->GetColCount(); ++col )
2098 {
2099 SCH_TABLECELL* cell = aTable->GetCell( row, col );
2100 VECTOR2I botLeft( cell->GetStartX(), cell->GetEndY() );
2101
2102 if( !cell->GetTextAngle().IsHorizontal() )
2103 botLeft = VECTOR2I( cell->GetEndX(), cell->GetStartY() );
2104
2105 if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 )
2106 strokeLine( botLeft, cell->GetEnd() );
2107 }
2108 }
2109 }
2110 }
2111
2112 if( aTable->GetBorderStroke().GetWidth() >= 0 )
2113 {
2114 SCH_TABLECELL* first = aTable->GetCell( 0, 0 );
2115
2116 setupStroke( aTable->GetBorderStroke() );
2117
2118 if( aTable->StrokeHeader() )
2119 {
2120 if( !first->GetTextAngle().IsHorizontal() )
2121 strokeLine( VECTOR2I( first->GetEndX(), pos.y ), VECTOR2I( first->GetEndX(), first->GetEndY() ) );
2122 else
2123 strokeLine( VECTOR2I( pos.x, first->GetEndY() ), VECTOR2I( end.x, first->GetEndY() ) );
2124 }
2125
2126 if( aTable->StrokeExternal() )
2127 {
2128 if( !first->GetTextAngle().IsHorizontal() )
2129 {
2130 RotatePoint( pos, aTable->GetPosition(), ANGLE_90 );
2131 RotatePoint( end, aTable->GetPosition(), ANGLE_90 );
2132 }
2133
2134 strokeRect( pos, end );
2135 }
2136 }
2137}
2138
2139
2140wxString SCH_PAINTER::expandLibItemTextVars( const wxString& aSourceText,
2141 const SCH_SYMBOL* aSymbolContext )
2142{
2143 std::function<bool( wxString* )> symbolResolver =
2144 [&]( wxString* token ) -> bool
2145 {
2146 if( !m_schematic )
2147 return false;
2148
2149 return aSymbolContext->ResolveTextVar( &m_schematic->CurrentSheet(), token );
2150 };
2151
2152 return ExpandTextVars( aSourceText, &symbolResolver );
2153}
2154
2155
2156void SCH_PAINTER::draw( const SCH_SYMBOL* aSymbol, int aLayer )
2157{
2158 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2159 bool DNP = aSymbol->GetDNP();
2160 bool markExclusion = eeconfig()->m_Appearance.mark_sim_exclusions
2161 && aSymbol->GetExcludedFromSim();
2162
2163 if( m_schSettings.IsPrinting() && drawingShadows )
2164 return;
2165
2166 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2167 {
2168 for( const SCH_FIELD& field : aSymbol->GetFields() )
2169 draw( &field, aLayer, DNP || markExclusion );
2170 }
2171
2172 if( isFieldsLayer( aLayer ) )
2173 return;
2174
2175 if( drawingShadows && !( aSymbol->IsBrightened() || aSymbol->IsSelected() ) )
2176 {
2177 // Don't exit here; symbol may still have selected pins
2178 // return;
2179 }
2180
2181 int unit = m_schematic ? aSymbol->GetUnitSelection( &m_schematic->CurrentSheet() ) : 1;
2182 int bodyStyle = aSymbol->GetBodyStyle();
2183
2184 // Use dummy symbol if the actual couldn't be found (or couldn't be locked).
2185 LIB_SYMBOL* originalSymbol =
2186 aSymbol->GetLibSymbolRef() ? aSymbol->GetLibSymbolRef().get() : LIB_SYMBOL::GetDummy();
2187 std::vector<SCH_PIN*> originalPins = originalSymbol->GetPins( unit, bodyStyle );
2188
2189 // Copy the source so we can re-orient and translate it.
2190 LIB_SYMBOL tempSymbol( *originalSymbol );
2191 std::vector<SCH_PIN*> tempPins = tempSymbol.GetPins( unit, bodyStyle );
2192
2193 tempSymbol.SetFlags( aSymbol->GetFlags() );
2194
2195 OrientAndMirrorSymbolItems( &tempSymbol, aSymbol->GetOrientation() );
2196
2197 for( SCH_ITEM& tempItem : tempSymbol.GetDrawItems() )
2198 {
2199 tempItem.SetFlags( aSymbol->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED,
2200 tempItem.Move( aSymbol->GetPosition() );
2201
2202 if( tempItem.Type() == SCH_TEXT_T )
2203 {
2204 SCH_TEXT* textItem = static_cast<SCH_TEXT*>( &tempItem );
2205
2206 if( textItem->HasTextVars() )
2207 textItem->SetText( expandLibItemTextVars( textItem->GetText(), aSymbol ) );
2208 }
2209 else if( tempItem.Type() == SCH_TEXTBOX_T )
2210 {
2211 SCH_TEXTBOX* textboxItem = static_cast<SCH_TEXTBOX*>( &tempItem );
2212
2213 if( textboxItem->HasTextVars() )
2214 textboxItem->SetText( expandLibItemTextVars( textboxItem->GetText(), aSymbol ) );
2215 }
2216 }
2217
2218 // Copy the pin info from the symbol to the temp pins
2219 for( unsigned i = 0; i < tempPins.size(); ++ i )
2220 {
2221 SCH_PIN* symbolPin = aSymbol->GetPin( originalPins[ i ] );
2222 SCH_PIN* tempPin = tempPins[ i ];
2223
2224 tempPin->ClearFlags();
2225 tempPin->SetFlags( symbolPin->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED,
2226 // IS_SHOWN_AS_BITMAP
2227
2228 tempPin->SetName( expandLibItemTextVars( symbolPin->GetShownName(), aSymbol ) );
2229 tempPin->SetType( symbolPin->GetType() );
2230 tempPin->SetShape( symbolPin->GetShape() );
2231
2232 if( symbolPin->IsDangling() )
2233 tempPin->SetFlags( IS_DANGLING );
2234 else
2235 tempPin->ClearFlags( IS_DANGLING );
2236
2237 tempPin->SetOperatingPoint( symbolPin->GetOperatingPoint() );
2238 }
2239
2240 draw( &tempSymbol, aLayer, false, aSymbol->GetUnit(), aSymbol->GetBodyStyle(),
2241 DNP || markExclusion );
2242
2243 for( unsigned i = 0; i < tempPins.size(); ++i )
2244 {
2245 SCH_PIN* symbolPin = aSymbol->GetPin( originalPins[ i ] );
2246 SCH_PIN* tempPin = tempPins[ i ];
2247
2248 symbolPin->ClearFlags();
2249 tempPin->ClearFlags( IS_DANGLING ); // Clear this temporary flag
2250 symbolPin->SetFlags( tempPin->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED,
2251 // IS_SHOWN_AS_BITMAP
2252 }
2253
2254 if( DNP || markExclusion )
2255 {
2256 int layer = DNP ? LAYER_DNP_MARKER : LAYER_EXCLUDED_FROM_SIM;
2257 BOX2I bbox = aSymbol->GetBodyBoundingBox();
2258 BOX2I pins = aSymbol->GetBodyAndPinsBoundingBox();
2259 VECTOR2D margins( std::max( bbox.GetX() - pins.GetX(), pins.GetEnd().x - bbox.GetEnd().x ),
2260 std::max( bbox.GetY() - pins.GetY(), pins.GetEnd().y - bbox.GetEnd().y ) );
2261 int strokeWidth = 3 * schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
2262
2263 margins.x = std::max( margins.x * 0.6, margins.y * 0.3 );
2264 margins.y = std::max( margins.y * 0.6, margins.x * 0.3 );
2265 bbox.Inflate( KiROUND( margins.x ), KiROUND( margins.y ) );
2266
2267 VECTOR2I pt1 = bbox.GetOrigin();
2268 VECTOR2I pt2 = bbox.GetEnd();
2269
2270 GAL_SCOPED_ATTRS scopedAttrs( *m_gal, GAL_SCOPED_ATTRS::ALL_ATTRS );
2271 m_gal->AdvanceDepth();
2272 m_gal->SetIsStroke( true );
2273 m_gal->SetIsFill( true );
2274 m_gal->SetStrokeColor( m_schSettings.GetLayerColor( layer ) );
2275 m_gal->SetFillColor( m_schSettings.GetLayerColor( layer ) );
2276
2277 m_gal->DrawSegment( pt1, pt2, strokeWidth );
2278 std::swap( pt1.x, pt2.x );
2279 m_gal->DrawSegment( pt1, pt2, strokeWidth );
2280 }
2281}
2282
2283
2284void SCH_PAINTER::draw( const SCH_FIELD* aField, int aLayer, bool aDimmed )
2285{
2286 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2287
2288 if( m_schSettings.IsPrinting() && drawingShadows )
2289 return;
2290
2291 if( drawingShadows && !( aField->IsBrightened() || aField->IsSelected() ) )
2292 return;
2293
2294 if( !isUnitAndConversionShown( aField ) )
2295 return;
2296
2297 if( aField->IsPrivate() && !m_schSettings.m_IsSymbolEditor )
2298 return;
2299
2300 // Must check layer as fields are sometimes drawn by their parent rather than directly
2301 // from the view.
2302 std::vector<int> layers = aField->ViewGetLayers();
2303
2304 if( std::find( layers.begin(), layers.end(), aLayer ) == layers.end() )
2305 return;
2306
2307 aLayer = aField->GetLayer();
2308
2309 COLOR4D color = getRenderColor( aField, aLayer, drawingShadows, aDimmed );
2310
2311 if( !( aField->IsVisible() || aField->IsForceVisible() ) )
2312 {
2313 bool force_show = m_schematic ? eeconfig()->m_Appearance.show_hidden_fields
2314 : m_schSettings.m_ShowHiddenFields;
2315
2316 if( force_show )
2317 color = getRenderColor( aField, LAYER_HIDDEN, drawingShadows, aDimmed );
2318 else
2319 return;
2320 }
2321
2322 wxString shownText = aField->GetShownText( true );
2323
2324 if( shownText.IsEmpty() )
2325 return;
2326
2327 // Calculate the text orientation according to the parent orientation.
2328 EDA_ANGLE orient = aField->GetTextAngle();
2329
2330 if( aField->GetParent() && aField->GetParent()->Type() == SCH_SYMBOL_T )
2331 {
2332 if( static_cast<SCH_SYMBOL*>( aField->GetParent() )->GetTransform().y1 )
2333 {
2334 // Rotate symbol 90 degrees.
2335 if( orient.IsHorizontal() )
2336 orient = ANGLE_VERTICAL;
2337 else
2338 orient = ANGLE_HORIZONTAL;
2339 }
2340 }
2341
2342 /*
2343 * Calculate the text justification, according to the symbol orientation/mirror.
2344 * This is a bit complicated due to cumulative calculations:
2345 * - numerous cases (mirrored or not, rotation)
2346 * - the DrawGraphicText function recalculate also H and H justifications according to the
2347 * text orientation.
2348 * - when symbol is mirrored, the text is not mirrored and justifications are complicated
2349 * to calculate so the easier way is to use no justifications (centered text) and use
2350 * GetBoundingBox to know the text coordinate considered as centered
2351 */
2352 BOX2I bbox = aField->GetBoundingBox();
2353
2354 if( aField->GetParent() && aField->GetParent()->Type() == SCH_GLOBAL_LABEL_T )
2355 {
2356 SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( aField->GetParent() );
2357 bbox.Offset( label->GetSchematicTextOffset( &m_schSettings ) );
2358 }
2359
2360 if( m_schSettings.GetDrawBoundingBoxes() )
2361 drawItemBoundingBox( aField );
2362
2363 m_gal->SetStrokeColor( color );
2364 m_gal->SetFillColor( color );
2365
2366 if( drawingShadows && getFont( aField )->IsOutline() )
2367 {
2368 BOX2I shadow_box = bbox;
2369 shadow_box.Inflate( KiROUND( getTextThickness( aField ) * 2 ) );
2370
2371 m_gal->SetIsStroke( false );
2372 m_gal->SetIsFill( true );
2373 m_gal->DrawRectangle( shadow_box.GetPosition(), shadow_box.GetEnd() );
2374 }
2375 else
2376 {
2377 VECTOR2I textpos = bbox.Centre();
2378 TEXT_ATTRIBUTES attributes = aField->GetAttributes();
2379
2380 attributes.m_Halign = GR_TEXT_H_ALIGN_CENTER;
2381 attributes.m_Valign = GR_TEXT_V_ALIGN_CENTER;
2382 attributes.m_StrokeWidth = KiROUND( getTextThickness( aField ) );
2383 attributes.m_Angle = orient;
2384
2385 if( drawingShadows )
2386 attributes.m_StrokeWidth += getShadowWidth( !aField->IsSelected() );
2387
2388 if( aField->IsHypertext() && aField->IsRollover() )
2389 {
2390 m_gal->SetStrokeColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
2391 m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
2392 attributes.m_Underlined = true;
2393 }
2394
2395 if( nonCached( aField ) && aField->RenderAsBitmap( m_gal->GetWorldScale() ) )
2396 {
2397 bitmapText( *m_gal, shownText, textpos, attributes );
2398 const_cast<SCH_FIELD*>( aField )->SetFlags( IS_SHOWN_AS_BITMAP );
2399 }
2400 else
2401 {
2402 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
2403
2404 if( !aField->IsHypertext() )
2405 cache = aField->GetRenderCache( shownText, textpos, attributes );
2406
2407 if( cache )
2408 {
2409 m_gal->SetLineWidth( attributes.m_StrokeWidth );
2410 m_gal->DrawGlyphs( *cache );
2411 }
2412 else
2413 {
2414 strokeText( *m_gal, shownText, textpos, attributes, aField->GetFontMetrics() );
2415 }
2416
2417 const_cast<SCH_FIELD*>( aField )->ClearFlags( IS_SHOWN_AS_BITMAP );
2418 }
2419 }
2420
2421 // Draw anchor or umbilical line
2422 if( aField->IsMoving() && m_schematic )
2423 {
2424 VECTOR2I parentPos = aField->GetParentPosition();
2425
2426 m_gal->SetLineWidth( m_schSettings.GetOutlineWidth() );
2427 m_gal->SetStrokeColor( getRenderColor( aField, LAYER_SCHEMATIC_ANCHOR, drawingShadows ) );
2428 m_gal->DrawLine( aField->GetPosition(), parentPos );
2429 }
2430 else if( aField->IsSelected() )
2431 {
2432 drawAnchor( aField->GetPosition(), drawingShadows );
2433 }
2434}
2435
2436
2437void SCH_PAINTER::draw( const SCH_GLOBALLABEL* aLabel, int aLayer )
2438{
2439 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2440
2441 if( m_schSettings.IsPrinting() && drawingShadows )
2442 return;
2443
2444 bool drawingDangling = aLayer == LAYER_DANGLING;
2445
2446 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2447 {
2448 for( const SCH_FIELD& field : aLabel->GetFields() )
2449 draw( &field, aLayer, false );
2450 }
2451
2452 if( isFieldsLayer( aLayer ) )
2453 return;
2454
2455 if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
2456 return;
2457
2458 COLOR4D color = getRenderColor( aLabel, LAYER_GLOBLABEL, drawingShadows );
2459
2460 if( drawingDangling )
2461 {
2462 if( aLabel->IsDangling() )
2463 {
2464 drawDanglingIndicator( aLabel->GetTextPos(), color,
2466 drawingShadows, aLabel->IsBrightened() );
2467 }
2468
2469 return;
2470 }
2471
2472 std::vector<VECTOR2I> pts;
2473 std::deque<VECTOR2D> pts2;
2474
2475 aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() );
2476
2477 for( const VECTOR2I& p : pts )
2478 pts2.emplace_back( VECTOR2D( p.x, p.y ) );
2479
2480 m_gal->SetIsStroke( true );
2481 m_gal->SetLineWidth( getLineWidth( aLabel, drawingShadows ) );
2482 m_gal->SetStrokeColor( color );
2483
2484 if( drawingShadows )
2485 {
2486 m_gal->SetIsFill( eeconfig()->m_Selection.fill_shapes );
2487 m_gal->SetFillColor( color );
2488 m_gal->DrawPolygon( pts2 );
2489 }
2490 else
2491 {
2492 m_gal->SetIsFill( false );
2493 m_gal->DrawPolyline( pts2 );
2494 }
2495
2496 draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer, false );
2497}
2498
2499
2500void SCH_PAINTER::draw( const SCH_LABEL* aLabel, int aLayer )
2501{
2502 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2503
2504 if( m_schSettings.IsPrinting() && drawingShadows )
2505 return;
2506
2507 bool drawingDangling = aLayer == LAYER_DANGLING;
2508
2509 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2510 {
2511 for( const SCH_FIELD& field : aLabel->GetFields() )
2512 draw( &field, aLayer, false );
2513 }
2514
2515 if( isFieldsLayer( aLayer ) )
2516 return;
2517
2518 if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
2519 return;
2520
2521 COLOR4D color = getRenderColor( aLabel, LAYER_HIERLABEL, drawingShadows );
2522
2523 if( drawingDangling )
2524 {
2525 if( aLabel->IsDangling() )
2526 {
2527 drawDanglingIndicator( aLabel->GetTextPos(), color,
2529 drawingShadows, aLabel->IsBrightened() );
2530 }
2531
2532 return;
2533 }
2534
2535 draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer, false );
2536}
2537
2538
2539void SCH_PAINTER::draw( const SCH_HIERLABEL* aLabel, int aLayer, bool aDimmed )
2540{
2541 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2542
2543 if( m_schSettings.IsPrinting() && drawingShadows )
2544 return;
2545
2546 bool drawingDangling = aLayer == LAYER_DANGLING;
2547
2548 if( !( drawingShadows || drawingDangling ) || eeconfig()->m_Selection.draw_selected_children )
2549 {
2550 for( const SCH_FIELD& field : aLabel->GetFields() )
2551 draw( &field, aLayer, false );
2552 }
2553
2554 if( isFieldsLayer( aLayer ) )
2555 return;
2556
2557 if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
2558 return;
2559
2560 COLOR4D color = getRenderColor( aLabel, LAYER_HIERLABEL, drawingShadows, aDimmed );
2561
2562 if( drawingDangling )
2563 {
2564 if( aLabel->IsDangling() )
2565 {
2566 drawDanglingIndicator( aLabel->GetTextPos(), color,
2568 drawingShadows, aLabel->IsBrightened() );
2569 }
2570
2571 return;
2572 }
2573
2574 std::vector<VECTOR2I> i_pts;
2575 std::deque<VECTOR2D> d_pts;
2576
2577 aLabel->CreateGraphicShape( &m_schSettings, i_pts, (VECTOR2I)aLabel->GetTextPos() );
2578
2579 for( const VECTOR2I& i_pt : i_pts )
2580 d_pts.emplace_back( VECTOR2D( i_pt.x, i_pt.y ) );
2581
2582 m_gal->SetIsFill( true );
2583 m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
2584 m_gal->SetIsStroke( true );
2585 m_gal->SetLineWidth( getLineWidth( aLabel, drawingShadows ) );
2586 m_gal->SetStrokeColor( color );
2587 m_gal->DrawPolyline( d_pts );
2588
2589 draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer, false );
2590}
2591
2592
2593void SCH_PAINTER::draw( const SCH_DIRECTIVE_LABEL* aLabel, int aLayer )
2594{
2595 if( !eeconfig()->m_Appearance.show_directive_labels && !aLabel->IsSelected() )
2596 return;
2597
2598 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2599
2600 if( m_schSettings.IsPrinting() && drawingShadows )
2601 return;
2602
2603 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2604 {
2605 for( const SCH_FIELD& field : aLabel->GetFields() )
2606 draw( &field, aLayer, false );
2607 }
2608
2609 if( isFieldsLayer( aLayer ) )
2610 return;
2611
2612 if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
2613 return;
2614
2615 COLOR4D color = getRenderColor( aLabel, LAYER_NETCLASS_REFS, drawingShadows );
2616
2617 if( aLayer == LAYER_DANGLING )
2618 {
2619 if( aLabel->IsDangling() )
2620 {
2621 drawDanglingIndicator( aLabel->GetTextPos(), color,
2623 drawingShadows, aLabel->IsBrightened() );
2624 }
2625
2626 return;
2627 }
2628
2629 std::vector<VECTOR2I> pts;
2630 std::deque<VECTOR2D> pts2;
2631
2632 aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() );
2633
2634 for( const VECTOR2I& p : pts )
2635 pts2.emplace_back( VECTOR2D( p.x, p.y ) );
2636
2637 m_gal->SetIsFill( false );
2638 m_gal->SetFillColor( color );
2639 m_gal->SetIsStroke( true );
2640 m_gal->SetLineWidth( getLineWidth( aLabel, drawingShadows ) );
2641 m_gal->SetStrokeColor( color );
2642
2643 if( aLabel->GetShape() == LABEL_FLAG_SHAPE::F_DOT )
2644 {
2645 m_gal->DrawLine( pts2[0], pts2[1] );
2646 m_gal->SetIsFill( true );
2647 m_gal->DrawCircle( pts2[2], ( pts2[2] - pts2[1] ).EuclideanNorm() );
2648 }
2649 else if( aLabel->GetShape() == LABEL_FLAG_SHAPE::F_ROUND )
2650 {
2651 m_gal->DrawLine( pts2[0], pts2[1] );
2652 m_gal->DrawCircle( pts2[2], ( pts2[2] - pts2[1] ).EuclideanNorm() );
2653 }
2654 else
2655 {
2656 m_gal->DrawPolyline( pts2 );
2657 }
2658}
2659
2660
2661void SCH_PAINTER::draw( const SCH_SHEET* aSheet, int aLayer )
2662{
2663 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2664 bool DNP = aSheet->GetDNP();
2665 bool markExclusion = eeconfig()->m_Appearance.mark_sim_exclusions
2666 && aSheet->GetExcludedFromSim();
2667
2668 if( m_schSettings.IsPrinting() && drawingShadows )
2669 return;
2670
2671 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2672 {
2673 for( const SCH_FIELD& field : aSheet->GetFields() )
2674 draw( &field, aLayer, DNP || markExclusion );
2675
2676 for( SCH_SHEET_PIN* sheetPin : aSheet->GetPins() )
2677 draw( static_cast<SCH_HIERLABEL*>( sheetPin ), aLayer, DNP || markExclusion );
2678 }
2679
2680 if( isFieldsLayer( aLayer ) )
2681 return;
2682
2683 VECTOR2D pos = aSheet->GetPosition();
2684 VECTOR2D size = aSheet->GetSize();
2685
2686 if( aLayer == LAYER_SHEET_BACKGROUND )
2687 {
2688 // Do not fill the shape in B&W print mode, to avoid to visible items
2689 // inside the shape
2690 if( !m_schSettings.PrintBlackAndWhiteReq() )
2691 {
2692 m_gal->SetFillColor( getRenderColor( aSheet, LAYER_SHEET_BACKGROUND, true ) );
2693 m_gal->SetIsFill( true );
2694 m_gal->SetIsStroke( false );
2695
2696 m_gal->DrawRectangle( pos, pos + size );
2697 }
2698 }
2699
2700 if( aLayer == LAYER_SHEET || aLayer == LAYER_SELECTION_SHADOWS )
2701 {
2702 m_gal->SetStrokeColor( getRenderColor( aSheet, LAYER_SHEET, drawingShadows ) );
2703 m_gal->SetIsStroke( true );
2704 m_gal->SetLineWidth( getLineWidth( aSheet, drawingShadows ) );
2705 m_gal->SetIsFill( false );
2706
2707 m_gal->DrawRectangle( pos, pos + size );
2708 }
2709
2710 if( DNP || markExclusion )
2711 {
2712 int layer = DNP ? LAYER_DNP_MARKER : LAYER_EXCLUDED_FROM_SIM;
2713 BOX2I bbox = aSheet->GetBodyBoundingBox();
2714 BOX2I pins = aSheet->GetBoundingBox();
2715 VECTOR2D margins( std::max( bbox.GetX() - pins.GetX(), pins.GetEnd().x - bbox.GetEnd().x ),
2716 std::max( bbox.GetY() - pins.GetY(), pins.GetEnd().y - bbox.GetEnd().y ) );
2717 int strokeWidth = 3 * schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
2718
2719 margins.x = std::max( margins.x * 0.6, margins.y * 0.3 );
2720 margins.y = std::max( margins.y * 0.6, margins.x * 0.3 );
2721 bbox.Inflate( KiROUND( margins.x ), KiROUND( margins.y ) );
2722
2723 VECTOR2I pt1 = bbox.GetOrigin();
2724 VECTOR2I pt2 = bbox.GetEnd();
2725
2726 GAL_SCOPED_ATTRS scopedAttrs( *m_gal, GAL_SCOPED_ATTRS::ALL_ATTRS );
2727 m_gal->SetIsStroke( true );
2728 m_gal->SetIsFill( true );
2729 m_gal->SetStrokeColor( m_schSettings.GetLayerColor( layer ) );
2730 m_gal->SetFillColor( m_schSettings.GetLayerColor( layer ) );
2731
2732 m_gal->DrawSegment( pt1, pt2, strokeWidth );
2733 std::swap( pt1.x, pt2.x );
2734 m_gal->DrawSegment( pt1, pt2, strokeWidth );
2735 }
2736}
2737
2738
2739void SCH_PAINTER::draw( const SCH_NO_CONNECT* aNC, int aLayer )
2740{
2741 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2742
2743 if( m_schSettings.IsPrinting() && drawingShadows )
2744 return;
2745
2746 if( drawingShadows && !( aNC->IsBrightened() || aNC->IsSelected() ) )
2747 return;
2748
2749 m_gal->SetIsStroke( true );
2750 m_gal->SetLineWidth( getLineWidth( aNC, drawingShadows ) );
2751 m_gal->SetStrokeColor( getRenderColor( aNC, LAYER_NOCONNECT, drawingShadows ) );
2752 m_gal->SetIsFill( false );
2753
2754 VECTOR2D p = aNC->GetPosition();
2755 int delta = std::max( aNC->GetSize(), m_schSettings.GetDefaultPenWidth() * 3 ) / 2;
2756
2757 m_gal->DrawLine( p + VECTOR2D( -delta, -delta ), p + VECTOR2D( delta, delta ) );
2758 m_gal->DrawLine( p + VECTOR2D( -delta, delta ), p + VECTOR2D( delta, -delta ) );
2759}
2760
2761
2762void SCH_PAINTER::draw( const SCH_BUS_ENTRY_BASE *aEntry, int aLayer )
2763{
2765 SCH_LINE line( VECTOR2I(), layer );
2766 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2767 bool drawingNetColorHighlights = aLayer == LAYER_NET_COLOR_HIGHLIGHT;
2768 bool drawingDangling = aLayer == LAYER_DANGLING;
2769 bool drawingWires = aLayer == LAYER_WIRE;
2770 bool drawingBusses = aLayer == LAYER_BUS;
2771
2772 if( m_schSettings.IsPrinting() && drawingShadows )
2773 return;
2774
2775 bool highlightNetclassColors = false;
2776 EESCHEMA_SETTINGS* eeschemaCfg = eeconfig();
2777
2778 if( eeschemaCfg )
2779 {
2780 highlightNetclassColors = eeschemaCfg->m_Selection.highlight_netclass_colors;
2781 }
2782
2783 if( !highlightNetclassColors && drawingNetColorHighlights )
2784 return;
2785
2786 if( m_schSettings.m_OverrideItemColors && drawingNetColorHighlights )
2787 return;
2788
2789 if( drawingShadows && !( aEntry->IsBrightened() || aEntry->IsSelected() ) )
2790 return;
2791
2792 if( aEntry->IsSelected() )
2793 {
2794 line.SetSelected();
2795 // Never show unselected endpoints on bus entries
2796 line.SetFlags( STARTPOINT | ENDPOINT );
2797 }
2798 else if( aEntry->IsBrightened() )
2799 line.SetBrightened();
2800
2801 line.SetStartPoint( aEntry->GetPosition() );
2802 line.SetEndPoint( aEntry->GetEnd() );
2803 line.SetStroke( aEntry->GetStroke() );
2804 line.SetLineWidth( KiROUND( getLineWidth( aEntry, false ) ) );
2805
2806 COLOR4D color = getRenderColor( aEntry, LAYER_WIRE, drawingShadows );
2807
2808 if( aEntry->Type() == SCH_BUS_BUS_ENTRY_T )
2809 color = getRenderColor( aEntry, LAYER_BUS, drawingShadows );
2810
2811 if( highlightNetclassColors )
2812 {
2813 // Force default color for nets we are going to highlight
2814 if( drawingWires )
2815 color = m_schSettings.GetLayerColor( LAYER_WIRE );
2816 else if( drawingBusses )
2817 color = m_schSettings.GetLayerColor( LAYER_BUS );
2818 }
2819
2820 if( drawingNetColorHighlights )
2821 {
2822 // Don't draw highlights for default-colored nets
2823 if( ( aEntry->Type() == SCH_BUS_WIRE_ENTRY_T
2824 && color == m_schSettings.GetLayerColor( LAYER_WIRE ) )
2825 || ( aEntry->Type() == SCH_BUS_BUS_ENTRY_T
2826 && color == m_schSettings.GetLayerColor( LAYER_BUS ) ) )
2827 {
2828 return;
2829 }
2830 }
2831
2832 if( drawingDangling )
2833 {
2834 m_gal->SetIsFill( false );
2835 m_gal->SetIsStroke( true );
2836 m_gal->SetStrokeColor( color.Brightened( 0.3 ) );
2837 m_gal->SetLineWidth( m_schSettings.GetDanglingIndicatorThickness() );
2838
2839 if( aEntry->IsStartDangling() )
2840 {
2841 m_gal->DrawCircle( aEntry->GetPosition(),
2842 aEntry->GetPenWidth() + KiROUND( TARGET_BUSENTRY_RADIUS / 2.0 ) );
2843 }
2844
2845 if( aEntry->IsEndDangling() )
2846 {
2847 m_gal->DrawCircle( aEntry->GetEnd(),
2848 aEntry->GetPenWidth() + KiROUND( TARGET_BUSENTRY_RADIUS / 2.0 ) );
2849 }
2850 }
2851 else
2852 {
2853 line.SetLineColor( color );
2854 line.SetLineStyle( aEntry->GetEffectiveLineStyle() );
2855
2856 draw( &line, aLayer );
2857 }
2858}
2859
2860
2861void SCH_PAINTER::draw( const SCH_BITMAP* aBitmap, int aLayer )
2862{
2863 m_gal->Save();
2864 m_gal->Translate( aBitmap->GetPosition() );
2865
2866 const REFERENCE_IMAGE& refImage = aBitmap->GetReferenceImage();
2867
2868 // When the image scale factor is not 1.0, we need to modify the actual as the image scale
2869 // factor is similar to a local zoom
2870 const double img_scale = refImage.GetImageScale();
2871
2872 if( img_scale != 1.0 )
2873 m_gal->Scale( VECTOR2D( img_scale, img_scale ) );
2874
2875 if( aLayer == LAYER_DRAW_BITMAPS )
2876 {
2877 m_gal->DrawBitmap( refImage.GetImage() );
2878 }
2879
2880 if( aLayer == LAYER_SELECTION_SHADOWS )
2881 {
2882 if( aBitmap->IsSelected() || aBitmap->IsBrightened() )
2883 {
2884 const COLOR4D color = getRenderColor( aBitmap, LAYER_DRAW_BITMAPS, true );
2885 m_gal->SetIsStroke( true );
2886 m_gal->SetStrokeColor( color );
2887 m_gal->SetLineWidth ( getShadowWidth( aBitmap->IsBrightened() ) );
2888 m_gal->SetIsFill( false );
2889
2890 // Draws a bounding box.
2891 VECTOR2D bm_size( refImage.GetSize() );
2892 // bm_size is the actual image size in UI.
2893 // but m_gal scale was previously set to img_scale
2894 // so recalculate size relative to this image size.
2895 bm_size.x /= img_scale;
2896 bm_size.y /= img_scale;
2897 const VECTOR2D origin( -bm_size.x / 2.0, -bm_size.y / 2.0 );
2898 const VECTOR2D end = origin + bm_size;
2899
2900 m_gal->DrawRectangle( origin, end );
2901 }
2902 }
2903
2904 m_gal->Restore();
2905}
2906
2907
2908void SCH_PAINTER::draw( const SCH_MARKER* aMarker, int aLayer )
2909{
2910 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2911
2912 if( m_schSettings.IsPrinting() && drawingShadows )
2913 return;
2914
2915 if( drawingShadows && !( aMarker->IsBrightened() || aMarker->IsSelected() ) )
2916 return;
2917
2918 COLOR4D color = getRenderColor( aMarker, aMarker->GetColorLayer(), drawingShadows );
2919
2920 m_gal->Save();
2921 m_gal->Translate( aMarker->GetPosition() );
2922 m_gal->SetIsFill( !drawingShadows );
2923 m_gal->SetFillColor( color );
2924 m_gal->SetIsStroke( drawingShadows );
2925 m_gal->SetLineWidth( getLineWidth( aMarker, drawingShadows ) );
2926 m_gal->SetStrokeColor( color );
2927
2928 SHAPE_LINE_CHAIN polygon;
2929 aMarker->ShapeToPolygon( polygon );
2930
2931 m_gal->DrawPolygon( polygon );
2932 m_gal->Restore();
2933}
2934
2935
2936}; // namespace KIGFX
int color
Definition: DXF_plotter.cpp:60
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
BOX2< VECTOR2I > BOX2I
Definition: box2.h:922
std::optional< BOX2I > OPT_BOX2I
Definition: box2.h:926
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
constexpr const Vec & GetPosition() const
Definition: box2.h:211
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:558
constexpr const Vec GetEnd() const
Definition: box2.h:212
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:146
constexpr coord_type GetY() const
Definition: box2.h:208
constexpr size_type GetWidth() const
Definition: box2.h:214
constexpr Vec Centre() const
Definition: box2.h:97
constexpr coord_type GetX() const
Definition: box2.h:207
constexpr size_type GetHeight() const
Definition: box2.h:215
constexpr coord_type GetLeft() const
Definition: box2.h:228
constexpr void SetX(coord_type val)
Definition: box2.h:277
constexpr const Vec & GetOrigin() const
Definition: box2.h:210
constexpr void SetY(coord_type val)
Definition: box2.h:282
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:720
constexpr coord_type GetRight() const
Definition: box2.h:217
constexpr coord_type GetTop() const
Definition: box2.h:229
constexpr void Offset(coord_type dx, coord_type dy)
Definition: box2.h:259
constexpr coord_type GetBottom() const
Definition: box2.h:222
Represent basic circle geometry with utility geometry functions.
Definition: circle.h:33
VECTOR2I Center
Public to make access simpler.
Definition: circle.h:130
int Radius
Public to make access simpler.
Definition: circle.h:129
bool IsHorizontal() const
Definition: eda_angle.h:138
EDA_ANGLE Normalize180()
Definition: eda_angle.h:260
double AsRadians() const
Definition: eda_angle.h:117
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:77
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:127
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:129
bool IsSelected() const
Definition: eda_item.h:110
void SetSelected()
Definition: eda_item.h:119
void SetBrightened()
Definition: eda_item.h:120
EDA_ITEM * GetParent() const
Definition: eda_item.h:103
bool IsRollover() const
Definition: eda_item.h:114
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:131
bool IsBrightened() const
Definition: eda_item.h:112
bool IsForceVisible() const
Definition: eda_item.h:195
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:130
bool IsMoving() const
Definition: eda_item.h:108
bool IsNew() const
Definition: eda_item.h:107
int GetStartY() const
Definition: eda_shape.h:138
FILL_T GetFillMode() const
Definition: eda_shape.h:114
int GetEndX() const
Definition: eda_shape.h:176
bool IsFilled() const
Definition: eda_shape.h:98
SHAPE_T GetShape() const
Definition: eda_shape.h:132
int GetEndY() const
Definition: eda_shape.h:175
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:174
COLOR4D GetFillColor() const
Definition: eda_shape.h:118
int GetStartX() const
Definition: eda_shape.h:139
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:80
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:260
COLOR4D GetTextColor() const
Definition: eda_text.h:257
bool IsItalic() const
Definition: eda_text.h:156
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
virtual bool IsVisible() const
Definition: eda_text.h:174
KIFONT::FONT * GetFont() const
Definition: eda_text.h:234
BOX2I GetTextBox(int aLine=-1) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:721
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:662
virtual EDA_ANGLE GetDrawRotation() const
Definition: eda_text.h:365
virtual VECTOR2I GetDrawPos() const
Definition: eda_text.h:366
bool HasTextVars() const
Indicates the ShownText has text var references which need to be processed.
Definition: eda_text.h:117
const TEXT_ATTRIBUTES & GetAttributes() const
Definition: eda_text.h:218
bool IsBold() const
Definition: eda_text.h:171
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:268
VECTOR2I GetTextSize() const
Definition: eda_text.h:248
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:95
FONT is an abstract base class for both outline and stroke fonts.
Definition: font.h:131
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
Definition: font.cpp:146
virtual bool IsStroke() const
Definition: font.h:138
void Draw(KIGFX::GAL *aGal, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aCursor, const TEXT_ATTRIBUTES &aAttributes, const METRICS &aFontMetrics) const
Draw a string.
Definition: font.cpp:249
virtual bool IsOutline() const
Definition: font.h:139
VECTOR2I StringBoundaryLimits(const wxString &aText, const VECTOR2I &aSize, int aThickness, bool aBold, bool aItalic, const METRICS &aFontMetrics) const
Compute the boundary limits of aText (the bounding box of all shapes).
Definition: font.cpp:426
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:311
COLOR4D & Invert()
Makes the color inverted, alpha remains the same.
Definition: color4d.h:242
double a
Alpha component.
Definition: color4d.h:395
COLOR4D Brightened(double aFactor) const
Return a color that is brighter by a given factor, without modifying object.
Definition: color4d.h:268
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition: color4d.h:398
COLOR4D & Desaturate()
Removes color (in HSL model)
Definition: color4d.cpp:511
COLOR4D Mix(const COLOR4D &aColor, double aFactor) const
Return a color that is mixed with the input by a factor.
Definition: color4d.h:295
Attribute save/restore for GAL attributes.
Abstract interface for drawing on a 2D-surface.
virtual void DrawPolygon(const std::deque< VECTOR2D > &aPointList)
Draw a polygon.
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
virtual void Rotate(double aAngle)
Rotate the context.
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)
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
virtual void Translate(const VECTOR2D &aTranslation)
Translate the context.
const MATRIX3x3D & GetScreenWorldMatrix() const
Get the screen <-> world transformation matrix.
virtual void Restore()
Restore the context.
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.
virtual void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a line.
void SetGlyphSize(const VECTOR2I aSize)
virtual void DrawArc(const VECTOR2D &aCenterPoint, double aRadius, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aAngle)
Draw an arc.
virtual void BitmapText(const wxString &aText, const VECTOR2I &aPosition, const EDA_ANGLE &aAngle)
Draw a text using a bitmap font.
virtual void Save()
Save the context.
double GetWorldScale() const
Get the world scale.
Contains all the knowledge about how to draw graphical object onto any particular output device.
Definition: painter.h:59
GAL * m_gal
Instance of graphic abstraction layer that gives an interface to call commands used to draw (eg.
Definition: painter.h:102
const wxString & GetDefaultFont() const
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
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.
COLOR4D getRenderColor(const SCH_ITEM *aItem, int aLayer, bool aDrawingShadows, bool aDimmed=false) const
float getShadowWidth(bool aForHighlight) const
KIFONT::FONT * getFont(const EDA_TEXT *aText) const
void draw(const EDA_ITEM *, int, bool aDimmed)
static std::vector< KICAD_T > g_ScaledSelectionTypes
Definition: sch_painter.h:133
SCH_RENDER_SETTINGS m_schSettings
Definition: sch_painter.h:136
bool nonCached(const EDA_ITEM *aItem)
SCH_PAINTER(GAL *aGal)
void drawItemBoundingBox(const EDA_ITEM *aItem)
bool isUnitAndConversionShown(const SCH_ITEM *aItem) const
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:86
double GetForcedTransparency() const
Definition: view_item.h:165
Define a library symbol object.
Definition: lib_symbol.h:84
std::vector< SCH_PIN * > GetPins(int aUnit, int aBodyStyle) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:851
bool IsAlias() const
Definition: lib_symbol.h:206
static LIB_SYMBOL * GetDummy()
Returns a dummy LIB_SYMBOL, used when one is missing in the schematic.
Definition: lib_symbol.cpp:227
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:531
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:333
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:295
A pin layout helper is a class that manages the layout of the parts of a pin on a schematic symbol:
OPT_BOX2I GetAltIconBBox()
Get the box of the alt mode icon, if there is one.
std::optional< TEXT_INFO > GetPinNameInfo(int aShadowWidth)
Get the text info for the pin name.
std::optional< TEXT_INFO > GetPinElectricalTypeInfo(int aShadowWidth)
CIRCLE GetDanglingIndicator() const
Gets the dangling indicator geometry for this pin, if the pin were to be dangling.
std::optional< TEXT_INFO > GetPinNumberInfo(int aShadowWidth)
void SetRenderParameters(int aNameThickness, int aNumberThickness, bool aShowElectricalType, bool aShowAltIcons)
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
VECTOR2I GetSize() const
const BITMAP_BASE & GetImage() const
Get the underlying image.
double GetImageScale() const
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:40
VECTOR2I GetPosition() const override
Definition: sch_bitmap.cpp:115
REFERENCE_IMAGE & GetReferenceImage()
Definition: sch_bitmap.h:51
Base class for a bus or wire entry.
Definition: sch_bus_entry.h:38
bool IsStartDangling() const
Definition: sch_bus_entry.h:43
VECTOR2I GetPosition() const override
bool IsEndDangling() const
Definition: sch_bus_entry.h:44
virtual STROKE_PARAMS GetStroke() const override
Definition: sch_bus_entry.h:81
int GetPenWidth() const override
VECTOR2I GetEnd() const
LINE_STYLE GetEffectiveLineStyle() 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:1622
virtual bool IsDangling() const override
Determines dangling state from connectivity and cached connected rule areas.
Definition: sch_label.cpp:1780
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_field.cpp:616
VECTOR2I GetPosition() const override
Definition: sch_field.cpp:1485
bool IsHypertext() const override
Allow items to support hypertext actions when hovered/clicked.
Definition: sch_field.h:101
std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
Definition: sch_field.cpp:560
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
Definition: sch_field.cpp:211
std::vector< std::unique_ptr< KIFONT::GLYPH > > * GetRenderCache(const wxString &forResolvedText, const VECTOR2I &forPosition, TEXT_ATTRIBUTES &aAttrs) const
Definition: sch_field.cpp:383
VECTOR2I GetParentPosition() const
Definition: sch_field.cpp:1501
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:1927
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:1822
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:2037
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:167
const SYMBOL * GetParentSymbol() const
Definition: sch_item.cpp:166
int GetBodyStyle() const
Definition: sch_item.h:233
std::vector< int > ViewGetLayers() const override
Return the layers the item is drawn on (which may be more than its "home" layer)
Definition: sch_item.cpp:202
int GetUnit() const
Definition: sch_item.h:230
bool IsPrivate() const
Definition: sch_item.h:236
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:282
bool RenderAsBitmap(double aWorldScale) const override
Definition: sch_item.cpp:487
bool IsConnectivityDirty() const
Definition: sch_item.h:511
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:218
wxString GetClass() const override
Return the class name.
Definition: sch_item.h:177
const KIFONT::METRICS & GetFontMetrics() const
Definition: sch_item.cpp:464
int GetEffectivePenWidth(const SCH_RENDER_SETTINGS *aSettings) const
Definition: sch_item.cpp:473
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition: sch_item.h:182
int GetEffectiveDiameter() const
VECTOR2I GetPosition() const override
Definition: sch_junction.h:107
bool IsDangling() const override
Definition: sch_label.h:324
LABEL_FLAG_SHAPE GetShape() const
Definition: sch_label.h:177
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:201
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:41
void SetStartPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:137
bool IsWire() const
Return true if the line is a wire.
Definition: sch_line.cpp:956
bool IsStartDangling() const
Definition: sch_line.h:266
void SetLineColor(const COLOR4D &aColor)
Definition: sch_line.cpp:243
void SetLineWidth(const int aSize)
Definition: sch_line.cpp:300
LINE_STYLE GetEffectiveLineStyle() const
Definition: sch_line.cpp:287
VECTOR2I GetMidPoint() const
Definition: sch_line.h:139
VECTOR2I GetEndPoint() const
Definition: sch_line.h:141
VECTOR2I GetStartPoint() const
Definition: sch_line.h:136
bool IsEndDangling() const
Definition: sch_line.h:267
bool IsBus() const
Return true if the line is a bus.
Definition: sch_line.cpp:962
void SetLineStyle(const LINE_STYLE aStyle)
Definition: sch_line.cpp:280
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: sch_line.h:190
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:142
const wxString & GetOperatingPoint() const
Definition: sch_line.h:317
SCH_LAYER_ID GetColorLayer() const
Definition: sch_marker.cpp:307
VECTOR2I GetPosition() const override
Definition: sch_marker.h:106
int GetSize() const
VECTOR2I GetPosition() const override
int GetNumberTextSize() const
Definition: sch_pin.cpp:564
int GetLength() const
Definition: sch_pin.cpp:295
const wxString & GetOperatingPoint() const
Definition: sch_pin.h:283
void SetName(const wxString &aName)
Definition: sch_pin.cpp:406
bool IsGlobalPower() const
Return whether this pin forms a global power connection: i.e., is part of a power symbol and of type ...
Definition: sch_pin.cpp:367
bool IsVisible() const
Definition: sch_pin.cpp:374
VECTOR2I GetPinRoot() const
Definition: sch_pin.cpp:588
bool IsDangling() const override
Definition: sch_pin.cpp:419
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: sch_pin.h:88
VECTOR2I GetPosition() const override
Definition: sch_pin.cpp:252
int GetNameTextSize() const
Definition: sch_pin.cpp:540
wxString GetShownName() const
Definition: sch_pin.cpp:504
PIN_LAYOUT_CACHE & GetLayoutCache() const
Get the layout cache associated with this pin.
Definition: sch_pin.h:297
void SetOperatingPoint(const wxString &aText)
Definition: sch_pin.h:284
void SetType(ELECTRICAL_PINTYPE aType)
Definition: sch_pin.cpp:329
GRAPHIC_PINSHAPE GetShape() const
Definition: sch_pin.cpp:274
ELECTRICAL_PINTYPE GetType() const
Definition: sch_pin.cpp:309
std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const override
Make a set of SHAPE objects representing the SCH_SHAPE.
Definition: sch_shape.h:99
LINE_STYLE GetEffectiveLineStyle() const
Definition: sch_shape.h:60
STROKE_PARAMS GetStroke() const override
Definition: sch_shape.h:55
VECTOR2I GetPosition() const override
Definition: sch_shape.h:72
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:57
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:92
VECTOR2I GetSize() const
Definition: sch_sheet.h:111
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:399
const BOX2I GetBodyBoundingBox() const
Return a bounding box for the sheet body but not the fields.
Definition: sch_sheet.cpp:717
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_sheet.cpp:738
KIGFX::COLOR4D GetBorderColor() const
Definition: sch_sheet.h:117
bool GetExcludedFromSim() const override
Definition: sch_sheet.h:369
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:180
bool GetDNP() const
Set or clear the 'Do Not Populate' flaga.
Definition: sch_sheet.h:386
KIGFX::COLOR4D GetBackgroundColor() const
Definition: sch_sheet.h:120
Schematic symbol object.
Definition: sch_symbol.h:77
BOX2I GetBodyAndPinsBoundingBox() const override
Return a bounding box for the symbol body and pins but not the fields.
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) override
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:953
VECTOR2I GetPosition() const override
Definition: sch_symbol.h:774
bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the symbol.
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
Definition: sch_symbol.cpp:831
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
int GetOrientation() const override
Get the display symbol orientation.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:185
BOX2I GetBodyBoundingBox() const override
Return a bounding box for the symbol body but not the pins or fields.
int GetColSpan() const
Definition: sch_tablecell.h:61
int GetRowSpan() const
Definition: sch_tablecell.h:64
const STROKE_PARAMS & GetSeparatorsStroke() const
Definition: sch_table.h:72
bool StrokeExternal() const
Definition: sch_table.h:54
std::vector< SCH_TABLECELL * > GetCells() const
Definition: sch_table.h:142
const STROKE_PARAMS & GetBorderStroke() const
Definition: sch_table.h:60
VECTOR2I GetPosition() const override
Definition: sch_table.cpp:115
VECTOR2I GetEnd() const
Definition: sch_table.cpp:135
int GetColCount() const
Definition: sch_table.h:105
SCH_TABLECELL * GetCell(int aRow, int aCol) const
Definition: sch_table.h:132
bool StrokeColumns() const
Definition: sch_table.h:84
bool StrokeRows() const
Definition: sch_table.h:87
int GetRowCount() const
Definition: sch_table.h:107
bool StrokeHeader() const
Definition: sch_table.h:57
virtual wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
VECTOR2I GetDrawPos() const override
bool IsHypertext() const override
Allow items to support hypertext actions when hovered/clicked.
Definition: sch_textbox.h:86
bool IsHypertext() const override
Allow items to support hypertext actions when hovered/clicked.
Definition: sch_text.h:78
VECTOR2I GetPosition() const override
Definition: sch_text.h:141
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_text.cpp:385
virtual wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
Definition: sch_text.cpp:406
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:72
VECTOR2I B
Definition: seg.h:50
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void Fracture()
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
const SEG & GetSeg() const
An abstract shape on 2D plane.
Definition: shape.h:126
Simple container to manage line stroke parameters.
Definition: stroke_params.h:93
int GetWidth() const
KIGFX::COLOR4D GetColor() const
static void Stroke(const SHAPE *aShape, LINE_STYLE aLineStyle, int aWidth, const KIGFX::RENDER_SETTINGS *aRenderSettings, const std::function< void(const VECTOR2I &a, const VECTOR2I &b)> &aStroker)
const TRANSFORM & GetTransform() const
Definition: symbol.h:191
bool GetDNP() const
Set or clear the 'Do Not Populate' flag.
Definition: symbol.h:186
bool GetExcludedFromSim() const override
Definition: symbol.h:169
KIGFX::COLOR4D m_Color
GR_TEXT_H_ALIGN_T m_Halign
GR_TEXT_V_ALIGN_T m_Valign
KIFONT::FONT * m_Font
int y1
Definition: transform.h:49
@ LIGHTRED
Definition: color4d.h:65
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
Definition: common.cpp:59
The common library.
#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 UNSELECTED_END_SIZE
The size of the rectangle indicating the anchor of a text object (including fields)
#define TEXT_ANCHOR_SIZE
The default pin len value when creating pins(can be changed in preference menu)
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:401
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:403
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition: eda_angle.h:398
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition: eda_angle.h:397
static constexpr EDA_ANGLE ANGLE_270
Definition: eda_angle.h:406
static constexpr EDA_ANGLE ANGLE_180
Definition: eda_angle.h:405
#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.
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
@ FILLED_WITH_COLOR
@ FILLED_WITH_BG_BODYCOLOR
@ FILLED_SHAPE
Fill with object color.
int GetPenSizeForDemiBold(int aTextSize)
Definition: gr_text.cpp:42
int ClampTextPenSize(int aPenSize, int aSize, bool aStrict)
Pen width should not allow characters to become cluttered up in their own fatness.
Definition: gr_text.cpp:72
@ LAYER_DRAW_BITMAPS
Draw images.
Definition: layer_ids.h:246
SCH_LAYER_ID
Eeschema drawing layers.
Definition: layer_ids.h:401
@ LAYER_DANGLING
Definition: layer_ids.h:429
@ LAYER_SHAPES_BACKGROUND
Definition: layer_ids.h:435
@ LAYER_SHEETNAME
Definition: layer_ids.h:424
@ LAYER_SCHEMATIC_ANCHOR
Definition: layer_ids.h:451
@ LAYER_SHEETLABEL
Definition: layer_ids.h:427
@ LAYER_PINNUM
Definition: layer_ids.h:410
@ LAYER_RULE_AREAS
Definition: layer_ids.h:417
@ LAYER_DEVICE
Definition: layer_ids.h:418
@ LAYER_SHEET_BACKGROUND
Definition: layer_ids.h:437
@ LAYER_EXCLUDED_FROM_SIM
Definition: layer_ids.h:434
@ LAYER_BRIGHTENED
Definition: layer_ids.h:443
@ LAYER_HIDDEN
Definition: layer_ids.h:444
@ LAYER_HIERLABEL
Definition: layer_ids.h:409
@ LAYER_PINNAM
Definition: layer_ids.h:411
@ LAYER_PRIVATE_NOTES
Definition: layer_ids.h:420
@ LAYER_HOVERED
Definition: layer_ids.h:442
@ LAYER_GLOBLABEL
Definition: layer_ids.h:408
@ LAYER_WIRE
Definition: layer_ids.h:404
@ LAYER_NOTES
Definition: layer_ids.h:419
@ LAYER_NET_COLOR_HIGHLIGHT
Definition: layer_ids.h:445
@ LAYER_PIN
Definition: layer_ids.h:422
@ LAYER_VALUEPART
Definition: layer_ids.h:413
@ LAYER_BUS
Definition: layer_ids.h:405
@ LAYER_FIELDS
Definition: layer_ids.h:414
@ LAYER_DEVICE_BACKGROUND
Definition: layer_ids.h:436
@ LAYER_LOCLABEL
Definition: layer_ids.h:407
@ LAYER_SHEETFIELDS
Definition: layer_ids.h:426
@ LAYER_REFERENCEPART
Definition: layer_ids.h:412
@ LAYER_NETCLASS_REFS
Definition: layer_ids.h:416
@ LAYER_NOTES_BACKGROUND
Definition: layer_ids.h:421
@ LAYER_OP_CURRENTS
Definition: layer_ids.h:453
@ LAYER_SHEET
Definition: layer_ids.h:423
@ LAYER_SELECTION_SHADOWS
Definition: layer_ids.h:446
@ LAYER_SCHEMATIC_BACKGROUND
Definition: layer_ids.h:440
@ LAYER_INTERSHEET_REFS
Definition: layer_ids.h:415
@ LAYER_OP_VOLTAGES
Definition: layer_ids.h:452
@ LAYER_SHEETFILENAME
Definition: layer_ids.h:425
@ LAYER_DNP_MARKER
Definition: layer_ids.h:430
@ LAYER_NOCONNECT
Definition: layer_ids.h:428
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:96
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:247
static void boxText(KIGFX::GAL &aGal, const wxString &aText, const VECTOR2D &aPosition, const TEXT_ATTRIBUTES &aAttrs, const KIFONT::METRICS &aFontMetrics)
static void bitmapText(KIGFX::GAL &aGal, const wxString &aText, const VECTOR2D &aPosition, const TEXT_ATTRIBUTES &aAttrs)
EESCHEMA_SETTINGS * eeconfig()
Definition: sch_painter.cpp:72
static void strokeText(KIGFX::GAL &aGal, const wxString &aText, const VECTOR2D &aPosition, const TEXT_ATTRIBUTES &aAttrs, const KIFONT::METRICS &aFontMetrics)
static void knockoutText(KIGFX::GAL &aGal, const wxString &aText, const VECTOR2D &aPosition, const TEXT_ATTRIBUTES &aAttrs, const KIFONT::METRICS &aFontMetrics)
static void drawAltPinModesIcon(GAL &aGal, const VECTOR2D &aPos, double aSize, bool aBaseSelected, bool aRotate, int aExtraLineWidth, const COLOR4D &aColor)
Draw an alternate pin mode indicator icon.
static bool isFieldsLayer(int aLayer)
static BOX2I GetTextExtents(const wxString &aText, const VECTOR2D &aPosition, KIFONT::FONT &aFont, const TEXT_ATTRIBUTES &aAttrs, const KIFONT::METRICS &aFontMetrics)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:390
see class PGM_BASE
@ PT_NC
not connected (must be left open)
#define TARGET_BUSENTRY_RADIUS
Definition: sch_bus_entry.h:31
#define BITMAP_FONT_SIZE_THRESHOLD
Definition: sch_item.cpp:49
@ F_DOT
Definition: sch_label.h:106
@ F_ROUND
Definition: sch_label.h:107
static int externalPinDecoSize(const RENDER_SETTINGS *aSettings, const SCH_PIN &aPin)
Utility for getting the size of the 'external' pin decorators (as a radius)
Definition: sch_pin.cpp:89
static int internalPinDecoSize(const RENDER_SETTINGS *aSettings, const SCH_PIN &aPin)
Utility for getting the size of the 'internal' pin decorators (as a radius)
Definition: sch_pin.cpp:76
#define TARGET_PIN_RADIUS
Definition: sch_pin.h:36
Utility functions for working with shapes.
LINE_STYLE
Dashed line types.
Definition: stroke_params.h:46
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
void OrientAndMirrorSymbolItems(LIB_SYMBOL *aSymbol, int aOrientation)
Rotate and/or mirror graphic objects of LIB_SYMBOL aSymbol according to aOrientMirror.
constexpr int delta
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_H_ALIGN_INDETERMINATE
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_INDETERMINATE
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:229
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
Definition: trigo.cpp:521
@ SCH_TABLE_T
Definition: typeinfo.h:165
@ SCH_LINE_T
Definition: typeinfo.h:163
@ LIB_SYMBOL_T
Definition: typeinfo.h:148
@ SCH_NO_CONNECT_T
Definition: typeinfo.h:160
@ SCH_SYMBOL_T
Definition: typeinfo.h:172
@ SCH_TABLECELL_T
Definition: typeinfo.h:166
@ SCH_FIELD_T
Definition: typeinfo.h:150
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:171
@ SCH_LABEL_T
Definition: typeinfo.h:167
@ SCH_SHEET_T
Definition: typeinfo.h:174
@ SCH_MARKER_T
Definition: typeinfo.h:158
@ SCH_SHAPE_T
Definition: typeinfo.h:149
@ SCH_RULE_AREA_T
Definition: typeinfo.h:170
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:169
@ SCH_BUS_BUS_ENTRY_T
Definition: typeinfo.h:162
@ SCH_LABEL_LOCATE_ANY_T
Definition: typeinfo.h:190
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:173
@ SCH_TEXT_T
Definition: typeinfo.h:151
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:161
@ SCH_BITMAP_T
Definition: typeinfo.h:164
@ SCH_TEXTBOX_T
Definition: typeinfo.h:152
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:168
@ SCH_JUNCTION_T
Definition: typeinfo.h:159
@ SCH_PIN_T
Definition: typeinfo.h:153
constexpr int sign(T val)
Definition: util.h:159
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695
VECTOR2< double > VECTOR2D
Definition: vector2d.h:694