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 8337797580de42cdb722caab4bed121311ed7d0d2halcanary#include "SkTextBlobRunIterator.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()) 2432d6b876163580711a07e96d9f29c9c1490a7271fmalita , fAlign(paint.getTextAlign()) 25055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita , fHinting(paint.getHinting()) 26055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita , fFlags(paint.getFlags() & kFlagsMask) { } 27055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 28055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita void applyToPaint(SkPaint* paint) const { 29055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); 30055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setTypeface(fTypeface.get()); 31055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setTextSize(fSize); 32055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setTextScaleX(fScaleX); 33055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setTextSkewX(fSkewX); 3432d6b876163580711a07e96d9f29c9c1490a7271fmalita paint->setTextAlign(static_cast<SkPaint::Align>(fAlign)); 35055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setHinting(static_cast<SkPaint::Hinting>(fHinting)); 36055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 37055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita paint->setFlags((paint->getFlags() & ~kFlagsMask) | fFlags); 38055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita } 39055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 40055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita bool operator==(const RunFont& other) const { 41055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita return fTypeface == other.fTypeface 42055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita && fSize == other.fSize 43055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita && fScaleX == other.fScaleX 44055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita && fSkewX == other.fSkewX 4532d6b876163580711a07e96d9f29c9c1490a7271fmalita && fAlign == other.fAlign 46055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita && fHinting == other.fHinting 47055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita && fFlags == other.fFlags; 48055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita } 49055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 50055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita bool operator!=(const RunFont& other) const { 51055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita return !(*this == other); 52055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita } 539e36c1a9306f052331550dab4728b9875127bfb5joshualitt 549e36c1a9306f052331550dab4728b9875127bfb5joshualitt uint32_t flags() const { return fFlags; } 559e36c1a9306f052331550dab4728b9875127bfb5joshualitt 56055f6b59d879b2adac52748ea5a58c8a05bf501cfmalitaprivate: 57055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita const static uint32_t kFlagsMask = 58055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kAntiAlias_Flag | 59055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kUnderlineText_Flag | 60055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kStrikeThruText_Flag | 61055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kFakeBoldText_Flag | 62055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kLinearText_Flag | 63055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kSubpixelText_Flag | 64055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kDevKernText_Flag | 65055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kLCDRenderText_Flag | 66055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kEmbeddedBitmapText_Flag | 67055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kAutoHinting_Flag | 68055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint::kVerticalText_Flag | 694854d13c27f6e3f8f763afd291821ce42324e645jvanverth SkPaint::kGenA8FromLCD_Flag; 70055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 71055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkScalar fSize; 72055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkScalar fScaleX; 73055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 74055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita // Keep this SkAutoTUnref off the first position, to avoid interfering with SkNoncopyable 75055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita // empty baseclass optimization (http://code.google.com/p/skia/issues/detail?id=3694). 76055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkAutoTUnref<SkTypeface> fTypeface; 77055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkScalar fSkewX; 78055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 7932d6b876163580711a07e96d9f29c9c1490a7271fmalita static_assert(SkPaint::kAlignCount < 4, "insufficient_align_bits"); 8032d6b876163580711a07e96d9f29c9c1490a7271fmalita uint32_t fAlign : 2; 8199fe82260633fcf5d92cca38d12ef0937ecca61cbungeman static_assert(SkPaint::kFull_Hinting < 4, "insufficient_hinting_bits"); 82055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita uint32_t fHinting : 2; 8399fe82260633fcf5d92cca38d12ef0937ecca61cbungeman static_assert((kFlagsMask & 0xffff) == kFlagsMask, "insufficient_flags_bits"); 84055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita uint32_t fFlags : 16; 85055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 86055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita typedef SkNoncopyable INHERITED; 87055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita}; 88055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 89055f6b59d879b2adac52748ea5a58c8a05bf501cfmalitastruct RunFontStorageEquivalent { 90055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkScalar fSize, fScaleX; 91055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita void* fTypeface; 92055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkScalar fSkewX; 93055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita uint32_t fFlags; 94055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita}; 9599fe82260633fcf5d92cca38d12ef0937ecca61cbungemanstatic_assert(sizeof(RunFont) == sizeof(RunFontStorageEquivalent), "runfont_should_stay_packed"); 96055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 97055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita} // anonymous namespace 98055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita 993c196def91726913a417e703ac482bb2dbbfff27fmalita// 1003c196def91726913a417e703ac482bb2dbbfff27fmalita// Textblob data is laid out into externally-managed storage as follows: 1013c196def91726913a417e703ac482bb2dbbfff27fmalita// 1023c196def91726913a417e703ac482bb2dbbfff27fmalita// ----------------------------------------------------------------------------- 1033c196def91726913a417e703ac482bb2dbbfff27fmalita// | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ... 1043c196def91726913a417e703ac482bb2dbbfff27fmalita// ----------------------------------------------------------------------------- 1053c196def91726913a417e703ac482bb2dbbfff27fmalita// 1063c196def91726913a417e703ac482bb2dbbfff27fmalita// Each run record describes a text blob run, and can be used to determine the (implicit) 1073c196def91726913a417e703ac482bb2dbbfff27fmalita// location of the following record. 1083c196def91726913a417e703ac482bb2dbbfff27fmalita 1093c196def91726913a417e703ac482bb2dbbfff27fmalitaSkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;) 1103c196def91726913a417e703ac482bb2dbbfff27fmalita 1113c196def91726913a417e703ac482bb2dbbfff27fmalitaclass SkTextBlob::RunRecord { 1123c196def91726913a417e703ac482bb2dbbfff27fmalitapublic: 1133c196def91726913a417e703ac482bb2dbbfff27fmalita RunRecord(uint32_t count, const SkPoint& offset, const SkPaint& font, GlyphPositioning pos) 114055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita : fFont(font) 115055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita , fCount(count) 1163c196def91726913a417e703ac482bb2dbbfff27fmalita , fOffset(offset) 1173c196def91726913a417e703ac482bb2dbbfff27fmalita , fPositioning(pos) { 1183c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(fMagic = kRunRecordMagic); 1193c196def91726913a417e703ac482bb2dbbfff27fmalita } 1203c196def91726913a417e703ac482bb2dbbfff27fmalita 1213c196def91726913a417e703ac482bb2dbbfff27fmalita uint32_t glyphCount() const { 1223c196def91726913a417e703ac482bb2dbbfff27fmalita return fCount; 1233c196def91726913a417e703ac482bb2dbbfff27fmalita } 1243c196def91726913a417e703ac482bb2dbbfff27fmalita 1253c196def91726913a417e703ac482bb2dbbfff27fmalita const SkPoint& offset() const { 1263c196def91726913a417e703ac482bb2dbbfff27fmalita return fOffset; 1273c196def91726913a417e703ac482bb2dbbfff27fmalita } 1283c196def91726913a417e703ac482bb2dbbfff27fmalita 129055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita const RunFont& font() const { 1303c196def91726913a417e703ac482bb2dbbfff27fmalita return fFont; 1313c196def91726913a417e703ac482bb2dbbfff27fmalita } 1323c196def91726913a417e703ac482bb2dbbfff27fmalita 1333c196def91726913a417e703ac482bb2dbbfff27fmalita GlyphPositioning positioning() const { 1343c196def91726913a417e703ac482bb2dbbfff27fmalita return fPositioning; 1353c196def91726913a417e703ac482bb2dbbfff27fmalita } 1363c196def91726913a417e703ac482bb2dbbfff27fmalita 1373c196def91726913a417e703ac482bb2dbbfff27fmalita uint16_t* glyphBuffer() const { 1383c196def91726913a417e703ac482bb2dbbfff27fmalita // Glyph are stored immediately following the record. 1393c196def91726913a417e703ac482bb2dbbfff27fmalita return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1); 1403c196def91726913a417e703ac482bb2dbbfff27fmalita } 1413c196def91726913a417e703ac482bb2dbbfff27fmalita 1423c196def91726913a417e703ac482bb2dbbfff27fmalita SkScalar* posBuffer() const { 1433c196def91726913a417e703ac482bb2dbbfff27fmalita // Position scalars follow the (aligned) glyph buffer. 1443c196def91726913a417e703ac482bb2dbbfff27fmalita return reinterpret_cast<SkScalar*>(reinterpret_cast<uint8_t*>(this->glyphBuffer()) + 1453c196def91726913a417e703ac482bb2dbbfff27fmalita SkAlign4(fCount * sizeof(uint16_t))); 1463c196def91726913a417e703ac482bb2dbbfff27fmalita } 1473c196def91726913a417e703ac482bb2dbbfff27fmalita 1483c196def91726913a417e703ac482bb2dbbfff27fmalita static size_t StorageSize(int glyphCount, SkTextBlob::GlyphPositioning positioning) { 1493c196def91726913a417e703ac482bb2dbbfff27fmalita // RunRecord object + (aligned) glyph buffer + position buffer 1503c196def91726913a417e703ac482bb2dbbfff27fmalita return SkAlignPtr(sizeof(SkTextBlob::RunRecord) 1513c196def91726913a417e703ac482bb2dbbfff27fmalita + SkAlign4(glyphCount* sizeof(uint16_t)) 1523c196def91726913a417e703ac482bb2dbbfff27fmalita + glyphCount * sizeof(SkScalar) * ScalarsPerGlyph(positioning)); 1533c196def91726913a417e703ac482bb2dbbfff27fmalita } 1543c196def91726913a417e703ac482bb2dbbfff27fmalita 1553c196def91726913a417e703ac482bb2dbbfff27fmalita static const RunRecord* First(const SkTextBlob* blob) { 1563c196def91726913a417e703ac482bb2dbbfff27fmalita // The first record (if present) is stored following the blob object. 1573c196def91726913a417e703ac482bb2dbbfff27fmalita return reinterpret_cast<const RunRecord*>(blob + 1); 1583c196def91726913a417e703ac482bb2dbbfff27fmalita } 1593c196def91726913a417e703ac482bb2dbbfff27fmalita 1603c196def91726913a417e703ac482bb2dbbfff27fmalita static const RunRecord* Next(const RunRecord* run) { 1613c196def91726913a417e703ac482bb2dbbfff27fmalita return reinterpret_cast<const RunRecord*>(reinterpret_cast<const uint8_t*>(run) 1623c196def91726913a417e703ac482bb2dbbfff27fmalita + StorageSize(run->glyphCount(), run->positioning())); 1633c196def91726913a417e703ac482bb2dbbfff27fmalita } 1643c196def91726913a417e703ac482bb2dbbfff27fmalita 16592d976c3ad06d4a398d7bf95d2060e40154c39d7fmalita void validate(const uint8_t* storageTop) const { 1663c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(kRunRecordMagic == fMagic); 1673c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT((uint8_t*)Next(this) <= storageTop); 1683c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(glyphBuffer() + fCount <= (uint16_t*)posBuffer()); 1693c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(posBuffer() + fCount * ScalarsPerGlyph(fPositioning) <= (SkScalar*)Next(this)); 1703c196def91726913a417e703ac482bb2dbbfff27fmalita } 1713c196def91726913a417e703ac482bb2dbbfff27fmalita 1723c196def91726913a417e703ac482bb2dbbfff27fmalitaprivate: 1733c196def91726913a417e703ac482bb2dbbfff27fmalita friend class SkTextBlobBuilder; 1743c196def91726913a417e703ac482bb2dbbfff27fmalita 1753c196def91726913a417e703ac482bb2dbbfff27fmalita void grow(uint32_t count) { 1763c196def91726913a417e703ac482bb2dbbfff27fmalita SkScalar* initialPosBuffer = posBuffer(); 1773c196def91726913a417e703ac482bb2dbbfff27fmalita uint32_t initialCount = fCount; 1783c196def91726913a417e703ac482bb2dbbfff27fmalita fCount += count; 1793c196def91726913a417e703ac482bb2dbbfff27fmalita 1803c196def91726913a417e703ac482bb2dbbfff27fmalita // Move the initial pos scalars to their new location. 1813c196def91726913a417e703ac482bb2dbbfff27fmalita size_t copySize = initialCount * sizeof(SkScalar) * ScalarsPerGlyph(fPositioning); 1823c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT((uint8_t*)posBuffer() + copySize <= (uint8_t*)Next(this)); 1833c196def91726913a417e703ac482bb2dbbfff27fmalita 1843c196def91726913a417e703ac482bb2dbbfff27fmalita // memmove, as the buffers may overlap 1853c196def91726913a417e703ac482bb2dbbfff27fmalita memmove(posBuffer(), initialPosBuffer, copySize); 1863c196def91726913a417e703ac482bb2dbbfff27fmalita } 1873c196def91726913a417e703ac482bb2dbbfff27fmalita 188055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita RunFont fFont; 1893c196def91726913a417e703ac482bb2dbbfff27fmalita uint32_t fCount; 1903c196def91726913a417e703ac482bb2dbbfff27fmalita SkPoint fOffset; 1913c196def91726913a417e703ac482bb2dbbfff27fmalita GlyphPositioning fPositioning; 1923c196def91726913a417e703ac482bb2dbbfff27fmalita 1933c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(unsigned fMagic;) 1943c196def91726913a417e703ac482bb2dbbfff27fmalita}; 1953c196def91726913a417e703ac482bb2dbbfff27fmalita 1962af858354d913397a6c316ef46a5d52d686e10abjoshualittstatic int32_t gNextID = 1; 1972af858354d913397a6c316ef46a5d52d686e10abjoshualittstatic int32_t next_id() { 1982af858354d913397a6c316ef46a5d52d686e10abjoshualitt int32_t id; 1992af858354d913397a6c316ef46a5d52d686e10abjoshualitt do { 2002af858354d913397a6c316ef46a5d52d686e10abjoshualitt id = sk_atomic_inc(&gNextID); 2012af858354d913397a6c316ef46a5d52d686e10abjoshualitt } while (id == SK_InvalidGenID); 2022af858354d913397a6c316ef46a5d52d686e10abjoshualitt return id; 2032af858354d913397a6c316ef46a5d52d686e10abjoshualitt} 2042af858354d913397a6c316ef46a5d52d686e10abjoshualitt 2053c196def91726913a417e703ac482bb2dbbfff27fmalitaSkTextBlob::SkTextBlob(int runCount, const SkRect& bounds) 2063c196def91726913a417e703ac482bb2dbbfff27fmalita : fRunCount(runCount) 2072af858354d913397a6c316ef46a5d52d686e10abjoshualitt , fBounds(bounds) 2082af858354d913397a6c316ef46a5d52d686e10abjoshualitt , fUniqueID(next_id()) { 20900d5c2c6523321d25b32905ff4822f083a4173eefmalita} 21000d5c2c6523321d25b32905ff4822f083a4173eefmalita 2113c196def91726913a417e703ac482bb2dbbfff27fmalitaSkTextBlob::~SkTextBlob() { 2123c196def91726913a417e703ac482bb2dbbfff27fmalita const RunRecord* run = RunRecord::First(this); 2133c196def91726913a417e703ac482bb2dbbfff27fmalita for (int i = 0; i < fRunCount; ++i) { 2143c196def91726913a417e703ac482bb2dbbfff27fmalita const RunRecord* nextRun = RunRecord::Next(run); 2153c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(run->validate((uint8_t*)this + fStorageSize);) 2163c196def91726913a417e703ac482bb2dbbfff27fmalita run->~RunRecord(); 2173c196def91726913a417e703ac482bb2dbbfff27fmalita run = nextRun; 2183c196def91726913a417e703ac482bb2dbbfff27fmalita } 2193c196def91726913a417e703ac482bb2dbbfff27fmalita} 2203c196def91726913a417e703ac482bb2dbbfff27fmalita 221b7425173f96e93b090787e2386ba5f022b6c2869fmalitavoid SkTextBlob::flatten(SkWriteBuffer& buffer) const { 2223c196def91726913a417e703ac482bb2dbbfff27fmalita int runCount = fRunCount; 223b7425173f96e93b090787e2386ba5f022b6c2869fmalita 224b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.write32(runCount); 225b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writeRect(fBounds); 226b7425173f96e93b090787e2386ba5f022b6c2869fmalita 227b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkPaint runPaint; 228337797580de42cdb722caab4bed121311ed7d0d2halcanary SkTextBlobRunIterator it(this); 229b7425173f96e93b090787e2386ba5f022b6c2869fmalita while (!it.done()) { 230b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkASSERT(it.glyphCount() > 0); 231b7425173f96e93b090787e2386ba5f022b6c2869fmalita 232b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.write32(it.glyphCount()); 233b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.write32(it.positioning()); 234b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writePoint(it.offset()); 235b7425173f96e93b090787e2386ba5f022b6c2869fmalita // This should go away when switching to SkFont 236b7425173f96e93b090787e2386ba5f022b6c2869fmalita it.applyFontToPaint(&runPaint); 237b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writePaint(runPaint); 238b7425173f96e93b090787e2386ba5f022b6c2869fmalita 239b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writeByteArray(it.glyphs(), it.glyphCount() * sizeof(uint16_t)); 240b7425173f96e93b090787e2386ba5f022b6c2869fmalita buffer.writeByteArray(it.pos(), 241b7425173f96e93b090787e2386ba5f022b6c2869fmalita it.glyphCount() * sizeof(SkScalar) * ScalarsPerGlyph(it.positioning())); 242b7425173f96e93b090787e2386ba5f022b6c2869fmalita 243b7425173f96e93b090787e2386ba5f022b6c2869fmalita it.next(); 244b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkDEBUGCODE(runCount--); 245b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 246b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkASSERT(0 == runCount); 247b7425173f96e93b090787e2386ba5f022b6c2869fmalita} 248b7425173f96e93b090787e2386ba5f022b6c2869fmalita 249b7425173f96e93b090787e2386ba5f022b6c2869fmalitaconst SkTextBlob* SkTextBlob::CreateFromBuffer(SkReadBuffer& reader) { 250b7425173f96e93b090787e2386ba5f022b6c2869fmalita int runCount = reader.read32(); 251b7425173f96e93b090787e2386ba5f022b6c2869fmalita if (runCount < 0) { 25296fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 253b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 254b7425173f96e93b090787e2386ba5f022b6c2869fmalita 255b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkRect bounds; 256b7425173f96e93b090787e2386ba5f022b6c2869fmalita reader.readRect(&bounds); 257b7425173f96e93b090787e2386ba5f022b6c2869fmalita 258b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkTextBlobBuilder blobBuilder; 259b7425173f96e93b090787e2386ba5f022b6c2869fmalita for (int i = 0; i < runCount; ++i) { 260b7425173f96e93b090787e2386ba5f022b6c2869fmalita int glyphCount = reader.read32(); 261b7425173f96e93b090787e2386ba5f022b6c2869fmalita GlyphPositioning pos = static_cast<GlyphPositioning>(reader.read32()); 262b7425173f96e93b090787e2386ba5f022b6c2869fmalita if (glyphCount <= 0 || pos > kFull_Positioning) { 26396fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 264b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 265b7425173f96e93b090787e2386ba5f022b6c2869fmalita 266b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkPoint offset; 267b7425173f96e93b090787e2386ba5f022b6c2869fmalita reader.readPoint(&offset); 268b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkPaint font; 269b7425173f96e93b090787e2386ba5f022b6c2869fmalita reader.readPaint(&font); 270b7425173f96e93b090787e2386ba5f022b6c2869fmalita 27196fcdcc219d2a0d3579719b84b28bede76efba64halcanary const SkTextBlobBuilder::RunBuffer* buf = nullptr; 272b7425173f96e93b090787e2386ba5f022b6c2869fmalita switch (pos) { 273b7425173f96e93b090787e2386ba5f022b6c2869fmalita case kDefault_Positioning: 274b7425173f96e93b090787e2386ba5f022b6c2869fmalita buf = &blobBuilder.allocRun(font, glyphCount, offset.x(), offset.y(), &bounds); 275b7425173f96e93b090787e2386ba5f022b6c2869fmalita break; 276b7425173f96e93b090787e2386ba5f022b6c2869fmalita case kHorizontal_Positioning: 277b7425173f96e93b090787e2386ba5f022b6c2869fmalita buf = &blobBuilder.allocRunPosH(font, glyphCount, offset.y(), &bounds); 278b7425173f96e93b090787e2386ba5f022b6c2869fmalita break; 279b7425173f96e93b090787e2386ba5f022b6c2869fmalita case kFull_Positioning: 280b7425173f96e93b090787e2386ba5f022b6c2869fmalita buf = &blobBuilder.allocRunPos(font, glyphCount, &bounds); 281b7425173f96e93b090787e2386ba5f022b6c2869fmalita break; 282b7425173f96e93b090787e2386ba5f022b6c2869fmalita default: 28396fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 284b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 285b7425173f96e93b090787e2386ba5f022b6c2869fmalita 286b7425173f96e93b090787e2386ba5f022b6c2869fmalita if (!reader.readByteArray(buf->glyphs, glyphCount * sizeof(uint16_t)) || 2873c196def91726913a417e703ac482bb2dbbfff27fmalita !reader.readByteArray(buf->pos, 2883c196def91726913a417e703ac482bb2dbbfff27fmalita glyphCount * sizeof(SkScalar) * ScalarsPerGlyph(pos))) { 28996fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 290b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 291b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 292b7425173f96e93b090787e2386ba5f022b6c2869fmalita 293b7425173f96e93b090787e2386ba5f022b6c2869fmalita return blobBuilder.build(); 294b7425173f96e93b090787e2386ba5f022b6c2869fmalita} 295b7425173f96e93b090787e2386ba5f022b6c2869fmalita 2963c196def91726913a417e703ac482bb2dbbfff27fmalitaunsigned SkTextBlob::ScalarsPerGlyph(GlyphPositioning pos) { 2973c196def91726913a417e703ac482bb2dbbfff27fmalita // GlyphPositioning values are directly mapped to scalars-per-glyph. 2983c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(pos <= 2); 2993c196def91726913a417e703ac482bb2dbbfff27fmalita return pos; 3003c196def91726913a417e703ac482bb2dbbfff27fmalita} 3013c196def91726913a417e703ac482bb2dbbfff27fmalita 302337797580de42cdb722caab4bed121311ed7d0d2halcanarySkTextBlobRunIterator::SkTextBlobRunIterator(const SkTextBlob* blob) 303337797580de42cdb722caab4bed121311ed7d0d2halcanary : fCurrentRun(SkTextBlob::RunRecord::First(blob)) 3043c196def91726913a417e703ac482bb2dbbfff27fmalita , fRemainingRuns(blob->fRunCount) { 3053c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(fStorageTop = (uint8_t*)blob + blob->fStorageSize;) 30600d5c2c6523321d25b32905ff4822f083a4173eefmalita} 30700d5c2c6523321d25b32905ff4822f083a4173eefmalita 308337797580de42cdb722caab4bed121311ed7d0d2halcanarybool SkTextBlobRunIterator::done() const { 3093c196def91726913a417e703ac482bb2dbbfff27fmalita return fRemainingRuns <= 0; 31000d5c2c6523321d25b32905ff4822f083a4173eefmalita} 31100d5c2c6523321d25b32905ff4822f083a4173eefmalita 312337797580de42cdb722caab4bed121311ed7d0d2halcanaryvoid SkTextBlobRunIterator::next() { 31300d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 3143c196def91726913a417e703ac482bb2dbbfff27fmalita 3153c196def91726913a417e703ac482bb2dbbfff27fmalita if (!this->done()) { 3163c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE(fCurrentRun->validate(fStorageTop);) 317337797580de42cdb722caab4bed121311ed7d0d2halcanary fCurrentRun = SkTextBlob::RunRecord::Next(fCurrentRun); 3183c196def91726913a417e703ac482bb2dbbfff27fmalita fRemainingRuns--; 3193c196def91726913a417e703ac482bb2dbbfff27fmalita } 32000d5c2c6523321d25b32905ff4822f083a4173eefmalita} 32100d5c2c6523321d25b32905ff4822f083a4173eefmalita 322337797580de42cdb722caab4bed121311ed7d0d2halcanaryuint32_t SkTextBlobRunIterator::glyphCount() const { 32300d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 3243c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->glyphCount(); 32500d5c2c6523321d25b32905ff4822f083a4173eefmalita} 32600d5c2c6523321d25b32905ff4822f083a4173eefmalita 327337797580de42cdb722caab4bed121311ed7d0d2halcanaryconst uint16_t* SkTextBlobRunIterator::glyphs() const { 32800d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 3293c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->glyphBuffer(); 33000d5c2c6523321d25b32905ff4822f083a4173eefmalita} 33100d5c2c6523321d25b32905ff4822f083a4173eefmalita 332337797580de42cdb722caab4bed121311ed7d0d2halcanaryconst SkScalar* SkTextBlobRunIterator::pos() const { 33300d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 3343c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->posBuffer(); 33500d5c2c6523321d25b32905ff4822f083a4173eefmalita} 33600d5c2c6523321d25b32905ff4822f083a4173eefmalita 337337797580de42cdb722caab4bed121311ed7d0d2halcanaryconst SkPoint& SkTextBlobRunIterator::offset() const { 33800d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 3393c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->offset(); 34000d5c2c6523321d25b32905ff4822f083a4173eefmalita} 34100d5c2c6523321d25b32905ff4822f083a4173eefmalita 342337797580de42cdb722caab4bed121311ed7d0d2halcanarySkTextBlob::GlyphPositioning SkTextBlobRunIterator::positioning() const { 34300d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 3443c196def91726913a417e703ac482bb2dbbfff27fmalita return fCurrentRun->positioning(); 34500d5c2c6523321d25b32905ff4822f083a4173eefmalita} 34600d5c2c6523321d25b32905ff4822f083a4173eefmalita 347337797580de42cdb722caab4bed121311ed7d0d2halcanaryvoid SkTextBlobRunIterator::applyFontToPaint(SkPaint* paint) const { 34800d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(!this->done()); 34937ecbaffd1f9f6841aa562aa31a824d109d52988fmalita 350055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita fCurrentRun->font().applyToPaint(paint); 35100d5c2c6523321d25b32905ff4822f083a4173eefmalita} 35200d5c2c6523321d25b32905ff4822f083a4173eefmalita 353337797580de42cdb722caab4bed121311ed7d0d2halcanarybool SkTextBlobRunIterator::isLCD() const { 3549e36c1a9306f052331550dab4728b9875127bfb5joshualitt return SkToBool(fCurrentRun->font().flags() & SkPaint::kLCDRenderText_Flag); 3559e36c1a9306f052331550dab4728b9875127bfb5joshualitt} 3569e36c1a9306f052331550dab4728b9875127bfb5joshualitt 3573c196def91726913a417e703ac482bb2dbbfff27fmalitaSkTextBlobBuilder::SkTextBlobBuilder() 3583c196def91726913a417e703ac482bb2dbbfff27fmalita : fStorageSize(0) 3593c196def91726913a417e703ac482bb2dbbfff27fmalita , fStorageUsed(0) 3603c196def91726913a417e703ac482bb2dbbfff27fmalita , fRunCount(0) 3613c196def91726913a417e703ac482bb2dbbfff27fmalita , fDeferredBounds(false) 3623c196def91726913a417e703ac482bb2dbbfff27fmalita , fLastRun(0) { 36300d5c2c6523321d25b32905ff4822f083a4173eefmalita fBounds.setEmpty(); 36400d5c2c6523321d25b32905ff4822f083a4173eefmalita} 36500d5c2c6523321d25b32905ff4822f083a4173eefmalita 36600d5c2c6523321d25b32905ff4822f083a4173eefmalitaSkTextBlobBuilder::~SkTextBlobBuilder() { 36796fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr != fStorage.get()) { 3683c196def91726913a417e703ac482bb2dbbfff27fmalita // We are abandoning runs and must destruct the associated font data. 3693c196def91726913a417e703ac482bb2dbbfff27fmalita // The easiest way to accomplish that is to use the blob destructor. 3703c196def91726913a417e703ac482bb2dbbfff27fmalita build()->unref(); 3713c196def91726913a417e703ac482bb2dbbfff27fmalita } 37200d5c2c6523321d25b32905ff4822f083a4173eefmalita} 37300d5c2c6523321d25b32905ff4822f083a4173eefmalita 3743dc40ac9f968eee95eef5e8ee811e0640691df0ffmalitaSkRect SkTextBlobBuilder::TightRunBounds(const SkTextBlob::RunRecord& run) { 375f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkRect bounds; 376055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita SkPaint paint; 377055f6b59d879b2adac52748ea5a58c8a05bf501cfmalita run.font().applyToPaint(&paint); 378b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita 379b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita if (SkTextBlob::kDefault_Positioning == run.positioning()) { 380b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita paint.measureText(run.glyphBuffer(), run.glyphCount() * sizeof(uint16_t), &bounds); 381b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita return bounds.makeOffset(run.offset().x(), run.offset().y()); 382b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita } 383b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita 384b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita SkAutoSTArray<16, SkRect> glyphBounds(run.glyphCount()); 385b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita paint.getTextWidths(run.glyphBuffer(), 386b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita run.glyphCount() * sizeof(uint16_t), 387b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita NULL, 388b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita glyphBounds.get()); 389b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita 390b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita SkASSERT(SkTextBlob::kFull_Positioning == run.positioning() || 391b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita SkTextBlob::kHorizontal_Positioning == run.positioning()); 392b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita // kFull_Positioning => [ x, y, x, y... ] 393b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita // kHorizontal_Positioning => [ x, x, x... ] 394b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita // (const y applied by runBounds.offset(run->offset()) later) 395b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita const SkScalar horizontalConstY = 0; 396b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita const SkScalar* glyphPosX = run.posBuffer(); 397b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita const SkScalar* glyphPosY = (run.positioning() == SkTextBlob::kFull_Positioning) ? 398b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita glyphPosX + 1 : &horizontalConstY; 399b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita const unsigned posXInc = SkTextBlob::ScalarsPerGlyph(run.positioning()); 400b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita const unsigned posYInc = (run.positioning() == SkTextBlob::kFull_Positioning) ? 401b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita posXInc : 0; 402b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita 403b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita bounds.setEmpty(); 404b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita for (unsigned i = 0; i < run.glyphCount(); ++i) { 405b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita bounds.join(glyphBounds[i].makeOffset(*glyphPosX, *glyphPosY)); 406b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita glyphPosX += posXInc; 407b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita glyphPosY += posYInc; 408b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita } 409b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita 410b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita SkASSERT((void*)glyphPosX <= SkTextBlob::RunRecord::Next(&run)); 4113dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita 4123dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita return bounds.makeOffset(run.offset().x(), run.offset().y()); 4133dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita} 4143dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita 4153dc40ac9f968eee95eef5e8ee811e0640691df0ffmalitaSkRect SkTextBlobBuilder::ConservativeRunBounds(const SkTextBlob::RunRecord& run) { 4163dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita SkASSERT(run.glyphCount() > 0); 417f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkASSERT(SkTextBlob::kFull_Positioning == run.positioning() || 418f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkTextBlob::kHorizontal_Positioning == run.positioning()); 4193dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita 420b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita SkPaint paint; 421b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita run.font().applyToPaint(&paint); 422b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita const SkRect fontBounds = paint.getFontBounds(); 423b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita if (fontBounds.isEmpty()) { 424b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita // Empty font bounds are likely a font bug. TightBounds has a better chance of 425b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita // producing useful results in this case. 426b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita return TightRunBounds(run); 427b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita } 428b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita 429b0b45d35e4f30c1f42b6a910dc7f90e1a88de70cfmalita // Compute the glyph position bbox. 430f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkRect bounds; 431f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita switch (run.positioning()) { 432f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita case SkTextBlob::kHorizontal_Positioning: { 433f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita const SkScalar* glyphPos = run.posBuffer(); 434f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkASSERT((void*)(glyphPos + run.glyphCount()) <= SkTextBlob::RunRecord::Next(&run)); 435f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita 436f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkScalar minX = *glyphPos; 437f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkScalar maxX = *glyphPos; 438f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita for (unsigned i = 1; i < run.glyphCount(); ++i) { 439f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkScalar x = glyphPos[i]; 440f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita minX = SkMinScalar(x, minX); 441f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita maxX = SkMaxScalar(x, maxX); 442f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita } 443f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita 444f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita bounds.setLTRB(minX, 0, maxX, 0); 445f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita } break; 446f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita case SkTextBlob::kFull_Positioning: { 447f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita const SkPoint* glyphPosPts = reinterpret_cast<const SkPoint*>(run.posBuffer()); 448f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkASSERT((void*)(glyphPosPts + run.glyphCount()) <= SkTextBlob::RunRecord::Next(&run)); 449f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita 450f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita bounds.setBounds(glyphPosPts, run.glyphCount()); 451f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita } break; 452f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita default: 453f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkFAIL("unsupported positioning mode"); 4543dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita } 4553dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita 4563dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita // Expand by typeface glyph bounds. 4573dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita bounds.fLeft += fontBounds.left(); 4583dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita bounds.fTop += fontBounds.top(); 4593dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita bounds.fRight += fontBounds.right(); 4603dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita bounds.fBottom += fontBounds.bottom(); 4613dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita 4623dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita // Offset by run position. 4633dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita return bounds.makeOffset(run.offset().x(), run.offset().y()); 4643dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita} 4653dc40ac9f968eee95eef5e8ee811e0640691df0ffmalita 46600d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkTextBlobBuilder::updateDeferredBounds() { 4673c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(!fDeferredBounds || fRunCount > 0); 46800d5c2c6523321d25b32905ff4822f083a4173eefmalita 46900d5c2c6523321d25b32905ff4822f083a4173eefmalita if (!fDeferredBounds) { 47000d5c2c6523321d25b32905ff4822f083a4173eefmalita return; 47100d5c2c6523321d25b32905ff4822f083a4173eefmalita } 47200d5c2c6523321d25b32905ff4822f083a4173eefmalita 47319653d1d004610b4ba07ce563a5701164e120e45fmalita SkASSERT(fLastRun >= sizeof(SkTextBlob)); 47419653d1d004610b4ba07ce563a5701164e120e45fmalita SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + 47519653d1d004610b4ba07ce563a5701164e120e45fmalita fLastRun); 47619653d1d004610b4ba07ce563a5701164e120e45fmalita 477f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita // FIXME: we should also use conservative bounds for kDefault_Positioning. 478f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita SkRect runBounds = SkTextBlob::kDefault_Positioning == run->positioning() ? 479f9a40723f5d9bfe02cc60bedb5b956916e5cea01fmalita TightRunBounds(*run) : ConservativeRunBounds(*run); 48019653d1d004610b4ba07ce563a5701164e120e45fmalita fBounds.join(runBounds); 48100d5c2c6523321d25b32905ff4822f083a4173eefmalita fDeferredBounds = false; 48200d5c2c6523321d25b32905ff4822f083a4173eefmalita} 48300d5c2c6523321d25b32905ff4822f083a4173eefmalita 4843c196def91726913a417e703ac482bb2dbbfff27fmalitavoid SkTextBlobBuilder::reserve(size_t size) { 4853c196def91726913a417e703ac482bb2dbbfff27fmalita // We don't currently pre-allocate, but maybe someday... 4863c196def91726913a417e703ac482bb2dbbfff27fmalita if (fStorageUsed + size <= fStorageSize) { 4873c196def91726913a417e703ac482bb2dbbfff27fmalita return; 4883c196def91726913a417e703ac482bb2dbbfff27fmalita } 4893c196def91726913a417e703ac482bb2dbbfff27fmalita 4903c196def91726913a417e703ac482bb2dbbfff27fmalita if (0 == fRunCount) { 49196fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(nullptr == fStorage.get()); 4923c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(0 == fStorageSize); 4933c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(0 == fStorageUsed); 49413645ea0ea87038ebd71be3bd6d53b313069a9e4fmalita 4953c196def91726913a417e703ac482bb2dbbfff27fmalita // the first allocation also includes blob storage 4963c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed += sizeof(SkTextBlob); 4973c196def91726913a417e703ac482bb2dbbfff27fmalita } 4983c196def91726913a417e703ac482bb2dbbfff27fmalita 4993c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageSize = fStorageUsed + size; 5003c196def91726913a417e703ac482bb2dbbfff27fmalita // FYI: This relies on everything we store being relocatable, particularly SkPaint. 5013c196def91726913a417e703ac482bb2dbbfff27fmalita fStorage.realloc(fStorageSize); 5023c196def91726913a417e703ac482bb2dbbfff27fmalita} 5033c196def91726913a417e703ac482bb2dbbfff27fmalita 5043c196def91726913a417e703ac482bb2dbbfff27fmalitabool SkTextBlobBuilder::mergeRun(const SkPaint &font, SkTextBlob::GlyphPositioning positioning, 5053c196def91726913a417e703ac482bb2dbbfff27fmalita int count, SkPoint offset) { 5063c196def91726913a417e703ac482bb2dbbfff27fmalita if (0 == fLastRun) { 5073c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(0 == fRunCount); 5083c196def91726913a417e703ac482bb2dbbfff27fmalita return false; 5093c196def91726913a417e703ac482bb2dbbfff27fmalita } 5103c196def91726913a417e703ac482bb2dbbfff27fmalita 5113c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fLastRun >= sizeof(SkTextBlob)); 5123c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + 5133c196def91726913a417e703ac482bb2dbbfff27fmalita fLastRun); 5143c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(run->glyphCount() > 0); 5153c196def91726913a417e703ac482bb2dbbfff27fmalita 5163c196def91726913a417e703ac482bb2dbbfff27fmalita if (run->positioning() != positioning 5173c196def91726913a417e703ac482bb2dbbfff27fmalita || run->font() != font 5183c196def91726913a417e703ac482bb2dbbfff27fmalita || (run->glyphCount() + count < run->glyphCount())) { 5193c196def91726913a417e703ac482bb2dbbfff27fmalita return false; 52000d5c2c6523321d25b32905ff4822f083a4173eefmalita } 52100d5c2c6523321d25b32905ff4822f083a4173eefmalita 52200d5c2c6523321d25b32905ff4822f083a4173eefmalita // we can merge same-font/same-positioning runs in the following cases: 52300d5c2c6523321d25b32905ff4822f083a4173eefmalita // * fully positioned run following another fully positioned run 52400d5c2c6523321d25b32905ff4822f083a4173eefmalita // * horizontally postioned run following another horizontally positioned run with the same 52500d5c2c6523321d25b32905ff4822f083a4173eefmalita // y-offset 5263c196def91726913a417e703ac482bb2dbbfff27fmalita if (SkTextBlob::kFull_Positioning != positioning 5273c196def91726913a417e703ac482bb2dbbfff27fmalita && (SkTextBlob::kHorizontal_Positioning != positioning 5283c196def91726913a417e703ac482bb2dbbfff27fmalita || run->offset().y() != offset.y())) { 5293c196def91726913a417e703ac482bb2dbbfff27fmalita return false; 53000d5c2c6523321d25b32905ff4822f083a4173eefmalita } 53100d5c2c6523321d25b32905ff4822f083a4173eefmalita 5323c196def91726913a417e703ac482bb2dbbfff27fmalita size_t sizeDelta = SkTextBlob::RunRecord::StorageSize(run->glyphCount() + count, positioning) - 5333c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord::StorageSize(run->glyphCount(), positioning); 5343c196def91726913a417e703ac482bb2dbbfff27fmalita this->reserve(sizeDelta); 5353c196def91726913a417e703ac482bb2dbbfff27fmalita 5363c196def91726913a417e703ac482bb2dbbfff27fmalita // reserve may have realloced 5373c196def91726913a417e703ac482bb2dbbfff27fmalita run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + fLastRun); 5383c196def91726913a417e703ac482bb2dbbfff27fmalita uint32_t preMergeCount = run->glyphCount(); 5393c196def91726913a417e703ac482bb2dbbfff27fmalita run->grow(count); 54000d5c2c6523321d25b32905ff4822f083a4173eefmalita 5413c196def91726913a417e703ac482bb2dbbfff27fmalita // Callers expect the buffers to point at the newly added slice, ant not at the beginning. 5423c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRunBuffer.glyphs = run->glyphBuffer() + preMergeCount; 5433c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRunBuffer.pos = run->posBuffer() 5443c196def91726913a417e703ac482bb2dbbfff27fmalita + preMergeCount * SkTextBlob::ScalarsPerGlyph(positioning); 5453c196def91726913a417e703ac482bb2dbbfff27fmalita 5463c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed += sizeDelta; 5473c196def91726913a417e703ac482bb2dbbfff27fmalita 5483c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fStorageUsed <= fStorageSize); 5493c196def91726913a417e703ac482bb2dbbfff27fmalita run->validate(fStorage.get() + fStorageUsed); 5503c196def91726913a417e703ac482bb2dbbfff27fmalita 5513c196def91726913a417e703ac482bb2dbbfff27fmalita return true; 55200d5c2c6523321d25b32905ff4822f083a4173eefmalita} 55300d5c2c6523321d25b32905ff4822f083a4173eefmalita 55400d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkTextBlobBuilder::allocInternal(const SkPaint &font, 55500d5c2c6523321d25b32905ff4822f083a4173eefmalita SkTextBlob::GlyphPositioning positioning, 55600d5c2c6523321d25b32905ff4822f083a4173eefmalita int count, SkPoint offset, const SkRect* bounds) { 55700d5c2c6523321d25b32905ff4822f083a4173eefmalita SkASSERT(count > 0); 5583c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(SkPaint::kGlyphID_TextEncoding == font.getTextEncoding()); 55900d5c2c6523321d25b32905ff4822f083a4173eefmalita 5603c196def91726913a417e703ac482bb2dbbfff27fmalita if (!this->mergeRun(font, positioning, count, offset)) { 56119653d1d004610b4ba07ce563a5701164e120e45fmalita this->updateDeferredBounds(); 56200d5c2c6523321d25b32905ff4822f083a4173eefmalita 5633c196def91726913a417e703ac482bb2dbbfff27fmalita size_t runSize = SkTextBlob::RunRecord::StorageSize(count, positioning); 5643c196def91726913a417e703ac482bb2dbbfff27fmalita this->reserve(runSize); 56500d5c2c6523321d25b32905ff4822f083a4173eefmalita 5663c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fStorageUsed >= sizeof(SkTextBlob)); 5673c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fStorageUsed + runSize <= fStorageSize); 56800d5c2c6523321d25b32905ff4822f083a4173eefmalita 5693c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord* run = new (fStorage.get() + fStorageUsed) 5703c196def91726913a417e703ac482bb2dbbfff27fmalita SkTextBlob::RunRecord(count, offset, font, positioning); 57100d5c2c6523321d25b32905ff4822f083a4173eefmalita 5723c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRunBuffer.glyphs = run->glyphBuffer(); 5733c196def91726913a417e703ac482bb2dbbfff27fmalita fCurrentRunBuffer.pos = run->posBuffer(); 57400d5c2c6523321d25b32905ff4822f083a4173eefmalita 5753c196def91726913a417e703ac482bb2dbbfff27fmalita fLastRun = fStorageUsed; 5763c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed += runSize; 5773c196def91726913a417e703ac482bb2dbbfff27fmalita fRunCount++; 5783c196def91726913a417e703ac482bb2dbbfff27fmalita 5793c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(fStorageUsed <= fStorageSize); 5803c196def91726913a417e703ac482bb2dbbfff27fmalita run->validate(fStorage.get() + fStorageUsed); 5813c196def91726913a417e703ac482bb2dbbfff27fmalita } 58200d5c2c6523321d25b32905ff4822f083a4173eefmalita 58300d5c2c6523321d25b32905ff4822f083a4173eefmalita if (!fDeferredBounds) { 58449f085dddff10473b6ebf832a974288300224e60bsalomon if (bounds) { 58500d5c2c6523321d25b32905ff4822f083a4173eefmalita fBounds.join(*bounds); 58600d5c2c6523321d25b32905ff4822f083a4173eefmalita } else { 58700d5c2c6523321d25b32905ff4822f083a4173eefmalita fDeferredBounds = true; 58800d5c2c6523321d25b32905ff4822f083a4173eefmalita } 58900d5c2c6523321d25b32905ff4822f083a4173eefmalita } 59000d5c2c6523321d25b32905ff4822f083a4173eefmalita} 59100d5c2c6523321d25b32905ff4822f083a4173eefmalita 59200d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRun(const SkPaint& font, int count, 59300d5c2c6523321d25b32905ff4822f083a4173eefmalita SkScalar x, SkScalar y, 59400d5c2c6523321d25b32905ff4822f083a4173eefmalita const SkRect* bounds) { 59500d5c2c6523321d25b32905ff4822f083a4173eefmalita this->allocInternal(font, SkTextBlob::kDefault_Positioning, count, SkPoint::Make(x, y), bounds); 59600d5c2c6523321d25b32905ff4822f083a4173eefmalita 59700d5c2c6523321d25b32905ff4822f083a4173eefmalita return fCurrentRunBuffer; 59800d5c2c6523321d25b32905ff4822f083a4173eefmalita} 59900d5c2c6523321d25b32905ff4822f083a4173eefmalita 60000d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPosH(const SkPaint& font, int count, 60100d5c2c6523321d25b32905ff4822f083a4173eefmalita SkScalar y, 60200d5c2c6523321d25b32905ff4822f083a4173eefmalita const SkRect* bounds) { 60300d5c2c6523321d25b32905ff4822f083a4173eefmalita this->allocInternal(font, SkTextBlob::kHorizontal_Positioning, count, SkPoint::Make(0, y), 60400d5c2c6523321d25b32905ff4822f083a4173eefmalita bounds); 60500d5c2c6523321d25b32905ff4822f083a4173eefmalita 60600d5c2c6523321d25b32905ff4822f083a4173eefmalita return fCurrentRunBuffer; 60700d5c2c6523321d25b32905ff4822f083a4173eefmalita} 60800d5c2c6523321d25b32905ff4822f083a4173eefmalita 60900d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPos(const SkPaint& font, int count, 61000d5c2c6523321d25b32905ff4822f083a4173eefmalita const SkRect *bounds) { 61100d5c2c6523321d25b32905ff4822f083a4173eefmalita this->allocInternal(font, SkTextBlob::kFull_Positioning, count, SkPoint::Make(0, 0), bounds); 61200d5c2c6523321d25b32905ff4822f083a4173eefmalita 61300d5c2c6523321d25b32905ff4822f083a4173eefmalita return fCurrentRunBuffer; 61400d5c2c6523321d25b32905ff4822f083a4173eefmalita} 61500d5c2c6523321d25b32905ff4822f083a4173eefmalita 61600d5c2c6523321d25b32905ff4822f083a4173eefmalitaconst SkTextBlob* SkTextBlobBuilder::build() { 61796fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT((fRunCount > 0) == (nullptr != fStorage.get())); 6183c196def91726913a417e703ac482bb2dbbfff27fmalita 6193c196def91726913a417e703ac482bb2dbbfff27fmalita this->updateDeferredBounds(); 6203c196def91726913a417e703ac482bb2dbbfff27fmalita 6213c196def91726913a417e703ac482bb2dbbfff27fmalita if (0 == fRunCount) { 62296fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(nullptr == fStorage.get()); 6233c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed = sizeof(SkTextBlob); 6243c196def91726913a417e703ac482bb2dbbfff27fmalita fStorage.realloc(fStorageUsed); 62500d5c2c6523321d25b32905ff4822f083a4173eefmalita } 62600d5c2c6523321d25b32905ff4822f083a4173eefmalita 62792d976c3ad06d4a398d7bf95d2060e40154c39d7fmalita const SkTextBlob* blob = new (fStorage.detach()) SkTextBlob(fRunCount, fBounds); 62892d976c3ad06d4a398d7bf95d2060e40154c39d7fmalita SkDEBUGCODE(const_cast<SkTextBlob*>(blob)->fStorageSize = fStorageSize;) 62992d976c3ad06d4a398d7bf95d2060e40154c39d7fmalita 6303c196def91726913a417e703ac482bb2dbbfff27fmalita SkDEBUGCODE( 6313c196def91726913a417e703ac482bb2dbbfff27fmalita size_t validateSize = sizeof(SkTextBlob); 63292d976c3ad06d4a398d7bf95d2060e40154c39d7fmalita const SkTextBlob::RunRecord* run = SkTextBlob::RunRecord::First(blob); 6333c196def91726913a417e703ac482bb2dbbfff27fmalita for (int i = 0; i < fRunCount; ++i) { 6343c196def91726913a417e703ac482bb2dbbfff27fmalita validateSize += SkTextBlob::RunRecord::StorageSize(run->fCount, run->fPositioning); 63592d976c3ad06d4a398d7bf95d2060e40154c39d7fmalita run->validate(reinterpret_cast<const uint8_t*>(blob) + fStorageUsed); 6363c196def91726913a417e703ac482bb2dbbfff27fmalita run = SkTextBlob::RunRecord::Next(run); 6373c196def91726913a417e703ac482bb2dbbfff27fmalita } 6383c196def91726913a417e703ac482bb2dbbfff27fmalita SkASSERT(validateSize == fStorageUsed); 6393c196def91726913a417e703ac482bb2dbbfff27fmalita ) 6403c196def91726913a417e703ac482bb2dbbfff27fmalita 6413c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageUsed = 0; 6423c196def91726913a417e703ac482bb2dbbfff27fmalita fStorageSize = 0; 6433c196def91726913a417e703ac482bb2dbbfff27fmalita fRunCount = 0; 6443c196def91726913a417e703ac482bb2dbbfff27fmalita fLastRun = 0; 6453c196def91726913a417e703ac482bb2dbbfff27fmalita fBounds.setEmpty(); 6463c196def91726913a417e703ac482bb2dbbfff27fmalita 64700d5c2c6523321d25b32905ff4822f083a4173eefmalita return blob; 64800d5c2c6523321d25b32905ff4822f083a4173eefmalita} 64900d5c2c6523321d25b32905ff4822f083a4173eefmalita 650