Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      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 
     11 #include "SkTypefaceCache.h"
     12 #include "SkThread.h"
     13 
     14 #define TYPEFACE_CACHE_LIMIT    1024
     15 
     16 void SkTypefaceCache::add(SkTypeface* face,
     17                           SkTypeface::Style requestedStyle,
     18                           bool strong) {
     19     if (fArray.count() >= TYPEFACE_CACHE_LIMIT) {
     20         this->purge(TYPEFACE_CACHE_LIMIT >> 2);
     21     }
     22 
     23     Rec* rec = fArray.append();
     24     rec->fFace = face;
     25     rec->fRequestedStyle = requestedStyle;
     26     rec->fStrong = strong;
     27     if (strong) {
     28         face->ref();
     29     } else {
     30         face->weak_ref();
     31     }
     32 }
     33 
     34 SkTypeface* SkTypefaceCache::findByID(SkFontID fontID) const {
     35     const Rec* curr = fArray.begin();
     36     const Rec* stop = fArray.end();
     37     while (curr < stop) {
     38         if (curr->fFace->uniqueID() == fontID) {
     39             return curr->fFace;
     40         }
     41         curr += 1;
     42     }
     43     return NULL;
     44 }
     45 
     46 SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const {
     47     const Rec* curr = fArray.begin();
     48     const Rec* stop = fArray.end();
     49     while (curr < stop) {
     50         SkTypeface* currFace = curr->fFace;
     51         if (proc(currFace, curr->fRequestedStyle, ctx)) {
     52             if (curr->fStrong) {
     53                 currFace->ref();
     54                 return currFace;
     55             } else if (currFace->try_ref()) {
     56                 return currFace;
     57             } else {
     58                 //remove currFace from fArray?
     59             }
     60         }
     61         curr += 1;
     62     }
     63     return NULL;
     64 }
     65 
     66 void SkTypefaceCache::purge(int numToPurge) {
     67     int count = fArray.count();
     68     int i = 0;
     69     while (i < count) {
     70         SkTypeface* face = fArray[i].fFace;
     71         bool strong = fArray[i].fStrong;
     72         if ((strong && face->unique()) || (!strong && face->weak_expired())) {
     73             if (strong) {
     74                 face->unref();
     75             } else {
     76                 face->weak_unref();
     77             }
     78             fArray.remove(i);
     79             --count;
     80             if (--numToPurge == 0) {
     81                 return;
     82             }
     83         } else {
     84             ++i;
     85         }
     86     }
     87 }
     88 
     89 void SkTypefaceCache::purgeAll() {
     90     this->purge(fArray.count());
     91 }
     92 
     93 ///////////////////////////////////////////////////////////////////////////////
     94 
     95 SkTypefaceCache& SkTypefaceCache::Get() {
     96     static SkTypefaceCache gCache;
     97     return gCache;
     98 }
     99 
    100 SkFontID SkTypefaceCache::NewFontID() {
    101     static int32_t gFontID;
    102     return sk_atomic_inc(&gFontID) + 1;
    103 }
    104 
    105 SK_DECLARE_STATIC_MUTEX(gMutex);
    106 
    107 void SkTypefaceCache::Add(SkTypeface* face,
    108                           SkTypeface::Style requestedStyle,
    109                           bool strong) {
    110     SkAutoMutexAcquire ama(gMutex);
    111     Get().add(face, requestedStyle, strong);
    112 }
    113 
    114 SkTypeface* SkTypefaceCache::FindByID(SkFontID fontID) {
    115     SkAutoMutexAcquire ama(gMutex);
    116     return Get().findByID(fontID);
    117 }
    118 
    119 SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
    120     SkAutoMutexAcquire ama(gMutex);
    121     SkTypeface* typeface = Get().findByProcAndRef(proc, ctx);
    122     return typeface;
    123 }
    124 
    125 void SkTypefaceCache::PurgeAll() {
    126     SkAutoMutexAcquire ama(gMutex);
    127     Get().purgeAll();
    128 }
    129 
    130 ///////////////////////////////////////////////////////////////////////////////
    131 
    132 #ifdef SK_DEBUG
    133 static bool DumpProc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
    134     SkDebugf("SkTypefaceCache: face %p fontID %d style %d refcnt %d\n",
    135              face, face->uniqueID(), style, face->getRefCnt());
    136     return false;
    137 }
    138 #endif
    139 
    140 void SkTypefaceCache::Dump() {
    141 #ifdef SK_DEBUG
    142     SkAutoMutexAcquire ama(gMutex);
    143     (void)Get().findByProcAndRef(DumpProc, NULL);
    144 #endif
    145 }
    146