rgrid-python 4.5.3__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.
- grid_py/__init__.py +340 -0
- grid_py/_arrow.py +331 -0
- grid_py/_clippath.py +170 -0
- grid_py/_colour.py +815 -0
- grid_py/_coords.py +1534 -0
- grid_py/_curve.py +1668 -0
- grid_py/_display_list.py +507 -0
- grid_py/_draw.py +1397 -0
- grid_py/_edit.py +756 -0
- grid_py/_font_metrics.py +319 -0
- grid_py/_gpar.py +572 -0
- grid_py/_grab.py +501 -0
- grid_py/_grob.py +1377 -0
- grid_py/_group.py +798 -0
- grid_py/_highlevel.py +2176 -0
- grid_py/_just.py +361 -0
- grid_py/_layout.py +593 -0
- grid_py/_ls.py +895 -0
- grid_py/_mask.py +196 -0
- grid_py/_path.py +414 -0
- grid_py/_patterns.py +1049 -0
- grid_py/_primitives.py +2198 -0
- grid_py/_renderer_base.py +1184 -0
- grid_py/_scene_graph.py +248 -0
- grid_py/_size.py +1352 -0
- grid_py/_state.py +683 -0
- grid_py/_transforms.py +448 -0
- grid_py/_typeset.py +384 -0
- grid_py/_units.py +1924 -0
- grid_py/_utils.py +310 -0
- grid_py/_viewport.py +1649 -0
- grid_py/_vp_calc.py +970 -0
- grid_py/py.typed +0 -0
- grid_py/renderer.py +1762 -0
- grid_py/renderer_web.py +764 -0
- grid_py/resources/d3.v7.min.js +2 -0
- grid_py/resources/gridpy.css +80 -0
- grid_py/resources/gridpy.js +813 -0
- rgrid_python-4.5.3.dist-info/METADATA +489 -0
- rgrid_python-4.5.3.dist-info/RECORD +42 -0
- rgrid_python-4.5.3.dist-info/WHEEL +4 -0
- rgrid_python-4.5.3.dist-info/licenses/LICENSE +3 -0
grid_py/_typeset.py
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"""Glyph/typesetting support for grid_py (port of R's grid ``typeset.R``).
|
|
2
|
+
|
|
3
|
+
This module provides grob constructors for rendering pre-typeset glyph
|
|
4
|
+
information, mirroring R's ``glyphGrob()`` and ``grid.glyph()`` functions.
|
|
5
|
+
A *glyph grob* wraps a ``GlyphInfo`` object together with position,
|
|
6
|
+
justification, and graphical parameters, allowing the grid drawing
|
|
7
|
+
pipeline to render individual glyphs at specified locations.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import warnings
|
|
13
|
+
from typing import Any, Dict, List, Optional, Sequence, Union
|
|
14
|
+
|
|
15
|
+
from ._gpar import Gpar
|
|
16
|
+
from ._grob import Grob, grob_name
|
|
17
|
+
from ._units import Unit, is_unit
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"GlyphJust",
|
|
21
|
+
"glyph_just",
|
|
22
|
+
"GlyphInfo",
|
|
23
|
+
"glyph_grob",
|
|
24
|
+
"grid_glyph",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
# Glyph justification
|
|
30
|
+
# ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class GlyphJust:
|
|
34
|
+
"""Wrapper for glyph justification values.
|
|
35
|
+
|
|
36
|
+
In R, glyph justification can be a numeric proportion (0 = left/bottom,
|
|
37
|
+
1 = right/top) or a named anchor string (e.g. ``"left"``, ``"centre"``).
|
|
38
|
+
This class tags the value so that downstream code can distinguish between
|
|
39
|
+
numeric proportional justification and named-anchor justification.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
value : float, int, or str
|
|
44
|
+
The justification value. Strings such as ``"left"``, ``"centre"``,
|
|
45
|
+
``"center"``, ``"right"``, ``"top"``, ``"bottom"`` are accepted as
|
|
46
|
+
named anchors. Numeric values are interpreted as proportional
|
|
47
|
+
offsets (0.0 to 1.0).
|
|
48
|
+
name : str or None, optional
|
|
49
|
+
An optional width/height name to associate with a numeric
|
|
50
|
+
justification (mirrors R's ``names(hjust)``).
|
|
51
|
+
|
|
52
|
+
Attributes
|
|
53
|
+
----------
|
|
54
|
+
value : float or str
|
|
55
|
+
The justification value.
|
|
56
|
+
name : str or None
|
|
57
|
+
Optional name qualifier.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
__slots__ = ("value", "name")
|
|
61
|
+
|
|
62
|
+
def __init__(
|
|
63
|
+
self,
|
|
64
|
+
value: Union[float, int, str],
|
|
65
|
+
name: Optional[str] = None,
|
|
66
|
+
) -> None:
|
|
67
|
+
self.value: Union[float, str] = value
|
|
68
|
+
self.name: Optional[str] = name
|
|
69
|
+
|
|
70
|
+
def __repr__(self) -> str:
|
|
71
|
+
if self.name is not None:
|
|
72
|
+
return f"GlyphJust(value={self.value!r}, name={self.name!r})"
|
|
73
|
+
return f"GlyphJust(value={self.value!r})"
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def is_numeric(self) -> bool:
|
|
77
|
+
"""Return ``True`` if this justification is a numeric proportion."""
|
|
78
|
+
return isinstance(self.value, (int, float))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def glyph_just(value: Union[float, int, str, "GlyphJust"]) -> GlyphJust:
|
|
82
|
+
"""Normalise a justification value into a :class:`GlyphJust`.
|
|
83
|
+
|
|
84
|
+
Parameters
|
|
85
|
+
----------
|
|
86
|
+
value : float, int, str, or GlyphJust
|
|
87
|
+
If already a ``GlyphJust``, return as-is. Strings are mapped to
|
|
88
|
+
canonical anchor names; numeric values are wrapped directly.
|
|
89
|
+
|
|
90
|
+
Returns
|
|
91
|
+
-------
|
|
92
|
+
GlyphJust
|
|
93
|
+
A validated glyph-justification object.
|
|
94
|
+
|
|
95
|
+
Raises
|
|
96
|
+
------
|
|
97
|
+
TypeError
|
|
98
|
+
If *value* is not a recognised type.
|
|
99
|
+
"""
|
|
100
|
+
if isinstance(value, GlyphJust):
|
|
101
|
+
return value
|
|
102
|
+
|
|
103
|
+
if isinstance(value, str):
|
|
104
|
+
canonical = _JUST_ALIASES.get(value.lower(), value.lower())
|
|
105
|
+
return GlyphJust(canonical)
|
|
106
|
+
|
|
107
|
+
if isinstance(value, (int, float)):
|
|
108
|
+
return GlyphJust(float(value))
|
|
109
|
+
|
|
110
|
+
raise TypeError(
|
|
111
|
+
f"'hjust'/'vjust' must be numeric or a string, got {type(value).__name__}"
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
_JUST_ALIASES: Dict[str, str] = {
|
|
116
|
+
"center": "centre",
|
|
117
|
+
"left": "left",
|
|
118
|
+
"right": "right",
|
|
119
|
+
"top": "top",
|
|
120
|
+
"bottom": "bottom",
|
|
121
|
+
"centre": "centre",
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
# ---------------------------------------------------------------------------
|
|
126
|
+
# GlyphInfo (minimal container)
|
|
127
|
+
# ---------------------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class GlyphInfo:
|
|
131
|
+
"""Container for pre-typeset glyph information.
|
|
132
|
+
|
|
133
|
+
This is a lightweight Python analogue of R's ``RGlyphInfo`` objects
|
|
134
|
+
produced by typesetting engines (e.g. ``systemfonts::shape_string``).
|
|
135
|
+
It carries per-glyph positions, font information, and overall bounding
|
|
136
|
+
metrics.
|
|
137
|
+
|
|
138
|
+
Parameters
|
|
139
|
+
----------
|
|
140
|
+
glyphs : dict
|
|
141
|
+
Per-glyph data. Expected keys include ``"x"``, ``"y"``, and
|
|
142
|
+
optionally ``"font"``, ``"size"``, ``"rot"``, ``"colour"``.
|
|
143
|
+
width : dict or float
|
|
144
|
+
Overall width(s) of the typeset block in big points. May be a
|
|
145
|
+
dict mapping names to widths.
|
|
146
|
+
height : dict or float
|
|
147
|
+
Overall height(s) of the typeset block in big points.
|
|
148
|
+
h_anchor : dict or None, optional
|
|
149
|
+
Named horizontal anchors (e.g. ``{"left": 0, "right": 100}``).
|
|
150
|
+
v_anchor : dict or None, optional
|
|
151
|
+
Named vertical anchors (e.g. ``{"bottom": 0, "top": 80}``).
|
|
152
|
+
|
|
153
|
+
Attributes
|
|
154
|
+
----------
|
|
155
|
+
glyphs : dict
|
|
156
|
+
width : dict or float
|
|
157
|
+
height : dict or float
|
|
158
|
+
h_anchor : dict
|
|
159
|
+
v_anchor : dict
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
def __init__(
|
|
163
|
+
self,
|
|
164
|
+
glyphs: Dict[str, Any],
|
|
165
|
+
width: Union[Dict[str, float], float],
|
|
166
|
+
height: Union[Dict[str, float], float],
|
|
167
|
+
h_anchor: Optional[Dict[str, float]] = None,
|
|
168
|
+
v_anchor: Optional[Dict[str, float]] = None,
|
|
169
|
+
) -> None:
|
|
170
|
+
self.glyphs = glyphs
|
|
171
|
+
self.width = width
|
|
172
|
+
self.height = height
|
|
173
|
+
self.h_anchor = h_anchor if h_anchor is not None else {"left": 0.0}
|
|
174
|
+
self.v_anchor = v_anchor if v_anchor is not None else {"bottom": 0.0}
|
|
175
|
+
|
|
176
|
+
def __repr__(self) -> str:
|
|
177
|
+
n = len(self.glyphs.get("x", []))
|
|
178
|
+
return f"GlyphInfo(n_glyphs={n})"
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
# ---------------------------------------------------------------------------
|
|
182
|
+
# Validation helper
|
|
183
|
+
# ---------------------------------------------------------------------------
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _valid_glyph_grob(x: Grob) -> Grob:
|
|
187
|
+
"""Validate a glyph grob (mirrors R's ``validDetails.glyphgrob``).
|
|
188
|
+
|
|
189
|
+
Parameters
|
|
190
|
+
----------
|
|
191
|
+
x : Grob
|
|
192
|
+
The grob to validate.
|
|
193
|
+
|
|
194
|
+
Returns
|
|
195
|
+
-------
|
|
196
|
+
Grob
|
|
197
|
+
The validated grob (unchanged if valid).
|
|
198
|
+
|
|
199
|
+
Raises
|
|
200
|
+
------
|
|
201
|
+
TypeError
|
|
202
|
+
If *glyphInfo* is not a :class:`GlyphInfo`, or if *x*/*y* are not
|
|
203
|
+
units, or if justification values are invalid.
|
|
204
|
+
ValueError
|
|
205
|
+
If *x*/*y* have length < 1, or justification values have length != 1.
|
|
206
|
+
"""
|
|
207
|
+
glyph_info = getattr(x, "glyphInfo", None)
|
|
208
|
+
if not isinstance(glyph_info, GlyphInfo):
|
|
209
|
+
raise TypeError("Invalid glyph info; expected a GlyphInfo instance")
|
|
210
|
+
|
|
211
|
+
grob_x = getattr(x, "x", None)
|
|
212
|
+
grob_y = getattr(x, "y", None)
|
|
213
|
+
if not is_unit(grob_x) or not is_unit(grob_y):
|
|
214
|
+
raise TypeError("'x' and 'y' must be Unit objects")
|
|
215
|
+
|
|
216
|
+
if len(grob_x) < 1 or len(grob_y) < 1:
|
|
217
|
+
raise ValueError("'x' and 'y' must have length > 0")
|
|
218
|
+
|
|
219
|
+
hjust = getattr(x, "hjust", None)
|
|
220
|
+
vjust = getattr(x, "vjust", None)
|
|
221
|
+
if not isinstance(hjust, GlyphJust) or not isinstance(vjust, GlyphJust):
|
|
222
|
+
raise TypeError("'hjust' and 'vjust' must be GlyphJust values")
|
|
223
|
+
|
|
224
|
+
return x
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
# ---------------------------------------------------------------------------
|
|
228
|
+
# Glyph grob constructor
|
|
229
|
+
# ---------------------------------------------------------------------------
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def glyph_grob(
|
|
233
|
+
glyphInfo: GlyphInfo,
|
|
234
|
+
x: Union[float, Unit] = 0.5,
|
|
235
|
+
y: Union[float, Unit] = 0.5,
|
|
236
|
+
default_units: str = "npc",
|
|
237
|
+
hjust: Union[float, str, GlyphJust] = "centre",
|
|
238
|
+
vjust: Union[float, str, GlyphJust] = "centre",
|
|
239
|
+
gp: Optional[Gpar] = None,
|
|
240
|
+
vp: Optional[Any] = None,
|
|
241
|
+
name: Optional[str] = None,
|
|
242
|
+
) -> Grob:
|
|
243
|
+
"""Create a glyph grob for rendering pre-typeset glyph information.
|
|
244
|
+
|
|
245
|
+
This mirrors R's ``glyphGrob()`` function. The resulting :class:`Grob`
|
|
246
|
+
has ``_grid_class="glyphgrob"`` and carries the glyph data, position,
|
|
247
|
+
and justification as attributes.
|
|
248
|
+
|
|
249
|
+
Parameters
|
|
250
|
+
----------
|
|
251
|
+
glyphInfo : GlyphInfo
|
|
252
|
+
The pre-typeset glyph information to render.
|
|
253
|
+
x : float or Unit, optional
|
|
254
|
+
Horizontal position of the glyph block (default ``0.5``).
|
|
255
|
+
y : float or Unit, optional
|
|
256
|
+
Vertical position of the glyph block (default ``0.5``).
|
|
257
|
+
default_units : str, optional
|
|
258
|
+
Unit type for *x* and *y* when they are plain numbers
|
|
259
|
+
(default ``"npc"``).
|
|
260
|
+
hjust : float, str, or GlyphJust, optional
|
|
261
|
+
Horizontal justification (default ``"centre"``).
|
|
262
|
+
vjust : float, str, or GlyphJust, optional
|
|
263
|
+
Vertical justification (default ``"centre"``).
|
|
264
|
+
gp : Gpar or None, optional
|
|
265
|
+
Graphical parameters.
|
|
266
|
+
vp : object or None, optional
|
|
267
|
+
Viewport.
|
|
268
|
+
name : str or None, optional
|
|
269
|
+
Grob name. Auto-generated when ``None``.
|
|
270
|
+
|
|
271
|
+
Returns
|
|
272
|
+
-------
|
|
273
|
+
Grob
|
|
274
|
+
A grob with ``_grid_class="glyphgrob"`` ready for drawing.
|
|
275
|
+
|
|
276
|
+
Raises
|
|
277
|
+
------
|
|
278
|
+
TypeError
|
|
279
|
+
If *glyphInfo* is not a :class:`GlyphInfo`.
|
|
280
|
+
|
|
281
|
+
Examples
|
|
282
|
+
--------
|
|
283
|
+
>>> info = GlyphInfo({"x": [0], "y": [0]}, width=10.0, height=12.0)
|
|
284
|
+
>>> g = glyph_grob(info)
|
|
285
|
+
>>> g._grid_class
|
|
286
|
+
'glyphgrob'
|
|
287
|
+
"""
|
|
288
|
+
# Coerce x/y to Unit if needed
|
|
289
|
+
if not is_unit(x):
|
|
290
|
+
x = Unit(x, default_units)
|
|
291
|
+
if not is_unit(y):
|
|
292
|
+
y = Unit(y, default_units)
|
|
293
|
+
|
|
294
|
+
# Normalise justification
|
|
295
|
+
hjust_val = glyph_just(hjust)
|
|
296
|
+
vjust_val = glyph_just(vjust)
|
|
297
|
+
|
|
298
|
+
grob_obj = Grob(
|
|
299
|
+
name=name,
|
|
300
|
+
gp=gp if gp is not None else Gpar(),
|
|
301
|
+
vp=vp,
|
|
302
|
+
_grid_class="glyphgrob",
|
|
303
|
+
glyphInfo=glyphInfo,
|
|
304
|
+
x=x,
|
|
305
|
+
y=y,
|
|
306
|
+
hjust=hjust_val,
|
|
307
|
+
vjust=vjust_val,
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
# Validate
|
|
311
|
+
_valid_glyph_grob(grob_obj)
|
|
312
|
+
|
|
313
|
+
return grob_obj
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
# ---------------------------------------------------------------------------
|
|
317
|
+
# grid.glyph equivalent
|
|
318
|
+
# ---------------------------------------------------------------------------
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def grid_glyph(
|
|
322
|
+
glyphInfo: GlyphInfo,
|
|
323
|
+
x: Union[float, Unit] = 0.5,
|
|
324
|
+
y: Union[float, Unit] = 0.5,
|
|
325
|
+
default_units: str = "npc",
|
|
326
|
+
hjust: Union[float, str, GlyphJust] = "centre",
|
|
327
|
+
vjust: Union[float, str, GlyphJust] = "centre",
|
|
328
|
+
gp: Optional[Gpar] = None,
|
|
329
|
+
vp: Optional[Any] = None,
|
|
330
|
+
name: Optional[str] = None,
|
|
331
|
+
draw: bool = True,
|
|
332
|
+
) -> Grob:
|
|
333
|
+
"""Create and optionally draw a glyph grob.
|
|
334
|
+
|
|
335
|
+
This is the high-level interface mirroring R's ``grid.glyph()``. It
|
|
336
|
+
constructs a glyph grob via :func:`glyph_grob` and, when *draw* is
|
|
337
|
+
``True``, immediately renders it by calling ``grid_draw``.
|
|
338
|
+
|
|
339
|
+
Parameters
|
|
340
|
+
----------
|
|
341
|
+
glyphInfo : GlyphInfo
|
|
342
|
+
The pre-typeset glyph information.
|
|
343
|
+
x : float or Unit, optional
|
|
344
|
+
Horizontal position (default ``0.5``).
|
|
345
|
+
y : float or Unit, optional
|
|
346
|
+
Vertical position (default ``0.5``).
|
|
347
|
+
default_units : str, optional
|
|
348
|
+
Unit type when *x*/*y* are plain numbers (default ``"npc"``).
|
|
349
|
+
hjust : float, str, or GlyphJust, optional
|
|
350
|
+
Horizontal justification (default ``"centre"``).
|
|
351
|
+
vjust : float, str, or GlyphJust, optional
|
|
352
|
+
Vertical justification (default ``"centre"``).
|
|
353
|
+
gp : Gpar or None, optional
|
|
354
|
+
Graphical parameters.
|
|
355
|
+
vp : object or None, optional
|
|
356
|
+
Viewport.
|
|
357
|
+
name : str or None, optional
|
|
358
|
+
Grob name.
|
|
359
|
+
draw : bool, optional
|
|
360
|
+
If ``True`` (default), the grob is drawn immediately.
|
|
361
|
+
|
|
362
|
+
Returns
|
|
363
|
+
-------
|
|
364
|
+
Grob
|
|
365
|
+
The glyph grob (returned invisibly in R; here simply returned).
|
|
366
|
+
"""
|
|
367
|
+
g = glyph_grob(
|
|
368
|
+
glyphInfo=glyphInfo,
|
|
369
|
+
x=x,
|
|
370
|
+
y=y,
|
|
371
|
+
default_units=default_units,
|
|
372
|
+
hjust=hjust,
|
|
373
|
+
vjust=vjust,
|
|
374
|
+
gp=gp,
|
|
375
|
+
vp=vp,
|
|
376
|
+
name=name,
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
if draw:
|
|
380
|
+
from ._draw import grid_draw
|
|
381
|
+
|
|
382
|
+
grid_draw(g)
|
|
383
|
+
|
|
384
|
+
return g
|