aspose-pdf-foss-for-python 0.1.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.
Files changed (265) hide show
  1. aspose_pdf/__init__.py +367 -0
  2. aspose_pdf/_compat_surface.py +142 -0
  3. aspose_pdf/_export_files.py +108 -0
  4. aspose_pdf/_pending_signatures.py +222 -0
  5. aspose_pdf/_version.py +17 -0
  6. aspose_pdf/actions.py +273 -0
  7. aspose_pdf/annotations/__init__.py +1614 -0
  8. aspose_pdf/annotations/pdf3d.py +70 -0
  9. aspose_pdf/attachments.py +62 -0
  10. aspose_pdf/auto_links.py +375 -0
  11. aspose_pdf/block_extraction.py +223 -0
  12. aspose_pdf/cgm.py +7 -0
  13. aspose_pdf/clustering/__init__.py +13 -0
  14. aspose_pdf/clustering/hierarchical_agglomerative_clustering.py +151 -0
  15. aspose_pdf/color.py +241 -0
  16. aspose_pdf/destinations.py +164 -0
  17. aspose_pdf/document.py +5884 -0
  18. aspose_pdf/document_fonts.py +150 -0
  19. aspose_pdf/drawing.py +13 -0
  20. aspose_pdf/engine/__init__.py +1 -0
  21. aspose_pdf/engine/agl.py +243 -0
  22. aspose_pdf/engine/annotation_cleanup.py +407 -0
  23. aspose_pdf/engine/annotation_import.py +503 -0
  24. aspose_pdf/engine/annotation_json.py +313 -0
  25. aspose_pdf/engine/annotation_xfdf.py +405 -0
  26. aspose_pdf/engine/annotation_xfdf_import.py +389 -0
  27. aspose_pdf/engine/appearance.py +1361 -0
  28. aspose_pdf/engine/attachment_zip.py +306 -0
  29. aspose_pdf/engine/attachment_zip_import.py +387 -0
  30. aspose_pdf/engine/auto_crop.py +101 -0
  31. aspose_pdf/engine/auto_tag.py +1451 -0
  32. aspose_pdf/engine/blank_pages.py +198 -0
  33. aspose_pdf/engine/blank_split.py +73 -0
  34. aspose_pdf/engine/bookmark_json.py +714 -0
  35. aspose_pdf/engine/bookmark_split.py +167 -0
  36. aspose_pdf/engine/ccitt.py +457 -0
  37. aspose_pdf/engine/ccitt_tables.py +231 -0
  38. aspose_pdf/engine/cert_chain.py +306 -0
  39. aspose_pdf/engine/cff_outlines.py +928 -0
  40. aspose_pdf/engine/cms.py +562 -0
  41. aspose_pdf/engine/comparison_html.py +435 -0
  42. aspose_pdf/engine/conformance.py +2748 -0
  43. aspose_pdf/engine/contact_sheet.py +215 -0
  44. aspose_pdf/engine/content_authoring.py +1347 -0
  45. aspose_pdf/engine/content_bounds.py +67 -0
  46. aspose_pdf/engine/content_isolation.py +180 -0
  47. aspose_pdf/engine/content_stream_parser.py +2318 -0
  48. aspose_pdf/engine/cos.py +416 -0
  49. aspose_pdf/engine/data/__init__.py +81 -0
  50. aspose_pdf/engine/data/agl/LICENSE-ADOBE-AGL.txt +28 -0
  51. aspose_pdf/engine/data/agl/LICENSE-REPORTLAB.txt +31 -0
  52. aspose_pdf/engine/data/agl/README.md +44 -0
  53. aspose_pdf/engine/data/agl/glyphlist.json.zlib +0 -0
  54. aspose_pdf/engine/data/cmaps/LICENSE-ADOBE-CMAP.txt +28 -0
  55. aspose_pdf/engine/data/cmaps/LICENSE-ADOBE-MAPPING.txt +28 -0
  56. aspose_pdf/engine/data/cmaps/README.md +51 -0
  57. aspose_pdf/engine/data/cmaps/predefined_cmaps_CNS1.json.zlib +0 -0
  58. aspose_pdf/engine/data/cmaps/predefined_cmaps_GB1.json.zlib +0 -0
  59. aspose_pdf/engine/data/cmaps/predefined_cmaps_Japan1.json.zlib +0 -0
  60. aspose_pdf/engine/data/cmaps/predefined_cmaps_Korea1.json.zlib +0 -0
  61. aspose_pdf/engine/data/cmaps/predefined_cmaps_index.json.zlib +0 -0
  62. aspose_pdf/engine/data/fonts/LICENSE-DEJAVU.txt +187 -0
  63. aspose_pdf/engine/data/fonts/LICENSE-OFL.txt +102 -0
  64. aspose_pdf/engine/data/fonts/README.md +47 -0
  65. aspose_pdf/engine/data/fonts/dingbats.ttf.zlib +0 -0
  66. aspose_pdf/engine/data/fonts/mono-bold.ttf.zlib +0 -0
  67. aspose_pdf/engine/data/fonts/mono-bolditalic.ttf.zlib +0 -0
  68. aspose_pdf/engine/data/fonts/mono-italic.ttf.zlib +0 -0
  69. aspose_pdf/engine/data/fonts/mono-regular.ttf.zlib +0 -0
  70. aspose_pdf/engine/data/fonts/sans-bold.ttf.zlib +0 -0
  71. aspose_pdf/engine/data/fonts/sans-bolditalic.ttf.zlib +0 -0
  72. aspose_pdf/engine/data/fonts/sans-italic.ttf.zlib +0 -0
  73. aspose_pdf/engine/data/fonts/sans-regular.ttf.zlib +0 -0
  74. aspose_pdf/engine/data/fonts/serif-bold.ttf.zlib +0 -0
  75. aspose_pdf/engine/data/fonts/serif-bolditalic.ttf.zlib +0 -0
  76. aspose_pdf/engine/data/fonts/serif-italic.ttf.zlib +0 -0
  77. aspose_pdf/engine/data/fonts/serif-regular.ttf.zlib +0 -0
  78. aspose_pdf/engine/data/fonts/symbol.ttf.zlib +0 -0
  79. aspose_pdf/engine/data/number.py +78 -0
  80. aspose_pdf/engine/data/types.py +156 -0
  81. aspose_pdf/engine/data/xmp.py +1458 -0
  82. aspose_pdf/engine/dct.py +854 -0
  83. aspose_pdf/engine/dss.py +658 -0
  84. aspose_pdf/engine/duplicate_pages.py +67 -0
  85. aspose_pdf/engine/encryption.py +967 -0
  86. aspose_pdf/engine/field_appearance.py +310 -0
  87. aspose_pdf/engine/file_output.py +98 -0
  88. aspose_pdf/engine/filters.py +958 -0
  89. aspose_pdf/engine/flatten.py +388 -0
  90. aspose_pdf/engine/font_authoring.py +609 -0
  91. aspose_pdf/engine/font_inventory.py +211 -0
  92. aspose_pdf/engine/font_resolver.py +829 -0
  93. aspose_pdf/engine/font_subset.py +545 -0
  94. aspose_pdf/engine/font_subset_cff.py +963 -0
  95. aspose_pdf/engine/font_subset_type1.py +114 -0
  96. aspose_pdf/engine/font_variations.py +159 -0
  97. aspose_pdf/engine/form_batch.py +134 -0
  98. aspose_pdf/engine/form_csv.py +267 -0
  99. aspose_pdf/engine/form_csv_export.py +131 -0
  100. aspose_pdf/engine/form_data.py +364 -0
  101. aspose_pdf/engine/form_field_edit.py +306 -0
  102. aspose_pdf/engine/form_fields.py +253 -0
  103. aspose_pdf/engine/form_json.py +89 -0
  104. aspose_pdf/engine/form_schema.py +246 -0
  105. aspose_pdf/engine/form_validation.py +395 -0
  106. aspose_pdf/engine/glyph_outlines.py +465 -0
  107. aspose_pdf/engine/graphics_absorb.py +1061 -0
  108. aspose_pdf/engine/grid_split.py +80 -0
  109. aspose_pdf/engine/gvar.py +467 -0
  110. aspose_pdf/engine/headings.py +273 -0
  111. aspose_pdf/engine/image_export.py +875 -0
  112. aspose_pdf/engine/image_import.py +219 -0
  113. aspose_pdf/engine/image_resample.py +116 -0
  114. aspose_pdf/engine/image_resolution.py +376 -0
  115. aspose_pdf/engine/image_zip.py +339 -0
  116. aspose_pdf/engine/imposition.py +233 -0
  117. aspose_pdf/engine/incremental_update.py +477 -0
  118. aspose_pdf/engine/inline_image.py +337 -0
  119. aspose_pdf/engine/interleave.py +188 -0
  120. aspose_pdf/engine/io.py +53 -0
  121. aspose_pdf/engine/jbig2.py +186 -0
  122. aspose_pdf/engine/jpeg2000.py +2124 -0
  123. aspose_pdf/engine/jpeg_encoder.py +706 -0
  124. aspose_pdf/engine/jpx.py +211 -0
  125. aspose_pdf/engine/link_extraction.py +378 -0
  126. aspose_pdf/engine/link_urls.py +252 -0
  127. aspose_pdf/engine/link_validation.py +555 -0
  128. aspose_pdf/engine/lists.py +307 -0
  129. aspose_pdf/engine/logging.py +18 -0
  130. aspose_pdf/engine/merge_bookmarks.py +180 -0
  131. aspose_pdf/engine/optional_content.py +1323 -0
  132. aspose_pdf/engine/page_count_split.py +60 -0
  133. aspose_pdf/engine/page_labels.py +295 -0
  134. aspose_pdf/engine/page_zip.py +219 -0
  135. aspose_pdf/engine/parser_exceptions.py +125 -0
  136. aspose_pdf/engine/pdf_matrix.py +90 -0
  137. aspose_pdf/engine/pdf_parser_cos.py +1611 -0
  138. aspose_pdf/engine/pdf_writer_cos.py +544 -0
  139. aspose_pdf/engine/predefined_cmaps.py +635 -0
  140. aspose_pdf/engine/primitives/__init__.py +5 -0
  141. aspose_pdf/engine/primitives/matrix.py +31 -0
  142. aspose_pdf/engine/pubsec.py +898 -0
  143. aspose_pdf/engine/rasterized_copy.py +171 -0
  144. aspose_pdf/engine/rasterizer.py +5483 -0
  145. aspose_pdf/engine/redaction.py +140 -0
  146. aspose_pdf/engine/revocation.py +495 -0
  147. aspose_pdf/engine/rich_text.py +415 -0
  148. aspose_pdf/engine/sanitize.py +412 -0
  149. aspose_pdf/engine/sfnt.py +247 -0
  150. aspose_pdf/engine/shading.py +2317 -0
  151. aspose_pdf/engine/sign_field.py +689 -0
  152. aspose_pdf/engine/signature_appearance.py +302 -0
  153. aspose_pdf/engine/signature_profiles.py +206 -0
  154. aspose_pdf/engine/signature_revisions.py +476 -0
  155. aspose_pdf/engine/signature_validator.py +313 -0
  156. aspose_pdf/engine/signed_changes.py +208 -0
  157. aspose_pdf/engine/signing.py +288 -0
  158. aspose_pdf/engine/simple_pdf.py +21416 -0
  159. aspose_pdf/engine/spread_split.py +330 -0
  160. aspose_pdf/engine/stamps.py +414 -0
  161. aspose_pdf/engine/std_font_data.py +201 -0
  162. aspose_pdf/engine/std_fonts.py +97 -0
  163. aspose_pdf/engine/std_metrics.py +364 -0
  164. aspose_pdf/engine/stream_output.py +22 -0
  165. aspose_pdf/engine/stroke.py +228 -0
  166. aspose_pdf/engine/svg_export.py +1162 -0
  167. aspose_pdf/engine/symbol_encodings.py +260 -0
  168. aspose_pdf/engine/tables.py +420 -0
  169. aspose_pdf/engine/text_blocks.py +467 -0
  170. aspose_pdf/engine/text_comparison.py +146 -0
  171. aspose_pdf/engine/text_edit.py +1936 -0
  172. aspose_pdf/engine/text_export.py +758 -0
  173. aspose_pdf/engine/text_faces.py +275 -0
  174. aspose_pdf/engine/text_highlight.py +197 -0
  175. aspose_pdf/engine/text_layout.py +574 -0
  176. aspose_pdf/engine/text_locate.py +423 -0
  177. aspose_pdf/engine/text_metrics.py +86 -0
  178. aspose_pdf/engine/text_outlines.py +150 -0
  179. aspose_pdf/engine/text_region.py +476 -0
  180. aspose_pdf/engine/text_selection.py +53 -0
  181. aspose_pdf/engine/text_split.py +141 -0
  182. aspose_pdf/engine/tiff_import.py +130 -0
  183. aspose_pdf/engine/timestamp.py +327 -0
  184. aspose_pdf/engine/toc.py +407 -0
  185. aspose_pdf/engine/type1_outlines.py +471 -0
  186. aspose_pdf/engine/viewer_preferences.py +275 -0
  187. aspose_pdf/engine/visual_comparison.py +318 -0
  188. aspose_pdf/engine/webp_encoder.py +107 -0
  189. aspose_pdf/engine/woff.py +302 -0
  190. aspose_pdf/engine/woff2.py +674 -0
  191. aspose_pdf/engine/word_extraction.py +235 -0
  192. aspose_pdf/exceptions.py +148 -0
  193. aspose_pdf/facades.py +1569 -0
  194. aspose_pdf/font_registry.py +149 -0
  195. aspose_pdf/font_repository.py +311 -0
  196. aspose_pdf/font_substitution.py +115 -0
  197. aspose_pdf/forms.py +1688 -0
  198. aspose_pdf/generated/__init__.py +3 -0
  199. aspose_pdf/generated/document.py +14 -0
  200. aspose_pdf/generated/forms.py +12 -0
  201. aspose_pdf/generated/pdfa.py +12 -0
  202. aspose_pdf/generated/security.py +33 -0
  203. aspose_pdf/geometry.py +149 -0
  204. aspose_pdf/graphics.py +256 -0
  205. aspose_pdf/html.py +117 -0
  206. aspose_pdf/image_resolution.py +45 -0
  207. aspose_pdf/images.py +524 -0
  208. aspose_pdf/interactive.py +435 -0
  209. aspose_pdf/latex.py +14 -0
  210. aspose_pdf/layers.py +482 -0
  211. aspose_pdf/license_management.py +65 -0
  212. aspose_pdf/link_extraction.py +52 -0
  213. aspose_pdf/link_validation.py +29 -0
  214. aspose_pdf/lists.py +365 -0
  215. aspose_pdf/load_limits.py +173 -0
  216. aspose_pdf/load_options.py +63 -0
  217. aspose_pdf/logical_structure.py +34 -0
  218. aspose_pdf/lowcode.py +1598 -0
  219. aspose_pdf/markdown.py +38 -0
  220. aspose_pdf/ofd.py +7 -0
  221. aspose_pdf/optimization.py +51 -0
  222. aspose_pdf/outlines.py +271 -0
  223. aspose_pdf/page_labels.py +169 -0
  224. aspose_pdf/page_ranges.py +90 -0
  225. aspose_pdf/page_size.py +220 -0
  226. aspose_pdf/pages.py +1883 -0
  227. aspose_pdf/paths.py +306 -0
  228. aspose_pdf/pdf_consts.py +19 -0
  229. aspose_pdf/pdfa.py +285 -0
  230. aspose_pdf/pdfua.py +194 -0
  231. aspose_pdf/pdfx.py +267 -0
  232. aspose_pdf/permissions.py +340 -0
  233. aspose_pdf/presentation.py +170 -0
  234. aspose_pdf/primitives.py +22 -0
  235. aspose_pdf/printing.py +41 -0
  236. aspose_pdf/py.typed +0 -0
  237. aspose_pdf/recipients.py +78 -0
  238. aspose_pdf/sanitization.py +90 -0
  239. aspose_pdf/save_format.py +25 -0
  240. aspose_pdf/save_options.py +25 -0
  241. aspose_pdf/security/__init__.py +160 -0
  242. aspose_pdf/security/impl/__init__.py +1 -0
  243. aspose_pdf/security/impl/digests/__init__.py +1 -0
  244. aspose_pdf/signature.py +385 -0
  245. aspose_pdf/signature_appearance.py +263 -0
  246. aspose_pdf/stamps.py +563 -0
  247. aspose_pdf/svg.py +41 -0
  248. aspose_pdf/table_extraction.py +156 -0
  249. aspose_pdf/tables.py +272 -0
  250. aspose_pdf/tagged.py +254 -0
  251. aspose_pdf/text.py +762 -0
  252. aspose_pdf/text_block.py +286 -0
  253. aspose_pdf/text_comparison.py +31 -0
  254. aspose_pdf/text_layout.py +100 -0
  255. aspose_pdf/utils.py +74 -0
  256. aspose_pdf/validation.py +286 -0
  257. aspose_pdf/viewer_preferences.py +375 -0
  258. aspose_pdf/visual_comparison.py +53 -0
  259. aspose_pdf/visualization.py +118 -0
  260. aspose_pdf/xmp.py +75 -0
  261. aspose_pdf_foss_for_python-0.1.0.dist-info/METADATA +2233 -0
  262. aspose_pdf_foss_for_python-0.1.0.dist-info/RECORD +265 -0
  263. aspose_pdf_foss_for_python-0.1.0.dist-info/WHEEL +5 -0
  264. aspose_pdf_foss_for_python-0.1.0.dist-info/licenses/LICENSE +21 -0
  265. aspose_pdf_foss_for_python-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,220 @@
1
+ """Named page sizes for authoring, in PDF points.
2
+
3
+ A PDF measures its pages in default user space units, which are 1/72 inch
4
+ (ISO 32000-1 8.3.2.3), so every size here is a point pair. The ISO A and B
5
+ sizes are defined in millimetres and the US sizes in inches, and both are
6
+ converted exactly rather than rounded to a printer's approximation: an A4 page
7
+ is 210 x 297 mm, which is 595.275591 x 841.889764 pt as the writer spells it.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import math
13
+ from dataclasses import dataclass
14
+ from typing import ClassVar
15
+
16
+ __all__ = ["PageSize"]
17
+
18
+ _POINTS_PER_INCH = 72.0
19
+ _MM_PER_INCH = 25.4
20
+
21
+
22
+ @dataclass(frozen=True, slots=True, eq=False)
23
+ class PageSize:
24
+ """A page's width and height in PDF points.
25
+
26
+ The named sizes are class attributes -- ``PageSize.A4``, ``PageSize.LETTER``
27
+ and the rest listed below -- and each one is *portrait*, the shorter side
28
+ first, which is how both ISO 216 and the US sizes are named. Turn one over
29
+ with :meth:`landscape`.
30
+
31
+ ISO A series: ``A0``, ``A1``, ``A2``, ``A3``, ``A4``, ``A5``, ``A6``.
32
+ ISO B series: ``B4``, ``B5``.
33
+ US sizes: ``LETTER``, ``LEGAL``, ``TABLOID``, ``LEDGER``, ``EXECUTIVE``,
34
+ ``STATEMENT``.
35
+
36
+ ``LETTER`` is the size a new page has when none is asked for, because it is
37
+ what this package has always created and what a ``/MediaBox`` that cannot
38
+ give a size falls back to.
39
+ """
40
+
41
+ width: float
42
+ height: float
43
+
44
+ # ClassVar, so the named sizes stay class attributes: an annotation without
45
+ # it would make each one a *field* of the dataclass and PageSize(w, h) would
46
+ # need seventeen arguments. They are assigned below the class body, which is
47
+ # the earliest a PageSize can be built.
48
+ A0: ClassVar[PageSize]
49
+ A1: ClassVar[PageSize]
50
+ A2: ClassVar[PageSize]
51
+ A3: ClassVar[PageSize]
52
+ A4: ClassVar[PageSize]
53
+ A5: ClassVar[PageSize]
54
+ A6: ClassVar[PageSize]
55
+ B4: ClassVar[PageSize]
56
+ B5: ClassVar[PageSize]
57
+ LETTER: ClassVar[PageSize]
58
+ LEGAL: ClassVar[PageSize]
59
+ TABLOID: ClassVar[PageSize]
60
+ LEDGER: ClassVar[PageSize]
61
+ EXECUTIVE: ClassVar[PageSize]
62
+ STATEMENT: ClassVar[PageSize]
63
+
64
+ def __post_init__(self) -> None:
65
+ object.__setattr__(self, "width", _positive(self.width, "width"))
66
+ object.__setattr__(self, "height", _positive(self.height, "height"))
67
+
68
+ @classmethod
69
+ def from_mm(cls, width: float, height: float) -> PageSize:
70
+ """A size given in millimetres, converted to points."""
71
+ # Multiplied before it is divided: 72 and the millimetres are both
72
+ # exact, so there is one rounding here instead of two, and the result is
73
+ # the number a caller gets computing it by hand.
74
+ return cls(
75
+ _positive(width, "width") * _POINTS_PER_INCH / _MM_PER_INCH,
76
+ _positive(height, "height") * _POINTS_PER_INCH / _MM_PER_INCH,
77
+ )
78
+
79
+ @classmethod
80
+ def from_inches(cls, width: float, height: float) -> PageSize:
81
+ """A size given in inches, converted to points."""
82
+ return cls(
83
+ _positive(width, "width") * _POINTS_PER_INCH,
84
+ _positive(height, "height") * _POINTS_PER_INCH,
85
+ )
86
+
87
+ @classmethod
88
+ def by_name(cls, name: str) -> PageSize:
89
+ """The named size *name* ("A4", "letter", "half letter", ...).
90
+
91
+ Case, spaces, hyphens and underscores are ignored, so a size read from a
92
+ configuration file or a command line needs no normalising first.
93
+ """
94
+ if not isinstance(name, str):
95
+ raise TypeError("page size name must be a string")
96
+ key = "".join(name.split()).replace("-", "").replace("_", "").upper()
97
+ try:
98
+ return _NAMED[key]
99
+ except KeyError:
100
+ known = ", ".join(sorted(_CANONICAL))
101
+ raise ValueError(f"Unknown page size {name!r}; known sizes: {known}") from None
102
+
103
+ def landscape(self) -> PageSize:
104
+ """This size with its longer side across: ``width >= height``."""
105
+ if self.width >= self.height:
106
+ return self
107
+ return PageSize(self.height, self.width)
108
+
109
+ def portrait(self) -> PageSize:
110
+ """This size with its longer side up: ``width <= height``."""
111
+ if self.width <= self.height:
112
+ return self
113
+ return PageSize(self.height, self.width)
114
+
115
+ def rotated(self) -> PageSize:
116
+ """This size with the two sides swapped, whichever way round it is."""
117
+ return PageSize(self.height, self.width)
118
+
119
+ def scaled(self, factor: float) -> PageSize:
120
+ """This size with both sides multiplied by *factor*."""
121
+ scale = _positive(factor, "factor")
122
+ return PageSize(self.width * scale, self.height * scale)
123
+
124
+ def __eq__(self, other: object) -> bool:
125
+ """Two sizes are equal when they write the same numbers into a file.
126
+
127
+ A PDF holds six decimal places (7.3.3), so an A4 page saved and reloaded
128
+ comes back as 595.275591 x 841.889764 -- the same sheet as
129
+ :attr:`PageSize.A4`, half a nanometre from it in floating point. Comparing
130
+ the rounded pair is what makes ``page.size == PageSize.A4`` true for a
131
+ document that has been through a save, which is the only answer that is
132
+ any use.
133
+ """
134
+ if not isinstance(other, PageSize):
135
+ return NotImplemented
136
+ return self._written() == other._written()
137
+
138
+ def __hash__(self) -> int:
139
+ return hash(self._written())
140
+
141
+ def _written(self) -> tuple[float, float]:
142
+ """The pair as a file would hold it: six decimal places."""
143
+ return (round(self.width, 6), round(self.height, 6))
144
+
145
+ def as_rect(self, x: float = 0.0, y: float = 0.0) -> tuple[float, float, float, float]:
146
+ """This size as a rectangle ``(x, y, x + width, y + height)``.
147
+
148
+ The origin defaults to ``(0, 0)``, where a page's own coordinate system
149
+ starts; a ``/MediaBox`` may sit elsewhere and this keeps that possible.
150
+ """
151
+ try:
152
+ x0, y0 = float(x), float(y)
153
+ except (TypeError, ValueError):
154
+ raise TypeError("rectangle origin must be two numbers") from None
155
+ if not (math.isfinite(x0) and math.isfinite(y0)):
156
+ raise ValueError("rectangle origin must be finite")
157
+ return (x0, y0, x0 + self.width, y0 + self.height)
158
+
159
+
160
+ def _positive(value: float, name: str) -> float:
161
+ """*value* as a finite positive float, or a refusal that names the field."""
162
+ if isinstance(value, bool):
163
+ raise TypeError(f"{name} must be a number")
164
+ try:
165
+ number = float(value)
166
+ except (TypeError, ValueError):
167
+ raise TypeError(f"{name} must be a number") from None
168
+ if not math.isfinite(number):
169
+ raise ValueError(f"{name} must be finite")
170
+ if number <= 0:
171
+ raise ValueError(f"{name} must be above zero")
172
+ return number
173
+
174
+
175
+ # ISO 216 defines the A series by halving A0, one square metre, and the B
176
+ # series between two neighbouring A sizes; both are stated in millimetres.
177
+ PageSize.A0 = PageSize.from_mm(841, 1189)
178
+ PageSize.A1 = PageSize.from_mm(594, 841)
179
+ PageSize.A2 = PageSize.from_mm(420, 594)
180
+ PageSize.A3 = PageSize.from_mm(297, 420)
181
+ PageSize.A4 = PageSize.from_mm(210, 297)
182
+ PageSize.A5 = PageSize.from_mm(148, 210)
183
+ PageSize.A6 = PageSize.from_mm(105, 148)
184
+ PageSize.B4 = PageSize.from_mm(250, 353)
185
+ PageSize.B5 = PageSize.from_mm(176, 250)
186
+
187
+ # The US sizes are whole inches or halves of one, so these are exact.
188
+ PageSize.LETTER = PageSize.from_inches(8.5, 11)
189
+ PageSize.LEGAL = PageSize.from_inches(8.5, 14)
190
+ PageSize.TABLOID = PageSize.from_inches(11, 17)
191
+ PageSize.LEDGER = PageSize.from_inches(17, 11)
192
+ PageSize.EXECUTIVE = PageSize.from_inches(7.25, 10.5)
193
+ PageSize.STATEMENT = PageSize.from_inches(5.5, 8.5)
194
+
195
+ #: The sizes :meth:`PageSize.by_name` knows, by their canonical name.
196
+ _CANONICAL: dict[str, PageSize] = {
197
+ "A0": PageSize.A0,
198
+ "A1": PageSize.A1,
199
+ "A2": PageSize.A2,
200
+ "A3": PageSize.A3,
201
+ "A4": PageSize.A4,
202
+ "A5": PageSize.A5,
203
+ "A6": PageSize.A6,
204
+ "B4": PageSize.B4,
205
+ "B5": PageSize.B5,
206
+ "LETTER": PageSize.LETTER,
207
+ "LEGAL": PageSize.LEGAL,
208
+ "TABLOID": PageSize.TABLOID,
209
+ "LEDGER": PageSize.LEDGER,
210
+ "EXECUTIVE": PageSize.EXECUTIVE,
211
+ "STATEMENT": PageSize.STATEMENT,
212
+ }
213
+
214
+ # Spellings a caller is as likely to write as the canonical one.
215
+ _NAMED: dict[str, PageSize] = {
216
+ **_CANONICAL,
217
+ "HALFLETTER": PageSize.STATEMENT,
218
+ "LEDGER11X17": PageSize.TABLOID,
219
+ "11X17": PageSize.TABLOID,
220
+ }