From 74b390d6b136a60f1df15ac5ecd19bd8ad5a394b Mon Sep 17 00:00:00 2001 From: Hal Canary Date: Wed, 6 Jun 2018 13:29:51 +0000 Subject: Revert "Have draw(Text|PosText|PosTextH) use a single entry on the device" This reverts commit 4225b3220ef4bf50f0d9403f812ea94d50c4ee59. Reason for revert: made valgrind unhappy. Original change's description: > Have draw(Text|PosText|PosTextH) use a single entry on the device > > Handle the positioning of drawText at the canvas layer. Simplify > the code by removing similar implementations. > > Change-Id: I8b711783435072f560e29fca1dd934fa2e345ed2 > Reviewed-on: https://skia-review.googlesource.com/127131 > Reviewed-by: Ben Wagner > Commit-Queue: Herb Derby TBR=jvanverth@google.com,bungeman@google.com,herb@google.com Change-Id: I65c9d30ae6ecb1f87e8660e56d8f8ce5daab7551 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://skia-review.googlesource.com/132403 Reviewed-by: Hal Canary Commit-Queue: Hal Canary --- src/gpu/GrRenderTargetContext.cpp | 14 +++ src/gpu/GrRenderTargetContext.h | 3 + src/gpu/SkGpuDevice.cpp | 11 ++ src/gpu/SkGpuDevice.h | 2 + src/gpu/text/GrTextContext.cpp | 227 +++++++++++++++++++++++++++++++++----- src/gpu/text/GrTextContext.h | 28 +++++ 6 files changed, 259 insertions(+), 26 deletions(-) (limited to 'src/gpu') diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index a79f9d113d..e5bda32354 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -217,6 +217,20 @@ GrOpList* GrRenderTargetContext::getOpList() { return this->getRTOpList(); } +void GrRenderTargetContext::drawText(const GrClip& clip, const SkPaint& skPaint, + const SkMatrix& viewMatrix, const char text[], + size_t byteLength, SkScalar x, SkScalar y, + const SkIRect& clipBounds) { + ASSERT_SINGLE_OWNER + RETURN_IF_ABANDONED + SkDEBUGCODE(this->validate();) + GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawText", fContext); + + GrTextContext* atlasTextContext = this->drawingManager()->getTextContext(); + atlasTextContext->drawText(fContext, fTextTarget.get(), clip, skPaint, viewMatrix, + fSurfaceProps, text, byteLength, x, y, clipBounds); +} + void GrRenderTargetContext::drawPosText(const GrClip& clip, const SkPaint& paint, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h index d605314385..acbf963c06 100644 --- a/src/gpu/GrRenderTargetContext.h +++ b/src/gpu/GrRenderTargetContext.h @@ -63,6 +63,9 @@ public: // we could use GrPaint except that // * SkPaint->GrPaint conversion depends upon whether the glyphs are color or grayscale and // this can vary within a text run. + virtual void drawText(const GrClip&, const SkPaint&, const SkMatrix& viewMatrix, + const char text[], size_t byteLength, SkScalar x, SkScalar y, + const SkIRect& clipBounds); virtual void drawPosText(const GrClip&, const SkPaint&, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset, diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 210cefc7a7..06307a1af2 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -1611,6 +1611,17 @@ void SkGpuDevice::drawAtlas(const SkImage* atlas, const SkRSXform xform[], /////////////////////////////////////////////////////////////////////////////// +void SkGpuDevice::drawText(const void* text, + size_t byteLength, SkScalar x, SkScalar y, + const SkPaint& paint) { + ASSERT_SINGLE_OWNER + GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawText", fContext.get()); + SkDEBUGCODE(this->validate();) + + fRenderTargetContext->drawText(this->clip(), paint, this->ctm(), (const char*)text, byteLength, + x, y, this->devClipBounds()); +} + void SkGpuDevice::drawPosText(const void* text, size_t byteLength, const SkScalar pos[], int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) { diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h index 7c7030e1ab..d98dbffe1d 100644 --- a/src/gpu/SkGpuDevice.h +++ b/src/gpu/SkGpuDevice.h @@ -87,6 +87,8 @@ public: const SkPaint& paint, SkCanvas::SrcRectConstraint) override; void drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& paint) override; + void drawText(const void* text, size_t len, SkScalar x, SkScalar y, + const SkPaint&) override; void drawPosText(const void* text, size_t len, const SkScalar pos[], int scalarsPerPos, const SkPoint& offset, const SkPaint&) override; void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y, diff --git a/src/gpu/text/GrTextContext.cpp b/src/gpu/text/GrTextContext.cpp index 72926fe280..f662fa9c12 100644 --- a/src/gpu/text/GrTextContext.cpp +++ b/src/gpu/text/GrTextContext.cpp @@ -17,7 +17,6 @@ #include "SkFindAndPlaceGlyph.h" #include "SkGr.h" #include "SkGraphics.h" -#include "SkGlyphRun.h" #include "SkMakeUnique.h" #include "SkMaskFilterBase.h" #include "SkPaintPriv.h" @@ -210,17 +209,11 @@ void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob, shaderCaps.supportsDistanceFieldText(), fOptions)) { switch (it.positioning()) { case SkTextBlob::kDefault_Positioning: { - auto origin = SkPoint::Make(x + offset.x(), y + offset.y()); - auto glyphRun = - SkGlyphRun::MakeFromDrawText(runPaint.skPaint(), - (const char*)it.glyphs(), textLen, origin); - - this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, - scalerContextFlags, viewMatrix, (const char*)it.glyphs(), - textLen, glyphRun.getPositions(), 2, SkPoint::Make(0,0)); + this->drawDFText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, + viewMatrix, (const char*)it.glyphs(), textLen, x + offset.x(), + y + offset.y()); break; } - case SkTextBlob::kHorizontal_Positioning: { SkPoint dfOffset = SkPoint::Make(x, y + offset.y()); this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, @@ -238,17 +231,11 @@ void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob, } } else { switch (it.positioning()) { - case SkTextBlob::kDefault_Positioning: { - auto origin = SkPoint::Make(x + offset.x(), y + offset.y()); - auto glyphRun = - SkGlyphRun::MakeFromDrawText( - runPaint.skPaint(), (const char*) it.glyphs(), textLen, origin); - - this->DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, - scalerContextFlags, viewMatrix, (const char*) it.glyphs(), - textLen, glyphRun.getPositions(), 2, SkPoint::Make(0, 0)); + case SkTextBlob::kDefault_Positioning: + DrawBmpText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, + viewMatrix, (const char*)it.glyphs(), textLen, x + offset.x(), + y + offset.y()); break; - } case SkTextBlob::kHorizontal_Positioning: DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1, @@ -264,6 +251,35 @@ void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob, } } +inline sk_sp +GrTextContext::makeDrawTextBlob(GrTextBlobCache* blobCache, + GrGlyphCache* glyphCache, + const GrShaderCaps& shaderCaps, + const GrTextUtils::Paint& paint, + SkScalerContextFlags scalerContextFlags, + const SkMatrix& viewMatrix, + const SkSurfaceProps& props, + const char text[], size_t byteLength, + SkScalar x, SkScalar y) const { + int glyphCount = paint.skPaint().countText(text, byteLength); + if (!glyphCount) { + return nullptr; + } + sk_sp blob = blobCache->makeBlob(glyphCount, 1); + blob->initThrowawayBlob(viewMatrix, x, y); + blob->setRunPaintFlags(0, paint.skPaint().getFlags()); + + if (CanDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps.supportsDistanceFieldText(), + fOptions)) { + this->drawDFText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, + text, byteLength, x, y); + } else { + DrawBmpText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, text, + byteLength, x, y); + } + return blob; +} + inline sk_sp GrTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache, GrGlyphCache* glyphCache, @@ -295,6 +311,29 @@ GrTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache, return blob; } +void GrTextContext::drawText(GrContext* context, GrTextUtils::Target* target, + const GrClip& clip, const SkPaint& skPaint, + const SkMatrix& viewMatrix, const SkSurfaceProps& props, + const char text[], size_t byteLength, SkScalar x, SkScalar y, + const SkIRect& regionClipBounds) { + if (context->contextPriv().abandoned()) { + return; + } + + auto glyphCache = context->contextPriv().getGlyphCache(); + auto textBlobCache = context->contextPriv().getTextBlobCache(); + + GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo()); + sk_sp blob(this->makeDrawTextBlob( + textBlobCache, glyphCache, *context->contextPriv().caps()->shaderCaps(), paint, + ComputeScalerContextFlags(target->colorSpaceInfo()), viewMatrix, props, text, + byteLength, x, y)); + if (blob) { + blob->flush(target, props, fDistanceAdjustTable.get(), paint, + clip, viewMatrix, regionClipBounds, x, y); + } +} + void GrTextContext::drawPosText(GrContext* context, GrTextUtils::Target* target, const GrClip& clip, const SkPaint& skPaint, const SkMatrix& viewMatrix, const SkSurfaceProps& props, @@ -319,6 +358,41 @@ void GrTextContext::drawPosText(GrContext* context, GrTextUtils::Target* target, } } +void GrTextContext::DrawBmpText(GrTextBlob* blob, int runIndex, + GrGlyphCache* glyphCache, const SkSurfaceProps& props, + const GrTextUtils::Paint& paint, + SkScalerContextFlags scalerContextFlags, + const SkMatrix& viewMatrix, const char text[], + size_t byteLength, SkScalar x, SkScalar y) { + SkASSERT(byteLength == 0 || text != nullptr); + + // nothing to draw + if (text == nullptr || byteLength == 0) { + return; + } + + // Ensure the blob is set for bitmaptext + blob->setHasBitmap(); + + if (SkDraw::ShouldDrawTextAsPaths(paint, viewMatrix)) { + DrawBmpTextAsPaths(blob, runIndex, glyphCache, props, paint, scalerContextFlags, viewMatrix, + text, byteLength, x, y); + return; + } + + sk_sp currStrike; + auto cache = blob->setupCache(runIndex, props, scalerContextFlags, paint, &viewMatrix); + SkFindAndPlaceGlyph::ProcessText(paint.skPaint().getTextEncoding(), text, byteLength, {x, y}, + viewMatrix, paint.skPaint().getTextAlign(), cache.get(), + [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { + position += rounding; + BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike, + glyph, SkScalarFloorToScalar(position.fX), + SkScalarFloorToScalar(position.fY), + paint.filteredPremulColor(), cache.get(), + SK_Scalar1, false); + }); +} void GrTextContext::DrawBmpPosText(GrTextBlob* blob, int runIndex, GrGlyphCache* glyphCache, const SkSurfaceProps& props, @@ -358,6 +432,43 @@ void GrTextContext::DrawBmpPosText(GrTextBlob* blob, int runIndex, }); } +void GrTextContext::DrawBmpTextAsPaths(GrTextBlob* blob, int runIndex, + GrGlyphCache* glyphCache, + const SkSurfaceProps& props, + const GrTextUtils::Paint& origPaint, + SkScalerContextFlags scalerContextFlags, + const SkMatrix& viewMatrix, const char text[], + size_t byteLength, SkScalar x, SkScalar y) { + // nothing to draw + if (text == nullptr || byteLength == 0) { + return; + } + + // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. + SkPaint pathPaint(origPaint); + pathPaint.setStyle(SkPaint::kFill_Style); + pathPaint.setPathEffect(nullptr); + + GrTextUtils::PathTextIter iter(text, byteLength, pathPaint, true); + FallbackTextHelper fallbackTextHelper(viewMatrix, pathPaint, glyphCache, iter.getPathScale()); + + const SkGlyph* iterGlyph; + const SkPath* iterPath; + SkScalar xpos = 0; + const char* lastText = text; + while (iter.next(&iterGlyph, &iterPath, &xpos)) { + if (iterGlyph) { + SkPoint pos = SkPoint::Make(xpos + x, y); + fallbackTextHelper.appendText(*iterGlyph, iter.getText() - lastText, lastText, pos); + } else if (iterPath) { + blob->appendPathGlyph(runIndex, *iterPath, xpos + x, y, iter.getPathScale(), false); + } + lastText = iter.getText(); + } + + fallbackTextHelper.drawText(blob, runIndex, glyphCache, props, origPaint, scalerContextFlags); +} + void GrTextContext::DrawBmpPosTextAsPaths(GrTextBlob* blob, int runIndex, GrGlyphCache* glyphCache, const SkSurfaceProps& props, @@ -567,6 +678,74 @@ void GrTextContext::InitDistanceFieldPaint(GrTextBlob* blob, *flags = SkScalerContextFlags::kNone; } +void GrTextContext::drawDFText(GrTextBlob* blob, int runIndex, + GrGlyphCache* glyphCache, const SkSurfaceProps& props, + const GrTextUtils::Paint& paint, + SkScalerContextFlags scalerContextFlags, + const SkMatrix& viewMatrix, const char text[], + size_t byteLength, SkScalar x, SkScalar y) const { + SkASSERT(byteLength == 0 || text != nullptr); + + // nothing to draw + if (text == nullptr || byteLength == 0) { + return; + } + + const SkPaint& skPaint = paint.skPaint(); + SkPaint::GlyphCacheProc glyphCacheProc = + SkPaint::GetGlyphCacheProc(skPaint.getTextEncoding(), true); + + SkTArray positions; + + const char* textPtr = text; + SkScalar stopX = 0; + SkScalar stopY = 0; + + SkAutoDescriptor desc; + SkScalerContextEffects effects; + // We apply the fake-gamma by altering the distance in the shader, so we ignore the + // passed-in scaler context flags. (It's only used when we fall-back to bitmap text). + SkScalerContext::CreateDescriptorAndEffectsUsingPaint( + skPaint, &props, SkScalerContextFlags::kNone, nullptr, &desc, &effects); + auto typeface = SkPaintPriv::GetTypefaceOrDefault(skPaint); + + { + auto origPaintCache = + SkStrikeCache::FindOrCreateStrikeExclusive(*desc.getDesc(), effects, *typeface); + + const char* stop = text + byteLength; + while (textPtr < stop) { + // don't need x, y here, since all subpixel variants will have the + // same advance + const SkGlyph& glyph = glyphCacheProc(origPaintCache.get(), &textPtr); + + positions.push_back(stopX); + positions.push_back(stopY); + + stopX += SkFloatToScalar(glyph.fAdvanceX); + stopY += SkFloatToScalar(glyph.fAdvanceY); + } + SkASSERT(textPtr == stop); + } + + // now adjust starting point depending on alignment + SkScalar alignX = stopX; + SkScalar alignY = stopY; + if (skPaint.getTextAlign() == SkPaint::kCenter_Align) { + alignX = SkScalarHalf(alignX); + alignY = SkScalarHalf(alignY); + } else if (skPaint.getTextAlign() == SkPaint::kLeft_Align) { + alignX = 0; + alignY = 0; + } + x -= alignX; + y -= alignY; + SkPoint offset = SkPoint::Make(x, y); + + this->drawDFPosText(blob, runIndex, glyphCache, props, paint, scalerContextFlags, + viewMatrix, text, byteLength, positions.begin(), 2, offset); +} + void GrTextContext::drawDFPosText(GrTextBlob* blob, int runIndex, GrGlyphCache* glyphCache, const SkSurfaceProps& props, const GrTextUtils::Paint& paint, @@ -757,15 +936,11 @@ std::unique_ptr GrTextContext::createOp_TestingOnly(GrContext* context // right now we don't handle textblobs, nor do we handle drawPosText. Since we only intend to // test the text op with this unit test, that is okay. - - auto origin = SkPoint::Make(x, y); - auto glyphRun = SkGlyphRun::MakeFromDrawText(skPaint, text, textLen, origin); - - sk_sp blob(textContext->makeDrawPosTextBlob( + sk_sp blob(textContext->makeDrawTextBlob( context->contextPriv().getTextBlobCache(), glyphCache, *context->contextPriv().caps()->shaderCaps(), utilsPaint, GrTextContext::kTextBlobOpScalerContextFlags, viewMatrix, surfaceProps, text, - static_cast(textLen), glyphRun.getPositions(), 2, origin)); + static_cast(textLen), SkIntToScalar(x), SkIntToScalar(y))); return blob->test_makeOp(textLen, 0, 0, viewMatrix, x, y, utilsPaint, surfaceProps, textContext->dfAdjustTable(), rtc->textTarget()); diff --git a/src/gpu/text/GrTextContext.h b/src/gpu/text/GrTextContext.h index 7d31d84a05..3dab70ba9b 100644 --- a/src/gpu/text/GrTextContext.h +++ b/src/gpu/text/GrTextContext.h @@ -44,6 +44,9 @@ public: static std::unique_ptr Make(const Options& options); + void drawText(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&, + const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[], + size_t byteLength, SkScalar x, SkScalar y, const SkIRect& regionClipBounds); void drawPosText(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&, const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, @@ -120,6 +123,15 @@ private: static bool HasLCD(const SkTextBlob*); + sk_sp makeDrawTextBlob(GrTextBlobCache*, GrGlyphCache*, + const GrShaderCaps&, + const GrTextUtils::Paint&, + SkScalerContextFlags scalerContextFlags, + const SkMatrix& viewMatrix, + const SkSurfaceProps&, + const char text[], size_t byteLength, + SkScalar x, SkScalar y) const; + sk_sp makeDrawPosTextBlob(GrTextBlobCache*, GrGlyphCache*, const GrShaderCaps&, const GrTextUtils::Paint&, @@ -132,12 +144,23 @@ private: const SkPoint& offset) const; // Functions for appending BMP text to GrTextBlob + static void DrawBmpText(GrTextBlob*, int runIndex, GrGlyphCache*, + const SkSurfaceProps&, const GrTextUtils::Paint& paint, + SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, + const char text[], size_t byteLength, SkScalar x, SkScalar y); + static void DrawBmpPosText(GrTextBlob*, int runIndex, GrGlyphCache*, const SkSurfaceProps&, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset); + static void DrawBmpTextAsPaths(GrTextBlob*, int runIndex, GrGlyphCache*, + const SkSurfaceProps&, const GrTextUtils::Paint& paint, + SkScalerContextFlags scalerContextFlags, + const SkMatrix& viewMatrix, const char text[], + size_t byteLength, SkScalar x, SkScalar y); + static void DrawBmpPosTextAsPaths(GrTextBlob*, int runIndex, GrGlyphCache*, const SkSurfaceProps&, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, @@ -147,6 +170,11 @@ private: const SkPoint& offset); // functions for appending distance field text + void drawDFText(GrTextBlob* blob, int runIndex, GrGlyphCache*, const SkSurfaceProps&, + const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, + const SkMatrix& viewMatrix, const char text[], size_t byteLength, SkScalar x, + SkScalar y) const; + void drawDFPosText(GrTextBlob* blob, int runIndex, GrGlyphCache*, const SkSurfaceProps&, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, -- cgit v1.2.3