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