Coverage Report

Created: 2025-07-07 10:01

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