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& 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++ )
{
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;
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
// stroking
attrs.m_Size = VECTOR2I( m_attributes.m_Size.x * 0.83, m_attributes.m_Size.y * 0.86 );
int strokeWidth = GetLineWidth();
attrs.m_StrokeWidth = strokeWidth * 0.8;
attrs.m_Size = VECTOR2I( m_attributes.m_Size.x, m_attributes.m_Size.y * 0.95 );
attrs.m_StrokeWidth = GetLineWidth() * 0.74;
font->Draw( this, aText, aPosition, attrs );
}

View File

@ -2036,13 +2036,13 @@ int OPENGL_GAL::drawBitmapChar( unsigned long aChar )
if( aChar == ' ' )
{
const FONT_GLYPH_TYPE* g = LookupGlyph( 'x' );
wxASSERT( g );
wxCHECK( g, 0 );
if( !g ) // Should not happen.
return 0;
// Match stroke font as well as possible
double spaceWidth = g->advance * 0.74;
Translate( VECTOR2D( g->advance, 0 ) );
return g->advance;
Translate( VECTOR2D( spaceWidth, 0 ) );
return KiROUND( spaceWidth );
}
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_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_checkSelFillShapes->SetValue( cfg->m_Selection.fill_shapes );
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_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.fill_shapes = m_checkSelFillShapes->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/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -68,9 +68,6 @@ PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE::PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE( wxWind
wxStaticBoxSizer* sbSizer3;
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 );
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" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="16" />
<FileVersion major="1" minor="15" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
@ -14,7 +14,6 @@
<property name="file">panel_eeschema_display_options_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">PanelEeschemaDisplayOptions</property>
@ -26,7 +25,6 @@
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">1</property>
<property name="use_microsoft_bom">0</property>
<object class="Panel" expanded="1">
@ -48,7 +46,6 @@
<property name="size">-1,-1</property>
<property name="subclass">RESETTABLE_PANEL; widgets/resettable_panel.h; Not forward_declare</property>
<property name="tooltip"></property>
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
@ -623,70 +620,6 @@
<property name="orient">wxVERTICAL</property>
<property name="parent">1</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">
<property name="border">5</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/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -46,7 +46,6 @@ class PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE : public RESETTABLE_PANEL
wxCheckBox* m_checkShowERCWarnings;
wxCheckBox* m_checkShowERCExclusions;
wxCheckBox* m_checkPageLimits;
wxCheckBox* m_checkSelTextBox;
wxCheckBox* m_checkSelDrawChildItems;
wxCheckBox* m_checkSelFillShapes;
wxStaticText* m_selWidthLabel;
@ -62,7 +61,6 @@ class PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE : public RESETTABLE_PANEL
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();
};

View File

@ -1,7 +1,7 @@
/*
* 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
* 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_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_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, "SelectPinSelectSymbolOpt",
"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, "AnnotateFilterMsg", "annotation.messages_filter" );

View File

@ -1,7 +1,7 @@
/*
* 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
* modify it under the terms of the GNU General Public License
@ -139,7 +139,6 @@ public:
bool draw_selected_children;
bool fill_shapes;
bool select_pin_selects_symbol;
bool text_as_box;
};
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 )
{
EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>();
@ -379,18 +388,13 @@ void SCH_BASE_FRAME::RefreshSelection()
for( EDA_ITEM* item : selection )
{
EDA_ITEM* parent = item->GetParent();
if( item->Type() == SCH_SHEET_PIN_T )
{
// Sheet pins aren't in the view. Refresh their parent.
if( parent )
GetCanvas()->GetView()->Update( parent );
}
else
if( item->RenderAsBitmap( view->GetGAL()->GetWorldScale() ) != item->IsShownAsBitmap()
|| item->IsType( KIGFX::SCH_PAINTER::g_ScaledSelectionTypes ) )
{
view->Update( item, KIGFX::REPAINT );
EDA_ITEM* parent = item->GetParent();
// Symbol children are drawn from their parents. Mark them for re-paint.
if( parent && parent->Type() == SCH_SYMBOL_T )
GetCanvas()->GetView()->Update( parent, KIGFX::REPAINT );

View File

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

View File

@ -39,6 +39,13 @@
#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 */
/* 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
{
wxFAIL_MSG( wxT( "Plot() method not implemented for class " ) + GetClass() );

View File

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

View File

@ -607,7 +607,7 @@ const EDA_RECT SCH_LABEL_BASE::GetBoundingBox() const
{
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 ) );
box.Merge( fieldBBox );
@ -635,7 +635,7 @@ bool SCH_LABEL_BASE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
EDA_RECT fieldBBox = field.GetBoundingBox();
fieldBBox.Inflate( aAccuracy );
if( Type() == SCH_GLOBAL_LABEL_T )
if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
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();
if( Type() == SCH_GLOBAL_LABEL_T )
if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
if( rect.Intersects( fieldBBox ) )
@ -900,6 +900,7 @@ const EDA_RECT SCH_LABEL::GetBodyBoundingBox() const
EDA_RECT rect = GetTextBox();
rect.Offset( 0, -GetTextOffset() );
rect.Inflate( GetEffectiveTextPenWidth() );
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,
std::vector<VECTOR2I>& aPoints,
const VECTOR2I& aPos ) const

View File

@ -235,6 +235,8 @@ public:
int GetPinLength() const { return m_pinLength; }
void SetPinLength( int aLength ) { m_pinLength = aLength; }
int GetPenWidth() const override;
void CreateGraphicShape( const RENDER_SETTINGS* aSettings, std::vector<VECTOR2I>& aPoints,
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() :
m_IsSymbolEditor( false ),
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 )
{
// 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
{
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;
if( ( aItem->IsBrightened() || aItem->IsSelected() ) && aDrawingShadows )
width += getShadowWidth( aItem->IsBrightened() );
if( aItem->IsBrightened() || aItem->IsSelected() )
{
if( aDrawingShadows && aItem->IsType( g_ScaledSelectionTypes ) )
width += getShadowWidth( aItem->IsBrightened() );
}
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();
@ -477,12 +482,7 @@ float SCH_PAINTER::getTextThickness( const EDA_ITEM* aItem, bool aDrawingShadows
UNIMPLEMENTED_FOR( aItem->GetClass() );
}
float width = (float) pen;
if( ( aItem->IsBrightened() || aItem->IsSelected() ) && aDrawingShadows )
width += getShadowWidth( aItem->IsBrightened() );
return width;
return (float) pen;
}
@ -526,10 +526,10 @@ void SCH_PAINTER::strokeText( const wxString& aText, const VECTOR2D& aPosition,
void SCH_PAINTER::bitmapText( const wxString& aText, const VECTOR2D& aPosition,
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
m_gal->SetGlyphSize( VECTOR2I( aAttrs.m_Size.x * 0.60, aAttrs.m_Size.y * 0.72 ) );
m_gal->SetLineWidth( aAttrs.m_StrokeWidth * 1.2 );
m_gal->SetGlyphSize( VECTOR2I( aAttrs.m_Size.x, aAttrs.m_Size.y * 1.05 ) );
m_gal->SetLineWidth( aAttrs.m_StrokeWidth * 1.35 );
m_gal->SetHorizontalJustify( aAttrs.m_Halign );
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;
}
// Many fonts draw diacriticals, descenders, etc. outside the X-height of the font. This
// will cacth most (but probably not all) of them.
box.Inflate( 0, aAttrs.m_StrokeWidth );
// Give the highlight a bit of margin.
box.Inflate( 0, aAttrs.m_StrokeWidth * 2 );
box.Normalize(); // Make h and v sizes always >= 0
box = box.GetBoundingBoxRotated( (VECTOR2I) aPosition, aAttrs.m_Angle );
box.RevertYAxis();
m_gal->SetIsFill( true );
m_gal->SetIsStroke( true );
m_gal->SetLineWidth( getShadowWidth( false ) );
m_gal->SetIsStroke( false );
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 );
EDA_RECT bbox = aField->GetBoundingBox();
VECTOR2I textpos = bbox.Centre();
if( drawingShadows && ( eeconfig()->m_Selection.text_as_box
|| aField->GetDrawFont()->IsOutline()
|| underLODThreshold( aField->GetTextHeight() ) ) )
if( drawingShadows )
{
m_gal->SetIsStroke( true );
bbox.Inflate( getTextThickness( aField ) * 2 );
m_gal->SetIsStroke( false );
m_gal->SetIsFill( true );
m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
m_gal->DrawRectangle( bbox.GetPosition(), bbox.GetEnd() );
}
else
{
VECTOR2I textpos = bbox.Centre();
TEXT_ATTRIBUTES attrs( aField->GetAttributes() );
attrs.m_Halign = GR_TEXT_H_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() ) )
bitmapText( UnescapeString( aField->GetText() ), textpos, attrs );
else
strokeText( UnescapeString( aField->GetText() ), textpos, attrs );
strokeText( UnescapeString( aField->GetText() ), textpos, attrs );
}
// 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->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();
VECTOR2D pos = bBox.Centre();
m_gal->SetFillColor( color );
m_gal->SetStrokeColor( color );
if( drawingShadows && ( eeconfig()->m_Selection.text_as_box
|| aText->GetDrawFont()->IsOutline()
|| underLODThreshold( aText->GetTextHeight() ) ) )
if( drawingShadows )
{
m_gal->SetIsStroke( true );
bBox.Inflate( getTextThickness( aText ) * 2 );
m_gal->SetIsStroke( false );
m_gal->SetIsFill( true );
m_gal->SetLineWidth( getTextThickness( aText, drawingShadows ) );
m_gal->DrawRectangle( bBox.GetPosition(), bBox.GetEnd() );
return;
}
wxString shownText( aText->GetShownText() );
if( !shownText.IsEmpty() )
else
{
wxString shownText( aText->GetShownText() );
VECTOR2D pos = bBox.Centre();
TEXT_ATTRIBUTES attrs = aText->GetAttributes();
attrs.m_StrokeWidth = getTextThickness( aText, drawingShadows );
attrs.m_StrokeWidth = getTextThickness( aText );
if( attrs.m_Angle == ANGLE_VERTICAL )
{
@ -982,16 +974,7 @@ void SCH_PAINTER::draw( const LIB_TEXT* aText, int aLayer )
// vertically centered.
attrs.m_Valign = GR_TEXT_V_ALIGN_CENTER;
if( nonCached( aText )
&& underLODThreshold( aText->GetTextHeight() )
&& !shownText.Contains( wxT( "\n" ) ) )
{
bitmapText( shownText, pos, attrs );
}
else
{
strokeText( shownText, pos, attrs );
}
strokeText( shownText, pos, attrs );
}
}
@ -1009,25 +992,19 @@ void SCH_PAINTER::draw( const LIB_TEXTBOX* aTextBox, int aLayer )
if( drawingShadows && !( aTextBox->IsBrightened() || aTextBox->IsSelected() ) )
return;
COLOR4D color = getRenderColor( aTextBox, aLayer, drawingShadows );
float borderWidth = getLineWidth( aTextBox, drawingShadows );
PLOT_DASH_TYPE borderStyle = aTextBox->GetStroke().GetPlotStyle();
wxString shownText = aTextBox->GetShownText();
COLOR4D color = getRenderColor( aTextBox, aLayer, drawingShadows );
float borderWidth = getLineWidth( aTextBox, drawingShadows );
auto drawText =
[&]()
{
if( !shownText.IsEmpty() )
{
TEXT_ATTRIBUTES attrs = aTextBox->GetAttributes();
attrs.m_Angle = aTextBox->GetDrawRotation();
attrs.m_StrokeWidth = getTextThickness( aTextBox, drawingShadows );
wxString shownText = aTextBox->GetShownText();
TEXT_ATTRIBUTES attrs = aTextBox->GetAttributes();
// Note: don't check LODThreshold for textboxes: the bitmap font may mess
// up tab positioning.
attrs.m_Angle = aTextBox->GetDrawRotation();
attrs.m_StrokeWidth = getTextThickness( aTextBox );
strokeText( shownText, aTextBox->GetDrawPos(), attrs );
}
strokeText( shownText, aTextBox->GetDrawPos(), attrs );
};
m_gal->SetStrokeColor( color );
@ -1035,28 +1012,12 @@ void SCH_PAINTER::draw( const LIB_TEXTBOX* aTextBox, int aLayer )
if( aLayer == LAYER_SELECTION_SHADOWS )
{
if( eeconfig()->m_Selection.fill_shapes
|| eeconfig()->m_Selection.text_as_box
|| aTextBox->GetDrawFont()->IsOutline()
|| underLODThreshold( aTextBox->GetTextHeight() ) )
{
m_gal->SetIsFill( true );
m_gal->SetIsStroke( false );
m_gal->SetLineWidth( borderWidth );
m_gal->SetIsFill( true );
m_gal->SetIsStroke( false );
m_gal->SetLineWidth( borderWidth );
m_gal->DrawRectangle( mapCoords( aTextBox->GetPosition() ),
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();
}
m_gal->DrawRectangle( mapCoords( aTextBox->GetPosition() ),
mapCoords( aTextBox->GetEnd() ) );
}
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 )
{
COLOR4D borderColor = aTextBox->GetStroke().GetColor();
COLOR4D borderColor = aTextBox->GetStroke().GetColor();
PLOT_DASH_TYPE borderStyle = aTextBox->GetStroke().GetPlotStyle();
if( m_schSettings.m_OverrideItemColors || aTextBox->IsBrightened()
|| borderColor == COLOR4D::UNSPECIFIED )
@ -1410,6 +1372,17 @@ void SCH_PAINTER::draw( LIB_PIN *aPin, int aLayer )
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() )
{
for( COLOR4D& c : colour )
@ -1450,19 +1423,19 @@ void SCH_PAINTER::draw( LIB_PIN *aPin, int aLayer )
attrs.m_Angle = aAngle;
attrs.m_StrokeWidth = thickness[i];
if( drawingShadows && ( eeconfig()->m_Selection.text_as_box
|| aPin->GetDrawFont()->IsOutline()
|| underLODThreshold( size[i] ) ) )
if( drawingShadows )
{
boxText( text[i], aPos, attrs );
}
else if( nonCached( aPin ) && underLODThreshold( size[i] ) )
else if( nonCached( aPin ) && renderTextAsBitmap )
{
bitmapText( text[i], aPos, attrs );
const_cast<LIB_PIN*>( aPin )->SetFlags( IS_SHOWN_AS_BITMAP );
}
else
{
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->SetFillColor( color );
VECTOR2I text_offset = aText->GetSchematicTextOffset( &m_schSettings );
wxString shownText( aText->GetShownText() );
if( drawingShadows && ( eeconfig()->m_Selection.text_as_box
|| aText->GetDrawFont()->IsOutline()
|| underLODThreshold( aText->GetTextHeight() ) ) )
if( drawingShadows )
{
EDA_RECT bBox = aText->GetBoundingBox();
bBox.Inflate( getTextThickness( aText ) * 2 );
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();
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
// SCH_FIELD text.
@ -1900,10 +1870,11 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
}
if( nonCached( aText )
&& underLODThreshold( aText->GetTextHeight() )
&& aText->RenderAsBitmap( m_gal->GetWorldScale() )
&& !shownText.Contains( wxT( "\n" ) ) )
{
bitmapText( shownText, aText->GetDrawPos() + text_offset, attrs );
const_cast<SCH_TEXT*>( aText )->SetFlags( IS_SHOWN_AS_BITMAP );
}
else
{
@ -1920,6 +1891,8 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
{
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 )
{
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
COLOR4D color = getRenderColor( aTextBox, aLayer, drawingShadows );
float borderWidth = getLineWidth( aTextBox, drawingShadows );
PLOT_DASH_TYPE borderStyle = aTextBox->GetEffectiveLineStyle();
wxString shownText = aTextBox->GetShownText();
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
COLOR4D color = getRenderColor( aTextBox, aLayer, drawingShadows );
float borderWidth = getLineWidth( aTextBox, drawingShadows );
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();
attrs.m_Angle = aTextBox->GetDrawRotation();
attrs.m_StrokeWidth = getTextThickness( aTextBox, drawingShadows );
// Note: don't check LODThreshold for textboxes: the bitmap font may mess
// up tab positioning.
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 );
}
}
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() ) )
@ -1969,26 +1936,11 @@ void SCH_PAINTER::draw( const SCH_TEXTBOX* aTextBox, int aLayer )
if( aLayer == LAYER_SELECTION_SHADOWS )
{
if( eeconfig()->m_Selection.fill_shapes
|| eeconfig()->m_Selection.text_as_box
|| aTextBox->GetDrawFont()->IsOutline()
|| underLODThreshold( aTextBox->GetTextHeight() ) )
{
m_gal->SetIsFill( true );
m_gal->SetIsStroke( false );
m_gal->SetLineWidth( borderWidth );
m_gal->SetIsFill( true );
m_gal->SetIsStroke( false );
m_gal->SetLineWidth( borderWidth );
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();
}
m_gal->DrawRectangle( aTextBox->GetPosition(), aTextBox->GetEnd() );
}
else if( aLayer == LAYER_NOTES_BACKGROUND )
{
@ -2007,7 +1959,8 @@ void SCH_PAINTER::draw( const SCH_TEXTBOX* aTextBox, int aLayer )
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()
|| borderColor == COLOR4D::UNSPECIFIED )
@ -2076,7 +2029,7 @@ static void orientSymbol( LIB_SYMBOL* symbol, int orientation )
ORIENT o = orientations[ 0 ];
for( auto& i : orientations )
for( ORIENT& i : orientations )
{
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++ )
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() )
{
tempItem.SetFlags( aSymbol->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED
tempItem.SetFlags( aSymbol->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED,
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 ];
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->SetType( symbolPin->GetType() );
@ -2160,6 +2114,16 @@ void SCH_PAINTER::draw( SCH_SYMBOL* aSymbol, int aLayer )
}
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 ) );
}
VECTOR2I textpos = bbox.Centre();
m_gal->SetStrokeColor( color );
m_gal->SetFillColor( color );
if( drawingShadows && ( eeconfig()->m_Selection.text_as_box
|| aField->GetDrawFont()->IsOutline()
|| underLODThreshold( aField->GetTextHeight() ) ) )
if( drawingShadows )
{
bbox.Inflate( getTextThickness( aField ) * 2 );
bbox.RevertYAxis();
m_gal->SetIsStroke( true );
m_gal->SetIsStroke( false );
m_gal->SetIsFill( true );
m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
m_gal->DrawRectangle( mapCoords( bbox.GetPosition() ), mapCoords( bbox.GetEnd() ) );
}
else
{
wxString shownText = aField->GetShownText();
VECTOR2I textpos = bbox.Centre();
TEXT_ATTRIBUTES attributes = aField->GetAttributes();
attributes.m_Halign = GR_TEXT_H_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;
if( nonCached( aField ) && underLODThreshold( aField->GetTextHeight() ) )
if( nonCached( aField ) && aField->RenderAsBitmap( m_gal->GetWorldScale() ) )
{
bitmapText( shownText, textpos, attributes );
const_cast<SCH_FIELD*>( aField )->SetFlags( IS_SHOWN_AS_BITMAP );
}
else
{
@ -2274,6 +2237,8 @@ void SCH_PAINTER::draw( const SCH_FIELD *aField, int aLayer )
{
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->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->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
m_gal->SetIsStroke( true );
m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) );
m_gal->SetLineWidth( getTextThickness( aLabel ) );
m_gal->SetStrokeColor( color );
m_gal->DrawPolyline( pts2 );
@ -2392,7 +2357,7 @@ void SCH_PAINTER::draw( const SCH_HIERLABEL *aLabel, int aLayer )
m_gal->SetIsFill( true );
m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
m_gal->SetIsStroke( true );
m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) );
m_gal->SetLineWidth( getTextThickness( aLabel ) );
m_gal->SetStrokeColor( color );
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->SetFillColor( color );
m_gal->SetIsStroke( true );
m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) );
m_gal->SetLineWidth( getLineWidth( aLabel, drawingShadows ) );
m_gal->SetStrokeColor( color );
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
bool nonCached( const EDA_ITEM* aItem );
bool underLODThreshold( int aFontSize );
bool isUnitAndConversionShown( const LIB_ITEM* aItem ) const;
float getShadowWidth( bool aForHighlight ) const;
COLOR4D getRenderColor( const EDA_ITEM* aItem, int aLayer, 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 );
@ -205,6 +203,9 @@ private:
void boxText( const wxString& aText, const VECTOR2D& aPosition,
const TEXT_ATTRIBUTES& aAttrs );
public:
static KICAD_T g_ScaledSelectionTypes[];
private:
SCH_RENDER_SETTINGS m_schSettings;

View File

@ -28,7 +28,6 @@
#include <core/typeinfo.h>
#include <memory>
#include <view/view.h>
#include <view/view_group.h>
#include <view/view_rtree.h>
#include <view/wx_view_controls.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 );
//Redraw selection halos since their width is dependent on zoom
// Redraw items whose rendering is dependent on zoom
if( m_frame )
m_frame->RefreshSelection();
m_frame->RefreshZoomDependentItems();
}

View File

@ -172,6 +172,18 @@ public:
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.
*

View File

@ -52,8 +52,8 @@
#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 IS_PASTED (1 << 17) ///< Modifier on IS_NEW which indicates it came from clipboard
#define UNUSED_1 (1 << 18)
#define UNUSED_2 (1 << 19)
#define IS_SHOWN_AS_BITMAP (1 << 18)
#define UNUSED_2 (1 << 19)
#define MALFORMED_F_COURTYARD (1 << 20)
#define MALFORMED_B_COURTYARD (1 << 21)
#define MALFORMED_COURTYARDS ( MALFORMED_F_COURTYARD | MALFORMED_B_COURTYARD )