1 # -*- encoding: utf-8 -*-
4 # Copyright (C) 2002-2012 Jörg Lehmann <joergl@users.sourceforge.net>
5 # Copyright (C) 2003-2006 Michael Schindler <m-schindler@users.sourceforge.net>
6 # Copyright (C) 2002-2012 André Wobst <wobsta@users.sourceforge.net>
8 # This file is part of PyX (http://pyx.sourceforge.net/).
10 # PyX is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
15 # PyX is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with PyX; if not, write to the Free Software
22 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 from . import attr
, unit
28 # base classes for stroke and fill styles
34 class strokestyle(style
):
37 class fillstyle(style
):
41 # common stroke styles
45 class linecap(attr
.exclusiveattr
, strokestyle
):
47 """linecap of paths"""
49 def __init__(self
, value
=0):
50 attr
.exclusiveattr
.__init
__(self
, linecap
)
53 def processPS(self
, file, writer
, context
, registry
):
54 file.write("%d setlinecap\n" % self
.value
)
56 def processPDF(self
, file, writer
, context
, registry
):
57 file.write("%d J\n" % self
.value
)
59 def processSVGattrs(self
, attrs
, writer
, context
, registry
):
60 attrs
["stroke-linecap"] = {0: "butt", 1: "round", 2: "square"}[self
.value
]
63 linecap
.butt
= linecap(0)
64 linecap
.round = linecap(1)
65 linecap
.square
= linecap(2)
66 linecap
.clear
= attr
.clearclass(linecap
)
69 class linejoin(attr
.exclusiveattr
, strokestyle
):
71 """linejoin of paths"""
73 def __init__(self
, value
=0):
74 attr
.exclusiveattr
.__init
__(self
, linejoin
)
77 def processPS(self
, file, writer
, context
, registry
):
78 file.write("%d setlinejoin\n" % self
.value
)
80 def processPDF(self
, file, writer
, context
, registry
):
81 file.write("%d j\n" % self
.value
)
83 def processSVGattrs(self
, attrs
, writer
, context
, registry
):
84 attrs
["stroke-linejoin"] = {0: "miter", 1: "round", 2: "bevel"}[self
.value
]
86 linejoin
.miter
= linejoin(0)
87 linejoin
.round = linejoin(1)
88 linejoin
.bevel
= linejoin(2)
89 linejoin
.clear
= attr
.clearclass(linejoin
)
92 class miterlimit(attr
.exclusiveattr
, strokestyle
):
94 """miterlimit of paths"""
96 def __init__(self
, value
=10.0):
97 attr
.exclusiveattr
.__init
__(self
, miterlimit
)
100 def processPS(self
, file, writer
, context
, registry
):
101 file.write("%f setmiterlimit\n" % self
.value
)
103 def processPDF(self
, file, writer
, context
, registry
):
104 file.write("%f M\n" % self
.value
)
106 def processSVGattrs(self
, attrs
, writer
, context
, registry
):
107 attrs
["stroke-miterlimit"] = "%f" % self
.value
109 miterlimit
.lessthan180deg
= miterlimit(1/math
.sin(math
.pi
*180/360))
110 miterlimit
.lessthan90deg
= miterlimit(1/math
.sin(math
.pi
*90/360))
111 miterlimit
.lessthan60deg
= miterlimit(1/math
.sin(math
.pi
*60/360))
112 miterlimit
.lessthan45deg
= miterlimit(1/math
.sin(math
.pi
*45/360))
113 miterlimit
.lessthan11deg
= miterlimit(10) # the default, approximately 11.4783 degress
114 miterlimit
.clear
= attr
.clearclass(miterlimit
)
117 _defaultlinewidth
= 0.02 * unit
.w_cm
118 _defaultlinewidth_pt
= unit
.topt(_defaultlinewidth
)
120 class dash(attr
.exclusiveattr
, strokestyle
):
124 def __init__(self
, pattern
=[], offset
=0, rellengths
=1):
125 """set pattern with offset.
127 If rellengths is True, interpret all dash lengths relative to current linewidth.
129 attr
.exclusiveattr
.__init
__(self
, dash
)
130 self
.pattern
= pattern
132 self
.rellengths
= rellengths
134 def processPS(self
, file, writer
, context
, registry
):
136 patternstring
= " ".join(["%f" % (element
* context
.linewidth_pt
/_defaultlinewidth_pt
) for element
in self
.pattern
])
138 patternstring
= " ".join(["%f" % element
for element
in self
.pattern
])
139 file.write("[%s] %f setdash\n" % (patternstring
, self
.offset
))
141 def processPDF(self
, file, writer
, context
, registry
):
143 patternstring
= " ".join(["%f" % (element
* context
.linewidth_pt
/_defaultlinewidth_pt
) for element
in self
.pattern
])
145 patternstring
= " ".join(["%f" % element
for element
in self
.pattern
])
146 file.write("[%s] %f d\n" % (patternstring
, self
.offset
))
148 def processSVGattrs(self
, attrs
, writer
, context
, registry
):
150 patternstring
= " ".join(["%f" % (element
* context
.linewidth_pt
/_defaultlinewidth_pt
) for element
in self
.pattern
])
152 patternstring
= " ".join(["%f" % element
for element
in self
.pattern
])
154 attrs
["stroke-dasharray"] = patternstring
155 attrs
["stroke-dashoffset"] = "%f" % self
.offset
157 attrs
["stroke-dasharray"] = "none"
159 dash
.clear
= attr
.clearclass(dash
)
162 class linestyle(attr
.exclusiveattr
, strokestyle
):
164 """linestyle (linecap together with dash) of paths"""
166 def __init__(self
, c
=linecap
.butt
, d
=dash([])):
167 # XXX better, but at the moment not supported by attr.exlusiveattr would be:
168 # XXX attr.exclusiveattr.__init__(self, [linestyle, linecap, dash])
169 attr
.exclusiveattr
.__init
__(self
, linestyle
)
173 def processPS(self
, file, writer
, context
, registry
):
174 self
.c
.processPS(file, writer
, context
, registry
)
175 self
.d
.processPS(file, writer
, context
, registry
)
177 def processPDF(self
, file, writer
, context
, registry
):
178 self
.c
.processPDF(file, writer
, context
, registry
)
179 self
.d
.processPDF(file, writer
, context
, registry
)
181 def processSVGattrs(self
, attrs
, writer
, context
, registry
):
182 self
.c
.processSVGattrs(attrs
, writer
, context
, registry
)
183 self
.d
.processSVGattrs(attrs
, writer
, context
, registry
)
185 linestyle
.solid
= linestyle(linecap
.butt
, dash([]))
186 linestyle
.dashed
= linestyle(linecap
.butt
, dash([2]))
187 linestyle
.dotted
= linestyle(linecap
.round, dash([0, 2]))
188 linestyle
.dashdotted
= linestyle(linecap
.round, dash([0, 2, 2, 2]))
189 linestyle
.clear
= attr
.clearclass(linestyle
)
192 class linewidth(attr
.sortbeforeexclusiveattr
, strokestyle
):
194 """linewidth of paths"""
196 def __init__(self
, width
):
197 attr
.sortbeforeexclusiveattr
.__init
__(self
, linewidth
, [dash
, linestyle
])
200 def processPS(self
, file, writer
, context
, registry
):
201 context
.linewidth_pt
= unit
.topt(self
.width
)
202 file.write("%f setlinewidth\n" % context
.linewidth_pt
)
204 def processPDF(self
, file, writer
, context
, registry
):
205 context
.linewidth_pt
= unit
.topt(self
.width
)
206 file.write("%f w\n" % context
.linewidth_pt
)
208 def processSVGattrs(self
, attrs
, writer
, context
, registry
):
209 context
.linewidth_pt
= unit
.topt(self
.width
)
210 attrs
["stroke-width"] = "%f" % context
.linewidth_pt
212 linewidth
.THIN
= linewidth(_defaultlinewidth
/math
.sqrt(32))
213 linewidth
.THIn
= linewidth(_defaultlinewidth
/math
.sqrt(16))
214 linewidth
.THin
= linewidth(_defaultlinewidth
/math
.sqrt(8))
215 linewidth
.Thin
= linewidth(_defaultlinewidth
/math
.sqrt(4))
216 linewidth
.thin
= linewidth(_defaultlinewidth
/math
.sqrt(2))
217 linewidth
.normal
= linewidth(_defaultlinewidth
)
218 linewidth
.thick
= linewidth(_defaultlinewidth
*math
.sqrt(2))
219 linewidth
.Thick
= linewidth(_defaultlinewidth
*math
.sqrt(4))
220 linewidth
.THick
= linewidth(_defaultlinewidth
*math
.sqrt(8))
221 linewidth
.THIck
= linewidth(_defaultlinewidth
*math
.sqrt(16))
222 linewidth
.THICk
= linewidth(_defaultlinewidth
*math
.sqrt(32))
223 linewidth
.THICK
= linewidth(_defaultlinewidth
*math
.sqrt(64))
224 linewidth
.clear
= attr
.clearclass(linewidth
)
227 class fillrule(attr
.exclusiveattr
, fillstyle
):
229 """defines the fill rule to be used"""
231 def __init__(self
, even_odd
):
232 attr
.exclusiveattr
.__init
__(self
, fillrule
)
233 self
.even_odd
= even_odd
235 def processPS(self
, file, writer
, context
, registry
):
236 context
.fillrule
= self
.even_odd
238 def processPDF(self
, file, writer
, context
, registry
):
239 context
.fillrule
= self
.even_odd
241 def processSVGattrs(self
, attrs
, writer
, context
, registry
):
242 attrs
["fill-rule"] = {0: "nonzero", 1: "evenodd"}[self
.even_odd
]
244 fillrule
.nonzero_winding
= fillrule(0)
245 fillrule
.even_odd
= fillrule(1)
246 fillrule
.clear
= attr
.clearclass(fillrule
)