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

WIP: New FreeType wrappers #5414

Closed
wants to merge 35 commits into from
Closed

WIP: New FreeType wrappers #5414

wants to merge 35 commits into from

Conversation

mdboom
Copy link
Member

@mdboom mdboom commented Nov 5, 2015

This isn't done yet, but thought I'd share at this point in the interest of transparency. This is related to the (really old at this point) MEP14.

This deletes the somewhat messy and inefficient FT2Font freetype wrapper with a new one at http://github.com/matplotlib/freetypy, which, being an independent project, should hopefully see more use and eyes from the Python graphics/viz community at large. http://github.com/rougier/freetype-py is the only other project I'm aware of that comes close in scope, but being that it's ctypes-based, it's a non-starter for matplotlib which needs to run in restricted environments. Also, the memory management in FreeType is really tricky, and I don't think it's possible to mange it correctly from ctypes.

This is mostly a refactor and should have no impact on most end users. However, it enables some cool things already:

  • It supports fonts that don't have "legacy" Macintosh metadata. This includes most of the new fonts that have shipped with MS-Windows since Vista or so, which only have UTF-16 metadata.
  • It handles Unicode better. It prefers to use Unicode mappings if available in a font, where the master uses the default mapping of the font which may be in some obscure code page resulting in the wrong glyphs. If there is no unicode mapping in the font, the new wrappers will correctly map unicode to that encoding using the extensive collection of codecs that come with Python.
  • Having a clean path of all the various transformations along the way (including the handling of fixed-point numbers correctly), this finally fixes the "wiggly" baselines problem that has plagued matplotlib for years.

BEFORE:

mathfont_cm_06-expected

AFTER:

mathfont_cm_06

Steps yet to do:

- [ ] Handle AFM file parsing in FreeType, rather than our own Python code (afm.py). This should provide a consistent interface and remove all the blocks that say "if afm... if ttf..."

  • Handle all text layout through a consistent interface. This will remove all the blocks that say "if math... if regular text..."
  • Ditch ttconv in favor of Python code that uses FreeType behind it. This will allow any font to be used in PDF and PS, not just TTF fonts.
  • Ditch font_manager.py and matplotlib's notorious font cache in favor of fontconfig (though that will require writing wrappers to fontconfig).
  • Handle Type 1 fonts in FreeType, rather than our own Python code (type1.py)

@tacaswell tacaswell added this to the proposed next point release (2.1) milestone Nov 5, 2015
@Tillsten
Copy link
Contributor

Tillsten commented Nov 6, 2015

Awesome to see work on the text-stuff!
Some questions:
a) Could you expand the point why ctypes or cffi wouldn't work? From an maintenance pov these are much easier to handle.
b) After looking at the code this seem to be a perfect match for cython, or am i wrong here?
c) I toyed around with idea of using the internal freetype-cache system for matplotlib, would that be supported?

Thanks for all the and sorry if this sounds too critical.

@mdboom
Copy link
Member Author

mdboom commented Nov 6, 2015

a) Could you expand the point why ctypes or cffi wouldn't work? From an maintenance pov these are much easier to handle.

ctypes and cffi both create a major security hole since one can basically open any library and call any address in it, so they are not available in restricted execution environments such as Google App Engine. With the whole world going to containers, I suppose that will become less of an issue over time, but in the meantime, we can't really decrease the number of platforms that matplotlib can run in.

b) After looking at the code this seem to be a perfect match for cython, or am i wrong here?

I actually tried and failed with Cython initially for these wrappers. The very careful memory management required for freetype and the stuff like the FT_OpenArgs with its C callbacks etc. really is far more cumbersome in Cython than in direct C. Plus, Cython requires copying all of the information in the FreeType headers over which is a real pain when trying to support multiple versions of FreeType. For example, FreeType explicitly says to not rely on the numeric values of error codes -- but in Cython we would have to copy those numbers over and then keep them in sync with each revision of FreeType. The FreeType API also provides a lot of things through direct access in structs. Again, as those structures change, a Cython wrapper would potentially have to account for changes in those structs over time. With C, a simple recompile will do.

Above all that, I find Cython really hard to deal with when things go wrong. Trying to run gdb or valgrind over that stuff is a nightmare.

Of course, all of this comes from a bias of being very comfortable with C.

c) I toyed around with idea of using the internal freetype-cache system for matplotlib, would that be supported?

I haven't wrapped any of FreeType's cache stuff. It certainly could be added in this scheme. It doesn't look super useful in a Python context since it's so easy to implement cache-like behavior, and it's reference counted etc. However, it might be the case that FreeType's cache code has less overhead etc. I think I would start by seeing just how much time is spent re-doing work to get a theoretical "best case" for using caching before devoting the considerable effort to use this stuff.

@QuLogic
Copy link
Member

QuLogic commented Dec 3, 2015

Will this also obsolete #3912?

@mdboom
Copy link
Member Author

mdboom commented Dec 3, 2015

Will this also obsolete #3912?

This will provide an avenue for handling TTC files in the correct and general way. Probably will do that as a follow-on to this PR, however.

@mdboom
Copy link
Member Author

mdboom commented Jan 22, 2016

I've punted on checkbox #1 in the original topic. FreeType can only manage the metrics in an AFM file if you have an associated PFB file -- which we don't ship or need to ship. I think the status quo (using afm.py) is fine there for now. It supports what is now a sort of niche use case (generating PostScript files using only the core 14 fonts).

@tacaswell tacaswell mentioned this pull request May 12, 2017
@tacaswell tacaswell modified the milestones: 2.1 (next point release), 2.2 (next next feature release) Aug 29, 2017
@anntzer anntzer mentioned this pull request Nov 13, 2017
@anntzer
Copy link
Contributor

anntzer commented Nov 15, 2017

For the record FreeType is already using a unicode charmap by default (http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/src/base/ftobjs.c#n1370); since FreeType 2.8.1 such a charmap will be automatically generated if the font doesn't include it (https://sourceforge.net/projects/freetype/files/freetype2/2.8.1/). So the second point will become moot once we switch the vendored FT version to >=2.8.1.

@jklymak
Copy link
Member

jklymak commented Mar 7, 2018

Closing in lieu of #9763

@jklymak jklymak closed this Mar 7, 2018
@anntzer
Copy link
Contributor

anntzer commented Mar 8, 2018

Actually there's (at least) still one thing that this PR does which #9763 doesn't, which is to replace ttconv (the font subsetter for pdf/ps output). That's actually a task fairly independent from wrapping freetype (which is what #9763 focuses on).

@anntzer anntzer reopened this Mar 8, 2018
@jklymak jklymak modified the milestones: needs sorting, v3.0 May 17, 2018
@tacaswell tacaswell modified the milestones: v3.0, v3.1 Jul 9, 2018
@jklymak
Copy link
Member

jklymak commented Oct 6, 2018

Opened issue about ttconv and closing this again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

6 participants