Line data Source code
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 "../private/SkAtomics.h"
13 : #include "SkPaint.h"
14 : #include "SkString.h"
15 : #include "SkRefCnt.h"
16 :
17 : class SkReadBuffer;
18 : class SkWriteBuffer;
19 :
20 : /** \class SkTextBlob
21 :
22 : SkTextBlob combines multiple text runs into an immutable, ref-counted structure.
23 : */
24 : class SK_API SkTextBlob final : public SkNVRefCnt<SkTextBlob> {
25 : public:
26 : /**
27 : * Returns a conservative blob bounding box.
28 : */
29 0 : const SkRect& bounds() const { return fBounds; }
30 :
31 : /**
32 : * Return a non-zero, unique value representing the text blob.
33 : */
34 0 : uint32_t uniqueID() const { return fUniqueID; }
35 :
36 : /**
37 : * Serialize to a buffer.
38 : */
39 : void flatten(SkWriteBuffer&) const;
40 :
41 : /**
42 : * Recreate an SkTextBlob that was serialized into a buffer.
43 : *
44 : * @param SkReadBuffer Serialized blob data.
45 : * @return A new SkTextBlob representing the serialized data, or NULL if the buffer is
46 : * invalid.
47 : */
48 : static sk_sp<SkTextBlob> MakeFromBuffer(SkReadBuffer&);
49 :
50 0 : static const SkTextBlob* CreateFromBuffer(SkReadBuffer& buffer) {
51 0 : return MakeFromBuffer(buffer).release();
52 : }
53 :
54 : enum GlyphPositioning : uint8_t {
55 : kDefault_Positioning = 0, // Default glyph advances -- zero scalars per glyph.
56 : kHorizontal_Positioning = 1, // Horizontal positioning -- one scalar per glyph.
57 : kFull_Positioning = 2 // Point positioning -- two scalars per glyph.
58 : };
59 :
60 : private:
61 : friend class SkNVRefCnt<SkTextBlob>;
62 : class RunRecord;
63 :
64 : explicit SkTextBlob(const SkRect& bounds);
65 :
66 : ~SkTextBlob();
67 :
68 : // Memory for objects of this class is created with sk_malloc rather than operator new and must
69 : // be freed with sk_free.
70 0 : void operator delete(void* p) { sk_free(p); }
71 : void* operator new(size_t) {
72 : SkFAIL("All blobs are created by placement new.");
73 : return sk_malloc_throw(0);
74 : }
75 0 : void* operator new(size_t, void* p) { return p; }
76 :
77 : static unsigned ScalarsPerGlyph(GlyphPositioning pos);
78 :
79 : // Call when this blob is part of the key to a cache entry. This allows the cache
80 : // to know automatically those entries can be purged when this SkTextBlob is deleted.
81 0 : void notifyAddedToCache() const {
82 0 : fAddedToCache.store(true);
83 0 : }
84 :
85 : friend class GrTextBlobCache;
86 : friend class SkTextBlobBuilder;
87 : friend class SkTextBlobRunIterator;
88 :
89 : const SkRect fBounds;
90 : const uint32_t fUniqueID;
91 : mutable SkAtomic<bool> fAddedToCache;
92 :
93 : SkDEBUGCODE(size_t fStorageSize;)
94 :
95 : // The actual payload resides in externally-managed storage, following the object.
96 : // (see the .cpp for more details)
97 :
98 : typedef SkRefCnt INHERITED;
99 : };
100 :
101 : /** \class SkTextBlobBuilder
102 :
103 : Helper class for constructing SkTextBlobs.
104 : */
105 : class SK_API SkTextBlobBuilder {
106 : public:
107 : SkTextBlobBuilder();
108 :
109 : ~SkTextBlobBuilder();
110 :
111 : /**
112 : * Returns an immutable SkTextBlob for the current runs/glyphs,
113 : * or nullptr if no runs were allocated.
114 : *
115 : * The builder is reset and can be reused.
116 : */
117 : sk_sp<SkTextBlob> make();
118 :
119 : /**
120 : * Glyph and position buffers associated with a run.
121 : *
122 : * A run is a sequence of glyphs sharing the same font metrics
123 : * and positioning mode.
124 : *
125 : * If textByteCount is 0, utf8text and clusters will be NULL (no
126 : * character information will be associated with the glyphs).
127 : *
128 : * utf8text will point to a buffer of size textByteCount bytes.
129 : *
130 : * clusters (if not NULL) will point to an array of size count.
131 : * For each glyph, give the byte-offset into the text for the
132 : * first byte in the first character in that glyph's cluster.
133 : * Each value in the array should be an integer less than
134 : * textByteCount. Values in the array should either be
135 : * monotonically increasing (left-to-right text) or monotonically
136 : * decreasing (right-to-left text). This definiton is conviently
137 : * the same as used by Harfbuzz's hb_glyph_info_t::cluster field,
138 : * except that Harfbuzz interleaves glyphs and clusters.
139 : */
140 : struct RunBuffer {
141 : SkGlyphID* glyphs;
142 : SkScalar* pos;
143 : char* utf8text;
144 : uint32_t* clusters;
145 : };
146 :
147 : /**
148 : * Allocates a new default-positioned run and returns its writable glyph buffer
149 : * for direct manipulation.
150 : *
151 : * @param font The font to be used for this run.
152 : * @param count Number of glyphs.
153 : * @param x,y Position within the blob.
154 : * @param textByteCount length of the original UTF-8 text that
155 : * corresponds to this sequence of glyphs. If 0,
156 : * text will not be included in the textblob.
157 : * @param lang Language code, currently unimplemented.
158 : * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
159 : * be used when computing the blob bounds, to avoid re-measuring.
160 : *
161 : * @return A writable glyph buffer, valid until the next allocRun() or
162 : * build() call. The buffer is guaranteed to hold @count@ glyphs.
163 : */
164 : const RunBuffer& allocRunText(const SkPaint& font,
165 : int count,
166 : SkScalar x,
167 : SkScalar y,
168 : int textByteCount,
169 : SkString lang,
170 : const SkRect* bounds = NULL);
171 : const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y,
172 : const SkRect* bounds = NULL) {
173 : return this->allocRunText(font, count, x, y, 0, SkString(), bounds);
174 : }
175 :
176 : /**
177 : * Allocates a new horizontally-positioned run and returns its writable glyph and position
178 : * buffers for direct manipulation.
179 : *
180 : * @param font The font to be used for this run.
181 : * @param count Number of glyphs.
182 : * @param y Vertical offset within the blob.
183 : * @param textByteCount length of the original UTF-8 text that
184 : * corresponds to this sequence of glyphs. If 0,
185 : * text will not be included in the textblob.
186 : * @param lang Language code, currently unimplemented.
187 : * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
188 : * be used when computing the blob bounds, to avoid re-measuring.
189 : *
190 : * @return Writable glyph and position buffers, valid until the next allocRun()
191 : * or build() call. The buffers are guaranteed to hold @count@ elements.
192 : */
193 : const RunBuffer& allocRunTextPosH(const SkPaint& font, int count, SkScalar y,
194 : int textByteCount, SkString lang,
195 : const SkRect* bounds = NULL);
196 : const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y,
197 : const SkRect* bounds = NULL) {
198 : return this->allocRunTextPosH(font, count, y, 0, SkString(), bounds);
199 : }
200 :
201 : /**
202 : * Allocates a new fully-positioned run and returns its writable glyph and position
203 : * buffers for direct manipulation.
204 : *
205 : * @param font The font to be used for this run.
206 : * @param count Number of glyphs.
207 : * @param textByteCount length of the original UTF-8 text that
208 : * corresponds to this sequence of glyphs. If 0,
209 : * text will not be included in the textblob.
210 : * @param lang Language code, currently unimplemented.
211 : * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
212 : * be used when computing the blob bounds, to avoid re-measuring.
213 : *
214 : * @return Writable glyph and position buffers, valid until the next allocRun()
215 : * or build() call. The glyph buffer and position buffer are
216 : * guaranteed to hold @count@ and 2 * @count@ elements, respectively.
217 : */
218 : const RunBuffer& allocRunTextPos(const SkPaint& font, int count,
219 : int textByteCount, SkString lang,
220 : const SkRect* bounds = NULL);
221 0 : const RunBuffer& allocRunPos(const SkPaint& font, int count,
222 : const SkRect* bounds = NULL) {
223 0 : return this->allocRunTextPos(font, count, 0, SkString(), bounds);
224 : }
225 :
226 : private:
227 : void reserve(size_t size);
228 : void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
229 : int count, int textBytes, SkPoint offset, const SkRect* bounds);
230 : bool mergeRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
231 : int count, SkPoint offset);
232 : void updateDeferredBounds();
233 :
234 : static SkRect ConservativeRunBounds(const SkTextBlob::RunRecord&);
235 : static SkRect TightRunBounds(const SkTextBlob::RunRecord&);
236 :
237 : SkAutoTMalloc<uint8_t> fStorage;
238 : size_t fStorageSize;
239 : size_t fStorageUsed;
240 :
241 : SkRect fBounds;
242 : int fRunCount;
243 : bool fDeferredBounds;
244 : size_t fLastRun; // index into fStorage
245 :
246 : RunBuffer fCurrentRunBuffer;
247 : };
248 :
249 : #endif // SkTextBlob_DEFINED
|