3 * Copyright 2006 The Android Open Source Project
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
10 #ifndef SkGlyphCache_DEFINED
11 #define SkGlyphCache_DEFINED
14 #include "SkChunkAlloc.h"
15 #include "SkDescriptor.h"
17 #include "SkScalerContext.h"
18 #include "SkTemplates.h"
19 #include "SkTDArray.h"
21 struct SkDeviceProperties;
24 class SkGlyphCache_Globals;
26 /** \class SkGlyphCache
28 This class represents a strike: a specific combination of typeface, size,
29 matrix, etc., and holds the glyphs for that strike. Calling any of the
30 getUnichar.../getGlyphID... methods will return the requested glyph,
31 either instantly if it is already cached, or by first generating it and then
32 adding it to the strike.
34 The strikes are held in a global list, available to all threads. To interact
35 with one, call either VisitCache() or DetachCache().
39 /** Returns a glyph with valid fAdvance and fDevKern fields.
40 The remaining fields may be valid, but that is not guaranteed. If you
41 require those, call getUnicharMetrics or getGlyphIDMetrics instead.
43 const SkGlyph& getUnicharAdvance(SkUnichar);
44 const SkGlyph& getGlyphIDAdvance(uint16_t);
46 /** Returns a glyph with all fields valid except fImage and fPath, which
47 may be null. If they are null, call findImage or findPath for those.
48 If they are not null, then they are valid.
50 This call is potentially slower than the matching ...Advance call. If
51 you only need the fAdvance/fDevKern fields, call those instead.
53 const SkGlyph& getUnicharMetrics(SkUnichar);
54 const SkGlyph& getGlyphIDMetrics(uint16_t);
56 /** These are variants that take the device position of the glyph. Call
57 these only if you are drawing in subpixel mode. Passing 0, 0 is
58 effectively the same as calling the variants w/o the extra params, tho
61 const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y);
62 const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y);
64 /** Return the glyphID for the specified Unichar. If the char has already
65 been seen, use the existing cache entry. If not, ask the scalercontext
68 uint16_t unicharToGlyph(SkUnichar);
70 /** Map the glyph to its Unicode equivalent. Unmappable glyphs map to
71 a character code of zero.
73 SkUnichar glyphToUnichar(uint16_t);
75 /** Returns the number of glyphs for this strike.
77 unsigned getGlyphCount();
79 #ifdef SK_BUILD_FOR_ANDROID
80 /** Returns the base glyph count for this strike.
82 unsigned getBaseGlyphCount(SkUnichar charCode) const {
83 return fScalerContext->getBaseGlyphCount(charCode);
87 /** Return the image associated with the glyph. If it has not been generated
88 this will trigger that.
90 const void* findImage(const SkGlyph&);
91 /** Return the Path associated with the glyph. If it has not been generated
92 this will trigger that.
94 const SkPath* findPath(const SkGlyph&);
95 /** Return the distance field associated with the glyph. If it has not been generated
96 this will trigger that.
98 const void* findDistanceField(const SkGlyph&);
100 /** Return the vertical metrics for this strike.
102 const SkPaint::FontMetrics& getFontMetrics() const {
106 const SkDescriptor& getDescriptor() const { return *fDesc; }
108 SkMask::Format getMaskFormat() const {
109 return fScalerContext->getMaskFormat();
112 bool isSubpixel() const {
113 return fScalerContext->isSubpixel();
116 /* AuxProc/Data allow a client to associate data with this cache entry.
117 Multiple clients can use this, as their data is keyed with a function
118 pointer. In addition to serving as a key, the function pointer is called
119 with the data when the glyphcache object is deleted, so the client can
120 cleanup their data as well. NOTE: the auxProc must not try to access
121 this glyphcache in any way, since it may be in the process of being
125 //! If the proc is found, return true and set *dataPtr to its data
126 bool getAuxProcData(void (*auxProc)(void*), void** dataPtr) const;
127 //! Add a proc/data pair to the glyphcache. proc should be non-null
128 void setAuxProc(void (*auxProc)(void*), void* auxData);
130 SkScalerContext* getScalerContext() const { return fScalerContext; }
132 /** Call proc on all cache entries, stopping early if proc returns true.
133 The proc should not create or delete caches, since it could produce
136 static void VisitAllCaches(bool (*proc)(SkGlyphCache*, void*), void* ctx);
138 /** Find a matching cache entry, and call proc() with it. If none is found
139 create a new one. If the proc() returns true, detach the cache and
140 return it, otherwise leave it and return NULL.
142 static SkGlyphCache* VisitCache(SkTypeface*, const SkDescriptor* desc,
143 bool (*proc)(const SkGlyphCache*, void*),
146 /** Given a strike that was returned by either VisitCache() or DetachCache()
147 add it back into the global cache list (after which the caller should
148 not reference it anymore.
150 static void AttachCache(SkGlyphCache*);
152 /** Detach a strike from the global cache matching the specified descriptor.
153 Once detached, it can be queried/modified by the current thread, and
154 when finished, be reattached to the global cache with AttachCache().
155 While detached, if another request is made with the same descriptor,
156 a different strike will be generated. This is fine. It does mean we
157 can have more than 1 strike for the same descriptor, but that will
158 eventually get purged, and the win is that different thread will never
159 block each other while a strike is being used.
161 static SkGlyphCache* DetachCache(SkTypeface* typeface,
162 const SkDescriptor* desc) {
163 return VisitCache(typeface, desc, DetachProc, NULL);
167 void validate() const;
169 void validate() const {}
172 class AutoValidate : SkNoncopyable {
174 AutoValidate(const SkGlyphCache* cache) : fCache(cache) {
188 const SkGlyphCache* fCache;
192 // we take ownership of the scalercontext
193 SkGlyphCache(SkTypeface*, const SkDescriptor*, SkScalerContext*);
197 kJustAdvance_MetricsType,
201 SkGlyph* lookupMetrics(uint32_t id, MetricsType);
202 static bool DetachProc(const SkGlyphCache*, void*) { return true; }
204 SkGlyphCache* fNext, *fPrev;
206 SkScalerContext* fScalerContext;
207 SkPaint::FontMetrics fFontMetrics;
211 kHashCount = 1 << kHashBits,
212 kHashMask = kHashCount - 1
214 SkGlyph* fGlyphHash[kHashCount];
215 SkTDArray<SkGlyph*> fGlyphArray;
216 SkChunkAlloc fGlyphAlloc;
218 struct CharGlyphRec {
219 uint32_t fID; // unichar + subpixel
222 // no reason to use the same kHashCount as fGlyphHash, but we do for now
223 CharGlyphRec fCharToGlyphHash[kHashCount];
225 static inline unsigned ID2HashIndex(uint32_t id) {
228 return id & kHashMask;
231 // used to track (approx) how much ram is tied-up in this cache
236 void (*fProc)(void*);
239 AuxProcRec* fAuxProcList;
240 void invokeAndRemoveAuxProcs();
242 inline static SkGlyphCache* FindTail(SkGlyphCache* head);
244 friend class SkGlyphCache_Globals;
247 class SkAutoGlyphCache {
249 SkAutoGlyphCache(SkGlyphCache* cache) : fCache(cache) {}
250 SkAutoGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) {
251 fCache = SkGlyphCache::DetachCache(typeface, desc);
253 SkAutoGlyphCache(const SkPaint& paint,
254 const SkDeviceProperties* deviceProperties,
255 const SkMatrix* matrix) {
256 fCache = paint.detachCache(deviceProperties, matrix);
258 ~SkAutoGlyphCache() {
260 SkGlyphCache::AttachCache(fCache);
264 SkGlyphCache* getCache() const { return fCache; }
268 SkGlyphCache::AttachCache(fCache);
274 SkGlyphCache* fCache;
276 static bool DetachProc(const SkGlyphCache*, void*);
278 #define SkAutoGlyphCache(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCache)