DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (d8847129d134)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160

/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */



#include "SkTypefaceCache.h"
#include "SkThread.h"

#define TYPEFACE_CACHE_LIMIT    1024

SkTypefaceCache::SkTypefaceCache() {}

SkTypefaceCache::~SkTypefaceCache() {
    const Rec* curr = fArray.begin();
    const Rec* stop = fArray.end();
    while (curr < stop) {
        if (curr->fStrong) {
            curr->fFace->unref();
        } else {
            curr->fFace->weak_unref();
        }
        curr += 1;
    }
}

void SkTypefaceCache::add(SkTypeface* face,
                          SkTypeface::Style requestedStyle,
                          bool strong) {
    if (fArray.count() >= TYPEFACE_CACHE_LIMIT) {
        this->purge(TYPEFACE_CACHE_LIMIT >> 2);
    }

    Rec* rec = fArray.append();
    rec->fFace = face;
    rec->fRequestedStyle = requestedStyle;
    rec->fStrong = strong;
    if (strong) {
        face->ref();
    } else {
        face->weak_ref();
    }
}

SkTypeface* SkTypefaceCache::findByID(SkFontID fontID) const {
    const Rec* curr = fArray.begin();
    const Rec* stop = fArray.end();
    while (curr < stop) {
        if (curr->fFace->uniqueID() == fontID) {
            return curr->fFace;
        }
        curr += 1;
    }
    return NULL;
}

SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const {
    const Rec* curr = fArray.begin();
    const Rec* stop = fArray.end();
    while (curr < stop) {
        SkTypeface* currFace = curr->fFace;
        if (proc(currFace, curr->fRequestedStyle, ctx)) {
            if (curr->fStrong) {
                currFace->ref();
                return currFace;
            } else if (currFace->try_ref()) {
                return currFace;
            } else {
                //remove currFace from fArray?
            }
        }
        curr += 1;
    }
    return NULL;
}

void SkTypefaceCache::purge(int numToPurge) {
    int count = fArray.count();
    int i = 0;
    while (i < count) {
        SkTypeface* face = fArray[i].fFace;
        bool strong = fArray[i].fStrong;
        if ((strong && face->unique()) || (!strong && face->weak_expired())) {
            if (strong) {
                face->unref();
            } else {
                face->weak_unref();
            }
            fArray.remove(i);
            --count;
            if (--numToPurge == 0) {
                return;
            }
        } else {
            ++i;
        }
    }
}

void SkTypefaceCache::purgeAll() {
    this->purge(fArray.count());
}

///////////////////////////////////////////////////////////////////////////////

SkTypefaceCache& SkTypefaceCache::Get() {
    static SkTypefaceCache gCache;
    return gCache;
}

SkFontID SkTypefaceCache::NewFontID() {
    static int32_t gFontID;
    return sk_atomic_inc(&gFontID) + 1;
}

SK_DECLARE_STATIC_MUTEX(gMutex);

void SkTypefaceCache::Add(SkTypeface* face,
                          SkTypeface::Style requestedStyle,
                          bool strong) {
    SkAutoMutexAcquire ama(gMutex);
    Get().add(face, requestedStyle, strong);
}

SkTypeface* SkTypefaceCache::FindByID(SkFontID fontID) {
    SkAutoMutexAcquire ama(gMutex);
    return Get().findByID(fontID);
}

SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
    SkAutoMutexAcquire ama(gMutex);
    SkTypeface* typeface = Get().findByProcAndRef(proc, ctx);
    return typeface;
}

void SkTypefaceCache::PurgeAll() {
    SkAutoMutexAcquire ama(gMutex);
    Get().purgeAll();
}

///////////////////////////////////////////////////////////////////////////////

#ifdef SK_DEBUG
static bool DumpProc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
    SkDebugf("SkTypefaceCache: face %p fontID %d style %d refcnt %d\n",
             face, face->uniqueID(), style, face->getRefCnt());
    return false;
}
#endif

void SkTypefaceCache::Dump() {
#ifdef SK_DEBUG
    SkAutoMutexAcquire ama(gMutex);
    (void)Get().findByProcAndRef(DumpProc, NULL);
#endif
}