3b1b-manim/manimlib/utils/tex_file_writing.py

99 lines
2.8 KiB
Python
Raw Normal View History

2018-05-09 14:10:04 -07:00
import os
import hashlib
from manimlib.constants import TEX_DIR
from manimlib.constants import TEX_TEXT_TO_REPLACE
from manimlib.constants import TEX_USE_CTEX
2018-05-09 14:10:04 -07:00
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]
2018-05-09 14:10:04 -07:00
def tex_to_svg_file(expression, template_tex_file_body):
tex_file = generate_tex_file(expression, template_tex_file_body)
2018-05-09 14:10:04 -07:00
dvi_file = tex_to_dvi(tex_file)
return dvi_to_svg(dvi_file)
def generate_tex_file(expression, template_tex_file_body):
2018-05-09 14:10:04 -07:00
result = os.path.join(
TEX_DIR,
tex_hash(expression, template_tex_file_body)
2018-05-09 14:10:04 -07:00
) + ".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
)
2018-05-09 14:10:04 -07:00
with open(result, "w") as outfile:
outfile.write(new_body)
2018-05-09 14:10:04 -07:00
return result
def get_null():
if os.name == "nt":
return "NUL"
return "/dev/null"
def tex_to_dvi(tex_file):
2018-09-26 21:09:04 +08:00
result = tex_file.replace(".tex", ".dvi" if not TEX_USE_CTEX else ".xdv")
2018-05-09 14:10:04 -07:00
if not os.path.exists(result):
commands = [
"latex",
"-interaction=batchmode",
"-halt-on-error",
"-output-directory=" + TEX_DIR,
tex_file,
">",
get_null()
2018-09-26 21:09:04 +08:00
] if not TEX_USE_CTEX else [
"xelatex",
"-no-pdf",
"-interaction=batchmode",
"-halt-on-error",
"-output-directory=" + TEX_DIR,
tex_file,
">",
get_null()
2018-05-09 14:10:04 -07:00
]
exit_code = os.system(" ".join(commands))
if exit_code != 0:
log_file = tex_file.replace(".tex", ".log")
raise Exception(
2018-09-26 21:09:04 +08:00
("Latex error converting to dvi. " if not TEX_USE_CTEX
else "Xelatex error converting to xdv. ") +
2018-05-09 14:10:04 -07:00
"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
"""
2018-09-26 21:09:04 +08:00
result = dvi_file.replace(".dvi" if not TEX_USE_CTEX else ".xdv", ".svg")
2018-05-09 14:10:04 -07:00
if not os.path.exists(result):
commands = [
"dvisvgm",
dvi_file,
"-n",
"-v",
"0",
"-o",
result,
">",
get_null()
]
os.system(" ".join(commands))
return result