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 
15 class SkReadBuffer;
16 class SkWriteBuffer;
17 
18 /** \class SkTextBlob
19 
20     SkTextBlob combines multiple text runs into an immutable, ref-counted structure.
21 */
22 class SK_API SkTextBlob : public SkRefCnt {
23 public:
24     /**
25      *  Returns a conservative blob bounding box.
26      */
bounds()27     const SkRect& bounds() const { return fBounds; }
28 
29     /**
30      *  Return a non-zero, unique value representing the text blob.
31      */
uniqueID()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 
54 private:
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.
delete(void * p)63     void operator delete(void* p) { sk_free(p); }
new(size_t)64     void* operator new(size_t) {
65         SkFAIL("All blobs are created by placement new.");
66         return sk_malloc_throw(0);
67     }
new(size_t,void * p)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  */
91 class SK_API SkTextBlobBuilder {
92 public:
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 
160 private:
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