summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsubhransu mohanty <sub.mohanty@samsung.com>2018-01-17 14:20:15 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2018-01-17 14:54:18 +0900
commit2a31883f5a53b15128a49aee17b737ec0ee1d9c2 (patch)
tree99434bd95cd76789f92cca9873ef126b189b62c7
parent7cef580f11d47b90dc0af0a790935e85bbb89f20 (diff)
efl/vg: Refactor the svg path handling and interpolation.
Summary: This patch is taken from the tizen branch 1. Take care when the locale is different than POSIX. See: strtod, strtol 2. Interpolate all the property of a shape. Reviewers: jpeg Subscribers: cedric, jpeg Differential Revision: https://phab.enlightenment.org/D5740
-rw-r--r--src/lib/efl/interfaces/efl_gfx_path.c858
1 files changed, 424 insertions, 434 deletions
diff --git a/src/lib/efl/interfaces/efl_gfx_path.c b/src/lib/efl/interfaces/efl_gfx_path.c
index 2901373ddc..4d8ed3c6ca 100644
--- a/src/lib/efl/interfaces/efl_gfx_path.c
+++ b/src/lib/efl/interfaces/efl_gfx_path.c
@@ -5,6 +5,7 @@
5#include <math.h> 5#include <math.h>
6#include <float.h> 6#include <float.h>
7#include <ctype.h> 7#include <ctype.h>
8#include <locale.h>
8 9
9#include <Efl.h> 10#include <Efl.h>
10 11
@@ -21,6 +22,7 @@ struct _Efl_Gfx_Path_Data
21 22
22 unsigned int commands_count; 23 unsigned int commands_count;
23 unsigned int points_count; 24 unsigned int points_count;
25 char *path_data;
24 Eina_Bool convex; 26 Eina_Bool convex;
25}; 27};
26 28
@@ -273,6 +275,48 @@ interpolate(double from, double to, double pos_map)
273 return (from * (1.0 - pos_map)) + (to * pos_map); 275 return (from * (1.0 - pos_map)) + (to * pos_map);
274} 276}
275 277
278static inline int
279interpolatei(int from, int to, double pos_map)
280{
281 return (from * (1.0 - pos_map)) + (to * pos_map);
282}
283
284typedef struct _Efl_Gfx_Property Efl_Gfx_Property;
285struct _Efl_Gfx_Property
286{
287 double scale;
288 double w;
289 double centered;
290
291 Efl_Gfx_Cap c;
292 Efl_Gfx_Join j;
293
294 const Efl_Gfx_Dash *dash;
295 unsigned int dash_length;
296
297 int r, g, b, a;
298 int fr, fg, fb, fa;
299};
300
301static inline void
302_efl_gfx_property_get(const Eo *obj, Efl_Gfx_Property *property)
303{
304
305 property->scale = efl_gfx_shape_stroke_scale_get(obj);
306 efl_gfx_shape_stroke_color_get(obj, &property->r, &property->g, &property->b, &property->a);
307 efl_gfx_color_get(obj, &property->fr, &property->fg, &property->fb, &property->fa);
308 property->w = efl_gfx_shape_stroke_width_get(obj);
309 property->centered = efl_gfx_shape_stroke_location_get(obj);
310 efl_gfx_shape_stroke_dash_get(obj, &property->dash, &property->dash_length);
311 property->c = efl_gfx_shape_stroke_cap_get(obj);
312 property->j = efl_gfx_shape_stroke_join_get(obj);
313}
314
315
316
317static void _path_interpolation(Eo *obj, Efl_Gfx_Path_Data *pd, char *from, char *to, double pos);
318static void _efl_gfx_path_reset(Eo *obj, Efl_Gfx_Path_Data *pd);
319
276EOLIAN static Eina_Bool 320EOLIAN static Eina_Bool
277_efl_gfx_path_interpolate(Eo *obj, Efl_Gfx_Path_Data *pd, 321_efl_gfx_path_interpolate(Eo *obj, Efl_Gfx_Path_Data *pd,
278 const Eo *from, const Eo *to, double pos_map) 322 const Eo *from, const Eo *to, double pos_map)
@@ -280,68 +324,112 @@ _efl_gfx_path_interpolate(Eo *obj, Efl_Gfx_Path_Data *pd,
280 Efl_Gfx_Path_Change_Event ev = { EFL_GFX_CHANGE_FLAG_PATH }; 324 Efl_Gfx_Path_Change_Event ev = { EFL_GFX_CHANGE_FLAG_PATH };
281 Efl_Gfx_Path_Data *from_pd, *to_pd; 325 Efl_Gfx_Path_Data *from_pd, *to_pd;
282 Efl_Gfx_Path_Command *cmds; 326 Efl_Gfx_Path_Command *cmds;
327 Efl_Gfx_Property property_from, property_to;
328 Efl_Gfx_Dash *dash = NULL;
283 double *pts; 329 double *pts;
284 unsigned int i, j; 330 unsigned int i, j;
285 331
286 from_pd = efl_data_scope_get(from, EFL_GFX_PATH_MIXIN); 332 from_pd = efl_data_scope_get(from, EFL_GFX_PATH_MIXIN);
287 to_pd = efl_data_scope_get(to, EFL_GFX_PATH_MIXIN); 333 to_pd = efl_data_scope_get(to, EFL_GFX_PATH_MIXIN);
288
289 if (!efl_isa(from, EFL_GFX_PATH_MIXIN) || !efl_isa(to, EFL_GFX_PATH_MIXIN)) 334 if (!efl_isa(from, EFL_GFX_PATH_MIXIN) || !efl_isa(to, EFL_GFX_PATH_MIXIN))
290 return EINA_FALSE; 335 return EINA_FALSE;
291
292 if (pd == from_pd || pd == to_pd) return EINA_FALSE; 336 if (pd == from_pd || pd == to_pd) return EINA_FALSE;
293 337
294 if (!_efl_gfx_path_equal_commands_internal(from_pd, to_pd))
295 return EINA_FALSE;
296 338
297 cmds = realloc(pd->commands, 339 _efl_gfx_property_get(from, &property_from);
298 sizeof (Efl_Gfx_Path_Command) * from_pd->commands_count); 340 _efl_gfx_property_get(to, &property_to);
299 if (!cmds && from_pd->commands_count) return EINA_FALSE; 341
342 if (property_from.dash_length != property_to.dash_length) return EINA_FALSE;
300 343
301 pts = realloc(pd->points, sizeof (double) * from_pd->points_count); 344 if (from_pd->path_data && to_pd->path_data)
302 if (!pts && from_pd->points_count)
303 { 345 {
304 free(cmds); 346 _efl_gfx_path_reset(obj, pd);
305 return EINA_FALSE; 347 _path_interpolation(obj, pd, from_pd->path_data, to_pd->path_data, pos_map);
306 } 348 }
307 349 else
308 pd->commands = cmds;
309 pd->points = pts;
310
311 if (cmds)
312 { 350 {
313 memcpy(cmds, from_pd->commands, 351 if (!_efl_gfx_path_equal_commands_internal(from_pd, to_pd))
314 sizeof (Efl_Gfx_Path_Command) * from_pd->commands_count); 352 return EINA_FALSE;
353 cmds = realloc(pd->commands,
354 sizeof (Efl_Gfx_Path_Command) * from_pd->commands_count);
355 if (!cmds && from_pd->commands_count) return EINA_FALSE;
356 pd->commands = cmds;
315 357
316 if (pts) 358 pts = realloc(pd->points,
359 sizeof (double) * from_pd->points_count);
360 if (!pts && from_pd->points_count) return EINA_FALSE;
361 pd->points = pts;
362
363 if (cmds)
317 { 364 {
318 double *to_pts = to_pd->points; 365 memcpy(cmds, from_pd->commands,
319 double *from_pts = from_pd->points; 366 sizeof (Efl_Gfx_Path_Command) * from_pd->commands_count);
320 367
321 for (i = 0; cmds[i] != EFL_GFX_PATH_COMMAND_TYPE_END; i++) 368 if (pts)
322 { 369 {
323 for (j = 0; j < _efl_gfx_path_command_length(cmds[i]); j++) 370 double *to_pts = to_pd->points;
324 { 371 double *from_pts = from_pd->points;
325 *pts = interpolate(*from_pts, *to_pts, pos_map); 372
326 pts++; 373 for (i = 0; cmds[i] != EFL_GFX_PATH_COMMAND_TYPE_END; i++)
327 from_pts++; 374 for (j = 0; j < _efl_gfx_path_command_length(cmds[i]); j++)
328 to_pts++; 375 {
329 } 376 *pts = interpolate(*from_pts, *to_pts, pos_map);
377
378 pts++;
379 from_pts++;
380 to_pts++;
381 }
330 } 382 }
331 } 383 }
384
385 pd->points_count = from_pd->points_count;
386 pd->commands_count = from_pd->commands_count;
387
388 pd->current.x = interpolate(from_pd->current.x,
389 to_pd->current.x,
390 pos_map);
391 pd->current.y = interpolate(from_pd->current.y,
392 to_pd->current.y,
393 pos_map);
394 pd->current_ctrl.x = interpolate(from_pd->current_ctrl.x,
395 to_pd->current_ctrl.x,
396 pos_map);
397 pd->current_ctrl.y = interpolate(from_pd->current_ctrl.y,
398 to_pd->current_ctrl.y,
399 pos_map);
400 }
401
402 if (property_to.dash_length)
403 {
404 dash = malloc(sizeof (Efl_Gfx_Dash) * property_to.dash_length);
405 if (!dash) return EINA_FALSE;
406
407 for (i = 0; i < property_to.dash_length; i++)
408 {
409 dash[i].length = interpolate(property_from.dash[i].length,
410 property_to.dash[i].length, pos_map);
411 dash[i].gap = interpolate(property_from.dash[i].gap,
412 property_to.dash[i].gap, pos_map);
413 }
332 } 414 }
333 415
334 pd->points_count = from_pd->points_count;
335 pd->commands_count = from_pd->commands_count;
336 416
337 pd->current.x = interpolate(from_pd->current.x, to_pd->current.x, pos_map); 417 efl_gfx_shape_stroke_scale_set(obj, interpolate(property_from.scale, property_to.scale, pos_map));
338 pd->current.y = interpolate(from_pd->current.y, to_pd->current.y, pos_map); 418 efl_gfx_shape_stroke_color_set(obj, interpolatei(property_from.r, property_to.r, pos_map),
339 pd->current_ctrl.x = interpolate(from_pd->current_ctrl.x, 419 interpolatei(property_from.g, property_to.g, pos_map),
340 to_pd->current_ctrl.x, pos_map); 420 interpolatei(property_from.b, property_to.b, pos_map),
341 pd->current_ctrl.y = interpolate(from_pd->current_ctrl.y, 421 interpolatei(property_from.a, property_to.a, pos_map));
342 to_pd->current_ctrl.y, pos_map); 422 efl_gfx_color_set(obj, interpolatei(property_from.fr, property_to.fr, pos_map),
423 interpolatei(property_from.fg, property_to.fg, pos_map),
424 interpolatei(property_from.fb, property_to.fb, pos_map),
425 interpolatei(property_from.fa, property_to.fa, pos_map));
426 efl_gfx_shape_stroke_width_set(obj, interpolate(property_from.w, property_to.w, pos_map));
427 efl_gfx_shape_stroke_location_set(obj, interpolate(property_from.centered, property_to.centered, pos_map));
428 efl_gfx_shape_stroke_dash_set(obj, dash, property_to.dash_length);
429 efl_gfx_shape_stroke_cap_set(obj, pos_map < 0.5 ? property_from.c : property_to.c);
430 efl_gfx_shape_stroke_join_set(obj, pos_map < 0.5 ? property_from.j : property_to.j);
343 431
344 efl_event_callback_legacy_call(obj, EFL_GFX_PATH_EVENT_CHANGED, &ev); 432 efl_event_callback_legacy_call(obj, EFL_GFX_PATH_EVENT_CHANGED, &ev);
345 433
346 return EINA_TRUE; 434 return EINA_TRUE;
347} 435}
@@ -371,6 +459,8 @@ _efl_gfx_path_reset(Eo *obj, Efl_Gfx_Path_Data *pd)
371 free(pd->points); 459 free(pd->points);
372 pd->points = NULL; 460 pd->points = NULL;
373 pd->points_count = 0; 461 pd->points_count = 0;
462 free(pd->path_data);
463 pd->path_data = NULL;
374 464
375 pd->current.x = 0; 465 pd->current.x = 0;
376 pd->current.y = 0; 466 pd->current.y = 0;
@@ -1128,453 +1218,353 @@ _parse_number(char **content, double *number)
1128{ 1218{
1129 char *end = NULL; 1219 char *end = NULL;
1130 *number = strtod(*content, &end); 1220 *number = strtod(*content, &end);
1131 // if the start of string is not number 1221 // if the start of string is not number
1132 if ((*content) == end) return EINA_FALSE; 1222 if ((*content) == end) return EINA_FALSE;
1133 //skip comma if any 1223 //skip comma if any
1134 *content = _skipcomma(end); 1224 *content = _skipcomma(end);
1135 return EINA_TRUE; 1225 return EINA_TRUE;
1136} 1226}
1137 1227
1138static Eina_Bool 1228static inline Eina_Bool
1139_efl_gfx_path_parse_pair(const char *content, char **end, double *x, double *y) 1229_parse_long(char **content, int *number)
1140{ 1230{
1141 char *str = (char *) content; 1231 char *end = NULL;
1142 1232 *number = strtol(*content, &end, 10) ? 1 : 0;
1143 if (_parse_number(&str, x)) 1233 // if the start of string is not number
1144 if (_parse_number(&str, y)) 1234 if ((*content) == end) return EINA_FALSE;
1145 { 1235 *content = _skipcomma(end);
1146 *end = str; 1236 return EINA_TRUE;
1147 return EINA_TRUE;
1148 }
1149 return EINA_FALSE;
1150} 1237}
1151 1238
1152static Eina_Bool 1239static int
1153_efl_gfx_path_parse_pair_to(const char *content, char **end, 1240_number_count(char cmd)
1154 Eo *obj, Efl_Gfx_Path_Data *pd,
1155 double *current_x, double *current_y,
1156 void (*func)(Eo *obj, Efl_Gfx_Path_Data *pd,
1157 double x, double y),
1158 Eina_Bool rel)
1159{ 1241{
1160 double x, y; 1242 int count = 0;
1161 1243 switch (cmd)
1162 *end = (char*) content;
1163
1164 do
1165 { 1244 {
1166 if (!_efl_gfx_path_parse_pair(content, end, &x, &y)) 1245 case 'M':
1167 return EINA_FALSE; 1246 case 'm':
1168 1247 case 'L':
1169 if (rel) 1248 case 'l':
1170 { 1249 {
1171 x += *current_x; 1250 count = 2;
1172 y += *current_y; 1251 break;
1173 } 1252 }
1174 func(obj, pd, x, y); 1253 case 'C':
1175 content = *end; 1254 case 'c':
1176 1255 case 'E':
1177 *current_x = x; 1256 case 'e':
1178 *current_y = y; 1257 {
1179 } 1258 count = 6;
1180 while (_next_isnumber(content)); 1259 break;
1181 1260 }
1182 return EINA_TRUE; 1261 case 'H':
1262 case 'h':
1263 case 'V':
1264 case 'v':
1265 {
1266 count = 1;
1267 break;
1268 }
1269 case 'S':
1270 case 's':
1271 case 'Q':
1272 case 'q':
1273 case 'T':
1274 case 't':
1275 {
1276 count = 4;
1277 break;
1278 }
1279 case 'A':
1280 case 'a':
1281 {
1282 count = 7;
1283 break;
1284 }
1285 default:
1286 break;
1287 }
1288 return count;
1183} 1289}
1184 1290
1185static Eina_Bool 1291static void
1186_efl_gfx_path_parse_double_to(const char *content, char **end, 1292process_command(Eo *obj, Efl_Gfx_Path_Data *pd, char cmd, double *arr, int count, double *cur_x, double *cur_y)
1187 Eo *obj, Efl_Gfx_Path_Data *pd,
1188 double *current, double current_x,
1189 double current_y,
1190 void (*func)(Eo *obj, Efl_Gfx_Path_Data *pd,
1191 double d, double current_x,
1192 double current_y),
1193 Eina_Bool rel)
1194{ 1293{
1195 double d; 1294 int i;
1196 Eina_Bool first = EINA_FALSE; 1295 switch (cmd)
1197
1198 *end = (char*) content;
1199 do
1200 { 1296 {
1201 d = strtod(content, end); 1297 case 'm':
1202 if (content == *end) return first; 1298 case 'l':
1203 first = EINA_TRUE; 1299 case 'c':
1204 1300 case 's':
1205 if (rel) d += *current; 1301 case 'q':
1206 1302 case 't':
1207 func(obj, pd, d, current_x, current_y); 1303 {
1208 content = *end; 1304 for(i=0; i<count; i += 2)
1209 1305 {
1210 *current = d; 1306 arr[i] = arr[i] + *cur_x;
1211 } 1307 arr[i+1] = arr[i+1] + *cur_y;
1212 while (1); // This is an optimisation as we have only one parameter. 1308 }
1213 1309 break;
1214 return EINA_TRUE; 1310 }
1311 case 'h':
1312 {
1313 arr[0] = arr[0] + *cur_x;
1314 break;
1315 }
1316 case 'v':
1317 {
1318 arr[0] = arr[0] + *cur_y;
1319 break;
1320 }
1321 case 'a':
1322 {
1323 arr[5] = arr[5] + *cur_x;
1324 arr[6] = arr[6] + *cur_y;
1325 break;
1326 }
1327 default:
1328 break;
1329 }
1330
1331 switch (cmd)
1332 {
1333 case 'm':
1334 case 'M':
1335 {
1336 _efl_gfx_path_append_move_to(obj, pd, arr[0], arr[1]);
1337 *cur_x = arr[0];
1338 *cur_y = arr[1];
1339 break;
1340 }
1341 case 'l':
1342 case 'L':
1343 {
1344 _efl_gfx_path_append_line_to(obj, pd, arr[0], arr[1]);
1345 *cur_x = arr[0];
1346 *cur_y = arr[1];
1347 break;
1348 }
1349 case 'c':
1350 case 'C':
1351 {
1352 _efl_gfx_path_append_cubic_to(obj, pd, arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]);
1353 *cur_x = arr[4];
1354 *cur_y = arr[5];
1355 break;
1356 }
1357 case 's':
1358 case 'S':
1359 {
1360 _efl_gfx_path_append_scubic_to(obj, pd, arr[2], arr[3], arr[0], arr[1]);
1361 *cur_x = arr[2];
1362 *cur_y = arr[3];
1363 break;
1364 }
1365 case 'q':
1366 case 'Q':
1367 {
1368 _efl_gfx_path_append_quadratic_to(obj, pd, arr[2], arr[3], arr[0], arr[1]);
1369 *cur_x = arr[2];
1370 *cur_y = arr[3];
1371 break;
1372 }
1373 case 't':
1374 case 'T':
1375 {
1376 _efl_gfx_path_append_move_to(obj, pd, arr[0], arr[1]);
1377 *cur_x = arr[0];
1378 *cur_y = arr[1];
1379 break;
1380 }
1381 case 'h':
1382 case 'H':
1383 {
1384 _efl_gfx_path_append_horizontal_to(obj, pd, arr[0], *cur_x, *cur_y);
1385 *cur_x = arr[0];
1386 break;
1387 }
1388 case 'v':
1389 case 'V':
1390 {
1391 _efl_gfx_path_append_vertical_to(obj, pd, arr[0], *cur_x, *cur_y);
1392 *cur_y = arr[0];
1393 break;
1394 }
1395 case 'z':
1396 case 'Z':
1397 {
1398 _efl_gfx_path_append_close(obj, pd);
1399 break;
1400 }
1401 case 'a':
1402 case 'A':
1403 {
1404 _efl_gfx_path_append_arc_to(obj, pd, arr[5], arr[6], arr[0], arr[1], arr[2], arr[3], arr[4]);
1405 *cur_x = arr[5];
1406 *cur_y = arr[6];
1407 break;
1408 }
1409 case 'E':
1410 case 'e':
1411 {
1412 _efl_gfx_path_append_arc(obj, pd, arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]);
1413 break;
1414 }
1415 default:
1416 break;
1417 }
1215} 1418}
1216 1419
1217static Eina_Bool 1420static char *
1218_efl_gfx_path_parse_six(const char *content, char **end, 1421_next_command(char *path, char *cmd, double *arr, int *count)
1219 double *x, double *y,
1220 double *ctrl_x0, double *ctrl_y0,
1221 double *ctrl_x1, double *ctrl_y1)
1222{ 1422{
1223 char *str = (char *) content; 1423 int i=0, large, sweep;
1224 1424
1225 if (_parse_number(&str, ctrl_x0)) 1425 path = _skipcomma(path);
1426 if (isalpha(*path))
1226 { 1427 {
1227 if (_parse_number(&str, ctrl_y0)) 1428 *cmd = *path;
1228 { 1429 path++;
1229 if (_parse_number(&str, ctrl_x1)) 1430 *count = _number_count(*cmd);
1230 {
1231 if (_parse_number(&str, ctrl_y1))
1232 {
1233 if (_parse_number(&str, x))
1234 {
1235 if (_parse_number(&str, y))
1236 {
1237 *end = str;
1238 return EINA_TRUE;
1239 }
1240 }
1241 }
1242 }
1243 }
1244 } 1431 }
1245 1432 if ( *count == 7)
1246 return EINA_FALSE;
1247}
1248
1249static Eina_Bool
1250_efl_gfx_path_parse_six_to(const char *content, char **end,
1251 Eo *obj, Efl_Gfx_Path_Data *pd,
1252 double *current_x, double *current_y,
1253 void (*func)(Eo *obj, Efl_Gfx_Path_Data *pd,
1254 double ctrl_x0, double ctrl_y0,
1255 double ctrl_x1, double ctrl_y1,
1256 double x, double y),
1257 Eina_Bool rel)
1258{
1259 double x, y, ctrl_x0, ctrl_y0, ctrl_x1, ctrl_y1;
1260
1261 *end = (char*) content;
1262
1263 do
1264 { 1433 {
1265 if (!_efl_gfx_path_parse_six(content, end, &x, &y, &ctrl_x0, &ctrl_y0, 1434 // special case for arc command
1266 &ctrl_x1, &ctrl_y1)) 1435 if(_parse_number(&path, &arr[0]))
1267 return EINA_FALSE; 1436 if(_parse_number(&path, &arr[1]))
1268 1437 if(_parse_number(&path, &arr[2]))
1269 if (rel) 1438 if(_parse_long(&path, &large))
1270 { 1439 if(_parse_long(&path, &sweep))
1271 x += *current_x; 1440 if(_parse_number(&path, &arr[5]))
1272 y += *current_y; 1441 if(_parse_number(&path, &arr[6]))
1273 ctrl_x0 += *current_x; 1442 {
1274 ctrl_y0 += *current_y; 1443 arr[3] = large;
1275 ctrl_x1 += *current_x; 1444 arr[4] = sweep;
1276 ctrl_y1 += *current_y; 1445 return path;
1277 } 1446 }
1278 func(obj, pd, ctrl_x0, ctrl_y0, ctrl_x1, ctrl_y1, x, y); 1447 *count = 0;
1279 content = *end; 1448 return NULL;
1280
1281 *current_x = x;
1282 *current_y = y;
1283 } 1449 }
1284 while (_next_isnumber(content)); 1450 for (i = 0; i < *count; i++)
1285
1286 return EINA_TRUE;
1287}
1288
1289static Eina_Bool
1290_efl_gfx_path_parse_quad(const char *content, char **end,
1291 double *x, double *y,
1292 double *ctrl_x0, double *ctrl_y0)
1293{
1294 char *str = (char *) content;
1295
1296 if (_parse_number(&str, ctrl_x0))
1297 if (_parse_number(&str, ctrl_y0))
1298 if (_parse_number(&str, x))
1299 if (_parse_number(&str, y))
1300 {
1301 *end = str;
1302 return EINA_TRUE;
1303 }
1304 return EINA_FALSE;
1305}
1306
1307static Eina_Bool
1308_efl_gfx_path_parse_quad_to(const char *content, char **end,
1309 Eo *obj, Efl_Gfx_Path_Data *pd,
1310 double *current_x, double *current_y,
1311 void (*func)(Eo *obj, Efl_Gfx_Path_Data *pd,
1312 double x, double y, double ctrl_x0, double ctrl_y0),
1313 Eina_Bool rel)
1314{
1315 double x, y, ctrl_x0, ctrl_y0;
1316
1317 *end = (char*) content;
1318
1319 do
1320 { 1451 {
1321 Eina_Bool r; 1452 if (!_parse_number(&path, &arr[i]))
1322
1323 r = _efl_gfx_path_parse_quad(content, end, &x, &y, &ctrl_x0, &ctrl_y0);
1324 if (!r) return EINA_FALSE;
1325
1326 if (rel)
1327 { 1453 {
1328 x += *current_x; 1454 *count = 0;
1329 y += *current_y; 1455 return NULL;
1330 ctrl_x0 += *current_x;
1331 ctrl_y0 += *current_y;
1332 } 1456 }
1333 func(obj, pd, x, y, ctrl_x0, ctrl_y0); 1457 path = _skipcomma(path);
1334 content = *end;
1335
1336 *current_x = x;
1337 *current_y = y;
1338 } 1458 }
1339 while (_next_isnumber(content)); 1459 return path;
1340
1341 return EINA_TRUE;
1342} 1460}
1343 1461
1344static Eina_Bool 1462static void
1345_efl_gfx_path_parse_arc(const char *content, char **end, 1463_path_interpolation(Eo *obj, Efl_Gfx_Path_Data *pd,
1346 double *x, double *y, 1464 char *from, char *to, double pos)
1347 double *rx, double *ry,
1348 double *radius,
1349 Eina_Bool *large_arc, Eina_Bool *sweep)
1350{ 1465{
1351 char *str = (char *) content; 1466 int i;
1352 char *end1 = NULL; 1467 double from_arr[7], to_arr[7];
1353 char *end2 = NULL; 1468 int from_count=0, to_count=0;
1469 double cur_x=0, cur_y=0;
1470 char from_cmd= 0, to_cmd = 0;
1471 char *cur_locale;
1472
1473 if (!from || !to)
1474 return;
1354 1475
1355 if (_parse_number(&str, rx)) 1476 cur_locale = setlocale(LC_NUMERIC, NULL);
1477 if (cur_locale)
1478 cur_locale = strdup(cur_locale);
1479 setlocale(LC_NUMERIC, "POSIX");
1480
1481 while ((from[0] != '\0') && (to[0] != '\0'))
1356 { 1482 {
1357 if (_parse_number(&str, ry)) 1483 from = _next_command(from, &from_cmd, from_arr, &from_count);
1484 to = _next_command(to, &to_cmd, to_arr, &to_count);
1485 if (from_cmd == to_cmd)
1358 { 1486 {
1359 if (_parse_number(&str, radius)) 1487 if (from_count == 7)
1360 { 1488 {
1361 // large_arc 1489 //special case for arc command
1362 *large_arc = strtol(str, &end1, 10) ? EINA_TRUE : EINA_FALSE; 1490 i=0;
1363 if (!end1 || (str == end1)) return EINA_FALSE; 1491 from_arr[i] = interpolate(from_arr[i], to_arr[i], pos);
1364 end1 = _skipcomma(end1); 1492 i=1;
1365 1493 from_arr[i] = interpolate(from_arr[i], to_arr[i], pos);
1366 // sweep 1494 i=2;
1367 *sweep = strtol(end1, &end2, 10) ? EINA_TRUE : EINA_FALSE; 1495 from_arr[i] = interpolate(from_arr[i], to_arr[i], pos);
1368 if (!end2 || (end1 == end2)) return EINA_FALSE; 1496 i=5;
1369 str = _skipcomma(end2); 1497 from_arr[i] = interpolate(from_arr[i], to_arr[i], pos);
1370 1498 i=6;
1371 if (_parse_number(&str, x)) 1499 from_arr[i] = interpolate(from_arr[i], to_arr[i], pos);
1372 if (_parse_number(&str, y))
1373 {
1374 *end = str;
1375 return EINA_TRUE;
1376 }
1377 } 1500 }
1501 else
1502 {
1503 for(i=0; i < from_count; i++)
1504 {
1505 from_arr[i] = interpolate(from_arr[i], to_arr[i], pos);
1506 }
1507 }
1508 process_command(obj, pd, from_cmd, from_arr, from_count, &cur_x, &cur_y);
1378 } 1509 }
1379 } 1510 else
1380 return EINA_FALSE;
1381}
1382
1383static Eina_Bool
1384_efl_gfx_path_parse_arc_to(const char *content, char **end,
1385 Eo *obj, Efl_Gfx_Path_Data *pd,
1386 double *current_x, double *current_y,
1387 void (*func)(Eo *obj, Efl_Gfx_Path_Data *pd,
1388 double x, double y, double rx, double ry,
1389 double angle, Eina_Bool large_arc, Eina_Bool sweep),
1390 Eina_Bool rel)
1391{
1392 double x, y, rx, ry, angle;
1393 Eina_Bool large_arc, sweep; // FIXME: handle those flag
1394
1395 *end = (char*) content;
1396
1397 do
1398 {
1399 Eina_Bool r;
1400
1401 r = _efl_gfx_path_parse_arc(content, end, &x, &y, &rx, &ry, &angle,
1402 &large_arc, &sweep);
1403 if (!r) return EINA_FALSE;
1404
1405 if (rel)
1406 { 1511 {
1407 x += *current_x; 1512 goto error;
1408 y += *current_y;
1409 } 1513 }
1410
1411 func(obj, pd, x, y, rx, ry, angle, large_arc, sweep);
1412 content = *end;
1413
1414 *current_x = x;
1415 *current_y = y;
1416 } 1514 }
1417 while (_next_isnumber(content));
1418 1515
1419 return EINA_TRUE; 1516error:
1517 setlocale(LC_NUMERIC, cur_locale);
1518 if (cur_locale)
1519 free(cur_locale);
1420} 1520}
1421 1521
1422EOLIAN static void 1522EOLIAN static void
1423_efl_gfx_path_append_svg_path(Eo *obj, Efl_Gfx_Path_Data *pd, 1523_efl_gfx_path_append_svg_path(Eo *obj, Efl_Gfx_Path_Data *pd,
1424 const char *svg_path_data) 1524 const char *svg_path_data)
1425{ 1525{
1426 double current_x = 0, current_y = 0; 1526 double number_array[7];
1427 1527 int number_count = 0;
1428 //FIXME: const char *svg_path_data ??? 1528 double cur_x=0, cur_y=0;
1429 char *content = (char*) svg_path_data; 1529 char cmd= 0;
1530 char *path = (char *) svg_path_data;
1531 Eina_Bool arc = EINA_FALSE;
1532 char *cur_locale;
1533
1534 if (!path)
1535 return;
1430 1536
1431 if (!content) return; 1537 cur_locale = setlocale(LC_NUMERIC, NULL);
1538 if (cur_locale)
1539 cur_locale = strdup(cur_locale);
1540 setlocale(LC_NUMERIC, "POSIX");
1432 1541
1433 while (content[0] != '\0') 1542 while ((path[0] != '\0'))
1434 { 1543 {
1435 while (isspace(content[0])) content++; 1544 path = _next_command(path, &cmd, number_array, &number_count);
1436 1545 if (!path)
1437 switch (content[0])
1438 { 1546 {
1439 case 'M': 1547 //printf("Error parsing command\n");
1440 if (!_efl_gfx_path_parse_pair_to(&content[1], &content, obj, pd, 1548 goto error;
1441 &current_x, &current_y,
1442 _efl_gfx_path_append_move_to,
1443 EINA_FALSE))
1444 return;
1445 break;
1446 case 'm':
1447 if (!_efl_gfx_path_parse_pair_to(&content[1], &content, obj, pd,
1448 &current_x, &current_y,
1449 _efl_gfx_path_append_move_to,
1450 EINA_TRUE))
1451 return;
1452 break;
1453 case 'z':
1454 case 'Z':
1455 _efl_gfx_path_append_close(obj, pd);
1456 content++;
1457 break;
1458 case 'L':
1459 if (!_efl_gfx_path_parse_pair_to(&content[1], &content, obj, pd,
1460 &current_x, &current_y,
1461 _efl_gfx_path_append_line_to,
1462 EINA_FALSE))
1463 return;
1464 break;
1465 case 'l':
1466 if (!_efl_gfx_path_parse_pair_to(&content[1], &content, obj, pd,
1467 &current_x, &current_y,
1468 _efl_gfx_path_append_line_to,
1469 EINA_TRUE))
1470 return;
1471 break;
1472 case 'H':
1473 if (!_efl_gfx_path_parse_double_to(&content[1], &content, obj, pd,
1474 &current_x, current_x,
1475 current_y,
1476 _efl_gfx_path_append_horizontal_to,
1477 EINA_FALSE))
1478 return;
1479 break;
1480 case 'h':
1481 if (!_efl_gfx_path_parse_double_to(&content[1], &content, obj, pd,
1482 &current_x, current_x,
1483 current_y,
1484 _efl_gfx_path_append_horizontal_to,
1485 EINA_TRUE))
1486 return;
1487 break;
1488 case 'V':
1489 if (!_efl_gfx_path_parse_double_to(&content[1], &content, obj, pd,
1490 &current_y, current_x,
1491 current_y,
1492 _efl_gfx_path_append_vertical_to,
1493 EINA_FALSE))
1494 return;
1495 break;
1496 case 'v':
1497 if (!_efl_gfx_path_parse_double_to(&content[1], &content, obj, pd,
1498 &current_y, current_x,
1499 current_y,
1500 _efl_gfx_path_append_vertical_to,
1501 EINA_TRUE))
1502 return;
1503 break;
1504 case 'C':
1505 if (!_efl_gfx_path_parse_six_to(&content[1], &content, obj, pd,
1506 &current_x, &current_y,
1507 _efl_gfx_path_append_cubic_to,
1508 EINA_FALSE))
1509 return;
1510 break;
1511 case 'c':
1512 if (!_efl_gfx_path_parse_six_to(&content[1], &content, obj, pd,
1513 &current_x, &current_y,
1514 _efl_gfx_path_append_cubic_to,
1515 EINA_TRUE))
1516 return;
1517 break;
1518 case 'S':
1519 if (!_efl_gfx_path_parse_quad_to(&content[1], &content, obj, pd,
1520 &current_x, &current_y,
1521 _efl_gfx_path_append_scubic_to,
1522 EINA_FALSE))
1523 return;
1524 break;
1525 case 's':
1526 if (!_efl_gfx_path_parse_quad_to(&content[1], &content,
1527 obj, pd, &current_x, &current_y,
1528 _efl_gfx_path_append_scubic_to,
1529 EINA_TRUE))
1530 return;
1531 break;
1532 case 'Q':
1533 if (!_efl_gfx_path_parse_quad_to(&content[1], &content,
1534 obj, pd, &current_x, &current_y,
1535 _efl_gfx_path_append_quadratic_to,
1536 EINA_FALSE))
1537 return;
1538 break;
1539 case 'q':
1540 if (!_efl_gfx_path_parse_quad_to(&content[1], &content,
1541 obj, pd, &current_x, &current_y,
1542 _efl_gfx_path_append_quadratic_to,
1543 EINA_TRUE))
1544 return;
1545 break;
1546 case 'T':
1547 if (!_efl_gfx_path_parse_pair_to(&content[1], &content,
1548 obj, pd, &current_x, &current_y,
1549 _efl_gfx_path_append_squadratic_to,
1550 EINA_FALSE))
1551 return;
1552 break;
1553 case 't':
1554 if (!_efl_gfx_path_parse_pair_to(&content[1], &content,
1555 obj, pd, &current_x, &current_y,
1556 _efl_gfx_path_append_squadratic_to,
1557 EINA_TRUE))
1558 return;
1559 break;
1560 case 'A':
1561 if (!_efl_gfx_path_parse_arc_to(&content[1], &content,
1562 obj, pd, &current_x, &current_y,
1563 _efl_gfx_path_append_arc_to,
1564 EINA_FALSE))
1565 return;
1566 break;
1567 case 'a':
1568 if (!_efl_gfx_path_parse_arc_to(&content[1], &content,
1569 obj, pd, &current_x, &current_y,
1570 _efl_gfx_path_append_arc_to,
1571 EINA_TRUE))
1572 return;
1573 break;
1574 default:
1575 return;
1576 } 1549 }
1550 process_command(obj, pd, cmd, number_array, number_count, &cur_x, &cur_y);
1551 if ((!arc) && ((cmd == 'a') || (cmd == 'A') ||
1552 (cmd == 'e') || (cmd == 'E')))
1553 arc = EINA_TRUE;
1554 }
1555 if (arc)
1556 {
1557 // need to keep the path for interpolation
1558 if (pd->path_data)
1559 free(pd->path_data);
1560 pd->path_data = malloc(strlen(svg_path_data) + 1);
1561 strcpy(pd->path_data, svg_path_data);
1577 } 1562 }
1563
1564error:
1565 setlocale(LC_NUMERIC, cur_locale);
1566 if (cur_locale)
1567 free(cur_locale);
1578} 1568}
1579 1569
1580EOLIAN static void 1570EOLIAN static void