1
2from .elements import DrawingElement, DrawingParentElement
3
4
5class DrawingDef(DrawingParentElement):
6 ''' Parent class of SVG nodes that must be direct children of <defs> '''
7 def getSvgDefs(self):
8 return (self,)
9
10class DrawingDefSub(DrawingParentElement):
11 ''' Parent class of SVG nodes that are meant to be descendants of a Def '''
12 pass
13
14class LinearGradient(DrawingDef):
15 ''' A linear gradient to use as a fill or other color
16
17 Has <stop> nodes as children. '''
18 TAG_NAME = 'linearGradient'
19 def __init__(self, x1, y1, x2, y2, gradientUnits='userSpaceOnUse', **kwargs):
20 yShift = 0
21 if gradientUnits != 'userSpaceOnUse':
22 yShift = 1
23 try: y1 = yShift - y1
24 except TypeError: pass
25 try: y2 = yShift - y2
26 except TypeError: pass
27 super().__init__(x1=x1, y1=y1, x2=x2, y2=y2, gradientUnits=gradientUnits,
28 **kwargs)
29 def addStop(self, offset, color, opacity=None, **kwargs):
30 stop = GradientStop(offset=offset, stop_color=color,
31 stop_opacity=opacity, **kwargs)
32 self.append(stop)
33
34class RadialGradient(DrawingDef):
35 ''' A radial gradient to use as a fill or other color
36
37 Has <stop> nodes as children. '''
38 TAG_NAME = 'radialGradient'
39 def __init__(self, cx, cy, r, gradientUnits='userSpaceOnUse', fy=None, **kwargs):
40 yShift = 0
41 if gradientUnits != 'userSpaceOnUse':
42 yShift = 1
43 try: cy = yShift - cy
44 except TypeError: pass
45 try: fy = yShift - fy
46 except TypeError: pass
47 super().__init__(cx=cx, cy=cy, r=r, gradientUnits=gradientUnits,
48 fy=fy, **kwargs)
49 def addStop(self, offset, color, opacity=None, **kwargs):
50 stop = GradientStop(offset=offset, stop_color=color,
51 stop_opacity=opacity, **kwargs)
52 self.append(stop)
53
54class GradientStop(DrawingDefSub):
55 ''' A control point for a radial or linear gradient '''
56 TAG_NAME = 'stop'
57 hasContent = False
58
59class ClipPath(DrawingDef):
60 ''' A shape used to crop another element by not drawing outside of this
61 shape
62
63 Has regular drawing elements as children. '''
64 TAG_NAME = 'clipPath'
65
66class Mask(DrawingDef):
67 ''' A drawing where the gray value and transparency are used to control the
68 transparency of another shape.
69
70 Has regular drawing elements as children. '''
71 TAG_NAME = 'mask'
72
73class Filter(DrawingDef):
74 ''' A filter to apply to geometry
75
76 For example a blur filter. '''
77 TAG_NAME = 'filter'
78
79class FilterItem(DrawingDefSub):
80 ''' A child of Filter with any tag name'''
81 hasContent = False
82 def __init__(self, tag_name, **args):
83 super().__init__(**args)
84 self.TAG_NAME = tag_name
85
86class Marker(DrawingDef):
87 ''' A small drawing that can be placed at the ends of (or along) a path.
88
89 This can be used for arrow heads or points on a graph for example.
90
91 By default, units are multiples of stroke width.'''
92 TAG_NAME = 'marker'
93 def __init__(self, minx, miny, maxx, maxy, scale=1, orient='auto',
94 **kwargs):
95 width = maxx - minx
96 height = maxy - miny
97 kwargs = {
98 'markerWidth': width if scale == 1 else float(width) * scale,
99 'markerHeight': height if scale == 1 else float(height) * scale,
100 'viewBox': '{} {} {} {}'.format(minx, -maxy, width, height),
101 'orient': orient,
102 **kwargs,
103 }
104 super().__init__(**kwargs)