mirror of
https://git.pwmt.org/pwmt/zathura.git
synced 2024-12-28 06:36:00 +01:00
Support recolor with transparency
This commit is contained in:
parent
338986283e
commit
e586178a18
2 changed files with 61 additions and 8 deletions
|
@ -629,7 +629,7 @@ zathura_page_widget_draw(GtkWidget* widget, cairo_t* cairo)
|
||||||
if (zathura_renderer_recolor_enabled(priv->zathura->sync.render_thread) == true) {
|
if (zathura_renderer_recolor_enabled(priv->zathura->sync.render_thread) == true) {
|
||||||
GdkRGBA color;
|
GdkRGBA color;
|
||||||
zathura_renderer_get_recolor_colors(priv->zathura->sync.render_thread, &color, NULL);
|
zathura_renderer_get_recolor_colors(priv->zathura->sync.render_thread, &color, NULL);
|
||||||
cairo_set_source_rgb(cairo, color.red, color.green, color.blue);
|
cairo_set_source_rgba(cairo, color.red, color.green, color.blue, color.alpha);
|
||||||
} else {
|
} else {
|
||||||
const GdkRGBA color = priv->zathura->ui.colors.render_loading_bg;
|
const GdkRGBA color = priv->zathura->ui.colors.render_loading_bg;
|
||||||
cairo_set_source_rgb(cairo, color.red, color.green, color.blue);
|
cairo_set_source_rgb(cairo, color.red, color.green, color.blue);
|
||||||
|
|
|
@ -594,6 +594,8 @@ recolor(ZathuraRendererPrivate* priv, zathura_page_t* page, unsigned int page_wi
|
||||||
|
|
||||||
const double l1 = a[0]*rgb1.red + a[1]*rgb1.green + a[2]*rgb1.blue;
|
const double l1 = a[0]*rgb1.red + a[1]*rgb1.green + a[2]*rgb1.blue;
|
||||||
const double l2 = a[0]*rgb2.red + a[1]*rgb2.green + a[2]*rgb2.blue;
|
const double l2 = a[0]*rgb2.red + a[1]*rgb2.green + a[2]*rgb2.blue;
|
||||||
|
const double negalph1 = 1. - rgb1.alpha;
|
||||||
|
const double negalph2 = 1. - rgb2.alpha;
|
||||||
|
|
||||||
const double rgb_diff[] = {
|
const double rgb_diff[] = {
|
||||||
rgb2.red - rgb1.red,
|
rgb2.red - rgb1.red,
|
||||||
|
@ -601,6 +603,24 @@ recolor(ZathuraRendererPrivate* priv, zathura_page_t* page, unsigned int page_wi
|
||||||
rgb2.blue - rgb1.blue
|
rgb2.blue - rgb1.blue
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const double h1[3] = {
|
||||||
|
rgb1.red*rgb1.alpha - l1,
|
||||||
|
rgb1.green*rgb1.alpha - l1,
|
||||||
|
rgb1.blue*rgb1.alpha - l1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const double h2[3] = {
|
||||||
|
rgb2.red*rgb2.alpha - l2,
|
||||||
|
rgb2.green*rgb2.alpha - l2,
|
||||||
|
rgb2.blue*rgb2.alpha - l2,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Decide if we can use the older, faster formulas */
|
||||||
|
const bool fast_formula = (!priv->recolor.hue || (
|
||||||
|
fabs(rgb1.red - rgb1.blue) < DBL_EPSILON && fabs(rgb1.red - rgb1.green) < DBL_EPSILON &&
|
||||||
|
fabs(rgb2.red - rgb2.blue) < DBL_EPSILON && fabs(rgb2.red - rgb2.green) < DBL_EPSILON
|
||||||
|
)) && (rgb1.alpha >= 1. - DBL_EPSILON && rgb2.alpha >= 1. - DBL_EPSILON);
|
||||||
|
|
||||||
girara_list_t* images = NULL;
|
girara_list_t* images = NULL;
|
||||||
girara_list_t* rectangles = NULL;
|
girara_list_t* rectangles = NULL;
|
||||||
bool found_images = false;
|
bool found_images = false;
|
||||||
|
@ -645,6 +665,8 @@ recolor(ZathuraRendererPrivate* priv, zathura_page_t* page, unsigned int page_wi
|
||||||
);
|
);
|
||||||
/* If it's inside and image don't recolor */
|
/* If it's inside and image don't recolor */
|
||||||
if (inside_image == true) {
|
if (inside_image == true) {
|
||||||
|
/* It is not guaranteed that the pixel is already opaque. */
|
||||||
|
data[3] = 255;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -678,15 +700,38 @@ recolor(ZathuraRendererPrivate* priv, zathura_page_t* page, unsigned int page_wi
|
||||||
l = l * (l2 - l1) + l1;
|
l = l * (l2 - l1) + l1;
|
||||||
|
|
||||||
const double su = s * colorumax(h, l, l1, l2);
|
const double su = s * colorumax(h, l, l1, l2);
|
||||||
data[2] = (unsigned char)round(255.*(l + su * h[0]));
|
|
||||||
data[1] = (unsigned char)round(255.*(l + su * h[1]));
|
if (fast_formula) {
|
||||||
data[0] = (unsigned char)round(255.*(l + su * h[2]));
|
data[3] = 255;
|
||||||
|
data[2] = (unsigned char)round(255.*(l + su * h[0]));
|
||||||
|
data[1] = (unsigned char)round(255.*(l + su * h[1]));
|
||||||
|
data[0] = (unsigned char)round(255.*(l + su * h[2]));
|
||||||
|
} else {
|
||||||
|
/* Mix lightcolor, darkcolor and the original color, according to the
|
||||||
|
* minimal and maximal channel of the original color */
|
||||||
|
const double tr1 = (1. - fmax(fmax(rgb[0], rgb[1]), rgb[2]));
|
||||||
|
const double tr2 = fmin(fmin(rgb[0], rgb[1]), rgb[2]);
|
||||||
|
data[3] = (unsigned char)round(255.*(1. - tr1*negalph1 - tr2*negalph2));
|
||||||
|
data[2] = (unsigned char)round(255.*fmin(1, fmax(0, tr1*h1[0] + tr2*h2[0] + (l + su * h[0]))));
|
||||||
|
data[1] = (unsigned char)round(255.*fmin(1, fmax(0, tr1*h1[1] + tr2*h2[1] + (l + su * h[1]))));
|
||||||
|
data[0] = (unsigned char)round(255.*fmin(1, fmax(0, tr1*h1[2] + tr2*h2[2] + (l + su * h[2]))));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* linear interpolation between dark and light with color ligtness as
|
/* linear interpolation between dark and light with color ligtness as
|
||||||
* a parameter */
|
* a parameter */
|
||||||
data[2] = (unsigned char)round(255.*(l * rgb_diff[0] + rgb1.red));
|
if (fast_formula) {
|
||||||
data[1] = (unsigned char)round(255.*(l * rgb_diff[1] + rgb1.green));
|
data[3] = 255;
|
||||||
data[0] = (unsigned char)round(255.*(l * rgb_diff[2] + rgb1.blue));
|
data[2] = (unsigned char)round(255.*(l * rgb_diff[0] + rgb1.red));
|
||||||
|
data[1] = (unsigned char)round(255.*(l * rgb_diff[1] + rgb1.green));
|
||||||
|
data[0] = (unsigned char)round(255.*(l * rgb_diff[2] + rgb1.blue));
|
||||||
|
} else {
|
||||||
|
const double f1 = 1. - (1. - fmax(fmax(rgb[0], rgb[1]), rgb[2]))*negalph1;
|
||||||
|
const double f2 = fmin(fmin(rgb[0], rgb[1]), rgb[2])*negalph2;
|
||||||
|
data[3] = (unsigned char)round(255.*(f1 - f2));
|
||||||
|
data[2] = (unsigned char)round(255.*(l * rgb_diff[0] - f2*rgb2.red + f1*rgb1.red));
|
||||||
|
data[1] = (unsigned char)round(255.*(l * rgb_diff[1] - f2*rgb2.green + f1*rgb1.green));
|
||||||
|
data[0] = (unsigned char)round(255.*(l * rgb_diff[2] - f2*rgb2.blue + f1*rgb1.blue));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -778,8 +823,16 @@ render(render_job_t* job, ZathuraRenderRequest* request, ZathuraRenderer* render
|
||||||
page_height = height;
|
page_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
|
cairo_format_t format;
|
||||||
|
if (priv->recolor.enabled) {
|
||||||
|
format = CAIRO_FORMAT_ARGB32;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
format = CAIRO_FORMAT_RGB24;
|
||||||
|
}
|
||||||
|
cairo_surface_t* surface = cairo_image_surface_create(format,
|
||||||
page_width, page_height);
|
page_width, page_height);
|
||||||
|
|
||||||
if (surface == NULL) {
|
if (surface == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue