Start work on horizontal align for multicells
This commit is contained in:
parent
714910382b
commit
15f711d6b5
9 changed files with 47 additions and 24 deletions
|
|
@ -79,6 +79,8 @@ There are only a handful of metadata keys, defined in the table below:
|
|||
|
||||
"v", "Integer from 0 to 2", "0", "The vertical alignment to use for fractionally scaled text. ``0`` - top, ``1`` - bottom, ``2`` - centered"
|
||||
|
||||
"h", "Integer from 0 to 2", "0", "The horizontal alignment to use for fractionally scaled text. ``0`` - left, ``1`` - right, ``2`` - centered"
|
||||
|
||||
|
||||
How it works
|
||||
------------------
|
||||
|
|
|
|||
|
|
@ -322,6 +322,7 @@ def parsers() -> None:
|
|||
'n': ('subscale_n', 'uint'),
|
||||
'd': ('subscale_d', 'uint'),
|
||||
'v': ('vertical_align', 'uint'),
|
||||
'h': ('horizontal_align', 'uint'),
|
||||
}
|
||||
text = generate(
|
||||
'parse_multicell_code', 'screen_handle_multicell_command', 'multicell_command', keymap, 'MultiCellCommand',
|
||||
|
|
|
|||
|
|
@ -34,7 +34,11 @@ typedef struct {
|
|||
} GPUSpriteTracker;
|
||||
|
||||
typedef struct RunFont {
|
||||
unsigned scale, subscale_n, subscale_d, vertical_align, multicell_y;
|
||||
unsigned scale, subscale_n, subscale_d, multicell_y;
|
||||
union {
|
||||
struct { uint8_t vertical: 4; uint8_t horizontal: 4; };
|
||||
uint8_t val;
|
||||
} align;
|
||||
ssize_t font_idx;
|
||||
} RunFont;
|
||||
|
||||
|
|
@ -92,7 +96,7 @@ typedef struct ScaledFontData {
|
|||
#include "kitty-verstable.h"
|
||||
|
||||
typedef union DecorationsKey {
|
||||
struct { uint8_t scale : 8, subscale_n : 8, subscale_d : 8, vertical_align : 8, multicell_y : 8, u1 : 8, u2 : 8, u3 : 8; };
|
||||
struct { uint8_t scale : 8, subscale_n : 8, subscale_d : 8, align : 8, multicell_y : 8, u1 : 8, u2 : 8, u3 : 8; };
|
||||
uint64_t val;
|
||||
} DecorationsKey;
|
||||
static_assert(sizeof(DecorationsKey) == sizeof(uint64_t), "Fix the ordering of DecorationsKey");
|
||||
|
|
@ -322,7 +326,7 @@ sprite_position_for(FontGroup *fg, RunFont rf, glyph_index *glyphs, unsigned gly
|
|||
uint8_t subscale = ((rf.subscale_n & 0xf) << 4) | (rf.subscale_d & 0xf);
|
||||
SpritePosition *s = find_or_create_sprite_position(
|
||||
font->sprite_position_hash_table, glyphs, glyph_count, ligature_index, cell_count,
|
||||
rf.scale, subscale, rf.multicell_y, rf.vertical_align, &created);
|
||||
rf.scale, subscale, rf.multicell_y, rf.align.val, &created);
|
||||
if (!s) { PyErr_NoMemory(); return NULL; }
|
||||
return s;
|
||||
}
|
||||
|
|
@ -905,7 +909,7 @@ calculate_regions_for_line(RunFont rf, unsigned cell_height, Region *src, Region
|
|||
unsigned src_height = src->bottom;
|
||||
Region src_in_full_coords = *src; unsigned full_dest_height = cell_height * rf.scale;
|
||||
if (rf.subscale_n && rf.subscale_d) {
|
||||
switch(rf.vertical_align) {
|
||||
switch(rf.align.vertical) {
|
||||
case 0: break; // top aligned no change
|
||||
case 1: // bottom aligned
|
||||
src_in_full_coords.top = full_dest_height - src_height;
|
||||
|
|
@ -1012,7 +1016,7 @@ render_decorations(FontGroup *fg, Region src, Region dest, FontCellMetrics scale
|
|||
|
||||
static DecorationMetadata
|
||||
index_for_decorations(FontGroup *fg, RunFont rf, Region src, Region dest, FontCellMetrics scaled_metrics) {
|
||||
const DecorationsKey key = {.scale=rf.scale, .subscale_n = rf.subscale_n, .subscale_d = rf.subscale_d, .vertical_align = rf.vertical_align, .multicell_y = rf.multicell_y, .u1 = 0, .u2 = 0, .u3 = 0 };
|
||||
const DecorationsKey key = {.scale=rf.scale, .subscale_n = rf.subscale_n, .subscale_d = rf.subscale_d, .align = rf.align.val, .multicell_y = rf.multicell_y, .u1 = 0, .u2 = 0, .u3 = 0 };
|
||||
decorations_index_map_t_itr i = vt_get(&fg->decorations_index_map, key);
|
||||
if (!vt_is_end(i)) return i.data->val;
|
||||
DecorationMetadata val;
|
||||
|
|
@ -1799,7 +1803,7 @@ cell_cap_for_codepoint(const char_type cp) {
|
|||
|
||||
static bool
|
||||
run_fonts_are_equal(const RunFont *a, const RunFont *b) {
|
||||
return a->font_idx == b->font_idx && a->scale == b->scale && a->subscale_n == b->subscale_n && a->subscale_d == b->subscale_d && a->vertical_align == b->vertical_align && a->multicell_y == b->multicell_y;
|
||||
return a->font_idx == b->font_idx && a->scale == b->scale && a->subscale_n == b->subscale_n && a->subscale_d == b->subscale_d && a->align.val == b->align.val && a->multicell_y == b->multicell_y;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -1833,7 +1837,8 @@ render_line(FONTS_DATA_HANDLE fg_, Line *line, index_type lnum, Cursor *cursor,
|
|||
i += mcd_x_limit(cpu_cell) - cpu_cell->x - 1;
|
||||
continue;
|
||||
}
|
||||
cell_font.scale = cpu_cell->scale; cell_font.subscale_n = cpu_cell->subscale_n; cell_font.subscale_d = cpu_cell->subscale_d; cell_font.vertical_align = cpu_cell->vertical_align;
|
||||
cell_font.scale = cpu_cell->scale; cell_font.subscale_n = cpu_cell->subscale_n; cell_font.subscale_d = cpu_cell->subscale_d;
|
||||
cell_font.align.vertical = cpu_cell->valign; cell_font.align.horizontal = cpu_cell->halign;
|
||||
cell_font.multicell_y = cpu_cell->y;
|
||||
}
|
||||
text_in_cell(cpu_cell, line->text_cache, lc);
|
||||
|
|
|
|||
11
kitty/line.c
11
kitty/line.c
|
|
@ -78,8 +78,11 @@ write_multicell_ansi_prefix(ANSILineState *s, const CPUCell *mcd) {
|
|||
if (mcd->subscale_d) {
|
||||
w('d'); w('='); nonnegative_integer_as_utf32(mcd->subscale_d, s->output_buf); w(':');
|
||||
}
|
||||
if (mcd->vertical_align) {
|
||||
w('v'); w('='); nonnegative_integer_as_utf32(mcd->vertical_align, s->output_buf); w(':');
|
||||
if (mcd->valign) {
|
||||
w('v'); w('='); nonnegative_integer_as_utf32(mcd->valign, s->output_buf); w(':');
|
||||
}
|
||||
if (mcd->halign) {
|
||||
w('h'); w('='); nonnegative_integer_as_utf32(mcd->halign, s->output_buf); w(':');
|
||||
}
|
||||
if (s->output_buf->buf[s->output_buf->len - 1] == ':') s->output_buf->len--;
|
||||
w(';');
|
||||
|
|
@ -98,12 +101,12 @@ close_multicell(ANSILineState *s) {
|
|||
|
||||
static void
|
||||
start_multicell_if_needed(ANSILineState *s, const CPUCell *c) {
|
||||
if (!c->natural_width || c->scale > 1 || c->subscale_n || c->subscale_d || c->vertical_align) write_multicell_ansi_prefix(s, c);
|
||||
if (!c->natural_width || c->scale > 1 || c->subscale_n || c->subscale_d || c->valign || c->halign) write_multicell_ansi_prefix(s, c);
|
||||
}
|
||||
|
||||
static bool
|
||||
multicell_is_continuation_of_previous(const CPUCell *prev, const CPUCell *curr) {
|
||||
if (prev->scale != curr->scale || prev->subscale_n != curr->subscale_n || prev->subscale_d != curr->subscale_d || prev->vertical_align != curr->vertical_align) return false;
|
||||
if (prev->scale != curr->scale || prev->subscale_n != curr->subscale_n || prev->subscale_d != curr->subscale_d || prev->valign != curr->valign || prev->halign != curr->halign) return false;
|
||||
if (prev->natural_width) return curr->natural_width;
|
||||
return prev->width == curr->width && !curr->natural_width;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ static_assert(sizeof(GPUCell) == 20, "Fix the ordering of GPUCell");
|
|||
#define WIDTH_BITS 3
|
||||
#define SUBSCALE_BITS 4
|
||||
#define VALIGN_BITS 2
|
||||
#define HALIGN_BITS 2
|
||||
|
||||
typedef union CPUCell {
|
||||
struct {
|
||||
|
|
@ -59,9 +60,10 @@ typedef union CPUCell {
|
|||
char_type x : WIDTH_BITS + SCALE_BITS;
|
||||
char_type y : SCALE_BITS;
|
||||
char_type width: WIDTH_BITS;
|
||||
char_type vertical_align: VALIGN_BITS;
|
||||
char_type valign: VALIGN_BITS;
|
||||
char_type halign: HALIGN_BITS;
|
||||
char_type temp_flag: 1;
|
||||
char_type : 17;
|
||||
char_type : 15;
|
||||
};
|
||||
struct {
|
||||
char_type ch_and_idx: sizeof(char_type) * 8;
|
||||
|
|
@ -95,7 +97,7 @@ typedef struct {
|
|||
} Line;
|
||||
|
||||
typedef struct MultiCellCommand {
|
||||
unsigned int width, scale, subscale_n, subscale_d, vertical_align;
|
||||
unsigned int width, scale, subscale_n, subscale_d, vertical_align, horizontal_align;
|
||||
size_t payload_sz;
|
||||
} MultiCellCommand;
|
||||
|
||||
|
|
|
|||
12
kitty/parse-multicell-command.h
generated
12
kitty/parse-multicell-command.h
generated
|
|
@ -23,7 +23,8 @@ static inline void parse_multicell_code(PS *self, uint8_t *parser_buf,
|
|||
scale = 's',
|
||||
subscale_n = 'n',
|
||||
subscale_d = 'd',
|
||||
vertical_align = 'v'
|
||||
vertical_align = 'v',
|
||||
horizontal_align = 'h'
|
||||
};
|
||||
|
||||
enum KEYS key = 'a';
|
||||
|
|
@ -51,6 +52,9 @@ static inline void parse_multicell_code(PS *self, uint8_t *parser_buf,
|
|||
case vertical_align:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case horizontal_align:
|
||||
value_state = UINT;
|
||||
break;
|
||||
default:
|
||||
REPORT_ERROR("Malformed MultiCellCommand control block, invalid key "
|
||||
"character: 0x%x",
|
||||
|
|
@ -131,6 +135,7 @@ static inline void parse_multicell_code(PS *self, uint8_t *parser_buf,
|
|||
U(subscale_n);
|
||||
U(subscale_d);
|
||||
U(vertical_align);
|
||||
U(horizontal_align);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -183,12 +188,13 @@ static inline void parse_multicell_code(PS *self, uint8_t *parser_buf,
|
|||
}
|
||||
|
||||
REPORT_VA_COMMAND(
|
||||
"K s { sI sI sI sI sI ss#}", self->window_id, "multicell_command",
|
||||
"K s { sI sI sI sI sI sI ss#}", self->window_id, "multicell_command",
|
||||
|
||||
"width", (unsigned int)g.width, "scale", (unsigned int)g.scale,
|
||||
"subscale_n", (unsigned int)g.subscale_n, "subscale_d",
|
||||
(unsigned int)g.subscale_d, "vertical_align",
|
||||
(unsigned int)g.vertical_align,
|
||||
(unsigned int)g.vertical_align, "horizontal_align",
|
||||
(unsigned int)g.horizontal_align,
|
||||
|
||||
"", (char *)parser_buf + payload_start, g.payload_sz);
|
||||
|
||||
|
|
|
|||
|
|
@ -1258,7 +1258,8 @@ screen_handle_multicell_command(Screen *self, const MultiCellCommand *cmd, const
|
|||
CPUCell mcd = {
|
||||
.width=MIN(cmd->width, M(WIDTH_BITS)), .scale=MAX(1u, MIN(cmd->scale, M(SCALE_BITS))),
|
||||
.subscale_n=MIN(cmd->subscale_n, M(SUBSCALE_BITS)), .subscale_d=MIN(cmd->subscale_d, M(SUBSCALE_BITS)),
|
||||
.vertical_align=MIN(cmd->vertical_align, M(VALIGN_BITS)), .is_multicell=true
|
||||
.valign=MIN(cmd->vertical_align, M(VALIGN_BITS)), .halign=MIN(cmd->horizontal_align, M(HALIGN_BITS)),
|
||||
.is_multicell=true
|
||||
};
|
||||
#undef M
|
||||
if (mcd.width) handle_fixed_width_multicell_command(self, mcd, self->lc);
|
||||
|
|
@ -5389,10 +5390,10 @@ test_parse_written_data(Screen *screen, PyObject *args) {
|
|||
|
||||
static PyObject*
|
||||
multicell_data_as_dict(CPUCell mcd) {
|
||||
return Py_BuildValue("{sI sI sI sI sO sI}",
|
||||
return Py_BuildValue("{sI sI sI sI sO sI sI}",
|
||||
"scale", (unsigned int)mcd.scale, "width", (unsigned int)mcd.width,
|
||||
"subscale_n", (unsigned int)mcd.subscale_n, "subscale_d", (unsigned int)mcd.subscale_d,
|
||||
"natural_width", mcd.natural_width ? Py_True : Py_False, "vertical_align", mcd.vertical_align);
|
||||
"natural_width", mcd.natural_width ? Py_True : Py_False, "vertical_align", mcd.valign, "horizontal_align", mcd.halign);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
|
|
|
|||
|
|
@ -36,8 +36,10 @@ def parse_bytes(screen, data, dump_callback=None):
|
|||
screen.test_parse_written_data(dump_callback)
|
||||
|
||||
|
||||
def draw_multicell(screen: Screen, text: str, width: int = 0, scale: int = 1, subscale_n: int = 0, subscale_d: int = 0, vertical_align: int = 0) -> None:
|
||||
cmd = f'\x1b]{TEXT_SIZE_CODE};w={width}:s={scale}:n={subscale_n}:d={subscale_d}:v={vertical_align};{text}\a'
|
||||
def draw_multicell(
|
||||
screen: Screen, text: str, width: int = 0, scale: int = 1, subscale_n: int = 0, subscale_d: int = 0, vertical_align: int = 0, horizontal_align: int = 0
|
||||
) -> None:
|
||||
cmd = f'\x1b]{TEXT_SIZE_CODE};w={width}:s={scale}:n={subscale_n}:d={subscale_d}:v={vertical_align}:h={horizontal_align};{text}\a'
|
||||
parse_bytes(screen, cmd.encode())
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ def ae(key):
|
|||
ae('subscale_n')
|
||||
ae('subscale_d')
|
||||
ae('vertical_align')
|
||||
ae('horizontal_align')
|
||||
ae('text')
|
||||
ae('natural_width')
|
||||
ae('next_char_was_wrapped')
|
||||
|
|
@ -448,8 +449,8 @@ def ta(expected):
|
|||
s.reset()
|
||||
|
||||
s.reset()
|
||||
multicell(s, 'a', width=2, scale=3, subscale_n=1, subscale_d=2, vertical_align=1)
|
||||
ta(f'\x1b]{TEXT_SIZE_CODE};w=2:s=3:n=1:d=2:v=1;a\x07')
|
||||
multicell(s, 'a', width=2, scale=3, subscale_n=1, subscale_d=2, vertical_align=3, horizontal_align=3)
|
||||
ta(f'\x1b]{TEXT_SIZE_CODE};w=2:s=3:n=1:d=2:v=3:h=3;a\x07')
|
||||
s.draw('a')
|
||||
multicell(s, 'b', width=2)
|
||||
s.draw('c')
|
||||
|
|
|
|||
Loading…
Reference in a new issue