changeset 197:bcad1ccdf45c

Translate the path string into binary array to save the parsing in the runtime. It can reduce the size as well.
author wycc@wycc-desktop
date Wed, 19 Nov 2008 00:27:20 +0800
parents 54fdc2a65242
children f9d507a3e1d9
files include/mb_shapes.h src/shape_path.c tools/mb_c_source.m4 tools/svg2code.py
diffstat 4 files changed, 115 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/include/mb_shapes.h	Tue Nov 18 21:42:30 2008 +0800
+++ b/include/mb_shapes.h	Wed Nov 19 00:27:20 2008 +0800
@@ -39,6 +39,7 @@
  * @{
  */
 extern shape_t *rdman_shape_path_new(redraw_man_t *rdman, char *data);
+extern shape_t *rdman_shape_path_new_from_binary(redraw_man_t *rdman, char *commands, co_aix *arg,int  arg_cnt,int *fix_arg,int fix_arg_cnt);
 extern void sh_path_transform(shape_t *shape);
 extern void sh_path_draw(shape_t *shape, cairo_t *cr);
 /* @} */
--- a/src/shape_path.c	Tue Nov 18 21:42:30 2008 +0800
+++ b/src/shape_path.c	Wed Nov 19 00:27:20 2008 +0800
@@ -713,6 +713,42 @@
     return (shape_t *)path;
 }
 
+shape_t *rdman_shape_path_new_from_binary(redraw_man_t *rdman, char *commands, co_aix *arg,int  arg_cnt,int *fix_arg,int fix_arg_cnt) {
+    sh_path_t *path;
+    int msz;
+    int cmd_cnt = strlen(commands);
+
+    /*! \todo Use elmpool to manage sh_path_t objects. */
+    path = (sh_path_t *)malloc(sizeof(sh_path_t));
+    /*! \todo Remove this memset()? */
+    memset(&path->shape, 0, sizeof(shape_t));
+    path->shape.sh_type = SHT_PATH;
+    path->cmd_len = strlen(commands);
+    path->arg_len = arg_cnt;
+    path->fix_arg_len = fix_arg_cnt;
+    msz = cmd_cnt + sizeof(co_aix) * arg_cnt + sizeof(int) * fix_arg_cnt;
+    path->user_data = (char *)malloc(msz * 2);
+    if(path->user_data == NULL) {
+	free(path);
+	return NULL;
+    }
+
+    path->dev_data = path->user_data + msz;
+    memcpy(path->user_data,commands,cmd_cnt);
+    memcpy(path->user_data+cmd_cnt,arg, sizeof(co_aix)*arg_cnt);
+    memcpy(path->user_data+cmd_cnt+arg_cnt*sizeof(co_aix),fix_arg, sizeof(int)*fix_arg_cnt);
+    memcpy(path->dev_data, path->user_data, msz);
+
+    path->shape.free = sh_path_free;
+
+#ifndef UNITTEST
+    rdman_shape_man(rdman, (shape_t *)path);
+#endif
+
+    return (shape_t *)path;
+}
+
+
 /*! \brief Transform a path from user space to device space.
  *
  */
--- a/tools/mb_c_source.m4	Tue Nov 18 21:42:30 2008 +0800
+++ b/tools/mb_c_source.m4	Wed Nov 19 00:27:20 2008 +0800
@@ -86,12 +86,18 @@
 
 define([S_ADD_RECT],[[
     obj->$1 = rdman_shape_rect_new(rdman, $2, $3, $4, $5, $6, $7);
+
     rdman_add_shape(rdman, obj->$1, obj->$8);
 ]])
 
 define([S_ADD_PATH],[[
-    obj->$1 = rdman_shape_path_new(rdman, "$2");
-    rdman_add_shape(rdman, obj->$1, obj->$3);
+    {
+        char _cmds[] = "$3";
+        float _args[] = {$4};
+        int _fix_args[] = {$6};
+        obj->$1 = rdman_shape_path_new_from_binary(rdman, _cmds,_args,$5,_fix_args,$7);
+        rdman_add_shape(rdman, obj->$1, obj->$2);
+    }
 ]])
 
 define([S_ADD_COORD],[[
--- a/tools/svg2code.py	Tue Nov 18 21:42:30 2008 +0800
+++ b/tools/svg2code.py	Wed Nov 19 00:27:20 2008 +0800
@@ -210,13 +210,82 @@
         pass
     return coord_id
 
+# M x y             : Move to (x,y)
+# Z                 : close path
+# L x y             : lineto (x,y)
+# H x               : horizontal line to x
+# V y               : Vertical line to y
+# C x1 y1 x2 y2 x y : Draw a segment of bezier curve
+# S x2 y2 x t       : Draw a segment of bezier curve from the last control point
+# Q x1 y1 x y       : Draw a segment of quadratic curve
+# T x y             : Draw a segment of quadratic curve from the last control pint
+# A x y r f s x y   : Draw an arc
+# translate the path data into two arrays. The first is an integer whose upper 8
+# bits are the command type The second array hold all arguments.
+
+command_length={'M': 2, 'm':2,
+                'Z': 0, 'z':0,
+                'L': 2, 'l':2,
+                'H': 1, 'h':1,
+                'V': 1, 'v':1,
+                'C': 6, 'c':6,
+                'S': 4, 's':4,
+                'Q': 4, 'q':4,
+                'T': 2, 't':2}
+
+
+def translate_path_data(data,codefo):
+    temp = data.split()
+    fields=[]
+    for f in temp:
+        for s in f.split(','):
+            if s != '':
+                fields.append(s)
+    cmd = ''
+    commands=''
+    args=[]
+    fix_args=[]
+    for f in fields:
+        if cmd == 'A' or cmd == 'a':
+            try:
+                d = int(f)
+                fix_args.append(d)
+                if (narg % 7) == 0:
+                    commands = commands + cmd
+                narg = narg + 1
+            except:
+	        pass
+        else:
+            try:
+	        d = float(f)
+            	args.append(d)
+            	if (narg % command_length[cmd]) == 0:
+                    commands = commands + cmd
+            	narg = narg + 1
+            	continue
+            except:
+                pass
+        cmd = f
+        narg=0
+    pass
+    return [commands,args,fix_args]
+
 def translate_path(path, coord_id, codefo, doc):
     coord_id = translate_shape_transform(path, coord_id, codefo)
 
     path_id = path.getAttribute('id')
     d = path.getAttribute('d')
+    (commands,args,fix_args) = translate_path_data(d,codefo)
     print >> codefo, 'dnl'
-    print >> codefo, 'ADD_PATH([%s], [%s], [%s])dnl' % (path_id, d, coord_id)
+    #print >> codefo, 'ADD_PATH([%s], [%s], [%s])dnl' % (path_id, d, coord_id)
+    sarg=''
+    for c in args:
+        sarg = sarg + "%f," % c
+    s_fix_arg=''
+    for c in fix_args:
+        s_fix_arg = s_fix_arg + ("%d," % c)
+
+    print >> codefo, 'ADD_PATH([%s], [%s],[%s],[%s],[%d],[%s],[%d])dnl' % (path_id, coord_id,commands,sarg,len(args),s_fix_arg,len(fix_args))
 
     translate_style(path, coord_id, codefo, doc, 'PATH_')
     pass