[ManimGL 源码解读] SingleStringTex 如何渲染公式
和 Tex
一样,定义在 manimlib/mobject/svg/tex_mobject.py
。传入单个字符串 tex_string
渲染出 SVGMobject
。
检测类型,保存 tex_string
,调用 SVGMobject.__init__
。
init_svg_mobject
大概就是设置散列(Hash),生成 SVG。
SingleStringTex
重写了 SVGMobject.hash_seed
(获取散列种子方法)。
与父类相比,SingleStringTex.hash_seed
去掉 file_name
(因为是 None
),添加 tex_string
(传入的 LaTeX 字符串)、alignment
(对齐方式,默认 "\centering"
)、math_mode
(是否开启数学环境,默认 True
)(为什么要这样做?)。
SVG_HASH_TO_MOB_MAP
是一个存储 VMobject
的散列值的字典。
generate_mobject
生成 SVG。
SingleStringTex
重写了 get_file_path
方法。它会根据一开始提供的 tex_string
渲染 SVG 文件,返回文件名。display_during_execution
给出提示信息。
get_tex_file_body
获得最终写入 .tex
的字符串。
get_modified_expression
获得 tex_string
特殊处理(大概是补全括号之类的)后的字符串,用 new_tex
保存。
modify_special_strings
特殊处理 tex_string
(这两个函数直接把我整蒙了,get_modified_expression
里面就直接 return
掉,差不多就是起了个别名。而且它还会对一个字符串 strip
两次⋯⋯我很难理解这样做的用意)。
(modify_special_strings
代码我就不贴了,60+ 行又臭又长)
tex_to_svg_file
读取 .tex
文件位置,根据 tex_file_content
计算散列值构造文件名(svg_file
)。如果没有渲染过,则写入 .tex
文件并渲染它。
get_tex_dir
获得保存 .tex
文件的文件夹。
get_temp_dir
获得保存临时文件的位置。在 Linux 上是 /tmp
。
get_directories
获得文件夹设置。
CUSTOMIZATION
一开始是空字典,第一次调用后就会把 default_config.yml
和 custom_config.yml
(若存在)转换成字典。可以看出,这里有对 temporary_storage
特判:若它是空字符串 ""
,则把它设置为操作系统的默认临时文件存放位置(tempfile.gettempdir()
)。
guarantee_existence
保证文件夹存在。如果不存在就新建文件夹。
tex_hash
根据 tex_content
生成对应散列值,这是用于判断两个 SingleStringTex
是否相等的方法。回想前面的 SingleStringTex.hash_seed
,增加的内容正好共同决定了 tex_content
。其实现在你还可以再看看 SVGMobject.init_svg_mobject
,相同的不仅不会重复渲染,也不会重复执行 generate_mobject
。
现在我们终于弄清 ManimGL 如何生成 .tex
的文件名的细节了。这时文件名保存在 tex_to_svg_file
变量里,最终返回的也是这个变量。接下来我们来看看 ManimGL 怎么调用 LaTeX,怎么生成最终的 SVG 文件。
tex_to_svg
把传入的 tex_file_content
渲染成 SVG,写入传入的 svg_file
,返回 svg_file
。可以看到,svg_file
的后缀转换成 .svg
,保存在 tex_file
。接着打开文件,把 tex_file_content
写入 tex_file
,开始渲染(如果以前渲染过的话就不会调用 tex_to_svg
)。渲染完成后,把除了 .svg
的文件删除。
tex_to_dvi
调用 letax
(xelatex -no-pdf
) 把 .tex
渲染成 .dvi
(.xdv
) 文件。
dvi_to_svg
调用 dvisvgm
把 .dvi
转换成 .svg
文件。
回到生成 SVG 的 generate_mobject
,后面是杂七杂八地对 .svg
一顿操作。不过这些都不是和渲染公式相关的,不是本文重点。
回到 SVGMobject.__init__
,后面是调用设置颜色、位置的方法。
再退回 SingleStringTex.__init__
,后面是设置高度、给 submobjects
排序。
没了。