Fix advances for aliased text with DirectWrite.
authorBen Wagner <bungeman@google.com>
Fri, 14 Apr 2017 15:39:34 +0000 (11:39 -0400)
committerMatthew Leibowitz <mattleibow@live.com>
Fri, 21 Apr 2017 07:38:54 +0000 (09:38 +0200)
The existing code assumes that GetGdiCompatibleGlyphMetrics transform
parameter acts the same as the GetGlyphOutlineW lpmat2 parameter.
However, it appears this is very much not true.

BUG=skia:6499

Change-Id: I88c762b27acd09cc746da4d6e2b901540876908a
Reviewed-on: https://skia-review.googlesource.com/13479
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>

src/ports/SkScalerContext_win_dw.cpp
src/ports/SkScalerContext_win_dw.h

index 10afb5a..729a738 100644 (file)
@@ -236,9 +236,7 @@ SkScalerContext_DW::SkScalerContext_DW(sk_sp<DWriteFontTypeface> typefaceRef,
     // horizontal glyphs and the subpixel flag should not affect glyph shapes.
 
     SkVector scale;
-    SkMatrix GsA;
-    fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale,
-                         &scale, &fSkXform, &GsA, &fG_inv);
+    fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale, &scale, &fSkXform);
 
     fXform.m11 = SkScalarToFloat(fSkXform.getScaleX());
     fXform.m12 = SkScalarToFloat(fSkXform.getSkewY());
@@ -247,13 +245,6 @@ SkScalerContext_DW::SkScalerContext_DW(sk_sp<DWriteFontTypeface> typefaceRef,
     fXform.dx = 0;
     fXform.dy = 0;
 
-    fGsA.m11 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleX));
-    fGsA.m12 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewY)); // This should be ~0.
-    fGsA.m21 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewX));
-    fGsA.m22 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleY));
-    fGsA.dx = 0;
-    fGsA.dy = 0;
-
     // realTextSize is the actual device size we want (as opposed to the size the user requested).
     // gdiTextSize is the size we request when GDI compatible.
     // If the scale is negative, this means the matrix will do the flip anyway.
@@ -367,7 +358,9 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
         HRVM(this->getDWriteTypeface()->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
                  fTextSizeMeasure,
                  1.0f, // pixelsPerDip
-                 &fGsA,
+                 // This parameter does not act like the lpmat2 parameter to GetGlyphOutlineW.
+                 // If it did then GsA here and G_inv below to mapVectors.
+                 nullptr,
                  DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode,
                  &glyphId, 1,
                  &gm),
@@ -387,20 +380,18 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
                                        SkIntToScalar(gm.advanceWidth),
                                        SkIntToScalar(dwfm.designUnitsPerEm));
 
-    SkVector vecs[1] = { { advanceX, 0 } };
+    SkVector advance = { advanceX, 0 };
     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));
+        advance.fX = SkScalarRoundToScalar(advance.fX);
     }
+    fSkXform.mapVectors(&advance, 1);
 
-    glyph->fAdvanceX = SkScalarToFloat(vecs[0].fX);
-    glyph->fAdvanceY = SkScalarToFloat(vecs[0].fY);
+    glyph->fAdvanceX = SkScalarToFloat(advance.fX);
+    glyph->fAdvanceY = SkScalarToFloat(advance.fY);
 }
 
 HRESULT SkScalerContext_DW::getBoundingBox(SkGlyph* glyph,
index 7b45c32..695a10f 100644 (file)
@@ -64,14 +64,6 @@ private:
     SkMatrix fSkXform;
     /** The total matrix without the text height scale. */
     DWRITE_MATRIX fXform;
-    /** The non-rotational part of total matrix without the text height scale.
-     *  This is used to find the magnitude of gdi compatible advances.
-     */
-    DWRITE_MATRIX fGsA;
-    /** The inverse of the rotational part of the total matrix.
-     *  This is used to find the direction of gdi compatible advances.
-     */
-    SkMatrix fG_inv;
     /** The text size to render with. */
     SkScalar fTextSizeRender;
     /** The text size to measure with. */