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