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/private/SkMutex.h" 13 #include "include/private/SkTHash.h" 14 #include "include/private/SkTemplates.h" 15 #include "src/core/SkArenaAlloc.h" 16 #include "src/core/SkDescriptor.h" 17 #include "src/core/SkGlyph.h" 18 #include "src/core/SkGlyphRunPainter.h" 19 #include "src/core/SkStrikeForGPU.h" 20 #include <memory> 21 22 class SkScalerContext; 23 24 // The value stored in fDigestForPackedGlyphID. 25 // index() is the index into fGlyphForIndex. 26 class SkGlyphDigest { 27 public: 28 // Default ctor is only needed for the hash table. 29 SkGlyphDigest() = default; SkGlyphDigest(size_t i,const SkGlyph & glyph)30 SkGlyphDigest(size_t i, const SkGlyph& glyph) 31 : fIndex{SkTo<uint32_t>(i)} 32 , fIsEmpty(glyph.isEmpty()) 33 , fIsColor(glyph.isColor()) 34 , fCanDrawAsMask{SkStrikeForGPU::CanDrawAsMask(glyph)} 35 , fCanDrawAsSDFT{SkStrikeForGPU::CanDrawAsSDFT(glyph)} {} index()36 int index() const {return fIndex; } isEmpty()37 bool isEmpty() const {return fIsEmpty; } isColor()38 bool isColor() const {return fIsColor; } canDrawAsMask()39 bool canDrawAsMask() const {return fCanDrawAsMask;} canDrawAsSDFT()40 bool canDrawAsSDFT() const {return fCanDrawAsSDFT;} 41 42 private: 43 static_assert(SkPackedGlyphID::kEndData == 20); 44 uint32_t fIndex : SkPackedGlyphID::kEndData; 45 uint32_t fIsEmpty : 1; 46 uint32_t fIsColor : 1; 47 uint32_t fCanDrawAsMask : 1; 48 uint32_t fCanDrawAsSDFT : 1; 49 }; 50 51 // This class represents a strike: a specific combination of typeface, size, matrix, etc., and 52 // holds the glyphs for that strike. 53 class SkScalerCache { 54 public: 55 SkScalerCache(const SkDescriptor& desc, 56 std::unique_ptr<SkScalerContext> scaler, 57 const SkFontMetrics* metrics = nullptr); 58 59 // Lookup (or create if needed) the toGlyph using toID. If that glyph is not initialized with 60 // an image, then use the information in from to initialize the width, height top, left, 61 // format and image of the toGlyph. This is mainly used preserving the glyph if it was 62 // created by a search of desperation. 63 std::tuple<SkGlyph*, size_t> mergeGlyphAndImage( 64 SkPackedGlyphID toID, const SkGlyph& from) SK_EXCLUDES(fMu); 65 66 // If the path has never been set, then add a path to glyph. 67 std::tuple<const SkPath*, size_t> mergePath( 68 SkGlyph* glyph, const SkPath* path) SK_EXCLUDES(fMu); 69 70 /** Return the number of glyphs currently cached. */ 71 int countCachedGlyphs() const SK_EXCLUDES(fMu); 72 73 /** If the advance axis intersects the glyph's path, append the positions scaled and offset 74 to the array (if non-null), and set the count to the updated array length. 75 */ 76 void findIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos, 77 SkGlyph* , SkScalar* array, int* count) SK_EXCLUDES(fMu); 78 getFontMetrics()79 const SkFontMetrics& getFontMetrics() const { 80 return fFontMetrics; 81 } 82 83 std::tuple<SkSpan<const SkGlyph*>, size_t> metrics( 84 SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) SK_EXCLUDES(fMu); 85 86 std::tuple<SkSpan<const SkGlyph*>, size_t> preparePaths( 87 SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) SK_EXCLUDES(fMu); 88 89 std::tuple<SkSpan<const SkGlyph*>, size_t> prepareImages( 90 SkSpan<const SkPackedGlyphID> glyphIDs, const SkGlyph* results[]) SK_EXCLUDES(fMu); 91 92 size_t prepareForDrawingMasksCPU(SkDrawableGlyphBuffer* drawables) SK_EXCLUDES(fMu); 93 94 // SkStrikeForGPU APIs roundingSpec()95 const SkGlyphPositionRoundingSpec& roundingSpec() const { 96 return fRoundingSpec; 97 } 98 99 const SkDescriptor& getDescriptor() const; 100 101 size_t prepareForMaskDrawing( 102 SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) SK_EXCLUDES(fMu); 103 104 size_t prepareForSDFTDrawing( 105 SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) SK_EXCLUDES(fMu); 106 107 size_t prepareForPathDrawing( 108 SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) SK_EXCLUDES(fMu); 109 110 void dump() const SK_EXCLUDES(fMu); 111 getScalerContext()112 SkScalerContext* getScalerContext() const { return fScalerContext.get(); } 113 114 private: 115 template <typename Fn> 116 size_t commonFilterLoop(SkDrawableGlyphBuffer* drawables, Fn&& fn) SK_REQUIRES(fMu); 117 118 // Return a glyph. Create it if it doesn't exist, and initialize the glyph with metrics and 119 // advances using a scaler. 120 std::tuple<SkGlyph*, size_t> glyph(SkPackedGlyphID) SK_REQUIRES(fMu); 121 122 std::tuple<SkGlyphDigest, size_t> digest(SkPackedGlyphID) SK_REQUIRES(fMu); 123 124 // Generate the glyph digest information and update structures to add the glyph. 125 SkGlyphDigest addGlyph(SkGlyph* glyph) SK_REQUIRES(fMu); 126 127 std::tuple<const void*, size_t> prepareImage(SkGlyph* glyph) SK_REQUIRES(fMu); 128 129 // If the path has never been set, then use the scaler context to add the glyph. 130 std::tuple<const SkPath*, size_t> preparePath(SkGlyph*) SK_REQUIRES(fMu); 131 132 enum PathDetail { 133 kMetricsOnly, 134 kMetricsAndPath 135 }; 136 137 // internalPrepare will only be called with a mutex already held. 138 std::tuple<SkSpan<const SkGlyph*>, size_t> internalPrepare( 139 SkSpan<const SkGlyphID> glyphIDs, 140 PathDetail pathDetail, 141 const SkGlyph** results) SK_REQUIRES(fMu); 142 143 const SkAutoDescriptor fDesc; 144 const std::unique_ptr<SkScalerContext> fScalerContext; 145 const SkFontMetrics fFontMetrics; 146 const SkGlyphPositionRoundingSpec fRoundingSpec; 147 148 mutable SkMutex fMu; 149 150 // Map from a combined GlyphID and sub-pixel position to a SkGlyphDigest. The actual glyph is 151 // stored in the fAlloc. The pointer to the glyph is stored fGlyphForIndex. The 152 // SkGlyphDigest's fIndex field stores the index. This pointer provides an unchanging 153 // reference to the SkGlyph as long as the strike is alive, and fGlyphForIndex 154 // provides a dense index for glyphs. 155 SkTHashMap<SkPackedGlyphID, SkGlyphDigest> fDigestForPackedGlyphID SK_GUARDED_BY(fMu); 156 std::vector<SkGlyph*> fGlyphForIndex SK_GUARDED_BY(fMu); 157 158 // so we don't grow our arrays a lot 159 static constexpr size_t kMinGlyphCount = 8; 160 static constexpr size_t kMinGlyphImageSize = 16 /* height */ * 8 /* width */; 161 static constexpr size_t kMinAllocAmount = kMinGlyphImageSize * kMinGlyphCount; 162 SK_GUARDED_BY(fMu)163 SkArenaAlloc fAlloc SK_GUARDED_BY(fMu) {kMinAllocAmount}; 164 }; 165 166 #endif // SkStrike_DEFINED 167