Skip to content

Instantly share code, notes, and snippets.

@miseran
Last active August 12, 2022 14:34
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miseran/0ea4b95e9816bf915b7b7171a5a0e42d to your computer and use it in GitHub Desktop.
Save miseran/0ea4b95e9816bf915b7b7171a5a0e42d to your computer and use it in GitHub Desktop.
Transparency patch for zathura
diff --git a/girara/session.c b/girara/session.c
index 927e9b5..040ac5c 100644
--- a/girara/session.c
+++ b/girara/session.c
@@ -378,6 +378,16 @@ girara_session_create(void)
return session;
}
+static void
+screen_changed(GtkWidget* widget, GdkScreen* GIRARA_UNUSED(old_screen), gpointer GIRARA_UNUSED(userdata)) {
+ GdkScreen *screen = gtk_widget_get_screen(widget);
+ GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
+ if (!visual) {
+ visual = gdk_screen_get_system_visual(screen);
+ }
+ gtk_widget_set_visual(widget, visual);
+}
+
bool
girara_session_init(girara_session_t* session, const char* sessionname)
{
@@ -410,6 +420,9 @@ girara_session_init(girara_session_t* session, const char* sessionname)
gtk_widget_set_name(session->gtk.window, session->private_data->session_name);
+ g_signal_connect(G_OBJECT(session->gtk.window), "screen-changed", G_CALLBACK(screen_changed), NULL);
+ screen_changed(GTK_WIDGET(session->gtk.window), NULL, NULL);
+
/* apply CSS style */
css_template_changed(session->private_data->csstemplate, session);
# Maintainer: none
_pkgname=girara
pkgname=girara-git-alpha
pkgver=0.3.4.r1.g051de04
pkgrel=1
pkgdesc="user interface library"
arch=('i686' 'x86_64')
url="http://pwmt.org/projects/girara"
license=('custom')
depends=('gtk3>=3.2' 'glib2>=2.28' 'intltool')
makedepends=('git' 'meson')
conflicts=('girara')
provides=('girara')
source=("${_pkgname}::git+https://git.pwmt.org/pwmt/girara.git#branch=develop" 'girara-alpha.patch')
md5sums=('SKIP' 'SKIP')
prepare() {
mkdir -p build
cd "$srcdir/girara"
patch -Np1 -i "$srcdir/girara-alpha.patch"
}
build() {
cd build
meson --prefix=/usr --buildtype=release $srcdir/$_pkgname
ninja
}
package() {
cd build
DESTDIR="$pkgdir/" ninja install
}
pkgver() {
cd "$_pkgname"
git describe --long | sed -r 's/([^-]*-g)/r\1/;s/-/./g'
}
# vim:set ts=2 sw=2 et:
# Maintainer: none
pkgname=zathura-git-alpha
pkgver=0.4.5.4.g99a4983
pkgrel=1
pkgdesc="a document viewer"
arch=('i686' 'x86_64')
url="http://pwmt.org/projects/zathura"
license=('custom')
depends=('girara-git-alpha' 'gtk3>=3.10' 'cairo>=1.8.8')
makedepends=('git' 'python-sphinx' 'intltool' 'meson')
conflicts=('zathura')
provides=('zathura')
source=('zathura::git+https://git.pwmt.org/pwmt/zathura.git#branch=develop' 'zathura-alpha.patch')
md5sums=('SKIP' 'SKIP')
_gitname=zathura
optdepends=(
'zathura-pdf-poppler-git: PDF support by using poppler'
'zathura-pdf-mupdf-git: PDF support by using mupdf'
'zathura-djvu-git: djvu support by using djvulibre'
'zathura-ps-git: PostSctipt support by using libspectre'
)
prepare() {
mkdir -p build
cd "$srcdir/zathura"
patch -Np1 -i "$srcdir/zathura-alpha.patch"
}
build() {
cd build
meson --prefix=/usr --buildtype=release $srcdir/$_gitname
ninja
}
package() {
cd build
DESTDIR="$pkgdir/" ninja install
}
pkgver() {
cd "$_gitname"
local ver="$(git describe --long)"
printf "%s" "${ver//-/.}"
}
# vim:set ts=2 sw=2 et:
diff --git a/zathura/page-widget.c b/zathura/page-widget.c
index 1132920..373afeb 100644
--- a/zathura/page-widget.c
+++ b/zathura/page-widget.c
@@ -629,7 +629,7 @@ zathura_page_widget_draw(GtkWidget* widget, cairo_t* cairo)
if (zathura_renderer_recolor_enabled(priv->zathura->sync.render_thread) == true) {
GdkRGBA color;
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 {
const GdkRGBA color = priv->zathura->ui.colors.render_loading_bg;
cairo_set_source_rgb(cairo, color.red, color.green, color.blue);
diff --git a/zathura/render.c b/zathura/render.c
index 9d67c63..b5a1041 100644
--- a/zathura/render.c
+++ b/zathura/render.c
@@ -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 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[] = {
rgb2.red - rgb1.red,
@@ -601,6 +603,24 @@ recolor(ZathuraRendererPrivate* priv, zathura_page_t* page, unsigned int page_wi
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* rectangles = NULL;
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 (inside_image == true) {
+ /* It is not guaranteed that the pixel is already opaque. */
+ data[3] = 255;
continue;
}
}
@@ -678,15 +700,38 @@ recolor(ZathuraRendererPrivate* priv, zathura_page_t* page, unsigned int page_wi
l = l * (l2 - l1) + l1;
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]));
- data[0] = (unsigned char)round(255.*(l + su * h[2]));
+
+ if (fast_formula) {
+ 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 {
/* linear interpolation between dark and light with color ligtness as
* a parameter */
- 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));
+ if (fast_formula) {
+ data[3] = 255;
+ 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;
}
- 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);
+
if (surface == NULL) {
return false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment