Pre-multiply gradients after color interpolation

This commit is contained in:
David Reveman 2004-06-11 06:20:17 +00:00
parent f82f1ba380
commit 06ef87276e
6 changed files with 71 additions and 39 deletions

View file

@ -1,3 +1,14 @@
2004-06-11 David Reveman <c99drn@cs.umu.se>
* src/cairo_gstate.c (_cairo_gstate_create_pattern): Get solid color
from color stop components.
* src/cairoint.h: Removed cairo color from color stop.
* src/cairo_pattern.c: Added MULTIPLY_COLORCOMP macro.
(cairo_pattern_add_color_stop): Do not pre-multiply stop color.
(_cairo_pattern_calc_color_at_pixel): Multiply with alpha.
2004-05-28 Keith Packard <keithp@keithp.com>
* configure.in:

View file

@ -1264,8 +1264,16 @@ _cairo_gstate_create_pattern (cairo_gstate_t *gstate,
if (pattern->n_stops < 2) {
pattern->type = CAIRO_PATTERN_SOLID;
if (pattern->n_stops)
pattern->color = pattern->stops->color;
if (pattern->n_stops) {
cairo_color_stop_t *stop = pattern->stops;
_cairo_color_set_rgb (&pattern->color,
(double) stop->color_char[0] / 0xff,
(double) stop->color_char[1] / 0xff,
(double) stop->color_char[2] / 0xff);
_cairo_color_set_alpha (&pattern->color,
(double) stop->color_char[3] / 0xff);
}
}
}

View file

@ -27,6 +27,10 @@
#include "cairoint.h"
#define MULTIPLY_COLORCOMP(c1, c2) \
((unsigned char) \
((((unsigned char) (c1)) * (int) ((unsigned char) (c2))) / 0xff))
void
_cairo_pattern_init (cairo_pattern_t *pattern)
{
@ -247,13 +251,11 @@ cairo_pattern_add_color_stop (cairo_pattern_t *pattern,
stop->offset = _cairo_fixed_from_double (offset);
stop->id = pattern->n_stops;
_cairo_color_init (&stop->color);
_cairo_color_set_rgb (&stop->color, red, green, blue);
_cairo_color_set_alpha (&stop->color, alpha);
stop->color_char[0] = stop->color.red_short / 256;
stop->color_char[1] = stop->color.green_short / 256;
stop->color_char[2] = stop->color.blue_short / 256;
stop->color_char[3] = stop->color.alpha_short / 256;
stop->color_char[0] = red * 0xff;
stop->color_char[1] = green * 0xff;
stop->color_char[2] = blue * 0xff;
stop->color_char[3] = alpha * 0xff;
/* sort stops in ascending order */
qsort (pattern->stops, pattern->n_stops, sizeof (cairo_color_stop_t),
@ -329,16 +331,9 @@ _cairo_pattern_set_alpha (cairo_pattern_t *pattern, double alpha)
_cairo_color_set_alpha (&pattern->color, alpha);
for (i = 0; i < pattern->n_stops; i++) {
cairo_color_stop_t *stop = &pattern->stops[i];
_cairo_color_set_alpha (&stop->color, stop->color.alpha * alpha);
stop->color_char[0] = stop->color.red_short / 256;
stop->color_char[1] = stop->color.green_short / 256;
stop->color_char[2] = stop->color.blue_short / 256;
stop->color_char[3] = stop->color.alpha_short / 256;
}
for (i = 0; i < pattern->n_stops; i++)
pattern->stops[i].color_char[3] =
MULTIPLY_COLORCOMP (pattern->stops[i].color_char[3], alpha * 0xff);
}
void
@ -510,6 +505,14 @@ _cairo_pattern_calc_color_at_pixel (cairo_shader_op_t *op,
op->shader_function (op->stops[i].color_char,
op->stops[i + 1].color_char,
factor, pixel);
/* multiply alpha */
if (((unsigned char) (*pixel >> 24)) != 0xff) {
*pixel = (*pixel & 0xff000000) |
(MULTIPLY_COLORCOMP (*pixel >> 16, *pixel >> 24) << 16) |
(MULTIPLY_COLORCOMP (*pixel >> 8, *pixel >> 24) << 8) |
(MULTIPLY_COLORCOMP (*pixel >> 0, *pixel >> 24) << 0);
}
break;
}
}

View file

@ -1264,8 +1264,16 @@ _cairo_gstate_create_pattern (cairo_gstate_t *gstate,
if (pattern->n_stops < 2) {
pattern->type = CAIRO_PATTERN_SOLID;
if (pattern->n_stops)
pattern->color = pattern->stops->color;
if (pattern->n_stops) {
cairo_color_stop_t *stop = pattern->stops;
_cairo_color_set_rgb (&pattern->color,
(double) stop->color_char[0] / 0xff,
(double) stop->color_char[1] / 0xff,
(double) stop->color_char[2] / 0xff);
_cairo_color_set_alpha (&pattern->color,
(double) stop->color_char[3] / 0xff);
}
}
}

View file

@ -27,6 +27,10 @@
#include "cairoint.h"
#define MULTIPLY_COLORCOMP(c1, c2) \
((unsigned char) \
((((unsigned char) (c1)) * (int) ((unsigned char) (c2))) / 0xff))
void
_cairo_pattern_init (cairo_pattern_t *pattern)
{
@ -247,13 +251,11 @@ cairo_pattern_add_color_stop (cairo_pattern_t *pattern,
stop->offset = _cairo_fixed_from_double (offset);
stop->id = pattern->n_stops;
_cairo_color_init (&stop->color);
_cairo_color_set_rgb (&stop->color, red, green, blue);
_cairo_color_set_alpha (&stop->color, alpha);
stop->color_char[0] = stop->color.red_short / 256;
stop->color_char[1] = stop->color.green_short / 256;
stop->color_char[2] = stop->color.blue_short / 256;
stop->color_char[3] = stop->color.alpha_short / 256;
stop->color_char[0] = red * 0xff;
stop->color_char[1] = green * 0xff;
stop->color_char[2] = blue * 0xff;
stop->color_char[3] = alpha * 0xff;
/* sort stops in ascending order */
qsort (pattern->stops, pattern->n_stops, sizeof (cairo_color_stop_t),
@ -329,16 +331,9 @@ _cairo_pattern_set_alpha (cairo_pattern_t *pattern, double alpha)
_cairo_color_set_alpha (&pattern->color, alpha);
for (i = 0; i < pattern->n_stops; i++) {
cairo_color_stop_t *stop = &pattern->stops[i];
_cairo_color_set_alpha (&stop->color, stop->color.alpha * alpha);
stop->color_char[0] = stop->color.red_short / 256;
stop->color_char[1] = stop->color.green_short / 256;
stop->color_char[2] = stop->color.blue_short / 256;
stop->color_char[3] = stop->color.alpha_short / 256;
}
for (i = 0; i < pattern->n_stops; i++)
pattern->stops[i].color_char[3] =
MULTIPLY_COLORCOMP (pattern->stops[i].color_char[3], alpha * 0xff);
}
void
@ -510,6 +505,14 @@ _cairo_pattern_calc_color_at_pixel (cairo_shader_op_t *op,
op->shader_function (op->stops[i].color_char,
op->stops[i + 1].color_char,
factor, pixel);
/* multiply alpha */
if (((unsigned char) (*pixel >> 24)) != 0xff) {
*pixel = (*pixel & 0xff000000) |
(MULTIPLY_COLORCOMP (*pixel >> 16, *pixel >> 24) << 16) |
(MULTIPLY_COLORCOMP (*pixel >> 8, *pixel >> 24) << 8) |
(MULTIPLY_COLORCOMP (*pixel >> 0, *pixel >> 24) << 0);
}
break;
}
}

View file

@ -472,7 +472,6 @@ typedef struct cairo_color_stop {
cairo_fixed_t offset;
cairo_fixed_48_16_t scale;
int id;
cairo_color_t color;
unsigned char color_char[4];
} cairo_color_stop_t;