Skip to content

Commit 776a74b

Browse files
committed
[models] new approach to partial instantiation / sub-space slicing
Revert the use of "var" or "variable" string entry and simply keep variable axis *if user does not enter an explicit value*. This is a more intuitive approach. If you don't enter a value, you don't want change in the source font.
1 parent f95e20a commit 776a74b

File tree

3 files changed

+76
-45
lines changed

3 files changed

+76
-45
lines changed

src/slice/models.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -279,12 +279,7 @@ def get_instance_data(self):
279279
axis_value = self._data[x][1]
280280
if axis_value == "":
281281
# if user did not define the axis value, then
282-
# use the default axis value
283-
instance_data[axistag] = float(self.get_default_axis_value(axistag))
284-
elif axis_value.lower() in ("var", "variable"):
285-
# skip the axis if the user requests that it remains
286-
# a variable design axis with any casing of "var"
287-
# or "variable" text string entry
282+
# it remains a variable axis
288283
pass
289284
else:
290285
# else use the numeric value set in the editor
@@ -298,6 +293,13 @@ def get_instance_data(self):
298293

299294
return instance_data
300295

296+
def instance_data_validates(self):
297+
# validator that returns True if there is at least one
298+
# axis tag with a defined instance, and False if all
299+
# axis tags have blank entry fields = the original variable
300+
# font that the user entered
301+
return len(self.get_instance_data()) != 0
302+
301303
def get_default_axis_value(self, axistag):
302304
if axistag in self.fvar_axes:
303305
# field that contains the default axis value

tests/test_instanceworker.py

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ def bit_is_set(int_type, offset):
1515

1616

1717
def get_font_model():
18+
# Values in this test font
19+
# {'axisTag': 'MONO', 'axisNameID': 269, 'flags': 0, 'minValue': 0.0, 'defaultValue': 0.0, 'maxValue': 1.0}
20+
# {'axisTag': 'CASL', 'axisNameID': 270, 'flags': 0, 'minValue': 0.0, 'defaultValue': 0.0, 'maxValue': 1.0}
21+
# {'axisTag': 'wght', 'axisNameID': 271, 'flags': 0, 'minValue': 300.0, 'defaultValue': 300.0, 'maxValue': 1000.0}
22+
# {'axisTag': 'slnt', 'axisNameID': 272, 'flags': 0, 'minValue': -15.0, 'defaultValue': 0.0, 'maxValue': 0.0}
23+
# {'axisTag': 'CRSV', 'axisNameID': 273, 'flags': 0, 'minValue': 0.0, 'defaultValue': 0.5, 'maxValue': 1.0}
1824
return FontModel(Path("tests/assets/fonts/Recursive-VF.subset.ttf").resolve())
1925

2026

@@ -90,7 +96,11 @@ def test_instanceworker_class_default(tmpdir):
9096
assert iw.ttfont is None
9197

9298

93-
def test_instanceworker_instantiate_ttfont_and_gen_static_instance(tmpdir):
99+
def test_instanceworker_instantiate_ttfont_and_gen_with_no_user_axis_defs(tmpdir):
100+
# This should gen to the var font with the same axis ranges
101+
# Note that this route is not executed because the application validates
102+
# that at least one axis is defined, else there is nothing to do
103+
# since the request is the original var font if there are no axis value defs
94104
outpath = str(tmpdir.join("test.ttf"))
95105
font_model = get_font_model()
96106

@@ -121,20 +131,32 @@ def test_instanceworker_instantiate_ttfont_and_gen_static_instance(tmpdir):
121131
# it is a variable font and should have an fvar table
122132
assert "fvar" in iw.ttfont
123133

124-
# after instantiation of the static, fvar should be gone
134+
# confirm that all variable axes remain
125135
iw.instantiate_variable_font()
126-
assert "fvar" not in iw.ttfont
136+
assert "fvar" in iw.ttfont
137+
# make list of axis tags
138+
axis_tags = [axis.axisTag for axis in iw.ttfont["fvar"].axes]
139+
# the font should include all variable axis tags in the original
140+
assert "MONO" in axis_tags
141+
assert "CASL" in axis_tags
142+
assert "wght" in axis_tags
143+
assert "slnt" in axis_tags
144+
assert "CRSV" in axis_tags
127145

128146

129147
def test_instanceworker_instantiate_ttfont_and_gen_partial_instance_one_axis(tmpdir):
148+
# When there are
130149
outpath = str(tmpdir.join("test.ttf"))
131150
font_model = get_font_model()
132151

133152
axis_model = DesignAxisModel()
134153
axis_model.load_font(font_model)
135-
# the next step sets the user entered text to a value of "var"
136-
# on the "MONO" axis row
137-
axis_model._data[0][1] = "var"
154+
# "MONO" axis defined as variable (i.e., no user input)
155+
axis_model._data[0][1] = ""
156+
axis_model._data[1][1] = "0"
157+
axis_model._data[2][1] = "300"
158+
axis_model._data[3][1] = "0"
159+
axis_model._data[4][1] = "0.5"
138160

139161
name_model = FontNameModel()
140162
name_model.load_font(font_model)
@@ -163,7 +185,15 @@ def test_instanceworker_instantiate_ttfont_and_gen_partial_instance_one_axis(tmp
163185
assert "fvar" in iw.ttfont
164186
# in the test font, the "MONO" axis should still be variable
165187
# with the variable setting that was used above
166-
assert [a.axisTag for a in iw.ttfont["fvar"].axes] == ["MONO"]
188+
# make list of axis tags
189+
axis_tags = [axis.axisTag for axis in iw.ttfont["fvar"].axes]
190+
# the font should include a variable MONO axis, all others
191+
# should have been sliced
192+
assert "MONO" in axis_tags
193+
assert "CASL" not in axis_tags
194+
assert "wght" not in axis_tags
195+
assert "slnt" not in axis_tags
196+
assert "CRSV" not in axis_tags
167197

168198

169199
def test_instanceworker_instantiate_ttfont_and_gen_partial_instance_multi_axis(tmpdir):
@@ -172,10 +202,14 @@ def test_instanceworker_instantiate_ttfont_and_gen_partial_instance_multi_axis(t
172202

173203
axis_model = DesignAxisModel()
174204
axis_model.load_font(font_model)
175-
# the next step sets the user entered text to a value of "var"
176-
# and "variable" on the "MONO" and "wght" axis rows, respectively
177-
axis_model._data[0][1] = "var"
178-
axis_model._data[2][1] = "variable"
205+
# the next step mocks lack of user entry in MONO and CASL axis fields
206+
# with values defined for other fields. This should lead to a sub-space
207+
# build with variable and wght var axes
208+
axis_model._data[0][1] = ""
209+
axis_model._data[1][1] = ""
210+
axis_model._data[2][1] = "300"
211+
axis_model._data[3][1] = "0"
212+
axis_model._data[4][1] = "0.5"
179213

180214
name_model = FontNameModel()
181215
name_model.load_font(font_model)
@@ -199,12 +233,17 @@ def test_instanceworker_instantiate_ttfont_and_gen_partial_instance_multi_axis(t
199233
# it is a variable font and should have an fvar table
200234
assert "fvar" in iw.ttfont
201235

202-
# after instantiation of the partial, fvar should still be present
236+
# after sub-space gen, fvar should still be present
203237
iw.instantiate_variable_font()
204238
assert "fvar" in iw.ttfont
205-
# in the test font, the "MONO" axis should still be variable
206-
# with the variable setting that was used above
207-
assert [a.axisTag for a in iw.ttfont["fvar"].axes] == ["MONO", "wght"]
239+
axis_tags = [axis.axisTag for axis in iw.ttfont["fvar"].axes]
240+
# the font should include a variable MONO and CASL axes, all others
241+
# should have been sliced
242+
assert "MONO" in axis_tags
243+
assert "CASL" in axis_tags
244+
assert "wght" not in axis_tags
245+
assert "slnt" not in axis_tags
246+
assert "CRSV" not in axis_tags
208247

209248

210249
def test_instanceworker_instantiate_ttfont_raises_valueerror_on_invalid_data(tmpdir):

tests/test_models_designaxis.py

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,18 @@ def test_designaxis_model_filled(qtbot, qtmodeltester):
4848
]
4949

5050

51-
def test_designaxis_model_get_static_instance_data(qtbot):
51+
def test_designaxis_model_get_instance_data(qtbot):
5252
tableview = QTableView()
5353
model = DesignAxisModel()
5454
tableview.setModel(model)
5555
qtbot.addWidget(tableview)
5656
model.load_font(get_font_model())
5757

58-
# without user entered definitions, we should get default
59-
# axis values
60-
assert model.get_instance_data() == {
61-
"MONO": 0.0,
62-
"CASL": 0.0,
63-
"wght": 300.0,
64-
"slnt": 0.0,
65-
"CRSV": 0.5,
66-
}
58+
# without user entered definitions, we should get
59+
# an empty axis tag / value dict
60+
# this is intentional so that these axes remain
61+
# variable
62+
assert model.get_instance_data() == {}
6763

6864
# simulate update of model data with user input
6965
# and check again to confirm that it is present
@@ -90,28 +86,22 @@ def test_designaxis_model_get_partial_instance_data(qtbot):
9086
qtbot.addWidget(tableview)
9187
model.load_font(get_font_model())
9288

93-
# without user entered definitions, we should get default
94-
# axis values
95-
assert model.get_instance_data() == {
96-
"MONO": 0.0,
97-
"CASL": 0.0,
98-
"wght": 300.0,
99-
"slnt": 0.0,
100-
"CRSV": 0.5,
101-
}
89+
# without user entered definitions, we should get
90+
# empty set
91+
assert model.get_instance_data() == {}
10292

10393
# simulate update of model data with user input
104-
# that requests partial instance that maintains
94+
# that requests sub-space that maintains
10595
# variable "MONO" and "slnt" axes
106-
# (i.e. includes "var" and "Variable" definitions)
107-
model._data[0][1] = "var"
96+
# (i.e. these fields are empty)
97+
model._data[0][1] = ""
10898
model._data[1][1] = "1.0"
10999
model._data[2][1] = "1000.0"
110-
model._data[3][1] = "Variable"
100+
model._data[3][1] = ""
111101
model._data[4][1] = "1.0"
112102
model.layoutChanged.emit()
113103

114-
# should not include axis tags: "MONO", "slnt"
104+
# should not include instance values for: "MONO", "slnt"
115105
# the instantiation function maintains variable
116106
# axes for any axis tag that is present in font
117107
# and not included in this dict

0 commit comments

Comments
 (0)