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