忽如一夜春风来,千树万树梨花开
时光如白驹过隙,寥寥草草,今年的冬天又要到来了,怀念火炉打边的日子——

Android disabled ligature

Android 连字 参考
fi、fl、ff、ffi、ffl 称为f合字,为了 f 和 i 的点,以及 f 和 f、l 在相邻处避免以难看的外形直接相连而特地制作成一个合体字形。另,在金属活字里,f 和 i 的点会碰到一起产生空隙甚至会被折断,因此做一个 fi 合字尤其必要。摘自【日】高冈 昌生. 西文排版——排版的基础和规范. 中信出版社, 2016: 102.

连字

那么问题来了Android 如何解决这种问题呢?

Paint

连字属于字体功能之一,所以我们可以通过 Paint.java 的setFontFeatureSettings(String)方式来激活和屏蔽连字功能

Paint p = new Paint();
//Disable ligature using OpenType feature
p.setFontFeatureSettings("'liga' off");
 //Re-enable ligature
p.setFontFeatureSettings("'liga' on");

textview of letterspacing

通过修改文本的字间距控制 ligature,只要大于 0.03 就可以让 i 的小点显示出来。

android:letterSpacing="0.031"

为什么是0.03

代码展示

framework/minikin/libs/minikin/Layout.cpp

Android P doLayoutRun ()
Android Q LayoutPiece()

void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
bool isRtl, const MinikinPaint& paint, StartHyphenEdit startHyphen,
EndHyphenEdit endHyphen) {
...
	if (fabs(paint.letterSpacing) > 0.03) {
	static const hb_feature_t no_liga = {HB_TAG(‘l’, ‘i’, ‘g’, ‘a’), 0, 0, ~0u};
	static const hb_feature_t no_clig = {HB_TAG(‘c’, ‘l’, ‘i’, ‘g’), 0, 0, ~0u};
	features.push_back(no_liga);
	features.push_back(no_clig);
}
...
}

上述代码展示了一个很明显的0.03

方法调用堆栈

4462 4462 D Minikin : #00 pc 0000000000016544 /system/lib64/libminikin.so (minikin::Layout::doLayoutRun(unsigned short const, unsigned long, unsigned long, unsigned long, bool, minikin::MinikinPaint const&, minikin::StartHyphenEdit, minikin::EndHyphenEdit)+404)
4462 4462 D Minikin : #01 pc 000000000001446c /system/lib64/libminikin.so (minikin::LayoutCacheKey::doLayout(minikin::Layout, minikin::MinikinPaint const&) const+204)
4462 4462 D Minikin : #02 pc 00000000000141e0 /system/lib64/libminikin.so (void minikin::LayoutCache::getOrCreateminikin::LayoutAppendFunctor(minikin::U16StringPiece const&, minikin::Range const&, minikin::MinikinPaint const&, bool, minikin::StartHyphenEdit, minikin::EndHyphenEdit, minikin::LayoutAppendFunctor&)+480)
4462 4462 D Minikin : #03 pc 0000000000013cbc /system/lib64/libminikin.so (minikin::Layout::doLayoutWord(unsigned short const, unsigned long, unsigned long, unsigned long, bool, minikin::MinikinPaint const&, unsigned long, minikin::StartHyphenEdit, minikin::EndHyphenEdit, minikin::LayoutPieces const, minikin::Layout, float, minikin::MinikinExtent, minikin::MinikinRect, minikin::LayoutPieces) [clone .cfi]+364)
4462 4462 D Minikin : #04 pc 0000000000013a34 /system/lib64/libminikin.so (minikin::Layout::doLayoutRunCached(minikin::U16StringPiece const&, minikin::Range const&, bool, minikin::MinikinPaint const&, unsigned long, minikin::StartHyphenEdit, minikin::EndHyphenEdit, minikin::LayoutPieces const, minikin::Layout, float, minikin::MinikinExtent, minikin::MinikinRect, minikin::LayoutPieces) [clone .cfi]+364)
4462 4462 D Minikin : #05 pc 0000000000018294 /system/lib64/libminikin.so (minikin::Layout::measureText(minikin::U16StringPiece const&, minikin::Range const&, minikin::Bidi, minikin::MinikinPaint const&, minikin::StartHyphenEdit, minikin::EndHyphenEdit, float, minikin::MinikinExtent, minikin::LayoutPieces) [clone .cfi]+228)
4462 4462 D Minikin : #06 pc 00000000000f2204 /system/lib64/libhwui.so (android::MinikinUtils::measureText(android::Paint const, minikin::Bidi, android::Typeface const, unsigned short const, unsigned long, unsigned long, unsigned long, float)+140)
4462 4462 D Minikin : #07 pc 000000000014e390 /system/lib64/libandroid_runtime.so (android::PaintGlue::getRunAdvance___CIIIIZI_F(_JNIEnv, _jclass, long, _jcharArray*, int, int, int, int, unsigned char, int)+336)
4462 4462 D Minikin : #08 pc 00000000003dd18c /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.graphics.Paint.nGetRunAdvance+236)
4462 4462 D Minikin : #09 pc 00000000007f37e8 /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.graphics.Paint.getRunAdvance+168)
4462 4462 D Minikin : #10 pc 00000000007f3658 /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.graphics.Paint.getRunAdvance+328)
4462 4462 D Minikin : #11 pc 0000000000b2ede0 /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.text.TextLine.getRunAdvance+128)
4462 4462 D Minikin : #12 pc 0000000000b2ffa4 /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.text.TextLine.handleText+372)
4462 4462 D Minikin : #13 pc 0000000000b2f368 /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.text.TextLine.handleRun+680)
4462 4462 D Minikin : #14 pc 0000000000b30d88 /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.text.TextLine.measure+216)
4462 4462 D Minikin : #15 pc 0000000000b312ec /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.text.TextLine.metrics+60)
4462 4462 D Minikin : #16 pc 0000000000c458fc /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.text.BoringLayout.isBoring+460)
4462 4462 D Minikin : #17 pc 0000000000d6a33c /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.widget.TextView.makeSingleLayout+204)
4462 4462 D Minikin : #18 pc 0000000000d69b5c /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.widget.TextView.makeNewLayout+700)
4462 4462 D Minikin : #19 pc 0000000000d6da80 /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.widget.TextView.onMeasure+1680)
4462 4462 D Minikin : #20 pc 0000000000c7d9ac /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.view.View.measure+956)
4462 4462 D Minikin : #21 pc 0000000000d3d9ac /system/framework/arm64/boot-framework.oat (offset 0x3d1000) (android.view.ViewGroup.measureChild+172)
4462 4462 D Minikin : #22 pc 0000000000000e40 /dev/ashmem/dalvik-jit-code-cache (deleted)
posted on 2020-10-27 15:37  寒风凛凛  阅读(247)  评论(0编辑  收藏  举报