aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Herb Derby <herb@google.com>2018-06-21 16:03:47 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-06-28 03:36:16 +0000
commite2e52e46ca63540d429656baeee48fd3a402be26 (patch)
tree574c2f990282798988f47a5519a5ed5f3a990569 /src
parent0ce5ab9d3122bcd9dce65ecb51a0da973da09816 (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/core/SkCanvas.cpp13
-rw-r--r--src/core/SkDevice.cpp56
-rw-r--r--src/core/SkDevice.h7
-rw-r--r--src/core/SkGlyphRun.cpp136
-rw-r--r--src/core/SkGlyphRun.h100
-rw-r--r--src/core/SkRemoteGlyphCache.cpp23
-rw-r--r--src/core/SkTypeface_remote.h3
-rw-r--r--src/gpu/GrRenderTargetContext.cpp13
-rw-r--r--src/gpu/GrRenderTargetContext.h8
-rw-r--r--src/gpu/SkGpuDevice.cpp9
-rw-r--r--src/gpu/SkGpuDevice.h3
-rw-r--r--src/gpu/text/GrTextBlobCache.h14
-rw-r--r--src/gpu/text/GrTextContext.cpp156
-rw-r--r--src/gpu/text/GrTextContext.h14
-rw-r--r--src/pdf/SkPDFDevice.cpp14
-rw-r--r--src/pdf/SkPDFDevice.h4
16 files changed, 290 insertions, 283 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index b297f98156..c590d77cb7 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2453,8 +2453,7 @@ 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));
- auto glyphRun = fScratchGlyphRunBuilder->useGlyphRun();
- iter.fDevice->drawGlyphRun(looper.paint(), glyphRun);
+ fScratchGlyphRunBuilder->draw(iter.fDevice);
}
LOOPER_END
@@ -2467,8 +2466,7 @@ void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint
while (iter.next()) {
fScratchGlyphRunBuilder->prepareDrawPosText(looper.paint(), text, byteLength, pos);
- auto glyphRun = fScratchGlyphRunBuilder->useGlyphRun();
- iter.fDevice->drawGlyphRun(looper.paint(), glyphRun);
+ fScratchGlyphRunBuilder->draw(iter.fDevice);
}
LOOPER_END
@@ -2482,8 +2480,7 @@ void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScala
while (iter.next()) {
fScratchGlyphRunBuilder->prepareDrawPosTextH(
looper.paint(), text, byteLength, xpos, constY);
- const auto& glyphRun = fScratchGlyphRunBuilder->useGlyphRun();
- iter.fDevice->drawGlyphRun(looper.paint(), glyphRun);
+ fScratchGlyphRunBuilder->draw(iter.fDevice);
}
LOOPER_END
@@ -2536,7 +2533,9 @@ void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
while (iter.next()) {
- iter.fDevice->drawTextBlob(blob, x, y, looper.paint(), drawFilter);
+ fScratchGlyphRunBuilder->prepareTextBlob(
+ looper.paint(), *blob, SkPoint::Make(x, y), drawFilter);
+ fScratchGlyphRunBuilder->draw(iter.fDevice);
}
LOOPER_END
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 46404b2887..9fd61c9d28 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -141,53 +141,6 @@ 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;
@@ -252,11 +205,10 @@ void SkBaseDevice::drawImageLattice(const SkImage* image,
}
}
-void SkBaseDevice::drawGlyphRun(const SkPaint& paint, SkGlyphRun* glyphRun) {
- SkPaint glyphPaint(paint);
- glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-
- glyphRun->temporaryShuntToDrawPosText(glyphPaint, this);
+void SkBaseDevice::drawGlyphRunList(SkGlyphRunList* glyphRunList) {
+ for (auto& glyphRun : *glyphRunList) {
+ glyphRun.temporaryShuntToDrawPosText(this, glyphRunList->origin());
+ }
}
void SkBaseDevice::drawBitmapLattice(const SkBitmap& bitmap,
diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h
index f840cf6218..9a4086e51d 100644
--- a/src/core/SkDevice.h
+++ b/src/core/SkDevice.h
@@ -18,6 +18,7 @@ class SkBitmap;
class SkDrawFilter;
struct SkDrawShadowRec;
class SkGlyphRun;
+class SkGlyphRunList;
class SkGlyphRunBuilder;
class SkImageFilterCache;
struct SkIRect;
@@ -224,13 +225,10 @@ protected:
* Does not handle text decoration.
* Decorations (underline and stike-thru) will be handled by SkCanvas.
*/
- virtual void drawGlyphRun(const SkPaint& paint, SkGlyphRun* glyphRun);
+ virtual void drawGlyphRunList(SkGlyphRunList* glyphRunList);
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,
@@ -349,6 +347,7 @@ 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 ce1c336d88..583d676940 100644
--- a/src/core/SkGlyphRun.cpp
+++ b/src/core/SkGlyphRun.cpp
@@ -12,7 +12,7 @@
#include <tuple>
#include "SkDevice.h"
-#include "SkDraw.h"
+#include "SkDrawFilter.h"
#include "SkGlyphCache.h"
#include "SkMSAN.h"
#include "SkMakeUnique.h"
@@ -90,22 +90,23 @@ SkGlyphRun::SkGlyphRun(const SkIndexedRunInfo& runInfo,
size_t uniqueOffset, uint16_t uniqueSize,
SkSpan<SkGlyphID> scratchGlyphs,
SkSpan<const char> text,
- SkSpan<uint32_t> clusters)
+ SkSpan<const uint32_t> clusters,
+ SkPaint&& runPaint)
: fRunInfo{runInfo}
, fDenseOffset{denseOffset}, fDenseSize{denseSize}
, fUniqueOffset{uniqueOffset}, fUniqueSize{uniqueSize}
, fTemporaryShuntGlyphIDs{scratchGlyphs}
, fText{text}
- , fClusters{clusters} { }
+ , fClusters{clusters}
+ , fRunPaint{std::move(runPaint)} {}
-
-void SkGlyphRun::temporaryShuntToDrawPosText(const SkPaint& paint, SkBaseDevice* device) {
+void SkGlyphRun::temporaryShuntToDrawPosText(SkBaseDevice* device, SkPoint origin) {
auto pos = (const SkScalar*) this->positions().data();
device->drawPosText(
fTemporaryShuntGlyphIDs.data(), fDenseSize * sizeof(SkGlyphID),
- pos, 2, SkPoint::Make(0, 0), paint);
+ pos, 2, origin, fRunPaint);
}
void SkGlyphRun::temporaryShuntToCallback(TemporaryShuntCallback callback) {
@@ -115,19 +116,40 @@ void SkGlyphRun::temporaryShuntToCallback(TemporaryShuntCallback callback) {
}
// -- SkGlyphRunList -------------------------------------------------------------------------------
-SkGlyphRunList::SkGlyphRunList(SkSpan<SkGlyphRun> glyphRuns, uint64_t uniqueID)
- : fUniqueID{uniqueID}
- , fGlyphRuns{glyphRuns} { }
+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;
// -- SkGlyphRunBuilder ----------------------------------------------------------------------------
void SkGlyphRunBuilder::prepareDrawText(
const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin) {
this->initialize();
- 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>());
+ this->drawText(
+ paint, bytes, byteLength, origin, SkSpan<const char>(), SkSpan<const uint32_t>());
}
void SkGlyphRunBuilder::prepareDrawPosTextH(const SkPaint& paint, const void* bytes,
@@ -135,19 +157,22 @@ void SkGlyphRunBuilder::prepareDrawPosTextH(const SkPaint& paint, const void* by
SkScalar constY) {
this->initialize();
this->drawPosTextH(
- paint, bytes, byteLength, xpos, constY, SkSpan<const char>(), SkSpan<uint32_t>());
+ paint, bytes, byteLength, xpos, constY,
+ SkSpan<const char>(), SkSpan<const 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<uint32_t>());
+ this->drawPosText(paint, bytes, byteLength, pos,
+ SkSpan<const char>(), SkSpan<const uint32_t>());
}
void SkGlyphRunBuilder::prepareTextBlob(
- const SkPaint& paint, const SkTextBlob& blob, SkPoint origin) {
+ const SkPaint& paint, const SkTextBlob& blob, SkPoint origin, SkDrawFilter* drawFilter) {
this->initialize();
- fUniqueID = blob.uniqueID();
+ fTemporaryTextBlobShunt = &blob;
+ fOrigin = origin;
SkPaint runPaint = paint;
@@ -156,33 +181,44 @@ 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<uint32_t>(it.clusters(), it.glyphCount());
+ auto clusters = SkSpan<const 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: {
- auto dtOrigin = origin + offset;
- this->drawText(runPaint, it.glyphs(), glyphLen, dtOrigin, text, clusters);
+ this->drawText(runPaint, it.glyphs(), glyphLen, offset, text, clusters);
}
break;
case SkTextBlob::kHorizontal_Positioning: {
- auto constY = origin.y() + offset.y();
+ auto constY = 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;
+ }
}
}
@@ -193,22 +229,29 @@ SkGlyphRun* SkGlyphRunBuilder::useGlyphRun() {
}
SkGlyphRunList* SkGlyphRunBuilder::useGlyphRunList() {
- new ((void*)&fScratchGlyphRunList) SkGlyphRunList{SkSpan<SkGlyphRun>(fGlyphRuns), fUniqueID};
+ new ((void*)&fScratchGlyphRunList)
+ SkGlyphRunList{SkSpan<SkGlyphRun>(fGlyphRuns), fOrigin, fTemporaryTextBlobShunt};
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() {
- fUniqueID = 0;
+ fTemporaryTextBlobShunt = nullptr;
fDenseIndex.clear();
fPositions.clear();
fUniqueGlyphIDs.clear();
fGlyphRuns.clear();
fLastDenseIndex = 0;
fLastUniqueIndex = 0;
+ fOrigin = {0, 0};
}
SkGlyphID* SkGlyphRunBuilder::addDenseAndUnique(
@@ -245,10 +288,19 @@ SkGlyphID* SkGlyphRunBuilder::addDenseAndUnique(
}
void SkGlyphRunBuilder::addGlyphRunToList(
- SkGlyphID* temporaryShuntGlyphIDs, SkSpan<const char> text, SkSpan<uint32_t> clusters) {
+ const SkPaint& runPaint,
+ SkGlyphID* temporaryShuntGlyphIDs,
+ SkSpan<const char> text,
+ SkSpan<const 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();
@@ -258,7 +310,8 @@ void SkGlyphRunBuilder::addGlyphRunToList(
fLastUniqueIndex, SkTo<uint16_t>(uniqueSize),
SkSpan<SkGlyphID>(temporaryShuntGlyphIDs, runSize),
text,
- clusters);
+ clusters,
+ std::move(modifiedRunPaint));
fLastDenseIndex = fDenseIndex.size();
fLastUniqueIndex = fUniqueGlyphIDs.size();
@@ -267,7 +320,7 @@ void SkGlyphRunBuilder::addGlyphRunToList(
void SkGlyphRunBuilder::drawText(
const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin,
- SkSpan<const char> text, SkSpan<uint32_t> clusters) {
+ SkSpan<const char> text, SkSpan<const uint32_t> clusters) {
SkGlyphID* temporaryShuntGlyphIDs = this->addDenseAndUnique(paint, bytes, byteLength);
@@ -286,22 +339,22 @@ void SkGlyphRunBuilder::drawText(
}
if (paint.getTextAlign() != SkPaint::kLeft_Align) {
- SkVector len = endOfLastGlyph - origin;
+ SkVector runWidth = endOfLastGlyph - origin;
if (paint.getTextAlign() == SkPaint::kCenter_Align) {
- len.scale(SK_ScalarHalf);
+ runWidth.scale(SK_ScalarHalf);
}
for (size_t i = fLastDenseIndex; i < this->runSize(); i++) {
- fPositions[i] -= len;
+ fPositions[i] -= runWidth;
}
}
- this->addGlyphRunToList(temporaryShuntGlyphIDs, text, clusters);
+ this->addGlyphRunToList(paint, 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<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<const uint32_t> clusters) {
SkGlyphID* temporaryShuntGlyphIDs = this->addDenseAndUnique(paint, bytes, byteLength);
@@ -309,19 +362,20 @@ void SkGlyphRunBuilder::drawPosTextH(const SkPaint& paint, const void* bytes,
fPositions.push_back(SkPoint::Make(xpos[i], constY));
}
- this->addGlyphRunToList(temporaryShuntGlyphIDs, text, clusters);
+ this->addGlyphRunToList(paint, temporaryShuntGlyphIDs, text, clusters);
}
-void SkGlyphRunBuilder::drawPosText(const SkPaint& paint, const void* bytes,
- size_t byteLength, const SkPoint* pos,
- SkSpan<const char> text, SkSpan<uint32_t> 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) {
SkGlyphID* temporaryShuntGlyphIDs = this->addDenseAndUnique(paint, bytes, byteLength);
for (size_t i = 0; i < runSize(); i++) {
fPositions.push_back(pos[i]);
}
- this->addGlyphRunToList(temporaryShuntGlyphIDs, text, clusters);
+ this->addGlyphRunToList(paint, temporaryShuntGlyphIDs, text, clusters);
}
diff --git a/src/core/SkGlyphRun.h b/src/core/SkGlyphRun.h
index 739ad0bc38..6f9041c443 100644
--- a/src/core/SkGlyphRun.h
+++ b/src/core/SkGlyphRun.h
@@ -16,9 +16,11 @@
#include "SkMask.h"
#include "SkPath.h"
#include "SkPoint.h"
+#include "SkTextBlob.h"
#include "SkTypes.h"
class SkBaseDevice;
+class SkDrawFilter;
template <typename T>
class SkSpan {
@@ -74,11 +76,12 @@ public:
size_t fUniqueOffset, uint16_t fUniqueSize,
SkSpan<SkGlyphID> scratchGlyphs,
SkSpan<const char> text,
- SkSpan<uint32_t> clusters);
+ SkSpan<const uint32_t> clusters,
+ SkPaint&& runPaint);
// The temporaryShunt calls are to allow inter-operating with existing code while glyph runs
// are developed.
- void temporaryShuntToDrawPosText(const SkPaint& paint, SkBaseDevice* device);
+ void temporaryShuntToDrawPosText(SkBaseDevice* device, SkPoint origin);
using TemporaryShuntCallback = std::function<void(size_t, const char*, const SkScalar*)>;
void temporaryShuntToCallback(TemporaryShuntCallback callback);
@@ -90,6 +93,21 @@ 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;
@@ -103,18 +121,39 @@ 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<uint32_t> fClusters;
+ const SkSpan<const uint32_t> fClusters;
+ // Paint for this run modified to have glyph encoding and left alignment.
+ const SkPaint fRunPaint;
};
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;
- SkGlyphRunList(SkSpan<SkGlyphRun> glyphRuns, uint64_t uniqueID);
+ // 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;
+ }
- uint64_t uniqueID() const { return fUniqueID; }
+ SkPoint origin() const { return fOrigin; }
auto begin() -> decltype(fGlyphRuns.begin()) { return fGlyphRuns.begin(); }
auto end() -> decltype(fGlyphRuns.end()) { return fGlyphRuns.end(); }
@@ -122,6 +161,30 @@ 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
@@ -154,10 +217,14 @@ 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);
+ void prepareTextBlob(
+ const SkPaint& paint, const SkTextBlob& blob, SkPoint origin, SkDrawFilter* filter);
- SkGlyphRunList* useGlyphRunList();
+ void draw(SkBaseDevice* device);
+
+ // Public for testing only.
SkGlyphRun* useGlyphRun();
+ SkGlyphRunList* useGlyphRunList();
private:
size_t runSize() const;
@@ -165,20 +232,27 @@ private:
void initialize();
SkGlyphID* addDenseAndUnique(const SkPaint& paint, const void* bytes, size_t byteLength);
void addGlyphRunToList(
- SkGlyphID* temporaryShuntGlyphIDs, SkSpan<const char> text, SkSpan<uint32_t> clusters);
+ const SkPaint& runPaint,
+ SkGlyphID* temporaryShuntGlyphIDs,
+ SkSpan<const char> text,
+ SkSpan<const uint32_t> clusters);
void drawText(
const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin,
- SkSpan<const char> text, SkSpan<uint32_t> clusters);
+ SkSpan<const char> text, SkSpan<const uint32_t> clusters);
void drawPosTextH(
const SkPaint& paint, const void* bytes, size_t byteLength,
const SkScalar* xpos, SkScalar constY,
- SkSpan<const char> text, SkSpan<uint32_t> clusters);
+ SkSpan<const char> text, SkSpan<const uint32_t> clusters);
void drawPosText(
const SkPaint& paint, const void* bytes, size_t byteLength, const SkPoint* pos,
- SkSpan<const char> text, SkSpan<uint32_t> clusters);
+ SkSpan<const char> text, SkSpan<const uint32_t> clusters);
+
+ const SkTextBlob* fTemporaryTextBlobShunt{nullptr};
- uint64_t fUniqueID{0};
+ // The point passed into drawTextBlob. This allows the GPU back end to detect and adjust for
+ // translations.
+ SkPoint fOrigin;
std::vector<uint16_t> fDenseIndex;
std::vector<SkPoint> fPositions;
diff --git a/src/core/SkRemoteGlyphCache.cpp b/src/core/SkRemoteGlyphCache.cpp
index 774a1eb77c..18e47f3f4c 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,27 +240,20 @@ public:
}
protected:
- 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);
+ void drawGlyphRunList(SkGlyphRunList* glyphRunList) override {
+ SkPaint runPaint;
+ SkGlyphRunListIterator it(glyphRunList);
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(position, it, runPaint);
+ this->processGlyphRun(glyphRunList->origin(), it, runPaint);
}
}
private:
void processGlyphRun(const SkPoint& position,
- const SkTextBlobRunIterator& it,
+ const SkGlyphRunListIterator& it,
const SkPaint& runPaint) {
TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::processGlyphRun");
@@ -344,7 +337,7 @@ private:
}
}
- void processGlyphRunForPaths(const SkTextBlobRunIterator& it,
+ void processGlyphRunForPaths(const SkGlyphRunListIterator& it,
const SkPaint& runPaint,
const SkMatrix& runMatrix) {
TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::processGlyphRunForPaths");
@@ -394,7 +387,7 @@ private:
}
#if SK_SUPPORT_GPU
- bool processGlyphRunForDFT(const SkTextBlobRunIterator& it,
+ bool processGlyphRunForDFT(const SkGlyphRunListIterator& 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 47a68fd08d..f7326ccf7d 100644
--- a/src/core/SkTypeface_remote.h
+++ b/src/core/SkTypeface_remote.h
@@ -123,8 +123,7 @@ protected:
return 0;
}
int onCountGlyphs() const override {
- SK_ABORT("Should never be called.");
- return 0;
+ return this->glyphCount();
}
void* onGetCTFontRef() const override {
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 1dbde17575..9d31a0dde6 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -237,18 +237,17 @@ void GrRenderTargetContext::drawPosText(const GrClip& clip, const SkPaint& paint
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) {
+void GrRenderTargetContext::drawGlyphRunList(
+ const GrClip& clip, const SkMatrix& viewMatrix,
+ SkGlyphRunList* blob, const SkIRect& clipBounds) {
ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED
SkDEBUGCODE(this->validate();)
- GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextBlob", fContext);
+ GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawGlyphRunList", fContext);
GrTextContext* atlasTextContext = this->drawingManager()->getTextContext();
- atlasTextContext->drawTextBlob(fContext, fTextTarget.get(), clip, paint, viewMatrix,
- fSurfaceProps, blob, x, y, filter, clipBounds);
+ atlasTextContext->drawGlyphRunList(fContext, fTextTarget.get(), clip, viewMatrix,
+ fSurfaceProps, blob, clipBounds);
}
void GrRenderTargetContext::discard() {
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index 783b351b06..b5293982fb 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -37,6 +37,7 @@ class GrTextureProxy;
struct GrUserStencilSettings;
class SkDrawFilter;
struct SkDrawShadowRec;
+class SkGlyphRunList;
struct SkIPoint;
struct SkIRect;
class SkLatticeIter;
@@ -67,10 +68,9 @@ public:
const char text[], size_t byteLength, const SkScalar pos[],
int scalarsPerPosition, const SkPoint& offset,
const SkIRect& clipBounds);
- virtual void drawTextBlob(const GrClip&, const SkPaint&,
- const SkMatrix& viewMatrix, const SkTextBlob*,
- SkScalar x, SkScalar y,
- SkDrawFilter*, const SkIRect& clipBounds);
+ virtual void drawGlyphRunList(const GrClip&,
+ const SkMatrix& viewMatrix, SkGlyphRunList*,
+ 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 819acd2ef8..d4f329dcb2 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1624,14 +1624,13 @@ void SkGpuDevice::drawPosText(const void* text, size_t byteLength,
this->devClipBounds());
}
-void SkGpuDevice::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
- const SkPaint& paint, SkDrawFilter* drawFilter) {
+void SkGpuDevice::drawGlyphRunList(SkGlyphRunList* list) {
ASSERT_SINGLE_OWNER
- GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawTextBlob", fContext.get());
+ GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawGlyphRunList", fContext.get());
SkDEBUGCODE(this->validate();)
- fRenderTargetContext->drawTextBlob(this->clip(), paint, this->ctm(), blob, x, y, drawFilter,
- this->devClipBounds());
+ fRenderTargetContext->drawGlyphRunList(
+ this->clip(), this->ctm(), list, this->devClipBounds());
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index 7c7030e1ab..0bd1c80346 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -89,8 +89,7 @@ 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 drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
- const SkPaint& paint, SkDrawFilter* drawFilter) override;
+ void drawGlyphRunList(SkGlyphRunList* list) 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 b41d401aee..7a8ea0bcfe 100644
--- a/src/gpu/text/GrTextBlobCache.h
+++ b/src/gpu/text/GrTextBlobCache.h
@@ -55,6 +55,20 @@ 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 a20ba4424a..3309d22d09 100644
--- a/src/gpu/text/GrTextContext.cpp
+++ b/src/gpu/text/GrTextContext.cpp
@@ -84,58 +84,48 @@ SkScalerContextFlags GrTextContext::ComputeScalerContextFlags(
}
}
-// 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::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();
-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 = !(skPaint.getPathEffect() ||
- (mf && !as_MFB(mf)->asABlur(&blurRec)) ||
- drawFilter);
+ bool canCache = glyphRunList->canCache() && !(skPaint.getPathEffect() ||
+ (mf && !as_MFB(mf)->asABlur(&blurRec)));
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 = HasLCD(blob);
+ bool hasLCD = glyphRunList->anyRunsLCD();
// 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 = blob->uniqueID();
+ key.fUniqueID = glyphRunList->uniqueID();
key.fStyle = skPaint.getStyle();
key.fHasBlur = SkToBool(mf);
key.fCanonicalColor = canonicalColor;
@@ -145,135 +135,77 @@ void GrTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* target
GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo());
if (cacheBlob) {
- if (cacheBlob->mustRegenerate(paint, blurRec, viewMatrix, x, y)) {
+ if (cacheBlob->mustRegenerate(paint, blurRec, viewMatrix, origin.x(), origin.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(blob, key, blurRec, skPaint);
- this->regenerateTextBlob(cacheBlob.get(), glyphCache,
+ cacheBlob = textBlobCache->makeCachedBlob(glyphRunList, key, blurRec, skPaint);
+ this->regenerateGlyphRunList(cacheBlob.get(), glyphCache,
*context->contextPriv().caps()->shaderCaps(), paint,
- scalerContextFlags, viewMatrix, props, blob, x, y, drawFilter);
+ scalerContextFlags, viewMatrix, props, glyphRunList);
} else {
textBlobCache->makeMRU(cacheBlob.get());
if (CACHE_SANITY_CHECK) {
- int glyphCount = 0;
- int runCount = 0;
- GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob);
+ int glyphCount = glyphRunList->totalGlyphCount();
+ int runCount = glyphRunList->runCount();
sk_sp<GrTextBlob> sanityBlob(textBlobCache->makeBlob(glyphCount, runCount));
sanityBlob->setupKey(key, blurRec, skPaint);
- this->regenerateTextBlob(
+ this->regenerateGlyphRunList(
sanityBlob.get(), glyphCache, *context->contextPriv().caps()->shaderCaps(),
- paint, scalerContextFlags, viewMatrix, props, blob, x, y, drawFilter);
+ paint, scalerContextFlags, viewMatrix, props, glyphRunList);
GrTextBlob::AssertEqual(*sanityBlob, *cacheBlob);
}
}
} else {
if (canCache) {
- cacheBlob = textBlobCache->makeCachedBlob(blob, key, blurRec, skPaint);
+ cacheBlob = textBlobCache->makeCachedBlob(glyphRunList, key, blurRec, skPaint);
} else {
- cacheBlob = textBlobCache->makeBlob(blob);
+ cacheBlob = textBlobCache->makeBlob(glyphRunList);
}
- this->regenerateTextBlob(cacheBlob.get(), glyphCache,
+ this->regenerateGlyphRunList(cacheBlob.get(), glyphCache,
*context->contextPriv().caps()->shaderCaps(), paint,
- scalerContextFlags, viewMatrix, props, blob, x, y, drawFilter);
+ scalerContextFlags, viewMatrix, props, glyphRunList);
}
cacheBlob->flush(target, props, fDistanceAdjustTable.get(), paint,
- clip, viewMatrix, clipBounds, x, y);
+ clip, viewMatrix, clipBounds, origin.x(), origin.y());
}
-void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob,
+void GrTextContext::regenerateGlyphRunList(GrTextBlob* cacheBlob,
GrGlyphCache* glyphCache,
const GrShaderCaps& shaderCaps,
const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix,
- const SkSurfaceProps& props, const SkTextBlob* blob,
- SkScalar x, SkScalar y,
- SkDrawFilter* drawFilter) const {
- cacheBlob->initReusableBlob(paint.luminanceColor(), viewMatrix, x, y);
+ const SkSurfaceProps& props,
+ SkGlyphRunList* glyphRunList) const {
+ SkPoint origin = glyphRunList->origin();
+ cacheBlob->initReusableBlob(paint.luminanceColor(), viewMatrix, origin.x(), origin.y());
// Regenerate textblob
- SkTextBlobRunIterator it(blob);
- GrTextUtils::RunPaint runPaint(&paint, drawFilter);
+ SkGlyphRunListIterator it(glyphRunList);
+ GrTextUtils::RunPaint runPaint(&paint, nullptr);
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)) {
- 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;
- }
- }
+ this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint,
+ scalerContextFlags, viewMatrix, (const char*)it.glyphs(),
+ textLen, it.pos(), 2, origin);
} else {
- 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;
- }
+ DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags,
+ viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2,
+ origin);
}
}
}
@@ -333,7 +265,6 @@ void GrTextContext::drawPosText(GrContext* context, GrTextUtils::Target* target,
}
}
-
void GrTextContext::DrawBmpPosText(GrTextBlob* blob, int runIndex,
GrGlyphCache* glyphCache, const SkSurfaceProps& props,
const GrTextUtils::Paint& paint,
@@ -786,6 +717,7 @@ 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 dd82b3ce7d..25aeea0c7a 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 drawTextBlob(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&,
- const SkMatrix& viewMatrix, const SkSurfaceProps&, const SkTextBlob*,
- SkScalar x, SkScalar y, SkDrawFilter*, const SkIRect& clipBounds);
+ void drawGlyphRunList(GrContext*, GrTextUtils::Target*, const GrClip&,
+ const SkMatrix& viewMatrix, const SkSurfaceProps&, SkGlyphRunList*,
+ const SkIRect& clipBounds);
std::unique_ptr<GrDrawOp> createOp_TestingOnly(GrContext*,
GrTextContext*,
@@ -115,17 +115,15 @@ 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 regenerateTextBlob(GrTextBlob* bmp,
+
+ void regenerateGlyphRunList(GrTextBlob* bmp,
GrGlyphCache*,
const GrShaderCaps&,
const GrTextUtils::Paint&,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix,
const SkSurfaceProps&,
- const SkTextBlob* blob, SkScalar x, SkScalar y,
- SkDrawFilter* drawFilter) const;
-
- static bool HasLCD(const SkTextBlob*);
+ SkGlyphRunList* glyphRunList) const;
sk_sp<GrTextBlob> makeDrawPosTextBlob(GrTextBlobCache*, GrGlyphCache*,
const GrShaderCaps&,
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 45a9b95915..72d543c67e 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -19,6 +19,7 @@
#include "SkDraw.h"
#include "SkDrawFilter.h"
#include "SkGlyphCache.h"
+#include "SkGlyphRun.h"
#include "SkImageFilterCache.h"
#include "SkJpegEncoder.h"
#include "SkMakeUnique.h"
@@ -1458,17 +1459,12 @@ void SkPDFDevice::drawPosText(const void* text, size_t len,
offset, paint, nullptr, 0, nullptr);
}
-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);
+void SkPDFDevice::drawGlyphRunList(SkGlyphRunList* glyphRunList) {
+ for (SkGlyphRunListIterator it(glyphRunList); !it.done(); it.next()) {
+ SkPaint runPaint;
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(), offset, runPaint,
+ it.pos(), it.positioning(), glyphRunList->origin(), runPaint,
it.clusters(), it.textSize(), it.text());
}
}
diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h
index 33d0e70e67..90f4b8e480 100644
--- a/src/pdf/SkPDFDevice.h
+++ b/src/pdf/SkPDFDevice.h
@@ -22,6 +22,7 @@
#include "SkTextBlob.h"
#include "SkKeyedImage.h"
+class SkGlyphRunList;
class SkKeyedImage;
class SkPath;
class SkPDFArray;
@@ -98,8 +99,7 @@ public:
void drawPosText(const void* text, size_t len,
const SkScalar pos[], int scalarsPerPos,
const SkPoint& offset, const SkPaint&) override;
- void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
- const SkPaint &, SkDrawFilter*) override;
+ void drawGlyphRunList(SkGlyphRunList* glyphRunList) override;
void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override;
void drawDevice(SkBaseDevice*, int x, int y,
const SkPaint&) override;