| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
''' |
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
import inkex, cubicsuperpath |
|---|
| 25 |
import math, re |
|---|
| 26 |
|
|---|
| 27 |
def parseTransform(transf,mat=[[1.0,0.0,0.0],[0.0,1.0,0.0]]): |
|---|
| 28 |
if transf=="" or transf==None: |
|---|
| 29 |
return(mat) |
|---|
| 30 |
result=re.match("(translate|scale|rotate|skewX|skewY|matrix)\(([^)]*)\)",transf) |
|---|
| 31 |
|
|---|
| 32 |
if result.group(1)=="translate": |
|---|
| 33 |
args=result.group(2).split(",") |
|---|
| 34 |
dx=float(args[0]) |
|---|
| 35 |
if len(args)==1: |
|---|
| 36 |
dy=0.0 |
|---|
| 37 |
else: |
|---|
| 38 |
dy=float(args[1]) |
|---|
| 39 |
matrix=[[1,0,dx],[0,1,dy]] |
|---|
| 40 |
|
|---|
| 41 |
if result.groups(1)=="scale": |
|---|
| 42 |
args=result.group(2).split(",") |
|---|
| 43 |
sx=float(args[0]) |
|---|
| 44 |
if len(args)==1: |
|---|
| 45 |
sy=sx |
|---|
| 46 |
else: |
|---|
| 47 |
sy=float(args[1]) |
|---|
| 48 |
matrix=[[sx,0,0],[0,sy,0]] |
|---|
| 49 |
|
|---|
| 50 |
if result.groups(1)=="rotate": |
|---|
| 51 |
args=result.group(2).split(",") |
|---|
| 52 |
a=float(args[0])*math.pi/180 |
|---|
| 53 |
if len(args)==1: |
|---|
| 54 |
cx,cy=(0.0,0.0) |
|---|
| 55 |
else: |
|---|
| 56 |
cx,cy=args[1:] |
|---|
| 57 |
matrix=[[math.cos(a),-math.sin(a),cx],[math.sin(a),math.cos(a),cy]] |
|---|
| 58 |
|
|---|
| 59 |
if result.groups(1)=="skewX": |
|---|
| 60 |
a=float(result.group(2))*math.pi/180 |
|---|
| 61 |
matrix=[[1,math.tan(a),0],[0,1,0]] |
|---|
| 62 |
|
|---|
| 63 |
if result.groups(1)=="skewX": |
|---|
| 64 |
a=float(result.group(2))*math.pi/180 |
|---|
| 65 |
matrix=[[1,0,0],[math.tan(a),1,0]] |
|---|
| 66 |
|
|---|
| 67 |
if result.group(1)=="matrix": |
|---|
| 68 |
a11,a21,a12,a22,v1,v2=result.group(2).split(",") |
|---|
| 69 |
matrix=[[float(a11),float(a12),float(v1)],[float(a21),float(a22),float(v2)]] |
|---|
| 70 |
|
|---|
| 71 |
matrix=composeTransform(mat,matrix) |
|---|
| 72 |
if result.end()<len(transf): |
|---|
| 73 |
return(parseTransform(transf[result.end():],matrix)) |
|---|
| 74 |
else: |
|---|
| 75 |
return matrix |
|---|
| 76 |
|
|---|
| 77 |
def formatTransform(mat): |
|---|
| 78 |
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])) |
|---|
| 79 |
|
|---|
| 80 |
def composeTransform(M1,M2): |
|---|
| 81 |
a11=M1[0][0]*M2[0][0]+M1[0][1]*M2[1][0] |
|---|
| 82 |
a12=M1[0][0]*M2[0][1]+M1[0][1]*M2[1][1] |
|---|
| 83 |
a21=M1[1][0]*M2[0][0]+M1[1][1]*M2[1][0] |
|---|
| 84 |
a22=M1[1][0]*M2[0][1]+M1[1][1]*M2[1][1] |
|---|
| 85 |
|
|---|
| 86 |
v1=M1[0][0]*M2[0][2]+M1[0][1]*M2[1][2]+M1[0][2] |
|---|
| 87 |
v2=M1[1][0]*M2[0][2]+M1[1][1]*M2[1][2]+M1[1][2] |
|---|
| 88 |
return [[a11,a12,v1],[a21,a22,v2]] |
|---|
| 89 |
|
|---|
| 90 |
def writeTransformToNode(mat,node): |
|---|
| 91 |
node.set("transform", formatTransform(mat)) |
|---|
| 92 |
|
|---|
| 93 |
def applyTransformToNode(mat,node): |
|---|
| 94 |
m=parseTransform(node.get("transform")) |
|---|
| 95 |
writeTransformToNode(composeTransform(mat,m), node) |
|---|
| 96 |
|
|---|
| 97 |
def applyTransformToPoint(mat,pt): |
|---|
| 98 |
x=mat[0][0]*pt[0]+mat[0][1]*pt[1]+mat[0][2] |
|---|
| 99 |
y=mat[1][0]*pt[0]+mat[1][1]*pt[1]+mat[1][2] |
|---|
| 100 |
pt[0]=x |
|---|
| 101 |
pt[1]=y |
|---|
| 102 |
|
|---|
| 103 |
def applyTransformToPath(mat,path): |
|---|
| 104 |
for comp in path: |
|---|
| 105 |
for ctl in comp: |
|---|
| 106 |
for pt in ctl: |
|---|
| 107 |
applyTransformToPoint(mat,pt) |
|---|
| 108 |
|
|---|
| 109 |
|
|---|
| 110 |
|
|---|
| 111 |
|
|---|
| 112 |
|
|---|
| 113 |
def boxunion(b1,b2): |
|---|
| 114 |
if b1 is None: |
|---|
| 115 |
return b2 |
|---|
| 116 |
elif b2 is None: |
|---|
| 117 |
return b1 |
|---|
| 118 |
else: |
|---|
| 119 |
return((min(b1[0],b2[0]),max(b1[1],b2[1]),min(b1[2],b2[2]),max(b1[3],b2[3]))) |
|---|
| 120 |
|
|---|
| 121 |
def roughBBox(path): |
|---|
| 122 |
xmin,xMax,ymin,yMax=path[0][0][0][0],path[0][0][0][0],path[0][0][0][1],path[0][0][0][1] |
|---|
| 123 |
for pathcomp in path: |
|---|
| 124 |
for ctl in pathcomp: |
|---|
| 125 |
for pt in ctl: |
|---|
| 126 |
xmin=min(xmin,pt[0]) |
|---|
| 127 |
xMax=max(xMax,pt[0]) |
|---|
| 128 |
ymin=min(ymin,pt[1]) |
|---|
| 129 |
yMax=max(yMax,pt[1]) |
|---|
| 130 |
return xmin,xMax,ymin,yMax |
|---|
| 131 |
|
|---|
| 132 |
def computeBBox(aList,mat=[[1,0,0],[0,1,0]]): |
|---|
| 133 |
bbox=None |
|---|
| 134 |
for node in aList: |
|---|
| 135 |
m = parseTransform(node.get('transform')) |
|---|
| 136 |
m = composeTransform(mat,m) |
|---|
| 137 |
|
|---|
| 138 |
|
|---|
| 139 |
if node.tag == inkex.addNS('rect','svg'): |
|---|
| 140 |
A=[0,0] |
|---|
| 141 |
B=[0,0] |
|---|
| 142 |
A[0] = float(node.get('x')) |
|---|
| 143 |
A[1] = float(node.get('y')) |
|---|
| 144 |
B[0] = A[0]+float(node.get('width')) |
|---|
| 145 |
B[1] = A[1]+float(node.get('height')) |
|---|
| 146 |
applyTransformToPoint(mat, A) |
|---|
| 147 |
applyTransformToPoint(mat, B) |
|---|
| 148 |
bbox = min(A[0], B[0]), max(A[0], B[0]), min(A[1], B[1]), max(A[1], B[1]) |
|---|
| 149 |
if node.get("d"): |
|---|
| 150 |
d = node.get('d') |
|---|
| 151 |
p = cubicsuperpath.parsePath(d) |
|---|
| 152 |
applyTransformToPath(m,p) |
|---|
| 153 |
bbox=boxunion(roughBBox(p),bbox) |
|---|
| 154 |
|
|---|
| 155 |
if node.tag == inkex.addNS('use','svg') or node.tag=='use': |
|---|
| 156 |
refid=node.get(inkex.addNS('href','xlink')) |
|---|
| 157 |
path = '//*[@id="%s"]' % refid[1:] |
|---|
| 158 |
refnode = node.getroottree().xpath(path, namespaces=inkex.NSS) |
|---|
| 159 |
bbox=boxunion(computeBBox(refnode,m),bbox) |
|---|
| 160 |
|
|---|
| 161 |
bbox=boxunion(computeBBox(node,m),bbox) |
|---|
| 162 |
return bbox |
|---|