1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <stdio.h> 5 #include "../common/common.h" 6 #include "ps_include.h" 7 8 extern int curpostfontid; 9 extern int curfontsize; 10 11 typedef struct {long start, end;} Section; 12 static char *buf; 13 14 static void 15 copy(Biobufhdr *fin, Biobufhdr *fout, Section *s) { 16 if (s->end <= s->start) 17 return; 18 Bseek(fin, s->start, 0); 19 while (Bseek(fin, 0L, 1) < s->end && (buf=Brdline(fin, '\n')) != NULL){ 20 /* 21 * We have to be careful here, because % can legitimately appear 22 * in Ascii85 encodings, and must not be elided. 23 * The goal here is to make any DSC comments impotent without 24 * actually changing the behavior of the Postscript. 25 * Since stripping ``comments'' breaks Ascii85, we can instead just 26 * indent comments a space, which turns DSC comments into non-DSC comments 27 * and has no effect on binary encodings, which are whitespace-blind. 28 */ 29 if(buf[0] == '%') 30 Bputc(fout, ' '); 31 Bwrite(fout, buf, Blinelen(fin)); 32 } 33 } 34 35 /* 36 * Reads a PostScript file (*fin), and uses structuring comments to locate the 37 * prologue, trailer, global definitions, and the requested page. After the whole 38 * file is scanned, the special ps_include PostScript definitions are copied to 39 * *fout, followed by the prologue, global definitions, the requested page, and 40 * the trailer. Before returning the initial environment (saved in PS_head) is 41 * restored. 42 * 43 * By default we assume the picture is 8.5 by 11 inches, but the BoundingBox 44 * comment, if found, takes precedence. 45 */ 46 /* *fin, *fout; /* input and output files */ 47 /* page_no; /* physical page number from *fin */ 48 /* whiteout; /* erase picture area */ 49 /* outline; /* draw a box around it and */ 50 /* scaleboth; /* scale both dimensions - if not zero */ 51 /* cx, cy; /* center of the picture and */ 52 /* sx, sy; /* its size - in current coordinates */ 53 /* ax, ay; /* left-right, up-down adjustment */ 54 /* rot; /* rotation - in clockwise degrees */ 55 56 void 57 ps_include(Biobufhdr *fin, Biobufhdr *fout, int page_no, int whiteout, 58 int outline, int scaleboth, double cx, double cy, double sx, double sy, 59 double ax, double ay, double rot) { 60 int foundpage = 0; /* found the page when non zero */ 61 int foundpbox = 0; /* found the page bounding box */ 62 int i; 63 int maxglobal = 0; /* the number we've got room for */ 64 int nglobal = 0; /* number of global defs so far */ 65 char **strp; 66 double llx, lly; /* lower left and */ 67 double o = outline != 0; 68 double s = scaleboth != 0; 69 double urx, ury; /* upper right corners - default coords */ 70 double w = whiteout != 0; /* mostly for the var() macro */ 71 Section *global; /* offsets for all global definitions */ 72 Section prolog, page, trailer; /* prologue, page, and trailer offsets */ 73 74 #define has(word) (strncmp(buf, word, strlen(word)) == 0) 75 #define grab(n) ((Section *)(nglobal \ 76 ? realloc((char *)global, n*sizeof(Section)) \ 77 : calloc(n, sizeof(Section)))) 78 global = nil; 79 llx = lly = 0; /* default BoundingBox - 8.5x11 inches */ 80 urx = 72 * 8.5; 81 ury = 72 * 11.0; 82 83 /* section boundaries and bounding box */ 84 85 prolog.start = prolog.end = 0; 86 page.start = page.end = 0; 87 trailer.start = 0; 88 Bseek(fin, 0L, 0); 89 90 while ((buf=Brdline(fin, '\n')) != NULL) { 91 buf[Blinelen(fin)-1] = '\0'; 92 if (!has("%%")) 93 continue; 94 else if (has("%%Page: ")) { 95 if (!foundpage) 96 page.start = Bseek(fin, 0L, 1); 97 sscanf(buf, "%*s %*s %d", &i); 98 if (i == page_no) 99 foundpage = 1; 100 else if (foundpage && page.end <= page.start) 101 page.end = Bseek(fin, 0L, 1); 102 } else if (has("%%EndPage: ")) { 103 sscanf(buf, "%*s %*s %d", &i); 104 if (i == page_no) { 105 foundpage = 1; 106 page.end = Bseek(fin, 0L, 1); 107 } 108 if (!foundpage) 109 page.start = Bseek(fin, 0L, 1); 110 } else if (has("%%PageBoundingBox: ")) { 111 if (i == page_no) { 112 foundpbox = 1; 113 sscanf(buf, "%*s %lf %lf %lf %lf", 114 &llx, &lly, &urx, &ury); 115 } 116 } else if (has("%%BoundingBox: ")) { 117 if (!foundpbox) 118 sscanf(buf,"%*s %lf %lf %lf %lf", 119 &llx, &lly, &urx, &ury); 120 } else if (has("%%EndProlog") || has("%%EndSetup") || has("%%EndDocumentSetup")) 121 prolog.end = page.start = Bseek(fin, 0L, 1); 122 else if (has("%%Trailer")) 123 trailer.start = Bseek(fin, 0L, 1); 124 else if (has("%%BeginGlobal")) { 125 if (page.end <= page.start) { 126 if (nglobal >= maxglobal) { 127 maxglobal += 20; 128 global = grab(maxglobal); 129 } 130 global[nglobal].start = Bseek(fin, 0L, 1); 131 } 132 } else if (has("%%EndGlobal")) 133 if (page.end <= page.start) 134 global[nglobal++].end = Bseek(fin, 0L, 1); 135 } 136 Bseek(fin, 0L, 2); 137 if (trailer.start == 0) 138 trailer.start = Bseek(fin, 0L, 1); 139 trailer.end = Bseek(fin, 0L, 1); 140 141 if (page.end <= page.start) 142 page.end = trailer.start; 143 144 /* 145 fprint(2, "prolog=(%d,%d)\n", prolog.start, prolog.end); 146 fprint(2, "page=(%d,%d)\n", page.start, page.end); 147 for(i = 0; i < nglobal; i++) 148 fprint(2, "global[%d]=(%d,%d)\n", i, global[i].start, global[i].end); 149 fprint(2, "trailer=(%d,%d)\n", trailer.start, trailer.end); 150 */ 151 152 /* all output here */ 153 for (strp = PS_head; *strp != NULL; strp++) 154 Bwrite(fout, *strp, strlen(*strp)); 155 156 Bprint(fout, "/llx %g def\n", llx); 157 Bprint(fout, "/lly %g def\n", lly); 158 Bprint(fout, "/urx %g def\n", urx); 159 Bprint(fout, "/ury %g def\n", ury); 160 Bprint(fout, "/w %g def\n", w); 161 Bprint(fout, "/o %g def\n", o); 162 Bprint(fout, "/s %g def\n", s); 163 Bprint(fout, "/cx %g def\n", cx); 164 Bprint(fout, "/cy %g def\n", cy); 165 Bprint(fout, "/sx %g def\n", sx); 166 Bprint(fout, "/sy %g def\n", sy); 167 Bprint(fout, "/ax %g def\n", ax); 168 Bprint(fout, "/ay %g def\n", ay); 169 Bprint(fout, "/rot %g def\n", rot); 170 171 for (strp = PS_setup; *strp != NULL; strp++) 172 Bwrite(fout, *strp, strlen(*strp)); 173 174 copy(fin, fout, &prolog); 175 for(i = 0; i < nglobal; i++) 176 copy(fin, fout, &global[i]); 177 copy(fin, fout, &page); 178 copy(fin, fout, &trailer); 179 for (strp = PS_tail; *strp != NULL; strp++) 180 Bwrite(fout, *strp, strlen(*strp)); 181 182 if(nglobal) 183 free(global); 184 185 /* force the program to reestablish its state */ 186 curpostfontid = -1; 187 curfontsize = -1; 188 } 189