1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2011 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTypefaceCache.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkAtomics.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMutex.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define TYPEFACE_CACHE_LIMIT    1024
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkTypefaceCache::SkTypefaceCache() {}
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkTypefaceCache::add(SkTypeface* face) {
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (fTypefaces.count() >= TYPEFACE_CACHE_LIMIT) {
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->purge(TYPEFACE_CACHE_LIMIT >> 2);
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fTypefaces.emplace_back(SkRef(face));
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const {
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (const sk_sp<SkTypeface>& typeface : fTypefaces) {
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (proc(typeface.get(), ctx)) {
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return SkRef(typeface.get());
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return nullptr;
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkTypefaceCache::purge(int numToPurge) {
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int count = fTypefaces.count();
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int i = 0;
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (i < count) {
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fTypefaces[i]->unique()) {
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fTypefaces.removeShuffle(i);
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            --count;
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (--numToPurge == 0) {
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return;
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ++i;
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkTypefaceCache::purgeAll() {
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->purge(fTypefaces.count());
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkTypefaceCache& SkTypefaceCache::Get() {
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static SkTypefaceCache gCache;
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return gCache;
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkFontID SkTypefaceCache::NewFontID() {
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static int32_t gFontID;
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return sk_atomic_inc(&gFontID) + 1;
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSK_DECLARE_STATIC_MUTEX(gMutex);
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkTypefaceCache::Add(SkTypeface* face) {
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAutoMutexAcquire ama(gMutex);
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Get().add(face);
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAutoMutexAcquire ama(gMutex);
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return Get().findByProcAndRef(proc, ctx);
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkTypefaceCache::PurgeAll() {
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAutoMutexAcquire ama(gMutex);
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Get().purgeAll();
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool DumpProc(SkTypeface* face, void* ctx) {
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString n;
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    face->getFamilyName(&n);
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkFontStyle s = face->fontStyle();
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkFontID id = face->uniqueID();
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("SkTypefaceCache: face %p fontID %d weight %d width %d style %d refcnt %d name %s\n",
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot             face, id, s.weight(), s.width(), s.slant(), face->getRefCnt(), n.c_str());
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return false;
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkTypefaceCache::Dump() {
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    (void)Get().findByProcAndRef(DumpProc, nullptr);
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
103