DirectFB 源码解读之字体-2

本文深入解析初次绘制字符串过程中的关键步骤,包括字体与surface的关联、字符串解码、字形查找与分配、字符绘制与复制等。通过理解这些步骤,开发者能够更深入地掌握文本渲染技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载时请表明原文出处(http://blog.sina.com.cn/wyw1976)及作者邮箱(wyw1976@gmail.com)
 
 
字体关联
 
    字体与surface的关联是在SetFont中完成的。其过程很简单,就是将字体对象记录在surface的一个指针中,以后该surface上画字符,就会找到相应的字体对象。
    需要说明的是,一个字体对象可以同时属于多个surface,而每个surface在某个时刻最多拥有一个Font对象。


第一次绘制字符串"aAbB"
 
    用户在调用surface->DrawString()时,对应DFB中的函数是dfb_gfxcard_drawstring(), 这也是绘制字符串的主函数。
 
    它的工作包含以下几步:
    (1)对需要绘制的字符串进行解码,解码的结果是得到每个字符的索引值。字符的索引值的定义依赖于不同的字体库,对于FT2,最终是调用FT_Get_Char_Index()得到索引值,而对于default font, 其索引值就是字符对应的整数值。总之,索引值与字符是一一对应的。
    (2)对于每一个字符,首先根据它的索引值在字体对象的字形数组或字形HASH表中查找它的字形对象(DFB中称为CoreGlyphData),因为是第一次画,必然找不到。(如果索引值小于128,在数组中查找,否则在哈希表中查找)。字形数组和hash表的定义如下:


    (3)接着,调用dfb_font_get_glyph_data()得到字符的字形对象。该对象的数据结构如下:
typedef struct {
     DirectLink     link;
     unsigned int   index;
     unsigned int   row;
     CoreSurface   *surface;             
     int            start;               
     int            width;               
     int            height;              
     int            left;                
     int            top;                 
     int            advance;             
     int            magic;
} CoreGlyphData;
 
    首先,为字符分配一个新的字形对象:CoreGlyphData。
    然后,调用font->GetGlyphData()绘制字符,这时绘制的字符仍然存在字体库的buffer中。
    其次,分配一个新的row(包含一个surface)用于存放该字形。
    再次,调用font->RenderGlyph()将该字符绘制到row中的surfaceace上,其中CoreGlyphData->surface 就指向这个内部的surface, CoreGlyphData->start指向了这个字符在surface上的起始位置。CoreGlyphData->width和CoreGlyphData->height 指向的是字符的宽度和高度,这几个变量就可以确定surface上的包含该字符一个矩形
    最后,将该字符对应的字形对象存放到了hash表或字形数组中。所以这时的CoreFont, CoreGlyphData和CoreFontCacheRow三者的关系如下:
 
 DirectFB <wbr>源码解读之字体-4
 
有关上面这个图,有几点需要说明:
       @每个CoreFontCacheRow都拥有一个surface用来绘制字符,CoreFontCacheRow->next_x指向surface中下一个可以绘图的地址,每次绘制一个字符,next_x都会增加。
       @如果next_x指到了该surface的最后,或者surface所剩的空间不足以绘制一个字符,则DFB会分配一个新的CoreFontCacheRow并为其分配新的surface,而系统中最多支持5个CoreFontCacheRow(这个值是在创建字体对象CoreFont时指定的)
       @CoreFontCacheRow->glyphs是一个链表,链表中的每一项都是一个CoreGlyphData对象,我们知道字符与CoreGlyphData是一一对应的,因此该链表记录了所有绘制在该row上的字形对象。
       @如果5个CoreFontCacheRow都用完了,还是不能存放所有的字符,这时就需要替换,替换的原则是LRU(最近最少用),CoreFontCacheRow->stamp记录了该row的使用情况,每次属于该row的字符被绘制,该值加1,例如row0中有字符a, row1中有字符M, 用户调用surface->DrawString(surface, "aMMMaaaMMMM", ...)后,row0的stamp将加4, 而row1的stamp将加7.
       @在row的替换时,需要释放原来row的资源,包括它的surface,以及row->glyphs链表中所有字形对象
       @CoreFont->glyph_data[128]是一个指针数组,初始时,每个元素都是NULL, 在绘制字符时,该字符对应的字形对象CoreGlyphData会记录在这个数组中,而记录的位置就是它的索引值,以后再绘制同样的字符,就可以从数组中直接找到。
       @如果字符个数多于128,则要用到hash表。
 
     (4)将字符从font对象内部的surface,拷贝到目标surface,即调用DrawString的surface。拷贝的过程就是blit的过程,根据不同的系统,可以调用硬件支持blit或软件blit。
     (5)转向(2)绘制下一个字符,在绘制接下来的几个字符"AbB"时,就不需要分配新的row了,因为第一次分配的row足够放下这几个字符了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值