linuxOS_AP06/app/lvgl_demo/gallery/gallery.c
2025-06-03 12:28:32 +08:00

443 lines
13 KiB
C

#include <lvgl/lvgl.h>
#include "gallery.h"
#include "anims/fade_out.h"
#include "anims/fade_slide_out.h"
#include "anims/photo_stream.h"
#include "anims/slide_out.h"
#ifdef USE_OPENGL
#include <lvgl/lv_drivers/sdl/gl/gl.h>
#include "anims/cube_flip.h"
#include "anims/cube_lyric.h"
#include "anims/cube_rotate.h"
#include "anims/fold.h"
#include "anims/roller.h"
#include "anims/stiker.h"
static char *lyric[] =
{
"左面",
"Left",
"右面",
"Right",
"顶面",
"Top",
"底面",
"Bottom",
"前面",
"Front",
"背面",
"Back",
};
int lines = sizeof(lyric) / sizeof(lyric[0]);
lv_gl_tex_t *tex_cube;
lv_gl_tex_t *tex_2d[6];
lv_gl_tex_t *tex_roller;
lv_gl_tex_t *tex_fb;
lv_gl_obj_t *obj_fb;
lv_gl_obj_t *obj_img0;
lv_gl_obj_t *obj_img1;
lv_gl_obj_t *obj_cube;
lv_gl_obj_t *obj_fold[4];
lv_gl_obj_t *obj_roller_items[6];
lv_gl_obj_t *obj_roller;
lyric_row *obj_lyrics;
SDL_Rect view;
SDL_Rect screen;
#endif
int animing = 0;
lv_ft_info_t ttf_main;
lv_obj_t *scr;
lv_obj_t *img1;
lv_obj_t *img2;
lv_obj_t *anim_area;
lv_obj_t *btn_mat;
lv_obj_t *slider;
lv_obj_t *photo_box;
lv_obj_t *photos[6];
static lv_anim_t anims[] =
{
ANIM_FADE_OUT,
ANIM_SLIDE_OUT,
ANIM_FADE_SLIDE_OUT,
#ifdef USE_OPENGL
ANIM_CUBE_ROTATE,
ANIM_CUBE_FLIP,
ANIM_CUBE_LYRIC,
ANIM_FOLD,
ANIM_ROLLER,
ANIM_STIKER,
#endif
ANIM_PHOTO_STREAM,
};
static int anim_cnt = sizeof(anims) / sizeof(anims[0]);
static const char *btnm_map[] = {
"fade out", "slide out", "fade slide", "\n",
#ifdef USE_OPENGL
"cube rotate", "cube flip", "cube lyric", "\n",
"fold", "roller", "stiker", "\n",
#endif
"photo stream", ""
};
static void event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
if(code == LV_EVENT_VALUE_CHANGED) {
uint32_t id = lv_btnmatrix_get_selected_btn(obj);
if (id >= anim_cnt)
return;
if (!animing)
{
lv_anim_start(&anims[id]);
if (anims[id].start_value > anims[id].end_value)
{
lv_slider_set_range(slider,
anims[id].end_value,
anims[id].start_value);
}
else
{
lv_slider_set_range(slider,
anims[id].start_value,
anims[id].end_value);
}
lv_slider_set_value(slider, 0, LV_ANIM_OFF);
animing = 1;
}
}
}
static void font_init(void)
{
printf("%s\n", __func__);
lv_freetype_init(64, 1, 0);
ttf_main.weight = 60;
ttf_main.name = "/usr/share/fonts/source-han-sans-cn/SourceHanSansCN-Regular.otf";
ttf_main.style = FT_FONT_STYLE_NORMAL;
lv_ft_font_init(&ttf_main);
}
static label_canvas *create_canvas(lv_color_t color,
lv_font_t *font)
{
label_canvas *lc;
lc = lv_mem_alloc(sizeof(label_canvas));
if (!lc)
return NULL;
lv_memset_00(lc, sizeof(label_canvas));
lv_draw_label_dsc_init(&lc->label_dsc);
lc->label_dsc.color = color;
lc->label_dsc.font = font;
lc->canvas = lv_canvas_create(NULL);
return lc;
}
#if USE_OPENGL
static lv_gl_obj_t *utf8_to_obj(lv_gl_obj_t *parent,
label_canvas *lc, char *text)
{
lv_img_dsc_t *img_dsc = lc->img_dsc;
lv_gl_obj_t *obj;
lv_gl_tex_t *tex;
lv_gl_img_t img;
lv_coord_t data_size;
lv_point_t size;
lv_txt_get_size(&size, text, lc->label_dsc.font,
0, 0, LV_COORD_MAX, 0);
data_size = lv_img_buf_get_img_size(ALIGN(size.x, 16),
ALIGN(size.y, 16), LV_IMG_CF_TRUE_COLOR_ALPHA);
if (!img_dsc ||
data_size > img_dsc->data_size)
{
if (img_dsc)
lv_img_buf_free(img_dsc);
img_dsc = lv_img_buf_alloc(ALIGN(size.x, 16),
ALIGN(size.y, 16), LV_IMG_CF_TRUE_COLOR_ALPHA);
lc->img_dsc = img_dsc;
printf("new buf %p\n", img_dsc);
}
else
{
lv_memset_00((uint8_t *)img_dsc->data,
img_dsc->data_size);
}
lv_canvas_set_buffer(lc->canvas, (void *)img_dsc->data,
ALIGN(size.x, 16), ALIGN(size.y, 16),
img_dsc->header.cf);
lv_canvas_draw_text(lc->canvas,
((ALIGN(size.x, 16) - size.x) / 2),
((ALIGN(size.y, 16) - size.y) / 2),
ALIGN(size.x, 16), &lc->label_dsc, text);
img.pixels = img_dsc->data;
img.format = LV_GL_FMT_BGRA;
img.w = ALIGN(size.x, 16);
img.h = ALIGN(size.y, 16);
obj = lv_gl_obj_create(img.w, img.h);
tex = lv_gl_tex_create(GL_TEX_TYPE_2D, 0, 0, &img);
lv_gl_obj_bind_tex(obj, tex);
return obj;
}
#endif
void common_anim_start(void)
{
lv_obj_add_flag(anim_area, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(img1, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(img2, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(photo_box, LV_OBJ_FLAG_HIDDEN);
anim_photo_stream_stop();
#if USE_OPENGL
lv_gl_set_render_cb(NULL);
lv_gl_obj_set_viewport(NULL, &view);
lv_gl_obj_set_crop(NULL, NULL, 0);
#endif
}
#if USE_OPENGL
static void tex_init(void)
{
lv_gl_img_t imgs[6];
imgs[CUBE_LEFT].format = LV_GL_FMT_BGRA;
imgs[CUBE_LEFT].pixels = pic1.data;
imgs[CUBE_LEFT].w = pic1.header.w;
imgs[CUBE_LEFT].h = pic1.header.h;
imgs[CUBE_RIGHT].format = LV_GL_FMT_BGRA;
imgs[CUBE_RIGHT].pixels = pic2.data;
imgs[CUBE_RIGHT].w = pic2.header.w;
imgs[CUBE_RIGHT].h = pic2.header.h;
imgs[CUBE_TOP].format = LV_GL_FMT_BGRA;
imgs[CUBE_TOP].pixels = pic3.data;
imgs[CUBE_TOP].w = pic3.header.w;
imgs[CUBE_TOP].h = pic3.header.h;
imgs[CUBE_BOTTOM].format = LV_GL_FMT_BGRA;
imgs[CUBE_BOTTOM].pixels = pic4.data;
imgs[CUBE_BOTTOM].w = pic4.header.w;
imgs[CUBE_BOTTOM].h = pic4.header.h;
imgs[CUBE_FRONT].format = LV_GL_FMT_BGRA;
imgs[CUBE_FRONT].pixels = pic5.data;
imgs[CUBE_FRONT].w = pic5.header.w;
imgs[CUBE_FRONT].h = pic5.header.h;
imgs[CUBE_BACK].format = LV_GL_FMT_BGRA;
imgs[CUBE_BACK].pixels = pic6.data;
imgs[CUBE_BACK].w = pic6.header.w;
imgs[CUBE_BACK].h = pic6.header.h;
tex_cube = lv_gl_tex_create(GL_TEX_TYPE_CUBE, 0, 0, imgs);
tex_2d[0] = lv_gl_tex_create(GL_TEX_TYPE_2D, 0, 0, &imgs[0]);
tex_2d[1] = lv_gl_tex_create(GL_TEX_TYPE_2D, 0, 0, &imgs[1]);
tex_2d[2] = lv_gl_tex_create(GL_TEX_TYPE_2D, 0, 0, &imgs[2]);
tex_2d[3] = lv_gl_tex_create(GL_TEX_TYPE_2D, 0, 0, &imgs[3]);
tex_2d[4] = lv_gl_tex_create(GL_TEX_TYPE_2D, 0, 0, &imgs[4]);
tex_2d[5] = lv_gl_tex_create(GL_TEX_TYPE_2D, 0, 0, &imgs[5]);
}
#endif
void gallery(void)
{
font_init();
scr = lv_scr_act();
lv_obj_clear_flag(scr, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_refr_size(scr);
anim_area = lv_obj_create(scr);
lv_obj_remove_style_all(anim_area);
lv_obj_set_size(anim_area, lv_pct(100), lv_pct(80));
lv_obj_align(anim_area, LV_ALIGN_TOP_MID, 0, 0);
img1 = lv_img_create(anim_area);
lv_img_set_src(img1, (void *)&pic1);
lv_obj_center(img1);
img2 = lv_img_create(anim_area);
lv_img_set_src(img2, (void *)&pic2);
lv_obj_center(img2);
btn_mat = lv_btnmatrix_create(scr);
lv_obj_set_size(btn_mat, lv_pct(100), lv_pct(20));
lv_btnmatrix_set_map(btn_mat, btnm_map);
lv_obj_align(btn_mat, LV_ALIGN_BOTTOM_MID, 0, 0);
lv_obj_add_event_cb(btn_mat, event_handler,
LV_EVENT_ALL, NULL);
lv_obj_refr_size(btn_mat);
slider = lv_slider_create(scr);
lv_obj_set_style_bg_opa(slider, LV_OPA_TRANSP,
LV_PART_KNOB);
lv_obj_set_size(slider, lv_pct(100), 2);
lv_slider_set_range(slider, 0, 100);
lv_slider_set_value(slider, 0, LV_ANIM_ON);
lv_obj_align(slider, LV_ALIGN_BOTTOM_MID, 0, 0);
#ifdef USE_OPENGL
screen.x = 0;
screen.y = 0;
screen.w = lv_obj_get_width(scr);
screen.h = lv_obj_get_height(scr);
view.x = 0;
view.y = lv_obj_get_height(btn_mat);
view.w = lv_obj_get_width(scr);
view.h = lv_obj_get_height(scr) - view.y;
printf("view %d %d %d %d\n", view.x, view.y, view.w, view.h);
lv_gl_obj_set_viewport(NULL, &view);
tex_init();
obj_cube = lv_gl_obj_create(480, 480);
lv_gl_obj_bind_tex(obj_cube, tex_cube);
printf("cube %p\n", obj_cube);
obj_fold[0] = lv_gl_obj_create(screen.w / 2, screen.w);
obj_fold[1] = lv_gl_obj_create(screen.w / 2, screen.w);
obj_fold[2] = lv_gl_obj_create(screen.w / 2, screen.w);
obj_fold[3] = lv_gl_obj_create(screen.w / 2, screen.w);
lv_gl_obj_bind_tex(obj_fold[0], tex_2d[0]);
lv_gl_obj_bind_tex(obj_fold[1], tex_2d[0]);
lv_gl_obj_bind_tex(obj_fold[2], tex_2d[1]);
lv_gl_obj_bind_tex(obj_fold[3], tex_2d[1]);
printf("fold %p %p %p %p\n", obj_fold[0], obj_fold[1],
obj_fold[2], obj_fold[3]);
obj_fb = lv_gl_obj_create(480, 480);
obj_fb->scale.x = (float)obj_fb->base.w / view.w;
obj_fb->scale.y = (float)obj_fb->base.h / view.h;
obj_img0 = lv_gl_obj_create(120, 120);
obj_img1 = lv_gl_obj_create(480, 480);
tex_fb = lv_gl_tex_create(GL_TEX_TYPE_2D, 480, 480, NULL);
lv_gl_obj_resize(obj_img0, obj_fb);
lv_gl_obj_resize(obj_img1, obj_fb);
lv_gl_obj_bind_tex(obj_img0, tex_2d[0]);
lv_gl_obj_bind_tex(obj_img1, tex_2d[1]);
lv_gl_obj_bind_tex(obj_fb, tex_fb);
obj_roller = lv_gl_obj_create(480, 480);
lv_gl_obj_resize(obj_roller, NULL);
tex_roller = lv_gl_tex_create(GL_TEX_TYPE_2D, 480, 480, NULL);
lv_gl_obj_bind_tex(obj_roller, tex_roller);
lv_gl_set_fb(obj_roller);
for (int i = 0; i < 6; i++)
{
obj_roller_items[i] = lv_gl_obj_create(240, 480);
lv_gl_obj_resize(obj_roller_items[i], obj_roller);
lv_gl_obj_bind_tex(obj_roller_items[i], tex_2d[i]);
/* the full image size is 480x480, just use 240x480 at [120, 0]*/
obj_roller_items[i]->tp.x = 120;
obj_roller_items[i]->tp.w = 240;
lv_gl_obj_update_vao(obj_roller_items[i]);
obj_roller_items[i]->self_rot.y = (360.0 / 6.0) * i;
}
lv_gl_set_fb(NULL);
printf("roller %p\n", obj_roller);
label_canvas *lc =
create_canvas(lv_palette_main(LV_PALETTE_ORANGE),
ttf_main.font);
obj_lyrics = lv_mem_alloc(lines * sizeof(*obj_lyrics));
for (int i = 0; i < lines; i++)
{
uint32_t byte_id = 0;
uint32_t last_byte_id = 0;
uint32_t word;
uint32_t words = 0;
char buf[32];
while (1)
{
word = _lv_txt_encoded_next(lyric[i], &byte_id);
if (!word)
break;
words++;
}
obj_lyrics[i].objs =
lv_mem_alloc(words * sizeof(lv_gl_obj_t *));
obj_lyrics[i].len = words;
byte_id = 0;
for (int j = 0; j < words; j++)
{
last_byte_id = byte_id;
_lv_txt_encoded_next(lyric[i], &byte_id);
memcpy(buf, lyric[i] + last_byte_id,
byte_id - last_byte_id);
buf[byte_id - last_byte_id] = 0;
obj_lyrics[i].objs[j] =
utf8_to_obj(obj_cube, lc, buf);
lv_gl_obj_resize(obj_lyrics[i].objs[j], obj_cube);
}
}
float box_w, box_h;
float start_x, start_y;
for (int idx = CUBE_LEFT; idx <= CUBE_BACK; idx++)
{
box_h = 2 * (obj_lyrics[idx].objs[0]->scale.y * 2.0);
start_y = obj_lyrics[0].objs[0]->scale.y + (2.0 - box_h) / 2 - 1.0;
for (int i = 0; i < 2; i++)
{
box_w = obj_lyrics[idx * 2 + i].len *
(obj_lyrics[idx * 2 + i].objs[0]->scale.x * 2.0);
for (int j = 0; j < obj_lyrics[idx * 2 + i].len; j++)
{
start_x = (2.0 - box_w) / 2 - 1.0;
obj_lyrics[idx * 2 + i].objs[j]->out_type =
GL_TEXTURE_CUBE_MAP_POSITIVE_X + idx;
obj_lyrics[idx * 2 + i].objs[j]->move.x = start_x +
j * (obj_lyrics[i].objs[0]->scale.x * 2.0);
obj_lyrics[idx * 2 + i].objs[j]->move.y = start_y +
i * (obj_lyrics[i].objs[0]->scale.y * 2.0);
}
}
}
#endif
photo_box = lv_obj_create(anim_area);
lv_obj_remove_style_all(photo_box);
lv_obj_set_size(photo_box, lv_pct(100), lv_pct(100));
lv_obj_refr_size(anim_area);
lv_obj_refr_size(photo_box);
lv_obj_add_flag(photo_box, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(photo_box, LV_OBJ_FLAG_SCROLLABLE);
for (int i = 0; i < 6; i++)
{
photos[i] = lv_img_create(photo_box);
lv_obj_set_pos(photos[i],
(lv_obj_get_width(photo_box) - pic1.header.w) / 2, 500 * i);
}
lv_img_set_src(photos[0], &pic1);
lv_img_set_src(photos[1], &pic2);
lv_img_set_src(photos[2], &pic3);
lv_img_set_src(photos[3], &pic4);
lv_img_set_src(photos[4], &pic5);
lv_img_set_src(photos[5], &pic6);
}