Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Bug]: Saving as an SVG and PDF produce different outputs with Latex characters, with wrong character sizing #29791

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jamesmeiklejohn opened this issue Mar 21, 2025 · 3 comments
Labels
status: has patch patch suggested, PR still needed topic: text/usetex

Comments

@jamesmeiklejohn
Copy link

Bug summary

When saving certain outputs using Latex rendering as an SVG, it produces wrong outputs. Using plt.show() it renders correctly, and it works for saving as a PDF, but saving the output as a SVG math environment characters can render in the wrong size (see attached screenshots.)

Code for reproduction

from pathlib import Path
import pandas as pd
import matplotlib.pyplot as plt
import scienceplots


BASE_PATH = Path(__file__).parent
DATA_PATH = BASE_PATH / "ion_ranges.csv"


plt.style.use(['science', 'latex-siunitx'])

dat = pd.read_csv(DATA_PATH)

plt.plot(dat["energy"], dat["projected_range_um"], marker="o", linestyle="-")
plt.xlabel("Energy (keV)")
plt.ylabel(r"Projected Range (\si{\um})")
plt.tight_layout()
plt.savefig(BASE_PATH / "ion_ranges_plot.pdf")

Actual outcome

Image

Expected outcome

ion_ranges_plot.pdf

Additional information

No response

Operating system

No response

Matplotlib Version

3.10.1

Matplotlib Backend

No response

Python version

No response

Jupyter version

No response

Installation

None

@jklymak
Copy link
Member

jklymak commented Mar 21, 2025

We don;'t provide the styles science or siunitx. Without those files it is hard to know if this is a Matplotlib bug or a bug in wherever you got those style files. Can you make a reproducible, self contained example that just uses Matplotlib and numpy?

@jklymak jklymak added the status: needs clarification Issues that need more information to resolve. label Mar 21, 2025
@anntzer
Copy link
Contributor

anntzer commented Mar 22, 2025

I am almost certain that this is the same issue as the glyph sizing issue reported in #12928 (which that PR didn't fix). Probably need to revive #14159...

Repro:

rcParams["text.latex.preamble"] = r"\usepackage{siunitx}"; figtext(.5, .5, r"\si{\um}", usetex=True); savefig("/tmp/test.svg")
# or, without siunitx
figtext(.5, .5, r"ff\textwon", usetex=True); savefig("/tmp/test.svg")

@anntzer anntzer added topic: text/usetex and removed status: needs clarification Issues that need more information to resolve. labels Mar 22, 2025
@anntzer
Copy link
Contributor

anntzer commented Mar 22, 2025

Figured this out (after 6 years...). The following patch fixes the issue (it is derived from #27654 (comment) but not loading the incompatible type1cm anymore, which may have been the cause of the test failures reported in the linked comment)

diff --git i/lib/matplotlib/mpl-data/matplotlibrc w/lib/matplotlib/mpl-data/matplotlibrc
index ab412302f3..3dc0a4e2e3 100644
--- i/lib/matplotlib/mpl-data/matplotlibrc
+++ w/lib/matplotlib/mpl-data/matplotlibrc
@@ -334,7 +334,7 @@
                         # become quite long.
                         # The following packages are always loaded with usetex,
                         # so beware of package collisions:
-                        #   geometry, inputenc, type1cm.
+                        #   color, fix-cm, geometry, graphicx, textcomp.
                         # PostScript (PSNFSS) font packages may also be
                         # loaded, depending on your font settings.
 
diff --git i/lib/matplotlib/mpl-data/stylelib/classic.mplstyle w/lib/matplotlib/mpl-data/stylelib/classic.mplstyle
index 6cba66076a..ca9b04a2cb 100644
--- i/lib/matplotlib/mpl-data/stylelib/classic.mplstyle
+++ w/lib/matplotlib/mpl-data/stylelib/classic.mplstyle
@@ -122,8 +122,8 @@ text.latex.preamble :  # IMPROPER USE OF THIS FEATURE WILL LEAD TO LATEX FAILURE
                        # Note that it has to be put on a single line, which may
                        # become quite long.
                        # The following packages are always loaded with usetex, so
-                       # beware of package collisions: color, geometry, graphicx,
-                       # type1cm, textcomp.
+                       # beware of package collisions:
+                       #   color, fix-cm, geometry, graphicx, textcomp.
                        # Adobe Postscript (PSSNFS) font packages may also be
                        # loaded, depending on your font settings.
 
diff --git i/lib/matplotlib/texmanager.py w/lib/matplotlib/texmanager.py
index 94fc94e9e8..c10f90a796 100644
--- i/lib/matplotlib/texmanager.py
+++ w/lib/matplotlib/texmanager.py
@@ -67,6 +67,13 @@ class TexManager:
     _grey_arrayd = {}
 
     _font_families = ('serif', 'sans-serif', 'cursive', 'monospace')
+    # Check for the cm-super package (which registers unicode computer modern
+    # support just by being installed) without actually loading any package
+    # (because we already load the incompatible fix-cm).
+    _check_cmsuper_installed = (
+        r'\IfFileExists{type1ec.sty}{}{\PackageError{matplotlib-support}{'
+        r'Missing cm-super package, required by Matplotlib}{}}'
+    )
     _font_preambles = {
         'new century schoolbook': r'\renewcommand{\rmdefault}{pnc}',
         'bookman': r'\renewcommand{\rmdefault}{pbk}',
@@ -83,10 +90,10 @@ class TexManager:
         # Loading the type1ec package ensures that cm-super is installed, which
         # is necessary for Unicode computer modern.  (It also allows the use of
         # computer modern at arbitrary sizes, but that's just a side effect.)
-        'monospace': r'\usepackage{type1ec}',
-        'computer modern roman': r'\usepackage{type1ec}',
-        'computer modern sans serif': r'\usepackage{type1ec}',
-        'computer modern typewriter': r'\usepackage{type1ec}',
+        'monospace': _check_cmsuper_installed,
+        'computer modern roman': _check_cmsuper_installed,
+        'computer modern sans serif': _check_cmsuper_installed,
+        'computer modern typewriter': _check_cmsuper_installed,
     }
     _font_types = {
         'new century schoolbook': 'serif',
@@ -200,6 +207,7 @@ class TexManager:
         font_preamble, fontcmd = cls._get_font_preamble_and_command()
         baselineskip = 1.25 * fontsize
         return "\n".join([
+            r"\RequirePackage{fix-cm}",
             r"\documentclass{article}",
             r"% Pass-through \mathdefault, which is used in non-usetex mode",
             r"% to use the default text font but was historically suppressed",

It also supersedes #14159 which turns out to not have been the right approach after all. This would also close #27654 and #28675.

The fundamental underlying issue is the following: for glyph to path conversion (used by svg), textpath renders the text at fontsize FONT_SCALE = 100, and scales it appropriately after. But type1ec, despite its name, doesn't actually allow rendering glyphs such as the micro-sign or the won sign at that size; manually compiling the tex file generated by texmanager.py shows the warning

LaTeX Font Warning: Font shape `TS1/cmr/m/n' in size <100> not available
(Font)              size <35.83> substituted on input line 31.

i.e. the micro sign is actually rendered ~3x smaller than the rest of the text (and then the ratio is kept when scaling down the text). Why greater sizes are now allowed remains a bit a mystery to me, as there's clearly an entry for bigger sizes in https://mirrors.ircam.fr/pub/CTAN/fonts/ps-type1/cm-super/type1ec.sty (<35.83->#53583%) but heh. In any case, using fix-cm allows rendering these glyphs correctly at size 100 and fixes the issue.

More links:

A side question that remains is whether textpath should really generate the glyphs at fontsize 100 and scale them (usually down) later. Indeed, size 100 computer modern is not the same as size 5 computer modern scaled up 20 times (see e.g. https://tex.stackexchange.com/questions/18721/). FWIW I don't see why textpath couldn't just do the rendering at the "real" requested size indicated in fontproperties...

@anntzer anntzer added the status: has patch patch suggested, PR still needed label Mar 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: has patch patch suggested, PR still needed topic: text/usetex
Projects
None yet
Development

No branches or pull requests

3 participants