📄 minigui 体系结构之三逻辑字体以及多字体和多字符集实现.htm
字号:
560 }
561
562 return -1;
563 }
564
565 #ifndef _LITE_VERSION
566 static unsigned short euckr_conv_to_uc16 (const unsigned char* mchar, int len)
567 {
568 return '?';
569 }
570 #endif
571
572 static CHARSETOPS CharsetOps_euckr = {
573 8836,
574 2,
575 2,
576 FONT_CHARSET_EUCKR,
577 {'\xA1', '\xA1'},
578 euckr_len_first_char,
579 euckr_char_offset,
580 db_nr_chars_in_str,
581 euckr_is_this_charset,
582 euckr_len_first_substr,
583 db_get_next_word,
584 euckr_pos_first_char,
585 #ifndef _LITE_VERSION
586 euckr_conv_to_uc16
587 #endif
588 };
589 /************************* End of EUCKR *************************************/
590 #endif /* _EUCKR_SUPPORT */
</PRE></TD></TR></TBODY></TABLE><A id=4 name=4></A>
<P><STRONG class=subhead>4 MiniGUI 中的字体支持</STRONG></P><STRONG>4.1
设备字体</STRONG>
<P>在 MiniGUI 中,设备字体定义如下(include/gdi.h):</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE> 319 struct _DEVFONT
320 {
321 char name [LEN_DEVFONT_NAME + 1];
322 DWORD style;
323 FONTOPS* font_ops;
324 CHARSETOPS* charset_ops;
325 struct _DEVFONT* sbc_next;
326 struct _DEVFONT* mbc_next;
327 void* data;
328 };
</PRE></TD></TR></TBODY></TABLE>
<P>其中各字段说明如下:</P>
<UL class=noindent>
<LI>name:该设备字体的名称。MiniGUI 中设备字体的名称格式如下:<BR></LI></UL>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE><type>-<name>-<style>-<width>-<height>-<charset1[,charset2]>
</PRE></TD></TR></TBODY></TABLE><BR>其中每个域的含义如下:<BR>
<UL>
<LI>type:字体类型,比如RBF(MiniGUI 定义的等宽字体格式)、VBF(MiniGUI
定义的变宽字体格式)、TTF(TrueType 字体)等等。
<LI>name:名称,比如 Song、Hei、Times 等等。
<LI>style:该字体的样式,比如黑体、斜体等等。
<LI>width:该字体的宽度,对矢量字体来说,可取 0。
<LI>height:该字体的高度,对矢量字体来说,可取 0。
<LI>charset1, charset2:该字体适用的字符集名称。 </LI></UL>
<UL class=noindent>
<LI>style:字体样式。
<LI>font_ops:设备字体对应的字体操作集。
<LI>charset_ops:设备字体对应的字符集操作集。
<LI>sbc_next、mbc_next:内部使用的链表维护字段。
<LI>data:该设备字体相关的内部数据。 </LI></UL>
<P>在 MiniGUI 启动时,将根据 MiniGUI.cfg
文件中的定义建立两个设备字体链表,分别为单字节设备字体链和多字节设备字体链。这两个链表将由 CreateLogFont
使用,通过查找和匹配,建立对应的逻辑字体。</P><STRONG>4.2 逻辑字体</STRONG>
<P>逻辑字体的定义如下(include/gdi.h):</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE> 228 typedef struct _LOGFONT {
229 char type [LEN_FONT_NAME + 1];
230 char family [LEN_FONT_NAME + 1];
231 char charset [LEN_FONT_NAME + 1];
232 DWORD style;
233 int size;
234 int rotation;
235 DEVFONT* sbc_devfont;
236 DEVFONT* mbc_devfont;
237 } LOGFONT;
238 typedef LOGFONT* PLOGFONT;
</PRE></TD></TR></TBODY></TABLE>
<P>显然,每个逻辑字体由最匹配该字体要求(大小、字符集、样式等)的两个设备字体(sbc_devfont和
mbc_devfong)组成,分别用来处理多字节字符串中的单字节字符和多字节字符。其中单字节设备字体是必不可少的。</P>
<P>逻辑字体的匹配算法可参见 src/gdi/logfont.c 和src/font/devfont.c
文件。限于篇幅,不再赘述。</P><STRONG>4.3 设备字体操作集</STRONG>
<P>和字符集操作集一样,MiniGUI
中的设备字体操作集针对每种设备字体类型而定义,包括对这种设备字体的各种操作函数(include/gdi.h):</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE> 276 typedef struct _FONTOPS
277 {
278 int (*get_char_width) (LOGFONT* logfont, DEVFONT* devfont,
279 const unsigned char* mchar, int len);
280 int (*get_str_width) (LOGFONT* logfont, DEVFONT* devfont,
281 const unsigned char* mstr, int n, int cExtra);
282 int (*get_ave_width) (LOGFONT* logfont, DEVFONT* devfont);
283 int (*get_max_width) (LOGFONT* logfont, DEVFONT* devfont);
284 int (*get_font_height) (LOGFONT* logfont, DEVFONT* devfont);
285 int (*get_font_size) (LOGFONT* logfont, DEVFONT* devfont, int expect);
286 int (*get_font_ascent) (LOGFONT* logfont, DEVFONT* devfont);
287 int (*get_font_descent) (LOGFONT* logfont, DEVFONT* devfont);
288
289 /* TODO */
290 // int (*get_font_ABC) (LOGFONT* logfont);
291
292 size_t (*char_bitmap_size) (LOGFONT* logfont, DEVFONT* devfont,
293 const unsigned char* mchar, int len);
294 size_t (*max_bitmap_size) (LOGFONT* logfont, DEVFONT* devfont);
295 const void* (*get_char_bitmap) (LOGFONT* logfont, DEVFONT* devfont,
296 const unsigned char* mchar, int len);
297
298 const void* (*get_char_pixmap) (LOGFONT* logfont, DEVFONT* devfont,
299 const unsigned char* mchar, int len, int* pitch);
300 /* Can be NULL */
301
302 void (*start_str_output) (LOGFONT* logfont, DEVFONT* devfont);
303 /* Can be NULL */
304 int (*get_char_bbox) (LOGFONT* logfont, DEVFONT* devfont,
305 const unsigned char* mchar, int len,
306 int* px, int* py, int* pwidth, int* pheight);
307 /* Can be NULL */
308 void (*get_char_advance) (LOGFONT* logfont, DEVFONT* devfont,
309 int* px, int* py);
310 /* Can be NULL */
311
312 DEVFONT* (*new_instance) (LOGFONT* logfont, DEVFONT* devfont,
313 BOOL need_sbc_font);
314 /* Can be NULL */
315 void (*delete_instance) (DEVFONT* devfont);
316 /* Can be NULL */
317 } FONTOPS;
</PRE></TD></TR></TBODY></TABLE>
<P>比如,get_char_width 用来获得某个字符的宽度,而 get_char_bitmap 用来获得某个字符的位图信息等等。</P>
<P>在 src/font/rawbitmap.c 和 src/font/varbitmap.c 文件中分别定义了对 RBF 和 VBF
两种字体的操作函数,比如对变宽光栅字体来讲(VBF),其 get_char_bitmap
定义如下(src/font/rawbitmap.c):</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE> 155 static const void* get_char_bitmap (LOGFONT* logfont, DEVFONT* devfont,
156 const unsigned char* mchar, int len)
157 {
158 int offset;
159 unsigned char eff_char = *mchar;
160 VBFINFO* vbf_info = VARFONT_INFO_P (devfont);
161
162 if (*mchar < vbf_info->first_char || *mchar > vbf_info->last_char)
163 eff_char = vbf_info->def_char;
164
165 if (vbf_info->offset == NULL)
166 offset = (((size_t)vbf_info->max_width + 7) >> 3) * vbf_info->height
167 * (eff_char - vbf_info->first_char);
168 else
169 offset = vbf_info->offset [eff_char - vbf_info->first_char];
170
171 return vbf_info->bits + offset;
172 }
</PRE></TD></TR></TBODY></TABLE>
<P>其中,VARFONT_INFO_P 是一个宏,用来从设备字体的 data 字段中获得 VBFINFO
结构的指针。有了这个指针之后,该函数计算字符位图的偏移量最后返回字符的位图。</P><STRONG>4.4 新设备字体的实现举例</STRONG>
<P>这里以 Adobe Type1 字体的实现为例,说明如何在 MiniGUI 中实现一种新的设备字体。MiniGUI 借用了 T1Lib
函数库实现了对 Type1 字体的支持。</P>
<P><B><I>4.4.1 Type1 字体简介</I></B></P>
<P>Type1 矢量字体1格式由 Adobe 公司设计,并被该公司的ps标准支持。因此,它在Linux下也被支持得很好。它被 X和
ghostscript支持。一个典型的Type1字体包括一个afm(adobe font metric) 度量文件,一个外形文件,通常是一个pfb
( printer font binary) 或者 pfa (printer font ascii)
文件,外形文件包括所有的轮廓,而度量文件包含了所有的度量。比如紧排,连字等信息。</P>
<P><B><I>4.4.2 T1Lib 简介</I></B></P>
<P>T1Lib 是用 C 语言实现的一个库,它可以从 Adobe Type 1 字体生成位图。它可以使用X11R5
或者更新版本提供的光栅化工具的很多功能,但避免了其已知的缺点。当然,T1Lib完全可以在没有 X11 的环境下工作。T1Lib
可以被编译成静态或者动态库,从而可以方便地连接。</P>
<P>这里是T1Lib 的一些特性:</P>
<UL>
<LI>字体通过运行时读取字库而被T1lib得知。即它是灵活可配置的。当然,它只支持Type 1字体。
<LI>字符或字符串只在需要时才被光栅化。
<LI>对字符串光栅化时支持字符间紧排,并且可以利用一个AFM文件提供紧排信息,如果没有这个文件,T1Lib可以直接生成这些信息,也可以将其输出到一个文件以备后用。
<LI>支持连字,连字是一个好的字体模型会提供的功能,目前,只有TEX和与其相关的软件包对连字支持得比较好。连字信息也包含在AFM文件里。
<LI>支持旋转和各种仿射变换。支持字体扩展,倾斜。
<LI>可以动态载入新的解码矢量。用新的解码矢量解析字体。
<LI>支持5灰度的低分辨率和17灰度的高分辨率的反走样。
<LI>字符串可以被添加下划线,上划线或者横线。 </LI></UL>
<P><B><I>4.4.3 Adobe Type1 字体支持的实现</I></B></P>
<P>在 MiniGUI 设备字体定义中,有一个 data 字段可用来保存设备字体相关的数据结构。对 Type1 字体来讲,我们使用
TYPE1INFO和TYPE1INSTANCEINFO两个数据结构来存储这种设备字体的类信息和实例信息。</P>
<P>1) TYPE1INFO和TYPE1INSTANCEINFO 结构</P>
<P>这两个结构的定义如下(src/font/type1.h):</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE> 22 typedef struct tagTYPE1GLYPHINFO {
23 int font_id;
24 //BBox font_bbox;
25 //int ave_width;
26 BOOL valid;
27 } TYPE1INFO, *PTYPE1INFO;
28
29 typedef struct tagTYPE1INSTANCEINFO {
30 PTYPE1INFO type1_info;
31 int rotation;/*in tenthdegrees*/
32 T1_TMATRIX * pmatrix;
33 int size;
34 int font_height;
35 int font_ascent;
36 int font_descent;
37
38 int max_width;
39 int ave_width;
40
41 double csUnit2Pixel;
42 /*
43 * last char or string's info
44 * T1_SetChar, T1_SetString, T1_AASetSting, T1_AASetString all return a static
45 * glyph pointer, we save the related infomation here for later use.
46 * */
47 char last_bitmap_char;
48 char last_pixmap_char;
49 char * last_bitmap_str;
50 char * last_pixmap_str;
51 int last_ascent;
52 int last_descent;
53 int last_leftSideBearing;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -