Skip to content

Commit

Permalink
Use the descriptors when adding @font-face fonts
Browse files Browse the repository at this point in the history
  • Loading branch information
liZe committed Sep 26, 2016
1 parent f8f586a commit fc5eb6c
Showing 1 changed file with 75 additions and 39 deletions.
114 changes: 75 additions & 39 deletions weasyprint/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from __future__ import division
# XXX No unicode_literals, cffi likes native strings

import os
import re
import tempfile

Expand Down Expand Up @@ -202,30 +203,14 @@
void pango_cairo_show_layout_line (cairo_t *cr, PangoLayoutLine *line);
typedef enum _FcMatchKind {
FcMatchPattern, FcMatchFont, FcMatchScan
} FcMatchKind;
typedef enum _FcResult {
FcResultMatch, FcResultNoMatch, FcResultTypeMismatch, FcResultNoId,
FcResultOutOfMemory
} FcResult;
typedef unsigned char FcChar8;
typedef int FcBool;
typedef struct _FcConfig FcConfig;
typedef struct _FcPattern FcPattern;
typedef unsigned char FcChar8;
typedef int FcBool;
typedef struct _FcConfig FcConfig;
FcBool FcConfigAppFontAddFile (FcConfig *config, const FcChar8 *file);
FcPattern * FcPatternCreate (void);
FcConfig * FcConfigGetCurrent (void);
FcBool FcPatternAddString
(FcPattern *p, const char *object, const FcChar8 *s);
FcBool FcConfigSubstitute
(FcConfig *config, FcPattern *p, FcMatchKind kind);
void FcDefaultSubstitute (FcPattern *pattern);
FcPattern * FcFontMatch(FcConfig *config, FcPattern *p);
FcBool FcPatternDel(FcPattern *p, const char *object);
void FcPatternPrint(const FcPattern *p);
FcBool FcConfigParseAndLoad
(FcConfig *config, const FcChar8 *file, FcBool complain);
''')

Expand Down Expand Up @@ -562,6 +547,38 @@ def dlopen(ffi, *names):
'znd': 'zne',
}

FONTCONFIG_WEIGHT_CONSTANTS = {
'normal': 'normal',
'bold': 'bold',
100: 'thin',
200: 'extralight',
300: 'light',
400: 'normal',
500: 'medium',
600: 'demibold',
700: 'bold',
800: 'extrabold',
900: 'black',
}

FONTCONFIG_STYLE_CONSTANTS = {
'normal': 'roman',
'italic': 'italic',
'oblique': 'oblique',
}

FONTCONFIG_STRETCH_CONSTANTS = {
'normal': 'normal',
'ultra-condensed': 'ultracondensed',
'extra-condensed': 'extracondensed',
'condensed': 'condensed',
'semi-condensed': 'semicondensed',
'semi-expanded': 'semiexpanded',
'expanded': 'expanded',
'extra-expanded': 'extraexpanded',
'ultra-expanded': 'ultraexpanded',
}


def utf8_slice(string, slice_):
return string.encode('utf-8')[slice_].decode('utf-8')
Expand Down Expand Up @@ -1158,25 +1175,44 @@ def add_font_face(rule_descriptors):
fd.write(urlopen(font[1]).read())
else:
filename = font[1]
filename = filename.encode(FILESYSTEM_ENCODING)
font_added = fontconfig.FcConfigAppFontAddFile(config, filename)
xml = '''<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<match target="scan">
<test name="file" compare="eq"><string>%s</string></test>
<edit name="family" mode="assign_replace">
<string>%s</string>
</edit>
<edit name="slant" mode="assign_replace">
<const>%s</const>
</edit>
<edit name="weight" mode="assign_replace">
<const>%s</const>
</edit>
<edit name="width" mode="assign_replace">
<const>%s</const>
</edit>
</match>
</fontconfig>''' % (
filename,
rule_descriptors['font_family'],
FONTCONFIG_STYLE_CONSTANTS[
rule_descriptors.get('font_style', 'normal')],
FONTCONFIG_WEIGHT_CONSTANTS[
rule_descriptors.get('font_weight', 'normal')],
FONTCONFIG_STRETCH_CONSTANTS[
rule_descriptors.get('font_stretch', 'normal')],
)
_, conf_filename = tempfile.mkstemp()
with open(conf_filename, 'wb') as fd:
# TODO: encoding is OK for <test>, but what about <edit>s?
fd.write(xml.encode(FILESYSTEM_ENCODING))
fontconfig.FcConfigParseAndLoad(
config, conf_filename.encode(FILESYSTEM_ENCODING), True)
os.remove(conf_filename)
font_added = fontconfig.FcConfigAppFontAddFile(
config, filename.encode(FILESYSTEM_ENCODING))
if font_added:
# TODO: Change the real font features into the wanted description
pattern = fontconfig.FcPatternCreate()
fontconfig.FcPatternAddString(pattern, b'file', filename)
fontconfig.FcConfigSubstitute(
config, pattern, fontconfig.FcMatchFont)
fontconfig.FcDefaultSubstitute(pattern)
new_pattern = fontconfig.FcFontMatch(config, pattern)
fontconfig.FcPatternDel(new_pattern, b'family')
fontconfig.FcPatternDel(new_pattern, b'familylang')
fontconfig.FcPatternDel(new_pattern, b'fullname')
fontconfig.FcPatternDel(new_pattern, b'fullnamelang')
fontconfig.FcPatternDel(new_pattern, b'postscriptname')
fontconfig.FcPatternAddString(
new_pattern, b'family',
rule_descriptors['font_family'].encode('utf-8'))
# fontconfig.FcPatternPrint(new_pattern)
# TODO: we should mask the local fonts with the same name too
return filename
LOGGER.warning(
Expand Down

0 comments on commit fc5eb6c

Please sign in to comment.