DirectWrite to detect GDI only fonts.

The exist a number of webfonts which have poor hinting which look very
bad with any vertical subsampling. The fonts often rely on drop out
control to avoid zero coverage in the y direction. As a result, any font
with hints but no 'gasp' table is considered to be poorly hinted in this
way, and will not be rendered with vertical subsampling when hinted.

R=eae@chromium.org, reed@google.com, mtklein@google.com

Author: bungeman@google.com

Review URL: https://codereview.chromium.org/363433002
diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp
index 99799a5..345cefd 100644
--- a/src/ports/SkScalerContext_win_dw.cpp
+++ b/src/ports/SkScalerContext_win_dw.cpp
@@ -18,6 +18,7 @@
 #include "SkOTTable_EBLC.h"
 #include "SkOTTable_EBSC.h"
 #include "SkOTTable_gasp.h"
+#include "SkOTTable_maxp.h"
 #include "SkPath.h"
 #include "SkScalerContext.h"
 #include "SkScalerContext_win_dw.h"
@@ -31,6 +32,27 @@
            SkMask::kLCD32_Format == rec.fMaskFormat;
 }
 
+static bool is_hinted_without_gasp(DWriteFontTypeface* typeface) {
+    AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get());
+    if (!maxp.fExists) {
+        return false;
+    }
+    if (maxp.fSize < sizeof(SkOTTableMaximumProfile::Version::TT)) {
+        return false;
+    }
+    if (maxp->version.version != SkOTTableMaximumProfile::Version::TT::VERSION) {
+        return false;
+    }
+
+    if (0 == maxp->version.tt.maxSizeOfInstructions) {
+        // No hints.
+        return false;
+    }
+
+    AutoTDWriteTable<SkOTTableGridAndScanProcedure> gasp(typeface->fDWriteFontFace.get());
+    return !gasp.fExists;
+}
+
 /** A PPEMRange is inclusive, [min, max]. */
 struct PPEMRange {
     int min;
@@ -254,6 +276,17 @@
         fTextSizeMeasure = gdiTextSize;
         fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
 
+    // Fonts that have hints but no gasp table get non-symmetric rendering.
+    // Usually such fonts have low quality hints which were never tested
+    // with anything but GDI ClearType classic. Such fonts often rely on
+    // drop out control in the y direction in order to be legible.
+    } else if (is_hinted_without_gasp(typeface)) {
+        fTextSizeRender = gdiTextSize;
+        fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL;
+        fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
+        fTextSizeMeasure = realTextSize;
+        fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
+
     // The normal case is to use natural symmetric rendering and linear metrics.
     } else {
         fTextSizeRender = realTextSize;
@@ -354,6 +387,9 @@
     if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
         DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
     {
+        // DirectWrite produced 'compatible' metrics, but while close,
+        // the end result is not always an integer as it would be with GDI.
+        vecs[0].fX = SkScalarRoundToScalar(advanceX);
         fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
     } else {
         fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs));