Skip to content

Commit 4e0e00b

Browse files
committed
Add support for subpixel rendering on Linux
1 parent 268e5ce commit 4e0e00b

File tree

11 files changed

+90
-19
lines changed

11 files changed

+90
-19
lines changed

kitty/cell_fragment.glsl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#version GLSL_VERSION
22
#define WHICH_PROGRAM
33
#define NOT_TRANSPARENT
4+
#define NOT_SUBPIXEL
45

5-
#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL)
6+
#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL) || defined(SUBPIXEL)
67
#define NEEDS_BACKROUND
78
#endif
89

@@ -28,6 +29,7 @@ in vec3 foreground;
2829
in vec4 cursor_color_vec;
2930
in vec3 decoration_fg;
3031
in float colored_sprite;
32+
in float subpixel;
3133
#endif
3234

3335
out vec4 final_color;
@@ -56,7 +58,13 @@ vec4 alpha_blend_premul(vec3 over, float over_alpha, vec3 under, float under_alp
5658
#ifdef NEEDS_FOREGROUND
5759
vec4 calculate_foreground() {
5860
vec4 text_fg = texture(sprites, sprite_pos);
61+
#ifdef SUBPIXEL
62+
vec3 unblended_fg = mix(foreground, text_fg.rgb, colored_sprite);
63+
vec3 blended_fg = mix(background, unblended_fg, text_fg.rgb);
64+
vec3 fg = mix(unblended_fg, blended_fg, subpixel);
65+
#else
5966
vec3 fg = mix(foreground, text_fg.rgb, colored_sprite);
67+
#endif
6068
float text_alpha = text_fg.a;
6169
float underline_alpha = texture(sprites, underline_pos).a;
6270
float strike_alpha = texture(sprites, strike_pos).a;

kitty/cell_vertex.glsl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define STRIKE_SHIFT {STRIKE_SHIFT}
77
#define DIM_SHIFT {DIM_SHIFT}
88
#define USE_SELECTION_FG
9+
#define NOT_SUBPIXEL
910

1011
// Inputs {{{
1112
layout(std140) uniform CellRenderData {
@@ -35,7 +36,7 @@ const uvec2 cell_pos_map[] = uvec2[4](
3536
// }}}
3637

3738

38-
#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL)
39+
#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL) || defined(SUBPIXEL)
3940
#define NEEDS_BACKROUND
4041
#endif
4142

@@ -61,6 +62,7 @@ out vec3 strike_pos;
6162
out vec3 foreground;
6263
out vec3 decoration_fg;
6364
out float colored_sprite;
65+
out float subpixel;
6466
out float effective_text_alpha;
6567
#endif
6668

@@ -69,6 +71,7 @@ out float effective_text_alpha;
6971
const uint BYTE_MASK = uint(0xFF);
7072
const uint Z_MASK = uint(0xFFF);
7173
const uint COLOR_MASK = uint(0x4000);
74+
const uint SUBPIXEL_MASK = uint(0x8000);
7275
const uint ZERO = uint(0);
7376
const uint ONE = uint(1);
7477
const uint TWO = uint(2);
@@ -166,6 +169,7 @@ void main() {
166169
// The character sprite being rendered
167170
sprite_pos = to_sprite_pos(pos, sprite_coords.x, sprite_coords.y, sprite_coords.z & Z_MASK);
168171
colored_sprite = float((sprite_coords.z & COLOR_MASK) >> 14);
172+
subpixel = float((sprite_coords.z & SUBPIXEL_MASK) >> 15);
169173

170174
// Foreground
171175
uint resolved_fg = resolve_color(colors[fg_index], default_colors[fg_index]);

kitty/config_data.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,11 @@ def macos_option_as_alt(x):
941941
invisible on dual GPU machines.'''))
942942
# }}}
943943

944+
o('linux_use_subpixel_rendering', False, long_text=_('''
945+
Use subpixel rendering instead of grayscale in freetype. Impacts performance,
946+
but may look better on low DPI screens.
947+
'''))
948+
944949
g('shortcuts') # {{{
945950

946951
o('kitty_mod', 'ctrl+shift', option_type=to_modifiers, long_text=_('''

kitty/fonts.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ typedef struct {
3232
typedef struct SpritePosition SpritePosition;
3333
struct SpritePosition {
3434
SpritePosition *next;
35-
bool filled, rendered, colored;
35+
bool filled, rendered, colored, subpixel;
3636
sprite_index x, y, z;
3737
uint8_t ligature_index;
3838
glyph_index glyph;
@@ -247,6 +247,7 @@ sprite_position_for(FontGroup *fg, Font *font, glyph_index glyph, ExtraGlyphs *e
247247
s->filled = true;
248248
s->rendered = false;
249249
s->colored = false;
250+
s->subpixel = false;
250251
s->x = fg->sprite_tracker.x; s->y = fg->sprite_tracker.y; s->z = fg->sprite_tracker.z;
251252
do_increment(fg, error);
252253
return s;
@@ -301,7 +302,7 @@ free_maps(Font *font) {
301302

302303
void
303304
clear_sprite_map(Font *font) {
304-
#define CLEAR(s) s->filled = false; s->rendered = false; s->colored = false; s->glyph = 0; memset(&s->extra_glyphs, 0, sizeof(ExtraGlyphs)); s->x = 0; s->y = 0; s->z = 0; s->ligature_index = 0;
305+
#define CLEAR(s) s->filled = false; s->rendered = false; s->colored = false; s->subpixel = false; s->glyph = 0; memset(&s->extra_glyphs, 0, sizeof(ExtraGlyphs)); s->x = 0; s->y = 0; s->z = 0; s->ligature_index = 0;
305306
SpritePosition *s;
306307
for (size_t i = 0; i < sizeof(font->sprite_map)/sizeof(font->sprite_map[0]); i++) {
307308
s = font->sprite_map + i;
@@ -606,6 +607,7 @@ render_box_cell(FontGroup *fg, CPUCell *cpu_cell, GPUCell *gpu_cell) {
606607
if (sp->rendered) return;
607608
sp->rendered = true;
608609
sp->colored = false;
610+
sp->subpixel = false;
609611
PyObject *ret = PyObject_CallFunction(box_drawing_function, "IIId", cpu_cell->ch, fg->cell_width, fg->cell_height, (fg->logical_dpi_x + fg->logical_dpi_y) / 2.0);
610612
if (ret == NULL) { PyErr_Print(); return; }
611613
uint8_t *alpha_mask = PyLong_AsVoidPtr(PyTuple_GET_ITEM(ret, 0));
@@ -640,6 +642,7 @@ static inline void
640642
set_cell_sprite(GPUCell *cell, SpritePosition *sp) {
641643
cell->sprite_x = sp->x; cell->sprite_y = sp->y; cell->sprite_z = sp->z;
642644
if (sp->colored) cell->sprite_z |= 0x4000;
645+
if (sp->subpixel) cell->sprite_z |= 0x8000;
643646
}
644647

645648
static inline pixel*
@@ -671,12 +674,14 @@ render_group(FontGroup *fg, unsigned int num_cells, unsigned int num_glyphs, CPU
671674

672675
clear_canvas(fg);
673676
bool was_colored = (gpu_cells->attrs & WIDTH_MASK) == 2 && is_emoji(cpu_cells->ch);
674-
render_glyphs_in_cells(font->face, font->bold, font->italic, info, positions, num_glyphs, fg->canvas, fg->cell_width, fg->cell_height, num_cells, fg->baseline, &was_colored, (FONTS_DATA_HANDLE)fg, center_glyph);
677+
bool was_subpixel = false;
678+
render_glyphs_in_cells(font->face, font->bold, font->italic, info, positions, num_glyphs, fg->canvas, fg->cell_width, fg->cell_height, num_cells, fg->baseline, &was_colored, &was_subpixel, (FONTS_DATA_HANDLE)fg, center_glyph);
675679
if (PyErr_Occurred()) PyErr_Print();
676680

677681
for (unsigned int i = 0; i < num_cells; i++) {
678682
sprite_position[i]->rendered = true;
679683
sprite_position[i]->colored = was_colored;
684+
sprite_position[i]->subpixel = was_subpixel;
680685
set_cell_sprite(gpu_cells + i, sprite_position[i]);
681686
pixel *buf = num_cells == 1 ? fg->canvas : extract_cell_from_canvas(fg, i, num_cells);
682687
current_send_sprite_to_gpu((FONTS_DATA_HANDLE)fg, sprite_position[i]->x, sprite_position[i]->y, sprite_position[i]->z, buf);

kitty/fonts.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ bool is_glyph_empty(PyObject *, glyph_index);
2626
hb_font_t* harfbuzz_font_for_face(PyObject*);
2727
bool set_size_for_face(PyObject*, unsigned int, bool, FONTS_DATA_HANDLE);
2828
void cell_metrics(PyObject*, unsigned int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*);
29-
bool render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *positions, unsigned int num_glyphs, pixel *canvas, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, unsigned int baseline, bool *was_colored, FONTS_DATA_HANDLE, bool center_glyph);
29+
bool render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *positions, unsigned int num_glyphs, pixel *canvas, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, unsigned int baseline, bool *was_colored, bool *was_subpixel, FONTS_DATA_HANDLE, bool center_glyph);
3030
PyObject* create_fallback_face(PyObject *base_face, CPUCell* cell, bool bold, bool italic, bool emoji_presentation, FONTS_DATA_HANDLE fg);
3131
PyObject* specialize_font_descriptor(PyObject *base_descriptor, FONTS_DATA_HANDLE);
3232
PyObject* face_from_path(const char *path, int index, FONTS_DATA_HANDLE);

kitty/freetype.c

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
#include <math.h>
1111
#include <structmember.h>
1212
#include <ft2build.h>
13+
#include FT_DRIVER_H
1314
#include <hb-ft.h>
15+
#include <fontconfig/fontconfig.h>
1416

1517
#if HB_VERSION_MAJOR > 1 || (HB_VERSION_MAJOR == 1 && (HB_VERSION_MINOR > 6 || (HB_VERSION_MINOR == 6 && HB_VERSION_MICRO >= 3)))
1618
#define HARFBUZZ_HAS_CHANGE_FONT
@@ -29,6 +31,7 @@ typedef struct {
2931
unsigned int units_per_EM;
3032
int ascender, descender, height, max_advance_width, max_advance_height, underline_position, underline_thickness;
3133
int hinting, hintstyle, index;
34+
int rgba;
3235
bool is_scalable, has_color;
3336
float size_in_pts;
3437
FT_F26Dot6 char_width, char_height;
@@ -159,13 +162,14 @@ get_load_flags(int hinting, int hintstyle, int base) {
159162

160163

161164
static inline bool
162-
init_ft_face(Face *self, PyObject *path, int hinting, int hintstyle, FONTS_DATA_HANDLE fg) {
165+
init_ft_face(Face *self, PyObject *path, int hinting, int hintstyle, int rgba, FONTS_DATA_HANDLE fg) {
163166
#define CPY(n) self->n = self->face->n;
164167
CPY(units_per_EM); CPY(ascender); CPY(descender); CPY(height); CPY(max_advance_width); CPY(max_advance_height); CPY(underline_position); CPY(underline_thickness);
165168
#undef CPY
166169
self->is_scalable = FT_IS_SCALABLE(self->face);
167170
self->has_color = FT_HAS_COLOR(self->face);
168171
self->hinting = hinting; self->hintstyle = hintstyle;
172+
self->rgba = rgba;
169173
if (!set_size_for_face((PyObject*)self, 0, false, fg)) return false;
170174
self->harfbuzz_font = hb_ft_font_create(self->face, NULL);
171175
if (self->harfbuzz_font == NULL) { PyErr_NoMemory(); return false; }
@@ -189,16 +193,24 @@ face_from_descriptor(PyObject *descriptor, FONTS_DATA_HANDLE fg) {
189193
long index = 0;
190194
bool hinting = false;
191195
long hint_style = 0;
196+
long rgba = 0;
192197
D(path, PyUnicode_AsUTF8, false);
193198
D(index, PyLong_AsLong, true);
194199
D(hinting, PyObject_IsTrue, true);
195200
D(hint_style, PyLong_AsLong, true);
201+
D(rgba, PyLong_AsLong, true);
196202
#undef D
197203
Face *self = (Face *)Face_Type.tp_alloc(&Face_Type, 0);
198204
if (self != NULL) {
199205
int error = FT_New_Face(library, path, index, &(self->face));
200206
if(error) { set_freetype_error("Failed to load face, with error:", error); Py_CLEAR(self); return NULL; }
201-
if (!init_ft_face(self, PyDict_GetItemString(descriptor, "path"), hinting, hint_style, fg)) { Py_CLEAR(self); return NULL; }
207+
if (!init_ft_face(self, PyDict_GetItemString(descriptor, "path"), hinting, hint_style, rgba, fg)) { Py_CLEAR(self); return NULL; }
208+
FT_Parameter property_darkening;
209+
FT_Bool darken_stems = 1;
210+
property_darkening.tag = FT_PARAM_TAG_STEM_DARKENING;
211+
property_darkening.data = &darken_stems;
212+
error = FT_Face_Properties(self->face, 1, &property_darkening);
213+
if(error) { set_freetype_error("Failed to set face property, with error:", error); Py_CLEAR(self); return NULL; }
202214
}
203215
return (PyObject*)self;
204216
}
@@ -210,7 +222,7 @@ face_from_path(const char *path, int index, FONTS_DATA_HANDLE fg) {
210222
int error;
211223
error = FT_New_Face(library, path, index, &ans->face);
212224
if (error) { set_freetype_error("Failed to load face, with error:", error); ans->face = NULL; return NULL; }
213-
if (!init_ft_face(ans, Py_None, true, 3, fg)) { Py_CLEAR(ans); return NULL; }
225+
if (!init_ft_face(ans, Py_None, true, 3, 1, fg)) { Py_CLEAR(ans); return NULL; }
214226
return (PyObject*)ans;
215227
}
216228

@@ -351,7 +363,10 @@ populate_processed_bitmap(FT_GlyphSlotRec *slot, FT_Bitmap *bitmap, ProcessedBit
351363

352364
static inline bool
353365
render_bitmap(Face *self, int glyph_id, ProcessedBitmap *ans, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, bool bold, bool italic, bool rescale, FONTS_DATA_HANDLE fg) {
354-
if (!load_glyph(self, glyph_id, FT_LOAD_RENDER)) return false;
366+
int flags = FT_LOAD_RENDER;
367+
if (OPT(linux_use_subpixel_rendering))
368+
flags |= FT_LOAD_TARGET_LCD;
369+
if (!load_glyph(self, glyph_id, flags)) return false;
355370
unsigned int max_width = cell_width * num_cells;
356371

357372
// Embedded bitmap glyph?
@@ -372,6 +387,9 @@ render_bitmap(Face *self, int glyph_id, ProcessedBitmap *ans, unsigned int cell_
372387
}
373388
populate_processed_bitmap(self->face->glyph, &bitmap, ans, true);
374389
FT_Bitmap_Done(library, &bitmap);
390+
} else if (self->face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD) {
391+
populate_processed_bitmap(self->face->glyph, &self->face->glyph->bitmap, ans, false);
392+
ans->width /= 3;
375393
} else {
376394
populate_processed_bitmap(self->face->glyph, &self->face->glyph->bitmap, ans, false);
377395
}
@@ -488,7 +506,24 @@ copy_color_bitmap(uint8_t *src, pixel* dest, Region *src_rect, Region *dest_rect
488506
}
489507

490508
static inline void
491-
place_bitmap_in_canvas(pixel *cell, ProcessedBitmap *bm, size_t cell_width, size_t cell_height, float x_offset, float y_offset, size_t baseline) {
509+
copy_lcd_bitmap(uint8_t *src, pixel* dest, Region *src_rect, Region *dest_rect, size_t src_stride, size_t dest_stride, bool bgr) {
510+
for (size_t sr = src_rect->top, dr = dest_rect->top; sr < src_rect->bottom && dr < dest_rect->bottom; sr++, dr++) {
511+
pixel *d = dest + dest_stride * dr;
512+
uint8_t *s = src + src_stride * sr;
513+
for(size_t sc = src_rect->left, dc = dest_rect->left; sc < src_rect->right && dc < dest_rect->right; sc++, dc++) {
514+
uint8_t *rgb = s + 3 * sc;
515+
#define C(idx, shift) ( rgb[idx] << shift)
516+
if (!bgr)
517+
d[dc] = C(0, 24) | C(1, 16) | C(2, 8) | 0xff;
518+
else
519+
d[dc] = C(2, 24) | C(1, 16) | C(0, 8) | 0xff;
520+
#undef C
521+
}
522+
}
523+
}
524+
525+
static inline void
526+
place_bitmap_in_canvas(pixel *cell, ProcessedBitmap *bm, size_t cell_width, size_t cell_height, float x_offset, float y_offset, size_t baseline, bool bgr) {
492527
// We want the glyph to be positioned inside the cell based on the bearingX
493528
// and bearingY values, making sure that it does not overflow the cell.
494529

@@ -517,13 +552,15 @@ place_bitmap_in_canvas(pixel *cell, ProcessedBitmap *bm, size_t cell_width, size
517552

518553
if (bm->pixel_mode == FT_PIXEL_MODE_BGRA) {
519554
copy_color_bitmap(bm->buf, cell, &src, &dest, bm->stride, cell_width);
555+
} else if (bm->pixel_mode == FT_PIXEL_MODE_LCD) {
556+
copy_lcd_bitmap(bm->buf, cell, &src, &dest, bm->stride, cell_width, bgr);
520557
} else render_alpha_mask(bm->buf, cell, &src, &dest, bm->stride, cell_width);
521558
}
522559

523560
static const ProcessedBitmap EMPTY_PBM = {.factor = 1};
524561

525562
bool
526-
render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *positions, unsigned int num_glyphs, pixel *canvas, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, unsigned int baseline, bool *was_colored, FONTS_DATA_HANDLE fg, bool center_glyph) {
563+
render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *positions, unsigned int num_glyphs, pixel *canvas, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, unsigned int baseline, bool *was_colored, bool *was_subpixel, FONTS_DATA_HANDLE fg, bool center_glyph) {
527564
Face *self = (Face*)f;
528565
bool is_emoji = *was_colored; *was_colored = is_emoji && self->has_color;
529566
float x = 0.f, y = 0.f, x_offset = 0.f;
@@ -540,10 +577,11 @@ render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *inf
540577
} else {
541578
if (!render_bitmap(self, info[i].codepoint, &bm, cell_width, cell_height, num_cells, bold, italic, true, fg)) return false;
542579
}
580+
*was_subpixel = (bm.pixel_mode == FT_PIXEL_MODE_LCD);
543581
x_offset = x + (float)positions[i].x_offset / 64.0f;
544582
y = (float)positions[i].y_offset / 64.0f;
545583
if ((*was_colored || self->face->glyph->metrics.width > 0) && bm.width > 0) {
546-
place_bitmap_in_canvas(canvas, &bm, canvas_width, cell_height, x_offset, y, baseline);
584+
place_bitmap_in_canvas(canvas, &bm, canvas_width, cell_height, x_offset, y, baseline, (self->rgba == FC_RGBA_BGR));
547585
}
548586
x += (float)positions[i].x_advance / 64.0f;
549587
free_processed_bitmap(&bm);
@@ -591,12 +629,17 @@ render_simple_text_impl(PyObject *s, const char *text, unsigned int baseline) {
591629
FT_UInt glyph_index = FT_Get_Char_Index(self->face, text[n]);
592630
int error = FT_Load_Glyph(self->face, glyph_index, FT_LOAD_DEFAULT);
593631
if (error) continue;
594-
error = FT_Render_Glyph(self->face->glyph, FT_RENDER_MODE_NORMAL);
632+
int flags = 0;
633+
if (OPT(linux_use_subpixel_rendering))
634+
flags |= FT_RENDER_MODE_LCD;
635+
else
636+
flags |= FT_RENDER_MODE_NORMAL;
637+
error = FT_Render_Glyph(self->face->glyph, flags);
595638
if (error) continue;
596639
FT_Bitmap *bitmap = &self->face->glyph->bitmap;
597640
pbm = EMPTY_PBM;
598641
populate_processed_bitmap(self->face->glyph, bitmap, &pbm, false);
599-
place_bitmap_in_canvas(canvas, &pbm, canvas_width, canvas_height, pen_x, 0, baseline);
642+
place_bitmap_in_canvas(canvas, &pbm, canvas_width, canvas_height, pen_x, 0, baseline, (self->rgba == FC_RGBA_BGR));
600643
pen_x += self->face->glyph->advance.x >> 6;
601644
}
602645
ans.width = pen_x; ans.height = canvas_height;

kitty/glfw.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
567567
// blank the window once so that there is no initial flash of color
568568
// changing, in case the background color is not black
569569
blank_canvas(is_semi_transparent ? OPT(background_opacity) : 1.0f);
570+
bool is_subpixel_enabled = OPT(linux_use_subpixel_rendering);
570571
#ifndef __APPLE__
571572
if (is_first_window) glfwSwapInterval(OPT(sync_to_monitor) && !global_state.is_wayland ? 1 : 0);
572573
#endif
@@ -579,7 +580,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
579580
glfwShowWindow(glfw_window);
580581
}
581582
if (is_first_window) {
582-
PyObject *ret = PyObject_CallFunction(load_programs, "O", is_semi_transparent ? Py_True : Py_False);
583+
PyObject *ret = PyObject_CallFunction(load_programs, "OO", is_semi_transparent ? Py_True : Py_False, is_subpixel_enabled ? Py_True : Py_False);
583584
if (ret == NULL) return NULL;
584585
Py_DECREF(ret);
585586
#ifdef __APPLE__

kitty/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ def talk_to_instance(args):
8282
conn.close()
8383

8484

85-
def load_all_shaders(semi_transparent=0):
86-
load_shader_programs(semi_transparent)
85+
def load_all_shaders(semi_transparent=False, subpixel_enabled=False):
86+
load_shader_programs(semi_transparent, subpixel_enabled)
8787
load_borders_program()
8888

8989

kitty/state.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ PYWRAP1(set_options) {
408408
S(macos_window_resizable, PyObject_IsTrue);
409409
S(macos_hide_from_tasks, PyObject_IsTrue);
410410
S(macos_thicken_font, PyFloat_AsDouble);
411+
S(linux_use_subpixel_rendering, PyObject_IsTrue);
411412
S(tab_bar_min_tabs, PyLong_AsUnsignedLong);
412413
S(disable_ligatures, PyLong_AsLong);
413414

kitty/state.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ typedef struct {
2525
double repaint_delay, input_delay;
2626
bool focus_follows_mouse, hide_window_decorations;
2727
bool macos_hide_from_tasks, macos_quit_when_last_window_closed, macos_window_resizable, macos_traditional_fullscreen, macos_show_window_title_in_menubar;
28+
bool linux_use_subpixel_rendering;
2829
unsigned int macos_option_as_alt;
2930
float macos_thicken_font;
3031
int adjust_line_height_px, adjust_column_width_px;

0 commit comments

Comments
 (0)