Let text contexts fall back directly to paths

BUG=skia:

Review URL: https://codereview.chromium.org/1015173002
This commit is contained in:
joshualitt 2015-03-20 10:30:14 -07:00 committed by Commit bot
parent 1b600d3446
commit 6e8cd96719
13 changed files with 222 additions and 97 deletions

View File

@ -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;

View File

@ -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
@ -762,6 +753,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
@ -776,6 +781,9 @@ private:
*/
static void OverBudgetCB(void* data);
// TODO see note on createTextContext
friend class SkGpuDevice;
typedef SkRefCnt INHERITED;
};

View File

@ -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();

View File

@ -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

View File

@ -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);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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();

View File

@ -11,11 +11,19 @@
#include "GrFontScaler.h"
#include "SkAutoKern.h"
#include "SkDrawProcs.h"
#include "SkGlyphCache.h"
#include "SkGpuDevice.h"
#include "SkTextMapStateProc.h"
#include "SkTextToPathIter.h"
GrTextContext::GrTextContext(GrContext* context, const SkDeviceProperties& properties) :
fFallbackTextContext(NULL),
fContext(context), fDeviceProperties(properties), fDrawTarget(NULL) {
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,

View File

@ -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);

View File

@ -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());
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -210,6 +210,7 @@ private:
static GrRenderTarget* CreateRenderTarget(GrContext*, SkSurface::Budgeted, const SkImageInfo&,
int sampleCount);
friend class GrTextContext;
typedef SkBaseDevice INHERITED;
};