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