xref: /plan9-contrib/sys/src/cmd/postscript/common/bbox.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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