Coverage Report

Created: 2025-11-16 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cairo/subprojects/pixman-0.44.2/pixman/pixman-edge.c
Line
Count
Source
1
/*
2
 * Copyright © 2004 Keith Packard
3
 *
4
 * Permission to use, copy, modify, distribute, and sell this software and its
5
 * documentation for any purpose is hereby granted without fee, provided that
6
 * the above copyright notice appear in all copies and that both that
7
 * copyright notice and this permission notice appear in supporting
8
 * documentation, and that the name of Keith Packard not be used in
9
 * advertising or publicity pertaining to distribution of the software without
10
 * specific, written prior permission.  Keith Packard makes no
11
 * representations about the suitability of this software for any purpose.  It
12
 * is provided "as is" without express or implied warranty.
13
 *
14
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20
 * PERFORMANCE OF THIS SOFTWARE.
21
 */
22
23
#ifdef HAVE_CONFIG_H
24
#include <pixman-config.h>
25
#endif
26
27
#include <string.h>
28
29
#include "pixman-private.h"
30
#include "pixman-accessor.h"
31
32
/*
33
 * Step across a small sample grid gap
34
 */
35
#define RENDER_EDGE_STEP_SMALL(edge)          \
36
2.70k
    {                 \
37
2.70k
  edge->x += edge->stepx_small;         \
38
2.70k
  edge->e += edge->dx_small;          \
39
2.70k
  if (edge->e > 0)           \
40
2.70k
  {               \
41
1.54k
      edge->e -= edge->dy;          \
42
1.54k
      edge->x += edge->signdx;          \
43
1.54k
  }                \
44
2.70k
    }
45
46
/*
47
 * Step across a large sample grid gap
48
 */
49
#define RENDER_EDGE_STEP_BIG(edge)          \
50
198
    {                 \
51
198
  edge->x += edge->stepx_big;         \
52
198
  edge->e += edge->dx_big;          \
53
198
  if (edge->e > 0)           \
54
198
  {               \
55
72
      edge->e -= edge->dy;          \
56
72
      edge->x += edge->signdx;          \
57
72
  }                \
58
198
    }
59
60
#ifdef PIXMAN_FB_ACCESSORS
61
#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors
62
#else
63
#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors
64
#endif
65
66
/*
67
 * 4 bit alpha
68
 */
69
70
#define N_BITS  4
71
#define RASTERIZE_EDGES rasterize_edges_4
72
73
#ifndef WORDS_BIGENDIAN
74
0
#define SHIFT_4(o)      ((o) << 2)
75
#else
76
#define SHIFT_4(o)      ((1 - (o)) << 2)
77
#endif
78
79
0
#define GET_4(x, o)      (((x) >> SHIFT_4 (o)) & 0xf)
80
#define PUT_4(x, o, v)              \
81
    (((x) & ~(0xf << SHIFT_4 (o))) | (((v) & 0xf) << SHIFT_4 (o)))
82
83
#define DEFINE_ALPHA(line, x)           \
84
0
    uint8_t   *__ap = (uint8_t *) line + ((x) >> 1);      \
85
0
    int __ao = (x) & 1
86
87
0
#define STEP_ALPHA      ((__ap += __ao), (__ao ^= 1))
88
89
#define ADD_ALPHA(a)              \
90
0
    {                 \
91
0
        uint8_t __o = READ (image, __ap);       \
92
0
        uint8_t __a = (a) + GET_4 (__o, __ao);       \
93
0
        WRITE (image, __ap, PUT_4 (__o, __ao, __a | (0 - ((__a) >> 4)))); \
94
0
    }
95
96
#include "pixman-edge-imp.h"
97
98
#undef ADD_ALPHA
99
#undef STEP_ALPHA
100
#undef DEFINE_ALPHA
101
#undef RASTERIZE_EDGES
102
#undef N_BITS
103
104
105
/*
106
 * 1 bit alpha
107
 */
108
109
#define N_BITS 1
110
#define RASTERIZE_EDGES rasterize_edges_1
111
112
#include "pixman-edge-imp.h"
113
114
#undef RASTERIZE_EDGES
115
#undef N_BITS
116
117
/*
118
 * 8 bit alpha
119
 */
120
121
static force_inline uint8_t
122
clip255 (int x)
123
4.42k
{
124
4.42k
    if (x > 255)
125
0
  return 255;
126
127
4.42k
    return x;
128
4.42k
}
pixman-edge.c:clip255
Line
Count
Source
123
4.42k
{
124
4.42k
    if (x > 255)
125
0
  return 255;
126
127
4.42k
    return x;
128
4.42k
}
Unexecuted instantiation: pixman-edge-accessors.c:clip255
129
130
#define ADD_SATURATE_8(buf, val, length)        \
131
768
    do                  \
132
768
    {                 \
133
768
        int i__ = (length);           \
134
768
        uint8_t *buf__ = (buf);           \
135
1.53k
        int val__ = (val);            \
136
768
                  \
137
2.28k
        while (i__--)             \
138
1.51k
        {               \
139
1.51k
            WRITE (image, (buf__), clip255 (READ (image, (buf__)) + (val__))); \
140
1.51k
            (buf__)++;              \
141
1.51k
  }                \
142
768
    } while (0)
143
144
/*
145
 * We want to detect the case where we add the same value to a long
146
 * span of pixels.  The triangles on the end are filled in while we
147
 * count how many sub-pixel scanlines contribute to the middle section.
148
 *
149
 *                 +--------------------------+
150
 *  fill_height =|   \                      /
151
 *                     +------------------+
152
 *                      |================|
153
 *                   fill_start       fill_end
154
 */
155
static void
156
rasterize_edges_8 (pixman_image_t *image,
157
                   pixman_edge_t * l,
158
                   pixman_edge_t * r,
159
                   pixman_fixed_t  t,
160
                   pixman_fixed_t  b)
161
18
{
162
18
    pixman_fixed_t y = t;
163
18
    uint32_t  *line;
164
18
    int fill_start = -1, fill_end = -1;
165
18
    int fill_size = 0;
166
18
    uint32_t *buf = (image)->bits.bits;
167
18
    int stride = (image)->bits.rowstride;
168
18
    int width = (image)->bits.width;
169
170
18
    line = buf + pixman_fixed_to_int (y) * stride;
171
172
18
    for (;;)
173
1.46k
    {
174
1.46k
        uint8_t *ap = (uint8_t *) line;
175
1.46k
        pixman_fixed_t lx, rx;
176
1.46k
        int lxi, rxi;
177
178
        /* clip X */
179
1.46k
        lx = l->x;
180
1.46k
        if (lx < 0)
181
0
      lx = 0;
182
183
1.46k
        rx = r->x;
184
185
1.46k
        if (pixman_fixed_to_int (rx) >= width)
186
0
  {
187
      /* Use the last pixel of the scanline, covered 100%.
188
       * We can't use the first pixel following the scanline,
189
       * because accessing it could result in a buffer overrun.
190
       */
191
0
      rx = pixman_int_to_fixed (width) - 1;
192
0
  }
193
194
        /* Skip empty (or backwards) sections */
195
1.46k
        if (rx > lx)
196
1.46k
        {
197
1.46k
            int lxs, rxs;
198
199
            /* Find pixel bounds for span. */
200
1.46k
            lxi = pixman_fixed_to_int (lx);
201
1.46k
            rxi = pixman_fixed_to_int (rx);
202
203
            /* Sample coverage for edge pixels */
204
1.46k
            lxs = RENDER_SAMPLES_X (lx, 8);
205
1.46k
            rxs = RENDER_SAMPLES_X (rx, 8);
206
207
            /* Add coverage across row */
208
1.46k
            if (lxi == rxi)
209
30
            {
210
30
                WRITE (image, ap + lxi,
211
30
           clip255 (READ (image, ap + lxi) + rxs - lxs));
212
30
      }
213
1.43k
            else
214
1.43k
            {
215
1.43k
                WRITE (image, ap + lxi,
216
1.43k
           clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs));
217
218
                /* Move forward so that lxi/rxi is the pixel span */
219
1.43k
                lxi++;
220
221
                /* Don't bother trying to optimize the fill unless
222
     * the span is longer than 4 pixels. */
223
1.43k
                if (rxi - lxi > 4)
224
1.24k
                {
225
1.24k
                    if (fill_start < 0)
226
102
                    {
227
102
                        fill_start = lxi;
228
102
                        fill_end = rxi;
229
102
                        fill_size++;
230
102
        }
231
1.14k
                    else
232
1.14k
                    {
233
1.14k
                        if (lxi >= fill_end || rxi < fill_start)
234
0
                        {
235
                            /* We're beyond what we saved, just fill it */
236
0
                            ADD_SATURATE_8 (ap + fill_start,
237
0
                                            fill_size * N_X_FRAC (8),
238
0
                                            fill_end - fill_start);
239
0
                            fill_start = lxi;
240
0
                            fill_end = rxi;
241
0
                            fill_size = 1;
242
0
      }
243
1.14k
                        else
244
1.14k
                        {
245
                            /* Update fill_start */
246
1.14k
                            if (lxi > fill_start)
247
75
                            {
248
75
                                ADD_SATURATE_8 (ap + fill_start,
249
75
                                                fill_size * N_X_FRAC (8),
250
75
                                                lxi - fill_start);
251
75
                                fill_start = lxi;
252
75
          }
253
1.07k
                            else if (lxi < fill_start)
254
66
                            {
255
66
                                ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8),
256
66
                                                fill_start - lxi);
257
66
          }
258
259
                            /* Update fill_end */
260
1.14k
                            if (rxi < fill_end)
261
6
                            {
262
6
                                ADD_SATURATE_8 (ap + rxi,
263
6
                                                fill_size * N_X_FRAC (8),
264
6
                                                fill_end - rxi);
265
6
                                fill_end = rxi;
266
6
          }
267
1.14k
                            else if (fill_end < rxi)
268
396
                            {
269
396
                                ADD_SATURATE_8 (ap + fill_end,
270
396
                                                N_X_FRAC (8),
271
396
                                                rxi - fill_end);
272
396
          }
273
1.14k
                            fill_size++;
274
1.14k
      }
275
1.14k
        }
276
1.24k
    }
277
189
                else
278
189
                {
279
189
                    ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi);
280
189
    }
281
282
1.43k
                WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs));
283
1.43k
      }
284
1.46k
  }
285
286
1.46k
        if (y == b)
287
18
        {
288
            /* We're done, make sure we clean up any remaining fill. */
289
18
            if (fill_start != fill_end)
290
15
            {
291
15
                if (fill_size == N_Y_FRAC (8))
292
0
                {
293
0
                    MEMSET_WRAPPED (image, ap + fill_start,
294
0
            0xff, fill_end - fill_start);
295
0
    }
296
15
                else
297
15
                {
298
15
                    ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
299
15
                                    fill_end - fill_start);
300
15
    }
301
15
      }
302
18
            break;
303
18
  }
304
305
1.44k
        if (pixman_fixed_frac (y) != Y_FRAC_LAST (8))
306
1.35k
        {
307
1.35k
            RENDER_EDGE_STEP_SMALL (l);
308
1.35k
            RENDER_EDGE_STEP_SMALL (r);
309
1.35k
            y += STEP_Y_SMALL (8);
310
1.35k
  }
311
99
        else
312
99
        {
313
99
            RENDER_EDGE_STEP_BIG (l);
314
99
            RENDER_EDGE_STEP_BIG (r);
315
99
            y += STEP_Y_BIG (8);
316
99
            if (fill_start != fill_end)
317
87
            {
318
87
                if (fill_size == N_Y_FRAC (8))
319
66
                {
320
66
                    MEMSET_WRAPPED (image, ap + fill_start,
321
66
            0xff, fill_end - fill_start);
322
66
    }
323
21
                else
324
21
                {
325
21
                    ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
326
21
                                    fill_end - fill_start);
327
21
    }
328
    
329
87
                fill_start = fill_end = -1;
330
87
                fill_size = 0;
331
87
      }
332
      
333
99
            line += stride;
334
99
  }
335
1.44k
    }
336
18
}
pixman-edge.c:rasterize_edges_8
Line
Count
Source
161
18
{
162
18
    pixman_fixed_t y = t;
163
18
    uint32_t  *line;
164
18
    int fill_start = -1, fill_end = -1;
165
18
    int fill_size = 0;
166
18
    uint32_t *buf = (image)->bits.bits;
167
18
    int stride = (image)->bits.rowstride;
168
18
    int width = (image)->bits.width;
169
170
18
    line = buf + pixman_fixed_to_int (y) * stride;
171
172
18
    for (;;)
173
1.46k
    {
174
1.46k
        uint8_t *ap = (uint8_t *) line;
175
1.46k
        pixman_fixed_t lx, rx;
176
1.46k
        int lxi, rxi;
177
178
        /* clip X */
179
1.46k
        lx = l->x;
180
1.46k
        if (lx < 0)
181
0
      lx = 0;
182
183
1.46k
        rx = r->x;
184
185
1.46k
        if (pixman_fixed_to_int (rx) >= width)
186
0
  {
187
      /* Use the last pixel of the scanline, covered 100%.
188
       * We can't use the first pixel following the scanline,
189
       * because accessing it could result in a buffer overrun.
190
       */
191
0
      rx = pixman_int_to_fixed (width) - 1;
192
0
  }
193
194
        /* Skip empty (or backwards) sections */
195
1.46k
        if (rx > lx)
196
1.46k
        {
197
1.46k
            int lxs, rxs;
198
199
            /* Find pixel bounds for span. */
200
1.46k
            lxi = pixman_fixed_to_int (lx);
201
1.46k
            rxi = pixman_fixed_to_int (rx);
202
203
            /* Sample coverage for edge pixels */
204
1.46k
            lxs = RENDER_SAMPLES_X (lx, 8);
205
1.46k
            rxs = RENDER_SAMPLES_X (rx, 8);
206
207
            /* Add coverage across row */
208
1.46k
            if (lxi == rxi)
209
30
            {
210
30
                WRITE (image, ap + lxi,
211
30
           clip255 (READ (image, ap + lxi) + rxs - lxs));
212
30
      }
213
1.43k
            else
214
1.43k
            {
215
1.43k
                WRITE (image, ap + lxi,
216
1.43k
           clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs));
217
218
                /* Move forward so that lxi/rxi is the pixel span */
219
1.43k
                lxi++;
220
221
                /* Don't bother trying to optimize the fill unless
222
     * the span is longer than 4 pixels. */
223
1.43k
                if (rxi - lxi > 4)
224
1.24k
                {
225
1.24k
                    if (fill_start < 0)
226
102
                    {
227
102
                        fill_start = lxi;
228
102
                        fill_end = rxi;
229
102
                        fill_size++;
230
102
        }
231
1.14k
                    else
232
1.14k
                    {
233
1.14k
                        if (lxi >= fill_end || rxi < fill_start)
234
0
                        {
235
                            /* We're beyond what we saved, just fill it */
236
0
                            ADD_SATURATE_8 (ap + fill_start,
237
0
                                            fill_size * N_X_FRAC (8),
238
0
                                            fill_end - fill_start);
239
0
                            fill_start = lxi;
240
0
                            fill_end = rxi;
241
0
                            fill_size = 1;
242
0
      }
243
1.14k
                        else
244
1.14k
                        {
245
                            /* Update fill_start */
246
1.14k
                            if (lxi > fill_start)
247
75
                            {
248
75
                                ADD_SATURATE_8 (ap + fill_start,
249
75
                                                fill_size * N_X_FRAC (8),
250
75
                                                lxi - fill_start);
251
75
                                fill_start = lxi;
252
75
          }
253
1.07k
                            else if (lxi < fill_start)
254
66
                            {
255
66
                                ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8),
256
66
                                                fill_start - lxi);
257
66
          }
258
259
                            /* Update fill_end */
260
1.14k
                            if (rxi < fill_end)
261
6
                            {
262
6
                                ADD_SATURATE_8 (ap + rxi,
263
6
                                                fill_size * N_X_FRAC (8),
264
6
                                                fill_end - rxi);
265
6
                                fill_end = rxi;
266
6
          }
267
1.14k
                            else if (fill_end < rxi)
268
396
                            {
269
396
                                ADD_SATURATE_8 (ap + fill_end,
270
396
                                                N_X_FRAC (8),
271
396
                                                rxi - fill_end);
272
396
          }
273
1.14k
                            fill_size++;
274
1.14k
      }
275
1.14k
        }
276
1.24k
    }
277
189
                else
278
189
                {
279
189
                    ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi);
280
189
    }
281
282
1.43k
                WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs));
283
1.43k
      }
284
1.46k
  }
285
286
1.46k
        if (y == b)
287
18
        {
288
            /* We're done, make sure we clean up any remaining fill. */
289
18
            if (fill_start != fill_end)
290
15
            {
291
15
                if (fill_size == N_Y_FRAC (8))
292
0
                {
293
0
                    MEMSET_WRAPPED (image, ap + fill_start,
294
0
            0xff, fill_end - fill_start);
295
0
    }
296
15
                else
297
15
                {
298
15
                    ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
299
15
                                    fill_end - fill_start);
300
15
    }
301
15
      }
302
18
            break;
303
18
  }
304
305
1.44k
        if (pixman_fixed_frac (y) != Y_FRAC_LAST (8))
306
1.35k
        {
307
1.35k
            RENDER_EDGE_STEP_SMALL (l);
308
1.35k
            RENDER_EDGE_STEP_SMALL (r);
309
1.35k
            y += STEP_Y_SMALL (8);
310
1.35k
  }
311
99
        else
312
99
        {
313
99
            RENDER_EDGE_STEP_BIG (l);
314
99
            RENDER_EDGE_STEP_BIG (r);
315
99
            y += STEP_Y_BIG (8);
316
99
            if (fill_start != fill_end)
317
87
            {
318
87
                if (fill_size == N_Y_FRAC (8))
319
66
                {
320
66
                    MEMSET_WRAPPED (image, ap + fill_start,
321
66
            0xff, fill_end - fill_start);
322
66
    }
323
21
                else
324
21
                {
325
21
                    ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
326
21
                                    fill_end - fill_start);
327
21
    }
328
    
329
87
                fill_start = fill_end = -1;
330
87
                fill_size = 0;
331
87
      }
332
      
333
99
            line += stride;
334
99
  }
335
1.44k
    }
336
18
}
Unexecuted instantiation: pixman-edge-accessors.c:rasterize_edges_8
337
338
#ifndef PIXMAN_FB_ACCESSORS
339
static
340
#endif
341
void
342
PIXMAN_RASTERIZE_EDGES (pixman_image_t *image,
343
                        pixman_edge_t * l,
344
                        pixman_edge_t * r,
345
                        pixman_fixed_t  t,
346
                        pixman_fixed_t  b)
347
18
{
348
18
    switch (PIXMAN_FORMAT_BPP (image->bits.format))
349
18
    {
350
0
    case 1:
351
0
  rasterize_edges_1 (image, l, r, t, b);
352
0
  break;
353
354
0
    case 4:
355
0
  rasterize_edges_4 (image, l, r, t, b);
356
0
  break;
357
358
18
    case 8:
359
18
  rasterize_edges_8 (image, l, r, t, b);
360
18
  break;
361
362
0
    default:
363
0
        break;
364
18
    }
365
18
}
pixman-edge.c:pixman_rasterize_edges_no_accessors
Line
Count
Source
347
18
{
348
18
    switch (PIXMAN_FORMAT_BPP (image->bits.format))
349
18
    {
350
0
    case 1:
351
0
  rasterize_edges_1 (image, l, r, t, b);
352
0
  break;
353
354
0
    case 4:
355
0
  rasterize_edges_4 (image, l, r, t, b);
356
0
  break;
357
358
18
    case 8:
359
18
  rasterize_edges_8 (image, l, r, t, b);
360
18
  break;
361
362
0
    default:
363
0
        break;
364
18
    }
365
18
}
Unexecuted instantiation: pixman_rasterize_edges_accessors
366
367
#ifndef PIXMAN_FB_ACCESSORS
368
369
PIXMAN_EXPORT void
370
pixman_rasterize_edges (pixman_image_t *image,
371
                        pixman_edge_t * l,
372
                        pixman_edge_t * r,
373
                        pixman_fixed_t  t,
374
                        pixman_fixed_t  b)
375
18
{
376
18
    return_if_fail (image->type == BITS);
377
18
    return_if_fail (PIXMAN_FORMAT_TYPE (image->bits.format) == PIXMAN_TYPE_A);
378
    
379
18
    if (image->bits.read_func || image->bits.write_func)
380
0
  pixman_rasterize_edges_accessors (image, l, r, t, b);
381
18
    else
382
18
  pixman_rasterize_edges_no_accessors (image, l, r, t, b);
383
18
}
384
385
#endif