Coverage Report

Created: 2025-06-10 07:15

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