NAME¶
PostScript::File - Class for creating Adobe PostScript files
VERSION¶
This document describes version 2.20 of PostScript::File, released February 11,
2012 as part of PostScript-File version 2.20.
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"), or "undef" (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.20
%%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 re-encoded 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
<
http://en.wikipedia.org/wiki/Windows-1252>
For backwards compatibility with versions of PostScript::File older than 1.05,
setting this to "ISOLatin1Encoding" re-encodes 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 re-encoded. (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 the "ttfont" 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
separately. 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", or
"pattern" (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
<
http://rt.cpan.org/Public/Bug/Report.html?Queue=PostScript-File>
You can follow or contribute to PostScript::File's development at
http://github.com/madsen/postscript-file
<
http://github.com/madsen/postscript-file>.
COPYRIGHT AND LICENSE¶
Copyright 2002, 2003 Christopher P Willmot. All rights reserved.
Copyright 2012 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.