Bug 1732577 - Don't round FT glyph extents when hinting is disabled. r=jfkthame

This bug originated from bug 1547063 when we started to allow subpixel positioning
for FreeType fonts. It would check if we requested no hinting from FreeType and
always try to round the X extents. However, light hinting disables X hinting as
well (just not Y hinting), so the behavior in this case diverged between light and
no hinting. This should make the two cases now look similar.

Differential Revision: https://phabricator.services.mozilla.com/D131537
This commit is contained in:
Lee Salzman 2021-11-19 16:03:27 +00:00
parent 8ff6f25a7d
commit 62a97131b7

View File

@ -636,7 +636,14 @@ bool gfxFT2FontBase::GetFTGlyphExtents(uint16_t aGID, int32_t* aAdvance,
return false;
}
// Whether to interpret hinting settings (i.e. not printing)
bool hintMetrics = ShouldHintMetrics();
// Whether to disable subpixel positioning
bool roundX = ShouldRoundXOffset(nullptr);
// No hinting disables X and Y hinting. Light disables only X hinting.
bool unhintedY = (mFTLoadFlags & FT_LOAD_NO_HINTING) != 0;
bool unhintedX =
unhintedY || FT_LOAD_TARGET_MODE(mFTLoadFlags) == FT_RENDER_MODE_LIGHT;
// Normalize out the loaded FT glyph size and then scale to the actually
// desired size, in case these two sizes differ.
@ -649,7 +656,7 @@ bool gfxFT2FontBase::GetFTGlyphExtents(uint16_t aGID, int32_t* aAdvance,
// applying hinting. Otherwise, prefer hinted width from glyph->advance.x.
if (aAdvance) {
FT_Fixed advance;
if (!ShouldRoundXOffset(nullptr) || FT_HAS_MULTIPLE_MASTERS(face.get())) {
if (!roundX || FT_HAS_MULTIPLE_MASTERS(face.get())) {
advance = face.get()->glyph->linearHoriAdvance;
} else {
advance = face.get()->glyph->advance.x << 10; // convert 26.6 to 16.16
@ -661,7 +668,7 @@ bool gfxFT2FontBase::GetFTGlyphExtents(uint16_t aGID, int32_t* aAdvance,
// Round the advance here to approximate hinting as Cairo does. This must
// happen BEFORE we apply the glyph extents scale, just like FT hinting
// would.
if (hintMetrics && (mFTLoadFlags & FT_LOAD_NO_HINTING)) {
if (hintMetrics && roundX && unhintedX) {
advance = (advance + 0x8000) & 0xffff0000u;
}
*aAdvance = NS_lround(advance * extentsScale);
@ -676,11 +683,15 @@ bool gfxFT2FontBase::GetFTGlyphExtents(uint16_t aGID, int32_t* aAdvance,
// Synthetic bold moves the glyph top and right boundaries.
y -= bold.y;
x2 += bold.x;
if (hintMetrics && (mFTLoadFlags & FT_LOAD_NO_HINTING)) {
x &= -64;
y &= -64;
x2 = (x2 + 63) & -64;
y2 = (y2 + 63) & -64;
if (hintMetrics) {
if (roundX && unhintedX) {
x &= -64;
x2 = (x2 + 63) & -64;
}
if (unhintedY) {
y &= -64;
y2 = (y2 + 63) & -64;
}
}
*aBounds = IntRect(x, y, x2 - x, y2 - y);
}