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" 113dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita#include "SkTypeface.h" 12b7425173f96e93b090787e2386ba5f022b6c2869fmalita#include "SkWriteBuffer.h" 13b7425173f96e93b090787e2386ba5f022b6c2869fmalita 14055f6b59d879b2adac52748ea5a58c8a05bf501cfmalitanamespace { 15055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 16055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita// TODO(fmalita): replace with SkFont. 17055f6b59d879b2adac52748ea5a58c8a05bf501cfmalitaclass RunFont : SkNoncopyable { 18055f6b59d879b2adac52748ea5a58c8a05bf501cfmalitapublic: 19055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita RunFont(const SkPaint& paint) 20055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita : fSize(paint.getTextSize()) 21055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita , fScaleX(paint.getTextScaleX()) 22055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita , fTypeface(SkSafeRef(paint.getTypeface())) 23055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita , fSkewX(paint.getTextSkewX()) 24055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita , fHinting(paint.getHinting()) 25055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita , fFlags(paint.getFlags() & kFlagsMask) { } 26055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 27055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita void applyToPaint(SkPaint* paint) const { 28055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); 29055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setTypeface(fTypeface.get()); 30055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setTextSize(fSize); 31055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setTextScaleX(fScaleX); 32055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setTextSkewX(fSkewX); 33055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setHinting(static_cast<SkPaint::Hinting>(fHinting)); 34055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 35055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setFlags((paint->getFlags() & ~kFlagsMask) | fFlags); 36055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita } 37055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 38055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita bool operator==(const RunFont& other) const { 39055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita return fTypeface == other.fTypeface 40055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita && fSize == other.fSize 41055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita && fScaleX == other.fScaleX 42055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita && fSkewX == other.fSkewX 43055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita && fHinting == other.fHinting 44055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita && fFlags == other.fFlags; 45055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita } 46055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 47055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita bool operator!=(const RunFont& other) const { 48055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita return !(*this == other); 49055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita } 509e36c1a9306f052331550dab4728b9875127bfb5joshualitt 519e36c1a9306f052331550dab4728b9875127bfb5joshualitt uint32_t flags() const { return fFlags; } 529e36c1a9306f052331550dab4728b9875127bfb5joshualitt 53055f6b59d879b2adac52748ea5a58c8a05bf501cfmalitaprivate: 54055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita const static uint32_t kFlagsMask = 55055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kAntiAlias_Flag | 56055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kUnderlineText_Flag | 57055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kStrikeThruText_Flag | 58055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kFakeBoldText_Flag | 59055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kLinearText_Flag | 60055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kSubpixelText_Flag | 61055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kDevKernText_Flag | 62055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kLCDRenderText_Flag | 63055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kEmbeddedBitmapText_Flag | 64055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kAutoHinting_Flag | 65055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kVerticalText_Flag | 66055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kGenA8FromLCD_Flag | 67055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kDistanceFieldTextTEMP_Flag; 68055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 69055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkScalar fSize; 70055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkScalar fScaleX; 71055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 72055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita // Keep this SkAutoTUnref off the first position, to avoid interfering with SkNoncopyable 73055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita // empty baseclass optimization (http://code.google.com/p/skia/issues/detail?id=3694). 74055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkAutoTUnref<SkTypeface> fTypeface; 75055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkScalar fSkewX; 76055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 77055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SK_COMPILE_ASSERT(SkPaint::kFull_Hinting < 4, insufficient_hinting_bits); 78055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita uint32_t fHinting : 2; 79055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SK_COMPILE_ASSERT((kFlagsMask & 0xffff) == kFlagsMask, insufficient_flags_bits); 80055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita uint32_t fFlags : 16; 81055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 82055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita typedef SkNoncopyable INHERITED; 83055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita}; 84055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 85055f6b59d879b2adac52748ea5a58c8a05bf501cfmalitastruct RunFontStorageEquivalent { 86055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkScalar fSize, fScaleX; 87055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita void* fTypeface; 88055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkScalar fSkewX; 89055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita uint32_t fFlags; 90055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita}; 91055f6b59d879b2adac52748ea5a58c8a05bf501cfmalitaSK_COMPILE_ASSERT(sizeof(RunFont) == sizeof(RunFontStorageEquivalent), runfont_should_stay_packed); 92055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 93055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita} // anonymous namespace 94055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 953c196def91726913a417e703ac482bb2dbbfff27fmalita// 963c196def91726913a417e703ac482bb2dbbfff27fmalita// Textblob data is laid out into externally-managed storage as follows: 973c196def91726913a417e703ac482bb2dbbfff27fmalita// 983c196def91726913a417e703ac482bb2dbbfff27fmalita// ----------------------------------------------------------------------------- 993c196def91726913a417e703ac482bb2dbbfff27fmalita// | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ... 1003c196def91726913a417e703ac482bb2dbbfff27fmalita// ----------------------------------------------------------------------------- 1013c196def91726913a417e703ac482bb2dbbfff27fmalita// 1023c196def91726913a417e703ac482bb2dbbfff27fmalita// Each run record describes a text blob run, and can be used to determine the (implicit) 1033c196def91726913a417e703ac482bb2dbbfff27fmalita// location of the following record. 1043c196def91726913a417e703ac482bb2dbbfff27fmalita 1053c196def91726913a417e703ac482bb2dbbfff27fmalitaSkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;) 1063c196def91726913a417e703ac482bb2dbbfff27fmalita 1073c196def91726913a417e703ac482bb2dbbfff27fmalitaclass SkTextBlob::RunRecord { 1083c196def91726913a417e703ac482bb2dbbfff27fmalitapublic: 1093c196def91726913a417e703ac482bb2dbbfff27fmalita RunRecord(uint32_t count, const SkPoint& offset, const SkPaint& font, GlyphPositioning pos) 110055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita : fFont(font) 111055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita , fCount(count) 1123c196def91726913a417e703ac482bb2dbbfff27fmalita , fOffset(offset) 1133c196def91726913a417e703ac482bb2dbbfff27fmalita , fPositioning(pos) { 1143c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(fMagic = kRunRecordMagic); 1153c196def91726913a417e703ac482bb2dbbfff27fmalita } 1163c196def91726913a417e703ac482bb2dbbfff27fmalita 1173c196def91726913a417e703ac482bb2dbbfff27fmalita uint32_t glyphCount() const { 1183c196def91726913a417e703ac482bb2dbbfff27fmalita return fCount; 1193c196def91726913a417e703ac482bb2dbbfff27fmalita } 1203c196def91726913a417e703ac482bb2dbbfff27fmalita 1213c196def91726913a417e703ac482bb2dbbfff27fmalita const SkPoint& offset() const { 1223c196def91726913a417e703ac482bb2dbbfff27fmalita return fOffset; 1233c196def91726913a417e703ac482bb2dbbfff27fmalita } 1243c196def91726913a417e703ac482bb2dbbfff27fmalita 125055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita const RunFont& font() const { 1263c196def91726913a417e703ac482bb2dbbfff27fmalita return fFont; 1273c196def91726913a417e703ac482bb2dbbfff27fmalita } 1283c196def91726913a417e703ac482bb2dbbfff27fmalita 1293c196def91726913a417e703ac482bb2dbbfff27fmalita GlyphPositioning positioning() const { 1303c196def91726913a417e703ac482bb2dbbfff27fmalita return fPositioning; 1313c196def91726913a417e703ac482bb2dbbfff27fmalita } 1323c196def91726913a417e703ac482bb2dbbfff27fmalita 1333c196def91726913a417e703ac482bb2dbbfff27fmalita uint16_t* glyphBuffer() const { 1343c196def91726913a417e703ac482bb2dbbfff27fmalita // Glyph are stored immediately following the record. 1353c196def91726913a417e703ac482bb2dbbfff27fmalita return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1); 1363c196def91726913a417e703ac482bb2dbbfff27fmalita } 1373c196def91726913a417e703ac482bb2dbbfff27fmalita 1383c196def91726913a417e703ac482bb2dbbfff27fmalita SkScalar* posBuffer() const { 1393c196def91726913a417e703ac482bb2dbbfff27fmalita // Position scalars follow the (aligned) glyph buffer. 1403c196def91726913a417e703ac482bb2dbbfff27fmalita return reinterpret_cast<SkScalar*>(reinterpret_cast<uint8_t*>(this->glyphBuffer()) + 1413c196def91726913a417e703ac482bb2dbbfff27fmalita SkAlign4(fCount * sizeof(uint16_t))); 1423c196def91726913a417e703ac482bb2dbbfff27fmalita } 1433c196def91726913a417e703ac482bb2dbbfff27fmalita 1443c196def91726913a417e703ac482bb2dbbfff27fmalita static size_t StorageSize(int glyphCount, SkTextBlob::GlyphPositioning positioning) { 1453c196def91726913a417e703ac482bb2dbbfff27fmalita // RunRecord object + (aligned) glyph buffer + position buffer 1463c196def91726913a417e703ac482bb2dbbfff27fmalita return SkAlignPtr(sizeof(SkTextBlob::RunRecord) 1473c196def91726913a417e703ac482bb2dbbfff27fmalita + SkAlign4(glyphCount* sizeof(uint16_t)) 1483c196def91726913a417e703ac482bb2dbbfff27fmalita + glyphCount * sizeof(SkScalar) * ScalarsPerGlyph(positioning)); 1493c196def91726913a417e703ac482bb2dbbfff27fmalita } 1503c196def91726913a417e703ac482bb2dbbfff27fmalita 1513c196def91726913a417e703ac482bb2dbbfff27fmalita static const RunRecord* First(const SkTextBlob* blob) { 1523c196def91726913a417e703ac482bb2dbbfff27fmalita // The first record (if present) is stored following the blob object. 1533c196def91726913a417e703ac482bb2dbbfff27fmalita return reinterpret_cast<const RunRecord*>(blob + 1); 1543c196def91726913a417e703ac482bb2dbbfff27fmalita } 1553c196def91726913a417e703ac482bb2dbbfff27fmalita 1563c196def91726913a417e703ac482bb2dbbfff27fmalita static const RunRecord* Next(const RunRecord* run) { 1573c196def91726913a417e703ac482bb2dbbfff27fmalita return reinterpret_cast<const RunRecord*>(reinterpret_cast<const uint8_t*>(run) 1583c196def91726913a417e703ac482bb2dbbfff27fmalita + StorageSize(run->glyphCount(), run->positioning())); 1593c196def91726913a417e703ac482bb2dbbfff27fmalita } 1603c196def91726913a417e703ac482bb2dbbfff27fmalita 1613c196def91726913a417e703ac482bb2dbbfff27fmalita void validate(uint8_t* storageTop) const { 1623c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(kRunRecordMagic == fMagic); 1633c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT((uint8_t*)Next(this) <= storageTop); 1643c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(glyphBuffer() + fCount <= (uint16_t*)posBuffer()); 1653c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(posBuffer() + fCount * ScalarsPerGlyph(fPositioning) <= (SkScalar*)Next(this)); 1663c196def91726913a417e703ac482bb2dbbfff27fmalita } 1673c196def91726913a417e703ac482bb2dbbfff27fmalita 1683c196def91726913a417e703ac482bb2dbbfff27fmalitaprivate: 1693c196def91726913a417e703ac482bb2dbbfff27fmalita friend class SkTextBlobBuilder; 1703c196def91726913a417e703ac482bb2dbbfff27fmalita 1713c196def91726913a417e703ac482bb2dbbfff27fmalita void grow(uint32_t count) { 1723c196def91726913a417e703ac482bb2dbbfff27fmalita SkScalar* initialPosBuffer = posBuffer(); 1733c196def91726913a417e703ac482bb2dbbfff27fmalita uint32_t initialCount = fCount; 1743c196def91726913a417e703ac482bb2dbbfff27fmalita fCount += count; 1753c196def91726913a417e703ac482bb2dbbfff27fmalita 1763c196def91726913a417e703ac482bb2dbbfff27fmalita // Move the initial pos scalars to their new location. 1773c196def91726913a417e703ac482bb2dbbfff27fmalita size_t copySize = initialCount * sizeof(SkScalar) * ScalarsPerGlyph(fPositioning); 1783c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT((uint8_t*)posBuffer() + copySize <= (uint8_t*)Next(this)); 1793c196def91726913a417e703ac482bb2dbbfff27fmalita 1803c196def91726913a417e703ac482bb2dbbfff27fmalita // memmove, as the buffers may overlap 1813c196def91726913a417e703ac482bb2dbbfff27fmalita memmove(posBuffer(), initialPosBuffer, copySize); 1823c196def91726913a417e703ac482bb2dbbfff27fmalita } 1833c196def91726913a417e703ac482bb2dbbfff27fmalita 184055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita RunFont fFont; 1853c196def91726913a417e703ac482bb2dbbfff27fmalita uint32_t fCount; 1863c196def91726913a417e703ac482bb2dbbfff27fmalita SkPoint fOffset; 1873c196def91726913a417e703ac482bb2dbbfff27fmalita GlyphPositioning fPositioning; 1883c196def91726913a417e703ac482bb2dbbfff27fmalita 1893c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(unsigned fMagic;) 1903c196def91726913a417e703ac482bb2dbbfff27fmalita}; 1913c196def91726913a417e703ac482bb2dbbfff27fmalita 1922af858354d913397a6c316ef46a5d52d686e10abjoshualittstatic int32_t gNextID = 1; 1932af858354d913397a6c316ef46a5d52d686e10abjoshualittstatic int32_t next_id() { 1942af858354d913397a6c316ef46a5d52d686e10abjoshualitt int32_t id; 1952af858354d913397a6c316ef46a5d52d686e10abjoshualitt do { 1962af858354d913397a6c316ef46a5d52d686e10abjoshualitt id = sk_atomic_inc(&gNextID); 1972af858354d913397a6c316ef46a5d52d686e10abjoshualitt } while (id == SK_InvalidGenID); 1982af858354d913397a6c316ef46a5d52d686e10abjoshualitt return id; 1992af858354d913397a6c316ef46a5d52d686e10abjoshualitt} 2002af858354d913397a6c316ef46a5d52d686e10abjoshualitt 2013c196def91726913a417e703ac482bb2dbbfff27fmalitaSkTextBlob::SkTextBlob(int runCount, const SkRect& bounds) 2023c196def91726913a417e703ac482bb2dbbfff27fmalita : fRunCount(runCount) 2032af858354d913397a6c316ef46a5d52d686e10abjoshualitt , fBounds(bounds) 2042af858354d913397a6c316ef46a5d52d686e10abjoshualitt , fUniqueID(next_id()) { 20500d5c2c6523321d25b32905ff4822f083a4173eefmalita} 20600d5c2c6523321d25b32905ff4822f083a4173eefmalita 2073c196def91726913a417e703ac482bb2dbbfff27fmalitaSkTextBlob::~SkTextBlob() { 2083c196def91726913a417e703ac482bb2dbbfff27fmalita const RunRecord* run = RunRecord::First(this); 2093c196def91726913a417e703ac482bb2dbbfff27fmalita for (int i = 0; i < fRunCount; ++i) { 2103c196def91726913a417e703ac482bb2dbbfff27fmalita const RunRecord* nextRun = RunRecord::Next(run); 2113c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(run->validate((uint8_t*)this + fStorageSize);) 2123c196def91726913a417e703ac482bb2dbbfff27fmalita run->~RunRecord(); 2133c196def91726913a417e703ac482bb2dbbfff27fmalita run = nextRun; 2143c196def91726913a417e703ac482bb2dbbfff27fmalita } 2153c196def91726913a417e703ac482bb2dbbfff27fmalita} 2163c196def91726913a417e703ac482bb2dbbfff27fmalita 217b7425173f96e93b090787e2386ba5f022b6c2869fmalitavoid SkTextBlob::flatten(SkWriteBuffer& buffer) const { 2183c196def91726913a417e703ac482bb2dbbfff27fmalita int runCount = fRunCount; 219b7425173f96e93b090787e2386ba5f022b6c2869fmalita 220b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.write32(runCount); 221b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writeRect(fBounds); 222b7425173f96e93b090787e2386ba5f022b6c2869fmalita 223b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkPaint runPaint; 224b7425173f96e93b090787e2386ba5f022b6c2869fmalita RunIterator it(this); 225b7425173f96e93b090787e2386ba5f022b6c2869fmalita while (!it.done()) { 226b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkASSERT(it.glyphCount() > 0); 227b7425173f96e93b090787e2386ba5f022b6c2869fmalita 228b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.write32(it.glyphCount()); 229b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.write32(it.positioning()); 230b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writePoint(it.offset()); 231b7425173f96e93b090787e2386ba5f022b6c2869fmalita // This should go away when switching to SkFont 232b7425173f96e93b090787e2386ba5f022b6c2869fmalita it.applyFontToPaint(&runPaint); 233b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writePaint(runPaint); 234b7425173f96e93b090787e2386ba5f022b6c2869fmalita 235b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writeByteArray(it.glyphs(), it.glyphCount() * sizeof(uint16_t)); 236b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writeByteArray(it.pos(), 237b7425173f96e93b090787e2386ba5f022b6c2869fmalita it.glyphCount() * sizeof(SkScalar) * ScalarsPerGlyph(it.positioning())); 238b7425173f96e93b090787e2386ba5f022b6c2869fmalita 239b7425173f96e93b090787e2386ba5f022b6c2869fmalita it.next(); 240b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkDEBUGCODE(runCount--); 241b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 242b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkASSERT(0 == runCount); 243b7425173f96e93b090787e2386ba5f022b6c2869fmalita} 244b7425173f96e93b090787e2386ba5f022b6c2869fmalita 245b7425173f96e93b090787e2386ba5f022b6c2869fmalitaconst SkTextBlob* SkTextBlob::CreateFromBuffer(SkReadBuffer& reader) { 246b7425173f96e93b090787e2386ba5f022b6c2869fmalita int runCount = reader.read32(); 247b7425173f96e93b090787e2386ba5f022b6c2869fmalita if (runCount < 0) { 248b7425173f96e93b090787e2386ba5f022b6c2869fmalita return NULL; 249b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 250b7425173f96e93b090787e2386ba5f022b6c2869fmalita 251b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkRect bounds; 252b7425173f96e93b090787e2386ba5f022b6c2869fmalita reader.readRect(&bounds); 253b7425173f96e93b090787e2386ba5f022b6c2869fmalita 254b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkTextBlobBuilder blobBuilder; 255b7425173f96e93b090787e2386ba5f022b6c2869fmalita for (int i = 0; i < runCount; ++i) { 256b7425173f96e93b090787e2386ba5f022b6c2869fmalita int glyphCount = reader.read32(); 257b7425173f96e93b090787e2386ba5f022b6c2869fmalita GlyphPositioning pos = static_cast<GlyphPositioning>(reader.read32()); 258b7425173f96e93b090787e2386ba5f022b6c2869fmalita if (glyphCount <= 0 || pos > kFull_Positioning) { 259b7425173f96e93b090787e2386ba5f022b6c2869fmalita return NULL; 260b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 261b7425173f96e93b090787e2386ba5f022b6c2869fmalita 262b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkPoint offset; 263b7425173f96e93b090787e2386ba5f022b6c2869fmalita reader.readPoint(&offset); 264b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkPaint font; 265b7425173f96e93b090787e2386ba5f022b6c2869fmalita reader.readPaint(&font); 266b7425173f96e93b090787e2386ba5f022b6c2869fmalita 267b7425173f96e93b090787e2386ba5f022b6c2869fmalita const SkTextBlobBuilder::RunBuffer* buf = NULL; 268b7425173f96e93b090787e2386ba5f022b6c2869fmalita switch (pos) { 269b7425173f96e93b090787e2386ba5f022b6c2869fmalita case kDefault_Positioning: 270b7425173f96e93b090787e2386ba5f022b6c2869fmalita buf = &blobBuilder.allocRun(font, glyphCount, offset.x(), offset.y(), &bounds); 271b7425173f96e93b090787e2386ba5f022b6c2869fmalita break; 272b7425173f96e93b090787e2386ba5f022b6c2869fmalita case kHorizontal_Positioning: 273b7425173f96e93b090787e2386ba5f022b6c2869fmalita buf = &blobBuilder.allocRunPosH(font, glyphCount, offset.y(), &bounds); 274b7425173f96e93b090787e2386ba5f022b6c2869fmalita break; 275b7425173f96e93b090787e2386ba5f022b6c2869fmalita case kFull_Positioning: 276b7425173f96e93b090787e2386ba5f022b6c2869fmalita buf = &blobBuilder.allocRunPos(font, glyphCount, &bounds); 277b7425173f96e93b090787e2386ba5f022b6c2869fmalita break; 278b7425173f96e93b090787e2386ba5f022b6c2869fmalita default: 279b7425173f96e93b090787e2386ba5f022b6c2869fmalita return NULL; 280b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 281b7425173f96e93b090787e2386ba5f022b6c2869fmalita 282b7425173f96e93b090787e2386ba5f022b6c2869fmalita if (!reader.readByteArray(buf->glyphs, glyphCount * sizeof(uint16_t)) || 2833c196def91726913a417e703ac482bb2dbbfff27fmalita !reader.readByteArray(buf->pos, 2843c196def91726913a417e703ac482bb2dbbfff27fmalita glyphCount * sizeof(SkScalar) * ScalarsPerGlyph(pos))) { 285b7425173f96e93b090787e2386ba5f022b6c2869fmalita return NULL; 286b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 287b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 288b7425173f96e93b090787e2386ba5f022b6c2869fmalita 289b7425173f96e93b090787e2386ba5f022b6c2869fmalita return blobBuilder.build(); 290b7425173f96e93b090787e2386ba5f022b6c2869fmalita} 291b7425173f96e93b090787e2386ba5f022b6c2869fmalita 2923c196def91726913a417e703ac482bb2dbbfff27fmalitaunsigned SkTextBlob::ScalarsPerGlyph(GlyphPositioning pos) { 2933c196def91726913a417e703ac482bb2dbbfff27fmalita // GlyphPositioning values are directly mapped to scalars-per-glyph. 2943c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(pos <= 2); 2953c196def91726913a417e703ac482bb2dbbfff27fmalita return pos; 2963c196def91726913a417e703ac482bb2dbbfff27fmalita} 2973c196def91726913a417e703ac482bb2dbbfff27fmalita 29800d5c2c6523321d25b32905ff4822f083a4173eefmalitaSkTextBlob::RunIterator::RunIterator(const SkTextBlob* blob) 2993c196def91726913a417e703ac482bb2dbbfff27fmalita : fCurrentRun(RunRecord::First(blob)) 3003c196def91726913a417e703ac482bb2dbbfff27fmalita , fRemainingRuns(blob->fRunCount) { 3013c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(fStorageTop = (uint8_t*)blob + blob->fStorageSize;) 30200d5c2c6523321d25b32905ff4822f083a4173eefmalita} 30300d5c2c6523321d25b32905ff4822f083a4173eefmalita 30400d5c2c6523321d25b32905ff4822f083a4173eefmalitabool SkTextBlob::RunIterator::done() const { 3053c196def91726913a417e703ac482bb2dbbfff27fmalita return fRemainingRuns <= 0; 30600d5c2c6523321d25b32905ff4822f083a4173eefmalita} 30700d5c2c6523321d25b32905ff4822f083a4173eefmalita 30800d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkTextBlob::RunIterator::next() { 30900d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 3103c196def91726913a417e703ac482bb2dbbfff27fmalita 3113c196def91726913a417e703ac482bb2dbbfff27fmalita if (!this->done()) { 3123c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(fCurrentRun->validate(fStorageTop);) 3133c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRun = RunRecord::Next(fCurrentRun); 3143c196def91726913a417e703ac482bb2dbbfff27fmalita fRemainingRuns--; 3153c196def91726913a417e703ac482bb2dbbfff27fmalita } 31600d5c2c6523321d25b32905ff4822f083a4173eefmalita} 31700d5c2c6523321d25b32905ff4822f083a4173eefmalita 31800d5c2c6523321d25b32905ff4822f083a4173eefmalitauint32_t SkTextBlob::RunIterator::glyphCount() const { 31900d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 3203c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->glyphCount(); 32100d5c2c6523321d25b32905ff4822f083a4173eefmalita} 32200d5c2c6523321d25b32905ff4822f083a4173eefmalita 32300d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst uint16_t* SkTextBlob::RunIterator::glyphs() const { 32400d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 3253c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->glyphBuffer(); 32600d5c2c6523321d25b32905ff4822f083a4173eefmalita} 32700d5c2c6523321d25b32905ff4822f083a4173eefmalita 32800d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkScalar* SkTextBlob::RunIterator::pos() const { 32900d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 3303c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->posBuffer(); 33100d5c2c6523321d25b32905ff4822f083a4173eefmalita} 33200d5c2c6523321d25b32905ff4822f083a4173eefmalita 33300d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkPoint& SkTextBlob::RunIterator::offset() const { 33400d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 3353c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->offset(); 33600d5c2c6523321d25b32905ff4822f083a4173eefmalita} 33700d5c2c6523321d25b32905ff4822f083a4173eefmalita 33837ecbaffd1f9f6841aa562aa31a824d109d52988fmalitaSkTextBlob::GlyphPositioning SkTextBlob::RunIterator::positioning() const { 33900d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 3403c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->positioning(); 34100d5c2c6523321d25b32905ff4822f083a4173eefmalita} 34200d5c2c6523321d25b32905ff4822f083a4173eefmalita 34337ecbaffd1f9f6841aa562aa31a824d109d52988fmalitavoid SkTextBlob::RunIterator::applyFontToPaint(SkPaint* paint) const { 34400d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 34537ecbaffd1f9f6841aa562aa31a824d109d52988fmalita 346055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita fCurrentRun->font().applyToPaint(paint); 34700d5c2c6523321d25b32905ff4822f083a4173eefmalita} 34800d5c2c6523321d25b32905ff4822f083a4173eefmalita 3499e36c1a9306f052331550dab4728b9875127bfb5joshualittbool SkTextBlob::RunIterator::isLCD() const { 3509e36c1a9306f052331550dab4728b9875127bfb5joshualitt return SkToBool(fCurrentRun->font().flags() & SkPaint::kLCDRenderText_Flag); 3519e36c1a9306f052331550dab4728b9875127bfb5joshualitt} 3529e36c1a9306f052331550dab4728b9875127bfb5joshualitt 3533c196def91726913a417e703ac482bb2dbbfff27fmalitaSkTextBlobBuilder::SkTextBlobBuilder() 3543c196def91726913a417e703ac482bb2dbbfff27fmalita : fStorageSize(0) 3553c196def91726913a417e703ac482bb2dbbfff27fmalita , fStorageUsed(0) 3563c196def91726913a417e703ac482bb2dbbfff27fmalita , fRunCount(0) 3573c196def91726913a417e703ac482bb2dbbfff27fmalita , fDeferredBounds(false) 3583c196def91726913a417e703ac482bb2dbbfff27fmalita , fLastRun(0) { 35900d5c2c6523321d25b32905ff4822f083a4173eefmalita fBounds.setEmpty(); 36000d5c2c6523321d25b32905ff4822f083a4173eefmalita} 36100d5c2c6523321d25b32905ff4822f083a4173eefmalita 36200d5c2c6523321d25b32905ff4822f083a4173eefmalitaSkTextBlobBuilder::~SkTextBlobBuilder() { 3633c196def91726913a417e703ac482bb2dbbfff27fmalita if (NULL != fStorage.get()) { 3643c196def91726913a417e703ac482bb2dbbfff27fmalita // We are abandoning runs and must destruct the associated font data. 3653c196def91726913a417e703ac482bb2dbbfff27fmalita // The easiest way to accomplish that is to use the blob destructor. 3663c196def91726913a417e703ac482bb2dbbfff27fmalita build()->unref(); 3673c196def91726913a417e703ac482bb2dbbfff27fmalita } 36800d5c2c6523321d25b32905ff4822f083a4173eefmalita} 36900d5c2c6523321d25b32905ff4822f083a4173eefmalita 3703dc40ac9f968eee95eef5e8ee811e0640691df0ffmalitaSkRect SkTextBlobBuilder::TightRunBounds(const SkTextBlob::RunRecord& run) { 371f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkASSERT(SkTextBlob::kDefault_Positioning == run.positioning()); 3723dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita 373f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkRect bounds; 374055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint paint; 375055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita run.font().applyToPaint(&paint); 376055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint.measureText(run.glyphBuffer(), run.glyphCount() * sizeof(uint16_t), &bounds); 3773dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita 3783dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita return bounds.makeOffset(run.offset().x(), run.offset().y()); 3793dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita} 3803dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita 3813dc40ac9f968eee95eef5e8ee811e0640691df0ffmalitaSkRect SkTextBlobBuilder::ConservativeRunBounds(const SkTextBlob::RunRecord& run) { 3823dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita SkASSERT(run.glyphCount() > 0); 383f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkASSERT(SkTextBlob::kFull_Positioning == run.positioning() || 384f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkTextBlob::kHorizontal_Positioning == run.positioning()); 3853dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita 3863dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita // First, compute the glyph position bbox. 387f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkRect bounds; 388f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita switch (run.positioning()) { 389f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita case SkTextBlob::kHorizontal_Positioning: { 390f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita const SkScalar* glyphPos = run.posBuffer(); 391f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkASSERT((void*)(glyphPos + run.glyphCount()) <= SkTextBlob::RunRecord::Next(&run)); 392f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita 393f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkScalar minX = *glyphPos; 394f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkScalar maxX = *glyphPos; 395f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita for (unsigned i = 1; i < run.glyphCount(); ++i) { 396f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkScalar x = glyphPos[i]; 397f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita minX = SkMinScalar(x, minX); 398f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita maxX = SkMaxScalar(x, maxX); 399f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita } 400f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita 401f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita bounds.setLTRB(minX, 0, maxX, 0); 402f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita } break; 403f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita case SkTextBlob::kFull_Positioning: { 404f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita const SkPoint* glyphPosPts = reinterpret_cast<const SkPoint*>(run.posBuffer()); 405f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkASSERT((void*)(glyphPosPts + run.glyphCount()) <= SkTextBlob::RunRecord::Next(&run)); 406f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita 407f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita bounds.setBounds(glyphPosPts, run.glyphCount()); 408f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita } break; 409f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita default: 410f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkFAIL("unsupported positioning mode"); 4113dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita } 4123dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita 4133dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita // Expand by typeface glyph bounds. 414055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint paint; 415055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita run.font().applyToPaint(&paint); 416055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita const SkRect fontBounds = paint.getFontBounds(); 4173dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita bounds.fLeft += fontBounds.left(); 4183dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita bounds.fTop += fontBounds.top(); 4193dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita bounds.fRight += fontBounds.right(); 4203dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita bounds.fBottom += fontBounds.bottom(); 4213dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita 4223dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita // Offset by run position. 4233dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita return bounds.makeOffset(run.offset().x(), run.offset().y()); 4243dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita} 4253dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita 42600d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkTextBlobBuilder::updateDeferredBounds() { 4273c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(!fDeferredBounds || fRunCount > 0); 42800d5c2c6523321d25b32905ff4822f083a4173eefmalita 42900d5c2c6523321d25b32905ff4822f083a4173eefmalita if (!fDeferredBounds) { 43000d5c2c6523321d25b32905ff4822f083a4173eefmalita return; 43100d5c2c6523321d25b32905ff4822f083a4173eefmalita } 43200d5c2c6523321d25b32905ff4822f083a4173eefmalita 43319653d1d004610b4ba07ce563a5701164e120e45fmalita SkASSERT(fLastRun >= sizeof(SkTextBlob)); 43419653d1d004610b4ba07ce563a5701164e120e45fmalita SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + 43519653d1d004610b4ba07ce563a5701164e120e45fmalita fLastRun); 43619653d1d004610b4ba07ce563a5701164e120e45fmalita 437f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita // FIXME: we should also use conservative bounds for kDefault_Positioning. 438f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkRect runBounds = SkTextBlob::kDefault_Positioning == run->positioning() ? 439f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita TightRunBounds(*run) : ConservativeRunBounds(*run); 44019653d1d004610b4ba07ce563a5701164e120e45fmalita fBounds.join(runBounds); 44100d5c2c6523321d25b32905ff4822f083a4173eefmalita fDeferredBounds = false; 44200d5c2c6523321d25b32905ff4822f083a4173eefmalita} 44300d5c2c6523321d25b32905ff4822f083a4173eefmalita 4443c196def91726913a417e703ac482bb2dbbfff27fmalitavoid SkTextBlobBuilder::reserve(size_t size) { 4453c196def91726913a417e703ac482bb2dbbfff27fmalita // We don't currently pre-allocate, but maybe someday... 4463c196def91726913a417e703ac482bb2dbbfff27fmalita if (fStorageUsed + size <= fStorageSize) { 4473c196def91726913a417e703ac482bb2dbbfff27fmalita return; 4483c196def91726913a417e703ac482bb2dbbfff27fmalita } 4493c196def91726913a417e703ac482bb2dbbfff27fmalita 4503c196def91726913a417e703ac482bb2dbbfff27fmalita if (0 == fRunCount) { 4513c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(NULL == fStorage.get()); 4523c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(0 == fStorageSize); 4533c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(0 == fStorageUsed); 45413645ea0ea87038ebd71be3bd6d53b313069a9e4fmalita 4553c196def91726913a417e703ac482bb2dbbfff27fmalita // the first allocation also includes blob storage 4563c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed += sizeof(SkTextBlob); 4573c196def91726913a417e703ac482bb2dbbfff27fmalita } 4583c196def91726913a417e703ac482bb2dbbfff27fmalita 4593c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageSize = fStorageUsed + size; 4603c196def91726913a417e703ac482bb2dbbfff27fmalita // FYI: This relies on everything we store being relocatable, particularly SkPaint. 4613c196def91726913a417e703ac482bb2dbbfff27fmalita fStorage.realloc(fStorageSize); 4623c196def91726913a417e703ac482bb2dbbfff27fmalita} 4633c196def91726913a417e703ac482bb2dbbfff27fmalita 4643c196def91726913a417e703ac482bb2dbbfff27fmalitabool SkTextBlobBuilder::mergeRun(const SkPaint &font, SkTextBlob::GlyphPositioning positioning, 4653c196def91726913a417e703ac482bb2dbbfff27fmalita int count, SkPoint offset) { 4663c196def91726913a417e703ac482bb2dbbfff27fmalita if (0 == fLastRun) { 4673c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(0 == fRunCount); 4683c196def91726913a417e703ac482bb2dbbfff27fmalita return false; 4693c196def91726913a417e703ac482bb2dbbfff27fmalita } 4703c196def91726913a417e703ac482bb2dbbfff27fmalita 4713c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fLastRun >= sizeof(SkTextBlob)); 4723c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + 4733c196def91726913a417e703ac482bb2dbbfff27fmalita fLastRun); 4743c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(run->glyphCount() > 0); 4753c196def91726913a417e703ac482bb2dbbfff27fmalita 4763c196def91726913a417e703ac482bb2dbbfff27fmalita if (run->positioning() != positioning 4773c196def91726913a417e703ac482bb2dbbfff27fmalita || run->font() != font 4783c196def91726913a417e703ac482bb2dbbfff27fmalita || (run->glyphCount() + count < run->glyphCount())) { 4793c196def91726913a417e703ac482bb2dbbfff27fmalita return false; 48000d5c2c6523321d25b32905ff4822f083a4173eefmalita } 48100d5c2c6523321d25b32905ff4822f083a4173eefmalita 48200d5c2c6523321d25b32905ff4822f083a4173eefmalita // we can merge same-font/same-positioning runs in the following cases: 48300d5c2c6523321d25b32905ff4822f083a4173eefmalita // * fully positioned run following another fully positioned run 48400d5c2c6523321d25b32905ff4822f083a4173eefmalita // * horizontally postioned run following another horizontally positioned run with the same 48500d5c2c6523321d25b32905ff4822f083a4173eefmalita // y-offset 4863c196def91726913a417e703ac482bb2dbbfff27fmalita if (SkTextBlob::kFull_Positioning != positioning 4873c196def91726913a417e703ac482bb2dbbfff27fmalita && (SkTextBlob::kHorizontal_Positioning != positioning 4883c196def91726913a417e703ac482bb2dbbfff27fmalita || run->offset().y() != offset.y())) { 4893c196def91726913a417e703ac482bb2dbbfff27fmalita return false; 49000d5c2c6523321d25b32905ff4822f083a4173eefmalita } 49100d5c2c6523321d25b32905ff4822f083a4173eefmalita 4923c196def91726913a417e703ac482bb2dbbfff27fmalita size_t sizeDelta = SkTextBlob::RunRecord::StorageSize(run->glyphCount() + count, positioning) - 4933c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord::StorageSize(run->glyphCount(), positioning); 4943c196def91726913a417e703ac482bb2dbbfff27fmalita this->reserve(sizeDelta); 4953c196def91726913a417e703ac482bb2dbbfff27fmalita 4963c196def91726913a417e703ac482bb2dbbfff27fmalita // reserve may have realloced 4973c196def91726913a417e703ac482bb2dbbfff27fmalita run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + fLastRun); 4983c196def91726913a417e703ac482bb2dbbfff27fmalita uint32_t preMergeCount = run->glyphCount(); 4993c196def91726913a417e703ac482bb2dbbfff27fmalita run->grow(count); 50000d5c2c6523321d25b32905ff4822f083a4173eefmalita 5013c196def91726913a417e703ac482bb2dbbfff27fmalita // Callers expect the buffers to point at the newly added slice, ant not at the beginning. 5023c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRunBuffer.glyphs = run->glyphBuffer() + preMergeCount; 5033c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRunBuffer.pos = run->posBuffer() 5043c196def91726913a417e703ac482bb2dbbfff27fmalita + preMergeCount * SkTextBlob::ScalarsPerGlyph(positioning); 5053c196def91726913a417e703ac482bb2dbbfff27fmalita 5063c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed += sizeDelta; 5073c196def91726913a417e703ac482bb2dbbfff27fmalita 5083c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fStorageUsed <= fStorageSize); 5093c196def91726913a417e703ac482bb2dbbfff27fmalita run->validate(fStorage.get() + fStorageUsed); 5103c196def91726913a417e703ac482bb2dbbfff27fmalita 5113c196def91726913a417e703ac482bb2dbbfff27fmalita return true; 51200d5c2c6523321d25b32905ff4822f083a4173eefmalita} 51300d5c2c6523321d25b32905ff4822f083a4173eefmalita 51400d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkTextBlobBuilder::allocInternal(const SkPaint &font, 51500d5c2c6523321d25b32905ff4822f083a4173eefmalita SkTextBlob::GlyphPositioning positioning, 51600d5c2c6523321d25b32905ff4822f083a4173eefmalita int count, SkPoint offset, const SkRect* bounds) { 51700d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(count > 0); 5183c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(SkPaint::kGlyphID_TextEncoding == font.getTextEncoding()); 51900d5c2c6523321d25b32905ff4822f083a4173eefmalita 5203c196def91726913a417e703ac482bb2dbbfff27fmalita if (!this->mergeRun(font, positioning, count, offset)) { 52119653d1d004610b4ba07ce563a5701164e120e45fmalita this->updateDeferredBounds(); 52200d5c2c6523321d25b32905ff4822f083a4173eefmalita 5233c196def91726913a417e703ac482bb2dbbfff27fmalita size_t runSize = SkTextBlob::RunRecord::StorageSize(count, positioning); 5243c196def91726913a417e703ac482bb2dbbfff27fmalita this->reserve(runSize); 52500d5c2c6523321d25b32905ff4822f083a4173eefmalita 5263c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fStorageUsed >= sizeof(SkTextBlob)); 5273c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fStorageUsed + runSize <= fStorageSize); 52800d5c2c6523321d25b32905ff4822f083a4173eefmalita 5293c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord* run = new (fStorage.get() + fStorageUsed) 5303c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord(count, offset, font, positioning); 53100d5c2c6523321d25b32905ff4822f083a4173eefmalita 5323c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRunBuffer.glyphs = run->glyphBuffer(); 5333c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRunBuffer.pos = run->posBuffer(); 53400d5c2c6523321d25b32905ff4822f083a4173eefmalita 5353c196def91726913a417e703ac482bb2dbbfff27fmalita fLastRun = fStorageUsed; 5363c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed += runSize; 5373c196def91726913a417e703ac482bb2dbbfff27fmalita fRunCount++; 5383c196def91726913a417e703ac482bb2dbbfff27fmalita 5393c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fStorageUsed <= fStorageSize); 5403c196def91726913a417e703ac482bb2dbbfff27fmalita run->validate(fStorage.get() + fStorageUsed); 5413c196def91726913a417e703ac482bb2dbbfff27fmalita } 54200d5c2c6523321d25b32905ff4822f083a4173eefmalita 54300d5c2c6523321d25b32905ff4822f083a4173eefmalita if (!fDeferredBounds) { 54449f085dddff10473b6ebf832a974288300224e60bsalomon if (bounds) { 54500d5c2c6523321d25b32905ff4822f083a4173eefmalita fBounds.join(*bounds); 54600d5c2c6523321d25b32905ff4822f083a4173eefmalita } else { 54700d5c2c6523321d25b32905ff4822f083a4173eefmalita fDeferredBounds = true; 54800d5c2c6523321d25b32905ff4822f083a4173eefmalita } 54900d5c2c6523321d25b32905ff4822f083a4173eefmalita } 55000d5c2c6523321d25b32905ff4822f083a4173eefmalita} 55100d5c2c6523321d25b32905ff4822f083a4173eefmalita 55200d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRun(const SkPaint& font, int count, 55300d5c2c6523321d25b32905ff4822f083a4173eefmalita SkScalar x, SkScalar y, 55400d5c2c6523321d25b32905ff4822f083a4173eefmalita const SkRect* bounds) { 55500d5c2c6523321d25b32905ff4822f083a4173eefmalita this->allocInternal(font, SkTextBlob::kDefault_Positioning, count, SkPoint::Make(x, y), bounds); 55600d5c2c6523321d25b32905ff4822f083a4173eefmalita 55700d5c2c6523321d25b32905ff4822f083a4173eefmalita return fCurrentRunBuffer; 55800d5c2c6523321d25b32905ff4822f083a4173eefmalita} 55900d5c2c6523321d25b32905ff4822f083a4173eefmalita 56000d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPosH(const SkPaint& font, int count, 56100d5c2c6523321d25b32905ff4822f083a4173eefmalita SkScalar y, 56200d5c2c6523321d25b32905ff4822f083a4173eefmalita const SkRect* bounds) { 56300d5c2c6523321d25b32905ff4822f083a4173eefmalita this->allocInternal(font, SkTextBlob::kHorizontal_Positioning, count, SkPoint::Make(0, y), 56400d5c2c6523321d25b32905ff4822f083a4173eefmalita bounds); 56500d5c2c6523321d25b32905ff4822f083a4173eefmalita 56600d5c2c6523321d25b32905ff4822f083a4173eefmalita return fCurrentRunBuffer; 56700d5c2c6523321d25b32905ff4822f083a4173eefmalita} 56800d5c2c6523321d25b32905ff4822f083a4173eefmalita 56900d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPos(const SkPaint& font, int count, 57000d5c2c6523321d25b32905ff4822f083a4173eefmalita const SkRect *bounds) { 57100d5c2c6523321d25b32905ff4822f083a4173eefmalita this->allocInternal(font, SkTextBlob::kFull_Positioning, count, SkPoint::Make(0, 0), bounds); 57200d5c2c6523321d25b32905ff4822f083a4173eefmalita 57300d5c2c6523321d25b32905ff4822f083a4173eefmalita return fCurrentRunBuffer; 57400d5c2c6523321d25b32905ff4822f083a4173eefmalita} 57500d5c2c6523321d25b32905ff4822f083a4173eefmalita 57600d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkTextBlob* SkTextBlobBuilder::build() { 5773c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT((fRunCount > 0) == (NULL != fStorage.get())); 5783c196def91726913a417e703ac482bb2dbbfff27fmalita 5793c196def91726913a417e703ac482bb2dbbfff27fmalita this->updateDeferredBounds(); 5803c196def91726913a417e703ac482bb2dbbfff27fmalita 5813c196def91726913a417e703ac482bb2dbbfff27fmalita if (0 == fRunCount) { 5823c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(NULL == fStorage.get()); 5833c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed = sizeof(SkTextBlob); 5843c196def91726913a417e703ac482bb2dbbfff27fmalita fStorage.realloc(fStorageUsed); 58500d5c2c6523321d25b32905ff4822f083a4173eefmalita } 58600d5c2c6523321d25b32905ff4822f083a4173eefmalita 5873c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE( 5883c196def91726913a417e703ac482bb2dbbfff27fmalita size_t validateSize = sizeof(SkTextBlob); 5893c196def91726913a417e703ac482bb2dbbfff27fmalita const SkTextBlob::RunRecord* run = 5903c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord::First(reinterpret_cast<const SkTextBlob*>(fStorage.get())); 5913c196def91726913a417e703ac482bb2dbbfff27fmalita for (int i = 0; i < fRunCount; ++i) { 5923c196def91726913a417e703ac482bb2dbbfff27fmalita validateSize += SkTextBlob::RunRecord::StorageSize(run->fCount, run->fPositioning); 5933c196def91726913a417e703ac482bb2dbbfff27fmalita run->validate(fStorage.get() + fStorageUsed); 5943c196def91726913a417e703ac482bb2dbbfff27fmalita run = SkTextBlob::RunRecord::Next(run); 5953c196def91726913a417e703ac482bb2dbbfff27fmalita } 5963c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(validateSize == fStorageUsed); 5973c196def91726913a417e703ac482bb2dbbfff27fmalita ) 5983c196def91726913a417e703ac482bb2dbbfff27fmalita 5993c196def91726913a417e703ac482bb2dbbfff27fmalita const SkTextBlob* blob = new (fStorage.detach()) SkTextBlob(fRunCount, fBounds); 6003c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(const_cast<SkTextBlob*>(blob)->fStorageSize = fStorageSize;) 6013c196def91726913a417e703ac482bb2dbbfff27fmalita 6023c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed = 0; 6033c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageSize = 0; 6043c196def91726913a417e703ac482bb2dbbfff27fmalita fRunCount = 0; 6053c196def91726913a417e703ac482bb2dbbfff27fmalita fLastRun = 0; 6063c196def91726913a417e703ac482bb2dbbfff27fmalita fBounds.setEmpty(); 6073c196def91726913a417e703ac482bb2dbbfff27fmalita 60800d5c2c6523321d25b32905ff4822f083a4173eefmalita return blob; 60900d5c2c6523321d25b32905ff4822f083a4173eefmalita} 61000d5c2c6523321d25b32905ff4822f083a4173eefmalita 611