diff options
author | robot-piglet <[email protected]> | 2025-06-21 09:48:29 +0300 |
---|---|---|
committer | robot-piglet <[email protected]> | 2025-06-21 10:03:08 +0300 |
commit | 611e4b05d6ad91269dc89f06090a2ae208d5f8f5 (patch) | |
tree | 3a9ee0f338c6178febe496e4fe5cf223b460e39f /contrib/python | |
parent | e49a9cd791ec787f817f98a7992deedb46478758 (diff) |
Intermediate changes
commit_hash:694a59b7c082431d781edd4484f72ab37faca2cd
Diffstat (limited to 'contrib/python')
-rw-r--r-- | contrib/python/fonttools/.dist-info/METADATA | 8 | ||||
-rw-r--r-- | contrib/python/fonttools/fontTools/__init__.py | 2 | ||||
-rw-r--r-- | contrib/python/fonttools/fontTools/subset/__init__.py | 82 | ||||
-rw-r--r-- | contrib/python/fonttools/fontTools/ttLib/reorderGlyphs.py | 15 | ||||
-rw-r--r-- | contrib/python/fonttools/ya.make | 2 |
5 files changed, 98 insertions, 11 deletions
diff --git a/contrib/python/fonttools/.dist-info/METADATA b/contrib/python/fonttools/.dist-info/METADATA index 052bb26273e..7b18279e831 100644 --- a/contrib/python/fonttools/.dist-info/METADATA +++ b/contrib/python/fonttools/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: fonttools -Version: 4.58.1 +Version: 4.58.2 Summary: Tools to manipulate font files Home-page: http://github.com/fonttools/fonttools Author: Just van Rossum @@ -388,6 +388,12 @@ Have fun! Changelog ~~~~~~~~~ +4.58.2 (released 2025-06-06) +---------------------------- + +- [ttLib.reorderGlyphs] Handle CFF2 when reordering glyphs (#3852) +- [subset] Copy name IDs in use before scrapping or scrambling them for webfonts (#3853) + 4.58.1 (released 2025-05-28) ---------------------------- diff --git a/contrib/python/fonttools/fontTools/__init__.py b/contrib/python/fonttools/fontTools/__init__.py index ee6b53b553e..418fd44b166 100644 --- a/contrib/python/fonttools/fontTools/__init__.py +++ b/contrib/python/fonttools/fontTools/__init__.py @@ -3,6 +3,6 @@ from fontTools.misc.loggingTools import configLogger log = logging.getLogger(__name__) -version = __version__ = "4.58.1" +version = __version__ = "4.58.2" __all__ = ["version", "log", "configLogger"] diff --git a/contrib/python/fonttools/fontTools/subset/__init__.py b/contrib/python/fonttools/fontTools/subset/__init__.py index 71d5f5d80d6..baad419a11e 100644 --- a/contrib/python/fonttools/fontTools/subset/__init__.py +++ b/contrib/python/fonttools/fontTools/subset/__init__.py @@ -2,6 +2,8 @@ # # Google Author(s): Behdad Esfahbod +from __future__ import annotations + from fontTools import config from fontTools.misc.roundTools import otRound from fontTools import ttLib @@ -15,7 +17,7 @@ from fontTools.subset.util import _add_method, _uniq_sort from fontTools.subset.cff import * from fontTools.subset.svg import * from fontTools.varLib import varStore, multiVarStore # For monkey-patching -from fontTools.ttLib.tables._n_a_m_e import NameRecordVisitor +from fontTools.ttLib.tables._n_a_m_e import NameRecordVisitor, makeName from fontTools.unicodedata import mirrored import sys import struct @@ -3004,6 +3006,9 @@ def prune_pre_subset(self, font, options): return True +NAME_IDS_TO_OBFUSCATE = {1, 2, 3, 4, 6, 16, 17, 18} + + @_add_method(ttLib.getTableClass("name")) def prune_post_subset(self, font, options): visitor = NameRecordVisitor() @@ -3022,6 +3027,11 @@ def prune_post_subset(self, font, options): self.names = [n for n in self.names if n.langID in options.name_languages] if options.obfuscate_names: namerecs = [] + # Preserve names to be scrambled or dropped elsewhere so that other + # parts of the font don't break. + needRemapping = visitor.seen.intersection(NAME_IDS_TO_OBFUSCATE) + if needRemapping: + _remap_select_name_ids(font, needRemapping) for n in self.names: if n.nameID in [1, 4]: n.string = ".\x7f".encode("utf_16_be") if n.isUnicode() else ".\x7f" @@ -3036,6 +3046,76 @@ def prune_post_subset(self, font, options): return True # Required table +def _remap_select_name_ids(font: ttLib.TTFont, needRemapping: set[int]) -> None: + """Remap a set of IDs so that the originals can be safely scrambled or + dropped. + + For each name record whose name id is in the `needRemapping` set, make a copy + and allocate a new unused name id in the font-specific range (> 255). + + Finally update references to these in the `fvar` and `STAT` tables. + """ + + if "fvar" not in font and "STAT" not in font: + return + + name = font["name"] + + # 1. Assign new IDs for names to be preserved. + existingIds = {record.nameID for record in name.names} + remapping = {} + nextId = name._findUnusedNameID() - 1 # Should skip gaps in name IDs. + for nameId in needRemapping: + nextId += 1 # We should have complete freedom until 32767. + assert nextId not in existingIds, "_findUnusedNameID did not skip gaps" + if nextId > 32767: + raise ValueError("Ran out of name IDs while trying to remap existing ones.") + remapping[nameId] = nextId + + # 2. Copy records to use the new ID. We can't rewrite them in place, because + # that could make IDs 1 to 6 "disappear" from code that follows. Some + # tools that produce EOT fonts expect them to exist, even when they're + # scrambled. See https://github.com/fonttools/fonttools/issues/165. + copiedRecords = [] + for record in name.names: + if record.nameID not in needRemapping: + continue + recordCopy = makeName( + record.string, + remapping[record.nameID], + record.platformID, + record.platEncID, + record.langID, + ) + copiedRecords.append(recordCopy) + name.names.extend(copiedRecords) + + # 3. Rewrite the corresponding IDs in other tables. For now, care only about + # STAT and fvar. If more tables need to be changed, consider adapting + # NameRecordVisitor to rewrite IDs wherever it finds them. + fvar = font.get("fvar") + if fvar is not None: + for axis in fvar.axes: + axis.axisNameID = remapping.get(axis.axisNameID, axis.axisNameID) + for instance in fvar.instances: + nameID = instance.subfamilyNameID + instance.subfamilyNameID = remapping.get(nameID, nameID) + nameID = instance.postscriptNameID + instance.postscriptNameID = remapping.get(nameID, nameID) + + stat = font.get("STAT") + if stat is None: + return + elidedNameID = stat.table.ElidedFallbackNameID + stat.table.ElidedFallbackNameID = remapping.get(elidedNameID, elidedNameID) + if stat.table.DesignAxisRecord: + for axis in stat.table.DesignAxisRecord.Axis: + axis.AxisNameID = remapping.get(axis.AxisNameID, axis.AxisNameID) + if stat.table.AxisValueArray: + for value in stat.table.AxisValueArray.AxisValue: + value.ValueNameID = remapping.get(value.ValueNameID, value.ValueNameID) + + @_add_method(ttLib.getTableClass("head")) def prune_post_subset(self, font, options): # Force re-compiling head table, to update any recalculated values. diff --git a/contrib/python/fonttools/fontTools/ttLib/reorderGlyphs.py b/contrib/python/fonttools/fontTools/ttLib/reorderGlyphs.py index fd950ba0e32..63ca75a9052 100644 --- a/contrib/python/fonttools/fontTools/ttLib/reorderGlyphs.py +++ b/contrib/python/fonttools/fontTools/ttLib/reorderGlyphs.py @@ -275,10 +275,11 @@ def reorderGlyphs(font: ttLib.TTFont, new_glyph_order: List[str]): for reorder in _REORDER_RULES.get(reorder_key, []): reorder.apply(font, value) - if "CFF " in font: - cff_table = font["CFF "] - charstrings = cff_table.cff.topDictIndex[0].CharStrings.charStrings - cff_table.cff.topDictIndex[0].charset = new_glyph_order - cff_table.cff.topDictIndex[0].CharStrings.charStrings = { - k: charstrings.get(k) for k in new_glyph_order - } + for tag in ["CFF ", "CFF2"]: + if tag in font: + cff_table = font[tag] + charstrings = cff_table.cff.topDictIndex[0].CharStrings.charStrings + cff_table.cff.topDictIndex[0].charset = new_glyph_order + cff_table.cff.topDictIndex[0].CharStrings.charStrings = { + k: charstrings.get(k) for k in new_glyph_order + } diff --git a/contrib/python/fonttools/ya.make b/contrib/python/fonttools/ya.make index 21543c545db..734819d9145 100644 --- a/contrib/python/fonttools/ya.make +++ b/contrib/python/fonttools/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(4.58.1) +VERSION(4.58.2) LICENSE(MIT) |