LCOV - code coverage report
Current view: top level - gfx/cairo/libpixman/src - pixman-linear-gradient.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 183 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             :  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
       6             :  *             2005 Lars Knoll & Zack Rusin, Trolltech
       7             :  *
       8             :  * Permission to use, copy, modify, distribute, and sell this software and its
       9             :  * documentation for any purpose is hereby granted without fee, provided that
      10             :  * the above copyright notice appear in all copies and that both that
      11             :  * copyright notice and this permission notice appear in supporting
      12             :  * documentation, and that the name of Keith Packard not be used in
      13             :  * advertising or publicity pertaining to distribution of the software without
      14             :  * specific, written prior permission.  Keith Packard makes no
      15             :  * representations about the suitability of this software for any purpose.  It
      16             :  * is provided "as is" without express or implied warranty.
      17             :  *
      18             :  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
      19             :  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
      20             :  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
      21             :  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      22             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
      23             :  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
      24             :  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
      25             :  * SOFTWARE.
      26             :  */
      27             : 
      28             : #ifdef HAVE_CONFIG_H
      29             : #include <config.h>
      30             : #endif
      31             : #include <stdlib.h>
      32             : #include "pixman-private.h"
      33             : 
      34             : #include "pixman-dither.h"
      35             : 
      36             : static pixman_bool_t
      37           0 : linear_gradient_is_horizontal (pixman_image_t *image,
      38             :                                int             x,
      39             :                                int             y,
      40             :                                int             width,
      41             :                                int             height)
      42             : {
      43           0 :     linear_gradient_t *linear = (linear_gradient_t *)image;
      44             :     pixman_vector_t v;
      45             :     pixman_fixed_32_32_t l;
      46             :     pixman_fixed_48_16_t dx, dy;
      47             :     double inc;
      48             : 
      49           0 :     if (image->common.transform)
      50             :     {
      51             :         /* projective transformation */
      52           0 :         if (image->common.transform->matrix[2][0] != 0 ||
      53           0 :             image->common.transform->matrix[2][1] != 0 ||
      54           0 :             image->common.transform->matrix[2][2] == 0)
      55             :         {
      56           0 :             return FALSE;
      57             :         }
      58             : 
      59           0 :         v.vector[0] = image->common.transform->matrix[0][1];
      60           0 :         v.vector[1] = image->common.transform->matrix[1][1];
      61           0 :         v.vector[2] = image->common.transform->matrix[2][2];
      62             :     }
      63             :     else
      64             :     {
      65           0 :         v.vector[0] = 0;
      66           0 :         v.vector[1] = pixman_fixed_1;
      67           0 :         v.vector[2] = pixman_fixed_1;
      68             :     }
      69             : 
      70           0 :     dx = linear->p2.x - linear->p1.x;
      71           0 :     dy = linear->p2.y - linear->p1.y;
      72             : 
      73           0 :     l = dx * dx + dy * dy;
      74             : 
      75           0 :     if (l == 0)
      76           0 :         return FALSE;
      77             : 
      78             :     /*
      79             :      * compute how much the input of the gradient walked changes
      80             :      * when moving vertically through the whole image
      81             :      */
      82           0 :     inc = height * (double) pixman_fixed_1 * pixman_fixed_1 *
      83           0 :         (dx * v.vector[0] + dy * v.vector[1]) /
      84           0 :         (v.vector[2] * (double) l);
      85             : 
      86             :     /* check that casting to integer would result in 0 */
      87           0 :     if (-1 < inc && inc < 1)
      88           0 :         return TRUE;
      89             : 
      90           0 :     return FALSE;
      91             : }
      92             : 
      93             : static uint32_t *
      94           0 : linear_get_scanline_narrow (pixman_iter_t  *iter,
      95             :                             const uint32_t *mask)
      96             : {
      97           0 :     pixman_image_t *image  = iter->image;
      98           0 :     int             x      = iter->x;
      99           0 :     int             y      = iter->y;
     100           0 :     int             width  = iter->width;
     101           0 :     uint32_t *      buffer = iter->buffer;
     102             : 
     103             :     pixman_vector_t v, unit;
     104             :     pixman_fixed_32_32_t l;
     105             :     pixman_fixed_48_16_t dx, dy;
     106           0 :     gradient_t *gradient = (gradient_t *)image;
     107           0 :     linear_gradient_t *linear = (linear_gradient_t *)image;
     108           0 :     uint32_t *end = buffer + width;
     109             :     pixman_gradient_walker_t walker;
     110             : 
     111           0 :     _pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
     112             : 
     113             :     /* reference point is the center of the pixel */
     114           0 :     v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
     115           0 :     v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
     116           0 :     v.vector[2] = pixman_fixed_1;
     117             : 
     118           0 :     if (image->common.transform)
     119             :     {
     120           0 :         if (!pixman_transform_point_3d (image->common.transform, &v))
     121           0 :             return iter->buffer;
     122             : 
     123           0 :         unit.vector[0] = image->common.transform->matrix[0][0];
     124           0 :         unit.vector[1] = image->common.transform->matrix[1][0];
     125           0 :         unit.vector[2] = image->common.transform->matrix[2][0];
     126             :     }
     127             :     else
     128             :     {
     129           0 :         unit.vector[0] = pixman_fixed_1;
     130           0 :         unit.vector[1] = 0;
     131           0 :         unit.vector[2] = 0;
     132             :     }
     133             : 
     134           0 :     dx = linear->p2.x - linear->p1.x;
     135           0 :     dy = linear->p2.y - linear->p1.y;
     136             : 
     137           0 :     l = dx * dx + dy * dy;
     138             : 
     139           0 :     if (l == 0 || unit.vector[2] == 0)
     140           0 :     {
     141             :         /* affine transformation only */
     142             :         pixman_fixed_32_32_t t, next_inc;
     143             :         double inc;
     144             : 
     145           0 :         if (l == 0 || v.vector[2] == 0)
     146             :         {
     147           0 :             t = 0;
     148           0 :             inc = 0;
     149             :         }
     150             :         else
     151             :         {
     152             :             double invden, v2;
     153             : 
     154           0 :             invden = pixman_fixed_1 * (double) pixman_fixed_1 /
     155           0 :                 (l * (double) v.vector[2]);
     156           0 :             v2 = v.vector[2] * (1. / pixman_fixed_1);
     157           0 :             t = ((dx * v.vector[0] + dy * v.vector[1]) - 
     158           0 :                  (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
     159           0 :             inc = (dx * unit.vector[0] + dy * unit.vector[1]) * invden;
     160             :         }
     161           0 :         next_inc = 0;
     162             : 
     163           0 :         if (((pixman_fixed_32_32_t )(inc * width)) == 0)
     164             :         {
     165             :             register uint32_t color;
     166             : 
     167           0 :             color = _pixman_gradient_walker_pixel (&walker, t);
     168           0 :             while (buffer < end)
     169           0 :                 *buffer++ = color;
     170             :         }
     171             :         else
     172             :         {
     173             :             int i;
     174             : 
     175           0 :             i = 0;
     176           0 :             while (buffer < end)
     177             :             {
     178           0 :                 if (!mask || *mask++)
     179             :                 {
     180           0 :                     *buffer = _pixman_gradient_walker_pixel (&walker,
     181             :                                                              t + next_inc);
     182             :                 }
     183           0 :                 i++;
     184           0 :                 next_inc = inc * i;
     185           0 :                 buffer++;
     186             :             }
     187             :         }
     188             :     }
     189             :     else
     190             :     {
     191             :         /* projective transformation */
     192             :         double t;
     193             : 
     194           0 :         t = 0;
     195             : 
     196           0 :         while (buffer < end)
     197             :         {
     198           0 :             if (!mask || *mask++)
     199             :             {
     200           0 :                 if (v.vector[2] != 0)
     201             :                 {
     202             :                     double invden, v2;
     203             : 
     204           0 :                     invden = pixman_fixed_1 * (double) pixman_fixed_1 /
     205           0 :                         (l * (double) v.vector[2]);
     206           0 :                     v2 = v.vector[2] * (1. / pixman_fixed_1);
     207           0 :                     t = ((dx * v.vector[0] + dy * v.vector[1]) - 
     208           0 :                          (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
     209             :                 }
     210             : 
     211           0 :                 *buffer = _pixman_gradient_walker_pixel (&walker, t);
     212             :             }
     213             : 
     214           0 :             ++buffer;
     215             : 
     216           0 :             v.vector[0] += unit.vector[0];
     217           0 :             v.vector[1] += unit.vector[1];
     218           0 :             v.vector[2] += unit.vector[2];
     219             :         }
     220             :     }
     221             : 
     222           0 :     iter->y++;
     223             : 
     224           0 :     return iter->buffer;
     225             : }
     226             : 
     227             : static uint32_t *
     228           0 : linear_get_scanline_16 (pixman_iter_t  *iter,
     229             :                         const uint32_t *mask)
     230             : {
     231           0 :     pixman_image_t *image  = iter->image;
     232           0 :     int             x      = iter->x;
     233           0 :     int             y      = iter->y;
     234           0 :     int             width  = iter->width;
     235           0 :     uint16_t *      buffer = (uint16_t*)iter->buffer;
     236           0 :     pixman_bool_t   toggle = ((x ^ y) & 1);
     237             : 
     238             :     pixman_vector_t v, unit;
     239             :     pixman_fixed_32_32_t l;
     240             :     pixman_fixed_48_16_t dx, dy;
     241           0 :     gradient_t *gradient = (gradient_t *)image;
     242           0 :     linear_gradient_t *linear = (linear_gradient_t *)image;
     243           0 :     uint16_t *end = buffer + width;
     244             :     pixman_gradient_walker_t walker;
     245             : 
     246           0 :     _pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
     247             : 
     248             :     /* reference point is the center of the pixel */
     249           0 :     v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
     250           0 :     v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
     251           0 :     v.vector[2] = pixman_fixed_1;
     252             : 
     253           0 :     if (image->common.transform)
     254             :     {
     255           0 :         if (!pixman_transform_point_3d (image->common.transform, &v))
     256           0 :             return iter->buffer;
     257             : 
     258           0 :         unit.vector[0] = image->common.transform->matrix[0][0];
     259           0 :         unit.vector[1] = image->common.transform->matrix[1][0];
     260           0 :         unit.vector[2] = image->common.transform->matrix[2][0];
     261             :     }
     262             :     else
     263             :     {
     264           0 :         unit.vector[0] = pixman_fixed_1;
     265           0 :         unit.vector[1] = 0;
     266           0 :         unit.vector[2] = 0;
     267             :     }
     268             : 
     269           0 :     dx = linear->p2.x - linear->p1.x;
     270           0 :     dy = linear->p2.y - linear->p1.y;
     271             : 
     272           0 :     l = dx * dx + dy * dy;
     273             : 
     274           0 :     if (l == 0 || unit.vector[2] == 0)
     275           0 :     {
     276             :         /* affine transformation only */
     277             :         pixman_fixed_32_32_t t, next_inc;
     278             :         double inc;
     279             : 
     280           0 :         if (l == 0 || v.vector[2] == 0)
     281             :         {
     282           0 :             t = 0;
     283           0 :             inc = 0;
     284             :         }
     285             :         else
     286             :         {
     287             :             double invden, v2;
     288             : 
     289           0 :             invden = pixman_fixed_1 * (double) pixman_fixed_1 /
     290           0 :                 (l * (double) v.vector[2]);
     291           0 :             v2 = v.vector[2] * (1. / pixman_fixed_1);
     292           0 :             t = ((dx * v.vector[0] + dy * v.vector[1]) - 
     293           0 :                  (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
     294           0 :             inc = (dx * unit.vector[0] + dy * unit.vector[1]) * invden;
     295             :         }
     296           0 :         next_inc = 0;
     297             : 
     298           0 :         if (((pixman_fixed_32_32_t )(inc * width)) == 0)
     299             :         {
     300             :             register uint32_t color;
     301             :             uint16_t dither_diff;
     302             :             uint16_t color16;
     303             :             uint16_t color16b;
     304             : 
     305           0 :             color = _pixman_gradient_walker_pixel (&walker, t);
     306           0 :             color16 = dither_8888_to_0565(color, toggle);
     307           0 :             color16b = dither_8888_to_0565(color, toggle^1);
     308             :             // compute the difference
     309           0 :             dither_diff =  color16 ^ color16b;
     310           0 :             while (buffer < end) {
     311           0 :                 *buffer++ = color16;
     312             :                 // use dither_diff to toggle between color16 and color16b
     313           0 :                 color16 ^= dither_diff;
     314           0 :                 toggle ^= 1;
     315             :             }
     316             :         }
     317             :         else
     318             :         {
     319             :             int i;
     320             : 
     321           0 :             i = 0;
     322           0 :             while (buffer < end)
     323             :             {
     324           0 :                 if (!mask || *mask++)
     325             :                 {
     326           0 :                     *buffer = dither_8888_to_0565(_pixman_gradient_walker_pixel (&walker,
     327             :                                                                                  t + next_inc),
     328             :                                                   toggle);
     329             :                 }
     330           0 :                 toggle ^= 1;
     331           0 :                 i++;
     332           0 :                 next_inc = inc * i;
     333           0 :                 buffer++;
     334             :             }
     335             :         }
     336             :     }
     337             :     else
     338             :     {
     339             :         /* projective transformation */
     340             :         double t;
     341             : 
     342           0 :         t = 0;
     343             : 
     344           0 :         while (buffer < end)
     345             :         {
     346           0 :             if (!mask || *mask++)
     347             :             {
     348           0 :                 if (v.vector[2] != 0)
     349             :                 {
     350             :                     double invden, v2;
     351             : 
     352           0 :                     invden = pixman_fixed_1 * (double) pixman_fixed_1 /
     353           0 :                         (l * (double) v.vector[2]);
     354           0 :                     v2 = v.vector[2] * (1. / pixman_fixed_1);
     355           0 :                     t = ((dx * v.vector[0] + dy * v.vector[1]) - 
     356           0 :                          (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
     357             :                 }
     358             : 
     359           0 :                 *buffer = dither_8888_to_0565(_pixman_gradient_walker_pixel (&walker, t),
     360             :                                               toggle);
     361             :             }
     362           0 :             toggle ^= 1;
     363             : 
     364           0 :             ++buffer;
     365             : 
     366           0 :             v.vector[0] += unit.vector[0];
     367           0 :             v.vector[1] += unit.vector[1];
     368           0 :             v.vector[2] += unit.vector[2];
     369             :         }
     370             :     }
     371             : 
     372           0 :     iter->y++;
     373             : 
     374           0 :     return iter->buffer;
     375             : }
     376             : 
     377             : static uint32_t *
     378           0 : linear_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
     379             : {
     380           0 :     uint32_t *buffer = linear_get_scanline_narrow (iter, NULL);
     381             : 
     382           0 :     pixman_expand_to_float (
     383             :         (argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
     384             : 
     385           0 :     return buffer;
     386             : }
     387             : 
     388             : void
     389           0 : _pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t  *iter)
     390             : {
     391             :     // XXX: we can't use this optimization when dithering
     392             :     if (0 && linear_gradient_is_horizontal (
     393             :             iter->image, iter->x, iter->y, iter->width, iter->height))
     394             :     {
     395             :         if (iter->iter_flags & ITER_16)
     396             :             linear_get_scanline_16 (iter, NULL);
     397             :         else if (iter->iter_flags & ITER_NARROW)
     398             :             linear_get_scanline_narrow (iter, NULL);
     399             :         else
     400             :             linear_get_scanline_wide (iter, NULL);
     401             : 
     402             :         iter->get_scanline = _pixman_iter_get_scanline_noop;
     403             :     }
     404             :     else
     405             :     {
     406           0 :         if (iter->iter_flags & ITER_16)
     407           0 :             iter->get_scanline = linear_get_scanline_16;
     408           0 :         else if (iter->iter_flags & ITER_NARROW)
     409           0 :             iter->get_scanline = linear_get_scanline_narrow;
     410             :         else
     411           0 :             iter->get_scanline = linear_get_scanline_wide;
     412             :     }
     413           0 : }
     414             : 
     415             : PIXMAN_EXPORT pixman_image_t *
     416           0 : pixman_image_create_linear_gradient (const pixman_point_fixed_t *  p1,
     417             :                                      const pixman_point_fixed_t *  p2,
     418             :                                      const pixman_gradient_stop_t *stops,
     419             :                                      int                           n_stops)
     420             : {
     421             :     pixman_image_t *image;
     422             :     linear_gradient_t *linear;
     423             : 
     424           0 :     image = _pixman_image_allocate ();
     425             : 
     426           0 :     if (!image)
     427           0 :         return NULL;
     428             : 
     429           0 :     linear = &image->linear;
     430             : 
     431           0 :     if (!_pixman_init_gradient (&linear->common, stops, n_stops))
     432             :     {
     433           0 :         free (image);
     434           0 :         return NULL;
     435             :     }
     436             : 
     437           0 :     linear->p1 = *p1;
     438           0 :     linear->p2 = *p2;
     439             : 
     440           0 :     image->type = LINEAR;
     441             : 
     442           0 :     return image;
     443             : }
     444             : 

Generated by: LCOV version 1.13