/* * this code (except for the driver XImageToEPS) is taken straight from * pnmtops.c, which is part of the pbmplus image manipulation package. */ /* pnmtops.c - read a portable anymap and produce a PostScript file ** ** Copyright (C) 1989 by Jef Poskanzer. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ # include # include # include # include # include "proto.h" # include "error.h" # include "version.h" #define MARGIN 0.95 typedef unsigned char xelval; extern XImage *WidgetToXImage PROTO((Widget, XColor **, int *)); static int colorstobpp PROTO((int colors)); static void putinit PROTO(( char* name, int cols, int rows, int padright, int bps, float scale, int dpi, int pagewid, int pagehgt, int turnflag, int turnokflag, int rleflag )); static void putitem PROTO(( void )); static void putxelval PROTO(( xelval xv )); static void putrest PROTO(( void )); static void rleputbuffer PROTO(( void )); static void rleputitem PROTO(( void )); static void rleputxelval PROTO(( xelval xv )); static void rleflush PROTO(( void )); static void rleputrest PROTO(( void )); static FILE *output; void WidgetToEPS (filename, w) char *filename; Widget w; { XImage *img; int turnflag, turnokflag, rleflag; int rows, cols, bps, padright, row, col; float scale; int dpi, pagewid, pagehgt; unsigned i; int ncells; XColor *colors; int idx; output = fopen (filename, "w"); if (output == NULL) { error ("could not open %s for writing.", filename); return; } img = WidgetToXImage(w, &colors, &ncells); for (i = 0 ; i < ncells ; i++) fprintf (stderr,"%d -> %u : %d %d %d\n", i, colors [i].pixel, colors [i].red, colors [i].green, colors [i].blue); scale = 1.0; turnflag = 0; turnokflag = 1; rleflag = 0; /* LaserWriter defaults. */ dpi = 300; pagewid = 612; pagehgt = 762; cols = img -> width; rows = img -> height; /* Figure out bps. */ bps = colorstobpp (ncells); if ( bps > 2 && bps < 4 ) bps = 4; else if ( bps > 4 && bps < 8 ) bps = 8; /* Compute padding to round cols * bps up to the nearest multiple of 8. */ padright = ( ( ( cols * bps + 7 ) / 8 ) * 8 - cols * bps ) / bps; putinit( filename, cols, rows, padright, bps, scale, dpi, pagewid, pagehgt, turnflag, turnokflag, rleflag ); for ( row = 0; row < rows; ++row ) { /* First red. */ for ( col = 0; col < cols; ++col ) idx = XImageCellXY(img, col, row, colors, ncells); if ( rleflag ) rleputxelval( colors [idx].red/256 ); else putxelval( colors [idx].red/256 ); for ( col = 0; col < padright; ++col ) if ( rleflag ) rleputxelval( 0 ); else putxelval( 0 ); if ( rleflag ) rleflush(); /* Then green. */ for ( col = 0; col < cols; ++col ) idx = XImageCellXY(img, col, row, colors, ncells); if ( rleflag ) rleputxelval( colors [idx].green/256 ); else putxelval( colors [idx].green/256 ); for ( col = 0; col < padright; ++col ) if ( rleflag ) rleputxelval( 0 ); else putxelval( 0 ); if ( rleflag ) rleflush(); /* And blue. */ for ( col = 0; col < cols; ++col ) idx = XImageCellXY(img, col, row, colors, ncells); if ( rleflag ) rleputxelval( colors [idx].blue/256 ); else putxelval( colors [idx].blue/256 ); for ( col = 0; col < padright; ++col ) if ( rleflag ) rleputxelval( 0 ); else putxelval( 0 ); if ( rleflag ) rleflush(); } if ( rleflag ) rleputrest(); else putrest(); fclose (output); free(colors); return; } static int colorstobpp( colors ) int colors; { int bpp; if ( colors <= 1 ) bpp = 1; else if ( colors <= 3 ) bpp = 2; else if ( colors <= 7 ) bpp = 3; else if ( colors <= 15 ) bpp = 4; else if ( colors <= 31 ) bpp = 5; else if ( colors <= 63 ) bpp = 6; else if ( colors <= 127 ) bpp = 7; else if ( colors <= 255 ) bpp = 8; else bpp = 8; return bpp; } static int bitspersample, item, bitsperitem, bitshift, itemsperline, items; static int rleitem, rlebitsperitem, rlebitshift; static int repeat, itembuf[128], count, repeatitem, repeatcount; #ifdef __STDC__ static void putinit( char* name, int cols, int rows, int padright, int bps, float scale, int dpi, int pagewid, int pagehgt, int turnflag, int turnokflag, int rleflag ) #else /*__STDC__*/ static void putinit( name, cols, rows, padright, bps, scale, dpi, pagewid, pagehgt, turnflag, turnokflag, rleflag ) char* name; int cols, rows, padright, bps; float scale; int dpi, pagewid, pagehgt, turnflag, turnokflag, rleflag; #endif /*__STDC__*/ { int icols, irows, devpix; float pixfac, scols, srows, llx, lly; /* Turn? */ icols = cols; irows = rows; if ( turnflag || ( turnokflag && cols > rows ) ) { turnflag = 1; cols = irows; rows = icols; } /* Figure out size. */ devpix = dpi / 72.0 + 0.5; /* device pixels per unit, approx. */ pixfac = 72.0 / dpi * devpix; /* 1, approx. */ scols = scale * cols * pixfac; srows = scale * rows * pixfac; if ( scols > pagewid * MARGIN || srows > pagehgt * MARGIN ) { if ( scols > pagewid * MARGIN ) { scale *= pagewid / scols * MARGIN; scols = scale * cols * pixfac; srows = scale * rows * pixfac; } if ( srows > pagehgt * MARGIN ) { scale *= pagehgt / srows * MARGIN; scols = scale * cols * pixfac; srows = scale * rows * pixfac; } error( "warning, image too large for page, rescaling to %g", scale ); } llx = ( pagewid - scols ) / 2; lly = ( pagehgt - srows ) / 2; fprintf(output, "%%!PS-Adobe-2.0 EPSF-2.0\n" ); fprintf(output, "%%%%Creator: Velvet %s\n", VERSION ); fprintf(output, "%%%%Title: %s\n", name ); fprintf(output, "%%%%Pages: 1\n" ); fprintf(output, "%%%%BoundingBox: %d %d %d %d\n", (int) llx, (int) lly, (int) ( llx + scols + 0.5 ), (int) ( lly + srows + 0.5 ) ); fprintf(output, "%%%%EndComments\n" ); if ( rleflag ) { fprintf(output, "/rlestr1 1 string def\n" ); fprintf(output, "/readrlestring {\n" ); /* s -- nr */ fprintf(output, " /rlestr exch def\n" ); /* - */ fprintf(output, " currentfile rlestr1 readhexstring pop\n" ); /* s1 */ fprintf(output, " 0 get\n" ); /* c */ fprintf(output, " dup 127 le {\n" ); /* c */ fprintf(output, " currentfile rlestr 0\n" ); /* c f s 0 */ fprintf(output, " 4 3 roll\n" ); /* f s 0 c */ fprintf(output, " 1 add getinterval\n" ); /* f s */ fprintf(output, " readhexstring pop\n" ); /* s */ fprintf(output, " length\n" ); /* nr */ fprintf(output, " } {\n" ); /* c */ fprintf(output, " 256 exch sub dup\n" ); /* n n */ fprintf(output, " currentfile rlestr1 readhexstring pop\n" );/* n n s1 */ fprintf(output, " 0 get\n" ); /* n n c */ fprintf(output, " exch 0 exch 1 exch 1 sub {\n" ); /* n c 0 1 n-1*/ fprintf(output, " rlestr exch 2 index put\n" ); fprintf(output, " } for\n" ); /* n c */ fprintf(output, " pop\n" ); /* nr */ fprintf(output, " } ifelse\n" ); /* nr */ fprintf(output, "} bind def\n" ); fprintf(output, "/readstring {\n" ); /* s -- s */ fprintf(output, " dup length 0 {\n" ); /* s l 0 */ fprintf(output, " 3 copy exch\n" ); /* s l n s n l*/ fprintf(output, " 1 index sub\n" ); /* s l n s n r*/ fprintf(output, " getinterval\n" ); /* s l n ss */ fprintf(output, " readrlestring\n" ); /* s l n nr */ fprintf(output, " add\n" ); /* s l n */ fprintf(output, " 2 copy le { exit } if\n" ); /* s l n */ fprintf(output, " } loop\n" ); /* s l l */ fprintf(output, " pop pop\n" ); /* s */ fprintf(output, "} bind def\n" ); } else { fprintf(output, "/readstring {\n" ); /* s -- s */ fprintf(output, " currentfile exch readhexstring pop\n" ); fprintf(output, "} bind def\n" ); } fprintf(output, "/rpicstr %d string def\n", ( icols + padright ) * bps / 8 ); fprintf(output, "/gpicstr %d string def\n", ( icols + padright ) * bps / 8 ); fprintf(output, "/bpicstr %d string def\n", ( icols + padright ) * bps / 8 ); fprintf(output, "%%%%EndProlog\n" ); fprintf(output, "%%%%Page: 1 1\n" ); fprintf(output, "gsave\n" ); fprintf(output, "%g %g translate\n", llx, lly ); fprintf(output, "%g %g scale\n", scols, srows ); if ( turnflag ) fprintf(output, "0.5 0.5 translate 90 rotate -0.5 -0.5 translate\n" ); fprintf(output, "%d %d %d\n", icols, irows, bps ); fprintf(output, "[ %d 0 0 -%d 0 %d ]\n", icols, irows, irows ); fprintf(output, "{ rpicstr readstring }\n" ); fprintf(output, "{ gpicstr readstring }\n" ); fprintf(output, "{ bpicstr readstring }\n" ); fprintf(output, "true 3\n" ); fprintf(output, "colorimage\n" ); bitspersample = bps; itemsperline = items = 0; if ( rleflag ) { rleitem = 0; rlebitsperitem = 0; rlebitshift = 8 - bitspersample; repeat = 1; count = 0; } else { item = 0; bitsperitem = 0; bitshift = 8 - bitspersample; } } static void putitem() { char* hexits = "0123456789abcdef"; if ( itemsperline == 30 ) { putc( '\n', output ); itemsperline = 0; } putc( hexits[item >> 4], output ); putc( hexits[item & 15], output ); ++itemsperline; ++items; item = 0; bitsperitem = 0; bitshift = 8 - bitspersample; } #if __STDC__ static void putxelval( xelval xv ) #else /*__STDC__*/ static void putxelval( xv ) xelval xv; #endif /*__STDC__*/ { if ( bitsperitem == 8 ) putitem(); item += xv << bitshift; bitsperitem += bitspersample; bitshift -= bitspersample; } static void putrest() { if ( bitsperitem > 0 ) putitem(); fprintf(output, "\n" ); fprintf(output, "grestore\n" ); fprintf(output, "showpage\n" ); fprintf(output, "%%%%Trailer\n" ); } static void rleputbuffer() { int i; if ( repeat ) { item = 256 - count; putitem(); item = repeatitem; putitem(); } else { item = count - 1; putitem(); for ( i = 0; i < count; ++i ) { item = itembuf[i]; putitem(); } } repeat = 1; count = 0; } static void rleputitem() { int i; if ( count == 128 ) rleputbuffer(); if ( repeat && count == 0 ) { /* Still initializing a repeat buf. */ itembuf[count] = repeatitem = rleitem; ++count; } else if ( repeat ) { /* Repeating - watch for end of run. */ if ( rleitem == repeatitem ) { /* Run continues. */ itembuf[count] = rleitem; ++count; } else { /* Run ended - is it long enough to dump? */ if ( count > 2 ) { /* Yes, dump a repeat-mode buffer and start a new one. */ rleputbuffer(); itembuf[count] = repeatitem = rleitem; ++count; } else { /* Not long enough - convert to non-repeat mode. */ repeat = 0; itembuf[count] = repeatitem = rleitem; ++count; repeatcount = 1; } } } else { /* Not repeating - watch for a run worth repeating. */ if ( rleitem == repeatitem ) { /* Possible run continues. */ ++repeatcount; if ( repeatcount > 3 ) { /* Long enough - dump non-repeat part and start repeat. */ count = count - ( repeatcount - 1 ); rleputbuffer(); count = repeatcount; for ( i = 0; i < count; ++i ) itembuf[i] = rleitem; } else { /* Not long enough yet - continue as non-repeat buf. */ itembuf[count] = rleitem; ++count; } } else { /* Broken run. */ itembuf[count] = repeatitem = rleitem; ++count; repeatcount = 1; } } rleitem = 0; rlebitsperitem = 0; rlebitshift = 8 - bitspersample; } #if __STDC__ static void rleputxelval( xelval xv ) #else /*__STDC__*/ static void rleputxelval( xv ) xelval xv; #endif /*__STDC__*/ { if ( rlebitsperitem == 8 ) rleputitem(); rleitem += xv << rlebitshift; rlebitsperitem += bitspersample; rlebitshift -= bitspersample; } static void rleflush() { if ( rlebitsperitem > 0 ) rleputitem(); if ( count > 0 ) rleputbuffer(); } static void rleputrest() { rleflush(); fprintf(output, "\n" ); fprintf(output, "grestore\n" ); fprintf(output, "showpage\n" ); fprintf(output, "%%%%Trailer\n" ); }