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 : pixman_bool_t
35 0 : _pixman_init_gradient (gradient_t * gradient,
36 : const pixman_gradient_stop_t *stops,
37 : int n_stops)
38 : {
39 0 : return_val_if_fail (n_stops > 0, FALSE);
40 :
41 0 : gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t));
42 0 : if (!gradient->stops)
43 0 : return FALSE;
44 :
45 0 : memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
46 :
47 0 : gradient->n_stops = n_stops;
48 :
49 0 : return TRUE;
50 : }
51 :
52 : pixman_image_t *
53 75 : _pixman_image_allocate (void)
54 : {
55 75 : pixman_image_t *image = malloc (sizeof (pixman_image_t));
56 :
57 75 : if (image)
58 : {
59 75 : image_common_t *common = &image->common;
60 :
61 75 : pixman_region32_init (&common->clip_region);
62 :
63 75 : common->alpha_count = 0;
64 75 : common->have_clip_region = FALSE;
65 75 : common->clip_sources = FALSE;
66 75 : common->transform = NULL;
67 75 : common->repeat = PIXMAN_REPEAT_NONE;
68 75 : common->filter = PIXMAN_FILTER_NEAREST;
69 75 : common->filter_params = NULL;
70 75 : common->n_filter_params = 0;
71 75 : common->alpha_map = NULL;
72 75 : common->component_alpha = FALSE;
73 75 : common->ref_count = 1;
74 75 : common->property_changed = NULL;
75 75 : common->client_clip = FALSE;
76 75 : common->destroy_func = NULL;
77 75 : common->destroy_data = NULL;
78 75 : common->dirty = TRUE;
79 : }
80 :
81 75 : return image;
82 : }
83 :
84 : static void
85 20 : image_property_changed (pixman_image_t *image)
86 : {
87 20 : image->common.dirty = TRUE;
88 20 : }
89 :
90 : /* Ref Counting */
91 : PIXMAN_EXPORT pixman_image_t *
92 37 : pixman_image_ref (pixman_image_t *image)
93 : {
94 37 : image->common.ref_count++;
95 :
96 37 : return image;
97 : }
98 :
99 : /* returns TRUE when the image is freed */
100 : PIXMAN_EXPORT pixman_bool_t
101 112 : pixman_image_unref (pixman_image_t *image)
102 : {
103 112 : image_common_t *common = (image_common_t *)image;
104 :
105 112 : common->ref_count--;
106 :
107 112 : if (common->ref_count == 0)
108 : {
109 75 : if (image->common.destroy_func)
110 0 : image->common.destroy_func (image, image->common.destroy_data);
111 :
112 75 : pixman_region32_fini (&common->clip_region);
113 :
114 75 : if (common->transform)
115 10 : free (common->transform);
116 :
117 75 : if (common->filter_params)
118 0 : free (common->filter_params);
119 :
120 75 : if (common->alpha_map)
121 0 : pixman_image_unref ((pixman_image_t *)common->alpha_map);
122 :
123 150 : if (image->type == LINEAR ||
124 150 : image->type == RADIAL ||
125 75 : image->type == CONICAL)
126 : {
127 0 : if (image->gradient.stops)
128 0 : free (image->gradient.stops);
129 : }
130 :
131 75 : if (image->type == BITS && image->bits.free_me)
132 0 : free (image->bits.free_me);
133 :
134 75 : free (image);
135 :
136 75 : return TRUE;
137 : }
138 :
139 37 : return FALSE;
140 : }
141 :
142 : PIXMAN_EXPORT void
143 0 : pixman_image_set_destroy_function (pixman_image_t * image,
144 : pixman_image_destroy_func_t func,
145 : void * data)
146 : {
147 0 : image->common.destroy_func = func;
148 0 : image->common.destroy_data = data;
149 0 : }
150 :
151 : PIXMAN_EXPORT void *
152 0 : pixman_image_get_destroy_data (pixman_image_t *image)
153 : {
154 0 : return image->common.destroy_data;
155 : }
156 :
157 : void
158 75 : _pixman_image_reset_clip_region (pixman_image_t *image)
159 : {
160 75 : image->common.have_clip_region = FALSE;
161 75 : }
162 :
163 : /* Executive Summary: This function is a no-op that only exists
164 : * for historical reasons.
165 : *
166 : * There used to be a bug in the X server where it would rely on
167 : * out-of-bounds accesses when it was asked to composite with a
168 : * window as the source. It would create a pixman image pointing
169 : * to some bogus position in memory, but then set a clip region
170 : * to the position where the actual bits were.
171 : *
172 : * Due to a bug in old versions of pixman, where it would not clip
173 : * against the image bounds when a clip region was set, this would
174 : * actually work. So when the pixman bug was fixed, a workaround was
175 : * added to allow certain out-of-bound accesses. This function disabled
176 : * those workarounds.
177 : *
178 : * Since 0.21.2, pixman doesn't do these workarounds anymore, so now
179 : * this function is a no-op.
180 : */
181 : PIXMAN_EXPORT void
182 0 : pixman_disable_out_of_bounds_workaround (void)
183 : {
184 0 : }
185 :
186 : static void
187 72 : compute_image_info (pixman_image_t *image)
188 : {
189 : pixman_format_code_t code;
190 72 : uint32_t flags = 0;
191 :
192 : /* Transform */
193 72 : if (!image->common.transform)
194 : {
195 62 : flags |= (FAST_PATH_ID_TRANSFORM |
196 : FAST_PATH_X_UNIT_POSITIVE |
197 : FAST_PATH_Y_UNIT_ZERO |
198 : FAST_PATH_AFFINE_TRANSFORM);
199 : }
200 : else
201 : {
202 10 : flags |= FAST_PATH_HAS_TRANSFORM;
203 :
204 20 : if (image->common.transform->matrix[2][0] == 0 &&
205 20 : image->common.transform->matrix[2][1] == 0 &&
206 10 : image->common.transform->matrix[2][2] == pixman_fixed_1)
207 : {
208 10 : flags |= FAST_PATH_AFFINE_TRANSFORM;
209 :
210 20 : if (image->common.transform->matrix[0][1] == 0 &&
211 10 : image->common.transform->matrix[1][0] == 0)
212 : {
213 10 : if (image->common.transform->matrix[0][0] == -pixman_fixed_1 &&
214 0 : image->common.transform->matrix[1][1] == -pixman_fixed_1)
215 : {
216 0 : flags |= FAST_PATH_ROTATE_180_TRANSFORM;
217 : }
218 10 : flags |= FAST_PATH_SCALE_TRANSFORM;
219 : }
220 0 : else if (image->common.transform->matrix[0][0] == 0 &&
221 0 : image->common.transform->matrix[1][1] == 0)
222 : {
223 0 : pixman_fixed_t m01 = image->common.transform->matrix[0][1];
224 0 : if (m01 == -image->common.transform->matrix[1][0])
225 : {
226 0 : if (m01 == -pixman_fixed_1)
227 0 : flags |= FAST_PATH_ROTATE_90_TRANSFORM;
228 0 : else if (m01 == pixman_fixed_1)
229 0 : flags |= FAST_PATH_ROTATE_270_TRANSFORM;
230 : }
231 : }
232 : }
233 :
234 10 : if (image->common.transform->matrix[0][0] > 0)
235 10 : flags |= FAST_PATH_X_UNIT_POSITIVE;
236 :
237 10 : if (image->common.transform->matrix[1][0] == 0)
238 10 : flags |= FAST_PATH_Y_UNIT_ZERO;
239 : }
240 :
241 : /* Filter */
242 72 : switch (image->common.filter)
243 : {
244 : case PIXMAN_FILTER_NEAREST:
245 : case PIXMAN_FILTER_FAST:
246 62 : flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
247 62 : break;
248 :
249 : case PIXMAN_FILTER_BILINEAR:
250 : case PIXMAN_FILTER_GOOD:
251 : case PIXMAN_FILTER_BEST:
252 10 : flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
253 10 : break;
254 :
255 : case PIXMAN_FILTER_CONVOLUTION:
256 0 : break;
257 :
258 : default:
259 0 : flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
260 0 : break;
261 : }
262 :
263 : /* Repeat mode */
264 72 : switch (image->common.repeat)
265 : {
266 : case PIXMAN_REPEAT_NONE:
267 72 : flags |=
268 : FAST_PATH_NO_REFLECT_REPEAT |
269 : FAST_PATH_NO_PAD_REPEAT |
270 : FAST_PATH_NO_NORMAL_REPEAT;
271 72 : break;
272 :
273 : case PIXMAN_REPEAT_REFLECT:
274 0 : flags |=
275 : FAST_PATH_NO_PAD_REPEAT |
276 : FAST_PATH_NO_NONE_REPEAT |
277 : FAST_PATH_NO_NORMAL_REPEAT;
278 0 : break;
279 :
280 : case PIXMAN_REPEAT_PAD:
281 0 : flags |=
282 : FAST_PATH_NO_REFLECT_REPEAT |
283 : FAST_PATH_NO_NONE_REPEAT |
284 : FAST_PATH_NO_NORMAL_REPEAT;
285 0 : break;
286 :
287 : default:
288 0 : flags |=
289 : FAST_PATH_NO_REFLECT_REPEAT |
290 : FAST_PATH_NO_PAD_REPEAT |
291 : FAST_PATH_NO_NONE_REPEAT;
292 0 : break;
293 : }
294 :
295 : /* Component alpha */
296 72 : if (image->common.component_alpha)
297 0 : flags |= FAST_PATH_COMPONENT_ALPHA;
298 : else
299 72 : flags |= FAST_PATH_UNIFIED_ALPHA;
300 :
301 72 : flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);
302 :
303 : /* Type specific checks */
304 72 : switch (image->type)
305 : {
306 : case SOLID:
307 0 : code = PIXMAN_solid;
308 :
309 0 : if (image->solid.color.alpha == 0xffff)
310 0 : flags |= FAST_PATH_IS_OPAQUE;
311 0 : break;
312 :
313 : case BITS:
314 72 : if (image->bits.width == 1 &&
315 0 : image->bits.height == 1 &&
316 0 : image->common.repeat != PIXMAN_REPEAT_NONE)
317 : {
318 0 : code = PIXMAN_solid;
319 : }
320 : else
321 : {
322 72 : code = image->bits.format;
323 :
324 134 : if (!image->common.transform &&
325 62 : image->common.repeat == PIXMAN_REPEAT_NORMAL)
326 : {
327 0 : flags |= FAST_PATH_SIMPLE_REPEAT | FAST_PATH_SAMPLES_COVER_CLIP;
328 : }
329 : }
330 :
331 86 : if (!PIXMAN_FORMAT_A (image->bits.format) &&
332 28 : PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY &&
333 14 : PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR)
334 : {
335 14 : flags |= FAST_PATH_SAMPLES_OPAQUE;
336 :
337 14 : if (image->common.repeat != PIXMAN_REPEAT_NONE)
338 0 : flags |= FAST_PATH_IS_OPAQUE;
339 : }
340 :
341 72 : if (image->bits.read_func || image->bits.write_func)
342 0 : flags &= ~FAST_PATH_NO_ACCESSORS;
343 :
344 72 : if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
345 0 : flags &= ~FAST_PATH_NARROW_FORMAT;
346 72 : break;
347 :
348 : case RADIAL:
349 0 : code = PIXMAN_unknown;
350 :
351 : /*
352 : * As explained in pixman-radial-gradient.c, every point of
353 : * the plane has a valid associated radius (and thus will be
354 : * colored) if and only if a is negative (i.e. one of the two
355 : * circles contains the other one).
356 : */
357 :
358 0 : if (image->radial.a >= 0)
359 0 : break;
360 :
361 : /* Fall through */
362 :
363 : case CONICAL:
364 : case LINEAR:
365 0 : code = PIXMAN_unknown;
366 :
367 0 : if (image->common.repeat != PIXMAN_REPEAT_NONE)
368 : {
369 : int i;
370 :
371 0 : flags |= FAST_PATH_IS_OPAQUE;
372 0 : for (i = 0; i < image->gradient.n_stops; ++i)
373 : {
374 0 : if (image->gradient.stops[i].color.alpha != 0xffff)
375 : {
376 0 : flags &= ~FAST_PATH_IS_OPAQUE;
377 0 : break;
378 : }
379 : }
380 : }
381 0 : break;
382 :
383 : default:
384 0 : code = PIXMAN_unknown;
385 0 : break;
386 : }
387 :
388 : /* Alpha map */
389 72 : if (!image->common.alpha_map)
390 : {
391 72 : flags |= FAST_PATH_NO_ALPHA_MAP;
392 : }
393 : else
394 : {
395 0 : if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
396 0 : flags &= ~FAST_PATH_NARROW_FORMAT;
397 : }
398 :
399 : /* Both alpha maps and convolution filters can introduce
400 : * non-opaqueness in otherwise opaque images. Also
401 : * an image with component alpha turned on is only opaque
402 : * if all channels are opaque, so we simply turn it off
403 : * unconditionally for those images.
404 : */
405 144 : if (image->common.alpha_map ||
406 144 : image->common.filter == PIXMAN_FILTER_CONVOLUTION ||
407 72 : image->common.component_alpha)
408 : {
409 0 : flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
410 : }
411 :
412 72 : image->common.flags = flags;
413 72 : image->common.extended_format_code = code;
414 72 : }
415 :
416 : void
417 94 : _pixman_image_validate (pixman_image_t *image)
418 : {
419 94 : if (image->common.dirty)
420 : {
421 72 : compute_image_info (image);
422 :
423 : /* It is important that property_changed is
424 : * called *after* compute_image_info() because
425 : * property_changed() can make use of the flags
426 : * to set up accessors etc.
427 : */
428 72 : if (image->common.property_changed)
429 72 : image->common.property_changed (image);
430 :
431 72 : image->common.dirty = FALSE;
432 : }
433 :
434 94 : if (image->common.alpha_map)
435 0 : _pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
436 94 : }
437 :
438 : PIXMAN_EXPORT pixman_bool_t
439 0 : pixman_image_set_clip_region32 (pixman_image_t * image,
440 : pixman_region32_t *region)
441 : {
442 0 : image_common_t *common = (image_common_t *)image;
443 : pixman_bool_t result;
444 :
445 0 : if (region)
446 : {
447 0 : if ((result = pixman_region32_copy (&common->clip_region, region)))
448 0 : image->common.have_clip_region = TRUE;
449 : }
450 : else
451 : {
452 0 : _pixman_image_reset_clip_region (image);
453 :
454 0 : result = TRUE;
455 : }
456 :
457 0 : image_property_changed (image);
458 :
459 0 : return result;
460 : }
461 :
462 : PIXMAN_EXPORT pixman_bool_t
463 0 : pixman_image_set_clip_region (pixman_image_t * image,
464 : pixman_region16_t *region)
465 : {
466 0 : image_common_t *common = (image_common_t *)image;
467 : pixman_bool_t result;
468 :
469 0 : if (region)
470 : {
471 0 : if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
472 0 : image->common.have_clip_region = TRUE;
473 : }
474 : else
475 : {
476 0 : _pixman_image_reset_clip_region (image);
477 :
478 0 : result = TRUE;
479 : }
480 :
481 0 : image_property_changed (image);
482 :
483 0 : return result;
484 : }
485 :
486 : PIXMAN_EXPORT void
487 0 : pixman_image_set_has_client_clip (pixman_image_t *image,
488 : pixman_bool_t client_clip)
489 : {
490 0 : image->common.client_clip = client_clip;
491 0 : }
492 :
493 : PIXMAN_EXPORT pixman_bool_t
494 10 : pixman_image_set_transform (pixman_image_t * image,
495 : const pixman_transform_t *transform)
496 : {
497 : static const pixman_transform_t id =
498 : {
499 : { { pixman_fixed_1, 0, 0 },
500 : { 0, pixman_fixed_1, 0 },
501 : { 0, 0, pixman_fixed_1 } }
502 : };
503 :
504 10 : image_common_t *common = (image_common_t *)image;
505 : pixman_bool_t result;
506 :
507 10 : if (common->transform == transform)
508 0 : return TRUE;
509 :
510 10 : if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
511 : {
512 0 : free (common->transform);
513 0 : common->transform = NULL;
514 0 : result = TRUE;
515 :
516 0 : goto out;
517 : }
518 :
519 10 : if (common->transform &&
520 0 : memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0)
521 : {
522 0 : return TRUE;
523 : }
524 :
525 10 : if (common->transform == NULL)
526 10 : common->transform = malloc (sizeof (pixman_transform_t));
527 :
528 10 : if (common->transform == NULL)
529 : {
530 0 : result = FALSE;
531 :
532 0 : goto out;
533 : }
534 :
535 10 : memcpy (common->transform, transform, sizeof(pixman_transform_t));
536 :
537 10 : result = TRUE;
538 :
539 : out:
540 10 : image_property_changed (image);
541 :
542 10 : return result;
543 : }
544 :
545 : PIXMAN_EXPORT void
546 10 : pixman_image_set_repeat (pixman_image_t *image,
547 : pixman_repeat_t repeat)
548 : {
549 10 : if (image->common.repeat == repeat)
550 10 : return;
551 :
552 0 : image->common.repeat = repeat;
553 :
554 0 : image_property_changed (image);
555 : }
556 :
557 : PIXMAN_EXPORT pixman_bool_t
558 10 : pixman_image_set_filter (pixman_image_t * image,
559 : pixman_filter_t filter,
560 : const pixman_fixed_t *params,
561 : int n_params)
562 : {
563 10 : image_common_t *common = (image_common_t *)image;
564 : pixman_fixed_t *new_params;
565 :
566 10 : if (params == common->filter_params && filter == common->filter)
567 0 : return TRUE;
568 :
569 10 : new_params = NULL;
570 10 : if (params)
571 : {
572 0 : new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
573 0 : if (!new_params)
574 0 : return FALSE;
575 :
576 0 : memcpy (new_params,
577 : params, n_params * sizeof (pixman_fixed_t));
578 : }
579 :
580 10 : common->filter = filter;
581 :
582 10 : if (common->filter_params)
583 0 : free (common->filter_params);
584 :
585 10 : common->filter_params = new_params;
586 10 : common->n_filter_params = n_params;
587 :
588 10 : image_property_changed (image);
589 10 : return TRUE;
590 : }
591 :
592 : PIXMAN_EXPORT void
593 0 : pixman_image_set_source_clipping (pixman_image_t *image,
594 : pixman_bool_t clip_sources)
595 : {
596 0 : if (image->common.clip_sources == clip_sources)
597 0 : return;
598 :
599 0 : image->common.clip_sources = clip_sources;
600 :
601 0 : image_property_changed (image);
602 : }
603 :
604 : /* Unlike all the other property setters, this function does not
605 : * copy the content of indexed. Doing this copying is simply
606 : * way, way too expensive.
607 : */
608 : PIXMAN_EXPORT void
609 0 : pixman_image_set_indexed (pixman_image_t * image,
610 : const pixman_indexed_t *indexed)
611 : {
612 0 : bits_image_t *bits = (bits_image_t *)image;
613 :
614 0 : if (bits->indexed == indexed)
615 0 : return;
616 :
617 0 : bits->indexed = indexed;
618 :
619 0 : image_property_changed (image);
620 : }
621 :
622 : PIXMAN_EXPORT void
623 0 : pixman_image_set_alpha_map (pixman_image_t *image,
624 : pixman_image_t *alpha_map,
625 : int16_t x,
626 : int16_t y)
627 : {
628 0 : image_common_t *common = (image_common_t *)image;
629 :
630 0 : return_if_fail (!alpha_map || alpha_map->type == BITS);
631 :
632 0 : if (alpha_map && common->alpha_count > 0)
633 : {
634 : /* If this image is being used as an alpha map itself,
635 : * then you can't give it an alpha map of its own.
636 : */
637 0 : return;
638 : }
639 :
640 0 : if (alpha_map && alpha_map->common.alpha_map)
641 : {
642 : /* If the image has an alpha map of its own,
643 : * then it can't be used as an alpha map itself
644 : */
645 0 : return;
646 : }
647 :
648 0 : if (common->alpha_map != (bits_image_t *)alpha_map)
649 : {
650 0 : if (common->alpha_map)
651 : {
652 0 : common->alpha_map->common.alpha_count--;
653 :
654 0 : pixman_image_unref ((pixman_image_t *)common->alpha_map);
655 : }
656 :
657 0 : if (alpha_map)
658 : {
659 0 : common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
660 :
661 0 : common->alpha_map->common.alpha_count++;
662 : }
663 : else
664 : {
665 0 : common->alpha_map = NULL;
666 : }
667 : }
668 :
669 0 : common->alpha_origin_x = x;
670 0 : common->alpha_origin_y = y;
671 :
672 0 : image_property_changed (image);
673 : }
674 :
675 : PIXMAN_EXPORT void
676 0 : pixman_image_set_component_alpha (pixman_image_t *image,
677 : pixman_bool_t component_alpha)
678 : {
679 0 : if (image->common.component_alpha == component_alpha)
680 0 : return;
681 :
682 0 : image->common.component_alpha = component_alpha;
683 :
684 0 : image_property_changed (image);
685 : }
686 :
687 : PIXMAN_EXPORT pixman_bool_t
688 0 : pixman_image_get_component_alpha (pixman_image_t *image)
689 : {
690 0 : return image->common.component_alpha;
691 : }
692 :
693 : PIXMAN_EXPORT void
694 0 : pixman_image_set_accessors (pixman_image_t * image,
695 : pixman_read_memory_func_t read_func,
696 : pixman_write_memory_func_t write_func)
697 : {
698 0 : return_if_fail (image != NULL);
699 :
700 0 : if (image->type == BITS)
701 : {
702 0 : image->bits.read_func = read_func;
703 0 : image->bits.write_func = write_func;
704 :
705 0 : image_property_changed (image);
706 : }
707 : }
708 :
709 : PIXMAN_EXPORT uint32_t *
710 65 : pixman_image_get_data (pixman_image_t *image)
711 : {
712 65 : if (image->type == BITS)
713 65 : return image->bits.bits;
714 :
715 0 : return NULL;
716 : }
717 :
718 : PIXMAN_EXPORT int
719 65 : pixman_image_get_width (pixman_image_t *image)
720 : {
721 65 : if (image->type == BITS)
722 65 : return image->bits.width;
723 :
724 0 : return 0;
725 : }
726 :
727 : PIXMAN_EXPORT int
728 65 : pixman_image_get_height (pixman_image_t *image)
729 : {
730 65 : if (image->type == BITS)
731 65 : return image->bits.height;
732 :
733 0 : return 0;
734 : }
735 :
736 : PIXMAN_EXPORT int
737 65 : pixman_image_get_stride (pixman_image_t *image)
738 : {
739 65 : if (image->type == BITS)
740 65 : return image->bits.rowstride * (int) sizeof (uint32_t);
741 :
742 0 : return 0;
743 : }
744 :
745 : PIXMAN_EXPORT int
746 65 : pixman_image_get_depth (pixman_image_t *image)
747 : {
748 65 : if (image->type == BITS)
749 65 : return PIXMAN_FORMAT_DEPTH (image->bits.format);
750 :
751 0 : return 0;
752 : }
753 :
754 : PIXMAN_EXPORT pixman_format_code_t
755 0 : pixman_image_get_format (pixman_image_t *image)
756 : {
757 0 : if (image->type == BITS)
758 0 : return image->bits.format;
759 :
760 0 : return 0;
761 : }
762 :
763 : uint32_t
764 0 : _pixman_image_get_solid (pixman_implementation_t *imp,
765 : pixman_image_t * image,
766 : pixman_format_code_t format)
767 : {
768 : uint32_t result;
769 : pixman_iter_t iter;
770 :
771 0 : _pixman_implementation_src_iter_init (
772 : imp, &iter, image, 0, 0, 1, 1,
773 : (uint8_t *)&result, ITER_NARROW);
774 :
775 0 : result = *iter.get_scanline (&iter, NULL);
776 :
777 : /* If necessary, convert RGB <--> BGR. */
778 0 : if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB)
779 : {
780 0 : result = (((result & 0xff000000) >> 0) |
781 0 : ((result & 0x00ff0000) >> 16) |
782 0 : ((result & 0x0000ff00) >> 0) |
783 0 : ((result & 0x000000ff) << 16));
784 : }
785 :
786 0 : return result;
787 : }
|