Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright © 2000 SuSE, Inc.
  3.  * Copyright © 1999 Keith Packard
  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.  * Author:  Keith Packard, SuSE, Inc.
  23.  */
  24.  
  25. #ifdef HAVE_CONFIG_H
  26. #include <config.h>
  27. #endif
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30.  
  31. #include "pixman-private.h"
  32.  
  33. pixman_bool_t
  34. pixman_multiply_overflows_int (unsigned int a,
  35.                                unsigned int b)
  36. {
  37.     return a >= INT32_MAX / b;
  38. }
  39.  
  40. pixman_bool_t
  41. pixman_addition_overflows_int (unsigned int a,
  42.                                unsigned int b)
  43. {
  44.     return a > INT32_MAX - b;
  45. }
  46.  
  47. void *
  48. pixman_malloc_ab (unsigned int a,
  49.                   unsigned int b)
  50. {
  51.     if (a >= INT32_MAX / b)
  52.         return NULL;
  53.  
  54.     return malloc (a * b);
  55. }
  56.  
  57. void *
  58. pixman_malloc_abc (unsigned int a,
  59.                    unsigned int b,
  60.                    unsigned int c)
  61. {
  62.     if (a >= INT32_MAX / b)
  63.         return NULL;
  64.     else if (a * b >= INT32_MAX / c)
  65.         return NULL;
  66.     else
  67.         return malloc (a * b * c);
  68. }
  69.  
  70. /*
  71.  * Helper routine to expand a color component from 0 < n <= 8 bits to 16
  72.  * bits by replication.
  73.  */
  74. static inline uint64_t
  75. expand16 (const uint8_t val, int nbits)
  76. {
  77.     /* Start out with the high bit of val in the high bit of result. */
  78.     uint16_t result = (uint16_t)val << (16 - nbits);
  79.  
  80.     if (nbits == 0)
  81.         return 0;
  82.  
  83.     /* Copy the bits in result, doubling the number of bits each time, until
  84.      * we fill all 16 bits.
  85.      */
  86.     while (nbits < 16)
  87.     {
  88.         result |= result >> nbits;
  89.         nbits *= 2;
  90.     }
  91.  
  92.     return result;
  93. }
  94.  
  95. /*
  96.  * This function expands images from ARGB8 format to ARGB16.  To preserve
  97.  * precision, it needs to know the original source format.  For example, if the
  98.  * source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then
  99.  * the expanded value is 12345123.  To correctly expand this to 16 bits, it
  100.  * should be 1234512345123451 and not 1234512312345123.
  101.  */
  102. void
  103. pixman_expand (uint64_t *           dst,
  104.                const uint32_t *     src,
  105.                pixman_format_code_t format,
  106.                int                  width)
  107. {
  108.     /*
  109.      * Determine the sizes of each component and the masks and shifts
  110.      * required to extract them from the source pixel.
  111.      */
  112.     const int a_size = PIXMAN_FORMAT_A (format),
  113.               r_size = PIXMAN_FORMAT_R (format),
  114.               g_size = PIXMAN_FORMAT_G (format),
  115.               b_size = PIXMAN_FORMAT_B (format);
  116.     const int a_shift = 32 - a_size,
  117.               r_shift = 24 - r_size,
  118.               g_shift = 16 - g_size,
  119.               b_shift =  8 - b_size;
  120.     const uint8_t a_mask = ~(~0 << a_size),
  121.                   r_mask = ~(~0 << r_size),
  122.                   g_mask = ~(~0 << g_size),
  123.                   b_mask = ~(~0 << b_size);
  124.     int i;
  125.  
  126.     /* Start at the end so that we can do the expansion in place
  127.      * when src == dst
  128.      */
  129.     for (i = width - 1; i >= 0; i--)
  130.     {
  131.         const uint32_t pixel = src[i];
  132.         const uint8_t a = (pixel >> a_shift) & a_mask,
  133.                       r = (pixel >> r_shift) & r_mask,
  134.                       g = (pixel >> g_shift) & g_mask,
  135.                       b = (pixel >> b_shift) & b_mask;
  136.         const uint64_t a16 = a_size ? expand16 (a, a_size) : 0xffff,
  137.                        r16 = expand16 (r, r_size),
  138.                        g16 = expand16 (g, g_size),
  139.                        b16 = expand16 (b, b_size);
  140.  
  141.         dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16;
  142.     }
  143. }
  144.  
  145. /*
  146.  * Contracting is easier than expanding.  We just need to truncate the
  147.  * components.
  148.  */
  149. void
  150. pixman_contract (uint32_t *      dst,
  151.                  const uint64_t *src,
  152.                  int             width)
  153. {
  154.     int i;
  155.  
  156.     /* Start at the beginning so that we can do the contraction in
  157.      * place when src == dst
  158.      */
  159.     for (i = 0; i < width; i++)
  160.     {
  161.         const uint8_t a = src[i] >> 56,
  162.                       r = src[i] >> 40,
  163.                       g = src[i] >> 24,
  164.                       b = src[i] >> 8;
  165.  
  166.         dst[i] = a << 24 | r << 16 | g << 8 | b;
  167.     }
  168. }
  169.  
  170. #define N_TMP_BOXES (16)
  171.  
  172. pixman_bool_t
  173. pixman_region16_copy_from_region32 (pixman_region16_t *dst,
  174.                                     pixman_region32_t *src)
  175. {
  176.     int n_boxes, i;
  177.     pixman_box32_t *boxes32;
  178.     pixman_box16_t *boxes16;
  179.     pixman_bool_t retval;
  180.  
  181.     boxes32 = pixman_region32_rectangles (src, &n_boxes);
  182.  
  183.     boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t));
  184.  
  185.     if (!boxes16)
  186.         return FALSE;
  187.  
  188.     for (i = 0; i < n_boxes; ++i)
  189.     {
  190.         boxes16[i].x1 = boxes32[i].x1;
  191.         boxes16[i].y1 = boxes32[i].y1;
  192.         boxes16[i].x2 = boxes32[i].x2;
  193.         boxes16[i].y2 = boxes32[i].y2;
  194.     }
  195.  
  196.     pixman_region_fini (dst);
  197.     retval = pixman_region_init_rects (dst, boxes16, n_boxes);
  198.     free (boxes16);
  199.     return retval;
  200. }
  201.  
  202. pixman_bool_t
  203. pixman_region32_copy_from_region16 (pixman_region32_t *dst,
  204.                                     pixman_region16_t *src)
  205. {
  206.     int n_boxes, i;
  207.     pixman_box16_t *boxes16;
  208.     pixman_box32_t *boxes32;
  209.     pixman_box32_t tmp_boxes[N_TMP_BOXES];
  210.     pixman_bool_t retval;
  211.  
  212.     boxes16 = pixman_region_rectangles (src, &n_boxes);
  213.  
  214.     if (n_boxes > N_TMP_BOXES)
  215.         boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t));
  216.     else
  217.         boxes32 = tmp_boxes;
  218.  
  219.     if (!boxes32)
  220.         return FALSE;
  221.  
  222.     for (i = 0; i < n_boxes; ++i)
  223.     {
  224.         boxes32[i].x1 = boxes16[i].x1;
  225.         boxes32[i].y1 = boxes16[i].y1;
  226.         boxes32[i].x2 = boxes16[i].x2;
  227.         boxes32[i].y2 = boxes16[i].y2;
  228.     }
  229.  
  230.     pixman_region32_fini (dst);
  231.     retval = pixman_region32_init_rects (dst, boxes32, n_boxes);
  232.  
  233.     if (boxes32 != tmp_boxes)
  234.         free (boxes32);
  235.  
  236.     return retval;
  237. }
  238.  
  239. #ifdef DEBUG
  240.  
  241. void
  242. _pixman_log_error (const char *function, const char *message)
  243. {
  244.     static int n_messages = 0;
  245.  
  246.     if (n_messages < 10)
  247.     {
  248.         fprintf (stderr,
  249.                  "*** BUG ***\n"
  250.                  "In %s: %s\n"
  251.                  "Set a breakpoint on '_pixman_log_error' to debug\n\n",
  252.                  function, message);
  253.  
  254.         n_messages++;
  255.     }
  256. }
  257.  
  258. #endif
  259.