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