Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/core/SkTextBlobPriv.h
Line
Count
Source
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:
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
483k
            , fFlags(pos) {
71
483k
        SkASSERT(static_cast<unsigned>(pos) <= Flags::kPositioning_Mask);
72
73
483k
        SkDEBUGCODE(fMagic = kRunRecordMagic);
74
483k
        if (textSize > 0) {
75
156
            fFlags |= kExtended_Flag;
76
156
            *this->textSizePtr() = textSize;
77
156
        }
78
483k
    }
79
80
8.03M
    uint32_t glyphCount() const {
81
8.03M
        return fCount;
82
8.03M
    }
83
84
995k
    const SkPoint& offset() const {
85
995k
        return fOffset;
86
995k
    }
87
88
2.22M
    const SkFont& font() const {
89
2.22M
        return fFont;
90
2.22M
    }
91
92
2.77M
    GlyphPositioning positioning() const {
93
2.77M
        return static_cast<GlyphPositioning>(fFlags & kPositioning_Mask);
94
2.77M
    }
95
96
3.22M
    uint16_t* glyphBuffer() const {
97
3.22M
        static_assert(SkIsAlignPtr(sizeof(RunRecord)), "");
98
        // Glyphs are stored immediately following the record.
99
3.22M
        return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1);
100
3.22M
    }
101
102
    // can be aliased with pointBuffer() or xformBuffer()
103
1.37M
    SkScalar* posBuffer() const {
104
        // Position scalars follow the (aligned) glyph buffer.
105
1.37M
        return reinterpret_cast<SkScalar*>(reinterpret_cast<uint8_t*>(this->glyphBuffer()) +
106
1.37M
                                           SkAlign4(fCount * sizeof(uint16_t)));
107
1.37M
    }
108
109
    // alias for posBuffer()
110
13.6k
    SkPoint* pointBuffer() const {
111
13.6k
        SkASSERT(this->positioning() == (GlyphPositioning)2);
112
13.6k
        return reinterpret_cast<SkPoint*>(this->posBuffer());
113
13.6k
    }
114
115
    // alias for posBuffer()
116
854k
    SkRSXform* xformBuffer() const {
117
854k
        SkASSERT(this->positioning() == (GlyphPositioning)3);
118
854k
        return reinterpret_cast<SkRSXform*>(this->posBuffer());
119
854k
    }
120
121
526k
    uint32_t textSize() const { return isExtended() ? *this->textSizePtr() : 0; }
122
123
888k
    uint32_t* clusterBuffer() const {
124
        // clusters follow the textSize.
125
887k
        return isExtended() ? 1 + this->textSizePtr() : nullptr;
126
888k
    }
127
128
888k
    char* textBuffer() const {
129
888k
        return isExtended()
130
226
               ? reinterpret_cast<char*>(this->clusterBuffer() + fCount)
131
887k
               : nullptr;
132
888k
    }
133
134
430k
    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
165
2.78M
    bool isExtended() const {
166
2.78M
        return fFlags & kExtended_Flag;
167
2.78M
    }
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 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
194
2.55M
    bool done() const {
195
2.55M
        return !fCurrentRun;
196
2.55M
    }
197
    void next();
198
199
1.24M
    uint32_t glyphCount() const {
200
1.24M
        SkASSERT(!this->done());
201
1.24M
        return fCurrentRun->glyphCount();
202
1.24M
    }
203
458k
    const uint16_t* glyphs() const {
204
458k
        SkASSERT(!this->done());
205
458k
        return fCurrentRun->glyphBuffer();
206
458k
    }
207
1.17k
    const SkScalar* pos() const {
208
1.17k
        SkASSERT(!this->done());
209
1.17k
        return fCurrentRun->posBuffer();
210
1.17k
    }
211
    // alias for pos()
212
6.73k
    const SkPoint* points() const {
213
6.73k
        return fCurrentRun->pointBuffer();
214
6.73k
    }
215
    // alias for pos()
216
438k
    const SkRSXform* xforms() const {
217
438k
        return fCurrentRun->xformBuffer();
218
438k
    }
219
47.4k
    const SkPoint& offset() const {
220
47.4k
        SkASSERT(!this->done());
221
47.4k
        return fCurrentRun->offset();
222
47.4k
    }
223
864k
    const SkFont& font() const {
224
864k
        SkASSERT(!this->done());
225
864k
        return fCurrentRun->font();
226
864k
    }
227
    GlyphPositioning positioning() const;
228
    unsigned scalarsPerGlyph() const;
229
404k
    uint32_t* clusters() const {
230
404k
        SkASSERT(!this->done());
231
404k
        return fCurrentRun->clusterBuffer();
232
404k
    }
233
404k
    uint32_t textSize() const {
234
404k
        SkASSERT(!this->done());
235
404k
        return fCurrentRun->textSize();
236
404k
    }
237
404k
    char* text() const {
238
404k
        SkASSERT(!this->done());
239
404k
        return fCurrentRun->textBuffer();
240
404k
    }
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