sRGB glyph composition: Use default values that give "close to native" rendering. Also use only a single option to control it.
This commit is contained in:
parent
8433f1d731
commit
4dfd4d4972
@ -38,7 +38,7 @@ Detailed list of changes
|
||||
0.28.0 [future]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Text rendering: Use sRGB correct linear gamma blending for nicer font rendering and better color accuracy with transparent windows. See the options :opt:`text_old_gamma`, :opt:`text_gamma_adjustment` and :opt:`text_contrast` (:pull:`5969`)
|
||||
- Text rendering: Use sRGB correct linear gamma blending for nicer font rendering and better color accuracy with transparent windows. See the option :opt:`text_composition_strategy` for details. (:pull:`5969`)
|
||||
|
||||
|
||||
0.27.1 [2023-02-07]
|
||||
|
||||
@ -233,36 +233,30 @@ the curl will peak once per character, with dense twice.
|
||||
'''
|
||||
)
|
||||
|
||||
opt('text_old_gamma', 'no',
|
||||
option_type='to_bool', ctype='bool',
|
||||
long_text='''
|
||||
Revert to using the old (pre 0.28) gamma correction algorithm when rendering text.
|
||||
This will make some text appear like the strokes are uneven. Dark text on bright backgrounds
|
||||
will also look thicker while lighter text on darker backgrounds will look thinner.
|
||||
'''
|
||||
)
|
||||
opt('text_composition_strategy', 'platform', ctype='!text_composition_strategy', long_text='''
|
||||
Control how kitty composites text glyphs onto the background color.
|
||||
The default value of :code:`platform` tries for text rendering as
|
||||
close to "native" for the platform kitty is running on as possible.
|
||||
|
||||
opt('text_gamma_adjustment', '1.0',
|
||||
option_type='positive_float', ctype='float',
|
||||
long_text='''
|
||||
Adjust the thickness of darker text on lighter backgrounds. Increasing the value
|
||||
setting will make the text appear thicker while decreasing the value will make it thinner. It
|
||||
can compensate for some fonts looking too-thin when using the gamma-correct alpha blending.
|
||||
A value of :code:`legacy` uses the old (pre kitty 0.28) strategy for how glyphs
|
||||
are composited. This will make dark text on light backgrounds look thicker and
|
||||
light text on dark backgrounds thinner. It might also make some text appear like
|
||||
the strokes are uneven.
|
||||
|
||||
You can fine tune the actual contrast curve used for glyph composition
|
||||
by specifying two space separated numbers for this setting.
|
||||
|
||||
The first number is the gamma adjustment, which
|
||||
controls the thickness of dark text on light backgrounds. Increasing the value will make text appear thicker.
|
||||
The default value for this is 1.0 on Linux and 1.7 on macOS. Valid values are 0.01 and above.
|
||||
The result is scaled based on the luminance difference between the background and the foreground.
|
||||
Dark text on light backgrounds receives the full impact of the curve while light text on dark
|
||||
backgrounds is affected very little. Valid values are 0.01 and above. For macOS like text rendering,
|
||||
a value of ~1.7 usually works well.
|
||||
'''
|
||||
)
|
||||
backgrounds is affected very little.
|
||||
|
||||
The second number is an additional multiplicative contrast. It is percentage ranging from 0 to 100.
|
||||
The default value is zero On Linux and 30 on macOS.
|
||||
''')
|
||||
|
||||
opt('text_contrast', '0',
|
||||
option_type='positive_float', ctype='float',
|
||||
long_text='''
|
||||
Increase text contrast further. This will cause jagged edges due to over saturation if set too high.
|
||||
The value is a percentage from 0 to 100. For macOS like text rendering, a value of 30 usually works well.
|
||||
'''
|
||||
)
|
||||
egr() # }}}
|
||||
|
||||
|
||||
|
||||
10
kitty/options/parse.py
generated
10
kitty/options/parse.py
generated
@ -1278,14 +1278,8 @@ class Parser:
|
||||
def term(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['term'] = str(val)
|
||||
|
||||
def text_contrast(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['text_contrast'] = positive_float(val)
|
||||
|
||||
def text_gamma_adjustment(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['text_gamma_adjustment'] = positive_float(val)
|
||||
|
||||
def text_old_gamma(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['text_old_gamma'] = to_bool(val)
|
||||
def text_composition_strategy(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['text_composition_strategy'] = str(val)
|
||||
|
||||
def touch_scroll_multiplier(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['touch_scroll_multiplier'] = float(val)
|
||||
|
||||
42
kitty/options/to-c-generated.h
generated
42
kitty/options/to-c-generated.h
generated
@ -58,41 +58,15 @@ convert_from_opts_modify_font(PyObject *py_opts, Options *opts) {
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_text_old_gamma(PyObject *val, Options *opts) {
|
||||
opts->text_old_gamma = PyObject_IsTrue(val);
|
||||
convert_from_python_text_composition_strategy(PyObject *val, Options *opts) {
|
||||
text_composition_strategy(val, opts);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_text_old_gamma(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "text_old_gamma");
|
||||
convert_from_opts_text_composition_strategy(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "text_composition_strategy");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_text_old_gamma(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_text_gamma_adjustment(PyObject *val, Options *opts) {
|
||||
opts->text_gamma_adjustment = PyFloat_AsFloat(val);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_text_gamma_adjustment(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "text_gamma_adjustment");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_text_gamma_adjustment(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_text_contrast(PyObject *val, Options *opts) {
|
||||
opts->text_contrast = PyFloat_AsFloat(val);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_text_contrast(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "text_contrast");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_text_contrast(ret, opts);
|
||||
convert_from_python_text_composition_strategy(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
@ -1081,11 +1055,7 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) {
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_modify_font(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_text_old_gamma(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_text_gamma_adjustment(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_text_contrast(py_opts, opts);
|
||||
convert_from_opts_text_composition_strategy(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_cursor_shape(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
|
||||
@ -175,6 +175,31 @@ url_prefixes(PyObject *up, Options *opts) {
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
text_composition_strategy(PyObject *val, Options *opts) {
|
||||
if (!PyUnicode_Check(val)) { PyErr_SetString(PyExc_TypeError, "text_rendering_strategy must be a string"); return; }
|
||||
opts->text_old_gamma = false;
|
||||
opts->text_gamma_adjustment = 1.0f; opts->text_contrast = 0.f;
|
||||
if (PyUnicode_CompareWithASCIIString(val, "platform") == 0) {
|
||||
#ifdef __APPLE__
|
||||
opts->text_gamma_adjustment = 1.7f; opts->text_contrast = 30.f;
|
||||
#endif
|
||||
}
|
||||
else if (PyUnicode_CompareWithASCIIString(val, "legacy") == 0) {
|
||||
opts->text_old_gamma = true;
|
||||
} else {
|
||||
DECREF_AFTER_FUNCTION PyObject *parts = PyUnicode_Split(val, NULL, 1);
|
||||
if (PyList_GET_SIZE(parts) != 2) { PyErr_SetString(PyExc_ValueError, "text_rendering_strategy must be of the form number:number"); return; }
|
||||
DECREF_AFTER_FUNCTION PyObject *ga = PyFloat_FromString(PyList_GET_ITEM(parts, 0));
|
||||
if (PyErr_Occurred()) return;
|
||||
opts->text_gamma_adjustment = MAX(0.01f, PyFloat_AsFloat(ga));
|
||||
DECREF_AFTER_FUNCTION PyObject *contrast = PyFloat_FromString(PyList_GET_ITEM(parts, 1));
|
||||
if (PyErr_Occurred()) return;
|
||||
opts->text_contrast = MAX(0.0f, PyFloat_AsFloat(contrast));
|
||||
opts->text_contrast = MIN(100.0f, opts->text_contrast);
|
||||
}
|
||||
}
|
||||
|
||||
static char_type*
|
||||
list_of_chars(PyObject *chars) {
|
||||
if (!PyUnicode_Check(chars)) { PyErr_SetString(PyExc_TypeError, "list_of_chars must be a string"); return NULL; }
|
||||
|
||||
8
kitty/options/types.py
generated
8
kitty/options/types.py
generated
@ -443,9 +443,7 @@ option_names = ( # {{{
|
||||
'tab_title_max_length',
|
||||
'tab_title_template',
|
||||
'term',
|
||||
'text_contrast',
|
||||
'text_gamma_adjustment',
|
||||
'text_old_gamma',
|
||||
'text_composition_strategy',
|
||||
'touch_scroll_multiplier',
|
||||
'undercurl_style',
|
||||
'update_check_interval',
|
||||
@ -597,9 +595,7 @@ class Options:
|
||||
tab_title_max_length: int = 0
|
||||
tab_title_template: str = '{fmt.fg.red}{bell_symbol}{activity_symbol}{fmt.fg.tab}{title}'
|
||||
term: str = 'xterm-kitty'
|
||||
text_contrast: float = 0
|
||||
text_gamma_adjustment: float = 1.0
|
||||
text_old_gamma: bool = False
|
||||
text_composition_strategy: str = 'platform'
|
||||
touch_scroll_multiplier: float = 1.0
|
||||
undercurl_style: choices_for_undercurl_style = 'thin-sparse'
|
||||
update_check_interval: float = 24.0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user