NAME
PostScript::File - Class for creating Adobe PostScript files
VERSION
This document describes version 2.22 of PostScript::File, released May 9, 2015 as part of PostScript-File version 2.22.
Attributes and methods added since version 2.00 are marked with the version they were added in (e.g. "(v2.10)"). Because there were significant API changes in 2.00, I recommend that any code using PostScript::File specify a minimum version of at least 2.
SYNOPSIS
Simplest
A 'hello world' program:
use PostScript::File 2;
my $ps = PostScript::File->new(reencode => 'cp1252');
$ps->add_to_page( <<END_PAGE );
/Helvetica findfont
12 scalefont
setfont
72 300 moveto
(hello world) show
END_PAGE
$ps->output( "test" );
All options
my $ps = PostScript::File->new(
paper => 'Letter',
height => 500,
width => 400,
bottom => 30,
top => 30,
left => 30,
right => 30,
clip_command => 'stroke',
clipping => 1,
eps => 1,
dir => '~/foo',
file => "bar",
landscape => 0,
headings => 1,
reencode => 'cp1252',
font_suffix => '-iso',
need_fonts => [qw(Helvetica Helvetica-Bold)],
errors => 1,
errmsg => 'Failed:',
errfont => 'Helvetica',
errsize => 12,
errx => 72,
erry => 300,
debug => 2,
db_active => 1,
db_xgap => 120,
db_xtab => 8,
db_base => 300,
db_ytop => 500,
db_color => '1 0 0 setrgbcolor',
db_font => 'Times-Roman',
db_fontsize => 11,
db_bufsize => 256,
);
DESCRIPTION
PostScript::File is a class that writes PostScript files following Adobe's Document Structuring Conventions (DSC). You should be familiar with the DSC if you're using this class directly; consult the PostScript Language Document Structuring Conventions Specification linked to in "SEE ALSO".
There are also a number of modules that build upon PostScript::File to produce various kinds of documents without requiring knowledge of PostScript. These are listed in "SEE ALSO".
It is possible to construct and output files in either normal PostScript (*.ps files) or as Encapsulated PostScript (*.epsf or *.epsi files). By default a minimal file is output, but support for font encoding, PostScript error reporting and debugging can be built in if required.
Documents can typically be built using only these functions:
new The constructor, with many options
add_procset Add PostScript functions to the prolog
add_to_page Add PostScript to construct each page
newpage Begins a new page in the document
output Construct the file and saves it
The rest of the module involves fine-tuning this. Some settings only really make sense when given once, while others can control each page independently. See new
for the functions that duplicate option settings, they all have get_
counterparts. The following provide additional support.
get/set_bounding_box
get/set_page_bounding_box
get/set_page_clipping
get/set_page_landscape
set_page_margins
get_pagecount
draw_bounding_box
clip_bounding_box
The functions which insert entries into each of the DSC sections all begin with 'add_'. They also have get_
counterparts.
add_comment
add_preview
add_default
add_resource
add_procset
add_setup
add_page_setup
add_to_page
add_page_trailer
add_trailer
Finally, there are a few stand-alone functions. These are not methods and are available for export if requested.
check_tilde
check_file
incpage_label
incpage_roman
Hyphens and Minus Signs
In ASCII, the character \x2D
(\055
) is used as both a hyphen and a minus sign. Unicode calls this character HYPHEN-MINUS (U+002D). PostScript has two characters, which it calls /hyphen
and /minus
. The difference is that /minus
is usually wider than /hyphen
(except in Courier, of course).
In PostScript's StandardEncoding (what you get if you don't use "reencode"), character \x2D
is /hyphen
, and /minus
is not available. In the Latin1-based encodings created by reencode
, character \x2D
is /minus
, and character \xAD
is /hyphen
. (\xAD
is supposed to be a "soft hyphen" (U+00AD) that appears only if the line is broken at that point, but it doesn't work that way in PostScript.)
Unicode has additional non-ambiguous characters: HYPHEN (U+2010), NON-BREAKING HYPHEN (U+2011), and MINUS SIGN (U+2212). The first two always indicate /hyphen
, and the last is always /minus
. When you set reencode
to cp1252
or iso-8859-1
, those characters will be handled automatically.
To make it easier to handle strings containing HYPHEN-MINUS, PostScript::File provides the "auto_hyphen" attribute. When this is true (the default when using cp1252
or iso-8859-1
), the "pstr" method will automatically translate HYPHEN-MINUS to either HYPHEN or MINUS SIGN. (This happens only when pstr
is called as an object method.)
The rule is that if a HYPHEN-MINUS is surrounded by whitespace, or surrounded by digits, or it's preceded by whitespace or punctuation and followed by a digit, or it's followed by a currency symbol, it's translated to MINUS SIGN. Otherwise, it's translated to HYPHEN.
ATTRIBUTES
Unlike many classes that use the same method for reading and writing an attribute's value, PostScript::File has separate methods for reading and writing. The read accessor is prefixed with get_
, and the write accessor is prefixed with set_
. If no write accessor is mentioned, then the attribute is read-only.
auto_hyphen
$ps = PostScript::File->new( auto_hyphen => $translate )
$translate = $ps->get_auto_hyphen
$ps->set_auto_hyphen( $translate )
If $translate
is a true value, then "pstr" will do automatic hyphen-minus translation when called as an object method (but only if the document uses character set translation). (Default: true) See "Hyphens and Minus Signs".
clipping
$ps = PostScript::File->new( clipping => $clipping )
$clipping = $ps->get_clipping
$ps->set_clipping( $clipping )
If $clipping
is true, printing will be clipped to each page's bounding box. This is the document's default value. Each page has its own "page_clipping" attribute, which is initialized to this default value when the page is created. (Default: false)
eps
$ps = PostScript::File->new( eps => $eps )
$eps = $ps->get_eps
$eps
is true if this is an Encapsulated PostScript document. False indicates an ordinary PostScript document.
extensions
$ps = PostScript::File->new( extensions => $extensions )
$extensions = $ps->get_extensions
The PostScript extensions required by this document, for use in the %%Extensions
DSC comment. (Default: undef
, meaning omit the %%Extensions
comment)
file_ext
$ps = PostScript::File->new( file_ext => $file_ext )
$file_ext = $ps->get_file_ext
$ps->set_file_ext( $file_ext )
If $file_ext
is undef (the default), then the extension is set automatically based on the output type. .ps
will be added for ordinary PostScript files. EPS files have an extension of .epsf
without or .epsi
with a preview image.
If $file_ext
is the empty string, then no extension will be added to the filename. Otherwise, it should be a string like '.ps' or '.eps'. (But setting this has no effect on the actual type of the output file, only its name.)
filename
$ps = PostScript::File->new( file => $file, [dir => $dir] )
$filename = $ps->get_filename
$ps->set_filename( $file, [$dir] )
$file
-
An optional fully qualified path-and-file, a simple file name, the empty string (which stands for the special file
File::Spec->devnull
), orundef
(which indicates the document has no associated filename). $dir
-
An optional directory name. If present (and
$file
is not already an absolute path), it is prepended to$file
. If no$file
was specified,$dir
is ignored.
The base filename for the output file(s). When the filename is set, if that filename includes a directory component, the directories are created immediately (if they don't already exist).
See "file_ext" for details on how the filename extension is handled.
If "eps" has been set, multiple pages will have the page label appended to the file name.
Example:
$ps = PostScript::File->new( eps => 1 );
$ps->set_filename( "pics", "~/book" );
$ps->newpage("vi");
... draw page
$ps->newpage("7");
... draw page
$ps->newpage();
... draw page
$ps->output();
The three pages for user 'chris' on a Unix system would be:
/home/chris/book/pics-vi.epsf
/home/chris/book/pics-7.epsf
/home/chris/book/pics-8.epsf
It would be wise to use set_page_bounding_box
explicitly for each page if using multiple pages in EPS files.
incpage_handler
$ps = PostScript::File->new( incpage_handler => \&handler )
$handler = $ps->get_incpage_handler
$ps->set_incpage_handler( [\&handler] )
The function used to increment the page label when creating a new page. \&handler
is a reference to a subroutine that takes the current page label as its only argument and returns the new label.
This module provides the "incpage_label" (which uses Perl's autoincrement operator) and "incpage_roman" (which handles lowercase Roman numberals from i to xxxix, 1-39) functions for use as incpage_handler
. (Default: \&incpage_label
)
langlevel
$ps = PostScript::File->new( langlevel => $langlevel )
$langlevel = $ps->get_langlevel
$ps->set_min_langlevel( $langlevel ) # added in v2.20
The level of the PostScript language used in this document, for use in the %%LanguageLevel
DSC comment. The "set_min_langlevel" method can be used to raise the language level, but it cannot be decreased. (Default: undef
, meaning omit the %%LanguageLevel
comment)
order
$ps = PostScript::File->new( order => $order )
$order = $ps->get_order
The order the pages are defined in the document, for use in the %%PageOrder
DSC comment. It must be one of "Ascend", "Descend" or "Special" (meaning a document manager must not reorder the pages). The default is undef
, meaning omit the %%PageOrder
comment.
strip (attribute)
$ps = PostScript::File->new( strip => $strip )
$strip = $ps->get_strip
$ps->set_strip( $strip )
Determine whether the PostScript code is filtered. $strip
must be one of the following values: space
strips leading spaces so the user can indent freely without increasing the file size. comments
removes lines beginning with '%' as well. all_comments
(v2.20) also removes comments that aren't at the beginning of a line. See also the strip method, which actually does the filtering described here.
Passing undef
or omitting $strip
sets it to the default value, space
.
title
$ps = PostScript::File->new( title => $title )
$title = $ps->get_title
The document's title for use in the %%Title
DSC comment. The default (undef
) means to use the document's filename as the title. If no filename is available when the document is output, the %%Title
comment wil be omitted.
version
$ps = PostScript::File->new( version => $version )
$version = $ps->get_version
The document's version for use in the %%Version
DSC comment. The $version
should be a string in the form VERNUM REV
, where VERNUM
is a floating point number and REV
is an unsigned integer. (Default: undef
, meaning omit the %%Version
comment)
Paper Size and Margins
These attributes are interrelated, and changing one may change the others.
bounding_box
( $llx, $lly, $urx, $ury ) = $ps->get_bounding_box
$ps->set_bounding_box( $llx, $lly, $urx, $ury )
The bounding box for the whole document. The lower left corner is ($llx, $lly)
, and the upper right corner is ($urx, $ury)
.
Setting the bounding box automatically enables clipping. Call $ps->set_clipping(0)
afterwards to undo that.
The default bounding_box
is calculated from the paper size (taken from the "paper", "height", and "width" attributes) and the "left", "right", "top", and "bottom" margins.
Each page also has an individual "page_bounding_box", which is initialized from the document's bounding_box
when the page is created.
height
$ps = PostScript::File->new( height => $height )
$height = $ps->get_height
$ps->set_height( $height )
The page height in points. This is normally the longer dimension of the paper. Note that in landscape mode this is actually the width of the bounding box.
Setting this sets "paper" to "Custom" and the "bounding_box" is expanded to the full height.
landscape
$ps = PostScript::File->new( landscape => $landscape )
$landscape = $ps->get_landscape
$ps->set_landscape( $landscape )
If $landscape
is true, the page is rotated 90 degrees counter-clockwise, swapping the meaning of height & width. (Default: false)
In landscape mode the coordinates are rotated 90 degrees and the origin moved to the bottom left corner. Thus the coordinate system appears the same to the user, with the origin at the bottom left.
paper
$ps = PostScript::File->new( paper => $paper_size )
$paper_size = $ps->get_paper
$ps->set_paper( $paper_size )
Set the paper size of each page. A document can be created using a standard paper size without having to remember the size of paper using PostScript points. Valid choices are currently A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, Executive, Folio, Half-Letter, Letter, US-Letter, Legal, US-Legal, Tabloid, SuperB, Ledger, 'Comm #10 Envelope', Envelope-Monarch, Envelope-DL, Envelope-C5, and EuroPostcard. (Default: "A4")
You can also give a string in the form 'WIDTHxHEIGHT', where WIDTH and HEIGHT are numbers (in points). This sets the paper size to "Custom".
Setting this also sets "bounding_box", "height", and "width" to the full height and width of the paper.
width
$ps = PostScript::File->new( width => $width )
$width = $ps->get_width
$ps->set_width( $width )
The page width in points. This is normally the shorter dimension of the paper. Note that in landscape mode this is actually the height of the bounding box.
Setting this sets "paper" to "Custom" and the "bounding_box" is expanded to the full width.
Page Attributes
The following attributes can have a different value for every page. You can't set them directly in the constructor, but they all have a document-wide default value that each page inherits when it is created. When accessing or setting them, $page
is the page label. If $page
is omitted, it defaults to the current page.
page_bounding_box
( $llx, $lly, $urx, $ury ) = $ps->get_page_bounding_box( [$page] )
$ps->set_page_bounding_box( [$page,] $llx, $lly, $urx, $ury )
The bounding box for this page. The lower left corner is ($llx, $lly)
, and the upper right corner is ($urx, $ury)
.
Note that calling set_page_bounding_box
automatically enables clipping for that page. If this isn't what you want, call $ps->set_page_clipping(0)
afterwards.
When a page is created, page_bounding_box
is initialized from the document's "bounding_box" attribute.
page_clipping
$clipping = $ps->get_page_clipping( [$page] )
$ps->set_page_clipping( [[$page,] $clipping] )
If $clipping
is true, printing will be clipped to this page's bounding box. (Default: false)
When a page is created, page_clipping
is initialized from the document's "clipping" attribute.
page_label
$ps = PostScript::File->new( page => $page )
$page = $ps->get_page_label
$ps->set_page_label( [$page] )
The label for the current page (used in the %%Page
comment). (Default: "1")
Unlike the other page attributes, you can only access the page_label
of the current page. (Since pages are specified by label, it makes no sense to ask for the label of a different page.)
When a page is created, page_label
is initialized by passing the previous page's label to the "incpage_handler". For the first page, it's initialized from the page
given to the constructor.
page_landscape
$landscape = $ps->get_page_landscape( [$page] )
$ps->set_page_landscape( [[$page,] $landscape] )
If $landscape
is true, this page is using landscape mode. (Default: false)
When a page is created, page_landscape
is initialized from the document's "landscape" attribute.
METHODS
Note: In the following descriptions, []
are used to denote optional parameters, not array references.
Constructor
new
$ps = PostScript::File->new(options)
Create a new PostScript::File object, either a set of pages or an Encapsulated PostScript (EPS) file. Options are hash keys and values. All values should be in the native PostScript units of 1/72 inch.
Example
$ps = PostScript::File->new(
eps => 1,
landscape => 1,
width => 216,
height => 288,
left => 36,
right => 44,
clipping => 1,
);
This creates an Encapsulated PostScript document, 4 by 3 inch pages printing landscape with left and right margins of around half an inch. The width is always the shortest side, even in landscape mode. 3*72=216 and 4*72=288. Being in landscape mode, these would be swapped. The bounding box used for clipping would then be from (50,0) to (244,216).
options
may be a single hash reference instead of an options list, but the hash must have the same structure. This is more convenient when used as a base class.
The following keys are recognized options:
Attributes
The following attributes can be set through the constructor: "auto_hyphen", "clipping", "eps", "extensions", "file_ext", "filename", "height", "incpage_handler", "landscape", "langlevel", "order", "page_label", "paper", strip, "title", "version", and "width".
File size keys
There are four options which control how much gets put into the resulting file.
debug
undef
-
No debug code is added to the file. Of course there must be no calls to debug functions in the PostScript code. This is the default.
0
-
db_ functions are replaced by dummy functions which do nothing.
1
-
A range of functions are added to the file to support debugging PostScript. This switch is similar to the 'C'
NDEBUG
macro in that debugging statements may be left in the PostScript code but their effect is removed.Of course, being an interpreted language, it is not quite the same as the calls still takes up space - they just do nothing. See "POSTSCRIPT DEBUGGING SUPPORT" for details of the functions.
2
-
Loads the debug functions and gives some reassuring output at the start and a stack dump at the end of each page.
A mark is placed on the stack at the beginning of each page and 'cleartomark' is given at the end, avoiding potential
invalidrestore
errors. Note, however, that if the page does not end with a clean stack, it will fail when debugging is turned off.
errors
PostScript has a nasty habit of failing silently. If errors
is true, code that prints fatal error messages on the bottom left of the paper is added to the file. For user functions, a PostScript function report_error is defined. This expects a message string on the stack, which it prints before stopping. (Default: true)
headings
If true, add PostScript DSC comments recording the date of creation and user's name. (Default: false)
The comments inserted when headings
is true are:
%%For: USER@HOSTNAME
%%Creator: Perl module PostScript::File v2.22
%%CreationDate: Sun Jan 1 00:00:00 2012
%%DocumentMedia: US-Letter 612 792 80 ( ) ( )
USER comes from getlogin() || getpwuid($<)
, and HOSTNAME comes from Sys::Hostname. The DocumentMedia values come from the paper size attributes. The DocumentMedia comment is omitted from EPS files.
If you want different values, leave headings
false and use "add_comment" to add whatever you want.
reencode
Requests that a font re-encode function be added and that the fonts used by this document get re-encoded in the specified encoding. The only allowed values are cp1252
, iso-8859-1
, and ISOLatin1Encoding
. You should almost always set this to cp1252
, even if you are not using Windows.
The list of fonts to re-encode comes from the "need_fonts" parameter, the "need_resource" method, and all fonts added using "embed_font" or "add_resource". The Symbol font is never re-encoded, because it uses a non-standard character set.
Setting this to cp1252
or iso-8859-1
also causes the document to be encoded in that character set. Any strings you add to the document that have the UTF-8 flag set will be reencoded automatically. Strings that do not have the UTF-8 flag are expected to be in the correct character set already. This means that you should be able to set this to cp1252
, use Unicode characters in your code and the "-iso" versions of the fonts, and just have it do the right thing.
Windows code page 1252 (a.k.a. WinLatin1) is a superset of the printable characters in ISO-8859-1 (a.k.a. Latin1). It adds a number of characters that are not in Latin1, especially common punctuation marks like the curly quotation marks, en & em dashes, Euro sign, and ellipsis. These characters exist in the standard PostScript fonts, but there's no easy way to access them when using the standard or ISOLatin1 encodings. http://en.wikipedia.org/wiki/Windows-1252
For backwards compatibility with versions of PostScript::File older than 1.05, setting this to ISOLatin1Encoding
reencodes the fonts, but does not do any character set translation in the document.
Initialization keys
There are a few initialization settings that are only relevant when the file object is constructed.
bottom
The margin in from the paper's bottom edge, specifying the non-printable area. Remember to specify clipping
if that is what is wanted. (Default: 28)
clip_command
The bounding box is used for clipping if this is set to "clip" or is drawn with "stroke". This also makes the whole page area available for debugging output. (Default: "clip").
font_suffix
This string is appended to each font name as it is reencoded. (Default: "-iso")
The string value is appended to these to make the new names.
Example:
$ps = PostScript::File->new(
font_suffix => "-iso",
reencode => "cp1252"
);
"Courier" still has the standard mapping while "Courier-iso" includes the additional European characters.
left
The margin in from the paper's left edge, specifying the non-printable area. Remember to specify clipping
if that is what is wanted. (Default: 28)
need_fonts
An arrayref of font names required by this document. This is equivalent to calling $ps->need_resource(font => @$arrayref)
. See "need_resource" for details.
newpage
(v2.10) Normally, an initial page is created automatically (using the label specified by page
). But starting with PostScript::File 2.10, you can pass newpage => 0
to override this. This makes for more natural loops:
use PostScript::File 2.10;
my $ps = PostScript::File->new(newpage => 0);
for (@pages) {
$ps->newpage; # don't need "unless first page"
...
}
It's important to require PostScript::File 2.10 if you do this, because older versions would produce an initial blank page.
If you don't pass a page label to the first call to newpage
, it will be taken from the page
option. After the first page, the page label will increment as specified by "incpage_handler".
right
The margin in from the paper's right edge. It is a positive offset, so right=36
will leave a half inch no-go margin on the right hand side of the page. Remember to specify clipping
if that is what is wanted. (Default: 28)
top
The margin in from the paper's top edge. It is a positive offset, so top=36
will leave a half inch no-go margin at the top of the page. Remember to specify clipping
if that is what is wanted. (Default: 28)
Debugging support keys
This makes most sense in the PostScript code rather than Perl. However, it is convenient to be able to set defaults for the output position and so on. See "POSTSCRIPT DEBUGGING SUPPORT" for further details.
db_active
Set to 0 to temporarily suppress the debug output. (Default: 1)
db_base
Debug printing will not occur below this point. (Default: 6)
db_bufsize
The size of string buffers used. Output must be no longer than this. (Default: 256)
db_color
This is the whole PostScript command (with any parameters) to specify the colour of the text printed by the debug routines. (Default: "0 setgray")
db_font
The name of the font to use. (Default: "Courier")
Courier
Courier-Bold
Courier-BoldOblique
Courier-Oblique
Helvetica
Helvetica-Bold
Helvetica-BoldOblique
Helvetica-Oblique
Times-Roman
Times-Bold
Times-BoldItalic
Times-Italic
Symbol
db_fontsize
The size of the font. PostScript uses its own units, but they are almost points. (Default: 10)
db_xgap
Typically, the output comprises single values such as a column showing the stack contents. db_xgap
specifies the width of each column. By default, this is calculated to allow 4 columns across the page.
db_xpos
The left edge, where debug output starts. (Default: 6)
db_xtab
The amount indented by db_indent
. (Default: 10)
db_ytop
The top line of debugging output. Defaults to 6 below the top of the page.
Error handling keys
If errors
is set, the position of any fatal error message can be controlled with the following options. Each value is placed into a PostScript variable of the same name, so they can be overridden from within the code if necessary.
errfont
The name of the font used to show the error message. (Default: "Courier-Bold")
errmsg
The error message comprises two lines. The second is the name of the PostScript error. This sets the first line. (Default: "ERROR:")
errsize
Size of the error message font. (Default: 12)
errx
X position of the error message on the page. (Default: (72))
erry
Y position of the error message on the page. (Default: (72))
Main Methods
newpage
$ps->newpage( [$page] )
Generate a new PostScript page, unless in a EPS file when it is ignored.
If $page
is not specified the previous page's label is incremented using the "incpage_handler".
output
$ps->output( [$file, [$dir]] )
If $file
is an open filehandle, write the PostScript document to that filehandle and return nothing.
If a filename has been given either here, to new
, or to set_filename
, write the PostScript document to that file and return its pathname. ($file
and $dir
have the same meaning here as they do in set_filename.)
If no filename has been given, or $file
is undef, return the PostScript document as a string.
In eps
mode, each page of the document becomes a separate EPS file. In list context, returns a list of these files (either the pathname or the PostScript code as explained above). In scalar context, only the first page is returned (but all pages will still be processed). If you pass a filehandle when you have multiple pages, all the documents are written to that filehandle, which is probably not what you want.
Use this option whenever output is required to disk. The current PostScript document in memory is not cleared, and can still be extended or output again.
as_string
$postscript_code = $ps->as_string
This returns the PostScript document as a string. It is equivalent to $ps->output(undef)
.
testable_output
$postscript_code = $ps->testable_output( [$verbatim] )
This returns the PostScript document as a string, but with the PostScript::File generated code removed (unless $verbatim
is true). This is intended for use in test scripts, so they won't see changes in the output caused by different versions of PostScript::File. The PostScript code returned by this method will probably not work in a PostScript interpreter.
If $verbatim
is true, this is equivalent to $ps->output(undef)
.
Access Methods
Use these get_
and set_
methods to access a PostScript::File object's data.
get_metrics
$metrics = $ps->get_metrics( $font, [$size, [$encoding]] )
Construct a PostScript::File::Metrics object for $font
. The $encoding
is normally determined automatically from the font name and the document's encoding. The default $size
is 1000.
If this document uses "reencode", and the font ends with "font_suffix", then the Metrics object will use that encoding. Otherwise, the encoding is std
(except for the Symbol font, which always uses sym
).
No matter what encoding the font uses, the Metrics object will always use the same Unicode translation setting as this document. It also inherits the current value of the "auto_hyphen" attribute.
set_min_langlevel
$new_langlevel = $ps->set_min_langlevel( $langlevel )
(v2.20) Set the "langlevel" attribute of this document to $langlevel
, but only if the current level is less than $langlevel
. It returns the value of langlevel
, which will be greater than or equal to $langlevel
.
set_page_margins
$ps->set_page_margins( [$page,] $left, $bottom, $right, $top )
This sets the "page_bounding_box" based on the paper size and the specified margins. It also automatically enables clipping for the page. If this isn't what you want, call $ps->set_page_clipping(0)
afterwards.
get_page_printable_height
$height = $ps->get_page_printable_height( [$page] )
(v2.10) Returns the height of the page's bounding box (ury - lly
).
get_page_printable_width
$width = $ps->get_page_printable_width( [$page] )
(v2.10) Returns the width of the page's bounding box (urx - llx
.
get_page_variable
$value = $ps->get_page_variable( $key )
Retrieve a user defined value previously assigned by "set_page_variable".
set_page_variable
$ps->set_page_variable( $key, $value )
Assign a user defined hash key and value only valid on the current page. Provided to keep track of states within the PostScript code, such as which styles are currently active. PostScript::File does not use this (except to clear it at the start of each page). It is recommended that $key
is the module name to avoid clashes. The $value
could then be a hash holding any number of user variables.
get_pagecount
$pages = $ps->get_pagecount
Returns the number of pages currently in the document.
get_printable_height
$height = $ps->get_printable_height
(v2.10) Returns the height of the document's bounding box (ury - lly
).
get_printable_width
$width = $ps->get_printable_width
(v2.10) Returns the width of the document's bounding box (urx - llx
).
get_variable
$value = $ps->get_variable( $key )
Retrieve a user defined value previously assigned by "set_variable".
set_variable
$ps->set_variable( $key, $value )
Assign a user defined hash key and value. Provided to keep track of states within the PostScript code, such as which dictionaries are currently open. PostScript::File does not use this - it is provided for client programs. It is recommended that $key
is the module name to avoid clashes. The $value
could then be a hash holding any number of user variables.
Content Methods
add_comment
$ps->add_comment( $comment )
Append a comment to the document's DSC comments section. Most of the required and recommended comments are set directly from the document's attributes, so this method should rarely be needed. It is provided for completeness so that comments not otherwise supported can be added. $comment
should contain the bare PostScript DSC name and value, with additional lines merely prefixed by +
. It should NOT end with a newline.
Programs written for older versions of PostScript::File might use this to add a DocumentNeededResources
comment. That is now deprecated; you should use "need_resource" instead.
Examples:
$ps->add_comment("ProofMode: NotifyMe");
$ps->add_comment("Requirements: manualfeed");
get_comments
$comments = $ps->get_comments
Retrieve any extra DSC comments added by "add_comment".
add_default
$ps->add_default( $default )
Use this to append a PostScript DSC comment to the Defaults section. These would be typically values like PageCustomColors:
or PageRequirements:
. The format is the same as for "add_comment".
get_defaults
$comments = $ps->get_defaults
Returns the contents of the DSC Defaults section, if any.
embed_document
$code = $ps->embed_document( $filename )
This reads the contents of $filename
, which should be a PostScript file. It returns a string with the contents of the file surrounded by %%BeginDocument
and %%EndDocument
comments, and adds $filename
to the list of document supplied resources.
You must pass the returned string to add_to_page or some other method that will actually include it in the document.
embed_font
$font_name = $ps->embed_font( $filename, [$type] )
This reads the contents of $filename
, which must contain a PostScript font. It calls "add_resource" to add the font to the document, and returns the name of the font (without a leading slash).
If $type
is omitted, the $filename
's extension is used as the type. Type names are not case sensitive. The currently supported types are:
- PFA
-
A PostScript font in ASCII format
- PFB
-
A PostScript font in binary format. This requires the t1ascii program from http://www.lcdf.org/type/#t1utils. (You can set
$PostScript::File::t1ascii
to the name of the program to use. It defaults to t1ascii.) - TTF
-
A TrueType font. This requires the ttftotype42 program from http://www.lcdf.org/type/#typetools. (You can set
$PostScript::File::ttftotype42
to the name of the program to use. It defaults to ttftotype42.)Since TrueType (a.k.a. Type42) font support was introduced in PostScript level 2, embedding a TTF font automatically sets
langlevel
to 2 (unless it was already set to a higher level). Be aware that not all printers can handle Type42 fonts. (Even PostScript level 2 printers need not support them.) Ghostscript does support Type42 fonts (when compiled with thettfont
option).
need_resource
$ps->need_resource( $type, @resources )
This adds resources to the DocumentNeededResources comment. $type
is one of encoding
, file
, font
, form
, pattern
, or procset
(case sensitive).
Any number of resources (of a single type) may be added in one call. For most types, $resource[N]
is just the resource name. But for procset
, each element of @resources
should be an arrayref of 3 elements: [$name, $version, $revision]
. Names that contain special characters such as spaces will be quoted automatically.
If need_resource
is never called for the font
type (and "need_fonts" is not used), it assumes the document requires all 13 of the standard PostScript fonts: Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique, Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique, Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic, and Symbol. But this behaviour is deprecated; a document should explicitly list the fonts it requires. If you don't use any of the standard fonts, pass need_fonts => []
to the constructor (or call $ps->need_resource('font')
) to indicate that.
add_to_page
$ps->add_to_page( [$page,] $code )
This appends $code
to the specified $page
, which can be any page label. (Default: the current page)
If the specified $page
does not exist, a new page is added with that label. Note that this is added on the end, not in the order you might expect. So adding "vi" to page set "iii, iv, v, 6, 7, 8" would create a new page after "8" not after "v".
Examples
$ps->add_to_page( <<END_PAGE );
...PostScript building this page
END_PAGE
$ps->add_to_page( "3", <<END_PAGE );
...PostScript building page 3
END_PAGE
The first example adds code onto the end of the current page. The second one either adds additional code to page 3 if it exists, or starts a new one.
get_page
$code = $ps->get_page( [$page] )
Returns the PostScript code from the body of the page.
add_page_setup
$ps->add_page_setup( $code )
Appends $code
to the DSC PageSetup section. Note that this is a document-global value, although the code will be repeated on each page.
Also note that any settings defined here will be active for each page seperately. Use "add_setup" if you want to carry settings from one page to another.
get_page_setup
$setup = $ps->get_page_setup
Returns the contents of the DSC PageSetup section, if any. Note that this is a document-global value, although the code will be repeated on each page.
add_page_trailer
$ps->add_page_trailer( $code )
Appends $code
to the DSC PageTrailer section. Note that this is a document-global value, although the code will be repeated on each page.
Code added here is output after each page. It may refer to settings made during "add_page_setup" or "add_to_page".
get_page_trailer
$code = $ps->get_page_trailer
Returns the contents of the DSC PageTrailer section, if any. Note that this is a document-global value, although the code will be repeated on each page.
add_preview
$ps->add_preview( $width, $height, $depth, $lines, $preview )
Sets the EPSI format preview for this document - an ASCII representation of a bitmap. Only EPS files should have a preview, but that is not enforced. If an EPS file has a preview it becomes an EPSI file rather than EPSF.
get_preview
$preview = $ps->get_preview
Returns the EPSI preview of the document, if any, including the %%BeginPreview
and %%EndPreview
comments.
add_procset
$ps->add_procset( $name, $code, [$version, [$revision]] )
(v2.20) Add a ProcSet containing user defined functions to the PostScript prolog. $name
is an arbitrary identifier of this resource. $code
is a block of PostScript code, usually from a 'here' document. If the document already contains ProcSet $name
(as reported by has_procset
, then add_procset
does nothing.
$version
is a real number, and $revision
is an unsigned integer. They both default to 0. PostScript::File does not make any use of these, but a PostScript document manager may assume that a procset with a higher revision number may be substituted for a procset with the same name and version but a lower revision.
Returns true if the ProcSet was added, or false if it already existed.
Example
$ps->add_procset( "My_Functions", <<END_FUNCTIONS );
% PostScript code can be freely indented
% as leading spaces and blank lines
% (and comments, if desired) are stripped
% foo does this...
/foo {
... definition of foo
} bind def
% bar does that...
/bar {
... definition of bar
} bind def
END_FUNCTIONS
Note that get_procsets
(in common with the others) will return all user defined functions possibly including those added by other classes.
has_procset
$exists = $ps->has_procset( $name )
(v2.20) This returns true if $name
has already been included in the file. The name should be identical to that given to "add_procset".
get_procsets
$code = $ps->get_procsets
(v2.20) Return all the procsets defined in this document.
add_resource
$ps->add_resource( $type, $name, $params, $resource )
$type
-
A string indicating the DSC type of the resource. It should be one of
Document
,Feature
,encoding
,file
,font
,form
, orpattern
(case sensitive). $name
-
An arbitrary identifier of this resource. (For a Font, it must be the PostScript name of the font, without a leading slash.)
$params
-
Some resource types require parameters. See the Adobe documentation for details.
$resource
-
A string containing the PostScript code. Probably best provided a 'here' document.
Use this to add fonts or images (although you may prefer "embed_font" or "embed_document"). "add_procset" is provided for functions.
Example
$ps->add_resource( "File", "My_File1",
"", <<END_FILE1 );
...PostScript resource definition
END_FILE1
get_resources
$resources = $ps->get_resources
Returns all resources provided by this document. This does not include procsets.
add_setup
$ps->add_setup( $code )
This appends $code
to the DSC Setup section. Use this for setpagedevice
, statusdict
or other settings that initialize the device or document.
get_setup
$setup = $ps->get_setup
Returns the contents of the DSC Setup section, if any.
add_trailer
$ps->add_trailer( $code )
Appends $code
to the document's DSC Trailer section. Use this for any tidying up after all the pages are output.
get_trailer
$code = $ps->get_trailer
Returns the contents of the document's DSC Trailer section, if any.
use_functions
$ps->use_functions( @function_names )
This requests that the PostScript functions listed in @function_names
be included in this document. See PostScript::File::Functions for a list of available functions.
Text Processing Methods
convert_hyphens
$converted_text = $ps->convert_hyphens( $text )
Converts any HYPHEN-MINUS (U+002D) characters in $text
to either HYPHEN (U+2010) or MINUS SIGN (U+2212) according to the rules described in "Hyphens and Minus Signs". This has the side-effect of setting the UTF-8 flag on $converted_text
.
If $text
does not have the UTF-8 flag set, it is assumed to be in the document's character encoding.
If $text
does not contain any HYPHEN-MINUS characters, it is returned as-is.
decode_text
$text = $ps->decode_text( $encoded_text, [$preserve_minus] )
This is the inverse of "encode_text". It converts $encoded_text
from the document's character encoding into Unicode. If $encoded_text
already has the UTF-8 flag set, or the document is not using character translation, then it returns $encoded_text
as-is.
If the optional argument $preserve_minus
is true (and $encoded_text
is not being returned as-is), then any HYPHEN-MINUS (U+002D) characters in $encoded_text
are decoded as MINUS SIGN (U+2212). This ensures that encode_text
will treat them as minus signs instead of hyphens.
encode_text
$encoded_text = $ps->encode_text( $text )
This returns $text
converted to the document's character encoding. If $text
does not have the UTF-8 flag set, or the document is not using character translation, then it returns $text
as-is.
pstr
$code = $ps->pstr( $string, [$nowrap] )
$code = PostScript::File->pstr( $string, [$nowrap] )
$code = pstr( $string )
Converts the string to a PostScript string literal. If the result is more than 240 characters, it will be broken into multiple lines. (A PostScript file should not contain lines with more than 255 characters.)
When called as a class or object method, you can pass a second parameter $nowrap
. If this optional parameter is true, then the string will not be wrapped, no matter how long it is.
When called as an object method, pstr
will do automatic hyphen-minus translation if "auto_hyphen" is true. This has the side-effect of setting the UTF-8 flag on the returned string. (If the UTF-8 flag was not set on the input string, it will be decoded using the document's character set.) See "Hyphens and Minus Signs". For this reason, pstr
should normally be called as an object method.
strip (method)
$ps->strip( $code )
$ps->strip( $strip => @code )
The strip
method filters PostScript code according to the value of $strip
, which can be any valid value for the strip attribute. The code is modified in-place; there is no return value. If $code
is undef
, it is left unchanged.
When called with a single argument, strips $code
according to the current value of the strip
attribute.
SUBROUTINES
array_as_string
$code = array_as_string( @array )
Converts a Perl array to a PostScript array literal. The array elements are used as-is. If you want an array of strings, you should do something like:
$code = array_as_string( map { $ps->pstr($_) } @array )
check_file
$pathname = check_file( $file, [$dir, [$create]] )
$file
-
An optional fully qualified path-and-file or a simple file name. If omitted or the empty string, the special file
File::Spec->devnull
is returned. $dir
-
An optional directory path. If defined (and
$file
is not already an absolute path), it is prepended to$file
. $create
-
If true, create the file if it doesn't exist already. (Default: false)
This converts a filename and optional directory to an absolute path, and then creates any directories that don't already exist. Any leading ~
is expanded to the user's home directory using "check_tilde".
If $create
is true, and $pathname
does not exist, it is created as an empty file.
File::Spec is used throughout so file access should be portable.
check_tilde
$expanded_path = check_tilde( $path )
Expands a leading ~
or ~user
in $path
to the home directory.
incpage_label
$next_label = incpage_label( $label )
This function applies Perl's autoincrement operator to $label
and returns the result. (This means that the magic string autoincrement applies to values that match /^[a-zA-Z]*[0-9]*\z/
.)
This function is the default value of the "incpage_handler" attribute.
incpage_roman
$next_label = incpage_roman( $label )
This function increments lower case Roman numerals. $label
must be a value between "i" and "xxxviii" (1 to 38), and $next_label
will be "ii" to "xxxix" (2 to 39). That should be quite enough for numbering the odd preface.
This function is normally used as the value of the "incpage_handler" attribute:
$ps->set_incpage_handler( \&PostScript::File::incpage_roman )
quote_text
$quoted = quote_text( $string )
$quoted = PostScript::File->quote_text( $string )
$quoted = $ps->quote_text( $string )
Quotes the string if it contains special characters, making it suitable for a DSC comment. Strings without special characters are returned unchanged.
This may also be called as a class or object method, but it does not do hyphen-minus translation, even if "auto_hyphen" is true.
str
$code = str( $value )
If $value
is an arrayref, returns array_as_string(@$value)
. Otherwise, returns $value
as-is. This function was designed to simplify passing colors to the PostScript function "setColor" in PostScript::File::Functions, which expects either an RGB array or a greyscale decimal.
POSTSCRIPT DEBUGGING SUPPORT
This section documents the PostScript functions which provide debugging output. Please note that any clipping or bounding boxes will also hide the debugging output which by default starts at the top left of the page. Typical new
options required for debugging would include the following.
$ps = PostScript::File->new (
errors => "page",
debug => 2,
clipcmd => "stroke" );
The debugging output is printed on the page being drawn. In practice this works fine, especially as it is possible to move the output around. Where the text appears is controlled by a number of PostScript variables, most of which may also be given as options to new
.
The main controller is db_active
which needs to be non-zero for any output to be seen. It might be useful to set this to 0 in new
, then at some point in your code enable it. Remember that the debugdict
dictionary needs to be selected in order for any of its variables to be changed. This is better done with db_on
but it illustrates the point.
/debugdict begin
/db_active 1 def
end
(this will now show) db_show
At any time, the next output will appear at db_xpos
and db_ypos
. These can of course be set directly. However, after most prints, the equivalent of a 'newline' is executed. It moves down db_fontsize
and left to db_xpos
. If, however, that would take it below db_ybase
, db_ypos
is reset to db_ytop
and the x coordinate will have db_xgap
added to it, starting a new column.
The positioning of the debug output is changed by setting db_xpos
and db_ytop
to the top left starting position, with db_ybase
guarding the bottom. Extending to the right is controlled by not printing too much! Judicious use of db_active
can help there.
PostScript functions
x0 y0 x1 y1 cliptobox
This function is only available if 'clipping' is set. By calling the Perl method draw_bounding_box
(and resetting with clip_bounding_box
) it is possible to use this to identify areas on the page.
$ps->draw_bounding_box();
$ps->add_to_page( <<END_CODE );
...
my_l my_b my_r my_t cliptobox
...
END_CODE
$ps->clip_bounding_box();
msg report_error
If 'errors' is enabled, this call allows you to report a fatal error from within your PostScript code. It expects a string on the stack and it does not return.
All the db_
variables (including function names) are defined within their own dictionary (debugdict
). But this can be ignored by all calls originating from within code passed to add_to_page
(usually including add_procset
code) as the dictionary is automatically put on the stack before each page and taken off as each finishes.
any db_show
The workhorse of the system. This takes the item off the top of the stack and outputs a string representation of it. So you can call it on numbers or strings and it will show them. Arrays are printed using db_array
and marks are shown as '--mark--'.
n msg db_nshow
This shows top n
items on the stack. It requires a number and a string on the stack, which it removes. It prints out msg
then the top n
items on the stack, assuming there are that many. It can be used to do a labelled stack dump. Note that if new
was given the option debug =
2>, There will always be a '--mark--' entry at the base of the stack. See "debug".
count (at this point) db_nshow
db_stack
Prints out the contents of the stack. No stack requirements.
The stack contents is printed top first, the last item printed is the lowest one inspected.
array db_print
The closest this module has to a print statement. It takes an array of strings and/or numbers off the top of the stack and prints them with a space in between each item.
[ (myvar1=) myvar1 (str2=) str2 ] db_print
will print something like the following.
myvar= 23.4 str2= abc
When printing something from the stack you need to take into account the array-building items, too. In the next example, at the point '2 index' fetches 111, the stack holds '222 111 [ (top=)' but 'index' requires 5 to get at 222 because the stack now holds '222 111 [ (top=) 111 (next=)'.
222 111
[ (top=) 2 index (next=) 5 index ] db_print
willl output this.
top= 111 next= 222
It is important that the output does not exceed the string buffer size. The default is 256, but it can be changed by giving new
the option bufsize
.
x y msg db_point
It is common to have coordinates as the top two items on the stack. This call inspects them. It pops the message off the stack, leaving x and y in place, then prints all three.
450 666
(starting point=) db_print
moveto
would produce:
starting point= ( 450 , 666 )
array db_array
Like "db_print" but the array is printed enclosed within square brackets.
var db_where
A 'where' search is made to find the dictionary containing var
. The messages 'found' or 'not found' are output accordingly. Of course, var
should be quoted with '/' to put the name on the stack, otherwise it will either be executed or force an error.
db_newcol
Starts the next debugging column. No stack requirements.
db_on
Enable debug output
db_off
Disable debug output
db_down
Does a 'carriage-return, line-feed'. No stack requirements.
db_indent
Moves output right by db_xtab
. No stack requirements. Useful for indenting output within loops.
db_unindent
Moves output left by db_xtab
. No stack requirements.
EXPORTS
No functions are exported by default. All the functions listed in "SUBROUTINES" may be exported by request.
In addition, the pstr
method may be exported as a subroutine, but this usage is deprecated.
BUGS AND LIMITATIONS
When making EPS files, the landscape transformation throws the coordinates off. To work around this, avoid the landscape flag and set width and height differently.
Most of these functions have only had a couple of tests, so please feel free to report all you find.
AUTHOR
Chris Willmot <chris AT willmot.co.uk>
Thanks to Johan Vromans for the ISOLatin1Encoding.
As of September 2009, PostScript::File is now being maintained by Christopher J. Madsen <perl AT cjmweb.net>
.
Please report any bugs or feature requests to <bug-PostScript-File AT rt.cpan.org>
, or through the web interface at http://rt.cpan.org/Public/Bug/Report.html?Queue=PostScript-File
You can follow or contribute to PostScript::File's development at https://github.com/madsen/postscript-file.
COPYRIGHT AND LICENSE
Copyright 2002, 2003 Christopher P Willmot. All rights reserved.
Copyright 2015 Christopher J. Madsen. All rights reserved.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
SEE ALSO
PostScript Language Document Structuring Conventions Specification Version 3.0 and Encapsulated PostScript File Format Specification Version 3.0 published by Adobe, 1992. http://partners.adobe.com/asn/developer/technotes/postscript.html
PostScript::Convert, for PDF or PNG output.
PostScript::Calendar, for creating monthly calendars.
PostScript::Report, for creating tabular reports.
PostScript::ScheduleGrid, for printing schedules in a grid format.
PostScript::ScheduleGrid::XMLTV, for printing TV listings in a grid format.
PostScript::Graph::Paper, PostScript::Graph::Style, PostScript::Graph::Key, PostScript::Graph::XY, PostScript::Graph::Bar, PostScript::Graph::Stock.
DISCLAIMER OF WARRANTY
BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.