~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to pixman/pixman/pixman-image.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2000 SuSE, Inc.
 
3
 * Copyright © 2007 Red Hat, Inc.
 
4
 *
 
5
 * Permission to use, copy, modify, distribute, and sell this software and its
 
6
 * documentation for any purpose is hereby granted without fee, provided that
 
7
 * the above copyright notice appear in all copies and that both that
 
8
 * copyright notice and this permission notice appear in supporting
 
9
 * documentation, and that the name of SuSE not be used in advertising or
 
10
 * publicity pertaining to distribution of the software without specific,
 
11
 * written prior permission.  SuSE makes no representations about the
 
12
 * suitability of this software for any purpose.  It is provided "as is"
 
13
 * without express or implied warranty.
 
14
 *
 
15
 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
 
16
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
 
17
 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 
18
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 
19
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 
20
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
21
 */
 
22
 
 
23
#ifdef HAVE_CONFIG_H
 
24
#include <config.h>
 
25
#endif
 
26
 
 
27
#include <stdlib.h>
 
28
#include <stdio.h>
 
29
#include <string.h>
 
30
#include <assert.h>
 
31
 
 
32
#include "pixman-private.h"
 
33
 
 
34
static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
 
35
 
 
36
static void
 
37
gradient_property_changed (pixman_image_t *image)
 
38
{
 
39
    gradient_t *gradient = &image->gradient;
 
40
    int n = gradient->n_stops;
 
41
    pixman_gradient_stop_t *stops = gradient->stops;
 
42
    pixman_gradient_stop_t *begin = &(gradient->stops[-1]);
 
43
    pixman_gradient_stop_t *end = &(gradient->stops[n]);
 
44
 
 
45
    switch (gradient->common.repeat)
 
46
    {
 
47
    default:
 
48
    case PIXMAN_REPEAT_NONE:
 
49
        begin->x = INT32_MIN;
 
50
        begin->color = transparent_black;
 
51
        end->x = INT32_MAX;
 
52
        end->color = transparent_black;
 
53
        break;
 
54
 
 
55
    case PIXMAN_REPEAT_NORMAL:
 
56
        begin->x = stops[n - 1].x - pixman_fixed_1;
 
57
        begin->color = stops[n - 1].color;
 
58
        end->x = stops[0].x + pixman_fixed_1;
 
59
        end->color = stops[0].color;
 
60
        break;
 
61
 
 
62
    case PIXMAN_REPEAT_REFLECT:
 
63
        begin->x = - stops[0].x;
 
64
        begin->color = stops[0].color;
 
65
        end->x = pixman_int_to_fixed (2) - stops[n - 1].x;
 
66
        end->color = stops[n - 1].color;
 
67
        break;
 
68
 
 
69
    case PIXMAN_REPEAT_PAD:
 
70
        begin->x = INT32_MIN;
 
71
        begin->color = stops[0].color;
 
72
        end->x = INT32_MAX;
 
73
        end->color = stops[n - 1].color;
 
74
        break;
 
75
    }
 
76
}
 
77
 
 
78
pixman_bool_t
 
79
_pixman_init_gradient (gradient_t *                  gradient,
 
80
                       const pixman_gradient_stop_t *stops,
 
81
                       int                           n_stops)
 
82
{
 
83
    return_val_if_fail (n_stops > 0, FALSE);
 
84
 
 
85
    /* We allocate two extra stops, one before the beginning of the stop list,
 
86
     * and one after the end. These stops are initialized to whatever color
 
87
     * would be used for positions outside the range of the stop list.
 
88
     *
 
89
     * This saves a bit of computation in the gradient walker.
 
90
     *
 
91
     * The pointer we store in the gradient_t struct still points to the
 
92
     * first user-supplied struct, so when freeing, we will have to
 
93
     * subtract one.
 
94
     */
 
95
    gradient->stops =
 
96
        pixman_malloc_ab (n_stops + 2, sizeof (pixman_gradient_stop_t));
 
97
    if (!gradient->stops)
 
98
        return FALSE;
 
99
 
 
100
    gradient->stops += 1;
 
101
    memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
 
102
    gradient->n_stops = n_stops;
 
103
 
 
104
    gradient->common.property_changed = gradient_property_changed;
 
105
 
 
106
    return TRUE;
 
107
}
 
108
 
 
109
void
 
110
_pixman_image_init (pixman_image_t *image)
 
111
{
 
112
    image_common_t *common = &image->common;
 
113
 
 
114
    pixman_region32_init (&common->clip_region);
 
115
 
 
116
    common->alpha_count = 0;
 
117
    common->have_clip_region = FALSE;
 
118
    common->clip_sources = FALSE;
 
119
    common->transform = NULL;
 
120
    common->repeat = PIXMAN_REPEAT_NONE;
 
121
    common->filter = PIXMAN_FILTER_NEAREST;
 
122
    common->filter_params = NULL;
 
123
    common->n_filter_params = 0;
 
124
    common->alpha_map = NULL;
 
125
    common->component_alpha = FALSE;
 
126
    common->ref_count = 1;
 
127
    common->property_changed = NULL;
 
128
    common->client_clip = FALSE;
 
129
    common->destroy_func = NULL;
 
130
    common->destroy_data = NULL;
 
131
    common->dirty = TRUE;
 
132
}
 
133
 
 
134
pixman_bool_t
 
135
_pixman_image_fini (pixman_image_t *image)
 
136
{
 
137
    image_common_t *common = (image_common_t *)image;
 
138
 
 
139
    common->ref_count--;
 
140
 
 
141
    if (common->ref_count == 0)
 
142
    {
 
143
        if (image->common.destroy_func)
 
144
            image->common.destroy_func (image, image->common.destroy_data);
 
145
 
 
146
        pixman_region32_fini (&common->clip_region);
 
147
 
 
148
        free (common->transform);
 
149
        free (common->filter_params);
 
150
 
 
151
        if (common->alpha_map)
 
152
            pixman_image_unref ((pixman_image_t *)common->alpha_map);
 
153
 
 
154
        if (image->type == LINEAR ||
 
155
            image->type == RADIAL ||
 
156
            image->type == CONICAL)
 
157
        {
 
158
            if (image->gradient.stops)
 
159
            {
 
160
                /* See _pixman_init_gradient() for an explanation of the - 1 */
 
161
                free (image->gradient.stops - 1);
 
162
            }
 
163
 
 
164
            /* This will trigger if someone adds a property_changed
 
165
             * method to the linear/radial/conical gradient overwriting
 
166
             * the general one.
 
167
             */
 
168
            assert (
 
169
                image->common.property_changed == gradient_property_changed);
 
170
        }
 
171
 
 
172
        if (image->type == BITS && image->bits.free_me)
 
173
            free (image->bits.free_me);
 
174
 
 
175
        return TRUE;
 
176
    }
 
177
 
 
178
    return FALSE;
 
179
}
 
180
 
 
181
pixman_image_t *
 
182
_pixman_image_allocate (void)
 
183
{
 
184
    pixman_image_t *image = malloc (sizeof (pixman_image_t));
 
185
 
 
186
    if (image)
 
187
        _pixman_image_init (image);
 
188
 
 
189
    return image;
 
190
}
 
191
 
 
192
static void
 
193
image_property_changed (pixman_image_t *image)
 
194
{
 
195
    image->common.dirty = TRUE;
 
196
}
 
197
 
 
198
/* Ref Counting */
 
199
PIXMAN_EXPORT pixman_image_t *
 
200
pixman_image_ref (pixman_image_t *image)
 
201
{
 
202
    image->common.ref_count++;
 
203
 
 
204
    return image;
 
205
}
 
206
 
 
207
/* returns TRUE when the image is freed */
 
208
PIXMAN_EXPORT pixman_bool_t
 
209
pixman_image_unref (pixman_image_t *image)
 
210
{
 
211
    if (_pixman_image_fini (image))
 
212
    {
 
213
        free (image);
 
214
        return TRUE;
 
215
    }
 
216
 
 
217
    return FALSE;
 
218
}
 
219
 
 
220
PIXMAN_EXPORT void
 
221
pixman_image_set_destroy_function (pixman_image_t *            image,
 
222
                                   pixman_image_destroy_func_t func,
 
223
                                   void *                      data)
 
224
{
 
225
    image->common.destroy_func = func;
 
226
    image->common.destroy_data = data;
 
227
}
 
228
 
 
229
PIXMAN_EXPORT void *
 
230
pixman_image_get_destroy_data (pixman_image_t *image)
 
231
{
 
232
  return image->common.destroy_data;
 
233
}
 
234
 
 
235
void
 
236
_pixman_image_reset_clip_region (pixman_image_t *image)
 
237
{
 
238
    image->common.have_clip_region = FALSE;
 
239
}
 
240
 
 
241
/* Executive Summary: This function is a no-op that only exists
 
242
 * for historical reasons.
 
243
 *
 
244
 * There used to be a bug in the X server where it would rely on
 
245
 * out-of-bounds accesses when it was asked to composite with a
 
246
 * window as the source. It would create a pixman image pointing
 
247
 * to some bogus position in memory, but then set a clip region
 
248
 * to the position where the actual bits were.
 
249
 *
 
250
 * Due to a bug in old versions of pixman, where it would not clip
 
251
 * against the image bounds when a clip region was set, this would
 
252
 * actually work. So when the pixman bug was fixed, a workaround was
 
253
 * added to allow certain out-of-bound accesses. This function disabled
 
254
 * those workarounds.
 
255
 *
 
256
 * Since 0.21.2, pixman doesn't do these workarounds anymore, so now
 
257
 * this function is a no-op.
 
258
 */
 
259
PIXMAN_EXPORT void
 
260
pixman_disable_out_of_bounds_workaround (void)
 
261
{
 
262
}
 
263
 
 
264
static void
 
265
compute_image_info (pixman_image_t *image)
 
266
{
 
267
    pixman_format_code_t code;
 
268
    uint32_t flags = 0;
 
269
 
 
270
    /* Transform */
 
271
    if (!image->common.transform)
 
272
    {
 
273
        flags |= (FAST_PATH_ID_TRANSFORM        |
 
274
                  FAST_PATH_X_UNIT_POSITIVE     |
 
275
                  FAST_PATH_Y_UNIT_ZERO         |
 
276
                  FAST_PATH_AFFINE_TRANSFORM);
 
277
    }
 
278
    else
 
279
    {
 
280
        flags |= FAST_PATH_HAS_TRANSFORM;
 
281
 
 
282
        if (image->common.transform->matrix[2][0] == 0                  &&
 
283
            image->common.transform->matrix[2][1] == 0                  &&
 
284
            image->common.transform->matrix[2][2] == pixman_fixed_1)
 
285
        {
 
286
            flags |= FAST_PATH_AFFINE_TRANSFORM;
 
287
 
 
288
            if (image->common.transform->matrix[0][1] == 0 &&
 
289
                image->common.transform->matrix[1][0] == 0)
 
290
            {
 
291
                if (image->common.transform->matrix[0][0] == -pixman_fixed_1 &&
 
292
                    image->common.transform->matrix[1][1] == -pixman_fixed_1)
 
293
                {
 
294
                    flags |= FAST_PATH_ROTATE_180_TRANSFORM;
 
295
                }
 
296
                flags |= FAST_PATH_SCALE_TRANSFORM;
 
297
            }
 
298
            else if (image->common.transform->matrix[0][0] == 0 &&
 
299
                     image->common.transform->matrix[1][1] == 0)
 
300
            {
 
301
                pixman_fixed_t m01 = image->common.transform->matrix[0][1];
 
302
                pixman_fixed_t m10 = image->common.transform->matrix[1][0];
 
303
 
 
304
                if (m01 == -pixman_fixed_1 && m10 == pixman_fixed_1)
 
305
                    flags |= FAST_PATH_ROTATE_90_TRANSFORM;
 
306
                else if (m01 == pixman_fixed_1 && m10 == -pixman_fixed_1)
 
307
                    flags |= FAST_PATH_ROTATE_270_TRANSFORM;
 
308
            }
 
309
        }
 
310
 
 
311
        if (image->common.transform->matrix[0][0] > 0)
 
312
            flags |= FAST_PATH_X_UNIT_POSITIVE;
 
313
 
 
314
        if (image->common.transform->matrix[1][0] == 0)
 
315
            flags |= FAST_PATH_Y_UNIT_ZERO;
 
316
    }
 
317
 
 
318
    /* Filter */
 
319
    switch (image->common.filter)
 
320
    {
 
321
    case PIXMAN_FILTER_NEAREST:
 
322
    case PIXMAN_FILTER_FAST:
 
323
        flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
 
324
        break;
 
325
 
 
326
    case PIXMAN_FILTER_BILINEAR:
 
327
    case PIXMAN_FILTER_GOOD:
 
328
    case PIXMAN_FILTER_BEST:
 
329
        flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
 
330
 
 
331
        /* Here we have a chance to optimize BILINEAR filter to NEAREST if
 
332
         * they are equivalent for the currently used transformation matrix.
 
333
         */
 
334
        if (flags & FAST_PATH_ID_TRANSFORM)
 
335
        {
 
336
            flags |= FAST_PATH_NEAREST_FILTER;
 
337
        }
 
338
        else if (
 
339
            /* affine and integer translation components in matrix ... */
 
340
            ((flags & FAST_PATH_AFFINE_TRANSFORM) &&
 
341
             !pixman_fixed_frac (image->common.transform->matrix[0][2] |
 
342
                                 image->common.transform->matrix[1][2])) &&
 
343
            (
 
344
                /* ... combined with a simple rotation */
 
345
                (flags & (FAST_PATH_ROTATE_90_TRANSFORM |
 
346
                          FAST_PATH_ROTATE_180_TRANSFORM |
 
347
                          FAST_PATH_ROTATE_270_TRANSFORM)) ||
 
348
                /* ... or combined with a simple non-rotated translation */
 
349
                (image->common.transform->matrix[0][0] == pixman_fixed_1 &&
 
350
                 image->common.transform->matrix[1][1] == pixman_fixed_1 &&
 
351
                 image->common.transform->matrix[0][1] == 0 &&
 
352
                 image->common.transform->matrix[1][0] == 0)
 
353
                )
 
354
            )
 
355
        {
 
356
            /* FIXME: there are some affine-test failures, showing that
 
357
             * handling of BILINEAR and NEAREST filter is not quite
 
358
             * equivalent when getting close to 32K for the translation
 
359
             * components of the matrix. That's likely some bug, but for
 
360
             * now just skip BILINEAR->NEAREST optimization in this case.
 
361
             */
 
362
            pixman_fixed_t magic_limit = pixman_int_to_fixed (30000);
 
363
            if (image->common.transform->matrix[0][2] <= magic_limit  &&
 
364
                image->common.transform->matrix[1][2] <= magic_limit  &&
 
365
                image->common.transform->matrix[0][2] >= -magic_limit &&
 
366
                image->common.transform->matrix[1][2] >= -magic_limit)
 
367
            {
 
368
                flags |= FAST_PATH_NEAREST_FILTER;
 
369
            }
 
370
        }
 
371
        break;
 
372
 
 
373
    case PIXMAN_FILTER_CONVOLUTION:
 
374
        break;
 
375
 
 
376
    case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
 
377
        flags |= FAST_PATH_SEPARABLE_CONVOLUTION_FILTER;
 
378
        break;
 
379
 
 
380
    default:
 
381
        flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
 
382
        break;
 
383
    }
 
384
 
 
385
    /* Repeat mode */
 
386
    switch (image->common.repeat)
 
387
    {
 
388
    case PIXMAN_REPEAT_NONE:
 
389
        flags |=
 
390
            FAST_PATH_NO_REFLECT_REPEAT         |
 
391
            FAST_PATH_NO_PAD_REPEAT             |
 
392
            FAST_PATH_NO_NORMAL_REPEAT;
 
393
        break;
 
394
 
 
395
    case PIXMAN_REPEAT_REFLECT:
 
396
        flags |=
 
397
            FAST_PATH_NO_PAD_REPEAT             |
 
398
            FAST_PATH_NO_NONE_REPEAT            |
 
399
            FAST_PATH_NO_NORMAL_REPEAT;
 
400
        break;
 
401
 
 
402
    case PIXMAN_REPEAT_PAD:
 
403
        flags |=
 
404
            FAST_PATH_NO_REFLECT_REPEAT         |
 
405
            FAST_PATH_NO_NONE_REPEAT            |
 
406
            FAST_PATH_NO_NORMAL_REPEAT;
 
407
        break;
 
408
 
 
409
    default:
 
410
        flags |=
 
411
            FAST_PATH_NO_REFLECT_REPEAT         |
 
412
            FAST_PATH_NO_PAD_REPEAT             |
 
413
            FAST_PATH_NO_NONE_REPEAT;
 
414
        break;
 
415
    }
 
416
 
 
417
    /* Component alpha */
 
418
    if (image->common.component_alpha)
 
419
        flags |= FAST_PATH_COMPONENT_ALPHA;
 
420
    else
 
421
        flags |= FAST_PATH_UNIFIED_ALPHA;
 
422
 
 
423
    flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);
 
424
 
 
425
    /* Type specific checks */
 
426
    switch (image->type)
 
427
    {
 
428
    case SOLID:
 
429
        code = PIXMAN_solid;
 
430
 
 
431
        if (image->solid.color.alpha == 0xffff)
 
432
            flags |= FAST_PATH_IS_OPAQUE;
 
433
        break;
 
434
 
 
435
    case BITS:
 
436
        if (image->bits.width == 1      &&
 
437
            image->bits.height == 1     &&
 
438
            image->common.repeat != PIXMAN_REPEAT_NONE)
 
439
        {
 
440
            code = PIXMAN_solid;
 
441
        }
 
442
        else
 
443
        {
 
444
            code = image->bits.format;
 
445
            flags |= FAST_PATH_BITS_IMAGE;
 
446
        }
 
447
 
 
448
        if (!PIXMAN_FORMAT_A (image->bits.format)                               &&
 
449
            PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY         &&
 
450
            PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR)
 
451
        {
 
452
            flags |= FAST_PATH_SAMPLES_OPAQUE;
 
453
 
 
454
            if (image->common.repeat != PIXMAN_REPEAT_NONE)
 
455
                flags |= FAST_PATH_IS_OPAQUE;
 
456
        }
 
457
 
 
458
        if (image->bits.read_func || image->bits.write_func)
 
459
            flags &= ~FAST_PATH_NO_ACCESSORS;
 
460
 
 
461
        if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
 
462
            flags &= ~FAST_PATH_NARROW_FORMAT;
 
463
        break;
 
464
 
 
465
    case RADIAL:
 
466
        code = PIXMAN_unknown;
 
467
 
 
468
        /*
 
469
         * As explained in pixman-radial-gradient.c, every point of
 
470
         * the plane has a valid associated radius (and thus will be
 
471
         * colored) if and only if a is negative (i.e. one of the two
 
472
         * circles contains the other one).
 
473
         */
 
474
 
 
475
        if (image->radial.a >= 0)
 
476
            break;
 
477
 
 
478
        /* Fall through */
 
479
 
 
480
    case CONICAL:
 
481
    case LINEAR:
 
482
        code = PIXMAN_unknown;
 
483
 
 
484
        if (image->common.repeat != PIXMAN_REPEAT_NONE)
 
485
        {
 
486
            int i;
 
487
 
 
488
            flags |= FAST_PATH_IS_OPAQUE;
 
489
            for (i = 0; i < image->gradient.n_stops; ++i)
 
490
            {
 
491
                if (image->gradient.stops[i].color.alpha != 0xffff)
 
492
                {
 
493
                    flags &= ~FAST_PATH_IS_OPAQUE;
 
494
                    break;
 
495
                }
 
496
            }
 
497
        }
 
498
        break;
 
499
 
 
500
    default:
 
501
        code = PIXMAN_unknown;
 
502
        break;
 
503
    }
 
504
 
 
505
    /* Alpha maps are only supported for BITS images, so it's always
 
506
     * safe to ignore their presense for non-BITS images
 
507
     */
 
508
    if (!image->common.alpha_map || image->type != BITS)
 
509
    {
 
510
        flags |= FAST_PATH_NO_ALPHA_MAP;
 
511
    }
 
512
    else
 
513
    {
 
514
        if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
 
515
            flags &= ~FAST_PATH_NARROW_FORMAT;
 
516
    }
 
517
 
 
518
    /* Both alpha maps and convolution filters can introduce
 
519
     * non-opaqueness in otherwise opaque images. Also
 
520
     * an image with component alpha turned on is only opaque
 
521
     * if all channels are opaque, so we simply turn it off
 
522
     * unconditionally for those images.
 
523
     */
 
524
    if (image->common.alpha_map                                         ||
 
525
        image->common.filter == PIXMAN_FILTER_CONVOLUTION               ||
 
526
        image->common.filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION     ||
 
527
        image->common.component_alpha)
 
528
    {
 
529
        flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
 
530
    }
 
531
 
 
532
    image->common.flags = flags;
 
533
    image->common.extended_format_code = code;
 
534
}
 
535
 
 
536
void
 
537
_pixman_image_validate (pixman_image_t *image)
 
538
{
 
539
    if (image->common.dirty)
 
540
    {
 
541
        compute_image_info (image);
 
542
 
 
543
        /* It is important that property_changed is
 
544
         * called *after* compute_image_info() because
 
545
         * property_changed() can make use of the flags
 
546
         * to set up accessors etc.
 
547
         */
 
548
        if (image->common.property_changed)
 
549
            image->common.property_changed (image);
 
550
 
 
551
        image->common.dirty = FALSE;
 
552
    }
 
553
 
 
554
    if (image->common.alpha_map)
 
555
        _pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
 
556
}
 
557
 
 
558
PIXMAN_EXPORT pixman_bool_t
 
559
pixman_image_set_clip_region32 (pixman_image_t *   image,
 
560
                                pixman_region32_t *region)
 
561
{
 
562
    image_common_t *common = (image_common_t *)image;
 
563
    pixman_bool_t result;
 
564
 
 
565
    if (region)
 
566
    {
 
567
        if ((result = pixman_region32_copy (&common->clip_region, region)))
 
568
            image->common.have_clip_region = TRUE;
 
569
    }
 
570
    else
 
571
    {
 
572
        _pixman_image_reset_clip_region (image);
 
573
 
 
574
        result = TRUE;
 
575
    }
 
576
 
 
577
    image_property_changed (image);
 
578
 
 
579
    return result;
 
580
}
 
581
 
 
582
PIXMAN_EXPORT pixman_bool_t
 
583
pixman_image_set_clip_region (pixman_image_t *   image,
 
584
                              pixman_region16_t *region)
 
585
{
 
586
    image_common_t *common = (image_common_t *)image;
 
587
    pixman_bool_t result;
 
588
 
 
589
    if (region)
 
590
    {
 
591
        if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
 
592
            image->common.have_clip_region = TRUE;
 
593
    }
 
594
    else
 
595
    {
 
596
        _pixman_image_reset_clip_region (image);
 
597
 
 
598
        result = TRUE;
 
599
    }
 
600
 
 
601
    image_property_changed (image);
 
602
 
 
603
    return result;
 
604
}
 
605
 
 
606
PIXMAN_EXPORT void
 
607
pixman_image_set_has_client_clip (pixman_image_t *image,
 
608
                                  pixman_bool_t   client_clip)
 
609
{
 
610
    image->common.client_clip = client_clip;
 
611
}
 
612
 
 
613
PIXMAN_EXPORT pixman_bool_t
 
614
pixman_image_set_transform (pixman_image_t *          image,
 
615
                            const pixman_transform_t *transform)
 
616
{
 
617
    static const pixman_transform_t id =
 
618
    {
 
619
        { { pixman_fixed_1, 0, 0 },
 
620
          { 0, pixman_fixed_1, 0 },
 
621
          { 0, 0, pixman_fixed_1 } }
 
622
    };
 
623
 
 
624
    image_common_t *common = (image_common_t *)image;
 
625
    pixman_bool_t result;
 
626
 
 
627
    if (common->transform == transform)
 
628
        return TRUE;
 
629
 
 
630
    if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
 
631
    {
 
632
        free (common->transform);
 
633
        common->transform = NULL;
 
634
        result = TRUE;
 
635
 
 
636
        goto out;
 
637
    }
 
638
 
 
639
    if (common->transform &&
 
640
        memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0)
 
641
    {
 
642
        return TRUE;
 
643
    }
 
644
 
 
645
    if (common->transform == NULL)
 
646
        common->transform = malloc (sizeof (pixman_transform_t));
 
647
 
 
648
    if (common->transform == NULL)
 
649
    {
 
650
        result = FALSE;
 
651
 
 
652
        goto out;
 
653
    }
 
654
 
 
655
    memcpy (common->transform, transform, sizeof(pixman_transform_t));
 
656
 
 
657
    result = TRUE;
 
658
 
 
659
out:
 
660
    image_property_changed (image);
 
661
 
 
662
    return result;
 
663
}
 
664
 
 
665
PIXMAN_EXPORT void
 
666
pixman_image_set_repeat (pixman_image_t *image,
 
667
                         pixman_repeat_t repeat)
 
668
{
 
669
    if (image->common.repeat == repeat)
 
670
        return;
 
671
 
 
672
    image->common.repeat = repeat;
 
673
 
 
674
    image_property_changed (image);
 
675
}
 
676
 
 
677
PIXMAN_EXPORT pixman_bool_t
 
678
pixman_image_set_filter (pixman_image_t *      image,
 
679
                         pixman_filter_t       filter,
 
680
                         const pixman_fixed_t *params,
 
681
                         int                   n_params)
 
682
{
 
683
    image_common_t *common = (image_common_t *)image;
 
684
    pixman_fixed_t *new_params;
 
685
 
 
686
    if (params == common->filter_params && filter == common->filter)
 
687
        return TRUE;
 
688
 
 
689
    if (filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
 
690
    {
 
691
        int width = pixman_fixed_to_int (params[0]);
 
692
        int height = pixman_fixed_to_int (params[1]);
 
693
        int x_phase_bits = pixman_fixed_to_int (params[2]);
 
694
        int y_phase_bits = pixman_fixed_to_int (params[3]);
 
695
        int n_x_phases = (1 << x_phase_bits);
 
696
        int n_y_phases = (1 << y_phase_bits);
 
697
 
 
698
        return_val_if_fail (
 
699
            n_params == 4 + n_x_phases * width + n_y_phases * height, FALSE);
 
700
    }
 
701
    
 
702
    new_params = NULL;
 
703
    if (params)
 
704
    {
 
705
        new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
 
706
        if (!new_params)
 
707
            return FALSE;
 
708
 
 
709
        memcpy (new_params,
 
710
                params, n_params * sizeof (pixman_fixed_t));
 
711
    }
 
712
 
 
713
    common->filter = filter;
 
714
 
 
715
    if (common->filter_params)
 
716
        free (common->filter_params);
 
717
 
 
718
    common->filter_params = new_params;
 
719
    common->n_filter_params = n_params;
 
720
 
 
721
    image_property_changed (image);
 
722
    return TRUE;
 
723
}
 
724
 
 
725
PIXMAN_EXPORT void
 
726
pixman_image_set_source_clipping (pixman_image_t *image,
 
727
                                  pixman_bool_t   clip_sources)
 
728
{
 
729
    if (image->common.clip_sources == clip_sources)
 
730
        return;
 
731
 
 
732
    image->common.clip_sources = clip_sources;
 
733
 
 
734
    image_property_changed (image);
 
735
}
 
736
 
 
737
/* Unlike all the other property setters, this function does not
 
738
 * copy the content of indexed. Doing this copying is simply
 
739
 * way, way too expensive.
 
740
 */
 
741
PIXMAN_EXPORT void
 
742
pixman_image_set_indexed (pixman_image_t *        image,
 
743
                          const pixman_indexed_t *indexed)
 
744
{
 
745
    bits_image_t *bits = (bits_image_t *)image;
 
746
 
 
747
    if (bits->indexed == indexed)
 
748
        return;
 
749
 
 
750
    bits->indexed = indexed;
 
751
 
 
752
    image_property_changed (image);
 
753
}
 
754
 
 
755
PIXMAN_EXPORT void
 
756
pixman_image_set_alpha_map (pixman_image_t *image,
 
757
                            pixman_image_t *alpha_map,
 
758
                            int16_t         x,
 
759
                            int16_t         y)
 
760
{
 
761
    image_common_t *common = (image_common_t *)image;
 
762
 
 
763
    return_if_fail (!alpha_map || alpha_map->type == BITS);
 
764
 
 
765
    if (alpha_map && common->alpha_count > 0)
 
766
    {
 
767
        /* If this image is being used as an alpha map itself,
 
768
         * then you can't give it an alpha map of its own.
 
769
         */
 
770
        return;
 
771
    }
 
772
 
 
773
    if (alpha_map && alpha_map->common.alpha_map)
 
774
    {
 
775
        /* If the image has an alpha map of its own,
 
776
         * then it can't be used as an alpha map itself
 
777
         */
 
778
        return;
 
779
    }
 
780
 
 
781
    if (common->alpha_map != (bits_image_t *)alpha_map)
 
782
    {
 
783
        if (common->alpha_map)
 
784
        {
 
785
            common->alpha_map->common.alpha_count--;
 
786
 
 
787
            pixman_image_unref ((pixman_image_t *)common->alpha_map);
 
788
        }
 
789
 
 
790
        if (alpha_map)
 
791
        {
 
792
            common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
 
793
 
 
794
            common->alpha_map->common.alpha_count++;
 
795
        }
 
796
        else
 
797
        {
 
798
            common->alpha_map = NULL;
 
799
        }
 
800
    }
 
801
 
 
802
    common->alpha_origin_x = x;
 
803
    common->alpha_origin_y = y;
 
804
 
 
805
    image_property_changed (image);
 
806
}
 
807
 
 
808
PIXMAN_EXPORT void
 
809
pixman_image_set_component_alpha   (pixman_image_t *image,
 
810
                                    pixman_bool_t   component_alpha)
 
811
{
 
812
    if (image->common.component_alpha == component_alpha)
 
813
        return;
 
814
 
 
815
    image->common.component_alpha = component_alpha;
 
816
 
 
817
    image_property_changed (image);
 
818
}
 
819
 
 
820
PIXMAN_EXPORT pixman_bool_t
 
821
pixman_image_get_component_alpha   (pixman_image_t       *image)
 
822
{
 
823
    return image->common.component_alpha;
 
824
}
 
825
 
 
826
PIXMAN_EXPORT void
 
827
pixman_image_set_accessors (pixman_image_t *           image,
 
828
                            pixman_read_memory_func_t  read_func,
 
829
                            pixman_write_memory_func_t write_func)
 
830
{
 
831
    return_if_fail (image != NULL);
 
832
 
 
833
    if (image->type == BITS)
 
834
    {
 
835
        image->bits.read_func = read_func;
 
836
        image->bits.write_func = write_func;
 
837
 
 
838
        image_property_changed (image);
 
839
    }
 
840
}
 
841
 
 
842
PIXMAN_EXPORT uint32_t *
 
843
pixman_image_get_data (pixman_image_t *image)
 
844
{
 
845
    if (image->type == BITS)
 
846
        return image->bits.bits;
 
847
 
 
848
    return NULL;
 
849
}
 
850
 
 
851
PIXMAN_EXPORT int
 
852
pixman_image_get_width (pixman_image_t *image)
 
853
{
 
854
    if (image->type == BITS)
 
855
        return image->bits.width;
 
856
 
 
857
    return 0;
 
858
}
 
859
 
 
860
PIXMAN_EXPORT int
 
861
pixman_image_get_height (pixman_image_t *image)
 
862
{
 
863
    if (image->type == BITS)
 
864
        return image->bits.height;
 
865
 
 
866
    return 0;
 
867
}
 
868
 
 
869
PIXMAN_EXPORT int
 
870
pixman_image_get_stride (pixman_image_t *image)
 
871
{
 
872
    if (image->type == BITS)
 
873
        return image->bits.rowstride * (int) sizeof (uint32_t);
 
874
 
 
875
    return 0;
 
876
}
 
877
 
 
878
PIXMAN_EXPORT int
 
879
pixman_image_get_depth (pixman_image_t *image)
 
880
{
 
881
    if (image->type == BITS)
 
882
        return PIXMAN_FORMAT_DEPTH (image->bits.format);
 
883
 
 
884
    return 0;
 
885
}
 
886
 
 
887
PIXMAN_EXPORT pixman_format_code_t
 
888
pixman_image_get_format (pixman_image_t *image)
 
889
{
 
890
    if (image->type == BITS)
 
891
        return image->bits.format;
 
892
 
 
893
    return PIXMAN_null;
 
894
}
 
895
 
 
896
uint32_t
 
897
_pixman_image_get_solid (pixman_implementation_t *imp,
 
898
                         pixman_image_t *         image,
 
899
                         pixman_format_code_t     format)
 
900
{
 
901
    uint32_t result;
 
902
 
 
903
    if (image->type == SOLID)
 
904
    {
 
905
        result = image->solid.color_32;
 
906
    }
 
907
    else if (image->type == BITS)
 
908
    {
 
909
        if (image->bits.format == PIXMAN_a8r8g8b8)
 
910
            result = image->bits.bits[0];
 
911
        else if (image->bits.format == PIXMAN_x8r8g8b8)
 
912
            result = image->bits.bits[0] | 0xff000000;
 
913
        else if (image->bits.format == PIXMAN_a8)
 
914
            result = (*(uint8_t *)image->bits.bits) << 24;
 
915
        else
 
916
            goto otherwise;
 
917
    }
 
918
    else
 
919
    {
 
920
        pixman_iter_t iter;
 
921
 
 
922
    otherwise:
 
923
        _pixman_implementation_iter_init (
 
924
            imp, &iter, image, 0, 0, 1, 1,
 
925
            (uint8_t *)&result,
 
926
            ITER_NARROW | ITER_SRC, image->common.flags);
 
927
        
 
928
        result = *iter.get_scanline (&iter, NULL);
 
929
 
 
930
        if (iter.fini)
 
931
            iter.fini (&iter);
 
932
    }
 
933
 
 
934
    /* If necessary, convert RGB <--> BGR. */
 
935
    if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB
 
936
        && PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB)
 
937
    {
 
938
        result = (((result & 0xff000000) >>  0) |
 
939
                  ((result & 0x00ff0000) >> 16) |
 
940
                  ((result & 0x0000ff00) >>  0) |
 
941
                  ((result & 0x000000ff) << 16));
 
942
    }
 
943
 
 
944
    return result;
 
945
}