diff options
Diffstat (limited to 'gfx/cairo/quartz-repeating-radial-gradients.patch')
-rw-r--r-- | gfx/cairo/quartz-repeating-radial-gradients.patch | 305 |
1 files changed, 0 insertions, 305 deletions
diff --git a/gfx/cairo/quartz-repeating-radial-gradients.patch b/gfx/cairo/quartz-repeating-radial-gradients.patch deleted file mode 100644 index 67fca30d0..000000000 --- a/gfx/cairo/quartz-repeating-radial-gradients.patch +++ /dev/null @@ -1,305 +0,0 @@ -# HG changeset patch -# User Robert O'Callahan <robert@ocallahan.org> -# Date 1249558156 -43200 -# Node ID e564f3ab4ea6e3b5dd9c4e9e6042d3a84c229dde -# Parent 6ef9993a30bf2f983c9d64d7441d2e3b6b935de1 -Bug 508227. Don't fallback to Quartz for repeating radial gradients. r=jmuizelaar - -diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c ---- a/gfx/cairo/cairo/src/cairo-quartz-surface.c -+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c -@@ -708,20 +708,20 @@ CreateGradientFunction (const cairo_grad - 1, - input_value_range, - 4, - output_value_ranges, - &callbacks); - } - - static CGFunctionRef --CreateRepeatingGradientFunction (cairo_quartz_surface_t *surface, -- const cairo_gradient_pattern_t *gpat, -- CGPoint *start, CGPoint *end, -- CGAffineTransform matrix) -+CreateRepeatingLinearGradientFunction (cairo_quartz_surface_t *surface, -+ const cairo_gradient_pattern_t *gpat, -+ CGPoint *start, CGPoint *end, -+ CGAffineTransform matrix) - { - cairo_pattern_t *pat; - float input_value_range[2]; - float output_value_ranges[8] = { 0.f, 1.f, 0.f, 1.f, 0.f, 1.f, 0.f, 1.f }; - CGFunctionCallbacks callbacks = { - 0, ComputeGradientValue, (CGFunctionReleaseInfoCallback) cairo_pattern_destroy - }; - -@@ -791,16 +791,156 @@ CreateRepeatingGradientFunction (cairo_q - return CGFunctionCreate (pat, - 1, - input_value_range, - 4, - output_value_ranges, - &callbacks); - } - -+static void -+UpdateRadialParameterToIncludePoint(double *max_t, CGPoint *center, -+ double dr, double dx, double dy, -+ double x, double y) -+{ -+ /* Compute a parameter t such that a circle centered at -+ (center->x + dx*t, center->y + dy*t) with radius dr*t contains the -+ point (x,y). -+ -+ Let px = x - center->x, py = y - center->y. -+ Parameter values for which t is on the circle are given by -+ (px - dx*t)^2 + (py - dy*t)^2 = (t*dr)^2 -+ -+ Solving for t using the quadratic formula, and simplifying, we get -+ numerator = dx*px + dy*py +- -+ sqrt( dr^2*(px^2 + py^2) - (dx*py - dy*px)^2 ) -+ denominator = dx^2 + dy^2 - dr^2 -+ t = numerator/denominator -+ -+ In CreateRepeatingRadialGradientFunction we know the outer circle -+ contains the inner circle. Therefore the distance between the circle -+ centers plus the radius of the inner circle is less than the radius of -+ the outer circle. (This is checked in _cairo_quartz_setup_radial_source.) -+ Therefore -+ dx^2 + dy^2 < dr^2 -+ So the denominator is negative and the larger solution for t is given by -+ numerator = dx*px + dy*py - -+ sqrt( dr^2*(px^2 + py^2) - (dx*py - dy*px)^2 ) -+ denominator = dx^2 + dy^2 - dr^2 -+ t = numerator/denominator -+ dx^2 + dy^2 < dr^2 also ensures that the operand of sqrt is positive. -+ */ -+ double px = x - center->x; -+ double py = y - center->y; -+ double dx_py_minus_dy_px = dx*py - dy*px; -+ double numerator = dx*px + dy*py - -+ sqrt (dr*dr*(px*px + py*py) - dx_py_minus_dy_px*dx_py_minus_dy_px); -+ double denominator = dx*dx + dy*dy - dr*dr; -+ double t = numerator/denominator; -+ -+ if (*max_t < t) { -+ *max_t = t; -+ } -+} -+ -+/* This must only be called when one of the circles properly contains the other */ -+static CGFunctionRef -+CreateRepeatingRadialGradientFunction (cairo_quartz_surface_t *surface, -+ const cairo_gradient_pattern_t *gpat, -+ CGPoint *start, double *start_radius, -+ CGPoint *end, double *end_radius) -+{ -+ CGRect clip = CGContextGetClipBoundingBox (surface->cgContext); -+ CGAffineTransform transform; -+ cairo_pattern_t *pat; -+ float input_value_range[2]; -+ float output_value_ranges[8] = { 0.f, 1.f, 0.f, 1.f, 0.f, 1.f, 0.f, 1.f }; -+ CGFunctionCallbacks callbacks = { -+ 0, ComputeGradientValue, (CGFunctionReleaseInfoCallback) cairo_pattern_destroy -+ }; -+ CGPoint *inner; -+ double *inner_radius; -+ CGPoint *outer; -+ double *outer_radius; -+ /* minimum and maximum t-parameter values that will make our gradient -+ cover the clipBox */ -+ double t_min, t_max, t_temp; -+ /* outer minus inner */ -+ double dr, dx, dy; -+ -+ _cairo_quartz_cairo_matrix_to_quartz (&gpat->base.matrix, &transform); -+ /* clip is in cairo device coordinates; get it into cairo user space */ -+ clip = CGRectApplyAffineTransform (clip, transform); -+ -+ if (*start_radius < *end_radius) { -+ /* end circle contains start circle */ -+ inner = start; -+ outer = end; -+ inner_radius = start_radius; -+ outer_radius = end_radius; -+ } else { -+ /* start circle contains end circle */ -+ inner = end; -+ outer = start; -+ inner_radius = end_radius; -+ outer_radius = start_radius; -+ } -+ -+ dr = *outer_radius - *inner_radius; -+ dx = outer->x - inner->x; -+ dy = outer->y - inner->y; -+ -+ t_min = -(*inner_radius/dr); -+ inner->x += t_min*dx; -+ inner->y += t_min*dy; -+ *inner_radius = 0.; -+ -+ t_temp = 0.; -+ UpdateRadialParameterToIncludePoint(&t_temp, inner, dr, dx, dy, -+ clip.origin.x, clip.origin.y); -+ UpdateRadialParameterToIncludePoint(&t_temp, inner, dr, dx, dy, -+ clip.origin.x + clip.size.width, clip.origin.y); -+ UpdateRadialParameterToIncludePoint(&t_temp, inner, dr, dx, dy, -+ clip.origin.x + clip.size.width, clip.origin.y + clip.size.height); -+ UpdateRadialParameterToIncludePoint(&t_temp, inner, dr, dx, dy, -+ clip.origin.x, clip.origin.y + clip.size.height); -+ /* UpdateRadialParameterToIncludePoint assumes t=0 means radius 0. -+ But for the parameter values we use with Quartz, t_min means radius 0. -+ Also, add a small fudge factor to avoid rounding issues. Since the -+ circles are alway expanding and containing the earlier circles, this is -+ OK. */ -+ t_temp += 1e-6; -+ t_max = t_min + t_temp; -+ outer->x = inner->x + t_temp*dx; -+ outer->y = inner->y + t_temp*dy; -+ *outer_radius = t_temp*dr; -+ -+ /* set the input range for the function -- the function knows how to -+ map values outside of 0.0 .. 1.0 to that range for REPEAT/REFLECT. */ -+ if (*start_radius < *end_radius) { -+ input_value_range[0] = t_min; -+ input_value_range[1] = t_max; -+ } else { -+ input_value_range[0] = -t_max; -+ input_value_range[1] = -t_min; -+ } -+ -+ if (_cairo_pattern_create_copy (&pat, &gpat->base)) -+ /* quartz doesn't deal very well with malloc failing, so there's -+ * not much point in us trying either */ -+ return NULL; -+ -+ return CGFunctionCreate (pat, -+ 1, -+ input_value_range, -+ 4, -+ output_value_ranges, -+ &callbacks); -+} -+ - /* Obtain a CGImageRef from a #cairo_surface_t * */ - - static void - DataProviderReleaseCallback (void *info, const void *data, size_t size) - { - cairo_surface_t *surface = (cairo_surface_t *) info; - cairo_surface_destroy (surface); - } -@@ -1112,23 +1252,24 @@ _cairo_quartz_setup_linear_source (cairo - rgb = CGColorSpaceCreateDeviceRGB(); - - start = CGPointMake (_cairo_fixed_to_double (lpat->p1.x), - _cairo_fixed_to_double (lpat->p1.y)); - end = CGPointMake (_cairo_fixed_to_double (lpat->p2.x), - _cairo_fixed_to_double (lpat->p2.y)); - - if (abspat->extend == CAIRO_EXTEND_NONE || -- abspat->extend == CAIRO_EXTEND_PAD) -+ abspat->extend == CAIRO_EXTEND_PAD) - { - gradFunc = CreateGradientFunction (&lpat->base); - } else { -- gradFunc = CreateRepeatingGradientFunction (surface, -- &lpat->base, -- &start, &end, surface->sourceTransform); -+ gradFunc = CreateRepeatingLinearGradientFunction (surface, -+ &lpat->base, -+ &start, &end, -+ surface->sourceTransform); - } - - surface->sourceShading = CGShadingCreateAxial (rgb, - start, end, - gradFunc, - extend, extend); - - CGColorSpaceRelease(rgb); -@@ -1142,52 +1283,68 @@ _cairo_quartz_setup_radial_source (cairo - const cairo_radial_pattern_t *rpat) - { - const cairo_pattern_t *abspat = &rpat->base.base; - cairo_matrix_t mat; - CGPoint start, end; - CGFunctionRef gradFunc; - CGColorSpaceRef rgb; - bool extend = abspat->extend == CAIRO_EXTEND_PAD; -+ double c1x = _cairo_fixed_to_double (rpat->c1.x); -+ double c1y = _cairo_fixed_to_double (rpat->c1.y); -+ double c2x = _cairo_fixed_to_double (rpat->c2.x); -+ double c2y = _cairo_fixed_to_double (rpat->c2.y); -+ double r1 = _cairo_fixed_to_double (rpat->r1); -+ double r2 = _cairo_fixed_to_double (rpat->r2); -+ double dx = c1x - c2x; -+ double dy = c1y - c2y; -+ double centerDistance = sqrt (dx*dx + dy*dy); - - if (rpat->base.n_stops == 0) { - CGContextSetRGBStrokeColor (surface->cgContext, 0., 0., 0., 0.); - CGContextSetRGBFillColor (surface->cgContext, 0., 0., 0., 0.); - return DO_SOLID; - } - -- if (abspat->extend == CAIRO_EXTEND_REPEAT || -- abspat->extend == CAIRO_EXTEND_REFLECT) -- { -- /* I started trying to map these to Quartz, but it's much harder -- * then the linear case (I think it would involve doing multiple -- * Radial shadings). So, instead, let's just render an image -- * for pixman to draw the shading into, and use that. -+ if (r2 <= centerDistance + r1 + 1e-6 && /* circle 2 doesn't contain circle 1 */ -+ r1 <= centerDistance + r2 + 1e-6) { /* circle 1 doesn't contain circle 2 */ -+ /* Quartz handles cases where neither circle contains the other very -+ * differently from pixman. -+ * Whatever the correct behaviour is, let's at least have only pixman's -+ * implementation to worry about. -+ * Note that this also catches the cases where r1 == r2. - */ -- return _cairo_quartz_setup_fallback_source (surface, &rpat->base.base); -+ return _cairo_quartz_setup_fallback_source (surface, abspat); - } - - mat = abspat->matrix; - cairo_matrix_invert (&mat); - _cairo_quartz_cairo_matrix_to_quartz (&mat, &surface->sourceTransform); - - rgb = CGColorSpaceCreateDeviceRGB(); - -- start = CGPointMake (_cairo_fixed_to_double (rpat->c1.x), -- _cairo_fixed_to_double (rpat->c1.y)); -- end = CGPointMake (_cairo_fixed_to_double (rpat->c2.x), -- _cairo_fixed_to_double (rpat->c2.y)); -+ start = CGPointMake (c1x, c1y); -+ end = CGPointMake (c2x, c2y); - -- gradFunc = CreateGradientFunction (&rpat->base); -+ if (abspat->extend == CAIRO_EXTEND_NONE || -+ abspat->extend == CAIRO_EXTEND_PAD) -+ { -+ gradFunc = CreateGradientFunction (&rpat->base); -+ } else { -+ gradFunc = CreateRepeatingRadialGradientFunction (surface, -+ &rpat->base, -+ &start, &r1, -+ &end, &r2); -+ } - - surface->sourceShading = CGShadingCreateRadial (rgb, - start, -- _cairo_fixed_to_double (rpat->r1), -+ r1, - end, -- _cairo_fixed_to_double (rpat->r2), -+ r2, - gradFunc, - extend, extend); - - CGColorSpaceRelease(rgb); - CGFunctionRelease(gradFunc); - - return DO_SHADING; - } |