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