Skip to content

generating fontconfig strings from mpl FontProperties is broken #4910

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions lib/matplotlib/fontconfig_pattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,21 @@ def generate_fontconfig_pattern(d):
props = []
families = ''
size = ''
for key in 'family style variant weight stretch file size'.split():
# Handle 'family' first and escape it properly
family = d.get_family()
if family:
if type(family) == list:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be isinstance(family, list)?

family = [family_escape( r'\\\1', str(x)) for x in family if x]
if family:
family = ','.join(family)
props.append("%s" % family)

for key in ['style', 'variant', 'weight', 'stretch', 'file', 'size']:
val = getattr(d, 'get_' + key)()
if val is not None and val != []:
if val:
if type(val) == list:
val = [value_escape(r'\\\1', str(x)) for x in val if x is not None]
if val != []:
val = [value_escape(r'\\\1', str(x)) for x in val if x]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is subtly different than before. Anything that was None before was getting filtered out, now they will be encoded in this config string as a "None".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nevermind, I misread the line.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, there is still another subtle difference. Before, it would only filter out None's, now it will also filter out things like empty strings and zeros. Don't know this part of the codebase enough to know if that is a problem or not.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably not, since an empty string would have no effect in a fontconfig string anyway.

if val:
val = ','.join(val)
props.append(":%s=%s" % (key, val))
return ''.join(props)
50 changes: 50 additions & 0 deletions lib/matplotlib/tests/test_fontconfig.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from __future__ import (absolute_import, division, print_function,
unicode_literals)

from nose.tools import assert_equal
from matplotlib.externals import six

import os

from matplotlib.font_manager import FontProperties
from matplotlib.fontconfig_pattern import generate_fontconfig_pattern
from matplotlib.fontconfig_pattern import parse_fontconfig_pattern


def check_fonts_same(f1, f2):
assert_equal(f1.get_family(), f2.get_family())
assert_equal(f1.get_style(), f2.get_style())
assert_equal(f1.get_variant(), f2.get_variant())
assert_equal(f1.get_weight(), f2.get_weight())
assert_equal(f1.get_stretch(), f2.get_stretch())
assert_equal(f1.get_size(), f2.get_size())


def do_test(font, expected):
# First convert the mpl FontProperties to a fontconfig string
fc = generate_fontconfig_pattern(font)

# make sure it is what we expected
assert_equal(fc, expected)

# now make sure we can convert it back
newfont = parse_fontconfig_pattern(fc)

# ensure the new font property maches the old one
check_fonts_same(font, newfont)


def test_fontconfig():
s1 ="u'sans\\-serif:style=normal:variant=normal:weight=normal:stretch=normal:size=12.0'"
f1 = FontProperties()
do_test(f1, s1)

s2 ="u'serif:style=normal:variant=normal:weight=normal:stretch=normal:size=12.0'"
f2 = FontProperties(family = 'serif')
do_test(f2, s2)

s1 ="u'sans\\-serif:style=normal:variant=normal:weight=bold:stretch=normal:size=24.0'"
f3 = FontProperties(size=24, weight="bold")
f3.set_family(None)
do_test(f3, s3)