svg-ultralight 0.37.0__py3-none-any.whl → 0.39.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of svg-ultralight might be problematic. Click here for more details.
- svg_ultralight/bounding_boxes/bound_helpers.py +4 -11
- svg_ultralight/bounding_boxes/supports_bounds.py +4 -9
- svg_ultralight/bounding_boxes/type_bound_collection.py +2 -2
- svg_ultralight/bounding_boxes/type_bound_element.py +4 -5
- svg_ultralight/bounding_boxes/type_bounding_box.py +155 -262
- svg_ultralight/bounding_boxes/type_padded_text.py +65 -205
- svg_ultralight/constructors/new_element.py +3 -1
- svg_ultralight/inkscape.py +3 -1
- svg_ultralight/layout.py +22 -13
- svg_ultralight/main.py +12 -4
- svg_ultralight/metadata.py +1 -1
- svg_ultralight/query.py +72 -40
- svg_ultralight/root_elements.py +3 -1
- svg_ultralight/string_conversion.py +7 -3
- svg_ultralight/transformations.py +17 -9
- {svg_ultralight-0.37.0.dist-info → svg_ultralight-0.39.0.dist-info}/METADATA +5 -4
- svg_ultralight-0.39.0.dist-info/RECORD +29 -0
- {svg_ultralight-0.37.0.dist-info → svg_ultralight-0.39.0.dist-info}/WHEEL +1 -1
- svg_ultralight-0.37.0.dist-info/RECORD +0 -29
- {svg_ultralight-0.37.0.dist-info → svg_ultralight-0.39.0.dist-info}/top_level.txt +0 -0
svg_ultralight/query.py
CHANGED
|
@@ -21,7 +21,7 @@ from copy import deepcopy
|
|
|
21
21
|
from pathlib import Path
|
|
22
22
|
from subprocess import PIPE, Popen
|
|
23
23
|
from tempfile import NamedTemporaryFile, TemporaryFile
|
|
24
|
-
from typing import TYPE_CHECKING
|
|
24
|
+
from typing import TYPE_CHECKING, Literal
|
|
25
25
|
from warnings import warn
|
|
26
26
|
|
|
27
27
|
from lxml import etree
|
|
@@ -31,7 +31,11 @@ from svg_ultralight.bounding_boxes.type_padded_text import PaddedText
|
|
|
31
31
|
from svg_ultralight.main import new_svg_root, write_svg
|
|
32
32
|
|
|
33
33
|
if TYPE_CHECKING:
|
|
34
|
-
from
|
|
34
|
+
from collections.abc import Iterator
|
|
35
|
+
|
|
36
|
+
from lxml.etree import (
|
|
37
|
+
_Element as EtreeElement, # pyright: ignore[reportPrivateUsage]
|
|
38
|
+
)
|
|
35
39
|
|
|
36
40
|
|
|
37
41
|
with TemporaryFile() as f:
|
|
@@ -39,24 +43,27 @@ with TemporaryFile() as f:
|
|
|
39
43
|
|
|
40
44
|
_CACHE_DIR.mkdir(exist_ok=True)
|
|
41
45
|
|
|
46
|
+
_TEMP_ID_PREFIX = "svg_ultralight-temp_query_module-"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _iter_elems(*elem_args: EtreeElement) -> Iterator[EtreeElement]:
|
|
50
|
+
"""Yield element and sub-elements."""
|
|
51
|
+
for elem in elem_args:
|
|
52
|
+
yield from elem.iter()
|
|
53
|
+
|
|
42
54
|
|
|
43
55
|
def _fill_ids(*elem_args: EtreeElement) -> None:
|
|
44
56
|
"""Set the id attribute of an element and all its children. Keep existing ids.
|
|
45
57
|
|
|
46
58
|
:param elem: an etree element, accepts multiple arguments
|
|
47
59
|
"""
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
for child in elem:
|
|
52
|
-
_fill_ids(child)
|
|
53
|
-
if elem.get("id") is None:
|
|
54
|
-
elem.set("id", f"svg_ul-{uuid.uuid4()}")
|
|
55
|
-
_fill_ids(*elem_args[1:])
|
|
60
|
+
for elem in _iter_elems(*elem_args):
|
|
61
|
+
if elem.get("id") is None:
|
|
62
|
+
elem.set("id", f"{_TEMP_ID_PREFIX}-{uuid.uuid4()}")
|
|
56
63
|
|
|
57
64
|
|
|
58
65
|
def _normalize_views(elem: EtreeElement) -> None:
|
|
59
|
-
"""Create a square
|
|
66
|
+
"""Create a square viewBox for any element with an svg tag.
|
|
60
67
|
|
|
61
68
|
:param elem: an etree element
|
|
62
69
|
|
|
@@ -83,57 +90,82 @@ def _envelop_copies(*elem_args: EtreeElement) -> EtreeElement:
|
|
|
83
90
|
return envelope
|
|
84
91
|
|
|
85
92
|
|
|
86
|
-
def
|
|
93
|
+
def _split_bb_string(bb_string: str) -> tuple[str, BoundingBox]:
|
|
94
|
+
"""Split a bounding box string into id and BoundingBox instance.
|
|
95
|
+
|
|
96
|
+
:param bb_string: "id,x,y,width,height"
|
|
97
|
+
:return: (id, BoundingBox(x, y, width, height))
|
|
98
|
+
"""
|
|
99
|
+
id_, *bounds = bb_string.split(",")
|
|
100
|
+
x, y, width, height = (float(x) for x in bounds)
|
|
101
|
+
return id_, BoundingBox(x, y, width, height)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def map_elems_to_bounding_boxes(
|
|
87
105
|
inkscape: str | Path, *elem_args: EtreeElement
|
|
88
|
-
) -> dict[
|
|
106
|
+
) -> dict[EtreeElement | Literal["svg"], BoundingBox]:
|
|
89
107
|
r"""Query an svg file for bounding-box dimensions.
|
|
90
108
|
|
|
91
109
|
:param inkscape: path to an inkscape executable on your local file system
|
|
92
110
|
IMPORTANT: path cannot end with ``.exe``.
|
|
93
111
|
Use something like ``"C:\\Program Files\\Inkscape\\inkscape"``
|
|
94
112
|
:param elem_args: xml element (written to a temporary file then queried)
|
|
95
|
-
:return: svg
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
113
|
+
:return: input svg elements and any descendents of those elements mapped
|
|
114
|
+
`BoundingBox(x, y, width, height)`
|
|
115
|
+
So return dict keys are the input elements themselves with one exception: a
|
|
116
|
+
string key, "svg", is mapped to a bounding box around all input elements.
|
|
117
|
+
:effects: temporarily adds an id attribute if any ids are missing. These are
|
|
118
|
+
removed if the function completes. Existing, non-unique ids will break this
|
|
119
|
+
function.
|
|
120
|
+
|
|
121
|
+
Bounding boxes are relative to svg viewBox. If, for instance, viewBox x == -10,
|
|
101
122
|
all bounding-box x values will be offset -10. So, everything is wrapped in a root
|
|
102
|
-
element with a "normalized"
|
|
103
|
-
elements ("child root elements" sounds wrong, but it works)
|
|
104
|
-
normalized as well. This works even with a root element around a
|
|
105
|
-
input elem_args can be root elements or "normal" elements like
|
|
106
|
-
or "text" or a mixture of both.
|
|
123
|
+
element, `envelope` with a "normalized" viewBox, `viewBox=(0, 0, 1, 1)`. That
|
|
124
|
+
way, any child root elements ("child root elements" sounds wrong, but it works)
|
|
125
|
+
viewBoxes are normalized as well. This works even with a root element around a
|
|
126
|
+
root element, so input elem_args can be root elements or "normal" elements like
|
|
127
|
+
"rect", "circle", or "text" or a mixture of both. Bounding boxes output here will
|
|
128
|
+
work as expected in any viewBox.
|
|
107
129
|
|
|
108
130
|
The ``inkscape --query-all svg`` call will return a tuple:
|
|
109
131
|
|
|
110
132
|
(b'svg1,x,y,width,height\\r\\elem1,x,y,width,height\\r\\n', None)
|
|
111
133
|
where x, y, width, and height are strings of numbers.
|
|
112
134
|
|
|
113
|
-
This calls the command and formats the output into a dictionary.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
a
|
|
118
|
-
|
|
135
|
+
This calls the command and formats the output into a dictionary. There is a
|
|
136
|
+
little extra complexity to handle cases with duplicate elements. Inkscape will
|
|
137
|
+
map bounding boxes to element ids *if* those ids are unique. If Inkscape
|
|
138
|
+
encounters a duplicate ID, Inkscape will map the bounding box of that element to
|
|
139
|
+
a string like "rect1". If you pass unequal elements with the same id, I can't
|
|
140
|
+
help you, but you might pass the same element multiple times. If you do this,
|
|
141
|
+
Inkscape will find a bounding box for each occurrence, map the first occurrence
|
|
142
|
+
to the id, then map subsequent occurrences to a string like "rect1". This
|
|
143
|
+
function will handle that.
|
|
119
144
|
"""
|
|
120
145
|
if not elem_args:
|
|
121
146
|
return {}
|
|
122
147
|
_fill_ids(*elem_args)
|
|
123
|
-
envelope = _envelop_copies(*elem_args)
|
|
124
148
|
|
|
149
|
+
envelope = _envelop_copies(*elem_args)
|
|
125
150
|
with NamedTemporaryFile(mode="wb", delete=False, suffix=".svg") as svg_file:
|
|
126
151
|
svg = write_svg(svg_file, envelope)
|
|
127
152
|
with Popen(f'"{inkscape}" --query-all {svg}', stdout=PIPE) as bb_process:
|
|
128
153
|
bb_data = str(bb_process.communicate()[0])[2:-1]
|
|
129
|
-
bb_strings = re.split(r"[\\r]*\\n", bb_data)[:-1]
|
|
130
154
|
os.unlink(svg_file.name)
|
|
131
155
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
156
|
+
bb_strings = re.split(r"[\\r]*\\n", bb_data)[:-1]
|
|
157
|
+
id2bbox = dict(map(_split_bb_string, bb_strings))
|
|
158
|
+
|
|
159
|
+
elem2bbox: dict[EtreeElement | Literal["svg"], BoundingBox] = {}
|
|
160
|
+
for elem in _iter_elems(*elem_args):
|
|
161
|
+
elem_id = elem.attrib.get("id")
|
|
162
|
+
if not (elem_id): # id removed in a previous loop
|
|
163
|
+
continue
|
|
164
|
+
elem2bbox[elem] = id2bbox[elem_id]
|
|
165
|
+
if elem_id.startswith(_TEMP_ID_PREFIX):
|
|
166
|
+
del elem.attrib["id"]
|
|
167
|
+
elem2bbox["svg"] = BoundingBox.merged(*id2bbox.values())
|
|
168
|
+
return elem2bbox
|
|
137
169
|
|
|
138
170
|
|
|
139
171
|
def _hash_elem(elem: EtreeElement) -> str:
|
|
@@ -178,7 +210,7 @@ def get_bounding_boxes(
|
|
|
178
210
|
|
|
179
211
|
This will work most of the time, but if you're missing an nsmap, you'll need to
|
|
180
212
|
create an entire xml file with a custom nsmap (using
|
|
181
|
-
`svg_ultralight.new_svg_root`) then call `
|
|
213
|
+
`svg_ultralight.new_svg_root`) then call `map_elems_to_bounding_boxes` directly.
|
|
182
214
|
"""
|
|
183
215
|
elem2hash = {elem: _hash_elem(elem) for elem in elem_args}
|
|
184
216
|
cached = [_try_bbox_cache(h) for h in elem2hash.values()]
|
|
@@ -187,10 +219,10 @@ def get_bounding_boxes(
|
|
|
187
219
|
|
|
188
220
|
hash2bbox = {h: c for h, c in zip(elem2hash.values(), cached) if c is not None}
|
|
189
221
|
remainder = [e for e, c in zip(elem_args, cached) if c is None]
|
|
190
|
-
id2bbox =
|
|
222
|
+
id2bbox = map_elems_to_bounding_boxes(inkscape, *remainder)
|
|
191
223
|
for elem in remainder:
|
|
192
224
|
hash_ = elem2hash[elem]
|
|
193
|
-
hash2bbox[hash_] = id2bbox[elem
|
|
225
|
+
hash2bbox[hash_] = id2bbox[elem]
|
|
194
226
|
with (_CACHE_DIR / hash_).open("wb") as f:
|
|
195
227
|
pickle.dump(hash2bbox[hash_], f)
|
|
196
228
|
return tuple(hash2bbox[h] for h in elem2hash.values())
|
svg_ultralight/root_elements.py
CHANGED
|
@@ -13,7 +13,9 @@ from svg_ultralight.bounding_boxes.type_bounding_box import BoundingBox
|
|
|
13
13
|
from svg_ultralight.main import new_svg_root
|
|
14
14
|
|
|
15
15
|
if TYPE_CHECKING:
|
|
16
|
-
from lxml.etree import
|
|
16
|
+
from lxml.etree import (
|
|
17
|
+
_Element as EtreeElement, # pyright: ignore[reportPrivateUsage]
|
|
18
|
+
)
|
|
17
19
|
|
|
18
20
|
from svg_ultralight.bounding_boxes.supports_bounds import SupportsBounds
|
|
19
21
|
from svg_ultralight.layout import PadArg
|
|
@@ -22,7 +22,9 @@ from svg_ultralight.nsmap import NSMAP
|
|
|
22
22
|
if TYPE_CHECKING:
|
|
23
23
|
from collections.abc import Iterable
|
|
24
24
|
|
|
25
|
-
from lxml.etree import
|
|
25
|
+
from lxml.etree import (
|
|
26
|
+
_Element as EtreeElement, # pyright: ignore[reportPrivateUsage]
|
|
27
|
+
)
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
def format_number(num: float | str) -> str:
|
|
@@ -120,7 +122,9 @@ def _fix_key_and_format_val(key: str, val: str | float) -> tuple[str, str]:
|
|
|
120
122
|
popular one will be 'class') can be passed with a trailing underscore (e.g.,
|
|
121
123
|
class_='body_text').
|
|
122
124
|
"""
|
|
123
|
-
if ":" in key:
|
|
125
|
+
if "http:" in key or "https:" in key:
|
|
126
|
+
key_ = key
|
|
127
|
+
elif ":" in key:
|
|
124
128
|
namespace, tag = key.split(":")
|
|
125
129
|
key_ = str(etree.QName(NSMAP[namespace], tag))
|
|
126
130
|
else:
|
|
@@ -184,7 +188,7 @@ def svg_tostring(xml: EtreeElement, **tostring_kwargs: str | bool | None) -> byt
|
|
|
184
188
|
value = tostring_kwargs.get(arg_name, default.value)
|
|
185
189
|
tostring_kwargs[arg_name] = value
|
|
186
190
|
as_bytes = etree.tostring(etree.ElementTree(xml), **tostring_kwargs) # type: ignore
|
|
187
|
-
return cast(bytes, as_bytes)
|
|
191
|
+
return cast("bytes", as_bytes)
|
|
188
192
|
|
|
189
193
|
|
|
190
194
|
def get_viewBox_str(
|
|
@@ -13,10 +13,12 @@ from typing import TYPE_CHECKING, cast
|
|
|
13
13
|
from svg_ultralight.string_conversion import format_number
|
|
14
14
|
|
|
15
15
|
if TYPE_CHECKING:
|
|
16
|
-
from lxml.etree import
|
|
16
|
+
from lxml.etree import (
|
|
17
|
+
_Element as EtreeElement, # pyright: ignore[reportPrivateUsage]
|
|
18
|
+
)
|
|
17
19
|
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
RE_MATRIX = re.compile(r"matrix\(([^)]+)\)")
|
|
20
22
|
|
|
21
23
|
_Matrix = tuple[float, float, float, float, float, float]
|
|
22
24
|
|
|
@@ -50,13 +52,19 @@ def mat_dot(mat1: _Matrix, mat2: _Matrix) -> _Matrix:
|
|
|
50
52
|
return (aa, bb, cc, dd, ee, ff)
|
|
51
53
|
|
|
52
54
|
|
|
53
|
-
def mat_apply(
|
|
55
|
+
def mat_apply(matrix: _Matrix, point: tuple[float, float]) -> tuple[float, float]:
|
|
54
56
|
"""Apply an svg-style transformation matrix to a point.
|
|
55
57
|
|
|
56
|
-
:param mat1: transformation matrix (
|
|
58
|
+
:param mat1: transformation matrix (a, b, c, d, e, f) describing a 3x3 matrix
|
|
59
|
+
with an implied third row of (0, 0, 1)
|
|
60
|
+
[[a, c, e], [b, d, f], [0, 0, 1]]
|
|
57
61
|
:param mat2: point (x, y)
|
|
58
62
|
"""
|
|
59
|
-
|
|
63
|
+
a, b, c, d, e, f = matrix
|
|
64
|
+
x, y = point
|
|
65
|
+
result_x = a * x + c * y + e
|
|
66
|
+
result_y = b * x + d * y + f
|
|
67
|
+
return result_x, result_y
|
|
60
68
|
|
|
61
69
|
|
|
62
70
|
def mat_invert(tmat: _Matrix) -> _Matrix:
|
|
@@ -86,7 +94,7 @@ def get_transform_matrix(elem: EtreeElement) -> _Matrix:
|
|
|
86
94
|
return (1, 0, 0, 1, 0, 0)
|
|
87
95
|
values_str = ""
|
|
88
96
|
with suppress(AttributeError):
|
|
89
|
-
values_str = cast(re.Match[str],
|
|
97
|
+
values_str = cast("re.Match[str]", RE_MATRIX.match(transform)).group(1)
|
|
90
98
|
with suppress(ValueError):
|
|
91
99
|
aa, bb, cc, dd, ee, ff = (float(val) for val in values_str.split())
|
|
92
100
|
return (aa, bb, cc, dd, ee, ff)
|
|
@@ -97,7 +105,7 @@ def get_transform_matrix(elem: EtreeElement) -> _Matrix:
|
|
|
97
105
|
def new_transformation_matrix(
|
|
98
106
|
transformation: _Matrix | None = None,
|
|
99
107
|
*,
|
|
100
|
-
scale: float | None = None,
|
|
108
|
+
scale: tuple[float, float] | None = None,
|
|
101
109
|
dx: float | None = None,
|
|
102
110
|
dy: float | None = None,
|
|
103
111
|
) -> _Matrix:
|
|
@@ -107,10 +115,10 @@ def new_transformation_matrix(
|
|
|
107
115
|
svg-style transformation matrix.
|
|
108
116
|
"""
|
|
109
117
|
transformation = transformation or (1, 0, 0, 1, 0, 0)
|
|
110
|
-
scale = scale or 1
|
|
118
|
+
scale = scale or (1, 1)
|
|
111
119
|
dx = dx or 0
|
|
112
120
|
dy = dy or 0
|
|
113
|
-
return mat_dot((scale, 0, 0, scale, dx, dy), transformation)
|
|
121
|
+
return mat_dot((scale[0], 0, 0, scale[1], dx, dy), transformation)
|
|
114
122
|
|
|
115
123
|
|
|
116
124
|
def transform_element(elem: EtreeElement, matrix: _Matrix) -> EtreeElement:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: svg-ultralight
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.39.0
|
|
4
4
|
Summary: a sensible way to create svg files with Python
|
|
5
5
|
Author-email: Shay Hill <shay_public@hotmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -10,6 +10,7 @@ Requires-Dist: lxml
|
|
|
10
10
|
Requires-Dist: pillow
|
|
11
11
|
Requires-Dist: paragraphs
|
|
12
12
|
Requires-Dist: types-lxml
|
|
13
|
+
Requires-Dist: typing-extensions
|
|
13
14
|
Provides-Extra: dev
|
|
14
15
|
Requires-Dist: pytest; extra == "dev"
|
|
15
16
|
Requires-Dist: commitizen; extra == "dev"
|
|
@@ -187,7 +188,7 @@ Another way to add params through the new_element name / float translator. Again
|
|
|
187
188
|
|
|
188
189
|
## Extras:
|
|
189
190
|
|
|
190
|
-
### query.
|
|
191
|
+
### query.map_elems_to_bounding_boxes
|
|
191
192
|
|
|
192
193
|
Python cannot parse an svg file. Python can *create* an svg file, and Inkscape can parse (and inspect) it. Inkscape has a command-line interface capable of reading an svg file and returning some limited information. This is the only way I know for a Python program to:
|
|
193
194
|
|
|
@@ -197,7 +198,7 @@ Python cannot parse an svg file. Python can *create* an svg file, and Inkscape c
|
|
|
197
198
|
|
|
198
199
|
This would be necessary for, e.g., algorithmically fitting text in a box.
|
|
199
200
|
|
|
200
|
-
from svg_ultralight.queries import
|
|
201
|
+
from svg_ultralight.queries import map_elems_to_bounding_boxes
|
|
201
202
|
|
|
202
203
|
You can get a tiny bit more sophisticated with Inkscape bounding-box queries, but not much. This will give you pretty much all you can get out of it.
|
|
203
204
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
svg_ultralight/__init__.py,sha256=wUc79mKsG6lGZ1xaYijyJ4Sm9lG5-5XgRArVsCI0niY,2554
|
|
2
|
+
svg_ultralight/animate.py,sha256=JSrBm-59BcNXDF0cGgl4-C89eBunjevZnwZxIWt48TU,1112
|
|
3
|
+
svg_ultralight/image_ops.py,sha256=PXN_p5GX91UTvhnwwU-bPuj6WzM9wCx1SqfzR5icNnQ,4686
|
|
4
|
+
svg_ultralight/inkscape.py,sha256=tVFPtwsUcGKGODmYhC9IdGLyT7OAeNCVsDN0hPBSSgg,9194
|
|
5
|
+
svg_ultralight/layout.py,sha256=7LV2I3u4EhqSc6ASvgwDtTZyV-Y1qt2wtvRtH2uKVAE,12799
|
|
6
|
+
svg_ultralight/main.py,sha256=VA7tVMO7fiRI_JkEGaH7UFgzJ5YIbHKx4VHfMnT50hI,7446
|
|
7
|
+
svg_ultralight/metadata.py,sha256=xaIfqhKu52Dl4JOrRlpUsWkkE7Umw8j5Z4waFTli-kI,4234
|
|
8
|
+
svg_ultralight/nsmap.py,sha256=y63upO78Rr-JJT56RWWZuyrsILh6HPoY4GhbYnK1A0g,1244
|
|
9
|
+
svg_ultralight/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
svg_ultralight/query.py,sha256=wR8oixRYA489k03RU5apXaoami2KvYl8BKmwypQGTi0,10972
|
|
11
|
+
svg_ultralight/root_elements.py,sha256=E_H7HXk0M5F3IyFVOxO8PQmhww1-sHTzJhx8hBJPZvg,2911
|
|
12
|
+
svg_ultralight/string_conversion.py,sha256=7gaUWEJptAVZawlvoAJ7JoP996nALoJrAByM3o219Tc,7462
|
|
13
|
+
svg_ultralight/transformations.py,sha256=h1GUD4hvo10ugnSwShDmrwzF048yfug7lCWqCzOTxWs,4296
|
|
14
|
+
svg_ultralight/unit_conversion.py,sha256=g07nhzXdjPvGcJmkhLdFbeDLrSmbI8uFoVgPo7G62Bg,9258
|
|
15
|
+
svg_ultralight/bounding_boxes/__init__.py,sha256=qUEn3r4s-1QNHaguhWhhaNfdP4tl_B6YEqxtiTFuzhQ,78
|
|
16
|
+
svg_ultralight/bounding_boxes/bound_helpers.py,sha256=LFkVsdYFKYCnEL6vLvEa_5cfu8D44ZGYeEEb7_0MnC0,7146
|
|
17
|
+
svg_ultralight/bounding_boxes/supports_bounds.py,sha256=Yi696oJ393y29vql0U6kLMR3soSggLB3_wSACHppoJo,4505
|
|
18
|
+
svg_ultralight/bounding_boxes/type_bound_collection.py,sha256=yW-gwehTrLhgG4Rk-wd6XWP0oLj7Yh_Njrudm8Dn1fk,2637
|
|
19
|
+
svg_ultralight/bounding_boxes/type_bound_element.py,sha256=v-XwW1bxA3tT0CzLWOrRO5EHtLA3ivds8DyA5KFju6w,2196
|
|
20
|
+
svg_ultralight/bounding_boxes/type_bounding_box.py,sha256=XsjM6nR5bKRLFa8z1U84GIC-YbleKoXa0s-UScz9Ewo,13621
|
|
21
|
+
svg_ultralight/bounding_boxes/type_padded_text.py,sha256=fiDZoHIaQbGK8ETrPRa2wa5ykbdFBeeDHw9zGqKtD6E,10674
|
|
22
|
+
svg_ultralight/constructors/__init__.py,sha256=XLOInLhzMERWNnFAs-itMs-OZrBOpvQthZJ2T5duqBE,327
|
|
23
|
+
svg_ultralight/constructors/new_element.py,sha256=hRUW2hR_BTkthEqPClYV7-IeFe9iv2zwb6ehp1k1xDk,3475
|
|
24
|
+
svg_ultralight/strings/__init__.py,sha256=BMGhF1pulscIgkiYvZLr6kPRR0L4lW0jUNFxkul4_EM,295
|
|
25
|
+
svg_ultralight/strings/svg_strings.py,sha256=FQNxNmMkR2M-gCFo_woQKXLgCHi3ncUlRMiaRR_a9nQ,1978
|
|
26
|
+
svg_ultralight-0.39.0.dist-info/METADATA,sha256=--QD3_OuduOUZx2fsCx6FsgTaDAuPAFHkkeKxCKY5Dw,8971
|
|
27
|
+
svg_ultralight-0.39.0.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
|
|
28
|
+
svg_ultralight-0.39.0.dist-info/top_level.txt,sha256=se-6yqM_0Yg5orJKvKWdjQZ4iR4G_EjhL7oRgju-fdY,15
|
|
29
|
+
svg_ultralight-0.39.0.dist-info/RECORD,,
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
svg_ultralight/__init__.py,sha256=wUc79mKsG6lGZ1xaYijyJ4Sm9lG5-5XgRArVsCI0niY,2554
|
|
2
|
-
svg_ultralight/animate.py,sha256=JSrBm-59BcNXDF0cGgl4-C89eBunjevZnwZxIWt48TU,1112
|
|
3
|
-
svg_ultralight/image_ops.py,sha256=PXN_p5GX91UTvhnwwU-bPuj6WzM9wCx1SqfzR5icNnQ,4686
|
|
4
|
-
svg_ultralight/inkscape.py,sha256=M8yTxXOu4NlXnhsMycvEJiIDpnDeiZ_bZakJBM38ZoU,9152
|
|
5
|
-
svg_ultralight/layout.py,sha256=FgR45FsHax4xDjGkk9HEVW4OcwhtM8aqw2JUdZs_m7Q,12326
|
|
6
|
-
svg_ultralight/main.py,sha256=6oNkZfD27UMdP-oYqp5agS_IGcYb8NkUZwM9Zdyb3SA,7287
|
|
7
|
-
svg_ultralight/metadata.py,sha256=xR3ObM0QV7OQ90IKvfigR5B6e0JW6GGVGvTlL5NswWI,4211
|
|
8
|
-
svg_ultralight/nsmap.py,sha256=y63upO78Rr-JJT56RWWZuyrsILh6HPoY4GhbYnK1A0g,1244
|
|
9
|
-
svg_ultralight/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
svg_ultralight/query.py,sha256=SufFumN11VTWloqjMpSuQ5eghAYx4ABQRIMXRJGs70o,9428
|
|
11
|
-
svg_ultralight/root_elements.py,sha256=pt9J6mPrnoTAZVF6vKTZoM_o947I8UCj6MbGcD2JUCk,2869
|
|
12
|
-
svg_ultralight/string_conversion.py,sha256=WEmpf75RJmJ2lfJluagAz2wPsz6wM8XvTEwkq4U0vEc,7353
|
|
13
|
-
svg_ultralight/transformations.py,sha256=7-6NNh6xZ45mM_933fMuQfRGpI7q9Qrt5qse9e6FUek,4036
|
|
14
|
-
svg_ultralight/unit_conversion.py,sha256=g07nhzXdjPvGcJmkhLdFbeDLrSmbI8uFoVgPo7G62Bg,9258
|
|
15
|
-
svg_ultralight/bounding_boxes/__init__.py,sha256=qUEn3r4s-1QNHaguhWhhaNfdP4tl_B6YEqxtiTFuzhQ,78
|
|
16
|
-
svg_ultralight/bounding_boxes/bound_helpers.py,sha256=V0BlBHDZ9xksVG5dGLPfcyRwPP3jSj6ODdtIpqT-FcI,7273
|
|
17
|
-
svg_ultralight/bounding_boxes/supports_bounds.py,sha256=fbHV6mGdeIVV3lS15vBKSrHiHKR7DMg4K5X__4LLmCE,4569
|
|
18
|
-
svg_ultralight/bounding_boxes/type_bound_collection.py,sha256=b89TM2UsdaeApyjTQeMbx_FG_WcCiLAImEiHiZ6EWPI,2600
|
|
19
|
-
svg_ultralight/bounding_boxes/type_bound_element.py,sha256=9RdxH8osOlAvPdWR0Ww9NsasHLPYFDs-MbydoV48x4E,2239
|
|
20
|
-
svg_ultralight/bounding_boxes/type_bounding_box.py,sha256=cDrMp6uwaA--KJIQS2puG10qh8n3TBmiscg-cfk1f3w,16149
|
|
21
|
-
svg_ultralight/bounding_boxes/type_padded_text.py,sha256=QA6PfeO_sQYc5pEXuyfyQ3lRUcZAc4B2BthWXpdt3qQ,14848
|
|
22
|
-
svg_ultralight/constructors/__init__.py,sha256=XLOInLhzMERWNnFAs-itMs-OZrBOpvQthZJ2T5duqBE,327
|
|
23
|
-
svg_ultralight/constructors/new_element.py,sha256=8nqmOEgt3j-aOVeRaMLFHqrwKg2Dm5w0AfuK9MP4ak8,3433
|
|
24
|
-
svg_ultralight/strings/__init__.py,sha256=BMGhF1pulscIgkiYvZLr6kPRR0L4lW0jUNFxkul4_EM,295
|
|
25
|
-
svg_ultralight/strings/svg_strings.py,sha256=FQNxNmMkR2M-gCFo_woQKXLgCHi3ncUlRMiaRR_a9nQ,1978
|
|
26
|
-
svg_ultralight-0.37.0.dist-info/METADATA,sha256=wWTDiiOScZrgr_Np0_XCqyJ9WKEAEKHJRXvPU5Qw5-Y,8933
|
|
27
|
-
svg_ultralight-0.37.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
28
|
-
svg_ultralight-0.37.0.dist-info/top_level.txt,sha256=se-6yqM_0Yg5orJKvKWdjQZ4iR4G_EjhL7oRgju-fdY,15
|
|
29
|
-
svg_ultralight-0.37.0.dist-info/RECORD,,
|
|
File without changes
|