Make the bundled fonts available on all platforms

This commit is contained in:
Kovid Goyal 2012-10-22 10:56:42 +05:30
parent a69112b3e4
commit 7c18f4f0d2
8 changed files with 71 additions and 40 deletions

View File

@ -9,6 +9,7 @@ let g:syntastic_cpp_include_dirs = [
\'/usr/include/qt4/QtGui', \'/usr/include/qt4/QtGui',
\'/usr/include/qt4', \'/usr/include/qt4',
\'/usr/include/freetype2', \'/usr/include/freetype2',
\'/usr/include/fontconfig',
\'src/qtcurve/common', 'src/qtcurve', \'src/qtcurve/common', 'src/qtcurve',
\'/usr/include/ImageMagick', \'/usr/include/ImageMagick',
\] \]

View File

@ -329,6 +329,7 @@ def get_parsed_proxy(typ='http', debug=True):
ans['port'] = int(ans['port']) ans['port'] = int(ans['port'])
except: except:
if debug: if debug:
import traceback
traceback.print_exc() traceback.print_exc()
else: else:
if debug: if debug:
@ -689,26 +690,18 @@ def remove_bracketed_text(src,
buf.append(char) buf.append(char)
return u''.join(buf) return u''.join(buf)
if isosx:
import glob, shutil
fdir = os.path.expanduser('~/.fonts')
try:
if not os.path.exists(fdir):
os.makedirs(fdir)
if not os.path.exists(os.path.join(fdir, 'LiberationSans_Regular.ttf')):
base = P('fonts/liberation/*.ttf')
for f in glob.glob(base):
shutil.copy2(f, fdir)
except:
import traceback
traceback.print_exc()
def load_builtin_fonts(): def load_builtin_fonts():
if iswindows or isosx:
import glob import glob
from PyQt4.Qt import QFontDatabase from PyQt4.Qt import QFontDatabase
base = P('fonts/liberation/*.ttf') for f in glob.glob(P('fonts/liberation/*.ttf')):
for f in glob.glob(base):
QFontDatabase.addApplicationFont(f) QFontDatabase.addApplicationFont(f)
else:
# On linux these are loaded by fontconfig which means that
# they are available to Qt as well, since Qt uses fontconfig
from calibre.utils.fonts import fontconfig
fontconfig
return 'Liberation Serif', 'Liberation Sans', 'Liberation Mono' return 'Liberation Serif', 'Liberation Sans', 'Liberation Mono'

View File

@ -12,7 +12,7 @@ from PyQt4.Qt import (QVariant, QFileInfo, QObject, SIGNAL, QBuffer, Qt,
ORG_NAME = 'KovidsBrain' ORG_NAME = 'KovidsBrain'
APP_UID = 'libprs500' APP_UID = 'libprs500'
from calibre import prints from calibre import prints, load_builtin_fonts
from calibre.constants import (islinux, iswindows, isbsd, isfrozen, isosx, from calibre.constants import (islinux, iswindows, isbsd, isfrozen, isosx,
plugins, config_dir, filesystem_encoding, DEBUG) plugins, config_dir, filesystem_encoding, DEBUG)
from calibre.utils.config import Config, ConfigProxy, dynamic, JSONConfig from calibre.utils.config import Config, ConfigProxy, dynamic, JSONConfig
@ -779,6 +779,7 @@ class Application(QApplication):
qt_app = self qt_app = self
self._file_open_paths = [] self._file_open_paths = []
self._file_open_lock = RLock() self._file_open_lock = RLock()
load_builtin_fonts()
self.setup_styles(force_calibre_style) self.setup_styles(force_calibre_style)
if DEBUG: if DEBUG:

View File

@ -16,7 +16,7 @@ from PyQt4.QtWebKit import QWebPage, QWebView, QWebSettings
from calibre.gui2.viewer.flip import SlideFlip from calibre.gui2.viewer.flip import SlideFlip
from calibre.gui2.shortcuts import Shortcuts from calibre.gui2.shortcuts import Shortcuts
from calibre import prints, load_builtin_fonts from calibre import prints
from calibre.customize.ui import all_viewer_plugins from calibre.customize.ui import all_viewer_plugins
from calibre.gui2.viewer.keys import SHORTCUTS from calibre.gui2.viewer.keys import SHORTCUTS
from calibre.gui2.viewer.javascript import JavaScriptLoader from calibre.gui2.viewer.javascript import JavaScriptLoader
@ -86,7 +86,6 @@ class Document(QWebPage): # {{{
settings = self.settings() settings = self.settings()
# Fonts # Fonts
load_builtin_fonts()
self.all_viewer_plugins = tuple(all_viewer_plugins()) self.all_viewer_plugins = tuple(all_viewer_plugins())
for pl in self.all_viewer_plugins: for pl in self.all_viewer_plugins:
pl.load_fonts() pl.load_fonts()

View File

@ -111,9 +111,9 @@ fontconfig = Fonts()
def test(): def test():
import os import os
print(fontconfig.find_font_families()) print(fontconfig.find_font_families())
m = 'times new roman' if iswindows else 'liberation serif' m = 'Liberation Serif'
for ft, val in fontconfig.files_for_family(m).iteritems(): for ft, val in fontconfig.files_for_family(m).iteritems():
print val[0], ft, val[1], os.path.getsize(val[1]) print val[0], ft, val[1], os.path.getsize(val[0])
if __name__ == '__main__': if __name__ == '__main__':
test() test()

View File

@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
import os, sys import os, sys
from calibre.constants import plugins, iswindows, islinux, isbsd from calibre.constants import plugins, islinux, isbsd
_fc, _fc_err = plugins['fontconfig'] _fc, _fc_err = plugins['fontconfig']
@ -35,18 +35,14 @@ class FontConfig(Thread):
if isinstance(config_dir, unicode): if isinstance(config_dir, unicode):
config_dir = config_dir.encode(sys.getfilesystemencoding()) config_dir = config_dir.encode(sys.getfilesystemencoding())
config = os.path.join(config_dir, 'fonts.conf') config = os.path.join(config_dir, 'fonts.conf')
if iswindows and getattr(sys, 'frozen', False):
config_dir = os.path.join(os.path.dirname(sys.executable),
'fontconfig')
if isinstance(config_dir, unicode):
config_dir = config_dir.encode(sys.getfilesystemencoding())
config = os.path.join(config_dir, 'fonts.conf')
try: try:
_fc.initialize(config) _fc.initialize(config)
except: except:
import traceback import traceback
traceback.print_exc() traceback.print_exc()
self.failed = True self.failed = True
if not self.failed and hasattr(_fc, 'add_font_dir'):
_fc.add_font_dir(P('fonts/liberation'))
def wait(self): def wait(self):
if not (islinux or isbsd): if not (islinux or isbsd):
@ -162,7 +158,7 @@ def test():
from pprint import pprint; from pprint import pprint;
pprint(fontconfig.find_font_families()) pprint(fontconfig.find_font_families())
pprint(fontconfig.files_for_family('liberation serif')) pprint(fontconfig.files_for_family('liberation serif'))
m = 'times new roman' if iswindows else 'liberation serif' m = 'liberation serif'
pprint(fontconfig.match(m+':slant=italic:weight=bold', verbose=True)) pprint(fontconfig.match(m+':slant=italic:weight=bold', verbose=True))
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -44,6 +44,17 @@ fontconfig_initialize(PyObject *self, PyObject *args) {
Py_RETURN_FALSE; Py_RETURN_FALSE;
} }
static PyObject*
fontconfig_add_font_dir(PyObject *self, PyObject *args) {
FcChar8 *path;
if (!PyArg_ParseTuple(args, "s", &path)) return NULL;
if (FcConfigAppFontAddDir(NULL, path))
Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
static void static void
fontconfig_cleanup_find(FcPattern *p, FcObjectSet *oset, FcFontSet *fs) { fontconfig_cleanup_find(FcPattern *p, FcObjectSet *oset, FcFontSet *fs) {
if (p != NULL) FcPatternDestroy(p); if (p != NULL) FcPatternDestroy(p);
@ -314,6 +325,11 @@ PyMethodDef fontconfig_methods[] = {
}, },
{"add_font_dir", fontconfig_add_font_dir, METH_VARARGS,
"add_font_dir(path_to_dir)\n\n"
"Add the fonts in the specified directory to the list of application specific fonts."
},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };

View File

@ -19,6 +19,23 @@ class WinFonts(object):
def __init__(self, winfonts): def __init__(self, winfonts):
self.w = winfonts self.w = winfonts
# Windows thinks the Liberation font files are not valid, so we use
# this hack to make them available
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): def font_families(self):
names = set() names = set()
@ -30,7 +47,7 @@ class WinFonts(object):
not font['name'].startswith('@') not font['name'].startswith('@')
): ):
names.add(font['name']) names.add(font['name'])
return sorted(names) return sorted(names.union(frozenset(self.app_font_families)))
def get_normalized_name(self, is_italic, weight): def get_normalized_name(self, is_italic, weight):
if is_italic: if is_italic:
@ -43,6 +60,12 @@ class WinFonts(object):
family = type(u'')(family) family = type(u'')(family)
ans = {} ans = {}
for weight, is_italic in product( (self.w.FW_NORMAL, self.w.FW_BOLD), (False, True) ): 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: try:
data = self.w.font_data(family, is_italic, weight) data = self.w.font_data(family, is_italic, weight)
except Exception as e: except Exception as e:
@ -122,7 +145,7 @@ def test_ttf_reading():
get_font_characteristics(raw) get_font_characteristics(raw)
print() print()
if __name__ == '__main__': def test():
base = os.path.abspath(__file__) base = os.path.abspath(__file__)
d = os.path.dirname d = os.path.dirname
pluginsd = os.path.join(d(d(d(base))), 'plugins') pluginsd = os.path.join(d(d(d(base))), 'plugins')
@ -143,3 +166,5 @@ if __name__ == '__main__':
prints(' ', font, data[0], data[1], len(data[2])) prints(' ', font, data[0], data[1], len(data[2]))
print () print ()
if __name__ == '__main__':
test()