/*
# poster - resize a postscript image to print on larger media and/or multiple sheets
#
# This program scales a PostScript page to a given size (a poster).
# The output can be tiled on multiple sheets, and output
# media size can be chosen independently.
# Each tile (sheet) of a will bear cropmarks and slightly overlapping
# image for easier poster assembly.
# In principle it requires the input file to adhere to 'eps'
# (encapsulated postscript) conventions but it will work for many
# 'normal' postscript files as well.
#
# Compile this program with:
# cc -O -o poster poster.c -lm
# or something alike.
#
# Maybe you want to change the `DefaultMedia' and `DefaultImage'
# settings in the few lines below, to reflect your local situation.
# Names can to be chosen from the `mediatable' further down.
#
# The `Gv_gs_orientbug 1' disables a feature of this program to
# ask for landscape previewing of rotated images.
# Our currently installed combination of ghostview 1.5 with ghostscript 3.33
# cannot properly do a landscape viewing of the `poster' output.
# The problem does not exist in combination with an older ghostscript 2.x,
# and has the attention of the ghostview authors.
# (The problem is in the evaluation of the `setpagedevice' call.)
# If you have a different previewing environment,
# you might want to set `Gv_gs_orientbug 0'
#
# --------------------------------------------------------------
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY;
# The full text of the GNU General Public License is supplied
# with 'poster' in the file LICENSE.
#
# Copyright (C) 1999 Jos T.J. van Eijndhoven
# --------------------------------------------------------------
# email:
[email protected]
*/
#define Gv_gs_orientbug 1
#define DefaultMedia "A4"
#define DefaultImage "A4"
#define DefaultCutMargin "5%"
#define DefaultWhiteMargin "0"
#define BUFSIZE 1024
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
extern char *optarg; /* silently set by getopt() */
extern int optind, opterr; /* silently set by getopt() */
static void usage();
static void dsc_head1();
static int dsc_infile( double ps_bb[4]);
static void dsc_head2( void);
static void printposter( void);
static void printprolog();
static void tile ( int row, int col);
static void printfile( void);
static void postersize( char *scalespec, char *posterspec);
static void box_convert( char *boxspec, double psbox[4]);
static void boxerr( char *spec);
static void margin_convert( char *spec, double margin[2]);
static int mystrncasecmp( const char *s1, const char *s2, int n);
int verbose;
char *myname;
char *infile;
int rotate, nrows, ncols;
int manualfeed = 0;
int tail_cntl_D = 0;
#define Xl 0
#define Yb 1
#define Xr 2
#define Yt 3
#define X 0
#define Y 1
double posterbb[4]; /* final image in ps units */
double imagebb[4]; /* original image in ps units */
double mediasize[4]; /* [34] = size of media to print on, [01] not used! */
double cutmargin[2];
double whitemargin[2];
double scale; /* linear scaling factor */
/* defaults: */
char *imagespec = NULL;
char *posterspec = NULL;
char *mediaspec = NULL;
char *cutmarginspec = NULL;
char *whitemarginspec = NULL;
char *scalespec = NULL;
char *filespec = NULL;
/* media sizes in ps units (1/72 inch) */
static char *mediatable[][2] =
{ { "Letter", "612,792"},
{ "Legal", "612,1008"},
{ "Tabloid", "792,1224"},
{ "Ledger", "792,1224"},
{ "Executive","540,720"},
{ "Monarch", "279,540"},
{ "Statement","396,612"},
{ "Folio", "612,936"},
{ "Quarto", "610,780"},
{ "C5", "459,649"},
{ "B4", "729,1032"},
{ "B5", "516,729"},
{ "Dl", "312,624"},
{ "A0", "2380,3368"},
{ "A1", "1684,2380"},
{ "A2", "1190,1684"},
{ "A3", "842,1190"},
{ "A4", "595,842"},
{ "A5", "420,595"},
{ "A6", "297,421"},
/* as fall-back: linear units of measurement: */
{ "p", "1,1"},
{ "i", "72,72"},
{ "ft", "864,864"},
{ "mm", "2.83465,2.83465"},
{ "cm", "28.3465,28.3465"},
{ "m", "2834.65,2834.65"},
{ NULL, NULL}
};
int main( int argc, char *argv[])
{
int opt;
double ps_bb[4];
int got_bb;
myname = argv[0];
while ((opt = getopt( argc, argv, "vfi:c:w:m:p:s:o:")) != EOF)
{ switch( opt)
{ case 'v': verbose++; break;
case 'f': manualfeed = 1; break;
case 'i': imagespec = optarg; break;
case 'c': cutmarginspec = optarg; break;
case 'w': whitemarginspec = optarg; break;
case 'm': mediaspec = optarg; break;
case 'p': posterspec = optarg; break;
case 's': scalespec = optarg; break;
case 'o': filespec = optarg; break;
default: usage(); break;
}
}
/*** check command line arguments ***/
if (scalespec && posterspec)
{ fprintf( stderr, "Please don't specify both -s and -o, ignoring -s!\n");
scalespec = NULL;
}
if (optind < argc)
infile = argv[ optind];
else
{ fprintf( stderr, "Filename argument missing!\n");
usage();
}
/*** decide on media size ***/
if (!mediaspec)
{ mediaspec = DefaultMedia;
if (verbose)
fprintf( stderr,
"Using default media of %s\n",
mediaspec);
}
box_convert( mediaspec, mediasize);
if (mediasize[3] < mediasize[2])
{ fprintf( stderr, "Media should always be specified in portrait format!\n");
exit(1);
}
if (mediasize[2]-mediasize[0] <= 10.0 || mediasize[3]-mediasize[1] <= 10.0)
{ fprintf( stderr, "Media size is ridiculous!\n");
exit(1);
}
/*** defaulting poster size ? **/
if (!scalespec && !posterspec)
{ /* inherit postersize from given media size */
posterspec = mediaspec;
if (verbose)
fprintf( stderr,
"Defaulting poster size to media size of %s\n",
mediaspec);
}
/*** decide the cutmargin size, after knowing media size ***/
if (!cutmarginspec)
{ /* if (!strcmp( posterspec, mediaspec)) */
/* zero cutmargin if printing to 1 sheet */
/* marginspec = "0%";
else */ cutmarginspec = DefaultCutMargin;
if (verbose)
fprintf( stderr,
"Using default cutmargin of %s\n",
cutmarginspec);
}
margin_convert( cutmarginspec, cutmargin);
/*** decide the whitemargin size, after knowing media size ***/
if (!whitemarginspec)
{ whitemarginspec = DefaultWhiteMargin;
if (verbose)
fprintf( stderr,
"Using default whitemargin of %s\n",
whitemarginspec);
}
margin_convert( whitemarginspec, whitemargin);
/******************* now start doing things **************************/
/* open output file */
if (filespec)
{ if (!freopen( filespec, "w", stdout))
{ fprintf( stderr, "Cannot open '%s' for writing!\n",
filespec);
exit(1);
} else if (verbose)
fprintf( stderr, "Opened '%s' for writing\n",
filespec);
}
/******* I might need to read some input to find picture size ********/
/* start DSC header on output */
dsc_head1();
/* pass input DSC lines to output, get BoundingBox spec if there */
got_bb = dsc_infile( ps_bb);
/**** decide the input image bounding box ****/
if (!got_bb && !imagespec)
{ imagespec = DefaultImage;
if (verbose)
fprintf( stderr,
"Using default input image of %s\n",
imagespec);
}
if (imagespec)
box_convert( imagespec, imagebb);
else
{ int i;
for (i=0; i<4; i++)
imagebb[i] = ps_bb[i];
}
if (verbose > 1)
fprintf( stderr, " Input image is: [%g,%g,%g,%g]\n",
imagebb[0], imagebb[1], imagebb[2], imagebb[3]);
if (imagebb[2]-imagebb[0] <= 0.0 || imagebb[3]-imagebb[1] <= 0.0)
{ fprintf( stderr, "Input image should have positive size!\n");
exit(1);
}
/*** decide on the scale factor and poster size ***/
postersize( scalespec, posterspec);
if (verbose > 1)
fprintf( stderr, " Output image is: [%g,%g,%g,%g]\n",
posterbb[0], posterbb[1], posterbb[2], posterbb[3]);
dsc_head2();
printposter();
exit (0);
}
static void usage()
{
fprintf( stderr, "Usage: %s <options> infile\n\n", myname);
fprintf( stderr, "options are:\n");
fprintf( stderr, " -v: be verbose\n");
fprintf( stderr, " -f: ask manual feed on plotting/printing device\n");
fprintf( stderr, " -i<box>: specify input image size\n");
fprintf( stderr, " -c<margin>: horizontal and vertical cutmargin\n");
fprintf( stderr, " -w<margin>: horizontal and vertical additional white margin\n");
fprintf( stderr, " -m<box>: media paper size\n");
fprintf( stderr, " -p<box>: output poster size\n");
fprintf( stderr, " -s<number>: linear scale factor for poster\n");
fprintf( stderr, " -o<file>: output redirection to named file\n\n");
fprintf( stderr, " At least one of -s -p -m is mandatory, and don't give both -s and -p\n");
fprintf( stderr, " <box> is like 'A4', '3x3letter', '10x25cm', '200x200+10,10p'\n");
fprintf( stderr, " <margin> is either a simple <box> or <number>%%\n\n");
fprintf( stderr, " Defaults are: '-m%s', '-c%s', '-i<box>' read from input file.\n",
DefaultMedia, DefaultCutMargin);
fprintf( stderr, " and output written to stdout.\n");
exit(1);
}
#define exch( x, y) {double h; h=x; x=y; y=h;}
static void postersize( char *scalespec, char *posterspec)
{ /* exactly one the arguments is NULL ! */
/* media and image sizes are fixed already */
int nx0, ny0, nx1, ny1;
double sizex, sizey; /* size of the scaled image in ps units */
double drawablex, drawabley; /* effective drawable size of media */
double mediax, mediay;
double tmpposter[4];
/* available drawing area per sheet: */
drawablex = mediasize[2] - 2.0*cutmargin[0];
drawabley = mediasize[3] - 2.0*cutmargin[1];
/*** decide on number of pages ***/
if (scalespec)
{ /* user specified scale factor */
scale = atof( scalespec);
if (scale < 0.01 || scale > 1.0e6)
{ fprintf( stderr, "Illegal scale value %s!\n", scalespec);
exit(1);
}
sizex = (imagebb[2] - imagebb[0]) * scale + 2*whitemargin[0];
sizey = (imagebb[3] - imagebb[1]) * scale + 2*whitemargin[1];
/* without rotation */
nx0 = ceil( sizex / drawablex);
ny0 = ceil( sizey / drawabley);
/* with rotation */
nx1 = ceil( sizex / drawabley);
ny1 = ceil( sizey / drawablex);
} else
{ /* user specified output size */
box_convert( posterspec, tmpposter);
if (tmpposter[0]!=0.0 || tmpposter[1]!=0.0)
{ fprintf( stderr, "Poster lower-left coordinates are assumed 0!\n");
tmpposter[0] = tmpposter[1] = 0.0;
}
if (tmpposter[2]-tmpposter[0] <= 0.0 || tmpposter[3]-tmpposter[1] <= 0.0)
{ fprintf( stderr, "Poster should have positive size!\n");
exit(1);
}
if ((tmpposter[3]-tmpposter[1]) < (tmpposter[2]-tmpposter[0]))
{ /* hmmm... landscape spec, change to portrait for now */
exch( tmpposter[0], tmpposter[1]);
exch( tmpposter[2], tmpposter[3]);
}
/* Should we tilt the poster to landscape style? */
if ((imagebb[3] - imagebb[1]) < (imagebb[2] - imagebb[0]))
{ /* image has landscape format ==> make landscape poster */
exch( tmpposter[0], tmpposter[1]);
exch( tmpposter[2], tmpposter[3]);
}
/* without rotation */ /* assuming tmpposter[0],[1] = 0,0 */
nx0 = ceil( 0.95 * tmpposter[2] / mediasize[2]);
ny0 = ceil( 0.95 * tmpposter[3] / mediasize[3]);
/* with rotation */
nx1 = ceil( 0.95 * tmpposter[2] / mediasize[3]);
ny1 = ceil( 0.95 * tmpposter[3] / mediasize[2]);
/* (rotation is considered as media versus image, which is totally */
/* independent of the portrait or landscape style of the final poster) */
}
/* decide for rotation to get the minimum page count */
rotate = nx0*ny0 > nx1*ny1;
ncols = rotate ? nx1 : nx0;
nrows = rotate ? ny1 : ny0;
if (verbose)
fprintf( stderr,
"Deciding for %d column%s and %d row%s of %s pages.\n",
ncols, (ncols==1)?"":"s", nrows, (nrows==1)?"":"s",
rotate?"landscape":"portrait");
if (nrows * ncols > 400)
{ fprintf( stderr, "However %dx%d pages seems ridiculous to me!\n",
ncols, nrows);
exit(1);
}
mediax = ncols * (rotate ? drawabley : drawablex);
mediay = nrows * (rotate ? drawablex : drawabley);
if (!scalespec) /* no scaling number given by user */
{ double scalex, scaley;
scalex = (mediax - 2*whitemargin[0]) / (imagebb[2] - imagebb[0]);
scaley = (mediay - 2*whitemargin[1]) / (imagebb[3] - imagebb[1]);
scale = (scalex < scaley) ? scalex : scaley;
if (verbose)
fprintf( stderr,
"Deciding for a scale factor of %g\n", scale);
sizex = scale * (imagebb[2] - imagebb[0]);
sizey = scale * (imagebb[3] - imagebb[1]);
}
/* set poster size as if it were a continuous surface without margins */
posterbb[0] = (mediax - sizex) / 2.0; /* center picture on paper */
posterbb[1] = (mediay - sizey) / 2.0; /* center picture on paper */
posterbb[2] = posterbb[0] + sizex;
posterbb[3] = posterbb[1] + sizey;
}
static void margin_convert( char *spec, double margin[2])
{ double x;
int i, n;
if (1==sscanf( spec, "%lf%n", &x, &n) && x==0.0 && n==strlen(spec))
{ /* margin spec of 0, dont bother about a otherwise mandatory unit */
margin[0] = margin[1] = 0.0;
} else if (spec[ strlen( spec) - 1] == '%')
{ /* margin relative to media size */
if (1 != sscanf( spec, "%lf%%", &x))
{ fprintf( stderr, "Illegal margin specification!\n");
exit( 1);
}
margin[0] = 0.01 * x * mediasize[2];
margin[1] = 0.01 * x * mediasize[3];
} else
{ /* absolute margin value */
double marg[4];
box_convert( spec, marg);
margin[0] = marg[2];
margin[1] = marg[3];
}
for (i=0; i<2; i++)
{ if (margin[i] < 0 || 2.0*margin[i] >= mediasize[i+2])
{ fprintf( stderr, "Margin value '%s' out of range!\n",
spec);
exit(1);
}
}
}
static void box_convert( char *boxspec, double psbox[4])
{ /* convert user textual box spec into numbers in ps units */
/* box = [fixed x fixed][+ fixed , fixed] unit */
/* fixed = digits [ . digits] */
/* unit = medianame | i | cm | mm | m | p */
double mx, my, ox, oy, ux, uy;
int n, r, i, l, inx;
char *spec;
mx = my = 1.0;
ox = oy = 0.0;
spec = boxspec;
/* read 'fixed x fixed' */
if (isdigit( spec[0]))
{ r = sscanf( spec, "%lfx%lf%n", &mx, &my, &n);
if (r != 2)
{ r = sscanf( spec, "%lf*%lf%n", &mx, &my, &n);
if (r != 2) boxerr( boxspec);
}
spec += n;
}
/* read '+ fixed , fixed' */
if (1 < (r = sscanf( spec, "+%lf,%lf%n", &ox, &oy, &n)))
{ if (r != 2) boxerr( boxspec);
spec += n;
}
/* read unit */
l = strlen( spec);
for (n=i=0; mediatable[i][0]; i++)
{ if (!mystrncasecmp( mediatable[i][0], spec, l))
{ /* found */
n++;
inx = i;
if (l == strlen( mediatable[i][0]))
{ /* match is exact */
n = 1;
break;
}
}
}
if (!n) boxerr( boxspec);
if (n>1)
{ fprintf( stderr, "Your box spec '%s' is not unique! (give more chars)\n",
spec);
exit(1);
}
sscanf( mediatable[inx][1], "%lf,%lf", &ux, &uy);
psbox[0] = ox * ux;
psbox[1] = oy * uy;
psbox[2] = mx * ux;
psbox[3] = my * uy;
if (verbose > 1)
fprintf( stderr, " Box_convert: '%s' into [%g,%g,%g,%g]\n",
boxspec, psbox[0], psbox[1], psbox[2], psbox[3]);
for (i=0; i<2; i++)
{ if (psbox[i] < 0.0 || psbox[i+2] < psbox[i])
{ fprintf( stderr, "Your specification `%s' leads to "
"negative values!\n", boxspec);
exit(1);
}
}
}
static void boxerr( char *spec)
{ int i;
fprintf( stderr, "I don't understand your box specification `%s'!\n",
spec);
fprintf( stderr, "The proper format is: ([text] meaning optional text)\n");
fprintf( stderr, " [multiplier][offset]unit\n");
fprintf( stderr, " with multiplier: numberxnumber\n");
fprintf( stderr, " with offset: +number,number\n");
fprintf( stderr, " with unit one of:");
for (i=0; mediatable[i][0]; i++)
fprintf( stderr, "%c%-10s", (i%7)?' ':'\n', mediatable[i][0]);
fprintf( stderr, "\nYou can use a shorthand for these unit names,\n"
"provided it resolves unique.\n");
exit( 1);
}
/*********************************************/
/* output first part of DSC header */
/*********************************************/
static void dsc_head1()
{
printf ("%%!PS-Adobe-3.0\n");
printf ("%%%%Creator: %s\n", myname);
}
/*********************************************/
/* pass some DSC info from the infile in the new DSC header */
/* such as document fonts and */
/* extract BoundingBox info from the PS file */
/*********************************************/
static int dsc_infile( double ps_bb[4])
{
char *c, buf[BUFSIZE];
int gotall, atend, level, dsc_cont, inbody, got_bb;
if (freopen (infile, "r", stdin) == NULL) {
fprintf (stderr, "%s: fail to open file '%s'!\n",
myname, infile);
exit (1);
}
got_bb = 0;
dsc_cont = inbody = gotall = level = atend = 0;
while (!gotall && (gets(buf) != NULL))
{
if (buf[0] != '%')
{ dsc_cont = 0;
if (!inbody) inbody = 1;
if (!atend) gotall = 1;
continue;
}
if (!strncmp( buf, "%%+",3) && dsc_cont)
{ puts( buf);
continue;
}
dsc_cont = 0;
if (!strncmp( buf, "%%EndComments", 13))
{ inbody = 1;
if (!atend) gotall = 1;
}
else if (!strncmp( buf, "%%BeginDocument", 15) ||
!strncmp( buf, "%%BeginData", 11)) level++;
else if (!strncmp( buf, "%%EndDocument", 13) ||
!strncmp( buf, "%%EndData", 9)) level--;
else if (!strncmp( buf, "%%Trailer", 9) && level == 0)
inbody = 2;
else if (!strncmp( buf, "%%BoundingBox:", 14) &&
inbody!=1 && !level)
{ for (c=buf+14; *c==' ' || *c=='\t'; c++);
if (!strncmp( c, "(atend)", 7)) atend = 1;
else
{ sscanf( c, "%lf %lf %lf %lf",
ps_bb, ps_bb+1, ps_bb+2, ps_bb+3);
got_bb = 1;
}
}
else if (!strncmp( buf, "%%Document", 10) &&
inbody!=1 && !level) /* several kinds of doc props */
{ for (c=buf+10; *c && *c!=' ' && *c!='\t'; c++);
for (; *c==' ' || *c=='\t'; c++);
if (!strncmp( c, "(atend)", 7)) atend = 1;
else
{ /* pass this DSC to output */
puts( buf);
dsc_cont = 1;
}
}
}
return got_bb;
}
/*********************************************/
/* output last part of DSC header */
/*********************************************/
static void dsc_head2()
{
printf ("%%%%Pages: %d\n", nrows*ncols);
#ifndef Gv_gs_orientbug
printf ("%%%%Orientation: %s\n", rotate?"Landscape":"Portrait");
#endif
printf ("%%%%DocumentMedia: %s %d %d 0 white ()\n",
mediaspec, (int)(mediasize[2]), (int)(mediasize[3]));
printf ("%%%%BoundingBox: 0 0 %d %d\n", (int)(mediasize[2]), (int)(mediasize[3]));
printf ("%%%%EndComments\n\n");
printf ("%% Print poster %s in %dx%d tiles with %.3g magnification\n",
infile, nrows, ncols, scale);
}
/*********************************************/
/* output the poster, create tiles if needed */
/*********************************************/
static void printposter()
{
int row, col;
printprolog();
for (row = 1; row <= nrows; row++)
for (col = 1; col <= ncols; col++)
tile( row, col);
printf ("%%%%EOF\n");
if (tail_cntl_D)
{ printf("%c", 0x4);
}
}
/*******************************************************/
/* output PS prolog of the scaling and tiling routines */
/*******************************************************/
static void printprolog()
{
printf( "%%%%BeginProlog\n");
printf( "/cutmark %% - cutmark -\n"
"{ %% draw cutline\n"
" 0.23 setlinewidth 0 setgray\n"
" clipmargin\n"
" dup 0 moveto\n"
" dup neg leftmargin add 0 rlineto stroke\n"
" %% draw sheet alignment mark\n"
" dup dup neg moveto\n"
" dup 0 rlineto\n"
" dup dup lineto\n"
" 0 rlineto\n"
" closepath fill\n"
"} bind def\n\n");
printf( "%% usage: row col tileprolog ps-code tilepilog\n"
"%% these procedures output the tile specified by row & col\n"
"/tileprolog\n"
"{ %%def\n"
" gsave\n"
" leftmargin botmargin translate\n"
" do_turn {exch} if\n"
" /colcount exch def\n"
" /rowcount exch def\n"
" %% clip page contents\n"
" clipmargin neg dup moveto\n"
" pagewidth clipmargin 2 mul add 0 rlineto\n"
" 0 pageheight clipmargin 2 mul add rlineto\n"
" pagewidth clipmargin 2 mul add neg 0 rlineto\n"
" closepath clip\n"
" %% set page contents transformation\n"
" do_turn\n"
" { pagewidth 0 translate\n"
" 90 rotate\n"
" } if\n"
" pagewidth colcount 1 sub mul neg\n"
" pageheight rowcount 1 sub mul neg\n"
" do_turn {exch} if\n"
" translate\n"
" posterxl posteryb translate\n"
" sfactor dup scale\n"
" imagexl neg imageyb neg translate\n"
" tiledict begin\n"
" 0 setgray 0 setlinecap 1 setlinewidth\n"
" 0 setlinejoin 10 setmiterlimit [] 0 setdash newpath\n"
"} bind def\n\n");
printf( "/tileepilog\n"
"{ end %% of tiledict\n"
" grestore\n"
" %% print the cutmarks\n"
" gsave\n"
" leftmargin botmargin translate\n"
" pagewidth pageheight translate cutmark 90 rotate cutmark\n"
" 0 pagewidth translate cutmark 90 rotate cutmark\n"
" 0 pageheight translate cutmark 90 rotate cutmark\n"
" 0 pagewidth translate cutmark 90 rotate cutmark\n"
" grestore\n"
" %% print the page label\n"
" 0 setgray\n"
" leftmargin clipmargin 3 mul add clipmargin labelsize add neg botmargin add moveto\n"
" (Grid \\( ) show\n"
" rowcount strg cvs show\n"
" ( , ) show\n"
" colcount strg cvs show\n"
" ( \\)) show\n"
" showpage\n"
"} bind def\n\n");
printf( "%%%%EndProlog\n\n");
printf( "%%%%BeginSetup\n");
printf( "%% Try to inform the printer about the desired media size:\n"
"/setpagedevice where %% level-2 page commands available...\n"
"{ pop %% ignore where found\n"
" 3 dict dup /PageSize [ %d %d ] put\n"
" dup /Duplex false put\n%s"
" setpagedevice\n"
"} if\n",
(int)(mediasize[2]), (int)(mediasize[3]),
manualfeed?" dup /ManualFeed true put\n":"");
printf( "/sfactor %.10f def\n"
"/leftmargin %d def\n"
"/botmargin %d def\n"
"/pagewidth %d def\n"
"/pageheight %d def\n"
"/imagexl %d def\n"
"/imageyb %d def\n"
"/posterxl %d def\n"
"/posteryb %d def\n"
"/do_turn %s def\n"
"/strg 10 string def\n"
"/clipmargin 6 def\n"
"/labelsize 9 def\n"
"/tiledict 250 dict def\n"
"tiledict begin\n"
"%% delay users showpage until cropmark is printed.\n"
"/showpage {} def\n"
"/setpagedevice { pop } def\n"
"end\n",
scale, (int)(cutmargin[0]), (int)(cutmargin[1]),
(int)(mediasize[2]-2.0*cutmargin[0]), (int)(mediasize[3]-2.0*cutmargin[1]),
(int)imagebb[0], (int)imagebb[1], (int)posterbb[0], (int)posterbb[1],
rotate?"true":"false");
printf( "/Helvetica findfont labelsize scalefont setfont\n");
printf( "%%%%EndSetup\n");
}
/*****************************/
/* output one tile at a time */
/*****************************/
static void tile ( int row, int col)
{
static int page=1;
if (verbose) fprintf( stderr, "print page %d\n", page);
printf ("\n%%%%Page: %d %d\n", page, page);
printf ("%d %d tileprolog\n", row, col);
printf ("%%%%BeginDocument: %s\n", infile);
printfile ();
printf ("\n%%%%EndDocument\n");
printf ("tileepilog\n");
page++;
}
/******************************/
/* copy the PS file to output */
/******************************/
static void printfile ()
{
/* use a double line buffer, so that when I print */
/* a line, I know whether it is the last or not */
/* I surely dont want to print a 'cntl_D' on the last line */
/* The double buffer removes the need to scan each line for each page*/
/* Furthermore allows cntl_D within binary transmissions */
char buf[2][BUFSIZE];
int bp;
char *c;
if (freopen (infile, "r", stdin) == NULL) {
fprintf (stderr, "%s: fail to open file '%s'!\n",
myname, infile);
printf ("/systemdict /showpage get exec\n");
printf ("%%%%EOF\n");
exit (1);
}
/* fill first buffer for the first time */
fgets( buf[bp=0], BUFSIZE, stdin);
/* read subsequent lines by rotating the buffers */
while (fgets(buf[1-bp], BUFSIZE, stdin))
{ /* print line from the previous fgets */
/* do not print postscript comment lines: those (DSC) lines */
/* sometimes disturb proper previewing of the result with ghostview */
if (buf[bp][0] != '%')
fputs( buf[bp], stdout);
bp = 1-bp;
}
/* print buf from last successfull fgets, after removing cntlD */
for (c=buf[bp]; *c && *c != '\04'; c++);
if (*c == '\04')
{ tail_cntl_D = 1;
*c = '\0';
}
if (buf[bp][0] != '%' && strlen( buf[bp]))
fputs( buf[bp], stdout);
}
static int mystrncasecmp( const char *s1, const char *s2, int n)
{ /* compare case-insensitive s1 and s2 for at most n chars */
/* return 0 if equal. */
/* Although standard available on some machines, */
/* this function seems not everywhere around... */
char c1, c2;
int i;
if (!s1) s1 = "";
if (!s2) s2 = "";
for (i=0; i<n && *s1 && *s2; i++, s1++, s2++)
{ c1 = tolower( *s1);
c2 = tolower( *s2);
if (c1 != c2) break;
}
return (i < n && (*s1 || *s2));
}