Smarter use of glyph cache

Change-Id: Ic9bea7310b375575503042881d9d54ff13996729
Reviewed-on: https://skia-review.googlesource.com/131924
Reviewed-by: Mike Klein <mtklein@chromium.org>
This commit is contained in:
Herb Derby 2018-06-04 15:49:15 -04:00 committed by Mike Klein
parent 975f8eeb44
commit 4ffa027cf6
7 changed files with 125 additions and 110 deletions

View File

@ -26,6 +26,7 @@ class SkDraw;
class SkDrawable; class SkDrawable;
class SkDrawFilter; class SkDrawFilter;
struct SkDrawShadowRec; struct SkDrawShadowRec;
class SkGlyphSet;
class SkImage; class SkImage;
class SkImageFilter; class SkImageFilter;
class SkMetaData; class SkMetaData;
@ -2709,6 +2710,8 @@ private:
void validateClip() const {} void validateClip() const {}
#endif #endif
std::unique_ptr<SkGlyphSet> fScratchGlyphSet;
typedef SkRefCnt INHERITED; typedef SkRefCnt INHERITED;
}; };

View File

@ -590,6 +590,8 @@ void SkCanvas::init(sk_sp<SkBaseDevice> device, InitFlags flags) {
device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect); device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
} }
fScratchGlyphSet = skstd::make_unique<SkGlyphSet>();
} }
SkCanvas::SkCanvas() SkCanvas::SkCanvas()
@ -2448,7 +2450,7 @@ void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkSca
while (iter.next()) { while (iter.next()) {
auto glyphRun = SkGlyphRun::MakeFromDrawText( auto glyphRun = SkGlyphRun::MakeFromDrawText(
looper.paint(), text, byteLength, SkPoint::Make(x, y)); looper.paint(), text, byteLength, SkPoint::Make(x, y), fScratchGlyphSet.get());
iter.fDevice->drawGlyphRun(looper.paint(), &glyphRun); iter.fDevice->drawGlyphRun(looper.paint(), &glyphRun);
} }
@ -2461,7 +2463,8 @@ void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
while (iter.next()) { while (iter.next()) {
auto glyphRun = SkGlyphRun::MakeFromDrawPosText(looper.paint(), text, byteLength, pos); auto glyphRun = SkGlyphRun::MakeFromDrawPosText(
looper.paint(), text, byteLength, pos, fScratchGlyphSet.get());
iter.fDevice->drawGlyphRun(looper.paint(), &glyphRun); iter.fDevice->drawGlyphRun(looper.paint(), &glyphRun);
} }
@ -2475,7 +2478,8 @@ void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScala
while (iter.next()) { while (iter.next()) {
auto glyphRun = auto glyphRun =
SkGlyphRun::MakeFromDrawPosTextH(looper.paint(), text, byteLength, xpos, constY); SkGlyphRun::MakeFromDrawPosTextH(
looper.paint(), text, byteLength, xpos, constY, fScratchGlyphSet.get());
iter.fDevice->drawGlyphRun(looper.paint(), &glyphRun); iter.fDevice->drawGlyphRun(looper.paint(), &glyphRun);
} }

View File

@ -160,10 +160,11 @@ void SkBaseDevice::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
switch (it.positioning()) { switch (it.positioning()) {
case SkTextBlob::kDefault_Positioning: { case SkTextBlob::kDefault_Positioning: {
SkGlyphSet glyphSet;
auto origin = SkPoint::Make(x + offset.x(), y + offset.y()); auto origin = SkPoint::Make(x + offset.x(), y + offset.y());
auto glyphRun = auto glyphRun =
SkGlyphRun::MakeFromDrawText(runPaint, SkGlyphRun::MakeFromDrawText(
(const char*) it.glyphs(), textLen, origin); runPaint, (const char*) it.glyphs(), textLen, origin, &glyphSet);
this->drawPosText( this->drawPosText(
it.glyphs(), textLen, glyphRun.getPositions(), 2, it.glyphs(), textLen, glyphRun.getPositions(), 2,
SkPoint::Make(0, 0), runPaint); SkPoint::Make(0, 0), runPaint);

View File

@ -21,61 +21,7 @@
namespace { namespace {
// A faster set implementation that does not need any initialization, and reading the set items static SkTypeface::Encoding convert_encoding(SkPaint::TextEncoding encoding) {
// 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
// for Sparse Sets"
class GlyphSet {
public:
GlyphSet(uint32_t glyphUniverseSize)
: fUniverseSize{glyphUniverseSize}
, fIndexes{skstd::make_unique_default<uint16_t[]>(2 * glyphUniverseSize)}
, fUniqueGlyphIDs{&fIndexes[glyphUniverseSize]} {
SkASSERT(glyphUniverseSize <= (1 << 16));
sk_msan_mark_initialized(fIndexes.get(), &fIndexes[glyphUniverseSize], "works with uninited");
}
uint16_t add(SkGlyphID glyphID) {
if (glyphID >= fUniverseSize) {
glyphID = kUndefGlyph;
}
auto index = fIndexes[glyphID];
if (index < fUniqueCount && fUniqueGlyphIDs[index] == glyphID) {
return index;
}
fUniqueGlyphIDs[fUniqueCount] = glyphID;
fIndexes[glyphID] = fUniqueCount;
fUniqueCount += 1;
return fUniqueCount - 1;
}
std::tuple<uint16_t, std::unique_ptr<SkGlyphID[]>> uniqueGlyphIDs() const {
auto uniqueGlyphs = skstd::make_unique_default<SkGlyphID[]>(fUniqueCount);
memcpy(uniqueGlyphs.get(), fUniqueGlyphIDs, fUniqueCount * sizeof(SkGlyphID));
return std::make_tuple(fUniqueCount, std::move(uniqueGlyphs));
}
private:
static constexpr SkGlyphID kUndefGlyph{0};
const uint32_t fUniverseSize;
uint16_t fUniqueCount{0};
std::unique_ptr<uint16_t[]> fIndexes;
SkGlyphID* fUniqueGlyphIDs;
};
template<typename T>
bool is_aligned(const void* ptr) {
uintptr_t bits = reinterpret_cast<uintptr_t>(ptr);
return (bits & (alignof(T) - 1)) == 0;
}
template<typename T>
bool is_aligned_size(size_t size) {
return size % sizeof(T) == 0;
}
SkTypeface::Encoding convert_encoding(SkPaint::TextEncoding encoding) {
switch (encoding) { switch (encoding) {
case SkPaint::kUTF8_TextEncoding: return SkTypeface::kUTF8_Encoding; case SkPaint::kUTF8_TextEncoding: return SkTypeface::kUTF8_Encoding;
case SkPaint::kUTF16_TextEncoding: return SkTypeface::kUTF16_Encoding; case SkPaint::kUTF16_TextEncoding: return SkTypeface::kUTF16_Encoding;
@ -84,32 +30,28 @@ SkTypeface::Encoding convert_encoding(SkPaint::TextEncoding encoding) {
} }
} }
using Core = std::tuple<size_t, std::unique_ptr<uint16_t[]>, using Core = std::tuple<size_t, std::unique_ptr<uint16_t[]>, std::vector<SkGlyphID>>;
uint16_t, std::unique_ptr<SkGlyphID[]>>;
Core make_from_glyphids(size_t glyphCount, const SkGlyphID* glyphs, SkGlyphID maxGlyphID) { Core make_from_glyphids(
if (glyphCount == 0) { return Core(0, nullptr, 0, nullptr); } size_t glyphCount, const SkGlyphID* glyphs, SkGlyphID maxGlyphID, SkGlyphSet* glyphSet) {
if (glyphCount == 0) { return Core(0, nullptr, std::vector<SkGlyphID>()); }
GlyphSet glyphSet{maxGlyphID}; glyphSet->reuse(maxGlyphID);
auto denseIndex = skstd::make_unique_default<uint16_t[]>(glyphCount); auto denseIndex = skstd::make_unique_default<uint16_t[]>(glyphCount);
for (size_t i = 0; i < glyphCount; i++) { for (size_t i = 0; i < glyphCount; i++) {
denseIndex[i] = glyphSet.add(glyphs[i]); denseIndex[i] = glyphSet->add(glyphs[i]);
} }
std::unique_ptr<SkGlyphID[]> uniqueGlyphIDs; return Core(glyphCount, std::move(denseIndex), glyphSet->uniqueGlyphIDs());
uint16_t uniqueCount;
std::tie(uniqueCount, uniqueGlyphIDs) = glyphSet.uniqueGlyphIDs();
return Core(glyphCount, std::move(denseIndex), uniqueCount, std::move(uniqueGlyphIDs));
} }
Core make_from_utfn(size_t byteLength, const void* utfN, const SkTypeface& typeface, Core make_from_utfn(size_t byteLength, const void* utfN, const SkTypeface& typeface,
SkTypeface::Encoding encoding) { SkTypeface::Encoding encoding, SkGlyphSet* glyphSet) {
auto count = SkUTFN_CountUnichars(encoding, utfN, byteLength); auto count = SkUTFN_CountUnichars(encoding, utfN, byteLength);
if (count <= 0) { if (count <= 0) {
return Core(0, nullptr, 0, nullptr); return Core(0, nullptr, std::vector<SkGlyphID>());
} }
auto glyphs = skstd::make_unique_default<SkGlyphID[]>(count); auto glyphs = skstd::make_unique_default<SkGlyphID[]>(count);
@ -117,17 +59,18 @@ Core make_from_utfn(size_t byteLength, const void* utfN, const SkTypeface& typef
// TODO: move to using cached version. // TODO: move to using cached version.
typeface.charsToGlyphs(utfN, encoding, glyphs.get(), count); typeface.charsToGlyphs(utfN, encoding, glyphs.get(), count);
return make_from_glyphids(count, glyphs.get(), typeface.countGlyphs()); return make_from_glyphids(count, glyphs.get(), typeface.countGlyphs(), glyphSet);
} }
Core make_core(const SkPaint& paint, const void* bytes, size_t byteLength) { Core make_core(const SkPaint& paint, const void* bytes, size_t byteLength, SkGlyphSet* glyphSet) {
auto encoding = paint.getTextEncoding(); auto encoding = paint.getTextEncoding();
auto typeface = SkPaintPriv::GetTypefaceOrDefault(paint); auto typeface = SkPaintPriv::GetTypefaceOrDefault(paint);
if (encoding == SkPaint::kGlyphID_TextEncoding) { if (encoding == SkPaint::kGlyphID_TextEncoding) {
return make_from_glyphids( return make_from_glyphids(
byteLength / 2, reinterpret_cast<const SkGlyphID*>(bytes), typeface->countGlyphs()); byteLength / 2, reinterpret_cast<const SkGlyphID*>(bytes),
typeface->countGlyphs(), glyphSet);
} else { } else {
return make_from_utfn(byteLength, bytes, *typeface, convert_encoding(encoding)); return make_from_utfn(byteLength, bytes, *typeface, convert_encoding(encoding), glyphSet);
} }
} }
@ -135,20 +78,20 @@ Core make_core(const SkPaint& paint, const void* bytes, size_t byteLength) {
SkGlyphRun SkGlyphRun::MakeFromDrawText( SkGlyphRun SkGlyphRun::MakeFromDrawText(
const SkPaint& paint, const void* bytes, size_t byteLength, const SkPaint& paint, const void* bytes, size_t byteLength,
const SkPoint origin) { const SkPoint origin, SkGlyphSet* glyphSet) {
size_t runSize; size_t runSize;
std::unique_ptr<uint16_t[]> denseIndex; std::unique_ptr<uint16_t[]> denseIndex;
uint16_t uniqueSize; std::vector<SkGlyphID> uniqueGlyphIDs;
std::unique_ptr<SkGlyphID[]> uniqueGlyphIDs; std::tie(runSize, denseIndex, uniqueGlyphIDs) = make_core(paint, bytes, byteLength, glyphSet);
std::tie(runSize, denseIndex, uniqueSize, uniqueGlyphIDs) = make_core(paint, bytes, byteLength);
if (runSize == 0) { return SkGlyphRun{}; } if (runSize == 0) { return SkGlyphRun{}; }
auto advances = skstd::make_unique_default<SkPoint[]>(uniqueSize); auto advances = skstd::make_unique_default<SkPoint[]>(uniqueGlyphIDs.size());
{ {
auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(paint); auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(paint);
cache->getAdvances(SkSpan<SkGlyphID>{uniqueGlyphIDs.get(), uniqueSize}, advances.get()); cache->getAdvances(SkSpan<SkGlyphID>{uniqueGlyphIDs.data(),
uniqueGlyphIDs.size()}, advances.get());
} }
auto positions = skstd::make_unique_default<SkPoint[]>(runSize); auto positions = skstd::make_unique_default<SkPoint[]>(runSize);
@ -171,17 +114,16 @@ SkGlyphRun SkGlyphRun::MakeFromDrawText(
} }
return SkGlyphRun{ return SkGlyphRun{
runSize, std::move(denseIndex), std::move(positions), uniqueSize, std::move(uniqueGlyphIDs)}; runSize, std::move(denseIndex), std::move(positions), std::move(uniqueGlyphIDs)};
} }
SkGlyphRun SkGlyphRun::MakeFromDrawPosTextH( SkGlyphRun SkGlyphRun::MakeFromDrawPosTextH(
const SkPaint& paint, const void* bytes, size_t byteLength, const SkPaint& paint, const void* bytes, size_t byteLength,
const SkScalar xpos[], SkScalar constY) { const SkScalar xpos[], SkScalar constY, SkGlyphSet* glyphSet) {
size_t runSize; size_t runSize;
std::unique_ptr<uint16_t[]> denseIndex; std::unique_ptr<uint16_t[]> denseIndex;
uint16_t uniqueSize; std::vector<SkGlyphID> uniqueGlyphIDs;
std::unique_ptr<SkGlyphID[]> uniqueGlyphIDs; std::tie(runSize, denseIndex, uniqueGlyphIDs) = make_core(paint, bytes, byteLength, glyphSet);
std::tie(runSize, denseIndex, uniqueSize, uniqueGlyphIDs) = make_core(paint, bytes, byteLength);
if (runSize == 0) { return SkGlyphRun{}; } if (runSize == 0) { return SkGlyphRun{}; }
@ -192,17 +134,16 @@ SkGlyphRun SkGlyphRun::MakeFromDrawPosTextH(
} }
return SkGlyphRun{ return SkGlyphRun{
runSize, std::move(denseIndex), std::move(positions), uniqueSize, std::move(uniqueGlyphIDs)}; runSize, std::move(denseIndex), std::move(positions), std::move(uniqueGlyphIDs)};
} }
SkGlyphRun SkGlyphRun::MakeFromDrawPosText( SkGlyphRun SkGlyphRun::MakeFromDrawPosText(
const SkPaint& paint, const void* bytes, size_t byteLength, const SkPaint& paint, const void* bytes, size_t byteLength,
const SkPoint pos[]) { const SkPoint pos[], SkGlyphSet* glyphSet) {
size_t runSize; size_t runSize;
std::unique_ptr<uint16_t[]> denseIndex; std::unique_ptr<uint16_t[]> denseIndex;
uint16_t uniqueSize; std::vector<SkGlyphID> uniqueGlyphIDs;
std::unique_ptr<SkGlyphID[]> uniqueGlyphIDs; std::tie(runSize, denseIndex, uniqueGlyphIDs) = make_core(paint, bytes, byteLength, glyphSet);
std::tie(runSize, denseIndex, uniqueSize, uniqueGlyphIDs) = make_core(paint, bytes, byteLength);
if (runSize == 0) { return SkGlyphRun{}; } if (runSize == 0) { return SkGlyphRun{}; }
@ -211,7 +152,7 @@ SkGlyphRun SkGlyphRun::MakeFromDrawPosText(
memcpy(positions.get(), pos, sizeof(SkPoint) * runSize); memcpy(positions.get(), pos, sizeof(SkPoint) * runSize);
return SkGlyphRun{ return SkGlyphRun{
runSize, std::move(denseIndex), std::move(positions), uniqueSize, std::move(uniqueGlyphIDs)}; runSize, std::move(denseIndex), std::move(positions), std::move(uniqueGlyphIDs)};
} }
std::unique_ptr<SkGlyphID[]> SkGlyphRun::copyGlyphIDs() const { std::unique_ptr<SkGlyphID[]> SkGlyphRun::copyGlyphIDs() const {
@ -227,10 +168,55 @@ std::unique_ptr<SkGlyphID[]> SkGlyphRun::copyGlyphIDs() const {
SkGlyphRun::SkGlyphRun(size_t runSize, SkGlyphRun::SkGlyphRun(size_t runSize,
std::unique_ptr<uint16_t[]>&& denseIndex, std::unique_ptr<uint16_t[]>&& denseIndex,
std::unique_ptr<SkPoint[]>&& positions, std::unique_ptr<SkPoint[]>&& positions,
uint16_t uniqueSize, std::vector<SkGlyphID>&& uniqueGlyphIDs)
std::unique_ptr<SkGlyphID[]>&& uniqueGlyphIDs)
: fDenseIndex{std::move(denseIndex)} : fDenseIndex{std::move(denseIndex)}
, fPositions{std::move(positions)} , fPositions{std::move(positions)}
, fUniqueGlyphs{std::move(uniqueGlyphIDs)} , fUniqueGlyphs{std::move(uniqueGlyphIDs)}
, fRunSize{runSize} , fRunSize{runSize} { }
, fUniqueSize{uniqueSize} { }
uint16_t SkGlyphSet::add(SkGlyphID glyphID) {
static constexpr SkGlyphID kUndefGlyph{0};
if (glyphID >= fUniverseSize) {
glyphID = kUndefGlyph;
}
if (glyphID >= fIndices.size()) {
fIndices.resize(glyphID + 1);
}
auto index = fIndices[glyphID];
if (index < fUniqueGlyphIDs.size() && fUniqueGlyphIDs[index] == glyphID) {
return index;
}
uint16_t newIndex = SkTo<uint16_t>(fUniqueGlyphIDs.size());
fUniqueGlyphIDs.push_back(glyphID);
fIndices[glyphID] = newIndex;
return newIndex;
}
std::vector<SkGlyphID> SkGlyphSet::uniqueGlyphIDs() {
return fUniqueGlyphIDs;
}
void SkGlyphSet::reuse(uint32_t glyphUniverseSize) {
SkASSERT(glyphUniverseSize <= (1 << 16));
fUniverseSize = glyphUniverseSize;
// If we're hanging onto these arrays for a long time, we don't want their size to drift
// endlessly upwards. It's unusual to see more than 256 unique glyphs used in a run,
// or a typeface with more than 4096 possible glyphs.
if (fUniqueGlyphIDs.size() > 256) {
fUniqueGlyphIDs.resize(256);
fUniqueGlyphIDs.shrink_to_fit();
}
fUniqueGlyphIDs.clear();
if (glyphUniverseSize < 4096 && fIndices.size() > 4096) {
fIndices.resize(4096);
fIndices.shrink_to_fit();
}
// No need to clear fIndices here... SkGlyphSet's set insertion algorithm is designed to work
// correctly even when the fIndexes buffer is uninitialized!
}

View File

@ -17,22 +17,39 @@
#include "SkPoint.h" #include "SkPoint.h"
#include "SkTypes.h" #include "SkTypes.h"
// 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
// for Sparse Sets"
class SkGlyphSet {
public:
SkGlyphSet() = default;
uint16_t add(SkGlyphID glyphID);
std::vector<SkGlyphID> uniqueGlyphIDs();
void reuse(uint32_t glyphUniverseSize);
private:
uint32_t fUniverseSize{0};
std::vector<uint16_t> fIndices;
std::vector<SkGlyphID> fUniqueGlyphIDs;
};
class SkGlyphRun { class SkGlyphRun {
public: public:
SkGlyphRun() = default; SkGlyphRun() = default;
SkGlyphRun(SkGlyphRun&&) = default; SkGlyphRun(SkGlyphRun&&) = default;
static SkGlyphRun MakeFromDrawText( static SkGlyphRun MakeFromDrawText(
const SkPaint& paint, const void* bytes, size_t byteLength, const SkPaint& paint, const void* bytes, size_t byteLength,
SkPoint origin); SkPoint origin, SkGlyphSet* glyphSet);
static SkGlyphRun MakeFromDrawPosTextH( static SkGlyphRun MakeFromDrawPosTextH(
const SkPaint& paint, const void* bytes, size_t byteLength, const SkPaint& paint, const void* bytes, size_t byteLength,
const SkScalar xpos[], SkScalar constY); const SkScalar xpos[], SkScalar constY, SkGlyphSet* glyphSet);
static SkGlyphRun MakeFromDrawPosText( static SkGlyphRun MakeFromDrawPosText(
const SkPaint& paint, const void* bytes, size_t byteLength, const SkPaint& paint, const void* bytes, size_t byteLength,
const SkPoint pos[]); const SkPoint pos[], SkGlyphSet* glyphSet);
size_t runSize() const { return fRunSize; } size_t runSize() const { return fRunSize; }
uint16_t uniqueSize() const { return fUniqueSize; } uint16_t uniqueSize() const { return fUniqueGlyphs.size(); }
// copyGlyphIDs is temporary glue to work with the existing system. Don't use with new code. // copyGlyphIDs is temporary glue to work with the existing system. Don't use with new code.
std::unique_ptr<SkGlyphID[]> copyGlyphIDs() const; std::unique_ptr<SkGlyphID[]> copyGlyphIDs() const;
@ -44,14 +61,12 @@ private:
SkGlyphRun(size_t runSize, SkGlyphRun(size_t runSize,
std::unique_ptr<uint16_t[]>&& denseIndex, std::unique_ptr<uint16_t[]>&& denseIndex,
std::unique_ptr<SkPoint[]>&& positions, std::unique_ptr<SkPoint[]>&& positions,
uint16_t uniqueSize, std::vector<SkGlyphID>&& uniqueGlyphIDs);
std::unique_ptr<SkGlyphID[]>&& uniqueGlyphIDs);
std::unique_ptr<uint16_t[]> fDenseIndex; std::unique_ptr<uint16_t[]> fDenseIndex;
std::unique_ptr<SkPoint[]> fPositions; std::unique_ptr<SkPoint[]> fPositions;
std::unique_ptr<SkGlyphID[]> fUniqueGlyphs; std::vector<SkGlyphID> fUniqueGlyphs;
const size_t fRunSize{0}; const size_t fRunSize{0};
const uint16_t fUniqueSize{0};
}; };
template <typename T> template <typename T>

View File

@ -210,10 +210,11 @@ void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob,
shaderCaps.supportsDistanceFieldText(), fOptions)) { shaderCaps.supportsDistanceFieldText(), fOptions)) {
switch (it.positioning()) { switch (it.positioning()) {
case SkTextBlob::kDefault_Positioning: { case SkTextBlob::kDefault_Positioning: {
SkGlyphSet glyphSet;
auto origin = SkPoint::Make(x + offset.x(), y + offset.y()); auto origin = SkPoint::Make(x + offset.x(), y + offset.y());
auto glyphRun = auto glyphRun =
SkGlyphRun::MakeFromDrawText(runPaint.skPaint(), SkGlyphRun::MakeFromDrawText(runPaint.skPaint(),
(const char*)it.glyphs(), textLen, origin); (const char*)it.glyphs(), textLen, origin, &glyphSet);
this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint,
scalerContextFlags, viewMatrix, (const char*)it.glyphs(), scalerContextFlags, viewMatrix, (const char*)it.glyphs(),
@ -239,10 +240,12 @@ void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob,
} else { } else {
switch (it.positioning()) { switch (it.positioning()) {
case SkTextBlob::kDefault_Positioning: { case SkTextBlob::kDefault_Positioning: {
SkGlyphSet glyphSet;
auto origin = SkPoint::Make(x + offset.x(), y + offset.y()); auto origin = SkPoint::Make(x + offset.x(), y + offset.y());
auto glyphRun = auto glyphRun =
SkGlyphRun::MakeFromDrawText( SkGlyphRun::MakeFromDrawText(
runPaint.skPaint(), (const char*) it.glyphs(), textLen, origin); runPaint.skPaint(), (const char*) it.glyphs(), textLen, origin,
&glyphSet);
this->DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, this->DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint,
scalerContextFlags, viewMatrix, (const char*) it.glyphs(), scalerContextFlags, viewMatrix, (const char*) it.glyphs(),
@ -758,8 +761,9 @@ std::unique_ptr<GrDrawOp> GrTextContext::createOp_TestingOnly(GrContext* context
// right now we don't handle textblobs, nor do we handle drawPosText. Since we only intend to // right now we don't handle textblobs, nor do we handle drawPosText. Since we only intend to
// test the text op with this unit test, that is okay. // test the text op with this unit test, that is okay.
SkGlyphSet glyphSet;
auto origin = SkPoint::Make(x, y); auto origin = SkPoint::Make(x, y);
auto glyphRun = SkGlyphRun::MakeFromDrawText(skPaint, text, textLen, origin); auto glyphRun = SkGlyphRun::MakeFromDrawText(skPaint, text, textLen, origin, &glyphSet);
sk_sp<GrTextBlob> blob(textContext->makeDrawPosTextBlob( sk_sp<GrTextBlob> blob(textContext->makeDrawPosTextBlob(
context->contextPriv().getTextBlobCache(), glyphCache, context->contextPriv().getTextBlobCache(), glyphCache,

View File

@ -16,5 +16,7 @@ DEF_TEST(GlyphRunInfo, reporter) {
SkPaint paint; SkPaint paint;
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
SkGlyphRun::MakeFromDrawText(paint, glyphs, count, SkPoint::Make(0, 0)); SkGlyphSet glyphSet;
SkGlyphRun::MakeFromDrawText(paint, glyphs, count, SkPoint::Make(0, 0), &glyphSet);
} }