Split up the color field into fg/bg colors

Avoid a lot of unnecessary masking as well as unaligned read/writes
This commit is contained in:
Kovid Goyal 2017-05-15 08:32:52 +05:30
parent 800291c147
commit 69b187a743
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 64 additions and 63 deletions

View File

@ -17,8 +17,7 @@
#define MIN(x, y) (((x) > (y)) ? (y) : (x)) #define MIN(x, y) (((x) > (y)) ? (y) : (x))
typedef Py_UCS4 char_type; typedef Py_UCS4 char_type;
typedef uint64_t color_type; typedef uint32_t color_type;
typedef uint32_t decoration_type;
typedef uint32_t combining_type; typedef uint32_t combining_type;
typedef unsigned int index_type; typedef unsigned int index_type;
@ -31,7 +30,8 @@ typedef unsigned int index_type;
#define SGR_PROTOCOL 2 #define SGR_PROTOCOL 2
#define URXVT_PROTOCOL 3 #define URXVT_PROTOCOL 3
#define CELL_SIZE (sizeof(char_type) + sizeof(color_type) + sizeof(decoration_type) + sizeof(combining_type)) #define CELL_FIELD_COUNT 5
#define CELL_SIZE (CELL_FIELD_COUNT * 4)
// The data cell size must be a multiple of 3 // The data cell size must be a multiple of 3
#define DATA_CELL_SIZE 2 * 3 #define DATA_CELL_SIZE 2 * 3
@ -46,8 +46,6 @@ typedef unsigned int index_type;
#define REVERSE_SHIFT 6 #define REVERSE_SHIFT 6
#define STRIKE_SHIFT 7 #define STRIKE_SHIFT 7
#define COL_MASK 0xFFFFFFFF #define COL_MASK 0xFFFFFFFF
#define COL_SHIFT 32
#define HAS_BG_MASK (0xFF << COL_SHIFT)
#define CC_MASK 0xFFFF #define CC_MASK 0xFFFF
#define CC_SHIFT 16 #define CC_SHIFT 16
#define UTF8_ACCEPT 0 #define UTF8_ACCEPT 0
@ -77,7 +75,8 @@ typedef unsigned int index_type;
#define COPY_CELL(src, s, dest, d) \ #define COPY_CELL(src, s, dest, d) \
(dest)->chars[d] = (src)->chars[s]; \ (dest)->chars[d] = (src)->chars[s]; \
(dest)->colors[d] = (src)->colors[s]; \ (dest)->fg_colors[d] = (src)->fg_colors[s]; \
(dest)->bg_colors[d] = (src)->bg_colors[s]; \
(dest)->decoration_fg[d] = (src)->decoration_fg[s]; \ (dest)->decoration_fg[d] = (src)->decoration_fg[s]; \
(dest)->combining_chars[d] = (src)->combining_chars[s]; (dest)->combining_chars[d] = (src)->combining_chars[s];
@ -85,18 +84,17 @@ typedef unsigned int index_type;
#define COPY_LINE(src, dest) \ #define COPY_LINE(src, dest) \
memcpy((dest)->chars, (src)->chars, sizeof(char_type) * MIN((src)->xnum, (dest)->xnum)); \ memcpy((dest)->chars, (src)->chars, sizeof(char_type) * MIN((src)->xnum, (dest)->xnum)); \
memcpy((dest)->colors, (src)->colors, sizeof(color_type) * MIN((src)->xnum, (dest)->xnum)); \ memcpy((dest)->fg_colors, (src)->fg_colors, sizeof(color_type) * MIN((src)->xnum, (dest)->xnum)); \
memcpy((dest)->decoration_fg, (src)->decoration_fg, sizeof(decoration_type) * MIN((src)->xnum, (dest)->xnum)); \ memcpy((dest)->bg_colors, (src)->bg_colors, sizeof(color_type) * MIN((src)->xnum, (dest)->xnum)); \
memcpy((dest)->decoration_fg, (src)->decoration_fg, sizeof(color_type) * MIN((src)->xnum, (dest)->xnum)); \
memcpy((dest)->combining_chars, (src)->combining_chars, sizeof(combining_type) * MIN((src)->xnum, (dest)->xnum)); memcpy((dest)->combining_chars, (src)->combining_chars, sizeof(combining_type) * MIN((src)->xnum, (dest)->xnum));
#define CLEAR_LINE(l, at, num) \ #define CLEAR_LINE(l, num) \
for (index_type i = (at); i < (num); i++) (l)->chars[i] = (1 << ATTRS_SHIFT) | 32; \ for (index_type i = 0; i < (num); i++) (l)->chars[i] = (1 << ATTRS_SHIFT) | 32; \
memset((l)->colors, (at), (num) * sizeof(color_type)); \ memset((l)->fg_colors, 0, (num) * sizeof(color_type)); \
memset((l)->decoration_fg, (at), (num) * sizeof(decoration_type)); \ memset((l)->bg_colors, 0, (num) * sizeof(color_type)); \
memset((l)->combining_chars, (at), (num) * sizeof(combining_type)); memset((l)->decoration_fg, 0, (num) * sizeof(color_type)); \
memset((l)->combining_chars, 0, (num) * sizeof(combining_type));
#define COLORS_TO_CURSOR(col, c) \
c->fg = col & COL_MASK; c->bg = (col >> COL_SHIFT)
#define METHOD(name, arg_type) {#name, (PyCFunction)name, arg_type, name##_doc}, #define METHOD(name, arg_type) {#name, (PyCFunction)name, arg_type, name##_doc},
@ -145,8 +143,9 @@ typedef struct {
PyObject_HEAD PyObject_HEAD
char_type *chars; char_type *chars;
color_type *colors; color_type *fg_colors;
decoration_type *decoration_fg; color_type *bg_colors;
color_type *decoration_fg;
combining_type *combining_chars; combining_type *combining_chars;
index_type xnum, ynum; index_type xnum, ynum;
bool continued; bool continued;
@ -166,8 +165,9 @@ typedef struct {
// Pointers into buf // Pointers into buf
char_type *chars; char_type *chars;
color_type *colors; color_type *fg_colors;
decoration_type *decoration_fg; color_type *bg_colors;
color_type *decoration_fg;
combining_type *combining_chars; combining_type *combining_chars;
} LineBuf; } LineBuf;
PyTypeObject LineBuf_Type; PyTypeObject LineBuf_Type;

View File

@ -72,8 +72,9 @@ init_line(HistoryBuf *self, index_type num, Line *l) {
uint8_t *start_ptr = start_of(self, num); uint8_t *start_ptr = start_of(self, num);
l->continued = *start_ptr; l->continued = *start_ptr;
l->chars = (char_type*)(start_ptr + 1); l->chars = (char_type*)(start_ptr + 1);
l->colors = (color_type*)(l->chars + self->xnum); l->fg_colors = (color_type*)(l->chars + self->xnum);
l->decoration_fg = (decoration_type*)(l->colors + self->xnum); l->bg_colors = (color_type*)(l->fg_colors + self->xnum);
l->decoration_fg = (color_type*)(l->bg_colors + self->xnum);
l->combining_chars = (combining_type*)(l->decoration_fg + self->xnum); l->combining_chars = (combining_type*)(l->decoration_fg + self->xnum);
} }

View File

@ -63,8 +63,9 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
Py_CLEAR(self); Py_CLEAR(self);
} else { } else {
self->chars = (char_type*)self->buf; self->chars = (char_type*)self->buf;
self->colors = (color_type*)(self->chars + self->block_size); self->fg_colors = (color_type*)(self->chars + self->block_size);
self->decoration_fg = (decoration_type*)(self->colors + self->block_size); self->bg_colors = (color_type*)(self->fg_colors + self->block_size);
self->decoration_fg = (color_type*)(self->bg_colors + self->block_size);
self->combining_chars = (combining_type*)(self->decoration_fg + self->block_size); self->combining_chars = (combining_type*)(self->decoration_fg + self->block_size);
self->line->xnum = xnum; self->line->xnum = xnum;
for(index_type i = 0; i < ynum; i++) { for(index_type i = 0; i < ynum; i++) {
@ -89,7 +90,8 @@ dealloc(LineBuf* self) {
#define INIT_LINE(lb, l, ynum) \ #define INIT_LINE(lb, l, ynum) \
(l)->chars = (lb)->chars + (ynum) * (lb)->xnum; \ (l)->chars = (lb)->chars + (ynum) * (lb)->xnum; \
(l)->colors = (lb)->colors + (ynum) * (lb)->xnum; \ (l)->fg_colors = (lb)->fg_colors + (ynum) * (lb)->xnum; \
(l)->bg_colors = (lb)->bg_colors + (ynum) * (lb)->xnum; \
(l)->decoration_fg = (lb)->decoration_fg + (ynum) * (lb)->xnum; \ (l)->decoration_fg = (lb)->decoration_fg + (ynum) * (lb)->xnum; \
(l)->combining_chars = (lb)->combining_chars + (ynum) * (lb)->xnum; (l)->combining_chars = (lb)->combining_chars + (ynum) * (lb)->xnum;
@ -150,19 +152,22 @@ static inline int
allocate_line_storage(Line *line, bool initialize) { allocate_line_storage(Line *line, bool initialize) {
if (initialize) { if (initialize) {
line->chars = PyMem_Calloc(line->xnum, sizeof(char_type)); line->chars = PyMem_Calloc(line->xnum, sizeof(char_type));
line->colors = PyMem_Calloc(line->xnum, sizeof(color_type)); line->fg_colors = PyMem_Calloc(line->xnum, sizeof(color_type));
line->decoration_fg = PyMem_Calloc(line->xnum, sizeof(decoration_type)); line->bg_colors = PyMem_Calloc(line->xnum, sizeof(color_type));
line->decoration_fg = PyMem_Calloc(line->xnum, sizeof(color_type));
line->combining_chars = PyMem_Calloc(line->xnum, sizeof(combining_type)); line->combining_chars = PyMem_Calloc(line->xnum, sizeof(combining_type));
for (index_type i = 0; i < line->xnum; i++) line->chars[i] = (1 << ATTRS_SHIFT) | 32; for (index_type i = 0; i < line->xnum; i++) line->chars[i] = (1 << ATTRS_SHIFT) | 32;
} else { } else {
line->chars = PyMem_Malloc(line->xnum * sizeof(char_type)); line->chars = PyMem_Malloc(line->xnum * sizeof(char_type));
line->colors = PyMem_Malloc(line->xnum * sizeof(color_type)); line->fg_colors = PyMem_Malloc(line->xnum * sizeof(color_type));
line->decoration_fg = PyMem_Malloc(line->xnum * sizeof(decoration_type)); line->bg_colors = PyMem_Malloc(line->xnum * sizeof(color_type));
line->decoration_fg = PyMem_Malloc(line->xnum * sizeof(color_type));
line->combining_chars = PyMem_Malloc(line->xnum * sizeof(combining_type)); line->combining_chars = PyMem_Malloc(line->xnum * sizeof(combining_type));
} }
if (line->chars == NULL || line->colors == NULL || line->decoration_fg == NULL || line->combining_chars == NULL) { if (line->chars == NULL || line->fg_colors == NULL || line->bg_colors == NULL || line->decoration_fg == NULL || line->combining_chars == NULL) {
PyMem_Free(line->chars); line->chars = NULL; PyMem_Free(line->chars); line->chars = NULL;
PyMem_Free(line->colors); line->colors = NULL; PyMem_Free(line->fg_colors); line->fg_colors = NULL;
PyMem_Free(line->bg_colors); line->bg_colors = NULL;
PyMem_Free(line->decoration_fg); line->decoration_fg = NULL; PyMem_Free(line->decoration_fg); line->decoration_fg = NULL;
PyMem_Free(line->combining_chars); line->combining_chars = NULL; PyMem_Free(line->combining_chars); line->combining_chars = NULL;
PyErr_NoMemory(); PyErr_NoMemory();
@ -210,7 +215,7 @@ copy_line_to(LineBuf *self, PyObject *args) {
void linebuf_clear_line(LineBuf *self, index_type y) { void linebuf_clear_line(LineBuf *self, index_type y) {
Line l; Line l;
INIT_LINE(self, &l, self->line_map[y]); INIT_LINE(self, &l, self->line_map[y]);
CLEAR_LINE(&l, 0, self->xnum); CLEAR_LINE(&l, self->xnum);
self->continued_map[y] = 0; self->continued_map[y] = 0;
} }
@ -295,7 +300,7 @@ void linebuf_insert_lines(LineBuf *self, unsigned int num, unsigned int y, unsig
Line l; Line l;
for (i = y; i < y + num; i++) { for (i = y; i < y + num; i++) {
INIT_LINE(self, &l, self->line_map[i]); INIT_LINE(self, &l, self->line_map[i]);
CLEAR_LINE(&l, 0, self->xnum); CLEAR_LINE(&l, self->xnum);
self->continued_map[i] = 0; self->continued_map[i] = 0;
} }
} }
@ -330,7 +335,7 @@ linebuf_delete_lines(LineBuf *self, index_type num, index_type y, index_type bot
Line l; Line l;
for (i = ylimit - num; i < ylimit; i++) { for (i = ylimit - num; i < ylimit; i++) {
INIT_LINE(self, &l, self->line_map[i]); INIT_LINE(self, &l, self->line_map[i]);
CLEAR_LINE(&l, 0, self->xnum); CLEAR_LINE(&l, self->xnum);
self->continued_map[i] = 0; self->continued_map[i] = 0;
} }
} }

View File

@ -17,7 +17,8 @@ static void
dealloc(Line* self) { dealloc(Line* self) {
if (self->needs_free) { if (self->needs_free) {
PyMem_Free(self->chars); PyMem_Free(self->chars);
PyMem_Free(self->colors); PyMem_Free(self->fg_colors);
PyMem_Free(self->bg_colors);
PyMem_Free(self->decoration_fg); PyMem_Free(self->decoration_fg);
PyMem_Free(self->combining_chars); PyMem_Free(self->combining_chars);
} }
@ -170,9 +171,8 @@ line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen) {
WRITE_SGR(0); break; WRITE_SGR(0); break;
} }
} }
color_type col = self->colors[pos]; CHECK_COLOR(fg, self->fg_colors[pos], 38);
CHECK_COLOR(fg, col & COL_MASK, 38); CHECK_COLOR(bg, self->bg_colors[pos], 48);
CHECK_COLOR(bg, col >> COL_SHIFT, 48);
CHECK_COLOR(decoration_fg, self->decoration_fg[pos], DECORATION_FG_CODE); CHECK_COLOR(decoration_fg, self->decoration_fg[pos], DECORATION_FG_CODE);
WRITE_CH(ch); WRITE_CH(ch);
char_type cc = self->combining_chars[pos]; char_type cc = self->combining_chars[pos];
@ -226,15 +226,6 @@ width(Line *self, PyObject *val) {
return PyLong_FromUnsignedLong((unsigned long) (attrs & WIDTH_MASK)); return PyLong_FromUnsignedLong((unsigned long) (attrs & WIDTH_MASK));
} }
static PyObject*
basic_cell_data(Line *self, PyObject *val) {
#define basic_cell_data_doc "basic_cell_data(x) -> ch, attrs, colors"
unsigned long x = PyLong_AsUnsignedLong(val);
if (x >= self->xnum) { PyErr_SetString(PyExc_ValueError, "Out of bounds"); return NULL; }
char_type ch = self->chars[x];
return Py_BuildValue("IBK", (unsigned int)(ch & CHAR_MASK), (unsigned char)(ch >> ATTRS_SHIFT), (unsigned long long)self->colors[x]);
}
void line_add_combining_char(Line *self, uint32_t ch, unsigned int x) { void line_add_combining_char(Line *self, uint32_t ch, unsigned int x) {
combining_type c = self->combining_chars[x]; combining_type c = self->combining_chars[x];
if (c & CC_MASK) self->combining_chars[x] = (c & CC_MASK) | ( (ch & CC_MASK) << CC_SHIFT ); if (c & CC_MASK) self->combining_chars[x] = (c & CC_MASK) | ( (ch & CC_MASK) << CC_SHIFT );
@ -279,12 +270,13 @@ set_text(Line* self, PyObject *args) {
return NULL; return NULL;
} }
attrs = CURSOR_TO_ATTRS(cursor, 1); attrs = CURSOR_TO_ATTRS(cursor, 1);
color_type col = (cursor->fg & COL_MASK) | ((color_type)(cursor->bg & COL_MASK) << COL_SHIFT); color_type fg = (cursor->fg & COL_MASK), bg = cursor->bg & COL_MASK;
decoration_type dfg = cursor->decoration_fg & COL_MASK; color_type dfg = cursor->decoration_fg & COL_MASK;
for (index_type i = cursor->x; offset < limit && i < self->xnum; i++, offset++) { for (index_type i = cursor->x; offset < limit && i < self->xnum; i++, offset++) {
self->chars[i] = (PyUnicode_READ(kind, buf, offset) & CHAR_MASK) | attrs; self->chars[i] = (PyUnicode_READ(kind, buf, offset) & CHAR_MASK) | attrs;
self->colors[i] = col; self->fg_colors[i] = fg;
self->bg_colors[i] = bg;
self->decoration_fg[i] = dfg; self->decoration_fg[i] = dfg;
self->combining_chars[i] = 0; self->combining_chars[i] = 0;
} }
@ -307,7 +299,7 @@ cursor_from(Line* self, PyObject *args) {
ans->x = x; ans->y = y; ans->x = x; ans->y = y;
char_type attrs = self->chars[x] >> ATTRS_SHIFT; char_type attrs = self->chars[x] >> ATTRS_SHIFT;
ATTRS_TO_CURSOR(attrs, ans); ATTRS_TO_CURSOR(attrs, ans);
COLORS_TO_CURSOR(self->colors[x], ans); ans->fg = self->fg_colors[x]; ans->bg = self->bg_colors[x];
ans->decoration_fg = self->decoration_fg[x] & COL_MASK; ans->decoration_fg = self->decoration_fg[x] & COL_MASK;
return (PyObject*)ans; return (PyObject*)ans;
@ -335,8 +327,8 @@ clear_text(Line* self, PyObject *args) {
void void
line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num, bool clear_char) { line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num, bool clear_char) {
char_type attrs = CURSOR_TO_ATTRS(cursor, 1); char_type attrs = CURSOR_TO_ATTRS(cursor, 1);
color_type col = (cursor->fg & COL_MASK) | ((color_type)(cursor->bg & COL_MASK) << COL_SHIFT); color_type fg = (cursor->fg & COL_MASK), bg = (cursor->bg & COL_MASK);
decoration_type dfg = cursor->decoration_fg & COL_MASK; color_type dfg = cursor->decoration_fg & COL_MASK;
if (!clear_char) attrs = ((attrs >> ATTRS_SHIFT) & ~WIDTH_MASK) << ATTRS_SHIFT; if (!clear_char) attrs = ((attrs >> ATTRS_SHIFT) & ~WIDTH_MASK) << ATTRS_SHIFT;
for (index_type i = at; i < self->xnum && i < at + num; i++) { for (index_type i = at; i < self->xnum && i < at + num; i++) {
@ -347,7 +339,7 @@ line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num,
char_type w = ((self->chars[i] >> ATTRS_SHIFT) & WIDTH_MASK) << ATTRS_SHIFT; char_type w = ((self->chars[i] >> ATTRS_SHIFT) & WIDTH_MASK) << ATTRS_SHIFT;
self->chars[i] = (self->chars[i] & CHAR_MASK) | attrs | w; self->chars[i] = (self->chars[i] & CHAR_MASK) | attrs | w;
} }
self->colors[i] = col; self->fg_colors[i] = fg; self->bg_colors[i] = bg;
self->decoration_fg[i] = dfg; self->decoration_fg[i] = dfg;
} }
} }
@ -407,7 +399,8 @@ line_set_char(Line *self, unsigned int at, uint32_t ch, unsigned int width, Curs
attrs = (((self->chars[at] >> ATTRS_SHIFT) & ~3) | (width & 3)) << ATTRS_SHIFT; attrs = (((self->chars[at] >> ATTRS_SHIFT) & ~3) | (width & 3)) << ATTRS_SHIFT;
} else { } else {
attrs = CURSOR_TO_ATTRS(cursor, width & 3); attrs = CURSOR_TO_ATTRS(cursor, width & 3);
self->colors[at] = (cursor->fg & COL_MASK) | ((color_type)(cursor->bg & COL_MASK) << COL_SHIFT); self->fg_colors[at] = (cursor->fg & COL_MASK);
self->bg_colors[at] = (cursor->bg & COL_MASK);
self->decoration_fg[at] = cursor->decoration_fg & COL_MASK; self->decoration_fg[at] = cursor->decoration_fg & COL_MASK;
} }
self->chars[at] = (ch & CHAR_MASK) | attrs; self->chars[at] = (ch & CHAR_MASK) | attrs;
@ -449,8 +442,9 @@ __len__(PyObject *self) {
static int __eq__(Line *a, Line *b) { static int __eq__(Line *a, Line *b) {
return a->xnum == b->xnum && \ return a->xnum == b->xnum && \
memcmp(a->chars, b->chars, sizeof(char_type) * a->xnum) == 0 && \ memcmp(a->chars, b->chars, sizeof(char_type) * a->xnum) == 0 && \
memcmp(a->colors, b->colors, sizeof(color_type) * a->xnum) == 0 && \ memcmp(a->fg_colors, b->fg_colors, sizeof(color_type) * a->xnum) == 0 && \
memcmp(a->decoration_fg, b->decoration_fg, sizeof(decoration_type) * a->xnum) == 0 && \ memcmp(a->bg_colors, b->bg_colors, sizeof(color_type) * a->xnum) == 0 && \
memcmp(a->decoration_fg, b->decoration_fg, sizeof(color_type) * a->xnum) == 0 && \
memcmp(a->combining_chars, b->combining_chars, sizeof(combining_type) * a->xnum) == 0; memcmp(a->combining_chars, b->combining_chars, sizeof(combining_type) * a->xnum) == 0;
} }
@ -483,7 +477,6 @@ static PyMethodDef methods[] = {
METHOD(as_ansi, METH_NOARGS) METHOD(as_ansi, METH_NOARGS)
METHOD(is_continued, METH_NOARGS) METHOD(is_continued, METH_NOARGS)
METHOD(width, METH_O) METHOD(width, METH_O)
METHOD(basic_cell_data, METH_O)
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };
@ -522,7 +515,8 @@ copy_char(Line* self, PyObject *args) {
return NULL; return NULL;
} }
to->chars[dest] = self->chars[src]; to->chars[dest] = self->chars[src];
to->colors[dest] = self->colors[src]; to->fg_colors[dest] = self->fg_colors[src];
to->bg_colors[dest] = self->bg_colors[src];
to->decoration_fg[dest] = self->decoration_fg[src]; to->decoration_fg[dest] = self->decoration_fg[src];
to->combining_chars[dest] = self->combining_chars[src]; to->combining_chars[dest] = self->combining_chars[src];
Py_RETURN_NONE; Py_RETURN_NONE;

View File

@ -43,8 +43,9 @@
static inline void copy_range(Line *src, index_type src_at, Line* dest, index_type dest_at, index_type num) { static inline void copy_range(Line *src, index_type src_at, Line* dest, index_type dest_at, index_type num) {
memcpy(dest->chars + dest_at, src->chars + src_at, num * sizeof(char_type)); memcpy(dest->chars + dest_at, src->chars + src_at, num * sizeof(char_type));
memcpy(dest->colors + dest_at, src->colors + src_at, num * sizeof(color_type)); memcpy(dest->fg_colors + dest_at, src->fg_colors + src_at, num * sizeof(color_type));
memcpy(dest->decoration_fg + dest_at, src->decoration_fg + src_at, num * sizeof(decoration_type)); memcpy(dest->bg_colors + dest_at, src->bg_colors + src_at, num * sizeof(color_type));
memcpy(dest->decoration_fg + dest_at, src->decoration_fg + src_at, num * sizeof(color_type));
memcpy(dest->combining_chars + dest_at, src->combining_chars + src_at, num * sizeof(combining_type)); memcpy(dest->combining_chars + dest_at, src->combining_chars + src_at, num * sizeof(combining_type));
} }

View File

@ -160,8 +160,8 @@ update_cell_range_data(ScreenModes *modes, SpriteMap *self, Line *line, unsigned
data[offset] = sp->x; data[offset] = sp->x;
data[offset+1] = sp->y; data[offset+1] = sp->y;
data[offset+2] = sp->z; data[offset+2] = sp->z;
data[offset+(reverse ? 4 : 3)] = to_color(color_profile, line->colors[i] & COL_MASK, default_fg); data[offset+(reverse ? 4 : 3)] = to_color(color_profile, line->fg_colors[i] & COL_MASK, default_fg);
data[offset+(reverse ? 3 : 4)] = to_color(color_profile, line->colors[i] >> COL_SHIFT, default_bg); data[offset+(reverse ? 3 : 4)] = to_color(color_profile, line->bg_colors[i] & COL_MASK, default_bg);
unsigned int decoration_fg = to_color(color_profile, line->decoration_fg[i] & COL_MASK, data[offset+3]); unsigned int decoration_fg = to_color(color_profile, line->decoration_fg[i] & COL_MASK, data[offset+3]);
data[offset+5] = (decoration_fg & COL_MASK) | (decoration << 24) | (strikethrough << 26); data[offset+5] = (decoration_fg & COL_MASK) | (decoration << 24) | (strikethrough << 26);
previous_ch = ch; previous_width = (attrs) & WIDTH_MASK; previous_ch = ch; previous_width = (attrs) & WIDTH_MASK;