Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/claptrap-planar.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2015-2021 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
#include <stdlib.h>
17
#include <string.h>
18
#include <assert.h>
19
20
#include "claptrap.h"
21
#include "claptrap-impl.h"
22
23
/* This is the actual guts of the per-pixel processing.
24
 * We use a static inline, so the compiler can optimise
25
 * out as many of the tests as possible. */
26
inline static void process_at_pixel(ClapTrap      * gs_restrict ct,
27
                                    unsigned char * gs_restrict buffer,
28
                                    int             x,
29
                                    int             clips_on_x,
30
                                    int             clips_on_y,
31
                                    int             first_comp,
32
                                    int             last_comp,
33
                                    int             prev_comp,
34
                                    int             comp,
35
                                    int             line_offset,
36
                                    unsigned char  *process)
37
0
{
38
    /* We look at the pixel values on comp.
39
     * We look at the process values passed into us from prev_comp, and pass out
40
     * into comp.
41
     */
42
43
    /* Use local vars to avoid pointer aliasing */
44
0
    int            width        = ct->width;
45
0
    int            height       = ct->height;
46
#ifndef NDEBUG
47
    int            num_comp_lim = ct->num_comps-1;
48
#endif
49
0
    int            max_x_offset = ct->max_x_offset;
50
0
    int            max_y_offset = ct->max_y_offset;
51
0
    int            span         = ct->span;
52
0
    int            lines_in_buf = ct->lines_in_buf;
53
0
    unsigned char *linebuf      = ct->linebuf;
54
0
    int            y            = ct->y;
55
    /* Some offsets we will use repeatedly */
56
0
    int            oc           = x + comp * width;
57
    /* p != 0 if we need to be processed because a previous component shadows us.
58
     * If we're the first component then no one can shadow us. */
59
0
    int            p            = (first_comp ? 0 : *process);
60
0
    int            sx, sy, ex, ey, lo, v;
61
0
    unsigned char *pc;
62
0
    unsigned char *ppc;
63
64
0
    assert((first_comp != 1) ^ (prev_comp == -1));
65
0
    assert((last_comp != 1) ^ (comp == ct->comp_order[num_comp_lim]));
66
67
    /* Work out the search region bounds */
68
0
    sy = y - max_y_offset;
69
0
    if (clips_on_y && sy < 0)
70
0
        sy = 0;
71
0
    ey = y + max_y_offset;
72
0
    if (clips_on_y && ey >= height)
73
0
        ey = height-1;
74
0
    sx = x - max_x_offset;
75
0
    if (clips_on_x && sx < 0)
76
0
        sx = 0;
77
0
    ex = x + max_x_offset;
78
0
    if (clips_on_x && ex >= width)
79
0
        ex = width-1;
80
81
    /* We only need to check for shadowing lower components if we're
82
     * not the last last component (!last_comp). We can only need to process
83
     * here if we are not the first component (!first_comp) and
84
     * if (p != 0) then we need to search for the maximum local value
85
     * of  this component. */
86
0
    v = linebuf[line_offset + oc];
87
0
    if (!last_comp || (!first_comp && p))
88
0
    {
89
0
        int min_v, max_v;
90
91
0
        lo = sy % lines_in_buf;
92
0
        if (!first_comp)
93
0
            max_v = v;
94
0
        if (!last_comp)
95
0
            min_v = v;
96
0
        pc = &linebuf[lo * span + comp * width + sx];
97
0
        ex -= sx;
98
0
        for (sy = ey-sy; sy >= 0; sy--)
99
0
        {
100
0
            ppc = pc;
101
0
            for (sx = ex; sx >= 0; sx--)
102
0
            {
103
0
                int cv = *ppc++;
104
0
                if (!first_comp && cv > max_v)
105
0
                    max_v = cv;
106
0
                else if (!last_comp && cv < min_v)
107
0
                    min_v = cv;
108
0
            }
109
0
            pc += span;
110
0
            lo++;
111
0
            if (lo == lines_in_buf)
112
0
            {
113
0
                pc -= span * lines_in_buf;
114
0
            }
115
0
        }
116
        /* If we're not the last component, and we meet the criteria
117
         * the next component needs processing. */
118
0
        if (!last_comp)
119
0
        {
120
            /* Process flag for next component inherits from this one */
121
0
            int np = p;
122
0
            if (v > np && shadow_here(v, min_v, comp))
123
0
                np = v;
124
125
            /* Update the next components process flag if required */
126
0
            *process = np;
127
#ifdef SAVE_PROCESS_BUFFER
128
            buffer[x] = np;
129
            return;
130
#endif
131
0
        }
132
133
0
        if (!first_comp && p > v && trap_here(v, max_v, comp))
134
0
        {
135
0
            if (max_v < p)
136
0
                p = max_v;
137
0
            v = p;
138
0
        }
139
0
    }
140
0
    buffer[x] = v;
141
0
}
142
143
int ClapTrap_GetLinePlanar(ClapTrap       * gs_restrict ct,
144
                           unsigned char ** gs_restrict buffer)
145
0
{
146
0
    int max_y;
147
0
    int l_margin;
148
0
    int r_margin;
149
0
    int comp_idx;
150
0
    int prev_comp;
151
0
    int comp;
152
0
    int x;
153
0
    int line_offset;
154
0
    unsigned char *process;
155
0
    int num_comp_lim = ct->num_comps-1;
156
157
    /* Read in as many lines as we need */
158
0
    max_y = ct->y + ct->max_y_offset;
159
0
    if (max_y > ct->height-1)
160
0
        max_y = ct->height-1;
161
0
    while (ct->lines_read <= max_y)
162
0
    {
163
0
        int bufpos = ct->span * (ct->lines_read % ct->lines_in_buf);
164
0
        int code = ct->get_line(ct->get_line_arg, &ct->linebuf[bufpos]);
165
0
        if (code < 0)
166
0
            return code;
167
0
        ct->lines_read++;
168
0
    }
169
170
    /* Now we have enough information to calculate the process map for the next line of data */
171
0
    l_margin = ct->max_x_offset;
172
0
    r_margin = ct->width - ct->max_x_offset;
173
0
    if (r_margin < 0)
174
0
    {
175
0
        r_margin = 0;
176
0
        l_margin = 0;
177
0
    }
178
0
    x = (ct->y % ct->lines_in_buf);
179
0
    process = &ct->process[x * ct->width];
180
0
    line_offset = x * ct->span;
181
0
    if (ct->y < ct->max_y_offset || ct->y >= ct->height - ct->max_y_offset)
182
0
    {
183
0
        unsigned char *p = process;
184
        /* Some of our search area is off the end of the bitmap. We must be careful. */
185
0
        comp = ct->comp_order[0];
186
0
        for (x = 0; x < l_margin; x++)
187
0
        {
188
0
            process_at_pixel(ct, buffer[comp], x, 1, 1, 1, 0, -1, comp, line_offset, p++);
189
0
        }
190
0
        for (; x < r_margin; x++)
191
0
        {
192
0
            process_at_pixel(ct, buffer[comp], x, 0, 1, 1, 0, -1, comp, line_offset, p++);
193
0
        }
194
0
        for (; x < ct->width; x++)
195
0
        {
196
0
            process_at_pixel(ct, buffer[comp], x, 1, 1, 1, 0, -1, comp, line_offset, p++);
197
0
        }
198
0
        for (comp_idx = 1; comp_idx < num_comp_lim; comp_idx++)
199
0
        {
200
0
            prev_comp = comp;
201
0
            p = process;
202
0
            comp = ct->comp_order[comp_idx];
203
0
            for (x = 0; x < l_margin; x++)
204
0
            {
205
0
                process_at_pixel(ct, buffer[comp], x, 1, 1, 0, 0, prev_comp, comp, line_offset, p++);
206
0
            }
207
0
            for (; x < r_margin; x++)
208
0
            {
209
0
                process_at_pixel(ct, buffer[comp], x, 0, 1, 0, 0, prev_comp, comp, line_offset, p++);
210
0
            }
211
0
            for (; x < ct->width; x++)
212
0
            {
213
0
                process_at_pixel(ct, buffer[comp], x, 1, 1, 0, 0, prev_comp, comp, line_offset, p++);
214
0
            }
215
0
        }
216
0
        prev_comp = comp;
217
0
        p = process;
218
0
        comp = ct->comp_order[comp_idx];
219
0
        for (x = 0; x < l_margin; x++)
220
0
        {
221
0
            process_at_pixel(ct, buffer[comp], x, 1, 1, 0, 1, prev_comp, comp, line_offset, p++);
222
0
        }
223
0
        for (; x < r_margin; x++)
224
0
        {
225
0
            process_at_pixel(ct, buffer[comp], x, 0, 1, 0, 1, prev_comp, comp, line_offset, p++);
226
0
        }
227
0
        for (; x < ct->width; x++)
228
0
        {
229
0
            process_at_pixel(ct, buffer[comp], x, 1, 1, 0, 1, prev_comp, comp, line_offset, p++);
230
0
        }
231
0
    }
232
0
    else
233
0
    {
234
        /* Our search area never clips on y at least. */
235
0
        unsigned char *p = process;
236
0
        comp = ct->comp_order[0];
237
0
        for (x = 0; x < l_margin; x++)
238
0
        {
239
0
            process_at_pixel(ct, buffer[comp], x, 1, 0, 1, 0, -1, comp, line_offset, p++);
240
0
        }
241
0
        for (; x < r_margin; x++)
242
0
        {
243
0
            process_at_pixel(ct, buffer[comp], x, 0, 0, 1, 0, -1, comp, line_offset, p++);
244
0
        }
245
0
        for (; x < ct->width; x++)
246
0
        {
247
0
            process_at_pixel(ct, buffer[comp], x, 1, 0, 1, 0, -1, comp, line_offset, p++);
248
0
        }
249
0
        for (comp_idx = 1; comp_idx < num_comp_lim; comp_idx++)
250
0
        {
251
0
            prev_comp = comp;
252
0
            p = process;
253
0
            comp = ct->comp_order[comp_idx];
254
0
            for (x = 0; x < l_margin; x++)
255
0
            {
256
0
                process_at_pixel(ct, buffer[comp], x, 1, 0, 0, 0, prev_comp, comp, line_offset, p++);
257
0
            }
258
0
            for (; x < r_margin; x++)
259
0
            {
260
0
                process_at_pixel(ct, buffer[comp], x, 0, 0, 0, 0, prev_comp, comp, line_offset, p++);
261
0
            }
262
0
            for (; x < ct->width; x++)
263
0
            {
264
0
                process_at_pixel(ct, buffer[comp], x, 1, 0, 0, 0, prev_comp, comp, line_offset, p++);
265
0
            }
266
0
        }
267
0
        prev_comp = comp;
268
0
        p = process;
269
0
        comp = ct->comp_order[comp_idx];
270
0
        for (x = 0; x < l_margin; x++)
271
0
        {
272
0
            process_at_pixel(ct, buffer[comp], x, 1, 0, 0, 1, prev_comp, comp, line_offset, p++);
273
0
        }
274
0
        for (; x < r_margin; x++)
275
0
        {
276
0
            process_at_pixel(ct, buffer[comp], x, 0, 0, 0, 1, prev_comp, comp, line_offset, p++);
277
0
        }
278
0
        for (; x < ct->width; x++)
279
0
        {
280
0
            process_at_pixel(ct, buffer[comp], x, 1, 0, 0, 1, prev_comp, comp, line_offset, p++);
281
0
        }
282
0
    }
283
0
    ct->y++;
284
0
    if (ct->y == ct->height)
285
0
    {
286
0
        ct->y = 0;
287
0
        ct->lines_read = 0;
288
0
    }
289
290
0
    return 0;
291
0
}