Commit | Line | Data |
---|---|---|
1530e5b9 WJ |
1 | /* Copyright (C) 1989, 1991 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
19 | ||
20 | /* zmatrix.c */ | |
21 | /* Matrix operators for Ghostscript */ | |
22 | #include "ghost.h" | |
23 | #include "errors.h" | |
24 | #include "oper.h" | |
25 | #include "gsmatrix.h" | |
26 | #include "state.h" | |
27 | #include "gscoord.h" | |
28 | #include "store.h" | |
29 | ||
30 | /* Forward references */ | |
31 | private int near common_transform(P3(os_ptr, | |
32 | int (*)(P4(gs_state *, floatp, floatp, gs_point *)), | |
33 | int (*)(P4(floatp, floatp, const gs_matrix *, gs_point *)))); | |
34 | ||
35 | /* Initialize the type and attributes of the identity matrix. */ | |
36 | /* We may have to do this after each save and restore, */ | |
37 | /* in order to get the l_new attribute correct. */ | |
38 | void | |
39 | init_identity_matrix() | |
40 | { extern gs_matrix gs_identity_matrix; | |
41 | ref *mp = (ref *)&gs_identity_matrix; | |
42 | int attrs = alloc_save_new_mask; | |
43 | int i; | |
44 | for ( i = 0; i < 6; i++, mp++ ) | |
45 | r_set_type_attrs(mp, t_real, attrs); | |
46 | } | |
47 | ||
48 | /* currentmatrix */ | |
49 | int | |
50 | zcurrentmatrix(register os_ptr op) | |
51 | { int code = write_matrix(op); | |
52 | if ( code < 0 ) return code; | |
53 | gs_currentmatrix(igs, (gs_matrix *)(op->value.refs)); | |
54 | return 0; | |
55 | } | |
56 | ||
57 | /* setmatrix */ | |
58 | int | |
59 | zsetmatrix(register os_ptr op) | |
60 | { gs_matrix mat; | |
61 | int code = read_matrix(op, &mat); | |
62 | if ( code < 0 ) return code; | |
63 | if ( (code = gs_setmatrix(igs, &mat)) < 0 ) return code; | |
64 | pop(1); | |
65 | return 0; | |
66 | } | |
67 | ||
68 | /* translate */ | |
69 | int | |
70 | ztranslate(register os_ptr op) | |
71 | { int code = write_matrix(op); | |
72 | float trans[2]; | |
73 | if ( code < 0 ) /* no matrix operand */ | |
74 | { if ( (code = num_params(op, 2, trans)) < 0 ) return code; | |
75 | code = gs_translate(igs, trans[0], trans[1]); | |
76 | } | |
77 | else /* matrix operand */ | |
78 | { gs_matrix *pmat = (gs_matrix *)op->value.refs; | |
79 | if ( (code = num_params(op - 1, 2, trans)) < 0 ) return code; | |
80 | code = gs_make_translation(trans[0], trans[1], pmat); | |
81 | op[-2] = *op; | |
82 | } | |
83 | if ( code >= 0 ) pop(2); | |
84 | return code; | |
85 | } | |
86 | ||
87 | /* scale */ | |
88 | int | |
89 | zscale(register os_ptr op) | |
90 | { float scale[2]; | |
91 | int code = write_matrix(op); | |
92 | if ( code < 0 ) /* no matrix operand */ | |
93 | { if ( (code = num_params(op, 2, scale)) < 0 ) return code; | |
94 | code = gs_scale(igs, scale[0], scale[1]); | |
95 | } | |
96 | else /* matrix operand */ | |
97 | { gs_matrix *pmat = (gs_matrix *)op->value.refs; | |
98 | if ( (code = num_params(op - 1, 2, scale)) < 0 ) return code; | |
99 | code = gs_make_scaling(scale[0], scale[1], pmat); | |
100 | op[-2] = *op; | |
101 | } | |
102 | if ( code >= 0 ) pop(2); | |
103 | return code; | |
104 | } | |
105 | ||
106 | /* rotate */ | |
107 | int | |
108 | zrotate(register os_ptr op) | |
109 | { int code = write_matrix(op); | |
110 | float ang; | |
111 | if ( code < 0 ) /* no matrix operand */ | |
112 | { if ( (code = num_params(op, 1, &ang)) < 0 ) return code; | |
113 | code = gs_rotate(igs, ang); | |
114 | } | |
115 | else /* matrix operand */ | |
116 | { gs_matrix *pmat = (gs_matrix *)op->value.refs; | |
117 | if ( (code = num_params(op - 1, 1, &ang)) < 0 ) return code; | |
118 | code = gs_make_rotation(ang, pmat); | |
119 | op[-1] = *op; | |
120 | } | |
121 | if ( code >= 0 ) pop(1); | |
122 | return code; | |
123 | } | |
124 | ||
125 | /* concat */ | |
126 | int | |
127 | zconcat(register os_ptr op) | |
128 | { gs_matrix mat; | |
129 | int code = read_matrix(op, &mat); | |
130 | if ( code < 0 ) return code; | |
131 | code = gs_concat(igs, &mat); | |
132 | if ( code < 0 ) return code; | |
133 | pop(1); | |
134 | return 0; | |
135 | } | |
136 | ||
137 | /* concatmatrix */ | |
138 | int | |
139 | zconcatmatrix(register os_ptr op) | |
140 | { gs_matrix m1, m2; | |
141 | int code; | |
142 | if ( (code = read_matrix(op - 2, &m1)) < 0 || | |
143 | (code = read_matrix(op - 1, &m2)) < 0 || | |
144 | (code = write_matrix(op)) < 0 || | |
145 | (code = gs_matrix_multiply(&m1, &m2, (gs_matrix *)(op->value.refs))) < 0 | |
146 | ) return code; | |
147 | op[-2] = *op; | |
148 | pop(2); | |
149 | return code; | |
150 | } | |
151 | ||
152 | /* transform */ | |
153 | int | |
154 | ztransform(register os_ptr op) | |
155 | { return common_transform(op, gs_transform, gs_point_transform); | |
156 | } | |
157 | ||
158 | /* dtransform */ | |
159 | int | |
160 | zdtransform(register os_ptr op) | |
161 | { return common_transform(op, gs_dtransform, gs_distance_transform); | |
162 | } | |
163 | ||
164 | /* itransform */ | |
165 | int | |
166 | zitransform(register os_ptr op) | |
167 | { return common_transform(op, gs_itransform, gs_point_transform_inverse); | |
168 | } | |
169 | ||
170 | /* idtransform */ | |
171 | int | |
172 | zidtransform(register os_ptr op) | |
173 | { return common_transform(op, gs_idtransform, gs_distance_transform_inverse); | |
174 | } | |
175 | ||
176 | /* Common logic for [i][d]transform */ | |
177 | private int near | |
178 | common_transform(register os_ptr op, | |
179 | int (*ptproc)(P4(gs_state *, floatp, floatp, gs_point *)), | |
180 | int (*matproc)(P4(floatp, floatp, const gs_matrix *, gs_point *))) | |
181 | { float opxy[2]; | |
182 | gs_point pt; | |
183 | int code; | |
184 | /* Optimize for the non-matrix case */ | |
185 | switch ( r_type(op) ) | |
186 | { | |
187 | case t_real: opxy[1] = op->value.realval; break; | |
188 | case t_integer: opxy[1] = op->value.intval; break; | |
189 | case t_array: /* might be a matrix */ | |
190 | { gs_matrix mat; | |
191 | gs_matrix *pmat = &mat; | |
192 | if ( (code = read_matrix(op, pmat)) < 0 || | |
193 | (code = num_params(op - 1, 2, opxy)) < 0 || | |
194 | (code = (*matproc)(opxy[0], opxy[1], pmat, &pt)) < 0 | |
195 | ) return code; | |
196 | op--; | |
197 | pop(1); | |
198 | goto out; | |
199 | } | |
200 | default: return e_typecheck; | |
201 | } | |
202 | switch ( r_type(op - 1) ) | |
203 | { | |
204 | case t_real: opxy[0] = (op - 1)->value.realval; break; | |
205 | case t_integer: opxy[0] = (op - 1)->value.intval; break; | |
206 | default: return e_typecheck; | |
207 | } | |
208 | if ( (code = (*ptproc)(igs, opxy[0], opxy[1], &pt)) < 0 ) | |
209 | return code; | |
210 | out: make_real(op - 1, pt.x); | |
211 | make_real(op, pt.y); | |
212 | return 0; | |
213 | } | |
214 | ||
215 | /* invertmatrix */ | |
216 | int | |
217 | zinvertmatrix(register os_ptr op) | |
218 | { gs_matrix m; | |
219 | int code; | |
220 | if ( (code = read_matrix(op - 1, &m)) < 0 || | |
221 | (code = write_matrix(op)) < 0 || | |
222 | (code = gs_matrix_invert(&m, (gs_matrix *)op->value.refs)) < 0 | |
223 | ) return code; | |
224 | op[-1] = *op; | |
225 | pop(1); | |
226 | return code; | |
227 | } | |
228 | ||
229 | /* ------ Initialization procedure ------ */ | |
230 | ||
231 | op_def zmatrix_op_defs[] = { | |
232 | {"1concat", zconcat}, | |
233 | {"2dtransform", zdtransform}, | |
234 | {"3concatmatrix", zconcatmatrix}, | |
235 | {"1currentmatrix", zcurrentmatrix}, | |
236 | {"2idtransform", zidtransform}, | |
237 | {"2invertmatrix", zinvertmatrix}, | |
238 | {"2itransform", zitransform}, | |
239 | {"1rotate", zrotate}, | |
240 | {"2scale", zscale}, | |
241 | {"1setmatrix", zsetmatrix}, | |
242 | {"2transform", ztransform}, | |
243 | {"2translate", ztranslate}, | |
244 | op_def_end(init_identity_matrix) | |
245 | }; |