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