~ubuntu-branches/ubuntu/saucy/pixman/saucy-security

« back to all changes in this revision

Viewing changes to pixman/pixman-utils.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Cristau
  • Date: 2009-09-28 18:12:47 UTC
  • mfrom: (1.1.8 upstream) (2.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090928181247-3iehog63i50htejf
Tags: 0.16.2-1
* New upstream release (closes: #546849).
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Copyright © 2000 SuSE, Inc.
 
3
 * Copyright © 1999 Keith Packard
3
4
 *
4
5
 * Permission to use, copy, modify, distribute, and sell this software and its
5
6
 * documentation for any purpose is hereby granted without fee, provided that
24
25
#ifdef HAVE_CONFIG_H
25
26
#include <config.h>
26
27
#endif
27
 
 
 
28
#include <stdio.h>
28
29
#include <stdlib.h>
29
30
 
30
31
#include "pixman-private.h"
31
 
#include "pixman-mmx.h"
32
 
#include "pixman-sse2.h"
33
 
 
34
 
#if defined(USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
35
 
__attribute__((__force_align_arg_pointer__))
36
 
#endif
37
 
PIXMAN_EXPORT pixman_bool_t
38
 
pixman_blt (uint32_t *src_bits,
39
 
            uint32_t *dst_bits,
40
 
            int src_stride,
41
 
            int dst_stride,
42
 
            int src_bpp,
43
 
            int dst_bpp,
44
 
            int src_x, int src_y,
45
 
            int dst_x, int dst_y,
46
 
            int width, int height)
47
 
{
48
 
#ifdef USE_SSE2
49
 
    if (pixman_have_sse2())
50
 
    {
51
 
        return pixmanBltsse2 (src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
52
 
                              src_x, src_y, dst_x, dst_y, width, height);
53
 
    }
54
 
    else
55
 
#endif
56
 
#ifdef USE_MMX
57
 
    if (pixman_have_mmx())
58
 
    {
59
 
        return pixman_blt_mmx (src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
60
 
                               src_x, src_y, dst_x, dst_y, width, height);
61
 
    }
62
 
    else
63
 
#endif
64
 
        return FALSE;
65
 
}
66
 
 
67
 
static void
68
 
pixman_fill8 (uint32_t  *bits,
69
 
              int       stride,
70
 
              int       x,
71
 
              int       y,
72
 
              int       width,
73
 
              int       height,
74
 
              uint32_t  xor)
75
 
{
76
 
    int byte_stride = stride * (int) sizeof (uint32_t);
77
 
    uint8_t *dst = (uint8_t *) bits;
78
 
    uint8_t v = xor & 0xff;
79
 
    int i;
80
 
 
81
 
    dst = dst + y * byte_stride + x;
82
 
 
83
 
    while (height--)
84
 
    {
85
 
        for (i = 0; i < width; ++i)
86
 
            dst[i] = v;
87
 
 
88
 
        dst += byte_stride;
89
 
    }
90
 
}
91
 
 
92
 
static void
93
 
pixman_fill16 (uint32_t *bits,
94
 
               int       stride,
95
 
               int       x,
96
 
               int       y,
97
 
               int       width,
98
 
               int       height,
99
 
               uint32_t  xor)
100
 
{
101
 
    int short_stride = (stride * (int) sizeof (uint32_t)) / (int) sizeof (uint16_t);
102
 
    uint16_t *dst = (uint16_t *)bits;
103
 
    uint16_t v = xor & 0xffff;
104
 
    int i;
105
 
 
106
 
    dst = dst + y * short_stride + x;
107
 
 
108
 
    while (height--)
109
 
    {
110
 
        for (i = 0; i < width; ++i)
111
 
            dst[i] = v;
112
 
 
113
 
        dst += short_stride;
114
 
    }
115
 
}
116
 
 
117
 
static void
118
 
pixman_fill32 (uint32_t *bits,
119
 
               int       stride,
120
 
               int       x,
121
 
               int       y,
122
 
               int       width,
123
 
               int       height,
124
 
               uint32_t  xor)
125
 
{
126
 
    int i;
127
 
 
128
 
    bits = bits + y * stride + x;
129
 
 
130
 
    while (height--)
131
 
    {
132
 
        for (i = 0; i < width; ++i)
133
 
            bits[i] = xor;
134
 
 
135
 
        bits += stride;
136
 
    }
137
 
}
138
 
 
139
 
#if defined(USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
140
 
__attribute__((__force_align_arg_pointer__))
141
 
#endif
142
 
PIXMAN_EXPORT pixman_bool_t
143
 
pixman_fill (uint32_t *bits,
144
 
             int stride,
145
 
             int bpp,
146
 
             int x,
147
 
             int y,
148
 
             int width,
149
 
             int height,
150
 
             uint32_t xor)
151
 
{
152
 
#if 0
153
 
    printf ("filling: %d %d %d %d (stride: %d, bpp: %d)   pixel: %x\n",
154
 
            x, y, width, height, stride, bpp, xor);
155
 
#endif
156
 
 
157
 
#ifdef USE_SSE2
158
 
    if (pixman_have_sse2() && pixmanFillsse2 (bits, stride, bpp, x, y, width, height, xor))
159
 
        return TRUE;
160
 
#endif
161
 
 
162
 
#ifdef USE_MMX
163
 
    if (pixman_have_mmx() && pixman_fill_mmx (bits, stride, bpp, x, y, width, height, xor))
164
 
        return TRUE;
165
 
#endif
166
 
    
167
 
    switch (bpp)
168
 
    {
169
 
    case 8:
170
 
        pixman_fill8 (bits, stride, x, y, width, height, xor);
171
 
        break;
172
 
        
173
 
    case 16:
174
 
        pixman_fill16 (bits, stride, x, y, width, height, xor);
175
 
        break;
176
 
        
177
 
    case 32:
178
 
        pixman_fill32 (bits, stride, x, y, width, height, xor);
179
 
        break;
180
 
        
181
 
    default:
182
 
        return FALSE;
183
 
        break;
 
32
 
 
33
/*
 
34
 * Computing composite region
 
35
 */
 
36
#define BOUND(v)        (int16_t) ((v) < INT16_MIN ? INT16_MIN : (v) > INT16_MAX ? INT16_MAX : (v))
 
37
 
 
38
static inline pixman_bool_t
 
39
clip_general_image (pixman_region32_t * region,
 
40
                    pixman_region32_t * clip,
 
41
                    int                 dx,
 
42
                    int                 dy)
 
43
{
 
44
    if (pixman_region32_n_rects (region) == 1 &&
 
45
        pixman_region32_n_rects (clip) == 1)
 
46
    {
 
47
        pixman_box32_t *  rbox = pixman_region32_rectangles (region, NULL);
 
48
        pixman_box32_t *  cbox = pixman_region32_rectangles (clip, NULL);
 
49
        int v;
 
50
 
 
51
        if (rbox->x1 < (v = cbox->x1 + dx))
 
52
            rbox->x1 = BOUND (v);
 
53
        if (rbox->x2 > (v = cbox->x2 + dx))
 
54
            rbox->x2 = BOUND (v);
 
55
        if (rbox->y1 < (v = cbox->y1 + dy))
 
56
            rbox->y1 = BOUND (v);
 
57
        if (rbox->y2 > (v = cbox->y2 + dy))
 
58
            rbox->y2 = BOUND (v);
 
59
        if (rbox->x1 >= rbox->x2 ||
 
60
            rbox->y1 >= rbox->y2)
 
61
        {
 
62
            pixman_region32_init (region);
 
63
        }
 
64
    }
 
65
    else if (!pixman_region32_not_empty (clip))
 
66
    {
 
67
        return FALSE;
 
68
    }
 
69
    else
 
70
    {
 
71
        if (dx || dy)
 
72
            pixman_region32_translate (region, -dx, -dy);
 
73
        if (!pixman_region32_intersect (region, region, clip))
 
74
            return FALSE;
 
75
        if (dx || dy)
 
76
            pixman_region32_translate (region, dx, dy);
 
77
    }
 
78
    return pixman_region32_not_empty (region);
 
79
}
 
80
 
 
81
static inline pixman_bool_t
 
82
clip_source_image (pixman_region32_t * region,
 
83
                   pixman_image_t *    image,
 
84
                   int                 dx,
 
85
                   int                 dy)
 
86
{
 
87
    /* Source clips are ignored, unless they are explicitly turned on
 
88
     * and the clip in question was set by an X client. (Because if
 
89
     * the clip was not set by a client, then it is a hierarchy
 
90
     * clip and those should always be ignored for sources).
 
91
     */
 
92
    if (!image->common.clip_sources || !image->common.client_clip)
 
93
        return TRUE;
 
94
 
 
95
    return clip_general_image (region,
 
96
                               &image->common.clip_region,
 
97
                               dx, dy);
 
98
}
 
99
 
 
100
/*
 
101
 * returns FALSE if the final region is empty.  Indistinguishable from
 
102
 * an allocation failure, but rendering ignores those anyways.
 
103
 */
 
104
static pixman_bool_t
 
105
pixman_compute_composite_region32 (pixman_region32_t * region,
 
106
                                   pixman_image_t *    src_image,
 
107
                                   pixman_image_t *    mask_image,
 
108
                                   pixman_image_t *    dst_image,
 
109
                                   int16_t             src_x,
 
110
                                   int16_t             src_y,
 
111
                                   int16_t             mask_x,
 
112
                                   int16_t             mask_y,
 
113
                                   int16_t             dest_x,
 
114
                                   int16_t             dest_y,
 
115
                                   uint16_t            width,
 
116
                                   uint16_t            height)
 
117
{
 
118
    int v;
 
119
 
 
120
    region->extents.x1 = dest_x;
 
121
    v = dest_x + width;
 
122
    region->extents.x2 = BOUND (v);
 
123
    region->extents.y1 = dest_y;
 
124
    v = dest_y + height;
 
125
    region->extents.y2 = BOUND (v);
 
126
 
 
127
    region->extents.x1 = MAX (region->extents.x1, 0);
 
128
    region->extents.y1 = MAX (region->extents.y1, 0);
 
129
    region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
 
130
    region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
 
131
 
 
132
    region->data = 0;
 
133
 
 
134
    /* Check for empty operation */
 
135
    if (region->extents.x1 >= region->extents.x2 ||
 
136
        region->extents.y1 >= region->extents.y2)
 
137
    {
 
138
        pixman_region32_init (region);
 
139
        return FALSE;
 
140
    }
 
141
 
 
142
    if (dst_image->common.have_clip_region)
 
143
    {
 
144
        if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
 
145
        {
 
146
            pixman_region32_fini (region);
 
147
            return FALSE;
 
148
        }
 
149
    }
 
150
 
 
151
    if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region)
 
152
    {
 
153
        if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
 
154
                                 -dst_image->common.alpha_origin_x,
 
155
                                 -dst_image->common.alpha_origin_y))
 
156
        {
 
157
            pixman_region32_fini (region);
 
158
            return FALSE;
 
159
        }
 
160
    }
 
161
 
 
162
    /* clip against src */
 
163
    if (src_image->common.have_clip_region)
 
164
    {
 
165
        if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
 
166
        {
 
167
            pixman_region32_fini (region);
 
168
            return FALSE;
 
169
        }
 
170
    }
 
171
    if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
 
172
    {
 
173
        if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
 
174
                                dest_x - (src_x - src_image->common.alpha_origin_x),
 
175
                                dest_y - (src_y - src_image->common.alpha_origin_y)))
 
176
        {
 
177
            pixman_region32_fini (region);
 
178
            return FALSE;
 
179
        }
 
180
    }
 
181
    /* clip against mask */
 
182
    if (mask_image && mask_image->common.have_clip_region)
 
183
    {
 
184
        if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
 
185
        {
 
186
            pixman_region32_fini (region);
 
187
            return FALSE;
 
188
        }
 
189
        if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
 
190
        {
 
191
            if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
 
192
                                    dest_x - (mask_x - mask_image->common.alpha_origin_x),
 
193
                                    dest_y - (mask_y - mask_image->common.alpha_origin_y)))
 
194
            {
 
195
                pixman_region32_fini (region);
 
196
                return FALSE;
 
197
            }
 
198
        }
184
199
    }
185
200
 
186
201
    return TRUE;
187
202
}
188
203
 
189
 
 
190
 
/*
191
 
 * Compute the smallest value no less than y which is on a
192
 
 * grid row
193
 
 */
194
 
 
195
 
PIXMAN_EXPORT pixman_fixed_t
196
 
pixman_sample_ceil_y (pixman_fixed_t y, int n)
197
 
{
198
 
    pixman_fixed_t   f = pixman_fixed_frac(y);
199
 
    pixman_fixed_t   i = pixman_fixed_floor(y);
200
 
 
201
 
    f = ((f + Y_FRAC_FIRST(n)) / STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
202
 
    if (f > Y_FRAC_LAST(n))
203
 
    {
204
 
        f = Y_FRAC_FIRST(n);
205
 
        i += pixman_fixed_1;
206
 
    }
207
 
    return (i | f);
208
 
}
209
 
 
210
 
#define _div(a,b)    ((a) >= 0 ? (a) / (b) : -((-(a) + (b) - 1) / (b)))
211
 
 
212
 
/*
213
 
 * Compute the largest value no greater than y which is on a
214
 
 * grid row
215
 
 */
216
 
PIXMAN_EXPORT pixman_fixed_t
217
 
pixman_sample_floor_y (pixman_fixed_t y, int n)
218
 
{
219
 
    pixman_fixed_t   f = pixman_fixed_frac(y);
220
 
    pixman_fixed_t   i = pixman_fixed_floor (y);
221
 
 
222
 
    f = _div(f - Y_FRAC_FIRST(n), STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
223
 
    if (f < Y_FRAC_FIRST(n))
224
 
    {
225
 
        f = Y_FRAC_LAST(n);
226
 
        i -= pixman_fixed_1;
227
 
    }
228
 
    return (i | f);
229
 
}
230
 
 
231
 
/*
232
 
 * Step an edge by any amount (including negative values)
233
 
 */
234
 
PIXMAN_EXPORT void
235
 
pixman_edge_step (pixman_edge_t *e, int n)
236
 
{
237
 
    pixman_fixed_48_16_t        ne;
238
 
 
239
 
    e->x += n * e->stepx;
240
 
 
241
 
    ne = e->e + n * (pixman_fixed_48_16_t) e->dx;
242
 
 
243
 
    if (n >= 0)
244
 
    {
245
 
        if (ne > 0)
246
 
        {
247
 
            int nx = (ne + e->dy - 1) / e->dy;
248
 
            e->e = ne - nx * (pixman_fixed_48_16_t) e->dy;
249
 
            e->x += nx * e->signdx;
250
 
        }
251
 
    }
252
 
    else
253
 
    {
254
 
        if (ne <= -e->dy)
255
 
        {
256
 
            int nx = (-ne) / e->dy;
257
 
            e->e = ne + nx * (pixman_fixed_48_16_t) e->dy;
258
 
            e->x -= nx * e->signdx;
259
 
        }
260
 
    }
261
 
}
262
 
 
263
 
/*
264
 
 * A private routine to initialize the multi-step
265
 
 * elements of an edge structure
266
 
 */
267
 
static void
268
 
_pixman_edge_tMultiInit (pixman_edge_t *e, int n, pixman_fixed_t *stepx_p, pixman_fixed_t *dx_p)
269
 
{
270
 
    pixman_fixed_t      stepx;
271
 
    pixman_fixed_48_16_t        ne;
272
 
 
273
 
    ne = n * (pixman_fixed_48_16_t) e->dx;
274
 
    stepx = n * e->stepx;
275
 
    if (ne > 0)
276
 
    {
277
 
        int nx = ne / e->dy;
278
 
        ne -= nx * e->dy;
279
 
        stepx += nx * e->signdx;
280
 
    }
281
 
    *dx_p = ne;
282
 
    *stepx_p = stepx;
283
 
}
284
 
 
285
 
/*
286
 
 * Initialize one edge structure given the line endpoints and a
287
 
 * starting y value
288
 
 */
289
 
PIXMAN_EXPORT void
290
 
pixman_edge_init (pixman_edge_t *e,
291
 
                  int           n,
292
 
                  pixman_fixed_t                y_start,
293
 
                  pixman_fixed_t                x_top,
294
 
                  pixman_fixed_t                y_top,
295
 
                  pixman_fixed_t                x_bot,
296
 
                  pixman_fixed_t                y_bot)
297
 
{
298
 
    pixman_fixed_t      dx, dy;
299
 
 
300
 
    e->x = x_top;
301
 
    e->e = 0;
302
 
    dx = x_bot - x_top;
303
 
    dy = y_bot - y_top;
304
 
    e->dy = dy;
305
 
    e->dx = 0;
306
 
    if (dy)
307
 
    {
308
 
        if (dx >= 0)
309
 
        {
310
 
            e->signdx = 1;
311
 
            e->stepx = dx / dy;
312
 
            e->dx = dx % dy;
313
 
            e->e = -dy;
314
 
        }
315
 
        else
316
 
        {
317
 
            e->signdx = -1;
318
 
            e->stepx = -(-dx / dy);
319
 
            e->dx = -dx % dy;
320
 
            e->e = 0;
321
 
        }
322
 
 
323
 
        _pixman_edge_tMultiInit (e, STEP_Y_SMALL(n), &e->stepx_small, &e->dx_small);
324
 
        _pixman_edge_tMultiInit (e, STEP_Y_BIG(n), &e->stepx_big, &e->dx_big);
325
 
    }
326
 
    pixman_edge_step (e, y_start - y_top);
327
 
}
328
 
 
329
 
/*
330
 
 * Initialize one edge structure given a line, starting y value
331
 
 * and a pixel offset for the line
332
 
 */
333
 
PIXMAN_EXPORT void
334
 
pixman_line_fixed_edge_init (pixman_edge_t *e,
335
 
                             int            n,
336
 
                             pixman_fixed_t         y,
337
 
                             const pixman_line_fixed_t *line,
338
 
                             int            x_off,
339
 
                             int            y_off)
340
 
{
341
 
    pixman_fixed_t      x_off_fixed = pixman_int_to_fixed(x_off);
342
 
    pixman_fixed_t      y_off_fixed = pixman_int_to_fixed(y_off);
343
 
    const pixman_point_fixed_t *top, *bot;
344
 
 
345
 
    if (line->p1.y <= line->p2.y)
346
 
    {
347
 
        top = &line->p1;
348
 
        bot = &line->p2;
349
 
    }
350
 
    else
351
 
    {
352
 
        top = &line->p2;
353
 
        bot = &line->p1;
354
 
    }
355
 
    pixman_edge_init (e, n, y,
356
 
                    top->x + x_off_fixed,
357
 
                    top->y + y_off_fixed,
358
 
                    bot->x + x_off_fixed,
359
 
                    bot->y + y_off_fixed);
 
204
PIXMAN_EXPORT pixman_bool_t
 
205
pixman_compute_composite_region (pixman_region16_t * region,
 
206
                                 pixman_image_t *    src_image,
 
207
                                 pixman_image_t *    mask_image,
 
208
                                 pixman_image_t *    dst_image,
 
209
                                 int16_t             src_x,
 
210
                                 int16_t             src_y,
 
211
                                 int16_t             mask_x,
 
212
                                 int16_t             mask_y,
 
213
                                 int16_t             dest_x,
 
214
                                 int16_t             dest_y,
 
215
                                 uint16_t            width,
 
216
                                 uint16_t            height)
 
217
{
 
218
    pixman_region32_t r32;
 
219
    pixman_bool_t retval;
 
220
 
 
221
    pixman_region32_init (&r32);
 
222
 
 
223
    retval = pixman_compute_composite_region32 (
 
224
        &r32, src_image, mask_image, dst_image,
 
225
        src_x, src_y, mask_x, mask_y, dest_x, dest_y,
 
226
        width, height);
 
227
 
 
228
    if (retval)
 
229
    {
 
230
        if (!pixman_region16_copy_from_region32 (region, &r32))
 
231
            retval = FALSE;
 
232
    }
 
233
 
 
234
    pixman_region32_fini (&r32);
 
235
    return retval;
360
236
}
361
237
 
362
238
pixman_bool_t
363
239
pixman_multiply_overflows_int (unsigned int a,
364
 
                               unsigned int b)
 
240
                               unsigned int b)
365
241
{
366
242
    return a >= INT32_MAX / b;
367
243
}
368
244
 
369
245
pixman_bool_t
370
246
pixman_addition_overflows_int (unsigned int a,
371
 
                               unsigned int b)
 
247
                               unsigned int b)
372
248
{
373
249
    return a > INT32_MAX - b;
374
250
}
375
251
 
376
252
void *
377
 
pixman_malloc_ab(unsigned int a,
378
 
                 unsigned int b)
 
253
pixman_malloc_ab (unsigned int a,
 
254
                  unsigned int b)
379
255
{
380
256
    if (a >= INT32_MAX / b)
381
257
        return NULL;
385
261
 
386
262
void *
387
263
pixman_malloc_abc (unsigned int a,
388
 
                   unsigned int b,
389
 
                   unsigned int c)
 
264
                   unsigned int b,
 
265
                   unsigned int c)
390
266
{
391
267
    if (a >= INT32_MAX / b)
392
268
        return NULL;
396
272
        return malloc (a * b * c);
397
273
}
398
274
 
399
 
 
400
 
/**
401
 
 * pixman_version:
402
 
 *
403
 
 * Returns the version of the pixman library encoded in a single
404
 
 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
405
 
 * later versions compare greater than earlier versions.
406
 
 *
407
 
 * A run-time comparison to check that pixman's version is greater than
408
 
 * or equal to version X.Y.Z could be performed as follows:
409
 
 *
410
 
 * <informalexample><programlisting>
411
 
 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
412
 
 * </programlisting></informalexample>
413
 
 *
414
 
 * See also pixman_version_string() as well as the compile-time
415
 
 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
416
 
 *
417
 
 * Return value: the encoded version.
418
 
 **/
419
 
PIXMAN_EXPORT int
420
 
pixman_version (void)
421
 
{
422
 
    return PIXMAN_VERSION;
423
 
}
424
 
 
425
 
/**
426
 
 * pixman_version_string:
427
 
 *
428
 
 * Returns the version of the pixman library as a human-readable string
429
 
 * of the form "X.Y.Z".
430
 
 *
431
 
 * See also pixman_version() as well as the compile-time equivalents
432
 
 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
433
 
 *
434
 
 * Return value: a string containing the version.
435
 
 **/
436
 
PIXMAN_EXPORT const char*
437
 
pixman_version_string (void)
438
 
{
439
 
    return PIXMAN_VERSION_STRING;
440
 
}
441
 
 
442
 
/**
443
 
 * pixman_format_supported_destination:
444
 
 * @format: A pixman_format_code_t format
445
 
 * 
446
 
 * Return value: whether the provided format code is a supported
447
 
 * format for a pixman surface used as a destination in
448
 
 * rendering.
449
 
 *
450
 
 * Currently, all pixman_format_code_t values are supported
451
 
 * except for the YUV formats.
452
 
 **/
453
 
PIXMAN_EXPORT pixman_bool_t
454
 
pixman_format_supported_destination (pixman_format_code_t format)
455
 
{
456
 
    switch (format) {
457
 
    /* 32 bpp formats */
458
 
    case PIXMAN_a2b10g10r10:
459
 
    case PIXMAN_x2b10g10r10:
460
 
    case PIXMAN_a8r8g8b8:
461
 
    case PIXMAN_x8r8g8b8:
462
 
    case PIXMAN_a8b8g8r8:
463
 
    case PIXMAN_x8b8g8r8:
464
 
    case PIXMAN_r8g8b8:
465
 
    case PIXMAN_b8g8r8:
466
 
    case PIXMAN_r5g6b5:
467
 
    case PIXMAN_b5g6r5:
468
 
    /* 16 bpp formats */
469
 
    case PIXMAN_a1r5g5b5:
470
 
    case PIXMAN_x1r5g5b5:
471
 
    case PIXMAN_a1b5g5r5:
472
 
    case PIXMAN_x1b5g5r5:
473
 
    case PIXMAN_a4r4g4b4:
474
 
    case PIXMAN_x4r4g4b4:
475
 
    case PIXMAN_a4b4g4r4:
476
 
    case PIXMAN_x4b4g4r4:
477
 
    /* 8bpp formats */
478
 
    case PIXMAN_a8:
479
 
    case PIXMAN_r3g3b2:
480
 
    case PIXMAN_b2g3r3:
481
 
    case PIXMAN_a2r2g2b2:
482
 
    case PIXMAN_a2b2g2r2:
483
 
    case PIXMAN_c8:
484
 
    case PIXMAN_g8:
485
 
    case PIXMAN_x4a4:
486
 
    /* Collides with PIXMAN_c8
487
 
    case PIXMAN_x4c4:
488
 
    */
489
 
    /* Collides with PIXMAN_g8
490
 
    case PIXMAN_x4g4:
491
 
    */
492
 
    /* 4bpp formats */
493
 
    case PIXMAN_a4:
494
 
    case PIXMAN_r1g2b1:
495
 
    case PIXMAN_b1g2r1:
496
 
    case PIXMAN_a1r1g1b1:
497
 
    case PIXMAN_a1b1g1r1:
498
 
    case PIXMAN_c4:
499
 
    case PIXMAN_g4:
500
 
    /* 1bpp formats */
501
 
    case PIXMAN_a1:
502
 
    case PIXMAN_g1:
503
 
        return TRUE;
504
 
        
505
 
    /* YUV formats */
506
 
    case PIXMAN_yuy2:
507
 
    case PIXMAN_yv12:
508
 
    default:
509
 
        return FALSE;
510
 
    }
511
 
}
512
 
 
513
 
/**
514
 
 * pixman_format_supported_source:
515
 
 * @format: A pixman_format_code_t format
516
 
 * 
517
 
 * Return value: whether the provided format code is a supported
518
 
 * format for a pixman surface used as a source in
519
 
 * rendering.
520
 
 *
521
 
 * Currently, all pixman_format_code_t values are supported.
522
 
 **/
523
 
PIXMAN_EXPORT pixman_bool_t
524
 
pixman_format_supported_source (pixman_format_code_t format)
525
 
{
526
 
    switch (format) {
527
 
    /* 32 bpp formats */
528
 
    case PIXMAN_a2b10g10r10:
529
 
    case PIXMAN_x2b10g10r10:
530
 
    case PIXMAN_a8r8g8b8:
531
 
    case PIXMAN_x8r8g8b8:
532
 
    case PIXMAN_a8b8g8r8:
533
 
    case PIXMAN_x8b8g8r8:
534
 
    case PIXMAN_r8g8b8:
535
 
    case PIXMAN_b8g8r8:
536
 
    case PIXMAN_r5g6b5:
537
 
    case PIXMAN_b5g6r5:
538
 
    /* 16 bpp formats */
539
 
    case PIXMAN_a1r5g5b5:
540
 
    case PIXMAN_x1r5g5b5:
541
 
    case PIXMAN_a1b5g5r5:
542
 
    case PIXMAN_x1b5g5r5:
543
 
    case PIXMAN_a4r4g4b4:
544
 
    case PIXMAN_x4r4g4b4:
545
 
    case PIXMAN_a4b4g4r4:
546
 
    case PIXMAN_x4b4g4r4:
547
 
    /* 8bpp formats */
548
 
    case PIXMAN_a8:
549
 
    case PIXMAN_r3g3b2:
550
 
    case PIXMAN_b2g3r3:
551
 
    case PIXMAN_a2r2g2b2:
552
 
    case PIXMAN_a2b2g2r2:
553
 
    case PIXMAN_c8:
554
 
    case PIXMAN_g8:
555
 
    case PIXMAN_x4a4:
556
 
    /* Collides with PIXMAN_c8
557
 
    case PIXMAN_x4c4:
558
 
    */
559
 
    /* Collides with PIXMAN_g8
560
 
    case PIXMAN_x4g4:
561
 
    */
562
 
    /* 4bpp formats */
563
 
    case PIXMAN_a4:
564
 
    case PIXMAN_r1g2b1:
565
 
    case PIXMAN_b1g2r1:
566
 
    case PIXMAN_a1r1g1b1:
567
 
    case PIXMAN_a1b1g1r1:
568
 
    case PIXMAN_c4:
569
 
    case PIXMAN_g4:
570
 
    /* 1bpp formats */
571
 
    case PIXMAN_a1:
572
 
    case PIXMAN_g1:
573
 
    /* YUV formats */
574
 
    case PIXMAN_yuy2:
575
 
    case PIXMAN_yv12:
576
 
        return TRUE;
577
 
 
578
 
    default:
579
 
        return FALSE;
580
 
    }
 
275
/*
 
276
 * Helper routine to expand a color component from 0 < n <= 8 bits to 16
 
277
 * bits by replication.
 
278
 */
 
279
static inline uint64_t
 
280
expand16 (const uint8_t val, int nbits)
 
281
{
 
282
    /* Start out with the high bit of val in the high bit of result. */
 
283
    uint16_t result = (uint16_t)val << (16 - nbits);
 
284
 
 
285
    if (nbits == 0)
 
286
        return 0;
 
287
 
 
288
    /* Copy the bits in result, doubling the number of bits each time, until
 
289
     * we fill all 16 bits.
 
290
     */
 
291
    while (nbits < 16)
 
292
    {
 
293
        result |= result >> nbits;
 
294
        nbits *= 2;
 
295
    }
 
296
 
 
297
    return result;
 
298
}
 
299
 
 
300
/*
 
301
 * This function expands images from ARGB8 format to ARGB16.  To preserve
 
302
 * precision, it needs to know the original source format.  For example, if the
 
303
 * source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then
 
304
 * the expanded value is 12345123.  To correctly expand this to 16 bits, it
 
305
 * should be 1234512345123451 and not 1234512312345123.
 
306
 */
 
307
void
 
308
pixman_expand (uint64_t *           dst,
 
309
               const uint32_t *     src,
 
310
               pixman_format_code_t format,
 
311
               int                  width)
 
312
{
 
313
    /*
 
314
     * Determine the sizes of each component and the masks and shifts
 
315
     * required to extract them from the source pixel.
 
316
     */
 
317
    const int a_size = PIXMAN_FORMAT_A (format),
 
318
              r_size = PIXMAN_FORMAT_R (format),
 
319
              g_size = PIXMAN_FORMAT_G (format),
 
320
              b_size = PIXMAN_FORMAT_B (format);
 
321
    const int a_shift = 32 - a_size,
 
322
              r_shift = 24 - r_size,
 
323
              g_shift = 16 - g_size,
 
324
              b_shift =  8 - b_size;
 
325
    const uint8_t a_mask = ~(~0 << a_size),
 
326
                  r_mask = ~(~0 << r_size),
 
327
                  g_mask = ~(~0 << g_size),
 
328
                  b_mask = ~(~0 << b_size);
 
329
    int i;
 
330
 
 
331
    /* Start at the end so that we can do the expansion in place
 
332
     * when src == dst
 
333
     */
 
334
    for (i = width - 1; i >= 0; i--)
 
335
    {
 
336
        const uint32_t pixel = src[i];
 
337
        const uint8_t a = (pixel >> a_shift) & a_mask,
 
338
                      r = (pixel >> r_shift) & r_mask,
 
339
                      g = (pixel >> g_shift) & g_mask,
 
340
                      b = (pixel >> b_shift) & b_mask;
 
341
        const uint64_t a16 = a_size ? expand16 (a, a_size) : 0xffff,
 
342
                       r16 = expand16 (r, r_size),
 
343
                       g16 = expand16 (g, g_size),
 
344
                       b16 = expand16 (b, b_size);
 
345
 
 
346
        dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16;
 
347
    }
 
348
}
 
349
 
 
350
/*
 
351
 * Contracting is easier than expanding.  We just need to truncate the
 
352
 * components.
 
353
 */
 
354
void
 
355
pixman_contract (uint32_t *      dst,
 
356
                 const uint64_t *src,
 
357
                 int             width)
 
358
{
 
359
    int i;
 
360
 
 
361
    /* Start at the beginning so that we can do the contraction in
 
362
     * place when src == dst
 
363
     */
 
364
    for (i = 0; i < width; i++)
 
365
    {
 
366
        const uint8_t a = src[i] >> 56,
 
367
                      r = src[i] >> 40,
 
368
                      g = src[i] >> 24,
 
369
                      b = src[i] >> 8;
 
370
 
 
371
        dst[i] = a << 24 | r << 16 | g << 8 | b;
 
372
    }
 
373
}
 
374
 
 
375
static void
 
376
walk_region_internal (pixman_implementation_t *imp,
 
377
                      pixman_op_t              op,
 
378
                      pixman_image_t *         src_image,
 
379
                      pixman_image_t *         mask_image,
 
380
                      pixman_image_t *         dst_image,
 
381
                      int16_t                  src_x,
 
382
                      int16_t                  src_y,
 
383
                      int16_t                  mask_x,
 
384
                      int16_t                  mask_y,
 
385
                      int16_t                  dest_x,
 
386
                      int16_t                  dest_y,
 
387
                      uint16_t                 width,
 
388
                      uint16_t                 height,
 
389
                      pixman_bool_t            src_repeat,
 
390
                      pixman_bool_t            mask_repeat,
 
391
                      pixman_region32_t *      region,
 
392
                      pixman_composite_func_t  composite_rect)
 
393
{
 
394
    int n;
 
395
    const pixman_box32_t *pbox;
 
396
    int w, h, w_this, h_this;
 
397
    int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
 
398
 
 
399
    pbox = pixman_region32_rectangles (region, &n);
 
400
    while (n--)
 
401
    {
 
402
        h = pbox->y2 - pbox->y1;
 
403
        y_src = pbox->y1 - dest_y + src_y;
 
404
        y_msk = pbox->y1 - dest_y + mask_y;
 
405
        y_dst = pbox->y1;
 
406
 
 
407
        while (h)
 
408
        {
 
409
            h_this = h;
 
410
            w = pbox->x2 - pbox->x1;
 
411
            x_src = pbox->x1 - dest_x + src_x;
 
412
            x_msk = pbox->x1 - dest_x + mask_x;
 
413
            x_dst = pbox->x1;
 
414
 
 
415
            if (mask_repeat)
 
416
            {
 
417
                y_msk = MOD (y_msk, mask_image->bits.height);
 
418
                if (h_this > mask_image->bits.height - y_msk)
 
419
                    h_this = mask_image->bits.height - y_msk;
 
420
            }
 
421
 
 
422
            if (src_repeat)
 
423
            {
 
424
                y_src = MOD (y_src, src_image->bits.height);
 
425
                if (h_this > src_image->bits.height - y_src)
 
426
                    h_this = src_image->bits.height - y_src;
 
427
            }
 
428
 
 
429
            while (w)
 
430
            {
 
431
                w_this = w;
 
432
 
 
433
                if (mask_repeat)
 
434
                {
 
435
                    x_msk = MOD (x_msk, mask_image->bits.width);
 
436
                    if (w_this > mask_image->bits.width - x_msk)
 
437
                        w_this = mask_image->bits.width - x_msk;
 
438
                }
 
439
 
 
440
                if (src_repeat)
 
441
                {
 
442
                    x_src = MOD (x_src, src_image->bits.width);
 
443
                    if (w_this > src_image->bits.width - x_src)
 
444
                        w_this = src_image->bits.width - x_src;
 
445
                }
 
446
 
 
447
                (*composite_rect) (imp, op,
 
448
                                   src_image, mask_image, dst_image,
 
449
                                   x_src, y_src, x_msk, y_msk, x_dst, y_dst,
 
450
                                   w_this, h_this);
 
451
                w -= w_this;
 
452
 
 
453
                x_src += w_this;
 
454
                x_msk += w_this;
 
455
                x_dst += w_this;
 
456
            }
 
457
 
 
458
            h -= h_this;
 
459
            y_src += h_this;
 
460
            y_msk += h_this;
 
461
            y_dst += h_this;
 
462
        }
 
463
 
 
464
        pbox++;
 
465
    }
 
466
}
 
467
 
 
468
void
 
469
_pixman_walk_composite_region (pixman_implementation_t *imp,
 
470
                               pixman_op_t              op,
 
471
                               pixman_image_t *         src_image,
 
472
                               pixman_image_t *         mask_image,
 
473
                               pixman_image_t *         dst_image,
 
474
                               int16_t                  src_x,
 
475
                               int16_t                  src_y,
 
476
                               int16_t                  mask_x,
 
477
                               int16_t                  mask_y,
 
478
                               int16_t                  dest_x,
 
479
                               int16_t                  dest_y,
 
480
                               uint16_t                 width,
 
481
                               uint16_t                 height,
 
482
                               pixman_composite_func_t  composite_rect)
 
483
{
 
484
    pixman_region32_t region;
 
485
 
 
486
    pixman_region32_init (&region);
 
487
 
 
488
    if (pixman_compute_composite_region32 (
 
489
            &region, src_image, mask_image, dst_image,
 
490
            src_x, src_y, mask_x, mask_y, dest_x, dest_y,
 
491
            width, height))
 
492
    {
 
493
        walk_region_internal (imp, op,
 
494
                              src_image, mask_image, dst_image,
 
495
                              src_x, src_y, mask_x, mask_y, dest_x, dest_y,
 
496
                              width, height, FALSE, FALSE,
 
497
                              &region,
 
498
                              composite_rect);
 
499
 
 
500
        pixman_region32_fini (&region);
 
501
    }
 
502
}
 
503
 
 
504
static pixman_bool_t
 
505
mask_is_solid (pixman_image_t *mask)
 
506
{
 
507
    if (mask->type == SOLID)
 
508
        return TRUE;
 
509
 
 
510
    if (mask->type == BITS &&
 
511
        mask->common.repeat == PIXMAN_REPEAT_NORMAL &&
 
512
        mask->bits.width == 1 &&
 
513
        mask->bits.height == 1)
 
514
    {
 
515
        return TRUE;
 
516
    }
 
517
 
 
518
    return FALSE;
 
519
}
 
520
 
 
521
static const pixman_fast_path_t *
 
522
get_fast_path (const pixman_fast_path_t *fast_paths,
 
523
               pixman_op_t               op,
 
524
               pixman_image_t *          src_image,
 
525
               pixman_image_t *          mask_image,
 
526
               pixman_image_t *          dst_image,
 
527
               pixman_bool_t             is_pixbuf)
 
528
{
 
529
    const pixman_fast_path_t *info;
 
530
 
 
531
    for (info = fast_paths; info->op != PIXMAN_OP_NONE; info++)
 
532
    {
 
533
        pixman_bool_t valid_src = FALSE;
 
534
        pixman_bool_t valid_mask = FALSE;
 
535
 
 
536
        if (info->op != op)
 
537
            continue;
 
538
 
 
539
        if ((info->src_format == PIXMAN_solid &&
 
540
             _pixman_image_is_solid (src_image)) ||
 
541
            (src_image->type == BITS &&
 
542
             info->src_format == src_image->bits.format))
 
543
        {
 
544
            valid_src = TRUE;
 
545
        }
 
546
 
 
547
        if (!valid_src)
 
548
            continue;
 
549
 
 
550
        if ((info->mask_format == PIXMAN_null && !mask_image) ||
 
551
            (mask_image && mask_image->type == BITS &&
 
552
             info->mask_format == mask_image->bits.format))
 
553
        {
 
554
            valid_mask = TRUE;
 
555
 
 
556
            if (info->flags & NEED_SOLID_MASK)
 
557
            {
 
558
                if (!mask_image || !mask_is_solid (mask_image))
 
559
                    valid_mask = FALSE;
 
560
            }
 
561
 
 
562
            if (info->flags & NEED_COMPONENT_ALPHA)
 
563
            {
 
564
                if (!mask_image || !mask_image->common.component_alpha)
 
565
                    valid_mask = FALSE;
 
566
            }
 
567
        }
 
568
 
 
569
        if (!valid_mask)
 
570
            continue;
 
571
 
 
572
        if (info->dest_format != dst_image->bits.format)
 
573
            continue;
 
574
 
 
575
        if ((info->flags & NEED_PIXBUF) && !is_pixbuf)
 
576
            continue;
 
577
 
 
578
        return info;
 
579
    }
 
580
 
 
581
    return NULL;
 
582
}
 
583
 
 
584
static force_inline pixman_bool_t
 
585
image_covers (pixman_image_t *image,
 
586
              pixman_box32_t *extents,
 
587
              int             x,
 
588
              int             y)
 
589
{
 
590
    if (image->common.type == BITS &&
 
591
        image->common.repeat == PIXMAN_REPEAT_NONE)
 
592
    {
 
593
        if (x > extents->x1 || y > extents->y1 ||
 
594
            x + image->bits.width < extents->x2 ||
 
595
            y + image->bits.height < extents->y2)
 
596
        {
 
597
            return FALSE;
 
598
        }
 
599
    }
 
600
 
 
601
    return TRUE;
 
602
}
 
603
 
 
604
static force_inline pixman_bool_t
 
605
sources_cover (pixman_image_t *src,
 
606
               pixman_image_t *mask,
 
607
               pixman_box32_t *extents,
 
608
               int             src_x,
 
609
               int             src_y,
 
610
               int             mask_x,
 
611
               int             mask_y,
 
612
               int             dest_x,
 
613
               int             dest_y)
 
614
{
 
615
    if (!image_covers (src, extents, dest_x - src_x, dest_y - src_y))
 
616
        return FALSE;
 
617
 
 
618
    if (!mask)
 
619
        return TRUE;
 
620
    
 
621
    if (!image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
 
622
        return FALSE;
 
623
 
 
624
    return TRUE;
 
625
}
 
626
 
 
627
pixman_bool_t
 
628
_pixman_run_fast_path (const pixman_fast_path_t *paths,
 
629
                       pixman_implementation_t * imp,
 
630
                       pixman_op_t               op,
 
631
                       pixman_image_t *          src,
 
632
                       pixman_image_t *          mask,
 
633
                       pixman_image_t *          dest,
 
634
                       int32_t                   src_x,
 
635
                       int32_t                   src_y,
 
636
                       int32_t                   mask_x,
 
637
                       int32_t                   mask_y,
 
638
                       int32_t                   dest_x,
 
639
                       int32_t                   dest_y,
 
640
                       int32_t                   width,
 
641
                       int32_t                   height)
 
642
{
 
643
    pixman_composite_func_t func = NULL;
 
644
    pixman_bool_t src_repeat =
 
645
        src->common.repeat == PIXMAN_REPEAT_NORMAL;
 
646
    pixman_bool_t mask_repeat =
 
647
        mask && mask->common.repeat == PIXMAN_REPEAT_NORMAL;
 
648
    pixman_bool_t result;
 
649
    pixman_bool_t has_fast_path;
 
650
 
 
651
    has_fast_path = !dest->common.alpha_map &&
 
652
                    !dest->bits.read_func &&
 
653
                    !dest->bits.write_func;
 
654
 
 
655
    if (has_fast_path)
 
656
    {
 
657
        has_fast_path = (src->type == BITS || _pixman_image_is_solid (src)) &&
 
658
                        !src->common.transform &&
 
659
                        !src->common.alpha_map &&
 
660
                        src->common.filter != PIXMAN_FILTER_CONVOLUTION &&
 
661
                        src->common.repeat != PIXMAN_REPEAT_PAD &&
 
662
                        src->common.repeat != PIXMAN_REPEAT_REFLECT;
 
663
        if (has_fast_path && src->type == BITS)
 
664
        {
 
665
            has_fast_path = !src->bits.read_func &&
 
666
                            !src->bits.write_func &&
 
667
                            !PIXMAN_FORMAT_IS_WIDE (src->bits.format);
 
668
        }
 
669
    }
 
670
 
 
671
    if (mask && has_fast_path)
 
672
    {
 
673
        has_fast_path =
 
674
            mask->type == BITS &&
 
675
            !mask->common.transform &&
 
676
            !mask->common.alpha_map &&
 
677
            !mask->bits.read_func &&
 
678
            !mask->bits.write_func &&
 
679
            mask->common.filter != PIXMAN_FILTER_CONVOLUTION &&
 
680
            mask->common.repeat != PIXMAN_REPEAT_PAD &&
 
681
            mask->common.repeat != PIXMAN_REPEAT_REFLECT &&
 
682
            !PIXMAN_FORMAT_IS_WIDE (mask->bits.format);
 
683
    }
 
684
 
 
685
    if (has_fast_path)
 
686
    {
 
687
        const pixman_fast_path_t *info;
 
688
        pixman_bool_t pixbuf;
 
689
 
 
690
        pixbuf =
 
691
            src && src->type == BITS            &&
 
692
            mask && mask->type == BITS          &&
 
693
            src->bits.bits == mask->bits.bits   &&
 
694
            src_x == mask_x                     &&
 
695
            src_y == mask_y                     &&
 
696
            !mask->common.component_alpha       &&
 
697
            !mask_repeat;
 
698
 
 
699
        info = get_fast_path (paths, op, src, mask, dest, pixbuf);
 
700
 
 
701
        if (info)
 
702
        {
 
703
            func = info->func;
 
704
 
 
705
            if (info->src_format == PIXMAN_solid)
 
706
                src_repeat = FALSE;
 
707
 
 
708
            if (info->mask_format == PIXMAN_solid ||
 
709
                info->flags & NEED_SOLID_MASK)
 
710
            {
 
711
                mask_repeat = FALSE;
 
712
            }
 
713
 
 
714
            if ((src_repeat                     &&
 
715
                 src->bits.width == 1           &&
 
716
                 src->bits.height == 1) ||
 
717
                (mask_repeat                    &&
 
718
                 mask->bits.width == 1          &&
 
719
                 mask->bits.height == 1))
 
720
            {
 
721
                /* If src or mask are repeating 1x1 images and src_repeat or
 
722
                 * mask_repeat are still TRUE, it means the fast path we
 
723
                 * selected does not actually handle repeating images.
 
724
                 *
 
725
                 * So rather than call the "fast path" with a zillion
 
726
                 * 1x1 requests, we just fall back to the general code (which
 
727
                 * does do something sensible with 1x1 repeating images).
 
728
                 */
 
729
                func = NULL;
 
730
            }
 
731
        }
 
732
    }
 
733
 
 
734
    result = FALSE;
 
735
 
 
736
    if (func)
 
737
    {
 
738
        pixman_region32_t region;
 
739
        pixman_region32_init (&region);
 
740
 
 
741
        if (pixman_compute_composite_region32 (
 
742
                &region, src, mask, dest,
 
743
                src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
 
744
        {
 
745
            pixman_box32_t *extents = pixman_region32_extents (&region);
 
746
 
 
747
            if (sources_cover (
 
748
                    src, mask, extents,
 
749
                    src_x, src_y, mask_x, mask_y, dest_x, dest_y))
 
750
            {
 
751
                walk_region_internal (imp, op,
 
752
                                      src, mask, dest,
 
753
                                      src_x, src_y, mask_x, mask_y,
 
754
                                      dest_x, dest_y,
 
755
                                      width, height,
 
756
                                      src_repeat, mask_repeat,
 
757
                                      &region,
 
758
                                      func);
 
759
 
 
760
                result = TRUE;
 
761
            }
 
762
 
 
763
            pixman_region32_fini (&region);
 
764
        }
 
765
    }
 
766
 
 
767
    return result;
 
768
}
 
769
 
 
770
#define N_TMP_BOXES (16)
 
771
 
 
772
pixman_bool_t
 
773
pixman_region16_copy_from_region32 (pixman_region16_t *dst,
 
774
                                    pixman_region32_t *src)
 
775
{
 
776
    int n_boxes, i;
 
777
    pixman_box32_t *boxes32;
 
778
    pixman_box16_t *boxes16;
 
779
    pixman_bool_t retval;
 
780
 
 
781
    boxes32 = pixman_region32_rectangles (src, &n_boxes);
 
782
 
 
783
    boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t));
 
784
 
 
785
    if (!boxes16)
 
786
        return FALSE;
 
787
 
 
788
    for (i = 0; i < n_boxes; ++i)
 
789
    {
 
790
        boxes16[i].x1 = boxes32[i].x1;
 
791
        boxes16[i].y1 = boxes32[i].y1;
 
792
        boxes16[i].x2 = boxes32[i].x2;
 
793
        boxes16[i].y2 = boxes32[i].y2;
 
794
    }
 
795
 
 
796
    pixman_region_fini (dst);
 
797
    retval = pixman_region_init_rects (dst, boxes16, n_boxes);
 
798
    free (boxes16);
 
799
    return retval;
 
800
}
 
801
 
 
802
pixman_bool_t
 
803
pixman_region32_copy_from_region16 (pixman_region32_t *dst,
 
804
                                    pixman_region16_t *src)
 
805
{
 
806
    int n_boxes, i;
 
807
    pixman_box16_t *boxes16;
 
808
    pixman_box32_t *boxes32;
 
809
    pixman_box32_t tmp_boxes[N_TMP_BOXES];
 
810
    pixman_bool_t retval;
 
811
 
 
812
    boxes16 = pixman_region_rectangles (src, &n_boxes);
 
813
 
 
814
    if (n_boxes > N_TMP_BOXES)
 
815
        boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t));
 
816
    else
 
817
        boxes32 = tmp_boxes;
 
818
 
 
819
    if (!boxes32)
 
820
        return FALSE;
 
821
 
 
822
    for (i = 0; i < n_boxes; ++i)
 
823
    {
 
824
        boxes32[i].x1 = boxes16[i].x1;
 
825
        boxes32[i].y1 = boxes16[i].y1;
 
826
        boxes32[i].x2 = boxes16[i].x2;
 
827
        boxes32[i].y2 = boxes16[i].y2;
 
828
    }
 
829
 
 
830
    pixman_region32_fini (dst);
 
831
    retval = pixman_region32_init_rects (dst, boxes32, n_boxes);
 
832
 
 
833
    if (boxes32 != tmp_boxes)
 
834
        free (boxes32);
 
835
 
 
836
    return retval;
581
837
}