home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / Inkscape / Inkscape-0.48.2-1-win32.exe / share / extensions / edge3d.py < prev    next >
Text File  |  2011-07-08  |  7KB  |  150 lines

  1. #!/usr/bin/env python 
  2. '''
  3. Copyright (C) 2007 Terry Brown, terry_n_brown@yahoo.com
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. '''
  19. import inkex, simplepath, sys, copy
  20. from math import degrees, atan2
  21.  
  22. class Edge3d(inkex.Effect):
  23.     def __init__(self):
  24.         inkex.Effect.__init__(self)
  25.         opts = [('-a', '--angle', 'float', 'angle', 45.0,
  26.                  'angle of illumination, clockwise, 45 = upper right'),
  27.                 ('-d', '--stddev', 'float', 'stddev', 5.0,
  28.                  'stdDeviation for Gaussian Blur'),
  29.                 ('-H', '--blurheight', 'float', 'blurheight', 2.0,
  30.                  'height for Gaussian Blur'),
  31.                 ('-W', '--blurwidth', 'float', 'blurwidth', 2.0,
  32.                  'width for Gaussian Blur'),
  33.                 ('-s', '--shades', 'int', 'shades', 2,
  34.                  'shades, 2 = black and white, 3 = black, grey, white, etc.'),
  35.                 ('-b', '--bw', 'inkbool', 'bw', False,
  36.                  'black and white, create only the fully black and white wedges'),
  37.                 ('-p', '--thick', 'float', 'thick', 10.,
  38.                  'stroke-width for path pieces'),
  39.                 ]
  40.         for o in opts:
  41.             self.OptionParser.add_option(o[0], o[1], action="store", type=o[2],
  42.                                          dest=o[3], default=o[4], help=o[5])
  43.         self.filtId = ''
  44.  
  45.     def angleBetween(self, start, end, angle):
  46.         """Return true if angle (degrees, clockwise, 0 = up/north) is between
  47.            angles start and end"""
  48.         def f(x):
  49.             """Maybe add 360 to x"""
  50.             if x < 0: return x + 360.
  51.             return x
  52.         # rotate all inputs by start, => start = 0
  53.         a = f(f(angle) - f(start))
  54.         e = f(f(end) - f(start))
  55.         return a < e
  56.  
  57.     def effectX(self):
  58.         # size of a wedge for shade i, wedges come in pairs
  59.         delta = 360. / self.options.shades / 2.
  60.  
  61.         for shade in range(0, self.options.shades):
  62.             if self.options.bw and shade > 0 and shade < self.options.shades-1:
  63.                 continue
  64.             self.start = [self.options.angle - delta * (shade+1)]
  65.             self.end = [self.options.angle - delta * (shade)]
  66.             self.start.append( self.options.angle + delta * (shade) )
  67.             self.end.append( self.options.angle + delta * (shade+1) )
  68.             self.makeShade(float(shade)/float(self.options.shades-1))
  69.  
  70.     def effect(self):
  71.         """Check each internode to see if it's in one of the wedges
  72.            for the current shade.  shade is a floating point 0-1 white-black"""
  73.         # size of a wedge for shade i, wedges come in pairs
  74.         delta = 360. / self.options.shades / 2.
  75.         for id, node in self.selected.iteritems():
  76.             if node.tag == inkex.addNS('path','svg'):
  77.                 d = node.get('d')
  78.                 p = simplepath.parsePath(d)
  79.                 g = None
  80.                 for shade in range(0, self.options.shades):
  81.                     if (self.options.bw and shade > 0 and
  82.                         shade < self.options.shades - 1):
  83.                         continue
  84.                     self.start = [self.options.angle - delta * (shade+1)]
  85.                     self.end = [self.options.angle - delta * (shade)]
  86.                     self.start.append( self.options.angle + delta * (shade) )
  87.                     self.end.append( self.options.angle + delta * (shade+1) )
  88.                     level=float(shade)/float(self.options.shades-1)
  89.                     last = []
  90.                     result = []
  91.                     for cmd,params in p:
  92.                         if cmd == 'Z':
  93.                             last = []
  94.                             continue
  95.                         if last:
  96.                             a = degrees(atan2(params[-2:][0] - last[0],
  97.                                               params[-2:][1] - last[1]))
  98.                             if (self.angleBetween(self.start[0], self.end[0], a) or
  99.                                 self.angleBetween(self.start[1], self.end[1], a)):
  100.                                 result.append(('M', last))
  101.                                 result.append((cmd, params))
  102.                         last = params[-2:]
  103.                     if result:
  104.                         if g is None:
  105.                             g = self.getGroup(node)
  106.                         nn = copy.deepcopy(node)
  107.                         nn.set('d',simplepath.formatPath(result))
  108.                         
  109.                         col = 255 - int(255. * level)
  110.                         a = 'fill:none;stroke:#%02x%02x%02x;stroke-opacity:1;stroke-width:10;%s' % ((col,)*3 + (self.filtId,))
  111.                         nn.set('style',a)
  112.                         g.append(nn)
  113.         
  114.     def getGroup(self, node):
  115.         defs = self.document.getroot().xpath('//svg:defs', namespaces=inkex.NSS)
  116.         if defs:
  117.             defs = defs[0]
  118.             # make a clipped group, clip with clone of original, clipped group
  119.             # include original and group of paths
  120.             clip = inkex.etree.SubElement(defs,inkex.addNS('clipPath','svg'))
  121.             clip.append(copy.deepcopy(node))
  122.             clipId = self.uniqueId('clipPath')
  123.             clip.set('id', clipId)
  124.             clipG = inkex.etree.SubElement(node.getparent(),inkex.addNS('g','svg'))
  125.             g = inkex.etree.SubElement(clipG,inkex.addNS('g','svg'))
  126.             clipG.set('clip-path', 'url(#'+clipId+')')
  127.             # make a blur filter reference by the style of each path
  128.             filt = inkex.etree.SubElement(defs,inkex.addNS('filter','svg'))
  129.             filtId = self.uniqueId('filter')
  130.             self.filtId = 'filter:url(#%s);' % filtId
  131.             for k, v in [('id', filtId), ('height', str(self.options.blurheight)),
  132.                          ('width', str(self.options.blurwidth)),
  133.                          ('x', '-0.5'), ('y', '-0.5')]:
  134.                 filt.set(k, v)
  135.             fe = inkex.etree.SubElement(filt,inkex.addNS('feGaussianBlur','svg'))
  136.             fe.set('stdDeviation', str(self.options.stddev))
  137.         else:
  138.             # can't find defs, just group paths
  139.             g = inkex.etree.SubElement(node.getparent(),inkex.addNS('g','svg'))
  140.             g.append(node)
  141.  
  142.         return g
  143.  
  144. if __name__ == '__main__':
  145.     e = Edge3d()
  146.     e.affect()
  147.  
  148.  
  149. # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99
  150.