svg-ultralight 0.64.0__py3-none-any.whl → 0.73.1__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.
@@ -12,6 +12,7 @@ import math
12
12
  from svg_ultralight.bounding_boxes.supports_bounds import SupportsBounds
13
13
  from svg_ultralight.strings import svg_matrix
14
14
  from svg_ultralight.transformations import mat_apply, mat_dot, new_transformation_matrix
15
+ from svg_ultralight.unit_conversion import MeasurementArg, to_user_units
15
16
 
16
17
  _Matrix = tuple[float, float, float, float, float, float]
17
18
 
@@ -39,7 +40,7 @@ class HasBoundingBox(SupportsBounds):
39
40
  y = self.bbox.base_y
40
41
  x2 = x + self.bbox.base_width
41
42
  y2 = y + self.bbox.base_height
42
- return (x, y), (x2, y), (x2, y2), (x, y2)
43
+ return (x, y), (x, y2), (x2, y2), (x2, y)
43
44
 
44
45
  def values(self) -> tuple[float, float, float, float]:
45
46
  """Get the values of the bounding box.
@@ -65,12 +66,28 @@ class HasBoundingBox(SupportsBounds):
65
66
 
66
67
  :return: four corners counter-clockwise starting at top left, transformed by
67
68
  self.transformation
69
+
70
+ These quadrilateral defined by these corners may not be axis aligned. This is
71
+ purely for determining the bounds of the transformed box.
68
72
  """
69
73
  c0, c1, c2, c3 = (
70
74
  mat_apply(self.bbox.transformation, c) for c in self._get_input_corners()
71
75
  )
72
76
  return c0, c1, c2, c3
73
77
 
78
+ @property
79
+ def corners(
80
+ self,
81
+ ) -> tuple[
82
+ tuple[float, float],
83
+ tuple[float, float],
84
+ tuple[float, float],
85
+ tuple[float, float],
86
+ ]:
87
+ """Get the corners of the bbox in the current state. CW from top left."""
88
+ x, y, x2, y2 = self.x, self.y, self.x2, self.y2
89
+ return ((x, y), (x, y2), (x2, y2), (x2, y))
90
+
74
91
  def transform(
75
92
  self,
76
93
  transformation: _Matrix | None = None,
@@ -106,7 +123,7 @@ class HasBoundingBox(SupportsBounds):
106
123
  def scale(self) -> tuple[float, float]:
107
124
  """Get scale of the bounding box.
108
125
 
109
- :return: uniform scale of the bounding box
126
+ :return: x and y scale of the bounding box
110
127
 
111
128
  Use caution, the scale attribute can cause errors in intuition. Changing
112
129
  width or height will change the scale attribute, but not the x or y values.
@@ -301,13 +318,13 @@ class BoundingBox(HasBoundingBox):
301
318
  :param transformation: transformation matrix
302
319
 
303
320
  Functions that return a bounding box will return a BoundingBox instance. This
304
- instance can be transformed (uniform scale and translate only). Transformations
305
- will be combined and scored to be passed to new_element as a transform value.
321
+ instance can be transformed. Transformations will be combined and stored to be
322
+ passed to new_element as a transform value.
306
323
 
307
324
  Define the bbox with x=, y=, width=, height=
308
325
 
309
326
  Transform the BoundingBox by setting these variables. Each time you set x, cx,
310
- x2, y, cy, y2, width, or height, private transformation value transformation
327
+ x2, y, cy, y2, width, or height, private transformation value `transformation`
311
328
  will be updated.
312
329
 
313
330
  The ultimate transformation can be accessed through ``.transform_string``.
@@ -316,7 +333,7 @@ class BoundingBox(HasBoundingBox):
316
333
  1. Get the bounding box of an svg element
317
334
  2. Update the bounding box x, y, width, and height
318
335
  3. Transform the original svg element with
319
- update_element(elem, transform=bbox.transform_string)
336
+ svg_ultralight.transform_element(elem, bbox.transformation)
320
337
  4. The transformed element will lie in the transformed BoundingBox
321
338
 
322
339
  In addition to x, y, width, and height, x2 and y2 can be set to establish the
@@ -352,10 +369,10 @@ class BoundingBox(HasBoundingBox):
352
369
 
353
370
  def __init__(
354
371
  self,
355
- x: float,
356
- y: float,
357
- width: float,
358
- height: float,
372
+ x: MeasurementArg,
373
+ y: MeasurementArg,
374
+ width: MeasurementArg,
375
+ height: MeasurementArg,
359
376
  transformation: _Matrix = (1, 0, 0, 1, 0, 0),
360
377
  ) -> None:
361
378
  """Initialize a BoundingBox instance.
@@ -365,10 +382,10 @@ class BoundingBox(HasBoundingBox):
365
382
  :param width: width of the bounding box
366
383
  :param height: height of the bounding box
367
384
  """
368
- self.base_x = x
369
- self.base_y = y
370
- self.base_width = width
371
- self.base_height = height
385
+ self.base_x = to_user_units(x)
386
+ self.base_y = to_user_units(y)
387
+ self.base_width = to_user_units(width)
388
+ self.base_height = to_user_units(height)
372
389
  self.transformation = transformation
373
390
  self.bbox = self
374
391
 
@@ -32,7 +32,7 @@ from svg_ultralight.attrib_hints import ElemAttrib
32
32
  from svg_ultralight.bounding_boxes.bound_helpers import new_bound_union
33
33
  from svg_ultralight.bounding_boxes.type_bound_element import BoundElement
34
34
  from svg_ultralight.bounding_boxes.type_bounding_box import BoundingBox
35
- from svg_ultralight.bounding_boxes.type_padded_text import PaddedText
35
+ from svg_ultralight.bounding_boxes.type_padded_text import PaddedText, new_padded_union
36
36
  from svg_ultralight.constructors import update_element
37
37
  from svg_ultralight.transformations import new_transformation_matrix
38
38
 
@@ -123,12 +123,7 @@ class PaddedList:
123
123
 
124
124
  def padded_union(self, **attribs: ElemAttrib) -> PaddedText:
125
125
  """Return a PaddedText inst where the elem is a `g` of all the padded text."""
126
- union = self.tunion(**attribs)
127
- tpad = self.tbox.y - self.bbox.y
128
- rpad = self.bbox.x2 - self.tbox.x2
129
- bpad = self.bbox.y2 - self.tbox.y2
130
- lpad = self.tbox.x - self.bbox.x
131
- return PaddedText(union.elem, union.bbox, tpad, rpad, bpad, lpad)
126
+ return new_padded_union(*self.plems, **attribs)
132
127
 
133
128
  def get_dim(self, dim: str) -> float:
134
129
  """Get a dimension from bbox or tbox."""
@@ -51,35 +51,77 @@ PaddedText instances with sensible defaults.
51
51
 
52
52
  from __future__ import annotations
53
53
 
54
+ import dataclasses
54
55
  import math
55
56
  from typing import TYPE_CHECKING
56
57
 
57
- from paragraphs import par
58
-
59
58
  from svg_ultralight.bounding_boxes.type_bound_element import BoundElement
60
59
  from svg_ultralight.bounding_boxes.type_bounding_box import BoundingBox
61
- from svg_ultralight.transformations import new_transformation_matrix, transform_element
60
+ from svg_ultralight.constructors.new_element import new_element_union
61
+ from svg_ultralight.transformations import (
62
+ mat_apply,
63
+ new_transformation_matrix,
64
+ transform_element,
65
+ )
62
66
 
63
67
  if TYPE_CHECKING:
64
68
  from lxml.etree import (
65
69
  _Element as EtreeElement, # pyright: ignore[reportPrivateUsage]
66
70
  )
67
71
 
72
+ from svg_ultralight.attrib_hints import ElemAttrib
73
+
68
74
  _Matrix = tuple[float, float, float, float, float, float]
69
75
 
70
- _no_line_gap_msg = par(
71
- """No line_gap defined. Line gap is an inherent font attribute defined within a
72
- font file. If this PaddedText instance was created with `pad_text` from reference
73
- elements, a line_gap was not defined. Reading line_gap from the font file
74
- requires creating a PaddedText instance with `pad_text_ft` or `pad_text_mixed`.
75
- You can set an arbitrary line_gap after init with `instance.line_gap = value`."""
76
- )
77
76
 
78
- _no_font_size_msg = par(
79
- """No font_size defined. Font size is an inherent font attribute defined within a
80
- font file or an argument passed to `pad_text`. Any instance created with a padded
81
- text initializer should have this property."""
82
- )
77
+ @dataclasses.dataclass
78
+ class FontMetrics:
79
+ """Font metrics."""
80
+
81
+ _font_size: float
82
+ _ascent: float
83
+ _descent: float
84
+ _cap_height: float
85
+ _x_height: float
86
+ _line_gap: float
87
+ _scalar: float = dataclasses.field(default=1.0, init=False)
88
+
89
+ def scale(self, scalar: float) -> None:
90
+ """Scale the font metrics by a scalar.
91
+
92
+ :param scalar: The scaling factor.
93
+ """
94
+ self._scalar *= scalar
95
+
96
+ @property
97
+ def font_size(self) -> float:
98
+ """The font size."""
99
+ return self._font_size * self._scalar
100
+
101
+ @property
102
+ def ascent(self) -> float:
103
+ """Return the ascent."""
104
+ return self._ascent * self._scalar
105
+
106
+ @property
107
+ def descent(self) -> float:
108
+ """Return the descent."""
109
+ return self._descent * self._scalar
110
+
111
+ @property
112
+ def cap_height(self) -> float:
113
+ """Return the cap height."""
114
+ return self._cap_height * self._scalar
115
+
116
+ @property
117
+ def x_height(self) -> float:
118
+ """Return the x height."""
119
+ return self._x_height * self._scalar
120
+
121
+ @property
122
+ def line_gap(self) -> float:
123
+ """Return the line gap."""
124
+ return self._line_gap * self._scalar
83
125
 
84
126
 
85
127
  class PaddedText(BoundElement):
@@ -93,8 +135,7 @@ class PaddedText(BoundElement):
93
135
  rpad: float,
94
136
  bpad: float,
95
137
  lpad: float,
96
- line_gap: float | None = None,
97
- font_size: float | None = None,
138
+ metrics: FontMetrics | None = None,
98
139
  ) -> None:
99
140
  """Initialize a PaddedText instance.
100
141
 
@@ -113,8 +154,26 @@ class PaddedText(BoundElement):
113
154
  self.rpad = rpad
114
155
  self.base_bpad = bpad
115
156
  self.lpad = lpad
116
- self._line_gap = line_gap
117
- self._font_size = font_size
157
+ self._metrics = metrics
158
+
159
+ @property
160
+ def metrics(self) -> FontMetrics:
161
+ """The font metrics for this PaddedText.
162
+
163
+ :return: The font metrics for this PaddedText.
164
+ """
165
+ if self._metrics is None:
166
+ msg = "No font metrics defined for this PaddedText."
167
+ raise AttributeError(msg)
168
+ return self._metrics
169
+
170
+ @metrics.setter
171
+ def metrics(self, value: FontMetrics) -> None:
172
+ """Set the font metrics for this PaddedText.
173
+
174
+ :param value: The new font metrics.
175
+ """
176
+ self._metrics = value
118
177
 
119
178
  @property
120
179
  def tbox(self) -> BoundingBox:
@@ -181,17 +240,14 @@ class PaddedText(BoundElement):
181
240
  transformed by tmat.
182
241
  """
183
242
  tmat = new_transformation_matrix(transformation, scale=scale, dx=dx, dy=dy)
184
- self.unpadded_bbox.transform(tmat, reverse=reverse)
243
+ self.tbox.transform(tmat, reverse=reverse)
185
244
  _ = transform_element(self.elem, tmat, reverse=reverse)
186
245
  x_norm = pow(tmat[0] ** 2 + tmat[1] ** 2, 1 / 2)
187
246
  self.lpad *= x_norm
188
247
  self.rpad *= x_norm
189
- if self._line_gap or self._font_size:
248
+ if self._metrics:
190
249
  y_norm = pow(tmat[2] ** 2 + tmat[3] ** 2, 1 / 2)
191
- if self._line_gap:
192
- self._line_gap *= y_norm
193
- if self._font_size:
194
- self._font_size *= y_norm
250
+ self._metrics.scale(y_norm)
195
251
 
196
252
  def transform_preserve_sidebearings(
197
253
  self,
@@ -222,22 +278,152 @@ class PaddedText(BoundElement):
222
278
  self.y2 = y2
223
279
 
224
280
  @property
225
- def line_gap(self) -> float:
226
- """The line gap between this line of text and the next.
281
+ def tx(self) -> float:
282
+ """The x value of the tight element bounding box.
283
+
284
+ :return: The x value of the tight element bounding box.
285
+ """
286
+ return self.tbox.x
287
+
288
+ @tx.setter
289
+ def tx(self, value: float) -> None:
290
+ """Set the x value of the tight element bounding box.
291
+
292
+ :param value: The new x value of the tight element bounding box.
293
+ """
294
+ self.transform(dx=value - self.tbox.x)
295
+
296
+ @property
297
+ def tx2(self) -> float:
298
+ """The x2 value of the tight element bounding box.
299
+
300
+ :return: The x2 value of the tight element bounding box.
301
+ """
302
+ return self.tbox.x2
303
+
304
+ @tx2.setter
305
+ def tx2(self, value: float) -> None:
306
+ """Set the x2 value of the tight element bounding box.
307
+
308
+ :param value: The new x2 value of the tight element bounding box.
309
+ """
310
+ self.transform(dx=value - self.tbox.x2)
311
+
312
+ @property
313
+ def ty(self) -> float:
314
+ """The y value of the tight element bounding box.
315
+
316
+ :return: The y value of the tight element bounding box.
317
+ """
318
+ return self.tbox.y
227
319
 
228
- :return: The line gap between this line of text and the next.
320
+ @ty.setter
321
+ def ty(self, value: float) -> None:
322
+ """Set the y value of the tight element bounding box.
323
+
324
+ :param value: The new y value of the tight element bounding box.
325
+ """
326
+ self.transform(dy=value - self.tbox.y)
327
+
328
+ @property
329
+ def ty2(self) -> float:
330
+ """The y2 value of the tight element bounding box.
331
+
332
+ :return: The y2 value of the tight element bounding box.
333
+ """
334
+ return self.tbox.y2
335
+
336
+ @ty2.setter
337
+ def ty2(self, value: float) -> None:
338
+ """Set the y2 value of the tight element bounding box.
339
+
340
+ :param value: The new y2 value of the tight element bounding box.
341
+ """
342
+ self.transform(dy=value - self.tbox.y2)
343
+
344
+ @property
345
+ def twidth(self) -> float:
346
+ """The width of the tight element bounding box.
347
+
348
+ :return: The width of the tight element bounding box.
229
349
  """
230
- if self._line_gap is None:
231
- raise AttributeError(_no_line_gap_msg)
232
- return self._line_gap
350
+ return self.tbox.width
233
351
 
234
- @line_gap.setter
235
- def line_gap(self, value: float) -> None:
236
- """Set the line gap between this line of text and the next.
352
+ @twidth.setter
353
+ def twidth(self, value: float) -> None:
354
+ """Set the width of the tight element bounding box.
237
355
 
238
- :param value: The new line gap.
356
+ :param value: The new width of the tight element bounding box.
239
357
  """
240
- self._line_gap = value
358
+ self.transform(scale=value / self.tbox.width)
359
+
360
+ @property
361
+ def theight(self) -> float:
362
+ """The height of the tight element bounding box.
363
+
364
+ :return: The height of the tight element bounding box.
365
+ """
366
+ return self.tbox.height
367
+
368
+ @theight.setter
369
+ def theight(self, value: float) -> None:
370
+ """Set the height of the tight element bounding box.
371
+
372
+ :param value: The new height of the tight element bounding box.
373
+ """
374
+ self.transform(scale=value / self.tbox.height)
375
+
376
+ @property
377
+ def baseline(self) -> float:
378
+ """The y value of the baseline for the font.
379
+
380
+ :return: The baseline y value of this line of text.
381
+ """
382
+ return mat_apply(self.tbox.transformation, (0, 0))[1]
383
+ return self.y2 + (self.metrics.descent)
384
+
385
+ @baseline.setter
386
+ def baseline(self, value: float) -> None:
387
+ """Set the y value of the baseline for the font.
388
+
389
+ :param value: The new baseline y value.
390
+ """
391
+ dy = value - self.baseline
392
+ self.transform(dy=dy)
393
+
394
+ @property
395
+ def capline(self) -> float:
396
+ """The y value of the top of flat-topped capital letters for the font.
397
+
398
+ :return: The capline y value of this line of text.
399
+ """
400
+ return self.baseline - self.metrics.cap_height
401
+
402
+ @capline.setter
403
+ def capline(self, value: float) -> None:
404
+ """Set the capline y value for the font.
405
+
406
+ :param value: The new capline y value.
407
+ """
408
+ dy = value - self.capline
409
+ self.transform(dy=dy)
410
+
411
+ @property
412
+ def xline(self) -> float:
413
+ """The y value of the x-height for the font.
414
+
415
+ :return: The xline y value of this line of text.
416
+ """
417
+ return self.baseline - self.metrics.x_height
418
+
419
+ @xline.setter
420
+ def xline(self, value: float) -> None:
421
+ """Set the xline y value for the font.
422
+
423
+ :param value: The new xline y value.
424
+ """
425
+ dy = value - self.xline
426
+ self.transform(dy=dy)
241
427
 
242
428
  @property
243
429
  def font_size(self) -> float:
@@ -245,9 +431,7 @@ class PaddedText(BoundElement):
245
431
 
246
432
  :return: The font size of this line of text.
247
433
  """
248
- if self._font_size is None:
249
- raise AttributeError(_no_font_size_msg)
250
- return self._font_size
434
+ return self.metrics.font_size
251
435
 
252
436
  @font_size.setter
253
437
  def font_size(self, value: float) -> None:
@@ -263,7 +447,7 @@ class PaddedText(BoundElement):
263
447
 
264
448
  :return: The line gap plus the height of this line of text.
265
449
  """
266
- return self.height + self.line_gap
450
+ return self.height + self.metrics.line_gap
267
451
 
268
452
  @property
269
453
  def tpad(self) -> float:
@@ -332,19 +516,6 @@ class PaddedText(BoundElement):
332
516
  )
333
517
  self.transform(scale=new_scale)
334
518
 
335
- @property
336
- def uniform_scale(self) -> float:
337
- """Get uniform scale of the bounding box.
338
-
339
- :return: uniform scale of the bounding box
340
- :raises ValueError: if the scale is non-uniform.
341
- """
342
- scale = self.scale
343
- if math.isclose(scale[0], scale[1]):
344
- return scale[0]
345
- msg = f"Non-uniform scale detected: sx={scale[0]}, sy={scale[1]}"
346
- raise ValueError(msg)
347
-
348
519
  @property
349
520
  def width(self) -> float:
350
521
  """The width of this line of text with padding.
@@ -500,3 +671,19 @@ class PaddedText(BoundElement):
500
671
  :param value: The bottom of this line of text.
501
672
  """
502
673
  self.transform(dy=value - self.bpad - self.tbox.y2)
674
+
675
+
676
+ def new_padded_union(*plems: PaddedText, **attributes: ElemAttrib) -> PaddedText:
677
+ """Create a new PaddedText instance that is the union of multiple PaddedText.
678
+
679
+ :param plems: The PaddedText instances to union.
680
+ :return: A new PaddedText instance that is the union of the input instances.
681
+ """
682
+ bbox = BoundingBox.union(*(t.bbox for t in plems))
683
+ tbox = BoundingBox.union(*(t.tbox for t in plems))
684
+ tpad = tbox.y - bbox.y
685
+ rpad = bbox.x2 - tbox.x2
686
+ bpad = bbox.y2 - tbox.y2
687
+ lpad = tbox.x - bbox.x
688
+ elem = new_element_union(*(t.elem for t in plems), **attributes)
689
+ return PaddedText(elem, tbox, tpad, rpad, bpad, lpad, plems[0]._metrics) # pyright: ignore[reportPrivateUsage]
@@ -16,6 +16,7 @@ import warnings
16
16
  from typing import TYPE_CHECKING
17
17
 
18
18
  from lxml import etree
19
+ from lxml.etree import _Element as EtreeElement # pyright: ignore[reportPrivateUsage]
19
20
 
20
21
  from svg_ultralight.string_conversion import set_attributes
21
22
 
@@ -23,9 +24,6 @@ if TYPE_CHECKING:
23
24
  from lxml.etree import (
24
25
  QName,
25
26
  )
26
- from lxml.etree import (
27
- _Element as EtreeElement, # pyright: ignore[reportPrivateUsage]
28
- )
29
27
 
30
28
  from svg_ultralight.attrib_hints import ElemAttrib
31
29
 
@@ -115,3 +113,39 @@ def deepcopy_element(elem: EtreeElement, **attributes: ElemAttrib) -> EtreeEleme
115
113
  elem = copy.deepcopy(elem)
116
114
  _ = update_element(elem, **attributes)
117
115
  return elem
116
+
117
+
118
+ def new_element_union(
119
+ *elems: EtreeElement | object, **attributes: ElemAttrib
120
+ ) -> EtreeElement:
121
+ """Get the union of any elements found in the given arguments.
122
+
123
+ :param elems: EtreeElements or containers like BoundElements, PaddedTexts, or
124
+ others that have an `elem` attribute that is an EtreeElement. Other arguments
125
+ will be ignored.
126
+ :return: a new group element containing all elements.
127
+
128
+ This does not support consolidating attributes. E.g., if all elements have the
129
+ same fill color, this will not be recognized and consolidated into a single
130
+ attribute for the group. Too many attributes change their behavior when applied
131
+ to a group.
132
+ """
133
+ elements_found: list[EtreeElement] = []
134
+ for elem in elems:
135
+ if isinstance(elem, EtreeElement):
136
+ elements_found.append(elem)
137
+ continue
138
+ elem_elem = getattr(elem, "elem", None)
139
+ if isinstance(elem_elem, EtreeElement):
140
+ elements_found.append(elem_elem)
141
+
142
+ if not elements_found:
143
+ msg = (
144
+ "Cannot find any elements to union. "
145
+ + "At least one argument must be a "
146
+ + "BoundElement, PaddedText, or EtreeElement."
147
+ )
148
+ raise ValueError(msg)
149
+ group = new_element("g", **attributes)
150
+ group.extend(elements_found)
151
+ return group
@@ -1,9 +1,9 @@
1
1
  """Compare results between Inkscape and fontTools.
2
2
 
3
3
  Function `check_font_tools_alignment` will let you know if it's relatively safe to
4
- use `pad_text_mix` or `pad_text_ft`, which improve `pad_text` by assigning `line_gap`
5
- values to the resulting PaddedText instance and by aligning with the actual descent
6
- and ascent of a font instead of by attempting to infer these from a referenve string.
4
+ use `pad_text_ft`, which improves `pad_text_inkscape` by assigning `line_gap` values
5
+ to the resulting PaddedText instance and by aligning with the actual descent and
6
+ ascent of a font instead of by attempting to infer these from a referenve string.
7
7
 
8
8
  See Enum `FontBboxError` for the possible error codes and their meanings returned by
9
9
  `check_font`.
@@ -27,8 +27,8 @@ from typing import TYPE_CHECKING
27
27
  from svg_ultralight.bounding_boxes.bound_helpers import new_bbox_rect, pad_bbox
28
28
  from svg_ultralight.bounding_boxes.padded_text_initializers import (
29
29
  DEFAULT_Y_BOUNDS_REFERENCE,
30
- pad_text,
31
30
  pad_text_ft,
31
+ pad_text_inkscape,
32
32
  )
33
33
  from svg_ultralight.constructors import new_element
34
34
  from svg_ultralight.font_tools.font_info import FTFontInfo, get_svg_font_attributes
@@ -45,14 +45,14 @@ if TYPE_CHECKING:
45
45
  class FontBboxError(enum.Enum):
46
46
  """Classify the type of error between Inkscape and fontTools bounding boxes.
47
47
 
48
- INIT: Use `pad_text`.
48
+ INIT: Use `pad_text_inkscape`.
49
49
 
50
- FontTools failed to run. This can happen with fonts that, inentionally or
51
- not, do not have the required tables or character sets to build a bounding box
52
- around the TEXT_TEXT. You can only use the `pad_text` PaddedText constructor.
53
- This font may work with other or ascii-only text.
50
+ FontTools failed to run. This can happen with fonts that, inentionally or not, do
51
+ not have the required tables or character sets to build a bounding box around the
52
+ TEXT_TEXT. You can only use the `pad_text_inkscape` PaddedText constructor. This
53
+ font may work with other or ascii-only text.
54
54
 
55
- ELEM_Y: Use `pad_text` or `pad_text_mix` with cautions.
55
+ ELEM_Y: Use `pad_text_inkscape` with cautions.
56
56
 
57
57
  The y coordinate of the element bounding box is off by more than 1% of
58
58
  the height. This error matters, because the y coordinates are used by
@@ -60,21 +60,21 @@ class FontBboxError(enum.Enum):
60
60
  y_bounds_reference element and accept some potential error in `line_gap` or
61
61
  explicitly pass `ascent` and `descent` values to `pad_text_ft` or `pad_text_mix`.
62
62
 
63
- SAFE_ELEM_X: Use `pad_text_mix`.
63
+ SAFE_ELEM_X:
64
64
 
65
65
  The y bounds are accurate, but the x coordinate of the element
66
66
  bounding box is off by more than 1%. This is called "safe" because it is not used
67
67
  by pad_bbox_mix, but you cannot use `pad_text_ft` without expecting BoundingBox
68
68
  inaccuracies.
69
69
 
70
- LINE_Y: Use `pad_text` or `pad_text_mix` with caution.
70
+ LINE_Y: Use `pad_text_inkscape` with caution.
71
71
 
72
72
  All of the above match, but the y coordinate of the line bounding box
73
73
  (the padded bounding box) is off by more than 1% of the height. This error
74
74
  matters as does ELEM_Y, but it does not exist for any font on my system. Fonts
75
75
  without ELEM_Y errors should not have LINE_Y errors.
76
76
 
77
- SAFE_LINE_X: Use `pad_text_mix`.
77
+ SAFE_LINE_X:
78
78
 
79
79
  All of the above match, but the x coordinate of the line bounding
80
80
  box (the padded bounding box) is off by more than 1%. This is safe or unsafe as
@@ -82,9 +82,9 @@ class FontBboxError(enum.Enum):
82
82
 
83
83
  NO_ERROR: Use `pad_text_ft`.
84
84
 
85
- No errors were found. The bounding boxes match within 1% of the height.
86
- You can use `pad_text_ft` to get the same result as `pad_text` or `pad_text_mix`
87
- without the delay caused by an Inkscape call.
85
+ No errors were found. The bounding boxes match within 1% of the height. You can
86
+ use `pad_text_ft` to get the same result as `pad_text_inkscape` without the delay
87
+ caused by an Inkscape call.
88
88
  """
89
89
 
90
90
  INIT = enum.auto()
@@ -154,7 +154,7 @@ def check_font_tools_alignment(
154
154
  try:
155
155
  svg_attribs = get_svg_font_attributes(font)
156
156
  text_elem = new_element("text", **svg_attribs, text=text)
157
- rslt_pt = pad_text(inkscape, text_elem)
157
+ rslt_pt = pad_text_inkscape(inkscape, text_elem)
158
158
  rslt_ft = pad_text_ft(
159
159
  font,
160
160
  text,
@@ -212,7 +212,7 @@ def draw_comparison(
212
212
  stroke="green",
213
213
  stroke_width=0.1,
214
214
  )
215
- padded_pt = pad_text(inkscape, text_elem)
215
+ padded_pt = pad_text_inkscape(inkscape, text_elem)
216
216
  padded_ft = pad_text_ft(
217
217
  font,
218
218
  text,