Skip to content

6. 画布

本章导读:

AWTK提供了各种绘制图像的API接口,方便程序员绘制直线、矩形、椭圆等形状。也可以根据AWTK提供的API接口绘制自己想要的控件,例如饼图、柱状图等。AWTK提供了两种画布:普通和矢量图画布,通过调用这两种画布提供的画图接口,实现不同的绘图功能。

6.1 普通画布

6.1.1 简介

canvas类。普通画布可以实现一些简单的绘制功能,如:绘制水平或垂直直线、文本、图片、矩形等。如果需要绘制比较复杂一点的图形就需要使用矢量图画布,如:绘制椭圆、圆弧等。

6.1.2 函数

canvas提供的函数详见下表,具体的函数API请查看AWTK_API手册。

函数名称说明
canvas_begin_frame绘制开始
canvas_cast转换为canvas对象(供脚本语言使用)
canvas_clear_rect用填充颜色填充指定矩形
canvas_draw_hline画水平线
canvas_draw_icon绘制图标
canvas_draw_image绘制图片
canvas_draw_image_at在指定位置画图
canvas_draw_image_ex绘制图片
canvas_draw_image_ex2绘制图片
canvas_draw_line画直线
canvas_draw_points画多个点
canvas_draw_text绘制文本
canvas_draw_text_bidi_in_rect绘制文本
canvas_draw_text_in_rect绘制文本
canvas_draw_utf8绘制文本
canvas_draw_utf8_in_rect绘制文本
canvas_draw_vline画垂直线
canvas_end_frame绘制结束
canvas_fill_rect绘制矩形
canvas_fill_rect_gradient绘制矩形
canvas_fill_rounded_rect填充区域
canvas_fill_rounded_rect_ex填充圆角矩形区域
canvas_fill_rounded_rect_gradient填充圆角矩形区域
canvas_fill_rounded_rect_gradient_ex填充圆角矩形区域
canvas_get_clip_rect获取裁剪区
canvas_get_font_height获取字体的高度
canvas_get_height获取画布的高度
canvas_get_text_metrics获取当前字体的度量信息
canvas_get_vgcanvas获取vgcanvas对象
canvas_get_width获取画布的宽度
canvas_init初始化,系统内部调用
canvas_measure_text计算文本所占的宽度
canvas_measure_utf8计算文本所占的宽度
canvas_reset释放相关资源
canvas_set_assets_manager设置canvas的assets_manager对象
canvas_set_clip_rect设置裁剪区
canvas_set_clip_rect_ex设置裁剪区
canvas_set_fill_color设置填充颜色
canvas_set_fill_color_str设置填充颜色
canvas_set_font设置字体
canvas_set_font_manager设置canvas的font_manager对象
canvas_set_fps设置FPS
canvas_set_global_alpha设置全局alpha值
canvas_set_stroke_color设置线条颜色
canvas_set_stroke_color_str设置线条颜色
canvas_set_text_align设置文本对齐方式
canvas_set_text_color设置文本颜色
canvas_set_text_color_str设置文本颜色
canvas_stroke_rect绘制矩形
canvas_stroke_rounded_rect绘制边框
canvas_stroke_rounded_rect_ex绘制边框
canvas_translate平移原点坐标
canvas_untranslate反向平移原点坐标

6.1.3 属性

canvas还提供了下面属性,详见下表:

属性名称类型说明
assets_managerassets_manager_t*资源管理器对象
clip_bottomxy_t当前裁剪矩形的底部位置
clip_leftxy_t当前裁剪矩形的左边位置
clip_rightxy_t当前裁剪矩形的右边位置
clip_topxy_t当前裁剪矩形的顶部位置
fontfont_t*字体对象
font_managerfont_manager_t*字体管理器对象
font_namechar*当前字体名称
font_sizeuint16_t当前字体大小
fpsuint32_t当前的帧率
global_alphauint8_t当前全局alpha
lcdlcd_t*lcd对象
oxxy_tx坐标偏移
oyxy_ty坐标偏移
show_fpsbool_t是否显示帧率
text_align_halign_h_t文本水平对齐方式
text_align_valign_v_t文本垂直对齐方式

6.1.4 示例

canvas的用法与vgcanvas的类似,请参考下文6.2.4章节。

6.2 矢量图画布

6.2.1 简介

vgcanvas_t矢量图画布抽象基类。与canvas相比vgcanvas的效率要低一些,但功能也丰富些。绘制一些简单的图形,如线条、矩形等可以用canvas;复杂一点图形,如圆角矩形就用vgcanvas。

具体实现时,vgcanvas内部调用了nanovg、cairo的功能进行绘图。目前只提供了基于nanovg的实现,支持软件渲染和硬件渲染。AWTK对nanovg进行了一些改进:

  • 可以用agg/agge实现软件渲染(暂时不支持文本绘制)
  • 可以用bgfx使用DirectX(Windows平台)、Metal(iOS平台)和使用OpenGL,Vulkan(Linux平台)硬件加速

6.2.2 函数

vgcanvas提供的函数详见下表,具体的函数API请查看AWTK_API手册。

函数名称说明
vgcanvas_arc生成一条圆弧
vgcanvas_arc_to生成一条圆弧路径到指定点
vgcanvas_begin_frame开始绘制,系统内部调用
vgcanvas_begin_path清除之前的路径,并重新开始一条路径
vgcanvas_bezier_to生成一条三次贝塞尔曲线
vgcanvas_bind_fbo绑定 fbo 对象
vgcanvas_cast转换为vgcanvas对象(供脚本语言使用)
vgcanvas_clear_cache释放vgcanvas对象的缓冲数据
vgcanvas_clear_rect用颜色清除指定矩形区域
vgcanvas_clip_path使用当前的path裁剪
vgcanvas_clip_rect矩形裁剪
vgcanvas_close_path闭合路径
vgcanvas_create创建vgcanvas
vgcanvas_create_fbo创建 fbo 对象
vgcanvas_destroy销毁vgcanvas对象
vgcanvas_destroy_fbo销毁 fbo 对象
vgcanvas_draw_icon绘制图标
vgcanvas_draw_image绘制图片
vgcanvas_ellipse生成一个椭圆路径
vgcanvas_end_frame结束绘制系统内部调用
vgcanvas_fbo_to_bitmap把 fbo 对象的数据拷贝到 bitmap 中
vgcanvas_fill填充多边形
vgcanvas_fill_text绘制文本
vgcanvas_flushflush
vgcanvas_get_height获取高度
vgcanvas_get_text_metrics获取当前字体的度量信息
vgcanvas_get_width获取宽度
vgcanvas_intersect_clip_rect设置一个与前一个裁剪区做交集的矩形裁剪区
vgcanvas_is_point_in_path检查点是否在当前路径中
vgcanvas_line_to生成一条线段(从当前点到目标点)
vgcanvas_measure_text测量文本的宽度
vgcanvas_move_to移动当前点到指定点
vgcanvas_paint用图片填充/画多边形(可能存在可移植性问题,除非必要请勿使用)
vgcanvas_path_winding设置路径填充实心与否
vgcanvas_quad_to生成一条二次贝塞尔曲线
vgcanvas_rect生成一个矩形路径
vgcanvas_reinit重新初始化,系统内部调用
vgcanvas_reset重置所有状态
vgcanvas_reset_curr_state重置当前状态
vgcanvas_restore恢复上次save的状态
vgcanvas_rotate旋转
vgcanvas_rounded_rect生成一个圆角矩形路径
vgcanvas_save保存当前的状态如颜色和矩阵等信息
vgcanvas_scale缩放
vgcanvas_set_antialias设置是否启用反走样
vgcanvas_set_fill_color设置填充颜色
vgcanvas_set_fill_color_str设置填充颜色
vgcanvas_set_fill_gradient设置填充颜色为渐变色
vgcanvas_set_fill_linear_gradient设置填充颜色为线性渐变色
vgcanvas_set_fill_radial_gradient设置填充颜色为径向渐变色
vgcanvas_set_font设置字体的名称
vgcanvas_set_font_size设置字体的大小
vgcanvas_set_global_alpha设置全局透明度
vgcanvas_set_line_cap设置line cap
vgcanvas_set_line_join设置line join
vgcanvas_set_line_width设置线条的宽度
vgcanvas_set_miter_limit设置miter limit
vgcanvas_set_stroke_color设置线条颜色
vgcanvas_set_stroke_color_str设置线条颜色
vgcanvas_set_stroke_gradient设置线条颜色为渐变色
vgcanvas_set_stroke_linear_gradient设置线条颜色为线性渐变色
vgcanvas_set_stroke_radial_gradient设置线条颜色为径向渐变色
vgcanvas_set_text_align设置文本水平对齐的方式
vgcanvas_set_text_baseline设置文本垂直对齐的方式
vgcanvas_set_transform设置变换矩阵
vgcanvas_stroke画线
vgcanvas_transform变换矩阵
vgcanvas_translate平移
vgcanvas_unbind_fbo解开绑定 fbo 对象

6.2.3 属性

vgcanvas还提供了下面属性,详见下表:

属性名称类型说明
anti_aliasbool_t是否启用反走样功能
fill_colorcolor_t填充颜色
fontchar*字体
font_sizefloat_t字体大小
global_alphafloat_t全局alpha
hwh_tcanvas的高度
line_capconst char*line_cap
line_joinconst char*line_join
line_widthfloat_t线宽
miter_limitfloat_tmiter_limit
ratiofloat_t显示比例
strideuint32_t一行占的字节
stroke_colorcolor_t线条颜色
text_alignconst char*文本对齐方式
text_baselineconst char*文本基线
wwh_tcanvas的宽度

6.2.4 示例

例如:要实现下图所示的效果,步骤如下:

步骤一:创建canvas_widget控件,并为该控件注册EVT_PAINT绘制事件的回调函数on_paint_vg。

步骤二:在on_paint_vg回调函数中调用canvas或者vgcanvas画布接口提供的函数进行重绘。

具体代码如下:

c
/* awtk/demos/demo_vg_app.c */
static ret_t on_paint_vg(void* ctx, event_t* e) {
  paint_event_t* evt = (paint_event_t*)e;
  canvas_t* c = evt->c;
  vgcanvas_t* vg = canvas_get_vgcanvas(c);

  vgcanvas_save(vg);
  vgcanvas_set_line_width(vg, 1);
  vgcanvas_set_stroke_color(vg, color_init(0, 0xff, 0, 0xff));
  vgcanvas_set_fill_color(vg, color_init(0xff, 0, 0, 0xff));
  ...
  return RET_OK;
}

ret_t application_init() {
  widget_t* win = window_create(NULL, 0, 0, 0, 0);
  widget_t* canvas = canvas_widget_create(win, 0, 0, win->w, win->h);
  widget_on(canvas, EVT_PAINT, on_paint_vg, NULL);

  timer_add(on_timer, win, 500);

  return RET_OK;
}

完整示例请参考 demo_vg_app.c

6.3 离线画布

6.3.1 简介

1. 在线画布

通常可以调用canvas或者vgcanvas画布接口提供的函数,将要绘制的内容显示到屏幕上,称这种方式为在线画布,并且可以通过下面几种方式实现:

(1)方式一:创建canvas_widget控件,并为该控件注册EVT_PAINT绘制事件的回调函数,在该回调函数中调用canvas或者vgcanvas画布接口提供的函数进行绘图。

完整示例请参考 demo_vg_app.c

(2)方式二:在控件中的on_paint_self自绘函数中,调用canvas或者vgcanvas画布接口提供的函数进行绘图。

完整示例请参考 guage.c

2. 离线画布

将canvas绘制到内存bitmap对象中,然后可以对bitmap对象做进一步处理,比如将bitmap对象保存到文件中,实现截图效果,称这种方式为离线画布。

为了解决用户离线画布的需求,在AWTK中提供了canvas_offline类供用户使用。

6.3.2 函数

canvas_offline类提供了下表中的函数,具体的函数API请查看AWTK_API手册。

函数名称说明
canvas_offline_begin_draw设置离线 canvas 开始绘图
canvas_offline_bitmap_move_to_new_bitmap把离线 canvas 的离线 bitmap 移动赋值给新的 bitmap
canvas_offline_clear_canvas清除离线 canvas 所有数据,并把背景设置为全透明
canvas_offline_create创建一个离线的 canvas
canvas_offline_custom_begin_draw用户自定义 canvas_offline_custom_begin_draw
canvas_offline_custom_bitmap_move_to_new_bitmap用户自定义 canvas_offline_custom_bitmap_move_to_new_bitmap
canvas_offline_custom_clear_canvas用户自定义 canvas_offline_custom_clear_canvas
canvas_offline_custom_create用户自定义 canvas_offline_create
canvas_offline_custom_destroy用户自定义 canvas_offline_custom_destroy
canvas_offline_custom_end_draw用户自定义 canvas_offline_custom_end_draw
canvas_offline_custom_flush_bitmap用户自定义 canvas_offline_custom_flush_bitmap
canvas_offline_custom_get_bitmap用户自定义 canvas_offline_custom_get_bitmap
canvas_offline_destroy释放离线 canvas 和离线 bitmap
canvas_offline_end_draw设置离线 canvas 结束绘图
canvas_offline_flush_bitmap把离线 canvas 的数据放到绑定的 bitmap 中
canvas_offline_get_bitmap获取离线 canvas 的离线 bitmap

6.3.3 属性

canvas_offline还提供了下面属性,详见下表:

属性名称类型说明
bitmapbitmap_t*绑定的离线 bitmap

6.3.4 示例

例如,使用离线画布完成一个截屏的功能,其步骤如下:

步骤一:创建离线画布。调用canvas_offline_create函数创建离线画布,在离线画布内置了一个离线的bitmap位图,提供给用户使用。创建离线画布,代码如下:

c
canvas_t* canvas_offline = canvas_offline = canvas_offline_create(320, 480, BITMAP_FMT_RGBA8888);

在OpenGL模式下离线画布canvas格式只能为RGBA8888;在AGGE模式下可以为:RGBA8888、BGRA8888、RGB565和BGR5656。(其他的格式暂时不支持)

步骤二:绘图。离线画布的绘图过程和平时使用canvas或者vgcanvas绘图是一样的,只不过在绘制之前需要先调用canvas_offline_begin_draw函数开始绘图,并在绘制结束的时候调用canvas_offline_end_draw函数结束绘图。例如,把整个窗口绘制到离线画布上,代码如下:

c
bitmap_t* offline_bitmap = NULL;
canvas_offline_begin_draw(canvas_offline);       /* 开始离线 canvas 绘图 */
widget_paint(window_manager(), canvas_offline);  /* 把整个窗口绘制到离线的 canvas 中 */
canvas_offline_end_draw(canvas_offline);         /* 结束离线 canvas 绘图 */

/* 由于需要把 bitmap 保存为 png 文件,所以需要把显存中的数据回传到内存中 */
canvas_offline_flush_bitmap(canvas_offline);
offline_bitmap = canvas_offline_get_bitmap(canvas_offline); /* 获取离线 bitmap */
bitmap_save_png(offline_bitmap, "test.png");                /* 把 bitmap 保存为 png 文件 */

步骤三:释放离线画布和绑定的离线 bitmap,代码如下:

c
canvas_offline_destroy(canvas_offline);

完整示例请参考 demo_canvas_offline.c