Change GrTextContext fallbacks to be a linked list chain.
authorjvanverth <jvanverth@google.com>
Tue, 14 Oct 2014 15:45:50 +0000 (08:45 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 14 Oct 2014 15:45:50 +0000 (08:45 -0700)
Preliminary work for getting color emoji working with
distance field text.

BUG=skia:2887

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

src/gpu/GrBitmapTextContext.cpp
src/gpu/GrBitmapTextContext.h
src/gpu/GrContext.cpp
src/gpu/GrDistanceFieldTextContext.cpp
src/gpu/GrDistanceFieldTextContext.h
src/gpu/GrStencilAndCoverTextContext.cpp
src/gpu/GrStencilAndCoverTextContext.h
src/gpu/GrTextContext.cpp
src/gpu/GrTextContext.h
src/gpu/SkGpuDevice.cpp
src/gpu/SkGpuDevice.h

index 7cfe917..8620e97 100755 (executable)
@@ -66,6 +66,11 @@ GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
     fVertexBounds.setLargestInverted();
 }
 
+GrBitmapTextContext* GrBitmapTextContext::Create(GrContext* context,
+                                                 const SkDeviceProperties& props) {
+    return SkNEW_ARGS(GrBitmapTextContext, (context, props));
+}
+
 GrBitmapTextContext::~GrBitmapTextContext() {
     this->flush();
 }
@@ -86,7 +91,7 @@ inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPai
     fMaxVertices = 0;
 }
 
-void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
+void GrBitmapTextContext::onDrawText(const GrPaint& paint, const SkPaint& skPaint,
                                    const char text[], size_t byteLength,
                                    SkScalar x, SkScalar y) {
     SkASSERT(byteLength == 0 || text != NULL);
@@ -177,7 +182,7 @@ void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
     this->finish();
 }
 
-void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
+void GrBitmapTextContext::onDrawPosText(const GrPaint& paint, const SkPaint& skPaint,
                                       const char text[], size_t byteLength,
                                       const SkScalar pos[], int scalarsPerPosition,
                                       const SkPoint& offset) {
index a9805cb..7a93820 100644 (file)
@@ -18,17 +18,9 @@ class GrTextStrike;
  */
 class GrBitmapTextContext : public GrTextContext {
 public:
-    GrBitmapTextContext(GrContext*, const SkDeviceProperties&);
-    virtual ~GrBitmapTextContext();
+    static GrBitmapTextContext* Create(GrContext*, const SkDeviceProperties&);
 
-    virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
-
-    virtual void drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength,
-                          SkScalar x, SkScalar y) SK_OVERRIDE;
-    virtual void drawPosText(const GrPaint&, const SkPaint&,
-                             const char text[], size_t byteLength,
-                             const SkScalar pos[], int scalarsPerPosition,
-                             const SkPoint& offset) SK_OVERRIDE;
+    virtual ~GrBitmapTextContext();
 
 private:
     enum {
@@ -49,6 +41,17 @@ private:
     // Used to check whether fCachedEffect is still valid.
     uint32_t                          fEffectTextureUniqueID;
 
+    GrBitmapTextContext(GrContext*, const SkDeviceProperties&);
+
+    virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
+
+    virtual void onDrawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength,
+                            SkScalar x, SkScalar y) SK_OVERRIDE;
+    virtual void onDrawPosText(const GrPaint&, const SkPaint&,
+                               const char text[], size_t byteLength,
+                               const SkScalar pos[], int scalarsPerPosition,
+                               const SkPoint& offset) SK_OVERRIDE;
+
     void init(const GrPaint&, const SkPaint&);
     void appendGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
     void flush();                 // automatically called by destructor
index d5b2116..402e2ec 100755 (executable)
@@ -251,13 +251,12 @@ GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget,
                                             const SkDeviceProperties&
                                             leakyProperties,
                                             bool enableDistanceFieldFonts) {
-    if (fGpu->caps()->pathRenderingSupport()) {
-        if (renderTarget->getStencilBuffer() && renderTarget->isMultisampled()) {
-            return SkNEW_ARGS(GrStencilAndCoverTextContext, (this, leakyProperties));
-        }
-    }
-    return SkNEW_ARGS(GrDistanceFieldTextContext, (this, leakyProperties,
-                                                   enableDistanceFieldFonts));
+    if (fGpu->caps()->pathRenderingSupport() && renderTarget->getStencilBuffer() && 
+                                                renderTarget->isMultisampled()) {
+        return GrStencilAndCoverTextContext::Create(this, leakyProperties);
+    } 
+
+    return GrDistanceFieldTextContext::Create(this, leakyProperties, enableDistanceFieldFonts);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
index 04ad59b..e10fa4f 100755 (executable)
@@ -7,6 +7,7 @@
 
 #include "GrDistanceFieldTextContext.h"
 #include "GrAtlas.h"
+#include "GrBitmapTextContext.h"
 #include "GrDrawTarget.h"
 #include "GrDrawTargetCaps.h"
 #include "GrFontScaler.h"
@@ -80,6 +81,16 @@ GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
     fVertexBounds.setLargestInverted();
 }
 
+GrDistanceFieldTextContext* GrDistanceFieldTextContext::Create(GrContext* context,
+                                                               const SkDeviceProperties& props,
+                                                               bool enable) {
+    GrDistanceFieldTextContext* textContext = SkNEW_ARGS(GrDistanceFieldTextContext, 
+                                                         (context, props, enable));
+    textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, props);
+
+    return textContext;
+}
+
 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
     this->flush();
     SkSafeSetNull(fGammaTexture);
@@ -196,7 +207,7 @@ static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache,
     }
 }
 
-void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
+void GrDistanceFieldTextContext::onDrawText(const GrPaint& paint, const SkPaint& skPaint,
                                           const char text[], size_t byteLength,
                                           SkScalar x, SkScalar y) {
     SkASSERT(byteLength == 0 || text != NULL);
@@ -271,7 +282,7 @@ void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& s
     this->finish();
 }
 
-void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
+void GrDistanceFieldTextContext::onDrawPosText(const GrPaint& paint, const SkPaint& skPaint,
                                              const char text[], size_t byteLength,
                                              const SkScalar pos[], int scalarsPerPosition,
                                              const SkPoint& offset) {
index d628e3e..6fa2d6f 100644 (file)
@@ -18,17 +18,9 @@ class GrTextStrike;
  */
 class GrDistanceFieldTextContext : public GrTextContext {
 public:
-    GrDistanceFieldTextContext(GrContext*, const SkDeviceProperties&, bool enable);
-    virtual ~GrDistanceFieldTextContext();
+    static GrDistanceFieldTextContext* Create(GrContext*, const SkDeviceProperties&, bool enable);
 
-    virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
-
-    virtual void drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength,
-                          SkScalar x, SkScalar y) SK_OVERRIDE;
-    virtual void drawPosText(const GrPaint&, const SkPaint&,
-                             const char text[], size_t byteLength,
-                             const SkScalar pos[], int scalarsPerPosition,
-                             const SkPoint& offset) SK_OVERRIDE;
+    virtual ~GrDistanceFieldTextContext();
 
 private:
     enum {
@@ -54,6 +46,17 @@ private:
     int                                fCurrVertex;
     SkRect                             fVertexBounds;
 
+    GrDistanceFieldTextContext(GrContext*, const SkDeviceProperties&, bool enable);
+
+    virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
+
+    virtual void onDrawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength,
+                            SkScalar x, SkScalar y) SK_OVERRIDE;
+    virtual void onDrawPosText(const GrPaint&, const SkPaint&,
+                               const char text[], size_t byteLength,
+                               const SkScalar pos[], int scalarsPerPosition,
+                               const SkPoint& offset) SK_OVERRIDE;
+
     void init(const GrPaint&, const SkPaint&);
     void appendGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
     void setupCoverageEffect(const SkColor& filteredColor);
index 1941fa7..b53ff79 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "GrStencilAndCoverTextContext.h"
+#include "GrBitmapTextContext.h"
 #include "GrDrawTarget.h"
 #include "GrGpu.h"
 #include "GrPath.h"
@@ -25,6 +26,15 @@ GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(
     , fPendingGlyphCount(0) {
 }
 
+GrStencilAndCoverTextContext* GrStencilAndCoverTextContext::Create(GrContext* context,
+                                                                 const SkDeviceProperties& props) {
+    GrStencilAndCoverTextContext* textContext = SkNEW_ARGS(GrStencilAndCoverTextContext,
+                                                           (context, props));
+    textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, props);
+
+    return textContext;
+}
+
 GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() {
 }
 
@@ -52,7 +62,7 @@ bool GrStencilAndCoverTextContext::canDraw(const SkPaint& paint) {
     return rec.getFormat() != SkMask::kARGB32_Format;
 }
 
-void GrStencilAndCoverTextContext::drawText(const GrPaint& paint,
+void GrStencilAndCoverTextContext::onDrawText(const GrPaint& paint,
                                             const SkPaint& skPaint,
                                             const char text[],
                                             size_t byteLength,
@@ -142,7 +152,7 @@ void GrStencilAndCoverTextContext::drawText(const GrPaint& paint,
     this->finish();
 }
 
-void GrStencilAndCoverTextContext::drawPosText(const GrPaint& paint,
+void GrStencilAndCoverTextContext::onDrawPosText(const GrPaint& paint,
                                                const SkPaint& skPaint,
                                                const char text[],
                                                size_t byteLength,
index dc32025..40d38c2 100644 (file)
@@ -24,18 +24,9 @@ class GrPathRange;
  */
 class GrStencilAndCoverTextContext : public GrTextContext {
 public:
-    GrStencilAndCoverTextContext(GrContext*, const SkDeviceProperties&);
-    virtual ~GrStencilAndCoverTextContext();
+    static GrStencilAndCoverTextContext* Create(GrContext*, const SkDeviceProperties&);
 
-    virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
-
-    virtual void drawText(const GrPaint&, const SkPaint&, const char text[],
-                          size_t byteLength,
-                          SkScalar x, SkScalar y) SK_OVERRIDE;
-    virtual void drawPosText(const GrPaint&, const SkPaint&,
-                             const char text[], size_t byteLength,
-                             const SkScalar pos[], int scalarsPerPosition,
-                             const SkPoint& offset) SK_OVERRIDE;
+    virtual ~GrStencilAndCoverTextContext();
 
 private:
     static const int kGlyphBufferSize = 1024;
@@ -73,6 +64,18 @@ private:
     SkMatrix                        fContextInitialMatrix;
     bool                            fNeedsDeviceSpaceGlyphs;
 
+    GrStencilAndCoverTextContext(GrContext*, const SkDeviceProperties&);
+
+    virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
+
+    virtual void onDrawText(const GrPaint&, const SkPaint&, const char text[],
+                            size_t byteLength,
+                            SkScalar x, SkScalar y) SK_OVERRIDE;
+    virtual void onDrawPosText(const GrPaint&, const SkPaint&,
+                               const char text[], size_t byteLength,
+                               const SkScalar pos[], int scalarsPerPosition,
+                               const SkPoint& offset) SK_OVERRIDE;
+
     void init(const GrPaint&, const SkPaint&, size_t textByteLength,
               RenderMode, const SkPoint& textTranslate);
     void initGlyphs(SkGlyphCache* cache);
index d281173..94c05a7 100644 (file)
 #include "GrFontScaler.h"
 
 GrTextContext::GrTextContext(GrContext* context, const SkDeviceProperties& properties) :
+                            fFallbackTextContext(NULL),
                             fContext(context), fDeviceProperties(properties), fDrawTarget(NULL) {
 }
 
+GrTextContext::~GrTextContext() {
+    SkDELETE(fFallbackTextContext);
+}
+
 void GrTextContext::init(const GrPaint& grPaint, const SkPaint& skPaint) {
     const GrClipData* clipData = fContext->getClip();
 
@@ -35,6 +40,41 @@ void GrTextContext::init(const GrPaint& grPaint, const SkPaint& skPaint) {
     fSkPaint = skPaint;
 }
 
+bool GrTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
+                             const char text[], size_t byteLength,
+                             SkScalar x, SkScalar y) {
+
+    GrTextContext* textContext = this;
+    do {
+        if (textContext->canDraw(skPaint)) {
+            textContext->onDrawText(paint, skPaint, text, byteLength, x, y);
+            return true;
+        }
+        textContext = textContext->fFallbackTextContext;
+    } while (textContext);
+
+    return false;
+}
+
+bool GrTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
+                                const char text[], size_t byteLength,
+                                const SkScalar pos[], int scalarsPerPosition,
+                                const SkPoint& offset) {
+
+    GrTextContext* textContext = this;
+    do {
+        if (textContext->canDraw(skPaint)) {
+            textContext->onDrawPosText(paint, skPaint, text, byteLength, pos, scalarsPerPosition,
+                                     offset);
+            return true;
+        }
+        textContext = textContext->fFallbackTextContext;
+    } while (textContext);
+
+    return false;
+}
+
+
 //*** change to output positions?
 void GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
                                 const char text[], size_t byteLength, SkVector* stopVector) {
index b82a648..95344dd 100644 (file)
@@ -23,18 +23,17 @@ class GrFontScaler;
  */
 class GrTextContext {
 public:
-    virtual ~GrTextContext() {}
+    virtual ~GrTextContext();
 
-    virtual bool canDraw(const SkPaint& paint) = 0;
-
-    virtual void drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength,
-                          SkScalar x, SkScalar y) = 0;
-    virtual void drawPosText(const GrPaint&, const SkPaint&,
-                             const char text[], size_t byteLength,
-                             const SkScalar pos[], int scalarsPerPosition,
-                             const SkPoint& offset) = 0;
+    bool drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength,
+                  SkScalar x, SkScalar y);
+    bool drawPosText(const GrPaint&, const SkPaint&,
+                     const char text[], size_t byteLength,
+                     const SkScalar pos[], int scalarsPerPosition,
+                     const SkPoint& offset);
 
 protected:
+    GrTextContext*     fFallbackTextContext;
     GrContext*         fContext;
     SkDeviceProperties fDeviceProperties;
 
@@ -45,6 +44,15 @@ protected:
 
     GrTextContext(GrContext*, const SkDeviceProperties&);
 
+    virtual bool canDraw(const SkPaint& paint) = 0;
+
+    virtual void onDrawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength,
+                            SkScalar x, SkScalar y) = 0;
+    virtual void onDrawPosText(const GrPaint&, const SkPaint&,
+                               const char text[], size_t byteLength,
+                               const SkScalar pos[], int scalarsPerPosition,
+                               const SkPoint& offset) = 0;
+
     void init(const GrPaint&, const SkPaint&);
     void finish() { fDrawTarget = NULL; }
 
index 6f4d1a6..0912b3d 100644 (file)
@@ -147,8 +147,7 @@ SkGpuDevice::SkGpuDevice(GrSurface* surface, const SkSurfaceProps& props, unsign
     this->setPixelGeometry(props.pixelGeometry());
 
     bool useDFFonts = !!(flags & kDFFonts_Flag);
-    fMainTextContext = fContext->createTextContext(fRenderTarget, this->getLeakyProperties(), useDFFonts);
-    fFallbackTextContext = SkNEW_ARGS(GrBitmapTextContext, (fContext, this->getLeakyProperties()));
+    fTextContext = fContext->createTextContext(fRenderTarget, this->getLeakyProperties(), useDFFonts);
 }
 
 SkGpuDevice* SkGpuDevice::Create(GrContext* context, const SkImageInfo& origInfo,
@@ -192,8 +191,7 @@ SkGpuDevice::~SkGpuDevice() {
         delete fDrawProcs;
     }
 
-    delete fMainTextContext;
-    delete fFallbackTextContext;
+    delete fTextContext;
 
     // The GrContext takes a ref on the target. We don't want to cause the render
     // target to be unnecessarily kept alive.
@@ -1685,22 +1683,13 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
     CHECK_SHOULD_DRAW(draw, false);
     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawText", fContext);
 
-    if (fMainTextContext->canDraw(paint)) {
-        GrPaint grPaint;
-        SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
-
-        SkDEBUGCODE(this->validate();)
-
-        fMainTextContext->drawText(grPaint, paint, (const char *)text, byteLength, x, y);
-    } else if (fFallbackTextContext && fFallbackTextContext->canDraw(paint)) {
-        GrPaint grPaint;
-        SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
+    GrPaint grPaint;
+    SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
 
-        SkDEBUGCODE(this->validate();)
+    SkDEBUGCODE(this->validate();)
 
-        fFallbackTextContext->drawText(grPaint, paint, (const char *)text, byteLength, x, y);
-    } else {
-        // this guy will just call our drawPath()
+    if (!fTextContext->drawText(grPaint, paint, (const char *)text, byteLength, x, y)) {
+        // this will just call our drawPath()
         draw.drawText_asPaths((const char*)text, byteLength, x, y, paint);
     }
 }
@@ -1711,23 +1700,14 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, size_t byteL
     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPosText", fContext);
     CHECK_SHOULD_DRAW(draw, false);
 
-    if (fMainTextContext->canDraw(paint)) {
-        GrPaint grPaint;
-        SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
-
-        SkDEBUGCODE(this->validate();)
-
-        fMainTextContext->drawPosText(grPaint, paint, (const char *)text, byteLength, pos,
-                                      scalarsPerPos, offset);
-    } else if (fFallbackTextContext && fFallbackTextContext->canDraw(paint)) {
-        GrPaint grPaint;
-        SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
+    GrPaint grPaint;
+    SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
 
-        SkDEBUGCODE(this->validate();)
+    SkDEBUGCODE(this->validate();)
 
-        fFallbackTextContext->drawPosText(grPaint, paint, (const char *)text, byteLength, pos,
-                                          scalarsPerPos, offset);
-    } else {
+    if (!fTextContext->drawPosText(grPaint, paint, (const char *)text, byteLength, pos,
+                                   scalarsPerPos, offset)) {
+        // this will just call our drawPath()
         draw.drawPosText_asPaths((const char*)text, byteLength, pos, scalarsPerPos, offset, paint);
     }
 }
index fe03e32..6a68eeb 100644 (file)
@@ -133,8 +133,7 @@ private:
 
     GrClipData      fClipData;
 
-    GrTextContext*  fMainTextContext;
-    GrTextContext*  fFallbackTextContext;
+    GrTextContext*  fTextContext;
 
     // state for our render-target
     GrRenderTarget*     fRenderTarget;