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