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