diff options
author | Robert Phillips <robertphillips@google.com> | 2018-06-28 12:00:35 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-06-28 12:00:47 +0000 |
commit | 385804514edf602f978975c825b78692a044c6b9 (patch) | |
tree | 891790d5b77fa447c75ec9a25487ecd8ae22c332 | |
parent | e97bb26893a1c24deeb38b818a1f4c1638a9983d (diff) |
Revert "Remove drawTextBlob from device use drawGlyphRunList"
This reverts commit e2e52e46ca63540d429656baeee48fd3a402be26.
Reason for revert: See if this is blocking the Chrome roll
Original change's description:
> Remove drawTextBlob from device use drawGlyphRunList
>
> Convert all backends to use GlyphRunList instead of
> text blobs. If the device did not originally implement
> drawTextBlob it will be simulated by drawPosText on the
> device.
>
> Other changes:
> Change to using an origin from absolulte positioning. The GPU
> code uses origin change to update blobs under translation.
>
> Change cluster to use const uint32_t instead of just
> uint32_t.
>
> Add SkPaint to runs.
>
> The draw filter is hosted up to the canavas level and applied there.
>
> Change-Id: Ib105b6bd26b67db55f1c954e37c79fbdcaa9d4a2
> Reviewed-on: https://skia-review.googlesource.com/137224
> Reviewed-by: Herb Derby <herb@google.com>
> Reviewed-by: Khusal Sagar <khushalsagar@chromium.org>
> Reviewed-by: Hal Canary <halcanary@google.com>
> Reviewed-by: Jim Van Verth <jvanverth@google.com>
> Commit-Queue: Herb Derby <herb@google.com>
TBR=jvanverth@google.com,halcanary@google.com,bungeman@google.com,herb@google.com,reed@google.com,khushalsagar@chromium.org,khushalsagar@google.com
Change-Id: I4d93a534990c89deee7d3aaa00ec40d47e0d2ece
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/138120
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
-rw-r--r-- | include/core/SkTextBlob.h | 2 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 13 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 56 | ||||
-rw-r--r-- | src/core/SkDevice.h | 7 | ||||
-rw-r--r-- | src/core/SkGlyphRun.cpp | 136 | ||||
-rw-r--r-- | src/core/SkGlyphRun.h | 100 | ||||
-rw-r--r-- | src/core/SkRemoteGlyphCache.cpp | 23 | ||||
-rw-r--r-- | src/core/SkTypeface_remote.h | 3 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.cpp | 13 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.h | 8 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 9 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.h | 3 | ||||
-rw-r--r-- | src/gpu/text/GrTextBlobCache.h | 14 | ||||
-rw-r--r-- | src/gpu/text/GrTextContext.cpp | 156 | ||||
-rw-r--r-- | src/gpu/text/GrTextContext.h | 14 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 14 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.h | 4 | ||||
-rw-r--r-- | tests/GlyphRunTest.cpp | 4 | ||||
-rw-r--r-- | tests/SkRemoteGlyphCacheTest.cpp | 46 |
19 files changed, 287 insertions, 338 deletions
diff --git a/include/core/SkTextBlob.h b/include/core/SkTextBlob.h index 9f4f10f2e4..59151d3002 100644 --- a/include/core/SkTextBlob.h +++ b/include/core/SkTextBlob.h @@ -14,7 +14,6 @@ #include "SkString.h" #include "SkRefCnt.h" -class SkGlyphRunList; class SkReadBuffer; class SkWriteBuffer; @@ -111,7 +110,6 @@ private: fCacheID.store(cacheID); } - friend class SkGlyphRunList; friend class GrTextBlobCache; friend class SkTextBlobBuilder; friend class SkTextBlobRunIterator; diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index c590d77cb7..b297f98156 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -2453,7 +2453,8 @@ void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkSca while (iter.next()) { fScratchGlyphRunBuilder->prepareDrawText( looper.paint(), text, byteLength, SkPoint::Make(x, y)); - fScratchGlyphRunBuilder->draw(iter.fDevice); + auto glyphRun = fScratchGlyphRunBuilder->useGlyphRun(); + iter.fDevice->drawGlyphRun(looper.paint(), glyphRun); } LOOPER_END @@ -2466,7 +2467,8 @@ void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint while (iter.next()) { fScratchGlyphRunBuilder->prepareDrawPosText(looper.paint(), text, byteLength, pos); - fScratchGlyphRunBuilder->draw(iter.fDevice); + auto glyphRun = fScratchGlyphRunBuilder->useGlyphRun(); + iter.fDevice->drawGlyphRun(looper.paint(), glyphRun); } LOOPER_END @@ -2480,7 +2482,8 @@ void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScala while (iter.next()) { fScratchGlyphRunBuilder->prepareDrawPosTextH( looper.paint(), text, byteLength, xpos, constY); - fScratchGlyphRunBuilder->draw(iter.fDevice); + const auto& glyphRun = fScratchGlyphRunBuilder->useGlyphRun(); + iter.fDevice->drawGlyphRun(looper.paint(), glyphRun); } LOOPER_END @@ -2533,9 +2536,7 @@ void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds) while (iter.next()) { - fScratchGlyphRunBuilder->prepareTextBlob( - looper.paint(), *blob, SkPoint::Make(x, y), drawFilter); - fScratchGlyphRunBuilder->draw(iter.fDevice); + iter.fDevice->drawTextBlob(blob, x, y, looper.paint(), drawFilter); } LOOPER_END diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 9fd61c9d28..46404b2887 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -141,6 +141,53 @@ void SkBaseDevice::drawPatch(const SkPoint cubics[12], const SkColor colors[4], } } +void SkBaseDevice::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, + const SkPaint &paint, SkDrawFilter* drawFilter) { + + SkPaint runPaint = paint; + + 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 = paint; + continue; + } + + switch (it.positioning()) { + case SkTextBlob::kDefault_Positioning: { + auto origin = SkPoint::Make(x + offset.x(), y + offset.y()); + SkGlyphRunBuilder builder; + builder.prepareDrawText(runPaint, (const char*) it.glyphs(), textLen, origin); + auto glyphRun = builder.useGlyphRun(); + glyphRun->temporaryShuntToDrawPosText(runPaint, this); + } + break; + case SkTextBlob::kHorizontal_Positioning: + this->drawPosText(it.glyphs(), textLen, it.pos(), 1, + SkPoint::Make(x, y + offset.y()), runPaint); + break; + case SkTextBlob::kFull_Positioning: + this->drawPosText(it.glyphs(), textLen, it.pos(), 2, + SkPoint::Make(x, y), runPaint); + break; + default: + SK_ABORT("unhandled positioning mode"); + } + + if (drawFilter) { + // A draw filter may change the paint arbitrarily, so we must re-seed in this case. + runPaint = paint; + } + } +} + void SkBaseDevice::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint& paint) { SkBitmap bm; @@ -205,10 +252,11 @@ void SkBaseDevice::drawImageLattice(const SkImage* image, } } -void SkBaseDevice::drawGlyphRunList(SkGlyphRunList* glyphRunList) { - for (auto& glyphRun : *glyphRunList) { - glyphRun.temporaryShuntToDrawPosText(this, glyphRunList->origin()); - } +void SkBaseDevice::drawGlyphRun(const SkPaint& paint, SkGlyphRun* glyphRun) { + SkPaint glyphPaint(paint); + glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + + glyphRun->temporaryShuntToDrawPosText(glyphPaint, this); } void SkBaseDevice::drawBitmapLattice(const SkBitmap& bitmap, diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h index 9a4086e51d..f840cf6218 100644 --- a/src/core/SkDevice.h +++ b/src/core/SkDevice.h @@ -18,7 +18,6 @@ class SkBitmap; class SkDrawFilter; struct SkDrawShadowRec; class SkGlyphRun; -class SkGlyphRunList; class SkGlyphRunBuilder; class SkImageFilterCache; struct SkIRect; @@ -225,10 +224,13 @@ protected: * Does not handle text decoration. * Decorations (underline and stike-thru) will be handled by SkCanvas. */ - virtual void drawGlyphRunList(SkGlyphRunList* glyphRunList); + virtual void drawGlyphRun(const SkPaint& paint, SkGlyphRun* glyphRun); virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) = 0; virtual void drawShadow(const SkPath&, const SkDrawShadowRec&); + // default implementation unrolls the blob runs. + virtual void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y, + const SkPaint& paint, SkDrawFilter* drawFilter); // default implementation calls drawVertices virtual void drawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4], SkBlendMode, bool interpColorsLinearly, @@ -347,7 +349,6 @@ private: // Temporarily friend the SkGlyphRunBuilder until drawPosText is gone. friend class SkGlyphRun; - friend class SkGlyphRunBuilder; 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 583d676940..ce1c336d88 100644 --- a/src/core/SkGlyphRun.cpp +++ b/src/core/SkGlyphRun.cpp @@ -12,7 +12,7 @@ #include <tuple> #include "SkDevice.h" -#include "SkDrawFilter.h" +#include "SkDraw.h" #include "SkGlyphCache.h" #include "SkMSAN.h" #include "SkMakeUnique.h" @@ -90,23 +90,22 @@ SkGlyphRun::SkGlyphRun(const SkIndexedRunInfo& runInfo, size_t uniqueOffset, uint16_t uniqueSize, SkSpan<SkGlyphID> scratchGlyphs, SkSpan<const char> text, - SkSpan<const uint32_t> clusters, - SkPaint&& runPaint) + SkSpan<uint32_t> clusters) : fRunInfo{runInfo} , fDenseOffset{denseOffset}, fDenseSize{denseSize} , fUniqueOffset{uniqueOffset}, fUniqueSize{uniqueSize} , fTemporaryShuntGlyphIDs{scratchGlyphs} , fText{text} - , fClusters{clusters} - , fRunPaint{std::move(runPaint)} {} + , fClusters{clusters} { } -void SkGlyphRun::temporaryShuntToDrawPosText(SkBaseDevice* device, SkPoint origin) { + +void SkGlyphRun::temporaryShuntToDrawPosText(const SkPaint& paint, SkBaseDevice* device) { auto pos = (const SkScalar*) this->positions().data(); device->drawPosText( fTemporaryShuntGlyphIDs.data(), fDenseSize * sizeof(SkGlyphID), - pos, 2, origin, fRunPaint); + pos, 2, SkPoint::Make(0, 0), paint); } void SkGlyphRun::temporaryShuntToCallback(TemporaryShuntCallback callback) { @@ -116,40 +115,19 @@ void SkGlyphRun::temporaryShuntToCallback(TemporaryShuntCallback callback) { } // -- SkGlyphRunList ------------------------------------------------------------------------------- -SkGlyphRunList::SkGlyphRunList( - SkSpan<SkGlyphRun> glyphRuns, SkPoint origin, const SkTextBlob* textBlob) - : fGlyphRuns{glyphRuns} - , fOrigin{origin} - , fTemporaryTextBlobShunt{textBlob} { } - -uint64_t SkGlyphRunList::uniqueID() const { - return fTemporaryTextBlobShunt != nullptr ? fTemporaryTextBlobShunt->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(fTemporaryTextBlobShunt != nullptr); - fTemporaryTextBlobShunt->notifyAddedToCache(cacheID); -} - -// -- SkGlyphRunListIterator ----------------------------------------------------------------------- -constexpr SkPoint SkGlyphRunListIterator::fZero; +SkGlyphRunList::SkGlyphRunList(SkSpan<SkGlyphRun> glyphRuns, uint64_t uniqueID) + : fUniqueID{uniqueID} + , fGlyphRuns{glyphRuns} { } // -- SkGlyphRunBuilder ---------------------------------------------------------------------------- void SkGlyphRunBuilder::prepareDrawText( const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin) { this->initialize(); - this->drawText( - paint, bytes, byteLength, origin, SkSpan<const char>(), SkSpan<const uint32_t>()); + SkSpan<const char> originalText((const char*)bytes, byteLength); + if (paint.getTextEncoding() != SkPaint::kUTF8_TextEncoding) { + originalText = SkSpan<const char>(); + } + this->drawText(paint, bytes, byteLength, origin, originalText, SkSpan<uint32_t>()); } void SkGlyphRunBuilder::prepareDrawPosTextH(const SkPaint& paint, const void* bytes, @@ -157,22 +135,19 @@ void SkGlyphRunBuilder::prepareDrawPosTextH(const SkPaint& paint, const void* by SkScalar constY) { this->initialize(); this->drawPosTextH( - paint, bytes, byteLength, xpos, constY, - SkSpan<const char>(), SkSpan<const uint32_t>()); + paint, bytes, byteLength, xpos, constY, SkSpan<const char>(), SkSpan<uint32_t>()); } void SkGlyphRunBuilder::prepareDrawPosText(const SkPaint& paint, const void* bytes, size_t byteLength, const SkPoint* pos) { this->initialize(); - this->drawPosText(paint, bytes, byteLength, pos, - SkSpan<const char>(), SkSpan<const uint32_t>()); + this->drawPosText(paint, bytes, byteLength, pos, SkSpan<const char>(), SkSpan<uint32_t>()); } void SkGlyphRunBuilder::prepareTextBlob( - const SkPaint& paint, const SkTextBlob& blob, SkPoint origin, SkDrawFilter* drawFilter) { + const SkPaint& paint, const SkTextBlob& blob, SkPoint origin) { this->initialize(); - fTemporaryTextBlobShunt = &blob; - fOrigin = origin; + fUniqueID = blob.uniqueID(); SkPaint runPaint = paint; @@ -181,44 +156,33 @@ void SkGlyphRunBuilder::prepareTextBlob( // so it is safe to not re-seed the paint for this reason. it.applyFontToPaint(&runPaint); - if (drawFilter != nullptr && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) { - // A false return from filter() means we should abort the current draw. - runPaint = paint; - continue; - } - // 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(), it.glyphCount()); + auto clusters = SkSpan<uint32_t>(it.clusters(), it.glyphCount()); size_t glyphLen = it.glyphCount() * sizeof(SkGlyphID); const SkPoint& offset = it.offset(); switch (it.positioning()) { case SkTextBlob::kDefault_Positioning: { - this->drawText(runPaint, it.glyphs(), glyphLen, offset, text, clusters); + auto dtOrigin = origin + offset; + this->drawText(runPaint, it.glyphs(), glyphLen, dtOrigin, text, clusters); } break; case SkTextBlob::kHorizontal_Positioning: { - auto constY = offset.y(); + auto constY = origin.y() + offset.y(); this->drawPosTextH( runPaint, it.glyphs(), glyphLen, it.pos(), constY, text, clusters); } break; case SkTextBlob::kFull_Positioning: this->drawPosText( - runPaint, it.glyphs(), glyphLen, (const SkPoint*)it.pos(), text, - clusters); + runPaint, it.glyphs(), glyphLen, (const SkPoint*)it.pos(), text, clusters); break; default: SK_ABORT("unhandled positioning mode"); } - - if (drawFilter != nullptr) { - // A draw filter may change the paint arbitrarily, so we must re-seed in this case. - runPaint = paint; - } } } @@ -229,29 +193,22 @@ SkGlyphRun* SkGlyphRunBuilder::useGlyphRun() { } SkGlyphRunList* SkGlyphRunBuilder::useGlyphRunList() { - new ((void*)&fScratchGlyphRunList) - SkGlyphRunList{SkSpan<SkGlyphRun>(fGlyphRuns), fOrigin, fTemporaryTextBlobShunt}; + new ((void*)&fScratchGlyphRunList) SkGlyphRunList{SkSpan<SkGlyphRun>(fGlyphRuns), fUniqueID}; return &fScratchGlyphRunList; } -void SkGlyphRunBuilder::draw(SkBaseDevice* device) { - auto glyphRunList = this->useGlyphRunList(); - device->drawGlyphRunList(glyphRunList); -} - size_t SkGlyphRunBuilder::runSize() const { return fDenseIndex.size() - fLastDenseIndex; } size_t SkGlyphRunBuilder::uniqueSize() const { return fUniqueGlyphIDs.size() - fLastUniqueIndex; } void SkGlyphRunBuilder::initialize() { - fTemporaryTextBlobShunt = nullptr; + fUniqueID = 0; fDenseIndex.clear(); fPositions.clear(); fUniqueGlyphIDs.clear(); fGlyphRuns.clear(); fLastDenseIndex = 0; fLastUniqueIndex = 0; - fOrigin = {0, 0}; } SkGlyphID* SkGlyphRunBuilder::addDenseAndUnique( @@ -288,19 +245,10 @@ SkGlyphID* SkGlyphRunBuilder::addDenseAndUnique( } void SkGlyphRunBuilder::addGlyphRunToList( - const SkPaint& runPaint, - SkGlyphID* temporaryShuntGlyphIDs, - SkSpan<const char> text, - SkSpan<const uint32_t> clusters) { + SkGlyphID* temporaryShuntGlyphIDs, SkSpan<const char> text, SkSpan<uint32_t> clusters) { // Ignore empty runs. if (fDenseIndex.size() != fLastDenseIndex) { - SkPaint modifiedRunPaint{runPaint}; - - // TODO: remove these once the text stack has all the encoding and align code removed. - modifiedRunPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); - modifiedRunPaint.setTextAlign(SkPaint::kLeft_Align); - auto runSize = this->runSize(); auto uniqueSize = this->uniqueSize(); @@ -310,8 +258,7 @@ void SkGlyphRunBuilder::addGlyphRunToList( fLastUniqueIndex, SkTo<uint16_t>(uniqueSize), SkSpan<SkGlyphID>(temporaryShuntGlyphIDs, runSize), text, - clusters, - std::move(modifiedRunPaint)); + clusters); fLastDenseIndex = fDenseIndex.size(); fLastUniqueIndex = fUniqueGlyphIDs.size(); @@ -320,7 +267,7 @@ void SkGlyphRunBuilder::addGlyphRunToList( void SkGlyphRunBuilder::drawText( const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin, - SkSpan<const char> text, SkSpan<const uint32_t> clusters) { + SkSpan<const char> text, SkSpan<uint32_t> clusters) { SkGlyphID* temporaryShuntGlyphIDs = this->addDenseAndUnique(paint, bytes, byteLength); @@ -339,22 +286,22 @@ void SkGlyphRunBuilder::drawText( } if (paint.getTextAlign() != SkPaint::kLeft_Align) { - SkVector runWidth = endOfLastGlyph - origin; + SkVector len = endOfLastGlyph - origin; if (paint.getTextAlign() == SkPaint::kCenter_Align) { - runWidth.scale(SK_ScalarHalf); + len.scale(SK_ScalarHalf); } for (size_t i = fLastDenseIndex; i < this->runSize(); i++) { - fPositions[i] -= runWidth; + fPositions[i] -= len; } } - this->addGlyphRunToList(paint, temporaryShuntGlyphIDs, text, clusters); + this->addGlyphRunToList(temporaryShuntGlyphIDs, text, clusters); } -void SkGlyphRunBuilder::drawPosTextH( - const SkPaint& paint, const void* bytes, size_t byteLength, - const SkScalar* xpos, SkScalar constY, - SkSpan<const char> text, SkSpan<const uint32_t> clusters) { +void SkGlyphRunBuilder::drawPosTextH(const SkPaint& paint, const void* bytes, + size_t byteLength, const SkScalar* xpos, + SkScalar constY, + SkSpan<const char> text, SkSpan<uint32_t> clusters) { SkGlyphID* temporaryShuntGlyphIDs = this->addDenseAndUnique(paint, bytes, byteLength); @@ -362,20 +309,19 @@ void SkGlyphRunBuilder::drawPosTextH( fPositions.push_back(SkPoint::Make(xpos[i], constY)); } - this->addGlyphRunToList(paint, temporaryShuntGlyphIDs, text, clusters); + this->addGlyphRunToList(temporaryShuntGlyphIDs, text, clusters); } -void SkGlyphRunBuilder::drawPosText( - const SkPaint& paint, const void* bytes, - size_t byteLength, const SkPoint* pos, - SkSpan<const char> text, SkSpan<const uint32_t> clusters) { +void SkGlyphRunBuilder::drawPosText(const SkPaint& paint, const void* bytes, + size_t byteLength, const SkPoint* pos, + SkSpan<const char> text, SkSpan<uint32_t> clusters) { SkGlyphID* temporaryShuntGlyphIDs = this->addDenseAndUnique(paint, bytes, byteLength); for (size_t i = 0; i < runSize(); i++) { fPositions.push_back(pos[i]); } - this->addGlyphRunToList(paint, temporaryShuntGlyphIDs, text, clusters); + this->addGlyphRunToList(temporaryShuntGlyphIDs, text, clusters); } diff --git a/src/core/SkGlyphRun.h b/src/core/SkGlyphRun.h index 6f9041c443..739ad0bc38 100644 --- a/src/core/SkGlyphRun.h +++ b/src/core/SkGlyphRun.h @@ -16,11 +16,9 @@ #include "SkMask.h" #include "SkPath.h" #include "SkPoint.h" -#include "SkTextBlob.h" #include "SkTypes.h" class SkBaseDevice; -class SkDrawFilter; template <typename T> class SkSpan { @@ -76,12 +74,11 @@ public: size_t fUniqueOffset, uint16_t fUniqueSize, SkSpan<SkGlyphID> scratchGlyphs, SkSpan<const char> text, - SkSpan<const uint32_t> clusters, - SkPaint&& runPaint); + SkSpan<uint32_t> clusters); // The temporaryShunt calls are to allow inter-operating with existing code while glyph runs // are developed. - void temporaryShuntToDrawPosText(SkBaseDevice* device, SkPoint origin); + void temporaryShuntToDrawPosText(const SkPaint& paint, SkBaseDevice* device); using TemporaryShuntCallback = std::function<void(size_t, const char*, const SkScalar*)>; void temporaryShuntToCallback(TemporaryShuntCallback callback); @@ -93,21 +90,6 @@ public: SkSpan<const SkGlyphID> uniqueGlyphIDs() const { return fRunInfo.uniqueGlyphIDs(fUniqueOffset, fUniqueSize); } - SkSpan<SkGlyphID> shuntGlyphsIDs() const { - return fTemporaryShuntGlyphIDs; - } - - const SkPaint& paint() const { - return fRunPaint; - } - - SkSpan<const uint32_t> clusters() const { - return fClusters; - } - - SkSpan<const char> text() const { - return fText; - } private: const SkIndexedRunInfo& fRunInfo; @@ -121,39 +103,18 @@ private: // Original text from SkTextBlob if present. Will be empty of not present. const SkSpan<const char> fText; // Original clusters from SkTextBlob if present. Will be empty if not present. - const SkSpan<const uint32_t> fClusters; - // Paint for this run modified to have glyph encoding and left alignment. - const SkPaint fRunPaint; + const SkSpan<uint32_t> fClusters; }; class SkGlyphRunList { + const uint64_t fUniqueID{0}; SkSpan<SkGlyphRun> fGlyphRuns; - SkPoint fOrigin = {0, 0}; - - // The text blob is needed to hookup the call back that the SkTextBlob destructor calls. It - // should be used for nothing else - const SkTextBlob* fTemporaryTextBlobShunt{nullptr}; public: SkGlyphRunList() = default; - // Blob maybe null. - SkGlyphRunList(SkSpan<SkGlyphRun> glyphRuns, SkPoint origin, const SkTextBlob* blob); - - uint64_t uniqueID() const; - bool anyRunsLCD() const; - void temporaryShuntBlobnotifyAddedToCache(uint32_t cacheID) const; - - bool canCache() const { return fTemporaryTextBlobShunt != nullptr; } - ptrdiff_t runCount() const { return fGlyphRuns.size(); } - size_t totalGlyphCount() const { - size_t glyphCount = 0; - for(const auto& run : fGlyphRuns) { - glyphCount += run.runSize(); - } - return glyphCount; - } + SkGlyphRunList(SkSpan<SkGlyphRun> glyphRuns, uint64_t uniqueID); - SkPoint origin() const { return fOrigin; } + uint64_t uniqueID() const { return fUniqueID; } auto begin() -> decltype(fGlyphRuns.begin()) { return fGlyphRuns.begin(); } auto end() -> decltype(fGlyphRuns.end()) { return fGlyphRuns.end(); } @@ -161,30 +122,6 @@ public: auto operator [] (ptrdiff_t i) -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i]; } }; -class SkGlyphRunListIterator { -public: - explicit SkGlyphRunListIterator(SkGlyphRunList* list) : fList{*list} {} - - bool done() const { return fIndex == fList.size(); } - void next() { fIndex += 1;} - uint32_t glyphCount() const { return fList[fIndex].runSize(); } - const uint16_t* glyphs() const { return fList[fIndex].shuntGlyphsIDs().data(); } - const SkScalar* pos() const { return (const SkScalar*)fList[fIndex].positions().data(); } - const SkPoint& offset() const { return fZero; } - void applyFontToPaint(SkPaint* paint) const { *paint = fList[fIndex].paint(); } - SkTextBlob::GlyphPositioning positioning() const { return SkTextBlob::kFull_Positioning; } - const uint32_t* clusters() const { return fList[fIndex].clusters().data(); } - uint32_t textSize() const { return fList[fIndex].text().size(); } - const char* text() const { return fList[fIndex].text().data(); } - - bool isLCD() const { return fList[fIndex].paint().isLCDRenderText(); } - -private: - static constexpr SkPoint fZero{0,0}; - ptrdiff_t fIndex{0}; - SkGlyphRunList& fList; -}; - // 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. // This implementation is based on the paper by Briggs and Torczon, "An Efficient Representation @@ -217,14 +154,10 @@ public: const SkScalar xpos[], SkScalar constY); void prepareDrawPosText( const SkPaint& paint, const void* bytes, size_t byteLength, const SkPoint pos[]); - void prepareTextBlob( - const SkPaint& paint, const SkTextBlob& blob, SkPoint origin, SkDrawFilter* filter); + void prepareTextBlob(const SkPaint& paint, const SkTextBlob& blob, SkPoint origin); - void draw(SkBaseDevice* device); - - // Public for testing only. - SkGlyphRun* useGlyphRun(); SkGlyphRunList* useGlyphRunList(); + SkGlyphRun* useGlyphRun(); private: size_t runSize() const; @@ -232,27 +165,20 @@ private: void initialize(); SkGlyphID* addDenseAndUnique(const SkPaint& paint, const void* bytes, size_t byteLength); void addGlyphRunToList( - const SkPaint& runPaint, - SkGlyphID* temporaryShuntGlyphIDs, - SkSpan<const char> text, - SkSpan<const uint32_t> clusters); + SkGlyphID* temporaryShuntGlyphIDs, SkSpan<const char> text, SkSpan<uint32_t> clusters); void drawText( const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin, - SkSpan<const char> text, SkSpan<const uint32_t> clusters); + SkSpan<const char> text, SkSpan<uint32_t> clusters); void drawPosTextH( const SkPaint& paint, const void* bytes, size_t byteLength, const SkScalar* xpos, SkScalar constY, - SkSpan<const char> text, SkSpan<const uint32_t> clusters); + SkSpan<const char> text, SkSpan<uint32_t> clusters); void drawPosText( const SkPaint& paint, const void* bytes, size_t byteLength, const SkPoint* pos, - SkSpan<const char> text, SkSpan<const uint32_t> clusters); - - const SkTextBlob* fTemporaryTextBlobShunt{nullptr}; + SkSpan<const char> text, SkSpan<uint32_t> clusters); - // The point passed into drawTextBlob. This allows the GPU back end to detect and adjust for - // translations. - SkPoint fOrigin; + uint64_t fUniqueID{0}; std::vector<uint16_t> fDenseIndex; std::vector<SkPoint> fPositions; diff --git a/src/core/SkRemoteGlyphCache.cpp b/src/core/SkRemoteGlyphCache.cpp index 18e47f3f4c..774a1eb77c 100644 --- a/src/core/SkRemoteGlyphCache.cpp +++ b/src/core/SkRemoteGlyphCache.cpp @@ -16,9 +16,9 @@ #include "SkDevice.h" #include "SkDraw.h" #include "SkFindAndPlaceGlyph.h" -#include "SkGlyphRun.h" #include "SkPathEffect.h" #include "SkStrikeCache.h" +#include "SkTextBlobRunIterator.h" #include "SkTraceEvent.h" #include "SkTypeface_remote.h" @@ -240,20 +240,27 @@ public: } protected: - void drawGlyphRunList(SkGlyphRunList* glyphRunList) override { - SkPaint runPaint; - SkGlyphRunListIterator it(glyphRunList); + void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint, + SkDrawFilter* drawFilter) override { + // The looper should be applied by the SkCanvas. + SkASSERT(paint.getDrawLooper() == nullptr); + // We don't support SkDrawFilter. + SkASSERT(drawFilter == nullptr); + + SkPoint position{x, y}; + SkPaint runPaint{paint}; + SkTextBlobRunIterator it(blob); for (; !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); - this->processGlyphRun(glyphRunList->origin(), it, runPaint); + this->processGlyphRun(position, it, runPaint); } } private: void processGlyphRun(const SkPoint& position, - const SkGlyphRunListIterator& it, + const SkTextBlobRunIterator& it, const SkPaint& runPaint) { TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::processGlyphRun"); @@ -337,7 +344,7 @@ private: } } - void processGlyphRunForPaths(const SkGlyphRunListIterator& it, + void processGlyphRunForPaths(const SkTextBlobRunIterator& it, const SkPaint& runPaint, const SkMatrix& runMatrix) { TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::processGlyphRunForPaths"); @@ -387,7 +394,7 @@ private: } #if SK_SUPPORT_GPU - bool processGlyphRunForDFT(const SkGlyphRunListIterator& it, + bool processGlyphRunForDFT(const SkTextBlobRunIterator& it, const SkPaint& runPaint, const SkMatrix& runMatrix) { TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::processGlyphRunForDFT"); diff --git a/src/core/SkTypeface_remote.h b/src/core/SkTypeface_remote.h index f7326ccf7d..47a68fd08d 100644 --- a/src/core/SkTypeface_remote.h +++ b/src/core/SkTypeface_remote.h @@ -123,7 +123,8 @@ protected: return 0; } int onCountGlyphs() const override { - return this->glyphCount(); + SK_ABORT("Should never be called."); + return 0; } void* onGetCTFontRef() const override { diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 9d31a0dde6..1dbde17575 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -237,17 +237,18 @@ void GrRenderTargetContext::drawPosText(const GrClip& clip, const SkPaint& paint clipBounds); } -void GrRenderTargetContext::drawGlyphRunList( - const GrClip& clip, const SkMatrix& viewMatrix, - SkGlyphRunList* blob, const SkIRect& clipBounds) { +void GrRenderTargetContext::drawTextBlob(const GrClip& clip, const SkPaint& paint, + const SkMatrix& viewMatrix, const SkTextBlob* blob, + SkScalar x, SkScalar y, SkDrawFilter* filter, + const SkIRect& clipBounds) { ASSERT_SINGLE_OWNER RETURN_IF_ABANDONED SkDEBUGCODE(this->validate();) - GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawGlyphRunList", fContext); + GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextBlob", fContext); GrTextContext* atlasTextContext = this->drawingManager()->getTextContext(); - atlasTextContext->drawGlyphRunList(fContext, fTextTarget.get(), clip, viewMatrix, - fSurfaceProps, blob, clipBounds); + atlasTextContext->drawTextBlob(fContext, fTextTarget.get(), clip, paint, viewMatrix, + fSurfaceProps, blob, x, y, filter, clipBounds); } void GrRenderTargetContext::discard() { diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h index b5293982fb..783b351b06 100644 --- a/src/gpu/GrRenderTargetContext.h +++ b/src/gpu/GrRenderTargetContext.h @@ -37,7 +37,6 @@ class GrTextureProxy; struct GrUserStencilSettings; class SkDrawFilter; struct SkDrawShadowRec; -class SkGlyphRunList; struct SkIPoint; struct SkIRect; class SkLatticeIter; @@ -68,9 +67,10 @@ public: const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset, const SkIRect& clipBounds); - virtual void drawGlyphRunList(const GrClip&, - const SkMatrix& viewMatrix, SkGlyphRunList*, - const SkIRect& clipBounds); + virtual void drawTextBlob(const GrClip&, const SkPaint&, + const SkMatrix& viewMatrix, const SkTextBlob*, + SkScalar x, SkScalar y, + SkDrawFilter*, const SkIRect& clipBounds); /** * Provides a perfomance hint that the render target's contents are allowed diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index d4f329dcb2..819acd2ef8 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -1624,13 +1624,14 @@ void SkGpuDevice::drawPosText(const void* text, size_t byteLength, this->devClipBounds()); } -void SkGpuDevice::drawGlyphRunList(SkGlyphRunList* list) { +void SkGpuDevice::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, + const SkPaint& paint, SkDrawFilter* drawFilter) { ASSERT_SINGLE_OWNER - GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawGlyphRunList", fContext.get()); + GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawTextBlob", fContext.get()); SkDEBUGCODE(this->validate();) - fRenderTargetContext->drawGlyphRunList( - this->clip(), this->ctm(), list, this->devClipBounds()); + fRenderTargetContext->drawTextBlob(this->clip(), paint, this->ctm(), blob, x, y, drawFilter, + this->devClipBounds()); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h index 0bd1c80346..7c7030e1ab 100644 --- a/src/gpu/SkGpuDevice.h +++ b/src/gpu/SkGpuDevice.h @@ -89,7 +89,8 @@ public: const SkPaint& paint) override; void drawPosText(const void* text, size_t len, const SkScalar pos[], int scalarsPerPos, const SkPoint& offset, const SkPaint&) override; - void drawGlyphRunList(SkGlyphRunList* list) override; + void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y, + const SkPaint& paint, SkDrawFilter* drawFilter) override; void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override; void drawShadow(const SkPath&, const SkDrawShadowRec&) override; void drawAtlas(const SkImage* atlas, const SkRSXform[], const SkRect[], diff --git a/src/gpu/text/GrTextBlobCache.h b/src/gpu/text/GrTextBlobCache.h index 7a8ea0bcfe..b41d401aee 100644 --- a/src/gpu/text/GrTextBlobCache.h +++ b/src/gpu/text/GrTextBlobCache.h @@ -55,20 +55,6 @@ public: blob->notifyAddedToCache(fUniqueID); return cacheBlob; } - sk_sp<GrTextBlob> makeBlob(SkGlyphRunList* glyphRunList) { - return GrTextBlob::Make(glyphRunList->totalGlyphCount(), glyphRunList->size()); - } - - sk_sp<GrTextBlob> makeCachedBlob(SkGlyphRunList* glyphRunList, - const GrTextBlob::Key& key, - const SkMaskFilterBase::BlurRec& blurRec, - const SkPaint& paint) { - sk_sp<GrTextBlob> cacheBlob(makeBlob(glyphRunList)); - cacheBlob->setupKey(key, blurRec, paint); - this->add(cacheBlob); - glyphRunList->temporaryShuntBlobnotifyAddedToCache(fUniqueID); - return cacheBlob; - } sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) const { const auto* idEntry = fBlobIDCache.find(key.fUniqueID); diff --git a/src/gpu/text/GrTextContext.cpp b/src/gpu/text/GrTextContext.cpp index 3309d22d09..a20ba4424a 100644 --- a/src/gpu/text/GrTextContext.cpp +++ b/src/gpu/text/GrTextContext.cpp @@ -84,48 +84,58 @@ SkScalerContextFlags GrTextContext::ComputeScalerContextFlags( } } -void GrTextContext::drawGlyphRunList( - GrContext* context, GrTextUtils::Target* target, const GrClip& clip, - const SkMatrix& viewMatrix, const SkSurfaceProps& props, SkGlyphRunList* glyphRunList, - const SkIRect& clipBounds) { - SkPoint origin = glyphRunList->origin(); - - // Get the first paint to use as the key paint. - const SkPaint& skPaint = (*glyphRunList)[0].paint(); +// TODO if this function ever shows up in profiling, then we can compute this value when the +// textblob is being built and cache it. However, for the time being textblobs mostly only have 1 +// run so this is not a big deal to compute here. +bool GrTextContext::HasLCD(const SkTextBlob* blob) { + SkTextBlobRunIterator it(blob); + for (; !it.done(); it.next()) { + if (it.isLCD()) { + return true; + } + } + return false; +} +void GrTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* target, + const GrClip& clip, const SkPaint& skPaint, + const SkMatrix& viewMatrix, const SkSurfaceProps& props, + const SkTextBlob* blob, SkScalar x, SkScalar y, + SkDrawFilter* drawFilter, const SkIRect& clipBounds) { // If we have been abandoned, then don't draw if (context->abandoned()) { return; } + sk_sp<GrTextBlob> cacheBlob; SkMaskFilterBase::BlurRec blurRec; + GrTextBlob::Key key; // It might be worth caching these things, but its not clear at this time // TODO for animated mask filters, this will fill up our cache. We need a safeguard here const SkMaskFilter* mf = skPaint.getMaskFilter(); - bool canCache = glyphRunList->canCache() && !(skPaint.getPathEffect() || - (mf && !as_MFB(mf)->asABlur(&blurRec))); + bool canCache = !(skPaint.getPathEffect() || + (mf && !as_MFB(mf)->asABlur(&blurRec)) || + drawFilter); SkScalerContextFlags scalerContextFlags = ComputeScalerContextFlags(target->colorSpaceInfo()); auto glyphCache = context->contextPriv().getGlyphCache(); GrTextBlobCache* textBlobCache = context->contextPriv().getTextBlobCache(); - sk_sp<GrTextBlob> cacheBlob; - GrTextBlob::Key key; if (canCache) { - bool hasLCD = glyphRunList->anyRunsLCD(); + bool hasLCD = HasLCD(blob); // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry SkPixelGeometry pixelGeometry = hasLCD ? props.pixelGeometry() : - kUnknown_SkPixelGeometry; + kUnknown_SkPixelGeometry; // TODO we want to figure out a way to be able to use the canonical color on LCD text, // see the note on ComputeCanonicalColor above. We pick a dummy value for LCD text to // ensure we always match the same key GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT : - ComputeCanonicalColor(skPaint, hasLCD); + ComputeCanonicalColor(skPaint, hasLCD); key.fPixelGeometry = pixelGeometry; - key.fUniqueID = glyphRunList->uniqueID(); + key.fUniqueID = blob->uniqueID(); key.fStyle = skPaint.getStyle(); key.fHasBlur = SkToBool(mf); key.fCanonicalColor = canonicalColor; @@ -135,77 +145,135 @@ void GrTextContext::drawGlyphRunList( GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo()); if (cacheBlob) { - if (cacheBlob->mustRegenerate(paint, blurRec, viewMatrix, origin.x(), origin.y())) { + if (cacheBlob->mustRegenerate(paint, blurRec, viewMatrix, x, y)) { // We have to remake the blob because changes may invalidate our masks. // TODO we could probably get away reuse most of the time if the pointer is unique, // but we'd have to clear the subrun information textBlobCache->remove(cacheBlob.get()); - cacheBlob = textBlobCache->makeCachedBlob(glyphRunList, key, blurRec, skPaint); - this->regenerateGlyphRunList(cacheBlob.get(), glyphCache, + cacheBlob = textBlobCache->makeCachedBlob(blob, key, blurRec, skPaint); + this->regenerateTextBlob(cacheBlob.get(), glyphCache, *context->contextPriv().caps()->shaderCaps(), paint, - scalerContextFlags, viewMatrix, props, glyphRunList); + scalerContextFlags, viewMatrix, props, blob, x, y, drawFilter); } else { textBlobCache->makeMRU(cacheBlob.get()); if (CACHE_SANITY_CHECK) { - int glyphCount = glyphRunList->totalGlyphCount(); - int runCount = glyphRunList->runCount(); + int glyphCount = 0; + int runCount = 0; + GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob); sk_sp<GrTextBlob> sanityBlob(textBlobCache->makeBlob(glyphCount, runCount)); sanityBlob->setupKey(key, blurRec, skPaint); - this->regenerateGlyphRunList( + this->regenerateTextBlob( sanityBlob.get(), glyphCache, *context->contextPriv().caps()->shaderCaps(), - paint, scalerContextFlags, viewMatrix, props, glyphRunList); + paint, scalerContextFlags, viewMatrix, props, blob, x, y, drawFilter); GrTextBlob::AssertEqual(*sanityBlob, *cacheBlob); } } } else { if (canCache) { - cacheBlob = textBlobCache->makeCachedBlob(glyphRunList, key, blurRec, skPaint); + cacheBlob = textBlobCache->makeCachedBlob(blob, key, blurRec, skPaint); } else { - cacheBlob = textBlobCache->makeBlob(glyphRunList); + cacheBlob = textBlobCache->makeBlob(blob); } - this->regenerateGlyphRunList(cacheBlob.get(), glyphCache, + this->regenerateTextBlob(cacheBlob.get(), glyphCache, *context->contextPriv().caps()->shaderCaps(), paint, - scalerContextFlags, viewMatrix, props, glyphRunList); + scalerContextFlags, viewMatrix, props, blob, x, y, drawFilter); } cacheBlob->flush(target, props, fDistanceAdjustTable.get(), paint, - clip, viewMatrix, clipBounds, origin.x(), origin.y()); + clip, viewMatrix, clipBounds, x, y); } -void GrTextContext::regenerateGlyphRunList(GrTextBlob* cacheBlob, +void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob, GrGlyphCache* glyphCache, const GrShaderCaps& shaderCaps, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, - const SkSurfaceProps& props, - SkGlyphRunList* glyphRunList) const { - SkPoint origin = glyphRunList->origin(); - cacheBlob->initReusableBlob(paint.luminanceColor(), viewMatrix, origin.x(), origin.y()); + const SkSurfaceProps& props, const SkTextBlob* blob, + SkScalar x, SkScalar y, + SkDrawFilter* drawFilter) const { + cacheBlob->initReusableBlob(paint.luminanceColor(), viewMatrix, x, y); // Regenerate textblob - SkGlyphRunListIterator it(glyphRunList); - GrTextUtils::RunPaint runPaint(&paint, nullptr); + SkTextBlobRunIterator it(blob); + GrTextUtils::RunPaint runPaint(&paint, drawFilter); for (int run = 0; !it.done(); it.next(), run++) { int glyphCount = it.glyphCount(); size_t textLen = glyphCount * sizeof(uint16_t); + const SkPoint& offset = it.offset(); cacheBlob->push_back_run(run); if (!runPaint.modifyForRun([it](SkPaint* p) { it.applyFontToPaint(p); })) { continue; } cacheBlob->setRunPaintFlags(run, runPaint.skPaint().getFlags()); - SkASSERT(it.positioning() == SkTextBlob::kFull_Positioning); if (CanDrawAsDistanceFields(runPaint, viewMatrix, props, shaderCaps.supportsDistanceFieldText(), fOptions)) { - this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, - scalerContextFlags, viewMatrix, (const char*)it.glyphs(), - textLen, it.pos(), 2, origin); + switch (it.positioning()) { + case SkTextBlob::kDefault_Positioning: { + auto origin = SkPoint::Make(x + offset.x(), y + offset.y()); + SkGlyphRunBuilder builder; + builder.prepareDrawText(runPaint.skPaint(), + (const char*)it.glyphs(), textLen, origin); + + auto glyphRun = builder.useGlyphRun(); + + 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)); + }); + break; + } + + case SkTextBlob::kHorizontal_Positioning: { + SkPoint dfOffset = SkPoint::Make(x, y + offset.y()); + this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, + scalerContextFlags, viewMatrix, (const char*)it.glyphs(), + textLen, it.pos(), 1, dfOffset); + break; + } + case SkTextBlob::kFull_Positioning: { + SkPoint dfOffset = SkPoint::Make(x, y); + this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, + scalerContextFlags, viewMatrix, (const char*)it.glyphs(), + textLen, it.pos(), 2, dfOffset); + break; + } + } } else { - DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, - viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2, - origin); + switch (it.positioning()) { + case SkTextBlob::kDefault_Positioning: { + auto origin = SkPoint::Make(x + offset.x(), y + offset.y()); + SkGlyphRunBuilder builder; + builder.prepareDrawText(runPaint.skPaint(), + (const char*)it.glyphs(), textLen, origin); + + auto glyphRun = builder.useGlyphRun(); + + glyphRun->temporaryShuntToCallback( + [&](size_t runSize, const char* glyphIDs, const SkScalar* pos) { + this->DrawBmpPosText( + cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, + viewMatrix, glyphIDs, 2 * runSize, + pos, 2, SkPoint::Make(0, 0)); + }); + break; + } + case SkTextBlob::kHorizontal_Positioning: + DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, + viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1, + SkPoint::Make(x, y + offset.y())); + break; + case SkTextBlob::kFull_Positioning: + DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, + viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2, + SkPoint::Make(x, y)); + break; + } } } } @@ -265,6 +333,7 @@ void GrTextContext::drawPosText(GrContext* context, GrTextUtils::Target* target, } } + void GrTextContext::DrawBmpPosText(GrTextBlob* blob, int runIndex, GrGlyphCache* glyphCache, const SkSurfaceProps& props, const GrTextUtils::Paint& paint, @@ -717,7 +786,6 @@ std::unique_ptr<GrDrawOp> GrTextContext::createOp_TestingOnly(GrContext* context builder.prepareDrawText(skPaint, text, textLen, origin); sk_sp<GrTextBlob> blob; - // TODO - remove shunt call when removing drawPosText from device. auto glyphRun = builder.useGlyphRun(); // Use the text and textLen below, because we don't want to mess with the paint. glyphRun->temporaryShuntToCallback( diff --git a/src/gpu/text/GrTextContext.h b/src/gpu/text/GrTextContext.h index 25aeea0c7a..dd82b3ce7d 100644 --- a/src/gpu/text/GrTextContext.h +++ b/src/gpu/text/GrTextContext.h @@ -48,9 +48,9 @@ public: const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset, const SkIRect& regionClipBounds); - void drawGlyphRunList(GrContext*, GrTextUtils::Target*, const GrClip&, - const SkMatrix& viewMatrix, const SkSurfaceProps&, SkGlyphRunList*, - const SkIRect& clipBounds); + void drawTextBlob(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&, + const SkMatrix& viewMatrix, const SkSurfaceProps&, const SkTextBlob*, + SkScalar x, SkScalar y, SkDrawFilter*, const SkIRect& clipBounds); std::unique_ptr<GrDrawOp> createOp_TestingOnly(GrContext*, GrTextContext*, @@ -115,15 +115,17 @@ private: static SkColor ComputeCanonicalColor(const SkPaint&, bool lcd); // Determines if we need to use fake gamma (and contrast boost): static SkScalerContextFlags ComputeScalerContextFlags(const GrColorSpaceInfo&); - - void regenerateGlyphRunList(GrTextBlob* bmp, + void regenerateTextBlob(GrTextBlob* bmp, GrGlyphCache*, const GrShaderCaps&, const GrTextUtils::Paint&, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, const SkSurfaceProps&, - SkGlyphRunList* glyphRunList) const; + const SkTextBlob* blob, SkScalar x, SkScalar y, + SkDrawFilter* drawFilter) const; + + static bool HasLCD(const SkTextBlob*); sk_sp<GrTextBlob> makeDrawPosTextBlob(GrTextBlobCache*, GrGlyphCache*, const GrShaderCaps&, diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 72d543c67e..45a9b95915 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -19,7 +19,6 @@ #include "SkDraw.h" #include "SkDrawFilter.h" #include "SkGlyphCache.h" -#include "SkGlyphRun.h" #include "SkImageFilterCache.h" #include "SkJpegEncoder.h" #include "SkMakeUnique.h" @@ -1459,12 +1458,17 @@ void SkPDFDevice::drawPosText(const void* text, size_t len, offset, paint, nullptr, 0, nullptr); } -void SkPDFDevice::drawGlyphRunList(SkGlyphRunList* glyphRunList) { - for (SkGlyphRunListIterator it(glyphRunList); !it.done(); it.next()) { - SkPaint runPaint; +void SkPDFDevice::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, + const SkPaint &paint, SkDrawFilter* drawFilter) { + for (SkTextBlobRunIterator it(blob); !it.done(); it.next()) { + SkPaint runPaint(paint); it.applyFontToPaint(&runPaint); + if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) { + continue; + } + SkPoint offset = it.offset() + SkPoint{x, y}; this->internalDrawText(it.glyphs(), sizeof(SkGlyphID) * it.glyphCount(), - it.pos(), it.positioning(), glyphRunList->origin(), runPaint, + it.pos(), it.positioning(), offset, runPaint, it.clusters(), it.textSize(), it.text()); } } diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h index 90f4b8e480..33d0e70e67 100644 --- a/src/pdf/SkPDFDevice.h +++ b/src/pdf/SkPDFDevice.h @@ -22,7 +22,6 @@ #include "SkTextBlob.h" #include "SkKeyedImage.h" -class SkGlyphRunList; class SkKeyedImage; class SkPath; class SkPDFArray; @@ -99,7 +98,8 @@ public: void drawPosText(const void* text, size_t len, const SkScalar pos[], int scalarsPerPos, const SkPoint& offset, const SkPaint&) override; - void drawGlyphRunList(SkGlyphRunList* glyphRunList) override; + void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y, + const SkPaint &, SkDrawFilter*) override; void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override; void drawDevice(SkBaseDevice*, int x, int y, const SkPaint&) override; diff --git a/tests/GlyphRunTest.cpp b/tests/GlyphRunTest.cpp index 8107f2075c..cd2a221719 100644 --- a/tests/GlyphRunTest.cpp +++ b/tests/GlyphRunTest.cpp @@ -75,7 +75,7 @@ DEF_TEST(GlyphRunBlob, reporter) { paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); SkGlyphRunBuilder runBuilder; - runBuilder.prepareTextBlob(font, *blob, SkPoint::Make(0, 0), nullptr); + runBuilder.prepareTextBlob(font, *blob, SkPoint::Make(0, 0)); auto runList = runBuilder.useGlyphRunList(); @@ -96,4 +96,4 @@ DEF_TEST(GlyphRunBlob, reporter) { runIndex += 1; } -} +}
\ No newline at end of file diff --git a/tests/SkRemoteGlyphCacheTest.cpp b/tests/SkRemoteGlyphCacheTest.cpp index 6986a7bb03..4a7bd86dc0 100644 --- a/tests/SkRemoteGlyphCacheTest.cpp +++ b/tests/SkRemoteGlyphCacheTest.cpp @@ -69,8 +69,6 @@ sk_sp<SkTextBlob> buildTextBlob(sk_sp<SkTypeface> tf, int glyphCount) { font.setStyle(SkPaint::kFill_Style); font.setHinting(SkPaint::kNormal_Hinting); font.setTextSize(1u); - font.setAntiAlias(true); - font.setSubpixelText(true); SkTextBlobBuilder builder; SkRect bounds = SkRect::MakeWH(10, 10); @@ -101,13 +99,12 @@ SkTextBlobCacheDiffCanvas::Settings MakeSettings(GrContext* context) { } SkBitmap RasterBlob(sk_sp<SkTextBlob> blob, int width, int height, const SkPaint& paint, - GrContext* context, const SkMatrix* matrix = nullptr, - SkScalar x = 0) { + GrContext* context, const SkMatrix* matrix = nullptr) { const SkImageInfo info = SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); auto surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info); if (matrix) surface->getCanvas()->concat(*matrix); - surface->getCanvas()->drawTextBlob(blob.get(), x, 0, paint); + surface->getCanvas()->drawTextBlob(blob.get(), 0u, 0u, paint); SkBitmap bitmap; bitmap.allocN32Pixels(width, height); surface->readPixels(bitmap, 0, 0); @@ -335,45 +332,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsPath, reporter, discardableManager->unlockAndDeleteAll(); } -DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextXY, reporter, ctxInfo) { - sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); - SkStrikeServer server(discardableManager.get()); - SkStrikeClient client(discardableManager, false); - SkPaint paint; - paint.setAntiAlias(true); - paint.setSubpixelText(true); - paint.setLCDRenderText(true); - - // Server. - auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); - auto serverTfData = server.serializeTypeface(serverTf.get()); - - int glyphCount = 10; - auto serverBlob = buildTextBlob(serverTf, glyphCount); - const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); - SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, SkMatrix::I(), props, &server, - MakeSettings(ctxInfo.grContext())); - cache_diff_canvas.drawTextBlob(serverBlob.get(), 0.5, 0, paint); - - std::vector<uint8_t> serverStrikeData; - server.writeStrikeData(&serverStrikeData); - - // Client. - auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()); - REPORTER_ASSERT(reporter, - client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); - auto clientBlob = buildTextBlob(clientTf, glyphCount); - - SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, ctxInfo.grContext(), nullptr, 0.5); - SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, ctxInfo.grContext(), nullptr, 0.5); - COMPARE_BLOBS(expected, actual, reporter); - REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss()); - SkStrikeCache::ValidateGlyphCacheDataSize(); - - // Must unlock everything on termination, otherwise valgrind complains about memory leaks. - discardableManager->unlockAndDeleteAll(); -} - DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsDFT, reporter, ctxInfo) { sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); SkStrikeServer server(discardableManager.get()); |