PythonQwt 0.15.0__py3-none-any.whl → 0.16.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.
- {pythonqwt-0.15.0.dist-info → pythonqwt-0.16.0.dist-info}/METADATA +22 -10
- {pythonqwt-0.15.0.dist-info → pythonqwt-0.16.0.dist-info}/RECORD +18 -18
- {pythonqwt-0.15.0.dist-info → pythonqwt-0.16.0.dist-info}/WHEEL +1 -1
- qwt/__init__.py +3 -3
- qwt/graphic.py +30 -13
- qwt/null_paintdevice.py +5 -1
- qwt/painter_command.py +49 -12
- qwt/plot_canvas.py +1 -1
- qwt/scale_div.py +5 -3
- qwt/scale_draw.py +103 -41
- qwt/scale_engine.py +17 -10
- qwt/scale_map.py +19 -10
- qwt/tests/test_bodedemo.py +1 -2
- qwt/tests/test_relativemargin.py +2 -2
- qwt/text.py +170 -39
- {pythonqwt-0.15.0.dist-info → pythonqwt-0.16.0.dist-info}/entry_points.txt +0 -0
- {pythonqwt-0.15.0.dist-info → pythonqwt-0.16.0.dist-info}/licenses/LICENSE +0 -0
- {pythonqwt-0.15.0.dist-info → pythonqwt-0.16.0.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PythonQwt
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.0
|
|
4
4
|
Summary: Qt plotting widgets for Python
|
|
5
5
|
Author-email: Pierre Raybaut <pierre.raybaut@gmail.com>
|
|
6
6
|
License: PythonQwt License Agreement
|
|
@@ -666,12 +666,11 @@ License: PythonQwt License Agreement
|
|
|
666
666
|
Project-URL: Homepage, https://github.com/PlotPyStack/PythonQwt/
|
|
667
667
|
Project-URL: Documentation, https://PythonQwt.readthedocs.io/en/latest/
|
|
668
668
|
Classifier: Topic :: Scientific/Engineering
|
|
669
|
+
Classifier: Topic :: Scientific/Engineering :: Human Machine Interfaces
|
|
669
670
|
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
670
671
|
Classifier: Topic :: Software Development :: Widget Sets
|
|
671
672
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
672
673
|
Classifier: Topic :: Utilities
|
|
673
|
-
Classifier: Topic :: Scientific/Engineering
|
|
674
|
-
Classifier: Topic :: Scientific/Engineering :: Human Machine Interfaces
|
|
675
674
|
Classifier: Topic :: Software Development :: User Interfaces
|
|
676
675
|
Classifier: Operating System :: MacOS
|
|
677
676
|
Classifier: Operating System :: Microsoft :: Windows
|
|
@@ -683,15 +682,18 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
683
682
|
Classifier: Programming Language :: Python :: 3.11
|
|
684
683
|
Classifier: Programming Language :: Python :: 3.12
|
|
685
684
|
Classifier: Programming Language :: Python :: 3.13
|
|
685
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
686
686
|
Requires-Python: <4,>=3.9
|
|
687
687
|
Description-Content-Type: text/markdown
|
|
688
688
|
License-File: LICENSE
|
|
689
|
-
Requires-Dist: NumPy>=1.
|
|
689
|
+
Requires-Dist: NumPy>=1.21
|
|
690
690
|
Requires-Dist: QtPy>=1.9
|
|
691
691
|
Provides-Extra: dev
|
|
692
|
+
Requires-Dist: build; extra == "dev"
|
|
692
693
|
Requires-Dist: ruff; extra == "dev"
|
|
693
694
|
Requires-Dist: pylint; extra == "dev"
|
|
694
695
|
Requires-Dist: Coverage; extra == "dev"
|
|
696
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
695
697
|
Provides-Extra: doc
|
|
696
698
|
Requires-Dist: PyQt5; extra == "doc"
|
|
697
699
|
Requires-Dist: sphinx>6; extra == "doc"
|
|
@@ -760,7 +762,7 @@ tests.run()
|
|
|
760
762
|
or from the command line:
|
|
761
763
|
|
|
762
764
|
```bash
|
|
763
|
-
PythonQwt
|
|
765
|
+
PythonQwt-tests
|
|
764
766
|
```
|
|
765
767
|
|
|
766
768
|
Tests may also be executed in unattended mode:
|
|
@@ -773,9 +775,9 @@ PythonQwt-tests --mode unattended
|
|
|
773
775
|
|
|
774
776
|
The `qwt` package is a pure Python implementation of `Qwt` C++ library with the following limitations.
|
|
775
777
|
|
|
776
|
-
The following `Qwt` classes won't be reimplemented in `qwt` because more powerful features already exist in `
|
|
778
|
+
The following `Qwt` classes won't be reimplemented in `qwt` because more powerful features already exist in `PlotPy`: `QwtPlotZoomer`, `QwtCounter`, `QwtEventPattern`, `QwtPicker`, `QwtPlotPicker`.
|
|
777
779
|
|
|
778
|
-
Only the following plot items are currently implemented in `qwt` (the only plot items needed by `
|
|
780
|
+
Only the following plot items are currently implemented in `qwt` (the only plot items needed by `PlotPy`): `QwtPlotItem` (base class), `QwtPlotGrid`, `QwtPlotMarker`, `QwtPlotSeriesItem` and `QwtPlotCurve`.
|
|
779
781
|
|
|
780
782
|
See "Overview" section in [documentation](https://pythonqwt.readthedocs.io/en/latest/) for more details on API limitations when comparing to Qwt.
|
|
781
783
|
|
|
@@ -798,14 +800,14 @@ Compatibility table:
|
|
|
798
800
|
|
|
799
801
|
| PythonQwt version | PyQt5 | PyQt6 | PySide2 | PySide6 |
|
|
800
802
|
|-------------------|-------|-------|---------|---------|
|
|
801
|
-
| 0.
|
|
803
|
+
| 0.15 and earlier | ✅ | ⚠️ | ❌ | ⚠️ |
|
|
802
804
|
| Latest | ✅ | ✅ | ❌ | ✅ |
|
|
803
805
|
|
|
804
806
|
### Requirements
|
|
805
807
|
|
|
806
808
|
- Python >=3.9
|
|
807
|
-
- QtPy >= 1.
|
|
808
|
-
- NumPy >= 1.
|
|
809
|
+
- QtPy >= 1.9 (and a Python-to-Qt binding library, see above)
|
|
810
|
+
- NumPy >= 1.21
|
|
809
811
|
|
|
810
812
|
### Optional dependencies
|
|
811
813
|
|
|
@@ -814,12 +816,22 @@ Compatibility table:
|
|
|
814
816
|
|
|
815
817
|
### Installation
|
|
816
818
|
|
|
819
|
+
From PyPI:
|
|
820
|
+
|
|
821
|
+
```bash
|
|
822
|
+
pip install PythonQwt
|
|
823
|
+
```
|
|
824
|
+
|
|
817
825
|
From the source package:
|
|
818
826
|
|
|
819
827
|
```bash
|
|
820
828
|
python -m build
|
|
821
829
|
```
|
|
822
830
|
|
|
831
|
+
## Performance investigation
|
|
832
|
+
|
|
833
|
+
Tooling for performance benchmarks, profiling and visual-regression checks across PyQt5/PyQt6/PySide6 lives in [`scripts/`](scripts/README.md). See [`doc/issue93_optimization_summary.md`](doc/issue93_optimization_summary.md) for a worked example.
|
|
834
|
+
|
|
823
835
|
## Copyrights
|
|
824
836
|
|
|
825
837
|
### Main code base
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
pythonqwt-0.
|
|
2
|
-
qwt/__init__.py,sha256=
|
|
1
|
+
pythonqwt-0.16.0.dist-info/licenses/LICENSE,sha256=qjEk8TRuXmFS7QC-omINvD1UPGqWaOs6CzcCZoMEhdI,33457
|
|
2
|
+
qwt/__init__.py,sha256=wOp2xyXj0loXQntSFHwu_OzVj09zvQ6n-BLp46BXy68,5990
|
|
3
3
|
qwt/_math.py,sha256=fNcPJcaK-ldCCFB20T2N58LEkQ1lwZY1-q5veXXhwl8,1501
|
|
4
4
|
qwt/color_map.py,sha256=fLRpymqOXtLrhuPrbbCxTvNINbr2GH7pYBG4fZidrcs,11812
|
|
5
5
|
qwt/column_symbol.py,sha256=0aFyQ05ryTKbaSTctkhtXa0pB_tWG444zlH3991_bt0,5760
|
|
6
6
|
qwt/dyngrid_layout.py,sha256=wgff6mZ1okNhQRRbwaw1I__vOXqGdUG0uafkShuns08,13477
|
|
7
|
-
qwt/graphic.py,sha256=
|
|
7
|
+
qwt/graphic.py,sha256=rSxvgIAm9ctcyszvZrN_03KpBhKSHabbPYdcrztSta8,28962
|
|
8
8
|
qwt/interval.py,sha256=PMrCQxV9NXGk2JG0MNjJ3zGTNTSSRfa_noxbpm-Okns,12287
|
|
9
9
|
qwt/legend.py,sha256=GBUim67HWgwLat5tOWDpK98fWcFxV-RkxWjoyWd9Gao,31313
|
|
10
|
-
qwt/null_paintdevice.py,sha256=
|
|
10
|
+
qwt/null_paintdevice.py,sha256=1pgbcvyRTVN32RGzuPzUOm0iUImjvPQ4l5OfJVyA3hg,9375
|
|
11
11
|
qwt/painter.py,sha256=k345puF4MAoTye0WBveiTNpCNWXx1K2o62_I0PZYlIA,16536
|
|
12
|
-
qwt/painter_command.py,sha256=
|
|
12
|
+
qwt/painter_command.py,sha256=7D3goNsX_2Ufr5kCpC3Cr1t8GoD5Yz0G1oIZJKvoGBY,8501
|
|
13
13
|
qwt/plot.py,sha256=d8rf4F-fpQgdpTTqNKQFJh7B0FlQ4WlquooeJQRn_eo,75660
|
|
14
|
-
qwt/plot_canvas.py,sha256=
|
|
14
|
+
qwt/plot_canvas.py,sha256=INRcxB17dvyGI7Jqi2FX4gm16EG4gzJKULj9inHkibA,30309
|
|
15
15
|
qwt/plot_curve.py,sha256=ThlfxUjB4yiP_Dh96P7PXusyqUfDWcRcyt31OHvu2vk,37059
|
|
16
16
|
qwt/plot_directpainter.py,sha256=JCWNhCC21L1A1HZnxd-C95QNlrVJbLztmGab-X8gCGc,10165
|
|
17
17
|
qwt/plot_grid.py,sha256=h-cDTzibEzQyX2g25SBg5ysyXwmONmMFy9NcuzFySYc,16607
|
|
@@ -20,20 +20,20 @@ qwt/plot_marker.py,sha256=6vDHdMsyGClMruWLA4lChUCpoLzmxGNkvmICm0KjP6I,21284
|
|
|
20
20
|
qwt/plot_renderer.py,sha256=v-fSwicMGQBa_kQx4hJJptlVNpNsKbgWk9jjqG-r_1g,27201
|
|
21
21
|
qwt/plot_series.py,sha256=Wa_Wunu-t_L8vl95RJq6__k-XA8UV2YNIsc8yNGpTT8,10654
|
|
22
22
|
qwt/qthelpers.py,sha256=GpvLr96Ip8SIGwyFfs0f7ocHyKPB7PEjHBQyrpw84xw,1405
|
|
23
|
-
qwt/scale_div.py,sha256=
|
|
24
|
-
qwt/scale_draw.py,sha256=
|
|
25
|
-
qwt/scale_engine.py,sha256=
|
|
26
|
-
qwt/scale_map.py,sha256=
|
|
23
|
+
qwt/scale_div.py,sha256=_iI5cy4s8H6wigE8xsn7W44T2-DqVADqdjQ31uJPa_I,9266
|
|
24
|
+
qwt/scale_draw.py,sha256=iO39q7nXJRuFTYan3m5taAGqvmzCq2JX0PhySWtAYVo,41007
|
|
25
|
+
qwt/scale_engine.py,sha256=7KQB5k-JXuJMsEMQXBJBNppCN-rTN97UKQCYXdazvqQ,36674
|
|
26
|
+
qwt/scale_map.py,sha256=rHmPv7e9voEFuAIInQJq60mTtIGrLMViNlgJYu20znA,9605
|
|
27
27
|
qwt/scale_widget.py,sha256=p202DrRgMraGbVcubzkatvVXOLbO9CPho729hz6gqa0,27125
|
|
28
28
|
qwt/symbol.py,sha256=DIXtIOgniO70pScKF-H_mee8GgBuycW3YcsopvfCRGY,39147
|
|
29
|
-
qwt/text.py,sha256=
|
|
29
|
+
qwt/text.py,sha256=isLS7UmbJrAmOoxhszPwrkJSRTh5WFmqVkbz_npIi94,48099
|
|
30
30
|
qwt/toqimage.py,sha256=H2u_qDt32n7HGZakWvs3Ve0G3u04Uk2ZQYp8MuZkkmU,1723
|
|
31
31
|
qwt/transform.py,sha256=bFkdmI2wDjOJrUZU6E9-sAvwoo_umXycxq6LPvD6N_c,6078
|
|
32
32
|
qwt/tests/__init__.py,sha256=diBkA_H_Xuxb84tNelsNU4djTlUnKJ5HZNZr02EwnjE,1102
|
|
33
33
|
qwt/tests/comparative_benchmarks.py,sha256=hlLFkyWzadbUyUX2vka_l2bdcGe8U9sOKBDny3o3U40,1821
|
|
34
34
|
qwt/tests/conftest.py,sha256=LwqVA58_Cv7Fitpcn9bGdhbWDBwID_3gaZg2LkJQtGQ,2196
|
|
35
35
|
qwt/tests/test_backingstore.py,sha256=AIiRPqcNPY1riXSQXU43tqB2_z02PhxmK1zA4OxQixM,524
|
|
36
|
-
qwt/tests/test_bodedemo.py,sha256=
|
|
36
|
+
qwt/tests/test_bodedemo.py,sha256=A9iZ4FmTmn96YAwxeIQIPBwIZtj4Jk_ftB78bJAIV_c,9367
|
|
37
37
|
qwt/tests/test_cartesian.py,sha256=0VCrvclqbQJSEGhWpZLq6brA9Qm9oRIgluEBbxOTOds,3855
|
|
38
38
|
qwt/tests/test_cpudemo.py,sha256=1XECvuJwOzMjI5JWCBUwvnQ6dCkcDEqZlhQ7KU8N-Rs,12853
|
|
39
39
|
qwt/tests/test_curvebenchmark1.py,sha256=a53CvA149Ng1Vj4oruKo4Gp952-0A5gLXvRPOiNSYQk,5891
|
|
@@ -49,7 +49,7 @@ qwt/tests/test_loadtest.py,sha256=ZTHatcGAbLyvS0BpbOWbzPD2Bjz4rckF7oxZsUVQ5KM,18
|
|
|
49
49
|
qwt/tests/test_logcurve.py,sha256=XOtR0asSqFfzc0VL0qfXN0fXNvxvLnz5fxmNZ2gzQWk,1129
|
|
50
50
|
qwt/tests/test_mapdemo.py,sha256=e7rvB8IPKYVVii8UgdHSbOHLc3i7eB21EQNKZ151Kc8,3423
|
|
51
51
|
qwt/tests/test_multidemo.py,sha256=YS-P08qcakD41OJy6ZI53ofKOnUvD-2_uum0yOLiIRc,2530
|
|
52
|
-
qwt/tests/test_relativemargin.py,sha256=
|
|
52
|
+
qwt/tests/test_relativemargin.py,sha256=Shn0aE7UeETSSaQFpt4DrMOFeMN3p4rmEHKqPhXfQTI,2097
|
|
53
53
|
qwt/tests/test_simple.py,sha256=4opQp_-RkcVdpRyYSh89ddBkeXCPrppB-_2KTiu5vjI,2347
|
|
54
54
|
qwt/tests/test_stylesheet.py,sha256=cuL1iY4pp5ZoMX4OI86amJA6R5SzQsH1JUWLtEiitZ4,950
|
|
55
55
|
qwt/tests/test_symbols.py,sha256=YcGM0_Em8QtcbqpLSU98PxvGo7BIIYviP2o_4Fg2LbI,5607
|
|
@@ -77,8 +77,8 @@ qwt/tests/data/symbol.svg,sha256=ONkkohVqpg3OO2-XEZge7UZLqqNyOQXbSpLgHXcTBFU,127
|
|
|
77
77
|
qwt/tests/data/symbols.png,sha256=wiqRBc2MJluJ-am9LtZ0K9DHV9BnreYMiEvfzJUFzCk,55586
|
|
78
78
|
qwt/tests/data/testlauncher.png,sha256=WmucObp30QYYKsVRBs5-6t1aEN0FbIWRmOVFN1gt-vQ,139676
|
|
79
79
|
qwt/tests/data/vertical.png,sha256=EvyG6q6rZm6pTT08Y_nzdBYCnqmoX1QDuEQtp2pyGlw,34076
|
|
80
|
-
pythonqwt-0.
|
|
81
|
-
pythonqwt-0.
|
|
82
|
-
pythonqwt-0.
|
|
83
|
-
pythonqwt-0.
|
|
84
|
-
pythonqwt-0.
|
|
80
|
+
pythonqwt-0.16.0.dist-info/METADATA,sha256=jjr2ZDxH0abEGbmHoFLQsXEbk8X-3FLRTRqajqSnqDk,45515
|
|
81
|
+
pythonqwt-0.16.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
82
|
+
pythonqwt-0.16.0.dist-info/entry_points.txt,sha256=pdPda-YcYigCi00hR4tMxWKu6byxM2x3zA8BQFDYvwI,46
|
|
83
|
+
pythonqwt-0.16.0.dist-info/top_level.txt,sha256=KB1IBdWRWnaItyJMaECwZiEi1jWt3IvqCrRVVhMjTu8,4
|
|
84
|
+
pythonqwt-0.16.0.dist-info/RECORD,,
|
qwt/__init__.py
CHANGED
|
@@ -22,8 +22,8 @@ External resources:
|
|
|
22
22
|
* Project page on GitHub: `GitHubPage`_
|
|
23
23
|
* Bug reports and feature requests: `GitHub`_
|
|
24
24
|
|
|
25
|
-
.. _PyPI: https://pypi.
|
|
26
|
-
.. _GitHubPage:
|
|
25
|
+
.. _PyPI: https://pypi.org/project/PythonQwt/
|
|
26
|
+
.. _GitHubPage: https://github.com/PlotPyStack/PythonQwt
|
|
27
27
|
.. _GitHub: https://github.com/PlotPyStack/PythonQwt
|
|
28
28
|
"""
|
|
29
29
|
|
|
@@ -63,7 +63,7 @@ from qwt.symbol import QwtSymbol as QSbl # see deprecated section
|
|
|
63
63
|
from qwt.text import QwtText # noqa: F401
|
|
64
64
|
from qwt.toqimage import array_to_qimage as toQImage # noqa: F401
|
|
65
65
|
|
|
66
|
-
__version__ = "0.
|
|
66
|
+
__version__ = "0.16.0"
|
|
67
67
|
QWT_VERSION_STR = "6.1.5"
|
|
68
68
|
|
|
69
69
|
|
qwt/graphic.py
CHANGED
|
@@ -26,7 +26,23 @@ from qtpy.QtGui import (
|
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
from qwt.null_paintdevice import QwtNullPaintDevice
|
|
29
|
-
from qwt.painter_command import QwtPainterCommand
|
|
29
|
+
from qwt.painter_command import QwtPainterCommand, _flag_int
|
|
30
|
+
|
|
31
|
+
# See painter_command.py for the rationale: cache the QPaintEngine.DirtyXxx
|
|
32
|
+
# flags as plain ints so the State-replay branch below does plain int bitwise
|
|
33
|
+
# tests instead of going through Python's enum.Flag.__and__ on PyQt6.
|
|
34
|
+
_DIRTY_PEN = _flag_int(QPaintEngine.DirtyPen)
|
|
35
|
+
_DIRTY_BRUSH = _flag_int(QPaintEngine.DirtyBrush)
|
|
36
|
+
_DIRTY_BRUSH_ORIGIN = _flag_int(QPaintEngine.DirtyBrushOrigin)
|
|
37
|
+
_DIRTY_FONT = _flag_int(QPaintEngine.DirtyFont)
|
|
38
|
+
_DIRTY_BACKGROUND = _flag_int(QPaintEngine.DirtyBackground)
|
|
39
|
+
_DIRTY_TRANSFORM = _flag_int(QPaintEngine.DirtyTransform)
|
|
40
|
+
_DIRTY_CLIP_ENABLED = _flag_int(QPaintEngine.DirtyClipEnabled)
|
|
41
|
+
_DIRTY_CLIP_REGION = _flag_int(QPaintEngine.DirtyClipRegion)
|
|
42
|
+
_DIRTY_CLIP_PATH = _flag_int(QPaintEngine.DirtyClipPath)
|
|
43
|
+
_DIRTY_HINTS = _flag_int(QPaintEngine.DirtyHints)
|
|
44
|
+
_DIRTY_COMPOSITION_MODE = _flag_int(QPaintEngine.DirtyCompositionMode)
|
|
45
|
+
_DIRTY_OPACITY = _flag_int(QPaintEngine.DirtyOpacity)
|
|
30
46
|
|
|
31
47
|
|
|
32
48
|
def qwtHasScalablePen(painter):
|
|
@@ -83,35 +99,36 @@ def qwtExecCommand(painter, cmd, renderHints, transform, initialTransform):
|
|
|
83
99
|
painter.drawImage(data.rect, data.image, data.subRect, data.flags)
|
|
84
100
|
elif cmd.type() == QwtPainterCommand.State:
|
|
85
101
|
data = cmd.stateData()
|
|
86
|
-
|
|
102
|
+
flags = _flag_int(data.flags)
|
|
103
|
+
if flags & _DIRTY_PEN:
|
|
87
104
|
painter.setPen(data.pen)
|
|
88
|
-
if
|
|
105
|
+
if flags & _DIRTY_BRUSH:
|
|
89
106
|
painter.setBrush(data.brush)
|
|
90
|
-
if
|
|
107
|
+
if flags & _DIRTY_BRUSH_ORIGIN:
|
|
91
108
|
painter.setBrushOrigin(data.brushOrigin)
|
|
92
|
-
if
|
|
109
|
+
if flags & _DIRTY_FONT:
|
|
93
110
|
painter.setFont(data.font)
|
|
94
|
-
if
|
|
111
|
+
if flags & _DIRTY_BACKGROUND:
|
|
95
112
|
painter.setBackgroundMode(data.backgroundMode)
|
|
96
113
|
painter.setBackground(data.backgroundBrush)
|
|
97
|
-
if
|
|
114
|
+
if flags & _DIRTY_TRANSFORM:
|
|
98
115
|
painter.setTransform(data.transform)
|
|
99
|
-
if
|
|
116
|
+
if flags & _DIRTY_CLIP_ENABLED:
|
|
100
117
|
painter.setClipping(data.isClipEnabled)
|
|
101
|
-
if
|
|
118
|
+
if flags & _DIRTY_CLIP_REGION:
|
|
102
119
|
painter.setClipRegion(data.clipRegion, data.clipOperation)
|
|
103
|
-
if
|
|
120
|
+
if flags & _DIRTY_CLIP_PATH:
|
|
104
121
|
painter.setClipPath(data.clipPath, data.clipOperation)
|
|
105
|
-
if
|
|
122
|
+
if flags & _DIRTY_HINTS:
|
|
106
123
|
for hint in (
|
|
107
124
|
QPainter.Antialiasing,
|
|
108
125
|
QPainter.TextAntialiasing,
|
|
109
126
|
QPainter.SmoothPixmapTransform,
|
|
110
127
|
):
|
|
111
128
|
painter.setRenderHint(hint, bool(data.renderHints & hint))
|
|
112
|
-
if
|
|
129
|
+
if flags & _DIRTY_COMPOSITION_MODE:
|
|
113
130
|
painter.setCompositionMode(data.compositionMode)
|
|
114
|
-
if
|
|
131
|
+
if flags & _DIRTY_OPACITY:
|
|
115
132
|
painter.setOpacity(data.opacity)
|
|
116
133
|
|
|
117
134
|
|
qwt/null_paintdevice.py
CHANGED
|
@@ -272,8 +272,12 @@ class QwtNullPaintDevice(QPaintDevice):
|
|
|
272
272
|
* 25.4
|
|
273
273
|
/ self.metric(QPaintDevice.PdmDpiY)
|
|
274
274
|
)
|
|
275
|
+
elif deviceMetric == QPaintDevice.PdmDevicePixelRatio:
|
|
276
|
+
value = 1
|
|
277
|
+
elif deviceMetric == QPaintDevice.PdmDevicePixelRatioScaled:
|
|
278
|
+
value = 1
|
|
275
279
|
else:
|
|
276
|
-
value =
|
|
280
|
+
value = super(QwtNullPaintDevice, self).metric(deviceMetric)
|
|
277
281
|
return value
|
|
278
282
|
|
|
279
283
|
def drawRects(self, rects, rectCount):
|
qwt/painter_command.py
CHANGED
|
@@ -18,6 +18,40 @@ import copy
|
|
|
18
18
|
from qtpy.QtGui import QPaintEngine, QPainterPath
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
def _flag_int(flag):
|
|
22
|
+
"""Return the integer value of a Qt enum/flag (PyQt5 and PyQt6).
|
|
23
|
+
|
|
24
|
+
PyQt5 exposes Qt enums as plain ints (``int(flag)`` works). PyQt6 wraps
|
|
25
|
+
them as ``enum.Flag`` instances which are not ``int`` subclasses, so
|
|
26
|
+
``int(flag)`` raises -- the value must be read from ``flag.value``.
|
|
27
|
+
"""
|
|
28
|
+
try:
|
|
29
|
+
return flag.value
|
|
30
|
+
except AttributeError:
|
|
31
|
+
return int(flag)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# Cache QPaintEngine.DirtyXxx flags as plain Python ints once at import time.
|
|
35
|
+
# On PyQt6, Qt enums are full ``enum.Flag`` instances and every ``flags &
|
|
36
|
+
# Member`` test goes through Python's ``enum.__and__`` machinery (~6 us each).
|
|
37
|
+
# In ``QwtPainterCommand.__init__`` below, the State branch performs twelve
|
|
38
|
+
# successive flag tests per painter command -- on PyQt6 alone this accounted
|
|
39
|
+
# for ~20 ms of the residual perf gap on the load test. Casting once to int
|
|
40
|
+
# and bitwise-testing against int constants brings each test back to ~50 ns.
|
|
41
|
+
_DIRTY_PEN = _flag_int(QPaintEngine.DirtyPen)
|
|
42
|
+
_DIRTY_BRUSH = _flag_int(QPaintEngine.DirtyBrush)
|
|
43
|
+
_DIRTY_BRUSH_ORIGIN = _flag_int(QPaintEngine.DirtyBrushOrigin)
|
|
44
|
+
_DIRTY_FONT = _flag_int(QPaintEngine.DirtyFont)
|
|
45
|
+
_DIRTY_BACKGROUND = _flag_int(QPaintEngine.DirtyBackground)
|
|
46
|
+
_DIRTY_TRANSFORM = _flag_int(QPaintEngine.DirtyTransform)
|
|
47
|
+
_DIRTY_CLIP_ENABLED = _flag_int(QPaintEngine.DirtyClipEnabled)
|
|
48
|
+
_DIRTY_CLIP_REGION = _flag_int(QPaintEngine.DirtyClipRegion)
|
|
49
|
+
_DIRTY_CLIP_PATH = _flag_int(QPaintEngine.DirtyClipPath)
|
|
50
|
+
_DIRTY_HINTS = _flag_int(QPaintEngine.DirtyHints)
|
|
51
|
+
_DIRTY_COMPOSITION_MODE = _flag_int(QPaintEngine.DirtyCompositionMode)
|
|
52
|
+
_DIRTY_OPACITY = _flag_int(QPaintEngine.DirtyOpacity)
|
|
53
|
+
|
|
54
|
+
|
|
21
55
|
class PixmapData(object):
|
|
22
56
|
def __init__(self):
|
|
23
57
|
self.rect = None
|
|
@@ -125,32 +159,35 @@ class QwtPainterCommand(object):
|
|
|
125
159
|
self.__type = self.State
|
|
126
160
|
self.__stateData = StateData()
|
|
127
161
|
self.__stateData.flags = state.state()
|
|
128
|
-
|
|
162
|
+
# Cast to int once: subsequent bitwise tests are done against
|
|
163
|
+
# the cached _DIRTY_* int constants (see top of module).
|
|
164
|
+
flags = _flag_int(self.__stateData.flags)
|
|
165
|
+
if flags & _DIRTY_PEN:
|
|
129
166
|
self.__stateData.pen = state.pen()
|
|
130
|
-
if
|
|
167
|
+
if flags & _DIRTY_BRUSH:
|
|
131
168
|
self.__stateData.brush = state.brush()
|
|
132
|
-
if
|
|
169
|
+
if flags & _DIRTY_BRUSH_ORIGIN:
|
|
133
170
|
self.__stateData.brushOrigin = state.brushOrigin()
|
|
134
|
-
if
|
|
171
|
+
if flags & _DIRTY_FONT:
|
|
135
172
|
self.__stateData.font = state.font()
|
|
136
|
-
if
|
|
173
|
+
if flags & _DIRTY_BACKGROUND:
|
|
137
174
|
self.__stateData.backgroundMode = state.backgroundMode()
|
|
138
175
|
self.__stateData.backgroundBrush = state.backgroundBrush()
|
|
139
|
-
if
|
|
176
|
+
if flags & _DIRTY_TRANSFORM:
|
|
140
177
|
self.__stateData.transform = state.transform()
|
|
141
|
-
if
|
|
178
|
+
if flags & _DIRTY_CLIP_ENABLED:
|
|
142
179
|
self.__stateData.isClipEnabled = state.isClipEnabled()
|
|
143
|
-
if
|
|
180
|
+
if flags & _DIRTY_CLIP_REGION:
|
|
144
181
|
self.__stateData.clipRegion = state.clipRegion()
|
|
145
182
|
self.__stateData.clipOperation = state.clipOperation()
|
|
146
|
-
if
|
|
183
|
+
if flags & _DIRTY_CLIP_PATH:
|
|
147
184
|
self.__stateData.clipPath = state.clipPath()
|
|
148
185
|
self.__stateData.clipOperation = state.clipOperation()
|
|
149
|
-
if
|
|
186
|
+
if flags & _DIRTY_HINTS:
|
|
150
187
|
self.__stateData.renderHints = state.renderHints()
|
|
151
|
-
if
|
|
188
|
+
if flags & _DIRTY_COMPOSITION_MODE:
|
|
152
189
|
self.__stateData.compositionMode = state.compositionMode()
|
|
153
|
-
if
|
|
190
|
+
if flags & _DIRTY_OPACITY:
|
|
154
191
|
self.__stateData.opacity = state.opacity()
|
|
155
192
|
elif len(args) == 3:
|
|
156
193
|
rect, pixmap, subRect = args
|
qwt/plot_canvas.py
CHANGED
|
@@ -787,7 +787,7 @@ class QwtPlotCanvas(QFrame):
|
|
|
787
787
|
import warnings
|
|
788
788
|
|
|
789
789
|
warnings.warn(
|
|
790
|
-
"`invalidatePaintCache` has been removed:
|
|
790
|
+
"`invalidatePaintCache` has been removed: please use `replot` instead",
|
|
791
791
|
RuntimeWarning,
|
|
792
792
|
)
|
|
793
793
|
self.replot()
|
qwt/scale_div.py
CHANGED
|
@@ -235,9 +235,11 @@ class QwtScaleDiv(object):
|
|
|
235
235
|
:param float value: Value
|
|
236
236
|
:return: True/False
|
|
237
237
|
"""
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
238
|
+
lb = self.__lowerBound
|
|
239
|
+
ub = self.__upperBound
|
|
240
|
+
if lb <= ub:
|
|
241
|
+
return lb <= value <= ub
|
|
242
|
+
return ub <= value <= lb
|
|
241
243
|
|
|
242
244
|
def invert(self):
|
|
243
245
|
"""
|
qwt/scale_draw.py
CHANGED
|
@@ -24,7 +24,6 @@ from datetime import datetime
|
|
|
24
24
|
|
|
25
25
|
from qtpy.QtCore import (
|
|
26
26
|
QLineF,
|
|
27
|
-
QObject,
|
|
28
27
|
QPoint,
|
|
29
28
|
QPointF,
|
|
30
29
|
QRect,
|
|
@@ -39,11 +38,34 @@ from qwt.scale_div import QwtScaleDiv
|
|
|
39
38
|
from qwt.scale_map import QwtScaleMap
|
|
40
39
|
from qwt.text import QwtText
|
|
41
40
|
|
|
41
|
+
# Plain-int aliases for Qt alignment flags. Qt6 exposes alignment flags as
|
|
42
|
+
# IntEnum members and bitwise operations on them go through Python's
|
|
43
|
+
# enum machinery (`__and__`/`__call__`), which is one of the dominant costs
|
|
44
|
+
# of label layout. Casting to int once and using these constants makes the
|
|
45
|
+
# bitwise tests in `labelTransformation` ~10x cheaper without changing
|
|
46
|
+
# semantics.
|
|
47
|
+
_ALIGN_LEFT = int(Qt.AlignLeft)
|
|
48
|
+
_ALIGN_RIGHT = int(Qt.AlignRight)
|
|
49
|
+
_ALIGN_TOP = int(Qt.AlignTop)
|
|
50
|
+
_ALIGN_BOTTOM = int(Qt.AlignBottom)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class QwtAbstractScaleDraw_PrivateData(object):
|
|
54
|
+
# See QwtText_PrivateData: ``QObject`` inheritance is unused and the
|
|
55
|
+
# base class' ``__init__`` is a measurable cost in tick-heavy renders.
|
|
56
|
+
__slots__ = (
|
|
57
|
+
"spacing",
|
|
58
|
+
"penWidth",
|
|
59
|
+
"minExtent",
|
|
60
|
+
"components",
|
|
61
|
+
"tick_length",
|
|
62
|
+
"tick_lighter_factor",
|
|
63
|
+
"map",
|
|
64
|
+
"scaleDiv",
|
|
65
|
+
"labelCache",
|
|
66
|
+
)
|
|
42
67
|
|
|
43
|
-
class QwtAbstractScaleDraw_PrivateData(QObject):
|
|
44
68
|
def __init__(self):
|
|
45
|
-
QObject.__init__(self)
|
|
46
|
-
|
|
47
69
|
self.spacing = 4
|
|
48
70
|
self.penWidth = 0
|
|
49
71
|
self.minExtent = 0.0
|
|
@@ -470,12 +492,25 @@ class QwtAbstractScaleDraw(object):
|
|
|
470
492
|
self.__data.labelCache.clear()
|
|
471
493
|
|
|
472
494
|
|
|
473
|
-
class QwtScaleDraw_PrivateData(
|
|
474
|
-
|
|
475
|
-
|
|
495
|
+
class QwtScaleDraw_PrivateData(object):
|
|
496
|
+
# See QwtText_PrivateData: ``QObject`` inheritance is unused and the
|
|
497
|
+
# base class' ``__init__`` is a measurable cost in tick-heavy renders.
|
|
498
|
+
__slots__ = (
|
|
499
|
+
"len",
|
|
500
|
+
"alignment",
|
|
501
|
+
"orientation",
|
|
502
|
+
"labelAlignment",
|
|
503
|
+
"labelRotation",
|
|
504
|
+
"labelAutoSize",
|
|
505
|
+
"pos",
|
|
506
|
+
)
|
|
476
507
|
|
|
508
|
+
def __init__(self):
|
|
477
509
|
self.len = 0
|
|
478
510
|
self.alignment = QwtScaleDraw.BottomScale
|
|
511
|
+
# Cached orientation - kept in sync by ``QwtScaleDraw.setAlignment``
|
|
512
|
+
# so that the very hot ``orientation()`` accessor avoids any test.
|
|
513
|
+
self.orientation = Qt.Horizontal
|
|
479
514
|
self.labelAlignment = 0
|
|
480
515
|
self.labelRotation = 0.0
|
|
481
516
|
self.labelAutoSize = True
|
|
@@ -554,6 +589,11 @@ class QwtScaleDraw(QwtAbstractScaleDraw):
|
|
|
554
589
|
:py:meth:`alignment()`
|
|
555
590
|
"""
|
|
556
591
|
self.__data.alignment = align
|
|
592
|
+
# Keep cached orientation in sync (see ``orientation()``).
|
|
593
|
+
if align == self.BottomScale or align == self.TopScale:
|
|
594
|
+
self.__data.orientation = Qt.Horizontal
|
|
595
|
+
else:
|
|
596
|
+
self.__data.orientation = Qt.Vertical
|
|
557
597
|
|
|
558
598
|
def orientation(self):
|
|
559
599
|
"""
|
|
@@ -568,10 +608,8 @@ class QwtScaleDraw(QwtAbstractScaleDraw):
|
|
|
568
608
|
|
|
569
609
|
:py:meth:`alignment()`
|
|
570
610
|
"""
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
elif self.__data.alignment in (self.LeftScale, self.RightScale):
|
|
574
|
-
return Qt.Vertical
|
|
611
|
+
# Pre-computed by ``setAlignment`` - this method is called per tick.
|
|
612
|
+
return self.__data.orientation
|
|
575
613
|
|
|
576
614
|
def getBorderDistHint(self, font):
|
|
577
615
|
"""
|
|
@@ -597,17 +635,19 @@ class QwtScaleDraw(QwtAbstractScaleDraw):
|
|
|
597
635
|
if len(ticks) == 0:
|
|
598
636
|
return start, end
|
|
599
637
|
|
|
638
|
+
scale_map = self.scaleMap()
|
|
639
|
+
transform = scale_map.transform
|
|
600
640
|
minTick = ticks[0]
|
|
601
|
-
minPos =
|
|
641
|
+
minPos = transform(minTick)
|
|
602
642
|
maxTick = minTick
|
|
603
643
|
maxPos = minPos
|
|
604
644
|
|
|
605
645
|
for tick in ticks:
|
|
606
|
-
tickPos =
|
|
646
|
+
tickPos = transform(tick)
|
|
607
647
|
if tickPos < minPos:
|
|
608
648
|
minTick = tick
|
|
609
649
|
minPos = tickPos
|
|
610
|
-
if tickPos >
|
|
650
|
+
if tickPos > maxPos:
|
|
611
651
|
maxTick = tick
|
|
612
652
|
maxPos = tickPos
|
|
613
653
|
|
|
@@ -615,16 +655,16 @@ class QwtScaleDraw(QwtAbstractScaleDraw):
|
|
|
615
655
|
e = 0.0
|
|
616
656
|
if self.orientation() == Qt.Vertical:
|
|
617
657
|
s = -self.labelRect(font, minTick).top()
|
|
618
|
-
s -= abs(minPos - round(
|
|
658
|
+
s -= abs(minPos - round(scale_map.p2()))
|
|
619
659
|
|
|
620
660
|
e = self.labelRect(font, maxTick).bottom()
|
|
621
|
-
e -= abs(maxPos -
|
|
661
|
+
e -= abs(maxPos - scale_map.p1())
|
|
622
662
|
else:
|
|
623
663
|
s = -self.labelRect(font, minTick).left()
|
|
624
|
-
s -= abs(minPos -
|
|
664
|
+
s -= abs(minPos - scale_map.p1())
|
|
625
665
|
|
|
626
666
|
e = self.labelRect(font, maxTick).right()
|
|
627
|
-
e -= abs(maxPos -
|
|
667
|
+
e -= abs(maxPos - scale_map.p2())
|
|
628
668
|
|
|
629
669
|
return max(math.ceil(s), 0), max(math.ceil(e), 0)
|
|
630
670
|
|
|
@@ -763,27 +803,22 @@ class QwtScaleDraw(QwtAbstractScaleDraw):
|
|
|
763
803
|
"""
|
|
764
804
|
tval = self.scaleMap().transform(value)
|
|
765
805
|
dist = self.spacing()
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
806
|
+
hasComponent = self.hasComponent
|
|
807
|
+
if hasComponent(QwtAbstractScaleDraw.Backbone):
|
|
808
|
+
dist += max(1, self.penWidth())
|
|
809
|
+
if hasComponent(QwtAbstractScaleDraw.Ticks):
|
|
769
810
|
dist += self.tickLength(QwtScaleDiv.MajorTick)
|
|
770
811
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
if
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
py = self.__data.pos.y() + dist
|
|
782
|
-
elif self.alignment() == self.TopScale:
|
|
783
|
-
px = tval
|
|
784
|
-
py = self.__data.pos.y() - dist
|
|
785
|
-
|
|
786
|
-
return QPointF(px, py)
|
|
812
|
+
alignment = self.alignment()
|
|
813
|
+
pos = self.__data.pos
|
|
814
|
+
if alignment == self.RightScale:
|
|
815
|
+
return QPointF(pos.x() + dist, tval)
|
|
816
|
+
if alignment == self.LeftScale:
|
|
817
|
+
return QPointF(pos.x() - dist, tval)
|
|
818
|
+
if alignment == self.BottomScale:
|
|
819
|
+
return QPointF(tval, pos.y() + dist)
|
|
820
|
+
# TopScale
|
|
821
|
+
return QPointF(tval, pos.y() - dist)
|
|
787
822
|
|
|
788
823
|
def drawTick(self, painter, value, len_):
|
|
789
824
|
"""
|
|
@@ -1007,17 +1042,19 @@ class QwtScaleDraw(QwtAbstractScaleDraw):
|
|
|
1007
1042
|
flags = self.labelAlignment()
|
|
1008
1043
|
if flags == 0:
|
|
1009
1044
|
flags = self.Flags[self.alignment()]
|
|
1045
|
+
# Cast to plain int once to avoid the per-bit Qt6 enum overhead.
|
|
1046
|
+
flags = int(flags)
|
|
1010
1047
|
|
|
1011
|
-
if flags &
|
|
1048
|
+
if flags & _ALIGN_LEFT:
|
|
1012
1049
|
x = -size.width()
|
|
1013
|
-
elif flags &
|
|
1050
|
+
elif flags & _ALIGN_RIGHT:
|
|
1014
1051
|
x = 0.0
|
|
1015
1052
|
else:
|
|
1016
1053
|
x = -(0.5 * size.width())
|
|
1017
1054
|
|
|
1018
|
-
if flags &
|
|
1055
|
+
if flags & _ALIGN_TOP:
|
|
1019
1056
|
y = -size.height()
|
|
1020
|
-
elif flags &
|
|
1057
|
+
elif flags & _ALIGN_BOTTOM:
|
|
1021
1058
|
y = 0
|
|
1022
1059
|
else:
|
|
1023
1060
|
y = -(0.5 * size.height())
|
|
@@ -1039,6 +1076,31 @@ class QwtScaleDraw(QwtAbstractScaleDraw):
|
|
|
1039
1076
|
lbl, labelSize = self.tickLabel(font, value)
|
|
1040
1077
|
if not lbl or lbl.isEmpty():
|
|
1041
1078
|
return QRectF(0.0, 0.0, 0.0, 0.0)
|
|
1079
|
+
# Fast path: when the label is not rotated, the contribution of
|
|
1080
|
+
# ``pos`` cancels out (transform.translate(pos) followed by
|
|
1081
|
+
# br.translate(-pos)). This avoids ``labelPosition``,
|
|
1082
|
+
# ``labelTransformation`` and ``QTransform.mapRect`` entirely - all
|
|
1083
|
+
# of which are dominant costs in tick-heavy layouts.
|
|
1084
|
+
if self.labelRotation() == 0.0:
|
|
1085
|
+
flags = self.labelAlignment()
|
|
1086
|
+
if flags == 0:
|
|
1087
|
+
flags = self.Flags[self.alignment()]
|
|
1088
|
+
flags = int(flags)
|
|
1089
|
+
w = labelSize.width()
|
|
1090
|
+
h = labelSize.height()
|
|
1091
|
+
if flags & _ALIGN_LEFT:
|
|
1092
|
+
x = -w
|
|
1093
|
+
elif flags & _ALIGN_RIGHT:
|
|
1094
|
+
x = 0.0
|
|
1095
|
+
else:
|
|
1096
|
+
x = -0.5 * w
|
|
1097
|
+
if flags & _ALIGN_TOP:
|
|
1098
|
+
y = -h
|
|
1099
|
+
elif flags & _ALIGN_BOTTOM:
|
|
1100
|
+
y = 0.0
|
|
1101
|
+
else:
|
|
1102
|
+
y = -0.5 * h
|
|
1103
|
+
return QRectF(x, y, w, h)
|
|
1042
1104
|
pos = self.labelPosition(value)
|
|
1043
1105
|
transform = self.labelTransformation(pos, labelSize)
|
|
1044
1106
|
br = transform.mapRect(QRectF(QPointF(0, 0), labelSize))
|
qwt/scale_engine.py
CHANGED
|
@@ -324,11 +324,10 @@ class QwtScaleEngine(object):
|
|
|
324
324
|
"""
|
|
325
325
|
if not interval.isValid():
|
|
326
326
|
return False
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
return True
|
|
327
|
+
min_v = interval.minValue()
|
|
328
|
+
max_v = interval.maxValue()
|
|
329
|
+
eps = abs(1.0e-6 * (max_v - min_v))
|
|
330
|
+
return not (min_v - value > eps or value - max_v > eps)
|
|
332
331
|
|
|
333
332
|
def strip(self, ticks, interval):
|
|
334
333
|
"""
|
|
@@ -340,9 +339,17 @@ class QwtScaleEngine(object):
|
|
|
340
339
|
"""
|
|
341
340
|
if not interval.isValid() or not ticks:
|
|
342
341
|
return []
|
|
343
|
-
|
|
342
|
+
# Inline ``contains`` to avoid one Python call per tick: ``strip`` is
|
|
343
|
+
# called by buildTicks for every layout pass and is one of the
|
|
344
|
+
# dominant costs in tick-heavy plots.
|
|
345
|
+
min_v = interval.minValue()
|
|
346
|
+
max_v = interval.maxValue()
|
|
347
|
+
eps = abs(1.0e-6 * (max_v - min_v))
|
|
348
|
+
lo = min_v - eps
|
|
349
|
+
hi = max_v + eps
|
|
350
|
+
if lo <= ticks[0] and ticks[-1] <= hi:
|
|
344
351
|
return ticks
|
|
345
|
-
return [tick for tick in ticks if
|
|
352
|
+
return [tick for tick in ticks if lo <= tick <= hi]
|
|
346
353
|
|
|
347
354
|
def buildInterval(self, value):
|
|
348
355
|
"""
|
|
@@ -594,7 +601,7 @@ class QwtLinearScaleEngine(QwtScaleEngine):
|
|
|
594
601
|
numTicks = int(math.ceil(abs(stepSize / minStep)) - 1)
|
|
595
602
|
medIndex = -1
|
|
596
603
|
if numTicks % 2:
|
|
597
|
-
medIndex = numTicks
|
|
604
|
+
medIndex = numTicks // 2
|
|
598
605
|
for val in ticks[QwtScaleDiv.MajorTick]:
|
|
599
606
|
for k in range(numTicks):
|
|
600
607
|
val += minStep
|
|
@@ -837,7 +844,7 @@ class QwtLogScaleEngine(QwtScaleEngine):
|
|
|
837
844
|
|
|
838
845
|
mediumTickIndex = -1
|
|
839
846
|
if numSteps > 2 and numSteps % 2 == 0:
|
|
840
|
-
mediumTickIndex = numSteps
|
|
847
|
+
mediumTickIndex = numSteps // 2
|
|
841
848
|
|
|
842
849
|
for v in ticks[QwtScaleDiv.MajorTick]:
|
|
843
850
|
s = logBase / numSteps
|
|
@@ -872,7 +879,7 @@ class QwtLogScaleEngine(QwtScaleEngine):
|
|
|
872
879
|
|
|
873
880
|
mediumTickIndex = -1
|
|
874
881
|
if numTicks > 2 and numTicks % 2:
|
|
875
|
-
mediumTickIndex = numTicks
|
|
882
|
+
mediumTickIndex = numTicks // 2
|
|
876
883
|
|
|
877
884
|
minFactor = max([math.pow(logBase, minStep), float(logBase)])
|
|
878
885
|
|
qwt/scale_map.py
CHANGED
|
@@ -217,8 +217,12 @@ class QwtScaleMap(object):
|
|
|
217
217
|
if self.__transform:
|
|
218
218
|
self.__ts1 = self.__transform.transform(self.__ts1)
|
|
219
219
|
ts2 = self.__transform.transform(ts2)
|
|
220
|
-
self.
|
|
221
|
-
|
|
220
|
+
if self.__ts1 == ts2:
|
|
221
|
+
# Degenerate scale: collapse every value to ``p1`` (matches the
|
|
222
|
+
# symmetric guard in ``invTransform_scalar`` and the C++ Qwt
|
|
223
|
+
# behaviour).
|
|
224
|
+
self.__cnv = 0.0
|
|
225
|
+
else:
|
|
222
226
|
self.__cnv = (self.__p2 - self.__p1) / (ts2 - self.__ts1)
|
|
223
227
|
|
|
224
228
|
def transform(self, *args):
|
|
@@ -245,13 +249,18 @@ class QwtScaleMap(object):
|
|
|
245
249
|
|
|
246
250
|
:py:meth:`invTransform()`
|
|
247
251
|
"""
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
+
nargs = len(args)
|
|
253
|
+
if nargs == 1:
|
|
254
|
+
# Scalar transform: inline the fast path for the dominant case
|
|
255
|
+
# (avoids one Python call frame per tick label).
|
|
256
|
+
s = args[0]
|
|
257
|
+
if self.__transform:
|
|
258
|
+
s = self.__transform.transform(s)
|
|
259
|
+
return self.__p1 + (s - self.__ts1) * self.__cnv
|
|
260
|
+
elif nargs == 3 and isinstance(args[2], QPointF):
|
|
252
261
|
xMap, yMap, pos = args
|
|
253
262
|
return QPointF(xMap.transform(pos.x()), yMap.transform(pos.y()))
|
|
254
|
-
elif
|
|
263
|
+
elif nargs == 3 and isinstance(args[2], QRectF):
|
|
255
264
|
xMap, yMap, rect = args
|
|
256
265
|
x1 = xMap.transform(rect.left())
|
|
257
266
|
x2 = xMap.transform(rect.right())
|
|
@@ -269,7 +278,7 @@ class QwtScaleMap(object):
|
|
|
269
278
|
y1 = 0.0
|
|
270
279
|
if qwtFuzzyCompare(y2, 0.0, y2 - y1) == 0:
|
|
271
280
|
y2 = 0.0
|
|
272
|
-
return QRectF(x1, y1, x2 - x1
|
|
281
|
+
return QRectF(x1, y1, x2 - x1, y2 - y1)
|
|
273
282
|
else:
|
|
274
283
|
raise TypeError(
|
|
275
284
|
"%s().transform() takes 1 or 3 argument(s) (%s "
|
|
@@ -292,8 +301,8 @@ class QwtScaleMap(object):
|
|
|
292
301
|
elif isinstance(args[2], QRectF):
|
|
293
302
|
xMap, yMap, rect = args
|
|
294
303
|
x1 = xMap.invTransform(rect.left())
|
|
295
|
-
x2 = xMap.invTransform(rect.right()
|
|
304
|
+
x2 = xMap.invTransform(rect.right())
|
|
296
305
|
y1 = yMap.invTransform(rect.top())
|
|
297
|
-
y2 = yMap.invTransform(rect.bottom()
|
|
306
|
+
y2 = yMap.invTransform(rect.bottom())
|
|
298
307
|
r = QRectF(x1, y1, x2 - x1, y2 - y1)
|
|
299
308
|
return r.normalized()
|
qwt/tests/test_bodedemo.py
CHANGED
|
@@ -144,8 +144,7 @@ class BodePlot(QwtPlot):
|
|
|
144
144
|
yvalue=-20.0,
|
|
145
145
|
align=Qt.AlignRight | Qt.AlignBottom,
|
|
146
146
|
label=QwtText.make(
|
|
147
|
-
"[1-(\u03c9/\u03c9<sub>0</sub>)<sup>2</sup>+2j\u03c9/Q]"
|
|
148
|
-
"<sup>-1</sup>",
|
|
147
|
+
"[1-(\u03c9/\u03c9<sub>0</sub>)<sup>2</sup>+2j\u03c9/Q]<sup>-1</sup>",
|
|
149
148
|
color=Qt.white,
|
|
150
149
|
borderradius=2,
|
|
151
150
|
borderpen=QPen(Qt.lightGray, 5),
|
qwt/tests/test_relativemargin.py
CHANGED
|
@@ -30,9 +30,9 @@ class RelativeMarginDemo(QW.QWidget):
|
|
|
30
30
|
def_margin = plot.axisMargin(qwt.QwtPlot.yLeft)
|
|
31
31
|
scale_str = "lin/lin" if not log_scale else "log/lin"
|
|
32
32
|
if relative_margin is None:
|
|
33
|
-
margin_str = f"default ({def_margin*100:.0f}%)"
|
|
33
|
+
margin_str = f"default ({def_margin * 100:.0f}%)"
|
|
34
34
|
else:
|
|
35
|
-
margin_str = f"{relative_margin*100:.0f}%"
|
|
35
|
+
margin_str = f"{relative_margin * 100:.0f}%"
|
|
36
36
|
plot.setTitle(f"{scale_str}, margin: {margin_str}")
|
|
37
37
|
if relative_margin is not None:
|
|
38
38
|
plot.setAxisMargin(qwt.QwtPlot.yLeft, relative_margin)
|
qwt/text.py
CHANGED
|
@@ -72,13 +72,34 @@ QWIDGETSIZE_MAX = (1 << 24) - 1
|
|
|
72
72
|
QT_API = os.environ["QT_API"]
|
|
73
73
|
|
|
74
74
|
|
|
75
|
+
# Cache Qt alignment flags as plain ints once at import time. On PyQt6 these
|
|
76
|
+
# are ``Qt.AlignmentFlag`` enum members and every bitwise test goes through
|
|
77
|
+
# ``enum.__and__`` (~6 us each). The test code below combines them in hot
|
|
78
|
+
# paths called per-tick / per-label / per-paint event.
|
|
79
|
+
def _flag_int(flag):
|
|
80
|
+
"""Return the integer value of a Qt enum/flag (PyQt5 and PyQt6)."""
|
|
81
|
+
try:
|
|
82
|
+
return flag.value
|
|
83
|
+
except AttributeError:
|
|
84
|
+
return int(flag)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
_ALIGN_LEFT = _flag_int(Qt.AlignLeft)
|
|
88
|
+
_ALIGN_RIGHT = _flag_int(Qt.AlignRight)
|
|
89
|
+
_ALIGN_TOP = _flag_int(Qt.AlignTop)
|
|
90
|
+
_ALIGN_BOTTOM = _flag_int(Qt.AlignBottom)
|
|
91
|
+
_ALIGN_HCENTER = _flag_int(Qt.AlignHCenter)
|
|
92
|
+
_ALIGN_JUSTIFY = _flag_int(Qt.AlignJustify)
|
|
93
|
+
_ALIGN_CENTER = _flag_int(Qt.AlignCenter)
|
|
94
|
+
|
|
95
|
+
|
|
75
96
|
def taggedRichText(text, flags):
|
|
76
97
|
richText = text
|
|
77
|
-
if flags &
|
|
98
|
+
if flags & _ALIGN_JUSTIFY:
|
|
78
99
|
richText = '<div align="justify">' + richText + "</div>"
|
|
79
|
-
elif flags &
|
|
100
|
+
elif flags & _ALIGN_RIGHT:
|
|
80
101
|
richText = '<div align="right">' + richText + "</div>"
|
|
81
|
-
elif flags &
|
|
102
|
+
elif flags & _ALIGN_HCENTER:
|
|
82
103
|
richText = '<div align="center">' + richText + "</div>"
|
|
83
104
|
return richText
|
|
84
105
|
|
|
@@ -189,6 +210,65 @@ class QwtTextEngine(object):
|
|
|
189
210
|
|
|
190
211
|
ASCENTCACHE = {}
|
|
191
212
|
|
|
213
|
+
# Module-level cache: ``id(font) -> tuple_key`` (fast path) and
|
|
214
|
+
# ``tuple_key -> tuple_key`` (slow path). The tuple key is built from a
|
|
215
|
+
# handful of QFont attributes that uniquely identify the *logical* font for
|
|
216
|
+
# metrics purposes. Tick-rendering uses very few distinct fonts in practice
|
|
217
|
+
# so both dicts stay tiny.
|
|
218
|
+
#
|
|
219
|
+
# This replaces the previous ``id(font) -> font.key()`` design. Two reasons:
|
|
220
|
+
#
|
|
221
|
+
# 1. ``QFont.key()`` is a sip dispatch that costs ~3.3 us/call on PyQt5 and
|
|
222
|
+
# ~9.3 us/call on PyQt6 -- it became the single biggest residual hotspot
|
|
223
|
+
# in ``QwtText.textSize`` on PyQt6.
|
|
224
|
+
# 2. PyQt6 returns a fresh Python wrapper around the same QFont on most
|
|
225
|
+
# calls, so ``id(font)`` changes between calls and the id-keyed fast path
|
|
226
|
+
# misses ~92% of the time. The tuple-key second level recovers the hits
|
|
227
|
+
# those misses would have produced, without paying for ``font.key()``.
|
|
228
|
+
#
|
|
229
|
+
# The tuple key uses ``(family, pixelSize-or-pointSizeF, weight, italic,
|
|
230
|
+
# stretch, styleStrategy)``. This is what determines ``QFontMetrics`` output
|
|
231
|
+
# in practice; if two QFonts share these values they share metrics.
|
|
232
|
+
|
|
233
|
+
_FONT_KEY_CACHE: dict = {} # id(font) -> tuple_key (fast path)
|
|
234
|
+
_FONT_TUPLE_CACHE: dict = {} # tuple_key -> tuple_key (interning, also acts
|
|
235
|
+
# as the "have we seen this logical font" set)
|
|
236
|
+
_FONT_KEY_CACHE_LIMIT = 1024
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def _font_tuple_key(font):
|
|
240
|
+
"""Build a hashable tuple identifying the logical font."""
|
|
241
|
+
px = font.pixelSize()
|
|
242
|
+
return (
|
|
243
|
+
font.family(),
|
|
244
|
+
px if px > 0 else font.pointSizeF(),
|
|
245
|
+
font.weight(),
|
|
246
|
+
font.italic(),
|
|
247
|
+
font.stretch(),
|
|
248
|
+
font.styleStrategy(),
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def font_key_cached(font):
|
|
253
|
+
"""Return a hashable cache key uniquely identifying ``font`` for metrics.
|
|
254
|
+
|
|
255
|
+
The returned value is **not** ``QFont.key()`` -- it is a tuple computed
|
|
256
|
+
from a handful of QFont attributes. It is safe to use as a dict key for
|
|
257
|
+
metrics caches (callers in this module always compare by ``==`` only).
|
|
258
|
+
"""
|
|
259
|
+
fid = id(font)
|
|
260
|
+
entry = _FONT_KEY_CACHE.get(fid)
|
|
261
|
+
if entry is not None:
|
|
262
|
+
return entry[1]
|
|
263
|
+
tkey = _font_tuple_key(font)
|
|
264
|
+
# Intern: reuse the same tuple object across all id() variants so dict
|
|
265
|
+
# lookups in caller-side caches benefit from object-identity hash hits.
|
|
266
|
+
interned = _FONT_TUPLE_CACHE.setdefault(tkey, tkey)
|
|
267
|
+
if len(_FONT_KEY_CACHE) >= _FONT_KEY_CACHE_LIMIT:
|
|
268
|
+
_FONT_KEY_CACHE.clear()
|
|
269
|
+
_FONT_KEY_CACHE[fid] = (font, interned)
|
|
270
|
+
return interned
|
|
271
|
+
|
|
192
272
|
|
|
193
273
|
def get_screen_resolution():
|
|
194
274
|
"""Return screen resolution: tuple of floats (DPIx, DPIy)"""
|
|
@@ -226,16 +306,21 @@ class QwtPlainTextEngine(QwtTextEngine):
|
|
|
226
306
|
self.qrectf_max = QRectF(0, 0, QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)
|
|
227
307
|
self._fm_cache = {}
|
|
228
308
|
self._fm_cache_f = {}
|
|
309
|
+
self._margins_cache = {}
|
|
310
|
+
# Fast path: when textMargins is called repeatedly with the same
|
|
311
|
+
# QFont instance, skip the (expensive) font.key() Qt call.
|
|
312
|
+
self._margins_last_id = -1
|
|
313
|
+
self._margins_last_value = None
|
|
229
314
|
|
|
230
315
|
def fontmetrics(self, font):
|
|
231
|
-
fid = font
|
|
316
|
+
fid = font_key_cached(font)
|
|
232
317
|
try:
|
|
233
318
|
return self._fm_cache[fid]
|
|
234
319
|
except KeyError:
|
|
235
320
|
return self._fm_cache.setdefault(fid, QFontMetrics(font))
|
|
236
321
|
|
|
237
322
|
def fontmetrics_f(self, font):
|
|
238
|
-
fid = font
|
|
323
|
+
fid = font_key_cached(font)
|
|
239
324
|
try:
|
|
240
325
|
return self._fm_cache_f[fid]
|
|
241
326
|
except KeyError:
|
|
@@ -270,7 +355,7 @@ class QwtPlainTextEngine(QwtTextEngine):
|
|
|
270
355
|
|
|
271
356
|
def effectiveAscent(self, font):
|
|
272
357
|
global ASCENTCACHE
|
|
273
|
-
fontKey = font
|
|
358
|
+
fontKey = font_key_cached(font)
|
|
274
359
|
ascent = ASCENTCACHE.get(fontKey)
|
|
275
360
|
if ascent is not None:
|
|
276
361
|
return ascent
|
|
@@ -317,11 +402,19 @@ class QwtPlainTextEngine(QwtTextEngine):
|
|
|
317
402
|
:param QFont font: Font of the text
|
|
318
403
|
:return: tuple (left, right, top, bottom) representing margins
|
|
319
404
|
"""
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
405
|
+
# Fast path: same QFont object as the previous call.
|
|
406
|
+
font_id = id(font)
|
|
407
|
+
if font_id == self._margins_last_id:
|
|
408
|
+
return self._margins_last_value
|
|
409
|
+
fkey = font_key_cached(font)
|
|
410
|
+
cached = self._margins_cache.get(fkey)
|
|
411
|
+
if cached is None:
|
|
412
|
+
fm = self.fontmetrics(font)
|
|
413
|
+
cached = (0, 0, fm.ascent() - self.effectiveAscent(font), fm.descent())
|
|
414
|
+
self._margins_cache[fkey] = cached
|
|
415
|
+
self._margins_last_id = font_id
|
|
416
|
+
self._margins_last_value = cached
|
|
417
|
+
return cached
|
|
325
418
|
|
|
326
419
|
def draw(self, painter, rect, flags, text):
|
|
327
420
|
"""
|
|
@@ -464,10 +557,26 @@ class QwtRichTextEngine(QwtTextEngine):
|
|
|
464
557
|
return 0, 0, 0, 0
|
|
465
558
|
|
|
466
559
|
|
|
467
|
-
class QwtText_PrivateData(
|
|
468
|
-
|
|
469
|
-
|
|
560
|
+
class QwtText_PrivateData(object):
|
|
561
|
+
# ``QObject`` was previously used as the base class but no Qt signals
|
|
562
|
+
# or events are ever emitted from ``_PrivateData`` containers and the
|
|
563
|
+
# ``QObject.__init__`` call dominates ``QwtText.__init__`` (it is the
|
|
564
|
+
# single most expensive line for tick-label-heavy renders, see
|
|
565
|
+
# https://github.com/PlotPyStack/PythonQwt/issues/93).
|
|
566
|
+
__slots__ = (
|
|
567
|
+
"renderFlags",
|
|
568
|
+
"borderRadius",
|
|
569
|
+
"borderPen",
|
|
570
|
+
"backgroundBrush",
|
|
571
|
+
"paintAttributes",
|
|
572
|
+
"layoutAttributes",
|
|
573
|
+
"textEngine",
|
|
574
|
+
"text",
|
|
575
|
+
"font",
|
|
576
|
+
"color",
|
|
577
|
+
)
|
|
470
578
|
|
|
579
|
+
def __init__(self):
|
|
471
580
|
self.renderFlags = Qt.AlignCenter
|
|
472
581
|
self.borderRadius = 0
|
|
473
582
|
self.borderPen = Qt.NoPen
|
|
@@ -484,10 +593,13 @@ class QwtText_PrivateData(QObject):
|
|
|
484
593
|
class QwtText_LayoutCache(object):
|
|
485
594
|
def __init__(self):
|
|
486
595
|
self.textSize = None
|
|
487
|
-
self.
|
|
596
|
+
self.fontKey = None
|
|
597
|
+
self.fontId = -1
|
|
488
598
|
|
|
489
599
|
def invalidate(self):
|
|
490
600
|
self.textSize = None
|
|
601
|
+
self.fontKey = None
|
|
602
|
+
self.fontId = -1
|
|
491
603
|
|
|
492
604
|
|
|
493
605
|
class QwtText(object):
|
|
@@ -727,7 +839,13 @@ class QwtText(object):
|
|
|
727
839
|
:py:meth:`renderFlags()`,
|
|
728
840
|
:py:meth:`qwt.text.QwtTextEngine.draw()`
|
|
729
841
|
"""
|
|
730
|
-
|
|
842
|
+
# Wrap into Qt.AlignmentFlag so that downstream Qt APIs (notably
|
|
843
|
+
# ``QTextOption.setAlignment``, ``QPainter.drawText``,
|
|
844
|
+
# ``QFontMetrics.boundingRect``) that strictly require an enum on
|
|
845
|
+
# PyQt6 keep working. Hot bitwise-test sites locally cast back to
|
|
846
|
+
# int to avoid the per-test enum.__and__ cost.
|
|
847
|
+
if not isinstance(renderFlags, Qt.AlignmentFlag):
|
|
848
|
+
renderFlags = Qt.AlignmentFlag(renderFlags)
|
|
731
849
|
if renderFlags != self.__data.renderFlags:
|
|
732
850
|
self.__data.renderFlags = renderFlags
|
|
733
851
|
self.__layoutCache.invalidate()
|
|
@@ -994,17 +1112,24 @@ class QwtText(object):
|
|
|
994
1112
|
:param QFont defaultFont Font, used for the calculation if the text has no font
|
|
995
1113
|
:return: Caluclated size
|
|
996
1114
|
"""
|
|
997
|
-
font =
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1115
|
+
font = self.usedFont(defaultFont)
|
|
1116
|
+
cache = self.__layoutCache
|
|
1117
|
+
font_id = id(font)
|
|
1118
|
+
if cache.textSize is not None and cache.fontId == font_id:
|
|
1119
|
+
sz = QSizeF(cache.textSize)
|
|
1120
|
+
else:
|
|
1121
|
+
fkey = font_key_cached(font)
|
|
1122
|
+
if (
|
|
1123
|
+
cache.textSize is None
|
|
1124
|
+
or not cache.textSize.isValid()
|
|
1125
|
+
or cache.fontKey != fkey
|
|
1126
|
+
):
|
|
1127
|
+
cache.textSize = self.__data.textEngine.textSize(
|
|
1128
|
+
font, self.__data.renderFlags, self.__data.text
|
|
1129
|
+
)
|
|
1130
|
+
cache.fontKey = fkey
|
|
1131
|
+
cache.fontId = font_id
|
|
1132
|
+
sz = QSizeF(cache.textSize)
|
|
1008
1133
|
if self.__data.layoutAttributes & self.MinimumLayout:
|
|
1009
1134
|
(left, right, top, bottom) = self.__data.textEngine.textMargins(font)
|
|
1010
1135
|
sz -= QSizeF(left + right, top + bottom)
|
|
@@ -1072,7 +1197,13 @@ class QwtText(object):
|
|
|
1072
1197
|
return self.__map.get(format_)
|
|
1073
1198
|
elif format_ is not None:
|
|
1074
1199
|
if format_ == QwtText.AutoText:
|
|
1075
|
-
|
|
1200
|
+
# Fast path: a string with no ``<`` cannot be rich text, so
|
|
1201
|
+
# we can return the plain engine without iterating the map
|
|
1202
|
+
# and calling Qt.mightBeRichText (which is a hot Qt call
|
|
1203
|
+
# for tick labels like " 1.5").
|
|
1204
|
+
if "<" not in text:
|
|
1205
|
+
return self.__map[QwtText.PlainText]
|
|
1206
|
+
for key, engine in self.__map.items():
|
|
1076
1207
|
if key != QwtText.PlainText:
|
|
1077
1208
|
if engine and engine.mightRender(text):
|
|
1078
1209
|
return engine
|
|
@@ -1291,10 +1422,10 @@ class QwtTextLabel(QFrame):
|
|
|
1291
1422
|
if indent <= 0:
|
|
1292
1423
|
indent = self.defaultIndent()
|
|
1293
1424
|
if indent > 0:
|
|
1294
|
-
align = self.__data.text.renderFlags()
|
|
1295
|
-
if align &
|
|
1425
|
+
align = _flag_int(self.__data.text.renderFlags())
|
|
1426
|
+
if align & (_ALIGN_LEFT | _ALIGN_RIGHT):
|
|
1296
1427
|
mw += self.__data.indent
|
|
1297
|
-
elif align &
|
|
1428
|
+
elif align & (_ALIGN_TOP | _ALIGN_BOTTOM):
|
|
1298
1429
|
mh += self.__data.indent
|
|
1299
1430
|
sz += QSizeF(mw, mh)
|
|
1300
1431
|
return QSize(math.ceil(sz.width()), math.ceil(sz.height()))
|
|
@@ -1304,15 +1435,15 @@ class QwtTextLabel(QFrame):
|
|
|
1304
1435
|
:param int width: Width
|
|
1305
1436
|
:return: Preferred height for this widget, given the width.
|
|
1306
1437
|
"""
|
|
1307
|
-
renderFlags = self.__data.text.renderFlags()
|
|
1438
|
+
renderFlags = _flag_int(self.__data.text.renderFlags())
|
|
1308
1439
|
indent = self.__data.indent
|
|
1309
1440
|
if indent <= 0:
|
|
1310
1441
|
indent = self.defaultIndent()
|
|
1311
1442
|
width -= 2 * self.frameWidth()
|
|
1312
|
-
if renderFlags &
|
|
1443
|
+
if renderFlags & (_ALIGN_LEFT | _ALIGN_RIGHT):
|
|
1313
1444
|
width -= indent
|
|
1314
1445
|
height = math.ceil(self.__data.text.heightForWidth(width, self.font()))
|
|
1315
|
-
if renderFlags &
|
|
1446
|
+
if renderFlags & (_ALIGN_TOP | _ALIGN_BOTTOM):
|
|
1316
1447
|
height += indent
|
|
1317
1448
|
height += 2 * self.frameWidth()
|
|
1318
1449
|
return height
|
|
@@ -1372,14 +1503,14 @@ class QwtTextLabel(QFrame):
|
|
|
1372
1503
|
if indent <= 0:
|
|
1373
1504
|
indent = self.defaultIndent()
|
|
1374
1505
|
if indent > 0:
|
|
1375
|
-
renderFlags = self.__data.text.renderFlags()
|
|
1376
|
-
if renderFlags &
|
|
1506
|
+
renderFlags = _flag_int(self.__data.text.renderFlags())
|
|
1507
|
+
if renderFlags & _ALIGN_LEFT:
|
|
1377
1508
|
r.setX(r.x() + indent)
|
|
1378
|
-
elif renderFlags &
|
|
1509
|
+
elif renderFlags & _ALIGN_RIGHT:
|
|
1379
1510
|
r.setWidth(r.width() - indent)
|
|
1380
|
-
elif renderFlags &
|
|
1511
|
+
elif renderFlags & _ALIGN_TOP:
|
|
1381
1512
|
r.setY(r.y() + indent)
|
|
1382
|
-
elif renderFlags &
|
|
1513
|
+
elif renderFlags & _ALIGN_BOTTOM:
|
|
1383
1514
|
r.setHeight(r.height() - indent)
|
|
1384
1515
|
return r
|
|
1385
1516
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|