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>
diff --git a/include/core/SkTextBlob.h b/include/core/SkTextBlob.h
index 9f4f10f..59151d3 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 @@
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 c590d77..b297f98 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2453,7 +2453,8 @@
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 @@
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 @@
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 @@
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 9fd61c9..46404b2 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -141,6 +141,53 @@
}
}
+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::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 9a4086e..f840cf6 100644
--- a/src/core/SkDevice.h
+++ b/src/core/SkDevice.h
@@ -18,7 +18,6 @@
class SkDrawFilter;
struct SkDrawShadowRec;
class SkGlyphRun;
-class SkGlyphRunList;
class SkGlyphRunBuilder;
class SkImageFilterCache;
struct SkIRect;
@@ -225,10 +224,13 @@
* 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 @@
// 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 583d676..ce1c336 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 @@
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 @@
}
// -- 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 @@
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 @@
// 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 @@
}
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 @@
}
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 @@
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::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 @@
}
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 @@
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 6f9041c..739ad0b 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 @@
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 @@
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 @@
// 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);
+ SkGlyphRunList(SkSpan<SkGlyphRun> glyphRuns, uint64_t uniqueID);
- 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;
- }
-
- 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 @@
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 @@
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 @@
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);
+ SkSpan<const char> text, SkSpan<uint32_t> clusters);
- const SkTextBlob* fTemporaryTextBlobShunt{nullptr};
-
- // 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 18e47f3..774a1eb 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 @@
}
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 @@
}
}
- 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 @@
}
#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 f7326cc..47a68fd 100644
--- a/src/core/SkTypeface_remote.h
+++ b/src/core/SkTypeface_remote.h
@@ -123,7 +123,8 @@
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 9d31a0d..1dbde17 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -237,17 +237,18 @@
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 b529398..783b351 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -37,7 +37,6 @@
struct GrUserStencilSettings;
class SkDrawFilter;
struct SkDrawShadowRec;
-class SkGlyphRunList;
struct SkIPoint;
struct SkIRect;
class SkLatticeIter;
@@ -68,9 +67,10 @@
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 d4f329d..819acd2 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1624,13 +1624,14 @@
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 0bd1c80..7c7030e 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -89,7 +89,8 @@
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 7a8ea0b..b41d401 100644
--- a/src/gpu/text/GrTextBlobCache.h
+++ b/src/gpu/text/GrTextBlobCache.h
@@ -55,20 +55,6 @@
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 3309d22..a20ba44 100644
--- a/src/gpu/text/GrTextContext.cpp
+++ b/src/gpu/text/GrTextContext.cpp
@@ -84,48 +84,58 @@
}
}
-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();
+// 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;
+}
- // Get the first paint to use as the key paint.
- const SkPaint& skPaint = (*glyphRunList)[0].paint();
-
+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 @@
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::DrawBmpPosText(GrTextBlob* blob, int runIndex,
GrGlyphCache* glyphCache, const SkSurfaceProps& props,
const GrTextUtils::Paint& paint,
@@ -717,7 +786,6 @@
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 25aeea0..dd82b3c 100644
--- a/src/gpu/text/GrTextContext.h
+++ b/src/gpu/text/GrTextContext.h
@@ -48,9 +48,9 @@
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 @@
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 72d543c..45a9b95 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 @@
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 90f4b8e..33d0e70 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 @@
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 8107f20..cd2a221 100644
--- a/tests/GlyphRunTest.cpp
+++ b/tests/GlyphRunTest.cpp
@@ -75,7 +75,7 @@
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 @@
runIndex += 1;
}
-}
+}
\ No newline at end of file
diff --git a/tests/SkRemoteGlyphCacheTest.cpp b/tests/SkRemoteGlyphCacheTest.cpp
index 6986a7b..4a7bd86 100644
--- a/tests/SkRemoteGlyphCacheTest.cpp
+++ b/tests/SkRemoteGlyphCacheTest.cpp
@@ -69,8 +69,6 @@
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 @@
}
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 @@
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());