Skip to content

Unable to set more than one font in legends, impossible to label data with Glyph from multiple languages. #15260

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
mvarnold opened this issue Sep 12, 2019 · 3 comments
Labels
Difficulty: Hard https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues status: duplicate topic: text/fonts

Comments

@mvarnold
Copy link

Bug report

Bug summary

It is impossible to set more than one font in a legend making it impossible to label data in different languages, such as chinese, arabic and emojis, in the same legend. Allowing prop to accept lists of dictionaries would solve this issue.

Code for reproduction

import matplotlib.pyplot as plt

f, axs = plt.subplots()
plt.plot([i for i in range(5)], label=u"#방탄소년단")
plt.plot([i for i in range(6)], label=u"#🔥")
plt.legend()
plt.show()

Actual outcome
image

Expected outcome

While it would be nice if matplotlib searched for fonts with support for unicode characters, simply allowing lists of fonts to be specified for each handle label, rather than enforcing using one font.

@mvarnold
Copy link
Author

A work around for at least rendering the text is as follows

from fontTools.ttLib import TTFont
import matplotlib.font_manager as mfm
import matplotlib.pyplot as plt

def char_in_font(Unicode_char, font):
    for cmap in font['cmap'].tables:
        if cmap.isUnicode():
            if ord(Unicode_char) in cmap.cmap:
                return True
    return False

def label_unicode(char, axs,x=0.5,y=0.5):
    

    font_info = [(f.fname, f.name) for f in mfm.fontManager.ttflist]
    
    print('finding fonts for ',char)
    font_list = []
    for i, font in enumerate(font_info):
        if char_in_font(char[1], TTFont(font[0], fontNumber=0)):
            #print(font[0], font[1]) #uncomment to see all your fonts
            font_list.append(font[0])
            
    font_path = font_list[-1]
    prop = mfm.FontProperties(fname=font_path) # find this font
    axs.text(x, y, s=char, fontproperties=prop, fontsize=20)

f, axs = plt.subplots()
plt.plot([i for i in range(5)])
label_unicode(u"#방탄소년단 ",axs,1,1)
label_unicode(u"#裏垢女子",axs,1.5,2)
label_unicode(u"#🔥",axs,2,3)
plt.show()

image

@anntzer
Copy link
Contributor

anntzer commented Sep 13, 2019

allowing lists of fonts to be specified for each handle label, rather than enforcing using one font.

The problem is well understood, but would require major rearchitecting of the text handling machinery, so is unlikely to happen soon.

@anntzer anntzer added the Difficulty: Hard https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues label Nov 3, 2020
@anntzer
Copy link
Contributor

anntzer commented Nov 3, 2020

I'll close this in favor of #18883 which is essentially the same but points more explicitly at font-family fallbacks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Difficulty: Hard https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues status: duplicate topic: text/fonts
Projects
None yet
Development

No branches or pull requests

2 participants