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