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