黑暗模式
如何绘制旋转文字
要旋转文字只能用 vgcanvas 绘制文字。在不同的情况下,AWTK 底层采用不同的 vgcanvas 引擎,遗憾的是部分 vgcanvas 引擎并不支持绘制文字。事实上只能在用 OpenGL 的情况下,才支持绘制文字。
不过没有关系,毕竟在嵌入式平台,旋转文字的需求不多,如果确实需要,也是有解决方案的。本文介绍一种跨平台的绘制旋转的文字方法。
字体引擎(比如 stb/freetype) 会把矢量字体转换成一种特殊位图,这个位图只有透明通道 (alpha) 信息,在 AWTK 中用 glyph_t 表示。vgcanvas 引擎都支持贴图功能,只要把 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;
uint32_t baseline = 0;
bitmap_t* bitmap = NULL;
uint32_t font_size = canvas->font_size;
font_manager_t* fm = canvas->font_manager;
font_t* font = font_manager_get_font(fm, canvas->font_name, font_size);
return_value_if_fail(font != NULL, NULL);
vm = font_get_vmetrics(font, font_size);
h = vm.ascent - vm.descent;
return_value_if_fail(h > 0, NULL);
baseline = vm.ascent;
for (i = 0; str[i]; i++) {
return_value_if_fail(font_get_glyph(font, str[i], font_size, &g) == RET_OK, NULL);
w += g.advance + 1;
}
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++) {
int32_t dx = ox + g.x + x;
int32_t dy = baseline + g.y + y;
uint32_t* d = p + dy * w + dx;
const uint8_t* s = g.data + y * g.w + x;
tc.rgba.a = *s;
*d = tc.color;
}
}
ox += g.advance + 1;
}
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
vgcanvas 的 API 基本上是参考 HTML5 Canvas API 定义的,这个 API 是我见过最好的 2D 绘图 API。不过,vgcanvas 在没有 GPU 的情况下,性能远远不如 canvas,除非有旋转之类的特殊需求,尽量使用 canvas 的 API。