Let text contexts fall back directly to paths
BUG=skia: Review URL: https://codereview.chromium.org/1015173002
This commit is contained in:
parent
1b600d3446
commit
6e8cd96719
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -210,6 +210,7 @@ private:
|
||||
static GrRenderTarget* CreateRenderTarget(GrContext*, SkSurface::Budgeted, const SkImageInfo&,
|
||||
int sampleCount);
|
||||
|
||||
friend class GrTextContext;
|
||||
typedef SkBaseDevice INHERITED;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user