Closed V1ki closed 5 years ago
这样做的目的是什么?
在海思平台下录像,需要做OSD ,想将文字转换成 图片数据后,然后画在region 中.
这样做的目的是什么?
另外 我看awtk 中有canvas ,最初的设想是画到canvas 中,然后将canvas 转换成 位图数据,但是发现 canvas 好像没有此类方法,所以看有没有其他的快捷的方法.
这样做的目的是什么?
在浏览canvas 的代码中发现可以通过lcd_mem 来创建lcd,并初始化canvas,然后将文字画到canvas 中,最后将lcd 中的buff写入到region 中. 不知这种方法是否可行,我先测试一下.
这样做的目的是什么?
canvas_t canvas;
font_manager_t font_manager;
font_manager_init(&font_manager, NULL);
uint8_t* region_datas = (uint8_t*)(stBitmap.pData);
lcd_t* lcd = lcd_mem_rgba8888_create_single_fb(64, 64, region_datas);
canvas_t* c = canvas_init(&canvas, lcd, &font_manager);
ret_t ret = RET_FAIL;
color_t fill_color = color_init(0xff, 0xff, 0xff, 0xff);
rect_t r = rect_init(0, 0, 64, 64);
canvas_begin_frame(c, &r, LCD_DRAW_NORMAL);
ret = canvas_set_fill_color(c, fill_color);
printf("canvas_set_fill_color:%d\n", ret);
ret = canvas_fill_rect(c, 0, 0, 64, 64);
printf("canvas_fill_rect:%d\n", ret);
canvas_draw_text(c, L"Hello AWTK", 10, 20, 20);
// printf("canvas_draw_text:%d\n", ret);
color_t color = lcd_get_point_color(c->lcd, 10, 10);
printf("color:%#x -- fill_color:%#x\n", color.color, fill_color.color);
canvas_end_frame(&canvas);
单独显示颜色已经可以,但是 在draw_text的时候,出现了 Segmentation fault
了.
发现崩溃出现在:
static ret_t canvas_draw_text_impl(canvas_t* c, const wchar_t* str, uint32_t nr, xy_t x, xy_t y) {
glyph_t g;
uint32_t i = 0;
xy_t left = x;
printf("111111111111111111111111\n");
uint32_t start_time = time_now_ms();
printf("2222222222222222222222\n");
font_size_t font_size = c->font_size;
y -= font_size * 1 / 3;
for (i = 0; i < nr; i++) {
wchar_t chr = str[i];
if (chr == ' ') {
x += 4;
} else if (chr == '\r') {
if (str[i + 1] != '\n') {
y += font_size;
x = left;
}
} else if (chr == '\r') {
y += font_size;
x = left;
} else if (font_get_glyph(c->font, chr, c->font_size, &g) == RET_OK) {
xy_t xx = x + g.x;
xy_t yy = y + font_size + g.y;
canvas_draw_glyph(c, &g, xx, yy);
x += g.advance + 1;
} else {
x += 4;
}
}
y = time_now_ms() - start_time;
return RET_OK;
}
1 和2 中间的 time_now_ms
里了 . 下面的是报错日志:
canvas_set_fill_color:0
canvas_fill_rect:0
111111111111111111111111
Segmentation fault
大概是因为我没有在系统初始化之前继续调用?
使用font manager全局对象试试:
canvas_t* c = canvas_init(&canvas, lcd, font_manager());
使用font manager全局对象试试:
canvas_t* c = canvas_init(&canvas, lcd, font_manager());
目前我将update 的方法放在tk_thread 中进行执行.
tk_thread_t* thread = tk_thread_create(osd_thread_entry, NULL);
tk_thread_start(thread);
canvas_t canvas;
// font_manager_t font_manager;
// font_manager_init(&font_manager, NULL);
uint8_t* region_datas = (uint8_t*)(stBitmap.pData);
lcd_t* lcd = lcd_mem_rgba8888_create_single_fb(64, 64, region_datas);
canvas_t* c = canvas_init(&canvas, lcd, font_manager());
ret_t ret = RET_FAIL;
color_t fill_color = color_init(0x0, 0x0, 0x0, 0xff);
rect_t r = rect_init(0, 0, 64, 64);
canvas_begin_frame(c, &r, LCD_DRAW_NORMAL);
ret = canvas_set_fill_color(c, fill_color);
printf("canvas_set_fill_color:%d\n", ret);
ret = canvas_fill_rect(c, 0, 0, 64, 64);
printf("canvas_fill_rect:%d\n", ret);
canvas_draw_text(c, L"Hello AWTK", 10, 20, 20);
// printf("canvas_draw_text:%d\n", ret);
color_t color = lcd_get_point_color(c->lcd, 10, 10);
printf("color:%#x -- fill_color:%#x\n", color.color, fill_color.color);
canvas_end_frame(&canvas);
使用的是font manager 的全局对象,但是还是会出现 Segmentation fault
,日志如下:
window main open
111111111111111111111111
2222222222222222222222
111111111111111111111111
HI_MPI_RGN_GetCanvasInfo Success! canvas.size:(64,64) u32Stride:128--
canvas_set_fill_color:0
canvas_fill_rect:0
111111111111111111111111
2222222222222222222222
font_get_glyph:26 f != NULL && f->get_glyph != NULL && g != NULL
font_get_glyph:26 f != NULL && f->get_glyph != NULL && g != NULL
font_get_glyph:26 f != NULL && f->get_glyph != NULL && g != NULL
font_get_glyph:26 f != NULL && f->get_glyph != NULL && g != NULL
font_get_glyph:26 f != NULL && f->get_glyph != NULL && g != NULL
font_get_glyph:26 f != NULL && f->get_glyph != NULL && g != NULL
font_get_glyph:26 f != NULL && f->get_glyph != NULL && g != NULL
font_get_glyph:26 f != NULL && f->get_glyph != NULL && g != NULL
font_get_glyph:26 f != NULL && f->get_glyph != NULL && g != NULL
color:0xff000000 -- fill_color:0xff000000
HI_MPI_RGN_UpdateCanvas Success!
2222222222222222222222
111111111111111111111111
2222222222222222222222
111111111111111111111111
2222222222222222222222
111111111111111111111111
2222222222222222222222
111111111111111111111111
2222222222222222222222
111111111111111111111111
2222222222222222222222
111111111111111111111111
2222222222222222222222
111111111111111111111111
2222222222222222222222
111111111111111111111111
2222222222222222222222
111111111111111111111111
2222222222222222222222
Segmentation fault
感觉很像是tk_thread 执行完成后出的错误.
感觉很像是tk_thread 执行完成后出的错误.
排查了一下,并不是 tk_thread 执行完成的问题, 那 是 font 的问题 ?
设置字体之后,运行正常。
canvas_set_font(c, NULL, 18);
设置字体之后,运行正常。
canvas_set_font(c, NULL, 18);
这个我之前有试过,但是还是不行,依旧会出现 Segmentation fault
设置字体之后,运行正常。
canvas_set_font(c, NULL, 18);
我将之前加上的 111,222给删除了,另外 在font中加上了ch : %c 的打印
ret_t font_get_glyph(font_t* f, wchar_t chr, font_size_t font_size, glyph_t* g) {
printf("chr:%c\n",chr);
return_value_if_fail(f != NULL && f->get_glyph != NULL && g != NULL, RET_BAD_PARAMS);
return f->get_glyph(f, chr, font_size, g);
}
报错日志如下:
canvas_set_fill_color:0
canvas_fill_rect:0
chr:H
Segmentation fault
实现代码如下:
void* osd_thread_entry(void* args) {
// while (TRUE) {
s32Ret = HI_MPI_RGN_GetAttr(Handle, &stRgnAttrSet);
if (HI_SUCCESS != s32Ret) {
printf("HI_MPI_RGN_GetAttr failed! s32Ret: 0x%x.\n", s32Ret);
return;
}
s32Ret = HI_MPI_RGN_GetCanvasInfo(Handle, &stCanvasInfo);
if (HI_SUCCESS != s32Ret) {
printf("HI_MPI_RGN_GetCanvasInfo failed! s32Ret: 0x%x.\n", s32Ret);
return;
}
printf("HI_MPI_RGN_GetCanvasInfo Success! canvas.size:(%d,%d) u32Stride:%d-- \n",
stCanvasInfo.stSize.u32Width, stCanvasInfo.stSize.u32Height, stCanvasInfo.u32Stride);
stBitmap.pData = (HI_VOID*)stCanvasInfo.u32VirtAddr;
stSize.u32Width = stCanvasInfo.stSize.u32Width;
stSize.u32Height = stCanvasInfo.stSize.u32Height;
canvas_t canvas;
// font_manager_t* fontm = font_manager();
//font_manager_add_font(font_manager(), font_dummy_0("demo0", 10));
// font_manager_init(&font_manager, NULL);
uint8_t* region_datas = (uint8_t*)(stBitmap.pData);
lcd_t* lcd = lcd_mem_rgba8888_create_single_fb(64, 64, region_datas);
canvas_t* c = canvas_init(&canvas, lcd, font_manager());
ret_t ret = RET_FAIL;
color_t fill_color = color_init(0x0, 0x0, 0x0, 0xff);
rect_t r = rect_init(0, 0, 64, 64);
canvas_begin_frame(c, &r, LCD_DRAW_NORMAL);
canvas_set_font(c, NULL, 20);
color_t tc = color_init(0, 0, 0, 0xff);
canvas_set_text_color(c, tc);
ret = canvas_set_fill_color(c, fill_color);
printf("canvas_set_fill_color:%d\n", ret);
ret = canvas_fill_rect(c, 0, 0, 64, 64);
printf("canvas_fill_rect:%d\n", ret);
canvas_draw_text(c, L"Hello AWTK", 10, 20, 20);
// printf("canvas_draw_text:%d\n", ret);
color_t color = lcd_get_point_color(c->lcd, 10, 10);
printf("color:%#x -- fill_color:%#x\n", color.color, fill_color.color);
canvas_end_frame(&canvas);
// font_manager_deinit(&font_manager);
//lcd_destroy(lcd);
s32Ret = HI_MPI_RGN_UpdateCanvas(Handle);
if (HI_SUCCESS != s32Ret) {
printf("HI_MPI_RGN_UpdateCanvas failed! s32Ret: 0x%x.\n", s32Ret);
return;
}
printf("HI_MPI_RGN_UpdateCanvas Success! \n");
return NULL ;
// }
}
#ifdef USE_GUI_MAIN
int gui_app_start(int lcd_w, int lcd_h) {
tk_init(lcd_w, lcd_h, APP_MOBILE, NULL, NULL);
#else
#ifdef WIN32
#include <windows.h>
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) {
#else
int main(void) {
#endif
int lcd_w = 800;
int lcd_h = 480;
#if defined(LCD_W) && defined(LCD_H)
lcd_w = LCD_W;
lcd_h = LCD_H;
#endif
lcd_w = 720;
lcd_h = 576;
Hi_OPENFB();
#ifdef WITH_FS_RES
char res_root[MAX_PATH + 1];
char app_root[MAX_PATH + 1];
path_app_root(app_root);
memset(res_root, 0x00, sizeof(res_root));
path_build(res_root, MAX_PATH, app_root, "res", NULL);
LOG("res_root:%s lcd_w:%d lcd_h:%d\n", res_root, lcd_w, lcd_h);
tk_init(lcd_w, lcd_h, APP_MOBILE, NULL, res_root);
#else
tk_init(lcd_w, lcd_h, APP_MOBILE, NULL, NULL);
#endif
#endif
//#define WITH_LCD_PORTRAIT 1
#if defined(USE_GUI_MAIN) && 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*/
/* 初始化资源 */
assets_init();
/* 初始化扩展控件 */
tk_ext_widgets_init();
/* 打开主屏幕 */
//application_init();
// tk_thread_t* thread = tk_thread_create(venc_thread_entry, NULL);
// tk_thread_start(thread);
tk_thread_t* thread = tk_thread_create(osd_thread_entry, "args");
tk_thread_start(thread);
/* 进入awtk事件循环 */
tk_run();
return 0;
}
我在canvas.c
及 font.c
中加上了一些打印. 报错日志如下:
canvas_set_fill_color:0
canvas_fill_rect:0
start_time:2151426
font_size:18
font_get_glyph font_name:default -- chr:H
Segmentation fault
加的打印如下 .
static ret_t canvas_draw_text_impl(canvas_t* c, const wchar_t* str, uint32_t nr, xy_t x, xy_t y) {
glyph_t g;
uint32_t i = 0;
xy_t left = x;
uint32_t start_time = time_now_ms();
printf("start_time:%d\n",start_time);
font_size_t font_size = c->font_size;
printf("font_size:%d\n",font_size);
y -= font_size * 1 / 3;
for (i = 0; i < nr; i++) {
wchar_t chr = str[i];
if (chr == ' ') {
x += 4;
} else if (chr == '\r') {
if (str[i + 1] != '\n') {
y += font_size;
x = left;
}
} else if (chr == '\r') {
y += font_size;
x = left;
} else if (font_get_glyph(c->font, chr, c->font_size, &g) == RET_OK) {
xy_t xx = x + g.x;
xy_t yy = y + font_size + g.y;
printf("before canvas_draw_glyph:(%d,%d)\n",xx, yy);
canvas_draw_glyph(c, &g, xx, yy);
x += g.advance + 1;
} else {
x += 4;
}
}
y = time_now_ms() - start_time;
return RET_OK;
}
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);
printf("font_get_glyph font_name:%s -- chr:%c\n",f->name,chr);
return f->get_glyph(f, chr, font_size, g);
}
可以看到 before canvas_draw_glyph
并没有打印出来.
定位到问题, @xianjimli 日志如下:
canvas_set_fill_color:0
canvas_fill_rect:0
start_time:1525029
font_size:18
font_get_glyph font_name:default -- chr:H
font_stb_get_glyph -- font_name:default -- chr:H
stbtt_ScaleForPixelHeight -- scale:0.006659 -- sf->numGlyphs:100
glyph_cache_lookup --- glyph_t:(-128,94) -- cache->size:0
Segmentation fault
发现问题出在 font_loader_stb.c
中的font_stb_get_glyph
方法里, stbtt_GetCodepointBitmap
的时候出现了该问题,
static ret_t font_stb_get_glyph(font_t* f, wchar_t c, font_size_t font_size, glyph_t* g) {
int x = 0;
int y = 0;
int w = 0;
int h = 0;
int lsb = 0;
int advance = 0;
printf("font_stb_get_glyph -- font_name:%s -- chr:%c\n",f->name,c);
font_stb_t* font = (font_stb_t*)f;
stbtt_fontinfo* sf = &(font->stb_font);
float scale = stbtt_ScaleForPixelHeight(sf, font_size);
printf("stbtt_ScaleForPixelHeight -- scale:%f -- sf->numGlyphs:%d\n",scale,sf->numGlyphs);
if (glyph_cache_lookup(&(font->cache), c, font_size, g) == RET_OK) {
return RET_OK;
}
g->data = stbtt_GetCodepointBitmap(sf, 0, scale, c, &w, &h, &x, &y);
printf("stbtt_GetCodepointBitmap -- [w,h,x,y] : [%d,%d,%d,%d]\n",w,h,x,y);
stbtt_GetCodepointHMetrics(sf, c, &advance, &lsb);
printf("stbtt_GetCodepointHMetrics -- advance:%d -- lsb:%d\n",advance,lsb);
g->x = x;
g->y = y;
g->w = w;
g->h = h;
g->advance = advance * scale;
if (g->data != NULL) {
glyph_t* gg = glyph_clone(g);
if (gg != NULL) {
printf("before glyph_cache_add \n");
glyph_cache_add(&(font->cache), c, font_size, gg);
} else {
STBTT_free(g->data, NULL);
log_warn("out of memory\n");
g->data = NULL;
}
}
return g->data != NULL ? RET_OK : RET_NOT_FOUND;
}
应该如何解决.
你放到UI线程试一下。
我直接放在main
中的时候,发现还是会出现, main
中 不是UI线程吗?
昨天我放在button的click事件里,测试是正常的。
准备使用SDL_ttf来完成OSD相关功能了.
如何快速将文字转换成图片? 库中是否有相应的工具函数?