Skip to content

Commit 50009fc

Browse files
committed
[models] refactor input syntax for L3 (and future L4) sub-spacing
Introduces syntax min:max [default] with new regex input parsing approach. This anticipates future support for L4 range restriction input definitions once fonttools supports this.
1 parent 5631550 commit 50009fc

File tree

1 file changed

+43
-19
lines changed

1 file changed

+43
-19
lines changed

src/slice/models.py

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
# You should have received a copy of the GNU General Public License
1414
# along with Slice. If not, see <https://www.gnu.org/licenses/>.
1515

16+
import re
17+
1618
from fontTools.ttLib import TTFont
1719
from PyQt5.QtCore import QAbstractTableModel, Qt
1820

@@ -197,6 +199,9 @@ def __init__(self, *args):
197199
"Axis 5",
198200
]
199201
self._h_header = ["Min : Max [Default]", "Edit Values"]
202+
self.axis_range_regex = re.compile(
203+
r"(?P<start>\d+(\.\d+)?)\s*\:\s*(?P<end>\d+(\.\d+)?)\s*(\[\s*(?P<default>\d+(\.?\d+)?)\s*\])?"
204+
)
200205

201206
def data(self, index, role):
202207
if role in (Qt.DisplayRole, Qt.EditRole):
@@ -285,7 +290,10 @@ def get_instance_data(self):
285290
# it remains a variable axis
286291
pass
287292
elif ":" in axis_value:
288-
instance_data[axistag] = self.parse_subspace_range(axis_value, axistag)
293+
subspace_range = self.parse_subspace_range(axis_value, axistag)[0]
294+
# for future L4 sub-space support
295+
# subspace_default = self.parse_subspace_range(axis_value, axistag)[1]
296+
instance_data[axistag] = subspace_range
289297
else:
290298
# else use the numeric value set in the editor
291299
try:
@@ -299,31 +307,47 @@ def get_instance_data(self):
299307
return instance_data
300308

301309
def parse_subspace_range(self, range_string, axistag):
302-
range_list = range_string.split(":")
303-
# expect 2 values: min and max range sub-space values
304-
# formatted as `value1:value2`
305-
if len(range_list) != 2:
310+
match = self.axis_range_regex.search(range_string)
311+
312+
# confirm that we match on the regular expression parser
313+
# and that there will be group methods to execute on the regex
314+
if not match:
315+
raise ValueError(
316+
f"{range_string} is not a valid axis range definition for {axistag}."
317+
)
318+
319+
start_string = match.group("start")
320+
end_string = match.group("end")
321+
default_string = match.group("default")
322+
323+
if not start_string or not end_string:
306324
raise ValueError(
307-
f"{range_string} is not a valid axis range. "
308-
f"Use the format `min_value:max_value`"
325+
f"{range_string} is not a valid axis range definition for {axistag}."
309326
)
310-
# remove any extraneous whitespace (e.g., "100 : 200" entry)
311-
# before attempt to cast to a float
327+
328+
float_range_list = []
329+
330+
# cast to float with numeric type validations
312331
try:
313-
range_list[0] = float(range_list[0].strip())
314-
range_list[1] = float(range_list[1].strip())
315-
except ValueError as e:
316-
raise ValueError(f"{range_string} is not a valid axis value range. {e}")
317-
# order the values in case they were entered in reverse
332+
float_range_list.append(float(start_string))
333+
except ValueError:
334+
raise ValueError(f"{start_string} is not a valid axis value for {axistag}.")
335+
336+
try:
337+
float_range_list.append(float(end_string))
338+
except ValueError:
339+
raise ValueError(f"{end_string} is not a valid axis value for {axistag}.")
340+
# sort the values in case they were entered in reverse numeric order
318341
# e.g., 800:400, not 400:800
319-
sorted_range_list = sorted(range_list)
320-
# We only support Level 3 sub-spacing due to the support
342+
sorted_range_list = sorted(float_range_list)
343+
# We only support Level 3 sub-spacing now due to the support
321344
# that is available in fontTools lib. Let's check that user
322345
# included the default axis value in the range request
323346
self.subspace_data_validates_includes_default_value(sorted_range_list, axistag)
324-
# all seems well, return data formatted as tuple
325-
# this is the data format required by fonttools lib
326-
return (sorted_range_list[0], sorted_range_list[1])
347+
# return the tuple range required for L3 support at index 0
348+
# return the default value (currently as string or None) required for
349+
# (future) L4 support at index 1
350+
return ((sorted_range_list[0], sorted_range_list[1]), default_string)
327351

328352
def subspace_data_validates_includes_default_value(self, range_list, axistag):
329353
"""Validates Level 3 sub-space requirement that restricted axis range

0 commit comments

Comments
 (0)