• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "Minikin"
18 
19 #include "HbFontCache.h"
20 
21 #include <log/log.h>
22 #include <utils/LruCache.h>
23 
24 #include <hb-ot.h>
25 #include <hb.h>
26 
27 #include <minikin/MinikinFont.h>
28 #include "MinikinInternal.h"
29 
30 namespace minikin {
31 
32 class HbFontCache : private android::OnEntryRemoved<int32_t, hb_font_t*> {
33  public:
HbFontCache()34   HbFontCache() : mCache(kMaxEntries) {
35     mCache.setOnEntryRemovedListener(this);
36   }
37 
38   // callback for OnEntryRemoved
operator ()(int32_t &,hb_font_t * & value)39   void operator()(int32_t& /* key */, hb_font_t*& value) {
40     hb_font_destroy(value);
41   }
42 
get(int32_t fontId)43   hb_font_t* get(int32_t fontId) { return mCache.get(fontId); }
44 
put(int32_t fontId,hb_font_t * font)45   void put(int32_t fontId, hb_font_t* font) { mCache.put(fontId, font); }
46 
clear()47   void clear() { mCache.clear(); }
48 
remove(int32_t fontId)49   void remove(int32_t fontId) { mCache.remove(fontId); }
50 
51  private:
52   static const size_t kMaxEntries = 100;
53 
54   android::LruCache<int32_t, hb_font_t*> mCache;
55 };
56 
getFontCacheLocked()57 HbFontCache* getFontCacheLocked() {
58   assertMinikinLocked();
59   static HbFontCache* cache = nullptr;
60   if (cache == nullptr) {
61     cache = new HbFontCache();
62   }
63   return cache;
64 }
65 
purgeHbFontCacheLocked()66 void purgeHbFontCacheLocked() {
67   assertMinikinLocked();
68   getFontCacheLocked()->clear();
69 }
70 
purgeHbFontLocked(const MinikinFont * minikinFont)71 void purgeHbFontLocked(const MinikinFont* minikinFont) {
72   assertMinikinLocked();
73   const int32_t fontId = minikinFont->GetUniqueId();
74   getFontCacheLocked()->remove(fontId);
75 }
76 
77 // Returns a new reference to a hb_font_t object, caller is
78 // responsible for calling hb_font_destroy() on it.
getHbFontLocked(const MinikinFont * minikinFont)79 hb_font_t* getHbFontLocked(const MinikinFont* minikinFont) {
80   assertMinikinLocked();
81   // TODO: get rid of nullFaceFont
82   static hb_font_t* nullFaceFont = nullptr;
83   if (minikinFont == nullptr) {
84     if (nullFaceFont == nullptr) {
85       nullFaceFont = hb_font_create(nullptr);
86     }
87     return hb_font_reference(nullFaceFont);
88   }
89 
90   HbFontCache* fontCache = getFontCacheLocked();
91   const int32_t fontId = minikinFont->GetUniqueId();
92   hb_font_t* font = fontCache->get(fontId);
93   if (font != nullptr) {
94     return hb_font_reference(font);
95   }
96 
97   hb_face_t* face = minikinFont->CreateHarfBuzzFace();
98 
99   hb_font_t* parent_font = hb_font_create(face);
100   hb_ot_font_set_funcs(parent_font);
101 
102   unsigned int upem = hb_face_get_upem(face);
103   hb_font_set_scale(parent_font, upem, upem);
104 
105   font = hb_font_create_sub_font(parent_font);
106   std::vector<hb_variation_t> variations;
107   for (const FontVariation& variation : minikinFont->GetAxes()) {
108       variations.push_back({variation.axisTag, variation.value});
109   }
110   hb_font_set_variations(font, variations.data(), variations.size());
111   hb_font_destroy(parent_font);
112   hb_face_destroy(face);
113   fontCache->put(fontId, font);
114   return hb_font_reference(font);
115 }
116 
117 }  // namespace minikin
118