Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
PSDraw.py239 linesDownload Raw Back to PIL
1#
2# The Python Imaging Library
3# $Id$
4#
5# Simple PostScript graphics interface
6#
7# History:
8# 1996-04-20 fl   Created
9# 1999-01-10 fl   Added gsave/grestore to image method
10# 2005-05-04 fl   Fixed floating point issue in image (from Eric Etheridge)
11#
12# Copyright (c) 1997-2005 by Secret Labs AB.  All rights reserved.
13# Copyright (c) 1996 by Fredrik Lundh.
14#
15# See the README file for information on usage and redistribution.
16#
17from __future__ import annotations
18
19import sys
20from typing import IO
21
22from . import EpsImagePlugin
23
24TYPE_CHECKING = False
25
26
27##
28# Simple PostScript graphics interface.
29
30
31class PSDraw:
32    """
33    Sets up printing to the given file. If ``fp`` is omitted,
34    ``sys.stdout.buffer`` is assumed.
35    """
36
37    def __init__(self, fp: IO[bytes] | None = None) -> None:
38        if not fp:
39            fp = sys.stdout.buffer
40        self.fp = fp
41
42    def begin_document(self, id: str | None = None) -> None:
43        """Set up printing of a document. (Write PostScript DSC header.)"""
44        # FIXME: incomplete
45        self.fp.write(
46            b"%!PS-Adobe-3.0\n"
47            b"save\n"
48            b"/showpage { } def\n"
49            b"%%EndComments\n"
50            b"%%BeginDocument\n"
51        )
52        # self.fp.write(ERROR_PS)  # debugging!
53        self.fp.write(EDROFF_PS)
54        self.fp.write(VDI_PS)
55        self.fp.write(b"%%EndProlog\n")
56        self.isofont: dict[bytes, int] = {}
57
58    def end_document(self) -> None:
59        """Ends printing. (Write PostScript DSC footer.)"""
60        self.fp.write(b"%%EndDocument\nrestore showpage\n%%End\n")
61        if hasattr(self.fp, "flush"):
62            self.fp.flush()
63
64    def setfont(self, font: str, size: int) -> None:
65        """
66        Selects which font to use.
67
68        :param font: A PostScript font name
69        :param size: Size in points.
70        """
71        font_bytes = bytes(font, "UTF-8")
72        if font_bytes not in self.isofont:
73            # reencode font
74            self.fp.write(
75                b"/PSDraw-%s ISOLatin1Encoding /%s E\n" % (font_bytes, font_bytes)
76            )
77            self.isofont[font_bytes] = 1
78        # rough
79        self.fp.write(b"/F0 %d /PSDraw-%s F\n" % (size, font_bytes))
80
81    def line(self, xy0: tuple[int, int], xy1: tuple[int, int]) -> None:
82        """
83        Draws a line between the two points. Coordinates are given in
84        PostScript point coordinates (72 points per inch, (0, 0) is the lower
85        left corner of the page).
86        """
87        self.fp.write(b"%d %d %d %d Vl\n" % (*xy0, *xy1))
88
89    def rectangle(self, box: tuple[int, int, int, int]) -> None:
90        """
91        Draws a rectangle.
92
93        :param box: A tuple of four integers, specifying left, bottom, width and
94           height.
95        """
96        self.fp.write(b"%d %d M 0 %d %d Vr\n" % box)
97
98    def text(self, xy: tuple[int, int], text: str) -> None:
99        """
100        Draws text at the given position. You must use
101        :py:meth:`~PIL.PSDraw.PSDraw.setfont` before calling this method.
102        """
103        # The font is loaded as ISOLatin1Encoding, so use latin-1 here.
104        text_bytes = bytes(text, "latin-1")
105        text_bytes = b"\\(".join(text_bytes.split(b"("))
106        text_bytes = b"\\)".join(text_bytes.split(b")"))
107        self.fp.write(b"%d %d M (%s) S\n" % (xy + (text_bytes,)))
108
109    if TYPE_CHECKING:
110        from . import Image
111
112    def image(
113        self, box: tuple[int, int, int, int], im: Image.Image, dpi: int | None = None
114    ) -> None:
115        """Draw a PIL image, centered in the given box."""
116        # default resolution depends on mode
117        if not dpi:
118            if im.mode == "1":
119                dpi = 200  # fax
120            else:
121                dpi = 100  # grayscale
122        # image size (on paper)
123        x = im.size[0] * 72 / dpi
124        y = im.size[1] * 72 / dpi
125        # max allowed size
126        xmax = float(box[2] - box[0])
127        ymax = float(box[3] - box[1])
128        if x > xmax:
129            y = y * xmax / x
130            x = xmax
131        if y > ymax:
132            x = x * ymax / y
133            y = ymax
134        dx = (xmax - x) / 2 + box[0]
135        dy = (ymax - y) / 2 + box[1]
136        self.fp.write(b"gsave\n%f %f translate\n" % (dx, dy))
137        if (x, y) != im.size:
138            # EpsImagePlugin._save prints the image at (0,0,xsize,ysize)
139            sx = x / im.size[0]
140            sy = y / im.size[1]
141            self.fp.write(b"%f %f scale\n" % (sx, sy))
142        EpsImagePlugin._save(im, self.fp, "", 0)
143        self.fp.write(b"\ngrestore\n")
144
145
146# --------------------------------------------------------------------
147# PostScript driver
148
149#
150# EDROFF.PS -- PostScript driver for Edroff 2
151#
152# History:
153# 94-01-25 fl: created (edroff 2.04)
154#
155# Copyright (c) Fredrik Lundh 1994.
156#
157
158
159EDROFF_PS = b"""\
160/S { show } bind def
161/P { moveto show } bind def
162/M { moveto } bind def
163/X { 0 rmoveto } bind def
164/Y { 0 exch rmoveto } bind def
165/E {    findfont
166        dup maxlength dict begin
167        {
168                1 index /FID ne { def } { pop pop } ifelse
169        } forall
170        /Encoding exch def
171        dup /FontName exch def
172        currentdict end definefont pop
173} bind def
174/F {    findfont exch scalefont dup setfont
175        [ exch /setfont cvx ] cvx bind def
176} bind def
177"""
178
179#
180# VDI.PS -- PostScript driver for VDI meta commands
181#
182# History:
183# 94-01-25 fl: created (edroff 2.04)
184#
185# Copyright (c) Fredrik Lundh 1994.
186#
187
188VDI_PS = b"""\
189/Vm { moveto } bind def
190/Va { newpath arcn stroke } bind def
191/Vl { moveto lineto stroke } bind def
192/Vc { newpath 0 360 arc closepath } bind def
193/Vr {   exch dup 0 rlineto
194        exch dup 0 exch rlineto
195        exch neg 0 rlineto
196        0 exch neg rlineto
197        setgray fill } bind def
198/Tm matrix def
199/Ve {   Tm currentmatrix pop
200        translate scale newpath 0 0 .5 0 360 arc closepath
201        Tm setmatrix
202} bind def
203/Vf { currentgray exch setgray fill setgray } bind def
204"""
205
206#
207# ERROR.PS -- Error handler
208#
209# History:
210# 89-11-21 fl: created (pslist 1.10)
211#
212
213ERROR_PS = b"""\
214/landscape false def
215/errorBUF 200 string def
216/errorNL { currentpoint 10 sub exch pop 72 exch moveto } def
217errordict begin /handleerror {
218    initmatrix /Courier findfont 10 scalefont setfont
219    newpath 72 720 moveto $error begin /newerror false def
220    (PostScript Error) show errorNL errorNL
221    (Error: ) show
222        /errorname load errorBUF cvs show errorNL errorNL
223    (Command: ) show
224        /command load dup type /stringtype ne { errorBUF cvs } if show
225        errorNL errorNL
226    (VMstatus: ) show
227        vmstatus errorBUF cvs show ( bytes available, ) show
228        errorBUF cvs show ( bytes used at level ) show
229        errorBUF cvs show errorNL errorNL
230    (Operand stargck: ) show errorNL /ostargck load {
231        dup type /stringtype ne { errorBUF cvs } if 72 0 rmoveto show errorNL
232    } forall errorNL
233    (Execution stargck: ) show errorNL /estargck load {
234        dup type /stringtype ne { errorBUF cvs } if 72 0 rmoveto show errorNL
235    } forall
236    end showpage
237} def end
238"""
239 
codekingpro/portable-devtools · Team Ai