1 /**
2 * @file lv_snapshot.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "../../draw/lv_draw_private.h"
10 #include "../../core/lv_obj_draw_private.h"
11 #include "lv_snapshot.h"
12 #if LV_USE_SNAPSHOT
13
14 #include <stdbool.h>
15 #include "../../display/lv_display.h"
16 #include "../../core/lv_refr_private.h"
17 #include "../../display/lv_display_private.h"
18 #include "../../stdlib/lv_string.h"
19
20 /*********************
21 * DEFINES
22 *********************/
23
24 /**********************
25 * TYPEDEFS
26 **********************/
27
28 /**********************
29 * STATIC PROTOTYPES
30 **********************/
31
32 /**********************
33 * STATIC VARIABLES
34 **********************/
35
36 /**********************
37 * MACROS
38 **********************/
39
40 /**********************
41 * GLOBAL FUNCTIONS
42 **********************/
43
44 /**
45 * Create a draw buffer for object to store the snapshot image.
46 */
lv_snapshot_create_draw_buf(lv_obj_t * obj,lv_color_format_t cf)47 lv_draw_buf_t * lv_snapshot_create_draw_buf(lv_obj_t * obj, lv_color_format_t cf)
48 {
49 lv_obj_update_layout(obj);
50 int32_t w = lv_obj_get_width(obj);
51 int32_t h = lv_obj_get_height(obj);
52 int32_t ext_size = lv_obj_get_ext_draw_size(obj);
53 w += ext_size * 2;
54 h += ext_size * 2;
55 if(w == 0 || h == 0) return NULL;
56
57 return lv_draw_buf_create(w, h, cf, LV_STRIDE_AUTO);
58 }
59
lv_snapshot_reshape_draw_buf(lv_obj_t * obj,lv_draw_buf_t * draw_buf)60 lv_result_t lv_snapshot_reshape_draw_buf(lv_obj_t * obj, lv_draw_buf_t * draw_buf)
61 {
62 lv_obj_update_layout(obj);
63 int32_t w = lv_obj_get_width(obj);
64 int32_t h = lv_obj_get_height(obj);
65 int32_t ext_size = lv_obj_get_ext_draw_size(obj);
66 w += ext_size * 2;
67 h += ext_size * 2;
68 if(w == 0 || h == 0) return LV_RESULT_INVALID;
69
70 draw_buf = lv_draw_buf_reshape(draw_buf, LV_COLOR_FORMAT_UNKNOWN, w, h, LV_STRIDE_AUTO);
71 return draw_buf == NULL ? LV_RESULT_INVALID : LV_RESULT_OK;
72 }
73
lv_snapshot_take_to_draw_buf(lv_obj_t * obj,lv_color_format_t cf,lv_draw_buf_t * draw_buf)74 lv_result_t lv_snapshot_take_to_draw_buf(lv_obj_t * obj, lv_color_format_t cf, lv_draw_buf_t * draw_buf)
75 {
76 LV_ASSERT_NULL(obj);
77 LV_ASSERT_NULL(draw_buf);
78 lv_result_t res;
79
80 switch(cf) {
81 case LV_COLOR_FORMAT_RGB565:
82 case LV_COLOR_FORMAT_ARGB8565:
83 case LV_COLOR_FORMAT_RGB888:
84 case LV_COLOR_FORMAT_XRGB8888:
85 case LV_COLOR_FORMAT_ARGB8888:
86 case LV_COLOR_FORMAT_A8:
87 case LV_COLOR_FORMAT_L8:
88 case LV_COLOR_FORMAT_I1:
89 case LV_COLOR_FORMAT_ARGB2222:
90 case LV_COLOR_FORMAT_ARGB4444:
91 case LV_COLOR_FORMAT_ARGB1555:
92 break;
93 default:
94 LV_LOG_WARN("Not supported color format");
95 return LV_RESULT_INVALID;
96 }
97
98 res = lv_snapshot_reshape_draw_buf(obj, draw_buf);
99 if(res != LV_RESULT_OK) return res;
100
101 /* clear draw buffer*/
102 lv_draw_buf_clear(draw_buf, NULL);
103
104 lv_area_t snapshot_area;
105 int32_t w = draw_buf->header.w;
106 int32_t h = draw_buf->header.h;
107 int32_t ext_size = lv_obj_get_ext_draw_size(obj);
108 lv_obj_get_coords(obj, &snapshot_area);
109 lv_area_increase(&snapshot_area, ext_size, ext_size);
110
111 lv_layer_t layer;
112 lv_layer_init(&layer);
113
114 layer.draw_buf = draw_buf;
115 layer.buf_area.x1 = snapshot_area.x1;
116 layer.buf_area.y1 = snapshot_area.y1;
117 layer.buf_area.x2 = snapshot_area.x1 + w - 1;
118 layer.buf_area.y2 = snapshot_area.y1 + h - 1;
119 layer.color_format = cf;
120 layer._clip_area = snapshot_area;
121 layer.phy_clip_area = snapshot_area;
122
123 lv_display_t * disp_old = lv_refr_get_disp_refreshing();
124 lv_display_t * disp_new = lv_obj_get_display(obj);
125 lv_layer_t * layer_old = disp_new->layer_head;
126 disp_new->layer_head = &layer;
127
128 lv_refr_set_disp_refreshing(disp_new);
129 lv_obj_redraw(&layer, obj);
130
131 while(layer.draw_task_head) {
132 lv_draw_dispatch_wait_for_request();
133 lv_draw_dispatch();
134 }
135
136 disp_new->layer_head = layer_old;
137 lv_refr_set_disp_refreshing(disp_old);
138
139 return LV_RESULT_OK;
140 }
141
lv_snapshot_take(lv_obj_t * obj,lv_color_format_t cf)142 lv_draw_buf_t * lv_snapshot_take(lv_obj_t * obj, lv_color_format_t cf)
143 {
144 LV_ASSERT_NULL(obj);
145 lv_draw_buf_t * draw_buf = lv_snapshot_create_draw_buf(obj, cf);
146 if(draw_buf == NULL) return NULL;
147
148 if(lv_snapshot_take_to_draw_buf(obj, cf, draw_buf) != LV_RESULT_OK) {
149 lv_draw_buf_destroy(draw_buf);
150 return NULL;
151 }
152
153 return draw_buf;
154 }
155
lv_snapshot_free(lv_image_dsc_t * dsc)156 void lv_snapshot_free(lv_image_dsc_t * dsc)
157 {
158 LV_LOG_WARN("Deprecated API, use lv_draw_buf_destroy directly.");
159 lv_draw_buf_destroy((lv_draw_buf_t *)dsc);
160 }
161
lv_snapshot_take_to_buf(lv_obj_t * obj,lv_color_format_t cf,lv_image_dsc_t * dsc,void * buf,uint32_t buf_size)162 lv_result_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_color_format_t cf, lv_image_dsc_t * dsc,
163 void * buf,
164 uint32_t buf_size)
165 {
166 lv_draw_buf_t draw_buf;
167 LV_LOG_WARN("Deprecated API, use lv_snapshot_take_to_draw_buf instead.");
168 lv_draw_buf_init(&draw_buf, 1, 1, cf, buf_size, buf, buf_size);
169 lv_result_t res = lv_snapshot_take_to_draw_buf(obj, cf, &draw_buf);
170 if(res == LV_RESULT_OK) {
171 lv_memcpy((void *)dsc, &draw_buf, sizeof(lv_image_dsc_t));
172 }
173 return res;
174 }
175
176 /**********************
177 * STATIC FUNCTIONS
178 **********************/
179
180 #endif /*LV_USE_SNAPSHOT*/
181