svg-ultralight 0.51.0__tar.gz → 0.52.0__tar.gz
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-0.51.0 → svg_ultralight-0.52.0}/PKG-INFO +1 -1
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/pyproject.toml +2 -2
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/bounding_boxes/supports_bounds.py +1 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/bounding_boxes/type_bound_collection.py +6 -3
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/bounding_boxes/type_bound_element.py +5 -2
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/bounding_boxes/type_bounding_box.py +7 -1
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/bounding_boxes/type_padded_text.py +15 -2
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/font_tools/font_info.py +15 -3
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/transformations.py +15 -3
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/README.md +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/__init__.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/animate.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/attrib_hints.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/bounding_boxes/__init__.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/bounding_boxes/bound_helpers.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/bounding_boxes/padded_text_initializers.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/constructors/__init__.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/constructors/new_element.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/font_tools/__init__.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/font_tools/comp_results.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/image_ops.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/inkscape.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/layout.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/main.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/metadata.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/nsmap.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/py.typed +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/query.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/read_svg.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/root_elements.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/string_conversion.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/strings/__init__.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/strings/svg_strings.py +0 -0
- {svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/unit_conversion.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "svg-ultralight"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.52.0"
|
|
4
4
|
description = "a sensible way to create svg files with Python"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -33,7 +33,7 @@ dev = [
|
|
|
33
33
|
|
|
34
34
|
[tool.commitizen]
|
|
35
35
|
name = "cz_conventional_commits"
|
|
36
|
-
version = "0.
|
|
36
|
+
version = "0.52.0"
|
|
37
37
|
tag_format = "$version"
|
|
38
38
|
major-version-zero = true
|
|
39
39
|
version_files = ["pyproject.toml:^version"]
|
|
@@ -47,6 +47,7 @@ class BoundCollection(HasBoundingBox):
|
|
|
47
47
|
scale: tuple[float, float] | float | None = None,
|
|
48
48
|
dx: float | None = None,
|
|
49
49
|
dy: float | None = None,
|
|
50
|
+
reverse: bool = False,
|
|
50
51
|
) -> None:
|
|
51
52
|
"""Transform each bound element in self.blems.
|
|
52
53
|
|
|
@@ -54,9 +55,11 @@ class BoundCollection(HasBoundingBox):
|
|
|
54
55
|
:param scale: optional scale factor
|
|
55
56
|
:param dx: optional x translation
|
|
56
57
|
:param dy: optional y translation
|
|
58
|
+
:param reverse: Transform the element as if it were in a <g> element
|
|
59
|
+
transformed by tmat.
|
|
57
60
|
|
|
58
61
|
Keep track of all compounding transformations in order to have a value for
|
|
59
|
-
self.scale (required for
|
|
62
|
+
self.scale (required for members and to provide access to cumulative
|
|
60
63
|
transforms should this be useful for any reason. This means all
|
|
61
64
|
transformations must be applied to two bounding boxes: a persistant bbox to
|
|
62
65
|
keep track of the scale property and a temporary bbox to isolate each
|
|
@@ -66,6 +69,6 @@ class BoundCollection(HasBoundingBox):
|
|
|
66
69
|
self.bbox.transform(tmat)
|
|
67
70
|
for blem in self.blems:
|
|
68
71
|
if isinstance(blem, EtreeElement):
|
|
69
|
-
_ = transform_element(blem, tmat)
|
|
72
|
+
_ = transform_element(blem, tmat, reverse=reverse)
|
|
70
73
|
else:
|
|
71
|
-
blem.transform(tmat)
|
|
74
|
+
blem.transform(tmat, reverse=reverse)
|
|
@@ -52,6 +52,7 @@ class BoundElement(HasBoundingBox):
|
|
|
52
52
|
scale: tuple[float, float] | float | None = None,
|
|
53
53
|
dx: float | None = None,
|
|
54
54
|
dy: float | None = None,
|
|
55
|
+
reverse: bool = False,
|
|
55
56
|
) -> None:
|
|
56
57
|
"""Transform the element and bounding box.
|
|
57
58
|
|
|
@@ -59,7 +60,9 @@ class BoundElement(HasBoundingBox):
|
|
|
59
60
|
:param scale: a scaling factor
|
|
60
61
|
:param dx: the x translation
|
|
61
62
|
:param dy: the y translation
|
|
63
|
+
:param reverse: Transform the element as if it were in a <g> element
|
|
64
|
+
transformed by tmat.
|
|
62
65
|
"""
|
|
63
66
|
tmat = new_transformation_matrix(transformation, scale=scale, dx=dx, dy=dy)
|
|
64
|
-
self.bbox.transform(tmat)
|
|
65
|
-
_ = transform_element(self.elem, tmat)
|
|
67
|
+
self.bbox.transform(tmat, reverse=reverse)
|
|
68
|
+
_ = transform_element(self.elem, tmat, reverse=reverse)
|
|
@@ -78,6 +78,7 @@ class HasBoundingBox(SupportsBounds):
|
|
|
78
78
|
scale: tuple[float, float] | float | None = None,
|
|
79
79
|
dx: float | None = None,
|
|
80
80
|
dy: float | None = None,
|
|
81
|
+
reverse: bool = False,
|
|
81
82
|
) -> None:
|
|
82
83
|
"""Transform the bounding box by updating the transformation attribute.
|
|
83
84
|
|
|
@@ -85,6 +86,8 @@ class HasBoundingBox(SupportsBounds):
|
|
|
85
86
|
:param scale: scale factor
|
|
86
87
|
:param dx: x translation
|
|
87
88
|
:param dy: y translation
|
|
89
|
+
:param reverse: Transform the element as if it were in a <g> element
|
|
90
|
+
transformed by tmat.
|
|
88
91
|
|
|
89
92
|
All parameters are optional. Scale, dx, and dy are optional and applied after
|
|
90
93
|
the transformation matrix if both are given. This shouldn't be necessary in
|
|
@@ -94,7 +97,10 @@ class HasBoundingBox(SupportsBounds):
|
|
|
94
97
|
when applying a transformation from another bounding box instance.
|
|
95
98
|
"""
|
|
96
99
|
tmat = new_transformation_matrix(transformation, scale=scale, dx=dx, dy=dy)
|
|
97
|
-
|
|
100
|
+
if reverse:
|
|
101
|
+
self.bbox.transformation = mat_dot(self.bbox.transformation, tmat)
|
|
102
|
+
else:
|
|
103
|
+
self.bbox.transformation = mat_dot(tmat, self.bbox.transformation)
|
|
98
104
|
|
|
99
105
|
@property
|
|
100
106
|
def scale(self) -> tuple[float, float]:
|
|
@@ -119,6 +119,16 @@ class PaddedText(BoundElement):
|
|
|
119
119
|
self.lpad = lpad
|
|
120
120
|
self._line_gap = line_gap
|
|
121
121
|
|
|
122
|
+
@property
|
|
123
|
+
def tbox(self) -> BoundingBox:
|
|
124
|
+
"""Return the unpadded BoundingBox around the text element.
|
|
125
|
+
|
|
126
|
+
Tight bbox or True bbox. An alias for unpadded_bbox.
|
|
127
|
+
|
|
128
|
+
:return: The unpadded BoundingBox around the text element.
|
|
129
|
+
"""
|
|
130
|
+
return self.unpadded_bbox
|
|
131
|
+
|
|
122
132
|
@property
|
|
123
133
|
def bbox(self) -> BoundingBox:
|
|
124
134
|
"""Return a BoundingBox around the margins and cap/baseline.
|
|
@@ -154,6 +164,7 @@ class PaddedText(BoundElement):
|
|
|
154
164
|
scale: tuple[float, float] | float | None = None,
|
|
155
165
|
dx: float | None = None,
|
|
156
166
|
dy: float | None = None,
|
|
167
|
+
reverse: bool = False,
|
|
157
168
|
) -> None:
|
|
158
169
|
"""Transform the element and bounding box.
|
|
159
170
|
|
|
@@ -161,10 +172,12 @@ class PaddedText(BoundElement):
|
|
|
161
172
|
:param scale: a scaling factor
|
|
162
173
|
:param dx: the x translation
|
|
163
174
|
:param dy: the y translation
|
|
175
|
+
:param reverse: Transform the element as if it were in a <g> element
|
|
176
|
+
transformed by tmat.
|
|
164
177
|
"""
|
|
165
178
|
tmat = new_transformation_matrix(transformation, scale=scale, dx=dx, dy=dy)
|
|
166
|
-
self.unpadded_bbox.transform(tmat)
|
|
167
|
-
_ = transform_element(self.elem, tmat)
|
|
179
|
+
self.unpadded_bbox.transform(tmat, reverse=reverse)
|
|
180
|
+
_ = transform_element(self.elem, tmat, reverse=reverse)
|
|
168
181
|
|
|
169
182
|
@property
|
|
170
183
|
def line_gap(self) -> float:
|
|
@@ -425,7 +425,13 @@ class FTFontInfo:
|
|
|
425
425
|
coordinates (+y is down).
|
|
426
426
|
"""
|
|
427
427
|
min_x, min_y, max_x, max_y = self.get_char_bounds(char)
|
|
428
|
-
return BoundingBox(
|
|
428
|
+
return BoundingBox(
|
|
429
|
+
min_x,
|
|
430
|
+
min_y,
|
|
431
|
+
max_x - min_x,
|
|
432
|
+
max_y - min_y,
|
|
433
|
+
transformation=(1, 0, 0, -1, 0, 0),
|
|
434
|
+
)
|
|
429
435
|
|
|
430
436
|
def get_text_bounds(self, text: str) -> tuple[int, int, int, int]:
|
|
431
437
|
"""Return bounds of a string as xmin, ymin, xmax, ymax.
|
|
@@ -484,7 +490,13 @@ class FTFontInfo:
|
|
|
484
490
|
coordinates (+y is down).
|
|
485
491
|
"""
|
|
486
492
|
min_x, min_y, max_x, max_y = self.get_text_bounds(text)
|
|
487
|
-
return BoundingBox(
|
|
493
|
+
return BoundingBox(
|
|
494
|
+
min_x,
|
|
495
|
+
min_y,
|
|
496
|
+
max_x - min_x,
|
|
497
|
+
max_y - min_y,
|
|
498
|
+
transformation=(1, 0, 0, -1, 0, 0),
|
|
499
|
+
)
|
|
488
500
|
|
|
489
501
|
def get_lsb(self, char: str) -> float:
|
|
490
502
|
"""Return the left side bearing of a character."""
|
|
@@ -567,7 +579,7 @@ class FTTextInfo:
|
|
|
567
579
|
"""
|
|
568
580
|
bbox = self.font.get_text_bbox(self.text)
|
|
569
581
|
bbox.transform(scale=self.scale)
|
|
570
|
-
return
|
|
582
|
+
return bbox
|
|
571
583
|
|
|
572
584
|
@property
|
|
573
585
|
def ascent(self) -> float:
|
|
@@ -129,12 +129,24 @@ def new_transformation_matrix(
|
|
|
129
129
|
return mat_dot((float(scale_x), 0, 0, float(scale_y), dx, dy), transformation)
|
|
130
130
|
|
|
131
131
|
|
|
132
|
-
def transform_element(
|
|
132
|
+
def transform_element(
|
|
133
|
+
elem: EtreeElement, matrix: _Matrix, *, reverse: bool = False
|
|
134
|
+
) -> EtreeElement:
|
|
133
135
|
"""Apply a transformation matrix to an svg element.
|
|
134
136
|
|
|
135
137
|
:param elem: svg element
|
|
136
|
-
:
|
|
138
|
+
:par m matrix: transformation matrix
|
|
139
|
+
|
|
140
|
+
:param reverse: If you have a transformation matrix, A, and wish to apply an
|
|
141
|
+
additional transform, B, the result is B @ A. This is how an element can be
|
|
142
|
+
cumulatively transformed in svg.
|
|
143
|
+
|
|
144
|
+
If the element is transformed by A and is a part of a GROUP transformed by B,
|
|
145
|
+
then the result is the reverse: A @ B.
|
|
137
146
|
"""
|
|
138
147
|
current = get_transform_matrix(elem)
|
|
139
|
-
|
|
148
|
+
if reverse:
|
|
149
|
+
elem.attrib["transform"] = svg_matrix(mat_dot(current, matrix))
|
|
150
|
+
else:
|
|
151
|
+
elem.attrib["transform"] = svg_matrix(mat_dot(matrix, current))
|
|
140
152
|
return elem
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/bounding_boxes/__init__.py
RENAMED
|
File without changes
|
{svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/bounding_boxes/bound_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/constructors/new_element.py
RENAMED
|
File without changes
|
|
File without changes
|
{svg_ultralight-0.51.0 → svg_ultralight-0.52.0}/src/svg_ultralight/font_tools/comp_results.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|