1 /* 2 * 3 * Boundingbox code for PostScript translators. The boundingbox for each page 4 * is accumulated in bbox - the one for the whole document goes in docbbox. A 5 * call to writebbox() puts out an appropriate comment, updates docbbox, and 6 * resets bbox for the next page. The assumption made at the end of writebbox() 7 * is that we're really printing the current page only if output is now going 8 * to stdout - a valid assumption for all supplied translators. Needs the math 9 * library. 10 * 11 */ 12 13 #include <stdio.h> 14 #include <ctype.h> 15 #include <sys/types.h> 16 #include <fcntl.h> 17 #include <math.h> 18 19 #include "comments.h" /* PostScript file structuring comments */ 20 #include "gen.h" /* a few general purpose definitions */ 21 #include "ext.h" /* external variable declarations */ 22 23 typedef struct bbox { 24 int set; 25 double llx, lly; 26 double urx, ury; 27 } Bbox; 28 29 Bbox bbox = {FALSE, 0.0, 0.0, 0.0, 0.0}; 30 Bbox docbbox = {FALSE, 0.0, 0.0, 0.0, 0.0}; 31 32 double ctm[6] = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0}; 33 double matrix1[6], matrix2[6]; 34 35 /*****************************************************************************/ 36 37 cover(x, y) 38 39 double x, y; 40 41 { 42 43 /* 44 * 45 * Adds point (x, y) to bbox. Coordinates are in user space - the transformation 46 * to default coordinates happens in writebbox(). 47 * 48 */ 49 50 if ( bbox.set == FALSE ) { 51 bbox.llx = bbox.urx = x; 52 bbox.lly = bbox.ury = y; 53 bbox.set = TRUE; 54 } else { 55 if ( x < bbox.llx ) 56 bbox.llx = x; 57 if ( y < bbox.lly ) 58 bbox.lly = y; 59 if ( x > bbox.urx ) 60 bbox.urx = x; 61 if ( y > bbox.ury ) 62 bbox.ury = y; 63 } /* End else */ 64 65 } /* End of cover */ 66 67 /*****************************************************************************/ 68 69 writebbox(fp, keyword, slop) 70 71 FILE *fp; /* the comment is written here */ 72 char *keyword; /* the boundingbox comment string */ 73 int slop; /* expand (or contract?) the box a bit */ 74 75 { 76 77 Bbox ubbox; /* user space bounding box */ 78 double x, y; 79 80 /* 81 * 82 * Transforms the numbers in the bbox[] using ctm[], adjusts the corners a bit 83 * (depending on slop) and then writes comment. If *keyword is BoundingBox use 84 * whatever's been saved in docbbox, otherwise assume the comment is just for 85 * the current page. 86 * 87 */ 88 89 if ( strcmp(keyword, BOUNDINGBOX) == 0 ) 90 bbox = docbbox; 91 92 if ( bbox.set == TRUE ) { 93 ubbox = bbox; 94 bbox.set = FALSE; /* so cover() works properly */ 95 x = ctm[0] * ubbox.llx + ctm[2] * ubbox.lly + ctm[4]; 96 y = ctm[1] * ubbox.llx + ctm[3] * ubbox.lly + ctm[5]; 97 cover(x, y); 98 x = ctm[0] * ubbox.llx + ctm[2] * ubbox.ury + ctm[4]; 99 y = ctm[1] * ubbox.llx + ctm[3] * ubbox.ury + ctm[5]; 100 cover(x, y); 101 x = ctm[0] * ubbox.urx + ctm[2] * ubbox.ury + ctm[4]; 102 y = ctm[1] * ubbox.urx + ctm[3] * ubbox.ury + ctm[5]; 103 cover(x, y); 104 x = ctm[0] * ubbox.urx + ctm[2] * ubbox.lly + ctm[4]; 105 y = ctm[1] * ubbox.urx + ctm[3] * ubbox.lly + ctm[5]; 106 cover(x, y); 107 bbox.llx -= slop + 0.5; 108 bbox.lly -= slop + 0.5; 109 bbox.urx += slop + 0.5; 110 bbox.ury += slop + 0.5; 111 fprintf(fp, "%s %d %d %d %d\n", keyword, (int)bbox.llx, (int)bbox.lly,(int)bbox.urx, (int)bbox.ury); 112 bbox = ubbox; 113 } /* End if */ 114 115 resetbbox((fp == stdout) ? TRUE : FALSE); 116 117 } /* End of writebbox */ 118 119 /*****************************************************************************/ 120 121 resetbbox(output) 122 123 int output; 124 125 { 126 127 /* 128 * 129 * Adds bbox to docbbox and resets bbox for the next page. Only update docbbox 130 * if we really did output on the last page. 131 * 132 */ 133 134 if ( docbbox.set == TRUE ) { 135 cover(docbbox.llx, docbbox.lly); 136 cover(docbbox.urx, docbbox.ury); 137 } /* End if */ 138 139 if ( output == TRUE ) { 140 docbbox = bbox; 141 docbbox.set = TRUE; 142 } /* End if */ 143 144 bbox.set = FALSE; 145 146 } /* End of resetbbox */ 147 148 /*****************************************************************************/ 149 150 scale(sx, sy) 151 152 double sx, sy; 153 154 { 155 156 /* 157 * 158 * Scales the default matrix. 159 * 160 */ 161 162 matrix1[0] = sx; 163 matrix1[1] = 0; 164 matrix1[2] = 0; 165 matrix1[3] = sy; 166 matrix1[4] = 0; 167 matrix1[5] = 0; 168 169 concat(matrix1); 170 171 } /* End of scale */ 172 173 /*****************************************************************************/ 174 175 translate(tx, ty) 176 177 double tx, ty; 178 179 { 180 181 /* 182 * 183 * Translates the default matrix. 184 * 185 */ 186 187 matrix1[0] = 1.0; 188 matrix1[1] = 0.0; 189 matrix1[2] = 0.0; 190 matrix1[3] = 1.0; 191 matrix1[4] = tx; 192 matrix1[5] = ty; 193 194 concat(matrix1); 195 196 } /* End of translate */ 197 198 /*****************************************************************************/ 199 200 rotate(angle) 201 202 double angle; 203 204 { 205 206 /* 207 * 208 * Rotates by angle degrees. 209 * 210 */ 211 212 angle *= 3.1416 / 180; 213 214 matrix1[0] = matrix1[3] = cos(angle); 215 matrix1[1] = sin(angle); 216 matrix1[2] = -matrix1[1]; 217 matrix1[4] = 0.0; 218 matrix1[5] = 0.0; 219 220 concat(matrix1); 221 222 } /* End of rotate */ 223 224 /*****************************************************************************/ 225 226 concat(m1) 227 228 double m1[]; 229 230 { 231 232 double m2[6]; 233 234 /* 235 * 236 * Replaces the ctm[] by the result of the matrix multiplication m1[] x ctm[]. 237 * 238 */ 239 240 m2[0] = ctm[0]; 241 m2[1] = ctm[1]; 242 m2[2] = ctm[2]; 243 m2[3] = ctm[3]; 244 m2[4] = ctm[4]; 245 m2[5] = ctm[5]; 246 247 ctm[0] = m1[0] * m2[0] + m1[1] * m2[2]; 248 ctm[1] = m1[0] * m2[1] + m1[1] * m2[3]; 249 ctm[2] = m1[2] * m2[0] + m1[3] * m2[2]; 250 ctm[3] = m1[2] * m2[1] + m1[3] * m2[3]; 251 ctm[4] = m1[4] * m2[0] + m1[5] * m2[2] + m2[4]; 252 ctm[5] = m1[4] * m2[1] + m1[5] * m2[3] + m2[5]; 253 254 } /* End of concat */ 255 256 /*****************************************************************************/ 257 258