Implement cached nvpr text blobs
BUG=skia: Review URL: https://codereview.chromium.org/1381073002
This commit is contained in:
parent
02015e51d9
commit
cdd7907a3d
@ -93,6 +93,7 @@ private:
|
|||||||
static unsigned ScalarsPerGlyph(GlyphPositioning pos);
|
static unsigned ScalarsPerGlyph(GlyphPositioning pos);
|
||||||
|
|
||||||
friend class GrAtlasTextContext;
|
friend class GrAtlasTextContext;
|
||||||
|
friend class GrStencilAndCoverTextContext;
|
||||||
friend class GrTextBlobCache;
|
friend class GrTextBlobCache;
|
||||||
friend class GrTextContext;
|
friend class GrTextContext;
|
||||||
friend class SkBaseDevice;
|
friend class SkBaseDevice;
|
||||||
|
@ -17,15 +17,27 @@
|
|||||||
#include "SkDrawProcs.h"
|
#include "SkDrawProcs.h"
|
||||||
#include "SkGlyphCache.h"
|
#include "SkGlyphCache.h"
|
||||||
#include "SkGpuDevice.h"
|
#include "SkGpuDevice.h"
|
||||||
|
#include "SkGrPriv.h"
|
||||||
#include "SkPath.h"
|
#include "SkPath.h"
|
||||||
#include "SkTextMapStateProc.h"
|
#include "SkTextMapStateProc.h"
|
||||||
#include "SkTextFormatParams.h"
|
#include "SkTextFormatParams.h"
|
||||||
|
|
||||||
#include "batches/GrDrawPathBatch.h"
|
#include "batches/GrDrawPathBatch.h"
|
||||||
|
|
||||||
|
template<typename Key, typename Val> static void delete_hash_map_entry(const Key&, Val* val) {
|
||||||
|
SkASSERT(*val);
|
||||||
|
delete *val;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> static void delete_hash_table_entry(T* val) {
|
||||||
|
SkASSERT(*val);
|
||||||
|
delete *val;
|
||||||
|
}
|
||||||
|
|
||||||
GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context,
|
GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context,
|
||||||
const SkSurfaceProps& surfaceProps)
|
const SkSurfaceProps& surfaceProps)
|
||||||
: INHERITED(context, surfaceProps) {
|
: INHERITED(context, surfaceProps),
|
||||||
|
fCacheSize(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
GrStencilAndCoverTextContext*
|
GrStencilAndCoverTextContext*
|
||||||
@ -38,13 +50,11 @@ GrStencilAndCoverTextContext::Create(GrContext* context, const SkSurfaceProps& s
|
|||||||
}
|
}
|
||||||
|
|
||||||
GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() {
|
GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() {
|
||||||
|
fBlobIdCache.foreach(delete_hash_map_entry<uint32_t, TextBlob*>);
|
||||||
|
fBlobKeyCache.foreach(delete_hash_table_entry<TextBlob*>);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GrStencilAndCoverTextContext::canDraw(const GrRenderTarget* rt,
|
bool GrStencilAndCoverTextContext::internalCanDraw(const SkPaint& skPaint) {
|
||||||
const GrClip& clip,
|
|
||||||
const GrPaint& paint,
|
|
||||||
const SkPaint& skPaint,
|
|
||||||
const SkMatrix& viewMatrix) {
|
|
||||||
if (skPaint.getRasterizer()) {
|
if (skPaint.getRasterizer()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -68,10 +78,12 @@ void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget*
|
|||||||
const char text[],
|
const char text[],
|
||||||
size_t byteLength,
|
size_t byteLength,
|
||||||
SkScalar x, SkScalar y,
|
SkScalar x, SkScalar y,
|
||||||
const SkIRect& regionClipBounds) {
|
const SkIRect& clipBounds) {
|
||||||
TextRun run(skPaint);
|
TextRun run(skPaint);
|
||||||
|
GrPipelineBuilder pipelineBuilder(paint, rt, clip);
|
||||||
run.setText(text, byteLength, x, y, fContext, &fSurfaceProps);
|
run.setText(text, byteLength, x, y, fContext, &fSurfaceProps);
|
||||||
run.draw(dc, rt, clip, paint, viewMatrix, regionClipBounds, fFallbackTextContext, skPaint);
|
run.draw(dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBounds,
|
||||||
|
fFallbackTextContext, skPaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarget* rt,
|
void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarget* rt,
|
||||||
@ -84,10 +96,137 @@ void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarg
|
|||||||
const SkScalar pos[],
|
const SkScalar pos[],
|
||||||
int scalarsPerPosition,
|
int scalarsPerPosition,
|
||||||
const SkPoint& offset,
|
const SkPoint& offset,
|
||||||
const SkIRect& regionClipBounds) {
|
const SkIRect& clipBounds) {
|
||||||
TextRun run(skPaint);
|
TextRun run(skPaint);
|
||||||
|
GrPipelineBuilder pipelineBuilder(paint, rt, clip);
|
||||||
run.setPosText(text, byteLength, pos, scalarsPerPosition, offset, fContext, &fSurfaceProps);
|
run.setPosText(text, byteLength, pos, scalarsPerPosition, offset, fContext, &fSurfaceProps);
|
||||||
run.draw(dc, rt, clip, paint, viewMatrix, regionClipBounds, fFallbackTextContext, skPaint);
|
run.draw(dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBounds,
|
||||||
|
fFallbackTextContext, skPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GrStencilAndCoverTextContext::drawTextBlob(GrDrawContext* dc, GrRenderTarget* rt,
|
||||||
|
const GrClip& clip, const SkPaint& skPaint,
|
||||||
|
const SkMatrix& viewMatrix,
|
||||||
|
const SkTextBlob* skBlob, SkScalar x, SkScalar y,
|
||||||
|
SkDrawFilter* drawFilter,
|
||||||
|
const SkIRect& clipBounds) {
|
||||||
|
if (!this->internalCanDraw(skPaint)) {
|
||||||
|
fFallbackTextContext->drawTextBlob(dc, rt, clip, skPaint, viewMatrix, skBlob, x, y,
|
||||||
|
drawFilter, clipBounds);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drawFilter || skPaint.getPathEffect()) {
|
||||||
|
// This draw can't be cached.
|
||||||
|
INHERITED::drawTextBlob(dc, rt, clip, skPaint, viewMatrix, skBlob, x, y, drawFilter,
|
||||||
|
clipBounds);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fContext->abandoned()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GrPaint paint;
|
||||||
|
if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &paint)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint);
|
||||||
|
GrPipelineBuilder pipelineBuilder(paint, rt, clip);
|
||||||
|
|
||||||
|
TextBlob::Iter iter(blob);
|
||||||
|
for (TextRun* run = iter.get(); run; run = iter.next()) {
|
||||||
|
run->draw(dc, &pipelineBuilder, paint.getColor(), viewMatrix, x, y, clipBounds,
|
||||||
|
fFallbackTextContext, skPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const GrStencilAndCoverTextContext::TextBlob&
|
||||||
|
GrStencilAndCoverTextContext::findOrCreateTextBlob(const SkTextBlob* skBlob,
|
||||||
|
const SkPaint& skPaint) {
|
||||||
|
// The font-related parameters are baked into the text blob and will override this skPaint, so
|
||||||
|
// the only remaining properties that can affect a TextBlob are the ones related to stroke.
|
||||||
|
if (SkPaint::kFill_Style == skPaint.getStyle()) { // Fast path.
|
||||||
|
if (TextBlob** found = fBlobIdCache.find(skBlob->uniqueID())) {
|
||||||
|
fLRUList.remove(*found);
|
||||||
|
fLRUList.addToTail(*found);
|
||||||
|
return **found;
|
||||||
|
}
|
||||||
|
TextBlob* blob = new TextBlob(skBlob->uniqueID(), skBlob, skPaint, fContext,
|
||||||
|
&fSurfaceProps);
|
||||||
|
this->purgeToFit(*blob);
|
||||||
|
fBlobIdCache.set(skBlob->uniqueID(), blob);
|
||||||
|
fLRUList.addToTail(blob);
|
||||||
|
fCacheSize += blob->cpuMemorySize();
|
||||||
|
return *blob;
|
||||||
|
} else {
|
||||||
|
GrStrokeInfo stroke(skPaint);
|
||||||
|
SkSTArray<4, uint32_t, true> key;
|
||||||
|
key.reset(1 + stroke.computeUniqueKeyFragmentData32Cnt());
|
||||||
|
key[0] = skBlob->uniqueID();
|
||||||
|
stroke.asUniqueKeyFragment(&key[1]);
|
||||||
|
if (TextBlob** found = fBlobKeyCache.find(key)) {
|
||||||
|
fLRUList.remove(*found);
|
||||||
|
fLRUList.addToTail(*found);
|
||||||
|
return **found;
|
||||||
|
}
|
||||||
|
TextBlob* blob = new TextBlob(key, skBlob, skPaint, fContext, &fSurfaceProps);
|
||||||
|
this->purgeToFit(*blob);
|
||||||
|
fBlobKeyCache.set(blob);
|
||||||
|
fLRUList.addToTail(blob);
|
||||||
|
fCacheSize += blob->cpuMemorySize();
|
||||||
|
return *blob;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GrStencilAndCoverTextContext::purgeToFit(const TextBlob& blob) {
|
||||||
|
static const int maxCacheSize = 4 * 1024 * 1024; // Allow up to 4 MB for caching text blobs.
|
||||||
|
|
||||||
|
int maxSizeForNewBlob = maxCacheSize - blob.cpuMemorySize();
|
||||||
|
while (fCacheSize && fCacheSize > maxSizeForNewBlob) {
|
||||||
|
TextBlob* lru = fLRUList.head();
|
||||||
|
if (1 == lru->key().count()) {
|
||||||
|
// 1-length keys are unterstood to be the blob id.
|
||||||
|
fBlobIdCache.remove(lru->key()[0]);
|
||||||
|
} else {
|
||||||
|
fBlobKeyCache.remove(lru->key());
|
||||||
|
}
|
||||||
|
fLRUList.remove(lru);
|
||||||
|
fCacheSize -= lru->cpuMemorySize();
|
||||||
|
delete lru;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void GrStencilAndCoverTextContext::TextBlob::init(const SkTextBlob* skBlob, const SkPaint& skPaint,
|
||||||
|
GrContext* ctx, const SkSurfaceProps* props) {
|
||||||
|
fCpuMemorySize = sizeof(TextBlob);
|
||||||
|
SkPaint runPaint(skPaint);
|
||||||
|
for (SkTextBlob::RunIterator iter(skBlob); !iter.done(); iter.next()) {
|
||||||
|
iter.applyFontToPaint(&runPaint); // No need to re-seed the paint.
|
||||||
|
TextRun* run = SkNEW_INSERT_AT_LLIST_TAIL(this, TextRun, (runPaint));
|
||||||
|
|
||||||
|
const char* text = reinterpret_cast<const char*>(iter.glyphs());
|
||||||
|
size_t byteLength = sizeof(uint16_t) * iter.glyphCount();
|
||||||
|
const SkPoint& runOffset = iter.offset();
|
||||||
|
|
||||||
|
switch (iter.positioning()) {
|
||||||
|
case SkTextBlob::kDefault_Positioning:
|
||||||
|
run->setText(text, byteLength, runOffset.fX, runOffset.fY, ctx, props);
|
||||||
|
break;
|
||||||
|
case SkTextBlob::kHorizontal_Positioning:
|
||||||
|
run->setPosText(text, byteLength, iter.pos(), 1, SkPoint::Make(0, runOffset.fY),
|
||||||
|
ctx, props);
|
||||||
|
break;
|
||||||
|
case SkTextBlob::kFull_Positioning:
|
||||||
|
run->setPosText(text, byteLength, iter.pos(), 2, SkPoint::Make(0, 0), ctx, props);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fCpuMemorySize += run->cpuMemorySize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -120,7 +259,8 @@ private:
|
|||||||
|
|
||||||
GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke)
|
GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke)
|
||||||
: fStroke(fontAndStroke),
|
: fStroke(fontAndStroke),
|
||||||
fFont(fontAndStroke) {
|
fFont(fontAndStroke),
|
||||||
|
fTotalGlyphCount(0) {
|
||||||
SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported.
|
SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported.
|
||||||
|
|
||||||
// Setting to "fill" ensures that no strokes get baked into font outlines. (We use the GPU path
|
// Setting to "fill" ensures that no strokes get baked into font outlines. (We use the GPU path
|
||||||
@ -168,7 +308,7 @@ GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// When drawing from canonically sized paths, the actual local coords are fTextRatio * coords.
|
// When drawing from canonically sized paths, the actual local coords are fTextRatio * coords.
|
||||||
fLocalMatrix.setScale(fTextRatio, fTextRatio);
|
fLocalMatrixTemplate.setScale(fTextRatio, fTextRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
GrStencilAndCoverTextContext::TextRun::~TextRun() {
|
GrStencilAndCoverTextContext::TextRun::~TextRun() {
|
||||||
@ -182,9 +322,10 @@ void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by
|
|||||||
SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr);
|
SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr);
|
||||||
SkGlyphCache* glyphCache = autoGlyphCache.getCache();
|
SkGlyphCache* glyphCache = autoGlyphCache.getCache();
|
||||||
|
|
||||||
|
fTotalGlyphCount = fFont.countText(text, byteLength);
|
||||||
fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache),
|
fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache),
|
||||||
GrPathRendering::kTranslate_PathTransformType,
|
GrPathRendering::kTranslate_PathTransformType,
|
||||||
fFont.countText(text, byteLength)));
|
fTotalGlyphCount));
|
||||||
|
|
||||||
SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
|
SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
|
||||||
|
|
||||||
@ -250,9 +391,10 @@ void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t
|
|||||||
SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr);
|
SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr);
|
||||||
SkGlyphCache* glyphCache = autoGlyphCache.getCache();
|
SkGlyphCache* glyphCache = autoGlyphCache.getCache();
|
||||||
|
|
||||||
|
fTotalGlyphCount = fFont.countText(text, byteLength);
|
||||||
fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache),
|
fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache),
|
||||||
GrPathRendering::kTranslate_PathTransformType,
|
GrPathRendering::kTranslate_PathTransformType,
|
||||||
fFont.countText(text, byteLength)));
|
fTotalGlyphCount));
|
||||||
|
|
||||||
SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
|
SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
|
||||||
|
|
||||||
@ -323,19 +465,19 @@ inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& gl
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GrStencilAndCoverTextContext::TextRun::draw(GrDrawContext* dc,
|
void GrStencilAndCoverTextContext::TextRun::draw(GrDrawContext* dc,
|
||||||
GrRenderTarget* rt,
|
GrPipelineBuilder* pipelineBuilder,
|
||||||
const GrClip& clip,
|
GrColor color,
|
||||||
const GrPaint& paint,
|
|
||||||
const SkMatrix& viewMatrix,
|
const SkMatrix& viewMatrix,
|
||||||
const SkIRect& regionClipBounds,
|
SkScalar x, SkScalar y,
|
||||||
|
const SkIRect& clipBounds,
|
||||||
GrTextContext* fallbackTextContext,
|
GrTextContext* fallbackTextContext,
|
||||||
const SkPaint& originalSkPaint) const {
|
const SkPaint& originalSkPaint) const {
|
||||||
SkASSERT(fDraw);
|
SkASSERT(fDraw);
|
||||||
|
SkASSERT(pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled() ||
|
||||||
|
!fFont.isAntiAlias());
|
||||||
|
|
||||||
if (fDraw->count()) {
|
if (fDraw->count()) {
|
||||||
GrPipelineBuilder pipelineBuilder(paint, rt, clip);
|
pipelineBuilder->setState(GrPipelineBuilder::kHWAntialias_Flag, fFont.isAntiAlias());
|
||||||
SkASSERT(rt->isStencilBufferMultisampled() || !paint.isAntiAlias());
|
|
||||||
pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, paint.isAntiAlias());
|
|
||||||
|
|
||||||
GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
|
GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
|
||||||
kZero_StencilOp,
|
kZero_StencilOp,
|
||||||
@ -345,12 +487,17 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrDrawContext* dc,
|
|||||||
0x0000,
|
0x0000,
|
||||||
0xffff);
|
0xffff);
|
||||||
|
|
||||||
*pipelineBuilder.stencil() = kStencilPass;
|
*pipelineBuilder->stencil() = kStencilPass;
|
||||||
|
|
||||||
SkMatrix drawMatrix(viewMatrix);
|
SkMatrix drawMatrix(viewMatrix);
|
||||||
|
drawMatrix.preTranslate(x, y);
|
||||||
drawMatrix.preScale(fTextRatio, fTextRatio);
|
drawMatrix.preScale(fTextRatio, fTextRatio);
|
||||||
|
|
||||||
dc->drawPathsFromRange(&pipelineBuilder, drawMatrix, fLocalMatrix, paint.getColor(), fDraw,
|
SkMatrix& localMatrix = fLocalMatrixTemplate;
|
||||||
|
localMatrix.setTranslateX(x);
|
||||||
|
localMatrix.setTranslateY(y);
|
||||||
|
|
||||||
|
dc->drawPathsFromRange(pipelineBuilder, drawMatrix, localMatrix, color, fDraw,
|
||||||
GrPathRendering::kWinding_FillType);
|
GrPathRendering::kWinding_FillType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,11 +508,23 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrDrawContext* dc,
|
|||||||
fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio);
|
fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
fallbackTextContext->drawTextBlob(dc, rt, clip, fallbackSkPaint, viewMatrix,
|
fallbackTextContext->drawTextBlob(dc, pipelineBuilder->getRenderTarget(),
|
||||||
fFallbackTextBlob, 0, 0, nullptr, regionClipBounds);
|
pipelineBuilder->clip(), fallbackSkPaint, viewMatrix,
|
||||||
|
fFallbackTextBlob, x, y, nullptr, clipBounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GrStencilAndCoverTextContext::TextRun::cpuMemorySize() const {
|
||||||
|
int size = sizeof(TextRun) + fTotalGlyphCount * (sizeof(uint16_t) + 2 * sizeof(float));
|
||||||
|
if (fDraw) {
|
||||||
|
size += sizeof(GrPathRangeDraw);
|
||||||
|
}
|
||||||
|
if (fFallbackTextBlob) {
|
||||||
|
size += sizeof(SkTextBlob);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void GrStencilAndCoverTextContext::FallbackBlobBuilder::init(const SkPaint& font,
|
void GrStencilAndCoverTextContext::FallbackBlobBuilder::init(const SkPaint& font,
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
#include "GrTextContext.h"
|
#include "GrTextContext.h"
|
||||||
#include "GrDrawTarget.h"
|
#include "GrDrawTarget.h"
|
||||||
#include "GrStrokeInfo.h"
|
#include "GrStrokeInfo.h"
|
||||||
|
#include "SkTHash.h"
|
||||||
|
#include "SkTInternalLList.h"
|
||||||
|
#include "SkTLList.h"
|
||||||
|
|
||||||
class GrTextStrike;
|
class GrTextStrike;
|
||||||
class GrPath;
|
class GrPath;
|
||||||
@ -31,19 +34,24 @@ public:
|
|||||||
private:
|
private:
|
||||||
GrStencilAndCoverTextContext(GrContext*, const SkSurfaceProps&);
|
GrStencilAndCoverTextContext(GrContext*, const SkSurfaceProps&);
|
||||||
|
|
||||||
bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
|
bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint& skPaint,
|
||||||
const SkPaint&, const SkMatrix& viewMatrix) override;
|
const SkMatrix&) override { return this->internalCanDraw(skPaint); }
|
||||||
|
|
||||||
|
bool internalCanDraw(const SkPaint&);
|
||||||
|
|
||||||
void onDrawText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
|
void onDrawText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
|
||||||
const SkMatrix& viewMatrix,
|
const SkMatrix& viewMatrix,
|
||||||
const char text[], size_t byteLength,
|
const char text[], size_t byteLength,
|
||||||
SkScalar x, SkScalar y, const SkIRect& regionClipBounds) override;
|
SkScalar x, SkScalar y, const SkIRect& clipBounds) override;
|
||||||
void onDrawPosText(GrDrawContext*, GrRenderTarget*,
|
void onDrawPosText(GrDrawContext*, GrRenderTarget*,
|
||||||
const GrClip&, const GrPaint&, const SkPaint&,
|
const GrClip&, const GrPaint&, const SkPaint&,
|
||||||
const SkMatrix& viewMatrix,
|
const SkMatrix& viewMatrix,
|
||||||
const char text[], size_t byteLength,
|
const char text[], size_t byteLength,
|
||||||
const SkScalar pos[], int scalarsPerPosition,
|
const SkScalar pos[], int scalarsPerPosition,
|
||||||
const SkPoint& offset, const SkIRect& regionClipBounds) override;
|
const SkPoint& offset, const SkIRect& clipBounds) override;
|
||||||
|
void drawTextBlob(GrDrawContext*, GrRenderTarget*, const GrClip&, const SkPaint&,
|
||||||
|
const SkMatrix& viewMatrix, const SkTextBlob*, SkScalar x, SkScalar y,
|
||||||
|
SkDrawFilter*, const SkIRect& clipBounds) override;
|
||||||
|
|
||||||
class FallbackBlobBuilder;
|
class FallbackBlobBuilder;
|
||||||
|
|
||||||
@ -59,9 +67,11 @@ private:
|
|||||||
const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset,
|
const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset,
|
||||||
GrContext*, const SkSurfaceProps*);
|
GrContext*, const SkSurfaceProps*);
|
||||||
|
|
||||||
void draw(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkMatrix&,
|
void draw(GrDrawContext*, GrPipelineBuilder*, GrColor, const SkMatrix&,
|
||||||
const SkIRect& regionClipBounds, GrTextContext* fallbackTextContext,
|
SkScalar x, SkScalar y, const SkIRect& clipBounds,
|
||||||
const SkPaint& originalSkPaint) const;
|
GrTextContext* fallbackTextContext, const SkPaint& originalSkPaint) const;
|
||||||
|
|
||||||
|
int cpuMemorySize() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GrPathRange* createGlyphs(GrContext*, SkGlyphCache*);
|
GrPathRange* createGlyphs(GrContext*, SkGlyphCache*);
|
||||||
@ -72,12 +82,59 @@ private:
|
|||||||
SkPaint fFont;
|
SkPaint fFont;
|
||||||
SkScalar fTextRatio;
|
SkScalar fTextRatio;
|
||||||
float fTextInverseRatio;
|
float fTextInverseRatio;
|
||||||
SkMatrix fLocalMatrix;
|
|
||||||
bool fUsingRawGlyphPaths;
|
bool fUsingRawGlyphPaths;
|
||||||
|
int fTotalGlyphCount;
|
||||||
SkAutoTUnref<GrPathRangeDraw> fDraw;
|
SkAutoTUnref<GrPathRangeDraw> fDraw;
|
||||||
SkAutoTUnref<const SkTextBlob> fFallbackTextBlob;
|
SkAutoTUnref<const SkTextBlob> fFallbackTextBlob;
|
||||||
|
mutable SkMatrix fLocalMatrixTemplate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Text blobs/caches.
|
||||||
|
|
||||||
|
class TextBlob : public SkTLList<TextRun> {
|
||||||
|
public:
|
||||||
|
typedef SkTArray<uint32_t, true> Key;
|
||||||
|
|
||||||
|
static const Key& GetKey(const TextBlob* blob) { return blob->key(); }
|
||||||
|
|
||||||
|
static uint32_t Hash(const Key& key) {
|
||||||
|
SkASSERT(key.count() > 1); // 1-length keys should be using the blob-id hash map.
|
||||||
|
return SkChecksum::Murmur3(key.begin(), sizeof(uint32_t) * key.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
TextBlob(uint32_t blobId, const SkTextBlob* skBlob, const SkPaint& skPaint,
|
||||||
|
GrContext* ctx, const SkSurfaceProps* props)
|
||||||
|
: fKey(&blobId, 1) { this->init(skBlob, skPaint, ctx, props); }
|
||||||
|
|
||||||
|
TextBlob(const Key& key, const SkTextBlob* skBlob, const SkPaint& skPaint,
|
||||||
|
GrContext* ctx, const SkSurfaceProps* props)
|
||||||
|
: fKey(key) {
|
||||||
|
// 1-length keys are unterstood to be the blob id and must use the other constructor.
|
||||||
|
SkASSERT(fKey.count() > 1);
|
||||||
|
this->init(skBlob, skPaint, ctx, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Key& key() const { return fKey; }
|
||||||
|
|
||||||
|
int cpuMemorySize() const { return fCpuMemorySize; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init(const SkTextBlob*, const SkPaint&, GrContext*, const SkSurfaceProps*);
|
||||||
|
|
||||||
|
const SkSTArray<1, uint32_t, true> fKey;
|
||||||
|
int fCpuMemorySize;
|
||||||
|
|
||||||
|
SK_DECLARE_INTERNAL_LLIST_INTERFACE(TextBlob);
|
||||||
|
};
|
||||||
|
|
||||||
|
const TextBlob& findOrCreateTextBlob(const SkTextBlob*, const SkPaint&);
|
||||||
|
void purgeToFit(const TextBlob&);
|
||||||
|
|
||||||
|
SkTHashMap<uint32_t, TextBlob*> fBlobIdCache;
|
||||||
|
SkTHashTable<TextBlob*, const TextBlob::Key&, TextBlob> fBlobKeyCache;
|
||||||
|
SkTInternalLList<TextBlob> fLRUList;
|
||||||
|
int fCacheSize;
|
||||||
|
|
||||||
typedef GrTextContext INHERITED;
|
typedef GrTextContext INHERITED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user