Sun Position: fix error in HDRI mode when no env tex is selected
[blender-addons.git] / io_curve_svg / svg_util.py
blobf02dc7ff77c9d265e086852ab8e5af3a9d2d6e5e
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 import re
6 units = {"": 1.0,
7 "px": 1.0,
8 "in": 90.0,
9 "mm": 90.0 / 25.4,
10 "cm": 90.0 / 2.54,
11 "pt": 1.25,
12 "pc": 15.0,
13 "em": 1.0,
14 "ex": 1.0,
15 "INVALID": 1.0, # some DocBook files contain this
19 def srgb_to_linearrgb(c):
20 if c < 0.04045:
21 return 0.0 if c < 0.0 else c * (1.0 / 12.92)
22 else:
23 return pow((c + 0.055) * (1.0 / 1.055), 2.4)
26 def check_points_equal(point_a, point_b):
27 return (abs(point_a[0] - point_b[0]) < 1e-6 and
28 abs(point_a[1] - point_b[1]) < 1e-6)
30 match_number = r"-?\d+(\.\d+)?([eE][-+]?\d+)?"
31 match_first_comma = r"^\s*(?=,)"
32 match_comma_pair = r",\s*(?=,)"
33 match_last_comma = r",\s*$"
35 match_number_optional_parts = r"(-?\d+(\.\d*)?([eE][-+]?\d+)?)|(-?\.\d+([eE][-+]?\d+)?)"
36 re_match_number_optional_parts = re.compile(match_number_optional_parts)
38 array_of_floats_pattern = f"({match_number_optional_parts})|{match_first_comma}|{match_comma_pair}|{match_last_comma}"
39 re_array_of_floats_pattern = re.compile(array_of_floats_pattern)
41 def parse_array_of_floats(text):
42 """
43 Accepts comma or space separated list of floats (without units) and returns an array
44 of floating point values.
45 """
46 elements = re_array_of_floats_pattern.findall(text)
47 return [value_to_float(v[0]) for v in elements]
50 def read_float(text: str, start_index: int = 0):
51 """
52 Reads floating point value from a string. Parsing starts at the given index.
54 Returns the value itself (as a string) and index of first character after the value.
55 """
57 n = len(text)
59 # Skip leading whitespace characters and characters which we consider ignorable for float
60 # (like values separator).
61 while start_index < n and (text[start_index].isspace() or text[start_index] == ','):
62 start_index += 1
63 if start_index == n:
64 return "0", start_index
66 text_part = text[start_index:]
67 match = re_match_number_optional_parts.match(text_part)
69 if match is None:
70 raise Exception('Invalid float value near ' + text[start_index:start_index + 10])
72 token = match.group(0)
73 endptr = start_index + match.end(0)
75 return token, endptr
78 def parse_coord(coord, size):
79 """
80 Parse coordinate component to common basis
82 Needed to handle coordinates set in cm, mm, inches.
83 """
85 token, last_char = read_float(coord)
86 val = float(token)
87 unit = coord[last_char:].strip() # strip() in case there is a space
89 if unit == '%':
90 return float(size) / 100.0 * val
91 else:
92 return val * units[unit]
94 return val
97 def value_to_float(value_encoded: str):
98 """
99 A simple wrapper around float() which supports empty strings (which are converted to 0).
101 if len(value_encoded) == 0:
102 return 0
103 return float(value_encoded)