2020-06-06 16:54:04 +08:00
|
|
|
|
# 如何绘制旋转文字
|
|
|
|
|
|
|
|
|
|
要旋转文字只能用 [vgcanvas](https://github.com/zlgopen/awtk/blob/master/docs/manual/vgcanvas_t.md) 绘制文字。在不同的情况下,AWTK 底层采用不同的 [vgcanvas](https://github.com/zlgopen/awtk/blob/master/docs/manual/vgcanvas_t.md) 引擎,遗憾的是部分 [vgcanvas](https://github.com/zlgopen/awtk/blob/master/docs/manual/vgcanvas_t.md) 引擎并不支持绘制文字。事实上只能在用 OpenGL 的情况下,才支持绘制文字。
|
|
|
|
|
|
|
|
|
|
不过没有关系,毕竟在嵌入式平台,旋转文字的需求不多,如果确实需要,也是有解决方案的。本文介绍一种跨平台的绘制旋转的文字方法。
|
|
|
|
|
|
|
|
|
|
字体引擎(比如 stb/freetype) 会把矢量字体转换成一种特殊位图,这个位图只有透明通道 (alpha) 信息,在 AWTK 中用 glyph\_t 表示。[vgcanvas](https://github.com/zlgopen/awtk/blob/master/docs/manual/vgcanvas_t.md) 引擎都支持贴图功能,只要把 glyph\_t 转换成正常 bitmap\_t 对象,就可以利用 vgcanvas 各种变换效果了。
|
|
|
|
|
|
|
|
|
|
下面这个函数可以把字符串对应的 glyph 转换成位图对象(拿去用就好了):
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
static bitmap_t* bitmap_from_str(canvas_t* canvas, wchar_t* str, color_t tc) {
|
|
|
|
|
glyph_t g;
|
|
|
|
|
uint32_t x = 0;
|
|
|
|
|
uint32_t y = 0;
|
|
|
|
|
uint32_t i = 0;
|
|
|
|
|
uint32_t w = 0;
|
|
|
|
|
uint32_t h = 0;
|
|
|
|
|
uint32_t ox = 0;
|
|
|
|
|
font_vmetrics_t vm;
|
|
|
|
|
uint32_t* p = NULL;
|
2020-06-11 17:56:31 +08:00
|
|
|
|
uint32_t baseline = 0;
|
2020-06-06 16:54:04 +08:00
|
|
|
|
bitmap_t* bitmap = NULL;
|
|
|
|
|
uint32_t font_size = canvas->font_size;
|
|
|
|
|
font_manager_t* fm = canvas->font_manager;
|
2020-06-07 16:55:33 +08:00
|
|
|
|
font_t* font = font_manager_get_font(fm, canvas->font_name, font_size);
|
2020-06-06 16:54:04 +08:00
|
|
|
|
return_value_if_fail(font != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
vm = font_get_vmetrics(font, font_size);
|
2020-06-11 17:56:31 +08:00
|
|
|
|
h = vm.ascent - vm.descent;
|
2020-06-06 16:54:04 +08:00
|
|
|
|
return_value_if_fail(h > 0, NULL);
|
|
|
|
|
|
2020-06-11 17:56:31 +08:00
|
|
|
|
baseline = vm.ascent;
|
2020-06-06 16:54:04 +08:00
|
|
|
|
for (i = 0; str[i]; i++) {
|
|
|
|
|
return_value_if_fail(font_get_glyph(font, str[i], font_size, &g) == RET_OK, NULL);
|
2020-06-11 17:56:31 +08:00
|
|
|
|
w += g.advance + 1;
|
2020-06-06 16:54:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bitmap = bitmap_create_ex(w, h, 0, BITMAP_FMT_RGBA8888);
|
|
|
|
|
return_value_if_fail(bitmap != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
p = (uint32_t*)bitmap_lock_buffer_for_write(bitmap);
|
|
|
|
|
|
|
|
|
|
memset(p, 0x00, w * h * 4);
|
|
|
|
|
|
|
|
|
|
for (i = 0; str[i]; i++) {
|
|
|
|
|
return_value_if_fail(font_get_glyph(font, str[i], font_size, &g) == RET_OK, NULL);
|
|
|
|
|
|
|
|
|
|
for (y = 0; y < g.h; y++) {
|
|
|
|
|
for (x = 0; x < g.w; x++) {
|
2020-06-11 17:56:31 +08:00
|
|
|
|
int32_t dx = ox + g.x + x;
|
|
|
|
|
int32_t dy = baseline + g.y + y;
|
|
|
|
|
|
|
|
|
|
uint32_t* d = p + dy * w + dx;
|
2020-06-06 16:54:04 +08:00
|
|
|
|
const uint8_t* s = g.data + y * g.w + x;
|
2020-06-11 17:56:31 +08:00
|
|
|
|
|
2020-06-06 16:54:04 +08:00
|
|
|
|
tc.rgba.a = *s;
|
|
|
|
|
*d = tc.color;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-06-11 17:56:31 +08:00
|
|
|
|
ox += g.advance + 1;
|
2020-06-06 16:54:04 +08:00
|
|
|
|
}
|
|
|
|
|
bitmap_unlock_buffer(bitmap);
|
|
|
|
|
bitmap->flags |= BITMAP_FLAG_CHANGED;
|
|
|
|
|
|
|
|
|
|
return bitmap;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
然后?然后就和画图一样了:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
vgcanvas_save(vg);
|
|
|
|
|
vgcanvas_translate(vg, c->ox, c->oy);
|
|
|
|
|
|
|
|
|
|
vgcanvas_translate(vg, cx, cy);
|
|
|
|
|
vgcanvas_rotate(vg, info->rotation);
|
|
|
|
|
vgcanvas_scale(vg, info->scale, info->scale);
|
|
|
|
|
vgcanvas_translate(vg, -cx, -cy);
|
|
|
|
|
|
|
|
|
|
canvas_widget_draw_image_center(widget, vg, text_img);
|
|
|
|
|
|
|
|
|
|
vgcanvas_restore(vg);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
完整代码请参考:[vgcanvas_draw_text](https://github.com/zlgopen/awtk-c-demos/blob/master/demos/vgcanvas_draw_text.c)
|
|
|
|
|
|
|
|
|
|
vgcanvas 的 API 基本上是参考 [HTML5 Canvas API](https://www.w3schools.com/tags/ref_canvas.asp) 定义的,这个 API 是我见过最好的 2D 绘图 API。不过,[vgcanvas](https://github.com/zlgopen/awtk/blob/master/docs/manual/vgcanvas_t.md) 在没有 GPU 的情况下,性能远远不如 [canvas](https://github.com/zlgopen/awtk/blob/master/docs/manual/canvas_t.md),除非有旋转之类的特殊需求,尽量使用 [canvas](https://github.com/zlgopen/awtk/blob/master/docs/manual/canvas_t.md) 的 API。
|