Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gxshade4.c
Line
Count
Source
1
/* Copyright (C) 2001-2025 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
/* Rendering for Gouraud triangle shadings */
18
#include "math_.h"
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsmatrix.h"   /* for gscoord.h */
23
#include "gscoord.h"
24
#include "gsptype2.h"
25
#include "gxcspace.h"
26
#include "gxdcolor.h"
27
#include "gxdevcli.h"
28
#include "gxgstate.h"
29
#include "gxpath.h"
30
#include "gxshade.h"
31
#include "gxshade4.h"
32
#include "gsicc_cache.h"
33
34
/* Initialize the fill state for triangle shading. */
35
int
36
mesh_init_fill_state(mesh_fill_state_t * pfs, const gs_shading_mesh_t * psh,
37
                     const gs_fixed_rect * rect_clip, gx_device * dev,
38
                     gs_gstate * pgs)
39
2.49k
{
40
2.49k
    int code;
41
2.49k
    code = shade_init_fill_state((shading_fill_state_t *) pfs,
42
2.49k
                                 (const gs_shading_t *)psh, dev, pgs);
43
2.49k
    if (code < 0)
44
0
        return code;
45
2.49k
    pfs->pshm = psh;
46
2.49k
    pfs->rect = *rect_clip;
47
2.49k
    return 0;
48
2.49k
}
49
50
/* ---------------- Gouraud triangle shadings ---------------- */
51
52
static int
53
Gt_next_vertex(const gs_shading_mesh_t * psh, shade_coord_stream_t * cs,
54
               shading_vertex_t * vertex, patch_color_t *c)
55
2.36M
{
56
2.36M
    int code = shade_next_vertex(cs, vertex, c);
57
2.36M
    if (code < 0)
58
416
        return code;
59
60
2.36M
    if (psh->params.Function) {
61
2.29M
        c->t[0] = c->cc.paint.values[0];
62
2.29M
        c->t[1] = 0;
63
        /* Decode the color with the function. */
64
2.29M
        code = gs_function_evaluate(psh->params.Function, c->t,
65
2.29M
                                    c->cc.paint.values);
66
2.29M
    } else
67
70.1k
        psh->params.ColorSpace->type->restrict_color(&c->cc, psh->params.ColorSpace);
68
2.36M
    return code;
69
2.36M
}
70
71
static inline int
72
Gt_fill_triangle(patch_fill_state_t * pfs, const shading_vertex_t * va,
73
                 const shading_vertex_t * vb, const shading_vertex_t * vc)
74
4.14M
{
75
4.14M
    int code = 0;
76
77
4.14M
    if (INTERPATCH_PADDING) {
78
4.14M
        code = mesh_padding(pfs, &va->p, &vb->p, va->c, vb->c);
79
4.14M
        if (code >= 0)
80
4.14M
            code = mesh_padding(pfs, &vb->p, &vc->p, vb->c, vc->c);
81
4.14M
        if (code >= 0)
82
4.14M
            code = mesh_padding(pfs, &vc->p, &va->p, vc->c, va->c);
83
4.14M
    }
84
4.14M
    if (code >= 0)
85
4.14M
        code = mesh_triangle(pfs, va, vb, vc);
86
4.14M
    return code;
87
4.14M
}
88
89
int
90
gs_shading_FfGt_fill_rectangle(const gs_shading_t * psh0, const gs_rect * rect,
91
                               const gs_fixed_rect * rect_clip,
92
                               gx_device * dev, gs_gstate * pgs)
93
409
{
94
409
    const gs_shading_FfGt_t * const psh = (const gs_shading_FfGt_t *)psh0;
95
409
    patch_fill_state_t pfs;
96
409
    const gs_shading_mesh_t *pshm = (const gs_shading_mesh_t *)psh;
97
409
    shade_coord_stream_t cs;
98
409
    int num_bits = psh->params.BitsPerFlag;
99
409
    int flag;
100
409
    shading_vertex_t va, vb, vc;
101
409
    patch_color_t *c, *C[3], *ca, *cb, *cc; /* va.c == ca && vb.c == cb && vc.c == cc always,
102
                                        provides a non-const access. */
103
409
    int code;
104
105
409
    code = shade_init_fill_state((shading_fill_state_t *)&pfs,
106
409
                                 (const gs_shading_t *)psh, dev, pgs);
107
409
    if (code < 0)
108
0
        return code;
109
409
    pfs.Function = pshm->params.Function;
110
409
    pfs.rect = *rect_clip;
111
409
    code = init_patch_fill_state(&pfs);
112
409
    if (code < 0) {
113
0
        if (pfs.icclink != NULL) gsicc_release_link(pfs.icclink);
114
0
        return code;
115
0
    }
116
409
    reserve_colors(&pfs, C, 3); /* Can't fail */
117
409
    va.c = ca = C[0];
118
409
    vb.c = cb = C[1];
119
409
    vc.c = cc = C[2];
120
409
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params,
121
409
                    pgs);
122
    /* CET 09-47J.PS SpecialTestI04Test01 does not need the color data alignment. */
123
23.6k
    while ((flag = shade_next_flag(&cs, num_bits)) >= 0) {
124
23.4k
        switch (flag) {
125
238
            default:
126
238
                code = gs_note_error(gs_error_rangecheck);
127
238
                goto error;
128
23.1k
            case 0:
129
23.1k
                if ((code = Gt_next_vertex(pshm, &cs, &va, ca)) < 0 ||
130
23.1k
                    (code = shade_next_flag(&cs, num_bits)) < 0 ||
131
23.1k
                    (code = Gt_next_vertex(pshm, &cs, &vb, cb)) < 0 ||
132
23.1k
                    (code = shade_next_flag(&cs, num_bits)) < 0
133
23.1k
                    )
134
10
                    break;
135
23.1k
                goto v2;
136
23.1k
            case 1:
137
5
                c = ca;
138
5
                va = vb;
139
5
                ca = cb;
140
5
                vb.c = cb = c;
141
                /* fall through */
142
5
            case 2:
143
5
                c = cb;
144
5
                vb = vc;
145
5
                cb = cc;
146
5
                vc.c = cc = c;
147
23.1k
v2:   if ((code = Gt_next_vertex(pshm, &cs, &vc, cc)) < 0)
148
1
                    break;
149
23.1k
                if ((code = Gt_fill_triangle(&pfs, &va, &vb, &vc)) < 0)
150
20
                    break;
151
23.4k
        }
152
23.2k
        cs.align(&cs, 8); /* Debugged with 12-14O.PS page 2. */
153
23.2k
    }
154
409
error:
155
409
    release_colors(&pfs, pfs.color_stack, 3);
156
409
    if (pfs.icclink != NULL) gsicc_release_link(pfs.icclink);
157
409
    if (term_patch_fill_state(&pfs))
158
0
        return_error(gs_error_unregistered); /* Must not happen. */
159
409
    if (!cs.is_eod(&cs))
160
238
        return_error(gs_error_rangecheck);
161
171
    return code;
162
409
}
163
164
int
165
gs_shading_LfGt_fill_rectangle(const gs_shading_t * psh0, const gs_rect * rect,
166
                               const gs_fixed_rect * rect_clip,
167
                               gx_device * dev, gs_gstate * pgs)
168
442
{
169
442
    const gs_shading_LfGt_t * const psh = (const gs_shading_LfGt_t *)psh0;
170
442
    patch_fill_state_t pfs;
171
442
    const gs_shading_mesh_t *pshm = (const gs_shading_mesh_t *)psh;
172
442
    shade_coord_stream_t cs;
173
442
    shading_vertex_t *vertex = NULL;
174
442
    byte *color_buffer = NULL;
175
442
    patch_color_t **color_buffer_ptrs = NULL; /* non-const access to vertex[i].c */
176
442
    shading_vertex_t next;
177
442
    int per_row = psh->params.VerticesPerRow;
178
442
    patch_color_t *c, *cn; /* cn == next.c always, provides a non-contst access. */
179
442
    int i, code;
180
181
442
    code = shade_init_fill_state((shading_fill_state_t *)&pfs,
182
442
                                 (const gs_shading_t *)psh, dev, pgs);
183
442
    if (code < 0)
184
0
        return code;
185
442
    pfs.Function = pshm->params.Function;
186
442
    pfs.rect = *rect_clip;
187
442
    code = init_patch_fill_state(&pfs);
188
442
    if (code < 0)
189
0
        goto out;
190
442
    reserve_colors(&pfs, &cn, 1); /* Can't fail. */
191
442
    next.c = cn;
192
442
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params,
193
442
                    pgs);
194
442
    vertex = (shading_vertex_t *)
195
442
        gs_alloc_byte_array(pgs->memory, per_row, sizeof(*vertex),
196
442
                            "gs_shading_LfGt_render");
197
442
    if (vertex == NULL) {
198
0
        code = gs_note_error(gs_error_VMerror);
199
0
        goto out;
200
0
    }
201
442
    color_buffer = gs_alloc_bytes(pgs->memory,
202
442
                                  (size_t)pfs.color_stack_step * (size_t)per_row,
203
442
                                  "gs_shading_LfGt_fill_rectangle");
204
442
    if (color_buffer == NULL) {
205
0
        code = gs_note_error(gs_error_VMerror);
206
0
        goto out;
207
0
    }
208
442
    color_buffer_ptrs = (patch_color_t **)gs_alloc_bytes(pgs->memory,
209
442
                            sizeof(patch_color_t *) * (size_t)per_row, "gs_shading_LfGt_fill_rectangle");
210
442
    if (color_buffer_ptrs == NULL) {
211
0
        code = gs_note_error(gs_error_VMerror);
212
0
        goto out;
213
0
    }
214
    /* CET 09-47K.PS SpecialTestJ02Test05 needs the color data alignment. */
215
4.70k
    for (i = 0; i < per_row; ++i) {
216
4.28k
        color_buffer_ptrs[i] = (patch_color_t *)(color_buffer + pfs.color_stack_step * i);
217
4.28k
        vertex[i].c = color_buffer_ptrs[i];
218
4.28k
        if ((code = Gt_next_vertex(pshm, &cs, &vertex[i], color_buffer_ptrs[i])) < 0)
219
18
            goto out;
220
4.28k
    }
221
229k
    while (!seofp(cs.s)) {
222
229k
        code = Gt_next_vertex(pshm, &cs, &next, cn);
223
229k
        if (code < 0)
224
51
            goto out;
225
2.29M
        for (i = 1; i < per_row; ++i) {
226
2.06M
            code = Gt_fill_triangle(&pfs, &vertex[i - 1], &vertex[i], &next);
227
2.06M
            if (code < 0)
228
0
                goto out;
229
2.06M
            c = color_buffer_ptrs[i - 1];
230
2.06M
            vertex[i - 1] = next;
231
2.06M
            color_buffer_ptrs[i - 1] = cn;
232
2.06M
            next.c = cn = c;
233
2.06M
            code = Gt_next_vertex(pshm, &cs, &next, cn);
234
2.06M
            if (code < 0)
235
337
                goto out;
236
2.06M
            code = Gt_fill_triangle(&pfs, &vertex[i], &vertex[i - 1], &next);
237
2.06M
            if (code < 0)
238
0
                goto out;
239
2.06M
        }
240
229k
        c = color_buffer_ptrs[per_row - 1];
241
229k
        vertex[per_row - 1] = next;
242
229k
        color_buffer_ptrs[per_row - 1] = cn;
243
229k
        next.c = cn = c;
244
229k
    }
245
442
out:
246
442
    gs_free_object(pgs->memory, vertex, "gs_shading_LfGt_render");
247
442
    gs_free_object(pgs->memory, color_buffer, "gs_shading_LfGt_render");
248
442
    gs_free_object(pgs->memory, color_buffer_ptrs, "gs_shading_LfGt_render");
249
442
    release_colors(&pfs, pfs.color_stack, 1);
250
442
    if (pfs.icclink != NULL) gsicc_release_link(pfs.icclink);
251
442
    if (term_patch_fill_state(&pfs))
252
0
        return_error(gs_error_unregistered); /* Must not happen. */
253
442
    return code;
254
442
}