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