tpictures.c - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tpictures.c (9628B)
       ---
            1 /*
            2  *
            3  * PostScript picture inclusion routines. Support for managing in-line pictures
            4  * has been added, and works in combination with the simple picpack pre-processor
            5  * that's supplied with this package. An in-line picture begins with a special
            6  * device control command that looks like,
            7  *
            8  *                x X InlinPicture name size
            9  *
           10  * where name is the pathname of the original picture file and size is the number
           11  * of bytes in the picture, which begins immediately on the next line. When dpost
           12  * encounters the InlinePicture device control command inlinepic() is called and
           13  * that routine appends the string name and the integer size to a temporary file
           14  * (fp_pic) and then adds the next size bytes read from the current input file to
           15  * file fp_pic. All in-line pictures are saved in fp_pic and located later using
           16  * the name string and picture file size that separate pictures saved in fp_pic.
           17  *
           18  * When a picture request (ie. an "x X PI" command) is encountered picopen() is
           19  * called and it first looks for the picture file in fp_pic. If it's found there
           20  * the entire picture (ie. size bytes) is copied from fp_pic to a new temp file
           21  * and that temp file is used as the picture file. If there's nothing in fp_pic
           22  * or if the lookup failed the original route is taken.
           23  *
           24  * Support for in-line pictures is an attempt to address requirements, expressed
           25  * by several organizations, of being able to store a document as a single file
           26  * (usually troff input) that can then be sent through dpost and ultimately to
           27  * a PostScript printer. The mechanism may help some users, but the are obvious
           28  * disadvantages to this approach, and the original mechanism is the recommended
           29  * approach! Perhaps the most important problem is that troff output, with in-line
           30  * pictures included, doesn't fit the device independent language accepted by
           31  * important post-processors (like proff) and that means you won't be able to
           32  * reliably preview a packed file on your 5620 (or whatever).
           33  *
           34  */
           35 
           36 #include <u.h>
           37 #include <libc.h>
           38 #include <bio.h>
           39 #include <stdio.h>
           40 #include "ext.h"
           41 #include "common.h"
           42 #include "tr2post.h"
           43 /* PostScript file structuring comments */
           44 #include "comments.h"
           45 /* general purpose definitions */
           46 /* #include "gen.h" */
           47 /* just for TEMPDIR definition */
           48 #include "path.h"
           49 /* external variable declarations */
           50 /* #include "ext.h" */
           51 
           52 Biobuf        *bfp_pic = NULL;
           53 Biobuf        *Bfp_pic;
           54 Biobuf        *picopen(char *);
           55 
           56 #define MAXGETFIELDS        16
           57 char *fields[MAXGETFIELDS];
           58 int nfields;
           59 
           60 extern int        devres, hpos, vpos;
           61 extern int        picflag;
           62 
           63 /*****************************************************************************/
           64 
           65 void
           66 picture(Biobuf *inp, char *buf) {
           67         int        poffset;                /* page offset */
           68         int        indent;                /* indent */
           69         int        length;                /* line length  */
           70         int        totrap;                /* distance to next trap */
           71         char        name[100];        /* picture file and page string */
           72         char        hwo[40], *p;        /* height, width and offset strings */
           73         char        flags[20];                /* miscellaneous stuff */
           74         int        page = 1;                /* page number pulled from name[] */
           75         double        frame[4];        /* height, width, y, and x offsets from hwo[] */
           76         char        units;                /* scale indicator for frame dimensions */
           77         int        whiteout = 0;        /* white out the box? */
           78         int        outline = 0;        /* draw a box around the picture? */
           79         int        scaleboth = 0;        /* scale both dimensions? */
           80         double        adjx = 0.5;        /* left-right adjustment */
           81         double        adjy = 0.5;        /* top-bottom adjustment */
           82         double        rot = 0;        /* rotation in clockwise degrees */
           83         Biobuf        *fp_in;        /* for *name */
           84         int        i;                        /* loop index */
           85 
           86 /*
           87  *
           88  * Called from devcntrl() after an 'x X PI' command is found. The syntax of that
           89  * command is:
           90  *
           91  *        x X PI:args
           92  *
           93  * with args separated by colons and given by:
           94  *
           95  *        poffset
           96  *        indent
           97  *        length
           98  *        totrap
           99  *        file[(page)]
          100  *        height[,width[,yoffset[,xoffset]]]
          101  *        [flags]
          102  *
          103  * poffset, indent, length, and totrap are given in machine units. height, width,
          104  * and offset refer to the picture frame in inches, unless they're followed by
          105  * the u scale indicator. flags is a string that provides a little bit of control
          106  * over the placement of the picture in the frame. Rotation of the picture, in
          107  * clockwise degrees, is set by the a flag. If it's not followed by an angle
          108  * the current rotation angle is incremented by 90 degrees, otherwise the angle
          109  * is set by the number that immediately follows the a.
          110  *
          111  */
          112 
          113         if (!picflag)                /* skip it */
          114                 return;
          115         endstring();
          116 
          117         flags[0] = '\0';                        /* just to be safe */
          118 
          119         nfields = getfields(buf, fields, MAXGETFIELDS, 0, ":\n");
          120         if (nfields < 6) {
          121                 error(WARNING, "too few arguments to specify picture");
          122                 return;
          123         }
          124         poffset = atoi(fields[1]);
          125         indent = atoi(fields[2]);
          126         length = atoi(fields[3]);
          127         totrap = atoi(fields[4]);
          128         strncpy(name, fields[5], sizeof(name));
          129         strncpy(hwo, fields[6], sizeof(hwo));
          130         if (nfields >= 6)
          131                 strncpy(flags, fields[7], sizeof(flags));
          132 
          133         nfields = getfields(buf, fields, MAXGETFIELDS, 0, "()");
          134         if (nfields == 2) {
          135                 strncpy(name, fields[0], sizeof(name));
          136                 page = atoi(fields[1]);
          137         }
          138 
          139         if ((fp_in = picopen(name)) == NULL) {
          140                 error(WARNING, "can't open picture file %s\n", name);
          141                 return;
          142         }
          143 
          144         frame[0] = frame[1] = -1;                /* default frame height, width */
          145         frame[2] = frame[3] = 0;                /* and y and x offsets */
          146 
          147         for (i = 0, p = hwo-1; i < 4 && p != NULL; i++, p = strchr(p, ','))
          148                 if (sscanf(++p, "%lf%c", &frame[i], &units) == 2)
          149                             if (units == 'i' || units == ',' || units == '\0')
          150                                 frame[i] *= devres;
          151 
          152         if (frame[0] <= 0)                /* check what we got for height */
          153                 frame[0] = totrap;
          154 
          155             if (frame[1] <= 0)                /* and width - check too big?? */
          156                 frame[1] = length - indent;
          157 
          158         frame[3] += poffset + indent;        /* real x offset */
          159 
          160         for (i = 0; flags[i]; i++)
          161                 switch (flags[i]) {
          162                 case 'c': adjx = adjy = 0.5; break;        /* move to the center */
          163                 case 'l': adjx = 0; break;                /* left */
          164                 case 'r': adjx = 1; break;                /* right */
          165                 case 't': adjy = 1; break;                /* top */
          166                 case 'b': adjy = 0; break;                /* or bottom justify */
          167                 case 'o': outline = 1; break;        /* outline the picture */
          168                 case 'w': whiteout = 1; break;        /* white out the box */
          169                 case 's': scaleboth = 1; break;        /* scale both dimensions */
          170                 case 'a': if ( sscanf(&flags[i+1], "%lf", &rot) != 1 )
          171                           rot += 90;
          172         }
          173 
          174         /* restore(); */
          175         endstring();
          176         Bprint(Bstdout, "cleartomark\n");
          177         Bprint(Bstdout, "saveobj restore\n");
          178 
          179         ps_include(fp_in, Bstdout, page, whiteout, outline, scaleboth,
          180                 frame[3]+frame[1]/2, -vpos-frame[2]-frame[0]/2, frame[1], frame[0], adjx, adjy, -rot);
          181         /* save(); */
          182         Bprint(Bstdout, "/saveobj save def\n");
          183         Bprint(Bstdout, "mark\n");
          184         Bterm(fp_in);
          185 
          186 }
          187 
          188 /*
          189  *
          190  * Responsible for finding and opening the next picture file. If we've accumulated
          191  * any in-line pictures fp_pic won't be NULL and we'll look there first. If *path
          192  * is found in *fp_pic we create another temp file, open it for update, unlink it,
          193  * copy in the picture, seek back to the start of the new temp file, and return
          194  * the file pointer to the caller. If fp_pic is NULL or the lookup fails we just
          195  * open file *path and return the resulting file pointer to the caller.
          196  *
          197  */
          198 Biobuf *
          199 picopen(char *path) {
          200 /*        char        name[100];        /* pathnames */
          201 /*        long        pos;                        /* current position */
          202 /*        long        total;                        /* and sizes - from *fp_pic */
          203         Biobuf *bfp;
          204         Biobuf        *Bfp;                /* and pointer for the new temp file */
          205 
          206 
          207         if ((bfp = Bopen(path, OREAD)) == 0)
          208                 error(FATAL, "can't open %s\n", path);
          209         Bfp = bfp; /* &(bfp->Biobufhdr); */
          210         return(Bfp);
          211 #ifdef UNDEF
          212         if (Bfp_pic != NULL) {
          213                 Bseek(Bfp_pic, 0L, 0);
          214                 while (Bgetfield(Bfp_pic, 's', name, 99)>0
          215                         && Bgetfield(Bfp_pic, 'd', &total, 0)>0) {
          216                         pos = Bseek(Bfp_pic, 0L, 1);
          217                         if (strcmp(path, name) == 0) {
          218                                 if (tmpnam(pictmpname) == NULL)
          219                                         error(FATAL, "can't generate temp file name");
          220                                 if ( (bfp = Bopen(pictmpname, ORDWR)) == NULL )
          221                                         error(FATAL, "can't open %s", pictmpname);
          222                                 Bfp = &(bfp->Biobufhdr);
          223                                 piccopy(Bfp_pic, Bfp, total);
          224                                 Bseek(Bfp, 0L, 0);
          225                                 return(Bfp);
          226                             }
          227                         Bseek(Bfp_pic, total+pos, 0);
          228                 }
          229         }
          230         if ((bfp = Bopen(path, OREAD)) == 0)
          231                 Bfp = 0;
          232         else
          233                 Bfp = &(bfp->Biobufhdr);
          234         return(Bfp);
          235 #endif
          236 }
          237 
          238 /*
          239  *
          240  * Adds an in-line picture file to the end of temporary file *Bfp_pic. All pictures
          241  * grabbed from the input file are saved in the same temp file. Each is preceeded
          242  * by a one line header that includes the original picture file pathname and the
          243  * size of the picture in bytes. The in-line picture file is opened for update,
          244  * left open, and unlinked so it disappears when we do.
          245  *
          246  */
          247 /*        *fp;                        /* current input file */
          248 /*        *buf;                        /* whatever followed "x X InlinePicture" */
          249 
          250 #ifdef UNDEF
          251 void
          252 inlinepic(Biobufhdr *Bfp, char *buf) {
          253         char        name[100];                /* picture file pathname */
          254         long        total;                        /* and size - both from *buf */
          255 
          256 
          257         if (Bfp_pic == NULL ) {
          258                 tmpnam(pictmpname);
          259                 if ((bfp_pic = Bopen(pictmpname, ORDWR)) == 0)
          260                             error(FATAL, "can't open in-line picture file %s", ipictmpname);
          261                 unlink(pictmpname);
          262         }
          263 
          264         if ( sscanf(buf, "%s %ld", name, &total) != 2 )
          265                 error(FATAL, "in-line picture error");
          266 
          267         fseek(Bfp_pic, 0L, 2);
          268         fprintf(Bfp_pic, "%s %ld\n", name, total);
          269         getc(fp);
          270         fflush(fp_pic);
          271         piccopy(fp, fp_pic, total);
          272         ungetc('\n', fp);
          273 
          274 }
          275 #endif
          276 
          277 /*
          278  *
          279  * Copies total bytes from file fp_in to fp_out. Used to append picture files to
          280  * *fp_pic and then copy them to yet another temporary file immediately before
          281  * they're used (in picture()).
          282  *
          283  */
          284 /*        *fp_in;        input */
          285 /*        *fp_out;        and output file pointers */
          286 /*        total;                number of bytes to be copied */
          287 void
          288 piccopy(Biobuf *Bfp_in, Biobuf *Bfp_out, long total) {
          289         long i;
          290 
          291         for (i = 0; i < total; i++)
          292                 if (Bputc(Bfp_out, Bgetc(Bfp_in)) < 0)
          293                         error(FATAL, "error copying in-line picture file");
          294         Bflush(Bfp_out);
          295 }