egc inlining #830

pull/893/head
nick black 4 years ago committed by Nick Black
parent 99d90a4ecf
commit b0f7f36995

@ -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
// 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.
//
// 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
// play, and fully supports all transparency options.
typedef struct cell {
// These 32 bits are either a single-byte, single-character grapheme cluster
// (values 0--0x7f), or an offset into a per-ncplane attached pool of
// varying-length UTF-8 grapheme clusters. This pool may thus be up to 32MB.
// These 32 bits are either a complete grapheme cluster in 4 bytes or less,
// or 0x01000000 plus an offset into a per-ncplane attached pool of varying-
// 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
// 8 bits of zero + 8 reserved bits + NCSTYLE_* attributes (16 bits).
// (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)?
static inline bool
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

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

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

@ -1364,36 +1364,30 @@ cell_load_direct(ncplane* n, cell* c, const char* gcluster, int bytes, int cols)
if(bytes < 0 || cols < 0){
return -1;
}
if(bytes <= 1){
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{
if(cols < 2){
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)){
c->channels &= ~CELL_NOBACKGROUND_MASK;
}else{
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);
if(eoffset < 0){
return -1;
}
c->gcluster = eoffset + 0x80;
cell_release(n, c);
c->gcluster = 0x01000000ul + eoffset;
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){
return -1;
}
//fprintf(stderr, "%08x %d %d\n", targ->gcluster, bytes, cols);
targ->attrword = n->attrword;
targ->channels = channels;
if(wide){ // must set our right wide, and check for further damage

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

Loading…
Cancel
Save