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