gfx/cairo/libpixman/src/pixman-gradient-walker.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2  *
     3  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
     4  *             2005 Lars Knoll & Zack Rusin, Trolltech
     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 Keith Packard not be used in
    11  * advertising or publicity pertaining to distribution of the software without
    12  * specific, written prior permission.  Keith Packard makes no
    13  * representations about the suitability of this software for any purpose.  It
    14  * is provided "as is" without express or implied warranty.
    15  *
    16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
    17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
    18  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
    19  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    21  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
    22  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
    23  * SOFTWARE.
    24  */
    26 #ifdef HAVE_CONFIG_H
    27 #include <config.h>
    28 #endif
    29 #include "pixman-private.h"
    31 void
    32 _pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
    33                               gradient_t *              gradient,
    34                               pixman_repeat_t		repeat)
    35 {
    36     walker->num_stops = gradient->n_stops;
    37     walker->stops     = gradient->stops;
    38     walker->left_x    = 0;
    39     walker->right_x   = 0x10000;
    40     walker->stepper   = 0;
    41     walker->left_ag   = 0;
    42     walker->left_rb   = 0;
    43     walker->right_ag  = 0;
    44     walker->right_rb  = 0;
    45     walker->repeat    = repeat;
    47     walker->need_reset = TRUE;
    48 }
    50 static void
    51 gradient_walker_reset (pixman_gradient_walker_t *walker,
    52 		       pixman_fixed_48_16_t      pos)
    53 {
    54     int32_t x, left_x, right_x;
    55     pixman_color_t *left_c, *right_c;
    56     int n, count = walker->num_stops;
    57     pixman_gradient_stop_t *stops = walker->stops;
    59     if (walker->repeat == PIXMAN_REPEAT_NORMAL)
    60     {
    61 	x = (int32_t)pos & 0xffff;
    62     }
    63     else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
    64     {
    65 	x = (int32_t)pos & 0xffff;
    66 	if ((int32_t)pos & 0x10000)
    67 	    x = 0x10000 - x;
    68     }
    69     else
    70     {
    71 	x = pos;
    72     }
    74     for (n = 0; n < count; n++)
    75     {
    76 	if (x < stops[n].x)
    77 	    break;
    78     }
    80     left_x =  stops[n - 1].x;
    81     left_c = &stops[n - 1].color;
    83     right_x =  stops[n].x;
    84     right_c = &stops[n].color;
    86     if (walker->repeat == PIXMAN_REPEAT_NORMAL)
    87     {
    88 	left_x  += (pos - x);
    89 	right_x += (pos - x);
    90     }
    91     else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
    92     {
    93 	if ((int32_t)pos & 0x10000)
    94 	{
    95 	    pixman_color_t  *tmp_c;
    96 	    int32_t tmp_x;
    98 	    tmp_x   = 0x10000 - right_x;
    99 	    right_x = 0x10000 - left_x;
   100 	    left_x  = tmp_x;
   102 	    tmp_c   = right_c;
   103 	    right_c = left_c;
   104 	    left_c  = tmp_c;
   106 	    x = 0x10000 - x;
   107 	}
   108 	left_x  += (pos - x);
   109 	right_x += (pos - x);
   110     }
   111     else if (walker->repeat == PIXMAN_REPEAT_NONE)
   112     {
   113 	if (n == 0)
   114 	    right_c = left_c;
   115 	else if (n == count)
   116 	    left_c = right_c;
   117     }
   119     walker->left_x   = left_x;
   120     walker->right_x  = right_x;
   121     walker->left_ag  = ((left_c->alpha >> 8) << 16)   | (left_c->green >> 8);
   122     walker->left_rb  = ((left_c->red & 0xff00) << 8)  | (left_c->blue >> 8);
   123     walker->right_ag = ((right_c->alpha >> 8) << 16)  | (right_c->green >> 8);
   124     walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8);
   126     if (walker->left_x == walker->right_x                ||
   127         (walker->left_ag == walker->right_ag &&
   128 	 walker->left_rb == walker->right_rb))
   129     {
   130 	walker->stepper = 0;
   131     }
   132     else
   133     {
   134 	int32_t width = right_x - left_x;
   135 	walker->stepper = ((1 << 24) + width / 2) / width;
   136     }
   138     walker->need_reset = FALSE;
   139 }
   141 uint32_t
   142 _pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
   143                                pixman_fixed_48_16_t      x)
   144 {
   145     int dist, idist;
   146     uint32_t t1, t2, a, color;
   148     if (walker->need_reset || x < walker->left_x || x >= walker->right_x)
   149 	gradient_walker_reset (walker, x);
   151     dist  = ((int)(x - walker->left_x) * walker->stepper) >> 16;
   152     idist = 256 - dist;
   154     /* combined INTERPOLATE and premultiply */
   155     t1 = walker->left_rb * idist + walker->right_rb * dist;
   156     t1 = (t1 >> 8) & 0xff00ff;
   158     t2  = walker->left_ag * idist + walker->right_ag * dist;
   159     t2 &= 0xff00ff00;
   161     color = t2 & 0xff000000;
   162     a     = t2 >> 24;
   164     t1  = t1 * a + 0x800080;
   165     t1  = (t1 + ((t1 >> 8) & 0xff00ff)) >> 8;
   167     t2  = (t2 >> 8) * a + 0x800080;
   168     t2  = (t2 + ((t2 >> 8) & 0xff00ff));
   170     return (color | (t1 & 0xff00ff) | (t2 & 0xff00));
   171 }

mercurial