blob: 1d17f4dafe516c307d6709665eb03ab51083e790 [file] [log] [blame]
fmalita00d5c2c2014-08-21 08:53:26 -07001/*
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
bungemanbf521ff2016-02-17 13:13:44 -080011#include "../private/SkTemplates.h"
fmalita00d5c2c2014-08-21 08:53:26 -070012#include "SkPaint.h"
halcanary4f0a23a2016-08-30 11:58:33 -070013#include "SkString.h"
fmalita00d5c2c2014-08-21 08:53:26 -070014#include "SkRefCnt.h"
fmalita00d5c2c2014-08-21 08:53:26 -070015
fmalitab7425172014-08-26 07:56:44 -070016class SkReadBuffer;
17class SkWriteBuffer;
18
fmalita00d5c2c2014-08-21 08:53:26 -070019/** \class SkTextBlob
20
21 SkTextBlob combines multiple text runs into an immutable, ref-counted structure.
22*/
mtkleinb47cd4b2016-08-09 12:20:04 -070023class SK_API SkTextBlob final : public SkNVRefCnt<SkTextBlob> {
fmalita00d5c2c2014-08-21 08:53:26 -070024public:
25 /**
fmalita3dc40ac2015-01-28 10:56:06 -080026 * Returns a conservative blob bounding box.
fmalita00d5c2c2014-08-21 08:53:26 -070027 */
28 const SkRect& bounds() const { return fBounds; }
29
30 /**
31 * Return a non-zero, unique value representing the text blob.
32 */
joshualitt2af85832015-03-25 13:40:13 -070033 uint32_t uniqueID() const { return fUniqueID; }
fmalita00d5c2c2014-08-21 08:53:26 -070034
fmalita228a6f22014-08-28 13:59:42 -070035 /**
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 */
reed2ab90572016-08-10 14:16:41 -070047 static sk_sp<SkTextBlob> MakeFromBuffer(SkReadBuffer&);
48
49 static const SkTextBlob* CreateFromBuffer(SkReadBuffer& buffer) {
50 return MakeFromBuffer(buffer).release();
51 }
fmalita228a6f22014-08-28 13:59:42 -070052
halcanary4f0a23a2016-08-30 11:58:33 -070053 enum GlyphPositioning : uint8_t {
fmalita00d5c2c2014-08-21 08:53:26 -070054 kDefault_Positioning = 0, // Default glyph advances -- zero scalars per glyph.
55 kHorizontal_Positioning = 1, // Horizontal positioning -- one scalar per glyph.
56 kFull_Positioning = 2 // Point positioning -- two scalars per glyph.
57 };
58
halcanary33779752015-10-27 14:01:05 -070059private:
mtkleinb47cd4b2016-08-09 12:20:04 -070060 friend class SkNVRefCnt<SkTextBlob>;
fmalita3c196de2014-09-20 05:40:22 -070061 class RunRecord;
62
Florin Malita3a9a7a32017-03-13 09:03:24 -040063 explicit SkTextBlob(const SkRect& bounds);
fmalita00d5c2c2014-08-21 08:53:26 -070064
mtkleinb47cd4b2016-08-09 12:20:04 -070065 ~SkTextBlob();
bsalomon07280312014-11-20 08:02:46 -080066
67 // Memory for objects of this class is created with sk_malloc rather than operator new and must
68 // be freed with sk_free.
69 void operator delete(void* p) { sk_free(p); }
70 void* operator new(size_t) {
71 SkFAIL("All blobs are created by placement new.");
72 return sk_malloc_throw(0);
73 }
74 void* operator new(size_t, void* p) { return p; }
fmalita00d5c2c2014-08-21 08:53:26 -070075
fmalitab7425172014-08-26 07:56:44 -070076 static unsigned ScalarsPerGlyph(GlyphPositioning pos);
77
fmalita00d5c2c2014-08-21 08:53:26 -070078 friend class SkTextBlobBuilder;
halcanary33779752015-10-27 14:01:05 -070079 friend class SkTextBlobRunIterator;
fmalita00d5c2c2014-08-21 08:53:26 -070080
Florin Malita3a9a7a32017-03-13 09:03:24 -040081 const SkRect fBounds;
joshualitt2af85832015-03-25 13:40:13 -070082 const uint32_t fUniqueID;
fmalita00d5c2c2014-08-21 08:53:26 -070083
fmalita3c196de2014-09-20 05:40:22 -070084 SkDEBUGCODE(size_t fStorageSize;)
fmalita00d5c2c2014-08-21 08:53:26 -070085
fmalita3c196de2014-09-20 05:40:22 -070086 // The actual payload resides in externally-managed storage, following the object.
87 // (see the .cpp for more details)
fmalita00d5c2c2014-08-21 08:53:26 -070088
89 typedef SkRefCnt INHERITED;
90};
91
92/** \class SkTextBlobBuilder
93
94 Helper class for constructing SkTextBlobs.
95 */
jbroman3053dfa2014-08-25 06:22:12 -070096class SK_API SkTextBlobBuilder {
fmalita00d5c2c2014-08-21 08:53:26 -070097public:
fmalita3c196de2014-09-20 05:40:22 -070098 SkTextBlobBuilder();
fmalita00d5c2c2014-08-21 08:53:26 -070099
100 ~SkTextBlobBuilder();
101
102 /**
Florin Malita3a9a7a32017-03-13 09:03:24 -0400103 * Returns an immutable SkTextBlob for the current runs/glyphs,
104 * or nullptr if no runs were allocated.
105 *
106 * The builder is reset and can be reused.
fmalita00d5c2c2014-08-21 08:53:26 -0700107 */
reed2ab90572016-08-10 14:16:41 -0700108 sk_sp<SkTextBlob> make();
109
fmalita00d5c2c2014-08-21 08:53:26 -0700110 /**
111 * Glyph and position buffers associated with a run.
112 *
halcanary4f0a23a2016-08-30 11:58:33 -0700113 * A run is a sequence of glyphs sharing the same font metrics
114 * and positioning mode.
115 *
116 * If textByteCount is 0, utf8text and clusters will be NULL (no
117 * character information will be associated with the glyphs).
118 *
119 * utf8text will point to a buffer of size textByteCount bytes.
120 *
121 * clusters (if not NULL) will point to an array of size count.
122 * For each glyph, give the byte-offset into the text for the
123 * first byte in the first character in that glyph's cluster.
124 * Each value in the array should be an integer less than
125 * textByteCount. Values in the array should either be
126 * monotonically increasing (left-to-right text) or monotonically
127 * decreasing (right-to-left text). This definiton is conviently
128 * the same as used by Harfbuzz's hb_glyph_info_t::cluster field,
129 * except that Harfbuzz interleaves glyphs and clusters.
fmalita00d5c2c2014-08-21 08:53:26 -0700130 */
131 struct RunBuffer {
halcanaryd0e95a52016-07-25 07:18:12 -0700132 SkGlyphID* glyphs;
fmalita00d5c2c2014-08-21 08:53:26 -0700133 SkScalar* pos;
halcanary4f0a23a2016-08-30 11:58:33 -0700134 char* utf8text;
135 uint32_t* clusters;
fmalita00d5c2c2014-08-21 08:53:26 -0700136 };
137
138 /**
139 * Allocates a new default-positioned run and returns its writable glyph buffer
140 * for direct manipulation.
141 *
142 * @param font The font to be used for this run.
143 * @param count Number of glyphs.
144 * @param x,y Position within the blob.
halcanary4f0a23a2016-08-30 11:58:33 -0700145 * @param textByteCount length of the original UTF-8 text that
146 * corresponds to this sequence of glyphs. If 0,
147 * text will not be included in the textblob.
148 * @param lang Language code, currently unimplemented.
fmalita00d5c2c2014-08-21 08:53:26 -0700149 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
150 * be used when computing the blob bounds, to avoid re-measuring.
151 *
152 * @return A writable glyph buffer, valid until the next allocRun() or
153 * build() call. The buffer is guaranteed to hold @count@ glyphs.
154 */
halcanary4f0a23a2016-08-30 11:58:33 -0700155 const RunBuffer& allocRunText(const SkPaint& font,
156 int count,
157 SkScalar x,
158 SkScalar y,
159 int textByteCount,
160 SkString lang,
161 const SkRect* bounds = NULL);
fmalita00d5c2c2014-08-21 08:53:26 -0700162 const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y,
halcanary4f0a23a2016-08-30 11:58:33 -0700163 const SkRect* bounds = NULL) {
164 return this->allocRunText(font, count, x, y, 0, SkString(), bounds);
165 }
fmalita00d5c2c2014-08-21 08:53:26 -0700166
167 /**
168 * Allocates a new horizontally-positioned run and returns its writable glyph and position
169 * buffers for direct manipulation.
170 *
171 * @param font The font to be used for this run.
172 * @param count Number of glyphs.
173 * @param y Vertical offset within the blob.
halcanary4f0a23a2016-08-30 11:58:33 -0700174 * @param textByteCount length of the original UTF-8 text that
175 * corresponds to this sequence of glyphs. If 0,
176 * text will not be included in the textblob.
177 * @param lang Language code, currently unimplemented.
fmalita00d5c2c2014-08-21 08:53:26 -0700178 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
179 * be used when computing the blob bounds, to avoid re-measuring.
180 *
181 * @return Writable glyph and position buffers, valid until the next allocRun()
182 * or build() call. The buffers are guaranteed to hold @count@ elements.
183 */
halcanary4f0a23a2016-08-30 11:58:33 -0700184 const RunBuffer& allocRunTextPosH(const SkPaint& font, int count, SkScalar y,
185 int textByteCount, SkString lang,
186 const SkRect* bounds = NULL);
fmalita00d5c2c2014-08-21 08:53:26 -0700187 const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y,
halcanary4f0a23a2016-08-30 11:58:33 -0700188 const SkRect* bounds = NULL) {
189 return this->allocRunTextPosH(font, count, y, 0, SkString(), bounds);
190 }
fmalita00d5c2c2014-08-21 08:53:26 -0700191
192 /**
193 * Allocates a new fully-positioned run and returns its writable glyph and position
194 * buffers for direct manipulation.
195 *
196 * @param font The font to be used for this run.
197 * @param count Number of glyphs.
halcanary4f0a23a2016-08-30 11:58:33 -0700198 * @param textByteCount length of the original UTF-8 text that
199 * corresponds to this sequence of glyphs. If 0,
200 * text will not be included in the textblob.
201 * @param lang Language code, currently unimplemented.
fmalita00d5c2c2014-08-21 08:53:26 -0700202 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
203 * be used when computing the blob bounds, to avoid re-measuring.
204 *
205 * @return Writable glyph and position buffers, valid until the next allocRun()
206 * or build() call. The glyph buffer and position buffer are
207 * guaranteed to hold @count@ and 2 * @count@ elements, respectively.
208 */
halcanary4f0a23a2016-08-30 11:58:33 -0700209 const RunBuffer& allocRunTextPos(const SkPaint& font, int count,
210 int textByteCount, SkString lang,
211 const SkRect* bounds = NULL);
212 const RunBuffer& allocRunPos(const SkPaint& font, int count,
213 const SkRect* bounds = NULL) {
214 return this->allocRunTextPos(font, count, 0, SkString(), bounds);
215 }
fmalita00d5c2c2014-08-21 08:53:26 -0700216
217private:
fmalita3c196de2014-09-20 05:40:22 -0700218 void reserve(size_t size);
fmalita00d5c2c2014-08-21 08:53:26 -0700219 void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
halcanary4f0a23a2016-08-30 11:58:33 -0700220 int count, int textBytes, SkPoint offset, const SkRect* bounds);
fmalita3c196de2014-09-20 05:40:22 -0700221 bool mergeRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
222 int count, SkPoint offset);
fmalita00d5c2c2014-08-21 08:53:26 -0700223 void updateDeferredBounds();
224
fmalita3dc40ac2015-01-28 10:56:06 -0800225 static SkRect ConservativeRunBounds(const SkTextBlob::RunRecord&);
226 static SkRect TightRunBounds(const SkTextBlob::RunRecord&);
227
fmalita3c196de2014-09-20 05:40:22 -0700228 SkAutoTMalloc<uint8_t> fStorage;
229 size_t fStorageSize;
230 size_t fStorageUsed;
fmalita00d5c2c2014-08-21 08:53:26 -0700231
fmalita3c196de2014-09-20 05:40:22 -0700232 SkRect fBounds;
233 int fRunCount;
234 bool fDeferredBounds;
235 size_t fLastRun; // index into fStorage
fmalita00d5c2c2014-08-21 08:53:26 -0700236
fmalita3c196de2014-09-20 05:40:22 -0700237 RunBuffer fCurrentRunBuffer;
fmalita00d5c2c2014-08-21 08:53:26 -0700238};
239
240#endif // SkTextBlob_DEFINED