Coverage Report

Created: 2025-06-10 06:59

/src/ghostpdl/base/gdevdsha.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2024 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
/* Default shading drawing device procedures. */
17
18
#include "gx.h"
19
#include "gserrors.h"
20
#include "gxdevice.h"
21
#include "gxcindex.h"
22
#include "gxdevsop.h"
23
24
static bool
25
gx_devn_diff(frac31 devn1[], frac31 devn2[], int num)
26
0
{
27
0
    int k;
28
29
0
    for (k = 0; k < num; k++) {
30
0
        if (devn1[k] != devn2[k]) {
31
0
            return true;
32
0
        }
33
0
    }
34
0
    return false;
35
0
}
36
37
int
38
gx_hl_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa,
39
        int i0, int j, int w, const frac31 *c0, const int32_t *c0f,
40
        const int32_t *cg_num, int32_t cg_den)
41
0
{
42
0
    frac31 c[GX_DEVICE_COLOR_MAX_COMPONENTS];
43
0
    frac31 curr[GX_DEVICE_COLOR_MAX_COMPONENTS];
44
0
    ulong f[GX_DEVICE_COLOR_MAX_COMPONENTS];
45
0
    int i, i1 = i0 + w, bi = i0, k;
46
0
    const gx_device_color_info *cinfo = &dev->color_info;
47
0
    int n = cinfo->num_components;
48
0
    int si, ei, di, code;
49
0
    gs_fixed_rect rect;
50
0
    gx_device_color devc;
51
52
    /* Note: All the stepping math is done with frac color values */
53
54
0
    devc.type = gx_dc_type_devn;
55
56
0
    if (j < fixed2int(fa->clip->p.y) ||
57
0
            j > fixed2int_ceiling(fa->clip->q.y)) /* Must be compatible to the clipping logic. */
58
0
        return 0;
59
0
    for (k = 0; k < n; k++) {
60
0
        curr[k] = c[k] = c0[k];
61
0
        f[k] = c0f[k];
62
0
    }
63
0
    for (i = i0 + 1, di = 1; i < i1; i += di) {
64
0
        if (di == 1) {
65
            /* Advance colors by 1 pixel. */
66
0
            for (k = 0; k < n; k++) {
67
0
                if (cg_num[k]) {
68
0
                    int32_t m = f[k] + cg_num[k];
69
70
0
                    c[k] += m / cg_den;
71
0
                    m -= m / cg_den * cg_den;
72
0
                    if (m < 0) {
73
0
                        c[k]--;
74
0
                        m += cg_den;
75
0
                    }
76
0
                    f[k] = m;
77
0
                }
78
0
            }
79
0
        } else {
80
            /* Advance colors by di pixels. */
81
0
            for (k = 0; k < n; k++) {
82
0
                if (cg_num[k]) {
83
0
                    int64_t M = f[k] + (int64_t)cg_num[k] * di;
84
0
                    int32_t m;
85
86
0
                    c[k] += (frac31)(M / cg_den);
87
0
                    m = (int32_t)(M - M / cg_den * cg_den);
88
0
                    if (m < 0) {
89
0
                        c[k]--;
90
0
                        m += cg_den;
91
0
                    }
92
0
                    f[k] = m;
93
0
                }
94
0
            }
95
0
        }
96
0
        if (gx_devn_diff(c, curr, n)) {
97
0
            si = max(bi, fixed2int(fa->clip->p.x));     /* Must be compatible to the clipping logic. */
98
0
            ei = min(i, fixed2int_ceiling(fa->clip->q.x));  /* Must be compatible to the clipping logic. */
99
0
            if (si < ei) {
100
0
                if (fa->swap_axes) {
101
0
                    rect.p.x = int2fixed(j);
102
0
                    rect.p.y = int2fixed(si);
103
0
                    rect.q.x = int2fixed(j + 1);
104
0
                    rect.q.y = int2fixed(ei);
105
0
                } else {
106
0
                    rect.p.x = int2fixed(si);
107
0
                    rect.p.y = int2fixed(j);
108
0
                    rect.q.x = int2fixed(ei);
109
0
                    rect.q.y = int2fixed(j + 1);
110
0
                }
111
0
                for (k = 0; k < n; k++) {
112
0
                    devc.colors.devn.values[k] = frac312cv(curr[k]);
113
0
                }
114
0
                devc.tag = device_current_tag(dev);
115
0
                code = dev_proc(dev, fill_rectangle_hl_color) (dev, &rect, NULL, &devc, NULL);
116
0
                if (code < 0)
117
0
                    return code;
118
0
            }
119
0
            bi = i;
120
0
            for (k = 0; k < n; k++) {
121
0
                curr[k] = c[k];
122
0
            }
123
0
            di = 1;
124
0
        } else if (i == i1) {
125
0
            i++;
126
0
            break;
127
0
        } else {
128
            /* Compute a color change pixel analytically. */
129
0
            di = i1 - i;
130
0
            for (k = 0; k < n; k++) {
131
0
                int32_t a;
132
0
                int64_t x;
133
0
                frac31 v = 1 << (31 - cinfo->comp_bits[k]); /* Color index precision in frac31. */
134
0
                frac31 u = c[k] & (v - 1);
135
136
0
                if (cg_num[k] == 0) {
137
                    /* No change. */
138
0
                    continue;
139
0
                } if (cg_num[k] > 0) {
140
                    /* Solve[(f[k] + cg_num[k]*x)/cg_den == v - u, x]  */
141
0
                    a = v - u;
142
0
                } else {
143
                    /* Solve[(f[k] + cg_num[k]*x)/cg_den == - u - 1, x]  */
144
0
                    a = -u - 1;
145
0
                }
146
0
                x = ((int64_t)a * cg_den - f[k]) / cg_num[k];
147
0
                if (i + x >= i1)
148
0
                    continue;
149
0
                else if (x < 0)
150
0
                    return_error(gs_error_unregistered); /* Must not happen. */
151
0
                else if (di > (int)x) {
152
0
                    di = (int)x;
153
0
                    if (di <= 1) {
154
0
                        di = 1;
155
0
                        break;
156
0
                    }
157
0
                }
158
0
            }
159
0
        }
160
0
    }
161
0
    si = max(bi, fixed2int(fa->clip->p.x));     /* Must be compatible to the clipping logic. */
162
0
    ei = min(i, fixed2int_ceiling(fa->clip->q.x));  /* Must be compatible to the clipping logic. */
163
0
    if (si < ei) {
164
0
        if (fa->swap_axes) {
165
0
            rect.p.x = int2fixed(j);
166
0
            rect.p.y = int2fixed(si);
167
0
            rect.q.x = int2fixed(j + 1);
168
0
            rect.q.y = int2fixed(ei);
169
0
        } else {
170
0
            rect.p.x = int2fixed(si);
171
0
            rect.p.y = int2fixed(j);
172
0
            rect.q.x = int2fixed(ei);
173
0
            rect.q.y = int2fixed(j + 1);
174
0
        }
175
0
        for (k = 0; k < n; k++) {
176
0
            devc.colors.devn.values[k] = frac312cv(curr[k]);
177
0
        }
178
0
        devc.tag = device_current_tag(dev);
179
0
        return dev_proc(dev, fill_rectangle_hl_color) (dev, &rect, NULL, &devc, NULL);
180
0
    }
181
0
    return 0;
182
0
}
183
184
int
185
gx_default_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa,
186
        int i0, int j, int w,
187
        const frac31 *c0, const int32_t *c0f, const int32_t *cg_num, int32_t cg_den)
188
5.38M
{
189
    /* This default implementation decomposes the area into constant color rectangles.
190
       Devices may supply optimized implementations with
191
       the inversed nesting of the i,k cicles,
192
       i.e. with enumerating planes first, with a direct writing to the raster,
193
       and with a fixed bits per component.
194
     */
195
    /* First determine if we are doing high level style colors or pure colors */
196
5.38M
    bool devn = dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0);
197
5.38M
    frac31 c[GX_DEVICE_COLOR_MAX_COMPONENTS];
198
5.38M
    ulong f[GX_DEVICE_COLOR_MAX_COMPONENTS];
199
5.38M
    int i, i1 = i0 + w, bi = i0, k;
200
5.38M
    gx_color_index ci0 = 0, ci1;
201
5.38M
    const gx_device_color_info *cinfo = &dev->color_info;
202
5.38M
    int n = cinfo->num_components;
203
5.38M
    int si, ei, di, code;
204
205
    /* Todo: set this up to vector earlier */
206
5.38M
    if (devn)  /* Note, PDF14 could be additive and doing devn */
207
0
        return gx_hl_fill_linear_color_scanline(dev, fa, i0, j, w, c0, c0f,
208
0
                                                cg_num, cg_den);
209
5.38M
    if (j < fixed2int(fa->clip->p.y) ||
210
5.38M
            j > fixed2int_ceiling(fa->clip->q.y)) /* Must be compatible to the clipping logic. */
211
0
        return 0;
212
23.5M
    for (k = 0; k < n; k++) {
213
18.1M
        int shift = cinfo->comp_shift[k];
214
18.1M
        int bits = cinfo->comp_bits[k];
215
216
18.1M
        c[k] = c0[k];
217
18.1M
        f[k] = c0f[k];
218
18.1M
        ci0 |= (gx_color_index)(c[k] >> (sizeof(c[k]) * 8 - 1 - bits)) << shift;
219
18.1M
    }
220
21.2M
    for (i = i0 + 1, di = 1; i < i1; i += di) {
221
15.8M
        if (di == 1) {
222
            /* Advance colors by 1 pixel. */
223
15.7M
            ci1 = 0;
224
59.1M
            for (k = 0; k < n; k++) {
225
43.4M
                int shift = cinfo->comp_shift[k];
226
43.4M
                int bits = cinfo->comp_bits[k];
227
228
43.4M
                if (cg_num[k]) {
229
35.2M
                    int32_t m = f[k] + cg_num[k];
230
231
35.2M
                    c[k] += m / cg_den;
232
35.2M
                    m -= m / cg_den * cg_den;
233
35.2M
                    if (m < 0) {
234
17.4M
                        c[k]--;
235
17.4M
                        m += cg_den;
236
17.4M
                    }
237
35.2M
                    f[k] = m;
238
35.2M
                }
239
43.4M
                ci1 |= (gx_color_index)(c[k] >> (sizeof(c[k]) * 8 - 1 - bits)) << shift;
240
43.4M
            }
241
15.7M
        } else {
242
            /* Advance colors by di pixels. */
243
103k
            ci1 = 0;
244
296k
            for (k = 0; k < n; k++) {
245
193k
                int shift = cinfo->comp_shift[k];
246
193k
                int bits = cinfo->comp_bits[k];
247
248
193k
                if (cg_num[k]) {
249
112k
                    int64_t M = f[k] + (int64_t)cg_num[k] * di;
250
112k
                    int32_t m;
251
252
112k
                    c[k] += (frac31)(M / cg_den);
253
112k
                    m = (int32_t)(M - M / cg_den * cg_den);
254
112k
                    if (m < 0) {
255
0
                        c[k]--;
256
0
                        m += cg_den;
257
0
                    }
258
112k
                    f[k] = m;
259
112k
                }
260
193k
                ci1 |= (gx_color_index)(c[k] >> (sizeof(c[k]) * 8 - 1 - bits)) << shift;
261
193k
            }
262
103k
        }
263
15.8M
        if (ci1 != ci0) {
264
7.07M
            si = max(bi, fixed2int(fa->clip->p.x));     /* Must be compatible to the clipping logic. */
265
7.07M
            ei = min(i, fixed2int_ceiling(fa->clip->q.x));  /* Must be compatible to the clipping logic. */
266
7.07M
            if (si < ei) {
267
6.96M
                if (fa->swap_axes) {
268
0
                    code = dev_proc(dev, fill_rectangle)(dev, j, si, 1, ei - si, ci0);
269
6.96M
                } else {
270
6.96M
                    code = dev_proc(dev, fill_rectangle)(dev, si, j, ei - si, 1, ci0);
271
6.96M
                }
272
6.96M
                if (code < 0)
273
0
                    return code;
274
6.96M
            }
275
7.07M
            bi = i;
276
7.07M
            ci0 = ci1;
277
7.07M
            di = 1;
278
8.76M
        } else if (i == i1) {
279
0
            i++;
280
0
            break;
281
8.76M
        } else {
282
            /* Compute a color change pixel analitically. */
283
8.76M
            di = i1 - i;
284
17.9M
            for (k = 0; k < n; k++) {
285
17.1M
                int32_t a;
286
17.1M
                int64_t x;
287
17.1M
                frac31 v = 1 << (31 - cinfo->comp_bits[k]); /* Color index precision in frac31. */
288
17.1M
                frac31 u = c[k] & (v - 1);
289
290
17.1M
                if (cg_num[k] == 0) {
291
                    /* No change. */
292
4.60M
                    continue;
293
12.4M
                } if (cg_num[k] > 0) {
294
                    /* Solve[(f[k] + cg_num[k]*x)/cg_den == v - u, x]  */
295
6.54M
                    a = v - u;
296
6.54M
                } else {
297
                    /* Solve[(f[k] + cg_num[k]*x)/cg_den == - u - 1, x]  */
298
5.95M
                    a = -u - 1;
299
5.95M
                }
300
12.4M
                x = ((int64_t)a * cg_den - f[k]) / cg_num[k];
301
12.4M
                if (i + x >= i1)
302
590k
                    continue;
303
11.9M
                else if (x < 0)
304
0
                    return_error(gs_error_unregistered); /* Must not happen. */
305
11.9M
                else if (di > (int)x) {
306
10.7M
                    di = (int)x;
307
10.7M
                    if (di <= 1) {
308
7.96M
                        di = 1;
309
7.96M
                        break;
310
7.96M
                    }
311
10.7M
                }
312
12.4M
            }
313
8.76M
        }
314
15.8M
    }
315
5.38M
    si = max(bi, fixed2int(fa->clip->p.x));     /* Must be compatible to the clipping logic. */
316
5.38M
    ei = min(i, fixed2int_ceiling(fa->clip->q.x));  /* Must be compatible to the clipping logic. */
317
5.38M
    if (si < ei) {
318
5.04M
        if (fa->swap_axes) {
319
1.97M
            return dev_proc(dev, fill_rectangle)(dev, j, si, 1, ei - si, ci0);
320
3.07M
        } else {
321
3.07M
            return dev_proc(dev, fill_rectangle)(dev, si, j, ei - si, 1, ci0);
322
3.07M
        }
323
5.04M
    }
324
337k
    return 0;
325
5.38M
}