~ubuntu-branches/ubuntu/saucy/pixman/saucy-security

« back to all changes in this revision

Viewing changes to pixman/pixman-source.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Cristau
  • Date: 2009-09-28 18:12:47 UTC
  • mfrom: (1.1.8 upstream) (2.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090928181247-3iehog63i50htejf
Tags: 0.16.2-1
* New upstream release (closes: #546849).
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 */
25
 
 
26
 
#ifdef HAVE_CONFIG_H
27
 
#include <config.h>
28
 
#endif
29
 
 
30
 
#include <stdlib.h>
31
 
#include <math.h>
32
 
 
33
 
#include "pixman-private.h"
34
 
 
35
 
typedef struct
36
 
{
37
 
    uint32_t        left_ag;
38
 
    uint32_t        left_rb;
39
 
    uint32_t        right_ag;
40
 
    uint32_t        right_rb;
41
 
    int32_t       left_x;
42
 
    int32_t       right_x;
43
 
    int32_t       stepper;
44
 
 
45
 
    pixman_gradient_stop_t      *stops;
46
 
    int                      num_stops;
47
 
    unsigned int             spread;
48
 
 
49
 
    int           need_reset;
50
 
} GradientWalker;
51
 
 
52
 
static void
53
 
_gradient_walker_init (GradientWalker  *walker,
54
 
                       gradient_t      *gradient,
55
 
                       unsigned int     spread)
56
 
{
57
 
    walker->num_stops = gradient->n_stops;
58
 
    walker->stops     = gradient->stops;
59
 
    walker->left_x    = 0;
60
 
    walker->right_x   = 0x10000;
61
 
    walker->stepper   = 0;
62
 
    walker->left_ag   = 0;
63
 
    walker->left_rb   = 0;
64
 
    walker->right_ag  = 0;
65
 
    walker->right_rb  = 0;
66
 
    walker->spread    = spread;
67
 
 
68
 
    walker->need_reset = TRUE;
69
 
}
70
 
 
71
 
static void
72
 
_gradient_walker_reset (GradientWalker  *walker,
73
 
                        pixman_fixed_32_32_t     pos)
74
 
{
75
 
    int32_t                  x, left_x, right_x;
76
 
    pixman_color_t          *left_c, *right_c;
77
 
    int                      n, count = walker->num_stops;
78
 
    pixman_gradient_stop_t *      stops = walker->stops;
79
 
 
80
 
    static const pixman_color_t   transparent_black = { 0, 0, 0, 0 };
81
 
 
82
 
    switch (walker->spread)
83
 
    {
84
 
    case PIXMAN_REPEAT_NORMAL:
85
 
        x = (int32_t)pos & 0xFFFF;
86
 
        for (n = 0; n < count; n++)
87
 
            if (x < stops[n].x)
88
 
                break;
89
 
        if (n == 0) {
90
 
            left_x =  stops[count-1].x - 0x10000;
91
 
            left_c = &stops[count-1].color;
92
 
        } else {
93
 
            left_x =  stops[n-1].x;
94
 
            left_c = &stops[n-1].color;
95
 
        }
96
 
 
97
 
        if (n == count) {
98
 
            right_x =  stops[0].x + 0x10000;
99
 
            right_c = &stops[0].color;
100
 
        } else {
101
 
            right_x =  stops[n].x;
102
 
            right_c = &stops[n].color;
103
 
        }
104
 
        left_x  += (pos - x);
105
 
        right_x += (pos - x);
106
 
        break;
107
 
 
108
 
    case PIXMAN_REPEAT_PAD:
109
 
        for (n = 0; n < count; n++)
110
 
            if (pos < stops[n].x)
111
 
                break;
112
 
 
113
 
        if (n == 0) {
114
 
            left_x =  INT32_MIN;
115
 
            left_c = &stops[0].color;
116
 
        } else {
117
 
            left_x =  stops[n-1].x;
118
 
            left_c = &stops[n-1].color;
119
 
        }
120
 
 
121
 
        if (n == count) {
122
 
            right_x =  INT32_MAX;
123
 
            right_c = &stops[n-1].color;
124
 
        } else {
125
 
            right_x =  stops[n].x;
126
 
            right_c = &stops[n].color;
127
 
        }
128
 
        break;
129
 
 
130
 
    case PIXMAN_REPEAT_REFLECT:
131
 
        x = (int32_t)pos & 0xFFFF;
132
 
        if ((int32_t)pos & 0x10000)
133
 
            x = 0x10000 - x;
134
 
        for (n = 0; n < count; n++)
135
 
            if (x < stops[n].x)
136
 
                break;
137
 
 
138
 
        if (n == 0) {
139
 
            left_x =  -stops[0].x;
140
 
            left_c = &stops[0].color;
141
 
        } else {
142
 
            left_x =  stops[n-1].x;
143
 
            left_c = &stops[n-1].color;
144
 
        }
145
 
 
146
 
        if (n == count) {
147
 
            right_x = 0x20000 - stops[n-1].x;
148
 
            right_c = &stops[n-1].color;
149
 
        } else {
150
 
            right_x =  stops[n].x;
151
 
            right_c = &stops[n].color;
152
 
        }
153
 
 
154
 
        if ((int32_t)pos & 0x10000) {
155
 
            pixman_color_t  *tmp_c;
156
 
            int32_t          tmp_x;
157
 
 
158
 
            tmp_x   = 0x10000 - right_x;
159
 
            right_x = 0x10000 - left_x;
160
 
            left_x  = tmp_x;
161
 
 
162
 
            tmp_c   = right_c;
163
 
            right_c = left_c;
164
 
            left_c  = tmp_c;
165
 
 
166
 
            x = 0x10000 - x;
167
 
        }
168
 
        left_x  += (pos - x);
169
 
        right_x += (pos - x);
170
 
        break;
171
 
 
172
 
    default:  /* RepeatNone */
173
 
        for (n = 0; n < count; n++)
174
 
            if (pos < stops[n].x)
175
 
                break;
176
 
 
177
 
        if (n == 0)
178
 
        {
179
 
            left_x  =  INT32_MIN;
180
 
            right_x =  stops[0].x;
181
 
            left_c  = right_c = (pixman_color_t*) &transparent_black;
182
 
        }
183
 
        else if (n == count)
184
 
        {
185
 
            left_x  = stops[n-1].x;
186
 
            right_x = INT32_MAX;
187
 
            left_c  = right_c = (pixman_color_t*) &transparent_black;
188
 
        }
189
 
        else
190
 
        {
191
 
            left_x  =  stops[n-1].x;
192
 
            right_x =  stops[n].x;
193
 
            left_c  = &stops[n-1].color;
194
 
            right_c = &stops[n].color;
195
 
        }
196
 
    }
197
 
 
198
 
    walker->left_x   = left_x;
199
 
    walker->right_x  = right_x;
200
 
    walker->left_ag  = ((left_c->alpha >> 8) << 16)   | (left_c->green >> 8);
201
 
    walker->left_rb  = ((left_c->red & 0xff00) << 8)  | (left_c->blue >> 8);
202
 
    walker->right_ag = ((right_c->alpha >> 8) << 16)  | (right_c->green >> 8);
203
 
    walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8);
204
 
 
205
 
    if ( walker->left_x == walker->right_x                ||
206
 
         ( walker->left_ag == walker->right_ag &&
207
 
           walker->left_rb == walker->right_rb )   )
208
 
    {
209
 
        walker->stepper = 0;
210
 
    }
211
 
    else
212
 
    {
213
 
        int32_t width = right_x - left_x;
214
 
        walker->stepper = ((1 << 24) + width/2)/width;
215
 
    }
216
 
 
217
 
    walker->need_reset = FALSE;
218
 
}
219
 
 
220
 
#define  GRADIENT_WALKER_NEED_RESET(w,x)                                \
221
 
    ( (w)->need_reset || (x) < (w)->left_x || (x) >= (w)->right_x)
222
 
 
223
 
 
224
 
/* the following assumes that GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */
225
 
static uint32_t
226
 
_gradient_walker_pixel (GradientWalker  *walker,
227
 
                        pixman_fixed_32_32_t     x)
228
 
{
229
 
    int  dist, idist;
230
 
    uint32_t  t1, t2, a, color;
231
 
 
232
 
    if (GRADIENT_WALKER_NEED_RESET (walker, x))
233
 
        _gradient_walker_reset (walker, x);
234
 
 
235
 
    dist  = ((int)(x - walker->left_x)*walker->stepper) >> 16;
236
 
    idist = 256 - dist;
237
 
 
238
 
    /* combined INTERPOLATE and premultiply */
239
 
    t1 = walker->left_rb*idist + walker->right_rb*dist;
240
 
    t1 = (t1 >> 8) & 0xff00ff;
241
 
 
242
 
    t2  = walker->left_ag*idist + walker->right_ag*dist;
243
 
    t2 &= 0xff00ff00;
244
 
 
245
 
    color = t2 & 0xff000000;
246
 
    a     = t2 >> 24;
247
 
 
248
 
    t1  = t1*a + 0x800080;
249
 
    t1  = (t1 + ((t1 >> 8) & 0xff00ff)) >> 8;
250
 
 
251
 
    t2  = (t2 >> 8)*a + 0x800080;
252
 
    t2  = (t2 + ((t2 >> 8) & 0xff00ff));
253
 
 
254
 
    return (color | (t1 & 0xff00ff) | (t2 & 0xff00));
255
 
}
256
 
 
257
 
void pixmanFetchSourcePict(source_image_t * pict, int x, int y, int width,
258
 
                           uint32_t *buffer, uint32_t *mask, uint32_t maskBits)
259
 
{
260
 
#if 0
261
 
    SourcePictPtr   pGradient = pict->pSourcePict;
262
 
#endif
263
 
    GradientWalker  walker;
264
 
    uint32_t       *end = buffer + width;
265
 
    gradient_t      *gradient;
266
 
 
267
 
    if (pict->common.type == SOLID)
268
 
    {
269
 
        register uint32_t color = ((solid_fill_t *)pict)->color;
270
 
 
271
 
        while (buffer < end)
272
 
            *(buffer++) = color;
273
 
 
274
 
        return;
275
 
    }
276
 
 
277
 
    gradient = (gradient_t *)pict;
278
 
 
279
 
    _gradient_walker_init (&walker, gradient, pict->common.repeat);
280
 
 
281
 
    if (pict->common.type == LINEAR) {
282
 
        pixman_vector_t v, unit;
283
 
        pixman_fixed_32_32_t l;
284
 
        pixman_fixed_48_16_t dx, dy, a, b, off;
285
 
        linear_gradient_t *linear = (linear_gradient_t *)pict;
286
 
 
287
 
        /* reference point is the center of the pixel */
288
 
        v.vector[0] = pixman_int_to_fixed(x) + pixman_fixed_1/2;
289
 
        v.vector[1] = pixman_int_to_fixed(y) + pixman_fixed_1/2;
290
 
        v.vector[2] = pixman_fixed_1;
291
 
        if (pict->common.transform) {
292
 
            if (!pixman_transform_point_3d (pict->common.transform, &v))
293
 
                return;
294
 
            unit.vector[0] = pict->common.transform->matrix[0][0];
295
 
            unit.vector[1] = pict->common.transform->matrix[1][0];
296
 
            unit.vector[2] = pict->common.transform->matrix[2][0];
297
 
        } else {
298
 
            unit.vector[0] = pixman_fixed_1;
299
 
            unit.vector[1] = 0;
300
 
            unit.vector[2] = 0;
301
 
        }
302
 
 
303
 
        dx = linear->p2.x - linear->p1.x;
304
 
        dy = linear->p2.y - linear->p1.y;
305
 
        l = dx*dx + dy*dy;
306
 
        if (l != 0) {
307
 
            a = (dx << 32) / l;
308
 
            b = (dy << 32) / l;
309
 
            off = (-a*linear->p1.x - b*linear->p1.y)>>16;
310
 
        }
311
 
        if (l == 0  || (unit.vector[2] == 0 && v.vector[2] == pixman_fixed_1)) {
312
 
            pixman_fixed_48_16_t inc, t;
313
 
            /* affine transformation only */
314
 
            if (l == 0) {
315
 
                t = 0;
316
 
                inc = 0;
317
 
            } else {
318
 
                t = ((a*v.vector[0] + b*v.vector[1]) >> 16) + off;
319
 
                inc = (a * unit.vector[0] + b * unit.vector[1]) >> 16;
320
 
            }
321
 
 
322
 
            if (pict->class == SOURCE_IMAGE_CLASS_VERTICAL)
323
 
            {
324
 
                register uint32_t color;
325
 
 
326
 
                color = _gradient_walker_pixel( &walker, t );
327
 
                while (buffer < end)
328
 
                    *(buffer++) = color;
329
 
            }
330
 
            else
331
 
            {
332
 
                if (!mask) {
333
 
                    while (buffer < end)
334
 
                    {
335
 
                        *(buffer) = _gradient_walker_pixel (&walker, t);
336
 
                        buffer += 1;
337
 
                        t      += inc;
338
 
                    }
339
 
                } else {
340
 
                    while (buffer < end) {
341
 
                        if (*mask++ & maskBits)
342
 
                        {
343
 
                            *(buffer) = _gradient_walker_pixel (&walker, t);
344
 
                        }
345
 
                        buffer += 1;
346
 
                        t      += inc;
347
 
                    }
348
 
                }
349
 
            }
350
 
        }
351
 
        else /* projective transformation */
352
 
        {
353
 
            pixman_fixed_48_16_t t;
354
 
 
355
 
            if (pict->class == SOURCE_IMAGE_CLASS_VERTICAL)
356
 
            {
357
 
                register uint32_t color;
358
 
 
359
 
                if (v.vector[2] == 0)
360
 
                {
361
 
                    t = 0;
362
 
                }
363
 
                else
364
 
                {
365
 
                    pixman_fixed_48_16_t x, y;
366
 
 
367
 
                    x = ((pixman_fixed_48_16_t) v.vector[0] << 16) / v.vector[2];
368
 
                    y = ((pixman_fixed_48_16_t) v.vector[1] << 16) / v.vector[2];
369
 
                    t = ((a * x + b * y) >> 16) + off;
370
 
                }
371
 
 
372
 
                color = _gradient_walker_pixel( &walker, t );
373
 
                while (buffer < end)
374
 
                    *(buffer++) = color;
375
 
            }
376
 
            else
377
 
            {
378
 
                while (buffer < end)
379
 
                {
380
 
                    if (!mask || *mask++ & maskBits)
381
 
                    {
382
 
                        if (v.vector[2] == 0) {
383
 
                            t = 0;
384
 
                        } else {
385
 
                            pixman_fixed_48_16_t x, y;
386
 
                            x = ((pixman_fixed_48_16_t)v.vector[0] << 16) / v.vector[2];
387
 
                            y = ((pixman_fixed_48_16_t)v.vector[1] << 16) / v.vector[2];
388
 
                            t = ((a*x + b*y) >> 16) + off;
389
 
                        }
390
 
                        *(buffer) = _gradient_walker_pixel (&walker, t);
391
 
                    }
392
 
                    ++buffer;
393
 
                    v.vector[0] += unit.vector[0];
394
 
                    v.vector[1] += unit.vector[1];
395
 
                    v.vector[2] += unit.vector[2];
396
 
                }
397
 
            }
398
 
        }
399
 
    } else {
400
 
 
401
 
/*
402
 
 * In the radial gradient problem we are given two circles (c₁,r₁) and
403
 
 * (c₂,r₂) that define the gradient itself. Then, for any point p, we
404
 
 * must compute the value(s) of t within [0.0, 1.0] representing the
405
 
 * circle(s) that would color the point.
406
 
 *
407
 
 * There are potentially two values of t since the point p can be
408
 
 * colored by both sides of the circle, (which happens whenever one
409
 
 * circle is not entirely contained within the other).
410
 
 *
411
 
 * If we solve for a value of t that is outside of [0.0, 1.0] then we
412
 
 * use the extend mode (NONE, REPEAT, REFLECT, or PAD) to map to a
413
 
 * value within [0.0, 1.0].
414
 
 *
415
 
 * Here is an illustration of the problem:
416
 
 *
417
 
 *              p₂
418
 
 *           p  •
419
 
 *           •   ╲
420
 
 *        ·       ╲r₂
421
 
 *  p₁ ·           ╲
422
 
 *  •              θ╲
423
 
 *   ╲             ╌╌•
424
 
 *    ╲r₁        ·   c₂
425
 
 *    θ╲    ·
426
 
 *    ╌╌•
427
 
 *      c₁
428
 
 *
429
 
 * Given (c₁,r₁), (c₂,r₂) and p, we must find an angle θ such that two
430
 
 * points p₁ and p₂ on the two circles are collinear with p. Then, the
431
 
 * desired value of t is the ratio of the length of p₁p to the length
432
 
 * of p₁p₂.
433
 
 *
434
 
 * So, we have six unknown values: (p₁x, p₁y), (p₂x, p₂y), θ and t.
435
 
 * We can also write six equations that constrain the problem:
436
 
 *
437
 
 * Point p₁ is a distance r₁ from c₁ at an angle of θ:
438
 
 *
439
 
 *      1. p₁x = c₁x + r₁·cos θ
440
 
 *      2. p₁y = c₁y + r₁·sin θ
441
 
 *
442
 
 * Point p₂ is a distance r₂ from c₂ at an angle of θ:
443
 
 *
444
 
 *      3. p₂x = c₂x + r2·cos θ
445
 
 *      4. p₂y = c₂y + r2·sin θ
446
 
 *
447
 
 * Point p lies at a fraction t along the line segment p₁p₂:
448
 
 *
449
 
 *      5. px = t·p₂x + (1-t)·p₁x
450
 
 *      6. py = t·p₂y + (1-t)·p₁y
451
 
 *
452
 
 * To solve, first subtitute 1-4 into 5 and 6:
453
 
 *
454
 
 * px = t·(c₂x + r₂·cos θ) + (1-t)·(c₁x + r₁·cos θ)
455
 
 * py = t·(c₂y + r₂·sin θ) + (1-t)·(c₁y + r₁·sin θ)
456
 
 *
457
 
 * Then solve each for cos θ and sin θ expressed as a function of t:
458
 
 *
459
 
 * cos θ = (-(c₂x - c₁x)·t + (px - c₁x)) / ((r₂-r₁)·t + r₁)
460
 
 * sin θ = (-(c₂y - c₁y)·t + (py - c₁y)) / ((r₂-r₁)·t + r₁)
461
 
 *
462
 
 * To simplify this a bit, we define new variables for several of the
463
 
 * common terms as shown below:
464
 
 *
465
 
 *              p₂
466
 
 *           p  •
467
 
 *           •   ╲
468
 
 *        ·  ┆    ╲r₂
469
 
 *  p₁ ·     ┆     ╲
470
 
 *  •     pdy┆      ╲
471
 
 *   ╲       ┆       •c₂
472
 
 *    ╲r₁    ┆   ·   ┆
473
 
 *     ╲    ·┆       ┆cdy
474
 
 *      •╌╌╌╌┴╌╌╌╌╌╌╌┘
475
 
 *    c₁  pdx   cdx
476
 
 *
477
 
 * cdx = (c₂x - c₁x)
478
 
 * cdy = (c₂y - c₁y)
479
 
 *  dr =  r₂-r₁
480
 
 * pdx =  px - c₁x
481
 
 * pdy =  py - c₁y
482
 
 *
483
 
 * Note that cdx, cdy, and dr do not depend on point p at all, so can
484
 
 * be pre-computed for the entire gradient. The simplifed equations
485
 
 * are now:
486
 
 *
487
 
 * cos θ = (-cdx·t + pdx) / (dr·t + r₁)
488
 
 * sin θ = (-cdy·t + pdy) / (dr·t + r₁)
489
 
 *
490
 
 * Finally, to get a single function of t and eliminate the last
491
 
 * unknown θ, we use the identity sin²θ + cos²θ = 1. First, square
492
 
 * each equation, (we knew a quadratic was coming since it must be
493
 
 * possible to obtain two solutions in some cases):
494
 
 *
495
 
 * cos²θ = (cdx²t² - 2·cdx·pdx·t + pdx²) / (dr²·t² + 2·r₁·dr·t + r₁²)
496
 
 * sin²θ = (cdy²t² - 2·cdy·pdy·t + pdy²) / (dr²·t² + 2·r₁·dr·t + r₁²)
497
 
 *
498
 
 * Then add both together, set the result equal to 1, and express as a
499
 
 * standard quadratic equation in t of the form At² + Bt + C = 0
500
 
 *
501
 
 * (cdx² + cdy² - dr²)·t² - 2·(cdx·pdx + cdy·pdy + r₁·dr)·t + (pdx² + pdy² - r₁²) = 0
502
 
 *
503
 
 * In other words:
504
 
 *
505
 
 * A = cdx² + cdy² - dr²
506
 
 * B = -2·(pdx·cdx + pdy·cdy + r₁·dr)
507
 
 * C = pdx² + pdy² - r₁²
508
 
 *
509
 
 * And again, notice that A does not depend on p, so can be
510
 
 * precomputed. From here we just use the quadratic formula to solve
511
 
 * for t:
512
 
 *
513
 
 * t = (-2·B ± ⎷(B² - 4·A·C)) / 2·A
514
 
 */
515
 
        /* radial or conical */
516
 
        pixman_bool_t affine = TRUE;
517
 
        double cx = 1.;
518
 
        double cy = 0.;
519
 
        double cz = 0.;
520
 
        double rx = x + 0.5;
521
 
        double ry = y + 0.5;
522
 
        double rz = 1.;
523
 
 
524
 
        if (pict->common.transform) {
525
 
            pixman_vector_t v;
526
 
            /* reference point is the center of the pixel */
527
 
            v.vector[0] = pixman_int_to_fixed(x) + pixman_fixed_1/2;
528
 
            v.vector[1] = pixman_int_to_fixed(y) + pixman_fixed_1/2;
529
 
            v.vector[2] = pixman_fixed_1;
530
 
            if (!pixman_transform_point_3d (pict->common.transform, &v))
531
 
                return;
532
 
 
533
 
            cx = pict->common.transform->matrix[0][0]/65536.;
534
 
            cy = pict->common.transform->matrix[1][0]/65536.;
535
 
            cz = pict->common.transform->matrix[2][0]/65536.;
536
 
            rx = v.vector[0]/65536.;
537
 
            ry = v.vector[1]/65536.;
538
 
            rz = v.vector[2]/65536.;
539
 
            affine = pict->common.transform->matrix[2][0] == 0 && v.vector[2] == pixman_fixed_1;
540
 
        }
541
 
 
542
 
        if (pict->common.type == RADIAL) {
543
 
            radial_gradient_t *radial = (radial_gradient_t *)pict;
544
 
            if (affine) {
545
 
                while (buffer < end) {
546
 
                    if (!mask || *mask++ & maskBits)
547
 
                    {
548
 
                        double pdx, pdy;
549
 
                        double B, C;
550
 
                        double det;
551
 
                        double c1x = radial->c1.x / 65536.0;
552
 
                        double c1y = radial->c1.y / 65536.0;
553
 
                        double r1  = radial->c1.radius / 65536.0;
554
 
                        pixman_fixed_48_16_t t;
555
 
 
556
 
                        pdx = rx - c1x;
557
 
                        pdy = ry - c1y;
558
 
 
559
 
                        B = -2 * (  pdx * radial->cdx
560
 
                                    + pdy * radial->cdy
561
 
                                    + r1 * radial->dr);
562
 
                        C = (pdx * pdx + pdy * pdy - r1 * r1);
563
 
 
564
 
                        det = (B * B) - (4 * radial->A * C);
565
 
                        if (det < 0.0)
566
 
                            det = 0.0;
567
 
 
568
 
                        if (radial->A < 0)
569
 
                            t = (pixman_fixed_48_16_t) ((- B - sqrt(det)) / (2.0 * radial->A) * 65536);
570
 
                        else
571
 
                            t = (pixman_fixed_48_16_t) ((- B + sqrt(det)) / (2.0 * radial->A) * 65536);
572
 
 
573
 
                        *(buffer) = _gradient_walker_pixel (&walker, t);
574
 
                    }
575
 
                    ++buffer;
576
 
 
577
 
                    rx += cx;
578
 
                    ry += cy;
579
 
                }
580
 
            } else {
581
 
                /* projective */
582
 
                while (buffer < end) {
583
 
                    if (!mask || *mask++ & maskBits)
584
 
                    {
585
 
                        double pdx, pdy;
586
 
                        double B, C;
587
 
                        double det;
588
 
                        double c1x = radial->c1.x / 65536.0;
589
 
                        double c1y = radial->c1.y / 65536.0;
590
 
                        double r1  = radial->c1.radius / 65536.0;
591
 
                        pixman_fixed_48_16_t t;
592
 
                        double x, y;
593
 
 
594
 
                        if (rz != 0) {
595
 
                            x = rx/rz;
596
 
                            y = ry/rz;
597
 
                        } else {
598
 
                            x = y = 0.;
599
 
                        }
600
 
 
601
 
                        pdx = x - c1x;
602
 
                        pdy = y - c1y;
603
 
 
604
 
                        B = -2 * (  pdx * radial->cdx
605
 
                                    + pdy * radial->cdy
606
 
                                    + r1 * radial->dr);
607
 
                        C = (pdx * pdx + pdy * pdy - r1 * r1);
608
 
 
609
 
                        det = (B * B) - (4 * radial->A * C);
610
 
                        if (det < 0.0)
611
 
                            det = 0.0;
612
 
 
613
 
                        if (radial->A < 0)
614
 
                            t = (pixman_fixed_48_16_t) ((- B - sqrt(det)) / (2.0 * radial->A) * 65536);
615
 
                        else
616
 
                            t = (pixman_fixed_48_16_t) ((- B + sqrt(det)) / (2.0 * radial->A) * 65536);
617
 
 
618
 
                        *(buffer) = _gradient_walker_pixel (&walker, t);
619
 
                    }
620
 
                    ++buffer;
621
 
 
622
 
                    rx += cx;
623
 
                    ry += cy;
624
 
                    rz += cz;
625
 
                }
626
 
            }
627
 
        } else /* SourcePictTypeConical */ {
628
 
            conical_gradient_t *conical = (conical_gradient_t *)pict;
629
 
            double a = conical->angle/(180.*65536);
630
 
            if (affine) {
631
 
                rx -= conical->center.x/65536.;
632
 
                ry -= conical->center.y/65536.;
633
 
 
634
 
                while (buffer < end) {
635
 
                    double angle;
636
 
 
637
 
                    if (!mask || *mask++ & maskBits)
638
 
                    {
639
 
                        pixman_fixed_48_16_t   t;
640
 
 
641
 
                        angle = atan2(ry, rx) + a;
642
 
                        t     = (pixman_fixed_48_16_t) (angle * (65536. / (2*M_PI)));
643
 
 
644
 
                        *(buffer) = _gradient_walker_pixel (&walker, t);
645
 
                    }
646
 
 
647
 
                    ++buffer;
648
 
                    rx += cx;
649
 
                    ry += cy;
650
 
                }
651
 
            } else {
652
 
                while (buffer < end) {
653
 
                    double x, y;
654
 
                    double angle;
655
 
 
656
 
                    if (!mask || *mask++ & maskBits)
657
 
                    {
658
 
                        pixman_fixed_48_16_t  t;
659
 
 
660
 
                        if (rz != 0) {
661
 
                            x = rx/rz;
662
 
                            y = ry/rz;
663
 
                        } else {
664
 
                            x = y = 0.;
665
 
                        }
666
 
                        x -= conical->center.x/65536.;
667
 
                        y -= conical->center.y/65536.;
668
 
                        angle = atan2(y, x) + a;
669
 
                        t     = (pixman_fixed_48_16_t) (angle * (65536. / (2*M_PI)));
670
 
 
671
 
                        *(buffer) = _gradient_walker_pixel (&walker, t);
672
 
                    }
673
 
 
674
 
                    ++buffer;
675
 
                    rx += cx;
676
 
                    ry += cy;
677
 
                    rz += cz;
678
 
                }
679
 
            }
680
 
        }
681
 
    }
682
 
}
683
 
 
684
 
/*
685
 
 * For now, just evaluate the source picture at 32bpp and expand.  We could
686
 
 * produce smoother gradients by evaluating them at higher color depth, but
687
 
 * that's a project for the future.
688
 
 */
689
 
void pixmanFetchSourcePict64(source_image_t * pict, int x, int y, int width,
690
 
                             uint64_t *buffer, uint64_t *mask, uint32_t maskBits)
691
 
{
692
 
    uint32_t *mask8 = NULL;
693
 
 
694
 
    // Contract the mask image, if one exists, so that the 32-bit fetch function
695
 
    // can use it.
696
 
    if (mask) {
697
 
        mask8 = pixman_malloc_ab(width, sizeof(uint32_t));
698
 
        pixman_contract(mask8, mask, width);
699
 
    }
700
 
 
701
 
    // Fetch the source image into the first half of buffer.
702
 
    pixmanFetchSourcePict(pict, x, y, width, (uint32_t*)buffer, mask8,
703
 
                          maskBits);
704
 
 
705
 
    // Expand from 32bpp to 64bpp in place.
706
 
    pixman_expand(buffer, (uint32_t*)buffer, PIXMAN_a8r8g8b8, width);
707
 
 
708
 
    free(mask8);
709
 
}