Performance enhancements for fonts.

This commit is contained in:
Jeff Young 2022-01-07 17:42:43 +00:00
parent 438c63f587
commit 04c76f10e9
30 changed files with 582 additions and 470 deletions

View File

@ -303,7 +303,6 @@ set( FONT_SRCS
font/stroke_font.cpp font/stroke_font.cpp
font/outline_font.cpp font/outline_font.cpp
font/outline_decomposer.cpp font/outline_decomposer.cpp
font/triangulate.cpp
font/fontconfig.cpp font/fontconfig.cpp
) )

View File

@ -107,7 +107,8 @@ GR_TEXT_V_ALIGN_T EDA_TEXT::MapVertJustify( int aVertJustify )
EDA_TEXT::EDA_TEXT( const wxString& text ) : EDA_TEXT::EDA_TEXT( const wxString& text ) :
m_text( text ) m_text( text ),
m_bounding_box_cache_valid( false )
{ {
int sz = Mils2iu( DEFAULT_SIZE_TEXT ); int sz = Mils2iu( DEFAULT_SIZE_TEXT );
SetTextSize( wxSize( sz, sz ) ); SetTextSize( wxSize( sz, sz ) );
@ -134,6 +135,9 @@ EDA_TEXT::EDA_TEXT( const EDA_TEXT& aText )
KIFONT::OUTLINE_GLYPH* outline_glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() ); KIFONT::OUTLINE_GLYPH* outline_glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() );
m_render_cache.emplace_back( std::make_unique<KIFONT::OUTLINE_GLYPH>( *outline_glyph ) ); m_render_cache.emplace_back( std::make_unique<KIFONT::OUTLINE_GLYPH>( *outline_glyph ) );
} }
m_bounding_box_cache_valid = aText.m_bounding_box_cache_valid;
m_bounding_box_cache = aText.m_bounding_box_cache;
} }
@ -162,6 +166,9 @@ EDA_TEXT& EDA_TEXT::operator=( const EDA_TEXT& aText )
m_render_cache.emplace_back( std::make_unique<KIFONT::OUTLINE_GLYPH>( *outline_glyph ) ); m_render_cache.emplace_back( std::make_unique<KIFONT::OUTLINE_GLYPH>( *outline_glyph ) );
} }
m_bounding_box_cache_valid = aText.m_bounding_box_cache_valid;
m_bounding_box_cache = aText.m_bounding_box_cache;
return *this; return *this;
} }
@ -169,7 +176,11 @@ EDA_TEXT& EDA_TEXT::operator=( const EDA_TEXT& aText )
void EDA_TEXT::SetText( const wxString& aText ) void EDA_TEXT::SetText( const wxString& aText )
{ {
m_text = aText; m_text = aText;
cacheShownText(); cacheShownText();
ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
@ -179,77 +190,87 @@ void EDA_TEXT::CopyText( const EDA_TEXT& aSrc )
m_shown_text = aSrc.m_shown_text; m_shown_text = aSrc.m_shown_text;
m_shown_text_has_text_var_refs = aSrc.m_shown_text_has_text_var_refs; m_shown_text_has_text_var_refs = aSrc.m_shown_text_has_text_var_refs;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
void EDA_TEXT::SetTextThickness( int aWidth ) void EDA_TEXT::SetTextThickness( int aWidth )
{ {
m_attributes.m_StrokeWidth = aWidth; m_attributes.m_StrokeWidth = aWidth;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
void EDA_TEXT::SetTextAngle( const EDA_ANGLE& aAngle ) void EDA_TEXT::SetTextAngle( const EDA_ANGLE& aAngle )
{ {
m_attributes.m_Angle = aAngle; m_attributes.m_Angle = aAngle;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
void EDA_TEXT::SetItalic( bool aItalic ) void EDA_TEXT::SetItalic( bool aItalic )
{ {
m_attributes.m_Italic = aItalic; m_attributes.m_Italic = aItalic;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
void EDA_TEXT::SetBold( bool aBold ) void EDA_TEXT::SetBold( bool aBold )
{ {
m_attributes.m_Bold = aBold; m_attributes.m_Bold = aBold;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
void EDA_TEXT::SetVisible( bool aVisible ) void EDA_TEXT::SetVisible( bool aVisible )
{ {
m_attributes.m_Visible = aVisible; m_attributes.m_Visible = aVisible;
m_render_cache.clear(); ClearRenderCache();
} }
void EDA_TEXT::SetMirrored( bool isMirrored ) void EDA_TEXT::SetMirrored( bool isMirrored )
{ {
m_attributes.m_Mirrored = isMirrored; m_attributes.m_Mirrored = isMirrored;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
void EDA_TEXT::SetMultilineAllowed( bool aAllow ) void EDA_TEXT::SetMultilineAllowed( bool aAllow )
{ {
m_attributes.m_Multiline = aAllow; m_attributes.m_Multiline = aAllow;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
void EDA_TEXT::SetHorizJustify( GR_TEXT_H_ALIGN_T aType ) void EDA_TEXT::SetHorizJustify( GR_TEXT_H_ALIGN_T aType )
{ {
m_attributes.m_Halign = aType; m_attributes.m_Halign = aType;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
void EDA_TEXT::SetVertJustify( GR_TEXT_V_ALIGN_T aType ) void EDA_TEXT::SetVertJustify( GR_TEXT_V_ALIGN_T aType )
{ {
m_attributes.m_Valign = aType; m_attributes.m_Valign = aType;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
void EDA_TEXT::SetKeepUpright( bool aKeepUpright ) void EDA_TEXT::SetKeepUpright( bool aKeepUpright )
{ {
m_attributes.m_KeepUpright = aKeepUpright; m_attributes.m_KeepUpright = aKeepUpright;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
@ -257,7 +278,8 @@ void EDA_TEXT::SetAttributes( const EDA_TEXT& aSrc )
{ {
m_attributes = aSrc.m_attributes; m_attributes = aSrc.m_attributes;
m_pos = aSrc.m_pos; m_pos = aSrc.m_pos;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
@ -267,7 +289,8 @@ void EDA_TEXT::SwapText( EDA_TEXT& aTradingPartner )
std::swap( m_shown_text, aTradingPartner.m_shown_text ); std::swap( m_shown_text, aTradingPartner.m_shown_text );
std::swap( m_shown_text_has_text_var_refs, aTradingPartner.m_shown_text_has_text_var_refs ); std::swap( m_shown_text_has_text_var_refs, aTradingPartner.m_shown_text_has_text_var_refs );
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
@ -276,7 +299,11 @@ void EDA_TEXT::SwapAttributes( EDA_TEXT& aTradingPartner )
std::swap( m_attributes, aTradingPartner.m_attributes ); std::swap( m_attributes, aTradingPartner.m_attributes );
std::swap( m_pos, aTradingPartner.m_pos ); std::swap( m_pos, aTradingPartner.m_pos );
m_render_cache.clear(); ClearRenderCache();
aTradingPartner.ClearRenderCache();
m_bounding_box_cache_valid = false;
aTradingPartner.m_bounding_box_cache_valid = false;
} }
@ -304,8 +331,12 @@ int EDA_TEXT::GetEffectiveTextPenWidth( int aDefaultWidth ) const
bool EDA_TEXT::Replace( const wxFindReplaceData& aSearchData ) bool EDA_TEXT::Replace( const wxFindReplaceData& aSearchData )
{ {
bool retval = EDA_ITEM::Replace( aSearchData, m_text ); bool retval = EDA_ITEM::Replace( aSearchData, m_text );
cacheShownText(); cacheShownText();
ClearRenderCache();
m_bounding_box_cache_valid = false;
return retval; return retval;
} }
@ -313,35 +344,40 @@ bool EDA_TEXT::Replace( const wxFindReplaceData& aSearchData )
void EDA_TEXT::SetFont( KIFONT::FONT* aFont ) void EDA_TEXT::SetFont( KIFONT::FONT* aFont )
{ {
m_attributes.m_Font = aFont; m_attributes.m_Font = aFont;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
void EDA_TEXT::SetLineSpacing( double aLineSpacing ) void EDA_TEXT::SetLineSpacing( double aLineSpacing )
{ {
m_attributes.m_LineSpacing = aLineSpacing; m_attributes.m_LineSpacing = aLineSpacing;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
void EDA_TEXT::SetTextSize( const wxSize& aNewSize ) void EDA_TEXT::SetTextSize( const wxSize& aNewSize )
{ {
m_attributes.m_Size = aNewSize; m_attributes.m_Size = aNewSize;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
void EDA_TEXT::SetTextWidth( int aWidth ) void EDA_TEXT::SetTextWidth( int aWidth )
{ {
m_attributes.m_Size.x = aWidth; m_attributes.m_Size.x = aWidth;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
void EDA_TEXT::SetTextHeight( int aHeight ) void EDA_TEXT::SetTextHeight( int aHeight )
{ {
m_attributes.m_Size.y = aHeight; m_attributes.m_Size.y = aHeight;
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
@ -368,17 +404,17 @@ void EDA_TEXT::Offset( const VECTOR2I& aOffset )
m_pos += aOffset; m_pos += aOffset;
for( std::unique_ptr<KIFONT::GLYPH>& glyph : m_render_cache ) for( std::unique_ptr<KIFONT::GLYPH>& glyph : m_render_cache )
{ static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() )->Move( aOffset );
KIFONT::OUTLINE_GLYPH* outline_glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() );
outline_glyph->Move( aOffset ); m_bounding_box_cache.Move( aOffset );
}
} }
void EDA_TEXT::Empty() void EDA_TEXT::Empty()
{ {
m_text.Empty(); m_text.Empty();
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
@ -395,7 +431,8 @@ void EDA_TEXT::cacheShownText()
m_shown_text_has_text_var_refs = m_shown_text.Contains( wxT( "${" ) ); m_shown_text_has_text_var_refs = m_shown_text.Contains( wxT( "${" ) );
} }
m_render_cache.clear(); ClearRenderCache();
m_bounding_box_cache_valid = false;
} }
@ -410,6 +447,19 @@ KIFONT::FONT* EDA_TEXT::GetDrawFont() const
} }
void EDA_TEXT::ClearRenderCache()
{
m_render_cache.clear();
}
void EDA_TEXT::ClearBoundingBoxCache()
{
m_bounding_box_cache_valid = false;
}
std::vector<std::unique_ptr<KIFONT::GLYPH>>* std::vector<std::unique_ptr<KIFONT::GLYPH>>*
EDA_TEXT::GetRenderCache( const wxString& forResolvedText ) const EDA_TEXT::GetRenderCache( const wxString& forResolvedText ) const
{ {
@ -424,7 +474,7 @@ EDA_TEXT::GetRenderCache( const wxString& forResolvedText ) const
m_render_cache.clear(); m_render_cache.clear();
KIFONT::OUTLINE_FONT* font = static_cast<KIFONT::OUTLINE_FONT*>( GetFont() ); KIFONT::OUTLINE_FONT* font = static_cast<KIFONT::OUTLINE_FONT*>( GetFont() );
font->GetLinesAsGlyphs( m_render_cache, this ); font->GetLinesAsGlyphs( &m_render_cache, this );
m_render_cache_angle = resolvedAngle; m_render_cache_angle = resolvedAngle;
m_render_cache_text = forResolvedText; m_render_cache_text = forResolvedText;
@ -474,6 +524,9 @@ int EDA_TEXT::GetInterline() const
EDA_RECT EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const EDA_RECT EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
{ {
if( m_bounding_box_cache_valid && aLine < 0 && !aInvertY )
return m_bounding_box_cache;
EDA_RECT rect; EDA_RECT rect;
wxArrayString strings; wxArrayString strings;
wxString text = GetShownText(); wxString text = GetShownText();
@ -498,8 +551,7 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
double penWidth( thickness ); double penWidth( thickness );
bool bold = IsBold(); bool bold = IsBold();
bool italic = IsItalic(); bool italic = IsItalic();
VECTOR2D extents = font->StringBoundaryLimits( text, fontSize, penWidth, bold, italic ); int dx = font->StringBoundaryLimits( text, fontSize, penWidth, bold, italic ).x;
int dx = KiROUND( extents.x );
int dy = GetInterline(); int dy = GetInterline();
// Creates bounding box (rectangle) for horizontal, left and top justified text. The // Creates bounding box (rectangle) for horizontal, left and top justified text. The
@ -521,7 +573,7 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
for( unsigned ii = 1; ii < strings.GetCount(); ii++ ) for( unsigned ii = 1; ii < strings.GetCount(); ii++ )
{ {
text = strings.Item( ii ); text = strings.Item( ii );
dx = KiROUND( font->StringBoundaryLimits( text, fontSize, penWidth, bold, italic ).x ); dx = font->StringBoundaryLimits( text, fontSize, penWidth, bold, italic ).x;
textsize.x = std::max( textsize.x, dx ); textsize.x = std::max( textsize.x, dx );
textsize.y += dy; textsize.y += dy;
} }
@ -561,6 +613,12 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
rect.Normalize(); // Make h and v sizes always >= 0 rect.Normalize(); // Make h and v sizes always >= 0
if( aLine < 0 && !aInvertY )
{
m_bounding_box_cache_valid = true;
m_bounding_box_cache = rect;
}
return rect; return rect;
} }
@ -797,25 +855,18 @@ std::shared_ptr<SHAPE_COMPOUND> EDA_TEXT::GetEffectiveTextShape( ) const
{ {
KIFONT::OUTLINE_GLYPH* glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( baseGlyph.get() ); KIFONT::OUTLINE_GLYPH* glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( baseGlyph.get() );
glyph->CacheTriangulation(); glyph->Triangulate(
[&]( int aPolygonIndex, const VECTOR2D& aVertex1, const VECTOR2D& aVertex2,
for( unsigned int ii = 0; ii < glyph->TriangulatedPolyCount(); ++ii ) const VECTOR2D& aVertex3 )
{ {
const SHAPE_POLY_SET::TRIANGULATED_POLYGON* tri = glyph->TriangulatedPolygon( ii );
for( size_t jj = 0; jj < tri->GetTriangleCount(); ++jj )
{
VECTOR2I a, b, c;
tri->GetTriangle( jj, a, b, c );
SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE; SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
triShape->Append( a ); triShape->Append( aVertex1 );
triShape->Append( b ); triShape->Append( aVertex2 );
triShape->Append( c ); triShape->Append( aVertex3 );
shape->AddShape( triShape ); shape->AddShape( triShape );
} } );
}
} }
} }
else else

View File

@ -104,72 +104,9 @@ bool FONT::IsStroke( const wxString& aFontName )
} }
/**
* Draw a string.
*
* @param aGal
* @param aTextItem is the underlying text item
* @param aPosition is the text position
* @return bounding box width/height
*/
VECTOR2D FONT::doDrawString( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition,
bool aParse, const TEXT_ATTRIBUTES& aAttrs ) const
{
if( aText.empty() )
return VECTOR2D( 0.0, 0.0 );
wxArrayString strings;
std::vector<VECTOR2I> positions;
VECTOR2D boundingBox;
std::vector<VECTOR2D> lineBoundingBoxes;
getLinePositions( aText, aPosition, strings, positions, lineBoundingBoxes, aAttrs );
for( size_t i = 0; i < strings.GetCount(); i++ )
{
VECTOR2D lineBoundingBox;
if( aParse )
{
MARKUP::MARKUP_PARSER markupParser( std::string( strings.Item( i ) ) );
//auto parse_result = markupParser.Parse();
VECTOR2I cursor = positions[i];
std::function<void( const std::unique_ptr<MARKUP::NODE>& )> nodeHandler =
[&]( const std::unique_ptr<MARKUP::NODE>& aNode )
{
if( !aNode->is_root() && aNode->has_content() )
{
VECTOR2D itemBoundingBox = Draw( aGal, aNode->string(), cursor,
aPosition, aAttrs );
lineBoundingBox += itemBoundingBox;
cursor += itemBoundingBox;
}
for( const auto& child : aNode->children )
nodeHandler( child );
};
nodeHandler( markupParser.Parse() );
}
else
{
lineBoundingBox = Draw( aGal, strings.Item( i ), positions[i], aPosition, aAttrs );
}
boundingBox.x = fmax( boundingBox.x, lineBoundingBox.x );
}
boundingBox.y = ( strings.GetCount() + 1 ) * GetInterline( aAttrs.m_Size.y );
return boundingBox;
}
void FONT::getLinePositions( const UTF8& aText, const VECTOR2I& aPosition, void FONT::getLinePositions( const UTF8& aText, const VECTOR2I& aPosition,
wxArrayString& aTextLines, std::vector<VECTOR2I>& aPositions, wxArrayString& aTextLines, std::vector<VECTOR2I>& aPositions,
std::vector<VECTOR2D>& aBoundingBoxes, std::vector<VECTOR2I>& aExtents, const TEXT_ATTRIBUTES& aAttrs ) const
const TEXT_ATTRIBUTES& aAttrs ) const
{ {
wxStringSplit( aText, aTextLines, '\n' ); wxStringSplit( aText, aTextLines, '\n' );
int lineCount = aTextLines.Count(); int lineCount = aTextLines.Count();
@ -180,12 +117,12 @@ void FONT::getLinePositions( const UTF8& aText, const VECTOR2I& aPosition,
for( int i = 0; i < lineCount; i++ ) for( int i = 0; i < lineCount; i++ )
{ {
VECTOR2D pos( aPosition.x, aPosition.y + i * interline ); VECTOR2I pos( aPosition.x, aPosition.y + i * interline );
VECTOR2D end = boundingBoxSingleLine( nullptr, aTextLines[i], pos, aAttrs.m_Size, VECTOR2I end = boundingBoxSingleLine( nullptr, aTextLines[i], pos, aAttrs.m_Size,
aAttrs.m_Italic ); aAttrs.m_Italic );
VECTOR2D bBox( end - pos ); VECTOR2I bBox( end - pos );
aBoundingBoxes.push_back( bBox ); aExtents.push_back( bBox );
if( i == 0 ) if( i == 0 )
height += aAttrs.m_Size.y; height += aAttrs.m_Size.y;
@ -205,7 +142,7 @@ void FONT::getLinePositions( const UTF8& aText, const VECTOR2I& aPosition,
for( int i = 0; i < lineCount; i++ ) for( int i = 0; i < lineCount; i++ )
{ {
VECTOR2I lineSize = aBoundingBoxes.at( i ); VECTOR2I lineSize = aExtents.at( i );
wxPoint lineOffset( offset ); wxPoint lineOffset( offset );
lineOffset.y += i * interline; lineOffset.y += i * interline;
@ -247,46 +184,35 @@ void FONT::DrawText( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosit
* object, such as a run of superscript characters) * object, such as a run of superscript characters)
* @param aAttrs are the styling attributes of the text, including its rotation * @param aAttrs are the styling attributes of the text, including its rotation
*/ */
VECTOR2D FONT::Draw( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition, void FONT::Draw( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition,
const VECTOR2I& aCursor, const TEXT_ATTRIBUTES& aAttrs ) const const VECTOR2I& aCursor, const TEXT_ATTRIBUTES& aAttrs ) const
{ {
if( !aGal || aText.empty() ) if( !aGal || aText.empty() )
return VECTOR2D( 0, 0 ); return;
VECTOR2D position( aPosition - aCursor ); VECTOR2I position( aPosition - aCursor );
// Split multiline strings into separate ones and draw them line by line // Split multiline strings into separate ones and draw them line by line
wxArrayString strings_list; wxArrayString strings_list;
std::vector<VECTOR2I> positions; std::vector<VECTOR2I> positions;
std::vector<VECTOR2D> boundingBoxes; std::vector<VECTOR2I> extents;
getLinePositions( aText, position, strings_list, positions, boundingBoxes, aAttrs ); getLinePositions( aText, position, strings_list, positions, extents, aAttrs );
VECTOR2D boundingBox( 0, 0 );
BOX2I lineBoundingBox;
aGal->SetLineWidth( aAttrs.m_StrokeWidth ); aGal->SetLineWidth( aAttrs.m_StrokeWidth );
for( size_t i = 0; i < strings_list.GetCount(); i++ ) for( size_t i = 0; i < strings_list.GetCount(); i++ )
{ {
(void) drawSingleLineText( aGal, &lineBoundingBox, strings_list[i], positions[i], drawSingleLineText( aGal, nullptr, strings_list[i], positions[i], aAttrs.m_Size,
aAttrs.m_Size, aAttrs.m_Angle, aAttrs.m_Mirrored, aPosition, aAttrs.m_Angle, aAttrs.m_Mirrored, aPosition, aAttrs.m_Italic );
aAttrs.m_Italic );
// expand bounding box of whole text
boundingBox.x = std::max( boundingBox.x, (double) lineBoundingBox.GetWidth() );
double lineHeight = GetInterline( aAttrs.m_Size.y, aAttrs.m_LineSpacing );
boundingBox.y += lineHeight;
} }
return boundingBox;
} }
/** /**
* @return position of cursor for drawing next substring * @return position of cursor for drawing next substring
*/ */
VECTOR2D drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>& aGlyphs, VECTOR2I drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
const std::unique_ptr<MARKUP::NODE>& aNode, const VECTOR2I& aPosition, const std::unique_ptr<MARKUP::NODE>& aNode, const VECTOR2I& aPosition,
const KIFONT::FONT* aFont, const VECTOR2D& aSize, const EDA_ANGLE& aAngle, const KIFONT::FONT* aFont, const VECTOR2D& aSize, const EDA_ANGLE& aAngle,
bool aMirror, const VECTOR2I& aOrigin, TEXT_STYLE_FLAGS aTextStyle ) bool aMirror, const VECTOR2I& aOrigin, TEXT_STYLE_FLAGS aTextStyle )
@ -328,7 +254,7 @@ VECTOR2D drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>& a
} }
VECTOR2D FONT::drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>& aGlyphs, VECTOR2I FONT::drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
const UTF8& aText, const VECTOR2I& aPosition, const VECTOR2D& aSize, const UTF8& aText, const VECTOR2I& aPosition, const VECTOR2D& aSize,
const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin, const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
TEXT_STYLE_FLAGS aTextStyle ) const TEXT_STYLE_FLAGS aTextStyle ) const
@ -341,16 +267,13 @@ VECTOR2D FONT::drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYP
} }
VECTOR2D FONT::drawSingleLineText( KIGFX::GAL* aGal, BOX2I* aBoundingBox, const UTF8& aText, void FONT::drawSingleLineText( KIGFX::GAL* aGal, BOX2I* aBoundingBox, const UTF8& aText,
const VECTOR2I& aPosition, const VECTOR2D& aSize, const VECTOR2I& aPosition, const VECTOR2D& aSize,
const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin, const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
bool aItalic ) const bool aItalic ) const
{ {
if( !aGal ) if( !aGal )
{ return;
// do nothing, cursor does not move
return aPosition;
}
TEXT_STYLE_FLAGS textStyle = 0; TEXT_STYLE_FLAGS textStyle = 0;
@ -358,21 +281,19 @@ VECTOR2D FONT::drawSingleLineText( KIGFX::GAL* aGal, BOX2I* aBoundingBox, const
textStyle |= TEXT_STYLE::ITALIC; textStyle |= TEXT_STYLE::ITALIC;
std::vector<std::unique_ptr<GLYPH>> glyphs; std::vector<std::unique_ptr<GLYPH>> glyphs;
VECTOR2D nextPosition = drawMarkup( aBoundingBox, glyphs, aText, aPosition, aSize, aAngle,
aMirror, aOrigin, textStyle ); (void) drawMarkup( aBoundingBox, &glyphs, aText, aPosition, aSize, aAngle, aMirror, aOrigin,
textStyle );
for( const std::unique_ptr<GLYPH>& glyph : glyphs ) for( const std::unique_ptr<GLYPH>& glyph : glyphs )
aGal->DrawGlyph( *glyph.get() ); aGal->DrawGlyph( *glyph.get() );
return nextPosition;
} }
VECTOR2D FONT::StringBoundaryLimits( const UTF8& aText, const VECTOR2D& aSize, int aThickness, VECTOR2I FONT::StringBoundaryLimits( const UTF8& aText, const VECTOR2D& aSize, int aThickness,
bool aBold, bool aItalic ) const bool aBold, bool aItalic ) const
{ {
// TODO do we need to parse every time - have we already parsed? // TODO do we need to parse every time - have we already parsed?
std::vector<std::unique_ptr<GLYPH>> glyphs; // ignored
BOX2I boundingBox; BOX2I boundingBox;
TEXT_STYLE_FLAGS textStyle = 0; TEXT_STYLE_FLAGS textStyle = 0;
@ -382,8 +303,8 @@ VECTOR2D FONT::StringBoundaryLimits( const UTF8& aText, const VECTOR2D& aSize, i
if( aItalic ) if( aItalic )
textStyle |= TEXT_STYLE::ITALIC; textStyle |= TEXT_STYLE::ITALIC;
(void) drawMarkup( &boundingBox, glyphs, aText, VECTOR2D(), aSize, EDA_ANGLE::ANGLE_0, (void) drawMarkup( &boundingBox, nullptr, aText, VECTOR2I(), aSize, EDA_ANGLE::ANGLE_0, false,
false, VECTOR2D(), textStyle ); VECTOR2I(), textStyle );
if( IsStroke() ) if( IsStroke() )
{ {
@ -399,18 +320,16 @@ VECTOR2D FONT::StringBoundaryLimits( const UTF8& aText, const VECTOR2D& aSize, i
} }
VECTOR2D FONT::boundingBoxSingleLine( BOX2I* aBoundingBox, const UTF8& aText, VECTOR2I FONT::boundingBoxSingleLine( BOX2I* aBBox, const UTF8& aText, const VECTOR2I& aPosition,
const VECTOR2I& aPosition, const VECTOR2D& aSize, const VECTOR2D& aSize, bool aItalic ) const
bool aItalic ) const
{ {
TEXT_STYLE_FLAGS textStyle = 0; TEXT_STYLE_FLAGS textStyle = 0;
if( aItalic ) if( aItalic )
textStyle |= TEXT_STYLE::ITALIC; textStyle |= TEXT_STYLE::ITALIC;
std::vector<std::unique_ptr<GLYPH>> glyphs; // ignored VECTOR2I extents = drawMarkup( aBBox, nullptr, aText, aPosition, aSize, EDA_ANGLE::ANGLE_0,
VECTOR2D nextPosition = drawMarkup( aBoundingBox, glyphs, aText, aPosition, aSize, false, VECTOR2I(), textStyle );
EDA_ANGLE::ANGLE_0, false, VECTOR2I(), textStyle );
return nextPosition; return extents;
} }

View File

@ -108,3 +108,23 @@ BOX2D OUTLINE_GLYPH::BoundingBox()
BOX2I bbox = BBox(); BOX2I bbox = BBox();
return BOX2D( bbox.GetOrigin(), bbox.GetSize() ); return BOX2D( bbox.GetOrigin(), bbox.GetSize() );
} }
void OUTLINE_GLYPH::Triangulate( TRIANGULATE_CALLBACK aCallback ) const
{
const_cast<OUTLINE_GLYPH*>( this )->CacheTriangulation();
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++ )
{
VECTOR2I a, b, c;
polygon->GetTriangle( j, a, b, c );
aCallback( i, a, b, c );
}
}
}

View File

@ -227,35 +227,43 @@ BOX2I OUTLINE_FONT::getBoundingBox( const std::vector<std::unique_ptr<GLYPH>>& a
} }
VECTOR2I OUTLINE_FONT::GetLinesAsGlyphs( std::vector<std::unique_ptr<GLYPH>>& aGlyphs, void OUTLINE_FONT::GetLinesAsGlyphs( std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
const EDA_TEXT* aText ) const const EDA_TEXT* aText ) const
{ {
wxArrayString strings; wxArrayString strings;
std::vector<VECTOR2I> positions; std::vector<VECTOR2I> positions;
VECTOR2I ret; std::vector<VECTOR2I> extents;
std::vector<VECTOR2D> boundingBoxes;
TEXT_ATTRIBUTES attrs = aText->GetAttributes(); TEXT_ATTRIBUTES attrs = aText->GetAttributes();
TEXT_STYLE_FLAGS textStyle = 0;
attrs.m_Angle = aText->GetDrawRotation(); attrs.m_Angle = aText->GetDrawRotation();
if( aText->IsItalic() ) return GetLinesAsGlyphs( aGlyphs, aText->GetShownText(), aText->GetTextPos(), attrs );
}
void OUTLINE_FONT::GetLinesAsGlyphs( std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
const UTF8& aText, const VECTOR2I& aPosition,
const TEXT_ATTRIBUTES& aAttrs ) const
{
wxArrayString strings;
std::vector<VECTOR2I> positions;
std::vector<VECTOR2I> extents;
TEXT_STYLE_FLAGS textStyle = 0;
if( aAttrs.m_Italic )
textStyle |= TEXT_STYLE::ITALIC; textStyle |= TEXT_STYLE::ITALIC;
getLinePositions( aText->GetShownText(), aText->GetTextPos(), strings, positions, boundingBoxes, getLinePositions( aText, aPosition, strings, positions, extents, aAttrs );
attrs );
for( size_t i = 0; i < strings.GetCount(); i++ ) for( size_t i = 0; i < strings.GetCount(); i++ )
{ {
ret = drawMarkup( nullptr, aGlyphs, UTF8( strings.Item( i ) ), positions[i], attrs.m_Size, (void) drawMarkup( nullptr, aGlyphs, UTF8( strings.Item( i ) ), positions[i],
attrs.m_Angle, attrs.m_Mirrored, aText->GetTextPos(), textStyle ); aAttrs.m_Size, aAttrs.m_Angle, aAttrs.m_Mirrored, aPosition, textStyle );
} }
return ret;
} }
VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr<GLYPH>>& aGlyphs, VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
const UTF8& aText, const VECTOR2D& aSize, const UTF8& aText, const VECTOR2D& aSize,
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle, const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
bool aMirror, const VECTOR2I& aOrigin, bool aMirror, const VECTOR2I& aOrigin,
@ -294,6 +302,8 @@ VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
hb_glyph_position_t& pos = glyphPos[i]; hb_glyph_position_t& pos = glyphPos[i];
int codepoint = glyphInfo[i].codepoint; int codepoint = glyphInfo[i].codepoint;
if( aGlyphs )
{
FT_Load_Glyph( face, codepoint, FT_LOAD_NO_BITMAP ); FT_Load_Glyph( face, codepoint, FT_LOAD_NO_BITMAP );
FT_GlyphSlot faceGlyph = face->glyph; FT_GlyphSlot faceGlyph = face->glyph;
@ -308,7 +318,6 @@ VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
std::unique_ptr<OUTLINE_GLYPH> glyph = std::make_unique<OUTLINE_GLYPH>(); std::unique_ptr<OUTLINE_GLYPH> glyph = std::make_unique<OUTLINE_GLYPH>();
std::vector<SHAPE_LINE_CHAIN> holes; std::vector<SHAPE_LINE_CHAIN> holes;
std::vector<SHAPE_LINE_CHAIN> outlines;
for( CONTOUR& c : contours ) for( CONTOUR& c : contours )
{ {
@ -346,52 +355,35 @@ VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
if( contourIsHole( c ) ) if( contourIsHole( c ) )
holes.push_back( std::move( shape ) ); holes.push_back( std::move( shape ) );
else else
outlines.push_back( std::move( shape ) ); glyph->AddOutline( std::move( shape ) );
} }
for( SHAPE_LINE_CHAIN& outline : outlines )
{
if( outline.PointCount() )
glyph->AddOutline( outline );
}
int nthHole = 0;
for( SHAPE_LINE_CHAIN& hole : holes ) for( SHAPE_LINE_CHAIN& hole : holes )
{ {
if( hole.PointCount() ) if( hole.PointCount() )
{ {
VECTOR2I firstPoint = hole.GetPoint( 0 ); for( int ii = 0; ii < glyph->OutlineCount(); ++ii )
int nthOutline = -1;
int n = 0;
for( SHAPE_LINE_CHAIN& outline : outlines )
{ {
if( outline.PointInside( firstPoint ) ) if( glyph->Outline( ii ).PointInside( hole.GetPoint( 0 ) ) )
{ {
nthOutline = n; glyph->AddHole( std::move( hole ), ii );
break; break;
} }
}
n++; }
} }
if( nthOutline > -1 ) if( glyph->HasHoles() )
glyph->AddHole( hole, n ); glyph->Fracture( SHAPE_POLY_SET::PM_FAST ); // FONT TODO verify aFastMode
}
nthHole++; aGlyphs->push_back( std::move( glyph ) );
} }
aGlyphs.push_back( std::move( glyph ) );
cursor.x += pos.x_advance; cursor.x += pos.x_advance;
cursor.y += pos.y_advance; cursor.y += pos.y_advance;
} }
VECTOR2I cursorEnd( cursor ); if( IsOverbar( aTextStyle ) && aGlyphs )
if( IsOverbar( aTextStyle ) )
{ {
topLeft *= scaleFactor; topLeft *= scaleFactor;
topRight *= scaleFactor; topRight *= scaleFactor;
@ -415,12 +407,12 @@ VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
ERROR_INSIDE ); ERROR_INSIDE );
std::unique_ptr<OUTLINE_GLYPH> overbarGlyph = std::make_unique<OUTLINE_GLYPH>( overbar ); std::unique_ptr<OUTLINE_GLYPH> overbarGlyph = std::make_unique<OUTLINE_GLYPH>( overbar );
aGlyphs.push_back( std::move( overbarGlyph ) ); aGlyphs->push_back( std::move( overbarGlyph ) );
} }
hb_buffer_destroy( buf ); hb_buffer_destroy( buf );
VECTOR2I cursorDisplacement( cursorEnd.x * scaleFactor.x, -cursorEnd.y * scaleFactor.y ); VECTOR2I cursorDisplacement( cursor.x * scaleFactor.x, -cursor.y * scaleFactor.y );
if( aBBox ) if( aBBox )
{ {

View File

@ -195,7 +195,7 @@ double STROKE_FONT::ComputeOverbarVerticalPosition( double aGlyphHeight ) const
} }
VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr<GLYPH>>& aGlyphs, VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
const UTF8& aText, const VECTOR2D& aSize, const UTF8& aText, const VECTOR2D& aSize,
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle, const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
bool aMirror, const VECTOR2I& aOrigin, bool aMirror, const VECTOR2I& aOrigin,
@ -252,10 +252,20 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
{ {
STROKE_GLYPH* source = static_cast<STROKE_GLYPH*>( m_glyphs->at( dd ).get() ); STROKE_GLYPH* source = static_cast<STROKE_GLYPH*>( m_glyphs->at( dd ).get() );
aGlyphs.push_back( source->Transform( glyphSize, cursor, tilt, aAngle, aMirror, if( aGlyphs )
{
aGlyphs->push_back( source->Transform( glyphSize, cursor, tilt, aAngle, aMirror,
aOrigin ) ); aOrigin ) );
}
cursor.x = aGlyphs.back()->BoundingBox().GetEnd().x; VECTOR2D glyphExtents = source->BoundingBox().GetEnd();
glyphExtents *= glyphSize;
if( tilt )
glyphExtents.x -= glyphExtents.y * tilt;
cursor.x += glyphExtents.x;
} }
} }
@ -263,8 +273,6 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
if( aTextStyle & TEXT_STYLE::OVERBAR ) if( aTextStyle & TEXT_STYLE::OVERBAR )
{ {
std::unique_ptr<STROKE_GLYPH> overbarGlyph = std::make_unique<STROKE_GLYPH>();
barOffset.y = ComputeOverbarVerticalPosition( glyphSize.y ); barOffset.y = ComputeOverbarVerticalPosition( glyphSize.y );
if( aTextStyle & TEXT_STYLE::ITALIC ) if( aTextStyle & TEXT_STYLE::ITALIC )
@ -279,11 +287,16 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
RotatePoint( barEnd, aOrigin, aAngle ); RotatePoint( barEnd, aOrigin, aAngle );
} }
if( aGlyphs )
{
std::unique_ptr<STROKE_GLYPH> overbarGlyph = std::make_unique<STROKE_GLYPH>();
overbarGlyph->AddPoint( barStart ); overbarGlyph->AddPoint( barStart );
overbarGlyph->AddPoint( barEnd ); overbarGlyph->AddPoint( barEnd );
overbarGlyph->Finalize(); overbarGlyph->Finalize();
aGlyphs.push_back( std::move( overbarGlyph ) ); aGlyphs->push_back( std::move( overbarGlyph ) );
}
} }
if( aBBox ) if( aBBox )

View File

@ -1,47 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2021 Ola Rinta-Koski
* Copyright (C) 2021 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 as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <limits>
#include <font/triangulate.h>
void Triangulate( const SHAPE_POLY_SET& aPolylist, TRIANGULATE_CALLBACK aCallback,
void* aCallbackData )
{
SHAPE_POLY_SET polys( aPolylist );
polys.Fracture( SHAPE_POLY_SET::PM_FAST ); // TODO verify aFastMode
polys.CacheTriangulation();
for( unsigned int i = 0; i < polys.TriangulatedPolyCount(); i++ )
{
const SHAPE_POLY_SET::TRIANGULATED_POLYGON* polygon = polys.TriangulatedPolygon( i );
for ( size_t j = 0; j < polygon->GetTriangleCount(); j++ )
{
VECTOR2I a;
VECTOR2I b;
VECTOR2I c;
polygon->GetTriangle( j, a, b, c );
aCallback( i, a, b, c, aCallbackData );
}
}
}

View File

@ -1786,9 +1786,9 @@ void CAIRO_GAL_BASE::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTota
// eventually glyphs should not be drawn as polygons at all, // eventually glyphs should not be drawn as polygons at all,
// but as bitmaps with antialiasing, this is just a stopgap measure // but as bitmaps with antialiasing, this is just a stopgap measure
// of getting some form of outline font display // of getting some form of outline font display
auto triangleCallback = [&]( int aPolygonIndex, const VECTOR2D& aVertex1, auto triangleCallback =
const VECTOR2D& aVertex2, const VECTOR2D& aVertex3, [&]( int aPolygonIndex, const VECTOR2D& aVertex1, const VECTOR2D& aVertex2,
void* aCallbackData ) const VECTOR2D& aVertex3, void* aCallbackData )
{ {
#if 1 #if 1
syncLineWidth(); syncLineWidth();

View File

@ -44,7 +44,6 @@
#include <bezier_curves.h> #include <bezier_curves.h>
#include <math/util.h> // for KiROUND #include <math/util.h> // for KiROUND
#include <trace_helpers.h> #include <trace_helpers.h>
#include <font/triangulate.h>
#include <wx/frame.h> #include <wx/frame.h>
@ -2425,24 +2424,16 @@ void OPENGL_GAL::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal )
{ {
const auto& outlineGlyph = static_cast<const KIFONT::OUTLINE_GLYPH&>( aGlyph ); const auto& outlineGlyph = static_cast<const KIFONT::OUTLINE_GLYPH&>( aGlyph );
fillPolygonAsTriangles( outlineGlyph );
}
}
void OPENGL_GAL::fillPolygonAsTriangles( const SHAPE_POLY_SET& aPolyList )
{
m_currentManager->Shader( SHADER_NONE ); m_currentManager->Shader( SHADER_NONE );
m_currentManager->Color( m_fillColor ); m_currentManager->Color( m_fillColor );
auto triangleCallback = [&]( int aPolygonIndex, const VECTOR2D& aVertex1, outlineGlyph.Triangulate(
const VECTOR2D& aVertex2, const VECTOR2D& aVertex3, [&]( int aPolygonIndex, const VECTOR2D& aVertex1, const VECTOR2D& aVertex2,
void* aCallbackData ) const VECTOR2D& aVertex3 )
{ {
m_currentManager->Vertex( aVertex1.x, aVertex1.y, m_layerDepth ); m_currentManager->Vertex( aVertex1.x, aVertex1.y, m_layerDepth );
m_currentManager->Vertex( aVertex2.x, aVertex2.y, m_layerDepth ); m_currentManager->Vertex( aVertex2.x, aVertex2.y, m_layerDepth );
m_currentManager->Vertex( aVertex3.x, aVertex3.y, m_layerDepth ); m_currentManager->Vertex( aVertex3.x, aVertex3.y, m_layerDepth );
}; } );
}
Triangulate( aPolyList, triangleCallback );
} }

View File

@ -1118,10 +1118,10 @@ const EDA_RECT LIB_PIN::GetBoundingBox( bool aIncludeInvisibles, bool aPinOnly )
if( showNum ) if( showNum )
{ {
VECTOR2D fontSize( m_numTextSize, m_numTextSize ); VECTOR2D fontSize( m_numTextSize, m_numTextSize );
VECTOR2D numSize = font->StringBoundaryLimits( number, fontSize, penWidth, false, false ); VECTOR2I numSize = font->StringBoundaryLimits( number, fontSize, penWidth, false, false );
numberTextLength = KiROUND( numSize.x ); numberTextLength = numSize.x;
numberTextHeight = KiROUND( numSize.y ); numberTextHeight = numSize.y;
} }
if( m_shape == GRAPHIC_PINSHAPE::INVERTED || m_shape == GRAPHIC_PINSHAPE::INVERTED_CLOCK ) if( m_shape == GRAPHIC_PINSHAPE::INVERTED || m_shape == GRAPHIC_PINSHAPE::INVERTED_CLOCK )
@ -1136,10 +1136,10 @@ const EDA_RECT LIB_PIN::GetBoundingBox( bool aIncludeInvisibles, bool aPinOnly )
if( showName ) if( showName )
{ {
VECTOR2D fontSize( m_nameTextSize, m_nameTextSize ); VECTOR2D fontSize( m_nameTextSize, m_nameTextSize );
VECTOR2D nameSize = font->StringBoundaryLimits( name, fontSize, penWidth, false, false ); VECTOR2I nameSize = font->StringBoundaryLimits( name, fontSize, penWidth, false, false );
nameTextLength = KiROUND( nameSize.x ) + nameTextOffset; nameTextLength = nameSize.x + nameTextOffset;
nameTextHeight = KiROUND( nameSize.y ) + Mils2iu( PIN_TEXT_MARGIN ); nameTextHeight = nameSize.y + Mils2iu( PIN_TEXT_MARGIN );
} }
if( nameTextOffset ) // for values > 0, pin name is inside the body if( nameTextOffset ) // for values > 0, pin name is inside the body

View File

@ -432,6 +432,19 @@ std::unique_ptr< LIB_SYMBOL > LIB_SYMBOL::Flatten() const
} }
void LIB_SYMBOL::ClearCaches()
{
for( LIB_ITEM& item : m_drawings )
{
if( EDA_TEXT* eda_text = dynamic_cast<EDA_TEXT*>( &item ) )
{
eda_text->ClearBoundingBoxCache();
eda_text->ClearRenderCache();
}
}
}
const wxString LIB_SYMBOL::GetLibraryName() const const wxString LIB_SYMBOL::GetLibraryName() const
{ {
if( m_library ) if( m_library )

View File

@ -126,6 +126,8 @@ public:
LIB_SYMBOL_REF& GetParent() { return m_parent; } LIB_SYMBOL_REF& GetParent() { return m_parent; }
const LIB_SYMBOL_REF& GetParent() const { return m_parent; } const LIB_SYMBOL_REF& GetParent() const { return m_parent; }
void ClearCaches();
virtual wxString GetClass() const override virtual wxString GetClass() const override
{ {
return wxT( "LIB_SYMBOL" ); return wxT( "LIB_SYMBOL" );

View File

@ -213,7 +213,8 @@ public:
/** /**
* Mark an item for refresh. * Mark an item for refresh.
*/ */
void UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete = false, bool aUpdateRtree = false ); virtual void UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete = false,
bool aUpdateRtree = false );
/** /**
* Mark selected items for refresh. * Mark selected items for refresh.

View File

@ -649,6 +649,14 @@ void SCH_EDIT_FRAME::SetCurrentSheet( const SCH_SHEET_PATH& aSheet )
void SCH_EDIT_FRAME::HardRedraw() void SCH_EDIT_FRAME::HardRedraw()
{ {
SCH_SCREEN* screen = GetCurrentSheet().LastScreen();
for( SCH_ITEM* item : screen->Items() )
item->ClearCaches();
for( std::pair<const wxString, LIB_SYMBOL*>& libSymbol : screen->GetLibSymbols() )
libSymbol.second->ClearCaches();
RecalculateConnections( LOCAL_CLEANUP ); RecalculateConnections( LOCAL_CLEANUP );
FocusOnItem( nullptr ); FocusOnItem( nullptr );
@ -1752,3 +1760,12 @@ void SCH_EDIT_FRAME::SaveSymbolToSchematic( const LIB_SYMBOL& aSymbol,
GetCanvas()->Refresh(); GetCanvas()->Refresh();
OnModify(); OnModify();
} }
void SCH_EDIT_FRAME::UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete, bool aUpdateRtree )
{
SCH_BASE_FRAME::UpdateItem( aItem, isAddOrDelete, aUpdateRtree );
if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( aItem ) )
sch_item->ClearCaches();
}

View File

@ -429,6 +429,9 @@ public:
void SetCurrentSheet( const SCH_SHEET_PATH& aSheet ); void SetCurrentSheet( const SCH_SHEET_PATH& aSheet );
void UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete = false,
bool aUpdateRtree = false ) override;
/** /**
* Rebuild the GAL and redraw the screen. Call when something went wrong. * Rebuild the GAL and redraw the screen. Call when something went wrong.
*/ */

View File

@ -52,13 +52,16 @@
#include <eeschema_id.h> #include <eeschema_id.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <tools/ee_actions.h> #include <tools/ee_actions.h>
#include <font/outline_font.h>
SCH_FIELD::SCH_FIELD( const VECTOR2I& aPos, int aFieldId, SCH_ITEM* aParent, SCH_FIELD::SCH_FIELD( const VECTOR2I& aPos, int aFieldId, SCH_ITEM* aParent,
const wxString& aName ) : const wxString& aName ) :
SCH_ITEM( aParent, SCH_FIELD_T ), SCH_ITEM( aParent, SCH_FIELD_T ),
EDA_TEXT( wxEmptyString ), EDA_TEXT( wxEmptyString ),
m_id( 0 ), m_id( 0 ),
m_name( aName ) m_name( aName ),
m_renderCacheValid( false )
{ {
SetTextPos( aPos ); SetTextPos( aPos );
SetId( aFieldId ); // will also set the layer SetId( aFieldId ); // will also set the layer
@ -66,11 +69,53 @@ SCH_FIELD::SCH_FIELD( const VECTOR2I& aPos, int aFieldId, SCH_ITEM* aParent,
} }
SCH_FIELD::SCH_FIELD( const SCH_FIELD& aField ) :
SCH_ITEM( aField ),
EDA_TEXT( aField )
{
m_id = aField.m_id;
m_name = aField.m_name;
m_renderCache.clear();
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aField.m_renderCache )
{
KIFONT::OUTLINE_GLYPH* outline_glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() );
m_renderCache.emplace_back( std::make_unique<KIFONT::OUTLINE_GLYPH>( *outline_glyph ) );
}
m_renderCacheValid = aField.m_renderCacheValid;
m_renderCachePos = aField.m_renderCachePos;
}
SCH_FIELD::~SCH_FIELD() SCH_FIELD::~SCH_FIELD()
{ {
} }
SCH_FIELD& SCH_FIELD::operator=( const SCH_FIELD& aField )
{
EDA_TEXT::operator=( aField );
m_id = aField.m_id;
m_name = aField.m_name;
m_renderCache.clear();
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aField.m_renderCache )
{
KIFONT::OUTLINE_GLYPH* outline_glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() );
m_renderCache.emplace_back( std::make_unique<KIFONT::OUTLINE_GLYPH>( *outline_glyph ) );
}
m_renderCacheValid = aField.m_renderCacheValid;
m_renderCachePos = aField.m_renderCachePos;
return *this;
}
EDA_ITEM* SCH_FIELD::Clone() const EDA_ITEM* SCH_FIELD::Clone() const
{ {
return new SCH_FIELD( *this ); return new SCH_FIELD( *this );
@ -226,6 +271,54 @@ KIFONT::FONT* SCH_FIELD::GetDrawFont() const
} }
void SCH_FIELD::ClearCaches()
{
ClearRenderCache();
EDA_TEXT::ClearBoundingBoxCache();
}
void SCH_FIELD::ClearRenderCache()
{
EDA_TEXT::ClearRenderCache();
m_renderCacheValid = false;
}
std::vector<std::unique_ptr<KIFONT::GLYPH>>*
SCH_FIELD::GetRenderCache( const wxString& forResolvedText, const VECTOR2I& forPosition,
TEXT_ATTRIBUTES& aAttrs ) const
{
if( GetDrawFont()->IsOutline() )
{
if( m_renderCache.empty() || !m_renderCacheValid )
{
m_renderCache.clear();
KIFONT::OUTLINE_FONT* font = static_cast<KIFONT::OUTLINE_FONT*>( GetDrawFont() );
font->GetLinesAsGlyphs( &m_renderCache, forResolvedText, forPosition, aAttrs );
m_renderCachePos = forPosition;
m_renderCacheValid = true;
}
if( m_renderCachePos != forPosition )
{
VECTOR2I delta = forPosition - m_renderCachePos;
for( std::unique_ptr<KIFONT::GLYPH>& glyph : m_renderCache )
static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() )->Move( delta );
m_renderCachePos = forPosition;
}
return &m_renderCache;
}
return nullptr;
}
void SCH_FIELD::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset ) void SCH_FIELD::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset )
{ {
wxDC* DC = aSettings->GetPrintDC(); wxDC* DC = aSettings->GetPrintDC();

View File

@ -52,10 +52,12 @@ public:
SCH_FIELD( const VECTOR2I& aPos, int aFieldId, SCH_ITEM* aParent, SCH_FIELD( const VECTOR2I& aPos, int aFieldId, SCH_ITEM* aParent,
const wxString& aName = wxEmptyString ); const wxString& aName = wxEmptyString );
// Do not create a copy constructor. The one generated by the compiler is adequate. SCH_FIELD( const SCH_FIELD& aText );
~SCH_FIELD(); ~SCH_FIELD();
SCH_FIELD& operator=( const SCH_FIELD& aField );
static inline bool ClassOf( const EDA_ITEM* aItem ) static inline bool ClassOf( const EDA_ITEM* aItem )
{ {
return aItem && SCH_FIELD_T == aItem->Type(); return aItem && SCH_FIELD_T == aItem->Type();
@ -156,6 +158,13 @@ public:
KIFONT::FONT* GetDrawFont() const override; KIFONT::FONT* GetDrawFont() const override;
void ClearCaches() override;
void ClearRenderCache() override;
std::vector<std::unique_ptr<KIFONT::GLYPH>>*
GetRenderCache( const wxString& forResolvedText, const VECTOR2I& forPosition,
TEXT_ATTRIBUTES& aAttrs ) const;
void Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset ) override; void Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset ) override;
void Move( const VECTOR2I& aMoveVector ) override void Move( const VECTOR2I& aMoveVector ) override
@ -222,6 +231,10 @@ private:
int m_id; ///< Field index, @see enum MANDATORY_FIELD_T int m_id; ///< Field index, @see enum MANDATORY_FIELD_T
wxString m_name; wxString m_name;
mutable bool m_renderCacheValid;
mutable VECTOR2I m_renderCachePos;
mutable std::vector<std::unique_ptr<KIFONT::GLYPH>> m_renderCache;
}; };

View File

@ -230,6 +230,26 @@ void SCH_ITEM::SwapData( SCH_ITEM* aItem )
} }
void SCH_ITEM::ClearCaches()
{
auto clearTextCaches =
[]( SCH_ITEM* aItem )
{
EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem );
if( text )
{
text->ClearBoundingBoxCache();
text->ClearRenderCache();
}
};
clearTextCaches( this );
RunOnChildren( clearTextCaches );
}
bool SCH_ITEM::operator < ( const SCH_ITEM& aItem ) const bool SCH_ITEM::operator < ( const SCH_ITEM& aItem ) const
{ {
if( Type() != aItem.Type() ) if( Type() != aItem.Type() )

View File

@ -429,6 +429,8 @@ public:
virtual void RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction ) { } virtual void RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction ) { }
virtual void ClearCaches();
/** /**
* Check if this schematic item has line stoke properties. * Check if this schematic item has line stoke properties.
* *

View File

@ -464,7 +464,7 @@ void SCH_PAINTER::boxText( const wxString& aText, const VECTOR2D& aPosition,
aAttrs.m_Italic ); aAttrs.m_Italic );
} }
VECTOR2D extents = font->StringBoundaryLimits( aText, aAttrs.m_Size, aAttrs.m_StrokeWidth, VECTOR2I extents = font->StringBoundaryLimits( aText, aAttrs.m_Size, aAttrs.m_StrokeWidth,
aAttrs.m_Bold, aAttrs.m_Italic ); aAttrs.m_Bold, aAttrs.m_Italic );
EDA_RECT box( (VECTOR2I) aPosition, wxSize( extents.x, aAttrs.m_Size.y ) ); EDA_RECT box( (VECTOR2I) aPosition, wxSize( extents.x, aAttrs.m_Size.y ) );
@ -718,11 +718,10 @@ void SCH_PAINTER::draw( const LIB_FIELD *aField, int aLayer )
if( drawingShadows && eeconfig()->m_Selection.text_as_box ) if( drawingShadows && eeconfig()->m_Selection.text_as_box )
{ {
bbox.RevertYAxis();
m_gal->SetIsStroke( true ); m_gal->SetIsStroke( true );
m_gal->SetIsFill( true ); m_gal->SetIsFill( true );
m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) ); m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
m_gal->DrawRectangle( mapCoords( bbox.GetPosition() ), mapCoords( bbox.GetEnd() ) ); m_gal->DrawRectangle( bbox.GetPosition(), bbox.GetEnd() );
} }
else else
{ {
@ -765,12 +764,20 @@ void SCH_PAINTER::draw( const LIB_TEXT *aText, int aLayer )
} }
EDA_RECT bBox = aText->GetBoundingBox(); EDA_RECT bBox = aText->GetBoundingBox();
bBox.RevertYAxis(); VECTOR2D pos = bBox.Centre();
VECTOR2D pos = mapCoords( 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 )
{
m_gal->SetIsStroke( true );
m_gal->SetIsFill( true );
m_gal->SetLineWidth( getTextThickness( aText, drawingShadows ) );
m_gal->DrawRectangle( bBox.GetPosition(), bBox.GetEnd() );
}
else
{
TEXT_ATTRIBUTES attrs( aText->GetAttributes() ); TEXT_ATTRIBUTES attrs( aText->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;
@ -778,6 +785,7 @@ void SCH_PAINTER::draw( const LIB_TEXT *aText, int aLayer )
strokeText( aText->GetText(), pos, attrs ); strokeText( aText->GetText(), pos, attrs );
} }
}
int SCH_PAINTER::internalPinDecoSize( const LIB_PIN &aPin ) int SCH_PAINTER::internalPinDecoSize( const LIB_PIN &aPin )
@ -1477,7 +1485,6 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
if( drawingShadows && eeconfig()->m_Selection.text_as_box ) if( drawingShadows && eeconfig()->m_Selection.text_as_box )
{ {
EDA_RECT bBox = aText->GetBoundingBox(); EDA_RECT bBox = aText->GetBoundingBox();
bBox.Offset( text_offset.x, text_offset.y );
bBox.RevertYAxis(); bBox.RevertYAxis();
m_gal->SetIsStroke( true ); m_gal->SetIsStroke( true );
m_gal->SetIsFill( true ); m_gal->SetIsFill( true );
@ -1503,7 +1510,7 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
} }
else else
{ {
strokeText( shownText, aText->GetTextPos(), attrs ); strokeText( shownText, aText->GetTextPos() + text_offset, attrs );
} }
} }
} }
@ -1705,13 +1712,27 @@ void SCH_PAINTER::draw( const SCH_FIELD *aField, int aLayer )
} }
else else
{ {
wxString shownText = aField->GetShownText();
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, drawingShadows );
attributes.m_Angle = orient; attributes.m_Angle = orient;
strokeText( aField->GetShownText(), textpos, attributes ); std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
cache = aField->GetRenderCache( shownText, textpos, attributes );
if( cache )
{
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
m_gal->DrawGlyph( *glyph.get() );
}
else
{
strokeText( shownText, textpos, attributes );
}
} }
// Draw the umbilical line // Draw the umbilical line

View File

@ -1049,7 +1049,10 @@ const EDA_RECT SCH_LABEL_BASE::GetBoundingBox() const
EDA_RECT box( GetBodyBoundingBox() ); EDA_RECT box( GetBodyBoundingBox() );
for( const SCH_FIELD& field : m_fields ) for( const SCH_FIELD& field : m_fields )
{
if( field.IsVisible() )
box.Merge( field.GetBoundingBox() ); box.Merge( field.GetBoundingBox() );
}
box.Normalize(); box.Normalize();

View File

@ -1165,6 +1165,8 @@ void SYMBOL_EDIT_FRAME::HardRedraw()
else else
item.SetSelected(); item.SetSelected();
} }
m_symbol->ClearCaches();
} }
RebuildView(); RebuildView();
@ -1482,3 +1484,15 @@ bool SYMBOL_EDIT_FRAME::IsSymbolEditable() const
{ {
return m_symbol && ( !IsSymbolFromLegacyLibrary() || IsSymbolFromSchematic() ); return m_symbol && ( !IsSymbolFromLegacyLibrary() || IsSymbolFromSchematic() );
} }
void SYMBOL_EDIT_FRAME::UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete, bool aUpdateRtree )
{
SCH_BASE_FRAME::UpdateItem( aItem, isAddOrDelete, aUpdateRtree );
if( EDA_TEXT* eda_text = dynamic_cast<EDA_TEXT*>( aItem ) )
{
eda_text->ClearBoundingBoxCache();
eda_text->ClearRenderCache();
}
}

View File

@ -323,6 +323,9 @@ public:
void RebuildView(); void RebuildView();
void UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete = false,
bool aUpdateRtree = false ) override;
/** /**
* Rebuild the GAL and redraw the screen. Call when something went wrong. * Rebuild the GAL and redraw the screen. Call when something went wrong.
*/ */

View File

@ -342,7 +342,8 @@ public:
virtual GR_TEXT_H_ALIGN_T GetDrawHorizJustify() const { return GetHorizJustify(); }; virtual GR_TEXT_H_ALIGN_T GetDrawHorizJustify() const { return GetHorizJustify(); };
virtual GR_TEXT_V_ALIGN_T GetDrawVertJustify() const { return GetVertJustify(); }; virtual GR_TEXT_V_ALIGN_T GetDrawVertJustify() const { return GetVertJustify(); };
void ClearRenderCache() { m_render_cache.clear(); } virtual void ClearRenderCache();
virtual void ClearBoundingBoxCache();
std::vector<std::unique_ptr<KIFONT::GLYPH>>* std::vector<std::unique_ptr<KIFONT::GLYPH>>*
GetRenderCache( const wxString& forResolvedText ) const; GetRenderCache( const wxString& forResolvedText ) const;
@ -377,6 +378,9 @@ private:
mutable EDA_ANGLE m_render_cache_angle; mutable EDA_ANGLE m_render_cache_angle;
mutable std::vector<std::unique_ptr<KIFONT::GLYPH>> m_render_cache; mutable std::vector<std::unique_ptr<KIFONT::GLYPH>> m_render_cache;
mutable bool m_bounding_box_cache_valid;
mutable EDA_RECT m_bounding_box_cache;
TEXT_ATTRIBUTES m_attributes; TEXT_ATTRIBUTES m_attributes;
VECTOR2I m_pos; VECTOR2I m_pos;
}; };

View File

@ -122,15 +122,14 @@ public:
* @param aCursor is the current text position (for multiple text blocks within a single text * @param aCursor is the current text position (for multiple text blocks within a single text
* object, such as a run of superscript characters) * object, such as a run of superscript characters)
* @param aAttrs are the styling attributes of the text, including its rotation * @param aAttrs are the styling attributes of the text, including its rotation
* @return bounding box
*/ */
VECTOR2D Draw( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition, void Draw( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition,
const VECTOR2I& aCursor, const TEXT_ATTRIBUTES& aAttrs ) const; const VECTOR2I& aCursor, const TEXT_ATTRIBUTES& aAttrs ) const;
VECTOR2D Draw( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition, void Draw( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition,
const TEXT_ATTRIBUTES& aAttributes ) const const TEXT_ATTRIBUTES& aAttributes ) const
{ {
return Draw( aGal, aText, aPosition, VECTOR2I( 0, 0 ), aAttributes ); Draw( aGal, aText, aPosition, VECTOR2I( 0, 0 ), aAttributes );
} }
virtual void DrawText( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition, virtual void DrawText( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition,
@ -141,7 +140,7 @@ public:
* *
* @return a VECTOR2D giving the width and height of text. * @return a VECTOR2D giving the width and height of text.
*/ */
VECTOR2D StringBoundaryLimits( const UTF8& aText, const VECTOR2D& aSize, int aThickness, VECTOR2I StringBoundaryLimits( const UTF8& aText, const VECTOR2D& aSize, int aThickness,
bool aBold, bool aItalic ) const; bool aBold, bool aItalic ) const;
/** /**
@ -170,7 +169,7 @@ public:
* @param aTextStyle text style flags * @param aTextStyle text style flags
* @return text cursor position after this text * @return text cursor position after this text
*/ */
virtual VECTOR2I GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr<GLYPH>>& aGlyphs, virtual VECTOR2I GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
const UTF8& aText, const VECTOR2D& aSize, const UTF8& aText, const VECTOR2D& aSize,
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle, const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
bool aMirror, const VECTOR2I& aOrigin, bool aMirror, const VECTOR2I& aOrigin,
@ -206,7 +205,7 @@ protected:
* @param aOrigin is the point around which the text should be rotated, mirrored, etc. * @param aOrigin is the point around which the text should be rotated, mirrored, etc.
* @return new cursor position in non-rotated, non-mirrored coordinates * @return new cursor position in non-rotated, non-mirrored coordinates
*/ */
VECTOR2D drawSingleLineText( KIGFX::GAL* aGal, BOX2I* aBoundingBox, const UTF8& aText, void drawSingleLineText( KIGFX::GAL* aGal, BOX2I* aBoundingBox, const UTF8& aText,
const VECTOR2I& aPosition, const VECTOR2D& aSize, const VECTOR2I& aPosition, const VECTOR2D& aSize,
const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin, const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
bool aItalic ) const; bool aItalic ) const;
@ -221,15 +220,14 @@ protected:
* @param aSize is the cap-height and em-width of the text. * @param aSize is the cap-height and em-width of the text.
* @return new cursor position * @return new cursor position
*/ */
VECTOR2D boundingBoxSingleLine( BOX2I* aBBox, const UTF8& aText, const VECTOR2I& aPosition, VECTOR2I boundingBoxSingleLine( BOX2I* aBBox, const UTF8& aText, const VECTOR2I& aPosition,
const VECTOR2D& aSize, bool aItalic ) const; const VECTOR2D& aSize, bool aItalic ) const;
void getLinePositions( const UTF8& aText, const VECTOR2I& aPosition, void getLinePositions( const UTF8& aText, const VECTOR2I& aPosition,
wxArrayString& aTextLines, std::vector<VECTOR2I>& aPositions, wxArrayString& aTextLines, std::vector<VECTOR2I>& aPositions,
std::vector<VECTOR2D>& aBoundingBoxes, std::vector<VECTOR2I>& aExtents, const TEXT_ATTRIBUTES& aAttrs ) const;
const TEXT_ATTRIBUTES& aAttributes ) const;
VECTOR2D drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>& aGlyphs, VECTOR2I drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
const UTF8& aText, const VECTOR2I& aPosition, const VECTOR2D& aSize, const UTF8& aText, const VECTOR2I& aPosition, const VECTOR2D& aSize,
const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin, const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
TEXT_STYLE_FLAGS aTextStyle ) const; TEXT_STYLE_FLAGS aTextStyle ) const;
@ -240,9 +238,6 @@ protected:
private: private:
static FONT* getDefaultFont(); static FONT* getDefaultFont();
VECTOR2D doDrawString( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition,
bool aParse, const TEXT_ATTRIBUTES& aAttrs ) const;
protected: protected:
wxString m_fontName; ///< Font name wxString m_fontName; ///< Font name
wxString m_fontFileName; ///< Font file name wxString m_fontFileName; ///< Font file name

View File

@ -31,6 +31,10 @@
#include <geometry/shape_poly_set.h> #include <geometry/shape_poly_set.h>
#include <wx/debug.h> #include <wx/debug.h>
typedef std::function<void( int, const VECTOR2I& aPoint1, const VECTOR2I& aPoint2,
const VECTOR2I& aPoint3 )>
TRIANGULATE_CALLBACK;
namespace KIFONT namespace KIFONT
{ {
class GLYPH class GLYPH
@ -64,6 +68,8 @@ public:
bool IsOutline() const override { return true; } bool IsOutline() const override { return true; }
BOX2D BoundingBox() override; BOX2D BoundingBox() override;
void Triangulate( TRIANGULATE_CALLBACK aCallback ) const;
}; };

View File

@ -93,7 +93,7 @@ public:
*/ */
double GetInterline( double aGlyphHeight = 0.0, double aLineSpacing = 1.0 ) const override; double GetInterline( double aGlyphHeight = 0.0, double aLineSpacing = 1.0 ) const override;
VECTOR2I GetTextAsGlyphs( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>& aGlyphs, VECTOR2I GetTextAsGlyphs( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
const UTF8& aText, const VECTOR2D& aSize, const VECTOR2I& aPosition, const UTF8& aText, const VECTOR2D& aSize, const VECTOR2I& aPosition,
const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin, const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
TEXT_STYLE_FLAGS aTextStyle ) const override; TEXT_STYLE_FLAGS aTextStyle ) const override;
@ -106,9 +106,12 @@ public:
* @param aGlyphs returns text glyphs * @param aGlyphs returns text glyphs
* @param aText the text item * @param aText the text item
*/ */
VECTOR2I GetLinesAsGlyphs( std::vector<std::unique_ptr<GLYPH>>& aGlyphs, void GetLinesAsGlyphs( std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
const EDA_TEXT* aText ) const; const EDA_TEXT* aText ) const;
void GetLinesAsGlyphs( std::vector<std::unique_ptr<GLYPH>>* aGlyphs, const UTF8& aText,
const VECTOR2I& aPosition, const TEXT_ATTRIBUTES& aAttrs ) const;
const FT_Face& GetFace() const { return m_face; } const FT_Face& GetFace() const { return m_face; }
#if 0 #if 0

View File

@ -76,7 +76,7 @@ public:
*/ */
double GetInterline( double aGlyphHeight, double aLineSpacing = 1.0 ) const override; double GetInterline( double aGlyphHeight, double aLineSpacing = 1.0 ) const override;
VECTOR2I GetTextAsGlyphs( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>& aGlyphs, VECTOR2I GetTextAsGlyphs( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
const UTF8& aText, const VECTOR2D& aSize, const VECTOR2I& aPosition, const UTF8& aText, const VECTOR2D& aSize, const VECTOR2I& aPosition,
const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin, const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
TEXT_STYLE_FLAGS aTextStyle ) const override; TEXT_STYLE_FLAGS aTextStyle ) const override;

View File

@ -1,37 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2021 Ola Rinta-Koski
* Copyright (C) 2021-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 as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRIANGULATE_H
#define TRIANGULATE_H
#include <math/vector2d.h>
#include <font/glyph.h>
#include <geometry/shape_poly_set.h>
#include <functional>
typedef std::function<void( int, const VECTOR2I& aPoint1, const VECTOR2I& aPoint2,
const VECTOR2I& aPoint3, void* aCallbackData )>
TRIANGULATE_CALLBACK;
void Triangulate( const SHAPE_POLY_SET& aPolylist, TRIANGULATE_CALLBACK aCallback,
void* aCallbackData = nullptr );
#endif // TRIANGULATE_H

View File

@ -524,8 +524,6 @@ private:
VECTOR2D getScreenPixelSize() const; VECTOR2D getScreenPixelSize() const;
void fillPolygonAsTriangles( const SHAPE_POLY_SET& aPolyList );
/** /**
* Basic OpenGL initialization and feature checks. * Basic OpenGL initialization and feature checks.
* *