11176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */ 21176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* 31176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 41176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. 51176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2000 SuSE, Inc. 61176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2005 Lars Knoll & Zack Rusin, Trolltech 71176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2007 Red Hat, Inc. 81176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 91176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Permission to use, copy, modify, distribute, and sell this software and its 111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * documentation for any purpose is hereby granted without fee, provided that 121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * the above copyright notice appear in all copies and that both that 131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * copyright notice and this permission notice appear in supporting 141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * documentation, and that the name of Keith Packard not be used in 151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * advertising or publicity pertaining to distribution of the software without 161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * specific, written prior permission. Keith Packard makes no 171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * representations about the suitability of this software for any purpose. It 181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * is provided "as is" without express or implied warranty. 191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * SOFTWARE. 281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef HAVE_CONFIG_H 311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <config.h> 321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif 331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <stdlib.h> 341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <math.h> 351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include "pixman-private.h" 361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 371176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic inline pixman_fixed_32_32_t 381176bdada62cabc6ec4b0308a930e83b679d5d36John Reckdot (pixman_fixed_48_16_t x1, 391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_fixed_48_16_t y1, 401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_fixed_48_16_t z1, 411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_fixed_48_16_t x2, 421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_fixed_48_16_t y2, 431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_fixed_48_16_t z2) 441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* 461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Exact computation, assuming that the input values can 471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * be represented as pixman_fixed_16_16_t 481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return x1 * x2 + y1 * y2 + z1 * z2; 501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 521176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic inline double 531176bdada62cabc6ec4b0308a930e83b679d5d36John Reckfdot (double x1, 541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double y1, 551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double z1, 561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double x2, 571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double y2, 581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double z2) 591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* 611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Error can be unbound in some special cases. 621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Using clever dot product algorithms (for example compensated 631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * dot product) would improve this but make the code much less 641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * obvious 651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return x1 * x2 + y1 * y2 + z1 * z2; 671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 691176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t 701176bdada62cabc6ec4b0308a930e83b679d5d36John Reckradial_compute_color (double a, 711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double b, 721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double c, 731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double inva, 741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double dr, 751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double mindr, 761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_gradient_walker_t *walker, 771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_repeat_t repeat) 781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* 801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * In this function error propagation can lead to bad results: 811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * - discr can have an unbound error (if b*b-a*c is very small), 821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * potentially making it the opposite sign of what it should have been 831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * (thus clearing a pixel that would have been colored or vice-versa) 841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * or propagating the error to sqrtdiscr; 851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * if discr has the wrong sign or b is very small, this can lead to bad 861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * results 871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * - the algorithm used to compute the solutions of the quadratic 891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * equation is not numerically stable (but saves one division compared 901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * to the numerically stable one); 911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * this can be a problem if a*c is much smaller than b*b 921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * - the above problems are worse if a is small (as inva becomes bigger) 941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double discr; 961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (a == 0) 981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double t; 1001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (b == 0) 1021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return 0; 1031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck t = pixman_fixed_1 / 2 * c / b; 1051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (repeat == PIXMAN_REPEAT_NONE) 1061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (0 <= t && t <= pixman_fixed_1) 1081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return _pixman_gradient_walker_pixel (walker, t); 1091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 1111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (t * dr >= mindr) 1131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return _pixman_gradient_walker_pixel (walker, t); 1141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return 0; 1171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck discr = fdot (b, a, 0, b, -c, 0); 1201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (discr >= 0) 1211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double sqrtdiscr, t0, t1; 1231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck sqrtdiscr = sqrt (discr); 1251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck t0 = (b + sqrtdiscr) * inva; 1261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck t1 = (b - sqrtdiscr) * inva; 1271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* 1291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * The root that must be used is the biggest one that belongs 1301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * to the valid range ([0,1] for PIXMAN_REPEAT_NONE, any 1311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * solution that results in a positive radius otherwise). 1321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 1331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * If a > 0, t0 is the biggest solution, so if it is valid, it 1341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * is the correct result. 1351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 1361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * If a < 0, only one of the solutions can be valid, so the 1371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * order in which they are tested is not important. 1381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 1391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (repeat == PIXMAN_REPEAT_NONE) 1401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (0 <= t0 && t0 <= pixman_fixed_1) 1421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return _pixman_gradient_walker_pixel (walker, t0); 1431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else if (0 <= t1 && t1 <= pixman_fixed_1) 1441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return _pixman_gradient_walker_pixel (walker, t1); 1451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 1471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (t0 * dr >= mindr) 1491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return _pixman_gradient_walker_pixel (walker, t0); 1501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else if (t1 * dr >= mindr) 1511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return _pixman_gradient_walker_pixel (walker, t1); 1521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return 0; 1561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 1571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1581176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t * 1591176bdada62cabc6ec4b0308a930e83b679d5d36John Reckradial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask) 1601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 1611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* 1621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Implementation of radial gradients following the PDF specification. 1631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * See section 8.7.4.5.4 Type 3 (Radial) Shadings of the PDF Reference 1641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Manual (PDF 32000-1:2008 at the time of this writing). 1651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 1661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * In the radial gradient problem we are given two circles (c₁,r₁) and 1671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * (c₂,r₂) that define the gradient itself. 1681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 1691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Mathematically the gradient can be defined as the family of circles 1701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 1711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * ((1-t)·c₁ + t·(c₂), (1-t)·r₁ + t·r₂) 1721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 1731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * excluding those circles whose radius would be < 0. When a point 1741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * belongs to more than one circle, the one with a bigger t is the only 1751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * one that contributes to its color. When a point does not belong 1761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * to any of the circles, it is transparent black, i.e. RGBA (0, 0, 0, 0). 1771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Further limitations on the range of values for t are imposed when 1781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * the gradient is not repeated, namely t must belong to [0,1]. 1791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 1801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * The graphical result is the same as drawing the valid (radius > 0) 1811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * circles with increasing t in [-inf, +inf] (or in [0,1] if the gradient 1821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * is not repeated) using SOURCE operator composition. 1831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 1841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * It looks like a cone pointing towards the viewer if the ending circle 1851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * is smaller than the starting one, a cone pointing inside the page if 1861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * the starting circle is the smaller one and like a cylinder if they 1871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * have the same radius. 1881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 1891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * What we actually do is, given the point whose color we are interested 1901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * in, compute the t values for that point, solving for t in: 1911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 1921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * length((1-t)·c₁ + t·(c₂) - p) = (1-t)·r₁ + t·r₂ 1931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 1941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Let's rewrite it in a simpler way, by defining some auxiliary 1951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * variables: 1961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 1971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * cd = c₂ - c₁ 1981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * pd = p - c₁ 1991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * dr = r₂ - r₁ 2001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * length(t·cd - pd) = r₁ + t·dr 2011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * which actually means 2031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * hypot(t·cdx - pdx, t·cdy - pdy) = r₁ + t·dr 2051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * or 2071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * ⎷((t·cdx - pdx)² + (t·cdy - pdy)²) = r₁ + t·dr. 2091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * If we impose (as stated earlier) that r₁ + t·dr >= 0, it becomes: 2111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * (t·cdx - pdx)² + (t·cdy - pdy)² = (r₁ + t·dr)² 2131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * where we can actually expand the squares and solve for t: 2151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * t²cdx² - 2t·cdx·pdx + pdx² + t²cdy² - 2t·cdy·pdy + pdy² = 2171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * = r₁² + 2·r₁·t·dr + t²·dr² 2181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * (cdx² + cdy² - dr²)t² - 2(cdx·pdx + cdy·pdy + r₁·dr)t + 2201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * (pdx² + pdy² - r₁²) = 0 2211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * A = cdx² + cdy² - dr² 2231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * B = pdx·cdx + pdy·cdy + r₁·dr 2241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * C = pdx² + pdy² - r₁² 2251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * At² - 2Bt + C = 0 2261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * The solutions (unless the equation degenerates because of A = 0) are: 2281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * t = (B ± ⎷(B² - A·C)) / A 2301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * The solution we are going to prefer is the bigger one, unless the 2321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * radius associated to it is negative (or it falls outside the valid t 2331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * range). 2341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Additional observations (useful for optimizations): 2361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * A does not depend on p 2371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * A < 0 <=> one of the two circles completely contains the other one 2391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * <=> for every p, the radiuses associated with the two t solutions 2401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * have opposite sign 2411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 2421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *image = iter->image; 2431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int x = iter->x; 2441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int y = iter->y; 2451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int width = iter->width; 2461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t *buffer = iter->buffer; 2471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck gradient_t *gradient = (gradient_t *)image; 2491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial_gradient_t *radial = (radial_gradient_t *)image; 2501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t *end = buffer + width; 2511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_gradient_walker_t walker; 2521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_vector_t v, unit; 2531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* reference point is the center of the pixel */ 2551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2; 2561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2; 2571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck v.vector[2] = pixman_fixed_1; 2581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck _pixman_gradient_walker_init (&walker, gradient, image->common.repeat); 2601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (image->common.transform) 2621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!pixman_transform_point_3d (image->common.transform, &v)) 2641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return iter->buffer; 2651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck unit.vector[0] = image->common.transform->matrix[0][0]; 2671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck unit.vector[1] = image->common.transform->matrix[1][0]; 2681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck unit.vector[2] = image->common.transform->matrix[2][0]; 2691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 2711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck unit.vector[0] = pixman_fixed_1; 2731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck unit.vector[1] = 0; 2741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck unit.vector[2] = 0; 2751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (unit.vector[2] == 0 && v.vector[2] == pixman_fixed_1) 2781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* 2801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Given: 2811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * t = (B ± ⎷(B² - A·C)) / A 2831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * where 2851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * A = cdx² + cdy² - dr² 2871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * B = pdx·cdx + pdy·cdy + r₁·dr 2881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * C = pdx² + pdy² - r₁² 2891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * det = B² - A·C 2901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Since we have an affine transformation, we know that (pdx, pdy) 2921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * increase linearly with each pixel, 2931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * pdx = pdx₀ + n·ux, 2951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * pdy = pdy₀ + n·uy, 2961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 2971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * we can then express B, C and det through multiple differentiation. 2981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 2991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_fixed_32_32_t b, db, c, dc, ddc; 3001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* warning: this computation may overflow */ 3021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck v.vector[0] -= radial->c1.x; 3031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck v.vector[1] -= radial->c1.y; 3041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* 3061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * B and C are computed and updated exactly. 3071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * If fdot was used instead of dot, in the worst case it would 3081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * lose 11 bits of precision in each of the multiplication and 3091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * summing up would zero out all the bit that were preserved, 3101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * thus making the result 0 instead of the correct one. 3111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * This would mean a worst case of unbound relative error or 3121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * about 2^10 absolute error 3131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 3141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck b = dot (v.vector[0], v.vector[1], radial->c1.radius, 3151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->delta.x, radial->delta.y, radial->delta.radius); 3161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck db = dot (unit.vector[0], unit.vector[1], 0, 3171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->delta.x, radial->delta.y, 0); 3181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck c = dot (v.vector[0], v.vector[1], 3201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck -((pixman_fixed_48_16_t) radial->c1.radius), 3211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck v.vector[0], v.vector[1], radial->c1.radius); 3221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dc = dot (2 * (pixman_fixed_48_16_t) v.vector[0] + unit.vector[0], 3231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2 * (pixman_fixed_48_16_t) v.vector[1] + unit.vector[1], 3241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 0, 3251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck unit.vector[0], unit.vector[1], 0); 3261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck ddc = 2 * dot (unit.vector[0], unit.vector[1], 0, 3271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck unit.vector[0], unit.vector[1], 0); 3281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck while (buffer < end) 3301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 3311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!mask || *mask++) 3321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 3331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *buffer = radial_compute_color (radial->a, b, c, 3341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->inva, 3351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->delta.radius, 3361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->mindr, 3371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck &walker, 3381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck image->common.repeat); 3391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 3401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck b += db; 3421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck c += dc; 3431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dc += ddc; 3441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck ++buffer; 3451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 3461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 3471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 3481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 3491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* projective */ 3501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* Warning: 3511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * error propagation guarantees are much looser than in the affine case 3521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 3531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck while (buffer < end) 3541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 3551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!mask || *mask++) 3561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 3571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (v.vector[2] != 0) 3581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 3591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck double pdx, pdy, invv2, b, c; 3601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck invv2 = 1. * pixman_fixed_1 / v.vector[2]; 3621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pdx = v.vector[0] * invv2 - radial->c1.x; 3641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* / pixman_fixed_1 */ 3651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pdy = v.vector[1] * invv2 - radial->c1.y; 3671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* / pixman_fixed_1 */ 3681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck b = fdot (pdx, pdy, radial->c1.radius, 3701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->delta.x, radial->delta.y, 3711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->delta.radius); 3721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* / pixman_fixed_1 / pixman_fixed_1 */ 3731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck c = fdot (pdx, pdy, -radial->c1.radius, 3751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pdx, pdy, radial->c1.radius); 3761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* / pixman_fixed_1 / pixman_fixed_1 */ 3771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *buffer = radial_compute_color (radial->a, b, c, 3791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->inva, 3801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->delta.radius, 3811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->mindr, 3821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck &walker, 3831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck image->common.repeat); 3841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 3851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 3861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 3871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *buffer = 0; 3881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 3891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 3901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck ++buffer; 3921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck v.vector[0] += unit.vector[0]; 3941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck v.vector[1] += unit.vector[1]; 3951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck v.vector[2] += unit.vector[2]; 3961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 3971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 3981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck iter->y++; 4001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return iter->buffer; 4011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 4021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4031176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic uint32_t * 4041176bdada62cabc6ec4b0308a930e83b679d5d36John Reckradial_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) 4051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 4061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t *buffer = radial_get_scanline_narrow (iter, NULL); 4071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_expand_to_float ( 4091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck (argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); 4101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return buffer; 4121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 4131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4141176bdada62cabc6ec4b0308a930e83b679d5d36John Reckvoid 4151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck_pixman_radial_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) 4161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 4171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (iter->iter_flags & ITER_NARROW) 4181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck iter->get_scanline = radial_get_scanline_narrow; 4191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 4201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck iter->get_scanline = radial_get_scanline_wide; 4211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 4221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4231176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT pixman_image_t * 4241176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_image_create_radial_gradient (const pixman_point_fixed_t * inner, 4251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const pixman_point_fixed_t * outer, 4261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_fixed_t inner_radius, 4271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_fixed_t outer_radius, 4281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const pixman_gradient_stop_t *stops, 4291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int n_stops) 4301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 4311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *image; 4321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial_gradient_t *radial; 4331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck image = _pixman_image_allocate (); 4351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!image) 4371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return NULL; 4381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial = &image->radial; 4401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!_pixman_init_gradient (&radial->common, stops, n_stops)) 4421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 4431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck free (image); 4441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return NULL; 4451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 4461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck image->type = RADIAL; 4481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->c1.x = inner->x; 4501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->c1.y = inner->y; 4511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->c1.radius = inner_radius; 4521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->c2.x = outer->x; 4531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->c2.y = outer->y; 4541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->c2.radius = outer_radius; 4551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* warning: this computations may overflow */ 4571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->delta.x = radial->c2.x - radial->c1.x; 4581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->delta.y = radial->c2.y - radial->c1.y; 4591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->delta.radius = radial->c2.radius - radial->c1.radius; 4601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* computed exactly, then cast to double -> every bit of the double 4621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck representation is correct (53 bits) */ 4631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->a = dot (radial->delta.x, radial->delta.y, -radial->delta.radius, 4641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->delta.x, radial->delta.y, radial->delta.radius); 4651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (radial->a != 0) 4661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->inva = 1. * pixman_fixed_1 / radial->a; 4671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck radial->mindr = -1. * pixman_fixed_1 * radial->c1.radius; 4691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return image; 4711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 472