mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-10 01:29:05 -04:00
glyph-based background spec elision #131
When we emit a glyph that has no background pixels (i.e. the U+2588 FULL BLOCK glyph), there's no need to emit a background color change. Eagle demo currently has hand-coded elision. Results from 80x70 runs using the `-c` parameter: No optimization: 12.63MiB Hand-optimized: 12.48MiB New scheme, no hand-coded optimization: 12.45MiB w00t!
This commit is contained in:
parent
113a8f8f62
commit
5b322add56
@ -3,6 +3,7 @@
|
||||
|
||||
#include <time.h>
|
||||
#include <uchar.h>
|
||||
#include <ctype.h>
|
||||
#include <wchar.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@ -1317,18 +1318,37 @@ cell_set_bg_alpha(cell* c, int alpha){
|
||||
return channels_set_bg_alpha(&c->channels, alpha);
|
||||
}
|
||||
|
||||
// does the cell contain an East Asian Wide codepoint?
|
||||
// Does the cell contain an East Asian Wide codepoint?
|
||||
static inline bool
|
||||
cell_double_wide_p(const cell* c){
|
||||
return (c->channels & CELL_WIDEASIAN_MASK);
|
||||
}
|
||||
|
||||
// is the cell simple (a lone ASCII character, encoded as such)?
|
||||
// Is the cell simple (a lone ASCII character, encoded as such)?
|
||||
static inline bool
|
||||
cell_simple_p(const cell* c){
|
||||
return c->gcluster < 0x80;
|
||||
}
|
||||
|
||||
// return a pointer to the NUL-terminated EGC referenced by 'c'. this pointer
|
||||
// is invalidated by any further operation on the plane 'n', so...watch out!
|
||||
API const char* cell_extended_gcluster(const struct ncplane* n, const cell* c);
|
||||
|
||||
// True if the cell does not generate foreground pixels (i.e., the cell is
|
||||
// entirely whitespace or special characters).
|
||||
// FIXME do this at cell prep time and set a bit in the channels
|
||||
static inline bool
|
||||
cell_noforeground_p(const cell* c){
|
||||
return cell_simple_p(c) || isspace(c->gcluster);
|
||||
}
|
||||
|
||||
// True if the cell does not generate background pixels. Only the FULL BLOCK
|
||||
// glyph has this property, AFAIK.
|
||||
static inline bool
|
||||
cell_nobackground_p(const struct ncplane* n, const cell* c){
|
||||
return !cell_simple_p(c) && !strcmp(cell_extended_gcluster(n, c), "\xe2\x96\x88");
|
||||
}
|
||||
|
||||
static inline int
|
||||
cell_load_simple(struct ncplane* n, cell* c, char ch){
|
||||
cell_release(n, c);
|
||||
@ -1347,10 +1367,6 @@ cell_egc_idx(const cell* c){
|
||||
return c->gcluster - 0x80;
|
||||
}
|
||||
|
||||
// return a pointer to the NUL-terminated EGC referenced by 'c'. this pointer
|
||||
// is invalidated by any further operation on the plane 'n', so...watch out!
|
||||
API const char* cell_extended_gcluster(const struct ncplane* n, const cell* c);
|
||||
|
||||
// load up six cells with the EGCs necessary to draw a box. returns 0 on
|
||||
// success, -1 on error. on error, any cells this function might
|
||||
// have loaded before the error are cell_release()d. There must be at least
|
||||
|
@ -121,8 +121,6 @@ draw_eagle(struct ncplane* n, const char* sprite){
|
||||
size_t s;
|
||||
int sbytes;
|
||||
uint64_t channels = 0;
|
||||
// optimization so we can elide more color changes, see README's "#perf"
|
||||
channels_set_bg_rgb(&channels, 0x00, 0x00, 0x00);
|
||||
ncplane_cursor_move_yx(n, 0, 0);
|
||||
for(s = 0 ; sprite[s] ; ++s){
|
||||
switch(sprite[s]){
|
||||
|
@ -534,8 +534,16 @@ notcurses_render_internal(notcurses* nc){
|
||||
// escapes ourselves, if either is set to default, we first send op, and
|
||||
// then a turnon for whichever aren't default.
|
||||
|
||||
// we can elide the default set iff the previous used both defaults
|
||||
if(cell_fg_default_p(&c) || cell_bg_default_p(&c)){
|
||||
// if our cell has a default foreground *or* background, we can elide the
|
||||
// default set iff one of:
|
||||
// * we are a partial glyph, and the previous was default on both, or
|
||||
// * we are a no-foreground glyph, and the previous was default background, or
|
||||
// * we are a no-background glyph, and the previous was default foreground
|
||||
|
||||
// FIXME move these into the cell bits
|
||||
bool noforeground = cell_noforeground_p(&c);
|
||||
bool nobackground = cell_nobackground_p(p, &c);
|
||||
if((!noforeground && cell_fg_default_p(&c)) || (!nobackground && cell_bg_default_p(&c))){
|
||||
if(!nc->rstate.defaultelidable){
|
||||
++nc->stats.defaultemissions;
|
||||
term_emit("op", nc->op, out, false);
|
||||
@ -548,8 +556,11 @@ notcurses_render_internal(notcurses* nc){
|
||||
nc->rstate.bgelidable = false;
|
||||
}
|
||||
|
||||
// we can elide the foreground set iff the previous used fg and matched
|
||||
if(!cell_fg_default_p(&c)){
|
||||
// if our cell has a non-default foreground, we can elide the non-default
|
||||
// foreground set iff either:
|
||||
// * the previous was non-default, and matches what we have now, or
|
||||
// * we are a no-foreground glyph (iswspace() is true)
|
||||
if(/*!noforeground &&*/ !cell_fg_default_p(&c)){
|
||||
cell_get_fg_rgb(&c, &r, &g, &b);
|
||||
if(nc->rstate.fgelidable && nc->rstate.lastr == r && nc->rstate.lastg == g && nc->rstate.lastb == b){
|
||||
++nc->stats.fgelisions;
|
||||
@ -561,7 +572,7 @@ notcurses_render_internal(notcurses* nc){
|
||||
nc->rstate.lastr = r; nc->rstate.lastg = g; nc->rstate.lastb = b;
|
||||
nc->rstate.defaultelidable = false;
|
||||
}
|
||||
if(!cell_bg_default_p(&c)){
|
||||
if(!nobackground && !cell_bg_default_p(&c)){
|
||||
cell_get_bg_rgb(&c, &br, &bg, &bb);
|
||||
if(nc->rstate.bgelidable && nc->rstate.lastbr == br && nc->rstate.lastbg == bg && nc->rstate.lastbb == bb){
|
||||
++nc->stats.bgelisions;
|
||||
|
Loading…
x
Reference in New Issue
Block a user