diff --git a/graphs/gui/canvasPanel.py b/graphs/gui/canvasPanel.py index 4c862f6001..47ab4199ee 100644 --- a/graphs/gui/canvasPanel.py +++ b/graphs/gui/canvasPanel.py @@ -30,6 +30,7 @@ from logbook import Logger +from graphs.mpl_fonts import configure_matplotlib_font from graphs.style import BASE_COLORS, LIGHTNESSES, STYLES, hsl_to_hsv from gui.utils.numberFormatter import roundToPrec @@ -43,6 +44,7 @@ mpl_version = int(mpl.__version__[0]) or -1 if mpl_version >= 2: mpl.use('wxagg') + configure_matplotlib_font() graphFrame_enabled = True else: graphFrame_enabled = False diff --git a/graphs/mpl_fonts.py b/graphs/mpl_fonts.py new file mode 100644 index 0000000000..75d5977445 --- /dev/null +++ b/graphs/mpl_fonts.py @@ -0,0 +1,84 @@ +# ============================================================================= +# Copyright (C) 2026 Du Yifeng +# +# This file is part of pyfa. +# +# pyfa is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# pyfa is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with pyfa. If not, see . +# ============================================================================= +""" +Configures Matplotlib font fallback stack to include available system CJK fonts. +This ensures Chinese, Japanese, and Korean characters render correctly in graphs. +""" + +import platform + + +def configure_matplotlib_font(): + """ + Configure matplotlib to use fonts that can render CJK text. + """ + try: + import matplotlib as mpl + from matplotlib import font_manager + except ImportError: + return + + candidates = [] + + try: + # noinspection PyPackageRequirements + import wx + gui_face = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT).GetFaceName() + if gui_face: + candidates.append(gui_face) + except Exception: + pass + + candidates.extend([ + 'Noto Sans CJK KR', 'Noto Sans CJK JP', 'Noto Sans CJK SC', 'Noto Sans CJK TC', + 'Source Han Sans KR', 'Source Han Sans JP', 'Source Han Sans CN', 'Source Han Sans TW', + ]) + + system = platform.system() + if system == 'Windows': + candidates.extend([ + 'Microsoft YaHei', 'Microsoft JhengHei', 'SimHei', 'SimSun', + 'Malgun Gothic', 'Gulim', 'Dotum', 'Batang', + 'Yu Gothic', 'Meiryo', 'Arial Unicode MS', + ]) + elif system == 'Darwin': + candidates.extend([ + 'Apple SD Gothic Neo', 'AppleGothic', 'PingFang SC', 'PingFang TC', + 'Hiragino Sans GB', 'Hiragino Sans', 'Heiti SC', 'Arial Unicode MS', + ]) + else: + candidates.extend([ + 'NanumGothic', 'UnDotum', 'WenQuanYi Micro Hei', 'WenQuanYi Zen Hei', + 'Droid Sans Fallback', + ]) + + candidates.append('DejaVu Sans') + + # Filter out unavailable fonts to prevent Matplotlib warnings + available = {f.name for f in font_manager.fontManager.ttflist} + + resolved = [] + for name in candidates: + if name in available and name not in resolved: + resolved.append(name) + + if resolved: + mpl.rcParams['font.family'] = resolved + + mpl.rcParams['axes.unicode_minus'] = False