зеркало из https://github.com/mozilla/gecko-dev.git
b=716402 improve inter-glyph pixel rounding r=jfkthame
This commit is contained in:
Родитель
c6b2a1ff71
Коммит
22fe2c5db5
|
@ -1016,6 +1016,18 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxContext *aContext,
|
||||||
// (only used if not rounding)
|
// (only used if not rounding)
|
||||||
double hb2appUnits = FixedToFloat(aShapedWord->AppUnitsPerDevUnit());
|
double hb2appUnits = FixedToFloat(aShapedWord->AppUnitsPerDevUnit());
|
||||||
|
|
||||||
|
// Residual from rounding of previous advance, for use in rounding the
|
||||||
|
// subsequent offset or advance appropriately. 16.16 fixed-point
|
||||||
|
//
|
||||||
|
// When rounding, the goal is to make the distance between glyphs and
|
||||||
|
// their base glyph equal to the integral number of pixels closest to that
|
||||||
|
// suggested by that shaper.
|
||||||
|
// i.e. posInfo[n].x_advance - posInfo[n].x_offset + posInfo[n+1].x_offset
|
||||||
|
//
|
||||||
|
// The value of the residual is the part of the desired distance that has
|
||||||
|
// not been included in integer offsets.
|
||||||
|
hb_position_t x_residual = 0;
|
||||||
|
|
||||||
// keep track of y-position to set glyph offsets if needed
|
// keep track of y-position to set glyph offsets if needed
|
||||||
nscoord yPos = 0;
|
nscoord yPos = 0;
|
||||||
|
|
||||||
|
@ -1116,17 +1128,27 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxContext *aContext,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if it's a simple one-to-one mapping
|
hb_position_t x_offset = posInfo[glyphStart].x_offset;
|
||||||
hb_position_t x_advance = posInfo[glyphStart].x_advance;
|
hb_position_t x_advance = posInfo[glyphStart].x_advance;
|
||||||
nscoord advance =
|
nscoord xOffset, advance;
|
||||||
roundX ? appUnitsPerDevUnit * FixedToIntRound(x_advance)
|
if (roundX) {
|
||||||
: floor(hb2appUnits * x_advance + 0.5);
|
xOffset =
|
||||||
|
appUnitsPerDevUnit * FixedToIntRound(x_offset + x_residual);
|
||||||
|
// Desired distance from the base glyph to the next reference point.
|
||||||
|
hb_position_t width = x_advance - x_offset;
|
||||||
|
int intWidth = FixedToIntRound(width);
|
||||||
|
x_residual = width - FloatToFixed(intWidth);
|
||||||
|
advance = appUnitsPerDevUnit * intWidth + xOffset;
|
||||||
|
} else {
|
||||||
|
xOffset = floor(hb2appUnits * x_offset + 0.5);
|
||||||
|
advance = floor(hb2appUnits * x_advance + 0.5);
|
||||||
|
}
|
||||||
|
// Check if it's a simple one-to-one mapping
|
||||||
if (glyphsInClump == 1 &&
|
if (glyphsInClump == 1 &&
|
||||||
gfxTextRun::CompressedGlyph::IsSimpleGlyphID(ginfo[glyphStart].codepoint) &&
|
gfxTextRun::CompressedGlyph::IsSimpleGlyphID(ginfo[glyphStart].codepoint) &&
|
||||||
gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
|
gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
|
||||||
aShapedWord->IsClusterStart(baseCharIndex) &&
|
aShapedWord->IsClusterStart(baseCharIndex) &&
|
||||||
posInfo[glyphStart].x_offset == 0 &&
|
xOffset == 0 &&
|
||||||
posInfo[glyphStart].y_offset == 0 && yPos == 0)
|
posInfo[glyphStart].y_offset == 0 && yPos == 0)
|
||||||
{
|
{
|
||||||
gfxTextRun::CompressedGlyph g;
|
gfxTextRun::CompressedGlyph g;
|
||||||
|
@ -1143,20 +1165,14 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxContext *aContext,
|
||||||
detailedGlyphs.AppendElement();
|
detailedGlyphs.AppendElement();
|
||||||
details->mGlyphID = ginfo[glyphStart].codepoint;
|
details->mGlyphID = ginfo[glyphStart].codepoint;
|
||||||
|
|
||||||
// Rounding offsets independently of advances on the assumption
|
details->mXOffset = xOffset;
|
||||||
// that clusters use offsets and rounding of offsets should
|
details->mAdvance = advance;
|
||||||
// not accumulate, and that advances are typically between
|
|
||||||
// clusters.
|
|
||||||
hb_position_t x_offset = posInfo[glyphStart].x_offset;
|
|
||||||
details->mXOffset =
|
|
||||||
roundX ? appUnitsPerDevUnit * FixedToIntRound(x_offset)
|
|
||||||
: floor(hb2appUnits * x_offset + 0.5);
|
|
||||||
hb_position_t y_offset = posInfo[glyphStart].y_offset;
|
hb_position_t y_offset = posInfo[glyphStart].y_offset;
|
||||||
details->mYOffset = yPos -
|
details->mYOffset = yPos -
|
||||||
(roundY ? appUnitsPerDevUnit * FixedToIntRound(y_offset)
|
(roundY ? appUnitsPerDevUnit * FixedToIntRound(y_offset)
|
||||||
: floor(hb2appUnits * y_offset + 0.5));
|
: floor(hb2appUnits * y_offset + 0.5));
|
||||||
|
|
||||||
details->mAdvance = advance;
|
|
||||||
hb_position_t y_advance = posInfo[glyphStart].y_advance;
|
hb_position_t y_advance = posInfo[glyphStart].y_advance;
|
||||||
if (y_advance != 0) {
|
if (y_advance != 0) {
|
||||||
yPos -=
|
yPos -=
|
||||||
|
@ -1166,10 +1182,25 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxContext *aContext,
|
||||||
if (++glyphStart >= glyphEnd) {
|
if (++glyphStart >= glyphEnd) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x_offset = posInfo[glyphStart].x_offset;
|
||||||
x_advance = posInfo[glyphStart].x_advance;
|
x_advance = posInfo[glyphStart].x_advance;
|
||||||
advance =
|
if (roundX) {
|
||||||
roundX ? appUnitsPerDevUnit * FixedToIntRound(x_advance)
|
xOffset = appUnitsPerDevUnit *
|
||||||
: floor(hb2appUnits * x_advance + 0.5);
|
FixedToIntRound(x_offset + x_residual);
|
||||||
|
// Desired distance to the next reference point. The
|
||||||
|
// residual is considered here, and includes the residual
|
||||||
|
// from the base glyph offset and subsequent advances, so
|
||||||
|
// that the distance from the base glyph is optimized
|
||||||
|
// rather than the distance from combining marks.
|
||||||
|
x_advance += x_residual;
|
||||||
|
int intAdvance = FixedToIntRound(x_advance);
|
||||||
|
x_residual = x_advance - FloatToFixed(intAdvance);
|
||||||
|
advance = appUnitsPerDevUnit * intAdvance;
|
||||||
|
} else {
|
||||||
|
xOffset = floor(hb2appUnits * x_offset + 0.5);
|
||||||
|
advance = floor(hb2appUnits * x_advance + 0.5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxTextRun::CompressedGlyph g;
|
gfxTextRun::CompressedGlyph g;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче