diff --git a/kitty/boss.py b/kitty/boss.py index 0e3f02939..5f98093ff 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -22,7 +22,7 @@ from .fast_data_types import ( GLFW_REPEAT, GLFW_MOUSE_BUTTON_1, glfw_post_empty_event, GLFW_CURSOR_NORMAL, GLFW_CURSOR, GLFW_CURSOR_HIDDEN, drain_read ) -from .fonts import set_font_family +from .fonts.render import set_font_family from .borders import BordersProgram from .char_grid import cursor_shader, cell_shader from .constants import is_key_pressed diff --git a/kitty/fonts/__init__.py b/kitty/fonts/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/kitty/fonts/fontconfig.py b/kitty/fonts/fontconfig.py new file mode 100644 index 000000000..81fadf24e --- /dev/null +++ b/kitty/fonts/fontconfig.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2016, Kovid Goyal + +import re +import subprocess +from collections import namedtuple +from functools import lru_cache +from kitty.fast_data_types import Face + + +def escape_family_name(name): + return re.sub(r'([-:,\\])', lambda m: '\\' + m.group(1), name) + + +Font = namedtuple('Font', 'face hinting hintstyle bold italic') + + +def get_font(query, bold, italic): + query += ':scalable=true:outline=true' + raw = subprocess.check_output(['fc-match', query, '-f', '%{file}\x1e%{hinting}\x1e%{hintstyle}']).decode('utf-8') + parts = raw.split('\x1e') + hintstyle, hinting = 1, 'True' + if len(parts) == 3: + path, hinting, hintstyle = parts + else: + path = parts[0] + hinting = hinting.lower() == 'true' + hintstyle = int(hintstyle) + return Font(path, hinting, hintstyle, bold, italic) + + +@lru_cache(maxsize=4096) +def find_font_for_character(family, char, bold=False, italic=False): + q = escape_family_name(family) + ':charset={}'.format(hex(ord(char[0]))[2:]) + if bold: + q += ':weight=200' + if italic: + q += ':slant=100' + return get_font(q, bold, italic) + + +@lru_cache(maxsize=64) +def get_font_information(q, bold=False, italic=False): + q = escape_family_name(q) + if bold: + q += ':weight=200' + if italic: + q += ':slant=100' + return get_font(q, bold, italic) + + +def get_font_files(family): + ans = {} + n = get_font_information(family) + ans['regular'] = Font(Face(n.face), n.hinting, n.hintstyle, n.bold, n.italic) + + def do(key): + b = get_font_information(family, bold=key in ('bold', 'bi'), italic=key in ('italic', 'bi')) + if b.face != n.face: + ans[key] = Font(Face(b.face), b.hinting, b.hintstyle, b.bold, b.italic) + do('bold'), do('italic'), do('bi') + return ans diff --git a/kitty/fonts.py b/kitty/fonts/freetype.py similarity index 84% rename from kitty/fonts.py rename to kitty/fonts/freetype.py index 9c59309d9..ba089448a 100644 --- a/kitty/fonts.py +++ b/kitty/fonts/freetype.py @@ -2,72 +2,17 @@ # vim:fileencoding=utf-8 # License: GPL v3 Copyright: 2016, Kovid Goyal -import subprocess import unicodedata -import re import ctypes import math from collections import namedtuple from functools import lru_cache from threading import Lock -from .fast_data_types import Face, FT_PIXEL_MODE_GRAY +from kitty.fast_data_types import Face, FT_PIXEL_MODE_GRAY +from .fontconfig import find_font_for_character, get_font_files -from .utils import get_logical_dpi, wcwidth - - -def escape_family_name(name): - return re.sub(r'([-:,\\])', lambda m: '\\' + m.group(1), name) - - -Font = namedtuple('Font', 'face hinting hintstyle bold italic') - - -def get_font(query, bold, italic): - query += ':scalable=true:outline=true' - raw = subprocess.check_output(['fc-match', query, '-f', '%{file}\x1e%{hinting}\x1e%{hintstyle}']).decode('utf-8') - parts = raw.split('\x1e') - hintstyle, hinting = 1, 'True' - if len(parts) == 3: - path, hinting, hintstyle = parts - else: - path = parts[0] - hinting = hinting.lower() == 'true' - hintstyle = int(hintstyle) - return Font(path, hinting, hintstyle, bold, italic) - - -@lru_cache(maxsize=4096) -def find_font_for_character(family, char, bold=False, italic=False): - q = escape_family_name(family) + ':charset={}'.format(hex(ord(char[0]))[2:]) - if bold: - q += ':weight=200' - if italic: - q += ':slant=100' - return get_font(q, bold, italic) - - -@lru_cache(maxsize=64) -def get_font_information(q, bold=False, italic=False): - q = escape_family_name(q) - if bold: - q += ':weight=200' - if italic: - q += ':slant=100' - return get_font(q, bold, italic) - - -def get_font_files(family): - ans = {} - n = get_font_information(family) - ans['regular'] = Font(Face(n.face), n.hinting, n.hintstyle, n.bold, n.italic) - - def do(key): - b = get_font_information(family, bold=key in ('bold', 'bi'), italic=key in ('italic', 'bi')) - if b.face != n.face: - ans[key] = Font(Face(b.face), b.hinting, b.hintstyle, b.bold, b.italic) - do('bold'), do('italic'), do('bi') - return ans +from kitty.utils import get_logical_dpi, wcwidth current_font_family = current_font_family_name = cff_size = cell_width = cell_height = baseline = None diff --git a/kitty/fonts/render.py b/kitty/fonts/render.py new file mode 100644 index 000000000..f20600144 --- /dev/null +++ b/kitty/fonts/render.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2016, Kovid Goyal + +from .freetype import set_font_family, render_cell # noqa diff --git a/kitty/shaders.py b/kitty/shaders.py index d27355199..b1c932982 100644 --- a/kitty/shaders.py +++ b/kitty/shaders.py @@ -6,7 +6,7 @@ from ctypes import addressof, sizeof from functools import lru_cache from threading import Lock -from .fonts import render_cell +from .fonts.render import render_cell from .fast_data_types import ( glCreateProgram, glAttachShader, GL_FRAGMENT_SHADER, GL_VERTEX_SHADER, glLinkProgram, GL_TRUE, GL_LINK_STATUS, glGetProgramiv,