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