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(std::unique_ptr<SkScalerContext> scaler, 56 const SkFontMetrics* metrics = nullptr); 57 58 // Lookup (or create if needed) the toGlyph using toID. If that glyph is not initialized with 59 // an image, then use the information in from to initialize the width, height top, left, 60 // format and image of the toGlyph. This is mainly used preserving the glyph if it was 61 // created by a search of desperation. 62 std::tuple<SkGlyph*, size_t> mergeGlyphAndImage( 63 SkPackedGlyphID toID, const SkGlyph& from) SK_EXCLUDES(fMu); 64 65 // If the path has never been set, then add a path to glyph. 66 std::tuple<const SkPath*, size_t> mergePath( 67 SkGlyph* glyph, const SkPath* path) SK_EXCLUDES(fMu); 68 69 /** Return the number of glyphs currently cached. */ 70 int countCachedGlyphs() const SK_EXCLUDES(fMu); 71 72 /** If the advance axis intersects the glyph's path, append the positions scaled and offset 73 to the array (if non-null), and set the count to the updated array length. 74 */ 75 void findIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos, 76 SkGlyph* , SkScalar* array, int* count) SK_EXCLUDES(fMu); 77 getFontMetrics()78 const SkFontMetrics& getFontMetrics() const { 79 return fFontMetrics; 80 } 81 82 std::tuple<SkSpan<const SkGlyph*>, size_t> metrics( 83 SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) SK_EXCLUDES(fMu); 84 85 std::tuple<SkSpan<const SkGlyph*>, size_t> preparePaths( 86 SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) SK_EXCLUDES(fMu); 87 88 std::tuple<SkSpan<const SkGlyph*>, size_t> prepareImages( 89 SkSpan<const SkPackedGlyphID> glyphIDs, const SkGlyph* results[]) SK_EXCLUDES(fMu); 90 91 size_t prepareForDrawingMasksCPU(SkDrawableGlyphBuffer* drawables) SK_EXCLUDES(fMu); 92 93 // SkStrikeForGPU APIs roundingSpec()94 const SkGlyphPositionRoundingSpec& roundingSpec() const { 95 return fRoundingSpec; 96 } 97 98 size_t prepareForMaskDrawing( 99 SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) SK_EXCLUDES(fMu); 100 101 size_t prepareForSDFTDrawing( 102 SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) SK_EXCLUDES(fMu); 103 104 size_t prepareForPathDrawing( 105 SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) SK_EXCLUDES(fMu); 106 107 void dump() const SK_EXCLUDES(fMu); 108 getScalerContext()109 SkScalerContext* getScalerContext() const { return fScalerContext.get(); } 110 111 private: 112 template <typename Fn> 113 size_t commonFilterLoop(SkDrawableGlyphBuffer* drawables, Fn&& fn) SK_REQUIRES(fMu); 114 115 // Return a glyph. Create it if it doesn't exist, and initialize the glyph with metrics and 116 // advances using a scaler. 117 std::tuple<SkGlyph*, size_t> glyph(SkPackedGlyphID) SK_REQUIRES(fMu); 118 119 std::tuple<SkGlyphDigest, size_t> digest(SkPackedGlyphID) SK_REQUIRES(fMu); 120 121 // Generate the glyph digest information and update structures to add the glyph. 122 SkGlyphDigest addGlyph(SkGlyph* glyph) SK_REQUIRES(fMu); 123 124 std::tuple<const void*, size_t> prepareImage(SkGlyph* glyph) SK_REQUIRES(fMu); 125 126 // If the path has never been set, then use the scaler context to add the glyph. 127 std::tuple<const SkPath*, size_t> preparePath(SkGlyph*) SK_REQUIRES(fMu); 128 129 enum PathDetail { 130 kMetricsOnly, 131 kMetricsAndPath 132 }; 133 134 // internalPrepare will only be called with a mutex already held. 135 std::tuple<SkSpan<const SkGlyph*>, size_t> internalPrepare( 136 SkSpan<const SkGlyphID> glyphIDs, 137 PathDetail pathDetail, 138 const SkGlyph** results) SK_REQUIRES(fMu); 139 140 const std::unique_ptr<SkScalerContext> fScalerContext; 141 const SkFontMetrics fFontMetrics; 142 const SkGlyphPositionRoundingSpec fRoundingSpec; 143 144 mutable SkMutex fMu; 145 146 // Map from a combined GlyphID and sub-pixel position to a SkGlyphDigest. The actual glyph is 147 // stored in the fAlloc. The pointer to the glyph is stored fGlyphForIndex. The 148 // SkGlyphDigest's fIndex field stores the index. This pointer provides an unchanging 149 // reference to the SkGlyph as long as the strike is alive, and fGlyphForIndex 150 // provides a dense index for glyphs. 151 SkTHashMap<SkPackedGlyphID, SkGlyphDigest> fDigestForPackedGlyphID SK_GUARDED_BY(fMu); 152 std::vector<SkGlyph*> fGlyphForIndex SK_GUARDED_BY(fMu); 153 154 // so we don't grow our arrays a lot 155 inline static constexpr size_t kMinGlyphCount = 8; 156 inline static constexpr size_t kMinGlyphImageSize = 16 /* height */ * 8 /* width */; 157 inline static constexpr size_t kMinAllocAmount = kMinGlyphImageSize * kMinGlyphCount; 158 SK_GUARDED_BY(fMu)159 SkArenaAlloc fAlloc SK_GUARDED_BY(fMu) {kMinAllocAmount}; 160 }; 161 162 #endif // SkStrike_DEFINED 163