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
Tool to split/merge TTC #17
Comments
The FDK now includes |
@twardoch ^^^ |
Cool :) I'm leaving this one open so Behdad remembers that he intends to still improve fontTools a bit (ability to handle TTC as a whole, he mentioned). |
@miguelsousa Is there documentation about those tools in FDK? I can provide the same API. |
@behdad the documentation that exists is in the scripts themselves and can be obtained by using the
|
I'd like to add support for collections to the WOFF2 encoder. However we first need to decide on an API for |
Let me upload whatever I have and leave it to your mighty hands... |
👍 |
BTW, note that the otc tools in FDK are completely standalone, simple, dependency-free pure-Python tools: I think this could be easily lifted, except that FDK is Apache 2 while fontTools is MIT-licensed. Not sure how this affects things. A. |
Note that Doug also wrote one in nototools: I agree we want to add API though. Unfortunately I cannot find what I had :(. It wasn't much though, was TTCollection indeed. For decompiling, it's easy. I think we want to set something like collection.fonts to be a list of TTFont() objects. Add iteration to the collection object as well such that we can just do for "font in collection:". Compiling becomes more complicated, but I leave that to you! Also, maybe we should add a TTFontOrCollection() function that creates either a TTFont or TTCollection based on the font data. We also need to add a simpler way to detect what the data represents. Currently one has to try to open... TTCollection should preferably have much of the same API as TTFont, in terms of compile(), save(), fromXML(), etc. Thanks! |
FWIW I did a test implementation (not realizing this issue existed) of TTC for fontTools and I found needing to branch what I was creating and worry about whether I had a TTFont or a SomethingElse annoying. I found it more convenient to make TTFont capable of representing either a regular font or a collection. If its a collection it has a fonts attribute with the TTFont's within the collection. This results in compile, save, to/from XML working with minimal changes. |
Since it's Python, you can have two different types that implement the same save, XML, compile, ... API... |
The convenience factor was mostly avoiding having to open the file to decide which object I was creating. As far as the API, my thinking was just that if it's the same entry points it doesn't have "much of the same API", it has exactly the same API and there is less tendency for those APIs to diverge over time. Either way is certainly workable. However, IMHO the more interesting question is how to handle editing shared tables. For example, if fonts 0 and 1 share glyf, can I reach in and edit by both |
@anthrotype Want to take this one? Perhaps summarize what we discussed in person? Thanks. |
Sure, I was planning to do it as soon as I finish the logging thing I'm working on. |
While implementing DSIG checking a while ago, I noticed some TTCs have individual DSIG's in their member fonts, and I have always wondered if I can split them up and verify the individual ones. MS Font Validator has some code for writing fonts (which itself does not use), so this is probably do'able. |
@rsheeter : about sharing tables. Sharing glyf table is messy (or have a superset that includes all the edits), but sharing most other tables could work at a copy-on-write manner, I guess; and just before writing, one needs to calculate the table checksum anyway, and I seem to have seen some code, either in ttx or in FontVal, which avoid writing duplicate tables of identical checksums. Hmm, it is in FontVal, OTFontFile/OTFile.cs:WriteTTCFile(), line 566 onwards - it does a barbaric binary check. |
@behdad @davelab6 @anthrotype @aaronbell @twardoch @miguelsousa @n8willis : A mere 30 lines (include blank lines, minus comments), IronPython Fontval-based example to split ttc's. https://gist.github.com/HinTak/33cdcb8e1558538389cb5e0475674acc I have only tried it on mingliu.tttc and the output seems to be valid. This is just to check that the Writefont functionality inside FontVal (which it does not use itself - obviously it has no use of that sort of routines) is functional. I might update it a bit to do what I have in mind - see if after splitting, whether individual DSIG in member fonts are valid in some such files I see. |
You shouldn't bother verifying the individual DSIGs of TTC's members. They should have never been there in the first place. TTC may only have a single Format-1 DSIG table for the whole collection. From https://www.microsoft.com/en-us/Typography/dsig.aspx
|
I know - I am just curious whether the merge happens immediately after the signing, or if there are changes between signing and merging. |
The corresponding FontVal-based IronPython script to merge truetype fonts into a truetype collection is about the same length, and 2/3 the same - they use the same modules, etc, obviously. https://gist.github.com/HinTak/96a686572a824d78f8e1967b464821aa Ran the splitter and merger against mingliu, @rsheeter , and there was already de-duplication on write, which is, I am glad to see, functional - note re-merge is a lot smaller than sum of all members: 32217124 original The 7k difference between the original and the new-merge is the TTC DSIG. The old version had all the directories up front, while the new has 2nd directory after tables of 1st font, etc. The 32MB TTC is about 22MB of glyphs, common to all three members, but contains two versions of EBDT at 5MB . So that's how all 3 member fonts are about 27MB each. |
Here's the API Cosimo and I came up with: fonts = TTCollection(ttcFilename, shareTables=False, ...)
fonts.fonts # is a plain list of the TTFont objects
fonts.importXML(...)
fonts[idx] # __getitem__, __setitem__, __delitem__
fonts.saveXML(...) # TTX XML with <TTCollection> root tag.
fonts.save(...) # ttc
fonts.flavor = 'woff2'
fonts.save(...) # woff2 collection
list_of_fonts = [ttFont1, ttFont2, ...]
ttc = TTCollection()
ttc.fonts = list_fonts
ttc.save(...)
fonts.save() To get there, here's a task list:
|
I've implemented basic reading, writing, and saveXML for TTCollection. If someone wants to go ahead and implement ttc2ttf and ttf2ttc, as well as the rest of the list above, would be great. I'm going to leave it for now. |
Thank you @behdad! We'll pick it up from here 👍 |
Return (spline, error) tuple from approximation functions
This is done now by |
Is there someplace where how to use these new split/merge features is explained? |
Try This currently only supports extracting one face from a TTC at a time, using |
Already had updated to latest fonttools and had also ran that help command. |
This does not seem to work with the latest release
However if I invoke the ttLib module directly it works
Environment:
|
That seems to be picking up an older |
I've tried both a "normal" system-wide install and installing in a virtual environment (same results) I.e.
and isolated with venv:
|
yeah, I can reproduce, thanks for the report. We need to add a |
As requested by Adam. Would be useful. Possibly as a separate tool as well as with support in ttx.
The text was updated successfully, but these errors were encountered: