Merge pull request #2837 from daltonmaag/fix-subset-palette-labels

[subset] Keep nameIDs used by CPAL palette entry labels
This commit is contained in:
Jany Belluz 2022-09-30 16:25:16 +01:00 committed by GitHub
commit 25bcde5f31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 192 additions and 21 deletions

View File

@ -2258,8 +2258,24 @@ def prune_post_subset(self, font, options):
self.numPaletteEntries = len(self.palettes[0])
if self.version == 1:
self.paletteEntryLabels = [
label for i, label in self.paletteEntryLabels if i in retained_palette_indices
kept_labels = []
dropped_labels = []
for i, label in enumerate(self.paletteEntryLabels):
if i in retained_palette_indices:
kept_labels.append(label)
else:
dropped_labels.append(label)
self.paletteEntryLabels = kept_labels
# Remove dropped labels from the name table.
name_table = font["name"]
name_table.names = [
n for n in name_table.names
if (
n.nameID not in dropped_labels
# Only remove nameIDs in the user range and if they're not explicitly kept
or n.nameID < 256
or n.nameID in options.name_IDs
)
]
return bool(self.numPaletteEntries)
@ -2553,6 +2569,10 @@ def prune_pre_subset(self, font, options):
if stat.table.AxisValueArray:
nameIDs.update([val_rec.ValueNameID for val_rec in stat.table.AxisValueArray.AxisValue])
nameIDs.update([axis_rec.AxisNameID for axis_rec in stat.table.DesignAxisRecord.Axis])
cpal = font.get('CPAL')
if cpal and cpal.version == 1:
nameIDs.update(cpal.paletteLabels)
nameIDs.update(cpal.paletteEntryLabels)
if '*' not in options.name_IDs:
self.names = [n for n in self.names if n.nameID in nameIDs]
if not options.name_legacy:

View File

@ -1,3 +1,11 @@
4.37.4 (released 2022-09-30)
----------------------------
- [subset] Keep nameIDs used by CPAL palette entry labels (#2837).
- [varLib] Avoid negative hmtx values when creating font from variable CFF2 font (#2827).
- [instancer] Don't prune stat.ElidedFallbackNameID (#2828).
- [unicodedata] Update Scripts/Blocks to Unicode 15.0 (#2833).
4.37.3 (released 2022-09-20)
----------------------------

View File

@ -1244,6 +1244,52 @@ def colrv1_path(tmp_path):
return output_path
@pytest.fixture
def colrv1_cpalv1_path(colrv1_path):
# upgrade CPAL from v0 to v1 by adding labels
font = TTFont(colrv1_path)
fb = FontBuilder(font=font)
fb.setupCPAL(
[
[
(1.0, 0.0, 0.0, 1.0), # red
(0.0, 1.0, 0.0, 1.0), # green
(0.0, 0.0, 1.0, 1.0), # blue
],
],
paletteLabels=["test palette"],
paletteEntryLabels=["first color", "second color", "third color"]
)
output_path = colrv1_path.parent / "TestCOLRv1CPALv1.ttf"
fb.save(output_path)
return output_path
@pytest.fixture
def colrv1_cpalv1_share_nameID_path(colrv1_path):
font = TTFont(colrv1_path)
fb = FontBuilder(font=font)
fb.setupCPAL(
[
[
(1.0, 0.0, 0.0, 1.0), # red
(0.0, 1.0, 0.0, 1.0), # green
(0.0, 0.0, 1.0, 1.0), # blue
],
],
paletteLabels=["test palette"],
paletteEntryLabels=["first color", "second color", "third color"]
)
# Set the name ID of the first color to use nameID 1 = familyName = "TestCOLRv1"
fb.font["CPAL"].paletteEntryLabels[0] = 1
output_path = colrv1_path.parent / "TestCOLRv1CPALv1.ttf"
fb.save(output_path)
return output_path
def test_subset_COLRv1_and_CPAL(colrv1_path):
subset_path = colrv1_path.parent / (colrv1_path.name + ".subset")
@ -1322,6 +1368,103 @@ def test_subset_COLRv1_and_CPAL(colrv1_path):
]
def test_subset_COLRv1_and_CPALv1(colrv1_cpalv1_path):
subset_path = colrv1_cpalv1_path.parent / (colrv1_cpalv1_path.name + ".subset")
subset.main(
[
str(colrv1_cpalv1_path),
"--glyph-names",
f"--output-file={subset_path}",
"--unicodes=E002,E003,E004",
]
)
subset_font = TTFont(subset_path)
assert "CPAL" in subset_font
cpal = subset_font["CPAL"]
name_table = subset_font["name"]
assert [name_table.getDebugName(name_id) for name_id in cpal.paletteEntryLabels] == [
# "first color", # The first color was pruned
"second color",
"third color",
]
# check that the "first color" name is dropped from name table
font = TTFont(colrv1_cpalv1_path)
first_color_nameID = None
for n in font["name"].names:
if n.toUnicode() == "first color":
first_color_nameID = n.nameID
break
assert first_color_nameID is not None
assert all(n.nameID != first_color_nameID for n in name_table.names)
def test_subset_COLRv1_and_CPALv1_keep_nameID(colrv1_cpalv1_path):
subset_path = colrv1_cpalv1_path.parent / (colrv1_cpalv1_path.name + ".subset")
# figure out the name ID of first color so we can keep it
font = TTFont(colrv1_cpalv1_path)
first_color_nameID = None
for n in font["name"].names:
if n.toUnicode() == "first color":
first_color_nameID = n.nameID
break
assert first_color_nameID is not None
subset.main(
[
str(colrv1_cpalv1_path),
"--glyph-names",
f"--output-file={subset_path}",
"--unicodes=E002,E003,E004",
f"--name-IDs={first_color_nameID}",
]
)
subset_font = TTFont(subset_path)
assert "CPAL" in subset_font
cpal = subset_font["CPAL"]
name_table = subset_font["name"]
assert [name_table.getDebugName(name_id) for name_id in cpal.paletteEntryLabels] == [
# "first color", # The first color was pruned
"second color",
"third color",
]
# Check that the name ID is kept
assert any(n.nameID == first_color_nameID for n in name_table.names)
def test_subset_COLRv1_and_CPALv1_share_nameID(colrv1_cpalv1_share_nameID_path):
subset_path = colrv1_cpalv1_share_nameID_path.parent / (colrv1_cpalv1_share_nameID_path.name + ".subset")
subset.main(
[
str(colrv1_cpalv1_share_nameID_path),
"--glyph-names",
f"--output-file={subset_path}",
"--unicodes=E002,E003,E004",
]
)
subset_font = TTFont(subset_path)
assert "CPAL" in subset_font
cpal = subset_font["CPAL"]
name_table = subset_font["name"]
assert [name_table.getDebugName(name_id) for name_id in cpal.paletteEntryLabels] == [
# "first color", # The first color was pruned
"second color",
"third color",
]
# Check that the name ID 1 is kept
assert any(n.nameID == 1 for n in name_table.names)
def test_subset_COLRv1_and_CPAL_drop_empty(colrv1_path):
subset_path = colrv1_path.parent / (colrv1_path.name + ".subset")