changeset 269:c96f38ad4bb6

Fix mis-behavior of translate_path_data() on arc. - Arc in a path in svg2code_ex is not showed. - translate_path_data() in svg2code.py was modified for calling binary version new method for path shape. - rdman_shape_path_new_from_binary() - Code to translate path data does not handle arc in a right way. - Copy calc_center_and_x_aix() from shape_path.c to svg2code.py and change name _calc_ellipse_of_arc() - _calc_ellipse_of_arc() handle arc data for translate_path_data()
author Thinker K.F. Li <thinker@branda.to>
date Sun, 25 Jan 2009 00:20:34 +0800
parents 43900cae1d49
children cd6af7da32c9
files Doxyfile Doxyfile-sf src/shape_path.c tools/svg2code.py
diffstat 4 files changed, 106 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/Doxyfile	Sat Jan 24 18:19:02 2009 +0800
+++ b/Doxyfile	Sun Jan 25 00:20:34 2009 +0800
@@ -534,7 +534,7 @@
 # directories like "/usr/src/myproject". Separate the files or directories 
 # with spaces.
 
-INPUT                  = src include dox README.h COPYING.h
+INPUT                  = src tools include dox README.h COPYING.h
 
 # This tag can be used to specify the character encoding of the source files 
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
--- a/Doxyfile-sf	Sat Jan 24 18:19:02 2009 +0800
+++ b/Doxyfile-sf	Sun Jan 25 00:20:34 2009 +0800
@@ -534,7 +534,7 @@
 # directories like "/usr/src/myproject". Separate the files or directories 
 # with spaces.
 
-INPUT                  = src include dox README.h COPYING.h
+INPUT                  = src tools include dox README.h COPYING.h
 
 # This tag can be used to specify the character encoding of the source files 
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
--- a/src/shape_path.c	Sat Jan 24 18:19:02 2009 +0800
+++ b/src/shape_path.c	Sun Jan 25 00:20:34 2009 +0800
@@ -53,11 +53,16 @@
 #include <math.h>
 /*! \brief Calculate center of the ellipse of an arc.
  *
+ * Origin of our coordination is left-top corner, and y-axis are grown
+ * to down-side.
+ *
+ * Space of the arc is transformed to space that correspondent
+ * ellipse containing the arc is mapped into an unit circle.
  * - ux0 = x0 / rx
  * - uy0 = y0 / ry
  * - ux = x / rx
- * - uy = y / rx
- * ux0, uy0, ux, yu are got by transforming (x0, y0) and (x, y) into points
+ * - uy = y / ry
+ * ux0, uy0, ux, uy are got by transforming (x0, y0) and (x, y) into points
  * on the unit circle. The center of unit circle are (ucx, ucy):
  * - umx = (ux0 + ux) / 2
  * - umy = (uy0 + uy) / 2
@@ -68,7 +73,9 @@
  *
  * - udx * udcx + udy * udcy = 0
  *
- * - udl2 = udx ** 2 + udy ** 2;
+ * - udl2 = udx ** 2 + udy ** 2
+ *
+ * For drawing small arc in clockwise
  * - udx * udcy - udy * udcx = sqrt((1 - udl2) * udl2)
  *
  * - udcy = -udcx * udx / udy
@@ -118,9 +125,11 @@
     udl2 = udx2 + udy2;
 
     if(udy != 0) {
+	/* center is at left-side of arc */
 	udcx = -sqrtf((1 - udl2) * udl2) / (udy + udx2 / udy);
 	udcy = -udcx * udx / udy;
     } else {
+	/* center is at down-side of arc */
 	udcx = 0;
 	udcy = sqrtf((1 - udl2) * udl2) / udx;
     }
--- a/tools/svg2code.py	Sat Jan 24 18:19:02 2009 +0800
+++ b/tools/svg2code.py	Sun Jan 25 00:20:34 2009 +0800
@@ -210,6 +210,63 @@
         pass
     return coord_id
 
+## \brief Calculate geometry of ellipse where the arc is on.
+#
+# This function calculate the ellipse with information from SVG path data.
+#
+# \see calc_center_and_x_aix()
+def _calc_ellipse_of_arc(x0, y0, rx, ry, x_rotate, large, sweep, x, y):
+    import math
+    
+    _sin = math.sin(x_rotate)
+    _cos = math.cos(x_rotate)
+    
+    nrx = x * _cos + y * _sin
+    nry = x * -_sin + y * _cos
+    nrx0 = x0 * _cos + y0 * _sin
+    nry0 = x0 * -_sin + y0 * _cos
+    
+    udx = (nrx - nrx0) / 2 / rx # ux - umx
+    udy = (nry - nry0) / 2 / ry # uy - umy
+    umx = (nrx + nrx0) / 2 / rx
+    umy = (nry + nry0) / 2 / ry
+
+    udx2 = udx * udx
+    udy2 = udy * udy
+    udl2 = udx2 + udy2
+
+    if udy != 0:
+	# center is at left-side of arc
+	udcx = -math.sqrt((1 - udl2) * udl2) / (udy + udx2 / udy)
+	udcy = -udcx * udx / udy
+    else:
+	# center is at down-side of arc
+	udcx = 0
+	udcy = math.sqrt((1 - udl2) * udl2) / udx
+        pass
+
+    reflect = 0
+    if large:
+	reflect ^= 1
+        pass
+    if sweep != 1:
+	reflect ^= 1
+        pass
+    if reflect:
+	udcx = -udcx
+	udcy = -udcy
+        pass
+
+    nrcx = rx * (udcx + umx)
+    nrcy = ry * (udcy + umy)
+    
+    cx = nrcx * _cos - nrcy * _sin
+    cy = nrcx * _sin + nrcy * _cos
+    
+    xx = rx * _cos + cx
+    xy = rx * _sin + cy
+    return cx, cy, xx, xy
+
 # M x y             : Move to (x,y)
 # Z                 : close path
 # L x y             : lineto (x,y)
@@ -233,8 +290,8 @@
                 'C': 6, 'c':6,
                 'S': 4, 's':4,
                 'Q': 4, 'q':4,
-                'T': 2, 't':2}
-
+                'T': 2, 't':2,
+                'A': 7, 'a':7}
 
 def translate_path_data(data,codefo):
     temp = data.split()
@@ -244,33 +301,41 @@
             if s != '':
                 fields.append(s)
     cmd = ''
+    cmd_args = 0
     commands=''
     args=[]
+    narg = 0
     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]
+        if f in command_length:
+            if cmd_args != 0 and (narg % cmd_args) != 0:
+                raise ValueError, 'invalid path data %s' % (repr(fields))
+            cmd = f
+            cmd_args = command_length[f]
+            narg = 0
+            continue
+
+        if (narg % cmd_args) == 0:
+            commands = commands + cmd
+            pass
+        arg = float(f)
+        args.append(arg)
+        narg = narg + 1
+        
+        if (narg % cmd_args) == 0 and (cmd in 'Aa'):
+            x0, y0, rx, ry, x_rotate, large, sweep, x, y = \
+                tuple(args[-9:])
+            x_rotate = int(x_rotate)
+            large = int(large)
+            sweep = int(sweep)
+            cx, cy, xx, xy = _calc_ellipse_of_arc(x0, y0, rx, ry,
+                                                  x_rotate, large,
+                                                  sweep, x, y)
+            args[-7:] = [cx, cy, xx, xy, x, y]
+            fix_args.append(sweep)
+            pass
+        pass
+    return commands, args, fix_args
 
 _id_sn = 0
 
@@ -307,7 +372,7 @@
 
     path_id = path.getAttribute('id')
     d = path.getAttribute('d')
-    (commands,args,fix_args) = translate_path_data(d,codefo)
+    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)
     sarg=''
@@ -536,7 +601,7 @@
 def svg_2_code(dom, codefo):
     for node in dom.childNodes:
         if node.localName == 'svg' and node.namespaceURI == svgns:
-            break;
+            break
         pass
     else:
         raise ValueErr, 'no any svg tag node.'