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#ifndef GrStrikeCache_DEFINED
9#define GrStrikeCache_DEFINED
10
11#include "include/private/SkTHash.h"
12#include "src/core/SkDescriptor.h"
13#include "src/gpu/GrDrawOpAtlas.h"
14#include "src/gpu/GrGlyph.h"
15
16class GrAtlasManager;
17class GrGpu;
18class GrStrikeCache;
19class SkBulkGlyphMetricsAndImages;
20
21/**
22 * The GrTextStrike manages a pool of CPU backing memory for GrGlyphs. This backing memory
23 * is indexed by a PackedID and SkStrike. The SkStrike is what actually creates the mask.
24 * The GrTextStrike may outlive the generating SkStrike. However, it retains a copy
25 * of it's SkDescriptor as a key to access (or regenerate) the SkStrike. GrTextStrikes are
26 * created by and owned by a GrStrikeCache.
27 */
28class GrTextStrike : public SkNVRefCnt<GrTextStrike> {
29public:
30 GrTextStrike(const SkDescriptor& fontScalerKey);
31
32 GrGlyph* getGlyph(SkPackedGlyphID);
33
34 // returns true if glyph successfully added to texture atlas, false otherwise. If the glyph's
35 // mask format has changed, then addGlyphToAtlas will draw a clear box. This will almost never
36 // happen.
37 // TODO we can handle some of these cases if we really want to, but the long term solution is to
38 // get the actual glyph image itself when we get the glyph metrics.
39 GrDrawOpAtlas::ErrorCode addGlyphToAtlas(const SkGlyph&,
40 GrMaskFormat expectedMaskFormat,
41 bool needsPadding,
42 GrResourceProvider*,
43 GrDeferredUploadTarget*,
44 GrAtlasManager*,
45 GrGlyph*);
46
47private:
48 struct HashTraits {
49 // GetKey and Hash for the the hash table.
50 static const SkPackedGlyphID& GetKey(const GrGlyph* glyph) {
51 return glyph->fPackedID;
52 }
53
54 static uint32_t Hash(SkPackedGlyphID key) {
55 return SkChecksum::Mix(key.hash());
56 }
57 };
58 SkTHashTable<GrGlyph*, SkPackedGlyphID, HashTraits> fCache;
59 SkAutoDescriptor fFontScalerKey;
60 SkArenaAlloc fAlloc{512};
61
62 friend class GrStrikeCache;
63};
64
65/**
66 * GrStrikeCache manages strikes which are indexed by a SkStrike. These strikes can then be
67 * used to generate individual Glyph Masks.
68 */
69class GrStrikeCache {
70public:
71 ~GrStrikeCache();
72
73 // The user of the cache may hold a long-lived ref to the returned strike. However, actions by
74 // another client of the cache may cause the strike to be purged while it is still reffed.
75 // Therefore, the caller must check GrTextStrike::isAbandoned() if there are other
76 // interactions with the cache since the strike was received.
77 sk_sp<GrTextStrike> getStrike(const SkDescriptor& desc) {
78 if (sk_sp<GrTextStrike>* cached = fCache.find(desc)) {
79 return *cached;
80 }
81 return this->generateStrike(desc);
82 }
83
84 void freeAll();
85
86private:
87 sk_sp<GrTextStrike> generateStrike(const SkDescriptor& desc) {
88 sk_sp<GrTextStrike> strike = sk_make_sp<GrTextStrike>(desc);
89 fCache.set(strike);
90 return strike;
91 }
92
93 struct DescriptorHashTraits {
94 static const SkDescriptor& GetKey(const sk_sp<GrTextStrike>& strike) {
95 return *strike->fFontScalerKey.getDesc();
96 }
97 static uint32_t Hash(const SkDescriptor& desc) { return desc.getChecksum(); }
98 };
99
100 using StrikeHash = SkTHashTable<sk_sp<GrTextStrike>, SkDescriptor, DescriptorHashTraits>;
101
102 StrikeHash fCache;
103};
104
105#endif // GrStrikeCache_DEFINED
106