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

Enhance otf2ttf for ttc, parallel, and file wildcards #1000

Merged
merged 18 commits into from Nov 19, 2019

Conversation

msoxzw
Copy link
Contributor

@msoxzw msoxzw commented Oct 16, 2019

I mainly pick these from my repo

From my view, converting ttc font to the first font in ttc is very confusing. Hence, processing ttc font as a whole is a better way compared with splitting font, then merging it.

Moreover, calculating TrueType outline from PostScript outline is time-consuming. So, I add data parallel and file wildcards input for otf2ttf.

@msoxzw
Copy link
Contributor Author

msoxzw commented Oct 16, 2019

However, I do not know how to make a test ttc font for unit test. So, unit test for this PR is missing.

@msoxzw
Copy link
Contributor Author

msoxzw commented Oct 16, 2019

The test error is expected, because multiprocessing module will mess up the logging module, particularly in Windows.

>       assert (b"WARNING: Dropping glyph names, they do not fit in 'post' "
                b"table.") in output
E       assert b"WARNING: Dropping glyph names, they do not fit in 'post' table." in b"Dropping glyph names, they do not fit in 'post' table.\r\n"

@miguelsousa
Copy link
Member

Looking at the failure makes me think that removing the WARNING: part from the expected result should make the test pass again.

Thanks for the PR, by the way. I have a few more comments to make but I need to run some validations first.

@miguelsousa
Copy link
Member

@josh-hadley perhaps something to look into: CircleCI didn't run. I wonder if it didn't happen because the branch to be merged doesn't belong to the afdko repo.

Copy link
Member

@miguelsousa miguelsousa left a comment

Choose a reason for hiding this comment

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

Looks good.
My only request is to handle non-OTF inputs and TTCs containing TTFs more gracefully. Right now the whole process stops at the assert ttFont.sfntVersion == "OTTO". It'd be better to skip the fonts that cannot be converted and log a warning.
Attached are fonts you can use for new tests.
pr1000.zip

@msoxzw
Copy link
Contributor Author

msoxzw commented Oct 18, 2019

@miguelsousa
Sorry, I do not fully understand your words. Given your attachments, I have some confusions:

font.ttf    -> font#1.ttf    or font.tff    -> none

otf_ttf.ttc -> otf_ttf#1.ttc or otf_ttf.ttc -> none
              (ttf_ttf) 

ttf_otf.ttc -> ttf_otf#1.ttc or ttf_otf.ttc -> none
              (ttf_ttf)

ttf_ttf.ttc -> ttf_ttf#1.ttc or ttf_ttf.ttc -> none

@miguelsousa
Copy link
Member

@msoxzw if you look in https://github.com/adobe-type-tools/afdko/tree/develop/tests/otf2ttf_data/input there's only OTFs in there. The TTF and TTC files I provided in the ZIP are for adding new tests.

Here's how I expect otf2ttf to work with the new test input files:

  • font.ttf, skip this file — the font is TTF already
  • ttf_ttf.ttc, skip this file — the TTC contains 2 fonts and they're both TTF
  • otf_otf.ttc, convert this file — the TTC contains 2 fonts and they're both OTF
  • otf_ttf.ttc, convert this file, but skip one of its fonts — the TTC contains 2 fonts; the first font is OTF and the second is TTF
  • ttf_otf.ttc, convert this file, but skip one of its fonts — the TTC contains 2 fonts; the first font is TTF and the second is OTF

@msoxzw
Copy link
Contributor Author

msoxzw commented Oct 19, 2019

@miguelsousa
Thanks a lot. At present I have only a small question:
In otf_ttf.ttc or ttf_otf.ttc, whether or not the original TTF is also saved in the converted TTC font?

@miguelsousa
Copy link
Member

Yes, keep the original TTFs inside the TTCs.
Thank YOU for taking the time to make these enhancements.

@msoxzw
Copy link
Contributor Author

msoxzw commented Oct 20, 2019

@miguelsousa
The test fonts that you provide give me much insight about OpenType.

I assume that the the results of otf_otf.ttc, otf_ttf.ttc, and ttf_otf.ttc are identical to ttf_ttf.ttc excluding checkSumAdjustment, created, and modified. However, the test error seems to detect the bugs in my codes. After a while, I think that I spot the cause of error: the 'hmtx' tables of test fonts are likely to not strictly conform to the OpenType spec, which makes some minor differences between ttf_ttf.tcc and others.

@miguelsousa
Copy link
Member

I assume that the the results of otf_otf.ttc, otf_ttf.ttc, and ttf_otf.ttc are identical to ttf_ttf.ttc excluding checkSumAdjustment, created, and modified

Yes, I also expected that the TTX dump of ttf_ttf.ttc would be the same as the dump of the other TTCs after their conversion.
Looking at the failures I can see that the problem is actually in the TTCs I provided. They were made with subset fonts that didn't get all their values recalculated (e.g. hhea.advanceWidthMax, maxp.maxCompositeContours), so the TTCs wound up with inflated numbers. I'll regenerate the TTCs and provide new files soon.

font = TTCollection(font_path)

temp_path = get_temp_file_path()
font.saveXML(temp_path, tables=tables)
Copy link
Member

Choose a reason for hiding this comment

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

Please add font.close() after font.saveXML().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have investigated this issue before I decided to remove "with" statement. "TTCollection" class does not provide the "close" method. Therefore, adding font.close() is impracticable. However, due to garbage collector of Python, the font object will be automatically closed and deleted, but heavily relying on garbage collector is a bad practice. Of course, there are at least two workarounds:

  1. Re-implement the close method:
if font.reader is not None:
   font.reader.close()
  1. Open font file by built-in open:
with open(font_path, 'rb') as f:    
    try:
        font = TTFont(f)
    except TTLibError:
        font = TTCollection(f)

    temp_path = get_temp_file_path()
    font.saveXML(temp_path, tables=tables)
    return temp_path

Nevertheless, both methods, I think, will add maintenance burden if the "TTCollection" class implement close method in some day.
So, how do you think?

Copy link
Member

Choose a reason for hiding this comment

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

I think the best would be to implement a close() method in the TTCollection class.
Would you mind submitting such change to https://github.com/fonttools/fonttools ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moreover, if I submit such change and it is merged in "fonttools", this whole project will require the latest "fonttools". Hence, is it worthy to do so?

Copy link
Member

Choose a reason for hiding this comment

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

Yes. The afdko always updates to the latest version of FontTools.
A lot of other projects rely on FontTools so every opportunity to make the changes there benefits everyone.

@miguelsousa
Copy link
Member

new_TTCs.zip

@miguelsousa
Copy link
Member

@msoxzw code coverage on otf2ttf dropped quite a lot, most likely because of the parallelisation.

Do you know how to fix the reporting?

@msoxzw
Copy link
Contributor Author

msoxzw commented Oct 22, 2019

@miguelsousa
Thank you for digging out this code coverage issue from my PR. At present, this PR is waiting for the "fontTools" next release 4.0.3, and fonttools/fonttools#1751 has been merged.

@miguelsousa
Copy link
Member

@msoxzw thanks for the FontTools contribution. We'll integrate the upcoming version shortly after it's released.

@miguelsousa
Copy link
Member

@msoxzw FontTools v4.1.0 has been integrated

@msoxzw
Copy link
Contributor Author

msoxzw commented Nov 19, 2019

@miguelsousa I could not figure out why PEP 448 and PEP 498 are identified as invalid syntax in Codacy/PR Quality Review. Probably, the Python version is too old in the PR Quality Review.

@miguelsousa
Copy link
Member

@msoxzw no worries, we're actually thinking of disconnecting Codacy.

Copy link
Member

@miguelsousa miguelsousa left a comment

Choose a reason for hiding this comment

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

Thanks for all the good work.

@miguelsousa miguelsousa merged commit d50fb71 into adobe-type-tools:develop Nov 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants