Add standalone drawText for GrTextContext.
authorcommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 28 Jan 2014 22:02:07 +0000 (22:02 +0000)
committercommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 28 Jan 2014 22:02:07 +0000 (22:02 +0000)
This unifies the interface between GrBitmapTextContext and
GrDistanceFieldTextContext so that they don't need special case code.
The future GrNVPRTextContext will also use this interface.

BUG=skia:2018
R=bsalomon@google.com, reed@google.com

Author: jvanverth@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@13227 2bbb7eff-a529-9590-31e7-b0007b416f81

include/core/SkPaint.h
include/gpu/GrBitmapTextContext.h
include/gpu/GrDistanceFieldTextContext.h
include/gpu/GrTextContext.h
include/gpu/SkGpuDevice.h
src/gpu/GrBitmapTextContext.cpp
src/gpu/GrDistanceFieldTextContext.cpp
src/gpu/GrTextContext.cpp
src/gpu/SkGpuDevice.cpp

index ab93eac..00ec29e 100644 (file)
@@ -1071,6 +1071,7 @@ private:
     friend class SkDraw;
     friend class SkGraphics; // So Term() can be called.
     friend class SkPDFDevice;
+    friend class GrBitmapTextContext;
     friend class GrDistanceFieldTextContext;
     friend class SkTextToPathIter;
     friend class SkCanonicalizePaint;
index e1b3d72..c66f8a8 100755 (executable)
@@ -17,17 +17,19 @@ class GrTextStrike;
  */
 class GrBitmapTextContext : public GrTextContext {
 public:
-    virtual void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top,
-                         GrFontScaler*) SK_OVERRIDE;
+    virtual void drawText(const char text[], size_t byteLength, SkScalar x, SkScalar y) SK_OVERRIDE;
+    virtual void drawPosText(const char text[], size_t byteLength,
+                             const SkScalar pos[], SkScalar constY,
+                             int scalarsPerPosition) SK_OVERRIDE;
 
 private:
-    GrBitmapTextContext(GrContext*, const GrPaint&, const SkPaint&);
+    GrBitmapTextContext(GrContext*, const GrPaint&, const SkPaint&, const SkDeviceProperties&);
     virtual ~GrBitmapTextContext();
     friend class GrTTextContextManager<GrBitmapTextContext>;
 
-    GrContext::AutoMatrix  fAutoMatrix;
     GrTextStrike*          fStrike;
 
+    void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top, GrFontScaler*);
     void flushGlyphs();                 // automatically called by destructor
 
     enum {
index 4fde6ce..79058b8 100755 (executable)
@@ -17,26 +17,21 @@ class GrTextStrike;
  */
 class GrDistanceFieldTextContext : public GrTextContext {
 public:
-    virtual void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top,
-                                 GrFontScaler*) SK_OVERRIDE;
-
-    void drawText(const char text[], size_t byteLength,
-                  SkScalar x, SkScalar y, SkGlyphCache*, GrFontScaler*);
-    void drawPosText(const char text[], size_t byteLength,
-                     const SkScalar pos[], SkScalar constY,
-                     int scalarsPerPosition,
-                     SkGlyphCache* cache, GrFontScaler* fontScaler);
-
-    const SkPaint& getSkPaint() { return fSkPaint; }
+    virtual void drawText(const char text[], size_t byteLength, SkScalar x, SkScalar y) SK_OVERRIDE;
+    virtual void drawPosText(const char text[], size_t byteLength,
+                             const SkScalar pos[], SkScalar constY,
+                             int scalarsPerPosition) SK_OVERRIDE;
 
 private:
-    GrDistanceFieldTextContext(GrContext*, const GrPaint&, const SkPaint&);
+    GrDistanceFieldTextContext(GrContext*, const GrPaint&, const SkPaint&, 
+                               const SkDeviceProperties&);
     virtual ~GrDistanceFieldTextContext();
     friend class GrTTextContextManager<GrDistanceFieldTextContext>;
 
     GrTextStrike*           fStrike;
     SkScalar                fTextRatio;
 
+    void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top, GrFontScaler*);
     void flushGlyphs();                 // automatically called by destructor
 
     enum {
index 1539df0..a8c0df0 100644 (file)
@@ -8,9 +8,10 @@
 #ifndef GrTextContext_DEFINED
 #define GrTextContext_DEFINED
 
-#include "GrContext.h"
+#include "GrPoint.h"
 #include "GrGlyph.h"
 #include "GrPaint.h"
+#include "SkDeviceProperties.h"
 
 #include "SkPostConfig.h"
 
@@ -24,18 +25,25 @@ class GrFontScaler;
 class GrTextContext {
 public:
     virtual ~GrTextContext() {}
-    virtual void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top,
-                                 GrFontScaler*) = 0;
+    virtual void drawText(const char text[], size_t byteLength, SkScalar x, SkScalar y) = 0;
+    virtual void drawPosText(const char text[], size_t byteLength,
+                             const SkScalar pos[], SkScalar constY,
+                             int scalarsPerPosition) = 0;
 
 protected:
-    GrTextContext(GrContext*, const GrPaint&, const SkPaint&);
-
-    GrPaint                fPaint;
-    SkPaint                fSkPaint;
-    GrContext*             fContext;
-    GrDrawTarget*          fDrawTarget;
-
-    SkIRect                fClipRect;
+    GrTextContext(GrContext*, const GrPaint&, const SkPaint&, const SkDeviceProperties&);
+
+    static GrFontScaler* GetGrFontScaler(SkGlyphCache* cache);
+    static void MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
+                            const char text[], size_t byteLength, SkVector* stopVector);
+    
+    GrContext*         fContext;
+    GrPaint            fPaint;
+    SkPaint            fSkPaint;
+    SkDeviceProperties fDeviceProperties;
+    GrDrawTarget*      fDrawTarget;
+
+    SkIRect            fClipRect;
 };
 
 /*
@@ -45,8 +53,8 @@ protected:
 class GrTextContextManager {
 public:
     virtual ~GrTextContextManager() {}
-    virtual GrTextContext* create(GrContext* context, const GrPaint& grPaint,
-                                  const SkPaint& skPaint) = 0;
+    virtual GrTextContext* create(GrContext* grContext, const GrPaint& grPaint,
+                                  const SkPaint& skPaint, const SkDeviceProperties& props) = 0;
 };
 
 template <class TextContextClass>
@@ -54,13 +62,14 @@ class GrTTextContextManager : public GrTextContextManager {
 private:
     class ManagedTextContext : public TextContextClass {
     public:
-        ~ManagedTextContext() {}
+        virtual ~ManagedTextContext() {}
 
-        ManagedTextContext(GrContext* context,
+        ManagedTextContext(GrContext* grContext,
                            const GrPaint& grPaint,
                            const SkPaint& skPaint,
+                           const SkDeviceProperties& properties,
                            GrTTextContextManager<TextContextClass>* manager) :
-        TextContextClass(context, grPaint, skPaint) {
+                          TextContextClass(grContext, grPaint, skPaint, properties) {
             fManager = manager;
         }
 
@@ -84,17 +93,19 @@ public:
         fUsed = false;
     }
 
-    ~GrTTextContextManager() {
+    virtual ~GrTTextContextManager() {
         SkASSERT(!fUsed);
         sk_free(fAllocation);
     }
 
-    GrTextContext* create(GrContext* context, const GrPaint& grPaint,
-                          const SkPaint& skPaint) {
+    virtual GrTextContext* create(GrContext* grContext, const GrPaint& grPaint,
+                                  const SkPaint& skPaint, const SkDeviceProperties& properties) 
+                                 SK_OVERRIDE {
         // add check for usePath here?
         SkASSERT(!fUsed);
         ManagedTextContext* obj = SkNEW_PLACEMENT_ARGS(fAllocation, ManagedTextContext,
-                                                       (context, grPaint, skPaint, this));
+                                                       (grContext, grPaint, skPaint, properties,
+                                                        this));
         fUsed = true;
         return obj;
     }
index 2888951..addf678 100644 (file)
@@ -167,8 +167,6 @@ private:
                                                    bool isOpaque,
                                                    Usage usage) SK_OVERRIDE;
 
-    SkDrawProcs* initDrawForText(GrTextContext*);
-
     // sets the render target, clip, and matrix on GrContext. Use forceIdenity to override
     // SkDraw's matrix and draw in device coords.
     void prepareDraw(const SkDraw&, bool forceIdentity);
index 6e33d90..da887a5 100755 (executable)
 #include "SkStrokeRec.h"
 #include "effects/GrCustomCoordsTextureEffect.h"
 
+#include "SkAutoKern.h"
+#include "SkGlyphCache.h"
+#include "SkGpuDevice.h"
+#include "SkGr.h"
+
 static const int kGlyphCoordsAttributeIndex = 1;
 
 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
                 "Dump the contents of the font cache before every purge.");
 
-GrBitmapTextContext::GrBitmapTextContext(GrContext* context, const GrPaint& paint,
-                                         const SkPaint& skPaint) :
-                                         GrTextContext(context, paint, skPaint) {
-    fAutoMatrix.setIdentity(fContext, &fPaint);
-
+GrBitmapTextContext::GrBitmapTextContext(GrContext* context, 
+                                         const GrPaint& grPaint,
+                                         const SkPaint& skPaint, 
+                                         const SkDeviceProperties& properties)
+                                       : GrTextContext(context, grPaint, skPaint, properties) {
     fStrike = NULL;
 
     fCurrTexture = NULL;
@@ -107,6 +112,330 @@ void GrBitmapTextContext::flushGlyphs() {
     }
 }
 
+void GrBitmapTextContext::drawText(const char text[], size_t byteLength,
+                                   SkScalar x, SkScalar y) {
+    SkASSERT(byteLength == 0 || text != NULL);
+
+    // nothing to draw
+    if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
+        return;
+    }
+
+    SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+    SkAutoGlyphCache    autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
+    SkGlyphCache*       cache = autoCache.getCache();
+    GrFontScaler*       fontScaler = GetGrFontScaler(cache);
+
+    // transform our starting point
+    {
+        SkPoint loc;
+        fContext->getMatrix().mapXY(x, y, &loc);
+        x = loc.fX;
+        y = loc.fY;
+    }
+
+    // need to measure first
+    if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
+        SkVector    stop;
+
+        MeasureText(cache, glyphCacheProc, text, byteLength, &stop);
+
+        SkScalar    stopX = stop.fX;
+        SkScalar    stopY = stop.fY;
+
+        if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
+            stopX = SkScalarHalf(stopX);
+            stopY = SkScalarHalf(stopY);
+        }
+        x -= stopX;
+        y -= stopY;
+    }
+
+    const char* stop = text + byteLength;
+
+    SkAutoKern autokern;
+
+    SkFixed fxMask = ~0;
+    SkFixed fyMask = ~0;
+    SkFixed halfSampleX, halfSampleY;
+    if (cache->isSubpixel()) {
+        halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
+        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(fContext->getMatrix());
+        if (kX_SkAxisAlignment == baseline) {
+            fyMask = 0;
+            halfSampleY = SK_FixedHalf;
+        } else if (kY_SkAxisAlignment == baseline) {
+            fxMask = 0;
+            halfSampleX = SK_FixedHalf;
+        }
+    } else {
+        halfSampleX = halfSampleY = SK_FixedHalf;
+    }
+
+    SkFixed fx = SkScalarToFixed(x) + halfSampleX;
+    SkFixed fy = SkScalarToFixed(y) + halfSampleY;
+    
+    GrContext::AutoMatrix  autoMatrix;
+    autoMatrix.setIdentity(fContext, &fPaint);
+    
+    while (text < stop) {
+        const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
+
+        fx += autokern.adjust(glyph);
+
+        if (glyph.fWidth) {
+            this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                          glyph.getSubXFixed(),
+                                          glyph.getSubYFixed()),
+                                  SkFixedFloorToFixed(fx),
+                                  SkFixedFloorToFixed(fy),
+                                  fontScaler);
+        }
+
+        fx += glyph.fAdvanceX;
+        fy += glyph.fAdvanceY;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Copied from SkDraw
+
+// last parameter is interpreted as SkFixed [x, y]
+// return the fixed position, which may be rounded or not by the caller
+//   e.g. subpixel doesn't round
+typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
+
+static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
+    dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
+}
+
+static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
+    dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
+             SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
+}
+
+static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
+    dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
+             SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
+}
+
+static AlignProc pick_align_proc(SkPaint::Align align) {
+    static const AlignProc gProcs[] = {
+        leftAlignProc, centerAlignProc, rightAlignProc
+    };
+
+    SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
+
+    return gProcs[align];
+}
+
+class BitmapTextMapState {
+public:
+    mutable SkPoint fLoc;
+
+    BitmapTextMapState(const SkMatrix& matrix, SkScalar y)
+        : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
+
+    typedef void (*Proc)(const BitmapTextMapState&, const SkScalar pos[]);
+
+    Proc pickProc(int scalarsPerPosition);
+
+private:
+    const SkMatrix&     fMatrix;
+    SkMatrix::MapXYProc fProc;
+    SkScalar            fY; // ignored by MapXYProc
+    // these are only used by Only... procs
+    SkScalar            fScaleX, fTransX, fTransformedY;
+
+    static void MapXProc(const BitmapTextMapState& state, const SkScalar pos[]) {
+        state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
+    }
+
+    static void MapXYProc(const BitmapTextMapState& state, const SkScalar pos[]) {
+        state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
+    }
+
+    static void MapOnlyScaleXProc(const BitmapTextMapState& state,
+                                  const SkScalar pos[]) {
+        state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
+                       state.fTransformedY);
+    }
+
+    static void MapOnlyTransXProc(const BitmapTextMapState& state,
+                                  const SkScalar pos[]) {
+        state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
+    }
+};
+
+BitmapTextMapState::Proc BitmapTextMapState::pickProc(int scalarsPerPosition) {
+    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
+
+    if (1 == scalarsPerPosition) {
+        unsigned mtype = fMatrix.getType();
+        if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
+            return MapXProc;
+        } else {
+            fScaleX = fMatrix.getScaleX();
+            fTransX = fMatrix.getTranslateX();
+            fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
+                            fMatrix.getTranslateY();
+            return (mtype & SkMatrix::kScale_Mask) ?
+                        MapOnlyScaleXProc : MapOnlyTransXProc;
+        }
+    } else {
+        return MapXYProc;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GrBitmapTextContext::drawPosText(const char text[], size_t byteLength,
+                                      const SkScalar pos[], SkScalar constY,
+                                      int scalarsPerPosition) {
+    SkASSERT(byteLength == 0 || text != NULL);
+    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
+
+    // nothing to draw
+    if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) {
+        return;
+    }
+
+    SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+    SkAutoGlyphCache    autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
+    SkGlyphCache*       cache = autoCache.getCache();
+    GrFontScaler*       fontScaler = GetGrFontScaler(cache);
+
+    // store original matrix before we reset, so we can use it to transform positions
+    SkMatrix ctm = fContext->getMatrix();
+    GrContext::AutoMatrix  autoMatrix;
+    autoMatrix.setIdentity(fContext, &fPaint);
+
+    const char*        stop = text + byteLength;
+    AlignProc          alignProc = pick_align_proc(fSkPaint.getTextAlign());
+    BitmapTextMapState       tms(ctm, constY);
+    BitmapTextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
+    SkFixed halfSampleX = 0, halfSampleY = 0;
+
+    if (cache->isSubpixel()) {
+        // maybe we should skip the rounding if linearText is set
+        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm);
+
+        SkFixed fxMask = ~0;
+        SkFixed fyMask = ~0;
+        if (kX_SkAxisAlignment == baseline) {
+            fyMask = 0;
+#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
+            halfSampleY = SK_FixedHalf;
+#endif
+        } else if (kY_SkAxisAlignment == baseline) {
+            fxMask = 0;
+#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
+            halfSampleX = SK_FixedHalf;
+#endif
+        }
+
+        if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
+            while (text < stop) {
+                tmsProc(tms, pos);
+                SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + halfSampleX;
+                SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + halfSampleY;
+
+                const SkGlyph& glyph = glyphCacheProc(cache, &text,
+                                                      fx & fxMask, fy & fyMask);
+
+                if (glyph.fWidth) {
+                    this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                        glyph.getSubXFixed(),
+                                                        glyph.getSubYFixed()),
+                                          SkFixedFloorToFixed(fx),
+                                          SkFixedFloorToFixed(fy),
+                                          fontScaler);
+                }
+                pos += scalarsPerPosition;
+            }
+        } else {
+            while (text < stop) {
+                const char* currentText = text;
+                const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
+
+                if (metricGlyph.fWidth) {
+                    SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
+                    SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
+
+                    tmsProc(tms, pos);
+                    SkIPoint fixedLoc;
+                    alignProc(tms.fLoc, metricGlyph, &fixedLoc);
+
+                    SkFixed fx = fixedLoc.fX + halfSampleX;
+                    SkFixed fy = fixedLoc.fY + halfSampleY;
+
+                    // have to call again, now that we've been "aligned"
+                    const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
+                                                          fx & fxMask, fy & fyMask);
+                    // the assumption is that the metrics haven't changed
+                    SkASSERT(prevAdvX == glyph.fAdvanceX);
+                    SkASSERT(prevAdvY == glyph.fAdvanceY);
+                    SkASSERT(glyph.fWidth);
+
+                    this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                        glyph.getSubXFixed(),
+                                                        glyph.getSubYFixed()),
+                                          SkFixedFloorToFixed(fx),
+                                          SkFixedFloorToFixed(fy),
+                                          fontScaler);
+                }
+                pos += scalarsPerPosition;
+            }
+        }
+    } else {    // not subpixel
+
+        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) {
+                    tmsProc(tms, pos);
+
+                    SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf; //halfSampleX;
+                    SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf; //halfSampleY;
+                    this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                        glyph.getSubXFixed(),
+                                                        glyph.getSubYFixed()),
+                                          SkFixedFloorToFixed(fx),
+                                          SkFixedFloorToFixed(fy),
+                                          fontScaler);
+                }
+                pos += scalarsPerPosition;
+            }
+        } else {
+            while (text < stop) {
+                // the last 2 parameters are ignored
+                const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+                if (glyph.fWidth) {
+                    tmsProc(tms, pos);
+
+                    SkIPoint fixedLoc;
+                    alignProc(tms.fLoc, glyph, &fixedLoc);
+
+                    SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX;
+                    SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY;
+                    this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                        glyph.getSubXFixed(),
+                                                        glyph.getSubYFixed()),
+                                          SkFixedFloorToFixed(fx),
+                                          SkFixedFloorToFixed(fy),
+                                          fontScaler);
+                }
+                pos += scalarsPerPosition;
+            }
+        }
+    }
+}
+
 namespace {
 
 // position + texture coord
@@ -123,6 +452,7 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
     if (NULL == fDrawTarget) {
         return;
     }
+
     if (NULL == fStrike) {
 #if SK_DISTANCEFIELD_FONTS
         fStrike = fContext->getFontCache()->getStrike(scaler, false);
index 4c9631e..afb203a 100755 (executable)
@@ -13,6 +13,7 @@
 #include "GrIndexBuffer.h"
 #include "GrTextStrike.h"
 #include "GrTextStrike_impl.h"
+#include "SkGpuDevice.h"
 #include "SkPath.h"
 #include "SkRTConf.h"
 #include "SkStrokeRec.h"
@@ -25,10 +26,11 @@ 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,
+GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context, 
                                                        const GrPaint& grPaint,
-                                                       const SkPaint& skPaint)
-                                                     : GrTextContext(context, grPaint, skPaint) {
+                                                       const SkPaint& skPaint, 
+                                                       const SkDeviceProperties& properties)
+                                            : GrTextContext(context, grPaint, skPaint, properties) {
     fStrike = NULL;
 
     fCurrTexture = NULL;
@@ -283,19 +285,23 @@ HAS_ATLAS:
 }
 
 void GrDistanceFieldTextContext::drawText(const char text[], size_t byteLength,
-                                          SkScalar x, SkScalar y, SkGlyphCache* cache,
-                                          GrFontScaler* fontScaler) {
+                                          SkScalar x, SkScalar y) {
     SkASSERT(byteLength == 0 || text != NULL);
 
-    // nothing to draw
-    if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
+    // nothing to draw or can't draw
+    if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
+        || fSkPaint.getRasterizer()) {
         return;
     }
-
+    
     SkScalar sizeRatio = fTextRatio;
 
     SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
 
+    SkAutoGlyphCache    autoCache(fSkPaint, &fDeviceProperties, NULL);
+    SkGlyphCache*       cache = autoCache.getCache();
+    GrFontScaler*       fontScaler = GetGrFontScaler(cache);
+    
     // need to measure first
     // TODO - generate positions and pre-load cache as well?
     const char* stop = text + byteLength;
@@ -348,19 +354,23 @@ void GrDistanceFieldTextContext::drawText(const char text[], size_t byteLength,
 
 void GrDistanceFieldTextContext::drawPosText(const char text[], size_t byteLength,
                                              const SkScalar pos[], SkScalar constY,
-                                             int scalarsPerPosition,
-                                             SkGlyphCache* cache, GrFontScaler* fontScaler) {
+                                             int scalarsPerPosition) {
 
     SkASSERT(byteLength == 0 || text != NULL);
     SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
 
     // nothing to draw
-    if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
+    if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
+        || fSkPaint.getRasterizer()) {
         return;
     }
 
     SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
 
+    SkAutoGlyphCache    autoCache(fSkPaint, &fDeviceProperties, NULL);
+    SkGlyphCache*       cache = autoCache.getCache();
+    GrFontScaler*       fontScaler = GetGrFontScaler(cache);
+    
     const char*        stop = text + byteLength;
 
     if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
index 77e98d2..ab9ef85 100644 (file)
@@ -5,12 +5,17 @@
  * found in the LICENSE file.
  */
 
-
 #include "GrTextContext.h"
+#include "GrContext.h"
+
+#include "SkAutoKern.h"
+#include "SkGlyphCache.h"
+#include "SkGr.h"
 
 GrTextContext::GrTextContext(GrContext* context, const GrPaint& paint,
-                             const SkPaint& skPaint) : fPaint(paint), fSkPaint(skPaint) {
-    fContext = context;
+                             const SkPaint& skPaint, const SkDeviceProperties& properties) : 
+                            fContext(context), fPaint(paint), fSkPaint(skPaint),
+                            fDeviceProperties(properties) {
 
     const GrClipData* clipData = context->getClip();
 
@@ -24,5 +29,47 @@ GrTextContext::GrTextContext(GrContext* context, const GrPaint& paint,
 
     devConservativeBound.roundOut(&fClipRect);
 
-    fDrawTarget = fContext->getTextTarget();
+    fDrawTarget = context->getTextTarget();
 }
+
+//*** change to output positions?
+void GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
+                                const char text[], size_t byteLength, SkVector* stopVector) {
+    SkFixed     x = 0, y = 0;
+    const char* stop = text + byteLength;
+    
+    SkAutoKern  autokern;
+    
+    while (text < stop) {
+        // don't need x, y here, since all subpixel variants will have the
+        // same advance
+        const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+        
+        x += autokern.adjust(glyph) + glyph.fAdvanceX;
+        y += glyph.fAdvanceY;
+    }
+    stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
+    
+    SkASSERT(text == stop);
+}
+
+static void GlyphCacheAuxProc(void* data) {
+    GrFontScaler* scaler = (GrFontScaler*)data;
+    SkSafeUnref(scaler);
+}
+
+GrFontScaler* GrTextContext::GetGrFontScaler(SkGlyphCache* cache) {
+    void* auxData;
+    GrFontScaler* scaler = NULL;
+    
+    if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
+        scaler = (GrFontScaler*)auxData;
+    }
+    if (NULL == scaler) {
+        scaler = SkNEW_ARGS(SkGrFontScaler, (cache));
+        cache->setAuxProc(GlyphCacheAuxProc, scaler);
+    }
+    
+    return scaler;
+}
+
index 73eb65b..f52385a 100644 (file)
@@ -1766,58 +1766,6 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
 
 ///////////////////////////////////////////////////////////////////////////////
 
-static void GlyphCacheAuxProc(void* data) {
-    GrFontScaler* scaler = (GrFontScaler*)data;
-    SkSafeUnref(scaler);
-}
-
-static GrFontScaler* get_gr_font_scaler(SkGlyphCache* cache) {
-    void* auxData;
-    GrFontScaler* scaler = NULL;
-    if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
-        scaler = (GrFontScaler*)auxData;
-    }
-    if (NULL == scaler) {
-        scaler = SkNEW_ARGS(SkGrFontScaler, (cache));
-        cache->setAuxProc(GlyphCacheAuxProc, scaler);
-    }
-    return scaler;
-}
-
-static void SkGPU_Draw1Glyph(const SkDraw1Glyph& state,
-                             SkFixed fx, SkFixed fy,
-                             const SkGlyph& glyph) {
-    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
-
-    GrSkDrawProcs* procs = static_cast<GrSkDrawProcs*>(state.fDraw->fProcs);
-
-    if (NULL == procs->fFontScaler) {
-        procs->fFontScaler = get_gr_font_scaler(state.fCache);
-    }
-
-    procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
-                                                       glyph.getSubXFixed(),
-                                                       glyph.getSubYFixed()),
-                                         SkFixedFloorToFixed(fx),
-                                         SkFixedFloorToFixed(fy),
-                                         procs->fFontScaler);
-}
-
-SkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) {
-
-    // deferred allocation
-    if (NULL == fDrawProcs) {
-        fDrawProcs = SkNEW(GrSkDrawProcs);
-        fDrawProcs->fD1GProc = SkGPU_Draw1Glyph;
-        fDrawProcs->fContext = fContext;
-    }
-
-    // init our (and GL's) state
-    fDrawProcs->fTextContext = context;
-    fDrawProcs->fFontScaler = NULL;
-    return fDrawProcs;
-}
-
 void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
                           size_t byteLength, SkScalar x, SkScalar y,
                           const SkPaint& paint) {
@@ -1825,8 +1773,7 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
 
     if (SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix())) {
         draw.drawText_asPaths((const char*)text, byteLength, x, y, paint);
-#if SK_DISTANCEFIELD_FONTS
-    } else if (!paint.getRasterizer()) {
+    } else {
         GrPaint grPaint;
         if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
             return;
@@ -1834,27 +1781,10 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
 
         SkDEBUGCODE(this->validate();)
 
-        SkAutoTDelete<GrTextContext> context(fTextContextManager->create(fContext, grPaint, paint));
-        GrDistanceFieldTextContext* dfContext =
-                                            static_cast<GrDistanceFieldTextContext*>(context.get());
-
-        SkAutoGlyphCache    autoCache(dfContext->getSkPaint(), &this->fLeakyProperties, NULL);
-        SkGlyphCache*       cache = autoCache.getCache();
-        GrFontScaler*       fontScaler = get_gr_font_scaler(cache);
-
-        dfContext->drawText((const char *)text, byteLength, x, y, cache, fontScaler);
-#endif
-    } else {
-        SkDraw myDraw(draw);
-
-        GrPaint grPaint;
-        if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
-            return;
-        }
-
-        SkAutoTDelete<GrTextContext> context(fTextContextManager->create(fContext, grPaint, paint));
-        myDraw.fProcs = this->initDrawForText(context.get());
-        this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
+        SkAutoTDelete<GrTextContext> ctx(fTextContextManager->create(this->context(), 
+                                                                     grPaint, paint,
+                                                                     this->getDeviceProperties()));
+        ctx->drawText((const char *)text, byteLength, x, y);
     }
 }
 
@@ -1868,8 +1798,7 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
         // this guy will just call our drawPath()
         draw.drawPosText_asPaths((const char*)text, byteLength, pos, constY,
                          scalarsPerPos, paint);
-#if SK_DISTANCEFIELD_FONTS
-    } else if (!paint.getRasterizer()) {
+    } else {
         GrPaint grPaint;
         if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
             return;
@@ -1877,29 +1806,10 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
 
         SkDEBUGCODE(this->validate();)
 
-        SkAutoTDelete<GrTextContext> context(fTextContextManager->create(fContext, grPaint, paint));
-        GrDistanceFieldTextContext* dfContext =
-                                            static_cast<GrDistanceFieldTextContext*>(context.get());
-
-        SkAutoGlyphCache    autoCache(dfContext->getSkPaint(), &this->fLeakyProperties, NULL);
-        SkGlyphCache*       cache = autoCache.getCache();
-        GrFontScaler*       fontScaler = get_gr_font_scaler(cache);
-
-        dfContext->drawPosText((const char *)text, byteLength, pos, constY, scalarsPerPos,
-                            cache, fontScaler);
-#endif
-    } else {
-        SkDraw myDraw(draw);
-
-        GrPaint grPaint;
-        if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
-            return;
-        }
-
-        SkAutoTDelete<GrTextContext> context(fTextContextManager->create(fContext, grPaint, paint));
-        myDraw.fProcs = this->initDrawForText(context.get());
-        this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
-                                        scalarsPerPos, paint);
+        SkAutoTDelete<GrTextContext> ctx(fTextContextManager->create(this->context(), 
+                                                                     grPaint, paint,
+                                                                     this->getDeviceProperties()));
+        ctx->drawPosText((const char *)text, byteLength, pos, constY, scalarsPerPos);
     }
 }