HbFontCache.cpp revision 89e80237bc27af084c9ff316d4f47abf426eced8
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
1989e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka#include "HbFontCache.h"
20fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
21bae347682989d2627081310129a5b60541ed6ad0Seigo Nonaka#include <cutils/log.h>
22fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#include <hb.h>
2389e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka#include <hb-ot.h>
24fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#include <utils/LruCache.h>
25fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
26fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#include <minikin/MinikinFont.h>
27fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#include "MinikinInternal.h"
28fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
29fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonakanamespace android {
30fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
31bae347682989d2627081310129a5b60541ed6ad0Seigo Nonakastatic hb_blob_t* referenceTable(hb_face_t* /* face */, hb_tag_t tag, void* userData) {
32fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    MinikinFont* font = reinterpret_cast<MinikinFont*>(userData);
33fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    size_t length = 0;
34fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    bool ok = font->GetTable(tag, NULL, &length);
35fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    if (!ok) {
36fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        return 0;
37fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
38fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    char* buffer = reinterpret_cast<char*>(malloc(length));
39fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    if (!buffer) {
40fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        return 0;
41fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
42fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    ok = font->GetTable(tag, reinterpret_cast<uint8_t*>(buffer), &length);
43fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#ifdef VERBOSE_DEBUG
44bae347682989d2627081310129a5b60541ed6ad0Seigo Nonaka    ALOGD("referenceTable %c%c%c%c length=%zd %d",
45fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        (tag >>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, tag&0xff, length, ok);
46fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#endif
47fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    if (!ok) {
48fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        free(buffer);
49fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        return 0;
50fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
51fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    return hb_blob_create(const_cast<char*>(buffer), length,
52fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka            HB_MEMORY_MODE_WRITABLE, buffer, free);
53fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka}
54fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
5589e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonakaclass HbFontCache : private OnEntryRemoved<int32_t, hb_font_t*> {
56fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonakapublic:
5789e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    HbFontCache() : mCache(kMaxEntries) {
58fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        mCache.setOnEntryRemovedListener(this);
59fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
60fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
61fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    // callback for OnEntryRemoved
6289e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    void operator()(int32_t& /* key */, hb_font_t*& value) {
6389e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka        hb_font_destroy(value);
64fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
65fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
6689e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    hb_font_t* get(int32_t fontId) {
67fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        return mCache.get(fontId);
68fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
69fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
7089e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    void put(int32_t fontId, hb_font_t* font) {
7189e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka        mCache.put(fontId, font);
72fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
73fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
74fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    void clear() {
75fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka        mCache.clear();
76fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
77fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
78fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonakaprivate:
79fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    static const size_t kMaxEntries = 100;
80fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
8189e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    LruCache<int32_t, hb_font_t*> mCache;
82fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka};
83fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
8489e80237bc27af084c9ff316d4f47abf426eced8Seigo NonakaHbFontCache* getFontCacheLocked() {
85fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    assertMinikinLocked();
8689e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    static HbFontCache* cache = nullptr;
87fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    if (cache == nullptr) {
8889e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka        cache = new HbFontCache();
89fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
90fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    return cache;
91fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka}
92fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
9389e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonakavoid purgeHbFontCacheLocked() {
94fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    assertMinikinLocked();
9589e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    getFontCacheLocked()->clear();
96fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka}
97fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
9889e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonakahb_font_t* getHbFontLocked(MinikinFont* minikinFont) {
99fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    assertMinikinLocked();
10089e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    static hb_font_t* nullFaceFont = nullptr;
101fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    if (minikinFont == nullptr) {
10289e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka        if (nullFaceFont == nullptr) {
10389e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka            nullFaceFont = hb_font_create(nullptr);
10489e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka        }
10589e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka        return nullFaceFont;
106fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
107fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
10889e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    HbFontCache* fontCache = getFontCacheLocked();
109fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    const int32_t fontId = minikinFont->GetUniqueId();
11089e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    hb_font_t* font = fontCache->get(fontId);
11189e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    if (font != nullptr) {
11289e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka        return font;
113fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka    }
114fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
11589e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    hb_face_t* face = hb_face_create_for_tables(referenceTable, minikinFont, nullptr);
11689e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    hb_font_t* parent_font = hb_font_create(face);
11789e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    hb_ot_font_set_funcs(parent_font);
11889e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka
11989e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    unsigned int upem = hb_face_get_upem(face);
12089e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    hb_font_set_scale(parent_font, upem, upem);
12189e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka
12289e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    font = hb_font_create_sub_font(parent_font);
12389e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    hb_font_destroy(parent_font);
12489e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    hb_face_destroy(face);
12589e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    fontCache->put(fontId, font);
12689e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka    return font;
127fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka}
128fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka
129fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka}  // namespace android
130