SkTextBlob.h revision b7425173f96e93b090787e2386ba5f022b6c2869
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 the 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
35private:
36    enum GlyphPositioning {
37        kDefault_Positioning      = 0, // Default glyph advances -- zero scalars per glyph.
38        kHorizontal_Positioning   = 1, // Horizontal positioning -- one scalar per glyph.
39        kFull_Positioning         = 2  // Point positioning -- two scalars per glyph.
40    };
41
42    class RunIterator {
43    public:
44        RunIterator(const SkTextBlob* blob);
45
46        bool done() const;
47        void next();
48
49        uint32_t glyphCount() const;
50        const uint16_t* glyphs() const;
51        const SkScalar* pos() const;
52        const SkPoint& offset() const;
53        void applyFontToPaint(SkPaint*) const;
54        GlyphPositioning positioning() const;
55
56    private:
57        const SkTextBlob* fBlob;
58        int               fIndex;
59    };
60
61    // A run is a sequence of glyphs sharing the same font metrics and positioning mode.
62    struct Run {
63        uint32_t         count;
64        uint32_t         glyphStart; // index into fGlyphBuffer
65        uint32_t         posStart;   // index into fPosBuffer
66        SkPoint          offset;     // run offset (unsued for fully positioned glyphs)
67        SkPaint          font;
68        GlyphPositioning positioning;
69    };
70
71    SkTextBlob(uint16_t* glyphs, SkScalar* pos, const SkTArray<Run>* runs, const SkRect& bounds);
72
73    void flatten(SkWriteBuffer&) const;
74    static const SkTextBlob* CreateFromBuffer(SkReadBuffer&);
75
76    static unsigned ScalarsPerGlyph(GlyphPositioning pos);
77
78    friend class SkCanvas;
79    friend class SkPictureData;
80    friend class SkTextBlobBuilder;
81    friend class TextBlobTester;
82
83    const SkAutoTMalloc<uint16_t>       fGlyphBuffer;
84    const SkAutoTMalloc<SkScalar>       fPosBuffer;
85
86    // SkTArray required here for run font destruction.
87    SkAutoTDelete<const SkTArray<Run> > fRuns;
88    const SkRect                        fBounds;
89
90    mutable uint32_t                    fUniqueID;
91
92    typedef SkRefCnt INHERITED;
93};
94
95/** \class SkTextBlobBuilder
96
97    Helper class for constructing SkTextBlobs.
98 */
99class SK_API SkTextBlobBuilder {
100public:
101    /**
102     *  @param runs The number of runs to be added, if known. This is a storage hint and
103     *              not a limit.
104     */
105    SkTextBlobBuilder(unsigned runs = 0);
106
107    ~SkTextBlobBuilder();
108
109    /**
110     *  Returns an immutable SkTextBlob for the current runs/glyphs. The builder is reset and
111     *  can be reused.
112     */
113    const SkTextBlob* build();
114
115    /**
116     *  Glyph and position buffers associated with a run.
117     *
118     *  A run is a sequence of glyphs sharing the same font metrics and positioning mode.
119     */
120    struct RunBuffer {
121        uint16_t* glyphs;
122        SkScalar* pos;
123    };
124
125    /**
126     *  Allocates a new default-positioned run and returns its writable glyph buffer
127     *  for direct manipulation.
128     *
129     *  @param font    The font to be used for this run.
130     *  @param count   Number of glyphs.
131     *  @param x,y     Position within the blob.
132     *  @param bounds  Optional run bounding box. If known in advance (!= NULL), it will
133     *                 be used when computing the blob bounds, to avoid re-measuring.
134     *
135     *  @return        A writable glyph buffer, valid until the next allocRun() or
136     *                 build() call. The buffer is guaranteed to hold @count@ glyphs.
137     */
138    const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y,
139                              const SkRect* bounds = NULL);
140
141    /**
142     *  Allocates a new horizontally-positioned run and returns its writable glyph and position
143     *  buffers for direct manipulation.
144     *
145     *  @param font    The font to be used for this run.
146     *  @param count   Number of glyphs.
147     *  @param y       Vertical offset within the blob.
148     *  @param bounds  Optional run bounding box. If known in advance (!= NULL), it will
149     *                 be used when computing the blob bounds, to avoid re-measuring.
150     *
151     *  @return        Writable glyph and position buffers, valid until the next allocRun()
152     *                 or build() call. The buffers are guaranteed to hold @count@ elements.
153     */
154    const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y,
155                                  const SkRect* bounds = NULL);
156
157    /**
158     *  Allocates a new fully-positioned run and returns its writable glyph and position
159     *  buffers for direct manipulation.
160     *
161     *  @param font   The font to be used for this run.
162     *  @param count  Number of glyphs.
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 glyph buffer and position buffer are
168     *                guaranteed to hold @count@ and 2 * @count@ elements, respectively.
169     */
170    const RunBuffer& allocRunPos(const SkPaint& font, int count, const SkRect* bounds = NULL);
171
172private:
173    void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
174                       int count, SkPoint offset, const SkRect* bounds);
175    void ensureRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
176                   const SkPoint& offset);
177    void updateDeferredBounds();
178
179    SkTDArray<uint16_t>        fGlyphBuffer;
180    SkTDArray<SkScalar>        fPosBuffer;
181    SkTArray<SkTextBlob::Run>* fRuns;
182
183    SkRect                     fBounds;
184    bool                       fDeferredBounds;
185
186    RunBuffer                  fCurrentRunBuffer;
187};
188
189#endif // SkTextBlob_DEFINED
190