[ps] A flattened gradient is not linear.

We cannot express an alpha-gradient as a simple linear interpolation
between 2 flattened colors. So fallback.
This commit is contained in:
Chris Wilson 2008-09-06 09:10:25 +01:00
parent c1c86afa87
commit 85ed37da33
9 changed files with 20 additions and 28 deletions

View file

@ -1427,6 +1427,10 @@ _gradient_pattern_supported (cairo_ps_surface_t *surface,
if (surface->ps_level == CAIRO_PS_LEVEL_2)
return FALSE;
/* alpha-blended gradients cannot be expressed as a linear function */
if (! _cairo_pattern_is_opaque (pattern))
return FALSE;
surface->ps_level_used = CAIRO_PS_LEVEL_3;
extend = cairo_pattern_get_extend (pattern);
@ -2413,7 +2417,7 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
typedef struct _cairo_ps_color_stop {
double offset;
double color[4];
double color[3];
} cairo_ps_color_stop_t;
static void
@ -2438,7 +2442,7 @@ _cairo_ps_surface_emit_linear_colorgradient (cairo_ps_surface_t *surface,
static void
_cairo_ps_surface_emit_stitched_colorgradient (cairo_ps_surface_t *surface,
unsigned int n_stops,
unsigned int n_stops,
cairo_ps_color_stop_t stops[])
{
unsigned int i;
@ -2468,11 +2472,14 @@ calc_gradient_color (cairo_ps_color_stop_t *new_stop,
cairo_ps_color_stop_t *stop1,
cairo_ps_color_stop_t *stop2)
{
int i;
double offset = stop1->offset / (stop1->offset + 1.0 - stop2->offset);
double one_minus_offset = 1. - offset;
int i;
for (i = 0; i < 4; i++)
new_stop->color[i] = stop1->color[i] + offset*(stop2->color[i] - stop1->color[i]);
for (i = 0; i < 3; i++) {
new_stop->color[i] = stop1->color[i] * one_minus_offset +
stop2->color[i] * offset;
}
}
#define COLOR_STOP_EPSILON 1e-6
@ -2484,7 +2491,8 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t *surface,
cairo_ps_color_stop_t *allstops, *stops;
unsigned int i, n_stops;
allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_ps_color_stop_t));
allstops = _cairo_malloc_ab (pattern->n_stops + 2,
sizeof (cairo_ps_color_stop_t));
if (allstops == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -2497,7 +2505,6 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t *surface,
stops[i].color[0] = stop->color.red;
stops[i].color[1] = stop->color.green;
stops[i].color[2] = stop->color.blue;
stops[i].color[3] = stop->color.alpha;
stops[i].offset = pattern->stops[i].offset;
}
@ -2507,7 +2514,8 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t *surface,
if (pattern->base.extend == CAIRO_EXTEND_REFLECT)
memcpy (allstops, stops, sizeof (cairo_ps_color_stop_t));
else
calc_gradient_color (&allstops[0], &stops[0], &stops[n_stops-1]);
calc_gradient_color (&allstops[0], &stops[0],
&stops[n_stops-1]);
stops = allstops;
n_stops++;
}
@ -2519,34 +2527,20 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t *surface,
&stops[n_stops - 1],
sizeof (cairo_ps_color_stop_t));
} else {
calc_gradient_color (&stops[n_stops], &stops[0], &stops[n_stops-1]);
calc_gradient_color (&stops[n_stops], &stops[0],
&stops[n_stops-1]);
}
n_stops++;
}
stops[n_stops-1].offset = 1.0;
}
for (i = 0; i < n_stops; i++) {
double red, green, blue;
cairo_color_t color;
_cairo_color_init_rgba (&color,
stops[i].color[0],
stops[i].color[1],
stops[i].color[2],
stops[i].color[3]);
_cairo_ps_surface_flatten_transparency (surface, &color,
&red, &green, &blue);
stops[i].color[0] = red;
stops[i].color[1] = green;
stops[i].color[2] = blue;
}
_cairo_output_stream_printf (surface->stream,
"/CairoFunction\n");
if (n_stops == 2) {
/* no need for stitched function */
_cairo_ps_surface_emit_linear_colorgradient (surface, &stops[0], &stops[1]);
_cairo_ps_surface_emit_linear_colorgradient (surface,
&stops[0], &stops[1]);
} else {
/* multiple stops: stitch. XXX possible optimization: regulary spaced
* stops do not require stitching. XXX */

View file

@ -448,8 +448,6 @@ REFERENCE_IMAGES = \
glyph-cache-pressure-quartz-ref.png \
gradient-alpha-pdf-argb32-ref.png \
gradient-alpha-pdf-rgb24-ref.png \
gradient-alpha-ps-argb32-ref.png \
gradient-alpha-ps-rgb24-ref.png \
gradient-alpha-ref.png \
gradient-alpha-rgb24-ref.png \
gradient-zero-stops-ref.png \

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB