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 // This class represents a strike: a specific combination of typeface, size, matrix, etc., and 25 // holds the glyphs for that strike. 26 27 class SkScalerCache { 28 public: 29 SkScalerCache(const SkDescriptor& desc, 30 std::unique_ptr<SkScalerContext> scaler, 31 const SkFontMetrics* metrics = nullptr); 32 33 // Lookup (or create if needed) the toGlyph using toID. If that glyph is not initialized with 34 // an image, then use the information in from to initialize the width, height top, left, 35 // format and image of the toGlyph. This is mainly used preserving the glyph if it was 36 // created by a search of desperation. 37 std::tuple<SkGlyph*, size_t> mergeGlyphAndImage( 38 SkPackedGlyphID toID, const SkGlyph& from) SK_EXCLUDES(fMu); 39 40 // If the path has never been set, then add a path to glyph. 41 std::tuple<const SkPath*, size_t> mergePath( 42 SkGlyph* glyph, const SkPath* path) SK_EXCLUDES(fMu); 43 44 /** Return the number of glyphs currently cached. */ 45 int countCachedGlyphs() const SK_EXCLUDES(fMu); 46 47 /** If the advance axis intersects the glyph's path, append the positions scaled and offset 48 to the array (if non-null), and set the count to the updated array length. 49 */ 50 void findIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos, 51 SkGlyph* , SkScalar* array, int* count) SK_EXCLUDES(fMu); 52 getFontMetrics()53 const SkFontMetrics& getFontMetrics() const { 54 return fFontMetrics; 55 } 56 57 std::tuple<SkSpan<const SkGlyph*>, size_t> metrics( 58 SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) SK_EXCLUDES(fMu); 59 60 std::tuple<SkSpan<const SkGlyph*>, size_t> preparePaths( 61 SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) SK_EXCLUDES(fMu); 62 63 std::tuple<SkSpan<const SkGlyph*>, size_t> prepareImages( 64 SkSpan<const SkPackedGlyphID> glyphIDs, const SkGlyph* results[]) SK_EXCLUDES(fMu); 65 66 size_t prepareForDrawingMasksCPU(SkDrawableGlyphBuffer* drawables) SK_EXCLUDES(fMu); 67 68 // SkStrikeForGPU APIs roundingSpec()69 const SkGlyphPositionRoundingSpec& roundingSpec() const { 70 return fRoundingSpec; 71 } 72 73 const SkDescriptor& getDescriptor() const; 74 75 size_t prepareForMaskDrawing( 76 SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) SK_EXCLUDES(fMu); 77 78 size_t prepareForSDFTDrawing( 79 SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) SK_EXCLUDES(fMu); 80 81 size_t prepareForPathDrawing( 82 SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) SK_EXCLUDES(fMu); 83 84 void dump() const SK_EXCLUDES(fMu); 85 getScalerContext()86 SkScalerContext* getScalerContext() const { return fScalerContext.get(); } 87 88 private: 89 class GlyphMapHashTraits { 90 public: GetKey(const SkGlyph * glyph)91 static SkPackedGlyphID GetKey(const SkGlyph* glyph) { 92 return glyph->getPackedID(); 93 } Hash(SkPackedGlyphID glyphId)94 static uint32_t Hash(SkPackedGlyphID glyphId) { 95 return glyphId.hash(); 96 } 97 }; 98 99 std::tuple<SkGlyph*, size_t> makeGlyph(SkPackedGlyphID) SK_REQUIRES(fMu); 100 101 template <typename Fn> 102 size_t commonFilterLoop(SkDrawableGlyphBuffer* drawables, Fn&& fn) SK_REQUIRES(fMu); 103 104 // Return a glyph. Create it if it doesn't exist, and initialize the glyph with metrics and 105 // advances using a scaler. 106 std::tuple<SkGlyph*, size_t> glyph(SkPackedGlyphID) SK_REQUIRES(fMu); 107 108 std::tuple<const void*, size_t> prepareImage(SkGlyph* glyph) SK_REQUIRES(fMu); 109 110 // If the path has never been set, then use the scaler context to add the glyph. 111 std::tuple<const SkPath*, size_t> preparePath(SkGlyph*) SK_REQUIRES(fMu); 112 113 enum PathDetail { 114 kMetricsOnly, 115 kMetricsAndPath 116 }; 117 118 // internalPrepare will only be called with a mutex already held. 119 std::tuple<SkSpan<const SkGlyph*>, size_t> internalPrepare( 120 SkSpan<const SkGlyphID> glyphIDs, 121 PathDetail pathDetail, 122 const SkGlyph** results) SK_REQUIRES(fMu); 123 124 const SkAutoDescriptor fDesc; 125 const std::unique_ptr<SkScalerContext> fScalerContext; 126 const SkFontMetrics fFontMetrics; 127 const SkGlyphPositionRoundingSpec fRoundingSpec; 128 129 mutable SkMutex fMu; 130 131 // Map from a combined GlyphID and sub-pixel position to a SkGlyph*. 132 // The actual glyph is stored in the fAlloc. This structure provides an 133 // unchanging pointer as long as the strike is alive. 134 SkTHashTable<SkGlyph*, SkPackedGlyphID, GlyphMapHashTraits> fGlyphMap SK_GUARDED_BY(fMu); 135 136 // so we don't grow our arrays a lot 137 static constexpr size_t kMinGlyphCount = 8; 138 static constexpr size_t kMinGlyphImageSize = 16 /* height */ * 8 /* width */; 139 static constexpr size_t kMinAllocAmount = kMinGlyphImageSize * kMinGlyphCount; 140 SK_GUARDED_BY(fMu)141 SkArenaAlloc fAlloc SK_GUARDED_BY(fMu) {kMinAllocAmount}; 142 }; 143 144 #endif // SkStrike_DEFINED 145