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 "SkGlyph.h" 17 #include "SkScalerContext.h" 18 #include "SkTemplates.h" 19 #include "SkTDArray.h" 20 21 struct SkDeviceProperties; 22 class SkPaint; 23 24 class SkGlyphCache_Globals; 25 26 /** \class SkGlyphCache 27 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. 33 34 The strikes are held in a global list, available to all threads. To interact 35 with one, call either VisitCache() or DetachCache(). 36 */ 37 class SkGlyphCache { 38 public: 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. 42 */ 43 const SkGlyph& getUnicharAdvance(SkUnichar); 44 const SkGlyph& getGlyphIDAdvance(uint16_t); 45 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. 49 50 This call is potentially slower than the matching ...Advance call. If 51 you only need the fAdvance/fDevKern fields, call those instead. 52 */ 53 const SkGlyph& getUnicharMetrics(SkUnichar); 54 const SkGlyph& getGlyphIDMetrics(uint16_t); 55 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 59 a tiny bit slower. 60 */ 61 const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y); 62 const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y); 63 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 66 to compute it for us. 67 */ 68 uint16_t unicharToGlyph(SkUnichar); 69 70 /** Map the glyph to its Unicode equivalent. Unmappable glyphs map to 71 a character code of zero. 72 */ 73 SkUnichar glyphToUnichar(uint16_t); 74 75 /** Returns the number of glyphs for this strike. 76 */ 77 unsigned getGlyphCount(); 78 79 /** Return the image associated with the glyph. If it has not been generated 80 this will trigger that. 81 */ 82 const void* findImage(const SkGlyph&); 83 /** Return the Path associated with the glyph. If it has not been generated 84 this will trigger that. 85 */ 86 const SkPath* findPath(const SkGlyph&); 87 /** Return the distance field associated with the glyph. If it has not been generated 88 this will trigger that. 89 */ 90 const void* findDistanceField(const SkGlyph&); 91 92 /** Return the vertical metrics for this strike. 93 */ 94 const SkPaint::FontMetrics& getFontMetrics() const { 95 return fFontMetrics; 96 } 97 98 const SkDescriptor& getDescriptor() const { return *fDesc; } 99 100 SkMask::Format getMaskFormat() const { 101 return fScalerContext->getMaskFormat(); 102 } 103 104 bool isSubpixel() const { 105 return fScalerContext->isSubpixel(); 106 } 107 108 /* AuxProc/Data allow a client to associate data with this cache entry. 109 Multiple clients can use this, as their data is keyed with a function 110 pointer. In addition to serving as a key, the function pointer is called 111 with the data when the glyphcache object is deleted, so the client can 112 cleanup their data as well. NOTE: the auxProc must not try to access 113 this glyphcache in any way, since it may be in the process of being 114 deleted. 115 */ 116 117 //! If the proc is found, return true and set *dataPtr to its data 118 bool getAuxProcData(void (*auxProc)(void*), void** dataPtr) const; 119 //! Add a proc/data pair to the glyphcache. proc should be non-null 120 void setAuxProc(void (*auxProc)(void*), void* auxData); 121 122 SkScalerContext* getScalerContext() const { return fScalerContext; } 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(SkTypeface*, 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 static SkGlyphCache* DetachCache(SkTypeface* typeface, 148 const SkDescriptor* desc) { 149 return VisitCache(typeface, desc, DetachProc, NULL); 150 } 151 152 #ifdef SK_DEBUG 153 void validate() const; 154 #else 155 void validate() const {} 156 #endif 157 158 class AutoValidate : SkNoncopyable { 159 public: 160 AutoValidate(const SkGlyphCache* cache) : fCache(cache) { 161 if (fCache) { 162 fCache->validate(); 163 } 164 } 165 ~AutoValidate() { 166 if (fCache) { 167 fCache->validate(); 168 } 169 } 170 void forget() { 171 fCache = NULL; 172 } 173 private: 174 const SkGlyphCache* fCache; 175 }; 176 177 private: 178 // we take ownership of the scalercontext 179 SkGlyphCache(SkTypeface*, const SkDescriptor*, SkScalerContext*); 180 ~SkGlyphCache(); 181 182 enum MetricsType { 183 kJustAdvance_MetricsType, 184 kFull_MetricsType 185 }; 186 187 SkGlyph* lookupMetrics(uint32_t id, MetricsType); 188 static bool DetachProc(const SkGlyphCache*, void*) { return true; } 189 190 SkGlyphCache* fNext, *fPrev; 191 SkDescriptor* fDesc; 192 SkScalerContext* fScalerContext; 193 SkPaint::FontMetrics fFontMetrics; 194 195 enum { 196 kHashBits = 8, 197 kHashCount = 1 << kHashBits, 198 kHashMask = kHashCount - 1 199 }; 200 SkGlyph* fGlyphHash[kHashCount]; 201 SkTDArray<SkGlyph*> fGlyphArray; 202 SkChunkAlloc fGlyphAlloc; 203 204 struct CharGlyphRec { 205 uint32_t fID; // unichar + subpixel 206 SkGlyph* fGlyph; 207 }; 208 // no reason to use the same kHashCount as fGlyphHash, but we do for now 209 CharGlyphRec fCharToGlyphHash[kHashCount]; 210 211 static inline unsigned ID2HashIndex(uint32_t id) { 212 id ^= id >> 16; 213 id ^= id >> 8; 214 return id & kHashMask; 215 } 216 217 // used to track (approx) how much ram is tied-up in this cache 218 size_t fMemoryUsed; 219 220 struct AuxProcRec { 221 AuxProcRec* fNext; 222 void (*fProc)(void*); 223 void* fData; 224 }; 225 AuxProcRec* fAuxProcList; 226 void invokeAndRemoveAuxProcs(); 227 228 inline static SkGlyphCache* FindTail(SkGlyphCache* head); 229 230 friend class SkGlyphCache_Globals; 231 }; 232 233 class SkAutoGlyphCacheBase { 234 public: 235 SkGlyphCache* getCache() const { return fCache; } 236 237 void release() { 238 if (fCache) { 239 SkGlyphCache::AttachCache(fCache); 240 fCache = NULL; 241 } 242 } 243 244 protected: 245 // Hide the constructors so we can't create one of these directly. 246 // Create SkAutoGlyphCache or SkAutoGlyphCacheNoCache instead. 247 SkAutoGlyphCacheBase(SkGlyphCache* cache) : fCache(cache) {} 248 SkAutoGlyphCacheBase(SkTypeface* typeface, const SkDescriptor* desc) { 249 fCache = SkGlyphCache::DetachCache(typeface, desc); 250 } 251 SkAutoGlyphCacheBase(const SkPaint& paint, 252 const SkDeviceProperties* deviceProperties, 253 const SkMatrix* matrix) { 254 fCache = NULL; 255 } 256 SkAutoGlyphCacheBase() { 257 fCache = NULL; 258 } 259 ~SkAutoGlyphCacheBase() { 260 if (fCache) { 261 SkGlyphCache::AttachCache(fCache); 262 } 263 } 264 265 SkGlyphCache* fCache; 266 267 private: 268 static bool DetachProc(const SkGlyphCache*, void*); 269 }; 270 271 class SkAutoGlyphCache : public SkAutoGlyphCacheBase { 272 public: 273 SkAutoGlyphCache(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {} 274 SkAutoGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) : 275 SkAutoGlyphCacheBase(typeface, desc) {} 276 SkAutoGlyphCache(const SkPaint& paint, 277 const SkDeviceProperties* deviceProperties, 278 const SkMatrix* matrix) { 279 fCache = paint.detachCache(deviceProperties, matrix, false); 280 } 281 282 private: 283 SkAutoGlyphCache() : SkAutoGlyphCacheBase() {} 284 }; 285 #define SkAutoGlyphCache(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCache) 286 287 class SkAutoGlyphCacheNoGamma : public SkAutoGlyphCacheBase { 288 public: 289 SkAutoGlyphCacheNoGamma(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {} 290 SkAutoGlyphCacheNoGamma(SkTypeface* typeface, const SkDescriptor* desc) : 291 SkAutoGlyphCacheBase(typeface, desc) {} 292 SkAutoGlyphCacheNoGamma(const SkPaint& paint, 293 const SkDeviceProperties* deviceProperties, 294 const SkMatrix* matrix) { 295 fCache = paint.detachCache(deviceProperties, matrix, true); 296 } 297 298 private: 299 SkAutoGlyphCacheNoGamma() : SkAutoGlyphCacheBase() {} 300 }; 301 #define SkAutoGlyphCacheNoGamma(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCacheNoGamma) 302 303 #endif 304