Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/psi/zform.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
/* Simple high level forms */
18
#include "ghost.h"
19
#include "oper.h"
20
#include "gxdevice.h"
21
#include "ialloc.h"
22
#include "idict.h"
23
#include "idparam.h"
24
#include "igstate.h"
25
#include "gxdevsop.h"
26
#include "gscoord.h"
27
#include "gsform1.h"
28
#include "gspath.h"
29
#include "gxpath.h"
30
#include "gzstate.h"
31
#include "store.h"
32
33
/* support for high level formss */
34
35
/* [CTM before Form Matrix applied] <<Form dictionary>> .beginform -
36
 */
37
static int zbeginform(i_ctx_t *i_ctx_p)
38
0
{
39
0
    os_ptr op = osp;
40
0
    gx_device *cdev = gs_currentdevice_inline(igs);
41
0
    int code;
42
0
    float BBox[4], Matrix[6];
43
0
    gs_form_template_t tmplate;
44
0
    gs_point ll, ur;
45
0
    gs_fixed_rect box;
46
47
0
    check_type(*op, t_dictionary);
48
0
    check_dict_read(*op);
49
50
0
    code = read_matrix(imemory, op - 1, &tmplate.CTM);
51
0
    if (code < 0)
52
0
        return code;
53
54
0
    code = dict_floats_param(imemory, op, "BBox", 4, BBox, NULL);
55
0
    if (code < 0)
56
0
        return code;
57
0
    if (code == 0)
58
0
       return_error(gs_error_undefined);
59
0
    tmplate.FormID = -1;
60
0
    tmplate.BBox.p.x = BBox[0];
61
0
    tmplate.BBox.p.y = BBox[1];
62
0
    tmplate.BBox.q.x = BBox[2];
63
0
    tmplate.BBox.q.y = BBox[3];
64
65
0
    code = dict_floats_param(imemory, op, "Matrix", 6, Matrix, NULL);
66
0
    if (code < 0)
67
0
        return code;
68
0
    if (code == 0)
69
0
       return_error(gs_error_undefined);
70
71
0
    tmplate.form_matrix.xx = Matrix[0];
72
0
    tmplate.form_matrix.xy = Matrix[1];
73
0
    tmplate.form_matrix.yx = Matrix[2];
74
0
    tmplate.form_matrix.yy = Matrix[3];
75
0
    tmplate.form_matrix.tx = Matrix[4];
76
0
    tmplate.form_matrix.ty = Matrix[5];
77
78
0
    tmplate.pcpath = igs->clip_path;
79
80
0
    tmplate.pgs = igs;
81
0
    code = dev_proc(cdev, dev_spec_op)(cdev, gxdso_form_begin,
82
0
                            &tmplate, 0);
83
84
    /* return value > 0 means the device sent us back a matrix
85
     * and wants the CTM set to that.
86
     */
87
0
    if (code > 0)
88
0
    {
89
0
        gs_setmatrix(igs, &tmplate.CTM);
90
0
        gs_distance_transform(tmplate.BBox.p.x, tmplate.BBox.p.y, &tmplate.CTM, &ll);
91
0
        gs_distance_transform(tmplate.BBox.q.x, tmplate.BBox.q.y, &tmplate.CTM, &ur);
92
93
        /* A form can legitimately have negative co-ordinates in paths
94
         * because it can be translated. But we always clip paths to the
95
         * page which (clearly) can't have negative co-ordinates. NB this
96
         * wouldn't be a problem if we didn't reset the CTM, but that would
97
         * break the form capture.
98
         * So here we temporarily set the clip to permit negative values,
99
         * fortunately this works.....
100
         */
101
        /* We choose to permit negative values of the same magnitude as the
102
         * positive ones.
103
         */
104
105
0
        box.p.x = float2fixed(ll.x);
106
0
        box.p.y = float2fixed(ll.y);
107
0
        box.q.x = float2fixed(ur.x);
108
0
        box.q.y = float2fixed(ur.y);
109
110
0
        if (box.p.x < 0) {
111
0
            if(box.p.x * -1 > box.q.x)
112
0
                box.q.x = box.p.x * -1;
113
0
        } else {
114
0
            if (fabs(ur.x) > fabs(ll.x))
115
0
                box.p.x = box.q.x * -1;
116
0
            else {
117
0
                box.p.x = float2fixed(ll.x * -1);
118
0
                box.q.x = float2fixed(ll.x);
119
0
            }
120
0
        }
121
0
        if (box.p.y < 0) {
122
0
            if(box.p.y * -1 > box.q.y)
123
0
                box.q.y = box.p.y * -1;
124
0
        } else {
125
0
            if (fabs(ur.y) > fabs(ll.y))
126
0
                box.p.y = box.q.y * -1;
127
0
            else {
128
0
                box.p.y = float2fixed(ll.y * -1);
129
0
                box.q.y = float2fixed(ll.y);
130
0
            }
131
0
        }
132
        /* This gets undone when we grestore after the form is executed */
133
0
        code = gx_clip_to_rectangle(igs, &box);
134
0
    }
135
136
0
    pop(2);
137
0
    return code;
138
0
}
139
140
/* - .endform -
141
 */
142
static int zendform(i_ctx_t *i_ctx_p)
143
0
{
144
0
    gx_device *cdev = gs_currentdevice_inline(igs);
145
0
    int code;
146
147
0
    code = dev_proc(cdev, dev_spec_op)(cdev, gxdso_form_end,
148
0
                            0, 0);
149
0
    return code;
150
0
}
151
152
/*
153
 * - .get_form_id <int>
154
 */
155
static int zget_form_id(i_ctx_t *i_ctx_p)
156
0
{
157
0
    os_ptr op = osp;
158
0
    gx_device *cdev = gs_currentdevice_inline(igs);
159
0
    int code, ID;
160
161
0
    code = dev_proc(cdev, dev_spec_op)(cdev, gxdso_get_form_ID,
162
0
                            &ID, sizeof(int));
163
164
0
    if (code < 0){
165
0
        ID = -1;
166
0
        code = 0;
167
0
    }
168
169
0
    push(1);
170
0
    make_int(op, ID);
171
0
    return code;
172
0
}
173
174
/*
175
 * [matrix] <dict> <int> .repeatform -
176
 */
177
static int zrepeatform(i_ctx_t *i_ctx_p)
178
0
{
179
0
    os_ptr op = osp;
180
0
    gx_device *cdev = gs_currentdevice_inline(igs);
181
0
    int code;
182
0
    gs_form_template_t tmplate;
183
0
    float BBox[4], Matrix[6];
184
185
0
    check_type(*op, t_integer);
186
187
0
    code = read_matrix(imemory, op - 2, &tmplate.CTM);
188
0
    if (code < 0)
189
0
        return code;
190
191
0
    check_type(op[- 1], t_dictionary);
192
0
    check_dict_read(*(op - 1));
193
194
0
    code = dict_floats_param(imemory, op - 1, "BBox", 4, BBox, NULL);
195
0
    if (code < 0)
196
0
        return code;
197
0
    if (code == 0)
198
0
       return_error(gs_error_undefined);
199
200
0
    tmplate.BBox.p.x = BBox[0];
201
0
    tmplate.BBox.p.y = BBox[1];
202
203
0
    code = dict_floats_param(imemory, op - 1, "Matrix", 6, Matrix, NULL);
204
0
    if (code < 0)
205
0
        return code;
206
0
    if (code == 0)
207
0
       return_error(gs_error_undefined);
208
209
0
    tmplate.form_matrix.xx = Matrix[0];
210
0
    tmplate.form_matrix.xy = Matrix[1];
211
0
    tmplate.form_matrix.yx = Matrix[2];
212
0
    tmplate.form_matrix.yy = Matrix[3];
213
0
    tmplate.form_matrix.tx = Matrix[4];
214
0
    tmplate.form_matrix.ty = Matrix[5];
215
216
0
    tmplate.pcpath = igs->clip_path;
217
218
0
    tmplate.FormID = op->value.intval;
219
220
0
    code = dev_proc(cdev, dev_spec_op)(cdev, gxdso_repeat_form,
221
0
                            &tmplate, sizeof(gs_form_template_t));
222
223
0
    pop(3);
224
0
    return code;
225
0
}
226
227
const op_def zform_op_defs[] =
228
{
229
    {"0.beginform", zbeginform},
230
    {"0.endform", zendform},
231
    {"0.get_form_id", zget_form_id},
232
    {"3.repeatform", zrepeatform},
233
op_def_end(0)
234
};