Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions manimlib/default_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ directories:
data: "data"
# When downloading, say an image, where will it go?
downloads: "downloads"
# For storing cached LaTeX compilation results
latex_cache: "latex_cache"
# For certain object types, especially Tex and Text, manim will save information
# to file to prevent the need to re-compute, e.g. recompiling the latex. By default,
# it stores this saved data to whatever directory appdirs.user_cache_dir("manim") returns,
Expand Down
97 changes: 50 additions & 47 deletions manimlib/utils/tex_file_writing.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,53 +93,56 @@ def full_tex_to_svg(full_tex: str, compiler: str = "latex", message: str = ""):
else:
raise NotImplementedError(f"Compiler '{compiler}' is not implemented")

# Write intermediate files to a temporary directory
with tempfile.TemporaryDirectory() as temp_dir:
tex_path = Path(temp_dir, "working").with_suffix(".tex")
dvi_path = tex_path.with_suffix(dvi_ext)

# Write tex file
tex_path.write_text(full_tex)

# Run latex compiler
process = subprocess.run(
[
compiler,
*(['-no-pdf'] if compiler == "xelatex" else []),
"-interaction=batchmode",
"-halt-on-error",
f"-output-directory={temp_dir}",
tex_path
],
capture_output=True,
text=True
)

if process.returncode != 0:
# Handle error
error_str = ""
log_path = tex_path.with_suffix(".log")
if log_path.exists():
content = log_path.read_text()
error_match = re.search(r"(?<=\n! ).*\n.*\n", content)
if error_match:
error_str = error_match.group()
raise LatexError(error_str or "LaTeX compilation failed")

# Run dvisvgm and capture output directly
process = subprocess.run(
[
"dvisvgm",
dvi_path,
"-n", # no fonts
"-v", "0", # quiet
"--stdout", # output to stdout instead of file
],
capture_output=True
)

# Return SVG string
result = process.stdout.decode('utf-8')
# Use the custom LaTeX cache directory from the config
temp_dir = Path(manim_config.directories.latex_cache)
temp_dir.mkdir(exist_ok=True) # Create the directory if it does not already exist

# Define paths for the intermediate TeX and DVI files
tex_path = temp_dir / "working.tex"
dvi_path = tex_path.with_suffix(dvi_ext)

# Write tex file
tex_path.write_text(full_tex)

# Run latex compiler
process = subprocess.run(
[
compiler,
*(['-no-pdf'] if compiler == "xelatex" else []),
"-interaction=batchmode",
"-halt-on-error",
f"-output-directory={temp_dir}",
tex_path
],
capture_output=True,
text=True
)

if process.returncode != 0:
# Handle error
error_str = ""
log_path = tex_path.with_suffix(".log")
if log_path.exists():
content = log_path.read_text()
error_match = re.search(r"(?<=\n! ).*\n.*\n", content)
if error_match:
error_str = error_match.group()
raise LatexError(error_str or "LaTeX compilation failed")

# Run dvisvgm and capture output directly
process = subprocess.run(
[
"dvisvgm",
dvi_path,
"-n", # no fonts
"-v", "0", # quiet
"--stdout", # output to stdout instead of file
],
capture_output=True
)

# Return SVG string
result = process.stdout.decode('utf-8')

if message:
print(" " * len(message), end="\r")
Expand Down