saver/svg: parse loaded tree data into svg XML file and save it

Just base source code which will parse all structures of svg tree into
xml text to save current vector image into file

@feature
This commit is contained in:
Vitalii Vorobiov 2017-01-31 18:06:36 +02:00 committed by Jean-Philippe Andre
parent 7d9c1256a3
commit 78bc406640
1 changed files with 132 additions and 10 deletions

View File

@ -5,26 +5,148 @@ static int _evas_vg_saver_svg_log_dom = -1;
#ifdef ERR
# undef ERR
#endif
#define ERR(...) EINA_LOG_DOM_ERR(_evas_vg_saver_eet_log_dom, __VA_ARGS__)
#define ERR(...) EINA_LOG_DOM_ERR(_evas_vg_saver_svg_log_dom, __VA_ARGS__)
#ifdef INF
# undef INF
#endif
#define INF(...) EINA_LOG_DOM_INFO(_evas_vg_saver_eet_log_dom, __VA_ARGS__)
#define INF(...) EINA_LOG_DOM_INFO(_evas_vg_saver_svg_log_dom, __VA_ARGS__)
static void
printf_style(Svg_Style_Property *style, Eina_Strbuf *buf)
{
if ((style->fill.paint.r) || (style->fill.paint.g) || (style->fill.paint.b))
eina_strbuf_append_printf(buf, " fill=\"#%02X%02X%02X\" ", style->fill.paint.r, style->fill.paint.g, style->fill.paint.b);
if (style->fill.fill_rule == EFL_GFX_FILL_RULE_ODD_EVEN)
eina_strbuf_append_printf(buf, " fill-rule=\"evenodd\" ");
if (style->fill.opacity != 255)
eina_strbuf_append_printf(buf, " fill-opacity=\"%f\"", style->fill.opacity / 255.0);
if ((style->stroke.paint.r) || (style->stroke.paint.g) || (style->stroke.paint.b))
eina_strbuf_append_printf(buf, " stroke=\"#%02X%02X%02X\" ", style->stroke.paint.r, style->stroke.paint.g, style->stroke.paint.b);
if (style->stroke.width)
eina_strbuf_append_printf(buf, " stroke-width=\"%f\" ", style->stroke.width);
if (style->stroke.cap == EFL_GFX_CAP_ROUND)
eina_strbuf_append_printf(buf, " stroke-linecap=\"round\" ");
else if (style->stroke.cap == EFL_GFX_CAP_SQUARE)
eina_strbuf_append_printf(buf, " stroke-linecap=\"square\" ");
}
static void
_svg_node_printf(Svg_Node *parent, Eina_Strbuf *buf)
{
int i = 0;
double *points;
double last_x = 0, last_y = 0;
Efl_Gfx_Path_Command *commands;
Eina_List *l;
Svg_Node *data;
switch (parent->type)
{
case SVG_NODE_DOC:
eina_strbuf_append_printf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
eina_strbuf_append_printf(buf, "<svg viewBox=\"%f %f %f %f\" xmlns=\"http://www.w3.org/2000/svg\""
" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
parent->node.doc.vx, parent->node.doc.vy,
parent->node.doc.vw, parent->node.doc.vh);
EINA_LIST_FOREACH(parent->child, l, data)
{
_svg_node_printf(data, buf);
}
eina_strbuf_append_printf(buf, "</svg>\n");
break;
case SVG_NODE_G:
eina_strbuf_append_printf(buf, "<g");
if (parent->transform)
eina_strbuf_append_printf(buf,
" transform=\"matrix(%f %f %f %f %f %f)\"",
parent->transform->xx,
parent->transform->yx,
parent->transform->xy,
parent->transform->yy,
parent->transform->xz,
parent->transform->yz);
eina_strbuf_append_printf(buf, ">\n");
EINA_LIST_FOREACH(parent->child, l, data)
{
_svg_node_printf(data, buf);
}
eina_strbuf_append_printf(buf, "</g>\n");
break;
case SVG_NODE_CUSTOME_COMMAND:
points = parent->node.command.points;
commands = parent->node.command.commands;
eina_strbuf_append_printf(buf, "<path d=\"");
for (i = 0; i < parent->node.command.commands_count; i++)
{
switch (commands[i])
{
case EFL_GFX_PATH_COMMAND_TYPE_END:
eina_strbuf_append_printf(buf, "\"");
if (parent->transform)
eina_strbuf_append_printf(buf, " transform=\"matrix(%f %f %f %f %f %f)\"",
parent->transform->xx,
parent->transform->yx,
parent->transform->xy,
parent->transform->yy,
parent->transform->xz,
parent->transform->yz);
printf_style(parent->style, buf);
eina_strbuf_append_printf(buf, "/>\n");
break;
case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO:
eina_strbuf_append_printf(buf, "m%f,%f ", points[0] - last_x, points[1] - last_y);
last_x = points[0];
last_y = points[1];
points += 2;
break;
case EFL_GFX_PATH_COMMAND_TYPE_LINE_TO:
eina_strbuf_append_printf(buf, "L%f,%f ", points[0], points[1]);
last_x = points[0];
last_y = points[1];
points += 2;
break;
case EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO:
eina_strbuf_append_printf(buf, "c%f,%f %f,%f %f,%f ",
points[0] - last_x, points[1] - last_y,
points[2] - last_x, points[3] - last_y,
points[4] - last_x, points[5] - last_y);
last_x = points[4];
last_y = points[5];
points += 6;
break;
case EFL_GFX_PATH_COMMAND_TYPE_CLOSE:
eina_strbuf_append_printf(buf, " z ");
break;
case EFL_GFX_PATH_COMMAND_TYPE_LAST:
default:
break;
}
}
break;
default:
break;
}
}
int
evas_vg_save_file_svg(Vg_File_Data *evg_data, const char *file, const char *key EINA_UNUSED, int compress EINA_UNUSED)
{
Svg_Node *root EINA_UNUSED;
Eet_File *ef;
ef = eet_open(file, EET_FILE_MODE_WRITE);
if (!ef)
return EVAS_LOAD_ERROR_GENERIC;
Eina_Strbuf *buf = NULL;
Svg_Node *root;
FILE *f = fopen(file, "w+");
if (!f)
{
ERR("Cannot open file '%s' for SVG save", file);
return EFL_IMAGE_LOAD_ERROR_GENERIC;
}
root = vg_common_create_svg_node(evg_data);
//TODO: parse root into SVG source code and save into file as text file
eet_close(ef);
buf = eina_strbuf_new();
_svg_node_printf(root, buf);
fprintf(f, "%s\n", eina_strbuf_string_get(buf));
fclose(f);
eina_strbuf_free(buf);
return EVAS_LOAD_ERROR_NONE;
}