转载:
Android字体工作原理
一、源码位置
1.添加字库
注意,其他随便:
frameworks/base/data/fonts/fonts.xml
<span style="font-size:14px;"> <font weight="400" style="normal">NotoSansCJKjp-Regular.otf</font> //正常 <font weight="700" style="normal">NotoSansCJKjp-Bold.otf</font> //粗体</span>
frameworks/base/data/fonts/Android.mk
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">font_src_files += \ NotoSansCJKjp-Black.otf \ NotoSansCJKjp-Bold.otf \ NotoSansCJKjp-DemiLight.otf \ NotoSansCJKjp-Light.otf \ NotoSansCJKjp-Medium.otf \ NotoSansCJKjp-Regular.otf \ NotoSansCJKjp-Thin.otf \ NotoSansCJKkr-Black.otf \ NotoSansCJKkr-Bold.otf \ NotoSansCJKkr-DemiLight.otf \ NotoSansCJKkr-Light.otf \ NotoSansCJKkr-Medium.otf \ NotoSansCJKkr-Regular.otf \ NotoSansCJKkr-Thin.otf \ NotoSansCJKsc-Black.otf \ NotoSansCJKsc-Bold.otf \ NotoSansCJKsc-DemiLight.otf \ NotoSansCJKsc-Light.otf \ NotoSansCJKsc-Medium.otf \ NotoSansCJKsc-Regular.otf \ NotoSansCJKsc-Thin.otf \ NotoSansCJKtc-Black.otf \ NotoSansCJKtc-Bold.otf \ NotoSansCJKtc-DemiLight.otf \ NotoSansCJKtc-Light.otf \ NotoSansCJKtc-Medium.otf \ NotoSansCJKtc-Regular.otf \ NotoSansCJKtc-Thin.otf </span></span></span>
注意:
external/skia/include/core/SkTypeface.h
<span style="font-size:14px;"> enum Style { kNormal = 0, kBold = 0x01, kItalic = 0x02, // helpers kBoldItalic = 0x03 };</span>
frameworks/base/core/jni/android/graphics/TypefaceImpl.cpp
<span style="font-size:14px;">static void resolveStyle(TypefaceImpl* typeface) { int weight = typeface->fBaseWeight / 100; //默认400 if (typeface->fSkiaStyle & SkTypeface::kBold) { weight += 3; //粗体:700 } if (weight > 9) { weight = 9; } bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0; typeface->fStyle = FontStyle(weight, italic); }</span>
frameworks/base/data/fonts/fonts.mk
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">PRODUCT_PACKAGES += \ NotoSansCJKjp-Black.otf \ NotoSansCJKjp-Bold.otf \ NotoSansCJKjp-DemiLight.otf \ NotoSansCJKjp-Light.otf \ NotoSansCJKjp-Medium.otf \ NotoSansCJKjp-Regular.otf \ NotoSansCJKjp-Thin.otf \ NotoSansCJKkr-Black.otf \ NotoSansCJKkr-Bold.otf \ NotoSansCJKkr-DemiLight.otf \ NotoSansCJKkr-Light.otf \ NotoSansCJKkr-Medium.otf \ NotoSansCJKkr-Regular.otf \ NotoSansCJKkr-Thin.otf \ NotoSansCJKsc-Black.otf \ NotoSansCJKsc-Bold.otf \ NotoSansCJKsc-DemiLight.otf \ NotoSansCJKsc-Light.otf \ NotoSansCJKsc-Medium.otf \ NotoSansCJKsc-Regular.otf \ NotoSansCJKsc-Thin.otf \ NotoSansCJKtc-Black.otf \ NotoSansCJKtc-Bold.otf \ NotoSansCJKtc-DemiLight.otf \ NotoSansCJKtc-Light.otf \ NotoSansCJKtc-Medium.otf \ NotoSansCJKtc-Regular.otf \ NotoSansCJKtc-Thin.otf </span></span></span>
frameworks/base/data/fonts/font.xml
添加说明:其中一个family家族(比如一套亚洲区域字库)中可以有多个font(比如不同字体),这些font根据不同weight区分;通过alias别名做区分,别名指向相同family名不同weight的font。见下边。
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"> <!--add by tank--> <family name="NotoSansCJKjp"> <font weight="100" style="normal">NotoSansCJKjp-Black.otf</font> <font weight="200" style="normal">NotoSansCJKjp-Bold.otf</font> <font weight="300" style="normal">NotoSansCJKjp-DemiLight.otf</font> <font weight="400" style="normal">NotoSansCJKjp-Light.otf</font> <font weight="500" style="normal">NotoSansCJKjp-Medium.otf</font> <font weight="600" style="normal">NotoSansCJKjp-Regular.otf</font> <font weight="700" style="normal">NotoSansCJKjp-Thin.otf</font> </family> <alias name="NotoSansCJKjp-Black" to="NotoSansCJKjp" weight="100" /> <alias name="NotoSansCJKjp-Bold" to="NotoSansCJKjp" weight="200" /> <alias name="NotoSansCJKjp-DemiLight" to="NotoSansCJKjp" weight="300" /> <alias name="NotoSansCJKjp-Light" to="NotoSansCJKjp" weight="400" /> <alias name="NotoSansCJKjp-Medium" to="NotoSansCJKjp" weight="500" /> <alias name="NotoSansCJKjp-Regular" to="NotoSansCJKjp" weight="600" /> <alias name="NotoSansCJKjp-Thin" to="NotoSansCJKjp" weight="700" /> <family name="NotoSansCJKkr"> <font weight="100" style="normal">NotoSansCJKkr-Black.otf</font> <font weight="200" style="normal">NotoSansCJKkr-Bold.otf</font> <font weight="300" style="normal">NotoSansCJKkr-DemiLight.otf</font> <font weight="400" style="normal">NotoSansCJKkr-Light.otf</font> <font weight="500" style="normal">NotoSansCJKkr-Medium.otf</font> <font weight="600" style="normal">NotoSansCJKkr-Regular.otf</font> <font weight="700" style="normal">NotoSansCJKkr-Thin.otf</font> </family> <alias name="NotoSansCJKkr-Black" to="NotoSansCJKkr" weight="100" /> <alias name="NotoSansCJKkr-Bold" to="NotoSansCJKkr" weight="200" /> <alias name="NotoSansCJKkr-DemiLight" to="NotoSansCJKkr" weight="300" /> <alias name="NotoSansCJKkr-Light" to="NotoSansCJKkr" weight="400" /> <alias name="NotoSansCJKkr-Medium" to="NotoSansCJKkr" weight="500" /> <alias name="NotoSansCJKkr-Regular" to="NotoSansCJKkr" weight="600" /> <alias name="NotoSansCJKkr-Thin" to="NotoSansCJKkr" weight="700" /> <family name="NotoSansCJKsc"> <font weight="100" style="normal">NotoSansCJKsc-Black.otf</font> <font weight="200" style="normal">NotoSansCJKsc-Bold.otf</font> <font weight="300" style="normal">NotoSansCJKsc-DemiLight.otf</font> <font weight="400" style="normal">NotoSansCJKsc-Light.otf</font> <font weight="500" style="normal">NotoSansCJKsc-Medium.otf</font> <font weight="600" style="normal">NotoSansCJKsc-Regular.otf</font> <font weight="700" style="normal">NotoSansCJKsc-Thin.otf</font> </family> <alias name="NotoSansCJKsc-Black" to="NotoSansCJKsc" weight="100" /> <alias name="NotoSansCJKsc-Bold" to="NotoSansCJKsc" weight="200" /> <alias name="NotoSansCJKsc-DemiLight" to="NotoSansCJKsc" weight="300" /> <alias name="NotoSansCJKsc-Light" to="NotoSansCJKsc" weight="400" /> <alias name="NotoSansCJKsc-Medium" to="NotoSansCJKsc" weight="500" /> <alias name="NotoSansCJKsc-Regular" to="NotoSansCJKsc" weight="600" /> <alias name="NotoSansCJKsc-Thin" to="NotoSansCJKsc" weight="700" /> <family name="NotoSansCJKtc"> <font weight="100" style="normal">NotoSansCJKtc-Black.otf</font> <span style="color:#ff0000;"><strong><font weight="200" style="normal">NotoSansCJKtc-Bold.otf</font></strong></span> <font weight="300" style="normal">NotoSansCJKtc-DemiLight.otf</font> <font weight="400" style="normal">NotoSansCJKtc-Light.otf</font> <font weight="500" style="normal">NotoSansCJKtc-Medium.otf</font> <font weight="600" style="normal">NotoSansCJKtc-Regular.otf</font> <font weight="700" style="normal">NotoSansCJKtc-Thin.otf</font> </family> <alias name="NotoSansCJKtc-Black" to="NotoSansCJKtc" weight="100" /> <span style="color:#ff0000;"><strong><alias name="NotoSansCJKtc-Bold" to="NotoSansCJKtc" weight="200" /></strong></span> <alias name="NotoSansCJKtc-DemiLight" to="NotoSansCJKtc" weight="300" /> <alias name="NotoSansCJKtc-Light" to="NotoSansCJKtc" weight="400" /> <alias name="NotoSansCJKtc-Medium" to="NotoSansCJKtc" weight="500" /> <alias name="NotoSansCJKtc-Regular" to="NotoSansCJKtc" weight="600" /> <alias name="NotoSansCJKtc-Thin" to="NotoSansCJKtc" weight="700" /> <!--end tank--></span></span></span>最后,需要将添加字库如NotoSansCJKtc-Bold.otf放到frameworks/base/data/fonts/目录下。
frameworks/base/graphics/java/android/graphics/Typeface.java
<span style="font-size:14px;"><span style="font-size:14px;"> private static void init() { for (FontListParser.Alias alias : fontConfig.aliases) { Typeface base = systemFonts.get(alias.toName); Typeface newFace = base; int weight = alias.weight; if (weight != 400) { newFace = new Typeface(nativeCreateWeightAlias(base.native_instance, weight)); } <span style="color:#ff0000;"><strong>systemFonts.put(alias.name, newFace);</strong></span> } sSystemFontMap = systemFonts; }</span></span>
frameworks/base/graphics/java/android/graphics/FontListParser.java
frameworks/base/core/jni/android_util_StringBlock.cpp
frameworks/base/core/jni/android/graphics/Typeface.cpp
frameworks/base/core/jni/android/graphics/TypefaceImpl.cpp
frameworks/minikin/include/minikin/FontFamily.h
默认字库是font.xml中第一个有效的family
<span style="font-size:14px;"><span style="font-size:14px;">TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { std::vector<FontFamily *>familyVec; for (size_t i = 0; i < size; i++) { FontFamily* family = reinterpret_cast<FontFamily*>(families[i]); familyVec.push_back(family); } TypefaceImpl* result = new TypefaceImpl; result->fFontCollection = new FontCollection(familyVec); if (size == 0) { ALOGW("createFromFamilies creating empty collection"); result->fSkiaStyle = SkTypeface::kNormal; } else { const FontStyle defaultStyle; FontFamily* firstFamily = reinterpret_cast<FontFamily*>(families[0]); MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font; if (mf != NULL) { SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface(); // TODO: probably better to query more precise style from family, will be important // when we open up API to access 100..900 weights result->fSkiaStyle = skTypeface->style(); } else { result->fSkiaStyle = SkTypeface::kNormal; } } result->fBaseWeight = 400; resolveStyle(result); return result; }</span></span>
external/noto-fonts/
external/google-fonts/
external/naver-fonts/
external/fonttools
2.使用方法
第一中使用方法:java代码中直接指定MainActivity.java
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">import android.graphics.Typeface; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final Button btn1; btn1 = (Button) findViewById(R.id.btn1); btn1.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { Log.d("TKTK","TK--------->>>btn1 onclick"); Typeface typeFace =Typeface.create("<span style="color:#ff0000;"><strong>NotoSansCJKtc-Bold</strong></span>",0); btn1.setTypeface(typeFace); //Typeface.setDefault(typeFace); } }); } }</span></span></span>
第二种使用方法:xml中使用
res/values/styles.xml
<span style="font-size:14px;"> <style name="app"> <item name="android:typeface">NotoSansCJKjp</item> <item name="android:textStyle">bold</item> </style></span>
<span style="font-size:14px;"> <TextView android:id="@+id/appName" style="@style/app" /></span>
二、开发板中位置
/system/etc/system_fonts.xml
/system/etc/fallback_fonts.xml
/system/etc/fonts.xml(Android5.0兼容上处两个xml)
/system/fonts/
三、系统默认字体
DroidSans.ttf是默认英文字库;DroidSans-Bold.ttf是默认英文粗体字库;DroidSansFallback.ttf是默认中文字库。
四、其他相关目录
1.系统资源文件
frameworks/base/core/res/res/values/attrs.xml
<span style="font-size:14px;"> <attr name="typeface"> <enum name="normal" value="0" /> <enum name="sans" value="1" /> <enum name="serif" value="2" /> <enum name="monospace" value="3" /> <!--add by tank--> <enum name="NotoSansCJKjp" value="4" /> <enum name="NotoSansCJKkr" value="5" /> <enum name="NotoSansCJKsc" value="6" /> <enum name="NotoSansCJKtc" value="7" /> <!--end tank--> </attr> ////// <attr name="textStyle"> <flag name="normal" value="0" /> <flag name="bold" value="1" /> <flag name="italic" value="2" /> </attr></span>
2.frameworks/base/graphics/java/android/graphics/Typeface.java
<span style="font-size:14px;"> public static final Typeface SANS_SERIF; /** The NORMAL style of the default serif typeface. */ public static final Typeface SERIF; /** The NORMAL style of the default monospace typeface. */ public static final Typeface MONOSPACE; //add by tank public static final Typeface NotoSansCJKjp; public static final Typeface NotoSansCJKkr; public static final Typeface NotoSansCJKsc; public static final Typeface NotoSansCJKtc; //end tank SANS_SERIF = create("sans-serif", 0); SERIF = create("serif", 0); MONOSPACE = create("monospace", 0); //add by tank NotoSansCJKjp = create("NotoSansCJKjp", 0); NotoSansCJKkr = create("NotoSansCJKkr", 0); NotoSansCJKsc = create("NotoSansCJKsc", 0); NotoSansCJKtc = create("NotoSansCJKtc", 0); //end tank</span>
<span style="font-size:14px;"> private static final int SANS = 1; private static final int SERIF = 2; private static final int MONOSPACE = 3; //add by tank private static final int NotoSansCJKjp = 4; private static final int NotoSansCJKkr = 5; private static final int NotoSansCJKsc = 6; private static final int NotoSansCJKtc = 7; //end tank private void setTypefaceFromAttrs(String familyName, int typefaceIndex, int styleIndex) { Typeface tf = null; if (familyName != null) { tf = Typeface.create(familyName, styleIndex); if (tf != null) { setTypeface(tf); return; } } switch (typefaceIndex) { case SANS: tf = Typeface.SANS_SERIF; break; case SERIF: tf = Typeface.SERIF; break; case MONOSPACE: tf = Typeface.MONOSPACE; break; //add by tank case NotoSansCJKjp: tf = Typeface.NotoSansCJKjp; break; case NotoSansCJKkr: tf = Typeface.NotoSansCJKkr; break; case NotoSansCJKsc: tf = Typeface.NotoSansCJKsc; break; case NotoSansCJKtc: tf = Typeface.NotoSansCJKtc; break; //end tank } setTypeface(tf, styleIndex); }</span>
4.external/skia/include/ports/SkFontStyle.h
<span style="font-size:14px;"> enum Weight { kThin_Weight = 100, kExtraLight_Weight = 200, kLight_Weight = 300, kNormal_Weight = 400, kMedium_Weight = 500, kSemiBold_Weight = 600, kBold_Weight = 700, kExtraBold_Weight = 800, kBlack_Weight = 900 };</span>