Overhaul bitmap text for performance.

Also adjusts metrics to better match stroke font.

Also removes text-halo highlighting as it's too expensive to re-render
when the zoom changes.

Fixes https://gitlab.com/kicad/code/kicad/issues/11460
This commit is contained in:
Jeff Young 2022-05-13 22:36:20 +01:00
parent 6d7835e742
commit 38e5faf21b
20 changed files with 234 additions and 298 deletions

View File

@ -120,13 +120,16 @@ void OUTLINE_GLYPH::Triangulate( std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2, const VECTOR2I& aPt2,
const VECTOR2I& aPt3 )> aCallback ) const const VECTOR2I& aPt3 )> aCallback ) const
{ {
const_cast<OUTLINE_GLYPH*>( this )->CacheTriangulation( false ); // Only call CacheTriangulation if it has never been done before. Otherwise we'll hash
// the triangulation to see if it has been edited, and glyphs after creation are read-only.
if( TriangulatedPolyCount() == 0 )
const_cast<OUTLINE_GLYPH*>( this )->CacheTriangulation( false );
for( unsigned int i = 0; i < TriangulatedPolyCount(); i++ ) for( unsigned int i = 0; i < TriangulatedPolyCount(); i++ )
{ {
const SHAPE_POLY_SET::TRIANGULATED_POLYGON* polygon = TriangulatedPolygon( i ); const SHAPE_POLY_SET::TRIANGULATED_POLYGON* polygon = TriangulatedPolygon( i );
for ( size_t j = 0; j < polygon->GetTriangleCount(); j++ ) for( size_t j = 0; j < polygon->GetTriangleCount(); j++ )
{ {
VECTOR2I a, b, c; VECTOR2I a, b, c;
polygon->GetTriangle( j, a, b, c ); polygon->GetTriangle( j, a, b, c );

View File

@ -270,9 +270,8 @@ void GAL::BitmapText( const wxString& aText, const VECTOR2I& aPosition, const ED
// Bitmap font has different metrics than the stroke font so we compensate a bit before // Bitmap font has different metrics than the stroke font so we compensate a bit before
// stroking // stroking
attrs.m_Size = VECTOR2I( m_attributes.m_Size.x * 0.83, m_attributes.m_Size.y * 0.86 ); attrs.m_Size = VECTOR2I( m_attributes.m_Size.x, m_attributes.m_Size.y * 0.95 );
int strokeWidth = GetLineWidth(); attrs.m_StrokeWidth = GetLineWidth() * 0.74;
attrs.m_StrokeWidth = strokeWidth * 0.8;
font->Draw( this, aText, aPosition, attrs ); font->Draw( this, aText, aPosition, attrs );
} }

View File

@ -2036,13 +2036,13 @@ int OPENGL_GAL::drawBitmapChar( unsigned long aChar )
if( aChar == ' ' ) if( aChar == ' ' )
{ {
const FONT_GLYPH_TYPE* g = LookupGlyph( 'x' ); const FONT_GLYPH_TYPE* g = LookupGlyph( 'x' );
wxASSERT( g ); wxCHECK( g, 0 );
if( !g ) // Should not happen. // Match stroke font as well as possible
return 0; double spaceWidth = g->advance * 0.74;
Translate( VECTOR2D( g->advance, 0 ) ); Translate( VECTOR2D( spaceWidth, 0 ) );
return g->advance; return KiROUND( spaceWidth );
} }
const FONT_GLYPH_TYPE* glyph = LookupGlyph( aChar ); const FONT_GLYPH_TYPE* glyph = LookupGlyph( aChar );

View File

@ -60,7 +60,6 @@ void PANEL_EESCHEMA_DISPLAY_OPTIONS::loadEEschemaSettings( EESCHEMA_SETTINGS* cf
m_checkShowERCExclusions->SetValue( cfg->m_Appearance.show_erc_exclusions ); m_checkShowERCExclusions->SetValue( cfg->m_Appearance.show_erc_exclusions );
m_checkPageLimits->SetValue( cfg->m_Appearance.show_page_limits ); m_checkPageLimits->SetValue( cfg->m_Appearance.show_page_limits );
m_checkSelTextBox->SetValue( cfg->m_Selection.text_as_box );
m_checkSelDrawChildItems->SetValue( cfg->m_Selection.draw_selected_children ); m_checkSelDrawChildItems->SetValue( cfg->m_Selection.draw_selected_children );
m_checkSelFillShapes->SetValue( cfg->m_Selection.fill_shapes ); m_checkSelFillShapes->SetValue( cfg->m_Selection.fill_shapes );
m_selWidthCtrl->SetValue( cfg->m_Selection.selection_thickness ); m_selWidthCtrl->SetValue( cfg->m_Selection.selection_thickness );
@ -101,7 +100,6 @@ bool PANEL_EESCHEMA_DISPLAY_OPTIONS::TransferDataFromWindow()
cfg->m_Appearance.show_erc_exclusions = m_checkShowERCExclusions->GetValue(); cfg->m_Appearance.show_erc_exclusions = m_checkShowERCExclusions->GetValue();
cfg->m_Appearance.show_page_limits = m_checkPageLimits->GetValue(); cfg->m_Appearance.show_page_limits = m_checkPageLimits->GetValue();
cfg->m_Selection.text_as_box = m_checkSelTextBox->GetValue();
cfg->m_Selection.draw_selected_children = m_checkSelDrawChildItems->GetValue(); cfg->m_Selection.draw_selected_children = m_checkSelDrawChildItems->GetValue();
cfg->m_Selection.fill_shapes = m_checkSelFillShapes->GetValue(); cfg->m_Selection.fill_shapes = m_checkSelFillShapes->GetValue();
cfg->m_Selection.selection_thickness = KiROUND( m_selWidthCtrl->GetValue() ); cfg->m_Selection.selection_thickness = KiROUND( m_selWidthCtrl->GetValue() );

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3) // C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO *NOT* EDIT THIS FILE! // PLEASE DO *NOT* EDIT THIS FILE!
@ -68,9 +68,6 @@ PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE::PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE( wxWind
wxStaticBoxSizer* sbSizer3; wxStaticBoxSizer* sbSizer3;
sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Selection && Highlighting") ), wxVERTICAL ); sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Selection && Highlighting") ), wxVERTICAL );
m_checkSelTextBox = new wxCheckBox( sbSizer3->GetStaticBox(), wxID_ANY, _("Draw selected text items as box"), wxDefaultPosition, wxDefaultSize, 0 );
sbSizer3->Add( m_checkSelTextBox, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_checkSelDrawChildItems = new wxCheckBox( sbSizer3->GetStaticBox(), wxID_ANY, _("Draw selected child items"), wxDefaultPosition, wxDefaultSize, 0 ); m_checkSelDrawChildItems = new wxCheckBox( sbSizer3->GetStaticBox(), wxID_ANY, _("Draw selected child items"), wxDefaultPosition, wxDefaultSize, 0 );
sbSizer3->Add( m_checkSelDrawChildItems, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); sbSizer3->Add( m_checkSelDrawChildItems, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project> <wxFormBuilder_Project>
<FileVersion major="1" minor="16" /> <FileVersion major="1" minor="15" />
<object class="Project" expanded="1"> <object class="Project" expanded="1">
<property name="class_decoration"></property> <property name="class_decoration"></property>
<property name="code_generation">C++</property> <property name="code_generation">C++</property>
@ -14,7 +14,6 @@
<property name="file">panel_eeschema_display_options_base</property> <property name="file">panel_eeschema_display_options_base</property>
<property name="first_id">1000</property> <property name="first_id">1000</property>
<property name="help_provider">none</property> <property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property> <property name="indent_with_spaces"></property>
<property name="internationalize">1</property> <property name="internationalize">1</property>
<property name="name">PanelEeschemaDisplayOptions</property> <property name="name">PanelEeschemaDisplayOptions</property>
@ -26,7 +25,6 @@
<property name="skip_php_events">1</property> <property name="skip_php_events">1</property>
<property name="skip_python_events">1</property> <property name="skip_python_events">1</property>
<property name="ui_table">UI</property> <property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">1</property> <property name="use_enum">1</property>
<property name="use_microsoft_bom">0</property> <property name="use_microsoft_bom">0</property>
<object class="Panel" expanded="1"> <object class="Panel" expanded="1">
@ -48,7 +46,6 @@
<property name="size">-1,-1</property> <property name="size">-1,-1</property>
<property name="subclass">RESETTABLE_PANEL; widgets/resettable_panel.h; Not forward_declare</property> <property name="subclass">RESETTABLE_PANEL; widgets/resettable_panel.h; Not forward_declare</property>
<property name="tooltip"></property> <property name="tooltip"></property>
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property> <property name="window_style">wxTAB_TRAVERSAL</property>
@ -623,70 +620,6 @@
<property name="orient">wxVERTICAL</property> <property name="orient">wxVERTICAL</property>
<property name="parent">1</property> <property name="parent">1</property>
<property name="permission">none</property> <property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Draw selected text items as box</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_checkSelTextBox</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property> <property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property>

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3) // C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO *NOT* EDIT THIS FILE! // PLEASE DO *NOT* EDIT THIS FILE!
@ -46,7 +46,6 @@ class PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE : public RESETTABLE_PANEL
wxCheckBox* m_checkShowERCWarnings; wxCheckBox* m_checkShowERCWarnings;
wxCheckBox* m_checkShowERCExclusions; wxCheckBox* m_checkShowERCExclusions;
wxCheckBox* m_checkPageLimits; wxCheckBox* m_checkPageLimits;
wxCheckBox* m_checkSelTextBox;
wxCheckBox* m_checkSelDrawChildItems; wxCheckBox* m_checkSelDrawChildItems;
wxCheckBox* m_checkSelFillShapes; wxCheckBox* m_checkSelFillShapes;
wxStaticText* m_selWidthLabel; wxStaticText* m_selWidthLabel;
@ -62,7 +61,6 @@ class PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE : public RESETTABLE_PANEL
public: public:
PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString ); PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
~PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE(); ~PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE();
}; };

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -203,9 +203,6 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() :
m_params.emplace_back( new PARAM<bool>( "selection.select_pin_selects_symbol", m_params.emplace_back( new PARAM<bool>( "selection.select_pin_selects_symbol",
&m_Selection.select_pin_selects_symbol, true ) ); &m_Selection.select_pin_selects_symbol, true ) );
m_params.emplace_back( new PARAM<bool>( "selection.text_as_box",
&m_Selection.text_as_box, false ) );
m_params.emplace_back( new PARAM<int>( "annotation.method", m_params.emplace_back( new PARAM<int>( "annotation.method",
&m_AnnotatePanel.method, 0, 0, 2 ) ); &m_AnnotatePanel.method, 0, 0, 2 ) );
@ -481,7 +478,6 @@ bool EESCHEMA_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
ret &= fromLegacy<bool>( aCfg, "SelectionFillShapes", "selection.fill_shapes" ); ret &= fromLegacy<bool>( aCfg, "SelectionFillShapes", "selection.fill_shapes" );
ret &= fromLegacy<bool>( aCfg, "SelectPinSelectSymbolOpt", ret &= fromLegacy<bool>( aCfg, "SelectPinSelectSymbolOpt",
"selection.select_pin_selects_symbol" ); "selection.select_pin_selects_symbol" );
ret &= fromLegacy<bool>( aCfg, "SelectionTextAsBox", "selection.text_as_box" );
ret &= fromLegacy<int>( aCfg, "AnnotateAlgoOption", "annotation.method" ); ret &= fromLegacy<int>( aCfg, "AnnotateAlgoOption", "annotation.method" );
ret &= fromLegacy<int>( aCfg, "AnnotateFilterMsg", "annotation.messages_filter" ); ret &= fromLegacy<int>( aCfg, "AnnotateFilterMsg", "annotation.messages_filter" );

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -139,7 +139,6 @@ public:
bool draw_selected_children; bool draw_selected_children;
bool fill_shapes; bool fill_shapes;
bool select_pin_selects_symbol; bool select_pin_selects_symbol;
bool text_as_box;
}; };
struct PAGE_SETTINGS struct PAGE_SETTINGS

View File

@ -369,8 +369,17 @@ void SCH_BASE_FRAME::UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete, bool aUpda
} }
void SCH_BASE_FRAME::RefreshSelection() void SCH_BASE_FRAME::RefreshZoomDependentItems()
{ {
// We currently have two zoom-dependent renderings: text, which is rendered as bitmap text
// when too small to see the difference, and selection shadows.
//
// Because non-selected text is cached by OpenGL, we only apply the bitmap performance hack
// to selected text items.
//
// Thus, as it currently stands, all zoom-dependent items can be found in the list of selected
// items.
if( m_toolManager ) if( m_toolManager )
{ {
EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>(); EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>();
@ -379,18 +388,13 @@ void SCH_BASE_FRAME::RefreshSelection()
for( EDA_ITEM* item : selection ) for( EDA_ITEM* item : selection )
{ {
EDA_ITEM* parent = item->GetParent(); if( item->RenderAsBitmap( view->GetGAL()->GetWorldScale() ) != item->IsShownAsBitmap()
|| item->IsType( KIGFX::SCH_PAINTER::g_ScaledSelectionTypes ) )
if( item->Type() == SCH_SHEET_PIN_T )
{
// Sheet pins aren't in the view. Refresh their parent.
if( parent )
GetCanvas()->GetView()->Update( parent );
}
else
{ {
view->Update( item, KIGFX::REPAINT ); view->Update( item, KIGFX::REPAINT );
EDA_ITEM* parent = item->GetParent();
// Symbol children are drawn from their parents. Mark them for re-paint. // Symbol children are drawn from their parents. Mark them for re-paint.
if( parent && parent->Type() == SCH_SYMBOL_T ) if( parent && parent->Type() == SCH_SYMBOL_T )
GetCanvas()->GetView()->Update( parent, KIGFX::REPAINT ); GetCanvas()->GetView()->Update( parent, KIGFX::REPAINT );

View File

@ -223,7 +223,7 @@ public:
/** /**
* Mark selected items for refresh. * Mark selected items for refresh.
*/ */
void RefreshSelection(); void RefreshZoomDependentItems();
/** /**
* Mark all items for refresh. * Mark all items for refresh.

View File

@ -39,6 +39,13 @@
#include <project/net_settings.h> #include <project/net_settings.h>
// Rendering fonts is expensive (particularly when using outline fonts). At small effective
// sizes (ie: zoomed out) the visual differences between outline and/or stroke fonts and the
// bitmap font becomes immaterial, and there's often more to draw when zoomed out so the
// performance gain becomes more significant.
#define BITMAP_FONT_SIZE_THRESHOLD 3
/* Constructor and destructor for SCH_ITEM */ /* Constructor and destructor for SCH_ITEM */
/* They are not inline because this creates problems with gcc at linking time in debug mode */ /* They are not inline because this creates problems with gcc at linking time in debug mode */
@ -282,6 +289,15 @@ const wxString& SCH_ITEM::GetDefaultFont() const
} }
bool SCH_ITEM::RenderAsBitmap( double aWorldScale ) const
{
if( const EDA_TEXT* text = dynamic_cast<const EDA_TEXT*>( this ) )
return text->GetTextHeight() * aWorldScale < BITMAP_FONT_SIZE_THRESHOLD;
return false;
}
void SCH_ITEM::Plot( PLOTTER* aPlotter, bool aBackground ) const void SCH_ITEM::Plot( PLOTTER* aPlotter, bool aBackground ) const
{ {
wxFAIL_MSG( wxT( "Plot() method not implemented for class " ) + GetClass() ); wxFAIL_MSG( wxT( "Plot() method not implemented for class " ) + GetClass() );

View File

@ -262,6 +262,8 @@ public:
const wxString& GetDefaultFont() const; const wxString& GetDefaultFont() const;
bool RenderAsBitmap( double aWorldScale ) const override;
/** /**
* Print a schematic item. * Print a schematic item.
* *

View File

@ -607,7 +607,7 @@ const EDA_RECT SCH_LABEL_BASE::GetBoundingBox() const
{ {
EDA_RECT fieldBBox = field.GetBoundingBox(); EDA_RECT fieldBBox = field.GetBoundingBox();
if( Type() == SCH_GLOBAL_LABEL_T ) if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
fieldBBox.Offset( GetSchematicTextOffset( nullptr ) ); fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
box.Merge( fieldBBox ); box.Merge( fieldBBox );
@ -635,7 +635,7 @@ bool SCH_LABEL_BASE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
EDA_RECT fieldBBox = field.GetBoundingBox(); EDA_RECT fieldBBox = field.GetBoundingBox();
fieldBBox.Inflate( aAccuracy ); fieldBBox.Inflate( aAccuracy );
if( Type() == SCH_GLOBAL_LABEL_T ) if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
fieldBBox.Offset( GetSchematicTextOffset( nullptr ) ); fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
if( fieldBBox.Contains( aPosition ) ) if( fieldBBox.Contains( aPosition ) )
@ -668,7 +668,7 @@ bool SCH_LABEL_BASE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccur
{ {
EDA_RECT fieldBBox = field.GetBoundingBox(); EDA_RECT fieldBBox = field.GetBoundingBox();
if( Type() == SCH_GLOBAL_LABEL_T ) if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
fieldBBox.Offset( GetSchematicTextOffset( nullptr ) ); fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
if( rect.Intersects( fieldBBox ) ) if( rect.Intersects( fieldBBox ) )
@ -900,6 +900,7 @@ const EDA_RECT SCH_LABEL::GetBodyBoundingBox() const
EDA_RECT rect = GetTextBox(); EDA_RECT rect = GetTextBox();
rect.Offset( 0, -GetTextOffset() ); rect.Offset( 0, -GetTextOffset() );
rect.Inflate( GetEffectiveTextPenWidth() );
if( !GetTextAngle().IsZero() ) if( !GetTextAngle().IsZero() )
{ {
@ -964,6 +965,17 @@ SCH_DIRECTIVE_LABEL::SCH_DIRECTIVE_LABEL( const SCH_DIRECTIVE_LABEL& aClassLabel
} }
int SCH_DIRECTIVE_LABEL::GetPenWidth() const
{
int pen = 0;
if( Schematic() )
pen = Schematic()->Settings().m_DefaultLineWidth;
return GetEffectiveTextPenWidth( pen );
}
void SCH_DIRECTIVE_LABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings, void SCH_DIRECTIVE_LABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings,
std::vector<VECTOR2I>& aPoints, std::vector<VECTOR2I>& aPoints,
const VECTOR2I& aPos ) const const VECTOR2I& aPos ) const

View File

@ -235,6 +235,8 @@ public:
int GetPinLength() const { return m_pinLength; } int GetPinLength() const { return m_pinLength; }
void SetPinLength( int aLength ) { m_pinLength = aLength; } void SetPinLength( int aLength ) { m_pinLength = aLength; }
int GetPenWidth() const override;
void CreateGraphicShape( const RENDER_SETTINGS* aSettings, std::vector<VECTOR2I>& aPoints, void CreateGraphicShape( const RENDER_SETTINGS* aSettings, std::vector<VECTOR2I>& aPoints,
const VECTOR2I& aPos ) const override; const VECTOR2I& aPos ) const override;

View File

@ -74,6 +74,21 @@ EESCHEMA_SETTINGS* eeconfig()
} }
KICAD_T SCH_PAINTER::g_ScaledSelectionTypes[] = { SCH_MARKER_T,
SCH_JUNCTION_T,
SCH_NO_CONNECT_T,
SCH_BUS_WIRE_ENTRY_T,
SCH_BUS_BUS_ENTRY_T,
SCH_LINE_T,
LIB_SHAPE_T, SCH_SHAPE_T,
SCH_BITMAP_T,
SCH_DIRECTIVE_LABEL_T,
LIB_SYMBOL_T, SCH_SYMBOL_T,
SCH_SHEET_T,
LIB_PIN_T, SCH_PIN_T,
EOT };
SCH_RENDER_SETTINGS::SCH_RENDER_SETTINGS() : SCH_RENDER_SETTINGS::SCH_RENDER_SETTINGS() :
m_IsSymbolEditor( false ), m_IsSymbolEditor( false ),
m_ShowUnit( 0 ), m_ShowUnit( 0 ),
@ -248,13 +263,6 @@ bool SCH_PAINTER::Draw( const VIEW_ITEM *aItem, int aLayer )
} }
// Drawing outline fonts, and to a lesser extent stroke fonts and stroke font drop-shadows, is
// expensive. At small effective sizes (ie: zoomed out) the differences between outline and/or
// stroke fonts and the bitmap font becomes immaterial, and there's often more to draw when
// zoomed out so the performance gain becomes more material.
#define BITMAP_FONT_LOD_THRESHOLD 3.5
bool SCH_PAINTER::nonCached( const EDA_ITEM* aItem ) bool SCH_PAINTER::nonCached( const EDA_ITEM* aItem )
{ {
// TODO: it would be nice to have a more definitive test for this, but we've currently got // TODO: it would be nice to have a more definitive test for this, but we've currently got
@ -263,12 +271,6 @@ bool SCH_PAINTER::nonCached( const EDA_ITEM* aItem )
} }
bool SCH_PAINTER::underLODThreshold( int aFontSize )
{
return aFontSize * m_gal->GetWorldScale() < BITMAP_FONT_LOD_THRESHOLD;
}
bool SCH_PAINTER::isUnitAndConversionShown( const LIB_ITEM* aItem ) const bool SCH_PAINTER::isUnitAndConversionShown( const LIB_ITEM* aItem ) const
{ {
if( m_schSettings.m_ShowUnit // showing a specific unit if( m_schSettings.m_ShowUnit // showing a specific unit
@ -428,14 +430,17 @@ float SCH_PAINTER::getLineWidth( const EDA_ITEM* aItem, bool aDrawingShadows ) c
float width = pen; float width = pen;
if( ( aItem->IsBrightened() || aItem->IsSelected() ) && aDrawingShadows ) if( aItem->IsBrightened() || aItem->IsSelected() )
width += getShadowWidth( aItem->IsBrightened() ); {
if( aDrawingShadows && aItem->IsType( g_ScaledSelectionTypes ) )
width += getShadowWidth( aItem->IsBrightened() );
}
return width; return width;
} }
float SCH_PAINTER::getTextThickness( const EDA_ITEM* aItem, bool aDrawingShadows ) const float SCH_PAINTER::getTextThickness( const EDA_ITEM* aItem ) const
{ {
int pen = m_schSettings.GetDefaultPenWidth(); int pen = m_schSettings.GetDefaultPenWidth();
@ -477,12 +482,7 @@ float SCH_PAINTER::getTextThickness( const EDA_ITEM* aItem, bool aDrawingShadows
UNIMPLEMENTED_FOR( aItem->GetClass() ); UNIMPLEMENTED_FOR( aItem->GetClass() );
} }
float width = (float) pen; return (float) pen;
if( ( aItem->IsBrightened() || aItem->IsSelected() ) && aDrawingShadows )
width += getShadowWidth( aItem->IsBrightened() );
return width;
} }
@ -526,10 +526,10 @@ void SCH_PAINTER::strokeText( const wxString& aText, const VECTOR2D& aPosition,
void SCH_PAINTER::bitmapText( const wxString& aText, const VECTOR2D& aPosition, void SCH_PAINTER::bitmapText( const wxString& aText, const VECTOR2D& aPosition,
const TEXT_ATTRIBUTES& aAttrs ) const TEXT_ATTRIBUTES& aAttrs )
{ {
// Bitmap font has different metrics than the stroke font so we compensate a bit before // Bitmap font has different metrics from the stroke font so we compensate a bit before
// stroking // stroking
m_gal->SetGlyphSize( VECTOR2I( aAttrs.m_Size.x * 0.60, aAttrs.m_Size.y * 0.72 ) ); m_gal->SetGlyphSize( VECTOR2I( aAttrs.m_Size.x, aAttrs.m_Size.y * 1.05 ) );
m_gal->SetLineWidth( aAttrs.m_StrokeWidth * 1.2 ); m_gal->SetLineWidth( aAttrs.m_StrokeWidth * 1.35 );
m_gal->SetHorizontalJustify( aAttrs.m_Halign ); m_gal->SetHorizontalJustify( aAttrs.m_Halign );
m_gal->SetVerticalJustify( aAttrs.m_Valign ); m_gal->SetVerticalJustify( aAttrs.m_Valign );
@ -567,17 +567,15 @@ void SCH_PAINTER::boxText( const wxString& aText, const VECTOR2D& aPosition,
case GR_TEXT_V_ALIGN_BOTTOM: box.SetY( box.GetY() - box.GetHeight() ); break; case GR_TEXT_V_ALIGN_BOTTOM: box.SetY( box.GetY() - box.GetHeight() ); break;
} }
// Many fonts draw diacriticals, descenders, etc. outside the X-height of the font. This // Give the highlight a bit of margin.
// will cacth most (but probably not all) of them. box.Inflate( 0, aAttrs.m_StrokeWidth * 2 );
box.Inflate( 0, aAttrs.m_StrokeWidth );
box.Normalize(); // Make h and v sizes always >= 0 box.Normalize(); // Make h and v sizes always >= 0
box = box.GetBoundingBoxRotated( (VECTOR2I) aPosition, aAttrs.m_Angle ); box = box.GetBoundingBoxRotated( (VECTOR2I) aPosition, aAttrs.m_Angle );
box.RevertYAxis(); box.RevertYAxis();
m_gal->SetIsFill( true ); m_gal->SetIsFill( true );
m_gal->SetIsStroke( true ); m_gal->SetIsStroke( false );
m_gal->SetLineWidth( getShadowWidth( false ) );
m_gal->DrawRectangle( mapCoords( box.GetOrigin() ), mapCoords( box.GetEnd() ) ); m_gal->DrawRectangle( mapCoords( box.GetOrigin() ), mapCoords( box.GetEnd() ) );
} }
@ -878,28 +876,25 @@ void SCH_PAINTER::draw( const LIB_FIELD *aField, int aLayer )
m_gal->SetFillColor( color ); m_gal->SetFillColor( color );
EDA_RECT bbox = aField->GetBoundingBox(); EDA_RECT bbox = aField->GetBoundingBox();
VECTOR2I textpos = bbox.Centre();
if( drawingShadows && ( eeconfig()->m_Selection.text_as_box if( drawingShadows )
|| aField->GetDrawFont()->IsOutline()
|| underLODThreshold( aField->GetTextHeight() ) ) )
{ {
m_gal->SetIsStroke( true ); bbox.Inflate( getTextThickness( aField ) * 2 );
m_gal->SetIsStroke( false );
m_gal->SetIsFill( true ); m_gal->SetIsFill( true );
m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
m_gal->DrawRectangle( bbox.GetPosition(), bbox.GetEnd() ); m_gal->DrawRectangle( bbox.GetPosition(), bbox.GetEnd() );
} }
else else
{ {
VECTOR2I textpos = bbox.Centre();
TEXT_ATTRIBUTES attrs( aField->GetAttributes() ); TEXT_ATTRIBUTES attrs( aField->GetAttributes() );
attrs.m_Halign = GR_TEXT_H_ALIGN_CENTER; attrs.m_Halign = GR_TEXT_H_ALIGN_CENTER;
attrs.m_Valign = GR_TEXT_V_ALIGN_CENTER; attrs.m_Valign = GR_TEXT_V_ALIGN_CENTER;
attrs.m_StrokeWidth = getTextThickness( aField, drawingShadows ); attrs.m_StrokeWidth = getTextThickness( aField );
if( nonCached( aField ) && underLODThreshold( aField->GetTextHeight() ) ) strokeText( UnescapeString( aField->GetText() ), textpos, attrs );
bitmapText( UnescapeString( aField->GetText() ), textpos, attrs );
else
strokeText( UnescapeString( aField->GetText() ), textpos, attrs );
} }
// Draw the umbilical line when in the schematic editor // Draw the umbilical line when in the schematic editor
@ -907,7 +902,7 @@ void SCH_PAINTER::draw( const LIB_FIELD *aField, int aLayer )
{ {
m_gal->SetLineWidth( m_schSettings.m_outlineWidth ); m_gal->SetLineWidth( m_schSettings.m_outlineWidth );
m_gal->SetStrokeColor( getRenderColor( aField, LAYER_SCHEMATIC_ANCHOR, drawingShadows ) ); m_gal->SetStrokeColor( getRenderColor( aField, LAYER_SCHEMATIC_ANCHOR, drawingShadows ) );
m_gal->DrawLine( textpos, VECTOR2I( 0, 0 ) ); m_gal->DrawLine( bbox.Centre(), VECTOR2I( 0, 0 ) );
} }
} }
@ -936,28 +931,25 @@ void SCH_PAINTER::draw( const LIB_TEXT* aText, int aLayer )
} }
EDA_RECT bBox = aText->GetBoundingBox(); EDA_RECT bBox = aText->GetBoundingBox();
VECTOR2D pos = bBox.Centre();
m_gal->SetFillColor( color ); m_gal->SetFillColor( color );
m_gal->SetStrokeColor( color ); m_gal->SetStrokeColor( color );
if( drawingShadows && ( eeconfig()->m_Selection.text_as_box if( drawingShadows )
|| aText->GetDrawFont()->IsOutline()
|| underLODThreshold( aText->GetTextHeight() ) ) )
{ {
m_gal->SetIsStroke( true ); bBox.Inflate( getTextThickness( aText ) * 2 );
m_gal->SetIsStroke( false );
m_gal->SetIsFill( true ); m_gal->SetIsFill( true );
m_gal->SetLineWidth( getTextThickness( aText, drawingShadows ) );
m_gal->DrawRectangle( bBox.GetPosition(), bBox.GetEnd() ); m_gal->DrawRectangle( bBox.GetPosition(), bBox.GetEnd() );
return;
} }
else
wxString shownText( aText->GetShownText() );
if( !shownText.IsEmpty() )
{ {
wxString shownText( aText->GetShownText() );
VECTOR2D pos = bBox.Centre();
TEXT_ATTRIBUTES attrs = aText->GetAttributes(); TEXT_ATTRIBUTES attrs = aText->GetAttributes();
attrs.m_StrokeWidth = getTextThickness( aText, drawingShadows );
attrs.m_StrokeWidth = getTextThickness( aText );
if( attrs.m_Angle == ANGLE_VERTICAL ) if( attrs.m_Angle == ANGLE_VERTICAL )
{ {
@ -982,16 +974,7 @@ void SCH_PAINTER::draw( const LIB_TEXT* aText, int aLayer )
// vertically centered. // vertically centered.
attrs.m_Valign = GR_TEXT_V_ALIGN_CENTER; attrs.m_Valign = GR_TEXT_V_ALIGN_CENTER;
if( nonCached( aText ) strokeText( shownText, pos, attrs );
&& underLODThreshold( aText->GetTextHeight() )
&& !shownText.Contains( wxT( "\n" ) ) )
{
bitmapText( shownText, pos, attrs );
}
else
{
strokeText( shownText, pos, attrs );
}
} }
} }
@ -1009,25 +992,19 @@ void SCH_PAINTER::draw( const LIB_TEXTBOX* aTextBox, int aLayer )
if( drawingShadows && !( aTextBox->IsBrightened() || aTextBox->IsSelected() ) ) if( drawingShadows && !( aTextBox->IsBrightened() || aTextBox->IsSelected() ) )
return; return;
COLOR4D color = getRenderColor( aTextBox, aLayer, drawingShadows ); COLOR4D color = getRenderColor( aTextBox, aLayer, drawingShadows );
float borderWidth = getLineWidth( aTextBox, drawingShadows ); float borderWidth = getLineWidth( aTextBox, drawingShadows );
PLOT_DASH_TYPE borderStyle = aTextBox->GetStroke().GetPlotStyle();
wxString shownText = aTextBox->GetShownText();
auto drawText = auto drawText =
[&]() [&]()
{ {
if( !shownText.IsEmpty() ) wxString shownText = aTextBox->GetShownText();
{ TEXT_ATTRIBUTES attrs = aTextBox->GetAttributes();
TEXT_ATTRIBUTES attrs = aTextBox->GetAttributes();
attrs.m_Angle = aTextBox->GetDrawRotation();
attrs.m_StrokeWidth = getTextThickness( aTextBox, drawingShadows );
// Note: don't check LODThreshold for textboxes: the bitmap font may mess attrs.m_Angle = aTextBox->GetDrawRotation();
// up tab positioning. attrs.m_StrokeWidth = getTextThickness( aTextBox );
strokeText( shownText, aTextBox->GetDrawPos(), attrs ); strokeText( shownText, aTextBox->GetDrawPos(), attrs );
}
}; };
m_gal->SetStrokeColor( color ); m_gal->SetStrokeColor( color );
@ -1035,28 +1012,12 @@ void SCH_PAINTER::draw( const LIB_TEXTBOX* aTextBox, int aLayer )
if( aLayer == LAYER_SELECTION_SHADOWS ) if( aLayer == LAYER_SELECTION_SHADOWS )
{ {
if( eeconfig()->m_Selection.fill_shapes m_gal->SetIsFill( true );
|| eeconfig()->m_Selection.text_as_box m_gal->SetIsStroke( false );
|| aTextBox->GetDrawFont()->IsOutline() m_gal->SetLineWidth( borderWidth );
|| underLODThreshold( aTextBox->GetTextHeight() ) )
{
m_gal->SetIsFill( true );
m_gal->SetIsStroke( false );
m_gal->SetLineWidth( borderWidth );
m_gal->DrawRectangle( mapCoords( aTextBox->GetPosition() ), m_gal->DrawRectangle( mapCoords( aTextBox->GetPosition() ),
mapCoords( aTextBox->GetEnd() ) ); mapCoords( aTextBox->GetEnd() ) );
}
else
{
m_gal->SetIsStroke( true );
m_gal->SetIsFill( false );
m_gal->SetLineWidth( borderWidth );
m_gal->DrawRectangle( mapCoords( aTextBox->GetPosition() ),
mapCoords( aTextBox->GetEnd() ) );
drawText();
}
} }
else if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_NOTES_BACKGROUND ) else if( aLayer == LAYER_DEVICE_BACKGROUND || aLayer == LAYER_NOTES_BACKGROUND )
{ {
@ -1076,7 +1037,8 @@ void SCH_PAINTER::draw( const LIB_TEXTBOX* aTextBox, int aLayer )
if( borderWidth > 0 ) if( borderWidth > 0 )
{ {
COLOR4D borderColor = aTextBox->GetStroke().GetColor(); COLOR4D borderColor = aTextBox->GetStroke().GetColor();
PLOT_DASH_TYPE borderStyle = aTextBox->GetStroke().GetPlotStyle();
if( m_schSettings.m_OverrideItemColors || aTextBox->IsBrightened() if( m_schSettings.m_OverrideItemColors || aTextBox->IsBrightened()
|| borderColor == COLOR4D::UNSPECIFIED ) || borderColor == COLOR4D::UNSPECIFIED )
@ -1410,6 +1372,17 @@ void SCH_PAINTER::draw( LIB_PIN *aPin, int aLayer )
text [OUTSIDE] = aPin->GetElectricalTypeName(); text [OUTSIDE] = aPin->GetElectricalTypeName();
} }
// Rendering text is expensive (particularly when using outline fonts). At small effective
// sizes (ie: zoomed out) the visual differences between outline and/or stroke fonts and the
// bitmap font becomes immaterial, and there's often more to draw when zoomed out so the
// performance gain becomes more significant.
#define BITMAP_FONT_SIZE_THRESHOLD 3.5
bool renderTextAsBitmap = size[0] * m_gal->GetWorldScale() < BITMAP_FONT_SIZE_THRESHOLD
&& size[1] * m_gal->GetWorldScale() < BITMAP_FONT_SIZE_THRESHOLD
&& size[2] * m_gal->GetWorldScale() < BITMAP_FONT_SIZE_THRESHOLD
&& size[3] * m_gal->GetWorldScale() < BITMAP_FONT_SIZE_THRESHOLD;
if( !aPin->IsVisible() ) if( !aPin->IsVisible() )
{ {
for( COLOR4D& c : colour ) for( COLOR4D& c : colour )
@ -1450,19 +1423,19 @@ void SCH_PAINTER::draw( LIB_PIN *aPin, int aLayer )
attrs.m_Angle = aAngle; attrs.m_Angle = aAngle;
attrs.m_StrokeWidth = thickness[i]; attrs.m_StrokeWidth = thickness[i];
if( drawingShadows && ( eeconfig()->m_Selection.text_as_box if( drawingShadows )
|| aPin->GetDrawFont()->IsOutline()
|| underLODThreshold( size[i] ) ) )
{ {
boxText( text[i], aPos, attrs ); boxText( text[i], aPos, attrs );
} }
else if( nonCached( aPin ) && underLODThreshold( size[i] ) ) else if( nonCached( aPin ) && renderTextAsBitmap )
{ {
bitmapText( text[i], aPos, attrs ); bitmapText( text[i], aPos, attrs );
const_cast<LIB_PIN*>( aPin )->SetFlags( IS_SHOWN_AS_BITMAP );
} }
else else
{ {
strokeText( text[i], aPos, attrs ); strokeText( text[i], aPos, attrs );
const_cast<LIB_PIN*>( aPin )->SetFlags( IS_SHOWN_AS_BITMAP );
} }
}; };
@ -1864,27 +1837,24 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
m_gal->SetStrokeColor( color ); m_gal->SetStrokeColor( color );
m_gal->SetFillColor( color ); m_gal->SetFillColor( color );
VECTOR2I text_offset = aText->GetSchematicTextOffset( &m_schSettings ); if( drawingShadows )
wxString shownText( aText->GetShownText() );
if( drawingShadows && ( eeconfig()->m_Selection.text_as_box
|| aText->GetDrawFont()->IsOutline()
|| underLODThreshold( aText->GetTextHeight() ) ) )
{ {
EDA_RECT bBox = aText->GetBoundingBox(); EDA_RECT bBox = aText->GetBoundingBox();
bBox.Inflate( getTextThickness( aText ) * 2 );
bBox.RevertYAxis(); bBox.RevertYAxis();
m_gal->SetIsStroke( true );
m_gal->SetIsFill( true );
m_gal->SetLineWidth( getTextThickness( aText, drawingShadows ) );
m_gal->DrawRectangle( mapCoords( bBox.GetPosition() ), mapCoords( bBox.GetEnd() ) );
return;
}
if( !shownText.IsEmpty() ) m_gal->SetIsStroke( false );
m_gal->SetIsFill( true );
m_gal->DrawRectangle( mapCoords( bBox.GetPosition() ), mapCoords( bBox.GetEnd() ) );
}
else
{ {
wxString shownText( aText->GetShownText() );
VECTOR2I text_offset = aText->GetSchematicTextOffset( &m_schSettings );
TEXT_ATTRIBUTES attrs = aText->GetAttributes(); TEXT_ATTRIBUTES attrs = aText->GetAttributes();
attrs.m_Angle = aText->GetDrawRotation(); attrs.m_Angle = aText->GetDrawRotation();
attrs.m_StrokeWidth = getTextThickness( aText, drawingShadows ); attrs.m_StrokeWidth = getTextThickness( aText );
// Adjust text drawn in an outline font to more closely mimic the positioning of // Adjust text drawn in an outline font to more closely mimic the positioning of
// SCH_FIELD text. // SCH_FIELD text.
@ -1900,10 +1870,11 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
} }
if( nonCached( aText ) if( nonCached( aText )
&& underLODThreshold( aText->GetTextHeight() ) && aText->RenderAsBitmap( m_gal->GetWorldScale() )
&& !shownText.Contains( wxT( "\n" ) ) ) && !shownText.Contains( wxT( "\n" ) ) )
{ {
bitmapText( shownText, aText->GetDrawPos() + text_offset, attrs ); bitmapText( shownText, aText->GetDrawPos() + text_offset, attrs );
const_cast<SCH_TEXT*>( aText )->SetFlags( IS_SHOWN_AS_BITMAP );
} }
else else
{ {
@ -1920,6 +1891,8 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
{ {
strokeText( shownText, aText->GetDrawPos() + text_offset, attrs ); strokeText( shownText, aText->GetDrawPos() + text_offset, attrs );
} }
const_cast<SCH_TEXT*>( aText )->ClearFlags( IS_SHOWN_AS_BITMAP );
} }
} }
} }
@ -1927,38 +1900,32 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
void SCH_PAINTER::draw( const SCH_TEXTBOX* aTextBox, int aLayer ) void SCH_PAINTER::draw( const SCH_TEXTBOX* aTextBox, int aLayer )
{ {
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS; bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
COLOR4D color = getRenderColor( aTextBox, aLayer, drawingShadows ); COLOR4D color = getRenderColor( aTextBox, aLayer, drawingShadows );
float borderWidth = getLineWidth( aTextBox, drawingShadows ); float borderWidth = getLineWidth( aTextBox, drawingShadows );
PLOT_DASH_TYPE borderStyle = aTextBox->GetEffectiveLineStyle();
wxString shownText = aTextBox->GetShownText();
auto drawText = auto drawText =
[&]() [&]()
{ {
if( !shownText.IsEmpty() ) wxString shownText = aTextBox->GetShownText();
TEXT_ATTRIBUTES attrs = aTextBox->GetAttributes();
attrs.m_Angle = aTextBox->GetDrawRotation();
attrs.m_StrokeWidth = getTextThickness( aTextBox );
std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
cache = aTextBox->GetRenderCache( shownText );
if( cache )
{ {
TEXT_ATTRIBUTES attrs = aTextBox->GetAttributes(); for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
attrs.m_Angle = aTextBox->GetDrawRotation(); m_gal->DrawGlyph( *glyph.get() );
attrs.m_StrokeWidth = getTextThickness( aTextBox, drawingShadows ); }
else
// Note: don't check LODThreshold for textboxes: the bitmap font may mess {
// up tab positioning. strokeText( shownText, aTextBox->GetDrawPos(), attrs );
}
std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
cache = aTextBox->GetRenderCache( shownText );
if( cache )
{
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
m_gal->DrawGlyph( *glyph.get() );
}
else
{
strokeText( shownText, aTextBox->GetDrawPos(), attrs );
}
}
}; };
if( drawingShadows && !( aTextBox->IsBrightened() || aTextBox->IsSelected() ) ) if( drawingShadows && !( aTextBox->IsBrightened() || aTextBox->IsSelected() ) )
@ -1969,26 +1936,11 @@ void SCH_PAINTER::draw( const SCH_TEXTBOX* aTextBox, int aLayer )
if( aLayer == LAYER_SELECTION_SHADOWS ) if( aLayer == LAYER_SELECTION_SHADOWS )
{ {
if( eeconfig()->m_Selection.fill_shapes m_gal->SetIsFill( true );
|| eeconfig()->m_Selection.text_as_box m_gal->SetIsStroke( false );
|| aTextBox->GetDrawFont()->IsOutline() m_gal->SetLineWidth( borderWidth );
|| underLODThreshold( aTextBox->GetTextHeight() ) )
{
m_gal->SetIsFill( true );
m_gal->SetIsStroke( false );
m_gal->SetLineWidth( borderWidth );
m_gal->DrawRectangle( aTextBox->GetPosition(), aTextBox->GetEnd() ); m_gal->DrawRectangle( aTextBox->GetPosition(), aTextBox->GetEnd() );
}
else
{
m_gal->SetIsStroke( true );
m_gal->SetIsFill( false );
m_gal->SetLineWidth( borderWidth );
m_gal->DrawRectangle( aTextBox->GetPosition(), aTextBox->GetEnd() );
drawText();
}
} }
else if( aLayer == LAYER_NOTES_BACKGROUND ) else if( aLayer == LAYER_NOTES_BACKGROUND )
{ {
@ -2007,7 +1959,8 @@ void SCH_PAINTER::draw( const SCH_TEXTBOX* aTextBox, int aLayer )
if( borderWidth > 0 ) if( borderWidth > 0 )
{ {
COLOR4D borderColor = aTextBox->GetStroke().GetColor(); COLOR4D borderColor = aTextBox->GetStroke().GetColor();
PLOT_DASH_TYPE borderStyle = aTextBox->GetEffectiveLineStyle();
if( m_schSettings.m_OverrideItemColors || aTextBox->IsBrightened() if( m_schSettings.m_OverrideItemColors || aTextBox->IsBrightened()
|| borderColor == COLOR4D::UNSPECIFIED ) || borderColor == COLOR4D::UNSPECIFIED )
@ -2076,7 +2029,7 @@ static void orientSymbol( LIB_SYMBOL* symbol, int orientation )
ORIENT o = orientations[ 0 ]; ORIENT o = orientations[ 0 ];
for( auto& i : orientations ) for( ORIENT& i : orientations )
{ {
if( i.flag == orientation ) if( i.flag == orientation )
{ {
@ -2085,7 +2038,7 @@ static void orientSymbol( LIB_SYMBOL* symbol, int orientation )
} }
} }
for( auto& item : symbol->GetDrawItems() ) for( LIB_ITEM& item : symbol->GetDrawItems() )
{ {
for( int i = 0; i < o.n_rots; i++ ) for( int i = 0; i < o.n_rots; i++ )
item.Rotate( VECTOR2I(0, 0 ), true ); item.Rotate( VECTOR2I(0, 0 ), true );
@ -2138,7 +2091,7 @@ void SCH_PAINTER::draw( SCH_SYMBOL* aSymbol, int aLayer )
for( LIB_ITEM& tempItem : tempSymbol.GetDrawItems() ) for( LIB_ITEM& tempItem : tempSymbol.GetDrawItems() )
{ {
tempItem.SetFlags( aSymbol->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED tempItem.SetFlags( aSymbol->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED,
tempItem.MoveTo( tempItem.GetPosition() + (VECTOR2I) mapCoords( aSymbol->GetPosition() ) ); tempItem.MoveTo( tempItem.GetPosition() + (VECTOR2I) mapCoords( aSymbol->GetPosition() ) );
} }
@ -2149,7 +2102,8 @@ void SCH_PAINTER::draw( SCH_SYMBOL* aSymbol, int aLayer )
LIB_PIN* tempPin = tempPins[ i ]; LIB_PIN* tempPin = tempPins[ i ];
tempPin->ClearFlags(); tempPin->ClearFlags();
tempPin->SetFlags( symbolPin->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED tempPin->SetFlags( symbolPin->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED,
// IS_SHOWN_AS_BITMAP
tempPin->SetName( symbolPin->GetShownName() ); tempPin->SetName( symbolPin->GetShownName() );
tempPin->SetType( symbolPin->GetType() ); tempPin->SetType( symbolPin->GetType() );
@ -2160,6 +2114,16 @@ void SCH_PAINTER::draw( SCH_SYMBOL* aSymbol, int aLayer )
} }
draw( &tempSymbol, aLayer, false, aSymbol->GetUnit(), aSymbol->GetConvert() ); draw( &tempSymbol, aLayer, false, aSymbol->GetUnit(), aSymbol->GetConvert() );
for( unsigned i = 0; i < tempPins.size(); ++i )
{
SCH_PIN* symbolPin = aSymbol->GetPin( originalPins[ i ] );
LIB_PIN* tempPin = tempPins[ i ];
symbolPin->ClearFlags();
symbolPin->SetFlags( tempPin->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED,
// IS_SHOWN_AS_BITMAP
}
} }
@ -2230,34 +2194,33 @@ void SCH_PAINTER::draw( const SCH_FIELD *aField, int aLayer )
bbox.Offset( label->GetSchematicTextOffset( &m_schSettings ) ); bbox.Offset( label->GetSchematicTextOffset( &m_schSettings ) );
} }
VECTOR2I textpos = bbox.Centre();
m_gal->SetStrokeColor( color ); m_gal->SetStrokeColor( color );
m_gal->SetFillColor( color ); m_gal->SetFillColor( color );
if( drawingShadows && ( eeconfig()->m_Selection.text_as_box if( drawingShadows )
|| aField->GetDrawFont()->IsOutline()
|| underLODThreshold( aField->GetTextHeight() ) ) )
{ {
bbox.Inflate( getTextThickness( aField ) * 2 );
bbox.RevertYAxis(); bbox.RevertYAxis();
m_gal->SetIsStroke( true );
m_gal->SetIsStroke( false );
m_gal->SetIsFill( true ); m_gal->SetIsFill( true );
m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
m_gal->DrawRectangle( mapCoords( bbox.GetPosition() ), mapCoords( bbox.GetEnd() ) ); m_gal->DrawRectangle( mapCoords( bbox.GetPosition() ), mapCoords( bbox.GetEnd() ) );
} }
else else
{ {
wxString shownText = aField->GetShownText(); wxString shownText = aField->GetShownText();
VECTOR2I textpos = bbox.Centre();
TEXT_ATTRIBUTES attributes = aField->GetAttributes(); TEXT_ATTRIBUTES attributes = aField->GetAttributes();
attributes.m_Halign = GR_TEXT_H_ALIGN_CENTER; attributes.m_Halign = GR_TEXT_H_ALIGN_CENTER;
attributes.m_Valign = GR_TEXT_V_ALIGN_CENTER; attributes.m_Valign = GR_TEXT_V_ALIGN_CENTER;
attributes.m_StrokeWidth = getTextThickness( aField, drawingShadows ); attributes.m_StrokeWidth = getTextThickness( aField );
attributes.m_Angle = orient; attributes.m_Angle = orient;
if( nonCached( aField ) && underLODThreshold( aField->GetTextHeight() ) ) if( nonCached( aField ) && aField->RenderAsBitmap( m_gal->GetWorldScale() ) )
{ {
bitmapText( shownText, textpos, attributes ); bitmapText( shownText, textpos, attributes );
const_cast<SCH_FIELD*>( aField )->SetFlags( IS_SHOWN_AS_BITMAP );
} }
else else
{ {
@ -2274,6 +2237,8 @@ void SCH_PAINTER::draw( const SCH_FIELD *aField, int aLayer )
{ {
strokeText( shownText, textpos, attributes ); strokeText( shownText, textpos, attributes );
} }
const_cast<SCH_FIELD*>( aField )->ClearFlags( IS_SHOWN_AS_BITMAP );
} }
} }
@ -2284,7 +2249,7 @@ void SCH_PAINTER::draw( const SCH_FIELD *aField, int aLayer )
m_gal->SetLineWidth( m_schSettings.m_outlineWidth ); m_gal->SetLineWidth( m_schSettings.m_outlineWidth );
m_gal->SetStrokeColor( getRenderColor( aField, LAYER_SCHEMATIC_ANCHOR, drawingShadows ) ); m_gal->SetStrokeColor( getRenderColor( aField, LAYER_SCHEMATIC_ANCHOR, drawingShadows ) );
m_gal->DrawLine( textpos, parentPos ); m_gal->DrawLine( bbox.Centre(), parentPos );
} }
} }
@ -2324,7 +2289,7 @@ void SCH_PAINTER::draw( const SCH_GLOBALLABEL *aLabel, int aLayer )
m_gal->SetIsFill( fillBg ); m_gal->SetIsFill( fillBg );
m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) ); m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
m_gal->SetIsStroke( true ); m_gal->SetIsStroke( true );
m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) ); m_gal->SetLineWidth( getTextThickness( aLabel ) );
m_gal->SetStrokeColor( color ); m_gal->SetStrokeColor( color );
m_gal->DrawPolyline( pts2 ); m_gal->DrawPolyline( pts2 );
@ -2392,7 +2357,7 @@ void SCH_PAINTER::draw( const SCH_HIERLABEL *aLabel, int aLayer )
m_gal->SetIsFill( true ); m_gal->SetIsFill( true );
m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) ); m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
m_gal->SetIsStroke( true ); m_gal->SetIsStroke( true );
m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) ); m_gal->SetLineWidth( getTextThickness( aLabel ) );
m_gal->SetStrokeColor( color ); m_gal->SetStrokeColor( color );
m_gal->DrawPolyline( pts2 ); m_gal->DrawPolyline( pts2 );
@ -2440,7 +2405,7 @@ void SCH_PAINTER::draw( const SCH_DIRECTIVE_LABEL *aLabel, int aLayer )
m_gal->SetIsFill( false ); m_gal->SetIsFill( false );
m_gal->SetFillColor( color ); m_gal->SetFillColor( color );
m_gal->SetIsStroke( true ); m_gal->SetIsStroke( true );
m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) ); m_gal->SetLineWidth( getLineWidth( aLabel, drawingShadows ) );
m_gal->SetStrokeColor( color ); m_gal->SetStrokeColor( color );
if( aLabel->GetShape() == LABEL_FLAG_SHAPE::F_DOT ) if( aLabel->GetShape() == LABEL_FLAG_SHAPE::F_DOT )

View File

@ -186,14 +186,12 @@ private:
// Indicates the item is drawn on a non-cached layer in OpenGL // Indicates the item is drawn on a non-cached layer in OpenGL
bool nonCached( const EDA_ITEM* aItem ); bool nonCached( const EDA_ITEM* aItem );
bool underLODThreshold( int aFontSize );
bool isUnitAndConversionShown( const LIB_ITEM* aItem ) const; bool isUnitAndConversionShown( const LIB_ITEM* aItem ) const;
float getShadowWidth( bool aForHighlight ) const; float getShadowWidth( bool aForHighlight ) const;
COLOR4D getRenderColor( const EDA_ITEM* aItem, int aLayer, bool aDrawingShadows ) const; COLOR4D getRenderColor( const EDA_ITEM* aItem, int aLayer, bool aDrawingShadows ) const;
float getLineWidth( const EDA_ITEM* aItem, bool aDrawingShadows ) const; float getLineWidth( const EDA_ITEM* aItem, bool aDrawingShadows ) const;
float getTextThickness( const EDA_ITEM* aItem, bool aDrawingShadows ) const; float getTextThickness( const EDA_ITEM* aItem ) const;
bool setDeviceColors( const LIB_ITEM* aItem, int aLayer ); bool setDeviceColors( const LIB_ITEM* aItem, int aLayer );
@ -205,6 +203,9 @@ private:
void boxText( const wxString& aText, const VECTOR2D& aPosition, void boxText( const wxString& aText, const VECTOR2D& aPosition,
const TEXT_ATTRIBUTES& aAttrs ); const TEXT_ATTRIBUTES& aAttrs );
public:
static KICAD_T g_ScaledSelectionTypes[];
private: private:
SCH_RENDER_SETTINGS m_schSettings; SCH_RENDER_SETTINGS m_schSettings;

View File

@ -28,7 +28,6 @@
#include <core/typeinfo.h> #include <core/typeinfo.h>
#include <memory> #include <memory>
#include <view/view.h> #include <view/view.h>
#include <view/view_group.h>
#include <view/view_rtree.h> #include <view/view_rtree.h>
#include <view/wx_view_controls.h> #include <view/wx_view_controls.h>
#include <drawing_sheet/ds_proxy_view_item.h> #include <drawing_sheet/ds_proxy_view_item.h>
@ -74,9 +73,9 @@ void SCH_VIEW::SetScale( double aScale, VECTOR2D aAnchor )
{ {
VIEW::SetScale( aScale, aAnchor ); VIEW::SetScale( aScale, aAnchor );
//Redraw selection halos since their width is dependent on zoom // Redraw items whose rendering is dependent on zoom
if( m_frame ) if( m_frame )
m_frame->RefreshSelection(); m_frame->RefreshZoomDependentItems();
} }

View File

@ -172,6 +172,18 @@ public:
ClearFlags( GetEditFlags() ); ClearFlags( GetEditFlags() );
} }
virtual bool RenderAsBitmap( double aWorldScale ) const { return false; }
void SetIsShownAsBitmap( bool aBitmap )
{
if( aBitmap )
SetFlags( IS_SHOWN_AS_BITMAP );
else
ClearFlags( IS_SHOWN_AS_BITMAP );
}
inline bool IsShownAsBitmap() const { return m_flags & IS_SHOWN_AS_BITMAP; }
/** /**
* Check whether the item is one of the listed types. * Check whether the item is one of the listed types.
* *

View File

@ -52,8 +52,8 @@
#define SKIP_STRUCT (1 << 15) ///< flag indicating that the structure should be ignored #define SKIP_STRUCT (1 << 15) ///< flag indicating that the structure should be ignored
#define DO_NOT_DRAW (1 << 16) ///< Used to disable draw function #define DO_NOT_DRAW (1 << 16) ///< Used to disable draw function
#define IS_PASTED (1 << 17) ///< Modifier on IS_NEW which indicates it came from clipboard #define IS_PASTED (1 << 17) ///< Modifier on IS_NEW which indicates it came from clipboard
#define UNUSED_1 (1 << 18) #define IS_SHOWN_AS_BITMAP (1 << 18)
#define UNUSED_2 (1 << 19) #define UNUSED_2 (1 << 19)
#define MALFORMED_F_COURTYARD (1 << 20) #define MALFORMED_F_COURTYARD (1 << 20)
#define MALFORMED_B_COURTYARD (1 << 21) #define MALFORMED_B_COURTYARD (1 << 21)
#define MALFORMED_COURTYARDS ( MALFORMED_F_COURTYARD | MALFORMED_B_COURTYARD ) #define MALFORMED_COURTYARDS ( MALFORMED_F_COURTYARD | MALFORMED_B_COURTYARD )