Track sprite positions in the Cell structure

This commit is contained in:
Kovid Goyal 2017-09-08 13:51:35 +05:30
parent a8d5ad2c1a
commit c4680aae2c
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 58 additions and 5 deletions

View File

@ -59,6 +59,7 @@ typedef uint16_t sprite_index;
#define UTF8_REJECT 1 #define UTF8_REJECT 1
#define UNDERCURL_CODE 6 #define UNDERCURL_CODE 6
#define DECORATION_FG_CODE 58 #define DECORATION_FG_CODE 58
#define CHAR_IS_BLANK(ch) ((ch & CHAR_MASK) == 32 || (ch & CHAR_MASK) == 0)
#define CURSOR_BLOCK 1 #define CURSOR_BLOCK 1
#define CURSOR_BEAM 2 #define CURSOR_BEAM 2
@ -130,6 +131,7 @@ typedef struct {
char_type ch; char_type ch;
color_type fg, bg, decoration_fg; color_type fg, bg, decoration_fg;
combining_type cc; combining_type cc;
sprite_index sprite_x, sprite_y, sprite_z;
} Cell; } Cell;
typedef struct { typedef struct {
@ -288,11 +290,16 @@ typedef struct {
} ChildMonitor; } ChildMonitor;
PyTypeObject ChildMonitor_Type; PyTypeObject ChildMonitor_Type;
#define clear_sprite_position(cell) (cell).sprite_x = 0; (cell).sprite_y = 0; (cell).sprite_z = 0;
#define left_shift_line(line, at, num) \ #define left_shift_line(line, at, num) \
for(index_type __i__ = (at); __i__ < (line)->xnum - (num); __i__++) { \ for(index_type __i__ = (at); __i__ < (line)->xnum - (num); __i__++) { \
COPY_CELL(line, __i__ + (num), line, __i__) \ COPY_CELL(line, __i__ + (num), line, __i__) \
} \ } \
if ((((line)->cells[(at)].ch >> ATTRS_SHIFT) & WIDTH_MASK) != 1) (line)->cells[(at)].ch = (1 << ATTRS_SHIFT) | BLANK_CHAR; if ((((line)->cells[(at)].ch >> ATTRS_SHIFT) & WIDTH_MASK) != 1) { \
(line)->cells[(at)].ch = (1 << ATTRS_SHIFT) | BLANK_CHAR; \
clear_sprite_position((line)->cells[(at)]); \
}
// Global functions // Global functions
@ -324,6 +331,7 @@ Cursor* cursor_copy(Cursor*);
void cursor_copy_to(Cursor *src, Cursor *dest); void cursor_copy_to(Cursor *src, Cursor *dest);
void cursor_reset_display_attrs(Cursor*); void cursor_reset_display_attrs(Cursor*);
bool update_cell_range_data(ScreenModes *modes, Line *, unsigned int, unsigned int, unsigned int *); bool update_cell_range_data(ScreenModes *modes, Line *, unsigned int, unsigned int, unsigned int *);
void set_sprite_position(Cell *cell, Cell *previous_cell);
PyObject* line_text_at(char_type, combining_type); PyObject* line_text_at(char_type, combining_type);
void line_clear_text(Line *self, unsigned int at, unsigned int num, int ch); void line_clear_text(Line *self, unsigned int at, unsigned int num, int ch);

View File

@ -219,11 +219,14 @@ width(Line *self, PyObject *val) {
return PyLong_FromUnsignedLong((unsigned long) (attrs & WIDTH_MASK)); return PyLong_FromUnsignedLong((unsigned long) (attrs & WIDTH_MASK));
} }
#define set_sprite_position_at(x) set_sprite_position(self->cells + x, x == 0 ? NULL : self->cells + x - 1);
void void
line_add_combining_char(Line *self, uint32_t ch, unsigned int x) { line_add_combining_char(Line *self, uint32_t ch, unsigned int x) {
combining_type c = self->cells[x].cc; combining_type c = self->cells[x].cc;
if (c & CC_MASK) self->cells[x].cc = (c & CC_MASK) | ( (ch & CC_MASK) << CC_SHIFT ); if (c & CC_MASK) self->cells[x].cc = (c & CC_MASK) | ( (ch & CC_MASK) << CC_SHIFT );
else self->cells[x].cc = ch & CC_MASK; else self->cells[x].cc = ch & CC_MASK;
set_sprite_position_at(x);
} }
static PyObject* static PyObject*
@ -273,6 +276,7 @@ set_text(Line* self, PyObject *args) {
self->cells[i].bg = bg; self->cells[i].bg = bg;
self->cells[i].decoration_fg = dfg; self->cells[i].decoration_fg = dfg;
self->cells[i].cc = 0; self->cells[i].cc = 0;
set_sprite_position_at(i);
} }
Py_RETURN_NONE; Py_RETURN_NONE;
@ -302,9 +306,16 @@ cursor_from(Line* self, PyObject *args) {
void void
line_clear_text(Line *self, unsigned int at, unsigned int num, int ch) { line_clear_text(Line *self, unsigned int at, unsigned int num, int ch) {
const char_type repl = ((char_type)ch & CHAR_MASK) | (1 << ATTRS_SHIFT); const char_type repl = ((char_type)ch & CHAR_MASK) | (1 << ATTRS_SHIFT);
for (index_type i = at; i < MIN(self->xnum, at + num); i++) { #define PREFIX \
self->cells[i].ch = (self->cells[i].ch & ATTRS_MASK_WITHOUT_WIDTH) | repl; for (index_type i = at; i < MIN(self->xnum, at + num); i++) { \
self->cells[i].cc = 0; self->cells[i].ch = (self->cells[i].ch & ATTRS_MASK_WITHOUT_WIDTH) | repl; \
self->cells[i].cc = 0;
if (CHAR_IS_BLANK(ch)) {
PREFIX
clear_sprite_position(self->cells[i]); }
} else {
PREFIX
set_sprite_position_at(i)}
} }
} }
@ -329,9 +340,11 @@ line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num,
if (clear_char) { if (clear_char) {
self->cells[i].ch = BLANK_CHAR | attrs; self->cells[i].ch = BLANK_CHAR | attrs;
self->cells[i].cc = 0; self->cells[i].cc = 0;
clear_sprite_position(self->cells[i]);
} else { } else {
char_type w = ((self->cells[i].ch >> ATTRS_SHIFT) & WIDTH_MASK) << ATTRS_SHIFT; char_type w = ((self->cells[i].ch >> ATTRS_SHIFT) & WIDTH_MASK) << ATTRS_SHIFT;
self->cells[i].ch = (self->cells[i].ch & CHAR_MASK) | attrs | w; self->cells[i].ch = (self->cells[i].ch & CHAR_MASK) | attrs | w;
set_sprite_position_at(i);
} }
self->cells[i].fg = fg; self->cells[i].bg = bg; self->cells[i].fg = fg; self->cells[i].bg = bg;
self->cells[i].decoration_fg = dfg; self->cells[i].decoration_fg = dfg;
@ -355,7 +368,10 @@ void line_right_shift(Line *self, unsigned int at, unsigned int num) {
} }
// Check if a wide character was split at the right edge // Check if a wide character was split at the right edge
char_type w = (self->cells[self->xnum - 1].ch >> ATTRS_SHIFT) & WIDTH_MASK; char_type w = (self->cells[self->xnum - 1].ch >> ATTRS_SHIFT) & WIDTH_MASK;
if (w != 1) self->cells[self->xnum - 1].ch = (1 << ATTRS_SHIFT) | BLANK_CHAR; if (w != 1) {
self->cells[self->xnum - 1].ch = (1 << ATTRS_SHIFT) | BLANK_CHAR;
clear_sprite_position(self->cells[self->xnum - 1]);
}
} }
static PyObject* static PyObject*
@ -399,6 +415,8 @@ line_set_char(Line *self, unsigned int at, uint32_t ch, unsigned int width, Curs
} }
self->cells[at].ch = (ch & CHAR_MASK) | attrs; self->cells[at].ch = (ch & CHAR_MASK) | attrs;
self->cells[at].cc = 0; self->cells[at].cc = 0;
if (CHAR_IS_BLANK(ch)) { clear_sprite_position(self->cells[at]); }
else set_sprite_position_at(at);
} }
static PyObject* static PyObject*

View File

@ -8,12 +8,23 @@
#include "data-types.h" #include "data-types.h"
static inline void
update_sprites_in_line(Cell *cells, index_type xnum) {
if (LIKELY(xnum > 0)) {
set_sprite_position(cells, NULL);
for (index_type i = 1; i < xnum; i++) {
set_sprite_position(cells + i, cells + i - 1);
}
}
}
static inline void static inline void
set_attribute_on_line(Cell *cells, uint32_t shift, uint32_t val, index_type xnum) { set_attribute_on_line(Cell *cells, uint32_t shift, uint32_t val, index_type xnum) {
uint32_t mask = shift == DECORATION_SHIFT ? 3 : 1; uint32_t mask = shift == DECORATION_SHIFT ? 3 : 1;
uint32_t aval = (val & mask) << (ATTRS_SHIFT + shift); uint32_t aval = (val & mask) << (ATTRS_SHIFT + shift);
mask = ~(mask << (ATTRS_SHIFT + shift)); mask = ~(mask << (ATTRS_SHIFT + shift));
for (index_type i = 0; i < xnum; i++) cells[i].ch = (cells[i].ch & mask) | aval; for (index_type i = 0; i < xnum; i++) cells[i].ch = (cells[i].ch & mask) | aval;
if (shift == BOLD_SHIFT || shift == ITALIC_SHIFT) update_sprites_in_line(cells, xnum);
} }
static inline void static inline void
@ -28,6 +39,7 @@ copy_line(const Line *src, Line *dest) {
static inline void static inline void
clear_chars_in_line(Cell *cells, index_type xnum, char_type ch) { clear_chars_in_line(Cell *cells, index_type xnum, char_type ch) {
// Clear only the char part of each cell, the rest must have been cleared by a memset or similar
char_type c = (1 << ATTRS_SHIFT) | ch; char_type c = (1 << ATTRS_SHIFT) | ch;
for (index_type i = 0; i < xnum; i++) cells[i].ch = c; for (index_type i = 0; i < xnum; i++) cells[i].ch = c;
} }

View File

@ -99,6 +99,21 @@ sprite_map_position_for(char_type ch, combining_type cc, bool is_second, int *er
return s; return s;
} }
void
set_sprite_position(Cell *cell, Cell *previous_cell) {
SpritePosition *sp;
static int error;
if (UNLIKELY(previous_cell != NULL && ((previous_cell->ch >> ATTRS_SHIFT) & WIDTH_MASK) == 2)) {
sp = sprite_map_position_for(previous_cell->ch, 0, true, &error);
} else {
sp = sprite_map_position_for(cell->ch, cell->cc, false, &error);
}
cell->sprite_x = sp->x;
cell->sprite_y = sp->y;
cell->sprite_z = sp->z;
}
PyObject* PyObject*
sprite_map_increment() { sprite_map_increment() {
#define increment_doc "Increment the current position and return the old (x, y, z) values" #define increment_doc "Increment the current position and return the old (x, y, z) values"