Somehow we forgot to replace round -> otRound in arrayTools.calcIntBounds.
This function is used by glyf table to compute the glyphs' bounding boxes.
We already use otRound (aka 'int(math.floor(v + .5))') to round glyph
coordinates upon compiling glyf table. So the use of python3's round
in calcIntBounds was producing inconsistent roundings between the glyph
coordinates and the glyph bbox (sometimes, i.e. only when the glyf table
contains float coordinates, e.g. after instantiating with varLib.mutator).
* a charstring is not guaranteed to end in an operator, so the final bytecodes 11 and 14 can be part of an encoded numeric value; so remove 'return' or 'endchar' at the program level instead of bytescode
* move non-CFF2 test+error to elif clause of earlier isCFF2 test
Fixes the remaining issue from #1451
* fix two cases where pathlib.Path objects were not accepted
* make macRes reader accept os.PathLike objects
* use __fspath__ explicitly to support os.PathLike paths
* use __fspath__ explicitly to support os.PathLike paths
* convert tmpdir to str
* only test pathlib.Path on Python 3.6 and up
@bedhad
Address issues raised in #1403
I do think setting the dummy CFF2 PrivateDict nominalWidthX and defaultWidthX to None, which leads to the charstring.width also being None, is a good idea. I originally set them to 0, which produces a charstring width of 0, in order to avoid problems with logic that assumes that the field is good for math. However, I now think that it is better to find errors around charstring type assumptions earlier than later.
"drop_hints()" is actually not wrong - I did look at this when making the changes. For CFF2 charstrings, self.width is always equal to self.private.defaultWidthX, so the width is never inserted. This is because in psCharstrings.py::T2WidthExtractor.popallWidth(), the test "evenOdd ^ (len(args) % 2)" is alway False. Left to myself, I would not change this code. If the CFF2 charstring is correct, there is not a problem. if the CFF2 charstring is not correct, then both in drop_hints() and in T2WidthExtractor.popallWidth(), the logic will stack dump. I did add asserts, but am not totally sure it is worth the extra calls.
Fixed psCharstrings so that calc_bounds will run. I would guess no-one has tried to use a BoundsPen on a CFF2 VF before - thanks to Chris Chapman. It now returns a result only for the default instance.
Fixed bug in subsetting: removed assert that a Subr is not empty after subsetting or de-hinting. CFF2 Charstrings do not have terminal "return' op.
Removed check_program functions. Supporting these requires knowledge of CFF vs CFF2 state, whci is leads to wide-spread diffuse changes. Also, not needed - the endchar/return opcodes are removed when compiling for CFF2.
Removed CFF2Subr class. This was used for CFF2 CharStrings, and allowed avoiding referencing the width fields. I worked around this by providing dummy values for the Private.nominalWidthX and defaultWidthX.
Added a public method PrivateDict.in_cff2.
varStore.py. Commit the correct function references.
psCharstrings.py. Add decompiler class specifically for flattening subroutinized charstrings.
mutator.py. Flatten the subroutinized charstrings, delete the Subrs.
TestCFF2VF.otf, Updated to version with subroutinization. Updated expected ttx output.
UFO images have a transformation matrix with those names.
This makes the Transform look more like a namedtuple, in that it can be accessed both by
index and by property name.
we can't set the logger.level directly because in py37 the logger has a _cache
attribute and that needs to be invalidated by calling setLevel method.
also, I noticed we weren't restoring the original 'disabled' attribute value...
And we need to also set/restore the 'propagate' attribute.
by encoding as integers all float values that have no decimal portion.
This optimization is expected to reduce the file size of CFF2 fonts that have intermediate masters.
Related to https://github.com/adobe-type-tools/afdko/issues/444
Many thanks to @cjchapman for the help on the fixed point math
To avoid the 'No handlers could be fonud' message, from now on, one should always
configure logging in one's scripts or applications.
logging.basicConfig, or fontTools.configLogger (with some predefined defaults
useful for fonttools scripts) can be used to quickly configure logging.
Read the python docs for more advanced logging usage.
So we now round towards +Infinity in:
- floatToFixed (which fully examplify that quotes from OT spec)
- psCharStrings: when packing floats as fixed 16.16
- t2CharStringPen: when rounding coordinates and advance widths
- subset: when rounding advance widths to compute average
- TupleVariation: rounding gvar deltas
- _g_l_y_f: when rounding coordinates: both in GlyphComponent.{x,y}
and for GlyphCoordinates.toInt()
- _h_m_t_x: for rounding horiz/vert metrics
- varLib: rounding horiz metrics and deltas
the logger name is constant (based on the user class's name and module)
so we can cache it.
(this means the LogMixin will only work on regular dict-based classes,
not on 'slotted' classes. But that's ok