1 #!/usr/bin/env python \r
2 '''\r
3 Copyright (C) 2006 Jos Hirth, kaioa.com\r
4 \r
5 This program is free software; you can redistribute it and/or modify\r
6 it under the terms of the GNU General Public License as published by\r
7 the Free Software Foundation; either version 2 of the License, or\r
8 (at your option) any later version.\r
9 \r
10 This program is distributed in the hope that it will be useful,\r
11 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
13 GNU General Public License for more details.\r
14 \r
15 You should have received a copy of the GNU General Public License\r
16 along with this program; if not, write to the Free Software\r
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
18 '''\r
19 import sys, copy, optparse, simplestyle, inkex\r
20 \r
21 import xml.xpath\r
22 \r
23 color_props_fill=('fill:','stop-color:','flood-color:','lighting-color:')\r
24 color_props_stroke=('stroke:',)\r
25 color_props = color_props_fill + color_props_stroke\r
26 \r
27 \r
28 class ColorEffect(inkex.Effect):\r
29 def __init__(self):\r
30 inkex.Effect.__init__(self,use_minidom=True)\r
31 self.visited = []\r
32 \r
33 def effect(self):\r
34 if len(self.selected)==0:\r
35 self.getAttribs(self.document)\r
36 else:\r
37 for id,node in self.selected.iteritems():\r
38 self.getAttribs(node)\r
39 \r
40 def getAttribs(self,node):\r
41 self.changeStyle(node)\r
42 if node.hasChildNodes():\r
43 childs=node.childNodes\r
44 for child in childs:\r
45 self.getAttribs(child)\r
46 \r
47 def changeStyle(self,node):\r
48 if node.hasAttributes():\r
49 style=node.getAttribute('style') # fixme: this will break for presentation attributes!\r
50 if style!='':\r
51 #inkex.debug('old style:'+style)\r
52 styles=style.split(';')\r
53 for i in range(len(styles)):\r
54 for c in range(len(color_props)):\r
55 if styles[i].startswith(color_props[c]):\r
56 styles[i]=color_props[c]+self.process_prop(styles[i][len(color_props[c]):])\r
57 #inkex.debug('new style:'+';'.join(styles))\r
58 node.setAttribute('style',';'.join(styles))\r
59 '''\r
60 def changeStyle(self,node):\r
61 if node.hasAttributes():\r
62 sa=node.getAttribute('style')\r
63 if sa!='':\r
64 debug(sa)\r
65 styles=simplestyle.parseStyle(sa)\r
66 for c in range(len(colortags)):\r
67 if colortags[c] in styles.keys():\r
68 styles[colortags[c]]=self.process_prop(styles[colortags[c]])\r
69 node.setAttribute('style',simplestyle.formatStyle(styles))\r
70 ''' \r
71 def process_prop(self,col):\r
72 #debug('got:'+col)\r
73 if simplestyle.isColor(col):\r
74 c=simplestyle.parseColor(col)\r
75 col='#'+self.colmod(c[0],c[1],c[2])\r
76 #debug('made:'+col)\r
77 if col.startswith('url(#'):\r
78 id = col[len('url(#'):col.find(')')]\r
79 #inkex.debug('ID:' + id )\r
80 path = '//*[@id="%s"]' % id\r
81 for node in xml.xpath.Evaluate(path,self.document):\r
82 self.process_gradient(node)\r
83 return col\r
84 \r
85 def process_gradient(self, node):\r
86 if node.hasAttributes(): \r
87 this_id=node.getAttribute('id')\r
88 if this_id in self.visited:\r
89 # prevent multiple processing of the same gradient if it is used by more than one selected object\r
90 #inkex.debug("already had: " + this_id)\r
91 return\r
92 self.visited.append(this_id)\r
93 #inkex.debug("visited: " + str(self.visited))\r
94 self.changeStyle(node)\r
95 if node.hasChildNodes():\r
96 for child in node.childNodes:\r
97 self.process_gradient(child)\r
98 if node.hasAttributes(): \r
99 href=node.getAttribute('xlink:href')\r
100 if href.startswith('#'):\r
101 id = href[len('#'):len(href)]\r
102 #inkex.debug('ID:' + id )\r
103 path = '//*[@id="%s"]' % id\r
104 for node in xml.xpath.Evaluate(path,self.document):\r
105 self.process_gradient(node)\r
106 \r
107 def colmod(self,r,g,b):\r
108 pass\r
109 \r
110 def rgb_to_hsl(self,r, g, b):\r
111 rgb_max = max (max (r, g), b)\r
112 rgb_min = min (min (r, g), b)\r
113 delta = rgb_max - rgb_min\r
114 hsl = [0.0, 0.0, 0.0]\r
115 hsl[2] = (rgb_max + rgb_min)/2.0\r
116 if delta == 0:\r
117 hsl[0] = 0.0\r
118 hsl[1] = 0.0\r
119 else:\r
120 if hsl[2] <= 0.5:\r
121 hsl[1] = delta / (rgb_max + rgb_min)\r
122 else:\r
123 hsl[1] = delta / (2 - rgb_max - rgb_min)\r
124 if r == rgb_max:\r
125 hsl[0] = (g - b) / delta\r
126 else:\r
127 if g == rgb_max:\r
128 hsl[0] = 2.0 + (b - r) / delta\r
129 else:\r
130 if b == rgb_max:\r
131 hsl[0] = 4.0 + (r - g) / delta\r
132 hsl[0] = hsl[0] / 6.0\r
133 if hsl[0] < 0:\r
134 hsl[0] = hsl[0] + 1\r
135 if hsl[0] > 1:\r
136 hsl[0] = hsl[0] - 1\r
137 return hsl\r
138 \r
139 def hue_2_rgb (self, v1, v2, h):\r
140 if h < 0:\r
141 h += 6.0\r
142 if h > 6:\r
143 h -= 6.0\r
144 if h < 1:\r
145 return v1 + (v2 - v1) * h\r
146 if h < 3:\r
147 return v2\r
148 if h < 4:\r
149 return v1 + (v2 - v1) * (4 - h)\r
150 return v1\r
151 \r
152 def hsl_to_rgb (self,h, s, l):\r
153 rgb = [0, 0, 0]\r
154 if s == 0:\r
155 rgb[0] = l\r
156 rgb[1] = l\r
157 rgb[2] = l\r
158 else:\r
159 if l < 0.5:\r
160 v2 = l * (1 + s)\r
161 else:\r
162 v2 = l + s - l*s\r
163 v1 = 2*l - v2\r
164 rgb[0] = self.hue_2_rgb (v1, v2, h*6 + 2.0)\r
165 rgb[1] = self.hue_2_rgb (v1, v2, h*6)\r
166 rgb[2] = self.hue_2_rgb (v1, v2, h*6 - 2.0)\r
167 return rgb\r