diff options
author | joshualitt <joshualitt@chromium.org> | 2015-03-20 10:30:14 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-20 10:30:14 -0700 |
commit | 6e8cd9671958c69babde9338c5c18a4c3d895575 (patch) | |
tree | eab4eb9c66a7b1831f589fac0bffc5c08f6852f6 | |
parent | 1b600d3446b3d236bfa06cf116ec41960bea6ac8 (diff) |
Let text contexts fall back directly to paths
BUG=skia:
Review URL: https://codereview.chromium.org/1015173002
-rw-r--r-- | include/core/SkPaint.h | 1 | ||||
-rw-r--r-- | include/gpu/GrContext.h | 28 | ||||
-rwxr-xr-x | src/gpu/GrBitmapTextContext.cpp | 19 | ||||
-rw-r--r-- | src/gpu/GrBitmapTextContext.h | 11 | ||||
-rwxr-xr-x | src/gpu/GrContext.cpp | 6 | ||||
-rwxr-xr-x | src/gpu/GrDistanceFieldTextContext.cpp | 32 | ||||
-rw-r--r-- | src/gpu/GrDistanceFieldTextContext.h | 12 | ||||
-rw-r--r-- | src/gpu/GrStencilAndCoverTextContext.cpp | 35 | ||||
-rw-r--r-- | src/gpu/GrStencilAndCoverTextContext.h | 12 | ||||
-rw-r--r-- | src/gpu/GrTextContext.cpp | 114 | ||||
-rw-r--r-- | src/gpu/GrTextContext.h | 32 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 18 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.h | 1 |
13 files changed, 223 insertions, 98 deletions
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h index 79821e5769..4bf8c059ac 100644 --- a/include/core/SkPaint.h +++ b/include/core/SkPaint.h @@ -1125,6 +1125,7 @@ private: friend class GrDistanceFieldTextContext; friend class GrStencilAndCoverTextContext; friend class GrPathRendering; + friend class GrTextContext; friend class GrGLPathRendering; friend class SkTextToPathIter; friend class SkCanonicalizePaint; diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index 6a225c2538..335b4169cc 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -41,6 +41,7 @@ class GrVertexBuffer; class GrVertexBufferAllocPool; class GrStrokeInfo; class GrSoftwarePathRenderer; +class SkGpuDevice; class SkStrokeRec; class SK_API GrContext : public SkRefCnt { @@ -201,16 +202,6 @@ public: */ bool isResourceInCache(const GrUniqueKey& key) const; - /** - * Creates a new text rendering context that is optimal for the - * render target and the context. Caller assumes the ownership - * of the returned object. The returned object must be deleted - * before the context is destroyed. - */ - GrTextContext* createTextContext(GrRenderTarget*, - const SkDeviceProperties&, - bool enableDistanceFieldFonts); - /////////////////////////////////////////////////////////////////////////// // Textures @@ -763,6 +754,20 @@ private: GrTexture* internalRefScratchTexture(const GrSurfaceDesc&, uint32_t flags); /** + * Creates a new text rendering context that is optimal for the + * render target and the context. Caller assumes the ownership + * of the returned object. The returned object must be deleted + * before the context is destroyed. + * TODO we can possibly bury this behind context, but we need to be able to use the + * drawText_asPaths logic on SkGpuDevice + */ + GrTextContext* createTextContext(GrRenderTarget*, + SkGpuDevice*, + const SkDeviceProperties&, + bool enableDistanceFieldFonts); + + + /** * These functions create premul <-> unpremul effects if it is possible to generate a pair * of effects that make a readToUPM->writeToPM->readToUPM cycle invariant. Otherwise, they * return NULL. @@ -776,6 +781,9 @@ private: */ static void OverBudgetCB(void* data); + // TODO see note on createTextContext + friend class SkGpuDevice; + typedef SkRefCnt INHERITED; }; diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp index ed3ed09642..4061c48821 100755 --- a/src/gpu/GrBitmapTextContext.cpp +++ b/src/gpu/GrBitmapTextContext.cpp @@ -46,8 +46,9 @@ static const int kIndicesPerGlyph = 6; }; GrBitmapTextContext::GrBitmapTextContext(GrContext* context, + SkGpuDevice* gpuDevice, const SkDeviceProperties& properties) - : GrTextContext(context, properties) { + : GrTextContext(context, gpuDevice, properties) { fStrike = NULL; fCurrTexture = NULL; @@ -62,8 +63,9 @@ GrBitmapTextContext::GrBitmapTextContext(GrContext* context, } GrBitmapTextContext* GrBitmapTextContext::Create(GrContext* context, + SkGpuDevice* gpuDevice, const SkDeviceProperties& props) { - return SkNEW_ARGS(GrBitmapTextContext, (context, props)); + return SkNEW_ARGS(GrBitmapTextContext, (context, gpuDevice, props)); } bool GrBitmapTextContext::canDraw(const SkPaint& paint, const SkMatrix& viewMatrix) { @@ -71,8 +73,9 @@ bool GrBitmapTextContext::canDraw(const SkPaint& paint, const SkMatrix& viewMatr } inline void GrBitmapTextContext::init(GrRenderTarget* rt, const GrClip& clip, - const GrPaint& paint, const SkPaint& skPaint) { - GrTextContext::init(rt, clip, paint, skPaint); + const GrPaint& paint, const SkPaint& skPaint, + const SkIRect& regionClipBounds) { + GrTextContext::init(rt, clip, paint, skPaint, regionClipBounds); fStrike = NULL; @@ -88,7 +91,7 @@ void GrBitmapTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& paint, const SkPaint& skPaint, const SkMatrix& viewMatrix, const char text[], size_t byteLength, - SkScalar x, SkScalar y) { + SkScalar x, SkScalar y, const SkIRect& regionClipBounds) { SkASSERT(byteLength == 0 || text != NULL); // nothing to draw @@ -96,7 +99,7 @@ void GrBitmapTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip, return; } - this->init(rt, clip, paint, skPaint); + this->init(rt, clip, paint, skPaint, regionClipBounds); SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); @@ -190,7 +193,7 @@ void GrBitmapTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, - const SkPoint& offset) { + const SkPoint& offset, const SkIRect& regionClipBounds) { SkASSERT(byteLength == 0 || text != NULL); SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); @@ -199,7 +202,7 @@ void GrBitmapTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip, return; } - this->init(rt, clip, paint, skPaint); + this->init(rt, clip, paint, skPaint, regionClipBounds); SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); diff --git a/src/gpu/GrBitmapTextContext.h b/src/gpu/GrBitmapTextContext.h index e181fd2b69..e389f81480 100644 --- a/src/gpu/GrBitmapTextContext.h +++ b/src/gpu/GrBitmapTextContext.h @@ -19,7 +19,7 @@ class GrTextStrike; */ class GrBitmapTextContext : public GrTextContext { public: - static GrBitmapTextContext* Create(GrContext*, const SkDeviceProperties&); + static GrBitmapTextContext* Create(GrContext*, SkGpuDevice*, const SkDeviceProperties&); virtual ~GrBitmapTextContext() {} @@ -37,20 +37,21 @@ private: uint32_t fEffectTextureUniqueID; SkMatrix fLocalMatrix; - GrBitmapTextContext(GrContext*, const SkDeviceProperties&); + GrBitmapTextContext(GrContext*, SkGpuDevice*, const SkDeviceProperties&); bool canDraw(const SkPaint& paint, const SkMatrix& viewMatrix) SK_OVERRIDE; virtual void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, const SkMatrix& viewMatrix, const char text[], size_t byteLength, - SkScalar x, SkScalar y) SK_OVERRIDE; + SkScalar x, SkScalar y, const SkIRect& regionClipBounds) SK_OVERRIDE; virtual void onDrawPosText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, - const SkPoint& offset) SK_OVERRIDE; + const SkPoint& offset, const SkIRect& regionClipBounds) SK_OVERRIDE; - void init(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&); + void init(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, + const SkIRect& regionClipBounds); void appendGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*); bool uploadGlyph(GrGlyph*, GrFontScaler*); void flush(); // automatically called by destructor diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 78f29e73bc..35b34e392d 100755 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -215,17 +215,19 @@ void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) } GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget, + SkGpuDevice* gpuDevice, const SkDeviceProperties& leakyProperties, bool enableDistanceFieldFonts) { if (fGpu->caps()->pathRenderingSupport() && renderTarget->isMultisampled()) { GrStencilBuffer* sb = renderTarget->renderTargetPriv().attachStencilBuffer(); if (sb) { - return GrStencilAndCoverTextContext::Create(this, leakyProperties); + return GrStencilAndCoverTextContext::Create(this, gpuDevice, leakyProperties); } } - return GrDistanceFieldTextContext::Create(this, leakyProperties, enableDistanceFieldFonts); + return GrDistanceFieldTextContext::Create(this, gpuDevice, leakyProperties, + enableDistanceFieldFonts); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp index 7e93892a68..28c76954da 100755 --- a/src/gpu/GrDistanceFieldTextContext.cpp +++ b/src/gpu/GrDistanceFieldTextContext.cpp @@ -43,9 +43,10 @@ static const int kVerticesPerGlyph = 4; static const int kIndicesPerGlyph = 6; GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context, + SkGpuDevice* gpuDevice, const SkDeviceProperties& properties, bool enable) - : GrTextContext(context, properties) { + : GrTextContext(context, gpuDevice, properties) { #if SK_FORCE_DISTANCE_FIELD_TEXT fEnableDFRendering = true; #else @@ -68,11 +69,12 @@ GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context, } GrDistanceFieldTextContext* GrDistanceFieldTextContext::Create(GrContext* context, + SkGpuDevice* gpuDevice, const SkDeviceProperties& props, bool enable) { GrDistanceFieldTextContext* textContext = SkNEW_ARGS(GrDistanceFieldTextContext, - (context, props, enable)); - textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, props); + (context, gpuDevice, props, enable)); + textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, gpuDevice, props); return textContext; } @@ -116,8 +118,9 @@ bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint, const SkMatrix& v } inline void GrDistanceFieldTextContext::init(GrRenderTarget* rt, const GrClip& clip, - const GrPaint& paint, const SkPaint& skPaint) { - GrTextContext::init(rt, clip, paint, skPaint); + const GrPaint& paint, const SkPaint& skPaint, + const SkIRect& regionClipBounds) { + GrTextContext::init(rt, clip, paint, skPaint, regionClipBounds); fStrike = NULL; @@ -214,7 +217,8 @@ void GrDistanceFieldTextContext::onDrawText(GrRenderTarget* rt, const GrClip& cl const GrPaint& paint, const SkPaint& skPaint, const SkMatrix& viewMatrix, const char text[], size_t byteLength, - SkScalar x, SkScalar y) { + SkScalar x, SkScalar y, + const SkIRect& regionClipBounds) { SkASSERT(byteLength == 0 || text != NULL); // nothing to draw @@ -272,8 +276,8 @@ void GrDistanceFieldTextContext::onDrawText(GrRenderTarget* rt, const GrClip& cl y -= alignY; SkPoint offset = SkPoint::Make(x, y); - this->drawPosText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, positions.begin(), 2, - offset); + this->onDrawPosText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, positions.begin(), + 2, offset, regionClipBounds); } void GrDistanceFieldTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip, @@ -281,7 +285,8 @@ void GrDistanceFieldTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& const SkPaint& skPaint, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, - const SkPoint& offset) { + const SkPoint& offset, + const SkIRect& regionClipBounds) { SkASSERT(byteLength == 0 || text != NULL); SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); @@ -292,7 +297,7 @@ void GrDistanceFieldTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& } fViewMatrix = viewMatrix; - this->init(rt, clip, paint, skPaint); + this->init(rt, clip, paint, skPaint, regionClipBounds); SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); @@ -369,9 +374,10 @@ void GrDistanceFieldTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& this->finish(); if (fallbackTxt.count() > 0) { - fFallbackTextContext->drawPosText(rt, clip, paint, skPaint, viewMatrix, fallbackTxt.begin(), - fallbackTxt.count(), fallbackPos.begin(), - scalarsPerPosition, offset); + fFallbackTextContext->drawPosText(rt, clip, paint, skPaint, viewMatrix, + fallbackTxt.begin(), fallbackTxt.count(), + fallbackPos.begin(), scalarsPerPosition, offset, + regionClipBounds); } } diff --git a/src/gpu/GrDistanceFieldTextContext.h b/src/gpu/GrDistanceFieldTextContext.h index 129c6e9d85..3fe44888ce 100644 --- a/src/gpu/GrDistanceFieldTextContext.h +++ b/src/gpu/GrDistanceFieldTextContext.h @@ -18,7 +18,8 @@ class GrTextStrike; */ class GrDistanceFieldTextContext : public GrTextContext { public: - static GrDistanceFieldTextContext* Create(GrContext*, const SkDeviceProperties&, bool enable); + static GrDistanceFieldTextContext* Create(GrContext*, SkGpuDevice*, const SkDeviceProperties&, + bool enable); virtual ~GrDistanceFieldTextContext(); @@ -48,21 +49,22 @@ private: SkRect fVertexBounds; SkMatrix fViewMatrix; - GrDistanceFieldTextContext(GrContext*, const SkDeviceProperties&, bool enable); + GrDistanceFieldTextContext(GrContext*, SkGpuDevice*, const SkDeviceProperties&, bool enable); bool canDraw(const SkPaint& paint, const SkMatrix& viewMatrix) SK_OVERRIDE; virtual void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, const SkMatrix& viewMatrix, const char text[], size_t byteLength, - SkScalar x, SkScalar y) SK_OVERRIDE; + SkScalar x, SkScalar y, const SkIRect& regionClipBounds) SK_OVERRIDE; virtual void onDrawPosText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, - const SkPoint& offset) SK_OVERRIDE; + const SkPoint& offset, const SkIRect& regionClipBounds) SK_OVERRIDE; - void init(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&); + void init(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, + const SkIRect& regionClipBounds); bool appendGlyph(GrGlyph::PackedID, SkScalar left, SkScalar top, GrFontScaler*); bool uploadGlyph(GrGlyph*, GrFontScaler*); void setupCoverageEffect(const SkColor& filteredColor); diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp index ec2fa21af0..db41c02239 100644 --- a/src/gpu/GrStencilAndCoverTextContext.cpp +++ b/src/gpu/GrStencilAndCoverTextContext.cpp @@ -20,19 +20,21 @@ #include "SkTextMapStateProc.h" #include "SkTextFormatParams.h" -GrStencilAndCoverTextContext::GrStencilAndCoverTextContext( - GrContext* context, const SkDeviceProperties& properties) - : GrTextContext(context, properties) +GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context, + SkGpuDevice* gpuDevice, + const SkDeviceProperties& properties) + : GrTextContext(context, gpuDevice, properties) , fStroke(SkStrokeRec::kFill_InitStyle) , fQueuedGlyphCount(0) , fFallbackGlyphsIdx(kGlyphBufferSize) { } -GrStencilAndCoverTextContext* GrStencilAndCoverTextContext::Create(GrContext* context, - const SkDeviceProperties& props) { +GrStencilAndCoverTextContext* +GrStencilAndCoverTextContext::Create(GrContext* context, SkGpuDevice* gpuDevice, + const SkDeviceProperties& props) { GrStencilAndCoverTextContext* textContext = SkNEW_ARGS(GrStencilAndCoverTextContext, - (context, props)); - textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, props); + (context, gpuDevice, props)); + textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, gpuDevice, props); return textContext; } @@ -71,7 +73,8 @@ void GrStencilAndCoverTextContext::onDrawText(GrRenderTarget* rt, const SkMatrix& viewMatrix, const char text[], size_t byteLength, - SkScalar x, SkScalar y) { + SkScalar x, SkScalar y, + const SkIRect& regionClipBounds) { SkASSERT(byteLength == 0 || text != NULL); if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { @@ -93,7 +96,8 @@ void GrStencilAndCoverTextContext::onDrawText(GrRenderTarget* rt, // will turn off the use of device-space glyphs when perspective transforms // are in use. - this->init(rt, clip, paint, skPaint, byteLength, kMaxAccuracy_RenderMode, viewMatrix); + this->init(rt, clip, paint, skPaint, byteLength, kMaxAccuracy_RenderMode, viewMatrix, + regionClipBounds); // Transform our starting point. if (fUsingDeviceSpaceGlyphs) { @@ -164,7 +168,8 @@ void GrStencilAndCoverTextContext::onDrawPosText(GrRenderTarget* rt, size_t byteLength, const SkScalar pos[], int scalarsPerPosition, - const SkPoint& offset) { + const SkPoint& offset, + const SkIRect& regionClipBounds) { SkASSERT(byteLength == 0 || text != NULL); SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); @@ -181,7 +186,8 @@ void GrStencilAndCoverTextContext::onDrawPosText(GrRenderTarget* rt, // transform is not part of SkPaint::measureText API, and thus we use the // same glyphs as what were measured. - this->init(rt, clip, paint, skPaint, byteLength, kMaxPerformance_RenderMode, viewMatrix); + this->init(rt, clip, paint, skPaint, byteLength, kMaxPerformance_RenderMode, viewMatrix, + regionClipBounds); SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); @@ -239,8 +245,9 @@ void GrStencilAndCoverTextContext::init(GrRenderTarget* rt, const SkPaint& skPaint, size_t textByteLength, RenderMode renderMode, - const SkMatrix& viewMatrix) { - GrTextContext::init(rt, clip, paint, skPaint); + const SkMatrix& viewMatrix, + const SkIRect& regionClipBounds) { + GrTextContext::init(rt, clip, paint, skPaint, regionClipBounds); fContextInitialMatrix = viewMatrix; fViewMatrix = viewMatrix; @@ -449,7 +456,7 @@ void GrStencilAndCoverTextContext::flush() { fViewMatrix, (char*)&fGlyphIndices[fFallbackGlyphsIdx], 2 * fallbackGlyphCount, get_xy_scalar_array(&fGlyphPositions[fFallbackGlyphsIdx]), - 2, SkPoint::Make(0, 0)); + 2, SkPoint::Make(0, 0), fRegionClipBounds); fFallbackGlyphsIdx = kGlyphBufferSize; } diff --git a/src/gpu/GrStencilAndCoverTextContext.h b/src/gpu/GrStencilAndCoverTextContext.h index d7871dcc31..e42989b90f 100644 --- a/src/gpu/GrStencilAndCoverTextContext.h +++ b/src/gpu/GrStencilAndCoverTextContext.h @@ -23,7 +23,8 @@ class GrPathRange; */ class GrStencilAndCoverTextContext : public GrTextContext { public: - static GrStencilAndCoverTextContext* Create(GrContext*, const SkDeviceProperties&); + static GrStencilAndCoverTextContext* Create(GrContext*, SkGpuDevice*, + const SkDeviceProperties&); virtual ~GrStencilAndCoverTextContext(); @@ -67,22 +68,23 @@ private: SkMatrix fLocalMatrix; bool fUsingDeviceSpaceGlyphs; - GrStencilAndCoverTextContext(GrContext*, const SkDeviceProperties&); + GrStencilAndCoverTextContext(GrContext*, SkGpuDevice*, const SkDeviceProperties&); bool canDraw(const SkPaint& paint, const SkMatrix& viewMatrix) SK_OVERRIDE; virtual void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, const SkMatrix& viewMatrix, const char text[], size_t byteLength, - SkScalar x, SkScalar y) SK_OVERRIDE; + SkScalar x, SkScalar y, const SkIRect& regionClipBounds) SK_OVERRIDE; virtual void onDrawPosText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, - const SkPoint& offset) SK_OVERRIDE; + const SkPoint& offset, const SkIRect& regionClipBounds) SK_OVERRIDE; void init(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, - size_t textByteLength, RenderMode, const SkMatrix& viewMatrix); + size_t textByteLength, RenderMode, const SkMatrix& viewMatrix, + const SkIRect& regionClipBounds); bool mapToFallbackContext(SkMatrix* inverse); void appendGlyph(const SkGlyph&, const SkPoint&); void flush(); diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp index ad5e7c0aa5..28e10e398c 100644 --- a/src/gpu/GrTextContext.cpp +++ b/src/gpu/GrTextContext.cpp @@ -11,11 +11,19 @@ #include "GrFontScaler.h" #include "SkAutoKern.h" +#include "SkDrawProcs.h" #include "SkGlyphCache.h" - -GrTextContext::GrTextContext(GrContext* context, const SkDeviceProperties& properties) : - fFallbackTextContext(NULL), - fContext(context), fDeviceProperties(properties), fDrawTarget(NULL) { +#include "SkGpuDevice.h" +#include "SkTextMapStateProc.h" +#include "SkTextToPathIter.h" + +GrTextContext::GrTextContext(GrContext* context, SkGpuDevice* gpuDevice, + const SkDeviceProperties& properties) + : fFallbackTextContext(NULL) + , fContext(context) + , fGpuDevice(gpuDevice) + , fDeviceProperties(properties) + , fDrawTarget(NULL) { } GrTextContext::~GrTextContext() { @@ -23,11 +31,12 @@ GrTextContext::~GrTextContext() { } void GrTextContext::init(GrRenderTarget* rt, const GrClip& clip, const GrPaint& grPaint, - const SkPaint& skPaint) { + const SkPaint& skPaint, const SkIRect& regionClipBounds) { fClip = clip; fRenderTarget.reset(SkRef(rt)); + fRegionClipBounds = regionClipBounds; fClip.getConservativeBounds(fRenderTarget->width(), fRenderTarget->height(), &fClipRect); fDrawTarget = fContext->getTextTarget(); @@ -36,48 +45,119 @@ void GrTextContext::init(GrRenderTarget* rt, const GrClip& clip, const GrPaint& fSkPaint = skPaint; } -bool GrTextContext::drawText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& paint, +void GrTextContext::drawText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& paint, const SkPaint& skPaint, const SkMatrix& viewMatrix, const char text[], size_t byteLength, - SkScalar x, SkScalar y) { + SkScalar x, SkScalar y, const SkIRect& clipBounds) { if (!fContext->getTextTarget()) { - return false; + return; } GrTextContext* textContext = this; do { if (textContext->canDraw(skPaint, viewMatrix)) { - textContext->onDrawText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, x, y); - return true; + textContext->onDrawText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, x, y, + clipBounds); + return; } textContext = textContext->fFallbackTextContext; } while (textContext); - return false; + // fall back to drawing as a path + this->drawTextAsPath(skPaint, viewMatrix, text, byteLength, x, y, clipBounds); } -bool GrTextContext::drawPosText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& paint, +void GrTextContext::drawPosText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& paint, const SkPaint& skPaint, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, - const SkPoint& offset) { + const SkPoint& offset, const SkIRect& clipBounds) { if (!fContext->getTextTarget()) { - return false; + return; } GrTextContext* textContext = this; do { if (textContext->canDraw(skPaint, viewMatrix)) { textContext->onDrawPosText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, pos, - scalarsPerPosition, offset); - return true; + scalarsPerPosition, offset, clipBounds); + return; } textContext = textContext->fFallbackTextContext; } while (textContext); - return false; + // fall back to drawing as a path + this->drawPosTextAsPath(skPaint, viewMatrix, text, byteLength, pos, scalarsPerPosition, offset, + clipBounds); +} + +void GrTextContext::drawTextAsPath(const SkPaint& skPaint, const SkMatrix& viewMatrix, + const char text[], size_t byteLength, SkScalar x, SkScalar y, + const SkIRect& clipBounds) { + SkTextToPathIter iter(text, byteLength, skPaint, true); + + SkMatrix matrix; + matrix.setScale(iter.getPathScale(), iter.getPathScale()); + matrix.postTranslate(x, y); + + const SkPath* iterPath; + SkScalar xpos, prevXPos = 0; + + while (iter.next(&iterPath, &xpos)) { + matrix.postTranslate(xpos - prevXPos, 0); + if (iterPath) { + const SkPaint& pnt = iter.getPaint(); + fGpuDevice->internalDrawPath(*iterPath, pnt, viewMatrix, &matrix, clipBounds, false); + } + prevXPos = xpos; + } } +void GrTextContext::drawPosTextAsPath(const SkPaint& origPaint, const SkMatrix& viewMatrix, + const char text[], size_t byteLength, + const SkScalar pos[], int scalarsPerPosition, + const SkPoint& offset, const SkIRect& clipBounds) { + // setup our std paint, in hopes of getting hits in the cache + SkPaint paint(origPaint); + SkScalar matrixScale = paint.setupForAsPaths(); + + SkMatrix matrix; + matrix.setScale(matrixScale, matrixScale); + + // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. + paint.setStyle(SkPaint::kFill_Style); + paint.setPathEffect(NULL); + + SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); + SkAutoGlyphCache autoCache(paint, NULL, NULL); + SkGlyphCache* cache = autoCache.getCache(); + + const char* stop = text + byteLength; + SkTextAlignProc alignProc(paint.getTextAlign()); + SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); + + // Now restore the original settings, so we "draw" with whatever style/stroking. + paint.setStyle(origPaint.getStyle()); + paint.setPathEffect(origPaint.getPathEffect()); + + while (text < stop) { + const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); + if (glyph.fWidth) { + const SkPath* path = cache->findPath(glyph); + if (path) { + SkPoint tmsLoc; + tmsProc(pos, &tmsLoc); + SkPoint loc; + alignProc(tmsLoc, glyph, &loc); + + matrix[SkMatrix::kMTransX] = loc.fX; + matrix[SkMatrix::kMTransY] = loc.fY; + fGpuDevice->internalDrawPath(*path, paint, viewMatrix, &matrix, clipBounds, false); + } + } + pos += scalarsPerPosition; + } +} //*** change to output positions? int GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc, diff --git a/src/gpu/GrTextContext.h b/src/gpu/GrTextContext.h index d333c63141..56a113daed 100644 --- a/src/gpu/GrTextContext.h +++ b/src/gpu/GrTextContext.h @@ -19,6 +19,7 @@ class GrClip; class GrContext; class GrDrawTarget; class GrFontScaler; +class SkGpuDevice; /* * This class wraps the state for a single text render @@ -27,41 +28,56 @@ class GrTextContext { public: virtual ~GrTextContext(); - bool drawText(GrRenderTarget* rt, const GrClip&, const GrPaint&, const SkPaint&, + void drawText(GrRenderTarget* rt, const GrClip&, const GrPaint&, const SkPaint&, const SkMatrix& viewMatrix, const char text[], size_t byteLength, SkScalar x, - SkScalar y); - bool drawPosText(GrRenderTarget* rt, const GrClip&, const GrPaint&, const SkPaint&, + SkScalar y, const SkIRect& clipBounds); + void drawPosText(GrRenderTarget* rt, const GrClip&, const GrPaint&, const SkPaint&, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, - const SkPoint& offset); + const SkPoint& offset, const SkIRect& clipBounds); protected: GrTextContext* fFallbackTextContext; GrContext* fContext; + // TODO we probably don't really need to store a back pointer to the owning SkGpuDevice, except + // we need to be able to call drawPath on it in the event no other text context can draw the + // text. We might be able to move this logic to context though. This is unreffed because + // GrTextContext is completely owned by SkGpuDevice + SkGpuDevice* fGpuDevice; SkDeviceProperties fDeviceProperties; SkAutoTUnref<GrRenderTarget> fRenderTarget; GrClip fClip; GrDrawTarget* fDrawTarget; SkIRect fClipRect; + SkIRect fRegionClipBounds; GrPaint fPaint; SkPaint fSkPaint; - GrTextContext(GrContext*, const SkDeviceProperties&); + GrTextContext(GrContext*, SkGpuDevice*, const SkDeviceProperties&); virtual bool canDraw(const SkPaint& paint, const SkMatrix& viewMatrix) = 0; virtual void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, const SkMatrix& viewMatrix, const char text[], size_t byteLength, - SkScalar x, SkScalar y) = 0; + SkScalar x, SkScalar y, const SkIRect& clipBounds) = 0; virtual void onDrawPosText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, - const SkPoint& offset) = 0; + const SkPoint& offset, const SkIRect& clipBounds) = 0; - void init(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&); + void drawTextAsPath(const SkPaint& origPaint, const SkMatrix& viewMatrix, + const char text[], size_t byteLength, SkScalar x, SkScalar y, + const SkIRect& clipBounds); + void drawPosTextAsPath(const SkPaint& origPaint, const SkMatrix& viewMatrix, + const char text[], size_t byteLength, + const SkScalar pos[], int scalarsPerPosition, + const SkPoint& offset, const SkIRect& clipBounds); + + void init(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, + const SkIRect& regionClipBounds); void finish() { fDrawTarget = NULL; } static GrFontScaler* GetGrFontScaler(SkGlyphCache* cache); diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index a97e42ece0..0335bcfa6b 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -160,7 +160,8 @@ SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, const SkSurfaceProps* props, unsign fLegacyBitmap.setPixelRef(pr)->unref(); bool useDFT = fSurfaceProps.isUseDistanceFieldFonts(); - fTextContext = fContext->createTextContext(fRenderTarget, this->getLeakyProperties(), useDFT); + fTextContext = fContext->createTextContext(fRenderTarget, this, this->getLeakyProperties(), + useDFT); } GrRenderTarget* SkGpuDevice::CreateRenderTarget(GrContext* context, SkSurface::Budgeted budgeted, @@ -1824,11 +1825,8 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text, SkDEBUGCODE(this->validate();) - if (!fTextContext->drawText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix, - (const char *)text, byteLength, x, y)) { - // this will just call our drawPath() - draw.drawText_asPaths((const char*)text, byteLength, x, y, paint); - } + fTextContext->drawText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix, + (const char *)text, byteLength, x, y, draw.fClip->getBounds()); } void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, size_t byteLength, @@ -1842,11 +1840,9 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, size_t byteL SkDEBUGCODE(this->validate();) - if (!fTextContext->drawPosText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix, - (const char *)text, byteLength, pos, scalarsPerPos, offset)) { - // this will just call our drawPath() - draw.drawPosText_asPaths((const char*)text, byteLength, pos, scalarsPerPos, offset, paint); - } + fTextContext->drawPosText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix, + (const char *)text, byteLength, pos, scalarsPerPos, offset, + draw.fClip->getBounds()); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h index af6dd0bcc2..be7857aadb 100644 --- a/src/gpu/SkGpuDevice.h +++ b/src/gpu/SkGpuDevice.h @@ -210,6 +210,7 @@ private: static GrRenderTarget* CreateRenderTarget(GrContext*, SkSurface::Budgeted, const SkImageInfo&, int sampleCount); + friend class GrTextContext; typedef SkBaseDevice INHERITED; }; |