Code

Translations. French translation minor update.
[inkscape.git] / share / extensions / simpletransform.py
index cf0751ca85df2f4ecc42d4d65a983c6c69c713d5..8f8a811dc0d94d905ba4c51874241e80ac2be173 100644 (file)
-#!/usr/bin/env python\r
-'''\r
-Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr\r
-\r
-This program is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-This program is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with this program; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-barraud@math.univ-lille1.fr\r
-\r
-This code defines several functions to make handling of transform\r
-attribute easier.\r
-'''\r
-import inkex, cubicsuperpath, bezmisc, simplestyle\r
-import copy, math, re\r
-\r
-def parseTransform(transf,mat=[[1.0,0.0,0.0],[0.0,1.0,0.0]]):\r
-    if transf=="" or transf==None:\r
-        return(mat)\r
-    result=re.match("(translate|scale|rotate|skewX|skewY|matrix)\(([^)]*)\)",transf)\r
-#-- translate --\r
-    if result.group(1)=="translate":\r
-        args=result.group(2).split(",")\r
-        dx=float(args[0])\r
-        if len(args)==1:\r
-            dy=0.0\r
-        else:\r
-            dy=float(args[1])\r
-        matrix=[[1,0,dx],[0,1,dy]]\r
-#-- scale --\r
-    if result.groups(1)=="scale":\r
-        args=result.group(2).split(",")\r
-        sx=float(args[0])\r
-        if len(args)==1:\r
-            sy=sx\r
-        else:\r
-            sy=float(args[1])\r
-        matrix=[[sx,0,0],[0,sy,0]]\r
-#-- rotate --\r
-    if result.groups(1)=="rotate":\r
-        args=result.group(2).split(",")\r
-        a=float(args[0])*math.pi/180\r
-        if len(args)==1:\r
-            cx,cy=(0.0,0.0)\r
-        else:\r
-            cx,cy=args[1:]\r
-        matrix=[[math.cos(a),-math.sin(a),cx],[math.sin(a),math.cos(a),cy]]\r
-#-- skewX --\r
-    if result.groups(1)=="skewX":\r
-        a=float(result.group(2))*math.pi/180\r
-        matrix=[[1,math.tan(a),0],[0,1,0]]\r
-#-- skewX --\r
-    if result.groups(1)=="skewX":\r
-        a=float(result.group(2))*math.pi/180\r
-        matrix=[[1,0,0],[math.tan(a),1,0]]\r
-#-- matrix --\r
-    if result.group(1)=="matrix":\r
-        a11,a21,a12,a22,v1,v2=result.group(2).split(",")\r
-        matrix=[[float(a11),float(a12),float(v1)],[float(a21),float(a22),float(v2)]]\r
-    \r
-    matrix=composeTransform(mat,matrix)\r
-    if result.end()<len(transf):\r
-        return(parseTransform(transf[result.end():],matrix))\r
-    else:\r
-        return matrix\r
-\r
-def formatTransform(mat):\r
-    return("matrix(%f,%f,%f,%f,%f,%f)"%(mat[0][0],mat[1][0],mat[0][1],mat[1][1],mat[0][2],mat[1][2]))\r
-\r
-def composeTransform(M1,M2):\r
-    a11=M1[0][0]*M2[0][0]+M1[0][1]*M2[1][0]\r
-    a12=M1[0][0]*M2[0][1]+M1[0][1]*M2[1][1]\r
-    a21=M1[1][0]*M2[0][0]+M1[1][1]*M2[1][0]\r
-    a22=M1[1][0]*M2[0][1]+M1[1][1]*M2[1][1]\r
-\r
-    v1=M1[0][0]*M2[0][2]+M1[0][1]*M2[1][2]+M1[0][2]\r
-    v2=M1[1][0]*M2[0][2]+M1[1][1]*M2[1][2]+M1[1][2]\r
-    return [[a11,a12,v1],[a21,a22,v2]]\r
-\r
-def applyTransformToNode(mat,node):\r
-    m=parseTransform(node.get("transform"))\r
-    newtransf=formatTransform(composeTransform(mat,m))\r
-    node.set("transform", newtransf)\r
-\r
-def applyTransformToPoint(mat,pt):\r
-    x=mat[0][0]*pt[0]+mat[0][1]*pt[1]+mat[0][2]\r
-    y=mat[1][0]*pt[0]+mat[1][1]*pt[1]+mat[1][2]\r
-    pt[0]=x\r
-    pt[1]=y\r
-\r
-def applyTransformToPath(mat,path):\r
-    for comp in path:\r
-        for ctl in comp:\r
-            for pt in ctl:\r
-                applyTransformToPoint(mat,pt)\r
-\r
-def fuseTransform(node):\r
-    if node.get('d')==None:\r
-        #FIX ME: how do you raise errors?\r
-        raise AssertionError, 'can not fuse "transform" of elements that have no "d" attribute'\r
-    t = node.get("transform")\r
-    if t == None:\r
-        return\r
-    m = parseTransform(t)\r
-    d = node.get('d')\r
-    p = cubicsuperpath.parsePath(d)\r
-    applyTransformToPath(m,p)\r
-    node.set('d', cubicsuperpath.formatPath(p))\r
-    del node.attrib["transform"]\r
-\r
-####################################################################\r
-##-- Some functions to compute a rough bbox of a given list of objects.\r
-##-- this should be shipped out in an separate file...\r
-\r
-def boxunion(b1,b2):\r
-    if b1 is None:\r
-        return b2\r
-    elif b2 is None:\r
-        return b1    \r
-    else:\r
-        return((min(b1[0],b2[0]),max(b1[1],b2[1]),min(b1[2],b2[2]),max(b1[3],b2[3])))\r
-\r
-def roughBBox(path):\r
-    xmin,xMax,ymin,yMax=path[0][0][0][0],path[0][0][0][0],path[0][0][0][1],path[0][0][0][1]\r
-    for pathcomp in path:\r
-        for ctl in pathcomp:\r
-           for pt in ctl:\r
-               xmin=min(xmin,pt[0])\r
-               xMax=max(xMax,pt[0])\r
-               ymin=min(ymin,pt[1])\r
-               yMax=max(yMax,pt[1])\r
-    return xmin,xMax,ymin,yMax\r
-\r
-def computeBBox(aList,mat=[[1,0,0],[0,1,0]]):\r
-    bbox=None\r
-    for node in aList:\r
-        m = parseTransform(node.get('transform'))\r
-        m = composeTransform(mat,m)\r
-        #TODO: text not supported!\r
-        if node.get("d"):\r
-            d = node.get('d')\r
-            p = cubicsuperpath.parsePath(d)\r
-            applyTransformToPath(m,p)\r
-            bbox=boxunion(roughBBox(p),bbox)\r
-\r
-        if  node.tag == inkex.addNS('use','svg') or node.tag=='use':\r
-            refid=node.get(inkex.addNS('href','xlink'))\r
-            path = '//*[@id="%s"]' % refid[1:]\r
-            refnode = node.getroottree().xpath(path, namespaces=inkex.NSS)\r
-            bbox=boxunion(computeBBox(refnode,m),bbox)\r
-            \r
-        bbox=boxunion(computeBBox(node,m),bbox)\r
-    return bbox\r
-\r
-\r
+#!/usr/bin/env python
+'''
+Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr
+Copyright (C) 2010 Alvin Penner, penner@vaxxine.com
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+barraud@math.univ-lille1.fr
+
+This code defines several functions to make handling of transform
+attribute easier.
+'''
+import inkex, cubicsuperpath, bezmisc, simplestyle
+import copy, math, re
+
+def parseTransform(transf,mat=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]):
+    if transf=="" or transf==None:
+        return(mat)
+    stransf = transf.strip()
+    result=re.match("(translate|scale|rotate|skewX|skewY|matrix)\s*\(([^)]*)\)\s*,?",stransf)
+#-- translate --
+    if result.group(1)=="translate":
+        args=result.group(2).replace(',',' ').split()
+        dx=float(args[0])
+        if len(args)==1:
+            dy=0.0
+        else:
+            dy=float(args[1])
+        matrix=[[1,0,dx],[0,1,dy]]
+#-- scale --
+    if result.group(1)=="scale":
+        args=result.group(2).replace(',',' ').split()
+        sx=float(args[0])
+        if len(args)==1:
+            sy=sx
+        else:
+            sy=float(args[1])
+        matrix=[[sx,0,0],[0,sy,0]]
+#-- rotate --
+    if result.group(1)=="rotate":
+        args=result.group(2).replace(',',' ').split()
+        a=float(args[0])*math.pi/180
+        if len(args)==1:
+            cx,cy=(0.0,0.0)
+        else:
+            cx,cy=map(float,args[1:])
+        matrix=[[math.cos(a),-math.sin(a),cx],[math.sin(a),math.cos(a),cy]]
+        matrix=composeTransform(matrix,[[1,0,-cx],[0,1,-cy]])
+#-- skewX --
+    if result.group(1)=="skewX":
+        a=float(result.group(2))*math.pi/180
+        matrix=[[1,math.tan(a),0],[0,1,0]]
+#-- skewY --
+    if result.group(1)=="skewY":
+        a=float(result.group(2))*math.pi/180
+        matrix=[[1,0,0],[math.tan(a),1,0]]
+#-- matrix --
+    if result.group(1)=="matrix":
+        a11,a21,a12,a22,v1,v2=result.group(2).replace(',',' ').split()
+        matrix=[[float(a11),float(a12),float(v1)], [float(a21),float(a22),float(v2)]]
+
+    matrix=composeTransform(mat,matrix)
+    if result.end() < len(stransf):
+        return(parseTransform(stransf[result.end():], matrix))
+    else:
+        return matrix
+
+def formatTransform(mat):
+    return ("matrix(%f,%f,%f,%f,%f,%f)" % (mat[0][0], mat[1][0], mat[0][1], mat[1][1], mat[0][2], mat[1][2]))
+
+def composeTransform(M1,M2):
+    a11 = M1[0][0]*M2[0][0] + M1[0][1]*M2[1][0]
+    a12 = M1[0][0]*M2[0][1] + M1[0][1]*M2[1][1]
+    a21 = M1[1][0]*M2[0][0] + M1[1][1]*M2[1][0]
+    a22 = M1[1][0]*M2[0][1] + M1[1][1]*M2[1][1]
+
+    v1 = M1[0][0]*M2[0][2] + M1[0][1]*M2[1][2] + M1[0][2]
+    v2 = M1[1][0]*M2[0][2] + M1[1][1]*M2[1][2] + M1[1][2]
+    return [[a11,a12,v1],[a21,a22,v2]]
+
+def applyTransformToNode(mat,node):
+    m=parseTransform(node.get("transform"))
+    newtransf=formatTransform(composeTransform(mat,m))
+    node.set("transform", newtransf)
+
+def applyTransformToPoint(mat,pt):
+    x = mat[0][0]*pt[0] + mat[0][1]*pt[1] + mat[0][2]
+    y = mat[1][0]*pt[0] + mat[1][1]*pt[1] + mat[1][2]
+    pt[0]=x
+    pt[1]=y
+
+def applyTransformToPath(mat,path):
+    for comp in path:
+        for ctl in comp:
+            for pt in ctl:
+                applyTransformToPoint(mat,pt)
+
+def fuseTransform(node):
+    if node.get('d')==None:
+        #FIXME: how do you raise errors?
+        raise AssertionError, 'can not fuse "transform" of elements that have no "d" attribute'
+    t = node.get("transform")
+    if t == None:
+        return
+    m = parseTransform(t)
+    d = node.get('d')
+    p = cubicsuperpath.parsePath(d)
+    applyTransformToPath(m,p)
+    node.set('d', cubicsuperpath.formatPath(p))
+    del node.attrib["transform"]
+
+####################################################################
+##-- Some functions to compute a rough bbox of a given list of objects.
+##-- this should be shipped out in an separate file...
+
+def boxunion(b1,b2):
+    if b1 is None:
+        return b2
+    elif b2 is None:
+        return b1    
+    else:
+        return((min(b1[0],b2[0]), max(b1[1],b2[1]), min(b1[2],b2[2]), max(b1[3],b2[3])))
+
+def roughBBox(path):
+    xmin,xMax,ymin,yMax = path[0][0][0][0],path[0][0][0][0],path[0][0][0][1],path[0][0][0][1]
+    for pathcomp in path:
+        for ctl in pathcomp:
+            for pt in ctl:
+                xmin = min(xmin,pt[0])
+                xMax = max(xMax,pt[0])
+                ymin = min(ymin,pt[1])
+                yMax = max(yMax,pt[1])
+    return xmin,xMax,ymin,yMax
+
+def refinedBBox(path):
+    xmin,xMax,ymin,yMax = path[0][0][1][0],path[0][0][1][0],path[0][0][1][1],path[0][0][1][1]
+    for pathcomp in path:
+        for i in range(1, len(pathcomp)):
+            cmin, cmax = cubicExtrema(pathcomp[i-1][1][0], pathcomp[i-1][2][0], pathcomp[i][0][0], pathcomp[i][1][0])
+            xmin = min(xmin, cmin)
+            xMax = max(xMax, cmax)
+            cmin, cmax = cubicExtrema(pathcomp[i-1][1][1], pathcomp[i-1][2][1], pathcomp[i][0][1], pathcomp[i][1][1])
+            ymin = min(ymin, cmin)
+            yMax = max(yMax, cmax)
+    return xmin,xMax,ymin,yMax
+
+def cubicExtrema(y0, y1, y2, y3):
+    cmin = min(y0, y3)
+    cmax = max(y0, y3)
+    d1 = y1 - y0
+    d2 = y2 - y1
+    d3 = y3 - y2
+    if (d1 - 2*d2 + d3):
+        if (d2*d2 > d1*d3):
+            t = (d1 - d2 + math.sqrt(d2*d2 - d1*d3))/(d1 - 2*d2 + d3)
+            if (t > 0) and (t < 1):
+                y = y0*(1-t)*(1-t)*(1-t) + 3*y1*t*(1-t)*(1-t) + 3*y2*t*t*(1-t) + y3*t*t*t
+                cmin = min(cmin, y)
+                cmax = max(cmax, y)
+            t = (d1 - d2 - math.sqrt(d2*d2 - d1*d3))/(d1 - 2*d2 + d3)
+            if (t > 0) and (t < 1):
+                y = y0*(1-t)*(1-t)*(1-t) + 3*y1*t*(1-t)*(1-t) + 3*y2*t*t*(1-t) + y3*t*t*t
+                cmin = min(cmin, y)
+                cmax = max(cmax, y)
+    elif (d3 - d1):
+        t = -d1/(d3 - d1)
+        if (t > 0) and (t < 1):
+            y = y0*(1-t)*(1-t)*(1-t) + 3*y1*t*(1-t)*(1-t) + 3*y2*t*t*(1-t) + y3*t*t*t
+            cmin = min(cmin, y)
+            cmax = max(cmax, y)
+    return cmin, cmax
+
+def computeBBox(aList,mat=[[1,0,0],[0,1,0]]):
+    bbox=None
+    for node in aList:
+        m = parseTransform(node.get('transform'))
+        m = composeTransform(mat,m)
+        #TODO: text not supported!
+        d = None
+        if node.get("d"):
+            d = node.get('d')
+        elif node.get('points'):
+            d = 'M' + node.get('points')
+        elif node.tag in [ inkex.addNS('rect','svg'), 'rect' ]:
+            d = 'M' + node.get('x', '0') + ',' + node.get('y', '0') + \
+                'h' + node.get('width') + 'v' + node.get('height') + \
+                'h-' + node.get('width')
+        elif node.tag in [ inkex.addNS('line','svg'), 'line' ]:
+            d = 'M' + node.get('x1') + ',' + node.get('y1') + \
+                ' ' + node.get('x2') + ',' + node.get('y2')
+        elif node.tag in [ inkex.addNS('circle','svg'), 'circle', \
+                            inkex.addNS('ellipse','svg'), 'ellipse' ]:
+            rx = node.get('r')
+            if rx is not None:
+                ry = rx
+            else:
+                rx = node.get('rx')
+                ry = node.get('ry')
+            cx = float(node.get('cx', '0'))
+            cy = float(node.get('cy', '0'))
+            x1 = cx - float(rx)
+            x2 = cx + float(rx)
+            d = 'M %f %f ' % (x1, cy) + \
+                'A' + rx + ',' + ry + ' 0 1 0 %f,%f' % (x2, cy) + \
+                'A' + rx + ',' + ry + ' 0 1 0 %f,%f' % (x1, cy)
+        if d is not None:
+            p = cubicsuperpath.parsePath(d)
+            applyTransformToPath(m,p)
+            bbox=boxunion(refinedBBox(p),bbox)
+
+        elif node.tag == inkex.addNS('use','svg') or node.tag=='use':
+            refid=node.get(inkex.addNS('href','xlink'))
+            path = '//*[@id="%s"]' % refid[1:]
+            refnode = node.xpath(path)
+            bbox=boxunion(computeBBox(refnode,m),bbox)
+            
+        bbox=boxunion(computeBBox(node,m),bbox)
+    return bbox
+
+
+# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99