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