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>
diff --git a/gm/fontscaler.cpp b/gm/fontscaler.cpp
index a650d2f..d0898b4 100644
--- a/gm/fontscaler.cpp
+++ b/gm/fontscaler.cpp
@@ -65,6 +65,7 @@
             }
             canvas->translate(0, SkIntToScalar(360));
             font.setSubpixel(true);
+            font.setLinearMetrics(true);
         }
     }
 
diff --git a/gm/fontscalerdistortable.cpp b/gm/fontscalerdistortable.cpp
index f3e6cb5..a2d9c13 100644
--- a/gm/fontscalerdistortable.cpp
+++ b/gm/fontscalerdistortable.cpp
@@ -88,6 +88,7 @@
             }
             canvas->translate(0, SkIntToScalar(360));
             font.setSubpixel(true);
+            font.setLinearMetrics(true);
         }
         return DrawResult::kOk;
     }
diff --git a/modules/skottie/src/SkottieShaper.cpp b/modules/skottie/src/SkottieShaper.cpp
index 1a33379..ab9c20b 100644
--- a/modules/skottie/src/SkottieShaper.cpp
+++ b/modules/skottie/src/SkottieShaper.cpp
@@ -53,6 +53,7 @@
         , fShaper(SkShaper::Make()) {
         fFont.setHinting(kNo_SkFontHinting);
         fFont.setSubpixel(true);
+        fFont.setLinearMetrics(true);
         fFont.setEdging(SkFont::Edging::kAntiAlias);
     }
 
diff --git a/src/core/SkFont.cpp b/src/core/SkFont.cpp
index ca933bc..48685da 100644
--- a/src/core/SkFont.cpp
+++ b/src/core/SkFont.cpp
@@ -113,8 +113,11 @@
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 SkScalar SkFont::setupForAsPaths(SkPaint* paint) {
-    constexpr uint32_t flagsToIgnore = kLinearMetrics_PrivFlag        |
-                                       kEmbeddedBitmaps_PrivFlag      |
+    constexpr uint32_t flagsToIgnore =
+#ifdef SK_IGNORE_LINEAR_METRICS_FIX
+                                       kLinearMetrics_PrivFlag   |
+#endif
+                                       kEmbeddedBitmaps_PrivFlag |
                                        kForceAutoHinting_PrivFlag;
 
     fFlags = (fFlags & ~flagsToIgnore) | kSubpixel_PrivFlag;
@@ -145,9 +148,11 @@
         if (paint) {
             fPaint = *paint;
         }
-        if (font.isLinearMetrics() ||
-            SkDraw::ShouldDrawTextAsPaths(font, fPaint, SkMatrix::I()))
-        {
+        if (
+#ifdef SK_IGNORE_LINEAR_METRICS_FIX
+            font.isLinearMetrics() ||
+#endif
+            SkDraw::ShouldDrawTextAsPaths(font, fPaint, SkMatrix::I())) {
             SkFont* f = fLazyFont.set(font);
             fScale = f->setupForAsPaths(nullptr);
             fFont = f;
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index d197fa7..064ceae 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -1025,18 +1025,27 @@
     if (font.isForceAutoHinting()) {
         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);
 
+#ifdef SK_IGNORE_LINEAR_METRICS_FIX
     // if linear-text is on, then we force hinting to be off (since that's sort of
     // the point of linear-text.
     SkFontHinting hinting = (SkFontHinting)font.getHinting();
     if (font.isLinearMetrics()) {
         hinting = kNo_SkFontHinting;
     }
-
+    rec->setHinting(font.getHinting());
+#else
     // these modify fFlags, so do them after assigning fFlags
-    rec->setHinting(hinting);
-
+    rec->setHinting(font.getHinting());
+#endif
     rec->setLuminanceColor(SkPaintPriv::ComputeLuminanceColor(paint));
 
     // For now always set the paint gamma equal to the device gamma.
diff --git a/src/core/SkScalerContext.h b/src/core/SkScalerContext.h
index 96f3dc0..ff2a543 100644
--- a/src/core/SkScalerContext.h
+++ b/src/core/SkScalerContext.h
@@ -241,6 +241,7 @@
         // Generate A8 from LCD source (for GDI and CoreGraphics).
         // only meaningful if fMaskFormat is kA8
         kGenA8FromLCD_Flag        = 0x0800, // could be 0x200 (bit meaning dependent on fMaskFormat)
+        kLinearMetrics_Flag       = 0x1000,
     };
 
     // computed values
@@ -261,6 +262,10 @@
         return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag);
     }
 
+     bool isLinearMetrics() const {
+        return SkToBool(fRec.fFlags & kLinearMetrics_Flag);
+    }
+
     // DEPRECATED
     bool isVertical() const { return false; }
 
diff --git a/src/core/SkTextBlob.cpp b/src/core/SkTextBlob.cpp
index 7c77816..1ab3179 100644
--- a/src/core/SkTextBlob.cpp
+++ b/src/core/SkTextBlob.cpp
@@ -906,8 +906,6 @@
                                const SkPaint* paint) : fFont(font) {
     SkAssertResult(count >= 0);
 
-    fFont.setLinearMetrics(true);
-
     if (paint) {
         fPaint = *paint;
     }
@@ -915,6 +913,9 @@
 
     // can't use our canonical size if we need to apply patheffects
     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;
         fFont.setSize(SkIntToScalar(SkFontPriv::kCanonicalTextSizeForPaths));
         // Note: fScale can be zero here (even if it wasn't before the divide). It can also
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index 8d8b45a..4f09d54 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -845,7 +845,7 @@
     fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
 
     // compute the flags we send to Load_Glyph
-    bool linearMetrics = this->isSubpixel();
+    bool linearMetrics = this->isLinearMetrics();
     {
         FT_Int32 loadFlags = FT_LOAD_DEFAULT;
 
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index e2f0f31..3d6a7c3 100644
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -723,7 +723,7 @@
         }
 
         // Create a hires matrix if we need linear metrics.
-        if (this->isSubpixel()) {
+        if (this->isLinearMetrics()) {
             OUTLINETEXTMETRIC otm;
             UINT success = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
             if (0 == success) {
@@ -885,7 +885,7 @@
     glyph->fAdvanceX = (float)((int)gm.gmCellIncX);
     glyph->fAdvanceY = (float)((int)gm.gmCellIncY);
 
-    if (this->isSubpixel()) {
+    if ((fTM.tmPitchAndFamily & TMPF_VECTOR) && this->isLinearMetrics()) {
         sk_bzero(&gm, sizeof(gm));
         status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, nullptr, &fHighResMat22);
         if (GDI_ERROR != status) {
diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp
index 6e91a74..de911fc 100644
--- a/src/ports/SkScalerContext_win_dw.cpp
+++ b/src/ports/SkScalerContext_win_dw.cpp
@@ -358,7 +358,7 @@
         }
     }
 
-    if (this->isSubpixel()) {
+    if (this->isLinearMetrics()) {
         fTextSizeMeasure = realTextSize;
         fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
     }