fix(svg): adjust svg render node object for reduce memory usage. (#8013)

Signed-off-by: zhangjipeng <zhangjipeng@xiaomi.com>
Co-authored-by: zhangjipeng <zhangjipeng@xiaomi.com>
This commit is contained in:
Zhang Ji Peng
2025-03-29 01:47:22 +08:00
committed by GitHub
parent 8e65486b32
commit f55c8d4dbe
3 changed files with 170 additions and 99 deletions
+1 -1
View File
@@ -146,7 +146,7 @@ static lv_result_t svg_decoder_info(lv_image_decoder_t * decoder, lv_image_decod
lv_svg_render_obj_t * svg_header = lv_svg_render_create(svg_doc);
if(svg_header->tag == LV_SVG_TAG_SVG) {
lv_area_t bounds;
svg_header->get_bounds(svg_header, &bounds);
svg_header->clz->get_bounds(svg_header, &bounds);
width = lv_area_get_width(&bounds) - 1;
height = lv_area_get_height(&bounds) - 1;
}
+163 -97
View File
@@ -483,7 +483,7 @@ static void _set_polyline_attr(lv_svg_render_obj_t * obj, lv_vector_draw_dsc_t *
}
}
static void _set_polygen_attr(lv_svg_render_obj_t * obj, lv_vector_draw_dsc_t * dsc, const lv_svg_attr_t * attr)
static void _set_polygon_attr(lv_svg_render_obj_t * obj, lv_vector_draw_dsc_t * dsc, const lv_svg_attr_t * attr)
{
_set_polyline_attr(obj, dsc, attr);
lv_svg_render_poly_t * poly = (lv_svg_render_poly_t *)obj;
@@ -899,7 +899,7 @@ static void _set_solid_ref(lv_svg_render_obj_t * obj, lv_vector_draw_dsc_t * dsc
static void _set_gradient_ref(lv_svg_render_obj_t * obj, lv_vector_draw_dsc_t * dsc,
const lv_svg_render_obj_t * target_obj, bool fill)
{
if(!target_obj->get_bounds) {
if(!target_obj->clz->get_bounds) {
return;
}
@@ -921,7 +921,7 @@ static void _set_gradient_ref(lv_svg_render_obj_t * obj, lv_vector_draw_dsc_t *
lv_memcpy(grad_dsc, &grad->dsc, sizeof(lv_vector_gradient_t));
lv_area_t bounds = {0, 0, 0, 0};
target_obj->get_bounds(target_obj, &bounds);
target_obj->clz->get_bounds(target_obj, &bounds);
int32_t w = bounds.x2 - bounds.x1;
int32_t h = bounds.y2 - bounds.y1;
@@ -998,7 +998,7 @@ static void _copy_draw_dsc_from_ref(lv_vector_dsc_t * dsc, const lv_svg_render_o
while(list) {
if(list->id) {
if(strcmp(obj->fill_ref, list->id) == 0) {
list->set_paint_ref(list, dst, obj, true);
list->clz->set_paint_ref(list, dst, obj, true);
break;
}
}
@@ -1011,7 +1011,7 @@ static void _copy_draw_dsc_from_ref(lv_vector_dsc_t * dsc, const lv_svg_render_o
while(list) {
if(list->id) {
if(strcmp(obj->stroke_ref, list->id) == 0) {
list->set_paint_ref(list, dst, obj, false);
list->clz->set_paint_ref(list, dst, obj, false);
break;
}
}
@@ -1027,8 +1027,8 @@ static void _set_render_attrs(lv_svg_render_obj_t * obj, const lv_svg_node_t * n
if((node->type != LV_SVG_TAG_CONTENT) && node->xml_id) {
obj->id = lv_strdup(node->xml_id);
}
if(obj->init) {
obj->init(obj, node);
if(obj->clz->init) {
obj->clz->init(obj, node);
}
if(state->draw_dsc->fill_ref) {
obj->fill_ref = lv_strdup(state->draw_dsc->fill_ref);
@@ -1040,7 +1040,7 @@ static void _set_render_attrs(lv_svg_render_obj_t * obj, const lv_svg_node_t * n
uint32_t len = lv_array_size(&node->attrs);
for(uint32_t i = 0; i < len; i++) {
lv_svg_attr_t * attr = lv_array_at(&node->attrs, i);
obj->set_attr(obj, &(state->draw_dsc->dsc), attr);
obj->clz->set_attr(obj, &(state->draw_dsc->dsc), attr);
}
if(node->type == LV_SVG_TAG_G) { // only <g> need store it
state->draw_dsc->fill_ref = obj->fill_ref;
@@ -1391,10 +1391,10 @@ static void _render_group(const lv_svg_render_obj_t * obj, lv_vector_dsc_t * dsc
for(uint32_t i = 0; i < group->items.size; i++) {
lv_svg_render_obj_t * list = *((lv_svg_render_obj_t **)lv_array_at(&group->items, i));
if(list->render && (list->flags & _RENDER_IN_GROUP)) {
if(list->clz->render && (list->flags & _RENDER_IN_GROUP)) {
_copy_draw_dsc(&(save_dsc.dsc), &(dsc->current_dsc));
_special_render(list, dsc);
list->render(list, dsc, matrix);
list->clz->render(list, dsc, matrix);
_copy_draw_dsc(&(dsc->current_dsc), &(save_dsc.dsc));
}
}
@@ -1525,10 +1525,10 @@ static void _render_use(const lv_svg_render_obj_t * obj, lv_vector_dsc_t * dsc,
while(list) {
if(list->id) {
if(strcmp(use->xlink, list->id) == 0) {
if(list->render) {
if(list->clz->render) {
_prepare_render(list, dsc);
_special_render(obj, dsc);
list->render(list, dsc, &mtx);
list->clz->render(list, dsc, &mtx);
}
break;
}
@@ -1951,6 +1951,135 @@ static void _destroy_tspan(lv_svg_render_obj_t * obj)
#endif
static lv_svg_render_class svg_viewport_class = {
.init = _init_viewport,
.render = _render_viewport,
.set_attr = _set_viewport_attr,
.get_bounds = _get_viewport_bounds,
.get_size = _get_viewport_size,
};
static lv_svg_render_class svg_rect_class = {
.init = _init_obj,
.render = _render_rect,
.set_attr = _set_rect_attr,
.get_bounds = _get_rect_bounds,
.get_size = _get_rect_size,
};
static lv_svg_render_class svg_circle_class = {
.init = _init_obj,
.render = _render_circle,
.set_attr = _set_circle_attr,
.get_bounds = _get_circle_bounds,
.get_size = _get_circle_size,
};
static lv_svg_render_class svg_ellipse_class = {
.init = _init_obj,
.render = _render_ellipse,
.set_attr = _set_ellipse_attr,
.get_bounds = _get_ellipse_bounds,
.get_size = _get_ellipse_size,
};
static lv_svg_render_class svg_line_class = {
.init = _init_obj,
.render = _render_line,
.set_attr = _set_line_attr,
.get_bounds = _get_line_bounds,
.get_size = _get_line_size,
};
static lv_svg_render_class svg_polyline_class = {
.init = _init_poly,
.render = _render_poly,
.set_attr = _set_polyline_attr,
.get_bounds = _get_poly_bounds,
.destroy = _destroy_poly,
.get_size = _get_poly_size,
};
static lv_svg_render_class svg_polygon_class = {
.init = _init_poly,
.render = _render_poly,
.set_attr = _set_polygon_attr,
.get_bounds = _get_poly_bounds,
.destroy = _destroy_poly,
.get_size = _get_poly_size,
};
static lv_svg_render_class svg_path_class = {
.init = _init_poly,
.render = _render_poly,
.set_attr = _set_path_attr,
.get_bounds = _get_poly_bounds,
.destroy = _destroy_poly,
.get_size = _get_poly_size,
};
#if LV_USE_FREETYPE
static lv_svg_render_class svg_text_class = {
.init = _init_text,
.set_attr = _set_text_attr,
.render = _render_text,
.get_bounds = _get_text_bounds,
.destroy = _destroy_text,
.get_size = _get_txt_size,
};
static lv_svg_render_class svg_tspan_class = {
.init = _init_tspan,
.set_attr = _set_tspan_attr,
.get_bounds = _get_tspan_bounds,
.destroy = _destroy_tspan,
.get_size = _get_span_size,
};
static lv_svg_render_class svg_content_class = {
.init = _init_content,
.destroy = _destroy_content,
.get_size = _get_content_size,
};
#endif
static lv_svg_render_class svg_image_class = {
.init = _init_image,
.render = _render_image,
.set_attr = _set_image_attr,
.get_size = _get_image_size,
};
static lv_svg_render_class svg_use_class = {
.init = _init_obj,
.set_attr = _set_use_attr,
.render = _render_use,
.destroy = _destroy_use,
.get_size = _get_use_size,
};
static lv_svg_render_class svg_solid_class = {
.init = _init_obj,
.set_attr = _set_solid_attr,
.set_paint_ref = _set_solid_ref,
.get_size = _get_solid_size,
};
static lv_svg_render_class svg_grad_class = {
.init = _init_gradient,
.set_attr = _set_gradient_attr,
.set_paint_ref = _set_gradient_ref,
.get_size = _get_grad_size,
};
static lv_svg_render_class svg_group_class = {
.init = _init_group,
.set_attr = _set_attr,
.render = _render_group,
.destroy = _destroy_group,
.get_size = _get_group_size,
};
static lv_svg_render_obj_t * _lv_svg_render_create(const lv_svg_node_t * node,
struct _lv_svg_drawing_builder_state * state)
{
@@ -1958,91 +2087,56 @@ static lv_svg_render_obj_t * _lv_svg_render_create(const lv_svg_node_t * node,
case LV_SVG_TAG_SVG: {
lv_svg_render_viewport_t * view = lv_zalloc(sizeof(lv_svg_render_viewport_t));
LV_ASSERT_MALLOC(view);
view->base.init = _init_viewport;
view->base.render = _render_viewport;
view->base.set_attr = _set_viewport_attr;
view->base.get_bounds = _get_viewport_bounds;
view->base.get_size = _get_viewport_size;
view->base.clz = &svg_viewport_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(view), node, state);
return LV_SVG_RENDER_OBJ(view);
}
case LV_SVG_TAG_RECT: {
lv_svg_render_rect_t * rect = lv_zalloc(sizeof(lv_svg_render_rect_t));
LV_ASSERT_MALLOC(rect);
rect->base.init = _init_obj;
rect->base.render = _render_rect;
rect->base.set_attr = _set_rect_attr;
rect->base.get_bounds = _get_rect_bounds;
rect->base.get_size = _get_rect_size;
rect->base.clz = &svg_rect_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(rect), node, state);
return LV_SVG_RENDER_OBJ(rect);
}
case LV_SVG_TAG_CIRCLE: {
lv_svg_render_circle_t * circle = lv_zalloc(sizeof(lv_svg_render_circle_t));
LV_ASSERT_MALLOC(circle);
circle->base.init = _init_obj;
circle->base.render = _render_circle;
circle->base.set_attr = _set_circle_attr;
circle->base.get_bounds = _get_circle_bounds;
circle->base.get_size = _get_circle_size;
circle->base.clz = &svg_circle_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(circle), node, state);
return LV_SVG_RENDER_OBJ(circle);
}
case LV_SVG_TAG_ELLIPSE: {
lv_svg_render_ellipse_t * ellipse = lv_zalloc(sizeof(lv_svg_render_ellipse_t));
LV_ASSERT_MALLOC(ellipse);
ellipse->base.init = _init_obj;
ellipse->base.render = _render_ellipse;
ellipse->base.set_attr = _set_ellipse_attr;
ellipse->base.get_bounds = _get_ellipse_bounds;
ellipse->base.get_size = _get_ellipse_size;
ellipse->base.clz = &svg_ellipse_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(ellipse), node, state);
return LV_SVG_RENDER_OBJ(ellipse);
}
case LV_SVG_TAG_LINE: {
lv_svg_render_line_t * line = lv_zalloc(sizeof(lv_svg_render_line_t));
LV_ASSERT_MALLOC(line);
line->base.init = _init_obj;
line->base.render = _render_line;
line->base.set_attr = _set_line_attr;
line->base.get_bounds = _get_line_bounds;
line->base.get_size = _get_line_size;
line->base.clz = &svg_line_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(line), node, state);
return LV_SVG_RENDER_OBJ(line);
}
case LV_SVG_TAG_POLYLINE: {
lv_svg_render_poly_t * poly = lv_zalloc(sizeof(lv_svg_render_poly_t));
LV_ASSERT_MALLOC(poly);
poly->base.init = _init_poly;
poly->base.render = _render_poly;
poly->base.set_attr = _set_polyline_attr;
poly->base.get_bounds = _get_poly_bounds;
poly->base.destroy = _destroy_poly;
poly->base.get_size = _get_poly_size;
poly->base.clz = &svg_polyline_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(poly), node, state);
return LV_SVG_RENDER_OBJ(poly);
}
case LV_SVG_TAG_POLYGON: {
lv_svg_render_poly_t * poly = lv_zalloc(sizeof(lv_svg_render_poly_t));
LV_ASSERT_MALLOC(poly);
poly->base.init = _init_poly;
poly->base.render = _render_poly;
poly->base.set_attr = _set_polygen_attr;
poly->base.get_bounds = _get_poly_bounds;
poly->base.destroy = _destroy_poly;
poly->base.get_size = _get_poly_size;
poly->base.clz = &svg_polygon_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(poly), node, state);
return LV_SVG_RENDER_OBJ(poly);
}
case LV_SVG_TAG_PATH: {
lv_svg_render_poly_t * poly = lv_zalloc(sizeof(lv_svg_render_poly_t));
LV_ASSERT_MALLOC(poly);
poly->base.init = _init_poly;
poly->base.render = _render_poly;
poly->base.set_attr = _set_path_attr;
poly->base.get_bounds = _get_poly_bounds;
poly->base.destroy = _destroy_poly;
poly->base.get_size = _get_poly_size;
poly->base.clz = &svg_path_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(poly), node, state);
return LV_SVG_RENDER_OBJ(poly);
}
@@ -2050,12 +2144,7 @@ static lv_svg_render_obj_t * _lv_svg_render_create(const lv_svg_node_t * node,
case LV_SVG_TAG_TEXT: {
lv_svg_render_text_t * txt = lv_zalloc(sizeof(lv_svg_render_text_t));
LV_ASSERT_MALLOC(txt);
txt->base.init = _init_text;
txt->base.set_attr = _set_text_attr;
txt->base.render = _render_text;
txt->base.get_bounds = _get_text_bounds;
txt->base.destroy = _destroy_text;
txt->base.get_size = _get_txt_size;
txt->base.clz = &svg_text_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(txt), node, state);
return LV_SVG_RENDER_OBJ(txt);
}
@@ -2064,20 +2153,14 @@ static lv_svg_render_obj_t * _lv_svg_render_create(const lv_svg_node_t * node,
LV_ASSERT_MALLOC(span);
lv_svg_render_content_t * content = (lv_svg_render_content_t *)span;
content->render_content = _render_span;
content->base.init = _init_tspan;
content->base.set_attr = _set_tspan_attr;
content->base.get_bounds = _get_tspan_bounds;
content->base.destroy = _destroy_tspan;
content->base.get_size = _get_span_size;
content->base.clz = &svg_tspan_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(span), node, state);
return LV_SVG_RENDER_OBJ(span);
}
case LV_SVG_TAG_CONTENT: {
lv_svg_render_content_t * content = lv_zalloc(sizeof(lv_svg_render_content_t));
LV_ASSERT_MALLOC(content);
content->base.init = _init_content;
content->base.destroy = _destroy_content;
content->base.get_size = _get_content_size;
content->base.clz = &svg_content_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(content), node, state);
return LV_SVG_RENDER_OBJ(content);
}
@@ -2085,31 +2168,21 @@ static lv_svg_render_obj_t * _lv_svg_render_create(const lv_svg_node_t * node,
case LV_SVG_TAG_IMAGE: {
lv_svg_render_image_t * image = lv_zalloc(sizeof(lv_svg_render_image_t));
LV_ASSERT_MALLOC(image);
image->base.init = _init_image;
image->base.render = _render_image;
image->base.set_attr = _set_image_attr;
image->base.get_size = _get_image_size;
image->base.clz = &svg_image_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(image), node, state);
return LV_SVG_RENDER_OBJ(image);
}
case LV_SVG_TAG_USE: {
lv_svg_render_use_t * use = lv_zalloc(sizeof(lv_svg_render_use_t));
LV_ASSERT_MALLOC(use);
use->base.init = _init_obj;
use->base.set_attr = _set_use_attr;
use->base.render = _render_use;
use->base.destroy = _destroy_use;
use->base.get_size = _get_use_size;
use->base.clz = &svg_use_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(use), node, state);
return LV_SVG_RENDER_OBJ(use);
}
case LV_SVG_TAG_SOLID_COLOR: {
lv_svg_render_solid_t * solid = lv_zalloc(sizeof(lv_svg_render_solid_t));
LV_ASSERT_MALLOC(solid);
solid->base.init = _init_obj;
solid->base.set_attr = _set_solid_attr;
solid->base.set_paint_ref = _set_solid_ref;
solid->base.get_size = _get_solid_size;
solid->base.clz = &svg_solid_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(solid), node, state);
return LV_SVG_RENDER_OBJ(solid);
}
@@ -2117,27 +2190,20 @@ static lv_svg_render_obj_t * _lv_svg_render_create(const lv_svg_node_t * node,
case LV_SVG_TAG_LINEAR_GRADIENT: {
lv_svg_render_gradient_t * grad = lv_zalloc(sizeof(lv_svg_render_gradient_t));
LV_ASSERT_MALLOC(grad);
grad->base.init = _init_gradient;
grad->base.set_attr = _set_gradient_attr;
grad->base.set_paint_ref = _set_gradient_ref;
grad->base.clz = &svg_grad_class;
if(node->type == LV_SVG_TAG_LINEAR_GRADIENT) {
grad->dsc.style = LV_VECTOR_GRADIENT_STYLE_LINEAR;
}
else { // radial gradient
grad->dsc.style = LV_VECTOR_GRADIENT_STYLE_RADIAL;
}
grad->base.get_size = _get_grad_size;
_set_render_attrs(LV_SVG_RENDER_OBJ(grad), node, state);
return LV_SVG_RENDER_OBJ(grad);
}
case LV_SVG_TAG_G: {
lv_svg_render_group_t * group = lv_zalloc(sizeof(lv_svg_render_group_t));
LV_ASSERT_MALLOC(group);
group->base.init = _init_group;
group->base.set_attr = _set_attr;
group->base.render = _render_group;
group->base.destroy = _destroy_group;
group->base.get_size = _get_group_size;
group->base.clz = &svg_group_class;
_set_render_attrs(LV_SVG_RENDER_OBJ(group), node, state);
return LV_SVG_RENDER_OBJ(group);
}
@@ -2330,8 +2396,8 @@ void lv_svg_render_delete(lv_svg_render_obj_t * list)
_deinit_draw_dsc(&(obj->dsc));
if(obj->destroy) {
obj->destroy(obj);
if(obj->clz->destroy) {
obj->clz->destroy(obj);
}
if(obj->id) {
lv_free(obj->id);
@@ -2355,8 +2421,8 @@ uint32_t lv_svg_render_get_size(const lv_svg_render_obj_t * render)
uint32_t size = 0;
const lv_svg_render_obj_t * cur = render;
while(cur) {
if(cur->get_size) {
cur->get_size(cur, &size);
if(cur->clz->get_size) {
cur->clz->get_size(cur, &size);
}
cur = cur->next;
}
@@ -2371,9 +2437,9 @@ void lv_draw_svg_render(lv_vector_dsc_t * dsc, const lv_svg_render_obj_t * rende
const lv_svg_render_obj_t * cur = render;
while(cur) {
if(cur->render && ((cur->flags & 3) == _RENDER_NORMAL)) {
if(cur->clz->render && ((cur->flags & 3) == _RENDER_NORMAL)) {
_prepare_render(cur, dsc);
cur->render(cur, dsc, NULL);
cur->clz->render(cur, dsc, NULL);
}
cur = cur->next;
}
+6 -1
View File
@@ -29,6 +29,7 @@
/**********************
* TYPEDEFS
**********************/
struct _lv_svg_render_class;
typedef struct _lv_svg_render_obj {
struct _lv_svg_render_obj * next;
@@ -42,6 +43,10 @@ typedef struct _lv_svg_render_obj {
struct _lv_svg_render_obj * head;
char * fill_ref;
char * stroke_ref;
struct _lv_svg_render_class * clz;
} lv_svg_render_obj_t;
typedef struct _lv_svg_render_class {
void (*set_paint_ref)(struct _lv_svg_render_obj * obj, lv_vector_draw_dsc_t * dsc,
const struct _lv_svg_render_obj * target_obj, bool fill);
@@ -51,7 +56,7 @@ typedef struct _lv_svg_render_obj {
void (*get_bounds)(const struct _lv_svg_render_obj * obj, lv_area_t * area);
void (*get_size)(const struct _lv_svg_render_obj * obj, uint32_t * size);
void (*destroy)(struct _lv_svg_render_obj * obj);
} lv_svg_render_obj_t;
} lv_svg_render_class;
typedef struct _lv_svg_render_hal {
void (*load_image)(const char * image_url, lv_draw_image_dsc_t * img_dsc);