1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/* 3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project 4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * 5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file. 7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */ 8685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifndef SkGlyphCache_DEFINED 11bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SkGlyphCache_DEFINED 12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkBitmap.h" 14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkChunkAlloc.h" 15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkDescriptor.h" 161ef6e7aa2ca040bc9a47708d832f21e22ae474acbungeman@google.com#include "SkGlyph.h" 17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkScalerContext.h" 18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkTemplates.h" 197fe2414be8d83797ff0c450a79bc2de165171555mike@reedtribe.org#include "SkTDArray.h" 20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 214efd34721cb0e87078ae06a03cd905ba8e8b7c29bungeman@google.comstruct SkDeviceProperties; 22bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass SkPaint; 23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass SkGlyphCache_Globals; 25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/** \class SkGlyphCache 27bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 28bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com This class represents a strike: a specific combination of typeface, size, 29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com matrix, etc., and holds the glyphs for that strike. Calling any of the 30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com getUnichar.../getGlyphID... methods will return the requested glyph, 31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com either instantly if it is already cahced, or by first generating it and then 32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com adding it to the strike. 33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com The strikes are held in a global list, available to all threads. To interact 35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com with one, call either VisitCache() or DetachCache(). 36bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com*/ 37bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass SkGlyphCache { 38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic: 39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /** Returns a glyph with valid fAdvance and fDevKern fields. 40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com The remaining fields may be valid, but that is not guaranteed. If you 41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com require those, call getUnicharMetrics or getGlyphIDMetrics instead. 42bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkGlyph& getUnicharAdvance(SkUnichar); 44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkGlyph& getGlyphIDAdvance(uint16_t); 45b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /** Returns a glyph with all fields valid except fImage and fPath, which 47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com may be null. If they are null, call findImage or findPath for those. 48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com If they are not null, then they are valid. 49b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com This call is potentially slower than the matching ...Advance call. If 51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com you only need the fAdvance/fDevKern fields, call those instead. 52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkGlyph& getUnicharMetrics(SkUnichar); 54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkGlyph& getGlyphIDMetrics(uint16_t); 55b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /** These are variants that take the device position of the glyph. Call 57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com these only if you are drawing in subpixel mode. Passing 0, 0 is 58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com effectively the same as calling the variants w/o the extra params, tho 59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a tiny bit slower. 60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y); 62bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y); 63b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /** Return the glyphID for the specified Unichar. If the char has already 65bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com been seen, use the existing cache entry. If not, ask the scalercontext 66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com to compute it for us. 67bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint16_t unicharToGlyph(SkUnichar); 69b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 70739245e986d7a78b96129f559363b7ab6fb0a21creed@android.com /** Map the glyph to its Unicode equivalent. Unmappable glyphs map to 71739245e986d7a78b96129f559363b7ab6fb0a21creed@android.com a character code of zero. 72739245e986d7a78b96129f559363b7ab6fb0a21creed@android.com */ 73739245e986d7a78b96129f559363b7ab6fb0a21creed@android.com SkUnichar glyphToUnichar(uint16_t); 74739245e986d7a78b96129f559363b7ab6fb0a21creed@android.com 75019978975b2cb2b2cfe270c72b53db0326002401ctguil@chromium.org /** Returns the number of glyphs for this strike. 76019978975b2cb2b2cfe270c72b53db0326002401ctguil@chromium.org */ 77019978975b2cb2b2cfe270c72b53db0326002401ctguil@chromium.org unsigned getGlyphCount(); 78019978975b2cb2b2cfe270c72b53db0326002401ctguil@chromium.org 79f2e6b589ab62dc52807e27d02fed14d0bd77e82fdjsollen@google.com#ifdef SK_BUILD_FOR_ANDROID 80f2e6b589ab62dc52807e27d02fed14d0bd77e82fdjsollen@google.com /** Returns the base glyph count for this strike. 81f2e6b589ab62dc52807e27d02fed14d0bd77e82fdjsollen@google.com */ 82f2e6b589ab62dc52807e27d02fed14d0bd77e82fdjsollen@google.com unsigned getBaseGlyphCount(SkUnichar charCode) const { 83f2e6b589ab62dc52807e27d02fed14d0bd77e82fdjsollen@google.com return fScalerContext->getBaseGlyphCount(charCode); 84f2e6b589ab62dc52807e27d02fed14d0bd77e82fdjsollen@google.com } 85f2e6b589ab62dc52807e27d02fed14d0bd77e82fdjsollen@google.com#endif 86f2e6b589ab62dc52807e27d02fed14d0bd77e82fdjsollen@google.com 87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /** Return the image associated with the glyph. If it has not been generated 88bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this will trigger that. 89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 90bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const void* findImage(const SkGlyph&); 91bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /** Return the Path associated with the glyph. If it has not been generated 92bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this will trigger that. 93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkPath* findPath(const SkGlyph&); 95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /** Return the vertical metrics for this strike. 97bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 982f45f0074cf3f265711b74eb3a1d757ae4b2ce02reed@google.com const SkPaint::FontMetrics& getFontMetrics() const { 992f45f0074cf3f265711b74eb3a1d757ae4b2ce02reed@google.com return fFontMetrics; 100bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 101e216b62841acd5db9d91b63960805568259a2e0ereed@android.com 102e216b62841acd5db9d91b63960805568259a2e0ereed@android.com const SkDescriptor& getDescriptor() const { return *fDesc; } 103e216b62841acd5db9d91b63960805568259a2e0ereed@android.com 104b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com SkMask::Format getMaskFormat() const { 105b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com return fScalerContext->getMaskFormat(); 106b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com } 107b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 10825802794590081d85749a99ff8490b738d5161ffreed@google.com bool isSubpixel() const { 10925802794590081d85749a99ff8490b738d5161ffreed@google.com return fScalerContext->isSubpixel(); 11025802794590081d85749a99ff8490b738d5161ffreed@google.com } 11125802794590081d85749a99ff8490b738d5161ffreed@google.com 112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /* AuxProc/Data allow a client to associate data with this cache entry. 113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Multiple clients can use this, as their data is keyed with a function 114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com pointer. In addition to serving as a key, the function pointer is called 115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com with the data when the glyphcache object is deleted, so the client can 116bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cleanup their data as well. NOTE: the auxProc must not try to access 117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this glyphcache in any way, since it may be in the process of being 118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com deleted. 119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 120b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com //! If the proc is found, return true and set *dataPtr to its data 122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bool getAuxProcData(void (*auxProc)(void*), void** dataPtr) const; 123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com //! Add a proc/data pair to the glyphcache. proc should be non-null 124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void setAuxProc(void (*auxProc)(void*), void* auxData); 125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 126a49cfc38fbbd85f8024eb7880de129bf15c0b4d9djsollen@google.com SkScalerContext* getScalerContext() const { return fScalerContext; } 127a49cfc38fbbd85f8024eb7880de129bf15c0b4d9djsollen@google.com 128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /** Call proc on all cache entries, stopping early if proc returns true. 129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com The proc should not create or delete caches, since it could produce 130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com deadlock. 131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static void VisitAllCaches(bool (*proc)(SkGlyphCache*, void*), void* ctx); 133b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /** Find a matching cache entry, and call proc() with it. If none is found 135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com create a new one. If the proc() returns true, detach the cache and 136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return it, otherwise leave it and return NULL. 137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 13878341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.com static SkGlyphCache* VisitCache(SkTypeface*, const SkDescriptor* desc, 139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bool (*proc)(const SkGlyphCache*, void*), 140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void* context); 141b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /** Given a strike that was returned by either VisitCache() or DetachCache() 143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com add it back into the global cache list (after which the caller should 144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com not reference it anymore. 145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static void AttachCache(SkGlyphCache*); 147bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /** Detach a strike from the global cache matching the specified descriptor. 149bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Once detached, it can be queried/modified by the current thread, and 150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com when finished, be reattached to the global cache with AttachCache(). 151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com While detached, if another request is made with the same descriptor, 152bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a different strike will be generated. This is fine. It does mean we 153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com can have more than 1 strike for the same descriptor, but that will 154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com eventually get purged, and the win is that different thread will never 155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com block each other while a strike is being used. 156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 15778341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.com static SkGlyphCache* DetachCache(SkTypeface* typeface, 15878341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.com const SkDescriptor* desc) { 15978341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.com return VisitCache(typeface, desc, DetachProc, NULL); 160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 162e216b62841acd5db9d91b63960805568259a2e0ereed@android.com#ifdef SK_DEBUG 163e216b62841acd5db9d91b63960805568259a2e0ereed@android.com void validate() const; 164e216b62841acd5db9d91b63960805568259a2e0ereed@android.com#else 165e216b62841acd5db9d91b63960805568259a2e0ereed@android.com void validate() const {} 166e216b62841acd5db9d91b63960805568259a2e0ereed@android.com#endif 167e216b62841acd5db9d91b63960805568259a2e0ereed@android.com 168e216b62841acd5db9d91b63960805568259a2e0ereed@android.com class AutoValidate : SkNoncopyable { 169e216b62841acd5db9d91b63960805568259a2e0ereed@android.com public: 170e216b62841acd5db9d91b63960805568259a2e0ereed@android.com AutoValidate(const SkGlyphCache* cache) : fCache(cache) { 171e216b62841acd5db9d91b63960805568259a2e0ereed@android.com if (fCache) { 172e216b62841acd5db9d91b63960805568259a2e0ereed@android.com fCache->validate(); 173e216b62841acd5db9d91b63960805568259a2e0ereed@android.com } 174e216b62841acd5db9d91b63960805568259a2e0ereed@android.com } 175e216b62841acd5db9d91b63960805568259a2e0ereed@android.com ~AutoValidate() { 176e216b62841acd5db9d91b63960805568259a2e0ereed@android.com if (fCache) { 177e216b62841acd5db9d91b63960805568259a2e0ereed@android.com fCache->validate(); 178e216b62841acd5db9d91b63960805568259a2e0ereed@android.com } 179e216b62841acd5db9d91b63960805568259a2e0ereed@android.com } 180e216b62841acd5db9d91b63960805568259a2e0ereed@android.com void forget() { 181e216b62841acd5db9d91b63960805568259a2e0ereed@android.com fCache = NULL; 182e216b62841acd5db9d91b63960805568259a2e0ereed@android.com } 183e216b62841acd5db9d91b63960805568259a2e0ereed@android.com private: 184e216b62841acd5db9d91b63960805568259a2e0ereed@android.com const SkGlyphCache* fCache; 185e216b62841acd5db9d91b63960805568259a2e0ereed@android.com }; 186b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate: 18842eacd7f693510758d71fdb07805a240d6176372reed@google.com // we take ownership of the scalercontext 18942eacd7f693510758d71fdb07805a240d6176372reed@google.com SkGlyphCache(SkTypeface*, const SkDescriptor*, SkScalerContext*); 190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ~SkGlyphCache(); 191b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com enum MetricsType { 193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com kJustAdvance_MetricsType, 194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com kFull_MetricsType 195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com }; 196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyph* lookupMetrics(uint32_t id, MetricsType); 198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static bool DetachProc(const SkGlyphCache*, void*) { return true; } 199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 200bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void detach(SkGlyphCache** head) { 201bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fPrev) { 202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPrev->fNext = fNext; 203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *head = fNext; 205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 206bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fNext) { 207bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fNext->fPrev = fPrev; 208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 209bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPrev = fNext = NULL; 210bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 211b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 212bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void attachToHead(SkGlyphCache** head) { 213bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(NULL == fPrev && NULL == fNext); 214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (*head) { 215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com (*head)->fPrev = this; 216bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fNext = *head; 217bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 218bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *head = this; 219bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 220bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 221bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyphCache* fNext, *fPrev; 222bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDescriptor* fDesc; 223bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalerContext* fScalerContext; 2242f45f0074cf3f265711b74eb3a1d757ae4b2ce02reed@google.com SkPaint::FontMetrics fFontMetrics; 225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com enum { 2273fba7f811a7f7344b1132003eb7048884343a7acreed@google.com kHashBits = 8, 228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com kHashCount = 1 << kHashBits, 229bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com kHashMask = kHashCount - 1 230bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com }; 231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyph* fGlyphHash[kHashCount]; 232bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkTDArray<SkGlyph*> fGlyphArray; 233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkChunkAlloc fGlyphAlloc; 234b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int fMetricsCount, fAdvanceCount; 236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com struct CharGlyphRec { 238bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t fID; // unichar + subpixel 239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyph* fGlyph; 240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com }; 241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // no reason to use the same kHashCount as fGlyphHash, but we do for now 242bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com CharGlyphRec fCharToGlyphHash[kHashCount]; 243b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 244bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static inline unsigned ID2HashIndex(uint32_t id) { 24544b0009949b3b5d79999bdb0147496f05272308creed@google.com id ^= id >> 16; 24644b0009949b3b5d79999bdb0147496f05272308creed@google.com id ^= id >> 8; 24744b0009949b3b5d79999bdb0147496f05272308creed@google.com return id & kHashMask; 248bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 249b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // used to track (approx) how much ram is tied-up in this cache 251bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com size_t fMemoryUsed; 252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com struct AuxProcRec { 254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com AuxProcRec* fNext; 255bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void (*fProc)(void*); 256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void* fData; 257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com }; 258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com AuxProcRec* fAuxProcList; 259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void invokeAndRemoveAuxProcs(); 260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // This relies on the caller to have already acquired the mutex to access the global cache 262bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static size_t InternalFreeCache(SkGlyphCache_Globals*, size_t bytesNeeded); 263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com inline static SkGlyphCache* FindTail(SkGlyphCache* head); 265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 266bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com friend class SkGlyphCache_Globals; 267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass SkAutoGlyphCache { 270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic: 271bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkAutoGlyphCache(SkGlyphCache* cache) : fCache(cache) {} 27278341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.com SkAutoGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) { 27378341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.com fCache = SkGlyphCache::DetachCache(typeface, desc); 274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 2754efd34721cb0e87078ae06a03cd905ba8e8b7c29bungeman@google.com SkAutoGlyphCache(const SkPaint& paint, 2764efd34721cb0e87078ae06a03cd905ba8e8b7c29bungeman@google.com const SkDeviceProperties* deviceProperties, 2774efd34721cb0e87078ae06a03cd905ba8e8b7c29bungeman@google.com const SkMatrix* matrix) { 2784efd34721cb0e87078ae06a03cd905ba8e8b7c29bungeman@google.com fCache = paint.detachCache(deviceProperties, matrix); 279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 2804b3bf9c2c863ad28e883f6f8372f46d5876480f5mike@reedtribe.org ~SkAutoGlyphCache() { 2814b3bf9c2c863ad28e883f6f8372f46d5876480f5mike@reedtribe.org if (fCache) { 282bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyphCache::AttachCache(fCache); 2834b3bf9c2c863ad28e883f6f8372f46d5876480f5mike@reedtribe.org } 284bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 2864b3bf9c2c863ad28e883f6f8372f46d5876480f5mike@reedtribe.org SkGlyphCache* getCache() const { return fCache; } 287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 2884b3bf9c2c863ad28e883f6f8372f46d5876480f5mike@reedtribe.org void release() { 2894b3bf9c2c863ad28e883f6f8372f46d5876480f5mike@reedtribe.org if (fCache) { 290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyphCache::AttachCache(fCache); 291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fCache = NULL; 292bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 293bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 2944b3bf9c2c863ad28e883f6f8372f46d5876480f5mike@reedtribe.org 295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate: 296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyphCache* fCache; 297b41ee2a22d7d651c58c173955a5dbdec23f2da45reed@google.com 298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static bool DetachProc(const SkGlyphCache*, void*); 299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 301bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 302