Simple iterator for textblobs
bug: skia:9503 Change-Id: I5b4e2434c6085d048d6d0fc42b2b928439b1066b Reviewed-on: https://skia-review.googlesource.com/c/skia/+/246296 Commit-Queue: Mike Reed <reed@google.com> Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
48de6fdef5
commit
a32654c13a
@ -4,6 +4,9 @@ This file includes a list of high level updates for each milestone release.
|
||||
|
||||
* * *
|
||||
|
||||
* SkTextBlob::Iter to discover the glyph indices and typefaces in each run
|
||||
https://skia-review.googlesource.com/246296
|
||||
|
||||
Milestone 79
|
||||
|
||||
[Insert new notes here.]
|
||||
|
@ -26,6 +26,9 @@ struct SkDeserialProcs;
|
||||
fonts and text rendering are used by run.
|
||||
*/
|
||||
class SK_API SkTextBlob final : public SkNVRefCnt<SkTextBlob> {
|
||||
private:
|
||||
class RunRecord;
|
||||
|
||||
public:
|
||||
|
||||
/** Returns conservative bounding box. Uses SkPaint associated with each glyph to
|
||||
@ -186,9 +189,28 @@ public:
|
||||
static sk_sp<SkTextBlob> Deserialize(const void* data, size_t size,
|
||||
const SkDeserialProcs& procs);
|
||||
|
||||
class Iter {
|
||||
public:
|
||||
struct Run {
|
||||
SkTypeface* fTypeface;
|
||||
int fGlyphCount;
|
||||
const uint16_t* fGlyphIndices;
|
||||
};
|
||||
|
||||
Iter(const SkTextBlob&);
|
||||
|
||||
/**
|
||||
* Returns true for each "run" inside the textblob, setting the Run fields (if not null).
|
||||
* If this returns false, there are no more runs, and the Run parameter will be ignored.
|
||||
*/
|
||||
bool next(Run*);
|
||||
|
||||
private:
|
||||
const RunRecord* fRunRecord;
|
||||
};
|
||||
|
||||
private:
|
||||
friend class SkNVRefCnt<SkTextBlob>;
|
||||
class RunRecord;
|
||||
|
||||
enum GlyphPositioning : uint8_t;
|
||||
|
||||
|
@ -919,3 +919,26 @@ int SkTextBlob::getIntercepts(const SkScalar bounds[2], SkScalar intervals[],
|
||||
|
||||
return intervalCount;
|
||||
}
|
||||
|
||||
////////
|
||||
|
||||
SkTextBlob::Iter::Iter(const SkTextBlob& blob) {
|
||||
fRunRecord = RunRecord::First(&blob);
|
||||
}
|
||||
|
||||
bool SkTextBlob::Iter::next(Run* rec) {
|
||||
if (fRunRecord) {
|
||||
if (rec) {
|
||||
rec->fTypeface = fRunRecord->font().getTypeface();
|
||||
rec->fGlyphCount = fRunRecord->glyphCount();
|
||||
rec->fGlyphIndices = fRunRecord->glyphBuffer();
|
||||
}
|
||||
if (fRunRecord->isLastRun()) {
|
||||
fRunRecord = nullptr;
|
||||
} else {
|
||||
fRunRecord = RunRecord::Next(fRunRecord);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -150,6 +150,8 @@ public:
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
bool isLastRun() const { return SkToBool(fFlags & kLast_Flag); }
|
||||
|
||||
static size_t StorageSize(uint32_t glyphCount, uint32_t textSize,
|
||||
SkTextBlob::GlyphPositioning positioning,
|
||||
SkSafeMath* safe);
|
||||
|
@ -449,3 +449,34 @@ DEF_TEST(TextBlob_MakeAsDrawText, reporter) {
|
||||
REPORTER_ASSERT(reporter, runs == 1);
|
||||
|
||||
}
|
||||
|
||||
DEF_TEST(TextBlob_iter, reporter) {
|
||||
sk_sp<SkTypeface> tf = SkTypeface::MakeFromName(nullptr, SkFontStyle::BoldItalic());
|
||||
|
||||
SkTextBlobBuilder builder;
|
||||
add_run(&builder, "Hello", 10, 20, nullptr);
|
||||
add_run(&builder, "World", 10, 40, tf);
|
||||
auto blob = builder.make();
|
||||
|
||||
SkTextBlob::Iter::Run expected[] = {
|
||||
{ nullptr, 5, nullptr },
|
||||
{ tf.get(), 5, nullptr },
|
||||
};
|
||||
|
||||
SkTextBlob::Iter iter(*blob);
|
||||
SkTextBlob::Iter::Run run;
|
||||
for (auto exp : expected) {
|
||||
REPORTER_ASSERT(reporter, iter.next(&run));
|
||||
REPORTER_ASSERT(reporter, run.fTypeface == exp.fTypeface);
|
||||
REPORTER_ASSERT(reporter, run.fGlyphCount == exp.fGlyphCount);
|
||||
for (int i = 0; i < run.fGlyphCount; ++i) {
|
||||
REPORTER_ASSERT(reporter, run.fGlyphIndices[i] != 0);
|
||||
}
|
||||
}
|
||||
REPORTER_ASSERT(reporter, !iter.next(&run)); // we're done
|
||||
|
||||
SkTextBlob::Iter iter2(*blob);
|
||||
REPORTER_ASSERT(reporter, iter2.next(&run));
|
||||
// Hello should have the same glyph repeated for the 'l'
|
||||
REPORTER_ASSERT(reporter, run.fGlyphIndices[2] == run.fGlyphIndices[3]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user