interp_att_g.py revision b6d0134d7b031d425c80e0fb696fb96173e00613
#!/usr/bin/env python
'''
Copyright (C) 2009 Aurelio A. Heckert, aurium (a) gmail dot com
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 inkex, simplestyle, math, re, string
class InterpAttG(inkex.Effect):
def __init__(self):
inkex.Effect.__init__(self)
self.OptionParser.add_option("-a", "--att",
action="store", type="string",
dest="att", default="fill",
help="Attribute to be interpolated.")
self.OptionParser.add_option("-o", "--att-other",
action="store", type="string",
dest="att_other",
help="Other attribute (for a limited UI).")
self.OptionParser.add_option("-t", "--att-other-type",
action="store", type="string",
dest="att_other_type",
help="The other attribute type.")
self.OptionParser.add_option("-w", "--att-other-where",
action="store", type="string",
dest="att_other_where",
help="That is a tag attribute or a style attribute?")
self.OptionParser.add_option("-s", "--start-val",
action="store", type="string",
dest="start_val", default="#F00",
help="Initial interpolation value.")
self.OptionParser.add_option("-e", "--end-val",
action="store", type="string",
dest="end_val", default="#00F",
help="End interpolation value.")
self.OptionParser.add_option("-u", "--unit",
action="store", type="string",
dest="unit", default="color",
help="Values unit.")
def getColorValues(self):
sv = string.replace( self.options.start_val, '#', '' )
ev = string.replace( self.options.end_val, '#', '' )
if re.search('\s|,', sv):
# There are separators. That must be a integer RGB color definition.
sv = re.split( '[\s,]+', sv )
ev = re.split( '[\s,]+', ev )
self.R_ini = int( sv[0] )
self.G_ini = int( sv[1] )
self.B_ini = int( sv[2] )
self.R_end = int( ev[0] )
self.G_end = int( ev[1] )
self.B_end = int( ev[2] )
else:
# There is no separator. That must be a Hex RGB color definition.
if len(sv) == 3:
self.R_ini = int( sv[0] + sv[0], 16 )
self.G_ini = int( sv[1] + sv[1], 16 )
self.B_ini = int( sv[2] + sv[2], 16 )
self.R_end = int( ev[0] + ev[0], 16 )
self.G_end = int( ev[1] + ev[1], 16 )
self.B_end = int( ev[2] + ev[2], 16 )
else: #the len must be 6
self.R_ini = int( sv[0] + sv[1], 16 )
self.G_ini = int( sv[2] + sv[3], 16 )
self.B_ini = int( sv[4] + sv[5], 16 )
self.R_end = int( ev[0] + ev[1], 16 )
self.G_end = int( ev[2] + ev[3], 16 )
self.B_end = int( ev[4] + ev[5], 16 )
self.R_inc = ( self.R_end - self.R_ini ) / float( self.tot_el - 1 )
self.G_inc = ( self.G_end - self.G_ini ) / float( self.tot_el - 1 )
self.B_inc = ( self.B_end - self.B_ini ) / float( self.tot_el - 1 )
self.R_cur = self.R_ini
self.G_cur = self.G_ini
self.B_cur = self.B_ini
def getNumberValues(self):
sv = self.options.start_val
ev = self.options.end_val
if self.inte_att_type and self.inte_att_type != 'none':
sv = inkex.unittouu( sv + self.inte_att_type )
ev = inkex.unittouu( ev + self.inte_att_type )
self.val_cur = self.val_ini = sv
self.val_end = ev
self.val_inc = ( ev - sv ) / float( self.tot_el - 1 )
def getTotElements(self):
self.tot_el = 0
self.collection = None
if len( self.selected ) == 0:
return False
if len( self.selected ) > 1:
# multiple selection
self.collection = self.options.ids
for i in self.options.ids:
path = '//*[@id="%s"]' % i
self.collection[self.tot_el] = self.document.xpath(path, namespaces=inkex.NSS)[0]
self.tot_el += 1
else:
# must be a group
self.collection = self.selected[ self.options.ids[0] ]
for i in self.collection:
self.tot_el += 1
def effect(self):
if self.options.att == 'other':
self.inte_att = self.options.att_other
self.inte_att_type = self.options.att_other_type
self.where = self.options.att_other_where
else:
self.inte_att = self.options.att
if self.inte_att == 'width':
self.inte_att_type = 'float'
self.where = 'tag'
elif self.inte_att == 'height':
self.inte_att_type = 'float'
self.where = 'tag'
elif self.inte_att == 'scale':
self.inte_att_type = 'float'
self.where = 'transform'
elif self.inte_att == 'trans-x':
self.inte_att_type = 'float'
self.where = 'transform'
elif self.inte_att == 'trans-y':
self.inte_att_type = 'float'
self.where = 'transform'
elif self.inte_att == 'fill':
self.inte_att_type = 'color'
self.where = 'style'
elif self.inte_att == 'opacity':
self.inte_att_type = 'float'
self.where = 'style'
self.getTotElements()
if self.inte_att_type == 'color':
self.getColorValues()
else:
self.getNumberValues()
if self.collection is None:
inkex.errormsg( 'There is no selection to interpolate' )
return False
for node in self.collection:
if self.inte_att_type == 'color':
val = 'rgb('+ \
str(int(round(self.R_cur))) +','+ \
str(int(round(self.G_cur))) +','+ \
str(int(round(self.B_cur))) +')'
else:
if self.inte_att_type == 'float':
val = self.val_cur
else: # inte_att_type == 'int'
val = round(self.val_cur)
if self.where == 'style':
s = node.get('style')
re_find = '(^|;)'+ self.inte_att +':[^;]*(;|$)'
if re.search( re_find, s ):
s = re.sub( re_find, '\\1'+ self.inte_att +':'+ str(val) +'\\2', s )
else:
s += ';'+ self.inte_att +':'+ str(val)
node.set( 'style', s )
elif self.where == 'transform':
t = node.get('transform')
if t == None: t = ""
if self.inte_att == 'trans-x':
val = "translate("+ str(val) +",0)"
elif self.inte_att == 'trans-y':
val = "translate(0,"+ str(val) +")"
else:
val = self.inte_att + "("+ str(val) +")"
node.set( 'transform', t +" "+ val )
else: # self.where == 'tag':
node.set( self.inte_att, str(val) )
if self.inte_att_type == 'color':
self.R_cur += self.R_inc
self.G_cur += self.G_inc
self.B_cur += self.B_inc
else:
self.val_cur += self.val_inc
return True
if __name__ == '__main__': #pragma: no cover
e = InterpAttG()
if e.affect():
exit(0)
else:
exit(1)