Coverage Report

Created: 2025-06-10 06:58

/src/ghostpdl/base/gsgstate.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
/* gs_gstate housekeeping */
18
#include "gx.h"
19
#include "gserrors.h"
20
#include "gscspace.h"
21
#include "gscie.h"
22
#include "gsstruct.h"
23
#include "gsutil.h"   /* for gs_next_ids */
24
#include "gxbitmap.h"
25
#include "gxcmap.h"
26
#include "gxdht.h"
27
#include "gxgstate.h"
28
#include "gzht.h"
29
#include "gzline.h"
30
#include "gxfmap.h"
31
#include "gsicc_cache.h"
32
#include "gsicc_manage.h"
33
#include "gsicc_profilecache.h"
34
35
/******************************************************************************
36
 * See gsstate.c for a discussion of graphics state memory management. *
37
 ******************************************************************************/
38
39
/* Imported values */
40
/* The following should include a 'const', but for some reason */
41
/* the Watcom compiler won't accept it, even though it happily accepts */
42
/* the same construct everywhere else. */
43
extern /*const*/ gx_color_map_procs *const cmap_procs_default;
44
45
/* GC procedures for gx_line_params */
46
static
47
199k
ENUM_PTRS_WITH(line_params_enum_ptrs, gx_line_params *plp) return 0;
48
99.9k
    case 0: return ENUM_OBJ((plp->dash.pattern_size == 0 ?
49
199k
                             NULL : plp->dash.pattern));
50
199k
ENUM_PTRS_END
51
99.9k
static RELOC_PTRS_WITH(line_params_reloc_ptrs, gx_line_params *plp)
52
99.9k
{
53
99.9k
    if (plp->dash.pattern_size)
54
99.9k
        RELOC_VAR(plp->dash.pattern);
55
99.9k
} RELOC_PTRS_END
56
private_st_line_params();
57
58
/*
59
 * GC procedures for gs_gstate
60
 *
61
 * See comments in gixstate.h before the definition of gs_cr_state_do_rc and
62
 * st_cr_state_num_ptrs for an explanation about why the effective_transfer
63
 * pointers are handled in this manner.
64
 */
65
public_st_gs_gstate();
66
static
67
4.09M
ENUM_PTRS_WITH(gs_gstate_enum_ptrs, gs_gstate *gisvptr)
68
199k
    ENUM_SUPER(gs_gstate, st_line_params, line_params, st_gs_gstate_num_ptrs - st_line_params_num_ptrs);
69
2.09M
#define e1(i,elt) ENUM_PTR(i,gs_gstate,elt);
70
2.09M
    gs_gstate_do_ptrs(e1)
71
0
#undef e1
72
1.69M
#define E1(i,elt) ENUM_PTR(i + gs_gstate_num_ptrs,gs_gstate,elt);
73
1.69M
    gs_cr_state_do_ptrs(E1)
74
0
#undef E1
75
99.9k
    case (gs_gstate_num_ptrs + st_cr_state_num_ptrs): /* handle device specially */
76
99.9k
        ENUM_RETURN(gx_device_enum_ptr(gisvptr->device));
77
4.09M
ENUM_PTRS_END
78
79
99.9k
static RELOC_PTRS_WITH(gs_gstate_reloc_ptrs, gs_gstate *gisvptr)
80
99.9k
{
81
99.9k
    RELOC_SUPER(gs_gstate, st_line_params, line_params);
82
2.09M
#define r1(i,elt) RELOC_PTR(gs_gstate,elt);
83
2.09M
    gs_gstate_do_ptrs(r1)
84
99.9k
#undef r1
85
1.69M
#define R1(i,elt) RELOC_PTR(gs_gstate,elt);
86
1.69M
    gs_cr_state_do_ptrs(R1)
87
99.9k
#undef R1
88
89
99.9k
    gisvptr->device = gx_device_reloc_ptr(gisvptr->device, gcst);
90
99.9k
    {
91
99.9k
        int i = GX_DEVICE_COLOR_MAX_COMPONENTS - 1;
92
93
6.49M
        for (; i >= 0; i--)
94
6.39M
            RELOC_PTR(gs_gstate, effective_transfer[i]);
95
99.9k
    }
96
99.9k
} RELOC_PTRS_END
97
98
/* Initialize an gs_gstate, other than the parts covered by */
99
/* GS_STATE_INIT_VALUES(). */
100
int
101
gs_gstate_initialize(gs_gstate * pgs, gs_memory_t * mem)
102
16.4k
{
103
16.4k
    int i;
104
16.4k
    pgs->memory = mem;
105
16.4k
    pgs->client_data = 0;
106
16.4k
    pgs->trans_device = 0;
107
    /* Color rendering state */
108
16.4k
    pgs->halftone = 0;
109
16.4k
    {
110
16.4k
        int i;
111
112
49.3k
        for (i = 0; i < gs_color_select_count; ++i)
113
32.8k
            pgs->screen_phase[i].x = pgs->screen_phase[i].y = 0;
114
16.4k
    }
115
82.2k
    for (i=0; i < HT_OBJTYPE_COUNT; i++)
116
65.7k
        pgs->dev_ht[i] = NULL;
117
16.4k
    pgs->cie_render = 0;
118
16.4k
    pgs->cie_to_xyz = false;
119
16.4k
    pgs->black_generation = 0;
120
16.4k
    pgs->undercolor_removal = 0;
121
    /* Allocate an initial transfer map. */
122
16.4k
    rc_alloc_struct_n(pgs->set_transfer.gray,
123
16.4k
                      gx_transfer_map, &st_transfer_map,
124
16.4k
                      mem, return_error(gs_error_VMerror),
125
16.4k
                      "gs_gstate_init(transfer)", 1);
126
16.4k
    pgs->set_transfer.gray->proc = gs_identity_transfer;
127
16.4k
    pgs->set_transfer.gray->id = gs_next_ids(pgs->memory, 1);
128
16.4k
    pgs->set_transfer.gray->values[0] = frac_0;
129
16.4k
    pgs->set_transfer.red =
130
16.4k
        pgs->set_transfer.green =
131
16.4k
        pgs->set_transfer.blue = NULL;
132
1.06M
    for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++)
133
1.05M
        pgs->effective_transfer[i] = pgs->set_transfer.gray;
134
16.4k
    pgs->cie_joint_caches = NULL;
135
16.4k
    pgs->cie_joint_caches_alt = NULL;
136
16.4k
    pgs->cmap_procs = cmap_procs_default;
137
16.4k
    pgs->pattern_cache = NULL;
138
16.4k
    pgs->have_pattern_streams = false;
139
16.4k
    pgs->devicergb_cs = gs_cspace_new_DeviceRGB(mem);
140
16.4k
    pgs->devicecmyk_cs = gs_cspace_new_DeviceCMYK(mem);
141
16.4k
    if (pgs->devicergb_cs == NULL || pgs->devicecmyk_cs == NULL)
142
0
        return_error(gs_error_VMerror);
143
16.4k
    pgs->icc_link_cache = gsicc_cache_new(pgs->memory);
144
16.4k
    if (pgs->icc_link_cache == NULL)
145
0
        return_error(gs_error_VMerror);
146
16.4k
    pgs->icc_manager = gsicc_manager_new(pgs->memory);
147
16.4k
    if (pgs->icc_manager == NULL)
148
0
        return_error(gs_error_VMerror);
149
16.4k
    pgs->icc_profile_cache = gsicc_profilecache_new(pgs->memory);
150
16.4k
    if (pgs->icc_profile_cache == NULL)
151
0
        return_error(gs_error_VMerror);
152
16.4k
    pgs->black_textvec_state = NULL;
153
#if ENABLE_CUSTOM_COLOR_CALLBACK
154
    pgs->custom_color_callback = INIT_CUSTOM_COLOR_PTR;
155
#endif
156
16.4k
    return 0;
157
16.4k
}
158
159
/* Increment reference counts to note that an gs_gstate has been copied. */
160
void
161
gs_gstate_copied(gs_gstate * pgs)
162
1.64M
{
163
1.64M
    int i;
164
165
1.64M
    rc_increment(pgs->halftone);
166
8.21M
    for (i=0; i < HT_OBJTYPE_COUNT; i++)
167
6.56M
        rc_increment(pgs->dev_ht[i]);
168
1.64M
    rc_increment(pgs->cie_render);
169
1.64M
    rc_increment(pgs->black_generation);
170
1.64M
    rc_increment(pgs->undercolor_removal);
171
1.64M
    rc_increment(pgs->set_transfer.gray);
172
1.64M
    rc_increment(pgs->set_transfer.red);
173
1.64M
    rc_increment(pgs->set_transfer.green);
174
1.64M
    rc_increment(pgs->set_transfer.blue);
175
1.64M
    rc_increment(pgs->cie_joint_caches);
176
1.64M
    rc_increment(pgs->cie_joint_caches_alt);
177
1.64M
    rc_increment(pgs->devicergb_cs);
178
1.64M
    rc_increment(pgs->devicecmyk_cs);
179
1.64M
    rc_increment(pgs->icc_link_cache);
180
1.64M
    rc_increment(pgs->icc_profile_cache);
181
1.64M
    rc_increment(pgs->icc_manager);
182
1.64M
    rc_increment(pgs->black_textvec_state);
183
1.64M
}
184
185
/* Adjust reference counts before assigning one gs_gstate to another. */
186
void
187
gs_gstate_pre_assign(gs_gstate *pto, const gs_gstate *pfrom)
188
9.25k
{
189
9.25k
    const char *const cname = "gs_gstate_pre_assign";
190
9.25k
    int i;
191
192
9.25k
#define RCCOPY(element)\
193
157k
    rc_pre_assign(pto->element, pfrom->element, cname)
194
195
9.25k
    RCCOPY(cie_joint_caches);
196
9.25k
    RCCOPY(cie_joint_caches_alt);
197
9.25k
    RCCOPY(set_transfer.blue);
198
9.25k
    RCCOPY(set_transfer.green);
199
9.25k
    RCCOPY(set_transfer.red);
200
9.25k
    RCCOPY(set_transfer.gray);
201
9.25k
    RCCOPY(undercolor_removal);
202
9.25k
    RCCOPY(black_generation);
203
9.25k
    RCCOPY(cie_render);
204
46.2k
    for (i=0; i < HT_OBJTYPE_COUNT; i++)
205
37.0k
        RCCOPY(dev_ht[i]);
206
9.25k
    RCCOPY(halftone);
207
9.25k
    RCCOPY(devicergb_cs);
208
9.25k
    RCCOPY(devicecmyk_cs);
209
9.25k
    RCCOPY(icc_link_cache);
210
9.25k
    RCCOPY(icc_profile_cache);
211
9.25k
    RCCOPY(icc_manager);
212
9.25k
    RCCOPY(black_textvec_state);
213
9.25k
#undef RCCOPY
214
9.25k
}
215
216
/* Release a gs_gstate. */
217
void
218
gs_gstate_release(gs_gstate * pgs)
219
3.30M
{
220
3.30M
    const char *const cname = "gs_gstate_release";
221
3.30M
    gx_device_halftone *pdht;
222
3.30M
    int i;
223
224
3.30M
#define RCDECR(element)\
225
62.7M
    rc_decrement(pgs->element, cname);\
226
62.7M
    pgs->element = NULL  /* prevent subsequent decrements from this gs_gstate */
227
228
3.30M
    RCDECR(cie_joint_caches);
229
3.30M
    RCDECR(set_transfer.gray);
230
3.30M
    RCDECR(set_transfer.blue);
231
3.30M
    RCDECR(set_transfer.green);
232
3.30M
    RCDECR(set_transfer.red);
233
3.30M
    RCDECR(undercolor_removal);
234
3.30M
    RCDECR(black_generation);
235
3.30M
    RCDECR(cie_render);
236
    /*
237
     * If we're going to free a device halftone, make sure we free the
238
     * dependent structures as well.
239
     */
240
16.5M
    for (i=0; i < HT_OBJTYPE_COUNT; i++) {
241
13.2M
        pdht = pgs->dev_ht[i];
242
13.2M
        if (pdht != NULL && pdht->rc.ref_count == 1) {
243
13.7k
            gx_device_halftone_release(pdht, pdht->rc.memory);
244
13.7k
        }
245
13.2M
        RCDECR(dev_ht[i]);
246
13.2M
    }
247
3.30M
    RCDECR(halftone);
248
3.30M
    RCDECR(devicergb_cs);
249
3.30M
    RCDECR(devicecmyk_cs);
250
3.30M
    RCDECR(icc_link_cache);
251
3.30M
    RCDECR(icc_profile_cache);
252
3.30M
    RCDECR(icc_manager);
253
3.30M
    RCDECR(black_textvec_state);
254
3.30M
#undef RCDECR
255
3.30M
}