美文网首页
minigui 4.0 源代码分析(五)

minigui 4.0 源代码分析(五)

作者: RonZheng2010 | 来源:发表于2020-11-24 23:04 被阅读0次

    1. 字体

    3.1 设备字体 DEVFONT

    DEVFONT定义设备字体。

    • name是名字
    • style是字体风格,如粗体、斜体、下划线等。
    • font_ops是字体函数集。这是一个FONTOPS结构。成员data是这个函数集加载的数据。
    • 成员charset_ops是字符集函数集。这是一个CHARSETOPS结构。
    • 成员next使DEVFONT实例可以链成一个链表。

    3.2 逻辑字体LOGFONT

    LOGFONT定义逻辑字体。设备描述表DC的成员pLogFont是它使用的逻辑字体。

    • type是字体类型
    • family是字体家族
    • charset是字符集
    • style是字体风格
    • size是字体大小
    • rotation是字体方向
    • devfonts[]保存它依赖的设备字体DEVFONT。

    3.3 创建设备逻辑字体

    3.3.1 add_dev_font()

    add_dev_font()从指定文件中,加载指定字体。

    add_dev_font()有三个参数:字体名、字体数据参数、参数标志。参数标志指示“字体数据参数”是实际的数据,还是文件名。如果是后者,则实际的数据要从文件中读取。

    这里书名的例子,
    字体名为ttf-helvetica-rrncnn-0-0-ISO8859-1,GB2312-0,UTF-8,
    字体数据参数为font/Helvetica.ttf,这是文件名。

    字体名包括几个部分:

    • ttf是字体类型,
      Helvetica是字体家族,
      rrncnn是字体风格,
      ISO8859-1,GB2312-0,UTF-8是三种字符集。

    add_dev_font()的步骤如下。

    • 调用make_devfont(),创建并设置字体DEVFONT。

      • 全局数组__mg_fontops_infos[]中保存了可用的字体操作函数集。这里根据字体类型ttf,找到对应的函数集。
      FONTOPS_INFO __mg_fontops_infos[] = { 
          {FONT_TYPE_NAME_BITMAP_RAW, &__mg_rbf_ops},
          {FONT_TYPE_NAME_SCALE_TTF, &__mg_ttf_ops},
          ...
      }
      
      • 根据字符集名ISO8859-1,调用GetCharsetOpsEx()。在全局数组Charsets[]中找到对应字符集的函数集CharsetOps_iso8859_1。
      CHARSETOPS* Charsets [] = {
          &CharsetOps_ascii,
          &CharsetOps_iso8859_1,
          &CharsetOps_gb2312_0,
          &CharsetOps_big5,
          ...
      };
      
      static CHARSETOPS CharsetOps_iso8859_1 = {
           256, 
          1,   
          FONT_CHARSET_ISO8859_1,
          sb_len_first_char,
          sb_get_char_value,
          sb_char_type,
          ...
          };
      
    • 调用find_devfont(),根据字体名查找全局链表mb_dev_font_head,看看是否有同名字体注册。如果已注册,则失败返回。这个链表保存所有注册的DEVFONT链表。

      DEVFONT* mb_dev_font_head = NULL;
      int nr_mb_dev_fonts;
      DEVFONT* sb_dev_font_head = NULL;
      int nr_sb_dev_fonts;
      
    • 创建DEVFONT实例,设置成员font_ops和charset_ops为刚得到的相应实例。

    • 根据字体风格rnncnn,设置为DEVFONT的成员style。其中,rrncnn中的每个字母代表一个风格bit是否使能。

    • 设置字体数据,也就是DEVFONT的成员data。如果数据是在内存中,则直接设置,如果在文件中,则调用font_ops的成员函数load_font_data(),从文件中读取数据,然后再设置。

    这里调用的是同名函数load_font_data()。

    • 调用ADD_DEVFONT_TO_LINKLIST(),将DEVFONT实例加入全局链表mb_dev_font_head。

    • 调用add_relating_devfonts_to_list(),进一步解析字符集ISO8859-1,GB2312-0,UTF-8,得到GB2312-0和UTF-8。与make_devfont()中一样,创建字体,并加入链表mb_dev_font_head。这样就注册了三个DEVFONT实例。

    3.3.2 load_font_data()

    DEVFONT的成员data,指向font_ops从文件读出的数据,这里指向FT2_DATA实例。FT2_DATA及其他结构是开源软件ft_library定义的接口。

    load_font_data()基于ft_library得到字体数据,就是FT2_DATA实例。Ft_library的初始化在font_InitFreetypeLibrary()中完成。

    3.3.3 font_InitFreetypeLibrary()

    font_InitFreetypeLibrary()负责完成初始化ft_library。其中依赖开源软件harzbuff。

    3.3.4 INIT_SPECIFICAL_FONTS()

    INIT_SPECIFICAL_FONTS()读取配置文件的指定节,遍历其中的字体列表,对每个字体读取其名字和文件名,并按如下步骤加载它。

    • 如果字体存在内存中,则LoadResource()负责加载。这里不说明。
    • 调用add_dev_font()加载字体。

    3.3.5 font_InitIncoreFonts()

    font_InitIncoreFonts()初始化内部字体。

    • 依次遍历_null_font_names[]、incore_rbfonts[]等全局数组中,调用add_dev_font()加载。这里的add_dev_font()的数据参数都在内存中,不需要从文件中读取。

      const char* _null_font_names [] = {
      "nuf-dummy-rrncnn-8-1-ISO8859-1",
      }
      
      INCORE_RBFINFO* incore_rbfonts [] = {
      &__mgif_rbf_fixedsys_8x15,
      };
      
      VBFINFO* incore_vbfonts [] = {
      &__mgif_vbf_Courier8x13,
      };
      

    3.4 创建逻辑字体

    3.4.1 mg_InitSysFont()

    mg_InitSysFont()根据配置文件的设置,初始化逻辑字体。

    配置文件中指定了逻辑字体。如下是配置文件的一个例子。

    [systemfont]
    font_number=5
    default=0
    wchar_def=1
    fixed=2
    caption=3
    menu=4
    font0=rbf-FixedSys-rrncnn-8-16-ISO8859-1
    
    • 调用GetMgEtcIntValue()得到逻辑字体数量。
    • 遍历全局数组sys_font_name[],这是字体应用的不同场景。调用GetMgEtcIntValue(),得到使用的字体编号。
    char* sys_font_name [] =                                                                      
    {                                                                                                    
        "default",
        "wchar_def",
        "fixed",
        “caption",                                                                                       
        "menu",                                                                                          
        "control"                                                                                        
    };    
    
    • 根据配置文件中指定的字体数量,创建逻辑本地逻辑字体数组sys_fonts[]。

    • 遍历sys_fonts[],根据编号加载它们。如字体编号为0,则配置文件中的键名为font0。

      • 调用GetMgEtcIntValue(),根据键名得到键值,就是字体名。
    • 调用fontGetTypeFromName()相关函数,解析字体名。

    比如rbf-FixedSys-rrncnn-8-16-ISO8859-1就是字体名,其中rbf为类型,FixedSys为family家族,rrnccn为风格,IOS8859-1为字符集。

    • sys_fonts[]数组中,第一个字体必须为字符宽度必须为一个字符。所以这里调用GetCharsetOps()得到它的字符集函数,检查是不是这样。

    • 调用CreateLogFont()创建逻辑字体。

    • 最后将sys_fonts中的内容挨个复制到全局变量g_SysLogFont[]中。

    LOGFONT* g_SysLogFont [NR_SYSLOGFONTS];
    

    3.4.2 CreateLogFont()

    CreateLogFont()基于设备字体,创建逻辑字体。

    • 调用fontConvertStyle转换字体风格表达方式。

    • 调用gdiCreateLogFont()创建逻辑字体。其中,

      • 创建FONT_RES实例。FONT_RES实例包含LOGFONT实例。
      • 调用font_GetMatchedSBDevFont(),根据字体的family值,在全局链表sb_dev_font_head中查找匹配的字体。找到的字体保存在本地数组devfonts[]中。
      • 遍历family中的所有值。调用font_GetMatchedMBDevFont(),在全局链表mb_dev_font_head中查找匹配的字体。找到的字体保存在devfonts[]中。
    • 将devfonts[]中的所有内容复制到LOGFONT的成员devfonts[]中。

    • 调用adjust_newlf_info()。其中调用DEVFONT的成员函数get_font_acent()、get_font_decent(),根据返回值LOGFONT实例中的成员值。

    3.5 初始化字体子系统 mg_InitGDI()

    mg_InitGDI()初始化字体子系统,包括初始化FT_library、加载配置文件中的字体、加载内部字体、和初始化逻辑字体。

    3.6 使用字体 TextOutOmitted()

    TextOutOmitted()用于输出文字。

    • 它将文本预处理后,分割成单个字符,然后在循环中调用cb_textout(),依次输出字符。
    • 在_gdi_draw_one_glyph()中,调用SELECT_DEVFONT_BY_GLYPH()选择当前的设备字体,然后调用_gdi_direct_fillgraph()绘制字符。其中,
      • 调用_gdi_get_glyph_data()得到字符的绘制函数,也就是GLYPH_CTXT的成员cb。然后调用它。最终调用_glyph_draw_pixels()绘制点、线。

    相关文章

      网友评论

          本文标题:minigui 4.0 源代码分析(五)

          本文链接:https://www.haomeiwen.com/subject/mffpiktx.html