DirectWrite to use aliased if ClearType is empty.

Some CJK fonts with some versions of DirectWrite return valid
data for bitmaps, but not for cleartype data.

For reference, two screenshots. M37 Stable and then with this patch:

http://imgur.com/9pf3rB9,EiTb6Li

See https://code.google.com/p/chromium/issues/detail?id=396624#c10 for
content of test html file.

R=eae@chromium.org, reed@google.com, shrikant@chromium.org, bungeman@chromium.org, cpu@chromium.org
BUG=chromium:407945

Review URL: https://codereview.chromium.org/504343007
diff --git a/src/core/SkGlyph.h b/src/core/SkGlyph.h
index 5e0ac7e..4290bb8 100644
--- a/src/core/SkGlyph.h
+++ b/src/core/SkGlyph.h
@@ -32,6 +32,7 @@
     void*       fDistanceField;
     uint8_t     fMaskFormat;
     int8_t      fRsbDelta, fLsbDelta;  // used by auto-kerning
+    int8_t      fForceBW;
 
     void init(uint32_t id) {
         fID             = id;
@@ -39,6 +40,7 @@
         fPath           = NULL;
         fDistanceField  = NULL;
         fMaskFormat     = MASK_FORMAT_UNKNOWN;
+        fForceBW        = 0;
     }
 
     /**
diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp
index f27497b..216c7dc 100644
--- a/src/ports/SkScalerContext_win_dw.cpp
+++ b/src/ports/SkScalerContext_win_dw.cpp
@@ -398,11 +398,11 @@
     glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
 }
 
-void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
-    glyph->fWidth = 0;
-
-    this->generateAdvance(glyph);
-
+void SkScalerContext_DW::getBoundingBox(SkGlyph* glyph,
+                                        DWRITE_RENDERING_MODE renderingMode,
+                                        DWRITE_TEXTURE_TYPE textureType,
+                                        RECT* bbox)
+{
     //Measure raster size.
     fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
     fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
@@ -430,16 +430,41 @@
              &run,
              1.0f, // pixelsPerDip,
              &fXform,
-             fRenderingMode,
+             renderingMode,
              fMeasuringMode,
              0.0f, // baselineOriginX,
              0.0f, // baselineOriginY,
              &glyphRunAnalysis),
          "Could not create glyph run analysis.");
 
-    RECT bbox;
-    HRVM(glyphRunAnalysis->GetAlphaTextureBounds(fTextureType, &bbox),
+    HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox),
          "Could not get texture bounds.");
+}
+
+void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
+    glyph->fWidth = 0;
+
+    this->generateAdvance(glyph);
+
+    RECT bbox;
+    this->getBoundingBox(glyph, fRenderingMode, fTextureType, &bbox);
+
+    // GetAlphaTextureBounds succeeds but returns an empty RECT if there are no
+    // glyphs of the specified texture type. When this happens, try with the
+    // alternate texture type.
+    if (bbox.left == bbox.right || bbox.top == bbox.bottom) {
+        if (DWRITE_TEXTURE_CLEARTYPE_3x1 == fTextureType) {
+            this->getBoundingBox(glyph,
+                                 DWRITE_RENDERING_MODE_ALIASED,
+                                 DWRITE_TEXTURE_ALIASED_1x1,
+                                 &bbox);
+            if (bbox.left != bbox.right && bbox.top != bbox.bottom) {
+                glyph->fForceBW = 1;
+            }
+        }
+        // TODO: handle the case where a request for DWRITE_TEXTURE_ALIASED_1x1
+        // fails, and try DWRITE_TEXTURE_CLEARTYPE_3x1.
+    }
 
     glyph->fWidth = SkToU16(bbox.right - bbox.left);
     glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
@@ -602,9 +627,12 @@
     }
 }
 
-const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph) {
+const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph,
+                                           DWRITE_RENDERING_MODE renderingMode,
+                                           DWRITE_TEXTURE_TYPE textureType)
+{
     int sizeNeeded = glyph.fWidth * glyph.fHeight;
-    if (DWRITE_RENDERING_MODE_ALIASED != fRenderingMode) {
+    if (DWRITE_RENDERING_MODE_ALIASED != renderingMode) {
         sizeNeeded *= 3;
     }
     if (sizeNeeded > fBits.count()) {
@@ -639,7 +667,7 @@
     HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run,
                                           1.0f, // pixelsPerDip,
                                           &fXform,
-                                          fRenderingMode,
+                                          renderingMode,
                                           fMeasuringMode,
                                           0.0f, // baselineOriginX,
                                           0.0f, // baselineOriginY,
@@ -653,7 +681,7 @@
     bbox.top = glyph.fTop;
     bbox.right = glyph.fLeft + glyph.fWidth;
     bbox.bottom = glyph.fTop + glyph.fHeight;
-    HRNM(glyphRunAnalysis->CreateAlphaTexture(fTextureType,
+    HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
                                               &bbox,
                                               fBits.begin(),
                                               sizeNeeded),
@@ -663,7 +691,13 @@
 
 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
     //Create the mask.
-    const void* bits = this->drawDWMask(glyph);
+    DWRITE_RENDERING_MODE renderingMode = fRenderingMode;
+    DWRITE_TEXTURE_TYPE textureType = fTextureType;
+    if (glyph.fForceBW) {
+        renderingMode = DWRITE_RENDERING_MODE_ALIASED;
+        textureType = DWRITE_TEXTURE_ALIASED_1x1;
+    }
+    const void* bits = this->drawDWMask(glyph, renderingMode, textureType);
     if (!bits) {
         sk_bzero(glyph.fImage, glyph.computeImageSize());
         return;
@@ -671,7 +705,7 @@
 
     //Copy the mask into the glyph.
     const uint8_t* src = (const uint8_t*)bits;
-    if (DWRITE_RENDERING_MODE_ALIASED == fRenderingMode) {
+    if (DWRITE_RENDERING_MODE_ALIASED == renderingMode) {
         bilevel_to_bw(src, glyph);
         const_cast<SkGlyph&>(glyph).fMaskFormat = SkMask::kBW_Format;
     } else if (!isLCD(fRec)) {
diff --git a/src/ports/SkScalerContext_win_dw.h b/src/ports/SkScalerContext_win_dw.h
index e8eff0d..e9eab94 100644
--- a/src/ports/SkScalerContext_win_dw.h
+++ b/src/ports/SkScalerContext_win_dw.h
@@ -33,7 +33,14 @@
     virtual void generateFontMetrics(SkPaint::FontMetrics*) SK_OVERRIDE;
 
 private:
-    const void* drawDWMask(const SkGlyph& glyph);
+    const void* drawDWMask(const SkGlyph& glyph,
+                           DWRITE_RENDERING_MODE renderingMode,
+                           DWRITE_TEXTURE_TYPE textureType);
+
+    void getBoundingBox(SkGlyph* glyph,
+                        DWRITE_RENDERING_MODE renderingMode,
+                        DWRITE_TEXTURE_TYPE textureType,
+                        RECT* bbox);
 
     SkTDArray<uint8_t> fBits;
     /** The total matrix without the text height scale. */