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