rsplotlib 0.1.4__cp313-cp313-macosx_11_0_arm64.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.
- rsplotlib/__init__.py +15 -0
- rsplotlib/_figure_defaults.py +10 -0
- rsplotlib/_font_resolver.py +167 -0
- rsplotlib/_rcparams.py +58 -0
- rsplotlib/api.py +729 -0
- rsplotlib/gridspec.py +111 -0
- rsplotlib/pylab.py +20 -0
- rsplotlib/pyplot.py +545 -0
- rsplotlib/rsplotlib.cpython-313-darwin.so +0 -0
- rsplotlib/style.py +56 -0
- rsplotlib/ticker.py +278 -0
- rsplotlib-0.1.4.dist-info/METADATA +179 -0
- rsplotlib-0.1.4.dist-info/RECORD +16 -0
- rsplotlib-0.1.4.dist-info/WHEEL +4 -0
- rsplotlib-0.1.4.dist-info/licenses/LICENSE +21 -0
- rsplotlib-0.1.4.dist-info/sboms/rsplotlib.cyclonedx.json +1922 -0
rsplotlib/__init__.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""rsplotlib 包顶层导出。建议通过导入自 `rsplotlib.api` 使用公开 API。"""
|
|
2
|
+
|
|
3
|
+
from .api import *
|
|
4
|
+
from .api import __all__ as _api_all
|
|
5
|
+
from .rsplotlib import register_sans_serif_font
|
|
6
|
+
from . import pyplot, style, gridspec, ticker
|
|
7
|
+
|
|
8
|
+
GridSpec = gridspec.GridSpec
|
|
9
|
+
MaxNLocator = ticker.MaxNLocator
|
|
10
|
+
MultipleLocator = ticker.MultipleLocator
|
|
11
|
+
AutoMinorLocator = ticker.AutoMinorLocator
|
|
12
|
+
|
|
13
|
+
# 从内部 Rust 模块导出字体注册函数
|
|
14
|
+
|
|
15
|
+
__all__ = list(_api_all) + ['pyplot', 'style', 'gridspec', 'ticker', 'GridSpec', 'MaxNLocator', 'MultipleLocator', 'AutoMinorLocator', 'register_sans_serif_font']
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""rsplotlib._font_resolver - 字体族名 → 字体文件路径解析
|
|
2
|
+
|
|
3
|
+
将 matplotlib 风格的无衬线字体族名(如 "Arial Unicode MS"、"Helvetica Neue")
|
|
4
|
+
映射到本地字体文件路径。找不到时返回 None,由调用方决定回退到默认字体。
|
|
5
|
+
"""
|
|
6
|
+
import os
|
|
7
|
+
from typing import Optional, List
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# ====== 字体族名 → 候选文件路径映射(按平台分别维护)======
|
|
12
|
+
|
|
13
|
+
_FONT_NAME_TO_PATHS = {
|
|
14
|
+
# macOS
|
|
15
|
+
"Arial Unicode MS": [
|
|
16
|
+
"/Library/Fonts/Arial Unicode.ttf",
|
|
17
|
+
"/System/Library/Fonts/Supplemental/Arial Unicode.ttf",
|
|
18
|
+
],
|
|
19
|
+
"Arial": [
|
|
20
|
+
"/Library/Fonts/Arial.ttf",
|
|
21
|
+
"/System/Library/Fonts/Supplemental/Arial.ttf",
|
|
22
|
+
],
|
|
23
|
+
"Helvetica": [
|
|
24
|
+
"/System/Library/Fonts/Helvetica.ttc",
|
|
25
|
+
"/System/Library/Fonts/HelveticaNeue.ttc",
|
|
26
|
+
],
|
|
27
|
+
"Helvetica Neue": [
|
|
28
|
+
"/System/Library/Fonts/HelveticaNeue.ttc",
|
|
29
|
+
],
|
|
30
|
+
"PingFang SC": [
|
|
31
|
+
"/System/Library/Fonts/PingFang.ttc",
|
|
32
|
+
],
|
|
33
|
+
"Heiti SC": [
|
|
34
|
+
"/System/Library/Fonts/STHeiti Light.ttc",
|
|
35
|
+
"/System/Library/Fonts/STHeiti Medium.ttc",
|
|
36
|
+
],
|
|
37
|
+
"Hiragino Sans GB": [
|
|
38
|
+
"/System/Library/Fonts/Hiragino Sans GB W3.otf",
|
|
39
|
+
"/System/Library/Fonts/Hiragino Sans GB W6.otf",
|
|
40
|
+
],
|
|
41
|
+
# Linux
|
|
42
|
+
"DejaVu Sans": [
|
|
43
|
+
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
|
44
|
+
"/usr/share/fonts/dejavu/DejaVuSans.ttf",
|
|
45
|
+
],
|
|
46
|
+
"Liberation Sans": [
|
|
47
|
+
"/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
|
|
48
|
+
],
|
|
49
|
+
"Noto Sans CJK SC": [
|
|
50
|
+
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
|
|
51
|
+
"/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc",
|
|
52
|
+
"/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc",
|
|
53
|
+
],
|
|
54
|
+
"WenQuanYi Micro Hei": [
|
|
55
|
+
"/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
|
|
56
|
+
],
|
|
57
|
+
# Windows
|
|
58
|
+
"Microsoft YaHei": [
|
|
59
|
+
"C:/Windows/Fonts/msyh.ttc",
|
|
60
|
+
"C:/Windows/Fonts/msyh.ttf",
|
|
61
|
+
"C:/Windows/Fonts/msyhbd.ttc",
|
|
62
|
+
],
|
|
63
|
+
"SimHei": [
|
|
64
|
+
"C:/Windows/Fonts/simhei.ttf",
|
|
65
|
+
],
|
|
66
|
+
"SimSun": [
|
|
67
|
+
"C:/Windows/Fonts/simsun.ttc",
|
|
68
|
+
],
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# 跨平台按系统名归一化的额外兜底字体路径
|
|
73
|
+
|
|
74
|
+
def _system_fallback_paths() -> List[str]:
|
|
75
|
+
"""按当前操作系统返回一组"通用全功能字体"候选路径"""
|
|
76
|
+
system = sys.platform
|
|
77
|
+
if system == "darwin":
|
|
78
|
+
return [
|
|
79
|
+
"/Library/Fonts/Arial Unicode.ttf",
|
|
80
|
+
"/System/Library/Fonts/Supplemental/Arial Unicode.ttf",
|
|
81
|
+
]
|
|
82
|
+
elif system == "linux":
|
|
83
|
+
return [
|
|
84
|
+
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
|
|
85
|
+
"/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc",
|
|
86
|
+
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
|
87
|
+
"/usr/share/fonts/dejavu/DejaVuSans.ttf",
|
|
88
|
+
]
|
|
89
|
+
elif system == "win32":
|
|
90
|
+
return [
|
|
91
|
+
"C:/Windows/Fonts/msyh.ttc",
|
|
92
|
+
"C:/Windows/Fonts/msyh.ttf",
|
|
93
|
+
"C:/Windows/Fonts/msyhbd.ttc",
|
|
94
|
+
]
|
|
95
|
+
elif system == "cygwin":
|
|
96
|
+
return [
|
|
97
|
+
"C:/Windows/Fonts/msyh.ttc",
|
|
98
|
+
"C:/Windows/Fonts/arial.ttf",
|
|
99
|
+
]
|
|
100
|
+
return []
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def resolve_font_path(family: str) -> Optional[str]:
|
|
104
|
+
"""根据字体族名查找本地的字体文件路径。
|
|
105
|
+
|
|
106
|
+
找不到时返回 None。
|
|
107
|
+
"""
|
|
108
|
+
if not family:
|
|
109
|
+
return None
|
|
110
|
+
# 精确匹配
|
|
111
|
+
candidates = _FONT_NAME_TO_PATHS.get(family, [])
|
|
112
|
+
for path in candidates:
|
|
113
|
+
if os.path.isfile(path):
|
|
114
|
+
return path
|
|
115
|
+
# 大小写不敏感匹配
|
|
116
|
+
lower_map = {k.lower(): v for k, v in _FONT_NAME_TO_PATHS.items()}
|
|
117
|
+
candidates = lower_map.get(family.lower(), [])
|
|
118
|
+
for path in candidates:
|
|
119
|
+
if os.path.isfile(path):
|
|
120
|
+
return path
|
|
121
|
+
# 平台回退
|
|
122
|
+
for path in _system_fallback_paths():
|
|
123
|
+
if os.path.isfile(path):
|
|
124
|
+
return path
|
|
125
|
+
return None
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def apply_rcparams_font() -> Optional[str]:
|
|
129
|
+
"""读取 rcParams["font.sans-serif"],把第一个能解析到本地文件的字体注册到 plotters。
|
|
130
|
+
|
|
131
|
+
返回实际注册的字体文件路径,如果没找到任何字体则返回 None。
|
|
132
|
+
"""
|
|
133
|
+
try:
|
|
134
|
+
# 延迟导入避免循环依赖
|
|
135
|
+
from . import rsplotlib as _rsplotlib
|
|
136
|
+
from .pylab import mpl
|
|
137
|
+
except Exception:
|
|
138
|
+
return None
|
|
139
|
+
|
|
140
|
+
sans_serif = mpl.rcParams.get("font.sans-serif")
|
|
141
|
+
if not sans_serif:
|
|
142
|
+
return None
|
|
143
|
+
|
|
144
|
+
if isinstance(sans_serif, str):
|
|
145
|
+
candidates = [sans_serif]
|
|
146
|
+
else:
|
|
147
|
+
try:
|
|
148
|
+
candidates = list(sans_serif)
|
|
149
|
+
except TypeError:
|
|
150
|
+
candidates = [str(sans_serif)]
|
|
151
|
+
|
|
152
|
+
# "sans-serif" 关键字跳过:让 plotters 使用内部默认
|
|
153
|
+
candidates = [c for c in candidates if c and c.lower() != "sans-serif"]
|
|
154
|
+
|
|
155
|
+
for family in candidates:
|
|
156
|
+
path = resolve_font_path(family)
|
|
157
|
+
if path is None:
|
|
158
|
+
# 可能是直接的字体文件路径
|
|
159
|
+
if os.path.isfile(family):
|
|
160
|
+
path = family
|
|
161
|
+
if path is not None:
|
|
162
|
+
try:
|
|
163
|
+
_rsplotlib.register_sans_serif_font(path)
|
|
164
|
+
return path
|
|
165
|
+
except Exception:
|
|
166
|
+
continue
|
|
167
|
+
return None
|
rsplotlib/_rcparams.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""rsplotlib._rcparams - Matplotlib 兼容的 rcParams 配置管理
|
|
2
|
+
|
|
3
|
+
提供类似 matplotlib.rcParams 的全局配置字典,保存绘图相关的默认参数。
|
|
4
|
+
|
|
5
|
+
**字体钩子**:当用户设置 `rcParams["font.sans-serif"]` 时,会自动调用
|
|
6
|
+
`_font_resolver.apply_rcparams_font()`,把对应的字体文件注册到 plotters 的
|
|
7
|
+
字体数据库中,从而真正影响文本渲染(而不是像普通 dict 一样只更新值)。
|
|
8
|
+
"""
|
|
9
|
+
import copy as _copy
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
# 默认配置:与 matplotlib 保持一致的常用项
|
|
13
|
+
_DEFAULT_RC = {
|
|
14
|
+
'font.sans-serif': ['Helvetica', 'Arial', 'sans-serif'],
|
|
15
|
+
'axes.unicode_minus': True,
|
|
16
|
+
'font.size': 10,
|
|
17
|
+
'figure.figsize': [6.4, 4.8],
|
|
18
|
+
'figure.dpi': 100.0,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RcParams(dict):
|
|
23
|
+
"""与 matplotlib.rcParams 兼容的配置字典
|
|
24
|
+
|
|
25
|
+
区别于普通 dict:
|
|
26
|
+
1. 当访问不存在的键时返回 None 而不是抛出 KeyError。
|
|
27
|
+
2. **设置 `font.sans-serif` 时自动调用字体解析器**,把对应字体文件
|
|
28
|
+
注册到 plotters 的字体数据库中,使 plotters 真正使用用户指定的字体
|
|
29
|
+
渲染文字(而不是只更新一个不会生效的字符串列表)。
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, *args, **kwargs):
|
|
33
|
+
super().__init__(*args, **kwargs)
|
|
34
|
+
self.update(_DEFAULT_RC)
|
|
35
|
+
|
|
36
|
+
def __getitem__(self, key):
|
|
37
|
+
try:
|
|
38
|
+
return super().__getitem__(key)
|
|
39
|
+
except KeyError:
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
43
|
+
super().__setitem__(key, value)
|
|
44
|
+
# 字体钩子:用户在 Python 端改字体时同步通知 Rust 端注册
|
|
45
|
+
if key == 'font.sans-serif':
|
|
46
|
+
try:
|
|
47
|
+
# 延迟导入避免循环依赖
|
|
48
|
+
from ._font_resolver import apply_rcparams_font
|
|
49
|
+
apply_rcparams_font()
|
|
50
|
+
except Exception:
|
|
51
|
+
# 注册失败不影响 rcParams 写入
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# 全局单例
|
|
56
|
+
rcParams = RcParams()
|
|
57
|
+
# 原始默认配置副本(用于 rcParams.reset() 等恢复操作)
|
|
58
|
+
rcParamsOrig = _copy.deepcopy(rcParams)
|