%PDF- %PDF-
| Direktori : /usr/lib/calibre/calibre/utils/fonts/ |
| Current File : //usr/lib/calibre/calibre/utils/fonts/win_fonts.py |
#!/usr/bin/env python3
__license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import os, sys, atexit
from itertools import product
from calibre import prints, isbytestring
from calibre.constants import filesystem_encoding
from calibre.utils.fonts.utils import (is_truetype_font, get_font_names,
get_font_characteristics)
from polyglot.builtins import iteritems
class WinFonts:
def __init__(self, winfonts):
self.w = winfonts
# Windows requires font files to be executable for them to be loaded,
# so instead we use this hack.
self.app_font_families = {}
for f in ('Serif', 'Sans', 'Mono'):
base = 'fonts/liberation/Liberation%s-%s.ttf'
self.app_font_families['Liberation %s'%f] = m = {}
for weight, is_italic in product((self.w.FW_NORMAL, self.w.FW_BOLD), (False, True)):
name = {(self.w.FW_NORMAL, False):'Regular',
(self.w.FW_NORMAL, True):'Italic',
(self.w.FW_BOLD, False):'Bold',
(self.w.FW_BOLD, True):'BoldItalic'}[(weight,
is_italic)]
m[(weight, is_italic)] = base%(f, name)
# import pprint
# pprint.pprint(self.app_font_families)
def font_families(self):
names = set()
for font in self.w.enum_font_families():
if (
font['is_truetype'] and
# Fonts with names starting with @ are designed for
# vertical text
not font['name'].startswith('@')
):
names.add(font['name'])
return sorted(names.union(frozenset(self.app_font_families)))
def get_normalized_name(self, is_italic, weight):
if is_italic:
ft = 'bi' if weight == self.w.FW_BOLD else 'italic'
else:
ft = 'bold' if weight == self.w.FW_BOLD else 'normal'
return ft
def fonts_for_family(self, family, normalize=True):
family = str(family)
ans = {}
for weight, is_italic in product((self.w.FW_NORMAL, self.w.FW_BOLD), (False, True)):
if family in self.app_font_families:
m = self.app_font_families[family]
path = m.get((weight, is_italic), None)
if path is None:
continue
data = P(path, data=True)
else:
try:
data = self.w.font_data(family, is_italic, weight)
except Exception as e:
prints('Failed to get font data for font: %s [%s] with error: %s'%
(family, self.get_normalized_name(is_italic, weight), e))
continue
ok, sig = is_truetype_font(data)
if not ok:
prints('Not a supported font, sfnt_version: %r'%sig)
continue
ext = 'otf' if sig == b'OTTO' else 'ttf'
try:
weight, is_italic, is_bold, is_regular = get_font_characteristics(data)[:4]
except Exception as e:
prints('Failed to get font characteristic for font: %s [%s]'
' with error: %s'%(family,
self.get_normalized_name(is_italic, weight), e))
continue
try:
family_name, sub_family_name, full_name = get_font_names(data)
except:
pass
if normalize:
ft = {(True, True):'bi', (True, False):'italic', (False,
True):'bold', (False, False):'normal'}[(is_italic,
is_bold)]
else:
ft = (1 if is_italic else 0, weight//10)
if not (family_name or full_name):
# prints('Font %s [%s] has no names'%(family,
# self.get_normalized_name(is_italic, weight)))
family_name = family
name = full_name or family + ' ' + (sub_family_name or '')
try:
name.encode('ascii')
except ValueError:
try:
sub_family_name.encode('ascii')
subf = sub_family_name
except:
subf = ''
name = family + ((' ' + subf) if subf else '')
ans[ft] = (ext, name, data)
return ans
def add_system_font(self, path):
'''
WARNING: The file you are adding must have execute permissions or
windows will fail to add it. (ls -l in cygwin to check)
'''
if isbytestring(path):
path = path.decode(filesystem_encoding)
path = os.path.abspath(path)
ret = self.w.add_system_font(path)
if ret > 0:
atexit.register(self.remove_system_font, path)
return ret
def remove_system_font(self, path):
return self.w.remove_system_font(path)
def load_winfonts():
from calibre_extensions import winfonts
return WinFonts(winfonts)
def test_ttf_reading():
for arg in sys.argv[1:]:
with open(arg, 'rb') as f:
raw = f.read()
print(os.path.basename(arg))
get_font_characteristics(raw)
print()
def test():
base = os.path.abspath(__file__)
d = os.path.dirname
pluginsd = os.path.join(d(d(d(base))), 'plugins')
if os.path.exists(os.path.join(pluginsd, 'winfonts.pyd')):
sys.path.insert(0, pluginsd)
import winfonts
w = WinFonts(winfonts)
else:
w = load_winfonts()
print(w.w)
families = w.font_families()
print(families)
for family in families:
prints(family + ':')
for font, data in iteritems(w.fonts_for_family(family)):
prints(' ', font, data[0], data[1], len(data[2]))
print()
if __name__ == '__main__':
test()