rendercanvas 1.0.0__tar.gz
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.
- rendercanvas-1.0.0/LICENSE +25 -0
- rendercanvas-1.0.0/PKG-INFO +160 -0
- rendercanvas-1.0.0/README.md +122 -0
- rendercanvas-1.0.0/pyproject.toml +61 -0
- rendercanvas-1.0.0/rendercanvas/__init__.py +17 -0
- rendercanvas-1.0.0/rendercanvas/__pyinstaller/__init__.py +12 -0
- rendercanvas-1.0.0/rendercanvas/__pyinstaller/conftest.py +1 -0
- rendercanvas-1.0.0/rendercanvas/__pyinstaller/hook-rendercanvas.py +22 -0
- rendercanvas-1.0.0/rendercanvas/__pyinstaller/test_rendercanvas.py +47 -0
- rendercanvas-1.0.0/rendercanvas/_context.py +78 -0
- rendercanvas-1.0.0/rendercanvas/_coreutils.py +264 -0
- rendercanvas-1.0.0/rendercanvas/_events.py +218 -0
- rendercanvas-1.0.0/rendercanvas/_loop.py +456 -0
- rendercanvas-1.0.0/rendercanvas/_version.py +113 -0
- rendercanvas-1.0.0/rendercanvas/asyncio.py +76 -0
- rendercanvas-1.0.0/rendercanvas/auto.py +206 -0
- rendercanvas-1.0.0/rendercanvas/base.py +568 -0
- rendercanvas-1.0.0/rendercanvas/glfw.py +570 -0
- rendercanvas-1.0.0/rendercanvas/jupyter.py +150 -0
- rendercanvas-1.0.0/rendercanvas/offscreen.py +135 -0
- rendercanvas-1.0.0/rendercanvas/pyqt5.py +11 -0
- rendercanvas-1.0.0/rendercanvas/pyqt6.py +11 -0
- rendercanvas-1.0.0/rendercanvas/pyside2.py +11 -0
- rendercanvas-1.0.0/rendercanvas/pyside6.py +11 -0
- rendercanvas-1.0.0/rendercanvas/qt.py +588 -0
- rendercanvas-1.0.0/rendercanvas/stub.py +120 -0
- rendercanvas-1.0.0/rendercanvas/utils/__init__.py +0 -0
- rendercanvas-1.0.0/rendercanvas/utils/bitmappresentadapter.py +344 -0
- rendercanvas-1.0.0/rendercanvas/utils/bitmaprenderingcontext.py +101 -0
- rendercanvas-1.0.0/rendercanvas/utils/cube.py +446 -0
- rendercanvas-1.0.0/rendercanvas/wx.py +522 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
BSD 2-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019-2024, Almar Klein, Korijn van Golen
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
17
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
18
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
19
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
20
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
21
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
22
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
23
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
24
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
25
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: rendercanvas
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: One canvas API, multiple backends
|
|
5
|
+
Keywords: canvas,rendering,graphics,wgpu,qt,wx,glfw,jupyter
|
|
6
|
+
Author: Almar Klein, Korijn van Golen
|
|
7
|
+
Requires-Python: >= 3.9
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: rendercanvas[lint,tests,examples,docs] ; extra == "dev"
|
|
10
|
+
Requires-Dist: sphinx>7.2 ; extra == "docs"
|
|
11
|
+
Requires-Dist: sphinx_rtd_theme ; extra == "docs"
|
|
12
|
+
Requires-Dist: sphinx-gallery ; extra == "docs"
|
|
13
|
+
Requires-Dist: numpy ; extra == "docs"
|
|
14
|
+
Requires-Dist: wgpu ; extra == "docs"
|
|
15
|
+
Requires-Dist: numpy ; extra == "examples"
|
|
16
|
+
Requires-Dist: wgpu ; extra == "examples"
|
|
17
|
+
Requires-Dist: glfw ; extra == "examples"
|
|
18
|
+
Requires-Dist: pyside6 ; extra == "examples"
|
|
19
|
+
Requires-Dist: glfw>=1.9 ; extra == "glfw"
|
|
20
|
+
Requires-Dist: jupyter_rfb>=0.4.2 ; extra == "jupyter"
|
|
21
|
+
Requires-Dist: ruff ; extra == "lint"
|
|
22
|
+
Requires-Dist: pre-commit ; extra == "lint"
|
|
23
|
+
Requires-Dist: pytest ; extra == "tests"
|
|
24
|
+
Requires-Dist: numpy ; extra == "tests"
|
|
25
|
+
Requires-Dist: wgpu ; extra == "tests"
|
|
26
|
+
Requires-Dist: glfw ; extra == "tests"
|
|
27
|
+
Project-URL: Documentation, https://rendercanvas.readthedocs.io
|
|
28
|
+
Project-URL: Homepage, https://github.com/pygfx/rendercanvas
|
|
29
|
+
Project-URL: Repository, https://github.com/pygfx/rendercanvas
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Provides-Extra: docs
|
|
32
|
+
Provides-Extra: examples
|
|
33
|
+
Provides-Extra: glfw
|
|
34
|
+
Provides-Extra: jupyter
|
|
35
|
+
Provides-Extra: lint
|
|
36
|
+
Provides-Extra: tests
|
|
37
|
+
|
|
38
|
+
[](https://github.com/pygfx/rendercanvas/actions)
|
|
39
|
+
[](https://rendercanvas.readthedocs.io)
|
|
40
|
+
[](https://badge.fury.io/py/rendercanvas)
|
|
41
|
+
[](https://jacobtomlinson.dev/effver)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# rendercanvas
|
|
45
|
+
|
|
46
|
+
One canvas API, multiple backends 🚀
|
|
47
|
+
|
|
48
|
+
<div>
|
|
49
|
+
<img width=354 src='https://github.com/user-attachments/assets/42656d13-0d81-47dd-b9c7-d76da8cfa6c1' />
|
|
50
|
+
<img width=354 src='https://github.com/user-attachments/assets/af8eefe0-4485-4daf-9fbd-36710e44f07c' />
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
*This project is part of [pygfx.org](https://pygfx.org)*
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
## Introduction
|
|
57
|
+
|
|
58
|
+
See how the two windows above look the same? That's the idea; they also look the
|
|
59
|
+
same to the code that renders to them. Yet, the GUI systems are very different
|
|
60
|
+
(Qt vs glfw in this case). Now that's a powerful abstraction!
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## Purpose
|
|
64
|
+
|
|
65
|
+
* Provide a generic canvas API to render to.
|
|
66
|
+
* Provide an event loop for scheduling events and draws.
|
|
67
|
+
* Provide a simple but powerful event system with standardized event objects.
|
|
68
|
+
* Provide various canvas implementations:
|
|
69
|
+
* One that is light and easily installed (glfw).
|
|
70
|
+
* For various GUI libraries (e.g. qt and wx), so visuzalizations can be embedded in a GUI.
|
|
71
|
+
* For specific platforms (e.g. Jupyter, browser).
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
The main use-case is rendering with [wgpu](https://github.com/pygfx/wgpu-py),
|
|
75
|
+
but ``rendercanvas``can be used by anything that can render based on a window-id or
|
|
76
|
+
by producing bitmap images.
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
## Installation
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
pip install rendercanvas
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
To have at least one backend, we recommend:
|
|
86
|
+
```
|
|
87
|
+
pip install rendercanvas glfw
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Usage
|
|
91
|
+
|
|
92
|
+
Also see the [online documentation](https://rendercanvas.readthedocs.io) and the [examples](https://github.com/pygfx/rendercanvas/tree/main/examples).
|
|
93
|
+
|
|
94
|
+
A minimal example that renders noise:
|
|
95
|
+
```py
|
|
96
|
+
import numpy as np
|
|
97
|
+
from rendercanvas.auto import RenderCanvas, loop
|
|
98
|
+
|
|
99
|
+
canvas = RenderCanvas(update_mode="continuous")
|
|
100
|
+
context = canvas.get_context("bitmap")
|
|
101
|
+
|
|
102
|
+
@canvas.request_draw
|
|
103
|
+
def animate():
|
|
104
|
+
w, h = canvas.get_logical_size()
|
|
105
|
+
bitmap = np.random.uniform(0, 255, (h, w)).astype(np.uint8)
|
|
106
|
+
context.set_bitmap(bitmap)
|
|
107
|
+
|
|
108
|
+
loop.run()
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Run wgpu visualizations:
|
|
112
|
+
```py
|
|
113
|
+
from rendercanvas.auto import RenderCanvas, loop
|
|
114
|
+
from rendercanvas.utils.cube import setup_drawing_sync
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
canvas = RenderCanvas(
|
|
118
|
+
title="The wgpu cube example on $backend", update_mode="continuous"
|
|
119
|
+
)
|
|
120
|
+
draw_frame = setup_drawing_sync(canvas)
|
|
121
|
+
canvas.request_draw(draw_frame)
|
|
122
|
+
|
|
123
|
+
loop.run()
|
|
124
|
+
````
|
|
125
|
+
|
|
126
|
+
Embed in a Qt application:
|
|
127
|
+
```py
|
|
128
|
+
from PySide6 import QtWidgets
|
|
129
|
+
from rendercanvas.qt import QRenderWidget
|
|
130
|
+
|
|
131
|
+
class Main(QtWidgets.QWidget):
|
|
132
|
+
|
|
133
|
+
def __init__(self):
|
|
134
|
+
super().__init__()
|
|
135
|
+
|
|
136
|
+
splitter = QtWidgets.QSplitter()
|
|
137
|
+
self.canvas = QRenderWidget(splitter)
|
|
138
|
+
...
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
app = QtWidgets.QApplication([])
|
|
142
|
+
main = Main()
|
|
143
|
+
app.exec()
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
This code is distributed under the 2-clause BSD license.
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
## Developers
|
|
153
|
+
|
|
154
|
+
* Clone the repo.
|
|
155
|
+
* Install `rendercanvas` and developer deps using `pip install -e .[dev]`.
|
|
156
|
+
* Use `ruff format` to apply autoformatting.
|
|
157
|
+
* Use `ruff check` to check for linting errors.
|
|
158
|
+
* Optionally, if you install [pre-commit](https://github.com/pre-commit/pre-commit/) hooks with `pre-commit install`, lint fixes and formatting will be automatically applied on `git commit`.
|
|
159
|
+
* Use `pytest tests` to run the tests.
|
|
160
|
+
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
[](https://github.com/pygfx/rendercanvas/actions)
|
|
2
|
+
[](https://rendercanvas.readthedocs.io)
|
|
3
|
+
[](https://badge.fury.io/py/rendercanvas)
|
|
4
|
+
[](https://jacobtomlinson.dev/effver)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# rendercanvas
|
|
8
|
+
|
|
9
|
+
One canvas API, multiple backends 🚀
|
|
10
|
+
|
|
11
|
+
<div>
|
|
12
|
+
<img width=354 src='https://github.com/user-attachments/assets/42656d13-0d81-47dd-b9c7-d76da8cfa6c1' />
|
|
13
|
+
<img width=354 src='https://github.com/user-attachments/assets/af8eefe0-4485-4daf-9fbd-36710e44f07c' />
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
*This project is part of [pygfx.org](https://pygfx.org)*
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## Introduction
|
|
20
|
+
|
|
21
|
+
See how the two windows above look the same? That's the idea; they also look the
|
|
22
|
+
same to the code that renders to them. Yet, the GUI systems are very different
|
|
23
|
+
(Qt vs glfw in this case). Now that's a powerful abstraction!
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## Purpose
|
|
27
|
+
|
|
28
|
+
* Provide a generic canvas API to render to.
|
|
29
|
+
* Provide an event loop for scheduling events and draws.
|
|
30
|
+
* Provide a simple but powerful event system with standardized event objects.
|
|
31
|
+
* Provide various canvas implementations:
|
|
32
|
+
* One that is light and easily installed (glfw).
|
|
33
|
+
* For various GUI libraries (e.g. qt and wx), so visuzalizations can be embedded in a GUI.
|
|
34
|
+
* For specific platforms (e.g. Jupyter, browser).
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
The main use-case is rendering with [wgpu](https://github.com/pygfx/wgpu-py),
|
|
38
|
+
but ``rendercanvas``can be used by anything that can render based on a window-id or
|
|
39
|
+
by producing bitmap images.
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
pip install rendercanvas
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
To have at least one backend, we recommend:
|
|
49
|
+
```
|
|
50
|
+
pip install rendercanvas glfw
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
Also see the [online documentation](https://rendercanvas.readthedocs.io) and the [examples](https://github.com/pygfx/rendercanvas/tree/main/examples).
|
|
56
|
+
|
|
57
|
+
A minimal example that renders noise:
|
|
58
|
+
```py
|
|
59
|
+
import numpy as np
|
|
60
|
+
from rendercanvas.auto import RenderCanvas, loop
|
|
61
|
+
|
|
62
|
+
canvas = RenderCanvas(update_mode="continuous")
|
|
63
|
+
context = canvas.get_context("bitmap")
|
|
64
|
+
|
|
65
|
+
@canvas.request_draw
|
|
66
|
+
def animate():
|
|
67
|
+
w, h = canvas.get_logical_size()
|
|
68
|
+
bitmap = np.random.uniform(0, 255, (h, w)).astype(np.uint8)
|
|
69
|
+
context.set_bitmap(bitmap)
|
|
70
|
+
|
|
71
|
+
loop.run()
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Run wgpu visualizations:
|
|
75
|
+
```py
|
|
76
|
+
from rendercanvas.auto import RenderCanvas, loop
|
|
77
|
+
from rendercanvas.utils.cube import setup_drawing_sync
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
canvas = RenderCanvas(
|
|
81
|
+
title="The wgpu cube example on $backend", update_mode="continuous"
|
|
82
|
+
)
|
|
83
|
+
draw_frame = setup_drawing_sync(canvas)
|
|
84
|
+
canvas.request_draw(draw_frame)
|
|
85
|
+
|
|
86
|
+
loop.run()
|
|
87
|
+
````
|
|
88
|
+
|
|
89
|
+
Embed in a Qt application:
|
|
90
|
+
```py
|
|
91
|
+
from PySide6 import QtWidgets
|
|
92
|
+
from rendercanvas.qt import QRenderWidget
|
|
93
|
+
|
|
94
|
+
class Main(QtWidgets.QWidget):
|
|
95
|
+
|
|
96
|
+
def __init__(self):
|
|
97
|
+
super().__init__()
|
|
98
|
+
|
|
99
|
+
splitter = QtWidgets.QSplitter()
|
|
100
|
+
self.canvas = QRenderWidget(splitter)
|
|
101
|
+
...
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
app = QtWidgets.QApplication([])
|
|
105
|
+
main = Main()
|
|
106
|
+
app.exec()
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
This code is distributed under the 2-clause BSD license.
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
## Developers
|
|
116
|
+
|
|
117
|
+
* Clone the repo.
|
|
118
|
+
* Install `rendercanvas` and developer deps using `pip install -e .[dev]`.
|
|
119
|
+
* Use `ruff format` to apply autoformatting.
|
|
120
|
+
* Use `ruff check` to check for linting errors.
|
|
121
|
+
* Optionally, if you install [pre-commit](https://github.com/pre-commit/pre-commit/) hooks with `pre-commit install`, lint fixes and formatting will be automatically applied on `git commit`.
|
|
122
|
+
* Use `pytest tests` to run the tests.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# ===== Project info
|
|
2
|
+
|
|
3
|
+
[project]
|
|
4
|
+
dynamic = ["version"]
|
|
5
|
+
name = "rendercanvas"
|
|
6
|
+
description = "One canvas API, multiple backends"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
license = { file = "LICENSE" }
|
|
9
|
+
authors = [{ name = "Almar Klein" }, { name = "Korijn van Golen" }]
|
|
10
|
+
keywords = [
|
|
11
|
+
"canvas",
|
|
12
|
+
"rendering",
|
|
13
|
+
"graphics",
|
|
14
|
+
"wgpu",
|
|
15
|
+
"qt",
|
|
16
|
+
"wx",
|
|
17
|
+
"glfw",
|
|
18
|
+
"jupyter",
|
|
19
|
+
]
|
|
20
|
+
requires-python = ">= 3.9"
|
|
21
|
+
dependencies = [] # no dependencies!
|
|
22
|
+
[project.optional-dependencies]
|
|
23
|
+
# For users
|
|
24
|
+
jupyter = ["jupyter_rfb>=0.4.2"]
|
|
25
|
+
glfw = ["glfw>=1.9"]
|
|
26
|
+
# For devs / ci
|
|
27
|
+
lint = ["ruff", "pre-commit"]
|
|
28
|
+
examples = ["numpy", "wgpu", "glfw", "pyside6"]
|
|
29
|
+
docs = ["sphinx>7.2", "sphinx_rtd_theme", "sphinx-gallery", "numpy", "wgpu"]
|
|
30
|
+
tests = ["pytest", "numpy", "wgpu", "glfw"]
|
|
31
|
+
dev = ["rendercanvas[lint,tests,examples,docs]"]
|
|
32
|
+
|
|
33
|
+
[project.entry-points."pyinstaller40"]
|
|
34
|
+
hook-dirs = "rendercanvas.__pyinstaller:get_hook_dirs"
|
|
35
|
+
tests = "rendercanvas.__pyinstaller:get_test_dirs"
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Homepage = "https://github.com/pygfx/rendercanvas"
|
|
39
|
+
Documentation = "https://rendercanvas.readthedocs.io"
|
|
40
|
+
Repository = "https://github.com/pygfx/rendercanvas"
|
|
41
|
+
|
|
42
|
+
# ===== Building
|
|
43
|
+
|
|
44
|
+
# Flit is great solution for simple pure-Python projects.
|
|
45
|
+
[build-system]
|
|
46
|
+
requires = ["flit_core >=3.2,<4"]
|
|
47
|
+
build-backend = "flit_core.buildapi"
|
|
48
|
+
|
|
49
|
+
# ===== Tooling
|
|
50
|
+
|
|
51
|
+
[tool.ruff]
|
|
52
|
+
line-length = 88
|
|
53
|
+
|
|
54
|
+
[tool.ruff.lint]
|
|
55
|
+
select = ["F", "E", "W", "N", "B", "RUF"]
|
|
56
|
+
ignore = [
|
|
57
|
+
"E501", # Line too long
|
|
58
|
+
"E731", # Do not assign a `lambda` expression, use a `def`
|
|
59
|
+
"B007", # Loop control variable `x` not used within loop body
|
|
60
|
+
"RUF012", # Mutable class attributes should be annotated with `typing.ClassVar`
|
|
61
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
RenderCanvas: one canvas API, multiple backends.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# ruff: noqa: F401
|
|
6
|
+
|
|
7
|
+
from ._version import __version__, version_info
|
|
8
|
+
from . import _coreutils
|
|
9
|
+
from ._events import EventType
|
|
10
|
+
from .base import BaseRenderCanvas, BaseLoop, BaseTimer
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"BaseRenderCanvas",
|
|
14
|
+
"EventType",
|
|
15
|
+
"BaseLoop",
|
|
16
|
+
"BaseTimer",
|
|
17
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from PyInstaller.utils.conftest import * # noqa: F403
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# ruff: noqa: N999
|
|
2
|
+
|
|
3
|
+
from PyInstaller.utils.hooks import collect_dynamic_libs
|
|
4
|
+
|
|
5
|
+
# Init variables that PyInstaller will pick up.
|
|
6
|
+
hiddenimports = []
|
|
7
|
+
datas = []
|
|
8
|
+
binaries = []
|
|
9
|
+
|
|
10
|
+
# Add modules that are safe to add, i.e. don't pull in dependencies that we don't want.
|
|
11
|
+
hiddenimports += ["rendercanvas.offscreen"]
|
|
12
|
+
|
|
13
|
+
# Since glfw does not have a hook like this, it does not include the glfw binary
|
|
14
|
+
# when freezing. We can solve this with the code below. Makes the binary a bit
|
|
15
|
+
# larger, but only marginally (less than 300kb).
|
|
16
|
+
try:
|
|
17
|
+
import glfw # noqa: F401
|
|
18
|
+
except ImportError:
|
|
19
|
+
pass
|
|
20
|
+
else:
|
|
21
|
+
hiddenimports += ["rendercanvas.glfw"]
|
|
22
|
+
binaries += collect_dynamic_libs("glfw")
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
script = """
|
|
2
|
+
# The script part
|
|
3
|
+
import sys
|
|
4
|
+
import importlib
|
|
5
|
+
|
|
6
|
+
from rendercanvas.auto import RenderCanvas
|
|
7
|
+
|
|
8
|
+
if "glfw" not in RenderCanvas.__name__.lower():
|
|
9
|
+
raise RuntimeError(f"Expected a glfw canvas, got {RenderCanvas.__name__}")
|
|
10
|
+
|
|
11
|
+
# The test part
|
|
12
|
+
if "is_test" in sys.argv:
|
|
13
|
+
included_modules = [
|
|
14
|
+
"rendercanvas.glfw",
|
|
15
|
+
"rendercanvas.offscreen",
|
|
16
|
+
"glfw",
|
|
17
|
+
]
|
|
18
|
+
excluded_modules = [
|
|
19
|
+
"PySide6.QtGui",
|
|
20
|
+
"PyQt6.QtGui",
|
|
21
|
+
]
|
|
22
|
+
for module_name in included_modules:
|
|
23
|
+
importlib.import_module(module_name)
|
|
24
|
+
for module_name in excluded_modules:
|
|
25
|
+
try:
|
|
26
|
+
importlib.import_module(module_name)
|
|
27
|
+
except ModuleNotFoundError:
|
|
28
|
+
continue
|
|
29
|
+
raise RuntimeError(module_name + " is not supposed to be importable.")
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_pyi_rendercanvas(pyi_builder):
|
|
34
|
+
pyi_builder.test_source(script, app_args=["is_test"])
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# We could also test the script below, but it's not that interesting since it uses direct imports.
|
|
38
|
+
# To safe CI-time we don't actively test it.
|
|
39
|
+
script_qt = """
|
|
40
|
+
import sys
|
|
41
|
+
import importlib
|
|
42
|
+
|
|
43
|
+
import PySide6
|
|
44
|
+
from rendercanvas.qt import RenderCanvas
|
|
45
|
+
|
|
46
|
+
assert "qt" in RenderCanvas.__name__.lower()
|
|
47
|
+
"""
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A stub context implementation for documentation purposes.
|
|
3
|
+
It does actually work, but presents nothing.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import weakref
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def rendercanvas_context_hook(canvas, present_methods):
|
|
10
|
+
"""Hook function to allow ``rendercanvas`` to detect your context implementation.
|
|
11
|
+
|
|
12
|
+
If you make a function with this name available in the module ``your.module``,
|
|
13
|
+
``rendercanvas`` will detect and call this function in order to obtain the canvas object.
|
|
14
|
+
That way, anyone can use ``canvas.get_context("your.module")`` to use your context.
|
|
15
|
+
The arguments are the same as for ``ContextInterface``.
|
|
16
|
+
"""
|
|
17
|
+
return ContextInterface(canvas, present_methods)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ContextInterface:
|
|
21
|
+
"""The interface that a context must implement, to be usable with a ``RenderCanvas``.
|
|
22
|
+
|
|
23
|
+
Arguments:
|
|
24
|
+
canvas (BaseRenderCanvas): the canvas to render to.
|
|
25
|
+
present_methods (dict): The supported present methods of the canvas.
|
|
26
|
+
|
|
27
|
+
The ``present_methods`` dict has a field for each supported present-method. A
|
|
28
|
+
canvas must support either "screen" or "bitmap". It may support both, as well as
|
|
29
|
+
additional (specialized) present methods. Below we list the common methods and
|
|
30
|
+
what fields the subdicts have.
|
|
31
|
+
|
|
32
|
+
* Render method "screen":
|
|
33
|
+
* "window": the native window id.
|
|
34
|
+
* "display": the native display id (Linux only).
|
|
35
|
+
* "platform": to determine between "x11" and "wayland" (Linux only).
|
|
36
|
+
* Render method "bitmap":
|
|
37
|
+
* "formats": a list of supported formats. It should always include "rgba-u8".
|
|
38
|
+
Other options can be be "i-u8" (intensity/grayscale), "i-f32", "bgra-u8", "rgba-u16", etc.
|
|
39
|
+
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(self, canvas, present_methods):
|
|
43
|
+
self._canvas_ref = weakref.ref(canvas)
|
|
44
|
+
self._present_methods = present_methods
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def canvas(self):
|
|
48
|
+
"""The associated canvas object. Internally, this should preferably be stored using a weakref."""
|
|
49
|
+
return self._canvas_ref()
|
|
50
|
+
|
|
51
|
+
def present(self):
|
|
52
|
+
"""Present the result to the canvas.
|
|
53
|
+
|
|
54
|
+
This is called by the canvas, and should not be called by user-code.
|
|
55
|
+
|
|
56
|
+
The implementation should always return a present-result dict, which
|
|
57
|
+
should have at least a field 'method'. The value of 'method' must be
|
|
58
|
+
one of the methods that the canvas supports, i.e. it must be in ``present_methods``.
|
|
59
|
+
|
|
60
|
+
* If there is nothing to present, e.g. because nothing was rendered yet:
|
|
61
|
+
* return ``{"method": "skip"}`` (special case).
|
|
62
|
+
* If presentation could not be done for some reason:
|
|
63
|
+
* return ``{"method": "fail", "message": "xx"}`` (special case).
|
|
64
|
+
* If ``present_method`` is "screen":
|
|
65
|
+
* Render to screen using the info in ``present_methods['screen']``).
|
|
66
|
+
* Return ``{"method", "screen"}`` as confirmation.
|
|
67
|
+
* If ``present_method`` is "bitmap":
|
|
68
|
+
* Return ``{"method": "bitmap", "data": data, "format": format}``.
|
|
69
|
+
* 'data' is a memoryview, or something that can be converted to a memoryview, like a numpy array.
|
|
70
|
+
* 'format' is the format of the bitmap, must be in ``present_methods['bitmap']['formats']`` ("rgba-u8" is always supported).
|
|
71
|
+
* If ``present_method`` is something else:
|
|
72
|
+
* Return ``{"method": "xx", ...}``.
|
|
73
|
+
* It's the responsibility of the context to use a render method that is supported by the canvas,
|
|
74
|
+
and that the appropriate arguments are supplied.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
# This is a stub
|
|
78
|
+
return {"method": "skip"}
|