Coverage Report

Created: 2025-06-10 07:17

/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
17.9M
{
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
17.9M
    bool devn = dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0);
197
17.9M
    frac31 c[GX_DEVICE_COLOR_MAX_COMPONENTS];
198
17.9M
    ulong f[GX_DEVICE_COLOR_MAX_COMPONENTS];
199
17.9M
    int i, i1 = i0 + w, bi = i0, k;
200
17.9M
    gx_color_index ci0 = 0, ci1;
201
17.9M
    const gx_device_color_info *cinfo = &dev->color_info;
202
17.9M
    int n = cinfo->num_components;
203
17.9M
    int si, ei, di, code;
204
205
    /* Todo: set this up to vector earlier */
206
17.9M
    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
17.9M
    if (j < fixed2int(fa->clip->p.y) ||
210
17.9M
            j > fixed2int_ceiling(fa->clip->q.y)) /* Must be compatible to the clipping logic. */
211
0
        return 0;
212
56.5M
    for (k = 0; k < n; k++) {
213
38.6M
        int shift = cinfo->comp_shift[k];
214
38.6M
        int bits = cinfo->comp_bits[k];
215
216
38.6M
        c[k] = c0[k];
217
38.6M
        f[k] = c0f[k];
218
38.6M
        ci0 |= (gx_color_index)(c[k] >> (sizeof(c[k]) * 8 - 1 - bits)) << shift;
219
38.6M
    }
220
462M
    for (i = i0 + 1, di = 1; i < i1; i += di) {
221
444M
        if (di == 1) {
222
            /* Advance colors by 1 pixel. */
223
439M
            ci1 = 0;
224
904M
            for (k = 0; k < n; k++) {
225
465M
                int shift = cinfo->comp_shift[k];
226
465M
                int bits = cinfo->comp_bits[k];
227
228
465M
                if (cg_num[k]) {
229
457M
                    int32_t m = f[k] + cg_num[k];
230
231
457M
                    c[k] += m / cg_den;
232
457M
                    m -= m / cg_den * cg_den;
233
457M
                    if (m < 0) {
234
428M
                        c[k]--;
235
428M
                        m += cg_den;
236
428M
                    }
237
457M
                    f[k] = m;
238
457M
                }
239
465M
                ci1 |= (gx_color_index)(c[k] >> (sizeof(c[k]) * 8 - 1 - bits)) << shift;
240
465M
            }
241
439M
        } else {
242
            /* Advance colors by di pixels. */
243
4.38M
            ci1 = 0;
244
8.93M
            for (k = 0; k < n; k++) {
245
4.54M
                int shift = cinfo->comp_shift[k];
246
4.54M
                int bits = cinfo->comp_bits[k];
247
248
4.54M
                if (cg_num[k]) {
249
4.40M
                    int64_t M = f[k] + (int64_t)cg_num[k] * di;
250
4.40M
                    int32_t m;
251
252
4.40M
                    c[k] += (frac31)(M / cg_den);
253
4.40M
                    m = (int32_t)(M - M / cg_den * cg_den);
254
4.40M
                    if (m < 0) {
255
0
                        c[k]--;
256
0
                        m += cg_den;
257
0
                    }
258
4.40M
                    f[k] = m;
259
4.40M
                }
260
4.54M
                ci1 |= (gx_color_index)(c[k] >> (sizeof(c[k]) * 8 - 1 - bits)) << shift;
261
4.54M
            }
262
4.38M
        }
263
444M
        if (ci1 != ci0) {
264
17.0M
            si = max(bi, fixed2int(fa->clip->p.x));     /* Must be compatible to the clipping logic. */
265
17.0M
            ei = min(i, fixed2int_ceiling(fa->clip->q.x));  /* Must be compatible to the clipping logic. */
266
17.0M
            if (si < ei) {
267
11.8M
                if (fa->swap_axes) {
268
0
                    code = dev_proc(dev, fill_rectangle)(dev, j, si, 1, ei - si, ci0);
269
11.8M
                } else {
270
11.8M
                    code = dev_proc(dev, fill_rectangle)(dev, si, j, ei - si, 1, ci0);
271
11.8M
                }
272
11.8M
                if (code < 0)
273
0
                    return code;
274
11.8M
            }
275
17.0M
            bi = i;
276
17.0M
            ci0 = ci1;
277
17.0M
            di = 1;
278
427M
        } else if (i == i1) {
279
0
            i++;
280
0
            break;
281
427M
        } else {
282
            /* Compute a color change pixel analitically. */
283
427M
            di = i1 - i;
284
438M
            for (k = 0; k < n; k++) {
285
431M
                int32_t a;
286
431M
                int64_t x;
287
431M
                frac31 v = 1 << (31 - cinfo->comp_bits[k]); /* Color index precision in frac31. */
288
431M
                frac31 u = c[k] & (v - 1);
289
290
431M
                if (cg_num[k] == 0) {
291
                    /* No change. */
292
6.22M
                    continue;
293
425M
                } if (cg_num[k] > 0) {
294
                    /* Solve[(f[k] + cg_num[k]*x)/cg_den == v - u, x]  */
295
11.3M
                    a = v - u;
296
414M
                } else {
297
                    /* Solve[(f[k] + cg_num[k]*x)/cg_den == - u - 1, x]  */
298
414M
                    a = -u - 1;
299
414M
                }
300
425M
                x = ((int64_t)a * cg_den - f[k]) / cg_num[k];
301
425M
                if (i + x >= i1)
302
1.21M
                    continue;
303
424M
                else if (x < 0)
304
0
                    return_error(gs_error_unregistered); /* Must not happen. */
305
424M
                else if (di > (int)x) {
306
424M
                    di = (int)x;
307
424M
                    if (di <= 1) {
308
420M
                        di = 1;
309
420M
                        break;
310
420M
                    }
311
424M
                }
312
425M
            }
313
427M
        }
314
444M
    }
315
17.9M
    si = max(bi, fixed2int(fa->clip->p.x));     /* Must be compatible to the clipping logic. */
316
17.9M
    ei = min(i, fixed2int_ceiling(fa->clip->q.x));  /* Must be compatible to the clipping logic. */
317
17.9M
    if (si < ei) {
318
14.6M
        if (fa->swap_axes) {
319
4.53M
            return dev_proc(dev, fill_rectangle)(dev, j, si, 1, ei - si, ci0);
320
10.0M
        } else {
321
10.0M
            return dev_proc(dev, fill_rectangle)(dev, si, j, ei - si, 1, ci0);
322
10.0M
        }
323
14.6M
    }
324
3.29M
    return 0;
325
17.9M
}