PostScript::File(3pm)

๐Ÿ“ฆ
version 2.23 ยท 3 versions
, in ubuntu noble, ubuntu resolute, ubuntu stonking

โœจ NAME โœจ

PostScript::File โ€” that's this one, and it's the 3pm manual page, bestie ๐Ÿ’– โ€” a whole class for creating Adobe PostScript files. Slay.


๐ŸŽ€ VERSION ๐ŸŽ€

Okay so this document describes version 2.23 of PostScript::File, released October 10, 2015 as part of PostScript-File version 2.23. Periodt.

Anything attributes-and-methods-wise that got added since version 2.00 is marked with the version it showed up in (like "(v2.10)") so you can tell what's new-new.

Real talk: because there were significant API changes in 2.00, the author recommends that any code using PostScript::File specify a minimum version of at least 2. Don't skip that, fr fr. ๐Ÿ™ˆ

๐ŸŒธ SYNOPSIS ๐ŸŒธ

๐Ÿฆ‹ Simplest ๐Ÿฆ‹

A 'hello world' program, because of course we start there:

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 ๐Ÿฆ‹

Every single knob, turned at once. Look at her go ๐Ÿ’…:

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). The vibe check here: if you're using this class directly, you should already be familiar with the DSC. Go consult the PostScript Language Document Structuring Conventions Specification linked to in "SEE ALSO" โ€” it's giving required reading, ngl.

There are also a bunch of modules that build on top of PostScript::File to produce all kinds of documents without you needing any PostScript knowledge at all. Those are listed in "SEE ALSO" too. Iconic of them.

You can construct and output files either as normal PostScript (*.ps files) or as Encapsulated PostScript (*.epsf or *.epsi files). By default you get a minimal file, but if you want font encoding, PostScript error reporting, and debugging built in โ€” you can absolutely have all that.

Documents can typically be built using only these functions, which is the whole main-character lineup:

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 is all about fine-tuning. Some settings only really make sense when you give them once, while others can control each page independently. Check "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 that insert entries into each of the DSC sections all start with add_. They also have get_ counterparts. Consistency, we love to see it:

add_comment
add_preview
add_default
add_resource
add_procset
add_setup
add_page_setup
add_to_page
add_page_trailer
add_trailer

And finally, there are a few stand-alone functions. These are not methods, and they're available for export if you ask nicely:

check_tilde
check_file
incpage_label
incpage_roman

๐Ÿ’ซ Hyphens and Minus Signs ๐Ÿ’ซ

Okay bestie, this part is the drama. 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, being extra, has two separate characters, which it calls /hyphen and /minus. The difference? /minus is usually wider than /hyphen (except in Courier, obviously โ€” Courier said not today).

In PostScript's StandardEncoding (which is what you get if you don't use reencode), character "\x2D" is /hyphen, and /minus is not available at all. In the Latin1-based encodings created by reencode, character "\x2D" is /minus, and character "\xAD" is /hyphen. (Side note: "\xAD" is supposed to be a "soft hyphen" (U+00AD) that only appears if the line is broken at that point โ€” but it does not work that way in PostScript. The audacity. ๐Ÿ’€)

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 get handled automatically. No cap, it just does it. โœจ

To make handling strings containing HYPHEN-MINUS easier, PostScript::File provides the auto_hyphen attribute. When this is true (and it's the default when using cp1252 or iso-8859-1), the pstr method will automatically translate HYPHEN-MINUS to either HYPHEN or MINUS SIGN. (Important: this only happens when pstr is called as an object method.)

And here's the rule, so write it down ๐Ÿซถ:

  • 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 reuse the same method for reading and writing an attribute's value, PostScript::File keeps them separate. The read accessor is prefixed with get_, and the write accessor is prefixed with set_. If no write accessor is mentioned for an attribute, then that attribute is read-only. Simple as.

๐ŸŒˆ 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 it's called as an object method โ€” but only if the document uses character set translation. (Default: true.) See "Hyphens and Minus Signs" above for the whole saga. ๐Ÿ’…

๐ŸŒˆ clipping

$ps = PostScript::File->new( clipping => $clipping )

$clipping = $ps->get_clipping

$ps->set_clipping( $clipping )

If $clipping is true, printing gets clipped to each page's bounding box. This is the document's default value. Every 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 means it's an ordinary PostScript document. (Note: read-only, no set_ for you.)

๐ŸŒˆ 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, which means omit the %%Extensions comment entirely.) Also read-only, bestie.

๐ŸŒˆ 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 gets added for ordinary PostScript files.
  • EPS files get an extension of .epsf without a preview image, 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 heads up: setting this has no effect on the actual type of the output file, only its name. The name is not the personality, okay?)

๐ŸŒˆ 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.

So: this is 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). It's giving proactive.

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 you're using multiple pages in EPS files. Do not skip this, I'm begging. ๐Ÿ˜ญ

๐ŸŒˆ 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 function (which uses Perl's autoincrement operator) and the incpage_roman function (which handles lowercase Roman numerals from i to xxxix, 1-39) 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, which means omit the %%LanguageLevel comment.) Exclusive behavior, honestly.

๐ŸŒˆ order

$ps = PostScript::File->new( order => $order )

$order = $ps->get_order

so basically, that's the order the pages are defined in the document, and it feeds into the %%PageOrder DSC comment. It's gotta be exactly one of "Ascend", "Descend", or "Special" โ€” and "Special" means a document manager must not reorder the pages, so like, hands off bestie ๐Ÿ™…โ€โ™€๏ธ. The default is "undef", which means we just omit the %%PageOrder comment entirely. No comment, no drama.

๐ŸŽ€ strip (attribute) ๐ŸŽ€

$ps = PostScript::File->new( strip => $strip )

$strip = $ps->get_strip

$ps->set_strip( $strip )

This one decides whether your PostScript code gets filtered at all. $strip has to be one of these:

  • "space" โ€” strips leading spaces so you can indent however you want without bloating the file size. (Go off, aesthetic indentation ๐Ÿ’…)
  • "comments" โ€” removes lines that begin with '%' too.
  • "all_comments" (v2.20) โ€” also nukes comments that aren't at the beginning of a line.

Also peep the strip method, which is the one that actually does the filtering described right here. Slay, division of labor โœจ

If you pass "undef" or just skip $strip altogether, it defaults to "space".

๐ŸŒท title ๐ŸŒท

$ps = PostScript::File->new( title => $title )

$title = $ps->get_title

The document's title, for the %%Title DSC comment. The default ("undef") means "just use the document's filename as the title, bestie". And if there's no filename available when the document gets output, the %%Title comment is simply omitted. Iconic minimalism.

๐Ÿฆ‹ version ๐Ÿฆ‹

$ps = PostScript::File->new( version => $version )

$version = $ps->get_version

The document's version, for the %%Version DSC comment. $version should be a string shaped like "VERNUM REV", where "VERNUM" is a floating point number and "REV" is an unsigned integer. (Default: "undef", meaning we omit the %%Version comment.)


๐ŸŒธ Paper Size and Margins ๐ŸŒธ

Heads up: these attributes are all up in each other's business. Change one and you might change the others. It's giving group project ๐Ÿ˜ญ

๐Ÿ’– 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. Lower left corner is ($llx, $lly), upper right corner is ($urx, $ury). Simple as.

โš ๏ธ Setting the bounding box automatically enables clipping. If that's not the vibe, call $ps->set_clipping(0) afterwards to undo it.

The default bounding_box gets calculated from the paper size (which comes from the paper, height, and width attributes) plus the left, right, top, and bottom margins.

Every page also has its own individual page_bounding_box, which gets initialized from the document's bounding_box the moment the page is created. Inheritance, queen behavior ๐Ÿ‘‘

๐Ÿ“ height ๐Ÿ“

$ps = PostScript::File->new( height => $height )

$height = $ps->get_height

$ps->set_height( $height )

The page height, in points. Normally this is the longer dimension of the paper. But note โ€” in landscape mode, this is actually the width of the bounding box. Sneaky little plot twist.

Setting this sets paper to "Custom", and the bounding_box gets 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 gets rotated 90 degrees counter-clockwise, which swaps the meaning of height & width. (Default: false)

In landscape mode, the coordinates are rotated 90 degrees and the origin gets moved to the bottom left corner. So the coordinate system still looks exactly the same to you, with the origin chilling at the bottom left. No cap, everything just works.

๐Ÿ“„ paper ๐Ÿ“„

$ps = PostScript::File->new( paper => $paper_size )

$paper_size = $ps->get_paper

$ps->set_paper( $paper_size )

Sets the paper size of each page. You can make a whole document with a standard paper size without having to memorize the size of paper in PostScript points. The valid choices right now are 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 hand it a string shaped like 'WIDTHxHEIGHT', where WIDTH and HEIGHT are numbers (in points). That sets the paper size to "Custom".

Setting this also sets bounding_box, height, and width to the full height and width of the paper. Everything cascades, it's a whole moment.

๐Ÿ“ width ๐Ÿ“

$ps = PostScript::File->new( width => $width )

$width = $ps->get_width

$ps->set_width( $width )

The page width, in points. Normally this is the shorter dimension of the paper. But note โ€” in landscape mode, this is actually the height of the bounding box. Again with the plot twist, we love a switcheroo.

Setting this sets paper to "Custom", and the bounding_box gets expanded to the full width.


๐ŸŽ€ Page Attributes ๐ŸŽ€

Okay so the following attributes are the feral ones โ€” they can have a different value for every single page. You can't set them directly in the constructor, but each one has a document-wide default value that every page inherits when it's created. Passing down the family traits, fr fr.

When you're 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. Lower left corner is ($llx, $lly), upper right corner is ($urx, $ury).

๐Ÿ‘€ Heads up: calling set_page_bounding_box automatically enables clipping for that page. If that isn't what you want, call $ps->set_page_clipping(0) afterwards.

When a page gets created, page_bounding_box is initialized from the document's bounding_box attribute. Yes, the whole inheritance thing again.

โœ‚๏ธ page_clipping โœ‚๏ธ

$clipping = $ps->get_page_clipping( [$page] )

$ps->set_page_clipping( [[$page,] $clipping] )

If $clipping is true, printing gets clipped to this page's bounding box. (Default: false)

When a page gets 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 ever access the page_label of the current page. (Since pages are literally specified by their label, it makes zero sense to ask for the label of a different page. Like, why would you ๐Ÿ˜ญ)

When a page gets 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 gets created, page_landscape is initialized from the document's landscape attribute.


๐Ÿ‘‘ METHODS ๐Ÿ‘‘

๐Ÿ’ก Quick note: in all the descriptions below, "[]" is used to mark optional parameters, not array references. Don't get it twisted bestie.

๐Ÿ› ๏ธ Constructor ๐Ÿ› ๏ธ

โญ new โญ

$ps = PostScript::File->new(options)

Creates 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). Math girlies rise up ๐Ÿงฎโœจ

"options" may be a single hash reference instead of an options list, but the hash has to have the same structure. That's way more convenient when you're using this thing 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 actually gets put into the resulting file. Size queen energy, but for bytes ๐Ÿ’…

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 take 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 gets 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 the user's name. (Default: false)

The comments inserted when "headings" is true are:

%%For: USER@HOSTNAME
%%Creator: Perl module PostScript::File v2.23
%%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. Main character customization, your call ๐Ÿ’…

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. Fr fr, just do it.

The list of fonts that get re-encoded comes from the need_fonts parameter, plus whatever the need_resource method digs up, plus every font you added with embed_font or add_resource. One exception bestie: the Symbol font never gets re-encoded, because it's out here living its own life with a non-standard character set. ๐Ÿฆ‹

Setting this to cp1252 or iso-8859-1 also makes the whole document get encoded in that character set. Any strings you drop into the document that have the UTF-8 flag set get re-encoded automatically. Strings that don't have the UTF-8 flag are expected to already be in the right character set โ€” like, they show up already dressed for the party. Which means you can set this to cp1252, use Unicode characters in your code and the -iso versions of the fonts, and it just... does the right thing. <sparkle>โœจ no manual fiddling โœจ</sparkle>

Windows code page 1252 (a.k.a. WinLatin1) is a superset of the printable characters in ISO-8859-1 (a.k.a. Latin1). It's got extra characters that Latin1 doesn't, especially common punctuation marks like curly quotation marks, en & em dashes, the Euro sign, and ellipsis. Those characters do exist in the standard PostScript fonts, but there's no easy way to reach them when you're 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 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 gets 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. ๐Ÿ˜ญ the blank page jumpscare.

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. Yeah, it's a PostScript-side situation. 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. math girlie behavior fr.
  • 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 you're in an EPS file, in which case it's just ignored. not me being ignored in EPS mode ๐Ÿ’€

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. it's giving fake-it-till-you-make-it, don't actually try to render it bestie.

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. getters and setters, the original besties.

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. page count check, iconic behavior.

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) hands u the width of the document's bounding box, aka urx - llx. cute lil subtraction, slay. ๐Ÿ’–

get_variable

$value = $ps->get_variable( $key )

Grabs back a user-defined value that u (or someone) stashed earlier with set_variable. it's giving "where did i put my keys" but the keys are in a hash. ๐ŸŽ€

set_variable

$ps->set_variable( $key, $value )

Assigns a user defined hash key + value, bestie. it exists so u can keep track of states inside ur PostScript code โ€” like which dictionaries are open rn. PostScript::File itself does not use this; it's purely a gift ๐ŸŽ for client programs.

โœจ pro tip from the vibes: make $key the module name so nothing clashes. and $value can totally be a hash holding however many user variables u want. main character data structure energy. ๐Ÿ’…

add_comment

$ps->add_comment( $comment )

Appends a comment to the document's DSC comments section. most of the required + recommended comments get set straight from the document's attributes, so u'll rarely need this one. it's here for completeness, so comments that aren't supported any other way can still sneak in. $comment should be the bare PostScript DSC name and value, with extra lines just prefixed by +. and it should NOT end with a newline, ok?? not even one. ๐Ÿ˜ค

Programs written for older versions of PostScript::File might use this to add a DocumentNeededResources comment. that's now deprecated โ€” use need_resource instead, bestie, the glow-up is real. ๐Ÿฆ‹

Examples:

$ps->add_comment("ProofMode: NotifyMe");
$ps->add_comment("Requirements: manualfeed");

get_comments

$comments = $ps->get_comments

Retrieves any extra DSC comments that got added via add_comment. ๐Ÿ’œ

add_default

$ps->add_default( $default )

Use this to append a PostScript DSC comment to the Defaults section. these are typically values like PageCustomColors: or PageRequirements:. format is the same as add_comment โ€” same rules, same energy. ๐ŸŒธ

get_defaults

$comments = $ps->get_defaults

Returns the contents of the DSC Defaults section, if there are any. if not, well. vibe check: empty. ๐Ÿ™ˆ

embed_document

$code = $ps->embed_document( $filename )

Reads the contents of $filename, which should be a PostScript file. returns a string with the file's contents wrapped in %%BeginDocument and %%EndDocument comments, and adds $filename to the list of document supplied resources. iconic. ๐Ÿ‘‘

โš ๏ธ u must pass the returned string to add_to_page or some other method that will actually include it in the document. the return value does not just magically appear, bestie, it's not that kind of girl. ๐Ÿ’€

embed_font

$font_name = $ps->embed_font( $filename, [$type] )

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 (no leading slash, we're not that extra).

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 one needs the t1ascii program from <http://www.lcdf.org/type/#t1utils>. (u can set $PostScript::File::t1ascii to the name of the program to use. it defaults to t1ascii.)
  • TTF โ€” a TrueType font. this one needs the ttftotype42 program from <http://www.lcdf.org/type/#typetools>. (u 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 only introduced in PostScript level 2, embedding a TTF font automatically sets langlevel to 2 (unless it was already set to a higher level). and be aware: not all printers can handle Type42 fonts. like, even PostScript level 2 printers don't have to support them. Ghostscript does support Type42 fonts (when it's compiled with the ttfont option), so at least there's that. ๐Ÿ˜ญ

need_resource

$ps->need_resource( $type, @resources )

Adds resources to the DocumentNeededResources comment. $type is one of encoding, file, font, form, pattern, or procset (case sensitive, so watch it ๐Ÿ‘€).

Any number of resources (of a single type) can 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 with special characters like spaces get quoted automatically โ€” it's very thoughtful of it. ๐ŸŽ€

If need_resource is never called for the font type (and need_fonts isn't used either), 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 that behaviour is deprecated ๐Ÿšซ โ€” a document should explicitly list the fonts it requires, no gatekeeping. if u don't use any of the standard fonts, pass need_fonts => [] to the constructor (or call $ps->need_resource('font')) to say so.

add_to_page

$ps->add_to_page( [$page,] $code )

Appends $code to the specified $page, which can be any page label. (default: the current page)

If the specified $page doesn't exist, a new page gets added with that label. note that this is added on the end, not in the order u might expect. so adding vi to page set iii, iv, v, 6, 7, 8 would create a new page after 8, not after v. it said what it said. ๐Ÿคท

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 extra code to page 3 if it exists, or starts a brand 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. heads up: this is a document-global value, even though the code gets repeated on each page. yes, both things are true. ๐Ÿ’…

Also note that any settings defined here will be active for each page separately. use add_setup if u want settings to carry from one page to another.

get_page_setup

$setup = $ps->get_page_setup

Returns the contents of the DSC PageSetup section, if any. again: document-global value, but the code repeats on each page. it's giving "same fit, every page". ๐ŸŒˆ

add_page_trailer

$ps->add_page_trailer( $code )

Appends $code to the DSC PageTrailer section. u guessed it โ€” document-global value, code 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, so it can gossip about what happened earlier. ๐Ÿ‘€

get_page_trailer

$code = $ps->get_page_trailer

Returns the contents of the DSC PageTrailer section, if any. document-global value, repeated on each page, we been knew. ๐Ÿฆ‹

add_preview

$ps->add_preview( $width, $height, $depth, $lines, $preview )

Sets the EPSI format preview for this document โ€” an ASCII representation of a bitmap, basically a lil thumbnail portrait. ๐Ÿ“ธ 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. glow-up via metadata.

get_preview

$preview = $ps->get_preview

Returns the EPSI preview of the document, if any, including the %%BeginPreview and %%EndPreview comments. the whole package. ๐ŸŽ

add_procset

$ps->add_procset( $name, $code, [$version, [$revision]] )

(v2.20) adds 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 absolutely nothing. respectfully declines. ๐Ÿ™…

$version is a real number, and $revision is an unsigned integer. they both default to 0. PostScript::File doesn't 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. iykyk. ๐Ÿค

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. it doesn't gatekeep, it just reports. ๐Ÿ’œ

has_procset

$exists = $ps->has_procset( $name )

(v2.20) returns true if $name has already been included in the file. the name should be identical to the one u gave to add_procset โ€” exact match only, no lowercase shenanigans. ๐Ÿ”

get_procsets

$code = $ps->get_procsets

(v2.20) returns all the procsets defined in this document. the full collection. ๐Ÿ‘‘

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, bestie, that's where the lore lives.
  • $resource โ€” a string containing the PostScript code. probably best provided as a 'here' document. ๐Ÿ“„

Use this to add fonts or images (although u may prefer embed_font or embed_document โ€” they're the shortcut routes). 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. different list, different vibe. โœจ

add_setup

$ps->add_setup( $code )

Appends $code to the DSC Setup section. use this for setpagedevice, statusdict, or other settings that initialize the device or document. it is that girl. ๐Ÿ’…

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 โ€” the closing-the-group-chat moment. ๐Ÿงน๐Ÿ’–

get_trailer

$code = $ps->get_trailer

Returns the contents of the document's DSC Trailer section, if any. final thoughts, archived. ๐ŸŒธ

use_functions

$ps->use_functions( @function_names )

This is basically you sliding into the document's DMs like "hey bestie, pls include these" โ€” the PostScript functions listed in @function_names get pulled into this document. Wanna know which ones you can ask for? Peep PostScript::File::Functions for the whole menu. ๐Ÿ‘‘

โœจ Text Processing Methods โœจ

๐Ÿ’… convert_hyphens

$converted_text = $ps->convert_hyphens( $text )

Takes every HYPHEN-MINUS (U+002D) character in $text and converts it to either HYPHEN (U+2010) or MINUS SIGN (U+2212) โ€” whichever is right, according to the rules up in "Hyphens and Minus Signs". Side effect queen: it sets the UTF-8 flag on $converted_text.

If $text doesn't have the UTF-8 flag set, it's assumed to be chilling in the document's character encoding.

And if $text has zero HYPHEN-MINUS characters in it? It comes right back at you as-is. No notes. ๐Ÿซถ


๐Ÿฆ‹ decode_text

$text = $ps->decode_text( $encoded_text, [$preserve_minus] )

This is the inverse of encode_text, bestie โ€” it takes $encoded_text out of the document's character encoding and makes it Unicode. But if $encoded_text already has the UTF-8 flag set, or the document isn't doing character translation at all, it just hands $encoded_text straight back, unchanged.

Now for the optional $preserve_minus (only matters when $encoded_text isn't being returned as-is): if it's true, any HYPHEN-MINUS (U+002D) characters in $encoded_text get decoded as MINUS SIGN (U+2212). Why do we care? Because it makes encode_text treat them as minus signs instead of hyphens. Little detail, big consequences. โœจ


๐ŸŽ€ encode_text

$encoded_text = $ps->encode_text( $text )

Gives you $text converted into the document's character encoding. But if $text doesn't have the UTF-8 flag set, or the document isn't using character translation, you get $text back exactly as-is. Simple as. ๐Ÿ’–


๐ŸŒธ pstr

$code = $ps->pstr( $string, [$nowrap] )

$code = PostScript::File->pstr( $string, [$nowrap] )

$code = pstr( $string )

Turns the string into a PostScript string literal. If the result is longer than 240 characters it gets chopped into multiple lines, because a PostScript file literally should not have lines longer than 255 characters. Respect the limit. ๐Ÿ˜ญ

When you call it as a class or object method you can hand it a second parameter, $nowrap. If that's true, the string does not get wrapped, no matter how long it is. Do what you want, icon.

When you call it as an object method, pstr does automatic hyphen-minus translation if auto_hyphen is true. Side effect: it sets the UTF-8 flag on the returned string. (And if the UTF-8 flag wasn't set on the input string, it gets decoded using the document's character set.) See "Hyphens and Minus Signs" for the deets. Which is exactly why pstr should normally be called as an object method โ€” that's the whole point, iykyk. ๐Ÿงš


โญ strip (method)

$ps->strip( $code )

$ps->strip( $strip => @code )

The strip method filters PostScript code based on whatever $strip is โ€” and it can be any valid value for the strip attribute. Heads up: the code is modified in-place, there's no return value, so don't go looking for one. And if $code is undef, it's just left alone, untouched, living its truth.

Call it with a single argument and it strips $code according to the current value of the strip attribute.


๐Ÿ”ฅ SUBROUTINES ๐Ÿ”ฅ

๐Ÿ’œ array_as_string

$code = array_as_string( @array )

Converts a Perl array into a PostScript array literal. The array elements get used as-is โ€” no glow-up, no edits. So if what you actually want is an array of strings, you gotta do something like:

$code = array_as_string( map { $ps->pstr($_) } @array )

Slay. ๐Ÿ’…


๐Ÿ‘‘ check_file

$pathname = check_file( $file, [$dir, [$create]] )
  • $file โ€” an optional fully qualified path-and-file, or just a plain file name. If you omit it, or pass the empty string, you get back the special file File::Spec->devnull. ๐Ÿ™ˆ
  • $dir โ€” an optional directory path. If it's defined (and $file isn't already an absolute path), it gets prepended to $file.
  • $create โ€” if true, create the file if it doesn't already exist. (Default: false.)

This takes a filename plus optional directory and turns it into an absolute path, then creates any directories that don't exist yet. Any leading ~ gets expanded to the user's home directory using check_tilde.

If $create is true and $pathname doesn't exist, it gets created as an empty file. Boom, new file, born today. โœจ

File::Spec is used all throughout, so file access stays portable. No platform drama. ๐ŸŒˆ


๐Ÿ“ check_tilde

$expanded_path = check_tilde( $path )

Expands a leading ~ or ~user in $path into the home directory. That's it, that's the whole job. ๐Ÿซถ


โญ incpage_label

$next_label = incpage_label( $label )

Applies Perl's autoincrement operator to $label and returns the result. Which means the magic string autoincrement rules kick in for any value matching /^[a-zA-Z]*[0-9]*\z/.

Fun fact: this function is the default value of the incpage_handler attribute. Main character energy, honestly. ๐Ÿ‘‘


๐ŸŒŸ incpage_roman

$next_label = incpage_roman( $label )

Increments lower case Roman numerals. $label must be a value between i and xxxviii (that's 1 to 38), and $next_label will come out as ii to xxxix (2 to 39). Which โ€” genuinely โ€” should be plenty for numbering the odd preface. ๐Ÿ˜Œ

Normally you'd use this as the value of the incpage_handler attribute, like so:

$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, which makes it suitable for a DSC comment. Strings with no special characters come back unchanged โ€” if it ain't broke, don't touch it. ๐ŸŽ€

You can also call this as a class or object method, but heads up: it does not do hyphen-minus translation, even if auto_hyphen is true. Not its job, not doing it.


๐Ÿฆ‹ str

$code = str( $value )

If $value is an arrayref, you get array_as_string(@$value). Otherwise you get $value straight back, as-is.

Why does this exist? Honestly, it was designed to make passing colors to the PostScript function setColor in PostScript::File::Functions way easier โ€” that function expects either an RGB array or a greyscale decimal, so this little cutie smooths the whole thing out. Convenience icon. ๐Ÿ’…

๐ŸŒˆ POSTSCRIPT DEBUGGING SUPPORT ๐ŸŒˆ

okay bestie, this section is about the PostScript functions that give you debugging output ๐Ÿ’… and yes it's a whole vibe. BIG WARNING THO: any clipping or bounding boxes will also hide the debugging output, which by default starts at the top left of the page. so like, if you're clipping, your debug text is gonna get ghosted ๐Ÿ‘ป. typical "new" options you'd want 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 bunch of PostScript variables, and most of them can also be given as options to new. ๐ŸŽ€

The main controller is db_active โ€” it 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. no cap, it's basically text wrapping but make it PostScript ๐Ÿฆ‹

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. (i know. "just print less" is the advice. iconic honestly ๐Ÿ’€)

โœจ 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. (it's giving "final girl", she does not survive the function ๐Ÿ˜ญ)

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. so you don't gotta worry about it, it's handled ๐Ÿซถ

  • 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

will 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. โš ๏ธ (do not overflow the buffer bestie, she's only 256 wide)

  • 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. (we don't do that anymore bestie, it's giving 2002)


๐Ÿซฃ 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. (landscape mode said "not today" ๐Ÿ’€)

Most of these functions have only had a couple of tests, so please feel free to report all you find. fr fr, if you find a bug, tell them!! ๐Ÿ›


๐ŸŒธ AUTHOR ๐ŸŒธ

Chris Willmot <chris AT willmot.co.uk>

Thanks to Johan Vromans for the ISOLatin1Encoding. (shoutout ๐Ÿซถ)

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 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.


and that's the whole page bestie!! ๐ŸŽ€ this one shipped as perl v5.36.0 and dated 2022-10-14, in the PostScript::File(3pm) era of the docs โ€” go forth and debug your PostScript, you absolute icon ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from