mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-13 08:26:56 +00:00
fix ligature
This commit is contained in:
parent
851ec96979
commit
a36634e6e1
1 changed files with 63 additions and 14 deletions
|
|
@ -1425,13 +1425,30 @@ ligature_type_from_glyph_name(const char *glyph_name, SpacerStrategy strategy) {
|
|||
|
||||
#define G(x) (group_state.x)
|
||||
|
||||
static bool
|
||||
shaped_glyphs_have_iosevka_join_names(hb_font_t *hbf) {
|
||||
char glyph_name[128]; glyph_name[arraysz(glyph_name)-1] = 0;
|
||||
for (unsigned i = 0; i < G(num_glyphs); i++) {
|
||||
glyph_index glyph_id = G(info)[i].codepoint;
|
||||
hb_font_glyph_to_string(hbf, glyph_id, glyph_name, arraysz(glyph_name)-1);
|
||||
char *dot = strrchr(glyph_name, '.');
|
||||
if (dot && (!strcmp(dot, ".join-l") || !strcmp(dot, ".join-r") || !strcmp(dot, ".join-m"))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
set_ascii_cells(CPUCell *cpu_cells, const char *text, size_t len) {
|
||||
for (size_t i = 0; i < len; i++) cell_set_char(cpu_cells + i, text[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
detect_spacer_strategy(hb_font_t *hbf, Font *font, const TextCache *tc) {
|
||||
CPUCell cpu_cells[3] = {0};
|
||||
for (unsigned i = 0; i < arraysz(cpu_cells); i++) cell_set_char(&cpu_cells[i], '=');
|
||||
CPUCell cpu_cells[5] = {0};
|
||||
set_ascii_cells(cpu_cells, "===", 3);
|
||||
const CellAttrs w1 = {0};
|
||||
GPUCell gpu_cells[3] = {{.attrs = w1}, {.attrs = w1}, {.attrs = w1}};
|
||||
shape(cpu_cells, gpu_cells, arraysz(cpu_cells), hbf, font, false, tc);
|
||||
GPUCell gpu_cells[5] = {{.attrs = w1}, {.attrs = w1}, {.attrs = w1}, {.attrs = w1}, {.attrs = w1}};
|
||||
shape(cpu_cells, gpu_cells, 3, hbf, font, false, tc);
|
||||
font->spacer_strategy = SPACERS_BEFORE;
|
||||
if (G(num_glyphs) > 1) {
|
||||
glyph_index glyph_id = G(info)[G(num_glyphs) - 1].codepoint;
|
||||
|
|
@ -1439,14 +1456,16 @@ detect_spacer_strategy(hb_font_t *hbf, Font *font, const TextCache *tc) {
|
|||
bool is_empty = is_special && is_empty_glyph(glyph_id, font);
|
||||
if (is_empty) font->spacer_strategy = SPACERS_AFTER;
|
||||
}
|
||||
set_ascii_cells(cpu_cells, "==", 2);
|
||||
shape(cpu_cells, gpu_cells, 2, hbf, font, false, tc);
|
||||
if (G(num_glyphs)) {
|
||||
char glyph_name[128]; glyph_name[arraysz(glyph_name)-1] = 0;
|
||||
for (unsigned i = 0; i < G(num_glyphs); i++) {
|
||||
glyph_index glyph_id = G(info)[i].codepoint;
|
||||
hb_font_glyph_to_string(hbf, glyph_id, glyph_name, arraysz(glyph_name)-1);
|
||||
char *dot = strrchr(glyph_name, '.');
|
||||
if (dot && (!strcmp(dot, ".join-l") || !strcmp(dot, ".join-r") || !strcmp(dot, ".join-m"))) {
|
||||
if (shaped_glyphs_have_iosevka_join_names(hbf)) font->spacer_strategy = SPACERS_IOSEVKA;
|
||||
if (font->spacer_strategy != SPACERS_IOSEVKA) {
|
||||
static const char *samples[] = {"->", "<-", "<<=", "<==>"};
|
||||
for (size_t s = 0; s < arraysz(samples); s++) {
|
||||
size_t len = strlen(samples[s]);
|
||||
set_ascii_cells(cpu_cells, samples[s], len);
|
||||
shape(cpu_cells, gpu_cells, len, hbf, font, false, tc);
|
||||
if (shaped_glyphs_have_iosevka_join_names(hbf)) {
|
||||
font->spacer_strategy = SPACERS_IOSEVKA;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1456,8 +1475,8 @@ detect_spacer_strategy(hb_font_t *hbf, Font *font, const TextCache *tc) {
|
|||
// If spacer_strategy is still default, check ### glyph to confirm strategy
|
||||
// https://github.com/kovidgoyal/kitty/issues/4721
|
||||
if (font->spacer_strategy == SPACERS_BEFORE) {
|
||||
for (unsigned i = 0; i < arraysz(cpu_cells); i++) cell_set_char(&cpu_cells[i], '#');
|
||||
shape(cpu_cells, gpu_cells, arraysz(cpu_cells), hbf, font, false, tc);
|
||||
set_ascii_cells(cpu_cells, "###", 3);
|
||||
shape(cpu_cells, gpu_cells, 3, hbf, font, false, tc);
|
||||
if (G(num_glyphs) > 1) {
|
||||
glyph_index glyph_id = G(info)[G(num_glyphs) - 1].codepoint;
|
||||
bool is_special = is_special_glyph(glyph_id, font, &G(current_cell_data));
|
||||
|
|
@ -1474,6 +1493,33 @@ ligature_type_for_glyph(hb_font_t *hbf, glyph_index glyph_id, SpacerStrategy str
|
|||
return ligature_type_from_glyph_name(glyph_name, strategy);
|
||||
}
|
||||
|
||||
static bool
|
||||
dot_liga_final_component(const char *glyph_name, char *output, size_t output_sz) {
|
||||
static const char suffix[] = ".liga";
|
||||
const size_t suffix_len = sizeof(suffix) - 1;
|
||||
size_t len = strlen(glyph_name);
|
||||
if (len <= suffix_len || strcmp(glyph_name + len - suffix_len, suffix) != 0) return false;
|
||||
len -= suffix_len;
|
||||
const char *start = glyph_name;
|
||||
for (const char *p = glyph_name; p < glyph_name + len; p++) {
|
||||
if (*p == '_') start = p + 1;
|
||||
}
|
||||
const size_t component_len = (size_t)(glyph_name + len - start);
|
||||
if (!component_len || component_len >= output_sz) return false;
|
||||
memcpy(output, start, component_len);
|
||||
output[component_len] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
glyph_matches_dot_liga_final_component(hb_font_t *hbf, glyph_index dot_liga_glyph_id, glyph_index current_glyph_id) {
|
||||
char dot_liga_name[128] = {0}, current_name[128] = {0}, final_component[128] = {0};
|
||||
hb_font_glyph_to_string(hbf, dot_liga_glyph_id, dot_liga_name, sizeof(dot_liga_name) - 1);
|
||||
if (!dot_liga_final_component(dot_liga_name, final_component, sizeof(final_component))) return false;
|
||||
hb_font_glyph_to_string(hbf, current_glyph_id, current_name, sizeof(current_name) - 1);
|
||||
return strcmp(final_component, current_name) == 0;
|
||||
}
|
||||
|
||||
#define L INFINITE_LIGATURE_START
|
||||
#define M INFINITE_LIGATURE_MIDDLE
|
||||
#define R INFINITE_LIGATURE_END
|
||||
|
|
@ -1618,7 +1664,10 @@ group_normal(Font *font, hb_font_t *hbf, const TextCache *tc, ListOfChars *lc) {
|
|||
else if (font->spacer_strategy == SPACERS_BEFORE) add_to_current_group = G(prev_was_empty);
|
||||
else add_to_current_group = is_empty;
|
||||
} else {
|
||||
add_to_current_group = !G(prev_was_special) || !current_group->num_cells;
|
||||
add_to_current_group = !G(prev_was_special) || !current_group->num_cells || (
|
||||
G(prev_was_empty) && current_group->has_special_glyph &&
|
||||
glyph_matches_dot_liga_final_component(hbf, G(info)[current_group->first_glyph_idx].codepoint, glyph_id)
|
||||
);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue