Overhaul the font metrics calcs for overbar, italics and bboxes.
This commit is contained in:
parent
624dc393bf
commit
5ce559176d
|
@ -544,6 +544,7 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
|
|||
bool bold = IsBold();
|
||||
bool italic = IsItalic();
|
||||
VECTOR2I extents = font->StringBoundaryLimits( text, fontSize, thickness, bold, italic );
|
||||
int overbarOffset = 0;
|
||||
|
||||
// Creates bounding box (rectangle) for horizontal, left and top justified text. The
|
||||
// bounding box will be moved later according to the actual text options
|
||||
|
@ -553,6 +554,9 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
|
|||
if( IsMultilineAllowed() && aLine > 0 && ( aLine < static_cast<int>( strings.GetCount() ) ) )
|
||||
pos.y -= KiROUND( aLine * font->GetInterline( fontSize.y ) );
|
||||
|
||||
if( text.Contains( wxT( "~{" ) ) )
|
||||
overbarOffset = extents.y / 14;
|
||||
|
||||
if( aInvertY )
|
||||
pos.y = -pos.y;
|
||||
|
||||
|
@ -575,34 +579,41 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
|
|||
|
||||
rect.SetSize( textsize );
|
||||
|
||||
/* Now, calculate the rect origin, according to text justification
|
||||
* At this point the rectangle origin is the text origin (m_Pos).
|
||||
* This is true only for left and top text justified texts (using top to bottom Y axis
|
||||
* orientation). and must be recalculated for others justifications
|
||||
* also, note the V justification is relative to the first line
|
||||
/*
|
||||
* At this point the rectangle origin is the text origin (m_Pos). This is correct only for
|
||||
* left and top justified, non-mirrored, non-overbarred texts. Recalculate for all others.
|
||||
*/
|
||||
int italicOffset = IsItalic() ? fontSize.y * ITALIC_TILT : 0;
|
||||
|
||||
switch( GetHorizJustify() )
|
||||
{
|
||||
case GR_TEXT_H_ALIGN_LEFT:
|
||||
if( IsMirrored() )
|
||||
rect.SetX( rect.GetX() - rect.GetWidth() );
|
||||
rect.SetX( rect.GetX() - ( rect.GetWidth() - italicOffset ) );
|
||||
break;
|
||||
|
||||
case GR_TEXT_H_ALIGN_CENTER:
|
||||
rect.SetX( rect.GetX() - rect.GetWidth() / 2 );
|
||||
rect.SetX( rect.GetX() - ( rect.GetWidth() - italicOffset ) / 2 );
|
||||
break;
|
||||
|
||||
case GR_TEXT_H_ALIGN_RIGHT:
|
||||
if( !IsMirrored() )
|
||||
rect.SetX( rect.GetX() - rect.GetWidth() );
|
||||
rect.SetX( rect.GetX() - ( rect.GetWidth() - italicOffset ) );
|
||||
break;
|
||||
}
|
||||
|
||||
switch( GetVertJustify() )
|
||||
{
|
||||
case GR_TEXT_V_ALIGN_TOP: break;
|
||||
case GR_TEXT_V_ALIGN_CENTER: rect.SetY( rect.GetY() - rect.GetHeight() / 2 ); break;
|
||||
case GR_TEXT_V_ALIGN_BOTTOM: rect.SetY( rect.GetY() - rect.GetHeight() ); break;
|
||||
case GR_TEXT_V_ALIGN_TOP:
|
||||
break;
|
||||
|
||||
case GR_TEXT_V_ALIGN_CENTER:
|
||||
rect.SetY( rect.GetY() - ( rect.GetHeight() + overbarOffset ) / 2 );
|
||||
break;
|
||||
|
||||
case GR_TEXT_V_ALIGN_BOTTOM:
|
||||
rect.SetY( rect.GetY() - ( rect.GetHeight() + overbarOffset ) );
|
||||
break;
|
||||
}
|
||||
|
||||
rect.Normalize(); // Make h and v sizes always >= 0
|
||||
|
@ -911,6 +922,11 @@ void EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( SHAPE_POLY_SET* aCorn
|
|||
|
||||
EDA_RECT rect = GetTextBox();
|
||||
|
||||
// TrueType bounding boxes aren't guaranteed to include all descenders, diacriticals, etc.
|
||||
// Since we use this for zone knockouts and DRC, we need something more accurate.
|
||||
if( GetDrawFont()->IsOutline() )
|
||||
rect = GetEffectiveTextShape()->BBox();
|
||||
|
||||
rect.Inflate( aClearanceValue );
|
||||
|
||||
corners[0].x = rect.GetOrigin().x;
|
||||
|
|
|
@ -248,8 +248,6 @@ VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
|||
scaleFactor = scaleFactor * m_outlineFontSizeCompensation;
|
||||
|
||||
VECTOR2I cursor( 0, 0 );
|
||||
VECTOR2D topLeft( INT_MAX * 1.0, -INT_MAX * 1.0 );
|
||||
VECTOR2D topRight( -INT_MAX * 1.0, -INT_MAX * 1.0 );
|
||||
|
||||
for( unsigned int i = 0; i < glyphCount; i++ )
|
||||
{
|
||||
|
@ -257,9 +255,8 @@ VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
|||
{
|
||||
FT_Load_Glyph( face, glyphInfo[i].codepoint, FT_LOAD_NO_BITMAP );
|
||||
|
||||
// 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 is a collection of all outlines in the glyph; for example the 'o' glyph
|
||||
// generally contains 2 contours, one for the glyph outline and one for the hole
|
||||
CONTOURS contours;
|
||||
|
||||
OUTLINE_DECOMPOSER decomposer( face->glyph->outline );
|
||||
|
@ -277,11 +274,6 @@ VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
|||
{
|
||||
VECTOR2D pt( v + cursor );
|
||||
|
||||
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 += m_subscriptVerticalOffset * scaler;
|
||||
else if( IsSuperscript( aTextStyle ) )
|
||||
|
@ -337,16 +329,36 @@ VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
|||
cursor.y += ( pos.y_advance * GLYPH_SIZE_SCALER );
|
||||
}
|
||||
|
||||
if( IsOverbar( aTextStyle ) && aGlyphs )
|
||||
int ascender = abs( face->size->metrics.ascender * GLYPH_SIZE_SCALER );
|
||||
int descender = abs( face->size->metrics.descender * GLYPH_SIZE_SCALER );
|
||||
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;
|
||||
|
||||
// Shorten the bar a little so its rounded ends don't make it over-long
|
||||
double barTrim = glyphSize.x * 0.125;
|
||||
|
||||
if( IsOverbar( aTextStyle ) )
|
||||
{
|
||||
topLeft *= scaleFactor;
|
||||
topRight *= scaleFactor;
|
||||
VECTOR2I topLeft( aPosition );
|
||||
VECTOR2I topRight( aPosition );
|
||||
|
||||
topLeft.y -= aSize.y * m_overbarOffset;
|
||||
topRight.y -= aSize.y * m_overbarOffset;
|
||||
topLeft.y += ascender * scaleFactor.y * ( 1.0 + m_overbarOffsetRatio );
|
||||
topRight.y += ascender * scaleFactor.y * ( 1.0 + m_overbarOffsetRatio );
|
||||
|
||||
topLeft += aPosition;
|
||||
topRight += aPosition;
|
||||
topLeft.x += barTrim;
|
||||
topRight.x += extents.x - barTrim;
|
||||
|
||||
extents.y *= ( 1.0 + m_overbarOffsetRatio + m_overbarOffsetRatio );
|
||||
extents.x += barTrim;
|
||||
|
||||
if( IsItalic() )
|
||||
{
|
||||
topLeft.x += aSize.y * ITALIC_TILT;
|
||||
topRight.x += aSize.y * ITALIC_TILT;
|
||||
extents.x += aSize.y * ITALIC_TILT;
|
||||
}
|
||||
|
||||
if( !aAngle.IsZero() )
|
||||
{
|
||||
|
@ -354,14 +366,21 @@ VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
|||
RotatePoint( topRight, aOrigin, aAngle );
|
||||
}
|
||||
|
||||
double overbarHeight = aSize.y * m_overbarHeightMultiplier;
|
||||
SHAPE_POLY_SET overbar;
|
||||
if( aGlyphs )
|
||||
{
|
||||
int thickness = abs( ascender * scaleFactor.y * m_overbarThicknessRatio );
|
||||
int maxError = KiROUND( thickness / 48 );
|
||||
|
||||
TransformOvalToPolygon( overbar, topLeft, topRight, overbarHeight, overbarHeight / 8,
|
||||
ERROR_INSIDE );
|
||||
if( IsBold() )
|
||||
thickness = KiROUND( thickness * 1.5 );
|
||||
|
||||
std::unique_ptr<OUTLINE_GLYPH> overbarGlyph = std::make_unique<OUTLINE_GLYPH>( overbar );
|
||||
aGlyphs->push_back( std::move( overbarGlyph ) );
|
||||
SHAPE_POLY_SET poly;
|
||||
|
||||
TransformOvalToPolygon( poly, topLeft, topRight, thickness, 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 );
|
||||
|
@ -371,7 +390,7 @@ VECTOR2I OUTLINE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
|||
if( aBBox )
|
||||
{
|
||||
aBBox->SetOrigin( aPosition.x, aPosition.y );
|
||||
aBBox->SetEnd( cursorDisplacement );
|
||||
aBBox->SetEnd( aPosition + extents );
|
||||
}
|
||||
|
||||
return VECTOR2I( aPosition.x + cursorDisplacement.x, aPosition.y + cursorDisplacement.y );
|
||||
|
|
|
@ -47,10 +47,6 @@ static constexpr double OVERBAR_POSITION_FACTOR = 1.33;
|
|||
///< Scale factor for a glyph
|
||||
static constexpr double STROKE_FONT_SCALE = 1.0 / 21.0;
|
||||
|
||||
///< Tilt factor for italic style (this is the scaling factor on dY relative coordinates to
|
||||
///< give a tilted shape)
|
||||
static constexpr double ITALIC_TILT = 1.0 / 8;
|
||||
|
||||
static constexpr int FONT_OFFSET = -10;
|
||||
|
||||
|
||||
|
@ -279,6 +275,9 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
|
|||
|
||||
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 );
|
||||
|
@ -286,8 +285,8 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
|
|||
if( aTextStyle & TEXT_STYLE::ITALIC )
|
||||
barOffset.x = barOffset.y * ITALIC_TILT;
|
||||
|
||||
VECTOR2D barStart( aPosition.x + barOffset.x, cursor.y - barOffset.y );
|
||||
VECTOR2D barEnd( cursor.x + barOffset.x, cursor.y - barOffset.y );
|
||||
VECTOR2D barStart( aPosition.x + barOffset.x + barTrim, cursor.y - barOffset.y );
|
||||
VECTOR2D barEnd( cursor.x + barOffset.x - barTrim, cursor.y - barOffset.y );
|
||||
|
||||
if( !aAngle.IsZero() )
|
||||
{
|
||||
|
@ -311,7 +310,7 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
|
|||
{
|
||||
aBBox->SetOrigin( aPosition );
|
||||
aBBox->SetEnd( cursor.x + barOffset.x - KiROUND( glyphSize.x * INTER_CHAR ),
|
||||
cursor.y + std::max( glyphSize.y, barOffset.y ) );
|
||||
cursor.y + std::max( glyphSize.y, barOffset.y * OVERBAR_POSITION_FACTOR ) );
|
||||
aBBox->Normalize();
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,15 @@ enum TEXT_STYLE
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tilt factor for italic style (this is the scaling factor on dY relative coordinates to give
|
||||
* a tilted shape).
|
||||
* This is applied directly to stroke fonts, and is used as an estimate for outline fonts (which
|
||||
* have the actual tilt built in to their polygonal glyph outlines).
|
||||
*/
|
||||
static constexpr double ITALIC_TILT = 1.0 / 8;
|
||||
|
||||
|
||||
using TEXT_STYLE_FLAGS = unsigned int;
|
||||
|
||||
|
||||
|
|
|
@ -72,21 +72,6 @@ public:
|
|||
*/
|
||||
static OUTLINE_FONT* LoadFont( const wxString& aFontFileName, bool aBold, bool aItalic );
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Draw a string.
|
||||
*
|
||||
* @param aGal
|
||||
* @param aText is the text to be drawn.
|
||||
* @param aPosition is the text position in world coordinates.
|
||||
* @param aOrigin is the item origin
|
||||
* @param aAttributes contains text attributes (angle, line spacing, ...)
|
||||
* @return bounding box width/height
|
||||
*/
|
||||
VECTOR2D Draw( KIGFX::GAL* aGal, const wxString& aText, const VECTOR2D& aPosition,
|
||||
const VECTOR2D& aOrigin, const TEXT_ATTRIBUTES& aAttributes ) const override;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Compute the vertical position of an overbar. This is the distance between the text
|
||||
* baseline and the overbar.
|
||||
|
@ -104,14 +89,6 @@ public:
|
|||
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle, bool aMirror,
|
||||
const VECTOR2I& aOrigin, TEXT_STYLE_FLAGS aTextStyle ) const override;
|
||||
|
||||
/**
|
||||
* Like GetTextAsGlyphs, but handles multiple lines.
|
||||
* TODO: Combine with GetTextAsGlyphs, maybe with a boolean parameter,
|
||||
* but it's possible a non-line-breaking version isn't even needed
|
||||
*
|
||||
* @param aGlyphs returns text glyphs
|
||||
* @param aText the text item
|
||||
*/
|
||||
void GetLinesAsGlyphs( std::vector<std::unique_ptr<GLYPH>>* aGlyphs, const wxString& aText,
|
||||
const VECTOR2I& aPosition, const TEXT_ATTRIBUTES& aAttrs ) const;
|
||||
|
||||
|
@ -145,8 +122,7 @@ private:
|
|||
// need to compensate to keep them from being much smaller than their stroked counterparts.
|
||||
static constexpr double m_outlineFontSizeCompensation = 1.4;
|
||||
|
||||
// FT_Set_Char_Size() gets character width and height specified in
|
||||
// 1/64ths of a point
|
||||
// FT_Set_Char_Size() gets character width and height specified in 1/64ths of a point
|
||||
static constexpr int m_charSizeScaler = 64;
|
||||
|
||||
// The KiCad stroke font uses a subscript/superscript size ratio of 0.7. This ratio is also
|
||||
|
@ -171,8 +147,8 @@ private:
|
|||
|
||||
static constexpr double m_subscriptVerticalOffset = -0.25;
|
||||
static constexpr double m_superscriptVerticalOffset = 0.45;
|
||||
static constexpr double m_overbarOffset = 0.16;
|
||||
static constexpr double m_overbarHeightMultiplier = 0.07;
|
||||
static constexpr double m_overbarOffsetRatio = 0.02;
|
||||
static constexpr double m_overbarThicknessRatio = 0.08;
|
||||
};
|
||||
|
||||
} //namespace KIFONT
|
||||
|
|
|
@ -150,8 +150,8 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::addItemToRTrees( BOARD_ITEM* item )
|
|||
PCB_VIA* via = static_cast<PCB_VIA*>( item );
|
||||
int clearance = ( m_webWidth / 2 ) + via->GetSolderMaskExpansion();
|
||||
|
||||
item->TransformShapeWithClearanceToPolygon( *solderMask->GetFill( layer ), layer,
|
||||
clearance, m_maxError, ERROR_OUTSIDE );
|
||||
via->TransformShapeWithClearanceToPolygon( *solderMask->GetFill( layer ), layer,
|
||||
clearance, m_maxError, ERROR_OUTSIDE );
|
||||
|
||||
m_itemTree->Insert( item, layer, m_largestClearance );
|
||||
}
|
||||
|
|
|
@ -2007,7 +2007,7 @@ double FOOTPRINT::GetCoverageArea( const BOARD_ITEM* aItem, const GENERAL_COLLEC
|
|||
}
|
||||
|
||||
default:
|
||||
aItem->TransformShapeWithClearanceToPolygon( poly, UNDEFINED_LAYER, 0,
|
||||
shape->TransformShapeWithClearanceToPolygon( poly, UNDEFINED_LAYER, 0,
|
||||
ARC_LOW_DEF, ERROR_OUTSIDE );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue