Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Implement Font-Fallback in Matplotlib#20740

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
efiring merged 1 commit intomatplotlib:mainfromaitikgupta:fallback-revamp
Aug 4, 2022

Conversation

aitikgupta
Copy link
Contributor

@aitikguptaaitikgupta commentedJul 25, 2021
edited
Loading

PR Summary

This PR modifies the internal structure ofFT2Font (the interface between fonts and Matplotlib) in favor of implementingFont Fallback for Matplotlib, and allow Agg backend to use the new codepath.
It builds on the previous PR:#20549, which was the 'first-step', i.e., "parsing multiple families".. this PR implementsusing those families for font fallback.

This would help us in multi-language support, for example (Previous / After):

^the fonts are chosen such that the difference is visually noticeable.

A flowchart explaining the text rendering algorithm with font fallback:
FontFallback

Here's the script:

importmatplotlib.pyplotasplt# "Authentic" is a fancy font, whereas "SimHei" is a CJK fontplt.rcParams['font.family']= ['Authentic','SimHei']plt.rcParams['font.size']=30plt.figtext(0.18,0.45,"There are 多个汉字 in between!")plt.show()

Fixes#18883,#15260

PR Checklist

  • Has pytest style unit tests (andpytest passes).
  • IsFlake 8 compliant (runflake8 on changed files to check).
  • New features are documented, with examples if plot related.
  • Documentation is sphinx and numpydoc compliant (the docs shouldbuild without error).
  • Conforms to Matplotlib style conventions (installflake8-docstrings and runflake8 --docstring-convention=all).
  • New features have an entry indoc/users/next_whats_new/ (follow instructions in README.rst there).
  • API changes documented indoc/api/next_api_changes/ (follow instructions in README.rst there).

cesaryuan, lostanlen, Alalalalaki, and Isuxiz reacted with thumbs up emojibmcfee and wxupjack reacted with heart emoji
@aitikgupta
Copy link
ContributorAuthor

aitikgupta commentedJul 25, 2021
edited
Loading

To actually trigger this workflow, I'll push similar commits similar to#20549..
Note: this is only tested against Agg backend (since agg is pretty straightforward in terms of font usage)

Also, there's a lot of print/debug statements throughout, I'll remove them once this moves ahead..

@aitikguptaaitikgupta marked this pull request as draftJuly 26, 2021 06:32
@aitikguptaaitikguptaforce-pushed thefallback-revamp branch 2 times, most recently from9aee34b to9fabbc7CompareAugust 6, 2021 23:47
@aitikguptaaitikgupta changed the titleImplement Font-Fallback in MatplotlibImplement Font-Fallback for Agg backendAug 6, 2021
@aitikgupta
Copy link
ContributorAuthor

aitikgupta commentedAug 7, 2021
edited
Loading

Note: There's some structural changes to how FT2Font is handling stuff in#20804, which builds on this PR..

EDIT: I've merged the FT2Font changes together for both PRs

@aitikguptaaitikguptaforce-pushed thefallback-revamp branch 2 times, most recently from0fa0625 toe868fbcCompareAugust 7, 2021 00:08
@aitikguptaaitikgupta marked this pull request as ready for reviewAugust 7, 2021 08:22
@aitikguptaaitikgupta changed the titleImplement Font-Fallback for Agg backendImplement Font-Fallback in MatplotlibAug 13, 2021
jkseppan added a commit to jkseppan/matplotlib that referenced this pull requestAug 20, 2021
On Linux and Mac. Add a font_manager test that loads the font anduses it. This could be useful in testing the multi-font support(matplotlib#20740 etc).I couldn't get the font installed on Windows. There is a Chocolateyinstaller that installs all of the Noto fonts, which takes a reallylong time to run.
@jklymak
Copy link
Member

@aitikgupta Do these have a review team looking at them?

@aitikgupta
Copy link
ContributorAuthor

@jklymak I don't think anybody is actively reviewing these font handling PRs at the moment.. but they're ready for review and not drafts (I'll resolve the conflicts)

@aitikgupta
Copy link
ContributorAuthor

aitikgupta commentedOct 22, 2021
edited
Loading

Going ahead and removing the test, since font distributions for different Linux versions across CI are different.. and thus their kerning information is different -- different visual outputs.

Wecan test it with a self-shipped CJK font, which is guaranteed to be present across all platforms.. but that'd be another problem because their file sizes are huge.

@anntzer
Copy link
Contributor

(Unfortunately, I will not have the bandwidth to review this in the coming days.)

aitikgupta reacted with thumbs up emoji

@jklymak
Copy link
Member

Hi@aitikgupta we were all discussing this PR yesterday - did you have an opportunity to rebase and address the review comments?

@aitikgupta
Copy link
ContributorAuthor

Hey@jklymak, I'm currently out sick. Will get back to this as soon as I can, probably a week or two. Apologies!

@jklymak
Copy link
Member

No rush, get better!

@aitikgupta
Copy link
ContributorAuthor

Hey@QuLogic, addressed all the comments (added comments for further discussions), and brought the PR up to speed!

@anntzer
Copy link
Contributor

The general design looks reasonable and a skim through the actual implementation only revealed the small issues listed above, which should be fixed, but once that's done I am happy with merging this as is and iterating over it later.

@QuLogic
Copy link
Member

The new code is 2-space indent instead of 4.

@@ -272,7 +272,9 @@ def _prepare_font(self, font_prop):
"""
Get the `.FT2Font` for *font_prop*, clear its buffer, and set its size.
"""
font = get_font(findfont(font_prop))
fname = find_fonts_by_props(font_prop)
Copy link
Contributor

@anntzeranntzerJul 8, 2022
edited
Loading

Choose a reason for hiding this comment

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

fname should be renamed tofilename_dict or at leastfilenames (plural) for clarity.
Given that get_font only uses.values(), I would suggest making it clearer at this stage too (filenames = list(find_fonts_by_props(font_prop).values()); font = get_font(filenames)) (and modify get_font to take a list instead of a dict). This would also make it easier for third-parties to directly callget_font with a list of font paths rather having to invent keys to create a dict, if they don't already have a dict at hand.

tacaswell reacted with thumbs up emoji
Copy link
Member

Choose a reason for hiding this comment

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

I do not remember why we used a dictionary instead of a list

@jklymak
Copy link
Member

As a meta comment, this seems like a pretty big change to squeeze in right before a 3.6 release, versus getting it inmain and letting the devs live with it, and anyone else who is testing our dev tree, for a few months. However, maybe I am misunderstanding its potential to break existing users who don't typically need the fallback.

@oscargus
Copy link
Member

right before a 3.6 release

Talking about that: what is the time line? I sort of expected 3.5.3 to be released "soon" and then probably a few months until 3.6? (Really OT, but still...)

@tacaswell
Copy link
Member

As a meta comment, this seems like a pretty big change to squeeze in right before a 3.6 release, ...

Fair, however you do not pass a list of fallbacks then there should be no behavior change, we hammer these code paths in the tests, and I do not think of the core devs do enough mixed glyph work (I could be wrong about that) to meaning stress it.

jklymak reacted with thumbs up emoji

@anntzer
Copy link
Contributor

An additional point I just thought about: the actual low-level API (including passing a list of fallback FT2Font to the FT2Font constructor) should probably be marked as provisional. While I haven't actually checked, I believe that the current API may be slightly inefficient, because (if I understood it correctly) we will always immediately parse all font files (a costly operation) in the fallback list, regardless of whether we actually need them or not, whereas we could imagine an API where we only store a list of fallbackpaths that get parsed one at a time when needed. (This is also relevant for mplcairo, which doesn't use FT2Font at all and simply gets the paths of the fonts to do its own interfacing with freetype.)
I certainly don't want to hold up merging by requesting a large API design change at the last minute, but marking the low-level parts as provisional would certainly simplify possible improvements in the future.

@tacaswell
Copy link
Member

An additional point I just thought about: the actual low-level API (including passing a list of fallback FT2Font to the FT2Font constructor) should probably be marked as provisional.

That will require documentingft2font at all, but a reasonable request. The keyword already starts with_ so I think documenting it at provisional and/or private is consistent with the original intent.

@anntzer
Copy link
Contributor

I wasn't actually asking for FT2Font to be documented (a blurb in the changelog without linking API entries would have worked too), but sure, that's always a good thing to add.

Copy link
Member

@QuLogicQuLogic left a comment

Choose a reason for hiding this comment

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

Should be good, though needs the rebase for added/removed files.

Co-authored-by: Aitik Gupta <aitikgupta@gmail.com>Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
@tacaswell
Copy link
Member

Squashed this all to 1 commit:

(dd310) ~/s/p/m/matplotlib fallback-revamp↑·1↓·63|…3⚑5✔ 17:45:01 $ git describev3.5.2-2641-g85bacdccc5(dd310) ~/s/p/m/matplotlib fallback-revamp↑·1↓·63|…3⚑5✔ 17:45:05 $ git diff 14251eb(dd310) ~/s/p/m/matplotlib fallback-revamp↑·1↓·63|…3⚑5

@efiringefiring merged commit535c953 intomatplotlib:mainAug 4, 2022
@tacaswell
Copy link
Member

Thank you@aitikgupta ! This would not have been possible without your work.

bmcfee and aitikgupta reacted with hooray emoji

@aitikgupta
Copy link
ContributorAuthor

Super glad this finally made it! Thanks everyone for pushing this 🙇🏼‍♂️

story645 and Hsins reacted with hooray emoji

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@tacaswelltacaswelltacaswell left review comments

@anntzeranntzeranntzer left review comments

@QuLogicQuLogicQuLogic approved these changes

Assignees
No one assigned
Labels
backend: aggRelease criticalFor bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.topic: text/fonts
Projects
None yet
Milestone
v3.6.0
Development

Successfully merging this pull request may close these issues.

Matplotlib would not try to apply all the font in font list to draw all characters in the given string.
8 participants
@aitikgupta@jklymak@anntzer@tacaswell@QuLogic@oscargus@efiring@story645

[8]ページ先頭

©2009-2025 Movatter.jp