summaryrefslogtreecommitdiffstats
path: root/src/libnrtype
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2015-11-18 09:34:55 +0000
committertavmjong-free <tavmjong@free.fr>2015-11-18 09:34:55 +0000
commit81760f171e6b7bce537fd94cae3e3e1a6d82e886 (patch)
tree7468d5470f58b2e05c29c24386235fcca1f4e3fd /src/libnrtype
parentRead/write 'dominant-baseline' property. (diff)
downloadinkscape-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.cpp267
-rw-r--r--src/libnrtype/font-instance.h33
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];
};