Cairo blending modes #1247
Cairo blending modes #1247
Conversation
| a[22] = CAIRO_OPERATOR_DIFFERENCE; | ||
| a[23] = CAIRO_OPERATOR_EXCLUSION; | ||
|
|
||
| cairo_set_operator(cr, a[i]); |
ngwese
Nov 24, 2020
Member
suggest performing bounds checking of i to ensure one can’t generate a segv
suggest performing bounds checking of i to ensure one can’t generate a segv
| @@ -449,5 +449,36 @@ extern void screen_export_png(const char *s) { | |||
| cairo_surface_write_to_png(surface, s); | |||
| } | |||
|
|
|||
| void screen_set_operator(int i) { | |||
| CHECK_CR | |||
| cairo_operator_t a[24]; | |||
ngwese
Nov 24, 2020
Member
the base type of the cairo_operator_t enum is an int, it may be more straightforward to cast i to the appropriate
type (after ensuring i contains a valid value)
the base type of the cairo_operator_t enum is an int, it may be more straightforward to cast i to the appropriate
type (after ensuring i contains a valid value)
tlubke
Nov 24, 2020
Author
Contributor
it may be more straightforward to cast i to the appropriate
type (after ensuring i contains a valid value)
Wouldn't this mean that all operators would have to be included then? There are some not in the array, such as CAIRO_OPERATOR_HSL_SATURATION which have no effect on grayscale values.
it may be more straightforward to cast i to the appropriate
type (after ensuring i contains a valid value)
Wouldn't this mean that all operators would have to be included then? There are some not in the array, such as CAIRO_OPERATOR_HSL_SATURATION which have no effect on grayscale values.
csboling
Nov 26, 2020
•
Contributor
Perhaps one option is to define a lookup table in Lua for the blend modes so that the "public" API lets you call them by name:
Screen.BLEND_MODES = {
['CLEAR'] = 0,
['SOURCE'] = 1,
...
}
Screen.blend_mode = function(mode)
_norns.screen_set_operator(Screen.BLEND_MODES[mode])
end
Then the int passed to the _screen_set_operator weaver function could be cast to a cairo_operator_t and as a script author I would call screen.blend_mode('SOURCE') instead of remembering the numbering or defining my own lookup table.
Perhaps one option is to define a lookup table in Lua for the blend modes so that the "public" API lets you call them by name:
Screen.BLEND_MODES = {
['CLEAR'] = 0,
['SOURCE'] = 1,
...
}
Screen.blend_mode = function(mode)
_norns.screen_set_operator(Screen.BLEND_MODES[mode])
endThen the int passed to the _screen_set_operator weaver function could be cast to a cairo_operator_t and as a script author I would call screen.blend_mode('SOURCE') instead of remembering the numbering or defining my own lookup table.
tehn
Nov 27, 2020
Member
we have a similar issue regarding fonts, which is just a blind index (and the font names are (of minor assistance) reported at matron startup.
just to say, it'd be nice to set up a pattern to follow for similar cases
we have a similar issue regarding fonts, which is just a blind index (and the font names are (of minor assistance) reported at matron startup.
just to say, it'd be nice to set up a pattern to follow for similar cases
|
it is great to see this. adding compositing modes has been on my personal todo/wish list for a long time. |
|
apologies, minor collision--- please merge |
|
@tehn just getting to some of these fixes now.
So should I move setting up the array of |
|
lol, apologies, i should've clarified. here's my proposition, following @csboling
this way the index or the string works. you can list the modes with |
|
@tehn ah, got it! Writing descriptions for each blending mode in the lua docs and I noticed that both Add and Saturate should result in alpha values of (aA + aB), but Saturate's clipping/masking behavior is different than Add's. It's also a bit hard to define in terms of behavior, as it seems to be acting like Dest. What do you think of having the following as the documented modes, and leaving the cairo link for further information?
|
| Screen.blend_mode = function(index) | ||
| if type(index) == "string" then | ||
| local i = Screen.BLEND_MODES[string.upper(index)] | ||
| if i ~= nil then |
tlubke
Nov 29, 2020
•
Author
Contributor
I wasn't able to test this with norns before pushing the commit, I suspect this would lead to the 'attempt to index nil value' error.
Actually I think this is fine, but I'm about to test it just in case.
I wasn't able to test this with norns before pushing the commit, I suspect this would lead to the 'attempt to index nil value' error.
Actually I think this is fine, but I'm about to test it just in case.
|
Compiled on norns now and found a bunch of small errors, don't merge yet, there's another commit coming. |
|
should be good now. found an embarrassing amount of mistakes, can I squash the commits? |
|
sure, rebase and force-push on your fork/branch is fine. |
* added static array of cairo_operator_t and set_operator() to screen.c * added blend_mode() and BLEND_MODES lookup table to Screen.lua
* formatting fix in screen.h
|
thank you this new feature! |




































motivation came from a conversation at the weekly discord meetup.
someone brought up that the cairo C API had support for different blending modes/operators as shown here: https://www.cairographics.org/operators/
I wrote a short norns script for testing all of the operators
some of them are less friendly/useable than others, and I expect the list should be curated a bit.
the added C bits were kinda rushed, so I'm sure there's plenty to clean up.