feat(libs): add SVG rendering support (#6845)
Signed-off-by: zhangjipeng <zhangjipeng@xiaomi.com> Co-authored-by: zhangjipeng <zhangjipeng@xiaomi.com>
8
Kconfig
@ -1299,6 +1299,14 @@ menu "LVGL configuration"
|
||||
bool "Decode whole image to RAM for bin decoder"
|
||||
default n
|
||||
|
||||
config LV_USE_SVG
|
||||
bool "SVG library"
|
||||
depends on LV_USE_VECTOR_GRAPHIC
|
||||
|
||||
config LV_USE_SVG_ANIMATION
|
||||
bool "SVG animation"
|
||||
depends on LV_USE_SVG
|
||||
|
||||
config LV_USE_RLE
|
||||
bool "LVGL's version of RLE compression method"
|
||||
|
||||
|
49
docs/libs/svg.rst
Normal file
@ -0,0 +1,49 @@
|
||||
.. _svg:
|
||||
|
||||
==============
|
||||
SVG support
|
||||
==============
|
||||
|
||||
Scalable Vector Graphics (SVG) Tiny 1.2 support in LVGL.
|
||||
|
||||
Detailed introduction: https://www.w3.org/TR/SVGTiny12/
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Enable :c:macro:`LV_USE_SVG` in ``lv_conf.h``.
|
||||
|
||||
See the examples below.
|
||||
|
||||
If you need support SVG animation attribute parsing,
|
||||
you can enable :c:macro:`LV_USE_SVG_ANIMATION` in ``lv_conf.h``.
|
||||
|
||||
.. _svg_example:
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. include:: ../examples/libs/svg/index.rst
|
||||
|
||||
.. code:: c
|
||||
|
||||
lv_svg_node_t * svg_doc;
|
||||
const char* svg_data = "<svg><rect x=\"0\" y=\"0\" width=\"100\" height=\"100\"/></svg>";
|
||||
|
||||
/* Create an SVG DOM tree*/
|
||||
svg_doc = lv_svg_load_data(svg_data, svg_len);
|
||||
...
|
||||
|
||||
/* Draw SVG image*/
|
||||
lv_draw_svg(layer, svg_doc);
|
||||
...
|
||||
|
||||
/* Release the DOM tree*/
|
||||
lv_svg_node_delete(svg_doc);
|
||||
|
||||
.. _svg_api:
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
|
@ -25,6 +25,7 @@ extern "C" {
|
||||
#include "tjpgd/lv_example_tjpgd.h"
|
||||
#include "libjpeg_turbo/lv_example_libjpeg_turbo.h"
|
||||
#include "tiny_ttf/lv_example_tiny_ttf.h"
|
||||
#include "svg/lv_example_svg.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
|
6
examples/libs/svg/index.rst
Normal file
@ -0,0 +1,6 @@
|
||||
Load and render SVG data
|
||||
---------------------------------------
|
||||
|
||||
.. lv_example:: libs/svg/lv_example_svg_1
|
||||
:language: c
|
||||
|
38
examples/libs/svg/lv_example_svg.h
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @file lv_example_svg.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_EXAMPLE_SVG_H
|
||||
#define LV_EXAMPLE_SVG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
void lv_example_svg_1(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_EXAMPLE_SVG_H*/
|
36
examples/libs/svg/lv_example_svg_1.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include "../../lv_examples.h"
|
||||
#if LV_BUILD_EXAMPLES
|
||||
#if LV_USE_SVG && LV_USE_VECTOR_GRAPHIC
|
||||
|
||||
/**
|
||||
* Load an SVG data
|
||||
*/
|
||||
static void event_cb(lv_event_t * e)
|
||||
{
|
||||
static char svg_data[] = "<svg width=\"12cm\" height=\"4cm\" viewBox=\"0 0 1200 400\">"
|
||||
"<circle cx=\"600\" cy=\"200\" r=\"100\" fill=\"red\" stroke=\"blue\" stroke-width=\"10\"/></svg>";
|
||||
|
||||
lv_layer_t * layer = lv_event_get_layer(e);
|
||||
lv_svg_node_t * svg = lv_svg_load_data(svg_data, sizeof(svg_data) / sizeof(char));
|
||||
lv_draw_svg(layer, svg);
|
||||
lv_svg_node_delete(svg);
|
||||
}
|
||||
|
||||
void lv_example_svg_1(void)
|
||||
{
|
||||
lv_obj_add_event_cb(lv_screen_active(), event_cb, LV_EVENT_DRAW_MAIN, NULL);
|
||||
}
|
||||
#else
|
||||
|
||||
void lv_example_svg_1(void)
|
||||
{
|
||||
/*TODO
|
||||
*fallback for online examples*/
|
||||
|
||||
lv_obj_t * label = lv_label_create(lv_screen_active());
|
||||
lv_label_set_text(label, "SVG is not enabled");
|
||||
lv_obj_center(label);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
@ -907,6 +907,11 @@
|
||||
/** Use external LZ4 library */
|
||||
#define LV_USE_LZ4_EXTERNAL 0
|
||||
|
||||
/*SVG library*/
|
||||
#define LV_USE_SVG 0
|
||||
#define LV_USE_SVG_ANIMATION 0
|
||||
#define LV_USE_SVG_DEBUG 0
|
||||
|
||||
/** FFmpeg library for image decoding and playing videos.
|
||||
* Supports all major image formats so do not enable other image decoder with it. */
|
||||
#define LV_USE_FFMPEG 0
|
||||
|
5
lvgl.h
@ -35,7 +35,8 @@ extern "C" {
|
||||
#include "src/misc/lv_utils.h"
|
||||
#include "src/misc/lv_iter.h"
|
||||
#include "src/misc/lv_circle_buf.h"
|
||||
|
||||
#include "src/misc/lv_tree.h"
|
||||
|
||||
#include "src/tick/lv_tick.h"
|
||||
|
||||
#include "src/core/lv_obj.h"
|
||||
@ -106,6 +107,8 @@ extern "C" {
|
||||
#include "src/libs/rlottie/lv_rlottie.h"
|
||||
#include "src/libs/ffmpeg/lv_ffmpeg.h"
|
||||
#include "src/libs/tiny_ttf/lv_tiny_ttf.h"
|
||||
#include "src/libs/svg/lv_svg.h"
|
||||
#include "src/libs/svg/lv_svg_render.h"
|
||||
|
||||
#include "src/layouts/lv_layout.h"
|
||||
|
||||
|
125
src/libs/svg/lv_svg.c
Normal file
@ -0,0 +1,125 @@
|
||||
/**
|
||||
* @file lv_svg.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_svg.h"
|
||||
#if LV_USE_SVG
|
||||
|
||||
#include "../../misc/lv_assert.h"
|
||||
#include "../../misc/lv_log.h"
|
||||
#include "../../stdlib/lv_mem.h"
|
||||
|
||||
#include "lv_svg_token.h"
|
||||
#include "lv_svg_parser.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_svg_node_constructor(const lv_tree_class_t * class_p, lv_tree_node_t * node)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
lv_svg_node_t * t = (lv_svg_node_t *)node;
|
||||
t->xml_id = NULL;
|
||||
t->type = LV_SVG_TAG_INVALID;
|
||||
lv_array_init(&t->attrs, 4, sizeof(lv_svg_attr_t));
|
||||
t->render_obj = NULL;
|
||||
}
|
||||
|
||||
static void lv_svg_node_destructor(const lv_tree_class_t * class_p, lv_tree_node_t * node)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
lv_svg_node_t * t = (lv_svg_node_t *)node;
|
||||
if(t->xml_id) {
|
||||
lv_free(t->xml_id);
|
||||
}
|
||||
for(uint32_t i = 0; i < lv_array_size(&t->attrs); i++) {
|
||||
lv_svg_attr_t * attr = lv_array_at(&t->attrs, i);
|
||||
if(attr->val_type == LV_SVG_ATTR_VALUE_PTR) {
|
||||
lv_free(attr->value.val);
|
||||
}
|
||||
}
|
||||
lv_array_deinit(&t->attrs);
|
||||
}
|
||||
|
||||
static bool svg_token_process_cb(_lv_svg_token_t * token, void * data)
|
||||
{
|
||||
_lv_svg_parser_t * parser = (_lv_svg_parser_t *)data;
|
||||
return _lv_svg_parser_token(parser, token);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
const lv_tree_class_t lv_svg_node_class = {
|
||||
.base_class = &lv_tree_node_class,
|
||||
.instance_size = sizeof(lv_svg_node_t),
|
||||
.constructor_cb = lv_svg_node_constructor,
|
||||
.destructor_cb = lv_svg_node_destructor,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
lv_svg_node_t * lv_svg_load_data(const char * svg_data, uint32_t data_len)
|
||||
{
|
||||
LV_ASSERT_NULL(svg_data);
|
||||
LV_ASSERT(data_len > 0);
|
||||
|
||||
_lv_svg_parser_t parser;
|
||||
_lv_svg_parser_init(&parser);
|
||||
|
||||
if(_lv_svg_tokenizer(svg_data, data_len, svg_token_process_cb, &parser)) {
|
||||
if(_lv_svg_parser_is_finish(&parser)) {
|
||||
lv_svg_node_t * doc = parser.doc_root;
|
||||
parser.doc_root = NULL;
|
||||
_lv_svg_parser_deinit(&parser);
|
||||
#if LV_USE_SVG_DEBUG
|
||||
_lv_svg_dump_tree(doc, 0);
|
||||
#endif
|
||||
return doc;
|
||||
}
|
||||
else {
|
||||
_lv_svg_parser_deinit(&parser);
|
||||
LV_LOG_ERROR("svg document parser raise errors!");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_lv_svg_parser_deinit(&parser);
|
||||
LV_LOG_ERROR("svg document tokenizer raise errors!");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lv_svg_node_t * lv_svg_node_create(lv_svg_node_t * parent)
|
||||
{
|
||||
lv_tree_node_t * node = lv_tree_node_create(&lv_svg_node_class, (lv_tree_node_t *)parent);
|
||||
return (lv_svg_node_t *)node;
|
||||
}
|
||||
|
||||
void lv_svg_node_delete(lv_svg_node_t * node)
|
||||
{
|
||||
LV_ASSERT_NULL(node);
|
||||
lv_tree_node_delete((lv_tree_node_t *)node);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
#endif /*LV_USE_SVG*/
|
334
src/libs/svg/lv_svg.h
Normal file
@ -0,0 +1,334 @@
|
||||
/**
|
||||
* @file lv_svg.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SVG_H
|
||||
#define LV_SVG_H
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_SVG
|
||||
|
||||
#include "../../misc/lv_array.h"
|
||||
#include "../../misc/lv_tree.h"
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
enum {
|
||||
LV_SVG_TAG_INVALID = -1,
|
||||
LV_SVG_TAG_CONTENT,
|
||||
LV_SVG_TAG_SVG,
|
||||
LV_SVG_TAG_USE,
|
||||
LV_SVG_TAG_G,
|
||||
LV_SVG_TAG_PATH,
|
||||
LV_SVG_TAG_RECT,
|
||||
LV_SVG_TAG_CIRCLE,
|
||||
LV_SVG_TAG_ELLIPSE,
|
||||
LV_SVG_TAG_LINE,
|
||||
LV_SVG_TAG_POLYLINE,
|
||||
LV_SVG_TAG_POLYGON,
|
||||
LV_SVG_TAG_SOLID_COLOR,
|
||||
LV_SVG_TAG_LINEAR_GRADIENT,
|
||||
LV_SVG_TAG_RADIAL_GRADIENT,
|
||||
LV_SVG_TAG_STOP,
|
||||
LV_SVG_TAG_DEFS,
|
||||
LV_SVG_TAG_IMAGE,
|
||||
#if LV_USE_SVG_ANIMATION
|
||||
LV_SVG_TAG_MPATH,
|
||||
LV_SVG_TAG_SET,
|
||||
LV_SVG_TAG_ANIMATE,
|
||||
LV_SVG_TAG_ANIMATE_COLOR,
|
||||
LV_SVG_TAG_ANIMATE_TRANSFORM,
|
||||
LV_SVG_TAG_ANIMATE_MOTION,
|
||||
#endif
|
||||
LV_SVG_TAG_TEXT,
|
||||
LV_SVG_TAG_TSPAN,
|
||||
LV_SVG_TAG_TEXT_AREA,
|
||||
};
|
||||
typedef int8_t lv_svg_tag_t;
|
||||
|
||||
enum {
|
||||
LV_SVG_ATTR_INVALID = 0,
|
||||
LV_SVG_ATTR_ID,
|
||||
LV_SVG_ATTR_XML_ID,
|
||||
LV_SVG_ATTR_VERSION,
|
||||
LV_SVG_ATTR_BASE_PROFILE,
|
||||
LV_SVG_ATTR_VIEWBOX,
|
||||
LV_SVG_ATTR_PRESERVE_ASPECT_RATIO,
|
||||
LV_SVG_ATTR_VIEWPORT_FILL,
|
||||
LV_SVG_ATTR_VIEWPORT_FILL_OPACITY,
|
||||
LV_SVG_ATTR_DISPLAY,
|
||||
LV_SVG_ATTR_VISIBILITY,
|
||||
LV_SVG_ATTR_X,
|
||||
LV_SVG_ATTR_Y,
|
||||
LV_SVG_ATTR_WIDTH,
|
||||
LV_SVG_ATTR_HEIGHT,
|
||||
LV_SVG_ATTR_RX,
|
||||
LV_SVG_ATTR_RY,
|
||||
LV_SVG_ATTR_CX,
|
||||
LV_SVG_ATTR_CY,
|
||||
LV_SVG_ATTR_R,
|
||||
LV_SVG_ATTR_X1,
|
||||
LV_SVG_ATTR_Y1,
|
||||
LV_SVG_ATTR_X2,
|
||||
LV_SVG_ATTR_Y2,
|
||||
LV_SVG_ATTR_POINTS,
|
||||
LV_SVG_ATTR_D,
|
||||
LV_SVG_ATTR_PATH_LENGTH,
|
||||
LV_SVG_ATTR_XLINK_HREF,
|
||||
LV_SVG_ATTR_FILL,
|
||||
LV_SVG_ATTR_FILL_RULE,
|
||||
LV_SVG_ATTR_FILL_OPACITY,
|
||||
LV_SVG_ATTR_STROKE,
|
||||
LV_SVG_ATTR_STROKE_WIDTH,
|
||||
LV_SVG_ATTR_STROKE_LINECAP,
|
||||
LV_SVG_ATTR_STROKE_LINEJOIN,
|
||||
LV_SVG_ATTR_STROKE_MITER_LIMIT,
|
||||
LV_SVG_ATTR_STROKE_DASH_ARRAY,
|
||||
LV_SVG_ATTR_STROKE_DASH_OFFSET,
|
||||
LV_SVG_ATTR_STROKE_OPACITY,
|
||||
LV_SVG_ATTR_OPACITY,
|
||||
LV_SVG_ATTR_SOLID_COLOR,
|
||||
LV_SVG_ATTR_SOLID_OPACITY,
|
||||
LV_SVG_ATTR_GRADIENT_UNITS,
|
||||
LV_SVG_ATTR_GRADIENT_STOP_OFFSET,
|
||||
LV_SVG_ATTR_GRADIENT_STOP_COLOR,
|
||||
LV_SVG_ATTR_GRADIENT_STOP_OPACITY,
|
||||
LV_SVG_ATTR_FONT_FAMILY,
|
||||
LV_SVG_ATTR_FONT_STYLE,
|
||||
LV_SVG_ATTR_FONT_VARIANT,
|
||||
LV_SVG_ATTR_FONT_WEIGHT,
|
||||
LV_SVG_ATTR_FONT_SIZE,
|
||||
LV_SVG_ATTR_TRANSFORM,
|
||||
LV_SVG_ATTR_TEXT_ANCHOR,
|
||||
#if LV_USE_SVG_ANIMATION
|
||||
LV_SVG_ATTR_ATTRIBUTE_NAME,
|
||||
LV_SVG_ATTR_ATTRIBUTE_TYPE,
|
||||
LV_SVG_ATTR_BEGIN,
|
||||
LV_SVG_ATTR_END,
|
||||
LV_SVG_ATTR_DUR,
|
||||
LV_SVG_ATTR_MIN,
|
||||
LV_SVG_ATTR_MAX,
|
||||
LV_SVG_ATTR_RESTART,
|
||||
LV_SVG_ATTR_REPEAT_COUNT,
|
||||
LV_SVG_ATTR_REPEAT_DUR,
|
||||
LV_SVG_ATTR_CALC_MODE,
|
||||
LV_SVG_ATTR_VALUES,
|
||||
LV_SVG_ATTR_KEY_TIMES,
|
||||
LV_SVG_ATTR_KEY_SPLINES,
|
||||
LV_SVG_ATTR_KEY_POINTS,
|
||||
LV_SVG_ATTR_FROM,
|
||||
LV_SVG_ATTR_TO,
|
||||
LV_SVG_ATTR_BY,
|
||||
LV_SVG_ATTR_ADDITIVE,
|
||||
LV_SVG_ATTR_ACCUMULATE,
|
||||
LV_SVG_ATTR_PATH,
|
||||
LV_SVG_ATTR_ROTATE,
|
||||
LV_SVG_ATTR_TRANSFORM_TYPE,
|
||||
#endif
|
||||
};
|
||||
typedef uint8_t lv_svg_attr_type_t;
|
||||
|
||||
enum {
|
||||
LV_SVG_TRANSFORM_TYPE_MATRIX = 1,
|
||||
LV_SVG_TRANSFORM_TYPE_TRANSLATE,
|
||||
LV_SVG_TRANSFORM_TYPE_ROTATE,
|
||||
LV_SVG_TRANSFORM_TYPE_SCALE,
|
||||
LV_SVG_TRANSFORM_TYPE_SKEW_X,
|
||||
LV_SVG_TRANSFORM_TYPE_SKEW_Y,
|
||||
};
|
||||
typedef uint8_t lv_svg_transform_type_t;
|
||||
|
||||
#if LV_USE_SVG_ANIMATION
|
||||
enum {
|
||||
LV_SVG_ANIM_REMOVE = 0,
|
||||
LV_SVG_ANIM_FREEZE,
|
||||
};
|
||||
|
||||
enum {
|
||||
LV_SVG_ANIM_RESTART_ALWAYS = 0,
|
||||
LV_SVG_ANIM_RESTART_WHEN_NOT_ACTIVE,
|
||||
LV_SVG_ANIM_RESTART_NEVER,
|
||||
};
|
||||
|
||||
enum {
|
||||
LV_SVG_ANIM_CALC_MODE_LINEAR = 0,
|
||||
LV_SVG_ANIM_CALC_MODE_PACED,
|
||||
LV_SVG_ANIM_CALC_MODE_SPLINE,
|
||||
LV_SVG_ANIM_CALC_MODE_DISCRETE,
|
||||
};
|
||||
|
||||
enum {
|
||||
LV_SVG_ANIM_ADDITIVE_REPLACE = 0,
|
||||
LV_SVG_ANIM_ADDITIVE_SUM,
|
||||
};
|
||||
|
||||
enum {
|
||||
LV_SVG_ANIM_ACCUMULATE_NONE = 0,
|
||||
LV_SVG_ANIM_ACCUMULATE_SUM,
|
||||
};
|
||||
#endif
|
||||
|
||||
enum {
|
||||
LV_SVG_ASPECT_RATIO_NONE = 0,
|
||||
LV_SVG_ASPECT_RATIO_XMIN_YMIN = (1 << 1),
|
||||
LV_SVG_ASPECT_RATIO_XMID_YMIN = (2 << 1),
|
||||
LV_SVG_ASPECT_RATIO_XMAX_YMIN = (3 << 1),
|
||||
LV_SVG_ASPECT_RATIO_XMIN_YMID = (4 << 1),
|
||||
LV_SVG_ASPECT_RATIO_XMID_YMID = (5 << 1),
|
||||
LV_SVG_ASPECT_RATIO_XMAX_YMID = (6 << 1),
|
||||
LV_SVG_ASPECT_RATIO_XMIN_YMAX = (7 << 1),
|
||||
LV_SVG_ASPECT_RATIO_XMID_YMAX = (8 << 1),
|
||||
LV_SVG_ASPECT_RATIO_XMAX_YMAX = (9 << 1),
|
||||
};
|
||||
|
||||
enum {
|
||||
LV_SVG_ASPECT_RATIO_OPT_MEET = 0,
|
||||
LV_SVG_ASPECT_RATIO_OPT_SLICE,
|
||||
};
|
||||
typedef uint32_t lv_svg_aspect_ratio_t;
|
||||
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
} lv_svg_point_t;
|
||||
|
||||
typedef struct {
|
||||
float m[3][3];
|
||||
} lv_svg_matrix_t;
|
||||
|
||||
typedef uint32_t lv_svg_color_t;
|
||||
|
||||
enum {
|
||||
LV_SVG_FILL_NONZERO = 0,
|
||||
LV_SVG_FILL_EVENODD,
|
||||
};
|
||||
typedef uint8_t lv_svg_fill_rule_t;
|
||||
|
||||
enum {
|
||||
LV_SVG_LINE_CAP_BUTT = 0,
|
||||
LV_SVG_LINE_CAP_SQUARE,
|
||||
LV_SVG_LINE_CAP_ROUND,
|
||||
};
|
||||
typedef uint8_t lv_svg_line_cap_t;
|
||||
|
||||
enum {
|
||||
LV_SVG_LINE_JOIN_MITER = 0,
|
||||
LV_SVG_LINE_JOIN_BEVEL,
|
||||
LV_SVG_LINE_JOIN_ROUND,
|
||||
};
|
||||
typedef uint8_t lv_svg_line_join_t;
|
||||
|
||||
enum {
|
||||
LV_SVG_GRADIENT_UNITS_OBJECT = 0,
|
||||
LV_SVG_GRADIENT_UNITS_USER_SPACE,
|
||||
};
|
||||
typedef uint8_t lv_svg_gradient_units_t;
|
||||
|
||||
typedef union {
|
||||
int32_t ival;
|
||||
uint32_t uval;
|
||||
float fval;
|
||||
char * sval;
|
||||
void * val;
|
||||
} lv_svg_attr_value_t;
|
||||
|
||||
/*
|
||||
* to simplify list buffer management, allocate enough memory for all data and length.
|
||||
* | size | data[0] | data[1] | data[2] | ... |
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t length;
|
||||
uint8_t data[1];
|
||||
} lv_svg_attr_values_list_t;
|
||||
|
||||
/* https://www.w3.org/TR/SVGTiny12/svgudomidl.html */
|
||||
enum {
|
||||
LV_SVG_PATH_CMD_MOVE_TO = 77,
|
||||
LV_SVG_PATH_CMD_LINE_TO = 76,
|
||||
LV_SVG_PATH_CMD_CURVE_TO = 67,
|
||||
LV_SVG_PATH_CMD_QUAD_TO = 81,
|
||||
LV_SVG_PATH_CMD_CLOSE = 90,
|
||||
};
|
||||
|
||||
/*
|
||||
* to simplify list buffer management, allocate enough memory for all path data and cmd.
|
||||
* | cmd | data[0] | data[1] | data[2] | ... |
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t cmd;
|
||||
uint8_t data[1];
|
||||
} lv_svg_attr_path_value_t;
|
||||
|
||||
enum {
|
||||
LV_SVG_ATTR_VALUE_DATA = 0,
|
||||
LV_SVG_ATTR_VALUE_PTR,
|
||||
};
|
||||
typedef uint8_t lv_svg_attr_value_type_t;
|
||||
|
||||
enum {
|
||||
LV_SVG_ATTR_VALUE_NONE = 0,
|
||||
LV_SVG_ATTR_VALUE_INITIAL,
|
||||
LV_SVG_ATTR_VALUE_INHERIT,
|
||||
};
|
||||
typedef uint8_t lv_svg_attr_value_class_t;
|
||||
|
||||
typedef struct {
|
||||
lv_svg_attr_type_t id;
|
||||
lv_svg_attr_value_type_t val_type;
|
||||
lv_svg_attr_value_class_t class_type;
|
||||
lv_svg_attr_value_t value;
|
||||
} lv_svg_attr_t;
|
||||
|
||||
struct _lv_svg_render_obj;
|
||||
|
||||
typedef struct {
|
||||
lv_tree_node_t base;
|
||||
char * xml_id; /* xml_id or content */
|
||||
lv_svg_tag_t type;
|
||||
lv_array_t attrs;
|
||||
struct _lv_svg_render_obj * render_obj;
|
||||
} lv_svg_node_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* @brief Loading SVG data and creating the DOM tree
|
||||
* @param svg_data pointer to the SVG data
|
||||
* @param data_len the SVG data length
|
||||
*/
|
||||
lv_svg_node_t * lv_svg_load_data(const char * svg_data, uint32_t data_len);
|
||||
|
||||
/**
|
||||
* @brief Create an SVG DOM node
|
||||
* @param parent pointer to the parent node
|
||||
* @return true: an new SVG DOM node, false: NULL
|
||||
*/
|
||||
lv_svg_node_t * lv_svg_node_create(lv_svg_node_t * parent);
|
||||
|
||||
/**
|
||||
* @brief Delete an SVG DOM subtree
|
||||
* @param node pointer to an SVG DOM subtree
|
||||
*/
|
||||
void lv_svg_node_delete(lv_svg_node_t * node);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#define LV_SVG_NODE_CHILD(n, i) \
|
||||
((lv_svg_node_t *)(LV_TREE_NODE((n))->children[i]))
|
||||
|
||||
#define LV_SVG_NODE(n) ((lv_svg_node_t*)(n))
|
||||
|
||||
#endif /*LV_USE_SVG*/
|
||||
|
||||
#endif /*LV_SVG_H*/
|
2309
src/libs/svg/lv_svg_parser.c
Normal file
84
src/libs/svg/lv_svg_parser.h
Normal file
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @file lv_svg_parser.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SVG_PARSER_H
|
||||
#define LV_SVG_PARSER_H
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_SVG
|
||||
|
||||
#include "lv_svg.h"
|
||||
#include "lv_svg_token.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef enum {
|
||||
LV_SVG_PARSER_PROCESS = 0,
|
||||
LV_SVG_PARSER_IGNORE,
|
||||
} _lv_svg_parser_state_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t state;
|
||||
char * ignore_name;
|
||||
uint32_t ignore_len;
|
||||
int32_t dpi;
|
||||
lv_svg_node_t * doc_root;
|
||||
lv_svg_node_t * cur_node;
|
||||
} _lv_svg_parser_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* @brief Initialize the SVG parser
|
||||
* @param parser pointer to a parser object
|
||||
*/
|
||||
void _lv_svg_parser_init(_lv_svg_parser_t * parser);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the SVG parser
|
||||
* @param parser pointer to a parser object
|
||||
*/
|
||||
void _lv_svg_parser_deinit(_lv_svg_parser_t * parser);
|
||||
|
||||
/**
|
||||
* @brief Parse an SVG document
|
||||
* @param parser pointer to a parser object
|
||||
* @param token pointer to a token object
|
||||
* @return true: the parsing is finished, false: the parsing is not finished yet.
|
||||
*/
|
||||
bool _lv_svg_parser_token(_lv_svg_parser_t * parser, const _lv_svg_token_t * token);
|
||||
|
||||
/**
|
||||
* @brief Check if the parsing is finished
|
||||
* @param parser pointer to a parser object
|
||||
* @return true: the parsing is finished, false: the parsing is not finished yet.
|
||||
*/
|
||||
bool _lv_svg_parser_is_finish(_lv_svg_parser_t * parser);
|
||||
|
||||
/**
|
||||
* @brief Dump the SVG tree
|
||||
* @param root pointer to the root of the SVG tree
|
||||
* @param depth the depth of the current node in the tree
|
||||
*/
|
||||
void _lv_svg_dump_tree(lv_svg_node_t * root, int depth);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_SVG*/
|
||||
|
||||
#endif /*LV_SVG_PARSER_H*/
|
2204
src/libs/svg/lv_svg_render.c
Normal file
98
src/libs/svg/lv_svg_render.h
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @file lv_svg_render.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SVG_RENDER_H
|
||||
#define LV_SVG_RENDER_H
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_SVG && LV_USE_VECTOR_GRAPHIC
|
||||
#include "lv_svg.h"
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../draw/lv_draw_vector_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_SVG_RENDER_OBJ(n) ((lv_svg_render_obj_t*)(n))
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct _lv_svg_render_obj {
|
||||
struct _lv_svg_render_obj * next;
|
||||
uint32_t flags;
|
||||
char * id;
|
||||
lv_vector_draw_dsc_t dsc;
|
||||
lv_matrix_t matrix;
|
||||
|
||||
/* for url(XXX) reference */
|
||||
struct _lv_svg_render_obj * head;
|
||||
char * fill_ref;
|
||||
char * stroke_ref;
|
||||
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);
|
||||
|
||||
void (*init)(struct _lv_svg_render_obj * obj, const lv_svg_node_t * node);
|
||||
void (*render)(const struct _lv_svg_render_obj * obj, lv_vector_dsc_t * dsc, const lv_matrix_t * matrix);
|
||||
void (*set_attr)(struct _lv_svg_render_obj * obj, lv_vector_draw_dsc_t * dsc, const lv_svg_attr_t * attr);
|
||||
void (*get_bounds)(const struct _lv_svg_render_obj * obj, lv_area_t * area);
|
||||
void (*destroy)(struct _lv_svg_render_obj * obj);
|
||||
} lv_svg_render_obj_t;
|
||||
|
||||
typedef struct _lv_svg_render_hal {
|
||||
void (*load_image)(const char * image_url, lv_draw_image_dsc_t * img_dsc);
|
||||
const char * (*get_font_path)(const char * font_family);
|
||||
} lv_svg_render_hal_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* @brief Initialize the SVG render
|
||||
* @param hal pointer to a structure with rendering functions
|
||||
*/
|
||||
void lv_svg_render_init(const lv_svg_render_hal_t * hal);
|
||||
|
||||
/**
|
||||
* @brief Create a new SVG render from an SVG document
|
||||
* @param svg_doc pointer to the SVG document
|
||||
* @return pointer to the new SVG render object
|
||||
*/
|
||||
lv_svg_render_obj_t * lv_svg_render_create(const lv_svg_node_t * svg_doc);
|
||||
|
||||
/**
|
||||
* @brief Delete an SVG render object
|
||||
* @param render pointer to the SVG render object to delete
|
||||
*/
|
||||
void lv_svg_render_delete(lv_svg_render_obj_t * render);
|
||||
|
||||
/**
|
||||
* @brief Render an SVG object to a vector graphics
|
||||
* @param dsc pointer to the vector graphics descriptor
|
||||
* @param render pointer to the SVG render object to render
|
||||
*/
|
||||
void lv_draw_svg_render(lv_vector_dsc_t * dsc, const lv_svg_render_obj_t * render);
|
||||
|
||||
/**
|
||||
* @brief Draw an SVG document to a layer
|
||||
* @param layer pointer to the target layer
|
||||
* @param svg_doc pointer to the SVG document to draw
|
||||
*/
|
||||
void lv_draw_svg(lv_layer_t * layer, const lv_svg_node_t * svg_doc);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_SVG*/
|
||||
|
||||
#endif /*LV_SVG_RENDER_H*/
|
483
src/libs/svg/lv_svg_token.c
Normal file
@ -0,0 +1,483 @@
|
||||
/**
|
||||
* @file lv_svg_token.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_svg_token.h"
|
||||
#if LV_USE_SVG
|
||||
|
||||
#include "../../../lvgl.h"
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*
|
||||
* tag mask quote mask tag search comment doc type xml inst
|
||||
* | 0 0 0 | 0 0 | 0 | 0 | 0 | 0 | 0 |
|
||||
*/
|
||||
enum {
|
||||
SVG_TAG_MASK = (1 << 3) - 1,
|
||||
SVG_QUOTE_MASK = (1 << 5) - (1 << 3),
|
||||
SVG_TAG = 1 << 5,
|
||||
SVG_SEARCH = 1 << 6,
|
||||
SVG_COMMENT = 1 << 7,
|
||||
SVG_DOCTYPE = 1 << 8,
|
||||
SVG_XMLINST = 1 << 9,
|
||||
};
|
||||
typedef uint32_t _lv_svg_parser_bits_t;
|
||||
|
||||
enum {
|
||||
SVG_NO_QUOTE = 0,
|
||||
SVG_SINGLE_QUOTE = 1,
|
||||
SVG_DOUBLE_QUOTE = 2,
|
||||
};
|
||||
typedef uint32_t _lv_svg_parser_quote_t;
|
||||
|
||||
enum {
|
||||
SVG_NO_TAG = 0,
|
||||
SVG_TAG_NAME = 1,
|
||||
SVG_ATTR_START = 2,
|
||||
SVG_ATTR_NAME = 3,
|
||||
SVG_SEARCH_EQUAL = 4,
|
||||
SVG_SEARCH_VALUE = 5,
|
||||
SVG_QUOTE_VALUE = 6,
|
||||
SVG_VALUE = 7,
|
||||
};
|
||||
typedef uint32_t _lv_svg_parser_tag_state_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t flags;
|
||||
const char * cur;
|
||||
const char * end;
|
||||
} _lv_svg_parser_state_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void _set_state(_lv_svg_parser_state_t * state, uint32_t bit)
|
||||
{
|
||||
state->flags |= bit;
|
||||
}
|
||||
|
||||
static void _clear_state(_lv_svg_parser_state_t * state, uint32_t bit)
|
||||
{
|
||||
state->flags &= ~bit;
|
||||
}
|
||||
|
||||
static bool _is_state(_lv_svg_parser_state_t * state, uint32_t bit)
|
||||
{
|
||||
return state->flags & bit;
|
||||
}
|
||||
|
||||
static void _set_tag_state(_lv_svg_parser_state_t * state, uint32_t bit)
|
||||
{
|
||||
state->flags = (state->flags & ~SVG_TAG_MASK) | bit;
|
||||
}
|
||||
|
||||
static void _set_quote_state(_lv_svg_parser_state_t * state, uint32_t bit)
|
||||
{
|
||||
state->flags = (state->flags & ~SVG_QUOTE_MASK) | (bit << 3);
|
||||
}
|
||||
|
||||
static bool _special_handle(_lv_svg_parser_state_t * state)
|
||||
{
|
||||
return state->flags & (SVG_TAG | SVG_SEARCH | SVG_TAG_MASK | SVG_COMMENT | SVG_DOCTYPE | SVG_XMLINST);
|
||||
}
|
||||
|
||||
static void _lv_svg_token_init(_lv_svg_token_t * token)
|
||||
{
|
||||
token->start = NULL;
|
||||
token->end = NULL;
|
||||
token->type = LV_SVG_TOKEN_CONTENT;
|
||||
token->flat = false;
|
||||
token->cur_attr = NULL;
|
||||
lv_array_init(&token->attrs, LV_ARRAY_DEFAULT_CAPACITY, sizeof(_lv_svg_token_attr_t));
|
||||
}
|
||||
|
||||
static void _lv_svg_token_reset(_lv_svg_token_t * token)
|
||||
{
|
||||
token->start = NULL;
|
||||
token->end = NULL;
|
||||
token->type = LV_SVG_TOKEN_CONTENT;
|
||||
token->flat = false;
|
||||
token->cur_attr = NULL;
|
||||
lv_array_clear(&token->attrs);
|
||||
}
|
||||
|
||||
static bool _lv_svg_token_process(_lv_svg_token_t * token, svg_token_process cb, void * data)
|
||||
{
|
||||
if(!token->start || SVG_TOKEN_LEN(token) == 0)
|
||||
return true;
|
||||
|
||||
bool ret = cb(token, data);
|
||||
_lv_svg_token_reset(token);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static _lv_svg_token_attr_t * _new_svg_attr(_lv_svg_token_t * token)
|
||||
{
|
||||
if((lv_array_size(&token->attrs) + 1) > lv_array_capacity(&token->attrs)) {
|
||||
lv_array_resize(&token->attrs, token->attrs.capacity << 1);
|
||||
}
|
||||
|
||||
token->attrs.size++;
|
||||
_lv_svg_token_attr_t * attr = lv_array_at(&token->attrs, token->attrs.size - 1);
|
||||
lv_memset(attr, 0, sizeof(_lv_svg_token_attr_t));
|
||||
return attr;
|
||||
}
|
||||
|
||||
static void _svg_parser_xml_inst(_lv_svg_parser_state_t * state, _lv_svg_token_t * token)
|
||||
{
|
||||
LV_UNUSED(token);
|
||||
|
||||
while(state->cur <= state->end) {
|
||||
char ch = *(state->cur);
|
||||
if(ch == '>' && (*(state->cur - 1)) == '?') {
|
||||
_clear_state(state, SVG_XMLINST);
|
||||
state->cur++;
|
||||
break;
|
||||
}
|
||||
state->cur++;
|
||||
}
|
||||
}
|
||||
|
||||
static void _svg_parser_comment(_lv_svg_parser_state_t * state, _lv_svg_token_t * token)
|
||||
{
|
||||
LV_UNUSED(token);
|
||||
|
||||
while(state->cur <= state->end) {
|
||||
char ch = *(state->cur);
|
||||
if(ch == '>' && (*(state->cur - 1)) == '-' && (*(state->cur - 2)) == '-') {
|
||||
_clear_state(state, SVG_COMMENT);
|
||||
state->cur++;
|
||||
break;
|
||||
}
|
||||
state->cur++;
|
||||
}
|
||||
}
|
||||
|
||||
static void _svg_parser_doctype(_lv_svg_parser_state_t * state, _lv_svg_token_t * token)
|
||||
{
|
||||
LV_UNUSED(token);
|
||||
|
||||
//TODO: processing DTD type
|
||||
while(state->cur <= state->end) {
|
||||
char ch = *(state->cur);
|
||||
if(ch == '>') {
|
||||
_clear_state(state, SVG_DOCTYPE);
|
||||
state->cur++;
|
||||
break;
|
||||
}
|
||||
state->cur++;
|
||||
}
|
||||
}
|
||||
|
||||
static bool _svg_parser_tag(_lv_svg_parser_state_t * state, _lv_svg_token_t * token, svg_token_process cb, void * data)
|
||||
{
|
||||
while(state->cur <= state->end) {
|
||||
switch(state->flags & SVG_TAG_MASK) {
|
||||
case SVG_NO_TAG: {
|
||||
if(!_lv_svg_token_process(token, cb, data)) {
|
||||
return false;
|
||||
}
|
||||
state->cur++;
|
||||
}
|
||||
return true;
|
||||
case SVG_TAG_NAME: {
|
||||
char ch = *(state->cur);
|
||||
if(ch == '/') {
|
||||
token->type = LV_SVG_TOKEN_END;
|
||||
state->cur++;
|
||||
if(!token->start) {
|
||||
token->start = state->cur;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if(ch == '>' || isspace(ch)) {
|
||||
token->end = state->cur;
|
||||
_set_tag_state(state, SVG_ATTR_START);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if(!token->start) {
|
||||
token->type = LV_SVG_TOKEN_BEGIN;
|
||||
token->start = state->cur;
|
||||
}
|
||||
state->cur++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SVG_ATTR_START: {
|
||||
char ch = *(state->cur);
|
||||
if(!isspace(ch) && ch != '\'' && ch != '\"') {
|
||||
if(ch == '/') {
|
||||
token->flat = true;
|
||||
state->cur++;
|
||||
continue;
|
||||
}
|
||||
if(ch == '>') {
|
||||
_set_tag_state(state, SVG_NO_TAG);
|
||||
}
|
||||
else {
|
||||
token->cur_attr = NULL;
|
||||
_set_tag_state(state, SVG_ATTR_NAME);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SVG_ATTR_NAME: {
|
||||
if(!token->cur_attr) {
|
||||
token->cur_attr = _new_svg_attr(token);
|
||||
}
|
||||
char ch = *(state->cur);
|
||||
if(isspace(ch) || ch == '=' || ch == '/' || ch == '>') {
|
||||
token->cur_attr->name_end = state->cur;
|
||||
_set_tag_state(state, SVG_SEARCH_EQUAL);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if(!token->cur_attr->name_start) {
|
||||
token->cur_attr->name_start = state->cur;
|
||||
}
|
||||
state->cur++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SVG_SEARCH_EQUAL: {
|
||||
char ch = *(state->cur);
|
||||
if(!isspace(ch) && ch != '/' && ch != '\'' && ch != '\"') {
|
||||
if(ch == '=') {
|
||||
_set_tag_state(state, SVG_SEARCH_VALUE);
|
||||
}
|
||||
else {
|
||||
// attr name has empty value
|
||||
token->cur_attr = NULL;
|
||||
_set_tag_state(state, SVG_ATTR_START);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SVG_SEARCH_VALUE: {
|
||||
char ch = *(state->cur);
|
||||
if(!isspace(ch)) {
|
||||
if(ch == '\'' || ch == '\"') {
|
||||
if(ch == '\'') {
|
||||
_set_quote_state(state, SVG_SINGLE_QUOTE);
|
||||
}
|
||||
else {
|
||||
_set_quote_state(state, SVG_DOUBLE_QUOTE);
|
||||
}
|
||||
_set_tag_state(state, SVG_QUOTE_VALUE);
|
||||
}
|
||||
else {
|
||||
_set_tag_state(state, SVG_VALUE);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SVG_QUOTE_VALUE: {
|
||||
char ch = *(state->cur);
|
||||
if((ch == '\'' && ((state->flags & SVG_QUOTE_MASK) >> 3) == SVG_SINGLE_QUOTE)
|
||||
|| (ch == '\"' && ((state->flags & SVG_QUOTE_MASK) >> 3) == SVG_DOUBLE_QUOTE)) {
|
||||
if(!token->cur_attr->value_start) {
|
||||
token->cur_attr->value_start = state->cur;
|
||||
}
|
||||
token->cur_attr->value_end = state->cur;
|
||||
_set_quote_state(state, SVG_NO_QUOTE);
|
||||
_set_tag_state(state, SVG_ATTR_START);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if(!token->cur_attr->value_start) {
|
||||
token->cur_attr->value_start = state->cur;
|
||||
}
|
||||
state->cur++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SVG_VALUE: {
|
||||
char ch = *(state->cur);
|
||||
if(isspace(ch) || ch == '>' || ch == '/') {
|
||||
if(!token->cur_attr->value_start) {
|
||||
token->cur_attr->value_start = state->cur;
|
||||
}
|
||||
token->cur_attr->value_end = state->cur;
|
||||
_set_quote_state(state, SVG_NO_QUOTE);
|
||||
_set_tag_state(state, SVG_ATTR_START);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if(!token->cur_attr->value_start) {
|
||||
token->cur_attr->value_start = state->cur;
|
||||
}
|
||||
state->cur++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
state->cur++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
bool _lv_svg_tokenizer(const char * svg_data, uint32_t data_len, svg_token_process cb, void * data)
|
||||
{
|
||||
LV_ASSERT_NULL(svg_data);
|
||||
LV_ASSERT(data_len > 0);
|
||||
LV_ASSERT_NULL(cb);
|
||||
LV_ASSERT_NULL(data);
|
||||
|
||||
_lv_svg_token_t token;
|
||||
_lv_svg_token_init(&token);
|
||||
_lv_svg_parser_state_t state = {
|
||||
.flags = 0,
|
||||
.cur = svg_data,
|
||||
.end = svg_data + data_len,
|
||||
};
|
||||
|
||||
while(state.cur <= state.end) {
|
||||
char ch = *(state.cur);
|
||||
if(ch == '\r' || ch == '\n') { // skip LR character
|
||||
state.cur++;
|
||||
continue;
|
||||
}
|
||||
else if(_special_handle(&state)) {
|
||||
if(_is_state(&state, SVG_TAG)) {
|
||||
_clear_state(&state, SVG_TAG);
|
||||
switch(ch) {
|
||||
case '/': // end tag
|
||||
_set_tag_state(&state, SVG_TAG_NAME);
|
||||
break;
|
||||
case '!': {
|
||||
// <!-- comment or <!DOCTYPE>
|
||||
_set_state(&state, SVG_SEARCH); // get more character
|
||||
state.cur++;
|
||||
}
|
||||
break;
|
||||
case '?': {
|
||||
// xml instruction
|
||||
_set_state(&state, SVG_XMLINST);
|
||||
state.cur++;
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
if(isalpha(ch)) {
|
||||
_set_tag_state(&state, SVG_TAG_NAME);
|
||||
}
|
||||
else {
|
||||
LV_LOG_ERROR("svg document parser error!");
|
||||
lv_array_deinit(&token.attrs);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// process token
|
||||
if(!_lv_svg_token_process(&token, cb, data)) {
|
||||
LV_LOG_ERROR("svg document parser error!");
|
||||
lv_array_deinit(&token.attrs);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(_is_state(&state, SVG_SEARCH)) {
|
||||
if(ch == '-' || isalpha(ch)) {
|
||||
if(!token.start) {
|
||||
token.start = state.cur;
|
||||
}
|
||||
token.end = state.cur;
|
||||
}
|
||||
else {
|
||||
// processing as a normal tag name.
|
||||
_clear_state(&state, SVG_SEARCH);
|
||||
_set_tag_state(&state, SVG_TAG_NAME);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(((token.end - token.start) == 1) && (token.start[0] == '-') && (token.start[1] == '-')) {
|
||||
// is <!-- comment start
|
||||
_clear_state(&state, SVG_SEARCH);
|
||||
token.start = token.end = NULL;
|
||||
_set_state(&state, SVG_COMMENT);
|
||||
}
|
||||
else if(((token.end - token.start) == 6) && (strncmp(token.start, "DOCTYPE", 7) == 0)) {
|
||||
_clear_state(&state, SVG_SEARCH);
|
||||
token.start = token.end = NULL;
|
||||
_set_state(&state, SVG_DOCTYPE);
|
||||
}
|
||||
state.cur++;
|
||||
}
|
||||
else if(_is_state(&state, SVG_COMMENT)) {
|
||||
_svg_parser_comment(&state, &token);
|
||||
}
|
||||
else if(_is_state(&state, SVG_DOCTYPE)) {
|
||||
_svg_parser_doctype(&state, &token);
|
||||
}
|
||||
else if(_is_state(&state, SVG_TAG_MASK)) {
|
||||
if(!_svg_parser_tag(&state, &token, cb, data)) {
|
||||
LV_LOG_ERROR("svg document parser error!");
|
||||
lv_array_deinit(&token.attrs);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(_is_state(&state, SVG_XMLINST)) {
|
||||
_svg_parser_xml_inst(&state, &token);
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch(ch) {
|
||||
case '<': {
|
||||
_set_state(&state, SVG_TAG); // start a new tag
|
||||
state.cur++;
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
if(!token.start) {
|
||||
token.start = state.cur;
|
||||
}
|
||||
if(state.cur == state.end) {
|
||||
goto finish;
|
||||
}
|
||||
token.end = ++state.cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finish:
|
||||
lv_array_deinit(&token.attrs);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
#endif /*LV_USE_SVG*/
|
70
src/libs/svg/lv_svg_token.h
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @file lv_svg_token.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SVG_TOKEN_H
|
||||
#define LV_SVG_TOKEN_H
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_SVG
|
||||
|
||||
#include "../../misc/lv_array.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define SVG_TOKEN_LEN(t) ((t)->end - (t)->start)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef enum {
|
||||
LV_SVG_TOKEN_BEGIN = 0,
|
||||
LV_SVG_TOKEN_END,
|
||||
LV_SVG_TOKEN_CONTENT,
|
||||
} _lv_svg_token_type_t;
|
||||
|
||||
typedef struct {
|
||||
const char * name_start;
|
||||
const char * name_end;
|
||||
const char * value_start;
|
||||
const char * value_end;
|
||||
} _lv_svg_token_attr_t;
|
||||
|
||||
typedef struct {
|
||||
const char * start;
|
||||
const char * end;
|
||||
_lv_svg_token_type_t type;
|
||||
bool flat;
|
||||
_lv_svg_token_attr_t * cur_attr;
|
||||
lv_array_t attrs;
|
||||
} _lv_svg_token_t;
|
||||
|
||||
typedef bool (*svg_token_process)(_lv_svg_token_t * token, void * user_data);
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* @brief Parse SVG data and call a callback for each token
|
||||
* @param svg_data pointer to SVG data
|
||||
* @param len length of the SVG data
|
||||
* @param cb callback function to be called for each token
|
||||
* @param user_data custom data to be passed to the callback function
|
||||
* @return true: SVG data successfully parsed, false: error occurred
|
||||
*/
|
||||
bool _lv_svg_tokenizer(const char * svg_data, uint32_t len, svg_token_process cb, void * user_data);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#endif /*LV_USE_SVG*/
|
||||
|
||||
#endif /*LV_SVG_TOKEN_H*/
|
@ -2900,6 +2900,29 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*SVG library*/
|
||||
#ifndef LV_USE_SVG
|
||||
#ifdef CONFIG_LV_USE_SVG
|
||||
#define LV_USE_SVG CONFIG_LV_USE_SVG
|
||||
#else
|
||||
#define LV_USE_SVG 0
|
||||
#endif
|
||||
#endif
|
||||
#ifndef LV_USE_SVG_ANIMATION
|
||||
#ifdef CONFIG_LV_USE_SVG_ANIMATION
|
||||
#define LV_USE_SVG_ANIMATION CONFIG_LV_USE_SVG_ANIMATION
|
||||
#else
|
||||
#define LV_USE_SVG_ANIMATION 0
|
||||
#endif
|
||||
#endif
|
||||
#ifndef LV_USE_SVG_DEBUG
|
||||
#ifdef CONFIG_LV_USE_SVG_DEBUG
|
||||
#define LV_USE_SVG_DEBUG CONFIG_LV_USE_SVG_DEBUG
|
||||
#else
|
||||
#define LV_USE_SVG_DEBUG 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** FFmpeg library for image decoding and playing videos.
|
||||
* Supports all major image formats so do not enable other image decoder with it. */
|
||||
#ifndef LV_USE_FFMPEG
|
||||
|
187
src/misc/lv_tree.c
Normal file
@ -0,0 +1,187 @@
|
||||
/**
|
||||
* @file lv_tree.c
|
||||
* Tree.
|
||||
* The nodes are dynamically allocated by the 'lv_mem' module,
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_tree.h"
|
||||
#include "../stdlib/lv_mem.h"
|
||||
#include "../stdlib/lv_string.h"
|
||||
|
||||
#include "lv_assert.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define INIT_CHILDREN_CAP 4
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
const lv_tree_class_t lv_tree_node_class = {
|
||||
.base_class = NULL,
|
||||
.instance_size = sizeof(lv_tree_node_t),
|
||||
.constructor_cb = NULL,
|
||||
.destructor_cb = NULL,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void _lv_tree_node_construct(const lv_tree_class_t * class_p, lv_tree_node_t * node)
|
||||
{
|
||||
if(node->class_p->base_class) {
|
||||
const lv_tree_class_t * original_class_p = node->class_p;
|
||||
|
||||
node->class_p = node->class_p->base_class;
|
||||
|
||||
_lv_tree_node_construct(class_p, node);
|
||||
|
||||
node->class_p = original_class_p;
|
||||
}
|
||||
|
||||
if(node->class_p->constructor_cb) node->class_p->constructor_cb(class_p, node);
|
||||
}
|
||||
|
||||
static void _lv_tree_node_destruct(lv_tree_node_t * node)
|
||||
{
|
||||
if(node->class_p->destructor_cb) node->class_p->destructor_cb(node->class_p, node);
|
||||
|
||||
if(node->class_p->base_class) {
|
||||
node->class_p = node->class_p->base_class;
|
||||
|
||||
_lv_tree_node_destruct(node);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_instance_size(const lv_tree_class_t * class_p)
|
||||
{
|
||||
const lv_tree_class_t * base = class_p;
|
||||
while(base && base->instance_size == 0)
|
||||
base = base->base_class;
|
||||
|
||||
return base->instance_size;
|
||||
}
|
||||
|
||||
static lv_tree_node_t * _lv_tree_class_create_node(const lv_tree_class_t * class_p, lv_tree_node_t * parent)
|
||||
{
|
||||
uint32_t s = get_instance_size(class_p);
|
||||
lv_tree_node_t * node = lv_malloc(s);
|
||||
if(node == NULL) return NULL;
|
||||
lv_memzero(node, s);
|
||||
node->class_p = class_p;
|
||||
node->parent = parent;
|
||||
node->child_cap = INIT_CHILDREN_CAP;
|
||||
node->children = lv_malloc(sizeof(lv_tree_node_t *) * node->child_cap);
|
||||
if(parent != NULL) {
|
||||
parent->child_cnt++;
|
||||
if(parent->child_cnt == parent->child_cap) {
|
||||
parent->child_cap <<= 1;
|
||||
parent->children = lv_realloc(parent->children, sizeof(lv_tree_node_t *) * parent->child_cap);
|
||||
}
|
||||
parent->children[parent->child_cnt - 1] = node;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
lv_tree_node_t * lv_tree_node_create(const lv_tree_class_t * class_p, lv_tree_node_t * parent)
|
||||
{
|
||||
lv_tree_node_t * node = _lv_tree_class_create_node(class_p, parent);
|
||||
LV_ASSERT_NULL(node);
|
||||
_lv_tree_node_construct(node->class_p, node);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool _lv_tree_node_destructor_cb(const lv_tree_node_t * n, void * user_data)
|
||||
{
|
||||
LV_UNUSED(user_data);
|
||||
if(n) {
|
||||
lv_tree_node_t * node = (lv_tree_node_t *)n;
|
||||
_lv_tree_node_destruct(node);
|
||||
lv_free(node->children);
|
||||
lv_free(node);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void lv_tree_node_delete(lv_tree_node_t * node)
|
||||
{
|
||||
if(node) {
|
||||
if(node->parent) {
|
||||
/* Remove from parent */
|
||||
lv_tree_node_t * parent = node->parent;
|
||||
for(uint32_t i = 0; i < parent->child_cnt; i++) {
|
||||
if(parent->children[i] == node) {
|
||||
parent->children[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
lv_tree_walk(node, LV_TREE_WALK_POST_ORDER, _lv_tree_node_destructor_cb, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
bool lv_tree_walk(const lv_tree_node_t * node,
|
||||
lv_tree_walk_mode_t mode,
|
||||
lv_tree_traverse_cb_t cb,
|
||||
lv_tree_before_cb_t bcb,
|
||||
lv_tree_after_cb_t acb,
|
||||
void * user_data)
|
||||
{
|
||||
if(node && cb) {
|
||||
if(mode == LV_TREE_WALK_PRE_ORDER) {
|
||||
if(bcb && !bcb(node, user_data)) {
|
||||
return false;
|
||||
}
|
||||
if(!cb(node, user_data)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for(uint32_t i = 0; i < node->child_cnt; i++) {
|
||||
if(!lv_tree_walk(node->children[i], mode, cb, bcb, acb, user_data)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(mode == LV_TREE_WALK_PRE_ORDER) {
|
||||
if(acb) {
|
||||
acb(node, user_data);
|
||||
}
|
||||
}
|
||||
|
||||
if(mode == LV_TREE_WALK_POST_ORDER) {
|
||||
if(bcb && !bcb(node, user_data)) {
|
||||
return false;
|
||||
}
|
||||
if(!cb(node, user_data)) {
|
||||
return false;
|
||||
}
|
||||
if(acb) {
|
||||
acb(node, user_data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
105
src/misc/lv_tree.h
Normal file
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @file lv_tree.h
|
||||
* Tree. The tree nodes are dynamically allocated by the 'lv_mem' module.
|
||||
*/
|
||||
|
||||
#ifndef LV_TREE_H
|
||||
#define LV_TREE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_TREE_NODE(n) ((lv_tree_node_t*)(n))
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_tree_node_t;
|
||||
|
||||
/**
|
||||
* Describe the common methods of every object.
|
||||
* Similar to a C++ class.
|
||||
*/
|
||||
typedef struct _lv_tree_class_t {
|
||||
const struct _lv_tree_class_t * base_class;
|
||||
uint32_t instance_size;
|
||||
void (*constructor_cb)(const struct _lv_tree_class_t * class_p, struct _lv_tree_node_t * node);
|
||||
void (*destructor_cb)(const struct _lv_tree_class_t * class_p, struct _lv_tree_node_t * node);
|
||||
} lv_tree_class_t;
|
||||
|
||||
/** Description of a tree node*/
|
||||
typedef struct _lv_tree_node_t {
|
||||
struct _lv_tree_node_t * parent;
|
||||
struct _lv_tree_node_t ** children;
|
||||
uint32_t child_cnt;
|
||||
uint32_t child_cap;
|
||||
const struct _lv_tree_class_t * class_p;
|
||||
} lv_tree_node_t;
|
||||
|
||||
enum {
|
||||
LV_TREE_WALK_PRE_ORDER = 0,
|
||||
LV_TREE_WALK_POST_ORDER,
|
||||
};
|
||||
typedef uint8_t lv_tree_walk_mode_t;
|
||||
|
||||
typedef bool (*lv_tree_traverse_cb_t)(const lv_tree_node_t * node, void * user_data);
|
||||
typedef bool (*lv_tree_before_cb_t)(const lv_tree_node_t * node, void * user_data);
|
||||
typedef void (*lv_tree_after_cb_t)(const lv_tree_node_t * node, void * user_data);
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
extern const lv_tree_class_t lv_tree_node_class;
|
||||
|
||||
/**
|
||||
* @brief Create a tree node
|
||||
* @param class_p pointer to a class of the node
|
||||
* @param parent pointer to the parent node (or NULL if it's the root node)
|
||||
* @return pointer to the new node
|
||||
*/
|
||||
lv_tree_node_t * lv_tree_node_create(const lv_tree_class_t * class_p, lv_tree_node_t * parent);
|
||||
|
||||
/**
|
||||
* @brief Delete a tree node and all its children recursively
|
||||
* @param node pointer to the node to delete
|
||||
*/
|
||||
void lv_tree_node_delete(lv_tree_node_t * node);
|
||||
|
||||
/**
|
||||
* @brief Walk the tree recursively and call a callback function on each node
|
||||
* @param node pointer to the root node of the tree
|
||||
* @param mode LV_TREE_WALK_PRE_ORDER or LV_TREE_WALK_POST_ORDER
|
||||
* @param cb callback function to call on each node
|
||||
* @param bcb callback function to call before visiting a node
|
||||
* @param acb callback function to call after visiting a node
|
||||
* @param user_data user data to pass to the callback functions
|
||||
* @return true: traversal is finished; false: traversal breaked
|
||||
*/
|
||||
bool lv_tree_walk(const lv_tree_node_t * node,
|
||||
lv_tree_walk_mode_t mode,
|
||||
lv_tree_traverse_cb_t cb,
|
||||
lv_tree_before_cb_t bcb,
|
||||
lv_tree_after_cb_t acb,
|
||||
void * user_data);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif
|
@ -206,6 +206,7 @@ if(NOT (CMAKE_C_COMPILER_ID STREQUAL "MSVC"))
|
||||
-Wno-double-promotion
|
||||
-Wno-unreachable-code
|
||||
-Wno-gnu-zero-variadic-macro-arguments
|
||||
-Wno-overlength-strings
|
||||
)
|
||||
else()
|
||||
list(APPEND COMPILE_OPTIONS
|
||||
|
BIN
tests/ref_imgs/draw/svg_draw_svg_com_1.lp32.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_1.lp64.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_2.lp32.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_2.lp64.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_3.lp32.png
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_3.lp64.png
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_4.lp32.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_4.lp64.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_5.lp32.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_5.lp64.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_6.lp32.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_6.lp64.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_7.lp32.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_7.lp64.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_com_8.lp32.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_group_1.lp32.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_group_1.lp64.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_group_2.lp32.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_group_2.lp64.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_group_3.lp32.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_group_3.lp64.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_group_4.lp32.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_group_4.lp64.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_0.lp32.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_0.lp64.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_1.lp32.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_1.lp64.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_10.lp32.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_10.lp64.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_11.lp32.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_11.lp64.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_12.lp32.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_12.lp64.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_2.lp32.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_2.lp64.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_3.lp32.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_3.lp64.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_4.lp32.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_4.lp64.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_5.lp32.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_5.lp64.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_6.lp32.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_6.lp64.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_7.lp32.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_7.lp64.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_8.lp32.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_8.lp64.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_9.lp32.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_image_9.lp64.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_1.lp32.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_1.lp64.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_10.lp32.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_10.lp64.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_11.lp32.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_11.lp64.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_2.lp32.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_2.lp64.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_3.lp32.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_3.lp64.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_4.lp32.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_4.lp64.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_5.lp32.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_5.lp64.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_6.lp32.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_6.lp64.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_7.lp32.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_7.lp64.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_8.lp32.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_8.lp64.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_9.lp32.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_shapes_9.lp64.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_text_1.lp32.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_text_1.lp64.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_text_2.lp32.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_text_2.lp64.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_viewport_1.lp32.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_viewport_1.lp64.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_viewport_2.lp32.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_viewport_2.lp64.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
tests/ref_imgs/draw/svg_draw_svg_viewport_3.lp32.png
Normal file
After Width: | Height: | Size: 7.7 KiB |