[cairo] FW: [patch] gl: use original data to compute gradient uniforms
Henry (Yu) Song - SISA
hsong at sisa.samsung.com
Thu Feb 14 11:18:50 PST 2013
re-post patch
________________________________________
From: Henry (Yu) Song - SISA
Sent: Wednesday, February 06, 2013 10:14 AM
To: cairo at cairographics.org
Subject: [patch] gl: use original data to compute gradient uniforms
>From 29e62f9edce2ee5a19f878b46e26e385c4b0e467 Mon Sep 17 00:00:00 2001
From: Henry Song <henry.song at samsung.com>
Date: Wed, 2 Jan 2013 17:57:34 +0100
Subject: [PATCH] gl: Scale radial gradient parameters down may introduce
rounding error.
gl: Use original data to compute gradient uniforms.
Instead of using scaled parametes to generate uniform values, we
compute them from origin radial gradient pattern. Scaled
data may introduce rounding error. For example,
operand->gradient.a may not be exactly 0 when using scaled
data. This causes operand type to use
CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT/NONE instead of
CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0, which produces different image.
---
src/cairo-gl-operand.c | 33 ++++++++++++++++++++++++++-------
1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index 502737a..1ef2cd5 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -682,6 +682,8 @@ _cairo_gl_gradient_operand_init (cairo_gl_operand_t *operand,
cairo_matrix_t m;
cairo_circle_double_t circles[2];
double x0, y0, r0, dx, dy, dr;
+ double scale = 1.0;
+ cairo_radial_pattern_t *radial_pattern = (cairo_radial_pattern_t *)gradient;
/*
* Some fragment shader implementations use half-floats to
@@ -695,18 +697,35 @@ _cairo_gl_gradient_operand_init (cairo_gl_operand_t *operand,
_cairo_gradient_pattern_fit_to_range (gradient, 8.,
&operand->gradient.m, circles);
+ /*
+ * Instead of using scaled data that might introducing rounding
+ * errors, we use original data directly
+ */
+ if (circles[0].center.x)
+ scale = radial_pattern->cd1.center.x / circles[0].center.x;
+ else if (circles[0].center.y)
+ scale = radial_pattern->cd1.center.y / circles[0].center.y;
+ else if (circles[0].radius)
+ scale = radial_pattern->cd1.radius / circles[0].radius;
+ else if (circles[1].center.x)
+ scale = radial_pattern->cd2.center.x / circles[1].center.x;
+ else if (circles[1].center.y)
+ scale = radial_pattern->cd2.center.y / circles[1].center.y;
+ else if (circles[1].radius)
+ scale = radial_pattern->cd2.radius / circles[1].radius;
+
x0 = circles[0].center.x;
y0 = circles[0].center.y;
r0 = circles[0].radius;
- dx = circles[1].center.x - x0;
- dy = circles[1].center.y - y0;
- dr = circles[1].radius - r0;
+ dx = radial_pattern->cd2.center.x - radial_pattern->cd1.center.x;
+ dy = radial_pattern->cd2.center.y - radial_pattern->cd1.center.y;
+ dr = radial_pattern->cd2.radius - radial_pattern->cd1.radius;
- operand->gradient.a = dx * dx + dy * dy - dr * dr;
+ operand->gradient.a = (dx * dx + dy * dy - dr * dr)/(scale * scale);
operand->gradient.radius_0 = r0;
- operand->gradient.circle_d.center.x = dx;
- operand->gradient.circle_d.center.y = dy;
- operand->gradient.circle_d.radius = dr;
+ operand->gradient.circle_d.center.x = dx / scale;
+ operand->gradient.circle_d.center.y = dy / scale;
+ operand->gradient.circle_d.radius = dr / scale;
if (operand->gradient.a == 0)
operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0;
--
1.7.9.5
More information about the cairo
mailing list