1.将A27新UI文件夹重命名为CANUI 2.A272O新版本发布

This commit is contained in:
2025-03-26 18:43:18 +08:00
parent 497f8eb1e1
commit 5bc7ee438c
13399 changed files with 58500 additions and 59183 deletions

View File

@ -0,0 +1,39 @@
## 目录介绍
* **tkc** toolkit c library。
* **base** GUI 基本库。
* **widgets** 基本控件。
* **blend** 图片渲染函数。
* **lcd** LCD的各种实现。
* **font** 字体的各种实现。
* **misc** C++支持等。
* **xml** XML解析器。
* **widget\_animators** 控件动画实现。
* **ext\_widgets** 扩展控件。
* **main\_loop** 主循环的各种实现。
* **window\_animators** 窗口动画的实现。
* **image\_loader** 加载的各种实现。
* **platforms** 平台相关的函数。
* **input\_engines** 输入法引擎的各种实现。
* **ui\_loader** 从界面描述数据创建窗口。
* **vgcanvas** 矢量图画布。
* **svg** 矢量图画SVG。
* **clip\_board** 剪切板的实现。
* **ubjson** Universal Binary JSON实现。
* **window\_manager** 窗口管理器的实现。
* **native_window** 原生窗口的实现。
* **graphic_buffer** 图像数据缓冲区。
* **streams** 各种流的实现(如果不用可以不移植)。
* **compressors** 压缩算法的实现(如果不用可以不移植)。
* **conf_io** json/jni/ubjson 等配置文件读写。
* **csv** csv 文件读写。
## 使用方法
应用程序只需包含awtk.h即可。
```
#include "awtk.h"
```

View File

@ -0,0 +1,144 @@
import os
import copy
import platform
BIN_DIR=os.environ['BIN_DIR'];
LIB_DIR=os.environ['LIB_DIR'];
NANOVG_BACKEND=os.environ['NANOVG_BACKEND'];
VGCANVAS=os.environ['VGCANVAS'];
NATIVE_WINDOW = os.environ['NATIVE_WINDOW'];
GRAPHIC_BUFFER = os.environ['GRAPHIC_BUFFER'];
TOOLS_NAME = os.environ['TOOLS_NAME']
BASE_SOURCES=Glob('layouters/*.c') + \
Glob('base/*.c') + \
Glob('ui_loader/*.c') + \
Glob('fscript_ext/*.c') + \
Glob('xml/*.c') + \
Glob('svg/*.c') + \
Glob('charset/*.c') + \
Glob('clip_board/*.c') + \
Glob('font_loader/*.c') + \
Glob('blend/*.c') + \
Glob('image_loader/*.c') + \
Glob('designer_support/*.c') + \
Glob('widget_animators/*.c') + \
Glob('misc/*.cpp') + \
Glob('window_animators/*.c') + \
Glob('dialog_highlighters/*.c') + \
Glob('window_manager/window_manager_default.c')
BASE_SOURCES += Glob('graphic_buffer/graphic_buffer_default.c')
if NATIVE_WINDOW == 'sdl':
BASE_SOURCES += Glob('native_window/native_window_sdl.c')
elif NATIVE_WINDOW == 'fb_gl':
BASE_SOURCES += Glob('native_window/native_window_fb_gl.c')
else:
BASE_SOURCES += Glob('native_window/native_window_raw.c')
BASE_SOURCES += ['lcd/lcd_mono.c'];
BASE_SOURCES += ['main_loop/main_loop_simple.c'];
if os.environ['LCD'] == 'SDL_GPU':
BASE_SOURCES += ['lcd/lcd_nanovg.c', 'main_loop/main_loop_sdl.c'];
elif os.environ['LCD'] == 'SDL_FB':
BASE_SOURCES += ['lcd/lcd_sdl2.c', 'main_loop/main_loop_sdl.c']
elif os.environ['LCD'] == 'SDL_FB_MONO':
BASE_SOURCES += ['lcd/lcd_sdl2_mono.c', 'main_loop/main_loop_sdl.c']
elif os.environ['LCD'] == 'FB_GL':
BASE_SOURCES += ['lcd/lcd_nanovg.c']
BASE_SOURCES += [
'input_methods/input_method_creator.c'
] + Glob('lcd/lcd_mem_*.c') ;
if VGCANVAS == 'CAIRO':
BASE_SOURCES +=['vgcanvas/vgcanvas_cairo.c'];
elif VGCANVAS == 'NANOVG_PLUS':
BASE_SOURCES +=['vgcanvas/vgcanvas_nanovg_plus.c'];
else:
if NANOVG_BACKEND == 'BGFX':
BASE_SOURCES +=['vgcanvas/vgcanvas_nanovg_bgfx.c'];
elif NANOVG_BACKEND == 'AGG':
BASE_SOURCES +=['vgcanvas/vgcanvas_nanovg_soft.c'];
elif NANOVG_BACKEND == 'AGGE':
BASE_SOURCES +=['vgcanvas/vgcanvas_nanovg_soft.c'];
else:
BASE_SOURCES +=['vgcanvas/vgcanvas_nanovg_gl.c'];
if os.environ['INPUT_ENGINE'] == 'null':
BASE_SOURCES += Glob('input_engines/input_engine_null.c')
elif os.environ['INPUT_ENGINE'] == 't9ext':
BASE_SOURCES += Glob('input_engines/ime_utils.c')
BASE_SOURCES += Glob('input_engines/input_engine_t9ext.c')
elif os.environ['INPUT_ENGINE'] == 't9':
BASE_SOURCES += Glob('input_engines/ime_utils.c')
BASE_SOURCES += Glob('input_engines/input_engine_t9.c')
elif os.environ['INPUT_ENGINE'] == 'spinyin':
BASE_SOURCES += Glob('input_engines/ime_utils.c')
BASE_SOURCES += Glob('input_engines/input_engine_spinyin.c')
else:
BASE_SOURCES += Glob('input_engines/input_engine_pinyin.cpp')
env=DefaultEnvironment().Clone()
if env['PLATFORM'] == 'win32' and os.environ['TOOLS_NAME'] != '':
import subprocess
class ourSpawn:
def ourspawn(self, sh, escape, cmd, args, env):
newargs = ' '.join(args[1:])
cmdline = cmd + " " + newargs
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False, env = env)
data, err = proc.communicate()
rv = proc.wait()
if rv:
print("=====")
print(err)
print("=====")
return rv
buf = ourSpawn()
buf.ourenv = env
env['SPAWN'] = buf.ourspawn
TK_SOURCES=Glob('tkc/*.c') + Glob('platforms/pc/*.c')
env.Library(os.path.join(LIB_DIR, 'tkc_static'), TK_SOURCES, LIBS=[])
TKC_DEPS_LIBS=[]
OS_NAME = platform.system()
TKC_LINKFLAGS = env['LINKFLAGS'];
TKC_STATIC_LIBS = ['conf_io', 'hal', 'csv', 'ubjson', 'streams', 'tkc_static', 'compressors', 'mbedtls', 'miniz']
TKC_LINK_ALL=' -Wl,--whole-archive -lstreams -lconf_io -lhal -lcsv -lubjson -ltkc_static -lcompressors -lmbedtls -lminiz -Wl,--no-whole-archive'
if OS_NAME == 'Windows':
if TOOLS_NAME == '' :
TKC_DEPS_LIBS= TKC_STATIC_LIBS + ['SDL2', 'user32','winmm.lib','advapi32.lib','shell32.lib', 'ole32.lib']
TKC_LINKFLAGS += ' /DEF:"dllexports/tkc.def" '
elif TOOLS_NAME == 'mingw':
TKC_DEPS_LIBS= TKC_STATIC_LIBS + ['SDL2', 'user32','winmm','advapi32','shell32', 'ole32', 'ws2_32','Gdi32','Imm32', 'Version', 'OleAut32', 'UUID']
TKC_LINKFLAGS += TKC_LINK_ALL
elif OS_NAME == 'Darwin':
TKC_DEPS_LIBS= TKC_STATIC_LIBS
TKC_LINKFLAGS +=' -all_load '
elif OS_NAME == 'Linux':
TKC_LINKFLAGS += TKC_LINK_ALL
env.SharedLibrary(os.path.join(BIN_DIR, 'tkc'), [], LIBS=TKC_DEPS_LIBS, LINKFLAGS=TKC_LINKFLAGS);
env.Library(os.path.join(LIB_DIR, 'base'), BASE_SOURCES, LIBS=[])
WIDGETS_SOURCES=Glob('widgets/*.c')
env.Library(os.path.join(LIB_DIR, 'widgets'), WIDGETS_SOURCES, LIBS=[])
EXT_WIDGETS_SOURCES=Glob('ext_widgets/*.c') + Glob('ext_widgets/*/*.c') + Glob('custom_widgets/*.c') + Glob('custom_widgets/*/*.c')
env.Library(os.path.join(LIB_DIR, 'extwidgets'), EXT_WIDGETS_SOURCES, LIBS=[])
env.Library(os.path.join(LIB_DIR, 'awtk_global'), ['awtk_global.c'], LIBS=[])
if 'WITH_AWTK_SO' in os.environ:
print("with awtk so");
LIBS=os.environ['AWTK_DLL_DEPS_LIBS'].split(';')
LINKFLAGS=env['LINKFLAGS'] + os.environ['OS_WHOLE_ARCHIVE']
env.SharedLibrary(os.path.join(BIN_DIR, 'awtk'), [], LIBS=LIBS, LINKFLAGS=LINKFLAGS);

View File

@ -0,0 +1,36 @@
/**
* File: awtk.h
* Author: AWTK Develop Team
* Brief: awtk entry.
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-03-03 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_AWTK_H
#define TK_AWTK_H
#include "awtk_version.h"
#include "awtk_tkc.h"
#include "awtk_base.h"
#include "awtk_global.h"
#include "awtk_widgets.h"
#ifndef WITHOUT_EXT_WIDGETS
#include "awtk_ext_widgets.h"
#endif /*WITHOUT_EXT_WIDGETS*/
#endif /*TK_AWTK_H*/

View File

@ -0,0 +1,88 @@
/**
* File: awtk_tkc.h
* Author: AWTK Develop Team
* Brief: awtk toolkit c libs
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-12-15 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_BASE_H
#define TK_BASE_H
#include "base/bidi.h"
#include "base/ui_feedback.h"
#include "base/assets_manager.h"
#include "base/awtk_config_sample.h"
#include "base/bitmap.h"
#include "base/canvas.h"
#include "base/canvas_offline.h"
#include "base/children_layouter.h"
#include "base/children_layouter_factory.h"
#include "base/clip_board.h"
#include "base/dialog_highlighter.h"
#include "base/dialog_highlighter_factory.h"
#include "base/enums.h"
#include "base/event_queue.h"
#include "base/events.h"
#include "base/font.h"
#include "base/font_loader.h"
#include "base/font_manager.h"
#include "base/g2d.h"
#include "base/glyph_cache.h"
#include "base/idle.h"
#include "base/image_base.h"
#include "base/image_loader.h"
#include "base/image_manager.h"
#include "base/input_device_status.h"
#include "base/input_engine.h"
#include "base/input_method.h"
#include "base/keys.h"
#include "base/layout.h"
#include "base/layout_def.h"
#include "base/lcd.h"
#include "base/lcd_profile.h"
#include "base/line_break.h"
#include "base/locale_info.h"
#include "base/main_loop.h"
#include "base/pixel.h"
#include "base/pixel_pack_unpack.h"
#include "base/self_layouter.h"
#include "base/self_layouter_factory.h"
#include "base/shortcut.h"
#include "base/style.h"
#include "base/style_const.h"
#include "base/style_factory.h"
#include "base/suggest_words.h"
#include "base/system_info.h"
#include "base/theme.h"
#include "base/timer.h"
#include "base/types_def.h"
#include "base/ui_builder.h"
#include "base/ui_loader.h"
#include "base/velocity.h"
#include "base/vgcanvas.h"
#include "base/widget.h"
#include "base/widget_animator.h"
#include "base/widget_animator_factory.h"
#include "base/widget_animator_manager.h"
#include "base/widget_consts.h"
#include "base/widget_factory.h"
#include "base/widget_vtable.h"
#include "base/window_animator.h"
#include "base/window_animator_factory.h"
#include "base/window_base.h"
#include "base/window_manager.h"
#include "base/style_mutable.h"
#endif /*TK_BASE_H*/

View File

@ -0,0 +1,234 @@
/**
* 嵌入式系统有自己的 main 函数时,请定义本宏。
*
* #define USE_GUI_MAIN 1
*/
/**
* 如果需要支持预先解码的位图字体,请定义本宏。一般只在 RAM 极小时,才启用本宏。
* #define WITH_BITMAP_FONT 1
*/
/**
* 如果支持 png/jpeg 图片,请定义本宏
*
* #define WITH_STB_IMAGE 1
*/
/**
* 如果用 stb 支持 Truetype 字体,请定义本宏
*
* #define WITH_STB_FONT 1
*/
/**
* 如果用 freetype 支持 Truetype 字体,请定义本宏。
*
* #define WITH_FT_FONT 1
*/
/**
* 如果支持从文件系统加载资源,请定义本宏
*
* #define WITH_FS_RES 1
*/
/**
* 如果代码在 flash 中,而资源在文件系统,请定义本宏指明资源所在的路径。
*
* #define APP_RES_ROOT "0://awtk/"
*
*/
/**
* 如果定义本宏,使用标准的 UNICODE 换行算法,除非资源极为有限,请定义本宏。
*
* #define WITH_UNICODE_BREAK 1
*/
/**
* 如果定义本宏,将图片解码成 BGRA8888 格式,否则解码成 RGBA8888 的格式。
* 当硬件的 2D 加速需要 BGRA 格式时,请启用本宏。
*
* #define WITH_BITMAP_BGRA 1
*/
/**
* 如果定义本宏,将不透明的 PNG 图片解码成 BGR565 格式,建议定义。
* 另外和 LCD 的格式保存一致,可以大幅度提高性能。
* 如果没有定义 WITH_BITMAP_BGR565 和 WITH_BITMAP_RGB565 宏,默认解析为 32 位色
*
* #define WITH_BITMAP_BGR565 1
*/
/**
* 如果定义本宏,将不透明的 PNG 图片解码成 RGB565 格式,建议定义。
* 另外和 LCD 的格式保存一致,可以大幅度提高性能。
* 如果没有定义 WITH_BITMAP_BGR565 和 WITH_BITMAP_RGB565 宏,默认解析为 32 位色
*
* #define WITH_BITMAP_RGB565 1
*/
/**
* 如果不需输入法,请定义本宏
*
* #define WITH_NULL_IM 1
*/
/**
* 如果有标准的 malloc/free/calloc 等函数,请定义本宏
*
* #define HAS_STD_MALLOC 1
*/
/**
* 如果有标准的 fopen/fclose 等函数,请定义本宏
*
* #define HAS_STDIO 1
*/
/**
* 如果有标准的 pthread 等函数,请定义本宏
*
* #define HAS_PTHREAD 1
*/
/**
* 如果有优化版本的 memcpy 函数,请定义本宏
*
* #define HAS_FAST_MEMCPY 1
*/
/**
* 如果出现 wcsxxx 之类的函数没有定义时,请定义该宏
*
* #define WITH_WCSXXX 1
*/
/**
* 如果启用 STM32 G2D 硬件加速,请定义本宏
*
* #define WITH_STM32_G2D 1
*/
/**
* 如果启用 NXP PXP 硬件加速,请定义本宏
*
* #define WITH_PXP_G2D 1
*/
/**
* 在没有 GPU 时,如果启用 agge 作为 nanovg 的后端(较 agg 作为后端:小,快,图形质量稍差),请定义本宏。
*
* #define WITH_NANOVG_AGGE 1
*/
/**
* 在没有 GPU 时,如果启用 agg 作为 nanovg 的后端(较 agge 作为后端:大,慢,图形质量好),请定义本宏。
* 注意agg 是以 GPL 协议开源。
*
* #define WITH_NANOVG_AGG 1
*/
/**
* 如果启用鼠标指针,请定义本宏
*
* #define ENABLE_CURSOR 1
*/
/**
* 对于低端平台,如果不使用控件动画,请定义本宏。
*
* #define WITHOUT_WIDGET_ANIMATORS 1
*/
//#define WITHOUT_WIDGET_ANIMATORS 1
/**
* 对于低端平台,如果不使用窗口动画,请定义本宏。
*
* #define WITHOUT_WINDOW_ANIMATORS 1
*/
//#define WITHOUT_WINDOW_ANIMATORS 1
/**
* 对于低端平台,如果不使用对话框高亮策略,请定义本宏。
*
* #define WITHOUT_DIALOG_HIGHLIGHTER 1
*/
/**
* 对于低端平台,如果不使用扩展控件,请定义本宏。
*
* #define WITHOUT_EXT_WIDGETS 1
*/
/**
* 对于低端平台,如果内存不足以提供完整的 FrameBuffer请定义本宏启用局部 FrameBuffer可大幅度提高渲染性能。单位是像素个数
*
* #define FRAGMENT_FRAME_BUFFER_SIZE 32 * 1024
*/
/**
* 启用 widget 类型检查,请定义本宏(除非编译器不支持,否则请定义它)。
*
* #define WITH_WIDGET_TYPE_CHECK 1
*/
/**
* 启用输入法,但不想启用联想功能,请定义本宏。
*
* #define WITHOUT_SUGGEST_WORDS 1
*/
/**
* 如果需要从 zip 文件中加载资源,请定义本宏。
*
* #define WITH_ASSET_LOADER_ZIP 1
*/
/**
* 对于只有 512K flash 的平台,而且 LCD 格式是 BGR565。如果希望进一步优化空间去掉多余的 bitmap 格式支持代码。请定义本宏。
* 其它 LCD 格式可以自行修改src/blend/soft_g2d.c 保留需要的格式即可。
*
* #define LCD_BGR565_LITE 1
*/
/**
* 如果希望支持文字双向排版算法(如阿拉伯语言),请定义本宏。
*
* #define WITH_TEXT_BIDI 1
*
*/
/**
* 开启自定义的离线 canvas如果板子使用特殊的画布的话需要定义该宏来定义特殊离线 canvas 函数
*
* #define WITH_CANVAS_OFFLINE_CUSTION 1
*/
/**
* 开启透明色背景的刷新机制,一般使用在多图层的透明背景使用
*
* #define WITH_LCD_CLEAR_ALPHA 1
*/
/**
* 如果支持多块不连续的内存块,请定义内存块的数目。
*
* #define TK_MAX_MEM_BLOCK_NR 4
*/
/**
* 用于控制窗口动画是否使用缓存。开启后可以降低内存需求(减少2倍framebuffer大小的内存),如果内存紧缺,在下面情况可以开启:
* 1. 界面简单
* 2. CPU速度快
*
* 如果绘制速度慢,而且内存紧缺,建议关闭窗口动画。
*
* 限制条件:
* 1.不支持缩放窗口动画。
* 2.不支持对话框高亮策略。
*
* #define WITHOUT_WINDOW_ANIMATOR_CACHE 1
*/
// #define WITHOUT_WINDOW_ANIMATOR_CACHE 1

View File

@ -0,0 +1,67 @@
/**
* File: awtk.h
* Author: AWTK Develop Team
* Brief: awtk widgets
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-12-15 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef AWTK_EXT_WIDGETS_H
#define AWTK_EXT_WIDGETS_H
#include "vpage/vpage.h"
#include "switch/switch.h"
#include "gauge/gauge.h"
#include "gauge/gauge_pointer.h"
#include "gif_image/gif_image.h"
#include "svg_image/svg_image.h"
#include "keyboard/keyboard.h"
#include "keyboard/candidates.h"
#include "keyboard/lang_indicator.h"
#include "base/widget_factory.h"
#include "rich_text/rich_text.h"
#include "rich_text/rich_text_view.h"
#include "slide_menu/slide_menu.h"
#include "image_value/image_value.h"
#include "time_clock/time_clock.h"
#include "scroll_view/list_item.h"
#include "scroll_view/list_view.h"
#include "slide_view/slide_view.h"
#include "slide_view/slide_indicator.h"
#include "scroll_view/scroll_bar.h"
#include "scroll_view/scroll_view.h"
#include "scroll_view/list_view_h.h"
#include "color_picker/color_picker.h"
#include "canvas_widget/canvas_widget.h"
#include "text_selector/text_selector.h"
#include "color_picker/color_component.h"
#include "progress_circle/progress_circle.h"
#include "image_animation/image_animation.h"
#include "mutable_image/mutable_image.h"
#include "combo_box_ex/combo_box_ex.h"
#include "scroll_label/hscroll_label.h"
#include "mledit/line_number.h"
#include "mledit/mledit.h"
#include "features/draggable.h"
#if defined(WITH_FS_RES) || defined(WITH_FS)
#include "file_browser/file_chooser.h"
#include "file_browser/file_browser_view.h"
#endif /*WITH_FS*/
#include "ext_widgets/ext_widgets.h"
#endif /*AWTK_EXT_WIDGETS_H*/

View File

@ -0,0 +1,528 @@
/**
* File: awtk.c
* Author: AWTK Develop Team
* Brief: awtk
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-03-03 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "awtk.h"
#include "tkc/mem.h"
#include "tkc/fscript.h"
#include "base/idle.h"
#include "base/timer.h"
#include "tkc/thread.h"
#include "tkc/time_now.h"
#include "base/locale_info.h"
#include "tkc/platform.h"
#include "base/main_loop.h"
#include "base/font_manager.h"
#include "base/input_method.h"
#include "base/image_manager.h"
#include "base/window_manager.h"
#include "base/widget_factory.h"
#include "base/assets_manager.h"
#include "fscript_ext/fscript_ext.h"
#ifdef WITH_VGCANVAS
#include "base/vgcanvas_asset_manager.h"
#endif
#ifdef WITH_FSCRIPT_EXT
#ifndef WITH_DATA_READER_WRITER
#define WITH_DATA_READER_WRITER
#endif /*WITH_DATA_READER_WRITER*/
#endif /*WITH_FSCRIPT_EXT*/
#ifdef WITH_DATA_READER_WRITER
#include "tkc/data_reader_factory.h"
#include "tkc/data_writer_factory.h"
#include "tkc/data_writer_file.h"
#include "tkc/data_writer_wbuffer.h"
#include "tkc/data_reader_file.h"
#include "tkc/data_reader_mem.h"
#include "base/data_reader_asset.h"
#endif /*WITH_DATA_READER_WRITER*/
#include "base/widget_animator_manager.h"
#include "font_loader/font_loader_bitmap.h"
#include "base/window_animator_factory.h"
#include "widgets/widgets.h"
#include "base/self_layouter_factory.h"
#include "base/children_layouter_factory.h"
#include "base/dialog_highlighter_factory.h"
#ifndef WITHOUT_LAYOUT
#include "layouters/self_layouter_builtins.h"
#include "layouters/children_layouter_builtins.h"
#endif /*WITHOUT_LAYOUT*/
#ifndef WITHOUT_WINDOW_ANIMATORS
#include "window_animators/window_animator_builtins.h"
#endif /*WITHOUT_WINDOW_ANIMATORS*/
#ifndef WITHOUT_DIALOG_HIGHLIGHTER
#include "dialog_highlighters/dialog_highlighter_builtins.h"
#endif /*WITHOUT_DIALOG_HIGHLIGHTER*/
#ifndef WITHOUT_CLIPBOARD
#ifdef WITH_SDL
#include "clip_board/clip_board_sdl.h"
#define clip_board_create clip_board_sdl_create
#else
#include "clip_board/clip_board_default.h"
#define clip_board_create clip_board_default_create
#endif /*WITH_SDL*/
#endif /*WITHOUT_CLIPBOARD*/
#ifdef WITH_TRUETYPE_FONT
#include "font_loader/font_loader_truetype.h"
#endif /*WITH_TRUETYPE_FONT*/
#ifdef WITH_STB_IMAGE
#include "image_loader/image_loader_stb.h"
#endif /*WITH_STB_IMAGE*/
#ifdef WITH_LIBPNG_IMAGE
#include "image_loader/image_loader_libpng.h"
#endif
#ifdef AWTK_WEB
#include "image_loader_web.h"
#endif /*AWTK_WEB*/
static uint64_t s_ui_thread_id = 0;
static ret_t tk_add_font(const asset_info_t* res) {
if (res->subtype == ASSET_TYPE_FONT_BMP) {
#ifdef WITH_BITMAP_FONT
font_manager_add_font(font_manager(), font_bitmap_create(res->name, res->data, res->size));
#endif
} else if (res->subtype == ASSET_TYPE_FONT_TTF) {
#ifdef WITH_TRUETYPE_FONT
font_manager_add_font(font_manager(), font_truetype_create(res->name, res->data, res->size));
#endif /*WITH_TRUETYPE_FONT*/
} else {
log_debug("not support font type:%d\n", res->subtype);
}
return RET_OK;
}
ret_t tk_init_assets(void) {
uint32_t i = 0;
uint32_t nr = assets_manager()->assets.size;
const asset_info_t** all = (const asset_info_t**)(assets_manager()->assets.elms);
for (i = 0; i < nr; i++) {
const asset_info_t* iter = all[i];
switch (iter->type) {
case ASSET_TYPE_FONT:
tk_add_font(iter);
break;
case ASSET_TYPE_STYLE:
if (theme()->data == NULL && strcmp(iter->name, "default") == 0) {
theme_set_theme_data(theme(), iter->data);
}
break;
}
}
return RET_OK;
}
static ret_t tk_clear_cache_when_oom(uint32_t tried_times) {
if (tried_times == 1) {
image_manager_unload_unused(image_manager(), 10);
font_manager_shrink_cache(font_manager(), 10);
} else if (tried_times == 2) {
image_manager_unload_unused(image_manager(), 0);
font_manager_shrink_cache(font_manager(), 0);
} else if (tried_times == 3) {
event_t e = event_init(EVT_LOW_MEMORY, NULL);
font_manager_unload_all(font_manager());
widget_dispatch(window_manager(), &e);
} else {
event_t e = event_init(EVT_OUT_OF_MEMORY, NULL);
widget_dispatch(window_manager(), &e);
}
return RET_OK;
}
static tk_semaphore_t* s_clear_cache_semaphore = NULL;
static ret_t exec_clear_cache(exec_info_t* info) {
uint32_t tried_times = (uint32_t)tk_pointer_to_int(info->ctx);
tk_clear_cache_when_oom(tried_times);
tk_semaphore_post(s_clear_cache_semaphore);
log_debug("clear cache: %u\n", tried_times);
return RET_REMOVE;
}
static ret_t awtk_mem_on_out_of_memory(void* ctx, uint32_t tried_times, uint32_t need_size) {
if (tk_is_ui_thread()) {
tk_clear_cache_when_oom(tried_times);
} else {
event_queue_req_t req;
memset(&req, 0x00, sizeof(req));
req.exec_in_ui.e.type = REQ_EXEC_IN_UI;
req.exec_in_ui.info.func = exec_clear_cache;
req.exec_in_ui.info.ctx = tk_pointer_from_int(tried_times);
log_debug("req clear cache begin: %u\n", tried_times);
main_loop_queue_event(main_loop(), &req);
tk_semaphore_wait(s_clear_cache_semaphore, 10000);
log_debug("req clear cache done: %u\n", tried_times);
}
return RET_OK;
}
ret_t tk_init_internal(void) {
font_loader_t* font_loader = NULL;
s_ui_thread_id = tk_thread_self();
#ifndef WITHOUT_FSCRIPT
fscript_global_init();
#endif
#ifdef WITH_FSCRIPT_EXT
fscript_ext_init();
#endif /*WITH_FSCRIPT_EXT*/
#ifdef WITH_DATA_READER_WRITER
data_writer_factory_set(data_writer_factory_create());
data_reader_factory_set(data_reader_factory_create());
data_writer_factory_register(data_writer_factory(), "file", data_writer_file_create);
data_reader_factory_register(data_reader_factory(), "file", data_reader_file_create);
data_reader_factory_register(data_reader_factory(), "asset", data_reader_asset_create);
data_reader_factory_register(data_reader_factory(), "mem", data_reader_mem_create);
data_writer_factory_register(data_writer_factory(), "wbuffer", data_writer_wbuffer_create);
#endif /*WITH_DATA_READER_WRITER*/
#ifdef WITH_STB_IMAGE
image_loader_register(image_loader_stb());
#endif /*WITH_STB_IMAGE*/
#ifdef WITH_LIBPNG_IMAGE
image_loader_register(image_loader_libpng());
#endif /*WITH_LIBPNG_IMAGE*/
#ifdef AWTK_WEB
image_loader_register(image_loader_web());
#endif /*AWTK_WEB*/
#ifdef WITH_TRUETYPE_FONT
font_loader = font_loader_truetype();
#elif defined(WITH_BITMAP_FONT)
font_loader = font_loader_bitmap();
#endif /*WITH_TRUETYPE_FONT*/
return_value_if_fail(timer_prepare(time_now_ms) == RET_OK, RET_FAIL);
return_value_if_fail(idle_manager_set(idle_manager_create()) == RET_OK, RET_FAIL);
return_value_if_fail(widget_factory_set(widget_factory_create()) == RET_OK, RET_FAIL);
return_value_if_fail(theme_set(theme_default_create(NULL)) == RET_OK, RET_FAIL);
return_value_if_fail(assets_manager_set(assets_manager_create(30)) == RET_OK, RET_FAIL);
#ifndef WITHOUT_INPUT_METHOD
return_value_if_fail(input_method_set(input_method_create()) == RET_OK, RET_FAIL);
#endif /*WITHOUT_INPUT_METHOD*/
#ifdef WITH_VGCANVAS
return_value_if_fail(vgcanvas_asset_manager_set(vgcanvas_asset_manager_create()) == RET_OK,
RET_FAIL);
#endif
return_value_if_fail(locale_info_set(locale_info_create(NULL, NULL)) == RET_OK, RET_FAIL);
return_value_if_fail(font_manager_set(font_manager_create(font_loader)) == RET_OK, RET_FAIL);
return_value_if_fail(font_manager_set_assets_manager(font_manager(), assets_manager()) == RET_OK,
RET_FAIL);
return_value_if_fail(image_manager_set(image_manager_create()) == RET_OK, RET_FAIL);
#ifndef WITHOUT_WINDOW_ANIMATORS
return_value_if_fail(window_animator_factory_set(window_animator_factory_create()) == RET_OK,
RET_FAIL);
window_animator_register_builtins();
#endif /*WITHOUT_WIDGET_ANIMATORS*/
#ifndef WITHOUT_DIALOG_HIGHLIGHTER
return_value_if_fail(
dialog_highlighter_factory_set(dialog_highlighter_factory_create()) == RET_OK, RET_FAIL);
#endif /*WITHOUT_DIALOG_HIGHLIGHTER*/
#ifndef WITHOUT_LAYOUT
return_value_if_fail(children_layouter_factory_set(children_layouter_factory_create()) == RET_OK,
RET_FAIL);
return_value_if_fail(self_layouter_factory_set(self_layouter_factory_create()) == RET_OK,
RET_FAIL);
self_layouter_register_builtins();
children_layouter_register_builtins();
#endif /*WITHOUT_LAYOUT*/
return_value_if_fail(window_manager_set(window_manager_create()) == RET_OK, RET_FAIL);
#ifndef WITHOUT_CLIPBOARD
return_value_if_fail(clip_board_set(clip_board_create()) == RET_OK, RET_FAIL);
#endif /*WITHOUT_CLIPBOARD*/
#ifndef WITHOUT_WIDGET_ANIMATORS
return_value_if_fail(widget_animator_manager_set(widget_animator_manager_create()) == RET_OK,
RET_FAIL);
#endif /*WITHOUT_WIDGET_ANIMATORS*/
#ifndef WITHOUT_DIALOG_HIGHLIGHTER
dialog_highlighter_register_builtins();
#endif /*WITHOUT_DIALOG_HIGHLIGHTER*/
tk_widgets_init();
tk_mem_set_on_out_of_memory(awtk_mem_on_out_of_memory, NULL);
s_clear_cache_semaphore = tk_semaphore_create(0, "clear_cache");
return RET_OK;
}
ret_t tk_init(wh_t w, wh_t h, app_type_t app_type, const char* app_name, const char* app_root) {
main_loop_t* loop = NULL;
return_value_if_fail(platform_prepare() == RET_OK, RET_FAIL);
return_value_if_fail(tk_mem_init_stage2() == RET_OK, RET_FAIL);
ENSURE(system_info_init(app_type, app_name, app_root) == RET_OK);
return_value_if_fail(tk_init_internal() == RET_OK, RET_FAIL);
loop = main_loop_init(w, h);
return_value_if_fail(loop != NULL, RET_FAIL);
return RET_OK;
}
ret_t tk_deinit_internal(void) {
idle_manager_dispatch(idle_manager());
#ifndef WITHOUT_CLIPBOARD
clip_board_destroy(clip_board());
clip_board_set(NULL);
#endif /*WITHOUT_CLIPBOARD*/
#ifndef WITHOUT_LAYOUT
children_layouter_factory_destroy(children_layouter_factory());
children_layouter_factory_set(NULL);
self_layouter_factory_destroy(self_layouter_factory());
self_layouter_factory_set(NULL);
#endif /*WITHOUT_LAYOUT*/
image_manager_destroy(image_manager());
image_manager_set(NULL);
window_manager_close_all(window_manager());
widget_destroy(window_manager());
widget_factory_destroy(widget_factory());
widget_factory_set(NULL);
idle_manager_dispatch(idle_manager());
window_manager_set(NULL);
#ifndef WITHOUT_INPUT_METHOD
input_method_destroy(input_method());
input_method_set(NULL);
#endif /*WITHOUT_INPUT_METHOD*/
#ifndef WITHOUT_DIALOG_HIGHLIGHTER
dialog_highlighter_factory_destroy(dialog_highlighter_factory());
dialog_highlighter_factory_set(NULL);
#endif /*WITHOUT_DIALOG_HIGHLIGHTER*/
#ifndef WITHOUT_WINDOW_ANIMATORS
window_animator_factory_destroy(window_animator_factory());
window_animator_factory_set(NULL);
#endif /*WITHOUT_WINDOW_ANIMATORS*/
#ifndef WITHOUT_WIDGET_ANIMATORS
widget_animator_manager_destroy(widget_animator_manager());
widget_animator_manager_set(NULL);
#endif /*WITHOUT_WIDGET_ANIMATORS*/
timer_manager_destroy(timer_manager());
timer_manager_set(NULL);
idle_manager_destroy(idle_manager());
idle_manager_set(NULL);
theme_destroy(theme());
theme_set(NULL);
font_manager_destroy(font_manager());
font_manager_set(NULL);
locale_info_destroy(locale_info());
locale_info_set(NULL);
assets_manager_destroy(assets_manager());
assets_manager_set(NULL);
#ifdef WITH_VGCANVAS
vgcanvas_asset_manager_destroy(vgcanvas_asset_manager());
vgcanvas_asset_manager_set(NULL);
#endif
#ifdef WITH_DATA_READER_WRITER
data_writer_factory_destroy(data_writer_factory());
data_reader_factory_destroy(data_reader_factory());
data_writer_factory_set(NULL);
data_reader_factory_set(NULL);
#endif /*WITH_DATA_READER_WRITER*/
system_info_deinit();
#ifndef WITHOUT_FSCRIPT
fscript_global_deinit();
#endif
tk_semaphore_destroy(s_clear_cache_semaphore);
return RET_OK;
}
ret_t tk_exit(void) {
main_loop_destroy(main_loop());
main_loop_set(NULL);
return tk_deinit_internal();
}
ret_t tk_run() {
main_loop_run(main_loop());
return tk_exit();
}
static ret_t tk_quit_idle(const timer_info_t* timer) {
main_loop_t* loop = main_loop();
loop->app_quited = TRUE;
return main_loop_quit(loop);
}
ret_t tk_quit() {
timer_add(tk_quit_idle, NULL, 0);
return RET_OK;
}
ret_t tk_set_lcd_orientation(lcd_orientation_t orientation) {
main_loop_t* loop = main_loop();
lcd_orientation_t old_orientation;
system_info_t* info = system_info();
return_value_if_fail(loop != NULL && info != NULL, RET_OK);
if (info->lcd_orientation != orientation) {
orientation_event_t e;
old_orientation = info->lcd_orientation;
system_info_set_lcd_orientation(info, orientation);
orientation_event_init(&e, EVT_ORIENTATION_WILL_CHANGED, NULL, old_orientation, orientation);
widget_dispatch(window_manager(), (event_t*)&e);
}
return RET_OK;
}
int32_t tk_get_pointer_x(void) {
return window_manager_get_pointer_x(window_manager());
}
int32_t tk_get_pointer_y(void) {
return window_manager_get_pointer_y(window_manager());
}
bool_t tk_is_pointer_pressed(void) {
return window_manager_get_pointer_pressed(window_manager());
}
bool_t tk_is_ui_thread(void) {
return s_ui_thread_id == tk_thread_self();
}
typedef struct _idle_callback_info_t {
void* ctx;
bool_t done;
bool_t sync;
ret_t result;
tk_callback_t func;
} idle_callback_info_t;
static idle_callback_info_t* idle_callback_info_create(tk_callback_t func, void* ctx) {
idle_callback_info_t* info = TKMEM_ZALLOC(idle_callback_info_t);
return_value_if_fail(info != NULL, NULL);
info->func = func;
info->ctx = ctx;
return info;
}
static ret_t idle_callback_info_destroy(idle_callback_info_t* info) {
return_value_if_fail(info != NULL && info->func != NULL, RET_BAD_PARAMS);
memset(info, 0x00, sizeof(*info));
TKMEM_FREE(info);
return RET_OK;
}
static ret_t idle_func_of_callback(const idle_info_t* info) {
idle_callback_info_t* cinfo = (idle_callback_info_t*)(info->ctx);
ret_t ret = cinfo->func(cinfo->ctx);
if (cinfo->sync) {
cinfo->done = TRUE;
cinfo->result = ret;
/*call by sync not allow repeat*/
assert(ret != RET_REPEAT);
return RET_REMOVE;
} else {
if (ret != RET_REPEAT) {
idle_callback_info_destroy(cinfo);
ret = RET_REMOVE;
}
return ret;
}
}
ret_t tk_run_in_ui_thread(tk_callback_t func, void* ctx, bool_t wait_until_done) {
return_value_if_fail(func != NULL, RET_BAD_PARAMS);
if (tk_is_ui_thread()) {
return func(ctx);
} else {
idle_callback_info_t* info = idle_callback_info_create(func, ctx);
return_value_if_fail(info != NULL, RET_OOM);
info->sync = wait_until_done;
if (idle_queue(idle_func_of_callback, info) == RET_OK) {
ret_t ret = RET_OK;
if (wait_until_done) {
while (!(info->done)) {
sleep_ms(20);
}
ret = info->result;
idle_callback_info_destroy(info);
}
return ret;
} else {
idle_callback_info_destroy(info);
return RET_FAIL;
}
}
}

View File

@ -0,0 +1,165 @@
/**
* File: awtk.h
* Author: AWTK Develop Team
* Brief: awtk
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-03-03 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_GLOBAL_H
#define TK_GLOBAL_H
#include "base/types_def.h"
BEGIN_C_DECLS
/**
* @class global_t
* @annotation ["scriptable", "fake"]
* TK全局对象。
*/
/**
* @method tk_init
* 初始化TK。
* @alias init
* @annotation ["static", "scriptable"]
* @param {wh_t} w LCD宽度。
* @param {wh_t} h LCD高度。
* @param {app_type_t} app_type 应用程序的类型。
* @param {const char*} app_name 应用程序的名称(必须为常量字符串)。
* @param {const char*} app_root 应用程序的根目录,用于定位资源文件(必须为常量字符串)。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t tk_init(wh_t w, wh_t h, app_type_t app_type, const char* app_name, const char* app_root);
/**
* @method tk_run
* 进入TK事件主循环。
* @alias run
* @annotation ["static", "scriptable"]
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t tk_run(void);
/**
* @method tk_quit
* 退出TK事件主循环。
* @alias global_quit
* @annotation ["static", "scriptable"]
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t tk_quit(void);
/**
* @method tk_get_pointer_x
* 获取全局指针的X坐标。
* @alias global_get_pointer_x
* @annotation ["static", "scriptable"]
*
* @return {int32_t} 返回全局指针的X坐标。
*/
int32_t tk_get_pointer_x(void);
/**
* @method tk_get_pointer_y
* 获取全局指针的Y坐标。
* @alias global_get_pointer_y
* @annotation ["static", "scriptable"]
*
* @return {int32_t} 返回全局指针的X坐标。
*/
int32_t tk_get_pointer_y(void);
/**
* @method tk_is_pointer_pressed
* 获取全局指针是否按下。
* @alias global_is_pointer_pressed
* @annotation ["static", "scriptable"]
*
* @return {bool_t} 返回全局指针是否按下。
*/
bool_t tk_is_pointer_pressed(void);
/**
* @method tk_set_lcd_orientation
* 设置屏幕的旋转方向(XXX:目前仅支持0度和90度)。
* @param {int} orientation 旋转方向。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t tk_set_lcd_orientation(lcd_orientation_t orientation);
/**
* @method tk_init_assets
* 初始化资源。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t tk_init_assets(void);
/**
* @method tk_init_internal
* init。
*> public for test program
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t tk_init_internal(void);
/**
* @method tk_deinit_internal
* deinit。
*> public for test program
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t tk_deinit_internal(void);
/**
* @method tk_exit
* public for web
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t tk_exit(void);
/**
* @method tk_is_ui_thread
*
* 判断当前线程是否是UI线程。
* @return {bool_t} 返回TRUE表示是否则表示否。
*/
bool_t tk_is_ui_thread(void);
/**
* @method tk_run_in_ui_thread
* 后台线程在UI线程执行指定的函数。
*
* @param {tk_callback_t} func 函数。
* @param {void*} ctx 回调函数的上下文。
* @param {bool_t} wait_until_done 是否等待完成。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t tk_run_in_ui_thread(tk_callback_t func, void* ctx, bool_t wait_until_done);
END_C_DECLS
#endif /*TK_GLOBAL_H*/

View File

@ -0,0 +1,243 @@
/**
* File: awtk_main.c
* Author: AWTK Develop Team
* Brief: awtk main
*
* Copyright (c) 2018 - 2020 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-02-16 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "awtk.h"
BEGIN_C_DECLS
extern ret_t assets_init(void);
END_C_DECLS
#ifndef APP_DEFAULT_FONT
#define APP_DEFAULT_FONT "default"
#endif /*APP_DEFAULT_FONT*/
#ifndef LCD_WIDTH
#define LCD_WIDTH 320
#endif /*LCD_WIDTH*/
#ifndef LCD_HEIGHT
#define LCD_HEIGHT 480
#endif /*LCD_HEIGHT*/
#ifndef APP_TYPE
#define APP_TYPE APP_SIMULATOR
#endif /*APP_TYPE*/
#ifndef GLOBAL_INIT
#define GLOBAL_INIT()
#endif /*GLOBAL_INIT*/
#ifndef GLOBAL_EXIT
#define GLOBAL_EXIT()
#endif /*GLOBAL_EXIT*/
#ifndef APP_NAME
#define APP_NAME "awtk"
#endif /*APP_NAME*/
#ifndef APP_RES_ROOT
#define APP_RES_ROOT NULL
#endif /*APP_RES_ROOT*/
#include "base/asset_loader_zip.h"
#ifdef USE_GUI_MAIN
int gui_app_start_ex(int lcd_w, int lcd_h, const char* res_root);
int gui_app_start(int lcd_w, int lcd_h) {
return gui_app_start_ex(lcd_w, lcd_h, APP_RES_ROOT);
}
int gui_app_start_ex(int lcd_w, int lcd_h, const char* res_root) {
bool_t is_reboot = FALSE;
do {
tk_init(lcd_w, lcd_h, APP_MOBILE, APP_NAME, res_root);
#elif defined(MOBILE_APP) && defined(WITH_SDL)
int SDL_main(int argc, char* argv[]) {
bool_t is_reboot = FALSE;
int32_t lcd_w = 0;
int32_t lcd_h = 0;
do {
tk_init(lcd_w, lcd_h, APP_MOBILE, APP_NAME, APP_RES_ROOT);
#elif defined(WIN32) && !defined(MINGW)
#include <windows.h>
#include <combaseapi.h>
#ifndef MAX_ARGV
#define MAX_ARGV 7
#endif
static void command_line_to_argv(char* lpcmdline, char* argv[MAX_ARGV], int32_t* argc) {
int32_t i = 1;
char* p = lpcmdline;
argv[0] = "awtk.exe";
if (p == NULL || *p == '\0') {
argv[1] = NULL;
return;
}
for (i = 1; i < MAX_ARGV; i++) {
argv[i] = p;
if (*p == '\"') {
argv[i] = p + 1;
p = strchr(p + 1, '\"');
if (p == NULL) break;
*p++ = '\0';
if (*p == 0) break;
} else {
p = strchr(p, ' ');
}
if (p == NULL) {
break;
}
while (*p == ' ') {
*p++ = '\0';
}
}
*argc = i + 1;
return;
}
int WINAPI wWinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPWSTR lpcmdline, int ncmdshow) {
str_t str;
int argc = 1;
char* argv[MAX_ARGV];
bool_t is_reboot = FALSE;
bool_t enable_console = TRUE;
int32_t lcd_w = LCD_WIDTH;
int32_t lcd_h = LCD_HEIGHT;
char buff[1024];
str_init(&str, 0);
str.str = buff;
str.size = 0;
str.capacity = sizeof(buff);
str_from_wstr(&str, lpcmdline);
command_line_to_argv(str.str, argv, &argc);
str.str = NULL;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
#ifdef ON_CMD_LINE
ON_CMD_LINE(argc, argv);
#else
if (argc >= 2) {
lcd_w = tk_atoi(argv[1]);
}
if (argc >= 3) {
lcd_h = tk_atoi(argv[2]);
}
if (argc >= 4) {
enable_console = tk_atob(argv[3]);
}
#endif /*ON_CMD_LINE*/
if (enable_console) {
TK_ENABLE_CONSOLE();
}
do {
tk_init(lcd_w, lcd_h, APP_TYPE, APP_NAME, APP_RES_ROOT);
#else
int main(int argc, char* argv[]) {
bool_t is_reboot = FALSE;
int32_t lcd_w = LCD_WIDTH;
int32_t lcd_h = LCD_HEIGHT;
#ifdef ON_CMD_LINE
ON_CMD_LINE(argc, argv);
#else
if (argc >= 2) {
lcd_w = tk_atoi(argv[1]);
}
if (argc >= 3) {
lcd_h = tk_atoi(argv[2]);
}
#endif /*ON_CMD_LINE*/
do {
tk_init(lcd_w, lcd_h, APP_TYPE, APP_NAME, APP_RES_ROOT);
#endif
#ifdef ASSETS_ZIP
assets_manager_set_res_root(assets_manager(), "");
log_debug("Load assets from zip: %s\n", ASSETS_ZIP);
assets_manager_set_loader(assets_manager(), asset_loader_zip_create(ASSETS_ZIP));
#endif /*ASSETS_ZIP*/
#if defined(WITH_LCD_PORTRAIT)
if (lcd_w > lcd_h) {
tk_set_lcd_orientation(LCD_ORIENTATION_90);
}
#endif /*WITH_LCD_PORTRAIT*/
#ifdef WITH_LCD_LANDSCAPE
if (lcd_w < lcd_h) {
tk_set_lcd_orientation(LCD_ORIENTATION_90);
}
#endif /*WITH_LCD_PORTRAIT*/
system_info_set_default_font(system_info(), APP_DEFAULT_FONT);
assets_init();
#ifndef WITHOUT_EXT_WIDGETS
tk_ext_widgets_init();
#endif /*WITHOUT_EXT_WIDGETS*/
#ifdef NDEBUG
log_set_log_level(LOG_LEVEL_INFO);
#else
log_set_log_level(LOG_LEVEL_DEBUG);
//log_set_log_level(LOG_LEVEL_WARN);
#endif /*NDEBUG*/
log_info("Build at: %s %s\n", __DATE__, __TIME__);
#ifdef ENABLE_CURSOR
window_manager_set_cursor(window_manager(), "cursor");
#endif /*ENABLE_CURSOR*/
GLOBAL_INIT();
#if defined(APP_DEFAULT_LANGUAGE) && defined(APP_DEFAULT_COUNTRY)
locale_info_change(locale_info(), APP_DEFAULT_LANGUAGE, APP_DEFAULT_COUNTRY);
#endif /*APP_DEFAULT_LANGUAGE and APP_DEFAULT_LANGUAGE*/
application_init();
tk_run();
is_reboot = application_exit() == RET_REPEAT;
GLOBAL_EXIT();
#ifdef HAS_STDIO
fflush(stdout);
#endif /*HAS_STDIO*/
} while (is_reboot);
#if defined(WIN32) && !defined(MINGW)
str_reset(&str);
#endif /*WIN32*/
#if defined(IOS) || defined(ANDROID)
exit(0);
#endif /*IOS | ANDROID*/
return 0;
}

View File

@ -0,0 +1,100 @@
/**
* File: awtk_tkc.h
* Author: AWTK Develop Team
* Brief: awtk toolkit c libs
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-12-15 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_TKC_H
#define TK_TKC_H
#include "tkc/action_queue.h"
#include "tkc/action_thread.h"
#include "tkc/action_thread_pool.h"
#include "tkc/asset_info.h"
#include "tkc/buffer.h"
#include "tkc/color.h"
#include "tkc/color_parser.h"
#include "tkc/compressor.h"
#include "tkc/cond.h"
#include "tkc/cond_var.h"
#include "tkc/crc.h"
#include "tkc/darray.h"
#include "tkc/data_reader.h"
#include "tkc/data_reader_factory.h"
#include "tkc/data_reader_file.h"
#include "tkc/data_writer.h"
#include "tkc/data_writer_factory.h"
#include "tkc/data_writer_file.h"
#include "tkc/date_time.h"
#include "tkc/easing.h"
#include "tkc/emitter.h"
#include "tkc/endian.h"
#include "tkc/event.h"
#include "tkc/event_source.h"
#include "tkc/event_source_fd.h"
#include "tkc/event_source_idle.h"
#include "tkc/event_source_manager.h"
#include "tkc/event_source_manager_default.h"
#include "tkc/event_source_timer.h"
#include "tkc/fscript.h"
#include "tkc/fs.h"
#include "tkc/func_call_parser.h"
#include "tkc/func_desc.h"
#include "tkc/idle_info.h"
#include "tkc/idle_manager.h"
#include "tkc/int_str.h"
#include "tkc/iostream.h"
#include "tkc/istream.h"
#include "tkc/log.h"
#include "tkc/matrix.h"
#include "tkc/mem.h"
#include "tkc/mime_types.h"
#include "tkc/mutex.h"
#include "tkc/named_value.h"
#include "tkc/object.h"
#include "tkc/object_array.h"
#include "tkc/object_default.h"
#include "tkc/ostream.h"
#include "tkc/path.h"
#include "tkc/platform.h"
#include "tkc/qaction.h"
#include "tkc/rect.h"
#include "tkc/ring_buffer.h"
#include "tkc/rom_fs.h"
#include "tkc/semaphore.h"
#include "tkc/slist.h"
#include "tkc/socket_pair.h"
#include "tkc/socket_helper.h"
#include "tkc/str.h"
#include "tkc/str_str.h"
#include "tkc/stream_const.h"
#include "tkc/thread.h"
#include "tkc/time_now.h"
#include "tkc/timer_info.h"
#include "tkc/timer_manager.h"
#include "tkc/tokenizer.h"
#include "tkc/types_def.h"
#include "tkc/utf8.h"
#include "tkc/utils.h"
#include "tkc/value.h"
#include "tkc/value_desc.h"
#include "tkc/waitable_action_queue.h"
#include "tkc/wstr.h"
#include "tkc/rlog.h"
#endif /*TK_TKC_H*/

View File

@ -0,0 +1,36 @@
/**
* File: awtk_version.h
* Author: AWTK Develop Team
* Brief: awtk version
*
* Copyright (c) 2021 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2021-08-06 Luo Zhiming <luozhiming@zlg.cn> created
*
*/
#ifndef AWTK_VERSION_H
#define AWTK_VERSION_H
#define AWTK_VERSION_MAJOR 1
#define AWTK_VERSION_MINOR 7
#define AWTK_VERSION_MICRO 0
#define AWTK_VERSION_RELEASE_NUMBER 0
#define AWTK_VERSION_EXPERIMENTAL 0x7FFFFFFF
/* awtk develop released a stable version */
#ifndef AWTK_VERSION_RELEASE_ID
#define AWTK_VERSION_RELEASE_ID AWTK_VERSION_EXPERIMENTAL
#endif /*AWTK_VERSION_RELEASE_ID*/
#endif /*AWTK_VERSION_H*/

View File

@ -0,0 +1,61 @@
/**
* File: awtk.h
* Author: AWTK Develop Team
* Brief: awtk widgets
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-12-15 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef AWTK_WIDGETS_H
#define AWTK_WIDGETS_H
#include "base/dialog.h"
#include "base/window.h"
#include "widgets/app_bar.h"
#include "widgets/button.h"
#include "widgets/button_group.h"
#include "widgets/calibration_win.h"
#include "widgets/check_button.h"
#include "widgets/color_tile.h"
#include "widgets/clip_view.h"
#include "widgets/column.h"
#include "widgets/combo_box.h"
#include "widgets/combo_box_item.h"
#include "widgets/dialog_client.h"
#include "widgets/dialog_title.h"
#include "widgets/dragger.h"
#include "widgets/edit.h"
#include "widgets/grid.h"
#include "widgets/grid_item.h"
#include "widgets/group_box.h"
#include "widgets/image.h"
#include "widgets/label.h"
#include "widgets/overlay.h"
#include "widgets/pages.h"
#include "widgets/popup.h"
#include "widgets/progress_bar.h"
#include "widgets/row.h"
#include "widgets/slider.h"
#include "widgets/spin_box.h"
#include "widgets/system_bar.h"
#include "widgets/tab_button.h"
#include "widgets/tab_button_group.h"
#include "widgets/tab_control.h"
#include "widgets/view.h"
#include "widgets/digit_clock.h"
#endif /*AWTK_WIDGETS_H*/

View File

@ -0,0 +1 @@
mem_test

View File

@ -0,0 +1,44 @@
/**
* File: asset_loader.c
* Author: AWTK Develop Team
* Brief: asset_loader
*
* Copyright (c) 2019 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-02-26 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "base/asset_loader.h"
asset_info_t* asset_loader_load(asset_loader_t* loader, uint16_t type, uint16_t subtype,
const char* path, const char* name) {
return_value_if_fail(path != NULL && name != NULL, NULL);
return_value_if_fail(loader != NULL && loader->vt != NULL && loader->vt->load != NULL, NULL);
return loader->vt->load(loader, type, subtype, path, name);
}
bool_t asset_loader_exist(asset_loader_t* loader, const char* path) {
return_value_if_fail(path != NULL, FALSE);
return_value_if_fail(loader != NULL && loader->vt != NULL && loader->vt->exist != NULL, FALSE);
return loader->vt->exist(loader, path);
}
ret_t asset_loader_destroy(asset_loader_t* loader) {
return_value_if_fail(loader != NULL && loader->vt != NULL && loader->vt->destroy != NULL,
RET_BAD_PARAMS);
return loader->vt->destroy(loader);
}

View File

@ -0,0 +1,97 @@
/**
* File: asset_loader.h
* Author: AWTK Develop Team
* Brief: asset_loader
*
* Copyright (c) 2019 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-02-26 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_ASSET_LOADER_H
#define TK_ASSET_LOADER_H
#include "tkc/asset_info.h"
BEGIN_C_DECLS
struct _asset_loader_t;
typedef struct _asset_loader_t asset_loader_t;
typedef asset_info_t* (*asset_loader_load_t)(asset_loader_t* loader, uint16_t type,
uint16_t subtype, const char* path, const char* name);
typedef bool_t (*asset_loader_exist_t)(asset_loader_t* loader, const char* path);
typedef ret_t (*asset_loader_destroy_t)(asset_loader_t* loader);
typedef struct _asset_loader_vtable_t {
asset_loader_load_t load;
asset_loader_exist_t exist;
asset_loader_destroy_t destroy;
} asset_loader_vtable_t;
/**
* @class asset_loader_t
* 资源加载器接口。
*/
struct _asset_loader_t {
const asset_loader_vtable_t* vt;
};
/**
* @method asset_loader_create
* 创建缺省的资源加载器。
*
* @return {asset_loader_t*} 返回loader对象。
*/
asset_loader_t* asset_loader_create(void);
/**
* @method asset_loader_load
* 加载指定的资源。
* @param {asset_loader_t*} loader loader对象。
* @param {uint16_t} type 资源类型。
* @param {uint16_t} subtype 资源子类型。
* @param {const char*} path 路径。
* @param {const char*} name 名称。
*
* @return {asset_info_t*} 返回资源对象(由调用者销毁)。
*/
asset_info_t* asset_loader_load(asset_loader_t* loader, uint16_t type, uint16_t subtype,
const char* path, const char* name);
/**
* @method asset_loader_exist
* 判断指定资源是否存在。
* 。
* @param {asset_loader_t*} loader loader对象。
* @param {const char*} path 资源是路径。
*
* @return {bool_t} 返回TRUE表示存在否则不存在。
*/
bool_t asset_loader_exist(asset_loader_t* loader, const char* path);
/**
* @method asset_loader_destroy
* 销毁loader对象。
* @param {asset_loader_t*} loader loader对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t asset_loader_destroy(asset_loader_t* loader);
#define ASSET_LOADER(loader) ((asset_loader_t*)(loader))
END_C_DECLS
#endif /*TK_ASSET_LOADER_H*/

View File

@ -0,0 +1,168 @@
/**
* File: asset_loader_default.c
* Author: AWTK Develop Team
* Brief: asset_loader_default
*
* Copyright (c) 2019 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-02-26 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/fs.h"
#include "base/asset_loader_default.h"
#define MMAP_ASSET_MIN_SIZE 4 * 1024
static asset_info_t* load_asset_with_mmap(uint16_t type, uint16_t subtype, const char* path,
const char* name) {
#ifdef LOAD_ASSET_WITH_MMAP
if (file_get_size(path) >= MMAP_ASSET_MIN_SIZE) {
asset_info_t* info = asset_info_create(type, subtype, name, 0);
return_value_if_fail(info != NULL, NULL);
info->map = mmap_create(path, FALSE, FALSE);
if (info->map != NULL) {
info->data = info->map->data;
info->size = info->map->size;
return info;
} else {
asset_info_destroy(info);
}
}
#endif /*LOAD_ASSET_WITH_MMAP*/
return NULL;
}
#ifdef WITH_SDL
#include <SDL.h>
static asset_info_t* load_asset(uint16_t type, uint16_t subtype, const char* path,
const char* name) {
asset_info_t* info = load_asset_with_mmap(type, subtype, path, name);
if (info == NULL) {
SDL_RWops* rwops = SDL_RWFromFile(path, "r");
if (rwops != NULL) {
int32_t size = rwops->size(rwops);
info = asset_info_create(type, subtype, name, size);
if (info != NULL) {
rwops->read(rwops, info->data, size, 1);
}
rwops->close(rwops);
}
}
return info;
}
static bool_t asset_exist(const char* path) {
SDL_RWops* rwops = SDL_RWFromFile(path, "r");
if (rwops != NULL) {
rwops->close(rwops);
return TRUE;
} else {
return FALSE;
}
}
#else
static bool_t asset_exist(const char* path) {
return file_exist(path);
}
#ifdef USE_TTF_FONT_DATA_CACHE
// 20220107 增加TTF字库Cache机制
#ifndef TTF_CACHABLE_FILE_SIZE
#define TTF_CACHABLE_FILE_SIZE 0x100000
#endif
#endif
static asset_info_t* load_asset(uint16_t type, uint16_t subtype, const char* path,
const char* name) {
asset_info_t* info = NULL;
if (file_exist(path)) {
info = load_asset_with_mmap(type, subtype, path, name);
if (info == NULL) {
#ifdef USE_TTF_FONT_DATA_CACHE
// 20220107 增加TTF字库Cache机制
int32_t size = file_get_size(path);
// 字体大小限制1MB以内
if (size >= TTF_CACHABLE_FILE_SIZE && type == ASSET_TYPE_FONT && subtype == ASSET_TYPE_FONT_TTF)
{
// TTF字库
int32_t size = strlen(path) + 1 + 8;
info = asset_info_create(type, subtype, name, size);
return_value_if_fail(info != NULL, NULL);
*(unsigned int *)(info->data + 0) = 0xAA5555AA;
*(unsigned int *)(info->data + 4) = 0x454C4946; // FILE
// 保存font的全路径名
memcpy(info->data + 8, path, size - (1+8));
}
else
{
// 其他资源数据 (将数据全部加载到内存)
int32_t size = file_get_size(path);
info = asset_info_create(type, subtype, name, size);
return_value_if_fail(info != NULL, NULL);
ENSURE(file_read_part(path, info->data, size, 0) == size);
}
#else
int32_t size = file_get_size(path);
info = asset_info_create(type, subtype, name, size);
return_value_if_fail(info != NULL, NULL);
ENSURE(file_read_part(path, info->data, size, 0) == size);
#endif
}
}
return info;
}
#endif /*WITH_SDL*/
static asset_info_t* asset_loader_default_load(asset_loader_t* loader, uint16_t type,
uint16_t subtype, const char* path,
const char* name) {
return load_asset(type, subtype, path, name);
}
static bool_t asset_loader_default_exist(asset_loader_t* loader, const char* path) {
return asset_exist(path);
}
static ret_t asset_loader_default_destroy(asset_loader_t* loader) {
TKMEM_FREE(loader);
return RET_OK;
}
static const asset_loader_vtable_t s_asset_loader_default_vtable = {
.load = asset_loader_default_load,
.exist = asset_loader_default_exist,
.destroy = asset_loader_default_destroy};
asset_loader_t* asset_loader_default_create(void) {
asset_loader_t* loader = TKMEM_ZALLOC(asset_loader_t);
return_value_if_fail(loader != NULL, NULL);
loader->vt = &s_asset_loader_default_vtable;
return loader;
}
asset_loader_t* asset_loader_create(void) {
return asset_loader_default_create();
}

View File

@ -0,0 +1,39 @@
/**
* File: asset_loader_default.h
* Author: AWTK Develop Team
* Brief: asset_loader_default
*
* Copyright (c) 2019 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-02-26 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_ASSET_LOADER_DEFAULT_H
#define TK_ASSET_LOADER_DEFAULT_H
#include "base/asset_loader.h"
BEGIN_C_DECLS
/**
* @method asset_loader_default_create
* 创建缺省的资源加载器。
*
* @return {asset_loader_t*} 返回loader对象。
*/
asset_loader_t* asset_loader_default_create(void);
END_C_DECLS
#endif /*TK_ASSET_LOADER_DEFAULT_H*/

View File

@ -0,0 +1,198 @@
/**
* File: asset_loader_zip.c
* Author: AWTK Develop Team
* Brief: asset_loader_zip
*
* Copyright (c) 2019 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-02-26 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#ifdef WITH_ASSET_LOADER_ZIP
#include "miniz/miniz.h"
#include "miniz/miniz_zip.h"
#include "base/asset_loader_zip.h"
#include "base/assets_manager.h"
typedef struct _asset_loader_zip_t {
asset_loader_t asset_loader;
void* data;
uint32_t size;
mz_zip_archive archive;
data_reader_t* reader;
bool_t own_the_reader;
} asset_loader_zip_t;
#ifdef WITH_SDL
#include <SDL.h>
static void* load_asset(const char* filename, uint32_t* data_size) {
SDL_RWops* rwops = SDL_RWFromFile(filename, "r");
if (rwops != NULL) {
uint32_t size = rwops->size(rwops);
void* data = TKMEM_ALLOC(size + 1);
if (data != NULL) {
memset(data, 0x00, size + 1);
rwops->read(rwops, data, size, 1);
}
rwops->close(rwops);
*data_size = size;
return data;
} else {
return NULL;
}
}
#else
extern void* file_read(const char* name, uint32_t* size);
static void* load_asset(const char* filename, uint32_t* data_size) {
return file_read(filename, data_size);
}
#endif /*WITH_SDL*/
static void* miniz_awtk_alloc_func(void* opaque, size_t items, size_t size) {
(void)opaque, (void)items, (void)size;
return TKMEM_ALLOC(items * size);
}
static void miniz_awtk_free_func(void* opaque, void* address) {
(void)opaque, (void)address;
TKMEM_FREE(address);
}
static void* miniz_awtk_realloc_func(void* opaque, void* address, size_t items, size_t size) {
(void)opaque, (void)address, (void)items, (void)size;
return TKMEM_REALLOC(address, items * size);
}
static bool_t asset_loader_zip_exist(asset_loader_t* loader, const char* path) {
asset_loader_zip_t* zip = (asset_loader_zip_t*)loader;
const char* res_root = assets_manager_get_res_root(assets_manager());
uint32_t res_root_len = res_root == NULL ? 0 : strlen(res_root);
const char* p = path + ((res_root_len == 0) ? 0 : (res_root_len + 1));
int file_index = mz_zip_reader_locate_file(&(zip->archive), p, NULL, 0);
return file_index >= 0;
}
static asset_info_t* asset_loader_zip_load(asset_loader_t* loader, uint16_t type, uint16_t subtype,
const char* path, const char* name) {
size_t size = 0;
void* data = NULL;
int file_index = 0;
asset_info_t* info = NULL;
asset_loader_zip_t* zip = (asset_loader_zip_t*)loader;
const char* res_root = assets_manager_get_res_root(assets_manager());
uint32_t res_root_len = res_root == NULL ? 0 : strlen(res_root);
const char* p = path + ((res_root_len == 0) ? 0 : (res_root_len));
while (*p == '/' || *p == TK_PATH_SEP) p++;
file_index = mz_zip_reader_locate_file(&(zip->archive), p, NULL, 0);
if (file_index < 0) {
return NULL;
}
data = mz_zip_reader_extract_to_heap(&(zip->archive), file_index, &size, 0);
return_value_if_fail(data != NULL, NULL);
info = asset_info_create(type, subtype, name, size);
if (info != NULL) {
memcpy(info->data, data, size);
}
TKMEM_FREE(data);
return info;
}
static ret_t asset_loader_zip_destroy(asset_loader_t* loader) {
asset_loader_zip_t* zip = (asset_loader_zip_t*)loader;
mz_zip_end(&(zip->archive));
if (zip->data != NULL) {
TKMEM_FREE(zip->data);
}
if (zip->own_the_reader && zip->reader != NULL) {
data_reader_destroy(zip->reader);
}
TKMEM_FREE(loader);
return RET_OK;
}
static const asset_loader_vtable_t s_asset_loader_zip_vtable = {
.load = asset_loader_zip_load,
.exist = asset_loader_zip_exist,
.destroy = asset_loader_zip_destroy};
static asset_loader_zip_t* asset_loader_zip_create_default(void) {
asset_loader_zip_t* zip = TKMEM_ZALLOC(asset_loader_zip_t);
return_value_if_fail(zip != NULL, NULL);
zip->archive.m_pFree = miniz_awtk_free_func;
zip->archive.m_pAlloc = miniz_awtk_alloc_func;
zip->archive.m_pRealloc = miniz_awtk_realloc_func;
zip->asset_loader.vt = &s_asset_loader_zip_vtable;
return zip;
}
asset_loader_t* asset_loader_zip_create(const char* zipfile) {
asset_loader_zip_t* zip = asset_loader_zip_create_default();
return_value_if_fail(zip != NULL, NULL);
zip->data = load_asset(zipfile, &(zip->size));
if (zip->data == NULL) {
TKMEM_FREE(zip);
}
if (!mz_zip_reader_init_mem(&(zip->archive), zip->data, zip->size, 0)) {
TKMEM_FREE(zip);
}
return (asset_loader_t*)zip;
}
static size_t asset_loader_zip_read(void* pOpaque, mz_uint64 offset, void* buff, size_t n) {
asset_loader_zip_t* zip = (asset_loader_zip_t*)pOpaque;
return data_reader_read(zip->reader, offset, buff, n);
}
asset_loader_t* asset_loader_zip_create_with_reader(data_reader_t* reader, bool_t own_the_reader) {
asset_loader_zip_t* zip = NULL;
uint32_t size = data_reader_get_size(reader);
return_value_if_fail(reader != NULL, NULL);
zip = asset_loader_zip_create_default();
return_value_if_fail(zip != NULL, NULL);
zip->reader = reader;
zip->own_the_reader = own_the_reader;
zip->archive.m_pIO_opaque = zip;
zip->archive.m_pRead = asset_loader_zip_read;
if (!mz_zip_reader_init(&(zip->archive), size, 0)) {
TKMEM_FREE(zip);
}
return (asset_loader_t*)zip;
}
#endif /*WITH_ASSET_LOADER_ZIP*/

View File

@ -0,0 +1,51 @@
/**
* File: asset_loader_zip.h
* Author: AWTK Develop Team
* Brief: asset_loader_zip
*
* Copyright (c) 2019 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-02-26 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_ASSET_LOADER_ZIP_H
#define TK_ASSET_LOADER_ZIP_H
#include "tkc/data_reader.h"
#include "base/asset_loader.h"
BEGIN_C_DECLS
/**
* @method asset_loader_zip_create
* 创建zip资源加载器。
* @param {const char*} zipfile zip文件名。
*
* @return {asset_loader_t*} 返回loader对象。
*/
asset_loader_t* asset_loader_zip_create(const char* zipfile);
/**
* @method asset_loader_zip_create_with_reader
* 创建zip资源加载器。
* @param {data_reader_t*} reader reader对象。
* @param {bool_t} own_the_reader 如果希望销毁loader时销毁reader请设置为TRUE。
*
* @return {asset_loader_t*} 返回loader对象。
*/
asset_loader_t* asset_loader_zip_create_with_reader(data_reader_t* reader, bool_t own_the_reader);
END_C_DECLS
#endif /*TK_ASSET_LOADER_ZIP_H*/

View File

@ -0,0 +1,859 @@
/**
* File: assets_manager.h
* Author: AWTK Develop Team
* Brief: asset manager
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-03-07 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/path.h"
#include "tkc/utils.h"
#include "base/enums.h"
#include "base/locale_info.h"
#include "base/system_info.h"
#include "base/assets_manager.h"
#include "base/vgcanvas_asset_manager.inc"
#define RAW_DIR "raw"
#define ASSETS_DIR "assets"
#define THEME_DEFAULT "default"
static int asset_cache_cmp_type(const void* a, const void* b) {
const asset_info_t* aa = (const asset_info_t*)a;
const asset_info_t* bb = (const asset_info_t*)b;
if (aa->is_in_rom) {
return -1;
}
return aa->type - bb->type;
}
static int asset_cache_cmp_type_and_name(const void* a, const void* b) {
const asset_info_t* aa = (const asset_info_t*)a;
const asset_info_t* bb = (const asset_info_t*)b;
if (aa->is_in_rom) {
return -1;
}
if (aa->type == bb->type) {
return tk_str_cmp(aa->name, bb->name);
} else {
return aa->type - bb->type;
}
}
static assets_manager_t* s_assets_manager = NULL;
static ret_t assets_manager_dispatch_event(assets_manager_t* am, int32_t etype,
asset_info_t* info) {
assets_event_t e;
return emitter_dispatch(EMITTER(am),
assets_event_init(&e, am, etype, (asset_type_t)(info->type), info));
}
static locale_info_t* assets_manager_get_locale_info(assets_manager_t* am) {
return_value_if_fail(am != NULL, NULL);
return am->locale_info != NULL ? am->locale_info : locale_info();
}
#if defined(AWTK_WEB)
static asset_info_t* assets_manager_load_impl(assets_manager_t* am, asset_type_t type,
uint16_t subtype, const char* name) {
asset_info_t* info = TKMEM_ALLOC(sizeof(asset_info_t));
return_value_if_fail(info != NULL, NULL);
memset(info, 0x00, sizeof(asset_info_t));
info->size = 0;
info->type = type;
info->subtype = subtype;
info->refcount = 1;
info->is_in_rom = FALSE;
strncpy(info->name, name, TK_NAME_LEN);
return info;
}
#else
#include "tkc/fs.h"
static system_info_t* assets_manager_get_system_info(assets_manager_t* am) {
return_value_if_fail(am != NULL, NULL);
return am->system_info != NULL ? am->system_info : system_info();
}
const char* assets_manager_get_res_root(assets_manager_t* am) {
return_value_if_fail(am != NULL, NULL);
if (am->res_root != NULL) {
return am->res_root;
} else {
return assets_manager_get_system_info(am)->app_root;
}
}
static ret_t build_asset_dir_one_theme(char* path, uint32_t size, const char* res_root,
const char* theme, const char* ratio, const char* subpath) {
if (ratio != NULL) {
return_value_if_fail(path_build(path, size, res_root, ASSETS_DIR, theme, RAW_DIR, subpath,
ratio, NULL) == RET_OK,
RET_FAIL);
} else {
return_value_if_fail(
path_build(path, size, res_root, ASSETS_DIR, theme, RAW_DIR, subpath, NULL) == RET_OK,
RET_FAIL);
}
return RET_OK;
}
static ret_t build_asset_filename_one_theme(char* path, uint32_t size, const char* res_root,
const char* theme, const char* ratio,
const char* subpath, const char* name,
const char* extname) {
const char* pextname = NULL;
char sep[2] = {TK_PATH_SEP, 0};
return_value_if_fail(
build_asset_dir_one_theme(path, size, res_root, theme, ratio, subpath) == RET_OK, RET_FAIL);
return_value_if_fail(tk_str_append(path, size, sep) == RET_OK, RET_FAIL);
return_value_if_fail(tk_str_append(path, size, name) == RET_OK, RET_FAIL);
pextname = strrchr(name, '.');
if (pextname == NULL || !tk_str_eq(pextname, extname)) {
return_value_if_fail(tk_str_append(path, size, extname) == RET_OK, RET_FAIL);
}
return RET_OK;
}
static ret_t build_asset_filename_custom(assets_manager_t* am, char* path, uint32_t size,
const char* theme, const char* ratio, const char* subpath,
const char* name, const char* extname) {
if (am->custom_build_asset_dir != NULL) {
char sep[2] = {TK_PATH_SEP, 0};
return_value_if_fail(am->custom_build_asset_dir(am->custom_build_asset_dir_ctx, path, size,
theme, ratio, subpath) == RET_OK,
RET_FAIL);
return_value_if_fail(tk_str_append(path, size, sep) == RET_OK, RET_FAIL);
return_value_if_fail(tk_str_append(path, size, name) == RET_OK, RET_FAIL);
return_value_if_fail(tk_str_append(path, size, extname) == RET_OK, RET_FAIL);
return RET_OK;
}
return RET_FAIL;
}
static ret_t build_asset_filename_default(char* path, uint32_t size, const char* res_root,
const char* theme, const char* ratio, const char* subpath,
const char* name, const char* extname) {
return_value_if_fail(build_asset_filename_one_theme(path, size, res_root, theme, ratio, subpath,
name, extname) == RET_OK,
RET_FAIL);
return RET_OK;
}
static const char* device_pixel_ratio_to_str(float_t dpr) {
const char* ratio = "x1";
if (dpr >= 3) {
ratio = "x3";
} else if (dpr >= 2) {
ratio = "x2";
}
return ratio;
}
ret_t assets_manager_build_asset_filename(assets_manager_t* am, char* path, uint32_t size,
const char* theme, bool_t ratio_sensitive,
const char* subpath, const char* name,
const char* extname) {
const char* ratio = NULL;
const char* res_root = assets_manager_get_res_root(am);
system_info_t* sysinfo = assets_manager_get_system_info(am);
return_value_if_fail(sysinfo != NULL, RET_BAD_PARAMS);
ratio = device_pixel_ratio_to_str(sysinfo->device_pixel_ratio);
if (ratio_sensitive) {
if (build_asset_filename_custom(am, path, size, theme, ratio, subpath, name, extname) ==
RET_OK) {
return RET_OK;
}
return build_asset_filename_default(path, size, res_root, theme, ratio, subpath, name, extname);
} else {
if (build_asset_filename_custom(am, path, size, theme, NULL, subpath, name, extname) ==
RET_OK) {
return RET_OK;
}
return build_asset_filename_default(path, size, res_root, theme, NULL, subpath, name, extname);
}
}
static asset_info_t* try_load_image(assets_manager_t* am, const char* theme, const char* name,
asset_image_type_t subtype, bool_t ratio) {
char path[MAX_PATH + 1];
const char* extname = NULL;
const char* subpath = ratio ? "images" : "images/xx";
switch (subtype) {
case ASSET_TYPE_IMAGE_JPG: {
extname = ".jpg";
break;
}
case ASSET_TYPE_IMAGE_PNG: {
extname = ".png";
break;
}
case ASSET_TYPE_IMAGE_GIF: {
extname = ".gif";
break;
}
case ASSET_TYPE_IMAGE_BMP: {
extname = ".bmp";
break;
}
case ASSET_TYPE_IMAGE_BSVG: {
extname = ".bsvg";
subpath = "images/svg";
break;
}
case ASSET_TYPE_IMAGE_OTHER: {
extname = "";
break;
}
default: {
return NULL;
}
}
return_value_if_fail(assets_manager_build_asset_filename(am, path, MAX_PATH, theme, ratio,
subpath, name, extname) == RET_OK,
NULL);
if (subtype == ASSET_TYPE_IMAGE_JPG && !asset_loader_exist(am->loader, path)) {
uint32_t len = strlen(path);
return_value_if_fail(MAX_PATH > len, NULL);
memcpy(path + len - 4, ".jpeg", 5);
path[len + 1] = '\0';
}
return asset_loader_load(am->loader, ASSET_TYPE_IMAGE, subtype, path, name);
}
static asset_info_t* try_load_assets(assets_manager_t* am, const char* theme, const char* name,
const char* extname, asset_type_t type, uint16_t subtype) {
char path[MAX_PATH + 1];
const char* subpath = NULL;
switch (type) {
case ASSET_TYPE_FONT: {
subpath = "fonts";
break;
}
case ASSET_TYPE_SCRIPT: {
subpath = "scripts";
break;
}
case ASSET_TYPE_FLOW: {
subpath = "flows";
break;
}
case ASSET_TYPE_STYLE: {
subpath = "styles";
break;
}
case ASSET_TYPE_STRINGS: {
subpath = "strings";
break;
}
case ASSET_TYPE_UI: {
subpath = "ui";
break;
}
case ASSET_TYPE_XML: {
subpath = "xml";
break;
}
case ASSET_TYPE_DATA: {
subpath = "data";
break;
}
default: {
return NULL;
}
}
return_value_if_fail(assets_manager_build_asset_filename(am, path, MAX_PATH, theme, FALSE,
subpath, name, extname) == RET_OK,
NULL);
return asset_loader_load(am->loader, type, subtype, path, name);
}
static uint16_t subtype_from_extname(const char* extname) {
uint16_t subtype = 0;
return_value_if_fail(extname != NULL, 0);
if (tk_str_ieq(extname, ".gif")) {
subtype = ASSET_TYPE_IMAGE_GIF;
} else if (tk_str_ieq(extname, ".png")) {
subtype = ASSET_TYPE_IMAGE_PNG;
} else if (tk_str_ieq(extname, ".bmp")) {
subtype = ASSET_TYPE_IMAGE_BMP;
} else if (tk_str_ieq(extname, ".bsvg")) {
subtype = ASSET_TYPE_IMAGE_BSVG;
} else if (tk_str_ieq(extname, ".jpg")) {
subtype = ASSET_TYPE_IMAGE_JPG;
} else if (tk_str_ieq(extname, ".jpeg")) {
subtype = ASSET_TYPE_IMAGE_JPG;
} else if (tk_str_ieq(extname, ".ttf")) {
subtype = ASSET_TYPE_FONT_TTF;
} else {
log_debug("not supported %s\n", extname);
}
return subtype;
}
static asset_info_t* load_asset_from_file(uint16_t type, uint16_t subtype, const char* path,
const char* name) {
asset_info_t* info = NULL;
if (file_exist(path)) {
int32_t size = file_get_size(path);
info = asset_info_create(type, subtype, name, size);
return_value_if_fail(info != NULL, NULL);
ENSURE(file_read_part(path, info->data, size, 0) == size);
}
return info;
}
asset_info_t* assets_manager_load_file(assets_manager_t* am, asset_type_t type, const char* path) {
if (file_exist(path)) {
const char* extname = strrchr(path, '.');
uint16_t subtype = subtype_from_extname(extname);
return load_asset_from_file(type, subtype, path, path);
}
return NULL;
}
bool_t assets_manager_is_save_assets_list(asset_type_t type) {
/* 资源列表暂时只保存字体资源,风格资源和字符串资源 */
if (type == ASSET_TYPE_FONT || type == ASSET_TYPE_STYLE || type == ASSET_TYPE_STRINGS) {
return TRUE;
}
return FALSE;
}
static asset_info_t* assets_manager_load_asset(assets_manager_t* am, asset_type_t type,
uint16_t subtype, const char* theme,
const char* name) {
asset_info_t* info = NULL;
switch (type) {
case ASSET_TYPE_FONT: {
if (subtype == 0 || (subtype != 0 && subtype == ASSET_TYPE_FONT_TTF)) {
if ((info = try_load_assets(am, theme, name, ".ttf", type, ASSET_TYPE_FONT_TTF)) != NULL) {
break;
}
}
if (subtype == 0 || (subtype != 0 && subtype == ASSET_TYPE_FONT_BMP)) {
if ((info = try_load_assets(am, theme, name, ".bin", type, ASSET_TYPE_FONT_BMP)) != NULL) {
break;
}
}
break;
}
case ASSET_TYPE_SCRIPT: {
if (subtype == 0 || (subtype != 0 && subtype == ASSET_TYPE_SCRIPT_JS)) {
if ((info = try_load_assets(am, theme, name, ".js", type, ASSET_TYPE_SCRIPT_JS)) != NULL) {
break;
}
}
if (subtype == 0 || (subtype != 0 && subtype == ASSET_TYPE_SCRIPT_LUA)) {
if ((info = try_load_assets(am, theme, name, ".lua", type, ASSET_TYPE_SCRIPT_LUA)) !=
NULL) {
break;
}
}
break;
}
case ASSET_TYPE_FLOW: {
if ((info = try_load_assets(am, theme, name, ".json", type, ASSET_TYPE_SCRIPT_JS)) != NULL) {
break;
}
break;
}
case ASSET_TYPE_STYLE: {
if ((info = try_load_assets(am, theme, name, ".bin", type, ASSET_TYPE_STYLE)) != NULL) {
break;
}
break;
}
case ASSET_TYPE_STRINGS: {
if ((info = try_load_assets(am, theme, name, ".bin", type, ASSET_TYPE_STRINGS)) != NULL) {
break;
}
break;
}
case ASSET_TYPE_IMAGE: {
if (subtype != 0) {
asset_image_type_t sub_type = (asset_image_type_t)subtype;
if ((info = try_load_image(am, theme, name, sub_type, sub_type != ASSET_TYPE_IMAGE_BSVG)) !=
NULL) {
break;
}
}
if ((info = try_load_image(am, theme, name, ASSET_TYPE_IMAGE_PNG, TRUE)) != NULL) {
break;
}
if ((info = try_load_image(am, theme, name, ASSET_TYPE_IMAGE_BMP, TRUE)) != NULL) {
break;
}
if ((info = try_load_image(am, theme, name, ASSET_TYPE_IMAGE_JPG, TRUE)) != NULL) {
break;
}
if ((info = try_load_image(am, theme, name, ASSET_TYPE_IMAGE_GIF, TRUE)) != NULL) {
break;
}
/*try ratio-insensitive image.*/
if ((info = try_load_image(am, theme, name, ASSET_TYPE_IMAGE_PNG, FALSE)) != NULL) {
break;
}
if ((info = try_load_image(am, theme, name, ASSET_TYPE_IMAGE_BMP, FALSE)) != NULL) {
break;
}
if ((info = try_load_image(am, theme, name, ASSET_TYPE_IMAGE_JPG, FALSE)) != NULL) {
break;
}
if ((info = try_load_image(am, theme, name, ASSET_TYPE_IMAGE_GIF, FALSE)) != NULL) {
break;
}
if ((info = try_load_image(am, theme, name, ASSET_TYPE_IMAGE_BSVG, FALSE)) != NULL) {
break;
}
if ((info = try_load_image(am, theme, name, ASSET_TYPE_IMAGE_OTHER, TRUE)) != NULL) {
break;
}
if ((info = try_load_image(am, theme, name, ASSET_TYPE_IMAGE_OTHER, FALSE)) != NULL) {
break;
}
break;
}
case ASSET_TYPE_UI: {
if ((info = try_load_assets(am, theme, name, ".bin", type, ASSET_TYPE_UI)) != NULL) {
break;
}
break;
}
case ASSET_TYPE_XML: {
if ((info = try_load_assets(am, theme, name, ".xml", type, ASSET_TYPE_XML)) != NULL) {
break;
}
break;
}
case ASSET_TYPE_DATA: {
if ((info = try_load_assets(am, theme, name, "", type, ASSET_TYPE_DATA)) != NULL) {
break;
}
break;
}
default:
break;
}
if (info != NULL && assets_manager_is_save_assets_list(type)) {
assets_manager_add(am, info);
}
return info;
}
static asset_info_t* assets_manager_load_impl(assets_manager_t* am, asset_type_t type,
uint16_t subtype, const char* name) {
asset_info_t* info = NULL;
if (am->loader == NULL) {
return NULL;
}
if (strncmp(name, STR_SCHEMA_FILE, strlen(STR_SCHEMA_FILE)) == 0) {
info = assets_manager_load_file(am, type, name + strlen(STR_SCHEMA_FILE));
/* 保持和 assets_manager_load_asset 函数内部中的调用 assets_manager_add 的逻辑一样 */
if (info != NULL && assets_manager_is_save_assets_list(type)) {
assets_manager_add(am, info);
}
return info;
} else {
const char* theme = am->theme ? am->theme : THEME_DEFAULT;
info = assets_manager_load_asset(am, type, subtype, theme, name);
if (info == NULL && !tk_str_eq(theme, THEME_DEFAULT)) {
info = assets_manager_load_asset(am, type, subtype, THEME_DEFAULT, name);
}
return info;
}
}
#endif
assets_manager_t* assets_manager(void) {
return s_assets_manager;
}
asset_info_t* assets_manager_load(assets_manager_t* am, asset_type_t type, const char* name) {
return assets_manager_load_ex(am, type, 0, name);
}
asset_info_t* assets_manager_load_ex(assets_manager_t* am, asset_type_t type, uint16_t subtype,
const char* name) {
asset_info_t* info = NULL;
return_value_if_fail(am != NULL && name != NULL, NULL);
if (am->custom_load_asset != NULL) {
return am->custom_load_asset(am->custom_load_asset_ctx, type, subtype, name);
}
info = assets_manager_load_impl(am, type, subtype, name);
if (info != NULL) {
assets_manager_dispatch_event(am, EVT_ASSET_MANAGER_LOAD_ASSET, info);
}
return info;
}
ret_t assets_manager_set(assets_manager_t* am) {
s_assets_manager = am;
return RET_OK;
}
assets_manager_t* assets_manager_create(uint32_t init_nr) {
assets_manager_t* am = TKMEM_ZALLOC(assets_manager_t);
emitter_init(EMITTER(am));
return assets_manager_init(am, init_nr);
}
assets_manager_t* assets_manager_init(assets_manager_t* am, uint32_t init_nr) {
return_value_if_fail(am != NULL, NULL);
darray_init(&(am->assets), init_nr, (tk_destroy_t)asset_info_unref,
(tk_compare_t)asset_cache_cmp_type);
assets_manager_set_theme(am, THEME_DEFAULT);
#ifdef WITH_ASSET_LOADER
am->loader = asset_loader_create();
#endif /*WITH_ASSET_LOADER*/
return am;
}
ret_t assets_manager_set_res_root(assets_manager_t* am, const char* res_root) {
return_value_if_fail(am != NULL, RET_BAD_PARAMS);
am->res_root = tk_str_copy(am->res_root, res_root);
return RET_OK;
}
ret_t assets_manager_clear_all(assets_manager_t* am) {
return_value_if_fail(am != NULL, RET_BAD_PARAMS);
assets_manager_clear_cache(am, ASSET_TYPE_UI);
assets_manager_clear_cache(am, ASSET_TYPE_STYLE);
assets_manager_clear_cache(am, ASSET_TYPE_FONT);
return darray_clear(&(am->assets));
}
ret_t assets_manager_set_theme(assets_manager_t* am, const char* theme) {
return_value_if_fail(am != NULL, RET_BAD_PARAMS);
am->theme = tk_str_copy(am->theme, theme);
assets_manager_clear_cache(am, ASSET_TYPE_UI);
assets_manager_clear_cache(am, ASSET_TYPE_STYLE);
assets_manager_clear_cache(am, ASSET_TYPE_FONT);
return RET_OK;
}
ret_t assets_manager_set_system_info(assets_manager_t* am, system_info_t* system_info) {
return_value_if_fail(am != NULL, RET_BAD_PARAMS);
if (system_info != NULL) {
am->system_info = system_info;
}
return RET_OK;
}
ret_t assets_manager_set_locale_info(assets_manager_t* am, locale_info_t* locale_info) {
return_value_if_fail(am != NULL, RET_BAD_PARAMS);
if (locale_info != NULL) {
am->locale_info = locale_info;
}
return RET_OK;
}
ret_t assets_manager_add(assets_manager_t* am, const void* info) {
const asset_info_t* r = (const asset_info_t*)info;
return_value_if_fail(am != NULL && info != NULL, RET_BAD_PARAMS);
#if LOAD_ASSET_WITH_MMAP
if (r->is_in_rom) {
// 不支持添加非 mmap 资源的外部资源。
assert(!" mmap model not supported assets this is in rom ");
}
#endif
asset_info_ref((asset_info_t*)r);
return darray_push(&(am->assets), (void*)r);
}
ret_t assets_manager_add_data(assets_manager_t* am, const char* name, uint16_t type,
uint16_t subtype, uint8_t* buff, uint32_t size) {
asset_info_t* info = asset_info_create(type, subtype, name, size);
return_value_if_fail(info != NULL, RET_FAIL);
memcpy(info->data, buff, size);
return_value_if_fail(assets_manager_add(am, info) == RET_OK, RET_FAIL);
return asset_info_unref(info);
}
const asset_info_t* assets_manager_find_in_cache(assets_manager_t* am, asset_type_t type,
uint16_t subtype, const char* name) {
uint32_t i = 0;
const char* assets_name = NULL;
const asset_info_t* iter = NULL;
const asset_info_t** all = NULL;
return_value_if_fail(am != NULL && name != NULL, NULL);
assets_name = asset_info_get_formatted_name(name);
all = (const asset_info_t**)(am->assets.elms);
for (i = 0; i < am->assets.size; i++) {
iter = all[i];
if (type == iter->type && strcmp(assets_name, iter->name) == 0 &&
(subtype == 0 || (subtype != 0 && subtype == iter->subtype))) {
return iter;
}
}
return NULL;
}
static const asset_info_t* assets_manager_ref_impl(assets_manager_t* am, asset_type_t type,
uint16_t subtype, const char* name) {
const asset_info_t* info = assets_manager_find_in_cache(am, type, subtype, name);
if (info == NULL) {
info = assets_manager_load_ex(am, type, subtype, name);
} else {
asset_info_ref((asset_info_t*)info);
}
return info;
}
const asset_info_t* assets_manager_ref(assets_manager_t* am, asset_type_t type, const char* name) {
return assets_manager_ref_ex(am, type, 0, name);
}
const asset_info_t* assets_manager_ref_ex(assets_manager_t* am, asset_type_t type, uint16_t subtype,
const char* name) {
const asset_info_t* info = NULL;
locale_info_t* locale_info = assets_manager_get_locale_info(am);
return_value_if_fail(am != NULL && name != NULL, NULL);
if (*name == '\0') {
return NULL;
}
if (strstr(name, TK_LOCALE_MAGIC) != NULL) {
char locale[TK_NAME_LEN + 1];
char real_name[TK_NAME_LEN + 1];
const char* language = locale_info->language;
const char* country = locale_info->country;
if (strlen(language) > 0 && strlen(country) > 0) {
tk_snprintf(locale, sizeof(locale) - 1, "%s_%s", language, country);
tk_replace_locale(name, real_name, locale);
info = assets_manager_ref_impl(am, type, subtype, real_name);
if (info != NULL) {
return info;
}
}
tk_replace_locale(name, real_name, language);
info = assets_manager_ref_impl(am, type, subtype, real_name);
if (info != NULL) {
return info;
}
tk_replace_locale(name, real_name, "");
info = assets_manager_ref_impl(am, type, subtype, real_name);
if (info != NULL) {
return info;
}
} else {
info = assets_manager_ref_impl(am, type, subtype, name);
}
if (info == NULL && type == ASSET_TYPE_UI) {
const key_type_value_t* kv = asset_type_find_by_value(type);
const char* asset_type = kv != NULL ? kv->name : "unknown";
log_warn("!!!Asset [name=%s type=%s] not exist!!!\n", name, asset_type);
(void)asset_type;
}
return info;
}
ret_t assets_manager_unref(assets_manager_t* am, const asset_info_t* info) {
if (am == NULL || info == NULL) {
/*asset manager was destroied*/
return RET_OK;
}
if (info->refcount == 1) {
assets_manager_dispatch_event(am, EVT_ASSET_MANAGER_UNLOAD_ASSET, (asset_info_t*)info);
}
return asset_info_unref((asset_info_t*)info);
}
ret_t assets_manager_clear_cache_ex(assets_manager_t* am, asset_type_t type, const char* name) {
int32_t size = 0;
asset_info_t info;
ret_t ret = RET_OK;
return_value_if_fail(am != NULL && name != NULL, RET_BAD_PARAMS);
memset(&info, 0x00, sizeof(info));
if (assets_manager_find_in_cache(am, type, 0, name) == NULL) {
return RET_NOT_FOUND;
}
info.type = type;
tk_strncpy_s(info.name, sizeof(info.name), name, strlen(name));
size = am->assets.size;
ret = darray_remove_all(&(am->assets), asset_cache_cmp_type_and_name, &info);
if (am->assets.size < size) {
assets_manager_dispatch_event(am, EVT_ASSET_MANAGER_UNLOAD_ASSET, &info);
}
return ret;
}
ret_t assets_manager_clear_cache(assets_manager_t* am, asset_type_t type) {
int32_t size = 0;
asset_info_t info;
ret_t ret = RET_OK;
memset(&info, 0x00, sizeof(info));
info.type = type;
return_value_if_fail(am != NULL, RET_BAD_PARAMS);
size = am->assets.size;
ret = darray_remove_all(&(am->assets), NULL, &info);
if (am->assets.size < size) {
assets_manager_dispatch_event(am, EVT_ASSET_MANAGER_CLEAR_CACHE, &info);
}
return ret;
}
ret_t assets_manager_preload(assets_manager_t* am, asset_type_t type, const char* name) {
asset_info_t* info = assets_manager_load(am, type, name);
return_value_if_fail(info != NULL, RET_FAIL);
assets_manager_unref(am, info);
return RET_OK;
}
ret_t assets_manager_deinit(assets_manager_t* am) {
return_value_if_fail(am != NULL, RET_BAD_PARAMS);
asset_loader_destroy(am->loader);
darray_deinit(&(am->assets));
return RET_OK;
}
ret_t assets_manager_set_custom_build_asset_dir(
assets_manager_t* am, assets_manager_build_asset_dir_t custom_build_asset_dir, void* ctx) {
return_value_if_fail(am != NULL, RET_BAD_PARAMS);
am->custom_build_asset_dir_ctx = ctx;
am->custom_build_asset_dir = custom_build_asset_dir;
return RET_OK;
}
ret_t assets_manager_set_custom_load_asset(assets_manager_t* am,
assets_manager_load_asset_t custom_load_asset,
void* ctx) {
return_value_if_fail(am != NULL, RET_BAD_PARAMS);
am->custom_load_asset_ctx = ctx;
am->custom_load_asset = custom_load_asset;
return RET_OK;
}
ret_t assets_manager_destroy(assets_manager_t* am) {
return_value_if_fail(am != NULL, RET_BAD_PARAMS);
emitter_deinit(EMITTER(am));
assets_manager_deinit(am);
if (am == assets_manager()) {
assets_manager_set(NULL);
}
TKMEM_FREE(am->res_root);
TKMEM_FREE(am->theme);
TKMEM_FREE(am);
return RET_OK;
}
ret_t assets_manager_set_loader(assets_manager_t* am, asset_loader_t* loader) {
return_value_if_fail(am != NULL && loader != NULL, RET_BAD_PARAMS);
if (am->loader != NULL) {
asset_loader_destroy(am->loader);
}
am->loader = loader;
return RET_OK;
}

View File

@ -0,0 +1,398 @@
/**
* File: assets_manager.h
* Author: AWTK Develop Team
* Brief: asset manager
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-03-07 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_ASSETS_MANAGER_H
#define TK_ASSETS_MANAGER_H
#include "tkc/darray.h"
#include "tkc/emitter.h"
#include "tkc/asset_info.h"
#include "base/types_def.h"
#include "base/asset_loader.h"
BEGIN_C_DECLS
typedef ret_t (*assets_manager_build_asset_dir_t)(void* ctx, char* path, uint32_t size,
const char* theme, const char* ratio,
const char* subpath);
typedef asset_info_t* (*assets_manager_load_asset_t)(assets_manager_t* am, asset_type_t type,
uint16_t subtype, const char* name);
/**
* @class assets_manager_t
* @parent emitter_t
* @annotation ["scriptable"]
* 资源管理器。
* 这里的资源管理器并非Windows下的文件浏览器而是负责对各种资源比如字体、窗体样式、图片、界面数据、字符串和其它数据的进行集中管理的组件。引入资源管理器的目的有以下几个
*
* * 让上层不需要了解存储的方式。
* 在没有文件系统时或者内存紧缺时,把资源转成常量数组直接编译到代码中。在有文件系统而且内存充足时,资源放在文件系统中。在有网络时,资源也可以存放在服务器上(暂未实现)。资源管理器为上层提供统一的接口,让上层而不用关心底层的存储方式。
*
* * 让上层不需要了解资源的具体格式。
* 比如一个名为earth的图片没有文件系统或内存紧缺图片直接用位图数据格式存在ROM中而有文件系统时则用PNG格式存放在文件系统中。资源管理器让上层不需要关心图片的格式访问时指定图片的名称即可(不用指定扩展名)。
*
* * 让上层不需要了解屏幕的密度。
* 不同的屏幕密度下需要加载不同的图片比如MacPro的Retina屏就需要用双倍解析度的图片否则就出现界面模糊。AWTK以后会支持PC软件和手机软件的开发所以资源管理器需要为此提供支持让上层不需关心屏幕的密度。
*
* * 对资源进行内存缓存。
* 不同类型的资源使用方式是不一样的比如字体和窗体样式加载之后会一直使用UI文件在生成界面之后就暂时不需要了PNG文件解码之后就只需要保留解码的位图数据即可。资源管理器配合图片管理器等其它组件实现资源的自动缓存。
*
*当从文件系统加载资源时,目录结构要求如下:
*
* ```
* assets/{theme}/raw/
* fonts 字体
* images 图片
* x1 普通密度屏幕的图片。
* x2 2倍密度屏幕的图片。
* x3 3倍密度屏幕的图片。
* xx 密度无关的图片。
* strings 需要翻译的字符串。
* styles 窗体样式数据。
* ui UI描述数据。
* ```
*
*/
struct _assets_manager_t {
emitter_t emitter;
darray_t assets;
/*private*/
char* theme;
char* res_root;
locale_info_t* locale_info;
system_info_t* system_info;
void* custom_load_asset_ctx;
assets_manager_load_asset_t custom_load_asset;
void* custom_build_asset_dir_ctx;
assets_manager_build_asset_dir_t custom_build_asset_dir;
asset_loader_t* loader;
};
/**
* @method assets_manager
* 获取缺省资源管理器。
* @alias assets_manager_instance
* @annotation ["constructor", "scriptable"]
*
* @return {assets_manager_t*} 返回asset manager对象。
*/
assets_manager_t* assets_manager(void);
/**
* @method assets_manager_set
* 设置缺省资源管理器。
* @param {assets_manager_t*} am asset manager对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_set(assets_manager_t* am);
/**
* @method assets_manager_create
* 创建资源管理器。
* @annotation ["constructor"]
* @param {uint32_t} init_nr 预先分配资源的个数。
*
* @return {assets_manager_t*} 返回asset manager对象。
*/
assets_manager_t* assets_manager_create(uint32_t init_nr);
/**
* @method assets_manager_init
* 初始化资源管理器。
* @annotation ["constructor"]
* @param {assets_manager_t*} am asset manager对象。
* @param {uint32_t} init_nr 预先分配资源的个数。
*
* @return {assets_manager_t*} 返回asset manager对象。
*/
assets_manager_t* assets_manager_init(assets_manager_t* am, uint32_t init_nr);
/**
* @method assets_manager_get_res_root
* 获取资源所在的目录(其下目录结构请参考demos)。
* @param {assets_manager_t*} am asset manager对象。
*
* @return {const char*} 返回资源所在的目录。
*/
const char* assets_manager_get_res_root(assets_manager_t* am);
/**
* @method assets_manager_set_res_root
* 设置资源所在的目录(其下目录结构请参考demos)。
* @param {assets_manager_t*} am asset manager对象。
* @param {const char*} res_root 资源所在的目录。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_set_res_root(assets_manager_t* am, const char* res_root);
/**
* @method assets_manager_set_theme
* 设置当前的主题。
* @annotation ["scriptable"]
* @param {assets_manager_t*} am asset manager对象。
* @param {const char*} theme 主题名称。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_set_theme(assets_manager_t* am, const char* theme);
/**
* @method assets_manager_set_system_info
* 设置system_info对象。
* @param {assets_manager_t*} am asset manager对象。
* @param {system_info_t*} system_info system_info对象。。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_set_system_info(assets_manager_t* am, system_info_t* system_info);
/**
* @method assets_manager_set_locale_info
* 设置locale_info对象。
* @param {assets_manager_t*} am asset manager对象。
* @param {locale_info_t*} locale_info locale_info对象。。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_set_locale_info(assets_manager_t* am, locale_info_t* locale_info);
/**
* @method assets_manager_add
* 向资源管理器中增加一个资源。
* @param {assets_manager_t*} am asset manager对象。
* @param {asset_info_t} info 待增加的资源。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_add(assets_manager_t* am, const void* info);
/**
* @method assets_manager_add_data
* 向资源管理器中增加一个资源data。
* @param {assets_manager_t*} am asset manager对象。
* @param {const char*} name 待增加的资源的名字。
* @param {uint16_t} type 待增加的资源的主类型枚举。
* @param {uint16_t} subtype 待增加的资源的子类型枚举。
* @param {uint8_t*} buff 待增加的资源的data数据。
* @param {uint32_t} size 待增加的资源的data数据长度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_add_data(assets_manager_t* am, const char* name, uint16_t type,
uint16_t subtype, uint8_t* buff, uint32_t size);
/**
* @method assets_manager_ref
* 在资源管理器的缓存中查找指定的资源并引用它,如果缓存中不存在,尝试加载该资源。
* @annotation ["scriptable"]
* @param {assets_manager_t*} am asset manager对象。
* @param {asset_type_t} type 资源的类型。
* @param {char*} name 资源的名称。
*
* @return {asset_info_t*} 返回资源。
*/
const asset_info_t* assets_manager_ref(assets_manager_t* am, asset_type_t type, const char* name);
/**
* @method assets_manager_ref_ex
* 在资源管理器的缓存中查找指定的资源并引用它,如果缓存中不存在,尝试加载该资源。
* @annotation ["scriptable"]
* @param {assets_manager_t*} am asset manager对象。
* @param {asset_type_t} type 资源的类型。
* @param {uint16_t} subtype 资源的子类型。
* @param {char*} name 资源的名称。
*
* @return {asset_info_t*} 返回资源。
*/
const asset_info_t* assets_manager_ref_ex(assets_manager_t* am, asset_type_t type, uint16_t subtype,
const char* name);
/**
* @method assets_manager_unref
* 释放指定的资源。
* @annotation ["scriptable"]
* @param {assets_manager_t*} am asset manager对象。
* @param {asset_info_t*} info 资源。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_unref(assets_manager_t* am, const asset_info_t* info);
/**
* @method assets_manager_find_in_cache
* 在资源管理器的缓存中查找指定的资源(不引用)。
* @param {assets_manager_t*} am asset manager对象。
* @param {asset_type_t} type 资源的类型。
* @param {uint16_t} subtype 资源的子类型。
* @param {char*} name 资源的名称。
*
* @return {asset_info_t*} 返回资源。
*/
const asset_info_t* assets_manager_find_in_cache(assets_manager_t* am, asset_type_t type,
uint16_t subtype, const char* name);
/**
* @method assets_manager_load
* 从文件系统中加载指定的资源并缓存到内存中。在定义了宏WITH\_FS\_RES时才生效。
* @param {assets_manager_t*} am asset manager对象。
* @param {asset_type_t} type 资源的类型。
* @param {const char*} name 资源的名称。
*
* @return {asset_info_t*} 返回资源。
*/
asset_info_t* assets_manager_load(assets_manager_t* am, asset_type_t type, const char* name);
/**
* @method assets_manager_load_ex
* 从文件系统中加载指定的资源并缓存到内存中。在定义了宏WITH\_FS\_RES时才生效。
* @param {assets_manager_t*} am asset manager对象。
* @param {asset_type_t} type 资源的类型。
* @param {asset_type_t} type 资源的子类型。
* @param {char*} name 资源的名称。
*
* @return {asset_info_t*} 返回资源。
*/
asset_info_t* assets_manager_load_ex(assets_manager_t* am, asset_type_t type, uint16_t subtype,
const char* name);
/**
* @method assets_manager_preload
* 从文件系统中加载指定的资源并缓存到内存中。在定义了宏WITH\_FS\_RES时才生效。
* @param {assets_manager_t*} am asset manager对象。
* @param {asset_type_t} type 资源的类型。
* @param {char*} name 资源的名称。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_preload(assets_manager_t* am, asset_type_t type, const char* name);
/**
* @method assets_manager_set_loader
* 设置loader。
* @param {assets_manager_t*} am asset manager对象。
* @param {asset_loader_t*} loader 加载器(由assets manager销毁)。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_set_loader(assets_manager_t* am, asset_loader_t* loader);
/**
* @method assets_manager_set_custom_build_asset_dir
* 设置一个函数,该函数用于生成资源路径。
*
* > 有时我们需要优先加载用户自定义的资源,加载失败才加载系统缺省的,可用设置一个函数去实现这类功能。
*
* @param {assets_manager_t*} am asset manager对象。
* @param {assets_manager_build_asset_dir_t} custom_build_asset_dir 回调函数。
* @param {void*} ctx 回调函数的上下文。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_set_custom_build_asset_dir(
assets_manager_t* am, assets_manager_build_asset_dir_t custom_build_asset_dir, void* ctx);
/**
* @method assets_manager_set_custom_load_asset
* 设置一个函数,该函数用于实现自定义加载资源。
*
* > 如果不支持文件系统开发者可以设置一个加载资源的回调函数从flash或其它地方读取资源。
*
* @param {assets_manager_t*} am asset manager对象。
* @param {assets_manager_load_asset_t} custom_load_asset 回调函数。
* @param {void*} ctx 回调函数的上下文。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_set_custom_load_asset(assets_manager_t* am,
assets_manager_load_asset_t custom_load_asset,
void* ctx);
/**
* @method assets_manager_clear_cache
* 清除指定类型的缓存。
* @param {assets_manager_t*} am asset manager对象。
* @param {asset_type_t} type 资源的类型。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_clear_cache(assets_manager_t* am, asset_type_t type);
/**
* @method assets_manager_clear_cache_ex
* 清除指定类型和名称的缓存。
* @param {assets_manager_t*} am asset manager对象。
* @param {asset_type_t} type 资源的类型。
* @param {const char*} name 资源的名称。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_clear_cache_ex(assets_manager_t* am, asset_type_t type, const char* name);
/**
* @method assets_manager_clear_all
* 清除全部缓存的资源。
* @param {assets_manager_t*} am asset manager对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_clear_all(assets_manager_t* am);
/**
* @method assets_manager_deinit
* @param {assets_manager_t*} am asset manager对象。
* 释放全部资源。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_deinit(assets_manager_t* am);
/**
* @method assets_manager_destroy
* @param {assets_manager_t*} am asset manager对象。
* 释放全部资源并销毁asset manager对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t assets_manager_destroy(assets_manager_t* am);
/**
* @method assets_manager_load_file
* @param {assets_manager_t*} am asset manager对象。
* @param {asset_type_t} type 资源类型。
* @param {const char*} path 目录。
* 获取path里的资源。
*
* @return {asset_info_t*} 返回asset_info_t。
*/
asset_info_t* assets_manager_load_file(assets_manager_t* am, asset_type_t type, const char* path);
/*public for test*/
bool_t assets_manager_is_save_assets_list(asset_type_t type);
END_C_DECLS
#endif /*TK_ASSETS_MANAGER_H*/

View File

@ -0,0 +1,276 @@

/**
* File: awtk_config.h
* Author: AWTK Develop Team
* Brief: config
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-09-12 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef AWTK_CONFIG_H
#define AWTK_CONFIG_H
/**
* 嵌入式系统有自己的main函数时请定义本宏。
*
* #define USE_GUI_MAIN 1
*/
/**
* 如果需要支持预先解码的位图字体请定义本宏。一般只在RAM极小时才启用本宏。
* #define WITH_BITMAP_FONT 1
*/
/**
* 如果支持png/jpeg图片请定义本宏
*
* #define WITH_STB_IMAGE 1
*/
/**
* 如果用stb支持Truetype字体请定义本宏
*
* #define WITH_STB_FONT 1
*/
/**
* 如果用freetype支持Truetype字体请定义本宏。
*
* #define WITH_FT_FONT 1
*/
/**
* 如果支持从文件系统加载资源,请定义本宏
*
* #define WITH_FS_RES 1
*/
/**
* 如果代码在flash中而资源在文件系统请定义本宏指明资源所在的路径。
*
* #define APP_RES_ROOT "0://awtk/"
*
*/
/**
* 如果定义本宏使用标准的UNICODE换行算法除非资源极为有限请定义本宏。
*
* #define WITH_UNICODE_BREAK 1
*/
/**
* 如果定义本宏将图片解码成BGRA8888格式否则解码成RGBA8888的格式。
* 当硬件的2D加速需要BGRA格式时请启用本宏。
*
* #define WITH_BITMAP_BGRA 1
*/
/**
* 如果定义本宏将不透明的PNG图片解码成BGR565格式建议定义。
* 另外和LCD的格式保存一致可以大幅度提高性能。
* 如果没有定义 WITH_BITMAP_BGR565 和 WITH_BITMAP_RGB565 宏默认解析为32位色
*
* #define WITH_BITMAP_BGR565 1
*/
/**
* 如果定义本宏将不透明的PNG图片解码成RGB565格式建议定义。
* 另外和LCD的格式保存一致可以大幅度提高性能。
* 如果没有定义 WITH_BITMAP_BGR565 和 WITH_BITMAP_RGB565 宏默认解析为32位色
*
* #define WITH_BITMAP_RGB565 1
*/
/**
* 如果不需输入法,请定义本宏
*
* #define WITH_NULL_IM 1
*/
/**
* 如果有标准的malloc/free/calloc等函数请定义本宏
*
* #define HAS_STD_MALLOC 1
*/
/**
* 如果有标准的fopen/fclose等函数请定义本宏
*
* #define HAS_STDIO 1
*/
/**
* 如果有标准的pthread等函数请定义本宏
*
* #define HAS_PTHREAD 1
*/
/**
* 如果有优化版本的memcpy函数请定义本宏
*
* #define HAS_FAST_MEMCPY 1
*/
/**
* 如果出现wcsxxx之类的函数没有定义时请定义该宏
*
* #define WITH_WCSXXX 1
*/
/**
* 如果启用STM32 G2D硬件加速请定义本宏
*
* #define WITH_STM32_G2D 1
*/
/**
* 如果启用NXP PXP硬件加速请定义本宏
*
* #define WITH_PXP_G2D 1
*/
/**
* 在没有GPU时如果启用agge作为nanovg的后端(较agg作为后端图形质量稍差),请定义本宏。
*
* #define WITH_NANOVG_AGGE 1
*/
/**
* 在没有GPU时如果启用agg作为nanovg的后端(较agge作为后端图形质量好),请定义本宏。
* 注意agg是以GPL协议开源。
*
* #define WITH_NANOVG_AGG 1
*/
/**
* 如果启用鼠标指针,请定义本宏
*
* #define ENABLE_CURSOR 1
*/
/**
* 对于低端平台,如果不使用控件动画,请定义本宏。
*
* #define WITHOUT_WIDGET_ANIMATORS 1
*/
/**
* 对于低端平台,如果不使用窗口动画,请定义本宏。
*
* #define WITHOUT_WINDOW_ANIMATORS 1
*/
/**
* 对于低端平台,如果不使用对话框高亮策略,请定义本宏。
*
* #define WITHOUT_DIALOG_HIGHLIGHTER 1
*/
/**
* 对于低端平台,如果不使用扩展控件,请定义本宏。
*
* #define WITHOUT_EXT_WIDGETS 1
*/
/**
* 对于低端平台如果内存不足以提供完整的FrameBuffer请定义本宏启用局部FrameBuffer可大幅度提高渲染性能。(单位是像素个数)
*
* #define FRAGMENT_FRAME_BUFFER_SIZE 32 * 1024
*/
/**
* 启用widget类型检查请定义本宏(除非编译器不支持,否则请定义它)。
*
* #define WITH_WIDGET_TYPE_CHECK 1
*/
/**
* 启用输入法,但不想启用联想功能,请定义本宏。
*
* #define WITHOUT_SUGGEST_WORDS 1
*/
/**
* 如果需要从zip文件中加载资源请定义本宏。
*
* #define WITH_ASSET_LOADER_ZIP 1
*/
/**
* 对于只有512K flash的平台而且LCD格式是BGR565。如果希望进一步优化空间去掉多余的bitmap格式支持代码。请定义本宏。
* 其它LCD格式可以自行修改src/blend/soft_g2d.c 保留需要的格式即可。
*
* #define LCD_BGR565_LITE 1
*/
/**
* 如果希望支持文字双向排版算法(如阿拉伯语言),请定义本宏。
*
* #define WITH_TEXT_BIDI 1
*
*/
/**
* 开启自定义的离线 canvas如果板子使用特殊的画布的话需要定义该宏来定义特殊离线 canvas 函数
*
* #define WITH_CANVAS_OFFLINE_CUSTION 1
*/
/**
* 开启透明色背景的刷新机制,一般使用在多图层的透明背景使用
*
* #define WITH_LCD_CLEAR_ALPHA 1
*/
/**
* 如果支持多块不连续的内存块,请定义内存块的数目。
*
* #define TK_MAX_MEM_BLOCK_NR 4
*/
/**
* 用于控制窗口动画是否使用缓存。开启后可以降低内存需求(减少2倍framebuffer大小的内存),如果内存紧缺,在下面情况可以开启:
* 1. 界面简单
* 2. CPU速度快
*
* 如果绘制速度慢,而且内存紧缺,建议关闭窗口动画。
*
* 限制条件:
* 1.不支持缩放窗口动画。
* 2.不支持对话框高亮策略。
*
* #define WITHOUT_WINDOW_ANIMATOR_CACHE 1
*/
/**
* 如果需要配置文件或者使用data_reader/data_writer请定义本宏。
*
* #define WITH_DATA_READER_WRITER 1
*/
/**
* 对于低端平台,如果不使用 fscript 模块,请定义本宏。
*
* #define WITHOUT_FSCRIPT 1
*/
/**
* 对于极简键盘(3keys/5keys),如果希望激活状态呈现不同的外观效果,请定义本宏。
*
* #define WITH_STATE_ACTIVATED 1
*/
#endif /*AWTK_CONFIG_H*/

View File

@ -0,0 +1,145 @@
/**
* File: bidi.h
* Author: AWTK Develop Team
* Brief: Unicode Bidirectional Algorithm.
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-07-09 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "base/bidi.h"
#ifdef WITH_TEXT_BIDI
#include "tkc/mem.h"
#include "fribidi/fribidi.h"
static bidi_type_t bidi_type_from(int fribidi_type) {
switch (fribidi_type) {
case FRIBIDI_PAR_RTL:
return BIDI_TYPE_RTL;
case FRIBIDI_PAR_LTR:
return BIDI_TYPE_LTR;
case FRIBIDI_TYPE_RLO:
return BIDI_TYPE_RLO;
case FRIBIDI_TYPE_LRO:
return BIDI_TYPE_LRO;
case FRIBIDI_PAR_WRTL:
return BIDI_TYPE_WRTL;
case FRIBIDI_PAR_WLTR:
return BIDI_TYPE_WLTR;
default:
return BIDI_TYPE_AUTO;
}
}
static FriBidiParType bidi_type_to(bidi_type_t type) {
switch (type) {
case BIDI_TYPE_RTL:
return (FriBidiParType)FRIBIDI_PAR_RTL;
case BIDI_TYPE_LTR:
return (FriBidiParType)FRIBIDI_PAR_LTR;
case BIDI_TYPE_RLO:
return (FriBidiParType)FRIBIDI_TYPE_RLO;
case BIDI_TYPE_LRO:
return (FriBidiParType)FRIBIDI_TYPE_LRO;
case BIDI_TYPE_WRTL:
return (FriBidiParType)FRIBIDI_PAR_WRTL;
case BIDI_TYPE_WLTR:
return (FriBidiParType)FRIBIDI_PAR_WLTR;
default:
return (FriBidiParType)FRIBIDI_PAR_ON;
}
}
bidi_type_t bidi_type_from_name(const char* name) {
if (name == NULL || *name == '\0') {
return BIDI_TYPE_AUTO;
}
if (tk_str_eq(name, "rtl")) {
return BIDI_TYPE_RTL;
} else if (tk_str_eq(name, "ltr")) {
return BIDI_TYPE_LTR;
} else if (tk_str_eq(name, "rlo")) {
return BIDI_TYPE_RLO;
} else if (tk_str_eq(name, "lro")) {
return BIDI_TYPE_LRO;
} else if (tk_str_eq(name, "wrtl")) {
return BIDI_TYPE_WRTL;
} else if (tk_str_eq(name, "wltr")) {
return BIDI_TYPE_WLTR;
} else {
return BIDI_TYPE_AUTO;
}
}
bidi_t* bidi_init(bidi_t* bidi, bool_t alloc_l2v, bool_t alloc_v2l, bidi_type_t type) {
return_value_if_fail(bidi != NULL, NULL);
memset(bidi, 0x00, sizeof(*bidi));
bidi->request_type = type;
bidi->alloc_l2v = alloc_l2v;
bidi->alloc_v2l = alloc_v2l;
return bidi;
}
ret_t bidi_log2vis(bidi_t* bidi, const wchar_t* str, uint32_t size) {
FriBidiLevel level = 0;
FriBidiParType type = FRIBIDI_PAR_ON;
return_value_if_fail(bidi != NULL && str != NULL && size > 0, RET_BAD_PARAMS);
if (ARRAY_SIZE(bidi->vis_str_static) > size) {
bidi->vis_str_size = size;
bidi->vis_str = bidi->vis_str_static;
} else {
bidi->vis_str_size = size;
assert(bidi->vis_str == NULL);
bidi->vis_str = TKMEM_ALLOC((size + 1) * sizeof(wchar_t));
}
return_value_if_fail(bidi->vis_str != NULL, RET_FAIL);
return_value_if_fail(sizeof(wchar_t) == sizeof(FriBidiChar), RET_BAD_PARAMS);
return_value_if_fail(sizeof(uint32_t) == sizeof(FriBidiStrIndex), RET_BAD_PARAMS);
if (bidi->alloc_l2v) {
bidi->positions_L_to_V = TKMEM_ZALLOCN(int32_t, size);
}
if (bidi->alloc_v2l) {
bidi->positions_L_to_V = TKMEM_ZALLOCN(int32_t, size);
}
type = bidi_type_to(bidi->request_type);
level = fribidi_log2vis(str, size, &type, bidi->vis_str, bidi->positions_L_to_V,
bidi->positions_V_to_L, NULL);
bidi->resolved_type = bidi_type_from(type);
(void)level;
return RET_OK;
}
ret_t bidi_deinit(bidi_t* bidi) {
return_value_if_fail(bidi != NULL, RET_BAD_PARAMS);
TKMEM_FREE(bidi->positions_L_to_V);
TKMEM_FREE(bidi->positions_V_to_L);
if (bidi->vis_str != bidi->vis_str_static) {
TKMEM_FREE(bidi->vis_str);
}
memset(bidi, 0x00, sizeof(*bidi));
return RET_OK;
}
#endif /*WITH_TEXT_BIDI*/

View File

@ -0,0 +1,195 @@
/**
* File: bidi.h
* Author: AWTK Develop Team
* Brief: Unicode Bidirectional Algorithm.
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-07-09 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_BIDI_H
#define TK_BIDI_H
#include "base/types_def.h"
BEGIN_C_DECLS
/**
* @enum bidi_type_t
* @annotation ["scriptable"]
* @prefix BIDI_TYPE_
* bidi 类型常量定义。
*/
typedef enum _bidi_type_t {
/**
* @const BIDI_TYPE_AUTO
* 自动检查。
*/
BIDI_TYPE_AUTO = 0,
/**
* @const BIDI_TYPE_LTR
* Left-To-Right letter。
*/
BIDI_TYPE_LTR,
/**
* @const BIDI_TYPE_RTL
* Right-To-Left letter。
*/
BIDI_TYPE_RTL,
/**
* @const BIDI_TYPE_LRO
* Left-To-Right letter Override。
*/
BIDI_TYPE_LRO,
/**
* @const BIDI_TYPE_RLO
* Right-To-Left letter Override。
*/
BIDI_TYPE_RLO,
/**
* @const BIDI_TYPE_WLTR
* Weak Left To Right paragraph。
*/
BIDI_TYPE_WLTR,
/**
* @const BIDI_TYPE_WRTL
* Weak Right To Left paragraph。
*/
BIDI_TYPE_WRTL
} bidi_type_t;
/**
* @class bidi_t
* Unicode Bidirectional Algorithm.
*
*/
typedef struct _bidi_t {
/**
* @property {wchar_t*} vis_strx
* @annotation ["readable"]
* 用于显示的字符串(存放log2vis的结果)。
*/
wchar_t* vis_str;
/**
* @property {uint32_t} vis_str_size
* @annotation ["readable"]
* 用于显示的字符串长度(存放log2vis的结果)。
*/
uint32_t vis_str_size;
/**
* @property {bidi_type_t} request_type
* @annotation ["readable"]
* 请求的类型。
*/
bidi_type_t request_type;
/**
* @property {bidi_type_t} resolved_type
* @annotation ["readable"]
* 实际的类型。
*/
bidi_type_t resolved_type;
/**
* @property {int32_t*} positions_L_to_V
* @annotation ["readable"]
* logical位置与visual位置的映射。
*/
int32_t* positions_L_to_V;
/**
* @property {int32_t*} positions_V_to_L
* @annotation ["readable"]
* visual位置与logical位置的映射。
*/
int32_t* positions_V_to_L;
/*private*/
bool_t alloc_l2v;
bool_t alloc_v2l;
wchar_t vis_str_static[128];
} bidi_t;
#ifdef WITH_TEXT_BIDI
/**
* @method bidi_init
* 初始化bidi对象。
* @annotation ["deconstructor"]
* @param {bidi_t*} bidi bidi对象。
* @param {bool_t} alloc_l2v 是否为positions_L_to_V分配空间。
* @param {bool_t} alloc_v2l 是否为positions_V_to_L分配空间。
* @param {bidi_type_t} type 类型。
*
* @return {bidi_t*} 返回bidi对象。
*/
bidi_t* bidi_init(bidi_t* bidi, bool_t alloc_l2v, bool_t alloc_v2l, bidi_type_t type);
/**
* @method bidi_type_from_name
* 将bidi类型的名称转换成类型。
* @annotation ["static"]
* @param {const char*} name 类型名称(取值rtl,ltr,auto,wrtl,wltr,lro,rlo)。
*
* @return {bidi_t*} 返回bidi对象。
*/
bidi_type_t bidi_type_from_name(const char* name);
/**
* @method bidi_log2vis
* 将字符串转成用于显示的字符串输出结果放在bidi->vis_str中。
*
* @param {bidi_t*} bidi bidi对象。
* @param {const wchar_t*} str 字符串。
* @param {uint32_t} size 字符串的长度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t bidi_log2vis(bidi_t* bidi, const wchar_t* str, uint32_t size);
/**
* @method bidi_deinit
* 释放bidi对象相关资源。
* @annotation ["deconstructor"]
* @param {bidi_t*} bidi bidi对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t bidi_deinit(bidi_t* bidi);
#else
static inline bidi_t* bidi_init(bidi_t* bidi, bool_t alloc_l2v, bool_t alloc_v2l,
bidi_type_t type) {
return_value_if_fail(bidi != NULL, NULL);
memset(bidi, 0x00, sizeof(bidi_t));
return bidi;
}
static inline ret_t bidi_log2vis(bidi_t* bidi, const wchar_t* str, uint32_t size) {
return_value_if_fail(bidi != NULL, RET_BAD_PARAMS);
bidi->vis_str = (wchar_t*)str;
bidi->vis_str_size = size;
return RET_OK;
}
static inline bidi_type_t bidi_type_from_name(const char* name) {
return BIDI_TYPE_AUTO;
}
static inline ret_t bidi_deinit(bidi_t* bidi) {
return_value_if_fail(bidi != NULL, RET_BAD_PARAMS);
return RET_OK;
}
#endif /*WITH_TEXT_BIDI*/
END_C_DECLS
#endif /*TK_BIDI_H*/

View File

@ -0,0 +1,924 @@
/**
* File: bitmap.c
* Author: AWTK Develop Team
* Brief: bitmap interface
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/pixel.h"
#include "base/bitmap.h"
#include "base/graphic_buffer.h"
bitmap_t* bitmap_create(void) {
bitmap_t* bitmap = TKMEM_ZALLOC(bitmap_t);
return_value_if_fail(bitmap != NULL, NULL);
bitmap->should_free_handle = TRUE;
return bitmap;
}
ret_t bitmap_destroy_with_self(bitmap_t* bitmap) {
return_value_if_fail(bitmap != NULL, RET_BAD_PARAMS);
bitmap->should_free_handle = TRUE;
return bitmap_destroy(bitmap);
}
ret_t bitmap_destroy(bitmap_t* bitmap) {
return_value_if_fail(bitmap != NULL, RET_BAD_PARAMS);
if (bitmap->specific_destroy != NULL) {
bitmap->specific_destroy(bitmap);
}
if (bitmap->destroy != NULL) {
bitmap->destroy(bitmap);
}
if (bitmap->should_free_data) {
if (bitmap->buffer != NULL) {
graphic_buffer_destroy(bitmap->buffer);
}
if (bitmap->gif_delays != NULL) {
TKMEM_FREE(bitmap->gif_delays);
bitmap->gif_delays = NULL;
}
TKMEM_FREE(bitmap->data_free_ptr);
}
if (bitmap->should_free_handle) {
memset(bitmap, 0x00, sizeof(bitmap_t));
TKMEM_FREE(bitmap);
} else {
memset(bitmap, 0x00, sizeof(bitmap_t));
}
return RET_OK;
}
#include "base/pixel_pack_unpack.h"
uint32_t bitmap_get_bpp_of_format(bitmap_format_t format) {
switch (format) {
case BITMAP_FMT_RGBA8888:
case BITMAP_FMT_ABGR8888:
case BITMAP_FMT_BGRA8888:
case BITMAP_FMT_ARGB8888:
return 4;
case BITMAP_FMT_RGB565:
case BITMAP_FMT_BGR565:
return 2;
case BITMAP_FMT_RGB888:
case BITMAP_FMT_BGR888:
return 3;
case BITMAP_FMT_GRAY:
return 1;
default:
break;
}
return 0;
}
uint32_t bitmap_get_bpp(bitmap_t* bitmap) {
return_value_if_fail(bitmap != NULL, 0);
return bitmap_get_bpp_of_format((bitmap_format_t)(bitmap->format));
}
ret_t bitmap_alloc_data(bitmap_t* bitmap) {
return_value_if_fail(bitmap != NULL && bitmap->w > 0 && bitmap->h > 0, RET_BAD_PARAMS);
return GRAPHIC_BUFFER_CREATE_FOR_BITMAP(bitmap);
}
#ifdef AWTK_WEB
#include <emscripten.h>
static ret_t bitmap_web_destroy(bitmap_t* bitmap) {
int32_t id = tk_pointer_to_int(bitmap->specific);
EM_ASM_INT({ return VGCanvas.destroyMutableImage($0); }, id);
return RET_OK;
}
#endif /*AWTK_WEB*/
bitmap_t* bitmap_create_ex(uint32_t w, uint32_t h, uint32_t line_length, bitmap_format_t format) {
bitmap_t* bitmap = TKMEM_ZALLOC(bitmap_t);
uint32_t bpp = bitmap_get_bpp_of_format(format);
return_value_if_fail(bitmap != NULL, NULL);
bitmap->w = w;
bitmap->h = h;
bitmap->format = format;
bitmap->should_free_handle = TRUE;
if (bpp < 4) {
bitmap->flags = BITMAP_FLAG_OPAQUE;
}
bitmap_set_line_length(bitmap, line_length);
bitmap_alloc_data(bitmap);
if (bitmap->buffer == NULL) {
TKMEM_FREE(bitmap);
bitmap = NULL;
} else {
#ifdef AWTK_WEB
uint8_t* data = bitmap_lock_buffer_for_write(bitmap);
return_value_if_fail(format == BITMAP_FMT_RGBA8888, NULL);
int32_t id = EM_ASM_INT({ return VGCanvas.createMutableImage($0, $1, $2, $3, $4); }, data, w, h,
line_length, format);
bitmap->specific = tk_pointer_from_int(id);
bitmap->specific_destroy = bitmap_web_destroy;
bitmap_unlock_buffer(bitmap);
#endif /*AWTK_WEB*/
}
return bitmap;
}
ret_t bitmap_get_pixel(bitmap_t* bitmap, uint32_t x, uint32_t y, rgba_t* rgba) {
ret_t ret = RET_OK;
const uint8_t* data = NULL;
uint8_t* bitmap_data = NULL;
uint32_t bpp = bitmap_get_bpp(bitmap);
return_value_if_fail(bitmap != NULL && bitmap->buffer != NULL && rgba != NULL, RET_BAD_PARAMS);
return_value_if_fail(x < bitmap->w && y < bitmap->h, RET_BAD_PARAMS);
bitmap_data = bitmap_lock_buffer_for_read(bitmap);
data = bitmap_data + bitmap_get_line_length(bitmap) * y + x * bpp;
switch (bitmap->format) {
case BITMAP_FMT_MONO: {
bool_t pixel = bitmap_mono_get_pixel(bitmap_data, bitmap->w, bitmap->h, x, y);
color_t c = color_from_mono(pixel);
*rgba = c.rgba;
break;
}
case BITMAP_FMT_RGBA8888: {
pixel_rgba8888_t* p = (pixel_rgba8888_t*)data;
rgba_t t = pixel_rgba8888_to_rgba((*p));
*rgba = t;
break;
}
case BITMAP_FMT_ABGR8888: {
pixel_abgr8888_t* p = (pixel_abgr8888_t*)data;
rgba_t t = pixel_abgr8888_to_rgba((*p));
*rgba = t;
break;
}
case BITMAP_FMT_BGRA8888: {
pixel_bgra8888_t* p = (pixel_bgra8888_t*)data;
rgba_t t = pixel_bgra8888_to_rgba((*p));
*rgba = t;
break;
}
case BITMAP_FMT_ARGB8888: {
pixel_argb8888_t* p = (pixel_argb8888_t*)data;
rgba_t t = pixel_argb8888_to_rgba((*p));
*rgba = t;
break;
}
case BITMAP_FMT_RGB565: {
pixel_rgb565_t* p = (pixel_rgb565_t*)data;
rgba_t t = pixel_rgb565_to_rgba((*p));
*rgba = t;
break;
}
case BITMAP_FMT_BGR565: {
pixel_bgr565_t* p = (pixel_bgr565_t*)data;
rgba_t t = pixel_bgr565_to_rgba((*p));
*rgba = t;
break;
}
case BITMAP_FMT_RGB888: {
pixel_rgb888_t* p = (pixel_rgb888_t*)data;
rgba_t t = pixel_rgb888_to_rgba((*p));
*rgba = t;
break;
}
case BITMAP_FMT_BGR888: {
pixel_bgr888_t* p = (pixel_bgr888_t*)data;
rgba_t t = pixel_bgr888_to_rgba((*p));
*rgba = t;
break;
}
default: {
ret = RET_NOT_IMPL;
break;
}
}
bitmap_unlock_buffer(bitmap);
return ret;
}
ret_t bitmap_init_rgba8888(bitmap_t* bitmap, uint32_t w, uint32_t h, const uint8_t* data,
uint32_t comp) {
uint32_t i = 0;
uint32_t j = 0;
uint8_t* bdata = bitmap_lock_buffer_for_write(bitmap);
return_value_if_fail(bdata != NULL && data != NULL, RET_BAD_PARAMS);
if (comp == 4) {
for (i = 0; i < h; i++) {
memcpy((uint8_t*)(bdata) + i * bitmap->line_length, data + i * w * 4, w * 4);
}
} else {
const uint8_t* s = data;
uint8_t* d = (uint8_t*)(bdata);
for (j = 0; j < h; j++) {
d = (uint8_t*)(bdata) + j * bitmap->line_length;
for (i = 0; i < w; i++) {
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = 0xff;
}
}
}
bitmap_unlock_buffer(bitmap);
return RET_OK;
}
ret_t bitmap_init_bgra8888(bitmap_t* bitmap, uint32_t w, uint32_t h, const uint8_t* data,
uint32_t comp) {
uint32_t i = 0;
uint32_t j = 0;
const uint8_t* s = data;
uint8_t* bdata = bitmap_lock_buffer_for_write(bitmap);
uint8_t* d = bdata;
/*bgra=rgba*/
for (j = 0; j < h; j++) {
d = (uint8_t*)(bdata) + j * bitmap->line_length;
for (i = 0; i < w; i++) {
d[0] = s[2];
d[1] = s[1];
d[2] = s[0];
d[3] = (comp == 3) ? 0xff : s[3];
d += 4;
s += comp;
}
}
bitmap_unlock_buffer(bitmap);
return RET_OK;
}
ret_t bitmap_init_rgb565(bitmap_t* bitmap, uint32_t w, uint32_t h, const uint8_t* data,
uint32_t comp) {
uint32_t i = 0;
uint32_t j = 0;
const uint8_t* s = data;
uint8_t* bdata = bitmap_lock_buffer_for_write(bitmap);
uint16_t* d = (uint16_t*)(bdata);
for (j = 0; j < h; j++) {
d = (uint16_t*)((bdata) + j * bitmap->line_length);
for (i = 0; i < w; i++) {
uint8_t r = s[0];
uint8_t g = s[1];
uint8_t b = s[2];
*d++ = rgb_to_rgb565(r, g, b);
s += comp;
}
}
bitmap_unlock_buffer(bitmap);
return RET_OK;
}
ret_t bitmap_init_bgr565(bitmap_t* bitmap, uint32_t w, uint32_t h, const uint8_t* data,
uint32_t comp) {
uint32_t i = 0;
uint32_t j = 0;
const uint8_t* s = data;
uint8_t* bdata = bitmap_lock_buffer_for_write(bitmap);
uint16_t* d = (uint16_t*)(bdata);
for (j = 0; j < h; j++) {
d = (uint16_t*)((bdata) + j * bitmap->line_length);
for (i = 0; i < w; i++) {
uint8_t r = s[0];
uint8_t g = s[1];
uint8_t b = s[2];
*d++ = rgb_to_bgr565(r, g, b);
s += comp;
}
}
bitmap_unlock_buffer(bitmap);
return RET_OK;
}
ret_t bitmap_init_mono(bitmap_t* bitmap, uint32_t w, uint32_t h, const uint8_t* data,
uint32_t comp) {
uint32_t i = 0;
uint32_t j = 0;
bool_t pixel = FALSE;
const uint8_t* s = data;
uint8_t* bdata = bitmap_lock_buffer_for_write(bitmap);
uint8_t* d = (uint8_t*)(bdata);
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
uint8_t r = s[0];
uint8_t g = s[1];
uint8_t b = s[2];
if (comp == 4) {
uint8_t a = s[3];
r = (r * a) >> 8;
g = (g * a) >> 8;
b = (b * a) >> 8;
}
pixel = rgb_to_gray(r, g, b) > 10;
bitmap_mono_set_pixel(d, w, h, i, j, pixel);
s += comp;
}
}
bitmap_unlock_buffer(bitmap);
return RET_OK;
}
ret_t bitmap_init_gray(bitmap_t* b, uint32_t w, uint32_t h, const uint8_t* data, uint32_t comp) {
uint32_t i = 0;
uint32_t j = 0;
const uint8_t* s = data;
uint8_t* bdata = bitmap_lock_buffer_for_write(b);
uint8_t* d = (uint8_t*)(bdata);
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
uint8_t r = s[0];
uint8_t g = s[1];
uint8_t b = s[2];
if (comp == 4) {
uint8_t a = s[3];
r = (r * a) >> 8;
g = (g * a) >> 8;
b = (b * a) >> 8;
}
*d++ = rgb_to_gray(r, g, b);
s += comp;
}
}
bitmap_unlock_buffer(b);
return RET_OK;
}
bool_t rgba_data_is_opaque(const uint8_t* data, uint32_t w, uint32_t h, uint8_t comp) {
if (comp == 4) {
uint32_t i = 0;
uint32_t n = w * h;
const uint8_t* s = data;
for (i = 0; i < n; i++) {
if (s[3] != 0xff) {
return FALSE;
}
s += 4;
}
}
return TRUE;
}
ret_t bitmap_init_from_bgra(bitmap_t* bitmap, uint32_t w, uint32_t h, bitmap_format_t format,
const uint8_t* data, uint32_t comp) {
return_value_if_fail(bitmap != NULL && data != NULL && (comp == 3 || comp == 4), RET_BAD_PARAMS);
memset(bitmap, 0x00, sizeof(bitmap_t));
bitmap->w = w;
bitmap->h = h;
bitmap->format = format;
bitmap_set_line_length(bitmap, 0);
bitmap->flags = BITMAP_FLAG_IMMUTABLE;
return_value_if_fail(bitmap_alloc_data(bitmap) == RET_OK, RET_OOM);
if (rgba_data_is_opaque(data, w, h, comp)) {
bitmap->flags |= BITMAP_FLAG_OPAQUE;
}
if (format == BITMAP_FMT_BGRA8888) {
return bitmap_init_rgba8888(bitmap, w, h, data, comp);
} else if (format == BITMAP_FMT_RGBA8888) {
return bitmap_init_bgra8888(bitmap, w, h, data, comp);
} else if (format == BITMAP_FMT_BGR565) {
return bitmap_init_rgb565(bitmap, w, h, data, comp);
} else if (format == BITMAP_FMT_RGB565) {
return bitmap_init_bgr565(bitmap, w, h, data, comp);
} else if (format == BITMAP_FMT_MONO) {
return bitmap_init_mono(bitmap, w, h, data, comp);
} else if (format == BITMAP_FMT_GRAY) {
return bitmap_init_gray(bitmap, w, h, data, comp);
} else {
return RET_NOT_IMPL;
}
}
ret_t bitmap_init_from_rgba(bitmap_t* bitmap, uint32_t w, uint32_t h, bitmap_format_t format,
const uint8_t* data, uint32_t comp) {
return_value_if_fail(bitmap != NULL && data != NULL && (comp == 3 || comp == 4), RET_BAD_PARAMS);
memset(bitmap, 0x00, sizeof(bitmap_t));
bitmap->w = w;
bitmap->h = h;
bitmap->format = format;
bitmap_set_line_length(bitmap, 0);
bitmap->flags = BITMAP_FLAG_IMMUTABLE;
return_value_if_fail(bitmap_alloc_data(bitmap) == RET_OK, RET_OOM);
if (rgba_data_is_opaque(data, w, h, comp)) {
bitmap->flags |= BITMAP_FLAG_OPAQUE;
}
if (format == BITMAP_FMT_BGRA8888) {
return bitmap_init_bgra8888(bitmap, w, h, data, comp);
} else if (format == BITMAP_FMT_RGBA8888) {
return bitmap_init_rgba8888(bitmap, w, h, data, comp);
} else if (format == BITMAP_FMT_BGR565) {
return bitmap_init_bgr565(bitmap, w, h, data, comp);
} else if (format == BITMAP_FMT_RGB565) {
return bitmap_init_rgb565(bitmap, w, h, data, comp);
} else if (format == BITMAP_FMT_MONO) {
return bitmap_init_mono(bitmap, w, h, data, comp);
} else if (format == BITMAP_FMT_GRAY) {
return bitmap_init_gray(bitmap, w, h, data, comp);
} else {
return RET_NOT_IMPL;
}
}
ret_t bitmap_init(bitmap_t* bitmap, uint32_t w, uint32_t h, bitmap_format_t format, uint8_t* data) {
uint32_t bpp = bitmap_get_bpp_of_format(format);
return_value_if_fail(bitmap != NULL, RET_BAD_PARAMS);
memset(bitmap, 0x00, sizeof(bitmap_t));
bitmap->w = w;
bitmap->h = h;
bitmap->format = format;
bitmap_set_line_length(bitmap, 0);
if (bpp < 4) {
bitmap->flags = BITMAP_FLAG_OPAQUE;
}
if (data == NULL) {
bitmap_alloc_data(bitmap);
} else {
bitmap->buffer = GRAPHIC_BUFFER_CREATE_WITH_DATA(data, w, h, format);
bitmap->should_free_data = TRUE;
}
return bitmap->buffer != NULL ? RET_OK : RET_OOM;
}
#ifdef WITH_VG_GPU
// 20211024 针对VG优化, 16像素对齐
#define VG_ALIGN_OPTIMIZE
#endif
#ifdef VG_ALIGN_OPTIMIZE
#define bmpALIGNDOWN(n, align) \
( \
(n) & ~((align) - 1) \
)
#define bmpALIGN(n, align) \
( \
bmpALIGNDOWN((n) + (align) - 1, align) \
)
#endif
ret_t bitmap_set_line_length(bitmap_t* bitmap, uint32_t line_length) {
return_value_if_fail(bitmap != NULL, RET_BAD_PARAMS);
if (bitmap->format == BITMAP_FMT_MONO) {
bitmap->line_length = TK_BITMAP_MONO_LINE_LENGTH(bitmap->w);
} else {
uint32_t bpp = bitmap_get_bpp(bitmap);
#ifdef VG_ALIGN_OPTIMIZE
// 20211024 针对VG优化, 16像素对齐
uint32_t width = bmpALIGN(bitmap->w,16);
bitmap->line_length = tk_max(width * bpp, line_length);
#else
bitmap->line_length = tk_max(bitmap->w * bpp, line_length);
#endif
}
return RET_OK;
}
uint32_t bitmap_get_line_length(bitmap_t* bitmap) {
return_value_if_fail(bitmap != NULL, 0);
if (bitmap->line_length == 0) {
bitmap_set_line_length(bitmap, 0);
}
return bitmap->line_length;
}
ret_t rgba_data_premulti_alpha(const uint8_t* data, uint8_t a_index, uint32_t w, uint32_t h) {
uint32_t i = 0;
uint32_t k = 0;
uint32_t n = w * h;
uint8_t* s = (uint8_t*)data;
return_value_if_fail(data != NULL && a_index < 4, RET_BAD_PARAMS);
for (i = 0; i < n; i++) {
uint8_t a = s[a_index];
for (k = 0; k < 4; k++) {
if (k != a_index) {
s[k] = (s[k] * a) >> 8;
}
}
s += 4;
}
return RET_OK;
}
ret_t bitmap_premulti_alpha(bitmap_t* bitmap) {
ret_t ret = RET_FAIL;
uint8_t* bitmap_data = NULL;
return_value_if_fail(bitmap != NULL, RET_BAD_PARAMS);
if (bitmap->flags & BITMAP_FLAG_PREMULTI_ALPHA) {
return RET_OK;
}
bitmap_data = bitmap_lock_buffer_for_write(bitmap);
return_value_if_fail(bitmap != NULL, RET_BAD_PARAMS);
switch (bitmap->format) {
case BITMAP_FMT_RGBA8888:
case BITMAP_FMT_BGRA8888: {
ret = rgba_data_premulti_alpha(bitmap_data, 3, bitmap->w, bitmap->h);
break;
}
case BITMAP_FMT_ABGR8888:
case BITMAP_FMT_ARGB8888: {
ret = rgba_data_premulti_alpha(bitmap_data, 0, bitmap->w, bitmap->h);
break;
}
}
if (ret == RET_OK) {
bitmap->flags = bitmap->flags | BITMAP_FLAG_PREMULTI_ALPHA;
}
bitmap_unlock_buffer(bitmap);
return ret;
}
bitmap_t* bitmap_clone(bitmap_t* bitmap) {
bitmap_t* b = NULL;
return_value_if_fail(bitmap != NULL && bitmap->buffer != NULL, NULL);
b = bitmap_create_ex(bitmap->w, bitmap->h, bitmap->line_length,
(bitmap_format_t)(bitmap->format));
return_value_if_fail(b != NULL, NULL);
if (b->buffer != NULL) {
uint8_t* s = bitmap_lock_buffer_for_read(bitmap);
uint8_t* d = bitmap_lock_buffer_for_write(b);
if (s != NULL && d != NULL) {
memcpy((char*)(d), s, b->line_length * b->h);
}
bitmap_unlock_buffer(bitmap);
bitmap_unlock_buffer(b);
b->name = bitmap->name;
}
return b;
}
#if defined(WITH_STB_IMAGE)
#define STB_IMAGE_STATIC 1
#define STBI_WRITE_NO_STDIO 1
#define STB_IMAGE_WRITE_STATIC 1
#define STB_IMAGE_WRITE_IMPLEMENTATION
#define STBI_FREE TKMEM_FREE
#define STBI_MALLOC TKMEM_ALLOC
#define STBI_REALLOC(p, s) TKMEM_REALLOC(p, s)
#include "tkc/fs.h"
#include "stb/stb_image_write.h"
bitmap_t* bitmap_rgba8888_from_bitmap(bitmap_t* bitmap) {
color_t c;
uint32_t x = 0;
uint32_t y = 0;
bitmap_t* t = NULL;
uint32_t* p = NULL;
uint8_t* tdata = NULL;
t = bitmap_create_ex(bitmap->w, bitmap->h, 0, BITMAP_FMT_RGBA8888);
return_value_if_fail(t != NULL, FALSE);
tdata = (uint8_t*)bitmap_lock_buffer_for_write(t);
for (y = 0; y < bitmap->h; y++) {
p = (uint32_t*)(tdata + (y * t->line_length));
for (x = 0; x < bitmap->w; x++) {
bitmap_get_pixel(bitmap, x, y, &(c.rgba));
*p++ = c.color;
}
}
bitmap_unlock_buffer(t);
return t;
}
static bool_t bitmap_rgba8888_save_png(bitmap_t* bitmap, const char* filename) {
int32_t len = 0;
bitmap_t* t = bitmap;
uint8_t* tdata = NULL;
unsigned char* png_data = NULL;
tdata = bitmap_lock_buffer_for_write(t);
png_data = stbi_write_png_to_mem(tdata, t->w * 4, t->w, t->h, 4, &len);
bitmap_unlock_buffer(t);
if (png_data == NULL) {
return_value_if_fail(png_data != NULL, FALSE);
} else {
fs_t* fs = os_fs();
fs_file_t* png_file = fs_open_file(fs, filename, "wb");
if (png_file != NULL) {
fs_file_write(png_file, png_data, len);
} else {
ENSURE(!" do not open file, do not save png file !");
}
STBIW_FREE(png_data);
return_value_if_fail(fs_file_close(png_file) == RET_OK, FALSE);
}
return TRUE;
}
bool_t bitmap_save_png(bitmap_t* bitmap, const char* filename) {
return_value_if_fail(bitmap != NULL && filename != NULL, FALSE);
if (bitmap->format != BITMAP_FMT_RGBA8888 || bitmap->line_length != bitmap->w * 4) {
bitmap_t* t = bitmap_rgba8888_from_bitmap(bitmap);
bitmap_rgba8888_save_png(t, filename);
bitmap_destroy(t);
} else {
bitmap_rgba8888_save_png(bitmap, filename);
}
return TRUE;
}
#else
bool_t bitmap_save_png(bitmap_t* bitmap, const char* filename) {
return FALSE;
}
#endif /*defined(WITH_STB_IMAGE)*/
/*helper*/
#define BIT_OFFSET(xx) (7 - ((xx) % 8))
ret_t bitmap_mono_set_pixel(uint8_t* buff, uint32_t w, uint32_t h, uint32_t x, uint32_t y,
bool_t pixel) {
uint32_t offset = y * TK_BITMAP_MONO_LINE_LENGTH(w) + (x >> 3);
uint8_t* data = buff + offset;
uint32_t offset_bit = BIT_OFFSET(x);
return_value_if_fail(buff != NULL, RET_BAD_PARAMS);
return_value_if_fail(x < w && y < h, RET_BAD_PARAMS);
if (pixel) {
*data |= (1 << offset_bit);
} else {
*data &= ~(1 << offset_bit);
}
return RET_OK;
}
bool_t bitmap_mono_get_pixel(const uint8_t* buff, uint32_t w, uint32_t h, uint32_t x, uint32_t y) {
uint32_t offset = y * TK_BITMAP_MONO_LINE_LENGTH(w) + (x >> 3);
const uint8_t* data = buff + offset;
uint32_t offset_bit = BIT_OFFSET(x);
return_value_if_fail(buff != NULL, FALSE);
return_value_if_fail(x < w && y < h, FALSE);
return (*data >> offset_bit) & 0x1;
}
uint8_t* bitmap_mono_create_data(uint32_t w, uint32_t h) {
uint8_t* buff = NULL;
uint32_t size = TK_BITMAP_MONO_LINE_LENGTH(w) * h;
return_value_if_fail(w > 0 && h > 0, NULL);
buff = TKMEM_ALLOC(size);
return_value_if_fail(buff != NULL, NULL);
memset(buff, 0x00, size);
return buff;
}
ret_t bitmap_mono_dump(const uint8_t* buff, uint32_t w, uint32_t h) {
uint32_t j = 0;
uint32_t i = 0;
return_value_if_fail(buff != NULL, RET_BAD_PARAMS);
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
bool_t pixel = bitmap_mono_get_pixel(buff, w, h, i, j);
if (pixel) {
log_debug("O");
} else {
log_debug(" ");
}
}
log_debug("\n");
}
return RET_OK;
}
uint8_t* bitmap_lock_buffer_for_read(bitmap_t* bitmap) {
return_value_if_fail(bitmap != NULL, NULL);
if (bitmap->buffer != NULL) {
if (!graphic_buffer_is_valid_for(bitmap->buffer, bitmap)) {
assert(!" graphic_buffer is not valid ");
return NULL;
}
return graphic_buffer_lock_for_read(bitmap->buffer);
} else {
return NULL;
}
}
uint8_t* bitmap_lock_buffer_for_write(bitmap_t* bitmap) {
return_value_if_fail(bitmap != NULL, NULL);
if (bitmap->buffer != NULL) {
if (!graphic_buffer_is_valid_for(bitmap->buffer, bitmap)) {
assert(!" graphic_buffer is not valid ");
return NULL;
}
return graphic_buffer_lock_for_write(bitmap->buffer);
} else {
return NULL;
}
}
ret_t bitmap_unlock_buffer(bitmap_t* bitmap) {
return_value_if_fail(bitmap != NULL, RET_BAD_PARAMS);
if (bitmap->buffer != NULL) {
assert(graphic_buffer_is_valid_for(bitmap->buffer, bitmap));
return graphic_buffer_unlock(bitmap->buffer);
} else {
return RET_FAIL;
}
}
ret_t bitmap_transform(bitmap_t* bitmap, bitmap_transform_t transform, void* ctx) {
uint32_t x = 0;
uint32_t y = 0;
ret_t ret = RET_OK;
const uint8_t* data = NULL;
uint8_t* bitmap_data = NULL;
uint32_t bpp = bitmap_get_bpp(bitmap);
return_value_if_fail(transform != NULL, RET_BAD_PARAMS);
return_value_if_fail(bitmap != NULL && bitmap->buffer != NULL, RET_BAD_PARAMS);
bitmap_data = bitmap_lock_buffer_for_write(bitmap);
for (y = 0; y < bitmap->h; y++) {
data = bitmap_data + bitmap_get_line_length(bitmap) * y;
for (x = 0; x < bitmap->w; x++) {
switch (bitmap->format) {
case BITMAP_FMT_RGBA8888: {
pixel_rgba8888_t* p = (pixel_rgba8888_t*)data;
rgba_t pixel = pixel_rgba8888_to_rgba((*p));
if (transform(ctx, bitmap, x, y, &pixel) == RET_OK) {
pixel_rgba8888_t result = pixel_rgba8888_from_rgba(pixel.r, pixel.g, pixel.b, pixel.a);
*p = result;
}
break;
}
case BITMAP_FMT_ABGR8888: {
pixel_abgr8888_t* p = (pixel_abgr8888_t*)data;
rgba_t pixel = pixel_abgr8888_to_rgba((*p));
if (transform(ctx, bitmap, x, y, &pixel) == RET_OK) {
pixel_abgr8888_t result = pixel_abgr8888_from_rgba(pixel.r, pixel.g, pixel.b, pixel.a);
*p = result;
}
break;
}
case BITMAP_FMT_BGRA8888: {
pixel_bgra8888_t* p = (pixel_bgra8888_t*)data;
rgba_t pixel = pixel_bgra8888_to_rgba((*p));
if (transform(ctx, bitmap, x, y, &pixel) == RET_OK) {
pixel_bgra8888_t result = pixel_bgra8888_from_rgba(pixel.r, pixel.g, pixel.b, pixel.a);
*p = result;
}
break;
}
case BITMAP_FMT_ARGB8888: {
pixel_argb8888_t* p = (pixel_argb8888_t*)data;
rgba_t pixel = pixel_argb8888_to_rgba((*p));
if (transform(ctx, bitmap, x, y, &pixel) == RET_OK) {
pixel_argb8888_t result = pixel_argb8888_from_rgba(pixel.r, pixel.g, pixel.b, pixel.a);
*p = result;
}
break;
}
case BITMAP_FMT_RGB565: {
pixel_rgb565_t* p = (pixel_rgb565_t*)data;
rgba_t pixel = pixel_rgb565_to_rgba((*p));
if (transform(ctx, bitmap, x, y, &pixel) == RET_OK) {
pixel_rgb565_t result = pixel_rgb565_from_rgba(pixel.r, pixel.g, pixel.b, pixel.a);
*p = result;
}
break;
}
case BITMAP_FMT_BGR565: {
pixel_bgr565_t* p = (pixel_bgr565_t*)data;
rgba_t pixel = pixel_bgr565_to_rgba((*p));
if (transform(ctx, bitmap, x, y, &pixel) == RET_OK) {
pixel_bgr565_t result = pixel_bgr565_from_rgba(pixel.r, pixel.g, pixel.b, pixel.a);
*p = result;
}
break;
}
case BITMAP_FMT_RGB888: {
pixel_rgb888_t* p = (pixel_rgb888_t*)data;
rgba_t pixel = pixel_rgb888_to_rgba((*p));
if (transform(ctx, bitmap, x, y, &pixel) == RET_OK) {
pixel_rgb888_t result = pixel_rgb888_from_rgba(pixel.r, pixel.g, pixel.b, pixel.a);
*p = result;
}
break;
}
case BITMAP_FMT_BGR888: {
pixel_bgr888_t* p = (pixel_bgr888_t*)data;
rgba_t pixel = pixel_bgr888_to_rgba((*p));
if (transform(ctx, bitmap, x, y, &pixel) == RET_OK) {
pixel_bgr888_t result = pixel_bgr888_from_rgba(pixel.r, pixel.g, pixel.b, pixel.a);
*p = result;
}
break;
}
default: {
ret = RET_NOT_IMPL;
break;
}
}
data += bpp;
}
}
bitmap_unlock_buffer(bitmap);
bitmap->flags |= BITMAP_FLAG_CHANGED;
return ret;
}
uint32_t bitmap_get_mem_size(bitmap_t* bitmap) {
return_value_if_fail(bitmap != NULL, 0);
return bitmap->w * bitmap->h * bitmap_get_bpp(bitmap);
}

View File

@ -0,0 +1,487 @@
/**
* File: bitmap.h
* Author: AWTK Develop Team
* Brief: bitmap interface
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_BITMAP_H
#define TK_BITMAP_H
#include "tkc/color.h"
#include "base/types_def.h"
#include "base/graphic_buffer.h"
BEGIN_C_DECLS
typedef ret_t (*bitmap_destroy_t)(bitmap_t* bitmap);
/**
* @class bitmap_t
* @order -9
* @annotation ["scriptable"]
* 位图。
*/
struct _bitmap_t {
/**
* @property {wh_t} w
* @annotation ["readable", "scriptable"]
* 宽度。
*/
wh_t w;
/**
* @property {wh_t} h
* @annotation ["readable", "scriptable"]
* 高度。
*/
wh_t h;
/**
* @property {uint32_t} line_length
* @annotation ["readable", "scriptable"]
* 每一行实际占用的内存(也称为stride或pitch)一般情况下为w*bpp。
*/
uint32_t line_length;
/**
* @property {uint16_t} flags
* @annotation ["readable", "scriptable"]
* 标志。请参考{bitmap_flag_t}。
*/
uint16_t flags;
/**
* @property {uint16_t} format
* @annotation ["readable", "scriptable"]
* 格式。请参考{bitmap_format_t}。
*/
uint16_t format;
/**
* @property {const char*} name
* @annotation ["readable", "scriptable"]
* 名称。
*/
const char* name;
/**
* @property {graphic_buffer_t*} buffer
* @annotation ["readable"]
* 图片数据。
*/
graphic_buffer_t* buffer;
bool_t is_gif;
/*for gif begin*/
int* gif_delays;
uint32_t gif_frame_h;
uint32_t gif_frames_nr;
/*for gif end*/
/*private members*/
/*data是按cache line对齐而data_free_ptr是用于释放的指针*/
uint8_t* data_free_ptr;
/*destroy时是否需要释放data指向的内存*/
bool_t should_free_data;
/*destroy时是否需要释放bitmap本身的内存*/
bool_t should_free_handle;
/* 显示特定的数据如OpenGL texture IDagg/agge中图片等。*/
void* specific;
/*specific_destroy的上下文*/
void* specific_ctx;
/*用于销毁specific*/
bitmap_destroy_t specific_destroy;
/*virtual functions*/
bitmap_destroy_t destroy;
image_manager_t* image_manager;
};
/**
* @method bitmap_create
* 创建图片对象(一般供脚本语言中使用)。
* @annotation ["constructor", "scriptable", "gc"]
* @return {bitmap_t*} 返回bitmap对象。
*/
bitmap_t* bitmap_create(void);
/**
* @method bitmap_create_ex
* 创建图片对象。
* @annotation ["constructor", "scriptable", "gc"]
* @param {uint32_t} w 宽度。
* @param {uint32_t} h 高度。
* @param {uint32_t} line_length line_length。
* @param {bitmap_format_t} format 格式。
*
* @return {bitmap_t*} 返回bitmap对象。
*/
bitmap_t* bitmap_create_ex(uint32_t w, uint32_t h, uint32_t line_length, bitmap_format_t format);
/**
* @method bitmap_get_bpp
* 获取图片一个像素占用的字节数。
* @annotation ["scriptable"]
* @param {bitmap_t*} bitmap bitmap对象。
*
* @return {uint32_t} 返回一个像素占用的字节数。
*/
uint32_t bitmap_get_bpp(bitmap_t* bitmap);
/**
* @method bitmap_lock_buffer_for_read
* 为读取数据而锁定bitmap的图片缓冲区。
*
* @param {bitmap_t*} bitmap bitmap对象。
*
* @return {uint8_t*} 返回缓存区的首地址。
*/
uint8_t* bitmap_lock_buffer_for_read(bitmap_t* bitmap);
/**
* @method bitmap_lock_buffer_for_write
* 为修改数据而锁定bitmap的图片缓冲区。
*
* @param {bitmap_t*} bitmap bitmap对象。
*
* @return {uint8_t*} 返回缓存区的首地址。
*/
uint8_t* bitmap_lock_buffer_for_write(bitmap_t* bitmap);
/**
* @method bitmap_unlock_buffer
* 解锁图像缓冲区。
*
* @param {bitmap_t*} bitmap bitmap对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t bitmap_unlock_buffer(bitmap_t* bitmap);
/**
* @method bitmap_get_pixel
* 获取图片指定像素的rgba颜色值(主要用于测试程序)。
* @param {bitmap_t*} bitmap bitmap对象。
* @param {uint32_t} x x坐标。
* @param {uint32_t} y y坐标。
* @param {rgba_t*} rgba 返回颜色值。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t bitmap_get_pixel(bitmap_t* bitmap, uint32_t x, uint32_t y, rgba_t* rgba);
/**
* @method bitmap_set_line_length
* 设置line_length。
* @param {bitmap_t*} bitmap bitmap对象。
* @param {uint32_t} line_length line_length。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t bitmap_set_line_length(bitmap_t* bitmap, uint32_t line_length);
/**
* @method bitmap_get_line_length
* 获取每一行占用内存的字节数。
* @param {bitmap_t*} bitmap bitmap对象。
*
* @return {ret_t} 返回每一行占用内存的字节数。
*/
uint32_t bitmap_get_line_length(bitmap_t* bitmap);
typedef ret_t (*bitmap_transform_t)(void* ctx, bitmap_t* bitmap, uint32_t x, uint32_t y,
rgba_t* pixel);
/**
* @method bitmap_clone
* Clone图片。
* @param {bitmap_t*} bitmap bitmap对象。
*
* @return {bitmap_t*} 返回新的bitmap对象。
*/
bitmap_t* bitmap_clone(bitmap_t* bitmap);
/**
* @method bitmap_transform
* 对图片每个像素进行变换。
* @param {bitmap_t*} bitmap bitmap对象。
* @param {bitmap_transform_t} transform 回调函数。
* @param {void*} ctx 回调函数的上下文。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t bitmap_transform(bitmap_t* bitmap, bitmap_transform_t transform, void* ctx);
/**
* @method bitmap_init_from_rgba
* 初始化图片。
* @param {bitmap_t*} bitmap bitmap对象。
* @param {uint32_t} w 宽度。
* @param {uint32_t} h 高度。
* @param {bitmap_format_t} format 格式。
* @param {const uint8_t*} data
* 数据。3通道时为RGB888格式4通道时为RGBA888格式(内部拷贝该数据,不会引用,调用者自行释放)。
* @param {uint32_t} comp 颜色通道数(目前支持3(rgb)和4(rgba))。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t bitmap_init_from_rgba(bitmap_t* bitmap, uint32_t w, uint32_t h, bitmap_format_t format,
const uint8_t* data, uint32_t comp);
/**
* @method bitmap_init_from_bgra
* 初始化图片。
* @param {bitmap_t*} bitmap bitmap对象。
* @param {uint32_t} w 宽度。
* @param {uint32_t} h 高度。
* @param {bitmap_format_t} format 格式。
* @param {const uint8_t*} data
* 数据。3通道时为BGR888格式4通道时为BGRA888格式(内部拷贝该数据,不会引用,调用者自行释放)。
* @param {uint32_t} comp 颜色通道数(目前支持3(bgr)和4(bgra))。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t bitmap_init_from_bgra(bitmap_t* bitmap, uint32_t w, uint32_t h, bitmap_format_t format,
const uint8_t* data, uint32_t comp);
/**
* @method bitmap_init
* 初始化图片。
* @param {bitmap_t*} bitmap bitmap对象。
* @param {uint32_t} w 宽度。
* @param {uint32_t} h 高度。
* @param {bitmap_format_t} format 格式。
* @param {const uint8_t*} data 数据,直接引用,但不负责释放。如果为空,由内部自动分配和释放。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t bitmap_init(bitmap_t* bitmap, uint32_t w, uint32_t h, bitmap_format_t format, uint8_t* data);
#if defined(WITH_STB_IMAGE) || defined(WITH_FS_RES)
/*for helping debug drawing bugs*/
/**
* @method bitmap_save_png
* 把bitmap保存为png。
*
* @param {bitmap_t*} bitmap bitmap对象。
* @param {const char*} filename 文件名。
*
* @return {bool_t} 返回TRUE表示成功FALSE表示失败。
*/
bool_t bitmap_save_png(bitmap_t* bitmap, const char* filename);
#endif /*defined(WITH_STB_IMAGE) || defined(WITH_FS_RES)*/
/**
* @method bitmap_mono_dump
* dump mono bitmap。
* @annotation ["static"]
* @param {const uint8_t*} buff 数据。
* @param {uint32_t} w 宽度。
* @param {uint32_t} h 高度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t bitmap_mono_dump(const uint8_t* buff, uint32_t w, uint32_t h);
/**
* @method bitmap_destroy_with_self
* 销毁图片(for script only)。
* @alias bitmap_destroy
* @annotation ["deconstructor", "scriptable", "gc"]
* @param {bitmap_t*} bitmap bitmap对象。
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t bitmap_destroy_with_self(bitmap_t* bitmap);
/**
* @method bitmap_destroy
* 销毁图片。
* @annotation ["deconstructor"]
* @param {bitmap_t*} bitmap bitmap对象。
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t bitmap_destroy(bitmap_t* bitmap);
/**
* @method bitmap_get_bpp_of_format
* 获取位图格式对应的颜色位数。
* @annotation ["scriptable", "static"]
*
* @param {bitmap_format_t} format 位图格式。
*
* @return {uint32_t} 成功返回颜色位数失败返回0。
*/
uint32_t bitmap_get_bpp_of_format(bitmap_format_t format);
/**
* @enum image_draw_type_t
* @prefix IMAGE_DRAW_
* @annotation ["scriptable"]
* 图片绘制方法常量定义。
*/
typedef enum _image_draw_type_t {
/**
* @const IMAGE_DRAW_DEFAULT
* 缺省显示。将图片按原大小显示在目标矩形的左上角。
*/
IMAGE_DRAW_DEFAULT = 0,
/**
* @const IMAGE_DRAW_CENTER
* 居中显示。将图片按原大小显示在目标矩形的中央。
*/
IMAGE_DRAW_CENTER,
/**
* @const IMAGE_DRAW_ICON
* 图标显示。同居中显示,但会根据屏幕密度调整大小。
*/
IMAGE_DRAW_ICON,
/**
* @const IMAGE_DRAW_SCALE
* 缩放显示。将图片缩放至目标矩形的大小(不保证宽高成比例)。
*/
IMAGE_DRAW_SCALE,
/**
* @const IMAGE_DRAW_SCALE_AUTO
* 自动缩放显示。将图片缩放至目标矩形的宽度或高度(选取最小的比例),并居中显示。
*/
IMAGE_DRAW_SCALE_AUTO,
/**
* @const IMAGE_DRAW_SCALE_DOWN
* 如果图片比目标矩形大,自动缩小显示,否则居中显示。
*/
IMAGE_DRAW_SCALE_DOWN,
/**
* @const IMAGE_DRAW_SCALE_W
* 宽度缩放显示。 将图片缩放至目标矩形的宽度,高度按此比例进行缩放,超出不部分不显示。
*/
IMAGE_DRAW_SCALE_W,
/**
* @const IMAGE_DRAW_SCALE_H
* 高度缩放显示。将图片缩放至目标矩形的高度,宽度按此比例进行缩放,超出不部分不显示。
*/
IMAGE_DRAW_SCALE_H,
/**
* @const IMAGE_DRAW_REPEAT
* 平铺显示。
*/
IMAGE_DRAW_REPEAT,
/**
* @const IMAGE_DRAW_REPEAT_X
* 水平方向平铺显示,垂直方向缩放。
*/
IMAGE_DRAW_REPEAT_X,
/**
* @const IMAGE_DRAW_REPEAT_Y
* 垂直方向平铺显示,水平方向缩放。
*/
IMAGE_DRAW_REPEAT_Y,
/**
* @const IMAGE_DRAW_REPEAT_Y_INVERSE
* 垂直方向平铺显示,水平方向缩放(从底部到顶部)。
*/
IMAGE_DRAW_REPEAT_Y_INVERSE,
/**
* @const IMAGE_DRAW_PATCH9
* 9宫格显示。
* 将图片分成等大小的9块4个角按原大小显示在目标矩形的4个角左右上下和中间5块分别缩放显示在对应的目标区域。
*/
IMAGE_DRAW_PATCH9,
/**
* @const IMAGE_DRAW_PATCH3_X
* 水平方向3宫格显示垂直方向居中显示。
* 将图片在水平方向上分成等大小的3块左右两块按原大小显示在目标矩形的左右中间一块缩放显示在目标区域中间剩余部分。
*/
IMAGE_DRAW_PATCH3_X,
/**
* @const IMAGE_DRAW_PATCH3_Y
* 垂直方向3宫格显示水平方向居中显示。
* 将图片在垂直方向上分成等大小的3块上下两块按原大小显示在目标矩形的上下中间一块缩放显示在目标区域中间剩余部分。
*/
IMAGE_DRAW_PATCH3_Y,
/**
* @const IMAGE_DRAW_PATCH3_X_SCALE_Y
* 水平方向3宫格显示垂直方向缩放显示。
* 将图片在水平方向上分成等大小的3块左右两块按原大小显示在目标矩形的左右中间一块缩放显示在目标区域中间剩余部分。
*/
IMAGE_DRAW_PATCH3_X_SCALE_Y,
/**
* @const IMAGE_DRAW_PATCH3_Y_SCALE_X
* 垂直方向3宫格显示水平方向缩放显示。
* 将图片在垂直方向上分成等大小的3块上下两块按原大小显示在目标矩形的上下中间一块缩放显示在目标区域中间剩余部分。
*/
IMAGE_DRAW_PATCH3_Y_SCALE_X,
/**
* @const IMAGE_DRAW_REPEAT9
* 平铺9宫格显示。
* 将图片分成4个角和5块平铺块4个角按原大小显示在目标矩形的4个角其余5块会平铺对应的目标区域。
* 切割方法为(如下图):
* 如果图片宽度为奇数,则中间一块为一列数据,如果图片宽度为偶数,则中间一块为二列数据,其他数据分为左右块
* 如果图片高度为奇数,则中间一块为一行数据,如果图片高度为偶数,则中间一块为二行数据,其他数据分为上下块
* 中间一块数据根据上面两条规则组成4中情况分别是一列一行数据一列两行数据两列一行数据和两行两列数据
*/
IMAGE_DRAW_REPEAT9,
/**
* @const IMAGE_DRAW_REPEAT3_X
* 水平方向3宫格显示垂直方向居中显示。
* 将图片在水平方向上分成左右相等两块和中间一块,如果图片宽度为奇数,则中间一块为一列数据,如果图片宽度为偶数,则中间一块为二列数据,其他数据分为左右块。
* 左右两块按原大小显示在目标矩形的左右,中间一列像素点平铺显示在目标区域中间剩余部分。
*/
IMAGE_DRAW_REPEAT3_X,
/**
* @const IMAGE_DRAW_REPEAT3_Y
* 垂直方向3宫格显示水平方向居中显示。
* 将图片在垂直方向上分成上下相等两块和中间一块,如果图片高度为奇数,则中间一块为一行数据,如果图片高度为偶数,则中间一块为二行数据,其他数据分为上下块
* 上下两块按原大小显示在目标矩形的上下,中间一块平铺显示在目标区域中间剩余部分。
*/
IMAGE_DRAW_REPEAT3_Y
} image_draw_type_t;
/*private*/
ret_t bitmap_alloc_data(bitmap_t* bitmap);
bool_t rgba_data_is_opaque(const uint8_t* data, uint32_t w, uint32_t h, uint8_t comp);
ret_t bitmap_premulti_alpha(bitmap_t* bitmap);
#define TK_BITMAP_MONO_LINE_LENGTH(w) (((w + 15) >> 4) << 1)
uint8_t* bitmap_mono_create_data(uint32_t w, uint32_t h);
bool_t bitmap_mono_get_pixel(const uint8_t* buff, uint32_t w, uint32_t h, uint32_t x, uint32_t y);
ret_t bitmap_mono_set_pixel(uint8_t* buff, uint32_t w, uint32_t h, uint32_t x, uint32_t y,
bool_t pixel);
uint32_t bitmap_get_mem_size(bitmap_t* bitmap);
END_C_DECLS
#endif /*TK_BITMAP_H*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,952 @@
/**
* File: canvas.h
* Author: AWTK Develop Team
* Brief: canvas provides basic drawings functions.
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_CANVAS_H
#define TK_CANVAS_H
#include "base/lcd.h"
#include "base/dirty_rects.h"
#include "base/system_info.h"
#include "base/font_manager.h"
BEGIN_C_DECLS
typedef ret_t (*canvas_end_frame_t)(canvas_t* c);
typedef ret_t (*canvas_begin_frame_t)(canvas_t* c, const dirty_rects_t* dirty_rects,
lcd_draw_mode_t draw_mode);
/**
* @class canvas_t
* @annotation ["scriptable"]
* 提供基本的绘图功能和状态管理。
*
*/
struct _canvas_t {
/**
* @property {xy_t} ox
* @annotation ["readable", "scriptable"]
* x坐标偏移。
*/
xy_t ox;
/**
* @property {xy_t} oy
* @annotation ["readable", "scriptable"]
* y坐标偏移。
*/
xy_t oy;
/**
* @property {char*} font_name
* @annotation ["readable", "scriptable"]
* 当前字体名称。
*/
char* font_name;
/**
* @property {uint16_t} font_size
* @annotation ["readable", "scriptable"]
* 当前字体大小。
*/
font_size_t font_size;
/**
* @property {uint8_t} global_alpha
* @annotation ["readable", "scriptable"]
* 当前全局alpha。
*/
uint8_t global_alpha;
/**
* @property {xy_t} clip_left
* @annotation ["readable"]
* 当前裁剪矩形的左边位置。
*/
xy_t clip_left;
/**
* @property {xy_t} clip_top
* @annotation ["readable"]
* 当前裁剪矩形的顶部位置。
*/
xy_t clip_top;
/**
* @property {xy_t} clip_right
* @annotation ["readable"]
* 当前裁剪矩形的右边位置。
*/
xy_t clip_right;
/**
* @property {xy_t} clip_bottom
* @annotation ["readable"]
* 当前裁剪矩形的底部位置。
*/
xy_t clip_bottom;
/**
* @property {uint32_t} fps
* @annotation ["readable"]
* 当前的帧率。
*/
uint32_t fps;
/**
* @property {bool_t} show_fps
* @annotation ["readable"]
* 是否显示帧率。
*/
bool_t show_fps;
/**
* @property {align_v_t} text_align_v
* @annotation ["readable"]
* 文本垂直对齐方式。
*/
align_v_t text_align_v;
/**
* @property {align_h_t} text_align_h
* @annotation ["readable"]
* 文本水平对齐方式。
*/
align_h_t text_align_h;
/**
* @property {lcd_t*} lcd
* @annotation ["readable"]
* lcd对象。
*/
lcd_t* lcd;
/**
* @property {font_t*} font
* @annotation ["readable"]
* 字体对象。
*/
font_t* font;
/**
* @property {font_manager_t*} font_manager
* @annotation ["readable"]
* 字体管理器对象。
*/
font_manager_t* font_manager;
/**
* @property {assets_manager_t*} assets_manager
* @annotation ["readable"]
* 资源管理器对象。
*/
assets_manager_t* assets_manager;
/*private*/
/*确保begin_frame/end_frame配对使用*/
bool_t began_frame;
canvas_end_frame_t end_frame;
canvas_begin_frame_t begin_frame;
};
/**
* @method canvas_init
* 初始化,系统内部调用。
*
* @param {canvas_t*} c canvas对象。
* @param {lcd_t*} lcd lcd对象。
* @param {font_manager_t*} font_manager 字体管理器对象。
*
* @return {canvas_t*} 返回canvas对象本身。
*/
canvas_t* canvas_init(canvas_t* c, lcd_t* lcd, font_manager_t* font_manager);
/**
* @method canvas_get_width
* 获取画布的宽度。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
*
* @return {wh_t} 返回画布的宽度。
*
*/
wh_t canvas_get_width(canvas_t* c);
/**
* @method canvas_get_height
* 获取画布的高度。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
*
* @return {wh_t} 返回画布的高度。
*
*/
wh_t canvas_get_height(canvas_t* c);
/**
* @method canvas_get_clip_rect
* 获取裁剪区。
*
* @param {canvas_t*} c canvas对象。
* @param {rect_t*} r rect对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_get_clip_rect(canvas_t* c, rect_t* r);
/**
* @method canvas_is_rect_in_clip_rect
* 判断改矩形区域是否在裁剪区中
* @param {canvas_t*} c canvas对象。
* @param {xy_t} left 矩形区域左边。
* @param {xy_t} top 矩形区域上边。
* @param {xy_t} right 矩形区域右边。
* @param {xy_t} bottom 矩形区域下边。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
bool_t canvas_is_rect_in_clip_rect(canvas_t* c, xy_t left, xy_t top, xy_t right, xy_t bottom);
/**
* @method canvas_set_clip_rect
* 设置裁剪区。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {const rect_t*} r rect对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_clip_rect(canvas_t* c, const rect_t* r);
#ifdef DIRTY_RECTS_CLIP_SUPPORT
/**
* @_method canvas_set_clip_rect_dirty_rects
* 设置裁剪区。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {const dirty_rects_t*} r dirty_rects_t对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_clip_rect_dirty_rects(canvas_t* c, const dirty_rects_t* r);
#endif
/**
* @method canvas_set_clip_rect_ex
* 设置裁剪区。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {const rect_t*} r rect对象。
* @param {bool_t} translate 是否将裁剪区的位置加上canvas当前的偏移。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_clip_rect_ex(canvas_t* c, const rect_t* r, bool_t translate);
/**
* @method canvas_set_fill_color
* 设置填充颜色。
*
* @param {canvas_t*} c canvas对象。
* @param {color_t} color 颜色。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_fill_color(canvas_t* c, color_t color);
/**
* @method canvas_set_text_color
* 设置文本颜色。
*
* @param {canvas_t*} c canvas对象。
* @param {color_t} color 颜色。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_text_color(canvas_t* c, color_t color);
/**
* @method canvas_set_stroke_color
* 设置线条颜色。
*
* @param {canvas_t*} c canvas对象。
* @param {color_t} color 颜色。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_stroke_color(canvas_t* c, color_t color);
/**
* @method canvas_set_fill_color_str
* 设置填充颜色。
*
* > 供脚本语言使用。
*
* @alias canvas_set_fill_color
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {const char*} color 颜色。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_fill_color_str(canvas_t* c, const char* color);
/**
* @method canvas_set_text_color_str
* 设置文本颜色。
*
* > 供脚本语言使用。
*
* @alias canvas_set_text_color
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {const char*} color 颜色。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_text_color_str(canvas_t* c, const char* color);
/**
* @method canvas_set_stroke_color_str
* 设置线条颜色。
*
* > 供脚本语言使用。
*
* @alias canvas_set_stroke_color
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {const char*} color 颜色。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_stroke_color_str(canvas_t* c, const char* color);
/**
* @method canvas_set_global_alpha
* 设置全局alpha值。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {uint8_t} alpha alpha值。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_global_alpha(canvas_t* c, uint8_t alpha);
/**
* @method canvas_translate
* 平移原点坐标。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {xy_t} dx x偏移。
* @param {xy_t} dy y偏移。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_translate(canvas_t* c, xy_t dx, xy_t dy);
/**
* @method canvas_untranslate
* 反向平移原点坐标。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {xy_t} dx x偏移。
* @param {xy_t} dy y偏移。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_untranslate(canvas_t* c, xy_t dx, xy_t dy);
/**
* @method canvas_draw_vline
* 画垂直线。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
* @param {wh_t} h 高度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_vline(canvas_t* c, xy_t x, xy_t y, wh_t h);
/**
* @method canvas_draw_hline
* 画水平线。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
* @param {wh_t} w 宽度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_hline(canvas_t* c, xy_t x, xy_t y, wh_t w);
/**
* @method canvas_draw_points
* 画多个点。
*
* @param {canvas_t*} c canvas对象。
* @param {const point_t*} points 点数组。
* @param {uint32_t} nr 点的个数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_points(canvas_t* c, const point_t* points, uint32_t nr);
/**
* @method canvas_fill_rect
* 绘制矩形。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
* @param {wh_t} w 宽度。
* @param {wh_t} h 高度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_fill_rect(canvas_t* c, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method canvas_fill_rect_gradient
* 绘制矩形。
*
* @param {canvas_t*} c canvas对象。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
* @param {wh_t} w 宽度。
* @param {wh_t} h 高度。
* @param {gradient_t*} gradient 渐变颜色。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_fill_rect_gradient(canvas_t* c, xy_t x, xy_t y, wh_t w, wh_t h, gradient_t* gradient);
/**
* @method canvas_clear_rect
* 用填充颜色填充指定矩形。
*
*> 如果lcd的颜色格式带alpha通道连同alpha的值一起修改。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
* @param {wh_t} w 宽度。
* @param {wh_t} h 高度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_clear_rect(canvas_t* c, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method canvas_stroke_rect
* 绘制矩形。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
* @param {wh_t} w 宽度。
* @param {wh_t} h 高度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_stroke_rect(canvas_t* c, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method canvas_set_font
* 设置字体。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {const char*} name 字体名称。
* @param {font_size_t} size 字体大小。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_font(canvas_t* c, const char* name, font_size_t size);
/**
* @method canvas_set_text_align
* 设置文本对齐方式。
*
* @param {canvas_t*} c canvas对象。
* @param {align_h_t} align_h 水平对齐方式。
* @param {align_v_t} align_v 垂直对齐方式。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_text_align(canvas_t* c, align_h_t align_h, align_v_t align_v);
/**
* @method canvas_measure_text
* 计算文本所占的宽度。
*
* @param {canvas_t*} c canvas对象。
* @param {const wchar_t*} str 字符串。
* @param {uint32_t} nr 字符数。
*
* @return {float_t} 返回文本所占的宽度。
*/
float_t canvas_measure_text(canvas_t* c, const wchar_t* str, uint32_t nr);
/**
* @method canvas_get_font_height
* 获取字体的高度。
*
* @param {canvas_t*} c canvas对象。
*
* @return {float_t} 返回字体的高度。
*/
float_t canvas_get_font_height(canvas_t* c);
/**
* @method canvas_measure_utf8
* 计算文本所占的宽度。
*
* > 供脚本语言使用。
*
* @alias canvas_measure_text
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {const char*} str 字符串。
*
* @return {float_t} 返回文本所占的宽度。
*/
float_t canvas_measure_utf8(canvas_t* c, const char* str);
/**
* @method canvas_draw_text
* 绘制文本。
*
* @param {canvas_t*} c canvas对象。
* @param {const wchar_t*} str 字符串。
* @param {uint32_t} nr 字符数。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_text(canvas_t* c, const wchar_t* str, uint32_t nr, xy_t x, xy_t y);
/**
* @method canvas_draw_utf8
* 绘制文本。
*
* > 供脚本语言使用。
*
* @alias canvas_draw_text
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {const char*} str 字符串。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_utf8(canvas_t* c, const char* str, xy_t x, xy_t y);
/**
* @method canvas_draw_text_in_rect
* 绘制文本。
*
* @param {canvas_t*} c canvas对象。
* @param {const wchar_t*} str 字符串。
* @param {uint32_t} nr 字符数。
* @param {const rect_t*} r 矩形区域。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_text_in_rect(canvas_t* c, const wchar_t* str, uint32_t nr, const rect_t* r);
/**
* @method canvas_draw_text_bidi_in_rect
* 绘制文本(支持Unicode Bidirectional Algorithm)。
*
* @param {canvas_t*} c canvas对象。
* @param {const wchar_t*} str 字符串。
* @param {uint32_t} nr 字符数。
* @param {const rect_t*} r 矩形区域。
* @param {const char*} bidi_type 类型。
* @param {bool_t} ellipses 如果目标宽度不够,是否显示省略号。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_text_bidi_in_rect(canvas_t* c, const wchar_t* str, uint32_t nr, const rect_t* r,
const char* bidi_type, bool_t ellipses);
/**
* @method canvas_draw_utf8_in_rect
* 绘制文本。
*
* > 供脚本语言使用。
*
* @alias canvas_draw_text_in_rect
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {const char*} str 字符串。
* @param {const rect_t*} r 矩形区域。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_utf8_in_rect(canvas_t* c, const char* str, const rect_t* r);
/**
* @method canvas_draw_icon
* 绘制图标。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {bitmap_t*} img 图片对象。
* @param {xy_t} cx 中心点x坐标。
* @param {xy_t} cy 中心点y坐标。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_icon(canvas_t* c, bitmap_t* img, xy_t cx, xy_t cy);
/**
* @method canvas_draw_image
* 绘制图片。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {bitmap_t*} img 图片对象。
* @param {const rect_t*} src 源区域。
* @param {const rect_t*} dst 目的区域。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_image(canvas_t* c, bitmap_t* img, const rect_t* src, const rect_t* dst);
/**
* @method canvas_draw_image_ex
* 绘制图片。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {bitmap_t*} img 图片对象。
* @param {image_draw_type_t} draw_type 绘制类型。
* @param {const rect_t*} dst 目的区域。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_image_ex(canvas_t* c, bitmap_t* img, image_draw_type_t draw_type,
const rect_t* dst);
/**
* @method canvas_draw_image_ex2
* 绘制图片。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
* @param {bitmap_t*} img 图片对象。
* @param {image_draw_type_t} draw_type 绘制类型。
* @param {const rect_t*} src 源区域。
* @param {const rect_t*} dst 目的区域。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_image_ex2(canvas_t* c, bitmap_t* img, image_draw_type_t draw_type,
const rect_t* src, const rect_t* dst);
/**
* @method canvas_get_vgcanvas
* 获取vgcanvas对象。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
*
* @return {vgcanvas_t*} 返回vgcanvas对象。
*/
vgcanvas_t* canvas_get_vgcanvas(canvas_t* c);
/**
* @method canvas_cast
* 转换为canvas对象(供脚本语言使用)。
* @annotation ["cast", "scriptable"]
* @param {canvas_t*} c canvas对象。
*
* @return {canvas_t*} canvas对象。
*/
canvas_t* canvas_cast(canvas_t* c);
/**
* @method canvas_reset
* 释放相关资源。
*
* @annotation ["scriptable"]
* @param {canvas_t*} c canvas对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_reset(canvas_t* c);
/**
* @method canvas_draw_image_at
* 在指定位置画图。
*
* @param {canvas_t*} c canvas对象。
* @param {bitmap_t*} img 图片对象。
* @param {xy_t} x x坐标。
* @param {xy_t} y w坐标。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_image_at(canvas_t* c, bitmap_t* img, xy_t x, xy_t y);
/*public for internal use*/
ret_t canvas_draw_icon_in_rect(canvas_t* c, bitmap_t* img, const rect_t* r);
ret_t canvas_draw_image_center(canvas_t* c, bitmap_t* img, const rect_t* dst);
ret_t canvas_draw_image_patch3_x(canvas_t* c, bitmap_t* img, const rect_t* dst);
ret_t canvas_draw_image_patch3_x_scale_y(canvas_t* c, bitmap_t* img, const rect_t* dst);
ret_t canvas_draw_image_patch3_y(canvas_t* c, bitmap_t* img, const rect_t* dst);
ret_t canvas_draw_image_patch3_y_scale_x(canvas_t* c, bitmap_t* img, const rect_t* dst);
ret_t canvas_draw_image_patch9(canvas_t* c, bitmap_t* img, const rect_t* dst);
ret_t canvas_draw_image_repeat(canvas_t* c, bitmap_t* img, const rect_t* dst);
ret_t canvas_draw_image_repeat_x(canvas_t* c, bitmap_t* img, const rect_t* dst);
ret_t canvas_draw_image_repeat_y(canvas_t* c, bitmap_t* img, const rect_t* dst);
ret_t canvas_draw_image_repeat_y_inverse(canvas_t* c, bitmap_t* img, const rect_t* dst_in);
ret_t canvas_draw_image_repeat9(canvas_t* c, bitmap_t* img, const rect_t* dst_in);
ret_t canvas_draw_image_repeat3_x(canvas_t* c, bitmap_t* img, const rect_t* dst_in);
ret_t canvas_draw_image_repeat3_y(canvas_t* c, bitmap_t* img, const rect_t* dst_in);
ret_t canvas_draw_image_scale(canvas_t* c, bitmap_t* img, const rect_t* dst);
ret_t canvas_draw_image_scale_w(canvas_t* c, bitmap_t* img, const rect_t* dst);
ret_t canvas_draw_image_scale_h(canvas_t* c, bitmap_t* img, const rect_t* dst);
ret_t canvas_draw_image_scale_down(canvas_t* c, bitmap_t* img, const rect_t* src,
const rect_t* dst);
/**
* @method canvas_draw_line
* 画直线。
* @param {canvas_t*} c canvas对象。
* @param {xy_t} x1 起始点的x坐标。
* @param {xy_t} y1 起始点的y坐标。
* @param {xy_t} x2 结束点的x坐标。
* @param {xy_t} y2 结束点的y坐标。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_draw_line(canvas_t* c, xy_t x1, xy_t y1, xy_t x2, xy_t y2);
ret_t canvas_draw_char(canvas_t* c, wchar_t chr, xy_t x, xy_t y);
ret_t canvas_draw_image_matrix(canvas_t* c, bitmap_t* img, matrix_t* matrix);
/**
* @method canvas_set_fps
* 设置FPS。
*
* @param {canvas_t*} c canvas对象。
* @param {bool_t} show_fps 是否显示fps。
* @param {uint32_t} fps FPS。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_fps(canvas_t* c, bool_t show_fps, uint32_t fps);
/**
* @method canvas_set_font_manager
* 设置canvas的font_manager对象。
*
* @param {canvas_t*} c canvas对象。
* @param {font_manager_t*} font_manager font_manager对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_font_manager(canvas_t* c, font_manager_t* font_manager);
/**
* @method canvas_set_assets_manager
* 设置canvas的assets_manager对象。
*
* @param {canvas_t*} c canvas对象。
* @param {assets_manager_t*} assets_manager assets_manager对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_set_assets_manager(canvas_t* c, assets_manager_t* assets_manager);
/**
* @method canvas_get_text_metrics
* 获取当前字体的度量信息。
*
* @param {canvas_t*} canvas canvas对象。
* @param {float_t*} ascent 用于返回ascent。
* @param {float_t*} descent 用于返回descent。
* @param {float_t*} line_hight 用于返回line height。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_get_text_metrics(canvas_t* canvas, float_t* ascent, float_t* descent,
float_t* line_hight);
/**
* @method canvas_begin_frame
* 绘制开始。
*
* @param {canvas_t*} c canvas对象。
* @param {const dirty_rects_t*} dirty_rects 脏矩形。
* @param {lcd_draw_mode_t} draw_mode 绘制模式。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_begin_frame(canvas_t* c, const dirty_rects_t* dirty_rects, lcd_draw_mode_t draw_mode);
/**
* @method canvas_fill_rounded_rect
* 填充区域。
* @param {canvas_t*} c canvas对象。
* @param {const rect_t*} r 矩形。
* @param {const rect_t*} bg_r 矩形(默认为 NULL当圆角直径大于 r 矩形的宽高后,会根据 bg_r 矩形来决定是否需要缩小圆角半径)。
* @param {const color_t*} color 颜色。
* @param {uint32_t} radius 圆角半径。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_fill_rounded_rect(canvas_t* c, const rect_t* r, const rect_t* bg_r,
const color_t* color, uint32_t radius);
/**
* @method canvas_fill_rounded_rect_gradient
* 填充圆角矩形区域。
* @param {canvas_t*} c canvas对象。
* @param {const rect_t*} r 矩形。
* @param {const rect_t*} bg_r 矩形(默认为 NULL当圆角直径大于 r 矩形的宽高后,会根据 bg_r 矩形来决定是否需要缩小圆角半径)。
* @param {const gradient_t*} gradient 渐变颜色。
* @param {uint32_t} radius 圆角半径。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_fill_rounded_rect_gradient(canvas_t* c, const rect_t* r, const rect_t* bg_r,
const gradient_t* gradient, uint32_t radius);
/**
* @method canvas_fill_rounded_rect_gradient_ex
* 填充圆角矩形区域。
* 半径半径小于等于2则表示该角为直角如果全部角都为直角则返回RET_FAIL。如果全是直角该函数效率没有canvas_fill_rect函数快
* 如果各个半径都不一样的话就是会使用vg如果不支持vg就会返回RET_FAIL直角的情况除外
* @param {canvas_t*} c canvas对象。
* @param {const rect_t*} r 矩形。
* @param {const rect_t*} bg_r 矩形。(默认为 NULL当圆角直径大于 r 矩形的宽高后,会根据 bg_r 矩形来决定是否需要缩小圆角半径)
* @param {const gradient_t*} gradient 渐变颜色。
* @param {uint32_t} radius_tl 左上角圆角半径。
* @param {uint32_t} radius_tr 右上角圆角半径。
* @param {uint32_t} radius_bl 左下角圆角半径。
* @param {uint32_t} radius_br 右下角圆角半径。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_fill_rounded_rect_gradient_ex(canvas_t* c, const rect_t* r, const rect_t* bg_r,
const gradient_t* gradient, uint32_t radius_tl,
uint32_t radius_tr, uint32_t radius_bl,
uint32_t radius_br);
/**
* @method canvas_fill_rounded_rect_ex
* 填充圆角矩形区域。
* 半径半径小于等于2则表示该角为直角如果全部角都为直角则返回RET_FAIL。如果全是直角该函数效率没有canvas_fill_rect函数快
* 如果各个半径都不一样的话就是会使用vg如果不支持vg就会返回RET_FAIL直角的情况除外
* @param {canvas_t*} c canvas对象。
* @param {const rect_t*} r 矩形。
* @param {const rect_t*} bg_r 矩形。(默认为 NULL当圆角直径大于 r 矩形的宽高后,会根据 bg_r 矩形来决定是否需要缩小圆角半径)
* @param {const color_t*} color 颜色。
* @param {uint32_t} radius_tl 左上角圆角半径。
* @param {uint32_t} radius_tr 右上角圆角半径。
* @param {uint32_t} radius_bl 左下角圆角半径。
* @param {uint32_t} radius_br 右下角圆角半径。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_fill_rounded_rect_ex(canvas_t* c, const rect_t* r, const rect_t* bg_r,
const color_t* color, uint32_t radius_tl, uint32_t radius_tr,
uint32_t radius_bl, uint32_t radius_br);
/**
* @method canvas_stroke_rounded_rect
* 绘制边框。
* @param {canvas_t*} c canvas对象。
* @param {const rect_t*} r 矩形。
* @param {const rect_t*} bg_r 矩形(默认为 NULL当圆角直径大于 r 矩形的宽高后,会根据 bg_r 矩形来决定是否需要缩小圆角半径)。
* @param {const color_t*} color 颜色。
* @param {uint32_t} radius 圆角半径。
* @param {uint32_t} border_width 边宽。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_stroke_rounded_rect(canvas_t* c, const rect_t* r, const rect_t* bg_r,
const color_t* color, uint32_t radius, uint32_t border_width);
/**
* @method canvas_stroke_rounded_rect_ex
* 绘制边框。
* 半径半径小于等于2则表示该角为直角如果全部角都为直角则返回RET_FAIL。如果全是直角该函数效率没有canvas_stroke_rect函数快
* 如果各个半径都不一样的话就是会使用vg如果不支持vg就会返回RET_FAIL直角的情况除外
* @param {canvas_t*} c canvas对象。
* @param {const rect_t*} r 矩形。
* @param {const rect_t*} bg_r 矩形(默认为 NULL当圆角直径大于 r 矩形的宽高后,会根据 bg_r 矩形来决定是否需要缩小圆角半径)。
* @param {const color_t*} color 颜色。
* @param {uint32_t} radius_tl 左上角圆角半径。
* @param {uint32_t} radius_tr 右上角圆角半径。
* @param {uint32_t} radius_bl 左下角圆角半径。
* @param {uint32_t} radius_br 右下角圆角半径。
* @param {uint32_t} border_width 边宽。
* @param {uint32_t} border_model 边框类型。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_stroke_rounded_rect_ex(canvas_t* c, const rect_t* r, const rect_t* bg_r,
const color_t* color, uint32_t radius_tl, uint32_t radius_tr,
uint32_t radius_bl, uint32_t radius_br, uint32_t border_width,
int32_t border_model);
/**
* @method canvas_end_frame
* 绘制结束。
*
* @param {canvas_t*} c canvas对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_end_frame(canvas_t* c);
ret_t canvas_test_paint(canvas_t* c, bool_t pressed, xy_t x, xy_t y);
/*save/restore works for awtk web only*/
ret_t canvas_save(canvas_t* c);
ret_t canvas_restore(canvas_t* c);
END_C_DECLS
#endif /*TK_CANVAS_H*/

View File

@ -0,0 +1,247 @@
/**
* File: canvas_offline.h
* Author: AWTK Develop Team
* Brief: offline canvas.
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-07-10 Luo Zhiming <luozhiming@zlg.cn> created
*
*/
#ifndef TK_CANVAS_OFFLINE_H
#define TK_CANVAS_OFFLINE_H
#include "base/system_info.h"
#include "base/font_manager.h"
#include "base/lcd.h"
BEGIN_C_DECLS
#include "base/canvas.h"
/**
* @class canvas_offline_t
* @annotation ["scriptable"]
* 离线画布 canvas。
*
*/
typedef struct _canvas_offline_t {
canvas_t base;
/**
* @property {bitmap_t*} bitmap
* @annotation ["readable"]
* 绑定的离线 bitmap
*/
bitmap_t* bitmap;
/* private */
/* 保存在线的 vg 和 canvas 的裁减区 */
rect_t vg_clip_rect;
rect_t canvas_clip_rect;
/*确保 begin_draw / end_draw 配对使用*/
int32_t begin_draw;
uint32_t lcd_w;
uint32_t lcd_h;
} canvas_offline_t;
/**
* @method canvas_offline_create
* 创建一个离线的 canvas
* 在 opengl 模式下 format 参数只能为 BITMAP_FMT_RGBA8888
* 在其他模式下,离线 canvas 格式可以为 rgbabgarbgr565和rgb565
*
* @param {uint32_t} w 离线 canvas 的宽。
* @param {uint32_t} h 离线 canvas 的高。
* @param {bitmap_format_t} format 离线 canvas 的格式。
*
* @return {canvas_t*} 成功返回 canvas ,失败返回 NULL。
*/
canvas_t* canvas_offline_create(uint32_t w, uint32_t h, bitmap_format_t format);
/**
* @method canvas_offline_clear_canvas
* 清除离线 canvas 所有数据,并把背景设置为全透明(注意:该离线 canvas 需要有透明通道)
* 该函数调用前必须要先 canvas_offline_begin_draw 函数。
* 该函数用来解决离线 canvas 多次绘图半透效果后导致半透效果无效的问题。
*
* @param {canvas_t*} canvas 离线 canvas 对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_offline_clear_canvas(canvas_t* canvas);
/**
* @method canvas_offline_begin_draw
* 设置离线 canvas 开始绘图
*
* @param {canvas_t*} canvas 离线 canvas 对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_offline_begin_draw(canvas_t* canvas);
/**
* @method canvas_offline_end_draw
* 设置离线 canvas 结束绘图
*
* @param {canvas_t*} canvas 离线 canvas 对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_offline_end_draw(canvas_t* canvas);
/**
* @method canvas_offline_get_bitmap
* 获取离线 canvas 的离线 bitmap。
*
* @param {canvas_t*} canvas 离线 canvas 对象。
*
* @return {bitmap_t*} 返回 bitmap_t 对象表示成功,返回 NULL 表示失败。
*/
bitmap_t* canvas_offline_get_bitmap(canvas_t* canvas);
/**
* @method canvas_offline_bitmap_move_to_new_bitmap
* 把离线 canvas 的离线 bitmap 移动赋值给新的 bitmap。
* 移动赋值后原来的离线 canvas 的离线 bitmap 就会被置空。
* 备注:在移动赋值之前会先调用 canvas_offline_flush_bitmap 把数据回流到内存中。
*
* @param {canvas_t*} canvas 离线 canvas 对象。
* @param {bitmap_t*} bitmap 新的 bitmap 对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_offline_bitmap_move_to_new_bitmap(canvas_t* canvas, bitmap_t* bitmap);
/**
* @method canvas_offline_flush_bitmap
* 把离线 canvas 的数据放到绑定的 bitmap 中
* 该函数只有在 opengl 模式才需要调用,是否把显存中的数据回传到内存中。
*
* @param {canvas_t*} canvas 离线 canvas 对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_offline_flush_bitmap(canvas_t* canvas);
/**
* @method canvas_offline_destroy
* 释放离线 canvas 和离线 bitmap
*
* @param {canvas_t*} canvas 离线 canvas 对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_offline_destroy(canvas_t* canvas);
/*
* WITH_CANVAS_OFFLINE_CUSTION 宏提供给用户在外部自定义离线 canvas 的机会,
* 主要是用于给用户在外部定义一些特殊的离线 canvas 使用的,而这些特殊的离线 canvas 很大概率和平台相关的,
* 所以可以通过 WITH_CANVAS_OFFLINE_CUSTION 宏来外部实现自定义离线 canvas 的效果。
*/
#ifdef WITH_CANVAS_OFFLINE_CUSTION
/**
* @method canvas_offline_custom_create
* @export none
* 用户自定义 canvas_offline_create
*
* @param {uint32_t} w 离线 canvas 的宽。
* @param {uint32_t} h 离线 canvas 的高。
* @param {bitmap_format_t} format 离线 canvas 的格式。
*
* @return {canvas_t*} 成功返回 canvas ,失败返回 NULL。
*/
canvas_t* canvas_offline_custom_create(uint32_t w, uint32_t h, bitmap_format_t format);
/**
* @method canvas_offline_custom_clear_canvas
* @export none
* 用户自定义 canvas_offline_custom_clear_canvas
*
* @param {canvas_t*} canvas 离线 canvas 对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_offline_custom_clear_canvas(canvas_t* canvas);
/**
* @method canvas_offline_custom_begin_draw
* @export none
* 用户自定义 canvas_offline_custom_begin_draw
*
* @param {canvas_t*} canvas 离线 canvas 对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_offline_custom_begin_draw(canvas_t* canvas);
/**
* @method canvas_offline_custom_end_draw
* @export none
* 用户自定义 canvas_offline_custom_end_draw
*
* @param {canvas_t*} canvas 离线 canvas 对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_offline_custom_end_draw(canvas_t* canvas);
/**
* @method canvas_offline_custom_get_bitmap
* @export none
* 用户自定义 canvas_offline_custom_get_bitmap
*
* @param {canvas_t*} canvas 离线 canvas 对象。
*
* @return {bitmap_t*} 返回 bitmap_t 对象表示成功,返回 NULL 表示失败。
*/
bitmap_t* canvas_offline_custom_get_bitmap(canvas_t* canvas);
/**
* @method canvas_offline_custom_bitmap_move_to_new_bitmap
* @export none
* 用户自定义 canvas_offline_custom_bitmap_move_to_new_bitmap
*
* @param {canvas_t*} canvas 离线 canvas 对象。
*
* @return {bitmap_t*} 返回 bitmap_t 对象表示成功,返回 NULL 表示失败。
*/
ret_t canvas_offline_custom_bitmap_move_to_new_bitmap(canvas_t* canvas, bitmap_t* bitmap);
/**
* @method canvas_offline_custom_flush_bitmap
* @export none
* 用户自定义 canvas_offline_custom_flush_bitmap
*
* @param {canvas_t*} canvas 离线 canvas 对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_offline_custom_flush_bitmap(canvas_t* canvas);
/**
* @method canvas_offline_custom_destroy
* @export none
* 用户自定义 canvas_offline_custom_destroy
*
* @param {canvas_t*} canvas 离线 canvas 对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t canvas_offline_custom_destroy(canvas_t* canvas);
#endif
END_C_DECLS
#endif /*TK_CANVAS_OFFLINE_H*/

View File

@ -0,0 +1,521 @@
/**
* File: canvas_offline.c
* Author: AWTK Develop Team
* Brief: offline canvas.
*
* Copyright (c) 2018 - 2020 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-07-10 Luo Zhiming <luozhiming@zlg.cn> created
*
*/
#include "tkc/wstr.h"
#include "tkc/mem.h"
#include "tkc/utf8.h"
#include "tkc/utils.h"
#include "base/canvas.h"
#include "base/system_info.h"
#include "widget.h"
#include "bitmap.h"
#include "native_window.h"
#include "widget_consts.h"
#include "window_manager.h"
#include "canvas_offline.h"
#include "base/vgcanvas_asset_manager.h"
#ifdef WITH_GPU
#ifdef WITHOUT_GLAD
#include <SDL.h>
#ifdef IOS
#include <OpenGLES/gltypes.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#else
#include <SDL_opengl.h>
#include <SDL_opengl_glext.h>
#endif /*IOS*/
#else
#include "glad/glad.h"
#endif /*WITHOUT_GLAD*/
#ifdef WITH_VG_GPU
#include "../blend/image_g2d.h"
#endif
typedef struct _canvas_offline_gpu_t {
canvas_offline_t base;
framebuffer_object_t* fbo;
} canvas_offline_gpu_t;
#else
#include "../blend/image_g2d.h"
#include "../lcd/lcd_mem_rgb565.h"
#include "../lcd/lcd_mem_bgr565.h"
#include "../lcd/lcd_mem_rgba8888.h"
#include "../lcd/lcd_mem_bgra8888.h"
#ifdef LINUX
#include "../lcd/lcd_mem_rgb888.h"
#include "../lcd/lcd_mem_bgr888.h"
#endif
#endif
static ret_t canvas_offline_begin_frame(canvas_t* c, const dirty_rects_t* dirty_rects, lcd_draw_mode_t draw_mode) {
ret_t ret = RET_OK;
const rect_t* dirty_rect = dirty_rects != NULL ? &(dirty_rects->max) : NULL;
ret = canvas_offline_begin_draw(c);
return_value_if_fail(ret == RET_OK, ret);
ret = canvas_set_clip_rect(c, dirty_rect);
return_value_if_fail(ret == RET_OK, ret);
return RET_OK;
}
canvas_t* canvas_offline_create(uint32_t w, uint32_t h, bitmap_format_t format) {
canvas_t* c = NULL;
native_window_t* native_window = NULL;
#ifdef WITH_GPU
ret_t ret = RET_OK;
float_t ratio = 0.0f;
vgcanvas_t* vg = NULL;
framebuffer_object_t* fbo = NULL;
canvas_offline_gpu_t* canvas = NULL;
#else
lcd_t* lcd = NULL;
uint8_t* buff = NULL;
bitmap_t* bitmap = NULL;
canvas_offline_t* canvas = NULL;
system_info_t* info = system_info();
#endif
#ifdef WITH_CANVAS_OFFLINE_CUSTION
canvas_t* custom_canvas = canvas_offline_custom_create(w, h, format);
if (custom_canvas != NULL) {
return custom_canvas;
}
#endif
#ifdef FRAGMENT_FRAME_BUFFER_SIZE
log_warn(" fragment frame buffer not supported yet\n");
return NULL;
#endif
native_window =
(native_window_t*)widget_get_prop_pointer(window_manager(), WIDGET_PROP_NATIVE_WINDOW);
return_value_if_fail(native_window != NULL, NULL);
c = native_window_get_canvas(native_window);
#ifdef WITH_GPU
#ifdef WITH_VG_GPU
// BITMAP_FMT_BGRA8888 等价于 630H的VG_sARGB_8888
if (format != BITMAP_FMT_RGBA8888 && format != BITMAP_FMT_BGRA8888 && format != BITMAP_FMT_RGB565) {
assert(!" opengl gpu only supported RGBA or BGRA or RGB565 foramt ");
log_warn(" opengl gpu only supported RGBA or BGRA or RGB565 foramt \n");
return NULL;
}
#else
if (format != BITMAP_FMT_RGBA8888) {
assert(!" opengl gpu only supported RGBA foramt ");
log_warn(" opengl gpu only supported RGBA foramt \n");
return NULL;
}
#endif
canvas = TKMEM_ZALLOC(canvas_offline_gpu_t);
return_value_if_fail(canvas != NULL, NULL);
canvas->fbo = TKMEM_ZALLOC(framebuffer_object_t);
if (canvas->fbo == NULL) {
TKMEM_FREE(canvas);
canvas = NULL;
}
return_value_if_fail(canvas != NULL, NULL);
fbo = canvas->fbo;
ratio = c->lcd->ratio;
#ifdef AWTK_WEB
canvas->base.bitmap = bitmap_create();
canvas->base.bitmap->w = w * ratio;
canvas->base.bitmap->h = h * ratio;
canvas->base.bitmap->should_free_handle = TRUE;
canvas->base.bitmap->format = BITMAP_FMT_RGBA8888;
bitmap_set_line_length(canvas->base.bitmap, 0);
#else
#ifdef WITH_VG_GPU
// VG下支持RGBA8888, ARGB8888, RGB565
canvas->base.bitmap = bitmap_create_ex(w * ratio, h * ratio, 0, format);
#else
canvas->base.bitmap = bitmap_create_ex(w * ratio, h * ratio, 0, BITMAP_FMT_RGBA8888);
#endif
#endif
canvas->base.begin_draw = 0;
canvas->base.lcd_w = c->lcd->w;
canvas->base.lcd_h = c->lcd->h;
vg = lcd_get_vgcanvas(c->lcd);
return_value_if_fail(c != NULL && vg != NULL, NULL);
canvas_init((canvas_t*)canvas, c->lcd, widget_get_font_manager(window_manager()));
canvas_set_assets_manager((canvas_t*)canvas, widget_get_assets_manager(window_manager()));
canvas_set_global_alpha((canvas_t*)canvas, 0xff);
ret = vgcanvas_create_fbo(vg, w, h, FALSE, fbo);
if (ret != RET_OK) {
assert(!" create fbo fail \n");
log_warn(" create fbo fail \n");
}
#else
(void)c;
canvas = TKMEM_ZALLOC(canvas_offline_t);
return_value_if_fail(canvas != NULL, NULL);
canvas->begin_draw = 0;
canvas->bitmap = bitmap_create_ex(w, h, 0, format);
canvas->lcd_w = info->lcd_w;
canvas->lcd_h = info->lcd_h;
bitmap = canvas->bitmap;
buff = bitmap_lock_buffer_for_write(bitmap);
return_value_if_fail(buff != NULL, NULL);
if (bitmap->format == BITMAP_FMT_RGBA8888) {
lcd = lcd_mem_rgba8888_create_single_fb(bitmap->w, bitmap->h, buff);
} else if (bitmap->format == BITMAP_FMT_BGRA8888) {
lcd = lcd_mem_bgra8888_create_single_fb(bitmap->w, bitmap->h, buff);
} else if (bitmap->format == BITMAP_FMT_BGR565) {
lcd = lcd_mem_bgr565_create_single_fb(bitmap->w, bitmap->h, buff);
} else if (bitmap->format == BITMAP_FMT_RGB565) {
lcd = lcd_mem_rgb565_create_single_fb(bitmap->w, bitmap->h, buff);
}
#ifdef LINUX
else if (bitmap->format == BITMAP_FMT_RGB888) {
lcd = lcd_mem_rgb888_create_single_fb(bitmap->w, bitmap->h, buff);
} else if (bitmap->format == BITMAP_FMT_BGR888) {
lcd = lcd_mem_bgr888_create_single_fb(bitmap->w, bitmap->h, buff);
}
#endif
else {
assert(!" bitmap format not supported yet \n");
log_warn(" bitmap format not supported yet \n");
}
bitmap_unlock_buffer(bitmap);
if (lcd != NULL) {
canvas_t* c_tmp = NULL;
c_tmp = canvas_init(&(canvas->base), lcd, widget_get_font_manager(window_manager()));
canvas_set_assets_manager(c_tmp, widget_get_assets_manager(window_manager()));
canvas_set_global_alpha(&(canvas->base), 0xff);
canvas_begin_frame(c_tmp, NULL, LCD_DRAW_OFFLINE);
} else {
TKMEM_FREE(canvas);
return NULL;
}
#endif
((canvas_t*)canvas)->end_frame = canvas_offline_end_draw;
((canvas_t*)canvas)->begin_frame = canvas_offline_begin_frame;
return (canvas_t*)canvas;
}
#ifdef AWTK_WEB
ret_t canvas_offline_clear_canvas(canvas_t* canvas) {
#ifdef WITH_CANVAS_OFFLINE_CUSTION
if (canvas_offline_custom_clear_canvas(canvas) == RET_OK) {
return RET_OK;
}
#endif
log_warn("canvas_offline_clear_canvas funtion do not supported web ~! \r\n");
return RET_FAIL;
}
#else
ret_t canvas_offline_clear_canvas(canvas_t* canvas) {
#ifndef WITH_NANOVG_GPU
rect_t rect;
canvas_offline_t* canvas_offline = NULL;
#endif
return_value_if_fail(canvas != NULL, RET_BAD_PARAMS);
#ifdef WITH_CANVAS_OFFLINE_CUSTION
if (canvas_offline_custom_clear_canvas(canvas) == RET_OK) {
return RET_OK;
}
#endif
#ifdef WITH_NANOVG_GPU
glEnable(GL_SCISSOR_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
#elif defined(WITH_VG_GPU)
canvas_offline = (canvas_offline_t*)canvas;
rect = rect_init(0, 0, canvas_offline->bitmap->w, canvas_offline->bitmap->h);
image_clear(canvas_offline->bitmap, &rect, color_init(0x0, 0x0, 0x0, 0x0));
#else
canvas_offline = (canvas_offline_t*)canvas;
rect = rect_init(0, 0, canvas_offline->bitmap->w, canvas_offline->bitmap->h);
image_clear(canvas_offline->bitmap, &rect, color_init(0x0, 0x0, 0x0, 0x0));
#endif
return RET_OK;
}
#endif
ret_t canvas_offline_begin_draw(canvas_t* canvas) {
vgcanvas_t* vg = NULL;
canvas_offline_t* canvas_offline = NULL;
#ifdef WITH_GPU
canvas_offline_gpu_t* c = NULL;
#endif
#ifdef WITH_CANVAS_OFFLINE_CUSTION
ret_t ret = canvas_offline_custom_begin_draw(canvas);
if (ret == RET_OK) {
return ret;
}
#endif
return_value_if_fail(canvas != NULL, RET_BAD_PARAMS);
vg = lcd_get_vgcanvas(canvas->lcd);
canvas_offline = (canvas_offline_t*)canvas;
#ifdef WITH_GPU
c = (canvas_offline_gpu_t*)canvas;
if (vg != NULL && canvas_offline->begin_draw == 0) {
canvas_get_clip_rect(canvas, &canvas_offline->canvas_clip_rect);
canvas_offline->vg_clip_rect = rect_from_rectf(vgcanvas_get_clip_rect(vg));
c->base.lcd_w = canvas->lcd->w;
c->base.lcd_h = canvas->lcd->h;
vgcanvas_flush(vg);
vgcanvas_bind_fbo(vg, c->fbo);
vgcanvas_save(vg);
canvas->lcd->w = vg->w = canvas_offline->bitmap->w;
canvas->lcd->h = vg->h = canvas_offline->bitmap->h;
canvas_set_clip_rect(canvas, NULL);
}
#else
if (canvas_offline->begin_draw == 0) {
canvas_get_clip_rect(canvas, &canvas_offline->canvas_clip_rect);
if (vg != NULL) {
canvas_offline->vg_clip_rect =
rect_init(vg->clip_rect.x, vg->clip_rect.y, vg->clip_rect.w, vg->clip_rect.h);
vgcanvas_save(vg);
vgcanvas_reset_curr_state(vg);
vgcanvas_clip_rect(vg, 0, 0, vg->w, vg->h);
}
canvas_set_clip_rect(canvas, NULL);
}
#endif
canvas_offline->begin_draw++;
return RET_OK;
}
ret_t canvas_offline_end_draw(canvas_t* canvas) {
vgcanvas_t* vg = NULL;
canvas_offline_t* canvas_offline = NULL;
#ifdef WITH_GPU
canvas_offline_gpu_t* c = NULL;
#endif
#ifdef WITH_CANVAS_OFFLINE_CUSTION
ret_t ret = canvas_offline_custom_end_draw(canvas);
if (ret == RET_OK) {
return ret;
}
#endif
return_value_if_fail(canvas != NULL, RET_BAD_PARAMS);
vg = lcd_get_vgcanvas(canvas->lcd);
canvas_offline = (canvas_offline_t*)canvas;
canvas_offline->begin_draw--;
#ifdef WITH_GPU
c = (canvas_offline_gpu_t*)canvas;
if (vg != NULL && canvas_offline->begin_draw == 0) {
uint16_t flag = BITMAP_FLAG_CHANGED;
canvas->lcd->w = vg->w = c->base.lcd_w;
canvas->lcd->h = vg->h = c->base.lcd_h;
vgcanvas_restore(vg);
vgcanvas_unbind_fbo(vg, c->fbo);
c->base.bitmap->flags &= (~flag);
c->base.bitmap->flags |= BITMAP_FLAG_TEXTURE;
vgcanvas_asset_manager_add_image(vgcanvas_asset_manager(), vg, c->base.bitmap, tk_pointer_from_int(c->fbo->id));
canvas_set_clip_rect(canvas, &canvas_offline->canvas_clip_rect);
}
#else
if (canvas_offline->begin_draw == 0) {
canvas_set_clip_rect(canvas, &canvas_offline->canvas_clip_rect);
if (vg != NULL) {
vgcanvas_clip_rect(vg, canvas_offline->vg_clip_rect.x, canvas_offline->vg_clip_rect.y,
canvas_offline->vg_clip_rect.w, canvas_offline->vg_clip_rect.h);
vgcanvas_restore(vg);
}
}
#endif
return RET_OK;
}
bitmap_t* canvas_offline_get_bitmap(canvas_t* canvas) {
canvas_offline_t* c = (canvas_offline_t*)canvas;
#ifdef WITH_CANVAS_OFFLINE_CUSTION
bitmap_t* bitmap = canvas_offline_custom_get_bitmap(canvas);
if (bitmap != NULL) {
return bitmap;
}
#endif
return_value_if_fail(canvas != NULL && c != NULL, NULL);
return c->bitmap;
}
#ifdef AWTK_WEB
typedef struct _web_bitmap_ctx_t {
vgcanvas_t* vg;
framebuffer_object_t* fbo;
} web_bitmap_ctx_t;
static ret_t canvas_offline_web_bitmap_destroy(bitmap_t* img) {
web_bitmap_ctx_t* ctx = (web_bitmap_ctx_t*)(img->specific_ctx);
vgcanvas_destroy_fbo(ctx->vg, ctx->fbo);
TKMEM_FREE(ctx->fbo);
TKMEM_FREE(ctx);
return RET_OK;
}
#endif
ret_t canvas_offline_bitmap_move_to_new_bitmap(canvas_t* canvas, bitmap_t* bitmap) {
bool_t should_free_handle;
bitmap_t* canvas_bitmap = NULL;
#ifdef AWTK_WEB
web_bitmap_ctx_t* ctx = TKMEM_ZALLOC(web_bitmap_ctx_t);
return_value_if_fail(ctx != NULL, RET_OOM);
#endif
return_value_if_fail(canvas != NULL && bitmap != NULL, RET_BAD_PARAMS);
#ifdef WITH_CANVAS_OFFLINE_CUSTION
if (canvas_offline_custom_bitmap_move_to_new_bitmap(canvas, bitmap) == RET_OK) {
return RET_OK;
}
#endif
canvas_offline_flush_bitmap(canvas);
should_free_handle = bitmap->should_free_handle;
canvas_bitmap = ((canvas_offline_t*)canvas)->bitmap;
memcpy(bitmap, canvas_bitmap, sizeof(bitmap_t));
bitmap->should_free_handle = should_free_handle;
#ifdef AWTK_WEB
ctx->vg = canvas_get_vgcanvas(canvas);
ctx->fbo = ((canvas_offline_gpu_t*)canvas)->fbo;
((canvas_offline_gpu_t*)canvas)->fbo = NULL;
vgcanvas_asset_manager_remove_image(vgcanvas_asset_manager(), lcd_get_vgcanvas(canvas->lcd), canvas_bitmap);
bitmap->specific_ctx = ctx;
bitmap->image_manager = image_manager();
bitmap->specific_destroy = canvas_offline_web_bitmap_destroy;
#elif defined(WITH_GPU)
vgcanvas_asset_manager_remove_image(vgcanvas_asset_manager(), lcd_get_vgcanvas(canvas->lcd), canvas_bitmap);
bitmap->specific = NULL;
bitmap->specific_destroy = NULL;
bitmap->image_manager = image_manager();
#endif
bitmap->flags = BITMAP_FLAG_IMMUTABLE;
((canvas_offline_t*)canvas)->bitmap = NULL;
TKMEM_FREE(canvas_bitmap);
return RET_OK;
}
ret_t canvas_offline_flush_bitmap(canvas_t* canvas) {
#ifdef WITH_GPU
rect_t r;
vgcanvas_t* vg = NULL;
canvas_offline_gpu_t* c = (canvas_offline_gpu_t*)canvas;
#endif
return_value_if_fail(canvas != NULL, RET_BAD_PARAMS);
#ifdef WITH_CANVAS_OFFLINE_CUSTION
if (canvas_offline_custom_flush_bitmap(canvas) == RET_OK) {
return RET_OK;
}
#endif
#ifdef WITH_GPU
vg = lcd_get_vgcanvas(canvas->lcd);
if (vg != NULL && c->fbo != NULL) {
c = (canvas_offline_gpu_t*)canvas;
r = rect_init(0, 0, c->base.bitmap->w, c->base.bitmap->h);
vgcanvas_fbo_to_bitmap(vg, c->fbo, c->base.bitmap, &r);
/* 不能把数据回流到 GPU 中,因为 fbo 颜色数据是预乘数据和垂直翻转的数据 */
// c->base.bitmap->flags |= BITMAP_FLAG_CHANGED;
}
#endif
return RET_OK;
}
ret_t canvas_offline_destroy(canvas_t* canvas) {
bitmap_t* bitmap = NULL;
#ifdef WITH_GPU
vgcanvas_t* vg = NULL;
framebuffer_object_t* fbo = NULL;
#else
system_info_t* info = system_info();
#endif
return_value_if_fail(canvas != NULL, RET_BAD_PARAMS);
#ifdef WITH_CANVAS_OFFLINE_CUSTION
if (canvas_offline_custom_destroy(canvas) == RET_OK) {
return RET_OK;
}
#endif
bitmap = ((canvas_offline_t*)canvas)->bitmap;
#ifdef WITH_GPU
vg = lcd_get_vgcanvas(canvas->lcd);
fbo = ((canvas_offline_gpu_t*)canvas)->fbo;
if (fbo != NULL) {
vgcanvas_destroy_fbo(vg, fbo);
TKMEM_FREE(fbo);
}
#else
system_info_set_lcd_w(info, ((canvas_offline_t*)canvas)->lcd_w);
system_info_set_lcd_h(info, ((canvas_offline_t*)canvas)->lcd_h);
lcd_destroy(canvas->lcd);
#endif
if (bitmap != NULL) {
bitmap_destroy(bitmap);
}
canvas_reset(canvas);
TKMEM_FREE(canvas);
return RET_OK;
}

View File

@ -0,0 +1,128 @@
/**
* File: children_layouter.c
* Author: AWTK Develop Team
* Brief: children layouter
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-12-16 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "base/children_layouter.h"
const char* children_layouter_to_string(children_layouter_t* layouter) {
if (layouter == NULL) {
return NULL;
}
return_value_if_fail(layouter->vt != NULL && layouter->vt->to_string != NULL, NULL);
return layouter->vt->to_string(layouter);
}
ret_t children_layouter_layout(children_layouter_t* layouter, widget_t* widget) {
if (layouter == NULL) {
return RET_FAIL;
}
return_value_if_fail(widget != NULL, RET_FAIL);
return_value_if_fail(layouter->vt != NULL && layouter->vt->layout != NULL, RET_FAIL);
return layouter->vt->layout(layouter, widget);
}
ret_t children_layouter_get_param(children_layouter_t* layouter, const char* name, value_t* v) {
if (layouter == NULL) {
return RET_FAIL;
}
return_value_if_fail(name != NULL && v != NULL, RET_FAIL);
return_value_if_fail(layouter->vt != NULL && layouter->vt->get_param != NULL, RET_FAIL);
return layouter->vt->get_param(layouter, name, v);
}
ret_t children_layouter_set_param(children_layouter_t* layouter, const char* name,
const value_t* v) {
if (layouter == NULL) {
return RET_FAIL;
}
return_value_if_fail(name != NULL && v != NULL, RET_FAIL);
return_value_if_fail(layouter->vt != NULL && layouter->vt->set_param != NULL, RET_FAIL);
return layouter->vt->set_param(layouter, name, v);
}
ret_t children_layouter_set_param_str(children_layouter_t* layouter, const char* name,
const char* value) {
value_t v;
value_set_str(&v, value);
return children_layouter_set_param(layouter, name, &v);
}
float_t children_layouter_get_param_float(children_layouter_t* layouter, const char* name,
float_t defval) {
value_t v;
if (children_layouter_get_param(layouter, name, &v) == RET_OK) {
return value_float(&v);
} else {
return defval;
}
}
int32_t children_layouter_get_param_int(children_layouter_t* layouter, const char* name,
int32_t defval) {
value_t v;
if (children_layouter_get_param(layouter, name, &v) == RET_OK) {
return value_int(&v);
} else {
return defval;
}
}
bool_t children_layouter_is_valid(children_layouter_t* layouter) {
if (layouter == NULL) {
return FALSE;
}
return_value_if_fail(layouter->vt != NULL && layouter->vt->is_valid != NULL, FALSE);
return layouter->vt->is_valid(layouter);
}
ret_t children_layouter_destroy(children_layouter_t* layouter) {
if (layouter == NULL) {
return RET_OK;
}
return_value_if_fail(layouter->vt != NULL && layouter->vt->destroy != NULL, RET_OK);
return layouter->vt->destroy(layouter);
}
children_layouter_t* children_layouter_clone(children_layouter_t* layouter) {
if (layouter != NULL && layouter->vt != NULL && layouter->vt->clone != NULL) {
return layouter->vt->clone(layouter);
}
return NULL;
}
#ifdef WITHOUT_LAYOUTER
children_layouter_t* children_layouter_create(const char* params) {
return NULL;
}
#endif /*WITHOUT_LAYOUTER*/

View File

@ -0,0 +1,192 @@
/**
* File: children_layouter.h
* Author: AWTK Develop Team
* Brief: children layouter
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-12-16 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_CHILDREN_LAYOUTER_H
#define TK_CHILDREN_LAYOUTER_H
#include "tkc/str.h"
#include "tkc/value.h"
#include "base/types_def.h"
BEGIN_C_DECLS
struct _children_layouter_t;
typedef struct _children_layouter_t children_layouter_t;
typedef const char* (*children_layouter_to_string_t)(children_layouter_t* layouter);
typedef ret_t (*children_layouter_layout_t)(children_layouter_t* layouter, widget_t* widget);
typedef ret_t (*children_layouter_get_param_t)(children_layouter_t* layouter, const char* name,
value_t* v);
typedef ret_t (*children_layouter_set_param_t)(children_layouter_t* layouter, const char* name,
const value_t* v);
typedef bool_t (*children_layouter_is_valid_t)(children_layouter_t* layouter);
typedef ret_t (*children_layouter_destroy_t)(children_layouter_t* layouter);
typedef children_layouter_t* (*children_layouter_create_t)(void);
typedef children_layouter_t* (*children_layouter_clone_t)(children_layouter_t* layouter);
typedef struct _children_layouter_vtable_t {
const char* type;
children_layouter_to_string_t to_string;
children_layouter_layout_t layout;
children_layouter_is_valid_t is_valid;
children_layouter_get_param_t get_param;
children_layouter_set_param_t set_param;
children_layouter_clone_t clone;
children_layouter_destroy_t destroy;
} children_layouter_vtable_t;
/**
* @class children_layouter_t
* 子控件排版布局器的接口。
*
* 按特定算法对子控件进行排版布局子类需要实现vtable中的函数。
*
*/
struct _children_layouter_t {
str_t params;
const children_layouter_vtable_t* vt;
};
/**
* @method children_layouter_to_string
* 获取全部参数。
* @param {children_layouter_t*} layouter layouter对象。
*
* @return {ret_t} 返回字符串格式的参数。
*/
const char* children_layouter_to_string(children_layouter_t* layouter);
/**
* @method children_layouter_layout
* 对控件的子控件进行布局。
*
* @param {children_layouter_t*} layouter layouter对象。
* @param {widget_t*} widget 控件。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t children_layouter_layout(children_layouter_t* layouter, widget_t* widget);
/**
* @method children_layouter_get_param
* 获取指定的参数。
*
* @param {children_layouter_t*} layouter layouter对象。
* @param {const char*} name 参数名。
* @param {value_t*} v 返回参数的值。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t children_layouter_get_param(children_layouter_t* layouter, const char* name, value_t* v);
/**
* @method children_layouter_set_param
* 获取指定的参数。
*
* @param {children_layouter_t*} layouter layouter对象。
* @param {const char*} name 参数名。
* @param {const value_t*} v 参数的值。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t children_layouter_set_param(children_layouter_t* layouter, const char* name,
const value_t* v);
/**
* @method children_layouter_set_param_str
* 设置字符串格式的参数。
*
* @param {children_layouter_t*} layouter layouter对象。
* @param {const char*} name 参数名。
* @param {const char*} value 参数值。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t children_layouter_set_param_str(children_layouter_t* layouter, const char* name,
const char* value);
/**
* @method children_layouter_get_param_float
* 获取指定的浮点格式的参数。
*
* @param {children_layouter_t*} layouter layouter对象。
* @param {const char*} name 参数名。
* @param {float_t} defval 缺省值。
*
* @return {ret_t} 成功返回参数的值,失败返回缺省值。
*/
float_t children_layouter_get_param_float(children_layouter_t* layouter, const char* name,
float_t defval);
/**
* @method children_layouter_get_param_int
* 获取指定的整数格式的参数。
*
* @param {children_layouter_t*} layouter layouter对象。
* @param {const char*} name 参数名。
* @param {int32_t} defval 缺省值。
*
* @return {ret_t} 成功返回参数的值,失败返回缺省值。
*/
int32_t children_layouter_get_param_int(children_layouter_t* layouter, const char* name,
int32_t defval);
/**
* @method children_layouter_is_valid
* 判断layouter对象是否有效。
*
* @param {children_layouter_t*} layouter layouter对象。
*
* @return {bool_t} 返回TRUE表示有效否则表示无效。
*/
bool_t children_layouter_is_valid(children_layouter_t* layouter);
/**
* @method children_layouter_destroy
* 销毁layouter对象。
*
* @param {children_layouter_t*} layouter layouter对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t children_layouter_destroy(children_layouter_t* layouter);
/**
* @method children_layouter_create
* 创建layouter对象。
* @param {const char*} params 参数。
*
* @return {children_layouter_t*} 返回layouter对象。
*/
children_layouter_t* children_layouter_create(const char* params);
/**
* @method children_layouter_clone
* 克隆layouter对象。
* @param {children_layouter_t*} layouter 被克隆的对象。
*
* @return {children_layouter_t*} 返回layouter对象。
*/
children_layouter_t* children_layouter_clone(children_layouter_t* layouter);
END_C_DECLS
#endif /*TK_CHILDREN_LAYOUTER_H*/

View File

@ -0,0 +1,114 @@
/**
* File: children_layouter_factory.c
* Author: AWTK Develop Team
* Brief: children layouter factory
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2019-03-27 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/enums.h"
#include "tkc/easing.h"
#include "base/window_manager.h"
#include "tkc/func_call_parser.h"
#include "base/children_layouter_factory.h"
static children_layouter_factory_t* children_layouter_factory_init(
children_layouter_factory_t* factory);
static ret_t children_layouter_factory_deinit(children_layouter_factory_t* factory);
static children_layouter_factory_t* s_children_layouter_factory = NULL;
typedef struct _creator_item_t {
char type[TK_NAME_LEN + 1];
children_layouter_create_t create;
} creator_item_t;
static int32_t creator_item_cmp(const creator_item_t* iter, const char* type) {
return strcmp(iter->type, type);
}
children_layouter_factory_t* children_layouter_factory(void) {
return s_children_layouter_factory;
}
children_layouter_factory_t* children_layouter_factory_create(void) {
children_layouter_factory_t* factory = TKMEM_ZALLOC(children_layouter_factory_t);
return_value_if_fail(factory != NULL, NULL);
return children_layouter_factory_init(factory);
}
static children_layouter_factory_t* children_layouter_factory_init(
children_layouter_factory_t* factory) {
return_value_if_fail(factory != NULL, NULL);
darray_init(&(factory->creators), 0, default_destroy, (tk_compare_t)creator_item_cmp);
return factory;
}
ret_t children_layouter_factory_register(children_layouter_factory_t* factory, const char* type,
children_layouter_create_t create) {
creator_item_t* item = NULL;
return_value_if_fail(factory != NULL && type != NULL && create != NULL, RET_BAD_PARAMS);
item = TKMEM_ZALLOC(creator_item_t);
return_value_if_fail(item != NULL, RET_OOM);
item->create = create;
tk_strncpy(item->type, type, TK_NAME_LEN);
darray_push(&(factory->creators), item);
return RET_OK;
}
children_layouter_t* children_layouter_factory_create_layouter(children_layouter_factory_t* factory,
const char* type) {
const creator_item_t* iter = NULL;
return_value_if_fail(factory != NULL && type != NULL, NULL);
iter = darray_find(&(factory->creators), (void*)type);
if (iter != NULL) {
return iter->create();
}
return NULL;
}
ret_t children_layouter_factory_set(children_layouter_factory_t* factory) {
s_children_layouter_factory = factory;
return RET_OK;
}
static ret_t children_layouter_factory_deinit(children_layouter_factory_t* factory) {
return_value_if_fail(factory != NULL, RET_BAD_PARAMS);
darray_deinit(&(factory->creators));
return RET_OK;
}
ret_t children_layouter_factory_destroy(children_layouter_factory_t* factory) {
return_value_if_fail(factory != NULL, RET_BAD_PARAMS);
children_layouter_factory_deinit(factory);
TKMEM_FREE(factory);
return RET_OK;
}

View File

@ -0,0 +1,100 @@
/**
* File: children_layouter_factory.h
* Author: AWTK Develop Team
* Brief: children layouter factory
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-03-27 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_CHILDREN_LAYOUTER_FACTORY_H
#define TK_CHILDREN_LAYOUTER_FACTORY_H
#include "tkc/darray.h"
#include "base/children_layouter.h"
BEGIN_C_DECLS
/**
* @class children_layouter_factory_t
* 子控件布局算法工厂。
*
*/
typedef struct _children_layouter_factory_t {
/*private*/
darray_t creators;
} children_layouter_factory_t;
/**
* @method children_layouter_factory
* 获取缺省的子控件布局算法工厂对象。
* @annotation ["constructor"]
* @return {children_layouter_factory_t*} 返回子控件布局算法工厂对象。
*/
children_layouter_factory_t* children_layouter_factory(void);
/**
* @method children_layouter_factory_set
* 设置缺省的子控件布局算法工厂对象。
* @param {children_layouter_factory_t*} factory 子控件布局算法工厂对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t children_layouter_factory_set(children_layouter_factory_t* factory);
/**
* @method children_layouter_factory_create
* 创建子控件布局算法工厂对象。
* @annotation ["constructor"]
*
* @return {children_layouter_factory_t*} 返回子控件布局算法工厂对象。
*/
children_layouter_factory_t* children_layouter_factory_create(void);
/**
* @method children_layouter_factory_register
* 注册子控件布局算法创建函数。
* @param {children_layouter_factory_t*} factory layouter工厂对象。
* @param {const char*} type 子控件布局算法类型。
* @param {children_layouter_create_t} create 子控件布局算法创建函数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t children_layouter_factory_register(children_layouter_factory_t* factory, const char* type,
children_layouter_create_t create);
/**
* @method children_layouter_factory_create_layouter
* 创建指定类型的子控件布局算法对象。
* @annotation ["constructor"]
* @param {children_layouter_factory_t*} factory 子控件布局算法工厂对象。
* @param {const char*} type 类型。
*
* @return {children_layouter_t*} 返回子控件布局算法对象。
*/
children_layouter_t* children_layouter_factory_create_layouter(children_layouter_factory_t* factory,
const char* type);
/**
* @method children_layouter_factory_destroy
* 析构并释放子控件布局算法工厂对象。
* @param {children_layouter_factory_t*} factory 子控件布局算法工厂对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t children_layouter_factory_destroy(children_layouter_factory_t* factory);
END_C_DECLS
#endif /*TK_CHILDREN_LAYOUTER_FACTORY_H*/

View File

@ -0,0 +1,83 @@
/**
* File: clip_board.h
* Author: AWTK Develop Team
* Brief: clip_board interface
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-11-21 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "base/clip_board.h"
static clip_board_t* s_clip_board = NULL;
clip_board_t* clip_board(void) {
return s_clip_board;
}
ret_t clip_board_set(clip_board_t* cl) {
s_clip_board = cl;
return RET_OK;
}
ret_t clip_board_clear(clip_board_t* cl) {
return_value_if_fail(cl != NULL && cl->vt->clear != NULL, RET_BAD_PARAMS);
return cl->vt->clear(cl);
}
ret_t clip_board_set_data(clip_board_t* cl, clip_board_data_type_t type, const void* data,
uint32_t size) {
return_value_if_fail(cl != NULL && cl->vt->set_data != NULL && data != NULL, RET_BAD_PARAMS);
return cl->vt->set_data(cl, type, data, size);
}
ret_t clip_board_get_data(clip_board_t* cl, clip_board_data_type_t* type, const void** data,
uint32_t* size) {
return_value_if_fail(cl != NULL && cl->vt->get_data != NULL, RET_BAD_PARAMS);
return cl->vt->get_data(cl, type, data, size);
}
ret_t clip_board_destroy(clip_board_t* cl) {
if (cl != NULL && cl->vt->destroy != NULL) {
cl->vt->destroy(cl);
}
return RET_OK;
}
ret_t clip_board_set_text(const char* text) {
return_value_if_fail(text != NULL && s_clip_board != NULL, RET_BAD_PARAMS);
return clip_board_set_data(s_clip_board, CLIP_BOARD_DATA_TYPE_TEXT, text, strlen(text));
}
const char* clip_board_get_text(void) {
uint32_t size = 0;
const void* data = NULL;
clip_board_data_type_t type = CLIP_BOARD_DATA_TYPE_NONE;
return_value_if_fail(s_clip_board != NULL, "");
return_value_if_fail(clip_board_get_data(s_clip_board, &type, &data, &size) == RET_OK, "");
if (type == CLIP_BOARD_DATA_TYPE_TEXT) {
return (const char*)data;
}
return "";
}

View File

@ -0,0 +1,159 @@
/**
* File: clip_board.h
* Author: AWTK Develop Team
* Brief: clip_board interface
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-11-21 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_CLIP_BOARD_H
#define TK_CLIP_BOARD_H
#include "base/types_def.h"
BEGIN_C_DECLS
struct _clip_board_t;
typedef struct _clip_board_t clip_board_t;
/**
* @enum clip_board_data_type_t
* @annotation ["scriptable"]
* @prefix CLIP_BOARD_DATA_TYPE_
* 剪切板数据类型定义。
*/
typedef enum _clip_board_data_type_t {
/**
* @const CLIP_BOARD_DATA_TYPE_NONE
* 无数据。
*/
CLIP_BOARD_DATA_TYPE_NONE,
/**
* @const CLIP_BOARD_DATA_TYPE_TEXT
* UTF8文本。
*/
CLIP_BOARD_DATA_TYPE_TEXT
} clip_board_data_type_t;
typedef ret_t (*clip_board_clear_t)(clip_board_t* cl);
typedef ret_t (*clip_board_get_data_t)(clip_board_t* cl, clip_board_data_type_t* type,
const void** data, uint32_t* size);
typedef ret_t (*clip_board_set_data_t)(clip_board_t* cl, clip_board_data_type_t type,
const void* data, uint32_t size);
typedef ret_t (*clip_board_destroy_t)(clip_board_t* cl);
typedef struct _clip_board_vtable_t {
clip_board_clear_t clear;
clip_board_get_data_t get_data;
clip_board_set_data_t set_data;
clip_board_destroy_t destroy;
} clip_board_vtable_t;
/**
* @class clip_board_t
* @annotation ["scriptable"]
* 剪切板接口。
*/
struct _clip_board_t {
const clip_board_vtable_t* vt;
};
/**
* @method clip_board
* 获取缺省的剪切板对象。
* @alias clip_board_instance
* @annotation ["constructor"]
*
* @return {ret_t} 返回缺省剪切板对象。
*/
clip_board_t* clip_board(void);
/**
* @method clip_board_set
* 设置缺省的剪切板对象。
* @param {clip_board_t*} cl 剪切板对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t clip_board_set(clip_board_t* cl);
/**
* @method clip_board_clear
* 清空剪切板中的数据。
* @param {clip_board_t*} cl 剪切板对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t clip_board_clear(clip_board_t* cl);
/**
* @method clip_board_set_data
* 设置数据到剪切板中。
* @param {clip_board_t*} cl 剪切板对象。
* @param {clip_board_data_type_t} type 数据类型。
* @param {const void* data} data 数据。
* @param {uint32_t} size 数据长度
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t clip_board_set_data(clip_board_t* cl, clip_board_data_type_t type, const void* data,
uint32_t size);
/**
* @method clip_board_get_data
* 从剪切板中获取数据。
* @param {clip_board_t*} cl 剪切板对象。
* @param {clip_board_data_type_t*} type 返回数据类型(可为NULL)。
* @param {void** data} data 返回数据(可为NULL)。
* @param {uint32_t*} size 返回数据长度(可为NULL)。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t clip_board_get_data(clip_board_t* cl, clip_board_data_type_t* type, const void** data,
uint32_t* size);
/**
* @method clip_board_destroy
* 销毁剪切板对象。
* @param {clip_board_t*} cl 剪切板对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t clip_board_destroy(clip_board_t* cl);
/**
* @method clip_board_set_text
* 设置文本(UTF8)数据到剪切板。
* @annotation ["static", "scriptable"]
* @param {const char*} text 文本。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t clip_board_set_text(const char* text);
/**
* @method clip_board_get_text
* 从剪切板中获取文本(UTF8)数据。
* @annotation ["static", "scriptable"]
*
* @return {const char*} 返回文本数据。
*/
const char* clip_board_get_text(void);
END_C_DECLS
#endif /*TK_CLIP_BOARD_H*/

View File

@ -0,0 +1,114 @@
/**
* File: data_reader.c
* Author: AWTK Develop Team
* Brief: data_reader asset
*
* Copyright (c) 2020 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License asset for more details.
*
*/
/**
* History:
* ================================================================
* 2020-06-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "tkc/asset_info.h"
#include "base/enums.h"
#include "base/assets_manager.h"
#include "base/data_reader_asset.h"
typedef struct _data_reader_asset_t {
data_reader_t data_reader;
const asset_info_t* info;
} data_reader_asset_t;
static int32_t data_reader_asset_read(data_reader_t* reader, uint64_t offset, void* data,
uint32_t size) {
const void* src = NULL;
uint32_t max_size = 0;
data_reader_asset_t* asset = (data_reader_asset_t*)reader;
return_value_if_fail(asset != NULL && asset->info != NULL, 0);
return_value_if_fail(offset < asset->info->size, 0);
src = asset->info->data + offset;
max_size = asset->info->size - offset;
size = tk_min(size, max_size);
memcpy(data, src, size);
return size;
}
static uint64_t data_reader_asset_get_size(data_reader_t* reader) {
data_reader_asset_t* asset = (data_reader_asset_t*)reader;
return_value_if_fail(asset != NULL && asset->info != NULL, 0);
return asset->info->size;
}
static ret_t data_reader_asset_destroy(data_reader_t* reader) {
data_reader_asset_t* asset = (data_reader_asset_t*)reader;
assets_manager_unref(assets_manager(), (asset_info_t*)(asset->info));
TKMEM_FREE(asset);
return RET_OK;
}
static data_reader_vtable_t s_data_reader_asset_vtable = {
.read = data_reader_asset_read,
.get_size = data_reader_asset_get_size,
.destroy = data_reader_asset_destroy,
};
data_reader_t* data_reader_asset_create(const char* assetname) {
const char* p = NULL;
char type[TK_NAME_LEN + 1];
data_reader_asset_t* asset = NULL;
const key_type_value_t* kv = NULL;
assets_manager_t* am = assets_manager();
return_value_if_fail(assetname != NULL, NULL);
asset = TKMEM_ZALLOC(data_reader_asset_t);
return_value_if_fail(asset != NULL && am != NULL, NULL);
p = strchr(assetname, '/');
if (p != NULL) {
tk_strncpy_s(type, sizeof(type), assetname, p - assetname);
assetname = p + 1;
} else {
strcpy(type, "data");
}
kv = asset_type_find(type);
return_value_if_fail(kv != NULL, NULL);
asset->data_reader.vt = &s_data_reader_asset_vtable;
asset->info = assets_manager_ref(am, (asset_type_t)(kv->value), assetname);
if (asset->info == NULL) {
TKMEM_FREE(asset);
}
return (data_reader_t*)asset;
}
const char* data_reader_asset_build_url(const char* name, asset_type_t type,
char url[MAX_PATH + 1]) {
const key_type_value_t* kv = asset_type_find_by_value(type);
return_value_if_fail(kv != NULL && name != NULL, NULL);
tk_snprintf(url, MAX_PATH, "asset://%s/%s", kv->name, name);
return url;
}

View File

@ -0,0 +1,70 @@
/**
* File: data_reader_asset.h
* Author: AWTK Develop Team
* Brief: data_reader asset
*
* Copyright (c) 2020 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License asset for more details.
*
*/
/**
* History:
* ================================================================
* 2020-06-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_DATA_READER_ASSET_H
#define TK_DATA_READER_ASSET_H
#include "tkc/asset_info.h"
#include "tkc/data_reader.h"
BEGIN_C_DECLS
/**
* @class data_reader_asset_t
* @parent data_reader_t
* @annotation ["fake"]
* 基于资源实现的 data_reader。通过 data_reader_factory 创建 reader 时URL的格式如下(请用函数data_reader_asset_build_url生成)
*
* ```
* asset://type/name
* ```
*/
/**
* @method data_reader_asset_create
* 创建基于asset的data reader。
*
* > 不要直接调用,而是注册到 data\_reader\_factory后通过data\_reader\_factory调用。
* @annotation ["constructor"]
* @param {const char*} assetname 资源的名称。
*
* @return {data_reader_t*} 返回data reader对象。
*/
data_reader_t* data_reader_asset_create(const char* assetname);
/**
* @method data_reader_asset_build_url
* 构造内存URL。
* @annotation ["static"]
*
* @param {const char*} name 资源的名称。
* @param {asset_type_t} type 资源的类型。
* @param {char*} url 生成的URL。
*
* @return {const char*} 返回URL。
*/
const char* data_reader_asset_build_url(const char* name, asset_type_t type,
char url[MAX_PATH + 1]);
#define DATA_READER_ASSET(reader) ((data_reader_t*)(reader))
END_C_DECLS
#endif /*TK_DATA_READER_ASSET_H*/

View File

@ -0,0 +1,152 @@
/**
* File: date_time_format.c
* Author: AWTK Develop Team
* Brief: date_time_format
*
* Copyright (c) 2020 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-01-11 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/utf8.h"
#include "base/locale_info.h"
#include "base/date_time_format.h"
static uint32_t count_char(const wchar_t* p, wchar_t c) {
uint32_t nr = 0;
while (*p++ == c) {
nr++;
}
return nr;
}
static wchar_t* translate_wday(wchar_t* str, uint32_t size, uint32_t wday) {
return_value_if_fail(wday < 7, NULL);
static const char* const wdays[] = {
"Sun", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat",
};
const char* utf8 = locale_info_tr(locale_info(), wdays[wday]);
return tk_utf8_to_utf16(utf8, str, size);
}
static wchar_t* translate_month(wchar_t* str, uint32_t size, uint32_t month) {
return_value_if_fail(month < 13 && month > 0, NULL);
static const char* const months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sept", "Oct", "Nov", "Dec"};
const char* utf8 = locale_info_tr(locale_info(), months[month - 1]);
return tk_utf8_to_utf16(utf8, str, size);
}
ret_t wstr_format_date_time(wstr_t* str, const char* format, const date_time_t* dt) {
wchar_t temp[32];
return_value_if_fail(format != NULL && str != NULL, RET_BAD_PARAMS);
wstr_t wformat;
wstr_init(&wformat, strlen(format) + 2);
wstr_set_utf8(&wformat, format);
const wchar_t* p = wformat.str;
str->size = 0;
memset(temp, 0x00, sizeof(temp));
while (*p) {
int32_t repeat = count_char(p, *p);
switch (*p) {
case 'Y': {
if (repeat == 2) {
wstr_push_int(str, "%02d", (dt->year % 100));
} else {
wstr_push_int(str, "%d", dt->year);
}
break;
}
case 'M': {
if (repeat == 2) {
wstr_push_int(str, "%02d", dt->month);
} else if (repeat == 3) {
translate_month(temp, ARRAY_SIZE(temp), dt->month);
wstr_append(str, temp);
} else {
wstr_push_int(str, "%d", dt->month);
}
break;
}
case 'D': {
if (repeat == 2) {
wstr_push_int(str, "%02d", dt->day);
} else {
wstr_push_int(str, "%d", dt->day);
}
break;
}
case 'h': {
if (repeat == 2) {
wstr_push_int(str, "%02d", dt->hour);
} else {
wstr_push_int(str, "%d", dt->hour);
}
break;
}
case 'm': {
if (repeat == 2) {
wstr_push_int(str, "%02d", dt->minute);
} else {
wstr_push_int(str, "%d", dt->minute);
}
break;
}
case 's': {
if (repeat == 2) {
wstr_push_int(str, "%02d", dt->second);
} else {
wstr_push_int(str, "%d", dt->second);
}
break;
}
case 'w': {
wstr_push_int(str, "%d", dt->wday);
break;
}
case 'W': {
translate_wday(temp, ARRAY_SIZE(temp), dt->wday);
wstr_append(str, temp);
break;
}
default: {
wstr_append_with_len(str, p, repeat);
break;
}
}
p += repeat;
}
wstr_reset(&wformat);
return RET_OK;
}
ret_t wstr_format_time(wstr_t* str, const char* format, uint64_t time) {
date_time_t dt;
return_value_if_fail(str != NULL && format != NULL, RET_BAD_PARAMS);
memset(&dt, 0x00, sizeof(dt));
date_time_from_time(&dt, time);
return wstr_format_date_time(str, format, &dt);
}

View File

@ -0,0 +1,85 @@
/**
* File: date_time_format.h
* Author: AWTK Develop Team
* Brief: date_time_format
*
* Copyright (c) 2020 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-01-11 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_DATE_TIME_FORMAT_H
#define TK_DATE_TIME_FORMAT_H
#include "tkc/str.h"
#include "tkc/wstr.h"
#include "tkc/types_def.h"
#include "tkc/date_time.h"
BEGIN_C_DECLS
/**
* @class date_time_format_t
* @annotation ["fake"]
* 格式化日期时间。
*
* 格式规则:
* * Y 代表年(完整显示)
* * M 代表月(1-12)
* * D 代表日(1-31)
* * h 代表时(0-23)
* * m 代表分(0-59)
* * s 代表秒(0-59)
* * w 代表星期(0-6)
* * W 代表星期的英文缩写(支持翻译)
* * YY 代表年(只显示末两位)
* * MM 代表月(01-12)
* * DD 代表日(01-31)
* * hh 代表时(00-23)
* * mm 代表分(00-59)
* * ss 代表秒(00-59)
* * MMM 代表月的英文缩写(支持翻译)
*
* 如 日期时间为2018/11/12 9:10:20
* * "Y/M/D"显示为"2018/11/12"
* * "Y-M-D"显示为"2018-11-12"
* * "Y-M-D h:m:s"显示为"2018-11-12 9:10:20"
* * "Y-M-D hh:mm:ss"显示为"2018-11-12 09:10:20"
*/
/**
* @method wstr_format_time
* 格式化time。
* @param {wstr_t*} str 输出字符串。
* @param {const char*} format 格式。
* @param {uint64_t} time 时间。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t wstr_format_time(wstr_t* str, const char* format, uint64_t time);
/**
* @method wstr_format_date_time
* 格式化date_time。
* @param {wstr_t*} str 输出字符串。
* @param {const char*} format 格式。
* @param {date_time_t*} dt 时间。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t wstr_format_date_time(wstr_t* str, const char* format, const date_time_t* dt);
END_C_DECLS
#endif /*TK_DATE_TIME_FORMAT_H*/

View File

@ -0,0 +1,218 @@
/**
* File: dialog.c
* Author: AWTK Develop Team
* Brief: dialog
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "base/idle.h"
#include "base/enums.h"
#include "tkc/utils.h"
#include "base/layout.h"
#include "base/dialog.h"
#include "base/main_loop.h"
#include "base/image_manager.h"
#include "base/window_manager.h"
#include "layouters/self_layouter_default.h"
static ret_t dialog_on_add_child(widget_t* widget, widget_t* child) {
dialog_t* dialog = DIALOG(widget);
return_value_if_fail(dialog != NULL, RET_BAD_PARAMS);
if (tk_str_eq(child->vt->type, WIDGET_TYPE_DIALOG_TITLE)) {
dialog->title = child;
} else if (tk_str_eq(child->vt->type, WIDGET_TYPE_DIALOG_CLIENT)) {
dialog->client = child;
}
return RET_CONTINUE;
}
static const char* const s_dialog_properties[] = {NULL};
static ret_t dialog_set_prop(widget_t* widget, const char* name, const value_t* v) {
dialog_t* dialog = DIALOG(widget);
return_value_if_fail(dialog != NULL, RET_BAD_PARAMS);
if (tk_str_eq(name, WIDGET_PROP_HIGHLIGHT)) {
dialog->highlight = tk_str_copy(dialog->highlight, value_str(v));
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_SELF_LAYOUT)) {
self_layouter_t* self_layout = widget->self_layout;
if (self_layouter_default_is_valid(self_layout)) {
if (self_layouter_get_param_int(self_layout, "x_attr", 0) == X_ATTR_UNDEF) {
self_layouter_set_param_str(self_layout, "x", "c");
}
if (self_layouter_get_param_int(self_layout, "y_attr", 0) == Y_ATTR_UNDEF) {
self_layouter_set_param_str(self_layout, "y", "m");
}
}
return RET_OK;
}
return window_base_set_prop(widget, name, v);
}
static ret_t dialog_get_prop(widget_t* widget, const char* name, value_t* v) {
dialog_t* dialog = DIALOG(widget);
return_value_if_fail(dialog != NULL, RET_BAD_PARAMS);
if (tk_str_eq(name, WIDGET_PROP_HIGHLIGHT)) {
value_set_str(v, dialog->highlight);
return RET_OK;
}
return window_base_get_prop(widget, name, v);
}
static ret_t dialog_on_destroy(widget_t* widget) {
dialog_t* dialog = DIALOG(widget);
return_value_if_fail(dialog != NULL, RET_BAD_PARAMS);
TKMEM_FREE(dialog->highlight);
return window_base_on_destroy(widget);
}
TK_DECL_VTABLE(dialog) = {.size = sizeof(dialog_t),
.type = WIDGET_TYPE_DIALOG,
.is_window = TRUE,
.clone_properties = s_dialog_properties,
.persistent_properties = s_dialog_properties,
.parent = TK_PARENT_VTABLE(window_base),
.create = dialog_create,
.on_add_child = dialog_on_add_child,
.on_event = window_base_on_event,
.on_paint_self = window_base_on_paint_self,
.on_paint_begin = window_base_on_paint_begin,
.on_paint_end = window_base_on_paint_end,
.set_prop = dialog_set_prop,
.get_prop = dialog_get_prop,
.on_destroy = dialog_on_destroy};
widget_t* dialog_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
return window_base_create(parent, TK_REF_VTABLE(dialog), x, y, w, h);
}
ret_t dialog_set_title(widget_t* widget, const char* title) {
dialog_t* dialog = DIALOG(widget);
return_value_if_fail(dialog != NULL && title != NULL, RET_BAD_PARAMS);
return widget_set_text_utf8(dialog->title, title);
}
static ret_t dialog_close(widget_t* widget) {
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
return window_manager_close_window(widget->parent, widget);
}
static ret_t dialog_idle_close(const idle_info_t* info) {
return dialog_close(WIDGET(info->ctx));
}
widget_t* dialog_get_title(widget_t* widget) {
dialog_t* dialog = DIALOG(widget);
return_value_if_fail(dialog != NULL, NULL);
return dialog->title;
}
widget_t* dialog_get_client(widget_t* widget) {
dialog_t* dialog = DIALOG(widget);
return_value_if_fail(dialog != NULL, NULL);
return dialog->client;
}
dialog_quit_code_t dialog_modal(widget_t* widget) {
#ifdef AWTK_WEB
log_debug("awtk web not support dialog_modal\n");
return DIALOG_QUIT_NONE;
#else
dialog_t* dialog = DIALOG(widget);
return_value_if_fail(dialog != NULL, DIALOG_QUIT_NONE);
log_debug("%s run\n", __FUNCTION__);
dialog->quited = FALSE;
dialog->is_model = TRUE;
widget_invalidate(widget, NULL);
main_loop_run(main_loop());
log_debug("%s quit\n", __FUNCTION__);
idle_add(dialog_idle_close, widget);
return (dialog_quit_code_t)(dialog->quit_code);
#endif /*AWTK_WEB*/
}
static bool_t is_dialog_opened(widget_t* widget) {
int32_t stage = widget_get_prop_int(widget, WIDGET_PROP_STAGE, WINDOW_STAGE_NONE);
if (stage == WINDOW_STAGE_OPENED) return TRUE;
if (stage != WINDOW_STAGE_SUSPEND || widget->parent == NULL) return FALSE;
WIDGET_FOR_EACH_CHILD_BEGIN_R(widget->parent, iter, i)
if (iter == widget) break;
if (!tk_str_eq(iter->vt->type, WIDGET_TYPE_DIALOG)) continue;
dialog_t* dialog = DIALOG(iter);
if (dialog == NULL || !dialog->quited) return FALSE;
WIDGET_FOR_EACH_CHILD_END()
return TRUE;
}
ret_t dialog_quit(widget_t* widget, uint32_t code) {
#ifdef AWTK_WEB
log_debug("awtk web not support dialog_modal\n");
dialog_close(widget);
#else
dialog_t* dialog = DIALOG(widget);
return_value_if_fail(dialog != NULL && !(dialog->quited), RET_BAD_PARAMS);
return_value_if_fail(is_dialog_opened(widget), RET_BAD_PARAMS);
dialog->quited = TRUE;
dialog->quit_code = (dialog_quit_code_t)code;
main_loop_quit(main_loop());
#endif /*AWTK_WEB*/
return RET_OK;
}
bool_t dialog_is_quited(widget_t* widget) {
dialog_t* dialog = DIALOG(widget);
return_value_if_fail(dialog != NULL, FALSE);
return dialog->quited;
}
bool_t dialog_is_modal(widget_t* widget) {
dialog_t* dialog = DIALOG(widget);
return_value_if_fail(dialog != NULL, FALSE);
return dialog->is_model;
}
widget_t* dialog_cast(widget_t* widget) {
return_value_if_fail(WIDGET_IS_INSTANCE_OF(widget, dialog), NULL);
return widget;
}

View File

@ -0,0 +1,392 @@
/**
* File: dialog.h
* Author: AWTK Develop Team
* Brief: dialog
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_DIALOG_H
#define TK_DIALOG_H
#include "base/window_base.h"
BEGIN_C_DECLS
/**
* @enum dialog_quit_code_t
* @annotation ["scriptable"]
* @prefix DIALOG_QUIT_
* 对话框退出码。
*
* > 一般用作dialog_quit函数的参数。
*/
typedef enum _dialog_quit_code_t {
/**
* @const DIALOG_QUIT_NONE
* 对话框被强行关闭或不关心关闭原因。
*/
DIALOG_QUIT_NONE = 0,
/**
* @const DIALOG_QUIT_OK
* 点击“OK”按钮关闭。
*/
DIALOG_QUIT_OK = 1,
/**
* @const DIALOG_QUIT_YES
* 点击“YES”按钮关闭。
*/
DIALOG_QUIT_YES = 1,
/**
* @const DIALOG_QUIT_CANCEL
* 点击“CANCEL”按钮关闭。
*/
DIALOG_QUIT_CANCEL = 2,
/**
* @const DIALOG_QUIT_NO
* 点击“NO”按钮关闭。
*/
DIALOG_QUIT_NO = 2,
/**
* @const DIALOG_QUIT_OTHER
* 点击其它按钮关闭。
*/
DIALOG_QUIT_OTHER
} dialog_quit_code_t;
/**
* @class dialog_t
* @parent window_base_t
* @annotation ["scriptable","design","widget","window"]
*
* 对话框。 对话框是一种特殊的窗口,大小和位置可以自由设置。
*
* AWTK中的对话框可以是模态的也可以是非模态的。
*
* 如果dialog有透明或半透效果则不支持窗口动画。
*
*> 由于浏览器中无法实现主循环嵌套,因此无法实现模态对话框。
* 如果希望自己写的AWTK应用程序可以在浏览器(包括各种小程序)中运行或演示,
* 请避免使用模态对话框。
*
* 对话框通常由对话框标题和对话框客户区两部分组成:
*
* ```graphviz
* [default_style]
*
* dialog_title_t -> dialog_t[arrowhead = "ediamond"]
* dialog_client_t -> dialog_t[arrowhead = "ediamond"]
* ```
*
* dialog\_t是[window\_base\_t](window_base_t.md)的子类控件window\_base\_t的函数均适用于dialog\_t控件。
*
* 在xml中使用"dialog"标签创建对话框。如:
*
* ```xml
* <dialog anim_hint="center_scale(duration=300)" x="c" y="m" w="80%" h="160" text="Dialog">
* <dialog_title x="0" y="0" w="100%" h="30" text="Hello AWTK" />
* <dialog_client x="0" y="bottom" w="100%" h="-30">
* <label name="" x="center" y="middle:-20" w="200" h="30" text="Are you ready?"/>
* <button name="quit" x="10" y="bottom:10" w="40%" h="30" text="确定"/>
* <button name="quit" x="right:10" y="bottom:10" w="40%" h="30" text="取消"/>
* </dialog_client>
* </dialog>
* ```
*
* 如果你不需要对话框的标题,可以这样写:
*
* ```xml
* <dialog anim_hint="center_scale(duration=300)" x="c" y="m" w="80%" h="160" text="Dialog">
* <label name="" x="center" y="middle:-20" w="200" h="30" text="Are you ready?"/>
* <button name="quit" x="10" y="bottom:10" w="40%" h="30" text="确定"/>
* <button name="quit" x="right:10" y="bottom:10" w="40%" h="30" text="取消"/>
* </dialog>
* ```
*
* 打开非模态对话框时其用法与普通窗口一样。打开非模态对话框时还需要调用dialog\_modal。
*
* ```c
* widget_t* dlg = dialog_open(name);
*
* ret = dialog_modal(dlg);
* ```
*
* 关闭模态对话框用dialog\_quit
*
* ```c
* static ret_t on_dialog_btn_click(void* ctx, event_t* evt) {
* widget_t* win = widget_get_window(WIDGET(evt->target));
* int code = (char*)ctx - (char*)NULL;
*
* dialog_quit(win, code);
*
* return RET_OK;
* }
* ```
*
* 关闭非模态对话框用window\_close。
*
* ```c
* static ret_t on_dialog_btn_click(void* ctx, event_t* evt) {
* widget_t* win = widget_get_window(WIDGET(evt->target));
* int code = (char*)ctx - (char*)NULL;
*
* window_close(win);
*
* return RET_OK;
* }
* ```
*
* > 更多用法请参考:
* [dialog.xml](https://github.com/zlgopen/awtk/blob/master/design/default/ui/)
*
* > 完整C代码示例请参考
*
* * [非模态对话框](https://github.com/zlgopen/awtk-c-demos/blob/master/demos/dialog.c)
*
* * [模态对话框](https://github.com/zlgopen/awtk-c-demos/blob/master/demos/dialog_modal.c)
*
*可用通过style来设置控件的显示风格如字体的大小和颜色等等。如
*
* ```xml
* <style name="default">
* <normal border_color="#606060" />
* </style>
* ```
*
* > 更多用法请参考:
* [theme default]
* (https://github.com/zlgopen/awtk/blob/master/design/default/styles/default.xml#L324)
*
*/
typedef struct _dialog_t {
window_base_t window;
/**
* @property {const char*} highlight
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 对话框高亮策略。
*
* > 请参考 [对话框高亮策略](https://github.com/zlgopen/awtk/blob/master/docs/dialog_highlight.md)
*/
char* highlight;
/*private*/
widget_t* title;
widget_t* client;
dialog_quit_code_t quit_code;
bool_t quited;
bool_t is_model;
} dialog_t;
/**
* @method dialog_create
* 创建dialog对象。
* @annotation ["constructor", "scriptable"]
* @param {widget_t*} parent 父控件
* @param {xy_t} x x坐标
* @param {xy_t} y y坐标
* @param {wh_t} w 宽度
* @param {wh_t} h 高度
*
* @return {widget_t*} dialog对象。
*/
widget_t* dialog_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method dialog_create_simple
* 创建dialog对象同时创建title/client。
* @annotation ["constructor", "scriptable"]
* @param {widget_t*} parent 父控件
* @param {xy_t} x x坐标
* @param {xy_t} y y坐标
* @param {wh_t} w 宽度
* @param {wh_t} h 高度
*
* @return {widget_t*} dialog对象。
*/
widget_t* dialog_create_simple(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method dialog_cast
* 转换dialog对象(供脚本语言使用)。
* @annotation ["cast", "scriptable"]
* @param {widget_t*} widget dialog对象。
*
* @return {widget_t*} dialog对象。
*/
widget_t* dialog_cast(widget_t* widget);
/**
* @method dialog_get_title
* 获取title控件。
* @annotation ["scriptable"]
* @param {widget_t*} widget dialog对象。
*
* @return {widget_t*} title对象。
*/
widget_t* dialog_get_title(widget_t* widget);
/**
* @method dialog_get_client
* 获取client控件。
* @annotation ["scriptable"]
* @param {widget_t*} widget dialog对象。
*
* @return {widget_t*} client对象。
*/
widget_t* dialog_get_client(widget_t* widget);
/**
* @method dialog_open
* @annotation ["constructor", "scriptable"]
* 从资源文件中加载并创建Dialog对象。
*
* 本函数在ui\_loader/ui\_builder_default里实现。
* @param {const char*} name dialog的名称。
*
* @return {widget_t*} 对象。
*/
widget_t* dialog_open(const char* name);
/**
* @method dialog_set_title
* 设置对话框的标题文本。
* @annotation ["scriptable"]
* @param {widget_t*} widget dialog对象。
* @param {char*} title 标题。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_set_title(widget_t* widget, const char* title);
/**
* @method dialog_modal
* 模态显示对话框。
* dialog_modal返回后dialog对象将在下一个idle函数中回收。
* 也就是在dialog_modal调用完成后仍然可以访问dialog中控件直到本次事件结束。
* @annotation ["scriptable"]
* @param {widget_t*} widget dialog对象。
*
* @return {dialog_quit_code_t} 返回退出码。
*/
dialog_quit_code_t dialog_modal(widget_t* widget);
/**
* @method dialog_quit
* 退出模态显示,关闭对话框。
*
*> 比如,在对话框中关闭按钮的事件处理函数中,调用本函数关闭对话框。
*
* @annotation ["scriptable"]
* @param {widget_t*} widget dialog对象。
* @param {uint32_t} code 退出码作为dialog_modal的返回值(参考:[dialog_quit_code_t](dialog_quit_code_t.md))。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_quit(widget_t* widget, uint32_t code);
/**
* @method dialog_is_quited
* 检查对话框是否已经退出模态。
*
* @annotation ["scriptable"]
* @param {widget_t*} widget dialog对象。
*
* @return {bool_t} 返回TRUE表示已经退出否则表示没有。
*/
bool_t dialog_is_quited(widget_t* widget);
/**
* @method dialog_is_modal
* 检查对话框是否为模态对话框。
*
* @annotation ["scriptable"]
* @param {widget_t*} widget dialog对象。
*
* @return {bool_t} 返回TRUE表示是模态对话框否则表示不是。
*/
bool_t dialog_is_modal(widget_t* widget);
/**
* @method dialog_toast
* 显示『短暂提示信息』对话框。
*
* 窗体样式由dialog_toast.xml文件决定。
*
* @annotation ["static", "scriptable"]
* @param {const char*} text 文本内容。
* @param {uint32_t} duration 显示时间(单位为毫秒)。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_toast(const char* text, uint32_t duration);
/**
* @method dialog_info
* 显示『提示信息』对话框。
*
* 窗体样式由dialog_info.xml文件决定。
*
* @annotation ["static", "scriptable"]
* @param {const char*} title 标题。
* @param {const char*} text 文本内容。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_info(const char* title, const char* text);
/**
* @method dialog_warn
* 显示『警告』对话框。
*
* 窗体样式由dialog_warn.xml文件决定。
*
* @annotation ["static", "scriptable"]
* @param {const char*} title 标题。
* @param {const char*} text 文本内容。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_warn(const char* title, const char* text);
/**
* @method dialog_confirm
* 显示『确认』对话框。
*
* 窗体样式由dialog_confirm.xml文件决定。
*
* @annotation ["static", "scriptable"]
* @param {const char*} title 标题。
* @param {const char*} text 文本内容。
*
* @return {ret_t} 返回RET_OK表示确认否则表示取消。
*/
ret_t dialog_confirm(const char* title, const char* text);
#define DIALOG(widget) ((dialog_t*)(dialog_cast(WIDGET(widget))))
/*public for subclass and runtime type check*/
TK_EXTERN_VTABLE(dialog);
END_C_DECLS
#endif /*TK_DIALOG_H*/

View File

@ -0,0 +1,153 @@
/**
* File: dialog_highlighter.c
* Author: AWTK Develop Team
* Brief: dialog_highlighter
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied highlighterrranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2019-03-27 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "base/dialog_highlighter.h"
ret_t dialog_highlighter_clear_image(dialog_highlighter_t* h) {
if (h->img.buffer != NULL) {
bitmap_destroy(&(h->img));
memset(&(h->img), 0x00, sizeof(h->img));
}
return RET_OK;
}
dialog_highlighter_t* dialog_highlighter_create(const dialog_highlighter_vtable_t* vt) {
dialog_highlighter_t* h = NULL;
return_value_if_fail(vt != NULL && vt->size >= sizeof(dialog_highlighter_t), NULL);
h = (dialog_highlighter_t*)TKMEM_ALLOC(vt->size);
return_value_if_fail(h != NULL, NULL);
memset(h, 0x00, vt->size);
emitter_init(EMITTER(h));
h->vt = vt;
return h;
}
ret_t dialog_highlighter_prepare_ex(dialog_highlighter_t* h, canvas_t* c,
canvas_t* canvas_offline) {
return_value_if_fail(h != NULL && h->vt != NULL && c != NULL, RET_BAD_PARAMS);
h->canvas = c;
if (h->vt->prepare != NULL) {
return h->vt->prepare(h, canvas_offline);
}
return RET_NOT_IMPL;
}
ret_t dialog_highlighter_prepare(dialog_highlighter_t* h, canvas_t* c) {
return dialog_highlighter_prepare_ex(h, c, c);
}
ret_t dialog_highlighter_set_bg(dialog_highlighter_t* h, bitmap_t* img) {
return_value_if_fail(h != NULL && h->vt != NULL, RET_BAD_PARAMS);
dialog_highlighter_clear_image(h);
if (img != NULL) {
h->img = *img;
}
return RET_OK;
}
ret_t dialog_highlighter_set_bg_clip_rect(dialog_highlighter_t* h, rect_t* clip_rect) {
return_value_if_fail(h != NULL && h->vt != NULL, RET_BAD_PARAMS);
h->clip_rect = rect_init(clip_rect->x, clip_rect->y, clip_rect->w, clip_rect->h);
return RET_OK;
}
ret_t dialog_highlighter_set_system_bar_alpha(dialog_highlighter_t* h, uint8_t alpha) {
return_value_if_fail(h != NULL && h->vt != NULL, RET_BAD_PARAMS);
if (h->vt->set_system_bar_alpha != NULL) {
return h->vt->set_system_bar_alpha(h, alpha);
}
return RET_NOT_IMPL;
}
uint8_t dialog_highlighter_get_alpha(dialog_highlighter_t* h, float_t percent) {
return_value_if_fail(h != NULL && h->vt != NULL, 0x0);
if (h->vt->get_alpha != NULL) {
return h->vt->get_alpha(h, percent);
}
return 0x0;
}
ret_t dialog_highlighter_draw(dialog_highlighter_t* h, float_t percent) {
return_value_if_fail(h != NULL && h->vt != NULL, RET_BAD_PARAMS);
if (h->vt->draw != NULL) {
return h->vt->draw(h, percent);
}
return RET_NOT_IMPL;
}
ret_t dialog_highlighter_draw_mask(dialog_highlighter_t* h, canvas_t* c, float_t percent) {
return_value_if_fail(h != NULL && h->vt != NULL, RET_BAD_PARAMS);
if (h->vt->draw_mask != NULL) {
return h->vt->draw_mask(h, c, percent);
}
return RET_NOT_IMPL;
}
bool_t dialog_highlighter_is_dynamic(dialog_highlighter_t* h) {
if (h != NULL && h->vt != NULL && h->vt->is_dynamic != NULL) {
return h->vt->is_dynamic(h);
} else {
return FALSE;
}
}
static ret_t dialog_highlighter_on_destroy(dialog_highlighter_t* h) {
return_value_if_fail(h != NULL && h->vt != NULL, RET_BAD_PARAMS);
if (h->vt->on_destroy != NULL) {
h->vt->on_destroy(h);
}
return RET_OK;
}
ret_t dialog_highlighter_destroy(dialog_highlighter_t* h) {
return_value_if_fail(h != NULL && h->vt != NULL, RET_BAD_PARAMS);
emitter_dispatch_simple_event(EMITTER(h), EVT_DESTROY);
dialog_highlighter_on_destroy(h);
dialog_highlighter_clear_image(h);
emitter_deinit(EMITTER(h));
memset(h, 0x00, h->vt->size);
TKMEM_FREE(h);
return RET_OK;
}

View File

@ -0,0 +1,222 @@
/**
* File: dialog_highlighter.h
* Author: AWTK Develop Team
* Brief: dialog_highlighter
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied highlighterrranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2019-03-27 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_DIALOG_HIGHLIGHTER_H
#define TK_DIALOG_HIGHLIGHTER_H
#include "base/widget.h"
BEGIN_C_DECLS
struct _dialog_highlighter_t;
typedef struct _dialog_highlighter_t dialog_highlighter_t;
typedef ret_t (*dialog_highlighter_set_system_bar_alpha_t)(dialog_highlighter_t* h, uint8_t alpha);
typedef uint8_t (*dialog_highlighter_get_alpha_t)(dialog_highlighter_t* h, float_t percent);
typedef ret_t (*dialog_highlighter_draw_mask_t)(dialog_highlighter_t* h, canvas_t* c,
float_t percent);
typedef ret_t (*dialog_highlighter_prepare_t)(dialog_highlighter_t* h, canvas_t* c);
typedef ret_t (*dialog_highlighter_draw_t)(dialog_highlighter_t* h, float_t percent);
typedef bool_t (*dialog_highlighter_is_dynamic_t)(dialog_highlighter_t* h);
typedef ret_t (*dialog_highlighter_on_destroy_t)(dialog_highlighter_t* h);
typedef dialog_highlighter_t* (*dialog_highlighter_create_t)(object_t* args);
typedef struct _dialog_highlighter_vtable_t {
const char* type;
const char* desc;
uint32_t size;
dialog_highlighter_draw_t draw;
dialog_highlighter_prepare_t prepare;
dialog_highlighter_draw_mask_t draw_mask;
dialog_highlighter_get_alpha_t get_alpha;
dialog_highlighter_is_dynamic_t is_dynamic;
dialog_highlighter_on_destroy_t on_destroy;
dialog_highlighter_set_system_bar_alpha_t set_system_bar_alpha;
} dialog_highlighter_vtable_t;
/**
* @enum dialog_highlighter_type_t
* @prefix DIALOG_HIGHLIGHTER_
* @type string
* 内置的对话框高亮策略。
*/
/**
* @const DIALOG_HIGHLIGHTER_DEFAULT
* 缺省的对话框高亮策略。
*/
#define DIALOG_HIGHLIGHTER_DEFAULT "default"
/**
* @class dialog_highlighter_t
* 对话框高亮策略。
*
*> 高亮策略的基本思路是对背景进行处理,比如将背景变暗或变模糊。
*
*/
struct _dialog_highlighter_t {
emitter_t emitter;
/**
* @property {bitmap_t} img
* 底层窗口的截图。
*/
bitmap_t img;
/**
* @property {canvas_t*} canvas
* 画布。
*/
canvas_t* canvas;
/**
* @property {widget_t*} dialog
* 对应的对话框。
*/
widget_t* dialog;
/**
* @property {rect_t*} clip_rect
* 截图的显示裁减区
*/
rect_t clip_rect;
/*private*/
const dialog_highlighter_vtable_t* vt;
};
/**
* @method dialog_highlighter_create
* 创建对话框高亮策略对象。
*
*>供子类构造函数用。
* @param {const dialog_highlighter_vtable_t*} vt 虚表对象。
*
* @return {dialog_highlighter_t*} 返回对话框高亮策略对象
*/
dialog_highlighter_t* dialog_highlighter_create(const dialog_highlighter_vtable_t* vt);
/**
* @method dialog_highlighter_set_bg
* 设置背景图片。
* @param {dialog_highlighter_t*} h 对话框高亮策略对象。
* @param {bitmap_t*} img 背景截图。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_highlighter_set_bg(dialog_highlighter_t* h, bitmap_t* img);
/**
* @method dialog_highlighter_set_bg_clip_rect
* 设置背景图片的显示裁剪区。
* @param {dialog_highlighter_t*} h 对话框高亮策略对象。
* @param {rect_t*} clip_rect 背景显示裁剪区。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_highlighter_set_bg_clip_rect(dialog_highlighter_t* h, rect_t* clip_rect);
/**
* @method dialog_highlighter_prepare
* 初始化。在绘制完背景,在截图前调用。
* @param {dialog_highlighter_t*} h 对话框高亮策略对象。
* @param {canvas_t*} c 画布。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_highlighter_prepare(dialog_highlighter_t* h, canvas_t* c);
/**
* @method dialog_highlighter_prepare_ex
* 初始化。在绘制完背景,在截图前调用。
* @param {dialog_highlighter_t*} h 对话框高亮策略对象。
* @param {canvas_t*} c 画布。
* @param {canvas_t*} canvas_offline 离线画布。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_highlighter_prepare_ex(dialog_highlighter_t* h, canvas_t* c, canvas_t* canvas_offline);
/**
* @method dialog_highlighter_set_system_bar_alpha
* 设置 sytem_bar 的高亮透明值。
* @param {dialog_highlighter_t*} h 对话框高亮策略对象。
* @param {uint8_t} alpha 设置 sytem_bar 的高亮透明值。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_highlighter_set_system_bar_alpha(dialog_highlighter_t* h, uint8_t alpha);
/**
* @method dialog_highlighter_get_alpha
* 获取高亮的透明度。
* @param {dialog_highlighter_t*} h 对话框高亮策略对象。
* @param {float_t} percent 高亮的百分比。
*
* @return {uint8_t} 返回透明度。
*/
uint8_t dialog_highlighter_get_alpha(dialog_highlighter_t* h, float_t percent);
/**
* @method dialog_highlighter_draw
* 绘制背景。
* @param {dialog_highlighter_t*} h 对话框高亮策略对象。
* @param {float_t} percent 动画进度(0-1)1表示打开已经完成。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_highlighter_draw(dialog_highlighter_t* h, float_t percent);
/**
* @method dialog_highlighter_draw_mask
* 绘制背景高亮部分。
* @param {dialog_highlighter_t*} h 对话框高亮策略对象。
* @param {canvas_t*} c 画布。
* @param {float_t} percent 高亮的百分比。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_highlighter_draw_mask(dialog_highlighter_t* h, canvas_t* c, float_t percent);
/**
* @method dialog_highlighter_is_dynamic
* 是否是动态绘制(方便外层优化)。
* @param {dialog_highlighter_t*} h 对话框高亮策略对象。
*
* @return {bool_t} 返回TRUE表示动态绘制否则表示不是动态绘制。
*/
bool_t dialog_highlighter_is_dynamic(dialog_highlighter_t* h);
/**
* @method dialog_highlighter_destroy
* 销毁对话框高亮策略对象。
* @param {dialog_highlighter_t*} h 对话框高亮策略对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_highlighter_destroy(dialog_highlighter_t* h);
/*for window manager*/
ret_t dialog_highlighter_clear_image(dialog_highlighter_t* h);
END_C_DECLS
#endif /*TK_DIALOG_HIGHLIGHTER_H*/

View File

@ -0,0 +1,140 @@
/**
* File: dialog_highlighter_factory.c
* Author: AWTK Develop Team
* Brief: window highlighter factory
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2019-03-27 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/enums.h"
#include "tkc/easing.h"
#include "base/window_manager.h"
#include "tkc/func_call_parser.h"
#include "base/dialog_highlighter_factory.h"
static dialog_highlighter_factory_t* dialog_highlighter_factory_init(
dialog_highlighter_factory_t* factory);
static ret_t dialog_highlighter_factory_deinit(dialog_highlighter_factory_t* factory);
static dialog_highlighter_factory_t* s_dialog_highlighter_factory = NULL;
typedef struct _creator_item_t {
char type[TK_NAME_LEN + 1];
dialog_highlighter_create_t create;
} creator_item_t;
static int32_t creator_item_cmp(const creator_item_t* iter, const char* type) {
return strcmp(iter->type, type);
}
dialog_highlighter_factory_t* dialog_highlighter_factory(void) {
return s_dialog_highlighter_factory;
}
dialog_highlighter_factory_t* dialog_highlighter_factory_create(void) {
dialog_highlighter_factory_t* factory = TKMEM_ZALLOC(dialog_highlighter_factory_t);
return_value_if_fail(factory != NULL, NULL);
return dialog_highlighter_factory_init(factory);
}
static dialog_highlighter_factory_t* dialog_highlighter_factory_init(
dialog_highlighter_factory_t* factory) {
return_value_if_fail(factory != NULL, NULL);
darray_init(&(factory->creators), 0, default_destroy, (tk_compare_t)creator_item_cmp);
return factory;
}
ret_t dialog_highlighter_factory_register(dialog_highlighter_factory_t* factory, const char* type,
dialog_highlighter_create_t create) {
creator_item_t* item = NULL;
return_value_if_fail(factory != NULL && type != NULL && create != NULL, RET_BAD_PARAMS);
item = TKMEM_ZALLOC(creator_item_t);
return_value_if_fail(item != NULL, RET_OOM);
item->create = create;
tk_strncpy(item->type, type, TK_NAME_LEN);
darray_push(&(factory->creators), item);
return RET_OK;
}
ret_t dialog_highlighter_on_dialog_destroy(void* ctx, event_t* e) {
dialog_highlighter_t* h = (dialog_highlighter_t*)ctx;
dialog_highlighter_destroy(h);
log_debug("dialog_highlighter_on_dialog_destroy\n");
return RET_REMOVE;
}
dialog_highlighter_t* dialog_highlighter_factory_create_highlighter(
dialog_highlighter_factory_t* factory, const char* args, widget_t* dialog) {
#ifndef WITHOUT_DIALOG_HIGHLIGHTER
object_t* args_obj = NULL;
dialog_highlighter_t* h = NULL;
const creator_item_t* iter = NULL;
return_value_if_fail(factory != NULL, NULL);
args_obj = func_call_parse(args, tk_strlen(args));
return_value_if_fail(args_obj != NULL, NULL);
iter = darray_find(&(factory->creators), (void*)args_obj->name);
if (iter != NULL) {
h = iter->create(args_obj);
}
object_unref(args_obj);
if (h != NULL) {
h->dialog = dialog;
if (dialog != NULL) {
widget_on(dialog, EVT_DESTROY, dialog_highlighter_on_dialog_destroy, h);
}
}
return h;
#else
return NULL;
#endif /*WITHOUT_DIALOG_HIGHLIGHTER*/
}
ret_t dialog_highlighter_factory_set(dialog_highlighter_factory_t* factory) {
s_dialog_highlighter_factory = factory;
return RET_OK;
}
static ret_t dialog_highlighter_factory_deinit(dialog_highlighter_factory_t* factory) {
return_value_if_fail(factory != NULL, RET_BAD_PARAMS);
darray_deinit(&(factory->creators));
return RET_OK;
}
ret_t dialog_highlighter_factory_destroy(dialog_highlighter_factory_t* factory) {
return_value_if_fail(factory != NULL, RET_BAD_PARAMS);
dialog_highlighter_factory_deinit(factory);
TKMEM_FREE(factory);
return RET_OK;
}

View File

@ -0,0 +1,104 @@
/**
* File: dialog_highlighter_factory.h
* Author: AWTK Develop Team
* Brief: dialog highlighter factory
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-03-27 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_DIALOG_HIGHLIGHTER_FACTORY_H
#define TK_DIALOG_HIGHLIGHTER_FACTORY_H
#include "tkc/darray.h"
#include "base/dialog_highlighter.h"
BEGIN_C_DECLS
/**
* @class dialog_highlighter_factory_t
* 对话框高亮策略工厂。
*
*/
typedef struct _dialog_highlighter_factory_t {
/*private*/
darray_t creators;
} dialog_highlighter_factory_t;
/**
* @method dialog_highlighter_factory
* 获取缺省的对话框高亮策略工厂对象。
* @annotation ["constructor"]
* @return {dialog_highlighter_factory_t*} 返回对话框高亮策略工厂对象。
*/
dialog_highlighter_factory_t* dialog_highlighter_factory(void);
/**
* @method dialog_highlighter_factory_set
* 设置缺省的对话框高亮策略工厂对象。
* @param {dialog_highlighter_factory_t*} factory 对话框高亮策略工厂对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_highlighter_factory_set(dialog_highlighter_factory_t* factory);
/**
* @method dialog_highlighter_factory_create
* 创建对话框高亮策略工厂对象。
* @annotation ["constructor"]
*
* @return {dialog_highlighter_factory_t*} 返回对话框高亮策略工厂对象。
*/
dialog_highlighter_factory_t* dialog_highlighter_factory_create(void);
/**
* @method dialog_highlighter_factory_register
* 注册对话框高亮策略创建函数。
* @param {dialog_highlighter_factory_t*} factory highlighter工厂对象。
* @param {const char*} type 对话框高亮策略类型。
* @param {dialog_highlighter_create_t} create 对话框高亮策略创建函数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_highlighter_factory_register(dialog_highlighter_factory_t* factory, const char* type,
dialog_highlighter_create_t create);
/**
* @method dialog_highlighter_factory_create_highlighter
* 创建指定类型的对话框高亮策略对象。
* @annotation ["constructor"]
* @param {dialog_highlighter_factory_t*} factory 对话框高亮策略工厂对象。
* @param {const char*} args 参数。如default(alpha=90)
* @param {widget_t*} dialog 对话框对象。
*
* @return {dialog_highlighter_t*} 返回窗口动画对象。
*/
dialog_highlighter_t* dialog_highlighter_factory_create_highlighter(
dialog_highlighter_factory_t* factory, const char* args, widget_t* dialog);
/**
* @method dialog_highlighter_factory_destroy
* 析构并释放对话框高亮策略工厂对象。
* @param {dialog_highlighter_factory_t*} factory 对话框高亮策略工厂对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t dialog_highlighter_factory_destroy(dialog_highlighter_factory_t* factory);
/*public for internal use*/
ret_t dialog_highlighter_on_dialog_destroy(void* ctx, event_t* e);
END_C_DECLS
#endif /*TK_DIALOG_HIGHLIGHTER_FACTORY_H*/

View File

@ -0,0 +1,282 @@
/**
* File: dirty_rects.h
* Author: AWTK Develop Team
* Brief: multiple dirty rects
*
* Copyright (c) 2021 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2021-06-17 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_DIRTY_RECTS_H
#define TK_DIRTY_RECTS_H
#include "tkc/rect.h"
BEGIN_C_DECLS
#ifndef TK_MAX_DIRTY_RECT_NR
#define TK_MAX_DIRTY_RECT_NR 10
#endif /*TK_MAX_DIRTY_RECT_NR*/
/**
* @class dirty_rects_t
* 支持多个脏矩形。
* > 在通常情况下,脏矩形的个数并不多,而且一般都是不重叠的,
* > 所以为了降低计算开销、避免内存分配和简化实现。这里采用下列措施:
*
* * 如果新的脏矩形是独立的,直接加入进来。
* * 如果新的脏矩形与某个脏矩形有重叠,则合并到该脏矩形。
* * 如果脏矩形的个数超出最大个数则进行合并。
*
*/
typedef struct _dirty_rects_t {
/**
* @property {uint32_t} nr
* @annotation ["readable"]
* 个数。
*/
uint32_t nr;
/**
* @property {rect_t} max
* @annotation ["readable"]
* 最大脏矩形。
*/
rect_t max;
/**
* @property {rect_t} rects
* @annotation ["readable"]
* 脏矩形。
*/
rect_t rects[TK_MAX_DIRTY_RECT_NR];
/*private*/
bool_t debug;
bool_t profile;
bool_t disable_multiple;
} dirty_rects_t;
/**
* @method dirty_rects_reset
* 重置dirty_rects对象。
* @export none
* @param {dirty_rects_t*} dirty_rects dirty_rects对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
static inline ret_t dirty_rects_reset(dirty_rects_t* dirty_rects) {
return_value_if_fail(dirty_rects != NULL, RET_BAD_PARAMS);
memset(dirty_rects, 0x00, sizeof(dirty_rects_t));
/*
dirty_rects->debug = TRUE;
dirty_rects->profile = TRUE;
dirty_rects->disable_multiple = TRUE;
*/
return RET_OK;
}
/**
* @method dirty_rects_init
* @export none
* 初始化dirty_rects对象。
* @param {dirty_rects_t*} dirty_rects dirty_rects对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
static inline ret_t dirty_rects_init(dirty_rects_t* dirty_rects) {
return dirty_rects_reset(dirty_rects);
}
/**
* @method dirty_rects_deinit
* @export none
* 释放dirty_rects对象。
* @param {dirty_rects_t*} dirty_rects dirty_rects对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
static inline ret_t dirty_rects_deinit(dirty_rects_t* dirty_rects) {
return dirty_rects_reset(dirty_rects);
}
/**
* @method dirty_rects_remove
* @export none
* 删除指定序数的矩形。
* @param {dirty_rects_t*} dirty_rects dirty_rects对象。
* @param {uint32_t} index 序数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
static inline ret_t dirty_rects_remove(dirty_rects_t* dirty_rects, uint32_t index) {
uint32_t i = 0;
return_value_if_fail(dirty_rects != NULL, RET_BAD_PARAMS);
return_value_if_fail(index < dirty_rects->nr, RET_BAD_PARAMS);
for (i = index; (i + 1) < dirty_rects->nr; i++) {
dirty_rects->rects[i] = dirty_rects->rects[i + 1];
}
dirty_rects->nr--;
return RET_OK;
}
/**
* @method dirty_rects_fix
* @export none
* 脏矩形之间可能重叠,合并重叠的脏矩形。
* @param {dirty_rects_t*} dirty_rects dirty_rects对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
static inline ret_t dirty_rects_fix(dirty_rects_t* dirty_rects) {
uint32_t i = 0;
return_value_if_fail(dirty_rects != NULL, RET_BAD_PARAMS);
if (dirty_rects->nr > 1) {
for (i = 1; i < dirty_rects->nr; i++) {
rect_t* iter = dirty_rects->rects + i;
if (rect_has_intersect(dirty_rects->rects, iter)) {
rect_merge(dirty_rects->rects, iter);
dirty_rects_remove(dirty_rects, i);
return dirty_rects_fix(dirty_rects);
}
}
}
return RET_OK;
}
/**
* @method dirty_rects_add
* @export none
* 增加脏矩形。
* @param {dirty_rects_t*} dirty_rects dirty_rects对象。
* @param {rect_t*} r 脏矩形。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
static inline ret_t dirty_rects_add(dirty_rects_t* dirty_rects, const rect_t* r) {
uint32_t i = 0;
return_value_if_fail(dirty_rects != NULL && r != NULL, RET_BAD_PARAMS);
if (r->w == 0 || r->h == 0) {
return RET_OK;
}
if (dirty_rects->nr >= TK_MAX_DIRTY_RECT_NR) {
for (i = 1; i < dirty_rects->nr; i++) {
rect_merge(dirty_rects->rects, dirty_rects->rects + i);
}
dirty_rects->nr = 1;
}
rect_merge(&(dirty_rects->max), r);
for (i = 0; i < dirty_rects->nr; i++) {
rect_t* iter = dirty_rects->rects + i;
if (rect_has_intersect(iter, r)) {
rect_merge(iter, r);
return dirty_rects_fix(dirty_rects);
}
}
dirty_rects->rects[dirty_rects->nr++] = *r;
return RET_OK;
}
/**
* @method dirty_rects_set_debug
* @export none
* 设置是否开启调试模式。
* @param {dirty_rects_t*} dirty_rects dirty_rects对象。
* @param {bool_t} debug 是否开启调试模式。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
static inline ret_t dirty_rects_set_debug(dirty_rects_t* dirty_rects, bool_t debug) {
return_value_if_fail(dirty_rects != NULL, RET_BAD_PARAMS);
dirty_rects->debug = debug;
return RET_OK;
}
/**
* @method dirty_rects_set_profile
* @export none
* 设置是否开启profile模式。
* @param {dirty_rects_t*} dirty_rects dirty_rects对象。
* @param {bool_t} profile 是否开启profile模式。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
static inline ret_t dirty_rects_set_profile(dirty_rects_t* dirty_rects, bool_t profile) {
return_value_if_fail(dirty_rects != NULL, RET_BAD_PARAMS);
dirty_rects->profile = profile;
return RET_OK;
}
/**
* @method dirty_rects_set_disable_multiple
* @export none
* 设置是否关闭多脏矩形模式(方便对比测试和调试)。
* @param {dirty_rects_t*} dirty_rects dirty_rects对象。
* @param {bool_t} disable_multiple 是否关闭多脏矩形模式。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
static inline ret_t dirty_rects_set_disable_multiple(dirty_rects_t* dirty_rects,
bool_t disable_multiple) {
return_value_if_fail(dirty_rects != NULL, RET_BAD_PARAMS);
dirty_rects->disable_multiple = disable_multiple;
return RET_OK;
}
/**
* @_method rect_intersect_dirty_rects
* 求脏矩形与rect的交集。
*
* @param {const dirty_rects_t*} r1 dirty_rects对象。
* @param {const rect_t*} r2 rect对象。
* @param {dirty_rects_t*} r3 dirty_rects对象。
*
* @return {dirty_rects_t *} 返回交集。
*/
static dirty_rects_t* rect_intersect_dirty_rects(const dirty_rects_t* r1, const rect_t* r2, dirty_rects_t* r3)
{
int i;
return_value_if_fail(r1 != NULL, NULL);
return_value_if_fail(r2 != NULL, NULL);
return_value_if_fail(r3 != NULL, NULL);
dirty_rects_init(r3);
// 遍历每个脏矩形,
for (i = 0; i < r1->nr; i++)
{
const rect_t* iter = r1->rects + i;
// 求其与r2的交集
if (rect_has_intersect(iter, r2))
{
rect_t r_inter = rect_intersect(iter, r2);
dirty_rects_add(r3, &r_inter);
}
}
return r3;
}
END_C_DECLS
#endif /*TK_DIRTY_RECTS_H*/

View File

@ -0,0 +1,142 @@
#include "base/lcd.h"
#include "base/widget_vtable.h"
#include "base/dirty_rects.h"
static inline ret_t dirty_rects_dump(dirty_rects_t* dirty_rects) {
uint32_t i = 0;
rect_t* iter = NULL;
return_value_if_fail(dirty_rects != NULL, RET_BAD_PARAMS);
iter = &(dirty_rects->max);
log_debug("max:");
log_debug("(%d %d %d %d)", iter->x, iter->y, iter->w, iter->h);
log_debug("\n");
log_debug("===========================================================\n");
for (i = 0; i < dirty_rects->nr; i++) {
rect_t* iter = dirty_rects->rects + i;
log_debug("(%d %d %d %d)", iter->x, iter->y, iter->w, iter->h);
}
log_debug("\n");
log_debug("===========================================================\n\n");
return RET_OK;
}
#ifdef DIRTY_RECTS_CLIP_SUPPORT
static inline ret_t dirty_rects_paint(dirty_rects_t* dirty_rects, widget_t* widget, canvas_t* c,
widget_on_paint_t on_paint) {
uint32_t cost = 0;
rect_t full_screen;
dirty_rects_t dirty_rects_clip;
dirty_rects_t* iter = NULL;
uint64_t start = time_now_us();
bool_t is_support_dirty_rect = TRUE;
return_value_if_fail(dirty_rects != NULL, RET_BAD_PARAMS);
return_value_if_fail(widget != NULL && c != NULL && on_paint != NULL, RET_BAD_PARAMS);
is_support_dirty_rect = lcd_is_support_dirty_rect(c->lcd);
if(!is_support_dirty_rect)
{
return RET_OK;
}
if (dirty_rects->nr == 0) {
return RET_OK;
}
full_screen = rect_init(0, 0, canvas_get_width(c), canvas_get_height(c));
if(is_support_dirty_rect)
{
dirty_rects_clip = *dirty_rects;
}
else
{
dirty_rects_init (&dirty_rects_clip);
dirty_rects_add (&dirty_rects_clip, &full_screen);
}
iter = &dirty_rects_clip;
widget_paint_with_clip_dirty_rects (widget, iter, c, on_paint);
if (dirty_rects->profile) {
cost = time_now_us() - start;
log_debug("paint max rect(%d %d %d %d) cost=%u\n", iter->max.x, iter->max.y, iter->max.w, iter->max.h, cost);
}
if (dirty_rects->debug) {
canvas_set_stroke_color_str(c, "red");
canvas_stroke_rect(c, iter->max.x + 1, iter->max.y + 1, iter->max.w - 2, iter->max.h - 2);
}
if (dirty_rects->profile) {
log_debug("\n\n");
}
return RET_OK;
}
#else
static inline ret_t dirty_rects_paint(dirty_rects_t* dirty_rects, widget_t* widget, canvas_t* c,
widget_on_paint_t on_paint) {
uint32_t cost = 0;
rect_t full_screen;
rect_t* iter = NULL;
uint64_t start = time_now_us();
bool_t is_support_dirty_rect = TRUE;
return_value_if_fail(dirty_rects != NULL, RET_BAD_PARAMS);
return_value_if_fail(widget != NULL && c != NULL && on_paint != NULL, RET_BAD_PARAMS);
is_support_dirty_rect = lcd_is_support_dirty_rect(c->lcd);
if (dirty_rects->nr == 0) {
return RET_OK;
}
if (dirty_rects->disable_multiple || !is_support_dirty_rect) {
full_screen = rect_init(0, 0, canvas_get_width(c), canvas_get_height(c));
iter = is_support_dirty_rect ? &(dirty_rects->max) : &full_screen;
widget_paint_with_clip(widget, iter, c, on_paint);
if (dirty_rects->profile) {
cost = time_now_us() - start;
log_debug("paint max rect(%d %d %d %d) cost=%u\n", iter->x, iter->y, iter->w, iter->h, cost);
}
if (dirty_rects->debug) {
canvas_set_stroke_color_str(c, "red");
canvas_stroke_rect(c, iter->x + 1, iter->y + 1, iter->w - 2, iter->h - 2);
}
} else {
uint32_t i = 0;
if (dirty_rects->debug) {
dirty_rects_dump(dirty_rects);
}
for (i = 0; i < dirty_rects->nr; i++) {
rect_t* iter = dirty_rects->rects + i;
uint64_t start1 = time_now_us();
widget_paint_with_clip(widget, iter, c, on_paint);
if (dirty_rects->debug) {
canvas_set_stroke_color_str(c, "red");
canvas_stroke_rect(c, iter->x + 1, iter->y + 1, iter->w - 2, iter->h - 2);
}
if (dirty_rects->profile) {
cost = time_now_us() - start1;
log_debug("paint %u rect(%d %d %d %d) cost=%u\n", i, iter->x, iter->y, iter->w, iter->h,
cost);
}
}
if (dirty_rects->profile) {
iter = &(dirty_rects->max);
cost = time_now_us() - start;
log_debug("paint total rect(%d %d %d %d) cost=%u\n", iter->x, iter->y, iter->w, iter->h,
cost);
}
}
if (dirty_rects->profile) {
log_debug("\n\n");
}
return RET_OK;
}
#endif

View File

@ -0,0 +1,409 @@
/**
* File: enums.c
* Author: AWTK Develop Team
* Brief: enumerations
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-02-14 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/utils.h"
#include "base/keys.h"
#include "base/enums.h"
#include "base/widget.h"
#include "base/input_method.h"
#include "base/window_animator.h"
#include "base/assets_manager.h"
static const key_type_value_t window_closable_name_value[] = {
{"yes", 0, WINDOW_CLOSABLE_YES},
{"no", 0, WINDOW_CLOSABLE_NO},
{"confirm", 0, WINDOW_CLOSABLE_CONFIRM}};
static const key_type_value_t align_v_name_value[] = {
{"top", 0, ALIGN_V_TOP}, {"middle", 0, ALIGN_V_MIDDLE}, {"bottom", 0, ALIGN_V_BOTTOM}};
static const key_type_value_t input_type_name_value[] = {
{"int", 0, INPUT_INT},
{"float", 0, INPUT_FLOAT},
{"uint", 0, INPUT_UINT},
{"ufloat", 0, INPUT_UFLOAT},
{"text", 0, INPUT_TEXT},
{"password", 0, INPUT_PASSWORD},
{"hex", 0, INPUT_HEX},
{"email", 0, INPUT_EMAIL},
{"phone", 0, INPUT_PHONE},
{"date", 0, INPUT_DATE},
{"time", 0, INPUT_TIME},
{"time_full", 0, INPUT_TIME_FULL},
{"ipv4", 0, INPUT_IPV4},
{"custom", 0, INPUT_CUSTOM},
{"custom_password", 0, INPUT_CUSTOM_PASSWORD},
{"ascii", 0, INPUT_ASCII},
};
static const key_type_value_t align_h_name_value[] = {
{"left", 0, ALIGN_H_LEFT}, {"center", 0, ALIGN_H_CENTER}, {"right", 0, ALIGN_H_RIGHT}};
static const key_type_value_t asset_type_value[] = {
{"font", 0, ASSET_TYPE_FONT}, {"image", 0, ASSET_TYPE_IMAGE},
{"style", 0, ASSET_TYPE_STYLE}, {"ui", 0, ASSET_TYPE_UI},
{"strings", 0, ASSET_TYPE_STRINGS}, {"xml", 0, ASSET_TYPE_XML},
{"flow", 0, ASSET_TYPE_FLOW}, {"data", 0, ASSET_TYPE_DATA},
{"script", 0, ASSET_TYPE_SCRIPT},
};
static const key_type_value_t image_draw_type_name_value[] = {
{"default", 0, IMAGE_DRAW_DEFAULT},
{"icon", 0, IMAGE_DRAW_ICON},
{"center", 0, IMAGE_DRAW_CENTER},
{"scale", 0, IMAGE_DRAW_SCALE},
{"auto", 0, IMAGE_DRAW_SCALE_AUTO},
{"scale_auto", 0, IMAGE_DRAW_SCALE_AUTO},
{"scale_down", 0, IMAGE_DRAW_SCALE_DOWN},
{"scale_w", 0, IMAGE_DRAW_SCALE_W},
{"scale_h", 0, IMAGE_DRAW_SCALE_H},
{"repeat", 0, IMAGE_DRAW_REPEAT},
{"repeat_x", 0, IMAGE_DRAW_REPEAT_X},
{"repeat_y", 0, IMAGE_DRAW_REPEAT_Y},
{"repeat_y_inverse", 0, IMAGE_DRAW_REPEAT_Y_INVERSE},
{"patch9", 0, IMAGE_DRAW_PATCH9},
{"patch3_x", 0, IMAGE_DRAW_PATCH3_X},
{"patch3_y", 0, IMAGE_DRAW_PATCH3_Y},
{"patch3_x_scale_y", 0, IMAGE_DRAW_PATCH3_X_SCALE_Y},
{"patch3_y_scale_x", 0, IMAGE_DRAW_PATCH3_Y_SCALE_X},
{"repeat9", 0, IMAGE_DRAW_REPEAT9},
{"repeat3_x", 0, IMAGE_DRAW_REPEAT3_X},
{"repeat3_y", 0, IMAGE_DRAW_REPEAT3_Y}};
static const key_type_value_t easing_type_name_value[] = {
{"linear", 0, EASING_LINEAR},
{"quadratic_in", 0, EASING_QUADRATIC_IN},
{"quadratic_out", 0, EASING_QUADRATIC_OUT},
{"quadratic_inout", 0, EASING_QUADRATIC_INOUT},
{"cubic_in", 0, EASING_CUBIC_IN},
{"cubic_out", 0, EASING_CUBIC_OUT},
{"sin_in", 0, EASING_SIN_IN},
{"sin_out", 0, EASING_SIN_OUT},
{"sin_inout", 0, EASING_SIN_INOUT},
{"pow_in", 0, EASING_POW_IN},
{"pow_out", 0, EASING_POW_OUT},
{"pow_inout", 0, EASING_POW_INOUT},
{"circular_in", 0, EASING_CIRCULAR_IN},
{"circular_out", 0, EASING_CIRCULAR_OUT},
{"circular_inout", 0, EASING_CIRCULAR_INOUT},
{"elastic_in", 0, EASING_ELASTIC_IN},
{"elastic_out", 0, EASING_ELASTIC_OUT},
{"elastic_inout", 0, EASING_ELASTIC_INOUT},
{"back_in", 0, EASING_BACK_IN},
{"back_out", 0, EASING_BACK_OUT},
{"back_inout", 0, EASING_BACK_INOUT},
{"bounce_in", 0, EASING_BOUNCE_IN},
{"bounce_out", 0, EASING_BOUNCE_OUT},
{"bounce_inout", 0, EASING_BOUNCE_INOUT}};
static const key_type_value_t keys_type_name_value[] = {
{"RETURN", 0, TK_KEY_RETURN},
{"ESCAPE", 0, TK_KEY_ESCAPE},
{"BACKSPACE", 0, TK_KEY_BACKSPACE},
{"TAB", 0, TK_KEY_TAB},
{"SPACE", 0, TK_KEY_SPACE},
{"EXCLAIM", 0, TK_KEY_EXCLAIM},
{"QUOTEDBL", 0, TK_KEY_QUOTEDBL},
{"HASH", 0, TK_KEY_HASH},
{"PERCENT", 0, TK_KEY_PERCENT},
{"DOLLAR", 0, TK_KEY_DOLLAR},
{"AMPERSAND", 0, TK_KEY_AMPERSAND},
{"QUOTE", 0, TK_KEY_QUOTE},
{"LEFTPAREN", 0, TK_KEY_LEFTPAREN},
{"RIGHTPAREN", 0, TK_KEY_RIGHTPAREN},
{"ASTERISK", 0, TK_KEY_ASTERISK},
{"PLUS", 0, TK_KEY_PLUS},
{"COMMA", 0, TK_KEY_COMMA},
{"MINUS", 0, TK_KEY_MINUS},
{"PERIOD", 0, TK_KEY_PERIOD},
{"SLASH", 0, TK_KEY_SLASH},
{"0", 0, TK_KEY_0},
{"1", 0, TK_KEY_1},
{"2", 0, TK_KEY_2},
{"3", 0, TK_KEY_3},
{"4", 0, TK_KEY_4},
{"5", 0, TK_KEY_5},
{"6", 0, TK_KEY_6},
{"7", 0, TK_KEY_7},
{"8", 0, TK_KEY_8},
{"9", 0, TK_KEY_9},
{"COLON", 0, TK_KEY_COLON},
{"SEMICOLON", 0, TK_KEY_SEMICOLON},
{"LESS", 0, TK_KEY_LESS},
{"EQUAL", 0, TK_KEY_EQUAL},
{"GREATER", 0, TK_KEY_GREATER},
{"QUESTION", 0, TK_KEY_QUESTION},
{"AT", 0, TK_KEY_AT},
{"LEFTBRACKET", 0, TK_KEY_LEFTBRACKET},
{"BACKSLASH", 0, TK_KEY_BACKSLASH},
{"RIGHTBRACKET", 0, TK_KEY_RIGHTBRACKET},
{"CARET", 0, TK_KEY_CARET},
{"UNDERSCORE", 0, TK_KEY_UNDERSCORE},
{"BACKQUOTE", 0, TK_KEY_BACKQUOTE},
{"a", 0, TK_KEY_a},
{"b", 0, TK_KEY_b},
{"c", 0, TK_KEY_c},
{"d", 0, TK_KEY_d},
{"e", 0, TK_KEY_e},
{"f", 0, TK_KEY_f},
{"g", 0, TK_KEY_g},
{"h", 0, TK_KEY_h},
{"i", 0, TK_KEY_i},
{"j", 0, TK_KEY_j},
{"k", 0, TK_KEY_k},
{"l", 0, TK_KEY_l},
{"m", 0, TK_KEY_m},
{"n", 0, TK_KEY_n},
{"o", 0, TK_KEY_o},
{"p", 0, TK_KEY_p},
{"q", 0, TK_KEY_q},
{"r", 0, TK_KEY_r},
{"s", 0, TK_KEY_s},
{"t", 0, TK_KEY_t},
{"u", 0, TK_KEY_u},
{"v", 0, TK_KEY_v},
{"w", 0, TK_KEY_w},
{"x", 0, TK_KEY_x},
{"y", 0, TK_KEY_y},
{"z", 0, TK_KEY_z},
{"A", 0, TK_KEY_A},
{"B", 0, TK_KEY_B},
{"C", 0, TK_KEY_C},
{"D", 0, TK_KEY_D},
{"E", 0, TK_KEY_E},
{"F", 0, TK_KEY_F},
{"G", 0, TK_KEY_G},
{"H", 0, TK_KEY_H},
{"I", 0, TK_KEY_I},
{"J", 0, TK_KEY_J},
{"K", 0, TK_KEY_K},
{"L", 0, TK_KEY_L},
{"M", 0, TK_KEY_M},
{"N", 0, TK_KEY_N},
{"O", 0, TK_KEY_O},
{"P", 0, TK_KEY_P},
{"Q", 0, TK_KEY_Q},
{"R", 0, TK_KEY_R},
{"S", 0, TK_KEY_S},
{"T", 0, TK_KEY_T},
{"U", 0, TK_KEY_U},
{"V", 0, TK_KEY_V},
{"W", 0, TK_KEY_W},
{"X", 0, TK_KEY_X},
{"Y", 0, TK_KEY_Y},
{"Z", 0, TK_KEY_Z},
{"DOT", 0, TK_KEY_DOT},
{"DELETE", 0, TK_KEY_DELETE},
{"LEFTBRACE", 0, TK_KEY_LEFTBRACE},
{"RIGHTBRACE", 0, TK_KEY_RIGHTBRACE},
{"BACK", 0, TK_KEY_BACK},
{"CANCEL", 0, TK_KEY_CANCEL},
#ifdef WITH_SDL
{"PRINTSCREEN", 0, TK_KEY_PRINTSCREEN},
{"SCROLLLOCK", 0, TK_KEY_SCROLLLOCK},
{"PAUSE", 0, TK_KEY_PAUSE},
{"NUMLOCKCLEAR", 0, TK_KEY_NUMLOCKCLEAR},
{"APPLICATION", 0, TK_KEY_APPLICATION},
{"POWER", 0, TK_KEY_POWER},
{"F13", 0, TK_KEY_F13},
{"F14", 0, TK_KEY_F14},
{"F15", 0, TK_KEY_F15},
{"F16", 0, TK_KEY_F16},
{"F17", 0, TK_KEY_F17},
{"F18", 0, TK_KEY_F18},
{"F19", 0, TK_KEY_F19},
{"F20", 0, TK_KEY_F20},
{"F21", 0, TK_KEY_F21},
{"F22", 0, TK_KEY_F22},
{"F23", 0, TK_KEY_F23},
{"F24", 0, TK_KEY_F24},
{"EXECUTE", 0, TK_KEY_EXECUTE},
{"HELP", 0, TK_KEY_HELP},
{"MENU", 0, TK_KEY_MENU},
{"SELECT", 0, TK_KEY_SELECT},
{"STOP", 0, TK_KEY_STOP},
{"AGAIN", 0, TK_KEY_AGAIN},
{"UNDO", 0, TK_KEY_UNDO},
{"CUT", 0, TK_KEY_CUT},
{"COPY", 0, TK_KEY_COPY},
{"PASTE", 0, TK_KEY_PASTE},
{"FIND", 0, TK_KEY_FIND},
{"MUTE", 0, TK_KEY_MUTE},
{"VOLUMEUP", 0, TK_KEY_VOLUMEUP},
{"VOLUMEDOWN", 0, TK_KEY_VOLUMEDOWN},
{"ALTERASE", 0, TK_KEY_ALTERASE},
{"SYSREQ", 0, TK_KEY_SYSREQ},
{"CLEAR", 0, TK_KEY_CLEAR},
{"PRIOR", 0, TK_KEY_PRIOR},
{"RETURN2", 0, TK_KEY_RETURN2},
{"SEPARATOR", 0, TK_KEY_SEPARATOR},
{"OUT", 0, TK_KEY_OUT},
{"OPER", 0, TK_KEY_OPER},
{"CLEARAGAIN", 0, TK_KEY_CLEARAGAIN},
{"CRSEL", 0, TK_KEY_CRSEL},
{"EXSEL", 0, TK_KEY_EXSEL},
{"THOUSANDSSEPARATOR", 0, TK_KEY_THOUSANDSSEPARATOR},
{"DECIMALSEPARATOR", 0, TK_KEY_DECIMALSEPARATOR},
{"CURRENCYUNIT", 0, TK_KEY_CURRENCYUNIT},
{"CURRENCYSUBUNIT", 0, TK_KEY_CURRENCYSUBUNIT},
{"LGUI", 0, TK_KEY_LGUI},
{"RGUI", 0, TK_KEY_RGUI},
{"MODE", 0, TK_KEY_MODE},
{"AUDIONEXT", 0, TK_KEY_AUDIONEXT},
{"AUDIOPREV", 0, TK_KEY_AUDIOPREV},
{"AUDIOSTOP", 0, TK_KEY_AUDIOSTOP},
{"AUDIOPLAY", 0, TK_KEY_AUDIOPLAY},
{"AUDIOMUTE", 0, TK_KEY_AUDIOMUTE},
{"MEDIASELECT", 0, TK_KEY_MEDIASELECT},
{"WWW", 0, TK_KEY_WWW},
{"MAIL", 0, TK_KEY_MAIL},
{"CALCULATOR", 0, TK_KEY_CALCULATOR},
{"COMPUTER", 0, TK_KEY_COMPUTER},
{"AC_SEARCH", 0, TK_KEY_AC_SEARCH},
{"AC_HOME", 0, TK_KEY_AC_HOME},
{"AC_BACK", 0, TK_KEY_AC_BACK},
{"AC_FORWARD", 0, TK_KEY_AC_FORWARD},
{"AC_STOP", 0, TK_KEY_AC_STOP},
{"AC_REFRESH", 0, TK_KEY_AC_REFRESH},
{"AC_BOOKMARKS", 0, TK_KEY_AC_BOOKMARKS},
{"BRIGHTNESSDOWN", 0, TK_KEY_BRIGHTNESSDOWN},
{"BRIGHTNESSUP", 0, TK_KEY_BRIGHTNESSUP},
{"DISPLAYSWITCH", 0, TK_KEY_DISPLAYSWITCH},
{"KBDILLUMTOGGLE", 0, TK_KEY_KBDILLUMTOGGLE},
{"KBDILLUMDOWN", 0, TK_KEY_KBDILLUMDOWN},
{"KBDILLUMUP", 0, TK_KEY_KBDILLUMUP},
{"EJECT", 0, TK_KEY_EJECT},
{"SLEEP", 0, TK_KEY_SLEEP},
{"APP1", 0, TK_KEY_APP1},
{"APP2", 0, TK_KEY_APP2},
#endif /*WITH_SDL*/
{"LCTRL", 0, TK_KEY_LCTRL},
{"RCTRL", 0, TK_KEY_RCTRL},
{"LSHIFT", 0, TK_KEY_LSHIFT},
{"RSHIFT", 0, TK_KEY_RSHIFT},
{"LALT", 0, TK_KEY_LALT},
{"RALT", 0, TK_KEY_RALT},
{"CAPSLOCK", 0, TK_KEY_CAPSLOCK},
{"HOME", 0, TK_KEY_HOME},
{"END", 0, TK_KEY_END},
{"INSERT", 0, TK_KEY_INSERT},
{"UP", 0, TK_KEY_UP},
{"DOWN", 0, TK_KEY_DOWN},
{"LEFT", 0, TK_KEY_LEFT},
{"RIGHT", 0, TK_KEY_RIGHT},
{"PAGEUP", 0, TK_KEY_PAGEUP},
{"PAGEDOWN", 0, TK_KEY_PAGEDOWN},
{"F1", 0, TK_KEY_F1},
{"F2", 0, TK_KEY_F2},
{"F3", 0, TK_KEY_F3},
{"F4", 0, TK_KEY_F4},
{"F5", 0, TK_KEY_F5},
{"F6", 0, TK_KEY_F6},
{"F7", 0, TK_KEY_F7},
{"F8", 0, TK_KEY_F8},
{"F9", 0, TK_KEY_F9},
{"F10", 0, TK_KEY_F10},
{"F11", 0, TK_KEY_F11},
{"F12", 0, TK_KEY_F12}};
const key_type_value_t* find_item(const key_type_value_t* items, uint32_t nr, const char* name) {
uint32_t i = 0;
return_value_if_fail(items != NULL && name != NULL, NULL);
for (i = 0; i < nr; i++) {
const key_type_value_t* iter = items + i;
if (strcmp(iter->name, name) == 0) {
return iter;
}
}
return NULL;
}
const key_type_value_t* find_item_by_value(const key_type_value_t* items, uint32_t nr,
uint32_t value) {
uint32_t i = 0;
return_value_if_fail(items != NULL, NULL);
for (i = 0; i < nr; i++) {
const key_type_value_t* iter = items + i;
if (iter->value == value) {
return iter;
}
}
return NULL;
}
const key_type_value_t* window_closable_type_find(const char* name) {
return find_item(window_closable_name_value, ARRAY_SIZE(window_closable_name_value), name);
}
const key_type_value_t* align_v_type_find(const char* name) {
return find_item(align_v_name_value, ARRAY_SIZE(align_v_name_value), name);
}
const key_type_value_t* align_h_type_find(const char* name) {
return find_item(align_h_name_value, ARRAY_SIZE(align_h_name_value), name);
}
const key_type_value_t* asset_type_find(const char* name) {
return find_item(asset_type_value, ARRAY_SIZE(asset_type_value), name);
}
const key_type_value_t* asset_type_find_by_value(uint32_t value) {
return find_item_by_value(asset_type_value, ARRAY_SIZE(asset_type_value), value);
}
const key_type_value_t* image_draw_type_find(const char* name) {
return find_item(image_draw_type_name_value, ARRAY_SIZE(image_draw_type_name_value), name);
}
const key_type_value_t* image_draw_type_find_by_value(uint32_t value) {
return find_item_by_value(image_draw_type_name_value, ARRAY_SIZE(image_draw_type_name_value),
value);
}
const key_type_value_t* input_type_find(const char* name) {
return find_item(input_type_name_value, ARRAY_SIZE(input_type_name_value), name);
}
const key_type_value_t* easing_type_find(const char* name) {
return find_item(easing_type_name_value, ARRAY_SIZE(easing_type_name_value), name);
}
const key_type_value_t* easing_type_find_by_value(uint32_t value) {
return find_item_by_value(easing_type_name_value, ARRAY_SIZE(easing_type_name_value), value);
}
const key_type_value_t* keys_type_find(const char* name) {
char fixed_name[TK_NAME_LEN + 1];
return_value_if_fail(name != NULL, NULL);
memset(fixed_name, 0x00, sizeof(fixed_name));
return find_item(keys_type_name_value, ARRAY_SIZE(keys_type_name_value),
tk_normalize_key_name(name, fixed_name));
}
const key_type_value_t* keys_type_find_by_value(uint32_t value) {
return find_item_by_value(keys_type_name_value, ARRAY_SIZE(keys_type_name_value), value);
}

View File

@ -0,0 +1,111 @@
/**
* File: enums.h
* Author: AWTK Develop Team
* Brief: enumerations
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-02-14 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_ENUMS_H
#define TK_ENUMS_H
#include "base/types_def.h"
BEGIN_C_DECLS
typedef struct _key_type_value_t {
const char* name;
uint32_t type;
uint32_t value;
} key_type_value_t;
enum { TYPE_INT = 0, TYPE_COLOR, TYPE_STRING, TYPE_WSTRING, TYPE_BOOL };
/**
* @class enum_helper
* @annotation ["fake"]
*/
const key_type_value_t* input_type_find(const char* name);
const key_type_value_t* window_closable_type_find(const char* name);
const key_type_value_t* align_v_type_find(const char* name);
const key_type_value_t* align_h_type_find(const char* name);
const key_type_value_t* asset_type_find(const char* name);
/**
* @method asset_type_find_by_value
*
* 获取资源类型枚值和名称的对应关系。
*
* @param {uint32_t} value 资源的类型。
*
* @return {const key_type_value_t*} 返回资源类型枚值和名称的对应关系。
*/
const key_type_value_t* asset_type_find_by_value(uint32_t value);
const key_type_value_t* image_draw_type_find(const char* name);
const key_type_value_t* image_draw_type_find_by_value(uint32_t value);
/**
* @method find_item
*
* 获取特定枚值和名称的对应关系。
*
* @param {const key_type_value_t*} items 特定枚举值对应列表。
* @param {uint32_t} nr 列表长度。
* @param {const char*} name 名称。
*
* @return {const key_type_value_t*} 返回资源类型枚值和名称的对应关系。
*/
const key_type_value_t* find_item(const key_type_value_t* items, uint32_t nr, const char* name);
/**
* @method find_item_by_value
*
* 获取特定枚值和名称的对应关系。
*
* @param {const key_type_value_t*} items 特定枚举值对应列表。
* @param {uint32_t} nr 列表长度。
* @param {uint32_t} value 资源的类型。
*
* @return {const key_type_value_t*} 返回资源类型枚值和名称的对应关系。
*/
const key_type_value_t* find_item_by_value(const key_type_value_t* items, uint32_t nr,
uint32_t value);
const key_type_value_t* easing_type_find(const char* name);
const key_type_value_t* easing_type_find_by_value(uint32_t value);
/**
* @method keys_type_find
*
* 获取按键值和名称的对应关系。
*
* @param {const char*} name 按键名。
*
* @return {const key_type_value_t*} 返回按键值和名称的对应关系。
*/
const key_type_value_t* keys_type_find(const char* name);
/**
* @method keys_type_find_by_value
*
* 获取按键值和名称的对应关系。
*
* @param {uint32_t} value 按键值。
*
* @return {const key_type_value_t*} 返回按键值和名称的对应关系。
*/
const key_type_value_t* keys_type_find_by_value(uint32_t value);
END_C_DECLS
#endif /*TK_ENUMS_H*/

View File

@ -0,0 +1,92 @@
/**
* File: event_queue.c
* Author: AWTK Develop Team
* Brief: event_queue
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-03-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "base/event_queue.h"
event_queue_t* event_queue_create(uint16_t capacity) {
uint16_t size = 0;
event_queue_t* q = NULL;
return_value_if_fail(capacity > 1, NULL);
size = sizeof(event_queue_t) + (capacity - 1) * sizeof(event_queue_req_t);
q = (event_queue_t*)TKMEM_ALLOC(size);
return_value_if_fail(q != NULL, NULL);
memset(q, 0x00, size);
q->capacity = capacity;
return q;
}
ret_t event_queue_recv(event_queue_t* q, event_queue_req_t* r) {
return_value_if_fail(q != NULL && r != NULL, RET_BAD_PARAMS);
if (q->r != q->w || q->full) {
memcpy(r, q->events + q->r, sizeof(*r));
if ((q->r + 1) < q->capacity) {
q->r++;
} else {
q->r = 0;
}
q->full = FALSE;
return RET_OK;
}
return RET_FAIL;
}
ret_t event_queue_send(event_queue_t* q, const event_queue_req_t* r) {
return_value_if_fail(q != NULL && r != NULL, RET_BAD_PARAMS);
if (q->r != q->w || !q->full) {
memcpy(q->events + q->w, r, sizeof(*r));
if ((q->w + 1) < q->capacity) {
q->w++;
} else {
q->w = 0;
}
if (q->r == q->w) {
q->full = TRUE;
}
return RET_OK;
}
return RET_FAIL;
}
ret_t event_queue_replace_last(event_queue_t* q, const event_queue_req_t* r) {
return_value_if_fail(q != NULL && r != NULL, RET_BAD_PARAMS);
if (q->w > 0) {
memcpy(q->events + q->w - 1, r, sizeof(*r));
} else {
memcpy(q->events + q->capacity - 1, r, sizeof(*r));
}
return RET_OK;
}
ret_t event_queue_destroy(event_queue_t* q) {
return_value_if_fail(q != NULL, RET_BAD_PARAMS);
TKMEM_FREE(q);
return RET_OK;
}

View File

@ -0,0 +1,91 @@
/**
* File: event_queue.h
* Author: AWTK Develop Team
* Brief: event_queue
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-03-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_EVENT_QUEUE_H
#define TK_EVENT_QUEUE_H
#include "base/idle.h"
#include "base/timer.h"
#include "base/events.h"
BEGIN_C_DECLS
enum { REQ_ADD_IDLE = EVT_REQ_START, REQ_ADD_TIMER, REQ_EXEC_IN_UI };
typedef struct _add_idle_t {
event_t e;
idle_func_t func;
tk_destroy_t on_destroy;
void* on_destroy_ctx;
} add_idle_t;
typedef struct _add_timer_t {
event_t e;
timer_func_t func;
uint32_t duration;
tk_destroy_t on_destroy;
void* on_destroy_ctx;
} add_timer_t;
struct _exec_info_t;
typedef struct _exec_info_t exec_info_t;
typedef ret_t (*exec_func_t)(exec_info_t* info);
struct _exec_info_t {
exec_func_t func;
void* ctx;
void* extra;
};
typedef struct _exec_in_ui_t {
event_t e;
exec_info_t info;
} exec_in_ui_t;
typedef union _event_queue_req_t {
event_t event;
key_event_t key_event;
wheel_event_t wheel_event;
pointer_event_t pointer_event;
multi_gesture_event_t multi_gesture_event;
add_idle_t add_idle;
add_timer_t add_timer;
exec_in_ui_t exec_in_ui;
} event_queue_req_t;
typedef struct _event_queue_t {
uint16_t r;
uint16_t w;
uint16_t full;
uint16_t capacity;
event_queue_req_t events[1];
} event_queue_t;
event_queue_t* event_queue_create(uint16_t capacity);
ret_t event_queue_recv(event_queue_t* q, event_queue_req_t* r);
ret_t event_queue_send(event_queue_t* q, const event_queue_req_t* r);
ret_t event_queue_replace_last(event_queue_t* q, const event_queue_req_t* r);
ret_t event_queue_destroy(event_queue_t* q);
END_C_DECLS
#endif /*TK_EVENT_QUEUE_H*/

View File

@ -0,0 +1,255 @@
/**
* File: event_recorder_player.c
* Author: AWTK Develop Team
* Brief: event_recorder_player
*
* Copyright (c) 2020 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-05-18 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/fs.h"
#include "tkc/types_def.h"
#include "base/main_loop.h"
#include "base/window_manager.h"
#include "base/event_recorder_player.h"
#ifdef WITH_EVENT_RECORDER_PLAYER
typedef union _log_event_t {
key_event_t key_event;
wheel_event_t wheel_event;
pointer_event_t pointer_event;
} log_event_t;
typedef struct _event_recorder_player_t {
fs_file_t* fp;
bool_t playing;
bool_t recording;
uint32_t times;
uint32_t timer_id;
uint64_t last_event_time;
log_event_t pending_event;
} event_recorder_player_t;
static event_recorder_player_t s_event_recorder_player;
static ret_t event_recorder_player_stop(void);
static ret_t event_recorder_player_play(event_recorder_player_t* p);
static ret_t dispatch_event_in_timer(const timer_info_t* info) {
event_recorder_player_t* p = (event_recorder_player_t*)(info->ctx);
return event_recorder_player_play(p);
}
static ret_t event_recorder_player_play(event_recorder_player_t* p) {
log_event_t event;
event_t* e = NULL;
int64_t duration = 0;
if (p->fp == NULL) {
return RET_REMOVE;
}
if (p->last_event_time > 0) {
event_queue_req_t req;
memset(&req, 0x00, sizeof(req));
e = (event_t*)&(p->pending_event);
memcpy(&req, e, sizeof(p->pending_event));
main_loop_queue_event(main_loop(), &req);
} else {
log_debug("prepare first event\n");
}
e = (event_t*)&event;
memset(&event, 0x00, sizeof(event));
if (!fs_file_eof(p->fp) && fs_file_read(p->fp, &event, sizeof(event)) == sizeof(event)) {
if (p->last_event_time == 0) {
p->last_event_time = e->time;
}
memcpy(&(p->pending_event), &event, sizeof(event));
duration = e->time - p->last_event_time;
p->last_event_time = e->time;
if (duration < 0) {
duration = 0;
}
if (duration > 100 * 1000) {
duration = 100;
}
timer_modify(p->timer_id, duration);
return RET_REPEAT;
} else {
p->times--;
if (p->times > 0) {
fs_file_seek(p->fp, 0);
p->last_event_time = 0;
log_debug("play event remain times: %d\n", p->times);
return RET_REPEAT;
} else {
p->playing = FALSE;
fs_file_close(p->fp);
p->fp = NULL;
log_debug("play event done\n");
return RET_REMOVE;
}
}
}
static ret_t event_recorder_player_record(event_recorder_player_t* p, event_t* e) {
log_event_t event;
memset(&event, 0x00, sizeof(event));
if (p->fp == NULL) {
return RET_REMOVE;
}
switch (e->type) {
case EVT_POINTER_DOWN:
case EVT_POINTER_MOVE:
case EVT_POINTER_UP: {
memcpy(&event, e, sizeof(pointer_event_t));
break;
}
case EVT_KEY_DOWN:
case EVT_KEY_UP: {
memcpy(&event, e, sizeof(key_event_t));
break;
}
case EVT_WHEEL: {
memcpy(&event, e, sizeof(wheel_event_t));
break;
}
default: {
return RET_OK;
}
}
ENSURE(fs_file_write(p->fp, &event, sizeof(log_event_t)) == sizeof(log_event_t));
return RET_OK;
}
static ret_t event_recorder_player_on_input_event(void* ctx, event_t* e) {
event_recorder_player_t* p = (event_recorder_player_t*)ctx;
if (p->recording) {
return event_recorder_player_record(p, e);
}
return RET_REMOVE;
}
ret_t event_recorder_player_start_record(const char* filename) {
event_recorder_player_t* p = &s_event_recorder_player;
return_value_if_fail(filename != NULL, RET_BAD_PARAMS);
event_recorder_player_stop();
p->fp = fs_open_file(os_fs(), filename, "wb+");
return_value_if_fail(p->fp != NULL, RET_BAD_PARAMS);
p->recording = TRUE;
widget_on(window_manager(), EVT_POINTER_DOWN, event_recorder_player_on_input_event, p);
widget_on(window_manager(), EVT_POINTER_MOVE, event_recorder_player_on_input_event, p);
widget_on(window_manager(), EVT_POINTER_UP, event_recorder_player_on_input_event, p);
widget_on(window_manager(), EVT_WHEEL, event_recorder_player_on_input_event, p);
widget_on(window_manager(), EVT_KEY_DOWN, event_recorder_player_on_input_event, p);
widget_on(window_manager(), EVT_KEY_UP, event_recorder_player_on_input_event, p);
log_debug("start record events: %s\n", filename);
return RET_OK;
}
ret_t event_recorder_player_start_play(const char* filename, uint32_t times) {
event_recorder_player_t* p = &s_event_recorder_player;
return_value_if_fail(filename != NULL && times > 0, RET_BAD_PARAMS);
event_recorder_player_stop();
p->fp = fs_open_file(os_fs(), filename, "rb");
return_value_if_fail(p->fp != NULL, RET_BAD_PARAMS);
p->times = times;
p->playing = TRUE;
p->timer_id = timer_add(dispatch_event_in_timer, p, 0);
log_debug("start play events: %s\n", filename);
return RET_OK;
}
static ret_t event_recorder_player_stop(void) {
event_recorder_player_t* p = &s_event_recorder_player;
if (p->recording || p->playing) {
fs_file_close(p->fp);
p->fp = NULL;
p->playing = FALSE;
p->recording = FALSE;
if (p->timer_id != TK_INVALID_ID) {
timer_remove(p->timer_id);
p->timer_id = TK_INVALID_ID;
}
widget_off_by_ctx(window_manager(), p);
memset(p, 0x00, sizeof(event_recorder_player_t));
}
return RET_OK;
}
ret_t event_recorder_player_stop_play(void) {
event_recorder_player_t* p = &s_event_recorder_player;
return_value_if_fail(p->playing, RET_BAD_PARAMS);
log_debug("event play stop ok\n");
return event_recorder_player_stop();
}
ret_t event_recorder_player_stop_record(void) {
event_recorder_player_t* p = &s_event_recorder_player;
return_value_if_fail(p->recording, RET_BAD_PARAMS);
log_debug("event record stop ok\n");
return event_recorder_player_stop();
}
#else
ret_t event_recorder_player_start_record(const char* filename) {
return RET_NOT_IMPL;
}
ret_t event_recorder_player_start_play(const char* filename, uint32_t times) {
return RET_NOT_IMPL;
}
ret_t event_recorder_player_stop_play(void) {
return RET_NOT_IMPL;
}
ret_t event_recorder_player_stop_record(void) {
return RET_NOT_IMPL;
}
#endif /*WITH_EVENT_RECORDER_PLAYER*/

View File

@ -0,0 +1,77 @@
/**
* File: event_recorder_player.h
* Author: AWTK Develop Team
* Brief: event_recorder_player
*
* Copyright (c) 2020 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2020-05-18 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_EVENT_RECORDER_PLAYER_H
#define TK_EVENT_RECORDER_PLAYER_H
#include "tkc/types_def.h"
BEGIN_C_DECLS
/**
* @class event_recorder_player_t
* @annotation ["fake"]
* 事件录制与重放,用于辅助自动测试和压力测试。
*
*/
/**
* @method event_recorder_player_start_record
* 开始事件记录。
* @annotation ["static"]
* @param {const char*} filename 用于保存事件的文件名。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t event_recorder_player_start_record(const char* filename);
/**
* @method event_recorder_player_start_play
* 开始事件重放。
* @annotation ["static"]
* @param {const char*} filename 存放事件的文件名。
* @param {uint32_t} times 循环播放的次数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t event_recorder_player_start_play(const char* filename, uint32_t times);
/**
* @method event_recorder_player_stop_record
* 停止事件记录。
* @annotation ["static"]
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t event_recorder_player_stop_record(void);
/**
* @method event_recorder_player_stop_play
* 停止事件重放。
* @annotation ["static"]
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t event_recorder_player_stop_play(void);
END_C_DECLS
#endif /*TK_EVENT_RECORDER_PLAYER_H*/

View File

@ -0,0 +1,370 @@
/**
* File: events.c
* Author: AWTK Develop Team
* Brief: events structs
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-03-02 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "base/events.h"
#include "tkc/time_now.h"
wheel_event_t* wheel_event_cast(event_t* event) {
return_value_if_fail(event != NULL, NULL);
return_value_if_fail(event->type == EVT_WHEEL || event->type == EVT_WHEEL_BEFORE_CHILDREN, NULL);
return_value_if_fail(event->size == sizeof(wheel_event_t), NULL);
return (wheel_event_t*)event;
}
orientation_event_t* orientation_event_cast(event_t* event) {
return_value_if_fail(event != NULL, NULL);
return_value_if_fail(
event->type == EVT_ORIENTATION_CHANGED || event->type == EVT_ORIENTATION_WILL_CHANGED, NULL);
return_value_if_fail(event->size == sizeof(orientation_event_t), NULL);
return (orientation_event_t*)event;
}
pointer_event_t* pointer_event_cast(event_t* event) {
return_value_if_fail(event != NULL, NULL);
return_value_if_fail(event->type >= EVT_POINTER_DOWN && event->type <= EVT_CLICK, NULL);
return_value_if_fail(event->size == sizeof(pointer_event_t), NULL);
return (pointer_event_t*)event;
}
value_change_event_t* value_change_event_cast(event_t* event) {
return_value_if_fail(event != NULL, NULL);
return_value_if_fail(event->type >= EVT_VALUE_WILL_CHANGE && event->type <= EVT_VALUE_CHANGING,
NULL);
return_value_if_fail(event->size == sizeof(value_change_event_t), NULL);
return (value_change_event_t*)event;
}
offset_change_event_t* offset_change_event_cast(event_t* event) {
return_value_if_fail(event != NULL, NULL);
return_value_if_fail(event->size == sizeof(offset_change_event_t), NULL);
return (offset_change_event_t*)event;
}
key_event_t* key_event_cast(event_t* event) {
return_value_if_fail(event != NULL, NULL);
return_value_if_fail(event->type >= EVT_KEY_DOWN && event->type <= EVT_KEY_UP_BEFORE_CHILDREN,
NULL);
return_value_if_fail(event->size == sizeof(key_event_t), NULL);
return (key_event_t*)event;
}
paint_event_t* paint_event_cast(event_t* event) {
return_value_if_fail(event != NULL, NULL);
return_value_if_fail(
event->type == EVT_PAINT || event->type == EVT_BEFORE_PAINT || event->type == EVT_AFTER_PAINT,
NULL);
return_value_if_fail(event->size == sizeof(paint_event_t), NULL);
return (paint_event_t*)event;
}
window_event_t* window_event_cast(event_t* event) {
return_value_if_fail(event != NULL, NULL);
return_value_if_fail(event->type == EVT_WINDOW_WILL_OPEN || event->type == EVT_WINDOW_OPEN ||
event->type == EVT_WINDOW_CLOSE,
NULL);
return_value_if_fail(event->size == sizeof(window_event_t), NULL);
return (window_event_t*)event;
}
ret_t pointer_event_rotate(pointer_event_t* evt, system_info_t* info) {
xy_t x = evt->x;
xy_t y = evt->y;
return_value_if_fail(evt != NULL && info != NULL, RET_BAD_PARAMS);
switch (info->lcd_orientation) {
case LCD_ORIENTATION_90: {
#ifdef WITH_GPU
evt->y = info->lcd_w - x - 1;
evt->x = y;
#else
evt->y = x;
evt->x = info->lcd_h - y - 1;
#endif
break;
}
case LCD_ORIENTATION_180: {
evt->y = info->lcd_h - y - 1;
evt->x = info->lcd_w - x - 1;
break;
}
case LCD_ORIENTATION_270: {
#ifdef WITH_GPU
evt->y = x;
evt->x = info->lcd_h - y - 1;
#else
evt->y = info->lcd_w - x - 1;
evt->x = y;
#endif
break;
}
default:
break;
}
return RET_OK;
}
event_t* wheel_event_init(wheel_event_t* event, uint32_t type, void* target, int32_t dy) {
return_value_if_fail(event != NULL, NULL);
memset(event, 0x00, sizeof(wheel_event_t));
event->e = event_init(type, target);
event->e.size = sizeof(*event);
event->dy = dy;
return (event_t*)event;
}
event_t* orientation_event_init(orientation_event_t* event, uint32_t type, void* target,
lcd_orientation_t old_orientation,
lcd_orientation_t new_orientation) {
return_value_if_fail(event != NULL, NULL);
memset(event, 0x00, sizeof(orientation_event_t));
event->e = event_init(type, target);
event->e.size = sizeof(*event);
event->orientation = new_orientation;
event->old_orientation = old_orientation;
return (event_t*)event;
}
event_t* pointer_event_init(pointer_event_t* event, uint32_t type, void* target, int32_t x,
int32_t y) {
return_value_if_fail(event != NULL, NULL);
memset(event, 0x00, sizeof(*event));
event->e = event_init(type, target);
event->e.size = sizeof(*event);
event->x = x;
event->y = y;
return (event_t*)event;
}
event_t* value_change_event_init(value_change_event_t* event, uint32_t type, void* target) {
return_value_if_fail(event != NULL, NULL);
memset(event, 0x00, sizeof(*event));
event->e = event_init(type, target);
event->e.size = sizeof(*event);
return (event_t*)event;
}
event_t* offset_change_event_init(offset_change_event_t* event, uint32_t type, void* target,
float_t old_offset, float_t new_offset) {
return_value_if_fail(event != NULL, NULL);
memset(event, 0x00, sizeof(*event));
event->e = event_init(type, target);
event->e.size = sizeof(*event);
event->old_offset = old_offset;
event->new_offset = new_offset;
return (event_t*)event;
}
event_t* key_event_init(key_event_t* event, uint32_t type, void* target, int32_t key) {
return_value_if_fail(event != NULL, NULL);
memset(event, 0x00, sizeof(key_event_t));
event->e = event_init(type, target);
event->e.size = sizeof(*event);
event->key = key;
return (event_t*)event;
}
event_t* paint_event_init(paint_event_t* event, uint32_t type, void* target, canvas_t* c) {
return_value_if_fail(event != NULL, NULL);
memset(event, 0x00, sizeof(paint_event_t));
event->e = event_init(type, target);
event->e.size = sizeof(*event);
event->c = c;
return (event_t*)event;
}
event_t* window_event_init(window_event_t* event, uint32_t type, void* target, widget_t* window) {
return_value_if_fail(event != NULL, NULL);
memset(event, 0x00, sizeof(window_event_t));
event->e = event_init(type, target);
event->window = window;
return (event_t*)event;
}
multi_gesture_event_t* multi_gesture_event_cast(event_t* event) {
return_value_if_fail(event != NULL, NULL);
return_value_if_fail(event->type == EVT_MULTI_GESTURE, NULL);
return_value_if_fail(event->size == sizeof(multi_gesture_event_t), NULL);
return (multi_gesture_event_t*)event;
}
event_t* multi_gesture_event_init(multi_gesture_event_t* event, void* target, int32_t x, int32_t y,
float rotation, float distance) {
return_value_if_fail(event != NULL, NULL);
memset(event, 0x00, sizeof(multi_gesture_event_t));
event->e = event_init(EVT_MULTI_GESTURE, target);
event->e.size = sizeof(*event);
event->x = x;
event->y = y;
event->rotation = rotation;
event->distance = distance;
return (event_t*)event;
}
event_t* assets_event_init(assets_event_t* event, assets_manager_t* am, uint32_t type,
asset_type_t asset_type, asset_info_t* asset_info) {
return_value_if_fail(event != NULL, NULL);
memset(event, 0x00, sizeof(assets_event_t));
event->e = event_init(type, am);
event->e.size = sizeof(*event);
event->type = asset_type;
event->asset_info = asset_info;
return (event_t*)event;
}
theme_change_event_t* theme_change_event_cast(event_t* event) {
return_value_if_fail(event != NULL, NULL);
return_value_if_fail(event->type == EVT_THEME_CHANGED || event->type == EVT_THEME_WILL_CHANGE,
NULL);
return_value_if_fail(event->size == sizeof(theme_change_event_t), NULL);
return (theme_change_event_t*)event;
}
event_t* theme_change_event_init(theme_change_event_t* event, uint32_t type, const char* name) {
return_value_if_fail(event != NULL, NULL);
memset(event, 0x00, sizeof(*event));
event->e = event_init(type, NULL);
event->e.size = sizeof(*event);
event->name = name;
return (event_t*)(event);
}
int32_t event_from_name(const char* name) {
return_value_if_fail(name != NULL, EVT_NONE);
switch (*name) {
case 'f': {
if (tk_str_eq(name, "focus")) {
return EVT_FOCUS;
}
}
case 'b': {
if (tk_str_eq(name, "blur")) {
return EVT_BLUR;
}
}
case 'g': {
if (tk_str_eq(name, "global_key_up")) {
return EVT_KEY_UP;
} else if (tk_str_eq(name, "global_key_down")) {
return EVT_KEY_DOWN;
} else if (tk_str_eq(name, "global_key_long_press")) {
return EVT_KEY_LONG_PRESS;
}
break;
}
case 'k': {
if (tk_str_eq(name, "key_up")) {
return EVT_KEY_UP;
} else if (tk_str_eq(name, "key_down")) {
return EVT_KEY_DOWN;
} else if (tk_str_eq(name, "key_long_press")) {
return EVT_KEY_LONG_PRESS;
} else if (tk_str_eq(name, "key_down_before_children")) {
return EVT_KEY_DOWN_BEFORE_CHILDREN;
} else if (tk_str_eq(name, "key_up_before_children")) {
return EVT_KEY_UP_BEFORE_CHILDREN;
}
break;
}
case 'p': {
if (tk_str_eq(name, "pointer_up")) {
return EVT_POINTER_UP;
} else if (tk_str_eq(name, "pointer_down")) {
return EVT_POINTER_DOWN;
} else if (tk_str_eq(name, "pointer_move")) {
return EVT_POINTER_MOVE;
}
break;
}
case 'c': {
if (tk_str_eq(name, "click")) {
return EVT_CLICK;
}
break;
}
case 't': {
if (tk_str_eq(name, "timer")) {
return EVT_TIMER;
}
break;
}
case 'w': {
if (tk_str_eq(name, "window_close")) {
return EVT_WINDOW_CLOSE;
} else if (tk_str_eq(name, "window_open")) {
return EVT_WINDOW_OPEN;
} else if (tk_str_eq(name, "window_will_open")) {
return EVT_WINDOW_WILL_OPEN;
}
break;
}
case 'v': {
if (tk_str_eq(name, "value_changed")) {
return EVT_VALUE_CHANGED;
} else if (tk_str_eq(name, STR_VALUE_CHANGED_BY_UI)) {
return EVT_VALUE_CHANGED;
}
break;
}
case 'i': {
if (tk_str_eq(name, "im_action")) {
return EVT_IM_ACTION;
}
break;
}
default:
break;
}
return EVT_NONE;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
/**
* File: font.c
* Author: AWTK Develop Team
* Brief: font interface
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "base/font.h"
ret_t font_get_glyph(font_t* f, wchar_t chr, font_size_t font_size, glyph_t* g) {
return_value_if_fail(f != NULL && f->get_glyph != NULL && g != NULL, RET_BAD_PARAMS);
return f->get_glyph(f, chr, font_size, g);
}
ret_t font_shrink_cache(font_t* f, uint32_t cache_size) {
return_value_if_fail(f != NULL, RET_BAD_PARAMS);
if (f->shrink_cache != NULL) {
f->shrink_cache(f, cache_size);
}
return RET_OK;
}
font_vmetrics_t font_get_vmetrics(font_t* f, font_size_t font_size) {
font_vmetrics_t vmetrics = {font_size, 0, 0};
if (f != NULL && f->get_vmetrics != NULL) {
return f->get_vmetrics(f, font_size);
} else {
return vmetrics;
}
}
bool_t font_match(font_t* f, const char* name, font_size_t font_size) {
return_value_if_fail(f != NULL && f->match != NULL, FALSE);
return f->match(f, name, font_size);
}
ret_t font_destroy(font_t* f) {
return_value_if_fail(f != NULL && f->destroy != NULL, RET_BAD_PARAMS);
return f->destroy(f);
}
glyph_t* glyph_create(void) {
return TKMEM_ZALLOC(glyph_t);
}
glyph_t* glyph_clone(glyph_t* old) {
glyph_t* g = NULL;
return_value_if_fail(old != NULL, NULL);
g = glyph_create();
return_value_if_fail(g != NULL, NULL);
*g = *old;
return g;
}
ret_t glyph_destroy(glyph_t* g) {
return_value_if_fail(g != NULL, RET_BAD_PARAMS);
TKMEM_FREE(g);
return RET_OK;
}

View File

@ -0,0 +1,228 @@
/**
* File: font.h
* Author: AWTK Develop Team
* Brief: font interface
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_FONT_H
#define TK_FONT_H
#include "base/types_def.h"
BEGIN_C_DECLS
/**
* @enum glyph_format_t
* @prefix GLYPH_FMT_
* @annotation ["scriptable"]
* 字模格式常量定义。
*/
typedef enum _glyph_format_t {
/**
* @const GLYPH_FMT_ALPHA
* 每个像素占用1个字节(缺省)。
*/
GLYPH_FMT_ALPHA,
/**
* @const GLYPH_FMT_MONO
* 每个像素占用1个比特。
*/
GLYPH_FMT_MONO,
/**
* @const GLYPH_FMT_RGBA
* 每个像素占用4个字节。
*/
GLYPH_FMT_RGBA
} glyph_format_t;
struct _font_t;
typedef struct _font_t font_t;
/**
* @class glyph_t
* 代表一个字符的字模。
*
*/
#pragma pack(push, 1)
typedef struct _glyph_t {
/**
* @property {int16_t} x
* @annotation ["readable"]
* x坐标。
*/
int16_t x;
/**
* @property {int16_t} y
* @annotation ["readable"]
* y坐标。
*/
int16_t y;
/**
* @property {uint16_t} w
* @annotation ["readable"]
* 宽度。
*/
uint16_t w;
/**
* @property {uint16_t} h
* @annotation ["readable"]
* 高度。
*/
uint16_t h;
/**
* @property {uint16_t} advance
* @annotation ["readable"]
* 占位宽度。
*/
uint16_t advance : 16;
/**
* @property {uint8_t} format
* @annotation ["readable"]
* 格式。
*/
uint8_t format : 8;
/**
* @property {uint8_t} pitch
* @annotation ["readable"]
* pitch。
*/
uint8_t pitch : 8;
/**
* @property {const uint8_t*} data
* @annotation ["readable"]
* 数据。
*/
const uint8_t* data;
} glyph_t;
#pragma pack(pop)
/**
* @method glyph_create
* @annotation ["constructor"]
* 创建glyph对象。
*
* @return {glyph_t*} glyph对象。
*/
glyph_t* glyph_create(void);
/**
* @method glyph_clone
* @annotation ["constructor"]
* 克隆glyph对象。
*
* @return {glyph_t*} glyph对象。
*/
glyph_t* glyph_clone(glyph_t* g);
/**
* @method glyph_destroy
* 销毁glyph对象。
* @annotation ["deconstructor"]
* @param {glyph_t*} glyph glyph对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t glyph_destroy(glyph_t* g);
typedef struct _font_vmetrics_t {
int16_t ascent;
int16_t descent;
int32_t line_gap;
} font_vmetrics_t;
typedef font_vmetrics_t (*font_get_vmetrics_t)(font_t* f, font_size_t font_size);
typedef bool_t (*font_match_t)(font_t* f, const char* name, font_size_t font_size);
typedef ret_t (*font_get_glyph_t)(font_t* f, wchar_t chr, font_size_t font_size, glyph_t* g);
typedef ret_t (*font_shrink_cache_t)(font_t* f, uint32_t cache_size);
typedef ret_t (*font_destroy_t)(font_t* f);
/**
* @class font_t
* 代表一种字体。
*
*/
struct _font_t {
char name[TK_NAME_LEN + 1];
font_match_t match;
font_get_glyph_t get_glyph;
font_get_vmetrics_t get_vmetrics;
font_shrink_cache_t shrink_cache;
font_destroy_t destroy;
const char* desc;
};
/**
* @method font_get_vmetrics
* 获取字体的高度信息。
* @param {font_t*} font font对象。
* @param {font_size_t} font_size 字体大小。
*
* @return {font_vmetrics_t} 返回字体的高度信息。
*/
font_vmetrics_t font_get_vmetrics(font_t* font, font_size_t font_size);
/**
* @method font_match
* 检查当前字体是否与指定名称和大小相匹配。
*
* @param {font_t*} font font对象。
* @param {const char*} font_name 字体名称。
* @param {font_size_t} font_size 字体大小。
*
* @return {int32_t} 返回TRUE表示成功FALSE表示失败。
*/
bool_t font_match(font_t* font, const char* font_name, font_size_t font_size);
/**
* @method font_get_glyph
* 获取指定字符和大小的字模。
*
* @param {font_t*} font font对象。
* @param {wchar_t} chr 字符。
* @param {font_size_t} font_size 字体大小。
* @param {glyph_t*} glyph 返回字模数据。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t font_get_glyph(font_t* font, wchar_t chr, font_size_t font_size, glyph_t* glyph);
/**
* @method font_shrink_cache
* 清除最近没使用的字模。
*
* @param {font_t*} font font对象。
* @param {uint32_t} cache_size 保留缓存字模的个数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t font_shrink_cache(font_t* font, uint32_t cache_size);
/**
* @method font_destroy
* 销毁font对象。
* @annotation ["deconstructor"]
* @param {font_t*} font font对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t font_destroy(font_t* font);
END_C_DECLS
#endif /*TK_FONT_H*/

View File

@ -0,0 +1,30 @@
/**
* File: font_loader.h
* Author: AWTK Develop Team
* Brief: font_loader interface
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-10-19 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "base/font_loader.h"
font_t* font_loader_load(font_loader_t* loader, const char* name, const uint8_t* buff,
uint32_t size) {
return_value_if_fail(loader != NULL && loader->load != NULL && name != NULL && buff != NULL,
NULL);
return loader->load(loader, name, buff, size);
}

View File

@ -0,0 +1,62 @@
/**
* File: font_loader.h
* Author: AWTK Develop Team
* Brief: font_loader interface
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-10-19 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_FONT_LOADER_H
#define TK_FONT_LOADER_H
#include "base/font.h"
#include "base/assets_manager.h"
BEGIN_C_DECLS
struct _font_loader_t;
typedef struct _font_loader_t font_loader_t;
typedef font_t* (*font_loader_load_t)(font_loader_t* loader, const char* name, const uint8_t* buff,
uint32_t size);
/**
* @class font_loader_t
* 字体加载接口。
*/
struct _font_loader_t {
asset_font_type_t type;
font_loader_load_t load;
};
/**
* @method font_loader_load
* 加载字体。
*
* @param {font_loader_t*} loader loader对象。
* @param {const char*} name 字体名字。
* @param {uint8_t*} buff 字体数据。
* @param {uint32_t} size 字体数据长度。
*
* @return {font_t*} 成功返回font失败返回NULL。
*/
font_t* font_loader_load(font_loader_t* loader, const char* name, const uint8_t* buff,
uint32_t size);
END_C_DECLS
#endif /*TK_FONT_LOADER_H*/

View File

@ -0,0 +1,246 @@
/**
* File: font_manager.c
* Author: AWTK Develop Team
* Brief: font manager
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/events.h"
#include "base/system_info.h"
#include "base/font_manager.h"
static font_manager_t* s_font_manager = NULL;
typedef struct _font_cmp_info_t {
const char* name;
uint32_t size;
} font_cmp_info_t;
static int32_t font_cmp(font_t* font, font_cmp_info_t* info) {
if (font_match(font, info->name, info->size)) {
return 0;
}
return -1;
}
font_manager_t* font_manager(void) {
return s_font_manager;
}
ret_t font_manager_set(font_manager_t* fm) {
s_font_manager = fm;
return RET_OK;
}
font_manager_t* font_manager_create(font_loader_t* loader) {
font_manager_t* fm = TKMEM_ZALLOC(font_manager_t);
return font_manager_init(fm, loader);
}
font_manager_t* font_manager_init(font_manager_t* fm, font_loader_t* loader) {
return_value_if_fail(fm != NULL, NULL);
darray_init(&(fm->fonts), 2, (tk_destroy_t)font_destroy, (tk_compare_t)font_cmp);
fm->loader = loader;
fm->assets_manager = NULL;
return fm;
}
static ret_t font_manager_on_asset_events(void* ctx, event_t* e) {
assets_event_t* evt = (assets_event_t*)e;
font_manager_t* fm = (font_manager_t*)ctx;
if (evt->type == ASSET_TYPE_FONT) {
asset_info_t* info = evt->asset_info;
if (e->type == EVT_ASSET_MANAGER_CLEAR_CACHE) {
font_manager_unload_all(fm);
} else if (e->type == EVT_ASSET_MANAGER_UNLOAD_ASSET) {
font_manager_unload_font(fm, info->name, 0);
}
}
return RET_OK;
}
ret_t font_manager_set_assets_manager(font_manager_t* fm, assets_manager_t* am) {
return_value_if_fail(fm != NULL, RET_BAD_PARAMS);
if (fm->assets_manager != NULL && fm->assets_manager != am) {
emitter_off_by_ctx(EMITTER(fm->assets_manager), fm);
}
if (am != NULL && fm->assets_manager != am) {
emitter_on(EMITTER(am), EVT_ASSET_MANAGER_CLEAR_CACHE, font_manager_on_asset_events, fm);
emitter_on(EMITTER(am), EVT_ASSET_MANAGER_UNLOAD_ASSET, font_manager_on_asset_events, fm);
}
fm->assets_manager = am;
return RET_OK;
}
ret_t font_manager_add_font(font_manager_t* fm, font_t* font) {
return_value_if_fail(fm != NULL && font != NULL, RET_BAD_PARAMS);
return darray_push(&(fm->fonts), font);
}
#if WITH_BITMAP_FONT
static const char* font_manager_fix_bitmap_font_name(char str[MAX_PATH], const char* name,
font_size_t size) {
memset(str, 0, MAX_PATH);
tk_snprintf(str, MAX_PATH, "%s_%d", name, size);
return str;
}
#endif
font_t* font_manager_lookup(font_manager_t* fm, const char* name, font_size_t size) {
#if WITH_BITMAP_FONT
font_t* font = NULL;
char font_name[MAX_PATH];
font_cmp_info_t info_bitmap;
#endif
font_cmp_info_t info = {name, size};
return_value_if_fail(fm != NULL, NULL);
#if WITH_BITMAP_FONT
info_bitmap.name = font_manager_fix_bitmap_font_name(font_name, name, size);
info_bitmap.size = size;
font = darray_find(&(fm->fonts), &info_bitmap);
if (font != NULL) {
return font;
}
#endif
return darray_find(&(fm->fonts), &info);
}
font_t* font_manager_load(font_manager_t* fm, const char* name, uint32_t size) {
font_t* font = NULL;
if (fm->loader != NULL) {
const asset_info_t* info = NULL;
#if WITH_BITMAP_FONT
char font_name[MAX_PATH];
font_manager_fix_bitmap_font_name(font_name, name, size);
info = assets_manager_ref(fm->assets_manager, ASSET_TYPE_FONT, font_name);
if (info != NULL) {
name = font_name;
}
#endif
if (info == NULL) {
info = assets_manager_ref(fm->assets_manager, ASSET_TYPE_FONT, name);
}
if (info != NULL) {
if (info->subtype == fm->loader->type) {
font = font_loader_load(fm->loader, name, info->data, info->size);
}
assets_manager_unref(fm->assets_manager, info);
}
}
return font;
}
font_t* font_manager_get_font(font_manager_t* fm, const char* name, font_size_t size) {
font_t* font = NULL;
const char* default_font = system_info()->default_font;
name = system_info_fix_font_name(name);
name = asset_info_get_formatted_name(name);
return_value_if_fail(fm != NULL, NULL);
font = font_manager_lookup(fm, name, size);
if (font == NULL) {
font = font_manager_load(fm, name, size);
if (font != NULL) {
font_manager_add_font(fm, font);
} else if (tk_str_cmp(name, default_font) != 0) {
font = font_manager_get_font(fm, default_font, size);
}
}
return font;
}
ret_t font_manager_unload_font(font_manager_t* fm, const char* name, font_size_t size) {
ret_t ret = RET_OK;
font_cmp_info_t info = {name, size};
#if WITH_BITMAP_FONT
char font_name[MAX_PATH];
font_cmp_info_t info_bitmap;
#endif
name = system_info_fix_font_name(name);
return_value_if_fail(fm != NULL, RET_FAIL);
#if WITH_BITMAP_FONT
info_bitmap.name = font_manager_fix_bitmap_font_name(font_name, name, size);
info_bitmap.size = size;
ret = darray_remove(&(fm->fonts), &info_bitmap);
#endif
ret = darray_remove(&(fm->fonts), &info);
if (ret == RET_OK) {
assets_manager_clear_cache_ex(assets_manager(), ASSET_TYPE_FONT, name);
}
return ret;
}
ret_t font_manager_unload_all(font_manager_t* fm) {
return_value_if_fail(fm != NULL, RET_FAIL);
return darray_clear(&(fm->fonts));
}
ret_t font_manager_deinit(font_manager_t* fm) {
return_value_if_fail(fm != NULL, RET_BAD_PARAMS);
return darray_deinit(&(fm->fonts));
}
ret_t font_manager_destroy(font_manager_t* fm) {
return_value_if_fail(fm != NULL, RET_BAD_PARAMS);
emitter_off_by_ctx(EMITTER(fm->assets_manager), fm);
font_manager_deinit(fm);
TKMEM_FREE(fm);
return RET_OK;
}
ret_t font_manager_shrink_cache(font_manager_t* fm, uint32_t cache_size) {
uint32_t i = 0;
font_t* font = NULL;
return_value_if_fail(fm != NULL, RET_FAIL);
for (i = 0; i < fm->fonts.size; i++) {
font = (font_t*)darray_get(&(fm->fonts), i);
font_shrink_cache(font, cache_size);
}
return RET_OK;
}

View File

@ -0,0 +1,199 @@
/**
* File: font_manager.h
* Author: AWTK Develop Team
* Brief: font manager
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_FONT_MANAGER_H
#define TK_FONT_MANAGER_H
#include "tkc/darray.h"
#include "base/types_def.h"
#include "base/font_loader.h"
#include "base/assets_manager.h"
BEGIN_C_DECLS
/**
* @class font_manager_t
* @annotation ["scriptable"]
* 字体管理器,负责字体的加载和缓存管理。
* (如果使用nanovg字体由nanovg内部管理)
*/
typedef struct _font_manager_t {
darray_t fonts;
/**
* @property {font_loader_t*} loader
* @annotation ["private"]
* 字体加载器。
*/
font_loader_t* loader;
/**
* @property {assets_manager_t*} assets_manager
* @annotation ["private"]
* 资源管理器。
*/
assets_manager_t* assets_manager;
} font_manager_t;
/**
* @method font_manager
* 获取缺省的字体管理器。
* @annotation ["constructor"]
* @return {font_manager_t*} 返回字体管理器对象。
*/
font_manager_t* font_manager(void);
/**
* @method font_manager_set
* 设置缺省的字体管理器。
* @param {font_manager_t*} fm 字体管理器对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t font_manager_set(font_manager_t* fm);
/**
* @method font_manager_create
* 创建字体管理器。
* @annotation ["constructor"]
* @param {font_loader_t*} loader 字体加载器。
*
* @return {font_manager_t*} 返回字体管理器对象。
*/
font_manager_t* font_manager_create(font_loader_t* loader);
/**
* @method font_manager_init
* 初始化字体管理器。
* @annotation ["constructor"]
* @param {font_manager_t*} fm 字体管理器对象。
* @param {font_loader_t*} loader 字体加载器。
*
* @return {font_manager_t*} 返回字体管理器对象。
*/
font_manager_t* font_manager_init(font_manager_t* fm, font_loader_t* loader);
/**
* @method font_manager_set_assets_manager
* 设置资源管理器对象
*
* 之所以需要设置资源管理器对象而不是使用缺省的资源管理器对象是因为在designer中有两个字体管理器
*
* * 一个用于designer本身加载字体。
*
* * 一个用于被设计的窗口加载字体。
*
*这两个字体管理器需要从不同的路径加载资源。
* @param {font_manager_t*} imm 字体管理器对象。
* @param {assets_manager_t*} assets_manager 资源管理器。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t font_manager_set_assets_manager(font_manager_t* imm, assets_manager_t* assets_manager);
/**
* @method font_manager_add_font
* 向缓存中加入字体。
* @param {font_manager_t*} fm 字体管理器对象。
* @param {char*} name 字体名。
* @param {font_t*} font 字体。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t font_manager_add_font(font_manager_t* fm, font_t* font);
/**
* @method font_manager_get_font
* 从缓存中查找字体,如果没找到,再加载字体,并缓存。
* @param {font_manager_t*} fm 字体管理器对象。
* @param {char*} name 字体名为NULL时使用缺省字体。
* @param {font_size_t} size 字体的大小。
*
* @return {font_t*} 返回字体对象。
*/
font_t* font_manager_get_font(font_manager_t* fm, const char* name, font_size_t size);
/**
* @method font_manager_unload_font
* 卸载指定的字体。
* @annotation ["scriptable"]
* @param {font_manager_t*} fm 字体管理器对象。
* @param {char*} name 字体名为NULL时使用缺省字体。
* @param {font_size_t} size 字体的大小(矢量字体指定为0即可)。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t font_manager_unload_font(font_manager_t* fm, const char* name, font_size_t size);
/**
* @method font_manager_shrink_cache
* 清除最久没有被使用的缓冲字模。
* @annotation ["scriptable"]
* @param {font_manager_t*} fm 字体管理器对象。
* @param {uint32_t} cache_size 每种字体保留缓存字模的个数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t font_manager_shrink_cache(font_manager_t* fm, uint32_t cache_size);
/**
* @method font_manager_unload_all
* 卸载全部字体。
* @annotation ["scriptable"]
* @param {font_manager_t*} fm 字体管理器对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t font_manager_unload_all(font_manager_t* fm);
/**
* @method font_manager_deinit
* 析构字体管理器。
* @param {font_manager_t*} fm 字体管理器对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t font_manager_deinit(font_manager_t* fm);
/**
* @method font_manager_destroy
* 析构并释放字体管理器。
* @param {font_manager_t*} fm 字体管理器对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t font_manager_destroy(font_manager_t* fm);
/*public for test*/
/**
* @method font_manager_lookup
* 查找字体。
* @param {font_manager_t*} fm 字体管理器对象。
* @param {const char*} name 字体名称。
* @param {int32_t} size 字体大小。
*
* @return {font_t*} 返回字体对象。
*/
font_t* font_manager_lookup(font_manager_t* fm, const char* name, font_size_t size);
END_C_DECLS
#endif /*TK_FONT_MANAGER_H*/

View File

@ -0,0 +1,94 @@
/**
* File: g2d.h
* Author: AWTK Develop Team
* Brief: hardware 2d
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* this program is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. see the
* license file for more details.
*
*/
/**
* history:
* ================================================================
* 2018-05-07 li xianjing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_G2D_H
#define TK_G2D_H
#include "tkc/rect.h"
#include "base/bitmap.h"
BEGIN_C_DECLS
/**
* @class g2d_t
*
* 2D加速接口。
*
*/
/**
* @method g2d_fill_rect
* @export none
* 用颜色填充指定的区域。
* @param {bitmap_t*} fb framebuffer对象。
* @param {const rect_t*} dst 要填充的目标区域。
* @param {color_t} c 颜色。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败返回失败则上层用软件实现。
*/
ret_t g2d_fill_rect(bitmap_t* fb, const rect_t* dst, color_t c);
/**
* @method g2d_copy_image
* @export none
* 把图片指定的区域拷贝到framebuffer中。
* @param {bitmap_t*} fb framebuffer对象。
* @param {bitmap_t*} img 图片对象。
* @param {const rect_t*} src 要拷贝的区域。
* @param {xy_t} dx 目标位置的x坐标。
* @param {xy_t} dy 目标位置的y坐标。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败返回失败则上层用软件实现。
*/
ret_t g2d_copy_image(bitmap_t* fb, bitmap_t* img, const rect_t* src, xy_t dx, xy_t dy);
/**
* @method g2d_rotate_image
* @export none
* 把图片指定的区域进行旋转并拷贝到framebuffer相应的区域本函数主要用于辅助实现横屏和竖屏的切换一般支持90度旋转即可。
* @param {bitmap_t*} fb framebuffer对象。
* @param {bitmap_t*} img 图片对象。
* @param {const rect_t*} src 要旋转并拷贝的区域。
* @param {lcd_orientation_t} o 旋转角度(一般支持90度即可)。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败返回失败则上层用软件实现。
*/
ret_t g2d_rotate_image(bitmap_t* fb, bitmap_t* img, const rect_t* src, lcd_orientation_t o);
/**
* @method g2d_blend_image
* @export none
* 把图片指定的区域渲染到framebuffer指定的区域src的大小和dst的大小不一致则进行缩放。
* 1.硬件不支持缩放则返回NOT_IMPL。
* 2.硬件不支持全局alphaglobal_alpha!=0xff时返回NOT_IMPL。
* @param {bitmap_t*} fb framebuffer对象。
* @param {bitmap_t*} img 图片对象。
* @param {const rect_t*} dst 目的区域。
* @param {const rect_t*} src 源区域。
* @param {uint8_t} global_alpha 全局alpha。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败返回失败则上层用软件实现。
*/
ret_t g2d_blend_image(bitmap_t* fb, bitmap_t* img, const rect_t* dst, const rect_t* src,
uint8_t global_alpha);
END_C_DECLS
#endif /*TK_G2D_H*/

View File

@ -0,0 +1,152 @@
/**
* File: glyph_cache.c
* Author: AWTK Develop Team
* Brief: glyph cache
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-06-10 Li XianJing <xianjimli@hotmail.com> created
*
*/
#define GLYPH_CACHE_FREE_ITEM(cache, item) \
{ \
if (cache->destroy_glyph && item->g != NULL) { \
cache->destroy_glyph(item->g); \
memset(item, 0x00, sizeof(glyph_cache_item_t)); \
} \
}
#include "tkc/mem.h"
#include "tkc/time_now.h"
#include "base/glyph_cache.h"
glyph_cache_t* glyph_cache_init(glyph_cache_t* cache, uint32_t capacity,
tk_destroy_t destroy_glyph) {
return_value_if_fail(cache != NULL && capacity > 0, NULL);
cache->items = TKMEM_ZALLOCN(glyph_cache_item_t, capacity);
return_value_if_fail(cache->items != NULL, NULL);
cache->size = 0;
cache->capacity = capacity;
cache->destroy_glyph = destroy_glyph;
return cache;
}
static glyph_cache_item_t* glyph_cache_get_empty(glyph_cache_t* cache) {
uint32_t i = 0;
uint32_t nr = 0;
uint32_t oldest = 0;
glyph_cache_item_t* item = NULL;
uint32_t oldest_time = 0xffffffff;
return_value_if_fail(cache != NULL && cache->items != NULL, NULL);
if (cache->size < cache->capacity) {
oldest = cache->size++;
return cache->items + oldest;
}
for (i = 0, nr = cache->size; i < nr; i++) {
glyph_cache_item_t* item = cache->items + i;
if (item->last_access_time < oldest_time) {
oldest_time = item->last_access_time;
oldest = i;
if (oldest_time == 0) {
break;
}
}
}
item = cache->items + oldest;
GLYPH_CACHE_FREE_ITEM(cache, item);
return item;
}
ret_t glyph_cache_add(glyph_cache_t* cache, wchar_t code, font_size_t size, glyph_t* g) {
glyph_cache_item_t* item = glyph_cache_get_empty(cache);
return_value_if_fail(cache != NULL && g != NULL && item != NULL, RET_BAD_PARAMS);
item->g = g;
item->size = size;
item->code = code;
item->last_access_time = time_now_ms();
return RET_OK;
}
ret_t glyph_cache_lookup(glyph_cache_t* cache, wchar_t code, font_size_t size, glyph_t* g) {
uint32_t i = 0;
uint32_t nr = 0;
return_value_if_fail(cache != NULL && g != NULL, RET_BAD_PARAMS);
for (i = 0, nr = cache->size; i < nr; i++) {
glyph_cache_item_t* item = cache->items + i;
if (item->code == code && item->size == size) {
*g = *(item->g);
item->last_access_time = time_now_ms();
return RET_OK;
}
}
return RET_NOT_FOUND;
}
ret_t glyph_cache_deinit(glyph_cache_t* cache) {
uint32_t i = 0;
uint32_t nr = 0;
return_value_if_fail(cache != NULL, RET_BAD_PARAMS);
if (cache->destroy_glyph != NULL) {
for (i = 0, nr = cache->size; i < nr; i++) {
glyph_cache_item_t* item = cache->items + i;
GLYPH_CACHE_FREE_ITEM(cache, item);
}
}
TKMEM_FREE(cache->items);
memset(cache, 0x00, sizeof(glyph_cache_t));
return RET_OK;
}
static int glyph_cache_item_compare_by_time(const void* a, const void* b) {
glyph_cache_item_t* aa = (glyph_cache_item_t*)a;
glyph_cache_item_t* bb = (glyph_cache_item_t*)b;
return bb->last_access_time - aa->last_access_time;
}
ret_t glyph_cache_shrink(glyph_cache_t* cache, uint32_t cache_size) {
return_value_if_fail(cache != NULL && cache->items != NULL, RET_BAD_PARAMS);
if (cache->size > cache_size) {
uint32_t i = 0;
qsort(cache->items, cache->size, sizeof(glyph_cache_item_t), glyph_cache_item_compare_by_time);
for (i = cache_size; i < cache->size; i++) {
glyph_cache_item_t* item = cache->items + i;
GLYPH_CACHE_FREE_ITEM(cache, item);
}
cache->size = cache_size;
}
return RET_OK;
}

View File

@ -0,0 +1,108 @@
/**
* File: glyph_cache.h
* Author: AWTK Develop Team
* Brief: glyph cache
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-06-10 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_GLYPH_CACHE_H
#define TK_GLYPH_CACHE_H
#include "base/font.h"
BEGIN_C_DECLS
typedef struct _glyph_cache_item_t {
uint64_t last_access_time;
font_size_t size;
wchar_t code;
glyph_t* g;
} glyph_cache_item_t;
/**
* @class glyph_cache_t
* glyph cache
*/
typedef struct _glyph_cache_t {
uint32_t size;
uint32_t capacity;
glyph_cache_item_t* items;
tk_destroy_t destroy_glyph;
} glyph_cache_t;
/**
* @method glyph_cache_init
* 初始化glyph_cache对象。
* @param {glyph_cache_t*} cache cache对象。
* @param {uint32_t} capacity 最大容量。
* @param {tk_destroy_t} destroy_glyph 销毁函数。
*
* @return {glyph_cache_t*} 返回cache对象。
*/
glyph_cache_t* glyph_cache_init(glyph_cache_t* cache, uint32_t capacity,
tk_destroy_t destroy_glyph);
/**
* @method glyph_cache_add
* 增加一个glyph对象到cache。
*
* @param {glyph_cache_t*} cache cache对象。
* @param {wchar_t} code 字符。
* @param {font_size_t} size 字体大小。
* @param {glyph_t} g glyph对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t glyph_cache_add(glyph_cache_t* cache, wchar_t code, font_size_t size, glyph_t* g);
/**
* @method glyph_cache_lookup
* 查找glyph对象。
*
* @param {glyph_cache_t*} cache cache对象。
* @param {wchar_t} code 字符。
* @param {font_size_t} size 字体大小。
* @param {glyph_t} g glyph对象(用于返回glyph)。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t glyph_cache_lookup(glyph_cache_t* cache, wchar_t code, font_size_t size, glyph_t* g);
/**
* @method glyph_cache_shrink
* 释放部分glyph。
*
* @param {glyph_cache_t*} cache cache对象。
* @param {uint32_t} cache_size 保留cache个数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t glyph_cache_shrink(glyph_cache_t* cache, uint32_t cache_size);
/**
* @method glyph_cache_deinit
* 释放全部cache。
*
* @param {glyph_cache_t*} cache cache对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t glyph_cache_deinit(glyph_cache_t* cache);
END_C_DECLS
#endif /*TK_GLYPH_CACHE_H*/

View File

@ -0,0 +1,267 @@

/**
* File: gradient.h
* Author: AWTK Develop Team
* Brief: vector graphic gradient
*
* Copyright (c) 2021 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2021-07-17 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_GRADIENT_H
#define TK_GRADIENT_H
#include "tkc/color.h"
#include "tkc/str.h"
#include "tkc/buffer.h"
BEGIN_C_DECLS
#ifndef TK_GRADIENT_MAX_STOP_NR
#define TK_GRADIENT_MAX_STOP_NR 8
#endif /*TK_GRADIENT_MAX_STOP_NR*/
/**
* @enum gradient_type_t
* 渐变色类型。
*/
typedef enum _gradient_type_t {
/**
* @const GRADIENT_NONE
* 无效类型。
*/
GRADIENT_NONE,
/**
* @const GRADIENT_LINEAR
* 线性渐变。
*/
GRADIENT_LINEAR,
/**
* @const GRADIENT_RADIAL
* 放射渐变。
*/
GRADIENT_RADIAL,
} gradient_type_t;
struct _gradient_stop_t;
typedef struct _gradient_stop_t gradient_stop_t;
/**
* @class gradient_stop_t
* 渐变关键点。
*/
struct _gradient_stop_t {
/**
* @property {color_t} color
* @annotation ["readable"]
* 颜色。
*/
color_t color;
/**
* @property {float} offset
* @annotation ["readable"]
* 偏移量(0-1)。
*/
float offset;
};
struct _gradient_t;
typedef struct _gradient_t gradient_t;
/**
* @class gradient_t
* 渐变。
*/
struct _gradient_t {
/**
* @property {gradient_type_t} type
* @annotation ["readable"]
* 类型。
*/
gradient_type_t type;
/**
* @property {uint32_t} degree
* @annotation ["readable"]
* 线性渐变的角度。
*/
uint32_t degree;
/**
* @property {uint32_t} nr
* @annotation ["readable"]
* stop个数。
*/
uint32_t nr;
/*private*/
gradient_stop_t stops[TK_GRADIENT_MAX_STOP_NR];
};
/**
* @method gradient_init
* 初始化gradient对象。
* @param {gradient_t*} gradient gradient对象。
*
* @return {gradient_t*} 返回gradient对象。
*/
gradient_t* gradient_init(gradient_t* gradient);
/**
* @method gradient_init_simple
* 初始化gradient对象。
* @param {gradient_t*} gradient gradient对象。
* @param {uint32_t} color 颜色。
*
* @return {gradient_t*} 返回gradient对象。
*/
gradient_t* gradient_init_simple(gradient_t* gradient, uint32_t color);
/**
* @method gradient_init_from_str
* 从字符串初始化gradient对象。
*
* > 字符串的格式兼容CSS请参考相关文档。
* @param {gradient_t*} gradient gradient对象。
* @param {const char*} str 字符串。
*
* @return {gradient_t*} 返回gradient对象。
*/
gradient_t* gradient_init_from_str(gradient_t* gradient, const char* str);
/**
* @method gradient_init_from_binary
* 从二进制数据初始化gradient对象。
*
* > 二进制数据必须由gradient_to_binary生成。
* @param {gradient_t*} gradient gradient对象。
* @param {const uint8_t*} data 数据。
* @param {uint32_t} size 数据长度。
*
* @return {gradient_t*} 返回gradient对象。
*/
gradient_t* gradient_init_from_binary(gradient_t* gradient, const uint8_t* data, uint32_t size);
/**
* @method gradient_set_type
* 设置类型。
*
* @param {gradient_t*} gradient gradient对象。
* @param {gradient_type_t} type 类型。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t gradient_set_type(gradient_t* gradient, gradient_type_t type);
/**
* @method gradient_set_linear_degree
* 设置线性渐变的角度。
*
* @param {gradient_t*} gradient gradient对象。
* @param {uint32_t} degree 角度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t gradient_set_linear_degree(gradient_t* gradient, uint32_t degree);
/**
* @method gradient_to_str
* 转换成字符串格式。
*
* @param {gradient_t*} gradient gradient对象。
* @param {str_t*} str 字符串。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t gradient_to_str(gradient_t* gradient, str_t* str);
/**
* @method gradient_to_binary
* 转成二进制格式。
*
* @param {gradient_t*} gradient gradient对象。
* @param {wbuffer_t*} wb 二进制数据。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t gradient_to_binary(gradient_t* gradient, wbuffer_t* wb);
/**
* @method gradient_add_stop
* 增加关键点。
*
* @param {gradient_t*} gradient gradient对象。
* @param {color_t} color 颜色。
* @param {float} stop 位置。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t gradient_add_stop(gradient_t* gradient, color_t color, float stop);
/**
* @method gradient_get_stop
* 获取关键点。
*
* @param {gradient_t*} gradient gradient对象。
* @param {uint32_t} index 序数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
gradient_stop_t* gradient_get_stop(gradient_t* gradient, uint32_t index);
/**
* @method gradient_get_first_color
* 获取开始的颜色。
*
* @param {gradient_t*} gradient gradient对象。
*
* @return {color_t} 返回颜色。
*/
color_t gradient_get_first_color(gradient_t* gradient);
/**
* @method gradient_get_last_color
* 获取结束的颜色。
*
* @param {gradient_t*} gradient gradient对象。
*
* @return {color_t} 返回颜色。
*/
color_t gradient_get_last_color(gradient_t* gradient);
/**
* @method gradient_get_color
* 获取颜色。
*
* @param {gradient_t*} gradient gradient对象。
* @param {float} offset 偏移(0-1)。
*
* @return {color_t} 返回颜色。
*/
color_t gradient_get_color(gradient_t* gradient, float offset);
/**
* @method gradient_deinit
* 释放gradient对象。
*
* @param {gradient_t*} gradient gradient对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t gradient_deinit(gradient_t* gradient);
END_C_DECLS
#endif /*TK_GRADIENT_H*/

View File

@ -0,0 +1,391 @@

/**
* File: gradient.c
* Author: AWTK Develop Team
* Brief: vector graphic gradient
*
* Copyright (c) 2021 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2021-07-17 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/utils.h"
#include "tkc/tokenizer.h"
#include "base/gradient.h"
#include "tkc/color_parser.h"
gradient_t* gradient_init(gradient_t* gradient) {
return_value_if_fail(gradient != NULL, NULL);
memset(gradient, 0x00, sizeof(gradient_t));
return gradient;
}
gradient_t* gradient_init_simple(gradient_t* gradient, uint32_t color) {
color_t c;
return_value_if_fail(gradient != NULL, NULL);
c.color = color;
gradient_init(gradient);
gradient->type = GRADIENT_LINEAR;
gradient_add_stop(gradient, c, 0);
return gradient;
}
static ret_t gradient_fix_stops(gradient_t* gradient) {
uint32_t i = 0;
if (gradient->nr > 1) {
float nr = gradient->nr - 1;
for (i = 0; i < gradient->nr; i++) {
gradient_stop_t* iter = gradient->stops + i;
if (iter->offset < 0) {
iter->offset = (float)i / nr;
}
}
}
return RET_OK;
}
static gradient_t* gradient_parse_stops(gradient_t* gradient, tokenizer_t* t) {
color_t color;
float offset = 0;
const char* token = NULL;
const char* p = t->str + t->cursor;
while (*p == ' ' || *p == '(' || *p == ',') {
p++;
}
while (*p && *p != ')') {
if (tk_str_start_with(p, "rgb")) {
color = color_parse(p);
p = strchr(p, ')');
return_value_if_fail(p != NULL, NULL);
p++;
} else {
t->cursor = p - t->str;
token = tokenizer_next_until(t, " ,)");
color = color_parse(token);
}
/*skip color*/
while (*p && *p != ')' && *p != ' ' && *p != ',') {
p++;
}
if (*p == ' ') {
p++;
offset = tk_atof(p) / 100;
} else {
offset = -1;
}
gradient_add_stop(gradient, color, offset);
/*skip offset*/
while (*p && *p != ')' && *p != ',') {
p++;
}
/*skip seperator*/
while (*p == ' ' || *p == ',') {
p++;
}
}
gradient_fix_stops(gradient);
return gradient;
}
static gradient_t* gradient_parse_linear(gradient_t* gradient, tokenizer_t* t) {
int32_t degree = 0;
const char* token = NULL;
uint32_t cursor = t->cursor;
token = tokenizer_next_until(t, ",)");
return_value_if_fail(token != NULL, NULL);
gradient_set_type(gradient, GRADIENT_LINEAR);
if (isdigit(*token)) {
if (strstr(token, "deg") != NULL) {
/*
* linear-gradient(0deg, blue, green 40%, red);
*/
degree = tk_atoi(token);
} else {
log_debug("not support %s\n", token);
return NULL;
}
} else if (*token == 't') {
/**
*linear-gradient(to left top, blue, red);
*/
if (strstr(token, "left") != NULL) {
if (strstr(token, "top") != NULL) {
degree = 315;
} else if (strstr(token, "bottom") != NULL) {
degree = 225;
} else {
degree = 270;
}
} else if (strstr(token, "right") != NULL) {
if (strstr(token, "top") != NULL) {
degree = 45;
} else if (strstr(token, "bottom") != NULL) {
degree = 135;
} else {
degree = 90;
}
} else if (strstr(token, "top") != NULL) {
degree = 0;
} else if (strstr(token, "bottom") != NULL) {
degree = 180;
}
} else {
/*it is color*/
t->cursor = cursor;
}
gradient_set_linear_degree(gradient, degree);
return gradient_parse_stops(gradient, t);
}
static gradient_t* gradient_parse_radial(gradient_t* gradient, tokenizer_t* t) {
const char* token = NULL;
uint32_t cursor = t->cursor;
token = tokenizer_next_until(t, ",)");
return_value_if_fail(token != NULL, NULL);
gradient_set_type(gradient, GRADIENT_LINEAR);
if (tk_str_start_with(token, "circle")) {
/*
* radial-gradient(circle, #333, #333 50%, #eee 75%, #333 75%);
*/
} else if (tk_str_start_with(token, "ellipse") || tk_str_start_with(token, "closest") ||
tk_str_start_with(token, "farthest")) {
/*
* radial-gradient(ellipse at top, #e66465, transparent),
* radial-gradient(closest-side, #3f87a6, #ebf8e1, #f69d3c);
*/
log_debug("not support type:%s\n", token);
return NULL;
} else {
/*it is color*/
t->cursor = cursor;
}
return gradient_parse_stops(gradient, t);
}
static gradient_t* gradient_parse_str(gradient_t* gradient, const char* str) {
tokenizer_t tokenizer;
const char* token = NULL;
tokenizer_t* t = tokenizer_init(&tokenizer, str, strlen(str), ":");
token = tokenizer_next_until(t, "(");
if (*token == 'l') {
/*
* linear-gradient(0deg, blue, green 40%, red);
*/
t->cursor++;
gradient_parse_linear(gradient, t);
} else if (*token == 'r') {
/*
* radial-gradient(circle, rgba(2,0,36,1) 0%, rgba(63,95,131,1) 58%, rgba(0,212,255,1) 100%);
*/
t->cursor++;
gradient_parse_radial(gradient, t);
}
tokenizer_deinit(t);
return gradient;
}
ret_t gradient_to_str(gradient_t* gradient, str_t* str) {
uint32_t i = 0;
char offset[32];
char color[TK_COLOR_HEX_LEN + 1];
return_value_if_fail(gradient != NULL && str != NULL, RET_BAD_PARAMS);
return_value_if_fail(str_extend(str, str->size + 128) == RET_OK, RET_OOM);
if (gradient->type == GRADIENT_LINEAR) {
str_append(str, "linear-gradient(");
str_append_int(str, gradient->degree);
str_append(str, "deg");
} else if (gradient->type == GRADIENT_RADIAL) {
str_append(str, "radial-gradient(circle");
}
for (i = 0; i < gradient->nr; i++) {
gradient_stop_t* iter = gradient->stops + i;
color_hex_str(iter->color, color);
tk_snprintf(offset, sizeof(offset) - 1, "%d", (int)(iter->offset * 100));
str_append_more(str, ", ", color, " ", offset, "%", NULL);
}
str_append(str, ")");
return RET_OK;
}
gradient_t* gradient_init_from_str(gradient_t* gradient, const char* str) {
return_value_if_fail(str != NULL, NULL);
return_value_if_fail(gradient_init(gradient) != NULL, NULL);
return gradient_parse_str(gradient, str);
}
static gradient_t* gradient_parse_binary(gradient_t* gradient, const uint8_t* data, uint32_t size) {
color_t c;
rbuffer_t rb;
uint32_t i = 0;
uint8_t nr = 0;
float offset = 0;
uint32_t color = 0;
uint8_t type = 0;
uint16_t degree = 0;
uint32_t correct_size = 0;
rbuffer_init(&rb, data, size);
rbuffer_read_uint16(&rb, &degree);
rbuffer_read_uint8(&rb, &type);
rbuffer_read_uint8(&rb, &nr);
correct_size = sizeof(uint32_t) + nr * (sizeof(float) + sizeof(uint32_t));
return_value_if_fail(size >= correct_size, NULL);
return_value_if_fail(nr < TK_GRADIENT_MAX_STOP_NR, NULL);
gradient->nr = 0;
gradient->degree = degree;
gradient->type = (gradient_type_t)type;
for (i = 0; i < nr; i++) {
rbuffer_read_float(&rb, &offset);
rbuffer_read_uint32(&rb, &color);
c.color = color;
gradient_add_stop(gradient, c, offset);
}
return gradient;
}
ret_t gradient_to_binary(gradient_t* gradient, wbuffer_t* wb) {
uint32_t i = 0;
uint32_t size = sizeof(uint32_t) + TK_GRADIENT_MAX_STOP_NR * (sizeof(uint32_t) + sizeof(float));
return_value_if_fail(gradient != NULL && wb != NULL, RET_BAD_PARAMS);
return_value_if_fail(wbuffer_extend_capacity(wb, wb->cursor + size) == RET_OK, RET_OOM);
wbuffer_write_uint16(wb, gradient->degree);
wbuffer_write_uint8(wb, gradient->type);
wbuffer_write_uint8(wb, gradient->nr);
for (i = 0; i < gradient->nr; i++) {
gradient_stop_t* iter = gradient->stops + i;
wbuffer_write_float(wb, iter->offset);
wbuffer_write_uint32(wb, iter->color.color);
}
return RET_OK;
}
gradient_t* gradient_init_from_binary(gradient_t* gradient, const uint8_t* data, uint32_t size) {
uint32_t least_size = sizeof(uint32_t) + sizeof(gradient_stop_t);
return_value_if_fail(data != NULL && size > least_size, NULL);
return_value_if_fail(gradient_init(gradient) != NULL, NULL);
return gradient_parse_binary(gradient, data, size);
}
ret_t gradient_set_type(gradient_t* gradient, gradient_type_t type) {
return_value_if_fail(gradient != NULL, RET_BAD_PARAMS);
gradient->type = type;
return RET_OK;
}
ret_t gradient_set_linear_degree(gradient_t* gradient, uint32_t degree) {
return_value_if_fail(gradient != NULL, RET_BAD_PARAMS);
gradient->degree = degree;
return RET_OK;
}
ret_t gradient_add_stop(gradient_t* gradient, color_t color, float offset) {
return_value_if_fail(gradient != NULL && gradient->nr < TK_GRADIENT_MAX_STOP_NR, RET_BAD_PARAMS);
gradient->stops[gradient->nr].color = color;
gradient->stops[gradient->nr++].offset = offset;
return RET_OK;
}
gradient_stop_t* gradient_get_stop(gradient_t* gradient, uint32_t index) {
return_value_if_fail(gradient != NULL, NULL);
return_value_if_fail(gradient->nr > index, NULL);
return gradient->stops + index;
}
color_t gradient_get_first_color(gradient_t* gradient) {
return_value_if_fail(gradient != NULL && gradient->nr > 0, color_init(0xff, 0xff, 0xff, 0xff));
return gradient->stops[0].color;
}
color_t gradient_get_last_color(gradient_t* gradient) {
return_value_if_fail(gradient != NULL && gradient->nr > 0, color_init(0xff, 0xff, 0xff, 0xff));
return gradient->stops[gradient->nr - 1].color;
}
ret_t gradient_deinit(gradient_t* gradient) {
return_value_if_fail(gradient != NULL, RET_BAD_PARAMS);
memset(gradient, 0x00, sizeof(gradient_t));
return RET_OK;
}
color_t gradient_get_color(gradient_t* gradient, float offset) {
color_t c = color_init(0x00, 0, 0, 0);
return_value_if_fail(gradient != NULL && gradient->nr > 0, c);
return_value_if_fail(offset >= 0 && offset <= 1, c);
if (gradient->nr == 1) {
return gradient_get_first_color(gradient);
} else {
uint32_t i = 0;
for (i = 0; i < gradient->nr; i++) {
gradient_stop_t* iter = gradient->stops + i;
if (iter->offset == offset || (i + 1) == gradient->nr) {
return iter->color;
} else if (offset > iter->offset) {
gradient_stop_t* next = gradient->stops + i + 1;
if (offset == next->offset) {
return next->color;
} else if (offset < next->offset) {
float range = next->offset - iter->offset;
float percent = (offset - iter->offset) / range;
c.rgba.r = (1 - percent) * iter->color.rgba.r + percent * next->color.rgba.r;
c.rgba.g = (1 - percent) * iter->color.rgba.g + percent * next->color.rgba.g;
c.rgba.b = (1 - percent) * iter->color.rgba.b + percent * next->color.rgba.b;
c.rgba.a = (1 - percent) * iter->color.rgba.a + percent * next->color.rgba.a;
return c;
}
}
}
}
return gradient_get_last_color(gradient);
}

View File

@ -0,0 +1,69 @@
/**
* File: graphic_buffer.c
* Author: AWTK Develop Team
* Brief: graphic_buffer
*
* Copyright (c) 2019 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2019-10-30 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "base/bitmap.h"
#include "base/graphic_buffer.h"
bool_t graphic_buffer_is_valid_for(graphic_buffer_t* buffer, bitmap_t* bitmap) {
return_value_if_fail(buffer != NULL && buffer->vt != NULL && bitmap != NULL, FALSE);
if (buffer->vt->is_valid_for != NULL) {
return buffer->vt->is_valid_for(buffer, bitmap);
} else {
return TRUE;
}
}
uint8_t* graphic_buffer_lock_for_read(graphic_buffer_t* buffer) {
return_value_if_fail(buffer != NULL && buffer->vt != NULL && buffer->vt->lock_for_read != NULL,
NULL);
return buffer->vt->lock_for_read(buffer);
}
uint8_t* graphic_buffer_lock_for_write(graphic_buffer_t* buffer) {
return_value_if_fail(buffer != NULL && buffer->vt != NULL && buffer->vt->lock_for_write != NULL,
NULL);
return buffer->vt->lock_for_write(buffer);
}
ret_t graphic_buffer_unlock(graphic_buffer_t* buffer) {
return_value_if_fail(buffer != NULL && buffer->vt != NULL && buffer->vt->unlock != NULL,
RET_BAD_PARAMS);
return buffer->vt->unlock(buffer);
}
ret_t graphic_buffer_attach(graphic_buffer_t* buffer, void* data, uint32_t w, uint32_t h) {
return_value_if_fail(buffer != NULL && buffer->vt != NULL && buffer->vt->attach != NULL,
RET_BAD_PARAMS);
return buffer->vt->attach(buffer, data, w, h);
}
ret_t graphic_buffer_destroy(graphic_buffer_t* buffer) {
return_value_if_fail(buffer != NULL && buffer->vt != NULL && buffer->vt->destroy != NULL,
RET_BAD_PARAMS);
return buffer->vt->destroy(buffer);
}

View File

@ -0,0 +1,167 @@
/**
* File: graphic_buffer.h
* Author: AWTK Develop Team
* Brief: graphic_buffer
*
* Copyright (c) 2019 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2019-10-30 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_GRAPHIC_BUFFER_H
#define TK_GRAPHIC_BUFFER_H
#include "base/types_def.h"
BEGIN_C_DECLS
struct _graphic_buffer_t;
typedef struct _graphic_buffer_t graphic_buffer_t;
typedef uint8_t* (*graphic_buffer_lock_for_read_t)(graphic_buffer_t* buffer);
typedef uint8_t* (*graphic_buffer_lock_for_write_t)(graphic_buffer_t* buffer);
typedef ret_t (*graphic_buffer_unlock_t)(graphic_buffer_t* buffer);
typedef ret_t (*graphic_buffer_attach_t)(graphic_buffer_t* buffer, void* data, uint32_t w,
uint32_t h);
typedef bool_t (*graphic_buffer_is_valid_for_t)(graphic_buffer_t* buffer, bitmap_t* bitmap);
typedef ret_t (*graphic_buffer_destroy_t)(graphic_buffer_t* buffer);
typedef enum _graphic_buffer_options_t {
GRAPHIC_BUFFER_SW_READ_NEVER = 1,
GRAPHIC_BUFFER_SW_READ_RARELY = (1 << 1),
GRAPHIC_BUFFER_SW_READ_OFTEN = (1 << 2),
GRAPHIC_BUFFER_SW_READ_MASK = (1 << 3),
GRAPHIC_BUFFER_SW_WRITE_NEVER = (1 << 4),
GRAPHIC_BUFFER_SW_WRITE_RARELY = (1 << 5),
GRAPHIC_BUFFER_SW_WRITE_OFTEN = (1 << 6),
GRAPHIC_BUFFER_SW_WRITE_MASK = (1 << 7),
GRAPHIC_BUFFER_SOFTWARE_MASK = (1 << 8),
GRAPHIC_BUFFER_PROTECTED = (1 << 9),
GRAPHIC_BUFFER_HW_TEXTURE = (1 << 10),
GRAPHIC_BUFFER_HW_RENDER = (1 << 11),
GRAPHIC_BUFFER_HW_2D = (1 << 12),
GRAPHIC_BUFFER_HW_COMPOSER = (1 << 13),
GRAPHIC_BUFFER_HW_VIDEO_ENCODER = (1 << 14),
GRAPHIC_BUFFER_HW_MASK = (1 << 15)
} graphic_buffer_options_t;
typedef struct _graphic_buffer_vtable_t {
graphic_buffer_lock_for_read_t lock_for_read;
graphic_buffer_lock_for_write_t lock_for_write;
graphic_buffer_unlock_t unlock;
graphic_buffer_attach_t attach;
graphic_buffer_is_valid_for_t is_valid_for;
graphic_buffer_destroy_t destroy;
} graphic_buffer_vtable_t;
/**
* @class graphic_buffer_t
* graphic_buffer。
*/
struct _graphic_buffer_t {
const graphic_buffer_vtable_t* vt;
};
/**
* @method graphic_buffer_create_for_bitmap
* 为位图创建缓冲区。
* @param {bitmap_t*} bitmap 位图对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t graphic_buffer_create_for_bitmap(bitmap_t* bitmap);
/**
* @method graphic_buffer_create_with_data
* 创建缓冲区。
*
* > 为了兼容raw图像。
* @param {const uint8_t*} data 数据。
* @param {uint32_t} w 宽度。
* @param {uint32_t} h 宽度。
* @param {bitmap_format_t} format 格式。
*
* @return {graphic_buffer_t*} 返回缓存区。
*/
graphic_buffer_t* graphic_buffer_create_with_data(const uint8_t* data, uint32_t w, uint32_t h,
bitmap_format_t format);
/**
* @method graphic_buffer_lock_for_read
* 为读取数据而锁定缓冲区。
* @param {graphic_buffer_t*} buffer 图像缓冲区对象。
*
* @return {uint8_t*} 返回缓存区的首地址。
*/
uint8_t* graphic_buffer_lock_for_read(graphic_buffer_t* buffer);
/**
* @method graphic_buffer_lock_for_write
* 为修改数据而锁定缓冲区。
* @param {graphic_buffer_t*} buffer 图像缓冲区对象。
*
* @return {uint8_t*} 返回缓存区的首地址。
*/
uint8_t* graphic_buffer_lock_for_write(graphic_buffer_t* buffer);
/**
* @method graphic_buffer_unlock
* 解锁缓冲区。
* @param {graphic_buffer_t*} buffer 图像缓冲区对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t graphic_buffer_unlock(graphic_buffer_t* buffer);
/**
* @method graphic_buffer_attach
* 附件到指定的内存。
* @param {graphic_buffer_t*} buffer 图像缓冲区对象。
* @param {void*} data 内存数据。
* @param {uint32_t} w 宽度。
* @param {uint32_t} h 宽度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t graphic_buffer_attach(graphic_buffer_t* buffer, void* data, uint32_t w, uint32_t h);
/**
* @method graphic_buffer_is_valid_for
* 用于检查graphic buffer的有效性。
*
* @param {graphic_buffer_t*} buffer 图像缓冲区对象。
* @param {bitmap_t*} bitmap 位图对象。
*
* @return {bool_t} 返回TRUE表示有效否则表示无效。
*/
bool_t graphic_buffer_is_valid_for(graphic_buffer_t* buffer, bitmap_t* bitmap);
/**
* @method graphic_buffer_destroy
* 销毁缓冲区。
* @param {graphic_buffer_t*} buffer 图像缓冲区对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t graphic_buffer_destroy(graphic_buffer_t* buffer);
#define GRAPHIC_BUFFER(buffer) ((graphic_buffer_t*)(buffer))
#define GRAPHIC_BUFFER_CREATE_FOR_BITMAP(bitmap) graphic_buffer_create_for_bitmap(bitmap)
#define GRAPHIC_BUFFER_CREATE_WITH_DATA(data, w, h, format) \
graphic_buffer_create_with_data(data, w, h, format)
END_C_DECLS
#endif /*TK_GRAPHIC_BUFFER_H*/

View File

@ -0,0 +1,344 @@
/**
* File: hscrollable.c
* Author: AWTK Develop Team
* Brief: hscrollable
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2019-05-30 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utf8.h"
#include "tkc/utils.h"
#include "base/hscrollable.h"
#include "base/widget_vtable.h"
#ifndef WITHOUT_WIDGET_ANIMATORS
#include "widget_animators/widget_animator_scroll.h"
#endif /*WITHOUT_WIDGET_ANIMATORS*/
static widget_t* hscrollable_get_widget(hscrollable_t* hscrollable) {
return hscrollable != NULL ? hscrollable->widget : NULL;
}
static ret_t hscrollable_on_pointer_down(hscrollable_t* hscrollable, pointer_event_t* e) {
velocity_t* v = &(hscrollable->velocity);
velocity_reset(v);
hscrollable->down.x = e->x;
hscrollable->down.y = e->y;
hscrollable->xoffset_save = hscrollable->xoffset;
velocity_update(v, e->e.time, e->x, e->y);
return RET_OK;
}
static ret_t hscrollable_on_pointer_move(hscrollable_t* hscrollable, pointer_event_t* e) {
velocity_t* v = &(hscrollable->velocity);
int32_t dx = e->x - hscrollable->down.x;
velocity_update(v, e->e.time, e->x, e->y);
hscrollable->xoffset = hscrollable->xoffset_save - dx;
if (!(hscrollable->always_scrollable)) {
widget_t* widget = hscrollable_get_widget(hscrollable);
if ((hscrollable->xoffset + widget->w) > hscrollable->virtual_w) {
hscrollable->xoffset = hscrollable->virtual_w - widget->w;
}
if (hscrollable->xoffset < 0) {
hscrollable->xoffset = 0;
}
}
return RET_OK;
}
#ifndef WITHOUT_WIDGET_ANIMATORS
static ret_t hscrollable_on_scroll_done(void* ctx, event_t* e) {
hscrollable_t* hscrollable = (hscrollable_t*)(ctx);
return_value_if_fail(hscrollable != NULL, RET_BAD_PARAMS);
hscrollable->wa = NULL;
widget_invalidate_force(hscrollable_get_widget(hscrollable), NULL);
return RET_REMOVE;
}
#endif /*WITHOUT_WIDGET_ANIMATORS*/
static ret_t hscrollable_fix_end_offset_default(hscrollable_t* hscrollable) {
int32_t xoffset_end = 0;
widget_t* widget = hscrollable_get_widget(hscrollable);
return_value_if_fail(hscrollable != NULL && widget != NULL, RET_BAD_PARAMS);
xoffset_end = hscrollable->xoffset_end;
xoffset_end = tk_max(xoffset_end, 0);
xoffset_end = tk_min(xoffset_end, (hscrollable->virtual_w - widget->w));
if (hscrollable->virtual_w <= widget->w) {
xoffset_end = 0;
}
hscrollable->xoffset_end = xoffset_end;
return RET_OK;
}
ret_t hscrollable_scroll_to(hscrollable_t* hscrollable, int32_t xoffset_end, int32_t duration) {
int32_t xoffset = 0;
widget_t* widget = hscrollable_get_widget(hscrollable);
return_value_if_fail(hscrollable != NULL && widget != NULL, RET_FAIL);
hscrollable_fix_end_offset_default(hscrollable);
xoffset_end = hscrollable->xoffset_end;
xoffset = hscrollable->xoffset;
if (xoffset == xoffset_end) {
return RET_OK;
}
#ifndef WITHOUT_WIDGET_ANIMATORS
if (hscrollable->enable_hscroll_animator) {
hscrollable->xoffset_end = xoffset_end;
xoffset_end = hscrollable->xoffset_end;
hscrollable->wa = widget_animator_scroll_create(widget, TK_ANIMATING_TIME, 0, EASING_SIN_INOUT);
return_value_if_fail(hscrollable->wa != NULL, RET_OOM);
widget_animator_scroll_set_params(hscrollable->wa, xoffset, 0, xoffset_end, 0);
widget_animator_on(hscrollable->wa, EVT_ANIM_END, hscrollable_on_scroll_done, hscrollable);
widget_animator_start(hscrollable->wa);
return RET_OK;
}
#endif /*WITHOUT_WIDGET_ANIMATORS*/
hscrollable->xoffset = xoffset_end;
return RET_OK;
}
#define SPEED_SCALE 2
#define MIN_DELTA 10
static ret_t hscrollable_on_pointer_up(hscrollable_t* hscrollable, pointer_event_t* e) {
velocity_t* v = &(hscrollable->velocity);
int32_t move_dx = e->x - hscrollable->down.x;
velocity_update(v, e->e.time, e->x, e->y);
if (move_dx) {
int xv = tk_min(v->xv, 100);
hscrollable->xoffset_end = hscrollable->xoffset - xv;
hscrollable_scroll_to(hscrollable, hscrollable->xoffset_end, 300);
}
return RET_OK;
}
ret_t hscrollable_on_event(hscrollable_t* hscrollable, event_t* e) {
ret_t ret = RET_OK;
uint16_t type = e->type;
widget_t* widget = hscrollable_get_widget(hscrollable);
return_value_if_fail(hscrollable != NULL && widget != NULL && e != NULL, RET_BAD_PARAMS);
if (hscrollable->wa != NULL) {
log_debug("animating ignore event\n");
return RET_STOP;
}
switch (type) {
case EVT_POINTER_DOWN:
hscrollable->dragged = FALSE;
widget_grab(widget->parent, widget);
hscrollable_on_pointer_down(hscrollable, (pointer_event_t*)e);
break;
case EVT_POINTER_UP: {
pointer_event_t* evt = (pointer_event_t*)e;
int32_t dx = evt->x - hscrollable->down.x;
if (dx) {
hscrollable_on_pointer_up(hscrollable, (pointer_event_t*)e);
}
hscrollable->dragged = FALSE;
widget_ungrab(widget->parent, widget);
break;
}
case EVT_POINTER_MOVE: {
pointer_event_t* evt = (pointer_event_t*)e;
if (!evt->pressed) {
break;
}
if (hscrollable->dragged) {
hscrollable_on_pointer_move(hscrollable, evt);
widget_invalidate_force(hscrollable_get_widget(hscrollable), NULL);
} else {
int32_t delta = evt->x - hscrollable->down.x;
if (tk_abs(delta) >= TK_DRAG_THRESHOLD) {
pointer_event_t abort = *evt;
abort.e.type = EVT_POINTER_DOWN_ABORT;
widget_dispatch_event_to_target_recursive(widget, (event_t*)(&abort));
hscrollable->dragged = TRUE;
}
}
ret = hscrollable->dragged ? RET_STOP : RET_OK;
break;
}
default:
break;
}
return ret;
}
ret_t hscrollable_on_paint_children(hscrollable_t* hscrollable, canvas_t* c) {
rect_t r_save;
widget_t* widget = hscrollable_get_widget(hscrollable);
vgcanvas_t* vg = canvas_get_vgcanvas(c);
return_value_if_fail(hscrollable != NULL && c != NULL && widget != NULL, RET_BAD_PARAMS);
rect_t r = rect_init(c->ox, c->oy, widget->w, widget->h);
int32_t xoffset = -hscrollable->xoffset;
canvas_translate(c, xoffset, 0);
canvas_get_clip_rect(c, &r_save);
r = rect_intersect(&r, &r_save);
if (vg != NULL) {
vgcanvas_save(vg);
vgcanvas_clip_rect(vg, (float_t)r.x, (float_t)r.y, (float_t)r.w, (float_t)r.h);
}
canvas_set_clip_rect(c, &r);
widget_on_paint_children_default(widget, c);
canvas_set_clip_rect(c, &r_save);
canvas_untranslate(c, xoffset, 0);
if (vg != NULL) {
vgcanvas_clip_rect(vg, (float_t)r_save.x, (float_t)r_save.y, (float_t)r_save.w,
(float_t)r_save.h);
vgcanvas_restore(vg);
}
return RET_OK;
}
ret_t hscrollable_get_prop(hscrollable_t* hscrollable, const char* name, value_t* v) {
widget_t* widget = hscrollable_get_widget(hscrollable);
return_value_if_fail(widget != NULL && hscrollable != NULL && name != NULL && v != NULL,
RET_BAD_PARAMS);
if (tk_str_eq(name, WIDGET_PROP_VIRTUAL_W)) {
value_set_int(v, tk_max(widget->w, hscrollable->virtual_w));
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_VIRTUAL_H) || tk_str_eq(name, WIDGET_PROP_LAYOUT_H)) {
value_set_int(v, widget->h);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_XOFFSET)) {
value_set_int(v, hscrollable->xoffset);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_YOFFSET)) {
value_set_int(v, 0);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_XSLIDABLE)) {
value_set_bool(v, TRUE);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_YSLIDABLE)) {
value_set_bool(v, FALSE);
return RET_OK;
}
return RET_NOT_FOUND;
}
ret_t hscrollable_set_prop(hscrollable_t* hscrollable, const char* name, const value_t* v) {
return_value_if_fail(hscrollable != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);
if (tk_str_eq(name, WIDGET_PROP_VIRTUAL_W)) {
hscrollable->virtual_w = value_int(v);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_XSLIDABLE)) {
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_XOFFSET)) {
if (hscrollable->wa != NULL) {
hscrollable->xoffset = value_int(v);
widget_invalidate_force(hscrollable_get_widget(hscrollable), NULL);
} else {
hscrollable->xoffset_end = value_int(v);
hscrollable_scroll_to(hscrollable, hscrollable->xoffset_end, 300);
}
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_YOFFSET)) {
return RET_OK;
} else if (tk_str_eq(name, HSCROLLABLE_PROP_ENABLE_HSCROLL_ANIMATOR)) {
return hscrollable_set_enable_hscroll_animator(hscrollable, value_bool(v));
}
return RET_NOT_FOUND;
}
hscrollable_t* hscrollable_create(widget_t* widget) {
hscrollable_t* hscrollable = NULL;
return_value_if_fail(widget != NULL, NULL);
hscrollable = TKMEM_ZALLOC(hscrollable_t);
return_value_if_fail(hscrollable != NULL, NULL);
hscrollable->widget = widget;
hscrollable->enable_hscroll_animator = TRUE;
return hscrollable;
}
ret_t hscrollable_set_always_scrollable(hscrollable_t* hscrollable, bool_t always_scrollable) {
return_value_if_fail(hscrollable != NULL, RET_BAD_PARAMS);
hscrollable->always_scrollable = always_scrollable;
return RET_OK;
}
ret_t hscrollable_set_xoffset(hscrollable_t* hscrollable, int32_t xoffset) {
return_value_if_fail(hscrollable != NULL, RET_BAD_PARAMS);
hscrollable->xoffset = xoffset;
return RET_OK;
}
ret_t hscrollable_set_virtual_w(hscrollable_t* hscrollable, int32_t virtual_w) {
return_value_if_fail(hscrollable != NULL, RET_BAD_PARAMS);
hscrollable->virtual_w = virtual_w;
return RET_OK;
}
ret_t hscrollable_set_enable_hscroll_animator(hscrollable_t* hscrollable,
bool_t enable_hscroll_animator) {
return_value_if_fail(hscrollable != NULL, RET_BAD_PARAMS);
hscrollable->enable_hscroll_animator = enable_hscroll_animator;
return RET_OK;
}
ret_t hscrollable_destroy(hscrollable_t* hscrollable) {
return_value_if_fail(hscrollable != NULL, RET_BAD_PARAMS);
TKMEM_FREE(hscrollable);
return RET_OK;
}

View File

@ -0,0 +1,69 @@
/**
* File: hscrollable.h
* Author: AWTK Develop Team
* Brief: input method text hscrollable
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2019-05-30 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_HSCROLLABLE_H
#define TK_HSCROLLABLE_H
#include "tkc/str.h"
#include "base/widget.h"
#include "base/velocity.h"
#include "base/widget_animator.h"
BEGIN_C_DECLS
/**
* @class hscrollable_t
* 帮助实现控件左右滚动的效果。
*/
typedef struct _hscrollable_t {
point_t down;
bool_t dragged;
int32_t xoffset;
int32_t xoffset_end;
int32_t xoffset_save;
int32_t virtual_w;
widget_t* widget;
velocity_t velocity;
widget_animator_t* wa;
bool_t always_scrollable;
bool_t enable_hscroll_animator;
} hscrollable_t;
hscrollable_t* hscrollable_create(widget_t* widget);
ret_t hscrollable_set_xoffset(hscrollable_t* hscrollable, int32_t xoffset);
ret_t hscrollable_set_virtual_w(hscrollable_t* hscrollable, int32_t virtual_w);
ret_t hscrollable_set_always_scrollable(hscrollable_t* hscrollable, bool_t always_scrollable);
ret_t hscrollable_set_enable_hscroll_animator(hscrollable_t* hscrollable,
bool_t enable_hscroll_animator);
ret_t hscrollable_on_event(hscrollable_t* hscrollable, event_t* e);
ret_t hscrollable_get_prop(hscrollable_t* hscrollable, const char* name, value_t* v);
ret_t hscrollable_set_prop(hscrollable_t* hscrollable, const char* name, const value_t* v);
ret_t hscrollable_on_paint_children(hscrollable_t* hscrollable, canvas_t* c);
ret_t hscrollable_destroy(hscrollable_t* hscrollable);
#define HSCROLLABLE_PROP_ENABLE_HSCROLL_ANIMATOR "enable_hscroll_animator"
END_C_DECLS
#endif /*TK_HSCROLLABLE_H*/

View File

@ -0,0 +1,93 @@
/**
* File: idle.c
* Author: AWTK Develop Team
* Brief: idle manager
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-04-19 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "base/idle.h"
#include "tkc/idle_manager.h"
uint32_t idle_add(idle_func_t on_idle, void* ctx) {
return idle_manager_add(idle_manager(), on_idle, ctx);
}
uint32_t idle_add_with_type(idle_func_t on_idle, void* ctx, uint32_t type) {
return idle_manager_add_with_type(idle_manager(), on_idle, ctx, type);
}
bool_t idle_exist(idle_func_t on_idle, void* ctx) {
return idle_manager_exist(idle_manager(), on_idle, ctx);
}
ret_t idle_remove(uint32_t idle_id) {
return idle_manager_remove(idle_manager(), idle_id);
}
ret_t idle_remove_all_by_ctx_and_type(uint32_t type, void* ctx) {
return idle_manager_remove_all_by_ctx_and_type(idle_manager(), type, ctx);
}
ret_t idle_remove_all_by_ctx(void* ctx) {
return idle_manager_remove_all_by_ctx(idle_manager(), ctx);
}
const idle_info_t* idle_find(uint32_t idle_id) {
return idle_manager_find(idle_manager(), idle_id);
}
ret_t idle_dispatch(void) {
return idle_manager_dispatch(idle_manager());
}
uint32_t idle_count(void) {
return idle_manager_count(idle_manager());
}
#include "base/main_loop.h"
ret_t idle_queue_ex(idle_func_t on_idle, void* ctx, tk_destroy_t on_destroy, void* on_destroy_ctx) {
#ifdef AWTK_WEB
idle_add(on_idle, ctx);
return RET_OK;
#else
event_queue_req_t r;
r.add_idle.func = on_idle;
r.add_idle.e.target = ctx;
r.add_idle.e.type = REQ_ADD_IDLE;
r.add_idle.on_destroy = on_destroy;
r.add_idle.on_destroy_ctx = on_destroy_ctx;
return main_loop_queue_event(main_loop(), &r);
#endif /*AWTK_WEB*/
}
ret_t idle_queue(idle_func_t on_idle, void* ctx) {
return idle_queue_ex(on_idle, ctx, NULL, NULL);
}
ret_t idle_set_on_destroy(uint32_t idle_id, tk_destroy_t on_destroy, void* on_destroy_ctx) {
idle_info_t* item = (idle_info_t*)idle_find(idle_id);
return_value_if_fail(item != NULL, RET_BAD_PARAMS);
item->on_destroy = on_destroy;
item->on_destroy_ctx = on_destroy_ctx;
return RET_OK;
}

View File

@ -0,0 +1,155 @@
/**
* File: idle.h
* Author: AWTK Develop Team
* Brief: idle manager
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-04-19 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_IDLE_H
#define TK_IDLE_H
#include "tkc/idle_manager.h"
BEGIN_C_DECLS
/**
* @class idle_t
* @annotation ["scriptable", "fake"]
*
* idle可以看作是duration为0的定时器。
*
* > idle可以用来实现一些异步处理。
*
* 示例:
*
* ```c
* static ret_t something_on_idle(const idle_info_t* info) {
* widget_t* widget = WIDGET(info->ctx);
* edit_t* edit = EDIT(widget);
* ...
* return RET_REMOVE;
* }
*
* ...
*
* idle_add(something_on_idle, edit);
*
* ```
*
* > 在非GUI线程请用idle\_queue。
*
*/
/**
* @method idle_add
* 增加一个idle。
* @annotation ["scriptable:custom", "static"]
* @param {idle_func_t} on_idle idle回调函数回调函数返回RET_REPEAT则下次继续执行否则自动移出。
* @param {void*} ctx idle回调函数的上下文。
*
* @return {uint32_t} 返回idle的ID0表示失败。
*/
uint32_t idle_add(idle_func_t on_idle, void* ctx);
/**
* @method idle_queue
* 用于非GUI线程增加一个idle本函数向主循环的事件队列中发送一个增加idle的请求。
* @annotation ["static"]
* @param {idle_func_t} on_idle idle回调函数。
* @param {void*} ctx idle回调函数的上下文。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t idle_queue(idle_func_t on_idle, void* ctx);
/**
* @method idle_queue_ex
* 用于非GUI线程增加一个idle本函数向主循环的事件队列中发送一个增加idle的请求。
* @annotation ["static"]
* @param {idle_func_t} on_idle idle回调函数。
* @param {void*} ctx idle回调函数的上下文。
* @param {tk_destroy_t} on_destroy 回调函数。
* @param {void*} on_destroy_ctx 回调函数上下文。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t idle_queue_ex(idle_func_t on_idle, void* ctx, tk_destroy_t on_destroy, void* on_destroy_ctx);
/**
* @method idle_remove
* 删除指定的idle。
* @annotation ["scriptable", "static"]
* @param {uint32_t} idle_id idleID。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t idle_remove(uint32_t idle_id);
/**
* @method idle_remove_all_by_ctx
* 根据上下文删除所有对应的idle。
* @annotation ["scriptable", "static"]
* @param {void*} ctx idle回调函数的上下文
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t idle_remove_all_by_ctx(void* ctx);
/**
* @method idle_find
* 查找指定ID的idle。
*
* @return {idle_info_t*} 返回idle的信息。
*/
const idle_info_t* idle_find(uint32_t idle_id);
/**
* @method idle_set_on_destroy
* 设置一个回调函数在idle被销毁时调用(方便脚本语言去释放回调函数)。
* @param {uint32_t} idle_id idleID。
* @param {tk_destroy_t} on_destroy 回调函数。
* @param {void*} on_destroy_ctx 回调函数上下文。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t idle_set_on_destroy(uint32_t idle_id, tk_destroy_t on_destroy, void* on_destroy_ctx);
/**
* @method idle_dispatch
* 调用全部idle的函数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t idle_dispatch(void);
/**
* @method idle_count
* 返回idle的个数。
* @annotation ["static"]
*
* @return {uint32_t} 返回idle的个数。
*/
uint32_t idle_count(void);
/*internal use*/
bool_t idle_exist(idle_func_t on_idle, void* ctx);
ret_t idle_remove_all_by_ctx_and_type(uint32_t type, void* ctx);
uint32_t idle_add_with_type(idle_func_t on_idle, void* ctx, uint32_t type);
END_C_DECLS
#endif /*TK_IDLE_H*/

View File

@ -0,0 +1,296 @@
/**
* File: image_base.h
* Author: AWTK Develop Team
* Brief: image base
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-11-22 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/image_base.h"
ret_t image_base_on_event(widget_t* widget, event_t* e) {
uint16_t type = e->type;
image_base_t* image = IMAGE_BASE(widget);
return_value_if_fail(image != NULL, RET_BAD_PARAMS);
switch (type) {
case EVT_POINTER_DOWN:
image->pressed = TRUE;
widget_grab(widget->parent, widget);
if (image->clickable) {
widget_set_state(widget, WIDGET_STATE_PRESSED);
widget_invalidate(widget, NULL);
}
break;
case EVT_POINTER_UP: {
if (image->pressed) {
if (image->clickable || image->selectable) {
pointer_event_t evt;
widget_dispatch(widget, pointer_event_init(&evt, EVT_CLICK, widget, 0, 0));
}
if (!image->selectable) {
widget_set_state(widget, WIDGET_STATE_NORMAL);
}
widget_ungrab(widget->parent, widget);
}
break;
}
case EVT_CLICK: {
if (image->selectable) {
image->selected = !image->selected;
widget_set_state(widget, image->selected ? WIDGET_STATE_SELECTED : WIDGET_STATE_NORMAL);
}
widget_invalidate(widget, NULL);
break;
}
case EVT_POINTER_DOWN_ABORT: {
image->pressed = FALSE;
widget_ungrab(widget->parent, widget);
if (image->selectable) {
widget_set_state(widget, image->selected ? WIDGET_STATE_SELECTED : WIDGET_STATE_NORMAL);
} else {
widget_set_state(widget, WIDGET_STATE_NORMAL);
}
break;
}
default:
break;
}
return RET_OK;
}
ret_t image_base_get_prop(widget_t* widget, const char* name, value_t* v) {
image_base_t* image = IMAGE_BASE(widget);
return_value_if_fail(image != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);
if (tk_str_eq(name, WIDGET_PROP_IMAGE)) {
value_set_str(v, image->image);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_SCALE_X)) {
value_set_float(v, image->scale_x);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_SCALE_Y)) {
value_set_float(v, image->scale_y);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_ANCHOR_X)) {
value_set_float(v, image->anchor_x);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_ANCHOR_Y)) {
value_set_float(v, image->anchor_y);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_ROTATION)) {
value_set_float(v, image->rotation);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_SELECTABLE)) {
value_set_bool(v, image->selectable);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_SELECTED)) {
value_set_bool(v, image->selected);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_CLICKABLE)) {
value_set_bool(v, image->clickable);
return RET_OK;
}
return RET_NOT_FOUND;
}
ret_t image_base_set_prop(widget_t* widget, const char* name, const value_t* v) {
image_base_t* image = IMAGE_BASE(widget);
return_value_if_fail(image != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);
if (tk_str_eq(name, WIDGET_PROP_IMAGE)) {
return image_base_set_image(widget, value_str(v));
} else if (tk_str_eq(name, WIDGET_PROP_SCALE_X)) {
image->scale_x = value_float(v);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_SCALE_Y)) {
image->scale_y = value_float(v);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_ANCHOR_X)) {
image->anchor_x = value_float(v);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_ANCHOR_Y)) {
image->anchor_y = value_float(v);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_ROTATION)) {
image->rotation = value_float(v);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_SELECTABLE)) {
image->selectable = value_bool(v);
return RET_OK;
} else if (tk_str_eq(name, WIDGET_PROP_SELECTED)) {
return image_base_set_selected(widget, value_bool(v));
} else if (tk_str_eq(name, WIDGET_PROP_CLICKABLE)) {
image->clickable = value_bool(v);
return RET_OK;
}
return RET_NOT_FOUND;
}
ret_t image_base_on_destroy(widget_t* widget) {
image_base_t* image = IMAGE_BASE(widget);
return_value_if_fail(image != NULL, RET_BAD_PARAMS);
TKMEM_FREE(image->image);
return RET_OK;
}
widget_t* image_base_init(widget_t* widget) {
image_base_t* image = IMAGE_BASE(widget);
return_value_if_fail(image != NULL, NULL);
image->scale_x = 1;
image->scale_y = 1;
image->rotation = 0;
image->anchor_x = 0.5;
image->anchor_y = 0.5;
return widget;
}
ret_t image_base_set_image(widget_t* widget, const char* name) {
image_base_t* image = IMAGE_BASE(widget);
return_value_if_fail(widget != NULL && name != NULL, RET_BAD_PARAMS);
image->image = tk_str_copy(image->image, name);
return widget_invalidate(widget, NULL);
}
ret_t image_base_set_rotation(widget_t* widget, float_t rotation) {
image_base_t* image = IMAGE_BASE(widget);
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
image->rotation = rotation;
return widget_invalidate(widget, NULL);
}
ret_t image_base_set_scale(widget_t* widget, float_t scale_x, float_t scale_y) {
image_base_t* image = IMAGE_BASE(widget);
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
image->scale_x = scale_x;
image->scale_y = scale_y;
return widget_invalidate(widget, NULL);
}
ret_t image_base_set_anchor(widget_t* widget, float_t anchor_x, float_t anchor_y) {
image_base_t* image = IMAGE_BASE(widget);
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
image->anchor_x = anchor_x;
image->anchor_y = anchor_y;
return widget_invalidate(widget, NULL);
}
ret_t image_base_set_selected(widget_t* widget, bool_t selected) {
image_base_t* image = IMAGE_BASE(widget);
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
image->selected = selected;
if (image->selected) {
widget_set_state(widget, WIDGET_STATE_SELECTED);
} else {
widget_set_state(widget, WIDGET_STATE_NORMAL);
}
return widget_invalidate(widget, NULL);
}
ret_t image_base_set_selectable(widget_t* widget, bool_t selectable) {
image_base_t* image = IMAGE_BASE(widget);
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
image->selectable = selectable;
return widget_invalidate(widget, NULL);
}
ret_t image_base_set_clickable(widget_t* widget, bool_t clickable) {
image_base_t* image = IMAGE_BASE(widget);
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
image->clickable = clickable;
return widget_invalidate(widget, NULL);
}
TK_DECL_VTABLE(image_base) = {.size = sizeof(image_base_t), .parent = TK_PARENT_VTABLE(widget)};
widget_t* image_base_cast(widget_t* widget) {
return_value_if_fail(WIDGET_IS_INSTANCE_OF(widget, image_base), NULL);
return widget;
}
bool_t image_need_transform(widget_t* widget) {
image_base_t* image_base = IMAGE_BASE(widget);
return_value_if_fail(widget != NULL, FALSE);
return !tk_fequal(image_base->scale_x, 1) || !tk_fequal(image_base->scale_y, 1) ||
!tk_fequal(image_base->rotation, 0);
}
ret_t image_transform(widget_t* widget, canvas_t* c) {
float_t anchor_x = 0;
float_t anchor_y = 0;
image_base_t* image_base = IMAGE_BASE(widget);
vgcanvas_t* vg = canvas_get_vgcanvas(c);
return_value_if_fail(widget != NULL && vg != NULL, RET_BAD_PARAMS);
anchor_x = image_base->anchor_x * widget->w;
anchor_y = image_base->anchor_y * widget->h;
vgcanvas_translate(vg, c->ox, c->oy);
vgcanvas_translate(vg, anchor_x, anchor_y);
vgcanvas_rotate(vg, image_base->rotation);
vgcanvas_scale(vg, image_base->scale_x, image_base->scale_y);
vgcanvas_translate(vg, -anchor_x, -anchor_y);
return RET_OK;
}
ret_t image_base_on_copy(widget_t* widget, widget_t* other) {
image_base_t* image = IMAGE_BASE(widget);
image_base_t* image_other = IMAGE_BASE(other);
return_value_if_fail(image != NULL && image_other != NULL, RET_BAD_PARAMS);
image->anchor_x = image_other->anchor_x;
image->anchor_y = image_other->anchor_y;
image->scale_x = image_other->scale_x;
image->scale_y = image_other->scale_y;
image->rotation = image_other->rotation;
image->clickable = image_other->clickable;
image->selectable = image_other->selectable;
image->selected = image_other->selected;
image->image = tk_str_copy(image->image, image_other->image);
return RET_OK;
}

View File

@ -0,0 +1,238 @@
/**
* File: image_base.h
* Author: AWTK Develop Team
* Brief: image base
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-11-22 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_IMAGE_BASE_H
#define TK_IMAGE_BASE_H
#include "base/widget.h"
BEGIN_C_DECLS
/**
* @class image_base_t
* @parent widget_t
* @annotation ["scriptable","widget"]
* 图片控件基类。
*
* 本类把图片相关控件的公共行为进行抽象,放到一起方便重用。目前已知的具体实现如下图:
*
* ```graphviz
* [default_style]
*
* image_t -> image_base_t[arrowhead = "empty"]
* svg_image_t -> image_base_t[arrowhead = "empty"]
* gif_image_t -> image_base_t[arrowhead = "empty"]
* ```
*
* > 本类是一个抽象类不能进行实例化。请在应用程序中使用具体的类如image\_t。
*
* 如果需要显示文件系统中的图片,只需将图片名称换成实际的文件名,并加上"file://"前缀即可。如:
*
*```
* <image draw_type="center" image="file://./design/default/images/xx/flag_CN.png" />
* <gif image="file://./design/default/images/x2/bee.gif" />
* <svg image="file://./design/default/images/svg/china.bsvg" />
* ```
*/
typedef struct _image_base_t {
widget_t widget;
/**
* @property {char*} image
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 图片的名称。
*/
char* image;
/**
* @property {float_t} anchor_x
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 锚点X(0-1)。0在控件左边0.5在控件中间1在控件右边。
*/
float_t anchor_x;
/**
* @property {float_t} anchor_y
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 锚点Y(0-1)。0在控件顶部0.5在控件中间1在控件底部。
*/
float_t anchor_y;
/**
* @property {float_t} scale_x
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 控件在X方向上的缩放比例。
*/
float_t scale_x;
/**
* @property {float_t} scale_y
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 控件在Y方向上的缩放比例。
*/
float_t scale_y;
/**
* @property {float_t} rotation
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 控件的旋转角度(幅度)。
*/
float_t rotation;
/**
* @property {bool_t} clickable
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 点击时是否触发EVT_CLICK事件。
*/
bool_t clickable;
/**
* @property {bool_t} selectable
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* 是否设置选中状态。
*/
bool_t selectable;
/**
* @property {bool_t} selected
* @annotation ["readable","scriptable"]
* 当前是否被选中。
*/
bool_t selected;
/*private*/
bool_t pressed;
} image_base_t;
/**
* @event {pointer_event_t} EVT_CLICK
* 点击事件。
*/
/**
* @method image_base_set_image
* 设置控件的图片名称。
*
*> 如果需要显示文件系统中的图片,只需将图片名称换成实际的文件名,并加上"file://"前缀即可。
*
* @annotation ["scriptable"]
* @param {widget_t*} widget image对象。
* @param {char*} name 图片名称,该图片必须存在于资源管理器。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_base_set_image(widget_t* widget, const char* name);
#define image_set_image image_base_set_image
/**
* @method image_base_set_rotation
* 设置控件的旋转角度(仅在WITH_VGCANVAS定义时生效)。
* @annotation ["scriptable"]
* @param {widget_t*} widget 控件对象。
* @param {float_t} rotation 旋转角度(幅度)。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_base_set_rotation(widget_t* widget, float_t rotation);
#define image_set_rotation image_base_set_rotation
/**
* @method image_base_set_scale
* 设置控件的缩放比例(仅在WITH_VGCANVAS定义时生效)。
* @annotation ["scriptable"]
* @param {widget_t*} widget 控件对象。
* @param {float_t} scale_x X方向缩放比例。
* @param {float_t} scale_y Y方向缩放比例。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_base_set_scale(widget_t* widget, float_t scale_x, float_t scale_y);
#define image_set_scale image_base_set_scale
/**
* @method image_base_set_anchor
* 设置控件的锚点(仅在WITH_VGCANVAS定义时生效)。
* @annotation ["scriptable"]
* @param {widget_t*} widget 控件对象。
* @param {float_t} anchor_x 锚点X(0-1)。0在控件左边0.5在控件中间1在控件右边。
* @param {float_t} anchor_y 锚点Y(0-1)。0在控件顶部0.5在控件中间1在控件底部。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_base_set_anchor(widget_t* widget, float_t anchor_x, float_t anchor_y);
#define image_set_anchor image_base_set_anchor
/**
* @method image_base_set_selected
* 设置控件的选中状态。
* @annotation ["scriptable"]
* @param {widget_t*} widget 控件对象。
* @param {bool_t} selected 是否被选中。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_base_set_selected(widget_t* widget, bool_t selected);
#define image_set_selected image_base_set_selected
/**
* @method image_base_set_selectable
* 设置控件是否可以被选中。
* @annotation ["scriptable"]
* @param {widget_t*} widget 控件对象。
* @param {bool_t} selectable 是否可以被选中。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_base_set_selectable(widget_t* widget, bool_t selectable);
#define image_set_selectable image_base_set_selectable
/**
* @method image_base_set_clickable
* 设置控件是否可以被点击。
* @annotation ["scriptable"]
* @param {widget_t*} widget 控件对象。
* @param {bool_t} clickable 是否可以被点击。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_base_set_clickable(widget_t* widget, bool_t clickable);
#define image_set_clickable image_base_set_clickable
/**
* @method image_base_cast
* 转换为image_base对象(供脚本语言使用)。
* @annotation ["cast", "scriptable"]
* @param {widget_t*} widget image_base对象。
*
* @return {widget_t*} image_base对象。
*/
widget_t* image_base_cast(widget_t* widget);
/*public for subclass*/
widget_t* image_base_init(widget_t* widget);
ret_t image_base_on_destroy(widget_t* widget);
ret_t image_base_on_event(widget_t* widget, event_t* e);
ret_t image_base_get_prop(widget_t* widget, const char* name, value_t* v);
ret_t image_base_set_prop(widget_t* widget, const char* name, const value_t* v);
bool_t image_need_transform(widget_t* widget);
ret_t image_transform(widget_t* widget, canvas_t* c);
ret_t image_base_on_copy(widget_t* widget, widget_t* other);
#define IMAGE_BASE(widget) ((image_base_t*)(image_base_cast(WIDGET(widget))))
/*public for subclass and runtime type check*/
TK_EXTERN_VTABLE(image_base);
END_C_DECLS
#endif /*TK_IMAGE_BASE_H*/

View File

@ -0,0 +1,75 @@
/**
* File: image_loader.h
* Author: AWTK Develop Team
* Brief: image_loader interface
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-04-18 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "base/image_loader.h"
ret_t image_loader_load(image_loader_t* loader, const asset_info_t* asset, bitmap_t* bitmap) {
return_value_if_fail(loader != NULL && loader->load != NULL && asset != NULL && bitmap != NULL,
RET_BAD_PARAMS);
return loader->load(loader, asset, bitmap);
}
#define MAX_IMAGE_LOADERS 5
static image_loader_t* s_image_loaders[MAX_IMAGE_LOADERS];
ret_t image_loader_register(image_loader_t* loader) {
uint32_t i = 0;
return_value_if_fail(loader != NULL, RET_BAD_PARAMS);
for (i = 0; i < ARRAY_SIZE(s_image_loaders); i++) {
if (s_image_loaders[i] == NULL) {
s_image_loaders[i] = loader;
return RET_OK;
}
}
return RET_FAIL;
}
ret_t image_loader_unregister(image_loader_t* loader) {
uint32_t i = 0;
return_value_if_fail(loader != NULL, RET_BAD_PARAMS);
for (i = 0; i < ARRAY_SIZE(s_image_loaders); i++) {
if (s_image_loaders[i] == loader) {
s_image_loaders[i] = NULL;
return RET_OK;
}
}
return RET_NOT_FOUND;
}
ret_t image_loader_load_image(const asset_info_t* asset, bitmap_t* bitmap) {
int32_t i = ARRAY_SIZE(s_image_loaders) - 1;
return_value_if_fail(asset != NULL && bitmap != NULL, RET_BAD_PARAMS);
for (; i >= 0; i--) {
image_loader_t* loader = s_image_loaders[i];
if (loader != NULL && image_loader_load(loader, asset, bitmap) == RET_OK) {
return RET_OK;
}
}
return RET_FAIL;
}

View File

@ -0,0 +1,91 @@
/**
* File: image_loader.h
* Author: AWTK Develop Team
* Brief: image_loader interface
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-04-18 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_IMAGE_LOADER_H
#define TK_IMAGE_LOADER_H
#include "base/bitmap.h"
#include "base/assets_manager.h"
BEGIN_C_DECLS
struct _image_loader_t;
typedef struct _image_loader_t image_loader_t;
typedef ret_t (*image_loader_load_t)(image_loader_t* loader, const asset_info_t* asset,
bitmap_t* bitmap);
/**
* @class image_loader_t
* 图片加载接口。
*/
struct _image_loader_t {
image_loader_load_t load;
};
/**
* @method image_loader_load
* 加载图片。
*
* @param {image_loader_t*} loader loader对象。
* @param {const asset_info_t*} asset 资源。
* @param {bitmap_t*} bitmap 用于返回位图对象。
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_loader_load(image_loader_t* loader, const asset_info_t* asset, bitmap_t* bitmap);
/**
* @method image_loader_register
* 注册图片加载器。
*
* @annotation ["static"]
* @param {image_loader_t*} loader loader对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_loader_register(image_loader_t* loader);
/**
* @method image_loader_unregister
* 注销图片加载器。
*
* @annotation ["static"]
* @param {image_loader_t*} loader loader对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_loader_unregister(image_loader_t* loader);
/**
* @method image_loader_load_image
* 查找满足条件加载器并加载图片。
*
* @annotation ["static"]
* @param {const asset_info_t*} asset 资源。
* @param {bitmap_t*} bitmap 用于返回位图对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_loader_load_image(const asset_info_t* asset, bitmap_t* bitmap);
END_C_DECLS
#endif /*TK_IMAGE_LOADER_H*/

View File

@ -0,0 +1,383 @@
/**
* File: image_manager.c
* Author: AWTK Develop Team
* Brief: bitmap manager
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-14 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "tkc/time_now.h"
#include "base/locale_info.h"
#include "base/image_manager.h"
typedef struct _bitmap_cache_t {
bitmap_t image;
char* name;
uint32_t access_count;
uint64_t created_time;
uint64_t last_access_time;
} bitmap_cache_t;
static int bitmap_cache_cmp_time(bitmap_cache_t* a, bitmap_cache_t* b) {
return (a->last_access_time <= b->last_access_time) ? 0 : -1;
}
static int bitmap_cache_cmp_name(bitmap_cache_t* a, bitmap_cache_t* b) {
return strcmp(a->name, b->name);
}
static int bitmap_cache_cmp_data(bitmap_cache_t* a, bitmap_cache_t* b) {
return (char*)(a->image.buffer) - (char*)(b->image.buffer);
}
static int bitmap_cache_cmp_access_time_dec(bitmap_cache_t* a, bitmap_cache_t* b) {
return (b->last_access_time) - (a->last_access_time);
}
static ret_t bitmap_cache_destroy(bitmap_cache_t* cache) {
return_value_if_fail(cache != NULL, RET_BAD_PARAMS);
bitmap_t* image = &(cache->image);
image_manager_t* imm = image->image_manager;
if (imm != NULL && image->should_free_data) {
imm->mem_size_of_cached_images -= bitmap_get_mem_size(image);
}
log_debug("unload image %s\n", cache->name);
bitmap_destroy(&(cache->image));
TKMEM_FREE(cache->name);
TKMEM_FREE(cache);
return RET_OK;
}
static image_manager_t* s_image_manager = NULL;
image_manager_t* image_manager() {
return s_image_manager;
}
ret_t image_manager_set(image_manager_t* imm) {
s_image_manager = imm;
return RET_OK;
}
image_manager_t* image_manager_create(void) {
image_manager_t* imm = TKMEM_ZALLOC(image_manager_t);
return_value_if_fail(imm != NULL, NULL);
return image_manager_init(imm);
}
static locale_info_t* image_manager_get_locale_info(image_manager_t* imm) {
return_value_if_fail(imm != NULL, NULL);
locale_info_t* locale = locale_info();
if (imm->assets_manager != NULL && imm->assets_manager->locale_info != NULL) {
locale = imm->assets_manager->locale_info;
}
return locale;
}
image_manager_t* image_manager_init(image_manager_t* imm) {
return_value_if_fail(imm != NULL, NULL);
darray_init(&(imm->images), 0, (tk_destroy_t)bitmap_cache_destroy, NULL);
imm->assets_manager = assets_manager();
return imm;
}
static ret_t image_manager_clear_cache(image_manager_t* imm) {
bitmap_cache_t* iter = NULL;
return_value_if_fail(imm != NULL, RET_BAD_PARAMS);
if (imm->images.size == 0 || imm->max_mem_size_of_cached_images == 0 ||
imm->mem_size_of_cached_images < imm->max_mem_size_of_cached_images) {
return RET_OK;
}
darray_sort(&(imm->images), (tk_compare_t)bitmap_cache_cmp_access_time_dec);
do {
iter = (bitmap_cache_t*)darray_pop(&(imm->images));
bitmap_cache_destroy(iter);
log_debug("clear cache: mem_size_of_cached_images=%u nr=%u", imm->mem_size_of_cached_images,
imm->images.size);
} while (imm->images.size > 0 &&
imm->mem_size_of_cached_images > imm->max_mem_size_of_cached_images);
return RET_OK;
}
ret_t image_manager_add(image_manager_t* imm, const char* name, const bitmap_t* image) {
bitmap_cache_t* cache = NULL;
return_value_if_fail(imm != NULL && name != NULL && image != NULL, RET_BAD_PARAMS);
cache = TKMEM_ZALLOC(bitmap_cache_t);
return_value_if_fail(cache != NULL, RET_OOM);
cache->image = *image;
cache->access_count = 1;
cache->created_time = time_now_s();
cache->image.should_free_handle = FALSE;
cache->name = tk_strdup(name);
cache->image.name = cache->name;
cache->last_access_time = cache->created_time;
cache->image.image_manager = imm;
if (image->should_free_data) {
imm->mem_size_of_cached_images += bitmap_get_mem_size((bitmap_t*)image);
image_manager_clear_cache(imm);
}
return darray_push(&(imm->images), cache);
}
ret_t image_manager_lookup(image_manager_t* imm, const char* name, bitmap_t* image) {
bitmap_cache_t info;
bitmap_cache_t* iter = NULL;
return_value_if_fail(imm != NULL && name != NULL && image != NULL, RET_BAD_PARAMS);
memset(&info, 0x00, sizeof(info));
info.name = (char*)name;
imm->images.compare = (tk_compare_t)bitmap_cache_cmp_name;
iter = darray_find(&(imm->images), &info);
if (iter != NULL) {
*image = iter->image;
image->destroy = NULL;
image->image_manager = imm;
image->specific_destroy = NULL;
image->should_free_data = FALSE;
iter->access_count++;
iter->last_access_time = time_now_s();
return RET_OK;
}
return RET_NOT_FOUND;
}
ret_t image_manager_update_specific(image_manager_t* imm, bitmap_t* image) {
bitmap_cache_t info;
bitmap_cache_t* iter = NULL;
return_value_if_fail(image != NULL, RET_BAD_PARAMS);
if (!imm && !(imm = image_manager())) {
return RET_FAIL;
}
if (image->image_manager != NULL) {
imm = image->image_manager;
}
info.image.buffer = image->buffer;
imm->images.compare = (tk_compare_t)bitmap_cache_cmp_data;
iter = darray_find(&(imm->images), &info);
if (iter != NULL) {
iter->image.flags = image->flags;
iter->image.specific = image->specific;
iter->image.specific_ctx = image->specific_ctx;
iter->image.specific_destroy = image->specific_destroy;
image->specific_destroy = NULL;
return RET_OK;
}
return RET_NOT_FOUND;
}
static ret_t image_manager_get_bitmap_impl(image_manager_t* imm, const char* name,
bitmap_t* image) {
const asset_info_t* res = NULL;
return_value_if_fail(imm != NULL && name != NULL && image != NULL, RET_BAD_PARAMS);
memset(image, 0x00, sizeof(bitmap_t));
if (image_manager_lookup(imm, name, image) == RET_OK) {
return RET_OK;
}
res = assets_manager_ref(imm->assets_manager, ASSET_TYPE_IMAGE, name);
if (res == NULL) {
return RET_NOT_FOUND;
}
memset(image, 0x00, sizeof(bitmap_t));
if (res->subtype == ASSET_TYPE_IMAGE_RAW) {
const bitmap_header_t* header = (const bitmap_header_t*)res->data;
image->w = header->w;
image->h = header->h;
image->flags = header->flags;
image->format = header->format;
image->name = res->name;
image->image_manager = imm;
bitmap_set_line_length(image, image->line_length);
image->buffer = GRAPHIC_BUFFER_CREATE_WITH_DATA(header->data, header->w, header->h,
(bitmap_format_t)(header->format));
image->should_free_data = image->buffer != NULL;
image_manager_add(imm, name, image);
image->should_free_data = FALSE;
return RET_OK;
} else if (res->subtype != ASSET_TYPE_IMAGE_BSVG) {
ret_t ret = image_loader_load_image(res, image);
if (ret == RET_OK) {
image_manager_add(imm, name, image);
assets_manager_unref(imm->assets_manager, res);
}
return image_manager_lookup(imm, name, image);
} else {
return RET_NOT_FOUND;
}
}
typedef struct _imm_expr_info_t {
image_manager_t* imm;
bitmap_t* image;
} imm_expr_info_t;
static ret_t image_manager_on_expr_result(void* ctx, const void* data) {
imm_expr_info_t* info = (imm_expr_info_t*)ctx;
const char* name = (const char*)data;
return image_manager_get_bitmap_impl(info->imm, name, info->image);
}
ret_t image_manager_get_bitmap_exprs(image_manager_t* imm, const char* exprs, bitmap_t* image) {
imm_expr_info_t ctx = {imm, image};
return system_info_eval_exprs(system_info(), exprs, image_manager_on_expr_result, &ctx);
}
ret_t image_manager_get_bitmap(image_manager_t* imm, const char* name, bitmap_t* image) {
return_value_if_fail(imm != NULL && name != NULL && image != NULL, RET_BAD_PARAMS);
locale_info_t* locale_info = image_manager_get_locale_info(imm);
if (strstr(name, TK_LOCALE_MAGIC) != NULL) {
char locale[TK_NAME_LEN + 1];
char real_name[TK_NAME_LEN + 1];
const char* language = locale_info->language;
const char* country = locale_info->country;
if (strlen(language) > 0 && strlen(country) > 0) {
tk_snprintf(locale, sizeof(locale) - 1, "%s_%s", language, country);
tk_replace_locale(name, real_name, locale);
if (image_manager_get_bitmap_impl(imm, real_name, image) == RET_OK) {
return RET_OK;
}
}
tk_replace_locale(name, real_name, language);
if (image_manager_get_bitmap_impl(imm, real_name, image) == RET_OK) {
return RET_OK;
}
tk_replace_locale(name, real_name, "");
if (image_manager_get_bitmap_impl(imm, real_name, image) == RET_OK) {
return RET_OK;
}
return RET_FAIL;
} else if (strchr(name, '$') != NULL || strchr(name, ',') != NULL) {
return image_manager_get_bitmap_exprs(imm, name, image);
} else {
return image_manager_get_bitmap_impl(imm, name, image);
}
}
ret_t image_manager_preload(image_manager_t* imm, const char* name) {
bitmap_t image;
return_value_if_fail(imm != NULL && name != NULL && *name, RET_BAD_PARAMS);
return image_manager_get_bitmap(imm, name, &image);
}
ret_t image_manager_set_assets_manager(image_manager_t* imm, assets_manager_t* am) {
return_value_if_fail(imm != NULL, RET_BAD_PARAMS);
imm->assets_manager = am;
return RET_OK;
}
bool_t image_manager_has_bitmap(image_manager_t* imm, bitmap_t* image) {
bitmap_cache_t b;
return_value_if_fail(imm != NULL && image != NULL, RET_BAD_PARAMS);
b.image.buffer = image->buffer;
if (darray_find_ex(&(imm->images), (tk_compare_t)bitmap_cache_cmp_data, &b) == NULL) {
return FALSE;
} else {
return TRUE;
}
}
ret_t image_manager_unload_unused(image_manager_t* imm, uint32_t time_delta_s) {
bitmap_cache_t b;
b.last_access_time = time_now_s() - time_delta_s;
return_value_if_fail(imm != NULL, RET_BAD_PARAMS);
imm->images.compare = (tk_compare_t)bitmap_cache_cmp_time;
return darray_remove_all(&(imm->images), NULL, &b);
}
ret_t image_manager_unload_all(image_manager_t* imm) {
return_value_if_fail(imm != NULL, RET_BAD_PARAMS);
return darray_clear(&(imm->images));
}
ret_t image_manager_unload_bitmap(image_manager_t* imm, bitmap_t* image) {
bitmap_cache_t b;
return_value_if_fail(imm != NULL && image != NULL, RET_BAD_PARAMS);
b.image.buffer = image->buffer;
imm->images.compare = (tk_compare_t)bitmap_cache_cmp_data;
return darray_remove_all(&(imm->images), NULL, &b);
}
ret_t image_manager_deinit(image_manager_t* imm) {
return_value_if_fail(imm != NULL, RET_BAD_PARAMS);
darray_deinit(&(imm->images));
return RET_OK;
}
ret_t image_manager_destroy(image_manager_t* imm) {
return_value_if_fail(imm != NULL, RET_BAD_PARAMS);
image_manager_deinit(imm);
TKMEM_FREE(imm);
return RET_OK;
}
ret_t image_manager_set_max_mem_size_of_cached_images(image_manager_t* imm, uint32_t max_mem_size) {
return_value_if_fail(imm != NULL, RET_BAD_PARAMS);
imm->max_mem_size_of_cached_images = max_mem_size;
return RET_OK;
}

View File

@ -0,0 +1,232 @@
/**
* File: image_manager.h
* Author: AWTK Develop Team
* Brief: image manager
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-14 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_IMAGE_MANAGER_H
#define TK_IMAGE_MANAGER_H
#include "tkc/darray.h"
#include "base/image_loader.h"
#include "base/assets_manager.h"
BEGIN_C_DECLS
/**
* 但没有文件系统时图片被转成位图直接编译到程序中。bitmap_header_t用来描述该位图的信息。
*/
typedef struct _bitmap_header_t {
uint16_t w;
uint16_t h;
uint16_t flags; /*bitmap_flag_t*/
uint16_t format; /*bitmap_format_t*/
uint8_t data[4];
} bitmap_header_t;
/**
* @class image_manager_t
* @annotation ["scriptable"]
* 图片管理器。负责加载,解码和缓存图片。
*/
struct _image_manager_t {
/**
* @property {darray_t} images
* @annotation ["private"]
* 缓存的图片。
*/
darray_t images;
/**
* @property {assets_manager_t*} assets_manager
* @annotation ["private"]
* 资源管理器。
*/
assets_manager_t* assets_manager;
/*private*/
uint32_t mem_size_of_cached_images;
uint32_t max_mem_size_of_cached_images;
};
/**
* @method image_manager
* 获取缺省的图片管理器。
* @alias image_manager_instance
* @annotation ["constructor", "scriptable"]
* @return {image_manager_t*} 返回图片管理器对象。
*/
image_manager_t* image_manager(void);
/**
* @method image_manager_set
* 设置缺省的图片管理器。
* @param {image_manager_t*} imm 图片管理器对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_manager_set(image_manager_t* imm);
/**
* @method image_manager_create
* 创建图片管理器。
* @annotation ["constructor"]
*
* @return {image_manager_t*} 返回图片管理器对象。
*/
image_manager_t* image_manager_create(void);
/**
* @method image_manager_init
* 初始化图片管理器。
* @annotation ["constructor"]
* @param {image_manager_t*} imm 图片管理器对象。
*
* @return {image_manager_t*} 返回图片管理器对象。
*/
image_manager_t* image_manager_init(image_manager_t* imm);
/**
* @method image_manager_set_max_mem_size_of_cached_images
* 设置图片缓存占用的最大内存。
* @param {image_manager_t*} imm 图片管理器对象。
* @param {uint32_t} max_mem_size 最大缓存内存(字节数)。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_manager_set_max_mem_size_of_cached_images(image_manager_t* imm, uint32_t max_mem_size);
/**
* @method image_manager_get_bitmap
* 获取指定的图片。
* 先从缓存查找,如果没找到,再加载并缓存。
*
* @annotation ["scriptable"]
* @param {image_manager_t*} imm 图片管理器对象。
* @param {char*} name 图片名称。
* @param {bitmap_t*} image 用于返回图片。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_manager_get_bitmap(image_manager_t* imm, const char* name, bitmap_t* image);
/**
* @method image_manager_preload
* 预加载指定的图片。
* @annotation ["scriptable"]
* @param {image_manager_t*} imm 图片管理器对象。
* @param {char*} name 图片名称。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_manager_preload(image_manager_t* imm, const char* name);
/**
* @method image_manager_has_bitmap
* 图片是否在图片管理中。
* @param {image_manager_t*} imm 图片管理器对象。
* @param {bitmap_t*} image 图片。
*
* @return {bool_t} 返回TRUE表示存在否则表示不存在。
*/
bool_t image_manager_has_bitmap(image_manager_t* imm, bitmap_t* image);
/**
* @method image_manager_unload_unused
* 从图片管理器中卸载指定时间内没有使用的图片。
* @param {image_manager_t*} imm 图片管理器对象。
* @param {uint32_t} time_delta_s 时间范围,单位为秒。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_manager_unload_unused(image_manager_t* imm, uint32_t time_delta_s);
/**
* @method image_manager_unload_all
* 从图片管理器中卸载全部图片。
*
* @param {image_manager_t*} imm 图片管理器对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_manager_unload_all(image_manager_t* imm);
/**
* @method image_manager_unload_bitmap
* 从图片管理器中卸载指定的图片。
* @param {image_manager_t*} imm 图片管理器对象。
* @param {bitmap_t*} image 图片。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_manager_unload_bitmap(image_manager_t* imm, bitmap_t* image);
/**
* @method image_manager_update_specific
* 更新缓存中图片的specific信息。
* @param {image_manager_t*} imm 图片管理器对象。
* @param {bitmap_t*} image 返回图片信息。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_manager_update_specific(image_manager_t* imm, bitmap_t* image);
/**
* @method image_manager_set_assets_manager
* 设置资源管理器对象。
*
* 之所以需要设置资源管理器对象而不是使用缺省的资源管理器对象是因为在designer中有两个图片管理器
*
* * 一个用于designer本身加载图片。
*
* * 一个用于被设计的窗口加载图片。
*
*这两个图片管理器需要从不同的路径加载资源。
*
* @param {image_manager_t*} imm 图片管理器对象。
* @param {assets_manager_t*} assets_manager 资源管理器。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_manager_set_assets_manager(image_manager_t* imm, assets_manager_t* assets_manager);
/**
* @method image_manager_deinit
* 析构图片管理器。
* @param {image_manager_t*} imm 图片管理器对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_manager_deinit(image_manager_t* im);
/**
* @method image_manager_destroy
* 析构并释放图片管理器。
* @param {image_manager_t*} imm 图片管理器对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t image_manager_destroy(image_manager_t* im);
/*public for test*/
ret_t image_manager_add(image_manager_t* imm, const char* name, const bitmap_t* image);
ret_t image_manager_lookup(image_manager_t* imm, const char* name, bitmap_t* image);
END_C_DECLS
#endif /*TK_IMAGE_MANAGER_H*/

View File

@ -0,0 +1,367 @@
/**
* File: input_device_status.h
* Author: AWTK Develop Team
* Brief: input device status
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-11-28 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/time_now.h"
#include "base/keys.h"
#include "base/system_info.h"
#include "base/window_manager.h"
#include "base/input_device_status.h"
static ret_t input_device_status_init_key_event(input_device_status_t* ids, key_event_t* evt);
input_device_status_t* input_device_status_init(input_device_status_t* ids) {
return_value_if_fail(ids != NULL, NULL);
memset(ids, 0x00, sizeof(input_device_status_t));
return ids;
}
static key_pressed_info_t* input_device_status_find_press_info(input_device_status_t* ids,
uint32_t key) {
uint32_t i = 0;
for (i = 0; i < MAX_PRESSED_KEYS_NR; i++) {
key_pressed_info_t* iter = ids->pressed_info + i;
if (iter->key == key) {
return iter;
}
}
return NULL;
}
static bool_t input_device_status_has_pressed_key(input_device_status_t* ids) {
uint32_t i = 0;
for (i = 0; i < MAX_PRESSED_KEYS_NR; i++) {
key_pressed_info_t* iter = ids->pressed_info + i;
if (iter->key) {
return TRUE;
}
}
return FALSE;
}
ret_t input_device_status_abort_all_pressed_keys(input_device_status_t* ids) {
uint32_t i = 0;
return_value_if_fail(ids != NULL, RET_BAD_PARAMS);
for (i = 0; i < MAX_PRESSED_KEYS_NR; i++) {
key_pressed_info_t* iter = ids->pressed_info + i;
if (iter->key) {
iter->should_abort = TRUE;
}
}
return RET_OK;
}
static ret_t input_device_status_dispatch_long_press(input_device_status_t* ids) {
uint32_t i = 0;
key_event_t evt;
uint64_t now = time_now_ms();
widget_t* widget = ids->widget;
for (i = 0; i < MAX_PRESSED_KEYS_NR; i++) {
key_pressed_info_t* iter = ids->pressed_info + i;
if (iter->key && !iter->emitted && !iter->should_abort) {
uint64_t t = now - iter->time;
if (t >= TK_KEY_LONG_PRESS_TIME) {
window_manager_t* wm = WINDOW_MANAGER(window_manager());
event_t* e = key_event_init(&evt, EVT_KEY_LONG_PRESS, wm->global_emitter, iter->key);
input_device_status_init_key_event(ids, &evt);
if (emitter_dispatch(wm->global_emitter, e) != RET_STOP) {
e->target = widget;
widget_on_keydown(widget, &evt);
}
log_debug("long press:%d\n", iter->key);
iter->emitted = TRUE;
}
}
}
return RET_OK;
}
static ret_t long_press_check_on_timer(const timer_info_t* info) {
input_device_status_t* ids = (input_device_status_t*)(info->ctx);
input_device_status_dispatch_long_press(ids);
if (input_device_status_has_pressed_key(ids)) {
return RET_REPEAT;
} else {
ids->long_press_check_timer = TK_INVALID_ID;
return RET_REMOVE;
}
}
static ret_t input_device_status_update_key_press_info(input_device_status_t* ids, uint32_t key,
bool_t down) {
key_pressed_info_t* info = input_device_status_find_press_info(ids, key);
if (down) {
if (info == NULL) {
info = input_device_status_find_press_info(ids, 0);
return_value_if_fail(info != NULL, RET_BAD_PARAMS);
info->key = key;
info->time = time_now_ms();
}
if (ids->long_press_check_timer == TK_INVALID_ID) {
ids->long_press_check_timer =
timer_add(long_press_check_on_timer, ids, TK_KEY_LONG_PRESS_TIME);
}
} else {
return_value_if_fail(info != NULL, RET_BAD_PARAMS);
memset(info, 0x00, sizeof(key_pressed_info_t));
}
return RET_OK;
}
static ret_t input_device_status_update_key_status(input_device_status_t* ids, uint32_t key,
bool_t down) {
if (key == TK_KEY_LSHIFT) {
ids->shift = down;
ids->lshift = down;
} else if (key == TK_KEY_RSHIFT) {
ids->shift = down;
ids->rshift = down;
} else if (key == TK_KEY_LALT) {
ids->alt = down;
ids->lalt = down;
} else if (key == TK_KEY_RALT) {
ids->alt = down;
ids->ralt = down;
} else if (key == TK_KEY_LCTRL) {
ids->ctrl = down;
ids->lctrl = down;
} else if (key == TK_KEY_RCTRL) {
ids->ctrl = down;
ids->rctrl = down;
} else if (key == TK_KEY_MENU) {
ids->menu = down;
} else if (key == TK_KEY_LCOMMAND || key == TK_KEY_RCOMMAND) {
ids->cmd = down;
}
if (!down) {
if (key == TK_KEY_CAPSLOCK) {
ids->capslock = !(ids->capslock);
}
}
input_device_status_update_key_press_info(ids, key, down);
return RET_OK;
}
typedef struct _key_shift_t {
char key;
char shift_key;
} key_shift_t;
static const key_shift_t key_shift[] = {
{'`', '~'}, {'1', '!'}, {'2', '@'}, {'3', '#'}, {'4', '$'}, {'5', '%'}, {'6', '^'},
{'7', '&'}, {'8', '*'}, {'9', '('}, {'0', ')'}, {'-', '_'}, {'=', '+'}, {'[', '{'},
{']', '}'}, {',', '<'}, {'.', '>'}, {'\\', '|'}, {'/', '?'}, {';', ':'}, {'\'', '\"'}};
static uint32_t input_device_status_get_shift_key_code(input_device_status_t* ids,
uint32_t old_key_code) {
char c = (char)old_key_code;
if (ids->shift) {
uint32_t i = 0;
for (i = 0; i < ARRAY_SIZE(key_shift); i++) {
if (key_shift[i].key == c) {
return key_shift[i].shift_key;
}
}
}
if (ids->shift && ids->capslock) {
if (c >= 'A' && c <= 'Z') {
return tolower(c);
}
}
if (ids->shift || ids->capslock) {
if (c >= 'a' && c <= 'z') {
return toupper(c);
}
}
return old_key_code;
}
static ret_t input_device_status_shift_key(input_device_status_t* ids, key_event_t* e) {
e->key = input_device_status_get_shift_key_code(ids, e->key);
return RET_OK;
}
static ret_t input_device_status_init_pointer_event(input_device_status_t* ids,
pointer_event_t* evt) {
return_value_if_fail(ids != NULL && evt != NULL, RET_BAD_PARAMS);
evt->alt = ids->alt;
evt->ctrl = ids->ctrl;
evt->shift = ids->shift;
evt->cmd = ids->cmd;
evt->menu = ids->menu;
return RET_OK;
}
static ret_t input_device_status_init_wheel_event(input_device_status_t* ids, wheel_event_t* evt) {
return_value_if_fail(ids != NULL && evt != NULL, RET_BAD_PARAMS);
evt->alt = ids->alt;
evt->ctrl = ids->ctrl;
evt->shift = ids->shift;
return RET_OK;
}
static ret_t input_device_status_init_key_event(input_device_status_t* ids, key_event_t* evt) {
return_value_if_fail(ids != NULL && evt != NULL, RET_BAD_PARAMS);
evt->alt = ids->alt;
evt->ctrl = ids->ctrl;
evt->shift = ids->shift;
evt->lalt = ids->lalt;
evt->lctrl = ids->lctrl;
evt->lshift = ids->lshift;
evt->ralt = ids->ralt;
evt->rctrl = ids->rctrl;
evt->rshift = ids->rshift;
evt->capslock = ids->capslock;
evt->cmd = ids->cmd;
evt->menu = ids->menu;
return RET_OK;
}
ret_t input_device_status_on_input_event(input_device_status_t* ids, widget_t* widget, event_t* e) {
window_manager_t* wm = WINDOW_MANAGER(widget_get_window_manager(widget));
return_value_if_fail(ids != NULL && e != NULL, RET_BAD_PARAMS);
ids->widget = widget;
switch (e->type) {
case EVT_POINTER_DOWN: {
pointer_event_t* evt = (pointer_event_t*)e;
pointer_event_rotate(evt, system_info());
ids->pressed = TRUE;
ids->last_x = evt->x;
ids->last_y = evt->y;
input_device_status_init_pointer_event(ids, evt);
widget_on_pointer_down(widget, evt);
break;
}
case EVT_POINTER_MOVE: {
pointer_event_t* evt = (pointer_event_t*)e;
pointer_event_rotate(evt, system_info());
if (evt->x != ids->last_x || evt->y != ids->last_y) {
ids->last_x = evt->x;
ids->last_y = evt->y;
input_device_status_init_pointer_event(ids, evt);
widget_on_pointer_move(widget, evt);
}
break;
}
case EVT_POINTER_UP: {
pointer_event_t* evt = (pointer_event_t*)e;
pointer_event_rotate(evt, system_info());
input_device_status_init_pointer_event(ids, evt);
widget_on_pointer_up(widget, evt);
ids->last_x = evt->x;
ids->last_y = evt->y;
ids->pressed = FALSE;
break;
}
case EVT_CONTEXT_MENU: {
pointer_event_t* evt = (pointer_event_t*)e;
pointer_event_rotate(evt, system_info());
input_device_status_init_pointer_event(ids, evt);
widget_on_context_menu(widget, evt);
break;
}
case EVT_KEY_DOWN: {
key_event_t* evt = (key_event_t*)e;
uint32_t key = input_device_status_get_shift_key_code(ids, evt->key);
key_pressed_info_t* info = input_device_status_find_press_info(ids, key);
input_device_status_update_key_status(ids, key, TRUE);
input_device_status_init_key_event(ids, evt);
input_device_status_shift_key(ids, evt);
if (info == NULL || !info->should_abort) {
if (wm->widget_grab_key != NULL) {
widget_on_keydown(wm->widget_grab_key, evt);
} else {
widget_on_keydown(widget, evt);
}
}
break;
}
case EVT_KEY_UP: {
key_event_t* evt = (key_event_t*)e;
key_pressed_info_t* info = input_device_status_find_press_info(ids, evt->key);
input_device_status_init_key_event(ids, evt);
input_device_status_shift_key(ids, evt);
if (info == NULL || !info->should_abort) {
if (wm->widget_grab_key != NULL) {
widget_on_keyup(wm->widget_grab_key, evt);
} else {
widget_on_keyup(widget, evt);
}
}
input_device_status_update_key_status(ids, evt->key, FALSE);
break;
}
case EVT_WHEEL: {
wheel_event_t* evt = (wheel_event_t*)e;
input_device_status_init_wheel_event(ids, evt);
widget_on_wheel(widget, evt);
break;
}
case EVT_MULTI_GESTURE: {
multi_gesture_event_t* evt = (multi_gesture_event_t*)e;
widget_on_multi_gesture(widget, evt);
break;
}
default:
break;
}
return RET_OK;
}

View File

@ -0,0 +1,104 @@
/**
* File: input_device_status.h
* Author: AWTK Develop Team
* Brief: input device status
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-11-28 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_INPUT_DEVICE_STATUS_H
#define TK_INPUT_DEVICE_STATUS_H
#include "base/widget.h"
BEGIN_C_DECLS
#define MAX_PRESSED_KEYS_NR 16
typedef struct _key_pressed_info_t {
uint32_t key;
uint32_t emitted;
uint64_t time;
/*
* 窗口切换时旧窗口按下的键一直不松开会持续触发PRESS可能会干扰新窗口的用户功能。
* 所在窗口切换时abort全部已经按下的键直到按键松开。
*/
bool_t should_abort;
} key_pressed_info_t;
/**
* @class input_device_status_t
* 输入设备状态管理器。本类仅供窗口管理器内部使用。
*/
typedef struct _input_device_status_t {
uint32_t ctrl : 1;
uint32_t alt : 1;
uint32_t shift : 1;
uint32_t lctrl : 1;
uint32_t lalt : 1;
uint32_t lshift : 1;
uint32_t rctrl : 1;
uint32_t ralt : 1;
uint32_t rshift : 1;
uint32_t cmd : 1;
uint32_t menu : 1;
uint32_t capslock : 1;
xy_t last_x;
xy_t last_y;
bool_t pressed;
widget_t* widget;
uint32_t long_press_check_timer;
key_pressed_info_t pressed_info[MAX_PRESSED_KEYS_NR + 1];
} input_device_status_t;
/**
* @method input_device_status_init
* 初始化输入设备状态管理器。
* @annotation ["constructor"]
* @param {input_device_status_t*} ids 输入设备状态管理器对象。
*
* @return {input_device_status_t*} 返回输入设备状态管理器对象。
*/
input_device_status_t* input_device_status_init(input_device_status_t* ids);
/**
* @method input_device_status_on_input_event
* 对输入事件进行处理然后分发给widget。
* @param {input_device_status_t*} ids 输入设备状态管理器对象。
* @param {widget_t*} widget 窗口管理器对象。
* @param {event_t*} e 事件对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_device_status_on_input_event(input_device_status_t* ids, widget_t* widget, event_t* e);
/**
* @method input_device_status_abort_all_pressed_keys
* 取消全部已经按下的键。
*
* 窗口切换时旧窗口按下的键一直不松开会持续触发PRESS可能会干扰新窗口的用户功能。
* 所在窗口切换时abort全部已经按下的键直到按键松开。
*
* @param {input_device_status_t*} ids 输入设备状态管理器对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_device_status_abort_all_pressed_keys(input_device_status_t* ids);
END_C_DECLS
#endif /*TK_INPUT_DEVICE_STATUS_H*/

View File

@ -0,0 +1,187 @@
/**
* File: input_engine.
* Author: AWTK Develop Team
* Brief: input method engine
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-06-23 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "base/keys.h"
#include "base/input_method.h"
#include "base/input_engine.h"
ret_t input_engine_init(input_engine_t* engine) {
ret_t ret = RET_OK;
return_value_if_fail(engine != NULL, RET_BAD_PARAMS);
wbuffer_init_extendable(&(engine->candidates));
if (TK_IM_MAX_CANDIDATE_CHARS != 0) {
wbuffer_extend_capacity(&(engine->candidates), TK_IM_MAX_CANDIDATE_CHARS);
}
if (engine->init) {
ret = engine->init(engine);
}
return ret;
}
ret_t input_engine_deinit(input_engine_t* engine) {
ret_t ret = RET_OK;
return_value_if_fail(engine != NULL, RET_BAD_PARAMS);
wbuffer_deinit(&(engine->candidates));
if (engine->deinit) {
ret = engine->deinit(engine);
}
return ret;
}
ret_t input_engine_reset_candidates(input_engine_t* engine) {
return_value_if_fail(engine != NULL, RET_BAD_PARAMS);
engine->candidates_nr = 0;
return wbuffer_rewind(&(engine->candidates));
}
ret_t input_engine_add_candidate(input_engine_t* engine, const char* str) {
return_value_if_fail(engine != NULL && str != NULL, RET_BAD_PARAMS);
if (TK_IM_MAX_CANDIDATE_CHARS != 0 &&
engine->candidates.cursor + strlen(str) + 2 > engine->candidates.capacity) {
return RET_FAIL;
}
engine->candidates_nr++;
return wbuffer_write_string(&(engine->candidates), str);
}
ret_t input_engine_add_candidates_from_char(input_engine_t* engine, const wchar_t** table, char c) {
#if defined(WITH_IME_T9) || defined(WITH_IME_T9EXT) || defined(WITH_IME_SPINYIN)
return_value_if_fail(engine != NULL && table != NULL, RET_BAD_PARAMS);
engine->candidates_nr +=
ime_utils_add_chars(&(engine->candidates), table, c, TK_IM_MAX_CANDIDATE_CHARS == 0);
return RET_OK;
#else
return RET_NOT_IMPL;
#endif
}
ret_t input_engine_add_candidates_from_string(input_engine_t* engine, const table_entry_t* items,
uint32_t items_nr, const char* key, bool_t exact) {
#if defined(WITH_IME_T9) || defined(WITH_IME_T9EXT) || defined(WITH_IME_SPINYIN)
return_value_if_fail(engine != NULL && items != NULL && items_nr > 0 && key != NULL,
RET_BAD_PARAMS);
engine->candidates_nr += ime_utils_table_search(items, items_nr, key, &(engine->candidates),
exact, TK_IM_MAX_CANDIDATE_CHARS == 0);
return RET_OK;
#else
return RET_NOT_IMPL;
#endif
}
ret_t input_engine_dispatch_candidates(input_engine_t* engine, int32_t selected) {
return_value_if_fail(engine != NULL, RET_BAD_PARAMS);
return input_method_dispatch_candidates(engine->im, (const char*)(engine->candidates.data),
engine->candidates_nr, selected);
}
ret_t input_engine_reset_input(input_engine_t* engine) {
ret_t ret = RET_OK;
return_value_if_fail(engine != NULL, RET_BAD_PARAMS);
engine->keys.size = 0;
engine->keys.str[0] = '\0';
engine->candidates_nr = 0;
if (engine->reset_input) {
ret = engine->reset_input(engine);
}
return ret;
}
ret_t input_engine_set_lang(input_engine_t* engine, const char* lang) {
ret_t ret = RET_OK;
return_value_if_fail(engine != NULL, RET_BAD_PARAMS);
input_engine_reset_input(engine);
if (engine->set_lang) {
ret = engine->set_lang(engine, lang);
}
return ret;
}
const char* input_engine_get_lang(input_engine_t* engine) {
return_value_if_fail(engine != NULL, NULL);
if (engine->get_lang) {
return engine->get_lang(engine);
}
return NULL;
}
ret_t input_engine_search(input_engine_t* engine, const char* keys) {
return_value_if_fail(engine != NULL && engine->search != NULL && keys != NULL, RET_BAD_PARAMS);
return engine->search(engine, keys);
}
static ret_t input_engine_append_char(input_engine_t* engine, int key) {
if (key == TK_KEY_TAB || key == TK_KEY_LEFT || key == TK_KEY_RIGHT || key == TK_KEY_UP ||
key == TK_KEY_DOWN || key == TK_KEY_PAGEUP || key == TK_KEY_PAGEDOWN ||
key_code_is_enter(key) || key == TK_KEY_CANCEL) {
return RET_OK;
}
if (tk_isprint(key)) {
str_append_char(&(engine->keys), (char)key);
}
return RET_OK;
}
ret_t input_engine_input(input_engine_t* engine, int key) {
ret_t ret = RET_OK;
return_value_if_fail(engine != NULL, RET_BAD_PARAMS);
if (key == TK_KEY_BACKSPACE || key == TK_KEY_DELETE) {
if (engine->keys.size > 0) {
engine->keys.size--;
engine->keys.str[engine->keys.size] = '\0';
} else {
input_engine_reset_input(engine);
return RET_FAIL;
}
} else {
if (engine->keys.size >= TK_IM_MAX_INPUT_CHARS) {
return RET_BAD_PARAMS;
}
if (engine->input != NULL) {
if (engine->input(engine, key) == RET_OK) {
input_engine_append_char(engine, key);
} else {
return RET_FAIL;
}
} else {
input_engine_append_char(engine, key);
}
}
if (engine->search) {
ret = engine->search(engine, engine->keys.str);
}
return ret;
}

View File

@ -0,0 +1,253 @@
/**
* File: input_engine.h
* Author: AWTK Develop Team
* Brief: input method engine
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-06-23 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_INPUT_ENGINE_H
#define TK_INPUT_ENGINE_H
#include "tkc/str.h"
#include "tkc/buffer.h"
#include "base/types_def.h"
#include "input_engines/ime_utils.h"
BEGIN_C_DECLS
typedef ret_t (*input_engine_init_t)(input_engine_t* engine);
typedef ret_t (*input_engine_deinit_t)(input_engine_t* engine);
typedef ret_t (*input_engine_search_t)(input_engine_t* engine, const char* keys);
typedef ret_t (*input_engine_reset_input_t)(input_engine_t* engine);
typedef ret_t (*input_engine_input_t)(input_engine_t* engine, int key);
typedef ret_t (*input_engine_set_lang_t)(input_engine_t* engine, const char* lang);
typedef const char* (*input_engine_get_lang_t)(input_engine_t* engine);
#ifndef TK_IM_MAX_INPUT_CHARS
#define TK_IM_MAX_INPUT_CHARS 15
#endif /*TK_IM_MAX_INPUT_CHARS*/
#define TK_IM_DEFAULT_MAX_CANDIDATE_CHARS 255
#ifndef TK_IM_MAX_CANDIDATE_CHARS
#define TK_IM_MAX_CANDIDATE_CHARS TK_IM_DEFAULT_MAX_CANDIDATE_CHARS
#endif
/**
* @class input_engine_t
* 输入法引擎接口。
*
* 常见的实现方式有以下几种:
*
* * 空实现。用于不需要输入法的嵌入式平台。
*
* * 拼音输入法实现。用于需要输入法的嵌入式平台。
*
* ```graphviz
* [default_style]
*
* input_engine_pinyin_t -> input_engine_t[arrowhead=empty style=dashed]
* input_engine_null_t -> input_engine_t[arrowhead=empty style=dashed]
*
* ```
*/
struct _input_engine_t {
/**
* @property {str_t} keys
* @annotation ["private"]
* 当前的按键组合。
*/
str_t keys;
/**
* @property {wbuffer_t} candidates
* @annotation ["private"]
* 当前按键组合对应的候选字列表。
*/
wbuffer_t candidates;
/**
* @property {uint32_t} candidates_nr
* @annotation ["private"]
* 当前按键组合对应的候选字/词个数。
*/
uint32_t candidates_nr;
/*具体实现需要实现的函数*/
input_engine_init_t init;
input_engine_deinit_t deinit;
input_engine_input_t input;
input_engine_search_t search;
input_engine_set_lang_t set_lang;
input_engine_get_lang_t get_lang;
input_engine_reset_input_t reset_input;
/*private*/
input_method_t* im;
char lang[TK_NAME_LEN + 1];
void* data;
};
/**
* @method input_engine_create
* @annotation ["constructor"]
* @param {input_method_t*} im 输入法对象。
* 创建输入法引擎对象。
*
* @return {input_engine_t*} 返回输入法引擎对象。
*/
input_engine_t* input_engine_create(input_method_t* im);
/**
* @method input_engine_destroy
* @annotation ["deconstructor"]
* 销毁输入法引擎对象。
* @param {input_engine_t*} engine 输入法引擎对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_engine_destroy(input_engine_t* engine);
/**
* @method input_engine_reset_input
* 清除所有输入的按键组合和候选字。
* @param {input_engine_t*} engine 输入法引擎对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_engine_reset_input(input_engine_t* engine);
/**
* @method input_engine_init
* 初始化输入法引擎对象。
* @param {input_engine_t*} engine 输入法引擎对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_engine_init(input_engine_t* engine);
/**
* @method input_engine_deinit
* 释放输入法引擎对象。
* @param {input_engine_t*} engine 输入法引擎对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_engine_deinit(input_engine_t* engine);
/**
* @method input_engine_reset_candidates
* 重置输入法引擎对象。
* @param {input_engine_t*} engine 输入法引擎对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_engine_reset_candidates(input_engine_t* engine);
/**
* @method input_engine_add_candidate
* 给输入法引擎对象加入一个候选字。
* @param {input_engine_t*} engine 输入法引擎对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_engine_add_candidate(input_engine_t* engine, const char* str);
/**
* @method input_engine_add_candidates_from_char
* 根据字符类型给输入法引擎对象加入所有符合的候选字。
* 备注:搜索表是二维数组,需要通过参数 c 来确定使用具体行数。
*
* @param {input_engine_t*} engine 输入法引擎对象。
* @param {const wchar_t**} table 输入法搜索表。
* @param {char} c 需要显示查询的字符。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_engine_add_candidates_from_char(input_engine_t* engine, const wchar_t** table, char c);
/**
* @method input_engine_add_candidates_from_string
* 根据字符串给输入法引擎对象加入所有符合的候选字。
* @param {input_engine_t*} engine 输入法引擎对象。
* @param {const table_entry_t*} items 输入法搜索表。
* @param {uint32_t} items_nr 输入法搜索表长度。
* @param {const char*} key 需要显示查询的字符。
* @param {bool_t} exact 是否只查询完全匹配的字符串。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_engine_add_candidates_from_string(input_engine_t* engine, const table_entry_t* items,
uint32_t items_nr, const char* key, bool_t exact);
/**
* @method input_engine_dispatch_candidates
* 请求显示候选字。
* @param {input_engine_t*} engine 输入法引擎对象。
* @param {int32_t} selected 缺省选中候选字的序数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_engine_dispatch_candidates(input_engine_t* engine, int32_t selected);
/**
* @engine input_engine_set_lang
* 设置语言。
* > 有时在同一种语言环境下,也需要输入多种文字,典型的情况是同时输入中文和英文。
* > 比如T9输入法可以同时支持中文和英文输入配合软键盘随时切换输入的语言。
* > 数字、小写字母、大写字母和符合也可以视为输入的语言。
* > 主要用于提示输入法引擎选择适当的输入方法。
*
* @annotation ["scriptable"]
* @param {input_engine_t*} engine 输入法引擎对象。
* @param {const char*} lang 语言。格式为语言+国家/地区码。如zh_cn和en_us等。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_engine_set_lang(input_engine_t* engine, const char* lang);
/**
* @engine input_engine_get_lang
* 获取语言。
* @annotation ["scriptable"]
* @param {input_engine_t*} engine 输入法引擎对象。
*
* @return {const char*} 返回语言。
*/
const char* input_engine_get_lang(input_engine_t* engine);
/**
* @method input_engine_input
* 输入新的按键,并更新候选字。
* @param {input_engine_t*} engine 输入法引擎对象。
* @param {int} key 键值。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_engine_input(input_engine_t* engine, int key);
/**
* @method input_engine_search
* 根据按键组合更新候选字并通过输入法对象提交候选字和pre候选字。
* @param {input_engine_t*} engine 输入法引擎对象。
* @param {const char*} keys 按键组合。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_engine_search(input_engine_t* engine, const char* keys);
END_C_DECLS
#endif /*TK_INPUT_ENGINE_H*/

View File

@ -0,0 +1,250 @@
/**
* File: input_method.h
* Author: AWTK Develop Team
* Brief: input method interface.
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-06-19 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "base/keys.h"
#include "tkc/utils.h"
#include "base/input_method.h"
#include "base/window_manager.h"
ret_t input_method_dispatch(input_method_t* im, event_t* e) {
return_value_if_fail(im != NULL && e != NULL, RET_BAD_PARAMS);
return emitter_dispatch(&(im->emitter), e);
}
ret_t input_method_dispatch_preedit(input_method_t* im) {
event_t e = event_init(EVT_IM_PREEDIT, im);
return input_method_dispatch_to_widget(im, &e);
}
ret_t input_method_dispatch_preedit_confirm(input_method_t* im) {
event_t e = event_init(EVT_IM_PREEDIT_CONFIRM, im);
return input_method_dispatch_to_widget(im, &e);
}
ret_t input_method_dispatch_preedit_abort(input_method_t* im) {
event_t e = event_init(EVT_IM_PREEDIT_ABORT, im);
return input_method_dispatch_to_widget(im, &e);
}
ret_t input_method_dispatch_to_widget(input_method_t* im, event_t* e) {
return_value_if_fail(im != NULL && im->widget != NULL && e != NULL, RET_BAD_PARAMS);
e->target = im->widget;
return widget_dispatch(im->widget, e);
}
uint32_t input_method_on(input_method_t* im, event_type_t type, event_func_t on_event, void* ctx) {
return_value_if_fail(im != NULL && on_event != NULL, 0);
return emitter_on(&(im->emitter), type, on_event, ctx);
}
ret_t input_method_off(input_method_t* im, uint32_t id) {
return_value_if_fail(im != NULL, RET_BAD_PARAMS);
return emitter_off(&(im->emitter), id);
}
ret_t input_method_request(input_method_t* im, widget_t* widget) {
return_value_if_fail(im != NULL && im->request != NULL, RET_BAD_PARAMS);
if (im->busy) {
return RET_FAIL;
}
if (im->widget == widget) {
return RET_OK;
}
if (widget != NULL) {
widget_dispatch_simple_event(window_manager(), EVT_IM_START);
} else {
widget_dispatch_simple_event(window_manager(), EVT_IM_STOP);
}
return im->request(im, widget);
}
static input_method_t* s_input_method = NULL;
input_method_t* input_method(void) {
return s_input_method;
}
ret_t input_method_set(input_method_t* im) {
s_input_method = im;
return RET_OK;
}
ret_t input_method_update_action_button_info(input_method_t* im, const char* text, bool_t enable) {
im_action_button_info_event_t e;
return_value_if_fail(im != NULL, RET_BAD_PARAMS);
e.text = text;
e.enable = enable;
e.e = event_init(EVT_IM_ACTION_INFO, im);
im->action_button_enable = enable;
tk_strncpy(im->action_buton_text, text ? text : "", TK_NAME_LEN);
return input_method_dispatch(im, (event_t*)(&e));
}
ret_t input_method_dispatch_action(input_method_t* im) {
event_t e = event_init(EVT_IM_ACTION, im);
return_value_if_fail(im != NULL, RET_BAD_PARAMS);
input_method_dispatch(im, &e);
if (im->engine != NULL && im->engine->keys.size > 0) {
char text[64];
tk_strncpy(text, im->engine->keys.str, sizeof(text) - 1);
input_method_commit_text(im, text);
}
return input_method_dispatch_to_widget(im, &e);
}
static ret_t input_method_dispatch_key_only(input_method_t* im, uint32_t key) {
key_event_t e;
key_event_init(&e, EVT_KEY_DOWN, NULL, key);
input_method_dispatch_to_widget(input_method(), (event_t*)&e);
e.e.type = EVT_KEY_UP;
input_method_dispatch_to_widget(input_method(), (event_t*)&e);
return RET_OK;
}
ret_t input_method_dispatch_key(input_method_t* im, uint32_t key) {
return_value_if_fail(im != NULL, RET_BAD_PARAMS);
if (im->engine != NULL) {
if (input_engine_input(im->engine, (char)key) == RET_OK) {
return RET_OK;
}
}
return input_method_dispatch_key_only(im, key);
}
ret_t input_method_dispatch_keys(input_method_t* im, const char* keys) {
return_value_if_fail(im != NULL && keys != NULL, RET_BAD_PARAMS);
if (im->engine != NULL) {
return input_engine_search(im->engine, keys);
}
return RET_OK;
}
ret_t input_method_set_lang(input_method_t* im, const char* lang) {
return_value_if_fail(im != NULL, RET_BAD_PARAMS);
if (im->engine != NULL) {
if (input_engine_set_lang(im->engine, lang) == RET_OK) {
event_t e = event_init(EVT_IM_LANG_CHANGED, im);
input_method_dispatch(im, &e);
return RET_OK;
}
}
return RET_FAIL;
}
const char* input_method_get_lang(input_method_t* im) {
return_value_if_fail(im != NULL, NULL);
if (im->engine != NULL) {
return input_engine_get_lang(im->engine);
}
return NULL;
}
ret_t input_method_dispatch_candidates(input_method_t* im, const char* strs, uint32_t nr,
int32_t selected) {
im_candidates_event_t ce;
ce.e = event_init(EVT_IM_SHOW_CANDIDATES, im);
ce.candidates_nr = nr;
ce.candidates = strs;
ce.selected = selected;
return input_method_dispatch(im, (event_t*)(&ce));
}
ret_t input_method_dispatch_pre_candidates(input_method_t* im, const char* strs, uint32_t nr,
int32_t selected) {
im_candidates_event_t ce;
ce.e = event_init(EVT_IM_SHOW_PRE_CANDIDATES, im);
ce.candidates_nr = nr;
ce.candidates = strs;
ce.selected = selected;
return input_method_dispatch(im, (event_t*)(&ce));
}
ret_t input_method_commit_text_ex(input_method_t* im, bool_t replace, const char* text) {
im_commit_event_t e;
return_value_if_fail(im != NULL && text != NULL, RET_BAD_PARAMS);
if (im->engine) {
input_engine_reset_input(im->engine);
input_method_dispatch_candidates(im, "", 0, 0);
}
return input_method_dispatch_to_widget(input_method(), im_commit_event_init(&e, text, replace));
}
ret_t input_method_commit_text(input_method_t* im, const char* text) {
return input_method_commit_text_ex(im, FALSE, text);
}
ret_t input_method_destroy(input_method_t* im) {
return_value_if_fail(im != NULL, RET_BAD_PARAMS);
if (im->destroy) {
im->destroy(im);
}
return RET_OK;
}
event_t* im_commit_event_init(im_commit_event_t* e, const char* text, bool_t replace) {
return_value_if_fail(e != NULL && text != NULL, NULL);
memset(e, 0x00, sizeof(*e));
e->text = text;
e->replace = replace;
e->e = event_init(EVT_IM_COMMIT, NULL);
return (event_t*)e;
}
bool_t input_method_is_native(input_method_t* im) {
return im != NULL && im->is_native;
}

View File

@ -0,0 +1,577 @@
/**
* File: input_method.h
* Author: AWTK Develop Team
* Brief: input method interface.
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-06-19 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_INPUT_METHOD_H
#define TK_INPUT_METHOD_H
#include "base/widget.h"
#include "base/input_engine.h"
#include "base/suggest_words.h"
BEGIN_C_DECLS
typedef ret_t (*input_method_request_t)(input_method_t* im, widget_t* widget);
typedef ret_t (*input_method_destroy_t)(input_method_t* im);
/**
* @enum input_type_t
* @annotation ["scriptable"]
* @prefix INPUT_
* 输入类型常量定义。
*/
typedef enum _input_type_t {
/**
* @const INPUT_TEXT
* 文本。字符串属性值text
*/
INPUT_TEXT = 0,
/**
* @const INPUT_INT
* 整数。字符串属性值int
*/
INPUT_INT,
/**
* @const INPUT_UINT
* 非负整数。字符串属性值uint
*/
INPUT_UINT,
/**
* @const INPUT_HEX
* 16进制整数。字符串属性值hex
*/
INPUT_HEX,
/**
* @const INPUT_FLOAT
* 浮点数。字符串属性值float
*/
INPUT_FLOAT,
/**
* @const INPUT_UFLOAT
* 非负浮点数。字符串属性值ufloat
*/
INPUT_UFLOAT,
/**
* @const INPUT_EMAIL
* 邮件地址。字符串属性值email
*/
INPUT_EMAIL,
/**
* @const INPUT_PASSWORD
* 密码。字符串属性值password
*/
INPUT_PASSWORD,
/**
* @const INPUT_PHONE
* 电话号码。字符串属性值phone
*/
INPUT_PHONE,
/**
* @const INPUT_IPV4
* IP Addr V4(如192.168.1.1)。字符串属性值ipv4
*/
INPUT_IPV4,
/**
* @const INPUT_DATE
* 日期(如2020/02/20)。字符串属性值date
*/
INPUT_DATE,
/**
* @const INPUT_TIME
* 时间(时分12:00)。字符串属性值time
*/
INPUT_TIME,
/**
* @const INPUT_TIME_FULL
* 时间(时分秒12:00:00)。字符串属性值time_full
*/
INPUT_TIME_FULL,
/**
* @const INPUT_CUSTOM
* 使用自定义的软键盘(如计算器等应用不希望弹出系统软键盘)。字符串属性值custom
*/
INPUT_CUSTOM,
/**
* @const INPUT_CUSTOM_PASSWORD
* 使用自定义的密码软键盘。字符串属性值custom_password
*/
INPUT_CUSTOM_PASSWORD,
/**
* @const INPUT_ASCII
* 纯英文文本。字符串属性值ascii
*/
INPUT_ASCII,
} input_type_t;
/**
* @class im_commit_event_t
* @parent event_t
* 输入法提交输入的文本事件。
*/
typedef struct _im_commit_event_t {
event_t e;
/**
* @property {char*} text
* @annotation ["readable"]
* 提交的文本。
*/
const char* text;
/**
* @property {bool_t} replace
* @annotation ["readable"]
* 是否替换原来的文本。
*/
bool_t replace;
} im_commit_event_t;
/**
* @method im_commit_event_init
* 初始化im_commit事件。
* @param {im_commit_event_t*} e 事件对象。
* @param {const char*} text 文本。
* @param {bool_t} replace 是否替代当前的内容。
*
* @return {event_t*} 返回事件对象。
*/
event_t* im_commit_event_init(im_commit_event_t* e, const char* text, bool_t replace);
/**
* @class im_action_button_info_event_t
* @parent event_t
* 设置软键盘上的action按钮的信息事件。
*/
typedef struct _im_action_button_info_event_t {
event_t e;
/**
* @property {char*} text
* @annotation ["readable"]
* 软键盘上的action按钮显示的文本。
*/
const char* text;
/**
* @property {bool_t} enable
* @annotation ["readable"]
* 软键盘上的action按钮启用。
*/
bool_t enable;
} im_action_button_info_event_t;
/**
* @class im_candidates_event_t
* @parent event_t
* 输入法请求显示候选字的事件。
*/
typedef struct _im_candidates_event_t {
event_t e;
/**
* @property {char*} candidates
* @annotation ["readable"]
* 可选的文本,多个文本以\0分隔。如里\0李\0力\0离\0
*/
const char* candidates;
/**
* @property {uint32_t} candidates_nr
* @annotation ["readable"]
* 可选的文本的个数。
*/
uint32_t candidates_nr;
/**
* @property {int32_t} selected
* @annotation ["readable"]
* 缺省选中某个候选字小于0不选择任何候选字。
*/
int32_t selected;
} im_candidates_event_t;
/**
* @class input_method_t
* 输入法接口。
*
* @annotation ["scriptable"]
* 常见的实现方式有以下几种:
*
* * 空实现。用于不需要输入法的嵌入式平台。
*
* * 缺省实现。用于需要输入法的嵌入式平台。
*
* * 基于SDL实现的平台原生输入法。用于桌面系统和手机系统。
*
* ```graphviz
* [default_style]
*
* input_method_default_t -> input_method_t [arrowhead=empty style=dashed]
* input_method_sdl_t -> input_method_t [arrowhead=empty style=dashed]
* input_method_null_t -> input_method_t [arrowhead=empty style=dashed]
*
* ```
*
* > 输入类型请参考:[input\_type](input_type_t.md)
*
*/
struct _input_method_t {
/**
* @property {bool_t} is_native
* @annotation ["readable"]
* 是否是原生输入法。
*/
bool_t is_native;
/**
* @property {widget_t*} widget
* @annotation ["private"]
* 当前的焦点控件。
*/
widget_t* widget;
/**
* @property {widget_t*} keyboard
* @annotation ["private"]
* 当前的软件键盘。
*/
widget_t* keyboard;
/**
* @property {widget_t*} win
* @annotation ["private"]
* 当前的窗口。
*/
widget_t* win;
/**
* @property {int32_t} win_delta_y
* @annotation ["private"]
* 由于软键盘的弹出可能会将窗口向上推移win_delta_y为推移的距离。
*/
int32_t win_delta_y;
/**
* @property {int32_t} win_old_y
* @annotation ["private"]
* 窗口原来的位置。
*/
int32_t win_old_y;
/**
* @property {bool_t} action_button_enable
* @annotation ["readable"]
* 软键盘的上的action按钮是否可用。
*/
bool_t action_button_enable;
/**
* @property {bool_t} action_button_enable
* @annotation ["readable"]
* 软键盘的上的action按钮文本。
*/
char action_buton_text[TK_NAME_LEN + 1];
/**
* @property {emitter_t} emitter
* @annotation ["private"]
* emitter。用于实现dispatch/on/off等功能。
*/
emitter_t emitter;
/**
* @property {char*} keyboard_name
* @annotation ["readable"]
* 软键盘资源名称。
*/
char keyboard_name[TK_NAME_LEN + 1];
input_engine_t* engine;
suggest_words_t* suggest_words;
/**
* 子类需要实现的函数。
*/
input_method_request_t request;
input_method_destroy_t destroy;
/*private*/
bool_t busy;
void* data;
uint32_t idle_close_id;
};
/**
* @method input_method_dispatch
* 分发一个事件。
* @param {input_method_t*} im 控件对象。
* @param {event_t*} e 事件。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_dispatch(input_method_t* im, event_t* e);
/**
* @method input_method_dispatch_to_widget
* 分发一个事件当前焦点控件。
* @param {input_method_t*} im 控件对象。
* @param {event_t*} e 事件。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_dispatch_to_widget(input_method_t* im, event_t* e);
/**
* @method input_method_on
* 注册指定事件的处理函数。
* @param {input_method_t*} im 输入法对象。
* @param {event_type_t} type 事件类型。
* @param {event_func_t} on_event 事件处理函数。
* @param {void*} ctx 事件处理函数上下文。
*
* @return {uint32_t} 返回id用于input_method_off。
*/
uint32_t input_method_on(input_method_t* im, event_type_t type, event_func_t on_event, void* ctx);
/**
* @method input_method_off
* 注销指定事件的处理函数。
* @param {input_method_t*} im 输入法对象。
* @param {uint32_t} id input_method_on返回的ID。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_off(input_method_t* im, uint32_t id);
/**
* @method input_method_request
* 打开或关闭输入法。
* @param {input_method_t*} im 输入法对象。
* @param {widget_t*} widget 焦点控件为NULL时关闭输入法非NULL时打开输入法。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_request(input_method_t* im, widget_t* widget);
/**
* @method input_method_update_action_button_info
* 设置软键盘上的action按钮的信息。
* @param {input_method_t*} im 输入法对象。
* @param {char*} text 按钮的文本。
* @param {bool_t} enable 按钮的是否可用。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_update_action_button_info(input_method_t* im, const char* text, bool_t enable);
/**
* @method input_method_dispatch_action
* 软键盘上的action按钮被点击时调用本函数分发EVT_IM_ACTION事件。
* @param {input_method_t*} im 输入法对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_dispatch_action(input_method_t* im);
/**
* @method input_method_commit_text
* 提交输入文本。
* @annotation ["scriptable"]
* @param {input_method_t*} im 输入法对象。
* @param {const char*} text 文本。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_commit_text(input_method_t* im, const char* text);
/**
* @method input_method_set_lang
* 设置语言。
*
* > 有时在同一种语言环境下,也需要输入多种文字,典型的情况是同时输入中文和英文。
* > 比如T9输入法可以同时支持中文和英文输入配合软键盘随时切换输入的语言。
* > 数字、小写字母、大写字母和符合也可以视为输入的语言。
* > 主要用于提示输入法引擎选择适当的输入方法。
*
* @annotation ["scriptable"]
* @param {input_method_t*} im 输入法对象。
* @param {const char*} lang 语言。格式为语言+国家/地区码。如zh_cn和en_us等。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_set_lang(input_method_t* im, const char* lang);
/**
* @method input_method_get_lang
* 获取语言。
*
* @annotation ["scriptable"]
* @param {input_method_t*} im 输入法对象。
*
* @return {const char*} 返回语言。
*/
const char* input_method_get_lang(input_method_t* im);
/**
* @method input_method_commit_text_ex
* 提交输入文本。
* @param {input_method_t*} im 输入法对象。
* @param {bool_t} replace 是否替换原来的文本。
* @param {const char*} text 文本。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_commit_text_ex(input_method_t* im, bool_t replace, const char* text);
/**
* @method input_method_dispatch_key
* 提交按键。
* @annotation ["scriptable"]
* @param {input_method_t*} im 输入法对象。
* @param {uint32_t} key 键值。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_dispatch_key(input_method_t* im, uint32_t key);
/**
* @method input_method_dispatch_keys
* 提交按键。
* @annotation ["scriptable"]
* @param {input_method_t*} im 输入法对象。
* @param {const char*} key 键值。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_dispatch_keys(input_method_t* im, const char* keys);
/**
* @method input_method_dispatch_preedit
* 分发进入预编辑状态的事件。
* @annotation ["scriptable"]
* @param {input_method_t*} im 输入法对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_dispatch_preedit(input_method_t* im);
/**
* @method input_method_dispatch_preedit_confirm
* 分发确认预编辑状态的事件(提交预编辑内容,退出预编辑状态)。
* @annotation ["scriptable"]
* @param {input_method_t*} im 输入法对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_dispatch_preedit_confirm(input_method_t* im);
/**
* @method input_method_dispatch_preedit_abort
* 分发取消预编辑状态的事件(提交预编辑内容,退出预编辑状态)。
* @annotation ["scriptable"]
* @param {input_method_t*} im 输入法对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_dispatch_preedit_abort(input_method_t* im);
/**
* @method input_method_dispatch_candidates
* 请求显示候选字。
* @param {input_method_t*} im 输入法对象。
* @param {char*} strs 候选字列表。
* @param {uint32_t} nr 候选字个数。
* @param {int32_t} selected 缺省选中候选字的序数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_dispatch_candidates(input_method_t* im, const char* strs, uint32_t nr,
int32_t selected);
/**
* @method input_method_dispatch_pre_candidates
* 请求显示预候选字。
*
* > 预候选字: 在有的输入法中比如T9硬键盘输入时按下12两个键时预候选字会显示可用的拼音列表。
* > 从预候选字列表中选择拼音,再查询拼音对应的候选字列表。
*
* @param {input_method_t*} im 输入法对象。
* @param {char*} strs 候选字列表。
* @param {uint32_t} nr 候选字个数。
* @param {int32_t} selected 缺省选中候选字的序数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_dispatch_pre_candidates(input_method_t* im, const char* strs, uint32_t nr,
int32_t selected);
/**
* @method input_method_create
* 创建输入法对象。在具体实现中实现。
*
* @return {input_method_t*} 成功返回输入法对象失败返回NULL。
*/
input_method_t* input_method_create(void);
/**
* @method input_method_is_native
* 是否是平台原生输入法。
*
* @param {input_method_t*} im 输入法对象。
*
* @return {bool_t} 返回TRUE表示是原生输入法否则表示不是。
*/
bool_t input_method_is_native(input_method_t* im);
/**
* @method input_method_destroy
* 销毁输入法对象。在具体实现中实现。
* @param {input_method_t*} im 输入法对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_destroy(input_method_t* im);
/**
* @method input_method
* 获取全局输入法对象。
* @alias input_method_instance
* @annotation ["constructor", "scriptable"]
*
* @return {input_method_t*} 成功返回输入法对象失败返回NULL。
*/
input_method_t* input_method(void);
/**
* @method input_method_set
* 设置全局输入法对象。
* @param {input_method_t*} im 输入法对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t input_method_set(input_method_t* im);
#define IM_LANG_DIGIT "123"
#define IM_LANG_LOWER "abc"
#define IM_LANG_UPPER "ABC"
#define IM_LANG_SYMBOL "sym"
#define IM_LANG_EN_US "en_us"
#define IM_LANG_ZH_CN "zh_cn"
#define IM_LANG_ZH_TW "zh_tw"
END_C_DECLS
#endif /*TK_INPUT_METHOD_H*/

View File

@ -0,0 +1,911 @@
/**
* File: keys.h
* Author: AWTK Develop Team
* Brief: key code constants
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-04-05 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_KEYS_H
#define TK_KEYS_H
#include "base/types_def.h"
#ifdef WITH_SDL
#include <SDL_keycode.h>
#endif
BEGIN_C_DECLS
/**
* @enum key_code_t
* @annotation ["scriptable"]
* @prefix TK_
* key code。
*/
typedef enum _key_code_t {
TK_KEY_UNKNOWN = 0,
/**
* @const TK_KEY_RETURN
* TK_KEY_RETURN
*/
TK_KEY_RETURN = '\r',
/**
* @const TK_KEY_ESCAPE
* TK_KEY_ESCAPE
*/
TK_KEY_ESCAPE = '\033',
/**
* @const TK_KEY_BACKSPACE
* TK_KEY_BACKSPACE
*/
TK_KEY_BACKSPACE = '\b',
/**
* @const TK_KEY_TAB
* TK_KEY_TAB
*/
TK_KEY_TAB = '\t',
/**
* @const TK_KEY_SPACE
* TK_KEY_SPACE
*/
TK_KEY_SPACE = ' ',
/**
* @const TK_KEY_EXCLAIM
* TK_KEY_EXCLAIM
*/
TK_KEY_EXCLAIM = '!',
/**
* @const TK_KEY_QUOTEDBL
* TK_KEY_QUOTEDBL
*/
TK_KEY_QUOTEDBL = '"',
/**
* @const TK_KEY_HASH
* TK_KEY_HASH
*/
TK_KEY_HASH = '#',
/**
* @const TK_KEY_PERCENT
* TK_KEY_PERCENT
*/
TK_KEY_PERCENT = '%',
/**
* @const TK_KEY_DOLLAR
* TK_KEY_DOLLAR
*/
TK_KEY_DOLLAR = '$',
/**
* @const TK_KEY_AMPERSAND
* TK_KEY_AMPERSAND
*/
TK_KEY_AMPERSAND = '&',
/**
* @const TK_KEY_QUOTE
* TK_KEY_QUOTE
*/
TK_KEY_QUOTE = '\'',
/**
* @const TK_KEY_LEFTPAREN
* TK_KEY_LEFTPAREN
*/
TK_KEY_LEFTPAREN = '(',
/**
* @const TK_KEY_RIGHTPAREN
* TK_KEY_RIGHTPAREN
*/
TK_KEY_RIGHTPAREN = ')',
/**
* @const TK_KEY_ASTERISK
* TK_KEY_ASTERISK
*/
TK_KEY_ASTERISK = '*',
/**
* @const TK_KEY_PLUS
* TK_KEY_PLUS
*/
TK_KEY_PLUS = '+',
/**
* @const TK_KEY_COMMA
* TK_KEY_COMMA
*/
TK_KEY_COMMA = ',',
/**
* @const TK_KEY_MINUS
* TK_KEY_MINUS
*/
TK_KEY_MINUS = '-',
/**
* @const TK_KEY_PERIOD
* TK_KEY_PERIOD
*/
TK_KEY_PERIOD = '.',
/**
* @const TK_KEY_SLASH
* TK_KEY_SLASH
*/
TK_KEY_SLASH = '/',
/**
* @const TK_KEY_0
* TK_KEY_0
*/
TK_KEY_0 = '0',
/**
* @const TK_KEY_1
* TK_KEY_1
*/
TK_KEY_1 = '1',
/**
* @const TK_KEY_2
* TK_KEY_2
*/
TK_KEY_2 = '2',
/**
* @const TK_KEY_3
* TK_KEY_3
*/
TK_KEY_3 = '3',
/**
* @const TK_KEY_4
* TK_KEY_4
*/
TK_KEY_4 = '4',
/**
* @const TK_KEY_5
* TK_KEY_5
*/
TK_KEY_5 = '5',
/**
* @const TK_KEY_6
* TK_KEY_6
*/
TK_KEY_6 = '6',
/**
* @const TK_KEY_7
* TK_KEY_7
*/
TK_KEY_7 = '7',
/**
* @const TK_KEY_8
* TK_KEY_8
*/
TK_KEY_8 = '8',
/**
* @const TK_KEY_9
* TK_KEY_9
*/
TK_KEY_9 = '9',
/**
* @const TK_KEY_COLON
* TK_KEY_COLON
*/
TK_KEY_COLON = ':',
/**
* @const TK_KEY_SEMICOLON
* TK_KEY_SEMICOLON
*/
TK_KEY_SEMICOLON = ';',
/**
* @const TK_KEY_LESS
* TK_KEY_LESS
*/
TK_KEY_LESS = '<',
/**
* @const TK_KEY_EQUAL
* TK_KEY_EQUAL
*/
TK_KEY_EQUAL = '=',
/**
* @const TK_KEY_GREATER
* TK_KEY_GREATER
*/
TK_KEY_GREATER = '>',
/**
* @const TK_KEY_QUESTION
* TK_KEY_QUESTION
*/
TK_KEY_QUESTION = '?',
/**
* @const TK_KEY_AT
* TK_KEY_AT
*/
TK_KEY_AT = '@',
/**
* @const TK_KEY_LEFTBRACKET
* TK_KEY_LEFTBRACKET
*/
TK_KEY_LEFTBRACKET = '[',
/**
* @const TK_KEY_BACKSLASH
* TK_KEY_BACKSLASH
*/
TK_KEY_BACKSLASH = '\\',
/**
* @const TK_KEY_RIGHTBRACKET
* TK_KEY_RIGHTBRACKET
*/
TK_KEY_RIGHTBRACKET = ']',
/**
* @const TK_KEY_CARET
* TK_KEY_CARET
*/
TK_KEY_CARET = '^',
/**
* @const TK_KEY_UNDERSCORE
* TK_KEY_UNDERSCORE
*/
TK_KEY_UNDERSCORE = '_',
/**
* @const TK_KEY_BACKQUOTE
* TK_KEY_BACKQUOTE
*/
TK_KEY_BACKQUOTE = '`',
/**
* @const TK_KEY_a
* TK_KEY_a
*/
TK_KEY_a = 'a',
/**
* @const TK_KEY_b
* TK_KEY_b
*/
TK_KEY_b = 'b',
/**
* @const TK_KEY_c
* TK_KEY_c
*/
TK_KEY_c = 'c',
/**
* @const TK_KEY_d
* TK_KEY_d
*/
TK_KEY_d = 'd',
/**
* @const TK_KEY_e
* TK_KEY_e
*/
TK_KEY_e = 'e',
/**
* @const TK_KEY_f
* TK_KEY_f
*/
TK_KEY_f = 'f',
/**
* @const TK_KEY_g
* TK_KEY_g
*/
TK_KEY_g = 'g',
/**
* @const TK_KEY_h
* TK_KEY_h
*/
TK_KEY_h = 'h',
/**
* @const TK_KEY_i
* TK_KEY_i
*/
TK_KEY_i = 'i',
/**
* @const TK_KEY_j
* TK_KEY_j
*/
TK_KEY_j = 'j',
/**
* @const TK_KEY_k
* TK_KEY_k
*/
TK_KEY_k = 'k',
/**
* @const TK_KEY_l
* TK_KEY_l
*/
TK_KEY_l = 'l',
/**
* @const TK_KEY_m
* TK_KEY_m
*/
TK_KEY_m = 'm',
/**
* @const TK_KEY_n
* TK_KEY_n
*/
TK_KEY_n = 'n',
/**
* @const TK_KEY_o
* TK_KEY_o
*/
TK_KEY_o = 'o',
/**
* @const TK_KEY_p
* TK_KEY_p
*/
TK_KEY_p = 'p',
/**
* @const TK_KEY_q
* TK_KEY_q
*/
TK_KEY_q = 'q',
/**
* @const TK_KEY_r
* TK_KEY_r
*/
TK_KEY_r = 'r',
/**
* @const TK_KEY_s
* TK_KEY_s
*/
TK_KEY_s = 's',
/**
* @const TK_KEY_t
* TK_KEY_t
*/
TK_KEY_t = 't',
/**
* @const TK_KEY_u
* TK_KEY_u
*/
TK_KEY_u = 'u',
/**
* @const TK_KEY_v
* TK_KEY_v
*/
TK_KEY_v = 'v',
/**
* @const TK_KEY_w
* TK_KEY_w
*/
TK_KEY_w = 'w',
/**
* @const TK_KEY_x
* TK_KEY_x
*/
TK_KEY_x = 'x',
/**
* @const TK_KEY_y
* TK_KEY_y
*/
TK_KEY_y = 'y',
/**
* @const TK_KEY_z
* TK_KEY_z
*/
TK_KEY_z = 'z',
/**
* @const TK_KEY_A
* TK_KEY_A
*/
TK_KEY_A = 'A',
/**
* @const TK_KEY_B
* TK_KEY_B
*/
TK_KEY_B = 'B',
/**
* @const TK_KEY_C
* TK_KEY_C
*/
TK_KEY_C = 'C',
/**
* @const TK_KEY_D
* TK_KEY_D
*/
TK_KEY_D = 'D',
/**
* @const TK_KEY_E
* TK_KEY_E
*/
TK_KEY_E = 'E',
/**
* @const TK_KEY_F
* TK_KEY_F
*/
TK_KEY_F = 'F',
/**
* @const TK_KEY_G
* TK_KEY_G
*/
TK_KEY_G = 'G',
/**
* @const TK_KEY_H
* TK_KEY_H
*/
TK_KEY_H = 'H',
/**
* @const TK_KEY_I
* TK_KEY_I
*/
TK_KEY_I = 'I',
/**
* @const TK_KEY_J
* TK_KEY_J
*/
TK_KEY_J = 'J',
/**
* @const TK_KEY_K
* TK_KEY_K
*/
TK_KEY_K = 'K',
/**
* @const TK_KEY_L
* TK_KEY_L
*/
TK_KEY_L = 'L',
/**
* @const TK_KEY_M
* TK_KEY_M
*/
TK_KEY_M = 'M',
/**
* @const TK_KEY_N
* TK_KEY_N
*/
TK_KEY_N = 'N',
/**
* @const TK_KEY_O
* TK_KEY_O
*/
TK_KEY_O = 'O',
/**
* @const TK_KEY_P
* TK_KEY_P
*/
TK_KEY_P = 'P',
/**
* @const TK_KEY_Q
* TK_KEY_Q
*/
TK_KEY_Q = 'Q',
/**
* @const TK_KEY_R
* TK_KEY_R
*/
TK_KEY_R = 'R',
/**
* @const TK_KEY_S
* TK_KEY_S
*/
TK_KEY_S = 'S',
/**
* @const TK_KEY_T
* TK_KEY_T
*/
TK_KEY_T = 'T',
/**
* @const TK_KEY_U
* TK_KEY_U
*/
TK_KEY_U = 'U',
/**
* @const TK_KEY_V
* TK_KEY_V
*/
TK_KEY_V = 'V',
/**
* @const TK_KEY_W
* TK_KEY_W
*/
TK_KEY_W = 'W',
/**
* @const TK_KEY_X
* TK_KEY_X
*/
TK_KEY_X = 'X',
/**
* @const TK_KEY_Y
* TK_KEY_Y
*/
TK_KEY_Y = 'Y',
/**
* @const TK_KEY_Z
* TK_KEY_Z
*/
TK_KEY_Z = 'Z',
/**
* @const TK_KEY_DOT
* TK_KEY_DOT
*/
TK_KEY_DOT = '.',
/**
* @const TK_KEY_DELETE
* TK_KEY_DELETE
*/
TK_KEY_DELETE = '\177',
/**
* @const TK_KEY_LEFTBRACE
* TK_KEY_LEFTBRACE
*/
TK_KEY_LEFTBRACE = '(',
/**
* @const TK_KEY_RIGHTBRACE
* TK_KEY_RIGHTBRACE
*/
TK_KEY_RIGHTBRACE = ')',
#ifdef WITH_SDL
TK_KEY_CAPSLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CAPSLOCK),
TK_KEY_F1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F1),
TK_KEY_F2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F2),
TK_KEY_F3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F3),
TK_KEY_F4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F4),
TK_KEY_F5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F5),
TK_KEY_F6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F6),
TK_KEY_F7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F7),
TK_KEY_F8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F8),
TK_KEY_F9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F9),
TK_KEY_F10 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F10),
TK_KEY_F11 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F11),
TK_KEY_F12 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F12),
TK_KEY_PRINTSCREEN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRINTSCREEN),
TK_KEY_SCROLLLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SCROLLLOCK),
TK_KEY_PAUSE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAUSE),
TK_KEY_INSERT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_INSERT),
TK_KEY_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HOME),
TK_KEY_PAGEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEUP),
TK_KEY_END = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_END),
TK_KEY_PAGEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEDOWN),
TK_KEY_RIGHT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RIGHT),
TK_KEY_LEFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LEFT),
TK_KEY_DOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DOWN),
TK_KEY_UP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UP),
TK_KEY_NUMLOCKCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_NUMLOCKCLEAR),
TK_KEY_KP_DIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DIVIDE),
TK_KEY_KP_MULTIPLY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MULTIPLY),
TK_KEY_KP_MINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MINUS),
TK_KEY_KP_PLUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUS),
TK_KEY_KP_ENTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_ENTER),
TK_KEY_KP_1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_1),
TK_KEY_KP_2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_2),
TK_KEY_KP_3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_3),
TK_KEY_KP_4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_4),
TK_KEY_KP_5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_5),
TK_KEY_KP_6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_6),
TK_KEY_KP_7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_7),
TK_KEY_KP_8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_8),
TK_KEY_KP_9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_9),
TK_KEY_KP_0 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_0),
TK_KEY_KP_PERIOD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERIOD),
TK_KEY_APPLICATION = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APPLICATION),
TK_KEY_POWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_POWER),
TK_KEY_KP_EQUALS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALS),
TK_KEY_F13 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F13),
TK_KEY_F14 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F14),
TK_KEY_F15 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F15),
TK_KEY_F16 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F16),
TK_KEY_F17 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F17),
TK_KEY_F18 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F18),
TK_KEY_F19 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F19),
TK_KEY_F20 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F20),
TK_KEY_F21 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F21),
TK_KEY_F22 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F22),
TK_KEY_F23 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F23),
TK_KEY_F24 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F24),
TK_KEY_EXECUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXECUTE),
TK_KEY_HELP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HELP),
TK_KEY_MENU = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MENU),
TK_KEY_SELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SELECT),
TK_KEY_STOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_STOP),
TK_KEY_AGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AGAIN),
TK_KEY_UNDO = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UNDO),
TK_KEY_CUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CUT),
TK_KEY_COPY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COPY),
TK_KEY_PASTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PASTE),
TK_KEY_FIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_FIND),
TK_KEY_MUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MUTE),
TK_KEY_VOLUMEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEUP),
TK_KEY_VOLUMEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEDOWN),
TK_KEY_KP_COMMA = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COMMA),
TK_KEY_KP_EQUALSAS400 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALSAS400),
TK_KEY_ALTERASE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_ALTERASE),
TK_KEY_SYSREQ = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SYSREQ),
TK_KEY_CANCEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CANCEL),
TK_KEY_CLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEAR),
TK_KEY_PRIOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRIOR),
TK_KEY_RETURN2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RETURN2),
TK_KEY_SEPARATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SEPARATOR),
TK_KEY_OUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OUT),
TK_KEY_OPER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OPER),
TK_KEY_CLEARAGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEARAGAIN),
TK_KEY_CRSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CRSEL),
TK_KEY_EXSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXSEL),
TK_KEY_KP_00 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_00),
TK_KEY_KP_000 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_000),
TK_KEY_THOUSANDSSEPARATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_THOUSANDSSEPARATOR),
TK_KEY_DECIMALSEPARATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DECIMALSEPARATOR),
TK_KEY_CURRENCYUNIT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYUNIT),
TK_KEY_CURRENCYSUBUNIT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYSUBUNIT),
TK_KEY_KP_LEFTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTPAREN),
TK_KEY_KP_RIGHTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTPAREN),
TK_KEY_KP_LEFTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTBRACE),
TK_KEY_KP_RIGHTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTBRACE),
TK_KEY_KP_TAB = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_TAB),
TK_KEY_KP_BACKSPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BACKSPACE),
TK_KEY_KP_A = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_A),
TK_KEY_KP_B = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_B),
TK_KEY_KP_C = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_C),
TK_KEY_KP_D = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_D),
TK_KEY_KP_E = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_E),
TK_KEY_KP_F = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_F),
TK_KEY_KP_XOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_XOR),
TK_KEY_KP_POWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_POWER),
TK_KEY_KP_PERCENT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERCENT),
TK_KEY_KP_LESS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LESS),
TK_KEY_KP_GREATER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_GREATER),
TK_KEY_KP_AMPERSAND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AMPERSAND),
TK_KEY_KP_DBLAMPERSAND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLAMPERSAND),
TK_KEY_KP_VERTICALBAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_VERTICALBAR),
TK_KEY_KP_DBLVERTICALBAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLVERTICALBAR),
TK_KEY_KP_COLON = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COLON),
TK_KEY_KP_HASH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HASH),
TK_KEY_KP_SPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_SPACE),
TK_KEY_KP_AT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AT),
TK_KEY_KP_EXCLAM = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EXCLAM),
TK_KEY_KP_MEMSTORE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSTORE),
TK_KEY_KP_MEMRECALL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMRECALL),
TK_KEY_KP_MEMCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMCLEAR),
TK_KEY_KP_MEMADD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMADD),
TK_KEY_KP_MEMSUBTRACT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSUBTRACT),
TK_KEY_KP_MEMMULTIPLY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMMULTIPLY),
TK_KEY_KP_MEMDIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMDIVIDE),
TK_KEY_KP_PLUSMINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUSMINUS),
TK_KEY_KP_CLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEAR),
TK_KEY_KP_CLEARENTRY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEARENTRY),
TK_KEY_KP_BINARY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BINARY),
TK_KEY_KP_OCTAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_OCTAL),
TK_KEY_KP_DECIMAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DECIMAL),
TK_KEY_KP_HEXADECIMAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HEXADECIMAL),
TK_KEY_LCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LCTRL),
TK_KEY_LSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LSHIFT),
TK_KEY_LALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LALT),
TK_KEY_LGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LGUI),
TK_KEY_RCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RCTRL),
TK_KEY_RSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RSHIFT),
TK_KEY_RALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RALT),
TK_KEY_RGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RGUI),
TK_KEY_MODE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MODE),
TK_KEY_AUDIONEXT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIONEXT),
TK_KEY_AUDIOPREV = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPREV),
TK_KEY_AUDIOSTOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOSTOP),
TK_KEY_AUDIOPLAY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPLAY),
TK_KEY_AUDIOMUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOMUTE),
TK_KEY_MEDIASELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIASELECT),
TK_KEY_WWW = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_WWW),
TK_KEY_MAIL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MAIL),
TK_KEY_CALCULATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CALCULATOR),
TK_KEY_COMPUTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COMPUTER),
TK_KEY_AC_SEARCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_SEARCH),
TK_KEY_AC_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_HOME),
TK_KEY_AC_BACK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BACK),
TK_KEY_AC_FORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_FORWARD),
TK_KEY_AC_STOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_STOP),
TK_KEY_AC_REFRESH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_REFRESH),
TK_KEY_AC_BOOKMARKS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BOOKMARKS),
TK_KEY_BRIGHTNESSDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSDOWN),
TK_KEY_BRIGHTNESSUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSUP),
TK_KEY_DISPLAYSWITCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DISPLAYSWITCH),
TK_KEY_KBDILLUMTOGGLE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMTOGGLE),
TK_KEY_KBDILLUMDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMDOWN),
TK_KEY_KBDILLUMUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMUP),
TK_KEY_EJECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EJECT),
TK_KEY_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP),
TK_KEY_APP1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APP1),
TK_KEY_APP2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APP2),
TK_KEY_COMMAND = TK_KEY_LGUI,
TK_KEY_LCOMMAND = TK_KEY_LGUI,
TK_KEY_RCOMMAND = TK_KEY_RGUI,
TK_KEY_BACK = TK_KEY_AC_BACK,
#else
/**
* @const TK_KEY_LSHIFT
* TK_KEY_LSHIFT
*/
TK_KEY_LSHIFT = 0x20 + 127,
/**
* @const TK_KEY_RSHIFT
* TK_KEY_RSHIFT
*/
TK_KEY_RSHIFT = 0x20 + 128,
/**
* @const TK_KEY_LCTRL
* TK_KEY_LCTRL
*/
TK_KEY_LCTRL = 0x20 + 129,
/**
* @const TK_KEY_RCTRL
* TK_KEY_RCTRL
*/
TK_KEY_RCTRL = 0x20 + 130,
/**
* @const TK_KEY_LALT
* TK_KEY_LALT
*/
TK_KEY_LALT = 0x20 + 131,
/**
* @const TK_KEY_RALT
* TK_KEY_RALT
*/
TK_KEY_RALT = 0x20 + 132,
/**
* @const TK_KEY_CAPSLOCK
* TK_KEY_CAPSLOCK
*/
TK_KEY_CAPSLOCK = 0x20 + 133,
/**
* @const TK_KEY_HOME
* TK_KEY_HOME
*/
TK_KEY_HOME = 0x20 + 134,
/**
* @const TK_KEY_END
* TK_KEY_END
*/
TK_KEY_END = 0x20 + 135,
/**
* @const TK_KEY_INSERT
* TK_KEY_INSERT
*/
TK_KEY_INSERT = 0x20 + 137,
/**
* @const TK_KEY_UP
* TK_KEY_UP
*/
TK_KEY_UP = 0x20 + 138,
/**
* @const TK_KEY_DOWN
* TK_KEY_DOWN
*/
TK_KEY_DOWN = 0x20 + 139,
/**
* @const TK_KEY_LEFT
* TK_KEY_LEFT
*/
TK_KEY_LEFT = 0x20 + 140,
/**
* @const TK_KEY_RIGHT
* TK_KEY_RIGHT
*/
TK_KEY_RIGHT = 0x20 + 141,
/**
* @const TK_KEY_PAGEUP
* TK_KEY_PAGEUP
*/
TK_KEY_PAGEUP = 0x20 + 142,
/**
* @const TK_KEY_PAGEDOWN
* TK_KEY_PAGEDOWN
*/
TK_KEY_PAGEDOWN = 0x20 + 143,
/**
* @const TK_KEY_F1
* TK_KEY_F1
*/
TK_KEY_F1 = 0x20 + 151,
/**
* @const TK_KEY_F2
* TK_KEY_F2
*/
TK_KEY_F2 = 0x20 + 152,
/**
* @const TK_KEY_F3
* TK_KEY_F3
*/
TK_KEY_F3 = 0x20 + 153,
/**
* @const TK_KEY_F4
* TK_KEY_F4
*/
TK_KEY_F4 = 0x20 + 154,
/**
* @const TK_KEY_F5
* TK_KEY_F5
*/
TK_KEY_F5 = 0x20 + 155,
/**
* @const TK_KEY_F6
* TK_KEY_F6
*/
TK_KEY_F6 = 0x20 + 156,
/**
* @const TK_KEY_F7
* TK_KEY_F7
*/
TK_KEY_F7 = 0x20 + 157,
/**
* @const TK_KEY_F8
* TK_KEY_F8
*/
TK_KEY_F8 = 0x20 + 158,
/**
* @const TK_KEY_F9
* TK_KEY_F9
*/
TK_KEY_F9 = 0x20 + 159,
/**
* @const TK_KEY_F10
* TK_KEY_F10
*/
TK_KEY_F10 = 0x20 + 160,
/**
* @const TK_KEY_F11
* TK_KEY_F11
*/
TK_KEY_F11 = 0x20 + 161,
/**
* @const TK_KEY_F12
* TK_KEY_F12
*/
TK_KEY_F12 = 0x20 + 162,
/**
* @const TK_KEY_MENU
* TK_KEY_MENU
*/
TK_KEY_MENU = 0x20 + 163,
/**
* @const TK_KEY_COMMAND
* TK_KEY_COMMAND
*/
TK_KEY_COMMAND = 0x20 + 164,
TK_KEY_LCOMMAND = 0x20 + 164,
TK_KEY_RCOMMAND = 0x20 + 165,
/**
* @const TK_KEY_BACK
* TK_KEY_BACK
*/
TK_KEY_BACK = 0x20 + 166,
/**
* @const TK_KEY_CANCEL
* TK_KEY_CANCEL
*/
TK_KEY_CANCEL = 0x20 + 167,
#endif
/**
* @const TK_KEY_WHEEL
* TK_KEY_WHEEL
*/
TK_KEY_WHEEL = 0x20 + 168,
} key_code_t;
#ifndef TK_KEY_CLOSE_INPUT_METHOD
#define TK_KEY_CLOSE_INPUT_METHOD TK_KEY_F7
#endif /*TK_KEY_CLOSE_INPUT_METHOD*/
#ifndef TK_KEY_OPEN_INPUT_METHOD
#define TK_KEY_OPEN_INPUT_METHOD TK_KEY_F8
#endif /*TK_KEY_OPEN_INPUT_METHOD*/
#ifndef TK_KEY_TOGGLE_INPUT_METHOD
#define TK_KEY_TOGGLE_INPUT_METHOD TK_KEY_F9
#endif /*TK_KEY_TOGGLE_INPUT_METHOD*/
static inline bool_t key_code_is_enter(int key) {
#ifdef WITH_SDL
return (key == TK_KEY_RETURN || key == TK_KEY_KP_ENTER);
#else
return key == TK_KEY_RETURN;
#endif /*WITH_SDL*/
}
END_C_DECLS
#endif /*TK_KEYS_H*/

View File

@ -0,0 +1,220 @@
/**
* File: layout.c
* Author: AWTK Develop Team
* Brief: widget layout
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-12-16 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/utils.h"
#include "base/widget.h"
#include "base/layout.h"
#include "base/self_layouter_factory.h"
#include "base/children_layouter_factory.h"
ret_t widget_auto_adjust_size(widget_t* widget) {
int32_t w = 0;
int32_t h = 0;
int32_t right = 0;
int32_t bottom = 0;
int32_t margin = 0;
int32_t margin_right = 0;
int32_t margin_bottom = 0;
style_t* style = NULL;
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
style = widget->astyle;
if (style != NULL) {
margin = style_get_int(style, STYLE_ID_MARGIN, 2);
margin_right = style_get_int(style, STYLE_ID_MARGIN_RIGHT, margin);
margin_bottom = style_get_int(style, STYLE_ID_MARGIN_BOTTOM, margin);
}
WIDGET_FOR_EACH_CHILD_BEGIN(widget, iter, i)
right = iter->x + iter->w + margin_right;
bottom = iter->y + iter->h + margin_bottom;
if (right > w) {
w = right;
}
if (bottom > h) {
h = bottom;
}
WIDGET_FOR_EACH_CHILD_END();
if (w != 0 && h != 0) {
widget_resize(widget, w, h);
}
return RET_OK;
}
ret_t widget_layout(widget_t* widget) {
widget_layout_self(widget);
widget_layout_children(widget);
if (widget->auto_adjust_size) {
widget_auto_adjust_size(widget);
}
return RET_OK;
}
ret_t widget_layout_self(widget_t* widget) {
value_t v;
rect_t r = {0, 0, 0, 0};
widget_t* parent = NULL;
return_value_if_fail(widget != NULL && widget->parent != NULL, RET_BAD_PARAMS);
parent = widget->parent;
if (widget_get_prop(parent, WIDGET_PROP_LAYOUT_W, &v) == RET_OK) {
r.w = value_int(&v);
} else {
r.w = parent->w;
}
if (widget_get_prop(parent, WIDGET_PROP_LAYOUT_H, &v) == RET_OK) {
r.h = value_int(&v);
} else {
r.h = parent->h;
}
return self_layouter_layout(widget->self_layout, widget, &r);
}
ret_t widget_layout_children_default(widget_t* widget) {
if (widget->children_layout != NULL) {
return children_layouter_layout(widget->children_layout, widget);
} else {
WIDGET_FOR_EACH_CHILD_BEGIN(widget, iter, i)
widget_layout(iter);
WIDGET_FOR_EACH_CHILD_END()
return RET_OK;
}
}
ret_t widget_layout_children(widget_t* widget) {
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
if (widget->vt->on_layout_children != NULL) {
return widget->vt->on_layout_children(widget);
} else {
return widget_layout_children_default(widget);
}
}
ret_t widget_set_self_layout(widget_t* widget, const char* params) {
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
if (widget->self_layout != NULL) {
if (tk_str_eq(widget->self_layout->params.str, params)) {
return RET_OK;
}
self_layouter_destroy(widget->self_layout);
widget->self_layout = NULL;
}
if (params != NULL && params[0] != '\0') {
widget->self_layout = self_layouter_create(params);
}
if (widget->self_layout != NULL) {
str_set(&(widget->self_layout->params), params);
}
return widget_set_need_relayout(widget);
}
ret_t widget_set_children_layout(widget_t* widget, const char* params) {
return_value_if_fail(widget != NULL && params != NULL, RET_BAD_PARAMS);
if (widget->children_layout != NULL) {
if (tk_str_eq(widget->children_layout->params.str, params)) {
return RET_OK;
}
children_layouter_destroy(widget->children_layout);
}
widget->children_layout = children_layouter_create(params);
if (widget->children_layout != NULL) {
str_set(&(widget->children_layout->params), params);
}
return widget_set_need_relayout(widget);
}
ret_t widget_set_self_layout_params(widget_t* widget, const char* x, const char* y, const char* w,
const char* h) {
char params[128];
tk_snprintf(params, sizeof(params) - 1, "default(x=%s, y=%s, w=%s, h=%s)", x, y, w, h);
return widget_set_self_layout(widget, params);
}
ret_t widget_layout_floating_children(widget_t* widget) {
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
if (widget->children != NULL) {
uint32_t i = 0;
uint32_t n = widget->children->size;
widget_t** children = (widget_t**)(widget->children->elms);
for (i = 0; i < n; i++) {
widget_t* iter = children[i];
if (iter->floating) {
widget_layout(iter);
}
}
}
return RET_OK;
}
ret_t widget_get_children_for_layout(widget_t* widget, darray_t* result, bool_t keep_disable,
bool_t keep_invisible) {
return_value_if_fail(widget != NULL && result != NULL, RET_BAD_PARAMS);
result->size = 0;
if (widget->children != NULL) {
uint32_t i = 0;
uint32_t n = widget->children->size;
widget_t** children = (widget_t**)(widget->children->elms);
for (i = 0; i < n; i++) {
widget_t* iter = children[i];
if (iter->floating) {
continue;
}
if (!(iter->enable)) {
if (!keep_disable) {
continue;
}
}
if (!(iter->visible)) {
if (!keep_invisible) {
continue;
}
}
darray_push(result, iter);
}
}
return RET_OK;
}

View File

@ -0,0 +1,79 @@
/**
* File: layout.h
* Author: AWTK Develop Team
* Brief: widget layout
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-12-16 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_LAYOUT_H
#define TK_LAYOUT_H
#include "tkc/darray.h"
#include "base/types_def.h"
BEGIN_C_DECLS
/**
* @method widget_layout_self
* 调用widget的selflayout。
* @annotation ["global"]
* @param {widget_t*} widget 控件。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t widget_layout_self(widget_t* widget);
/**
* @method widget_layout_children_default
* 调用widget默认的childrenlayout。
* @annotation ["global"]
* @param {widget_t*} widget 控件。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t widget_layout_children_default(widget_t* widget);
/**
* @method widget_layout_floating_children
* 对floating属性的子控件进行layout。
* @annotation ["global"]
* @param {widget_t*} widget 控件。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t widget_layout_floating_children(widget_t* widget);
/**
* @method widget_get_children_for_layout
* 获取受childrenlayout控件的子控件队列。
* @annotation ["global"]
* @param {widget_t*} widget 控件。
* @param {darray_t*} result 返回队列。
* @param {bool_t} keep_disable 是否保留非enable状态的控件。
* @param {bool_t} keep_invisible 是否保留非visible状态的控件。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t widget_get_children_for_layout(widget_t* widget, darray_t* result, bool_t keep_disable,
bool_t keep_invisible);
/* private */
ret_t widget_auto_adjust_size(widget_t* widget);
END_C_DECLS
#endif /*TK_LAYOUT_H*/

View File

@ -0,0 +1,55 @@
/**
* File: layout_def.h
* Author: AWTK Develop Team
* Brief: layout type def
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-03-10 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_LAYOUT_DEF_H
#define TK_LAYOUT_DEF_H
#include "base/types_def.h"
BEGIN_C_DECLS
typedef enum _x_attr_t {
X_ATTR_DEFAULT = 0,
X_ATTR_PERCENT,
X_ATTR_CENTER,
X_ATTR_RIGHT,
X_ATTR_CENTER_PERCENT,
X_ATTR_RIGHT_PERCENT,
X_ATTR_UNDEF
} x_attr_t;
typedef enum _y_attr_t {
Y_ATTR_DEFAULT = 0,
Y_ATTR_PERCENT,
Y_ATTR_MIDDLE,
Y_ATTR_BOTTOM,
Y_ATTR_MIDDLE_PERCENT,
Y_ATTR_BOTTOM_PERCENT,
Y_ATTR_UNDEF
} y_attr_t;
typedef enum _w_attr_t { W_ATTR_PIXEL = 0, W_ATTR_PERCENT, W_ATTR_UNDEF } w_attr_t;
typedef enum _h_attr_t { H_ATTR_PIXEL = 0, H_ATTR_PERCENT, H_ATTR_UNDEF } h_attr_t;
END_C_DECLS
#endif /*TK_LAYOUT_DEF_H*/

View File

@ -0,0 +1,431 @@
/**
* File: lcd.c
* Author: AWTK Develop Team
* Brief: lcd interface
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/lcd.h"
#include "tkc/time_now.h"
#include "base/system_info.h"
#include "base/lcd_fb_dirty_rects.inc"
ret_t lcd_begin_frame(lcd_t* lcd, const dirty_rects_t* dirty_rects, lcd_draw_mode_t draw_mode) {
const rect_t* dirty_rect = dirty_rects != NULL ? &(dirty_rects->max) : NULL;
return_value_if_fail(lcd != NULL && lcd->begin_frame != NULL, RET_BAD_PARAMS);
lcd->draw_mode = draw_mode;
if (dirty_rect == NULL) {
lcd->dirty_rect.x = 0;
lcd->dirty_rect.y = 0;
lcd->dirty_rect.w = lcd->w;
lcd->dirty_rect.h = lcd->h;
} else {
lcd->dirty_rect = *dirty_rect;
rect_fix(&(lcd->dirty_rect), lcd->w, lcd->h);
}
lcd->dirty_rects = dirty_rects;
return lcd->begin_frame(lcd, dirty_rects);
}
ret_t lcd_set_canvas(lcd_t* lcd, canvas_t* c) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
if (lcd->set_canvas != NULL) {
lcd->set_canvas(lcd, c);
}
return RET_OK;
}
const dirty_rects_t* lcd_get_dirty_rects(lcd_t* lcd) {
return_value_if_fail(lcd != NULL, NULL);
if (lcd->get_dirty_rects != NULL) {
return lcd->get_dirty_rects(lcd);
}
return lcd->dirty_rects;
}
ret_t lcd_get_dirty_rect(lcd_t* lcd, rect_t* r) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
if (lcd->get_dirty_rect != NULL) {
return lcd->get_dirty_rect(lcd, r);
} else {
r->x = lcd->dirty_rect.x;
r->y = lcd->dirty_rect.y;
r->w = lcd->dirty_rect.w;
r->h = lcd->dirty_rect.h;
}
return RET_OK;
}
ret_t lcd_set_clip_rect(lcd_t* lcd, const rect_t* rect) {
return_value_if_fail(lcd != NULL && lcd->set_clip_rect != NULL, RET_BAD_PARAMS);
return lcd->set_clip_rect(lcd, rect);
}
#ifdef DIRTY_RECTS_CLIP_SUPPORT
ret_t lcd_set_clip_dirty_rects (lcd_t* lcd, const dirty_rects_t* rect) {
return_value_if_fail(lcd != NULL && lcd->set_clip_dirty_rects != NULL, RET_BAD_PARAMS);
return lcd->set_clip_dirty_rects(lcd, rect);
}
#endif
ret_t lcd_get_clip_rect(lcd_t* lcd, rect_t* rect) {
return_value_if_fail(lcd != NULL && lcd->get_clip_rect != NULL, RET_BAD_PARAMS);
return lcd->get_clip_rect(lcd, rect);
}
bool_t lcd_is_rect_in_clip_rect(lcd_t* lcd, xy_t left, xy_t top, xy_t right, xy_t bottom) {
return_value_if_fail(lcd != NULL && lcd->is_rect_in_clip_rect != NULL, RET_BAD_PARAMS);
return lcd->is_rect_in_clip_rect (lcd, left, top, right, bottom);
}
ret_t lcd_set_global_alpha(lcd_t* lcd, uint8_t alpha) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
lcd->global_alpha = alpha;
if (lcd->set_global_alpha != NULL) {
lcd->set_global_alpha(lcd, alpha);
}
return RET_OK;
}
ret_t lcd_set_text_color(lcd_t* lcd, color_t color) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
lcd->text_color = color;
if (lcd->set_text_color != NULL) {
lcd->set_text_color(lcd, color);
}
return RET_OK;
}
ret_t lcd_set_stroke_color(lcd_t* lcd, color_t color) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
lcd->stroke_color = color;
if (lcd->set_stroke_color != NULL) {
lcd->set_stroke_color(lcd, color);
}
return RET_OK;
}
ret_t lcd_set_fill_color(lcd_t* lcd, color_t color) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
lcd->fill_color = color;
if (lcd->set_fill_color != NULL) {
lcd->set_fill_color(lcd, color);
}
return RET_OK;
}
ret_t lcd_set_font_name(lcd_t* lcd, const char* name) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
lcd->font_name = tk_str_copy(lcd->font_name, name);
if (lcd->set_font_name != NULL) {
lcd->set_font_name(lcd, name);
}
return RET_OK;
}
ret_t lcd_set_font_size(lcd_t* lcd, uint32_t size) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
lcd->font_size = size;
if (lcd->set_font_size != NULL) {
lcd->set_font_size(lcd, size);
}
return RET_OK;
}
ret_t lcd_draw_vline(lcd_t* lcd, xy_t x, xy_t y, wh_t h) {
return_value_if_fail(lcd != NULL && lcd->draw_vline != NULL, RET_BAD_PARAMS);
if (h == 0) {
return RET_BAD_PARAMS;
}
return lcd->draw_vline(lcd, x, y, h);
}
ret_t lcd_draw_hline(lcd_t* lcd, xy_t x, xy_t y, wh_t w) {
return_value_if_fail(lcd != NULL && lcd->draw_hline != NULL, RET_BAD_PARAMS);
if (w == 0) {
return RET_BAD_PARAMS;
}
return lcd->draw_hline(lcd, x, y, w);
}
ret_t lcd_fill_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h) {
return_value_if_fail(lcd != NULL && lcd->fill_rect != NULL, RET_BAD_PARAMS);
if (w == 0 || h == 0) {
return RET_BAD_PARAMS;
}
return lcd->fill_rect(lcd, x, y, w, h);
}
ret_t lcd_clear_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h) {
return_value_if_fail(lcd != NULL && lcd->clear_rect != NULL, RET_BAD_PARAMS);
if (w == 0 || h == 0) {
return RET_BAD_PARAMS;
}
return lcd->clear_rect(lcd, x, y, w, h);
}
ret_t lcd_stroke_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h) {
return_value_if_fail(lcd != NULL && lcd->stroke_rect != NULL, RET_BAD_PARAMS);
if (w == 0 || h == 0) {
return RET_BAD_PARAMS;
}
return lcd->stroke_rect(lcd, x, y, w, h);
}
ret_t lcd_draw_points(lcd_t* lcd, point_t* points, uint32_t nr) {
return_value_if_fail(lcd != NULL && lcd->draw_points != NULL && points != NULL, RET_BAD_PARAMS);
return lcd->draw_points(lcd, points, nr);
}
color_t lcd_get_point_color(lcd_t* lcd, xy_t x, xy_t y) {
color_t c = color_init(0, 0, 0, 0);
return_value_if_fail(lcd != NULL && x >= 0 && y >= 0 && x < lcd->w && y < lcd->h, c);
if (lcd->get_point_color != NULL) {
return lcd->get_point_color(lcd, x, y);
} else {
return lcd->fill_color;
}
}
ret_t lcd_draw_image(lcd_t* lcd, bitmap_t* img, const rectf_t* src, const rectf_t* dst) {
return_value_if_fail(lcd != NULL && lcd->draw_image != NULL && src != NULL && dst != NULL,
RET_BAD_PARAMS);
return lcd->draw_image(lcd, img, src, dst);
}
#ifdef WITH_VG_GPU
#ifdef VG_DRAW_IMAGE_REPEAT
ret_t lcd_draw_image_repeat(lcd_t* lcd, bitmap_t* img, const rect_t* src, const rect_t* dst, wh_t dst_w, wh_t dst_h) {
return_value_if_fail(lcd != NULL && lcd->draw_image_repeat != NULL && src != NULL && dst != NULL,
RET_BAD_PARAMS);
return lcd->draw_image_repeat(lcd, img, src, dst, dst_w, dst_h);
}
#endif
#endif
ret_t lcd_draw_image_matrix(lcd_t* lcd, draw_image_info_t* info) {
return_value_if_fail(lcd != NULL && info != NULL, RET_BAD_PARAMS);
if (lcd->draw_image_matrix != NULL) {
return lcd->draw_image_matrix(lcd, info);
}
return RET_NOT_IMPL;
}
ret_t lcd_draw_glyph(lcd_t* lcd, glyph_t* glyph, const rect_t* src, xy_t x, xy_t y) {
return_value_if_fail(lcd != NULL && lcd->draw_glyph != NULL && glyph != NULL && src != NULL,
RET_BAD_PARAMS);
return lcd->draw_glyph(lcd, glyph, src, x, y);
}
float_t lcd_measure_text(lcd_t* lcd, const wchar_t* str, uint32_t nr) {
return_value_if_fail(nr < 10240, 0.0f);
return_value_if_fail(lcd != NULL && lcd->measure_text != NULL && str != NULL, 0.0f);
return lcd->measure_text(lcd, str, nr);
}
ret_t lcd_draw_text(lcd_t* lcd, const wchar_t* str, uint32_t nr, xy_t x, xy_t y) {
return_value_if_fail(nr < 10240, RET_BAD_PARAMS);
return_value_if_fail(lcd != NULL && lcd->draw_text != NULL && str != NULL, RET_OK);
return lcd->draw_text(lcd, str, nr, x, y);
}
ret_t lcd_end_frame(lcd_t* lcd) {
return_value_if_fail(lcd != NULL && lcd->end_frame != NULL, RET_BAD_PARAMS);
return_value_if_fail(lcd->end_frame(lcd) == RET_OK, RET_FAIL);
lcd->last_update_time = time_now_ms();
return RET_OK;
}
ret_t lcd_swap(lcd_t* lcd) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
if (lcd->swap != NULL) {
return lcd->swap(lcd);
}
return RET_OK;
}
ret_t lcd_flush(lcd_t* lcd) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
if (lcd->flush != NULL) {
return lcd->flush(lcd);
}
return RET_OK;
}
ret_t lcd_sync(lcd_t* lcd) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
if (lcd->sync != NULL) {
return lcd->sync(lcd);
}
return RET_OK;
}
bool_t lcd_is_swappable(lcd_t* lcd) {
return_value_if_fail(lcd != NULL, FALSE);
if (lcd->swap != NULL) {
return system_info()->lcd_orientation == LCD_ORIENTATION_0;
}
return FALSE;
}
ret_t lcd_destroy(lcd_t* lcd) {
return_value_if_fail(lcd != NULL && lcd->destroy != NULL, RET_BAD_PARAMS);
TKMEM_FREE(lcd->font_name);
return lcd->destroy(lcd);
}
vgcanvas_t* lcd_get_vgcanvas(lcd_t* lcd) {
return_value_if_fail(lcd != NULL, NULL);
if (lcd->get_vgcanvas != NULL) {
return lcd->get_vgcanvas(lcd);
}
return NULL;
}
bitmap_format_t lcd_get_desired_bitmap_format(lcd_t* lcd) {
return_value_if_fail(lcd != NULL && lcd->get_desired_bitmap_format != NULL, BITMAP_FMT_BGR565);
return lcd->get_desired_bitmap_format(lcd);
}
ret_t lcd_resize(lcd_t* lcd, wh_t w, wh_t h, uint32_t line_length) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
if (lcd->resize != NULL) {
if (lcd->resize(lcd, w, h, line_length) == RET_OK) {
lcd->w = w;
lcd->h = h;
return RET_OK;
}
}
return RET_FAIL;
}
ret_t lcd_set_orientation(lcd_t* lcd, lcd_orientation_t old_orientation,
lcd_orientation_t new_orientation) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
if (lcd->set_orientation != NULL) {
return lcd->set_orientation(lcd, old_orientation, new_orientation);
}
return RET_FAIL;
}
wh_t lcd_get_width(lcd_t* lcd) {
return_value_if_fail(lcd != NULL, 0);
if (lcd->get_width != NULL) {
return lcd->get_width(lcd);
} else {
return lcd->w;
}
}
wh_t lcd_get_height(lcd_t* lcd) {
return_value_if_fail(lcd != NULL, 0);
if (lcd->get_height != NULL) {
return lcd->get_height(lcd);
} else {
return lcd->h;
}
}
ret_t lcd_get_text_metrics(lcd_t* lcd, float_t* ascent, float_t* descent, float_t* line_hight) {
return_value_if_fail(lcd != NULL && lcd->get_text_metrics != NULL, RET_BAD_PARAMS);
return lcd->get_text_metrics(lcd, ascent, descent, line_hight);
}
lcd_type_t lcd_get_type(lcd_t* lcd) {
return_value_if_fail(lcd != NULL, LCD_FRAMEBUFFER);
if (lcd->get_type != NULL) {
return (lcd_type_t)lcd->get_type(lcd);
}
return lcd->type;
}
ret_t lcd_set_vgcanvas(lcd_t* lcd, vgcanvas_t* vgcanvas) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
if (lcd->set_vgcanvas != NULL) {
return lcd->set_vgcanvas(lcd, vgcanvas);
}
return RET_FAIL;
}
ret_t lcd_set_line_length(lcd_t* lcd, uint32_t line_length) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
if (lcd->set_line_length != NULL) {
return lcd->set_line_length(lcd, line_length);
}
return RET_FAIL;
}
bool_t lcd_is_support_dirty_rect(lcd_t* lcd) {
return_value_if_fail(lcd != NULL, FALSE);
if (lcd->is_support_dirty_rect != NULL) {
return lcd->is_support_dirty_rect(lcd);
}
return lcd->support_dirty_rect;
}

View File

@ -0,0 +1,758 @@
/**
* File: lcd.h
* Author: AWTK Develop Team
* Brief: lcd interface
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-13 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_LCD_H
#define TK_LCD_H
#include "tkc/rect.h"
#include "base/font.h"
#include "tkc/matrix.h"
#include "base/bitmap.h"
#include "base/dirty_rects.h"
#include "base/vgcanvas.h"
#include "base/lcd_fb_dirty_rects.h"
BEGIN_C_DECLS
typedef struct _draw_image_info_t {
bitmap_t* img;
rect_t src;
rect_t dst;
rect_t clip;
matrix_t matrix;
} draw_image_info_t;
typedef int32_t (*lcd_get_type_t)(lcd_t* lcd);
typedef bool_t (*lcd_is_support_dirty_rect_t)(lcd_t* lcd);
typedef ret_t (*lcd_set_vgcanvas_t)(lcd_t* lcd, vgcanvas_t* vg);
typedef ret_t (*lcd_set_line_length_t)(lcd_t* lcd, uint32_t line_length);
typedef ret_t (*lcd_set_canvas_t)(lcd_t* lcd, canvas_t* c);
typedef ret_t (*lcd_get_dirty_rect_t)(lcd_t* lcd, rect_t* r);
typedef const dirty_rects_t* (*lcd_get_dirty_rects_t)(lcd_t* lcd);
typedef ret_t (*lcd_begin_frame_t)(lcd_t* lcd, const dirty_rects_t* dirty_rects);
typedef bool_t(*lcd_is_rect_in_clip_rect_t)(lcd_t* lcd, xy_t left, xy_t top, xy_t right, xy_t bottom);
typedef ret_t (*lcd_set_clip_rect_t)(lcd_t* lcd, const rect_t* rect);
typedef ret_t (*lcd_get_clip_rect_t)(lcd_t* lcd, rect_t* rect);
#ifdef DIRTY_RECTS_CLIP_SUPPORT
typedef ret_t(*lcd_set_clip_dirty_rects_t)(lcd_t* lcd, const dirty_rects_t* dirty_rects);
ret_t lcd_set_clip_dirty_rects(lcd_t* lcd, const dirty_rects_t* rect);
#endif
typedef ret_t (*lcd_set_orientation_t)(lcd_t* lcd, lcd_orientation_t old_orientation,
lcd_orientation_t new_orientation);
typedef ret_t (*lcd_resize_t)(lcd_t* lcd, wh_t w, wh_t h, uint32_t line_length);
typedef ret_t (*lcd_get_text_metrics_t)(lcd_t* lcd, float_t* ascent, float_t* descent,
float_t* line_hight);
typedef ret_t (*lcd_set_global_alpha_t)(lcd_t* lcd, uint8_t alpha);
typedef ret_t (*lcd_set_text_color_t)(lcd_t* lcd, color_t color);
typedef ret_t (*lcd_set_stroke_color_t)(lcd_t* lcd, color_t color);
typedef ret_t (*lcd_set_fill_color_t)(lcd_t* lcd, color_t color);
typedef ret_t (*lcd_set_font_name_t)(lcd_t* lcd, const char* name);
typedef ret_t (*lcd_set_font_size_t)(lcd_t* lcd, uint32_t size);
typedef ret_t (*lcd_draw_image_repeat_t)(lcd_t* lcd, bitmap_t* img, const rect_t* src_in,
const rect_t* dst_in, wh_t dst_w, wh_t dst_h);
typedef ret_t (*lcd_draw_vline_t)(lcd_t* lcd, xy_t x, xy_t y, wh_t h);
typedef ret_t (*lcd_draw_hline_t)(lcd_t* lcd, xy_t x, xy_t y, wh_t w);
typedef ret_t (*lcd_draw_points_t)(lcd_t* lcd, point_t* points, uint32_t nr);
typedef color_t (*lcd_get_point_color_t)(lcd_t* lcd, xy_t x, xy_t y);
typedef ret_t (*lcd_fill_rect_t)(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h);
typedef ret_t (*lcd_clear_rect_t)(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h);
typedef ret_t (*lcd_stroke_rect_t)(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h);
typedef ret_t (*lcd_draw_glyph_t)(lcd_t* lcd, glyph_t* glyph, const rect_t* src, xy_t x, xy_t y);
typedef float_t (*lcd_measure_text_t)(lcd_t* lcd, const wchar_t* str, uint32_t nr);
typedef ret_t (*lcd_draw_text_t)(lcd_t* lcd, const wchar_t* str, uint32_t nr, xy_t x, xy_t y);
typedef ret_t (*lcd_draw_image_t)(lcd_t* lcd, bitmap_t* img, const rectf_t* src,
const rectf_t* dst);
typedef ret_t (*lcd_draw_image_matrix_t)(lcd_t* lcd, draw_image_info_t* info);
typedef vgcanvas_t* (*lcd_get_vgcanvas_t)(lcd_t* lcd);
typedef bitmap_format_t (*lcd_get_desired_bitmap_format_t)(lcd_t* lcd);
typedef wh_t (*lcd_get_width_t)(lcd_t* lcd);
typedef wh_t (*lcd_get_height_t)(lcd_t* lcd);
typedef ret_t (*lcd_swap_t)(lcd_t* lcd);
typedef ret_t (*lcd_flush_t)(lcd_t* lcd);
typedef ret_t (*lcd_sync_t)(lcd_t* lcd);
typedef ret_t (*lcd_end_frame_t)(lcd_t* lcd);
typedef ret_t (*lcd_destroy_t)(lcd_t* lcd);
/**
* @enum lcd_draw_mode_t
* @prefix LCD_DRAW_
* LCD绘制模式常量定义。
*/
typedef enum _lcd_draw_mode_t {
/**
* @const LCD_DRAW_NORMAL
* 正常绘制。
*/
LCD_DRAW_NORMAL = 0,
/**
* @const LCD_DRAW_ANIMATION
* 绘制窗口动画,两个窗口无重叠。
* 在该模式下可以直接绘制到显存不用绘制到framebuffer中。
*/
LCD_DRAW_ANIMATION,
/**
* @const LCD_DRAW_ANIMATION_OVERLAP
* 绘制窗口动画,两个窗口有重叠。
* (目前无特殊用途)。
*/
LCD_DRAW_ANIMATION_OVERLAP,
/**
* @const LCD_DRAW_SWAP
* 如果lcd支持swap操作在特殊情况下可以使用该模式提速。
*/
LCD_DRAW_SWAP,
/**
* @const LCD_DRAW_OFFLINE
* 离线模式绘制(仅适用于framebuffer)。
* 在该模式下绘制的内容不会显示出来但可以用take_snapshot取出来主要用于窗口动画。
*/
LCD_DRAW_OFFLINE
} lcd_draw_mode_t;
/**
* @enum lcd_type_t
* @prefix LCD_
* LCD类型常量定义。
*/
typedef enum _lcd_type_t {
/**
* @const LCD_FRAMEBUFFER
* 基于FrameBuffer的LCD。
*/
LCD_FRAMEBUFFER = 0,
/**
* @const LCD_REGISTER
* 基于寄存器的LCD。
*/
LCD_REGISTER,
/**
* @const LCD_VGCANVAS
* 基于VGCANVS的LCD。仅在支持OpenGL时用nanovg实现。
*/
LCD_VGCANVAS,
/**
* @const LCD_MONO
* 单色LCD。
*/
LCD_MONO,
/**
* @const LCD_CLUT
* 颜色表 LCD。
*/
LCD_CLUT,
/**
* @const LCD_COMPOSITOR
* 复合LCD。用于同时使用多个 LCD 的情况
*/
LCD_COMPOSITOR
} lcd_type_t;
/**
* @class lcd_t
* 显示设备抽象基类。
*/
struct _lcd_t {
lcd_begin_frame_t begin_frame;
lcd_set_clip_rect_t set_clip_rect;
lcd_get_clip_rect_t get_clip_rect;
lcd_is_rect_in_clip_rect_t is_rect_in_clip_rect;
#ifdef DIRTY_RECTS_CLIP_SUPPORT
lcd_set_clip_dirty_rects_t set_clip_dirty_rects;
#endif
lcd_set_global_alpha_t set_global_alpha;
lcd_set_text_color_t set_text_color;
lcd_set_stroke_color_t set_stroke_color;
lcd_set_fill_color_t set_fill_color;
lcd_set_font_name_t set_font_name;
lcd_set_font_size_t set_font_size;
lcd_get_text_metrics_t get_text_metrics;
lcd_draw_vline_t draw_vline;
lcd_draw_hline_t draw_hline;
lcd_fill_rect_t fill_rect;
lcd_clear_rect_t clear_rect;
lcd_stroke_rect_t stroke_rect;
lcd_draw_image_t draw_image;
lcd_draw_image_matrix_t draw_image_matrix;
lcd_draw_glyph_t draw_glyph;
lcd_draw_text_t draw_text;
lcd_measure_text_t measure_text;
lcd_draw_points_t draw_points;
lcd_draw_image_repeat_t draw_image_repeat;
lcd_get_point_color_t get_point_color;
lcd_swap_t swap; /*适用于double fb可选*/
lcd_get_width_t get_width;
lcd_get_height_t get_height;
lcd_flush_t flush;
lcd_sync_t sync;
lcd_end_frame_t end_frame;
lcd_get_vgcanvas_t get_vgcanvas;
lcd_get_desired_bitmap_format_t get_desired_bitmap_format;
lcd_set_vgcanvas_t set_vgcanvas;
lcd_set_line_length_t set_line_length;
lcd_get_type_t get_type;
lcd_get_dirty_rect_t get_dirty_rect;
lcd_get_dirty_rects_t get_dirty_rects;
lcd_is_support_dirty_rect_t is_support_dirty_rect;
lcd_set_canvas_t set_canvas;
lcd_resize_t resize;
lcd_set_orientation_t set_orientation;
lcd_destroy_t destroy;
/**
* @property {wh_t} w
* @annotation ["readable"]
* 屏幕的宽度
*/
wh_t w;
/**
* @property {wh_t} height
* @annotation ["readable"]
* 屏幕的高度
*/
wh_t h;
/**
* @property {color_t} text_color
* @annotation ["readable"]
* 文本颜色
*/
color_t text_color;
/**
* @property {color_t} fill_color
* @annotation ["readable"]
* 填充颜色
*/
color_t fill_color;
/**
* @property {color_t} stroke_color
* @annotation ["readable"]
* 线条颜色
*/
color_t stroke_color;
/**
* @property {char*} font_name
* @annotation ["readable"]
* 字体名称。
*/
char* font_name;
/**
* @property {uint32_t} font_size
* @annotation ["readable"]
* 字体大小。
*/
uint32_t font_size;
/**
* @property {lcd_draw_mode_t} draw_mode
* @annotation ["readable"]
* 绘制模式。
*/
lcd_draw_mode_t draw_mode;
/**
* @property {lcd_type_t} type
* @annotation ["readable"]
* LCD的类型。
*/
lcd_type_t type;
/**
* @property {uint64_t} last_update_time
* @annotation ["readable"]
* last update time
*/
uint64_t last_update_time;
/**
* @property {float_t} ratio
* @annotation ["readable"]
* 屏幕密度。
*/
float_t ratio;
/**
* @property {uint8_t} global_alpha
* @annotation ["readable"]
* 全局alpha
*/
uint8_t global_alpha;
/**
* @property {bool_t} support_dirty_rect
* @annotation ["readable"]
* 是否支持脏矩形。
*/
bool_t support_dirty_rect;
/*private*/
rect_t fps_rect;
rect_t dirty_rect;
const dirty_rects_t* dirty_rects;
void* impl_data;
};
/**
* @method lcd_begin_frame
* 准备绘制。
* @param {lcd_t*} lcd lcd对象。
* @param {const dirty_rects_t*} dirty_rects 需要绘制的区域。
* @param {lcd_draw_mode_t} anim_mode 动画模式如果可能直接画到显存而不是离线的framebuffer。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_begin_frame(lcd_t* lcd, const dirty_rects_t* dirty_rects, lcd_draw_mode_t draw_mode);
/**
* @method lcd_set_clip_rect
* 设置裁剪区域。
* @param {lcd_t*} lcd lcd对象。
* @param {const rect_t*} rect 裁剪区域。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_set_clip_rect(lcd_t* lcd, const rect_t* rect);
bool_t lcd_is_rect_in_clip_rect(lcd_t* lcd, xy_t left, xy_t top, xy_t right, xy_t bottom);
/**
* @method lcd_get_clip_rect
* 获取裁剪区域。
* @param {lcd_t*} lcd lcd对象。
* @param {rect_t*} rect 裁剪区域。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_get_clip_rect(lcd_t* lcd, rect_t* rect);
/**
* @method lcd_resize
* 基于SDL的PC软件在SDL窗口resize时需要调用本函数resize lcd。
* 屏幕旋转时会调用本函数调整LCD的大小。
* @param {lcd_t*} lcd lcd对象。
* @param {wh_t} w 新的宽度。
* @param {wh_t} h 新的高度。
* @param {uint32_t} line_length line_length。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_resize(lcd_t* lcd, wh_t w, wh_t h, uint32_t line_length);
/**
* @method lcd_set_global_alpha
* 设置全局alpha。
* @param {lcd_t*} lcd lcd对象。
* @param {uint8_t} alpha 全局alpha。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_set_global_alpha(lcd_t* lcd, uint8_t alpha);
/**
* @method lcd_set_text_color
* 设置文本颜色。
* @param {lcd_t*} lcd lcd对象。
* @param {color_t} color 颜色。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_set_text_color(lcd_t* lcd, color_t color);
/**
* @method lcd_set_stroke_color
* 设置线条颜色。
* @param {lcd_t*} lcd lcd对象。
* @param {color_t} color 颜色。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_set_stroke_color(lcd_t* lcd, color_t color);
/**
* @method lcd_set_fill_color
* 设置填充颜色。
* @param {lcd_t*} lcd lcd对象。
* @param {color_t} color 颜色。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_set_fill_color(lcd_t* lcd, color_t color);
/**
* @method lcd_set_font_name
* 设置字体名称。
* @param {lcd_t*} lcd lcd对象。
* @param {const char*} name 字体名称。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_set_font_name(lcd_t* lcd, const char* name);
/**
* @method lcd_set_font_size
* 设置字体大小。
* @param {lcd_t*} lcd lcd对象。
* @param {uint32_t} font_size 字体大小。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_set_font_size(lcd_t* lcd, uint32_t font_size);
/**
* @method lcd_draw_vline
* 绘制一条垂直线。
* @param {lcd_t*} lcd lcd对象。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
* @param {xy_t} h 直线高度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_draw_vline(lcd_t* lcd, xy_t x, xy_t y, wh_t h);
/**
* @method lcd_draw_hline
* 绘制一条水平线。
* @param {lcd_t*} lcd lcd对象。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
* @param {xy_t} w 直线宽度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_draw_hline(lcd_t* lcd, xy_t x, xy_t y, wh_t w);
/**
* @method lcd_draw_points
* 绘制一组点。
* @param {lcd_t*} lcd lcd对象。
* @param {point_t*} points 要绘制的点集合。
* @param {uint32_t} nr 点的个数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_draw_points(lcd_t* lcd, point_t* points, uint32_t nr);
/**
* @method lcd_get_point_color
* 获取指定点的颜色对于基于非FrameBuffer的LCD返回当前的fill_color。
* @param {lcd_t*} lcd lcd对象。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
*
* @return {color_t} 返回RET_OK表示成功否则表示失败。
*/
color_t lcd_get_point_color(lcd_t* lcd, xy_t x, xy_t y);
/**
* @method lcd_fill_rect
* 绘制实心矩形。
* @param {lcd_t*} lcd lcd对象。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
* @param {wh_t} w 宽度。
* @param {wh_t} h 高度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_fill_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method lcd_clear_rect
* 填充实心矩形。
* @param {lcd_t*} lcd lcd对象。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
* @param {wh_t} w 宽度。
* @param {wh_t} h 高度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_clear_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method lcd_stroke_rect
* 绘制矩形边框。
* @param {lcd_t*} lcd lcd对象。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
* @param {wh_t} w 宽度。
* @param {wh_t} h 高度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_stroke_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method lcd_draw_glyph
* 绘制字符。如果实现了measure_text/draw_text则不需要实现本函数。
* @param {lcd_t*} lcd lcd对象。
* @param {glyph_t*} glyph 字模
* @param {const rect_t*} src 只绘制指定区域的部分。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_draw_glyph(lcd_t* lcd, glyph_t* glyph, const rect_t* src, xy_t x, xy_t y);
/**
* @method lcd_measure_text
* 测量字符串占用的宽度。
* @param {lcd_t*} lcd lcd对象。
* @param {const wchar_t*} str 字符串。
* @param {uint32_t} nr 字符数。
*
* @return {float_t} 返回字符串占用的宽度。
*/
float_t lcd_measure_text(lcd_t* lcd, const wchar_t* str, uint32_t nr);
/**
* @method lcd_draw_text
* 绘制字符。
* @param {lcd_t*} lcd lcd对象。
* @param {const wchar_t*} str 字符串。
* @param {uint32_t} nr 字符数。
* @param {xy_t} x x坐标。
* @param {xy_t} y y坐标。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_draw_text(lcd_t* lcd, const wchar_t* str, uint32_t nr, xy_t x, xy_t y);
/**
* @method lcd_draw_image
* 绘制图片。
* @param {lcd_t*} lcd lcd对象。
* @param {bitmap_t*} img 图片。
* @param {const rectf_t*} src 只绘制指定区域的部分。
* @param {const rectf_t*} dst 绘制到目标区域。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_draw_image(lcd_t* lcd, bitmap_t* img, const rectf_t* src, const rectf_t* dst);
#ifdef WITH_VG_GPU
#ifdef VG_DRAW_IMAGE_REPEAT
/**
* @_method lcd_draw_image_repeat
* 绘制图片。
* @param {lcd_t*} lcd lcd对象。
* @param {bitmap_t*} img 图片。
* @param {const rect_t*} src 只绘制指定区域的部分。
* @param {const rect_t*} dst 绘制到目标区域。
* @param {wh_t} dst_w 宽度。
* @param {wh_t} dst_h 高度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_draw_image_repeat(lcd_t* lcd, bitmap_t* img, const rect_t* src, const rect_t* dst, wh_t dst_w, wh_t dst_h);
#endif
#endif
/**
* @method lcd_draw_image_matrix
* 绘制图片。
* @param {lcd_t*} lcd lcd对象。
* @param {draw_image_info_t*} info 绘制参数。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_draw_image_matrix(lcd_t* lcd, draw_image_info_t* info);
/**
* @method lcd_get_vgcanvas
* 获取矢量图canvas。
* @param {lcd_t*} lcd lcd对象。
*
* @return {vgcanvas_t*} 返回矢量图canvas。
*/
vgcanvas_t* lcd_get_vgcanvas(lcd_t* lcd);
/**
* @method lcd_get_desired_bitmap_format
* 获取期望的位图格式。绘制期望的位图格式可以提高绘制性能。
* @param {lcd_t*} lcd lcd对象。
*
* @return {bitmap_format_t} 返回期望的位图格式。
*/
bitmap_format_t lcd_get_desired_bitmap_format(lcd_t* lcd);
/**
* @method lcd_swap
* 对于double fb如果硬件支持swap在LCD_DRAW_SWAP模式下该函数用于切换fb。
* @annotation ["private"]
* @param {lcd_t*} lcd lcd对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_swap(lcd_t* lcd);
/**
* @method lcd_get_width
* 获取宽度。
* @param {lcd_t*} lcd lcd对象。
*
* @return {wh_t} 返回宽度。
*/
wh_t lcd_get_width(lcd_t* lcd);
/**
* @method lcd_get_height
* 获取高度。
* @param {lcd_t*} lcd lcd对象。
*
* @return {wh_t} 返回高度。
*/
wh_t lcd_get_height(lcd_t* lcd);
/**
* @method lcd_flush
* flush。
* @annotation ["private"]
* @param {lcd_t*} lcd lcd对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_flush(lcd_t* lcd);
/**
* @method lcd_sync
* sync。
* @annotation ["private"]
* @param {lcd_t*} lcd lcd对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_sync(lcd_t* lcd);
/**
* @method lcd_is_swappable
* 判读lcd是否支持swap。
* @param {lcd_t*} lcd lcd对象。
*
* @return {bool_t} 返回是否支持swap。
*/
bool_t lcd_is_swappable(lcd_t* lcd);
/**
* @method lcd_end_frame
* 完成绘制,同步到显示设备。
* @param {lcd_t*} lcd lcd对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_end_frame(lcd_t* lcd);
/**
* @method lcd_get_text_metrics
* 获取当前字体的度量信息。
*
* @param {lcd_t*} lcd lcd对象。
* @param {float_t*} ascent 用于返回ascent。
* @param {float_t*} descent 用于返回descent。
* @param {float_t*} line_hight 用于返回line height。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_get_text_metrics(lcd_t* lcd, float_t* ascent, float_t* descent, float_t* line_hight);
/**
* @method lcd_get_type
* 获取 lcd 类型。
* @param {lcd_t*} lcd lcd对象。
*
* @return {lcd_type_t} 返回 lcd_type。
*/
lcd_type_t lcd_get_type(lcd_t* lcd);
/**
* @method lcd_set_vgcanvas
* 设置 vgcanvas。
* @param {lcd_t*} lcd lcd对象。
* @param {vgcanvas_t*} vgcanvas vgcanvas对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_set_vgcanvas(lcd_t* lcd, vgcanvas_t* vgcanvas);
/**
* @method lcd_set_line_length
* 设置 line_length 。
* @param {lcd_t*} lcd lcd对象。
* @param {uint32_t} line_length 一行的字节长度。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_set_line_length(lcd_t* lcd, uint32_t line_length);
/**
* @method lcd_destroy
* 销毁lcd对象。
* @param {lcd_t*} lcd lcd对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_destroy(lcd_t* lcd);
/**
* @method lcd_get_dirty_rect
* 获取 lcd 对象的脏矩形。
* @param {lcd_t*} lcd lcd对象。
* @param {rect_t*} r 返回脏矩形。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_get_dirty_rect(lcd_t* lcd, rect_t* r);
/**
* @method lcd_get_dirty_rect
* 获取 lcd 对象的脏矩形列表。
* @param {lcd_t*} lcd lcd对象。
*
* @return {const dirty_rects_t*} 成功返回脏矩形列表,失败返回 NULL。
*/
const dirty_rects_t* lcd_get_dirty_rects(lcd_t* lcd);
/**
* @method lcd_is_support_dirty_rect
* 获取 lcd 对象是否支持脏矩形。
* @param {lcd_t*} lcd lcd对象。
*
* @return {bool_t} 返回TRUE表示支持否则表示不支持。
*/
bool_t lcd_is_support_dirty_rect(lcd_t* lcd);
/* private */
bool_t lcd_is_dirty(lcd_t* lcd);
ret_t lcd_set_canvas(lcd_t* lcd, canvas_t* c);
ret_t lcd_set_orientation(lcd_t* lcd, lcd_orientation_t old_orientation,
lcd_orientation_t new_orientation);
END_C_DECLS
#endif /*TK_LCD_H*/

View File

@ -0,0 +1,107 @@
#ifndef TK_LCD_FB_DIRTY_RECTS_H
#define TK_LCD_FB_DIRTY_RECTS_H
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "tkc/darray.h"
#include "base/lcd.h"
#include "base/types_def.h"
BEGIN_C_DECLS
/**
* @class lcd_fb_dirty_rects_t
* lcd fb脏矩形。
*
*/
typedef struct _lcd_fb_dirty_rects_t {
wh_t lcd_w;
wh_t lcd_h;
darray_t fb_dirty_list;
} lcd_fb_dirty_rects_t;
/**
* @method lcd_fb_dirty_rects_get_dirty_rects_by_fb
* 根据 fb 来获取脏矩形对象
* @export none
* @param {lcd_fb_dirty_rects_t*} lcd_fb_dirty_rects lcd_fb_dirty_rects_t对象。
* @param {uint8_t*} fb fb 地址。
*
* @return {const dirty_rects_t*} 成功返回脏矩形对象,失败返回 NULL。
*/
const dirty_rects_t* lcd_fb_dirty_rects_get_dirty_rects_by_fb(
lcd_fb_dirty_rects_t* lcd_fb_dirty_rects, uint8_t* fb);
/**
* @method lcd_fb_dirty_rects_reset_dirty_rects_by_fb
* 清除对应 fb 的脏矩形列表。
* @export none
* @param {lcd_fb_dirty_rects_t*} lcd_fb_dirty_rects lcd_fb_dirty_rects_t对象。
* @param {uint8_t*} fb fb 地址。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_fb_dirty_rects_reset_dirty_rects_by_fb(lcd_fb_dirty_rects_t* lcd_fb_dirty_rects,
uint8_t* fb);
/**
* @method lcd_fb_dirty_rects_update_all_fb_dirty_rects
* 把当前脏矩形列表合并到所有 fb 的脏矩形中。
* @export none
* @param {lcd_fb_dirty_rects_t*} lcd_fb_dirty_rects lcd_fb_dirty_rects_t对象。
* @param {const dirty_rects_t*} dirty_rects 当前脏矩形列表。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_fb_dirty_rects_update_all_fb_dirty_rects(lcd_fb_dirty_rects_t* lcd_fb_dirty_rects,
const dirty_rects_t* dirty_rects);
/**
* @method lcd_fb_dirty_rects_add_fb_info
* 添加新的 fb 信息
* 如果已经存在的话,就不会重新添加
* @export none
* @param {lcd_fb_dirty_rects_t*} lcd_fb_dirty_rects lcd_fb_dirty_rects_t对象。
* @param {uint8_t*} fb fb 地址。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_fb_dirty_rects_add_fb_info(lcd_fb_dirty_rects_t* lcd_fb_dirty_rects, uint8_t* fb);
/**
* @method lcd_fb_dirty_rects_deinit
* 清除 lcd_fb_dirty_rects_t 对象数据
* @export none
* @param {lcd_fb_dirty_rects_t*} lcd_fb_dirty_rects lcd_fb_dirty_rects_t对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_fb_dirty_rects_deinit(lcd_fb_dirty_rects_t* lcd_fb_dirty_rects);
/**
* @method lcd_fb_dirty_rects_init
* 初始化 lcd_fb_dirty_rects_t 对象
* @export none
* @param {lcd_fb_dirty_rects_t*} lcd_fb_dirty_rects lcd_fb_dirty_rects_t对象。
* @param {wh_t} lcd_w lcd 的宽。
* @param {wh_t} lcd_h lcd 的高。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_fb_dirty_rects_init(lcd_fb_dirty_rects_t* lcd_fb_dirty_rects, wh_t lcd_w, wh_t lcd_h);
/**
* @method lcd_fb_dirty_rects_reinit
* 修改 lcd_fb_dirty_rects_t 对象的宽高
* @export none
* @param {lcd_fb_dirty_rects_t*} lcd_fb_dirty_rects lcd_fb_dirty_rects_t对象。
* @param {wh_t} lcd_w lcd 的宽。
* @param {wh_t} lcd_h lcd 的高。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t lcd_fb_dirty_rects_reinit(lcd_fb_dirty_rects_t* lcd_fb_dirty_rects, wh_t lcd_w, wh_t lcd_h);
END_C_DECLS
#endif /*TK_LCD_FB_DIRTY_RECTS_H*/

View File

@ -0,0 +1,110 @@
#include "base/lcd_fb_dirty_rects.h"
typedef struct _lcd_fb_info_t {
uint8_t* fb;
dirty_rects_t dirty_rects;
} lcd_fb_info_t;
const dirty_rects_t* lcd_fb_dirty_rects_get_dirty_rects_by_fb(lcd_fb_dirty_rects_t* lcd_fb_dirty_rects, uint8_t* fb) {
lcd_fb_info_t* fb_info = NULL;
return_value_if_fail(lcd_fb_dirty_rects != NULL && fb != NULL, NULL);
fb_info = (lcd_fb_info_t*)darray_find(&(lcd_fb_dirty_rects->fb_dirty_list), fb);
if (fb_info != NULL) {
return (const dirty_rects_t*)&(fb_info->dirty_rects);
}
return NULL;
}
ret_t lcd_fb_dirty_rects_reset_dirty_rects_by_fb(lcd_fb_dirty_rects_t* lcd_fb_dirty_rects, uint8_t* fb) {
lcd_fb_info_t* fb_info = NULL;
return_value_if_fail(lcd_fb_dirty_rects != NULL && fb != NULL, RET_BAD_PARAMS);
fb_info = (lcd_fb_info_t*)darray_find(&(lcd_fb_dirty_rects->fb_dirty_list), fb);
if (fb_info != NULL) {
return dirty_rects_reset(&(fb_info->dirty_rects));
}
return RET_NOT_FOUND;
}
ret_t lcd_fb_dirty_rects_update_all_fb_dirty_rects(lcd_fb_dirty_rects_t* lcd_fb_dirty_rects, const dirty_rects_t* dirty_rects) {
uint32_t i, j;
lcd_fb_info_t* fb_info = NULL;
return_value_if_fail(lcd_fb_dirty_rects != NULL, RET_BAD_PARAMS);
for (i = 0; i < lcd_fb_dirty_rects->fb_dirty_list.size; i++) {
fb_info = (lcd_fb_info_t*)darray_get(&(lcd_fb_dirty_rects->fb_dirty_list), i);
if (fb_info != NULL) {
if (dirty_rects == NULL) {
rect_t r = rect_init(0, 0, lcd_fb_dirty_rects->lcd_w, lcd_fb_dirty_rects->lcd_h);
dirty_rects_add(&(fb_info->dirty_rects), (const rect_t*)&r);
} else {
if (dirty_rects->disable_multiple) {
dirty_rects_add(&(fb_info->dirty_rects), &(dirty_rects->max));
} else {
for (j = 0; j < dirty_rects->nr; j++) {
const rect_t* iter = dirty_rects->rects + j;
dirty_rects_add(&(fb_info->dirty_rects), iter);
}
}
}
}
}
return RET_OK;
}
ret_t lcd_fb_dirty_rects_add_fb_info(lcd_fb_dirty_rects_t* lcd_fb_dirty_rects, uint8_t* fb) {
lcd_fb_info_t* fb_info = NULL;
return_value_if_fail(lcd_fb_dirty_rects != NULL && fb != NULL, RET_BAD_PARAMS);
fb_info = darray_find(&(lcd_fb_dirty_rects->fb_dirty_list), fb);
if (fb_info == NULL) {
rect_t r = rect_init(0, 0, lcd_fb_dirty_rects->lcd_w, lcd_fb_dirty_rects->lcd_h);
fb_info = TKMEM_ZALLOC(lcd_fb_info_t);
return_value_if_fail(fb_info != NULL, RET_OOM);
fb_info->fb = fb;
dirty_rects_init(&(fb_info->dirty_rects));
dirty_rects_add(&(fb_info->dirty_rects), &r);
darray_push(&(lcd_fb_dirty_rects->fb_dirty_list), fb_info);
}
return RET_OK;
}
static int lcd_fb_dirty_rects_fb_dirty_list_cmp_by_fb(const void* a, const void* b) {
lcd_fb_info_t* fb_info1 = (lcd_fb_info_t*)a;
return tk_pointer_to_int(fb_info1->fb) - tk_pointer_to_int(b);
}
static ret_t lcd_fb_dirty_rects_fb_dirty_list_destroy(void* data) {
lcd_fb_info_t* fb_info = (lcd_fb_info_t*)data;
dirty_rects_deinit(&(fb_info->dirty_rects));
TKMEM_FREE(data);
return RET_OK;
}
ret_t lcd_fb_dirty_rects_reinit(lcd_fb_dirty_rects_t* lcd_fb_dirty_rects, wh_t lcd_w, wh_t lcd_h) {
int32_t i;
return_value_if_fail(lcd_fb_dirty_rects != NULL, RET_BAD_PARAMS);
lcd_fb_dirty_rects->lcd_w = lcd_w;
lcd_fb_dirty_rects->lcd_h = lcd_h;
for (i = 0; i < lcd_fb_dirty_rects->fb_dirty_list.size; i++) {
lcd_fb_info_t* fb_info = (lcd_fb_info_t*)darray_get(&(lcd_fb_dirty_rects->fb_dirty_list), i);
if (fb_info != NULL) {
rect_t r = rect_init(0, 0, lcd_fb_dirty_rects->lcd_w, lcd_fb_dirty_rects->lcd_h);
dirty_rects_reset(&(fb_info->dirty_rects));
dirty_rects_add(&(fb_info->dirty_rects), &r);
}
}
return RET_OK;
}
ret_t lcd_fb_dirty_rects_init(lcd_fb_dirty_rects_t* lcd_fb_dirty_rects, wh_t lcd_w, wh_t lcd_h) {
darray_t* tmp = NULL;
return_value_if_fail(lcd_fb_dirty_rects != NULL, RET_BAD_PARAMS);
lcd_fb_dirty_rects->lcd_w = lcd_w;
lcd_fb_dirty_rects->lcd_h = lcd_h;
tmp = darray_init(&(lcd_fb_dirty_rects->fb_dirty_list), 4, lcd_fb_dirty_rects_fb_dirty_list_destroy, lcd_fb_dirty_rects_fb_dirty_list_cmp_by_fb);
return_value_if_fail(tmp != NULL, RET_FAIL);
return RET_OK;
}
ret_t lcd_fb_dirty_rects_deinit(lcd_fb_dirty_rects_t* lcd_fb_dirty_rects) {
return_value_if_fail(lcd_fb_dirty_rects != NULL, RET_BAD_PARAMS);
return darray_deinit(&(lcd_fb_dirty_rects->fb_dirty_list));
}

View File

@ -0,0 +1,507 @@
/**
* File: lcd_profile.c
* Author: AWTK Develop Team
* Brief: wrap lcd for performance profile.
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-03-21 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/time_now.h"
#include "base/lcd_profile.h"
#ifdef ENABLE_PERFORMANCE_PROFILE
static ret_t lcd_profile_begin_frame(lcd_t* lcd, const dirty_rects_t* dirty_rects) {
ret_t ret = RET_OK;
lcd_profile_t* profile = LCD_PROFILE(lcd);
profile->draw_image_times = 0;
profile->draw_image_cost = 0;
profile->draw_image_pixels = 0;
profile->draw_text_times = 0;
profile->draw_text_cost = 0;
profile->draw_text_chars = 0;
profile->fill_times = 0;
profile->fill_cost = 0;
profile->fill_pixels = 0;
profile->stroke_times = 0;
profile->stroke_cost = 0;
profile->stroke_pixels = 0;
profile->alpha_cost = 0;
profile->begin_frame_time = time_now_ms();
ret = lcd_begin_frame(profile->impl, dirty_rects, lcd->draw_mode);
return ret;
}
static ret_t lcd_profile_set_clip_rect(lcd_t* lcd, const rect_t* rect) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_set_clip_rect(profile->impl, rect);
}
static ret_t lcd_profile_get_clip_rect(lcd_t* lcd, rect_t* rect) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_get_clip_rect(profile->impl, rect);
}
static bool_t lcd_profile_is_rect_in_clip_rect(lcd_t* lcd, xy_t left, xy_t top, xy_t right, xy_t bottom) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_is_rect_in_clip_rect(profile->impl, left, top, right, bottom);
}
static ret_t lcd_profile_resize(lcd_t* lcd, wh_t w, wh_t h, uint32_t line_length) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_resize(profile->impl, w, h, line_length);
}
static ret_t lcd_profile_set_orientation(lcd_t* lcd, lcd_orientation_t old_orientation,
lcd_orientation_t new_orientation) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_set_orientation(profile->impl, old_orientation, new_orientation);
}
static ret_t lcd_profile_set_global_alpha(lcd_t* lcd, uint8_t alpha) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret_t ret = RET_OK;
uint32_t cost = 0;
uint64_t start = time_now_ms();
ret = lcd_set_global_alpha(profile->impl, alpha);
cost = time_now_ms() - start;
profile->alpha_cost += cost;
return ret;
}
static ret_t lcd_profile_set_text_color(lcd_t* lcd, color_t color) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_set_text_color(profile->impl, color);
}
static ret_t lcd_profile_set_stroke_color(lcd_t* lcd, color_t color) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_set_stroke_color(profile->impl, color);
}
static ret_t lcd_profile_set_fill_color(lcd_t* lcd, color_t color) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_set_fill_color(profile->impl, color);
}
static ret_t lcd_profile_set_font_name(lcd_t* lcd, const char* name) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_set_font_name(profile->impl, name);
}
static ret_t lcd_profile_set_font_size(lcd_t* lcd, uint32_t font_size) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_set_font_size(profile->impl, font_size);
}
static ret_t lcd_profile_draw_vline(lcd_t* lcd, xy_t x, xy_t y, xy_t h) {
ret_t ret = RET_OK;
uint32_t cost = 0;
uint64_t start = time_now_ms();
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret = lcd_draw_vline(profile->impl, x, y, h);
cost = time_now_ms() - start;
profile->stroke_times++;
profile->stroke_cost += cost;
profile->stroke_pixels += h;
return ret;
}
static ret_t lcd_profile_draw_hline(lcd_t* lcd, xy_t x, xy_t y, xy_t w) {
ret_t ret = RET_OK;
uint32_t cost = 0;
uint64_t start = time_now_ms();
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret = lcd_draw_hline(profile->impl, x, y, w);
cost = time_now_ms() - start;
profile->stroke_times++;
profile->stroke_cost += cost;
profile->stroke_pixels += w;
return ret;
}
static ret_t lcd_profile_draw_points(lcd_t* lcd, point_t* points, uint32_t nr) {
ret_t ret = RET_OK;
uint32_t cost = 0;
uint64_t start = time_now_ms();
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret = lcd_draw_points(profile->impl, points, nr);
cost = time_now_ms() - start;
profile->stroke_times++;
profile->stroke_cost += cost;
profile->stroke_pixels += nr;
return ret;
}
static color_t lcd_profile_get_point_color(lcd_t* lcd, xy_t x, xy_t y) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_get_point_color(profile->impl, x, y);
}
static ret_t lcd_profile_fill_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h) {
ret_t ret = RET_OK;
uint32_t cost = 0;
uint64_t start = time_now_ms();
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret = lcd_fill_rect(profile->impl, x, y, w, h);
cost = time_now_ms() - start;
profile->fill_times++;
profile->fill_cost += cost;
profile->fill_pixels += w * h;
return ret;
}
static ret_t lcd_profile_stroke_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h) {
ret_t ret = RET_OK;
uint32_t cost = 0;
uint64_t start = time_now_ms();
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret = lcd_stroke_rect(profile->impl, x, y, w, h);
cost = time_now_ms() - start;
profile->stroke_times++;
profile->stroke_cost += cost;
profile->stroke_pixels += w * h;
return ret;
}
static ret_t lcd_profile_draw_glyph(lcd_t* lcd, glyph_t* glyph, const rect_t* src, xy_t x, xy_t y) {
ret_t ret = RET_OK;
uint32_t cost = 0;
uint64_t start = time_now_ms();
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret = lcd_draw_glyph(profile->impl, glyph, src, x, y);
cost = time_now_ms() - start;
profile->draw_text_times++;
profile->draw_text_cost += cost;
profile->draw_text_chars++;
return ret;
}
static float_t lcd_profile_measure_text(lcd_t* lcd, const wchar_t* str, uint32_t nr) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_measure_text(profile->impl, str, nr);
}
static ret_t lcd_profile_draw_text(lcd_t* lcd, const wchar_t* str, uint32_t nr, xy_t x, xy_t y) {
ret_t ret = RET_OK;
uint32_t cost = 0;
uint64_t start = time_now_ms();
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret = lcd_draw_text(profile->impl, str, nr, x, y);
cost = time_now_ms() - start;
profile->draw_text_times++;
profile->draw_text_cost += cost;
profile->draw_text_chars += nr;
return ret;
}
static ret_t lcd_profile_draw_image(lcd_t* lcd, bitmap_t* img, const rectf_t* src, const rectf_t* dst) {
ret_t ret = RET_OK;
uint32_t cost = 0;
uint64_t start = time_now_ms();
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret = lcd_draw_image(profile->impl, img, src, dst);
cost = time_now_ms() - start;
profile->draw_image_times++;
profile->draw_image_cost += cost;
profile->draw_image_pixels += dst->w * dst->h;
return ret;
}
#ifdef WITH_VG_GPU
#ifdef VG_DRAW_IMAGE_REPEAT
static ret_t lcd_profile_draw_image_repeat(lcd_t* lcd, bitmap_t* img, const rect_t* src, const rect_t* dst, wh_t dst_w, wh_t dst_h) {
ret_t ret = RET_OK;
uint32_t cost = 0;
uint64_t start = time_now_ms();
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret = lcd_draw_image_repeat(profile->impl, img, src, dst, dst_w, dst_h);
cost = time_now_ms() - start;
profile->draw_image_times++;
profile->draw_image_cost += cost;
profile->draw_image_pixels += dst->w * dst->h;
return ret;
}
#endif
#endif
static ret_t lcd_profile_draw_image_matrix(lcd_t* lcd, draw_image_info_t* info) {
ret_t ret = RET_OK;
uint32_t cost = 0;
uint64_t start = time_now_ms();
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret = lcd_draw_image_matrix(profile->impl, info);
cost = time_now_ms() - start;
profile->draw_image_times++;
profile->draw_image_cost += cost;
return ret;
}
static vgcanvas_t* lcd_profile_get_vgcanvas(lcd_t* lcd) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_get_vgcanvas(profile->impl);
}
static bitmap_format_t lcd_profile_get_desired_bitmap_format(lcd_t* lcd) {
lcd_profile_t* profile = LCD_PROFILE(lcd);
return lcd_get_desired_bitmap_format(profile->impl);
}
static ret_t lcd_profile_swap(lcd_t* lcd) {
ret_t ret = RET_OK;
uint32_t cost = 0;
uint64_t start = time_now_ms();
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret = lcd_swap(profile->impl);
cost = time_now_ms() - start;
profile->swap_cost = cost;
return ret;
}
static ret_t lcd_profile_flush(lcd_t* lcd) {
ret_t ret = RET_OK;
uint32_t cost = 0;
uint64_t start = time_now_ms();
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret = lcd_flush(profile->impl);
cost = time_now_ms() - start;
profile->flush_cost = cost;
return ret;
}
static ret_t lcd_profile_end_frame(lcd_t* lcd) {
ret_t ret = RET_OK;
uint32_t cost = 0;
uint32_t end = 0;
uint64_t start = time_now_ms();
lcd_profile_t* profile = LCD_PROFILE(lcd);
ret = lcd_end_frame(profile->impl);
end = time_now_ms();
cost = end - start;
profile->total_cost = time_now_ms() - profile->begin_frame_time;
//return RET_OK;
static unsigned int count = 0;
count ++;
if (1 && ((count % 16) == 0) && profile->total_cost > 8) {
log_debug("#####################################\n");
log_debug("%s:%d\n", __FILE__, __LINE__);
log_debug("-------------------------------------\n");
log_debug(" total_cost=%u \n", profile->total_cost);
log_debug(" draw_image_cost=%u times=%u\n", profile->draw_image_cost,
profile->draw_image_times);
log_debug(" draw_text_cost=%u times=%u\n", profile->draw_text_cost, profile->draw_text_times);
log_debug(" fill_cost=%u times=%u\n", profile->fill_cost, profile->fill_times);
log_debug(" stroke_cost=%u times=%u\n", profile->stroke_cost, profile->stroke_times);
if (cost) {
log_debug(" end_frame_cost=%u\n", cost);
}
if (profile->alpha_cost) {
log_debug(" alpha_cost=%u\n", profile->alpha_cost);
}
if (profile->flush_cost) {
log_debug(" flush_cost=%u\n", profile->flush_cost);
}
if (profile->swap_cost) {
log_debug(" swap_cost=%u\n", profile->swap_cost);
}
log_debug("-------------------------------------\n");
}
return ret;
}
lcd_t* lcd_profile_create(lcd_t* impl) {
lcd_t* lcd = NULL;
return_value_if_fail(impl != NULL, NULL);
lcd = (lcd_t*)TKMEM_ZALLOC(lcd_profile_t);
return_value_if_fail(lcd != NULL, NULL);
lcd->type = impl->type;
lcd->ratio = impl->ratio;
lcd->w = lcd_get_width(impl);
lcd->h = lcd_get_height(impl);
LCD_PROFILE(lcd)->impl = impl;
lcd->support_dirty_rect = impl->support_dirty_rect;
lcd->begin_frame = lcd_profile_begin_frame;
lcd->set_global_alpha = lcd_profile_set_global_alpha;
lcd->set_text_color = lcd_profile_set_text_color;
lcd->set_stroke_color = lcd_profile_set_stroke_color;
lcd->set_fill_color = lcd_profile_set_fill_color;
if (impl->set_font_name != NULL) {
lcd->set_font_name = lcd_profile_set_font_name;
lcd->set_font_size = lcd_profile_set_font_size;
}
if (impl->set_clip_rect != NULL) {
lcd->set_clip_rect = lcd_profile_set_clip_rect;
}
if (impl->get_clip_rect != NULL) {
lcd->get_clip_rect = lcd_profile_get_clip_rect;
}
if (impl->is_rect_in_clip_rect != NULL) {
lcd->is_rect_in_clip_rect = lcd_profile_is_rect_in_clip_rect;
}
if (impl->resize != NULL) {
lcd->resize = lcd_profile_resize;
}
if (lcd->set_orientation != NULL) {
lcd->set_orientation = lcd_profile_set_orientation;
}
if (impl->draw_vline != NULL) {
lcd->draw_vline = lcd_profile_draw_vline;
}
if (impl->draw_hline != NULL) {
lcd->draw_hline = lcd_profile_draw_hline;
}
if (impl->draw_points != NULL) {
lcd->draw_points = lcd_profile_draw_points;
}
if (impl->get_point_color != NULL) {
lcd->get_point_color = lcd_profile_get_point_color;
}
if (impl->fill_rect != NULL) {
lcd->fill_rect = lcd_profile_fill_rect;
}
if (impl->stroke_rect != NULL) {
lcd->stroke_rect = lcd_profile_stroke_rect;
}
if (impl->draw_glyph != NULL) {
lcd->draw_glyph = lcd_profile_draw_glyph;
}
if (impl->measure_text != NULL) {
lcd->measure_text = lcd_profile_measure_text;
}
if (impl->draw_text != NULL) {
lcd->draw_text = lcd_profile_draw_text;
}
if (impl->draw_image != NULL) {
lcd->draw_image = lcd_profile_draw_image;
}
#ifdef WITH_VG_GPU
#ifdef VG_DRAW_IMAGE_REPEAT
if (impl->draw_image_repeat != NULL) {
lcd->draw_image_repeat = lcd_profile_draw_image_repeat;
}
#endif
#endif
if (impl->draw_image_matrix != NULL) {
lcd->draw_image_matrix = lcd_profile_draw_image_matrix;
}
if (impl->get_vgcanvas != NULL) {
lcd->get_vgcanvas = lcd_profile_get_vgcanvas;
}
if (impl->get_desired_bitmap_format != NULL) {
lcd->get_desired_bitmap_format = lcd_profile_get_desired_bitmap_format;
}
if (impl->swap != NULL) {
lcd->swap = lcd_profile_swap;
}
if (impl->flush != NULL) {
lcd->flush = lcd_profile_flush;
}
if (impl->end_frame != NULL) {
lcd->end_frame = lcd_profile_end_frame;
}
return lcd;
}
#else
lcd_t* lcd_profile_create(lcd_t* impl) {
return impl;
}
#endif /*ENABLE_PERFORMANCE_PROFILE*/

View File

@ -0,0 +1,71 @@
/**
* File: lcd_profile.h
* Author: AWTK Develop Team
* Brief: wrap lcd for performance profile.
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-03-21 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef LCD_PROFILE_H
#define LCD_PROFILE_H
#include "base/lcd.h"
BEGIN_C_DECLS
/**
* @class lcd_profile_t
* @parent lcd_t
* 对现有LCD对象进行包装实现对各个函数的时间统计用于辅助定位性能瓶颈。
*
*/
typedef struct _lcd_profile_t {
lcd_t lcd;
/*private*/
lcd_t* impl;
uint32_t begin_frame_time;
uint32_t total_cost;
uint32_t swap_cost;
uint32_t flush_cost;
uint32_t alpha_cost;
uint32_t draw_image_cost;
uint32_t draw_image_times;
uint32_t draw_image_pixels;
uint32_t draw_text_cost;
uint32_t draw_text_times;
uint32_t draw_text_chars;
uint32_t fill_cost;
uint32_t fill_times;
uint32_t fill_pixels;
uint32_t stroke_cost;
uint32_t stroke_times;
uint32_t stroke_pixels;
} lcd_profile_t;
lcd_t* lcd_profile_create(lcd_t* impl);
#define LCD_PROFILE(lcd) ((lcd_profile_t*)(lcd))
END_C_DECLS
#endif /*LCD_PROFILE_H*/

View File

@ -0,0 +1,151 @@
/**
* File: line_break.c
* Author: AWTK Develop Team
* Brief: line break and work break algorithm.
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-07-28 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "base/line_break.h"
#ifdef WITH_UNICODE_BREAK
#include "libunibreak/linebreak.h"
#include "libunibreak/wordbreak.h"
break_type_t line_break_check(wchar_t c1, wchar_t c2) {
int ret = 0;
static bool_t inited = FALSE;
if (!inited) {
inited = TRUE;
init_linebreak();
}
if (c1 == ' ') {
return LINE_BREAK_ALLOW;
}
ret = is_line_breakable(c1, c2, "");
switch (ret) {
case LINEBREAK_MUSTBREAK: {
return LINE_BREAK_MUST;
}
case LINEBREAK_ALLOWBREAK: {
return LINE_BREAK_ALLOW;
}
case LINEBREAK_NOBREAK: {
return LINE_BREAK_NO;
}
default: {
return LINE_BREAK_ALLOW;
}
}
}
break_type_t word_break_check(wchar_t c1, wchar_t c2) {
utf32_t s[2];
char brks[2];
static bool_t inited = FALSE;
if (!inited) {
inited = TRUE;
init_wordbreak();
}
s[0] = c1;
s[1] = c2;
set_wordbreaks_utf32(s, 2, "", brks);
if (brks[0] == WORDBREAK_BREAK) {
return LINE_BREAK_ALLOW;
} else {
return LINE_BREAK_NO;
}
}
#else
/*FIXME:*/
static const wchar_t* no_start_symbols = L",.?!)>:;,。?!》):;";
break_type_t line_break_check(wchar_t c1, wchar_t c2) {
if (wcschr(no_start_symbols, c2) != NULL) {
return LINE_BREAK_NO;
} else if (c1 == '\r' || c1 == '\n') {
return LINE_BREAK_MUST;
} else {
return word_break_check(c1, c2);
}
}
break_type_t word_break_check(wchar_t c1, wchar_t c2) {
if (tk_isspace(c1) || tk_isspace(c2)) {
return LINE_BREAK_ALLOW;
}
return LINE_BREAK_NO;
}
#endif /*WITH_UNICODE_BREAK*/
uint32_t line_break_count(const wchar_t* str) {
uint32_t lines = 1;
const wchar_t* p = str;
while (*p) {
if (*p == '\r') {
p++;
if (*p == '\n') {
p++;
}
lines++;
} else if (*p == '\n') {
p++;
lines++;
} else {
p++;
}
}
return lines;
}
ret_t line_break(const wchar_t* str, line_break_on_line_t on_line, void* ctx) {
uint32_t i = 0;
uint32_t line_len = 0;
const wchar_t* end = str;
const wchar_t* start = str;
uint32_t lines = line_break_count(str);
for (i = 0; (i < lines) && *start; i++) {
while (*end != '\r' && *end != '\n' && *end) {
end++;
}
line_len = end - start;
on_line(ctx, i, start, line_len);
if (*end == '\r') {
end++;
if (*end == '\n') {
end++;
}
} else {
end++;
}
start = end;
}
return RET_OK;
}

View File

@ -0,0 +1,109 @@
/**
* File: line_break.h
* Author: AWTK Develop Team
* Brief: line break and work break algorithm.
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-07-28 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_LINE_BREAK_H
#define TK_LINE_BREAK_H
#include "base/types_def.h"
BEGIN_C_DECLS
typedef ret_t (*line_break_on_line_t)(void* ctx, uint32_t index, const wchar_t* str, uint32_t size);
/**
* @enum line_break_type_t
* @prefix LINE_BREAK_
* 换行类型。
*/
typedef enum _line_break_type_t {
/**
* @const LINE_BREAK_MUST
* 必须换行。
*/
LINE_BREAK_MUST = 0,
/**
* @const LINE_BREAK_ALLOW
* 可以换行。
*/
LINE_BREAK_ALLOW,
/**
* @const LINE_BREAK_NO
* 不可以换行。
*/
LINE_BREAK_NO
} break_type_t,
line_break_type_t;
/**
* @class line_break_check
* 换行相关函数。
* @annotation ["fake"]
*
*/
/**
* @method line_break_check
* 检查两个字符之间是否允许换行。
*
* @param {wchar_t} c1 前面的字符。
* @param {wchar_t} c2 后面的字符。
*
* @return {line_break_type_t} 返回类型。
*/
line_break_type_t line_break_check(wchar_t c1, wchar_t c2);
/**
* @method word_break_check
* 检查两个字符之间是否允许单词分割。
*
* @param {wchar_t} c1 前面的字符。
* @param {wchar_t} c2 后面的字符。
*
* @return {line_break_type_t} 返回类型。
*/
line_break_type_t word_break_check(wchar_t c1, wchar_t c2);
/**
* @method line_break_count
* 统计行数。
*
* @param {const wchar_t*} str 字符串。
*
* @return {uint32_t} 返回行数。
*/
uint32_t line_break_count(const wchar_t* str);
/**
* @method line_break
*
* 解析字符串对于每一行调用on_line函数。
*
* @param {const wchar_t*} str 字符串。
* @param {line_break_on_line_t} on_line 回调函数。
* @param {void*} ctx 回调函数的上下文。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t line_break(const wchar_t* str, line_break_on_line_t on_line, void* ctx);
END_C_DECLS
#endif /*TK_LINE_BREAK_H*/

View File

@ -0,0 +1,216 @@
/**
* File: line_parser.h
* Author: AWTK Develop Team
* Brief: line_parser structs.
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2021-01-8 Luo Zhiming <luozhiming@zlg.cn> created
*
*/
#ifndef TK_LINE_PARSER_H
#define TK_LINE_PARSER_H
#include "tkc/types_def.h"
#include "base/canvas.h"
#include "base/line_break.h"
BEGIN_C_DECLS
typedef struct _line_parser_t {
canvas_t* c;
uint32_t size;
uint32_t width;
uint32_t font_size;
const wchar_t* str;
uint32_t total_lines;
uint32_t total_paragraphs;
uint32_t nline_numbers;
uint32_t cline_numbers;
uint32_t* line_numbers;
uint32_t curr_line_number;
/*current line*/
const wchar_t* line;
uint32_t line_size;
bool_t is_force_break;
bool_t line_wrap;
bool_t word_wrap;
} line_parser_t;
static ret_t line_parser_next(line_parser_t* parser);
static ret_t line_parser_next_impl(line_parser_t* parser);
static ret_t line_parser_deinit(line_parser_t* parser);
static ret_t line_parser_add_line_number(line_parser_t* parser, uint32_t line_number) {
if (parser->nline_numbers + 1 > parser->cline_numbers) {
uint32_t* line_numbers;
uint32_t cline_numbers = parser->nline_numbers + 1 + parser->cline_numbers / 2;
line_numbers = TKMEM_REALLOCT(uint32_t, parser->line_numbers, cline_numbers);
return_value_if_fail(line_numbers != NULL, RET_OOM);
parser->line_numbers = line_numbers;
parser->cline_numbers = cline_numbers;
}
parser->line_numbers[parser->nline_numbers] = line_number;
parser->nline_numbers++;
return RET_OK;
}
static ret_t line_parser_init(line_parser_t* parser, canvas_t* c, const wchar_t* str, uint32_t size,
uint32_t font_size, uint32_t width, bool_t line_wrap,
bool_t word_wrap) {
return_value_if_fail(parser != NULL && str != NULL && size > 0, RET_BAD_PARAMS);
return_value_if_fail(font_size > 0, RET_BAD_PARAMS);
memset(parser, 0x00, sizeof(line_parser_t));
parser->c = c;
parser->str = str;
parser->size = size;
parser->width = width;
parser->font_size = font_size;
parser->line_wrap = line_wrap;
parser->word_wrap = word_wrap;
parser->line = str;
parser->line_size = 0;
parser->is_force_break = FALSE;
while (line_parser_next_impl(parser) == RET_OK) {
if (parser->is_force_break) {
parser->total_paragraphs++;
}
parser->total_lines++;
line_parser_add_line_number(parser, parser->line - str);
}
if (!parser->is_force_break) {
parser->total_paragraphs++;
}
parser->line = str;
parser->line_size = 0;
return RET_OK;
}
static ret_t line_parser_deinit(line_parser_t* parser) {
if (parser != NULL && parser->line_numbers != NULL) {
TKMEM_FREE(parser->line_numbers);
}
return RET_OK;
}
static ret_t line_parser_next(line_parser_t* parser) {
return_value_if_fail(parser->str != NULL, RET_BAD_PARAMS);
if (parser->curr_line_number < parser->nline_numbers) {
uint32_t line_number = parser->curr_line_number++;
parser->line = parser->str + parser->line_numbers[line_number];
if (parser->nline_numbers == 1) {
parser->line_size = wcslen(parser->str);
} else {
if (line_number + 1 < parser->nline_numbers) {
parser->line_size =
parser->line_numbers[line_number + 1] - parser->line_numbers[line_number];
} else {
parser->line_size = wcslen(parser->line);
}
}
return RET_OK;
}
return RET_EOS;
}
static ret_t line_parser_next_impl(line_parser_t* parser) {
int32_t w = 0;
int32_t char_w = 0;
int32_t line_w = 0;
const wchar_t* p = NULL;
canvas_t* c = parser->c;
bool_t is_get_text_width = TRUE;
return_value_if_fail(parser->str != NULL, RET_BAD_PARAMS);
parser->line = parser->line + parser->line_size;
parser->line_size = 0;
if ((parser->line - parser->str) >= parser->size) {
return RET_EOS;
}
p = parser->line;
parser->is_force_break = FALSE;
while ((p - parser->str) < parser->size) {
if (*p == '\r') {
p++;
if (*p == '\n') {
p++;
}
parser->is_force_break = TRUE;
break;
} else if (*p == '\n') {
p++;
parser->is_force_break = TRUE;
break;
}
if (parser->line_wrap) {
if (line_w >= parser->width) {
if (is_get_text_width) {
w = canvas_measure_text(c, parser->line, p - parser->line);
is_get_text_width = FALSE;
}
char_w = canvas_measure_text(c, p, 1) + 1;
if ((w + char_w) > parser->width) {
return_value_if_fail(p > parser->line, RET_FAIL);
if (((p + 1) - parser->str) < parser->size) {
if (parser->word_wrap) {
const wchar_t* tmp_p = p;
while (line_break_check(*(p - 1), *p) == LINE_BREAK_NO) {
if (p == parser->line + 1) {
p = tmp_p;
break;
}
if (p > parser->line) {
p--;
}
}
}
if (tk_isspace(*p)) {
p++;
w += char_w;
}
break;
}
}
w += char_w - 1;
}
p++;
line_w += parser->font_size;
} else {
p++;
}
}
parser->line_size = p - parser->line;
return RET_OK;
}
END_C_DECLS
#endif /*TK_LINE_PARSER_H*/

View File

@ -0,0 +1,197 @@
/**
* File: locale_info.c
* Author: AWTK Develop Team
* Brief: locale_info
*
* Copyright (c) 2018 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-05-02 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/locale_info.h"
static locale_info_t* s_locale = NULL;
static locale_info_t* locale_info_init(locale_info_t* locale_info, const char* language,
const char* country);
static ret_t locale_info_deinit(locale_info_t* locale_info);
locale_info_t* locale_info() {
return s_locale;
}
ret_t locale_info_set(locale_info_t* locale_info) {
s_locale = locale_info;
return RET_OK;
}
locale_info_t* locale_info_create(const char* language, const char* country) {
locale_info_t* locale_info = TKMEM_ZALLOC(locale_info_t);
return locale_info_init(locale_info, language, country);
}
static locale_info_t* locale_info_init(locale_info_t* locale_info, const char* language,
const char* country) {
return_value_if_fail(locale_info != NULL, NULL);
locale_info->emitter = emitter_create();
locale_info_change(locale_info, language, country);
return locale_info;
}
const char* locale_info_tr(locale_info_t* locale_info, const char* text) {
str_table_t* table = NULL;
const char* tr_text = NULL;
return_value_if_fail(locale_info != NULL && text != NULL, text);
return_value_if_fail(locale_info->strs != NULL, text);
table = (str_table_t*)(locale_info->strs->data);
tr_text = str_table_lookup(table, text);
return tr_text != NULL ? tr_text : text;
}
#define DEFAULT_COUNTRY "US"
#define DEFAULT_LANGUAGE "en"
static assets_manager_t* locale_info_get_assets_manager(locale_info_t* locale_info) {
return_value_if_fail(locale_info != NULL, NULL);
return locale_info->assets_manager != NULL ? locale_info->assets_manager : assets_manager();
}
ret_t locale_info_reload(locale_info_t* locale_info) {
char name[16];
assets_manager_t* am = locale_info_get_assets_manager(locale_info);
if (locale_info->strs != NULL) {
assets_manager_unref(am, locale_info->strs);
locale_info->strs = NULL;
/*清除字符串缓存*/
assets_manager_clear_cache(am, ASSET_TYPE_STRINGS);
}
tk_snprintf(name, sizeof(name) - 1, "%s_%s", locale_info->language, locale_info->country);
locale_info->strs = assets_manager_ref(am, ASSET_TYPE_STRINGS, name);
if (locale_info->strs == NULL) {
locale_info->strs = assets_manager_ref(am, ASSET_TYPE_STRINGS, locale_info->language);
}
return RET_OK;
}
ret_t locale_info_change(locale_info_t* locale_info, const char* language, const char* country) {
return_value_if_fail(locale_info != NULL, RET_BAD_PARAMS);
if (country == NULL) {
country = DEFAULT_COUNTRY;
}
if (language == NULL) {
language = DEFAULT_LANGUAGE;
}
if (strcmp(locale_info->country, country) != 0 || strcmp(locale_info->language, language) != 0) {
event_t e = event_init(EVT_LOCALE_CHANGED, locale_info);
tk_strncpy(locale_info->country, country, sizeof(locale_info->country) - 1);
tk_strncpy(locale_info->language, language, sizeof(locale_info->language) - 1);
locale_info_reload(locale_info);
emitter_dispatch(locale_info->emitter, &e);
}
return RET_OK;
}
uint32_t locale_info_on(locale_info_t* locale_info, event_type_t type, event_func_t on_event,
void* ctx) {
return_value_if_fail(locale_info != NULL && on_event != NULL, 0);
type = EVT_LOCALE_CHANGED;
return emitter_on(locale_info->emitter, type, on_event, ctx);
}
ret_t locale_info_off(locale_info_t* locale_info, uint32_t id) {
return_value_if_fail(locale_info != NULL, RET_BAD_PARAMS);
return emitter_off(locale_info->emitter, id);
}
static ret_t locale_info_deinit(locale_info_t* locale_info) {
assets_manager_t* am = locale_info_get_assets_manager(locale_info);
return_value_if_fail(locale_info != NULL, RET_OK);
emitter_destroy(locale_info->emitter);
if (locale_info->strs != NULL) {
assets_manager_unref(am, locale_info->strs);
}
memset(locale_info, 0x00, sizeof(locale_info_t));
return RET_OK;
}
ret_t locale_info_set_assets_manager(locale_info_t* locale_info, assets_manager_t* assets_manager) {
return_value_if_fail(locale_info != NULL && assets_manager != NULL, RET_BAD_PARAMS);
locale_info->assets_manager = assets_manager;
return RET_OK;
}
ret_t locale_info_destroy(locale_info_t* locale_info) {
return_value_if_fail(locale_info != NULL, RET_BAD_PARAMS);
locale_info_deinit(locale_info);
TKMEM_FREE(locale_info);
return RET_OK;
}
const char* str_table_lookup(const str_table_t* table, const char* key) {
int low = 0;
int mid = 0;
int high = 0;
int result = 0;
const char* iter = NULL;
const char* start = (const char*)table;
return_value_if_fail(table != NULL && table->nr > 0 && key != NULL, NULL);
high = table->nr - 1;
while (low <= high) {
mid = low + ((high - low) >> 1);
iter = start + table->strs[mid].key;
result = strcmp(iter, key);
if (result == 0) {
return start + table->strs[mid].value;
} else if (result < 0) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return NULL;
}

Some files were not shown because too many files have changed in this diff Show More