Skip to content

Commit 4f2fd4b

Browse files
FASTSHIFTpengyiqiang
andauthored
fix(vg_lite): fix stroke crash when update failed (lvgl#7399)
Signed-off-by: pengyiqiang <[email protected]> Co-authored-by: pengyiqiang <[email protected]>
1 parent 65a52f2 commit 4f2fd4b

File tree

1 file changed

+149
-76
lines changed

1 file changed

+149
-76
lines changed

src/draw/vg_lite/lv_vg_lite_stroke.c

Lines changed: 149 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,41 @@
2424
* TYPEDEFS
2525
**********************/
2626

27+
28+
/**
29+
* Since the key-value data structure of lv_cache is integrated, the kv data structure
30+
* will be saved at the same time when the cache is successfully created.
31+
* In order to pursue efficiency during the matching process, the primary key (lv) used for matching
32+
* will not dup the dash_pattern secondary pointer, so when the creation is successful, dash_pattern needs
33+
* to be dup to the child key (vg), so type is added here to distinguish where the real data of dash_pattern exists.
34+
*/
35+
typedef enum {
36+
DASH_PATTERN_TYPE_LV,
37+
DASH_PATTERN_TYPE_VG
38+
} dash_pattern_type_t;
39+
2740
typedef struct {
28-
/* stroke path */
29-
lv_vg_lite_path_t * path;
30-
31-
/* stroke parameters */
32-
float width;
33-
lv_vector_stroke_cap_t cap;
34-
lv_vector_stroke_join_t join;
35-
uint16_t miter_limit;
36-
lv_array_t dash_pattern;
41+
dash_pattern_type_t dash_pattern_type;
42+
43+
struct {
44+
/* path data */
45+
lv_vg_lite_path_t * path;
46+
47+
/* stroke parameters */
48+
float width;
49+
lv_vector_stroke_cap_t cap;
50+
lv_vector_stroke_join_t join;
51+
uint16_t miter_limit;
52+
lv_array_t dash_pattern;
53+
} lv;
54+
55+
struct {
56+
/* stroke path */
57+
lv_vg_lite_path_t * path;
58+
59+
/* dash pattern, for comparison only */
60+
lv_array_t dash_pattern;
61+
} vg;
3762
} stroke_item_t;
3863

3964
/**********************
@@ -124,21 +149,21 @@ lv_cache_entry_t * lv_vg_lite_stroke_get(struct _lv_draw_vg_lite_unit_t * unit,
124149
/* prepare search key */
125150
stroke_item_t search_key;
126151
lv_memzero(&search_key, sizeof(search_key));
127-
search_key.cap = dsc->cap;
128-
search_key.join = dsc->join;
129-
search_key.width = dsc->width;
130-
search_key.miter_limit = dsc->miter_limit;
152+
search_key.lv.cap = dsc->cap;
153+
search_key.lv.join = dsc->join;
154+
search_key.lv.width = dsc->width;
155+
search_key.lv.miter_limit = dsc->miter_limit;
131156

132157
/* A one-time read-only array that only copies the pointer but not the content */
133-
search_key.dash_pattern = dsc->dash_pattern;
134-
search_key.path = path;
158+
search_key.lv.dash_pattern = dsc->dash_pattern;
159+
search_key.lv.path = path;
135160

136-
lv_cache_entry_t * cache_node_entry = lv_cache_acquire(unit->stroke_cache, &search_key, &search_key);
161+
lv_cache_entry_t * cache_node_entry = lv_cache_acquire(unit->stroke_cache, &search_key, NULL);
137162
if(cache_node_entry) {
138163
return cache_node_entry;
139164
}
140165

141-
cache_node_entry = lv_cache_acquire_or_create(unit->stroke_cache, &search_key, &search_key);
166+
cache_node_entry = lv_cache_acquire_or_create(unit->stroke_cache, &search_key, NULL);
142167
if(cache_node_entry == NULL) {
143168
LV_LOG_ERROR("stroke cache creating failed");
144169
return NULL;
@@ -153,7 +178,13 @@ struct _lv_vg_lite_path_t * lv_vg_lite_stroke_get_path(lv_cache_entry_t * cache_
153178

154179
stroke_item_t * stroke_item = lv_cache_entry_get_data(cache_entry);
155180
LV_ASSERT_NULL(stroke_item);
156-
return stroke_item->path;
181+
182+
if(lv_array_size(&stroke_item->vg.dash_pattern)) {
183+
/* check if dash pattern must be duped */
184+
LV_ASSERT(stroke_item->dash_pattern_type == DASH_PATTERN_TYPE_VG);
185+
}
186+
187+
return stroke_item->vg.path;
157188
}
158189

159190
void lv_vg_lite_stroke_drop(struct _lv_draw_vg_lite_unit_t * unit,
@@ -170,43 +201,49 @@ void lv_vg_lite_stroke_drop(struct _lv_draw_vg_lite_unit_t * unit,
170201

171202
static bool stroke_create_cb(stroke_item_t * item, void * user_data)
172203
{
204+
LV_UNUSED(user_data);
173205
LV_ASSERT_NULL(item);
174206

175-
stroke_item_t * src = user_data;
176-
LV_ASSERT_NULL(src);
177-
178-
lv_memzero(item, sizeof(stroke_item_t));
207+
/* Check if stroke width is valid */
208+
if(item->lv.width <= 0) {
209+
LV_LOG_WARN("stroke width error: %f", item->lv.width);
210+
return false;
211+
}
179212

180-
/* copy path */
181-
item->path = lv_vg_lite_path_create(VG_LITE_FP32);
182-
lv_vg_lite_path_append_path(item->path, src->path);
213+
/* Reset the dash pattern type */
214+
item->dash_pattern_type = DASH_PATTERN_TYPE_LV;
183215

184-
/* copy parameters */
185-
item->cap = src->cap;
186-
item->join = src->join;
187-
item->width = src->width;
188-
item->miter_limit = src->miter_limit;
216+
/* dup the path */
217+
item->vg.path = lv_vg_lite_path_create(VG_LITE_FP32);
218+
lv_vg_lite_path_append_path(item->vg.path, item->lv.path);
189219

190-
/* copy dash pattern */
191-
uint32_t size = lv_array_size(&src->dash_pattern);
220+
/* dup the dash pattern */
221+
vg_lite_float_t * vg_dash_pattern = NULL;
222+
const uint32_t size = lv_array_size(&item->lv.dash_pattern);
192223
if(size) {
193-
lv_array_init(&item->dash_pattern, size, sizeof(float));
194-
lv_array_copy(&item->dash_pattern, &src->dash_pattern);
224+
/* Only support float dash pattern */
225+
LV_ASSERT(item->lv.dash_pattern.element_size == sizeof(float));
226+
lv_array_init(&item->vg.dash_pattern, size, sizeof(float));
227+
lv_array_copy(&item->vg.dash_pattern, &item->lv.dash_pattern);
228+
229+
/* mark dash pattern has been duped */
230+
item->dash_pattern_type = DASH_PATTERN_TYPE_VG;
231+
vg_dash_pattern = lv_array_front(&item->vg.dash_pattern);
195232
}
196233

197234
/* update parameters */
198-
vg_lite_path_t * vg_path = lv_vg_lite_path_get_path(item->path);
235+
vg_lite_path_t * vg_path = lv_vg_lite_path_get_path(item->vg.path);
199236
LV_VG_LITE_CHECK_ERROR(vg_lite_set_path_type(vg_path, VG_LITE_DRAW_STROKE_PATH));
200237

201238
vg_lite_error_t error = vg_lite_set_stroke(
202239
vg_path,
203-
lv_stroke_cap_to_vg(item->cap),
204-
lv_stroke_join_to_vg(item->join),
205-
item->width,
206-
item->miter_limit,
207-
lv_array_front(&item->dash_pattern),
240+
lv_stroke_cap_to_vg(item->lv.cap),
241+
lv_stroke_join_to_vg(item->lv.join),
242+
item->lv.width,
243+
item->lv.miter_limit,
244+
vg_dash_pattern,
208245
size,
209-
item->width / 2,
246+
item->lv.width / 2,
210247
0);
211248

212249
if(error != VG_LITE_SUCCESS) {
@@ -242,68 +279,104 @@ static void stroke_free_cb(stroke_item_t * item, void * user_data)
242279
LV_UNUSED(user_data);
243280
LV_ASSERT_NULL(item);
244281

245-
lv_array_deinit(&item->dash_pattern);
246-
lv_vg_lite_path_destroy(item->path);
247-
lv_memzero(item, sizeof(stroke_item_t));
282+
if(item->vg.path) {
283+
lv_vg_lite_path_destroy(item->vg.path);
284+
item->vg.path = NULL;
285+
}
286+
287+
if(item->dash_pattern_type == DASH_PATTERN_TYPE_VG) {
288+
lv_array_deinit(&item->vg.dash_pattern);
289+
item->dash_pattern_type = DASH_PATTERN_TYPE_LV;
290+
}
248291
}
249292

250-
static lv_cache_compare_res_t path_compare(const vg_lite_path_t * lhs, const vg_lite_path_t * rhs)
293+
static lv_cache_compare_res_t dash_pattern_compare(const stroke_item_t * lhs, const stroke_item_t * rhs)
251294
{
252-
LV_ASSERT(lhs->format == VG_LITE_FP32);
253-
LV_ASSERT(rhs->format == VG_LITE_FP32);
295+
/* Select the dash pattern to compare */
296+
const lv_array_t * lhs_dash_pattern = lhs->dash_pattern_type == DASH_PATTERN_TYPE_LV ?
297+
&lhs->lv.dash_pattern :
298+
&lhs->vg.dash_pattern;
299+
const lv_array_t * rhs_dash_pattern = rhs->dash_pattern_type == DASH_PATTERN_TYPE_LV ?
300+
&rhs->lv.dash_pattern :
301+
&rhs->vg.dash_pattern;
302+
303+
const uint32_t lhs_dash_pattern_size = lv_array_size(lhs_dash_pattern);
304+
const uint32_t rhs_dash_pattern_size = lv_array_size(rhs_dash_pattern);
305+
306+
if(lhs_dash_pattern_size != rhs_dash_pattern_size) {
307+
return lhs_dash_pattern_size > rhs_dash_pattern_size ? 1 : -1;
308+
}
254309

255-
if(lhs->path_length != rhs->path_length) {
256-
return lhs->path_length > rhs->path_length ? 1 : -1;
310+
if(lhs_dash_pattern_size == 0 && rhs_dash_pattern_size == 0) {
311+
return 0;
257312
}
258313

259-
int cmp_res = lv_memcmp(lhs->path, rhs->path, lhs->path_length);
314+
/* Both dash pattern has the same size, compare them */
315+
LV_ASSERT(lhs_dash_pattern->element_size == sizeof(float));
316+
LV_ASSERT(rhs_dash_pattern->element_size == sizeof(float));
317+
318+
/* compare dash pattern data */
319+
int cmp_res = lv_memcmp(
320+
lv_array_front(lhs_dash_pattern),
321+
lv_array_front(rhs_dash_pattern),
322+
lhs_dash_pattern_size * sizeof(float));
323+
260324
if(cmp_res != 0) {
261325
return cmp_res > 0 ? 1 : -1;
262326
}
263327

264328
return 0;
265329
}
266330

267-
static lv_cache_compare_res_t stroke_compare_cb(const stroke_item_t * lhs, const stroke_item_t * rhs)
331+
static lv_cache_compare_res_t path_compare(const stroke_item_t * lhs, const stroke_item_t * rhs)
268332
{
269-
if(lhs->width != lhs->width) {
270-
return lhs->width > lhs->width ? 1 : -1;
333+
/* Give priority to using dup vg.path */
334+
const vg_lite_path_t * lhs_path = lhs->vg.path ?
335+
lv_vg_lite_path_get_path(lhs->vg.path) :
336+
lv_vg_lite_path_get_path(lhs->lv.path);
337+
const vg_lite_path_t * rhs_path = rhs->vg.path ?
338+
lv_vg_lite_path_get_path(rhs->vg.path) :
339+
lv_vg_lite_path_get_path(rhs->lv.path);
340+
341+
LV_ASSERT(lhs_path->format == VG_LITE_FP32);
342+
LV_ASSERT(rhs_path->format == VG_LITE_FP32);
343+
344+
if(lhs_path->path_length != rhs_path->path_length) {
345+
return lhs_path->path_length > rhs_path->path_length ? 1 : -1;
271346
}
272347

273-
if(lhs->cap != rhs->cap) {
274-
return lhs->cap > rhs->cap ? 1 : -1;
348+
int cmp_res = lv_memcmp(lhs_path->path, rhs_path->path, lhs_path->path_length);
349+
if(cmp_res != 0) {
350+
return cmp_res > 0 ? 1 : -1;
275351
}
276352

277-
if(lhs->join != rhs->join) {
278-
return lhs->join > rhs->join ? 1 : -1;
279-
}
353+
return 0;
354+
}
280355

281-
if(lhs->miter_limit != rhs->miter_limit) {
282-
return lhs->miter_limit > rhs->miter_limit ? 1 : -1;
356+
static lv_cache_compare_res_t stroke_compare_cb(const stroke_item_t * lhs, const stroke_item_t * rhs)
357+
{
358+
if(lhs->lv.width != rhs->lv.width) {
359+
return lhs->lv.width > rhs->lv.width ? 1 : -1;
283360
}
284361

285-
uint32_t lhs_dash_pattern_size = lv_array_size(&lhs->dash_pattern);
286-
uint32_t rhs_dash_pattern_size = lv_array_size(&rhs->dash_pattern);
287-
288-
if(lhs_dash_pattern_size != rhs_dash_pattern_size) {
289-
return lhs_dash_pattern_size > rhs_dash_pattern_size ? 1 : -1;
362+
if(lhs->lv.cap != rhs->lv.cap) {
363+
return lhs->lv.cap > rhs->lv.cap ? 1 : -1;
290364
}
291365

292-
if(lhs_dash_pattern_size > 0 && rhs_dash_pattern_size > 0) {
293-
LV_ASSERT(lhs->dash_pattern.element_size == sizeof(float));
294-
LV_ASSERT(rhs->dash_pattern.element_size == sizeof(float));
366+
if(lhs->lv.join != rhs->lv.join) {
367+
return lhs->lv.join > rhs->lv.join ? 1 : -1;
368+
}
295369

296-
const float * lhs_dash_pattern = lv_array_front(&lhs->dash_pattern);
297-
const float * rhs_dash_pattern = lv_array_front(&rhs->dash_pattern);
370+
if(lhs->lv.miter_limit != rhs->lv.miter_limit) {
371+
return lhs->lv.miter_limit > rhs->lv.miter_limit ? 1 : -1;
372+
}
298373

299-
/* compare dash pattern */
300-
int cmp_res = lv_memcmp(lhs_dash_pattern, rhs_dash_pattern, lhs_dash_pattern_size * sizeof(float));
301-
if(cmp_res != 0) {
302-
return cmp_res > 0 ? 1 : -1;
303-
}
374+
lv_cache_compare_res_t dash_pattern_res = dash_pattern_compare(lhs, rhs);
375+
if(dash_pattern_res != 0) {
376+
return dash_pattern_res;
304377
}
305378

306-
return path_compare(lv_vg_lite_path_get_path(lhs->path), lv_vg_lite_path_get_path(rhs->path));
379+
return path_compare(lhs, rhs);
307380
}
308381

309382
#endif /*LV_USE_DRAW_VG_LITE && LV_USE_VECTOR_GRAPHIC*/

0 commit comments

Comments
 (0)