The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Kite::PScript::Defs - useful PostScript definitions for kite layout et al

SYNOPSIS

    use Kite::PScript::Defs;

    # access package variables directly
    print $Kite::PScript::Defs::mm;

    # or as package subs
    print Kite::PScript::Defs::mm();

    # or as class methods
    print Kite::PScript::Defs->mm();

    # here's a convenient shorthand
    my $ps = 'Kite::PScript::Defs';
    print $ps->mm;

    # import various definitions
    use Kite::PScript::Defs qw( mm clip );
    print mm, clip;

    # or specify :all tag to import all definitions as subs
    use Kite::PScsript::Defs qw( :all );
    print mm, reg, clip, pathtext;

DESCRIPTION

Module defining a number of useful PostScript definitions for kite part layout and other similar tasks.

The definitions are provided as package variables which can be accessed directly:

    use Kite::PScript::Defs;

    print $Kite::PScript::Defs::mm;

An AUTOLOAD method is provided which translates any subroutine or method calls into accesses to the appropriate variable. Thus, the PostScript definition specified in the $mm package variable can be accessed by calling either of:

    Kite::PScript::mm();
    Kite::PScript->mm();

The latter use allows a 'factory' variable to be defined to make this less tedious.

    my $ps = 'Kite::PScript::Defs';
    print $ps->mm, $ps->clip, $ps->pathtext;

You can specify import parameters when loading the module. Any definitions specified will be imported as subroutines into the caller's namespace.

    use Kite::PScript::Defs qw( mm clip );
    print mm, clip;

The ':all' import tag can be specified to import all the PoscScript definitions.

    use Kite::PScript::Defs qw( :all );
    print mm, clip, pathtext;

TEMPLATE TOOLKIT

The module is defined to be intimately useful when used in conjunction with the Template Toolkit. To use the PostScript definitions within a template, simply ensure that the module is loaded and bless an empty hash into the Kite::PScript::Defs package. This will allow the Template Toolkit to resolve to the correct class methods.

    use Template;
    use Kite::PScript::Defs;

    my $tt2  = Template->new();
    my $vars = {
        psdefs => bless({ }, 'Kite::PScript::Defs'),
    };

    $tt2->process(\*DATA, $vars)
        || die $tt2->error();

    __END__
    %!PS-Adobe-3.0
    %%EndComments

    [% psdefs.mm %]
    [% psdefs.lines %]
    [% psdefs.cross %]
    [% psdefs.dot %]
    [% psdefs.circle %]
    [% psdefs.crop %]
    [% psdefs.reg %]

    0 mm 0 mm moveto    % /mm defined in psdefs.mm
    crop                % /crop defined in psdefs.crop
    regmarks            % /regmarks defined in psdefs.reg
    ...etc...

POSTSCRIPT DEFINITION METHODS

mm

Defines millimetres /mm.

    [% psdefs.mm %]
    10 mm 10 mm moveto
    50 mm 10 mm lineto
lines

Defines the following line styles:

    linelight           % 0.25 setlinewidth
    linenormal          % 0.5  setlinewidth
    lineheavy           % 0.75 setlinewidth
    linedotted          % 0.5  setlinewidth + dotted
    linedashed          % 0.5  setlinewidth + dashed

Example:

    [% psdefs.mm %]
    [% psdefs.lines %]
    linenormal
    newpath
    0 mm 0 mm moveto
    100 mm 0 mm lineto
    stroke
  
cross

Defines a procedure to generate a cross from vertical and horizontal lines 10mm in length, crossing at the current point. Requires 'mm' and 'lines'.

    [% psdefs.mm %]
    [% psdefs.lines %]
    [% psdefs.cross %]
    50 mm 50 mm         % move to a point
    cross               % draw cross
dot

Defines a procedure to generate a small filled dot at the current point. Requires 'mm' and 'lines'.

    [% psdefs.mm %]
    [% psdefs.lines %]
    [% psdefs.dot %]
    50 mm 50 mm         % move to a point
    dot                 % draw dot
circle

Defines a procedure to generate a small circle at the current point. Requires 'mm' and 'lines'.

    [% psdefs.mm %]
    [% psdefs.lines %]
    [% psdefs.circle %]
    50 mm 50 mm         % move to a point
    circle              % draw circle
crop

Defines a procedure to generate a crop mark at the current point, built from a combination of /cross and /circle. Requires 'mm', 'lines', 'cross' and 'circle'.

    [% psdefs.mm %]
    [% psdefs.lines %]
    [% psdefs.cross %]
    [% psdefs.circle %]
    0 mm 0 mm           % move to a point
    circle              % draw crop mark
clip

Defines /cliprect as a procedure to return a clipping rectangle set to the imageable size. Defines a number of other variables containing information about the clipping rectangle.

    cliprect            % clipping rectangle
    cliptrx             % top right x
    cliptry             % top right y
    clipblx             % bottom left x
    clipbly             % bottom left y
    clipxsize           % width 
    clipysize           % height 
reg

Defines /regmarks to generate registration marks (crop) at the corners of the clipping rectangle, /cliprect. Requires 'mm', 'lines', 'cross', 'circle', 'crop' and 'clip'.

    [% psdefs.mm %]
    [% psdefs.lines %]
    [% psdefs.cross %]
    [% psdefs.circle %]
    [% psdefs.crop %]
    [% psdefs.clip %]

    regmarks            % draw registration marks
noreg

Defines /regmarks as a no-op procedure to prevent registration marks from being produced.

    regmarks            % null registration marks
pathtext

Defines /pathtext to draw text along an arbitrary path.

    path text pathtext  % draw text along path    

    ** TODO - see Blue Book for examples **
tiles

Defines /tiles as a procedure which calculates the number of pages required to display the current path on the output device. Also calculates the X/Y origin required for the path to be centered within the tile set. Defines the following items.

    tilesnx             % no. of tiles in x
    tilesny             % no. of tiles in y
    tilesxorg           % suggested x origin
    tilesyorg           % suggested y origin

See next item for example of use.

dotiles

Generates PostScript to tile an image into multiple pages. It requires that a number of items be pre-defined. The first, /tileimage, should be a procedure defined to generate the image itself.

    /tileimage {
        ...PostScript to generate your image...
    } def

The next item, /tilepath, should be a procedure defined to generate a path which encloses the image. This is used to calculate the bounding box for the image.

    /tilepath {
        ...PostScript path to bound your image...
    } def

Finally, the /tilepage item should be a procedure defined to generate any output required on each tiled page (i.e. independant of the main image which ends up split across many pages).

    [% psdefs.mm %]
    [% psdefs.reg %]
    [% psdefs.clip %]

    /tilepage {
        regmarks                % generate registration marks
        /Times-Roman findfont 
        24 scalefont setfont    % set font
        clipblx 3 mm add 
        clipbly 3 mm add moveto % move to lower left corner
        ([% title %]) show      % print title
        tilemap                 % generate tiling map
    } def

To tile the image onto multiple pages, the /tiles procedure should be called to determine the tiling requirements. The /tilepath item should be on the stack (i.e. precede the call).

    [% psdefs.tiles %]

    tilepath tiles

Then, the 'dotiles' method can be called to generate the appropriate PostScript code to tile the image onto multiple pages.

    [% defs.dotiles %]
Box

This item generates a PostScript definition for a Box object which can be used for all kinds of things boxlike. The following documentation items describe the available Box "methods" in more detail, but for now, here's a complete example.

    %!PS-Adobe-3.0
    %%Title: Box Example
    %%EndComments

    [% defs.mm %]
    [% defs.lines %]
    [% defs.cross %]
    [% defs.dot %]
    [% defs.circle %]
    [% defs.crop %]
    [% defs.box %]

    # define a general border value
    /border [% border %] mm def

    % convert the clipping path into a Box
    clippath pathbbox Box 

    % inset this Box by /border
    border Box_border 

    % and define /page to be this slightly smaller Box
    /page exch def

    % split /page into 3 vertical boxes
    page 3 border 0 Box_vsplit
    /upper  exch def
    /middle exch def
    /lower  exch def

    % inset upper box by border and define /inner
    upper border Box_border
    /inner exch def

    % split it horizontally into /left and /right
    inner 2 border 0 Box_hsplit
    /right exch def
    /left  exch def

    % stroke /upper, /middle and /lower boxes.
    linenormal
    upper  Box_rect rectstroke
    middle Box_rect rectstroke
    lower  Box_rect rectstroke

    % focus the drawing context on the /middle box
    middle Box_focus
    newpath
    0 0 moveto
    100 mm 100 mm lineto
    ...more complicated stuff here...
    stroke
    middle Box_defocus

    showpage
Box_select

Unpacks a Box structure to define various Box_* variables.

    Box_try         % top right y
    Box_trx         % top right x
    Box_bly         % bottom left y
    Box_blx         % bottom left x
    Box_width       % width of Box
    Box_height      % height of Box

Example:

    mybox Box_select
Box_rect

Unpacks a Box structure to a rect suitable for rectstroke, etc.

    mybox Box_rect rectstroke
Box_path

Unpacks a Box structure to a path suitable for stroke, clip, etc.

    mybox Box_path stroke
Box_border

Creates a new Box within a specified border of an existing Box.

    mybox 10 mm Box_bqorder
    /smallbox exch def
Box_vsplit

Splits a box vertically into a number of equal sized boxes. Spacing and padding variables should also be specified to control the sizes and relative positions of the new boxes.

    % split /mybox into 3 new Box objects, /upper, /middle and 
    % /lower, padded 10 mm within existing /mybox and spaced 
    % 5 mm apart from each other
    mybox 3 10 mm 5 mm Box_vsplit
    /upper  exch def
    /middle exch def
    /lower  exch def
Box_hsplit

As per Box_Vsplit but splitting a Box horizontally.

    middle 2 10 mm 5 mm Box_hsplit
    /right exch def
    /left  exch def
Box_focus

Creates a new drawing context which is focussed on a particular Box. That is, all drawing will happen relative to the origin of the Box and be clipped within its bounds.

    middle Box_focus
Box_defocus

Restores the previous drawing context saved by a prior Box_focus.

AUTHOR

Simon Stapleton <simon@tufty.co.uk> wrote the original xml2ps.pl utility which inspired much of the original PostScript contained herein. Most of that, he freely admits, was gleaned from the Blue Book (PostScript Language Tutorial and Cookbook, Adobe).

Andy Wardley <abw@kfs.org> re-packaged it into a module for integration into the Kite bundle. Various features and more advanced defintions have been added along the way.

REVISION

$Revision: 1.3 $

COPYRIGHT

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

TODO

It would be nice to have some way of automatically managing all dependencies between different procedures. For example, if you call the 'circle' method then it should ensure that 'mm' and 'lines' are first called if they haven't been called previously.

It may make more sense to package this module as a general purpose PostScript library and/or plugin for the Template Toolkit.

SEE ALSO

For further information on the Kite::* modules, see Kite. For further information on the Template Toolkit, see Template or http://www.template-toolkit.org/ .