SkTextBlob.h revision 9c328187d9dee33736b77dc14dfb59529d948bb1
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;
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
72    private:
73        const RunRecord* fCurrentRun;
74        int              fRemainingRuns;
75
76        SkDEBUGCODE(uint8_t* fStorageTop;)
77    };
78
79    SkTextBlob(int runCount, const SkRect& bounds);
80
81    virtual ~SkTextBlob();
82
83    // Memory for objects of this class is created with sk_malloc rather than operator new and must
84    // be freed with sk_free.
85    void operator delete(void* p) { sk_free(p); }
86    void* operator new(size_t) {
87        SkFAIL("All blobs are created by placement new.");
88        return sk_malloc_throw(0);
89    }
90    void* operator new(size_t, void* p) { return p; }
91
92    static unsigned ScalarsPerGlyph(GlyphPositioning pos);
93
94    friend class GrTextContext;
95    friend class SkBaseDevice;
96    friend class SkTextBlobBuilder;
97    friend class TextBlobTester;
98
99    const int        fRunCount;
100    const SkRect     fBounds;
101    mutable uint32_t fUniqueID;
102
103    SkDEBUGCODE(size_t fStorageSize;)
104
105    // The actual payload resides in externally-managed storage, following the object.
106    // (see the .cpp for more details)
107
108    typedef SkRefCnt INHERITED;
109};
110
111/** \class SkTextBlobBuilder
112
113    Helper class for constructing SkTextBlobs.
114 */
115class SK_API SkTextBlobBuilder {
116public:
117    SkTextBlobBuilder();
118
119    ~SkTextBlobBuilder();
120
121    /**
122     *  Returns an immutable SkTextBlob for the current runs/glyphs. The builder is reset and
123     *  can be reused.
124     */
125    const SkTextBlob* build();
126
127    /**
128     *  Glyph and position buffers associated with a run.
129     *
130     *  A run is a sequence of glyphs sharing the same font metrics and positioning mode.
131     */
132    struct RunBuffer {
133        uint16_t* glyphs;
134        SkScalar* pos;
135    };
136
137    /**
138     *  Allocates a new default-positioned run and returns its writable glyph buffer
139     *  for direct manipulation.
140     *
141     *  @param font    The font to be used for this run.
142     *  @param count   Number of glyphs.
143     *  @param x,y     Position within the blob.
144     *  @param bounds  Optional run bounding box. If known in advance (!= NULL), it will
145     *                 be used when computing the blob bounds, to avoid re-measuring.
146     *
147     *  @return        A writable glyph buffer, valid until the next allocRun() or
148     *                 build() call. The buffer is guaranteed to hold @count@ glyphs.
149     */
150    const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y,
151                              const SkRect* bounds = NULL);
152
153    /**
154     *  Allocates a new horizontally-positioned run and returns its writable glyph and position
155     *  buffers for direct manipulation.
156     *
157     *  @param font    The font to be used for this run.
158     *  @param count   Number of glyphs.
159     *  @param y       Vertical offset within the blob.
160     *  @param bounds  Optional run bounding box. If known in advance (!= NULL), it will
161     *                 be used when computing the blob bounds, to avoid re-measuring.
162     *
163     *  @return        Writable glyph and position buffers, valid until the next allocRun()
164     *                 or build() call. The buffers are guaranteed to hold @count@ elements.
165     */
166    const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y,
167                                  const SkRect* bounds = NULL);
168
169    /**
170     *  Allocates a new fully-positioned run and returns its writable glyph and position
171     *  buffers for direct manipulation.
172     *
173     *  @param font   The font to be used for this run.
174     *  @param count  Number of glyphs.
175     *  @param bounds Optional run bounding box. If known in advance (!= NULL), it will
176     *                be used when computing the blob bounds, to avoid re-measuring.
177     *
178     *  @return       Writable glyph and position buffers, valid until the next allocRun()
179     *                or build() call. The glyph buffer and position buffer are
180     *                guaranteed to hold @count@ and 2 * @count@ elements, respectively.
181     */
182    const RunBuffer& allocRunPos(const SkPaint& font, int count, const SkRect* bounds = NULL);
183
184private:
185    void reserve(size_t size);
186    void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
187                       int count, SkPoint offset, const SkRect* bounds);
188    bool mergeRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
189                  int count, SkPoint offset);
190    void updateDeferredBounds();
191
192    static SkRect ConservativeRunBounds(const SkTextBlob::RunRecord&);
193    static SkRect TightRunBounds(const SkTextBlob::RunRecord&);
194
195    SkAutoTMalloc<uint8_t> fStorage;
196    size_t                 fStorageSize;
197    size_t                 fStorageUsed;
198
199    SkRect                 fBounds;
200    int                    fRunCount;
201    bool                   fDeferredBounds;
202    size_t                 fLastRun; // index into fStorage
203
204    RunBuffer              fCurrentRunBuffer;
205};
206
207#endif // SkTextBlob_DEFINED
208