[OS/2] Fix stupidities about scales when computing font metrics, part of work on Bug 381333

git-svn-id: svn://10.0.0.236/trunk@228648 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
mozilla%weilbacher.org
2007-06-24 11:10:03 +00:00
parent 81c9d9bab5
commit 7347ddf39a

View File

@@ -89,6 +89,10 @@ gfxOS2Font::~gfxOS2Font()
#define MOZ_FT_TRUNC(x) ((x) >> 6)
#define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s) \
MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v), (s))))
#define CONVERT_DESIGN_UNITS_TO_PIXELS_X(v) \
CONVERT_DESIGN_UNITS_TO_PIXELS(v, face->size->metrics.x_scale)
#define CONVERT_DESIGN_UNITS_TO_PIXELS_Y(v) \
CONVERT_DESIGN_UNITS_TO_PIXELS(v, face->size->metrics.y_scale)
const gfxFont::Metrics& gfxOS2Font::GetMetrics()
{
@@ -98,78 +102,67 @@ const gfxFont::Metrics& gfxOS2Font::GetMetrics()
if (!mMetrics) {
mMetrics = new gfxFont::Metrics;
// XXX maybe use CONVERT_DESIGN_UNITS_TO_PIXELS(..., face->size->metrics.y_scale);
// on all (y) properties?!
FT_UInt gid;
FT_Face face = cairo_ft_scaled_font_lock_face(CairoScaledFont());
#if 0
// face->units_per_EM doesn't work here, so use height of 'm' (the font's emHeight)
// and scale to correct height
gid = FT_Get_Char_Index(face, 'm'); // select the glyph
FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT); // load it into the slot
gfxFloat scale = face->glyph->metrics.height / mStyle.size;
// XXX no, that doesn't work, gives completely bogus results for maxHeight etc.
#endif
// instead, use this hack to scale, seems to give good results for all fonts
// and sizes
gfxFloat scale = face->units_per_EM / 8;
// properties of 'x', also use its width as average width
gid = FT_Get_Char_Index(face, 'x'); // select the glyph
FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT); // load it into the slot
mMetrics->xHeight = face->glyph->metrics.height / scale;
mMetrics->aveCharWidth = face->glyph->metrics.width / scale;
mMetrics->xHeight = CONVERT_DESIGN_UNITS_TO_PIXELS_Y(face->glyph->metrics.height);
mMetrics->aveCharWidth = CONVERT_DESIGN_UNITS_TO_PIXELS_X(face->glyph->metrics.width);
// properties of space
gid = FT_Get_Char_Index(face, ' ');
FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT);
// face->glyph->metrics.width doesn't work for spaces, use advance.x instead
// XXX spaces are always too narrow, unless I multiply by some extra factor
mMetrics->spaceWidth = face->glyph->advance.x / scale * 2;
// spaces are always too narrow, unless I multiply by some extra factor
mMetrics->spaceWidth = CONVERT_DESIGN_UNITS_TO_PIXELS_X(face->glyph->advance.x) * 2;
// save the space glyph
mSpaceGlyph = gid;
// now load the OS/2 TrueType table to load access some more properties
TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
if (os2 && os2->version != 0xFFFF) { // should be there if not old Mac font
mMetrics->superscriptOffset = PR_MAX(1, os2->ySuperscriptYOffset) / scale;
mMetrics->superscriptOffset = CONVERT_DESIGN_UNITS_TO_PIXELS_Y(os2->ySuperscriptYOffset);
mMetrics->superscriptOffset = PR_MAX(1, mMetrics->superscriptOffset);
// some fonts have the incorrect sign (from gfxPangoFonts)
mMetrics->subscriptOffset = PR_MAX(1, fabs(os2->ySubscriptYOffset)) / scale;
mMetrics->subscriptOffset = CONVERT_DESIGN_UNITS_TO_PIXELS_Y(os2->ySubscriptYOffset);
mMetrics->subscriptOffset = PR_MAX(1, fabs(mMetrics->subscriptOffset));
} else {
mMetrics->superscriptOffset = mMetrics->xHeight / scale;
mMetrics->subscriptOffset = mMetrics->xHeight / scale;
mMetrics->superscriptOffset = mMetrics->xHeight;
mMetrics->subscriptOffset = mMetrics->xHeight;
}
// could access these via os2 table, but copy behavior from gfxPangoFonts
mMetrics->strikeoutOffset = mMetrics->xHeight / 2.0 / scale;
mMetrics->strikeoutSize = face->underline_thickness / scale;
mMetrics->underlineOffset = face->underline_position / scale;
mMetrics->underlineSize = face->underline_thickness / scale;
mMetrics->strikeoutOffset = mMetrics->xHeight / 2.0;
mMetrics->strikeoutSize = CONVERT_DESIGN_UNITS_TO_PIXELS_Y(face->underline_thickness);
mMetrics->underlineOffset = CONVERT_DESIGN_UNITS_TO_PIXELS_Y(face->underline_position);
mMetrics->underlineSize = CONVERT_DESIGN_UNITS_TO_PIXELS_Y(face->underline_thickness);
// dividing by scale doesn't make sense
mMetrics->emHeight = face->size->metrics.y_ppem;
mMetrics->emAscent = face->ascender / scale;
mMetrics->emDescent = face->descender / scale;
mMetrics->maxHeight = face->height / scale;
mMetrics->maxAscent = face->bbox.yMax / scale;
mMetrics->maxDescent = face->bbox.yMin / scale;
mMetrics->maxAdvance = face->max_advance_width / scale;
// descents are negative in FT but Thebes wants them positive
mMetrics->emHeight = CONVERT_DESIGN_UNITS_TO_PIXELS_Y(face->size->metrics.y_ppem);
mMetrics->emAscent = CONVERT_DESIGN_UNITS_TO_PIXELS_Y(face->ascender);
mMetrics->emDescent = -CONVERT_DESIGN_UNITS_TO_PIXELS_Y(face->descender);
mMetrics->maxHeight = CONVERT_DESIGN_UNITS_TO_PIXELS_Y(face->height);
mMetrics->maxAscent = CONVERT_DESIGN_UNITS_TO_PIXELS_Y(face->bbox.yMax);
mMetrics->maxDescent = -CONVERT_DESIGN_UNITS_TO_PIXELS_Y(face->bbox.yMin);
mMetrics->maxAdvance = CONVERT_DESIGN_UNITS_TO_PIXELS_X(face->max_advance_width);
// leading are not available directly (only for WinFNTs)
mMetrics->internalLeading = (face->bbox.yMax - face->bbox.yMin
- mMetrics->xHeight) / scale;
mMetrics->externalLeading = 0; // normal value for OS/2 fonts
double lineHeight = mMetrics->maxAscent + mMetrics->maxDescent;
if (lineHeight > mMetrics->emHeight) {
mMetrics->internalLeading = lineHeight - mMetrics->emHeight;
} else {
mMetrics->internalLeading = 0;
}
mMetrics->externalLeading = 0; // normal value for OS/2 fonts, too
#ifdef DEBUG_thebes_1
printf("gfxOS2Font[%#x]::GetMetrics():\n"
" scale=%f\n"
" emHeight=%f==%f=gfxFont::mStyle.size\n"
" maxHeight=%f\n"
" xHeight=%f\n"
" aveCharWidth=%f==xWidth\n"
" spaceWidth=%f\n",
(unsigned)this,
scale,
mStyle.size,
mMetrics->emHeight,
mMetrics->emHeight, mStyle.size,
mMetrics->maxHeight,
mMetrics->xHeight,
mMetrics->aveCharWidth,