diff --git a/osx_installer.py b/osx_installer.py
index 84e1c6eaf5..ce9ee98f5c 100644
--- a/osx_installer.py
+++ b/osx_installer.py
@@ -240,6 +240,9 @@ _check_symlinks_prescript()
os.link(os.path.expanduser('~/pdftohtml'), os.path.join(frameworks_dir, 'pdftohtml'))
print 'Adding plugins'
module_dir = os.path.join(resource_dir, 'lib', 'python2.5', 'lib-dynload')
+ print 'Adding fontconfig'
+ for f in glob.glob(os.path.expanduser('~/fontconfig/*')):
+ os.link(f, os.path.join(frameworks_dir, os.path.basename(f)))
for src, dest in plugin_files:
if 'dylib' in dest:
os.link(src, os.path.join(frameworks_dir, dest))
diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py
index 23befd12dd..ccfcdd5113 100644
--- a/src/calibre/__init__.py
+++ b/src/calibre/__init__.py
@@ -15,15 +15,14 @@ from optparse import OptionParser as _OptionParser
from optparse import IndentedHelpFormatter
from logging import Formatter
-from ttfquery import findsystem, describe
from PyQt4.QtCore import QSettings, QVariant, QUrl
from PyQt4.QtGui import QDesktopServices
from calibre.translations.msgfmt import make
from calibre.ebooks.chardet import detect
from calibre.terminfo import TerminalController
-terminal_controller = TerminalController(sys.stdout)
+terminal_controller = TerminalController(sys.stdout)
iswindows = 'win32' in sys.platform.lower() or 'win64' in sys.platform.lower()
isosx = 'darwin' in sys.platform.lower()
islinux = not(iswindows or isosx)
@@ -306,44 +305,6 @@ def set_translator():
set_translator()
-font_families = {}
-def get_font_families(cached=None):
- global font_families
- if cached is not None:
- font_families = cached
- if not font_families:
- try:
- ffiles = findsystem.findFonts()
- except Exception, err:
- print 'WARNING: Could not find fonts on your system.'
- print err
- else:
- zlist = []
- for ff in ffiles:
- try:
- if 'Optane' in str(ff):
- font = describe.openFont(ff)
- wt, italic = describe.modifiers(font)
- except:
- pass
- try:
- font = describe.openFont(ff)
- except: # Some font files cause ttfquery to raise an exception, in which case they are ignored
- continue
- try:
- wt, italic = describe.modifiers(font)
- except:
- wt, italic = 0, 0
- if wt == 400 and italic == 0:
- try:
- family = describe.shortName(font)[1].strip()
- except: # Windows strikes again!
- continue
- zlist.append((family, ff))
- font_families = dict(zlist)
-
- return font_families
-
def sanitize_file_name(name):
'''
Remove characters that are illegal in filenames from name.
@@ -596,3 +557,12 @@ def entity_to_unicode(match, exceptions=[], encoding='cp1252'):
except KeyError:
return '&'+ent+';'
+if isosx:
+ fdir = os.path.expanduser('~/.fonts')
+ if not os.path.exists(fdir):
+ os.makedirs(fdir)
+ if not os.path.exists(os.path.join(fdir, 'LiberationSans_Regular.ttf')):
+ from calibre.ebooks.lrf.fonts.liberation import __all__ as fonts
+ for font in fonts:
+ exec 'from calibre.ebooks.lrf.fonts.liberation.'+font+' import font_data'
+ open(os.path.join(fdir, font+'.ttf'), 'wb').write(font_data)
\ No newline at end of file
diff --git a/src/calibre/ebooks/lrf/__init__.py b/src/calibre/ebooks/lrf/__init__.py
index 990ce6b08d..02882312a8 100644
--- a/src/calibre/ebooks/lrf/__init__.py
+++ b/src/calibre/ebooks/lrf/__init__.py
@@ -9,7 +9,6 @@ from optparse import OptionValueError
from htmlentitydefs import name2codepoint
from uuid import uuid4
-from ttfquery import describe, findsystem
from fontTools.ttLib import TTLibError
from calibre.ebooks.lrf.pylrs.pylrs import Book as _Book
@@ -67,20 +66,6 @@ def profile_from_string(option, opt_str, value, parser):
except KeyError:
raise OptionValueError('Profile: '+value+' is not implemented. Implemented profiles: %s'%(profile_map.keys()))
-def font_family(option, opt_str, value, parser):
- if value:
- value = value.split(',')
- if len(value) != 2:
- raise OptionValueError('Font family specification must be of the form'+\
- ' "path to font directory, font family"')
- path, family = tuple(value)
- if not os.path.isdir(path) or not os.access(path, os.R_OK|os.X_OK):
- raise OptionValueError('Cannot read from ' + path)
- setattr(parser.values, option.dest, (path, family))
- else:
- setattr(parser.values, option.dest, tuple())
-
-
def option_parser(usage, gui_mode=False):
parser = OptionParser(usage=usage, gui_mode=gui_mode)
metadata = parser.add_option_group('METADATA OPTIONS')
@@ -203,18 +188,17 @@ def option_parser(usage, gui_mode=False):
fonts = parser.add_option_group('FONT FAMILIES',
_('''Specify trutype font families for serif, sans-serif and monospace fonts. '''
'''These fonts will be embedded in the LRF file. Note that custom fonts lead to '''
- '''slower page turns. Each family specification is of the form: '''
- '''"path to fonts directory, family" '''
+ '''slower page turns. '''
'''For example: '''
- '''--serif-family "%s, Times New Roman"
- ''') % ('C:\Windows\Fonts' if iswindows else '/usr/share/fonts/corefonts'))
- fonts.add_option('--serif-family', action='callback', callback=font_family,
+ '''--serif-family "Times New Roman"
+ '''))
+ fonts.add_option('--serif-family',
default=None, dest='serif_family', type='string',
help=_('The serif family of fonts to embed'))
- fonts.add_option('--sans-family', action='callback', callback=font_family,
+ fonts.add_option('--sans-family',
default=None, dest='sans_family', type='string',
help=_('The sans-serif family of fonts to embed'))
- fonts.add_option('--mono-family', action='callback', callback=font_family,
+ fonts.add_option('--mono-family',
default=None, dest='mono_family', type='string',
help=_('The monospace family of fonts to embed'))
@@ -231,45 +215,25 @@ def option_parser(usage, gui_mode=False):
return parser
def find_custom_fonts(options, logger):
+ from calibre.utils.fontconfig import files_for_family
fonts = {'serif' : None, 'sans' : None, 'mono' : None}
- def find_family(option):
- path, family = option
- paths = findsystem.findFonts([path])
- results = {}
- for path in paths:
- if len(results.keys()) == 4:
- break
- f = describe.openFont(path)
- name, cfamily = describe.shortName(f)
- if cfamily.lower().strip() != family.lower().strip():
- continue
- try:
- wt, italic = describe.modifiers(f)
- except TTLibError:
- logger.exception('Could not process fonts in %s', path)
- wt, italic = 0, 0
- result = (path, name)
- if wt == 400 and italic == 0:
- results['normal'] = result
- elif wt == 400 and italic > 0:
- results['italic'] = result
- elif wt >= 700 and italic == 0:
- results['bold'] = result
- elif wt >= 700 and italic > 0:
- results['bi'] = result
- return results
+ def family(cmd):
+ return cmd.split(',')[-1].strip()
if options.serif_family:
- fonts['serif'] = find_family(options.serif_family)
+ f = family(options.serif_family)
+ fonts['serif'] = files_for_family(f)
if not fonts['serif']:
- logger.warn('Unable to find serif family %s in %s'%(options.serif_family[1].strip(), options.serif_family[0]))
+ logger.warn('Unable to find serif family %s'%f)
if options.sans_family:
- fonts['sans'] = find_family(options.sans_family)
+ f = family(options.sans_family)
+ fonts['sans'] = files_for_family(f)
if not fonts['sans']:
- logger.warn('Unable to find sans family %s in %s'%(options.sans_family[1].strip(), options.sans_family[0]))
+ logger.warn('Unable to find sans family %s'%f)
if options.mono_family:
- fonts['mono'] = find_family(options.mono_family)
+ f = family(options.mono_family)
+ fonts['mono'] = files_for_family(f)
if not fonts['mono']:
- logger.warn('Unable to find mono family %s in %s'%(options.mono_family[1].strip(), options.mono_family[0]))
+ logger.warn('Unable to find mono family %s'%f)
return fonts
@@ -324,4 +288,4 @@ def Book(options, logger, font_delta=0, header=None,
raise ConversionError, 'Could not find the normal version of the ' + family + ' font'
return book, fonts
-from calibre import entity_to_unicode
\ No newline at end of file
+from calibre import entity_to_unicode
diff --git a/src/calibre/ebooks/lrf/fonts/liberation/__init__.py b/src/calibre/ebooks/lrf/fonts/liberation/__init__.py
index e69de29bb2..95148ae3ec 100644
--- a/src/calibre/ebooks/lrf/fonts/liberation/__init__.py
+++ b/src/calibre/ebooks/lrf/fonts/liberation/__init__.py
@@ -0,0 +1,5 @@
+__all__ = ['LiberationMono_Bold', 'LiberationMono_Regular', 'LiberationSans_Bold',
+ 'LiberationSans_Regular', 'LiberationSerif_Bold', 'LiberationSerif_Regular',
+ 'LiberationMono_BoldItalic', 'LiberationMono_Italic',
+ 'LiberationSans_BoldItalic', 'LiberationSans_Italic',
+ 'LiberationSerif_BoldItalic', 'LiberationSerif_Italic']
\ No newline at end of file
diff --git a/src/calibre/gui2/dialogs/lrf_single.py b/src/calibre/gui2/dialogs/lrf_single.py
index 036570902f..543942f4e1 100644
--- a/src/calibre/gui2/dialogs/lrf_single.py
+++ b/src/calibre/gui2/dialogs/lrf_single.py
@@ -143,7 +143,7 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
for opt in ('--serif-family', '--sans-family', '--mono-family'):
if opt in cmdline:
print 'in'
- family = cmdline[cmdline.index(opt)+1].split(',')[1].strip()
+ family = cmdline[cmdline.index(opt)+1].split(',')[-1].strip()
obj = getattr(self, 'gui_'+opt[2:].replace('-', '_'))
try:
obj.setCurrentIndex(self.font_family_model.index_of(family))
@@ -332,12 +332,8 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
for opt in ('--serif-family', '--sans-family', '--mono-family'):
obj = getattr(self, 'gui_'+opt[2:].replace('-', '_'))
family = qstring_to_unicode(obj.itemText(obj.currentIndex())).strip()
- try:
- path = self.font_family_model.path_of(family)
- except KeyError:
- continue
- if path:
- cmd.extend([opt, os.path.dirname(path)+', '+family])
+ if family != 'None':
+ cmd.extend([opt, family])
return cmd
diff --git a/src/calibre/linux.py b/src/calibre/linux.py
index aad0fb616c..60d5763f2c 100644
--- a/src/calibre/linux.py
+++ b/src/calibre/linux.py
@@ -48,6 +48,7 @@ entry_points = {
'lrf2html = calibre.ebooks.lrf.html.convert_to:main',
'calibre-debug = calibre.debug:main',
'calibredb = calibre.library.cli:main',
+ 'calibre-fontconfig = calibre.utils.fontconfig:main',
],
'gui_scripts' : [
__appname__+' = calibre.gui2.main:main',
diff --git a/src/calibre/trac/plugins/download.py b/src/calibre/trac/plugins/download.py
index ca900837ce..e586a11f50 100644
--- a/src/calibre/trac/plugins/download.py
+++ b/src/calibre/trac/plugins/download.py
@@ -31,7 +31,6 @@ class Distribution(object):
('libusb', '0.1.12', None, None, None),
('Qt', '4.4.0', 'qt', 'libqt4-core libqt4-gui', 'qt4'),
('PyQt', '4.4.2', 'PyQt4', 'python-qt4', 'PyQt4'),
- ('fonttools', '2.0-beta1', 'fonttools', 'fonttools', 'fonttools'),
('mechanize for python', '0.1.7b', 'dev-python/mechanize', 'python-mechanize', 'python-mechanize'),
('ImageMagick', '6.3.5', 'imagemagick', 'imagemagick', 'ImageMagick'),
('xdg-utils', '1.0.2', 'xdg-utils', 'xdg-utils', 'xdg-utils'),
diff --git a/src/calibre/trac/plugins/templates/distro.html b/src/calibre/trac/plugins/templates/distro.html
index 237df4bdc5..61944e7747 100644
--- a/src/calibre/trac/plugins/templates/distro.html
+++ b/src/calibre/trac/plugins/templates/distro.html
@@ -34,7 +34,7 @@
- Make sure that your system has
python >= 2.5
- - Install the various dependencies listed below: Make sure that any python packages are installed into python2.5 (e.g. setuptools, python-imaging, PyQt4, fonttools, etc)
+ - Install the various dependencies listed below: Make sure that any python packages are installed into python2.5 (e.g. setuptools, python-imaging, PyQt4, etc)
- As root run the command
easy_install-2.5 -U TTFQuery calibre && calibre_postinstall
Dependencies
diff --git a/src/calibre/translations/__init__.py b/src/calibre/translations/__init__.py
index 46a73639e3..01f546b42e 100644
--- a/src/calibre/translations/__init__.py
+++ b/src/calibre/translations/__init__.py
@@ -85,7 +85,6 @@ def main(args=sys.argv):
if __name__ == '__main__':
cwd = os.getcwd()
sys.path.insert(0, os.path.dirname(os.path.dirname(cwd)))
- print sys.path[0]
sys.exit(main())
diff --git a/src/calibre/utils/fontconfig.py b/src/calibre/utils/fontconfig.py
new file mode 100644
index 0000000000..d00bfc9692
--- /dev/null
+++ b/src/calibre/utils/fontconfig.py
@@ -0,0 +1,320 @@
+#!/usr/bin/env python
+__license__ = 'GPL v3'
+__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
+__docformat__ = 'restructuredtext en'
+
+'''
+:mod:`fontconfig` -- Query system fonts
+=============================================
+.. module:: fontconfig
+ :platform: Unix, Windows, OS X
+ :synopsis: Query system fonts
+.. moduleauthor:: Kovid Goyal
+
+A ctypes based wrapper around the `fontconfig `_ library.
+It can be used to find all fonts available on the system as well as the closest
+match to a given font specification. The main functions in this module are:
+
+.. autofunction:: find_font_families
+
+.. autofunction:: files_for_family
+
+.. autofunction:: match
+'''
+
+import sys, os, locale, codecs
+from ctypes import cdll, c_void_p, Structure, c_int, POINTER, c_ubyte, c_char, \
+ pointer, byref, create_string_buffer, Union, c_char_p, c_double
+
+try:
+ preferred_encoding = locale.getpreferredencoding()
+ codecs.lookup(preferred_encoding)
+except:
+ preferred_encoding = 'utf-8'
+
+iswindows = 'win32' in sys.platform or 'win64' in sys.platform
+isosx = 'darwin' in sys.platform
+
+def load_library():
+ if isosx:
+ lib = 'libfontconfig.1.dylib'
+ if hasattr(sys, 'frameworks_dir'):
+ lib = os.path.join(getattr(sys, 'frameworks_dir'), lib)
+ return cdll.LoadLibrary(lib)
+ elif iswindows:
+ return cdll.LoadLibrary('libfontconfig-1')
+ else:
+ return cdll.LoadLibrary('libfontconfig.so')
+
+class FcPattern(Structure):
+ _fields_ = [
+ ('num', c_int),
+ ('size', c_int),
+ ('elts_offset', c_void_p),
+ ('ref', c_int)
+ ]
+class FcFontSet(Structure):
+ _fields_ = [
+ ('nfont', c_int),
+ ('sfont', c_int),
+ ('fonts', POINTER(POINTER(FcPattern)))
+ ]
+(
+ FcTypeVoid,
+ FcTypeInteger,
+ FcTypeDouble,
+ FcTypeString,
+ FcTypeBool,
+ FcTypeMatrix,
+ FcTypeCharSet,
+ FcTypeFTFace,
+ FcTypeLangSet
+) = map(c_int, range(9))
+(FcMatchPattern, FcMatchFont, FcMatchScan) = map(c_int, range(3))
+(
+FcResultMatch, FcResultNoMatch, FcResultTypeMismatch, FcResultNoId,
+ FcResultOutOfMemory
+) = map(c_int, range(5))
+FcFalse, FcTrue = c_int(0), c_int(1)
+
+class _FcValue(Union):
+ _fields_ = [
+ ('s', c_char_p),
+ ('i', c_int),
+ ('b', c_int),
+ ('d', c_double),
+ ]
+
+class FcValue(Structure):
+ _fields_ = [
+ ('type', c_int),
+ ('u', _FcValue)
+ ]
+
+lib = load_library()
+lib.FcPatternCreate.restype = c_void_p
+lib.FcObjectSetCreate.restype = c_void_p
+lib.FcFontSetDestroy.argtypes = [POINTER(FcFontSet)]
+lib.FcFontList.restype = POINTER(FcFontSet)
+lib.FcNameUnparse.argtypes = [POINTER(FcPattern)]
+lib.FcNameUnparse.restype = POINTER(c_ubyte)
+lib.FcPatternGetString.argtypes = [POINTER(FcPattern), POINTER(c_char), c_int, c_void_p]
+lib.FcPatternGetString.restype = c_int
+lib.FcPatternAdd.argtypes = [c_void_p, POINTER(c_char), FcValue, c_int]
+lib.FcPatternGetInteger.argtypes = [POINTER(FcPattern), POINTER(c_char), c_int, POINTER(c_int)]
+lib.FcPatternGetInteger.restype = c_int
+lib.FcNameParse.argtypes = [c_char_p]
+lib.FcNameParse.restype = POINTER(FcPattern)
+lib.FcDefaultSubstitute.argtypes = [POINTER(FcPattern)]
+lib.FcConfigSubstitute.argtypes = [c_void_p, POINTER(FcPattern), c_int]
+lib.FcFontSetCreate.restype = POINTER(FcFontSet)
+lib.FcFontMatch.argtypes = [c_void_p, POINTER(FcPattern), POINTER(c_int)]
+lib.FcFontMatch.restype = POINTER(FcPattern)
+lib.FcFontSetAdd.argtypes = [POINTER(FcFontSet), POINTER(FcPattern)]
+lib.FcFontSort.argtypes = [c_void_p, POINTER(FcPattern), c_int, c_void_p, POINTER(c_int)]
+lib.FcFontSort.restype = POINTER(FcFontSet)
+lib.FcFontRenderPrepare.argtypes = [c_void_p, POINTER(FcPattern), POINTER(FcPattern)]
+lib.FcFontRenderPrepare.restype = POINTER(FcPattern)
+
+
+if not lib.FcInit():
+ raise RuntimeError(_('Could not initialize the fontconfig library'))
+
+
+def find_font_families(allowed_extensions=['ttf']):
+ '''
+ Return an alphabetically sorted list of font families available on the system.
+
+ `allowed_extensions`: A list of allowed extensions for font file types. Defaults to
+ `['ttf']`. If it is empty, it is ignored.
+ '''
+ allowed_extensions = [i.lower() for i in allowed_extensions]
+
+ empty_pattern = lib.FcPatternCreate()
+ oset = lib.FcObjectSetCreate()
+ if not lib.FcObjectSetAdd(oset, 'file'):
+ raise RuntimeError('Allocation failure')
+ if not lib.FcObjectSetAdd(oset, 'family'):
+ raise RuntimeError('Allocation failure')
+ fs = lib.FcFontList(0, empty_pattern, oset)
+ font_set = fs.contents
+ file = pointer(create_string_buffer(chr(0), 5000))
+ family = pointer(create_string_buffer(chr(0), 200))
+ font_families = []
+ for i in range(font_set.nfont):
+ pat = font_set.fonts[i]
+ if lib.FcPatternGetString(pat, 'file', 0, byref(file)) != FcResultMatch.value:
+ raise RuntimeError('Error processing pattern')
+ path = str(file.contents.value)
+ ext = os.path.splitext(path)[1]
+ if ext:
+ ext = ext[1:].lower()
+ if allowed_extensions and ext in allowed_extensions:
+ if lib.FcPatternGetString(pat, 'family', 0, byref(family)) != FcResultMatch.value:
+ raise RuntimeError('Error processing pattern')
+ font_families.append(str(family.contents.value))
+
+
+ lib.FcObjectSetDestroy(oset)
+ lib.FcPatternDestroy(empty_pattern)
+ lib.FcFontSetDestroy(fs)
+ font_families = list(set(font_families))
+ font_families.sort()
+ return font_families
+
+def files_for_family(family, normalize=True):
+ '''
+ Find all the variants in the font family `family`.
+ Returns a dictionary of tuples. Each tuple is of the form (Full font name, path to font file).
+ The keys of the dictionary depend on `normalize`. If `normalize` is `False`,
+ they are a tuple (slant, weight) otherwise they are strings from the set
+ `('normal', 'bold', 'italic', 'bi', 'light', 'li')`
+ '''
+ if isinstance(family, unicode):
+ family = family.encode(preferred_encoding)
+ family_pattern = lib.FcPatternBuild(0, 'family', FcTypeString, family, 0)
+ if not family_pattern:
+ raise RuntimeError('Allocation failure')
+ #lib.FcPatternPrint(family_pattern)
+ oset = lib.FcObjectSetCreate()
+ if not lib.FcObjectSetAdd(oset, 'file'):
+ raise RuntimeError('Allocation failure')
+ if not lib.FcObjectSetAdd(oset, 'weight'):
+ raise RuntimeError('Allocation failure')
+ if not lib.FcObjectSetAdd(oset, 'fullname'):
+ raise RuntimeError('Allocation failure')
+ if not lib.FcObjectSetAdd(oset, 'slant'):
+ raise RuntimeError('Allocation failure')
+ if not lib.FcObjectSetAdd(oset, 'style'):
+ raise RuntimeError('Allocation failure')
+ fonts = {}
+ fs = lib.FcFontList(0, family_pattern, oset)
+ font_set = fs.contents
+ file = pointer(create_string_buffer(chr(0), 5000))
+ full_name = pointer(create_string_buffer(chr(0), 200))
+ weight = c_int(0)
+ slant = c_int(0)
+ fname = ''
+ for i in range(font_set.nfont):
+ pat = font_set.fonts[i]
+ #lib.FcPatternPrint(pat)
+ pat = font_set.fonts[i]
+ if lib.FcPatternGetString(pat, 'file', 0, byref(file)) != FcResultMatch.value:
+ raise RuntimeError('Error processing pattern')
+ if lib.FcPatternGetInteger(pat, 'weight', 0, byref(weight)) != FcResultMatch.value:
+ raise RuntimeError('Error processing pattern')
+ if lib.FcPatternGetString(pat, 'fullname', 0, byref(full_name)) != FcResultMatch.value:
+ if lib.FcPatternGetString(pat, 'fullname', 0, byref(full_name)) == FcResultNoMatch.value:
+ if lib.FcPatternGetString(pat, 'style', 0, byref(full_name)) != FcResultMatch.value:
+ raise RuntimeError('Error processing pattern')
+ fname = family + ' ' + full_name.contents.value
+ else:
+ raise RuntimeError('Error processing pattern')
+ else:
+ fname = full_name.contents.value
+ if lib.FcPatternGetInteger(pat, 'slant', 0, byref(slant)) != FcResultMatch.value:
+ raise RuntimeError('Error processing pattern')
+ style = (slant.value, weight.value)
+ if normalize:
+ italic = slant.value > 0
+ normal = weight.value == 80
+ bold = weight.value > 80
+ if italic:
+ style = 'italic' if normal else 'bi' if bold else 'li'
+ else:
+ style = 'normal' if normal else 'bold' if bold else 'light'
+ fonts[style] = (file.contents.value, fname)
+ lib.FcObjectSetDestroy(oset)
+ lib.FcPatternDestroy(family_pattern)
+ if not iswindows:
+ lib.FcFontSetDestroy(fs)
+
+ return fonts
+
+def match(name, sort=False, verbose=False):
+ '''
+ Find the system font that most closely matches `name`, where `name` is a specification
+ of the form::
+ familyname-::...
+
+ For example, `verdana:weight=bold:slant=italic`
+
+ Returns a list of dictionaries. Each dictionary has the keys: 'weight', 'slant', 'family', 'file'
+
+ `sort`: If `True` return a sorted list of matching fonts, where the sort id in order of
+ decreasing closeness of matching.
+ `verbose`: If `True` print debugging information to stdout
+ '''
+ if isinstance(name, unicode):
+ name = name.encode(preferred_encoding)
+ pat = lib.FcNameParse(name)
+ if not pat:
+ raise ValueError('Could not parse font name')
+ if verbose:
+ print 'Searching for pattern'
+ lib.FcPatternPrint(pat)
+ if not lib.FcConfigSubstitute(0, pat, FcMatchPattern):
+ raise RuntimeError('Allocation failure')
+ lib.FcDefaultSubstitute(pat)
+ fs = lib.FcFontSetCreate()
+ result = c_int(0)
+ matches = []
+ if sort:
+ font_patterns = lib.FcFontSort(0, pat, FcFalse, 0, byref(result))
+ if not font_patterns:
+ raise RuntimeError('Allocation failed')
+ fps = font_patterns.contents
+ for j in range(fps.nfont):
+ fpat = fps.fonts[j]
+ fp = lib.FcFontRenderPrepare(0, pat, fpat)
+ if fp:
+ lib.FcFontSetAdd(fs, fp)
+ lib.FcFontSetDestroy(font_patterns)
+ else:
+ match_pat = lib.FcFontMatch(0, pat, byref(result))
+ if pat:
+ lib.FcFontSetAdd(fs, match_pat)
+ if result.value != FcResultMatch.value:
+ lib.FcPatternDestroy(pat)
+ return matches
+ font_set = fs.contents
+
+ file = pointer(create_string_buffer(chr(0), 5000))
+ family = pointer(create_string_buffer(chr(0), 200))
+ weight = c_int(0)
+ slant = c_int(0)
+ for j in range(font_set.nfont):
+ fpat = font_set.fonts[j]
+ #lib.FcPatternPrint(fpat)
+ if lib.FcPatternGetString(fpat, 'file', 0, byref(file)) != FcResultMatch.value:
+ raise RuntimeError('Error processing pattern')
+ if lib.FcPatternGetString(fpat, 'family', 0, byref(family)) != FcResultMatch.value:
+ raise RuntimeError('Error processing pattern')
+ if lib.FcPatternGetInteger(fpat, 'weight', 0, byref(weight)) != FcResultMatch.value:
+ raise RuntimeError('Error processing pattern')
+ if lib.FcPatternGetInteger(fpat, 'slant', 0, byref(slant)) != FcResultMatch.value:
+ raise RuntimeError('Error processing pattern')
+
+ matches.append({
+ 'file' : file.contents.value,
+ 'family' : family.contents.value,
+ 'weight' : weight.value,
+ 'slant' : slant.value,
+ }
+ )
+
+ lib.FcPatternDestroy(pat)
+ lib.FcFontSetDestroy(fs)
+ return matches
+
+def main(args=sys.argv):
+ print find_font_families()
+ if len(args) > 1:
+ print
+ print files_for_family(args[1])
+ print
+ print match(args[1], verbose=True)
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main())
\ No newline at end of file
diff --git a/windows_installer.py b/windows_installer.py
index 0835942909..6608effa16 100644
--- a/windows_installer.py
+++ b/windows_installer.py
@@ -46,6 +46,7 @@ BrandingText "${PRODUCT_NAME} created by Kovid Goyal"
!define CLIT "C:\clit\clit.exe"
!define PDFTOHTML "C:\pdftohtml\pdftohtml.exe"
!define IMAGEMAGICK "C:\ImageMagick"
+!DEFINE FONTCONFIG "C:\fontconfig"
; ---------------PATH manipulation -----------------------------------------------------------------
@@ -283,6 +284,7 @@ Section "Main" "secmain"
File /r "${PY2EXE_DIR}\*"
File "${CLIT}"
File "${PDFTOHTML}"
+ File /r "${FONTCONFIG}\*"
SetOutPath "$INSTDIR\ImageMagick"
File /r "${IMAGEMAGICK}\*"