Rendering now does tripartite fallback to basecell

Each plane has a "base cell", which like all other cells is
initialized to the null glyph, opaque default foreground color,
and opaque default background color. Prior to this change, at
each cell of a plane, we decided whether to use that cell (the
"viscell") or the base cell depending on whether the viscell had
a non-null glyph. We now evaluate each component independently.
If the viscell has a null glyph, we use the base cell's glyph.
If the viscell has a default foreground, we use the base's fg.
If the viscell has a default background, we use the base's bg.
This was done because (a) it seems more intuitive (if I set a cell
to red, I expect red, not red iff there's a glyph in that cell
for this plane), and (b) because otherwise it was impossible to
do a multicolor overlay without blowing away underlying glyphs
(since without a glyph, you always reduced to the same base cell,
which could have only one fore- and background per render).

Existing code will need to change any instances where cells
lacking glyphs are colored, and those colors are not desired.
Since any such coloring had no effect before, it seems unlikely
that any ought exist (this did bring to light an instance in
the "qrcode" demo where we were staining overmuch of the plane).

This closes #395, the last big open worry regarding our API.
This commit is contained in:
nick black 2020-06-11 23:01:10 -04:00
parent 4391c661be
commit 185742fd08
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
4 changed files with 29 additions and 11 deletions

View File

@ -2,6 +2,14 @@ This document attempts to list user-visible changes and any major internal
rearrangements of Notcurses.
* 1.5.1 (not yet released)
* The semantics of rendering have changed slightly. In 1.5.0 and prior
versions, a cell without a glyph was replaced *in toto* by that plane's
base cell at rendering time. The replacement is now tripartite: if there
is no glyph, the base cell's glyph is used; if there is a default
foreground, the base cell's foreground is used; if there is a default
background, the base cell's background is used. This will hopefully be
more intuitive, and allows a plane to effect overlays of varying colors
without needing to override glyphs (#395).
* `ncvisual_geom()`'s `ncblitter_e` argument has been replaced with a
`const struct ncvisual_options*`, so that `NCVISUAL_OPTIONS_NODEGRADE`
can be taken into account (the latter contains a `blitter_e` field).

View File

@ -431,6 +431,17 @@ channels_set_fg_rgb_clipped(uint64_t* channels, int r, int g, int b){
*channels = ((uint64_t)channel << 32llu) | (*channels & 0xffffffffllu);
}
// Same, but set an assembled 24 bit channel at once.
static inline int
channels_set_fg(uint64_t* channels, unsigned rgb){
unsigned channel = channels_fchannel(*channels);
if(channel_set(&channel, rgb) < 0){
return -1;
}
*channels = ((uint64_t)channel << 32llu) | (*channels & 0xffffffffllu);
return 0;
}
// Set the r, g, and b channels for the background component of this 64-bit
// 'channels' variable, and mark it as not using the default color.
static inline int
@ -452,16 +463,6 @@ channels_set_bg_rgb_clipped(uint64_t* channels, int r, int g, int b){
}
// Same, but set an assembled 24 bit channel at once.
static inline int
channels_set_fg(uint64_t* channels, unsigned rgb){
unsigned channel = channels_fchannel(*channels);
if(channel_set(&channel, rgb) < 0){
return -1;
}
*channels = ((uint64_t)channel << 32llu) | (*channels & 0xffffffffllu);
return 0;
}
static inline int
channels_set_bg(uint64_t* channels, unsigned rgb){
unsigned channel = channels_bchannel(*channels);

View File

@ -59,7 +59,7 @@ int qrcode_demo(struct notcurses* nc){
channels_set_fg_rgb(&tr, random() % 255 + 1, random() % 255 + 1, random() % 255 + 1);
channels_set_fg_rgb(&bl, random() % 255 + 1, random() % 255 + 1, random() % 255 + 1);
channels_set_fg_rgb(&br, random() % 255 + 1, random() % 255 + 1, random() % 255 + 1);
if(ncplane_stain(n, dimy - 1, dimx - 1, tl, tr, bl, br) <= 0){
if(ncplane_stain(n, qrcode_rows(qlen), qrcode_cols(qlen), tl, tr, bl, br) <= 0){
ncplane_destroy(n);
return -1;
}

View File

@ -319,6 +319,10 @@ paint(ncplane* p, cell* lastframe, struct crender* rvec,
// glyph. If we've already locked in the background, it has no effect.
// If it's transparent, it has no effect. Otherwise, update the
// background channel and balpha.
vis = &p->fb[nfbcellidx(p, y, x)];
if(cell_bg_default_p(vis)){
vis = &p->basecell;
}
if(cell_bg_palindex_p(vis)){
if(cell_bg_alpha(targc) == CELL_ALPHA_TRANSPARENT){
cell_set_bg_palindex(targc, cell_bg_palindex(vis));
@ -326,7 +330,12 @@ paint(ncplane* p, cell* lastframe, struct crender* rvec,
}else if(cell_bg_alpha(targc) > CELL_ALPHA_OPAQUE){
cell_blend_bchannel(targc, cell_bchannel(vis), &crender->bgblends);
}
// Evaluate the background first, in case this is HIGHCONTRAST fg text.
vis = &p->fb[nfbcellidx(p, y, x)];
if(cell_fg_default_p(vis)){
vis = &p->basecell;
}
if(cell_fg_palindex_p(vis)){
if(cell_fg_alpha(targc) == CELL_ALPHA_TRANSPARENT){
cell_set_fg_palindex(targc, cell_fg_palindex(vis));