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 SkTypefaceCache::SkTypefaceCache() {}
     17 
     18 SkTypefaceCache::~SkTypefaceCache() {
     19     const Rec* curr = fArray.begin();
     20     const Rec* stop = fArray.end();
     21     while (curr < stop) {
     22         curr->fFace->unref();
     23         curr += 1;
     24     }
     25 }
     26 
     27 void SkTypefaceCache::add(SkTypeface* face, const SkFontStyle& requestedStyle) {
     28     if (fArray.count() >= TYPEFACE_CACHE_LIMIT) {
     29         this->purge(TYPEFACE_CACHE_LIMIT >> 2);
     30     }
     31 
     32     Rec* rec = fArray.append();
     33     rec->fFace = SkRef(face);
     34     rec->fRequestedStyle = requestedStyle;
     35 }
     36 
     37 SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const {
     38     const Rec* curr = fArray.begin();
     39     const Rec* stop = fArray.end();
     40     while (curr < stop) {
     41         SkTypeface* currFace = curr->fFace;
     42         if (proc(currFace, curr->fRequestedStyle, ctx)) {
     43             return SkRef(currFace);
     44         }
     45         curr += 1;
     46     }
     47     return NULL;
     48 }
     49 
     50 void SkTypefaceCache::purge(int numToPurge) {
     51     int count = fArray.count();
     52     int i = 0;
     53     while (i < count) {
     54         SkTypeface* face = fArray[i].fFace;
     55         if (face->unique()) {
     56             face->unref();
     57             fArray.remove(i);
     58             --count;
     59             if (--numToPurge == 0) {
     60                 return;
     61             }
     62         } else {
     63             ++i;
     64         }
     65     }
     66 }
     67 
     68 void SkTypefaceCache::purgeAll() {
     69     this->purge(fArray.count());
     70 }
     71 
     72 ///////////////////////////////////////////////////////////////////////////////
     73 
     74 SkTypefaceCache& SkTypefaceCache::Get() {
     75     static SkTypefaceCache gCache;
     76     return gCache;
     77 }
     78 
     79 SkFontID SkTypefaceCache::NewFontID() {
     80     static int32_t gFontID;
     81     return sk_atomic_inc(&gFontID) + 1;
     82 }
     83 
     84 SK_DECLARE_STATIC_MUTEX(gMutex);
     85 
     86 void SkTypefaceCache::Add(SkTypeface* face, const SkFontStyle& requestedStyle) {
     87     SkAutoMutexAcquire ama(gMutex);
     88     Get().add(face, requestedStyle);
     89 }
     90 
     91 SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
     92     SkAutoMutexAcquire ama(gMutex);
     93     SkTypeface* typeface = Get().findByProcAndRef(proc, ctx);
     94     return typeface;
     95 }
     96 
     97 void SkTypefaceCache::PurgeAll() {
     98     SkAutoMutexAcquire ama(gMutex);
     99     Get().purgeAll();
    100 }
    101 
    102 ///////////////////////////////////////////////////////////////////////////////
    103 
    104 #ifdef SK_DEBUG
    105 static bool DumpProc(SkTypeface* face, const SkFontStyle& s, void* ctx) {
    106     SkDebugf("SkTypefaceCache: face %p fontID %d weight %d width %d style %d refcnt %d\n",
    107              face, face->uniqueID(), s.weight(), s.width(), s.slant(), face->getRefCnt());
    108     return false;
    109 }
    110 #endif
    111 
    112 void SkTypefaceCache::Dump() {
    113 #ifdef SK_DEBUG
    114     SkAutoMutexAcquire ama(gMutex);
    115     (void)Get().findByProcAndRef(DumpProc, NULL);
    116 #endif
    117 }
    118