Bug 1232822 (part 5) - Moz2Dify GetRoundOffsetsToPixels(). r=jfkthame.

Make GetRoundOffsetsToPixel() take a DrawTarget instead of a gfxContext. This
requires moving it into gfxFontShaper. The only change of note within the
function is the use of aDrawTarget->GetTransform().HasNonTranslation() instead
of CurrentMatrix().HasNonTranslation().
This commit is contained in:
Nicholas Nethercote 2015-12-15 13:56:40 -08:00
parent ab6a8c401a
commit d6cbcc8ed2
6 changed files with 96 additions and 93 deletions

View File

@ -1296,86 +1296,3 @@ gfxContext::PushNewDT(gfxContentType content)
mDT = newDT;
}
/**
* Work out whether cairo will snap inter-glyph spacing to pixels.
*
* Layout does not align text to pixel boundaries, so, with font drawing
* backends that snap glyph positions to pixels, it is important that
* inter-glyph spacing within words is always an integer number of pixels.
* This ensures that the drawing backend snaps all of the word's glyphs in the
* same direction and so inter-glyph spacing remains the same.
*/
void
gfxContext::GetRoundOffsetsToPixels(bool *aRoundX, bool *aRoundY)
{
*aRoundX = false;
// Could do something fancy here for ScaleFactors of
// AxisAlignedTransforms, but we leave things simple.
// Not much point rounding if a matrix will mess things up anyway.
// Also return false for non-cairo contexts.
if (CurrentMatrix().HasNonTranslation()) {
*aRoundY = false;
return;
}
// All raster backends snap glyphs to pixels vertically.
// Print backends set CAIRO_HINT_METRICS_OFF.
*aRoundY = true;
cairo_t *cr = gfxContext::RefCairo(GetDrawTarget());
cairo_scaled_font_t *scaled_font = cairo_get_scaled_font(cr);
// bug 1198921 - this sometimes fails under Windows for whatver reason
NS_ASSERTION(scaled_font, "null cairo scaled font should never be returned "
"by cairo_get_scaled_font");
if (!scaled_font) {
*aRoundX = true; // default to the same as the fallback path below
return;
}
// Sometimes hint metrics gets set for us, most notably for printing.
cairo_font_options_t *font_options = cairo_font_options_create();
cairo_scaled_font_get_font_options(scaled_font, font_options);
cairo_hint_metrics_t hint_metrics =
cairo_font_options_get_hint_metrics(font_options);
cairo_font_options_destroy(font_options);
switch (hint_metrics) {
case CAIRO_HINT_METRICS_OFF:
*aRoundY = false;
return;
case CAIRO_HINT_METRICS_DEFAULT:
// Here we mimic what cairo surface/font backends do. Printing
// surfaces have already been handled by hint_metrics. The
// fallback show_glyphs implementation composites pixel-aligned
// glyph surfaces, so we just pick surface/font combinations that
// override this.
switch (cairo_scaled_font_get_type(scaled_font)) {
#if CAIRO_HAS_DWRITE_FONT // dwrite backend is not in std cairo releases yet
case CAIRO_FONT_TYPE_DWRITE:
// show_glyphs is implemented on the font and so is used for
// all surface types; however, it may pixel-snap depending on
// the dwrite rendering mode
if (!cairo_dwrite_scaled_font_get_force_GDI_classic(scaled_font) &&
gfxWindowsPlatform::GetPlatform()->DWriteMeasuringMode() ==
DWRITE_MEASURING_MODE_NATURAL) {
return;
}
MOZ_FALLTHROUGH;
#endif
case CAIRO_FONT_TYPE_QUARTZ:
// Quartz surfaces implement show_glyphs for Quartz fonts
if (cairo_surface_get_type(cairo_get_target(cr)) ==
CAIRO_SURFACE_TYPE_QUARTZ) {
return;
}
break;
default:
break;
}
break;
case CAIRO_HINT_METRICS_ON:
break;
}
*aRoundX = true;
}

View File

@ -445,9 +445,6 @@ public:
mozilla::gfx::Point GetDeviceOffset() const;
// Work out whether cairo will snap inter-glyph spacing to pixels.
void GetRoundOffsetsToPixels(bool *aRoundX, bool *aRoundY);
#ifdef MOZ_DUMP_PAINTING
/**
* Debug functions to encode the current surface as a PNG and export it.

View File

@ -549,6 +549,90 @@ gfxFontShaper::MergeFontFeatures(
}
}
// Work out whether cairo will snap inter-glyph spacing to pixels.
//
// Layout does not align text to pixel boundaries, so, with font drawing
// backends that snap glyph positions to pixels, it is important that
// inter-glyph spacing within words is always an integer number of pixels.
// This ensures that the drawing backend snaps all of the word's glyphs in the
// same direction and so inter-glyph spacing remains the same.
//
/* static */ void
gfxFontShaper::GetRoundOffsetsToPixels(DrawTarget* aDrawTarget,
bool* aRoundX, bool* aRoundY)
{
*aRoundX = false;
// Could do something fancy here for ScaleFactors of
// AxisAlignedTransforms, but we leave things simple.
// Not much point rounding if a matrix will mess things up anyway.
// Also return false for non-cairo contexts.
if (aDrawTarget->GetTransform().HasNonTranslation()) {
*aRoundY = false;
return;
}
// All raster backends snap glyphs to pixels vertically.
// Print backends set CAIRO_HINT_METRICS_OFF.
*aRoundY = true;
cairo_t* cr = gfxContext::RefCairo(aDrawTarget);
cairo_scaled_font_t *scaled_font = cairo_get_scaled_font(cr);
// bug 1198921 - this sometimes fails under Windows for whatver reason
NS_ASSERTION(scaled_font, "null cairo scaled font should never be returned "
"by cairo_get_scaled_font");
if (!scaled_font) {
*aRoundX = true; // default to the same as the fallback path below
return;
}
// Sometimes hint metrics gets set for us, most notably for printing.
cairo_font_options_t *font_options = cairo_font_options_create();
cairo_scaled_font_get_font_options(scaled_font, font_options);
cairo_hint_metrics_t hint_metrics =
cairo_font_options_get_hint_metrics(font_options);
cairo_font_options_destroy(font_options);
switch (hint_metrics) {
case CAIRO_HINT_METRICS_OFF:
*aRoundY = false;
return;
case CAIRO_HINT_METRICS_DEFAULT:
// Here we mimic what cairo surface/font backends do. Printing
// surfaces have already been handled by hint_metrics. The
// fallback show_glyphs implementation composites pixel-aligned
// glyph surfaces, so we just pick surface/font combinations that
// override this.
switch (cairo_scaled_font_get_type(scaled_font)) {
#if CAIRO_HAS_DWRITE_FONT // dwrite backend is not in std cairo releases yet
case CAIRO_FONT_TYPE_DWRITE:
// show_glyphs is implemented on the font and so is used for
// all surface types; however, it may pixel-snap depending on
// the dwrite rendering mode
if (!cairo_dwrite_scaled_font_get_force_GDI_classic(scaled_font) &&
gfxWindowsPlatform::GetPlatform()->DWriteMeasuringMode() ==
DWRITE_MEASURING_MODE_NATURAL) {
return;
}
MOZ_FALLTHROUGH;
#endif
case CAIRO_FONT_TYPE_QUARTZ:
// Quartz surfaces implement show_glyphs for Quartz fonts
if (cairo_surface_get_type(cairo_get_target(cr)) ==
CAIRO_SURFACE_TYPE_QUARTZ) {
return;
}
break;
default:
break;
}
break;
case CAIRO_HINT_METRICS_ON:
break;
}
*aRoundX = true;
}
void
gfxShapedText::SetupClusterBoundaries(uint32_t aOffset,
const char16_t *aString,

View File

@ -612,6 +612,8 @@ protected:
class gfxFontShaper {
public:
typedef mozilla::gfx::DrawTarget DrawTarget;
explicit gfxFontShaper(gfxFont *aFont)
: mFont(aFont)
{
@ -644,6 +646,10 @@ public:
void* aHandleFeatureData);
protected:
// Work out whether cairo will snap inter-glyph spacing to pixels.
static void GetRoundOffsetsToPixels(DrawTarget* aDrawTarget,
bool* aRoundX, bool* aRoundY);
// the font this shaper is working with. The font owns a nsAutoPtr reference
// to this object, and will destroy it before it dies. Thus, mFont will always
// be valid.

View File

@ -268,9 +268,8 @@ gfxGraphiteShaper::SetGlyphsFromSegment(gfxContext *aContext,
}
}
bool roundX;
bool roundY;
aContext->GetRoundOffsetsToPixels(&roundX, &roundY);
bool roundX, roundY;
GetRoundOffsetsToPixels(aContext->GetDrawTarget(), &roundX, &roundY);
gfxShapedText::CompressedGlyph *charGlyphs =
aShapedText->GetCharacterGlyphs() + aOffset;

View File

@ -1617,12 +1617,12 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxContext *aContext,
int32_t glyphStart = 0; // looking for a clump that starts at this glyph
int32_t charStart = 0; // and this char index within the range of the run
bool roundI;
bool roundB;
bool roundI, roundB;
DrawTarget* drawTarget = aContext->GetDrawTarget();
if (aVertical) {
aContext->GetRoundOffsetsToPixels(&roundB, &roundI);
GetRoundOffsetsToPixels(drawTarget, &roundB, &roundI);
} else {
aContext->GetRoundOffsetsToPixels(&roundI, &roundB);
GetRoundOffsetsToPixels(drawTarget, &roundI, &roundB);
}
int32_t appUnitsPerDevUnit = aShapedText->GetAppUnitsPerDevUnit();