Use simple buffers instead of vectors

Start using simple buffers, these will be used for
multiple runs latter on.

Change-Id: Iab0559d5a47eb5e54254a985051d5d25a91be69f
Reviewed-on: https://skia-review.googlesource.com/140791
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
Herb Derby 2018-07-09 17:06:09 -04:00 committed by Skia Commit-Bot
parent 8b5092671b
commit ff19d3473b
5 changed files with 66 additions and 35 deletions

View File

@ -131,9 +131,9 @@ const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFi
} }
void SkGlyphCache::getAdvances(SkSpan<const SkGlyphID> glyphIDs, SkPoint advances[]) { void SkGlyphCache::getAdvances(SkSpan<const SkGlyphID> glyphIDs, SkPoint advances[]) {
for (ptrdiff_t i = 0; i < glyphIDs.size(); i++) { for (auto glyphID : glyphIDs) {
auto glyph = this->getGlyphIDAdvance(glyphIDs[i]); auto glyph = this->getGlyphIDAdvance(glyphID);
advances[i] = SkPoint::Make(glyph.fAdvanceX, glyph.fAdvanceY); *advances++ = SkPoint::Make(glyph.fAdvanceX, glyph.fAdvanceY);
} }
} }

View File

@ -91,7 +91,7 @@ SkSpan<const SkGlyphID> SkGlyphIDSet::uniquifyGlyphIDs(
// If the following bzero becomes a performance problem, the memory can be marked as // If the following bzero becomes a performance problem, the memory can be marked as
// initialized for valgrind and msan. // initialized for valgrind and msan.
// valgrind = VALGRIND_MAKE_MEM_DEFINED(fUniverseToUnique, universeSize * sizeof(SkGlyphID)) // valgrind = VALGRIND_MAKE_MEM_DEFINED(fUniverseToUnique, universeSize * sizeof(SkGlyphID))
// msan = sk_msan_assert_initialized(fUniverseToUnique, universeSize * sizeof(SkGlyphID)) // msan = sk_msan_mark_initialized(fUniverseToUnique, universeSize * sizeof(SkGlyphID))
sk_bzero(fUniverseToUnique, universeSize * sizeof(SkGlyphID)); sk_bzero(fUniverseToUnique, universeSize * sizeof(SkGlyphID));
} }
@ -168,10 +168,12 @@ SkGlyphRun* SkGlyphRunBuilder::useGlyphRun() {
void SkGlyphRunBuilder::initialize(size_t totalRunSize) { void SkGlyphRunBuilder::initialize(size_t totalRunSize) {
fUniqueID = 0; fUniqueID = 0;
// Using resize is temporary until simpler buffers are in place. if (totalRunSize > fMaxTotalRunSize) {
fDenseIndex.resize(totalRunSize); fMaxTotalRunSize = totalRunSize;
fPositions.resize(totalRunSize); fUniqueGlyphIDIndices.reset(fMaxTotalRunSize);
fUniqueGlyphIDs.resize(totalRunSize); fPositions.reset(fMaxTotalRunSize);
fUniqueGlyphIDs.reset(fMaxTotalRunSize);
}
// Be sure to clean up the last run before we reuse it. // Be sure to clean up the last run before we reuse it.
fScratchGlyphRun.~SkGlyphRun(); fScratchGlyphRun.~SkGlyphRun();
@ -207,7 +209,7 @@ SkSpan<const SkGlyphID> SkGlyphRunBuilder::addDenseAndUnique(
// There better be glyphs in the font if we want to uniqify. // There better be glyphs in the font if we want to uniqify.
if (glyphUniverseSize > 0) { if (glyphUniverseSize > 0) {
uniquifiedGlyphIDs = fGlyphIDSet.uniquifyGlyphIDs( uniquifiedGlyphIDs = fGlyphIDSet.uniquifyGlyphIDs(
glyphUniverseSize, glyphIDs, fUniqueGlyphIDs.data(), fDenseIndex.data()); glyphUniverseSize, glyphIDs, fUniqueGlyphIDs, fUniqueGlyphIDIndices);
} }
} }
@ -218,21 +220,23 @@ void SkGlyphRunBuilder::makeGlyphRun(
const SkPaint& runPaint, const SkPaint& runPaint,
SkSpan<const SkGlyphID> glyphIDs, SkSpan<const SkGlyphID> glyphIDs,
SkSpan<const SkPoint> positions, SkSpan<const SkPoint> positions,
SkSpan<const uint16_t> uniqueGlyphIDIndices,
SkSpan<const SkGlyphID> uniqueGlyphIDs,
SkSpan<const char> text, SkSpan<const char> text,
SkSpan<const uint32_t> clusters) { SkSpan<const uint32_t> clusters) {
// Ignore empty runs. // Ignore empty runs.
if (!fDenseIndex.empty()) { if (!glyphIDs.empty()) {
SkPaint glyphRunPaint{runPaint}; SkPaint glyphRunPaint{runPaint};
glyphRunPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); glyphRunPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
glyphRunPaint.setTextAlign(SkPaint::kLeft_Align); glyphRunPaint.setTextAlign(SkPaint::kLeft_Align);
new ((void*)&fScratchGlyphRun) SkGlyphRun{ new ((void*)&fScratchGlyphRun) SkGlyphRun{
std::move(glyphRunPaint), std::move(glyphRunPaint),
SkSpan<const uint16_t>{fDenseIndex}, uniqueGlyphIDIndices,
positions, positions,
glyphIDs, glyphIDs,
SkSpan<const SkGlyphID>{fUniqueGlyphIDs}, uniqueGlyphIDs,
text, text,
clusters clusters
}; };
@ -244,10 +248,12 @@ void SkGlyphRunBuilder::drawText(
SkSpan<const char> text, SkSpan<const uint32_t> clusters) { SkSpan<const char> text, SkSpan<const uint32_t> clusters) {
SkASSERT(!glyphIDs.empty()); SkASSERT(!glyphIDs.empty());
auto runSize = glyphIDs.size();
auto unqiueGlyphIDs = this->addDenseAndUnique(paint, glyphIDs); auto unqiueGlyphIDs = this->addDenseAndUnique(paint, glyphIDs);
if (!unqiueGlyphIDs.empty()) { if (!unqiueGlyphIDs.empty()) {
fScratchAdvances.resize(fUniqueGlyphIDs.size()); fScratchAdvances.resize(runSize);
{ {
auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(paint); auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(paint);
cache->getAdvances(unqiueGlyphIDs, fScratchAdvances.data()); cache->getAdvances(unqiueGlyphIDs, fScratchAdvances.data());
@ -255,9 +261,9 @@ void SkGlyphRunBuilder::drawText(
SkPoint endOfLastGlyph = origin; SkPoint endOfLastGlyph = origin;
for (size_t i = 0; i < fDenseIndex.size(); i++) { for (size_t i = 0; i < runSize; i++) {
fPositions[i] = endOfLastGlyph; fPositions[i] = endOfLastGlyph;
endOfLastGlyph += fScratchAdvances[fDenseIndex[i]]; endOfLastGlyph += fScratchAdvances[fUniqueGlyphIDIndices[i]];
} }
if (paint.getTextAlign() != SkPaint::kLeft_Align) { if (paint.getTextAlign() != SkPaint::kLeft_Align) {
@ -265,12 +271,20 @@ void SkGlyphRunBuilder::drawText(
if (paint.getTextAlign() == SkPaint::kCenter_Align) { if (paint.getTextAlign() == SkPaint::kCenter_Align) {
len.scale(SK_ScalarHalf); len.scale(SK_ScalarHalf);
} }
for (size_t i = 0; i < fDenseIndex.size(); i++) { for (auto& pt : SkSpan<SkPoint>{fPositions, runSize}) {
fPositions[i] -= len; pt -= len;
} }
} }
this->makeGlyphRun(paint, glyphIDs, SkSpan<const SkPoint>{fPositions}, text, clusters);
this->makeGlyphRun(
paint,
glyphIDs,
SkSpan<const SkPoint>{fPositions, runSize},
SkSpan<const uint16_t>{fUniqueGlyphIDIndices, runSize},
unqiueGlyphIDs,
text,
clusters);
} }
} }
@ -278,6 +292,7 @@ void SkGlyphRunBuilder::drawPosTextH(const SkPaint& paint, SkSpan<const SkGlyphI
const SkScalar* xpos, SkScalar constY, const SkScalar* xpos, SkScalar constY,
SkSpan<const char> text, SkSpan<const uint32_t> clusters) { SkSpan<const char> text, SkSpan<const uint32_t> clusters) {
SkASSERT(!glyphIDs.empty()); SkASSERT(!glyphIDs.empty());
auto runSize = glyphIDs.size();
// The dense indices are not used by the rest of the stack yet. // The dense indices are not used by the rest of the stack yet.
#ifdef SK_DEBUG #ifdef SK_DEBUG
@ -286,17 +301,26 @@ void SkGlyphRunBuilder::drawPosTextH(const SkPaint& paint, SkSpan<const SkGlyphI
// TODO: when using the unique glyph system have a guard that there are actually glyphs like // TODO: when using the unique glyph system have a guard that there are actually glyphs like
// drawText above. // drawText above.
for (size_t i = 0; i < fDenseIndex.size(); i++) { auto posCursor = fPositions.get();
fPositions[i] = SkPoint::Make(xpos[i], constY); for (auto x : SkSpan<const SkScalar>{xpos, runSize}) {
*posCursor++ = SkPoint::Make(x, constY);
} }
this->makeGlyphRun(paint, glyphIDs, SkSpan<const SkPoint>{fPositions}, text, clusters); this->makeGlyphRun(
paint,
glyphIDs,
SkSpan<const SkPoint>{fPositions, runSize},
SkSpan<const uint16_t>{},
SkSpan<const SkGlyphID>{},
text,
clusters);
} }
void SkGlyphRunBuilder::drawPosText(const SkPaint& paint, SkSpan<const SkGlyphID> glyphIDs, void SkGlyphRunBuilder::drawPosText(const SkPaint& paint, SkSpan<const SkGlyphID> glyphIDs,
const SkPoint* pos, const SkPoint* pos,
SkSpan<const char> text, SkSpan<const uint32_t> clusters) { SkSpan<const char> text, SkSpan<const uint32_t> clusters) {
SkASSERT(!glyphIDs.empty()); SkASSERT(!glyphIDs.empty());
auto runSize = glyphIDs.size();
// The dense indices are not used by the rest of the stack yet. // The dense indices are not used by the rest of the stack yet.
#ifdef SK_DEBUG #ifdef SK_DEBUG
@ -305,11 +329,14 @@ void SkGlyphRunBuilder::drawPosText(const SkPaint& paint, SkSpan<const SkGlyphID
// TODO: when using the unique glyph system have a guard that there are actually glyphs like // TODO: when using the unique glyph system have a guard that there are actually glyphs like
// drawText above. // drawText above.
for (size_t i = 0; i < fDenseIndex.size(); i++) { this->makeGlyphRun(
fPositions[i] = pos[i]; paint,
} glyphIDs,
SkSpan<const SkPoint>{pos, runSize},
this->makeGlyphRun(paint, glyphIDs, SkSpan<const SkPoint>{fPositions}, text, clusters); SkSpan<const uint16_t>{},
SkSpan<const SkGlyphID>{},
text,
clusters);
} }

View File

@ -24,23 +24,23 @@ template <typename T>
class SkSpan { class SkSpan {
public: public:
SkSpan() : fPtr{nullptr}, fSize{0} {} SkSpan() : fPtr{nullptr}, fSize{0} {}
SkSpan(T* ptr, ptrdiff_t size) : fPtr{ptr}, fSize{size} { SkASSERT(size >= 0); } SkSpan(T* ptr, size_t size) : fPtr{ptr}, fSize{size} { }
template <typename U> template <typename U>
explicit SkSpan(std::vector<U>& v) : fPtr{v.data()}, fSize{SkTo<ptrdiff_t>(v.size())} {} explicit SkSpan(std::vector<U>& v) : fPtr{v.data()}, fSize{v.size()} {}
SkSpan(const SkSpan<T>& o) = default; SkSpan(const SkSpan<T>& o) = default;
SkSpan& operator=( const SkSpan& other ) = default; SkSpan& operator=( const SkSpan& other ) = default;
T& operator [] (ptrdiff_t i) const { return fPtr[i]; } T& operator [] (size_t i) const { return fPtr[i]; }
T* begin() const { return fPtr; } T* begin() const { return fPtr; }
T* end() const { return fPtr + fSize; } T* end() const { return fPtr + fSize; }
const T* cbegin() const { return fPtr; } const T* cbegin() const { return fPtr; }
const T* cend() const { return fPtr + fSize; } const T* cend() const { return fPtr + fSize; }
T* data() const { return fPtr; } T* data() const { return fPtr; }
ptrdiff_t size() const { return fSize; } size_t size() const { return fSize; }
bool empty() const { return fSize == 0; } bool empty() const { return fSize == 0; }
private: private:
T* fPtr; T* fPtr;
ptrdiff_t fSize; size_t fSize;
}; };
class SkGlyphRun { class SkGlyphRun {
@ -120,6 +120,8 @@ private:
const SkPaint& runPaint, const SkPaint& runPaint,
SkSpan<const SkGlyphID> glyphIDs, SkSpan<const SkGlyphID> glyphIDs,
SkSpan<const SkPoint> positions, SkSpan<const SkPoint> positions,
SkSpan<const uint16_t> uniqueGlyphIDIndices,
SkSpan<const SkGlyphID> uniqueGlyphIDs,
SkSpan<const char> text, SkSpan<const char> text,
SkSpan<const uint32_t> clusters); SkSpan<const uint32_t> clusters);
@ -136,9 +138,10 @@ private:
uint64_t fUniqueID{0}; uint64_t fUniqueID{0};
std::vector<uint16_t> fDenseIndex; size_t fMaxTotalRunSize{0};
std::vector<SkPoint> fPositions; SkAutoTMalloc<uint16_t> fUniqueGlyphIDIndices;
std::vector<SkGlyphID> fUniqueGlyphIDs; SkAutoTMalloc<SkPoint> fPositions;
SkAutoTMalloc<SkGlyphID> fUniqueGlyphIDs;
// Used as a temporary for preparing using utfN text. This implies that only one run of // 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. // glyph ids will ever be needed because blobs are already glyph based.

View File

@ -12,6 +12,7 @@
#include "SkGlyphCache.h" #include "SkGlyphCache.h"
#include "SkGraphics.h" #include "SkGraphics.h"
#include "SkMutex.h" #include "SkMutex.h"
#include "SkTemplates.h"
#include "SkTraceMemoryDump.h" #include "SkTraceMemoryDump.h"
#include "SkTypeface.h" #include "SkTypeface.h"
#include "SkPaintPriv.h" #include "SkPaintPriv.h"

View File

@ -24,7 +24,7 @@ DEF_TEST(GlyphRunGlyphIDSetBasic, reporter) {
std::vector<SkGlyphID> test{uniqueGlyphIDs.begin(), uniqueGlyphIDs.end()}; std::vector<SkGlyphID> test{uniqueGlyphIDs.begin(), uniqueGlyphIDs.end()};
std::sort(test.begin(), test.end()); std::sort(test.begin(), test.end());
auto newEnd = std::unique(test.begin(), test.end()); auto newEnd = std::unique(test.begin(), test.end());
REPORTER_ASSERT(reporter, uniqueGlyphIDs.size() == newEnd - test.begin()); REPORTER_ASSERT(reporter, uniqueGlyphIDs.size() == (size_t)(newEnd - test.begin()));
REPORTER_ASSERT(reporter, uniqueGlyphIDs.size() == 4); REPORTER_ASSERT(reporter, uniqueGlyphIDs.size() == 4);
{ {
uint16_t answer[] = {0, 1, 2, 1, 3}; uint16_t answer[] = {0, 1, 2, 1, 3};