aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-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;
+ }
+}