1 :
2 : /*
3 : * Copyright 2006 The Android Open Source Project
4 : *
5 : * Use of this source code is governed by a BSD-style license that can be
6 : * found in the LICENSE file.
7 : */
8 :
9 :
10 : #ifndef SkGlyphCache_DEFINED
11 : #define SkGlyphCache_DEFINED
12 :
13 : #include "SkBitmap.h"
14 : #include "SkChunkAlloc.h"
15 : #include "SkDescriptor.h"
16 : #include "SkScalerContext.h"
17 : #include "SkTemplates.h"
18 :
19 : class SkPaint;
20 :
21 : class SkGlyphCache_Globals;
22 :
23 : /** \class SkGlyphCache
24 :
25 : This class represents a strike: a specific combination of typeface, size,
26 : matrix, etc., and holds the glyphs for that strike. Calling any of the
27 : getUnichar.../getGlyphID... methods will return the requested glyph,
28 : either instantly if it is already cahced, or by first generating it and then
29 : adding it to the strike.
30 :
31 : The strikes are held in a global list, available to all threads. To interact
32 : with one, call either VisitCache() or DetachCache().
33 : */
34 : class SkGlyphCache {
35 : public:
36 : /** Returns a glyph with valid fAdvance and fDevKern fields.
37 : The remaining fields may be valid, but that is not guaranteed. If you
38 : require those, call getUnicharMetrics or getGlyphIDMetrics instead.
39 : */
40 : const SkGlyph& getUnicharAdvance(SkUnichar);
41 : const SkGlyph& getGlyphIDAdvance(uint16_t);
42 :
43 : /** Returns a glyph with all fields valid except fImage and fPath, which
44 : may be null. If they are null, call findImage or findPath for those.
45 : If they are not null, then they are valid.
46 :
47 : This call is potentially slower than the matching ...Advance call. If
48 : you only need the fAdvance/fDevKern fields, call those instead.
49 : */
50 : const SkGlyph& getUnicharMetrics(SkUnichar);
51 : const SkGlyph& getGlyphIDMetrics(uint16_t);
52 :
53 : /** These are variants that take the device position of the glyph. Call
54 : these only if you are drawing in subpixel mode. Passing 0, 0 is
55 : effectively the same as calling the variants w/o the extra params, tho
56 : a tiny bit slower.
57 : */
58 : const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y);
59 : const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y);
60 :
61 : /** Return the glyphID for the specified Unichar. If the char has already
62 : been seen, use the existing cache entry. If not, ask the scalercontext
63 : to compute it for us.
64 : */
65 : uint16_t unicharToGlyph(SkUnichar);
66 :
67 : /** Map the glyph to its Unicode equivalent. Unmappable glyphs map to
68 : a character code of zero.
69 : */
70 : SkUnichar glyphToUnichar(uint16_t);
71 :
72 : /** Returns the number of glyphs for this strike.
73 : */
74 : unsigned getGlyphCount();
75 :
76 : /** Return the image associated with the glyph. If it has not been generated
77 : this will trigger that.
78 : */
79 : const void* findImage(const SkGlyph&);
80 : /** Return the Path associated with the glyph. If it has not been generated
81 : this will trigger that.
82 : */
83 : const SkPath* findPath(const SkGlyph&);
84 :
85 : /** Return the vertical metrics for this strike.
86 : */
87 0 : const SkPaint::FontMetrics& getFontMetricsY() const {
88 0 : return fFontMetricsY;
89 : }
90 :
91 : const SkDescriptor& getDescriptor() const { return *fDesc; }
92 :
93 : SkMask::Format getMaskFormat() const {
94 : return fScalerContext->getMaskFormat();
95 : }
96 :
97 : bool isSubpixel() const {
98 : return fScalerContext->isSubpixel();
99 : }
100 :
101 : /* AuxProc/Data allow a client to associate data with this cache entry.
102 : Multiple clients can use this, as their data is keyed with a function
103 : pointer. In addition to serving as a key, the function pointer is called
104 : with the data when the glyphcache object is deleted, so the client can
105 : cleanup their data as well. NOTE: the auxProc must not try to access
106 : this glyphcache in any way, since it may be in the process of being
107 : deleted.
108 : */
109 :
110 : //! If the proc is found, return true and set *dataPtr to its data
111 : bool getAuxProcData(void (*auxProc)(void*), void** dataPtr) const;
112 : //! Add a proc/data pair to the glyphcache. proc should be non-null
113 : void setAuxProc(void (*auxProc)(void*), void* auxData);
114 : //! If found, remove the proc/data pair from the glyphcache (does not
115 : // call the proc)
116 : void removeAuxProc(void (*auxProc)(void*));
117 :
118 : /** Call proc on all cache entries, stopping early if proc returns true.
119 : The proc should not create or delete caches, since it could produce
120 : deadlock.
121 : */
122 : static void VisitAllCaches(bool (*proc)(SkGlyphCache*, void*), void* ctx);
123 :
124 : /** Find a matching cache entry, and call proc() with it. If none is found
125 : create a new one. If the proc() returns true, detach the cache and
126 : return it, otherwise leave it and return NULL.
127 : */
128 : static SkGlyphCache* VisitCache(const SkDescriptor* desc,
129 : bool (*proc)(const SkGlyphCache*, void*),
130 : void* context);
131 :
132 : /** Given a strike that was returned by either VisitCache() or DetachCache()
133 : add it back into the global cache list (after which the caller should
134 : not reference it anymore.
135 : */
136 : static void AttachCache(SkGlyphCache*);
137 :
138 : /** Detach a strike from the global cache matching the specified descriptor.
139 : Once detached, it can be queried/modified by the current thread, and
140 : when finished, be reattached to the global cache with AttachCache().
141 : While detached, if another request is made with the same descriptor,
142 : a different strike will be generated. This is fine. It does mean we
143 : can have more than 1 strike for the same descriptor, but that will
144 : eventually get purged, and the win is that different thread will never
145 : block each other while a strike is being used.
146 : */
147 0 : static SkGlyphCache* DetachCache(const SkDescriptor* desc) {
148 0 : return VisitCache(desc, DetachProc, NULL);
149 : }
150 :
151 : /** Return the approximate number of bytes used by the font cache
152 : */
153 : static size_t GetCacheUsed();
154 :
155 : /** This can be called to purge old font data, in an attempt to free
156 : enough bytes such that the font cache is not using more than the
157 : specified number of bytes. It is thread-safe, and may be called at
158 : any time.
159 : Return true if some amount of the cache was purged.
160 : */
161 : static bool SetCacheUsed(size_t bytesUsed);
162 :
163 : #ifdef SK_DEBUG
164 : void validate() const;
165 : #else
166 : void validate() const {}
167 : #endif
168 :
169 : class AutoValidate : SkNoncopyable {
170 : public:
171 0 : AutoValidate(const SkGlyphCache* cache) : fCache(cache) {
172 0 : if (fCache) {
173 0 : fCache->validate();
174 : }
175 0 : }
176 0 : ~AutoValidate() {
177 0 : if (fCache) {
178 0 : fCache->validate();
179 : }
180 0 : }
181 : void forget() {
182 : fCache = NULL;
183 : }
184 : private:
185 : const SkGlyphCache* fCache;
186 : };
187 :
188 : private:
189 : SkGlyphCache(const SkDescriptor*);
190 : ~SkGlyphCache();
191 :
192 : enum MetricsType {
193 : kJustAdvance_MetricsType,
194 : kFull_MetricsType
195 : };
196 :
197 : SkGlyph* lookupMetrics(uint32_t id, MetricsType);
198 0 : static bool DetachProc(const SkGlyphCache*, void*) { return true; }
199 :
200 0 : void detach(SkGlyphCache** head) {
201 0 : if (fPrev) {
202 0 : fPrev->fNext = fNext;
203 : } else {
204 0 : *head = fNext;
205 : }
206 0 : if (fNext) {
207 0 : fNext->fPrev = fPrev;
208 : }
209 0 : fPrev = fNext = NULL;
210 0 : }
211 :
212 0 : void attachToHead(SkGlyphCache** head) {
213 0 : SkASSERT(NULL == fPrev && NULL == fNext);
214 0 : if (*head) {
215 0 : (*head)->fPrev = this;
216 0 : fNext = *head;
217 : }
218 0 : *head = this;
219 0 : }
220 :
221 : SkGlyphCache* fNext, *fPrev;
222 : SkDescriptor* fDesc;
223 : SkScalerContext* fScalerContext;
224 : SkPaint::FontMetrics fFontMetricsY;
225 :
226 : enum {
227 : kHashBits = 12,
228 : kHashCount = 1 << kHashBits,
229 : kHashMask = kHashCount - 1
230 : };
231 : SkGlyph* fGlyphHash[kHashCount];
232 : SkTDArray<SkGlyph*> fGlyphArray;
233 : SkChunkAlloc fGlyphAlloc;
234 : SkChunkAlloc fImageAlloc;
235 :
236 : int fMetricsCount, fAdvanceCount;
237 :
238 : struct CharGlyphRec {
239 : uint32_t fID; // unichar + subpixel
240 : SkGlyph* fGlyph;
241 : };
242 : // no reason to use the same kHashCount as fGlyphHash, but we do for now
243 : CharGlyphRec fCharToGlyphHash[kHashCount];
244 :
245 : enum {
246 : // shift so that the top bits fall into kHashBits region
247 : kShiftForHashIndex = SkGlyph::kSubShift +
248 : SkGlyph::kSubBits*2 -
249 : kHashBits
250 : };
251 :
252 0 : static inline unsigned ID2HashIndex(uint32_t id) {
253 0 : return (id ^ (id >> kShiftForHashIndex)) & kHashMask;
254 : }
255 :
256 : // used to track (approx) how much ram is tied-up in this cache
257 : size_t fMemoryUsed;
258 :
259 : struct AuxProcRec {
260 : AuxProcRec* fNext;
261 : void (*fProc)(void*);
262 : void* fData;
263 : };
264 : AuxProcRec* fAuxProcList;
265 : void invokeAndRemoveAuxProcs();
266 :
267 : // This relies on the caller to have already acquired the mutex to access the global cache
268 : static size_t InternalFreeCache(SkGlyphCache_Globals*, size_t bytesNeeded);
269 :
270 : inline static SkGlyphCache* FindTail(SkGlyphCache* head);
271 : static size_t ComputeMemoryUsed(const SkGlyphCache* head);
272 :
273 : friend class SkGlyphCache_Globals;
274 : };
275 :
276 : class SkAutoGlyphCache {
277 : public:
278 : SkAutoGlyphCache(SkGlyphCache* cache) : fCache(cache) {}
279 : SkAutoGlyphCache(const SkDescriptor* desc) {
280 : fCache = SkGlyphCache::DetachCache(desc);
281 : }
282 0 : SkAutoGlyphCache(const SkPaint& paint, const SkMatrix* matrix) {
283 0 : fCache = paint.detachCache(matrix);
284 0 : }
285 0 : ~SkAutoGlyphCache() {
286 0 : if (fCache) {
287 0 : SkGlyphCache::AttachCache(fCache);
288 : }
289 0 : }
290 :
291 0 : SkGlyphCache* getCache() const { return fCache; }
292 :
293 : void release() {
294 : if (fCache) {
295 : SkGlyphCache::AttachCache(fCache);
296 : fCache = NULL;
297 : }
298 : }
299 :
300 : private:
301 : SkGlyphCache* fCache;
302 :
303 : static bool DetachProc(const SkGlyphCache*, void*);
304 : };
305 :
306 : #endif
307 :
|