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