The SVG specs has a chapter on
styling. The SVG and Cascading Style Sheets (CSS) share many styling properties. There are two ways to style an
element in SVG. We can style an element using individual attributes or combining
them together as the value of style attribute. For example, we can create
a blue rectangle with red border like this.
<rect
fill="blue"
stroke="red"
stroke-width="2"
x="10" y="10" width="30" height="20" />
Or we can specify a single style attribute like this.
<rect
style="fill:blue; stroke:red; stroke-width:3"
x="50" y="50" width="30" height="20" />
SVG elements generated by Inkscape itself use the style attribute.
The style.py module in inkex directory defines several classes. The most notable
one is the Style class which derives from OrderedDict class. The __init__ method
of the class is written in a way that it accepts a dictionary, a string, key value
pairs, or another Style object as the initial value. The Python interpreter session
below shows how to initialize a Style object in different ways.
george@Inspiron-5515:~$ /usr/bin/python3
>>> import sys
>>> sys.path.append('/usr/share/inkscape/extensions')
>>> from inkex import Style
>>> s = Style({'fill':'red', 'stroke':'green'})
>>> s
Style([('fill', 'red'), ('stroke', 'green')])
>>> str(s)
'fill:red;stroke:green'
>>> st1 = Style('fill:red; stroke:green')
>>> str(st1)
'fill:red;stroke:green'
>>> st2 = Style(fill='red', stroke='green')
>>> str(st2)
'fill:red;stroke:green'
>>> st3 = Style(st2)
>>> str(st3)
'fill:red;stroke:green'
The static method parse_str parses a string and yields key value pair as a tuple
from which we can create a new Style object. The to_str method converts a Style object
to a string.
The update method is similar to Python dictionary update method. The Style class
also defines the __add__ and __sub__ methods so we can add or subtract
Style class objects. The operators + or - create new copies of
Style object.
>>> st4 = Style({'stroke-width':'3'})
>>> st5 = st3 + st4
>>> print(st5)
fill:red;stroke:green;stroke-width:3
>>> st6 = st5 - {'fill':'red'}
>>> print(st6)
stroke:green;stroke-width:3
The Style class also defines a get_color and a set_color method. We can use them
like the examples shown below.
>>> st6.get_color('stroke')
[0, 128, 0, 1.0]
>>> st6.set_color('red', 'fill')
>>> print(st6)
stroke:green;stroke-width:3;fill:#ff0000
When we are working on element style in an Inkscape extension, we change the element
style in Inkscape itself and watch the style value in XML editor. Once we find a value
to use, we can set the same style attribute and value in extension code.
As shown in previous chapters, we set style property of an element object with a
Style object.
element.style = st2 # st2 is a Style object
The colors.py module in inkex directory defines an SVG_COLOR dictionary with
148 color names and values. The is_color function determines if a value is
a color that we can use.
>>> from inkex.colors import SVG_COLOR
>>> len(SVG_COLOR) # include a none
149
>>> SVG_COLOR['none']
>>> from inkex.colors import is_color
>>> is_color('#334')
True
>>> is_color('#334srd') # wrong value above F
False
>>> is_color('#33AABB')
True
>>> is_color('red')
True
>>> is_color(345)
True
>>> is_color('#334ABD00') # this is in rgba format
True
We usually use the color name as a string value such as red or an RGB string value
such as #FF00CC when we specify a color in extension code.
The Inkscape has a whole class of extensions dealing with colors. They are listed
under the Extensions > Color menu. The Randomize and Negative are
interesting, and Grayscale and Replace color are sometimes useful.
Those extensions have
classes derived from ColorExtension class which is defined in the
extensions.py module.
Let’s take a look at the Grayscale extension. The content of the color_grayscale.py
module is listed below. It only overrides a modify_color method. The color
argument is the color of the element to be modified. The name argument is one of the
color attribute names stroke, fill, stop-color, flood-color or lighting-color
defined in the Style class. The return value is the new modified color.
#!/usr/bin/env python
"""Convert to grey"""
import inkex
class Grayscale(inkex.ColorExtension):
"""Make all colours grayscale"""
def modify_color(self, name, color):
# ITU-R Recommendation BT.709 (NTSC and PAL)
# l = 0.2125 * r + 0.7154 * g + 0.0721 * b
lum = 0.299 * color.red + 0.587 * color.green + 0.114 * color.blue
return inkex.Color((int(round(lum)),
int(round(lum)), int(round(lum))))
if __name__ == '__main__':
Grayscale().run()
12. Colors and Styles