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 found in the LICENSE file. 5 */ 6 7 #ifndef SkStrike_DEFINED 8 #define SkStrike_DEFINED 9 10 #include "include/core/SkFontMetrics.h" 11 #include "include/core/SkFontTypes.h" 12 #include "include/core/SkRefCnt.h" 13 #include "include/private/base/SkMutex.h" 14 #include "include/private/base/SkTemplates.h" 15 #include "src/base/SkArenaAlloc.h" 16 #include "src/core/SkDescriptor.h" 17 #include "src/core/SkGlyph.h" 18 #include "src/core/SkGlyphRunPainter.h" 19 #include "src/core/SkStrikeSpec.h" 20 #include "src/core/SkTHash.h" 21 22 #include <memory> 23 24 class SkScalerContext; 25 class SkStrikeCache; 26 class SkTraceMemoryDump; 27 28 namespace sktext { 29 union IDOrPath; 30 union IDOrDrawable; 31 } // namespace sktext 32 33 class SkStrikePinner { 34 public: 35 virtual ~SkStrikePinner() = default; 36 virtual bool canDelete() = 0; assertValid()37 virtual void assertValid() {} 38 }; 39 40 // This class holds the results of an SkScalerContext, and owns a references to that scaler. 41 class SkStrike final : public sktext::StrikeForGPU { 42 public: 43 SkStrike(SkStrikeCache* strikeCache, 44 const SkStrikeSpec& strikeSpec, 45 std::unique_ptr<SkScalerContext> scaler, 46 const SkFontMetrics* metrics, 47 std::unique_ptr<SkStrikePinner> pinner); 48 49 void lock() override SK_ACQUIRE(fStrikeLock); 50 void unlock() override SK_RELEASE_CAPABILITY(fStrikeLock); 51 SkGlyphDigest digestFor(skglyph::ActionType, SkPackedGlyphID) override SK_REQUIRES(fStrikeLock); 52 bool prepareForImage(SkGlyph* glyph) override SK_REQUIRES(fStrikeLock); 53 bool prepareForPath(SkGlyph*) override SK_REQUIRES(fStrikeLock); 54 bool prepareForDrawable(SkGlyph*) override SK_REQUIRES(fStrikeLock); 55 56 // Lookup (or create if needed) the returned glyph using toID. If that glyph is not initialized 57 // with an image, then use the information in fromGlyph to initialize the width, height top, 58 // left, format and image of the glyph. This is mainly used preserving the glyph if it was 59 // created by a search of desperation. 60 SkGlyph* mergeGlyphAndImage( 61 SkPackedGlyphID toID, const SkGlyph& fromGlyph) SK_EXCLUDES(fStrikeLock); 62 63 // If the path has never been set, then add a path to glyph. 64 const SkPath* mergePath( 65 SkGlyph* glyph, const SkPath* path, bool hairline) SK_EXCLUDES(fStrikeLock); 66 67 // If the drawable has never been set, then add a drawable to glyph. 68 const SkDrawable* mergeDrawable( 69 SkGlyph* glyph, sk_sp<SkDrawable> drawable) SK_EXCLUDES(fStrikeLock); 70 71 // If the advance axis intersects the glyph's path, append the positions scaled and offset 72 // to the array (if non-null), and set the count to the updated array length. 73 // TODO: track memory usage. 74 void findIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos, 75 SkGlyph*, SkScalar* array, int* count) SK_EXCLUDES(fStrikeLock); 76 getFontMetrics()77 const SkFontMetrics& getFontMetrics() const { 78 return fFontMetrics; 79 } 80 81 SkSpan<const SkGlyph*> metrics( 82 SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) SK_EXCLUDES(fStrikeLock); 83 84 SkSpan<const SkGlyph*> preparePaths( 85 SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) SK_EXCLUDES(fStrikeLock); 86 87 SkSpan<const SkGlyph*> prepareImages(SkSpan<const SkPackedGlyphID> glyphIDs, 88 const SkGlyph* results[]) SK_EXCLUDES(fStrikeLock); 89 90 SkSpan<const SkGlyph*> prepareDrawables( 91 SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) SK_EXCLUDES(fStrikeLock); 92 93 // SkStrikeForGPU APIs getDescriptor()94 const SkDescriptor& getDescriptor() const override { 95 return fStrikeSpec.descriptor(); 96 } 97 roundingSpec()98 const SkGlyphPositionRoundingSpec& roundingSpec() const override { 99 return fRoundingSpec; 100 } 101 strikePromise()102 sktext::SkStrikePromise strikePromise() override { 103 return sktext::SkStrikePromise(sk_ref_sp<SkStrike>(this)); 104 } 105 106 // Convert all the IDs into SkPaths in the span. 107 void glyphIDsToPaths(SkSpan<sktext::IDOrPath> idsOrPaths) SK_EXCLUDES(fStrikeLock); 108 109 // Convert all the IDs into SkDrawables in the span. 110 void glyphIDsToDrawables(SkSpan<sktext::IDOrDrawable> idsOrDrawables) SK_EXCLUDES(fStrikeLock); 111 strikeSpec()112 const SkStrikeSpec& strikeSpec() const { 113 return fStrikeSpec; 114 } 115 verifyPinnedStrike()116 void verifyPinnedStrike() const { 117 if (fPinner != nullptr) { 118 fPinner->assertValid(); 119 } 120 } 121 122 void dump() const SK_EXCLUDES(fStrikeLock); 123 void dumpMemoryStatistics(SkTraceMemoryDump* dump) const SK_EXCLUDES(fStrikeLock); 124 125 SkGlyph* glyph(SkGlyphDigest) SK_REQUIRES(fStrikeLock); 126 127 private: 128 friend class SkStrikeCache; 129 class Monitor; 130 131 // Return a glyph. Create it if it doesn't exist, and initialize the glyph with metrics and 132 // advances using a scaler. 133 SkGlyph* glyph(SkPackedGlyphID) SK_REQUIRES(fStrikeLock); 134 135 // Generate the glyph digest information and update structures to add the glyph. 136 SkGlyphDigest* addGlyphAndDigest(SkGlyph* glyph) SK_REQUIRES(fStrikeLock); 137 138 // Maintain memory use statistics. 139 void updateMemoryUsage(size_t increase) SK_EXCLUDES(fStrikeLock); 140 141 enum PathDetail { 142 kMetricsOnly, 143 kMetricsAndPath 144 }; 145 146 // internalPrepare will only be called with a mutex already held. 147 SkSpan<const SkGlyph*> internalPrepare( 148 SkSpan<const SkGlyphID> glyphIDs, 149 PathDetail pathDetail, 150 const SkGlyph** results) SK_REQUIRES(fStrikeLock); 151 152 // The following are const and need no mutex protection. 153 const SkFontMetrics fFontMetrics; 154 const SkGlyphPositionRoundingSpec fRoundingSpec; 155 const SkStrikeSpec fStrikeSpec; 156 SkStrikeCache* const fStrikeCache; 157 158 // This mutex provides protection for this specific SkStrike. 159 mutable SkMutex fStrikeLock; 160 161 // Maps from a combined GlyphID and sub-pixel position to a SkGlyphDigest. The actual glyph is 162 // stored in the fAlloc. The pointer to the glyph is stored fGlyphForIndex. The 163 // SkGlyphDigest's fIndex field stores the index. This pointer provides an unchanging 164 // reference to the SkGlyph as long as the strike is alive, and fGlyphForIndex 165 // provides a dense index for glyphs. 166 SkTHashMap<SkPackedGlyphID, SkGlyphDigest, SkPackedGlyphID::Hash> 167 fDigestForPackedGlyphID SK_GUARDED_BY(fStrikeLock); 168 169 // Maps from a glyphIndex to a glyph 170 std::vector<SkGlyph*> fGlyphForIndex SK_GUARDED_BY(fStrikeLock); 171 172 // Context that corresponds to the glyph information in this strike. 173 const std::unique_ptr<SkScalerContext> fScalerContext SK_GUARDED_BY(fStrikeLock); 174 175 // Used while changing the strike to track memory increase. SK_GUARDED_BY(fStrikeLock)176 size_t fMemoryIncrease SK_GUARDED_BY(fStrikeLock) {0}; 177 178 // So, we don't grow our arrays a lot. 179 inline static constexpr size_t kMinGlyphCount = 8; 180 inline static constexpr size_t kMinGlyphImageSize = 16 /* height */ * 8 /* width */; 181 inline static constexpr size_t kMinAllocAmount = kMinGlyphImageSize * kMinGlyphCount; 182 SK_GUARDED_BY(fStrikeLock)183 SkArenaAlloc fAlloc SK_GUARDED_BY(fStrikeLock) {kMinAllocAmount}; 184 185 // The following are protected by the SkStrikeCache's mutex. 186 SkStrike* fNext{nullptr}; 187 SkStrike* fPrev{nullptr}; 188 std::unique_ptr<SkStrikePinner> fPinner; 189 size_t fMemoryUsed{sizeof(SkStrike)}; 190 bool fRemoved{false}; 191 }; 192 193 #endif // SkStrike_DEFINED 194