Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkStrike.cpp
Go to the documentation of this file.
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/SkStrike.h"
9
13#include "include/core/SkPath.h"
19#include "src/core/SkGlyph.h"
20#include "src/core/SkMask.h"
26
27#include <cctype>
28#include <new>
29#include <optional>
30#include <utility>
31
32using namespace skglyph;
33
35 const SkFontMetrics* metrics, SkScalerContext* context) {
36 SkFontMetrics answer;
37 if (metrics) {
38 answer = *metrics;
39 } else {
40 context->getFontMetrics(&answer);
41 }
42 return answer;
43}
44
46 const SkStrikeSpec& strikeSpec,
47 std::unique_ptr<SkScalerContext> scaler,
48 const SkFontMetrics* metrics,
49 std::unique_ptr<SkStrikePinner> pinner)
50 : fFontMetrics{use_or_generate_metrics(metrics, scaler.get())}
51 , fRoundingSpec{scaler->isSubpixel(),
52 scaler->computeAxisAlignmentForHText()}
53 , fStrikeSpec{strikeSpec}
54 , fStrikeCache{strikeCache}
55 , fScalerContext{std::move(scaler)}
56 , fPinner{std::move(pinner)} {
57 SkASSERT(fScalerContext != nullptr);
58}
59
61public:
62 Monitor(SkStrike* strike) SK_ACQUIRE(strike->fStrikeLock)
63 : fStrike{strike} {
64 fStrike->lock();
65 }
66
68 fStrike->unlock();
69 }
70
71private:
72 SkStrike* const fStrike;
73};
74
76 fStrikeLock.acquire();
77 fMemoryIncrease = 0;
78}
79
81 const size_t memoryIncrease = fMemoryIncrease;
82 fStrikeLock.release();
83 this->updateMemoryUsage(memoryIncrease);
84}
85
86void
88 SkSpan<SkGlyph> images,
89 SkSpan<SkGlyph> paths,
90 SkSpan<SkGlyph> drawables) {
91 SkASSERT_RELEASE(SkTFitsIn<int>(images.size()) &&
92 SkTFitsIn<int>(paths.size()) &&
93 SkTFitsIn<int>(drawables.size()));
94
95 buffer.writeInt(images.size());
96 for (SkGlyph& glyph : images) {
100 }
101
102 buffer.writeInt(paths.size());
103 for (SkGlyph& glyph : paths) {
107 }
108
109 buffer.writeInt(drawables.size());
110 for (SkGlyph& glyph : drawables) {
114 }
115}
116
118 // Read glyphs with images for the current strike.
119 const int imagesCount = buffer.readInt();
120 if (imagesCount == 0 && !buffer.isValid()) {
121 return false;
122 }
123
124 {
125 Monitor m{this};
126 for (int curImage = 0; curImage < imagesCount; ++curImage) {
127 if (!this->mergeGlyphAndImageFromBuffer(buffer)) {
128 return false;
129 }
130 }
131 }
132
133 // Read glyphs with paths for the current strike.
134 const int pathsCount = buffer.readInt();
135 if (pathsCount == 0 && !buffer.isValid()) {
136 return false;
137 }
138 {
139 Monitor m{this};
140 for (int curPath = 0; curPath < pathsCount; ++curPath) {
141 if (!this->mergeGlyphAndPathFromBuffer(buffer)) {
142 return false;
143 }
144 }
145 }
146
147 // Read glyphs with drawables for the current strike.
148 const int drawablesCount = buffer.readInt();
149 if (drawablesCount == 0 && !buffer.isValid()) {
150 return false;
151 }
152 {
153 Monitor m{this};
154 for (int curDrawable = 0; curDrawable < drawablesCount; ++curDrawable) {
155 if (!this->mergeGlyphAndDrawableFromBuffer(buffer)) {
156 return false;
157 }
158 }
159 }
160
161 return true;
162}
163
165 Monitor m{this};
166 // TODO(herb): remove finding the glyph when setting the metrics and image are separated
167 SkGlyphDigest* digest = fDigestForPackedGlyphID.find(toID);
168 if (digest != nullptr) {
169 SkGlyph* glyph = fGlyphForIndex[digest->index()];
170 if (fromGlyph.setImageHasBeenCalled()) {
172 // Should never set an image on a glyph which already has an image.
173 SkDEBUGFAIL("Re-adding image to existing glyph. This should not happen.");
174 }
175 // TODO: assert that any metrics on fromGlyph are the same.
176 fMemoryIncrease += glyph->setMetricsAndImage(&fAlloc, fromGlyph);
177 }
178 return glyph;
179 } else {
180 SkGlyph* glyph = fAlloc.make<SkGlyph>(toID);
181 fMemoryIncrease += glyph->setMetricsAndImage(&fAlloc, fromGlyph) + sizeof(SkGlyph);
182 (void)this->addGlyphAndDigest(glyph);
183 return glyph;
184 }
185}
186
187const SkPath* SkStrike::mergePath(SkGlyph* glyph, const SkPath* path, bool hairline) {
188 Monitor m{this};
190 SkDEBUGFAIL("Re-adding path to existing glyph. This should not happen.");
191 }
192 if (glyph->setPath(&fAlloc, path, hairline)) {
193 fMemoryIncrease += glyph->path()->approximateBytesUsed();
194 }
195
196 return glyph->path();
197}
198
200 Monitor m{this};
202 SkDEBUGFAIL("Re-adding drawable to existing glyph. This should not happen.");
203 }
204 if (glyph->setDrawable(&fAlloc, std::move(drawable))) {
205 fMemoryIncrease += glyph->drawable()->approximateBytesUsed();
206 SkASSERT(fMemoryIncrease > 0);
207 }
208
209 return glyph->drawable();
210}
211
213 SkGlyph* glyph, SkScalar* array, int* count) {
214 SkAutoMutexExclusive lock{fStrikeLock};
215 glyph->ensureIntercepts(bounds, scale, xPos, array, count, &fAlloc);
216}
217
219 SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) {
220 Monitor m{this};
221 return this->internalPrepare(glyphIDs, kMetricsOnly, results);
222}
223
225 SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) {
226 Monitor m{this};
227 return this->internalPrepare(glyphIDs, kMetricsAndPath, results);
228}
229
231 SkSpan<const SkPackedGlyphID> glyphIDs, const SkGlyph* results[]) {
232 const SkGlyph** cursor = results;
233 Monitor m{this};
234 for (auto glyphID : glyphIDs) {
235 SkGlyph* glyph = this->glyph(glyphID);
236 this->prepareForImage(glyph);
237 *cursor++ = glyph;
238 }
239
240 return {results, glyphIDs.size()};
241}
242
244 SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) {
245 const SkGlyph** cursor = results;
246 {
247 Monitor m{this};
248 for (auto glyphID : glyphIDs) {
249 SkGlyph* glyph = this->glyph(SkPackedGlyphID{glyphID});
250 this->prepareForDrawable(glyph);
251 *cursor++ = glyph;
252 }
253 }
254
255 return {results, glyphIDs.size()};
256}
257
259 Monitor m{this};
260 for (sktext::IDOrPath& idOrPath : idsOrPaths) {
261 SkGlyph* glyph = this->glyph(SkPackedGlyphID{idOrPath.fGlyphID});
262 this->prepareForPath(glyph);
263 new (&idOrPath.fPath) SkPath{*glyph->path()};
264 }
265}
266
268 Monitor m{this};
269 for (sktext::IDOrDrawable& idOrDrawable : idsOrDrawables) {
270 SkGlyph* glyph = this->glyph(SkPackedGlyphID{idOrDrawable.fGlyphID});
271 this->prepareForDrawable(glyph);
272 SkASSERT(glyph->drawable() != nullptr);
273 idOrDrawable.fDrawable = glyph->drawable();
274 }
275}
276
277void SkStrike::dump() const {
278 SkAutoMutexExclusive lock{fStrikeLock};
279 const SkTypeface* face = fScalerContext->getTypeface();
280 const SkScalerContextRec& rec = fScalerContext->getRec();
281 SkMatrix matrix;
282 rec.getSingleMatrix(&matrix);
283 matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize));
285 face->getFamilyName(&name);
286
287 SkString msg;
288 SkFontStyle style = face->fontStyle();
289 msg.printf("cache typeface:%x %25s:(%d,%d,%d)\n %s glyphs:%3d",
290 face->uniqueID(), name.c_str(), style.weight(), style.width(), style.slant(),
291 rec.dump().c_str(), fDigestForPackedGlyphID.count());
292 SkDebugf("%s\n", msg.c_str());
293}
294
296 SkAutoMutexExclusive lock{fStrikeLock};
297 const SkTypeface* face = fScalerContext->getTypeface();
298 const SkScalerContextRec& rec = fScalerContext->getRec();
299
300 SkString fontName;
301 face->getFamilyName(&fontName);
302 // Replace all special characters with '_'.
303 for (size_t index = 0; index < fontName.size(); ++index) {
304 if (!std::isalnum(fontName[index])) {
305 fontName[index] = '_';
306 }
307 }
308
309 SkString dumpName = SkStringPrintf("%s/%s_%u/%p",
310 SkStrikeCache::kGlyphCacheDumpName,
311 fontName.c_str(),
312 rec.fTypefaceID,
313 this);
314
315 dump->dumpNumericValue(dumpName.c_str(), "size", "bytes", fMemoryUsed);
316 dump->dumpNumericValue(dumpName.c_str(),
317 "glyph_count", "objects",
318 fDigestForPackedGlyphID.count());
319 dump->setMemoryBacking(dumpName.c_str(), "malloc", nullptr);
320}
321
323 return fGlyphForIndex[digest.index()];
324}
325
327 SkGlyphDigest digest = this->digestFor(kDirectMask, packedGlyphID);
328 return this->glyph(digest);
329}
330
331SkGlyphDigest SkStrike::digestFor(ActionType actionType, SkPackedGlyphID packedGlyphID) {
332 SkGlyphDigest* digestPtr = fDigestForPackedGlyphID.find(packedGlyphID);
333 if (digestPtr != nullptr && digestPtr->actionFor(actionType) != GlyphAction::kUnset) {
334 return *digestPtr;
335 }
336
337 SkGlyph* glyph;
338 if (digestPtr != nullptr) {
339 glyph = fGlyphForIndex[digestPtr->index()];
340 } else {
341 glyph = fAlloc.make<SkGlyph>(fScalerContext->makeGlyph(packedGlyphID, &fAlloc));
342 fMemoryIncrease += sizeof(SkGlyph);
343 digestPtr = this->addGlyphAndDigest(glyph);
344 }
345
346 digestPtr->setActionFor(actionType, glyph, this);
347
348 return *digestPtr;
349}
350
351SkGlyphDigest* SkStrike::addGlyphAndDigest(SkGlyph* glyph) {
352 size_t index = fGlyphForIndex.size();
353 SkGlyphDigest digest = SkGlyphDigest{index, *glyph};
354 SkGlyphDigest* newDigest = fDigestForPackedGlyphID.set(digest);
355 fGlyphForIndex.push_back(glyph);
356 return newDigest;
357}
358
360 if (glyph->setImage(&fAlloc, fScalerContext.get())) {
361 fMemoryIncrease += glyph->imageSize();
362 }
363 return glyph->image() != nullptr;
364}
365
367 if (glyph->setPath(&fAlloc, fScalerContext.get())) {
368 fMemoryIncrease += glyph->path()->approximateBytesUsed();
369 }
370 return glyph->path() !=nullptr;
371}
372
374 if (glyph->setDrawable(&fAlloc, fScalerContext.get())) {
375 size_t increase = glyph->drawable()->approximateBytesUsed();
376 SkASSERT(increase > 0);
377 fMemoryIncrease += increase;
378 }
379 return glyph->drawable() != nullptr;
380}
381
382SkGlyph* SkStrike::mergeGlyphFromBuffer(SkReadBuffer& buffer) {
383 SkASSERT(buffer.isValid());
384 std::optional<SkGlyph> prototypeGlyph = SkGlyph::MakeFromBuffer(buffer);
385 if (!buffer.validate(prototypeGlyph.has_value())) {
386 return nullptr;
387 }
388
389 // Check if this glyph has already been seen.
390 SkGlyphDigest* digestPtr = fDigestForPackedGlyphID.find(prototypeGlyph->getPackedID());
391 if (digestPtr != nullptr) {
392 return fGlyphForIndex[digestPtr->index()];
393 }
394
395 // This is the first time. Allocate a new glyph.
396 SkGlyph* glyph = fAlloc.make<SkGlyph>(prototypeGlyph.value());
397 fMemoryIncrease += sizeof(SkGlyph);
398 this->addGlyphAndDigest(glyph);
399 return glyph;
400}
401
402bool SkStrike::mergeGlyphAndImageFromBuffer(SkReadBuffer& buffer) {
403 SkASSERT(buffer.isValid());
404 SkGlyph* glyph = this->mergeGlyphFromBuffer(buffer);
405 if (!buffer.validate(glyph != nullptr)) {
406 return false;
407 }
408 fMemoryIncrease += glyph->addImageFromBuffer(buffer, &fAlloc);
409 return buffer.isValid();
410}
411
412bool SkStrike::mergeGlyphAndPathFromBuffer(SkReadBuffer& buffer) {
413 SkASSERT(buffer.isValid());
414 SkGlyph* glyph = this->mergeGlyphFromBuffer(buffer);
415 if (!buffer.validate(glyph != nullptr)) {
416 return false;
417 }
418 fMemoryIncrease += glyph->addPathFromBuffer(buffer, &fAlloc);
419 return buffer.isValid();
420}
421
422bool SkStrike::mergeGlyphAndDrawableFromBuffer(SkReadBuffer& buffer) {
423 SkASSERT(buffer.isValid());
424 SkGlyph* glyph = this->mergeGlyphFromBuffer(buffer);
425 if (!buffer.validate(glyph != nullptr)) {
426 return false;
427 }
428 fMemoryIncrease += glyph->addDrawableFromBuffer(buffer, &fAlloc);
429 return buffer.isValid();
430}
431
432SkSpan<const SkGlyph*> SkStrike::internalPrepare(
433 SkSpan<const SkGlyphID> glyphIDs, PathDetail pathDetail, const SkGlyph** results) {
434 const SkGlyph** cursor = results;
435 for (auto glyphID : glyphIDs) {
436 SkGlyph* glyph = this->glyph(SkPackedGlyphID{glyphID});
437 if (pathDetail == kMetricsAndPath) {
438 this->prepareForPath(glyph);
439 }
440 *cursor++ = glyph;
441 }
442
443 return {results, glyphIDs.size()};
444}
445
446void SkStrike::updateMemoryUsage(size_t increase) {
447 if (increase > 0) {
448 // fRemoved and the cache's total memory are managed under the cache's lock. This allows
449 // them to be accessed under LRU operation.
450 SkAutoMutexExclusive lock{fStrikeCache->fLock};
451 fMemoryUsed += increase;
452 if (!fRemoved) {
453 fStrikeCache->fTotalMemoryUsed += increase;
454 }
455 }
456}
int count
#define SkDEBUGFAIL(message)
Definition SkAssert.h:118
#define SkASSERT_RELEASE(cond)
Definition SkAssert.h:100
#define SkASSERT(cond)
Definition SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define SkScalarInvert(x)
Definition SkScalar.h:73
static SkFontMetrics use_or_generate_metrics(const SkFontMetrics *metrics, SkScalerContext *context)
Definition SkStrike.cpp:34
SK_API SkString static SkString SkStringPrintf()
Definition SkString.h:287
#define SK_SCOPED_CAPABILITY
#define SK_RELEASE_CAPABILITY(...)
#define SK_ACQUIRE(...)
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
size_t approximateBytesUsed()
Slant slant() const
Definition SkFontStyle.h:64
int width() const
Definition SkFontStyle.h:63
int weight() const
Definition SkFontStyle.h:62
void setActionFor(skglyph::ActionType, SkGlyph *, sktext::StrikeForGPU *)
Definition SkGlyph.cpp:634
int index() const
Definition SkGlyph.h:338
skglyph::GlyphAction actionFor(skglyph::ActionType actionType) const
Definition SkGlyph.h:343
bool setPathHasBeenCalled() const
Definition SkGlyph.h:486
size_t addPathFromBuffer(SkReadBuffer &, SkArenaAlloc *)
Definition SkGlyph.cpp:389
void ensureIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos, SkScalar *array, int *count, SkArenaAlloc *alloc)
Definition SkGlyph.cpp:547
void flattenMetrics(SkWriteBuffer &) const
Definition SkGlyph.cpp:336
bool setDrawableHasBeenCalled() const
Definition SkGlyph.h:495
size_t imageSize() const
Definition SkGlyph.cpp:241
bool setImageHasBeenCalled() const
Definition SkGlyph.h:459
size_t setMetricsAndImage(SkArenaAlloc *alloc, const SkGlyph &from)
Definition SkGlyph.cpp:207
const SkPath * path() const
Definition SkGlyph.cpp:284
SkMask::Format maskFormat() const
Definition SkGlyph.h:500
bool setDrawable(SkArenaAlloc *alloc, SkScalerContext *scalerContext)
Definition SkGlyph.cpp:310
bool setPath(SkArenaAlloc *alloc, SkScalerContext *scalerContext)
Definition SkGlyph.cpp:266
void flattenPath(SkWriteBuffer &) const
Definition SkGlyph.cpp:378
bool setImage(SkArenaAlloc *alloc, SkScalerContext *scalerContext)
Definition SkGlyph.cpp:185
void flattenDrawable(SkWriteBuffer &) const
Definition SkGlyph.cpp:414
size_t addImageFromBuffer(SkReadBuffer &, SkArenaAlloc *)
Definition SkGlyph.cpp:358
size_t addDrawableFromBuffer(SkReadBuffer &, SkArenaAlloc *)
Definition SkGlyph.cpp:425
void flattenImage(SkWriteBuffer &) const
Definition SkGlyph.cpp:349
SkDrawable * drawable() const
Definition SkGlyph.cpp:327
const void * image() const
Definition SkGlyph.h:465
static std::optional< SkGlyph > MakeFromBuffer(SkReadBuffer &)
Definition SkGlyph.cpp:95
size_t approximateBytesUsed() const
Definition SkPath.cpp:562
void getFontMetrics(SkFontMetrics *)
constexpr size_t size() const
Definition SkSpan_impl.h:95
static void FlattenGlyphsByType(SkWriteBuffer &buffer, SkSpan< SkGlyph > images, SkSpan< SkGlyph > paths, SkSpan< SkGlyph > drawables)
Definition SkStrike.cpp:87
void dump() const SK_EXCLUDES(fStrikeLock)
Definition SkStrike.cpp:277
const SkDrawable * mergeDrawable(SkGlyph *glyph, sk_sp< SkDrawable > drawable) SK_EXCLUDES(fStrikeLock)
Definition SkStrike.cpp:199
void glyphIDsToDrawables(SkSpan< sktext::IDOrDrawable > idsOrDrawables) SK_EXCLUDES(fStrikeLock)
Definition SkStrike.cpp:267
void dumpMemoryStatistics(SkTraceMemoryDump *dump) const SK_EXCLUDES(fStrikeLock)
Definition SkStrike.cpp:295
void unlock() override SK_RELEASE_CAPABILITY(fStrikeLock)
Definition SkStrike.cpp:80
bool mergeFromBuffer(SkReadBuffer &buffer) SK_EXCLUDES(fStrikeLock)
Definition SkStrike.cpp:117
~Monitor() SK_RELEASE_CAPABILITY()
Definition SkStrike.cpp:67
SkSpan< const SkGlyph * > metrics(SkSpan< const SkGlyphID > glyphIDs, const SkGlyph *results[]) SK_EXCLUDES(fStrikeLock)
Definition SkStrike.cpp:218
const SkPath * mergePath(SkGlyph *glyph, const SkPath *path, bool hairline) SK_EXCLUDES(fStrikeLock)
Definition SkStrike.cpp:187
bool prepareForPath(SkGlyph *) override SK_REQUIRES(fStrikeLock)
Definition SkStrike.cpp:366
void lock() override SK_ACQUIRE(fStrikeLock)
Definition SkStrike.cpp:75
SkStrike(SkStrikeCache *strikeCache, const SkStrikeSpec &strikeSpec, std::unique_ptr< SkScalerContext > scaler, const SkFontMetrics *metrics, std::unique_ptr< SkStrikePinner > pinner)
Definition SkStrike.cpp:45
SkSpan< const SkGlyph * > preparePaths(SkSpan< const SkGlyphID > glyphIDs, const SkGlyph *results[]) SK_EXCLUDES(fStrikeLock)
Definition SkStrike.cpp:224
void findIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos, SkGlyph *, SkScalar *array, int *count) SK_EXCLUDES(fStrikeLock)
Definition SkStrike.cpp:212
void glyphIDsToPaths(SkSpan< sktext::IDOrPath > idsOrPaths) SK_EXCLUDES(fStrikeLock)
Definition SkStrike.cpp:258
SkGlyph * mergeGlyphAndImage(SkPackedGlyphID toID, const SkGlyph &fromGlyph) SK_EXCLUDES(fStrikeLock)
Definition SkStrike.cpp:164
bool prepareForDrawable(SkGlyph *) override SK_REQUIRES(fStrikeLock)
Definition SkStrike.cpp:373
Monitor(SkStrike *strike) SK_ACQUIRE(strike -> fStrikeLock) :fStrike
Definition SkStrike.cpp:62
SkGlyph * glyph(SkGlyphDigest) SK_REQUIRES(fStrikeLock)
Definition SkStrike.cpp:322
SkSpan< const SkGlyph * > prepareDrawables(SkSpan< const SkGlyphID > glyphIDs, const SkGlyph *results[]) SK_EXCLUDES(fStrikeLock)
Definition SkStrike.cpp:243
bool prepareForImage(SkGlyph *glyph) override SK_REQUIRES(fStrikeLock)
Definition SkStrike.cpp:359
SkSpan< const SkGlyph * > prepareImages(SkSpan< const SkPackedGlyphID > glyphIDs, const SkGlyph *results[]) SK_EXCLUDES(fStrikeLock)
Definition SkStrike.cpp:230
SkGlyphDigest digestFor(skglyph::ActionType, SkPackedGlyphID) override SK_REQUIRES(fStrikeLock)
Definition SkStrike.cpp:331
void printf(const char format[],...) SK_PRINTF_LIKE(2
Definition SkString.cpp:534
size_t size() const
Definition SkString.h:131
const char * c_str() const
Definition SkString.h:133
SkTypefaceID uniqueID() const
Definition SkTypeface.h:101
void getFamilyName(SkString *name) const
SkFontStyle fontStyle() const
Definition SkTypeface.h:55
float SkScalar
Definition extension.cpp:12
static const uint8_t buffer[]
const char * name
Definition fuchsia.cc:50
std::array< MockImage, 3 > images
Definition ref_ptr.h:256
const Scalar scale
static bool IsValidFormat(uint8_t format)
Definition SkMask.h:46
void getSingleMatrix(SkMatrix *) const
SkTypefaceID fTypefaceID
SkString dump() const