ManimPango 0.4.3__cp311-cp311-win32.whl → 1.0.0a2__cp311-cp311-win32.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.
Files changed (83) hide show
  1. {ManimPango-0.4.3.dist-info → ManimPango-1.0.0a2.dist-info}/METADATA +2 -2
  2. ManimPango-1.0.0a2.dist-info/RECORD +85 -0
  3. {ManimPango-0.4.3.dist-info → ManimPango-1.0.0a2.dist-info}/WHEEL +1 -1
  4. manimpango/__init__.py +5 -7
  5. manimpango/_distributor_init.py +36 -0
  6. manimpango/_version.py +1 -1
  7. manimpango/attributes/__init__.py +324 -0
  8. manimpango/attributes/attributes.pxi +219 -0
  9. manimpango/buffer.pxi +15 -0
  10. manimpango/cmanimpango.c +10025 -0
  11. manimpango/cmanimpango.cp311-win32.pyd +0 -0
  12. manimpango/enums.c +3721 -0
  13. manimpango/enums.cp311-win32.pyd +0 -0
  14. manimpango/enums.pyx +1 -10
  15. manimpango/exceptions.py +5 -0
  16. manimpango/fonts/__init__.py +153 -0
  17. manimpango/fonts/_font_desc.c +7576 -0
  18. manimpango/fonts/_font_desc.cp311-win32.pyd +0 -0
  19. manimpango/fonts/_font_desc.pxd +5 -0
  20. manimpango/fonts/_font_desc.pyi +25 -0
  21. manimpango/fonts/_font_desc.pyx +114 -0
  22. manimpango/fonts/enums.c +3628 -0
  23. manimpango/fonts/enums.cp311-win32.pyd +0 -0
  24. manimpango/fonts/enums.pyi +23 -0
  25. manimpango/fonts/enums.pyx +84 -0
  26. manimpango/{cairo.pxd → include/cairo.pxd} +21 -0
  27. manimpango/include/glib.pxd +36 -0
  28. manimpango/{pango.pxd → include/pango.pxd} +61 -0
  29. manimpango/include/pango_attributes.pxd +184 -0
  30. manimpango/layout/__init__.py +266 -0
  31. manimpango/layout/_layout.c +8630 -0
  32. manimpango/layout/_layout.cp311-win32.pyd +0 -0
  33. manimpango/layout/_layout.pyx +60 -0
  34. manimpango/layout/layout.pxi +52 -0
  35. manimpango/register_font.c +5016 -0
  36. manimpango/register_font.cp311-win32.pyd +0 -0
  37. manimpango/renderer/__init__.py +5 -0
  38. manimpango/renderer/cairo_utils.pxi +72 -0
  39. manimpango/renderer/image_renderer.c +12319 -0
  40. manimpango/renderer/image_renderer.cp311-win32.pyd +0 -0
  41. manimpango/renderer/image_renderer.pxd +23 -0
  42. manimpango/renderer/image_renderer.pyi +21 -0
  43. manimpango/renderer/image_renderer.pyx +219 -0
  44. manimpango/renderer/svg_renderer.c +10671 -0
  45. manimpango/renderer/svg_renderer.cp311-win32.pyd +0 -0
  46. manimpango/renderer/svg_renderer.pxd +23 -0
  47. manimpango/renderer/svg_renderer.pyi +17 -0
  48. manimpango/renderer/svg_renderer.pyx +174 -0
  49. manimpango/utils/__init__.py +3 -0
  50. manimpango/utils/_utils.cp311-win32.pyd +0 -0
  51. manimpango/utils/_utils.pyi +2 -0
  52. manimpango/utils/utils.c +3533 -0
  53. manimpango/{utils.py → utils/utils.py} +3 -1
  54. manimpango/utils/utils.pyx +27 -0
  55. ManimPango-0.4.3.dist-info/RECORD +0 -44
  56. manimpango/glib.pxd +0 -13
  57. {ManimPango-0.4.3.dist-info → ManimPango-1.0.0a2.dist-info}/LICENSE +0 -0
  58. {ManimPango-0.4.3.dist-info → ManimPango-1.0.0a2.dist-info}/LICENSE.win32 +0 -0
  59. {ManimPango-0.4.3.dist-info → ManimPango-1.0.0a2.dist-info}/top_level.txt +0 -0
  60. /manimpango/{CORE_MANIM_cairo-2.dll → .libs/CORE_MANIM_cairo-2.dll} +0 -0
  61. /manimpango/{CORE_MANIM_cairo-gobject-2.dll → .libs/CORE_MANIM_cairo-gobject-2.dll} +0 -0
  62. /manimpango/{CORE_MANIM_cairo-script-interpreter-2.dll → .libs/CORE_MANIM_cairo-script-interpreter-2.dll} +0 -0
  63. /manimpango/{CORE_MANIM_expat.dll → .libs/CORE_MANIM_expat.dll} +0 -0
  64. /manimpango/{CORE_MANIM_ffi-7.dll → .libs/CORE_MANIM_ffi-7.dll} +0 -0
  65. /manimpango/{CORE_MANIM_fontconfig-1.dll → .libs/CORE_MANIM_fontconfig-1.dll} +0 -0
  66. /manimpango/{CORE_MANIM_freetype-6.dll → .libs/CORE_MANIM_freetype-6.dll} +0 -0
  67. /manimpango/{CORE_MANIM_fribidi-0.dll → .libs/CORE_MANIM_fribidi-0.dll} +0 -0
  68. /manimpango/{CORE_MANIM_gio-2.0-0.dll → .libs/CORE_MANIM_gio-2.0-0.dll} +0 -0
  69. /manimpango/{CORE_MANIM_glib-2.0-0.dll → .libs/CORE_MANIM_glib-2.0-0.dll} +0 -0
  70. /manimpango/{CORE_MANIM_gmodule-2.0-0.dll → .libs/CORE_MANIM_gmodule-2.0-0.dll} +0 -0
  71. /manimpango/{CORE_MANIM_gobject-2.0-0.dll → .libs/CORE_MANIM_gobject-2.0-0.dll} +0 -0
  72. /manimpango/{CORE_MANIM_gthread-2.0-0.dll → .libs/CORE_MANIM_gthread-2.0-0.dll} +0 -0
  73. /manimpango/{CORE_MANIM_harfbuzz-gobject.dll → .libs/CORE_MANIM_harfbuzz-gobject.dll} +0 -0
  74. /manimpango/{CORE_MANIM_harfbuzz-subset.dll → .libs/CORE_MANIM_harfbuzz-subset.dll} +0 -0
  75. /manimpango/{CORE_MANIM_harfbuzz.dll → .libs/CORE_MANIM_harfbuzz.dll} +0 -0
  76. /manimpango/{CORE_MANIM_intl-8.dll → .libs/CORE_MANIM_intl-8.dll} +0 -0
  77. /manimpango/{CORE_MANIM_pango-1.0-0.dll → .libs/CORE_MANIM_pango-1.0-0.dll} +0 -0
  78. /manimpango/{CORE_MANIM_pangocairo-1.0-0.dll → .libs/CORE_MANIM_pangocairo-1.0-0.dll} +0 -0
  79. /manimpango/{CORE_MANIM_pangoft2-1.0-0.dll → .libs/CORE_MANIM_pangoft2-1.0-0.dll} +0 -0
  80. /manimpango/{CORE_MANIM_pangowin32-1.0-0.dll → .libs/CORE_MANIM_pangowin32-1.0-0.dll} +0 -0
  81. /manimpango/{CORE_MANIM_pixman-1-0.dll → .libs/CORE_MANIM_pixman-1-0.dll} +0 -0
  82. /manimpango/{CORE_MANIM_png16-16.dll → .libs/CORE_MANIM_png16-16.dll} +0 -0
  83. /manimpango/{CORE_MANIM_z.dll → .libs/CORE_MANIM_z.dll} +0 -0
@@ -0,0 +1,266 @@
1
+ # -*- coding: utf-8 -*-
2
+ from __future__ import annotations
3
+
4
+ from ..attributes import TextAttribute
5
+ from ..enums import Alignment
6
+ from ..exceptions import MarkupParseError
7
+ from ..fonts import FontDescription
8
+ from ..utils import validate_markup
9
+
10
+ __all__ = ["Layout"]
11
+
12
+
13
+ class Layout:
14
+ """A :class:`Layout` class represents an entire paragraph of text.
15
+
16
+ :class:`Layout` provides a high-level driver for formatting entire
17
+ paragraphs of text at once. This includes paragraph-level functionality
18
+ such as line breaking, justification, alignment and ellipsization.
19
+
20
+ A :class:`Layout` is initialized with a :class:`str`. The layout
21
+ can then be rendered. There are a number of parameters to adjust
22
+ the formatting of a :class:`Layout`.
23
+
24
+ When both :attr:`markup` and :attr:`text` is set the behavior is
25
+ unknown.
26
+
27
+ Parameters
28
+ ==========
29
+ text:
30
+ The text to be set, by default None.
31
+ markup:
32
+ The text encoded in PangoMarkup, by default None.
33
+ font_desc:
34
+ The font description to be used while rendering.
35
+
36
+ Examples
37
+ ========
38
+ >>> import manimpango as mp
39
+ >>> mp.Layout("hello world")
40
+ <Layout text='hello world' markup=None>
41
+
42
+ Raises
43
+ ======
44
+ ValueError
45
+ If both ``text`` and ``markup`` is None.
46
+ """
47
+
48
+ def __init__(
49
+ self,
50
+ text: str = None,
51
+ markup: str = None,
52
+ font_desc: FontDescription = None,
53
+ attributes: list[TextAttribute] = None,
54
+ width: int = None,
55
+ height: int = None,
56
+ alignment: Alignment = None,
57
+ justify: bool = None,
58
+ ):
59
+ if text:
60
+ self.text = text
61
+ if markup:
62
+ self.markup = markup
63
+ if self.markup is None and self.text is None:
64
+ raise ValueError("Either 'markup' or 'text' is required.")
65
+ if font_desc:
66
+ self.font_desc = font_desc
67
+ if attributes:
68
+ self.attributes = attributes
69
+ if width:
70
+ self.width = width
71
+ if height:
72
+ self.height = height
73
+ if alignment:
74
+ self.alignment = alignment
75
+ if justify:
76
+ self.justify = justify
77
+
78
+ def __len__(self):
79
+ return len(self.text) if self.text is not None else len(self.markup)
80
+
81
+ @property
82
+ def text(self) -> str:
83
+ """The text to render.
84
+
85
+ Raises
86
+ ======
87
+ TypeError
88
+ If ``text`` is not a :class:`str`.
89
+ """
90
+ if hasattr(self, "_text"):
91
+ return self._text
92
+ return None
93
+
94
+ @text.setter
95
+ def text(self, val: str) -> None:
96
+ if not isinstance(val, str):
97
+ raise TypeError("'text' should be a str")
98
+ self._text = val
99
+
100
+ @property
101
+ def markup(self) -> str:
102
+ """The markup (in pango markup format) to render.
103
+
104
+ Raises
105
+ ======
106
+ TypeError
107
+ If ``text`` is not a :class:`str`.
108
+
109
+ MarkupParseError
110
+ If the passed markup is invalid.
111
+ """
112
+ if hasattr(self, "_markup"):
113
+ return self._markup
114
+ return None
115
+
116
+ @markup.setter
117
+ def markup(self, val: str) -> None:
118
+ if not isinstance(val, str):
119
+ raise TypeError("'markup' should be a str")
120
+ check = validate_markup(val)
121
+ if check:
122
+ raise MarkupParseError(check)
123
+ self._markup = val
124
+
125
+ @property
126
+ def width(self) -> int:
127
+ """The width to which the text should be wrapped or ellipsized.
128
+
129
+ Raises
130
+ ======
131
+ TypeError
132
+ If ``width`` is not a :class:`int`.
133
+ """
134
+ if hasattr(self, "_width"):
135
+ return self._width
136
+ return None
137
+
138
+ @width.setter
139
+ def width(self, val: int) -> None:
140
+ if not isinstance(val, int):
141
+ raise TypeError("'width' should be an int")
142
+ self._width = val
143
+
144
+ @property
145
+ def height(self) -> int:
146
+ """The height to which the text should be ellipsized at.
147
+
148
+ Raises
149
+ ======
150
+ TypeError
151
+ If ``height`` is not a :class:`int`.
152
+ """
153
+ if hasattr(self, "_height"):
154
+ return self._height
155
+ return None
156
+
157
+ @height.setter
158
+ def height(self, val: int) -> None:
159
+ if not isinstance(val, int):
160
+ raise TypeError("'height' should be an int")
161
+ self._height = val
162
+
163
+ @property
164
+ def alignment(self) -> Alignment:
165
+ if hasattr(self, "_alignment"):
166
+ return self._alignment
167
+ return None
168
+
169
+ @alignment.setter
170
+ def alignment(self, val: Alignment):
171
+ if not isinstance(val, Alignment):
172
+ raise TypeError("'alignment' should be an Alignment")
173
+ self._alignment = val
174
+
175
+ @property
176
+ def font_desc(self) -> FontDescription:
177
+ if hasattr(self, "_font_desc"):
178
+ return self._font_desc
179
+ return FontDescription()
180
+
181
+ @font_desc.setter
182
+ def font_desc(self, val: FontDescription):
183
+ if not isinstance(val, FontDescription):
184
+ raise TypeError("'font_desc' should be an FontDescription")
185
+ self._font_desc = val
186
+
187
+ @property
188
+ def attributes(self) -> list[TextAttribute]:
189
+ if hasattr(self, "_attributes"):
190
+ return self._attributes
191
+ return []
192
+
193
+ @attributes.setter
194
+ def attributes(self, val: list[TextAttribute]):
195
+ if not isinstance(val, list):
196
+ raise TypeError("'attributes' should be a list")
197
+ # check if all element of val is of type TextAttribute
198
+ if not all(isinstance(x, TextAttribute) for x in val):
199
+ raise TypeError("'attributes' should be a list of TextAttribute")
200
+ self._attributes = val
201
+
202
+ @property
203
+ def justify(self) -> bool:
204
+ """Whether the text should be justified.
205
+
206
+ Raises
207
+ ======
208
+ TypeError
209
+ If ``justify`` is not a :class:`bool`.
210
+ """
211
+ if hasattr(self, "_justify"):
212
+ return self._justify
213
+ return False
214
+
215
+ @justify.setter
216
+ def justify(self, val: bool) -> None:
217
+ if not isinstance(val, bool):
218
+ raise TypeError("'justify' should be a bool")
219
+ self._justify = val
220
+
221
+ def get_bounding_box(self) -> tuple[int, int, int, int]:
222
+ """Returns the bounding box of the layout.
223
+
224
+ Note that it's heavy to calculate the bounding box of a layout,
225
+ so it's better to cache the result.
226
+
227
+ Example
228
+ =======
229
+ >>> import manimpango as mp
230
+ >>> layout = mp.Layout("hello world")
231
+ >>> layout.get_bounding_box()
232
+ (0, 0, 82, 19)
233
+
234
+ Returns
235
+ =======
236
+ tuple
237
+ The bounding box of the layout in the form of
238
+ ``(x, y, width, height)``.
239
+ """
240
+ from ._layout import get_bbox
241
+
242
+ return get_bbox(self)
243
+
244
+ def render(self, file_name: str) -> None:
245
+ """Renders the layout into a PNG or SVG file depending
246
+ on the filename.
247
+
248
+ Parameters
249
+ ==========
250
+ file_name:
251
+ The filename to which the layout should be rendered.
252
+ """
253
+ from ..renderer import ImageRenderer, SVGRenderer
254
+
255
+ bbox = self.get_bounding_box()
256
+ if file_name.endswith(".png"):
257
+ renderer = ImageRenderer(*bbox[2:], self, file_name)
258
+ elif file_name.endswith(".svg"):
259
+ renderer = SVGRenderer(*bbox[2:], self, file_name)
260
+ else:
261
+ raise ValueError("Only rendering PNG and SVG files are supported.")
262
+ renderer.render()
263
+ renderer.save()
264
+
265
+ def __repr__(self):
266
+ return f"<Layout text={repr(self.text)} markup={repr(self.markup)}>"