summaryrefslogtreecommitdiffstats
path: root/contrib/python
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2025-06-21 09:48:29 +0300
committerrobot-piglet <[email protected]>2025-06-21 10:03:08 +0300
commit611e4b05d6ad91269dc89f06090a2ae208d5f8f5 (patch)
tree3a9ee0f338c6178febe496e4fe5cf223b460e39f /contrib/python
parente49a9cd791ec787f817f98a7992deedb46478758 (diff)
Intermediate changes
commit_hash:694a59b7c082431d781edd4484f72ab37faca2cd
Diffstat (limited to 'contrib/python')
-rw-r--r--contrib/python/fonttools/.dist-info/METADATA8
-rw-r--r--contrib/python/fonttools/fontTools/__init__.py2
-rw-r--r--contrib/python/fonttools/fontTools/subset/__init__.py82
-rw-r--r--contrib/python/fonttools/fontTools/ttLib/reorderGlyphs.py15
-rw-r--r--contrib/python/fonttools/ya.make2
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)