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
22class 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
27class SkScalerCache {
28public:
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
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
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
86 SkScalerContext* getScalerContext() const { return fScalerContext.get(); }
87
88private:
89 class GlyphMapHashTraits {
90 public:
91 static SkPackedGlyphID GetKey(const SkGlyph* glyph) {
92 return glyph->getPackedID();
93 }
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
141 SkArenaAlloc fAlloc SK_GUARDED_BY(fMu) {kMinAllocAmount};
142};
143
144#endif // SkStrike_DEFINED
145