From 35bde798b6cda13579337b0ec5a803fdd5eab19a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isma=C3=ABl=20Bouya?= Date: Wed, 27 Jul 2016 19:32:38 +0200 Subject: Remove fonts from directory --- helpers/__init__.py | 34 ++++++++ helpers/sysfont.py | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 258 insertions(+) create mode 100644 helpers/sysfont.py (limited to 'helpers') diff --git a/helpers/__init__.py b/helpers/__init__.py index f1a968b..4827e6c 100644 --- a/helpers/__init__.py +++ b/helpers/__init__.py @@ -6,9 +6,43 @@ import math import sounddevice as sd import logging +from . import sysfont + class Config: pass +def find_font(name, style=sysfont.STYLE_NONE): + if getattr(sys, 'frozen', False): + font = sys._MEIPASS + "/fonts/{}_{}.ttf".format(name, style) + else: + font = sysfont.get_font(name, style=style) + if font is not None: + font = font[4] + return font + +def register_fonts(): + from kivy.core.text import LabelBase + + ubuntu_regular = find_font("Ubuntu", style=sysfont.STYLE_NORMAL) + ubuntu_bold = find_font("Ubuntu", style=sysfont.STYLE_BOLD) + symbola = find_font("Symbola") + + if ubuntu_regular is None: + error_print("Font Ubuntu regular could not be found, please install it.") + sys.exit() + if symbola is None: + error_print("Font Symbola could not be found, please install it.") + sys.exit() + if ubuntu_bold is None: + warn_print("Font Ubuntu Bold could not be found.") + + LabelBase.register(name="Ubuntu", + fn_regular=ubuntu_regular, + fn_bold=ubuntu_bold) + LabelBase.register(name="Symbola", + fn_regular=symbola) + + def path(): if getattr(sys, 'frozen', False): return sys._MEIPASS + "/" diff --git a/helpers/sysfont.py b/helpers/sysfont.py new file mode 100644 index 0000000..f47693e --- /dev/null +++ b/helpers/sysfont.py @@ -0,0 +1,224 @@ +# This file was imported from +# https://bitbucket.org/marcusva/python-utils/overview +# And slightly adapted + +"""OS-specific font detection.""" +import os +import sys +from subprocess import Popen, PIPE + +if sys.platform in ("win32", "cli"): + import winreg + +__all__ = ["STYLE_NORMAL", "STYLE_BOLD", "STYLE_ITALIC", "STYLE_LIGHT", + "init", "list_fonts", "get_fonts", "get_font" + ] + +# Font cache entries: +# { family : [..., +# (name, styles, fonttype, filename) +# ... +# ] +# } +__FONTCACHE = None + + +STYLE_NONE = 0x00 +STYLE_NORMAL = 0x01 +STYLE_BOLD = 0x02 +STYLE_ITALIC = 0x04 +STYLE_LIGHT = 0x08 +STYLE_MEDIUM = 0x10 + +def _add_font(family, name, styles, fonttype, filename): + """Adds a font to the internal font cache.""" + global __FONTCACHE + + if family not in __FONTCACHE: + __FONTCACHE[family] = [] + __FONTCACHE[family].append((name, styles, fonttype, filename)) + + +def _cache_fonts_win32(): + """Caches fonts on a Win32 platform.""" + key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts" + regfonts = [] + try: + with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key) as fontkey: + idx = 0 + enumval = winreg.EnumValue + rappend = regfonts.append + while True: + rappend(enumval(fontkey, idx)[:2]) + idx += 1 + except WindowsError: + pass + + # TODO: integrate alias handling for fonts within the registry. + # TODO: Scan and index fonts from %SystemRoot%\\Fonts that are not in the + # registry + + # Received all fonts from the registry. + for name, filename in regfonts: + fonttype = os.path.splitext(filename)[1][1:].lower() + if name.endswith("(TrueType)"): + name = name[:-10].strip() + if name.endswith("(All Res)"): + name = name[:-9].strip() + style = STYLE_NORMAL + if name.find(" Bold") >= 0: + style |= STYLE_BOLD + if name.find(" Italic") >= 0 or name.find(" Oblique") >= 0: + style |= STYLE_ITALIC + + family = name + for rm in ("Bold", "Italic", "Oblique"): + family = family.replace(rm, "") + family = family.lower().strip() + + fontpath = os.environ.get("SystemRoot", "C:\\Windows") + fontpath = os.path.join(fontpath, "Fonts") + if filename.find("\\") == -1: + # No path delimiter is given; we assume it to be a font in + # %SystemRoot%\Fonts + filename = os.path.join(fontpath, filename) + _add_font(family, name, style, fonttype, filename) + + +def _cache_fonts_darwin(): + """Caches fonts on Mac OS.""" + raise NotImplementedError("Mac OS X support is not given yet") + + +def _cache_fonts_fontconfig(): + """Caches font on POSIX-alike platforms.""" + try: + command = "fc-list : file family style fullname fullnamelang" + proc = Popen(command, stdout=PIPE, shell=True, stderr=PIPE) + pout = proc.communicate()[0] + output = pout.decode("utf-8") + except OSError: + return + + for entry in output.split(os.linesep): + if entry.strip() == "": + continue + values = entry.split(":") + filename = values[0] + + # get the font type + fname, fonttype = os.path.splitext(filename) + if fonttype == ".gz": + fonttype = os.path.splitext(fname)[1][1:].lower() + else: + fonttype = fonttype.lstrip(".").lower() + + # get the font name + name = None + if len(values) > 3: + fullnames, fullnamelangs = values[3:] + langs = fullnamelangs.split(",") + try: + offset = langs.index("fullnamelang=en") + except ValueError: + offset = -1 + if offset == -1: + try: + offset = langs.index("en") + except ValueError: + offset = -1 + if offset != -1: + # got an english name, use that one + name = fullnames.split(",")[offset] + if name.startswith("fullname="): + name = name[9:] + if name is None: + if fname.endswith(".pcf") or fname.endswith(".bdf"): + name = os.path.basename(fname[:-4]) + else: + name = os.path.basename(fname) + name = name.lower() + + # family and styles + family = values[1].strip().lower() + stylevals = values[2].strip() + style = STYLE_NONE + + if stylevals.find("Bold") >= 0: + style |= STYLE_BOLD + if stylevals.find("Light") >= 0: + style |= STYLE_LIGHT + if stylevals.find("Italic") >= 0 or stylevals.find("Oblique") >= 0: + style |= STYLE_ITALIC + if stylevals.find("Medium") >= 0: + style |= STYLE_MEDIUM + if style == STYLE_NONE: + style = STYLE_NORMAL + _add_font(family, name, style, fonttype, filename) + + +def init(): + """Initialises the internal font cache. + + It does not need to be called explicitly. + """ + global __FONTCACHE + if __FONTCACHE is not None: + return + __FONTCACHE = {} + if sys.platform in ("win32", "cli"): + _cache_fonts_win32() + elif sys.platform == "darwin": + _cache_fonts_darwin() + else: + _cache_fonts_fontconfig() + + +def list_fonts(): + """Returns an iterator over the cached fonts.""" + if __FONTCACHE is None: + init() + if len(__FONTCACHE) == 0: + yield None + for family, entries in __FONTCACHE.items(): + for fname, styles, fonttype, filename in entries: + yield (family, fname, styles, fonttype, filename) + + +def get_fonts(name, style=STYLE_NONE, ftype=None): + """Retrieves all fonts matching the given family or font name.""" + if __FONTCACHE is None: + init() + if len(__FONTCACHE) == 0: + return None + + results = [] + rappend = results.append + + name = name.lower() + if ftype: + ftype = ftype.lower() + + fonts = __FONTCACHE.get(name, []) + for fname, fstyles, fonttype, filename in fonts: + if ftype and fonttype != ftype: + # ignore font filetype mismatches + continue + if style == STYLE_NONE or fstyles == style: + rappend((name, fname, fstyles, fonttype, filename)) + + for family, fonts in __FONTCACHE.items(): + for fname, fstyles, fonttype, filename in fonts: + if fname.lower() == name and filename not in results: + rappend((family, fname, fstyles, fonttype, filename)) + return results + + +def get_font(name, style=STYLE_NONE, ftype=None): + """Retrieves the best matching font file for the given name and + criteria. + """ + retvals = get_fonts(name, style, ftype) + if len(retvals) > 0: + return retvals[0] + return None -- cgit v1.2.3