Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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