[subset] draw charstrings with NullPen to set the width before dropping hints

This is the same patch as PR #606

Quoting myself:
```
It seems that the horizontal advance of hinted charstrings gets lost when the CFF hinting is stripped with '--no-hinting' option...

T2CharString objects only get assigned a 'witdh' attribute after their 'draw' method is called.

The subsetter's drop_hints function attempts to insert the width back at the beginning of the de-hinted charstring's program, but can do that only if the charstring does have a 'width' attribute:

c63fea0f8f/Lib/fontTools/subset/__init__.py (L1928)

Hence, we must 'draw' the charstring (with a NullPen) before stripping the hints.
```

Now this method fixes the issue (advances are kept) when doing _both_ --no-hinting and --desubroutinize (the test_no_hinting_desubroutinize should now pass, while it was failing before).

However, when one only does does --no-hinting, this method raises an error:

AttributeError: 'NoneType' object has no attribute 'nominalWidthX'
Lib/fontTools/misc/psCharStrings.py:282: AttributeError

(this is reflected in the failing `test_no_hinting_CFF`)
This commit is contained in:
Cosimo Lupo 2017-01-14 14:45:35 +00:00
parent 99303de5c5
commit 3b7124757c
No known key found for this signature in database
GPG Key ID: B61AAAD0B53A6419

View File

@ -7,7 +7,7 @@ from fontTools.misc.py23 import *
from fontTools import ttLib from fontTools import ttLib
from fontTools.ttLib.tables import otTables from fontTools.ttLib.tables import otTables
from fontTools.misc import psCharStrings from fontTools.misc import psCharStrings
from fontTools.pens.boundsPen import BoundsPen from fontTools.pens.basePen import NullPen
from fontTools.misc.loggingTools import Timer from fontTools.misc.loggingTools import Timer
import sys import sys
import struct import struct
@ -1851,8 +1851,8 @@ def prune_pre_subset(self, font, options):
private = font.Private private = font.Private
dfltWdX = private.defaultWidthX dfltWdX = private.defaultWidthX
nmnlWdX = private.nominalWidthX nmnlWdX = private.nominalWidthX
pen = BoundsPen(None) pen = NullPen()
c.draw(pen) # this will set the charstring's width c.draw(pen) # this will set the charstring's width
if c.width != dfltWdX: if c.width != dfltWdX:
c.program = [c.width - nmnlWdX, 'endchar'] c.program = [c.width - nmnlWdX, 'endchar']
else: else:
@ -2211,7 +2211,9 @@ def prune_post_subset(self, options):
subrs = getattr(c.private, "Subrs", []) subrs = getattr(c.private, "Subrs", [])
decompiler = _DehintingT2Decompiler(css, subrs, c.globalSubrs) decompiler = _DehintingT2Decompiler(css, subrs, c.globalSubrs)
decompiler.execute(c) decompiler.execute(c)
pen = NullPen()
for charstring in css: for charstring in css:
charstring.draw(pen) # this will set the charstring's width
charstring.drop_hints() charstring.drop_hints()
del css del css