0
点赞
收藏
分享

微信扫一扫

#夏日挑战赛#移植littleVGL库到OpenHarmony过程分享

移植轻量级通用型图形库到OpenHarmony

本文正在参加星光计划3.0–夏日挑战赛

一、项目简介

1.1 littleVGL 主要特性如下

  • 具有非常丰富的内置控件,像 buttons, charts, lists, sliders, images 等
  • 高级图形效果:动画,反锯齿,透明度,平滑滚动
  • 支持多种输入设备,像 touchpad, mouse, keyboard, encoder 等
  • 支持多语言的 UTF-8 编码 • 支持多个和多种显示设备,例如同步显示在多个彩色屏或单色屏上
  • 完全自定制的图形元素
  • 硬件独立于任何微控制器或显示器
  • 可以缩小到最小内存 (64 kB Flash, 16 kB RAM)
  • 支持操作系统、外部储存和 GPU(非必须)
  • 仅仅单个帧缓冲设备就可以呈现高级视觉特效
  • 使用 C 编写以获得最大兼容性(兼容 C++)
  • 支持 PC 模拟器
  • 为加速 GUI 设计,提供教程,案例和主题,支持响应式布局
  • 提供了在线和离线文档
  • 基于自由和开源的 MIT 协议

1.2 littleVGL 的要求如下:

  • 16、32 或 64 位的单片机(微控制器)或处理器
  • 微处理器的主频最好高于 16MHZ
  • Flash/ROM:如果只用 littleVGL 核心组件的话,则至少需要 64kB 的容量,如果想完整使用的 话,最好保证 180kB 以上的容量
  • RAM:
  • 静态 RAM: 大约 8 到 16 kB,这取决于你所用的组件功能和 objects 控件对象类型
  • 栈: 至少为 2Kb,一般推荐值为 4kBo 动态数据(堆): 至少 4kB,如果你用到了多个或多种控件的话,那么最好设置为 16kB 以 上,这个是可以通过 lv_conf.h 配置文件中的 LV_MEM_SIZE 宏来定义的
  • 显示缓冲区: 至少要比”水平分辨率像素”要大,一般推介值为 10 倍的”水平分辨率像 素”,取个例子,假如我们屏幕的水平分辨率为480个像素,采用16位的颜色深度进行显 示,即一个像素占 2 个字节,那么推介的显示缓冲区大小为 104802=9600 个字节
  • C99 或更新的编译器,如果是用 keil 开发的话,一定得勾选”c99”模式,否则编译会报错的
  • 基本的 c(或者 c++)语言知识,如:指针,结构体,回调函数

1.3 开源项目链接

  • littleVGL 的官方网址为: https://littlevgl.com
  • littleVGL 的 github 网址为: https://github.com/littlevgl/lvgl
  • littleVGL 的在线文档网址为: https://docs.littlevgl.com/zh-CN/html/index.html

二、 littleVGL 移植

2.1 开发前准备

  • 本次分享硬件采用的是HI3861开发板和SPI驱动的TFT显示屏
  • 搭建环境请参考上一篇文章
  • 软件包已上传附件,感兴趣可下载体验移植的乐趣

2.2 项目创建

2.2.1 在applications/sample/wifi-iot/app目录下创建一个GUI文件夹

image20220617163137883.png

GUI 目录是用来存放跟 littleVGL 库相关的所有文件的

2.2.2 解压lv_pc_simulator.zip包

接着把 lv_pc_simulator.zip 压缩包里面的 lv_examples.zip 和 lvgl.zip 俩个子压缩包直接拷 贝到GUI 目录下,拷贝完成之后,接着分别对lv_examples.zip 和 lvgl.zip 俩个子压缩包 在当前目录下进行解压缩操作,解压缩完成后,可以把 lv_examples.zip 和 lvgl.zip 都删除了

2.2.3 拷贝配置模板文件

接 着把 GUI/lvgl/lv_conf_template.h 和 GUI/lv_examples/lv_ex_conf_templ.h 俩 个配置模板文件统统拷贝到 GUI 目录下,然后对这个 2 文件分别重命名为 lv_conf.h和 lv_ex_conf.h

2.2.4 新建lvgl_driver子目录

接着还要在 GUI 目录下新建一个 lvgl_driver子目录,这个目录是用来 放底层显示驱动和触摸驱动文件的,最后 GUI 的目录结构如下图所示

image20220617164349718.png

注:在实际项目中,可以删除掉 lv_examples 目录来减少项目所占的磁盘空间,因为此目录就是 专门用来存放官方的演示 demo,对我们的实际项目没有任何作用

2.3 编写BUILD.gn文件

在GUI目录下添加BUILD.gn文件

group("GUI") {
    deps = [
        "lvgl:lvgl",
        "lvgl_driver:lvgl_port",
    ]
}

在GUI/lvgl_driver目录下添加BUILD.gn文件

static_library("lvgl_port") {
    sources = [
        "lv_port_disp.c",
    ]

    include_dirs = [
        "//base/iot_hardware/peripheral/interfaces/kits",
        "../../",
        "../lvgl_driver",

    ]

}

在GUI/lv_examples目录下添加BUILD.gn文件

static_library("lv_examples") {
    sources = [
        # "src/lv_demo_benchmark/lv_demo_benchmark.c",
        # "src/lv_demo_keypad_encoder/lv_demo_keypad_encoder.c",
        # "src/lv_demo_music/lv_demo_music.c",
        # "src/lv_demo_printer/lv_demo_printer.c",
        # "src/lv_demo_stress/lv_demo_stress.c",
        "src/lv_demo_widgets/lv_demo_widgets.c",
        # "src/lv_ex_get_started/lv_ex_get_started.c",
        # "src/lv_demo_widgets/lv_demo_widgets.c",
    ]

    cflags = [ "-Wno-unused-variable" ]
    cflags += [ "-Wno-unused-but-set-variable" ]
    cflags += [ "-Wno-unused-parameter" ]

    include_dirs = [
        "src/lv_demo_widgets",
    ]

}

在GUI/lvgl/BUILD.gn目录下添加BUILD.gn文件

```c++
static_library("lvgl") {
sources = [
"src/lv_core/lv_disp.c",
"src/lv_core/lv_group.c",
"src/lv_core/lv_indev.c",
"src/lv_core/lv_obj.c",
"src/lv_core/lv_refr.c",
"src/lv_core/lv_style.c",

    "src/lv_draw/lv_draw_basic.c",
    "src/lv_draw/lv_draw.c",
    "src/lv_draw/lv_draw_rect.c",
    "src/lv_draw/lv_draw_label.c",
    "src/lv_draw/lv_draw_line.c",
    "src/lv_draw/lv_draw_img.c",
    "src/lv_draw/lv_draw_arc.c",
    "src/lv_draw/lv_draw_triangle.c",
    "src/lv_draw/lv_img_decoder.c",
    "src/lv_draw/lv_img_cache.c",

    "src/lv_font/lv_font.c",
    "src/lv_font/lv_font_fmt_txt.c",
    "src/lv_font/lv_font_roboto_12.c",
    "src/lv_font/lv_font_roboto_16.c",
    "src/lv_font/lv_font_roboto_22.c",
    "src/lv_font/lv_font_roboto_28.c",
    "src/lv_font/lv_font_unscii_8.c",

    "src/lv_hal/lv_hal_disp.c",
    "src/lv_hal/lv_hal_indev.c",
    "src/lv_hal/lv_hal_tick.c",

    "src/lv_misc/lv_circ.c",
    "src/lv_misc/lv_area.c",
    "src/lv_misc/lv_task.c",
    "src/lv_misc/lv_fs.c",
    "src/lv_misc/lv_anim.c",
    "src/lv_misc/lv_mem.c",
    "src/lv_misc/lv_ll.c",
    "src/lv_misc/lv_color.c",
    "src/lv_misc/lv_txt.c",
    "src/lv_misc/lv_math.c",
    "src/lv_misc/lv_log.c",
    "src/lv_misc/lv_gc.c",
    "src/lv_misc/lv_utils.c",
    "src/lv_misc/lv_async.c",

    "src/lv_themes/lv_theme_alien.c",
    "src/lv_themes/lv_theme.c",
    "src/lv_themes/lv_theme_default.c",
    "src/lv_themes/lv_theme_night.c",
    "src/lv_themes/lv_theme_templ.c",
    "src/lv_themes/lv_theme_zen.c",
    "src/lv_themes/lv_theme_material.c",
    "src/lv_themes/lv_theme_nemo.c",
    "src/lv_themes/lv_theme_mono.c",

    "src/lv_objx/lv_arc.c",
    "src/lv_objx/lv_bar.c",
    "src/lv_objx/lv_cb.c",
    "src/lv_objx/lv_ddlist.c",
    "src/lv_objx/lv_kb.c",
    "src/lv_objx/lv_line.c",
    "src/lv_objx/lv_mbox.c",
    "src/lv_objx/lv_preload.c",
    "src/lv_objx/lv_roller.c",
    "src/lv_objx/lv_table.c",
    "src/lv_objx/lv_tabview.c",
    "src/lv_objx/lv_tileview.c",
    "src/lv_objx/lv_btn.c",
    "src/lv_objx/lv_calendar.c",
    "src/lv_objx/lv_chart.c",
    "src/lv_objx/lv_canvas.c",
    "src/lv_objx/lv_gauge.c",
    "src/lv_objx/lv_label.c",
    "src/lv_objx/lv_list.c",
    "src/lv_objx/lv_slider.c",
    "src/lv_objx/lv_ta.c",
    "src/lv_objx/lv_spinbox.c",
    "src/lv_objx/lv_btnm.c",
    "src/lv_objx/lv_cont.c",
    "src/lv_objx/lv_img.c",
    "src/lv_objx/lv_imgbtn.c",
    "src/lv_objx/lv_led.c",
    "src/lv_objx/lv_lmeter.c",
    "src/lv_objx/lv_page.c",
    "src/lv_objx/lv_sw.c",
    "src/lv_objx/lv_win.c",

]

cflags = [ "-Wno-unused-variable" ]
cflags += [ "-Wno-unused-but-set-variable" ]
cflags += [ "-Wno-unused-parameter" ]

include_dirs = [
    "lvgl",
]

}


# 移植littleVGL库到OpenHarmony过程分享

### 一、宏定义文件修改——修改 lv_conf.h 和 lv_ex_conf.h 配置文件

先打开 GUI 下的 lv_conf.h 文件,里面的配置项还是很多的,大家先不要纠结每个 配置项到底什么意思,后面我会专门来讲解的
![image20220617172531490.png](https://dl-harmonyos.51cto.com/images/202206/23dcdc126074a349929074e9773159bf85abfe.png?x-oss-process=image/resize,w_447,h_408)

#### 1.1 修改液晶屏分辨率

打开文件之后,第一个#if 后面的 0 改为 1,使整个文件生效,接着修改 LV_HOR_RES_MAX 和 LV_HOR_RES_MAX 宏的值,这个是告诉 littleVGL 你所用的液晶屏 分辨率是多少,请根据自己手头液晶屏的实际分辨率大小相应设置,比如我购买的是240*240,,因此 我这里就设置如下:

```c
#define LV_HOR_RES_MAX (240)
#define LV_VER_RES_MAX (240) 

1.2 修改颜色深度

接着我们修改 LV_COLOR_DEPTH 颜色深度,最常见的设置就是 1 或者 16 了,1 是用于单色 屏,而 16 是用于彩色屏,这里我们设置成 16 即可,即如下所示

/* Color depth:
 * - 1:  1 byte per pixel
 * - 8:  RGB233
 * - 16: RGB565
 * - 32: ARGB8888
 */
#define LV_COLOR_DEPTH     16

1.3 设置 界面缩放比例

再接着我们来设置 LV_DPI 的值,默认值为 100,我们不改变它,这个宏是用来调节界面缩 放比例的,此值越大,控件分布的就越散,控件自身的间隔也会变大

```c++
#define LV_DPI 100


#### 1.4 修改动态分配空间大小

再接着修改 LV_MEM_SIZE 的大小,这个就是控制 littleVGL 中所谓的动态数据堆的大小,是 用来给控件的创建动态分配空间的,我们这里设置为 32KB 的大小

```c
#  define LV_MEM_SIZE    (32U * 1024U)

1.5 修改 GPU使能情况

再接着修改 LV_USE_GPU 的值,默认值是 1,我们把它设置为 0,即不使能 GPU 功能

#define LV_USE_GPU              0

1.6 设置主题

再接着再把 LV_THEME_LIVE_UPDATE, LV_USE_THEME_TEMPL, LV_USE_THEME_DEFAULT, LV_USE_THEME_ALIEN, LV_USE_THEME_NIGHT, LV_USE_THEME_MONO, LV_USE_THEME_MATERIAL, LV_USE_THEME_ZEN, LV_USE_THEME_NEMO 等所有宏 的值都设置为0,即全部不使能,这些宏都是跟littleVGL自带的主题相关的,因为后面我们要自己写一个,所以这里我们先全部不使能

#define LV_THEME_LIVE_UPDATE    0   /*1: Allow theme switching at run time. Uses 8..10 kB of RAM*/

#define LV_USE_THEME_TEMPL      0   /*Just for test*/
#define LV_USE_THEME_DEFAULT    0   /*Built mainly from the built-in styles. Consumes very few RAM*/
#define LV_USE_THEME_ALIEN      0   /*Dark futuristic theme*/
#define LV_USE_THEME_NIGHT      0   /*Dark elegant theme*/
#define LV_USE_THEME_MONO       0   /*Mono color theme for monochrome displays*/
#define LV_USE_THEME_MATERIAL   0   /*Flat theme with bold colors and light shadows*/
#define LV_USE_THEME_ZEN        0   /*Peaceful, mainly light theme */
#define LV_USE_THEME_NEMO       0   /*Water-like theme based on the movie "Finding Nemo"*/

注意,在实际项目中,我们一般最多使能一个, 如果我们项目根本就用不到其自带的主题,那么我们应该把这些宏全部禁止,因为这样可以节 省 flash 和 ram。

1.7 修改 lv_ex_conf.h 文件

至此 lv_conf.h 文件修改就完成了,接下来我们要修改 lv_ex_conf.h 文件,这个文件就简单 很多了,而且这个文件也不是很重要,只有当我们要演示官方自带的例程时,才会用到,下面就 简单做一下说明.

把 LV_EX_KEYBOARD, LV_EX_MOUSEWHEEL, LV_USE_TESTS, LV_USE_TUTORIALS, LV_USE_BENCHMARK, LV_USE_DEMO, LV_USE_TERMINAL 等宏的值全部设置为 0,其 他宏保持默认即可。

#define LV_EX_PRINTF       0       /*Enable printf-ing data in demoes and examples*/
#define LV_EX_KEYBOARD     0       /*Add PC keyboard support to some examples (`lv_drivers` repository is required)*/
#define LV_EX_MOUSEWHEEL   0       /*Add 'encoder' (mouse wheel) support to some examples (`lv_drivers` repository is required)*/
/*Show some widget*/
#define LV_USE_DEMO_WIDGETS        1
#if LV_USE_DEMO_WIDGETS
#define LV_DEMO_WIDGETS_SLIDESHOW  0
#endif

/*Printer demo, optimized for 800x480*/
#define LV_USE_DEMO_PRINTER     0

/*Demonstrate the usage of encoder and keyboard*/
#define LV_USE_DEMO_KEYPAD_AND_ENCODER     0

/*Benchmark your system*/
#define LV_USE_DEMO_BENCHMARK   0

/*Stress test for LVGL*/
#define LV_USE_DEMO_STRESS      0

/*Music player for LVGL*/
#define LV_USE_DEMO_MUSIC      0
#if LV_USE_DEMO_MUSIC
#define LV_DEMO_MUSIC_AUTO_PLAY 0

二、创建OpenHarmony字体

2.1 littleVGL 字体介绍

​ 在 littleVGL 中的字体功能也是非常强大的,支持最高 8bpp(在老版本中存在)的抗锯齿, 另外还有 1bpp,2bpp,4bpp 三个值可选,实现灵活性配置,选择越大的 bpp 值时,要求的 flash 存 储资源也是成倍的增加的,比如 4bpp 的存储消耗是 1bpp 存储消耗的 4 倍,除了存储消耗变大 之外,bpp 值越大,在界面上进行字体渲染时,绘制速度也会越慢,当然了,bpp 值越大,也是有好 处的,那就是绘制出来的字体边缘越平滑,没有毛刺,使我们产品的 UI 界面看上去更高大上,所 以在实际项目中,我们应该根据硬件平台的实际性能来选出一个比较合适的 bpp 值,一般的项 目都是默认采用 4bpp 就可以了。

2.2 使用字体

​ 不论是使用 littleVGL 系统自带的字体,还是使用我们自己创建的字体,他们的使用方法 都是一样的,为了大家更容易接受,我先给大家介绍怎么使用字体,后面我再给大家介绍怎么 创建字体并使用它,我们就先以系统自带的字体为例来讲解怎么使用它,littleVGL 内置了 5 个 字库,如下所示:

字库
lv_font_roboto_16
lv_font_roboto_22
lv_font_roboto_28
lv_font_unscii_8
lv_font_roboto_12
2.2.1 字体类型介绍

​ 其中的 lv_font_roboto_12, lv_font_roboto_16, lv_font_roboto_22,lv_font_roboto_28 都是 Roboto 字体,只不过是细分出了 4 个不同的字体大小,这四个字库全都是 4bpp 抗锯齿的,这四 个字库中每一个字库除了包含所有的可见英文字符外,还都包含了一套相同的图标字符,也就 是我们前面所说的图标字体,这套图标字符有一个自己的字体名为 FontAwesome ,然后 lv_font_unscii_8 是一种非常好的单色屏字体,是 1bpp 的,相当于无抗锯齿的功能,另外 lv_font_unscii_8 字库只包含英文字符,不包含上面所说的图标字符.

​ 本次移植我用的是OpenHarmony开源的字体,所以都没有使能, 如果想使能其他的字体或者想设置默认的字体等,就必须得在 lv_conf.h 头文件中进行配置, 相关的配置宏如下:

#define LV_FONT_ROBOTO_12    0
#define LV_FONT_ROBOTO_16    0
#define LV_FONT_ROBOTO_22    0
#define LV_FONT_ROBOTO_28    0

/*Pixel perfect monospace font
 * http://pelulamu.net/unscii/ */
#define LV_FONT_UNSCII_8     0

2.3 如何创建自己的字体

2.3.1 安装node.js

离线工具是用 node.js 开发出来的,所以我们需要先安装 node.js 的运行环境,安装 node.js,过程有点久,请耐心等待!

我这里给出一个网上的参考教程:Node.js 安装配置 | 菜鸟教程 (runoob.com)

2.3.2 安装离线工具包

在安装完 node.js(会附带把 npm 包管 理器给装好)之后,我们接下来要安装 lv_font_conv 离线转换工具了,操作很简单,先打开 cmd 命令窗口,然后直接输入 npm i lv_font_conv -g 命令,回车运行就会把 lv_font_conv 给安装 好

```c++
npm i lv_font_conv -g

![node.png](https://dl-harmonyos.51cto.com/images/202206/7135f9e02aa5929f2942336baba4105a905c1c.png?x-oss-process=image/resize,w_820,h_218)

##### 2.3.3  lv_font_conv 的主要命令行参数

**--bpp**: 抗锯齿大小,可选值为 1-4 

**--size**: 字体的大小,实际就是指字符的高度 

**-o(或者--output)**: 输出路径,比如为 C:\Users\han\Desktop\my_font.c

**--format**: 输出格式,可选值有 dump,bin,lvgl,我们只用 lvgl 就行了

 **--font**: ttf/woff/woff2 字体文件的路径 

**-r(或--range)**: 所需字符的 unicode 编码范围,可选值为单个字符,字符范围,加可选的映射 地址,首先你得必须保证你所需要的字符范围在--font 指定的字体文件中能找得到,-r 命令行 参数可以在一条命令中多次出现,如下面例子所示:

```c++
-r 0xF450 单个字符,十六进制和十进制都行
-r 0xF450-0xF470 字符范围
-r '0xF450=>0x81' 单个字符加映射地址
-r '0xF450-0xF470=>0x81' 字符范围加映射地址
-r 0xF450 -r 0xF451-0xF470 一下使用 2 次-r 命令行参数
-r 0xF450,0xF451-0xF470 用单个-r 表示多种可选值

--symbols: 和-r 的作用差不多,都是用来指示所要用到的字符,不过他们的表达形式不一样, 对--symbols 而言,它是接受字符的字面量形式,而-r 是接受字符的编码形式, --symbols 和-r 可以同时使用,也可以只使用它们其中的一个,请看如下例子:

```c++
--symbols 0123456789 中 ABCD 国 EFG


**--no-compress:** 禁止进行 RLE 压缩,我们在生成字体时,请禁止进行压缩

#### 2.3.4 字体下载

这里我们要下载一下Open Harmony的字体,附件已给出

下载链接:https://developer.harmonyos.com/cn/docs/design/des-resources/general-0000001157315901

![字体.png](https://dl-harmonyos.51cto.com/images/202206/26387c918b50feb56004123e5b6182a1509bee.png?x-oss-process=image/resize,w_820,h_768)

下载后挑选自己喜欢的安装即可

![安装字体.png](https://dl-harmonyos.51cto.com/images/202206/3788de6531c48380d4a8380d1a1689b597ec6d.png?x-oss-process=image/resize,w_820,h_736)

#### 2.3.5 字体创建

下面给出一条完整的创建命令示例(复制到 cmd 命令窗口运行的):

lv_font_conv --no-compress --format lvgl --font C:\Users\han\Desktop\HarmonyOS_Sans_SC_Thin.ttf -o C:\Users\han\Desktop\my_font.c --bpp 4 --size 25 --symbols 我爱OpenHarmonyar -r 0x30-0x39 -r 0x41-0x5A -r 0x61-0x7A -r 0x95F4


![命令.png](https://dl-harmonyos.51cto.com/images/202206/9728ce15684aaf03d1a562ca1fd2eb16eec7c3.png?x-oss-process=image/resize,w_820,h_146)

##### 注意:

1.上面的文件路径要改成自己的

2.上面给出的代码可能会出现换行,请自行调整
生成的代码如下
![软件包.png](https://dl-harmonyos.51cto.com/images/202206/6223f3b4634329cbf63308a008ffecba0febf9.png?x-oss-process=image/resize,w_288,h_243)
将代码拉取到GUI文件目录下
![image.png](https://dl-harmonyos.51cto.com/images/202206/168b87513a4be7af8d9613e3e72df928938de1.png?x-oss-process=image/resize,w_363,h_304)

#### 2.4 测试代码

##### 2.4.1 声明字体

```c++
LV_FONT_DECLARE(my_font);//申明字体
2.4.2 入口函数

```c++
void lv_font_test_start()
{
lv_obj_t scr = lv_scr_act();
lv_obj_t
label1 = lv_label_create(scr,NULL);
static lv_style_t style1;
lv_style_copy(&style1,&lv_style_plain_color);
style1.text.font = &my_font;//在样式中使用这个字体
lv_label_set_style(label1,LV_LABEL_STYLE_MAIN,&style1);
lv_label_set_text(label1,"我爱OpenHarmony");//设置文本
lv_label_set_body_draw(label1,true);
lv_obj_align(label1,NULL,LV_ALIGN_CENTER,0,0);
}



#### 2.5 测试效果
![ll.jpg](https://dl-harmonyos.51cto.com/images/202206/126795d4293ff8fe7558982786241021cf0a14.jpg?x-oss-process=image/resize,w_820,h_728)

附件链接:
lvgl-master.zip(https://ost.51cto.com/resource/2087)
lv_pc_simulator.zip(https://ost.51cto.com/resource/2086)
HarmonyOS Sans.zip(https://ost.51cto.com/resource/2090)

[想了解更多关于开源的内容,请访问:](https://ost.51cto.com/#bkwz)

[51CTO 开源基础软件社区](https://ost.51cto.com#bkwz)

https://ost.51cto.com/#bkwz
举报

相关推荐

0 条评论