HbFontCache.cpp revision fb0d396929e534a3686469b474d4f670864aa5ac
1fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka/*
2fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka * Copyright (C) 2015 The Android Open Source Project
3fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka *
4fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka * Licensed under the Apache License, Version 2.0 (the "License");
5fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka * you may not use this file except in compliance with the License.
6fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka * You may obtain a copy of the License at
7fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka *
8fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka *      http://www.apache.org/licenses/LICENSE-2.0
9fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka *
10fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka * Unless required by applicable law or agreed to in writing, software
11fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka * distributed under the License is distributed on an "AS IS" BASIS,
12fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka * See the License for the specific language governing permissions and
14fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka * limitations under the License.
15fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka */
16fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
17fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#define LOG_TAG "Minikin"
18fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
19fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#include "HbFaceCache.h"
20fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
21fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#include <hb.h>
22fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#include <utils/LruCache.h>
23fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
24fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#include <minikin/MinikinFont.h>
25fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#include "MinikinInternal.h"
26fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
27fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonakanamespace android {
28fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
29fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonakastatic hb_blob_t* referenceTable(hb_face_t* face, hb_tag_t tag, void* userData) {
30fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    MinikinFont* font = reinterpret_cast<MinikinFont*>(userData);
31fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    size_t length = 0;
32fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    bool ok = font->GetTable(tag, NULL, &length);
33fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    if (!ok) {
34fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        return 0;
35fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
36fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    char* buffer = reinterpret_cast<char*>(malloc(length));
37fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    if (!buffer) {
38fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        return 0;
39fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
40fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    ok = font->GetTable(tag, reinterpret_cast<uint8_t*>(buffer), &length);
41fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#ifdef VERBOSE_DEBUG
42fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    ALOGD("referenceTable %c%c%c%c length=%d %d",
43fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        (tag >>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, tag&0xff, length, ok);
44fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#endif
45fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    if (!ok) {
46fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        free(buffer);
47fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        return 0;
48fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
49fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    return hb_blob_create(const_cast<char*>(buffer), length,
50fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka            HB_MEMORY_MODE_WRITABLE, buffer, free);
51fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka}
52fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
53fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonakastatic unsigned int disabledDecomposeCompatibility(
54fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        hb_unicode_funcs_t*, hb_codepoint_t, hb_codepoint_t*, void*) {
55fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    return 0;
56fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka}
57fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
58fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonakaclass HbFaceCache : private OnEntryRemoved<int32_t, hb_face_t*> {
59fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonakapublic:
60fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    HbFaceCache() : mCache(kMaxEntries) {
61fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        mCache.setOnEntryRemovedListener(this);
62fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
63fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
64fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    // callback for OnEntryRemoved
65fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    void operator()(int32_t& key, hb_face_t*& value) {
66fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        hb_face_destroy(value);
67fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
68fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
69fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    hb_face_t* get(int32_t fontId) {
70fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        return mCache.get(fontId);
71fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
72fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
73fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    void put(int32_t fontId, hb_face_t* face) {
74fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        mCache.put(fontId, face);
75fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
76fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
77fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    void clear() {
78fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        mCache.clear();
79fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
80fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
81fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonakaprivate:
82fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    static const size_t kMaxEntries = 100;
83fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
84fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    LruCache<int32_t, hb_face_t*> mCache;
85fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka};
86fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
87fb0d396929e534a3686469b474d4f670864aa5acSeigo NonakaHbFaceCache* getFaceCacheLocked() {
88fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    assertMinikinLocked();
89fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    static HbFaceCache* cache = nullptr;
90fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    if (cache == nullptr) {
91fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        cache = new HbFaceCache();
92fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
93fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    return cache;
94fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka}
95fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
96fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonakavoid purgeHbFaceCacheLocked() {
97fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    assertMinikinLocked();
98fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    getFaceCacheLocked()->clear();
99fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka}
100fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
101fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonakahb_face_t* getHbFaceLocked(MinikinFont* minikinFont) {
102fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    assertMinikinLocked();
103fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    if (minikinFont == nullptr) {
104fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        return nullptr;
105fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
106fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
107fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    HbFaceCache* faceCache = getFaceCacheLocked();
108fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    const int32_t fontId = minikinFont->GetUniqueId();
109fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    hb_face_t* face = faceCache->get(fontId);
110fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    if (face != nullptr) {
111fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        return face;
112fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
113fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
114fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    face = hb_face_create_for_tables(referenceTable, minikinFont, nullptr);
115fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    faceCache->put(fontId, face);
116fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    return face;
117fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka}
118fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
119fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka}  // namespace android
120