Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / core / SkScalerCache.cpp
1 /*
2  * Copyright 2006 The Android Open Source Project
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 "src/core/SkScalerCache.h"
9
10 #include "include/core/SkDrawable.h"
11 #include "include/core/SkGraphics.h"
12 #include "include/core/SkPath.h"
13 #include "include/core/SkTypeface.h"
14 #include "src/core/SkEnumerate.h"
15 #include "src/core/SkScalerContext.h"
16
17 static SkFontMetrics use_or_generate_metrics(
18         const SkFontMetrics* metrics, SkScalerContext* context) {
19     SkFontMetrics answer;
20     if (metrics) {
21         answer = *metrics;
22     } else {
23         context->getFontMetrics(&answer);
24     }
25     return answer;
26 }
27
28 SkScalerCache::SkScalerCache(
29     std::unique_ptr<SkScalerContext> scaler,
30     const SkFontMetrics* fontMetrics)
31         : fScalerContext{std::move(scaler)}
32         , fFontMetrics{use_or_generate_metrics(fontMetrics, fScalerContext.get())}
33         , fRoundingSpec{fScalerContext->isSubpixel(),
34                         fScalerContext->computeAxisAlignmentForHText()} {
35     SkASSERT(fScalerContext != nullptr);
36 }
37
38 std::tuple<SkGlyph*, size_t> SkScalerCache::glyph(SkPackedGlyphID packedGlyphID) {
39     auto [digest, size] = this->digest(packedGlyphID);
40     return {fGlyphForIndex[digest.index()], size};
41 }
42
43 std::tuple<SkGlyphDigest, size_t> SkScalerCache::digest(SkPackedGlyphID packedGlyphID) {
44     SkGlyphDigest* digest = fDigestForPackedGlyphID.find(packedGlyphID);
45
46     if (digest != nullptr) {
47         return {*digest, 0};
48     }
49
50     SkGlyph* glyph = fAlloc.make<SkGlyph>(fScalerContext->makeGlyph(packedGlyphID, &fAlloc));
51     return {this->addGlyph(glyph), sizeof(SkGlyph)};
52 }
53
54 SkGlyphDigest SkScalerCache::addGlyph(SkGlyph* glyph) {
55     size_t index = fGlyphForIndex.size();
56     SkGlyphDigest digest = SkGlyphDigest{index, *glyph};
57     fDigestForPackedGlyphID.set(glyph->getPackedID(), digest);
58     fGlyphForIndex.push_back(glyph);
59     return digest;
60 }
61
62 size_t SkScalerCache::preparePath(SkGlyph* glyph) {
63     size_t delta = 0;
64     if (glyph->setPath(&fAlloc, fScalerContext.get())) {
65         delta = glyph->path()->approximateBytesUsed();
66     }
67     return delta;
68 }
69
70 std::tuple<const SkPath*, size_t> SkScalerCache::mergePath(
71         SkGlyph* glyph, const SkPath* path, bool hairline) {
72     SkAutoMutexExclusive lock{fMu};
73     size_t pathDelta = 0;
74     if (glyph->setPathHasBeenCalled()) {
75         SkDEBUGFAIL("Re-adding path to existing glyph. This should not happen.");
76     }
77     if (glyph->setPath(&fAlloc, path, hairline)) {
78         pathDelta = glyph->path()->approximateBytesUsed();
79     }
80     return {glyph->path(), pathDelta};
81 }
82
83 size_t SkScalerCache::prepareDrawable(SkGlyph* glyph) {
84     size_t delta = 0;
85     if (glyph->setDrawable(&fAlloc, fScalerContext.get())) {
86         delta = glyph->drawable()->approximateBytesUsed();
87         SkASSERT(delta > 0);
88     }
89     return delta;
90 }
91
92 std::tuple<SkDrawable*, size_t> SkScalerCache::mergeDrawable(SkGlyph* glyph,
93                                                              sk_sp<SkDrawable> drawable) {
94     SkAutoMutexExclusive lock{fMu};
95     size_t delta = 0;
96     if (glyph->setDrawableHasBeenCalled()) {
97         SkDEBUGFAIL("Re-adding drawable to existing glyph. This should not happen.");
98     }
99     if (glyph->setDrawable(&fAlloc, std::move(drawable))) {
100         delta = glyph->drawable()->approximateBytesUsed();
101         SkASSERT(delta > 0);
102     }
103     return {glyph->drawable(), delta};
104 }
105
106 int SkScalerCache::countCachedGlyphs() const {
107     SkAutoMutexExclusive lock(fMu);
108     return fDigestForPackedGlyphID.count();
109 }
110
111 std::tuple<SkSpan<const SkGlyph*>, size_t> SkScalerCache::internalPrepare(
112         SkSpan<const SkGlyphID> glyphIDs, PathDetail pathDetail, const SkGlyph** results) {
113     const SkGlyph** cursor = results;
114     size_t delta = 0;
115     for (auto glyphID : glyphIDs) {
116         auto [glyph, size] = this->glyph(SkPackedGlyphID{glyphID});
117         delta += size;
118         if (pathDetail == kMetricsAndPath) {
119             size_t pathSize = this->preparePath(glyph);
120             delta += pathSize;
121         }
122         *cursor++ = glyph;
123     }
124
125     return {{results, glyphIDs.size()}, delta};
126 }
127
128 std::tuple<const void*, size_t> SkScalerCache::prepareImage(SkGlyph* glyph) {
129     size_t delta = 0;
130     if (glyph->setImage(&fAlloc, fScalerContext.get())) {
131         delta = glyph->imageSize();
132     }
133     return {glyph->image(), delta};
134 }
135
136 std::tuple<SkGlyph*, size_t> SkScalerCache::mergeGlyphAndImage(
137         SkPackedGlyphID toID, const SkGlyph& from) {
138     SkAutoMutexExclusive lock{fMu};
139     // TODO(herb): remove finding the glyph when setting the metrics and image are separated
140     SkGlyphDigest* digest = fDigestForPackedGlyphID.find(toID);
141     if (digest != nullptr) {
142         SkGlyph* to = fGlyphForIndex[digest->index()];
143         size_t delta = 0;
144         if (from.setImageHasBeenCalled()) {
145             if (to->setImageHasBeenCalled()) {
146                 // Should never set an image on a glyph which already has an image.
147                 SkDEBUGFAIL("Re-adding image to existing glyph. This should not happen.");
148             }
149             // TODO: assert that any metrics on `from` are the same.
150             delta = to->setMetricsAndImage(&fAlloc, from);
151         }
152         return {to, delta};
153     } else {
154         SkGlyph* glyph = fAlloc.make<SkGlyph>(toID);
155         size_t delta = glyph->setMetricsAndImage(&fAlloc, from);
156         (void)this->addGlyph(glyph);
157         return {glyph, sizeof(SkGlyph) + delta};
158     }
159 }
160
161 std::tuple<SkSpan<const SkGlyph*>, size_t> SkScalerCache::metrics(
162         SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) {
163     SkAutoMutexExclusive lock{fMu};
164     auto [glyphs, delta] = this->internalPrepare(glyphIDs, kMetricsOnly, results);
165     return {glyphs, delta};
166 }
167
168 std::tuple<SkSpan<const SkGlyph*>, size_t> SkScalerCache::preparePaths(
169         SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) {
170     SkAutoMutexExclusive lock{fMu};
171     auto [glyphs, delta] = this->internalPrepare(glyphIDs, kMetricsAndPath, results);
172     return {glyphs, delta};
173 }
174
175 std::tuple<SkSpan<const SkGlyph*>, size_t> SkScalerCache::prepareImages(
176         SkSpan<const SkPackedGlyphID> glyphIDs, const SkGlyph* results[]) {
177     const SkGlyph** cursor = results;
178     SkAutoMutexExclusive lock{fMu};
179     size_t delta = 0;
180     for (auto glyphID : glyphIDs) {
181         auto[glyph, glyphSize] = this->glyph(glyphID);
182         auto[_, imageSize] = this->prepareImage(glyph);
183         delta += glyphSize + imageSize;
184         *cursor++ = glyph;
185     }
186
187     return {{results, glyphIDs.size()}, delta};
188 }
189
190 std::tuple<SkSpan<const SkGlyph*>, size_t> SkScalerCache::prepareDrawables(
191         SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) {
192     const SkGlyph** cursor = results;
193     SkAutoMutexExclusive lock{fMu};
194     size_t delta = 0;
195     for (auto glyphID : glyphIDs) {
196         auto[glyph, glyphSize] = this->glyph(SkPackedGlyphID{glyphID});
197         size_t drawableSize = this->prepareDrawable(glyph);
198         delta += glyphSize + drawableSize;
199         *cursor++ = glyph;
200     }
201
202     return {{results, glyphIDs.size()}, delta};
203 }
204
205 template <typename Fn>
206 size_t SkScalerCache::commonFilterLoop(SkDrawableGlyphBuffer* accepted, Fn&& fn) {
207     size_t total = 0;
208     for (auto [i, packedID, pos] : SkMakeEnumerate(accepted->input())) {
209         if (SkScalarsAreFinite(pos.x(), pos.y())) {
210             auto [digest, size] = this->digest(packedID);
211             total += size;
212             if (!digest.isEmpty()) {
213                 fn(i, digest, pos);
214             }
215         }
216     }
217     return total;
218 }
219
220 size_t SkScalerCache::prepareForDrawingMasksCPU(SkDrawableGlyphBuffer* accepted) {
221     SkAutoMutexExclusive lock{fMu};
222     size_t imageDelta = 0;
223     size_t delta = this->commonFilterLoop(accepted,
224         [&](size_t i, SkGlyphDigest digest, SkPoint pos) SK_REQUIRES(fMu) {
225             // If the glyph is too large, then no image is created.
226             SkGlyph* glyph = fGlyphForIndex[digest.index()];
227             auto [image, imageSize] = this->prepareImage(glyph);
228             if (image != nullptr) {
229                 accepted->accept(glyph, i);
230                 imageDelta += imageSize;
231             }
232         });
233
234     return delta + imageDelta;
235 }
236
237 // Note: this does not actually fill out the image. That happens at atlas building time.
238 size_t SkScalerCache::prepareForMaskDrawing(
239         SkDrawableGlyphBuffer* accepted, SkSourceGlyphBuffer* rejected) {
240     SkAutoMutexExclusive lock{fMu};
241     size_t delta = this->commonFilterLoop(accepted,
242         [&](size_t i, SkGlyphDigest digest, SkPoint pos) SK_REQUIRES(fMu) {
243             // N.B. this must have the same behavior as RemoteStrike::prepareForMaskDrawing.
244             if (digest.canDrawAsMask()) {
245                 accepted->accept(fGlyphForIndex[digest.index()], i);
246             } else {
247                 rejected->reject(i, digest.maxDimension());
248             }
249         });
250
251     return delta;
252 }
253
254 size_t SkScalerCache::prepareForSDFTDrawing(
255         SkDrawableGlyphBuffer* accepted, SkSourceGlyphBuffer* rejected) {
256     SkAutoMutexExclusive lock{fMu};
257     size_t delta = this->commonFilterLoop(accepted,
258         [&](size_t i, SkGlyphDigest digest, SkPoint pos) SK_REQUIRES(fMu) {
259             if (digest.canDrawAsSDFT()) {
260                 accepted->accept(fGlyphForIndex[digest.index()], i);
261             } else {
262                 // Assume whatever follows SDF doesn't care about the maximum rejected size.
263                 rejected->reject(i);
264             }
265         });
266
267     return delta;
268 }
269
270 size_t SkScalerCache::prepareForPathDrawing(
271         SkDrawableGlyphBuffer* accepted, SkSourceGlyphBuffer* rejected) {
272     SkAutoMutexExclusive lock{fMu};
273     size_t pathDelta = 0;
274     size_t delta = this->commonFilterLoop(accepted,
275         [&](size_t i, SkGlyphDigest digest, SkPoint pos) SK_REQUIRES(fMu) {
276             SkGlyph* glyph = fGlyphForIndex[digest.index()];
277             auto pathSize = this->preparePath(glyph);
278             pathDelta += pathSize;
279             if (glyph->path() != nullptr) {
280                 // Save off the path to draw later.
281                 accepted->accept(glyph, i);
282             } else {
283                 // Glyph does not have a path.
284                 rejected->reject(i, digest.maxDimension());
285             }
286         });
287
288     return delta + pathDelta;
289 }
290
291 size_t SkScalerCache::prepareForDrawableDrawing(
292         SkDrawableGlyphBuffer* accepted, SkSourceGlyphBuffer* rejected) {
293     SkAutoMutexExclusive lock{fMu};
294     size_t drawableDelta = 0;
295     size_t delta = this->commonFilterLoop(accepted,
296         [&](size_t i, SkGlyphDigest digest, SkPoint pos) SK_REQUIRES(fMu) {
297             SkGlyph* glyph = fGlyphForIndex[digest.index()];
298             size_t drawableSize = this->prepareDrawable(glyph);
299             drawableDelta += drawableSize;
300             if (glyph->drawable() != nullptr) {
301                 // Save off the drawable to draw later.
302                 accepted->accept(glyph, i);
303             } else {
304                 // Glyph does not have a drawable.
305                 rejected->reject(i, glyph->maxDimension());
306             }
307         });
308
309     return delta + drawableDelta;
310 }
311
312 void SkScalerCache::findIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos,
313         SkGlyph* glyph, SkScalar* array, int* count) {
314     SkAutoMutexExclusive lock{fMu};
315     glyph->ensureIntercepts(bounds, scale, xPos, array, count, &fAlloc);
316 }
317
318 void SkScalerCache::dump() const {
319     SkAutoMutexExclusive lock{fMu};
320     const SkTypeface* face = fScalerContext->getTypeface();
321     const SkScalerContextRec& rec = fScalerContext->getRec();
322     SkMatrix matrix;
323     rec.getSingleMatrix(&matrix);
324     matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize));
325     SkString name;
326     face->getFamilyName(&name);
327
328     SkString msg;
329     SkFontStyle style = face->fontStyle();
330     msg.printf("cache typeface:%x %25s:(%d,%d,%d)\n %s glyphs:%3d",
331                face->uniqueID(), name.c_str(), style.weight(), style.width(), style.slant(),
332                rec.dump().c_str(), fDigestForPackedGlyphID.count());
333     SkDebugf("%s\n", msg.c_str());
334 }
335