Skip to content
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

Add support for loading TrueType font files. #1960

Merged
merged 7 commits into from Aug 6, 2023

Conversation

MarronEyes
Copy link
Contributor

In the ImageFormatter class, we can load ttf fonts that already exists in the operating system.
However, the "font_name" argument does not accept a custom font (a filename or a file-like object containing a ttf font).
I hope that this pull request solves this problem.

@birkenfeld
Copy link
Member

I think this is a good feature to have, only two questions:

  • how to handle different font styles? At the moment this is impossible.
  • I think it's more idiomatic to check for hasattr(obj, 'read') to check for file-like objects, no?

@MarronEyes
Copy link
Contributor Author

  • We can maybe ask the user to provide different styles of the font only if he wants to use a custom font.
  • You are right. I will change it.

@birkenfeld
Copy link
Member

Thanks! Could you please update the documentation of the parameter (in the docstring of ImageFormatter)?

@MarronEyes
Copy link
Contributor Author

Yes, of course!
I also noticed that the "FreeTypeFont" font object can take multiple styles if the specified font is a variation font. (See https://pillow.readthedocs.io/en/stable/reference/ImageFont.html#PIL.ImageFont.FreeTypeFont.get_variation_names)
So we could associate each style (in the "fonts" dict) with its font object ?

@MarronEyes
Copy link
Contributor Author

I tested it and cannot instantiate new font objects with different styles because it throws an OSError.
The only solution I think is to use the "set_variation_by_name" method (https://pillow.readthedocs.io/en/stable/reference/ImageFont.html#PIL.ImageFont.FreeTypeFont.set_variation_by_name) to switch the style of the font, but it requires changing the code of the ImageFormatter class.

@MarronEyes
Copy link
Contributor Author

Sorry for the long inactivity, I wasn't available at the moment.
I added a get_style function to get the specified style of the font in get_font.
The code is tested and it works! The pr can be merged.

@Anteru
Copy link
Collaborator

Anteru commented Mar 27, 2022

This also looks good to me, but there's no test for it (nor do I see how this can be tested easily.) @birkenfeld , @jean-abou-samra , any concerns with that? I'm not super happy to merge code without tests but I don't see an easy way to test image based output.

return font
except ValueError:
pass
except OSError:
Copy link
Contributor

Choose a reason for hiding this comment

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

This indicates an invalid font, right? Shouldn't there be a warning or an error?

font.set_variation_by_name(style_name)
return font
except ValueError:
pass
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

Does it guarantee that no ValueError is raised? I'd guess some of the code could do that ... alternative would be to catch only OSError and pass in all other cases?

@@ -254,6 +290,8 @@ class ImageFormatter(Formatter):
The font name to be used as the base font from which others, such as
bold and italic fonts will be generated. This really should be a
monospace font to look sane.
If a filename or a file-like object is specified, the user must
provide different styles of the font.
Copy link
Contributor

Choose a reason for hiding this comment

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

If I understand correctly, a typo in the file name will result in font_name being understood as the name of a font and not a path, and the errors will read 'No usable fonts named ...' or something like that depending on the system. Can we make it explicit rather than implicit and use a separate font_path parameter?

@jeanas
Copy link
Contributor

jeanas commented Mar 27, 2022

I'm not super happy to merge code without tests but I don't see an easy way to test image based output.

No, I don't see one either, especially that font stuff is so platform-dependent :( So I think it's OK if this doesn't have tests.

@Anteru Anteru added this to the 2.16.0 milestone Aug 6, 2023
@Anteru Anteru added the A-formatting area: changes to formatters label Aug 6, 2023
@Anteru Anteru merged commit 1a48184 into pygments:master Aug 6, 2023
@Anteru
Copy link
Collaborator

Anteru commented Aug 6, 2023

Merged for 2.16. Let's see if this works in the wild, thanks for the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-formatting area: changes to formatters
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants