100d5c2c6523321d25b32905ff4822f083a4173eefmalita/* 200d5c2c6523321d25b32905ff4822f083a4173eefmalita * Copyright 2014 Google Inc. 300d5c2c6523321d25b32905ff4822f083a4173eefmalita * 400d5c2c6523321d25b32905ff4822f083a4173eefmalita * Use of this source code is governed by a BSD-style license that can be 500d5c2c6523321d25b32905ff4822f083a4173eefmalita * found in the LICENSE file. 600d5c2c6523321d25b32905ff4822f083a4173eefmalita */ 700d5c2c6523321d25b32905ff4822f083a4173eefmalita 800d5c2c6523321d25b32905ff4822f083a4173eefmalita#include "SkTextBlob.h" 900d5c2c6523321d25b32905ff4822f083a4173eefmalita 10b7425173f96e93b090787e2386ba5f022b6c2869fmalita#include "SkReadBuffer.h" 11b7425173f96e93b090787e2386ba5f022b6c2869fmalita#include "SkWriteBuffer.h" 12b7425173f96e93b090787e2386ba5f022b6c2869fmalita 133c196def91726913a417e703ac482bb2dbbfff27fmalita// 143c196def91726913a417e703ac482bb2dbbfff27fmalita// Textblob data is laid out into externally-managed storage as follows: 153c196def91726913a417e703ac482bb2dbbfff27fmalita// 163c196def91726913a417e703ac482bb2dbbfff27fmalita// ----------------------------------------------------------------------------- 173c196def91726913a417e703ac482bb2dbbfff27fmalita// | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ... 183c196def91726913a417e703ac482bb2dbbfff27fmalita// ----------------------------------------------------------------------------- 193c196def91726913a417e703ac482bb2dbbfff27fmalita// 203c196def91726913a417e703ac482bb2dbbfff27fmalita// Each run record describes a text blob run, and can be used to determine the (implicit) 213c196def91726913a417e703ac482bb2dbbfff27fmalita// location of the following record. 223c196def91726913a417e703ac482bb2dbbfff27fmalita 233c196def91726913a417e703ac482bb2dbbfff27fmalitaSkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;) 243c196def91726913a417e703ac482bb2dbbfff27fmalita 253c196def91726913a417e703ac482bb2dbbfff27fmalitaclass SkTextBlob::RunRecord { 263c196def91726913a417e703ac482bb2dbbfff27fmalitapublic: 273c196def91726913a417e703ac482bb2dbbfff27fmalita RunRecord(uint32_t count, const SkPoint& offset, const SkPaint& font, GlyphPositioning pos) 283c196def91726913a417e703ac482bb2dbbfff27fmalita : fCount(count) 293c196def91726913a417e703ac482bb2dbbfff27fmalita , fOffset(offset) 303c196def91726913a417e703ac482bb2dbbfff27fmalita , fFont(font) 313c196def91726913a417e703ac482bb2dbbfff27fmalita , fPositioning(pos) { 323c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(fMagic = kRunRecordMagic); 333c196def91726913a417e703ac482bb2dbbfff27fmalita } 343c196def91726913a417e703ac482bb2dbbfff27fmalita 353c196def91726913a417e703ac482bb2dbbfff27fmalita uint32_t glyphCount() const { 363c196def91726913a417e703ac482bb2dbbfff27fmalita return fCount; 373c196def91726913a417e703ac482bb2dbbfff27fmalita } 383c196def91726913a417e703ac482bb2dbbfff27fmalita 393c196def91726913a417e703ac482bb2dbbfff27fmalita const SkPoint& offset() const { 403c196def91726913a417e703ac482bb2dbbfff27fmalita return fOffset; 413c196def91726913a417e703ac482bb2dbbfff27fmalita } 423c196def91726913a417e703ac482bb2dbbfff27fmalita 433c196def91726913a417e703ac482bb2dbbfff27fmalita const SkPaint& font() const { 443c196def91726913a417e703ac482bb2dbbfff27fmalita return fFont; 453c196def91726913a417e703ac482bb2dbbfff27fmalita } 463c196def91726913a417e703ac482bb2dbbfff27fmalita 473c196def91726913a417e703ac482bb2dbbfff27fmalita GlyphPositioning positioning() const { 483c196def91726913a417e703ac482bb2dbbfff27fmalita return fPositioning; 493c196def91726913a417e703ac482bb2dbbfff27fmalita } 503c196def91726913a417e703ac482bb2dbbfff27fmalita 513c196def91726913a417e703ac482bb2dbbfff27fmalita uint16_t* glyphBuffer() const { 523c196def91726913a417e703ac482bb2dbbfff27fmalita // Glyph are stored immediately following the record. 533c196def91726913a417e703ac482bb2dbbfff27fmalita return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1); 543c196def91726913a417e703ac482bb2dbbfff27fmalita } 553c196def91726913a417e703ac482bb2dbbfff27fmalita 563c196def91726913a417e703ac482bb2dbbfff27fmalita SkScalar* posBuffer() const { 573c196def91726913a417e703ac482bb2dbbfff27fmalita // Position scalars follow the (aligned) glyph buffer. 583c196def91726913a417e703ac482bb2dbbfff27fmalita return reinterpret_cast<SkScalar*>(reinterpret_cast<uint8_t*>(this->glyphBuffer()) + 593c196def91726913a417e703ac482bb2dbbfff27fmalita SkAlign4(fCount * sizeof(uint16_t))); 603c196def91726913a417e703ac482bb2dbbfff27fmalita } 613c196def91726913a417e703ac482bb2dbbfff27fmalita 623c196def91726913a417e703ac482bb2dbbfff27fmalita static size_t StorageSize(int glyphCount, SkTextBlob::GlyphPositioning positioning) { 633c196def91726913a417e703ac482bb2dbbfff27fmalita // RunRecord object + (aligned) glyph buffer + position buffer 643c196def91726913a417e703ac482bb2dbbfff27fmalita return SkAlignPtr(sizeof(SkTextBlob::RunRecord) 653c196def91726913a417e703ac482bb2dbbfff27fmalita + SkAlign4(glyphCount* sizeof(uint16_t)) 663c196def91726913a417e703ac482bb2dbbfff27fmalita + glyphCount * sizeof(SkScalar) * ScalarsPerGlyph(positioning)); 673c196def91726913a417e703ac482bb2dbbfff27fmalita } 683c196def91726913a417e703ac482bb2dbbfff27fmalita 693c196def91726913a417e703ac482bb2dbbfff27fmalita static const RunRecord* First(const SkTextBlob* blob) { 703c196def91726913a417e703ac482bb2dbbfff27fmalita // The first record (if present) is stored following the blob object. 713c196def91726913a417e703ac482bb2dbbfff27fmalita return reinterpret_cast<const RunRecord*>(blob + 1); 723c196def91726913a417e703ac482bb2dbbfff27fmalita } 733c196def91726913a417e703ac482bb2dbbfff27fmalita 743c196def91726913a417e703ac482bb2dbbfff27fmalita static const RunRecord* Next(const RunRecord* run) { 753c196def91726913a417e703ac482bb2dbbfff27fmalita return reinterpret_cast<const RunRecord*>(reinterpret_cast<const uint8_t*>(run) 763c196def91726913a417e703ac482bb2dbbfff27fmalita + StorageSize(run->glyphCount(), run->positioning())); 773c196def91726913a417e703ac482bb2dbbfff27fmalita } 783c196def91726913a417e703ac482bb2dbbfff27fmalita 793c196def91726913a417e703ac482bb2dbbfff27fmalita void validate(uint8_t* storageTop) const { 803c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(kRunRecordMagic == fMagic); 813c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT((uint8_t*)Next(this) <= storageTop); 823c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(glyphBuffer() + fCount <= (uint16_t*)posBuffer()); 833c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(posBuffer() + fCount * ScalarsPerGlyph(fPositioning) <= (SkScalar*)Next(this)); 843c196def91726913a417e703ac482bb2dbbfff27fmalita } 853c196def91726913a417e703ac482bb2dbbfff27fmalita 863c196def91726913a417e703ac482bb2dbbfff27fmalitaprivate: 873c196def91726913a417e703ac482bb2dbbfff27fmalita friend class SkTextBlobBuilder; 883c196def91726913a417e703ac482bb2dbbfff27fmalita 893c196def91726913a417e703ac482bb2dbbfff27fmalita void grow(uint32_t count) { 903c196def91726913a417e703ac482bb2dbbfff27fmalita SkScalar* initialPosBuffer = posBuffer(); 913c196def91726913a417e703ac482bb2dbbfff27fmalita uint32_t initialCount = fCount; 923c196def91726913a417e703ac482bb2dbbfff27fmalita fCount += count; 933c196def91726913a417e703ac482bb2dbbfff27fmalita 943c196def91726913a417e703ac482bb2dbbfff27fmalita // Move the initial pos scalars to their new location. 953c196def91726913a417e703ac482bb2dbbfff27fmalita size_t copySize = initialCount * sizeof(SkScalar) * ScalarsPerGlyph(fPositioning); 963c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT((uint8_t*)posBuffer() + copySize <= (uint8_t*)Next(this)); 973c196def91726913a417e703ac482bb2dbbfff27fmalita 983c196def91726913a417e703ac482bb2dbbfff27fmalita // memmove, as the buffers may overlap 993c196def91726913a417e703ac482bb2dbbfff27fmalita memmove(posBuffer(), initialPosBuffer, copySize); 1003c196def91726913a417e703ac482bb2dbbfff27fmalita } 1013c196def91726913a417e703ac482bb2dbbfff27fmalita 1023c196def91726913a417e703ac482bb2dbbfff27fmalita uint32_t fCount; 1033c196def91726913a417e703ac482bb2dbbfff27fmalita SkPoint fOffset; 1043c196def91726913a417e703ac482bb2dbbfff27fmalita SkPaint fFont; 1053c196def91726913a417e703ac482bb2dbbfff27fmalita GlyphPositioning fPositioning; 1063c196def91726913a417e703ac482bb2dbbfff27fmalita 1073c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(unsigned fMagic;) 1083c196def91726913a417e703ac482bb2dbbfff27fmalita}; 1093c196def91726913a417e703ac482bb2dbbfff27fmalita 1103c196def91726913a417e703ac482bb2dbbfff27fmalitaSkTextBlob::SkTextBlob(int runCount, const SkRect& bounds) 1113c196def91726913a417e703ac482bb2dbbfff27fmalita : fRunCount(runCount) 11200d5c2c6523321d25b32905ff4822f083a4173eefmalita , fBounds(bounds) { 11300d5c2c6523321d25b32905ff4822f083a4173eefmalita} 11400d5c2c6523321d25b32905ff4822f083a4173eefmalita 1153c196def91726913a417e703ac482bb2dbbfff27fmalitaSkTextBlob::~SkTextBlob() { 1163c196def91726913a417e703ac482bb2dbbfff27fmalita const RunRecord* run = RunRecord::First(this); 1173c196def91726913a417e703ac482bb2dbbfff27fmalita for (int i = 0; i < fRunCount; ++i) { 1183c196def91726913a417e703ac482bb2dbbfff27fmalita const RunRecord* nextRun = RunRecord::Next(run); 1193c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(run->validate((uint8_t*)this + fStorageSize);) 1203c196def91726913a417e703ac482bb2dbbfff27fmalita run->~RunRecord(); 1213c196def91726913a417e703ac482bb2dbbfff27fmalita run = nextRun; 1223c196def91726913a417e703ac482bb2dbbfff27fmalita } 1233c196def91726913a417e703ac482bb2dbbfff27fmalita} 1243c196def91726913a417e703ac482bb2dbbfff27fmalita 1253c196def91726913a417e703ac482bb2dbbfff27fmalitavoid SkTextBlob::internal_dispose() const { 1263c196def91726913a417e703ac482bb2dbbfff27fmalita // SkTextBlobs use externally-managed storage. 1273c196def91726913a417e703ac482bb2dbbfff27fmalita this->internal_dispose_restore_refcnt_to_1(); 1283c196def91726913a417e703ac482bb2dbbfff27fmalita this->~SkTextBlob(); 1293c196def91726913a417e703ac482bb2dbbfff27fmalita sk_free(const_cast<SkTextBlob*>(this)); 1303c196def91726913a417e703ac482bb2dbbfff27fmalita} 1313c196def91726913a417e703ac482bb2dbbfff27fmalita 13200d5c2c6523321d25b32905ff4822f083a4173eefmalitauint32_t SkTextBlob::uniqueID() const { 13300d5c2c6523321d25b32905ff4822f083a4173eefmalita static int32_t gTextBlobGenerationID; // = 0; 13400d5c2c6523321d25b32905ff4822f083a4173eefmalita 13500d5c2c6523321d25b32905ff4822f083a4173eefmalita // loop in case our global wraps around, as we never want to return SK_InvalidGenID 13600d5c2c6523321d25b32905ff4822f083a4173eefmalita while (SK_InvalidGenID == fUniqueID) { 13700d5c2c6523321d25b32905ff4822f083a4173eefmalita fUniqueID = sk_atomic_inc(&gTextBlobGenerationID) + 1; 13800d5c2c6523321d25b32905ff4822f083a4173eefmalita } 13900d5c2c6523321d25b32905ff4822f083a4173eefmalita 14000d5c2c6523321d25b32905ff4822f083a4173eefmalita return fUniqueID; 14100d5c2c6523321d25b32905ff4822f083a4173eefmalita} 14200d5c2c6523321d25b32905ff4822f083a4173eefmalita 143b7425173f96e93b090787e2386ba5f022b6c2869fmalitavoid SkTextBlob::flatten(SkWriteBuffer& buffer) const { 1443c196def91726913a417e703ac482bb2dbbfff27fmalita int runCount = fRunCount; 145b7425173f96e93b090787e2386ba5f022b6c2869fmalita 146b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.write32(runCount); 147b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writeRect(fBounds); 148b7425173f96e93b090787e2386ba5f022b6c2869fmalita 149b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkPaint runPaint; 150b7425173f96e93b090787e2386ba5f022b6c2869fmalita RunIterator it(this); 151b7425173f96e93b090787e2386ba5f022b6c2869fmalita while (!it.done()) { 152b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkASSERT(it.glyphCount() > 0); 153b7425173f96e93b090787e2386ba5f022b6c2869fmalita 154b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.write32(it.glyphCount()); 155b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.write32(it.positioning()); 156b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writePoint(it.offset()); 157b7425173f96e93b090787e2386ba5f022b6c2869fmalita // This should go away when switching to SkFont 158b7425173f96e93b090787e2386ba5f022b6c2869fmalita it.applyFontToPaint(&runPaint); 159b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writePaint(runPaint); 160b7425173f96e93b090787e2386ba5f022b6c2869fmalita 161b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writeByteArray(it.glyphs(), it.glyphCount() * sizeof(uint16_t)); 162b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writeByteArray(it.pos(), 163b7425173f96e93b090787e2386ba5f022b6c2869fmalita it.glyphCount() * sizeof(SkScalar) * ScalarsPerGlyph(it.positioning())); 164b7425173f96e93b090787e2386ba5f022b6c2869fmalita 165b7425173f96e93b090787e2386ba5f022b6c2869fmalita it.next(); 166b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkDEBUGCODE(runCount--); 167b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 168b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkASSERT(0 == runCount); 169b7425173f96e93b090787e2386ba5f022b6c2869fmalita} 170b7425173f96e93b090787e2386ba5f022b6c2869fmalita 171b7425173f96e93b090787e2386ba5f022b6c2869fmalitaconst SkTextBlob* SkTextBlob::CreateFromBuffer(SkReadBuffer& reader) { 172b7425173f96e93b090787e2386ba5f022b6c2869fmalita int runCount = reader.read32(); 173b7425173f96e93b090787e2386ba5f022b6c2869fmalita if (runCount < 0) { 174b7425173f96e93b090787e2386ba5f022b6c2869fmalita return NULL; 175b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 176b7425173f96e93b090787e2386ba5f022b6c2869fmalita 177b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkRect bounds; 178b7425173f96e93b090787e2386ba5f022b6c2869fmalita reader.readRect(&bounds); 179b7425173f96e93b090787e2386ba5f022b6c2869fmalita 180b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkTextBlobBuilder blobBuilder; 181b7425173f96e93b090787e2386ba5f022b6c2869fmalita for (int i = 0; i < runCount; ++i) { 182b7425173f96e93b090787e2386ba5f022b6c2869fmalita int glyphCount = reader.read32(); 183b7425173f96e93b090787e2386ba5f022b6c2869fmalita GlyphPositioning pos = static_cast<GlyphPositioning>(reader.read32()); 184b7425173f96e93b090787e2386ba5f022b6c2869fmalita if (glyphCount <= 0 || pos > kFull_Positioning) { 185b7425173f96e93b090787e2386ba5f022b6c2869fmalita return NULL; 186b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 187b7425173f96e93b090787e2386ba5f022b6c2869fmalita 188b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkPoint offset; 189b7425173f96e93b090787e2386ba5f022b6c2869fmalita reader.readPoint(&offset); 190b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkPaint font; 191b7425173f96e93b090787e2386ba5f022b6c2869fmalita reader.readPaint(&font); 192b7425173f96e93b090787e2386ba5f022b6c2869fmalita 193b7425173f96e93b090787e2386ba5f022b6c2869fmalita const SkTextBlobBuilder::RunBuffer* buf = NULL; 194b7425173f96e93b090787e2386ba5f022b6c2869fmalita switch (pos) { 195b7425173f96e93b090787e2386ba5f022b6c2869fmalita case kDefault_Positioning: 196b7425173f96e93b090787e2386ba5f022b6c2869fmalita buf = &blobBuilder.allocRun(font, glyphCount, offset.x(), offset.y(), &bounds); 197b7425173f96e93b090787e2386ba5f022b6c2869fmalita break; 198b7425173f96e93b090787e2386ba5f022b6c2869fmalita case kHorizontal_Positioning: 199b7425173f96e93b090787e2386ba5f022b6c2869fmalita buf = &blobBuilder.allocRunPosH(font, glyphCount, offset.y(), &bounds); 200b7425173f96e93b090787e2386ba5f022b6c2869fmalita break; 201b7425173f96e93b090787e2386ba5f022b6c2869fmalita case kFull_Positioning: 202b7425173f96e93b090787e2386ba5f022b6c2869fmalita buf = &blobBuilder.allocRunPos(font, glyphCount, &bounds); 203b7425173f96e93b090787e2386ba5f022b6c2869fmalita break; 204b7425173f96e93b090787e2386ba5f022b6c2869fmalita default: 205b7425173f96e93b090787e2386ba5f022b6c2869fmalita return NULL; 206b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 207b7425173f96e93b090787e2386ba5f022b6c2869fmalita 208b7425173f96e93b090787e2386ba5f022b6c2869fmalita if (!reader.readByteArray(buf->glyphs, glyphCount * sizeof(uint16_t)) || 2093c196def91726913a417e703ac482bb2dbbfff27fmalita !reader.readByteArray(buf->pos, 2103c196def91726913a417e703ac482bb2dbbfff27fmalita glyphCount * sizeof(SkScalar) * ScalarsPerGlyph(pos))) { 211b7425173f96e93b090787e2386ba5f022b6c2869fmalita return NULL; 212b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 213b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 214b7425173f96e93b090787e2386ba5f022b6c2869fmalita 215b7425173f96e93b090787e2386ba5f022b6c2869fmalita return blobBuilder.build(); 216b7425173f96e93b090787e2386ba5f022b6c2869fmalita} 217b7425173f96e93b090787e2386ba5f022b6c2869fmalita 2183c196def91726913a417e703ac482bb2dbbfff27fmalitaunsigned SkTextBlob::ScalarsPerGlyph(GlyphPositioning pos) { 2193c196def91726913a417e703ac482bb2dbbfff27fmalita // GlyphPositioning values are directly mapped to scalars-per-glyph. 2203c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(pos <= 2); 2213c196def91726913a417e703ac482bb2dbbfff27fmalita return pos; 2223c196def91726913a417e703ac482bb2dbbfff27fmalita} 2233c196def91726913a417e703ac482bb2dbbfff27fmalita 22400d5c2c6523321d25b32905ff4822f083a4173eefmalitaSkTextBlob::RunIterator::RunIterator(const SkTextBlob* blob) 2253c196def91726913a417e703ac482bb2dbbfff27fmalita : fCurrentRun(RunRecord::First(blob)) 2263c196def91726913a417e703ac482bb2dbbfff27fmalita , fRemainingRuns(blob->fRunCount) { 2273c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(fStorageTop = (uint8_t*)blob + blob->fStorageSize;) 22800d5c2c6523321d25b32905ff4822f083a4173eefmalita} 22900d5c2c6523321d25b32905ff4822f083a4173eefmalita 23000d5c2c6523321d25b32905ff4822f083a4173eefmalitabool SkTextBlob::RunIterator::done() const { 2313c196def91726913a417e703ac482bb2dbbfff27fmalita return fRemainingRuns <= 0; 23200d5c2c6523321d25b32905ff4822f083a4173eefmalita} 23300d5c2c6523321d25b32905ff4822f083a4173eefmalita 23400d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkTextBlob::RunIterator::next() { 23500d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 2363c196def91726913a417e703ac482bb2dbbfff27fmalita 2373c196def91726913a417e703ac482bb2dbbfff27fmalita if (!this->done()) { 2383c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(fCurrentRun->validate(fStorageTop);) 2393c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRun = RunRecord::Next(fCurrentRun); 2403c196def91726913a417e703ac482bb2dbbfff27fmalita fRemainingRuns--; 2413c196def91726913a417e703ac482bb2dbbfff27fmalita } 24200d5c2c6523321d25b32905ff4822f083a4173eefmalita} 24300d5c2c6523321d25b32905ff4822f083a4173eefmalita 24400d5c2c6523321d25b32905ff4822f083a4173eefmalitauint32_t SkTextBlob::RunIterator::glyphCount() const { 24500d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 2463c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->glyphCount(); 24700d5c2c6523321d25b32905ff4822f083a4173eefmalita} 24800d5c2c6523321d25b32905ff4822f083a4173eefmalita 24900d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst uint16_t* SkTextBlob::RunIterator::glyphs() const { 25000d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 2513c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->glyphBuffer(); 25200d5c2c6523321d25b32905ff4822f083a4173eefmalita} 25300d5c2c6523321d25b32905ff4822f083a4173eefmalita 25400d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkScalar* SkTextBlob::RunIterator::pos() const { 25500d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 2563c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->posBuffer(); 25700d5c2c6523321d25b32905ff4822f083a4173eefmalita} 25800d5c2c6523321d25b32905ff4822f083a4173eefmalita 25900d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkPoint& SkTextBlob::RunIterator::offset() const { 26000d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 2613c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->offset(); 26200d5c2c6523321d25b32905ff4822f083a4173eefmalita} 26300d5c2c6523321d25b32905ff4822f083a4173eefmalita 26437ecbaffd1f9f6841aa562aa31a824d109d52988fmalitaSkTextBlob::GlyphPositioning SkTextBlob::RunIterator::positioning() const { 26500d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 2663c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->positioning(); 26700d5c2c6523321d25b32905ff4822f083a4173eefmalita} 26800d5c2c6523321d25b32905ff4822f083a4173eefmalita 26937ecbaffd1f9f6841aa562aa31a824d109d52988fmalitavoid SkTextBlob::RunIterator::applyFontToPaint(SkPaint* paint) const { 27000d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 27137ecbaffd1f9f6841aa562aa31a824d109d52988fmalita 2723c196def91726913a417e703ac482bb2dbbfff27fmalita const SkPaint& font = fCurrentRun->font(); 27337ecbaffd1f9f6841aa562aa31a824d109d52988fmalita 27437ecbaffd1f9f6841aa562aa31a824d109d52988fmalita paint->setTypeface(font.getTypeface()); 27537ecbaffd1f9f6841aa562aa31a824d109d52988fmalita paint->setTextEncoding(font.getTextEncoding()); 27637ecbaffd1f9f6841aa562aa31a824d109d52988fmalita paint->setTextSize(font.getTextSize()); 27737ecbaffd1f9f6841aa562aa31a824d109d52988fmalita paint->setTextScaleX(font.getTextScaleX()); 27837ecbaffd1f9f6841aa562aa31a824d109d52988fmalita paint->setTextSkewX(font.getTextSkewX()); 27937ecbaffd1f9f6841aa562aa31a824d109d52988fmalita paint->setHinting(font.getHinting()); 28037ecbaffd1f9f6841aa562aa31a824d109d52988fmalita 28137ecbaffd1f9f6841aa562aa31a824d109d52988fmalita uint32_t flagsMask = SkPaint::kAntiAlias_Flag 28237ecbaffd1f9f6841aa562aa31a824d109d52988fmalita | SkPaint::kUnderlineText_Flag 28337ecbaffd1f9f6841aa562aa31a824d109d52988fmalita | SkPaint::kStrikeThruText_Flag 28437ecbaffd1f9f6841aa562aa31a824d109d52988fmalita | SkPaint::kFakeBoldText_Flag 28537ecbaffd1f9f6841aa562aa31a824d109d52988fmalita | SkPaint::kLinearText_Flag 28637ecbaffd1f9f6841aa562aa31a824d109d52988fmalita | SkPaint::kSubpixelText_Flag 28737ecbaffd1f9f6841aa562aa31a824d109d52988fmalita | SkPaint::kDevKernText_Flag 28837ecbaffd1f9f6841aa562aa31a824d109d52988fmalita | SkPaint::kLCDRenderText_Flag 28937ecbaffd1f9f6841aa562aa31a824d109d52988fmalita | SkPaint::kEmbeddedBitmapText_Flag 29037ecbaffd1f9f6841aa562aa31a824d109d52988fmalita | SkPaint::kAutoHinting_Flag 29137ecbaffd1f9f6841aa562aa31a824d109d52988fmalita | SkPaint::kVerticalText_Flag 29237ecbaffd1f9f6841aa562aa31a824d109d52988fmalita | SkPaint::kGenA8FromLCD_Flag 29337ecbaffd1f9f6841aa562aa31a824d109d52988fmalita | SkPaint::kDistanceFieldTextTEMP_Flag; 29437ecbaffd1f9f6841aa562aa31a824d109d52988fmalita paint->setFlags((paint->getFlags() & ~flagsMask) | (font.getFlags() & flagsMask)); 29500d5c2c6523321d25b32905ff4822f083a4173eefmalita} 29600d5c2c6523321d25b32905ff4822f083a4173eefmalita 2973c196def91726913a417e703ac482bb2dbbfff27fmalitaSkTextBlobBuilder::SkTextBlobBuilder() 2983c196def91726913a417e703ac482bb2dbbfff27fmalita : fStorageSize(0) 2993c196def91726913a417e703ac482bb2dbbfff27fmalita , fStorageUsed(0) 3003c196def91726913a417e703ac482bb2dbbfff27fmalita , fRunCount(0) 3013c196def91726913a417e703ac482bb2dbbfff27fmalita , fDeferredBounds(false) 3023c196def91726913a417e703ac482bb2dbbfff27fmalita , fLastRun(0) { 30300d5c2c6523321d25b32905ff4822f083a4173eefmalita fBounds.setEmpty(); 30400d5c2c6523321d25b32905ff4822f083a4173eefmalita} 30500d5c2c6523321d25b32905ff4822f083a4173eefmalita 30600d5c2c6523321d25b32905ff4822f083a4173eefmalitaSkTextBlobBuilder::~SkTextBlobBuilder() { 3073c196def91726913a417e703ac482bb2dbbfff27fmalita if (NULL != fStorage.get()) { 3083c196def91726913a417e703ac482bb2dbbfff27fmalita // We are abandoning runs and must destruct the associated font data. 3093c196def91726913a417e703ac482bb2dbbfff27fmalita // The easiest way to accomplish that is to use the blob destructor. 3103c196def91726913a417e703ac482bb2dbbfff27fmalita build()->unref(); 3113c196def91726913a417e703ac482bb2dbbfff27fmalita } 31200d5c2c6523321d25b32905ff4822f083a4173eefmalita} 31300d5c2c6523321d25b32905ff4822f083a4173eefmalita 31400d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkTextBlobBuilder::updateDeferredBounds() { 3153c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(!fDeferredBounds || fRunCount > 0); 31600d5c2c6523321d25b32905ff4822f083a4173eefmalita 31700d5c2c6523321d25b32905ff4822f083a4173eefmalita if (!fDeferredBounds) { 31800d5c2c6523321d25b32905ff4822f083a4173eefmalita return; 31900d5c2c6523321d25b32905ff4822f083a4173eefmalita } 32000d5c2c6523321d25b32905ff4822f083a4173eefmalita 32100d5c2c6523321d25b32905ff4822f083a4173eefmalita // FIXME: measure the current run & union bounds 32200d5c2c6523321d25b32905ff4822f083a4173eefmalita fDeferredBounds = false; 32300d5c2c6523321d25b32905ff4822f083a4173eefmalita} 32400d5c2c6523321d25b32905ff4822f083a4173eefmalita 3253c196def91726913a417e703ac482bb2dbbfff27fmalitavoid SkTextBlobBuilder::reserve(size_t size) { 3263c196def91726913a417e703ac482bb2dbbfff27fmalita // We don't currently pre-allocate, but maybe someday... 3273c196def91726913a417e703ac482bb2dbbfff27fmalita if (fStorageUsed + size <= fStorageSize) { 3283c196def91726913a417e703ac482bb2dbbfff27fmalita return; 3293c196def91726913a417e703ac482bb2dbbfff27fmalita } 3303c196def91726913a417e703ac482bb2dbbfff27fmalita 3313c196def91726913a417e703ac482bb2dbbfff27fmalita if (0 == fRunCount) { 3323c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(NULL == fStorage.get()); 3333c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(0 == fStorageSize); 3343c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(0 == fStorageUsed); 33513645ea0ea87038ebd71be3bd6d53b313069a9e4fmalita 3363c196def91726913a417e703ac482bb2dbbfff27fmalita // the first allocation also includes blob storage 3373c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed += sizeof(SkTextBlob); 3383c196def91726913a417e703ac482bb2dbbfff27fmalita } 3393c196def91726913a417e703ac482bb2dbbfff27fmalita 3403c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageSize = fStorageUsed + size; 3413c196def91726913a417e703ac482bb2dbbfff27fmalita // FYI: This relies on everything we store being relocatable, particularly SkPaint. 3423c196def91726913a417e703ac482bb2dbbfff27fmalita fStorage.realloc(fStorageSize); 3433c196def91726913a417e703ac482bb2dbbfff27fmalita} 3443c196def91726913a417e703ac482bb2dbbfff27fmalita 3453c196def91726913a417e703ac482bb2dbbfff27fmalitabool SkTextBlobBuilder::mergeRun(const SkPaint &font, SkTextBlob::GlyphPositioning positioning, 3463c196def91726913a417e703ac482bb2dbbfff27fmalita int count, SkPoint offset) { 3473c196def91726913a417e703ac482bb2dbbfff27fmalita if (0 == fLastRun) { 3483c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(0 == fRunCount); 3493c196def91726913a417e703ac482bb2dbbfff27fmalita return false; 3503c196def91726913a417e703ac482bb2dbbfff27fmalita } 3513c196def91726913a417e703ac482bb2dbbfff27fmalita 3523c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fLastRun >= sizeof(SkTextBlob)); 3533c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + 3543c196def91726913a417e703ac482bb2dbbfff27fmalita fLastRun); 3553c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(run->glyphCount() > 0); 3563c196def91726913a417e703ac482bb2dbbfff27fmalita 3573c196def91726913a417e703ac482bb2dbbfff27fmalita if (run->positioning() != positioning 3583c196def91726913a417e703ac482bb2dbbfff27fmalita || run->font() != font 3593c196def91726913a417e703ac482bb2dbbfff27fmalita || (run->glyphCount() + count < run->glyphCount())) { 3603c196def91726913a417e703ac482bb2dbbfff27fmalita return false; 36100d5c2c6523321d25b32905ff4822f083a4173eefmalita } 36200d5c2c6523321d25b32905ff4822f083a4173eefmalita 36300d5c2c6523321d25b32905ff4822f083a4173eefmalita // we can merge same-font/same-positioning runs in the following cases: 36400d5c2c6523321d25b32905ff4822f083a4173eefmalita // * fully positioned run following another fully positioned run 36500d5c2c6523321d25b32905ff4822f083a4173eefmalita // * horizontally postioned run following another horizontally positioned run with the same 36600d5c2c6523321d25b32905ff4822f083a4173eefmalita // y-offset 3673c196def91726913a417e703ac482bb2dbbfff27fmalita if (SkTextBlob::kFull_Positioning != positioning 3683c196def91726913a417e703ac482bb2dbbfff27fmalita && (SkTextBlob::kHorizontal_Positioning != positioning 3693c196def91726913a417e703ac482bb2dbbfff27fmalita || run->offset().y() != offset.y())) { 3703c196def91726913a417e703ac482bb2dbbfff27fmalita return false; 37100d5c2c6523321d25b32905ff4822f083a4173eefmalita } 37200d5c2c6523321d25b32905ff4822f083a4173eefmalita 3733c196def91726913a417e703ac482bb2dbbfff27fmalita size_t sizeDelta = SkTextBlob::RunRecord::StorageSize(run->glyphCount() + count, positioning) - 3743c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord::StorageSize(run->glyphCount(), positioning); 3753c196def91726913a417e703ac482bb2dbbfff27fmalita this->reserve(sizeDelta); 3763c196def91726913a417e703ac482bb2dbbfff27fmalita 3773c196def91726913a417e703ac482bb2dbbfff27fmalita // reserve may have realloced 3783c196def91726913a417e703ac482bb2dbbfff27fmalita run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + fLastRun); 3793c196def91726913a417e703ac482bb2dbbfff27fmalita uint32_t preMergeCount = run->glyphCount(); 3803c196def91726913a417e703ac482bb2dbbfff27fmalita run->grow(count); 38100d5c2c6523321d25b32905ff4822f083a4173eefmalita 3823c196def91726913a417e703ac482bb2dbbfff27fmalita // Callers expect the buffers to point at the newly added slice, ant not at the beginning. 3833c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRunBuffer.glyphs = run->glyphBuffer() + preMergeCount; 3843c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRunBuffer.pos = run->posBuffer() 3853c196def91726913a417e703ac482bb2dbbfff27fmalita + preMergeCount * SkTextBlob::ScalarsPerGlyph(positioning); 3863c196def91726913a417e703ac482bb2dbbfff27fmalita 3873c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed += sizeDelta; 3883c196def91726913a417e703ac482bb2dbbfff27fmalita 3893c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fStorageUsed <= fStorageSize); 3903c196def91726913a417e703ac482bb2dbbfff27fmalita run->validate(fStorage.get() + fStorageUsed); 3913c196def91726913a417e703ac482bb2dbbfff27fmalita 3923c196def91726913a417e703ac482bb2dbbfff27fmalita return true; 39300d5c2c6523321d25b32905ff4822f083a4173eefmalita} 39400d5c2c6523321d25b32905ff4822f083a4173eefmalita 39500d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkTextBlobBuilder::allocInternal(const SkPaint &font, 39600d5c2c6523321d25b32905ff4822f083a4173eefmalita SkTextBlob::GlyphPositioning positioning, 39700d5c2c6523321d25b32905ff4822f083a4173eefmalita int count, SkPoint offset, const SkRect* bounds) { 39800d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(count > 0); 3993c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(SkPaint::kGlyphID_TextEncoding == font.getTextEncoding()); 40000d5c2c6523321d25b32905ff4822f083a4173eefmalita 4013c196def91726913a417e703ac482bb2dbbfff27fmalita if (!this->mergeRun(font, positioning, count, offset)) { 4023c196def91726913a417e703ac482bb2dbbfff27fmalita updateDeferredBounds(); 40300d5c2c6523321d25b32905ff4822f083a4173eefmalita 4043c196def91726913a417e703ac482bb2dbbfff27fmalita size_t runSize = SkTextBlob::RunRecord::StorageSize(count, positioning); 4053c196def91726913a417e703ac482bb2dbbfff27fmalita this->reserve(runSize); 40600d5c2c6523321d25b32905ff4822f083a4173eefmalita 4073c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fStorageUsed >= sizeof(SkTextBlob)); 4083c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fStorageUsed + runSize <= fStorageSize); 40900d5c2c6523321d25b32905ff4822f083a4173eefmalita 4103c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord* run = new (fStorage.get() + fStorageUsed) 4113c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord(count, offset, font, positioning); 41200d5c2c6523321d25b32905ff4822f083a4173eefmalita 4133c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRunBuffer.glyphs = run->glyphBuffer(); 4143c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRunBuffer.pos = run->posBuffer(); 41500d5c2c6523321d25b32905ff4822f083a4173eefmalita 4163c196def91726913a417e703ac482bb2dbbfff27fmalita fLastRun = fStorageUsed; 4173c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed += runSize; 4183c196def91726913a417e703ac482bb2dbbfff27fmalita fRunCount++; 4193c196def91726913a417e703ac482bb2dbbfff27fmalita 4203c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fStorageUsed <= fStorageSize); 4213c196def91726913a417e703ac482bb2dbbfff27fmalita run->validate(fStorage.get() + fStorageUsed); 4223c196def91726913a417e703ac482bb2dbbfff27fmalita } 42300d5c2c6523321d25b32905ff4822f083a4173eefmalita 42400d5c2c6523321d25b32905ff4822f083a4173eefmalita if (!fDeferredBounds) { 42549f085dddff10473b6ebf832a974288300224e60bsalomon if (bounds) { 42600d5c2c6523321d25b32905ff4822f083a4173eefmalita fBounds.join(*bounds); 42700d5c2c6523321d25b32905ff4822f083a4173eefmalita } else { 42800d5c2c6523321d25b32905ff4822f083a4173eefmalita fDeferredBounds = true; 42900d5c2c6523321d25b32905ff4822f083a4173eefmalita } 43000d5c2c6523321d25b32905ff4822f083a4173eefmalita } 43100d5c2c6523321d25b32905ff4822f083a4173eefmalita} 43200d5c2c6523321d25b32905ff4822f083a4173eefmalita 43300d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRun(const SkPaint& font, int count, 43400d5c2c6523321d25b32905ff4822f083a4173eefmalita SkScalar x, SkScalar y, 43500d5c2c6523321d25b32905ff4822f083a4173eefmalita const SkRect* bounds) { 43600d5c2c6523321d25b32905ff4822f083a4173eefmalita this->allocInternal(font, SkTextBlob::kDefault_Positioning, count, SkPoint::Make(x, y), bounds); 43700d5c2c6523321d25b32905ff4822f083a4173eefmalita 43800d5c2c6523321d25b32905ff4822f083a4173eefmalita return fCurrentRunBuffer; 43900d5c2c6523321d25b32905ff4822f083a4173eefmalita} 44000d5c2c6523321d25b32905ff4822f083a4173eefmalita 44100d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPosH(const SkPaint& font, int count, 44200d5c2c6523321d25b32905ff4822f083a4173eefmalita SkScalar y, 44300d5c2c6523321d25b32905ff4822f083a4173eefmalita const SkRect* bounds) { 44400d5c2c6523321d25b32905ff4822f083a4173eefmalita this->allocInternal(font, SkTextBlob::kHorizontal_Positioning, count, SkPoint::Make(0, y), 44500d5c2c6523321d25b32905ff4822f083a4173eefmalita bounds); 44600d5c2c6523321d25b32905ff4822f083a4173eefmalita 44700d5c2c6523321d25b32905ff4822f083a4173eefmalita return fCurrentRunBuffer; 44800d5c2c6523321d25b32905ff4822f083a4173eefmalita} 44900d5c2c6523321d25b32905ff4822f083a4173eefmalita 45000d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPos(const SkPaint& font, int count, 45100d5c2c6523321d25b32905ff4822f083a4173eefmalita const SkRect *bounds) { 45200d5c2c6523321d25b32905ff4822f083a4173eefmalita this->allocInternal(font, SkTextBlob::kFull_Positioning, count, SkPoint::Make(0, 0), bounds); 45300d5c2c6523321d25b32905ff4822f083a4173eefmalita 45400d5c2c6523321d25b32905ff4822f083a4173eefmalita return fCurrentRunBuffer; 45500d5c2c6523321d25b32905ff4822f083a4173eefmalita} 45600d5c2c6523321d25b32905ff4822f083a4173eefmalita 45700d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkTextBlob* SkTextBlobBuilder::build() { 4583c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT((fRunCount > 0) == (NULL != fStorage.get())); 4593c196def91726913a417e703ac482bb2dbbfff27fmalita 4603c196def91726913a417e703ac482bb2dbbfff27fmalita this->updateDeferredBounds(); 4613c196def91726913a417e703ac482bb2dbbfff27fmalita 4623c196def91726913a417e703ac482bb2dbbfff27fmalita if (0 == fRunCount) { 4633c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(NULL == fStorage.get()); 4643c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed = sizeof(SkTextBlob); 4653c196def91726913a417e703ac482bb2dbbfff27fmalita fStorage.realloc(fStorageUsed); 46600d5c2c6523321d25b32905ff4822f083a4173eefmalita } 46700d5c2c6523321d25b32905ff4822f083a4173eefmalita 4683c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE( 4693c196def91726913a417e703ac482bb2dbbfff27fmalita size_t validateSize = sizeof(SkTextBlob); 4703c196def91726913a417e703ac482bb2dbbfff27fmalita const SkTextBlob::RunRecord* run = 4713c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord::First(reinterpret_cast<const SkTextBlob*>(fStorage.get())); 4723c196def91726913a417e703ac482bb2dbbfff27fmalita for (int i = 0; i < fRunCount; ++i) { 4733c196def91726913a417e703ac482bb2dbbfff27fmalita validateSize += SkTextBlob::RunRecord::StorageSize(run->fCount, run->fPositioning); 4743c196def91726913a417e703ac482bb2dbbfff27fmalita run->validate(fStorage.get() + fStorageUsed); 4753c196def91726913a417e703ac482bb2dbbfff27fmalita run = SkTextBlob::RunRecord::Next(run); 4763c196def91726913a417e703ac482bb2dbbfff27fmalita } 4773c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(validateSize == fStorageUsed); 4783c196def91726913a417e703ac482bb2dbbfff27fmalita ) 4793c196def91726913a417e703ac482bb2dbbfff27fmalita 4803c196def91726913a417e703ac482bb2dbbfff27fmalita const SkTextBlob* blob = new (fStorage.detach()) SkTextBlob(fRunCount, fBounds); 4813c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(const_cast<SkTextBlob*>(blob)->fStorageSize = fStorageSize;) 4823c196def91726913a417e703ac482bb2dbbfff27fmalita 4833c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed = 0; 4843c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageSize = 0; 4853c196def91726913a417e703ac482bb2dbbfff27fmalita fRunCount = 0; 4863c196def91726913a417e703ac482bb2dbbfff27fmalita fLastRun = 0; 4873c196def91726913a417e703ac482bb2dbbfff27fmalita fBounds.setEmpty(); 4883c196def91726913a417e703ac482bb2dbbfff27fmalita 48900d5c2c6523321d25b32905ff4822f083a4173eefmalita return blob; 49000d5c2c6523321d25b32905ff4822f083a4173eefmalita} 49100d5c2c6523321d25b32905ff4822f083a4173eefmalita 492