reportlab-layout 1.0.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.
- reportlab_layout/__init__.py +69 -0
- reportlab_layout/boxes.py +30 -0
- reportlab_layout/colors.py +31 -0
- reportlab_layout/cursor.py +58 -0
- reportlab_layout/document.py +525 -0
- reportlab_layout/frames.py +36 -0
- reportlab_layout/geometry.py +138 -0
- reportlab_layout/images.py +79 -0
- reportlab_layout/metrics.py +204 -0
- reportlab_layout/numbering.py +69 -0
- reportlab_layout/py.typed +0 -0
- reportlab_layout/shapes.py +103 -0
- reportlab_layout/styles.py +84 -0
- reportlab_layout/text.py +80 -0
- reportlab_layout-1.0.0.dist-info/METADATA +242 -0
- reportlab_layout-1.0.0.dist-info/RECORD +18 -0
- reportlab_layout-1.0.0.dist-info/WHEEL +4 -0
- reportlab_layout-1.0.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Une couche de mise en page à curseur au-dessus de reportlab.
|
|
2
|
+
|
|
3
|
+
Le canvas de reportlab dessine où on lui dit, en points, depuis le coin
|
|
4
|
+
bas-gauche. Ses ``platypus`` templates, à l'inverse, gèrent le flux mais
|
|
5
|
+
reprennent la main sur la page entière. Ce paquet occupe l'espace entre les
|
|
6
|
+
deux : un curseur qui descend dans la page, et le canvas resté accessible pour
|
|
7
|
+
tout ce qui doit être placé au point près.
|
|
8
|
+
|
|
9
|
+
from reportlab_layout import PDFMaker
|
|
10
|
+
|
|
11
|
+
with PDFMaker("bulletin.pdf", top=20) as doc:
|
|
12
|
+
doc.draw_paragraph("Bulletin du 3e trimestre", "Heading1 Centered")
|
|
13
|
+
doc.add_space()
|
|
14
|
+
doc.draw_table([["Matière", "Note"], ["Maths", "17"]])
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from reportlab_layout.boxes import Box
|
|
18
|
+
from reportlab_layout.colors import ColorLike, to_color
|
|
19
|
+
from reportlab_layout.cursor import Cursor
|
|
20
|
+
from reportlab_layout.document import PDFMaker
|
|
21
|
+
from reportlab_layout.frames import FrameWriter
|
|
22
|
+
from reportlab_layout.geometry import Margins, PageGeometry, resolve_pagesize
|
|
23
|
+
from reportlab_layout.images import ImageSpec, image_spec, load_image
|
|
24
|
+
from reportlab_layout.metrics import (
|
|
25
|
+
TextMetrics,
|
|
26
|
+
baseline_offset,
|
|
27
|
+
cap_height,
|
|
28
|
+
font_ascent,
|
|
29
|
+
font_descent,
|
|
30
|
+
font_height,
|
|
31
|
+
string_width,
|
|
32
|
+
)
|
|
33
|
+
from reportlab_layout.numbering import NumberedCanvas
|
|
34
|
+
from reportlab_layout.shapes import ShapePainter
|
|
35
|
+
from reportlab_layout.styles import STYLES, StyleLike, add_style, make_stylesheet, resolve_style
|
|
36
|
+
from reportlab_layout.text import TextPainter
|
|
37
|
+
|
|
38
|
+
__version__ = "1.0.0"
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"STYLES",
|
|
42
|
+
"Box",
|
|
43
|
+
"ColorLike",
|
|
44
|
+
"Cursor",
|
|
45
|
+
"FrameWriter",
|
|
46
|
+
"ImageSpec",
|
|
47
|
+
"Margins",
|
|
48
|
+
"NumberedCanvas",
|
|
49
|
+
"PDFMaker",
|
|
50
|
+
"PageGeometry",
|
|
51
|
+
"ShapePainter",
|
|
52
|
+
"StyleLike",
|
|
53
|
+
"TextMetrics",
|
|
54
|
+
"TextPainter",
|
|
55
|
+
"__version__",
|
|
56
|
+
"add_style",
|
|
57
|
+
"baseline_offset",
|
|
58
|
+
"cap_height",
|
|
59
|
+
"font_ascent",
|
|
60
|
+
"font_descent",
|
|
61
|
+
"font_height",
|
|
62
|
+
"image_spec",
|
|
63
|
+
"load_image",
|
|
64
|
+
"make_stylesheet",
|
|
65
|
+
"resolve_pagesize",
|
|
66
|
+
"resolve_style",
|
|
67
|
+
"string_width",
|
|
68
|
+
"to_color",
|
|
69
|
+
]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Rectangle rendu par une opération de tracé."""
|
|
2
|
+
|
|
3
|
+
from typing import NamedTuple
|
|
4
|
+
|
|
5
|
+
__all__ = ["Box"]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Box(NamedTuple):
|
|
9
|
+
"""Rectangle effectivement occupé par un élément dessiné, repère canvas.
|
|
10
|
+
|
|
11
|
+
Se déballe comme un quadruplet ``(x, y, width, height)``. ``x, y`` est le
|
|
12
|
+
coin **bas-gauche**, comme partout dans reportlab.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
x: float
|
|
16
|
+
y: float
|
|
17
|
+
width: float
|
|
18
|
+
height: float
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def right(self) -> float:
|
|
22
|
+
return self.x + self.width
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def top(self) -> float:
|
|
26
|
+
return self.y + self.height
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def center(self) -> tuple[float, float]:
|
|
30
|
+
return (self.x + self.width / 2, self.y + self.height / 2)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Conversion des couleurs vers le type attendu par reportlab."""
|
|
2
|
+
|
|
3
|
+
from typing import TypeAlias
|
|
4
|
+
|
|
5
|
+
from reportlab.lib.colors import Color, HexColor, toColor
|
|
6
|
+
|
|
7
|
+
__all__ = ["ColorLike", "to_color"]
|
|
8
|
+
|
|
9
|
+
#: Tout ce qui peut désigner une couleur dans ce paquet. ``None`` signifie
|
|
10
|
+
#: « conserver la couleur courante du canvas ».
|
|
11
|
+
ColorLike: TypeAlias = Color | str | tuple[float, ...] | list[float] | None
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def to_color(value: ColorLike) -> Color | None:
|
|
15
|
+
"""Normalise une couleur en ``reportlab.lib.colors.Color``.
|
|
16
|
+
|
|
17
|
+
Accepte un ``Color``, un nom CSS ou une chaîne ``"#rrggbb"``, un triplet ou
|
|
18
|
+
quadruplet de flottants dans ``[0, 1]``. ``None`` est rendu tel quel : il
|
|
19
|
+
signifie « ne pas toucher à la couleur courante ».
|
|
20
|
+
"""
|
|
21
|
+
if value is None or isinstance(value, Color):
|
|
22
|
+
return value
|
|
23
|
+
if isinstance(value, str):
|
|
24
|
+
return HexColor(value) if value.startswith("#") else toColor(value)
|
|
25
|
+
if isinstance(value, tuple | list):
|
|
26
|
+
if len(value) == 3:
|
|
27
|
+
return Color(*value)
|
|
28
|
+
if len(value) == 4:
|
|
29
|
+
return Color(value[0], value[1], value[2], alpha=value[3])
|
|
30
|
+
raise ValueError(f"Un tuple de couleur doit avoir 3 ou 4 composantes, reçu {len(value)}")
|
|
31
|
+
raise TypeError(f"Couleur non convertible : {value!r}")
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Curseur de flux : profondeur d'écriture courante dans la page."""
|
|
2
|
+
|
|
3
|
+
__all__ = ["Cursor"]
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Cursor:
|
|
7
|
+
"""Suit la profondeur d'écriture, mesurée depuis le haut de la page.
|
|
8
|
+
|
|
9
|
+
La profondeur croît vers le bas, contrairement à l'ordonnée du canvas
|
|
10
|
+
reportlab. La conversion est du ressort de
|
|
11
|
+
:class:`~reportlab_layout.geometry.PageGeometry`.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, top: float, bottom_depth: float) -> None:
|
|
15
|
+
self._top = top
|
|
16
|
+
self._bottom_depth = bottom_depth
|
|
17
|
+
self._depth = top
|
|
18
|
+
|
|
19
|
+
def __repr__(self) -> str:
|
|
20
|
+
return f"Cursor(depth={self._depth:.1f}, remaining={self.remaining:.1f})"
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def depth(self) -> float:
|
|
24
|
+
"""Profondeur courante, en points."""
|
|
25
|
+
return self._depth
|
|
26
|
+
|
|
27
|
+
@depth.setter
|
|
28
|
+
def depth(self, value: float) -> None:
|
|
29
|
+
self._depth = float(value)
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def top(self) -> float:
|
|
33
|
+
"""Profondeur de départ, c'est-à-dire la marge haute."""
|
|
34
|
+
return self._top
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def bottom_depth(self) -> float:
|
|
38
|
+
"""Profondeur de la limite basse de la zone de contenu."""
|
|
39
|
+
return self._bottom_depth
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def remaining(self) -> float:
|
|
43
|
+
"""Hauteur restante avant la marge basse. Négative en cas de débordement."""
|
|
44
|
+
return self._bottom_depth - self._depth
|
|
45
|
+
|
|
46
|
+
def fits(self, height: float) -> bool:
|
|
47
|
+
"""Vrai si un élément de hauteur ``height`` tient encore sur la page."""
|
|
48
|
+
return height <= self.remaining
|
|
49
|
+
|
|
50
|
+
def reset(self) -> float:
|
|
51
|
+
"""Ramène le curseur en haut de la zone de contenu."""
|
|
52
|
+
self._depth = self._top
|
|
53
|
+
return self._depth
|
|
54
|
+
|
|
55
|
+
def advance(self, height: float) -> float:
|
|
56
|
+
"""Descend le curseur de ``height`` points et rend la nouvelle profondeur."""
|
|
57
|
+
self._depth += height
|
|
58
|
+
return self._depth
|