From 9d85d63468eede1324c88b6e174834eb096113fe Mon Sep 17 00:00:00 2001 From: Herb Derby Date: Mon, 18 Jun 2018 16:25:52 -0400 Subject: [PATCH] Use SkGlyphRun instead of builder Move from passing builder down the stack to passing the object we really want to be the interface down the stack. Move code that shunts from glyph run style to drawTextPos to the SkGlyphRun from the builder. Change-Id: Iefaca69104737ce46c06fbb26dc99996784b2bdb Reviewed-on: https://skia-review.googlesource.com/135620 Commit-Queue: Herb Derby Reviewed-by: Ben Wagner --- src/core/SkCanvas.cpp | 9 ++++--- src/core/SkDevice.cpp | 7 ++--- src/core/SkDevice.h | 4 +-- src/core/SkGlyphRun.cpp | 46 +++++++++++++++++++-------------- src/core/SkGlyphRun.h | 47 ++++++++++++++++++++++------------ src/gpu/text/GrTextContext.cpp | 11 +++++--- 6 files changed, 78 insertions(+), 46 deletions(-) diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 494bd3b837..be55947efd 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -2452,7 +2452,8 @@ void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkSca while (iter.next()) { fScratchGlyphRunBuilder->prepareDrawText(paint, text, byteLength, SkPoint::Make(x, y)); - iter.fDevice->drawGlyphRun(looper.paint(), fScratchGlyphRunBuilder.get()); + auto glyphRun = fScratchGlyphRunBuilder->useGlyphRun(); + iter.fDevice->drawGlyphRun(looper.paint(), glyphRun); } LOOPER_END @@ -2465,7 +2466,8 @@ void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint while (iter.next()) { fScratchGlyphRunBuilder->prepareDrawPosText(paint, text, byteLength, pos); - iter.fDevice->drawGlyphRun(looper.paint(), fScratchGlyphRunBuilder.get()); + auto glyphRun = fScratchGlyphRunBuilder->useGlyphRun(); + iter.fDevice->drawGlyphRun(looper.paint(), glyphRun); } LOOPER_END @@ -2478,7 +2480,8 @@ void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScala while (iter.next()) { fScratchGlyphRunBuilder->prepareDrawPosTextH(paint, text, byteLength, xpos, constY); - iter.fDevice->drawGlyphRun(looper.paint(), fScratchGlyphRunBuilder.get()); + const auto& glyphRun = fScratchGlyphRunBuilder->useGlyphRun(); + iter.fDevice->drawGlyphRun(looper.paint(), glyphRun); } LOOPER_END diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index aea08c55ab..23560986bc 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -165,7 +165,8 @@ void SkBaseDevice::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, auto origin = SkPoint::Make(x + offset.x(), y + offset.y()); SkGlyphRunBuilder builder; builder.prepareDrawText(runPaint, (const char*) it.glyphs(), textLen, origin); - builder.temporaryShuntToDrawPosText(runPaint, this); + auto glyphRun = builder.useGlyphRun(); + glyphRun->temporaryShuntToDrawPosText(runPaint, this); } break; case SkTextBlob::kHorizontal_Positioning: @@ -251,11 +252,11 @@ void SkBaseDevice::drawImageLattice(const SkImage* image, } } -void SkBaseDevice::drawGlyphRun(const SkPaint& paint, SkGlyphRunBuilder* runBuilder) { +void SkBaseDevice::drawGlyphRun(const SkPaint& paint, SkGlyphRun* glyphRun) { SkPaint glyphPaint(paint); glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); - runBuilder->temporaryShuntToDrawPosText(glyphPaint, this); + glyphRun->temporaryShuntToDrawPosText(glyphPaint, this); } void SkBaseDevice::drawBitmapLattice(const SkBitmap& bitmap, diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h index 25008336c6..f840cf6218 100644 --- a/src/core/SkDevice.h +++ b/src/core/SkDevice.h @@ -224,7 +224,7 @@ protected: * Does not handle text decoration. * Decorations (underline and stike-thru) will be handled by SkCanvas. */ - virtual void drawGlyphRun(const SkPaint& paint, SkGlyphRunBuilder* info); + virtual void drawGlyphRun(const SkPaint& paint, SkGlyphRun* glyphRun); virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) = 0; virtual void drawShadow(const SkPath&, const SkDrawShadowRec&); @@ -348,7 +348,7 @@ private: friend class DeviceTestingAccess; // Temporarily friend the SkGlyphRunBuilder until drawPosText is gone. - friend class SkGlyphRunBuilder; + friend class SkGlyphRun; virtual void drawPosText(const void* text, size_t len, const SkScalar pos[], int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) = 0; diff --git a/src/core/SkGlyphRun.cpp b/src/core/SkGlyphRun.cpp index caea07a076..29c1dfdb78 100644 --- a/src/core/SkGlyphRun.cpp +++ b/src/core/SkGlyphRun.cpp @@ -76,6 +76,24 @@ void SkGlyphSet::reuse(uint32_t glyphUniverseSize, std::vector* uniqu // correctly even when the fIndexes buffer is uninitialized! } +// -- SkGlyphRun ----------------------------------------------------------------------------------- + +void SkGlyphRun::temporaryShuntToDrawPosText(const SkPaint& paint, SkBaseDevice* device) { + + auto pos = (const SkScalar*) fPositions.data(); + + device->drawPosText( + fTemporaryShuntGlyphIDs.data(), fDenseIndex.size() * sizeof(SkGlyphID), + pos, 2, SkPoint::Make(0, 0), paint); +} + +void SkGlyphRun::temporaryShuntToCallback(TemporaryShuntCallback callback) { + auto bytes = (const char *)fTemporaryShuntGlyphIDs.data(); + auto pos = (const SkScalar*)fPositions.data(); + callback(this->runSize(), bytes, pos); +} + + // -- SkGlyphRunBuilder ---------------------------------------------------------------------------- void SkGlyphRunBuilder::prepareDrawText( const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin) { @@ -127,26 +145,14 @@ void SkGlyphRunBuilder::prepareDrawPosText(const SkPaint& paint, const void* byt } } -const SkGlyphRun& SkGlyphRunBuilder::useGlyphRun() const { +SkGlyphRun* SkGlyphRunBuilder::useGlyphRun() { + fScratchGlyphRun.~SkGlyphRun(); new ((void*)&fScratchGlyphRun) SkGlyphRun{SkSpan(fDenseIndex), - SkSpan(fPositions), - SkSpan(fUniqueGlyphs)}; - return fScratchGlyphRun; -} - -void SkGlyphRunBuilder::temporaryShuntToDrawPosText(const SkPaint& paint, SkBaseDevice* device) { - - auto pos = (const SkScalar*) fPositions.data(); - - device->drawPosText( - fTemporaryShuntGlyphIDs, fDenseIndex.size() * 2, - pos, 2, SkPoint::Make(0, 0), paint); -} - -void SkGlyphRunBuilder::temporaryShuntToCallback(TemporaryShuntCallback callback) { - auto bytes = (const char *)fTemporaryShuntGlyphIDs; - auto pos = (const SkScalar*)fPositions.data(); - callback(this->runSize(), bytes, pos); + SkSpan(fPositions), + SkSpan( + fTemporaryShuntGlyphIDs, fDenseIndex.size()), + SkSpan(fUniqueGlyphs)}; + return &fScratchGlyphRun; } void SkGlyphRunBuilder::initializeDenseAndUnique( @@ -175,6 +181,8 @@ void SkGlyphRunBuilder::initializeDenseAndUnique( glyphIDs = (const SkGlyphID*)bytes; } + SkASSERT(glyphIDs != nullptr); + if (runSize == 0) { return; } fTemporaryShuntGlyphIDs = glyphIDs; diff --git a/src/core/SkGlyphRun.h b/src/core/SkGlyphRun.h index eeb9c2924e..243d5d121c 100644 --- a/src/core/SkGlyphRun.h +++ b/src/core/SkGlyphRun.h @@ -23,13 +23,17 @@ class SkBaseDevice; template class SkSpan { public: - SkSpan() = default; + SkSpan() : fPtr{nullptr}, fSize{0} {} SkSpan(const T* ptr, size_t size) : fPtr{ptr}, fSize{size} {} explicit SkSpan(const std::vector& v) : fPtr{v.data()}, fSize{v.size()} {} const T& operator [] (ptrdiff_t i) const { return fPtr[i]; } - const T* begin() const { return fPtr; } - const T* end() const { return fPtr + fSize; } + T* begin() const { return fPtr; } + T* end() const { return fPtr + fSize; } + const T* cbegin() const { return fPtr; } + const T* cend() const { return fPtr + fSize; } + const T* data() const { return fPtr; } ptrdiff_t size() const { return fSize; } + bool empty() const { return fSize == 0; } private: const T* fPtr; @@ -39,20 +43,37 @@ private: class SkGlyphRun { public: SkGlyphRun() = default; - SkGlyphRun(SkSpan denseIndex, SkSpan positions, + SkGlyphRun(SkSpan denseIndex, + SkSpan positions, + SkSpan scratchGlyphs, SkSpan uniqueGlyphIDs) : fDenseIndex{denseIndex} , fPositions{positions} - , fUniqueGlyphIDs{uniqueGlyphIDs} {} + , fTemporaryShuntGlyphIDs{scratchGlyphs} + , fUniqueGlyphIDs{uniqueGlyphIDs} { + SkASSERT(denseIndex.size() == positions.size()); + SkASSERT(denseIndex.size() == scratchGlyphs.size()); + } + + // The temporaryShunt calls are to allow inter-operating with existing code while glyph runs + // are developed. + void temporaryShuntToDrawPosText(const SkPaint& paint, SkBaseDevice* device); + using TemporaryShuntCallback = std::function; + void temporaryShuntToCallback(TemporaryShuntCallback callback); size_t runSize() const { return fDenseIndex.size(); } uint16_t uniqueSize() const { return fUniqueGlyphIDs.size(); } SkSpan positions() const { return SkSpan(fPositions); } private: - SkSpan fDenseIndex; - SkSpan fPositions; - SkSpan fUniqueGlyphIDs; + // Indices into the unique glyph IDs. On for each original glyph. + const SkSpan fDenseIndex; + // The base line position of all the glyphs in source space. + const SkSpan fPositions; + // This is temporary while converting from the old per glyph code to the bulk code. + const SkSpan fTemporaryShuntGlyphIDs; + // The set of unique glyphs in the run. + const SkSpan fUniqueGlyphIDs; }; // A faster set implementation that does not need any initialization, and reading the set items @@ -89,13 +110,7 @@ public: size_t runSize() const {return fDenseIndex.size();} size_t uniqueSize() const {return fUniqueGlyphs.size();} - const SkGlyphRun& useGlyphRun() const; - - // The temporaryShunt calls are to allow inter-operating with existing code while glyph runs - // are developed. - void temporaryShuntToDrawPosText(const SkPaint& paint, SkBaseDevice* device); - using TemporaryShuntCallback = std::function; - void temporaryShuntToCallback(TemporaryShuntCallback callback); + SkGlyphRun* useGlyphRun(); private: void initializeDenseAndUnique(const SkPaint& paint, const void* bytes, size_t byteLength); @@ -119,7 +134,7 @@ private: const SkGlyphID* fTemporaryShuntGlyphIDs{nullptr}; // Used for collecting the set of unique glyphs. - SkGlyphSet fGlyphSet; + SkGlyphSet fGlyphSet; }; #endif // SkGlyphRunInfo_DEFINED diff --git a/src/gpu/text/GrTextContext.cpp b/src/gpu/text/GrTextContext.cpp index b63b726079..6da4c0d014 100644 --- a/src/gpu/text/GrTextContext.cpp +++ b/src/gpu/text/GrTextContext.cpp @@ -217,7 +217,9 @@ void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob, builder.prepareDrawText(runPaint.skPaint(), (const char*)it.glyphs(), textLen, origin); - builder.temporaryShuntToCallback( + auto glyphRun = builder.useGlyphRun(); + + glyphRun->temporaryShuntToCallback( [&](size_t runSize, const char* glyphIDs, const SkScalar* pos) { this->drawDFPosText( cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, @@ -250,7 +252,9 @@ void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob, builder.prepareDrawText(runPaint.skPaint(), (const char*)it.glyphs(), textLen, origin); - builder.temporaryShuntToCallback( + auto glyphRun = builder.useGlyphRun(); + + glyphRun->temporaryShuntToCallback( [&](size_t runSize, const char* glyphIDs, const SkScalar* pos) { this->DrawBmpPosText( cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, @@ -782,8 +786,9 @@ std::unique_ptr GrTextContext::createOp_TestingOnly(GrContext* context builder.prepareDrawText(skPaint, text, textLen, origin); sk_sp blob; + auto glyphRun = builder.useGlyphRun(); // Use the text and textLen below, because we don't want to mess with the paint. - builder.temporaryShuntToCallback( + glyphRun->temporaryShuntToCallback( [&](size_t runSize, const char* glyphIDs, const SkScalar* pos) { blob = textContext->makeDrawPosTextBlob( context->contextPriv().getTextBlobCache(), glyphCache,