修复manim中Text类的bug
在使用manim时,对于Text类,会有一些bug,我尝试修复了它们
- 在
shaders
分支下无法使用Text类 - Text文字的stroke边框不完整,导致显示stroke会非常难看
- 含有空格的Text的空格不在文字内部,而在
ORIGIN
的位置,导致Transform
时会有字符在原位置和ORIGIN
之间反复横跳 - Text文字的默认大小要比TextMobject大,不容易像TextMobject一样控制大小
这些问题已经通过#1030修复到了manim的master分支中
$\mathcal{Bug\ 1.}$
当在shaders
分支下使用Text类时会出现如下报错:
其中最后一行让我发现此时的p0和p1的大小不相等,不能相加(broadcast),而p0和p1是通过贝赛尔曲线的次数(在shaders下是3)来拆分self.points
的
所以可能是self.points
的长度不为3的倍数,导致了错误.在print(len(self.points))
后发现确实是这样
然后我又用了 玄学 手段,删掉了SVGMobject的最后一个点,发现可以正常渲染
此时我又去看了cairo自动生成的svg代码,根据我之前学svg的一点经验,发现每个<path/>
的路径结尾都为Z M ... ... /">
而Z
是将路径闭合,但闭合后又多出了一个M
控制符,这会导致manim在处理svg时额外生成一个点
而删掉每个路径字符串的最后一个M
控制符,可以直接使用正则表达式匹配出来,然后替换掉
我第一个想到的正则表达式是Z M .*? /">
,但是如果在路径的中间出现Z M
,则会将其后面有用的部分一起删除
而有用的部分一定含有控制符,所以将控制符排除,就可以仅仅匹配掉最后一个M
,正则表达式:Z M [^A-Za-z]*? /">
1 | def remove_last_M(self, file_name): |
$\mathcal{Bug\ 2.}$
Text文字的stroke边框不完整,导致stroke显示不全,也会对DrawBorderThenFill
造成影响,也有B站的观众向我提了这个问题
– 话说,感觉每个Chapter之间的文字是不是先画出轮廓再填充上色,画完轮廓的时候停顿了一下。但是停顿的时候轮廓没有画完,有些地方有点断续的感觉
– Text类的bug,stroke日常乱套
为了解决这个问题,我只显示了stroke,并且用debugTeX
标出了构成每个字符的self.points
的位置,比如”manim”如下:
通过观察和与@XiaoYoung交流之后,确定了cairo生成的svg并不能使路径自动闭合
而在一般查看svg的软件(Chrome)中,svg图像只显示内部(fill),而stroke被忽略(很细),所以正常使用没问题
但是在manim中有时需要使用stroke,这时cairo生成的svg出现了bug,路径没有完全闭合
我最开始的想法是直接通过.add_line_to()
方法将svg收尾相连,但是这显然只解决了m和n
而a和i是由两条路径复合而成的,其中的每条路径都没有闭合,所以都需要手动闭合,所以我决定遍历self.points
这时我使用了一个last
变量来记录遍历到当前位置所在的路径上的起点,并且如果到了下一条路径(索引为nppc的倍数,并且不与前一个点相重合),就将首尾连接上,并更新last
而这样做还需要一个特判,当points为空时(空格)直接跳过,否则points[0]
会报错
1 | nppc = self.n_points_per_cubic_curve |
这样做之后,这个bug就完全解决了,而且中文也同时适用,对比如下,上为修复之前,下为修复之后(都为仅显示stroke)
$\mathcal{Bug\ 3.}$
这个是非常常见的问题了,如下:
之前解决这个问题是通过’假空格’,即用一个不常用字符表示空格,并将其设为背景色,或者opacity改成0
通过debugTeX可以发现,Text的空格占字符而且位置在ORIGIN
而TextMobject中的空格直接不占位置.所以我直接在处理bug2的同时,将len(each.points) == 0
的处理中加上了self.remove(each)
,这样就暂时解决了
而@XiaoYoung也提醒了我,这样的处理会干扰t2c的自动上色(下标改变了),在#1018这里,他决定单开一个pr来修复这个bug,所以我就把这一个commit删除掉了
$\mathcal{Bug\ 4.}$
Text文字的默认大小要比TextMobject大,不容易像TextMobject一样控制大小
通过阅读源码可以发现,TextMobject在__init__()
的结尾,有一句
1 | if self.height is None: |
而这个TEX_MOB_SCALE_FACTOR
默认为0.05
,即将默认的SVGMobject(高度为固定默认值)缩小为0.05倍
而Text类最后缩小了0.1倍,导致了大小不等,将其改为0.05后,就方便统一大小了
$\mathcal{Pull\ Requests}$
第一次提交pr,记录一下
- 将原repo fork到自己的用户上
- clone下来fork的repo
- 进行更改,add/commit/push,commit的注释要规范
- 在GitHub网页上,打开fork的repo,会有一个按钮
New Pull Request
- 比较,确认更改,然后
Create Pull Request
,表述出pr的必要性和验证,提交pr - 等待repo管理员merge
修复manim中Text类的bug