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