* Face transparency attribute @ 2024-01-18 1:35 Sebastian Wålinder 2024-01-18 7:14 ` Po Lu 0 siblings, 1 reply; 6+ messages in thread From: Sebastian Wålinder @ 2024-01-18 1:35 UTC (permalink / raw) To: emacs-devel Hello! Frames in Emacs recently got the option to set a transparency that makes all background colors in the frame transparent to the degree you set. Is there any way to set the transparency on a particular face? I didn't find any way when looking through the documentation. If not, are there any workarounds and would face local transparency be hard to implement? I'd like to experiment with transparency, making the fringes for instance more transparent, as it's not a content area. Thanks for any help! Sebastian ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Face transparency attribute 2024-01-18 1:35 Face transparency attribute Sebastian Wålinder @ 2024-01-18 7:14 ` Po Lu 2024-03-17 23:02 ` Nate Sandy 0 siblings, 1 reply; 6+ messages in thread From: Po Lu @ 2024-01-18 7:14 UTC (permalink / raw) To: Sebastian Wålinder; +Cc: emacs-devel Sebastian Wålinder <s.walinder@gmail.com> writes: > Frames in Emacs recently got the option to set a transparency that > makes all background colors in the frame transparent to the degree you > set. > > Is there any way to set the transparency on a particular face? I > didn't find any way when looking through the documentation. There are as yet no provisions for configuring individual faces to display at their own transparency levels. > If not, are there any workarounds and would face local transparency be > hard to implement? It would not be prohibitively difficult, although most of our code assumes that face colors are always opaque, which suggests two approaches to implementing per-face transparency values: either to extend face colors with an extra alpha channel, or to extend faces with a new attribute specifying a transparency value. The first would pose difficulties in the way of adapting the window-system code charged with manipulating colors without regard to the existence of an alpha channel, whereas the second would open a semantic can of worms, raising questions such as how the new face attribute should be disposed as two faces are merged. Right now, most such window-system code is jerry-rigged to introduce the alpha channel at the stage where glyph backgrounds are drawn, and before the few routines so affected colors are treated much as they have always been. Neither approach is easy or exceptionally challenging, so interested individuals are invited to chose whichever they should find more to their liking. > I'd like to experiment with transparency, making the fringes for > instance more transparent, as it's not a content area. The relevant code is in xterm.c and pgtkterm.c (*_draw_fringe_bitmap), and godspeed. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Face transparency attribute 2024-01-18 7:14 ` Po Lu @ 2024-03-17 23:02 ` Nate Sandy 2024-03-18 7:41 ` Protesilaos Stavrou 2024-03-18 13:50 ` Po Lu 0 siblings, 2 replies; 6+ messages in thread From: Nate Sandy @ 2024-03-17 23:02 UTC (permalink / raw) To: Po Lu, Sebastian Wålinder; +Cc: emacs-devel [-- Attachment #1: Type: text/plain, Size: 1471 bytes --] Po Lu <luangruo@yahoo.com> writes: > Neither approach is easy or exceptionally challenging, so interested > individuals are invited to chose whichever they should find more to > their liking. Hi Po, I have written a patch for this for the pgtk backend and went with the first route - supporting an alpha channel in face colors. I figured it's nicer since we get alpha channels for all other text decorations as well. The way it works is that when painting a background color (one which respects alpha-background), we instead compose it with the frame background color via a re-implementation of CAIRO_OPERATOR_OVER. I didn't find a way to do this with cairo itself without painting the surface inbetween. I also made sure that this patch integrates with alpha-background, which is also my primary use case - fully hiding faces which don't respect alpha-background. The only syntax supported for transparency is gtk_parse_rgba's `rgba(255,255,255,1.0)`. Maybe we would want support for `#ff00ff00` too? One interesting quirk is that when changing the opacity of the `default` face to less than 1, the whole background is fully transparent again. I am not sure whether this is a fault in my code or because of some extra logic regarding the `default` face. Attached are a screenshot and the patch. I'd very much appreciate feedback. If necessary I could also try to implement this for X and/or terminals, however I don't have access to other platforms. Best Nate [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: Add-rgba-support-for-faces-to-pgtk --] [-- Type: text/x-patch, Size: 5071 bytes --] From 63062b45d47f5054fc713f37daf3c0b88a7d5edf Mon Sep 17 00:00:00 2001 From: Nate Sandy <nsan@posteo.de> Date: Sun, 17 Mar 2024 23:10:53 +0100 Subject: [PATCH] Add rgba support for faces to pgtk --- src/dispextern.h | 2 +- src/pgtkterm.c | 56 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/dispextern.h b/src/dispextern.h index 5387cb4560..1a6fbb2d95 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -50,7 +50,7 @@ #define No_Cursor (None) typedef struct { unsigned long pixel; - unsigned short red, green, blue; + unsigned short red, green, blue, alpha; } Emacs_Color; #ifndef HAVE_ANDROID diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 1ec6bfcda4..b8284ba295 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -1677,6 +1677,7 @@ pgtk_compute_lighter_color (struct frame *f, unsigned long *pixel, new.red = min (0xffff, factor * color.red); new.green = min (0xffff, factor * color.green); new.blue = min (0xffff, factor * color.blue); + new.alpha = color.alpha; /* Calculate brightness of COLOR. */ bright = (2 * color.red + 3 * color.green + color.blue) / 6; @@ -1706,7 +1707,8 @@ pgtk_compute_lighter_color (struct frame *f, unsigned long *pixel, } } - new.pixel = (new.red >> 8 << 16 + new.pixel = (new.alpha >> 8 << 24 + | new.red >> 8 << 16 | new.green >> 8 << 8 | new.blue >> 8); @@ -1717,7 +1719,8 @@ pgtk_compute_lighter_color (struct frame *f, unsigned long *pixel, new.red = min (0xffff, delta + color.red); new.green = min (0xffff, delta + color.green); new.blue = min (0xffff, delta + color.blue); - new.pixel = (new.red >> 8 << 16 + new.pixel = (new.alpha >> 8 << 24 + | new.red >> 8 << 16 | new.green >> 8 << 8 | new.blue >> 8); } @@ -7046,7 +7049,9 @@ pgtk_parse_color (struct frame *f, const char *color_name, color->red = rgba.red * 65535; color->green = rgba.green * 65535; color->blue = rgba.blue * 65535; - color->pixel = ((color->red >> 8) << 16 + color->alpha = rgba.alpha * 65535; + color->pixel = ((color->alpha >> 8) << 24 + | (color->red >> 8) << 16 | (color->green >> 8) << 8 | (color->blue >> 8) << 0); return 1; @@ -7066,9 +7071,11 @@ pgtk_query_colors (struct frame *f, Emacs_Color * colors, int ncolors) { unsigned long pixel = colors[i].pixel; /* Convert to a 16 bit value in range 0 - 0xffff. */ +#define GetAValue(p) (((p) >> 24) & 0xff) #define GetRValue(p) (((p) >> 16) & 0xff) #define GetGValue(p) (((p) >> 8) & 0xff) #define GetBValue(p) (((p) >> 0) & 0xff) + colors[i].alpha = GetAValue (pixel) * 257; colors[i].red = GetRValue (pixel) * 257; colors[i].green = GetGValue (pixel) * 257; colors[i].blue = GetBValue (pixel) * 257; @@ -7255,6 +7262,18 @@ pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC *gc, respects_alpha_background); } +void +pgtk_cr_operator_over (Emacs_Color a, Emacs_Color b, Emacs_Color *result) { + double a_alpha_norm = a.alpha / 65535.0; + double b_alpha_norm = b.alpha / 65535.0; + + result->alpha = a_alpha_norm + b_alpha_norm * (1.0 - a_alpha_norm); + result->red = (a.red * a_alpha_norm + b.red * b_alpha_norm * (1.0 - a_alpha_norm)) / result->alpha; + result->green = (a.green * a_alpha_norm + b.green * b_alpha_norm * (1.0 - a_alpha_norm)) / result->alpha; + result->blue = (a.blue * a_alpha_norm + b.blue * b_alpha_norm * (1.0 - a_alpha_norm)) / result->alpha; + +} + void pgtk_set_cr_source_with_color (struct frame *f, unsigned long color, bool respects_alpha_background) @@ -7263,19 +7282,24 @@ pgtk_set_cr_source_with_color (struct frame *f, unsigned long color, col.pixel = color; pgtk_query_color (f, &col); - if (!respects_alpha_background) - { - cairo_set_source_rgb (FRAME_CR_CONTEXT (f), col.red / 65535.0, - col.green / 65535.0, col.blue / 65535.0); - cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_OVER); - } - else - { - cairo_set_source_rgba (FRAME_CR_CONTEXT (f), col.red / 65535.0, - col.green / 65535.0, col.blue / 65535.0, - f->alpha_background); - cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE); - } + if (respects_alpha_background) { + Emacs_Color frame_background; + pgtk_query_frame_background_color (f, &frame_background); + + Emacs_Color result; + pgtk_cr_operator_over (col, frame_background, &result); + + cairo_set_source_rgba (FRAME_CR_CONTEXT (f), result.red / 65535.0, + result.green / 65535.0, result.blue / 65535.0, + f->alpha_background * result.alpha); + cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE); + } else { + cairo_set_source_rgba (FRAME_CR_CONTEXT (f), col.red / 65535.0, + col.green / 65535.0, col.blue / 65535.0, + col.alpha / 65535.0); + cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_OVER); + } + } void -- 2.43.1 [-- Attachment #3: Emacs pgtk with face rgba support --] [-- Type: image/png, Size: 139959 bytes --] ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: Face transparency attribute 2024-03-17 23:02 ` Nate Sandy @ 2024-03-18 7:41 ` Protesilaos Stavrou 2024-03-18 13:50 ` Po Lu 1 sibling, 0 replies; 6+ messages in thread From: Protesilaos Stavrou @ 2024-03-18 7:41 UTC (permalink / raw) To: Nate Sandy, Po Lu, Sebastian Wålinder; +Cc: emacs-devel > From: Nate Sandy <nsan@posteo.de> > Date: Sun, 17 Mar 2024 23:02:20 +0000 > [... 24 lines elided] > The only syntax supported for transparency is gtk_parse_rgba's > `rgba(255,255,255,1.0)`. Maybe we would want support for `#ff00ff00` too? Please cover this case as well. It makes it easier to tweak existing hex values to have a transparency value than to convert them to the rgba notation. -- Protesilaos Stavrou https://protesilaos.com ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Face transparency attribute 2024-03-17 23:02 ` Nate Sandy 2024-03-18 7:41 ` Protesilaos Stavrou @ 2024-03-18 13:50 ` Po Lu 2024-05-03 7:01 ` Filippo Argiolas 1 sibling, 1 reply; 6+ messages in thread From: Po Lu @ 2024-03-18 13:50 UTC (permalink / raw) To: Nate Sandy; +Cc: Sebastian Wålinder, emacs-devel Nate Sandy <nsan@posteo.de> writes: > Po Lu <luangruo@yahoo.com> writes: > >> Neither approach is easy or exceptionally challenging, so interested >> individuals are invited to chose whichever they should find more to >> their liking. > > Hi Po, > > I have written a patch for this for the pgtk backend and went with the > first route - supporting an alpha channel in face colors. I figured it's > nicer since we get alpha channels for all other text decorations as > well. > > The way it works is that when painting a background color (one which > respects alpha-background), we instead compose it with the frame > background color via a re-implementation of CAIRO_OPERATOR_OVER. I > didn't find a way to do this with cairo itself without painting the > surface inbetween. > > I also made sure that this patch integrates with alpha-background, which > is also my primary use case - fully hiding faces which don't respect > alpha-background. > > The only syntax supported for transparency is gtk_parse_rgba's > `rgba(255,255,255,1.0)`. Maybe we would want support for `#ff00ff00` too? > > One interesting quirk is that when changing the opacity of the `default` > face to less than 1, the whole background is fully transparent again. I > am not sure whether this is a fault in my code or because of some extra > logic regarding the `default` face. > > Attached are a screenshot and the patch. I'd very much appreciate > feedback. If necessary I could also try to implement this for X and/or > terminals, however I don't have access to other platforms. I'm not happy with this approach, since it defines the alpha value as an integral component of a face's foreground and background colors, rather than an attribute (or attributes) the face merging process can manage independently to prevent alpha values from being transferred between faces against the user's wishes, and more broadly to enable specifying alpha values separately from face colors, which there is plenty of reason for users to replace that might not apply to transparency in identical circumstances. Furthermore, the transparency implemented in this patch is specified with premultiplied values--premultiplied alpha is more efficient on free systems, but admits of invalid color values whose behavior is undefined across all the systems and toolkits we support. It's already too easy for Emacs users to shoot themselves in the foot, and muddling the waters with the potential for invalid color definitions would be a step in the wrong direction, in my humble estimation, so I would prefer an implementation that exposes straight alpha values to users, converting between those and the suitable alpha format for the toolkit at display time. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Face transparency attribute 2024-03-18 13:50 ` Po Lu @ 2024-05-03 7:01 ` Filippo Argiolas 0 siblings, 0 replies; 6+ messages in thread From: Filippo Argiolas @ 2024-05-03 7:01 UTC (permalink / raw) To: Po Lu; +Cc: Nate Sandy, Sebastian Wålinder, emacs-devel A bit late but I agree that we should have a separate attribute for this. My use case would be to shade inactive code regions like I do in [1]. Right now I'm using a super hacky method that hooks into fontification and adds an overlay for each symbol in the buffer with a shaded foreground color. With Nate's patch I would still have the very same problem. With an attribute I could just set a single overlay over the whole inactive region and not mess with fontification. Is anyone still working on this? Nate? Cheers, Filippo 1. https://github.com/fargiolas/clangd-inactive-regions.el On Mon, Mar 18, 2024 at 2:51 PM Po Lu <luangruo@yahoo.com> wrote: > > Nate Sandy <nsan@posteo.de> writes: > > > Po Lu <luangruo@yahoo.com> writes: > > > >> Neither approach is easy or exceptionally challenging, so interested > >> individuals are invited to chose whichever they should find more to > >> their liking. > > > > Hi Po, > > > > I have written a patch for this for the pgtk backend and went with the > > first route - supporting an alpha channel in face colors. I figured it's > > nicer since we get alpha channels for all other text decorations as > > well. > > > > The way it works is that when painting a background color (one which > > respects alpha-background), we instead compose it with the frame > > background color via a re-implementation of CAIRO_OPERATOR_OVER. I > > didn't find a way to do this with cairo itself without painting the > > surface inbetween. > > > > I also made sure that this patch integrates with alpha-background, which > > is also my primary use case - fully hiding faces which don't respect > > alpha-background. > > > > The only syntax supported for transparency is gtk_parse_rgba's > > `rgba(255,255,255,1.0)`. Maybe we would want support for `#ff00ff00` too? > > > > One interesting quirk is that when changing the opacity of the `default` > > face to less than 1, the whole background is fully transparent again. I > > am not sure whether this is a fault in my code or because of some extra > > logic regarding the `default` face. > > > > Attached are a screenshot and the patch. I'd very much appreciate > > feedback. If necessary I could also try to implement this for X and/or > > terminals, however I don't have access to other platforms. > > I'm not happy with this approach, since it defines the alpha value as an > integral component of a face's foreground and background colors, rather > than an attribute (or attributes) the face merging process can manage > independently to prevent alpha values from being transferred between > faces against the user's wishes, and more broadly to enable specifying > alpha values separately from face colors, which there is plenty of > reason for users to replace that might not apply to transparency in > identical circumstances. > > Furthermore, the transparency implemented in this patch is specified > with premultiplied values--premultiplied alpha is more efficient on free > systems, but admits of invalid color values whose behavior is undefined > across all the systems and toolkits we support. It's already too easy > for Emacs users to shoot themselves in the foot, and muddling the waters > with the potential for invalid color definitions would be a step in the > wrong direction, in my humble estimation, so I would prefer an > implementation that exposes straight alpha values to users, converting > between those and the suitable alpha format for the toolkit at display > time. > ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-05-03 7:01 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2024-01-18 1:35 Face transparency attribute Sebastian Wålinder 2024-01-18 7:14 ` Po Lu 2024-03-17 23:02 ` Nate Sandy 2024-03-18 7:41 ` Protesilaos Stavrou 2024-03-18 13:50 ` Po Lu 2024-05-03 7:01 ` Filippo Argiolas
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).