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