Coverage Report

Created: 2026-08-14 08:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cairo/subprojects/pixman-0.44.2/pixman/pixman.c
Line
Count
Source
1
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
2
/*
3
 * Copyright © 2000 SuSE, Inc.
4
 * Copyright © 2007 Red Hat, Inc.
5
 *
6
 * Permission to use, copy, modify, distribute, and sell this software and its
7
 * documentation for any purpose is hereby granted without fee, provided that
8
 * the above copyright notice appear in all copies and that both that
9
 * copyright notice and this permission notice appear in supporting
10
 * documentation, and that the name of SuSE not be used in advertising or
11
 * publicity pertaining to distribution of the software without specific,
12
 * written prior permission.  SuSE makes no representations about the
13
 * suitability of this software for any purpose.  It is provided "as is"
14
 * without express or implied warranty.
15
 *
16
 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
18
 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
 *
23
 * Author:  Keith Packard, SuSE, Inc.
24
 */
25
26
#ifdef HAVE_CONFIG_H
27
#include <pixman-config.h>
28
#endif
29
#include "pixman-private.h"
30
31
#include <stdlib.h>
32
33
pixman_implementation_t *global_implementation;
34
35
#ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
36
static void __attribute__((constructor))
37
pixman_constructor (void)
38
14
{
39
14
    global_implementation = _pixman_choose_implementation ();
40
14
}
41
#endif
42
43
#ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_DESTRUCTOR
44
static void __attribute__((destructor))
45
pixman_destructor (void)
46
0
{
47
0
    pixman_implementation_t *imp = global_implementation;
48
49
0
    while (imp)
50
0
    {
51
0
        pixman_implementation_t *cur = imp;
52
0
        imp = imp->fallback;
53
0
        free (cur);
54
0
    }
55
0
}
56
#endif
57
58
typedef struct operator_info_t operator_info_t;
59
60
struct operator_info_t
61
{
62
    uint8_t opaque_info[4];
63
};
64
65
#define PACK(neither, src, dest, both)      \
66
    {{      (uint8_t)PIXMAN_OP_ ## neither,   \
67
      (uint8_t)PIXMAN_OP_ ## src,     \
68
      (uint8_t)PIXMAN_OP_ ## dest,    \
69
      (uint8_t)PIXMAN_OP_ ## both   }}
70
71
static const operator_info_t operator_table[] =
72
{
73
    /*    Neither Opaque         Src Opaque             Dst Opaque             Both Opaque */
74
    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
75
    PACK (SRC,                   SRC,                   SRC,                   SRC),
76
    PACK (DST,                   DST,                   DST,                   DST),
77
    PACK (OVER,                  SRC,                   OVER,                  SRC),
78
    PACK (OVER_REVERSE,          OVER_REVERSE,          DST,                   DST),
79
    PACK (IN,                    IN,                    SRC,                   SRC),
80
    PACK (IN_REVERSE,            DST,                   IN_REVERSE,            DST),
81
    PACK (OUT,                   OUT,                   CLEAR,                 CLEAR),
82
    PACK (OUT_REVERSE,           CLEAR,                 OUT_REVERSE,           CLEAR),
83
    PACK (ATOP,                  IN,                    OVER,                  SRC),
84
    PACK (ATOP_REVERSE,          OVER_REVERSE,          IN_REVERSE,            DST),
85
    PACK (XOR,                   OUT,                   OUT_REVERSE,           CLEAR),
86
    PACK (ADD,                   ADD,                   ADD,                   ADD),
87
    PACK (SATURATE,              OVER_REVERSE,          DST,                   DST),
88
89
    {{ 0 /* 0x0e */ }},
90
    {{ 0 /* 0x0f */ }},
91
92
    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
93
    PACK (SRC,                   SRC,                   SRC,                   SRC),
94
    PACK (DST,                   DST,                   DST,                   DST),
95
    PACK (DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER),
96
    PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE),
97
    PACK (DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN),
98
    PACK (DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE),
99
    PACK (DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT),
100
    PACK (DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE),
101
    PACK (DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP),
102
    PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE),
103
    PACK (DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR),
104
105
    {{ 0 /* 0x1c */ }},
106
    {{ 0 /* 0x1d */ }},
107
    {{ 0 /* 0x1e */ }},
108
    {{ 0 /* 0x1f */ }},
109
110
    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
111
    PACK (SRC,                   SRC,                   SRC,                   SRC),
112
    PACK (DST,                   DST,                   DST,                   DST),
113
    PACK (CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER),
114
    PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE),
115
    PACK (CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN),
116
    PACK (CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE),
117
    PACK (CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT),
118
    PACK (CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE),
119
    PACK (CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP),
120
    PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE),
121
    PACK (CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR),
122
123
    {{ 0 /* 0x2c */ }},
124
    {{ 0 /* 0x2d */ }},
125
    {{ 0 /* 0x2e */ }},
126
    {{ 0 /* 0x2f */ }},
127
128
    PACK (MULTIPLY,              MULTIPLY,              MULTIPLY,              MULTIPLY),
129
    PACK (SCREEN,                SCREEN,                SCREEN,                SCREEN),
130
    PACK (OVERLAY,               OVERLAY,               OVERLAY,               OVERLAY),
131
    PACK (DARKEN,                DARKEN,                DARKEN,                DARKEN),
132
    PACK (LIGHTEN,               LIGHTEN,               LIGHTEN,               LIGHTEN),
133
    PACK (COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE),
134
    PACK (COLOR_BURN,            COLOR_BURN,            COLOR_BURN,            COLOR_BURN),
135
    PACK (HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT),
136
    PACK (SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT),
137
    PACK (DIFFERENCE,            DIFFERENCE,            DIFFERENCE,            DIFFERENCE),
138
    PACK (EXCLUSION,             EXCLUSION,             EXCLUSION,             EXCLUSION),
139
    PACK (HSL_HUE,               HSL_HUE,               HSL_HUE,               HSL_HUE),
140
    PACK (HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION),
141
    PACK (HSL_COLOR,             HSL_COLOR,             HSL_COLOR,             HSL_COLOR),
142
    PACK (HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY),
143
};
144
145
/*
146
 * Optimize the current operator based on opacity of source or destination
147
 * The output operator should be mathematically equivalent to the source.
148
 */
149
static pixman_op_t
150
optimize_operator (pixman_op_t     op,
151
       uint32_t        src_flags,
152
       uint32_t        mask_flags,
153
       uint32_t        dst_flags)
154
6.29k
{
155
6.29k
    pixman_bool_t is_source_opaque, is_dest_opaque;
156
157
12.5k
#define OPAQUE_SHIFT 13
158
    
159
6.29k
    COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT));
160
    
161
6.29k
    is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE);
162
6.29k
    is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE);
163
164
6.29k
    is_dest_opaque >>= OPAQUE_SHIFT - 1;
165
6.29k
    is_source_opaque >>= OPAQUE_SHIFT;
166
167
6.29k
    return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
168
6.29k
}
169
170
/*
171
 * Computing composite region
172
 */
173
static inline pixman_bool_t
174
clip_general_image (pixman_region32_t * region,
175
                    pixman_region32_t * clip,
176
                    int                 dx,
177
                    int                 dy)
178
0
{
179
0
    if (pixman_region32_n_rects (region) == 1 &&
180
0
        pixman_region32_n_rects (clip) == 1)
181
0
    {
182
0
  pixman_box32_t *  rbox = pixman_region32_rectangles (region, NULL);
183
0
  pixman_box32_t *  cbox = pixman_region32_rectangles (clip, NULL);
184
0
  int v;
185
186
0
  if (rbox->x1 < (v = cbox->x1 + dx))
187
0
      rbox->x1 = v;
188
0
  if (rbox->x2 > (v = cbox->x2 + dx))
189
0
      rbox->x2 = v;
190
0
  if (rbox->y1 < (v = cbox->y1 + dy))
191
0
      rbox->y1 = v;
192
0
  if (rbox->y2 > (v = cbox->y2 + dy))
193
0
      rbox->y2 = v;
194
0
  if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
195
0
  {
196
0
      pixman_region32_init (region);
197
0
      return FALSE;
198
0
  }
199
0
    }
200
0
    else if (pixman_region32_empty (clip))
201
0
    {
202
0
  return FALSE;
203
0
    }
204
0
    else
205
0
    {
206
0
  if (dx || dy)
207
0
      pixman_region32_translate (region, -dx, -dy);
208
209
0
  if (!pixman_region32_intersect (region, region, clip))
210
0
      return FALSE;
211
212
0
  if (dx || dy)
213
0
      pixman_region32_translate (region, dx, dy);
214
0
    }
215
216
0
    return pixman_region32_not_empty (region);
217
0
}
218
219
static inline pixman_bool_t
220
clip_source_image (pixman_region32_t * region,
221
                   pixman_image_t *    image,
222
                   int                 dx,
223
                   int                 dy)
224
0
{
225
    /* Source clips are ignored, unless they are explicitly turned on
226
     * and the clip in question was set by an X client. (Because if
227
     * the clip was not set by a client, then it is a hierarchy
228
     * clip and those should always be ignored for sources).
229
     */
230
0
    if (!image->common.clip_sources || !image->common.client_clip)
231
0
  return TRUE;
232
233
0
    return clip_general_image (region,
234
0
                               &image->common.clip_region,
235
0
                               dx, dy);
236
0
}
237
238
/*
239
 * returns FALSE if the final region is empty.  Indistinguishable from
240
 * an allocation failure, but rendering ignores those anyways.
241
 */
242
pixman_bool_t
243
_pixman_compute_composite_region32 (pixman_region32_t * region,
244
            pixman_image_t *    src_image,
245
            pixman_image_t *    mask_image,
246
            pixman_image_t *    dest_image,
247
            int32_t             src_x,
248
            int32_t             src_y,
249
            int32_t             mask_x,
250
            int32_t             mask_y,
251
            int32_t             dest_x,
252
            int32_t             dest_y,
253
            int32_t             width,
254
            int32_t             height)
255
6.54k
{
256
6.54k
    region->extents.x1 = dest_x;
257
6.54k
    region->extents.x2 = dest_x + width;
258
6.54k
    region->extents.y1 = dest_y;
259
6.54k
    region->extents.y2 = dest_y + height;
260
261
6.54k
    region->extents.x1 = MAX (region->extents.x1, 0);
262
6.54k
    region->extents.y1 = MAX (region->extents.y1, 0);
263
6.54k
    region->extents.x2 = MIN (region->extents.x2, dest_image->bits.width);
264
6.54k
    region->extents.y2 = MIN (region->extents.y2, dest_image->bits.height);
265
266
6.54k
    region->data = 0;
267
268
    /* Check for empty operation */
269
6.54k
    if (region->extents.x1 >= region->extents.x2 ||
270
6.31k
        region->extents.y1 >= region->extents.y2)
271
228
    {
272
228
  region->extents.x1 = 0;
273
228
  region->extents.x2 = 0;
274
228
  region->extents.y1 = 0;
275
228
  region->extents.y2 = 0;
276
228
  return FALSE;
277
228
    }
278
279
6.31k
    if (dest_image->common.have_clip_region)
280
0
    {
281
0
  if (!clip_general_image (region, &dest_image->common.clip_region, 0, 0))
282
0
      return FALSE;
283
0
    }
284
285
6.31k
    if (dest_image->common.alpha_map)
286
0
    {
287
0
  if (!pixman_region32_intersect_rect (region, region,
288
0
               dest_image->common.alpha_origin_x,
289
0
               dest_image->common.alpha_origin_y,
290
0
               dest_image->common.alpha_map->width,
291
0
               dest_image->common.alpha_map->height))
292
0
  {
293
0
      return FALSE;
294
0
  }
295
0
  if (pixman_region32_empty (region))
296
0
      return FALSE;
297
0
  if (dest_image->common.alpha_map->common.have_clip_region)
298
0
  {
299
0
      if (!clip_general_image (region, &dest_image->common.alpha_map->common.clip_region,
300
0
             -dest_image->common.alpha_origin_x,
301
0
             -dest_image->common.alpha_origin_y))
302
0
      {
303
0
    return FALSE;
304
0
      }
305
0
  }
306
0
    }
307
308
    /* clip against src */
309
6.31k
    if (src_image->common.have_clip_region)
310
0
    {
311
0
  if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
312
0
      return FALSE;
313
0
    }
314
6.31k
    if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
315
0
    {
316
0
  if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
317
0
                          dest_x - (src_x - src_image->common.alpha_origin_x),
318
0
                          dest_y - (src_y - src_image->common.alpha_origin_y)))
319
0
  {
320
0
      return FALSE;
321
0
  }
322
0
    }
323
    /* clip against mask */
324
6.31k
    if (mask_image && mask_image->common.have_clip_region)
325
0
    {
326
0
  if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
327
0
      return FALSE;
328
329
0
  if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
330
0
  {
331
0
      if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
332
0
                              dest_x - (mask_x - mask_image->common.alpha_origin_x),
333
0
                              dest_y - (mask_y - mask_image->common.alpha_origin_y)))
334
0
      {
335
0
    return FALSE;
336
0
      }
337
0
  }
338
0
    }
339
340
6.31k
    return TRUE;
341
6.31k
}
342
343
typedef struct box_48_16 box_48_16_t;
344
345
struct box_48_16
346
{
347
    pixman_fixed_48_16_t        x1;
348
    pixman_fixed_48_16_t        y1;
349
    pixman_fixed_48_16_t        x2;
350
    pixman_fixed_48_16_t        y2;
351
};
352
353
static pixman_bool_t
354
compute_transformed_extents (pixman_transform_t   *transform,
355
           const pixman_box32_t *extents,
356
           box_48_16_t          *transformed)
357
18.3k
{
358
18.3k
    pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
359
18.3k
    pixman_fixed_t x1, y1, x2, y2;
360
18.3k
    int i;
361
362
18.3k
    x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2;
363
18.3k
    y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2;
364
18.3k
    x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2;
365
18.3k
    y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2;
366
367
18.3k
    if (!transform)
368
6.94k
    {
369
6.94k
  transformed->x1 = x1;
370
6.94k
  transformed->y1 = y1;
371
6.94k
  transformed->x2 = x2;
372
6.94k
  transformed->y2 = y2;
373
374
6.94k
  return TRUE;
375
6.94k
    }
376
377
11.3k
    tx1 = ty1 = INT64_MAX;
378
11.3k
    tx2 = ty2 = INT64_MIN;
379
380
56.8k
    for (i = 0; i < 4; ++i)
381
45.4k
    {
382
45.4k
  pixman_fixed_48_16_t tx, ty;
383
45.4k
  pixman_vector_t v;
384
385
45.4k
  v.vector[0] = (i & 0x01)? x1 : x2;
386
45.4k
  v.vector[1] = (i & 0x02)? y1 : y2;
387
45.4k
  v.vector[2] = pixman_fixed_1;
388
389
45.4k
  if (!pixman_transform_point (transform, &v))
390
0
      return FALSE;
391
392
45.4k
  tx = (pixman_fixed_48_16_t)v.vector[0];
393
45.4k
  ty = (pixman_fixed_48_16_t)v.vector[1];
394
395
45.4k
  if (tx < tx1)
396
22.1k
      tx1 = tx;
397
45.4k
  if (ty < ty1)
398
21.6k
      ty1 = ty;
399
45.4k
  if (tx > tx2)
400
12.4k
      tx2 = tx;
401
45.4k
  if (ty > ty2)
402
12.5k
      ty2 = ty;
403
45.4k
    }
404
405
11.3k
    transformed->x1 = tx1;
406
11.3k
    transformed->y1 = ty1;
407
11.3k
    transformed->x2 = tx2;
408
11.3k
    transformed->y2 = ty2;
409
410
11.3k
    return TRUE;
411
11.3k
}
412
413
81.9k
#define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
414
#define ABS(f)      (((f) < 0)?  (-(f)) : (f))
415
64.1k
#define IS_16_16(f) (((f) >= pixman_min_fixed_48_16 && ((f) <= pixman_max_fixed_48_16)))
416
417
static pixman_bool_t
418
analyze_extent (pixman_image_t       *image,
419
    const pixman_box32_t *extents,
420
    uint32_t             *flags)
421
12.5k
{
422
12.5k
    pixman_transform_t *transform;
423
12.5k
    pixman_fixed_t x_off, y_off;
424
12.5k
    pixman_fixed_t width, height;
425
12.5k
    pixman_fixed_t *params;
426
12.5k
    box_48_16_t transformed;
427
12.5k
    pixman_box32_t exp_extents;
428
429
12.5k
    if (!image)
430
890
  return TRUE;
431
432
    /* Some compositing functions walk one step
433
     * outside the destination rectangle, so we
434
     * check here that the expanded-by-one source
435
     * extents in destination space fits in 16 bits
436
     */
437
11.7k
    if (!IS_16BIT (extents->x1 - 1)    ||
438
11.7k
  !IS_16BIT (extents->y1 - 1)    ||
439
11.7k
  !IS_16BIT (extents->x2 + 1)    ||
440
11.7k
  !IS_16BIT (extents->y2 + 1))
441
0
    {
442
0
  return FALSE;
443
0
    }
444
445
11.7k
    transform = image->common.transform;
446
11.7k
    if (image->common.type == BITS)
447
7.03k
    {
448
  /* During repeat mode calculations we might convert the
449
   * width/height of an image to fixed 16.16, so we need
450
   * them to be smaller than 16 bits.
451
   */
452
7.03k
  if (image->bits.width >= 0x7fff  || image->bits.height >= 0x7fff)
453
0
      return FALSE;
454
455
7.03k
  if ((image->common.flags & FAST_PATH_ID_TRANSFORM) == FAST_PATH_ID_TRANSFORM &&
456
2.56k
      extents->x1 >= 0 &&
457
2.55k
      extents->y1 >= 0 &&
458
2.55k
      extents->x2 <= image->bits.width &&
459
2.54k
      extents->y2 <= image->bits.height)
460
2.54k
  {
461
2.54k
      *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
462
2.54k
      return TRUE;
463
2.54k
  }
464
465
4.48k
  switch (image->common.filter)
466
4.48k
  {
467
0
  case PIXMAN_FILTER_CONVOLUTION:
468
0
      params = image->common.filter_params;
469
0
      x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
470
0
      y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
471
0
      width = params[0];
472
0
      height = params[1];
473
0
      break;
474
475
0
  case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
476
0
      params = image->common.filter_params;
477
0
      x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
478
0
      y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
479
0
      width = params[0];
480
0
      height = params[1];
481
0
      break;
482
      
483
0
  case PIXMAN_FILTER_GOOD:
484
0
  case PIXMAN_FILTER_BEST:
485
26
  case PIXMAN_FILTER_BILINEAR:
486
26
      x_off = - pixman_fixed_1 / 2;
487
26
      y_off = - pixman_fixed_1 / 2;
488
26
      width = pixman_fixed_1;
489
26
      height = pixman_fixed_1;
490
26
      break;
491
492
0
  case PIXMAN_FILTER_FAST:
493
4.45k
  case PIXMAN_FILTER_NEAREST:
494
4.45k
      x_off = - pixman_fixed_e;
495
4.45k
      y_off = - pixman_fixed_e;
496
4.45k
      width = 0;
497
4.45k
      height = 0;
498
4.45k
      break;
499
500
0
  default:
501
0
      return FALSE;
502
4.48k
  }
503
4.48k
    }
504
4.67k
    else
505
4.67k
    {
506
4.67k
  x_off = 0;
507
4.67k
  y_off = 0;
508
4.67k
  width = 0;
509
4.67k
  height = 0;
510
4.67k
    }
511
512
9.15k
    if (!compute_transformed_extents (transform, extents, &transformed))
513
0
  return FALSE;
514
515
9.15k
    if (image->common.type == BITS)
516
4.48k
    {
517
4.48k
  if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_e) >= 0                &&
518
4.26k
      pixman_fixed_to_int (transformed.y1 - pixman_fixed_e) >= 0                &&
519
4.19k
      pixman_fixed_to_int (transformed.x2 - pixman_fixed_e) < image->bits.width &&
520
4.14k
      pixman_fixed_to_int (transformed.y2 - pixman_fixed_e) < image->bits.height)
521
3.90k
  {
522
3.90k
      *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
523
3.90k
  }
524
525
4.48k
  if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_1 / 2) >= 0      &&
526
3.05k
      pixman_fixed_to_int (transformed.y1 - pixman_fixed_1 / 2) >= 0      &&
527
2.70k
      pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2) < image->bits.width &&
528
2.43k
      pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2) < image->bits.height)
529
2.20k
  {
530
2.20k
      *flags |= FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR;
531
2.20k
  }
532
4.48k
    }
533
534
    /* Check we don't overflow when the destination extents are expanded by one.
535
     * This ensures that compositing functions can simply walk the source space
536
     * using 16.16 variables without worrying about overflow.
537
     */
538
9.15k
    exp_extents = *extents;
539
9.15k
    exp_extents.x1 -= 1;
540
9.15k
    exp_extents.y1 -= 1;
541
9.15k
    exp_extents.x2 += 1;
542
9.15k
    exp_extents.y2 += 1;
543
544
9.15k
    if (!compute_transformed_extents (transform, &exp_extents, &transformed))
545
0
  return FALSE;
546
    
547
9.15k
    if (!IS_16_16 (transformed.x1 + x_off - 8 * pixman_fixed_e)  ||
548
9.15k
  !IS_16_16 (transformed.y1 + y_off - 8 * pixman_fixed_e)  ||
549
9.15k
  !IS_16_16 (transformed.x2 + x_off + 8 * pixman_fixed_e + width)  ||
550
9.15k
  !IS_16_16 (transformed.y2 + y_off + 8 * pixman_fixed_e + height))
551
0
    {
552
0
  return FALSE;
553
0
    }
554
555
9.15k
    return TRUE;
556
9.15k
}
557
558
/*
559
 * Work around GCC bug causing crashes in Mozilla with SSE2
560
 *
561
 * When using -msse, gcc generates movdqa instructions assuming that
562
 * the stack is 16 byte aligned. Unfortunately some applications, such
563
 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
564
 * causes the movdqa instructions to fail.
565
 *
566
 * The __force_align_arg_pointer__ makes gcc generate a prologue that
567
 * realigns the stack pointer to 16 bytes.
568
 *
569
 * On x86-64 this is not necessary because the standard ABI already
570
 * calls for a 16 byte aligned stack.
571
 *
572
 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
573
 */
574
#if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
575
__attribute__((__force_align_arg_pointer__))
576
#endif
577
PIXMAN_EXPORT void
578
pixman_image_composite32 (pixman_op_t      op,
579
                          pixman_image_t * src,
580
                          pixman_image_t * mask,
581
                          pixman_image_t * dest,
582
                          int32_t          src_x,
583
                          int32_t          src_y,
584
                          int32_t          mask_x,
585
                          int32_t          mask_y,
586
                          int32_t          dest_x,
587
                          int32_t          dest_y,
588
                          int32_t          width,
589
                          int32_t          height)
590
6.52k
{
591
6.52k
    pixman_format_code_t src_format, mask_format, dest_format;
592
6.52k
    pixman_region32_t region;
593
6.52k
    pixman_box32_t extents;
594
6.52k
    pixman_implementation_t *imp;
595
6.52k
    pixman_composite_func_t func;
596
6.52k
    pixman_composite_info_t info;
597
6.52k
    const pixman_box32_t *pbox;
598
6.52k
    int n;
599
600
6.52k
    _pixman_image_validate (src);
601
6.52k
    if (mask)
602
5.40k
  _pixman_image_validate (mask);
603
6.52k
    _pixman_image_validate (dest);
604
605
6.52k
    src_format = src->common.extended_format_code;
606
6.52k
    info.src_flags = src->common.flags;
607
608
6.52k
    if (mask && !(mask->common.flags & FAST_PATH_IS_OPAQUE))
609
5.39k
    {
610
5.39k
  mask_format = mask->common.extended_format_code;
611
5.39k
  info.mask_flags = mask->common.flags;
612
5.39k
    }
613
1.13k
    else
614
1.13k
    {
615
1.13k
  mask_format = PIXMAN_null;
616
1.13k
  info.mask_flags = FAST_PATH_IS_OPAQUE | FAST_PATH_NO_ALPHA_MAP;
617
1.13k
    }
618
619
6.52k
    dest_format = dest->common.extended_format_code;
620
6.52k
    info.dest_flags = dest->common.flags;
621
622
    /* Check for pixbufs */
623
6.52k
    if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
624
8
  (src->type == BITS && src->bits.bits == mask->bits.bits)     &&
625
0
  (src->common.repeat == mask->common.repeat)         &&
626
0
  (info.src_flags & info.mask_flags & FAST_PATH_ID_TRANSFORM)    &&
627
0
  (src_x == mask_x && src_y == mask_y))
628
0
    {
629
0
  if (src_format == PIXMAN_x8b8g8r8)
630
0
      src_format = mask_format = PIXMAN_pixbuf;
631
0
  else if (src_format == PIXMAN_x8r8g8b8)
632
0
      src_format = mask_format = PIXMAN_rpixbuf;
633
0
    }
634
635
6.52k
    pixman_region32_init (&region);
636
637
6.52k
    if (!_pixman_compute_composite_region32 (
638
6.52k
      &region, src, mask, dest,
639
6.52k
      src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
640
228
    {
641
228
  goto out;
642
228
    }
643
644
6.29k
    extents = *pixman_region32_extents (&region);
645
646
6.29k
    extents.x1 -= dest_x - src_x;
647
6.29k
    extents.y1 -= dest_y - src_y;
648
6.29k
    extents.x2 -= dest_x - src_x;
649
6.29k
    extents.y2 -= dest_y - src_y;
650
651
6.29k
    if (!analyze_extent (src, &extents, &info.src_flags))
652
0
  goto out;
653
654
6.29k
    extents.x1 -= src_x - mask_x;
655
6.29k
    extents.y1 -= src_y - mask_y;
656
6.29k
    extents.x2 -= src_x - mask_x;
657
6.29k
    extents.y2 -= src_y - mask_y;
658
659
6.29k
    if (!analyze_extent (mask, &extents, &info.mask_flags))
660
0
  goto out;
661
662
    /* If the clip is within the source samples, and the samples are
663
     * opaque, then the source is effectively opaque.
664
     */
665
37.7k
#define NEAREST_OPAQUE  (FAST_PATH_SAMPLES_OPAQUE |      \
666
37.7k
       FAST_PATH_NEAREST_FILTER |      \
667
37.7k
       FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
668
23.0k
#define BILINEAR_OPAQUE (FAST_PATH_SAMPLES_OPAQUE |      \
669
23.0k
       FAST_PATH_BILINEAR_FILTER |      \
670
23.0k
       FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR)
671
672
6.29k
    if ((info.src_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
673
5.23k
  (info.src_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
674
1.05k
    {
675
1.05k
  info.src_flags |= FAST_PATH_IS_OPAQUE;
676
1.05k
    }
677
678
6.29k
    if ((info.mask_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
679
6.29k
  (info.mask_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
680
0
    {
681
0
  info.mask_flags |= FAST_PATH_IS_OPAQUE;
682
0
    }
683
684
    /*
685
     * Check if we can replace our operator by a simpler one
686
     * if the src or dest are opaque. The output operator should be
687
     * mathematically equivalent to the source.
688
     */
689
6.29k
    info.op = optimize_operator (op, info.src_flags, info.mask_flags, info.dest_flags);
690
691
6.29k
    _pixman_implementation_lookup_composite (
692
6.29k
  get_implementation (), info.op,
693
6.29k
  src_format, info.src_flags,
694
6.29k
  mask_format, info.mask_flags,
695
6.29k
  dest_format, info.dest_flags,
696
6.29k
  &imp, &func);
697
698
6.29k
    info.src_image = src;
699
6.29k
    info.mask_image = mask;
700
6.29k
    info.dest_image = dest;
701
702
6.29k
    pbox = pixman_region32_rectangles (&region, &n);
703
704
12.5k
    while (n--)
705
6.29k
    {
706
6.29k
  info.src_x = pbox->x1 + src_x - dest_x;
707
6.29k
  info.src_y = pbox->y1 + src_y - dest_y;
708
6.29k
  info.mask_x = pbox->x1 + mask_x - dest_x;
709
6.29k
  info.mask_y = pbox->y1 + mask_y - dest_y;
710
6.29k
  info.dest_x = pbox->x1;
711
6.29k
  info.dest_y = pbox->y1;
712
6.29k
  info.width = pbox->x2 - pbox->x1;
713
6.29k
  info.height = pbox->y2 - pbox->y1;
714
715
6.29k
  func (imp, &info);
716
717
6.29k
  pbox++;
718
6.29k
    }
719
720
6.52k
out:
721
6.52k
    pixman_region32_fini (&region);
722
6.52k
}
723
724
PIXMAN_EXPORT void
725
pixman_image_composite (pixman_op_t      op,
726
                        pixman_image_t * src,
727
                        pixman_image_t * mask,
728
                        pixman_image_t * dest,
729
                        int16_t          src_x,
730
                        int16_t          src_y,
731
                        int16_t          mask_x,
732
                        int16_t          mask_y,
733
                        int16_t          dest_x,
734
                        int16_t          dest_y,
735
                        uint16_t         width,
736
                        uint16_t         height)
737
0
{
738
0
    pixman_image_composite32 (op, src, mask, dest, src_x, src_y, 
739
0
                              mask_x, mask_y, dest_x, dest_y, width, height);
740
0
}
741
742
PIXMAN_EXPORT pixman_bool_t
743
pixman_blt (uint32_t *src_bits,
744
            uint32_t *dst_bits,
745
            int       src_stride,
746
            int       dst_stride,
747
            int       src_bpp,
748
            int       dst_bpp,
749
            int       src_x,
750
            int       src_y,
751
            int       dest_x,
752
            int       dest_y,
753
            int       width,
754
            int       height)
755
0
{
756
0
    return _pixman_implementation_blt (get_implementation(),
757
0
               src_bits, dst_bits, src_stride, dst_stride,
758
0
                                       src_bpp, dst_bpp,
759
0
                                       src_x, src_y,
760
0
                                       dest_x, dest_y,
761
0
                                       width, height);
762
0
}
763
764
PIXMAN_EXPORT pixman_bool_t
765
pixman_fill (uint32_t *bits,
766
             int       stride,
767
             int       bpp,
768
             int       x,
769
             int       y,
770
             int       width,
771
             int       height,
772
             uint32_t  filler)
773
846
{
774
846
    return _pixman_implementation_fill (
775
846
  get_implementation(), bits, stride, bpp, x, y, width, height, filler);
776
846
}
777
778
static uint32_t
779
color_to_uint32 (const pixman_color_t *color)
780
0
{
781
0
    return
782
0
        (color->alpha >> 8 << 24) |
783
0
        (color->red >> 8 << 16) |
784
0
        (color->green & 0xff00) |
785
0
        (color->blue >> 8);
786
0
}
787
788
static pixman_bool_t
789
color_to_pixel (const pixman_color_t *color,
790
                uint32_t *            pixel,
791
                pixman_format_code_t  format)
792
0
{
793
0
    uint32_t c = color_to_uint32 (color);
794
795
0
    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA_FLOAT)
796
0
    {
797
0
  return FALSE;
798
0
    }
799
800
0
    if (!(format == PIXMAN_a8r8g8b8     ||
801
0
          format == PIXMAN_x8r8g8b8     ||
802
0
          format == PIXMAN_a8b8g8r8     ||
803
0
          format == PIXMAN_x8b8g8r8     ||
804
0
          format == PIXMAN_b8g8r8a8     ||
805
0
          format == PIXMAN_b8g8r8x8     ||
806
0
          format == PIXMAN_r8g8b8a8     ||
807
0
          format == PIXMAN_r8g8b8x8     ||
808
0
          format == PIXMAN_r5g6b5       ||
809
0
          format == PIXMAN_b5g6r5       ||
810
0
          format == PIXMAN_a8           ||
811
0
          format == PIXMAN_a1))
812
0
    {
813
0
  return FALSE;
814
0
    }
815
816
0
    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
817
0
    {
818
0
  c = ((c & 0xff000000) >>  0) |
819
0
      ((c & 0x00ff0000) >> 16) |
820
0
      ((c & 0x0000ff00) >>  0) |
821
0
      ((c & 0x000000ff) << 16);
822
0
    }
823
0
    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
824
0
    {
825
0
  c = ((c & 0xff000000) >> 24) |
826
0
      ((c & 0x00ff0000) >>  8) |
827
0
      ((c & 0x0000ff00) <<  8) |
828
0
      ((c & 0x000000ff) << 24);
829
0
    }
830
0
    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA)
831
0
  c = ((c & 0xff000000) >> 24) | (c << 8);
832
833
0
    if (format == PIXMAN_a1)
834
0
  c = c >> 31;
835
0
    else if (format == PIXMAN_a8)
836
0
  c = c >> 24;
837
0
    else if (format == PIXMAN_r5g6b5 ||
838
0
             format == PIXMAN_b5g6r5)
839
0
  c = convert_8888_to_0565 (c);
840
841
#if 0
842
    printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
843
    printf ("pixel: %x\n", c);
844
#endif
845
846
0
    *pixel = c;
847
0
    return TRUE;
848
0
}
849
850
PIXMAN_EXPORT pixman_bool_t
851
pixman_image_fill_rectangles (pixman_op_t                 op,
852
                              pixman_image_t *            dest,
853
            const pixman_color_t *      color,
854
                              int                         n_rects,
855
                              const pixman_rectangle16_t *rects)
856
0
{
857
0
    pixman_box32_t stack_boxes[6];
858
0
    pixman_box32_t *boxes;
859
0
    pixman_bool_t result;
860
0
    int i;
861
862
0
    if (n_rects > 6)
863
0
    {
864
0
        boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
865
0
        if (boxes == NULL)
866
0
            return FALSE;
867
0
    }
868
0
    else
869
0
    {
870
0
        boxes = stack_boxes;
871
0
    }
872
873
0
    for (i = 0; i < n_rects; ++i)
874
0
    {
875
0
        boxes[i].x1 = rects[i].x;
876
0
        boxes[i].y1 = rects[i].y;
877
0
        boxes[i].x2 = boxes[i].x1 + rects[i].width;
878
0
        boxes[i].y2 = boxes[i].y1 + rects[i].height;
879
0
    }
880
881
0
    result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
882
883
0
    if (boxes != stack_boxes)
884
0
        free (boxes);
885
    
886
0
    return result;
887
0
}
888
889
PIXMAN_EXPORT pixman_bool_t
890
pixman_image_fill_boxes (pixman_op_t           op,
891
                         pixman_image_t *      dest,
892
                         const pixman_color_t *color,
893
                         int                   n_boxes,
894
                         const pixman_box32_t *boxes)
895
0
{
896
0
    pixman_image_t *solid;
897
0
    pixman_color_t c;
898
0
    int i;
899
900
0
    _pixman_image_validate (dest);
901
    
902
0
    if (color->alpha == 0xffff)
903
0
    {
904
0
        if (op == PIXMAN_OP_OVER)
905
0
            op = PIXMAN_OP_SRC;
906
0
    }
907
908
0
    if (op == PIXMAN_OP_CLEAR)
909
0
    {
910
0
        c.red = 0;
911
0
        c.green = 0;
912
0
        c.blue = 0;
913
0
        c.alpha = 0;
914
915
0
        color = &c;
916
917
0
        op = PIXMAN_OP_SRC;
918
0
    }
919
920
0
    if (op == PIXMAN_OP_SRC)
921
0
    {
922
0
        uint32_t pixel;
923
924
0
        if (color_to_pixel (color, &pixel, dest->bits.format))
925
0
        {
926
0
            pixman_region32_t fill_region;
927
0
            int n_rects, j;
928
0
            pixman_box32_t *rects;
929
930
0
            if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
931
0
                return FALSE;
932
933
0
            if (dest->common.have_clip_region)
934
0
            {
935
0
                if (!pixman_region32_intersect (&fill_region,
936
0
                                                &fill_region,
937
0
                                                &dest->common.clip_region))
938
0
                    return FALSE;
939
0
            }
940
941
0
            rects = pixman_region32_rectangles (&fill_region, &n_rects);
942
0
            for (j = 0; j < n_rects; ++j)
943
0
            {
944
0
                const pixman_box32_t *rect = &(rects[j]);
945
0
                pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
946
0
                             rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
947
0
                             pixel);
948
0
            }
949
950
0
            pixman_region32_fini (&fill_region);
951
0
            return TRUE;
952
0
        }
953
0
    }
954
955
0
    solid = pixman_image_create_solid_fill (color);
956
0
    if (!solid)
957
0
        return FALSE;
958
959
0
    for (i = 0; i < n_boxes; ++i)
960
0
    {
961
0
        const pixman_box32_t *box = &(boxes[i]);
962
963
0
        pixman_image_composite32 (op, solid, NULL, dest,
964
0
                                  0, 0, 0, 0,
965
0
                                  box->x1, box->y1,
966
0
                                  box->x2 - box->x1, box->y2 - box->y1);
967
0
    }
968
969
0
    pixman_image_unref (solid);
970
971
0
    return TRUE;
972
0
}
973
974
/**
975
 * pixman_version:
976
 *
977
 * Returns the version of the pixman library encoded in a single
978
 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
979
 * later versions compare greater than earlier versions.
980
 *
981
 * A run-time comparison to check that pixman's version is greater than
982
 * or equal to version X.Y.Z could be performed as follows:
983
 *
984
 * <informalexample><programlisting>
985
 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
986
 * </programlisting></informalexample>
987
 *
988
 * See also pixman_version_string() as well as the compile-time
989
 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
990
 *
991
 * Return value: the encoded version.
992
 **/
993
PIXMAN_EXPORT int
994
pixman_version (void)
995
0
{
996
0
    return PIXMAN_VERSION;
997
0
}
998
999
/**
1000
 * pixman_version_string:
1001
 *
1002
 * Returns the version of the pixman library as a human-readable string
1003
 * of the form "X.Y.Z".
1004
 *
1005
 * See also pixman_version() as well as the compile-time equivalents
1006
 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
1007
 *
1008
 * Return value: a string containing the version.
1009
 **/
1010
PIXMAN_EXPORT const char*
1011
pixman_version_string (void)
1012
0
{
1013
0
    return PIXMAN_VERSION_STRING;
1014
0
}
1015
1016
/**
1017
 * pixman_format_supported_source:
1018
 * @format: A pixman_format_code_t format
1019
 *
1020
 * Return value: whether the provided format code is a supported
1021
 * format for a pixman surface used as a source in
1022
 * rendering.
1023
 *
1024
 * Currently, all pixman_format_code_t values are supported.
1025
 **/
1026
PIXMAN_EXPORT pixman_bool_t
1027
pixman_format_supported_source (pixman_format_code_t format)
1028
0
{
1029
0
    switch (format)
1030
0
    {
1031
    /* 32 bpp formats */
1032
0
    case PIXMAN_a2b10g10r10:
1033
0
    case PIXMAN_x2b10g10r10:
1034
0
    case PIXMAN_a2r10g10b10:
1035
0
    case PIXMAN_x2r10g10b10:
1036
0
    case PIXMAN_a8r8g8b8:
1037
0
    case PIXMAN_a8r8g8b8_sRGB:
1038
0
    case PIXMAN_r8g8b8_sRGB:
1039
0
    case PIXMAN_x8r8g8b8:
1040
0
    case PIXMAN_a8b8g8r8:
1041
0
    case PIXMAN_x8b8g8r8:
1042
0
    case PIXMAN_b8g8r8a8:
1043
0
    case PIXMAN_b8g8r8x8:
1044
0
    case PIXMAN_r8g8b8a8:
1045
0
    case PIXMAN_r8g8b8x8:
1046
0
    case PIXMAN_r8g8b8:
1047
0
    case PIXMAN_b8g8r8:
1048
0
    case PIXMAN_r5g6b5:
1049
0
    case PIXMAN_b5g6r5:
1050
0
    case PIXMAN_x14r6g6b6:
1051
    /* 16 bpp formats */
1052
0
    case PIXMAN_a1r5g5b5:
1053
0
    case PIXMAN_x1r5g5b5:
1054
0
    case PIXMAN_a1b5g5r5:
1055
0
    case PIXMAN_x1b5g5r5:
1056
0
    case PIXMAN_a4r4g4b4:
1057
0
    case PIXMAN_x4r4g4b4:
1058
0
    case PIXMAN_a4b4g4r4:
1059
0
    case PIXMAN_x4b4g4r4:
1060
    /* 8bpp formats */
1061
0
    case PIXMAN_a8:
1062
0
    case PIXMAN_r3g3b2:
1063
0
    case PIXMAN_b2g3r3:
1064
0
    case PIXMAN_a2r2g2b2:
1065
0
    case PIXMAN_a2b2g2r2:
1066
0
    case PIXMAN_c8:
1067
0
    case PIXMAN_g8:
1068
0
    case PIXMAN_x4a4:
1069
    /* Collides with PIXMAN_c8
1070
       case PIXMAN_x4c4:
1071
     */
1072
    /* Collides with PIXMAN_g8
1073
       case PIXMAN_x4g4:
1074
     */
1075
    /* 4bpp formats */
1076
0
    case PIXMAN_a4:
1077
0
    case PIXMAN_r1g2b1:
1078
0
    case PIXMAN_b1g2r1:
1079
0
    case PIXMAN_a1r1g1b1:
1080
0
    case PIXMAN_a1b1g1r1:
1081
0
    case PIXMAN_c4:
1082
0
    case PIXMAN_g4:
1083
    /* 1bpp formats */
1084
0
    case PIXMAN_a1:
1085
0
    case PIXMAN_g1:
1086
    /* YUV formats */
1087
0
    case PIXMAN_yuy2:
1088
0
    case PIXMAN_yv12:
1089
0
  return TRUE;
1090
1091
0
    default:
1092
0
  return FALSE;
1093
0
    }
1094
0
}
1095
1096
/**
1097
 * pixman_format_supported_destination:
1098
 * @format: A pixman_format_code_t format
1099
 *
1100
 * Return value: whether the provided format code is a supported
1101
 * format for a pixman surface used as a destination in
1102
 * rendering.
1103
 *
1104
 * Currently, all pixman_format_code_t values are supported
1105
 * except for the YUV formats.
1106
 **/
1107
PIXMAN_EXPORT pixman_bool_t
1108
pixman_format_supported_destination (pixman_format_code_t format)
1109
0
{
1110
    /* YUV formats cannot be written to at the moment */
1111
0
    if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1112
0
  return FALSE;
1113
1114
0
    return pixman_format_supported_source (format);
1115
0
}
1116
1117
PIXMAN_EXPORT pixman_bool_t
1118
pixman_compute_composite_region (pixman_region16_t * region,
1119
                                 pixman_image_t *    src_image,
1120
                                 pixman_image_t *    mask_image,
1121
                                 pixman_image_t *    dest_image,
1122
                                 int16_t             src_x,
1123
                                 int16_t             src_y,
1124
                                 int16_t             mask_x,
1125
                                 int16_t             mask_y,
1126
                                 int16_t             dest_x,
1127
                                 int16_t             dest_y,
1128
                                 uint16_t            width,
1129
                                 uint16_t            height)
1130
0
{
1131
0
    pixman_region32_t r32;
1132
0
    pixman_bool_t retval;
1133
1134
0
    pixman_region32_init (&r32);
1135
1136
0
    retval = _pixman_compute_composite_region32 (
1137
0
  &r32, src_image, mask_image, dest_image,
1138
0
  src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1139
0
  width, height);
1140
1141
0
    if (retval)
1142
0
    {
1143
0
  if (!pixman_region16_copy_from_region32 (region, &r32))
1144
0
      retval = FALSE;
1145
0
    }
1146
1147
0
    pixman_region32_fini (&r32);
1148
0
    return retval;
1149
0
}