| Index: src/gpu/text/GrStencilAndCoverTextContext.cpp
|
| diff --git a/src/gpu/text/GrStencilAndCoverTextContext.cpp b/src/gpu/text/GrStencilAndCoverTextContext.cpp
|
| index d28f1a803a0abe7df26843e7848fd21821d8b4f5..2fbaec8f326b196c26567bea94a7dafc31790891 100644
|
| --- a/src/gpu/text/GrStencilAndCoverTextContext.cpp
|
| +++ b/src/gpu/text/GrStencilAndCoverTextContext.cpp
|
| @@ -12,12 +12,14 @@
|
| #include "GrPath.h"
|
| #include "GrPathRange.h"
|
| #include "GrResourceProvider.h"
|
| +#include "GrTextUtils.h"
|
| #include "SkAutoKern.h"
|
| #include "SkDraw.h"
|
| #include "SkDrawProcs.h"
|
| #include "SkGlyphCache.h"
|
| #include "SkGpuDevice.h"
|
| #include "SkGrPriv.h"
|
| +#include "SkDrawFilter.h"
|
| #include "SkPath.h"
|
| #include "SkTextBlobRunIterator.h"
|
| #include "SkTextMapStateProc.h"
|
| @@ -37,8 +39,9 @@ template<typename T> static void delete_hash_table_entry(T* val) {
|
|
|
| GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context,
|
| const SkSurfaceProps& surfaceProps)
|
| - : INHERITED(context, surfaceProps),
|
| - fCacheSize(0) {
|
| + : INHERITED(context, surfaceProps)
|
| + , fFallbackTextContext(nullptr)
|
| + , fCacheSize(0) {
|
| }
|
|
|
| GrStencilAndCoverTextContext*
|
| @@ -51,6 +54,7 @@ GrStencilAndCoverTextContext::Create(GrContext* context, const SkSurfaceProps& s
|
| }
|
|
|
| GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() {
|
| + delete fFallbackTextContext;
|
| fBlobIdCache.foreach(delete_hash_map_entry<uint32_t, TextBlob*>);
|
| fBlobKeyCache.foreach(delete_hash_table_entry<TextBlob*>);
|
| }
|
| @@ -71,38 +75,115 @@ bool GrStencilAndCoverTextContext::internalCanDraw(const SkPaint& skPaint) {
|
| return SkPaint::kStroke_Style != skPaint.getStyle() || 0 != skPaint.getStrokeWidth();
|
| }
|
|
|
| -void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc,
|
| - const GrClip& clip,
|
| - const GrPaint& paint,
|
| - const SkPaint& skPaint,
|
| - const SkMatrix& viewMatrix,
|
| - const char text[],
|
| - size_t byteLength,
|
| - SkScalar x, SkScalar y,
|
| - const SkIRect& clipBounds) {
|
| - TextRun run(skPaint);
|
| - GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip);
|
| - run.setText(text, byteLength, x, y);
|
| - run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBounds,
|
| - fFallbackTextContext, skPaint);
|
| +void GrStencilAndCoverTextContext::drawText(GrDrawContext* dc,
|
| + const GrClip& clip, const GrPaint& paint,
|
| + const SkPaint& skPaint, const SkMatrix& viewMatrix,
|
| + const char text[], size_t byteLength,
|
| + SkScalar x, SkScalar y, const SkIRect& clipBounds) {
|
| + if (fContext->abandoned()) {
|
| + return;
|
| + } else if (this->canDraw(skPaint, viewMatrix)) {
|
| + TextRun run(skPaint);
|
| + GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip);
|
| + run.setText(text, byteLength, x, y);
|
| + run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBounds,
|
| + fFallbackTextContext, skPaint);
|
| + return;
|
| + } else if (fFallbackTextContext->canDraw(skPaint, viewMatrix)) {
|
| + fFallbackTextContext->drawText(dc, clip, paint, skPaint, viewMatrix, text,
|
| + byteLength, x, y, clipBounds);
|
| + return;
|
| + }
|
| +
|
| + // fall back to drawing as a path
|
| + GrTextUtils::DrawTextAsPath(fContext, dc, clip, skPaint, viewMatrix, text, byteLength, x, y,
|
| + clipBounds);
|
| }
|
|
|
| -void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc,
|
| - 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 SkIRect& clipBounds) {
|
| - TextRun run(skPaint);
|
| - GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip);
|
| - run.setPosText(text, byteLength, pos, scalarsPerPosition, offset);
|
| - run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBounds,
|
| - fFallbackTextContext, skPaint);
|
| +void GrStencilAndCoverTextContext::drawPosText(GrDrawContext* dc,
|
| + 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 SkIRect& clipBounds) {
|
| + if (fContext->abandoned()) {
|
| + return;
|
| + } else if (this->canDraw(skPaint, viewMatrix)) {
|
| + TextRun run(skPaint);
|
| + GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip);
|
| + run.setPosText(text, byteLength, pos, scalarsPerPosition, offset);
|
| + run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBounds,
|
| + fFallbackTextContext, skPaint);
|
| + return;
|
| + } else if (fFallbackTextContext->canDraw(skPaint, viewMatrix)) {
|
| + fFallbackTextContext->drawPosText(dc, clip, paint, skPaint, viewMatrix,
|
| + text, byteLength, pos,
|
| + scalarsPerPosition, offset, clipBounds);
|
| + return;
|
| + }
|
| +
|
| + // fall back to drawing as a path
|
| + GrTextUtils::DrawPosTextAsPath(fContext, dc, fSurfaceProps, clip, skPaint, viewMatrix, text,
|
| + byteLength, pos, scalarsPerPosition, offset, clipBounds);
|
| +}
|
| +
|
| +void GrStencilAndCoverTextContext::uncachedDrawTextBlob(GrDrawContext* dc,
|
| + const GrClip& clip, const SkPaint& skPaint,
|
| + const SkMatrix& viewMatrix,
|
| + const SkTextBlob* blob,
|
| + SkScalar x, SkScalar y,
|
| + SkDrawFilter* drawFilter,
|
| + const SkIRect& clipBounds) {
|
| + SkPaint runPaint = skPaint;
|
| +
|
| + SkTextBlobRunIterator it(blob);
|
| + for (;!it.done(); it.next()) {
|
| + size_t textLen = it.glyphCount() * sizeof(uint16_t);
|
| + const SkPoint& offset = it.offset();
|
| +
|
| + // applyFontToPaint() always overwrites the exact same attributes,
|
| + // so it is safe to not re-seed the paint for this reason.
|
| + it.applyFontToPaint(&runPaint);
|
| +
|
| + if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) {
|
| + // A false return from filter() means we should abort the current draw.
|
| + runPaint = skPaint;
|
| + continue;
|
| + }
|
| +
|
| + runPaint.setFlags(FilterTextFlags(fSurfaceProps, runPaint));
|
| +
|
| + GrPaint grPaint;
|
| + if (!SkPaintToGrPaint(fContext, runPaint, viewMatrix, &grPaint)) {
|
| + return;
|
| + }
|
| +
|
| + switch (it.positioning()) {
|
| + case SkTextBlob::kDefault_Positioning:
|
| + this->drawText(dc, clip, grPaint, runPaint, viewMatrix, (const char *)it.glyphs(),
|
| + textLen, x + offset.x(), y + offset.y(), clipBounds);
|
| + break;
|
| + case SkTextBlob::kHorizontal_Positioning:
|
| + this->drawPosText(dc, clip, grPaint, runPaint, viewMatrix, (const char*)it.glyphs(),
|
| + textLen, it.pos(), 1, SkPoint::Make(x, y + offset.y()),
|
| + clipBounds);
|
| + break;
|
| + case SkTextBlob::kFull_Positioning:
|
| + this->drawPosText(dc, clip, grPaint, runPaint, viewMatrix, (const char*)it.glyphs(),
|
| + textLen, it.pos(), 2, SkPoint::Make(x, y), clipBounds);
|
| + break;
|
| + }
|
| +
|
| + if (drawFilter) {
|
| + // A draw filter may change the paint arbitrarily, so we must re-seed in this case.
|
| + runPaint = skPaint;
|
| + }
|
| + }
|
| }
|
|
|
| void GrStencilAndCoverTextContext::drawTextBlob(GrDrawContext* dc,
|
| @@ -111,6 +192,10 @@ void GrStencilAndCoverTextContext::drawTextBlob(GrDrawContext* dc,
|
| const SkTextBlob* skBlob, SkScalar x, SkScalar y,
|
| SkDrawFilter* drawFilter,
|
| const SkIRect& clipBounds) {
|
| + if (fContext->abandoned()) {
|
| + return;
|
| + }
|
| +
|
| if (!this->internalCanDraw(skPaint)) {
|
| fFallbackTextContext->drawTextBlob(dc, clip, skPaint, viewMatrix, skBlob, x, y,
|
| drawFilter, clipBounds);
|
| @@ -119,12 +204,8 @@ void GrStencilAndCoverTextContext::drawTextBlob(GrDrawContext* dc,
|
|
|
| if (drawFilter || skPaint.getPathEffect()) {
|
| // This draw can't be cached.
|
| - INHERITED::drawTextBlob(dc, clip, skPaint, viewMatrix, skBlob, x, y, drawFilter,
|
| - clipBounds);
|
| - return;
|
| - }
|
| -
|
| - if (fContext->abandoned()) {
|
| + this->uncachedDrawTextBlob(dc, clip, skPaint, viewMatrix, skBlob, x, y, drawFilter,
|
| + clipBounds);
|
| return;
|
| }
|
|
|
|
|