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 2139ab40115fae6d0c948e435233b3dd997ee7d8e5Mark Salyzyn#include <log/log.h> 22555d84c6f98eafcbe677cdcb8e9605760acd8ce5Mark Salyzyn#include <utils/LruCache.h> 23555d84c6f98eafcbe677cdcb8e9605760acd8ce5Mark Salyzyn 24fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#include <hb.h> 2589e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka#include <hb-ot.h> 26fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka 27fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#include <minikin/MinikinFont.h> 28fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka#include "MinikinInternal.h" 29fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka 3014e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonakanamespace minikin { 31fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka 3214e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonakaclass HbFontCache : private android::OnEntryRemoved<int32_t, hb_font_t*> { 33fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonakapublic: 3489e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka HbFontCache() : mCache(kMaxEntries) { 35fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka mCache.setOnEntryRemovedListener(this); 36fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka } 37fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka 38fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka // callback for OnEntryRemoved 3989e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka void operator()(int32_t& /* key */, hb_font_t*& value) { 4089e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka hb_font_destroy(value); 41fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka } 42fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka 4389e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka hb_font_t* get(int32_t fontId) { 44fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka return mCache.get(fontId); 45fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka } 46fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka 4789e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka void put(int32_t fontId, hb_font_t* font) { 4889e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka mCache.put(fontId, font); 49fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka } 50fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka 51fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka void clear() { 52fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka mCache.clear(); 53fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka } 54fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka 559afcc6e2bd4d89e4e1deb6e18c3c4daca4e114fdRaph Levien void remove(int32_t fontId) { 569afcc6e2bd4d89e4e1deb6e18c3c4daca4e114fdRaph Levien mCache.remove(fontId); 579afcc6e2bd4d89e4e1deb6e18c3c4daca4e114fdRaph Levien } 589afcc6e2bd4d89e4e1deb6e18c3c4daca4e114fdRaph Levien 59fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonakaprivate: 60fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka static const size_t kMaxEntries = 100; 61fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka 6214e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka android::LruCache<int32_t, hb_font_t*> mCache; 63fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka}; 64fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka 65fd4124c53399581dd94eac5a9749bc07b474a294Seigo NonakaHbFontCache* getFontCacheLocked() { 66fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka assertMinikinLocked(); 67fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka static HbFontCache* cache = nullptr; 68fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka if (cache == nullptr) { 69fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka cache = new HbFontCache(); 70fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka } 71fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka return cache; 72fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka} 73fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka 7489e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonakavoid purgeHbFontCacheLocked() { 75fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka assertMinikinLocked(); 76fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka getFontCacheLocked()->clear(); 77fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka} 78fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka 796c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonakavoid purgeHbFontLocked(const MinikinFont* minikinFont) { 80fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka assertMinikinLocked(); 81fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka const int32_t fontId = minikinFont->GetUniqueId(); 82fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka getFontCacheLocked()->remove(fontId); 839afcc6e2bd4d89e4e1deb6e18c3c4daca4e114fdRaph Levien} 849afcc6e2bd4d89e4e1deb6e18c3c4daca4e114fdRaph Levien 85aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien// Returns a new reference to a hb_font_t object, caller is 86aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien// responsible for calling hb_font_destroy() on it. 87dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonakahb_font_t* getHbFontLocked(const MinikinFont* minikinFont) { 88fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka assertMinikinLocked(); 89fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka // TODO: get rid of nullFaceFont 90fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka static hb_font_t* nullFaceFont = nullptr; 91fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka if (minikinFont == nullptr) { 92fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka if (nullFaceFont == nullptr) { 93fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka nullFaceFont = hb_font_create(nullptr); 94fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka } 95fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka return hb_font_reference(nullFaceFont); 96fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka } 97fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka 98fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka HbFontCache* fontCache = getFontCacheLocked(); 99fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka const int32_t fontId = minikinFont->GetUniqueId(); 100fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka hb_font_t* font = fontCache->get(fontId); 101fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka if (font != nullptr) { 102fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka return hb_font_reference(font); 103fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka } 104fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka 105fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka hb_face_t* face; 106fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka const void* buf = minikinFont->GetFontData(); 107fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka size_t size = minikinFont->GetFontSize(); 108fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka hb_blob_t* blob = hb_blob_create(reinterpret_cast<const char*>(buf), size, 109fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka HB_MEMORY_MODE_READONLY, nullptr, nullptr); 110fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka face = hb_face_create(blob, minikinFont->GetFontIndex()); 111fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka hb_blob_destroy(blob); 112fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka 113fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka hb_font_t* parent_font = hb_font_create(face); 114fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka hb_ot_font_set_funcs(parent_font); 115fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka 116fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka unsigned int upem = hb_face_get_upem(face); 117fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka hb_font_set_scale(parent_font, upem, upem); 118fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka 119fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka font = hb_font_create_sub_font(parent_font); 120fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka std::vector<hb_variation_t> variations; 121fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka for (const FontVariation& variation : minikinFont->GetAxes()) { 122fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka variations.push_back({variation.axisTag, variation.value}); 123fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka } 124fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka hb_font_set_variations(font, variations.data(), variations.size()); 125fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka hb_font_destroy(parent_font); 126fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka hb_face_destroy(face); 127fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka fontCache->put(fontId, font); 128fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka return hb_font_reference(font); 129fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka} 130fb0d396929e534a3686469b474d4f670864aa5acSeigo Nonaka 13114e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka} // namespace minikin 132