1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkGlyphCache.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,276 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#ifndef SkGlyphCache_DEFINED 1.14 +#define SkGlyphCache_DEFINED 1.15 + 1.16 +#include "SkBitmap.h" 1.17 +#include "SkChunkAlloc.h" 1.18 +#include "SkDescriptor.h" 1.19 +#include "SkGlyph.h" 1.20 +#include "SkScalerContext.h" 1.21 +#include "SkTemplates.h" 1.22 +#include "SkTDArray.h" 1.23 + 1.24 +struct SkDeviceProperties; 1.25 +class SkPaint; 1.26 + 1.27 +class SkGlyphCache_Globals; 1.28 + 1.29 +/** \class SkGlyphCache 1.30 + 1.31 + This class represents a strike: a specific combination of typeface, size, 1.32 + matrix, etc., and holds the glyphs for that strike. Calling any of the 1.33 + getUnichar.../getGlyphID... methods will return the requested glyph, 1.34 + either instantly if it is already cahced, or by first generating it and then 1.35 + adding it to the strike. 1.36 + 1.37 + The strikes are held in a global list, available to all threads. To interact 1.38 + with one, call either VisitCache() or DetachCache(). 1.39 +*/ 1.40 +class SkGlyphCache { 1.41 +public: 1.42 + /** Returns a glyph with valid fAdvance and fDevKern fields. 1.43 + The remaining fields may be valid, but that is not guaranteed. If you 1.44 + require those, call getUnicharMetrics or getGlyphIDMetrics instead. 1.45 + */ 1.46 + const SkGlyph& getUnicharAdvance(SkUnichar); 1.47 + const SkGlyph& getGlyphIDAdvance(uint16_t); 1.48 + 1.49 + /** Returns a glyph with all fields valid except fImage and fPath, which 1.50 + may be null. If they are null, call findImage or findPath for those. 1.51 + If they are not null, then they are valid. 1.52 + 1.53 + This call is potentially slower than the matching ...Advance call. If 1.54 + you only need the fAdvance/fDevKern fields, call those instead. 1.55 + */ 1.56 + const SkGlyph& getUnicharMetrics(SkUnichar); 1.57 + const SkGlyph& getGlyphIDMetrics(uint16_t); 1.58 + 1.59 + /** These are variants that take the device position of the glyph. Call 1.60 + these only if you are drawing in subpixel mode. Passing 0, 0 is 1.61 + effectively the same as calling the variants w/o the extra params, tho 1.62 + a tiny bit slower. 1.63 + */ 1.64 + const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y); 1.65 + const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y); 1.66 + 1.67 + /** Return the glyphID for the specified Unichar. If the char has already 1.68 + been seen, use the existing cache entry. If not, ask the scalercontext 1.69 + to compute it for us. 1.70 + */ 1.71 + uint16_t unicharToGlyph(SkUnichar); 1.72 + 1.73 + /** Map the glyph to its Unicode equivalent. Unmappable glyphs map to 1.74 + a character code of zero. 1.75 + */ 1.76 + SkUnichar glyphToUnichar(uint16_t); 1.77 + 1.78 + /** Returns the number of glyphs for this strike. 1.79 + */ 1.80 + unsigned getGlyphCount(); 1.81 + 1.82 +#ifdef SK_BUILD_FOR_ANDROID 1.83 + /** Returns the base glyph count for this strike. 1.84 + */ 1.85 + unsigned getBaseGlyphCount(SkUnichar charCode) const { 1.86 + return fScalerContext->getBaseGlyphCount(charCode); 1.87 + } 1.88 +#endif 1.89 + 1.90 + /** Return the image associated with the glyph. If it has not been generated 1.91 + this will trigger that. 1.92 + */ 1.93 + const void* findImage(const SkGlyph&); 1.94 + /** Return the Path associated with the glyph. If it has not been generated 1.95 + this will trigger that. 1.96 + */ 1.97 + const SkPath* findPath(const SkGlyph&); 1.98 + 1.99 + /** Return the vertical metrics for this strike. 1.100 + */ 1.101 + const SkPaint::FontMetrics& getFontMetrics() const { 1.102 + return fFontMetrics; 1.103 + } 1.104 + 1.105 + const SkDescriptor& getDescriptor() const { return *fDesc; } 1.106 + 1.107 + SkMask::Format getMaskFormat() const { 1.108 + return fScalerContext->getMaskFormat(); 1.109 + } 1.110 + 1.111 + bool isSubpixel() const { 1.112 + return fScalerContext->isSubpixel(); 1.113 + } 1.114 + 1.115 + /* AuxProc/Data allow a client to associate data with this cache entry. 1.116 + Multiple clients can use this, as their data is keyed with a function 1.117 + pointer. In addition to serving as a key, the function pointer is called 1.118 + with the data when the glyphcache object is deleted, so the client can 1.119 + cleanup their data as well. NOTE: the auxProc must not try to access 1.120 + this glyphcache in any way, since it may be in the process of being 1.121 + deleted. 1.122 + */ 1.123 + 1.124 + //! If the proc is found, return true and set *dataPtr to its data 1.125 + bool getAuxProcData(void (*auxProc)(void*), void** dataPtr) const; 1.126 + //! Add a proc/data pair to the glyphcache. proc should be non-null 1.127 + void setAuxProc(void (*auxProc)(void*), void* auxData); 1.128 + 1.129 + SkScalerContext* getScalerContext() const { return fScalerContext; } 1.130 + 1.131 + /** Call proc on all cache entries, stopping early if proc returns true. 1.132 + The proc should not create or delete caches, since it could produce 1.133 + deadlock. 1.134 + */ 1.135 + static void VisitAllCaches(bool (*proc)(SkGlyphCache*, void*), void* ctx); 1.136 + 1.137 + /** Find a matching cache entry, and call proc() with it. If none is found 1.138 + create a new one. If the proc() returns true, detach the cache and 1.139 + return it, otherwise leave it and return NULL. 1.140 + */ 1.141 + static SkGlyphCache* VisitCache(SkTypeface*, const SkDescriptor* desc, 1.142 + bool (*proc)(const SkGlyphCache*, void*), 1.143 + void* context); 1.144 + 1.145 + /** Given a strike that was returned by either VisitCache() or DetachCache() 1.146 + add it back into the global cache list (after which the caller should 1.147 + not reference it anymore. 1.148 + */ 1.149 + static void AttachCache(SkGlyphCache*); 1.150 + 1.151 + /** Detach a strike from the global cache matching the specified descriptor. 1.152 + Once detached, it can be queried/modified by the current thread, and 1.153 + when finished, be reattached to the global cache with AttachCache(). 1.154 + While detached, if another request is made with the same descriptor, 1.155 + a different strike will be generated. This is fine. It does mean we 1.156 + can have more than 1 strike for the same descriptor, but that will 1.157 + eventually get purged, and the win is that different thread will never 1.158 + block each other while a strike is being used. 1.159 + */ 1.160 + static SkGlyphCache* DetachCache(SkTypeface* typeface, 1.161 + const SkDescriptor* desc) { 1.162 + return VisitCache(typeface, desc, DetachProc, NULL); 1.163 + } 1.164 + 1.165 +#ifdef SK_DEBUG 1.166 + void validate() const; 1.167 +#else 1.168 + void validate() const {} 1.169 +#endif 1.170 + 1.171 + class AutoValidate : SkNoncopyable { 1.172 + public: 1.173 + AutoValidate(const SkGlyphCache* cache) : fCache(cache) { 1.174 + if (fCache) { 1.175 + fCache->validate(); 1.176 + } 1.177 + } 1.178 + ~AutoValidate() { 1.179 + if (fCache) { 1.180 + fCache->validate(); 1.181 + } 1.182 + } 1.183 + void forget() { 1.184 + fCache = NULL; 1.185 + } 1.186 + private: 1.187 + const SkGlyphCache* fCache; 1.188 + }; 1.189 + 1.190 +private: 1.191 + // we take ownership of the scalercontext 1.192 + SkGlyphCache(SkTypeface*, const SkDescriptor*, SkScalerContext*); 1.193 + ~SkGlyphCache(); 1.194 + 1.195 + enum MetricsType { 1.196 + kJustAdvance_MetricsType, 1.197 + kFull_MetricsType 1.198 + }; 1.199 + 1.200 + SkGlyph* lookupMetrics(uint32_t id, MetricsType); 1.201 + static bool DetachProc(const SkGlyphCache*, void*) { return true; } 1.202 + 1.203 + SkGlyphCache* fNext, *fPrev; 1.204 + SkDescriptor* fDesc; 1.205 + SkScalerContext* fScalerContext; 1.206 + SkPaint::FontMetrics fFontMetrics; 1.207 + 1.208 + enum { 1.209 + kHashBits = 8, 1.210 + kHashCount = 1 << kHashBits, 1.211 + kHashMask = kHashCount - 1 1.212 + }; 1.213 + SkGlyph* fGlyphHash[kHashCount]; 1.214 + SkTDArray<SkGlyph*> fGlyphArray; 1.215 + SkChunkAlloc fGlyphAlloc; 1.216 + 1.217 + struct CharGlyphRec { 1.218 + uint32_t fID; // unichar + subpixel 1.219 + SkGlyph* fGlyph; 1.220 + }; 1.221 + // no reason to use the same kHashCount as fGlyphHash, but we do for now 1.222 + CharGlyphRec fCharToGlyphHash[kHashCount]; 1.223 + 1.224 + static inline unsigned ID2HashIndex(uint32_t id) { 1.225 + id ^= id >> 16; 1.226 + id ^= id >> 8; 1.227 + return id & kHashMask; 1.228 + } 1.229 + 1.230 + // used to track (approx) how much ram is tied-up in this cache 1.231 + size_t fMemoryUsed; 1.232 + 1.233 + struct AuxProcRec { 1.234 + AuxProcRec* fNext; 1.235 + void (*fProc)(void*); 1.236 + void* fData; 1.237 + }; 1.238 + AuxProcRec* fAuxProcList; 1.239 + void invokeAndRemoveAuxProcs(); 1.240 + 1.241 + inline static SkGlyphCache* FindTail(SkGlyphCache* head); 1.242 + 1.243 + friend class SkGlyphCache_Globals; 1.244 +}; 1.245 + 1.246 +class SkAutoGlyphCache { 1.247 +public: 1.248 + SkAutoGlyphCache(SkGlyphCache* cache) : fCache(cache) {} 1.249 + SkAutoGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) { 1.250 + fCache = SkGlyphCache::DetachCache(typeface, desc); 1.251 + } 1.252 + SkAutoGlyphCache(const SkPaint& paint, 1.253 + const SkDeviceProperties* deviceProperties, 1.254 + const SkMatrix* matrix) { 1.255 + fCache = paint.detachCache(deviceProperties, matrix); 1.256 + } 1.257 + ~SkAutoGlyphCache() { 1.258 + if (fCache) { 1.259 + SkGlyphCache::AttachCache(fCache); 1.260 + } 1.261 + } 1.262 + 1.263 + SkGlyphCache* getCache() const { return fCache; } 1.264 + 1.265 + void release() { 1.266 + if (fCache) { 1.267 + SkGlyphCache::AttachCache(fCache); 1.268 + fCache = NULL; 1.269 + } 1.270 + } 1.271 + 1.272 +private: 1.273 + SkGlyphCache* fCache; 1.274 + 1.275 + static bool DetachProc(const SkGlyphCache*, void*); 1.276 +}; 1.277 +#define SkAutoGlyphCache(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCache) 1.278 + 1.279 +#endif