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