blob: 20d0d3fa5c4d3aecfc90d01ac4da2689b3e39524 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2006 The Android Open Source Project
3 *
herb0c752f42015-06-24 13:06:21 -07004 * Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 */
6
Herb Derby5fd955e2019-01-16 11:23:29 -05007#ifndef SkStrike_DEFINED
8#define SkStrike_DEFINED
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkFontMetrics.h"
11#include "include/core/SkFontTypes.h"
12#include "include/core/SkPaint.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/private/SkTHash.h"
14#include "include/private/SkTemplates.h"
Ben Wagner729a23f2019-05-17 16:29:34 -040015#include "src/core/SkArenaAlloc.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/core/SkDescriptor.h"
17#include "src/core/SkGlyph.h"
18#include "src/core/SkGlyphRunPainter.h"
19#include "src/core/SkScalerContext.h"
Herb Derby53eb1ec2019-09-25 13:34:19 -040020#include "src/core/SkStrikeForGPU.h"
bungeman520ced62016-10-18 08:03:42 -040021#include <memory>
reed@android.com8a1c16f2008-12-17 15:59:43 +000022
reed@android.com8a1c16f2008-12-17 15:59:43 +000023/** \class SkGlyphCache
24
herb0c752f42015-06-24 13:06:21 -070025 This class represents a strike: a specific combination of typeface, size, matrix, etc., and
Mike Reedfdb876d2019-02-01 09:55:20 -050026 holds the glyphs for that strike. Calling any of the getGlyphID... methods will
herb0c752f42015-06-24 13:06:21 -070027 return the requested glyph, either instantly if it is already cached, or by first generating
28 it and then adding it to the strike.
reed@android.com8a1c16f2008-12-17 15:59:43 +000029
herb0c752f42015-06-24 13:06:21 -070030 The strikes are held in a global list, available to all threads. To interact with one, call
Herb Derby82a36ac2018-03-09 16:40:48 -050031 either Find{OrCreate}Exclusive().
Herb Derbydfeb2aa2018-02-28 18:47:27 -050032
33 The Find*Exclusive() method returns SkExclusiveStrikePtr, which releases exclusive ownership
34 when they go out of scope.
reed@android.com8a1c16f2008-12-17 15:59:43 +000035*/
Herb Derby53eb1ec2019-09-25 13:34:19 -040036class SkStrike final : public SkStrikeForGPU {
reed@android.com8a1c16f2008-12-17 15:59:43 +000037public:
Herb Derby5fd955e2019-01-16 11:23:29 -050038 SkStrike(const SkDescriptor& desc,
39 std::unique_ptr<SkScalerContext> scaler,
40 const SkFontMetrics&);
Herb Derbydce19a72018-04-18 16:02:17 -040041
Herb Derbya4eecd82019-06-25 15:05:30 -040042 // Return a glyph. Create it if it doesn't exist, and initialize with the prototype.
43 SkGlyph* glyphFromPrototype(const SkGlyphPrototype& p, void* image = nullptr);
44
Herb Derbyf0e75812019-06-12 11:14:50 -040045 // Return a glyph or nullptr if it does not exits in the strike.
46 SkGlyph* glyphOrNull(SkPackedGlyphID id) const;
47
Herb Derby70190602019-06-24 14:53:59 -040048 // Lookup (or create if needed) the toGlyph using toID. If that glyph is not initialized with
49 // an image, then use the information in from to initialize the width, height top, left,
50 // format and image of the toGlyph. This is mainly used preserving the glyph if it was
51 // created by a search of desperation.
52 SkGlyph* mergeGlyphAndImage(SkPackedGlyphID toID, const SkGlyph& from);
Herb Derby33a6f7c2019-06-07 11:01:36 -040053
Herb Derbyf0e75812019-06-12 11:14:50 -040054 // If the path has never been set, then add a path to glyph.
55 const SkPath* preparePath(SkGlyph* glyph, const SkPath* path);
56
reed216b6432015-08-19 12:25:40 -070057 /** Return the number of glyphs currently cached. */
58 int countCachedGlyphs() const;
ctguil@chromium.org0bc7bf52011-03-04 19:04:57 +000059
caryclark0449bcf2016-02-09 13:25:45 -080060 /** If the advance axis intersects the glyph's path, append the positions scaled and offset
61 to the array (if non-null), and set the count to the updated array length.
62 */
63 void findIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos,
Herb Derby6a075912019-05-29 17:02:49 -040064 SkGlyph* , SkScalar* array, int* count);
caryclark0449bcf2016-02-09 13:25:45 -080065
Khushal8523b6b2018-06-12 11:26:17 -070066
reed@android.com8a1c16f2008-12-17 15:59:43 +000067 /** Return the vertical metrics for this strike.
68 */
Mike Reedcb6f53e2018-11-06 12:44:54 -050069 const SkFontMetrics& getFontMetrics() const {
reed@google.com0a01f5a2013-05-08 14:19:08 +000070 return fFontMetrics;
reed@android.com8a1c16f2008-12-17 15:59:43 +000071 }
reed@android.comf2b98d62010-12-20 18:26:13 +000072
Herbert Derby7951a0d2019-10-09 12:50:00 -040073 const SkGlyphPositionRoundingSpec& roundingSpec() const override {
74 return fRoundingSpec;
Herb Derbyc9fce9c2019-06-28 13:48:08 -040075 }
76
Herb Derby96850572019-02-11 13:02:18 -050077 const SkDescriptor& getDescriptor() const override;
78
Herb Derby9c9af8e2019-06-28 17:54:54 -040079 SkSpan<const SkGlyph*> metrics(SkSpan<const SkGlyphID> glyphIDs,
80 const SkGlyph* results[]);
81
Herb Derby246c3ea2019-07-03 10:42:20 -040082 SkSpan<const SkGlyph*> preparePaths(SkSpan<const SkGlyphID> glyphIDs,
83 const SkGlyph* results[]);
84
85 SkSpan<const SkGlyph*> prepareImages(SkSpan<const SkPackedGlyphID> glyphIDs,
86 const SkGlyph* results[]);
87
Herbert Derby3838fe32019-10-09 15:09:15 -040088 void prepareForDrawingMasksCPU(SkDrawableGlyphBuffer* drawables);
89
90 void prepareForDrawingPathsCPU(SkDrawableGlyphBuffer* drawables);
Herb Derbyf5e9b422019-10-22 16:06:22 -040091
92 void prepareForMaskDrawing(
93 SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) override;
94
95 void prepareForSDFTDrawing(
96 SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) override;
97
98 void prepareForPathDrawing(
99 SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) override;
Herb Derbye8d2d012019-03-11 17:22:47 -0400100
Herb Derby49253642019-02-11 14:20:31 -0500101 void onAboutToExitScope() override;
Herb Derby96850572019-02-11 13:02:18 -0500102
ssid33c594c2015-08-27 09:23:54 -0700103 /** Return the approx RAM usage for this cache. */
104 size_t getMemoryUsed() const { return fMemoryUsed; }
105
reed40dab982015-01-28 13:28:53 -0800106 void dump() const;
107
bungeman7cfd46a2016-10-20 16:06:52 -0400108 SkScalerContext* getScalerContext() const { return fScalerContext.get(); }
djsollen@google.com15eeca02012-06-01 12:52:26 +0000109
reed@android.comf2b98d62010-12-20 18:26:13 +0000110#ifdef SK_DEBUG
Khushalb2e71272018-05-15 12:59:48 -0700111 void forceValidate() const;
reed@android.comf2b98d62010-12-20 18:26:13 +0000112 void validate() const;
113#else
114 void validate() const {}
115#endif
116
117 class AutoValidate : SkNoncopyable {
118 public:
Herb Derby5fd955e2019-01-16 11:23:29 -0500119 AutoValidate(const SkStrike* cache) : fCache(cache) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000120 if (fCache) {
121 fCache->validate();
122 }
123 }
124 ~AutoValidate() {
125 if (fCache) {
126 fCache->validate();
127 }
128 }
129 void forget() {
halcanary96fcdcc2015-08-27 07:41:13 -0700130 fCache = nullptr;
reed@android.comf2b98d62010-12-20 18:26:13 +0000131 }
132 private:
Herb Derby5fd955e2019-01-16 11:23:29 -0500133 const SkStrike* fCache;
reed@android.comf2b98d62010-12-20 18:26:13 +0000134 };
reed@google.com98539c62011-03-15 15:40:16 +0000135
reed@android.com8a1c16f2008-12-17 15:59:43 +0000136private:
Herb Derbye46ccf82019-01-09 11:22:00 -0500137 class GlyphMapHashTraits {
138 public:
139 static SkPackedGlyphID GetKey(const SkGlyph* glyph) {
140 return glyph->getPackedID();
141 }
142 static uint32_t Hash(SkPackedGlyphID glyphId) {
143 return glyphId.hash();
144 }
145 };
146
Herb Derby33a6f7c2019-06-07 11:01:36 -0400147 SkGlyph* makeGlyph(SkPackedGlyphID);
148
Herb Derbyf5e9b422019-10-22 16:06:22 -0400149 template <typename Fn>
150 void commonFilterLoop(SkDrawableGlyphBuffer* drawables, Fn&& fn);
151
Herb Derbycb443a52019-11-11 18:01:36 -0500152 // Return a glyph. Create it if it doesn't exist, and initialize the glyph with metrics and
153 // advances using a scaler.
154 SkGlyph* glyph(SkPackedGlyphID packedID);
155
156 const void* prepareImage(SkGlyph* glyph);
157
158 // If the path has never been set, then use the scaler context to add the glyph.
159 const SkPath* preparePath(SkGlyph*);
160
Herb Derby246c3ea2019-07-03 10:42:20 -0400161 enum PathDetail {
162 kMetricsOnly,
163 kMetricsAndPath
164 };
Herb Derby246c3ea2019-07-03 10:42:20 -0400165 // internalPrepare will only be called with a mutex already held.
166 SkSpan<const SkGlyph*> internalPrepare(
167 SkSpan<const SkGlyphID> glyphIDs,
168 PathDetail pathDetail,
169 const SkGlyph** results);
Herb Derbyd2a18872019-06-18 17:07:39 -0400170
Herb Derby33a6f7c2019-06-07 11:01:36 -0400171 const SkAutoDescriptor fDesc;
172 const std::unique_ptr<SkScalerContext> fScalerContext;
Herb Derby4bb189f2019-11-11 18:21:23 -0500173 const SkFontMetrics fFontMetrics;
Herb Derby33a6f7c2019-06-07 11:01:36 -0400174
Herb Derbye46ccf82019-01-09 11:22:00 -0500175 // Map from a combined GlyphID and sub-pixel position to a SkGlyph*.
176 // The actual glyph is stored in the fAlloc. This structure provides an
Herb Derby33a6f7c2019-06-07 11:01:36 -0400177 // unchanging pointer as long as the strike is alive.
Herb Derbye46ccf82019-01-09 11:22:00 -0500178 SkTHashTable<SkGlyph*, SkPackedGlyphID, GlyphMapHashTraits> fGlyphMap;
herbcd7f0352015-09-15 15:15:40 -0700179
Herb Derby7c5a8062017-01-20 11:59:03 -0500180 // so we don't grow our arrays a lot
Herb Derby80d22ea2017-01-24 11:01:59 -0500181 static constexpr size_t kMinGlyphCount = 8;
182 static constexpr size_t kMinGlyphImageSize = 16 /* height */ * 8 /* width */;
183 static constexpr size_t kMinAllocAmount = kMinGlyphImageSize * kMinGlyphCount;
Herb Derby7c5a8062017-01-20 11:59:03 -0500184
Herb Derby80d22ea2017-01-24 11:01:59 -0500185 SkArenaAlloc fAlloc {kMinAllocAmount};
herbcd7f0352015-09-15 15:15:40 -0700186
Herb Derby33a6f7c2019-06-07 11:01:36 -0400187 // Tracks (approx) how much ram is tied-up in this strike.
Herb Derby80d22ea2017-01-24 11:01:59 -0500188 size_t fMemoryUsed;
Herb Derby4f169ec2018-08-22 17:26:46 -0400189
Herbert Derby7951a0d2019-10-09 12:50:00 -0400190 const SkGlyphPositionRoundingSpec fRoundingSpec;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000191};
192
Herb Derby5fd955e2019-01-16 11:23:29 -0500193#endif // SkStrike_DEFINED