Skip to content

Commit be864c4

Browse files
committed
Add initial support for LCD_V rendering (requires rewrite as height = rows/3 in this case)
1 parent c18a969 commit be864c4

File tree

5 files changed

+50
-14
lines changed

5 files changed

+50
-14
lines changed

kitty/config_data.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -939,12 +939,23 @@ def macos_option_as_alt(x):
939939
Enable/disable custom mouse cursor for macOS that is easier to see on both
940940
light and dark backgrounds. WARNING: this might make your mouse cursor
941941
invisible on dual GPU machines.'''))
942-
# }}}
943942

944-
o('use_subpixel_rendering', False, long_text=_('''
943+
944+
def to_subpixel_options(x):
945+
x = x.lower()
946+
if x == 'lcd':
947+
return 1
948+
if x == 'lcd_v':
949+
return 2
950+
return 0
951+
952+
953+
o('subpixel_rendering', 'none', option_type=to_subpixel_options, long_text=_('''
945954
Use subpixel rendering instead of grayscale in freetype. Impacts performance,
946-
but may look better on low DPI screens.
955+
but may look better on low DPI screens. Possible values are :code:`none`,
956+
:code:`lcd`, and :code:`lcd_v`.
947957
'''))
958+
# }}}
948959

949960
g('shortcuts') # {{{
950961

kitty/freetype.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ trim_borders(ProcessedBitmap *ans, size_t extra) {
329329
// Trim empty columns from the right side of the bitmap
330330
for (ssize_t x = ans->width - 1; !column_has_text && x > -1 && extra > 0; x--) {
331331
for (size_t y = 0; y < ans->rows && !column_has_text; y++) {
332-
if (ans->buf[x + y * ans->stride] > 200) column_has_text = true;
332+
if (ans->buf[x + y * ans->stride] > 200) column_has_text = true; // TODO
333333
}
334334
if (!column_has_text) { ans->width--; extra--; }
335335
}
@@ -357,8 +357,17 @@ populate_processed_bitmap(FT_GlyphSlotRec *slot, FT_Bitmap *bitmap, ProcessedBit
357357
static inline bool
358358
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) {
359359
int flags = FT_LOAD_RENDER;
360-
if (OPT(use_subpixel_rendering))
361-
flags |= FT_LOAD_TARGET_LCD;
360+
switch (OPT(subpixel_rendering)) {
361+
case SUBPIXEL_LCD:
362+
flags |= FT_LOAD_TARGET_LCD;
363+
break;
364+
case SUBPIXEL_LCD_V:
365+
flags |= FT_LOAD_TARGET_LCD_V;
366+
break;
367+
case SUBPIXEL_NONE:
368+
default:
369+
break;
370+
}
362371
if (!load_glyph(self, glyph_id, flags)) return false;
363372
unsigned int max_width = cell_width * num_cells;
364373

@@ -383,6 +392,9 @@ render_bitmap(Face *self, int glyph_id, ProcessedBitmap *ans, unsigned int cell_
383392
} else if (self->face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD) {
384393
populate_processed_bitmap(self->face->glyph, &self->face->glyph->bitmap, ans, false);
385394
ans->width /= 3;
395+
} else if (self->face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V) {
396+
populate_processed_bitmap(self->face->glyph, &self->face->glyph->bitmap, ans, false);
397+
// TODO: tune ans->rows, as it's 3 times biger than the actual height
386398
} else {
387399
populate_processed_bitmap(self->face->glyph, &self->face->glyph->bitmap, ans, false);
388400
}
@@ -547,6 +559,9 @@ place_bitmap_in_canvas(pixel *cell, ProcessedBitmap *bm, size_t cell_width, size
547559
copy_color_bitmap(bm->buf, cell, &src, &dest, bm->stride, cell_width);
548560
} else if (bm->pixel_mode == FT_PIXEL_MODE_LCD) {
549561
copy_lcd_bitmap(bm->buf, cell, &src, &dest, bm->stride, cell_width, bgr);
562+
} else if (bm->pixel_mode == FT_PIXEL_MODE_LCD_V) {
563+
// copy_lcd_v_bitmap(bm->buf, cell, &src, &dest, bm->stride, cell_width, bgr);
564+
// TODO: implement it
550565
} else render_alpha_mask(bm->buf, cell, &src, &dest, bm->stride, cell_width);
551566
}
552567

@@ -570,7 +585,7 @@ render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *inf
570585
} else {
571586
if (!render_bitmap(self, info[i].codepoint, &bm, cell_width, cell_height, num_cells, bold, italic, true, fg)) return false;
572587
}
573-
*was_subpixel = (bm.pixel_mode == FT_PIXEL_MODE_LCD);
588+
*was_subpixel = (bm.pixel_mode == FT_PIXEL_MODE_LCD || bm.pixel_mode = FT_PIXEL_MODE_LCD_V);
574589
x_offset = x + (float)positions[i].x_offset / 64.0f;
575590
y = (float)positions[i].y_offset / 64.0f;
576591
if ((*was_colored || self->face->glyph->metrics.width > 0) && bm.width > 0) {
@@ -623,10 +638,18 @@ render_simple_text_impl(PyObject *s, const char *text, unsigned int baseline) {
623638
int error = FT_Load_Glyph(self->face, glyph_index, FT_LOAD_DEFAULT);
624639
if (error) continue;
625640
int flags = 0;
626-
if (OPT(use_subpixel_rendering))
627-
flags |= FT_RENDER_MODE_LCD;
628-
else
629-
flags |= FT_RENDER_MODE_NORMAL;
641+
switch (OPT(subpixel_rendering)) {
642+
case SUBPIXEL_LCD:
643+
flags |= FT_RENDER_MODE_LCD;
644+
break;
645+
case SUBPIXEL_LCD_V:
646+
flags |= FT_RENDER_MODE_LCD_V;
647+
break;
648+
case SUBPIXEL_NONE:
649+
default:
650+
flags |= FT_RENDER_MODE_NORMAL;
651+
break;
652+
}
630653
error = FT_Render_Glyph(self->face->glyph, flags);
631654
if (error) continue;
632655
FT_Bitmap *bitmap = &self->face->glyph->bitmap;

kitty/glfw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +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(use_subpixel_rendering);
570+
bool is_subpixel_enabled = (OPT(subpixel_rendering) == SUBPIXEL_LCD || OPT(subpixel_rendering) == SUBPIXEL_LCD_V);
571571
#ifndef __APPLE__
572572
if (is_first_window) glfwSwapInterval(OPT(sync_to_monitor) && !global_state.is_wayland ? 1 : 0);
573573
#endif

kitty/state.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +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(use_subpixel_rendering, PyObject_IsTrue);
411+
S(subpixel_rendering, PyLong_AsLong);
412412
S(tab_bar_min_tabs, PyLong_AsUnsignedLong);
413413
S(disable_ligatures, PyLong_AsLong);
414414

kitty/state.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
typedef enum { LEFT_EDGE, TOP_EDGE, RIGHT_EDGE, BOTTOM_EDGE } Edge;
1414

15+
typedef enum { SUBPIXEL_NONE, SUBPIXEL_LCD, SUBPIXEL_LCD_V } SubpixelRendering;
16+
1517
typedef struct {
1618
double visual_bell_duration, cursor_blink_interval, cursor_stop_blinking_after, mouse_hide_wait, click_interval, wheel_scroll_multiplier, touch_scroll_multiplier;
1719
bool enable_audio_bell;
@@ -25,7 +27,7 @@ typedef struct {
2527
double repaint_delay, input_delay;
2628
bool focus_follows_mouse, hide_window_decorations;
2729
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 use_subpixel_rendering;
30+
SubpixelRendering subpixel_rendering;
2931
unsigned int macos_option_as_alt;
3032
float macos_thicken_font;
3133
int adjust_line_height_px, adjust_column_width_px;

0 commit comments

Comments
 (0)