1 /**
2 * @file lv_gifenc.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "lv_gif_private.h"
10 #if LV_USE_GIF
11 #include "../../misc/lv_timer_private.h"
12 #include "../../misc/cache/lv_image_cache.h"
13 #include "../../core/lv_obj_class_private.h"
14
15 #include "gifdec.h"
16
17 /*********************
18 * DEFINES
19 *********************/
20 #define MY_CLASS (&lv_gif_class)
21
22 /**********************
23 * TYPEDEFS
24 **********************/
25
26 /**********************
27 * STATIC PROTOTYPES
28 **********************/
29 static void lv_gif_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
30 static void lv_gif_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
31 static void next_frame_task_cb(lv_timer_t * t);
32
33 /**********************
34 * STATIC VARIABLES
35 **********************/
36
37 const lv_obj_class_t lv_gif_class = {
38 .constructor_cb = lv_gif_constructor,
39 .destructor_cb = lv_gif_destructor,
40 .instance_size = sizeof(lv_gif_t),
41 .base_class = &lv_image_class,
42 .name = "gif",
43 };
44
45 /**********************
46 * MACROS
47 **********************/
48
49 /**********************
50 * GLOBAL FUNCTIONS
51 **********************/
52
lv_gif_create(lv_obj_t * parent)53 lv_obj_t * lv_gif_create(lv_obj_t * parent)
54 {
55
56 LV_LOG_INFO("begin");
57 lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
58 lv_obj_class_init_obj(obj);
59 return obj;
60 }
61
lv_gif_set_src(lv_obj_t * obj,const void * src)62 void lv_gif_set_src(lv_obj_t * obj, const void * src)
63 {
64 lv_gif_t * gifobj = (lv_gif_t *) obj;
65 gd_GIF * gif = gifobj->gif;
66
67 /*Close previous gif if any*/
68 if(gif != NULL) {
69 lv_image_cache_drop(lv_image_get_src(obj));
70
71 gd_close_gif(gif);
72 gifobj->gif = NULL;
73 gifobj->imgdsc.data = NULL;
74 }
75
76 if(lv_image_src_get_type(src) == LV_IMAGE_SRC_VARIABLE) {
77 const lv_image_dsc_t * img_dsc = src;
78 gif = gd_open_gif_data(img_dsc->data);
79 }
80 else if(lv_image_src_get_type(src) == LV_IMAGE_SRC_FILE) {
81 gif = gd_open_gif_file(src);
82 }
83 if(gif == NULL) {
84 LV_LOG_WARN("Couldn't load the source");
85 return;
86 }
87
88 gifobj->gif = gif;
89 gifobj->imgdsc.data = gif->canvas;
90 gifobj->imgdsc.header.magic = LV_IMAGE_HEADER_MAGIC;
91 gifobj->imgdsc.header.flags = LV_IMAGE_FLAGS_MODIFIABLE;
92 gifobj->imgdsc.header.cf = LV_COLOR_FORMAT_ARGB8888;
93 gifobj->imgdsc.header.h = gif->height;
94 gifobj->imgdsc.header.w = gif->width;
95 gifobj->imgdsc.header.stride = gif->width * 4;
96 gifobj->imgdsc.data_size = gif->width * gif->height * 4;
97
98 gifobj->last_call = lv_tick_get();
99
100 lv_image_set_src(obj, &gifobj->imgdsc);
101
102 lv_timer_resume(gifobj->timer);
103 lv_timer_reset(gifobj->timer);
104
105 next_frame_task_cb(gifobj->timer);
106
107 }
108
lv_gif_restart(lv_obj_t * obj)109 void lv_gif_restart(lv_obj_t * obj)
110 {
111 lv_gif_t * gifobj = (lv_gif_t *) obj;
112
113 if(gifobj->gif == NULL) {
114 LV_LOG_WARN("Gif resource not loaded correctly");
115 return;
116 }
117
118 gd_rewind(gifobj->gif);
119 lv_timer_resume(gifobj->timer);
120 lv_timer_reset(gifobj->timer);
121 }
122
lv_gif_pause(lv_obj_t * obj)123 void lv_gif_pause(lv_obj_t * obj)
124 {
125 lv_gif_t * gifobj = (lv_gif_t *) obj;
126 lv_timer_pause(gifobj->timer);
127 }
128
lv_gif_resume(lv_obj_t * obj)129 void lv_gif_resume(lv_obj_t * obj)
130 {
131 lv_gif_t * gifobj = (lv_gif_t *) obj;
132
133 if(gifobj->gif == NULL) {
134 LV_LOG_WARN("Gif resource not loaded correctly");
135 return;
136 }
137
138 lv_timer_resume(gifobj->timer);
139 }
140
lv_gif_is_loaded(lv_obj_t * obj)141 bool lv_gif_is_loaded(lv_obj_t * obj)
142 {
143 lv_gif_t * gifobj = (lv_gif_t *) obj;
144
145 return (gifobj->gif != NULL);
146 }
147
lv_gif_get_loop_count(lv_obj_t * obj)148 int32_t lv_gif_get_loop_count(lv_obj_t * obj)
149 {
150 lv_gif_t * gifobj = (lv_gif_t *) obj;
151
152 if(gifobj->gif == NULL) {
153 return -1;
154 }
155
156 return gifobj->gif->loop_count;
157 }
158
lv_gif_set_loop_count(lv_obj_t * obj,int32_t count)159 void lv_gif_set_loop_count(lv_obj_t * obj, int32_t count)
160 {
161 lv_gif_t * gifobj = (lv_gif_t *) obj;
162
163 if(gifobj->gif == NULL) {
164 LV_LOG_WARN("Gif resource not loaded correctly");
165 return;
166 }
167
168 gifobj->gif->loop_count = count;
169 }
170
171 /**********************
172 * STATIC FUNCTIONS
173 **********************/
174
lv_gif_constructor(const lv_obj_class_t * class_p,lv_obj_t * obj)175 static void lv_gif_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
176 {
177 LV_UNUSED(class_p);
178
179 lv_gif_t * gifobj = (lv_gif_t *) obj;
180
181 gifobj->gif = NULL;
182 gifobj->timer = lv_timer_create(next_frame_task_cb, 10, obj);
183 lv_timer_pause(gifobj->timer);
184 }
185
lv_gif_destructor(const lv_obj_class_t * class_p,lv_obj_t * obj)186 static void lv_gif_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
187 {
188 LV_UNUSED(class_p);
189 lv_gif_t * gifobj = (lv_gif_t *) obj;
190
191 lv_image_cache_drop(lv_image_get_src(obj));
192
193 if(gifobj->gif)
194 gd_close_gif(gifobj->gif);
195 lv_timer_delete(gifobj->timer);
196 }
197
next_frame_task_cb(lv_timer_t * t)198 static void next_frame_task_cb(lv_timer_t * t)
199 {
200 lv_obj_t * obj = t->user_data;
201 lv_gif_t * gifobj = (lv_gif_t *) obj;
202 uint32_t elaps = lv_tick_elaps(gifobj->last_call);
203 if(elaps < gifobj->gif->gce.delay * 10) return;
204
205 gifobj->last_call = lv_tick_get();
206
207 int has_next = gd_get_frame(gifobj->gif);
208 if(has_next == 0) {
209 /*It was the last repeat*/
210 lv_result_t res = lv_obj_send_event(obj, LV_EVENT_READY, NULL);
211 lv_timer_pause(t);
212 if(res != LV_RESULT_OK) return;
213 }
214
215 gd_render_frame(gifobj->gif, (uint8_t *)gifobj->imgdsc.data);
216
217 lv_image_cache_drop(lv_image_get_src(obj));
218 lv_obj_invalidate(obj);
219 }
220
221 #endif /*LV_USE_GIF*/
222