Use linear metrics flag for linear metrics.

Now that no one is using the linear metrics flag directly, change the
meaning from 'no-hinting and subpixel positioning at an odd size when
measuring and just no-hinting when drawing' to meaning 'use linear
metrics'.

This also changes the font hosts to no longer use subpixel positioning
as a proxy for this value. This fixes outstanding bugs in Chromium about
getting the right metrics for hinted fonts.

Change-Id: I033b3d5ad431eba906a89cc0fefc59cd6702a02c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/209174
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Herb Derby <herb@google.com>
This commit is contained in:
Ben Wagner 2019-04-18 16:37:45 -04:00 committed by Skia Commit-Bot
parent f0a5369d0c
commit f460eeec99
10 changed files with 37 additions and 14 deletions

View File

@ -65,6 +65,7 @@ protected:
} }
canvas->translate(0, SkIntToScalar(360)); canvas->translate(0, SkIntToScalar(360));
font.setSubpixel(true); font.setSubpixel(true);
font.setLinearMetrics(true);
} }
} }

View File

@ -88,6 +88,7 @@ protected:
} }
canvas->translate(0, SkIntToScalar(360)); canvas->translate(0, SkIntToScalar(360));
font.setSubpixel(true); font.setSubpixel(true);
font.setLinearMetrics(true);
} }
return DrawResult::kOk; return DrawResult::kOk;
} }

View File

@ -53,6 +53,7 @@ public:
, fShaper(SkShaper::Make()) { , fShaper(SkShaper::Make()) {
fFont.setHinting(kNo_SkFontHinting); fFont.setHinting(kNo_SkFontHinting);
fFont.setSubpixel(true); fFont.setSubpixel(true);
fFont.setLinearMetrics(true);
fFont.setEdging(SkFont::Edging::kAntiAlias); fFont.setEdging(SkFont::Edging::kAntiAlias);
} }

View File

@ -113,7 +113,10 @@ SkFont SkFont::makeWithSize(SkScalar newSize) const {
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
SkScalar SkFont::setupForAsPaths(SkPaint* paint) { SkScalar SkFont::setupForAsPaths(SkPaint* paint) {
constexpr uint32_t flagsToIgnore = kLinearMetrics_PrivFlag | constexpr uint32_t flagsToIgnore =
#ifdef SK_IGNORE_LINEAR_METRICS_FIX
kLinearMetrics_PrivFlag |
#endif
kEmbeddedBitmaps_PrivFlag | kEmbeddedBitmaps_PrivFlag |
kForceAutoHinting_PrivFlag; kForceAutoHinting_PrivFlag;
@ -145,9 +148,11 @@ public:
if (paint) { if (paint) {
fPaint = *paint; fPaint = *paint;
} }
if (font.isLinearMetrics() || if (
SkDraw::ShouldDrawTextAsPaths(font, fPaint, SkMatrix::I())) #ifdef SK_IGNORE_LINEAR_METRICS_FIX
{ font.isLinearMetrics() ||
#endif
SkDraw::ShouldDrawTextAsPaths(font, fPaint, SkMatrix::I())) {
SkFont* f = fLazyFont.set(font); SkFont* f = fLazyFont.set(font);
fScale = f->setupForAsPaths(nullptr); fScale = f->setupForAsPaths(nullptr);
fFont = f; fFont = f;

View File

@ -1025,18 +1025,27 @@ void SkScalerContext::MakeRecAndEffects(const SkFont& font, const SkPaint& paint
if (font.isForceAutoHinting()) { if (font.isForceAutoHinting()) {
flags |= SkScalerContext::kForceAutohinting_Flag; flags |= SkScalerContext::kForceAutohinting_Flag;
} }
#ifdef SK_IGNORE_LINEAR_METRICS_FIX
if (font.isSubpixel()) {
#else
if (font.isLinearMetrics()) {
#endif
flags |= SkScalerContext::kLinearMetrics_Flag;
}
rec->fFlags = SkToU16(flags); rec->fFlags = SkToU16(flags);
#ifdef SK_IGNORE_LINEAR_METRICS_FIX
// if linear-text is on, then we force hinting to be off (since that's sort of // if linear-text is on, then we force hinting to be off (since that's sort of
// the point of linear-text. // the point of linear-text.
SkFontHinting hinting = (SkFontHinting)font.getHinting(); SkFontHinting hinting = (SkFontHinting)font.getHinting();
if (font.isLinearMetrics()) { if (font.isLinearMetrics()) {
hinting = kNo_SkFontHinting; hinting = kNo_SkFontHinting;
} }
rec->setHinting(font.getHinting());
#else
// these modify fFlags, so do them after assigning fFlags // these modify fFlags, so do them after assigning fFlags
rec->setHinting(hinting); rec->setHinting(font.getHinting());
#endif
rec->setLuminanceColor(SkPaintPriv::ComputeLuminanceColor(paint)); rec->setLuminanceColor(SkPaintPriv::ComputeLuminanceColor(paint));
// For now always set the paint gamma equal to the device gamma. // For now always set the paint gamma equal to the device gamma.

View File

@ -241,6 +241,7 @@ public:
// Generate A8 from LCD source (for GDI and CoreGraphics). // Generate A8 from LCD source (for GDI and CoreGraphics).
// only meaningful if fMaskFormat is kA8 // only meaningful if fMaskFormat is kA8
kGenA8FromLCD_Flag = 0x0800, // could be 0x200 (bit meaning dependent on fMaskFormat) kGenA8FromLCD_Flag = 0x0800, // could be 0x200 (bit meaning dependent on fMaskFormat)
kLinearMetrics_Flag = 0x1000,
}; };
// computed values // computed values
@ -261,6 +262,10 @@ public:
return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag); return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag);
} }
bool isLinearMetrics() const {
return SkToBool(fRec.fFlags & kLinearMetrics_Flag);
}
// DEPRECATED // DEPRECATED
bool isVertical() const { return false; } bool isVertical() const { return false; }

View File

@ -906,8 +906,6 @@ SkTextBaseIter::SkTextBaseIter(const SkGlyphID glyphs[], int count, const SkFont
const SkPaint* paint) : fFont(font) { const SkPaint* paint) : fFont(font) {
SkAssertResult(count >= 0); SkAssertResult(count >= 0);
fFont.setLinearMetrics(true);
if (paint) { if (paint) {
fPaint = *paint; fPaint = *paint;
} }
@ -915,6 +913,9 @@ SkTextBaseIter::SkTextBaseIter(const SkGlyphID glyphs[], int count, const SkFont
// can't use our canonical size if we need to apply patheffects // can't use our canonical size if we need to apply patheffects
if (fPaint.getPathEffect() == nullptr) { if (fPaint.getPathEffect() == nullptr) {
// If the wrong size is going to be used, don't hint anything.
fFont.setHinting(kNo_SkFontHinting);
fFont.setSubpixel(true);
fScale = fFont.getSize() / SkFontPriv::kCanonicalTextSizeForPaths; fScale = fFont.getSize() / SkFontPriv::kCanonicalTextSizeForPaths;
fFont.setSize(SkIntToScalar(SkFontPriv::kCanonicalTextSizeForPaths)); fFont.setSize(SkIntToScalar(SkFontPriv::kCanonicalTextSizeForPaths));
// Note: fScale can be zero here (even if it wasn't before the divide). It can also // Note: fScale can be zero here (even if it wasn't before the divide). It can also

View File

@ -845,7 +845,7 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(sk_sp<SkTypeface> typeface,
fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
// compute the flags we send to Load_Glyph // compute the flags we send to Load_Glyph
bool linearMetrics = this->isSubpixel(); bool linearMetrics = this->isLinearMetrics();
{ {
FT_Int32 loadFlags = FT_LOAD_DEFAULT; FT_Int32 loadFlags = FT_LOAD_DEFAULT;

View File

@ -723,7 +723,7 @@ SkScalerContext_GDI::SkScalerContext_GDI(sk_sp<LogFontTypeface> rawTypeface,
} }
// Create a hires matrix if we need linear metrics. // Create a hires matrix if we need linear metrics.
if (this->isSubpixel()) { if (this->isLinearMetrics()) {
OUTLINETEXTMETRIC otm; OUTLINETEXTMETRIC otm;
UINT success = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm); UINT success = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
if (0 == success) { if (0 == success) {
@ -885,7 +885,7 @@ void SkScalerContext_GDI::generateMetrics(SkGlyph* glyph) {
glyph->fAdvanceX = (float)((int)gm.gmCellIncX); glyph->fAdvanceX = (float)((int)gm.gmCellIncX);
glyph->fAdvanceY = (float)((int)gm.gmCellIncY); glyph->fAdvanceY = (float)((int)gm.gmCellIncY);
if (this->isSubpixel()) { if ((fTM.tmPitchAndFamily & TMPF_VECTOR) && this->isLinearMetrics()) {
sk_bzero(&gm, sizeof(gm)); sk_bzero(&gm, sizeof(gm));
status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, nullptr, &fHighResMat22); status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, nullptr, &fHighResMat22);
if (GDI_ERROR != status) { if (GDI_ERROR != status) {

View File

@ -358,7 +358,7 @@ SkScalerContext_DW::SkScalerContext_DW(sk_sp<DWriteFontTypeface> typefaceRef,
} }
} }
if (this->isSubpixel()) { if (this->isLinearMetrics()) {
fTextSizeMeasure = realTextSize; fTextSizeMeasure = realTextSize;
fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
} }