Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gsfunc.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
/* Generic Function support */
18
#include "memory_.h"
19
#include "gx.h"
20
#include "gserrors.h"
21
#include "gsparam.h"
22
#include "gxfunc.h"
23
#include "stream.h"
24
25
/* GC descriptors */
26
public_st_function();
27
gs_private_st_ptr(st_function_ptr, gs_function_t *, "gs_function_t *",
28
                  function_ptr_enum_ptrs, function_ptr_reloc_ptrs);
29
gs_private_st_element(st_function_ptr_element, gs_function_t *,
30
                      "gs_function_t *[]", function_ptr_element_enum_ptrs,
31
                      function_ptr_element_reloc_ptrs, st_function_ptr);
32
33
/* Allocate an array of function pointers. */
34
int
35
alloc_function_array(uint count, gs_function_t *** pFunctions,
36
                     gs_memory_t *mem)
37
31.7k
{
38
31.7k
    gs_function_t **ptr;
39
40
31.7k
    if (count == 0)
41
10
        return_error(gs_error_rangecheck);
42
31.7k
    ptr = gs_alloc_struct_array(mem, count, gs_function_t *,
43
31.7k
                                &st_function_ptr_element, "Functions");
44
31.7k
    if (ptr == 0)
45
0
        return_error(gs_error_VMerror);
46
31.7k
    memset(ptr, 0, sizeof(*ptr) * count);
47
31.7k
    *pFunctions = ptr;
48
31.7k
    return 0;
49
31.7k
}
50
51
/* Generic free_params implementation. */
52
void
53
fn_common_free_params(gs_function_params_t * params, gs_memory_t * mem)
54
300k
{
55
300k
    gs_free_const_object(mem, params->Range, "Range");
56
300k
    params->Range = NULL;
57
300k
    gs_free_const_object(mem, params->Domain, "Domain");
58
300k
    params->Domain = NULL;
59
300k
}
60
61
/* Generic free implementation. */
62
void
63
fn_common_free(gs_function_t * pfn, bool free_params, gs_memory_t * mem)
64
292k
{
65
292k
    if (free_params)
66
283k
        gs_function_free_params(pfn, mem);
67
292k
    gs_free_object(mem, pfn, "fn_common_free");
68
292k
}
69
70
/* Check the values of m, n, Domain, and (if supplied) Range. */
71
int
72
fn_check_mnDR(const gs_function_params_t * params, int m, int n)
73
298k
{
74
298k
    int i;
75
76
298k
    if (m <= 0 || n <= 0)
77
27
        return_error(gs_error_rangecheck);
78
623k
    for (i = 0; i < m; ++i)
79
324k
        if (params->Domain[2 * i] > params->Domain[2 * i + 1])
80
0
            return_error(gs_error_rangecheck);
81
298k
    if (params->Range != 0)
82
476k
        for (i = 0; i < n; ++i)
83
350k
            if (params->Range[2 * i] > params->Range[2 * i + 1])
84
9
                return_error(gs_error_rangecheck);
85
298k
    return 0;
86
298k
}
87
88
/* Return default function information. */
89
void
90
gs_function_get_info_default(const gs_function_t *pfn, gs_function_info_t *pfi)
91
49.4k
{
92
49.4k
    pfi->DataSource = 0;
93
49.4k
    pfi->Functions = 0;
94
49.4k
}
95
96
/*
97
 * Write generic parameters (FunctionType, Domain, Range) on a parameter list.
98
 */
99
int
100
fn_common_get_params(const gs_function_t *pfn, gs_param_list *plist)
101
18.3k
{
102
18.3k
    int ecode = param_write_int(plist, "FunctionType", &FunctionType(pfn));
103
18.3k
    int code;
104
105
18.3k
    if (pfn->params.Domain) {
106
18.3k
        code = param_write_float_values(plist, "Domain", pfn->params.Domain,
107
18.3k
                                        2 * pfn->params.m, false);
108
18.3k
        if (code < 0)
109
0
            ecode = code;
110
18.3k
    }
111
18.3k
    if (pfn->params.Range) {
112
18.1k
        code = param_write_float_values(plist, "Range", pfn->params.Range,
113
18.1k
                                        2 * pfn->params.n, false);
114
18.1k
        if (code < 0)
115
0
            ecode = code;
116
18.1k
    }
117
18.3k
    return ecode;
118
18.3k
}
119
120
/*
121
 * Copy an array of numeric values when scaling a function.
122
 */
123
void *
124
fn_copy_values(const void *pvalues, int count, int size, gs_memory_t *mem)
125
0
{
126
0
    if (pvalues) {
127
0
        void *values = gs_alloc_byte_array(mem, count, size, "fn_copy_values");
128
129
0
        if (values)
130
0
            memcpy(values, pvalues, (size_t)count * size);
131
0
        return values;
132
0
    } else
133
0
        return 0;   /* caller must check */
134
0
}
135
136
/*
137
 * If necessary, scale the Range or Decode array for fn_make_scaled.
138
 * Note that we must always allocate a new array.
139
 */
140
int
141
fn_scale_pairs(const float **ppvalues, const float *pvalues, int npairs,
142
               const gs_range_t *pranges, gs_memory_t *mem)
143
0
{
144
0
    if (pvalues == 0)
145
0
        *ppvalues = 0;
146
0
    else {
147
0
        float *out = (float *)
148
0
            gs_alloc_byte_array(mem, 2 * npairs, sizeof(*pvalues),
149
0
                                "fn_scale_pairs");
150
151
0
        *ppvalues = out;
152
0
        if (out == 0)
153
0
            return_error(gs_error_VMerror);
154
0
        if (pranges) {
155
            /* Allocate and compute scaled ranges. */
156
0
            int i;
157
0
            for (i = 0; i < npairs; ++i) {
158
0
                double base = pranges[i].rmin, factor = pranges[i].rmax - base;
159
160
0
                out[2 * i] = pvalues[2 * i] * factor + base;
161
0
                out[2 * i + 1] = pvalues[2 * i + 1] * factor + base;
162
0
            }
163
0
        } else
164
0
            memcpy(out, pvalues, 2 * sizeof(*pvalues) * npairs);
165
0
    }
166
0
    return 0;
167
0
}
168
169
/*
170
 * Scale the generic part of a function (Domain and Range).
171
 * The client must have copied the parameters already.
172
 */
173
int
174
fn_common_scale(gs_function_t *psfn, const gs_function_t *pfn,
175
                const gs_range_t *pranges, gs_memory_t *mem)
176
0
{
177
0
    int code;
178
179
0
    psfn->head = pfn->head;
180
0
    psfn->params.Domain = 0;    /* in case of failure */
181
0
    psfn->params.Range = 0;
182
0
    if ((code = fn_scale_pairs(&psfn->params.Domain, pfn->params.Domain,
183
0
                               pfn->params.m, NULL, mem)) < 0 ||
184
0
        (code = fn_scale_pairs(&psfn->params.Range, pfn->params.Range,
185
0
                               pfn->params.n, pranges, mem)) < 0)
186
0
        return code;
187
0
    return 0;
188
0
}
189
190
/* Serialize. */
191
int
192
fn_common_serialize(const gs_function_t * pfn, stream *s)
193
53.8k
{
194
53.8k
    uint n;
195
53.8k
    const gs_function_params_t * p = &pfn->params;
196
53.8k
    int code = sputs(s, (const byte *)&pfn->head.type, sizeof(pfn->head.type), &n);
197
53.8k
    const float dummy[8] = {0, 0, 0, 0,  0, 0, 0, 0};
198
199
53.8k
    if (code < 0)
200
0
        return code;
201
53.8k
    code = sputs(s, (const byte *)&p->m, sizeof(p->m), &n);
202
53.8k
    if (code < 0)
203
0
        return code;
204
53.8k
    code = sputs(s, (const byte *)&p->Domain[0], sizeof(p->Domain[0]) * p->m * 2, &n);
205
53.8k
    if (code < 0)
206
0
        return code;
207
53.8k
    code = sputs(s, (const byte *)&p->n, sizeof(p->n), &n);
208
53.8k
    if (code < 0)
209
0
        return code;
210
53.8k
    if (p->Range == NULL && p->n * 2 > count_of(dummy))
211
0
        return_error(gs_error_unregistered); /* Unimplemented. */
212
53.8k
    return sputs(s, (const byte *)(p->Range != NULL ? &p->Range[0] : dummy),
213
53.8k
            sizeof(p->Range[0]) * p->n * 2, &n);
214
53.8k
}