Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 map */
  506.     if (!image->common.alpha_map)
  507.     {
  508.         flags |= FAST_PATH_NO_ALPHA_MAP;
  509.     }
  510.     else
  511.     {
  512.         if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
  513.             flags &= ~FAST_PATH_NARROW_FORMAT;
  514.     }
  515.  
  516.     /* Both alpha maps and convolution filters can introduce
  517.      * non-opaqueness in otherwise opaque images. Also
  518.      * an image with component alpha turned on is only opaque
  519.      * if all channels are opaque, so we simply turn it off
  520.      * unconditionally for those images.
  521.      */
  522.     if (image->common.alpha_map                                         ||
  523.         image->common.filter == PIXMAN_FILTER_CONVOLUTION               ||
  524.         image->common.filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION     ||
  525.         image->common.component_alpha)
  526.     {
  527.         flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
  528.     }
  529.  
  530.     image->common.flags = flags;
  531.     image->common.extended_format_code = code;
  532. }
  533.  
  534. void
  535. _pixman_image_validate (pixman_image_t *image)
  536. {
  537.     if (image->common.dirty)
  538.     {
  539.         compute_image_info (image);
  540.  
  541.         /* It is important that property_changed is
  542.          * called *after* compute_image_info() because
  543.          * property_changed() can make use of the flags
  544.          * to set up accessors etc.
  545.          */
  546.         if (image->common.property_changed)
  547.             image->common.property_changed (image);
  548.  
  549.         image->common.dirty = FALSE;
  550.     }
  551.  
  552.     if (image->common.alpha_map)
  553.         _pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
  554. }
  555.  
  556. PIXMAN_EXPORT pixman_bool_t
  557. pixman_image_set_clip_region32 (pixman_image_t *   image,
  558.                                 pixman_region32_t *region)
  559. {
  560.     image_common_t *common = (image_common_t *)image;
  561.     pixman_bool_t result;
  562.  
  563.     if (region)
  564.     {
  565.         if ((result = pixman_region32_copy (&common->clip_region, region)))
  566.             image->common.have_clip_region = TRUE;
  567.     }
  568.     else
  569.     {
  570.         _pixman_image_reset_clip_region (image);
  571.  
  572.         result = TRUE;
  573.     }
  574.  
  575.     image_property_changed (image);
  576.  
  577.     return result;
  578. }
  579.  
  580. PIXMAN_EXPORT pixman_bool_t
  581. pixman_image_set_clip_region (pixman_image_t *   image,
  582.                               pixman_region16_t *region)
  583. {
  584.     image_common_t *common = (image_common_t *)image;
  585.     pixman_bool_t result;
  586.  
  587.     if (region)
  588.     {
  589.         if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
  590.             image->common.have_clip_region = TRUE;
  591.     }
  592.     else
  593.     {
  594.         _pixman_image_reset_clip_region (image);
  595.  
  596.         result = TRUE;
  597.     }
  598.  
  599.     image_property_changed (image);
  600.  
  601.     return result;
  602. }
  603.  
  604. PIXMAN_EXPORT void
  605. pixman_image_set_has_client_clip (pixman_image_t *image,
  606.                                   pixman_bool_t   client_clip)
  607. {
  608.     image->common.client_clip = client_clip;
  609. }
  610.  
  611. PIXMAN_EXPORT pixman_bool_t
  612. pixman_image_set_transform (pixman_image_t *          image,
  613.                             const pixman_transform_t *transform)
  614. {
  615.     static const pixman_transform_t id =
  616.     {
  617.         { { pixman_fixed_1, 0, 0 },
  618.           { 0, pixman_fixed_1, 0 },
  619.           { 0, 0, pixman_fixed_1 } }
  620.     };
  621.  
  622.     image_common_t *common = (image_common_t *)image;
  623.     pixman_bool_t result;
  624.  
  625.     if (common->transform == transform)
  626.         return TRUE;
  627.  
  628.     if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
  629.     {
  630.         free (common->transform);
  631.         common->transform = NULL;
  632.         result = TRUE;
  633.  
  634.         goto out;
  635.     }
  636.  
  637.     if (common->transform &&
  638.         memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0)
  639.     {
  640.         return TRUE;
  641.     }
  642.  
  643.     if (common->transform == NULL)
  644.         common->transform = malloc (sizeof (pixman_transform_t));
  645.  
  646.     if (common->transform == NULL)
  647.     {
  648.         result = FALSE;
  649.  
  650.         goto out;
  651.     }
  652.  
  653.     memcpy (common->transform, transform, sizeof(pixman_transform_t));
  654.  
  655.     result = TRUE;
  656.  
  657. out:
  658.     image_property_changed (image);
  659.  
  660.     return result;
  661. }
  662.  
  663. PIXMAN_EXPORT void
  664. pixman_image_set_repeat (pixman_image_t *image,
  665.                          pixman_repeat_t repeat)
  666. {
  667.     if (image->common.repeat == repeat)
  668.         return;
  669.  
  670.     image->common.repeat = repeat;
  671.  
  672.     image_property_changed (image);
  673. }
  674.  
  675. PIXMAN_EXPORT pixman_bool_t
  676. pixman_image_set_filter (pixman_image_t *      image,
  677.                          pixman_filter_t       filter,
  678.                          const pixman_fixed_t *params,
  679.                          int                   n_params)
  680. {
  681.     image_common_t *common = (image_common_t *)image;
  682.     pixman_fixed_t *new_params;
  683.  
  684.     if (params == common->filter_params && filter == common->filter)
  685.         return TRUE;
  686.  
  687.     if (filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
  688.     {
  689.         int width = pixman_fixed_to_int (params[0]);
  690.         int height = pixman_fixed_to_int (params[1]);
  691.         int x_phase_bits = pixman_fixed_to_int (params[2]);
  692.         int y_phase_bits = pixman_fixed_to_int (params[3]);
  693.         int n_x_phases = (1 << x_phase_bits);
  694.         int n_y_phases = (1 << y_phase_bits);
  695.  
  696.         return_val_if_fail (
  697.             n_params == 4 + n_x_phases * width + n_y_phases * height, FALSE);
  698.     }
  699.    
  700.     new_params = NULL;
  701.     if (params)
  702.     {
  703.         new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
  704.         if (!new_params)
  705.             return FALSE;
  706.  
  707.         memcpy (new_params,
  708.                 params, n_params * sizeof (pixman_fixed_t));
  709.     }
  710.  
  711.     common->filter = filter;
  712.  
  713.     if (common->filter_params)
  714.         free (common->filter_params);
  715.  
  716.     common->filter_params = new_params;
  717.     common->n_filter_params = n_params;
  718.  
  719.     image_property_changed (image);
  720.     return TRUE;
  721. }
  722.  
  723. PIXMAN_EXPORT void
  724. pixman_image_set_source_clipping (pixman_image_t *image,
  725.                                   pixman_bool_t   clip_sources)
  726. {
  727.     if (image->common.clip_sources == clip_sources)
  728.         return;
  729.  
  730.     image->common.clip_sources = clip_sources;
  731.  
  732.     image_property_changed (image);
  733. }
  734.  
  735. /* Unlike all the other property setters, this function does not
  736.  * copy the content of indexed. Doing this copying is simply
  737.  * way, way too expensive.
  738.  */
  739. PIXMAN_EXPORT void
  740. pixman_image_set_indexed (pixman_image_t *        image,
  741.                           const pixman_indexed_t *indexed)
  742. {
  743.     bits_image_t *bits = (bits_image_t *)image;
  744.  
  745.     if (bits->indexed == indexed)
  746.         return;
  747.  
  748.     bits->indexed = indexed;
  749.  
  750.     image_property_changed (image);
  751. }
  752.  
  753. PIXMAN_EXPORT void
  754. pixman_image_set_alpha_map (pixman_image_t *image,
  755.                             pixman_image_t *alpha_map,
  756.                             int16_t         x,
  757.                             int16_t         y)
  758. {
  759.     image_common_t *common = (image_common_t *)image;
  760.  
  761.     return_if_fail (!alpha_map || alpha_map->type == BITS);
  762.  
  763.     if (alpha_map && common->alpha_count > 0)
  764.     {
  765.         /* If this image is being used as an alpha map itself,
  766.          * then you can't give it an alpha map of its own.
  767.          */
  768.         return;
  769.     }
  770.  
  771.     if (alpha_map && alpha_map->common.alpha_map)
  772.     {
  773.         /* If the image has an alpha map of its own,
  774.          * then it can't be used as an alpha map itself
  775.          */
  776.         return;
  777.     }
  778.  
  779.     if (common->alpha_map != (bits_image_t *)alpha_map)
  780.     {
  781.         if (common->alpha_map)
  782.         {
  783.             common->alpha_map->common.alpha_count--;
  784.  
  785.             pixman_image_unref ((pixman_image_t *)common->alpha_map);
  786.         }
  787.  
  788.         if (alpha_map)
  789.         {
  790.             common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
  791.  
  792.             common->alpha_map->common.alpha_count++;
  793.         }
  794.         else
  795.         {
  796.             common->alpha_map = NULL;
  797.         }
  798.     }
  799.  
  800.     common->alpha_origin_x = x;
  801.     common->alpha_origin_y = y;
  802.  
  803.     image_property_changed (image);
  804. }
  805.  
  806. PIXMAN_EXPORT void
  807. pixman_image_set_component_alpha   (pixman_image_t *image,
  808.                                     pixman_bool_t   component_alpha)
  809. {
  810.     if (image->common.component_alpha == component_alpha)
  811.         return;
  812.  
  813.     image->common.component_alpha = component_alpha;
  814.  
  815.     image_property_changed (image);
  816. }
  817.  
  818. PIXMAN_EXPORT pixman_bool_t
  819. pixman_image_get_component_alpha   (pixman_image_t       *image)
  820. {
  821.     return image->common.component_alpha;
  822. }
  823.  
  824. PIXMAN_EXPORT void
  825. pixman_image_set_accessors (pixman_image_t *           image,
  826.                             pixman_read_memory_func_t  read_func,
  827.                             pixman_write_memory_func_t write_func)
  828. {
  829.     return_if_fail (image != NULL);
  830.  
  831.     if (image->type == BITS)
  832.     {
  833.         image->bits.read_func = read_func;
  834.         image->bits.write_func = write_func;
  835.  
  836.         image_property_changed (image);
  837.     }
  838. }
  839.  
  840. PIXMAN_EXPORT uint32_t *
  841. pixman_image_get_data (pixman_image_t *image)
  842. {
  843.     if (image->type == BITS)
  844.         return image->bits.bits;
  845.  
  846.     return NULL;
  847. }
  848.  
  849. PIXMAN_EXPORT int
  850. pixman_image_get_width (pixman_image_t *image)
  851. {
  852.     if (image->type == BITS)
  853.         return image->bits.width;
  854.  
  855.     return 0;
  856. }
  857.  
  858. PIXMAN_EXPORT int
  859. pixman_image_get_height (pixman_image_t *image)
  860. {
  861.     if (image->type == BITS)
  862.         return image->bits.height;
  863.  
  864.     return 0;
  865. }
  866.  
  867. PIXMAN_EXPORT int
  868. pixman_image_get_stride (pixman_image_t *image)
  869. {
  870.     if (image->type == BITS)
  871.         return image->bits.rowstride * (int) sizeof (uint32_t);
  872.  
  873.     return 0;
  874. }
  875.  
  876. PIXMAN_EXPORT int
  877. pixman_image_get_depth (pixman_image_t *image)
  878. {
  879.     if (image->type == BITS)
  880.         return PIXMAN_FORMAT_DEPTH (image->bits.format);
  881.  
  882.     return 0;
  883. }
  884.  
  885. PIXMAN_EXPORT pixman_format_code_t
  886. pixman_image_get_format (pixman_image_t *image)
  887. {
  888.     if (image->type == BITS)
  889.         return image->bits.format;
  890.  
  891.     return PIXMAN_null;
  892. }
  893.  
  894. uint32_t
  895. _pixman_image_get_solid (pixman_implementation_t *imp,
  896.                          pixman_image_t *         image,
  897.                          pixman_format_code_t     format)
  898. {
  899.     uint32_t result;
  900.  
  901.     if (image->type == SOLID)
  902.     {
  903.         result = image->solid.color_32;
  904.     }
  905.     else if (image->type == BITS)
  906.     {
  907.         if (image->bits.format == PIXMAN_a8r8g8b8)
  908.             result = image->bits.bits[0];
  909.         else if (image->bits.format == PIXMAN_x8r8g8b8)
  910.             result = image->bits.bits[0] | 0xff000000;
  911.         else if (image->bits.format == PIXMAN_a8)
  912.             result = (*(uint8_t *)image->bits.bits) << 24;
  913.         else
  914.             goto otherwise;
  915.     }
  916.     else
  917.     {
  918.         pixman_iter_t iter;
  919.  
  920.     otherwise:
  921.         _pixman_implementation_src_iter_init (
  922.             imp, &iter, image, 0, 0, 1, 1,
  923.             (uint8_t *)&result,
  924.             ITER_NARROW, image->common.flags);
  925.        
  926.         result = *iter.get_scanline (&iter, NULL);
  927.     }
  928.  
  929.     /* If necessary, convert RGB <--> BGR. */
  930.     if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB
  931.         && PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB)
  932.     {
  933.         result = (((result & 0xff000000) >>  0) |
  934.                   ((result & 0x00ff0000) >> 16) |
  935.                   ((result & 0x0000ff00) >>  0) |
  936.                   ((result & 0x000000ff) << 16));
  937.     }
  938.  
  939.     return result;
  940. }
  941.