[varc] Use Condition instead of ConditionSet

With more Condition formats.

df7dcc4618
https://github.com/harfbuzz/boring-expansion-spec/issues/147
This commit is contained in:
Behdad Esfahbod 2024-04-22 14:30:30 -06:00
parent 9cb73dafeb
commit 973dc5c9a7
5 changed files with 106 additions and 42 deletions

View File

@ -2693,21 +2693,21 @@ def prune_post_subset(self, font, options):
if comp.axisIndicesIndex is not None:
comp.axisIndicesIndex = mapping[comp.axisIndicesIndex]
conditionSetList = table.ConditionSetList
if conditionSetList is not None:
conditionSets = conditionSetList.ConditionSet
conditionList = table.ConditionList
if conditionList is not None:
conditionTables = conditionList.ConditionTable
usedIndices = set()
for glyph in table.VarCompositeGlyphs.VarCompositeGlyph:
for comp in glyph.components:
if comp.conditionSetIndex is not None:
usedIndices.add(comp.conditionSetIndex)
if comp.conditionIndex is not None:
usedIndices.add(comp.conditionIndex)
usedIndices = sorted(usedIndices)
conditionSetList.ConditionSet = _list_subset(conditionSets, usedIndices)
conditionList.ConditionTable = _list_subset(conditionTables, usedIndices)
mapping = {old: new for new, old in enumerate(usedIndices)}
for glyph in table.VarCompositeGlyphs.VarCompositeGlyph:
for comp in glyph.components:
if comp.conditionSetIndex is not None:
comp.conditionSetIndex = mapping[comp.conditionSetIndex]
if comp.conditionIndex is not None:
comp.conditionIndex = mapping[comp.conditionIndex]
return True

View File

@ -3169,21 +3169,21 @@ otData = [
],
),
(
"ConditionSetList",
"ConditionList",
[
(
"uint32",
"ConditionSetCount",
"ConditionCount",
None,
None,
"Number of condition-set tables in the ConditionSet array",
"Number of condition tables in the ConditionTable array",
),
(
"LOffset",
"ConditionSet",
"ConditionSetCount",
"ConditionTable",
"ConditionCount",
0,
"Array of condition-set tables.",
"Array of offset to condition tables, from the beginning of the ConditionList table.",
),
],
),
@ -3202,7 +3202,7 @@ otData = [
"ConditionTable",
"ConditionCount",
0,
"Array of condition tables.",
"Array of offset to condition tables, from the beginning of the ConditionSet table.",
),
],
),
@ -3233,6 +3233,59 @@ otData = [
),
],
),
(
"ConditionTableFormat2",
[
("uint16", "Format", None, None, "Format, = 2"),
(
"uint8",
"ConditionCount",
None,
None,
"Index for the variation axis within the fvar table, base 0.",
),
(
"Offset24",
"ConditionTable",
"ConditionCount",
0,
"Array of condition tables for this conjunction (AND) expression.",
),
],
),
(
"ConditionTableFormat3",
[
("uint16", "Format", None, None, "Format, = 3"),
(
"uint8",
"ConditionCount",
None,
None,
"Index for the variation axis within the fvar table, base 0.",
),
(
"Offset24",
"ConditionTable",
"ConditionCount",
0,
"Array of condition tables for this disjunction (OR) expression.",
),
],
),
(
"ConditionTableFormat4",
[
("uint16", "Format", None, None, "Format, = 4"),
(
"Offset24",
"ConditionTable",
None,
None,
"Condition to negate.",
),
],
),
(
"FeatureTableSubstitution",
[
@ -3396,7 +3449,7 @@ otData = [
),
("LOffset", "Coverage", None, None, ""),
("LOffset", "MultiVarStore", None, None, "(may be NULL)"),
("LOffset", "ConditionSetList", None, None, "(may be NULL)"),
("LOffset", "ConditionList", None, None, "(may be NULL)"),
("LOffset", "AxisIndicesList", None, None, "(may be NULL)"),
("LOffset", "VarCompositeGlyphs", None, None, ""),
],

View File

@ -158,7 +158,7 @@ class VarComponent:
def populateDefaults(self, propagator=None):
self.flags = 0
self.glyphName = None
self.conditionSetIndex = None
self.conditionIndex = None
self.axisIndicesIndex = None
self.axisValues = ()
self.axisValuesVarIndex = NO_VARIATION_INDEX
@ -176,7 +176,7 @@ class VarComponent:
self.glyphName = font.glyphOrder[glyphID]
if flags & VarComponentFlags.HAVE_CONDITION:
self.conditionSetIndex, i = _read_uint32var(data, i)
self.conditionIndex, i = _read_uint32var(data, i)
if flags & VarComponentFlags.HAVE_AXES:
self.axisIndicesIndex, i = _read_uint32var(data, i)
@ -248,9 +248,9 @@ class VarComponent:
flags &= ~VarComponentFlags.GID_IS_24BIT
data.append(_packer[2](glyphID))
if self.conditionSetIndex is not None:
if self.conditionIndex is not None:
flags |= VarComponentFlags.HAVE_CONDITION
data.append(_write_uint32var(self.conditionSetIndex))
data.append(_write_uint32var(self.conditionIndex))
numAxes = len(self.axisValues)
@ -301,8 +301,8 @@ class VarComponent:
write("glyphName", self.glyphName)
if self.conditionSetIndex is not None:
write("conditionSetIndex", self.conditionSetIndex)
if self.conditionIndex is not None:
write("conditionIndex", self.conditionIndex)
if self.axisIndicesIndex is not None:
write("axisIndicesIndex", self.axisIndicesIndex)
if (
@ -342,8 +342,8 @@ class VarComponent:
if name == "glyphName":
self.glyphName = v
elif name == "conditionSetIndex":
self.conditionSetIndex = safeEval(v)
elif name == "conditionIndex":
self.conditionIndex = safeEval(v)
elif name == "axisIndicesIndex":
self.axisIndicesIndex = safeEval(v)
elif name == "axisValues":

View File

@ -276,6 +276,33 @@ class _TTGlyphCFF(_TTGlyph):
self.glyphSet.charStrings[self.name].draw(pen, self.glyphSet.blender)
def _evaluateCondition(condition, fvarAxes, location):
if condition.Format == 1:
axisIndex = condition.AxisIndex
axisTag = fvarAxes[axisIndex].axisTag
axisValue = location.get(axisTag, 0)
minValue = condition.FilterRangeMinValue
maxValue = condition.FilterRangeMaxValue
return minValue <= axisValue <= maxValue
elif condition.Format == 2:
# ConditionAnd
for subcondition in condition.ConditionTable:
if not _evaluateCondition(subcondition, fvarAxes, location):
return False
return True
elif condition.Format == 3:
# ConditionOr
for subcondition in condition.ConditionTable:
if _evaluateCondition(subcondition, fvarAxes, location):
return True
return False
elif condition.Format == 4:
# ConditionNegate
return not _evaluateCondition(condition.conditionTable, fvarAxes, location)
else:
return False # Unkonwn condition format
class _TTGlyphVARC(_TTGlyph):
def _draw(self, pen, isPointPen):
"""Draw the glyph onto ``pen``. See fontTools.pens.basePen for details
@ -301,24 +328,8 @@ class _TTGlyphVARC(_TTGlyph):
for comp in glyph.components:
if comp.flags & VarComponentFlags.HAVE_CONDITION:
conditionSet = varc.ConditionSetList.ConditionSet[
comp.conditionSetIndex
]
# Evaluate condition
show = True
for condition in conditionSet.ConditionTable:
if condition.Format == 1:
axisIndex = condition.AxisIndex
axisTag = fvarAxes[axisIndex].axisTag
axisValue = self.glyphSet.location.get(axisTag, 0)
minValue = condition.FilterRangeMinValue
maxValue = condition.FilterRangeMaxValue
if not (minValue <= axisValue <= maxValue):
show = False
break
else:
show = False # Unkonwn condition format
if not show:
condition = varc.ConditionList.ConditionTable[comp.conditionIndex]
if not _evaluateCondition(condition, fvarAxes, self.glyphSet.location):
continue
location = {}