blob: b0ab8929e60f91cfdfe4190fa772c6e935539da8 [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 /**
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 */
47 static const SkTextBlob* CreateFromBuffer(SkReadBuffer&);
48
fmalita00d5c2c2014-08-21 08:53:26 -070049 enum GlyphPositioning {
50 kDefault_Positioning = 0, // Default glyph advances -- zero scalars per glyph.
51 kHorizontal_Positioning = 1, // Horizontal positioning -- one scalar per glyph.
52 kFull_Positioning = 2 // Point positioning -- two scalars per glyph.
53 };
54
halcanary33779752015-10-27 14:01:05 -070055private:
fmalita3c196de2014-09-20 05:40:22 -070056 class RunRecord;
57
fmalita3c196de2014-09-20 05:40:22 -070058 SkTextBlob(int runCount, const SkRect& bounds);
fmalita00d5c2c2014-08-21 08:53:26 -070059
fmalita3c196de2014-09-20 05:40:22 -070060 virtual ~SkTextBlob();
bsalomon07280312014-11-20 08:02:46 -080061
62 // Memory for objects of this class is created with sk_malloc rather than operator new and must
63 // be freed with sk_free.
64 void operator delete(void* p) { sk_free(p); }
65 void* operator new(size_t) {
66 SkFAIL("All blobs are created by placement new.");
67 return sk_malloc_throw(0);
68 }
69 void* operator new(size_t, void* p) { return p; }
fmalita00d5c2c2014-08-21 08:53:26 -070070
fmalitab7425172014-08-26 07:56:44 -070071 static unsigned ScalarsPerGlyph(GlyphPositioning pos);
72
fmalita00d5c2c2014-08-21 08:53:26 -070073 friend class SkTextBlobBuilder;
halcanary33779752015-10-27 14:01:05 -070074 friend class SkTextBlobRunIterator;
fmalita00d5c2c2014-08-21 08:53:26 -070075
fmalita3c196de2014-09-20 05:40:22 -070076 const int fRunCount;
77 const SkRect fBounds;
joshualitt2af85832015-03-25 13:40:13 -070078 const uint32_t fUniqueID;
fmalita00d5c2c2014-08-21 08:53:26 -070079
fmalita3c196de2014-09-20 05:40:22 -070080 SkDEBUGCODE(size_t fStorageSize;)
fmalita00d5c2c2014-08-21 08:53:26 -070081
fmalita3c196de2014-09-20 05:40:22 -070082 // The actual payload resides in externally-managed storage, following the object.
83 // (see the .cpp for more details)
fmalita00d5c2c2014-08-21 08:53:26 -070084
85 typedef SkRefCnt INHERITED;
86};
87
88/** \class SkTextBlobBuilder
89
90 Helper class for constructing SkTextBlobs.
91 */
jbroman3053dfa2014-08-25 06:22:12 -070092class SK_API SkTextBlobBuilder {
fmalita00d5c2c2014-08-21 08:53:26 -070093public:
fmalita3c196de2014-09-20 05:40:22 -070094 SkTextBlobBuilder();
fmalita00d5c2c2014-08-21 08:53:26 -070095
96 ~SkTextBlobBuilder();
97
98 /**
99 * Returns an immutable SkTextBlob for the current runs/glyphs. The builder is reset and
100 * can be reused.
101 */
102 const SkTextBlob* build();
103
104 /**
105 * Glyph and position buffers associated with a run.
106 *
107 * A run is a sequence of glyphs sharing the same font metrics and positioning mode.
108 */
109 struct RunBuffer {
110 uint16_t* glyphs;
111 SkScalar* pos;
112 };
113
114 /**
115 * Allocates a new default-positioned run and returns its writable glyph buffer
116 * for direct manipulation.
117 *
118 * @param font The font to be used for this run.
119 * @param count Number of glyphs.
120 * @param x,y Position within the blob.
121 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
122 * be used when computing the blob bounds, to avoid re-measuring.
123 *
124 * @return A writable glyph buffer, valid until the next allocRun() or
125 * build() call. The buffer is guaranteed to hold @count@ glyphs.
126 */
127 const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y,
128 const SkRect* bounds = NULL);
129
130 /**
131 * Allocates a new horizontally-positioned run and returns its writable glyph and position
132 * buffers for direct manipulation.
133 *
134 * @param font The font to be used for this run.
135 * @param count Number of glyphs.
136 * @param y Vertical offset within the blob.
137 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
138 * be used when computing the blob bounds, to avoid re-measuring.
139 *
140 * @return Writable glyph and position buffers, valid until the next allocRun()
141 * or build() call. The buffers are guaranteed to hold @count@ elements.
142 */
143 const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y,
144 const SkRect* bounds = NULL);
145
146 /**
147 * Allocates a new fully-positioned run and returns its writable glyph and position
148 * buffers for direct manipulation.
149 *
150 * @param font The font to be used for this run.
151 * @param count Number of glyphs.
152 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
153 * be used when computing the blob bounds, to avoid re-measuring.
154 *
155 * @return Writable glyph and position buffers, valid until the next allocRun()
156 * or build() call. The glyph buffer and position buffer are
157 * guaranteed to hold @count@ and 2 * @count@ elements, respectively.
158 */
159 const RunBuffer& allocRunPos(const SkPaint& font, int count, const SkRect* bounds = NULL);
160
161private:
fmalita3c196de2014-09-20 05:40:22 -0700162 void reserve(size_t size);
fmalita00d5c2c2014-08-21 08:53:26 -0700163 void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
164 int count, SkPoint offset, const SkRect* bounds);
fmalita3c196de2014-09-20 05:40:22 -0700165 bool mergeRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
166 int count, SkPoint offset);
fmalita00d5c2c2014-08-21 08:53:26 -0700167 void updateDeferredBounds();
168
fmalita3dc40ac2015-01-28 10:56:06 -0800169 static SkRect ConservativeRunBounds(const SkTextBlob::RunRecord&);
170 static SkRect TightRunBounds(const SkTextBlob::RunRecord&);
171
fmalita3c196de2014-09-20 05:40:22 -0700172 SkAutoTMalloc<uint8_t> fStorage;
173 size_t fStorageSize;
174 size_t fStorageUsed;
fmalita00d5c2c2014-08-21 08:53:26 -0700175
fmalita3c196de2014-09-20 05:40:22 -0700176 SkRect fBounds;
177 int fRunCount;
178 bool fDeferredBounds;
179 size_t fLastRun; // index into fStorage
fmalita00d5c2c2014-08-21 08:53:26 -0700180
fmalita3c196de2014-09-20 05:40:22 -0700181 RunBuffer fCurrentRunBuffer;
fmalita00d5c2c2014-08-21 08:53:26 -0700182};
183
184#endif // SkTextBlob_DEFINED