Applied upstream as r3028 r3025 r3024
[PyX/mjg.git] / pyx / document.py
blob5bb85aa9bf63855ae9ac51886c7e290cbaedb4d4
1 # -*- coding: ISO-8859-1 -*-
4 # Copyright (C) 2005-2006 Jörg Lehmann <joergl@users.sourceforge.net>
5 # Copyright (C) 2005-2006 André Wobst <wobsta@users.sourceforge.net>
7 # This file is part of PyX (http://pyx.sourceforge.net/).
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.
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.
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
23 import cStringIO, sys, warnings
24 import bbox, pswriter, pdfwriter, trafo, style, unit
25 import canvas as canvasmodule
28 class paperformat:
30 def __init__(self, width, height, name=None):
31 self.width = width
32 self.height = height
33 self.name = name
35 paperformat.A4 = paperformat(210 * unit.t_mm, 297 * unit.t_mm, "A4")
36 paperformat.A3 = paperformat(297 * unit.t_mm, 420 * unit.t_mm, "A3")
37 paperformat.A2 = paperformat(420 * unit.t_mm, 594 * unit.t_mm, "A2")
38 paperformat.A1 = paperformat(594 * unit.t_mm, 840 * unit.t_mm, "A1")
39 paperformat.A0 = paperformat(840 * unit.t_mm, 1188 * unit.t_mm, "A0")
40 paperformat.A0b = paperformat(910 * unit.t_mm, 1370 * unit.t_mm, None) # dedicated to our friends in Augsburg
41 paperformat.Letter = paperformat(8.5 * unit.t_inch, 11 * unit.t_inch, "Letter")
42 paperformat.Legal = paperformat(8.5 * unit.t_inch, 14 * unit.t_inch, "Legal")
44 def _paperformatfromstring(name):
45 return getattr(paperformat, name.capitalize())
48 class page:
50 def __init__(self, canvas, pagename=None, paperformat=None, rotated=0, centered=1, fittosize=0,
51 margin=1*unit.t_cm, bboxenlarge=1*unit.t_pt, bbox=None):
52 self.canvas = canvas
53 self.pagename = pagename
54 # support for deprecated string specification of paper formats
55 try:
56 paperformat + ""
57 except:
58 self.paperformat = paperformat
59 else:
60 self.paperformat = _paperformatfromstring(paperformat)
61 warnings.warn("specification of paperformat by string is deprecated, use document.paperformat.%s instead" % paperformat.capitalize(), DeprecationWarning)
63 self.rotated = rotated
64 self.centered = centered
65 self.fittosize = fittosize
66 self.margin = margin
67 self.bboxenlarge = bboxenlarge
68 self.pagebbox = bbox
70 def _process(self, processMethod, contentfile, writer, context, registry, bbox):
72 # check whether we expect a page trafo and use a temporary canvas to insert the
73 # page canvas
74 expectpagetrafo = self.paperformat and (self.rotated or self.centered or self.fittosize)
76 # usually, it is the bbox of the canvas enlarged by self.bboxenlarge, but
77 # it might be a different bbox as specified in the page constructor
78 assert not bbox
79 if self.pagebbox:
80 bbox.set(self.pagebbox)
81 elif bbox:
82 bbox.enlarge(self.bboxenlarge)
83 else:
84 bbox.set(self.canvas.bbox())
85 bbox.enlarge(self.bboxenlarge)
87 cc = self.canvas
88 if expectpagetrafo:
90 # calculate the pagetrafo
91 paperwidth, paperheight = self.paperformat.width, self.paperformat.height
93 # center (optionally rotated) output on page
94 if self.rotated:
95 pagetrafo = trafo.rotate(90).translated(paperwidth, 0)
96 if self.centered or self.fittosize:
97 if not self.fittosize and (bbox.height() > paperwidth or bbox.width() > paperheight):
98 warnings.warn("content exceeds the papersize")
99 pagetrafo = pagetrafo.translated(-0.5*(paperwidth - bbox.height()) + bbox.bottom(),
100 0.5*(paperheight - bbox.width()) - bbox.left())
101 else:
102 if not self.fittosize and (bbox.width() > paperwidth or bbox.height() > paperheight):
103 warnings.warn("content exceeds the papersize")
104 pagetrafo = trafo.translate(0.5*(paperwidth - bbox.width()) - bbox.left(),
105 0.5*(paperheight - bbox.height()) - bbox.bottom())
107 if self.fittosize:
109 if 2*self.margin > paperwidth or 2*self.margin > paperheight:
110 raise ValueError("Margins too broad for selected paperformat. Aborting.")
112 paperwidth -= 2 * self.margin
113 paperheight -= 2 * self.margin
115 # scale output to pagesize - margins
116 if self.rotated:
117 sfactor = min(unit.topt(paperheight)/bbox.width_pt(), unit.topt(paperwidth)/bbox.height_pt())
118 else:
119 sfactor = min(unit.topt(paperwidth)/bbox.width_pt(), unit.topt(paperheight)/bbox.height_pt())
121 pagetrafo = pagetrafo.scaled(sfactor, sfactor, self.margin + 0.5*paperwidth, self.margin + 0.5*paperheight)
123 bbox.transform(pagetrafo)
124 cc = canvasmodule.canvas()
125 cc.insert(self.canvas, [pagetrafo])
127 getattr(style.linewidth.normal, processMethod)(contentfile, writer, context, registry, bbox)
128 getattr(cc, processMethod)(contentfile, writer, context, registry, bbox)
130 def processPS(self, *args):
131 self._process("processPS", *args)
133 def processPDF(self, *args):
134 self._process("processPDF", *args)
137 def _outputstream(file, suffix):
138 if file is None:
139 if not sys.argv[0].endswith(".py"):
140 raise RuntimeError("could not auto-guess filename")
141 return open("%s.%s" % (sys.argv[0][:-3], suffix), "wb")
142 try:
143 file.write("")
144 return file
145 except:
146 if not file.endswith(".%s" % suffix):
147 return open("%s.%s" % (file, suffix), "wb")
148 return open(file, "wb")
151 class document:
153 """holds a collection of page instances which are output as pages of a document"""
155 def __init__(self, pages=None):
156 if pages is None:
157 self.pages = []
158 else:
159 self.pages = pages
161 def append(self, page):
162 self.pages.append(page)
164 def writeEPSfile(self, file=None, **kwargs):
165 pswriter.EPSwriter(self, _outputstream(file, "eps"), **kwargs)
167 def writePSfile(self, file=None, **kwargs):
168 pswriter.PSwriter(self, _outputstream(file, "ps"), **kwargs)
170 def writePDFfile(self, file=None, **kwargs):
171 pdfwriter.PDFwriter(self, _outputstream(file, "pdf"), **kwargs)
173 def writetofile(self, filename, **kwargs):
174 if filename.endswith(".eps"):
175 self.writeEPSfile(open(filename, "wb"), **kwargs)
176 elif filename.endswith(".ps"):
177 self.writePSfile(open(filename, "wb"), **kwargs)
178 elif filename.endswith(".pdf"):
179 self.writePDFfile(open(filename, "wb"), **kwargs)
180 else:
181 raise ValueError("unknown file extension")