~ubuntu-branches/ubuntu/trusty/pyx/trusty

« back to all changes in this revision

Viewing changes to pyx/pattern.py

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2006-11-26 14:04:53 UTC
  • mfrom: (2.1.3 edgy)
  • Revision ID: james.westby@ubuntu.com-20061126140453-1dq3cycpspmlik2t
Tags: 0.9-3
* New maintainer. Thank you for more than three years of
  maintenance,  Graham! Closes: #400087
* Don't hard-code python 2.3 in manual/Makefile.
  Thanks to Matthias Klose for the bug report and patch.
  Closes: #392634
* Remove obsolete dh_python call from debian/rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: ISO-8859-1 -*-
 
2
#
 
3
#
 
4
# Copyright (C) 2002-2006 J�rg Lehmann <joergl@users.sourceforge.net>
 
5
# Copyright (C) 2002-2006 Andr� Wobst <wobsta@users.sourceforge.net>
 
6
#
 
7
# This file is part of PyX (http://pyx.sourceforge.net/).
 
8
#
 
9
# PyX is free software; you can redistribute it and/or modify
 
10
# it under the terms of the GNU General Public License as published by
 
11
# the Free Software Foundation; either version 2 of the License, or
 
12
# (at your option) any later version.
 
13
#
 
14
# PyX is distributed in the hope that it will be useful,
 
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
# GNU General Public License for more details.
 
18
#
 
19
# You should have received a copy of the GNU General Public License
 
20
# along with PyX; if not, write to the Free Software
 
21
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
22
 
 
23
from __future__ import nested_scopes
 
24
 
 
25
import cStringIO, math, warnings
 
26
import attr, canvas, path, pdfwriter, pswriter, style, unit, trafo
 
27
import bbox as bboxmodule
 
28
 
 
29
class _marker: pass
 
30
 
 
31
# TODO: pattern should not derive from canvas but wrap a canvas
 
32
 
 
33
class pattern(canvas._canvas, attr.exclusiveattr, style.fillstyle):
 
34
 
 
35
    def __init__(self, painttype=1, tilingtype=1, xstep=None, ystep=None, bbox=None, trafo=None, **kwargs):
 
36
        canvas._canvas.__init__(self, **kwargs)
 
37
        attr.exclusiveattr.__init__(self, pattern)
 
38
        self.id = "pattern%d" % id(self)
 
39
        self.patterntype = 1
 
40
        if painttype not in (1,2):
 
41
            raise ValueError("painttype must be 1 or 2")
 
42
        self.painttype = painttype
 
43
        if tilingtype not in (1,2,3):
 
44
            raise ValueError("tilingtype must be 1, 2 or 3")
 
45
        self.tilingtype = tilingtype
 
46
        self.xstep = xstep
 
47
        self.ystep = ystep
 
48
        self.patternbbox = bbox
 
49
        self.patterntrafo = trafo
 
50
 
 
51
    def __call__(self, painttype=_marker, tilingtype=_marker, xstep=_marker, ystep=_marker, 
 
52
                 bbox=_marker, trafo=_marker):
 
53
        if painttype is _marker:
 
54
            painttype = self.painttype
 
55
        if tilingtype is _marker:
 
56
            tilingtype = self.tilingtype
 
57
        if xstep is _marker:
 
58
            xstep = self.xstep
 
59
        if ystep is _marker:
 
60
            ystep = self.ystep
 
61
        if bbox is _marker:
 
62
            bbox = self.bbox
 
63
        if trafo is _marker:
 
64
            trafo = self.trafo
 
65
        return pattern(painttype, tilingtype, xstep, ystep, bbox, trafo)
 
66
 
 
67
    def bbox(self):
 
68
        return bboxmodule.empty()
 
69
 
 
70
    def processPS(self, file, writer, context, registry, bbox):
 
71
        # process pattern, letting it register its resources and calculate the bbox of the pattern
 
72
        patternfile = cStringIO.StringIO()
 
73
        realpatternbbox = bboxmodule.empty()
 
74
        canvas._canvas.processPS(self, patternfile, writer, pswriter.context(), registry, realpatternbbox)
 
75
        patternproc = patternfile.getvalue()
 
76
        patternfile.close()
 
77
 
 
78
        if self.xstep is None:
 
79
           xstep = unit.topt(realpatternbbox.width())
 
80
        else:
 
81
           xstep = unit.topt(self.xstep)
 
82
        if self.ystep is None:
 
83
            ystep = unit.topt(realpatternbbox.height())
 
84
        else:
 
85
           ystep = unit.topt(self.ystep)
 
86
        if not xstep:
 
87
            raise ValueError("xstep in pattern cannot be zero")
 
88
        if not ystep:
 
89
            raise ValueError("ystep in pattern cannot be zero")
 
90
        patternbbox = self.patternbbox or realpatternbbox.enlarged(5*unit.pt)
 
91
 
 
92
        patternprefix = "\n".join(("<<",
 
93
                                   "/PatternType %d" % self.patterntype,
 
94
                                   "/PaintType %d" % self.painttype,
 
95
                                   "/TilingType %d" % self.tilingtype,
 
96
                                   "/BBox[%d %d %d %d]" % patternbbox.lowrestuple_pt(),
 
97
                                   "/XStep %g" % xstep,
 
98
                                   "/YStep %g" % ystep,
 
99
                                   "/PaintProc {\nbegin\n"))
 
100
        patterntrafostring = self.patterntrafo is None and "matrix" or str(self.patterntrafo)
 
101
        patternsuffix = "end\n} bind\n>>\n%s\nmakepattern" % patterntrafostring
 
102
 
 
103
        registry.add(pswriter.PSdefinition(self.id, "".join((patternprefix, patternproc, patternsuffix))))
 
104
 
 
105
        # activate pattern
 
106
        file.write("%s setpattern\n" % self.id)
 
107
 
 
108
    def processPDF(self, file, writer, context, registry, bbox):
 
109
        # we need to keep track of the resources used by the pattern, hence
 
110
        # we create our own registry, which we merge immediately in the main registry
 
111
        patternregistry = pdfwriter.PDFregistry()
 
112
 
 
113
        patternfile = cStringIO.StringIO()
 
114
        realpatternbbox = bboxmodule.empty()
 
115
        canvas._canvas.processPDF(self, patternfile, writer, pdfwriter.context(), patternregistry, realpatternbbox)
 
116
        patternproc = patternfile.getvalue()
 
117
        patternfile.close()
 
118
 
 
119
        registry.mergeregistry(patternregistry)
 
120
 
 
121
        if self.xstep is None:
 
122
           xstep = unit.topt(realpatternbbox.width())
 
123
        else:
 
124
           xstep = unit.topt(self.xstep)
 
125
        if self.ystep is None:
 
126
            ystep = unit.topt(realpatternbbox.height())
 
127
        else:
 
128
           ystep = unit.topt(self.ystep)
 
129
        if not xstep:
 
130
            raise ValueError("xstep in pattern cannot be zero")
 
131
        if not ystep:
 
132
            raise ValueError("ystep in pattern cannot be zero")
 
133
        patternbbox = self.patternbbox or realpatternbbox.enlarged(5*unit.pt)
 
134
        patterntrafo = self.patterntrafo or trafo.trafo()
 
135
 
 
136
        registry.add(PDFpattern(self.id, self.patterntype, self.painttype, self.tilingtype,
 
137
                                patternbbox, xstep, ystep, patterntrafo, patternproc, writer, registry, patternregistry))
 
138
 
 
139
        # activate pattern
 
140
        if context.colorspace != "Pattern":
 
141
            # we only set the fill color space (see next comment)
 
142
            file.write("/Pattern cs\n")
 
143
            context.colorspace = "Pattern"
 
144
        if context.strokeattr:
 
145
            # using patterns as stroke colors doesn't seem to work, so
 
146
            # we just don't do this...
 
147
            warnings.warn("ignoring stroke color for patterns in PDF")
 
148
        if context.fillattr:
 
149
            file.write("/%s scn\n"% self.id)
 
150
 
 
151
 
 
152
pattern.clear = attr.clearclass(pattern)
 
153
 
 
154
 
 
155
_base = 0.1 * unit.v_cm
 
156
 
 
157
class hatched(pattern):
 
158
    def __init__(self, dist, angle, strokestyles=[]):
 
159
        pattern.__init__(self, painttype=1, tilingtype=1, xstep=dist, ystep=100*unit.t_pt, bbox=None, trafo=trafo.rotate(angle))
 
160
        self.strokestyles = attr.mergeattrs([style.linewidth.THIN] + strokestyles)
 
161
        attr.checkattrs(self.strokestyles, [style.strokestyle])
 
162
        self.dist = dist
 
163
        self.angle = angle
 
164
        self.stroke(path.line_pt(0, -50, 0, 50), self.strokestyles)
 
165
 
 
166
    def __call__(self, dist=None, angle=None, strokestyles=None):
 
167
        if dist is None:
 
168
            dist = self.dist
 
169
        if angle is None:
 
170
            angle = self.angle
 
171
        if strokestyles is None:
 
172
            strokestyles = self.strokestyles
 
173
        return hatched(dist, angle, strokestyles)
 
174
 
 
175
hatched0 = hatched(_base, 0)
 
176
hatched0.SMALL = hatched0(_base/math.sqrt(64))
 
177
hatched0.SMALL = hatched0(_base/math.sqrt(64))
 
178
hatched0.SMALl = hatched0(_base/math.sqrt(32))
 
179
hatched0.SMAll = hatched0(_base/math.sqrt(16))
 
180
hatched0.SMall = hatched0(_base/math.sqrt(8))
 
181
hatched0.Small = hatched0(_base/math.sqrt(4))
 
182
hatched0.small = hatched0(_base/math.sqrt(2))
 
183
hatched0.normal = hatched0(_base)
 
184
hatched0.large = hatched0(_base*math.sqrt(2))
 
185
hatched0.Large = hatched0(_base*math.sqrt(4))
 
186
hatched0.LArge = hatched0(_base*math.sqrt(8))
 
187
hatched0.LARge = hatched0(_base*math.sqrt(16))
 
188
hatched0.LARGe = hatched0(_base*math.sqrt(32))
 
189
hatched0.LARGE = hatched0(_base*math.sqrt(64))
 
190
 
 
191
hatched45 = hatched(_base, 45)
 
192
hatched45.SMALL = hatched45(_base/math.sqrt(64))
 
193
hatched45.SMALl = hatched45(_base/math.sqrt(32))
 
194
hatched45.SMAll = hatched45(_base/math.sqrt(16))
 
195
hatched45.SMall = hatched45(_base/math.sqrt(8))
 
196
hatched45.Small = hatched45(_base/math.sqrt(4))
 
197
hatched45.small = hatched45(_base/math.sqrt(2))
 
198
hatched45.normal = hatched45(_base)
 
199
hatched45.large = hatched45(_base*math.sqrt(2))
 
200
hatched45.Large = hatched45(_base*math.sqrt(4))
 
201
hatched45.LArge = hatched45(_base*math.sqrt(8))
 
202
hatched45.LARge = hatched45(_base*math.sqrt(16))
 
203
hatched45.LARGe = hatched45(_base*math.sqrt(32))
 
204
hatched45.LARGE = hatched45(_base*math.sqrt(64))
 
205
 
 
206
hatched90 = hatched(_base, 90)
 
207
hatched90.SMALL = hatched90(_base/math.sqrt(64))
 
208
hatched90.SMALl = hatched90(_base/math.sqrt(32))
 
209
hatched90.SMAll = hatched90(_base/math.sqrt(16))
 
210
hatched90.SMall = hatched90(_base/math.sqrt(8))
 
211
hatched90.Small = hatched90(_base/math.sqrt(4))
 
212
hatched90.small = hatched90(_base/math.sqrt(2))
 
213
hatched90.normal = hatched90(_base)
 
214
hatched90.large = hatched90(_base*math.sqrt(2))
 
215
hatched90.Large = hatched90(_base*math.sqrt(4))
 
216
hatched90.LArge = hatched90(_base*math.sqrt(8))
 
217
hatched90.LARge = hatched90(_base*math.sqrt(16))
 
218
hatched90.LARGe = hatched90(_base*math.sqrt(32))
 
219
hatched90.LARGE = hatched90(_base*math.sqrt(64))
 
220
 
 
221
hatched135 = hatched(_base, 135)
 
222
hatched135.SMALL = hatched135(_base/math.sqrt(64))
 
223
hatched135.SMALl = hatched135(_base/math.sqrt(32))
 
224
hatched135.SMAll = hatched135(_base/math.sqrt(16))
 
225
hatched135.SMall = hatched135(_base/math.sqrt(8))
 
226
hatched135.Small = hatched135(_base/math.sqrt(4))
 
227
hatched135.small = hatched135(_base/math.sqrt(2))
 
228
hatched135.normal = hatched135(_base)
 
229
hatched135.large = hatched135(_base*math.sqrt(2))
 
230
hatched135.Large = hatched135(_base*math.sqrt(4))
 
231
hatched135.LArge = hatched135(_base*math.sqrt(8))
 
232
hatched135.LARge = hatched135(_base*math.sqrt(16))
 
233
hatched135.LARGe = hatched135(_base*math.sqrt(32))
 
234
hatched135.LARGE = hatched135(_base*math.sqrt(64))
 
235
 
 
236
 
 
237
class crosshatched(pattern):
 
238
    def __init__(self, dist, angle, strokestyles=[]):
 
239
        pattern.__init__(self, painttype=1, tilingtype=1, xstep=dist, ystep=dist, bbox=None, trafo=trafo.rotate(angle))
 
240
        self.strokestyles = attr.mergeattrs([style.linewidth.THIN] + strokestyles)
 
241
        attr.checkattrs(self.strokestyles, [style.strokestyle])
 
242
        self.dist = dist
 
243
        self.angle = angle
 
244
        self.stroke(path.line_pt(0, 0, 0, unit.topt(dist)), self.strokestyles)
 
245
        self.stroke(path.line_pt(0, 0, unit.topt(dist), 0), self.strokestyles)
 
246
 
 
247
    def __call__(self, dist=None, angle=None, strokestyles=None):
 
248
        if dist is None:
 
249
            dist = self.dist
 
250
        if angle is None:
 
251
            angle = self.angle
 
252
        if strokestyles is None:
 
253
            strokestyles = self.strokestyles
 
254
        return crosshatched(dist, angle, strokestyles)
 
255
 
 
256
crosshatched0 = crosshatched(_base, 0)
 
257
crosshatched0.SMALL = crosshatched0(_base/math.sqrt(64))
 
258
crosshatched0.SMALl = crosshatched0(_base/math.sqrt(32))
 
259
crosshatched0.SMAll = crosshatched0(_base/math.sqrt(16))
 
260
crosshatched0.SMall = crosshatched0(_base/math.sqrt(8))
 
261
crosshatched0.Small = crosshatched0(_base/math.sqrt(4))
 
262
crosshatched0.small = crosshatched0(_base/math.sqrt(2))
 
263
crosshatched0.normal = crosshatched0
 
264
crosshatched0.large = crosshatched0(_base*math.sqrt(2))
 
265
crosshatched0.Large = crosshatched0(_base*math.sqrt(4))
 
266
crosshatched0.LArge = crosshatched0(_base*math.sqrt(8))
 
267
crosshatched0.LARge = crosshatched0(_base*math.sqrt(16))
 
268
crosshatched0.LARGe = crosshatched0(_base*math.sqrt(32))
 
269
crosshatched0.LARGE = crosshatched0(_base*math.sqrt(64))
 
270
 
 
271
crosshatched45 = crosshatched(_base, 45)
 
272
crosshatched45.SMALL = crosshatched45(_base/math.sqrt(64))
 
273
crosshatched45.SMALl = crosshatched45(_base/math.sqrt(32))
 
274
crosshatched45.SMAll = crosshatched45(_base/math.sqrt(16))
 
275
crosshatched45.SMall = crosshatched45(_base/math.sqrt(8))
 
276
crosshatched45.Small = crosshatched45(_base/math.sqrt(4))
 
277
crosshatched45.small = crosshatched45(_base/math.sqrt(2))
 
278
crosshatched45.normal = crosshatched45
 
279
crosshatched45.large = crosshatched45(_base*math.sqrt(2))
 
280
crosshatched45.Large = crosshatched45(_base*math.sqrt(4))
 
281
crosshatched45.LArge = crosshatched45(_base*math.sqrt(8))
 
282
crosshatched45.LARge = crosshatched45(_base*math.sqrt(16))
 
283
crosshatched45.LARGe = crosshatched45(_base*math.sqrt(32))
 
284
crosshatched45.LARGE = crosshatched45(_base*math.sqrt(64))
 
285
 
 
286
 
 
287
class PDFpattern(pdfwriter.PDFobject):
 
288
 
 
289
    def __init__(self, name, patterntype, painttype, tilingtype, bbox, xstep, ystep, trafo,
 
290
                 patternproc, writer, registry, patternregistry):
 
291
        self.patternregistry = patternregistry
 
292
        pdfwriter.PDFobject.__init__(self, "pattern", name)
 
293
        registry.addresource("Pattern", name, self)
 
294
 
 
295
        self.name = name
 
296
        self.patterntype = patterntype
 
297
        self.painttype = painttype
 
298
        self.tilingtype = tilingtype
 
299
        self.bbox = bbox
 
300
        self.xstep = xstep
 
301
        self.ystep = ystep
 
302
        self.trafo = trafo
 
303
        self.patternproc = patternproc
 
304
 
 
305
    def write(self, file, writer, registry):
 
306
        file.write("<<\n"
 
307
                   "/Type /Pattern\n"
 
308
                   "/PatternType %d\n" % self.patterntype)
 
309
        file.write("/PaintType %d\n" % self.painttype)
 
310
        file.write("/TilingType %d\n" % self.tilingtype)
 
311
        file.write("/BBox [%d %d %d %d]\n" % self.bbox.lowrestuple_pt())
 
312
        file.write("/XStep %f\n" % self.xstep)
 
313
        file.write("/YStep %f\n" % self.ystep)
 
314
        file.write("/Matrix %s\n" % str(self.trafo))
 
315
        self.patternregistry.writeresources(file)
 
316
        if writer.compress:
 
317
            import zlib
 
318
            content = zlib.compress(self.patternproc)
 
319
        else:
 
320
            content = self.patterproc
 
321
 
 
322
        file.write("/Length %i\n" % len(content))
 
323
        if writer.compress:
 
324
            file.write("/Filter /FlateDecode\n")
 
325
        file.write(">>\n"
 
326
                   "stream\n")
 
327
        file.write(content)
 
328
        file.write("endstream\n")