Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/psi/zmatrix.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, 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
375k
{
34
375k
    return gs_initmatrix(igs);
35
375k
}
36
37
/* <matrix> defaultmatrix <matrix> */
38
static int
39
zdefaultmatrix(i_ctx_t *i_ctx_p)
40
364k
{
41
364k
    os_ptr op = osp;
42
364k
    gs_matrix mat;
43
44
364k
    gs_defaultmatrix(igs, &mat);
45
364k
    return write_matrix(op, &mat);
46
364k
}
47
48
/* - .currentmatrix <xx> <xy> <yx> <yy> <tx> <ty> */
49
static int
50
zcurrentmatrix(i_ctx_t *i_ctx_p)
51
404k
{
52
404k
    os_ptr op = osp;
53
404k
    gs_matrix mat;
54
404k
    int code = gs_currentmatrix(igs, &mat);
55
56
404k
    if (code < 0)
57
0
        return code;
58
404k
    push(6);
59
404k
    code = make_floats(op - 5, &mat.xx, 6);
60
404k
    if (code < 0)
61
0
        pop(6);
62
404k
    return code;
63
404k
}
64
65
/* <xx> <xy> <yx> <yy> <tx> <ty> .setmatrix - */
66
static int
67
zsetmatrix(i_ctx_t *i_ctx_p)
68
29.4k
{
69
29.4k
    os_ptr op = osp;
70
29.4k
    gs_matrix mat;
71
29.4k
    int code = float_params(op, 6, &mat.xx);
72
73
29.4k
    if (code < 0)
74
0
        return code;
75
29.4k
    if ((code = gs_setmatrix(igs, &mat)) < 0)
76
0
        return code;
77
29.4k
    pop(6);
78
29.4k
    return 0;
79
29.4k
}
80
81
/* <matrix|null> .setdefaultmatrix - */
82
static int
83
zsetdefaultmatrix(i_ctx_t *i_ctx_p)
84
375k
{
85
375k
    os_ptr op = osp;
86
375k
    int code;
87
88
375k
    if (r_has_type(op, t_null))
89
0
        code = gs_setdefaultmatrix(igs, NULL);
90
375k
    else {
91
375k
        gs_matrix mat;
92
93
375k
        code = read_matrix(imemory, op, &mat);
94
375k
        if (code < 0)
95
0
            return code;
96
375k
        code = gs_setdefaultmatrix(igs, &mat);
97
375k
    }
98
375k
    if (code < 0)
99
0
        return code;
100
375k
    pop(1);
101
375k
    return 0;
102
375k
}
103
104
/* <tx> <ty> translate - */
105
/* <tx> <ty> <matrix> translate <matrix> */
106
static int
107
ztranslate(i_ctx_t *i_ctx_p)
108
611k
{
109
611k
    os_ptr op = osp;
110
611k
    int code;
111
611k
    double trans[2];
112
113
611k
    if ((code = num_params(op, 2, trans)) >= 0) {
114
610k
        code = gs_translate(igs, trans[0], trans[1]);
115
610k
        if (code < 0)
116
0
            return code;
117
610k
    } else {     /* matrix operand */
118
777
        gs_matrix mat;
119
120
        /* The num_params failure might be a stack underflow. */
121
777
        check_op(2);
122
764
        if ((code = num_params(op - 1, 2, trans)) < 0 ||
123
764
            (code = gs_make_translation(trans[0], trans[1], &mat)) < 0 ||
124
764
            (code = write_matrix(op, &mat)) < 0
125
764
            ) {     /* Might be a stack underflow. */
126
31
            check_op(3);
127
17
            return code;
128
31
        }
129
733
        op[-2] = *op;
130
733
    }
131
611k
    pop(2);
132
611k
    return code;
133
611k
}
134
135
/* <sx> <sy> scale - */
136
/* <sx> <sy> <matrix> scale <matrix> */
137
static int
138
zscale(i_ctx_t *i_ctx_p)
139
7.26k
{
140
7.26k
    os_ptr op = osp;
141
7.26k
    int code;
142
7.26k
    double scale[2];
143
144
7.26k
    if ((code = num_params(op, 2, scale)) >= 0) {
145
6.97k
        code = gs_scale(igs, scale[0], scale[1]);
146
6.97k
        if (code < 0)
147
0
            return code;
148
6.97k
    } else {     /* matrix operand */
149
284
        gs_matrix mat;
150
151
        /* The num_params failure might be a stack underflow. */
152
284
        check_op(2);
153
270
        if ((code = num_params(op - 1, 2, scale)) < 0 ||
154
270
            (code = gs_make_scaling(scale[0], scale[1], &mat)) < 0 ||
155
270
            (code = write_matrix(op, &mat)) < 0
156
270
            ) {     /* Might be a stack underflow. */
157
31
            check_op(3);
158
19
            return code;
159
31
        }
160
239
        op[-2] = *op;
161
239
    }
162
7.21k
    pop(2);
163
7.21k
    return code;
164
7.26k
}
165
166
/* <angle> rotate - */
167
/* <angle> <matrix> rotate <matrix> */
168
static int
169
zrotate(i_ctx_t *i_ctx_p)
170
111k
{
171
111k
    os_ptr op = osp;
172
111k
    int code;
173
111k
    double ang;
174
175
111k
    if ((code = real_param(op, &ang)) >= 0) {
176
109k
        code = gs_rotate(igs, ang);
177
109k
        if (code < 0)
178
0
            return code;
179
109k
    } else {     /* matrix operand */
180
2.09k
        gs_matrix mat;
181
182
        /* The num_params failure might be a stack underflow. */
183
2.09k
        check_op(1);
184
2.08k
        if ((code = num_params(op - 1, 1, &ang)) < 0 ||
185
2.08k
            (code = gs_make_rotation(ang, &mat)) < 0 ||
186
2.08k
            (code = write_matrix(op, &mat)) < 0
187
2.08k
            ) {     /* Might be a stack underflow. */
188
38
            check_op(2);
189
28
            return code;
190
38
        }
191
2.04k
        op[-1] = *op;
192
2.04k
    }
193
111k
    pop(1);
194
111k
    return code;
195
111k
}
196
197
/* <matrix> concat - */
198
static int
199
zconcat(i_ctx_t *i_ctx_p)
200
404k
{
201
404k
    os_ptr op = osp;
202
404k
    gs_matrix mat;
203
404k
    int code = read_matrix(imemory, op, &mat);
204
205
404k
    if (code < 0)
206
18
        return code;
207
404k
    code = gs_concat(igs, &mat);
208
404k
    if (code < 0)
209
0
        return code;
210
404k
    pop(1);
211
404k
    return 0;
212
404k
}
213
214
/* <matrix1> <matrix2> <matrix> concatmatrix <matrix> */
215
static int
216
zconcatmatrix(i_ctx_t *i_ctx_p)
217
6.08k
{
218
6.08k
    os_ptr op = osp;
219
6.08k
    gs_matrix m1, m2, mp;
220
6.08k
    int code;
221
222
6.08k
    if ((code = read_matrix(imemory, op - 2, &m1)) < 0 ||
223
6.08k
        (code = read_matrix(imemory, op - 1, &m2)) < 0 ||
224
6.08k
        (code = gs_matrix_multiply(&m1, &m2, &mp)) < 0 ||
225
6.08k
        (code = write_matrix(op, &mp)) < 0
226
6.08k
        )
227
10
        return code;
228
6.07k
    op[-2] = *op;
229
6.07k
    pop(2);
230
6.07k
    return code;
231
6.08k
}
232
233
/* <x> <y> transform <xt> <yt> */
234
/* <x> <y> <matrix> transform <xt> <yt> */
235
static int
236
ztransform(i_ctx_t *i_ctx_p)
237
566k
{
238
566k
    return common_transform(i_ctx_p, gs_transform, gs_point_transform);
239
566k
}
240
241
/* <dx> <dy> dtransform <dxt> <dyt> */
242
/* <dx> <dy> <matrix> dtransform <dxt> <dyt> */
243
static int
244
zdtransform(i_ctx_t *i_ctx_p)
245
457k
{
246
457k
    return common_transform(i_ctx_p, gs_dtransform, gs_distance_transform);
247
457k
}
248
249
/* <xt> <yt> itransform <x> <y> */
250
/* <xt> <yt> <matrix> itransform <x> <y> */
251
static int
252
zitransform(i_ctx_t *i_ctx_p)
253
50
{
254
50
    return common_transform(i_ctx_p, gs_itransform, gs_point_transform_inverse);
255
50
}
256
257
/* <dxt> <dyt> idtransform <dx> <dy> */
258
/* <dxt> <dyt> <matrix> idtransform <dx> <dy> */
259
static int
260
zidtransform(i_ctx_t *i_ctx_p)
261
375k
{
262
375k
    return common_transform(i_ctx_p, gs_idtransform, gs_distance_transform_inverse);
263
375k
}
264
265
/* Common logic for [i][d]transform */
266
static int
267
common_transform(i_ctx_t *i_ctx_p,
268
        int (*ptproc)(gs_gstate *, double, double, gs_point *),
269
        int (*matproc)(double, double, const gs_matrix *, gs_point *))
270
1.39M
{
271
1.39M
    os_ptr op = osp;
272
1.39M
    double opxy[2];
273
1.39M
    gs_point pt;
274
1.39M
    int code;
275
276
    /* Optimize for the non-matrix case */
277
1.39M
    switch (r_type(op)) {
278
375k
        case t_real:
279
375k
            opxy[1] = op->value.realval;
280
375k
            break;
281
89.9k
        case t_integer:
282
89.9k
            opxy[1] = (double)op->value.intval;
283
89.9k
            break;
284
934k
        case t_array:   /* might be a matrix */
285
934k
        case t_shortarray:
286
934k
        case t_mixedarray: {
287
934k
            gs_matrix mat;
288
934k
            gs_matrix *pmat = &mat;
289
290
934k
            if ((code = read_matrix(imemory, op, pmat)) < 0 ||
291
934k
                (code = num_params(op - 1, 2, opxy)) < 0 ||
292
934k
                (code = (*matproc) (opxy[0], opxy[1], pmat, &pt)) < 0
293
934k
                ) {   /* Might be a stack underflow. */
294
15
                check_op(3);
295
9
                return code;
296
15
            }
297
934k
            op--;
298
934k
            pop(1);
299
934k
            goto out;
300
934k
        }
301
40
        default:
302
40
            return_op_typecheck(op);
303
1.39M
    }
304
465k
    switch (r_type(op - 1)) {
305
375k
        case t_real:
306
375k
            opxy[0] = (op - 1)->value.realval;
307
375k
            break;
308
89.8k
        case t_integer:
309
89.8k
            opxy[0] = (double)(op - 1)->value.intval;
310
89.8k
            break;
311
43
        default:
312
43
            return_op_typecheck(op - 1);
313
465k
    }
314
465k
    if ((code = (*ptproc) (igs, opxy[0], opxy[1], &pt)) < 0)
315
0
        return code;
316
1.39M
out:
317
1.39M
    make_real(op - 1, pt.x);
318
1.39M
    make_real(op, pt.y);
319
1.39M
    return 0;
320
465k
}
321
322
/* <matrix> <inv_matrix> invertmatrix <inv_matrix> */
323
static int
324
zinvertmatrix(i_ctx_t *i_ctx_p)
325
20
{
326
20
    os_ptr op = osp;
327
20
    gs_matrix m;
328
20
    int code;
329
330
20
    if ((code = read_matrix(imemory, op - 1, &m)) < 0 ||
331
20
        (code = gs_matrix_invert(&m, &m)) < 0 ||
332
20
        (code = write_matrix(op, &m)) < 0
333
20
        )
334
20
        return code;
335
0
    op[-1] = *op;
336
0
    pop(1);
337
0
    return code;
338
20
}
339
340
/* <bbox> <matrix> .bbox_transform <x0> <y0> <x1> <y1> */
341
/* Calculate bonding box of a box transformed by a matrix. */
342
static int
343
zbbox_transform(i_ctx_t *i_ctx_p)
344
0
{
345
0
    os_ptr op = osp;
346
0
    gs_matrix m;
347
0
    float bbox[4];
348
0
    gs_point aa, az, za, zz;
349
0
    double temp;
350
0
    int code;
351
352
0
    if ((code = read_matrix(imemory, op, &m)) < 0)
353
0
        return code;
354
355
0
    if (!r_is_array(op - 1))
356
0
        return_op_typecheck(op - 1);
357
0
    check_read(op[-1]);
358
0
    if (r_size(op - 1) != 4)
359
0
        return_error(gs_error_rangecheck);
360
0
    if ((code = process_float_array(imemory, op - 1, 4, bbox) < 0))
361
0
        return code;
362
363
0
    gs_point_transform(bbox[0], bbox[1], &m, &aa);
364
0
    gs_point_transform(bbox[0], bbox[3], &m, &az);
365
0
    gs_point_transform(bbox[2], bbox[1], &m, &za);
366
0
    gs_point_transform(bbox[2], bbox[3], &m, &zz);
367
368
0
    if ( aa.x > az.x)
369
0
        temp = aa.x, aa.x = az.x, az.x = temp;
370
0
    if ( za.x > zz.x)
371
0
        temp = za.x, za.x = zz.x, zz.x = temp;
372
0
    if ( za.x < aa.x)
373
0
        aa.x = za.x;  /* min */
374
0
    if ( az.x > zz.x)
375
0
        zz.x = az.x;  /* max */
376
377
0
    if ( aa.y > az.y)
378
0
        temp = aa.y, aa.y = az.y, az.y = temp;
379
0
    if ( za.y > zz.y)
380
0
        temp = za.y, za.y = zz.y, zz.y = temp;
381
0
    if ( za.y < aa.y)
382
0
        aa.y = za.y;  /* min */
383
0
    if ( az.y > zz.y)
384
0
        zz.y = az.y;  /* max */
385
386
0
    push(2);
387
0
    make_real(op - 3, (float)aa.x);
388
0
    make_real(op - 2, (float)aa.y);
389
0
    make_real(op - 1, (float)zz.x);
390
0
    make_real(op    , (float)zz.y);
391
0
    return 0;
392
0
}
393
394
/* <matrix> .currenttextlinematrix <matrix> */
395
static int
396
zcurrenttextlinematrix(i_ctx_t *i_ctx_p)
397
0
{
398
0
    os_ptr op = osp;
399
0
    gs_matrix mat;
400
401
0
    check_op(1);
402
0
    if (!r_has_type(op, t_array))
403
0
        return_error(gs_error_typecheck);
404
405
0
    gs_gettextlinematrix(igs, &mat);
406
0
    return write_matrix(op, &mat);
407
0
}
408
409
static int
410
zsettextlinematrix(i_ctx_t *i_ctx_p)
411
0
{
412
0
    os_ptr op = osp;
413
0
    int code;
414
415
0
    check_op(1);
416
0
    if (r_has_type(op, t_array)) {
417
0
        gs_matrix mat;
418
419
0
        code = read_matrix(imemory, op, &mat);
420
0
        if (code < 0)
421
0
            return code;
422
0
        code = gs_settextlinematrix(igs, &mat);
423
0
    } else
424
0
        code = gs_error_typecheck;
425
426
0
    if (code < 0)
427
0
        return code;
428
0
    pop(1);
429
0
    return 0;
430
0
}
431
432
/* <matrix> .currenttextmatrix <matrix> */
433
static int
434
zcurrenttextmatrix(i_ctx_t *i_ctx_p)
435
0
{
436
0
    os_ptr op = osp;
437
0
    gs_matrix mat;
438
439
0
    check_op(1);
440
0
    if (!r_has_type(op, t_array))
441
0
        return_error(gs_error_typecheck);
442
443
0
    gs_gettextmatrix(igs, &mat);
444
0
    return write_matrix(op, &mat);
445
0
}
446
447
static int
448
zsettextmatrix(i_ctx_t *i_ctx_p)
449
0
{
450
0
    os_ptr op = osp;
451
0
    int code;
452
453
0
    check_op(1);
454
0
    if (r_has_type(op, t_array)) {
455
0
        gs_matrix mat;
456
457
0
        code = read_matrix(imemory, op, &mat);
458
0
        if (code < 0)
459
0
            return code;
460
0
        code = gs_settextmatrix(igs, &mat);
461
0
    } else
462
0
        code = gs_error_typecheck;
463
464
0
    if (code < 0)
465
0
        return code;
466
0
    pop(1);
467
0
    return 0;
468
0
}
469
470
static int
471
zupdatematrices(i_ctx_t *i_ctx_p)
472
996k
{
473
996k
    return gs_updatematrices(igs);
474
996k
}
475
476
/* ------ Initialization procedure ------ */
477
478
const op_def zmatrix_op_defs[] =
479
{
480
    {"1concat", zconcat},
481
    {"2dtransform", zdtransform},
482
    {"3concatmatrix", zconcatmatrix},
483
    {"0.currentmatrix", zcurrentmatrix},
484
    {"1defaultmatrix", zdefaultmatrix},
485
    {"2idtransform", zidtransform},
486
    {"0initmatrix", zinitmatrix},
487
    {"2invertmatrix", zinvertmatrix},
488
    {"2itransform", zitransform},
489
    {"1rotate", zrotate},
490
    {"2scale", zscale},
491
    {"6.setmatrix", zsetmatrix},
492
    {"1.setdefaultmatrix", zsetdefaultmatrix},
493
    {"2transform", ztransform},
494
    {"2translate", ztranslate},
495
    op_def_end(0)
496
};
497
498
const op_def zmatrix2_op_defs[] =
499
{
500
    {"2.bbox_transform", zbbox_transform},
501
    {"1.currenttextlinematrix", zcurrenttextlinematrix},
502
    {"1.settextlinematrix", zsettextlinematrix},
503
    {"1.currenttextmatrix", zcurrenttextmatrix},
504
    {"1.settextmatrix", zsettextmatrix},
505
    {"1.updatematrices", zupdatematrices},
506
    op_def_end(0)
507
};