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 import attr
, unit
, canvasitem
26 import bbox
as bboxmodule
29 # base classes for stroke and fill styles
32 class strokestyle(canvasitem
.canvasitem
):
34 # TODO: see TODO in bbox method of canvasitem
35 return bboxmodule
.empty()
37 class fillstyle(canvasitem
.canvasitem
):
39 # TODO: see TODO in bbox method of canvasitem
40 return bboxmodule
.empty()
43 # common stroke styles
47 class linecap(attr
.exclusiveattr
, strokestyle
):
49 """linecap of paths"""
51 def __init__(self
, value
=0):
52 attr
.exclusiveattr
.__init
__(self
, linecap
)
55 def processPS(self
, file, writer
, context
, registry
, bbox
):
56 file.write("%d setlinecap\n" % self
.value
)
58 def processPDF(self
, file, writer
, context
, registry
, bbox
):
59 file.write("%d J\n" % self
.value
)
61 linecap
.butt
= linecap(0)
62 linecap
.round = linecap(1)
63 linecap
.square
= linecap(2)
64 linecap
.clear
= attr
.clearclass(linecap
)
67 class linejoin(attr
.exclusiveattr
, strokestyle
):
69 """linejoin of paths"""
71 def __init__(self
, value
=0):
72 attr
.exclusiveattr
.__init
__(self
, linejoin
)
75 def processPS(self
, file, writer
, context
, registry
, bbox
):
76 file.write("%d setlinejoin\n" % self
.value
)
78 def processPDF(self
, file, writer
, context
, registry
, bbox
):
79 file.write("%d j\n" % self
.value
)
81 linejoin
.miter
= linejoin(0)
82 linejoin
.round = linejoin(1)
83 linejoin
.bevel
= linejoin(2)
84 linejoin
.clear
= attr
.clearclass(linejoin
)
87 class miterlimit(attr
.exclusiveattr
, strokestyle
):
89 """miterlimit of paths"""
91 def __init__(self
, value
=10.0):
92 attr
.exclusiveattr
.__init
__(self
, miterlimit
)
95 def processPS(self
, file, writer
, context
, registry
, bbox
):
96 file.write("%f setmiterlimit\n" % self
.value
)
98 def processPDF(self
, file, writer
, context
, registry
, bbox
):
99 file.write("%f M\n" % self
.value
)
101 miterlimit
.lessthan180deg
= miterlimit(1/math
.sin(math
.pi
*180/360))
102 miterlimit
.lessthan90deg
= miterlimit(1/math
.sin(math
.pi
*90/360))
103 miterlimit
.lessthan60deg
= miterlimit(1/math
.sin(math
.pi
*60/360))
104 miterlimit
.lessthan45deg
= miterlimit(1/math
.sin(math
.pi
*45/360))
105 miterlimit
.lessthan11deg
= miterlimit(10) # the default, approximately 11.4783 degress
106 miterlimit
.clear
= attr
.clearclass(miterlimit
)
109 _defaultlinewidth
= 0.02 * unit
.w_cm
110 _defaultlinewidth_pt
= unit
.topt(_defaultlinewidth
)
112 class dash(attr
.exclusiveattr
, strokestyle
):
116 def __init__(self
, pattern
=[], offset
=0, rellengths
=1):
117 """set pattern with offset.
119 If rellengths is True, interpret all dash lengths relative to current linewidth.
121 attr
.exclusiveattr
.__init
__(self
, dash
)
122 self
.pattern
= pattern
124 self
.rellengths
= rellengths
126 def processPS(self
, file, writer
, context
, registry
, bbox
):
128 patternstring
= " ".join(["%f" % (element
* context
.linewidth_pt
/_defaultlinewidth_pt
) for element
in self
.pattern
])
130 patternstring
= " ".join(["%f" % element
for element
in self
.pattern
])
131 file.write("[%s] %d setdash\n" % (patternstring
, self
.offset
))
133 def processPDF(self
, file, writer
, context
, registry
, bbox
):
135 patternstring
= " ".join(["%f" % (element
* context
.linewidth_pt
/_defaultlinewidth_pt
) for element
in self
.pattern
])
137 patternstring
= " ".join(["%f" % element
for element
in self
.pattern
])
138 file.write("[%s] %d d\n" % (patternstring
, self
.offset
))
140 dash
.clear
= attr
.clearclass(dash
)
143 class linestyle(attr
.exclusiveattr
, strokestyle
):
145 """linestyle (linecap together with dash) of paths"""
147 def __init__(self
, c
=linecap
.butt
, d
=dash([])):
148 # XXX better, but at the moment not supported by attr.exlusiveattr would be:
149 # XXX attr.exclusiveattr.__init__(self, [linestyle, linecap, dash])
150 attr
.exclusiveattr
.__init
__(self
, linestyle
)
154 def processPS(self
, file, writer
, context
, registry
, bbox
):
155 self
.c
.processPS(file, writer
, context
, registry
, bbox
)
156 self
.d
.processPS(file, writer
, context
, registry
, bbox
)
158 def processPDF(self
, file, writer
, context
, registry
, bbox
):
159 self
.c
.processPDF(file, writer
, context
, registry
, bbox
)
160 self
.d
.processPDF(file, writer
, context
, registry
, bbox
)
162 linestyle
.solid
= linestyle(linecap
.butt
, dash([]))
163 linestyle
.dashed
= linestyle(linecap
.butt
, dash([2]))
164 linestyle
.dotted
= linestyle(linecap
.round, dash([0, 2]))
165 linestyle
.dashdotted
= linestyle(linecap
.round, dash([0, 2, 2, 2]))
166 linestyle
.clear
= attr
.clearclass(linestyle
)
169 class linewidth(attr
.sortbeforeexclusiveattr
, strokestyle
):
171 """linewidth of paths"""
173 def __init__(self
, width
):
174 attr
.sortbeforeexclusiveattr
.__init
__(self
, linewidth
, [dash
, linestyle
])
177 def processPS(self
, file, writer
, context
, registry
, bbox
):
178 file.write("%f setlinewidth\n" % unit
.topt(self
.width
))
179 context
.linewidth_pt
= unit
.topt(self
.width
)
181 def processPDF(self
, file, writer
, context
, registry
, bbox
):
182 file.write("%f w\n" % unit
.topt(self
.width
))
183 context
.linewidth_pt
= unit
.topt(self
.width
)
185 linewidth
.THIN
= linewidth(_defaultlinewidth
/math
.sqrt(32))
186 linewidth
.THIn
= linewidth(_defaultlinewidth
/math
.sqrt(16))
187 linewidth
.THin
= linewidth(_defaultlinewidth
/math
.sqrt(8))
188 linewidth
.Thin
= linewidth(_defaultlinewidth
/math
.sqrt(4))
189 linewidth
.thin
= linewidth(_defaultlinewidth
/math
.sqrt(2))
190 linewidth
.normal
= linewidth(_defaultlinewidth
)
191 linewidth
.thick
= linewidth(_defaultlinewidth
*math
.sqrt(2))
192 linewidth
.Thick
= linewidth(_defaultlinewidth
*math
.sqrt(4))
193 linewidth
.THick
= linewidth(_defaultlinewidth
*math
.sqrt(8))
194 linewidth
.THIck
= linewidth(_defaultlinewidth
*math
.sqrt(16))
195 linewidth
.THICk
= linewidth(_defaultlinewidth
*math
.sqrt(32))
196 linewidth
.THICK
= linewidth(_defaultlinewidth
*math
.sqrt(64))
197 linewidth
.clear
= attr
.clearclass(linewidth
)
200 class fillrule(attr
.exclusiveattr
):
202 """defines the fill rule to be used"""
204 def __init__(self
, even_odd
):
205 attr
.exclusiveattr
.__init
__(self
, fillrule
)
206 self
.even_odd
= even_odd
208 def processPS(self
, file, writer
, context
, registry
, bbox
):
211 def processPDF(self
, file, writer
, context
, registry
, bbox
):
214 fillrule
.nonzero_winding
= fillrule(0)
215 fillrule
.even_odd
= fillrule(1)
216 fillrule
.clear
= attr
.clearclass(fillrule
)