mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-06 09:18:11 +02:00
Use floating-point offsets for color stops
Previously we were using the cairo_fixed_t type which meant we've historically only been using 16 bits of precision for these offsets, and recently only 8 bits. Meanwhile, all manipulatons of offsets have been in floating-point anyway, so we might as well store them that way. This change also prevents a rendering regression introduced with the 24.8->16.16 change betwen snapshots 1.5.10 and 1.5.12 . This change affected gradient-rendering details for the clip-operator and operator-source tests, so the corresponding reference images are updated here.
This commit is contained in:
parent
80dc1714c8
commit
75972167a2
10 changed files with 30 additions and 35 deletions
|
|
@ -817,7 +817,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
(((int) (gradient->stops[i].color.green_short >> 8)) << 8) |
|
||||
(((int) (gradient->stops[i].color.blue_short >> 8)));
|
||||
|
||||
params[n_base_params + 3 * i + 0] = gradient->stops[i].x;
|
||||
params[n_base_params + 3 * i + 0] = _cairo_fixed_16_16_from_double (gradient->stops[i].offset);
|
||||
params[n_base_params + 3 * i + 1] = i << 16;
|
||||
params[n_base_params + 3 * i + 2] = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -821,7 +821,6 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
|
|||
double alpha)
|
||||
{
|
||||
cairo_gradient_stop_t *stops;
|
||||
cairo_fixed_t x;
|
||||
unsigned int i;
|
||||
|
||||
if (pattern->n_stops >= pattern->stops_size) {
|
||||
|
|
@ -834,10 +833,9 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
|
|||
|
||||
stops = pattern->stops;
|
||||
|
||||
x = _cairo_fixed_from_double (offset);
|
||||
for (i = 0; i < pattern->n_stops; i++)
|
||||
{
|
||||
if (x < stops[i].x)
|
||||
if (offset < stops[i].offset)
|
||||
{
|
||||
memmove (&stops[i + 1], &stops[i],
|
||||
sizeof (cairo_gradient_stop_t) * (pattern->n_stops - i));
|
||||
|
|
@ -846,7 +844,7 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
|
|||
}
|
||||
}
|
||||
|
||||
stops[i].x = x;
|
||||
stops[i].offset = offset;
|
||||
|
||||
stops[i].color.red = red;
|
||||
stops[i].color.green = green;
|
||||
|
|
@ -1208,7 +1206,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
|
|||
}
|
||||
|
||||
for (i = 0; i < pattern->n_stops; i++) {
|
||||
pixman_stops[i].x = _cairo_fixed_to_16_16 (pattern->stops[i].x);
|
||||
pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
|
||||
pixman_stops[i].color.red = pattern->stops[i].color.red_short;
|
||||
pixman_stops[i].color.green = pattern->stops[i].color.green_short;
|
||||
pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
|
||||
|
|
@ -2155,7 +2153,7 @@ cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
|
|||
return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
|
||||
|
||||
if (offset)
|
||||
*offset = _cairo_fixed_to_double(gradient->stops[index].x);
|
||||
*offset = gradient->stops[index].offset;
|
||||
if (red)
|
||||
*red = gradient->stops[index].color.red;
|
||||
if (green)
|
||||
|
|
|
|||
|
|
@ -1981,7 +1981,7 @@ _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface,
|
|||
stops[i].color[3] = pattern->stops[i].color.alpha;
|
||||
if (!CAIRO_ALPHA_IS_OPAQUE (stops[i].color[3]))
|
||||
emit_alpha = TRUE;
|
||||
stops[i].offset = _cairo_fixed_to_double (pattern->stops[i].x);
|
||||
stops[i].offset = pattern->stops[i].offset;
|
||||
}
|
||||
|
||||
if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
|
||||
|
|
@ -2220,8 +2220,8 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface,
|
|||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
|
||||
first_stop = _cairo_fixed_to_double (gradient->stops[0].x);
|
||||
last_stop = _cairo_fixed_to_double (gradient->stops[gradient->n_stops - 1].x);
|
||||
first_stop = gradient->stops[0].offset;
|
||||
last_stop = gradient->stops[gradient->n_stops - 1].offset;
|
||||
|
||||
if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
|
||||
pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
|
||||
|
|
|
|||
|
|
@ -2467,7 +2467,7 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t *surface,
|
|||
stops[i].color[1] = stop->color.green;
|
||||
stops[i].color[2] = stop->color.blue;
|
||||
stops[i].color[3] = stop->color.alpha;
|
||||
stops[i].offset = _cairo_fixed_to_double (pattern->stops[i].x);
|
||||
stops[i].offset = pattern->stops[i].offset;
|
||||
}
|
||||
|
||||
if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
|
||||
|
|
@ -2586,8 +2586,8 @@ _cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t *surface,
|
|||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
cairo_matrix_multiply (&pat_to_ps, &pat_to_ps, &surface->cairo_to_ps);
|
||||
first_stop = _cairo_fixed_to_double (gradient->stops[0].x);
|
||||
last_stop = _cairo_fixed_to_double (gradient->stops[gradient->n_stops - 1].x);
|
||||
first_stop = gradient->stops[0].offset;
|
||||
last_stop = gradient->stops[gradient->n_stops - 1].offset;
|
||||
|
||||
if (pattern->base.base.extend == CAIRO_EXTEND_REPEAT ||
|
||||
pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
|
||||
|
|
|
|||
|
|
@ -556,7 +556,7 @@ ComputeGradientValue (void *info, const float *in, float *out)
|
|||
}
|
||||
|
||||
for (i = 0; i < grad->n_stops; i++) {
|
||||
if (_cairo_fixed_to_double (grad->stops[i].x) > fdist)
|
||||
if (grad->stops[i].offset > fdist)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -568,8 +568,8 @@ ComputeGradientValue (void *info, const float *in, float *out)
|
|||
out[2] = grad->stops[i].color.blue;
|
||||
out[3] = grad->stops[i].color.alpha;
|
||||
} else {
|
||||
float ax = _cairo_fixed_to_double(grad->stops[i-1].x);
|
||||
float bx = _cairo_fixed_to_double(grad->stops[i].x) - ax;
|
||||
float ax = grad->stops[i-1].offset;
|
||||
float bx = grad->stops[i].offset - ax;
|
||||
float bp = (fdist - ax)/bx;
|
||||
float ap = 1.0 - bp;
|
||||
|
||||
|
|
|
|||
|
|
@ -1294,7 +1294,7 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
|
|||
"<stop offset=\"%f\" style=\""
|
||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
||||
"stop-opacity: %f;\"/>\n",
|
||||
_cairo_fixed_to_double (pattern->stops[0].x),
|
||||
pattern->stops[0].offset,
|
||||
pattern->stops[0].color.red * 100.0,
|
||||
pattern->stops[0].color.green * 100.0,
|
||||
pattern->stops[0].color.blue * 100.0,
|
||||
|
|
@ -1311,22 +1311,20 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
|
|||
for (i = 0; i < pattern->n_stops; i++) {
|
||||
if (reverse_stops) {
|
||||
stops[i] = pattern->stops[pattern->n_stops - i - 1];
|
||||
stops[i].x = _cairo_fixed_from_double (1.0 - _cairo_fixed_to_double (stops[i].x));
|
||||
stops[i].offset = 1.0 - stops[i].offset;
|
||||
} else
|
||||
stops[i] = pattern->stops[i];
|
||||
if (emulate_reflect) {
|
||||
stops[i].x /= 2;
|
||||
stops[i].offset /= 2;
|
||||
if (i > 0 && i < (pattern->n_stops - 1)) {
|
||||
if (reverse_stops) {
|
||||
stops[i + pattern->n_stops - 1] = pattern->stops[i];
|
||||
stops[i + pattern->n_stops - 1].x =
|
||||
_cairo_fixed_from_double (0.5 + 0.5
|
||||
* _cairo_fixed_to_double (stops[i + pattern->n_stops - 1].x));
|
||||
stops[i + pattern->n_stops - 1].offset =
|
||||
0.5 + 0.5 * stops[i + pattern->n_stops - 1].offset;
|
||||
} else {
|
||||
stops[i + pattern->n_stops - 1] = pattern->stops[pattern->n_stops - i - 1];
|
||||
stops[i + pattern->n_stops - 1].x =
|
||||
_cairo_fixed_from_double (1 - 0.5
|
||||
* _cairo_fixed_to_double (stops [i + pattern->n_stops - 1].x));
|
||||
stops[i + pattern->n_stops - 1].offset =
|
||||
1 - 0.5 * stops[i + pattern->n_stops - 1].offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1338,8 +1336,7 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
|
|||
|
||||
if (start_offset >= 0.0)
|
||||
for (i = 0; i < n_stops; i++) {
|
||||
offset = start_offset + (1 - start_offset ) *
|
||||
_cairo_fixed_to_double (stops[i].x);
|
||||
offset = start_offset + (1 - start_offset ) * stops[i].offset;
|
||||
_cairo_output_stream_printf (output,
|
||||
"<stop offset=\"%f\" style=\""
|
||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
||||
|
|
@ -1356,14 +1353,14 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
|
|||
cairo_color_t offset_color_start, offset_color_stop;
|
||||
|
||||
for (i = 0; i < n_stops; i++) {
|
||||
if (_cairo_fixed_to_double (stops[i].x) >= -start_offset) {
|
||||
if (stops[i].offset >= -start_offset) {
|
||||
if (i > 0) {
|
||||
if (stops[i].x != stops[i-1].x) {
|
||||
if (stops[i].offset != stops[i-1].offset) {
|
||||
double x0, x1;
|
||||
cairo_color_t *color0, *color1;
|
||||
|
||||
x0 = _cairo_fixed_to_double (stops[i-1].x);
|
||||
x1 = _cairo_fixed_to_double (stops[i].x);
|
||||
x0 = stops[i-1].offset;
|
||||
x1 = stops[i].offset;
|
||||
color0 = &stops[i-1].color;
|
||||
color1 = &stops[i].color;
|
||||
offset_color_start.red = color0->red + (color1->red - color0->red)
|
||||
|
|
@ -1405,7 +1402,7 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
|
|||
"<stop offset=\"%f\" style=\""
|
||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
||||
"stop-opacity: %f;\"/>\n",
|
||||
_cairo_fixed_to_double (stops[i].x) + start_offset,
|
||||
stops[i].offset + start_offset,
|
||||
stops[i].color.red * 100.0,
|
||||
stops[i].color.green * 100.0,
|
||||
stops[i].color.blue * 100.0,
|
||||
|
|
@ -1416,7 +1413,7 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
|
|||
"<stop offset=\"%f\" style=\""
|
||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
||||
"stop-opacity: %f;\"/>\n",
|
||||
1.0 + _cairo_fixed_to_double (stops[i].x) + start_offset,
|
||||
1.0 + stops[i].offset + start_offset,
|
||||
stops[i].color.red * 100.0,
|
||||
stops[i].color.green * 100.0,
|
||||
stops[i].color.blue * 100.0,
|
||||
|
|
|
|||
|
|
@ -757,7 +757,7 @@ _cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_surface_t *surfa
|
|||
}
|
||||
|
||||
stop = i%num_rects + 1;
|
||||
vert[i*2+1].x = (LONG)(d*(range_start + i/num_rects + _cairo_fixed_to_double (pattern->base.stops[stop].x)));
|
||||
vert[i*2+1].x = (LONG)(d*(range_start + i/num_rects + pattern->base.stops[stop].offset));
|
||||
vert[i*2+1].y = (LONG) clip.bottom;
|
||||
if (extend == CAIRO_EXTEND_REFLECT && (range_start+(i/num_rects))%2)
|
||||
stop = num_rects - stop;
|
||||
|
|
|
|||
|
|
@ -790,7 +790,7 @@ typedef struct _cairo_surface_pattern {
|
|||
} cairo_surface_pattern_t;
|
||||
|
||||
typedef struct _cairo_gradient_stop {
|
||||
cairo_fixed_t x;
|
||||
double offset;
|
||||
cairo_color_t color;
|
||||
} cairo_gradient_stop_t;
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Loading…
Add table
Reference in a new issue