From f6aa25df5237f011f399ca4e98ec9319ca53691f Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sun, 7 Feb 2021 13:10:30 +0000 Subject: [PATCH] Make bitmap text measuring cognizant of overbars. Also adds fallback for when text contains super- or subscript. Fixes https://gitlab.com/kicad/code/kicad/issues/6846 --- common/gal/opengl/opengl_gal.cpp | 56 ++++++++++++++++++------ common/gal/stroke_font.cpp | 4 +- include/gal/graphics_abstraction_layer.h | 13 +++++- 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index cec436f947..6963bcfead 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -1211,7 +1211,9 @@ void OPENGL_GAL::DrawBitmap( const BITMAP_BASE& aBitmap ) void OPENGL_GAL::BitmapText( const wxString& aText, const VECTOR2D& aPosition, double aRotationAngle ) { - wxASSERT_MSG( !IsTextMirrored(), "No support for mirrored text using bitmap fonts." ); + // Fallback to generic impl (which uses the stroke font) on cases we don't handle + if( IsTextMirrored() || aText.Contains( wxT( "^{" ) ) || aText.Contains( wxT( "_{" ) ) ) + return GAL::BitmapText( aText, aPosition, aRotationAngle ); const UTF8 text( aText ); // Compute text size, so it can be properly justified @@ -2002,33 +2004,61 @@ void OPENGL_GAL::drawBitmapOverbar( double aLength, double aHeight ) std::pair OPENGL_GAL::computeBitmapTextSize( const UTF8& aText ) const { + static const FONT_GLYPH_TYPE* defaultGlyph = LookupGlyph( '(' ); // for strange chars + static const FONT_GLYPH_TYPE* lineGlyph = LookupGlyph( '_' ); // for overbar thickness + VECTOR2D textSize( 0, 0 ); - float commonOffset = std::numeric_limits::max(); - static const auto defaultGlyph = LookupGlyph( '(' ); // for strange chars + float commonOffset = std::numeric_limits::max(); + bool in_overbar = false; + float char_height = font_information.max_y - defaultGlyph->miny; for( UTF8::uni_iter chIt = aText.ubegin(), end = aText.uend(); chIt < end; ++chIt ) { - unsigned int c = *chIt; + if( *chIt == '~' ) + { + if( ++chIt == end ) + break; - const FONT_GLYPH_TYPE* glyph = LookupGlyph( c ); - // Debug: show not coded char in the atlas - // Be carefull before allowing the assert: it usually crash kicad - // when the assert is made during a paint event. - // wxASSERT_MSG( glyph, wxString::Format( "missing char in font: code 0x%x <%c>", c, c ) ); + if( *chIt == '~' ) + { + // double ~ is really a ~ so go ahead and process the second one - if( !glyph || // Not coded in font - c == '-' || c == '_' ) // Strange size of these 2 chars + // so what's a triple ~? It could be a real ~ followed by an overbar, or + // it could be an overbar followed by a real ~. The old algorithm did the + // former so we will too.... + } + else + { + // single ~ toggles overbar + in_overbar = !in_overbar; + } + } + else if( in_overbar && ( *chIt == ' ' || *chIt == '}' || *chIt == ')' ) ) + { + in_overbar = false; + } + + const FONT_GLYPH_TYPE* glyph = LookupGlyph( *chIt ); + + if( !glyph // Not coded in font + || *chIt == '-' || *chIt == '_' ) // Strange size of these 2 chars { glyph = defaultGlyph; } if( glyph ) { - textSize.x += glyph->advance; + textSize.x += glyph->advance; + + if( in_overbar ) + { + const float H = lineGlyph->maxy - lineGlyph->miny; + textSize.y = std::max( textSize.y, char_height + 1.5 * H ); + } } } - textSize.y = std::max( textSize.y, font_information.max_y - defaultGlyph->miny ); + textSize.y = std::max( textSize.y, char_height ); commonOffset = std::min( font_information.max_y - defaultGlyph->maxy, commonOffset ); textSize.y -= commonOffset; diff --git a/common/gal/stroke_font.cpp b/common/gal/stroke_font.cpp index 9ec77961da..e4f22bdea7 100644 --- a/common/gal/stroke_font.cpp +++ b/common/gal/stroke_font.cpp @@ -531,8 +531,8 @@ VECTOR2D STROKE_FONT::ComputeStringBoundaryLimits( const UTF8& aText, const VECT double aGlyphThickness ) const { VECTOR2D string_bbox; - int line_count = 1; - double maxX = 0.0, curX = 0.0; + int line_count = 1; + double maxX = 0.0, curX = 0.0; double curScale = 1.0; bool in_overbar = false; diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index ace04040a6..b91bc48079 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -366,7 +366,18 @@ public: if( globalFlipX ) textProperties.m_mirrored = !textProperties.m_mirrored; - StrokeText( aText, aPosition, aRotationAngle ); + // Bitmap font is slightly smaller and slightly heavier than the stroke font so we + // compensate a bit before stroking + int saveLineWidth = lineWidth; + VECTOR2D saveGlyphSize = textProperties.m_glyphSize; + { + lineWidth *= 1.2; + textProperties.m_glyphSize = textProperties.m_glyphSize * 0.8; + + StrokeText( aText, aPosition, aRotationAngle ); + } + lineWidth = saveLineWidth; + textProperties.m_glyphSize = saveGlyphSize; if( globalFlipX ) textProperties.m_mirrored = !textProperties.m_mirrored;