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 std::vector<int> layers = item.ViewGetLayers();
730
731 return std::find( layers.begin(), layers.end(), layer ) != layers.end();
732 };
733
734 for( const SCH_ITEM& item : drawnSymbol->GetDrawItems() )
735 {
736 if( !aDrawFields && item.Type() == SCH_FIELD_T )
737 continue;
738
739 if( !childOnLayer( item, aLayer ) )
740 continue;
741
742 if( aUnit && item.GetUnit() && aUnit != item.GetUnit() )
743 continue;
744
745 if( aBodyStyle && item.GetBodyStyle() && aBodyStyle != item.GetBodyStyle() )
746 continue;
747
748 draw( &item, aLayer, aDimmed );
749 }
750}
751
752
753int SCH_PAINTER::internalPinDecoSize( const SCH_PIN &aPin )
754{
755 if( m_schSettings.m_PinSymbolSize > 0 )
756 return m_schSettings.m_PinSymbolSize;
757
758 return aPin.GetNameTextSize() != 0 ? aPin.GetNameTextSize() / 2 : aPin.GetNumberTextSize() / 2;
759}
760
761
762// Utility for getting the size of the 'external' pin decorators (as a radius)
763// i.e. the negation circle, the polarity 'slopes' and the nonlogic marker
764int SCH_PAINTER::externalPinDecoSize( const SCH_PIN &aPin )
765{
766 if( m_schSettings.m_PinSymbolSize > 0 )
767 return m_schSettings.m_PinSymbolSize;
768
769 return aPin.GetNumberTextSize() / 2;
770}
771
772
773// Draw the target (an open circle) for a pin which has no connection or is being moved.
774void SCH_PAINTER::drawPinDanglingIndicator( const SCH_PIN& aPin, const COLOR4D& aColor,
775 bool aDrawingShadows, bool aBrightened )
776{
777 const PIN_LAYOUT_CACHE& plc = aPin.GetLayoutCache();
778 const CIRCLE c = plc.GetDanglingIndicator();
779
780 float lineWidth = aDrawingShadows ? getShadowWidth( aBrightened )
781 : m_schSettings.GetDanglingIndicatorThickness();
782
783 // Dangling symbols must be drawn in a slightly different colour so they can be seen when
784 // they overlap with a junction dot.
785 m_gal->SetStrokeColor( aColor.Brightened( 0.3 ) );
786
787 m_gal->SetIsFill( false );
788 m_gal->SetIsStroke( true );
789 m_gal->SetLineWidth( lineWidth );
790 m_gal->DrawCircle( c.Center, c.Radius );
791}
792
793
797static void drawAltPinModesIcon( GAL& aGal, const VECTOR2D& aPos, double aSize, bool aBaseSelected,
798 bool aRotate, int aExtraLineWidth, const COLOR4D& aColor )
799{
800 aGal.Save();
801
802 aGal.Translate( aPos );
803 if( aRotate )
804 {
805 aGal.Rotate( ANGLE_270.AsRadians() );
806 }
807
808 aGal.SetIsFill( false );
809 aGal.SetIsStroke( true );
810 aGal.SetLineWidth( KiROUND( aSize / 10.0 + aExtraLineWidth ) );
811 aGal.SetStrokeColor( aColor );
812
813 /*
814 * ----------->
815 * + <--center
816 * \------->
817 *
818 * or
819 *
820 * ----- ---->
821 * \
822 * \------>
823 */
824
825 const double lineYOffset = aSize / 4;
826 const double arrowHead = aSize / 8;
827
828 const VECTOR2D topLineREnd = VECTOR2D{ aSize / 2, -lineYOffset };
829 const VECTOR2D btmLineREnd = VECTOR2D{ aSize / 2, lineYOffset };
830
831 // Top line and arrowhead
832 if( aBaseSelected )
833 {
834 // Full top line
835 aGal.DrawLine( topLineREnd, topLineREnd - VECTOR2D{ aSize, 0 } );
836 }
837 else
838 {
839 // Line with a gap
840 aGal.DrawLine( topLineREnd, topLineREnd - VECTOR2D{ aSize / 2, 0 } );
841 aGal.DrawLine( topLineREnd - VECTOR2D{ aSize, 0 },
842 topLineREnd - VECTOR2D{ aSize * 0.7, 0 } );
843 }
844 aGal.DrawLine( topLineREnd, topLineREnd - VECTOR2D{ arrowHead * 1.2, arrowHead } );
845 aGal.DrawLine( topLineREnd, topLineREnd - VECTOR2D{ arrowHead * 1.2, -arrowHead } );
846
847 // Bottom line and arrowhead
848 aGal.DrawLine( btmLineREnd, btmLineREnd - VECTOR2D{ aSize / 2, 0 } );
849 aGal.DrawLine( btmLineREnd, btmLineREnd - VECTOR2D{ arrowHead * 1.2, arrowHead } );
850 aGal.DrawLine( btmLineREnd, btmLineREnd - VECTOR2D{ arrowHead * 1.2, -arrowHead } );
851
852 // Top and bottom 'S' arcs
853 if( !aBaseSelected )
854 {
855 aGal.DrawArc( topLineREnd - VECTOR2D{ aSize, -lineYOffset },
856 lineYOffset, ANGLE_0, -ANGLE_90 );
857 }
858 aGal.DrawArc( topLineREnd - VECTOR2D{ aSize - lineYOffset * 2, -lineYOffset },
859 lineYOffset, ANGLE_180, -ANGLE_90 );
860
861 aGal.Restore();
862};
863
864
865void SCH_PAINTER::draw( const SCH_PIN* aPin, int aLayer, bool aDimmed )
866{
867 // Don't draw pins from a selection view-group. Pins in a schematic must always be drawn
868 // from their parent symbol's m_part.
869 if( dynamic_cast<const SCH_SYMBOL*>( aPin->GetParentSymbol() ) )
870 return;
871
872 if( !isUnitAndConversionShown( aPin ) )
873 return;
874
875 const bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
876
877 if( m_schSettings.IsPrinting() && drawingShadows )
878 return;
879
880 const bool drawingDangling = aLayer == LAYER_DANGLING;
881 const bool drawingOP = aLayer == LAYER_OP_CURRENTS;
882 const bool isDangling = m_schSettings.m_IsSymbolEditor || aPin->HasFlag( IS_DANGLING );
883
884 if( drawingShadows && !( aPin->IsBrightened() || aPin->IsSelected() ) )
885 return;
886
887 const VECTOR2I pos = aPin->GetPosition();
888 COLOR4D color = getRenderColor( aPin, LAYER_PIN, drawingShadows, aDimmed );
889
890 if( !aPin->IsVisible() )
891 {
892 if( m_schSettings.IsPrinting() )
893 return;
894
895 bool force_show = m_schematic ? eeconfig()->m_Appearance.show_hidden_pins
896 : m_schSettings.m_ShowHiddenPins;
897
898 if( force_show )
899 {
900 color = getRenderColor( aPin, LAYER_HIDDEN, drawingShadows, aDimmed );
901 }
902 else
903 {
904 if( drawingDangling && isDangling && aPin->IsGlobalPower() )
905 drawPinDanglingIndicator( *aPin, color, drawingShadows, aPin->IsBrightened() );
906
907 return;
908 }
909 }
910
911 if( drawingDangling )
912 {
913 if( isDangling )
914 drawPinDanglingIndicator( *aPin, color, drawingShadows, aPin->IsBrightened() );
915
916 return;
917 }
918
919 if( m_schSettings.GetDrawBoundingBoxes() )
920 drawItemBoundingBox( aPin );
921
922 const VECTOR2I p0 = aPin->GetPinRoot();
923 const VECTOR2I dir( sign( pos.x - p0.x ), sign( pos.y - p0.y ) );
924 const int len = aPin->GetLength();
925
926 if( drawingOP && !aPin->GetOperatingPoint().IsEmpty() )
927 {
928 int textSize = getOperatingPointTextSize();
929 VECTOR2I mid = ( p0 + pos ) / 2;
930 int textOffset = KiROUND( textSize * 0.22 );
931 TEXT_ATTRIBUTES attrs;
932
933 if( len > textSize )
934 {
935 if( dir.x == 0 )
936 {
937 mid.x += KiROUND( textOffset * 1.2 );
939 }
940 else
941 {
942 mid.y -= KiROUND( textOffset * 1.2 );
943 attrs.m_Angle = ANGLE_VERTICAL;
944 }
945
948
949 attrs.m_Font = KIFONT::FONT::GetFont(); // always use stroke font for performance
950 attrs.m_Size = VECTOR2I( textSize, textSize );
951 attrs.m_StrokeWidth = GetPenSizeForDemiBold( textSize );
952 attrs.m_Color = m_schSettings.GetLayerColor( LAYER_OP_CURRENTS );
953
954 knockoutText( *m_gal, aPin->GetOperatingPoint(), mid, attrs, aPin->GetFontMetrics() );
955 }
956 }
957
958 if( drawingOP )
959 return;
960
961 VECTOR2D pc;
962
963 m_gal->SetIsStroke( true );
964 m_gal->SetIsFill( false );
965 m_gal->SetLineWidth( getLineWidth( aPin, drawingShadows ) );
966 m_gal->SetStrokeColor( color );
967 m_gal->SetFontBold( false );
968 m_gal->SetFontUnderlined( false );
969 m_gal->SetFontItalic( false );
970
971 const int radius = externalPinDecoSize( *aPin );
972 const int diam = radius*2;
973 const int clock_size = internalPinDecoSize( *aPin );
974
975 if( aPin->GetType() == ELECTRICAL_PINTYPE::PT_NC ) // Draw a N.C. symbol
976 {
977 m_gal->DrawLine( p0, pos );
978
979 m_gal->DrawLine( pos + VECTOR2D( -1, -1 ) * TARGET_PIN_RADIUS,
980 pos + VECTOR2D( 1, 1 ) * TARGET_PIN_RADIUS );
981 m_gal->DrawLine( pos + VECTOR2D( 1, -1 ) * TARGET_PIN_RADIUS ,
982 pos + VECTOR2D( -1, 1 ) * TARGET_PIN_RADIUS );
983 }
984 else
985 {
986 switch( aPin->GetShape() )
987 {
988 default:
990 m_gal->DrawLine( p0, pos );
991 break;
992
994 m_gal->DrawCircle( p0 + dir * radius, radius );
995 m_gal->DrawLine( p0 + dir * ( diam ), pos );
996 break;
997
999 pc = p0 - dir * clock_size ;
1000
1001 triLine( p0 + VECTOR2D( dir.y, -dir.x) * clock_size,
1002 pc,
1003 p0 + VECTOR2D( -dir.y, dir.x) * clock_size );
1004
1005 m_gal->DrawCircle( p0 + dir * radius, radius );
1006 m_gal->DrawLine( p0 + dir * ( diam ), pos );
1007 break;
1008
1011 pc = p0 - dir * clock_size ;
1012
1013 triLine( p0 + VECTOR2D( dir.y, -dir.x) * clock_size,
1014 pc,
1015 p0 + VECTOR2D( -dir.y, dir.x) * clock_size );
1016
1017 if( !dir.y )
1018 {
1019 triLine( p0 + VECTOR2D(dir.x, 0) * diam,
1020 p0 + VECTOR2D(dir.x, -1) * diam,
1021 p0 );
1022 }
1023 else /* MapX1 = 0 */
1024 {
1025 triLine( p0 + VECTOR2D( 0, dir.y) * diam,
1026 p0 + VECTOR2D(-1, dir.y) * diam,
1027 p0 );
1028 }
1029
1030 m_gal->DrawLine( p0, pos );
1031 break;
1032
1034 m_gal->DrawLine( p0, pos );
1035
1036 if( !dir.y )
1037 {
1038 triLine( p0 + VECTOR2D( 0, clock_size ),
1039 p0 + VECTOR2D( -dir.x * clock_size, 0 ),
1040 p0 + VECTOR2D( 0, -clock_size ) );
1041 }
1042 else
1043 {
1044 triLine( p0 + VECTOR2D( clock_size, 0 ),
1045 p0 + VECTOR2D( 0, -dir.y * clock_size ),
1046 p0 + VECTOR2D( -clock_size, 0 ) );
1047 }
1048 break;
1049
1051 m_gal->DrawLine( p0, pos );
1052
1053 if( !dir.y )
1054 {
1055 triLine( p0 + VECTOR2D(dir.x, 0) * diam,
1056 p0 + VECTOR2D(dir.x, -1) * diam,
1057 p0 );
1058 }
1059 else /* MapX1 = 0 */
1060 {
1061 triLine( p0 + VECTOR2D( 0, dir.y) * diam,
1062 p0 + VECTOR2D(-1, dir.y) * diam,
1063 p0 );
1064 }
1065 break;
1066
1067 case GRAPHIC_PINSHAPE::OUTPUT_LOW: // IEEE symbol "Active Low Output"
1068 m_gal->DrawLine( p0, pos );
1069
1070 if( !dir.y ) // Horizontal pin
1071 m_gal->DrawLine( p0 - VECTOR2D( 0, diam ), p0 + VECTOR2D( dir.x, 0 ) * diam );
1072 else // Vertical pin
1073 m_gal->DrawLine( p0 - VECTOR2D( diam, 0 ), p0 + VECTOR2D( 0, dir.y ) * diam );
1074 break;
1075
1076 case GRAPHIC_PINSHAPE::NONLOGIC: // NonLogic pin symbol
1077 m_gal->DrawLine( p0, pos );
1078
1079 m_gal->DrawLine( p0 - VECTOR2D( dir.x + dir.y, dir.y - dir.x ) * radius,
1080 p0 + VECTOR2D( dir.x + dir.y, dir.y - dir.x ) * radius );
1081 m_gal->DrawLine( p0 - VECTOR2D( dir.x - dir.y, dir.x + dir.y ) * radius,
1082 p0 + VECTOR2D( dir.x - dir.y, dir.x + dir.y ) * radius );
1083 break;
1084 }
1085 }
1086
1087 if( drawingShadows && !eeconfig()->m_Selection.draw_selected_children )
1088 return;
1089
1090 // Draw the labels
1091 float nameStrokeWidth = getLineWidth( aPin, false );
1092 float numStrokeWidth = getLineWidth( aPin, false );
1093
1094 nameStrokeWidth = Clamp_Text_PenSize( nameStrokeWidth, aPin->GetNameTextSize(), true );
1095 numStrokeWidth = Clamp_Text_PenSize( numStrokeWidth, aPin->GetNumberTextSize(), true );
1096
1097 float shadowWidth = 0.0f;
1098
1099 if( drawingShadows )
1100 {
1101 shadowWidth = getShadowWidth( aPin->IsBrightened() );
1102 }
1103
1104 PIN_LAYOUT_CACHE& cache = aPin->GetLayoutCache();
1105 cache.SetRenderParameters( nameStrokeWidth, numStrokeWidth,
1106 m_schSettings.m_ShowPinsElectricalType,
1107 m_schSettings.m_ShowPinAltIcons );
1108
1109 const auto textRendersAsBitmap = [&]( KIGFX::GAL& aGal, int aTextSize )
1110 {
1111 // Rendering text is expensive (particularly when using outline fonts). At small effective
1112 // sizes (ie: zoomed out) the visual differences between outline and/or stroke fonts and the
1113 // bitmap font becomes immaterial, and there's often more to draw when zoomed out so the
1114 // performance gain becomes more significant.
1115 static const float BITMAP_FONT_SIZE_THRESHOLD = 3.5;
1116
1117 // Any text non bitmappable?
1118 return aTextSize * aGal.GetWorldScale() < BITMAP_FONT_SIZE_THRESHOLD;
1119 };
1120
1121 const auto drawTextInfo =
1122 [&]( const PIN_LAYOUT_CACHE::TEXT_INFO& aTextInfo, const COLOR4D& aColor )
1123 {
1124 // const double iconSize = std::min( aPin->GetNameTextSize(), schIUScale.mmToIU( 1.5 ) );
1125 const bool renderTextAsBitmap = textRendersAsBitmap( *m_gal, aTextInfo.m_TextSize );
1126
1127 // Which of these gets used depends on the font technology, so set both
1128 m_gal->SetStrokeColor( aColor );
1129 m_gal->SetFillColor( aColor );
1130
1131 TEXT_ATTRIBUTES attrs;
1132 attrs.m_Font = KIFONT::FONT::GetFont( eeconfig()->m_Appearance.default_font );
1133 attrs.m_Size = VECTOR2I( aTextInfo.m_TextSize, aTextInfo.m_TextSize );
1134 attrs.m_Halign = aTextInfo.m_HAlign;
1135 attrs.m_Valign = aTextInfo.m_VAlign;
1136 attrs.m_Angle = aTextInfo.m_Angle;
1137 attrs.m_StrokeWidth = aTextInfo.m_Thickness;
1138
1139 if( drawingShadows )
1140 {
1141 attrs.m_StrokeWidth += KiROUND( shadowWidth );
1142
1143 if( !attrs.m_Font->IsOutline() )
1144 {
1145 strokeText( *m_gal, aTextInfo.m_Text, aTextInfo.m_TextPosition, attrs,
1146 aPin->GetFontMetrics() );
1147 }
1148 else
1149 {
1150 boxText( *m_gal, aTextInfo.m_Text, aTextInfo.m_TextPosition, attrs,
1151 aPin->GetFontMetrics() );
1152 }
1153 }
1154 else if( nonCached( aPin ) && renderTextAsBitmap )
1155 {
1156 bitmapText( *m_gal, aTextInfo.m_Text, aTextInfo.m_TextPosition, attrs );
1157 const_cast<SCH_PIN*>( aPin )->SetFlags( IS_SHOWN_AS_BITMAP );
1158 }
1159 else
1160 {
1161 strokeText( *m_gal, aTextInfo.m_Text, aTextInfo.m_TextPosition, attrs,
1162 aPin->GetFontMetrics() );
1163 const_cast<SCH_PIN*>( aPin )->SetFlags( IS_SHOWN_AS_BITMAP );
1164 }
1165 };
1166
1167 const auto getColorForLayer = [&]( int aDrawnLayer )
1168 {
1169 if( !aPin->IsVisible() )
1170 return getRenderColor( aPin, LAYER_HIDDEN, drawingShadows, aDimmed );
1171
1172 return getRenderColor( aPin, aDrawnLayer, drawingShadows, aDimmed );
1173 };
1174
1175 // Request text layout infor and draw it
1176
1177 if( std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> numInfo = cache.GetPinNumberInfo( shadowWidth ) )
1178 {
1179 drawTextInfo( *numInfo, getColorForLayer( LAYER_PINNUM ) );
1180 }
1181
1182 if( std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> nameInfo = cache.GetPinNameInfo( shadowWidth ) )
1183 {
1184 drawTextInfo( *nameInfo, getColorForLayer( LAYER_PINNAM ) );
1185
1186 if( OPT_BOX2I altIconBox = cache.GetAltIconBBox() )
1187 {
1188 drawAltPinModesIcon( *m_gal, altIconBox->GetCenter(), altIconBox->GetWidth(),
1189 // Icon style doesn't work due to the tempPin having no alt
1190 // but maybe it's better with just one style anyway.
1191 true, nameInfo->m_Angle == ANGLE_VERTICAL, shadowWidth,
1192 getColorForLayer( LAYER_PINNAM ) );
1193 }
1194 }
1195
1196 if( std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> elecTypeInfo =
1197 cache.GetPinElectricalTypeInfo( shadowWidth ) )
1198 {
1199 drawTextInfo( *elecTypeInfo, getColorForLayer( LAYER_PRIVATE_NOTES ) );
1200 }
1201}
1202
1203
1204// Draw anchor indicating the anchor position of text objects, local labels, or fields.
1205void SCH_PAINTER::drawAnchor( const VECTOR2I& aPos, bool aDrawingShadows )
1206{
1207 if( m_schSettings.IsPrinting() )
1208 return;
1209
1210 // In order for the anchors to be visible but unobtrusive, their size must factor in the
1211 // current zoom level.
1212 const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
1213 int radius = KiROUND( std::fabs( matrix.GetScale().x * TEXT_ANCHOR_SIZE ) / 25 )
1215
1216 COLOR4D color = aDrawingShadows ? m_schSettings.GetLayerColor( LAYER_SELECTION_SHADOWS )
1217 : m_schSettings.GetLayerColor( LAYER_SCHEMATIC_ANCHOR );
1218
1219 m_gal->SetStrokeColor( color );
1220 m_gal->SetIsStroke( true );
1221 m_gal->SetLineWidth( aDrawingShadows ? getShadowWidth( false )
1222 : m_schSettings.GetDanglingIndicatorThickness() );
1223
1224 m_gal->DrawLine( aPos - VECTOR2I( radius, 0 ), aPos + VECTOR2I( radius, 0 ) );
1225 m_gal->DrawLine( aPos - VECTOR2I( 0, radius ), aPos + VECTOR2I( 0, radius ) );
1226}
1227
1228
1229// Draw the target (an open square) for a wire or label which has no connection or is
1230// being moved.
1231void SCH_PAINTER::drawDanglingIndicator( const VECTOR2I& aPos, const COLOR4D& aColor, int aWidth,
1232 bool aDangling, bool aDrawingShadows, bool aBrightened )
1233{
1234 if( m_schSettings.IsPrinting() )
1235 return;
1236
1237 int size = aDangling ? DANGLING_SYMBOL_SIZE : UNSELECTED_END_SIZE;
1238
1239 if( !aDangling )
1240 aWidth /= 2;
1241
1242 VECTOR2I radius( aWidth + schIUScale.MilsToIU( size / 2 ),
1243 aWidth + schIUScale.MilsToIU( size / 2 ) );
1244
1245 // Dangling symbols must be drawn in a slightly different colour so they can be seen when
1246 // they overlap with a junction dot.
1247 m_gal->SetStrokeColor( aColor.Brightened( 0.3 ) );
1248 m_gal->SetIsStroke( true );
1249 m_gal->SetIsFill( false );
1250 m_gal->SetLineWidth( aDrawingShadows ? getShadowWidth( aBrightened )
1251 : m_schSettings.GetDanglingIndicatorThickness() );
1252
1253 m_gal->DrawRectangle( aPos - radius, aPos + radius );
1254}
1255
1256
1257void SCH_PAINTER::draw( const SCH_JUNCTION* aJct, int aLayer )
1258{
1259 bool highlightNetclassColors = false;
1260 EESCHEMA_SETTINGS* eeschemaCfg = eeconfig();
1261
1262 if( eeschemaCfg )
1263 {
1264 highlightNetclassColors = eeschemaCfg->m_Selection.highlight_netclass_colors;
1265 }
1266
1267 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1268
1269 if( m_schSettings.IsPrinting() && drawingShadows )
1270 return;
1271
1272 if( drawingShadows && !( aJct->IsBrightened() || aJct->IsSelected() ) )
1273 return;
1274
1275 COLOR4D color;
1276
1277 if( highlightNetclassColors && aLayer == aJct->GetLayer() )
1278 color = m_schSettings.GetLayerColor( aJct->GetLayer() );
1279 else
1280 color = getRenderColor( aJct, aJct->GetLayer(), drawingShadows );
1281
1282 int junctionSize = aJct->GetEffectiveDiameter() / 2;
1283
1284 if( junctionSize > 1 )
1285 {
1286 m_gal->SetIsStroke( drawingShadows );
1287 m_gal->SetLineWidth( getLineWidth( aJct, drawingShadows ) );
1288 m_gal->SetStrokeColor( color );
1289 m_gal->SetIsFill( !drawingShadows );
1290 m_gal->SetFillColor( color );
1291 m_gal->DrawCircle( aJct->GetPosition(), junctionSize );
1292 }
1293}
1294
1295
1296void SCH_PAINTER::draw( const SCH_LINE* aLine, int aLayer )
1297{
1298 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1299 bool drawingNetColorHighlights = aLayer == LAYER_NET_COLOR_HIGHLIGHT;
1300 bool drawingWires = aLayer == LAYER_WIRE;
1301 bool drawingBusses = aLayer == LAYER_BUS;
1302 bool drawingDangling = aLayer == LAYER_DANGLING;
1303 bool drawingOP = aLayer == LAYER_OP_VOLTAGES;
1304
1305 bool highlightNetclassColors = false;
1306 double highlightAlpha = 0.6;
1307 EESCHEMA_SETTINGS* eeschemaCfg = eeconfig();
1308
1309 if( eeschemaCfg )
1310 {
1311 highlightNetclassColors = eeschemaCfg->m_Selection.highlight_netclass_colors;
1312 highlightAlpha = eeschemaCfg->m_Selection.highlight_netclass_colors_alpha;
1313 }
1314
1315 if( !highlightNetclassColors && drawingNetColorHighlights )
1316 return;
1317
1318 if( m_schSettings.m_OverrideItemColors && drawingNetColorHighlights )
1319 return;
1320
1321 if( m_schSettings.IsPrinting() && drawingShadows )
1322 return;
1323
1324 if( drawingShadows && !( aLine->IsBrightened() || aLine->IsSelected() ) )
1325 return;
1326
1327 // Line end dangling status isn't updated until the line is finished drawing, so don't warn
1328 // them about ends that are probably connected
1329 if( aLine->IsNew() && drawingDangling )
1330 return;
1331
1332 COLOR4D color = getRenderColor( aLine, aLine->GetLayer(), drawingShadows );
1333 float width = getLineWidth( aLine, drawingShadows, drawingNetColorHighlights );
1334 LINE_STYLE lineStyle = aLine->GetEffectiveLineStyle();
1335
1336 if( highlightNetclassColors )
1337 {
1338 // Force default color for nets we are going to highlight
1339 if( drawingWires )
1340 color = m_schSettings.GetLayerColor( LAYER_WIRE );
1341 else if( drawingBusses )
1342 color = m_schSettings.GetLayerColor( LAYER_BUS );
1343 }
1344
1345 if( drawingNetColorHighlights )
1346 {
1347 // Don't draw highlights for default-colored nets
1348 if( ( aLine->IsWire() && color == m_schSettings.GetLayerColor( LAYER_WIRE ) )
1349 || ( aLine->IsBus() && color == m_schSettings.GetLayerColor( LAYER_BUS ) ) )
1350 {
1351 return;
1352 }
1353
1354 color = color.WithAlpha( color.a * highlightAlpha );
1355 }
1356
1357 if( ( drawingDangling || drawingShadows ) && !aLine->IsNew() )
1358 {
1359 if( ( aLine->IsWire() && aLine->IsStartDangling() )
1360 || ( drawingShadows && aLine->IsSelected() && !aLine->HasFlag( STARTPOINT ) ) )
1361 {
1362 COLOR4D indicatorColor( color );
1363
1364 if( drawingShadows && !aLine->HasFlag( STARTPOINT ) )
1365 indicatorColor.Invert();
1366
1367 drawDanglingIndicator( aLine->GetStartPoint(), indicatorColor, KiROUND( width ),
1368 aLine->IsWire() && aLine->IsStartDangling(), drawingShadows,
1369 aLine->IsBrightened() );
1370 }
1371
1372 if( ( aLine->IsWire() && aLine->IsEndDangling() )
1373 || ( drawingShadows && aLine->IsSelected() && !aLine->HasFlag( ENDPOINT ) ) )
1374 {
1375 COLOR4D indicatorColor( color );
1376
1377 if( drawingShadows && !aLine->HasFlag( ENDPOINT ) )
1378 indicatorColor.Invert();
1379
1380 drawDanglingIndicator( aLine->GetEndPoint(), indicatorColor, KiROUND( width ),
1381 aLine->IsWire() && aLine->IsEndDangling(), drawingShadows,
1382 aLine->IsBrightened() );
1383 }
1384 }
1385
1386 if( drawingDangling )
1387 return;
1388
1389 if( drawingOP && !aLine->GetOperatingPoint().IsEmpty() )
1390 {
1391 int textSize = getOperatingPointTextSize();
1392 VECTOR2I pos = aLine->GetMidPoint();
1393 int textOffset = KiROUND( textSize * 0.22 );
1394 TEXT_ATTRIBUTES attrs;
1395
1396 if( aLine->GetStartPoint().y == aLine->GetEndPoint().y )
1397 {
1398 pos.y -= textOffset;
1401 }
1402 else
1403 {
1404 pos.x += KiROUND( textOffset * 1.2 );
1407 }
1408
1409 attrs.m_Font = KIFONT::FONT::GetFont(); // always use stroke font for performance
1410 attrs.m_Size = VECTOR2I( textSize, textSize );
1411 attrs.m_StrokeWidth = GetPenSizeForDemiBold( textSize );
1412 attrs.m_Color = m_schSettings.GetLayerColor( LAYER_OP_VOLTAGES );
1413
1414 knockoutText( *m_gal, aLine->GetOperatingPoint(), pos, attrs, aLine->GetFontMetrics() );
1415 }
1416
1417 if( drawingOP )
1418 return;
1419
1420 m_gal->SetIsStroke( true );
1421 m_gal->SetStrokeColor( color );
1422 m_gal->SetLineWidth( width );
1423
1424 if( lineStyle <= LINE_STYLE::FIRST_TYPE || drawingShadows )
1425 {
1426 m_gal->DrawLine( aLine->GetStartPoint(), aLine->GetEndPoint() );
1427 }
1428 else
1429 {
1430 SHAPE_SEGMENT line( aLine->GetStartPoint(), aLine->GetEndPoint() );
1431
1432 STROKE_PARAMS::Stroke( &line, lineStyle, KiROUND( width ), &m_schSettings,
1433 [&]( const VECTOR2I& a, const VECTOR2I& b )
1434 {
1435 // DrawLine has problem with 0 length lines so enforce minimum
1436 if( a == b )
1437 m_gal->DrawLine( a+1, b );
1438 else
1439 m_gal->DrawLine( a, b );
1440 } );
1441 }
1442}
1443
1444
1445void SCH_PAINTER::draw( const SCH_SHAPE* aShape, int aLayer, bool aDimmed )
1446{
1447 if( !isUnitAndConversionShown( aShape ) )
1448 return;
1449
1450 if( aShape->IsPrivate() && !m_schSettings.m_IsSymbolEditor )
1451 return;
1452
1453 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1454
1455 if( m_schSettings.IsPrinting() && drawingShadows )
1456 return;
1457
1458 LINE_STYLE lineStyle = aShape->GetEffectiveLineStyle();
1459 COLOR4D color = getRenderColor( aShape, aLayer, drawingShadows, aDimmed );
1460
1461 if( drawingShadows && !( aShape->IsBrightened() || aShape->IsSelected() ) )
1462 return;
1463
1464 auto drawShape =
1465 [&]( const SCH_SHAPE* shape )
1466 {
1467 switch( shape->GetShape() )
1468 {
1469 case SHAPE_T::ARC:
1470 {
1471 VECTOR2D start = shape->GetStart();
1472 VECTOR2D mid = shape->GetArcMid();
1473 VECTOR2D end = shape->GetEnd();
1474 VECTOR2D center = CalcArcCenter( start, mid, end );
1475
1476 EDA_ANGLE startAngle( start - center );
1477 EDA_ANGLE midAngle( mid - center );
1478 EDA_ANGLE endAngle( end - center );
1479
1480 EDA_ANGLE angle1 = midAngle - startAngle;
1481 EDA_ANGLE angle2 = endAngle - midAngle;
1482
1483 EDA_ANGLE angle = angle1.Normalize180() + angle2.Normalize180();
1484
1485 m_gal->DrawArc( center, ( start - center ).EuclideanNorm(), startAngle, angle );
1486 break;
1487 }
1488
1489 case SHAPE_T::CIRCLE:
1490 m_gal->DrawCircle( shape->GetPosition(), shape->GetRadius() );
1491 break;
1492
1493 case SHAPE_T::RECTANGLE:
1494 m_gal->DrawRectangle( shape->GetPosition(), shape->GetEnd() );
1495 break;
1496
1497 case SHAPE_T::POLY:
1498 {
1499 const std::vector<SHAPE*> polySegments = shape->MakeEffectiveShapes( true );
1500
1501 if( !polySegments.empty() )
1502 {
1503 std::deque<VECTOR2D> pts;
1504
1505 for( SHAPE* polySegment : polySegments )
1506 pts.push_back( static_cast<SHAPE_SEGMENT*>( polySegment )->GetSeg().A );
1507
1508 pts.push_back(
1509 static_cast<SHAPE_SEGMENT*>( polySegments.back() )->GetSeg().B );
1510
1511 for( SHAPE* polySegment : polySegments )
1512 delete polySegment;
1513
1514 m_gal->DrawPolygon( pts );
1515 }
1516 break;
1517 }
1518
1519 case SHAPE_T::BEZIER:
1520 {
1521 m_gal->DrawCurve( shape->GetStart(), shape->GetBezierC1(),
1522 shape->GetBezierC2(), shape->GetEnd() );
1523 break;
1524 }
1525
1526 default:
1527 UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
1528 }
1529 };
1530
1531 if( aLayer == LAYER_SELECTION_SHADOWS )
1532 {
1533 if( eeconfig()->m_Selection.fill_shapes )
1534 {
1535 // Consider a NAND gate. We have no idea which side of the arc is "inside"
1536 // so we can't reliably fill.
1537 if( aShape->GetShape() == SHAPE_T::ARC )
1538 m_gal->SetIsFill( aShape->IsFilled() );
1539 else
1540 m_gal->SetIsFill( true );
1541
1542 m_gal->SetIsStroke( false );
1543 m_gal->SetFillColor( color );
1544 }
1545 else
1546 {
1547 m_gal->SetIsStroke( true );
1548 m_gal->SetIsFill( false );
1549 m_gal->SetLineWidth( getLineWidth( aShape, true ) );
1550 m_gal->SetStrokeColor( color );
1551 }
1552
1553 drawShape( aShape );
1554 }
1555 else if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_NOTES_BACKGROUND )
1556 {
1557 switch( aShape->GetFillMode() )
1558 {
1559 case FILL_T::NO_FILL:
1560 break;
1561
1563 // Fill in the foreground layer
1564 break;
1565
1568 // Do not fill the shape in B&W print mode, to avoid to visible items inside the shape
1569 if( !m_schSettings.PrintBlackAndWhiteReq() )
1570 {
1571 m_gal->SetIsFill( true );
1572 m_gal->SetIsStroke( false );
1573 m_gal->SetFillColor( color );
1574
1575 drawShape( aShape );
1576 }
1577 break;
1578 }
1579 }
1580 else if( aLayer == LAYER_DEVICE || aLayer == LAYER_NOTES || aLayer == LAYER_PRIVATE_NOTES
1581 || aLayer == LAYER_RULE_AREAS )
1582 {
1583 // Shapes filled with the device colour must be filled in the foreground
1584 if( aShape->GetFillMode() == FILL_T::FILLED_SHAPE )
1585 {
1586 m_gal->SetIsFill( true );
1587 m_gal->SetIsStroke( false );
1588 m_gal->SetFillColor( color );
1589
1590 drawShape( aShape );
1591 }
1592
1593 float lineWidth = getLineWidth( aShape, drawingShadows );
1594
1595 if( lineWidth > 0 )
1596 {
1597 m_gal->SetIsFill( false );
1598 m_gal->SetIsStroke( true );
1599 m_gal->SetLineWidth( lineWidth );
1600 m_gal->SetStrokeColor( color );
1601
1602 if( lineStyle <= LINE_STYLE::FIRST_TYPE || drawingShadows )
1603 {
1604 drawShape( aShape );
1605 }
1606 else
1607 {
1608 std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapes( true );
1609
1610 for( SHAPE* shape : shapes )
1611 {
1612 STROKE_PARAMS::Stroke( shape, lineStyle, KiROUND( lineWidth ), &m_schSettings,
1613 [this]( const VECTOR2I& a, const VECTOR2I& b )
1614 {
1615 // DrawLine has problem with 0 length lines so enforce minimum
1616 if( a == b )
1617 m_gal->DrawLine( a+1, b );
1618 else
1619 m_gal->DrawLine( a, b );
1620 } );
1621 }
1622
1623 for( SHAPE* shape : shapes )
1624 delete shape;
1625 }
1626 }
1627 }
1628}
1629
1630
1631void SCH_PAINTER::draw( const SCH_TEXT* aText, int aLayer, bool aDimmed )
1632{
1633 if( !isUnitAndConversionShown( aText ) )
1634 return;
1635
1636 if( aText->IsPrivate() && !m_schSettings.m_IsSymbolEditor )
1637 return;
1638
1639 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1640
1641 if( m_schSettings.IsPrinting() && drawingShadows )
1642 return;
1643
1644 if( drawingShadows && !( aText->IsBrightened() || aText->IsSelected() ) )
1645 return;
1646
1647 switch( aText->Type() )
1648 {
1649 case SCH_SHEET_PIN_T: aLayer = LAYER_SHEETLABEL; break;
1650 case SCH_HIER_LABEL_T: aLayer = LAYER_HIERLABEL; break;
1651 case SCH_GLOBAL_LABEL_T: aLayer = LAYER_GLOBLABEL; break;
1652 case SCH_DIRECTIVE_LABEL_T: aLayer = LAYER_NETCLASS_REFS; break;
1653 case SCH_LABEL_T: aLayer = LAYER_LOCLABEL; break;
1654 case SCH_TEXT_T: aLayer = aText->GetParentSymbol() ? LAYER_DEVICE
1655 : LAYER_NOTES; break;
1656 default: aLayer = LAYER_NOTES; break;
1657 }
1658
1659 COLOR4D color = getRenderColor( aText, aLayer, drawingShadows, aDimmed );
1660
1661 if( m_schematic )
1662 {
1663 SCH_CONNECTION* conn = nullptr;
1664
1665 if( !aText->IsConnectivityDirty() )
1666 conn = aText->Connection();
1667
1668 if( conn && conn->IsBus() )
1669 color = getRenderColor( aText, LAYER_BUS, drawingShadows );
1670 }
1671
1672 if( !( aText->IsVisible() || aText->IsForceVisible() ) )
1673 {
1674 if( m_schSettings.m_IsSymbolEditor || eeconfig()->m_Appearance.show_hidden_fields )
1675 color = getRenderColor( aText, LAYER_HIDDEN, drawingShadows );
1676 else
1677 return;
1678 }
1679
1680 m_gal->SetStrokeColor( color );
1681 m_gal->SetFillColor( color );
1682
1683 wxString shownText( aText->GetShownText( true ) );
1684 VECTOR2I text_offset = aText->GetSchematicTextOffset( &m_schSettings );
1685 TEXT_ATTRIBUTES attrs = aText->GetAttributes();
1686 KIFONT::FONT* font = getFont( aText );
1687
1688 attrs.m_Angle = aText->GetDrawRotation();
1689 attrs.m_StrokeWidth = KiROUND( getTextThickness( aText ) );
1690
1691 if( drawingShadows && font->IsOutline() )
1692 {
1693 BOX2I bBox = aText->GetBoundingBox();
1694 bBox.Inflate( KiROUND( getTextThickness( aText ) * 2 ) );
1695
1696 m_gal->SetIsStroke( false );
1697 m_gal->SetIsFill( true );
1698 m_gal->DrawRectangle( bBox.GetPosition(), bBox.GetEnd() );
1699 }
1700 else if( aText->GetLayer() == LAYER_DEVICE )
1701 {
1702 BOX2I bBox = aText->GetBoundingBox();
1703 VECTOR2D pos = bBox.Centre();
1704
1705 // Due to the fact a shadow text can be drawn left or right aligned, it needs to be
1706 // offset by shadowWidth/2 to be drawn at the same place as normal text.
1707 // For some reason we need to slightly modify this offset for a better look (better
1708 // alignment of shadow shape), for KiCad font only.
1709 double shadowOffset = 0.0;
1710
1711 if( drawingShadows )
1712 {
1713 double shadowWidth = getShadowWidth( !aText->IsSelected() );
1714 attrs.m_StrokeWidth += getShadowWidth( !aText->IsSelected() );
1715
1716 const double adjust = 1.2f; // Value chosen after tests
1717 shadowOffset = shadowWidth/2.0f * adjust;
1718 }
1719
1720 if( attrs.m_Angle == ANGLE_VERTICAL )
1721 {
1722 switch( attrs.m_Halign )
1723 {
1725 pos.y = bBox.GetBottom() + shadowOffset;
1726 break;
1728 pos.y = ( bBox.GetTop() + bBox.GetBottom() ) / 2.0;
1729 break;
1731 pos.y = bBox.GetTop() - shadowOffset;
1732 break;
1734 wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) );
1735 break;
1736 }
1737 }
1738 else
1739 {
1740 switch( attrs.m_Halign )
1741 {
1743 pos.x = bBox.GetLeft() - shadowOffset;
1744 break;
1746 pos.x = ( bBox.GetLeft() + bBox.GetRight() ) / 2.0;
1747 break;
1749 pos.x = bBox.GetRight() + shadowOffset;
1750 break;
1752 wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) );
1753 break;
1754 }
1755 }
1756
1757 // Because the text vertical position is the bounding box center, the text is drawn as
1758 // vertically centered.
1760
1761 strokeText( *m_gal, shownText, pos, attrs, aText->GetFontMetrics() );
1762 }
1763 else if( drawingShadows )
1764 {
1765 m_gal->SetIsFill( false );
1766 m_gal->SetIsStroke( true );
1767 attrs.m_StrokeWidth += KiROUND( getShadowWidth( !aText->IsSelected() ) );
1768 attrs.m_Underlined = false;
1769
1770 // Fudge factors to match 6.0 positioning
1771 // New text stroking has width dependent offset but we need to center the shadow on the
1772 // stroke. NB this offset is in font.cpp also.
1773 int fudge = KiROUND( getShadowWidth( !aText->IsSelected() ) / 1.52 );
1774
1775 if( attrs.m_Halign == GR_TEXT_H_ALIGN_LEFT && attrs.m_Angle == ANGLE_0 )
1776 text_offset.x -= fudge;
1777 else if( attrs.m_Halign == GR_TEXT_H_ALIGN_RIGHT && attrs.m_Angle == ANGLE_90 )
1778 text_offset.y -= fudge;
1779 else if( attrs.m_Halign == GR_TEXT_H_ALIGN_RIGHT && attrs.m_Angle == ANGLE_0 )
1780 text_offset.x += fudge;
1781 else if( attrs.m_Halign == GR_TEXT_H_ALIGN_LEFT && attrs.m_Angle == ANGLE_90 )
1782 text_offset.y += fudge;
1783
1784 strokeText( *m_gal, shownText, aText->GetDrawPos() + text_offset, attrs,
1785 aText->GetFontMetrics() );
1786 }
1787 else
1788 {
1789 if( aText->IsHypertext() && aText->IsRollover() )
1790 {
1791 m_gal->SetStrokeColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
1792 m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
1793 attrs.m_Underlined = true;
1794 }
1795
1796 // Adjust text drawn in an outline font to more closely mimic the positioning of
1797 // SCH_FIELD text.
1798 if( font->IsOutline() && aText->Type() == SCH_TEXT_T )
1799 {
1800 BOX2I firstLineBBox = aText->GetTextBox( 0 );
1801 int sizeDiff = firstLineBBox.GetHeight() - aText->GetTextSize().y;
1802 int adjust = KiROUND( sizeDiff * 0.4 );
1803 VECTOR2I adjust_offset( 0, - adjust );
1804
1805 RotatePoint( adjust_offset, aText->GetDrawRotation() );
1806 text_offset += adjust_offset;
1807 }
1808
1809 if( nonCached( aText )
1810 && aText->RenderAsBitmap( m_gal->GetWorldScale() )
1811 && !shownText.Contains( wxT( "\n" ) ) )
1812 {
1813 bitmapText( *m_gal, shownText, aText->GetDrawPos() + text_offset, attrs );
1814 const_cast<SCH_TEXT*>( aText )->SetFlags( IS_SHOWN_AS_BITMAP );
1815 }
1816 else
1817 {
1818 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
1819
1820 if( !aText->IsHypertext() && font->IsOutline() )
1821 cache = aText->GetRenderCache( font, shownText, text_offset );
1822
1823 if( cache )
1824 {
1825 m_gal->SetLineWidth( attrs.m_StrokeWidth );
1826 m_gal->DrawGlyphs( *cache );
1827 }
1828 else
1829 {
1830 strokeText( *m_gal, shownText, aText->GetDrawPos() + text_offset, attrs,
1831 aText->GetFontMetrics() );
1832 }
1833
1834 const_cast<SCH_TEXT*>( aText )->ClearFlags( IS_SHOWN_AS_BITMAP );
1835 }
1836 }
1837
1838 // Draw anchor
1839 if( aText->IsSelected() )
1840 {
1841 bool showAnchor;
1842
1843 switch( aText->Type() )
1844 {
1845 case SCH_TEXT_T:
1846 showAnchor = true;
1847 break;
1848
1849 case SCH_LABEL_T:
1850 // Don't clutter things up if we're already showing a dangling indicator
1851 showAnchor = !static_cast<const SCH_LABEL*>( aText )->IsDangling();
1852 break;
1853
1855 case SCH_HIER_LABEL_T:
1856 case SCH_GLOBAL_LABEL_T:
1857 case SCH_SHEET_PIN_T:
1858 // These all have shapes and so don't need anchors
1859 showAnchor = false;
1860 break;
1861
1862 default:
1863 showAnchor = false;
1864 break;
1865 }
1866
1867 if( showAnchor )
1868 drawAnchor( aText->GetPosition(), drawingShadows );
1869 }
1870}
1871
1872
1873void SCH_PAINTER::draw( const SCH_TEXTBOX* aTextBox, int aLayer, bool aDimmed )
1874{
1875 if( aTextBox->Type() == SCH_TABLECELL_T )
1876 {
1877 const SCH_TABLECELL* cell = static_cast<const SCH_TABLECELL*>( aTextBox );
1878
1879 if( cell->GetColSpan() == 0 || cell->GetRowSpan() == 0 )
1880 return;
1881 }
1882
1883 if( !isUnitAndConversionShown( aTextBox ) )
1884 return;
1885
1886 if( aTextBox->IsPrivate() && !m_schSettings.m_IsSymbolEditor )
1887 return;
1888
1889 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
1890
1891 if( m_schSettings.IsPrinting() && drawingShadows )
1892 return;
1893
1894 COLOR4D color = getRenderColor( aTextBox, aLayer, drawingShadows, aDimmed );
1895 COLOR4D bg = m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND );
1896 float borderWidth = getLineWidth( aTextBox, drawingShadows );
1897 KIFONT::FONT* font = getFont( aTextBox );
1898
1899 auto drawText =
1900 [&]()
1901 {
1902 wxString shownText = aTextBox->GetShownText( true );
1903 TEXT_ATTRIBUTES attrs = aTextBox->GetAttributes();
1904
1905 attrs.m_Angle = aTextBox->GetDrawRotation();
1906 attrs.m_StrokeWidth = KiROUND( getTextThickness( aTextBox ) );
1907
1908 if( aTextBox->IsHypertext() && aTextBox->IsRollover() )
1909 {
1910 m_gal->SetStrokeColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
1911 m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
1912 attrs.m_Underlined = true;
1913 }
1914
1915 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
1916
1917 if( !aTextBox->IsHypertext() && font->IsOutline() )
1918 cache = aTextBox->GetRenderCache( font, shownText );
1919
1920 if( cache )
1921 {
1922 m_gal->SetLineWidth( attrs.m_StrokeWidth );
1923 m_gal->DrawGlyphs( *cache );
1924 }
1925 else
1926 {
1927 strokeText( *m_gal, shownText, aTextBox->GetDrawPos(), attrs,
1928 aTextBox->GetFontMetrics() );
1929 }
1930 };
1931
1932 if( drawingShadows && !( aTextBox->IsBrightened() || aTextBox->IsSelected() ) )
1933 return;
1934
1935 m_gal->SetFillColor( color );
1936 m_gal->SetStrokeColor( color );
1937
1938 if( aLayer == LAYER_SELECTION_SHADOWS )
1939 {
1940 m_gal->SetIsFill( true );
1941 m_gal->SetIsStroke( false );
1942 m_gal->SetLineWidth( borderWidth );
1943
1944 m_gal->DrawRectangle( aTextBox->GetPosition(), aTextBox->GetEnd() );
1945 }
1946 else if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_NOTES_BACKGROUND )
1947 {
1948 // Do not fill the shape in B&W print mode, to avoid to visible items
1949 // inside the shape
1950 if( aTextBox->IsFilled() && !m_schSettings.PrintBlackAndWhiteReq() )
1951 {
1952 m_gal->SetIsFill( true );
1953 m_gal->SetIsStroke( false );
1954 m_gal->SetLineWidth( borderWidth );
1955
1956 m_gal->DrawRectangle( aTextBox->GetPosition(), aTextBox->GetEnd() );
1957 }
1958 }
1959 else if( aLayer == LAYER_DEVICE || aLayer == LAYER_NOTES || aLayer == LAYER_PRIVATE_NOTES )
1960 {
1961 drawText();
1962
1963 if( aTextBox->Type() != SCH_TABLECELL_T && borderWidth > 0 )
1964 {
1965 COLOR4D borderColor = aTextBox->GetStroke().GetColor();
1966 LINE_STYLE borderStyle = aTextBox->GetEffectiveLineStyle();
1967 double transparency = aTextBox->GetForcedTransparency();
1968
1969 if( m_schSettings.m_OverrideItemColors || aTextBox->IsBrightened()
1970 || borderColor == COLOR4D::UNSPECIFIED )
1971 {
1972 borderColor = m_schSettings.GetLayerColor( aLayer );
1973 }
1974
1975 if( transparency > 0.0 )
1976 borderColor = borderColor.WithAlpha( borderColor.a * ( 1.0 - transparency ) );
1977
1978 if( aDimmed )
1979 {
1980 borderColor = borderColor.Mix( bg, 0.5f );
1981 borderColor.Desaturate( );
1982 }
1983
1984 m_gal->SetIsFill( false );
1985 m_gal->SetIsStroke( true );
1986 m_gal->SetStrokeColor( borderColor );
1987 m_gal->SetLineWidth( borderWidth );
1988
1989 if( borderStyle <= LINE_STYLE::FIRST_TYPE || drawingShadows )
1990 {
1991 m_gal->DrawRectangle( aTextBox->GetPosition(), aTextBox->GetEnd() );
1992 }
1993 else
1994 {
1995 std::vector<SHAPE*> shapes = aTextBox->MakeEffectiveShapes( true );
1996
1997 for( SHAPE* shape : shapes )
1998 {
1999 STROKE_PARAMS::Stroke( shape, borderStyle, KiROUND( borderWidth ),
2000 &m_schSettings,
2001 [this]( const VECTOR2I& a, const VECTOR2I& b )
2002 {
2003 // DrawLine has problem with 0 length lines so enforce minimum
2004 if( a == b )
2005 m_gal->DrawLine( a+1, b );
2006 else
2007 m_gal->DrawLine( a, b );
2008 } );
2009 }
2010
2011 for( SHAPE* shape : shapes )
2012 delete shape;
2013 }
2014 }
2015 }
2016}
2017
2018
2019void SCH_PAINTER::draw( const SCH_TABLE* aTable, int aLayer, bool aDimmed )
2020{
2021 if( aTable->GetCells().empty() )
2022 return;
2023
2024 for( SCH_TABLECELL* cell : aTable->GetCells() )
2025 draw( cell, aLayer, aDimmed );
2026
2027 if( aLayer == LAYER_SELECTION_SHADOWS )
2028 return;
2029
2030 VECTOR2I pos = aTable->GetPosition();
2031 VECTOR2I end = aTable->GetEnd();
2032
2033 int lineWidth;
2034 COLOR4D color;
2035 LINE_STYLE lineStyle;
2036
2037 auto setupStroke =
2038 [&]( const STROKE_PARAMS& stroke )
2039 {
2040 lineWidth = stroke.GetWidth();
2041 color = stroke.GetColor();
2042 lineStyle = stroke.GetLineStyle();
2043
2044 if( lineWidth == 0 )
2045 lineWidth = m_schSettings.GetDefaultPenWidth();
2046
2048 color = m_schSettings.GetLayerColor( LAYER_NOTES );
2049
2050 if( lineStyle == LINE_STYLE::DEFAULT )
2051 lineStyle = LINE_STYLE::SOLID;
2052
2053 m_gal->SetIsFill( false );
2054 m_gal->SetIsStroke( true );
2055 m_gal->SetStrokeColor( color );
2056 m_gal->SetLineWidth( (float) lineWidth );
2057 };
2058
2059 auto strokeShape =
2060 [&]( const SHAPE& shape )
2061 {
2062 STROKE_PARAMS::Stroke( &shape, lineStyle, lineWidth, &m_schSettings,
2063 [&]( const VECTOR2I& a, const VECTOR2I& b )
2064 {
2065 // DrawLine has problem with 0 length lines so enforce minimum
2066 if( a == b )
2067 m_gal->DrawLine( a+1, b );
2068 else
2069 m_gal->DrawLine( a, b );
2070 } );
2071 };
2072
2073 auto strokeLine =
2074 [&]( const VECTOR2I& ptA, const VECTOR2I& ptB )
2075 {
2076 if( lineStyle <= LINE_STYLE::FIRST_TYPE )
2077 {
2078 m_gal->DrawLine( ptA, ptB );
2079 }
2080 else
2081 {
2082 SHAPE_SEGMENT seg( ptA, ptB );
2083 strokeShape( seg );
2084 }
2085 };
2086
2087 auto strokeRect =
2088 [&]( const VECTOR2I& ptA, const VECTOR2I& ptB )
2089 {
2090 if( lineStyle <= LINE_STYLE::FIRST_TYPE )
2091 {
2092 m_gal->DrawRectangle( ptA, ptB );
2093 }
2094 else
2095 {
2096 SHAPE_RECT rect( BOX2I( ptA, ptB - ptA ) );
2097 strokeShape( rect );
2098 }
2099 };
2100
2101 if( aTable->GetSeparatorsStroke().GetWidth() >= 0 )
2102 {
2103 setupStroke( aTable->GetSeparatorsStroke() );
2104
2105 if( aTable->StrokeColumns() )
2106 {
2107 for( int col = 0; col < aTable->GetColCount() - 1; ++col )
2108 {
2109 for( int row = 0; row < aTable->GetRowCount(); ++row )
2110 {
2111 SCH_TABLECELL* cell = aTable->GetCell( row, col );
2112 VECTOR2I topRight( cell->GetEndX(), cell->GetStartY() );
2113
2114 if( !cell->GetTextAngle().IsHorizontal() )
2115 topRight = VECTOR2I( cell->GetStartX(), cell->GetEndY() );
2116
2117 if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 )
2118 strokeLine( topRight, cell->GetEnd() );
2119 }
2120 }
2121 }
2122
2123 if( aTable->StrokeRows() )
2124 {
2125 for( int row = 0; row < aTable->GetRowCount() - 1; ++row )
2126 {
2127 for( int col = 0; col < aTable->GetColCount(); ++col )
2128 {
2129 SCH_TABLECELL* cell = aTable->GetCell( row, col );
2130 VECTOR2I botLeft( cell->GetStartX(), cell->GetEndY() );
2131
2132 if( !cell->GetTextAngle().IsHorizontal() )
2133 botLeft = VECTOR2I( cell->GetEndX(), cell->GetStartY() );
2134
2135 if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 )
2136 strokeLine( botLeft, cell->GetEnd() );
2137 }
2138 }
2139 }
2140 }
2141
2142 if( aTable->GetBorderStroke().GetWidth() >= 0 )
2143 {
2144 SCH_TABLECELL* first = aTable->GetCell( 0, 0 );
2145
2146 setupStroke( aTable->GetBorderStroke() );
2147
2148 if( aTable->StrokeHeader() )
2149 {
2150 if( !first->GetTextAngle().IsHorizontal() )
2151 strokeLine( VECTOR2I( first->GetEndX(), pos.y ), VECTOR2I( first->GetEndX(), first->GetEndY() ) );
2152 else
2153 strokeLine( VECTOR2I( pos.x, first->GetEndY() ), VECTOR2I( end.x, first->GetEndY() ) );
2154 }
2155
2156 if( aTable->StrokeExternal() )
2157 {
2158 if( !first->GetTextAngle().IsHorizontal() )
2159 {
2160 RotatePoint( pos, aTable->GetPosition(), ANGLE_90 );
2161 RotatePoint( end, aTable->GetPosition(), ANGLE_90 );
2162 }
2163
2164 strokeRect( pos, end );
2165 }
2166 }
2167}
2168
2169
2170wxString SCH_PAINTER::expandLibItemTextVars( const wxString& aSourceText,
2171 const SCH_SYMBOL* aSymbolContext )
2172{
2173 std::function<bool( wxString* )> symbolResolver =
2174 [&]( wxString* token ) -> bool
2175 {
2176 if( !m_schematic )
2177 return false;
2178
2179 return aSymbolContext->ResolveTextVar( &m_schematic->CurrentSheet(), token );
2180 };
2181
2182 return ExpandTextVars( aSourceText, &symbolResolver );
2183}
2184
2185
2186void SCH_PAINTER::draw( const SCH_SYMBOL* aSymbol, int aLayer )
2187{
2188 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2189 bool DNP = aSymbol->GetDNP();
2190 bool markExclusion = eeconfig()->m_Appearance.mark_sim_exclusions
2191 && aSymbol->GetExcludedFromSim();
2192
2193 if( m_schSettings.IsPrinting() && drawingShadows )
2194 return;
2195
2196 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2197 {
2198 for( const SCH_FIELD& field : aSymbol->GetFields() )
2199 draw( &field, aLayer, DNP || markExclusion );
2200 }
2201
2202 if( isFieldsLayer( aLayer ) )
2203 return;
2204
2205 if( drawingShadows && !( aSymbol->IsBrightened() || aSymbol->IsSelected() ) )
2206 {
2207 // Don't exit here; symbol may still have selected pins
2208 // return;
2209 }
2210
2211 int unit = m_schematic ? aSymbol->GetUnitSelection( &m_schematic->CurrentSheet() ) : 1;
2212 int bodyStyle = aSymbol->GetBodyStyle();
2213
2214 // Use dummy symbol if the actual couldn't be found (or couldn't be locked).
2215 LIB_SYMBOL* originalSymbol = aSymbol->GetLibSymbolRef() ? aSymbol->GetLibSymbolRef().get()
2216 : dummy();
2217 std::vector<SCH_PIN*> originalPins = originalSymbol->GetPins( unit, bodyStyle );
2218
2219 // Copy the source so we can re-orient and translate it.
2220 LIB_SYMBOL tempSymbol( *originalSymbol );
2221 std::vector<SCH_PIN*> tempPins = tempSymbol.GetPins( unit, bodyStyle );
2222
2223 tempSymbol.SetFlags( aSymbol->GetFlags() );
2224
2225 OrientAndMirrorSymbolItems( &tempSymbol, aSymbol->GetOrientation() );
2226
2227 for( SCH_ITEM& tempItem : tempSymbol.GetDrawItems() )
2228 {
2229 tempItem.SetFlags( aSymbol->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED,
2230 tempItem.Move( aSymbol->GetPosition() );
2231
2232 if( tempItem.Type() == SCH_TEXT_T )
2233 {
2234 SCH_TEXT* textItem = static_cast<SCH_TEXT*>( &tempItem );
2235
2236 if( textItem->HasTextVars() )
2237 textItem->SetText( expandLibItemTextVars( textItem->GetText(), aSymbol ) );
2238 }
2239 else if( tempItem.Type() == SCH_TEXTBOX_T )
2240 {
2241 SCH_TEXTBOX* textboxItem = static_cast<SCH_TEXTBOX*>( &tempItem );
2242
2243 if( textboxItem->HasTextVars() )
2244 textboxItem->SetText( expandLibItemTextVars( textboxItem->GetText(), aSymbol ) );
2245 }
2246 }
2247
2248 // Copy the pin info from the symbol to the temp pins
2249 for( unsigned i = 0; i < tempPins.size(); ++ i )
2250 {
2251 SCH_PIN* symbolPin = aSymbol->GetPin( originalPins[ i ] );
2252 SCH_PIN* tempPin = tempPins[ i ];
2253
2254 tempPin->ClearFlags();
2255 tempPin->SetFlags( symbolPin->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED,
2256 // IS_SHOWN_AS_BITMAP
2257
2258 tempPin->SetName( expandLibItemTextVars( symbolPin->GetShownName(), aSymbol ) );
2259 tempPin->SetType( symbolPin->GetType() );
2260 tempPin->SetShape( symbolPin->GetShape() );
2261
2262 if( symbolPin->IsDangling() )
2263 tempPin->SetFlags( IS_DANGLING );
2264 else
2265 tempPin->ClearFlags( IS_DANGLING );
2266
2267 tempPin->SetOperatingPoint( symbolPin->GetOperatingPoint() );
2268 }
2269
2270 draw( &tempSymbol, aLayer, false, aSymbol->GetUnit(), aSymbol->GetBodyStyle(),
2271 DNP || markExclusion );
2272
2273 for( unsigned i = 0; i < tempPins.size(); ++i )
2274 {
2275 SCH_PIN* symbolPin = aSymbol->GetPin( originalPins[ i ] );
2276 SCH_PIN* tempPin = tempPins[ i ];
2277
2278 symbolPin->ClearFlags();
2279 tempPin->ClearFlags( IS_DANGLING ); // Clear this temporary flag
2280 symbolPin->SetFlags( tempPin->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED,
2281 // IS_SHOWN_AS_BITMAP
2282 }
2283
2284 if( DNP || markExclusion )
2285 {
2286 int layer = DNP ? LAYER_DNP_MARKER : LAYER_EXCLUDED_FROM_SIM;
2287 BOX2I bbox = aSymbol->GetBodyBoundingBox();
2288 BOX2I pins = aSymbol->GetBodyAndPinsBoundingBox();
2289 VECTOR2D margins( std::max( bbox.GetX() - pins.GetX(), pins.GetEnd().x - bbox.GetEnd().x ),
2290 std::max( bbox.GetY() - pins.GetY(), pins.GetEnd().y - bbox.GetEnd().y ) );
2291 int strokeWidth = 3 * schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
2292
2293 margins.x = std::max( margins.x * 0.6, margins.y * 0.3 );
2294 margins.y = std::max( margins.y * 0.6, margins.x * 0.3 );
2295 bbox.Inflate( KiROUND( margins.x ), KiROUND( margins.y ) );
2296
2297 VECTOR2I pt1 = bbox.GetOrigin();
2298 VECTOR2I pt2 = bbox.GetEnd();
2299
2300 GAL_SCOPED_ATTRS scopedAttrs( *m_gal, GAL_SCOPED_ATTRS::ALL_ATTRS );
2301 m_gal->AdvanceDepth();
2302 m_gal->SetIsStroke( true );
2303 m_gal->SetIsFill( true );
2304 m_gal->SetStrokeColor( m_schSettings.GetLayerColor( layer ) );
2305 m_gal->SetFillColor( m_schSettings.GetLayerColor( layer ) );
2306
2307 m_gal->DrawSegment( pt1, pt2, strokeWidth );
2308 std::swap( pt1.x, pt2.x );
2309 m_gal->DrawSegment( pt1, pt2, strokeWidth );
2310 }
2311}
2312
2313
2314void SCH_PAINTER::draw( const SCH_FIELD* aField, int aLayer, bool aDimmed )
2315{
2316 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2317
2318 if( m_schSettings.IsPrinting() && drawingShadows )
2319 return;
2320
2321 if( drawingShadows && !( aField->IsBrightened() || aField->IsSelected() ) )
2322 return;
2323
2324 if( !isUnitAndConversionShown( aField ) )
2325 return;
2326
2327 if( aField->IsPrivate() && !m_schSettings.m_IsSymbolEditor )
2328 return;
2329
2330 // Must check layer as fields are sometimes drawn by their parent rather than directly
2331 // from the view.
2332 std::vector<int> layers = aField->ViewGetLayers();
2333
2334 if( std::find( layers.begin(), layers.end(), aLayer ) == layers.end() )
2335 return;
2336
2337 aLayer = aField->GetLayer();
2338
2339 COLOR4D color = getRenderColor( aField, aLayer, drawingShadows, aDimmed );
2340
2341 if( !( aField->IsVisible() || aField->IsForceVisible() ) )
2342 {
2343 bool force_show = m_schematic ? eeconfig()->m_Appearance.show_hidden_fields
2344 : m_schSettings.m_ShowHiddenFields;
2345
2346 if( force_show )
2347 color = getRenderColor( aField, LAYER_HIDDEN, drawingShadows, aDimmed );
2348 else
2349 return;
2350 }
2351
2352 wxString shownText = aField->GetShownText( true );
2353
2354 if( shownText.IsEmpty() )
2355 return;
2356
2357 // Calculate the text orientation according to the parent orientation.
2358 EDA_ANGLE orient = aField->GetTextAngle();
2359
2360 if( aField->GetParent() && aField->GetParent()->Type() == SCH_SYMBOL_T )
2361 {
2362 if( static_cast<SCH_SYMBOL*>( aField->GetParent() )->GetTransform().y1 )
2363 {
2364 // Rotate symbol 90 degrees.
2365 if( orient.IsHorizontal() )
2366 orient = ANGLE_VERTICAL;
2367 else
2368 orient = ANGLE_HORIZONTAL;
2369 }
2370 }
2371
2372 /*
2373 * Calculate the text justification, according to the symbol orientation/mirror.
2374 * This is a bit complicated due to cumulative calculations:
2375 * - numerous cases (mirrored or not, rotation)
2376 * - the DrawGraphicText function recalculate also H and H justifications according to the
2377 * text orientation.
2378 * - when symbol is mirrored, the text is not mirrored and justifications are complicated
2379 * to calculate so the easier way is to use no justifications (centered text) and use
2380 * GetBoundingBox to know the text coordinate considered as centered
2381 */
2382 BOX2I bbox = aField->GetBoundingBox();
2383
2384 if( aField->GetParent() && aField->GetParent()->Type() == SCH_GLOBAL_LABEL_T )
2385 {
2386 SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( aField->GetParent() );
2387 bbox.Offset( label->GetSchematicTextOffset( &m_schSettings ) );
2388 }
2389
2390 if( m_schSettings.GetDrawBoundingBoxes() )
2391 drawItemBoundingBox( aField );
2392
2393 m_gal->SetStrokeColor( color );
2394 m_gal->SetFillColor( color );
2395
2396 if( drawingShadows && getFont( aField )->IsOutline() )
2397 {
2398 BOX2I shadow_box = bbox;
2399 shadow_box.Inflate( KiROUND( getTextThickness( aField ) * 2 ) );
2400
2401 m_gal->SetIsStroke( false );
2402 m_gal->SetIsFill( true );
2403 m_gal->DrawRectangle( shadow_box.GetPosition(), shadow_box.GetEnd() );
2404 }
2405 else
2406 {
2407 VECTOR2I textpos = bbox.Centre();
2408 TEXT_ATTRIBUTES attributes = aField->GetAttributes();
2409
2410 attributes.m_Halign = GR_TEXT_H_ALIGN_CENTER;
2411 attributes.m_Valign = GR_TEXT_V_ALIGN_CENTER;
2412 attributes.m_StrokeWidth = KiROUND( getTextThickness( aField ) );
2413 attributes.m_Angle = orient;
2414
2415 if( drawingShadows )
2416 attributes.m_StrokeWidth += getShadowWidth( !aField->IsSelected() );
2417
2418 if( aField->IsHypertext() && aField->IsRollover() )
2419 {
2420 m_gal->SetStrokeColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
2421 m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_HOVERED ) );
2422 attributes.m_Underlined = true;
2423 }
2424
2425 if( nonCached( aField ) && aField->RenderAsBitmap( m_gal->GetWorldScale() ) )
2426 {
2427 bitmapText( *m_gal, shownText, textpos, attributes );
2428 const_cast<SCH_FIELD*>( aField )->SetFlags( IS_SHOWN_AS_BITMAP );
2429 }
2430 else
2431 {
2432 std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
2433
2434 if( !aField->IsHypertext() )
2435 cache = aField->GetRenderCache( shownText, textpos, attributes );
2436
2437 if( cache )
2438 {
2439 m_gal->SetLineWidth( attributes.m_StrokeWidth );
2440 m_gal->DrawGlyphs( *cache );
2441 }
2442 else
2443 {
2444 strokeText( *m_gal, shownText, textpos, attributes, aField->GetFontMetrics() );
2445 }
2446
2447 const_cast<SCH_FIELD*>( aField )->ClearFlags( IS_SHOWN_AS_BITMAP );
2448 }
2449 }
2450
2451 // Draw anchor or umbilical line
2452 if( aField->IsMoving() && m_schematic )
2453 {
2454 VECTOR2I parentPos = aField->GetParentPosition();
2455
2456 m_gal->SetLineWidth( m_schSettings.GetOutlineWidth() );
2457 m_gal->SetStrokeColor( getRenderColor( aField, LAYER_SCHEMATIC_ANCHOR, drawingShadows ) );
2458 m_gal->DrawLine( aField->GetPosition(), parentPos );
2459 }
2460 else if( aField->IsSelected() )
2461 {
2462 drawAnchor( aField->GetPosition(), drawingShadows );
2463 }
2464}
2465
2466
2467void SCH_PAINTER::draw( const SCH_GLOBALLABEL* aLabel, int aLayer )
2468{
2469 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2470
2471 if( m_schSettings.IsPrinting() && drawingShadows )
2472 return;
2473
2474 bool drawingDangling = aLayer == LAYER_DANGLING;
2475
2476 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2477 {
2478 for( const SCH_FIELD& field : aLabel->GetFields() )
2479 draw( &field, aLayer, false );
2480 }
2481
2482 if( isFieldsLayer( aLayer ) )
2483 return;
2484
2485 if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
2486 return;
2487
2488 COLOR4D color = getRenderColor( aLabel, LAYER_GLOBLABEL, drawingShadows );
2489
2490 if( drawingDangling )
2491 {
2492 if( aLabel->IsDangling() )
2493 {
2494 drawDanglingIndicator( aLabel->GetTextPos(), color,
2496 drawingShadows, aLabel->IsBrightened() );
2497 }
2498
2499 return;
2500 }
2501
2502 std::vector<VECTOR2I> pts;
2503 std::deque<VECTOR2D> pts2;
2504
2505 aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() );
2506
2507 for( const VECTOR2I& p : pts )
2508 pts2.emplace_back( VECTOR2D( p.x, p.y ) );
2509
2510 m_gal->SetIsStroke( true );
2511 m_gal->SetLineWidth( getLineWidth( aLabel, drawingShadows ) );
2512 m_gal->SetStrokeColor( color );
2513
2514 if( drawingShadows )
2515 {
2516 m_gal->SetIsFill( eeconfig()->m_Selection.fill_shapes );
2517 m_gal->SetFillColor( color );
2518 m_gal->DrawPolygon( pts2 );
2519 }
2520 else
2521 {
2522 m_gal->SetIsFill( false );
2523 m_gal->DrawPolyline( pts2 );
2524 }
2525
2526 draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer, false );
2527}
2528
2529
2530void SCH_PAINTER::draw( const SCH_LABEL* aLabel, int aLayer )
2531{
2532 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2533
2534 if( m_schSettings.IsPrinting() && drawingShadows )
2535 return;
2536
2537 bool drawingDangling = aLayer == LAYER_DANGLING;
2538
2539 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2540 {
2541 for( const SCH_FIELD& field : aLabel->GetFields() )
2542 draw( &field, aLayer, false );
2543 }
2544
2545 if( isFieldsLayer( aLayer ) )
2546 return;
2547
2548 if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
2549 return;
2550
2551 COLOR4D color = getRenderColor( aLabel, LAYER_HIERLABEL, drawingShadows );
2552
2553 if( drawingDangling )
2554 {
2555 if( aLabel->IsDangling() )
2556 {
2557 drawDanglingIndicator( aLabel->GetTextPos(), color,
2559 drawingShadows, aLabel->IsBrightened() );
2560 }
2561
2562 return;
2563 }
2564
2565 draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer, false );
2566}
2567
2568
2569void SCH_PAINTER::draw( const SCH_HIERLABEL* aLabel, int aLayer, bool aDimmed )
2570{
2571 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2572
2573 if( m_schSettings.IsPrinting() && drawingShadows )
2574 return;
2575
2576 bool drawingDangling = aLayer == LAYER_DANGLING;
2577
2578 if( !( drawingShadows || drawingDangling ) || eeconfig()->m_Selection.draw_selected_children )
2579 {
2580 for( const SCH_FIELD& field : aLabel->GetFields() )
2581 draw( &field, aLayer, false );
2582 }
2583
2584 if( isFieldsLayer( aLayer ) )
2585 return;
2586
2587 if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
2588 return;
2589
2590 COLOR4D color = getRenderColor( aLabel, LAYER_HIERLABEL, drawingShadows, aDimmed );
2591
2592 if( drawingDangling )
2593 {
2594 if( aLabel->IsDangling() )
2595 {
2596 drawDanglingIndicator( aLabel->GetTextPos(), color,
2598 drawingShadows, aLabel->IsBrightened() );
2599 }
2600
2601 return;
2602 }
2603
2604 if( m_schematic )
2605 {
2606 SCH_CONNECTION* conn = nullptr;
2607
2608 if( !aLabel->IsConnectivityDirty() )
2609 conn = aLabel->Connection();
2610
2611 if( conn && conn->IsBus() )
2612 color = getRenderColor( aLabel, LAYER_BUS, drawingShadows, aDimmed );
2613 }
2614
2615 std::vector<VECTOR2I> pts;
2616 std::deque<VECTOR2D> pts2;
2617
2618 aLabel->CreateGraphicShape( &m_schSettings, pts, (VECTOR2I)aLabel->GetTextPos() );
2619
2620 for( const VECTOR2I& p : pts )
2621 pts2.emplace_back( VECTOR2D( p.x, p.y ) );
2622
2623 m_gal->SetIsFill( true );
2624 m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
2625 m_gal->SetIsStroke( true );
2626 m_gal->SetLineWidth( getLineWidth( aLabel, drawingShadows ) );
2627 m_gal->SetStrokeColor( color );
2628 m_gal->DrawPolyline( pts2 );
2629
2630 draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer, false );
2631}
2632
2633
2634void SCH_PAINTER::draw( const SCH_DIRECTIVE_LABEL* aLabel, int aLayer )
2635{
2636 if( !eeconfig()->m_Appearance.show_directive_labels && !aLabel->IsSelected() )
2637 return;
2638
2639 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2640
2641 if( m_schSettings.IsPrinting() && drawingShadows )
2642 return;
2643
2644 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2645 {
2646 for( const SCH_FIELD& field : aLabel->GetFields() )
2647 draw( &field, aLayer, false );
2648 }
2649
2650 if( isFieldsLayer( aLayer ) )
2651 return;
2652
2653 if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
2654 return;
2655
2656 COLOR4D color = getRenderColor( aLabel, LAYER_NETCLASS_REFS, drawingShadows );
2657
2658 if( aLayer == LAYER_DANGLING )
2659 {
2660 if( aLabel->IsDangling() )
2661 {
2662 drawDanglingIndicator( aLabel->GetTextPos(), color,
2664 drawingShadows, aLabel->IsBrightened() );
2665 }
2666
2667 return;
2668 }
2669
2670 std::vector<VECTOR2I> pts;
2671 std::deque<VECTOR2D> pts2;
2672
2673 aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() );
2674
2675 for( const VECTOR2I& p : pts )
2676 pts2.emplace_back( VECTOR2D( p.x, p.y ) );
2677
2678 m_gal->SetIsFill( false );
2679 m_gal->SetFillColor( color );
2680 m_gal->SetIsStroke( true );
2681 m_gal->SetLineWidth( getLineWidth( aLabel, drawingShadows ) );
2682 m_gal->SetStrokeColor( color );
2683
2684 if( aLabel->GetShape() == LABEL_FLAG_SHAPE::F_DOT )
2685 {
2686 m_gal->DrawLine( pts2[0], pts2[1] );
2687 m_gal->SetIsFill( true );
2688 m_gal->DrawCircle( pts2[2], ( pts2[2] - pts2[1] ).EuclideanNorm() );
2689 }
2690 else if( aLabel->GetShape() == LABEL_FLAG_SHAPE::F_ROUND )
2691 {
2692 m_gal->DrawLine( pts2[0], pts2[1] );
2693 m_gal->DrawCircle( pts2[2], ( pts2[2] - pts2[1] ).EuclideanNorm() );
2694 }
2695 else
2696 {
2697 m_gal->DrawPolyline( pts2 );
2698 }
2699}
2700
2701
2702void SCH_PAINTER::draw( const SCH_SHEET* aSheet, int aLayer )
2703{
2704 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2705 bool DNP = aSheet->GetDNP();
2706 bool markExclusion = eeconfig()->m_Appearance.mark_sim_exclusions
2707 && aSheet->GetExcludedFromSim();
2708
2709 if( m_schSettings.IsPrinting() && drawingShadows )
2710 return;
2711
2712 if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
2713 {
2714 for( const SCH_FIELD& field : aSheet->GetFields() )
2715 draw( &field, aLayer, DNP || markExclusion );
2716
2717 for( SCH_SHEET_PIN* sheetPin : aSheet->GetPins() )
2718 draw( static_cast<SCH_HIERLABEL*>( sheetPin ), aLayer, DNP || markExclusion );
2719 }
2720
2721 if( isFieldsLayer( aLayer ) )
2722 return;
2723
2724 VECTOR2D pos = aSheet->GetPosition();
2725 VECTOR2D size = aSheet->GetSize();
2726
2727 if( aLayer == LAYER_SHEET_BACKGROUND )
2728 {
2729 // Do not fill the shape in B&W print mode, to avoid to visible items
2730 // inside the shape
2731 if( !m_schSettings.PrintBlackAndWhiteReq() )
2732 {
2733 m_gal->SetFillColor( getRenderColor( aSheet, LAYER_SHEET_BACKGROUND, true ) );
2734 m_gal->SetIsFill( true );
2735 m_gal->SetIsStroke( false );
2736
2737 m_gal->DrawRectangle( pos, pos + size );
2738 }
2739 }
2740
2741 if( aLayer == LAYER_SHEET || aLayer == LAYER_SELECTION_SHADOWS )
2742 {
2743 m_gal->SetStrokeColor( getRenderColor( aSheet, LAYER_SHEET, drawingShadows ) );
2744 m_gal->SetIsStroke( true );
2745 m_gal->SetLineWidth( getLineWidth( aSheet, drawingShadows ) );
2746 m_gal->SetIsFill( false );
2747
2748 m_gal->DrawRectangle( pos, pos + size );
2749 }
2750
2751 if( DNP || markExclusion )
2752 {
2753 int layer = DNP ? LAYER_DNP_MARKER : LAYER_EXCLUDED_FROM_SIM;
2754 BOX2I bbox = aSheet->GetBodyBoundingBox();
2755 BOX2I pins = aSheet->GetBoundingBox();
2756 VECTOR2D margins( std::max( bbox.GetX() - pins.GetX(), pins.GetEnd().x - bbox.GetEnd().x ),
2757 std::max( bbox.GetY() - pins.GetY(), pins.GetEnd().y - bbox.GetEnd().y ) );
2758 int strokeWidth = 3 * schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
2759
2760 margins.x = std::max( margins.x * 0.6, margins.y * 0.3 );
2761 margins.y = std::max( margins.y * 0.6, margins.x * 0.3 );
2762 bbox.Inflate( KiROUND( margins.x ), KiROUND( margins.y ) );
2763
2764 VECTOR2I pt1 = bbox.GetOrigin();
2765 VECTOR2I pt2 = bbox.GetEnd();
2766
2767 GAL_SCOPED_ATTRS scopedAttrs( *m_gal, GAL_SCOPED_ATTRS::ALL_ATTRS );
2768 m_gal->SetIsStroke( true );
2769 m_gal->SetIsFill( true );
2770 m_gal->SetStrokeColor( m_schSettings.GetLayerColor( layer ) );
2771 m_gal->SetFillColor( m_schSettings.GetLayerColor( layer ) );
2772
2773 m_gal->DrawSegment( pt1, pt2, strokeWidth );
2774 std::swap( pt1.x, pt2.x );
2775 m_gal->DrawSegment( pt1, pt2, strokeWidth );
2776 }
2777}
2778
2779
2780void SCH_PAINTER::draw( const SCH_NO_CONNECT* aNC, int aLayer )
2781{
2782 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2783
2784 if( m_schSettings.IsPrinting() && drawingShadows )
2785 return;
2786
2787 if( drawingShadows && !( aNC->IsBrightened() || aNC->IsSelected() ) )
2788 return;
2789
2790 m_gal->SetIsStroke( true );
2791 m_gal->SetLineWidth( getLineWidth( aNC, drawingShadows ) );
2792 m_gal->SetStrokeColor( getRenderColor( aNC, LAYER_NOCONNECT, drawingShadows ) );
2793 m_gal->SetIsFill( false );
2794
2795 VECTOR2D p = aNC->GetPosition();
2796 int delta = std::max( aNC->GetSize(), m_schSettings.GetDefaultPenWidth() * 3 ) / 2;
2797
2798 m_gal->DrawLine( p + VECTOR2D( -delta, -delta ), p + VECTOR2D( delta, delta ) );
2799 m_gal->DrawLine( p + VECTOR2D( -delta, delta ), p + VECTOR2D( delta, -delta ) );
2800}
2801
2802
2803void SCH_PAINTER::draw( const SCH_BUS_ENTRY_BASE *aEntry, int aLayer )
2804{
2806 SCH_LINE line( VECTOR2I(), layer );
2807 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2808 bool drawingNetColorHighlights = aLayer == LAYER_NET_COLOR_HIGHLIGHT;
2809 bool drawingDangling = aLayer == LAYER_DANGLING;
2810 bool drawingWires = aLayer == LAYER_WIRE;
2811 bool drawingBusses = aLayer == LAYER_BUS;
2812
2813 if( m_schSettings.IsPrinting() && drawingShadows )
2814 return;
2815
2816 bool highlightNetclassColors = false;
2817 EESCHEMA_SETTINGS* eeschemaCfg = eeconfig();
2818
2819 if( eeschemaCfg )
2820 {
2821 highlightNetclassColors = eeschemaCfg->m_Selection.highlight_netclass_colors;
2822 }
2823
2824 if( !highlightNetclassColors && drawingNetColorHighlights )
2825 return;
2826
2827 if( m_schSettings.m_OverrideItemColors && drawingNetColorHighlights )
2828 return;
2829
2830 if( drawingShadows && !( aEntry->IsBrightened() || aEntry->IsSelected() ) )
2831 return;
2832
2833 if( aEntry->IsSelected() )
2834 {
2835 line.SetSelected();
2836 // Never show unselected endpoints on bus entries
2837 line.SetFlags( STARTPOINT | ENDPOINT );
2838 }
2839 else if( aEntry->IsBrightened() )
2840 line.SetBrightened();
2841
2842 line.SetStartPoint( aEntry->GetPosition() );
2843 line.SetEndPoint( aEntry->GetEnd() );
2844 line.SetStroke( aEntry->GetStroke() );
2845 line.SetLineWidth( KiROUND( getLineWidth( aEntry, false ) ) );
2846
2847 COLOR4D color = getRenderColor( aEntry, LAYER_WIRE, drawingShadows );
2848
2849 if( aEntry->Type() == SCH_BUS_BUS_ENTRY_T )
2850 color = getRenderColor( aEntry, LAYER_BUS, drawingShadows );
2851
2852 if( highlightNetclassColors )
2853 {
2854 // Force default color for nets we are going to highlight
2855 if( drawingWires )
2856 color = m_schSettings.GetLayerColor( LAYER_WIRE );
2857 else if( drawingBusses )
2858 color = m_schSettings.GetLayerColor( LAYER_BUS );
2859 }
2860
2861 if( drawingNetColorHighlights )
2862 {
2863 // Don't draw highlights for default-colored nets
2864 if( ( aEntry->Type() == SCH_BUS_WIRE_ENTRY_T
2865 && color == m_schSettings.GetLayerColor( LAYER_WIRE ) )
2866 || ( aEntry->Type() == SCH_BUS_BUS_ENTRY_T
2867 && color == m_schSettings.GetLayerColor( LAYER_BUS ) ) )
2868 {
2869 return;
2870 }
2871 }
2872
2873 if( drawingDangling )
2874 {
2875 m_gal->SetIsFill( false );
2876 m_gal->SetIsStroke( true );
2877 m_gal->SetStrokeColor( color.Brightened( 0.3 ) );
2878 m_gal->SetLineWidth( m_schSettings.GetDanglingIndicatorThickness() );
2879
2880 if( aEntry->IsDanglingStart() )
2881 {
2882 m_gal->DrawCircle( aEntry->GetPosition(),
2883 aEntry->GetPenWidth() + KiROUND( TARGET_BUSENTRY_RADIUS / 2.0 ) );
2884 }
2885
2886 if( aEntry->IsDanglingEnd() )
2887 {
2888 m_gal->DrawCircle( aEntry->GetEnd(),
2889 aEntry->GetPenWidth() + KiROUND( TARGET_BUSENTRY_RADIUS / 2.0 ) );
2890 }
2891 }
2892 else
2893 {
2894 line.SetLineColor( color );
2895 line.SetLineStyle( aEntry->GetLineStyle() );
2896
2897 draw( &line, aLayer );
2898 }
2899}
2900
2901
2902void SCH_PAINTER::draw( const SCH_BITMAP* aBitmap, int aLayer )
2903{
2904 m_gal->Save();
2905 m_gal->Translate( aBitmap->GetPosition() );
2906
2907 const REFERENCE_IMAGE& refImage = aBitmap->GetReferenceImage();
2908
2909 // When the image scale factor is not 1.0, we need to modify the actual as the image scale
2910 // factor is similar to a local zoom
2911 const double img_scale = refImage.GetImageScale();
2912
2913 if( img_scale != 1.0 )
2914 m_gal->Scale( VECTOR2D( img_scale, img_scale ) );
2915
2916 if( aLayer == LAYER_DRAW_BITMAPS )
2917 {
2918 m_gal->DrawBitmap( refImage.GetImage() );
2919 }
2920
2921 if( aLayer == LAYER_SELECTION_SHADOWS )
2922 {
2923 if( aBitmap->IsSelected() || aBitmap->IsBrightened() )
2924 {
2925 const COLOR4D color = getRenderColor( aBitmap, LAYER_DRAW_BITMAPS, true );
2926 m_gal->SetIsStroke( true );
2927 m_gal->SetStrokeColor( color );
2928 m_gal->SetLineWidth ( getShadowWidth( aBitmap->IsBrightened() ) );
2929 m_gal->SetIsFill( false );
2930
2931 // Draws a bounding box.
2932 VECTOR2D bm_size( refImage.GetSize() );
2933 // bm_size is the actual image size in UI.
2934 // but m_gal scale was previously set to img_scale
2935 // so recalculate size relative to this image size.
2936 bm_size.x /= img_scale;
2937 bm_size.y /= img_scale;
2938 const VECTOR2D origin( -bm_size.x / 2.0, -bm_size.y / 2.0 );
2939 const VECTOR2D end = origin + bm_size;
2940
2941 m_gal->DrawRectangle( origin, end );
2942 }
2943 }
2944
2945 m_gal->Restore();
2946}
2947
2948
2949void SCH_PAINTER::draw( const SCH_MARKER* aMarker, int aLayer )
2950{
2951 bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
2952
2953 if( m_schSettings.IsPrinting() && drawingShadows )
2954 return;
2955
2956 if( drawingShadows && !( aMarker->IsBrightened() || aMarker->IsSelected() ) )
2957 return;
2958
2959 COLOR4D color = getRenderColor( aMarker, aMarker->GetColorLayer(), drawingShadows );
2960
2961 m_gal->Save();
2962 m_gal->Translate( aMarker->GetPosition() );
2963 m_gal->SetIsFill( !drawingShadows );
2964 m_gal->SetFillColor( color );
2965 m_gal->SetIsStroke( drawingShadows );
2966 m_gal->SetLineWidth( getLineWidth( aMarker, drawingShadows ) );
2967 m_gal->SetStrokeColor( color );
2968
2969 SHAPE_LINE_CHAIN polygon;
2970 aMarker->ShapeToPolygon( polygon );
2971
2972 m_gal->DrawPolygon( polygon );
2973 m_gal->Restore();
2974}
2975
2976
2977}; // 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:138
FILL_T GetFillMode() const
Definition: eda_shape.h:114
int GetEndX() const
Definition: eda_shape.h:176
bool IsFilled() const
Definition: eda_shape.h:98
SHAPE_T GetShape() const
Definition: eda_shape.h:132
int GetEndY() const
Definition: eda_shape.h:175
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:174
COLOR4D GetFillColor() const
Definition: eda_shape.h:118
int GetStartX() const
Definition: eda_shape.h:139
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:80
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:257
COLOR4D GetTextColor() const
Definition: eda_text.h:254
bool IsItalic() const
Definition: eda_text.h:156
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
virtual bool IsVisible() const
Definition: eda_text.h:174
KIFONT::FONT * GetFont() const
Definition: eda_text.h:234
BOX2I GetTextBox(int aLine=-1) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:703
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:644
virtual EDA_ANGLE GetDrawRotation() const
Definition: eda_text.h:362
virtual VECTOR2I GetDrawPos() const
Definition: eda_text.h:363
bool HasTextVars() const
Indicates the ShownText has text var references which need to be processed.
Definition: eda_text.h:117
const TEXT_ATTRIBUTES & GetAttributes() const
Definition: eda_text.h:218
bool IsBold() const
Definition: eda_text.h:171
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:269
VECTOR2I GetTextSize() const
Definition: eda_text.h:245
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:158
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:822
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:808
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:1624
virtual bool IsDangling() const override
Determines dangling state from connectivity and cached connected rule areas.
Definition: sch_label.cpp:1781
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:617
VECTOR2I GetPosition() const override
Definition: sch_field.cpp:1486
bool IsHypertext() const override
Allow items to support hypertext actions when hovered/clicked.
Definition: sch_field.h:101
std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
Definition: sch_field.cpp:561
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
Definition: sch_field.cpp:211
std::vector< std::unique_ptr< KIFONT::GLYPH > > * GetRenderCache(const wxString &forResolvedText, const VECTOR2I &forPosition, TEXT_ATTRIBUTES &aAttrs) const
Definition: sch_field.cpp:384
VECTOR2I GetParentPosition() const
Definition: sch_field.cpp:1502
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:1928
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:1823
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:2038
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
std::vector< int > ViewGetLayers() const override
Return the layers the item is drawn on (which may be more than its "home" layer)
Definition: sch_item.cpp:202
int GetUnit() const
Definition: sch_item.h: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:487
bool IsConnectivityDirty() const
Definition: sch_item.h:510
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
Definition: sch_item.cpp:218
wxString GetClass() const override
Return the class name.
Definition: sch_item.h:176
const KIFONT::METRICS & GetFontMetrics() const
Definition: sch_item.cpp:464
int GetEffectivePenWidth(const SCH_RENDER_SETTINGS *aSettings) const
Definition: sch_item.cpp:473
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition: sch_item.h: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:973
bool IsStartDangling() const
Definition: sch_line.h:261
void SetLineColor(const COLOR4D &aColor)
Definition: sch_line.cpp:245
void SetLineWidth(const int aSize)
Definition: sch_line.cpp:317
LINE_STYLE GetEffectiveLineStyle() const
Definition: sch_line.cpp:304
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:979
void SetLineStyle(const LINE_STYLE aStyle)
Definition: sch_line.cpp:288
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:312
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:557
int GetLength() const
Definition: sch_pin.cpp:295
const wxString & GetOperatingPoint() const
Definition: sch_pin.h:288
void SetName(const wxString &aName)
Definition: sch_pin.cpp:399
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:367
VECTOR2I GetPinRoot() const
Definition: sch_pin.cpp:581
bool IsDangling() const override
Definition: sch_pin.cpp:412
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: sch_pin.h:89
VECTOR2I GetPosition() const override
Definition: sch_pin.cpp:252
int GetNameTextSize() const
Definition: sch_pin.cpp:533
wxString GetShownName() const
Definition: sch_pin.cpp:497
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:329
GRAPHIC_PINSHAPE GetShape() const
Definition: sch_pin.cpp:274
ELECTRICAL_PINTYPE GetType() const
Definition: sch_pin.cpp:309
std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const override
Make a set of SHAPE objects representing the SCH_SHAPE.
Definition: sch_shape.h: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:717
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_sheet.cpp:738
KIGFX::COLOR4D GetBorderColor() const
Definition: sch_sheet.h: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:142
const STROKE_PARAMS & GetBorderStroke() const
Definition: sch_table.h:60
VECTOR2I GetPosition() const override
Definition: sch_table.cpp:115
VECTOR2I GetEnd() const
Definition: sch_table.cpp:135
int GetColCount() const
Definition: sch_table.h:105
SCH_TABLECELL * GetCell(int aRow, int aCol) const
Definition: sch_table.h:132
bool StrokeColumns() const
Definition: sch_table.h:84
bool StrokeRows() const
Definition: sch_table.h:87
int GetRowCount() const
Definition: sch_table.h:107
bool StrokeHeader() const
Definition: sch_table.h:57
virtual wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
VECTOR2I GetDrawPos() const override
bool IsHypertext() const override
Allow items to support hypertext actions when hovered/clicked.
Definition: sch_textbox.h:86
bool IsHypertext() const override
Allow items to support hypertext actions when hovered/clicked.
Definition: sch_text.h:78
VECTOR2I GetPosition() const override
Definition: sch_text.h:141
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_text.cpp:385
virtual wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
Definition: sch_text.cpp:406
virtual VECTOR2I GetSchematicTextOffset(const RENDER_SETTINGS *aSettings) const
This offset depends on the orientation, the type of text, and the area required to draw the associate...
Definition: sch_text.cpp:72
VECTOR2I B
Definition: seg.h:50
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
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, int aFlags)
Definition: common.cpp:59
The common library.
#define DANGLING_SYMBOL_SIZE
< The size of the rectangle indicating an unconnected wire or label
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
#define UNSELECTED_END_SIZE
The size of the rectangle indicating the anchor of a text object (including fields)
#define TEXT_ANCHOR_SIZE
The default pin len value when creating pins(can be changed in preference menu)
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:401
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:403
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition: eda_angle.h:398
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition: eda_angle.h:397
static constexpr EDA_ANGLE ANGLE_270
Definition: eda_angle.h:406
static constexpr EDA_ANGLE ANGLE_180
Definition: eda_angle.h:405
#define IS_SHOWN_AS_BITMAP
#define ENDPOINT
ends. (Used to support dragging.)
#define IS_DANGLING
indicates a pin is dangling
#define STARTPOINT
When a line is selected, these flags indicate which.
@ 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