来源:百问网
作者:韦东山
本文字数:2620,阅读时长:4分钟
前面提到过,一行文字中:后一个字符的原点=前一个字符的原点 advance。
所以要计算一行文字的外框,需要按照排列顺序处理其中的每一个字符。
代码如下,注释写得很清楚了:
102 int compute_string_bbox(FT_Face face, wchar_t *wstr, FT_BBox *abbox)
103 {
104 int i;
105 int error;
106 FT_BBox bbox;
107 FT_BBox glyph_bbox;
108 FT_Vector pen;
109 FT_Glyph glyph;
110 FT_GlyphSlot slot = face->glyph;
111
112 /* 初始化 */
113 bbox.xMin = bbox.yMin = 32000;
114 bbox.xMax = bbox.yMax = -32000;
115
116 /* 指定原点为(0, 0) */
117 pen.x = 0;
118 pen.y = 0;
119
120 /* 计算每个字符的 bounding box */
121 /* 先 translate, 再 load char, 就可以得到它的外框了 */
122 for (i = 0; i < wcslen(wstr); i )
123 {
124 /* 转换:transformation */
125 FT_Set_Transform(face, 0, &pen);
126
127 /* 加载位图: load glyph image into the slot (erase previous one) */
128 error = FT_Load_Char(face, wstr[i], FT_LOAD_RENDER);
129 if (error)
130 {
131 printf("FT_Load_Char error\n");
132 return -1;
133 }
134
135 /* 取出 glyph */
136 error = FT_Get_Glyph(face->glyph, &glyph);
137 if (error)
138 {
139 printf("FT_Get_Glyph error!\n");
140 return -1;
141 }
142
143 /* 从 glyph 得到外框: bbox */
144 FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &glyph_bbox);
145
146 /* 更新外框 */
147 if ( glyph_bbox.xMin < bbox.xMin )
148 bbox.xMin = glyph_bbox.xMin;
149
150 if ( glyph_bbox.yMin < bbox.yMin )
151 bbox.yMin = glyph_bbox.yMin;
152
153 if ( glyph_bbox.xMax > bbox.xMax )
154 bbox.xMax = glyph_bbox.xMax;
155
156 if ( glyph_bbox.yMax > bbox.yMax )
157 bbox.yMax = glyph_bbox.yMax;
158
159 /* 计算下一个字符的原点: increment pen position */
160 pen.x = slot->advance.x;
161 pen.y = slot->advance.y;
162 }
163
164 /* return string bbox */
165 *abbox = bbox;
166 }
调整原点并绘制
代码如下,也不复杂:
169 int display_string(FT_Face face, wchar_t *wstr, int lcd_x, int lcd_y)
170 {
171 int i;
172 int error;
173 FT_BBox bbox;
174 FT_Vector pen;
175 FT_Glyph glyph;
176 FT_GlyphSlot slot = face->glyph;
177
178 /* 把 LCD 坐标转换为笛卡尔坐标 */
179 int x = lcd_x;
180 int y = var.yres - lcd_y;
181
182 /* 计算外框 */
183 compute_string_bbox(face, wstr, &bbox);
184
185 /* 反推原点 */
186 pen.x = (x - bbox.xMin) * 64; /* 单位: 1/64 像素 */
187 pen.y = (y - bbox.yMax) * 64; /* 单位: 1/64 像素 */
188
189 /* 处理每个字符 */
190 for (i = 0; i < wcslen(wstr); i )
191 {
192 /* 转换:transformation */
193 FT_Set_Transform(face, 0, &pen);
194
195 /* 加载位图: load glyph image into the slot (erase previous one) */
196 error = FT_Load_Char(face, wstr[i], FT_LOAD_RENDER);
197 if (error)
198 {
199 printf("FT_Load_Char error\n");
200 return -1;
201 }
202
203 /* 在 LCD 上绘制: 使用 LCD 坐标 */
204 draw_bitmap( &slot->bitmap,
205 slot->bitmap_left,
206 var.yres - slot->bitmap_top);
207
208 /* 计算下一个字符的原点: increment pen position */
209 pen.x = slot->advance.x;
210 pen.y = slot->advance.y;
211 }
212
213 return 0;
214 }
上机实验
编译命令(如果你使用的交叉编译链前缀不是 arm-buildroot-linux-gnueabihf,请自行修改命令):
$ arm-buildroot-linux-gnueabihf-gcc -o show_line show_line.c -lfreetype
将编译好的 show_line 文件与 simsun.ttc 字体文件拷贝至开发板,这 2 个文件放在同一个目录下,然后执行以下命令(其中的 3 个数字分别表示 LCD 的 X 坐标、Y 坐标、字体大小):
[root@board:~]# ./show_line ./simsun.ttc 10 200 80
如果实验成功,可以在 LCD 上看到一行文字“百问网 www.100ask.net”。
做两道题:修改程序,支持倾斜角度显示一行文字。
修改程序,支持显示多行文字。
点击“了解更多”阅读更多相关章节
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved