読者です 読者をやめる 読者になる 読者になる

のねのBlog

パソコンやソフト開発で起きた問題など書きます。よろしくお願いします。

minikin HbFontCache

bFontCache* getFontCacheLocked() {
    ALOGD("[S] minikin/HbFontCache.cpp getFontCacheLocked");
    assertMinikinLocked();
    static HbFontCache* cache = nullptr;
    if (cache == nullptr) {
        cache = new HbFontCache();
    }
    ALOGD("[E] minikin/HbFontCache.cpp getFontCacheLocked");
    return cache;
}

Cross Reference: /frameworks/minikin/libs/minikin/HbFontCache.cpp

     47 class HbFontCache : private OnEntryRemoved<int32_t, hb_font_t*> {
     48 public:
     49     HbFontCache() : mCache(kMaxEntries) { <=コンストラクタ
     50         mCache.setOnEntryRemovedListener(this); <=削除時の関数を登録
     51     }
     52 
     53     // callback for OnEntryRemoved
     54     void operator()(int32_t& /* key */, hb_font_t*& value) {
     55         hb_font_destroy(value);
     56     }
     57 
     58     hb_font_t* get(int32_t fontId) {
     59         return mCache.get(fontId);
     60     }
     61 
     62     void put(int32_t fontId, hb_font_t* font) {
     63         mCache.put(fontId, font);
     64     }
     65 
     66     void clear() {
     67         mCache.clear();
     68     }
     69 
     70     void remove(int32_t fontId) {
     71         mCache.remove(fontId);
     72     }
     73 
     74 private:
     75     static const size_t kMaxEntries = 100;<==最大100なのかな?
     76 
     77     LruCache<int32_t, hb_font_t*> mCache; <==key:font_idとvalue:hb_font_tのキャッシュ
     78 };
     79 

Cross Reference: /frameworks/minikin/libs/minikin/HbFontCache.cpp

    100 // Returns a new reference to a hb_font_t object, caller is
    101 // responsible for calling hb_font_destroy() on it.
    102 hb_font_t* getHbFontLocked(MinikinFont* minikinFont) {
    103     assertMinikinLocked();
    104     // TODO: get rid of nullFaceFont
    105     static hb_font_t* nullFaceFont = nullptr;
    106     if (minikinFont == nullptr) {
    107         if (nullFaceFont == nullptr) {
    108             nullFaceFont = hb_font_create(nullptr);
    109         }
    110         return hb_font_reference(nullFaceFont);
    111     }
    112 
            /***** キャッシュ取得 *****/
    113     HbFontCache* fontCache = getFontCacheLocked();
            /***** KeyのfontId取得 *****/
    114     const int32_t fontId = minikinFont->GetUniqueId();
           /***** fontIdでキャッシュにあるか確認 *****/
    115     hb_font_t* font = fontCache->get(fontId);
    116     if (font != nullptr) {
          /***** キャッシュにあったとき *****/
    117         return hb_font_reference(font);
    118     }
    119 
      /***** キャッシュにないとき *****/
    120     hb_face_t* face;
            /***** 生データ取得 *****/
    121     const void* buf = minikinFont->GetFontData();
    122     if (buf == nullptr) {
        /***** データがない(NULL)とき *****/
    123         face = hb_face_create_for_tables(referenceTable, minikinFont, nullptr);
    124     } else {
        /***** データがあるとき *****/
    125         size_t size = minikinFont->GetFontSize();

    126         hb_blob_t* blob = hb_blob_create(
                    reinterpret_cast<const char*>(buf),
                    size,
    127             HB_MEMORY_MODE_READONLY,
                    nullptr,
                    nullptr);

    128         face = hb_face_create(blob, minikinFont->GetFontIndex());
    129         hb_blob_destroy(blob);
    130     }
            /*** なんで親なんだろう? *****/
    131     hb_font_t* parent_font = hb_font_create(face);
    132     hb_ot_font_set_funcs(parent_font);
    133 
    134     unsigned int upem = hb_face_get_upem(face);
    135     hb_font_set_scale(parent_font, upem, upem);
    136 
            /***** こっちは、子供だ。*****/
    137     font = hb_font_create_sub_font(parent_font);
    138     hb_font_destroy(parent_font);
    139     hb_face_destroy(face);
    140     fontCache->put(fontId, font);
    141     return hb_font_reference(font);
    142 }

Cross Reference: /frameworks/minikin/libs/minikin/HbFontCache.cpp

   /***** 親の作成 *****/
   1121 hb_font_t *
   1122 hb_font_create (hb_face_t *face) /* <=== hbのface */
   1123 {
   1124   hb_font_t *font;
   1125 
   1126   if (unlikely (!face))
          {
            /*** faceがNULLのとき ***/
   1127     face = hb_face_get_empty ();
          }

          /* font オブジェクト作成 */
   1128   if (!(font = hb_object_create<hb_font_t> ()))
          {
            /*** fontオブジェクトの作成失敗の時 ***/
   1129     return hb_font_get_empty ();
          }
   1130 
   1131   hb_face_make_immutable (face);
   1132   font->parent = hb_font_get_empty ();
   1133   font->face   = hb_face_reference (face);
   1134   font->klass  = hb_font_funcs_get_empty ();
   1135 
   1136   font->x_scale = font->y_scale = hb_face_get_upem (face);
   1137 
   1138   return font;
   1139 }

Cross Reference: /external/harfbuzz_ng/src/hb-font.cc

分岐予測のためのマクロらしい。

     77 #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
     78     #define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0)
     79     #define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1))
            /* 0との比較 */
     80     #define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0))
     81 #else
     82     #define likely(expr) (expr)
     83     #define unlikely(expr) (expr)
     84 #endif

Cross Reference: /external/harfbuzz_ng/src/hb-private.hh
ほげほげまん: likely / unlikely

子供の作成

   1152 hb_font_create_sub_font (hb_font_t *parent)
   1153 {
   1154   if (unlikely (!parent))
     {
   1155     parent = hb_font_get_empty ();
          }
   1156 
   1157   hb_font_t *font = hb_font_create (parent->face);
   1158 
   1159   if (unlikely (hb_object_is_inert (font)))
          {
   1160     return font;
          }
   1161 
   1162   font->parent = hb_font_reference (parent);
   1163 
   1164   font->x_scale = parent->x_scale;
   1165   font->y_scale = parent->y_scale;
   1166   font->x_ppem = parent->x_ppem;
   1167   font->y_ppem = parent->y_ppem;
   1168 
   1169   return font;
   1170 }
    144 template <typename Type>
    145 static inline bool hb_object_is_inert (const Type *obj)
    146 {
    147   return unlikely (obj->header.ref_count.is_inert ());
    148 }

Cross Reference: /external/harfbuzz_ng/src/hb-object-private.hh
ejje.weblio.jp

     54 struct hb_reference_count_t
     55 {
     56   hb_atomic_int_t ref_count;
     57 
     58   inline void init (int v) { ref_count.set_unsafe (v); }
     59   inline int get_unsafe (void) const {
              return ref_count.get_unsafe ();           
          }

     60   inline int inc (void) {      return ref_count.inc ();           }
     61   inline int dec (void) {      return ref_count.dec ();           }

     62   inline void finish (void) {
              ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); 
          }
     63 
     64   inline bool is_inert (void) const {
              return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; 
          }

     65   inline bool is_valid (void) const {
              return ref_count.get_unsafe () > 0; 
          }
     66 };
     67 

     48 /* reference_count */
     49 
     50 #define HB_REFERENCE_COUNT_INERT_VALUE  -1
     51 #define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
     52 #define HB_REFERENCE_COUNT_INIT         {HB_ATOMIC_INT_INIT(HB_REFERENCE_COUNT_INERT_VALUE)}
     53 

Cross Reference: /external/harfbuzz_ng/src/hb-object-private.hh

    174 struct hb_atomic_int_t
    175 {
    176   hb_atomic_int_impl_t v;
    177 
    178   inline void set_unsafe (int v_) { v = v_; }
    179   inline int  get_unsafe (void) const { return v; }
    180   inline int inc (void) { 
              return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v),  1); 
          }
    181   inline int dec (void) {
              return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v), -1); 
          }
    182 };
    183 

Cross Reference: /external/harfbuzz_ng/src/hb-atomic-private.hh