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