HbFontCache.cpp revision bae347682989d2627081310129a5b60541ed6ad0
16df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui/*
26df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * Copyright (C) 2015 The Android Open Source Project
36df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui *
46df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * Licensed under the Apache License, Version 2.0 (the "License");
56df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * you may not use this file except in compliance with the License.
66df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * You may obtain a copy of the License at
76df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui *
86df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui *      http://www.apache.org/licenses/LICENSE-2.0
96df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui *
106df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * Unless required by applicable law or agreed to in writing, software
116df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * distributed under the License is distributed on an "AS IS" BASIS,
126df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * See the License for the specific language governing permissions and
146df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * limitations under the License.
156df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui */
166df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
176df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#define LOG_TAG "Minikin"
186df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
19377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT#include "HbFaceCache.h"
20c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen
21c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen#include <cutils/log.h>
22c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen#include <hb.h>
236df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <utils/LruCache.h>
246df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
256df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <minikin/MinikinFont.h>
261b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include "MinikinInternal.h"
276df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
286df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuinamespace android {
296df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
306df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuistatic hb_blob_t* referenceTable(hb_face_t* /* face */, hb_tag_t tag, void* userData) {
316df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    MinikinFont* font = reinterpret_cast<MinikinFont*>(userData);
326df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    size_t length = 0;
336df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool ok = font->GetTable(tag, NULL, &length);
346df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    if (!ok) {
356df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        return 0;
366df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
376df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    char* buffer = reinterpret_cast<char*>(malloc(length));
386df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    if (!buffer) {
396df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        return 0;
406df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
416df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    ok = font->GetTable(tag, reinterpret_cast<uint8_t*>(buffer), &length);
426df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#ifdef VERBOSE_DEBUG
436df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    ALOGD("referenceTable %c%c%c%c length=%zd %d",
446df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        (tag >>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, tag&0xff, length, ok);
456df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#endif
460ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar    if (!ok) {
476df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        free(buffer);
486df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        return 0;
496df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
506df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    return hb_blob_create(const_cast<char*>(buffer), length,
516df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            HB_MEMORY_MODE_WRITABLE, buffer, free);
526df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui}
536df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
546df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuiclass HbFaceCache : private OnEntryRemoved<int32_t, hb_face_t*> {
556df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuipublic:
566df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    HbFaceCache() : mCache(kMaxEntries) {
576df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        mCache.setOnEntryRemovedListener(this);
586df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
596df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
606df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    // callback for OnEntryRemoved
616df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    void operator()(int32_t& /* key */, hb_face_t*& value) {
626df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        hb_face_destroy(value);
63e0fb528f8e3bbab04620c8534177168b358e837bztenghui    }
640ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar
650ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar    hb_face_t* get(int32_t fontId) {
666df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        return mCache.get(fontId);
671b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
686df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
696df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    void put(int32_t fontId, hb_face_t* face) {
706df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        mCache.put(fontId, face);
716df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
726df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
736df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    void clear() {
746df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        mCache.clear();
756df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
766df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
776df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuiprivate:
786df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    static const size_t kMaxEntries = 100;
79c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen
80c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen    LruCache<int32_t, hb_face_t*> mCache;
81c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen};
82c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen
83c6ac859f5a82ea8642bc6351a45508a15f224f32Marco NelissenHbFaceCache* getFaceCacheLocked() {
84c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen    assertMinikinLocked();
850ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar    static HbFaceCache* cache = nullptr;
86c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen    if (cache == nullptr) {
876df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        cache = new HbFaceCache();
886df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
896df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    return cache;
906df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui}
916df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
926df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuivoid purgeHbFaceCacheLocked() {
936df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    assertMinikinLocked();
946df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    getFaceCacheLocked()->clear();
956df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui}
966df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
976df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuihb_face_t* getHbFaceLocked(MinikinFont* minikinFont) {
986df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    assertMinikinLocked();
996df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    if (minikinFont == nullptr) {
1006df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        return nullptr;
1016df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
1026df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1036df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    HbFaceCache* faceCache = getFaceCacheLocked();
1046df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    const int32_t fontId = minikinFont->GetUniqueId();
1056df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    hb_face_t* face = faceCache->get(fontId);
1066df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    if (face != nullptr) {
1076df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        return face;
1086df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
1096df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1106df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    face = hb_face_create_for_tables(referenceTable, minikinFont, nullptr);
1116df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    faceCache->put(fontId, face);
1126df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    return face;
1136df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui}
1146df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1156df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui}  // namespace android
1166df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui