Code

Cleaning Stone wall and Silk carpet, improving Pixel smear, correcting typing errors
[inkscape.git] / share / extensions / coloreffect.py
index 52eff5c0db5871ff42f97730aa0ac134082b6939..8f67c6090dee855d5144afe6b444be5659661f84 100644 (file)
-#!/usr/bin/env python \r
-'''\r
-Copyright (C) 2006 Jos Hirth, kaioa.com\r
-Copyright (C) 2007 Aaron C. Spike\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
-'''\r
-import sys, copy, optparse, simplestyle, inkex, copy\r
-\r
-import random\r
-\r
-color_props_fill=('fill:','stop-color:','flood-color:','lighting-color:')\r
-color_props_stroke=('stroke:',)\r
-color_props = color_props_fill + color_props_stroke\r
-\r
-\r
-class ColorEffect(inkex.Effect):\r
-  def __init__(self):\r
-    inkex.Effect.__init__(self)\r
-    self.visited = []\r
-\r
-  def effect(self):\r
-    if len(self.selected)==0:\r
-      self.getAttribs(self.document.getroot())\r
-    else:\r
-      for id,node in self.selected.iteritems():\r
-        self.getAttribs(node)\r
-\r
-  def getAttribs(self,node):\r
-    self.changeStyle(node)\r
-    for child in node:\r
-      self.getAttribs(child)\r
-  \r
-  def changeStyle(self,node):\r
-    if node.attrib.has_key('style'):\r
-      style=node.get('style') # fixme: this will break for presentation attributes!\r
-      if style!='':\r
-        #inkex.debug('old style:'+style)\r
-        styles=style.split(';')\r
-        for i in range(len(styles)):\r
-          for c in range(len(color_props)):\r
-            if styles[i].startswith(color_props[c]):\r
-              styles[i]=color_props[c]+self.process_prop(styles[i][len(color_props[c]):])\r
-        #inkex.debug('new style:'+';'.join(styles))\r
-        node.set('style',';'.join(styles))\r
-\r
-  def process_prop(self,col):\r
-    #debug('got:'+col)\r
-    if simplestyle.isColor(col):\r
-      c=simplestyle.parseColor(col)\r
-      col='#'+self.colmod(c[0],c[1],c[2])\r
-      #debug('made:'+col)\r
-    if col.startswith('url(#'):\r
-      id = col[len('url(#'):col.find(')')]\r
-      newid = '%s-%d' % (id, int(random.random() * 1000))\r
-      #inkex.debug('ID:' + id )\r
-      path = '//*[@id="%s"]' % id\r
-      for node in self.document.xpath(path, inkex.NSS):\r
-        self.process_gradient(node, newid)\r
-      col = 'url(#%s)' % newid\r
-    return col\r
-\r
-  def process_gradient(self, node, newid):\r
-    #if node.hasAttributes():                          \r
-       #this_id=node.getAttribute('id')\r
-       #if this_id in self.visited:\r
-         ## prevent multiple processing of the same gradient if it is used by more than one selected object\r
-         ##inkex.debug("already had: " + this_id)\r
-         #return\r
-       #self.visited.append(this_id)\r
-       #inkex.debug("visited: " + str(self.visited))\r
-    newnode = copy.deepcopy(node)\r
-    newnode.set('id', newid)\r
-    node.getparent().append(newnode)\r
-    self.changeStyle(newnode)\r
-    for child in newnode:\r
-      self.changeStyle(child)\r
-    xlink = inkex.addNS('href','xlink')\r
-    if newnode.attrib.has_key(xlink):\r
-      href=newnode.get(xlink)\r
-      if href.startswith('#'):\r
-        id = href[len('#'):len(href)]\r
-        #inkex.debug('ID:' + id )\r
-        newhref = '%s-%d' % (id, int(random.random() * 1000))\r
-        newnode.set(xlink, '#%s' % newhref)\r
-        path = '//*[@id="%s"]' % id\r
-        for node in self.document.xpath(path,inkex.NSS):\r
-          self.process_gradient(node, newhref)\r
\r
-  def colmod(self,r,g,b):\r
-    pass\r
-\r
-  def rgb_to_hsl(self,r, g, b):\r
-    rgb_max = max (max (r, g), b)\r
-    rgb_min = min (min (r, g), b)\r
-    delta = rgb_max - rgb_min\r
-    hsl = [0.0, 0.0, 0.0]\r
-    hsl[2] = (rgb_max + rgb_min)/2.0\r
-    if delta == 0:\r
-        hsl[0] = 0.0\r
-        hsl[1] = 0.0\r
-    else:\r
-        if hsl[2] <= 0.5:\r
-            hsl[1] = delta / (rgb_max + rgb_min)\r
-        else:\r
-            hsl[1] = delta / (2 - rgb_max - rgb_min)\r
-        if r == rgb_max:\r
-            hsl[0] = (g - b) / delta\r
-        else:\r
-            if g == rgb_max:\r
-                hsl[0] = 2.0 + (b - r) / delta\r
-            else:\r
-                if b == rgb_max:\r
-                    hsl[0] = 4.0 + (r - g) / delta\r
-        hsl[0] = hsl[0] / 6.0\r
-        if hsl[0] < 0:\r
-            hsl[0] = hsl[0] + 1\r
-        if hsl[0] > 1:\r
-            hsl[0] = hsl[0] - 1\r
-    return hsl\r
-\r
-  def hue_2_rgb (self, v1, v2, h):\r
-    if h < 0:\r
-        h += 6.0\r
-    if h > 6:\r
-        h -= 6.0\r
-    if h < 1:\r
-        return v1 + (v2 - v1) * h\r
-    if h < 3:\r
-        return v2\r
-    if h < 4:\r
-        return v1 + (v2 - v1) * (4 - h)\r
-    return v1\r
-\r
-  def hsl_to_rgb (self,h, s, l):\r
-    rgb = [0, 0, 0]\r
-    if s == 0:\r
-        rgb[0] = l\r
-        rgb[1] = l\r
-        rgb[2] = l\r
-    else:\r
-        if l < 0.5:\r
-            v2 = l * (1 + s)\r
-        else:\r
-            v2 = l + s - l*s\r
-        v1 = 2*l - v2\r
-        rgb[0] = self.hue_2_rgb (v1, v2, h*6 + 2.0)\r
-        rgb[1] = self.hue_2_rgb (v1, v2, h*6)\r
-        rgb[2] = self.hue_2_rgb (v1, v2, h*6 - 2.0)\r
-    return rgb\r
+#!/usr/bin/env python 
+'''
+Copyright (C) 2006 Jos Hirth, kaioa.com
+Copyright (C) 2007 Aaron C. Spike
+Copyright (C) 2009 Monash University
+
+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
+'''
+import sys, copy, simplestyle, inkex
+import random
+
+color_props_fill = ('fill', 'stop-color', 'flood-color', 'lighting-color')
+color_props_stroke = ('stroke',)
+color_props = color_props_fill + color_props_stroke
+
+
+class ColorEffect(inkex.Effect):
+  def __init__(self):
+    inkex.Effect.__init__(self)
+    self.visited = []
+
+  def effect(self):
+    if len(self.selected)==0:
+      self.getAttribs(self.document.getroot())
+    else:
+      for id,node in self.selected.iteritems():
+        self.getAttribs(node)
+
+  def getAttribs(self,node):
+    self.changeStyle(node)
+    for child in node:
+      self.getAttribs(child)
+
+  def changeStyle(self,node):
+    for attr in color_props:
+        val = node.get(attr)
+        if val:
+            new_val = self.process_prop(val)
+            if new_val != val:
+                node.set(attr, new_val)
+
+    if node.attrib.has_key('style'):
+        # References for style attribute:
+        # http://www.w3.org/TR/SVG11/styling.html#StyleAttribute,
+        # http://www.w3.org/TR/CSS21/syndata.html
+        #
+        # The SVG spec is ambiguous as to how style attributes should be parsed.
+        # For example, it isn't clear whether semicolons are allowed to appear
+        # within strings or comments, or indeed whether comments are allowed to
+        # appear at all.
+        #
+        # The processing here is just something simple that should usually work,
+        # without trying too hard to get everything right.
+        # (Won't work for the pathalogical case that someone escapes a property
+        # name, probably does the wrong thing if colon or semicolon is used inside
+        # a comment or string value.)
+        style = node.get('style') # fixme: this will break for presentation attributes!
+        if style:
+            #inkex.debug('old style:'+style)
+            declarations = style.split(';')
+            for i,decl in enumerate(declarations):
+                parts = decl.split(':', 2)
+                if len(parts) == 2:
+                    (prop, val) = parts
+                    prop = prop.strip().lower()
+                    if prop in color_props:
+                        val = val.strip()
+                        new_val = self.process_prop(val)
+                        if new_val != val:
+                            declarations[i] = prop + ':' + new_val
+            #inkex.debug('new style:'+';'.join(declarations))
+            node.set('style', ';'.join(declarations))
+
+  def process_prop(self,col):
+    #debug('got:'+col)
+    if simplestyle.isColor(col):
+      c=simplestyle.parseColor(col)
+      col='#'+self.colmod(c[0],c[1],c[2])
+      #debug('made:'+col)
+    if col.startswith('url(#'):
+      id = col[len('url(#'):col.find(')')]
+      newid = '%s-%d' % (id, int(random.random() * 1000))
+      #inkex.debug('ID:' + id )
+      path = '//*[@id="%s"]' % id
+      for node in self.document.xpath(path, namespaces=inkex.NSS):
+        self.process_gradient(node, newid)
+      col = 'url(#%s)' % newid
+    return col
+
+  def process_gradient(self, node, newid):
+    #if node.hasAttributes():
+       #this_id=node.getAttribute('id')
+       #if this_id in self.visited:
+         ## prevent multiple processing of the same gradient if it is used by more than one selected object
+         ##inkex.debug("already had: " + this_id)
+         #return
+       #self.visited.append(this_id)
+       #inkex.debug("visited: " + str(self.visited))
+    newnode = copy.deepcopy(node)
+    newnode.set('id', newid)
+    node.getparent().append(newnode)
+    self.changeStyle(newnode)
+    for child in newnode:
+      self.changeStyle(child)
+    xlink = inkex.addNS('href','xlink')
+    if newnode.attrib.has_key(xlink):
+      href=newnode.get(xlink)
+      if href.startswith('#'):
+        id = href[len('#'):len(href)]
+        #inkex.debug('ID:' + id )
+        newhref = '%s-%d' % (id, int(random.random() * 1000))
+        newnode.set(xlink, '#%s' % newhref)
+        path = '//*[@id="%s"]' % id
+        for node in self.document.xpath(path, namespaces=inkex.NSS):
+          self.process_gradient(node, newhref)
+  def colmod(self,r,g,b):
+    pass
+
+  def rgb_to_hsl(self,r, g, b):
+    rgb_max = max (max (r, g), b)
+    rgb_min = min (min (r, g), b)
+    delta = rgb_max - rgb_min
+    hsl = [0.0, 0.0, 0.0]
+    hsl[2] = (rgb_max + rgb_min)/2.0
+    if delta == 0:
+        hsl[0] = 0.0
+        hsl[1] = 0.0
+    else:
+        if hsl[2] <= 0.5:
+            hsl[1] = delta / (rgb_max + rgb_min)
+        else:
+            hsl[1] = delta / (2 - rgb_max - rgb_min)
+        if r == rgb_max:
+            hsl[0] = (g - b) / delta
+        else:
+            if g == rgb_max:
+                hsl[0] = 2.0 + (b - r) / delta
+            else:
+                if b == rgb_max:
+                    hsl[0] = 4.0 + (r - g) / delta
+        hsl[0] = hsl[0] / 6.0
+        if hsl[0] < 0:
+            hsl[0] = hsl[0] + 1
+        if hsl[0] > 1:
+            hsl[0] = hsl[0] - 1
+    return hsl
+
+  def hue_2_rgb (self, v1, v2, h):
+    if h < 0:
+        h += 6.0
+    if h > 6:
+        h -= 6.0
+    if h < 1:
+        return v1 + (v2 - v1) * h
+    if h < 3:
+        return v2
+    if h < 4:
+        return v1 + (v2 - v1) * (4 - h)
+    return v1
+
+  def hsl_to_rgb (self,h, s, l):
+    rgb = [0, 0, 0]
+    if s == 0:
+        rgb[0] = l
+        rgb[1] = l
+        rgb[2] = l
+    else:
+        if l < 0.5:
+            v2 = l * (1 + s)
+        else:
+            v2 = l + s - l*s
+        v1 = 2*l - v2
+        rgb[0] = self.hue_2_rgb (v1, v2, h*6 + 2.0)
+        rgb[1] = self.hue_2_rgb (v1, v2, h*6)
+        rgb[2] = self.hue_2_rgb (v1, v2, h*6 - 2.0)
+    return rgb
+
+# vi: set autoindent shiftwidth=2 tabstop=8 expandtab softtabstop=2 :