diff options
author | Herb Derby <herb@google.com> | 2018-07-12 15:30:35 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-07-13 03:21:54 +0000 |
commit | 8a6348e6d2ef095358cfc7d29d2a50d684cc719e (patch) | |
tree | 0554d2811a9550190ebca43f847b1c48e987f8cc /src | |
parent | 1c5fd18927d5a128a12d7d5fe27f08d898be1e5b (diff) |
Introduce text blob processing but don't wire it up
Have all the old code paths start using lists in preparation
for introducing text blobs.
Change-Id: I65cc02ee3da63bc3c9492db78a08b0eee3b1f931
Reviewed-on: https://skia-review.googlesource.com/141081
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Herb Derby <herb@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkCanvas.cpp | 12 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 11 | ||||
-rw-r--r-- | src/core/SkDevice.h | 4 | ||||
-rw-r--r-- | src/core/SkGlyphRun.cpp | 141 | ||||
-rw-r--r-- | src/core/SkGlyphRun.h | 76 | ||||
-rw-r--r-- | src/gpu/text/GrTextContext.cpp | 37 |
6 files changed, 220 insertions, 61 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 367105ddda..3c5ec347c7 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -2431,8 +2431,8 @@ void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkSca while (iter.next()) { fScratchGlyphRunBuilder->drawText( looper.paint(), text, byteLength, SkPoint::Make(x, y)); - auto glyphRun = fScratchGlyphRunBuilder->useGlyphRun(); - iter.fDevice->drawGlyphRun(looper.paint(), glyphRun); + auto glyphRunList = fScratchGlyphRunBuilder->useGlyphRunList(); + iter.fDevice->drawGlyphRunList(looper.paint(), glyphRunList); } LOOPER_END @@ -2445,8 +2445,8 @@ void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint while (iter.next()) { fScratchGlyphRunBuilder->drawPosText(looper.paint(), text, byteLength, pos); - auto glyphRun = fScratchGlyphRunBuilder->useGlyphRun(); - iter.fDevice->drawGlyphRun(looper.paint(), glyphRun); + auto glyphRunList = fScratchGlyphRunBuilder->useGlyphRunList(); + iter.fDevice->drawGlyphRunList(looper.paint(), glyphRunList); } LOOPER_END @@ -2460,8 +2460,8 @@ void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScala while (iter.next()) { fScratchGlyphRunBuilder->drawPosTextH( looper.paint(), text, byteLength, xpos, constY); - const auto& glyphRun = fScratchGlyphRunBuilder->useGlyphRun(); - iter.fDevice->drawGlyphRun(looper.paint(), glyphRun); + auto glyphRunList = fScratchGlyphRunBuilder->useGlyphRunList(); + iter.fDevice->drawGlyphRunList(looper.paint(), glyphRunList); } LOOPER_END diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 5ca8f5ec5e..a4482a19ec 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -157,8 +157,8 @@ void SkBaseDevice::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, auto origin = SkPoint::Make(x + offset.x(), y + offset.y()); SkGlyphRunBuilder builder; builder.drawText(runPaint, (const char*) it.glyphs(), textLen, origin); - auto glyphRun = builder.useGlyphRun(); - glyphRun->temporaryShuntToDrawPosText(this); + auto glyphRunList = builder.useGlyphRunList(); + glyphRunList->temporaryShuntToDrawPosText(this); } break; case SkTextBlob::kHorizontal_Positioning: @@ -239,11 +239,8 @@ void SkBaseDevice::drawImageLattice(const SkImage* image, } } -void SkBaseDevice::drawGlyphRun(const SkPaint& paint, SkGlyphRun* glyphRun) { - SkPaint glyphPaint(paint); - glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); - - glyphRun->temporaryShuntToDrawPosText(this); +void SkBaseDevice::drawGlyphRunList(const SkPaint& paint, SkGlyphRunList* glyphRunList) { + glyphRunList->temporaryShuntToDrawPosText(this); } void SkBaseDevice::drawBitmapLattice(const SkBitmap& bitmap, diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h index 2173d91023..2a33822b1e 100644 --- a/src/core/SkDevice.h +++ b/src/core/SkDevice.h @@ -16,7 +16,7 @@ class SkBitmap; struct SkDrawShadowRec; -class SkGlyphRun; +class SkGlyphRunList; class SkGlyphRunBuilder; class SkImageFilterCache; struct SkIRect; @@ -222,7 +222,7 @@ protected: * Does not handle text decoration. * Decorations (underline and stike-thru) will be handled by SkCanvas. */ - virtual void drawGlyphRun(const SkPaint& paint, SkGlyphRun* glyphRun); + virtual void drawGlyphRunList(const SkPaint& paint, SkGlyphRunList* glyphRunList); virtual void drawVertices(const SkVertices*, const SkMatrix* bones, int boneCount, SkBlendMode, const SkPaint&) = 0; virtual void drawShadow(const SkPath&, const SkDrawShadowRec&); diff --git a/src/core/SkGlyphRun.cpp b/src/core/SkGlyphRun.cpp index 781263c103..6cb458544f 100644 --- a/src/core/SkGlyphRun.cpp +++ b/src/core/SkGlyphRun.cpp @@ -69,6 +69,36 @@ void SkGlyphRun::temporaryShuntToCallback(TemporaryShuntCallback callback) { callback(fTemporaryShuntGlyphIDs.size(), bytes, pos); } +// -- SkGlyphRunList ------------------------------------------------------------------------------- +SkGlyphRunList::SkGlyphRunList( + const SkPaint& paint, + const SkTextBlob* blob, + SkPoint origin, + SkSpan<SkGlyphRun> glyphRunList) + : fOriginalPaint{&paint} + , fOriginalTextBlob{blob} + , fOrigin{origin} + , fGlyphRuns{glyphRunList} { } + +uint64_t SkGlyphRunList::uniqueID() const { + return fOriginalTextBlob != nullptr ? fOriginalTextBlob->uniqueID() + : SK_InvalidUniqueID; +} + +bool SkGlyphRunList::anyRunsLCD() const { + for (const auto& r : fGlyphRuns) { + if (r.paint().isLCDRenderText()) { + return true; + } + } + return false; +} + +void SkGlyphRunList::temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const { + SkASSERT(fOriginalTextBlob != nullptr); + fOriginalTextBlob->notifyAddedToCache(cacheID); +} + // -- SkGlyphIDSet --------------------------------------------------------------------------------- // A faster set implementation that does not need any initialization, and reading the set items // is order the number of items, and not the size of the universe. @@ -140,6 +170,8 @@ void SkGlyphRunBuilder::drawText( this->simplifyDrawText( paint, glyphIDs, origin, fUniqueGlyphIDIndices, fUniqueGlyphIDs, fPositions); } + + this->makeGlyphRunList(paint, nullptr, SkPoint::Make(0, 0)); } void SkGlyphRunBuilder::drawPosTextH(const SkPaint& paint, const void* bytes, @@ -151,6 +183,8 @@ void SkGlyphRunBuilder::drawPosTextH(const SkPaint& paint, const void* bytes, this->simplifyDrawPosTextH( paint, glyphIDs, xpos, constY, fUniqueGlyphIDIndices, fUniqueGlyphIDs, fPositions); } + + this->makeGlyphRunList(paint, nullptr, SkPoint::Make(0, 0)); } void SkGlyphRunBuilder::drawPosText(const SkPaint& paint, const void* bytes, @@ -158,17 +192,82 @@ void SkGlyphRunBuilder::drawPosText(const SkPaint& paint, const void* bytes, auto glyphIDs = textToGlyphIDs(paint, bytes, byteLength); if (!glyphIDs.empty()) { this->initialize(glyphIDs.size()); - this->simplifyDrawPosText( - paint, glyphIDs, pos, fUniqueGlyphIDIndices, fUniqueGlyphIDs); + this->simplifyDrawPosText(paint, glyphIDs, pos, fUniqueGlyphIDIndices, fUniqueGlyphIDs); } + + this->makeGlyphRunList(paint, nullptr, SkPoint::Make(0, 0)); } -SkGlyphRun* SkGlyphRunBuilder::useGlyphRun() { - return &fScratchGlyphRun; +void SkGlyphRunBuilder::drawTextBlob(const SkPaint& paint, const SkTextBlob& blob, SkPoint origin) { + SkPaint runPaint = paint; + + // Figure out all the storage needed to pre-size everything below. + size_t totalGlyphs = 0; + for (SkTextBlobRunIterator it(&blob); !it.done(); it.next()) { + totalGlyphs += it.glyphCount(); + } + + // Pre-size all the buffers so they don't move during processing. + this->initialize(totalGlyphs); + + uint16_t* currentDenseIndices = fUniqueGlyphIDIndices; + SkPoint* currentPositions = fPositions; + SkGlyphID* currentUniqueGlyphIDs = fUniqueGlyphIDs; + + for (SkTextBlobRunIterator it(&blob); !it.done(); it.next()) { + // applyFontToPaint() always overwrites the exact same attributes, + // so it is safe to not re-seed the paint for this reason. + it.applyFontToPaint(&runPaint); + size_t runSize = it.glyphCount(); + + // These better be glyphs + SkASSERT(runPaint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); + + auto text = SkSpan<const char>(it.text(), it.textSize()); + auto clusters = SkSpan<const uint32_t>(it.clusters(), runSize); + const SkPoint& offset = it.offset(); + auto glyphIDs = SkSpan<const SkGlyphID>{it.glyphs(), runSize}; + + size_t uniqueGlyphIDsSize = 0; + switch (it.positioning()) { + case SkTextBlob::kDefault_Positioning: { + uniqueGlyphIDsSize = this->simplifyDrawText( + runPaint, glyphIDs, offset, + currentDenseIndices, currentUniqueGlyphIDs, currentPositions, + text, clusters); + } + break; + case SkTextBlob::kHorizontal_Positioning: { + auto constY = offset.y(); + uniqueGlyphIDsSize = this->simplifyDrawPosTextH( + runPaint, glyphIDs, it.pos(), constY, + currentDenseIndices, currentUniqueGlyphIDs, currentPositions, + text, clusters); + } + break; + case SkTextBlob::kFull_Positioning: + uniqueGlyphIDsSize = this->simplifyDrawPosText( + runPaint, glyphIDs, (const SkPoint*)it.pos(), + currentDenseIndices, currentUniqueGlyphIDs, + text, clusters); + break; + default: + SK_ABORT("unhandled positioning mode"); + } + + currentDenseIndices += runSize; + currentPositions += runSize; + currentUniqueGlyphIDs += uniqueGlyphIDsSize; + } + + this->makeGlyphRunList(paint, &blob, origin); +} + +SkGlyphRunList* SkGlyphRunBuilder::useGlyphRunList() { + return &fGlyphRunList; } void SkGlyphRunBuilder::initialize(size_t totalRunSize) { - fUniqueID = 0; if (totalRunSize > fMaxTotalRunSize) { fMaxTotalRunSize = totalRunSize; @@ -177,8 +276,7 @@ void SkGlyphRunBuilder::initialize(size_t totalRunSize) { fUniqueGlyphIDs.reset(fMaxTotalRunSize); } - // Be sure to clean up the last run before we reuse it. - fScratchGlyphRun.~SkGlyphRun(); + fGlyphRunListStorage.clear(); } SkSpan<const SkGlyphID> SkGlyphRunBuilder::textToGlyphIDs( @@ -236,25 +334,31 @@ void SkGlyphRunBuilder::makeGlyphRun( glyphRunPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); glyphRunPaint.setTextAlign(SkPaint::kLeft_Align); - new ((void*)&fScratchGlyphRun) SkGlyphRun{ + fGlyphRunListStorage.emplace_back( std::move(glyphRunPaint), uniqueGlyphIDIndices, positions, glyphIDs, uniqueGlyphIDs, text, - clusters - }; + clusters); } } -void SkGlyphRunBuilder::simplifyDrawText( +void SkGlyphRunBuilder::makeGlyphRunList( + const SkPaint& paint, const SkTextBlob* blob, SkPoint origin) { + + fGlyphRunList.~SkGlyphRunList(); + new (&fGlyphRunList) SkGlyphRunList{ + paint, blob, origin, SkSpan<SkGlyphRun>{fGlyphRunListStorage}}; +} + +size_t SkGlyphRunBuilder::simplifyDrawText( const SkPaint& paint, SkSpan<const SkGlyphID> glyphIDs, SkPoint origin, uint16_t* uniqueGlyphIDIndicesBuffer, SkGlyphID* uniqueGlyphIDsBuffer, SkPoint* positions, SkSpan<const char> text, SkSpan<const uint32_t> clusters) { SkASSERT(!glyphIDs.empty()); - auto runSize = glyphIDs.size(); auto unqiueGlyphIDs = this->addDenseAndUnique( @@ -271,7 +375,7 @@ void SkGlyphRunBuilder::simplifyDrawText( for (size_t i = 0; i < runSize; i++) { positions[i] = endOfLastGlyph; - endOfLastGlyph += fScratchAdvances[fUniqueGlyphIDIndices[i]]; + endOfLastGlyph += fScratchAdvances[uniqueGlyphIDIndicesBuffer[i]]; } if (paint.getTextAlign() != SkPaint::kLeft_Align) { @@ -289,14 +393,16 @@ void SkGlyphRunBuilder::simplifyDrawText( paint, glyphIDs, SkSpan<const SkPoint>{positions, runSize}, - SkSpan<const uint16_t>{fUniqueGlyphIDIndices, runSize}, + SkSpan<const uint16_t>{uniqueGlyphIDIndicesBuffer, runSize}, unqiueGlyphIDs, text, clusters); } + + return unqiueGlyphIDs.size(); } -void SkGlyphRunBuilder::simplifyDrawPosTextH( +size_t SkGlyphRunBuilder::simplifyDrawPosTextH( const SkPaint& paint, SkSpan<const SkGlyphID> glyphIDs, const SkScalar* xpos, SkScalar constY, uint16_t* uniqueGlyphIDIndicesBuffer, SkGlyphID* uniqueGlyphIDsBuffer, SkPoint* positions, @@ -307,13 +413,13 @@ void SkGlyphRunBuilder::simplifyDrawPosTextH( *posCursor++ = SkPoint::Make(x, constY); } - this->simplifyDrawPosText( + return this->simplifyDrawPosText( paint, glyphIDs, positions, uniqueGlyphIDIndicesBuffer, uniqueGlyphIDsBuffer, text, clusters); } -void SkGlyphRunBuilder::simplifyDrawPosText( +size_t SkGlyphRunBuilder::simplifyDrawPosText( const SkPaint& paint, SkSpan<const SkGlyphID> glyphIDs, const SkPoint* pos, uint16_t* uniqueGlyphIDIndicesBuffer, SkGlyphID* uniqueGlyphIDsBuffer, SkSpan<const char> text, SkSpan<const uint32_t> clusters) { @@ -336,6 +442,7 @@ void SkGlyphRunBuilder::simplifyDrawPosText( uniqueGlyphIDs, text, clusters); + return 0; } diff --git a/src/core/SkGlyphRun.h b/src/core/SkGlyphRun.h index a1124fd58e..4b392fda0f 100644 --- a/src/core/SkGlyphRun.h +++ b/src/core/SkGlyphRun.h @@ -61,10 +61,8 @@ public: void temporaryShuntToCallback(TemporaryShuntCallback callback); size_t runSize() const { return fUniqueGlyphIDIndices.size(); } - uint16_t uniqueSize() const { return fUniqueGlyphIDs.size(); } SkSpan<const SkPoint> positions() const { return fPositions; } - SkSpan<const SkGlyphID> uniqueGlyphIDs() const { return fUniqueGlyphIDs; } - SkSpan<const SkGlyphID> shuntGlyphsIDs() const { return fTemporaryShuntGlyphIDs; } + const SkPaint& paint() const { return fRunPaint; } private: // @@ -83,6 +81,53 @@ private: const SkPaint fRunPaint; }; +class SkGlyphRunList { + const SkPaint* fOriginalPaint{nullptr}; + // The text blob is needed to hookup the call back that the SkTextBlob destructor calls. It + // should be used for nothing else + const SkTextBlob* fOriginalTextBlob{nullptr}; + SkPoint fOrigin = {0, 0}; + SkSpan<SkGlyphRun> fGlyphRuns; + +public: + SkGlyphRunList() = default; + // Blob maybe null. + SkGlyphRunList( + const SkPaint& paint, + const SkTextBlob* blob, + SkPoint origin, + SkSpan<SkGlyphRun> glyphRunList); + + uint64_t uniqueID() const; + bool anyRunsLCD() const; + void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const; + + bool canCache() const { return fOriginalTextBlob != nullptr; } + size_t runCount() const { return fGlyphRuns.size(); } + size_t totalGlyphCount() const { + size_t glyphCount = 0; + for(const auto& run : fGlyphRuns) { + glyphCount += run.runSize(); + } + return glyphCount; + } + + SkPoint origin() const { return fOrigin; } + const SkPaint& paint() const { return *fOriginalPaint; } + + auto begin() -> decltype(fGlyphRuns.begin()) { return fGlyphRuns.begin(); } + auto end() -> decltype(fGlyphRuns.end()) { return fGlyphRuns.end(); } + auto size() -> decltype(fGlyphRuns.size()) { return fGlyphRuns.size(); } + auto empty() -> decltype(fGlyphRuns.empty()) { return fGlyphRuns.empty(); } + auto operator [] (size_t i) -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i]; } + void temporaryShuntToDrawPosText(SkBaseDevice* device) { + for (auto& run : fGlyphRuns) { + run.temporaryShuntToDrawPosText(device); + } + } + +}; + class SkGlyphIDSet { public: SkSpan<const SkGlyphID> uniquifyGlyphIDs( @@ -96,16 +141,16 @@ private: class SkGlyphRunBuilder { public: void drawText( - const SkPaint& paint, const void* bytes, size_t byteLength, - SkPoint origin); + const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin); void drawPosTextH( const SkPaint& paint, const void* bytes, size_t byteLength, const SkScalar* xpos, SkScalar constY); void drawPosText( - const SkPaint& paint, const void* bytes, size_t byteLength, - const SkPoint* pos); + const SkPaint& paint, const void* bytes, size_t byteLength, const SkPoint* pos); + void drawTextBlob(const SkPaint& paint, const SkTextBlob& blob, SkPoint origin); SkGlyphRun* useGlyphRun(); + SkGlyphRunList* useGlyphRunList(); private: void initialize(size_t totalRunSize); @@ -128,30 +173,35 @@ private: SkSpan<const char> text, SkSpan<const uint32_t> clusters); - void simplifyDrawText( + void makeGlyphRunList(const SkPaint& paint, const SkTextBlob* blob, SkPoint origin); + + size_t simplifyDrawText( const SkPaint& paint, SkSpan<const SkGlyphID> glyphIDs, SkPoint origin, uint16_t* uniqueGlyphIDIndices, SkGlyphID* uniqueGlyphIDs, SkPoint* positions, SkSpan<const char> text = SkSpan<const char>{}, SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{}); - void simplifyDrawPosTextH( + size_t simplifyDrawPosTextH( const SkPaint& paint, SkSpan<const SkGlyphID> glyphIDs, const SkScalar* xpos, SkScalar constY, uint16_t* uniqueGlyphIDIndices, SkGlyphID* uniqueGlyphIDs, SkPoint* positions, SkSpan<const char> text = SkSpan<const char>{}, SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{}); - void simplifyDrawPosText( + size_t simplifyDrawPosText( const SkPaint& paint, SkSpan<const SkGlyphID> glyphIDs, const SkPoint* pos, uint16_t* uniqueGlyphIDIndices, SkGlyphID* uniqueGlyphIDs, SkSpan<const char> text = SkSpan<const char>{}, SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{}); - uint64_t fUniqueID{0}; size_t fMaxTotalRunSize{0}; SkAutoTMalloc<uint16_t> fUniqueGlyphIDIndices; SkAutoTMalloc<SkPoint> fPositions; SkAutoTMalloc<SkGlyphID> fUniqueGlyphIDs; + std::vector<SkGlyphRun> fGlyphRunListStorage; + SkGlyphRunList fGlyphRunList; + + // Used as a temporary for preparing using utfN text. This implies that only one run of // glyph ids will ever be needed because blobs are already glyph based. std::vector<SkGlyphID> fScratchGlyphIDs; @@ -159,10 +209,6 @@ private: // Used as temporary storage for calculating positions for drawText. std::vector<SkPoint> fScratchAdvances; - - // Used as temporary glyph run for the rest of the Text stack. - SkGlyphRun fScratchGlyphRun; - // Used for collecting the set of unique glyphs. SkGlyphIDSet fGlyphIDSet; }; diff --git a/src/gpu/text/GrTextContext.cpp b/src/gpu/text/GrTextContext.cpp index 04d92aef39..a2ef40f16d 100644 --- a/src/gpu/text/GrTextContext.cpp +++ b/src/gpu/text/GrTextContext.cpp @@ -214,15 +214,17 @@ void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob, builder.drawText(runPaint.skPaint(), (const char*) it.glyphs(), textLen, origin); - auto glyphRun = builder.useGlyphRun(); - - glyphRun->temporaryShuntToCallback( + auto glyphRunList = builder.useGlyphRunList(); + if (!glyphRunList->empty()) { + auto glyphRun = (*glyphRunList)[0]; + glyphRun.temporaryShuntToCallback( [&](size_t runSize, const char* glyphIDs, const SkScalar* pos) { this->drawDFPosText( - cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, - viewMatrix, glyphIDs, 2 * runSize, pos, 2, - SkPoint::Make(0,0)); + cacheBlob, run, glyphCache, props, runPaint, + scalerContextFlags, viewMatrix, glyphIDs, 2 * runSize, + pos, 2, SkPoint::Make(0, 0)); }); + } break; } @@ -249,15 +251,18 @@ void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob, builder.drawText(runPaint.skPaint(), (const char*) it.glyphs(), textLen, origin); - auto glyphRun = builder.useGlyphRun(); + auto glyphRunList = builder.useGlyphRunList(); + if (!glyphRunList->empty()) { + auto glyphRun = (*glyphRunList)[0]; - glyphRun->temporaryShuntToCallback( + glyphRun.temporaryShuntToCallback( [&](size_t runSize, const char* glyphIDs, const SkScalar* pos) { this->DrawBmpPosText( - cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, - viewMatrix, glyphIDs, 2 * runSize, + cacheBlob, run, glyphCache, props, runPaint, + scalerContextFlags, viewMatrix, glyphIDs, 2 * runSize, pos, 2, SkPoint::Make(0, 0)); }); + } break; } case SkTextBlob::kHorizontal_Positioning: @@ -783,16 +788,20 @@ std::unique_ptr<GrDrawOp> GrTextContext::createOp_TestingOnly(GrContext* context builder.drawText(skPaint, text, textLen, origin); sk_sp<GrTextBlob> blob; - auto glyphRun = builder.useGlyphRun(); - // Use the text and textLen below, because we don't want to mess with the paint. - glyphRun->temporaryShuntToCallback( + auto glyphRunList = builder.useGlyphRunList(); + if (!glyphRunList->empty()) { + auto glyphRun = (*glyphRunList)[0]; + // Use the text and textLen below, because we don't want to mess with the paint. + glyphRun.temporaryShuntToCallback( [&](size_t runSize, const char* glyphIDs, const SkScalar* pos) { blob = textContext->makeDrawPosTextBlob( context->contextPriv().getTextBlobCache(), glyphCache, *context->contextPriv().caps()->shaderCaps(), utilsPaint, - GrTextContext::kTextBlobOpScalerContextFlags, viewMatrix, surfaceProps, text, + GrTextContext::kTextBlobOpScalerContextFlags, viewMatrix, surfaceProps, + text, textLen, pos, 2, origin); }); + } return blob->test_makeOp(textLen, 0, 0, viewMatrix, x, y, utilsPaint, surfaceProps, textContext->dfAdjustTable(), rtc->textTarget()); |