svg-ultralight 0.46.0__tar.gz → 0.48.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.

Files changed (62) hide show
  1. {svg_ultralight-0.46.0/src/svg_ultralight.egg-info → svg_ultralight-0.48.0}/PKG-INFO +2 -2
  2. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/pyproject.toml +3 -3
  3. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/bounding_boxes/bound_helpers.py +3 -15
  4. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/bounding_boxes/padded_text_initializers.py +13 -4
  5. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/font_tools/font_info.py +14 -7
  6. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0/src/svg_ultralight.egg-info}/PKG-INFO +2 -2
  7. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight.egg-info/SOURCES.txt +0 -1
  8. svg_ultralight-0.46.0/src/svg_ultralight/font_tools/globs.py +0 -7
  9. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/.gitignore +0 -0
  10. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/.pre-commit-config.yaml +0 -0
  11. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/README.md +0 -0
  12. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/dev-requirements.txt +0 -0
  13. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/experiments/encode_fonts3.txt +0 -0
  14. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/experiments/font_css.py +0 -0
  15. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/setup.cfg +0 -0
  16. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/__init__.py +0 -0
  17. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/animate.py +0 -0
  18. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/attrib_hints.py +0 -0
  19. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/bounding_boxes/__init__.py +0 -0
  20. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/bounding_boxes/supports_bounds.py +0 -0
  21. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/bounding_boxes/type_bound_collection.py +0 -0
  22. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/bounding_boxes/type_bound_element.py +0 -0
  23. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/bounding_boxes/type_bounding_box.py +0 -0
  24. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/bounding_boxes/type_padded_text.py +0 -0
  25. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/constructors/__init__.py +0 -0
  26. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/constructors/new_element.py +0 -0
  27. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/font_tools/__init__.py +0 -0
  28. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/font_tools/comp_results.py +0 -0
  29. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/image_ops.py +0 -0
  30. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/inkscape.py +0 -0
  31. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/layout.py +0 -0
  32. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/main.py +0 -0
  33. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/metadata.py +0 -0
  34. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/nsmap.py +0 -0
  35. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/py.typed +0 -0
  36. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/query.py +0 -0
  37. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/root_elements.py +0 -0
  38. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/string_conversion.py +0 -0
  39. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/strings/__init__.py +0 -0
  40. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/strings/svg_strings.py +0 -0
  41. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/transformations.py +0 -0
  42. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight/unit_conversion.py +0 -0
  43. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight.egg-info/dependency_links.txt +0 -0
  44. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight.egg-info/requires.txt +0 -0
  45. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/src/svg_ultralight.egg-info/top_level.txt +0 -0
  46. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/__init__.py +0 -0
  47. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/conftest.py +0 -0
  48. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/resources/arrow.svg +0 -0
  49. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/test_bound_element.py +0 -0
  50. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/test_bounding.py +0 -0
  51. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/test_inkscape.py +0 -0
  52. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/test_layout.py +0 -0
  53. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/test_matrices.py +0 -0
  54. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/test_metadata.py +0 -0
  55. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/test_new_element.py +0 -0
  56. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/test_padded_text_initializers.py +0 -0
  57. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/test_padding.py +0 -0
  58. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/test_queries.py +0 -0
  59. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/test_root_elements.py +0 -0
  60. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/test_string_conversion.py +0 -0
  61. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tests/test_svg_ultralight.py +0 -0
  62. {svg_ultralight-0.46.0 → svg_ultralight-0.48.0}/tox.ini +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: svg-ultralight
3
- Version: 0.46.0
3
+ Version: 0.48.0
4
4
  Summary: a sensible way to create svg files with Python
5
5
  Author-email: Shay Hill <shay_public@hotmail.com>
6
- License: MIT
6
+ License-Expression: MIT
7
7
  Requires-Python: >=3.9
8
8
  Description-Content-Type: text/markdown
9
9
  Requires-Dist: cssutils
@@ -1,9 +1,9 @@
1
1
  [project]
2
2
  name = "svg-ultralight"
3
- version = "0.46.0"
3
+ version = "0.48.0"
4
4
  description = "a sensible way to create svg files with Python"
5
5
  authors = [{ name = "Shay Hill", email = "shay_public@hotmail.com" }]
6
- license = { text = "MIT" }
6
+ license = "MIT"
7
7
  readme = "README.md"
8
8
  requires-python = ">=3.9"
9
9
  dependencies = [
@@ -53,7 +53,7 @@ convention = "pep257"
53
53
 
54
54
  [tool.commitizen]
55
55
  name = "cz_conventional_commits"
56
- version = "0.46.0"
56
+ version = "0.48.0"
57
57
  tag_format = "$version"
58
58
  version_files = ["pyproject.toml:^version"]
59
59
  annotated_tag = true
@@ -16,6 +16,7 @@ from svg_ultralight.bounding_boxes.type_bound_element import BoundElement
16
16
  from svg_ultralight.bounding_boxes.type_bounding_box import BoundingBox, HasBoundingBox
17
17
  from svg_ultralight.bounding_boxes.type_padded_text import PaddedText
18
18
  from svg_ultralight.constructors import new_element
19
+ from svg_ultralight.layout import PadArg, expand_pad_arg
19
20
 
20
21
  if TYPE_CHECKING:
21
22
  import os
@@ -94,19 +95,6 @@ def new_bound_union(*blems: SupportsBounds | EtreeElement) -> BoundElement:
94
95
  return BoundElement(group, bbox)
95
96
 
96
97
 
97
- def _expand_pad(pad: float | tuple[float, ...]) -> tuple[float, float, float, float]:
98
- """Expand a float pad argument into a 4-tuple."""
99
- if isinstance(pad, (int, float)):
100
- return pad, pad, pad, pad
101
- if len(pad) == 1:
102
- return pad[0], pad[0], pad[0], pad[0]
103
- if len(pad) == 2:
104
- return pad[0], pad[1], pad[0], pad[1]
105
- if len(pad) == 3:
106
- return pad[0], pad[1], pad[2], pad[1]
107
- return pad[0], pad[1], pad[2], pad[3]
108
-
109
-
110
98
  def cut_bbox(
111
99
  bbox: SupportsBounds,
112
100
  *,
@@ -133,7 +121,7 @@ def cut_bbox(
133
121
  return BoundingBox(x, y, width, height)
134
122
 
135
123
 
136
- def pad_bbox(bbox: SupportsBounds, pad: float | tuple[float, ...]) -> BoundingBox:
124
+ def pad_bbox(bbox: SupportsBounds, pad: PadArg) -> BoundingBox:
137
125
  """Return a new bounding box with padding.
138
126
 
139
127
  :param bbox: the original bounding box or bounded element.
@@ -146,7 +134,7 @@ def pad_bbox(bbox: SupportsBounds, pad: float | tuple[float, ...]) -> BoundingBo
146
134
  len = 4 : 0, 1, 2, 3
147
135
  :return: a new bounding box with padding applied.
148
136
  """
149
- top, right, bottom, left = _expand_pad(pad)
137
+ top, right, bottom, left = expand_pad_arg(pad)
150
138
  return cut_bbox(
151
139
  bbox, x=bbox.x - left, y=bbox.y - top, x2=bbox.x2 + right, y2=bbox.y2 + bottom
152
140
  )
@@ -10,6 +10,12 @@ Three variants:
10
10
  line_gap while correcting some of the layout differences between fontTools and
11
11
  Inkscape.
12
12
 
13
+ There is a default font size for pad_text if an element is passed. There is also a
14
+ default for the other pad_text_ functions, but it taken from the font file and is
15
+ usually 1024, so it won't be easy to miss. The default for standard pad_text is to
16
+ prevent surprises if Inksape defaults to font-size 12pt while your browser defaults
17
+ to 16px.
18
+
13
19
  :author: Shay Hill
14
20
  :created: 2025-06-09
15
21
  """
@@ -25,7 +31,6 @@ from svg_ultralight.font_tools.font_info import (
25
31
  get_padded_text_info,
26
32
  get_svg_font_attributes,
27
33
  )
28
- from svg_ultralight.font_tools.globs import DEFAULT_FONT_SIZE
29
34
  from svg_ultralight.query import get_bounding_boxes
30
35
  from svg_ultralight.string_conversion import format_attr_dict, format_number
31
36
 
@@ -40,6 +45,10 @@ if TYPE_CHECKING:
40
45
 
41
46
  DEFAULT_Y_BOUNDS_REFERENCE = "{[|gjpqyf"
42
47
 
48
+ # A default font size for pad_text if font-size is not specified in the reference
49
+ # element.
50
+ DEFAULT_FONT_SIZE_FOR_PAD_TEXT = 12.0 # Default font size for pad_text if not specified
51
+
43
52
 
44
53
  def pad_text(
45
54
  inkscape: str | os.PathLike[str],
@@ -72,7 +81,7 @@ def pad_text(
72
81
  if font is not None:
73
82
  _ = update_element(text_elem, **get_svg_font_attributes(font))
74
83
  if "font-size" not in text_elem.attrib:
75
- text_elem.attrib["font-size"] = format_number(DEFAULT_FONT_SIZE)
84
+ text_elem.attrib["font-size"] = format_number(DEFAULT_FONT_SIZE_FOR_PAD_TEXT)
76
85
  rmargin_ref = deepcopy(text_elem)
77
86
  capline_ref = deepcopy(text_elem)
78
87
  _ = rmargin_ref.attrib.pop("id", None)
@@ -93,7 +102,7 @@ def pad_text(
93
102
  def pad_text_ft(
94
103
  font: str | os.PathLike[str],
95
104
  text: str,
96
- font_size: float = DEFAULT_FONT_SIZE,
105
+ font_size: float | None = None,
97
106
  ascent: float | None = None,
98
107
  descent: float | None = None,
99
108
  *,
@@ -144,7 +153,7 @@ def pad_text_mix(
144
153
  inkscape: str | os.PathLike[str],
145
154
  font: str | os.PathLike[str],
146
155
  text: str,
147
- font_size: float = DEFAULT_FONT_SIZE,
156
+ font_size: float | None = None,
148
157
  ascent: float | None = None,
149
158
  descent: float | None = None,
150
159
  *,
@@ -110,7 +110,6 @@ from svg_path_data import format_svgd_shortest, get_cpts_from_svgd, get_svgd_fro
110
110
 
111
111
  from svg_ultralight.bounding_boxes.type_bounding_box import BoundingBox
112
112
  from svg_ultralight.constructors.new_element import new_element
113
- from svg_ultralight.font_tools.globs import DEFAULT_FONT_SIZE
114
113
  from svg_ultralight.string_conversion import format_numbers
115
114
 
116
115
  if TYPE_CHECKING:
@@ -124,7 +123,15 @@ if TYPE_CHECKING:
124
123
  logging.getLogger("fontTools").setLevel(logging.ERROR)
125
124
 
126
125
 
127
- _ESCAPE_CHARS = {"&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&apos;"}
126
+ _ESCAPE_CHARS = {
127
+ "&": "&amp;",
128
+ "<": "&lt;",
129
+ ">": "&gt;",
130
+ '"': "&quot;",
131
+ "'": "&apos;",
132
+ "{": "&#123", # valid, but stops MS File Explorer from thumbnailing an svg
133
+ "}": "&#125", # valid, but stops MS File Explorer from thumbnailing an svg
134
+ }
128
135
 
129
136
 
130
137
  def _sanitize_svg_data_text(text: str) -> str:
@@ -377,8 +384,8 @@ class FTFontInfo:
377
384
  :param dx: An optional x translation to apply to the glyph.
378
385
  :return: The svg path data for the character.
379
386
  """
387
+ glyph_name = self.get_glyph_name(char)
380
388
  glyph_set = self.font.getGlyphSet()
381
- glyph_name = self.font.getBestCmap().get(ord(char))
382
389
  path_pen = PathPen(glyph_set)
383
390
  _ = glyph_set[glyph_name].draw(path_pen)
384
391
  svgd = path_pen.svgd
@@ -398,8 +405,8 @@ class FTFontInfo:
398
405
  same, but when they disagree, this method is more accurate. Additionally,
399
406
  some fonts do not have a glyf table, so this method is more robust.
400
407
  """
408
+ glyph_name = self.get_glyph_name(char)
401
409
  glyph_set = self.font.getGlyphSet()
402
- glyph_name = self.font.getBestCmap().get(ord(char))
403
410
  bounds_pen = BoundsPen(glyph_set)
404
411
  _ = glyph_set[glyph_name].draw(bounds_pen)
405
412
  pen_bounds = cast("None | tuple[int, int, int, int]", bounds_pen.bounds)
@@ -499,7 +506,7 @@ class FTTextInfo:
499
506
  self,
500
507
  font: str | os.PathLike[str] | FTFontInfo,
501
508
  text: str,
502
- font_size: float,
509
+ font_size: float | None = None,
503
510
  ascent: float | None = None,
504
511
  descent: float | None = None,
505
512
  ) -> None:
@@ -509,7 +516,7 @@ class FTTextInfo:
509
516
  else:
510
517
  self._font = FTFontInfo(font)
511
518
  self._text = text.rstrip(" ")
512
- self._font_size = font_size
519
+ self._font_size = font_size or self._font.units_per_em
513
520
  self._ascent = ascent
514
521
  self._descent = descent
515
522
 
@@ -638,7 +645,7 @@ def get_font_size_given_height(font: str | os.PathLike[str], height: float) -> f
638
645
  def get_padded_text_info(
639
646
  font: str | os.PathLike[str],
640
647
  text: str,
641
- font_size: float = DEFAULT_FONT_SIZE,
648
+ font_size: float | None = None,
642
649
  ascent: float | None = None,
643
650
  descent: float | None = None,
644
651
  *,
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: svg-ultralight
3
- Version: 0.46.0
3
+ Version: 0.48.0
4
4
  Summary: a sensible way to create svg files with Python
5
5
  Author-email: Shay Hill <shay_public@hotmail.com>
6
- License: MIT
6
+ License-Expression: MIT
7
7
  Requires-Python: >=3.9
8
8
  Description-Content-Type: text/markdown
9
9
  Requires-Dist: cssutils
@@ -39,7 +39,6 @@ src/svg_ultralight/constructors/new_element.py
39
39
  src/svg_ultralight/font_tools/__init__.py
40
40
  src/svg_ultralight/font_tools/comp_results.py
41
41
  src/svg_ultralight/font_tools/font_info.py
42
- src/svg_ultralight/font_tools/globs.py
43
42
  src/svg_ultralight/strings/__init__.py
44
43
  src/svg_ultralight/strings/svg_strings.py
45
44
  tests/__init__.py
@@ -1,7 +0,0 @@
1
- """Global values for working with fonts.
2
-
3
- :author: Shay Hill
4
- :created: 2025-06-09
5
- """
6
-
7
- DEFAULT_FONT_SIZE = 12.0
File without changes