Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright © 2000 SuSE, Inc.
  3.  * Copyright © 2007 Red Hat, Inc.
  4.  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
  5.  *             2005 Lars Knoll & Zack Rusin, Trolltech
  6.  *
  7.  * Permission to use, copy, modify, distribute, and sell this software and its
  8.  * documentation for any purpose is hereby granted without fee, provided that
  9.  * the above copyright notice appear in all copies and that both that
  10.  * copyright notice and this permission notice appear in supporting
  11.  * documentation, and that the name of Keith Packard not be used in
  12.  * advertising or publicity pertaining to distribution of the software without
  13.  * specific, written prior permission.  Keith Packard makes no
  14.  * representations about the suitability of this software for any purpose.  It
  15.  * is provided "as is" without express or implied warranty.
  16.  *
  17.  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  18.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  19.  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
  20.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  21.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  22.  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  23.  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  24.  * SOFTWARE.
  25.  */
  26.  
  27. #ifdef HAVE_CONFIG_H
  28. #include <config.h>
  29. #endif
  30.  
  31. #include <stdlib.h>
  32. #include <math.h>
  33. #include "pixman-private.h"
  34.  
  35. static force_inline double
  36. coordinates_to_parameter (double x, double y, double angle)
  37. {
  38.     double t;
  39.  
  40.     t = atan2 (y, x) + angle;
  41.  
  42.     while (t < 0)
  43.         t += 2 * M_PI;
  44.  
  45.     while (t >= 2 * M_PI)
  46.         t -= 2 * M_PI;
  47.  
  48.     return 1 - t * (1 / (2 * M_PI)); /* Scale t to [0, 1] and
  49.                                       * make rotation CCW
  50.                                       */
  51. }
  52.  
  53. static void
  54. conical_gradient_get_scanline_32 (pixman_image_t *image,
  55.                                   int             x,
  56.                                   int             y,
  57.                                   int             width,
  58.                                   uint32_t *      buffer,
  59.                                   const uint32_t *mask)
  60. {
  61.     source_image_t *source = (source_image_t *)image;
  62.     gradient_t *gradient = (gradient_t *)source;
  63.     conical_gradient_t *conical = (conical_gradient_t *)image;
  64.     uint32_t       *end = buffer + width;
  65.     pixman_gradient_walker_t walker;
  66.     pixman_bool_t affine = TRUE;
  67.     double cx = 1.;
  68.     double cy = 0.;
  69.     double cz = 0.;
  70.     double rx = x + 0.5;
  71.     double ry = y + 0.5;
  72.     double rz = 1.;
  73.  
  74.     _pixman_gradient_walker_init (&walker, gradient, source->common.repeat);
  75.  
  76.     if (source->common.transform)
  77.     {
  78.         pixman_vector_t v;
  79.  
  80.         /* reference point is the center of the pixel */
  81.         v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
  82.         v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
  83.         v.vector[2] = pixman_fixed_1;
  84.  
  85.         if (!pixman_transform_point_3d (source->common.transform, &v))
  86.             return;
  87.  
  88.         cx = source->common.transform->matrix[0][0] / 65536.;
  89.         cy = source->common.transform->matrix[1][0] / 65536.;
  90.         cz = source->common.transform->matrix[2][0] / 65536.;
  91.  
  92.         rx = v.vector[0] / 65536.;
  93.         ry = v.vector[1] / 65536.;
  94.         rz = v.vector[2] / 65536.;
  95.  
  96.         affine =
  97.             source->common.transform->matrix[2][0] == 0 &&
  98.             v.vector[2] == pixman_fixed_1;
  99.     }
  100.  
  101.     if (affine)
  102.     {
  103.         rx -= conical->center.x / 65536.;
  104.         ry -= conical->center.y / 65536.;
  105.  
  106.         while (buffer < end)
  107.         {
  108.             if (!mask || *mask++)
  109.             {
  110.                 double t = coordinates_to_parameter (rx, ry, conical->angle);
  111.  
  112.                 *buffer = _pixman_gradient_walker_pixel (
  113.                     &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
  114.             }
  115.  
  116.             ++buffer;
  117.  
  118.             rx += cx;
  119.             ry += cy;
  120.         }
  121.     }
  122.     else
  123.     {
  124.         while (buffer < end)
  125.         {
  126.             double x, y;
  127.  
  128.             if (!mask || *mask++)
  129.             {
  130.                 double t;
  131.  
  132.                 if (rz != 0)
  133.                 {
  134.                     x = rx / rz;
  135.                     y = ry / rz;
  136.                 }
  137.                 else
  138.                 {
  139.                     x = y = 0.;
  140.                 }
  141.  
  142.                 x -= conical->center.x / 65536.;
  143.                 y -= conical->center.y / 65536.;
  144.  
  145.                 t = coordinates_to_parameter (x, y, conical->angle);
  146.  
  147.                 *buffer = _pixman_gradient_walker_pixel (
  148.                     &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
  149.             }
  150.  
  151.             ++buffer;
  152.  
  153.             rx += cx;
  154.             ry += cy;
  155.             rz += cz;
  156.         }
  157.     }
  158. }
  159.  
  160. static void
  161. conical_gradient_property_changed (pixman_image_t *image)
  162. {
  163.     image->common.get_scanline_32 = conical_gradient_get_scanline_32;
  164.     image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
  165. }
  166.  
  167. PIXMAN_EXPORT pixman_image_t *
  168. pixman_image_create_conical_gradient (pixman_point_fixed_t *        center,
  169.                                       pixman_fixed_t                angle,
  170.                                       const pixman_gradient_stop_t *stops,
  171.                                       int                           n_stops)
  172. {
  173.     pixman_image_t *image = _pixman_image_allocate ();
  174.     conical_gradient_t *conical;
  175.  
  176.     if (!image)
  177.         return NULL;
  178.  
  179.     conical = &image->conical;
  180.  
  181.     if (!_pixman_init_gradient (&conical->common, stops, n_stops))
  182.     {
  183.         free (image);
  184.         return NULL;
  185.     }
  186.  
  187.     angle = MOD (angle, pixman_int_to_fixed (360));
  188.  
  189.     image->type = CONICAL;
  190.  
  191.     conical->center = *center;
  192.     conical->angle = (pixman_fixed_to_double (angle) / 180.0) * M_PI;
  193.  
  194.     image->common.property_changed = conical_gradient_property_changed;
  195.  
  196.     return image;
  197. }
  198.  
  199.