Subversion Repositories Kolibri OS

Rev

Rev 1891 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1891 Rev 3931
Line 29... Line 29...
29
#include "pixman-private.h"
29
#include "pixman-private.h"
Line 30... Line 30...
30
 
30
 
31
void
31
void
32
_pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
32
_pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
33
                              gradient_t *              gradient,
33
                              gradient_t *              gradient,
34
                              unsigned int              spread)
34
                              pixman_repeat_t		repeat)
35
{
35
{
36
    walker->num_stops = gradient->n_stops;
36
    walker->num_stops = gradient->n_stops;
37
    walker->stops     = gradient->stops;
37
    walker->stops     = gradient->stops;
38
    walker->left_x    = 0;
38
    walker->left_x    = 0;
39
    walker->right_x   = 0x10000;
39
    walker->right_x   = 0x10000;
40
    walker->stepper   = 0;
40
    walker->a_s       = 0.0f;
41
    walker->left_ag   = 0;
41
    walker->a_b       = 0.0f;
42
    walker->left_rb   = 0;
42
    walker->r_s       = 0.0f;
-
 
43
    walker->r_b       = 0.0f;
-
 
44
    walker->g_s       = 0.0f;
-
 
45
    walker->g_b       = 0.0f;
43
    walker->right_ag  = 0;
46
    walker->b_s       = 0.0f;
44
    walker->right_rb  = 0;
47
    walker->b_b       = 0.0f;
Line 45... Line 48...
45
    walker->spread    = spread;
48
    walker->repeat    = repeat;
46
 
49
 
Line 47... Line 50...
47
    walker->need_reset = TRUE;
50
    walker->need_reset = TRUE;
48
}
51
}
49
 
52
 
50
void
53
static void
51
_pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
54
gradient_walker_reset (pixman_gradient_walker_t *walker,
52
                               pixman_fixed_32_32_t      pos)
55
		       pixman_fixed_48_16_t      pos)
53
{
56
{
54
    int32_t x, left_x, right_x;
57
    int32_t x, left_x, right_x;
-
 
58
    pixman_color_t *left_c, *right_c;
-
 
59
    int n, count = walker->num_stops;
-
 
60
    pixman_gradient_stop_t *stops = walker->stops;
Line 55... Line -...
55
    pixman_color_t          *left_c, *right_c;
-
 
56
    int n, count = walker->num_stops;
-
 
57
    pixman_gradient_stop_t *      stops = walker->stops;
-
 
58
 
-
 
59
    static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
61
    float la, lr, lg, lb;
60
 
-
 
61
    switch (walker->spread)
-
 
62
    {
-
 
63
    case PIXMAN_REPEAT_NORMAL:
-
 
64
	x = (int32_t)pos & 0xFFFF;
-
 
65
	for (n = 0; n < count; n++)
-
 
66
	    if (x < stops[n].x)
-
 
67
		break;
-
 
68
	if (n == 0)
-
 
69
	{
-
 
70
	    left_x =  stops[count - 1].x - 0x10000;
62
    float ra, rr, rg, rb;
71
	    left_c = &stops[count - 1].color;
63
    float lx, rx;
72
	}
-
 
73
	else
64
 
74
	{
-
 
75
	    left_x =  stops[n - 1].x;
65
    if (walker->repeat == PIXMAN_REPEAT_NORMAL)
76
	    left_c = &stops[n - 1].color;
66
    {
-
 
67
	x = (int32_t)pos & 0xffff;
77
	}
68
    }
78
 
69
    else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
79
	if (n == count)
70
    {
80
	{
71
	x = (int32_t)pos & 0xffff;
81
	    right_x =  stops[0].x + 0x10000;
72
	if ((int32_t)pos & 0x10000)
82
	    right_c = &stops[0].color;
73
	    x = 0x10000 - x;
83
	}
-
 
84
	else
74
    }
85
	{
-
 
86
	    right_x =  stops[n].x;
-
 
87
	    right_c = &stops[n].color;
-
 
Line 88... Line -...
88
	}
-
 
89
	left_x  += (pos - x);
75
    else
90
	right_x += (pos - x);
-
 
91
	break;
-
 
92
 
-
 
93
    case PIXMAN_REPEAT_PAD:
-
 
94
	for (n = 0; n < count; n++)
76
    {
95
	    if (pos < stops[n].x)
77
	x = pos;
96
		break;
78
    }
97
 
79
    
98
	if (n == 0)
-
 
99
	{
80
    for (n = 0; n < count; n++)
100
	    left_x =  INT32_MIN;
81
    {
101
	    left_c = &stops[0].color;
82
	if (x < stops[n].x)
102
	}
-
 
Line 103... Line -...
103
	else
-
 
104
	{
-
 
105
	    left_x =  stops[n - 1].x;
-
 
106
	    left_c = &stops[n - 1].color;
-
 
107
	}
-
 
108
 
-
 
109
	if (n == count)
-
 
110
	{
83
	    break;
111
	    right_x =  INT32_MAX;
84
    }
112
	    right_c = &stops[n - 1].color;
-
 
113
	}
-
 
114
	else
-
 
115
	{
-
 
116
	    right_x =  stops[n].x;
-
 
117
	    right_c = &stops[n].color;
-
 
118
	}
-
 
119
	break;
-
 
120
 
-
 
121
    case PIXMAN_REPEAT_REFLECT:
-
 
Line 122... Line 85...
122
	x = (int32_t)pos & 0xFFFF;
85
    
123
	if ((int32_t)pos & 0x10000)
86
    left_x =  stops[n - 1].x;
124
	    x = 0x10000 - x;
-
 
125
	for (n = 0; n < count; n++)
-
 
126
	    if (x < stops[n].x)
-
 
127
		break;
-
 
128
 
-
 
129
	if (n == 0)
87
    left_c = &stops[n - 1].color;
130
	{
-
 
131
	    left_x =  -stops[0].x;
-
 
132
	    left_c = &stops[0].color;
-
 
133
	}
-
 
134
	else
-
 
135
	{
-
 
136
	    left_x =  stops[n - 1].x;
88
    
137
	    left_c = &stops[n - 1].color;
89
    right_x =  stops[n].x;
138
	}
90
    right_c = &stops[n].color;
139
 
91
 
140
	if (n == count)
-
 
141
	{
-
 
142
	    right_x = 0x20000 - stops[n - 1].x;
-
 
143
	    right_c = &stops[n - 1].color;
-
 
144
	}
92
    if (walker->repeat == PIXMAN_REPEAT_NORMAL)
145
	else
93
    {
146
	{
94
	left_x  += (pos - x);
147
	    right_x =  stops[n].x;
95
	right_x += (pos - x);
Line 163... Line 111...
163
 
111
 
164
	    x = 0x10000 - x;
112
	    x = 0x10000 - x;
165
	}
113
	}
166
	left_x  += (pos - x);
114
	left_x  += (pos - x);
-
 
115
	right_x += (pos - x);
-
 
116
    }
-
 
117
    else if (walker->repeat == PIXMAN_REPEAT_NONE)
-
 
118
    {
-
 
119
	if (n == 0)
-
 
120
	    right_c = left_c;
-
 
121
	else if (n == count)
167
	right_x += (pos - x);
122
	    left_c = right_c;
Line 168... Line 123...
168
	break;
123
    }
169
 
124
 
-
 
125
    /* The alpha channel is scaled to be in the [0, 255] interval,
170
    default:  /* REPEAT_NONE */
126
     * and the red/green/blue channels are scaled to be in [0, 1].
171
	for (n = 0; n < count; n++)
127
     * This ensures that after premultiplication all channels will
-
 
128
     * be in the [0, 255] interval.
-
 
129
     */
-
 
130
    la = (left_c->alpha * (1.0f/257.0f));
-
 
131
    lr = (left_c->red * (1.0f/257.0f));
Line -... Line 132...
-
 
132
    lg = (left_c->green * (1.0f/257.0f));
-
 
133
    lb = (left_c->blue * (1.0f/257.0f));
-
 
134
 
-
 
135
    ra = (right_c->alpha * (1.0f/257.0f));
-
 
136
    rr = (right_c->red * (1.0f/257.0f));
172
	    if (pos < stops[n].x)
137
    rg = (right_c->green * (1.0f/257.0f));
-
 
138
    rb = (right_c->blue * (1.0f/257.0f));
-
 
139
    
-
 
140
    lx = left_x * (1.0f/65536.0f);
173
		break;
141
    rx = right_x * (1.0f/65536.0f);
174
 
-
 
175
	if (n == 0)
-
 
176
	{
142
    
177
	    left_x  =  INT32_MIN;
-
 
178
	    right_x =  stops[0].x;
143
    if (FLOAT_IS_ZERO (rx - lx) || left_x == INT32_MIN || right_x == INT32_MAX)
179
	    left_c  = right_c = (pixman_color_t*) &transparent_black;
-
 
180
	}
144
    {
181
	else if (n == count)
145
	walker->a_s = walker->r_s = walker->g_s = walker->b_s = 0.0f;
182
	{
146
	walker->a_b = (la + ra) / 2.0f;
183
	    left_x  = stops[n - 1].x;
147
	walker->r_b = (lr + rr) / 510.0f;
184
	    right_x = INT32_MAX;
148
	walker->g_b = (lg + rg) / 510.0f;
185
	    left_c  = right_c = (pixman_color_t*) &transparent_black;
149
	walker->b_b = (lb + rb) / 510.0f;
186
	}
150
    }
-
 
151
    else
187
	else
152
    {
188
	{
153
	float w_rec = 1.0f / (rx - lx);
189
	    left_x  =  stops[n - 1].x;
154
 
-
 
155
	walker->a_b = (la * rx - ra * lx) * w_rec;
190
	    right_x =  stops[n].x;
156
	walker->r_b = (lr * rx - rr * lx) * w_rec * (1.0f/255.0f);
-
 
157
	walker->g_b = (lg * rx - rg * lx) * w_rec * (1.0f/255.0f);
-
 
158
	walker->b_b = (lb * rx - rb * lx) * w_rec * (1.0f/255.0f);
-
 
159
 
-
 
160
	walker->a_s = (ra - la) * w_rec;
191
	    left_c  = &stops[n - 1].color;
161
	walker->r_s = (rr - lr) * w_rec * (1.0f/255.0f);
Line 192... Line 162...
192
	    right_c = &stops[n].color;
162
	walker->g_s = (rg - lg) * w_rec * (1.0f/255.0f);
193
	}
163
	walker->b_s = (rb - lb) * w_rec * (1.0f/255.0f);
194
    }
-
 
195
 
-
 
196
    walker->left_x   = left_x;
-
 
197
    walker->right_x  = right_x;
-
 
198
    walker->left_ag  = ((left_c->alpha >> 8) << 16)   | (left_c->green >> 8);
-
 
199
    walker->left_rb  = ((left_c->red & 0xff00) << 8)  | (left_c->blue >> 8);
-
 
200
    walker->right_ag = ((right_c->alpha >> 8) << 16)  | (right_c->green >> 8);
-
 
201
    walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8);
-
 
202
 
-
 
203
    if (walker->left_x == walker->right_x                ||
-
 
204
        ( walker->left_ag == walker->right_ag &&
-
 
205
          walker->left_rb == walker->right_rb )   )
-
 
206
    {
-
 
207
	walker->stepper = 0;
-
 
208
    }
-
 
209
    else
-
 
Line 210... Line 164...
210
    {
164
    }
211
	int32_t width = right_x - left_x;
165
   
Line 212... Line -...
212
	walker->stepper = ((1 << 24) + width / 2) / width;
-
 
213
    }
-
 
214
 
-
 
215
    walker->need_reset = FALSE;
-
 
216
}
-
 
217
 
166
    walker->left_x = left_x;
218
#define  PIXMAN_GRADIENT_WALKER_NEED_RESET(w, x)                         \
167
    walker->right_x = right_x;
219
    ( (w)->need_reset || (x) < (w)->left_x || (x) >= (w)->right_x)
168
 
220
 
169
    walker->need_reset = FALSE;
221
 
170
}
222
/* the following assumes that PIXMAN_GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */
171
 
-
 
172
uint32_t
-
 
173
_pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
223
uint32_t
174
                               pixman_fixed_48_16_t      x)
224
_pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
175
{
225
                               pixman_fixed_32_32_t      x)
176
    float a, r, g, b;
-
 
177
    uint8_t a8, r8, g8, b8;
-
 
178
    uint32_t v;
226
{
179
    float y;
-
 
180
 
-
 
181
    if (walker->need_reset || x < walker->left_x || x >= walker->right_x)
-
 
182
        gradient_walker_reset (walker, x);
227
    int dist, idist;
183
 
-
 
184
    y = x * (1.0f / 65536.0f);
-
 
185
 
-
 
186
    a = walker->a_s * y + walker->a_b;
-
 
187
    r = a * (walker->r_s * y + walker->r_b);
228
    uint32_t t1, t2, a, color;
188
    g = a * (walker->g_s * y + walker->g_b);
229
 
189
    b = a * (walker->b_s * y + walker->b_b);
-
 
190
 
230
    if (PIXMAN_GRADIENT_WALKER_NEED_RESET (walker, x))
191
    a8 = a + 0.5f;
231
	_pixman_gradient_walker_reset (walker, x);
192
    r8 = r + 0.5f;
232
 
193
    g8 = g + 0.5f;
Line 233... Line -...
233
    dist  = ((int)(x - walker->left_x) * walker->stepper) >> 16;
-
 
234
    idist = 256 - dist;
-
 
235
 
-
 
236
    /* combined INTERPOLATE and premultiply */
-
 
237
    t1 = walker->left_rb * idist + walker->right_rb * dist;
194
    b8 = b + 0.5f;
238
    t1 = (t1 >> 8) & 0xff00ff;
-
 
239
 
-
 
240
    t2  = walker->left_ag * idist + walker->right_ag * dist;
-
 
241
    t2 &= 0xff00ff00;
-
 
242
 
-
 
243
    color = t2 & 0xff000000;
-
 
244
    a     = t2 >> 24;
-
 
245
 
-
 
246
    t1  = t1 * a + 0x800080;
195
 
247
    t1  = (t1 + ((t1 >> 8) & 0xff00ff)) >> 8;
-