feat(ime_pinyin): add API to use Pinyin IME(Chinese input) (#3408)

* feat(pinyin_ime): add API to use Pinyin IME(Chinese input)

1.Low resource usage
2.Support custom thesaurus
3.Support custom styles (Candidate panel, keyboard)
4.Support simple spelling

* fix(ime_pinyin): fix several problems of ime_pinyin

1. Change lv_pinyin_ime to lv_ime_pinyin
2. Add lv_pinyin_ime_set_keyboard interface
3. Add lv_ime_pinyin configuration in Kconfig, src/lv_conf_internal.h

* refactor(ime_pinyin): improve coding specification

* feat(ime_pinyin): add simple Pinyin IME example

* docs(ime_pinyin): Add ime_pinyin documentation

* Delete settings.json

* Update dictionary based on simsun

* Delete lv_font_source_han_sans_normal_16.c

* Update lv_example_ime_pinyin_1.c

* Update ime_pinyin.md

add Chinese translation document

* Update lv_ime_pinyin.c

* Update lv_ime_pinyin.c

* Update lv_ime_pinyin.h

* Update lv_ime_pinyin.c

* Update lv_example_ime_pinyin_1.c

* Update lv_conf_internal.h

* Update lv_ime_pinyin.c

* Update lv_ime_pinyin.c

Co-authored-by: 100askTeam <team100ask@outlook.com>
This commit is contained in:
Yobe Zhou
2022-06-24 20:38:24 +08:00
committed by GitHub
parent 4056a15ecc
commit 92f1f9c0cc
13 changed files with 1241 additions and 0 deletions
+3
View File
@@ -22,3 +22,6 @@ test_screenshot_error.h
build/
tests/build_*/
tests/report/
.DS_Store
.vscode
*.bak
+21
View File
@@ -1018,6 +1018,27 @@ menu "LVGL configuration"
config LV_USE_IMGFONT
bool "draw img in label or span obj"
default n
config LV_USE_MSG
bool "Enable a published subscriber based messaging system"
default n
config LV_USE_IME_PINYIN
bool "Enable Pinyin input method"
default n
config LV_IME_PINYIN_USE_DEFAULT_DICT
bool "Use built-in Thesaurus"
depends on LV_USE_IME_PINYIN
default y
help
If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss
config LV_IME_PINYIN_CAND_TEXT_NUM
int "maximum number of candidate panels"
depends on LV_USE_IME_PINYIN
default 6
help
Set the maximum number of candidate panels that can be displayed.
This needs to be adjusted according to the size of the screen.
endmenu
menu "Examples"
+136
View File
@@ -0,0 +1,136 @@
# Pinyin IME
Pinyin IME provides API to provide Chinese Pinyin input method (Chinese input) for keyboard object. You can think of `lv_ime_pinyin` as a Pinyin input method plug-in for keyboard objects.
Normally, an environment where [lv_keyboard](/widgets/extra/keyboard) can run can also run `lv_ime_pinyin`. There are two main influencing factors: the size of the font file and the size of the dictionary.
<details>
<summary>中文</summary>
<p>
`lv_ime_pinyin`为[键盘](/widgets/extra/keyboard)组件提供汉语拼音输入法(中文输入)的功能(后文简称为拼音输入法)。您可以将 `lv_ime_pinyin` 看成是键盘组件的汉语拼音输入法插件。
一般情况下,只要是[键盘](/widgets/extra/keyboard)组件能运行的环境 `lv_ime_pinyin` 也能运行。有两个影响因素:字库的大小和词库的大小。
</p>
</details>
## Usage
Enable `LV_USE_IME_PINYIN` in `lv_conf.h`.
First use `lv_ime_pinyin_create(lv_scr_act())` to create a Pinyin input method plug-in, then use `lv_ime_pinyin_set_keyboard(pinyin_ime, kb)` to add the `keyboard` you created to the Pinyin input method plug-in.
You can use `lv_ime_pinyin_set_dict(pinyin_ime, your_dict)` to use a custom dictionary (if you don't want to use the built-in dictionary at first, you can disable `LV_IME_PINYIN_USE_DEFAULT_DICT` in `lv_conf.h`, which can save a lot of memory space).
The built-in thesaurus is customized based on the **LV_FONT_SIMSUN_16_CJK** font library, which currently only has more than `1,000` most common CJK radicals, so it is recommended to use custom fonts and thesaurus.
In the process of using the Pinyin input method plug-in, you can change the keyboard and dictionary at any time.
<details>
<summary>中文</summary>
<p>
`lv_conf.h` 中打开 `LV_USE_IME_PINYIN`
首先,使用 `lv_ime_pinyin_create(lv_scr_act())` 函数创建一个拼音输入法插件,
然后使用 `lv_ime_pinyin_set_keyboard(pinyin_ime, kb)` 函数将您创建的键盘组件添加到插件中。
内置的词库是基于 LVGL 的 **LV_FONT_SIMSUN_16_CJK** 字库定制,这个字库目前只有 `1000` 多个最常见的 CJK 部首,所以建议使用自定义字库和词库。
您可以使用 `lv_ime_pinyin_set_dict(pinyin_ime, your_dict)` 函数来设置使用自定义的词库,如果您一开始就不打算使用内置的词库,建议您在 `lv_conf.h` 中将 `LV_IME_PINYIN_USE_DEFAULT_DICT` 关闭,这可以节省一些内存空间。
</p>
</details>
## Custom dictionary
If you don't want to use the built-in Pinyin dictionary, you can use the custom dictionary.
Or if you think that the built-in phonetic dictionary consumes a lot of memory, you can also use a custom dictionary.
Customizing the dictionary is very simple.
First, set `LV_IME_PINYIN_USE_DEFAULT_DICT` to `0` in `lv_conf.h`
Then, write a dictionary in the following format.
<details>
<summary>中文</summary>
<p>
如果您不想使用内置的词库,可以通过下面的方法自定义词库。
自定义词典非常简单。
首先,在 `lv_conf.h``LV_IME_PINYIN_USE_DEFAULT_DICT` 设置为 0。
然后按照下面的格式编写词库。
</p>
</details>
### Dictionary format
The arrangement order of each pinyin syllable is very important. You need to customize your own thesaurus according to the Hanyu Pinyin syllable table. You can read [here](https://baike.baidu.com/item/%E6%B1%89%E8%AF%AD%E6%8B%BC%E9%9F%B3%E9%9F%B3%E8%8A%82/9167981) to learn about the Hanyu Pinyin syllables and the syllable table.
Then, write your own dictionary according to the following format:
<details>
<summary>中文</summary>
<p>
**注意**,各个拼音音节的排列顺序非常重要,您需要按照汉语拼音音节表定制自己的词库,可以阅读[这里](https://baike.baidu.com/item/%E6%B1%89%E8%AF%AD%E6%8B%BC%E9%9F%B3%E9%9F%B3%E8%8A%82/9167981)了解[汉语拼音音节](https://baike.baidu.com/item/%E6%B1%89%E8%AF%AD%E6%8B%BC%E9%9F%B3%E9%9F%B3%E8%8A%82/9167981)以及[音节表](https://baike.baidu.com/item/%E6%B1%89%E8%AF%AD%E6%8B%BC%E9%9F%B3%E9%9F%B3%E8%8A%82/9167981#1)。
然后,根据下面的格式编写自己的词库:
</p>
</details>
```c
lv_100ask_pinyin_dict_t your_pinyin_dict[] = {
{ "a", "啊阿呵吖" },
{ "ai", "埃挨哎唉哀皑蔼矮碍爱隘癌艾" },
{ "an", "按安暗岸俺案鞍氨胺厂广庵揞犴铵桉谙鹌埯黯" },
{ "ang", "昂肮盎仰" },
{ "ao", "凹敖熬翱袄傲奥懊澳" },
{ "ba", "芭捌叭吧笆八疤巴拔跋靶把坝霸罢爸扒耙" },
{ "bai", "白摆佰败拜柏百稗伯" },
/* ...... */
{ "zuo", "昨左佐做作坐座撮琢柞"},
{NULL, NULL}
```
**The last item** must end with `{null, null}` , or it will not work properly.
### Apply new dictionary
After writing a dictionary according to the above dictionary format, you only need to call this function to set up and use your dictionary:
<details>
<summary>中文</summary>
<p>
按照上面的词库格式编写好自己的词库之后,参考下面的用法,调用 `lv_100ask_pinyin_ime_set_dict(pinyin_ime, your_pinyin_dict)` 函数即可设置和使用新词库:
</p>
</details>
```c
lv_obj_t * pinyin_ime = lv_100ask_pinyin_ime_create(lv_scr_act());
lv_100ask_pinyin_ime_set_dict(pinyin_ime, your_pinyin_dict);
```
## Example
```eval_rst
.. include:: ../../examples/others/ime/index.rst
```
## API
```eval_rst
.. doxygenfile:: lv_ime_pinyin.h
:project: lvgl
```
+1
View File
@@ -12,5 +12,6 @@
fragment
msg
imgfont
ime_pinyin
```
+8
View File
@@ -0,0 +1,8 @@
Simple Pinyin IME example
"""""""""""""""""""
.. lv_example:: others/ime/lv_example_ime_pinyin_1
:language: c
@@ -0,0 +1,38 @@
/**
* @file lv_example_ime_pinyin.h
*
*/
#ifndef LV_EX_IME_PINYIN_H
#define LV_EX_IME_PINYIN_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_example_ime_pinyin_1(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_EX_IME_PINYIN_H*/
@@ -0,0 +1,56 @@
#include "../../lv_examples.h"
#if LV_USE_LABEL && LV_USE_TEXTAREA && LV_FONT_SIMSUN_16_CJK && LV_USE_IME_PINYIN && LV_BUILD_EXAMPLES
static void ta_event_cb(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * ta = lv_event_get_target(e);
lv_obj_t * kb = lv_event_get_user_data(e);
if(code == LV_EVENT_FOCUSED) {
if(lv_indev_get_type(lv_indev_get_act()) != LV_INDEV_TYPE_KEYPAD) {
lv_keyboard_set_textarea(kb, ta);
lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN);
}
}
else if(code == LV_EVENT_READY || code == LV_EVENT_CANCEL) {
lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_state(ta, LV_STATE_FOCUSED);
lv_indev_reset(NULL, ta); /*To forget the last clicked object to make it focusable again*/
}
}
void lv_example_ime_pinyin_1(void)
{
lv_obj_t * pinyin_ime = lv_ime_pinyin_create(lv_scr_act());
lv_obj_set_style_text_font(pinyin_ime, &lv_font_simsun_16_cjk, 0);
//lv_ime_pinyin_set_dict(pinyin_ime, your_dict); // Use a custom dictionary. If it is not set, the built-in thesaurus will be used.
lv_obj_t * kb = lv_keyboard_create(lv_scr_act());
lv_ime_pinyin_set_keyboard(pinyin_ime, kb);
/* ta1 */
lv_obj_t * ta1 = lv_textarea_create(lv_scr_act());
lv_obj_set_style_text_font(ta1, &lv_font_simsun_16_cjk, 0);
lv_obj_align(ta1, LV_ALIGN_TOP_LEFT, 10, 10);
lv_keyboard_set_textarea(kb, ta1);
lv_obj_add_event_cb(ta1, ta_event_cb, LV_EVENT_ALL, kb);
/* ta2 */
lv_obj_t * ta2 = lv_textarea_create(lv_scr_act());
lv_obj_set_style_text_font(ta2, &lv_font_simsun_16_cjk, 0);
lv_obj_align_to(ta2, ta1, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
lv_obj_add_event_cb(ta2, ta_event_cb, LV_EVENT_ALL, kb);
lv_obj_t * cz_label = lv_label_create(lv_scr_act());
lv_label_set_text(cz_label,
"嵌入式系统(Embedded System),\n是一种嵌入机械或电气系统内部、具有专一功能和实时计算性能的计算机系统。");
lv_obj_set_style_text_font(cz_label, &lv_font_simsun_16_cjk, 0);
lv_obj_set_width(cz_label, 310);
lv_obj_align_to(cz_label, ta1, LV_ALIGN_OUT_BOTTOM_LEFT, 5, 5);
}
#endif
+1
View File
@@ -19,6 +19,7 @@ extern "C" {
#include "fragment/lv_example_fragment.h"
#include "imgfont/lv_example_imgfont.h"
#include "msg/lv_example_msg.h"
#include "ime/lv_example_ime_pinyin.h"
/*********************
* DEFINES
+12
View File
@@ -691,6 +691,18 @@
/*1: Enable a published subscriber based messaging system */
#define LV_USE_MSG 0
/*1: Enable Pinyin input method*/
/*Requires: lv_keyboard*/
#define LV_USE_IME_PINYIN 0
#if LV_USE_IME_PINYIN
/*1: Use default thesaurus*/
/*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/
#define LV_IME_PINYIN_USE_DEFAULT_DICT 1
/*Set the maximum number of candidate panels that can be displayed*/
/*This needs to be adjusted according to the size of the screen*/
#define LV_IME_PINYIN_CAND_TEXT_NUM 6
#endif
/*==================
* EXAMPLES
*==================*/
File diff suppressed because it is too large Load Diff
+117
View File
@@ -0,0 +1,117 @@
/**
* @file lv_ime_pinyin.h
*
*/
#ifndef LV_IME_PINYIN_H
#define LV_IME_PINYIN_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_IME_PINYIN != 0
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
const char * const py;
const char * const py_mb;
} lv_pinyin_dict_t;
/*Data of lv_ime_pinyin*/
typedef struct {
lv_obj_t obj;
lv_obj_t * kb;
lv_obj_t * cand_panel;
lv_pinyin_dict_t * dict;
char * cand_str; /* Candidate string */
char * btnm_pinyin_sel[LV_IME_PINYIN_CAND_TEXT_NUM + 3];
char input_char[16]; /* Input box character */
uint16_t ta_count; /* The number of characters entered in the text box this time */
uint16_t cand_num; /* Number of candidates */
uint16_t py_page; /* Current pinyin map pages */
uint16_t py_num[26]; /* Number and length of Pinyin */
uint16_t py_pos[26]; /* Pinyin position */
} lv_ime_pinyin_t;
/***********************
* GLOBAL VARIABLES
***********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_obj_t * lv_ime_pinyin_create(lv_obj_t * parent);
/*=====================
* Setter functions
*====================*/
/**
* Set the keyboard of Pinyin input method.
* @param obj pointer to a Pinyin input method object
* @param dict pointer to a Pinyin input method keyboard
*/
void lv_ime_pinyin_set_keyboard(lv_obj_t * obj, lv_obj_t * kb);
/**
* Set the dictionary of Pinyin input method.
* @param obj pointer to a Pinyin input method object
* @param dict pointer to a Pinyin input method dictionary
*/
void lv_ime_pinyin_set_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict);
/*=====================
* Getter functions
*====================*/
/**
* Set the dictionary of Pinyin input method.
* @param obj pointer to a Pinyin IME object
* @return pointer to the Pinyin IME keyboard
*/
lv_obj_t * lv_ime_pinyin_get_kb(lv_obj_t * obj);
/**
* Set the dictionary of Pinyin input method.
* @param obj pointer to a Pinyin input method object
* @return pointer to the Pinyin input method candidate panel
*/
lv_obj_t * lv_ime_pinyin_get_cand_panel(lv_obj_t * obj);
/**
* Set the dictionary of Pinyin input method.
* @param obj pointer to a Pinyin input method object
* @return pointer to the Pinyin input method dictionary
*/
lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj);
/*=====================
* Other functions
*====================*/
/**********************
* MACROS
**********************/
#endif /*LV_IME_PINYIN*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_USE_IME_PINYIN*/
+1
View File
@@ -19,6 +19,7 @@ extern "C" {
#include "fragment/lv_fragment.h"
#include "imgfont/lv_imgfont.h"
#include "msg/lv_msg.h"
#include "ime/lv_ime_pinyin.h"
/*********************
* DEFINES
+34
View File
@@ -2243,6 +2243,40 @@
#endif
#endif
/*1: Enable Pinyin input method*/
/*Requires: lv_keyboard*/
#ifndef LV_USE_IME_PINYIN
#ifdef CONFIG_LV_USE_IME_PINYIN
#define LV_USE_IME_PINYIN CONFIG_LV_USE_IME_PINYIN
#else
#define LV_USE_IME_PINYIN 0
#endif
#endif
#if LV_USE_IME_PINYIN
/*1: Use default thesaurus*/
/*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/
#ifndef LV_IME_PINYIN_USE_DEFAULT_DICT
#ifdef _LV_KCONFIG_PRESENT
#ifdef CONFIG_LV_IME_PINYIN_USE_DEFAULT_DICT
#define LV_IME_PINYIN_USE_DEFAULT_DICT CONFIG_LV_IME_PINYIN_USE_DEFAULT_DICT
#else
#define LV_IME_PINYIN_USE_DEFAULT_DICT 0
#endif
#else
#define LV_IME_PINYIN_USE_DEFAULT_DICT 1
#endif
#endif
/*Set the maximum number of candidate panels that can be displayed*/
/*This needs to be adjusted according to the size of the screen*/
#ifndef LV_IME_PINYIN_CAND_TEXT_NUM
#ifdef CONFIG_LV_IME_PINYIN_CAND_TEXT_NUM
#define LV_IME_PINYIN_CAND_TEXT_NUM CONFIG_LV_IME_PINYIN_CAND_TEXT_NUM
#else
#define LV_IME_PINYIN_CAND_TEXT_NUM 6
#endif
#endif
#endif
/*==================
* EXAMPLES
*==================*/