diff --git a/setup/build_environment.py b/setup/build_environment.py index 6601578345..492eca0697 100644 --- a/setup/build_environment.py +++ b/setup/build_environment.py @@ -87,8 +87,6 @@ ft_libs = [] ft_inc_dirs = [] jpg_libs = [] jpg_lib_dirs = [] -fc_inc = '/usr/include/fontconfig' -fc_lib = '/usr/lib' podofo_inc = '/usr/include/podofo' podofo_lib = '/usr/lib' chmlib_inc_dirs = chmlib_lib_dirs = [] @@ -107,8 +105,6 @@ if iswindows: 'source', 'i18n')] icu_lib_dirs = [os.path.join(ICU, 'source', 'lib')] sqlite_inc_dirs = [sw_inc_dir] - fc_inc = os.path.join(sw_inc_dir, 'fontconfig') - fc_lib = sw_lib_dir chmlib_inc_dirs = consolidate('CHMLIB_INC_DIR', os.path.join(prefix, 'build', 'chmlib-0.40', 'src')) chmlib_lib_dirs = consolidate('CHMLIB_LIB_DIR', os.path.join(prefix, @@ -131,8 +127,6 @@ if iswindows: podofo_inc = os.path.join(sw_inc_dir, 'podofo') podofo_lib = sw_lib_dir elif isosx: - fc_inc = '/sw/include/fontconfig' - fc_lib = '/sw/lib' podofo_inc = '/sw/podofo' podofo_lib = '/sw/lib' magick_inc_dirs = consolidate('MAGICK_INC', @@ -166,13 +160,6 @@ else: ft_libs = pkgconfig_libs('freetype2', '', '') -fc_inc = os.environ.get('FC_INC_DIR', fc_inc) -fc_lib = os.environ.get('FC_LIB_DIR', fc_lib) -fc_error = None if os.path.exists(os.path.join(fc_inc, 'fontconfig.h')) else \ - ('fontconfig header files not found on your system. ' - 'Try setting the FC_INC_DIR and FC_LIB_DIR environment ' - 'variables.') - magick_error = None if not magick_inc_dirs or not os.path.exists(os.path.join(magick_inc_dirs[0], 'wand')): diff --git a/setup/extensions.py b/setup/extensions.py index 989a9ddbe9..cfbb148873 100644 --- a/setup/extensions.py +++ b/setup/extensions.py @@ -13,7 +13,7 @@ from multiprocessing import cpu_count from PyQt4.pyqtconfig import QtGuiModuleMakefile from setup import Command, islinux, isbsd, isosx, SRC, iswindows -from setup.build_environment import (fc_inc, fc_lib, chmlib_inc_dirs, fc_error, +from setup.build_environment import (chmlib_inc_dirs, podofo_inc, podofo_lib, podofo_error, pyqt, OSX_SDK, NMAKE, QMAKE, msvc, MT, win_inc, win_lib, win_ddk, magick_inc_dirs, magick_lib_dirs, magick_libs, chmlib_lib_dirs, sqlite_inc_dirs, icu_inc_dirs, @@ -122,13 +122,6 @@ extensions = [ libraries=ft_libs, lib_dirs=ft_lib_dirs), - Extension('fontconfig', - ['calibre/utils/fonts/fontconfig.c'], - inc_dirs = [fc_inc], - libraries=['fontconfig'], - lib_dirs=[fc_lib], - error=fc_error), - Extension('woff', ['calibre/utils/fonts/woff/main.c', 'calibre/utils/fonts/woff/woff.c'], @@ -305,9 +298,6 @@ class Build(Command): CFLAGS - Extra compiler flags LDFLAGS - Extra linker flags - FC_INC_DIR - fontconfig header files - FC_LIB_DIR - fontconfig library - POPPLER_INC_DIR - poppler header files POPPLER_LIB_DIR - poppler-qt4 library diff --git a/setup/installer/osx/app/main.py b/setup/installer/osx/app/main.py index 14df94f4ba..a101c574b7 100644 --- a/setup/installer/osx/app/main.py +++ b/setup/installer/osx/app/main.py @@ -15,8 +15,6 @@ from setup import __version__ as VERSION, __appname__ as APPNAME, basenames, \ LICENSE = open('LICENSE', 'rb').read() MAGICK_HOME='@executable_path/../Frameworks/ImageMagick' ENV = dict( - FC_CONFIG_DIR='@executable_path/../Resources/fonts', - FC_CONFIG_FILE='@executable_path/../Resources/fonts/fonts.conf', MAGICK_CONFIGURE_PATH=MAGICK_HOME+'/config', MAGICK_CODER_MODULE_PATH=MAGICK_HOME+'/modules-Q16/coders', MAGICK_CODER_FILTER_PATH=MAGICK_HOME+'/modules-Q16/filter', @@ -180,7 +178,7 @@ class Py2App(object): self.add_poppler() self.add_libjpeg() self.add_libpng() - self.add_fontconfig() + self.add_freetype() self.add_imagemagick() self.add_misc_libraries() @@ -397,28 +395,11 @@ class Py2App(object): @flush - def add_fontconfig(self): - info('\nAdding fontconfig') - for x in ('fontconfig.1', 'freetype.6', 'expat.1'): + def add_freetype(self): + info('\nAdding freetype') + for x in ('freetype.6', 'expat.1'): src = os.path.join(SW, 'lib', 'lib'+x+'.dylib') self.install_dylib(src) - dst = os.path.join(self.resources_dir, 'fonts') - if os.path.exists(dst): - shutil.rmtree(dst) - src = os.path.join(SW, 'etc', 'fonts') - shutil.copytree(src, dst, symlinks=False) - fc = os.path.join(dst, 'fonts.conf') - raw = open(fc, 'rb').read() - raw = raw.replace('/usr/share/fonts', '''\ - /Library/Fonts - /Network/Library/Fonts - /System/Library/Fonts - /usr/X11R6/lib/X11/fonts - /usr/share/fonts - /var/root/Library/Fonts - /usr/share/fonts - ''') - open(fc, 'wb').write(raw) @flush def add_imagemagick(self): diff --git a/setup/installer/windows/freeze.py b/setup/installer/windows/freeze.py index 12443b4898..e578d64607 100644 --- a/setup/installer/windows/freeze.py +++ b/setup/installer/windows/freeze.py @@ -281,8 +281,6 @@ class Win32Freeze(Command, WixMixIn): for x in ('zlib1.dll', 'libxml2.dll'): shutil.copy2(self.j(bindir, x+'.manifest'), self.dll_dir) - shutil.copytree(os.path.join(SW, 'etc', 'fonts'), - os.path.join(self.base, 'fontconfig')) # Copy ImageMagick for pat in ('*.dll', '*.xml'): for f in glob.glob(self.j(IMAGEMAGICK, pat)): diff --git a/setup/installer/windows/notes.rst b/setup/installer/windows/notes.rst index 9502135f6e..fe0d8380e0 100644 --- a/setup/installer/windows/notes.rst +++ b/setup/installer/windows/notes.rst @@ -276,27 +276,6 @@ cp build/kdewin32-msvc-0.3.9/build/bin/Release/*.exp lib/ cp -r build/kdewin32-msvc-0.3.9/include/msvc/ include/ cp build/kdewin32-msvc-0.3.9/include/*.h include/ -fontconfig ---------------- - -Get it from http://www.winkde.org/pub/kde/ports/win32/repository/win32libs/ -mkdir build -Remove subdirectory test from the bottom of CMakeLists.txt -run cmake - -Set build type to release and project config to dll -Right click on the fontconfig project and select properties. Add sw/include/msvc to the include paths -Build only fontconfig - -cp build/fontconfig-msvc-2.4.2-3/build/src/Release/*.dll bin -cp build/fontconfig-msvc-2.4.2-3/build/src/Release/*.lib lib -cp build/fontconfig-msvc-2.4.2-3/build/src/Release/*.exp lib -cp -r build/fontconfig-msvc-2.4.2-3/fontconfig/ include/ - -Also install the etc files from the font-config-bin archive from kde win32libs -It contains correct fonts.conf etc. - - poppler ------------- diff --git a/src/calibre/constants.py b/src/calibre/constants.py index f098b77f9a..3c89db2d1a 100644 --- a/src/calibre/constants.py +++ b/src/calibre/constants.py @@ -83,7 +83,6 @@ class Plugins(collections.Mapping): 'magick', 'podofo', 'cPalmdoc', - 'fontconfig', 'progress_indicator', 'chmlib', 'chm_extra', diff --git a/src/calibre/utils/fonts/fc.py b/src/calibre/utils/fonts/fc.py deleted file mode 100644 index 3e6ae844bc..0000000000 --- a/src/calibre/utils/fonts/fc.py +++ /dev/null @@ -1,233 +0,0 @@ -#!/usr/bin/env python -# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai -from __future__ import with_statement - -__license__ = 'GPL v3' -__copyright__ = '2009, Kovid Goyal ' -__docformat__ = 'restructuredtext en' - -import os, sys - -from calibre.constants import plugins, islinux, isbsd, isosx, preferred_encoding - -_fc, _fc_err = plugins['fontconfig'] - -if _fc is None: - raise RuntimeError('Failed to load fontconfig with error:'+_fc_err) - -if islinux or isbsd: - Thread = object -else: - from threading import Thread - -class FontConfig(Thread): - - def __init__(self): - Thread.__init__(self) - self.daemon = True - self.failed = False - self.css_weight_map = { - _fc.FC_WEIGHT_THIN : u'100', - _fc.FC_WEIGHT_EXTRALIGHT : u'200', _fc.FC_WEIGHT_ULTRALIGHT : u'200', - _fc.FC_WEIGHT_LIGHT : u'300', - _fc.FC_WEIGHT_BOOK : u'normal', _fc.FC_WEIGHT_BOOK : u'normal', _fc.FC_WEIGHT_REGULAR : u'normal', - _fc.FC_WEIGHT_MEDIUM : u'500', - _fc.FC_WEIGHT_DEMIBOLD : u'600', _fc.FC_WEIGHT_SEMIBOLD : u'600', - _fc.FC_WEIGHT_BOLD : u'bold', - _fc.FC_WEIGHT_EXTRABOLD : u'800', _fc.FC_WEIGHT_ULTRABOLD : u'800', - _fc.FC_WEIGHT_HEAVY : u'900', _fc.FC_WEIGHT_BLACK : u'900', _fc.FC_WEIGHT_EXTRABLACK : u'900', _fc.FC_WEIGHT_ULTRABLACK : u'900' - } - self.css_slant_map = { - _fc.FC_SLANT_ROMAN : u'normal', - _fc.FC_SLANT_ITALIC : u'italic', - _fc.FC_SLANT_OBLIQUE : u'oblique' - } - self.css_stretch_map = { - _fc.FC_WIDTH_ULTRACONDENSED: u'ultra-condensed', - _fc.FC_WIDTH_EXTRACONDENSED : u'extra-condensed', - _fc.FC_WIDTH_CONDENSED: u'condensed', - _fc.FC_WIDTH_SEMICONDENSED: u'semi-condensed', - _fc.FC_WIDTH_NORMAL: u'normal', - _fc.FC_WIDTH_SEMIEXPANDED: u'semi-expanded', - _fc.FC_WIDTH_EXPANDED: u'expanded', - _fc.FC_WIDTH_EXTRAEXPANDED: u'extra-expanded', - _fc.FC_WIDTH_ULTRAEXPANDED: u'ultra-expanded', - } - - def run(self): - config = None - if getattr(sys, 'frameworks_dir', False): - config_dir = os.path.join(os.path.dirname( - getattr(sys, 'frameworks_dir')), 'Resources', 'fonts') - if isinstance(config_dir, unicode): - config_dir = config_dir.encode(sys.getfilesystemencoding()) - config = os.path.join(config_dir, 'fonts.conf') - try: - _fc.initialize(config) - except: - import traceback - traceback.print_exc() - self.failed = True - if not self.failed and hasattr(_fc, 'add_font_dir'): - _fc.add_font_dir(P('fonts/liberation')) - - def is_scanning(self): - if isosx: - return self.is_alive() - return False - - def wait(self): - if not (islinux or isbsd): - self.join() - if self.failed: - raise RuntimeError('Failed to initialize fontconfig') - - def find_font_families(self, allowed_extensions={'ttf', 'otf'}): - ''' - 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', 'otf']`. If it is empty, it is ignored. - ''' - self.wait() - ans = _fc.find_font_families([bytes('.'+x) for x in allowed_extensions]) - ans = sorted(set(ans), cmp=lambda x,y:cmp(x.lower(), y.lower())) - ans2 = [] - for x in ans: - try: - ans2.append(x.decode('utf-8')) - except UnicodeDecodeError: - continue - return ans2 - - def files_for_family(self, family, normalize=True): - ''' - Find all the variants in the font family `family`. - Returns a dictionary of tuples. Each tuple is of the form (path to font - file, Full font name). - 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')` - ''' - self.wait() - if not isinstance(family, unicode): - family = family.decode(preferred_encoding) - fonts = {} - for entry in _fc.files_for_family(family): - slant, weight = entry['slant'], entry['weight'] - fullname, path = entry['fullname'], entry['path'] - nfamily = entry['family'] - style = (slant, weight) - if normalize: - italic = slant > 0 - normal = weight == 80 - bold = weight > 80 - if italic: - style = 'italic' if normal else 'bi' if bold else 'li' - else: - style = 'normal' if normal else 'bold' if bold else 'light' - try: - fullname, path = fullname.decode('utf-8'), path.decode('utf-8') - nfamily = nfamily.decode('utf-8') - except UnicodeDecodeError: - continue - if style in fonts: - if nfamily.lower().strip() == family.lower().strip() \ - and 'Condensed' not in fullname and 'ExtraLight' not in fullname: - fonts[style] = (path, fullname) - else: - fonts[style] = (path, fullname) - - return fonts - - def faces_for_family(self, family): - ''' - Return all the faces in a font family in a manner suitable for CSS 3. - ''' - self.wait() - if not isinstance(family, unicode): - family = family.decode(preferred_encoding) - seen = set() - for entry in _fc.files_for_family(family): - slant, weight = entry['slant'], entry['weight'] - fullname, path = entry['fullname'], entry['path'] - nfamily, width = entry['family'], entry['width'] - fingerprint = (slant, weight, width, nfamily) - if fingerprint in seen: - # Fontconfig returns the same font multiple times if it is - # present in multiple locations - continue - seen.add(fingerprint) - - try: - nfamily = nfamily.decode('UTF-8') - fullname = fullname.decode('utf-8') - path = path.decode('utf-8') - except UnicodeDecodeError: - continue - - face = { - 'font-weight': self.css_weight_map[weight], - 'font-style': self.css_slant_map[slant], - 'font-stretch': self.css_stretch_map[width], - 'font-family': nfamily, - 'fullname': fullname, 'path':path - } - yield face - - def match(self, name, all=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, or a single dictionary. - Each dictionary has the keys: - 'weight', 'slant', 'family', 'file', 'fullname', 'style' - - `all`: If `True` return a sorted list of matching fonts, where the sort - is in order of decreasing closeness of matching. If `False` only the - best match is returned. ''' - self.wait() - if isinstance(name, unicode): - name = name.encode('utf-8') - fonts = [] - for fullname, path, style, family, weight, slant in \ - _fc.match(str(name), bool(all), bool(verbose)): - try: - fullname = fullname.decode('utf-8') - path = path.decode('utf-8') - style = style.decode('utf-8') - family = family.decode('utf-8') - fonts.append({ - 'fullname' : fullname, - 'path' : path, - 'style' : style, - 'family' : family, - 'weight' : weight, - 'slant' : slant - }) - except UnicodeDecodeError: - continue - return fonts if all else (fonts[0] if fonts else None) - -fontconfig = FontConfig() -if islinux or isbsd: - # On X11 Qt also uses fontconfig, so initialization must happen in the - # main thread. In any case on X11 initializing fontconfig should be very - # fast - fontconfig.run() -else: - fontconfig.start() - -def test(): - from pprint import pprint; - pprint(fontconfig.find_font_families()) - pprint(tuple(fontconfig.faces_for_family('liberation serif'))) - m = 'liberation serif' - pprint(fontconfig.match(m+':slant=italic:weight=bold', verbose=True)) - -if __name__ == '__main__': - test() diff --git a/src/calibre/utils/fonts/fontconfig.c b/src/calibre/utils/fonts/fontconfig.c deleted file mode 100644 index b66aba4b08..0000000000 --- a/src/calibre/utils/fonts/fontconfig.c +++ /dev/null @@ -1,374 +0,0 @@ -/* -:mod:`fontconfig` -- Pythonic interface to fontconfig -===================================================== - -.. module:: fontconfig - :platform: All - :synopsis: Pythonic interface to the fontconfig library - -.. moduleauthor:: Kovid Goyal Copyright 2009 - -*/ - -#define PY_SSIZE_T_CLEAN -#include -#include -#include -#include - -static PyObject * -fontconfig_initialize(PyObject *self, PyObject *args) { - FcChar8 *path; - FcBool ok; - FcConfig *config; - PyThreadState *_save; - - if (!PyArg_ParseTuple(args, "z", &path)) - return NULL; - if (path == NULL) { - _save = PyEval_SaveThread(); - ok = FcInit(); - PyEval_RestoreThread(_save); - } else { - config = FcConfigCreate(); - if (config == NULL) return PyErr_NoMemory(); - _save = PyEval_SaveThread(); - ok = FcConfigParseAndLoad(config, path, FcTrue); - if (ok) ok = FcConfigBuildFonts(config); - if (ok) ok = FcConfigSetCurrent(config); - PyEval_RestoreThread(_save); - if (!ok) return PyErr_NoMemory(); - ok = 1; - } - if (ok) Py_RETURN_TRUE; - 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 -fontconfig_cleanup_find(FcPattern *p, FcObjectSet *oset, FcFontSet *fs) { - if (p != NULL) FcPatternDestroy(p); - if (oset != NULL) FcObjectSetDestroy(oset); - if (fs != NULL) FcFontSetDestroy(fs); -} - - -static PyObject * -fontconfig_find_font_families(PyObject *self, PyObject *args) { - int i; - size_t flen; - char *ext; - Py_ssize_t l, j, extlen; - FcBool ok; - FcPattern *pat, *temp; - FcObjectSet *oset; - FcFontSet *fs; - FcValue v, w; - PyObject *ans, *exts, *t; - - ans = PyList_New(0); - fs = NULL; oset = NULL; pat = NULL; - - if (ans == NULL) return PyErr_NoMemory(); - - if (!PyArg_ParseTuple(args, "O", &exts)) - return NULL; - - if (!PySequence_Check(exts)) { - PyErr_SetString(PyExc_ValueError, "Must pass sequence of extensions"); - return NULL; - } - l = PySequence_Size(exts); - - - pat = FcPatternCreate(); - if (pat == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - - oset = FcObjectSetCreate(); - if (oset == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (!FcObjectSetAdd(oset, FC_FILE)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (!FcObjectSetAdd(oset, FC_FAMILY)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - - fs = FcFontList(FcConfigGetCurrent(), pat, oset); - if (fs == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - - for (i = 0; i < fs->nfont; i++) { - temp = fs->fonts[i]; - - if (temp == NULL) continue; - if (FcPatternGet(temp, FC_FILE, 0, &v) != FcResultMatch) continue; - - if (v.type == FcTypeString) { - flen = strlen((char *)v.u.s); - ok = FcFalse; - if (l == 0) ok = FcTrue; - for ( j = 0; j < l && !ok; j++) { - ext = PyBytes_AS_STRING(PySequence_ITEM(exts, j)); - extlen = PyBytes_GET_SIZE(PySequence_ITEM(exts, j)); - ok = flen > extlen && extlen > 0 && - PyOS_strnicmp(ext, ((char *)v.u.s) + (flen - extlen), extlen) == 0; - } - - if (ok) { - if (FcPatternGet(temp, FC_FAMILY, 0, &w) != FcResultMatch) continue; - if (w.type != FcTypeString) continue; - t = PyString_FromString((char *)w.u.s); - if (t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (PyList_Append(ans, t) != 0) - { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - } - } - - } - fontconfig_cleanup_find(pat, oset, fs); - Py_INCREF(ans); - return ans; -} - -static PyObject * -fontconfig_files_for_family(PyObject *self, PyObject *args) { - char *family; int i; - FcPattern *pat, *tp; - FcObjectSet *oset; - FcFontSet *fs; - FcValue file, weight, fullname, style, slant, family2, width; - PyObject *ans, *temp; - - if (!PyArg_ParseTuple(args, "es", "UTF-8", &family)) - return NULL; - - ans = PyList_New(0); - if (ans == NULL) return PyErr_NoMemory(); - - fs = NULL; oset = NULL; pat = NULL; - - pat = FcPatternBuild(0, FC_FAMILY, FcTypeString, family, (char *) 0); - if (pat == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - PyMem_Free(family); family = NULL; - - oset = FcObjectSetCreate(); - if (oset == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (!FcObjectSetAdd(oset, FC_FILE)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (!FcObjectSetAdd(oset, FC_STYLE)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (!FcObjectSetAdd(oset, FC_SLANT)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (!FcObjectSetAdd(oset, FC_WEIGHT)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (!FcObjectSetAdd(oset, FC_WIDTH)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (!FcObjectSetAdd(oset, FC_FAMILY)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (!FcObjectSetAdd(oset, FC_FULLNAME)) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - - fs = FcFontList(FcConfigGetCurrent(), pat, oset); - if (fs == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - - for (i = 0; i < fs->nfont; i++) { - tp = fs->fonts[i]; - - if (tp == NULL) continue; - if (FcPatternGet(tp, FC_FILE, 0, &file) != FcResultMatch) continue; - if (FcPatternGet(tp, FC_STYLE, 0, &style) != FcResultMatch) continue; - if (FcPatternGet(tp, FC_WEIGHT, 0, &weight) != FcResultMatch) continue; - if (FcPatternGet(tp, FC_WIDTH, 0, &width) != FcResultMatch) continue; - if (FcPatternGet(tp, FC_SLANT, 0, &slant) != FcResultMatch) continue; - if (FcPatternGet(tp, FC_FAMILY, 0, &family2) != FcResultMatch) continue; - if (FcPatternGet(tp, FC_FULLNAME, 0, &fullname) != FcResultMatch) continue; - - temp = Py_BuildValue("{s:s, s:s, s:s, s:s, s:l, s:l, s:l}", - "fullname", (char*)fullname.u.s, - "path", (char*)file.u.s, - "style", (char*)style.u.s, - "family", (char*)family2.u.s, - "weight", (long)weight.u.i, - "slant", (long)slant.u.i, - "width", (long)width.u.i - ); - if (temp == NULL) { fontconfig_cleanup_find(pat, oset, fs); return NULL; } - if (PyList_Append(ans, temp) != 0) - { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - } - fontconfig_cleanup_find(pat, oset, fs); - Py_INCREF(ans); - return ans; -} - -static PyObject * -fontconfig_match(PyObject *self, PyObject *args) { - FcChar8 *namespec; int i; - FcPattern *pat, *tp; - FcObjectSet *oset; - FcFontSet *fs, *fs2; - FcValue file, weight, fullname, style, slant, family; - FcResult res; - PyObject *ans, *temp, *t, *all, *verbose; - - if (!PyArg_ParseTuple(args, "sOO", &namespec, &all, &verbose)) - return NULL; - - ans = PyList_New(0); - if (ans == NULL) return PyErr_NoMemory(); - - fs = NULL; oset = NULL; pat = NULL; fs2 = NULL; - - pat = FcNameParse(namespec); - if (pat == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (PyObject_IsTrue(verbose)) FcPatternPrint(pat); - - if (!FcConfigSubstitute(FcConfigGetCurrent(), pat, FcMatchPattern)) - { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - FcDefaultSubstitute(pat); - - fs = FcFontSetCreate(); - if (fs == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (PyObject_IsTrue(all)) { - fs2 = FcFontSort(FcConfigGetCurrent(), pat, FcTrue, NULL, &res); - if (fs2 == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - - for (i = 0; i < fs2->nfont; i++) { - tp = fs2->fonts[i]; - if (tp == NULL) continue; - tp = FcFontRenderPrepare(FcConfigGetCurrent(), pat, tp); - if (tp == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (!FcFontSetAdd(fs, tp)) - { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - } - if (fs2 != NULL) FcFontSetDestroy(fs2); - } else { - tp = FcFontMatch(FcConfigGetCurrent(), pat, &res); - if (tp == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - if (!FcFontSetAdd(fs, tp)) - { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - } - - for (i = 0; i < fs->nfont; i++) { - tp = fs->fonts[i]; - if (tp == NULL) continue; - if (FcPatternGet(tp, FC_FILE, 0, &file) != FcResultMatch) continue; - if (FcPatternGet(tp, FC_STYLE, 0, &style) != FcResultMatch) continue; - if (FcPatternGet(tp, FC_WEIGHT, 0, &weight) != FcResultMatch) continue; - if (FcPatternGet(tp, FC_SLANT, 0, &slant) != FcResultMatch) continue; - if (FcPatternGet(tp, FC_FAMILY, 0, &family) != FcResultMatch) continue; - if (FcPatternGet(tp, "fullname", 0, &fullname) != FcResultMatch) continue; - - temp = PyTuple_New(6); - if(temp == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - t = PyBytes_FromString((char *)fullname.u.s); - if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - PyTuple_SET_ITEM(temp, 0, t); - t = PyBytes_FromString((char *)file.u.s); - if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - PyTuple_SET_ITEM(temp, 1, t); - t = PyBytes_FromString((char *)style.u.s); - if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - PyTuple_SET_ITEM(temp, 2, t); - t = PyBytes_FromString((char *)family.u.s); - if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - PyTuple_SET_ITEM(temp, 3, t); - t = PyInt_FromLong((long)weight.u.i); - if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - PyTuple_SET_ITEM(temp, 4, t); - t = PyInt_FromLong((long)slant.u.i); - if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - PyTuple_SET_ITEM(temp, 5, t); - if (PyList_Append(ans, temp) != 0) - { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); } - - } - fontconfig_cleanup_find(pat, oset, fs); - Py_INCREF(ans); - return ans; -} - - - -static -PyMethodDef fontconfig_methods[] = { - {"initialize", fontconfig_initialize, METH_VARARGS, - "initialize(path_to_config_file)\n\n" - "Initialize the library. If path to config file is specified it is used instead of the " - "default configuration. Returns True iff the initialization succeeded." - }, - - {"find_font_families", fontconfig_find_font_families, METH_VARARGS, - "find_font_families(allowed_extensions)\n\n" - "Find all font families on the system for fonts of the specified types. If no " - "types are specified all font families are returned." - }, - - {"files_for_family", fontconfig_files_for_family, METH_VARARGS, - "files_for_family(family, normalize)\n\n" - "Find all the variants in the font family `family`. " - "Returns a list of tuples. Each tuple is of the form " - "(fullname, path, style, family, weight, slant). " - }, - - {"match", fontconfig_match, METH_VARARGS, - "match(namespec,all,verbose)\n\n" - "Find all system fonts that match namespec, in decreasing order " - "of closeness. " - "Returns a list of tuples. Each tuple is of the form " - "(fullname, path, style, family, weight, slant). " - - }, - - {"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} -}; - - - -PyMODINIT_FUNC -initfontconfig(void) { - PyObject *m; - m = Py_InitModule3( - "fontconfig", fontconfig_methods, - "Find fonts." - ); - if (m == NULL) return; - - PyModule_AddIntMacro(m, FC_WEIGHT_THIN); - PyModule_AddIntMacro(m, FC_WEIGHT_EXTRALIGHT); - PyModule_AddIntMacro(m, FC_WEIGHT_ULTRALIGHT); - PyModule_AddIntMacro(m, FC_WEIGHT_LIGHT); - PyModule_AddIntMacro(m, FC_WEIGHT_BOOK); - PyModule_AddIntMacro(m, FC_WEIGHT_REGULAR); - PyModule_AddIntMacro(m, FC_WEIGHT_NORMAL); - PyModule_AddIntMacro(m, FC_WEIGHT_MEDIUM); - PyModule_AddIntMacro(m, FC_WEIGHT_DEMIBOLD); - PyModule_AddIntMacro(m, FC_WEIGHT_SEMIBOLD); - PyModule_AddIntMacro(m, FC_WEIGHT_BOLD); - PyModule_AddIntMacro(m, FC_WEIGHT_EXTRABOLD); - PyModule_AddIntMacro(m, FC_WEIGHT_ULTRABOLD); - PyModule_AddIntMacro(m, FC_WEIGHT_BLACK); - PyModule_AddIntMacro(m, FC_WEIGHT_HEAVY); - PyModule_AddIntMacro(m, FC_WEIGHT_EXTRABLACK); - PyModule_AddIntMacro(m, FC_WEIGHT_ULTRABLACK); - - PyModule_AddIntMacro(m, FC_SLANT_ROMAN); - PyModule_AddIntMacro(m, FC_SLANT_ITALIC); - PyModule_AddIntMacro(m, FC_SLANT_OBLIQUE); - - PyModule_AddIntMacro(m, FC_WIDTH_ULTRACONDENSED); - PyModule_AddIntMacro(m, FC_WIDTH_EXTRACONDENSED); - PyModule_AddIntMacro(m, FC_WIDTH_CONDENSED); - PyModule_AddIntMacro(m, FC_WIDTH_SEMICONDENSED); - PyModule_AddIntMacro(m, FC_WIDTH_NORMAL); - PyModule_AddIntMacro(m, FC_WIDTH_SEMIEXPANDED); - PyModule_AddIntMacro(m, FC_WIDTH_EXPANDED); - PyModule_AddIntMacro(m, FC_WIDTH_EXTRAEXPANDED); - PyModule_AddIntMacro(m, FC_WIDTH_ULTRAEXPANDED); - -# -} -