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 "SkAtomics.h"
     13 #include "SkMutex.h"
     14 
     15 #define TYPEFACE_CACHE_LIMIT    1024
     16 
     17 SkTypefaceCache::SkTypefaceCache() {}
     18 
     19 SkTypefaceCache::~SkTypefaceCache() {
     20     const Rec* curr = fArray.begin();
     21     const Rec* stop = fArray.end();
     22     while (curr < stop) {
     23         curr->fFace->unref();
     24         curr += 1;
     25     }
     26 }
     27 
     28 void SkTypefaceCache::add(SkTypeface* face, const SkFontStyle& requestedStyle) {
     29     if (fArray.count() >= TYPEFACE_CACHE_LIMIT) {
     30         this->purge(TYPEFACE_CACHE_LIMIT >> 2);
     31     }
     32 
     33     Rec* rec = fArray.append();
     34     rec->fFace = SkRef(face);
     35     rec->fRequestedStyle = requestedStyle;
     36 }
     37 
     38 SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const {
     39     const Rec* curr = fArray.begin();
     40     const Rec* stop = fArray.end();
     41     while (curr < stop) {
     42         SkTypeface* currFace = curr->fFace;
     43         if (proc(currFace, curr->fRequestedStyle, ctx)) {
     44             return SkRef(currFace);
     45         }
     46         curr += 1;
     47     }
     48     return nullptr;
     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 (face->unique()) {
     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, const SkFontStyle& requestedStyle) {
     88     SkAutoMutexAcquire ama(gMutex);
     89     Get().add(face, requestedStyle);
     90 }
     91 
     92 SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
     93     SkAutoMutexAcquire ama(gMutex);
     94     SkTypeface* typeface = Get().findByProcAndRef(proc, ctx);
     95     return typeface;
     96 }
     97 
     98 void SkTypefaceCache::PurgeAll() {
     99     SkAutoMutexAcquire ama(gMutex);
    100     Get().purgeAll();
    101 }
    102 
    103 ///////////////////////////////////////////////////////////////////////////////
    104 
    105 #ifdef SK_DEBUG
    106 static bool DumpProc(SkTypeface* face, const SkFontStyle& s, void* ctx) {
    107     SkDebugf("SkTypefaceCache: face %p fontID %d weight %d width %d style %d refcnt %d\n",
    108              face, face->uniqueID(), s.weight(), s.width(), s.slant(), face->getRefCnt());
    109     return false;
    110 }
    111 #endif
    112 
    113 void SkTypefaceCache::Dump() {
    114 #ifdef SK_DEBUG
    115     SkAutoMutexAcquire ama(gMutex);
    116     (void)Get().findByProcAndRef(DumpProc, nullptr);
    117 #endif
    118 }
    119