Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Unified Diff: src/core/SkTextBlob.cpp

Issue 2084533004: SkTextBlob: Begin implementing Extended TextBlob API (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2016-06-20 (Monday) 15:33:30 EDT Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/core/SkTextBlob.cpp
diff --git a/src/core/SkTextBlob.cpp b/src/core/SkTextBlob.cpp
index 1cbb2b6d6dabc9750c620b98cd1c8ec64c5adc84..7397fbeb62209395fa38f5977826f40744cee3c2 100644
--- a/src/core/SkTextBlob.cpp
+++ b/src/core/SkTextBlob.cpp
@@ -110,11 +110,12 @@ SkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;)
class SkTextBlob::RunRecord {
public:
- RunRecord(uint32_t count, const SkPoint& offset, const SkPaint& font, GlyphPositioning pos)
+ RunRecord(uint32_t count, const SkPoint& offset, const SkPaint& font, GlyphPositioning pos, bool extended)
: fFont(font)
, fCount(count)
, fOffset(offset)
- , fPositioning(pos) {
+ , fPositioning(pos)
+ , fExtended(extended) {
SkDEBUGCODE(fMagic = kRunRecordMagic);
}
@@ -135,6 +136,7 @@ public:
}
uint16_t* glyphBuffer() const {
+ static_assert(SkIsAlignPtr(sizeof(RunRecord)), "");
// Glyph are stored immediately following the record.
return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1);
}
@@ -145,11 +147,42 @@ public:
SkAlign4(fCount * sizeof(uint16_t)));
}
- static size_t StorageSize(int glyphCount, SkTextBlob::GlyphPositioning positioning) {
+ uint32_t textSize() const {
+ // textSize follows the position buffer.
+ if (!fExtended) { return 0; }
+ return *(uint32_t*)(&this->posBuffer()[ScalarsPerGlyph(fPositioning) * fCount]);
tomhudson 2016/06/21 14:51:28 Is it worth having an inlined private function for
+ }
+
+ void setTextSize(uint32_t size) {
+ SkASSERT(fExtended);
+ *(uint32_t*)(&this->posBuffer()[ScalarsPerGlyph(fPositioning) * fCount]) = size;
+
+ }
+ uint32_t* clusterBuffer() const {
+ // clusters follow the textSize.
+ if (!fExtended) { return nullptr; }
+ return (uint32_t*)(&this->posBuffer()[ScalarsPerGlyph(fPositioning) * fCount]) + 1;
+ }
+
+ char* textBuffer() const {
+ if (!fExtended) { return nullptr; }
+ return (char*)((uint32_t*)(&this->posBuffer()[ScalarsPerGlyph(fPositioning) * fCount]) + 1 + fCount);
+ }
+
+ static size_t StorageSize(int glyphCount, int textSize, SkTextBlob::GlyphPositioning positioning) {
// RunRecord object + (aligned) glyph buffer + position buffer
- return SkAlignPtr(sizeof(SkTextBlob::RunRecord)
- + SkAlign4(glyphCount* sizeof(uint16_t))
- + glyphCount * sizeof(SkScalar) * ScalarsPerGlyph(positioning));
+ if (0 == textSize) {
+ return SkAlignPtr(sizeof(SkTextBlob::RunRecord)
+ + SkAlign4(glyphCount* sizeof(uint16_t))
+ + glyphCount * sizeof(SkScalar) * ScalarsPerGlyph(positioning));
+ } else {
+ return SkAlignPtr(sizeof(SkTextBlob::RunRecord)
+ + SkAlign4(glyphCount* sizeof(uint16_t))
+ + glyphCount * sizeof(SkScalar) * ScalarsPerGlyph(positioning)
+ + sizeof(uint32_t)
+ + sizeof(uint32_t) * glyphCount
+ + textSize);
+ }
}
static const RunRecord* First(const SkTextBlob* blob) {
@@ -158,13 +191,15 @@ public:
}
static const RunRecord* Next(const RunRecord* run) {
- return reinterpret_cast<const RunRecord*>(reinterpret_cast<const uint8_t*>(run)
- + StorageSize(run->glyphCount(), run->positioning()));
+ return reinterpret_cast<const RunRecord*>(
+ reinterpret_cast<const uint8_t*>(run)
+ + StorageSize(run->glyphCount(), run->textSize(), run->positioning()));
}
void validate(const uint8_t* storageTop) const {
SkASSERT(kRunRecordMagic == fMagic);
SkASSERT((uint8_t*)Next(this) <= storageTop);
+
tomhudson 2016/06/21 14:51:28 nit: extra blank line?
SkASSERT(glyphBuffer() + fCount <= (uint16_t*)posBuffer());
SkASSERT(posBuffer() + fCount * ScalarsPerGlyph(fPositioning) <= (SkScalar*)Next(this));
}
@@ -189,6 +224,7 @@ private:
uint32_t fCount;
SkPoint fOffset;
GlyphPositioning fPositioning;
+ bool fExtended;
SkDEBUGCODE(unsigned fMagic;)
};
@@ -206,6 +242,11 @@ SkTextBlob::SkTextBlob(int runCount, const SkRect& bounds)
: fRunCount(runCount)
, fBounds(bounds)
, fUniqueID(next_id()) {
+ #ifdef SK_DEBUG
+ static_assert(sizeof(SkTextBlob::RunRecord) == SkAlignPtr(sizeof(void*) + 29 + 4), "");
+ #else
+ static_assert(sizeof(SkTextBlob::RunRecord) == SkAlignPtr(sizeof(void*) + 29), "");
+ #endif
}
SkTextBlob::~SkTextBlob() {
@@ -218,6 +259,17 @@ SkTextBlob::~SkTextBlob() {
}
}
+namespace {
+union PositioningAndExtended {
+ int32_t intValue;
+ struct {
+ SkTextBlob::GlyphPositioning positioning;
+ bool extended;
+ uint16_t padding;
+ };
+};
+} // namespace
+
void SkTextBlob::flatten(SkWriteBuffer& buffer) const {
int runCount = fRunCount;
@@ -230,7 +282,15 @@ void SkTextBlob::flatten(SkWriteBuffer& buffer) const {
SkASSERT(it.glyphCount() > 0);
buffer.write32(it.glyphCount());
- buffer.write32(it.positioning());
+ PositioningAndExtended pe;
+ pe.intValue = 0;
+ pe.positioning = it.positioning();
+ SkASSERT((int32_t)it.positioning() == pe.intValue); // backwards compat.
+ pe.extended = it.isExtended();
+ buffer.write32(pe.intValue);
+ if (pe.extended) {
+ buffer.write32(it.textSize());
+ }
buffer.writePoint(it.offset());
// This should go away when switching to SkFont
it.applyFontToPaint(&runPaint);
@@ -239,6 +299,10 @@ void SkTextBlob::flatten(SkWriteBuffer& buffer) const {
buffer.writeByteArray(it.glyphs(), it.glyphCount() * sizeof(uint16_t));
buffer.writeByteArray(it.pos(),
it.glyphCount() * sizeof(SkScalar) * ScalarsPerGlyph(it.positioning()));
+ if (pe.extended) {
+ buffer.writeByteArray(it.clusterBuffer(), sizeof(uint32_t) * it.glyphCount());
+ buffer.writeByteArray(it.textBuffer(), it.textSize());
+ }
it.next();
SkDEBUGCODE(runCount--);
@@ -258,10 +322,14 @@ const SkTextBlob* SkTextBlob::CreateFromBuffer(SkReadBuffer& reader) {
SkTextBlobBuilder blobBuilder;
for (int i = 0; i < runCount; ++i) {
int glyphCount = reader.read32();
- GlyphPositioning pos = static_cast<GlyphPositioning>(reader.read32());
+
+ PositioningAndExtended pe;
+ pe.intValue = reader.read32();
+ GlyphPositioning pos = pe.positioning;
if (glyphCount <= 0 || pos > kFull_Positioning) {
return nullptr;
}
+ uint32_t textSize = pe.extended ? (uint32_t)reader.read32() : 0;
SkPoint offset;
reader.readPoint(&offset);
@@ -271,13 +339,15 @@ const SkTextBlob* SkTextBlob::CreateFromBuffer(SkReadBuffer& reader) {
const SkTextBlobBuilder::RunBuffer* buf = nullptr;
switch (pos) {
case kDefault_Positioning:
- buf = &blobBuilder.allocRun(font, glyphCount, offset.x(), offset.y(), &bounds);
+ buf = &blobBuilder.allocRunText(font, glyphCount, offset.x(), offset.y(),
+ textSize, SkString(), &bounds);
break;
case kHorizontal_Positioning:
- buf = &blobBuilder.allocRunPosH(font, glyphCount, offset.y(), &bounds);
+ buf = &blobBuilder.allocRunTextPosH(font, glyphCount, offset.y(),
+ textSize, SkString(), &bounds);
break;
case kFull_Positioning:
- buf = &blobBuilder.allocRunPos(font, glyphCount, &bounds);
+ buf = &blobBuilder.allocRunTextPos(font, glyphCount, textSize, SkString(), &bounds);
break;
default:
return nullptr;
@@ -288,6 +358,13 @@ const SkTextBlob* SkTextBlob::CreateFromBuffer(SkReadBuffer& reader) {
glyphCount * sizeof(SkScalar) * ScalarsPerGlyph(pos))) {
return nullptr;
}
+
+ if (pe.extended) {
+ if (!reader.readByteArray(buf->clusters, glyphCount * sizeof(uint32_t)) ||
tomhudson 2016/06/21 14:51:28 If textSize is 0, shouldn't this also be a 0-lengt
+ !reader.readByteArray(buf->utf8text, textSize)) {
+ return nullptr;
+ }
+ }
}
return blobBuilder.build();
@@ -350,6 +427,24 @@ void SkTextBlobRunIterator::applyFontToPaint(SkPaint* paint) const {
fCurrentRun->font().applyToPaint(paint);
}
+bool SkTextBlobRunIterator::isExtended() const {
+ SkASSERT(!this->done());
+ return fCurrentRun->textSize() > 0;
+}
+uint32_t* SkTextBlobRunIterator::clusterBuffer() const {
+ SkASSERT(!this->done());
+ return fCurrentRun->clusterBuffer();
+}
+uint32_t SkTextBlobRunIterator::textSize() const {
+ SkASSERT(!this->done());
+ return fCurrentRun->textSize();
+}
+char* SkTextBlobRunIterator::textBuffer() const {
+ SkASSERT(!this->done());
+ return fCurrentRun->textBuffer();
+}
+
+
bool SkTextBlobRunIterator::isLCD() const {
return SkToBool(fCurrentRun->font().flags() & SkPaint::kLCDRenderText_Flag);
}
@@ -513,6 +608,10 @@ bool SkTextBlobBuilder::mergeRun(const SkPaint &font, SkTextBlob::GlyphPositioni
fLastRun);
SkASSERT(run->glyphCount() > 0);
+ if (run->textSize() != 0) {
+ return false;
tomhudson 2016/06/21 14:51:28 Tangent not for this CL: Because it's not worth th
+ }
+
if (run->positioning() != positioning
|| run->font() != font
|| (run->glyphCount() + count < run->glyphCount())) {
@@ -529,8 +628,8 @@ bool SkTextBlobBuilder::mergeRun(const SkPaint &font, SkTextBlob::GlyphPositioni
return false;
}
- size_t sizeDelta = SkTextBlob::RunRecord::StorageSize(run->glyphCount() + count, positioning) -
- SkTextBlob::RunRecord::StorageSize(run->glyphCount(), positioning);
+ size_t sizeDelta = SkTextBlob::RunRecord::StorageSize(run->glyphCount() + count, 0, positioning) -
+ SkTextBlob::RunRecord::StorageSize(run->glyphCount(), 0, positioning);
this->reserve(sizeDelta);
// reserve may have realloced
@@ -553,24 +652,29 @@ bool SkTextBlobBuilder::mergeRun(const SkPaint &font, SkTextBlob::GlyphPositioni
void SkTextBlobBuilder::allocInternal(const SkPaint &font,
SkTextBlob::GlyphPositioning positioning,
- int count, SkPoint offset, const SkRect* bounds) {
+ int count, int textSize, SkPoint offset, const SkRect* bounds) {
SkASSERT(count > 0);
+ SkASSERT(textSize >= 0);
SkASSERT(SkPaint::kGlyphID_TextEncoding == font.getTextEncoding());
- if (!this->mergeRun(font, positioning, count, offset)) {
+ if (textSize != 0 || !this->mergeRun(font, positioning, count, offset)) {
this->updateDeferredBounds();
- size_t runSize = SkTextBlob::RunRecord::StorageSize(count, positioning);
+ size_t runSize = SkTextBlob::RunRecord::StorageSize(count, textSize, positioning);
this->reserve(runSize);
SkASSERT(fStorageUsed >= sizeof(SkTextBlob));
SkASSERT(fStorageUsed + runSize <= fStorageSize);
SkTextBlob::RunRecord* run = new (fStorage.get() + fStorageUsed)
- SkTextBlob::RunRecord(count, offset, font, positioning);
-
+ SkTextBlob::RunRecord(count, offset, font, positioning, textSize > 0);
+ if (textSize > 0) {
+ run->setTextSize(textSize);
+ }
fCurrentRunBuffer.glyphs = run->glyphBuffer();
fCurrentRunBuffer.pos = run->posBuffer();
+ fCurrentRunBuffer.utf8text = run->textBuffer();
+ fCurrentRunBuffer.clusters = run->clusterBuffer();
fLastRun = fStorageUsed;
fStorageUsed += runSize;
@@ -578,6 +682,9 @@ void SkTextBlobBuilder::allocInternal(const SkPaint &font,
SkASSERT(fStorageUsed <= fStorageSize);
run->validate(fStorage.get() + fStorageUsed);
+ } else {
+ fCurrentRunBuffer.utf8text = nullptr;
+ fCurrentRunBuffer.clusters = nullptr;
}
if (!fDeferredBounds) {
@@ -589,26 +696,31 @@ void SkTextBlobBuilder::allocInternal(const SkPaint &font,
}
}
-const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRun(const SkPaint& font, int count,
- SkScalar x, SkScalar y,
- const SkRect* bounds) {
- this->allocInternal(font, SkTextBlob::kDefault_Positioning, count, SkPoint::Make(x, y), bounds);
-
+const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunText(const SkPaint& font, int count,
+ SkScalar x, SkScalar y,
+ int textByteCount,
+ SkString lang,
+ const SkRect* bounds) {
+ this->allocInternal(font, SkTextBlob::kDefault_Positioning, count, textByteCount, SkPoint::Make(x, y), bounds);
return fCurrentRunBuffer;
}
-const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPosH(const SkPaint& font, int count,
- SkScalar y,
- const SkRect* bounds) {
- this->allocInternal(font, SkTextBlob::kHorizontal_Positioning, count, SkPoint::Make(0, y),
+const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunTextPosH(const SkPaint& font, int count,
+ SkScalar y,
+ int textByteCount,
+ SkString lang,
+ const SkRect* bounds) {
+ this->allocInternal(font, SkTextBlob::kHorizontal_Positioning, count, textByteCount, SkPoint::Make(0, y),
bounds);
return fCurrentRunBuffer;
}
-const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPos(const SkPaint& font, int count,
- const SkRect *bounds) {
- this->allocInternal(font, SkTextBlob::kFull_Positioning, count, SkPoint::Make(0, 0), bounds);
+const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunTextPos(const SkPaint& font, int count,
+ int textByteCount,
+ SkString lang,
+ const SkRect *bounds) {
+ this->allocInternal(font, SkTextBlob::kFull_Positioning, count, textByteCount, SkPoint::Make(0, 0), bounds);
return fCurrentRunBuffer;
}
@@ -631,7 +743,8 @@ const SkTextBlob* SkTextBlobBuilder::build() {
size_t validateSize = sizeof(SkTextBlob);
const SkTextBlob::RunRecord* run = SkTextBlob::RunRecord::First(blob);
for (int i = 0; i < fRunCount; ++i) {
- validateSize += SkTextBlob::RunRecord::StorageSize(run->fCount, run->fPositioning);
+ validateSize += SkTextBlob::RunRecord::StorageSize(
+ run->fCount, run->textSize(), run->fPositioning);
run->validate(reinterpret_cast<const uint8_t*>(blob) + fStorageUsed);
run = SkTextBlob::RunRecord::Next(run);
}

Powered by Google App Engine
This is Rietveld 408576698