Remove the SkGlyphRunInfo code

The SkGlyphRunInfo code caused most of the complication.
Maintaining the various different indices became
unwieldy.

Change-Id: Ia0a1259338c8572c57bb11d2407f5709459e0c72
Reviewed-on: https://skia-review.googlesource.com/140001
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
Herb Derby 2018-07-09 15:53:57 -04:00 committed by Skia Commit-Bot
parent 1d784ceafa
commit b77822b444
3 changed files with 90 additions and 165 deletions

View File

@ -165,7 +165,7 @@ void SkBaseDevice::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
SkGlyphRunBuilder builder;
builder.prepareDrawText(runPaint, (const char*) it.glyphs(), textLen, origin);
auto glyphRun = builder.useGlyphRun();
glyphRun->temporaryShuntToDrawPosText(runPaint, this);
glyphRun->temporaryShuntToDrawPosText(this);
}
break;
case SkTextBlob::kHorizontal_Positioning:
@ -255,7 +255,7 @@ void SkBaseDevice::drawGlyphRun(const SkPaint& paint, SkGlyphRun* glyphRun) {
SkPaint glyphPaint(paint);
glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
glyphRun->temporaryShuntToDrawPosText(glyphPaint, this);
glyphRun->temporaryShuntToDrawPosText(this);
}
void SkBaseDevice::drawBitmapLattice(const SkBitmap& bitmap,

View File

@ -85,33 +85,37 @@ void SkGlyphSet::reuse(uint32_t glyphUniverseSize, std::vector<SkGlyphID>* uniqu
}
// -- SkGlyphRun -----------------------------------------------------------------------------------
SkGlyphRun::SkGlyphRun(const SkIndexedRunInfo* runInfo,
size_t denseOffset, size_t denseSize,
size_t uniqueOffset, uint16_t uniqueSize,
SkSpan<SkGlyphID> scratchGlyphs,
SkGlyphRun::SkGlyphRun(SkPaint&& runPaint,
SkSpan<const uint16_t> denseIndices,
SkSpan<const SkPoint> positions,
SkSpan<const SkGlyphID> glyphIDs,
SkSpan<const SkGlyphID> uniqueGlyphIDs,
SkSpan<const char> text,
SkSpan<uint32_t> clusters)
: fRunInfo{runInfo}
, fDenseOffset{denseOffset}, fDenseSize{denseSize}
, fUniqueOffset{uniqueOffset}, fUniqueSize{uniqueSize}
, fTemporaryShuntGlyphIDs{scratchGlyphs}
SkSpan<const uint32_t> clusters)
: fUniqueGlyphIDIndices{denseIndices}
, fPositions{positions}
, fTemporaryShuntGlyphIDs{glyphIDs}
, fUniqueGlyphIDs{uniqueGlyphIDs}
, fText{text}
, fClusters{clusters} { }
, fClusters{clusters}
, fRunPaint{std::move(runPaint)} {}
void SkGlyphRun::temporaryShuntToDrawPosText(const SkPaint& paint, SkBaseDevice* device) {
void SkGlyphRun::temporaryShuntToDrawPosText(SkBaseDevice* device) {
auto pos = (const SkScalar*) this->positions().data();
auto origin = SkPoint::Make(0, 0);
device->drawPosText(
fTemporaryShuntGlyphIDs.data(), fDenseSize * sizeof(SkGlyphID),
pos, 2, SkPoint::Make(0, 0), paint);
if (!fTemporaryShuntGlyphIDs.empty()) {
device->drawPosText(
fTemporaryShuntGlyphIDs.data(), fTemporaryShuntGlyphIDs.size() * sizeof(SkGlyphID),
pos, 2, origin, fRunPaint);
}
}
void SkGlyphRun::temporaryShuntToCallback(TemporaryShuntCallback callback) {
auto bytes = (const char *)fTemporaryShuntGlyphIDs.data();
auto pos = (const SkScalar*) this->positions().data();
callback(this->runSize(), bytes, pos);
callback(fTemporaryShuntGlyphIDs.size(), bytes, pos);
}
// -- SkGlyphRunBuilder ----------------------------------------------------------------------------
@ -122,7 +126,7 @@ void SkGlyphRunBuilder::prepareDrawText(
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, originalText, SkSpan<const uint32_t>());
}
void SkGlyphRunBuilder::prepareDrawPosTextH(const SkPaint& paint, const void* bytes,
@ -130,75 +134,31 @@ 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>());
}
void SkGlyphRunBuilder::prepareTextBlob(
const SkPaint& paint, const SkTextBlob& blob, SkPoint origin) {
this->initialize();
fUniqueID = blob.uniqueID();
SkPaint runPaint = paint;
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);
// 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());
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);
}
break;
case SkTextBlob::kHorizontal_Positioning: {
auto constY = origin.y() + offset.y();
this->drawPosTextH(
runPaint, it.glyphs(), glyphLen, it.pos(), constY, text, clusters);
}
break;
case SkTextBlob::kFull_Positioning:
this->drawPosText(
runPaint, it.glyphs(), glyphLen, (const SkPoint*)it.pos(), text, clusters);
break;
default:
SK_ABORT("unhandled positioning mode");
}
}
this->drawPosText(paint, bytes, byteLength, pos,
SkSpan<const char>(), SkSpan<const uint32_t>());
}
SkGlyphRun* SkGlyphRunBuilder::useGlyphRun() {
return &fScratchGlyphRun;
}
size_t SkGlyphRunBuilder::runSize() const { return fDenseIndex.size() - fLastDenseIndex; }
size_t SkGlyphRunBuilder::uniqueSize() const { return fUniqueGlyphIDs.size() - fLastUniqueIndex; }
void SkGlyphRunBuilder::initialize() {
fUniqueID = 0;
fDenseIndex.clear();
fPositions.clear();
fUniqueGlyphIDs.clear();
fLastDenseIndex = 0;
fLastUniqueIndex = 0;
// Be sure to clean up the last run before we reuse it.
fScratchGlyphRun.~SkGlyphRun();
}
SkGlyphID* SkGlyphRunBuilder::addDenseAndUnique(
void SkGlyphRunBuilder::addDenseAndUnique(
const SkPaint& paint, const void* bytes, size_t byteLength) {
size_t runSize = 0;
@ -227,50 +187,47 @@ SkGlyphID* SkGlyphRunBuilder::addDenseAndUnique(
fDenseIndex.push_back(fGlyphSet.add(glyphIDs[i]));
}
}
return glyphIDs;
}
void SkGlyphRunBuilder::makeGlyphRun(
SkGlyphID* temporaryShuntGlyphIDs, SkSpan<const char> text, SkSpan<uint32_t> clusters) {
const SkPaint& runPaint,
SkSpan<const char> text, SkSpan<const uint32_t> clusters) {
// Ignore empty runs.
if (fDenseIndex.size() != fLastDenseIndex) {
auto runSize = this->runSize();
auto uniqueSize = this->uniqueSize();
if (!fDenseIndex.empty()) {
SkPaint glyphRunPaint{runPaint};
glyphRunPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
glyphRunPaint.setTextAlign(SkPaint::kLeft_Align);
new ((void*)&fScratchGlyphRun) SkGlyphRun{
&fIndexed,
fLastDenseIndex, runSize,
fLastUniqueIndex, SkTo<uint16_t>(uniqueSize),
SkSpan<SkGlyphID>(temporaryShuntGlyphIDs, runSize),
std::move(glyphRunPaint),
SkSpan<const uint16_t>{fDenseIndex},
SkSpan<const SkPoint>{fPositions},
SkSpan<const SkGlyphID>{fScratchGlyphIDs},
SkSpan<const SkGlyphID>{fUniqueGlyphIDs},
text,
clusters
};
fLastDenseIndex = fDenseIndex.size();
fLastUniqueIndex = fUniqueGlyphIDs.size();
}
}
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);
this->addDenseAndUnique(paint, bytes, byteLength);
fScratchAdvances.resize(this->uniqueSize());
fScratchAdvances.resize(fUniqueGlyphIDs.size());
{
auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(paint);
cache->getAdvances(
fIndexed.uniqueGlyphIDs(fLastUniqueIndex, uniqueSize()), fScratchAdvances.data());
cache->getAdvances(SkSpan<const SkGlyphID>{fUniqueGlyphIDs}, fScratchAdvances.data());
}
SkPoint endOfLastGlyph = origin;
for (size_t i = 0; i < this->runSize(); i++) {
for (size_t i = 0; i < fDenseIndex.size(); i++) {
fPositions.push_back(endOfLastGlyph);
endOfLastGlyph += fScratchAdvances[fDenseIndex[fLastDenseIndex + i]];
endOfLastGlyph += fScratchAdvances[fDenseIndex[i]];
}
if (paint.getTextAlign() != SkPaint::kLeft_Align) {
@ -278,38 +235,38 @@ void SkGlyphRunBuilder::drawText(
if (paint.getTextAlign() == SkPaint::kCenter_Align) {
len.scale(SK_ScalarHalf);
}
for (size_t i = fLastDenseIndex; i < this->runSize(); i++) {
for (size_t i = 0; i < fDenseIndex.size(); i++) {
fPositions[i] -= len;
}
}
this->makeGlyphRun(temporaryShuntGlyphIDs, text, clusters);
this->makeGlyphRun(paint, 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) {
SkSpan<const char> text, SkSpan<const uint32_t> clusters) {
SkGlyphID* temporaryShuntGlyphIDs = this->addDenseAndUnique(paint, bytes, byteLength);
this->addDenseAndUnique(paint, bytes, byteLength);
for (size_t i = 0; i < runSize(); i++) {
for (size_t i = 0; i < fDenseIndex.size(); i++) {
fPositions.push_back(SkPoint::Make(xpos[i], constY));
}
this->makeGlyphRun(temporaryShuntGlyphIDs, text, clusters);
this->makeGlyphRun(paint, 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) {
SkGlyphID* temporaryShuntGlyphIDs = this->addDenseAndUnique(paint, bytes, byteLength);
SkSpan<const char> text, SkSpan<const uint32_t> clusters) {
this->addDenseAndUnique(paint, bytes, byteLength);
for (size_t i = 0; i < runSize(); i++) {
for (size_t i = 0; i < fDenseIndex.size(); i++) {
fPositions.push_back(pos[i]);
}
this->makeGlyphRun(temporaryShuntGlyphIDs, text, clusters);
this->makeGlyphRun(paint, text, clusters);
}

View File

@ -25,7 +25,8 @@ class SkSpan {
public:
SkSpan() : fPtr{nullptr}, fSize{0} {}
SkSpan(T* ptr, ptrdiff_t size) : fPtr{ptr}, fSize{size} { SkASSERT(size >= 0); }
explicit SkSpan(std::vector<T>& v) : fPtr{v.data()}, fSize{SkTo<ptrdiff_t>(v.size())} {}
template <typename U>
explicit SkSpan(std::vector<U>& v) : fPtr{v.data()}, fSize{SkTo<ptrdiff_t>(v.size())} {}
SkSpan(const SkSpan<T>& o) = default;
SkSpan& operator=( const SkSpan& other ) = default;
T& operator [] (ptrdiff_t i) const { return fPtr[i]; }
@ -42,70 +43,44 @@ private:
ptrdiff_t fSize;
};
struct SkIndexedRunInfo {
SkIndexedRunInfo(const std::vector<uint16_t>* denseIndex,
const std::vector<SkPoint>* positions,
const std::vector<SkGlyphID>* uniqueGlyphIDs)
: fDenseIndex{denseIndex}
, fPositions{positions}
, fUniqueGlyphIDs{uniqueGlyphIDs} {}
SkSpan<const uint16_t> denseIndex(size_t start, size_t size) {
return SkSpan<const uint16_t>(&(*fDenseIndex)[start], size);
}
SkSpan<const SkPoint> positions(size_t start, size_t size) const {
return SkSpan<const SkPoint>(&(*fPositions)[start], size);
}
SkSpan<const SkGlyphID> uniqueGlyphIDs(size_t start, size_t size) const {
return SkSpan<const SkGlyphID>(&(*fUniqueGlyphIDs)[start], size);
}
private:
const std::vector<uint16_t>* fDenseIndex;
const std::vector<SkPoint>* fPositions;
const std::vector<SkGlyphID>* fUniqueGlyphIDs;
};
class SkGlyphRun {
public:
SkGlyphRun() = default;
SkGlyphRun(const SkIndexedRunInfo* runInfo,
size_t denseOffset, size_t denseSize,
size_t fUniqueOffset, uint16_t fUniqueSize,
SkSpan<SkGlyphID> scratchGlyphs,
SkGlyphRun(SkPaint&& runPaint,
SkSpan<const uint16_t> denseIndices,
SkSpan<const SkPoint> positions,
SkSpan<const SkGlyphID> glyphIDs,
SkSpan<const SkGlyphID> uniqueGlyphIDs,
SkSpan<const char> text,
SkSpan<uint32_t> clusters);
SkSpan<const uint32_t> clusters);
// 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);
using TemporaryShuntCallback = std::function<void(size_t, const char*, const SkScalar*)>;
void temporaryShuntToCallback(TemporaryShuntCallback callback);
size_t runSize() const { return fDenseSize; }
uint16_t uniqueSize() const { return fUniqueSize; }
SkSpan<const SkPoint> positions() const {
return fRunInfo->positions(fDenseOffset, fDenseSize);
}
SkSpan<const SkGlyphID> uniqueGlyphIDs() const {
return fRunInfo->uniqueGlyphIDs(fUniqueOffset, fUniqueSize);
}
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; }
private:
const SkIndexedRunInfo* fRunInfo;
size_t fDenseOffset;
size_t fDenseSize;
size_t fUniqueOffset;
uint16_t fUniqueSize;
//
const SkSpan<const uint16_t> fUniqueGlyphIDIndices;
//
const SkSpan<const SkPoint> fPositions;
// This is temporary while converting from the old per glyph code to the bulk code.
const SkSpan<SkGlyphID> fTemporaryShuntGlyphIDs;
const SkSpan<const SkGlyphID> fTemporaryShuntGlyphIDs;
// The unique glyphs from fTemporaryShuntGlyphIDs.
const SkSpan<const SkGlyphID> fUniqueGlyphIDs;
// 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;
};
// A faster set implementation that does not need any initialization, and reading the set items
@ -145,41 +120,34 @@ public:
SkGlyphRun* useGlyphRun();
private:
size_t runSize() const;
size_t uniqueSize() const;
void initialize();
SkGlyphID* addDenseAndUnique(const SkPaint& paint, const void* bytes, size_t byteLength);
void addDenseAndUnique(const SkPaint& paint, const void* bytes, size_t byteLength);
void makeGlyphRun(
SkGlyphID* temporaryShuntGlyphIDs, SkSpan<const char> text, SkSpan<uint32_t> clusters);
const SkPaint& runPaint, 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);
uint64_t fUniqueID{0};
uint64_t fUniqueID{0};
std::vector<uint16_t> fDenseIndex;
std::vector<SkPoint> fPositions;
std::vector<uint16_t> fDenseIndex;
std::vector<SkPoint> fPositions;
std::vector<SkGlyphID> fUniqueGlyphIDs;
SkIndexedRunInfo fIndexed{&fDenseIndex, &fPositions, &fUniqueGlyphIDs};
size_t fLastDenseIndex{0};
size_t fLastUniqueIndex{0};
// 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;
// Used as temporary storage for calculating positions for drawText.
std::vector<SkPoint> fScratchAdvances;
std::vector<SkPoint> fScratchAdvances;
// Used as temporary glyph run for the rest of the Text stack.