Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
  2. /*
  3.  * Copyright © 2000 SuSE, Inc.
  4.  * Copyright © 2007 Red Hat, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of SuSE not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  SuSE makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Keith Packard, SuSE, Inc.
  24.  */
  25.  
  26. #ifdef HAVE_CONFIG_H
  27. #include <config.h>
  28. #endif
  29. #include "pixman-private.h"
  30.  
  31. #include <stdlib.h>
  32.  
  33. static force_inline pixman_implementation_t *
  34. get_implementation (void)
  35. {
  36.     static pixman_implementation_t *global_implementation;
  37.  
  38.     if (!global_implementation)
  39.         global_implementation = _pixman_choose_implementation ();
  40.  
  41.     return global_implementation;
  42. }
  43.  
  44. typedef struct operator_info_t operator_info_t;
  45.  
  46. struct operator_info_t
  47. {
  48.     uint8_t     opaque_info[4];
  49. };
  50.  
  51. #define PACK(neither, src, dest, both)                  \
  52.     {{      (uint8_t)PIXMAN_OP_ ## neither,             \
  53.             (uint8_t)PIXMAN_OP_ ## src,                 \
  54.             (uint8_t)PIXMAN_OP_ ## dest,                \
  55.             (uint8_t)PIXMAN_OP_ ## both         }}
  56.  
  57. static const operator_info_t operator_table[] =
  58. {
  59.     /*    Neither Opaque         Src Opaque             Dst Opaque             Both Opaque */
  60.     PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
  61.     PACK (SRC,                   SRC,                   SRC,                   SRC),
  62.     PACK (DST,                   DST,                   DST,                   DST),
  63.     PACK (OVER,                  SRC,                   OVER,                  SRC),
  64.     PACK (OVER_REVERSE,          OVER_REVERSE,          DST,                   DST),
  65.     PACK (IN,                    IN,                    SRC,                   SRC),
  66.     PACK (IN_REVERSE,            DST,                   IN_REVERSE,            DST),
  67.     PACK (OUT,                   OUT,                   CLEAR,                 CLEAR),
  68.     PACK (OUT_REVERSE,           CLEAR,                 OUT_REVERSE,           CLEAR),
  69.     PACK (ATOP,                  IN,                    OVER,                  SRC),
  70.     PACK (ATOP_REVERSE,          OVER_REVERSE,          IN_REVERSE,            DST),
  71.     PACK (XOR,                   OUT,                   OUT_REVERSE,           CLEAR),
  72.     PACK (ADD,                   ADD,                   ADD,                   ADD),
  73.     PACK (SATURATE,              OVER_REVERSE,          DST,                   DST),
  74.  
  75.     {{ 0 /* 0x0e */ }},
  76.     {{ 0 /* 0x0f */ }},
  77.  
  78.     PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
  79.     PACK (SRC,                   SRC,                   SRC,                   SRC),
  80.     PACK (DST,                   DST,                   DST,                   DST),
  81.     PACK (DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER),
  82.     PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE),
  83.     PACK (DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN),
  84.     PACK (DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE),
  85.     PACK (DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT),
  86.     PACK (DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE),
  87.     PACK (DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP),
  88.     PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE),
  89.     PACK (DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR),
  90.  
  91.     {{ 0 /* 0x1c */ }},
  92.     {{ 0 /* 0x1d */ }},
  93.     {{ 0 /* 0x1e */ }},
  94.     {{ 0 /* 0x1f */ }},
  95.  
  96.     PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
  97.     PACK (SRC,                   SRC,                   SRC,                   SRC),
  98.     PACK (DST,                   DST,                   DST,                   DST),
  99.     PACK (CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER),
  100.     PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE),
  101.     PACK (CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN),
  102.     PACK (CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE),
  103.     PACK (CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT),
  104.     PACK (CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE),
  105.     PACK (CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP),
  106.     PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE),
  107.     PACK (CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR),
  108.  
  109.     {{ 0 /* 0x2c */ }},
  110.     {{ 0 /* 0x2d */ }},
  111.     {{ 0 /* 0x2e */ }},
  112.     {{ 0 /* 0x2f */ }},
  113.  
  114.     PACK (MULTIPLY,              MULTIPLY,              MULTIPLY,              MULTIPLY),
  115.     PACK (SCREEN,                SCREEN,                SCREEN,                SCREEN),
  116.     PACK (OVERLAY,               OVERLAY,               OVERLAY,               OVERLAY),
  117.     PACK (DARKEN,                DARKEN,                DARKEN,                DARKEN),
  118.     PACK (LIGHTEN,               LIGHTEN,               LIGHTEN,               LIGHTEN),
  119.     PACK (COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE),
  120.     PACK (COLOR_BURN,            COLOR_BURN,            COLOR_BURN,            COLOR_BURN),
  121.     PACK (HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT),
  122.     PACK (SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT),
  123.     PACK (DIFFERENCE,            DIFFERENCE,            DIFFERENCE,            DIFFERENCE),
  124.     PACK (EXCLUSION,             EXCLUSION,             EXCLUSION,             EXCLUSION),
  125.     PACK (HSL_HUE,               HSL_HUE,               HSL_HUE,               HSL_HUE),
  126.     PACK (HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION),
  127.     PACK (HSL_COLOR,             HSL_COLOR,             HSL_COLOR,             HSL_COLOR),
  128.     PACK (HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY),
  129. };
  130.  
  131. /*
  132.  * Optimize the current operator based on opacity of source or destination
  133.  * The output operator should be mathematically equivalent to the source.
  134.  */
  135. static pixman_op_t
  136. optimize_operator (pixman_op_t     op,
  137.                    uint32_t        src_flags,
  138.                    uint32_t        mask_flags,
  139.                    uint32_t        dst_flags)
  140. {
  141.     pixman_bool_t is_source_opaque, is_dest_opaque;
  142.  
  143. #define OPAQUE_SHIFT 13
  144.    
  145.     COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT));
  146.    
  147.     is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE);
  148.     is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE);
  149.  
  150.     is_dest_opaque >>= OPAQUE_SHIFT - 1;
  151.     is_source_opaque >>= OPAQUE_SHIFT;
  152.  
  153.     return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
  154. }
  155.  
  156. static void
  157. apply_workaround (pixman_image_t *image,
  158.                   int32_t *       x,
  159.                   int32_t *       y,
  160.                   uint32_t **     save_bits,
  161.                   int *           save_dx,
  162.                   int *           save_dy)
  163. {
  164.     if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
  165.     {
  166.         /* Some X servers generate images that point to the
  167.          * wrong place in memory, but then set the clip region
  168.          * to point to the right place. Because of an old bug
  169.          * in pixman, this would actually work.
  170.          *
  171.          * Here we try and undo the damage
  172.          */
  173.         int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
  174.         pixman_box32_t *extents;
  175.         uint8_t *t;
  176.         int dx, dy;
  177.        
  178.         extents = pixman_region32_extents (&(image->common.clip_region));
  179.         dx = extents->x1;
  180.         dy = extents->y1;
  181.        
  182.         *save_bits = image->bits.bits;
  183.        
  184.         *x -= dx;
  185.         *y -= dy;
  186.         pixman_region32_translate (&(image->common.clip_region), -dx, -dy);
  187.        
  188.         t = (uint8_t *)image->bits.bits;
  189.         t += dy * image->bits.rowstride * 4 + dx * bpp;
  190.         image->bits.bits = (uint32_t *)t;
  191.        
  192.         *save_dx = dx;
  193.         *save_dy = dy;
  194.     }
  195. }
  196.  
  197. static void
  198. unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
  199. {
  200.     if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
  201.     {
  202.         image->bits.bits = bits;
  203.         pixman_region32_translate (&image->common.clip_region, dx, dy);
  204.     }
  205. }
  206.  
  207. /*
  208.  * Computing composite region
  209.  */
  210. static inline pixman_bool_t
  211. clip_general_image (pixman_region32_t * region,
  212.                     pixman_region32_t * clip,
  213.                     int                 dx,
  214.                     int                 dy)
  215. {
  216.     if (pixman_region32_n_rects (region) == 1 &&
  217.         pixman_region32_n_rects (clip) == 1)
  218.     {
  219.         pixman_box32_t *  rbox = pixman_region32_rectangles (region, NULL);
  220.         pixman_box32_t *  cbox = pixman_region32_rectangles (clip, NULL);
  221.         int v;
  222.  
  223.         if (rbox->x1 < (v = cbox->x1 + dx))
  224.             rbox->x1 = v;
  225.         if (rbox->x2 > (v = cbox->x2 + dx))
  226.             rbox->x2 = v;
  227.         if (rbox->y1 < (v = cbox->y1 + dy))
  228.             rbox->y1 = v;
  229.         if (rbox->y2 > (v = cbox->y2 + dy))
  230.             rbox->y2 = v;
  231.         if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
  232.         {
  233.             pixman_region32_init (region);
  234.             return FALSE;
  235.         }
  236.     }
  237.     else if (!pixman_region32_not_empty (clip))
  238.     {
  239.         return FALSE;
  240.     }
  241.     else
  242.     {
  243.         if (dx || dy)
  244.             pixman_region32_translate (region, -dx, -dy);
  245.  
  246.         if (!pixman_region32_intersect (region, region, clip))
  247.             return FALSE;
  248.  
  249.         if (dx || dy)
  250.             pixman_region32_translate (region, dx, dy);
  251.     }
  252.  
  253.     return pixman_region32_not_empty (region);
  254. }
  255.  
  256. static inline pixman_bool_t
  257. clip_source_image (pixman_region32_t * region,
  258.                    pixman_image_t *    image,
  259.                    int                 dx,
  260.                    int                 dy)
  261. {
  262.     /* Source clips are ignored, unless they are explicitly turned on
  263.      * and the clip in question was set by an X client. (Because if
  264.      * the clip was not set by a client, then it is a hierarchy
  265.      * clip and those should always be ignored for sources).
  266.      */
  267.     if (!image->common.clip_sources || !image->common.client_clip)
  268.         return TRUE;
  269.  
  270.     return clip_general_image (region,
  271.                                &image->common.clip_region,
  272.                                dx, dy);
  273. }
  274.  
  275. /*
  276.  * returns FALSE if the final region is empty.  Indistinguishable from
  277.  * an allocation failure, but rendering ignores those anyways.
  278.  */
  279. static pixman_bool_t
  280. pixman_compute_composite_region32 (pixman_region32_t * region,
  281.                                    pixman_image_t *    src_image,
  282.                                    pixman_image_t *    mask_image,
  283.                                    pixman_image_t *    dst_image,
  284.                                    int32_t             src_x,
  285.                                    int32_t             src_y,
  286.                                    int32_t             mask_x,
  287.                                    int32_t             mask_y,
  288.                                    int32_t             dest_x,
  289.                                    int32_t             dest_y,
  290.                                    int32_t             width,
  291.                                    int32_t             height)
  292. {
  293.     region->extents.x1 = dest_x;
  294.     region->extents.x2 = dest_x + width;
  295.     region->extents.y1 = dest_y;
  296.     region->extents.y2 = dest_y + height;
  297.  
  298.     region->extents.x1 = MAX (region->extents.x1, 0);
  299.     region->extents.y1 = MAX (region->extents.y1, 0);
  300.     region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
  301.     region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
  302.  
  303.     region->data = 0;
  304.  
  305.     /* Check for empty operation */
  306.     if (region->extents.x1 >= region->extents.x2 ||
  307.         region->extents.y1 >= region->extents.y2)
  308.     {
  309.         region->extents.x1 = 0;
  310.         region->extents.x2 = 0;
  311.         region->extents.y1 = 0;
  312.         region->extents.y2 = 0;
  313.         return FALSE;
  314.     }
  315.  
  316.     if (dst_image->common.have_clip_region)
  317.     {
  318.         if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
  319.             return FALSE;
  320.     }
  321.  
  322.     if (dst_image->common.alpha_map)
  323.     {
  324.         if (!pixman_region32_intersect_rect (region, region,
  325.                                              dst_image->common.alpha_origin_x,
  326.                                              dst_image->common.alpha_origin_y,
  327.                                              dst_image->common.alpha_map->width,
  328.                                              dst_image->common.alpha_map->height))
  329.         {
  330.             return FALSE;
  331.         }
  332.         if (!pixman_region32_not_empty (region))
  333.             return FALSE;
  334.         if (dst_image->common.alpha_map->common.have_clip_region)
  335.         {
  336.             if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
  337.                                      -dst_image->common.alpha_origin_x,
  338.                                      -dst_image->common.alpha_origin_y))
  339.             {
  340.                 return FALSE;
  341.             }
  342.         }
  343.     }
  344.  
  345.     /* clip against src */
  346.     if (src_image->common.have_clip_region)
  347.     {
  348.         if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
  349.             return FALSE;
  350.     }
  351.     if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
  352.     {
  353.         if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
  354.                                 dest_x - (src_x - src_image->common.alpha_origin_x),
  355.                                 dest_y - (src_y - src_image->common.alpha_origin_y)))
  356.         {
  357.             return FALSE;
  358.         }
  359.     }
  360.     /* clip against mask */
  361.     if (mask_image && mask_image->common.have_clip_region)
  362.     {
  363.         if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
  364.             return FALSE;
  365.  
  366.         if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
  367.         {
  368.             if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
  369.                                     dest_x - (mask_x - mask_image->common.alpha_origin_x),
  370.                                     dest_y - (mask_y - mask_image->common.alpha_origin_y)))
  371.             {
  372.                 return FALSE;
  373.             }
  374.         }
  375.     }
  376.  
  377.     return TRUE;
  378. }
  379.  
  380. #define N_CACHED_FAST_PATHS 8
  381.  
  382. typedef struct
  383. {
  384.     struct
  385.     {
  386.         pixman_implementation_t *       imp;
  387.         pixman_fast_path_t              fast_path;
  388.     } cache [N_CACHED_FAST_PATHS];
  389. } cache_t;
  390.  
  391. PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
  392.  
  393. static force_inline pixman_bool_t
  394. lookup_composite_function (pixman_op_t                  op,
  395.                            pixman_format_code_t         src_format,
  396.                            uint32_t                     src_flags,
  397.                            pixman_format_code_t         mask_format,
  398.                            uint32_t                     mask_flags,
  399.                            pixman_format_code_t         dest_format,
  400.                            uint32_t                     dest_flags,
  401.                            pixman_implementation_t    **out_imp,
  402.                            pixman_composite_func_t     *out_func)
  403. {
  404.     pixman_implementation_t *imp;
  405.     cache_t *cache;
  406.     int i;
  407.  
  408.     /* Check cache for fast paths */
  409.     cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
  410.  
  411.     for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
  412.     {
  413.         const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
  414.  
  415.         /* Note that we check for equality here, not whether
  416.          * the cached fast path matches. This is to prevent
  417.          * us from selecting an overly general fast path
  418.          * when a more specific one would work.
  419.          */
  420.         if (info->op == op                      &&
  421.             info->src_format == src_format      &&
  422.             info->mask_format == mask_format    &&
  423.             info->dest_format == dest_format    &&
  424.             info->src_flags == src_flags        &&
  425.             info->mask_flags == mask_flags      &&
  426.             info->dest_flags == dest_flags      &&
  427.             info->func)
  428.         {
  429.             *out_imp = cache->cache[i].imp;
  430.             *out_func = cache->cache[i].fast_path.func;
  431.  
  432.             goto update_cache;
  433.         }
  434.     }
  435.  
  436.     for (imp = get_implementation (); imp != NULL; imp = imp->delegate)
  437.     {
  438.         const pixman_fast_path_t *info = imp->fast_paths;
  439.  
  440.         while (info->op != PIXMAN_OP_NONE)
  441.         {
  442.             if ((info->op == op || info->op == PIXMAN_OP_any)           &&
  443.                 /* Formats */
  444.                 ((info->src_format == src_format) ||
  445.                  (info->src_format == PIXMAN_any))                      &&
  446.                 ((info->mask_format == mask_format) ||
  447.                  (info->mask_format == PIXMAN_any))                     &&
  448.                 ((info->dest_format == dest_format) ||
  449.                  (info->dest_format == PIXMAN_any))                     &&
  450.                 /* Flags */
  451.                 (info->src_flags & src_flags) == info->src_flags        &&
  452.                 (info->mask_flags & mask_flags) == info->mask_flags     &&
  453.                 (info->dest_flags & dest_flags) == info->dest_flags)
  454.             {
  455.                 *out_imp = imp;
  456.                 *out_func = info->func;
  457.  
  458.                 /* Set i to the last spot in the cache so that the
  459.                  * move-to-front code below will work
  460.                  */
  461.                 i = N_CACHED_FAST_PATHS - 1;
  462.  
  463.                 goto update_cache;
  464.             }
  465.  
  466.             ++info;
  467.         }
  468.     }
  469.     return FALSE;
  470.  
  471. update_cache:
  472.     if (i)
  473.     {
  474.         while (i--)
  475.             cache->cache[i + 1] = cache->cache[i];
  476.  
  477.         cache->cache[0].imp = *out_imp;
  478.         cache->cache[0].fast_path.op = op;
  479.         cache->cache[0].fast_path.src_format = src_format;
  480.         cache->cache[0].fast_path.src_flags = src_flags;
  481.         cache->cache[0].fast_path.mask_format = mask_format;
  482.         cache->cache[0].fast_path.mask_flags = mask_flags;
  483.         cache->cache[0].fast_path.dest_format = dest_format;
  484.         cache->cache[0].fast_path.dest_flags = dest_flags;
  485.         cache->cache[0].fast_path.func = *out_func;
  486.     }
  487.  
  488.     return TRUE;
  489. }
  490.  
  491. static pixman_bool_t
  492. compute_sample_extents (pixman_transform_t *transform,
  493.                         pixman_box32_t *extents, int x, int y,
  494.                         pixman_fixed_t x_off, pixman_fixed_t y_off,
  495.                         pixman_fixed_t width, pixman_fixed_t height)
  496. {
  497.     pixman_fixed_t x1, y1, x2, y2;
  498.     pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
  499.  
  500.     /* We have checked earlier that (extents->x1 - x) etc. fit in a pixman_fixed_t */
  501.     x1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x1 - x) + pixman_fixed_1 / 2;
  502.     y1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y1 - y) + pixman_fixed_1 / 2;
  503.     x2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x2 - x) - pixman_fixed_1 / 2;
  504.     y2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y2 - y) - pixman_fixed_1 / 2;
  505.  
  506.     if (!transform)
  507.     {
  508.         tx1 = (pixman_fixed_48_16_t)x1;
  509.         ty1 = (pixman_fixed_48_16_t)y1;
  510.         tx2 = (pixman_fixed_48_16_t)x2;
  511.         ty2 = (pixman_fixed_48_16_t)y2;
  512.     }
  513.     else
  514.     {
  515.         int i;
  516.  
  517.         /* Silence GCC */
  518.         tx1 = ty1 = tx2 = ty2 = 0;
  519.    
  520.         for (i = 0; i < 4; ++i)
  521.         {
  522.             pixman_fixed_48_16_t tx, ty;
  523.             pixman_vector_t v;
  524.  
  525.             v.vector[0] = (i & 0x01)? x1 : x2;
  526.             v.vector[1] = (i & 0x02)? y1 : y2;
  527.             v.vector[2] = pixman_fixed_1;
  528.  
  529.             if (!pixman_transform_point (transform, &v))
  530.                 return FALSE;
  531.  
  532.             tx = (pixman_fixed_48_16_t)v.vector[0];
  533.             ty = (pixman_fixed_48_16_t)v.vector[1];
  534.  
  535.             if (i == 0)
  536.             {
  537.                 tx1 = tx;
  538.                 ty1 = ty;
  539.                 tx2 = tx;
  540.                 ty2 = ty;
  541.             }
  542.             else
  543.             {
  544.                 if (tx < tx1)
  545.                     tx1 = tx;
  546.                 if (ty < ty1)
  547.                     ty1 = ty;
  548.                 if (tx > tx2)
  549.                     tx2 = tx;
  550.                 if (ty > ty2)
  551.                     ty2 = ty;
  552.             }
  553.         }
  554.     }
  555.  
  556.     /* Expand the source area by a tiny bit so account of different rounding that
  557.      * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
  558.      * 0.5 so this won't cause the area computed to be overly pessimistic.
  559.      */
  560.     tx1 += x_off - 8 * pixman_fixed_e;
  561.     ty1 += y_off - 8 * pixman_fixed_e;
  562.     tx2 += x_off + width + 8 * pixman_fixed_e;
  563.     ty2 += y_off + height + 8 * pixman_fixed_e;
  564.  
  565.     if (tx1 < pixman_min_fixed_48_16 || tx1 > pixman_max_fixed_48_16 ||
  566.         ty1 < pixman_min_fixed_48_16 || ty1 > pixman_max_fixed_48_16 ||
  567.         tx2 < pixman_min_fixed_48_16 || tx2 > pixman_max_fixed_48_16 ||
  568.         ty2 < pixman_min_fixed_48_16 || ty2 > pixman_max_fixed_48_16)
  569.     {
  570.         return FALSE;
  571.     }
  572.     else
  573.     {
  574.         extents->x1 = pixman_fixed_to_int (tx1);
  575.         extents->y1 = pixman_fixed_to_int (ty1);
  576.         extents->x2 = pixman_fixed_to_int (tx2) + 1;
  577.         extents->y2 = pixman_fixed_to_int (ty2) + 1;
  578.  
  579.         return TRUE;
  580.     }
  581. }
  582.  
  583. #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
  584.  
  585. static pixman_bool_t
  586. analyze_extent (pixman_image_t *image, int x, int y,
  587.                 const pixman_box32_t *extents, uint32_t *flags)
  588. {
  589.     pixman_transform_t *transform;
  590.     pixman_fixed_t *params;
  591.     pixman_fixed_t x_off, y_off;
  592.     pixman_fixed_t width, height;
  593.     pixman_box32_t ex;
  594.  
  595.     if (!image)
  596.         return TRUE;
  597.  
  598.     /* Some compositing functions walk one step
  599.      * outside the destination rectangle, so we
  600.      * check here that the expanded-by-one source
  601.      * extents in destination space fits in 16 bits
  602.      */
  603.     if (!IS_16BIT (extents->x1 - x - 1)         ||
  604.         !IS_16BIT (extents->y1 - y - 1)         ||
  605.         !IS_16BIT (extents->x2 - x + 1)         ||
  606.         !IS_16BIT (extents->y2 - y + 1))
  607.     {
  608.         return FALSE;
  609.     }
  610.  
  611.     transform = image->common.transform;
  612.     if (image->common.type == BITS)
  613.     {
  614.         /* During repeat mode calculations we might convert the
  615.          * width/height of an image to fixed 16.16, so we need
  616.          * them to be smaller than 16 bits.
  617.          */
  618.         if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff)
  619.             return FALSE;
  620.  
  621. #define ID_AND_NEAREST (FAST_PATH_ID_TRANSFORM | FAST_PATH_NEAREST_FILTER)
  622.        
  623.         if ((image->common.flags & ID_AND_NEAREST) == ID_AND_NEAREST &&
  624.             extents->x1 - x >= 0 &&
  625.             extents->y1 - y >= 0 &&
  626.             extents->x2 - x <= image->bits.width &&
  627.             extents->y2 - y <= image->bits.height)
  628.         {
  629.             *flags |= FAST_PATH_SAMPLES_COVER_CLIP;
  630.             return TRUE;
  631.         }
  632.    
  633.         switch (image->common.filter)
  634.         {
  635.         case PIXMAN_FILTER_CONVOLUTION:
  636.             params = image->common.filter_params;
  637.             x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
  638.             y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
  639.             width = params[0];
  640.             height = params[1];
  641.             break;
  642.  
  643.         case PIXMAN_FILTER_GOOD:
  644.         case PIXMAN_FILTER_BEST:
  645.         case PIXMAN_FILTER_BILINEAR:
  646.             x_off = - pixman_fixed_1 / 2;
  647.             y_off = - pixman_fixed_1 / 2;
  648.             width = pixman_fixed_1;
  649.             height = pixman_fixed_1;
  650.             break;
  651.  
  652.         case PIXMAN_FILTER_FAST:
  653.         case PIXMAN_FILTER_NEAREST:
  654.             x_off = - pixman_fixed_e;
  655.             y_off = - pixman_fixed_e;
  656.             width = 0;
  657.             height = 0;
  658.             break;
  659.  
  660.         default:
  661.             return FALSE;
  662.         }
  663.  
  664.         /* Check whether the non-expanded, transformed extent is entirely within
  665.          * the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is.
  666.          */
  667.         ex = *extents;
  668.         if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height) &&
  669.             ex.x1 >= 0 && ex.y1 >= 0 &&
  670.             ex.x2 <= image->bits.width && ex.y2 <= image->bits.height)
  671.         {
  672.             *flags |= FAST_PATH_SAMPLES_COVER_CLIP;
  673.         }
  674.     }
  675.     else
  676.     {
  677.         x_off = 0;
  678.         y_off = 0;
  679.         width = 0;
  680.         height = 0;
  681.     }
  682.  
  683.     /* Check that the extents expanded by one don't overflow. This ensures that
  684.      * compositing functions can simply walk the source space using 16.16
  685.      * variables without worrying about overflow.
  686.      */
  687.     ex.x1 = extents->x1 - 1;
  688.     ex.y1 = extents->y1 - 1;
  689.     ex.x2 = extents->x2 + 1;
  690.     ex.y2 = extents->y2 + 1;
  691.  
  692.     if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
  693.         return FALSE;
  694.  
  695.     return TRUE;
  696. }
  697.  
  698. /*
  699.  * Work around GCC bug causing crashes in Mozilla with SSE2
  700.  *
  701.  * When using -msse, gcc generates movdqa instructions assuming that
  702.  * the stack is 16 byte aligned. Unfortunately some applications, such
  703.  * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
  704.  * causes the movdqa instructions to fail.
  705.  *
  706.  * The __force_align_arg_pointer__ makes gcc generate a prologue that
  707.  * realigns the stack pointer to 16 bytes.
  708.  *
  709.  * On x86-64 this is not necessary because the standard ABI already
  710.  * calls for a 16 byte aligned stack.
  711.  *
  712.  * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
  713.  */
  714. #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
  715. __attribute__((__force_align_arg_pointer__))
  716. #endif
  717. PIXMAN_EXPORT void
  718. pixman_image_composite32 (pixman_op_t      op,
  719.                           pixman_image_t * src,
  720.                           pixman_image_t * mask,
  721.                           pixman_image_t * dest,
  722.                           int32_t          src_x,
  723.                           int32_t          src_y,
  724.                           int32_t          mask_x,
  725.                           int32_t          mask_y,
  726.                           int32_t          dest_x,
  727.                           int32_t          dest_y,
  728.                           int32_t          width,
  729.                           int32_t          height)
  730. {
  731.     pixman_format_code_t src_format, mask_format, dest_format;
  732.     uint32_t src_flags, mask_flags, dest_flags;
  733.     pixman_region32_t region;
  734.     pixman_box32_t *extents;
  735.     uint32_t *src_bits;
  736.     int src_dx, src_dy;
  737.     uint32_t *mask_bits;
  738.     int mask_dx, mask_dy;
  739.     uint32_t *dest_bits;
  740.     int dest_dx, dest_dy;
  741.     pixman_bool_t need_workaround;
  742.     pixman_implementation_t *imp;
  743.     pixman_composite_func_t func;
  744.  
  745.     _pixman_image_validate (src);
  746.     if (mask)
  747.         _pixman_image_validate (mask);
  748.     _pixman_image_validate (dest);
  749.  
  750.     src_format = src->common.extended_format_code;
  751.     src_flags = src->common.flags;
  752.  
  753.     if (mask)
  754.     {
  755.         mask_format = mask->common.extended_format_code;
  756.         mask_flags = mask->common.flags;
  757.     }
  758.     else
  759.     {
  760.         mask_format = PIXMAN_null;
  761.         mask_flags = FAST_PATH_IS_OPAQUE;
  762.     }
  763.  
  764.     dest_format = dest->common.extended_format_code;
  765.     dest_flags = dest->common.flags;
  766.  
  767.     /* Check for pixbufs */
  768.     if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
  769.         (src->type == BITS && src->bits.bits == mask->bits.bits)           &&
  770.         (src->common.repeat == mask->common.repeat)                        &&
  771.         (src_x == mask_x && src_y == mask_y))
  772.     {
  773.         if (src_format == PIXMAN_x8b8g8r8)
  774.             src_format = mask_format = PIXMAN_pixbuf;
  775.         else if (src_format == PIXMAN_x8r8g8b8)
  776.             src_format = mask_format = PIXMAN_rpixbuf;
  777.     }
  778.  
  779.     /* Check for workaround */
  780.     need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND;
  781.  
  782.     if (need_workaround)
  783.     {
  784.         apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
  785.         apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
  786.         apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
  787.     }
  788.  
  789.     pixman_region32_init (&region);
  790.  
  791.     if (!pixman_compute_composite_region32 (
  792.             &region, src, mask, dest,
  793.             src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
  794.     {
  795.         goto out;
  796.     }
  797.  
  798.     extents = pixman_region32_extents (&region);
  799.  
  800.     if (!analyze_extent (src, dest_x - src_x, dest_y - src_y, extents, &src_flags))
  801.         goto out;
  802.  
  803.     if (!analyze_extent (mask, dest_x - mask_x, dest_y - mask_y, extents, &mask_flags))
  804.         goto out;
  805.  
  806.     /* If the clip is within the source samples, and the samples are opaque,
  807.      * then the source is effectively opaque.
  808.      */
  809. #define BOTH (FAST_PATH_SAMPLES_OPAQUE | FAST_PATH_SAMPLES_COVER_CLIP)
  810.  
  811.     if ((src_flags & BOTH) == BOTH)
  812.         src_flags |= FAST_PATH_IS_OPAQUE;
  813.    
  814.     if ((mask_flags & BOTH) == BOTH)
  815.         mask_flags |= FAST_PATH_IS_OPAQUE;
  816.    
  817.     /*
  818.      * Check if we can replace our operator by a simpler one
  819.      * if the src or dest are opaque. The output operator should be
  820.      * mathematically equivalent to the source.
  821.      */
  822.     op = optimize_operator (op, src_flags, mask_flags, dest_flags);
  823.     if (op == PIXMAN_OP_DST)
  824.         goto out;
  825.  
  826.     if (lookup_composite_function (op,
  827.                                    src_format, src_flags,
  828.                                    mask_format, mask_flags,
  829.                                    dest_format, dest_flags,
  830.                                    &imp, &func))
  831.     {
  832.         const pixman_box32_t *pbox;
  833.         int n;
  834.  
  835.         pbox = pixman_region32_rectangles (&region, &n);
  836.        
  837.         while (n--)
  838.         {
  839.             func (imp, op,
  840.                   src, mask, dest,
  841.                   pbox->x1 + src_x - dest_x,
  842.                   pbox->y1 + src_y - dest_y,
  843.                   pbox->x1 + mask_x - dest_x,
  844.                   pbox->y1 + mask_y - dest_y,
  845.                   pbox->x1,
  846.                   pbox->y1,
  847.                   pbox->x2 - pbox->x1,
  848.                   pbox->y2 - pbox->y1);
  849.            
  850.             pbox++;
  851.         }
  852.     }
  853.  
  854. out:
  855.     if (need_workaround)
  856.     {
  857.         unapply_workaround (src, src_bits, src_dx, src_dy);
  858.         unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
  859.         unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
  860.     }
  861.  
  862.     pixman_region32_fini (&region);
  863. }
  864.  
  865. PIXMAN_EXPORT void
  866. pixman_image_composite (pixman_op_t      op,
  867.                         pixman_image_t * src,
  868.                         pixman_image_t * mask,
  869.                         pixman_image_t * dest,
  870.                         int16_t          src_x,
  871.                         int16_t          src_y,
  872.                         int16_t          mask_x,
  873.                         int16_t          mask_y,
  874.                         int16_t          dest_x,
  875.                         int16_t          dest_y,
  876.                         uint16_t         width,
  877.                         uint16_t         height)
  878. {
  879.     pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
  880.                               mask_x, mask_y, dest_x, dest_y, width, height);
  881. }
  882.  
  883. PIXMAN_EXPORT pixman_bool_t
  884. pixman_blt (uint32_t *src_bits,
  885.             uint32_t *dst_bits,
  886.             int       src_stride,
  887.             int       dst_stride,
  888.             int       src_bpp,
  889.             int       dst_bpp,
  890.             int       src_x,
  891.             int       src_y,
  892.             int       dst_x,
  893.             int       dst_y,
  894.             int       width,
  895.             int       height)
  896. {
  897.     return _pixman_implementation_blt (get_implementation(),
  898.                                        src_bits, dst_bits, src_stride, dst_stride,
  899.                                        src_bpp, dst_bpp,
  900.                                        src_x, src_y,
  901.                                        dst_x, dst_y,
  902.                                        width, height);
  903. }
  904.  
  905. PIXMAN_EXPORT pixman_bool_t
  906. pixman_fill (uint32_t *bits,
  907.              int       stride,
  908.              int       bpp,
  909.              int       x,
  910.              int       y,
  911.              int       width,
  912.              int       height,
  913.              uint32_t xor)
  914. {
  915.     return _pixman_implementation_fill (
  916.         get_implementation(), bits, stride, bpp, x, y, width, height, xor);
  917. }
  918.  
  919. static uint32_t
  920. color_to_uint32 (const pixman_color_t *color)
  921. {
  922.     return
  923.         (color->alpha >> 8 << 24) |
  924.         (color->red >> 8 << 16) |
  925.         (color->green & 0xff00) |
  926.         (color->blue >> 8);
  927. }
  928.  
  929. static pixman_bool_t
  930. color_to_pixel (pixman_color_t *     color,
  931.                 uint32_t *           pixel,
  932.                 pixman_format_code_t format)
  933. {
  934.     uint32_t c = color_to_uint32 (color);
  935.  
  936.     if (!(format == PIXMAN_a8r8g8b8     ||
  937.           format == PIXMAN_x8r8g8b8     ||
  938.           format == PIXMAN_a8b8g8r8     ||
  939.           format == PIXMAN_x8b8g8r8     ||
  940.           format == PIXMAN_b8g8r8a8     ||
  941.           format == PIXMAN_b8g8r8x8     ||
  942.           format == PIXMAN_r5g6b5       ||
  943.           format == PIXMAN_b5g6r5       ||
  944.           format == PIXMAN_a8))
  945.     {
  946.         return FALSE;
  947.     }
  948.  
  949.     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
  950.     {
  951.         c = ((c & 0xff000000) >>  0) |
  952.             ((c & 0x00ff0000) >> 16) |
  953.             ((c & 0x0000ff00) >>  0) |
  954.             ((c & 0x000000ff) << 16);
  955.     }
  956.     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
  957.     {
  958.         c = ((c & 0xff000000) >> 24) |
  959.             ((c & 0x00ff0000) >>  8) |
  960.             ((c & 0x0000ff00) <<  8) |
  961.             ((c & 0x000000ff) << 24);
  962.     }
  963.  
  964.     if (format == PIXMAN_a8)
  965.         c = c >> 24;
  966.     else if (format == PIXMAN_r5g6b5 ||
  967.              format == PIXMAN_b5g6r5)
  968.         c = CONVERT_8888_TO_0565 (c);
  969.  
  970. #if 0
  971.     printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
  972.     printf ("pixel: %x\n", c);
  973. #endif
  974.  
  975.     *pixel = c;
  976.     return TRUE;
  977. }
  978.  
  979. PIXMAN_EXPORT pixman_bool_t
  980. pixman_image_fill_rectangles (pixman_op_t                 op,
  981.                               pixman_image_t *            dest,
  982.                               pixman_color_t *            color,
  983.                               int                         n_rects,
  984.                               const pixman_rectangle16_t *rects)
  985. {
  986.     pixman_box32_t stack_boxes[6];
  987.     pixman_box32_t *boxes;
  988.     pixman_bool_t result;
  989.     int i;
  990.  
  991.     if (n_rects > 6)
  992.     {
  993.         boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
  994.         if (boxes == NULL)
  995.             return FALSE;
  996.     }
  997.     else
  998.     {
  999.         boxes = stack_boxes;
  1000.     }
  1001.  
  1002.     for (i = 0; i < n_rects; ++i)
  1003.     {
  1004.         boxes[i].x1 = rects[i].x;
  1005.         boxes[i].y1 = rects[i].y;
  1006.         boxes[i].x2 = boxes[i].x1 + rects[i].width;
  1007.         boxes[i].y2 = boxes[i].y1 + rects[i].height;
  1008.     }
  1009.  
  1010.     result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
  1011.  
  1012.     if (boxes != stack_boxes)
  1013.         free (boxes);
  1014.    
  1015.     return result;
  1016. }
  1017.  
  1018. PIXMAN_EXPORT pixman_bool_t
  1019. pixman_image_fill_boxes (pixman_op_t           op,
  1020.                          pixman_image_t *      dest,
  1021.                          pixman_color_t *      color,
  1022.                          int                   n_boxes,
  1023.                          const pixman_box32_t *boxes)
  1024. {
  1025.     pixman_image_t *solid;
  1026.     pixman_color_t c;
  1027.     int i;
  1028.  
  1029.     _pixman_image_validate (dest);
  1030.    
  1031.     if (color->alpha == 0xffff)
  1032.     {
  1033.         if (op == PIXMAN_OP_OVER)
  1034.             op = PIXMAN_OP_SRC;
  1035.     }
  1036.  
  1037.     if (op == PIXMAN_OP_CLEAR)
  1038.     {
  1039.         c.red = 0;
  1040.         c.green = 0;
  1041.         c.blue = 0;
  1042.         c.alpha = 0;
  1043.  
  1044.         color = &c;
  1045.  
  1046.         op = PIXMAN_OP_SRC;
  1047.     }
  1048.  
  1049.     if (op == PIXMAN_OP_SRC)
  1050.     {
  1051.         uint32_t pixel;
  1052.  
  1053.         if (color_to_pixel (color, &pixel, dest->bits.format))
  1054.         {
  1055.             pixman_region32_t fill_region;
  1056.             int n_rects, j;
  1057.             pixman_box32_t *rects;
  1058.  
  1059.             if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
  1060.                 return FALSE;
  1061.  
  1062.             if (dest->common.have_clip_region)
  1063.             {
  1064.                 if (!pixman_region32_intersect (&fill_region,
  1065.                                                 &fill_region,
  1066.                                                 &dest->common.clip_region))
  1067.                     return FALSE;
  1068.             }
  1069.  
  1070.             rects = pixman_region32_rectangles (&fill_region, &n_rects);
  1071.             for (j = 0; j < n_rects; ++j)
  1072.             {
  1073.                 const pixman_box32_t *rect = &(rects[j]);
  1074.                 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
  1075.                              rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
  1076.                              pixel);
  1077.             }
  1078.  
  1079.             pixman_region32_fini (&fill_region);
  1080.             return TRUE;
  1081.         }
  1082.     }
  1083.  
  1084.     solid = pixman_image_create_solid_fill (color);
  1085.     if (!solid)
  1086.         return FALSE;
  1087.  
  1088.     for (i = 0; i < n_boxes; ++i)
  1089.     {
  1090.         const pixman_box32_t *box = &(boxes[i]);
  1091.  
  1092.         pixman_image_composite32 (op, solid, NULL, dest,
  1093.                                   0, 0, 0, 0,
  1094.                                   box->x1, box->y1,
  1095.                                   box->x2 - box->x1, box->y2 - box->y1);
  1096.     }
  1097.  
  1098.     pixman_image_unref (solid);
  1099.  
  1100.     return TRUE;
  1101. }
  1102.  
  1103. /**
  1104.  * pixman_version:
  1105.  *
  1106.  * Returns the version of the pixman library encoded in a single
  1107.  * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
  1108.  * later versions compare greater than earlier versions.
  1109.  *
  1110.  * A run-time comparison to check that pixman's version is greater than
  1111.  * or equal to version X.Y.Z could be performed as follows:
  1112.  *
  1113.  * <informalexample><programlisting>
  1114.  * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
  1115.  * </programlisting></informalexample>
  1116.  *
  1117.  * See also pixman_version_string() as well as the compile-time
  1118.  * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
  1119.  *
  1120.  * Return value: the encoded version.
  1121.  **/
  1122. PIXMAN_EXPORT int
  1123. pixman_version (void)
  1124. {
  1125.     return PIXMAN_VERSION;
  1126. }
  1127.  
  1128. /**
  1129.  * pixman_version_string:
  1130.  *
  1131.  * Returns the version of the pixman library as a human-readable string
  1132.  * of the form "X.Y.Z".
  1133.  *
  1134.  * See also pixman_version() as well as the compile-time equivalents
  1135.  * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
  1136.  *
  1137.  * Return value: a string containing the version.
  1138.  **/
  1139. PIXMAN_EXPORT const char*
  1140. pixman_version_string (void)
  1141. {
  1142.     return PIXMAN_VERSION_STRING;
  1143. }
  1144.  
  1145. /**
  1146.  * pixman_format_supported_source:
  1147.  * @format: A pixman_format_code_t format
  1148.  *
  1149.  * Return value: whether the provided format code is a supported
  1150.  * format for a pixman surface used as a source in
  1151.  * rendering.
  1152.  *
  1153.  * Currently, all pixman_format_code_t values are supported.
  1154.  **/
  1155. PIXMAN_EXPORT pixman_bool_t
  1156. pixman_format_supported_source (pixman_format_code_t format)
  1157. {
  1158.     switch (format)
  1159.     {
  1160.     /* 32 bpp formats */
  1161.     case PIXMAN_a2b10g10r10:
  1162.     case PIXMAN_x2b10g10r10:
  1163.     case PIXMAN_a2r10g10b10:
  1164.     case PIXMAN_x2r10g10b10:
  1165.     case PIXMAN_a8r8g8b8:
  1166.     case PIXMAN_x8r8g8b8:
  1167.     case PIXMAN_a8b8g8r8:
  1168.     case PIXMAN_x8b8g8r8:
  1169.     case PIXMAN_b8g8r8a8:
  1170.     case PIXMAN_b8g8r8x8:
  1171.     case PIXMAN_r8g8b8:
  1172.     case PIXMAN_b8g8r8:
  1173.     case PIXMAN_r5g6b5:
  1174.     case PIXMAN_b5g6r5:
  1175.     case PIXMAN_x14r6g6b6:
  1176.     /* 16 bpp formats */
  1177.     case PIXMAN_a1r5g5b5:
  1178.     case PIXMAN_x1r5g5b5:
  1179.     case PIXMAN_a1b5g5r5:
  1180.     case PIXMAN_x1b5g5r5:
  1181.     case PIXMAN_a4r4g4b4:
  1182.     case PIXMAN_x4r4g4b4:
  1183.     case PIXMAN_a4b4g4r4:
  1184.     case PIXMAN_x4b4g4r4:
  1185.     /* 8bpp formats */
  1186.     case PIXMAN_a8:
  1187.     case PIXMAN_r3g3b2:
  1188.     case PIXMAN_b2g3r3:
  1189.     case PIXMAN_a2r2g2b2:
  1190.     case PIXMAN_a2b2g2r2:
  1191.     case PIXMAN_c8:
  1192.     case PIXMAN_g8:
  1193.     case PIXMAN_x4a4:
  1194.     /* Collides with PIXMAN_c8
  1195.        case PIXMAN_x4c4:
  1196.      */
  1197.     /* Collides with PIXMAN_g8
  1198.        case PIXMAN_x4g4:
  1199.      */
  1200.     /* 4bpp formats */
  1201.     case PIXMAN_a4:
  1202.     case PIXMAN_r1g2b1:
  1203.     case PIXMAN_b1g2r1:
  1204.     case PIXMAN_a1r1g1b1:
  1205.     case PIXMAN_a1b1g1r1:
  1206.     case PIXMAN_c4:
  1207.     case PIXMAN_g4:
  1208.     /* 1bpp formats */
  1209.     case PIXMAN_a1:
  1210.     case PIXMAN_g1:
  1211.     /* YUV formats */
  1212.     case PIXMAN_yuy2:
  1213.     case PIXMAN_yv12:
  1214.         return TRUE;
  1215.  
  1216.     default:
  1217.         return FALSE;
  1218.     }
  1219. }
  1220.  
  1221. /**
  1222.  * pixman_format_supported_destination:
  1223.  * @format: A pixman_format_code_t format
  1224.  *
  1225.  * Return value: whether the provided format code is a supported
  1226.  * format for a pixman surface used as a destination in
  1227.  * rendering.
  1228.  *
  1229.  * Currently, all pixman_format_code_t values are supported
  1230.  * except for the YUV formats.
  1231.  **/
  1232. PIXMAN_EXPORT pixman_bool_t
  1233. pixman_format_supported_destination (pixman_format_code_t format)
  1234. {
  1235.     /* YUV formats cannot be written to at the moment */
  1236.     if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
  1237.         return FALSE;
  1238.  
  1239.     return pixman_format_supported_source (format);
  1240. }
  1241.  
  1242. PIXMAN_EXPORT pixman_bool_t
  1243. pixman_compute_composite_region (pixman_region16_t * region,
  1244.                                  pixman_image_t *    src_image,
  1245.                                  pixman_image_t *    mask_image,
  1246.                                  pixman_image_t *    dst_image,
  1247.                                  int16_t             src_x,
  1248.                                  int16_t             src_y,
  1249.                                  int16_t             mask_x,
  1250.                                  int16_t             mask_y,
  1251.                                  int16_t             dest_x,
  1252.                                  int16_t             dest_y,
  1253.                                  uint16_t            width,
  1254.                                  uint16_t            height)
  1255. {
  1256.     pixman_region32_t r32;
  1257.     pixman_bool_t retval;
  1258.  
  1259.     pixman_region32_init (&r32);
  1260.  
  1261.     retval = pixman_compute_composite_region32 (
  1262.         &r32, src_image, mask_image, dst_image,
  1263.         src_x, src_y, mask_x, mask_y, dest_x, dest_y,
  1264.         width, height);
  1265.  
  1266.     if (retval)
  1267.     {
  1268.         if (!pixman_region16_copy_from_region32 (region, &r32))
  1269.             retval = FALSE;
  1270.     }
  1271.  
  1272.     pixman_region32_fini (&r32);
  1273.     return retval;
  1274. }
  1275.