Changed PSDraw default from sys.stdout to sys.stdout.buffer

This commit is contained in:
Andrew Murray 2021-04-25 15:33:36 +10:00
parent bb12c8079e
commit 9c06ce044c
3 changed files with 38 additions and 37 deletions

View File

@ -1,6 +1,6 @@
import os import os
import sys import sys
from io import StringIO from io import BytesIO
from PIL import Image, PSDraw from PIL import Image, PSDraw
@ -46,8 +46,12 @@ def test_draw_postscript(tmp_path):
def test_stdout(): def test_stdout():
# Temporarily redirect stdout # Temporarily redirect stdout
old_stdout = sys.stdout old_stdout = sys.stdout.buffer
sys.stdout = mystdout = StringIO()
class MyStdOut:
buffer = BytesIO()
sys.stdout = mystdout = MyStdOut()
ps = PSDraw.PSDraw() ps = PSDraw.PSDraw()
_create_document(ps) _create_document(ps)
@ -55,4 +59,4 @@ def test_stdout():
# Reset stdout # Reset stdout
sys.stdout = old_stdout sys.stdout = old_stdout
assert mystdout.getvalue() != "" assert mystdout.buffer.getvalue() != b""

View File

@ -424,7 +424,7 @@ Drawing PostScript
title = "hopper" title = "hopper"
box = (1*72, 2*72, 7*72, 10*72) # in points box = (1*72, 2*72, 7*72, 10*72) # in points
ps = PSDraw.PSDraw() # default is sys.stdout ps = PSDraw.PSDraw() # default is sys.stdout.buffer
ps.begin_document(title) ps.begin_document(title)
# draw the image (75 dpi) # draw the image (75 dpi)

View File

@ -26,39 +26,33 @@ from . import EpsImagePlugin
class PSDraw: class PSDraw:
""" """
Sets up printing to the given file. If ``fp`` is omitted, Sets up printing to the given file. If ``fp`` is omitted,
:py:data:`sys.stdout` is assumed. ``sys.stdout.buffer`` is assumed.
""" """
def __init__(self, fp=None): def __init__(self, fp=None):
if not fp: if not fp:
fp = sys.stdout fp = sys.stdout.buffer
self.fp = fp self.fp = fp
def _fp_write(self, to_write):
if self.fp == sys.stdout:
self.fp.write(to_write)
else:
self.fp.write(bytes(to_write, "UTF-8"))
def begin_document(self, id=None): def begin_document(self, id=None):
"""Set up printing of a document. (Write PostScript DSC header.)""" """Set up printing of a document. (Write PostScript DSC header.)"""
# FIXME: incomplete # FIXME: incomplete
self._fp_write( self.fp.write(
"%!PS-Adobe-3.0\n" b"%!PS-Adobe-3.0\n"
"save\n" b"save\n"
"/showpage { } def\n" b"/showpage { } def\n"
"%%EndComments\n" b"%%EndComments\n"
"%%BeginDocument\n" b"%%BeginDocument\n"
) )
# self._fp_write(ERROR_PS) # debugging! # self.fp.write(ERROR_PS) # debugging!
self._fp_write(EDROFF_PS) self.fp.write(EDROFF_PS)
self._fp_write(VDI_PS) self.fp.write(VDI_PS)
self._fp_write("%%EndProlog\n") self.fp.write(b"%%EndProlog\n")
self.isofont = {} self.isofont = {}
def end_document(self): def end_document(self):
"""Ends printing. (Write PostScript DSC footer.)""" """Ends printing. (Write PostScript DSC footer.)"""
self._fp_write("%%EndDocument\nrestore showpage\n%%End\n") self.fp.write(b"%%EndDocument\nrestore showpage\n%%End\n")
if hasattr(self.fp, "flush"): if hasattr(self.fp, "flush"):
self.fp.flush() self.fp.flush()
@ -69,12 +63,13 @@ class PSDraw:
:param font: A PostScript font name :param font: A PostScript font name
:param size: Size in points. :param size: Size in points.
""" """
font = bytes(font, "UTF-8")
if font not in self.isofont: if font not in self.isofont:
# reencode font # reencode font
self._fp_write(f"/PSDraw-{font} ISOLatin1Encoding /{font} E\n") self.fp.write(b"/PSDraw-%s ISOLatin1Encoding /%s E\n" % (font, font))
self.isofont[font] = 1 self.isofont[font] = 1
# rough # rough
self._fp_write(f"/F0 {size} /PSDraw-{font} F\n") self.fp.write(b"/F0 %d /PSDraw-%s F\n" % (size, font))
def line(self, xy0, xy1): def line(self, xy0, xy1):
""" """
@ -82,7 +77,7 @@ class PSDraw:
PostScript point coordinates (72 points per inch, (0, 0) is the lower PostScript point coordinates (72 points per inch, (0, 0) is the lower
left corner of the page). left corner of the page).
""" """
self._fp_write("%d %d %d %d Vl\n" % (*xy0, *xy1)) self.fp.write(b"%d %d %d %d Vl\n" % (*xy0, *xy1))
def rectangle(self, box): def rectangle(self, box):
""" """
@ -97,16 +92,18 @@ class PSDraw:
%d %d M %d %d 0 Vr\n %d %d M %d %d 0 Vr\n
""" """
self._fp_write("%d %d M %d %d 0 Vr\n" % box) self.fp.write(b"%d %d M %d %d 0 Vr\n" % box)
def text(self, xy, text): def text(self, xy, text):
""" """
Draws text at the given position. You must use Draws text at the given position. You must use
:py:meth:`~PIL.PSDraw.PSDraw.setfont` before calling this method. :py:meth:`~PIL.PSDraw.PSDraw.setfont` before calling this method.
""" """
text = "\\(".join(text.split("(")) text = bytes(text, "UTF-8")
text = "\\)".join(text.split(")")) text = b"\\(".join(text.split(b"("))
self._fp_write(f"{xy[0]} {xy[1]} M ({text}) S\n") text = b"\\)".join(text.split(b")"))
xy += (text,)
self.fp.write(b"%d %d M (%s) S\n" % xy)
def image(self, box, im, dpi=None): def image(self, box, im, dpi=None):
"""Draw a PIL image, centered in the given box.""" """Draw a PIL image, centered in the given box."""
@ -130,14 +127,14 @@ class PSDraw:
y = ymax y = ymax
dx = (xmax - x) / 2 + box[0] dx = (xmax - x) / 2 + box[0]
dy = (ymax - y) / 2 + box[1] dy = (ymax - y) / 2 + box[1]
self._fp_write(f"gsave\n{dx:f} {dy:f} translate\n") self.fp.write(b"gsave\n%f %f translate\n" % (dx, dy))
if (x, y) != im.size: if (x, y) != im.size:
# EpsImagePlugin._save prints the image at (0,0,xsize,ysize) # EpsImagePlugin._save prints the image at (0,0,xsize,ysize)
sx = x / im.size[0] sx = x / im.size[0]
sy = y / im.size[1] sy = y / im.size[1]
self._fp_write(f"{sx:f} {sy:f} scale\n") self.fp.write(b"%f %f scale\n" % (sx, sy))
EpsImagePlugin._save(im, self.fp, None, 0) EpsImagePlugin._save(im, self.fp, None, 0)
self._fp_write("\ngrestore\n") self.fp.write(b"\ngrestore\n")
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -153,7 +150,7 @@ class PSDraw:
# #
EDROFF_PS = """\ EDROFF_PS = b"""\
/S { show } bind def /S { show } bind def
/P { moveto show } bind def /P { moveto show } bind def
/M { moveto } bind def /M { moveto } bind def
@ -182,7 +179,7 @@ EDROFF_PS = """\
# Copyright (c) Fredrik Lundh 1994. # Copyright (c) Fredrik Lundh 1994.
# #
VDI_PS = """\ VDI_PS = b"""\
/Vm { moveto } bind def /Vm { moveto } bind def
/Va { newpath arcn stroke } bind def /Va { newpath arcn stroke } bind def
/Vl { moveto lineto stroke } bind def /Vl { moveto lineto stroke } bind def
@ -207,7 +204,7 @@ VDI_PS = """\
# 89-11-21 fl: created (pslist 1.10) # 89-11-21 fl: created (pslist 1.10)
# #
ERROR_PS = """\ ERROR_PS = b"""\
/landscape false def /landscape false def
/errorBUF 200 string def /errorBUF 200 string def
/errorNL { currentpoint 10 sub exch pop 72 exch moveto } def /errorNL { currentpoint 10 sub exch pop 72 exch moveto } def