mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-09 07:07:19 +02:00
Merge branch 'min-contrast-ratio' of https://github.com/arne314/kitty
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
#define HAS_TRANSPARENCY {TRANSPARENT}
|
||||
#define FG_OVERRIDE {FG_OVERRIDE}
|
||||
#define FG_OVERRIDE_THRESHOLD {FG_OVERRIDE_THRESHOLD}
|
||||
#define APPLY_MIN_CONTRAST_RATIO {APPLY_MIN_CONTRAST_RATIO}
|
||||
#define MIN_CONTRAST_RATIO {MIN_CONTRAST_RATIO}
|
||||
#define TEXT_NEW_GAMMA {TEXT_NEW_GAMMA}
|
||||
|
||||
#define DECORATION_SHIFT {DECORATION_SHIFT}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma kitty_include_shader <alpha_blend.glsl>
|
||||
#pragma kitty_include_shader <hsluv.glsl>
|
||||
#pragma kitty_include_shader <linear2srgb.glsl>
|
||||
#pragma kitty_include_shader <cell_defines.glsl>
|
||||
|
||||
@@ -87,6 +88,24 @@ vec3 fg_override(float under_luminance, float over_lumininace, vec3 over) {
|
||||
return original_level * over + override_level * vec3(step(under_luminance, 0.5f));
|
||||
}
|
||||
#endif
|
||||
#if (APPLY_MIN_CONTRAST_RATIO == 1)
|
||||
float contrast_ratio(float under_luminance, float over_luminance) {
|
||||
return clamp((max(under_luminance, over_luminance) + 0.05f) / (min(under_luminance, over_luminance) + 0.05f), 1.f, 21.f);
|
||||
}
|
||||
vec3 apply_min_contrast_ratio(float under_luminance, float over_luminance, vec3 under, vec3 over) {
|
||||
float ratio = contrast_ratio(under_luminance, over_luminance);
|
||||
vec3 diff = abs(under - over);
|
||||
vec3 over_hsluv = rgbToHsluv(over);
|
||||
float target_lum_a = clamp((under_luminance + 0.05f) * MIN_CONTRAST_RATIO - 0.05f, 0.f, 1.f);
|
||||
float target_lum_b = clamp((under_luminance + 0.05f) / MIN_CONTRAST_RATIO - 0.05f, 0.f, 1.f);
|
||||
vec3 result_a = clamp(hsluvToRgb(vec3(over_hsluv.x, over_hsluv.y, target_lum_a * 100.f)), 0.f, 1.f);
|
||||
vec3 result_b = clamp(hsluvToRgb(vec3(over_hsluv.x, over_hsluv.y, target_lum_b * 100.f)), 0.f, 1.f);
|
||||
float result_a_ratio = contrast_ratio(under_luminance, dot(result_a, Y));
|
||||
float result_b_ratio = contrast_ratio(under_luminance, dot(result_b, Y));
|
||||
vec3 result = mix(result_a, result_b, step(result_a_ratio, result_b_ratio));
|
||||
return mix(result, over, max(step(diff.r + diff.g + diff.g, 0.001f), step(MIN_CONTRAST_RATIO, ratio)));
|
||||
}
|
||||
#endif
|
||||
|
||||
vec4 foreground_contrast(vec4 over, vec3 under) {
|
||||
float under_luminance = dot(under, Y);
|
||||
@@ -96,6 +115,10 @@ vec4 foreground_contrast(vec4 over, vec3 under) {
|
||||
over.rgb = fg_override(under_luminance, over_lumininace, over.rgb);
|
||||
over_lumininace = dot(over.rgb, Y);
|
||||
#endif
|
||||
#if (APPLY_MIN_CONTRAST_RATIO == 1)
|
||||
over.rgb = apply_min_contrast_ratio(under_luminance, over_lumininace, under, over.rgb);
|
||||
over_lumininace = dot(over.rgb, Y);
|
||||
#endif
|
||||
|
||||
// Apply additional gamma-adjustment scaled by the luminance difference, the darker the foreground the more adjustment we apply.
|
||||
// A multiplicative contrast is also available to increase saturation.
|
||||
@@ -111,6 +134,10 @@ vec4 foreground_contrast_incorrect(vec4 over, vec3 under) {
|
||||
#if (FG_OVERRIDE == 1)
|
||||
over.rgb = fg_override(under_luminance, over_lumininace, over.rgb);
|
||||
over_lumininace = dot(over.rgb, Y);
|
||||
#endif
|
||||
#if (APPLY_MIN_CONTRAST_RATIO == 1)
|
||||
over.rgb = apply_min_contrast_ratio(under_luminance, over_lumininace, under, over.rgb);
|
||||
over_lumininace = dot(over.rgb, Y);
|
||||
#endif
|
||||
// This is the original gamma-incorrect rendering, it is the solution of the following equation:
|
||||
//
|
||||
|
||||
@@ -22,6 +22,7 @@ from ..typing import Protocol
|
||||
from ..utils import expandvars, log_error, shlex_split
|
||||
|
||||
key_pat = re.compile(r'([a-zA-Z][a-zA-Z0-9_-]*)\s+(.+)$')
|
||||
number_unit_pat = re.compile(r'\s*([-+]?\d+\.?\d*)\s*([^\d\s]*)?')
|
||||
ItemParser = Callable[[str, str, dict[str, Any]], bool]
|
||||
T = TypeVar('T')
|
||||
|
||||
@@ -66,6 +67,19 @@ def unit_float(x: ConvertibleToNumbers) -> float:
|
||||
return max(0, min(float(x), 1))
|
||||
|
||||
|
||||
def number_with_unit(x: str, default_unit: str = '') -> tuple[float, str]:
|
||||
mat = number_unit_pat.match(x)
|
||||
exception = None
|
||||
if mat is not None:
|
||||
try:
|
||||
value, unit = float(mat.group(1)), mat.group(2)
|
||||
unit = default_unit if not unit else unit
|
||||
return value, unit
|
||||
except Exception as e:
|
||||
exception = e
|
||||
raise ValueError(f'Invalid number with unit config option provided: {x if exception is None else exception}')
|
||||
|
||||
|
||||
def to_bool(x: str) -> bool:
|
||||
return x.lower() in ('y', 'yes', 'true')
|
||||
|
||||
|
||||
210
kitty/hsluv.glsl
Normal file
210
kitty/hsluv.glsl
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
HSLUV-GLSL v4.2
|
||||
HSLUV is a human-friendly alternative to HSL. ( http://www.hsluv.org )
|
||||
GLSL port by William Malo ( https://github.com/williammalo )
|
||||
Put this code in your fragment shader.
|
||||
*/
|
||||
|
||||
// stripped down and optimized (branchless) version
|
||||
|
||||
float divide(float num, float denom) {
|
||||
return num / (abs(denom) + 1e-15) * sign(denom);
|
||||
}
|
||||
|
||||
vec3 divide(vec3 num, vec3 denom) {
|
||||
return num / (abs(denom) + 1e-15) * sign(denom);
|
||||
}
|
||||
|
||||
vec3 hsluv_intersectLineLine(vec3 line1x, vec3 line1y, vec3 line2x, vec3 line2y) {
|
||||
return (line1y - line2y) / (line2x - line1x);
|
||||
}
|
||||
|
||||
vec3 hsluv_distanceFromPole(vec3 pointx,vec3 pointy) {
|
||||
return sqrt(pointx*pointx + pointy*pointy);
|
||||
}
|
||||
|
||||
vec3 hsluv_lengthOfRayUntilIntersect(float theta, vec3 x, vec3 y) {
|
||||
vec3 len = divide(y, sin(theta) - x * cos(theta));
|
||||
len = mix(len, vec3(1000.0), step(len, vec3(0.0)));
|
||||
return len;
|
||||
}
|
||||
|
||||
float hsluv_maxSafeChromaForL(float L){
|
||||
mat3 m2 = mat3(
|
||||
3.2409699419045214 ,-0.96924363628087983 , 0.055630079696993609,
|
||||
-1.5373831775700935 , 1.8759675015077207 ,-0.20397695888897657 ,
|
||||
-0.49861076029300328 , 0.041555057407175613, 1.0569715142428786
|
||||
);
|
||||
float sub0 = L + 16.0;
|
||||
float sub1 = sub0 * sub0 * sub0 * .000000641;
|
||||
float sub2 = mix(L / 903.2962962962963, sub1, step(0.0088564516790356308, sub1));
|
||||
|
||||
vec3 top1 = (284517.0 * m2[0] - 94839.0 * m2[2]) * sub2;
|
||||
vec3 bottom = (632260.0 * m2[2] - 126452.0 * m2[1]) * sub2;
|
||||
vec3 top2 = (838422.0 * m2[2] + 769860.0 * m2[1] + 731718.0 * m2[0]) * L * sub2;
|
||||
|
||||
vec3 bounds0x = top1 / bottom;
|
||||
vec3 bounds0y = top2 / bottom;
|
||||
|
||||
vec3 bounds1x = top1 / (bottom+126452.0);
|
||||
vec3 bounds1y = (top2-769860.0*L) / (bottom+126452.0);
|
||||
|
||||
vec3 xs0 = hsluv_intersectLineLine(bounds0x, bounds0y, -1.0/bounds0x, vec3(0.0) );
|
||||
vec3 xs1 = hsluv_intersectLineLine(bounds1x, bounds1y, -1.0/bounds1x, vec3(0.0) );
|
||||
|
||||
vec3 lengths0 = hsluv_distanceFromPole( xs0, bounds0y + xs0 * bounds0x );
|
||||
vec3 lengths1 = hsluv_distanceFromPole( xs1, bounds1y + xs1 * bounds1x );
|
||||
|
||||
return min(lengths0.r,
|
||||
min(lengths1.r,
|
||||
min(lengths0.g,
|
||||
min(lengths1.g,
|
||||
min(lengths0.b,
|
||||
lengths1.b)))));
|
||||
}
|
||||
|
||||
float hsluv_maxChromaForLH(float L, float H) {
|
||||
|
||||
float hrad = radians(H);
|
||||
|
||||
mat3 m2 = mat3(
|
||||
3.2409699419045214 ,-0.96924363628087983 , 0.055630079696993609,
|
||||
-1.5373831775700935 , 1.8759675015077207 ,-0.20397695888897657 ,
|
||||
-0.49861076029300328 , 0.041555057407175613, 1.0569715142428786
|
||||
);
|
||||
float sub1 = pow(L + 16.0, 3.0) / 1560896.0;
|
||||
float sub2 = mix(L / 903.2962962962963, sub1, step(0.0088564516790356308, sub1));
|
||||
|
||||
vec3 top1 = (284517.0 * m2[0] - 94839.0 * m2[2]) * sub2;
|
||||
vec3 bottom = (632260.0 * m2[2] - 126452.0 * m2[1]) * sub2;
|
||||
vec3 top2 = (838422.0 * m2[2] + 769860.0 * m2[1] + 731718.0 * m2[0]) * L * sub2;
|
||||
|
||||
vec3 bound0x = top1 / bottom;
|
||||
vec3 bound0y = top2 / bottom;
|
||||
|
||||
vec3 bound1x = top1 / (bottom+126452.0);
|
||||
vec3 bound1y = (top2-769860.0*L) / (bottom+126452.0);
|
||||
|
||||
vec3 lengths0 = hsluv_lengthOfRayUntilIntersect(hrad, bound0x, bound0y );
|
||||
vec3 lengths1 = hsluv_lengthOfRayUntilIntersect(hrad, bound1x, bound1y );
|
||||
|
||||
return min(lengths0.r,
|
||||
min(lengths1.r,
|
||||
min(lengths0.g,
|
||||
min(lengths1.g,
|
||||
min(lengths0.b,
|
||||
lengths1.b)))));
|
||||
}
|
||||
|
||||
vec3 hsluv_fromLinear(vec3 c) {
|
||||
return mix(c * 12.92, 1.055 * pow(max(c, vec3(0)), vec3(1.0 / 2.4)) - 0.055, step(0.0031308, c));
|
||||
}
|
||||
|
||||
vec3 hsluv_toLinear(vec3 c) {
|
||||
return mix(c / 12.92, pow(max((c + 0.055) / (1.0 + 0.055), vec3(0)), vec3(2.4)), step(0.04045, c));
|
||||
}
|
||||
|
||||
float hsluv_yToL(float Y){
|
||||
return mix(Y * 903.2962962962963, 116.0 * pow(max(Y, 0), 1.0 / 3.0) - 16.0, step(0.0088564516790356308, Y));
|
||||
}
|
||||
|
||||
float hsluv_lToY(float L) {
|
||||
return mix(L / 903.2962962962963, pow((max(L, 0) + 16.0) / 116.0, 3.0), step(8.0, L));
|
||||
}
|
||||
|
||||
vec3 xyzToRgb(vec3 tuple) {
|
||||
const mat3 m = mat3(
|
||||
3.2409699419045214 ,-1.5373831775700935 ,-0.49861076029300328 ,
|
||||
-0.96924363628087983 , 1.8759675015077207 , 0.041555057407175613,
|
||||
0.055630079696993609,-0.20397695888897657, 1.0569715142428786 );
|
||||
return hsluv_fromLinear(tuple*m);
|
||||
}
|
||||
|
||||
vec3 rgbToXyz(vec3 tuple) {
|
||||
const mat3 m = mat3(
|
||||
0.41239079926595948 , 0.35758433938387796, 0.18048078840183429 ,
|
||||
0.21263900587151036 , 0.71516867876775593, 0.072192315360733715,
|
||||
0.019330818715591851, 0.11919477979462599, 0.95053215224966058
|
||||
);
|
||||
return hsluv_toLinear(tuple) * m;
|
||||
}
|
||||
|
||||
vec3 xyzToLuv(vec3 tuple){
|
||||
float X = tuple.x;
|
||||
float Y = tuple.y;
|
||||
float Z = tuple.z;
|
||||
|
||||
float L = hsluv_yToL(Y);
|
||||
float div = 1. / max(dot(tuple, vec3(1, 15, 3)), 1e-15);
|
||||
|
||||
return vec3(
|
||||
1.,
|
||||
(52. * (X*div) - 2.57179),
|
||||
(117.* (Y*div) - 6.08816)
|
||||
) * L;
|
||||
}
|
||||
|
||||
|
||||
vec3 luvToXyz(vec3 tuple) {
|
||||
float L = tuple.x;
|
||||
|
||||
float U = divide(tuple.y, 13.0 * L) + 0.19783000664283681;
|
||||
float V = divide(tuple.z, 13.0 * L) + 0.468319994938791;
|
||||
|
||||
float Y = hsluv_lToY(L);
|
||||
float X = 2.25 * U * Y / V;
|
||||
float Z = (3./V - 5.)*Y - (X/3.);
|
||||
|
||||
return vec3(X, Y, Z);
|
||||
}
|
||||
|
||||
vec3 luvToLch(vec3 tuple) {
|
||||
float L = tuple.x;
|
||||
float U = tuple.y;
|
||||
float V = tuple.z;
|
||||
|
||||
float C = length(tuple.yz);
|
||||
float H = degrees(atan(V,U));
|
||||
H += 360.0 * step(H, 0.0);
|
||||
|
||||
return vec3(L, C, H);
|
||||
}
|
||||
|
||||
vec3 lchToLuv(vec3 tuple) {
|
||||
float hrad = radians(tuple.b);
|
||||
return vec3(
|
||||
tuple.r,
|
||||
cos(hrad) * tuple.g,
|
||||
sin(hrad) * tuple.g
|
||||
);
|
||||
}
|
||||
|
||||
vec3 hsluvToLch(vec3 tuple) {
|
||||
tuple.g *= hsluv_maxChromaForLH(tuple.b, tuple.r) * .01;
|
||||
return tuple.bgr;
|
||||
}
|
||||
|
||||
vec3 lchToHsluv(vec3 tuple) {
|
||||
tuple.g = divide(tuple.g, hsluv_maxChromaForLH(tuple.r, tuple.b) * .01);
|
||||
return tuple.bgr;
|
||||
}
|
||||
|
||||
vec3 lchToRgb(vec3 tuple) {
|
||||
return xyzToRgb(luvToXyz(lchToLuv(tuple)));
|
||||
}
|
||||
|
||||
vec3 rgbToLch(vec3 tuple) {
|
||||
return luvToLch(xyzToLuv(rgbToXyz(tuple)));
|
||||
}
|
||||
|
||||
vec3 hsluvToRgb(vec3 tuple) {
|
||||
return lchToRgb(hsluvToLch(tuple));
|
||||
}
|
||||
|
||||
vec3 rgbToHsluv(vec3 tuple) {
|
||||
return lchToHsluv(rgbToLch(tuple));
|
||||
}
|
||||
|
||||
vec3 luvToRgb(vec3 tuple){
|
||||
return xyzToRgb(luvToXyz(tuple));
|
||||
}
|
||||
@@ -265,21 +265,31 @@ Then adjust the second parameter until it looks good. Then switch to a light the
|
||||
and adjust the first parameter until the perceived thickness matches the dark theme.
|
||||
''')
|
||||
|
||||
opt('text_fg_override_threshold', 0, option_type='float', long_text='''
|
||||
The minimum accepted difference in luminance between the foreground and background
|
||||
color, below which kitty will override the foreground color. It is percentage
|
||||
ranging from :code:`0` to :code:`100`. If the difference in luminance of the
|
||||
foreground and background is below this threshold, the foreground color will be set
|
||||
to white if the background is dark or black if the background is light. The default
|
||||
value is :code:`0`, which means no overriding is performed. Useful when working with applications
|
||||
opt('text_fg_override_threshold', '0 %', option_type='text_fg_override_threshold', long_text='''
|
||||
A setting to prevent low contrast scenarios, configurable in two different modes (suffix :code:` %` and suffix :code:` ratio`).
|
||||
The default value is :code:`0`, which means no overriding is performed. Useful when working with applications
|
||||
that use colors that do not contrast well with your preferred color scheme.
|
||||
|
||||
A value with the suffix :code:` %` represents the minimum accepted difference in luminance between the foreground and background
|
||||
color, below which kitty will override the foreground color. It is percentage
|
||||
ranging from :code:`0 %` to :code:`100 %`. If the difference in luminance of the
|
||||
foreground and background is below this threshold, the foreground color will be set
|
||||
to white if the background is dark or black if the background is light.
|
||||
|
||||
A value with the suffix :code:` ratio` represents the minimum accepted contrast ratio between the foreground and background color.
|
||||
Possible values range from :code:`0.0 ratio` to :code:`21.0 ratio`.
|
||||
To for example meet :link:`WCAG level AA <https://en.wikipedia.org/wiki/Web_Content_Accessibility_Guidelines>`
|
||||
a value of :code:`4.5 ratio` can be provided.
|
||||
The algorithm is implemented using :link:`HSLuv <https://www.hsluv.org/>` which enables it to change
|
||||
the perceived lightness of a color just as much as needed without really changing its hue and saturation.
|
||||
|
||||
WARNING: Some programs use characters (such as block characters) for graphics
|
||||
display and may expect to be able to set the foreground and background to the
|
||||
same color (or similar colors). If you see unexpected stripes, dots, lines,
|
||||
incorrect color, no color where you expect color, or any kind of graphic
|
||||
display problem try setting :opt:`text_fg_override_threshold` to :code:`0` to
|
||||
see if this is the cause of the problem.
|
||||
see if this is the cause of the problem or consider the minimum contrast ratio (negative value)
|
||||
over the minimum difference as it implements a basic workaround for this scenario.
|
||||
''')
|
||||
|
||||
egr() # }}}
|
||||
|
||||
10
kitty/options/parse.py
generated
10
kitty/options/parse.py
generated
@@ -19,10 +19,10 @@ from kitty.options.utils import (
|
||||
pointer_shape_when_dragging, remote_control_password, resize_debounce_time, scrollback_lines,
|
||||
scrollback_pager_history_size, shell_integration, store_multiple, symbol_map, tab_activity_symbol,
|
||||
tab_bar_edge, tab_bar_margin_height, tab_bar_min_tabs, tab_fade, tab_font_style, tab_separator,
|
||||
tab_title_template, titlebar_color, to_cursor_shape, to_cursor_unfocused_shape, to_font_size,
|
||||
to_layout_names, to_modifiers, transparent_background_colors, underline_exclusion, url_prefixes,
|
||||
url_style, visual_bell_duration, visual_window_select_characters, window_border_width,
|
||||
window_logo_scale, window_size
|
||||
tab_title_template, text_fg_override_threshold, titlebar_color, to_cursor_shape,
|
||||
to_cursor_unfocused_shape, to_font_size, to_layout_names, to_modifiers,
|
||||
transparent_background_colors, underline_exclusion, url_prefixes, url_style, visual_bell_duration,
|
||||
visual_window_select_characters, window_border_width, window_logo_scale, window_size
|
||||
)
|
||||
|
||||
|
||||
@@ -1327,7 +1327,7 @@ class Parser:
|
||||
ans['text_composition_strategy'] = str(val)
|
||||
|
||||
def text_fg_override_threshold(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['text_fg_override_threshold'] = float(val)
|
||||
ans['text_fg_override_threshold'] = text_fg_override_threshold(val)
|
||||
|
||||
def touch_scroll_multiplier(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['touch_scroll_multiplier'] = float(val)
|
||||
|
||||
2
kitty/options/types.py
generated
2
kitty/options/types.py
generated
@@ -614,7 +614,7 @@ class Options:
|
||||
term: str = 'xterm-kitty'
|
||||
terminfo_type: choices_for_terminfo_type = 'path'
|
||||
text_composition_strategy: str = 'platform'
|
||||
text_fg_override_threshold: float = 0.0
|
||||
text_fg_override_threshold: tuple[float, str] = (0.0, '%')
|
||||
touch_scroll_multiplier: float = 1.0
|
||||
transparent_background_colors: tuple[tuple[kitty.fast_data_types.Color, float], ...] = ()
|
||||
undercurl_style: choices_for_undercurl_style = 'thin-sparse'
|
||||
|
||||
@@ -26,6 +26,7 @@ from kitty.conf.utils import (
|
||||
KeyAction,
|
||||
KeyFuncWrapper,
|
||||
currently_parsing,
|
||||
number_with_unit,
|
||||
percent,
|
||||
positive_float,
|
||||
positive_int,
|
||||
@@ -752,6 +753,13 @@ def active_tab_title_template(x: str) -> str | None:
|
||||
return None if x == 'none' else x
|
||||
|
||||
|
||||
def text_fg_override_threshold(x: str) -> tuple[float, str]:
|
||||
value, unit = number_with_unit(x, default_unit='%')
|
||||
if unit not in ['%', 'ratio']:
|
||||
raise ValueError(f'The unit {unit} is not a valid choice for text_fg_override_threshold')
|
||||
return value, unit
|
||||
|
||||
|
||||
ClearOn = Literal['next', 'focus']
|
||||
default_clear_on: tuple[ClearOn, ...] = 'focus', 'next'
|
||||
all_clear_on = get_args(ClearOn)
|
||||
|
||||
@@ -131,8 +131,8 @@ null_replacer = MultiReplacer()
|
||||
|
||||
|
||||
class LoadShaderPrograms:
|
||||
|
||||
text_fg_override_threshold: float = 0
|
||||
text_fg_override_threshold_unit: str = '%'
|
||||
text_old_gamma: bool = False
|
||||
semi_transparent: bool = False
|
||||
cell_program_replacer: MultiReplacer = null_replacer
|
||||
@@ -140,7 +140,10 @@ class LoadShaderPrograms:
|
||||
@property
|
||||
def needs_recompile(self) -> bool:
|
||||
opts = get_options()
|
||||
return opts.text_fg_override_threshold != self.text_fg_override_threshold or (opts.text_composition_strategy == 'legacy') != self.text_old_gamma
|
||||
return (
|
||||
opts.text_fg_override_threshold != (self.text_fg_override_threshold, self.text_fg_override_threshold_unit)
|
||||
or (opts.text_composition_strategy == 'legacy') != self.text_old_gamma
|
||||
)
|
||||
|
||||
def recompile_if_needed(self) -> None:
|
||||
if self.needs_recompile:
|
||||
@@ -150,7 +153,14 @@ class LoadShaderPrograms:
|
||||
self.semi_transparent = semi_transparent
|
||||
opts = get_options()
|
||||
self.text_old_gamma = opts.text_composition_strategy == 'legacy'
|
||||
self.text_fg_override_threshold = max(0, min(opts.text_fg_override_threshold, 100)) * 0.01
|
||||
|
||||
self.text_fg_override_threshold, self.text_fg_override_threshold_unit = opts.text_fg_override_threshold
|
||||
match self.text_fg_override_threshold_unit:
|
||||
case '%':
|
||||
self.text_fg_override_threshold = max(0, min(self.text_fg_override_threshold, 100.0)) * 0.01
|
||||
case 'ratio':
|
||||
self.text_fg_override_threshold = max(0, min(self.text_fg_override_threshold, 21.0))
|
||||
|
||||
cell = program_for('cell')
|
||||
if self.cell_program_replacer is null_replacer:
|
||||
self.cell_program_replacer = MultiReplacer(
|
||||
@@ -168,7 +178,9 @@ class LoadShaderPrograms:
|
||||
r['WHICH_PHASE'] = f'PHASE_{which}'
|
||||
r['TRANSPARENT'] = '1' if semi_transparent else '0'
|
||||
r['FG_OVERRIDE_THRESHOLD'] = str(self.text_fg_override_threshold)
|
||||
r['FG_OVERRIDE'] = '1' if self.text_fg_override_threshold != 0. else '0'
|
||||
r['FG_OVERRIDE'] = str(int(bool(self.text_fg_override_threshold_unit == '%')))
|
||||
r['MIN_CONTRAST_RATIO'] = str(self.text_fg_override_threshold)
|
||||
r['APPLY_MIN_CONTRAST_RATIO'] = str(int(bool(self.text_fg_override_threshold_unit == 'ratio')))
|
||||
r['TEXT_NEW_GAMMA'] = '0' if self.text_old_gamma else '1'
|
||||
return self.cell_program_replacer(src)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user