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
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 @@
fVertexBounds.setLargestInverted();
}
+GrBitmapTextContext* GrBitmapTextContext::Create(GrContext* context,
+ const SkDeviceProperties& props) {
+ return SkNEW_ARGS(GrBitmapTextContext, (context, props));
+}
+
GrBitmapTextContext::~GrBitmapTextContext() {
this->flush();
}
@@ -86,7 +91,7 @@
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 @@
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,18 +18,10 @@
*/
class GrBitmapTextContext : public GrTextContext {
public:
- GrBitmapTextContext(GrContext*, const SkDeviceProperties&);
+ static GrBitmapTextContext* Create(GrContext*, const SkDeviceProperties&);
+
virtual ~GrBitmapTextContext();
- 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;
-
private:
enum {
kMinRequestedGlyphs = 1,
@@ -49,6 +41,17 @@
// 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 @@
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 @@
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 @@
}
}
-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 @@
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,18 +18,10 @@
*/
class GrDistanceFieldTextContext : public GrTextContext {
public:
- GrDistanceFieldTextContext(GrContext*, const SkDeviceProperties&, bool enable);
+ static GrDistanceFieldTextContext* Create(GrContext*, const SkDeviceProperties&, bool enable);
+
virtual ~GrDistanceFieldTextContext();
- 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;
-
private:
enum {
kMinRequestedGlyphs = 1,
@@ -54,6 +46,17 @@
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 @@
, 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 @@
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 @@
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,19 +24,10 @@
*/
class GrStencilAndCoverTextContext : public GrTextContext {
public:
- GrStencilAndCoverTextContext(GrContext*, const SkDeviceProperties&);
+ static GrStencilAndCoverTextContext* Create(GrContext*, const SkDeviceProperties&);
+
virtual ~GrStencilAndCoverTextContext();
- 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;
-
private:
static const int kGlyphBufferSize = 1024;
@@ -73,6 +64,18 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
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);
+ GrPaint grPaint;
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
- SkDEBUGCODE(this->validate();)
+ 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);
-
- 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 @@
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);
+ GrPaint grPaint;
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
- SkDEBUGCODE(this->validate();)
+ 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);
-
- 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 @@
GrClipData fClipData;
- GrTextContext* fMainTextContext;
- GrTextContext* fFallbackTextContext;
+ GrTextContext* fTextContext;
// state for our render-target
GrRenderTarget* fRenderTarget;