Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkTextBlobPriv.h
Go to the documentation of this file.
1/*
2 * Copyright 2018 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 SkTextBlobPriv_DEFINED
9#define SkTextBlobPriv_DEFINED
10
12#include "include/core/SkFont.h"
19#include "src/base/SkSafeMath.h"
21
22class SkReadBuffer;
23class SkWriteBuffer;
24
26public:
27 /**
28 * Serialize to a buffer.
29 */
30 static void Flatten(const SkTextBlob& , SkWriteBuffer&);
31
32 /**
33 * Recreate an SkTextBlob that was serialized into a buffer.
34 *
35 * @param SkReadBuffer Serialized blob data.
36 * @return A new SkTextBlob representing the serialized data, or NULL if the buffer is
37 * invalid.
38 */
40
41 static bool HasRSXForm(const SkTextBlob& blob);
42};
43
44//
45// Textblob data is laid out into externally-managed storage as follows:
46//
47// -----------------------------------------------------------------------------
48// | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ...
49// -----------------------------------------------------------------------------
50//
51// Each run record describes a text blob run, and can be used to determine the (implicit)
52// location of the following record.
53//
54// Extended Textblob runs have more data after the Pos[] array:
55//
56// -------------------------------------------------------------------------
57// ... | RunRecord | Glyphs[] | Pos[] | TextSize | Clusters[] | Text[] | ...
58// -------------------------------------------------------------------------
59//
60// To determine the length of the extended run data, the TextSize must be read.
61//
62// Extended Textblob runs may be mixed with non-extended runs.
63
64SkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;)
65
66class SkTextBlob::RunRecord {
67public:
68 RunRecord(uint32_t count, uint32_t textSize, const SkPoint& offset, const SkFont& font, GlyphPositioning pos)
69 : fFont(font)
70 , fCount(count)
71 , fOffset(offset)
72 , fFlags(pos) {
73 SkASSERT(static_cast<unsigned>(pos) <= Flags::kPositioning_Mask);
74
75 SkDEBUGCODE(fMagic = kRunRecordMagic);
76 if (textSize > 0) {
77 fFlags |= kExtended_Flag;
78 *this->textSizePtr() = textSize;
79 }
80 }
81
82 uint32_t glyphCount() const {
83 return fCount;
84 }
85
86 const SkPoint& offset() const {
87 return fOffset;
88 }
89
90 const SkFont& font() const {
91 return fFont;
92 }
93
94 GlyphPositioning positioning() const {
95 return static_cast<GlyphPositioning>(fFlags & kPositioning_Mask);
96 }
97
98 uint16_t* glyphBuffer() const {
99 static_assert(SkIsAlignPtr(sizeof(RunRecord)), "");
100 // Glyphs are stored immediately following the record.
101 return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1);
102 }
103
104 // can be aliased with pointBuffer() or xformBuffer()
105 SkScalar* posBuffer() const {
106 // Position scalars follow the (aligned) glyph buffer.
107 return reinterpret_cast<SkScalar*>(reinterpret_cast<uint8_t*>(this->glyphBuffer()) +
108 SkAlign4(fCount * sizeof(uint16_t)));
109 }
110
111 // alias for posBuffer()
112 SkPoint* pointBuffer() const {
113 SkASSERT(this->positioning() == (GlyphPositioning)2);
114 return reinterpret_cast<SkPoint*>(this->posBuffer());
115 }
116
117 // alias for posBuffer()
118 SkRSXform* xformBuffer() const {
119 SkASSERT(this->positioning() == (GlyphPositioning)3);
120 return reinterpret_cast<SkRSXform*>(this->posBuffer());
121 }
122
123 uint32_t textSize() const { return isExtended() ? *this->textSizePtr() : 0; }
124
125 uint32_t* clusterBuffer() const {
126 // clusters follow the textSize.
127 return isExtended() ? 1 + this->textSizePtr() : nullptr;
128 }
129
130 char* textBuffer() const {
131 return isExtended()
132 ? reinterpret_cast<char*>(this->clusterBuffer() + fCount)
133 : nullptr;
134 }
135
136 bool isLastRun() const { return SkToBool(fFlags & kLast_Flag); }
137
138 static size_t StorageSize(uint32_t glyphCount, uint32_t textSize,
140 SkSafeMath* safe);
141
142 static const RunRecord* First(const SkTextBlob* blob);
143
144 static const RunRecord* Next(const RunRecord* run);
145
146 void validate(const uint8_t* storageTop) const;
147
148private:
149 friend class SkTextBlobBuilder;
150
151 enum Flags {
152 kPositioning_Mask = 0x03, // bits 0-1 reserved for positioning
153 kLast_Flag = 0x04, // set for the last blob run
154 kExtended_Flag = 0x08, // set for runs with text/cluster info
155 };
156
157 static const RunRecord* NextUnchecked(const RunRecord* run);
158
159 static size_t PosCount(uint32_t glyphCount,
161 SkSafeMath* safe);
162
163 uint32_t* textSizePtr() const;
164
165 void grow(uint32_t count);
166
167 bool isExtended() const {
168 return fFlags & kExtended_Flag;
169 }
170
171 SkFont fFont;
172 uint32_t fCount;
173 SkPoint fOffset;
174 uint32_t fFlags;
175
176 SkDEBUGCODE(unsigned fMagic;)
177};
178
179/**
180 * Iterate through all of the text runs of the text blob. For example:
181 * for (SkTextBlobRunIterator it(blob); !it.done(); it.next()) {
182 * .....
183 * }
184 */
186public:
188
189 enum GlyphPositioning : uint8_t {
190 kDefault_Positioning = 0, // Default glyph advances -- zero scalars per glyph.
191 kHorizontal_Positioning = 1, // Horizontal positioning -- one scalar per glyph.
192 kFull_Positioning = 2, // Point positioning -- two scalars per glyph.
193 kRSXform_Positioning = 3, // RSXform positioning -- four scalars per glyph.
194 };
195
196 bool done() const {
197 return !fCurrentRun;
198 }
199 void next();
200
201 uint32_t glyphCount() const {
202 SkASSERT(!this->done());
203 return fCurrentRun->glyphCount();
204 }
205 const uint16_t* glyphs() const {
206 SkASSERT(!this->done());
207 return fCurrentRun->glyphBuffer();
208 }
209 const SkScalar* pos() const {
210 SkASSERT(!this->done());
211 return fCurrentRun->posBuffer();
212 }
213 // alias for pos()
214 const SkPoint* points() const {
215 return fCurrentRun->pointBuffer();
216 }
217 // alias for pos()
218 const SkRSXform* xforms() const {
219 return fCurrentRun->xformBuffer();
220 }
221 const SkPoint& offset() const {
222 SkASSERT(!this->done());
223 return fCurrentRun->offset();
224 }
225 const SkFont& font() const {
226 SkASSERT(!this->done());
227 return fCurrentRun->font();
228 }
229 GlyphPositioning positioning() const;
230 unsigned scalarsPerGlyph() const;
231 uint32_t* clusters() const {
232 SkASSERT(!this->done());
233 return fCurrentRun->clusterBuffer();
234 }
235 uint32_t textSize() const {
236 SkASSERT(!this->done());
237 return fCurrentRun->textSize();
238 }
239 char* text() const {
240 SkASSERT(!this->done());
241 return fCurrentRun->textBuffer();
242 }
243
244 bool isLCD() const;
245
246private:
247 const SkTextBlob::RunRecord* fCurrentRun;
248
249 SkDEBUGCODE(const uint8_t* fStorageTop;)
250};
251
252#endif // SkTextBlobPriv_DEFINED
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
Definition DM.cpp:263
int count
SkPoint pos
static float next(float f)
uint16_t fFlags
#define SK_SPI
Definition SkAPI.h:41
static constexpr bool SkIsAlignPtr(T x)
Definition SkAlign.h:26
static constexpr T SkAlign4(T x)
Definition SkAlign.h:16
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
static bool isLCD(const SkScalerContextRec &rec)
@ kHorizontal_Positioning
@ kDefault_Positioning
@ kRSXform_Positioning
@ kFull_Positioning
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
static void Flatten(const SkTextBlob &, SkWriteBuffer &)
static sk_sp< SkTextBlob > MakeFromBuffer(SkReadBuffer &)
static bool HasRSXForm(const SkTextBlob &blob)
uint32_t * clusters() const
const SkPoint * points() const
const SkPoint & offset() const
const SkRSXform * xforms() const
const SkScalar * pos() const
const uint16_t * glyphs() const
uint32_t glyphCount() const
uint32_t textSize() const
const SkFont & font() const
float SkScalar
Definition extension.cpp:12
font
Font Metadata and Metrics.
Definition run.py:1
Point offset