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    128
     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->getRefCnt() == 1) ||
     73             (!strong && face->weak_expired()))
     74         {
     75             if (strong) {
     76                 face->unref();
     77             } else {
     78                 face->weak_unref();
     79             }
     80             fArray.remove(i);
     81             --count;
     82             if (--numToPurge == 0) {
     83                 return;
     84             }
     85         } else {
     86             ++i;
     87         }
     88     }
     89 }
     90 
     91 void SkTypefaceCache::purgeAll() {
     92     this->purge(fArray.count());
     93 }
     94 
     95 ///////////////////////////////////////////////////////////////////////////////
     96 
     97 SkTypefaceCache& SkTypefaceCache::Get() {
     98     static SkTypefaceCache gCache;
     99     return gCache;
    100 }
    101 
    102 SkFontID SkTypefaceCache::NewFontID() {
    103     static int32_t gFontID;
    104     return sk_atomic_inc(&gFontID) + 1;
    105 }
    106 
    107 SK_DECLARE_STATIC_MUTEX(gMutex);
    108 
    109 void SkTypefaceCache::Add(SkTypeface* face,
    110                           SkTypeface::Style requestedStyle,
    111                           bool strong) {
    112     SkAutoMutexAcquire ama(gMutex);
    113     Get().add(face, requestedStyle, strong);
    114 }
    115 
    116 SkTypeface* SkTypefaceCache::FindByID(SkFontID fontID) {
    117     SkAutoMutexAcquire ama(gMutex);
    118     return Get().findByID(fontID);
    119 }
    120 
    121 SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
    122     SkAutoMutexAcquire ama(gMutex);
    123     SkTypeface* typeface = Get().findByProcAndRef(proc, ctx);
    124     return typeface;
    125 }
    126 
    127 void SkTypefaceCache::PurgeAll() {
    128     SkAutoMutexAcquire ama(gMutex);
    129     Get().purgeAll();
    130 }
    131 
    132 ///////////////////////////////////////////////////////////////////////////////
    133 
    134 #ifdef SK_DEBUG
    135 static bool DumpProc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
    136     SkDebugf("SkTypefaceCache: face %p fontID %d style %d refcnt %d\n",
    137              face, face->uniqueID(), style, face->getRefCnt());
    138     return false;
    139 }
    140 #endif
    141 
    142 void SkTypefaceCache::Dump() {
    143 #ifdef SK_DEBUG
    144     SkAutoMutexAcquire ama(gMutex);
    145     (void)Get().findByProcAndRef(DumpProc, NULL);
    146 #endif
    147 }
    148