1/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkTextBlob_DEFINED
9#define SkTextBlob_DEFINED
10
11#include "SkPaint.h"
12#include "SkRefCnt.h"
13#include "SkTArray.h"
14#include "SkTDArray.h"
15
16class SkReadBuffer;
17class SkWriteBuffer;
18
19/** \class SkTextBlob
20
21    SkTextBlob combines multiple text runs into an immutable, ref-counted structure.
22*/
23class SK_API SkTextBlob : public SkRefCnt {
24public:
25    /**
26     *  Returns a conservative blob bounding box.
27     */
28    const SkRect& bounds() const { return fBounds; }
29
30    /**
31     *  Return a non-zero, unique value representing the text blob.
32     */
33    uint32_t uniqueID() const { return fUniqueID; }
34
35    /**
36     *  Serialize to a buffer.
37     */
38    void flatten(SkWriteBuffer&) const;
39
40    /**
41     *  Recreate an SkTextBlob that was serialized into a buffer.
42     *
43     *  @param  SkReadBuffer Serialized blob data.
44     *  @return A new SkTextBlob representing the serialized data, or NULL if the buffer is
45     *          invalid.
46     */
47    static const SkTextBlob* CreateFromBuffer(SkReadBuffer&);
48
49private:
50    enum GlyphPositioning {
51        kDefault_Positioning      = 0, // Default glyph advances -- zero scalars per glyph.
52        kHorizontal_Positioning   = 1, // Horizontal positioning -- one scalar per glyph.
53        kFull_Positioning         = 2  // Point positioning -- two scalars per glyph.
54    };
55
56    class RunRecord;
57
58    class RunIterator {
59    public:
60        RunIterator(const SkTextBlob* blob);
61
62        bool done() const;
63        void next();
64
65        uint32_t glyphCount() const;
66        const uint16_t* glyphs() const;
67        const SkScalar* pos() const;
68        const SkPoint& offset() const;
69        void applyFontToPaint(SkPaint*) const;
70        GlyphPositioning positioning() const;
71        bool isLCD() const;
72
73    private:
74        const RunRecord* fCurrentRun;
75        int              fRemainingRuns;
76
77        SkDEBUGCODE(uint8_t* fStorageTop;)
78    };
79
80    SkTextBlob(int runCount, const SkRect& bounds);
81
82    virtual ~SkTextBlob();
83
84    // Memory for objects of this class is created with sk_malloc rather than operator new and must
85    // be freed with sk_free.
86    void operator delete(void* p) { sk_free(p); }
87    void* operator new(size_t) {
88        SkFAIL("All blobs are created by placement new.");
89        return sk_malloc_throw(0);
90    }
91    void* operator new(size_t, void* p) { return p; }
92
93    static unsigned ScalarsPerGlyph(GlyphPositioning pos);
94
95    friend class GrAtlasTextContext;
96    friend class GrTextBlobCache;
97    friend class GrTextContext;
98    friend class SkBaseDevice;
99    friend class SkTextBlobBuilder;
100    friend class TextBlobTester;
101
102    const int        fRunCount;
103    const SkRect     fBounds;
104    const uint32_t fUniqueID;
105
106    SkDEBUGCODE(size_t fStorageSize;)
107
108    // The actual payload resides in externally-managed storage, following the object.
109    // (see the .cpp for more details)
110
111    typedef SkRefCnt INHERITED;
112};
113
114/** \class SkTextBlobBuilder
115
116    Helper class for constructing SkTextBlobs.
117 */
118class SK_API SkTextBlobBuilder {
119public:
120    SkTextBlobBuilder();
121
122    ~SkTextBlobBuilder();
123
124    /**
125     *  Returns an immutable SkTextBlob for the current runs/glyphs. The builder is reset and
126     *  can be reused.
127     */
128    const SkTextBlob* build();
129
130    /**
131     *  Glyph and position buffers associated with a run.
132     *
133     *  A run is a sequence of glyphs sharing the same font metrics and positioning mode.
134     */
135    struct RunBuffer {
136        uint16_t* glyphs;
137        SkScalar* pos;
138    };
139
140    /**
141     *  Allocates a new default-positioned run and returns its writable glyph buffer
142     *  for direct manipulation.
143     *
144     *  @param font    The font to be used for this run.
145     *  @param count   Number of glyphs.
146     *  @param x,y     Position within the blob.
147     *  @param bounds  Optional run bounding box. If known in advance (!= NULL), it will
148     *                 be used when computing the blob bounds, to avoid re-measuring.
149     *
150     *  @return        A writable glyph buffer, valid until the next allocRun() or
151     *                 build() call. The buffer is guaranteed to hold @count@ glyphs.
152     */
153    const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y,
154                              const SkRect* bounds = NULL);
155
156    /**
157     *  Allocates a new horizontally-positioned run and returns its writable glyph and position
158     *  buffers for direct manipulation.
159     *
160     *  @param font    The font to be used for this run.
161     *  @param count   Number of glyphs.
162     *  @param y       Vertical offset within the blob.
163     *  @param bounds  Optional run bounding box. If known in advance (!= NULL), it will
164     *                 be used when computing the blob bounds, to avoid re-measuring.
165     *
166     *  @return        Writable glyph and position buffers, valid until the next allocRun()
167     *                 or build() call. The buffers are guaranteed to hold @count@ elements.
168     */
169    const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y,
170                                  const SkRect* bounds = NULL);
171
172    /**
173     *  Allocates a new fully-positioned run and returns its writable glyph and position
174     *  buffers for direct manipulation.
175     *
176     *  @param font   The font to be used for this run.
177     *  @param count  Number of glyphs.
178     *  @param bounds Optional run bounding box. If known in advance (!= NULL), it will
179     *                be used when computing the blob bounds, to avoid re-measuring.
180     *
181     *  @return       Writable glyph and position buffers, valid until the next allocRun()
182     *                or build() call. The glyph buffer and position buffer are
183     *                guaranteed to hold @count@ and 2 * @count@ elements, respectively.
184     */
185    const RunBuffer& allocRunPos(const SkPaint& font, int count, const SkRect* bounds = NULL);
186
187private:
188    void reserve(size_t size);
189    void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
190                       int count, SkPoint offset, const SkRect* bounds);
191    bool mergeRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
192                  int count, SkPoint offset);
193    void updateDeferredBounds();
194
195    static SkRect ConservativeRunBounds(const SkTextBlob::RunRecord&);
196    static SkRect TightRunBounds(const SkTextBlob::RunRecord&);
197
198    SkAutoTMalloc<uint8_t> fStorage;
199    size_t                 fStorageSize;
200    size_t                 fStorageUsed;
201
202    SkRect                 fBounds;
203    int                    fRunCount;
204    bool                   fDeferredBounds;
205    size_t                 fLastRun; // index into fStorage
206
207    RunBuffer              fCurrentRunBuffer;
208};
209
210#endif // SkTextBlob_DEFINED
211