Performance enhancements for fonts.
This commit is contained in:
parent
438c63f587
commit
04c76f10e9
|
@ -303,7 +303,6 @@ set( FONT_SRCS
|
|||
font/stroke_font.cpp
|
||||
font/outline_font.cpp
|
||||
font/outline_decomposer.cpp
|
||||
font/triangulate.cpp
|
||||
font/fontconfig.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -107,7 +107,8 @@ GR_TEXT_V_ALIGN_T EDA_TEXT::MapVertJustify( int aVertJustify )
|
|||
|
||||
|
||||
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 );
|
||||
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() );
|
||||
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_bounding_box_cache_valid = aText.m_bounding_box_cache_valid;
|
||||
m_bounding_box_cache = aText.m_bounding_box_cache;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -169,7 +176,11 @@ EDA_TEXT& EDA_TEXT::operator=( const EDA_TEXT& aText )
|
|||
void EDA_TEXT::SetText( const wxString& aText )
|
||||
{
|
||||
m_text = aText;
|
||||
|
||||
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_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 )
|
||||
{
|
||||
m_attributes.m_StrokeWidth = aWidth;
|
||||
m_render_cache.clear();
|
||||
ClearRenderCache();
|
||||
m_bounding_box_cache_valid = false;
|
||||
}
|
||||
|
||||
|
||||
void EDA_TEXT::SetTextAngle( const EDA_ANGLE& aAngle )
|
||||
{
|
||||
m_attributes.m_Angle = aAngle;
|
||||
m_render_cache.clear();
|
||||
ClearRenderCache();
|
||||
m_bounding_box_cache_valid = false;
|
||||
}
|
||||
|
||||
|
||||
void EDA_TEXT::SetItalic( bool aItalic )
|
||||
{
|
||||
m_attributes.m_Italic = aItalic;
|
||||
m_render_cache.clear();
|
||||
ClearRenderCache();
|
||||
m_bounding_box_cache_valid = false;
|
||||
}
|
||||
|
||||
|
||||
void EDA_TEXT::SetBold( bool aBold )
|
||||
{
|
||||
m_attributes.m_Bold = aBold;
|
||||
m_render_cache.clear();
|
||||
ClearRenderCache();
|
||||
m_bounding_box_cache_valid = false;
|
||||
}
|
||||
|
||||
|
||||
void EDA_TEXT::SetVisible( bool aVisible )
|
||||
{
|
||||
m_attributes.m_Visible = aVisible;
|
||||
m_render_cache.clear();
|
||||
ClearRenderCache();
|
||||
}
|
||||
|
||||
|
||||
void EDA_TEXT::SetMirrored( bool isMirrored )
|
||||
{
|
||||
m_attributes.m_Mirrored = isMirrored;
|
||||
m_render_cache.clear();
|
||||
ClearRenderCache();
|
||||
m_bounding_box_cache_valid = false;
|
||||
}
|
||||
|
||||
|
||||
void EDA_TEXT::SetMultilineAllowed( bool 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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
m_attributes.m_Valign = aType;
|
||||
m_render_cache.clear();
|
||||
ClearRenderCache();
|
||||
m_bounding_box_cache_valid = false;
|
||||
}
|
||||
|
||||
|
||||
void EDA_TEXT::SetKeepUpright( bool 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_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_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_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 retval = EDA_ITEM::Replace( aSearchData, m_text );
|
||||
|
||||
cacheShownText();
|
||||
|
||||
ClearRenderCache();
|
||||
m_bounding_box_cache_valid = false;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -313,35 +344,40 @@ bool EDA_TEXT::Replace( const wxFindReplaceData& aSearchData )
|
|||
void EDA_TEXT::SetFont( KIFONT::FONT* aFont )
|
||||
{
|
||||
m_attributes.m_Font = aFont;
|
||||
m_render_cache.clear();
|
||||
ClearRenderCache();
|
||||
m_bounding_box_cache_valid = false;
|
||||
}
|
||||
|
||||
|
||||
void EDA_TEXT::SetLineSpacing( double aLineSpacing )
|
||||
{
|
||||
m_attributes.m_LineSpacing = aLineSpacing;
|
||||
m_render_cache.clear();
|
||||
ClearRenderCache();
|
||||
m_bounding_box_cache_valid = false;
|
||||
}
|
||||
|
||||
|
||||
void EDA_TEXT::SetTextSize( const wxSize& aNewSize )
|
||||
{
|
||||
m_attributes.m_Size = aNewSize;
|
||||
m_render_cache.clear();
|
||||
ClearRenderCache();
|
||||
m_bounding_box_cache_valid = false;
|
||||
}
|
||||
|
||||
|
||||
void EDA_TEXT::SetTextWidth( int aWidth )
|
||||
{
|
||||
m_attributes.m_Size.x = aWidth;
|
||||
m_render_cache.clear();
|
||||
ClearRenderCache();
|
||||
m_bounding_box_cache_valid = false;
|
||||
}
|
||||
|
||||
|
||||
void EDA_TEXT::SetTextHeight( int 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;
|
||||
|
||||
for( std::unique_ptr<KIFONT::GLYPH>& glyph : m_render_cache )
|
||||
{
|
||||
KIFONT::OUTLINE_GLYPH* outline_glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() );
|
||||
outline_glyph->Move( aOffset );
|
||||
}
|
||||
static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() )->Move( aOffset );
|
||||
|
||||
m_bounding_box_cache.Move( aOffset );
|
||||
}
|
||||
|
||||
|
||||
void EDA_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_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>>*
|
||||
EDA_TEXT::GetRenderCache( const wxString& forResolvedText ) const
|
||||
{
|
||||
|
@ -424,7 +474,7 @@ EDA_TEXT::GetRenderCache( const wxString& forResolvedText ) const
|
|||
m_render_cache.clear();
|
||||
|
||||
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_text = forResolvedText;
|
||||
|
@ -474,6 +524,9 @@ int EDA_TEXT::GetInterline() 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;
|
||||
wxArrayString strings;
|
||||
wxString text = GetShownText();
|
||||
|
@ -498,8 +551,7 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
|
|||
double penWidth( thickness );
|
||||
bool bold = IsBold();
|
||||
bool italic = IsItalic();
|
||||
VECTOR2D extents = font->StringBoundaryLimits( text, fontSize, penWidth, bold, italic );
|
||||
int dx = KiROUND( extents.x );
|
||||
int dx = font->StringBoundaryLimits( text, fontSize, penWidth, bold, italic ).x;
|
||||
int dy = GetInterline();
|
||||
|
||||
// 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++ )
|
||||
{
|
||||
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.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
|
||||
|
||||
if( aLine < 0 && !aInvertY )
|
||||
{
|
||||
m_bounding_box_cache_valid = true;
|
||||
m_bounding_box_cache = 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() );
|
||||
|
||||
glyph->CacheTriangulation();
|
||||
glyph->Triangulate(
|
||||
[&]( int aPolygonIndex, const VECTOR2D& aVertex1, const VECTOR2D& aVertex2,
|
||||
const VECTOR2D& aVertex3 )
|
||||
{
|
||||
SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
|
||||
|
||||
for( unsigned int ii = 0; ii < glyph->TriangulatedPolyCount(); ++ii )
|
||||
{
|
||||
const SHAPE_POLY_SET::TRIANGULATED_POLYGON* tri = glyph->TriangulatedPolygon( ii );
|
||||
triShape->Append( aVertex1 );
|
||||
triShape->Append( aVertex2 );
|
||||
triShape->Append( aVertex3 );
|
||||
|
||||
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;
|
||||
|
||||
triShape->Append( a );
|
||||
triShape->Append( b );
|
||||
triShape->Append( c );
|
||||
|
||||
shape->AddShape( triShape );
|
||||
}
|
||||
}
|
||||
shape->AddShape( triShape );
|
||||
} );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -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,
|
||||
wxArrayString& aTextLines, std::vector<VECTOR2I>& aPositions,
|
||||
std::vector<VECTOR2D>& aBoundingBoxes,
|
||||
const TEXT_ATTRIBUTES& aAttrs ) const
|
||||
std::vector<VECTOR2I>& aExtents, const TEXT_ATTRIBUTES& aAttrs ) const
|
||||
{
|
||||
wxStringSplit( aText, aTextLines, '\n' );
|
||||
int lineCount = aTextLines.Count();
|
||||
|
@ -180,12 +117,12 @@ void FONT::getLinePositions( const UTF8& aText, const VECTOR2I& aPosition,
|
|||
|
||||
for( int i = 0; i < lineCount; i++ )
|
||||
{
|
||||
VECTOR2D pos( aPosition.x, aPosition.y + i * interline );
|
||||
VECTOR2D end = boundingBoxSingleLine( nullptr, aTextLines[i], pos, aAttrs.m_Size,
|
||||
VECTOR2I pos( aPosition.x, aPosition.y + i * interline );
|
||||
VECTOR2I end = boundingBoxSingleLine( nullptr, aTextLines[i], pos, aAttrs.m_Size,
|
||||
aAttrs.m_Italic );
|
||||
VECTOR2D bBox( end - pos );
|
||||
VECTOR2I bBox( end - pos );
|
||||
|
||||
aBoundingBoxes.push_back( bBox );
|
||||
aExtents.push_back( bBox );
|
||||
|
||||
if( i == 0 )
|
||||
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++ )
|
||||
{
|
||||
VECTOR2I lineSize = aBoundingBoxes.at( i );
|
||||
VECTOR2I lineSize = aExtents.at( i );
|
||||
wxPoint lineOffset( offset );
|
||||
|
||||
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)
|
||||
* @param aAttrs are the styling attributes of the text, including its rotation
|
||||
*/
|
||||
VECTOR2D FONT::Draw( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition,
|
||||
const VECTOR2I& aCursor, const TEXT_ATTRIBUTES& aAttrs ) const
|
||||
void FONT::Draw( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition,
|
||||
const VECTOR2I& aCursor, const TEXT_ATTRIBUTES& aAttrs ) const
|
||||
{
|
||||
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
|
||||
wxArrayString strings_list;
|
||||
std::vector<VECTOR2I> positions;
|
||||
std::vector<VECTOR2D> boundingBoxes;
|
||||
std::vector<VECTOR2I> extents;
|
||||
|
||||
getLinePositions( aText, position, strings_list, positions, boundingBoxes, aAttrs );
|
||||
|
||||
VECTOR2D boundingBox( 0, 0 );
|
||||
BOX2I lineBoundingBox;
|
||||
getLinePositions( aText, position, strings_list, positions, extents, aAttrs );
|
||||
|
||||
aGal->SetLineWidth( aAttrs.m_StrokeWidth );
|
||||
|
||||
for( size_t i = 0; i < strings_list.GetCount(); i++ )
|
||||
{
|
||||
(void) drawSingleLineText( aGal, &lineBoundingBox, strings_list[i], positions[i],
|
||||
aAttrs.m_Size, aAttrs.m_Angle, aAttrs.m_Mirrored, aPosition,
|
||||
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;
|
||||
drawSingleLineText( aGal, nullptr, strings_list[i], positions[i], aAttrs.m_Size,
|
||||
aAttrs.m_Angle, aAttrs.m_Mirrored, aPosition, aAttrs.m_Italic );
|
||||
}
|
||||
|
||||
return boundingBox;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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 KIFONT::FONT* aFont, const VECTOR2D& aSize, const EDA_ANGLE& aAngle,
|
||||
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 EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
|
||||
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,
|
||||
const VECTOR2I& aPosition, const VECTOR2D& aSize,
|
||||
const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
|
||||
bool aItalic ) const
|
||||
void FONT::drawSingleLineText( KIGFX::GAL* aGal, BOX2I* aBoundingBox, const UTF8& aText,
|
||||
const VECTOR2I& aPosition, const VECTOR2D& aSize,
|
||||
const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
|
||||
bool aItalic ) const
|
||||
{
|
||||
if( !aGal )
|
||||
{
|
||||
// do nothing, cursor does not move
|
||||
return aPosition;
|
||||
}
|
||||
return;
|
||||
|
||||
TEXT_STYLE_FLAGS textStyle = 0;
|
||||
|
||||
|
@ -358,23 +281,21 @@ VECTOR2D FONT::drawSingleLineText( KIGFX::GAL* aGal, BOX2I* aBoundingBox, const
|
|||
textStyle |= TEXT_STYLE::ITALIC;
|
||||
|
||||
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 )
|
||||
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
|
||||
{
|
||||
// TODO do we need to parse every time - have we already parsed?
|
||||
std::vector<std::unique_ptr<GLYPH>> glyphs; // ignored
|
||||
BOX2I boundingBox;
|
||||
TEXT_STYLE_FLAGS textStyle = 0;
|
||||
BOX2I boundingBox;
|
||||
TEXT_STYLE_FLAGS textStyle = 0;
|
||||
|
||||
if( aBold )
|
||||
textStyle |= TEXT_STYLE::BOLD;
|
||||
|
@ -382,8 +303,8 @@ VECTOR2D FONT::StringBoundaryLimits( const UTF8& aText, const VECTOR2D& aSize, i
|
|||
if( aItalic )
|
||||
textStyle |= TEXT_STYLE::ITALIC;
|
||||
|
||||
(void) drawMarkup( &boundingBox, glyphs, aText, VECTOR2D(), aSize, EDA_ANGLE::ANGLE_0,
|
||||
false, VECTOR2D(), textStyle );
|
||||
(void) drawMarkup( &boundingBox, nullptr, aText, VECTOR2I(), aSize, EDA_ANGLE::ANGLE_0, false,
|
||||
VECTOR2I(), textStyle );
|
||||
|
||||
if( IsStroke() )
|
||||
{
|
||||
|
@ -399,18 +320,16 @@ VECTOR2D FONT::StringBoundaryLimits( const UTF8& aText, const VECTOR2D& aSize, i
|
|||
}
|
||||
|
||||
|
||||
VECTOR2D FONT::boundingBoxSingleLine( BOX2I* aBoundingBox, const UTF8& aText,
|
||||
const VECTOR2I& aPosition, const VECTOR2D& aSize,
|
||||
bool aItalic ) const
|
||||
VECTOR2I FONT::boundingBoxSingleLine( BOX2I* aBBox, const UTF8& aText, const VECTOR2I& aPosition,
|
||||
const VECTOR2D& aSize, bool aItalic ) const
|
||||
{
|
||||
TEXT_STYLE_FLAGS textStyle = 0;
|
||||
|
||||
if( aItalic )
|
||||
textStyle |= TEXT_STYLE::ITALIC;
|
||||
|
||||
std::vector<std::unique_ptr<GLYPH>> glyphs; // ignored
|
||||
VECTOR2D nextPosition = drawMarkup( aBoundingBox, glyphs, aText, aPosition, aSize,
|
||||
EDA_ANGLE::ANGLE_0, false, VECTOR2I(), textStyle );
|
||||
VECTOR2I extents = drawMarkup( aBBox, nullptr, aText, aPosition, aSize, EDA_ANGLE::ANGLE_0,
|
||||
false, VECTOR2I(), textStyle );
|
||||
|
||||
return nextPosition;
|
||||
return extents;
|
||||
}
|
||||
|
|
|
@ -108,3 +108,23 @@ BOX2D OUTLINE_GLYPH::BoundingBox()
|
|||
BOX2I bbox = BBox();
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
const EDA_TEXT* aText ) const
|
||||
void OUTLINE_FONT::GetLinesAsGlyphs( std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
|
||||
const EDA_TEXT* aText ) const
|
||||
{
|
||||
wxArrayString strings;
|
||||
std::vector<VECTOR2I> positions;
|
||||
VECTOR2I ret;
|
||||
std::vector<VECTOR2D> boundingBoxes;
|
||||
std::vector<VECTOR2I> extents;
|
||||
TEXT_ATTRIBUTES attrs = aText->GetAttributes();
|
||||
TEXT_STYLE_FLAGS textStyle = 0;
|
||||
|
||||
attrs.m_Angle = aText->GetDrawRotation();
|
||||
|
||||
if( aText->IsItalic() )
|
||||
textStyle |= TEXT_STYLE::ITALIC;
|
||||
|
||||
getLinePositions( aText->GetShownText(), aText->GetTextPos(), strings, positions, boundingBoxes,
|
||||
attrs );
|
||||
|
||||
for( size_t i = 0; i < strings.GetCount(); i++ )
|
||||
{
|
||||
ret = drawMarkup( nullptr, aGlyphs, UTF8( strings.Item( i ) ), positions[i], attrs.m_Size,
|
||||
attrs.m_Angle, attrs.m_Mirrored, aText->GetTextPos(), textStyle );
|
||||
}
|
||||
|
||||
return ret;
|
||||
return GetLinesAsGlyphs( aGlyphs, aText->GetShownText(), aText->GetTextPos(), attrs );
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr<GLYPH>>& aGlyphs,
|
||||
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;
|
||||
|
||||
getLinePositions( aText, aPosition, strings, positions, extents, aAttrs );
|
||||
|
||||
for( size_t i = 0; i < strings.GetCount(); i++ )
|
||||
{
|
||||
(void) drawMarkup( nullptr, aGlyphs, UTF8( strings.Item( i ) ), positions[i],
|
||||
aAttrs.m_Size, aAttrs.m_Angle, aAttrs.m_Mirrored, aPosition, textStyle );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
|
||||
const UTF8& aText, const VECTOR2D& aSize,
|
||||
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
|
||||
bool aMirror, const VECTOR2I& aOrigin,
|
||||
|
@ -294,104 +302,88 @@ VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
|||
hb_glyph_position_t& pos = glyphPos[i];
|
||||
int codepoint = glyphInfo[i].codepoint;
|
||||
|
||||
FT_Load_Glyph( face, codepoint, FT_LOAD_NO_BITMAP );
|
||||
|
||||
FT_GlyphSlot faceGlyph = face->glyph;
|
||||
|
||||
// contours is a collection of all outlines in the glyph;
|
||||
// example: glyph for 'o' generally contains 2 contours,
|
||||
// one for the glyph outline and one for the hole
|
||||
CONTOURS contours;
|
||||
|
||||
OUTLINE_DECOMPOSER decomposer( faceGlyph->outline );
|
||||
decomposer.OutlineToSegments( &contours );
|
||||
|
||||
std::unique_ptr<OUTLINE_GLYPH> glyph = std::make_unique<OUTLINE_GLYPH>();
|
||||
std::vector<SHAPE_LINE_CHAIN> holes;
|
||||
std::vector<SHAPE_LINE_CHAIN> outlines;
|
||||
|
||||
for( CONTOUR& c : contours )
|
||||
if( aGlyphs )
|
||||
{
|
||||
GLYPH_POINTS points = c.points;
|
||||
SHAPE_LINE_CHAIN shape;
|
||||
FT_Load_Glyph( face, codepoint, FT_LOAD_NO_BITMAP );
|
||||
|
||||
for( const VECTOR2D& v : points )
|
||||
FT_GlyphSlot faceGlyph = face->glyph;
|
||||
|
||||
// contours is a collection of all outlines in the glyph;
|
||||
// example: glyph for 'o' generally contains 2 contours,
|
||||
// one for the glyph outline and one for the hole
|
||||
CONTOURS contours;
|
||||
|
||||
OUTLINE_DECOMPOSER decomposer( faceGlyph->outline );
|
||||
decomposer.OutlineToSegments( &contours );
|
||||
|
||||
std::unique_ptr<OUTLINE_GLYPH> glyph = std::make_unique<OUTLINE_GLYPH>();
|
||||
std::vector<SHAPE_LINE_CHAIN> holes;
|
||||
|
||||
for( CONTOUR& c : contours )
|
||||
{
|
||||
VECTOR2D pt( v + cursor );
|
||||
GLYPH_POINTS points = c.points;
|
||||
SHAPE_LINE_CHAIN shape;
|
||||
|
||||
topLeft.x = std::min( topLeft.x, pt.x );
|
||||
topLeft.y = std::max( topLeft.y, pt.y );
|
||||
topRight.x = std::max( topRight.x, pt.x );
|
||||
topRight.y = std::max( topRight.y, pt.y );
|
||||
|
||||
if( IsSubscript( aTextStyle ) )
|
||||
pt.y -= 0.25 * scaler;
|
||||
else if( IsSuperscript( aTextStyle ) )
|
||||
pt.y += 0.45 * scaler;
|
||||
|
||||
pt *= scaleFactor;
|
||||
pt += aPosition;
|
||||
|
||||
if( aMirror )
|
||||
pt.x = aOrigin.x - ( pt.x - aOrigin.x );
|
||||
|
||||
if( !aAngle.IsZero() )
|
||||
RotatePoint( pt, aOrigin, aAngle );
|
||||
|
||||
shape.Append( pt.x, pt.y );
|
||||
}
|
||||
|
||||
shape.SetClosed( true );
|
||||
|
||||
if( contourIsHole( c ) )
|
||||
holes.push_back( std::move( shape ) );
|
||||
else
|
||||
outlines.push_back( std::move( shape ) );
|
||||
}
|
||||
|
||||
for( SHAPE_LINE_CHAIN& outline : outlines )
|
||||
{
|
||||
if( outline.PointCount() )
|
||||
glyph->AddOutline( outline );
|
||||
}
|
||||
|
||||
int nthHole = 0;
|
||||
|
||||
for( SHAPE_LINE_CHAIN& hole : holes )
|
||||
{
|
||||
if( hole.PointCount() )
|
||||
{
|
||||
VECTOR2I firstPoint = hole.GetPoint( 0 );
|
||||
int nthOutline = -1;
|
||||
int n = 0;
|
||||
|
||||
for( SHAPE_LINE_CHAIN& outline : outlines )
|
||||
for( const VECTOR2D& v : points )
|
||||
{
|
||||
if( outline.PointInside( firstPoint ) )
|
||||
{
|
||||
nthOutline = n;
|
||||
break;
|
||||
}
|
||||
VECTOR2D pt( v + cursor );
|
||||
|
||||
n++;
|
||||
topLeft.x = std::min( topLeft.x, pt.x );
|
||||
topLeft.y = std::max( topLeft.y, pt.y );
|
||||
topRight.x = std::max( topRight.x, pt.x );
|
||||
topRight.y = std::max( topRight.y, pt.y );
|
||||
|
||||
if( IsSubscript( aTextStyle ) )
|
||||
pt.y -= 0.25 * scaler;
|
||||
else if( IsSuperscript( aTextStyle ) )
|
||||
pt.y += 0.45 * scaler;
|
||||
|
||||
pt *= scaleFactor;
|
||||
pt += aPosition;
|
||||
|
||||
if( aMirror )
|
||||
pt.x = aOrigin.x - ( pt.x - aOrigin.x );
|
||||
|
||||
if( !aAngle.IsZero() )
|
||||
RotatePoint( pt, aOrigin, aAngle );
|
||||
|
||||
shape.Append( pt.x, pt.y );
|
||||
}
|
||||
|
||||
if( nthOutline > -1 )
|
||||
glyph->AddHole( hole, n );
|
||||
shape.SetClosed( true );
|
||||
|
||||
if( contourIsHole( c ) )
|
||||
holes.push_back( std::move( shape ) );
|
||||
else
|
||||
glyph->AddOutline( std::move( shape ) );
|
||||
}
|
||||
|
||||
nthHole++;
|
||||
}
|
||||
for( SHAPE_LINE_CHAIN& hole : holes )
|
||||
{
|
||||
if( hole.PointCount() )
|
||||
{
|
||||
for( int ii = 0; ii < glyph->OutlineCount(); ++ii )
|
||||
{
|
||||
if( glyph->Outline( ii ).PointInside( hole.GetPoint( 0 ) ) )
|
||||
{
|
||||
glyph->AddHole( std::move( hole ), ii );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aGlyphs.push_back( std::move( glyph ) );
|
||||
if( glyph->HasHoles() )
|
||||
glyph->Fracture( SHAPE_POLY_SET::PM_FAST ); // FONT TODO verify aFastMode
|
||||
|
||||
aGlyphs->push_back( std::move( glyph ) );
|
||||
}
|
||||
|
||||
cursor.x += pos.x_advance;
|
||||
cursor.y += pos.y_advance;
|
||||
}
|
||||
|
||||
VECTOR2I cursorEnd( cursor );
|
||||
|
||||
if( IsOverbar( aTextStyle ) )
|
||||
if( IsOverbar( aTextStyle ) && aGlyphs )
|
||||
{
|
||||
topLeft *= scaleFactor;
|
||||
topRight *= scaleFactor;
|
||||
|
@ -415,12 +407,12 @@ VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
|||
ERROR_INSIDE );
|
||||
|
||||
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 );
|
||||
|
||||
VECTOR2I cursorDisplacement( cursorEnd.x * scaleFactor.x, -cursorEnd.y * scaleFactor.y );
|
||||
VECTOR2I cursorDisplacement( cursor.x * scaleFactor.x, -cursor.y * scaleFactor.y );
|
||||
|
||||
if( aBBox )
|
||||
{
|
||||
|
|
|
@ -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 VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
|
||||
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() );
|
||||
|
||||
aGlyphs.push_back( source->Transform( glyphSize, cursor, tilt, aAngle, aMirror,
|
||||
aOrigin ) );
|
||||
if( aGlyphs )
|
||||
{
|
||||
aGlyphs->push_back( source->Transform( glyphSize, cursor, tilt, aAngle, aMirror,
|
||||
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 )
|
||||
{
|
||||
std::unique_ptr<STROKE_GLYPH> overbarGlyph = std::make_unique<STROKE_GLYPH>();
|
||||
|
||||
barOffset.y = ComputeOverbarVerticalPosition( glyphSize.y );
|
||||
|
||||
if( aTextStyle & TEXT_STYLE::ITALIC )
|
||||
|
@ -279,11 +287,16 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
|
|||
RotatePoint( barEnd, aOrigin, aAngle );
|
||||
}
|
||||
|
||||
overbarGlyph->AddPoint( barStart );
|
||||
overbarGlyph->AddPoint( barEnd );
|
||||
overbarGlyph->Finalize();
|
||||
if( aGlyphs )
|
||||
{
|
||||
std::unique_ptr<STROKE_GLYPH> overbarGlyph = std::make_unique<STROKE_GLYPH>();
|
||||
|
||||
aGlyphs.push_back( std::move( overbarGlyph ) );
|
||||
overbarGlyph->AddPoint( barStart );
|
||||
overbarGlyph->AddPoint( barEnd );
|
||||
overbarGlyph->Finalize();
|
||||
|
||||
aGlyphs->push_back( std::move( overbarGlyph ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( aBBox )
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1786,44 +1786,44 @@ void CAIRO_GAL_BASE::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTota
|
|||
// eventually glyphs should not be drawn as polygons at all,
|
||||
// but as bitmaps with antialiasing, this is just a stopgap measure
|
||||
// of getting some form of outline font display
|
||||
auto triangleCallback = [&]( int aPolygonIndex, const VECTOR2D& aVertex1,
|
||||
const VECTOR2D& aVertex2, const VECTOR2D& aVertex3,
|
||||
void* aCallbackData )
|
||||
{
|
||||
#if 1
|
||||
syncLineWidth();
|
||||
auto triangleCallback =
|
||||
[&]( int aPolygonIndex, const VECTOR2D& aVertex1, const VECTOR2D& aVertex2,
|
||||
const VECTOR2D& aVertex3, void* aCallbackData )
|
||||
{
|
||||
#if 1
|
||||
syncLineWidth();
|
||||
|
||||
const auto p0 = roundp( xform( aVertex1 ) );
|
||||
const auto p1 = roundp( xform( aVertex2 ) );
|
||||
const auto p2 = roundp( xform( aVertex3 ) );
|
||||
const auto p0 = roundp( xform( aVertex1 ) );
|
||||
const auto p1 = roundp( xform( aVertex2 ) );
|
||||
const auto p2 = roundp( xform( aVertex3 ) );
|
||||
|
||||
/*
|
||||
cairo_move_to( currentContext, aVertex1.x, aVertex1.y );
|
||||
cairo_line_to( currentContext, aVertex2.x, aVertex2.y );
|
||||
cairo_line_to( currentContext, aVertex3.x, aVertex3.y );
|
||||
cairo_line_to( currentContext, aVertex1.x, aVertex1.y );
|
||||
*/
|
||||
cairo_move_to( m_currentContext, p0.x, p0.y );
|
||||
cairo_line_to( m_currentContext, p1.x, p1.y );
|
||||
cairo_line_to( m_currentContext, p2.x, p2.y );
|
||||
cairo_close_path( m_currentContext );
|
||||
/*
|
||||
setSourceRgba( currentContext, fillColor );
|
||||
SetIsFill( true );
|
||||
cairo_set_fill_rule( currentContext, CAIRO_FILL_RULE_EVEN_ODD );
|
||||
flushPath();
|
||||
*/
|
||||
//cairo_fill( currentContext );
|
||||
#else
|
||||
// just a silly test
|
||||
/*
|
||||
DrawRectangle(aVertex1, aVertex2);
|
||||
DrawRectangle(aVertex2, aVertex3);
|
||||
DrawRectangle(aVertex3, aVertex1);
|
||||
*/
|
||||
DrawTriangle( aVertex1, aVertex2, aVertex3 );
|
||||
#endif
|
||||
};
|
||||
/*
|
||||
cairo_move_to( currentContext, aVertex1.x, aVertex1.y );
|
||||
cairo_line_to( currentContext, aVertex2.x, aVertex2.y );
|
||||
cairo_line_to( currentContext, aVertex3.x, aVertex3.y );
|
||||
cairo_line_to( currentContext, aVertex1.x, aVertex1.y );
|
||||
*/
|
||||
cairo_move_to( m_currentContext, p0.x, p0.y );
|
||||
cairo_line_to( m_currentContext, p1.x, p1.y );
|
||||
cairo_line_to( m_currentContext, p2.x, p2.y );
|
||||
cairo_close_path( m_currentContext );
|
||||
/*
|
||||
setSourceRgba( currentContext, fillColor );
|
||||
SetIsFill( true );
|
||||
cairo_set_fill_rule( currentContext, CAIRO_FILL_RULE_EVEN_ODD );
|
||||
flushPath();
|
||||
*/
|
||||
//cairo_fill( currentContext );
|
||||
#else
|
||||
// just a silly test
|
||||
/*
|
||||
DrawRectangle(aVertex1, aVertex2);
|
||||
DrawRectangle(aVertex2, aVertex3);
|
||||
DrawRectangle(aVertex3, aVertex1);
|
||||
*/
|
||||
DrawTriangle( aVertex1, aVertex2, aVertex3 );
|
||||
#endif
|
||||
};
|
||||
|
||||
Triangulate( aGlyph, triangleCallback );
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include <bezier_curves.h>
|
||||
#include <math/util.h> // for KiROUND
|
||||
#include <trace_helpers.h>
|
||||
#include <font/triangulate.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 );
|
||||
|
||||
fillPolygonAsTriangles( outlineGlyph );
|
||||
m_currentManager->Shader( SHADER_NONE );
|
||||
m_currentManager->Color( m_fillColor );
|
||||
|
||||
outlineGlyph.Triangulate(
|
||||
[&]( int aPolygonIndex, const VECTOR2D& aVertex1, const VECTOR2D& aVertex2,
|
||||
const VECTOR2D& aVertex3 )
|
||||
{
|
||||
m_currentManager->Vertex( aVertex1.x, aVertex1.y, m_layerDepth );
|
||||
m_currentManager->Vertex( aVertex2.x, aVertex2.y, m_layerDepth );
|
||||
m_currentManager->Vertex( aVertex3.x, aVertex3.y, m_layerDepth );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::fillPolygonAsTriangles( const SHAPE_POLY_SET& aPolyList )
|
||||
{
|
||||
m_currentManager->Shader( SHADER_NONE );
|
||||
m_currentManager->Color( m_fillColor );
|
||||
|
||||
auto triangleCallback = [&]( int aPolygonIndex, const VECTOR2D& aVertex1,
|
||||
const VECTOR2D& aVertex2, const VECTOR2D& aVertex3,
|
||||
void* aCallbackData )
|
||||
{
|
||||
m_currentManager->Vertex( aVertex1.x, aVertex1.y, m_layerDepth );
|
||||
m_currentManager->Vertex( aVertex2.x, aVertex2.y, m_layerDepth );
|
||||
m_currentManager->Vertex( aVertex3.x, aVertex3.y, m_layerDepth );
|
||||
};
|
||||
|
||||
Triangulate( aPolyList, triangleCallback );
|
||||
}
|
||||
|
|
|
@ -1118,10 +1118,10 @@ const EDA_RECT LIB_PIN::GetBoundingBox( bool aIncludeInvisibles, bool aPinOnly )
|
|||
if( showNum )
|
||||
{
|
||||
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 );
|
||||
numberTextHeight = KiROUND( numSize.y );
|
||||
numberTextLength = numSize.x;
|
||||
numberTextHeight = numSize.y;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
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;
|
||||
nameTextHeight = KiROUND( nameSize.y ) + Mils2iu( PIN_TEXT_MARGIN );
|
||||
nameTextLength = nameSize.x + nameTextOffset;
|
||||
nameTextHeight = nameSize.y + Mils2iu( PIN_TEXT_MARGIN );
|
||||
}
|
||||
|
||||
if( nameTextOffset ) // for values > 0, pin name is inside the body
|
||||
|
|
|
@ -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
|
||||
{
|
||||
if( m_library )
|
||||
|
|
|
@ -126,6 +126,8 @@ public:
|
|||
LIB_SYMBOL_REF& GetParent() { return m_parent; }
|
||||
const LIB_SYMBOL_REF& GetParent() const { return m_parent; }
|
||||
|
||||
void ClearCaches();
|
||||
|
||||
virtual wxString GetClass() const override
|
||||
{
|
||||
return wxT( "LIB_SYMBOL" );
|
||||
|
|
|
@ -213,7 +213,8 @@ public:
|
|||
/**
|
||||
* 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.
|
||||
|
|
|
@ -649,6 +649,14 @@ void SCH_EDIT_FRAME::SetCurrentSheet( const SCH_SHEET_PATH& aSheet )
|
|||
|
||||
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 );
|
||||
|
||||
FocusOnItem( nullptr );
|
||||
|
@ -1752,3 +1760,12 @@ void SCH_EDIT_FRAME::SaveSymbolToSchematic( const LIB_SYMBOL& aSymbol,
|
|||
GetCanvas()->Refresh();
|
||||
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();
|
||||
}
|
|
@ -429,6 +429,9 @@ public:
|
|||
|
||||
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.
|
||||
*/
|
||||
|
|
|
@ -52,13 +52,16 @@
|
|||
#include <eeschema_id.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/ee_actions.h>
|
||||
#include <font/outline_font.h>
|
||||
|
||||
|
||||
SCH_FIELD::SCH_FIELD( const VECTOR2I& aPos, int aFieldId, SCH_ITEM* aParent,
|
||||
const wxString& aName ) :
|
||||
SCH_ITEM( aParent, SCH_FIELD_T ),
|
||||
EDA_TEXT( wxEmptyString ),
|
||||
m_id( 0 ),
|
||||
m_name( aName )
|
||||
m_name( aName ),
|
||||
m_renderCacheValid( false )
|
||||
{
|
||||
SetTextPos( aPos );
|
||||
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::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
|
||||
{
|
||||
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 )
|
||||
{
|
||||
wxDC* DC = aSettings->GetPrintDC();
|
||||
|
|
|
@ -52,10 +52,12 @@ public:
|
|||
SCH_FIELD( const VECTOR2I& aPos, int aFieldId, SCH_ITEM* aParent,
|
||||
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& operator=( const SCH_FIELD& aField );
|
||||
|
||||
static inline bool ClassOf( const EDA_ITEM* aItem )
|
||||
{
|
||||
return aItem && SCH_FIELD_T == aItem->Type();
|
||||
|
@ -156,6 +158,13 @@ public:
|
|||
|
||||
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 Move( const VECTOR2I& aMoveVector ) override
|
||||
|
@ -222,6 +231,10 @@ private:
|
|||
int m_id; ///< Field index, @see enum MANDATORY_FIELD_T
|
||||
|
||||
wxString m_name;
|
||||
|
||||
mutable bool m_renderCacheValid;
|
||||
mutable VECTOR2I m_renderCachePos;
|
||||
mutable std::vector<std::unique_ptr<KIFONT::GLYPH>> m_renderCache;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
if( Type() != aItem.Type() )
|
||||
|
|
|
@ -429,6 +429,8 @@ public:
|
|||
|
||||
virtual void RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction ) { }
|
||||
|
||||
virtual void ClearCaches();
|
||||
|
||||
/**
|
||||
* Check if this schematic item has line stoke properties.
|
||||
*
|
||||
|
|
|
@ -464,7 +464,7 @@ void SCH_PAINTER::boxText( const wxString& aText, const VECTOR2D& aPosition,
|
|||
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 );
|
||||
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 )
|
||||
{
|
||||
bbox.RevertYAxis();
|
||||
m_gal->SetIsStroke( true );
|
||||
m_gal->SetIsFill( true );
|
||||
m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
|
||||
m_gal->DrawRectangle( mapCoords( bbox.GetPosition() ), mapCoords( bbox.GetEnd() ) );
|
||||
m_gal->DrawRectangle( bbox.GetPosition(), bbox.GetEnd() );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -765,18 +764,27 @@ void SCH_PAINTER::draw( const LIB_TEXT *aText, int aLayer )
|
|||
}
|
||||
|
||||
EDA_RECT bBox = aText->GetBoundingBox();
|
||||
bBox.RevertYAxis();
|
||||
VECTOR2D pos = mapCoords( bBox.Centre() );
|
||||
VECTOR2D pos = bBox.Centre();
|
||||
|
||||
m_gal->SetFillColor( color );
|
||||
m_gal->SetStrokeColor( color );
|
||||
|
||||
TEXT_ATTRIBUTES attrs( aText->GetAttributes() );
|
||||
attrs.m_Halign = GR_TEXT_H_ALIGN_CENTER;
|
||||
attrs.m_Valign = GR_TEXT_V_ALIGN_CENTER;
|
||||
attrs.m_StrokeWidth = getTextThickness( aText, drawingShadows );
|
||||
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() );
|
||||
attrs.m_Halign = GR_TEXT_H_ALIGN_CENTER;
|
||||
attrs.m_Valign = GR_TEXT_V_ALIGN_CENTER;
|
||||
attrs.m_StrokeWidth = getTextThickness( aText, drawingShadows );
|
||||
|
||||
strokeText( aText->GetText(), pos, attrs );
|
||||
strokeText( aText->GetText(), pos, attrs );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1477,7 +1485,6 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
|
|||
if( drawingShadows && eeconfig()->m_Selection.text_as_box )
|
||||
{
|
||||
EDA_RECT bBox = aText->GetBoundingBox();
|
||||
bBox.Offset( text_offset.x, text_offset.y );
|
||||
bBox.RevertYAxis();
|
||||
m_gal->SetIsStroke( true );
|
||||
m_gal->SetIsFill( true );
|
||||
|
@ -1503,7 +1510,7 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
|
|||
}
|
||||
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
|
||||
{
|
||||
wxString shownText = aField->GetShownText();
|
||||
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_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
|
||||
|
|
|
@ -1049,7 +1049,10 @@ const EDA_RECT SCH_LABEL_BASE::GetBoundingBox() const
|
|||
EDA_RECT box( GetBodyBoundingBox() );
|
||||
|
||||
for( const SCH_FIELD& field : m_fields )
|
||||
box.Merge( field.GetBoundingBox() );
|
||||
{
|
||||
if( field.IsVisible() )
|
||||
box.Merge( field.GetBoundingBox() );
|
||||
}
|
||||
|
||||
box.Normalize();
|
||||
|
||||
|
|
|
@ -1165,6 +1165,8 @@ void SYMBOL_EDIT_FRAME::HardRedraw()
|
|||
else
|
||||
item.SetSelected();
|
||||
}
|
||||
|
||||
m_symbol->ClearCaches();
|
||||
}
|
||||
|
||||
RebuildView();
|
||||
|
@ -1482,3 +1484,15 @@ bool SYMBOL_EDIT_FRAME::IsSymbolEditable() const
|
|||
{
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -323,6 +323,9 @@ public:
|
|||
|
||||
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.
|
||||
*/
|
||||
|
|
|
@ -342,7 +342,8 @@ public:
|
|||
virtual GR_TEXT_H_ALIGN_T GetDrawHorizJustify() const { return GetHorizJustify(); };
|
||||
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>>*
|
||||
GetRenderCache( const wxString& forResolvedText ) const;
|
||||
|
@ -369,16 +370,19 @@ private:
|
|||
const COLOR4D& aColor, OUTLINE_MODE aFillMode, const wxString& aText,
|
||||
const VECTOR2I& aPos );
|
||||
|
||||
wxString m_text;
|
||||
wxString m_shown_text; // Cache of unescaped text for efficient access
|
||||
bool m_shown_text_has_text_var_refs;
|
||||
wxString m_text;
|
||||
wxString m_shown_text; // Cache of unescaped text for efficient access
|
||||
bool m_shown_text_has_text_var_refs;
|
||||
|
||||
mutable wxString m_render_cache_text;
|
||||
mutable EDA_ANGLE m_render_cache_angle;
|
||||
mutable std::vector<std::unique_ptr<KIFONT::GLYPH>> m_render_cache;
|
||||
|
||||
TEXT_ATTRIBUTES m_attributes;
|
||||
VECTOR2I m_pos;
|
||||
mutable bool m_bounding_box_cache_valid;
|
||||
mutable EDA_RECT m_bounding_box_cache;
|
||||
|
||||
TEXT_ATTRIBUTES m_attributes;
|
||||
VECTOR2I m_pos;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -122,15 +122,14 @@ public:
|
|||
* @param aCursor is the current text position (for multiple text blocks within a single text
|
||||
* object, such as a run of superscript characters)
|
||||
* @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,
|
||||
const VECTOR2I& aCursor, const TEXT_ATTRIBUTES& aAttrs ) const;
|
||||
void Draw( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition,
|
||||
const VECTOR2I& aCursor, const TEXT_ATTRIBUTES& aAttrs ) const;
|
||||
|
||||
VECTOR2D Draw( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition,
|
||||
const TEXT_ATTRIBUTES& aAttributes ) const
|
||||
void Draw( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition,
|
||||
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,
|
||||
|
@ -141,7 +140,7 @@ public:
|
|||
*
|
||||
* @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;
|
||||
|
||||
/**
|
||||
|
@ -170,7 +169,7 @@ public:
|
|||
* @param aTextStyle text style flags
|
||||
* @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 VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
|
||||
bool aMirror, const VECTOR2I& aOrigin,
|
||||
|
@ -206,10 +205,10 @@ protected:
|
|||
* @param aOrigin is the point around which the text should be rotated, mirrored, etc.
|
||||
* @return new cursor position in non-rotated, non-mirrored coordinates
|
||||
*/
|
||||
VECTOR2D drawSingleLineText( KIGFX::GAL* aGal, BOX2I* aBoundingBox, const UTF8& aText,
|
||||
const VECTOR2I& aPosition, const VECTOR2D& aSize,
|
||||
const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
|
||||
bool aItalic ) const;
|
||||
void drawSingleLineText( KIGFX::GAL* aGal, BOX2I* aBoundingBox, const UTF8& aText,
|
||||
const VECTOR2I& aPosition, const VECTOR2D& aSize,
|
||||
const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
|
||||
bool aItalic ) const;
|
||||
|
||||
/**
|
||||
* Computes the bounding box for a single line of text.
|
||||
|
@ -221,15 +220,14 @@ protected:
|
|||
* @param aSize is the cap-height and em-width of the text.
|
||||
* @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;
|
||||
|
||||
void getLinePositions( const UTF8& aText, const VECTOR2I& aPosition,
|
||||
wxArrayString& aTextLines, std::vector<VECTOR2I>& aPositions,
|
||||
std::vector<VECTOR2D>& aBoundingBoxes,
|
||||
const TEXT_ATTRIBUTES& aAttributes ) const;
|
||||
std::vector<VECTOR2I>& aExtents, const TEXT_ATTRIBUTES& aAttrs ) 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 EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
|
||||
TEXT_STYLE_FLAGS aTextStyle ) const;
|
||||
|
@ -240,9 +238,6 @@ protected:
|
|||
private:
|
||||
static FONT* getDefaultFont();
|
||||
|
||||
VECTOR2D doDrawString( KIGFX::GAL* aGal, const UTF8& aText, const VECTOR2I& aPosition,
|
||||
bool aParse, const TEXT_ATTRIBUTES& aAttrs ) const;
|
||||
|
||||
protected:
|
||||
wxString m_fontName; ///< Font name
|
||||
wxString m_fontFileName; ///< Font file name
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
#include <geometry/shape_poly_set.h>
|
||||
#include <wx/debug.h>
|
||||
|
||||
typedef std::function<void( int, const VECTOR2I& aPoint1, const VECTOR2I& aPoint2,
|
||||
const VECTOR2I& aPoint3 )>
|
||||
TRIANGULATE_CALLBACK;
|
||||
|
||||
namespace KIFONT
|
||||
{
|
||||
class GLYPH
|
||||
|
@ -64,6 +68,8 @@ public:
|
|||
bool IsOutline() const override { return true; }
|
||||
|
||||
BOX2D BoundingBox() override;
|
||||
|
||||
void Triangulate( TRIANGULATE_CALLBACK aCallback ) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ public:
|
|||
*/
|
||||
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 EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
|
||||
TEXT_STYLE_FLAGS aTextStyle ) const override;
|
||||
|
@ -106,8 +106,11 @@ public:
|
|||
* @param aGlyphs returns text glyphs
|
||||
* @param aText the text item
|
||||
*/
|
||||
VECTOR2I GetLinesAsGlyphs( std::vector<std::unique_ptr<GLYPH>>& aGlyphs,
|
||||
const EDA_TEXT* aText ) const;
|
||||
void GetLinesAsGlyphs( std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
|
||||
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; }
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public:
|
|||
*/
|
||||
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 EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
|
||||
TEXT_STYLE_FLAGS aTextStyle ) const override;
|
||||
|
|
|
@ -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
|
|
@ -524,8 +524,6 @@ private:
|
|||
|
||||
VECTOR2D getScreenPixelSize() const;
|
||||
|
||||
void fillPolygonAsTriangles( const SHAPE_POLY_SET& aPolyList );
|
||||
|
||||
/**
|
||||
* Basic OpenGL initialization and feature checks.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue