Markup fixes.
1) allow escape sequences inside markup sequences 2) keep overbar when inside nested markup 3) always place overbar at full height, not sub/superscript height Fixes https://gitlab.com/kicad/code/kicad/issues/14553 Fixes https://gitlab.com/kicad/code/kicad/issues/13449
This commit is contained in:
parent
9b58f50c68
commit
7e5fedef6a
|
@ -37,6 +37,7 @@
|
||||||
#include <callback_gal.h>
|
#include <callback_gal.h>
|
||||||
#include <eda_text.h> // for EDA_TEXT, TEXT_EFFECTS, GR_TEXT_VJUSTIF...
|
#include <eda_text.h> // for EDA_TEXT, TEXT_EFFECTS, GR_TEXT_VJUSTIF...
|
||||||
#include <gal/color4d.h> // for COLOR4D, COLOR4D::BLACK
|
#include <gal/color4d.h> // for COLOR4D, COLOR4D::BLACK
|
||||||
|
#include <font/glyph.h>
|
||||||
#include <gr_text.h>
|
#include <gr_text.h>
|
||||||
#include <string_utils.h> // for UnescapeString
|
#include <string_utils.h> // for UnescapeString
|
||||||
#include <math/util.h> // for KiROUND
|
#include <math/util.h> // for KiROUND
|
||||||
|
@ -119,8 +120,10 @@ EDA_TEXT::EDA_TEXT( const EDA_TEXT& aText ) :
|
||||||
|
|
||||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aText.m_render_cache )
|
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aText.m_render_cache )
|
||||||
{
|
{
|
||||||
KIFONT::OUTLINE_GLYPH* outline_glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() );
|
if( KIFONT::OUTLINE_GLYPH* outline = dynamic_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 ) );
|
||||||
|
else if( KIFONT::STROKE_GLYPH* stroke = dynamic_cast<KIFONT::STROKE_GLYPH*>( glyph.get() ) )
|
||||||
|
m_render_cache.emplace_back( std::make_unique<KIFONT::STROKE_GLYPH>( *stroke ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_bounding_box_cache_valid = aText.m_bounding_box_cache_valid;
|
m_bounding_box_cache_valid = aText.m_bounding_box_cache_valid;
|
||||||
|
@ -151,8 +154,10 @@ EDA_TEXT& EDA_TEXT::operator=( const EDA_TEXT& aText )
|
||||||
|
|
||||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aText.m_render_cache )
|
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aText.m_render_cache )
|
||||||
{
|
{
|
||||||
KIFONT::OUTLINE_GLYPH* outline_glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() );
|
if( KIFONT::OUTLINE_GLYPH* outline = dynamic_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 ) );
|
||||||
|
else if( KIFONT::STROKE_GLYPH* stroke = dynamic_cast<KIFONT::STROKE_GLYPH*>( glyph.get() ) )
|
||||||
|
m_render_cache.emplace_back( std::make_unique<KIFONT::STROKE_GLYPH>( *stroke ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_bounding_box_cache_valid = aText.m_bounding_box_cache_valid;
|
m_bounding_box_cache_valid = aText.m_bounding_box_cache_valid;
|
||||||
|
@ -393,7 +398,12 @@ 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 );
|
{
|
||||||
|
if( KIFONT::OUTLINE_GLYPH* outline = dynamic_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() ) )
|
||||||
|
outline->Move( aOffset );
|
||||||
|
else if( KIFONT::STROKE_GLYPH* stroke = dynamic_cast<KIFONT::STROKE_GLYPH*>( glyph.get() ) )
|
||||||
|
glyph = stroke->Transform( { 1.0, 1.0 }, aOffset, 0, ANGLE_0, false, { 0, 0 } );
|
||||||
|
}
|
||||||
|
|
||||||
m_bounding_box_cache_valid = false;
|
m_bounding_box_cache_valid = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2021 Ola Rinta-Koski
|
* Copyright (C) 2021 Ola Rinta-Koski
|
||||||
* Copyright (C) 2021-2022 Kicad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2021-2023 Kicad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* Font abstract base class
|
* Font abstract base class
|
||||||
*
|
*
|
||||||
|
@ -264,6 +264,8 @@ VECTOR2I drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* a
|
||||||
bool aMirror, const VECTOR2I& aOrigin, TEXT_STYLE_FLAGS aTextStyle )
|
bool aMirror, const VECTOR2I& aOrigin, TEXT_STYLE_FLAGS aTextStyle )
|
||||||
{
|
{
|
||||||
VECTOR2I nextPosition = aPosition;
|
VECTOR2I nextPosition = aPosition;
|
||||||
|
bool drawUnderline = false;
|
||||||
|
bool drawOverbar = false;
|
||||||
|
|
||||||
if( aNode )
|
if( aNode )
|
||||||
{
|
{
|
||||||
|
@ -272,12 +274,12 @@ VECTOR2I drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* a
|
||||||
if( !aNode->is_root() )
|
if( !aNode->is_root() )
|
||||||
{
|
{
|
||||||
if( aNode->isSubscript() )
|
if( aNode->isSubscript() )
|
||||||
textStyle = TEXT_STYLE::SUBSCRIPT;
|
textStyle |= TEXT_STYLE::SUBSCRIPT;
|
||||||
else if( aNode->isSuperscript() )
|
else if( aNode->isSuperscript() )
|
||||||
textStyle = TEXT_STYLE::SUPERSCRIPT;
|
textStyle |= TEXT_STYLE::SUPERSCRIPT;
|
||||||
|
|
||||||
if( aNode->isOverbar() )
|
if( aNode->isOverbar() )
|
||||||
textStyle |= TEXT_STYLE::OVERBAR;
|
drawOverbar = true;
|
||||||
|
|
||||||
if( aNode->has_content() )
|
if( aNode->has_content() )
|
||||||
{
|
{
|
||||||
|
@ -291,6 +293,10 @@ VECTOR2I drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* a
|
||||||
aBoundingBox->Merge( bbox );
|
aBoundingBox->Merge( bbox );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if( aTextStyle & TEXT_STYLE::UNDERLINE )
|
||||||
|
{
|
||||||
|
drawUnderline = true;
|
||||||
|
}
|
||||||
|
|
||||||
for( const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
|
for( const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
|
||||||
{
|
{
|
||||||
|
@ -299,6 +305,50 @@ VECTOR2I drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( drawUnderline )
|
||||||
|
{
|
||||||
|
// Shorten the bar a little so its rounded ends don't make it over-long
|
||||||
|
double barTrim = aSize.x * 0.1;
|
||||||
|
double barOffset = aFont->ComputeUnderlineVerticalPosition( aSize.y );
|
||||||
|
|
||||||
|
VECTOR2D barStart( aPosition.x + barTrim, aPosition.y - barOffset );
|
||||||
|
VECTOR2D barEnd( nextPosition.x - barTrim, nextPosition.y - barOffset );
|
||||||
|
|
||||||
|
if( aGlyphs )
|
||||||
|
{
|
||||||
|
STROKE_GLYPH barGlyph;
|
||||||
|
|
||||||
|
barGlyph.AddPoint( barStart );
|
||||||
|
barGlyph.AddPoint( barEnd );
|
||||||
|
barGlyph.Finalize();
|
||||||
|
|
||||||
|
aGlyphs->push_back( barGlyph.Transform( { 1.0, 1.0 }, { 0, 0 }, false, aAngle, aMirror,
|
||||||
|
aOrigin ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( drawOverbar )
|
||||||
|
{
|
||||||
|
// Shorten the bar a little so its rounded ends don't make it over-long
|
||||||
|
double barTrim = aSize.x * 0.1;
|
||||||
|
double barOffset = aFont->ComputeOverbarVerticalPosition( aSize.y );
|
||||||
|
|
||||||
|
VECTOR2D barStart( aPosition.x + barTrim, aPosition.y - barOffset );
|
||||||
|
VECTOR2D barEnd( nextPosition.x - barTrim, nextPosition.y - barOffset );
|
||||||
|
|
||||||
|
if( aGlyphs )
|
||||||
|
{
|
||||||
|
STROKE_GLYPH barGlyph;
|
||||||
|
|
||||||
|
barGlyph.AddPoint( barStart );
|
||||||
|
barGlyph.AddPoint( barEnd );
|
||||||
|
barGlyph.Finalize();
|
||||||
|
|
||||||
|
aGlyphs->push_back( barGlyph.Transform( { 1.0, 1.0 }, { 0, 0 }, false, aAngle, aMirror,
|
||||||
|
aOrigin ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nextPosition;
|
return nextPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2021 Ola Rinta-Koski <gitlab@rinta-koski.net>
|
* Copyright (C) 2021 Ola Rinta-Koski <gitlab@rinta-koski.net>
|
||||||
* Copyright (C) 2021-2022 Kicad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2021-2023 Kicad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* Outline font class
|
* Outline font class
|
||||||
*
|
*
|
||||||
|
@ -313,22 +313,6 @@ VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double OUTLINE_FONT::getOverbarOffset( int ascender, int height, int thickness ) const
|
|
||||||
{
|
|
||||||
double thicknessRatio = abs( (double) thickness ) / (double) height;
|
|
||||||
double ascenderRatio = (double) ascender / (double) height;
|
|
||||||
|
|
||||||
if( thicknessRatio < 0.05 )
|
|
||||||
return 0.04;
|
|
||||||
else if( ascenderRatio < 0.78 )
|
|
||||||
return 0.00;
|
|
||||||
else if( ascenderRatio < 0.80 )
|
|
||||||
return -0.03;
|
|
||||||
else
|
|
||||||
return -0.06;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 wxString& aText, const VECTOR2I& aSize,
|
const wxString& aText, const VECTOR2I& aSize,
|
||||||
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
|
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
|
||||||
|
@ -338,14 +322,15 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
||||||
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
|
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
|
||||||
|
|
||||||
return getTextAsGlyphsUnlocked( aBBox, aGlyphs, aText, aSize, aPosition, aAngle, aMirror,
|
return getTextAsGlyphsUnlocked( aBBox, aGlyphs, aText, aSize, aPosition, aAngle, aMirror,
|
||||||
aOrigin, aTextStyle );
|
aOrigin, aTextStyle );
|
||||||
}
|
}
|
||||||
|
|
||||||
VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
|
VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
||||||
const wxString& aText, const VECTOR2I& aSize,
|
std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
|
||||||
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
|
const wxString& aText, const VECTOR2I& aSize,
|
||||||
bool aMirror, const VECTOR2I& aOrigin,
|
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
|
||||||
TEXT_STYLE_FLAGS aTextStyle ) const
|
bool aMirror, const VECTOR2I& aOrigin,
|
||||||
|
TEXT_STYLE_FLAGS aTextStyle ) const
|
||||||
{
|
{
|
||||||
VECTOR2D glyphSize = aSize;
|
VECTOR2D glyphSize = aSize;
|
||||||
FT_Face face = m_face;
|
FT_Face face = m_face;
|
||||||
|
@ -478,75 +463,9 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox, std::vector<std::u
|
||||||
}
|
}
|
||||||
|
|
||||||
int ascender = abs( face->size->metrics.ascender * GLYPH_SIZE_SCALER );
|
int ascender = abs( face->size->metrics.ascender * GLYPH_SIZE_SCALER );
|
||||||
int height = abs( face->size->metrics.height * GLYPH_SIZE_SCALER );
|
|
||||||
int descender = abs( face->size->metrics.descender * GLYPH_SIZE_SCALER );
|
int descender = abs( face->size->metrics.descender * GLYPH_SIZE_SCALER );
|
||||||
VECTOR2I extents( cursor.x * scaleFactor.x, ( ascender + descender ) * abs( scaleFactor.y ) );
|
VECTOR2I extents( cursor.x * scaleFactor.x, ( ascender + descender ) * abs( scaleFactor.y ) );
|
||||||
|
|
||||||
// Font metrics don't include all descenders and diacriticals, so beef them up just a little.
|
|
||||||
extents.y *= 1.05;
|
|
||||||
|
|
||||||
if( IsOverbar( aTextStyle ) )
|
|
||||||
{
|
|
||||||
std::vector<std::unique_ptr<GLYPH>> underscoreGlyphs;
|
|
||||||
|
|
||||||
getTextAsGlyphsUnlocked( nullptr, &underscoreGlyphs, wxT( "_" ), aSize, { 0, 0 }, ANGLE_0, false,
|
|
||||||
{ 0, 0 }, aTextStyle & ~TEXT_STYLE::OVERBAR );
|
|
||||||
|
|
||||||
OUTLINE_GLYPH* underscoreGlyph = static_cast<OUTLINE_GLYPH*>( underscoreGlyphs[0].get() );
|
|
||||||
BOX2I underscoreBBox;
|
|
||||||
|
|
||||||
for( const VECTOR2I& pt : underscoreGlyph->Outline( 0 ).CPoints() )
|
|
||||||
underscoreBBox.Merge( pt );
|
|
||||||
|
|
||||||
int barThickness = underscoreBBox.GetHeight();
|
|
||||||
|
|
||||||
// Shorten the bar a little so its rounded ends don't make it over-long
|
|
||||||
double barTrim = barThickness / 2.0;
|
|
||||||
double barOffset = getOverbarOffset( ascender, height, barThickness / scaleFactor.y );
|
|
||||||
|
|
||||||
VECTOR2I topLeft( aPosition );
|
|
||||||
VECTOR2I topRight( aPosition );
|
|
||||||
|
|
||||||
topLeft.y += ascender * scaleFactor.y * ( 1.0 + barOffset );
|
|
||||||
topRight.y = topLeft.y;
|
|
||||||
|
|
||||||
topLeft.x += barTrim;
|
|
||||||
topRight.x += extents.x - barTrim;
|
|
||||||
|
|
||||||
extents.y *= ( 1.0 + barOffset + barOffset );
|
|
||||||
extents.x += barTrim;
|
|
||||||
|
|
||||||
if( IsItalic() )
|
|
||||||
{
|
|
||||||
topLeft.x += aSize.y * ITALIC_TILT;
|
|
||||||
topRight.x += aSize.y * ITALIC_TILT;
|
|
||||||
extents.x += aSize.y * ITALIC_TILT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( aMirror )
|
|
||||||
{
|
|
||||||
topLeft.x = aOrigin.x - ( topLeft.x - aOrigin.x );
|
|
||||||
topRight.x = aOrigin.x - ( topRight.x - aOrigin.x );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !aAngle.IsZero() )
|
|
||||||
{
|
|
||||||
RotatePoint( topLeft, aOrigin, aAngle );
|
|
||||||
RotatePoint( topRight, aOrigin, aAngle );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( aGlyphs )
|
|
||||||
{
|
|
||||||
int maxError = KiROUND( barThickness / 48 );
|
|
||||||
SHAPE_POLY_SET poly;
|
|
||||||
|
|
||||||
TransformOvalToPolygon( poly, topLeft, topRight, barThickness, maxError, ERROR_INSIDE );
|
|
||||||
|
|
||||||
std::unique_ptr<OUTLINE_GLYPH> overbarGlyph = std::make_unique<OUTLINE_GLYPH>( poly );
|
|
||||||
aGlyphs->push_back( std::move( overbarGlyph ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_buffer_destroy( buf );
|
hb_buffer_destroy( buf );
|
||||||
hb_font_destroy( referencedFont );
|
hb_font_destroy( referencedFont );
|
||||||
|
|
||||||
|
@ -575,7 +494,7 @@ void OUTLINE_FONT::RenderToOpenGLCanvas( KIGFX::OPENGL_GAL& aGal, const wxString
|
||||||
unsigned int glyphCount;
|
unsigned int glyphCount;
|
||||||
hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos( buf, &glyphCount );
|
hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos( buf, &glyphCount );
|
||||||
hb_glyph_position_t* glyphPos = hb_buffer_get_glyph_positions( buf, &glyphCount );
|
hb_glyph_position_t* glyphPos = hb_buffer_get_glyph_positions( buf, &glyphCount );
|
||||||
|
|
||||||
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
|
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
|
||||||
|
|
||||||
hb_font_t* referencedFont = hb_ft_font_create_referenced( m_face );
|
hb_font_t* referencedFont = hb_ft_font_create_referenced( m_face );
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
|
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
|
||||||
* Copyright (C) 2013 CERN
|
* Copyright (C) 2013 CERN
|
||||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
* Copyright (C) 2016-2022 Kicad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2016-2023 Kicad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* Stroke font class
|
* Stroke font class
|
||||||
*
|
*
|
||||||
|
@ -128,7 +128,6 @@ void STROKE_FONT::loadNewStrokeFont( const char* const aNewStrokeFont[], int aNe
|
||||||
|
|
||||||
while( aNewStrokeFont[j][i] )
|
while( aNewStrokeFont[j][i] )
|
||||||
{
|
{
|
||||||
|
|
||||||
if( aNewStrokeFont[j][i] == ' ' && aNewStrokeFont[j][i+1] == 'R' )
|
if( aNewStrokeFont[j][i] == ' ' && aNewStrokeFont[j][i+1] == 'R' )
|
||||||
strokes++;
|
strokes++;
|
||||||
|
|
||||||
|
@ -304,62 +303,10 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
|
||||||
++char_count;
|
++char_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
VECTOR2D barOffset( 0.0, 0.0 );
|
|
||||||
|
|
||||||
// Shorten the bar a little so its rounded ends don't make it over-long
|
|
||||||
double barTrim = glyphSize.x * 0.1;
|
|
||||||
|
|
||||||
if( aTextStyle & TEXT_STYLE::OVERBAR )
|
|
||||||
{
|
|
||||||
barOffset.y = ComputeOverbarVerticalPosition( glyphSize.y );
|
|
||||||
|
|
||||||
if( aTextStyle & TEXT_STYLE::ITALIC )
|
|
||||||
barOffset.x = barOffset.y * ITALIC_TILT;
|
|
||||||
|
|
||||||
VECTOR2D barStart( aPosition.x + barOffset.x + barTrim, cursor.y - barOffset.y );
|
|
||||||
VECTOR2D barEnd( cursor.x + barOffset.x - barTrim, cursor.y - barOffset.y );
|
|
||||||
|
|
||||||
if( aGlyphs )
|
|
||||||
{
|
|
||||||
STROKE_GLYPH overbarGlyph;
|
|
||||||
|
|
||||||
overbarGlyph.AddPoint( barStart );
|
|
||||||
overbarGlyph.AddPoint( barEnd );
|
|
||||||
overbarGlyph.Finalize();
|
|
||||||
|
|
||||||
aGlyphs->push_back( overbarGlyph.Transform( { 1.0, 1.0 }, { 0, 0 }, false,
|
|
||||||
aAngle, aMirror, aOrigin ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( aTextStyle & TEXT_STYLE::UNDERLINE )
|
|
||||||
{
|
|
||||||
barOffset.y = ComputeUnderlineVerticalPosition( glyphSize.y );
|
|
||||||
|
|
||||||
if( aTextStyle & TEXT_STYLE::ITALIC )
|
|
||||||
barOffset.x = barOffset.y * ITALIC_TILT;
|
|
||||||
|
|
||||||
VECTOR2D barStart( aPosition.x + barOffset.x + barTrim, cursor.y - barOffset.y );
|
|
||||||
VECTOR2D barEnd( cursor.x + barOffset.x - barTrim, cursor.y - barOffset.y );
|
|
||||||
|
|
||||||
if( aGlyphs )
|
|
||||||
{
|
|
||||||
STROKE_GLYPH underlineGlyph;
|
|
||||||
|
|
||||||
underlineGlyph.AddPoint( barStart );
|
|
||||||
underlineGlyph.AddPoint( barEnd );
|
|
||||||
underlineGlyph.Finalize();
|
|
||||||
|
|
||||||
aGlyphs->push_back( underlineGlyph.Transform( { 1.0, 1.0 }, { 0, 0 }, false,
|
|
||||||
aAngle, aMirror, aOrigin ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( aBBox )
|
if( aBBox )
|
||||||
{
|
{
|
||||||
aBBox->SetOrigin( aPosition );
|
aBBox->SetOrigin( aPosition );
|
||||||
aBBox->SetEnd( cursor.x + barOffset.x - KiROUND( glyphSize.x * INTER_CHAR ),
|
aBBox->SetEnd( cursor.x - KiROUND( glyphSize.x * INTER_CHAR ), cursor.y + glyphSize.y );
|
||||||
cursor.y + std::max( glyphSize.y, barOffset.y * OVERBAR_POSITION_FACTOR ) );
|
|
||||||
aBBox->Normalize();
|
aBBox->Normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2004-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2004-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -280,42 +280,49 @@ wxString UnescapeString( const wxString& aSource )
|
||||||
wxString newbuf;
|
wxString newbuf;
|
||||||
newbuf.reserve( sourceLen );
|
newbuf.reserve( sourceLen );
|
||||||
|
|
||||||
|
wxUniChar prev = 0;
|
||||||
|
wxUniChar ch = 0;
|
||||||
|
|
||||||
for( size_t i = 0; i < sourceLen; ++i )
|
for( size_t i = 0; i < sourceLen; ++i )
|
||||||
{
|
{
|
||||||
wxUniChar ch = aSource[i];
|
prev = ch;
|
||||||
|
ch = aSource[i];
|
||||||
|
|
||||||
if( ( ch == '$' || ch == '~' || ch == '^' || ch == '_' )
|
if( ch == '{' )
|
||||||
&& i + 1 < sourceLen && aSource[i+1] == '{' )
|
|
||||||
{
|
|
||||||
for( ; i < sourceLen; ++i )
|
|
||||||
{
|
|
||||||
ch = aSource[i];
|
|
||||||
newbuf += ch;
|
|
||||||
|
|
||||||
if( ch == '}' )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( ch == '{' )
|
|
||||||
{
|
{
|
||||||
wxString token;
|
wxString token;
|
||||||
int depth = 1;
|
int depth = 1;
|
||||||
|
bool terminated = false;
|
||||||
|
|
||||||
for( i = i + 1; i < sourceLen; ++i )
|
for( i = i + 1; i < sourceLen; ++i )
|
||||||
{
|
{
|
||||||
ch = aSource[i];
|
ch = aSource[i];
|
||||||
|
|
||||||
if( ch == '{' )
|
if( ch == '{' )
|
||||||
depth++;
|
depth++;
|
||||||
else if( ch == '}' )
|
else if( ch == '}' )
|
||||||
depth--;
|
depth--;
|
||||||
|
|
||||||
if( depth <= 0 )
|
if( depth <= 0 )
|
||||||
|
{
|
||||||
|
terminated = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
token.append( ch );
|
token.append( ch );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( token == wxT( "dblquote" ) ) newbuf.append( wxT( "\"" ) );
|
if( !terminated )
|
||||||
|
{
|
||||||
|
newbuf.append( wxT( "{" ) + UnescapeString( token ) );
|
||||||
|
}
|
||||||
|
else if( prev == '$' || prev == '~' || prev == '^' || prev == '_' )
|
||||||
|
{
|
||||||
|
newbuf.append( wxT( "{" ) + UnescapeString( token ) + wxT( "}" ) );
|
||||||
|
}
|
||||||
|
else if( token == wxT( "dblquote" ) ) newbuf.append( wxT( "\"" ) );
|
||||||
else if( token == wxT( "quote" ) ) newbuf.append( wxT( "'" ) );
|
else if( token == wxT( "quote" ) ) newbuf.append( wxT( "'" ) );
|
||||||
else if( token == wxT( "lt" ) ) newbuf.append( wxT( "<" ) );
|
else if( token == wxT( "lt" ) ) newbuf.append( wxT( "<" ) );
|
||||||
else if( token == wxT( "gt" ) ) newbuf.append( wxT( ">" ) );
|
else if( token == wxT( "gt" ) ) newbuf.append( wxT( ">" ) );
|
||||||
|
@ -329,7 +336,6 @@ wxString UnescapeString( const wxString& aSource )
|
||||||
else if( token == wxT( "tab" ) ) newbuf.append( wxT( "\t" ) );
|
else if( token == wxT( "tab" ) ) newbuf.append( wxT( "\t" ) );
|
||||||
else if( token == wxT( "return" ) ) newbuf.append( wxT( "\n" ) );
|
else if( token == wxT( "return" ) ) newbuf.append( wxT( "\n" ) );
|
||||||
else if( token == wxT( "brace" ) ) newbuf.append( wxT( "{" ) );
|
else if( token == wxT( "brace" ) ) newbuf.append( wxT( "{" ) );
|
||||||
else if( token.IsEmpty() ) newbuf.append( wxT( "{" ) );
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newbuf.append( wxT( "{" ) + UnescapeString( token ) + wxT( "}" ) );
|
newbuf.append( wxT( "{" ) + UnescapeString( token ) + wxT( "}" ) );
|
||||||
|
|
|
@ -2154,8 +2154,8 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
|
||||||
|
|
||||||
if( cache )
|
if( cache )
|
||||||
{
|
{
|
||||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
|
m_gal->SetLineWidth( attrs.m_StrokeWidth );
|
||||||
m_gal->DrawGlyph( *glyph );
|
m_gal->DrawGlyphs( *cache );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2205,8 +2205,8 @@ void SCH_PAINTER::draw( const SCH_TEXTBOX* aTextBox, int aLayer )
|
||||||
|
|
||||||
if( cache )
|
if( cache )
|
||||||
{
|
{
|
||||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
|
m_gal->SetLineWidth( attrs.m_StrokeWidth );
|
||||||
m_gal->DrawGlyph( *glyph );
|
m_gal->DrawGlyphs( *cache );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2583,8 +2583,8 @@ void SCH_PAINTER::draw( const SCH_FIELD* aField, int aLayer, bool aDimmed )
|
||||||
|
|
||||||
if( cache )
|
if( cache )
|
||||||
{
|
{
|
||||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
|
m_gal->SetLineWidth( attributes.m_StrokeWidth );
|
||||||
m_gal->DrawGlyph( *glyph );
|
m_gal->DrawGlyphs( *cache );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -126,8 +126,6 @@ public:
|
||||||
protected:
|
protected:
|
||||||
FT_Error loadFace( const wxString& aFontFileName, int aFaceIndex );
|
FT_Error loadFace( const wxString& aFontFileName, int aFaceIndex );
|
||||||
|
|
||||||
double getOverbarOffset( int ascender, int height, int thickness ) const;
|
|
||||||
|
|
||||||
BOX2I getBoundingBox( const std::vector<std::unique_ptr<GLYPH>>& aGlyphs ) const;
|
BOX2I getBoundingBox( const std::vector<std::unique_ptr<GLYPH>>& aGlyphs ) const;
|
||||||
|
|
||||||
VECTOR2I getTextAsGlyphs( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
|
VECTOR2I getTextAsGlyphs( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
|
||||||
|
@ -136,10 +134,12 @@ protected:
|
||||||
const VECTOR2I& aOrigin, TEXT_STYLE_FLAGS aTextStyle ) const;
|
const VECTOR2I& aOrigin, TEXT_STYLE_FLAGS aTextStyle ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VECTOR2I getTextAsGlyphsUnlocked( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
|
VECTOR2I getTextAsGlyphsUnlocked( BOX2I* aBoundingBox,
|
||||||
const wxString& aText, const VECTOR2I& aSize,
|
std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
|
||||||
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle, bool aMirror,
|
const wxString& aText, const VECTOR2I& aSize,
|
||||||
const VECTOR2I& aOrigin, TEXT_STYLE_FLAGS aTextStyle ) const;
|
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
|
||||||
|
bool aMirror, const VECTOR2I& aOrigin,
|
||||||
|
TEXT_STYLE_FLAGS aTextStyle ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// FreeType variables
|
// FreeType variables
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2021 Ola Rinta-Koski
|
* Copyright (C) 2021 Ola Rinta-Koski
|
||||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* 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
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
@ -61,19 +61,25 @@ struct markup : sor< subscript,
|
||||||
struct anyString : plus< seq< not_at< markup >,
|
struct anyString : plus< seq< not_at< markup >,
|
||||||
utf8::any > > {};
|
utf8::any > > {};
|
||||||
|
|
||||||
struct anyStringWithinBraces : plus< seq< not_at< markup >,
|
struct escapeSequence : seq< string<'{'>, identifier, string<'}'> > {};
|
||||||
utf8::not_one< '}' > > > {};
|
|
||||||
|
struct anyStringWithinBraces : plus< sor< seq< not_at< markup >,
|
||||||
|
escapeSequence >,
|
||||||
|
seq< not_at< markup >,
|
||||||
|
utf8::not_one<'}'> > > > {};
|
||||||
|
|
||||||
template< typename ControlChar >
|
template< typename ControlChar >
|
||||||
struct braces : seq< seq< ControlChar, string< '{' > >,
|
struct braces : seq< seq< ControlChar,
|
||||||
until< string< '}' >, sor< anyStringWithinBraces,
|
string<'{'> >,
|
||||||
subscript,
|
until< string<'}'>,
|
||||||
superscript,
|
sor< anyStringWithinBraces,
|
||||||
overbar > > > {};
|
subscript,
|
||||||
|
superscript,
|
||||||
|
overbar > > > {};
|
||||||
|
|
||||||
struct superscript : braces< string< '^' > > {};
|
struct superscript : braces< string<'^'> > {};
|
||||||
struct subscript : braces< string< '_' > > {};
|
struct subscript : braces< string<'_'> > {};
|
||||||
struct overbar : braces< string< '~' > > {};
|
struct overbar : braces< string<'~'> > {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finally, the full grammar
|
* Finally, the full grammar
|
||||||
|
|
|
@ -2003,9 +2003,14 @@ void PCB_PAINTER::draw( const PCB_TEXT* aText, int aLayer )
|
||||||
cache = aText->GetRenderCache( font, resolvedText );
|
cache = aText->GetRenderCache( font, resolvedText );
|
||||||
|
|
||||||
if( cache )
|
if( cache )
|
||||||
|
{
|
||||||
|
m_gal->SetLineWidth( attrs.m_StrokeWidth );
|
||||||
m_gal->DrawGlyphs( *cache );
|
m_gal->DrawGlyphs( *cache );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
strokeText( resolvedText, aText->GetTextPos(), attrs );
|
strokeText( resolvedText, aText->GetTextPos(), attrs );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2101,9 +2106,14 @@ void PCB_PAINTER::draw( const PCB_TEXTBOX* aTextBox, int aLayer )
|
||||||
cache = aTextBox->GetRenderCache( font, resolvedText );
|
cache = aTextBox->GetRenderCache( font, resolvedText );
|
||||||
|
|
||||||
if( cache )
|
if( cache )
|
||||||
|
{
|
||||||
|
m_gal->SetLineWidth( attrs.m_StrokeWidth );
|
||||||
m_gal->DrawGlyphs( *cache );
|
m_gal->DrawGlyphs( *cache );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
strokeText( resolvedText, aTextBox->GetDrawPos(), attrs );
|
strokeText( resolvedText, aTextBox->GetDrawPos(), attrs );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue