/src/ghostpdl/psi/zmatrix.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2023 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Matrix operators */ |
18 | | #include "ghost.h" |
19 | | #include "oper.h" |
20 | | #include "igstate.h" |
21 | | #include "gsmatrix.h" |
22 | | #include "gscoord.h" |
23 | | #include "store.h" |
24 | | |
25 | | /* Forward references */ |
26 | | static int common_transform(i_ctx_t *, |
27 | | int (*)(gs_gstate *, double, double, gs_point *), |
28 | | int (*)(double, double, const gs_matrix *, gs_point *)); |
29 | | |
30 | | /* - initmatrix - */ |
31 | | static int |
32 | | zinitmatrix(i_ctx_t *i_ctx_p) |
33 | 766k | { |
34 | 766k | return gs_initmatrix(igs); |
35 | 766k | } |
36 | | |
37 | | /* <matrix> defaultmatrix <matrix> */ |
38 | | static int |
39 | | zdefaultmatrix(i_ctx_t *i_ctx_p) |
40 | 567k | { |
41 | 567k | os_ptr op = osp; |
42 | 567k | gs_matrix mat; |
43 | | |
44 | 567k | check_op(1); |
45 | 567k | gs_defaultmatrix(igs, &mat); |
46 | 567k | return write_matrix(op, &mat); |
47 | 567k | } |
48 | | |
49 | | /* - .currentmatrix <xx> <xy> <yx> <yy> <tx> <ty> */ |
50 | | static int |
51 | | zcurrentmatrix(i_ctx_t *i_ctx_p) |
52 | 852k | { |
53 | 852k | os_ptr op = osp; |
54 | 852k | gs_matrix mat; |
55 | 852k | int code = gs_currentmatrix(igs, &mat); |
56 | | |
57 | 852k | if (code < 0) |
58 | 0 | return code; |
59 | 852k | push(6); |
60 | 852k | code = make_floats(op - 5, &mat.xx, 6); |
61 | 852k | if (code < 0) |
62 | 0 | pop(6); |
63 | 852k | return code; |
64 | 852k | } |
65 | | |
66 | | /* <xx> <xy> <yx> <yy> <tx> <ty> .setmatrix - */ |
67 | | static int |
68 | | zsetmatrix(i_ctx_t *i_ctx_p) |
69 | 85.0k | { |
70 | 85.0k | os_ptr op = osp; |
71 | 85.0k | gs_matrix mat; |
72 | 85.0k | int code; |
73 | | |
74 | 85.0k | check_op(6); |
75 | 85.0k | code = float_params(op, 6, &mat.xx); |
76 | | |
77 | 85.0k | if (code < 0) |
78 | 0 | return code; |
79 | 85.0k | if ((code = gs_setmatrix(igs, &mat)) < 0) |
80 | 0 | return code; |
81 | 85.0k | pop(6); |
82 | 85.0k | return 0; |
83 | 85.0k | } |
84 | | |
85 | | /* <matrix|null> .setdefaultmatrix - */ |
86 | | static int |
87 | | zsetdefaultmatrix(i_ctx_t *i_ctx_p) |
88 | 766k | { |
89 | 766k | os_ptr op = osp; |
90 | 766k | int code; |
91 | | |
92 | 766k | check_op(1); |
93 | 766k | if (r_has_type(op, t_null)) |
94 | 0 | code = gs_setdefaultmatrix(igs, NULL); |
95 | 766k | else { |
96 | 766k | gs_matrix mat; |
97 | | |
98 | 766k | code = read_matrix(imemory, op, &mat); |
99 | 766k | if (code < 0) |
100 | 0 | return code; |
101 | 766k | code = gs_setdefaultmatrix(igs, &mat); |
102 | 766k | } |
103 | 766k | if (code < 0) |
104 | 0 | return code; |
105 | 766k | pop(1); |
106 | 766k | return 0; |
107 | 766k | } |
108 | | |
109 | | /* <tx> <ty> translate - */ |
110 | | /* <tx> <ty> <matrix> translate <matrix> */ |
111 | | static int |
112 | | ztranslate(i_ctx_t *i_ctx_p) |
113 | 4.17M | { |
114 | 4.17M | os_ptr op = osp; |
115 | 4.17M | int code; |
116 | 4.17M | double trans[2]; |
117 | | |
118 | 4.17M | if ((code = num_params(op, 2, trans)) >= 0) { |
119 | 4.17M | code = gs_translate(igs, trans[0], trans[1]); |
120 | 4.17M | if (code < 0) |
121 | 0 | return code; |
122 | 4.17M | } else { /* matrix operand */ |
123 | 802 | gs_matrix mat; |
124 | | |
125 | | /* The num_params failure might be a stack underflow. */ |
126 | 802 | check_op(2); |
127 | 779 | if ((code = num_params(op - 1, 2, trans)) < 0 || |
128 | 779 | (code = gs_make_translation(trans[0], trans[1], &mat)) < 0 || |
129 | 779 | (code = write_matrix(op, &mat)) < 0 |
130 | 779 | ) { /* Might be a stack underflow. */ |
131 | 26 | check_op(3); |
132 | 15 | return code; |
133 | 26 | } |
134 | 753 | op[-2] = *op; |
135 | 753 | } |
136 | 4.17M | pop(2); |
137 | 4.17M | return code; |
138 | 4.17M | } |
139 | | |
140 | | /* <sx> <sy> scale - */ |
141 | | /* <sx> <sy> <matrix> scale <matrix> */ |
142 | | static int |
143 | | zscale(i_ctx_t *i_ctx_p) |
144 | 15.5k | { |
145 | 15.5k | os_ptr op = osp; |
146 | 15.5k | int code; |
147 | 15.5k | double scale[2]; |
148 | | |
149 | 15.5k | if ((code = num_params(op, 2, scale)) >= 0) { |
150 | 15.3k | code = gs_scale(igs, scale[0], scale[1]); |
151 | 15.3k | if (code < 0) |
152 | 0 | return code; |
153 | 15.3k | } else { /* matrix operand */ |
154 | 209 | gs_matrix mat; |
155 | | |
156 | | /* The num_params failure might be a stack underflow. */ |
157 | 209 | check_op(2); |
158 | 194 | if ((code = num_params(op - 1, 2, scale)) < 0 || |
159 | 194 | (code = gs_make_scaling(scale[0], scale[1], &mat)) < 0 || |
160 | 194 | (code = write_matrix(op, &mat)) < 0 |
161 | 194 | ) { /* Might be a stack underflow. */ |
162 | 46 | check_op(3); |
163 | 27 | return code; |
164 | 46 | } |
165 | 148 | op[-2] = *op; |
166 | 148 | } |
167 | 15.5k | pop(2); |
168 | 15.5k | return code; |
169 | 15.5k | } |
170 | | |
171 | | /* <angle> rotate - */ |
172 | | /* <angle> <matrix> rotate <matrix> */ |
173 | | static int |
174 | | zrotate(i_ctx_t *i_ctx_p) |
175 | 2.79M | { |
176 | 2.79M | os_ptr op = osp; |
177 | 2.79M | int code; |
178 | 2.79M | double ang; |
179 | | |
180 | 2.79M | if ((code = real_param(op, &ang)) >= 0) { |
181 | 2.79M | code = gs_rotate(igs, ang); |
182 | 2.79M | if (code < 0) |
183 | 0 | return code; |
184 | 2.79M | } else { /* matrix operand */ |
185 | 3.20k | gs_matrix mat; |
186 | | |
187 | | /* The num_params failure might be a stack underflow. */ |
188 | 3.20k | check_op(1); |
189 | 3.18k | if ((code = num_params(op - 1, 1, &ang)) < 0 || |
190 | 3.18k | (code = gs_make_rotation(ang, &mat)) < 0 || |
191 | 3.18k | (code = write_matrix(op, &mat)) < 0 |
192 | 3.18k | ) { /* Might be a stack underflow. */ |
193 | 44 | check_op(2); |
194 | 31 | return code; |
195 | 44 | } |
196 | 3.14k | op[-1] = *op; |
197 | 3.14k | } |
198 | 2.79M | pop(1); |
199 | 2.79M | return code; |
200 | 2.79M | } |
201 | | |
202 | | /* <matrix> concat - */ |
203 | | static int |
204 | | zconcat(i_ctx_t *i_ctx_p) |
205 | 851k | { |
206 | 851k | os_ptr op = osp; |
207 | 851k | gs_matrix mat; |
208 | 851k | int code; |
209 | | |
210 | 851k | check_op(1); |
211 | 851k | code = read_matrix(imemory, op, &mat); |
212 | | |
213 | 851k | if (code < 0) |
214 | 12 | return code; |
215 | 851k | code = gs_concat(igs, &mat); |
216 | 851k | if (code < 0) |
217 | 0 | return code; |
218 | 851k | pop(1); |
219 | 851k | return 0; |
220 | 851k | } |
221 | | |
222 | | /* <matrix1> <matrix2> <matrix> concatmatrix <matrix> */ |
223 | | static int |
224 | | zconcatmatrix(i_ctx_t *i_ctx_p) |
225 | 9.68k | { |
226 | 9.68k | os_ptr op = osp; |
227 | 9.68k | gs_matrix m1, m2, mp; |
228 | 9.68k | int code; |
229 | | |
230 | 9.68k | check_op(3); |
231 | 9.67k | if ((code = read_matrix(imemory, op - 2, &m1)) < 0 || |
232 | 9.67k | (code = read_matrix(imemory, op - 1, &m2)) < 0 || |
233 | 9.67k | (code = gs_matrix_multiply(&m1, &m2, &mp)) < 0 || |
234 | 9.67k | (code = write_matrix(op, &mp)) < 0 |
235 | 9.67k | ) |
236 | 3 | return code; |
237 | 9.67k | op[-2] = *op; |
238 | 9.67k | pop(2); |
239 | 9.67k | return code; |
240 | 9.67k | } |
241 | | |
242 | | /* <x> <y> transform <xt> <yt> */ |
243 | | /* <x> <y> <matrix> transform <xt> <yt> */ |
244 | | static int |
245 | | ztransform(i_ctx_t *i_ctx_p) |
246 | 920k | { |
247 | 920k | return common_transform(i_ctx_p, gs_transform, gs_point_transform); |
248 | 920k | } |
249 | | |
250 | | /* <dx> <dy> dtransform <dxt> <dyt> */ |
251 | | /* <dx> <dy> <matrix> dtransform <dxt> <dyt> */ |
252 | | static int |
253 | | zdtransform(i_ctx_t *i_ctx_p) |
254 | 734k | { |
255 | 734k | return common_transform(i_ctx_p, gs_dtransform, gs_distance_transform); |
256 | 734k | } |
257 | | |
258 | | /* <xt> <yt> itransform <x> <y> */ |
259 | | /* <xt> <yt> <matrix> itransform <x> <y> */ |
260 | | static int |
261 | | zitransform(i_ctx_t *i_ctx_p) |
262 | 76 | { |
263 | 76 | return common_transform(i_ctx_p, gs_itransform, gs_point_transform_inverse); |
264 | 76 | } |
265 | | |
266 | | /* <dxt> <dyt> idtransform <dx> <dy> */ |
267 | | /* <dxt> <dyt> <matrix> idtransform <dx> <dy> */ |
268 | | static int |
269 | | zidtransform(i_ctx_t *i_ctx_p) |
270 | 766k | { |
271 | 766k | return common_transform(i_ctx_p, gs_idtransform, gs_distance_transform_inverse); |
272 | 766k | } |
273 | | |
274 | | /* Common logic for [i][d]transform */ |
275 | | static int |
276 | | common_transform(i_ctx_t *i_ctx_p, |
277 | | int (*ptproc)(gs_gstate *, double, double, gs_point *), |
278 | | int (*matproc)(double, double, const gs_matrix *, gs_point *)) |
279 | 2.42M | { |
280 | 2.42M | os_ptr op = osp; |
281 | 2.42M | double opxy[2]; |
282 | 2.42M | gs_point pt; |
283 | 2.42M | int code; |
284 | | |
285 | | /* Optimize for the non-matrix case */ |
286 | 2.42M | switch (r_type(op)) { |
287 | 766k | case t_real: |
288 | 766k | opxy[1] = op->value.realval; |
289 | 766k | break; |
290 | 160k | case t_integer: |
291 | 160k | opxy[1] = (double)op->value.intval; |
292 | 160k | break; |
293 | 1.49M | case t_array: /* might be a matrix */ |
294 | 1.49M | case t_shortarray: |
295 | 1.49M | case t_mixedarray: { |
296 | 1.49M | gs_matrix mat; |
297 | 1.49M | gs_matrix *pmat = &mat; |
298 | | |
299 | 1.49M | if ((code = read_matrix(imemory, op, pmat)) < 0 || |
300 | 1.49M | (code = num_params(op - 1, 2, opxy)) < 0 || |
301 | 1.49M | (code = (*matproc) (opxy[0], opxy[1], pmat, &pt)) < 0 |
302 | 1.49M | ) { /* Might be a stack underflow. */ |
303 | 16 | check_op(3); |
304 | 7 | return code; |
305 | 16 | } |
306 | 1.49M | op--; |
307 | 1.49M | pop(1); |
308 | 1.49M | goto out; |
309 | 1.49M | } |
310 | 63 | default: |
311 | 63 | return_op_typecheck(op); |
312 | 2.42M | } |
313 | 927k | switch (r_type(op - 1)) { |
314 | 766k | case t_real: |
315 | 766k | opxy[0] = (op - 1)->value.realval; |
316 | 766k | break; |
317 | 160k | case t_integer: |
318 | 160k | opxy[0] = (double)(op - 1)->value.intval; |
319 | 160k | break; |
320 | 61 | default: |
321 | 61 | return_op_typecheck(op - 1); |
322 | 927k | } |
323 | 927k | if ((code = (*ptproc) (igs, opxy[0], opxy[1], &pt)) < 0) |
324 | 0 | return code; |
325 | 2.42M | out: |
326 | 2.42M | make_real(op - 1, pt.x); |
327 | 2.42M | make_real(op, pt.y); |
328 | 2.42M | return 0; |
329 | 927k | } |
330 | | |
331 | | /* <matrix> <inv_matrix> invertmatrix <inv_matrix> */ |
332 | | static int |
333 | | zinvertmatrix(i_ctx_t *i_ctx_p) |
334 | 25 | { |
335 | 25 | os_ptr op = osp; |
336 | 25 | gs_matrix m; |
337 | 25 | int code; |
338 | | |
339 | 25 | check_op(2); |
340 | 15 | if ((code = read_matrix(imemory, op - 1, &m)) < 0 || |
341 | 15 | (code = gs_matrix_invert(&m, &m)) < 0 || |
342 | 15 | (code = write_matrix(op, &m)) < 0 |
343 | 15 | ) |
344 | 15 | return code; |
345 | 0 | op[-1] = *op; |
346 | 0 | pop(1); |
347 | 0 | return code; |
348 | 15 | } |
349 | | |
350 | | static int |
351 | | zupdatematrices(i_ctx_t *i_ctx_p) |
352 | 2.14M | { |
353 | 2.14M | return gs_updatematrices(igs); |
354 | 2.14M | } |
355 | | |
356 | | /* ------ Initialization procedure ------ */ |
357 | | |
358 | | const op_def zmatrix_op_defs[] = |
359 | | { |
360 | | {"1concat", zconcat}, |
361 | | {"2dtransform", zdtransform}, |
362 | | {"3concatmatrix", zconcatmatrix}, |
363 | | {"0.currentmatrix", zcurrentmatrix}, |
364 | | {"1defaultmatrix", zdefaultmatrix}, |
365 | | {"2idtransform", zidtransform}, |
366 | | {"0initmatrix", zinitmatrix}, |
367 | | {"2invertmatrix", zinvertmatrix}, |
368 | | {"2itransform", zitransform}, |
369 | | {"1rotate", zrotate}, |
370 | | {"2scale", zscale}, |
371 | | {"6.setmatrix", zsetmatrix}, |
372 | | {"1.setdefaultmatrix", zsetdefaultmatrix}, |
373 | | {"2transform", ztransform}, |
374 | | {"2translate", ztranslate}, |
375 | | op_def_end(0) |
376 | | }; |
377 | | |
378 | | const op_def zmatrix2_op_defs[] = |
379 | | { |
380 | | {"1.updatematrices", zupdatematrices}, |
381 | | op_def_end(0) |
382 | | }; |