blob: 1addb6f9142e11b7252ec3a534f50b571bfee44e [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"
13#include "SkRefCnt.h"
fmalita00d5c2c2014-08-21 08:53:26 -070014
fmalitab7425172014-08-26 07:56:44 -070015class SkReadBuffer;
16class SkWriteBuffer;
17
fmalita00d5c2c2014-08-21 08:53:26 -070018/** \class SkTextBlob
19
20 SkTextBlob combines multiple text runs into an immutable, ref-counted structure.
21*/
mtkleinb47cd4b2016-08-09 12:20:04 -070022class SK_API SkTextBlob final : public SkNVRefCnt<SkTextBlob> {
fmalita00d5c2c2014-08-21 08:53:26 -070023public:
24 /**
fmalita3dc40ac2015-01-28 10:56:06 -080025 * Returns a conservative blob bounding box.
fmalita00d5c2c2014-08-21 08:53:26 -070026 */
27 const SkRect& bounds() const { return fBounds; }
28
29 /**
30 * Return a non-zero, unique value representing the text blob.
31 */
joshualitt2af85832015-03-25 13:40:13 -070032 uint32_t uniqueID() const { return fUniqueID; }
fmalita00d5c2c2014-08-21 08:53:26 -070033
fmalita228a6f22014-08-28 13:59:42 -070034 /**
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 */
reed2ab90572016-08-10 14:16:41 -070046 static sk_sp<SkTextBlob> MakeFromBuffer(SkReadBuffer&);
47
48 static const SkTextBlob* CreateFromBuffer(SkReadBuffer& buffer) {
49 return MakeFromBuffer(buffer).release();
50 }
fmalita228a6f22014-08-28 13:59:42 -070051
fmalita00d5c2c2014-08-21 08:53:26 -070052 enum GlyphPositioning {
53 kDefault_Positioning = 0, // Default glyph advances -- zero scalars per glyph.
54 kHorizontal_Positioning = 1, // Horizontal positioning -- one scalar per glyph.
55 kFull_Positioning = 2 // Point positioning -- two scalars per glyph.
56 };
57
halcanary33779752015-10-27 14:01:05 -070058private:
mtkleinb47cd4b2016-08-09 12:20:04 -070059 friend class SkNVRefCnt<SkTextBlob>;
fmalita3c196de2014-09-20 05:40:22 -070060 class RunRecord;
61
fmalita3c196de2014-09-20 05:40:22 -070062 SkTextBlob(int runCount, const SkRect& bounds);
fmalita00d5c2c2014-08-21 08:53:26 -070063
mtkleinb47cd4b2016-08-09 12:20:04 -070064 ~SkTextBlob();
bsalomon07280312014-11-20 08:02:46 -080065
66 // Memory for objects of this class is created with sk_malloc rather than operator new and must
67 // be freed with sk_free.
68 void operator delete(void* p) { sk_free(p); }
69 void* operator new(size_t) {
70 SkFAIL("All blobs are created by placement new.");
71 return sk_malloc_throw(0);
72 }
73 void* operator new(size_t, void* p) { return p; }
fmalita00d5c2c2014-08-21 08:53:26 -070074
fmalitab7425172014-08-26 07:56:44 -070075 static unsigned ScalarsPerGlyph(GlyphPositioning pos);
76
fmalita00d5c2c2014-08-21 08:53:26 -070077 friend class SkTextBlobBuilder;
halcanary33779752015-10-27 14:01:05 -070078 friend class SkTextBlobRunIterator;
fmalita00d5c2c2014-08-21 08:53:26 -070079
fmalita3c196de2014-09-20 05:40:22 -070080 const int fRunCount;
81 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 /**
103 * Returns an immutable SkTextBlob for the current runs/glyphs. The builder is reset and
104 * can be reused.
105 */
reed2ab90572016-08-10 14:16:41 -0700106 sk_sp<SkTextBlob> make();
107
108 const SkTextBlob* build() {
109 return this->make().release();
110 }
fmalita00d5c2c2014-08-21 08:53:26 -0700111
112 /**
113 * Glyph and position buffers associated with a run.
114 *
115 * A run is a sequence of glyphs sharing the same font metrics and positioning mode.
116 */
117 struct RunBuffer {
halcanaryd0e95a52016-07-25 07:18:12 -0700118 SkGlyphID* glyphs;
fmalita00d5c2c2014-08-21 08:53:26 -0700119 SkScalar* pos;
120 };
121
122 /**
123 * Allocates a new default-positioned run and returns its writable glyph buffer
124 * for direct manipulation.
125 *
126 * @param font The font to be used for this run.
127 * @param count Number of glyphs.
128 * @param x,y Position within the blob.
129 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
130 * be used when computing the blob bounds, to avoid re-measuring.
131 *
132 * @return A writable glyph buffer, valid until the next allocRun() or
133 * build() call. The buffer is guaranteed to hold @count@ glyphs.
134 */
135 const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y,
136 const SkRect* bounds = NULL);
137
138 /**
139 * Allocates a new horizontally-positioned run and returns its writable glyph and position
140 * buffers for direct manipulation.
141 *
142 * @param font The font to be used for this run.
143 * @param count Number of glyphs.
144 * @param y Vertical offset within the blob.
145 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
146 * be used when computing the blob bounds, to avoid re-measuring.
147 *
148 * @return Writable glyph and position buffers, valid until the next allocRun()
149 * or build() call. The buffers are guaranteed to hold @count@ elements.
150 */
151 const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y,
152 const SkRect* bounds = NULL);
153
154 /**
155 * Allocates a new fully-positioned run and returns its writable glyph and position
156 * buffers for direct manipulation.
157 *
158 * @param font The font to be used for this run.
159 * @param count Number of glyphs.
160 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
161 * be used when computing the blob bounds, to avoid re-measuring.
162 *
163 * @return Writable glyph and position buffers, valid until the next allocRun()
164 * or build() call. The glyph buffer and position buffer are
165 * guaranteed to hold @count@ and 2 * @count@ elements, respectively.
166 */
167 const RunBuffer& allocRunPos(const SkPaint& font, int count, const SkRect* bounds = NULL);
168
169private:
fmalita3c196de2014-09-20 05:40:22 -0700170 void reserve(size_t size);
fmalita00d5c2c2014-08-21 08:53:26 -0700171 void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
172 int count, SkPoint offset, const SkRect* bounds);
fmalita3c196de2014-09-20 05:40:22 -0700173 bool mergeRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
174 int count, SkPoint offset);
fmalita00d5c2c2014-08-21 08:53:26 -0700175 void updateDeferredBounds();
176
fmalita3dc40ac2015-01-28 10:56:06 -0800177 static SkRect ConservativeRunBounds(const SkTextBlob::RunRecord&);
178 static SkRect TightRunBounds(const SkTextBlob::RunRecord&);
179
fmalita3c196de2014-09-20 05:40:22 -0700180 SkAutoTMalloc<uint8_t> fStorage;
181 size_t fStorageSize;
182 size_t fStorageUsed;
fmalita00d5c2c2014-08-21 08:53:26 -0700183
fmalita3c196de2014-09-20 05:40:22 -0700184 SkRect fBounds;
185 int fRunCount;
186 bool fDeferredBounds;
187 size_t fLastRun; // index into fStorage
fmalita00d5c2c2014-08-21 08:53:26 -0700188
fmalita3c196de2014-09-20 05:40:22 -0700189 RunBuffer fCurrentRunBuffer;
fmalita00d5c2c2014-08-21 08:53:26 -0700190};
191
192#endif // SkTextBlob_DEFINED