# 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_manager assets_manager_t* 资源管理器对象
clip_bottom xy_t 当前裁剪矩形的底部位置
clip_left xy_t 当前裁剪矩形的左边位置
clip_right xy_t 当前裁剪矩形的右边位置
clip_top xy_t 当前裁剪矩形的顶部位置
font font_t* 字体对象
font_manager font_manager_t* 字体管理器对象
font_name char* 当前字体名称
font_size uint16_t 当前字体大小
fps uint32_t 当前的帧率
global_alpha uint8_t 当前全局alpha
lcd lcd_t* lcd对象
ox xy_t x坐标偏移
oy xy_t y坐标偏移
show_fps bool_t 是否显示帧率
text_align_h align_h_t 文本水平对齐方式
text_align_v align_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.1 vgcanvas的UML图
图6.1 vgcanvas的UML图

# 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_flush flush
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_alias bool_t 是否启用反走样功能
fill_color color_t 填充颜色
font char* 字体
font_size float_t 字体大小
global_alpha float_t 全局alpha
h wh_t canvas的高度
line_cap const char* line_cap
line_join const char* line_join
line_width float_t 线宽
miter_limit float_t miter_limit
ratio float_t 显示比例
stride uint32_t 一行占的字节
stroke_color color_t 线条颜色
text_align const char* 文本对齐方式
text_baseline const char* 文本基线
w wh_t canvas的宽度

# 6.2.4 示例

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

图6.2 vgcanvas示例
图6.2 vgcanvas示例

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

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

具体代码如下:

/* 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 (opens new window)

# 6.3 离线画布

# 6.3.1 简介

1. 在线画布

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

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

完整示例请参考 demo_vg_app.c (opens new window)

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

完整示例请参考 guage.c (opens new window)

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还提供了下面属性,详见下表:

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

# 6.3.4 示例

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

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

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函数结束绘图。例如,把整个窗口绘制到离线画布上,代码如下:

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,代码如下:

canvas_offline_destroy(canvas_offline);

完整示例请参考 demo_canvas_offline.c (opens new window)