3b1b-manim/manimlib/utils/tex_file_writing.py
2019-06-17 15:40:03 -04:00

92 lines
2.8 KiB
Python

import os
import hashlib
from manimlib.constants import TEX_TEXT_TO_REPLACE
from manimlib.constants import TEX_USE_CTEX
import manimlib.constants as consts
def tex_hash(expression, template_tex_file_body):
id_str = str(expression + template_tex_file_body)
hasher = hashlib.sha256()
hasher.update(id_str.encode())
# Truncating at 16 bytes for cleanliness
return hasher.hexdigest()[:16]
def tex_to_svg_file(expression, template_tex_file_body):
tex_file = generate_tex_file(expression, template_tex_file_body)
dvi_file = tex_to_dvi(tex_file)
return dvi_to_svg(dvi_file)
def generate_tex_file(expression, template_tex_file_body):
result = os.path.join(
consts.TEX_DIR,
tex_hash(expression, template_tex_file_body)
) + ".tex"
if not os.path.exists(result):
print("Writing \"%s\" to %s" % (
"".join(expression), result
))
new_body = template_tex_file_body.replace(
TEX_TEXT_TO_REPLACE, expression
)
with open(result, "w", encoding="utf-8") as outfile:
outfile.write(new_body)
return result
def tex_to_dvi(tex_file):
result = tex_file.replace(".tex", ".dvi" if not TEX_USE_CTEX else ".xdv")
if not os.path.exists(result):
commands = [
"latex",
"-interaction=batchmode",
"-halt-on-error",
"-output-directory=\"{}\"".format(consts.TEX_DIR),
"\"{}\"".format(tex_file),
">",
os.devnull
] if not TEX_USE_CTEX else [
"xelatex",
"-no-pdf",
"-interaction=batchmode",
"-halt-on-error",
"-output-directory=\"{}\"".format(consts.TEX_DIR),
"\"{}\"".format(tex_file),
">",
os.devnull
]
exit_code = os.system(" ".join(commands))
if exit_code != 0:
log_file = tex_file.replace(".tex", ".log")
raise Exception(
("Latex error converting to dvi. " if not TEX_USE_CTEX
else "Xelatex error converting to xdv. ") +
"See log output above or the log file: %s" % log_file)
return result
def dvi_to_svg(dvi_file, regen_if_exists=False):
"""
Converts a dvi, which potentially has multiple slides, into a
directory full of enumerated pngs corresponding with these slides.
Returns a list of PIL Image objects for these images sorted as they
where in the dvi
"""
result = dvi_file.replace(".dvi" if not TEX_USE_CTEX else ".xdv", ".svg")
if not os.path.exists(result):
commands = [
"dvisvgm",
"\"{}\"".format(dvi_file),
"-n",
"-v",
"0",
"-o",
"\"{}\"".format(result),
">",
os.devnull
]
os.system(" ".join(commands))
return result