2 * Copyright © 2000 SuSE, Inc.
3 * Copyright © 2007 Red Hat, Inc.
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.
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.
32 #include "pixman-private.h"
33 #include "pixman-combine32.h"
36 _pixman_init_gradient (gradient_t * gradient,
37 const pixman_gradient_stop_t *stops,
40 return_val_if_fail (n_stops > 0, FALSE);
42 gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t));
46 memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
48 gradient->n_stops = n_stops;
54 _pixman_image_allocate (void)
56 pixman_image_t *image = malloc (sizeof (pixman_image_t));
60 image_common_t *common = &image->common;
62 pixman_region32_init (&common->clip_region);
64 common->alpha_count = 0;
65 common->have_clip_region = FALSE;
66 common->clip_sources = FALSE;
67 common->transform = NULL;
68 common->repeat = PIXMAN_REPEAT_NONE;
69 common->filter = PIXMAN_FILTER_NEAREST;
70 common->filter_params = NULL;
71 common->n_filter_params = 0;
72 common->alpha_map = NULL;
73 common->component_alpha = FALSE;
74 common->ref_count = 1;
75 common->property_changed = NULL;
76 common->client_clip = FALSE;
77 common->destroy_func = NULL;
78 common->destroy_data = NULL;
86 image_property_changed (pixman_image_t *image)
88 image->common.dirty = TRUE;
92 PIXMAN_EXPORT pixman_image_t *
93 pixman_image_ref (pixman_image_t *image)
95 image->common.ref_count++;
100 /* returns TRUE when the image is freed */
101 PIXMAN_EXPORT pixman_bool_t
102 pixman_image_unref (pixman_image_t *image)
104 image_common_t *common = (image_common_t *)image;
108 if (common->ref_count == 0)
110 if (image->common.destroy_func)
111 image->common.destroy_func (image, image->common.destroy_data);
113 pixman_region32_fini (&common->clip_region);
115 if (common->transform)
116 free (common->transform);
118 if (common->filter_params)
119 free (common->filter_params);
121 if (common->alpha_map)
122 pixman_image_unref ((pixman_image_t *)common->alpha_map);
124 if (image->type == LINEAR ||
125 image->type == RADIAL ||
126 image->type == CONICAL)
128 if (image->gradient.stops)
129 free (image->gradient.stops);
132 if (image->type == BITS && image->bits.free_me)
133 free (image->bits.free_me);
144 pixman_image_set_destroy_function (pixman_image_t * image,
145 pixman_image_destroy_func_t func,
148 image->common.destroy_func = func;
149 image->common.destroy_data = data;
153 pixman_image_get_destroy_data (pixman_image_t *image)
155 return image->common.destroy_data;
159 _pixman_image_reset_clip_region (pixman_image_t *image)
161 image->common.have_clip_region = FALSE;
164 /* Executive Summary: This function is a no-op that only exists
165 * for historical reasons.
167 * There used to be a bug in the X server where it would rely on
168 * out-of-bounds accesses when it was asked to composite with a
169 * window as the source. It would create a pixman image pointing
170 * to some bogus position in memory, but then set a clip region
171 * to the position where the actual bits were.
173 * Due to a bug in old versions of pixman, where it would not clip
174 * against the image bounds when a clip region was set, this would
175 * actually work. So when the pixman bug was fixed, a workaround was
176 * added to allow certain out-of-bound accesses. This function disabled
179 * Since 0.21.2, pixman doesn't do these workarounds anymore, so now
180 * this function is a no-op.
183 pixman_disable_out_of_bounds_workaround (void)
188 compute_image_info (pixman_image_t *image)
190 pixman_format_code_t code;
194 if (!image->common.transform)
196 flags |= (FAST_PATH_ID_TRANSFORM |
197 FAST_PATH_X_UNIT_POSITIVE |
198 FAST_PATH_Y_UNIT_ZERO |
199 FAST_PATH_AFFINE_TRANSFORM);
203 flags |= FAST_PATH_HAS_TRANSFORM;
205 if (image->common.transform->matrix[2][0] == 0 &&
206 image->common.transform->matrix[2][1] == 0 &&
207 image->common.transform->matrix[2][2] == pixman_fixed_1)
209 flags |= FAST_PATH_AFFINE_TRANSFORM;
211 if (image->common.transform->matrix[0][1] == 0 &&
212 image->common.transform->matrix[1][0] == 0)
214 flags |= FAST_PATH_SCALE_TRANSFORM;
218 if (image->common.transform->matrix[0][0] > 0)
219 flags |= FAST_PATH_X_UNIT_POSITIVE;
221 if (image->common.transform->matrix[1][0] == 0)
222 flags |= FAST_PATH_Y_UNIT_ZERO;
226 switch (image->common.filter)
228 case PIXMAN_FILTER_NEAREST:
229 case PIXMAN_FILTER_FAST:
230 flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
233 case PIXMAN_FILTER_BILINEAR:
234 case PIXMAN_FILTER_GOOD:
235 case PIXMAN_FILTER_BEST:
236 flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
239 case PIXMAN_FILTER_CONVOLUTION:
243 flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
248 switch (image->common.repeat)
250 case PIXMAN_REPEAT_NONE:
252 FAST_PATH_NO_REFLECT_REPEAT |
253 FAST_PATH_NO_PAD_REPEAT |
254 FAST_PATH_NO_NORMAL_REPEAT;
257 case PIXMAN_REPEAT_REFLECT:
259 FAST_PATH_NO_PAD_REPEAT |
260 FAST_PATH_NO_NONE_REPEAT |
261 FAST_PATH_NO_NORMAL_REPEAT;
264 case PIXMAN_REPEAT_PAD:
266 FAST_PATH_NO_REFLECT_REPEAT |
267 FAST_PATH_NO_NONE_REPEAT |
268 FAST_PATH_NO_NORMAL_REPEAT;
273 FAST_PATH_NO_REFLECT_REPEAT |
274 FAST_PATH_NO_PAD_REPEAT |
275 FAST_PATH_NO_NONE_REPEAT;
279 /* Component alpha */
280 if (image->common.component_alpha)
281 flags |= FAST_PATH_COMPONENT_ALPHA;
283 flags |= FAST_PATH_UNIFIED_ALPHA;
285 flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);
287 /* Type specific checks */
293 if (image->solid.color.alpha == 0xffff)
294 flags |= FAST_PATH_IS_OPAQUE;
298 if (image->bits.width == 1 &&
299 image->bits.height == 1 &&
300 image->common.repeat != PIXMAN_REPEAT_NONE)
306 code = image->bits.format;
309 if (!PIXMAN_FORMAT_A (image->bits.format) &&
310 PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY &&
311 PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR)
313 flags |= FAST_PATH_SAMPLES_OPAQUE;
315 if (image->common.repeat != PIXMAN_REPEAT_NONE)
316 flags |= FAST_PATH_IS_OPAQUE;
319 if (image->bits.read_func || image->bits.write_func)
320 flags &= ~FAST_PATH_NO_ACCESSORS;
322 if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
323 flags &= ~FAST_PATH_NARROW_FORMAT;
327 code = PIXMAN_unknown;
330 * As explained in pixman-radial-gradient.c, every point of
331 * the plane has a valid associated radius (and thus will be
332 * colored) if and only if a is negative (i.e. one of the two
333 * circles contains the other one).
336 if (image->radial.a >= 0)
343 code = PIXMAN_unknown;
345 if (image->common.repeat != PIXMAN_REPEAT_NONE)
349 flags |= FAST_PATH_IS_OPAQUE;
350 for (i = 0; i < image->gradient.n_stops; ++i)
352 if (image->gradient.stops[i].color.alpha != 0xffff)
354 flags &= ~FAST_PATH_IS_OPAQUE;
362 code = PIXMAN_unknown;
367 if (!image->common.alpha_map)
369 flags |= FAST_PATH_NO_ALPHA_MAP;
373 if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
374 flags &= ~FAST_PATH_NARROW_FORMAT;
377 /* Both alpha maps and convolution filters can introduce
378 * non-opaqueness in otherwise opaque images. Also
379 * an image with component alpha turned on is only opaque
380 * if all channels are opaque, so we simply turn it off
381 * unconditionally for those images.
383 if (image->common.alpha_map ||
384 image->common.filter == PIXMAN_FILTER_CONVOLUTION ||
385 image->common.component_alpha)
387 flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
390 image->common.flags = flags;
391 image->common.extended_format_code = code;
395 _pixman_image_validate (pixman_image_t *image)
397 if (image->common.dirty)
399 compute_image_info (image);
401 /* It is important that property_changed is
402 * called *after* compute_image_info() because
403 * property_changed() can make use of the flags
404 * to set up accessors etc.
406 if (image->common.property_changed)
407 image->common.property_changed (image);
409 image->common.dirty = FALSE;
412 if (image->common.alpha_map)
413 _pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
416 PIXMAN_EXPORT pixman_bool_t
417 pixman_image_set_clip_region32 (pixman_image_t * image,
418 pixman_region32_t *region)
420 image_common_t *common = (image_common_t *)image;
421 pixman_bool_t result;
425 if ((result = pixman_region32_copy (&common->clip_region, region)))
426 image->common.have_clip_region = TRUE;
430 _pixman_image_reset_clip_region (image);
435 image_property_changed (image);
440 PIXMAN_EXPORT pixman_bool_t
441 pixman_image_set_clip_region (pixman_image_t * image,
442 pixman_region16_t *region)
444 image_common_t *common = (image_common_t *)image;
445 pixman_bool_t result;
449 if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
450 image->common.have_clip_region = TRUE;
454 _pixman_image_reset_clip_region (image);
459 image_property_changed (image);
465 pixman_image_set_has_client_clip (pixman_image_t *image,
466 pixman_bool_t client_clip)
468 image->common.client_clip = client_clip;
471 PIXMAN_EXPORT pixman_bool_t
472 pixman_image_set_transform (pixman_image_t * image,
473 const pixman_transform_t *transform)
475 static const pixman_transform_t id =
477 { { pixman_fixed_1, 0, 0 },
478 { 0, pixman_fixed_1, 0 },
479 { 0, 0, pixman_fixed_1 } }
482 image_common_t *common = (image_common_t *)image;
483 pixman_bool_t result;
485 if (common->transform == transform)
488 if (memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
490 free (common->transform);
491 common->transform = NULL;
497 if (common->transform == NULL)
498 common->transform = malloc (sizeof (pixman_transform_t));
500 if (common->transform == NULL)
507 memcpy (common->transform, transform, sizeof(pixman_transform_t));
512 image_property_changed (image);
518 pixman_image_set_repeat (pixman_image_t *image,
519 pixman_repeat_t repeat)
521 image->common.repeat = repeat;
523 image_property_changed (image);
526 PIXMAN_EXPORT pixman_bool_t
527 pixman_image_set_filter (pixman_image_t * image,
528 pixman_filter_t filter,
529 const pixman_fixed_t *params,
532 image_common_t *common = (image_common_t *)image;
533 pixman_fixed_t *new_params;
535 if (params == common->filter_params && filter == common->filter)
541 new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
546 params, n_params * sizeof (pixman_fixed_t));
549 common->filter = filter;
551 if (common->filter_params)
552 free (common->filter_params);
554 common->filter_params = new_params;
555 common->n_filter_params = n_params;
557 image_property_changed (image);
562 pixman_image_set_source_clipping (pixman_image_t *image,
563 pixman_bool_t clip_sources)
565 image->common.clip_sources = clip_sources;
567 image_property_changed (image);
570 /* Unlike all the other property setters, this function does not
571 * copy the content of indexed. Doing this copying is simply
572 * way, way too expensive.
575 pixman_image_set_indexed (pixman_image_t * image,
576 const pixman_indexed_t *indexed)
578 bits_image_t *bits = (bits_image_t *)image;
580 bits->indexed = indexed;
582 image_property_changed (image);
586 pixman_image_set_alpha_map (pixman_image_t *image,
587 pixman_image_t *alpha_map,
591 image_common_t *common = (image_common_t *)image;
593 return_if_fail (!alpha_map || alpha_map->type == BITS);
595 if (alpha_map && common->alpha_count > 0)
597 /* If this image is being used as an alpha map itself,
598 * then you can't give it an alpha map of its own.
603 if (alpha_map && alpha_map->common.alpha_map)
605 /* If the image has an alpha map of its own,
606 * then it can't be used as an alpha map itself
611 if (common->alpha_map != (bits_image_t *)alpha_map)
613 if (common->alpha_map)
615 common->alpha_map->common.alpha_count--;
617 pixman_image_unref ((pixman_image_t *)common->alpha_map);
622 common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
624 common->alpha_map->common.alpha_count++;
628 common->alpha_map = NULL;
632 common->alpha_origin_x = x;
633 common->alpha_origin_y = y;
635 image_property_changed (image);
639 pixman_image_set_component_alpha (pixman_image_t *image,
640 pixman_bool_t component_alpha)
642 image->common.component_alpha = component_alpha;
644 image_property_changed (image);
647 PIXMAN_EXPORT pixman_bool_t
648 pixman_image_get_component_alpha (pixman_image_t *image)
650 return image->common.component_alpha;
654 pixman_image_set_accessors (pixman_image_t * image,
655 pixman_read_memory_func_t read_func,
656 pixman_write_memory_func_t write_func)
658 return_if_fail (image != NULL);
660 if (image->type == BITS)
662 image->bits.read_func = read_func;
663 image->bits.write_func = write_func;
665 image_property_changed (image);
669 PIXMAN_EXPORT uint32_t *
670 pixman_image_get_data (pixman_image_t *image)
672 if (image->type == BITS)
673 return image->bits.bits;
679 pixman_image_get_width (pixman_image_t *image)
681 if (image->type == BITS)
682 return image->bits.width;
688 pixman_image_get_height (pixman_image_t *image)
690 if (image->type == BITS)
691 return image->bits.height;
697 pixman_image_get_stride (pixman_image_t *image)
699 if (image->type == BITS)
700 return image->bits.rowstride * (int) sizeof (uint32_t);
706 pixman_image_get_depth (pixman_image_t *image)
708 if (image->type == BITS)
709 return PIXMAN_FORMAT_DEPTH (image->bits.format);
714 PIXMAN_EXPORT pixman_format_code_t
715 pixman_image_get_format (pixman_image_t *image)
717 if (image->type == BITS)
718 return image->bits.format;
724 _pixman_image_get_solid (pixman_implementation_t *imp,
725 pixman_image_t * image,
726 pixman_format_code_t format)
731 _pixman_implementation_src_iter_init (
732 imp, &iter, image, 0, 0, 1, 1,
733 (uint8_t *)&result, ITER_NARROW);
735 result = *iter.get_scanline (&iter, NULL);
737 /* If necessary, convert RGB <--> BGR. */
738 if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB)
740 result = (((result & 0xff000000) >> 0) |
741 ((result & 0x00ff0000) >> 16) |
742 ((result & 0x0000ff00) >> 0) |
743 ((result & 0x000000ff) << 16));