1 # -*- encoding: utf-8 -*-
4 # Copyright (C) 2002-2011 Jörg Lehmann <joergl@users.sourceforge.net>
5 # Copyright (C) 2003-2006 Michael Schindler <m-schindler@users.sourceforge.net>
6 # Copyright (C) 2002-2011 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 return bboxmodule
.empty()
36 class fillstyle(canvasitem
.canvasitem
):
38 return bboxmodule
.empty()
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
, bbox
):
54 file.write("%d setlinecap\n" % self
.value
)
56 def processPDF(self
, file, writer
, context
, registry
, bbox
):
57 file.write("%d J\n" % self
.value
)
59 linecap
.butt
= linecap(0)
60 linecap
.round = linecap(1)
61 linecap
.square
= linecap(2)
62 linecap
.clear
= attr
.clearclass(linecap
)
65 class linejoin(attr
.exclusiveattr
, strokestyle
):
67 """linejoin of paths"""
69 def __init__(self
, value
=0):
70 attr
.exclusiveattr
.__init
__(self
, linejoin
)
73 def processPS(self
, file, writer
, context
, registry
, bbox
):
74 file.write("%d setlinejoin\n" % self
.value
)
76 def processPDF(self
, file, writer
, context
, registry
, bbox
):
77 file.write("%d j\n" % self
.value
)
79 linejoin
.miter
= linejoin(0)
80 linejoin
.round = linejoin(1)
81 linejoin
.bevel
= linejoin(2)
82 linejoin
.clear
= attr
.clearclass(linejoin
)
85 class miterlimit(attr
.exclusiveattr
, strokestyle
):
87 """miterlimit of paths"""
89 def __init__(self
, value
=10.0):
90 attr
.exclusiveattr
.__init
__(self
, miterlimit
)
93 def processPS(self
, file, writer
, context
, registry
, bbox
):
94 file.write("%f setmiterlimit\n" % self
.value
)
96 def processPDF(self
, file, writer
, context
, registry
, bbox
):
97 file.write("%f M\n" % self
.value
)
99 miterlimit
.lessthan180deg
= miterlimit(1/math
.sin(math
.pi
*180/360))
100 miterlimit
.lessthan90deg
= miterlimit(1/math
.sin(math
.pi
*90/360))
101 miterlimit
.lessthan60deg
= miterlimit(1/math
.sin(math
.pi
*60/360))
102 miterlimit
.lessthan45deg
= miterlimit(1/math
.sin(math
.pi
*45/360))
103 miterlimit
.lessthan11deg
= miterlimit(10) # the default, approximately 11.4783 degress
104 miterlimit
.clear
= attr
.clearclass(miterlimit
)
107 _defaultlinewidth
= 0.02 * unit
.w_cm
108 _defaultlinewidth_pt
= unit
.topt(_defaultlinewidth
)
110 class dash(attr
.exclusiveattr
, strokestyle
):
114 def __init__(self
, pattern
=[], offset
=0, rellengths
=1):
115 """set pattern with offset.
117 If rellengths is True, interpret all dash lengths relative to current linewidth.
119 attr
.exclusiveattr
.__init
__(self
, dash
)
120 self
.pattern
= pattern
122 self
.rellengths
= rellengths
124 def processPS(self
, file, writer
, context
, registry
, bbox
):
126 patternstring
= " ".join(["%f" % (element
* context
.linewidth_pt
/_defaultlinewidth_pt
) for element
in self
.pattern
])
128 patternstring
= " ".join(["%f" % element
for element
in self
.pattern
])
129 file.write("[%s] %d setdash\n" % (patternstring
, self
.offset
))
131 def processPDF(self
, file, writer
, context
, registry
, bbox
):
133 patternstring
= " ".join(["%f" % (element
* context
.linewidth_pt
/_defaultlinewidth_pt
) for element
in self
.pattern
])
135 patternstring
= " ".join(["%f" % element
for element
in self
.pattern
])
136 file.write("[%s] %d d\n" % (patternstring
, self
.offset
))
138 dash
.clear
= attr
.clearclass(dash
)
141 class linestyle(attr
.exclusiveattr
, strokestyle
):
143 """linestyle (linecap together with dash) of paths"""
145 def __init__(self
, c
=linecap
.butt
, d
=dash([])):
146 # XXX better, but at the moment not supported by attr.exlusiveattr would be:
147 # XXX attr.exclusiveattr.__init__(self, [linestyle, linecap, dash])
148 attr
.exclusiveattr
.__init
__(self
, linestyle
)
152 def processPS(self
, file, writer
, context
, registry
, bbox
):
153 self
.c
.processPS(file, writer
, context
, registry
, bbox
)
154 self
.d
.processPS(file, writer
, context
, registry
, bbox
)
156 def processPDF(self
, file, writer
, context
, registry
, bbox
):
157 self
.c
.processPDF(file, writer
, context
, registry
, bbox
)
158 self
.d
.processPDF(file, writer
, context
, registry
, bbox
)
160 linestyle
.solid
= linestyle(linecap
.butt
, dash([]))
161 linestyle
.dashed
= linestyle(linecap
.butt
, dash([2]))
162 linestyle
.dotted
= linestyle(linecap
.round, dash([0, 2]))
163 linestyle
.dashdotted
= linestyle(linecap
.round, dash([0, 2, 2, 2]))
164 linestyle
.clear
= attr
.clearclass(linestyle
)
167 class linewidth(attr
.sortbeforeexclusiveattr
, strokestyle
):
169 """linewidth of paths"""
171 def __init__(self
, width
):
172 attr
.sortbeforeexclusiveattr
.__init
__(self
, linewidth
, [dash
, linestyle
])
175 def processPS(self
, file, writer
, context
, registry
, bbox
):
176 file.write("%f setlinewidth\n" % unit
.topt(self
.width
))
177 context
.linewidth_pt
= unit
.topt(self
.width
)
179 def processPDF(self
, file, writer
, context
, registry
, bbox
):
180 file.write("%f w\n" % unit
.topt(self
.width
))
181 context
.linewidth_pt
= unit
.topt(self
.width
)
183 linewidth
.THIN
= linewidth(_defaultlinewidth
/math
.sqrt(32))
184 linewidth
.THIn
= linewidth(_defaultlinewidth
/math
.sqrt(16))
185 linewidth
.THin
= linewidth(_defaultlinewidth
/math
.sqrt(8))
186 linewidth
.Thin
= linewidth(_defaultlinewidth
/math
.sqrt(4))
187 linewidth
.thin
= linewidth(_defaultlinewidth
/math
.sqrt(2))
188 linewidth
.normal
= linewidth(_defaultlinewidth
)
189 linewidth
.thick
= linewidth(_defaultlinewidth
*math
.sqrt(2))
190 linewidth
.Thick
= linewidth(_defaultlinewidth
*math
.sqrt(4))
191 linewidth
.THick
= linewidth(_defaultlinewidth
*math
.sqrt(8))
192 linewidth
.THIck
= linewidth(_defaultlinewidth
*math
.sqrt(16))
193 linewidth
.THICk
= linewidth(_defaultlinewidth
*math
.sqrt(32))
194 linewidth
.THICK
= linewidth(_defaultlinewidth
*math
.sqrt(64))
195 linewidth
.clear
= attr
.clearclass(linewidth
)
198 class fillrule(attr
.exclusiveattr
):
200 """defines the fill rule to be used"""
202 def __init__(self
, even_odd
):
203 attr
.exclusiveattr
.__init
__(self
, fillrule
)
204 self
.even_odd
= even_odd
206 def processPS(self
, file, writer
, context
, registry
, bbox
):
209 def processPDF(self
, file, writer
, context
, registry
, bbox
):
212 fillrule
.nonzero_winding
= fillrule(0)
213 fillrule
.even_odd
= fillrule(1)
214 fillrule
.clear
= attr
.clearclass(fillrule
)