blob: 334cfb98c4595d2d51844e55c82880b89de9a34e [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
11#include "SkPaint.h"
12#include "SkRefCnt.h"
13#include "SkTArray.h"
14#include "SkTDArray.h"
15
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*/
jbroman3053dfa2014-08-25 06:22:12 -070023class SK_API SkTextBlob : public SkRefCnt {
fmalita00d5c2c2014-08-21 08:53:26 -070024public:
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
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 */
47 static const SkTextBlob* CreateFromBuffer(SkReadBuffer&);
48
fmalita00d5c2c2014-08-21 08:53:26 -070049private:
50 enum GlyphPositioning {
51 kDefault_Positioning = 0, // Default glyph advances -- zero scalars per glyph.
52 kHorizontal_Positioning = 1, // Horizontal positioning -- one scalar per glyph.
53 kFull_Positioning = 2 // Point positioning -- two scalars per glyph.
54 };
55
fmalita3c196de2014-09-20 05:40:22 -070056 class RunRecord;
57
fmalita00d5c2c2014-08-21 08:53:26 -070058 class RunIterator {
59 public:
60 RunIterator(const SkTextBlob* blob);
61
62 bool done() const;
63 void next();
64
65 uint32_t glyphCount() const;
66 const uint16_t* glyphs() const;
67 const SkScalar* pos() const;
68 const SkPoint& offset() const;
fmalita37ecbaf2014-08-22 09:01:19 -070069 void applyFontToPaint(SkPaint*) const;
fmalita00d5c2c2014-08-21 08:53:26 -070070 GlyphPositioning positioning() const;
71
72 private:
fmalita3c196de2014-09-20 05:40:22 -070073 const RunRecord* fCurrentRun;
74 int fRemainingRuns;
75
76 SkDEBUGCODE(uint8_t* fStorageTop;)
fmalita00d5c2c2014-08-21 08:53:26 -070077 };
78
fmalita3c196de2014-09-20 05:40:22 -070079 SkTextBlob(int runCount, const SkRect& bounds);
fmalita00d5c2c2014-08-21 08:53:26 -070080
fmalita3c196de2014-09-20 05:40:22 -070081 virtual ~SkTextBlob();
bsalomon07280312014-11-20 08:02:46 -080082
83 // Memory for objects of this class is created with sk_malloc rather than operator new and must
84 // be freed with sk_free.
85 void operator delete(void* p) { sk_free(p); }
86 void* operator new(size_t) {
87 SkFAIL("All blobs are created by placement new.");
88 return sk_malloc_throw(0);
89 }
90 void* operator new(size_t, void* p) { return p; }
fmalita00d5c2c2014-08-21 08:53:26 -070091
fmalitab7425172014-08-26 07:56:44 -070092 static unsigned ScalarsPerGlyph(GlyphPositioning pos);
93
fmalitaaa1b9122014-08-28 14:32:24 -070094 friend class SkBaseDevice;
fmalita00d5c2c2014-08-21 08:53:26 -070095 friend class SkTextBlobBuilder;
fmalitac6765d62014-08-21 15:03:04 -070096 friend class TextBlobTester;
fmalita00d5c2c2014-08-21 08:53:26 -070097
fmalita3c196de2014-09-20 05:40:22 -070098 const int fRunCount;
99 const SkRect fBounds;
100 mutable uint32_t fUniqueID;
fmalita00d5c2c2014-08-21 08:53:26 -0700101
fmalita3c196de2014-09-20 05:40:22 -0700102 SkDEBUGCODE(size_t fStorageSize;)
fmalita00d5c2c2014-08-21 08:53:26 -0700103
fmalita3c196de2014-09-20 05:40:22 -0700104 // The actual payload resides in externally-managed storage, following the object.
105 // (see the .cpp for more details)
fmalita00d5c2c2014-08-21 08:53:26 -0700106
107 typedef SkRefCnt INHERITED;
108};
109
110/** \class SkTextBlobBuilder
111
112 Helper class for constructing SkTextBlobs.
113 */
jbroman3053dfa2014-08-25 06:22:12 -0700114class SK_API SkTextBlobBuilder {
fmalita00d5c2c2014-08-21 08:53:26 -0700115public:
fmalita3c196de2014-09-20 05:40:22 -0700116 SkTextBlobBuilder();
fmalita00d5c2c2014-08-21 08:53:26 -0700117
118 ~SkTextBlobBuilder();
119
120 /**
121 * Returns an immutable SkTextBlob for the current runs/glyphs. The builder is reset and
122 * can be reused.
123 */
124 const SkTextBlob* build();
125
126 /**
127 * Glyph and position buffers associated with a run.
128 *
129 * A run is a sequence of glyphs sharing the same font metrics and positioning mode.
130 */
131 struct RunBuffer {
132 uint16_t* glyphs;
133 SkScalar* pos;
134 };
135
136 /**
137 * Allocates a new default-positioned run and returns its writable glyph buffer
138 * for direct manipulation.
139 *
140 * @param font The font to be used for this run.
141 * @param count Number of glyphs.
142 * @param x,y Position within the blob.
143 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
144 * be used when computing the blob bounds, to avoid re-measuring.
145 *
146 * @return A writable glyph buffer, valid until the next allocRun() or
147 * build() call. The buffer is guaranteed to hold @count@ glyphs.
148 */
149 const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y,
150 const SkRect* bounds = NULL);
151
152 /**
153 * Allocates a new horizontally-positioned run and returns its writable glyph and position
154 * buffers for direct manipulation.
155 *
156 * @param font The font to be used for this run.
157 * @param count Number of glyphs.
158 * @param y Vertical offset within the blob.
159 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
160 * be used when computing the blob bounds, to avoid re-measuring.
161 *
162 * @return Writable glyph and position buffers, valid until the next allocRun()
163 * or build() call. The buffers are guaranteed to hold @count@ elements.
164 */
165 const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y,
166 const SkRect* bounds = NULL);
167
168 /**
169 * Allocates a new fully-positioned run and returns its writable glyph and position
170 * buffers for direct manipulation.
171 *
172 * @param font The font to be used for this run.
173 * @param count Number of glyphs.
174 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
175 * be used when computing the blob bounds, to avoid re-measuring.
176 *
177 * @return Writable glyph and position buffers, valid until the next allocRun()
178 * or build() call. The glyph buffer and position buffer are
179 * guaranteed to hold @count@ and 2 * @count@ elements, respectively.
180 */
181 const RunBuffer& allocRunPos(const SkPaint& font, int count, const SkRect* bounds = NULL);
182
183private:
fmalita3c196de2014-09-20 05:40:22 -0700184 void reserve(size_t size);
fmalita00d5c2c2014-08-21 08:53:26 -0700185 void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
186 int count, SkPoint offset, const SkRect* bounds);
fmalita3c196de2014-09-20 05:40:22 -0700187 bool mergeRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
188 int count, SkPoint offset);
fmalita00d5c2c2014-08-21 08:53:26 -0700189 void updateDeferredBounds();
190
fmalita3c196de2014-09-20 05:40:22 -0700191 SkAutoTMalloc<uint8_t> fStorage;
192 size_t fStorageSize;
193 size_t fStorageUsed;
fmalita00d5c2c2014-08-21 08:53:26 -0700194
fmalita3c196de2014-09-20 05:40:22 -0700195 SkRect fBounds;
196 int fRunCount;
197 bool fDeferredBounds;
198 size_t fLastRun; // index into fStorage
fmalita00d5c2c2014-08-21 08:53:26 -0700199
fmalita3c196de2014-09-20 05:40:22 -0700200 RunBuffer fCurrentRunBuffer;
fmalita00d5c2c2014-08-21 08:53:26 -0700201};
202
203#endif // SkTextBlob_DEFINED