diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2015-11-18 09:34:55 +0000 |
|---|---|---|
| committer | tavmjong-free <tavmjong@free.fr> | 2015-11-18 09:34:55 +0000 |
| commit | 81760f171e6b7bce537fd94cae3e3e1a6d82e886 (patch) | |
| tree | 7468d5470f58b2e05c29c24386235fcca1f4e3fd /src/libnrtype | |
| parent | Read/write 'dominant-baseline' property. (diff) | |
| download | inkscape-81760f171e6b7bce537fd94cae3e3e1a6d82e886.tar.gz inkscape-81760f171e6b7bce537fd94cae3e3e1a6d82e886.zip | |
Find font metrics when font is initialized. Fill baseline table.
Separately track typographic ascent/descent and maximum ascent/descent.
(bzr r14430.1.7)
Diffstat (limited to 'src/libnrtype')
| -rw-r--r-- | src/libnrtype/FontInstance.cpp | 267 | ||||
| -rw-r--r-- | src/libnrtype/font-instance.h | 33 |
2 files changed, 222 insertions, 78 deletions
diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp index 5853d5217..4578efe8f 100644 --- a/src/libnrtype/FontInstance.cpp +++ b/src/libnrtype/FontInstance.cpp @@ -184,6 +184,20 @@ font_instance::font_instance(void) : theFace(0) { //printf("font instance born\n"); + _ascent = _ascent_max = 0.8; + _descent = _descent_max = 0.2; + _xheight = 0.5; + + // Default baseline values, alphabetic is reference + _baselines[ SP_CSS_BASELINE_AUTO ] = 0.0; + _baselines[ SP_CSS_BASELINE_ALPHABETIC ] = 0.0; + _baselines[ SP_CSS_BASELINE_IDEOGRAPHIC ] = -_descent; + _baselines[ SP_CSS_BASELINE_HANGING ] = 0.8 * _ascent; + _baselines[ SP_CSS_BASELINE_MATHEMATICAL ] = 0.8 * _xheight; + _baselines[ SP_CSS_BASELINE_CENTRAL ] = 0.5; + _baselines[ SP_CSS_BASELINE_MIDDLE ] = 0.5 * _xheight; + _baselines[ SP_CSS_BASELINE_TEXT_BEFORE_EDGE ] = -_descent; + _baselines[ SP_CSS_BASELINE_TEXT_AFTER_EDGE ] = _ascent; } font_instance::~font_instance(void) @@ -260,6 +274,7 @@ void font_instance::InitTheFace() FT_Select_Charmap(theFace,ft_encoding_unicode) && FT_Select_Charmap(theFace,ft_encoding_symbol); } #endif + FindFontMetrics(); } } @@ -518,83 +533,16 @@ bool font_instance::FontMetrics(double &ascent,double &descent,double &xheight) return false; } - // CSS2 recommends using the OS/2 values sTypoAscender and sTypoDescender - // for the ascender and descender values: - // http://www.w3.org/TR/CSS2/visudet.html#sTypoAscender - // The typographic ascender and descender are taken from the - // otmMacAscent and otmMacDescent values: - // http://microsoft.public.win32.programmer.gdi.narkive.com/LV6k4BDh/msdn-documentation-outlinetextmetrics-clarification - // The otmAscent and otmDescent values are the maxiumum ascent and maxiumum - // descent of all the glyphs in a font. - -#ifdef USE_PANGO_WIN32 - OUTLINETEXTMETRIC otm; - if ( !GetOutlineTextMetrics(parent->hScreenDC,sizeof(otm),&otm) ) { - return false; - } - - double scale=1.0/parent->fontSize; - ascent=fabs(otm.otmMacAscent*scale); - descent=fabs(otm.otmMacDescent*scale); - xheight=fabs(otm.otmXHeight*scale); - // May not be necessary... but if OS/2 table is missing or not version 2 or higher, - // xheight might be set to 0. - if( xheight = 0.0 ) xheight = ascent/2.0; - //otmSubscriptSize, otmSubscriptOffset, otmSuperscriptSize, otmSuperscriptOffset, -#else - if ( theFace->units_per_EM == 0 ) { - return false; // bitmap font - } - - TT_OS2* os2 = (TT_OS2*)FT_Get_Sfnt_Table( theFace, FT_SFNT_OS2 ); - if( os2 ) { - ascent =fabs(((double)os2->sTypoAscender)/((double)theFace->units_per_EM)); - descent=fabs(((double)os2->sTypoDescender)/((double)theFace->units_per_EM)); - } else { - ascent =fabs(((double)theFace->ascender)/((double)theFace->units_per_EM)); - descent=fabs(((double)theFace->descender)/((double)theFace->units_per_EM)); - } - - // We must find x-height ourselves! First try OS/2 table. - if( os2 && os2->version >= 0x0002 && os2->version != 0xffffu ) { - // Only os/2 version 2 and above have sxHeight, 0xffff marks "old Mac fonts" without table - xheight=fabs(((double)os2->sxHeight)/((double)theFace->units_per_EM)); - } else { - // Measure 'x' height in font. Recommended option by XSL standard if no sxHeight. - FT_UInt index = FT_Get_Char_Index( theFace, 'x' ); - if( index != 0 ) { - FT_Load_Glyph( theFace, index, FT_LOAD_NO_SCALE ); - xheight = (fabs)(((double)theFace->glyph->metrics.height/(double)theFace->units_per_EM)); - } else { - // No 'x' in font! - xheight = ascent/2.0; - } - } -#endif - - // CSS dictates em size is ascent + descent.... but this doesn't seem to be used in practice. - // The em size is what the font reports... - double em = ascent + descent; - if( em <= 0 ) { - return false; // Pathological - } - ascent /= em; - descent /= em; - xheight /= em; - - // gchar* font_name = pango_font_description_to_string( descr ); - // std::cout << "Font: " << (font_name ? font_name : ("Null")) << std::endl; - // g_free( font_name ); - // std::cout << " ascent: " << ascent << " descent: " << descent - // << " x-height: " << xheight << "\n" << std::endl; + ascent = _ascent; + descent = _descent; + xheight = _xheight; return true; } -bool font_instance::FontDecoration( - double &underline_position, double &underline_thickness, - double &linethrough_position, double &linethrough_thickness -){ +bool font_instance::FontDecoration( double &underline_position, double &underline_thickness, + double &linethrough_position, double &linethrough_thickness) +{ if ( pFont == NULL ) { return false; } @@ -721,6 +669,179 @@ double font_instance::Advance(int glyph_id,bool vertical) return 0; } +// Internal function to find baselines +void font_instance::FindFontMetrics() { + + // CSS2 recommends using the OS/2 values sTypoAscender and sTypoDescender for the Typographic + // ascender and descender values: + // http://www.w3.org/TR/CSS2/visudet.html#sTypoAscender + // On Windows, the typographic ascender and descender are taken from the otmMacAscent and + // otmMacDescent values: + // http://microsoft.public.win32.programmer.gdi.narkive.com/LV6k4BDh/msdn-documentation-outlinetextmetrics-clarification + // The otmAscent and otmDescent values are the maxiumum ascent and maxiumum descent of all the + // glyphs in a font. + if ( theFace ) { + +#ifdef USE_PANGO_WIN32 + + if ( GetOutlineTextMetrics(parent->hScreenDC,sizeof(otm),&otm) ) { + double scale=1.0/parent->fontSize; + _ascent = fabs(otm.otmMacAscent * scale); + _descent = fabs(otm.otmMacDescent * scale); + _xheight = fabs(otm.otmXHeight * scale); + _ascent_max = fabs(otm.otmAscent * scale); + _descent_max = fabs(otm.otmDescent * scale); + + // In CSS em size is ascent + descent... which should be 1. If not, + // adjust so it is. + double em = _ascent + _descent; + if( em > 0 ) { + _ascent /= em; + _descent /= em; + } + + // May not be necessary but if OS/2 table missing or not version 2 or higher, + // xheight might be zero. + if( _xheight == 0.0 ) { + _xheight = 0.5; + } + + // Baselines defined relative to alphabetic. + _baselines[ SP_CSS_BASELINE_IDEOGRAPHIC ] = -_descent; // Recommendation + _baselines[ SP_CSS_BASELINE_HANGING ] = 0.8 * _ascent; // Guess + _baselines[ SP_CSS_BASELINE_MATHEMATICAL ] = 0.8 * _xheight; // Guess + _baselines[ SP_CSS_BASELINE_CENTRAL ] = 0.5; // Definition + _baselines[ SP_CSS_BASELINE_MIDDLE ] = 0.5 * _xheight; // Definition + _baselines[ SP_CSS_BASELINE_TEXT_BEFORE_EDGE ] = -_descent; // Definition + _baselines[ SP_CSS_BASELINE_TEXT_AFTER_EDGE ] = _ascent; // Definition + + + MAT2 identity = {{0,1},{0,0},{0,0},{0,1}}; + GLYPHMETRICS metrics; + int retval; + + // Better math baseline: + // Try center of minus sign + retval = GetGlyphOutline (parent->hScreenDC, 0x2212, GGO_NATIVE | GGO_UNHINTED, &metrics, 0, NULL, &identity); + // If no minus sign, try hyphen + if( retval <= 0 ) + retval = GetGlyphOutline (parent->hScreenDC, '-', GGO_NATIVE | GGO_UNHINTED, &metrics, 0, NULL, &identity); + + if( retval > 0 ) { + double math = (metrics.gmptGlyphOrigin.y + 0.5 * metrics.gmBlackBoxY) * scale; + _baselines[ SP_CSS_BASELINE_MATHEMATICAL ] = math; + } + + // Find hanging baseline... assume it is at top of 'म'. + retval = GetGlyphOutline (parent->hScreenDC, 0x092E, GGO_NATIVE | GGO_UNHINTED, &metrics, 0, NULL, &identity); + if( retval > 0 ) { + double hanging = metrics.gmptGlyphOrigin.y * scale; + _baselines[ SP_CSS_BASELINE_MATHEMATICAL ] = hanging; + } + } + +#else + + if ( theFace->units_per_EM != 0 ) { // If zero then it's a bitmap font. + + TT_OS2* os2 = (TT_OS2*)FT_Get_Sfnt_Table( theFace, FT_SFNT_OS2 ); + if( os2 ) { + _ascent = fabs(((double)os2->sTypoAscender) / ((double)theFace->units_per_EM)); + _descent = fabs(((double)os2->sTypoDescender)/ ((double)theFace->units_per_EM)); + } else { + _ascent = fabs(((double)theFace->ascender) / ((double)theFace->units_per_EM)); + _descent = fabs(((double)theFace->descender) / ((double)theFace->units_per_EM)); + } + _ascent_max = fabs(((double)theFace->ascender) / ((double)theFace->units_per_EM)); + _descent_max = fabs(((double)theFace->descender) / ((double)theFace->units_per_EM)); + + // In CSS em size is ascent + descent... which should be 1. If not, + // adjust so it is. + double em = _ascent + _descent; + if( em > 0 ) { + _ascent /= em; + _descent /= em; + } + + // x-height + if( os2 && os2->version >= 0x0002 && os2->version != 0xffffu ) { + // Only os/2 version 2 and above have sxHeight, 0xffff marks "old Mac fonts" without table + _xheight = fabs(((double)os2->sxHeight) / ((double)theFace->units_per_EM)); + } else { + // Measure 'x' height in font. Recommended option by XSL standard if no sxHeight. + FT_UInt index = FT_Get_Char_Index( theFace, 'x' ); + if( index != 0 ) { + FT_Load_Glyph( theFace, index, FT_LOAD_NO_SCALE ); + _xheight = (fabs)(((double)theFace->glyph->metrics.height/(double)theFace->units_per_EM)); + } else { + // No 'x' in font! + _xheight = 0.5; + } + } + + // Baselines defined relative to alphabetic. + _baselines[ SP_CSS_BASELINE_IDEOGRAPHIC ] = -_descent; // Recommendation + _baselines[ SP_CSS_BASELINE_HANGING ] = 0.8 * _ascent; // Guess + _baselines[ SP_CSS_BASELINE_MATHEMATICAL ] = 0.8 * _xheight; // Guess + _baselines[ SP_CSS_BASELINE_CENTRAL ] = 0.5; // Definition + _baselines[ SP_CSS_BASELINE_MIDDLE ] = 0.5 * _xheight; // Definition + _baselines[ SP_CSS_BASELINE_TEXT_BEFORE_EDGE ] = -_descent; // Definition + _baselines[ SP_CSS_BASELINE_TEXT_AFTER_EDGE ] = _ascent; // Definition + + // Better math baseline: + // Try center of minus sign + FT_UInt index = FT_Get_Char_Index( theFace, 0x2212 ); //'−' + // If no minus sign, try hyphen + if( index == 0 ) + index = FT_Get_Char_Index( theFace, '-' ); + + if( index != 0 ) { + FT_Load_Glyph( theFace, index, FT_LOAD_NO_SCALE ); + FT_Glyph aglyph; + FT_Get_Glyph( theFace->glyph, &aglyph ); + FT_BBox acbox; + FT_Glyph_Get_CBox( aglyph, FT_GLYPH_BBOX_UNSCALED, &acbox ); + double math = (acbox.yMin + acbox.yMax)/2.0/(double)theFace->units_per_EM; + _baselines[ SP_CSS_BASELINE_MATHEMATICAL ] = math; + std::cout << "Math baseline: - bbox: y_min: " << acbox.yMin + << " y_max: " << acbox.yMax + << " math: " << math << std::endl; + } + + // Find hanging baseline... assume it is at top of 'म'. + index = FT_Get_Char_Index( theFace, 0x092E ); // 'म' + if( index != 0 ) { + FT_Load_Glyph( theFace, index, FT_LOAD_NO_SCALE ); + FT_Glyph aglyph; + FT_Get_Glyph( theFace->glyph, &aglyph ); + FT_BBox acbox; + FT_Glyph_Get_CBox( aglyph, FT_GLYPH_BBOX_UNSCALED, &acbox ); + double hanging = (double)acbox.yMax/(double)theFace->units_per_EM; + _baselines[ SP_CSS_BASELINE_HANGING ] = hanging; + std::cout << "Hanging baseline: प: " << hanging << std::endl; + } + } +#endif + const gchar *family = pango_font_description_get_family(descr); + std::cout << "Font: " << (family?family:"null") << std::endl; + std::cout << " ascent: " << _ascent << std::endl; + std::cout << " descent: " << _descent << std::endl; + std::cout << " x-height: " << _xheight << std::endl; + std::cout << " max ascent: " << _ascent_max << std::endl; + std::cout << " max descent: " << _descent_max << std::endl; + std::cout << " Baselines:" << std::endl; + std::cout << " alphabetic: " << _baselines[ SP_CSS_BASELINE_ALPHABETIC ] << std::endl; + std::cout << " ideographic: " << _baselines[ SP_CSS_BASELINE_IDEOGRAPHIC ] << std::endl; + std::cout << " hanging: " << _baselines[ SP_CSS_BASELINE_HANGING ] << std::endl; + std::cout << " math: " << _baselines[ SP_CSS_BASELINE_MATHEMATICAL ] << std::endl; + std::cout << " central: " << _baselines[ SP_CSS_BASELINE_CENTRAL ] << std::endl; + std::cout << " middle: " << _baselines[ SP_CSS_BASELINE_MIDDLE ] << std::endl; + std::cout << " text_before: " << _baselines[ SP_CSS_BASELINE_TEXT_BEFORE_EDGE ] << std::endl; + std::cout << " text_after: " << _baselines[ SP_CSS_BASELINE_TEXT_AFTER_EDGE ] << std::endl; + } +} + + /* Local Variables: mode:c++ diff --git a/src/libnrtype/font-instance.h b/src/libnrtype/font-instance.h index 5a71e353b..2fac7c19b 100644 --- a/src/libnrtype/font-instance.h +++ b/src/libnrtype/font-instance.h @@ -57,19 +57,31 @@ public: // nota: all coordinates returned by these functions are on a [0..1] scale; you need to multiply // by the fontsize to get the real sizes + + // Return 2geom pathvector for glyph. Deallocated when font instance dies. Geom::PathVector* PathVector(int glyph_id); - // returns the 2geom-type pathvector for this glyph. no refcounting needed, it's deallocated when the font_instance dies + + // Horizontal advance if 'vertical' is false, vertical advance if true. double Advance(int glyph_id, bool vertical); - // nominal advance of the font. + + double GetTypoAscent() { return _ascent; } + double GetTypoDescent() { return _descent; } + double GetXHeight() { return _xheight; } + double GetMaxAscent() { return _ascent_max; } + double GetMaxDescent() { return _descent_max; } + const double* GetBaselines() { return _baselines; } + bool FontMetrics(double &ascent, double &descent, double &leading); - bool FontDecoration(double &underline_position, double &underline_thickness, - double &linethrough_position, double &linethrough_thickness); + bool FontDecoration(double &underline_position, double &underline_thickness, + double &linethrough_position, double &linethrough_thickness); bool FontSlope(double &run, double &rise); // for generating slanted cursors for oblique fonts - Geom::OptRect BBox(int glyph_id); + Geom::OptRect BBox(int glyph_id); private: void FreeTheFace(); + // Find ascent, descent, x-height, and baselines. + void FindFontMetrics(); // Temp: make public public: @@ -81,6 +93,17 @@ public: // as long as pFont is valid, theFace is too #endif +private: + + // Font metrics in em-box units + double _ascent; // Typographic ascent. + double _descent; // Typographic descent. + double _xheight; // x-height of font. + double _ascent_max; // Maxiumum ascent of all glyphs in font. + double _descent_max; // Maxiumum descent of all glyphs in font. + + // Baselines + double _baselines[SP_CSS_BASELINE_SIZE]; }; |
