egc inlining #830

This commit is contained in:
nick black 2020-08-02 23:25:19 -04:00 committed by Nick Black
parent 99d90a4ecf
commit b0f7f36995
5 changed files with 30 additions and 36 deletions

View File

@ -485,7 +485,7 @@ channels_set_bg_default(uint64_t* channels){
// //
// Each cell occupies 16 static bytes (128 bits). The surface is thus ~1.6MB // Each cell occupies 16 static bytes (128 bits). The surface is thus ~1.6MB
// for a (pretty large) 500x200 terminal. At 80x43, it's less than 64KB. // for a (pretty large) 500x200 terminal. At 80x43, it's less than 64KB.
// Dynamic requirements (the egcpool) can add up to 32MB to an ncplane, but // Dynamic requirements (the egcpool) can add up to 16MB to an ncplane, but
// such large pools are unlikely in common use. // such large pools are unlikely in common use.
// //
// We implement some small alpha compositing. Foreground and background both // We implement some small alpha compositing. Foreground and background both
@ -506,9 +506,12 @@ channels_set_bg_default(uint64_t* channels){
// RGB is used if neither default terminal colors nor palette indexing are in // RGB is used if neither default terminal colors nor palette indexing are in
// play, and fully supports all transparency options. // play, and fully supports all transparency options.
typedef struct cell { typedef struct cell {
// These 32 bits are either a single-byte, single-character grapheme cluster // These 32 bits are either a complete grapheme cluster in 4 bytes or less,
// (values 0--0x7f), or an offset into a per-ncplane attached pool of // or 0x01000000 plus an offset into a per-ncplane attached pool of varying-
// varying-length UTF-8 grapheme clusters. This pool may thus be up to 32MB. // length UTF-8 EGCs (an egcpool). This pool may thus be up to 16MB.
// Obviously, this implies that EGCs beginning with 0x01 are disallowed; such
// an EGC, if we wanted to support them, could be spilled to the egcpool. If
// the EGC is less than four bytes, it will be padded with zeroes.
uint32_t gcluster; // 4B -> 4B uint32_t gcluster; // 4B -> 4B
// 8 bits of zero + 8 reserved bits + NCSTYLE_* attributes (16 bits). // 8 bits of zero + 8 reserved bits + NCSTYLE_* attributes (16 bits).
// (attrword & 0xff000000): reserved, *must be zero* // (attrword & 0xff000000): reserved, *must be zero*
@ -648,7 +651,7 @@ cell_wide_left_p(const cell* c){
// 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 static inline bool
cell_simple_p(const cell* c){ cell_simple_p(const cell* c){
return c->gcluster < 0x80; return (c->gcluster >> 24u) != 0x01;
} }
// return a pointer to the NUL-terminated EGC referenced by 'c'. this pointer // return a pointer to the NUL-terminated EGC referenced by 'c'. this pointer

View File

@ -249,7 +249,7 @@ egcpool_dump(egcpool* pool){
// unsafe results if called on a simple cell. // unsafe results if called on a simple cell.
static inline uint32_t static inline uint32_t
cell_egc_idx(const cell* c){ cell_egc_idx(const cell* c){
return c->gcluster - 0x80; return c->gcluster & 0x00fffffflu;
} }
__attribute__ ((__returns_nonnull__)) static inline const char* __attribute__ ((__returns_nonnull__)) static inline const char*

View File

@ -608,7 +608,7 @@ cell_duplicate_far(egcpool* tpool, cell* targ, const ncplane* splane, const cell
if(eoffset < 0){ if(eoffset < 0){
return -1; return -1;
} }
targ->gcluster = eoffset + 0x80; targ->gcluster = 0x01000000ul + eoffset;
return ulen; return ulen;
} }

View File

@ -1364,36 +1364,30 @@ cell_load_direct(ncplane* n, cell* c, const char* gcluster, int bytes, int cols)
if(bytes < 0 || cols < 0){ if(bytes < 0 || cols < 0){
return -1; return -1;
} }
if(bytes <= 1){ if(cols < 2){
assert(cols < 2);
cell_release(n, c);
c->channels &= ~(CELL_WIDEASIAN_MASK | CELL_NOBACKGROUND_MASK);
c->gcluster = *gcluster;
return bytes;
}
if(!cell_simple_p(c)){
if(strcmp(gcluster, cell_extended_gcluster(n, c)) == 0){
return bytes; // reduce, reuse, recycle
}else{
cell_release(n, c);
}
}
if(cols > 1){
c->channels |= CELL_WIDEASIAN_MASK;
}else{
c->channels &= ~CELL_WIDEASIAN_MASK; c->channels &= ~CELL_WIDEASIAN_MASK;
}else{
c->channels |= CELL_WIDEASIAN_MASK;
} }
// FIXME also shaded blocks! ░ etc // FIXME also shaded blocks! ░ etc. are there combined EGCs involving these?
if(strncmp(gcluster, "\xe2\x96\x88", 3)){ if(strncmp(gcluster, "\xe2\x96\x88", 3)){
c->channels &= ~CELL_NOBACKGROUND_MASK; c->channels &= ~CELL_NOBACKGROUND_MASK;
}else{ }else{
c->channels |= CELL_NOBACKGROUND_MASK; c->channels |= CELL_NOBACKGROUND_MASK;
} }
if(bytes <= 4){
cell_release(n, c);
c->channels &= ~CELL_WIDEASIAN_MASK;
c->gcluster = 0;
memcpy(&c->gcluster, gcluster, bytes);
return bytes;
}
int eoffset = egcpool_stash(&n->pool, gcluster, bytes); int eoffset = egcpool_stash(&n->pool, gcluster, bytes);
if(eoffset < 0){ if(eoffset < 0){
return -1; return -1;
} }
c->gcluster = eoffset + 0x80; cell_release(n, c);
c->gcluster = 0x01000000ul + eoffset;
return bytes; return bytes;
} }
@ -1452,6 +1446,7 @@ int ncplane_putegc_yx(ncplane* n, int y, int x, const char* gclust, int* sbytes)
if(cell_load_direct(n, targ, gclust, bytes, cols) < 0){ if(cell_load_direct(n, targ, gclust, bytes, cols) < 0){
return -1; return -1;
} }
//fprintf(stderr, "%08x %d %d\n", targ->gcluster, bytes, cols);
targ->attrword = n->attrword; targ->attrword = n->attrword;
targ->channels = channels; targ->channels = channels;
if(wide){ // must set our right wide, and check for further damage if(wide){ // must set our right wide, and check for further damage

View File

@ -500,16 +500,12 @@ ncfputc(char c, FILE* out){
static int static int
term_putc(FILE* out, const egcpool* e, const cell* c){ term_putc(FILE* out, const egcpool* e, const cell* c){
if(cell_simple_p(c)){ if(cell_simple_p(c)){
if(c->gcluster == 0 || iscntrl(c->gcluster)){ char egc[5];
// fprintf(stderr, "[ ]\n"); memset(egc, 0, sizeof(egc));
if(ncfputc(' ', out) == EOF){ memcpy(egc, &c->gcluster, sizeof(c->gcluster));
return -1; //fprintf(stderr, "[%ls]\n", egc);
} if(ncfputs(egc, out) == EOF){
}else{ return -1;
//fprintf(stderr, "[%c]\n", c->gcluster);
if(ncfputc(c->gcluster, out) == EOF){
return -1;
}
} }
}else{ }else{
const char* ext = egcpool_extended_gcluster(e, c); const char* ext = egcpool_extended_gcluster(e, c);