b=385263 make line heights integer r=roc
--- a/gfx/thebes/src/gfxPangoFonts.cpp
+++ b/gfx/thebes/src/gfxPangoFonts.cpp
@@ -1238,34 +1238,35 @@ LockedFTFace::GetMetrics(gfxFont::Metric
aMetrics->superscriptOffset = aMetrics->xHeight;
aMetrics->subscriptOffset = aMetrics->xHeight;
return;
}
const FT_Size_Metrics& ftMetrics = mFace->size->metrics;
+ gfxFloat emHeight;
// Scale for vertical design metric conversion: pixels per design unit.
gfxFloat yScale;
if (FT_IS_SCALABLE(mFace)) {
// Prefer FT_Size_Metrics::x_scale to x_ppem as x_ppem does not
// have subpixel accuracy.
//
// FT_Size_Metrics::y_scale is in 16.16 fixed point format. Its
// (fractional) value is a factor that converts vertical metrics from
// design units to units of 1/64 pixels, so that the result may be
// interpreted as pixels in 26.6 fixed point format.
yScale = FLOAT_FROM_26_6(FLOAT_FROM_16_16(ftMetrics.y_scale));
- aMetrics->emHeight = mFace->units_per_EM * yScale;
+ emHeight = mFace->units_per_EM * yScale;
} else { // Not scalable.
// FT_Size_Metrics doc says x_scale is "only relevant for scalable
// font formats".
gfxFloat emUnit = mFace->units_per_EM;
- aMetrics->emHeight = ftMetrics.y_ppem;
- yScale = aMetrics->emHeight / emUnit;
+ emHeight = ftMetrics.y_ppem;
+ yScale = emHeight / emUnit;
}
TT_OS2 *os2 =
static_cast<TT_OS2*>(FT_Get_Sfnt_Table(mFace, ft_sfnt_os2));
aMetrics->maxAscent = FLOAT_FROM_26_6(ftMetrics.ascender);
aMetrics->maxDescent = -FLOAT_FROM_26_6(ftMetrics.descender);
aMetrics->maxAdvance = FLOAT_FROM_26_6(ftMetrics.max_advance);
@@ -1312,17 +1313,17 @@ LockedFTFace::GetMetrics(gfxFont::Metric
aMetrics->aveCharWidth = extents.x_advance;
} else {
if (os2 && os2->sxHeight) {
aMetrics->xHeight = os2->sxHeight * yScale;
} else {
// CSS 2.1, section 4.3.2 Lengths: "In the cases where it is
// impossible or impractical to determine the x-height, a value of
// 0.5em should be used."
- aMetrics->xHeight = 0.5 * aMetrics->emHeight;
+ aMetrics->xHeight = 0.5 * emHeight;
}
aMetrics->aveCharWidth = 0.0; // updated below
}
// aveCharWidth is used for the width of text input elements so be
// liberal rather than conservative in the estimate.
if (os2 && os2->xAvgCharWidth) {
// Round to pixels as this is compared with maxAdvance to guess
// whether this is a fixed width font.
@@ -1363,27 +1364,27 @@ LockedFTFace::GetMetrics(gfxFont::Metric
if (post && post->underlinePosition) {
aMetrics->underlineOffset = post->underlinePosition * yScale;
} else {
aMetrics->underlineOffset = mFace->underline_position * yScale
+ 0.5 * aMetrics->underlineSize;
}
} else { // No underline info.
// Imitate Pango.
- aMetrics->underlineSize = aMetrics->emHeight / 14.0;
+ aMetrics->underlineSize = emHeight / 14.0;
aMetrics->underlineOffset = -aMetrics->underlineSize;
}
if (os2 && os2->yStrikeoutSize && os2->yStrikeoutPosition) {
aMetrics->strikeoutSize = os2->yStrikeoutSize * yScale;
aMetrics->strikeoutOffset = os2->yStrikeoutPosition * yScale;
} else { // No strikeout info.
aMetrics->strikeoutSize = aMetrics->underlineSize;
// Use OpenType spec's suggested position for Roman font.
- aMetrics->strikeoutOffset = aMetrics->emHeight * 409.0 / 2048.0
+ aMetrics->strikeoutOffset = emHeight * 409.0 / 2048.0
+ 0.5 * aMetrics->strikeoutSize;
}
SnapLineToPixels(aMetrics->strikeoutOffset, aMetrics->strikeoutSize);
if (os2 && os2->ySuperscriptYOffset) {
gfxFloat val = ScaleRoundDesignUnits(os2->ySuperscriptYOffset,
ftMetrics.y_scale);
aMetrics->superscriptOffset = PR_MAX(1.0, val);
@@ -1398,26 +1399,40 @@ LockedFTFace::GetMetrics(gfxFont::Metric
val = fabs(val);
aMetrics->subscriptOffset = PR_MAX(1.0, val);
} else {
aMetrics->subscriptOffset = aMetrics->xHeight;
}
aMetrics->maxHeight = aMetrics->maxAscent + aMetrics->maxDescent;
+ // Make the line height an integer number of pixels so that lines will be
+ // equally spaced (rather than just being snapped to pixels, some up and
+ // some down). Layout calculates line height from the emHeight +
+ // internalLeading + externalLeading, but first each of these is rounded
+ // to layout units. To ensure that the result is an integer number of
+ // pixels, round each of the components to pixels.
+ aMetrics->emHeight = NS_floor(emHeight + 0.5);
+
+ // maxHeight will normally be an integer, but round anyway in case
+ // FreeType is configured differently.
+ aMetrics->internalLeading =
+ NS_floor(aMetrics->maxHeight - aMetrics->emHeight + 0.5);
+
+ // Text input boxes currently don't work well with lineHeight
+ // significantly less than maxHeight (with Verdana, for example).
+ lineHeight = NS_floor(PR_MAX(lineHeight, aMetrics->maxHeight) + 0.5);
+ aMetrics->externalLeading =
+ lineHeight - aMetrics->internalLeading - aMetrics->emHeight;
+
// Ensure emAscent + emDescent == emHeight
gfxFloat sum = aMetrics->emAscent + aMetrics->emDescent;
aMetrics->emAscent = sum > 0.0 ?
aMetrics->emAscent * aMetrics->emHeight / sum : 0.0;
aMetrics->emDescent = aMetrics->emHeight - aMetrics->emAscent;
-
- aMetrics->internalLeading = aMetrics->maxHeight - aMetrics->emHeight;
- // Text input boxes currently don't work well with lineHeight < maxHeight
- // (with Verdana, for example).
- aMetrics->externalLeading = PR_MAX(lineHeight - aMetrics->maxHeight, 0);
}
const gfxFont::Metrics&
gfxFcFont::GetMetrics()
{
if (mHasMetrics)
return mMetrics;