From 8c27a188a0b216021d439eb627622d17b9f78343 Mon Sep 17 00:00:00 2001 From: jvanverth Date: Tue, 14 Oct 2014 08:45:50 -0700 Subject: [PATCH] Change GrTextContext fallbacks to be a linked list chain. 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 | 9 +++++-- src/gpu/GrBitmapTextContext.h | 23 +++++++++------- src/gpu/GrContext.cpp | 13 +++++---- src/gpu/GrDistanceFieldTextContext.cpp | 15 +++++++++-- src/gpu/GrDistanceFieldTextContext.h | 23 +++++++++------- src/gpu/GrStencilAndCoverTextContext.cpp | 14 ++++++++-- src/gpu/GrStencilAndCoverTextContext.h | 25 +++++++++-------- src/gpu/GrTextContext.cpp | 40 +++++++++++++++++++++++++++ src/gpu/GrTextContext.h | 26 +++++++++++------- src/gpu/SkGpuDevice.cpp | 46 +++++++++----------------------- src/gpu/SkGpuDevice.h | 3 +-- 11 files changed, 149 insertions(+), 88 deletions(-) diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp index 7cfe917..8620e97 100755 --- a/src/gpu/GrBitmapTextContext.cpp +++ b/src/gpu/GrBitmapTextContext.cpp @@ -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) { diff --git a/src/gpu/GrBitmapTextContext.h b/src/gpu/GrBitmapTextContext.h index a9805cb..7a93820 100644 --- a/src/gpu/GrBitmapTextContext.h +++ b/src/gpu/GrBitmapTextContext.h @@ -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 diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index d5b2116..402e2ec 100755 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -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); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp index 04ad59b..e10fa4f 100755 --- a/src/gpu/GrDistanceFieldTextContext.cpp +++ b/src/gpu/GrDistanceFieldTextContext.cpp @@ -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) { diff --git a/src/gpu/GrDistanceFieldTextContext.h b/src/gpu/GrDistanceFieldTextContext.h index d628e3e..6fa2d6f 100644 --- a/src/gpu/GrDistanceFieldTextContext.h +++ b/src/gpu/GrDistanceFieldTextContext.h @@ -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); diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp index 1941fa7..b53ff79 100644 --- a/src/gpu/GrStencilAndCoverTextContext.cpp +++ b/src/gpu/GrStencilAndCoverTextContext.cpp @@ -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, diff --git a/src/gpu/GrStencilAndCoverTextContext.h b/src/gpu/GrStencilAndCoverTextContext.h index dc32025..40d38c2 100644 --- a/src/gpu/GrStencilAndCoverTextContext.h +++ b/src/gpu/GrStencilAndCoverTextContext.h @@ -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); diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp index d281173..94c05a7 100644 --- a/src/gpu/GrTextContext.cpp +++ b/src/gpu/GrTextContext.cpp @@ -13,9 +13,14 @@ #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) { diff --git a/src/gpu/GrTextContext.h b/src/gpu/GrTextContext.h index b82a648..95344dd 100644 --- a/src/gpu/GrTextContext.h +++ b/src/gpu/GrTextContext.h @@ -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; } diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 6f4d1a6..0912b3d 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -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); } } diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h index fe03e32..6a68eeb 100644 --- a/src/gpu/SkGpuDevice.h +++ b/src/gpu/SkGpuDevice.h @@ -133,8 +133,7 @@ private: GrClipData fClipData; - GrTextContext* fMainTextContext; - GrTextContext* fFallbackTextContext; + GrTextContext* fTextContext; // state for our render-target GrRenderTarget* fRenderTarget; -- 2.7.4