Coverage Report

Created: 2025-06-10 07:24

/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
60.7k
{
34
60.7k
    return gs_initmatrix(igs);
35
60.7k
}
36
37
/* <matrix> defaultmatrix <matrix> */
38
static int
39
zdefaultmatrix(i_ctx_t *i_ctx_p)
40
9.78k
{
41
9.78k
    os_ptr op = osp;
42
9.78k
    gs_matrix mat;
43
44
9.78k
    check_op(1);
45
9.78k
    gs_defaultmatrix(igs, &mat);
46
9.78k
    return write_matrix(op, &mat);
47
9.78k
}
48
49
/* - .currentmatrix <xx> <xy> <yx> <yy> <tx> <ty> */
50
static int
51
zcurrentmatrix(i_ctx_t *i_ctx_p)
52
61.9k
{
53
61.9k
    os_ptr op = osp;
54
61.9k
    gs_matrix mat;
55
61.9k
    int code = gs_currentmatrix(igs, &mat);
56
57
61.9k
    if (code < 0)
58
0
        return code;
59
61.9k
    push(6);
60
61.9k
    code = make_floats(op - 5, &mat.xx, 6);
61
61.9k
    if (code < 0)
62
0
        pop(6);
63
61.9k
    return code;
64
61.9k
}
65
66
/* <xx> <xy> <yx> <yy> <tx> <ty> .setmatrix - */
67
static int
68
zsetmatrix(i_ctx_t *i_ctx_p)
69
1.30k
{
70
1.30k
    os_ptr op = osp;
71
1.30k
    gs_matrix mat;
72
1.30k
    int code;
73
74
1.30k
    check_op(6);
75
1.30k
    code = float_params(op, 6, &mat.xx);
76
77
1.30k
    if (code < 0)
78
0
        return code;
79
1.30k
    if ((code = gs_setmatrix(igs, &mat)) < 0)
80
0
        return code;
81
1.30k
    pop(6);
82
1.30k
    return 0;
83
1.30k
}
84
85
/* <matrix|null> .setdefaultmatrix - */
86
static int
87
zsetdefaultmatrix(i_ctx_t *i_ctx_p)
88
60.6k
{
89
60.6k
    os_ptr op = osp;
90
60.6k
    int code;
91
92
60.6k
    check_op(1);
93
60.6k
    if (r_has_type(op, t_null))
94
0
        code = gs_setdefaultmatrix(igs, NULL);
95
60.6k
    else {
96
60.6k
        gs_matrix mat;
97
98
60.6k
        code = read_matrix(imemory, op, &mat);
99
60.6k
        if (code < 0)
100
0
            return code;
101
60.6k
        code = gs_setdefaultmatrix(igs, &mat);
102
60.6k
    }
103
60.6k
    if (code < 0)
104
0
        return code;
105
60.6k
    pop(1);
106
60.6k
    return 0;
107
60.6k
}
108
109
/* <tx> <ty> translate - */
110
/* <tx> <ty> <matrix> translate <matrix> */
111
static int
112
ztranslate(i_ctx_t *i_ctx_p)
113
82.3k
{
114
82.3k
    os_ptr op = osp;
115
82.3k
    int code;
116
82.3k
    double trans[2];
117
118
82.3k
    if ((code = num_params(op, 2, trans)) >= 0) {
119
82.2k
        code = gs_translate(igs, trans[0], trans[1]);
120
82.2k
        if (code < 0)
121
0
            return code;
122
82.2k
    } else {     /* matrix operand */
123
83
        gs_matrix mat;
124
125
        /* The num_params failure might be a stack underflow. */
126
83
        check_op(2);
127
83
        if ((code = num_params(op - 1, 2, trans)) < 0 ||
128
83
            (code = gs_make_translation(trans[0], trans[1], &mat)) < 0 ||
129
83
            (code = write_matrix(op, &mat)) < 0
130
83
            ) {     /* Might be a stack underflow. */
131
1
            check_op(3);
132
0
            return code;
133
1
        }
134
82
        op[-2] = *op;
135
82
    }
136
82.3k
    pop(2);
137
82.3k
    return code;
138
82.3k
}
139
140
/* <sx> <sy> scale - */
141
/* <sx> <sy> <matrix> scale <matrix> */
142
static int
143
zscale(i_ctx_t *i_ctx_p)
144
1.39k
{
145
1.39k
    os_ptr op = osp;
146
1.39k
    int code;
147
1.39k
    double scale[2];
148
149
1.39k
    if ((code = num_params(op, 2, scale)) >= 0) {
150
1.37k
        code = gs_scale(igs, scale[0], scale[1]);
151
1.37k
        if (code < 0)
152
0
            return code;
153
1.37k
    } else {     /* matrix operand */
154
21
        gs_matrix mat;
155
156
        /* The num_params failure might be a stack underflow. */
157
21
        check_op(2);
158
20
        if ((code = num_params(op - 1, 2, scale)) < 0 ||
159
20
            (code = gs_make_scaling(scale[0], scale[1], &mat)) < 0 ||
160
20
            (code = write_matrix(op, &mat)) < 0
161
20
            ) {     /* Might be a stack underflow. */
162
2
            check_op(3);
163
1
            return code;
164
2
        }
165
18
        op[-2] = *op;
166
18
    }
167
1.39k
    pop(2);
168
1.39k
    return code;
169
1.39k
}
170
171
/* <angle> rotate - */
172
/* <angle> <matrix> rotate <matrix> */
173
static int
174
zrotate(i_ctx_t *i_ctx_p)
175
10.1k
{
176
10.1k
    os_ptr op = osp;
177
10.1k
    int code;
178
10.1k
    double ang;
179
180
10.1k
    if ((code = real_param(op, &ang)) >= 0) {
181
9.84k
        code = gs_rotate(igs, ang);
182
9.84k
        if (code < 0)
183
0
            return code;
184
9.84k
    } else {     /* matrix operand */
185
337
        gs_matrix mat;
186
187
        /* The num_params failure might be a stack underflow. */
188
337
        check_op(1);
189
336
        if ((code = num_params(op - 1, 1, &ang)) < 0 ||
190
336
            (code = gs_make_rotation(ang, &mat)) < 0 ||
191
336
            (code = write_matrix(op, &mat)) < 0
192
336
            ) {     /* Might be a stack underflow. */
193
3
            check_op(2);
194
3
            return code;
195
3
        }
196
333
        op[-1] = *op;
197
333
    }
198
10.1k
    pop(1);
199
10.1k
    return code;
200
10.1k
}
201
202
/* <matrix> concat - */
203
static int
204
zconcat(i_ctx_t *i_ctx_p)
205
61.9k
{
206
61.9k
    os_ptr op = osp;
207
61.9k
    gs_matrix mat;
208
61.9k
    int code;
209
210
61.9k
    check_op(1);
211
61.9k
    code = read_matrix(imemory, op, &mat);
212
213
61.9k
    if (code < 0)
214
1
        return code;
215
61.9k
    code = gs_concat(igs, &mat);
216
61.9k
    if (code < 0)
217
0
        return code;
218
61.9k
    pop(1);
219
61.9k
    return 0;
220
61.9k
}
221
222
/* <matrix1> <matrix2> <matrix> concatmatrix <matrix> */
223
static int
224
zconcatmatrix(i_ctx_t *i_ctx_p)
225
1.03k
{
226
1.03k
    os_ptr op = osp;
227
1.03k
    gs_matrix m1, m2, mp;
228
1.03k
    int code;
229
230
1.03k
    check_op(3);
231
1.03k
    if ((code = read_matrix(imemory, op - 2, &m1)) < 0 ||
232
1.03k
        (code = read_matrix(imemory, op - 1, &m2)) < 0 ||
233
1.03k
        (code = gs_matrix_multiply(&m1, &m2, &mp)) < 0 ||
234
1.03k
        (code = write_matrix(op, &mp)) < 0
235
1.03k
        )
236
0
        return code;
237
1.03k
    op[-2] = *op;
238
1.03k
    pop(2);
239
1.03k
    return code;
240
1.03k
}
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
99.6k
{
247
99.6k
    return common_transform(i_ctx_p, gs_transform, gs_point_transform);
248
99.6k
}
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
19.8k
{
255
19.8k
    return common_transform(i_ctx_p, gs_dtransform, gs_distance_transform);
256
19.8k
}
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
6
{
263
6
    return common_transform(i_ctx_p, gs_itransform, gs_point_transform_inverse);
264
6
}
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
60.6k
{
271
60.6k
    return common_transform(i_ctx_p, gs_idtransform, gs_distance_transform_inverse);
272
60.6k
}
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
180k
{
280
180k
    os_ptr op = osp;
281
180k
    double opxy[2];
282
180k
    gs_point pt;
283
180k
    int code;
284
285
    /* Optimize for the non-matrix case */
286
180k
    switch (r_type(op)) {
287
60.6k
        case t_real:
288
60.6k
            opxy[1] = op->value.realval;
289
60.6k
            break;
290
9.81k
        case t_integer:
291
9.81k
            opxy[1] = (double)op->value.intval;
292
9.81k
            break;
293
109k
        case t_array:   /* might be a matrix */
294
109k
        case t_shortarray:
295
109k
        case t_mixedarray: {
296
109k
            gs_matrix mat;
297
109k
            gs_matrix *pmat = &mat;
298
299
109k
            if ((code = read_matrix(imemory, op, pmat)) < 0 ||
300
109k
                (code = num_params(op - 1, 2, opxy)) < 0 ||
301
109k
                (code = (*matproc) (opxy[0], opxy[1], pmat, &pt)) < 0
302
109k
                ) {   /* Might be a stack underflow. */
303
1
                check_op(3);
304
1
                return code;
305
1
            }
306
109k
            op--;
307
109k
            pop(1);
308
109k
            goto out;
309
109k
        }
310
3
        default:
311
3
            return_op_typecheck(op);
312
180k
    }
313
70.4k
    switch (r_type(op - 1)) {
314
60.6k
        case t_real:
315
60.6k
            opxy[0] = (op - 1)->value.realval;
316
60.6k
            break;
317
9.81k
        case t_integer:
318
9.81k
            opxy[0] = (double)(op - 1)->value.intval;
319
9.81k
            break;
320
3
        default:
321
3
            return_op_typecheck(op - 1);
322
70.4k
    }
323
70.4k
    if ((code = (*ptproc) (igs, opxy[0], opxy[1], &pt)) < 0)
324
0
        return code;
325
180k
out:
326
180k
    make_real(op - 1, pt.x);
327
180k
    make_real(op, pt.y);
328
180k
    return 0;
329
70.4k
}
330
331
/* <matrix> <inv_matrix> invertmatrix <inv_matrix> */
332
static int
333
zinvertmatrix(i_ctx_t *i_ctx_p)
334
3
{
335
3
    os_ptr op = osp;
336
3
    gs_matrix m;
337
3
    int code;
338
339
3
    check_op(2);
340
2
    if ((code = read_matrix(imemory, op - 1, &m)) < 0 ||
341
2
        (code = gs_matrix_invert(&m, &m)) < 0 ||
342
2
        (code = write_matrix(op, &m)) < 0
343
2
        )
344
2
        return code;
345
0
    op[-1] = *op;
346
0
    pop(1);
347
0
    return code;
348
2
}
349
350
static int
351
zupdatematrices(i_ctx_t *i_ctx_p)
352
154k
{
353
154k
    return gs_updatematrices(igs);
354
154k
}
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
};