efl/gfx: fix svg path parsing logic.

1. according to svg path specification, path string may or may not contain ',' as the separator
with current parsing logic we were expecting a ',' after each segment.
2. relative cubic bezier parsing was wrong as we were not adding the current value to all 4 points.
3. refactored the parse_pair, parse_six and parse_quad to use same helper function
path1: "M7.279,2h35.442C45.637,2,48,4.359,48,7.271v35.455C48,45.639,45.637,48,42.723,48H7.279C4.362,47.997,2,45.639,2,42.727V7.271C2,4.359,4.362,2,7.279,2z"
path2: "M-2.073-7h36.147C36.796-7,39-4.793,39-2.073v36.146C39,36.796,36.796,39,34.074,39H-2.073C-4.793,39-7,36.796-7,34.072V-2.073C-7-4.793-4.793-7-2.073-7z"

Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
This commit is contained in:
Subhransu Mohanty 2015-08-28 10:12:44 +09:00 committed by Cedric BAIL
parent fe10889ec7
commit 84b6b4c040
1 changed files with 71 additions and 82 deletions

View File

@ -873,11 +873,11 @@ _efl_gfx_path_append_vertical_to(Eo *obj, Efl_Gfx_Shape_Data *pd,
}
static char *
_strcomma(const char *content)
_skipcomma(const char *content)
{
while (*content && isspace(*content)) content++;
if (*content != ',') return NULL;
return (char*) content + 1;
if (*content == ',') return (char*) content + 1;
return (char*) content;
}
static inline Eina_Bool
@ -889,21 +889,30 @@ _next_isnumber(const char *content)
return content != tmp;
}
static inline Eina_Bool
_parse_number(char **content, double *number)
{
char *end = NULL;
*number = strtod(*content, &end);
// if the start of string is not number
if ((*content) == end) return EINA_FALSE;
//skip comma if any
*content = _skipcomma(end);
return EINA_TRUE;
}
static Eina_Bool
_efl_gfx_path_parse_pair(const char *content, char **end, double *x, double *y)
{
/* "x,y" */
char *end1 = NULL;
char *end2 = NULL;
char *str = (char *) content;
*x = strtod(content, &end1);
end1 = _strcomma(end1);
if (!end1) return EINA_FALSE;
*y = strtod(end1, &end2);
if (end1 == end2) return EINA_FALSE;
*end = end2;
return EINA_TRUE;
if (_parse_number(&str, x))
if (_parse_number(&str, y))
{
*end = str;
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
@ -979,31 +988,18 @@ _efl_gfx_path_parse_six(const char *content, char **end,
double *ctrl_x0, double *ctrl_y0,
double *ctrl_x1, double *ctrl_y1)
{
/* "x,y ctrl_x0,ctrl_y0 ctrl_x1,ctrl_y1" */
char *end1 = NULL;
char *end2 = NULL;
*ctrl_x0 = strtod(content, &end1);
end1 = _strcomma(end1);
if (!end1) return EINA_FALSE;
*ctrl_y0 = strtod(end1, &end2);
if (end1 == end2) return EINA_FALSE;
*ctrl_x1 = strtod(end2, &end2);
end2 = _strcomma(end2);
if (!end2) return EINA_FALSE;
*ctrl_y1 = strtod(end2, &end1);
if (end1 == end2) return EINA_FALSE;
*x = strtod(end1, &end2);
end2 = _strcomma(end2);
if (!end2) return EINA_FALSE;
*y = strtod(end2, &end1);
if (end1 == end2) return EINA_FALSE;
*end = end1;
return EINA_TRUE;
char *str = (char *) content;
if (_parse_number(&str, ctrl_x0))
if (_parse_number(&str, ctrl_y0))
if (_parse_number(&str, ctrl_x1))
if (_parse_number(&str, ctrl_y1))
if (_parse_number(&str, x))
if (_parse_number(&str, y))
{
*end = str;
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
@ -1030,8 +1026,11 @@ _efl_gfx_path_parse_six_to(const char *content, char **end,
{
x += *current_x;
y += *current_y;
ctrl_x0 += *current_x;
ctrl_y0 += *current_y;
ctrl_x1 += *current_x;
ctrl_y1 += *current_y;
}
func(obj, pd, x, y, ctrl_x0, ctrl_y0, ctrl_x1, ctrl_y1);
content = *end;
@ -1048,25 +1047,17 @@ _efl_gfx_path_parse_quad(const char *content, char **end,
double *x, double *y,
double *ctrl_x0, double *ctrl_y0)
{
/* "x,y ctrl_x0,ctrl_y0" */
char *end1 = NULL;
char *end2 = NULL;
char *str = (char *) content;
*ctrl_x0 = strtod(content, &end1);
end1 = _strcomma(end1);
if (!end1) return EINA_FALSE;
*ctrl_y0 = strtod(end1, &end2);
if (end1 == end2) return EINA_FALSE;
*x = strtod(end2, &end1);
end1 = _strcomma(end2);
if (!end1) return EINA_FALSE;
*y = strtod(end1, &end2);
if (end1 == end2) return EINA_FALSE;
*end = end2;
return EINA_TRUE;
if (_parse_number(&str, ctrl_x0))
if (_parse_number(&str, ctrl_y0))
if (_parse_number(&str, x))
if (_parse_number(&str, y))
{
*end = str;
return EINA_TRUE;
}
return EINA_FALSE;
}
static Eina_Bool
@ -1113,34 +1104,32 @@ _efl_gfx_path_parse_arc(const char *content, char **end,
double *radius,
Eina_Bool *large_arc, Eina_Bool *sweep)
{
/* "rx,ry r large-arc-flag,sweep-flag x,y" */
char *str = (char *) content;
char *end1 = NULL;
char *end2 = NULL;
*rx = strtod(content, &end1);
end1 = _strcomma(end1);
if (!end1) return EINA_FALSE;
*ry = strtod(end1, &end2);
if (end1 == end2) return EINA_FALSE;
if (_parse_number(&str, rx))
if (_parse_number(&str, ry))
if (_parse_number(&str, radius))
{
// large_arc
*large_arc = strtol(str, &end1, 10) ? EINA_TRUE : EINA_FALSE;
if (!end1 || (str == end1)) return EINA_FALSE;
end1 = _skipcomma(end1);
*radius = strtod(end2, &end1);
if (end1 == end2) return EINA_FALSE;
// sweeo
*sweep = strtol(end2, &end1, 10) ? EINA_TRUE : EINA_FALSE;
if (!end1 || (end1 == end2)) return EINA_FALSE;
str = _skipcomma(end1);
*large_arc = strtol(end1, &end2, 10) ? EINA_TRUE : EINA_FALSE;
end1 = _strcomma(end2);
if (!end1) return EINA_FALSE;
*sweep = strtol(end1, &end2, 10) ? EINA_TRUE : EINA_FALSE;
if (end1 == end2) return EINA_FALSE;
*x = strtod(end2, &end1);
end1 = _strcomma(end2);
if (!end1) return EINA_FALSE;
*y = strtod(end1, &end2);
if (end1 == end2) return EINA_FALSE;
*end = end2;
return EINA_TRUE;
if (_parse_number(&str, x))
if (_parse_number(&str, y))
{
*end = str;
return EINA_TRUE;
}
}
return EINA_FALSE;
}
static Eina_Bool
@ -1367,7 +1356,7 @@ _efl_gfx_shape_append_svg_path(Eo *obj, Efl_Gfx_Shape_Data *pd,
return ;
break;
default:
return ;
return;
}
}
}