From 3e757515d3633d4ddb4e58e9d68ed9ab782077d6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=B6rg=20Lehmann?= Date: Mon, 10 Apr 2006 17:55:26 +0000 Subject: [PATCH] - path module - path is no longer a canvasitem - reduce number of parameters of outputPS/outputPDF methods (do not pass context and registry) - normpath module: - normpath is no longer a canvasitem - reduce number of parameters of outputPS/outputPDF methods (do not pass context and registry) - canvas module: - rename outputPS/outputPDF -> processPS/processPDF git-svn-id: https://pyx.svn.sourceforge.net/svnroot/pyx/trunk/pyx@2584 069f4177-920e-0410-937b-c2a4a81bcd90 --- CHANGES | 5 ++ pyx/bbox.py | 113 +++++++++++++++++++++++++------- pyx/bitmap.py | 10 +-- pyx/canvas.py | 99 +++++++++++++--------------- pyx/color.py | 30 ++++----- pyx/deco.py | 102 +++++++++++------------------ pyx/document.py | 18 ++++-- pyx/epsfile.py | 13 ++-- pyx/graph/graph.py | 8 +-- pyx/normpath.py | 59 ++++++++--------- pyx/path.py | 55 ++++++++-------- pyx/pattern.py | 151 ++++++++++++++++++++++--------------------- pyx/pdfwriter.py | 26 +++----- pyx/pswriter.py | 139 +++++++++++++++++++-------------------- pyx/style.py | 32 ++++----- pyx/text.py | 8 +-- pyx/trafo.py | 9 +-- pyx/type1font.py | 19 ++---- test/functional/test_path.py | 2 +- test/functional/test_text.py | 8 +-- 20 files changed, 467 insertions(+), 439 deletions(-) diff --git a/CHANGES b/CHANGES index 6d39af53..749dbbbb 100644 --- a/CHANGES +++ b/CHANGES @@ -134,11 +134,15 @@ TODO: - add rotate methods to path, normpath, normsubpath, and normsubpathitems - add flushskippedline to normsubpath - add arclentoparam to normsubpath and normsubpathitems + - path is no longer a canvasitem + - reduce number of parameters of outputPS/outputPDF methods (do not pass context and registry) - normpath module: - contains normpath, normsubpath and normpathparam which have originally been in the path module - return "invalid" for certain path operations when the curve "speed" is below a certain threshold + - normpath is no longer a canvasitem + - reduce number of parameters of outputPS/outputPDF methods (do not pass context and registry) - deformer module: - rewritten smoother to make use of the subnormpath facilities - rewritten parallel for arbitrary paths @@ -165,6 +169,7 @@ TODO: - canvas module: - remove registerPS/registerPDF in favour of registering resourcing during the outputPS/outputPDF run - move bbox handling to registry + - rename outputPS/outputPDF -> processPS/processPDF - random notes: - switched to subversion on 2006/03/09 diff --git a/pyx/bbox.py b/pyx/bbox.py index 8167cfa5..f5295197 100644 --- a/pyx/bbox.py +++ b/pyx/bbox.py @@ -2,7 +2,7 @@ # -*- coding: ISO-8859-1 -*- # # -# Copyright (C) 2002-2005 Jörg Lehmann +# Copyright (C) 2002-2006 Jörg Lehmann # Copyright (C) 2002-2004 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). @@ -33,7 +33,11 @@ class bbox_pt: """class for bounding boxes This variant requires points in the constructor, and is used for internal - purposes.""" + purposes. + + A bbox for which llx_pt is None represents an empty bbox, i.e., one containing + no points. + """ def __init__(self, llx_pt, lly_pt, urx_pt, ury_pt): self.llx_pt = llx_pt @@ -43,55 +47,87 @@ class bbox_pt: def __add__(self, other): """join two bboxes""" - return bbox_pt(min(self.llx_pt, other.llx_pt), min(self.lly_pt, other.lly_pt), - max(self.urx_pt, other.urx_pt), max(self.ury_pt, other.ury_pt)) + if self.llx_pt is not None: + if other.llx_pt is not None: + return bbox_pt(min(self.llx_pt, other.llx_pt), min(self.lly_pt, other.lly_pt), + max(self.urx_pt, other.urx_pt), max(self.ury_pt, other.ury_pt)) + else: + return bbox_pt(self.llx_pt, self.lly_pt, self.urx_pt, self.ury_pt) + else: + return bbox_pt(other.llx_pt, other.lly_pt, other.urx_pt, other.ury_pt) def __iadd__(self, other): """join two bboxes inplace""" - self.llx_pt = min(self.llx_pt, other.llx_pt) - self.lly_pt = min(self.lly_pt, other.lly_pt) - self.urx_pt = max(self.urx_pt, other.urx_pt) - self.ury_pt = max(self.ury_pt, other.ury_pt) + if self.llx_pt is not None: + if other.llx_pt is not None: + self.llx_pt = min(self.llx_pt, other.llx_pt) + self.lly_pt = min(self.lly_pt, other.lly_pt) + self.urx_pt = max(self.urx_pt, other.urx_pt) + self.ury_pt = max(self.ury_pt, other.ury_pt) + else: + self.llx_pt = other.llx_pt + self.lly_pt = other.lly_pt + self.urx_pt = other.urx_pt + self.ury_pt = other.ury_pt return self def __mul__(self, other): """return intersection of two bboxes""" - return bbox_pt(max(self.llx_pt, other.llx_pt), max(self.lly_pt, other.lly_pt), - min(self.urx_pt, other.urx_pt), min(self.ury_pt, other.ury_pt)) + if self.llx_pt is not None and other.llx_pt is not None: + return bbox_pt(max(self.llx_pt, other.llx_pt), max(self.lly_pt, other.lly_pt), + min(self.urx_pt, other.urx_pt), min(self.ury_pt, other.ury_pt)) + else: + return empty() def __imul__(self, other): """intersect two bboxes in place""" - self.llx_pt = max(self.llx_pt, other.llx_pt) - self.lly_pt = max(self.lly_pt, other.lly_pt) - self.urx_pt = min(self.urx_pt, other.urx_pt) - self.ury_pt = min(self.ury_pt, other.ury_pt) + if self.llx_pt is not None and other.llx_pt is not None: + self.llx_pt = max(self.llx_pt, other.llx_pt) + self.lly_pt = max(self.lly_pt, other.lly_pt) + self.urx_pt = min(self.urx_pt, other.urx_pt) + self.ury_pt = min(self.ury_pt, other.ury_pt) + elif other.llx_pt is None: + self.llx_pt = None return self def copy(self): return bbox_pt(self.llx_pt, self.lly_pt, self.urx_pt, self.ury_pt) def lowrestuple_pt(self): + if self.llx_pt is None: + raise ValueError("Cannot return low-res tuple for empty bbox") return (math.floor(self.llx_pt), math.floor(self.lly_pt), math.ceil(self.urx_pt), math.ceil(self.ury_pt)) def highrestuple_pt(self): + if self.llx_pt is None: + raise ValueError("Cannot return high-res tuple for empty bbox") return (self.llx_pt, self.lly_pt, self.urx_pt, self.ury_pt) def intersects(self, other): """check, if two bboxes intersect eachother""" - return not (self.llx_pt > other.urx_pt or - self.lly_pt > other.ury_pt or - self.urx_pt < other.llx_pt or - self.ury_pt < other.lly_pt) + if self.llx_pt is None or other.llx_pt is None: + return 0 + else: + return not (self.llx_pt > other.urx_pt or + self.lly_pt > other.ury_pt or + self.urx_pt < other.llx_pt or + self.ury_pt < other.lly_pt) def includepoint_pt(self, x_pt, y_pt): - self.llx_pt = min(self.llx_pt, x_pt) - self.lly_pt = min(self.lly_pt, y_pt) - self.urx_pt = max(self.urx_pt, x_pt) - self.ury_pt = max(self.ury_pt, y_pt) + if self.llx_pt is None: + self.llx_pt = self.urx_pt = x_pt + self.ury_pt = self.ury_pt = y_pt + else: + self.llx_pt = min(self.llx_pt, x_pt) + self.lly_pt = min(self.lly_pt, y_pt) + self.urx_pt = max(self.urx_pt, x_pt) + self.ury_pt = max(self.ury_pt, y_pt) def transform(self, trafo): """transform bbox in place by trafo""" + if self.llx_pt is None: + return # we have to transform all four corner points of the bbox llx_pt, lly_pt = trafo.apply_pt(self.llx_pt, self.lly_pt) lrx_pt, lry_pt = trafo.apply_pt(self.urx_pt, self.lly_pt) @@ -107,6 +143,8 @@ class bbox_pt: def transformed(self, trafo): """return bbox transformed by trafo""" + if self.llx_pt is None: + return empty() # we have to transform all four corner points of the bbox llx_pt, lly_pt = trafo.apply_pt(self.llx_pt, self.lly_pt) lrx_pt, lry_pt = trafo.apply_pt(self.urx_pt, self.lly_pt) @@ -124,6 +162,8 @@ class bbox_pt: all is used, if bottom, left, top and/or right are not given. """ + if self.llx_pt is None: + return if bottom_pt is None: bottom_pt = all_pt if left_pt is None: @@ -143,6 +183,8 @@ class bbox_pt: all is used, if bottom, left, top and/or right are not given. """ + if self.llx_pt is None: + return empty() if bottom_pt is None: bottom_pt = all_pt if left_pt is None: @@ -159,6 +201,8 @@ class bbox_pt: all is used, if bottom, left, top and/or right are not given. """ + if self.llx_pt is None: + return bottom_pt = left_pt = top_pt = right_pt = unit.topt(all) if bottom is not None: bottom_pt = unit.topt(bottom) @@ -179,6 +223,8 @@ class bbox_pt: all is used, if bottom, left, top and/or right are not given. """ + if self.llx_pt is None: + return empty() bottom_pt = left_pt = top_pt = right_pt = unit.topt(all) if bottom is not None: bottom_pt = unit.topt(bottom) @@ -192,6 +238,8 @@ class bbox_pt: def rect(self): """return rectangle corresponding to bbox""" + if self.llx_pt is None: + raise ValueError("Cannot return path for empty bbox") import path return path.rect_pt(self.llx_pt, self.lly_pt, self.urx_pt-self.llx_pt, self.ury_pt-self.lly_pt) @@ -199,30 +247,44 @@ class bbox_pt: def height_pt(self): """return height of bbox in pts""" + if self.llx_pt is None: + raise ValueError("Cannot return heigth of empty bbox") return self.ury_pt-self.lly_pt def width_pt(self): """return width of bbox in pts""" + if self.llx_pt is None: + raise ValueError("Cannot return width of empty bbox") return self.urx_pt-self.llx_pt def top_pt(self): """return top coordinate of bbox in pts""" + if self.llx_pt is None: + raise ValueError("Cannot return top coordinate of empty bbox") return self.ury_pt def bottom_pt(self): """return bottom coordinate of bbox in pts""" + if self.llx_pt is None: + raise ValueError("Cannot return bottom coordinate of empty bbox") return self.lly_pt def left_pt(self): """return left coordinate of bbox in pts""" + if self.llx_pt is None: + raise ValueError("Cannot return left coordinate of empty bbox") return self.llx_pt def right_pt(self): """return right coordinate of bbox in pts""" + if self.llx_pt is None: + raise ValueError("Cannot return right coordinate of empty bbox") return self.urx_pt def center_pt(self): """return coordinates of the center of the bbox in pts""" + if self.llx_pt is None: + raise ValueError("Cannot return center coordinates of empty bbox") return 0.5 * (self.llx_pt+self.urx_pt), 0.5 * (self.lly_pt+self.ury_pt) def height(self): @@ -265,3 +327,10 @@ class bbox(bbox_pt): urx_pt = unit.topt(urx_pt) ury_pt = unit.topt(ury_pt) bbox_pt.__init__(self, llx_pt, lly_pt, urx_pt, ury_pt) + + +class empty(bbox_pt): + + """empty bounding box, i.e., one containing no point""" + def __init__(self): + bbox_pt.__init__(self, None, None, None, None) diff --git a/pyx/bitmap.py b/pyx/bitmap.py index 46046b22..87aa6492 100644 --- a/pyx/bitmap.py +++ b/pyx/bitmap.py @@ -150,7 +150,7 @@ class PSimagedata(pswriter.PSresource): self.singlestring = singlestring self.maxstrlen = maxstrlen - def outputPS(self, file, writer, registry): + def output(self, file, writer, registry): # TODO resource data could be written directly on the output stream # after proper code reorganization file.write("%%%%BeginRessource: %s\n" % self.id) @@ -360,7 +360,7 @@ class bitmap(canvas.canvasitem): return bbox.bbox_pt(self.xpos_pt, self.ypos_pt, self.xpos_pt+self.width_pt, self.ypos_pt+self.height_pt) - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): if self.PSstoreimage and not self.PSsinglestring: registry.add(pswriter.PSdefinition("imagedataaccess", "{ /imagedataindex load " # get list index @@ -368,6 +368,7 @@ class bitmap(canvas.canvasitem): "/imagedataid load exch get }")) # select string from array if self.PSstoreimage: registry.add(PSimagedata(self.PSimagename, self.data, self.PSsinglestring, self.PSmaxstrlen)) + bbox += self.bbox() file.write("gsave\n") if self.palettedata is not None: @@ -418,12 +419,13 @@ class bitmap(canvas.canvasitem): file.write("grestore\n") - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): registry.add(PDFimage(self.PDFimagename, self.imagewidth, self.imageheight, self.palettecolorspace, self.palettedata, self.colorspace, 8, self.compressmode, self.data, registry)) + bbox += self.bbox() file.write("q\n") - self.imagematrixPDF.outputPDF(file, writer, context, registry) + self.imagematrixPDF.processPDF(file, writer, context, registry, bbox) file.write("/%s Do\n" % self.PDFimagename) file.write("Q\n") diff --git a/pyx/canvas.py b/pyx/canvas.py index e3a70cdf..35d4137e 100644 --- a/pyx/canvas.py +++ b/pyx/canvas.py @@ -2,8 +2,8 @@ # -*- coding: ISO-8859-1 -*- # # -# Copyright (C) 2002-2005 Jörg Lehmann -# Copyright (C) 2002-2005 André Wobst +# Copyright (C) 2002-2006 Jörg Lehmann +# Copyright (C) 2002-2006 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # @@ -35,38 +35,40 @@ class canvasitem: """Base class for everything which can be inserted into a canvas""" def bbox(self): - """return bounding box of canvasitem or None""" + """return bounding box of canvasitem""" pass - - def outputPS(self, file, writer, context, registry): - """write PS code corresponding to canvasitem to file + + def processPS(self, file, writer, context, registry, bbox): + """write PS code corresponding to canvasitem to file and update context, + registry as well as bbox - file has to provide a write(string) method - writer is the PSwriter used for the output - context is used for keeping track of the graphics state, in particular for the emulation of PS behaviour regarding fill and stroke styles, for keeping track of the currently selected font as well as of text regions. - - registry is used for tracking resources needed + - registry is used for tracking resources needed + - bbox is used to keep track of the bounding box of the processed items """ pass - def outputPDF(self, file, writer, context, registry): - """write PDF code corresponding to canvasitem to file using the given writer - and context. + def processPDF(self, file, writer, context, registry, bbox): + """write PDF code corresponding to canvasitem to file and update context, + registry as well as bbox - file has to provide a write(string) method - writer contains properties like whether streamcompression is used. - context is used for keeping track of the graphics state, in particular for the emulation of PS behaviour regarding fill and stroke styles, for keeping track of the currently selected font as well as of text regions. - - registry is used for tracking resources needed + - registry is used for tracking resources needed + - bbox is used to keep track of the bounding box of the processed items """ pass - - import attr, deco, deformer, document, style, trafo, type1font +import bbox as bboxmodule # @@ -83,19 +85,19 @@ class clip(canvasitem): def bbox(self): # as a canvasitem a clipping path has NO influence on the bbox... - return None + return bboxmodule.empty() def clipbbox(self): # ... but for clipping, we nevertheless need the bbox return self.path.bbox() - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): file.write("newpath\n") - self.path.outputPS(file, writer, context, registry) + self.path.outputPS(file, writer) file.write("clip\n") - def outputPDF(self, file, writer, context, registry): - self.path.outputPDF(file, writer, context, registry) + def processPDF(self, file, writer, context, registry, bbox): + self.path.outputPDF(file, writer) file.write("W n\n") @@ -155,48 +157,42 @@ class _canvas(canvasitem): return self.items[i] def bbox(self): - """returns bounding box of canvas""" - obbox = None + """returns bounding box of canvas + + Note that this bounding box doesn't take into account the linewidths, so + is less accurate than the one used when writing the output to a file. + """ + obbox = bboxmodule.empty() for cmd in self.items: - abbox = cmd.bbox() - if obbox is None: - obbox = abbox - elif abbox is not None: - obbox += abbox + obbox += cmd.bbox() # transform according to our global transformation and # intersect with clipping bounding box (which has already been # transformed in canvas.__init__()) - if obbox is not None: - obbox.transform(self.trafo) - if self.clipbbox is not None: - obbox *= self.clipbbox + obbox.transform(self.trafo) + if self.clipbbox is not None: + obbox *= self.clipbbox return obbox - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): context = context() if self.items: file.write("gsave\n") - origbbox = registry.bbox - registry.bbox = None + nbbox = bboxmodule.empty() for item in self.items: - item.outputPS(file, writer, context, registry) - if registry.bbox is not None: - registry.bbox.transform(self.trafo) - if self.clipbbox is not None: - registry.bbox *= self.clipbbox - if origbbox: - registry.bbox += origbbox - else: - registry.bbox = origbbox + item.processPS(file, writer, context, registry, nbbox) + # update bounding bbox + nbbox.transform(self.trafo) + if self.clipbbox is not None: + nbbox *= self.clipbbox + bbox += nbbox file.write("grestore\n") - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): context = context() if self.items: file.write("q\n") # gsave - origbbox = registry.bbox - registry.bbox = None + nbbox = bboxmodule.empty() for item in self.items: if isinstance(item, type1font.text_pt): if not context.textregion: @@ -207,19 +203,16 @@ class _canvas(canvasitem): file.write("ET\n") context.textregion = 0 context.font = None - item.outputPDF(file, writer, context, registry) + item.processPDF(file, writer, context, registry, nbbox) if context.textregion: file.write("ET\n") context.textregion = 0 context.font = None - if registry.bbox is not None: - registry.bbox.transform(self.trafo) - if self.clipbbox is not None: - registry.bbox *= self.clipbbox - if origbbox: - registry.bbox += origbbox - else: - registry.bbox = origbbox + # update bounding bbox + nbbox.transform(self.trafo) + if self.clipbbox is not None: + nbbox *= self.clipbbox + bbox += nbbox file.write("Q\n") # grestore def insert(self, item, attrs=None): diff --git a/pyx/color.py b/pyx/color.py index 334b9c09..a3819488 100644 --- a/pyx/color.py +++ b/pyx/color.py @@ -70,10 +70,10 @@ class grey(color): if gray<0 or gray>1: raise ValueError self.color = {"gray": gray} - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): file.write("%(gray)g setgray\n" % self.color) - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): if context.strokeattr: file.write("%(gray)f G\n" % self.color) if context.fillattr: @@ -106,10 +106,10 @@ class rgb(color): if r<0 or r>1 or g<0 or g>1 or b<0 or b>1: raise ValueError self.color = {"r": r, "g": g, "b": b} - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): file.write("%(r)g %(g)g %(b)g setrgbcolor\n" % self.color) - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): if context.strokeattr: file.write("%(r)f %(g)f %(b)f RG\n" % self.color) if context.fillattr: @@ -172,12 +172,12 @@ class hsb(color): if h<0 or h>1 or s<0 or s>1 or b<0 or b>1: raise ValueError self.color = {"h": h, "s": s, "b": b} - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): file.write("%(h)g %(s)g %(b)g sethsbcolor\n" % self.color) - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): r, g, b = colorsys.hsv_to_rgb(self.color["h"], self.color["s"], self.color["b"]) - rgb(r, g, b).outputPDF(file, writer, context, registry) + rgb(r, g, b).processPDF(file, writer, context, registry, bbox) def cmyk(self): return self.rgb().cmyk() @@ -217,10 +217,10 @@ class cmyk(color): if c<0 or c>1 or m<0 or m>1 or y<0 or y>1 or k<0 or k>1: raise ValueError self.color = {"c": c, "m": m, "y": y, "k": k} - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): file.write("%(c)g %(m)g %(y)g %(k)g setcmykcolor\n" % self.color) - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): if context.strokeattr: file.write("%(c)f %(m)f %(y)f %(k)f K\n" % self.color) if context.fillattr: @@ -340,11 +340,11 @@ class palette(color, attr.changeattr): param = index / (n_indices - 1.0) return self.getcolor(param) - def outputPS(self, file, writer, context, registry): - self.getcolor(0).outputPS(file, writer, context) + def processPS(self, file, writer, context, registry, bbox): + self.getcolor(0).processPS(file, writer, context) - def outputPDF(self, file, writer, context, registry): - self.getcolor(0).outputPDF(file, writer, context) + def processPDF(self, file, writer, context, registry, bbox): + self.getcolor(0).processPDF(file, writer, context) class linearpalette(palette): @@ -448,10 +448,10 @@ class transparency(attr.exclusiveattr, style.strokestyle, style.fillstyle): self.name = "Transparency-%f" % value self.extgstate = "<< /Type /ExtGState /CA %f /ca %f >>" % (value, value) - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): raise NotImplementedError("transparency not available in PostScript") - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): registry.add(PDFextgstate(self.name, self.extgstate)) file.write("/%s gs\n" % self.name) diff --git a/pyx/deco.py b/pyx/deco.py index 8e7241d3..91a7a251 100644 --- a/pyx/deco.py +++ b/pyx/deco.py @@ -2,9 +2,9 @@ # -*- coding: ISO-8859-1 -*- # # -# Copyright (C) 2002-2005 Jörg Lehmann +# Copyright (C) 2002-2006 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler -# Copyright (C) 2002-2005 André Wobst +# Copyright (C) 2002-2006 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # @@ -129,21 +129,21 @@ class decoratedpath(canvas.canvasitem): else: return self.path - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): # draw (stroke and/or fill) the decoratedpath on the canvas # while trying to produce an efficient output, e.g., by # not writing one path two times # small helper - def _writestyles(styles, context, registry): + def _writestyles(styles, context, registry, bbox): for style in styles: - style.outputPS(file, writer, context, registry) + style.processPS(file, writer, context, registry, bbox) if self.strokestyles is None and self.fillstyles is None: if not len(self.ornaments): raise RuntimeError("Path neither to be stroked nor filled nor decorated in another way") # just draw additional elements of decoratedpath - self.ornaments.outputPS(file, writer, context, registry) + self.ornaments.processPS(file, writer, context, registry, bbox) return strokepath = self.strokepath() @@ -153,18 +153,18 @@ class decoratedpath(canvas.canvasitem): if self.styles: file.write("gsave\n") context = context() - _writestyles(self.styles, context, registry) + _writestyles(self.styles, context, registry, bbox) if self.fillstyles is not None: file.write("newpath\n") - fillpath.outputPS(file, writer, context, registry) + fillpath.outputPS(file, writer) if self.strokestyles is not None and strokepath is fillpath: # do efficient stroking + filling if respective paths are identical file.write("gsave\n") if self.fillstyles: - _writestyles(self.fillstyles, context(), registry) + _writestyles(self.fillstyles, context(), registry, bbox) file.write("fill\n") file.write("grestore\n") @@ -172,15 +172,11 @@ class decoratedpath(canvas.canvasitem): acontext = context() if self.strokestyles: file.write("gsave\n") - _writestyles(self.strokestyles, acontext, registry) + _writestyles(self.strokestyles, acontext, registry, bbox) file.write("stroke\n") # take linewidth into account for bbox when stroking a path - abbox = fillpath.bbox().enlarged_pt(0.5*acontext.linewidth_pt) - if registry.bbox: - registry.bbox += abbox - else: - registry.bbox = abbox + bbox += strokepath.bbox().enlarged_pt(0.5*acontext.linewidth_pt) if self.strokestyles: file.write("grestore\n") @@ -188,14 +184,10 @@ class decoratedpath(canvas.canvasitem): # only fill fillpath - for the moment if self.fillstyles: file.write("gsave\n") - _writestyles(self.fillstyles, context(), registry) + _writestyles(self.fillstyles, context(), registry, bbox) file.write("fill\n") - abbox = fillpath.bbox() - if registry.bbox: - registry.bbox += abbox - else: - registry.bbox = abbox + bbox += fillpath.bbox() if self.fillstyles: file.write("grestore\n") @@ -206,55 +198,48 @@ class decoratedpath(canvas.canvasitem): acontext = context() if self.strokestyles: file.write("gsave\n") - _writestyles(self.strokestyles, acontext, registry) + _writestyles(self.strokestyles, acontext, registry, bbox) file.write("newpath\n") - strokepath.outputPS(file, writer, acontext, registry) + strokepath.outputPS(file, writer) file.write("stroke\n") # take linewidth into account for bbox when stroking a path - abbox = strokepath.bbox() - if abbox is not None: - abbox.enlarge_pt(0.5*acontext.linewidth_pt) - if registry.bbox: - if abbox is not None: - registry.bbox += abbox - else: - registry.bbox = abbox + bbox += strokepath.bbox().enlarged_pt(0.5*acontext.linewidth_pt) if self.strokestyles: file.write("grestore\n") # now, draw additional elements of decoratedpath - self.ornaments.outputPS(file, writer, context, registry) + self.ornaments.processPS(file, writer, context, registry, bbox) # restore global styles if self.styles: file.write("grestore\n") - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): # draw (stroke and/or fill) the decoratedpath on the canvas - def _writestyles(styles, context, registry): + def _writestyles(styles, context, registry, bbox): for style in styles: - style.outputPDF(file, writer, context, registry) + style.processPDF(file, writer, context, registry, bbox) - def _writestrokestyles(strokestyles, context, registry): + def _writestrokestyles(strokestyles, context, registry, bbox): context.fillattr = 0 for style in strokestyles: - style.outputPDF(file, writer, context, registry) + style.processPDF(file, writer, context, registry, bbox) context.fillattr = 1 - def _writefillstyles(fillstyles, context, registry): + def _writefillstyles(fillstyles, context, registry, bbox): context.strokeattr = 0 for style in fillstyles: - style.outputPDF(file, writer, context, registry) + style.processPDF(file, writer, context, registry, bbox) context.strokeattr = 1 if self.strokestyles is None and self.fillstyles is None: if not len(self.ornaments): raise RuntimeError("Path neither to be stroked nor filled nor decorated in another way") # just draw additional elements of decoratedpath - self.ornaments.outputPDF(file, writer, context, registry) + self.ornaments.processPDF(file, writer, context, registry, bbox) return strokepath = self.strokepath() @@ -264,10 +249,10 @@ class decoratedpath(canvas.canvasitem): if self.styles: file.write("q\n") # gsave context = context() - _writestyles(self.styles, context, registry) + _writestyles(self.styles, context, registry, bbox) if self.fillstyles is not None: - fillpath.outputPDF(file, writer, context, registry) + fillpath.outputPDF(file, writer) if self.strokestyles is not None and strokepath is fillpath: # do efficient stroking + filling @@ -275,31 +260,23 @@ class decoratedpath(canvas.canvasitem): acontext = context() if self.fillstyles: - _writefillstyles(self.fillstyles, acontext, registry) + _writefillstyles(self.fillstyles, acontext, registry, bbox) if self.strokestyles: - _writestrokestyles(self.strokestyles, acontext, registry) + _writestrokestyles(self.strokestyles, acontext, registry, bbox) file.write("B\n") # both stroke and fill # take linewidth into account for bbox when stroking a path - abbox = fillpath.bbox().enlarged_pt(0.5*acontext.linewidth_pt) - if registry.bbox: - registry.bbox += abbox - else: - registry.bbox = abbox + bbox += strokepath.bbox().enlarged_pt(0.5*acontext.linewidth_pt) file.write("Q\n") # grestore else: # only fill fillpath - for the moment if self.fillstyles: file.write("q\n") # gsave - _writefillstyles(self.fillstyles, context(), registry) + _writefillstyles(self.fillstyles, context(), registry, bbox) file.write("f\n") # fill - abbox = fillpath.bbox() - if registry.bbox: - registry.bbox += abbox - else: - registry.bbox = abbox + bbox += fillpath.bbox() if self.fillstyles: file.write("Q\n") # grestore @@ -311,25 +288,18 @@ class decoratedpath(canvas.canvasitem): if self.strokestyles: file.write("q\n") # gsave - _writestrokestyles(self.strokestyles, acontext, registry) + _writestrokestyles(self.strokestyles, acontext, registry, bbox) - strokepath.outputPDF(file, writer, context, registry) + strokepath.outputPDF(file, writer) file.write("S\n") # stroke # take linewidth into account for bbox when stroking a path - abbox = strokepath.bbox() - if abbox is not None: - abbox.enlarge_pt(0.5*acontext.linewidth_pt) - if registry.bbox: - if abbox is not None: - registry.bbox += abbox - else: - registry.bbox = abbox + bbox += strokepath.bbox().enlarged_pt(0.5*acontext.linewidth_pt) if self.strokestyles: file.write("Q\n") # grestore # now, draw additional elements of decoratedpath - self.ornaments.outputPDF(file, writer, context, registry) + self.ornaments.processPDF(file, writer, context, registry, bbox) # restore global styles if self.styles: diff --git a/pyx/document.py b/pyx/document.py index 1ba81ff1..31ee5b71 100644 --- a/pyx/document.py +++ b/pyx/document.py @@ -67,21 +67,27 @@ class page: self.bboxenlarge = bboxenlarge self.pagebbox = bbox - def outputPS(self, file, writer, context, registry): - self.canvas.outputPS(file, writer, context, registry) + def processPS(self, file, writer, context, registry, bbox): + self.canvas.processPS(file, writer, context, registry, bbox) # usually its the bbox of the canvas enlarged by self.bboxenlarge, but # it might be a different bbox as specified in the page constructor if self.pagebbox: - registry.bbox = self.pagebbox.copy() - elif registry.bbox: - registry.bbox.enlarge(self.bboxenlarge) + # we have to modify the bbox in place + # XXX maybe there should be a bbox.set/replace routine which accepts another bbox as argument + bbox.llx_pt = self.pagebbox.llx_pt + bbox.lly_pt = self.pagebbox.lly_pt + bbox.urx_pt = self.pagebbox.urx_pt + bbox.ury_pt = self.pagebbox.ury_pt + elif bbox: + bbox.enlarge(self.bboxenlarge) def pagetrafo(self, bbox): """ calculate a trafo which rotates and fits a canvas on the page The canvas extents are described by bbox. """ - if bbox and self.paperformat and (self.rotated or self.centered or self.fittosize): + # XXX should we provide a method for bbox != empty (or use __zero__) + if bbox.llx_pt is not None and self.paperformat and (self.rotated or self.centered or self.fittosize): paperwidth, paperheight = self.paperformat.width, self.paperformat.height # center (optionally rotated) output on page diff --git a/pyx/epsfile.py b/pyx/epsfile.py index d6dad74b..b92c30d8 100644 --- a/pyx/epsfile.py +++ b/pyx/epsfile.py @@ -2,8 +2,8 @@ # -*- coding: ISO-8859-1 -*- # # -# Copyright (C) 2002-2005 Jörg Lehmann -# Copyright (C) 2002-2005 André Wobst +# Copyright (C) 2002-2006 Jörg Lehmann +# Copyright (C) 2002-2006 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # @@ -313,9 +313,10 @@ class epsfile(canvas.canvasitem): def bbox(self): return self.mybbox.transformed(self.trafo) - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): registry.add(_BeginEPSF) registry.add(_EndEPSF) + bbox += self.bbox() try: epsfile=open(self.filename,"rb") except: @@ -327,12 +328,12 @@ class epsfile(canvas.canvasitem): llx_pt, lly_pt, urx_pt, ury_pt = self.mybbox.transformed(self.trafo).highrestuple_pt() file.write("%g %g %g %g rectclip\n" % (llx_pt, lly_pt, urx_pt-llx_pt, ury_pt-lly_pt)) - self.trafo.outputPS(file, writer, context, registry) + self.trafo.processPS(file, writer, context, registry, bbox) file.write("%%%%BeginDocument: %s\n" % self.filename) file.write(epsfile.read()) file.write("%%EndDocument\n") file.write("EndEPSF\n") - def outputPDF(self, file, writer, context, registry): - raise RuntimeError("Including EPS files in PDF files not supported") + def processPDF(self, file, writer, context, registry, bbox): + raise RuntimeError("Including EPS files in PDF files not supported") diff --git a/pyx/graph/graph.py b/pyx/graph/graph.py index 3958fb80..0fc116db 100644 --- a/pyx/graph/graph.py +++ b/pyx/graph/graph.py @@ -154,13 +154,13 @@ class graph(canvas.canvas): self.finish() canvas.canvas.registerPDF(self, registry) - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): self.finish() - canvas.canvas.outputPS(self, file, writer, context, registry) + canvas.canvas.processPS(self, file, writer, context, registry, bbox) - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): self.finish() - canvas.canvas.outputPDF(self, file, writer, context, registry) + canvas.canvas.processPDF(self, file, writer, context, registry, bbox) def plot(self, data, styles=None, rangewarning=1): if self.didranges and rangewarning: diff --git a/pyx/normpath.py b/pyx/normpath.py index e34516ec..17eff505 100644 --- a/pyx/normpath.py +++ b/pyx/normpath.py @@ -2,7 +2,7 @@ # -*- coding: ISO-8859-1 -*- # # -# Copyright (C) 2002-2005 Jörg Lehmann +# Copyright (C) 2002-2006 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler # Copyright (C) 2002-2006 André Wobst # @@ -32,7 +32,8 @@ except ImportError: def radians(x): return x*math.pi/180 def degrees(x): return x*180/math.pi -import bbox, canvas, mathutils, path, trafo, unit +import mathutils, path, trafo, unit +import bbox as bboxmodule try: sum([]) @@ -212,11 +213,11 @@ class normsubpathitem: """return transformed normsubpathitem according to trafo""" pass - def outputPS(self, file, writer, context, registry): + def outputPS(self, file, writer): """write PS code corresponding to normsubpathitem to file""" pass - def outputPDF(self, file, writer, context, registry): + def outputPDF(self, file, writer): """write PDF code corresponding to normsubpathitem to file""" pass @@ -259,8 +260,8 @@ class normline_pt(normsubpathitem): return self.x1_pt, self.y1_pt def bbox(self): - return bbox.bbox_pt(min(self.x0_pt, self.x1_pt), min(self.y0_pt, self.y1_pt), - max(self.x0_pt, self.x1_pt), max(self.y0_pt, self.y1_pt)) + return bboxmodule.bbox_pt(min(self.x0_pt, self.x1_pt), min(self.y0_pt, self.y1_pt), + max(self.x0_pt, self.x1_pt), max(self.y0_pt, self.y1_pt)) cbox = bbox @@ -340,10 +341,10 @@ class normline_pt(normsubpathitem): def transformed(self, trafo): return normline_pt(*(trafo.apply_pt(self.x0_pt, self.y0_pt) + trafo.apply_pt(self.x1_pt, self.y1_pt))) - def outputPS(self, file, writer, context, registry): + def outputPS(self, file, writer): file.write("%g %g lineto\n" % (self.x1_pt, self.y1_pt)) - def outputPDF(self, file, writer, context, registry): + def outputPDF(self, file, writer): file.write("%f %f l\n" % (self.x1_pt, self.y1_pt)) @@ -472,13 +473,13 @@ class normcurve_pt(normsubpathitem): def bbox(self): xmin_pt, xmax_pt = path._bezierpolyrange(self.x0_pt, self.x1_pt, self.x2_pt, self.x3_pt) ymin_pt, ymax_pt = path._bezierpolyrange(self.y0_pt, self.y1_pt, self.y2_pt, self.y3_pt) - return bbox.bbox_pt(xmin_pt, ymin_pt, xmax_pt, ymax_pt) + return bboxmodule.bbox_pt(xmin_pt, ymin_pt, xmax_pt, ymax_pt) def cbox(self): - return bbox.bbox_pt(min(self.x0_pt, self.x1_pt, self.x2_pt, self.x3_pt), - min(self.y0_pt, self.y1_pt, self.y2_pt, self.y3_pt), - max(self.x0_pt, self.x1_pt, self.x2_pt, self.x3_pt), - max(self.y0_pt, self.y1_pt, self.y2_pt, self.y3_pt)) + return bboxmodule.bbox_pt(min(self.x0_pt, self.x1_pt, self.x2_pt, self.x3_pt), + min(self.y0_pt, self.y1_pt, self.y2_pt, self.y3_pt), + max(self.x0_pt, self.x1_pt, self.x2_pt, self.x3_pt), + max(self.y0_pt, self.y1_pt, self.y2_pt, self.y3_pt)) def curvature_pt(self, params): result = [] @@ -665,10 +666,10 @@ class normcurve_pt(normsubpathitem): x3_pt, y3_pt = trafo.apply_pt(self.x3_pt, self.y3_pt) return normcurve_pt(x0_pt, y0_pt, x1_pt, y1_pt, x2_pt, y2_pt, x3_pt, y3_pt) - def outputPS(self, file, writer, context, registry): + def outputPS(self, file, writer): file.write("%g %g %g %g %g %g curveto\n" % (self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.x3_pt, self.y3_pt)) - def outputPDF(self, file, writer, context, registry): + def outputPDF(self, file, writer): file.write("%f %f %f %f %f %f c\n" % (self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.x3_pt, self.y3_pt)) def x_pt(self, t): @@ -938,7 +939,7 @@ class normsubpath: abbox += anormpathitem.bbox() return abbox else: - return None + return bboxmodule.empty() def close(self): """close subnormpath @@ -1303,7 +1304,7 @@ class normsubpath: nnormsubpath.append(self.skippedline.transformed(trafo)) return nnormsubpath - def outputPS(self, file, writer, context, registry): + def outputPS(self, file, writer): # if the normsubpath is closed, we must not output a normline at # the end if not self.normsubpathitems: @@ -1315,11 +1316,11 @@ class normsubpath: normsubpathitems = self.normsubpathitems file.write("%g %g moveto\n" % self.atbegin_pt()) for anormsubpathitem in normsubpathitems: - anormsubpathitem.outputPS(file, writer, context, registry) + anormsubpathitem.outputPS(file, writer) if self.closed: file.write("closepath\n") - def outputPDF(self, file, writer, context, registry): + def outputPDF(self, file, writer): # if the normsubpath is closed, we must not output a normline at # the end if not self.normsubpathitems: @@ -1331,7 +1332,7 @@ class normsubpath: normsubpathitems = self.normsubpathitems file.write("%f %f m\n" % self.atbegin_pt()) for anormsubpathitem in normsubpathitems: - anormsubpathitem.outputPDF(file, writer, context, registry) + anormsubpathitem.outputPDF(file, writer) if self.closed: file.write("h\n") @@ -1419,7 +1420,7 @@ def _valueorlistmethod(method): return wrappedmethod -class normpath(canvas.canvasitem): +class normpath: """normalized path @@ -1594,13 +1595,9 @@ class normpath(canvas.canvasitem): def bbox(self): """return bbox of normpath""" - abbox = None + abbox = bboxmodule.empty() for normsubpath in self.normsubpaths: - nbbox = normsubpath.bbox() - if abbox is None: - abbox = nbbox - elif nbbox: - abbox += nbbox + abbox += normsubpath.bbox() return abbox def begin(self): @@ -1917,10 +1914,10 @@ class normpath(canvas.canvasitem): """return transformed normpath""" return normpath([normsubpath.transformed(trafo) for normsubpath in self.normsubpaths]) - def outputPS(self, file, writer, context, registry): + def outputPS(self, file, writer): for normsubpath in self.normsubpaths: - normsubpath.outputPS(file, writer, context, registry) + normsubpath.outputPS(file, writer) - def outputPDF(self, file, writer, context, registry): + def outputPDF(self, file, writer): for normsubpath in self.normsubpaths: - normsubpath.outputPDF(file, writer, context, registry) + normsubpath.outputPDF(file, writer) diff --git a/pyx/path.py b/pyx/path.py index b8ebdd1f..6495c5da 100755 --- a/pyx/path.py +++ b/pyx/path.py @@ -2,9 +2,9 @@ # -*- coding: ISO-8859-1 -*- # # -# Copyright (C) 2002-2005 Jörg Lehmann +# Copyright (C) 2002-2006 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler -# Copyright (C) 2002-2005 André Wobst +# Copyright (C) 2002-2006 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # @@ -33,8 +33,9 @@ except ImportError: def radians(x): return x*pi/180 def degrees(x): return x*180/pi -import bbox, canvas, trafo, unit +import trafo, unit from normpath import NormpathException, normpath, normsubpath, normline_pt, normcurve_pt +import bbox as bboxmodule # set is available as an external interface to the normpath.set method from normpath import set @@ -291,7 +292,7 @@ class pathitem: """ raise NotImplementedError() - def outputPS(self, file): + def outputPS(self, file, writer): """write PS representation of pathitem to file""" @@ -323,7 +324,7 @@ class closepath(pathitem): context.x_pt = context.subfirstx_pt context.y_pt = context.subfirsty_pt - def outputPS(self, file): + def outputPS(self, file, writer): file.write("closepath\n") @@ -344,7 +345,7 @@ class moveto_pt(pathitem): return context(self.x_pt, self.y_pt, self.x_pt, self.y_pt) def createbbox(self): - return bbox.bbox_pt(self.x_pt, self.y_pt, self.x_pt, self.y_pt) + return bboxmodule.bbox_pt(self.x_pt, self.y_pt, self.x_pt, self.y_pt) def createnormpath(self, epsilon=_marker): if epsilon is _marker: @@ -367,7 +368,7 @@ class moveto_pt(pathitem): context.x_pt = context.subfirstx_pt = self.x_pt context.y_pt = context.subfirsty_pt = self.y_pt - def outputPS(self, file): + def outputPS(self, file, writer): file.write("%g %g moveto\n" % (self.x_pt, self.y_pt) ) @@ -395,7 +396,7 @@ class lineto_pt(pathitem): context.x_pt = self.x_pt context.y_pt = self.y_pt - def outputPS(self, file): + def outputPS(self, file, writer): file.write("%g %g lineto\n" % (self.x_pt, self.y_pt) ) @@ -434,7 +435,7 @@ class curveto_pt(pathitem): context.x_pt = self.x3_pt context.y_pt = self.y3_pt - def outputPS(self, file): + def outputPS(self, file, writer): file.write("%g %g %g %g %g %g curveto\n" % (self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.x3_pt, self.y3_pt)) @@ -472,7 +473,7 @@ class rmoveto_pt(pathitem): else: normpath.append(normsubpath(epsilon=normpath.normsubpaths[-1].epsilon)) - def outputPS(self, file): + def outputPS(self, file, writer): file.write("%g %g rmoveto\n" % (self.dx_pt, self.dy_pt) ) @@ -500,7 +501,7 @@ class rlineto_pt(pathitem): context.x_pt += self.dx_pt context.y_pt += self.dy_pt - def outputPS(self, file): + def outputPS(self, file, writer): file.write("%g %g rlineto\n" % (self.dx_pt, self.dy_pt) ) @@ -545,7 +546,7 @@ class rcurveto_pt(pathitem): context.x_pt += self.dx3_pt context.y_pt += self.dy3_pt - def outputPS(self, file): + def outputPS(self, file, writer): file.write("%g %g %g %g %g %g rcurveto\n" % (self.dx1_pt, self.dy1_pt, self.dx2_pt, self.dy2_pt, self.dx3_pt, self.dy3_pt)) @@ -573,8 +574,8 @@ class arc_pt(pathitem): return context(x_pt, y_pt, x_pt, y_pt) def createbbox(self): - return bbox.bbox_pt(*_arcbboxdata(self.x_pt, self.y_pt, self.r_pt, - self.angle1, self.angle2)) + return bboxmodule.bbox_pt(*_arcbboxdata(self.x_pt, self.y_pt, self.r_pt, + self.angle1, self.angle2)) def createnormpath(self, epsilon=_marker): if epsilon is _marker: @@ -601,7 +602,7 @@ class arc_pt(pathitem): normpath.normsubpaths[-1].extend(_arctobezierpath(self.x_pt, self.y_pt, self.r_pt, self.angle1, self.angle2)) context.x_pt, context.y_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle2) - def outputPS(self, file): + def outputPS(self, file, writer): file.write("%g %g %g %g %g arc\n" % (self.x_pt, self.y_pt, self.r_pt, self.angle1, @@ -630,8 +631,8 @@ class arcn_pt(pathitem): return context(x_pt, y_pt, x_pt, y_pt) def createbbox(self): - return bbox.bbox_pt(*_arcbboxdata(self.x_pt, self.y_pt, self.r_pt, - self.angle2, self.angle1)) + return bboxmodule.bbox_pt(*_arcbboxdata(self.x_pt, self.y_pt, self.r_pt, + self.angle2, self.angle1)) def createnormpath(self, epsilon=_marker): if epsilon is _marker: @@ -661,7 +662,7 @@ class arcn_pt(pathitem): normpath.normsubpaths[-1].append(bpathitem.reversed()) context.x_pt, context.y_pt = _arcpoint(self.x_pt, self.y_pt, self.r_pt, self.angle2) - def outputPS(self, file): + def outputPS(self, file, writer): file.write("%g %g %g %g %g arcn\n" % (self.x_pt, self.y_pt, self.r_pt, self.angle1, @@ -756,7 +757,7 @@ class arct_pt(pathitem): for pathitem in self._pathitems(context.x_pt, context.y_pt): pathitem.updatenormpath(normpath, context) - def outputPS(self, file): + def outputPS(self, file, writer): file.write("%g %g %g %g %g arct\n" % (self.x1_pt, self.y1_pt, self.x2_pt, self.y2_pt, self.r_pt)) @@ -892,7 +893,7 @@ class multilineto_pt(pathitem): x0_pt, y0_pt = point_pt context.x_pt, context.y_pt = x0_pt, y0_pt - def outputPS(self, file): + def outputPS(self, file, writer): for point_pt in self.points_pt: file.write("%g %g lineto\n" % point_pt ) @@ -927,7 +928,7 @@ class multicurveto_pt(pathitem): x0_pt, y0_pt = point_pt[4:] context.x_pt, context.y_pt = x0_pt, y0_pt - def outputPS(self, file): + def outputPS(self, file, writer): for point_pt in self.points_pt: file.write("%g %g %g %g %g %g curveto\n" % point_pt) @@ -936,7 +937,7 @@ class multicurveto_pt(pathitem): # path: PS style path ################################################################################ -class path(canvas.canvasitem): +class path: """PS style path""" @@ -1033,7 +1034,7 @@ class path(canvas.canvasitem): pathitem.updatebbox(bbox, context) return bbox else: - return None + return bboxmodule.empty() def begin(self): """return param corresponding of the beginning of the path""" @@ -1175,17 +1176,17 @@ class path(canvas.canvasitem): """return transformed path""" return self.normpath().transformed(trafo) - def outputPS(self, file, writer, context, registry): + def outputPS(self, file, writer): """write PS code to file""" for pitem in self.pathitems: - pitem.outputPS(file) + pitem.outputPS(file, writer) - def outputPDF(self, file, writer, context, registry): + def outputPDF(self, file, writer): """write PDF code to file""" # PDF only supports normsubpathitems; we need to use a normpath # with epsilon equals None to prevent failure for paths shorter # than epsilon - self.normpath(epsilon=None).outputPDF(file, writer, context, registry) + self.normpath(epsilon=None).outputPDF(file, writer) # diff --git a/pyx/pattern.py b/pyx/pattern.py index 542a7c59..48b90655 100644 --- a/pyx/pattern.py +++ b/pyx/pattern.py @@ -2,7 +2,7 @@ # -*- coding: ISO-8859-1 -*- # # -# Copyright (C) 2002-2005 Jörg Lehmann +# Copyright (C) 2002-2006 Jörg Lehmann # Copyright (C) 2002-2005 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). @@ -25,6 +25,7 @@ from __future__ import nested_scopes import cStringIO, math, warnings import attr, canvas, path, pdfwriter, pswriter, style, unit, trafo +import bbox as bboxmodule class _marker: pass @@ -65,12 +66,72 @@ class pattern(canvas._canvas, attr.exclusiveattr, style.fillstyle): return pattern(painttype, tilingtype, xstep, ystep, bbox, trafo) def bbox(self): - return None - - def outputPS(self, file, writer, context): + return bboxmodule.empty() + + def processPS(self, file, writer, context, registry, bbox): + # process pattern, letting it register its resources and calculate the bbox of the pattern + patternfile = cStringIO.StringIO() + realpatternbbox = bboxmodule.empty() + canvas._canvas.processPS(self, patternfile, writer, pswriter.context(), registry, realpatternbbox) + patternproc = patternfile.getvalue() + patternfile.close() + + if self.xstep is None: + xstep = unit.topt(realpatternbbox.width()) + else: + xstep = unit.topt(self.xstep) + if self.ystep is None: + ystep = unit.topt(realpatternbbox.height()) + else: + ystep = unit.topt(self.ystep) + if not xstep: + raise ValueError("xstep in pattern cannot be zero") + if not ystep: + raise ValueError("ystep in pattern cannot be zero") + patternbbox = self.patternbbox or realpatternbbox.enlarged(5*unit.pt) + + patternprefix = "\n".join(("<<", + "/PatternType %d" % self.patterntype, + "/PaintType %d" % self.painttype, + "/TilingType %d" % self.tilingtype, + "/BBox[%d %d %d %d]" % patternbbox.lowrestuple_pt(), + "/XStep %g" % xstep, + "/YStep %g" % ystep, + "/PaintProc {\nbegin\n")) + patterntrafostring = self.patterntrafo is None and "matrix" or str(self.patterntrafo) + patternsuffix = "end\n} bind\n>>\n%s\nmakepattern" % patterntrafostring + + registry.add(pswriter.PSdefinition(self.id, "".join((patternprefix, patternproc, patternsuffix)))) + + # activate pattern file.write("%s setpattern\n" % self.id) - def outputPDF(self, file, writer, context): + def processPDF(self, file, writer, context, registry, bbox): + patternfile = cStringIO.StringIO() + realpatternbbox = bboxmodule.empty() + canvas._canvas.processPDF(self, patternfile, writer, pdfwriter.context(), registry, realpatternbbox) + patternproc = patternfile.getvalue() + patternfile.close() + if self.xstep is None: + xstep = unit.topt(realpatternbbox.width()) + else: + xstep = unit.topt(self.xstep) + if self.ystep is None: + ystep = unit.topt(realpatternbbox.height()) + else: + ystep = unit.topt(self.ystep) + if not xstep: + raise ValueError("xstep in pattern cannot be zero") + if not ystep: + raise ValueError("ystep in pattern cannot be zero") + patternbbox = self.patternbbox or realpatternbbox.enlarged(5*unit.pt) + patterntrafo = self.patterntrafo or trafo.trafo() + + registry.add(PDFpattern(self.id, self.patterntype, self.painttype, self.tilingtype, + patternbbox, xstep, ystep, patterntrafo, + patternproc, registry)) + + # activate pattern if context.colorspace != "Pattern": # we only set the fill color space (see next comment) file.write("/Pattern cs\n") @@ -82,64 +143,6 @@ class pattern(canvas._canvas, attr.exclusiveattr, style.fillstyle): if context.fillattr: file.write("/%s scn\n"% self.id) -# def registerPS(self, registry): -# canvas._canvas.registerPS(self, registry) -# realpatternbbox = canvas._canvas.bbox(self) -# if self.xstep is None: -# xstep = unit.topt(realpatternbbox.width()) -# else: -# xstep = unit.topt(self.xstep) -# if self.ystep is None: -# ystep = unit.topt(realpatternbbox.height()) -# else: -# ystep = unit.topt(self.ystep) -# if not xstep: -# raise ValueError("xstep in pattern cannot be zero") -# if not ystep: -# raise ValueError("ystep in pattern cannot be zero") -# patternbbox = self.patternbbox or realpatternbbox.enlarged(5*unit.pt) - -# patternprefix = "\n".join(("<<", -# "/PatternType %d" % self.patterntype, -# "/PaintType %d" % self.painttype, -# "/TilingType %d" % self.tilingtype, -# "/BBox[%d %d %d %d]" % patternbbox.lowrestuple_pt(), -# "/XStep %g" % xstep, -# "/YStep %g" % ystep, -# "/PaintProc {\nbegin\n")) -# stringfile = cStringIO.StringIO() -# # XXX here, we have a problem since the writer is not definined at that point -# # for the moment, we just path None since we do not use it anyway -# canvas._canvas.outputPS(self, stringfile, None, pswriter.context()) -# patternproc = stringfile.getvalue() -# stringfile.close() -# patterntrafostring = self.patterntrafo is None and "matrix" or str(self.patterntrafo) -# patternsuffix = "end\n} bind\n>>\n%s\nmakepattern" % patterntrafostring - -# registry.add(pswriter.PSdefinition(self.id, "".join((patternprefix, patternproc, patternsuffix)))) - -# def registerPDF(self, registry): -# realpatternbbox = canvas._canvas.bbox(self) -# if self.xstep is None: -# xstep = unit.topt(realpatternbbox.width()) -# else: -# xstep = unit.topt(self.xstep) -# if self.ystep is None: -# ystep = unit.topt(realpatternbbox.height()) -# else: -# ystep = unit.topt(self.ystep) -# if not xstep: -# raise ValueError("xstep in pattern cannot be zero") -# if not ystep: -# raise ValueError("ystep in pattern cannot be zero") -# patternbbox = self.patternbbox or realpatternbbox.enlarged(5*unit.pt) -# patterntrafo = self.patterntrafo or trafo.trafo() - -# registry.add(PDFpattern(self.id, self.patterntype, self.painttype, self.tilingtype, -# patternbbox, xstep, ystep, patterntrafo, -# lambda file, writer, context: canvas._canvas.outputPDF(self, file, writer, context()), -# lambda registry: canvas._canvas.registerPDF(self, registry), -# registry)) pattern.clear = attr.clearclass(pattern) @@ -279,7 +282,7 @@ crosshatched45.LARGE = crosshatched45(_base*math.sqrt(64)) class PDFpattern(pdfwriter.PDFobject): def __init__(self, name, patterntype, painttype, tilingtype, bbox, xstep, ystep, trafo, - canvasoutputPDF, canvasregisterPDF, registry): + patternproc, registry): pdfwriter.PDFobject.__init__(self, "pattern", name, "Pattern") self.name = name self.patterntype = patterntype @@ -289,18 +292,19 @@ class PDFpattern(pdfwriter.PDFobject): self.xstep = xstep self.ystep = ystep self.trafo = trafo - self.canvasoutputPDF = canvasoutputPDF + self.patternproc = patternproc + #self.canvasoutputPDF = canvasoutputPDF self.contentlength = pdfwriter.PDFcontentlength((self.type, self.id)) registry.add(self.contentlength) - # we need to keep track of the resources used by the pattern, hence - # we create our own registry, which we merge immediately in the main registry - self.patternregistry = pdfwriter.PDFregistry() - # XXX passing canvasregisterPDF is a Q&D way to get access to the registerPDF method - # of the _canvas superclass of the pattern - canvasregisterPDF(self.patternregistry) - registry.mergeregistry(self.patternregistry) + # # we need to keep track of the resources used by the pattern, hence + # # we create our own registry, which we merge immediately in the main registry + # self.patternregistry = pdfwriter.PDFregistry() + # # XXX passing canvasregisterPDF is a Q&D way to get access to the registerPDF method + # # of the _canvas superclass of the pattern + # canvasregisterPDF(self.patternregistry) + # registry.mergeregistry(self.patternregistry) def outputPDF(self, file, writer, registry): file.write("<<\n" @@ -339,8 +343,7 @@ class PDFpattern(pdfwriter.PDFobject): else: stream = file - acontext = pdfwriter.context() - self.canvasoutputPDF(stream, writer, acontext) + stream.write(self.patternproc) if writer.compress: stream.flush() diff --git a/pyx/pdfwriter.py b/pyx/pdfwriter.py index ea90df83..a15954f6 100644 --- a/pyx/pdfwriter.py +++ b/pyx/pdfwriter.py @@ -2,8 +2,8 @@ # -*- coding: ISO-8859-1 -*- # # -# Copyright (C) 2005 Jörg Lehmann -# Copyright (C) 2005 André Wobst +# Copyright (C) 2005-2006 Jörg Lehmann +# Copyright (C) 2005-2006 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # @@ -28,7 +28,7 @@ try: except: haszlib = 0 -import unit, style, type1font, version +import bbox, unit, style, type1font, version try: enumerate([]) @@ -61,11 +61,6 @@ class PDFregistry: def mergeregistry(self, registry): for resource in registry.resources: self.add(resource) - if self.bbox: - if registry.bbox: - self.bbox += registry.bbox - else: - self.bbox = registry.bbox def write(self, file, writer, catalog): # first we set all refnos @@ -219,13 +214,10 @@ class PDFpage(PDFobject): # resources are used within the page. However, the # pageregistry is also merged in the global registry self.pageregistry = PDFregistry() + self.bbox = bbox.empty() - self.PDFcontent = PDFcontent(self, writer, self.pageregistry) + self.PDFcontent = PDFcontent(self, writer, self.pageregistry, self.bbox) self.pageregistry.add(self.PDFcontent) - if self.pageregistry.bbox is not None: - self.bbox = self.pageregistry.bbox.copy() - else: - self.bbox = None registry.mergeregistry(self.pageregistry) self.pagetrafo = page.pagetrafo(self.bbox) @@ -265,7 +257,7 @@ class PDFpage(PDFobject): class PDFcontent(PDFobject): - def __init__(self, PDFpage, writer, registry): + def __init__(self, PDFpage, writer, registry, bbox): PDFobject.__init__(self, "content") self.PDFpage = PDFpage @@ -275,15 +267,15 @@ class PDFcontent(PDFobject): # set more info in the content dict) reuse PDFcontent for # patterns acontext = context() - style.linewidth.normal.outputPDF(self.contentfile, writer, acontext, registry) + style.linewidth.normal.processPDF(self.contentfile, writer, acontext, registry, bbox) - self.PDFpage.page.canvas.outputPDF(self.contentfile, writer, acontext, registry) + self.PDFpage.page.canvas.processPDF(self.contentfile, writer, acontext, registry, bbox) def output(self, file, writer, registry): # apply a possible global transformation if self.PDFpage.pagetrafo: pagetrafofile = cStringIO.StringIO() - self.PDFpage.pagetrafo.outputPDF(pagetrafofile, writer, context(), registry) + self.PDFpage.pagetrafo.processPDF(pagetrafofile, writer, context(), registry, bbox.empty()) content = pagetrafofile.getvalue() + self.contentfile.getvalue() else: content = self.contentfile.getvalue() diff --git a/pyx/pswriter.py b/pyx/pswriter.py index b9c58a45..bc80a7b8 100644 --- a/pyx/pswriter.py +++ b/pyx/pswriter.py @@ -2,8 +2,8 @@ # -*- coding: ISO-8859-1 -*- # # -# Copyright (C) 2005 Jörg Lehmann -# Copyright (C) 2005 André Wobst +# Copyright (C) 2005-2006 Jörg Lehmann +# Copyright (C) 2005-2006 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # @@ -22,7 +22,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import cStringIO, copy, time, math -import style, version, type1font, unit +import bbox, style, version, type1font, unit try: enumerate([]) @@ -41,7 +41,6 @@ class PSregistry: # kept) self.resourceshash = {} self.resourceslist = [] - self.bbox = None def add(self, resource): rkey = (resource.type, resource.id) @@ -54,16 +53,11 @@ class PSregistry: def mergeregistry(self, registry): for resource in registry.resources: self.add(resource) - if self.bbox: - if registry.bbox: - self.bbox += registry.bbox - else: - self.bbox = registry.bbox - def outputPS(self, file, writer): + def output(self, file, writer): """ write all PostScript code of the prolog resources """ for resource in self.resourceslist: - resource.outputPS(file, writer, self) + resource.output(file, writer, self) # # Abstract base class @@ -85,8 +79,8 @@ class PSresource: the same id""" pass - def outputPS(self, file, writer, registry): - raise NotImplementedError("outputPS not implemented for %s" % repr(self)) + def output(self, file, writer, registry): + raise NotImplementedError("output not implemented for %s" % repr(self)) # # Different variants of prolog items @@ -101,7 +95,7 @@ class PSdefinition(PSresource): self.id = id self.body = body - def outputPS(self, file, writer, registry): + def output(self, file, writer, registry): file.write("%%%%BeginRessource: %s\n" % self.id) file.write("%(body)s /%(id)s exch def\n" % self.__dict__) file.write("%%EndRessource\n") @@ -160,7 +154,7 @@ class PSfontfile(PSresource): # TODO: need to resolve the encoding when several encodings are in the play self.strip = 0 - def outputPS(self, file, writer, registry): + def output(self, file, writer, registry): import font.t1font font = font.t1font.T1pfbfont(self.filename) @@ -192,7 +186,7 @@ class PSfontencoding(PSresource): self.id = encoding.name self.encoding = encoding - def outputPS(self, file, writer, registry): + def output(self, file, writer, registry): encodingfile = type1font.encodingfile(self.encoding.name, self.encoding.filename) encodingfile.outputPS(file, writer) @@ -219,7 +213,7 @@ class PSfontreencoding(PSresource): self.basefontname = basefontname self.encodingname = encodingname - def outputPS(self, file, writer, registry): + def output(self, file, writer, registry): file.write("%%%%BeginProcSet: %s\n" % self.fontname) file.write("/%s /%s %s ReEncodeFont\n" % (self.basefontname, self.fontname, self.encodingname)) file.write("%%EndProcSet\n") @@ -264,24 +258,24 @@ class epswriter: canvasfile = cStringIO.StringIO() registry = PSregistry() acontext = context() + abbox = bbox.empty() - style.linewidth.normal.outputPS(file, self, acontext, registry) + style.linewidth.normal.processPS(canvasfile, self, acontext, registry, abbox) # here comes the page content - page.outputPS(canvasfile, self, acontext, registry) + page.processPS(canvasfile, self, acontext, registry, abbox) - bbox = registry.bbox - pagetrafo = page.pagetrafo(bbox) + pagetrafo = page.pagetrafo(abbox) # if a page transformation is necessary, we have to adjust the bounding box # accordingly if pagetrafo is not None: - bbox.transform(pagetrafo) + abbox.transform(pagetrafo) file.write("%!PS-Adobe-3.0 EPSF-3.0\n") if bbox: - file.write("%%%%BoundingBox: %d %d %d %d\n" % bbox.lowrestuple_pt()) - file.write("%%%%HiResBoundingBox: %g %g %g %g\n" % bbox.highrestuple_pt()) + file.write("%%%%BoundingBox: %d %d %d %d\n" % abbox.lowrestuple_pt()) + file.write("%%%%HiResBoundingBox: %g %g %g %g\n" % abbox.highrestuple_pt()) file.write("%%%%Creator: PyX %s\n" % version.version) file.write("%%%%Title: %s\n" % filename) file.write("%%%%CreationDate: %s\n" % @@ -289,12 +283,12 @@ class epswriter: file.write("%%EndComments\n") file.write("%%BeginProlog\n") - registry.outputPS(file, self) + registry.output(file, self) file.write("%%EndProlog\n") # apply a possible page transformation (using fake context and registry) if pagetrafo: - pagetrafo.outputPS(file, self, context(), PSregistry()) + pagetrafo.processPS(file, self, context(), PSregistry(), abbox) file.write(canvasfile.getvalue()) @@ -313,23 +307,54 @@ class pswriter: except IOError: raise IOError("cannot open output file") - # calculated bounding boxes of separate pages and the bounding box of the whole document - documentbbox = None - for page in document.pages: - canvas = page.canvas - page._bbox = page.bbox() - page._pagetrafo = page.pagetrafo(page._bbox) + + # We first have to process the content of the pages, writing them into the stream pagesfile + # Doing so, we fill the registry and also calculate the page bounding boxes, which are + # stored in page._bbox for every page + pagesfile = cStringIO.StringIO() + registry = PSregistry() + + # calculated bounding boxes of the whole document + documentbbox = bbox.empty() + + for nr, page in enumerate(document.pages): + # process conents of page + pagefile = cStringIO.StringIO() + acontext = context() + pagebbox = bbox.empty() + style.linewidth.normal.processPS(pagefile, self, acontext, registry, pagebbox) + page.canvas.processPS(pagefile, self, acontext, registry, pagebbox) + + # calculate transformed bbox + pagetrafo = page.pagetrafo(pagebbox) # if a page transformation is necessary, we have to adjust the bounding box # accordingly - if page._pagetrafo: - page._transformedbbox = page._bbox.transformed(page._pagetrafo) - else: - page._transformedbbox = page._bbox - if page._transformedbbox: - if documentbbox: - documentbbox += page._transformedbbox - else: - documentbbox = page._transformedbbox.copy() # make a copy + if pagetrafo: + pagebbox = pagebbox.transformed(pagetrafo) + + documentbbox += pagebbox + + pagesfile.write("%%%%Page: %s %d\n" % (page.pagename is None and str(nr+1) or page.pagename, nr+1)) + if page.paperformat: + pagesfile.write("%%%%PageMedia: %s\n" % page.paperformat.name) + pagesfile.write("%%%%PageOrientation: %s\n" % (page.rotated and "Landscape" or "Portrait")) + if pagebbox and writebbox: + pagesfile.write("%%%%PageBoundingBox: %d %d %d %d\n" % pagebbox.lowrestuple_pt()) + + # page setup section + pagesfile.write("%%BeginPageSetup\n") + pagesfile.write("/pgsave save def\n") + + # apply a possible page transformation + if pagetrafo is not None: + pagetrafo.processPS(pagesfile, self, acontext, registry, bbox.empty()) + + pagesfile.write("%%EndPageSetup\n") + # insert page content + pagesfile.write(pagefile.getvalue()) + pagesfile.write("pgsave restore\n") + pagesfile.write("showpage\n") + pagesfile.write("%%PageTrailer\n") file.write("%!PS-Adobe-3.0\n") if documentbbox and writebbox: @@ -367,39 +392,9 @@ class pswriter: #file.write("%%BeginDefaults\n") #file.write("%%EndDefaults\n") - pagesfile = cStringIO.StringIO() - registry = PSregistry() - - # pages section - for nr, page in enumerate(document.pages): - pagesfile.write("%%%%Page: %s %d\n" % (page.pagename is None and str(nr+1) or page.pagename, nr+1)) - if page.paperformat: - pagesfile.write("%%%%PageMedia: %s\n" % page.paperformat.name) - pagesfile.write("%%%%PageOrientation: %s\n" % (page.rotated and "Landscape" or "Portrait")) - if page._transformedbbox and writebbox: - pagesfile.write("%%%%PageBoundingBox: %d %d %d %d\n" % page._transformedbbox.lowrestuple_pt()) - - # page setup section - pagesfile.write("%%BeginPageSetup\n") - pagesfile.write("/pgsave save def\n") - - acontext = context() - # apply a possible page transformation - if page._pagetrafo is not None: - page._pagetrafo.outputPS(pagesfile, self, acontext, registry) - - style.linewidth.normal.outputPS(pagesfile, self, acontext, registry) - pagesfile.write("%%EndPageSetup\n") - - # here comes the actual content - page.canvas.outputPS(pagesfile, self, acontext, registry) - pagesfile.write("pgsave restore\n") - pagesfile.write("showpage\n") - pagesfile.write("%%PageTrailer\n") - # document prolog section file.write("%%BeginProlog\n") - registry.outputPS(file, self) + registry.output(file, self) file.write("%%EndProlog\n") # document setup section diff --git a/pyx/style.py b/pyx/style.py index 69a76713..0f74d1ed 100644 --- a/pyx/style.py +++ b/pyx/style.py @@ -2,7 +2,7 @@ # -*- coding: ISO-8859-1 -*- # # -# Copyright (C) 2002-2005 Jörg Lehmann +# Copyright (C) 2002-2006 Jörg Lehmann # Copyright (C) 2003-2004 Michael Schindler # Copyright (C) 2002-2004 André Wobst # @@ -46,10 +46,10 @@ class linecap(attr.exclusiveattr, strokestyle): attr.exclusiveattr.__init__(self, linecap) self.value = value - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): file.write("%d setlinecap\n" % self.value) - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): file.write("%d J\n" % self.value) linecap.butt = linecap(0) @@ -66,10 +66,10 @@ class linejoin(attr.exclusiveattr, strokestyle): attr.exclusiveattr.__init__(self, linejoin) self.value = value - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): file.write("%d setlinejoin\n" % self.value) - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): file.write("%d j\n" % self.value) linejoin.miter = linejoin(0) @@ -86,7 +86,7 @@ class miterlimit(attr.exclusiveattr, strokestyle): attr.exclusiveattr.__init__(self, miterlimit) self.value = value - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): file.write("%f setmiterlimit\n" % self.value) def outoutPDF(self, file): @@ -114,14 +114,14 @@ class dash(attr.exclusiveattr, strokestyle): self.offset = offset self.rellengths = rellengths - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): if self.rellengths: patternstring = " ".join(["%f" % (element * context.linewidth_pt) for element in self.pattern]) else: patternstring = " ".join(["%f" % element for element in self.pattern]) file.write("[%s] %d setdash\n" % (patternstring, self.offset)) - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): if self.rellengths: patternstring = " ".join(["%f" % (element * context.linewidth_pt) for element in self.pattern]) else: @@ -142,13 +142,13 @@ class linestyle(attr.exclusiveattr, strokestyle): self.c = c self.d = d - def outputPS(self, file, writer, context, registry): - self.c.outputPS(file, writer, context, registry) - self.d.outputPS(file, writer, context, registry) + def processPS(self, file, writer, context, registry, bbox): + self.c.processPS(file, writer, context, registry, bbox) + self.d.processPS(file, writer, context, registry, bbox) - def outputPDF(self, file, writer, context, registry): - self.c.outputPDF(file, writer, context, registry) - self.d.outputPDF(file, writer, context, registry) + def processPDF(self, file, writer, context, registry, bbox): + self.c.processPDF(file, writer, context, registry, bbox) + self.d.processPDF(file, writer, context, registry, bbox) linestyle.solid = linestyle(linecap.butt, dash([])) linestyle.dashed = linestyle(linecap.butt, dash([2])) @@ -165,11 +165,11 @@ class linewidth(attr.sortbeforeexclusiveattr, strokestyle): attr.sortbeforeexclusiveattr.__init__(self, linewidth, [dash, linestyle]) self.width = width - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): file.write("%f setlinewidth\n" % unit.topt(self.width)) context.linewidth_pt = unit.topt(self.width) - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): file.write("%f w\n" % unit.topt(self.width)) context.linewidth_pt = unit.topt(self.width) diff --git a/pyx/text.py b/pyx/text.py index 544e0ec3..8ef249f3 100644 --- a/pyx/text.py +++ b/pyx/text.py @@ -694,13 +694,13 @@ class textbox(box.rect, canvas._canvas): self.ensuredvicanvas() return self.texttrafo.apply(*self.dvicanvas.markers[marker]) - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): self.ensuredvicanvas() - canvas._canvas.outputPS(self, file, writer, context, registry) + canvas._canvas.processPS(self, file, writer, context, registry, bbox) - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): self.ensuredvicanvas() - canvas._canvas.outputPDF(self, file, writer, context, registry) + canvas._canvas.processPDF(self, file, writer, context, registry, bbox) def _cleantmp(texrunner): diff --git a/pyx/trafo.py b/pyx/trafo.py index 9cd93cda..99011416 100755 --- a/pyx/trafo.py +++ b/pyx/trafo.py @@ -2,7 +2,7 @@ # -*- coding: ISO-8859-1 -*- # # -# Copyright (C) 2002-2005 Jörg Lehmann +# Copyright (C) 2002-2006 Jörg Lehmann # Copyright (C) 2002-2004 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). @@ -23,6 +23,7 @@ import math import attr, canvas, deformer, unit +import bbox as bboxmodule # global epsilon (used to judge whether a matrix is singular) _epsilon = (1e-5)**2 @@ -125,20 +126,20 @@ class trafo_pt(canvas.canvasitem, deformer.deformer): self.matrix[0][1], self.matrix[1][1], self.vector[0], self.vector[1] ) - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): file.write("[%f %f %f %f %f %f] concat\n" % \ ( self.matrix[0][0], self.matrix[1][0], self.matrix[0][1], self.matrix[1][1], self.vector[0], self.vector[1] ) ) - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): file.write("%f %f %f %f %f %f cm\n" % \ ( self.matrix[0][0], self.matrix[1][0], self.matrix[0][1], self.matrix[1][1], self.vector[0], self.vector[1] ) ) def bbox(self): - return None + return bboxmodule.empty() def apply_pt(self, x_pt, y_pt): """apply transformation to point (x_pt, y_pt) in pts""" diff --git a/pyx/type1font.py b/pyx/type1font.py index 87172471..1b656e31 100644 --- a/pyx/type1font.py +++ b/pyx/type1font.py @@ -2,8 +2,8 @@ # -*- coding: ISO-8859-1 -*- # # -# Copyright (C) 2005 Jörg Lehmann -# Copyright (C) 2005 André Wobst +# Copyright (C) 2005-2006 Jörg Lehmann +# Copyright (C) 2005-2006 André Wobst # # This file is part of PyX (http://pyx.sourceforge.net/). # @@ -35,7 +35,6 @@ class encoding: def __init__(self, name, filename): """ font encoding contained in filename """ - print "x"*100 self.name = name self.filename = filename @@ -137,14 +136,11 @@ class text_pt(canvas.canvasitem): def bbox(self): return bbox.bbox_pt(self.x_pt, self.y_pt-self.depth_pt, self.x_pt+self.width_pt, self.y_pt+self.height_pt) - def outputPS(self, file, writer, context, registry): + def processPS(self, file, writer, context, registry, bbox): # note that we don't register PSfont as it is just a helper resource # which registers the needed components pswriter.PSfont(self.font, self.chars, registry) - if registry.bbox: - registry.bbox += self.bbox() - else: - registry.bbox = self.bbox() + bbox += self.bbox() if ( context.font is None or context.font.name != self.font.name or @@ -160,12 +156,9 @@ class text_pt(canvas.canvasitem): outstring += ascii file.write("%g %g moveto (%s) show\n" % (self.x_pt, self.y_pt, outstring)) - def outputPDF(self, file, writer, context, registry): + def processPDF(self, file, writer, context, registry, bbox): registry.add(pdfwriter.PDFfont(self.font, self.chars, writer, registry)) - if registry.bbox: - registry.bbox += self.bbox() - else: - registry.bbox = self.bbox() + bbox += self.bbox() if ( context.font is None or context.font.name != self.font.name or diff --git a/test/functional/test_path.py b/test/functional/test_path.py index 15213977..120540e4 100755 --- a/test/functional/test_path.py +++ b/test/functional/test_path.py @@ -177,7 +177,7 @@ def testtangent(c): # test the curvature cc = canvas.canvas() - cc.insert(p) + cc.stroke(p) cc = canvas.canvas([canvas.clip(cc.bbox().path())]) for i in range(points): radius = p.curveradius(arclen*i/points) diff --git a/test/functional/test_text.py b/test/functional/test_text.py index 7920be83..d1b04fe8 100755 --- a/test/functional/test_text.py +++ b/test/functional/test_text.py @@ -72,14 +72,14 @@ c.insert(myrunner2.text(6.5, 12, r"\char'035")) # test the specials c.stroke(c.text(10, 2, r"Hello, \color{green}world!", [trafo.slant(1)]).path()) -c.stroke(c.text(10, 0, r"\begin{rotate}{90}\parbox{5cm}{rotated\\ in \LaTeX}\end{rotate}")) +c.insert(c.text(10, 0, r"\begin{rotate}{90}\parbox{5cm}{rotated\\ in \LaTeX}\end{rotate}")) d = canvas.canvas() d.stroke(path.rect(0,0, 1,1)) d.stroke(path.line(0,0, 1,1)) d.stroke(path.line(1,0, 0,1)) d.writeEPSfile("sample") -c.stroke(c.text(10, 0, r""" +c.insert(c.text(10, 0, r""" \textcolor{col0}{abc} \textcolor{col1}{abc} \textcolor{col2}{abc} @@ -88,7 +88,7 @@ c.stroke(c.text(10, 0, r""" \textcolor{col5}{abc} % \textcolor{col6}{abc}% """, [text.parbox(3)])) -c.stroke(c.text(15, 0, r""" +c.insert(c.text(15, 0, r""" \colorbox{col2}{ColorBox}\\ \fcolorbox{col3}{col4}{FColorBox}""")) @@ -96,7 +96,7 @@ c.text(4, 2, r"{\color[cmyk]{0.1,0.2,0.3,0.4}c\color[gray]{0.5}o\color[hsb]{0.2, c.writePDFfile("test_text", paperformat=document.paperformat.A4) -c.stroke(c.text(10, 4, r"""% +c.insert(c.text(10, 4, r"""% \fbox{\includegraphics[% %type=eps, %% type of the file ... should not change anything -- % BUG!!!!!! size and filename information gets -- 2.11.4.GIT