のねのBlog

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

MinikinFont

    100 class MinikinFont : public MinikinRefCounted {
    101 public:
    102     MinikinFont(int32_t uniqueId) : mUniqueId(uniqueId) {}
    103 
    104     virtual ~MinikinFont();
    105 
    106     virtual float GetHorizontalAdvance(uint32_t glyph_id,
    107         const MinikinPaint &paint) const = 0;
    108 
    109     virtual void GetBounds(MinikinRect* bounds, uint32_t glyph_id,
    110         const MinikinPaint &paint) const = 0;
    111 
    112     virtual const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy) = 0;
    113 
    114     // Override if font can provide access to raw data
    115     virtual const void* GetFontData() const {
    116         return nullptr;
    117     }
    118 
    119     // Override if font can provide access to raw data
    120     virtual size_t GetFontSize() const {
    121         return 0;
    122     }
    123 
    124     // Override if font can provide access to raw data.
    125     // Returns index within OpenType collection
    126     virtual int GetFontIndex() const {
    127         return 0;
    128     }
    129 
    130     static uint32_t MakeTag(char c1, char c2, char c3, char c4) {
    131         return ((uint32_t)c1 << 24) | ((uint32_t)c2 << 16) |
    132             ((uint32_t)c3 << 8) | (uint32_t)c4;
    133     }
    134 
    135     int32_t GetUniqueId() const { return mUniqueId; }

    136 private:
    137     const int32_t mUniqueId; <==IDしかないのか。
    138 };

Cross Reference: /frameworks/minikin/include/minikin/MinikinFont.h

     28 class ANDROID_API MinikinFontSkia : public MinikinFont {
     29 public:
     30     // Note: this takes ownership of the reference (will unref on dtor)
     31     explicit MinikinFontSkia(SkTypeface *typeface, const void* fontData, size_t fontSize,
     32         int ttcIndex);
     33 
     34     ~MinikinFontSkia();
     35 
     36     float GetHorizontalAdvance(uint32_t glyph_id,
     37         const MinikinPaint &paint) const;
     38 
     39     void GetBounds(MinikinRect* bounds, uint32_t glyph_id,
     40         const MinikinPaint &paint) const;
     41 
     42     const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy);
     43 
     44     SkTypeface* GetSkTypeface() const;
     45 
     46     // Access to underlying raw font bytes
     47     const void* GetFontData() const;
     48     size_t GetFontSize() const;
     49     int GetFontIndex() const;
     50 
     51     static uint32_t packPaintFlags(const SkPaint* paint);
     52     static void unpackPaintFlags(SkPaint* paint, uint32_t paintFlags);
     53 
     54     // set typeface and fake bold/italic parameters
     55     static void populateSkPaint(SkPaint* paint, const MinikinFont* font, FontFakery fakery);
     56 private:
     57     SkTypeface* mTypeface;
     58 
     59     // A raw pointer to the font data - it should be owned by some other object with
     60     // lifetime at least as long as this object.
     61     const void* mFontData;
     62     size_t mFontSize;
     63     int mTtcIndex;
     64 };

Cross Reference: /frameworks/base/libs/hwui/hwui/MinikinSkia.h


MinikinFontSkiaを使っているところ、その1

     56 static jboolean addSkTypeface(
                            FontFamily* family,
                            SkTypeface* face,
                            const void* fontData,
     57                     size_t      fontSize,
                            int         ttcIndex) 
        {
     58     MinikinFont* minikinFont = new MinikinFontSkia(
                                           face,
                                           fontData,
                                           fontSize,
                                           ttcIndex);
     59     bool result = family->addFont(minikinFont);
     60     minikinFont->Unref();
     61     return result;
     62 }

Cross Reference: /frameworks/base/core/jni/android/graphics/FontFamily.cpp


MinikinFontSkiaを使っているところ、その2

    128 static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong familyPtr,
    129         jobject font, jint ttcIndex, jobject listOfAxis, jint weight, jboolean isItalic) {
    130     NPE_CHECK_RETURN_ZERO(env, font);
    131 
    132     // Declare axis native type.
    133     std::unique_ptr<SkFontMgr::FontParameters::Axis[]> skiaAxes;
    134     int skiaAxesLength = 0;
    135     if (listOfAxis) {
    136         jint listSize = env->CallIntMethod(listOfAxis, gListClassInfo.mSize);
    137 
    138         skiaAxes.reset(new SkFontMgr::FontParameters::Axis[listSize]);
    139         skiaAxesLength = listSize;
    140         for (jint i = 0; i < listSize; ++i) {
    141             jobject axisObject = env->CallObjectMethod(listOfAxis, gListClassInfo.mGet, i);
    142             if (!axisObject) {
    143                 skiaAxes[i].fTag = 0;
    144                 skiaAxes[i].fStyleValue = 0;
    145                 continue;
    146             }
    147 
    148             jint tag = env->GetIntField(axisObject, gAxisClassInfo.mTag);
    149             jfloat stylevalue = env->GetFloatField(axisObject, gAxisClassInfo.mStyleValue);
    150             skiaAxes[i].fTag = tag;
    151             skiaAxes[i].fStyleValue = SkFloatToScalar(stylevalue);
    152         }
    153     }
    154 
    155     const void* fontPtr = env->GetDirectBufferAddress(font);
    156     if (fontPtr == NULL) {
    157         ALOGE("addFont failed to create font, buffer invalid");
    158         return false;
    159     }
    160     jlong fontSize = env->GetDirectBufferCapacity(font);
    161     if (fontSize < 0) {
    162         ALOGE("addFont failed to create font, buffer size invalid");
    163         return false;
    164     }
    165     jobject fontRef = MakeGlobalRefOrDie(env, font);
    166     SkAutoTUnref<SkData> data(SkData::NewWithProc(fontPtr, fontSize,
    167             release_global_ref, reinterpret_cast<void*>(fontRef)));
    168     std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(data));
    169 
    170     SkFontMgr::FontParameters params;
    171     params.setCollectionIndex(ttcIndex);
    172     params.setAxes(skiaAxes.get(), skiaAxesLength);
    173 
    174     SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
    175     SkTypeface* face = fm->createFromStream(fontData.release(), params);
    176     if (face == NULL) {
    177         ALOGE("addFont failed to create font, invalid request");
    178         return false;
    179     }
    180     FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
    181     MinikinFont* minikinFont = new MinikinFontSkia(
                face,
                fontPtr,
                (size_t)fontSize,
                ttcIndex);
    182     fontFamily->addFont(minikinFont, FontStyle(weight / 100, isItalic));
    183     minikinFont->Unref();
    184     return true;
    185 }

Cross Reference: /frameworks/base/core/jni/android/graphics/FontFamily.cpp

     96 struct hb_font_t {
     97   hb_object_header_t header;
     98   ASSERT_POD ();
     99 
    100   hb_bool_t immutable;
    101 
    102   hb_font_t *parent;
    103   hb_face_t *face;
    104 
    105   int x_scale;
    106   int y_scale;
    107 
    108   unsigned int x_ppem;
    109   unsigned int y_ppem;
    110 
    111   hb_font_funcs_t   *klass;
    112   void              *user_data;
    113   hb_destroy_func_t  destroy;
    114 
    115   struct hb_shaper_data_t shaper_data;

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

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

Minikin getFontTable

     80 bool FontFamily::addFont(MinikinFont* typeface) {
     81     AutoMutex _l(gMinikinLock);

     82     const uint32_t os2Tag = MinikinFont::MakeTag('O', 'S', '/', '2');


     83     HbBlob os2Table(getFontTable(typeface, os2Tag));


     84     if (os2Table.get() == nullptr) return false;
     85     int weight;
     86     bool italic;
     87     if (analyzeStyle(os2Table.get(), os2Table.size(), &weight, &italic)) {
     88         //ALOGD("analyzed weight = %d, italic = %s", weight, italic ? "true" : "false");
     89         FontStyle style(weight, italic);
     90         addFontLocked(typeface, style);
     91         return true;
     92     } else {
     93         ALOGD("failed to analyze style");
     94     }
     95     return false;
     96 }

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

    172 const SparseBitSet* FontFamily::getCoverage() {
    173     if (!mCoverageValid) {
    174         const FontStyle defaultStyle;

    175         MinikinFont* typeface = getClosestMatch(defaultStyle).font;

    176         const uint32_t cmapTag = MinikinFont::MakeTag('c', 'm', 'a', 'p');


    177         HbBlob cmapTable(getFontTable(typeface, cmapTag));


    178         if (cmapTable.get() == nullptr) {
    179             ALOGE("Could not get cmap table size!\n");
    180             // Note: This means we will retry on the next call to getCoverage, as we can't store
    181             //       the failure. This is fine, as we assume this doesn't really happen in practice.
    182             return nullptr;
    183         }
    184         // TODO: Error check?
    185         CmapCoverage::getCoverage(mCoverage, cmapTable.get(), cmapTable.size(), &mHasVSTable);
    186 #ifdef VERBOSE_DEBUG
    187         ALOGD("font coverage length=%d, first ch=%x\n", mCoverage.length(),
    188                 mCoverage.nextSetBit(0));
    189 #endif
    190         mCoverageValid = true;
    191     }
    192     return &mCoverage;
    193 }

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