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