Move distance field font code into GrDistanceFieldTextContext.

This avoids the SkDraw path and renders the distance field glyphs directly from
GrDistanceFieldTextContext. It also disables LCD, subpixel and autohinting, and
removes the supporting code when rendering DF fonts.

R=reed@google.com, bsalomon@google.com, robertphillips@google.com

Author: jvanverth@google.com

Review URL: https://codereview.chromium.org/85653004

git-svn-id: http://skia.googlecode.com/svn/trunk@12770 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index 2f67c49..d04e52e 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -9,6 +9,7 @@
 #include "GrAtlas.h"
 #include "GrDrawTarget.h"
 #include "GrFontScaler.h"
+#include "SkGlyphCache.h"
 #include "GrIndexBuffer.h"
 #include "GrTextStrike.h"
 #include "GrTextStrike_impl.h"
@@ -19,18 +20,16 @@
 
 static const int kGlyphCoordsAttributeIndex = 1;
 
+static const int kBaseDFFontSize = 32;
+
 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
                 "Dump the contents of the font cache before every purge.");
 
-
 GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
-                                                       const GrPaint& paint,
-                                                       SkColor color,
-                                                       SkScalar textRatio)
-                                                     : GrTextContext(context, paint)
-                                                     , fTextRatio(textRatio) {
-    fSkPaintColor = color;
-
+                                                       const GrPaint& grPaint,
+                                                       const SkPaint& skPaint)
+                                                     : GrTextContext(context, grPaint),
+                                                       fSkPaint(skPaint) {
     fStrike = NULL;
 
     fCurrTexture = NULL;
@@ -38,6 +37,13 @@
 
     fVertices = NULL;
     fMaxVertices = 0;
+
+    fTextRatio = fSkPaint.getTextSize()/kBaseDFFontSize;
+
+    fSkPaint.setTextSize(SkIntToScalar(kBaseDFFontSize));
+    fSkPaint.setLCDRenderText(false);
+    fSkPaint.setAutohinted(false);
+    fSkPaint.setSubpixelText(false);
 }
 
 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
@@ -81,11 +87,11 @@
             // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
             // the mask texture color. The end result is that we get
             //            mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
-            int a = SkColorGetA(fSkPaintColor);
+            int a = SkColorGetA(fSkPaint.getColor());
             // paintAlpha
             drawState->setColor(SkColorSetARGB(a, a, a, a));
             // paintColor
-            drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaintColor));
+            drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
             drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
         } else {
             // set back to normal in case we took LCD path previously.
@@ -276,3 +282,127 @@
                                           2 * sizeof(SkPoint));
     fCurrVertex += 4;
 }
+
+void GrDistanceFieldTextContext::drawText(const char text[], size_t byteLength,
+                                          SkScalar x, SkScalar y, SkGlyphCache* cache,
+                                          GrFontScaler* fontScaler) {
+    SkASSERT(byteLength == 0 || text != NULL);
+
+    // nothing to draw
+    if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
+        return;
+    }
+
+    SkScalar sizeRatio = fTextRatio;
+
+    SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+    // need to measure first
+    // TODO - generate positions and pre-load cache as well?
+    const char* stop = text + byteLength;
+    if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
+        SkFixed    stopX = 0;
+        SkFixed    stopY = 0;
+
+        const char* textPtr = text;
+        while (textPtr < stop) {
+            // don't need x, y here, since all subpixel variants will have the
+            // same advance
+            const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);
+
+            stopX += glyph.fAdvanceX;
+            stopY += glyph.fAdvanceY;
+        }
+        SkASSERT(textPtr == stop);
+
+        SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio;
+        SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio;
+
+        if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
+            alignX = SkScalarHalf(alignX);
+            alignY = SkScalarHalf(alignY);
+        }
+
+        x -= alignX;
+        y -= alignY;
+    }
+
+    SkFixed fx = SkScalarToFixed(x) + SK_FixedHalf;
+    SkFixed fy = SkScalarToFixed(y) + SK_FixedHalf;
+    SkFixed fixedScale = SkScalarToFixed(sizeRatio);
+    while (text < stop) {
+        const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy);
+
+        if (glyph.fWidth) {
+            this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                glyph.getSubXFixed(),
+                                                glyph.getSubYFixed()),
+                                  SkFixedFloorToFixed(fx),
+                                  SkFixedFloorToFixed(fy),
+                                  fontScaler);
+        }
+
+        fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
+        fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
+    }
+}
+
+void GrDistanceFieldTextContext::drawPosText(const char text[], size_t byteLength,
+                                             const SkScalar pos[], SkScalar constY,
+                                             int scalarsPerPosition,
+                                             SkGlyphCache* cache, GrFontScaler* fontScaler) {
+
+    SkASSERT(byteLength == 0 || text != NULL);
+    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
+
+    // nothing to draw
+    if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
+        return;
+    }
+
+    SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+    const char*        stop = text + byteLength;
+
+    if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
+        while (text < stop) {
+            // the last 2 parameters are ignored
+            const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+            if (glyph.fWidth) {
+                SkScalar x = pos[0];
+                SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
+
+                this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                    glyph.getSubXFixed(),
+                                                    glyph.getSubYFixed()),
+                                      SkScalarToFixed(x) + SK_FixedHalf, //d1g.fHalfSampleX,
+                                      SkScalarToFixed(y) + SK_FixedHalf, //d1g.fHalfSampleY,
+                                      fontScaler);
+            }
+            pos += scalarsPerPosition;
+        }
+    } else {
+        int alignShift = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? 1 : 0;
+        while (text < stop) {
+            // the last 2 parameters are ignored
+            const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+            if (glyph.fWidth) {
+                SkScalar x = pos[0];
+                SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
+                
+                this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                    glyph.getSubXFixed(),
+                                                    glyph.getSubYFixed()),
+                                      SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift)
+                                        + SK_FixedHalf, //d1g.fHalfSampleX,
+                                      SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift)
+                                        + SK_FixedHalf, //d1g.fHalfSampleY,
+                                      fontScaler);
+            }
+            pos += scalarsPerPosition;
+        }
+    }
+}
+