mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Start work on replacing the use of fontconfig in windows
This commit is contained in:
parent
b4d4133c6d
commit
c6c878462e
@ -191,6 +191,12 @@ if iswindows:
|
||||
# needs_ddk=True,
|
||||
cflags=['/X']
|
||||
),
|
||||
Extension('winfonts',
|
||||
['calibre/utils/fonts/winfonts.cpp'],
|
||||
libraries=['Gdi32', 'User32'],
|
||||
cflags=['/X']
|
||||
),
|
||||
|
||||
])
|
||||
|
||||
if isosx:
|
||||
|
@ -91,7 +91,7 @@ class Plugins(collections.Mapping):
|
||||
'speedup',
|
||||
]
|
||||
if iswindows:
|
||||
plugins.extend(['winutil', 'wpd'])
|
||||
plugins.extend(['winutil', 'wpd', 'winfonts'])
|
||||
if isosx:
|
||||
plugins.append('usbobserver')
|
||||
if islinux or isosx:
|
||||
|
@ -151,14 +151,28 @@ class PDFOutput(OutputFormatPlugin):
|
||||
oeb_output.convert(oeb_book, oeb_dir, self.input_plugin, self.opts, self.log)
|
||||
|
||||
if iswindows:
|
||||
from calibre.utils.fonts.utils import remove_embed_restriction
|
||||
# On windows Qt generates an image based PDF if the html uses
|
||||
# embedded fonts. See https://launchpad.net/bugs/1053906
|
||||
for f in walk(oeb_dir):
|
||||
if f.rpartition('.')[-1].lower() in {'ttf', 'otf'}:
|
||||
self.log.warn('Found embedded font %s, removing it, as '
|
||||
'embedded fonts on windows are not supported by '
|
||||
'the PDF Output plugin'%os.path.basename(f))
|
||||
os.remove(f)
|
||||
fixed = False
|
||||
with open(f, 'r+b') as s:
|
||||
raw = s.read()
|
||||
try:
|
||||
raw = remove_embed_restriction(raw)
|
||||
except:
|
||||
self.log.exception('Failed to remove embedding'
|
||||
' restriction from font %s, ignoring it'%
|
||||
os.path.basename(f))
|
||||
else:
|
||||
s.seek(0)
|
||||
s.truncate()
|
||||
s.write(raw)
|
||||
fixed = True
|
||||
|
||||
if not fixed:
|
||||
os.remove(f)
|
||||
|
||||
opfpath = glob.glob(os.path.join(oeb_dir, '*.opf'))[0]
|
||||
opf = OPF(opfpath, os.path.dirname(opfpath))
|
||||
|
@ -1,45 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai
|
||||
from __future__ import (unicode_literals, division, absolute_import,
|
||||
print_function)
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import sys, struct
|
||||
|
||||
class UnsupportedFont(ValueError):
|
||||
pass
|
||||
|
||||
def remove_embed_restriction(raw):
|
||||
sfnt_version = raw[:4]
|
||||
if sfnt_version not in {b'\x00\x01\x00\x00', b'OTTO'}:
|
||||
raise UnsupportedFont('Not a supported font, sfnt_version: %r'%sfnt_version)
|
||||
|
||||
num_tables = struct.unpack_from(b'>H', raw, 4)[0]
|
||||
|
||||
# Find OS/2 table
|
||||
offset = 4 + 4*2 # Start of the Table record entries
|
||||
os2_table_offset = None
|
||||
for i in xrange(num_tables):
|
||||
table_tag = raw[offset:offset+4]
|
||||
offset += 16 # Size of a table record
|
||||
if table_tag == b'OS/2':
|
||||
os2_table_offset = struct.unpack_from(b'>I', raw, offset+8)[0]
|
||||
break
|
||||
if os2_table_offset is None:
|
||||
raise UnsupportedFont('Not a supported font, has no OS/2 table')
|
||||
|
||||
version, = struct.unpack_from(b'>H', raw, os2_table_offset)
|
||||
|
||||
fs_type_offset = os2_table_offset + struct.calcsize(b'>HhHH')
|
||||
fs_type = struct.unpack_from(b'>H', raw, fs_type_offset)[0]
|
||||
if fs_type == 0:
|
||||
return raw
|
||||
|
||||
return raw[:fs_type_offset] + struct.pack(b'>H', 0) + raw[fs_type_offset+2:]
|
||||
|
||||
if __name__ == '__main__':
|
||||
remove_embed_restriction(open(sys.argv[-1], 'rb').read())
|
||||
|
90
src/calibre/utils/fonts/utils.py
Normal file
90
src/calibre/utils/fonts/utils.py
Normal file
@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai
|
||||
from __future__ import (unicode_literals, division, absolute_import,
|
||||
print_function)
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import sys, struct
|
||||
|
||||
class UnsupportedFont(ValueError):
|
||||
pass
|
||||
|
||||
def is_truetype_font(raw):
|
||||
sfnt_version = raw[:4]
|
||||
return (sfnt_version in {b'\x00\x01\x00\x00', b'OTTO'}, sfnt_version)
|
||||
|
||||
def get_font_characteristics(raw):
|
||||
num_tables = struct.unpack_from(b'>H', raw, 4)[0]
|
||||
|
||||
# Find OS/2 table
|
||||
offset = 4 + 4*2 # Start of the Table record entries
|
||||
os2_table_offset = None
|
||||
for i in xrange(num_tables):
|
||||
table_tag = raw[offset:offset+4]
|
||||
if table_tag == b'OS/2':
|
||||
os2_table_offset = struct.unpack_from(b'>I', raw, offset+8)[0]
|
||||
break
|
||||
offset += 16 # Size of a table record
|
||||
if os2_table_offset is None:
|
||||
raise UnsupportedFont('Not a supported font, has no OS/2 table')
|
||||
|
||||
common_fields = b'>HhHHHhhhhhhhhhhh'
|
||||
(version, char_width, weight, width, fs_type, subscript_x_size,
|
||||
subscript_y_size, subscript_x_offset, subscript_y_offset,
|
||||
superscript_x_size, superscript_y_size, superscript_x_offset,
|
||||
superscript_y_offset, strikeout_size, strikeout_position,
|
||||
family_class) = struct.unpack_from(common_fields,
|
||||
raw, os2_table_offset)
|
||||
offset = os2_table_offset + struct.calcsize(common_fields)
|
||||
panose = struct.unpack_from(b'>'+b'B'*10, raw, offset)
|
||||
panose
|
||||
offset += 10
|
||||
(range1,) = struct.unpack_from(b'>L', raw, offset)
|
||||
offset += struct.calcsize(b'>L')
|
||||
if version > 0:
|
||||
range2, range3, range4 = struct.unpack_from(b'>LLL', raw, offset)
|
||||
offset += struct.calcsize(b'>LLL')
|
||||
vendor_id = raw[offset:offset+4]
|
||||
vendor_id
|
||||
offset += 4
|
||||
selection, = struct.unpack_from(b'>H', raw, offset)
|
||||
|
||||
is_italic = (selection & 0b1) != 0
|
||||
is_bold = (selection & 0b100000) != 0
|
||||
is_regular = (selection & 0b1000000) != 0
|
||||
return weight, is_italic, is_bold, is_regular
|
||||
|
||||
def remove_embed_restriction(raw):
|
||||
sfnt_version = raw[:4]
|
||||
if sfnt_version not in {b'\x00\x01\x00\x00', b'OTTO'}:
|
||||
raise UnsupportedFont('Not a supported font, sfnt_version: %r'%sfnt_version)
|
||||
|
||||
num_tables = struct.unpack_from(b'>H', raw, 4)[0]
|
||||
|
||||
# Find OS/2 table
|
||||
offset = 4 + 4*2 # Start of the Table record entries
|
||||
os2_table_offset = None
|
||||
for i in xrange(num_tables):
|
||||
table_tag = raw[offset:offset+4]
|
||||
if table_tag == b'OS/2':
|
||||
os2_table_offset = struct.unpack_from(b'>I', raw, offset+8)[0]
|
||||
break
|
||||
offset += 16 # Size of a table record
|
||||
if os2_table_offset is None:
|
||||
raise UnsupportedFont('Not a supported font, has no OS/2 table')
|
||||
|
||||
version, = struct.unpack_from(b'>H', raw, os2_table_offset)
|
||||
|
||||
fs_type_offset = os2_table_offset + struct.calcsize(b'>HhHH')
|
||||
fs_type = struct.unpack_from(b'>H', raw, fs_type_offset)[0]
|
||||
if fs_type == 0:
|
||||
return raw
|
||||
|
||||
return raw[:fs_type_offset] + struct.pack(b'>H', 0) + raw[fs_type_offset+2:]
|
||||
|
||||
if __name__ == '__main__':
|
||||
raw = remove_embed_restriction(open(sys.argv[-1], 'rb').read())
|
||||
|
112
src/calibre/utils/fonts/win_fonts.py
Normal file
112
src/calibre/utils/fonts/win_fonts.py
Normal file
@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai
|
||||
from __future__ import (unicode_literals, division, absolute_import,
|
||||
print_function)
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os, sys
|
||||
from itertools import product
|
||||
|
||||
from calibre import prints
|
||||
from calibre.constants import plugins
|
||||
from calibre.utils.fonts.utils import (is_truetype_font,
|
||||
get_font_characteristics)
|
||||
|
||||
class WinFonts(object):
|
||||
|
||||
def __init__(self, winfonts):
|
||||
self.w = winfonts
|
||||
|
||||
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)
|
||||
|
||||
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 = type(u'')(family)
|
||||
ans = {}
|
||||
for weight, is_italic in product( (self.w.FW_NORMAL, self.w.FW_BOLD), (False, True) ):
|
||||
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)
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
ans[ft] = (ext, data)
|
||||
|
||||
return ans
|
||||
|
||||
|
||||
def load_winfonts():
|
||||
w, err = plugins['winfonts']
|
||||
if w is None:
|
||||
raise RuntimeError('Failed to load the winfonts module: %s'%err)
|
||||
return WinFonts(w)
|
||||
|
||||
def test_ttf_reading():
|
||||
for f in sys.argv[1:]:
|
||||
raw = open(f).read()
|
||||
print (os.path.basename(f))
|
||||
get_font_characteristics(raw)
|
||||
print()
|
||||
|
||||
if __name__ == '__main__':
|
||||
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:
|
||||
print (family + ':')
|
||||
for font, data in w.fonts_for_family(family).iteritems():
|
||||
print (' ', font, data[0], len(data[1]))
|
||||
print ()
|
||||
|
@ -1,168 +1,202 @@
|
||||
/*
|
||||
:mod:`fontconfig` -- Pythonic interface to Windows font api
|
||||
:mod:`winfont` -- Pythonic interface to Windows font api
|
||||
============================================================
|
||||
|
||||
.. module:: fontconfig
|
||||
.. module:: winfonts
|
||||
:platform: All
|
||||
:synopsis: Pythonic interface to the fontconfig library
|
||||
:synopsis: Pythonic interface to the windows font routines
|
||||
|
||||
.. moduleauthor:: Kovid Goyal <kovid@kovidgoyal.net> Copyright 2009
|
||||
|
||||
*/
|
||||
|
||||
#define _UNICODE
|
||||
#define UNICODE
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include <Windows.h>
|
||||
#include <strsafe.h>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
vector<BYTE> *get_font_data(HDC hdc) {
|
||||
DWORD sz;
|
||||
vector<BYTE> *data;
|
||||
sz = GetFontData(hdc, 0, 0, NULL, 0);
|
||||
data = new vector<BYTE>(sz);
|
||||
if (GetFontData(hdc, 0, 0, &((*data)[0]), sz) == GDI_ERROR) {
|
||||
delete data; data = NULL;
|
||||
}
|
||||
return data;
|
||||
#include <Strsafe.h>
|
||||
#include <Python.h>
|
||||
#include <new>
|
||||
|
||||
// Utils {{{
|
||||
static wchar_t* unicode_to_wchar(PyObject *o) {
|
||||
wchar_t *buf;
|
||||
Py_ssize_t len;
|
||||
if (o == NULL) return NULL;
|
||||
if (!PyUnicode_Check(o)) {PyErr_Format(PyExc_TypeError, "The python object must be a unicode object"); return NULL;}
|
||||
len = PyUnicode_GET_SIZE(o);
|
||||
buf = (wchar_t *)calloc(len+2, sizeof(wchar_t));
|
||||
if (buf == NULL) { PyErr_NoMemory(); return NULL; }
|
||||
len = PyUnicode_AsWideChar((PyUnicodeObject*)o, buf, len);
|
||||
if (len == -1) { free(buf); PyErr_Format(PyExc_TypeError, "Invalid python unicode object."); return NULL; }
|
||||
return buf;
|
||||
}
|
||||
|
||||
BOOL is_font_embeddable(ENUMLOGFONTEX *lpelfe) {
|
||||
HDC hdc;
|
||||
HFONT font;
|
||||
HFONT old_font = NULL;
|
||||
UINT sz;
|
||||
size_t i;
|
||||
LPOUTLINETEXTMETRICW metrics;
|
||||
BOOL ans = TRUE;
|
||||
hdc = GetDC(NULL);
|
||||
font = CreateFontIndirect(&lpelfe->elfLogFont);
|
||||
if (font != NULL) {
|
||||
old_font = SelectObject(hdc, font);
|
||||
sz = GetOutlineTextMetrics(hdc, 0, NULL);
|
||||
metrics = new OUTLINETEXTMETRICW[sz];
|
||||
if ( GetOutlineTextMetrics(hdc, sz, metrics) != 0) {
|
||||
for ( i = 0; i < sz; i++) {
|
||||
if (metrics[i].otmfsType & 0x01) {
|
||||
wprintf_s(L"Not embeddable: %s\n", lpelfe->elfLogFont.lfFaceName);
|
||||
ans = FALSE; break;
|
||||
}
|
||||
}
|
||||
} else ans = FALSE;
|
||||
delete[] metrics;
|
||||
DeleteObject(font);
|
||||
SelectObject(hdc, old_font);
|
||||
} else ans = FALSE;
|
||||
ReleaseDC(NULL, hdc);
|
||||
static PyObject* wchar_to_unicode(const wchar_t *o) {
|
||||
PyObject *ans;
|
||||
if (o == NULL) return NULL;
|
||||
ans = PyUnicode_FromWideChar(o, wcslen(o));
|
||||
if (ans == NULL) PyErr_NoMemory();
|
||||
return ans;
|
||||
}
|
||||
|
||||
int CALLBACK find_families_callback (
|
||||
ENUMLOGFONTEX *lpelfe, /* pointer to logical-font data */
|
||||
NEWTEXTMETRICEX *lpntme, /* pointer to physical-font data */
|
||||
int FontType, /* type of font */
|
||||
LPARAM lParam /* a combo box HWND */
|
||||
) {
|
||||
size_t i;
|
||||
LPWSTR tmp;
|
||||
vector<LPWSTR> *families = (vector<LPWSTR>*)lParam;
|
||||
// }}}
|
||||
|
||||
if (FontType & TRUETYPE_FONTTYPE) {
|
||||
for (i = 0; i < families->size(); i++) {
|
||||
if (lstrcmp(families->at(i), lpelfe->elfLogFont.lfFaceName) == 0)
|
||||
return 1;
|
||||
}
|
||||
tmp = new WCHAR[LF_FACESIZE];
|
||||
swprintf_s(tmp, LF_FACESIZE, L"%s", lpelfe->elfLogFont.lfFaceName);
|
||||
families->push_back(tmp);
|
||||
}
|
||||
// Enumerate font families {{{
|
||||
struct EnumData {
|
||||
HDC hdc;
|
||||
PyObject *families;
|
||||
};
|
||||
|
||||
|
||||
static PyObject* logfont_to_dict(const ENUMLOGFONTEX *lf, const TEXTMETRIC *tm, DWORD font_type, HDC hdc) {
|
||||
PyObject *name, *full_name, *style, *script;
|
||||
LOGFONT f = lf->elfLogFont;
|
||||
|
||||
name = wchar_to_unicode(f.lfFaceName);
|
||||
full_name = wchar_to_unicode(lf->elfFullName);
|
||||
style = wchar_to_unicode(lf->elfStyle);
|
||||
script = wchar_to_unicode(lf->elfScript);
|
||||
|
||||
return Py_BuildValue("{s:N, s:N, s:N, s:N, s:O, s:O, s:O, s:O, s:l}",
|
||||
"name", name,
|
||||
"full_name", full_name,
|
||||
"style", style,
|
||||
"script", script,
|
||||
"is_truetype", (font_type & TRUETYPE_FONTTYPE) ? Py_True : Py_False,
|
||||
"is_italic", (tm->tmItalic != 0) ? Py_True : Py_False,
|
||||
"is_underlined", (tm->tmUnderlined != 0) ? Py_True : Py_False,
|
||||
"is_strikeout", (tm->tmStruckOut != 0) ? Py_True : Py_False,
|
||||
"weight", tm->tmWeight
|
||||
);
|
||||
}
|
||||
|
||||
static int CALLBACK find_families_callback(const ENUMLOGFONTEX *lpelfe, const TEXTMETRIC *lpntme, DWORD font_type, LPARAM lParam) {
|
||||
struct EnumData *enum_data = reinterpret_cast<struct EnumData*>(lParam);
|
||||
PyObject *font = logfont_to_dict(lpelfe, lpntme, font_type, enum_data->hdc);
|
||||
if (font == NULL) return 0;
|
||||
PyList_Append(enum_data->families, font);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
vector<LPWSTR>* find_font_families(void) {
|
||||
static PyObject* enum_font_families(PyObject *self, PyObject *args) {
|
||||
LOGFONTW logfont;
|
||||
HDC hdc;
|
||||
vector<LPWSTR> *families;
|
||||
PyObject *families;
|
||||
struct EnumData enum_data;
|
||||
|
||||
families = new vector<LPWSTR>();
|
||||
families = PyList_New(0);
|
||||
if (families == NULL) return PyErr_NoMemory();
|
||||
SecureZeroMemory(&logfont, sizeof(logfont));
|
||||
|
||||
logfont.lfCharSet = DEFAULT_CHARSET;
|
||||
logfont.lfPitchAndFamily = VARIABLE_PITCH | FF_DONTCARE;
|
||||
StringCchCopyW(logfont.lfFaceName, 2, L"\0");
|
||||
logfont.lfFaceName[0] = L'\0';
|
||||
|
||||
hdc = GetDC(NULL);
|
||||
EnumFontFamiliesExW(hdc, &logfont, (FONTENUMPROC)find_families_callback,
|
||||
(LPARAM)(families), 0);
|
||||
enum_data.hdc = hdc;
|
||||
enum_data.families = families;
|
||||
|
||||
EnumFontFamiliesExW(hdc, &logfont, (FONTENUMPROC)find_families_callback,
|
||||
(LPARAM)(&enum_data), 0);
|
||||
ReleaseDC(NULL, hdc);
|
||||
|
||||
return families;
|
||||
}
|
||||
|
||||
inline void free_families_vector(vector<LPWSTR> *v) {
|
||||
for (size_t i = 0; i < v->size(); i++) delete[] v->at(i);
|
||||
delete v;
|
||||
// }}}
|
||||
|
||||
static PyObject* font_data(PyObject *self, PyObject *args) {
|
||||
PyObject *ans = NULL, *italic, *pyname;
|
||||
LOGFONTW lf;
|
||||
HDC hdc;
|
||||
LONG weight;
|
||||
LPWSTR family = NULL;
|
||||
HGDIOBJ old_font = NULL;
|
||||
HFONT hf;
|
||||
DWORD sz;
|
||||
char *buf;
|
||||
|
||||
SecureZeroMemory(&lf, sizeof(lf));
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OOl", &pyname, &italic, &weight)) return NULL;
|
||||
|
||||
family = unicode_to_wchar(pyname);
|
||||
if (family == NULL) { Py_DECREF(ans); return NULL; }
|
||||
StringCchCopyW(lf.lfFaceName, LF_FACESIZE, family);
|
||||
free(family);
|
||||
|
||||
lf.lfItalic = (PyObject_IsTrue(italic)) ? 1 : 0;
|
||||
lf.lfWeight = weight;
|
||||
lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
|
||||
|
||||
hdc = GetDC(NULL);
|
||||
|
||||
if ( (hf = CreateFontIndirect(&lf)) != NULL) {
|
||||
|
||||
if ( (old_font = SelectObject(hdc, hf)) != NULL ) {
|
||||
sz = GetFontData(hdc, 0, 0, NULL, 0);
|
||||
if (sz != GDI_ERROR) {
|
||||
buf = (char*)calloc(sz, sizeof(char));
|
||||
|
||||
if (buf != NULL) {
|
||||
if (GetFontData(hdc, 0, 0, buf, sz) != GDI_ERROR) {
|
||||
ans = PyBytes_FromStringAndSize(buf, sz);
|
||||
if (ans == NULL) PyErr_NoMemory();
|
||||
} else PyErr_SetString(PyExc_ValueError, "GDI Error");
|
||||
free(buf);
|
||||
} else PyErr_NoMemory();
|
||||
} else PyErr_SetString(PyExc_ValueError, "GDI Error");
|
||||
|
||||
SelectObject(hdc, old_font);
|
||||
} else PyErr_SetFromWindowsErr(0);
|
||||
DeleteObject(hf);
|
||||
} else PyErr_SetFromWindowsErr(0);
|
||||
|
||||
ReleaseDC(NULL, hdc);
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
vector<LPWSTR> *all_families;
|
||||
size_t i;
|
||||
|
||||
all_families = find_font_families();
|
||||
|
||||
for (i = 0; i < all_families->size(); i++)
|
||||
wprintf_s(L"%s\n", all_families->at(i));
|
||||
|
||||
free_families_vector(all_families);
|
||||
|
||||
HDC hdc = GetDC(NULL);
|
||||
HFONT font = CreateFont(72,0,0,0,0,0,0,0,0,0,0,0,0,L"Verdana");
|
||||
HFONT old_font = SelectObject(hdc, font);
|
||||
vector<BYTE> *data = get_font_data(hdc);
|
||||
DeleteObject(font);
|
||||
SelectObject(hdc, old_font);
|
||||
ReleaseDC(NULL, hdc);
|
||||
if (data != NULL) printf("\nyay: %d\n", data->size());
|
||||
delete data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include <Python.h>
|
||||
#
|
||||
|
||||
static
|
||||
PyMethodDef fontconfig_methods[] = {
|
||||
{"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."
|
||||
PyMethodDef winfonts_methods[] = {
|
||||
{"enum_font_families", enum_font_families, METH_VARARGS,
|
||||
"enum_font_families()\n\n"
|
||||
"Enumerate all regular (not italic/bold/etc. variants) font families on the system. Note there will be multiple entries for every family (corresponding to each charset of the font)."
|
||||
},
|
||||
|
||||
{"font_data", font_data, METH_VARARGS,
|
||||
"font_data(family_name, italic, weight)\n\n"
|
||||
"Return the raw font data for the specified font."
|
||||
},
|
||||
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
extern "C" {
|
||||
PyMODINIT_FUNC
|
||||
initfontconfig(void) {
|
||||
initwinfonts(void) {
|
||||
PyObject *m;
|
||||
m = Py_InitModule3(
|
||||
"fontconfig", fontconfig_methods,
|
||||
"Find fonts."
|
||||
"winfonts", winfonts_methods,
|
||||
"Windows font API"
|
||||
);
|
||||
if (m == NULL) return;
|
||||
}
|
||||
|
||||
PyModule_AddIntMacro(m, FW_DONTCARE);
|
||||
PyModule_AddIntMacro(m, FW_THIN);
|
||||
PyModule_AddIntMacro(m, FW_EXTRALIGHT);
|
||||
PyModule_AddIntMacro(m, FW_ULTRALIGHT);
|
||||
PyModule_AddIntMacro(m, FW_LIGHT);
|
||||
PyModule_AddIntMacro(m, FW_NORMAL);
|
||||
PyModule_AddIntMacro(m, FW_REGULAR);
|
||||
PyModule_AddIntMacro(m, FW_MEDIUM);
|
||||
PyModule_AddIntMacro(m, FW_SEMIBOLD);
|
||||
PyModule_AddIntMacro(m, FW_DEMIBOLD);
|
||||
PyModule_AddIntMacro(m, FW_BOLD);
|
||||
PyModule_AddIntMacro(m, FW_EXTRABOLD);
|
||||
PyModule_AddIntMacro(m, FW_ULTRABOLD);
|
||||
PyModule_AddIntMacro(m, FW_HEAVY);
|
||||
PyModule_AddIntMacro(m, FW_BLACK);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user