码迷,mamicode.com
首页 > 移动开发 > 详细

android手机字体库相关问题深入剖析

时间:2016-07-19 10:19:35      阅读:393      评论:0      收藏:0      [点我收藏+]

标签:

hi,all:
   问题一、android系统支持什么字体库?
   1、Android系统默认支持三类字体家族,分别为:“seri
f”, “sans-serif”, “monospace",那如何证明?具体论证与定义详见下面的知识点。
        这三类字体家族,每一类都包括若干个*.ttf的字体文件。 除此之外,每个设备厂商在此基础上,都会额外增加一些自己定义的字体文件*.ttf,以兼容更多的语言及字体风格。
        以三星手机(SM-N7508V)为例:这些字体文件总计84个(如下图)。
        技术分享技术分享

      问题二、不同设备手机默认获取的字体是什么?(以三星(SM-N7508V)手机为例

            /system/etc/system_fonts.xml文件中有如下描述

技术分享

技术分享

             也就是说,在没有指定具体的字体名字的情况下, 系统默认使用的字体家族是第一标签<family>中显示的字体家族。

             一个xml文件中有多个字体家族,而多个字体家族会形成一个链表,如果整个链表中都没有某个字体,那么就在system/ect/fallback_fonts.xml配置文件中去找其他字体的描述。

             如果我们想要额外增加或修改字体,则需要在vendor/etc/fallback_fonts.xml文件中进行配置。

             <nameset>代表该font family的名字,一般第一个<name>标签代表字体家族的名字。<fileset>表示该font family所对应的*.ttf文件.每个字体家族都可以有normal

             粗体,斜体字,粗斜体等四种样式。但并不都是必须要有的。从上图中可以看出,三星(SM-N7508V)这个手机,(结论)优先使用的字体库为"Roboto-Regular.ttf"、"bold.ttf"、

             "italic.ttf"、"Roboto- BoldItalic.ttf"。分别代表正常,粗体,斜体字,粗斜体等四种样式。三星手机字体库文件请见附件。

    在  system/ect/fallback_fonts.xml文件中有如下描述:

技术分享

     技术分享


       这个文件中再次说明了,如果这个字体家族中没有某个字体,那么可以在system/ect/fallback_fonts.xml配置文件中找到其他字体的描述。

       思考:那么这些XML文件是如何解析,字体库又是如何被初始化的。(请见第三部分<其他相关知识扩充>)。

     

    3、不同手机设备,配置文件是不同的。也就是说,不同的手机,用的字体库也是不同的。
         如VIVO手机(型号X5M):  用的完全是自己的字体库,如下图:
          技术分享
技术分享
     4、 我们的H5页面使用的样式字体为:SimHei
           当手机浏览器在手机系统中能找到SimHei,则使用SimHei;找不到这个SimHei时,默认会选择手机系统中默认字体。
           
     相关知识点:
     a、Serif的意思是,在字的笔划开始及结束的地方有额外的装饰,而且笔划的粗细会因直横的不同而有不同。相反的,Sans Serif则没有这些额外的装饰,笔划粗细大致差不多
           Serif和Sans Serif的一般比较
           1)Serif的字体容易辨认,因此易读性较高。反之Sans Serif则较醒目,但在行文阅读的情况下,
Sans Serif容易造成字母辨认的困扰,常会有来回重读及上下行错乱的情形。
           2)Serif强调了字母笔划的开始及结束,因此较易前后连续性的辨识。
           3)Serif强调一个word,而非单一的字母,反之Sans Serif则强调个别字母。
           4)在小字体的场合,通常Sans Serif比Serif更清晰。
           5)可以看出,我们平时所用的Georgia、Times New Roman等就属于Serif字体,而Arial、Tahoma、Verdana等则属于Sans Serif字体。
                对中文而言,同样存在这两大种类,很明显,宋体、细明体(繁体中常用)等就属于Serif,而黑体、幼圆等则属于Sans Serif。 
     b、
Monospace:等宽字体,它是指每个字符宽度都一致的字体。一个著名的例子就是 Courier New 字体。因为字符宽度一致,所以这种字体特别容易对齐,
           能快速精确的定位到某行某列,因此经常用来显示代码  
   二、问题二:关于全角半角的问题?
     1、汉字:不管全角还是半角,汉字要占用两个字节。
     2、数字与字母:半角与全角都是一个字节
     3、标点符号:半角情况下(一个字节),全角情况下(两个字节)

   
三、相关知识扩充
     1、通过试验,三星手机的字体编码使用的是ISO 8859-1。在这种编码下,中文占二个字节。其他手机(已测试的VIVO,华为,小米)使用的是utf-8编码,
        这种编码是动态的,1-4个字节不等。中文一般占三个字节。
        2、如果需要自定义字体的话,android.graphics.Typeface提供了3个API供应用程序创建特定字体:

             a、 Typeface createFromAsset(AssetManager mgr, String path);

             b、Typeface createFromFile(File path);

             c、Typeface createFromFile(String path);

             以及如下3个API来创建系统字体:

             a、Typeface create(String familyName, int style);

             b、Typeface create(Typeface family, int style);

             c、Typeface defaultFromStyle(int style);

        3、如何证明android默认包括这三类字体呢?system/ect/fallback_fonts.xml和/system/etc/system_fonts.xml文件是如何被解析的,字体库又是如何被初始化的?

             往framework层去看,在如下路径下frameworks/base/core/java/com/android/internal/os/ZygoteInit.java。这个ZygoteInit类中的preloadClasses方法是加载字体库的入口

             具体过程如下:

             Zygote preloadClasses() -> Class.forName("android.graphics.Typeface")–> 执行Typeface.javastatic块 -> Typeface.cpp Typeface_create–> SkTypeface.cpp CreateFromName() ->                                                   SkFontHost.cpp load_system_fonts()

            我们先看android.graphics.Typeface这个类

            static {

            DEFAULT         = create((String)null,0);

            DEFAULT_BOLD    = create((String)null, Typeface.BOLD);

           SANS_SERIF      = create("sans-serif", 0);

           SERIF           =create("serif", 0);

           MONOSPACE      = create("monospace", 0);//从这里可以看出JAVA层面默认创建三类字体

 

        sDefaults = newTypeface[] {

           DEFAULT,

           DEFAULT_BOLD,

           create((String)null, Typeface.ITALIC),

           create((String)null, Typeface.BOLD_ITALIC),

         };

 

         public static Typeface create(String familyName, int style) {

             return newTypeface(nativeCreate(familyName, style));

         }

          nativeCreate()是jni方法,调用C++层的Typeface.cpp方法,在这个方法中,有一种数据结构(如下),它对应着/system/etc/system_fonts.xml文件中的每个family标签

          struct FontFamily {

         SkTDArray<constchar*>  fNames;//保存<name>标签对应的名字

         SkTDArray<const char*> fFileNames;//保存了<file>标签对应的文件名

         int order;//每个字体家族的加载顺序

         };

         还有其他的一些的数据结构,就不在这列举啦!

        ........................省略中间的代码......................................

        最终会调用到C++层的SkFontHost.cpp中的load_system_fonts()方法完成字体加载。

      4、(注意)字库大部分都是有版权的,所以你看到Android手机中很少有字体选择功能,即使有的话,那么一般都是链接到自己定义的字体库上。

android手机字体库相关问题深入剖析

标签:

原文地址:http://blog.csdn.net/yclfdn2004/article/details/51942225

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!