Coverage Report

Created: 2024-05-20 07:14

/src/skia/tools/fonts/RandomScalerContext.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2015 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
#include "tools/fonts/RandomScalerContext.h"
9
10
#include "include/core/SkBitmap.h"
11
#include "include/core/SkCanvas.h"
12
#include "include/core/SkDrawable.h"
13
#include "include/core/SkPath.h"
14
#include "include/core/SkStream.h"
15
#include "src/core/SkAdvancedTypefaceMetrics.h"
16
#include "src/core/SkGlyph.h"
17
#include "src/core/SkRectPriv.h"
18
#include "src/core/SkTHash.h"
19
20
using namespace skia_private;
21
22
class SkDescriptor;
23
24
class RandomScalerContext : public SkScalerContext {
25
public:
26
    RandomScalerContext(sk_sp<SkRandomTypeface>,
27
                        const SkScalerContextEffects&,
28
                        const SkDescriptor*,
29
                        bool fFakeIt);
30
31
protected:
32
    GlyphMetrics generateMetrics(const SkGlyph&, SkArenaAlloc*) override;
33
    void     generateImage(const SkGlyph&, void*) override;
34
    bool     generatePath(const SkGlyph&, SkPath*) override;
35
    sk_sp<SkDrawable> generateDrawable(const SkGlyph&) override;
36
    void     generateFontMetrics(SkFontMetrics*) override;
37
38
private:
39
0
    SkRandomTypeface* getRandomTypeface() const {
40
0
        return static_cast<SkRandomTypeface*>(this->getTypeface());
41
0
    }
42
    std::unique_ptr<SkScalerContext>   fProxy;
43
    // Many of the SkGlyphs returned are the same as those created by the fProxy.
44
    // When they are not, the originals are kept here.
45
    THashMap<SkPackedGlyphID, SkGlyph> fProxyGlyphs;
46
    bool                               fFakeIt;
47
};
48
49
RandomScalerContext::RandomScalerContext(sk_sp<SkRandomTypeface>       face,
50
                                         const SkScalerContextEffects& effects,
51
                                         const SkDescriptor*           desc,
52
                                         bool                          fakeIt)
53
        : SkScalerContext(std::move(face), effects, desc)
54
        , fProxy(getRandomTypeface()->proxy()->createScalerContext(SkScalerContextEffects(), desc))
55
0
        , fFakeIt(fakeIt) {
56
0
    fProxy->forceGenerateImageFromPath();
57
0
}
58
59
SkScalerContext::GlyphMetrics RandomScalerContext::generateMetrics(const SkGlyph& origGlyph,
60
0
                                                                   SkArenaAlloc* alloc) {
61
    // Here we will change the mask format of the glyph
62
    // NOTE: this may be overridden by the base class (e.g. if a mask filter is applied).
63
0
    SkMask::Format format = SkMask::kA8_Format;
64
0
    switch (origGlyph.getGlyphID() % 4) {
65
0
        case 0: format = SkMask::kLCD16_Format; break;
66
0
        case 1: format = SkMask::kA8_Format; break;
67
0
        case 2: format = SkMask::kARGB32_Format; break;
68
0
        case 3: format = SkMask::kBW_Format; break;
69
0
    }
70
71
0
    auto glyph = fProxy->internalMakeGlyph(origGlyph.getPackedID(), format, alloc);
72
73
0
    GlyphMetrics mx(SkMask::kA8_Format);
74
0
    mx.advance = glyph.advanceVector();
75
0
    mx.bounds = glyph.rect();
76
0
    mx.maskFormat = glyph.maskFormat();
77
0
    mx.extraBits = glyph.extraBits();
78
79
0
    if (fFakeIt || (glyph.getGlyphID() % 4) != 2) {
80
0
        mx.neverRequestPath = glyph.setPathHasBeenCalled() && !glyph.path();
81
0
        mx.computeFromPath = !mx.neverRequestPath;
82
0
        return mx;
83
0
    }
84
85
0
    fProxy->getPath(glyph, alloc);
86
0
    if (!glyph.path()) {
87
0
        mx.neverRequestPath = true;
88
0
        return mx;
89
0
    }
90
91
    // The proxy glyph has a path, but this glyph does not.
92
    // Stash the proxy glyph so it can be used later.
93
0
    const auto packedID = glyph.getPackedID();
94
0
    const SkGlyph* proxyGlyph = fProxyGlyphs.set(packedID, std::move(glyph));
95
0
    const SkPath& proxyPath = *proxyGlyph->path();
96
97
0
    mx.neverRequestPath = true;
98
0
    mx.maskFormat = SkMask::kARGB32_Format;
99
0
    mx.advance = proxyGlyph->advanceVector();
100
0
    mx.extraBits = proxyGlyph->extraBits();
101
102
0
    SkRect         storage;
103
0
    const SkPaint& paint = this->getRandomTypeface()->paint();
104
0
    const SkRect&  newBounds =
105
0
            paint.doComputeFastBounds(proxyPath.getBounds(), &storage, SkPaint::kFill_Style);
106
0
    newBounds.roundOut(&mx.bounds);
107
108
0
    return mx;
109
0
}
110
111
0
void RandomScalerContext::generateImage(const SkGlyph& glyph, void* imageBuffer) {
112
0
    if (fFakeIt) {
113
0
        sk_bzero(imageBuffer, glyph.imageSize());
114
0
        return;
115
0
    }
116
117
0
    SkGlyph* proxyGlyph = fProxyGlyphs.find(glyph.getPackedID());
118
0
    if (!proxyGlyph || !proxyGlyph->path()) {
119
0
        fProxy->getImage(glyph);
120
0
        return;
121
0
    }
122
0
    const SkPath& path = *proxyGlyph->path();
123
0
    const bool hairline = proxyGlyph->pathIsHairline();
124
125
0
    SkBitmap bm;
126
0
    bm.installPixels(SkImageInfo::MakeN32Premul(glyph.width(), glyph.height()),
127
0
                     imageBuffer, glyph.rowBytes());
128
0
    bm.eraseColor(0);
129
130
0
    SkCanvas canvas(bm);
131
0
    canvas.translate(-SkIntToScalar(glyph.left()), -SkIntToScalar(glyph.top()));
132
0
    SkPaint paint = this->getRandomTypeface()->paint();
133
0
    if (hairline) {
134
        // We have a device path with effects already applied which is normally a fill path.
135
        // However here we do not have a fill path and there is no area to fill.
136
0
        paint.setStyle(SkPaint::kStroke_Style);
137
0
        paint.setStroke(0);
138
0
    }
139
0
    canvas.drawPath(path, paint); //Need to modify the paint if the devPath is hairline
140
0
}
141
142
0
bool RandomScalerContext::generatePath(const SkGlyph& glyph, SkPath* path) {
143
0
    SkGlyph* shadowProxyGlyph = fProxyGlyphs.find(glyph.getPackedID());
144
0
    if (shadowProxyGlyph && shadowProxyGlyph->path()) {
145
0
        path->reset();
146
0
        return false;
147
0
    }
148
0
    return fProxy->generatePath(glyph, path);
149
0
}
150
151
0
sk_sp<SkDrawable> RandomScalerContext::generateDrawable(const SkGlyph& glyph) {
152
0
    SkGlyph* shadowProxyGlyph = fProxyGlyphs.find(glyph.getPackedID());
153
0
    if (shadowProxyGlyph && shadowProxyGlyph->path()) {
154
0
        return nullptr;
155
0
    }
156
0
    return fProxy->generateDrawable(glyph);
157
0
}
158
159
0
void RandomScalerContext::generateFontMetrics(SkFontMetrics* metrics) {
160
0
    fProxy->getFontMetrics(metrics);
161
0
}
162
163
///////////////////////////////////////////////////////////////////////////////
164
165
SkRandomTypeface::SkRandomTypeface(sk_sp<SkTypeface> proxy, const SkPaint& paint, bool fakeIt)
166
        : SkTypeface(proxy->fontStyle(), false)
167
        , fProxy(std::move(proxy))
168
        , fPaint(paint)
169
0
        , fFakeIt(fakeIt) {}
170
171
std::unique_ptr<SkScalerContext> SkRandomTypeface::onCreateScalerContext(
172
    const SkScalerContextEffects& effects, const SkDescriptor* desc) const
173
0
{
174
0
    return std::make_unique<RandomScalerContext>(
175
0
            sk_ref_sp(const_cast<SkRandomTypeface*>(this)), effects, desc, fFakeIt);
176
0
}
177
178
0
void SkRandomTypeface::onFilterRec(SkScalerContextRec* rec) const {
179
0
    fProxy->filterRec(rec);
180
0
    rec->setHinting(SkFontHinting::kNone);
181
0
    rec->fMaskFormat = SkMask::kARGB32_Format;
182
0
}
183
184
0
void SkRandomTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
185
0
    fProxy->getGlyphToUnicodeMap(glyphToUnicode);
186
0
}
187
188
0
std::unique_ptr<SkAdvancedTypefaceMetrics> SkRandomTypeface::onGetAdvancedMetrics() const {
189
0
    return fProxy->getAdvancedMetrics();
190
0
}
191
192
0
std::unique_ptr<SkStreamAsset> SkRandomTypeface::onOpenStream(int* ttcIndex) const {
193
0
    return fProxy->openStream(ttcIndex);
194
0
}
195
196
0
sk_sp<SkTypeface> SkRandomTypeface::onMakeClone(const SkFontArguments& args) const {
197
0
    sk_sp<SkTypeface> proxy = fProxy->makeClone(args);
198
0
    if (!proxy) {
199
0
        return nullptr;
200
0
    }
201
0
    return sk_make_sp<SkRandomTypeface>(proxy, fPaint, fFakeIt);
202
0
}
203
204
0
void SkRandomTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
205
    // TODO: anything that uses this typeface isn't correctly serializable, since this typeface
206
    // cannot be deserialized.
207
0
    fProxy->getFontDescriptor(desc, isLocal);
208
0
}
209
210
0
void SkRandomTypeface::onCharsToGlyphs(const SkUnichar* uni, int count, SkGlyphID glyphs[]) const {
211
0
    fProxy->unicharsToGlyphs(uni, count, glyphs);
212
0
}
213
214
0
int SkRandomTypeface::onCountGlyphs() const { return fProxy->countGlyphs(); }
215
216
0
int SkRandomTypeface::onGetUPEM() const { return fProxy->getUnitsPerEm(); }
217
218
0
void SkRandomTypeface::onGetFamilyName(SkString* familyName) const {
219
0
    fProxy->getFamilyName(familyName);
220
0
}
221
222
0
bool SkRandomTypeface::onGetPostScriptName(SkString* postScriptName) const {
223
0
    return fProxy->getPostScriptName(postScriptName);
224
0
}
225
226
0
SkTypeface::LocalizedStrings* SkRandomTypeface::onCreateFamilyNameIterator() const {
227
0
    return fProxy->createFamilyNameIterator();
228
0
}
229
230
0
void SkRandomTypeface::getPostScriptGlyphNames(SkString* names) const {
231
0
    return fProxy->getPostScriptGlyphNames(names);
232
0
}
233
234
0
bool SkRandomTypeface::onGlyphMaskNeedsCurrentColor() const {
235
0
    return fProxy->glyphMaskNeedsCurrentColor();
236
0
}
237
238
int SkRandomTypeface::onGetVariationDesignPosition(
239
        SkFontArguments::VariationPosition::Coordinate coordinates[],
240
0
        int                                            coordinateCount) const {
241
0
    return fProxy->onGetVariationDesignPosition(coordinates, coordinateCount);
242
0
}
243
244
int SkRandomTypeface::onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
245
0
                                                     int parameterCount) const {
246
0
    return fProxy->onGetVariationDesignParameters(parameters, parameterCount);
247
0
}
248
249
0
int SkRandomTypeface::onGetTableTags(SkFontTableTag tags[]) const {
250
0
    return fProxy->getTableTags(tags);
251
0
}
252
253
size_t SkRandomTypeface::onGetTableData(SkFontTableTag tag,
254
                                        size_t         offset,
255
                                        size_t         length,
256
0
                                        void*          data) const {
257
0
    return fProxy->getTableData(tag, offset, length, data);
258
0
}