• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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