## The Python Imaging Library# $Id$## Simple PostScript graphics interface## History:# 1996-04-20 fl Created# 1999-01-10 fl Added gsave/grestore to image method# 2005-05-04 fl Fixed floating point issue in image (from Eric Etheridge)## Copyright (c) 1997-2005 by Secret Labs AB. All rights reserved.# Copyright (c) 1996 by Fredrik Lundh.## See the README file for information on usage and redistribution.#from__future__importannotationsimportsysfromtypingimportIOfrom.importEpsImagePluginTYPE_CHECKING=False### Simple PostScript graphics interface.[docs]classPSDraw:""" Sets up printing to the given file. If ``fp`` is omitted, ``sys.stdout.buffer`` is assumed. """def__init__(self,fp:IO[bytes]|None=None)->None:ifnotfp:fp=sys.stdout.bufferself.fp=fp[docs]defbegin_document(self,id:str|None=None)->None:"""Set up printing of a document. (Write PostScript DSC header.)"""# FIXME: incompleteself.fp.write(b"%!PS-Adobe-3.0\n"b"save\n"b"/showpage { } def\n"b"%%EndComments\n"b"%%BeginDocument\n")# self.fp.write(ERROR_PS) # debugging!self.fp.write(EDROFF_PS)self.fp.write(VDI_PS)self.fp.write(b"%%EndProlog\n")self.isofont:dict[bytes,int]={} [docs]defend_document(self)->None:"""Ends printing. (Write PostScript DSC footer.)"""self.fp.write(b"%%EndDocument\nrestore showpage\n%%End\n")ifhasattr(self.fp,"flush"):self.fp.flush() [docs]defsetfont(self,font:str,size:int)->None:""" Selects which font to use. :param font: A PostScript font name :param size: Size in points. """font_bytes=bytes(font,"UTF-8")iffont_bytesnotinself.isofont:# reencode fontself.fp.write(b"/PSDraw-%s ISOLatin1Encoding /%s E\n"%(font_bytes,font_bytes))self.isofont[font_bytes]=1# roughself.fp.write(b"/F0%d /PSDraw-%s F\n"%(size,font_bytes)) [docs]defline(self,xy0:tuple[int,int],xy1:tuple[int,int])->None:""" Draws a line between the two points. Coordinates are given in PostScript point coordinates (72 points per inch, (0, 0) is the lower left corner of the page). """self.fp.write(b"%d%d%d%d Vl\n"%(*xy0,*xy1)) [docs]defrectangle(self,box:tuple[int,int,int,int])->None:""" Draws a rectangle. :param box: A tuple of four integers, specifying left, bottom, width and height. """self.fp.write(b"%d%d M 0%d%d Vr\n"%box) [docs]deftext(self,xy:tuple[int,int],text:str)->None:""" Draws text at the given position. You must use :py:meth:`~PIL.PSDraw.PSDraw.setfont` before calling this method. """text_bytes=bytes(text,"UTF-8")text_bytes=b"\\(".join(text_bytes.split(b"("))text_bytes=b"\\)".join(text_bytes.split(b")"))self.fp.write(b"%d%d M (%s) S\n"%(xy+(text_bytes,))) ifTYPE_CHECKING:from.importImage[docs]defimage(self,box:tuple[int,int,int,int],im:Image.Image,dpi:int|None=None)->None:"""Draw a PIL image, centered in the given box."""# default resolution depends on modeifnotdpi:ifim.mode=="1":dpi=200# faxelse:dpi=100# grayscale# image size (on paper)x=im.size[0]*72/dpiy=im.size[1]*72/dpi# max allowed sizexmax=float(box[2]-box[0])ymax=float(box[3]-box[1])ifx>xmax:y=y*xmax/xx=xmaxify>ymax:x=x*ymax/yy=ymaxdx=(xmax-x)/2+box[0]dy=(ymax-y)/2+box[1]self.fp.write(b"gsave\n%f%f translate\n"%(dx,dy))if(x,y)!=im.size:# EpsImagePlugin._save prints the image at (0,0,xsize,ysize)sx=x/im.size[0]sy=y/im.size[1]self.fp.write(b"%f%f scale\n"%(sx,sy))EpsImagePlugin._save(im,self.fp,"",0)self.fp.write(b"\ngrestore\n") # --------------------------------------------------------------------# PostScript driver## EDROFF.PS -- PostScript driver for Edroff 2## History:# 94-01-25 fl: created (edroff 2.04)## Copyright (c) Fredrik Lundh 1994.#EDROFF_PS=b"""\/S { show } bind def/P { moveto show } bind def/M { moveto } bind def/X { 0 rmoveto } bind def/Y { 0 exch rmoveto } bind def/E { findfont dup maxlength dict begin { 1 index /FID ne { def } { pop pop } ifelse } forall /Encoding exch def dup /FontName exch def currentdict end definefont pop} bind def/F { findfont exch scalefont dup setfont [ exch /setfont cvx ] cvx bind def} bind def"""## VDI.PS -- PostScript driver for VDI meta commands## History:# 94-01-25 fl: created (edroff 2.04)## Copyright (c) Fredrik Lundh 1994.#VDI_PS=b"""\/Vm { moveto } bind def/Va { newpath arcn stroke } bind def/Vl { moveto lineto stroke } bind def/Vc { newpath 0 360 arc closepath } bind def/Vr { exch dup 0 rlineto exch dup 0 exch rlineto exch neg 0 rlineto 0 exch neg rlineto setgray fill } bind def/Tm matrix def/Ve { Tm currentmatrix pop translate scale newpath 0 0 .5 0 360 arc closepath Tm setmatrix} bind def/Vf { currentgray exch setgray fill setgray } bind def"""## ERROR.PS -- Error handler## History:# 89-11-21 fl: created (pslist 1.10)#ERROR_PS=b"""\/landscape false def/errorBUF 200 string def/errorNL { currentpoint 10 sub exch pop 72 exch moveto } deferrordict begin /handleerror { initmatrix /Courier findfont 10 scalefont setfont newpath 72 720 moveto $error begin /newerror false def (PostScript Error) show errorNL errorNL (Error: ) show /errorname load errorBUF cvs show errorNL errorNL (Command: ) show /command load dup type /stringtype ne { errorBUF cvs } if show errorNL errorNL (VMstatus: ) show vmstatus errorBUF cvs show ( bytes available, ) show errorBUF cvs show ( bytes used at level ) show errorBUF cvs show errorNL errorNL (Operand stargck: ) show errorNL /ostargck load { dup type /stringtype ne { errorBUF cvs } if 72 0 rmoveto show errorNL } forall errorNL (Execution stargck: ) show errorNL /estargck load { dup type /stringtype ne { errorBUF cvs } if 72 0 rmoveto show errorNL } forall end showpage} def end"""