When I read a file of any text that is longer than 30 lines and use the resulting string to create a CairoText object, the creation crashes with the exception shown below. Standard setup as described in the documentation (Windows 10). But I think it has nothing to do with the setup.
from manim import *
class Test(Scene):
def construct(self):
with open("<path to file that has more than 30 lines>") as f:
code_raw = f.read()
code = CairoText(code_raw)
Traceback (most recent call last):
File "C:\Users\Chris\Documents\repos\manim\manim\__main__.py", line 75, in main
scene.render()
File "C:\Users\Chris\Documents\repos\manim\manim\scene\scene.py", line 88, in render
self.construct()
File "test.py", line 10, in construct
code = CairoText(code_raw)
File "C:\Users\Chris\Documents\repos\manim\manim\mobject\svg\text_mobject.py", line 136, in __init__
self.submobjects = [*self.gen_chars()]
File "C:\Users\Chris\Documents\repos\manim\manim\mobject\svg\text_mobject.py", line 187, in gen_chars
chars.add(self.submobjects[submobjects_char_index])
IndexError: list index out of range
Process finished with exit code 0
Thanks for reporting @ChristianCoenen. I can confirm this bug on latest master (even with a hard-coded very long string, no file involved).
There appears to be a limit on the actual width of the string that shows up on screen.
| Character | Max Number in string | Max Width| Single Char Width |
| ----------- | ----------- | -----------|------------------|
| A | 101 | 33.66953125| 0.31992185
| B | 101 |33.6261719| 0.2765625|
|a| 121 | 33.6166015| 0.2474609|
|莿| 55| 33.9277344| 0.5732422|
Any string lengthier than about 34 MUnits (without any scaling) seems to cause the IndexError.
If the string does turn out to be lengthier than 34 MUnits, CairoText.submobjects will be locked down to the number of characters whose length is lesser than 34 MUnits.
For example, if I try CairoText(101*"A"), everything works fine. CairoText.submobjects has exactly 101 elements.
BUT, if I try CairoText(102*"A"), CairoText.submobjects still only has 101 elements, and that causes the list index out of range error when CairoText.gen_chars tries to generate the 102nd "A", with the nonexistent 102nd element of CairoText.submobjects.
The same goes for 103*"A", 231*"A" and so on. In all cases with the letter "A" alone repeating more than 101 times, CairoText.submobjects has only 101 elements.
So I kept checking when the submobjects were actually created and in what order and traced it back to SVGMobject.generate_points.
And that is where I stopped investigating, because this _looks_ like a bug in SVGMobject's generate_points method, and SVGMobject is scary.
Great work. Yes, unfortunately, SVGMobject is not in good shape.
This is basically what I tried to fix with #476. For CairoText, we still might be able to fix it -- and Pango needs a bit more work anyways.
There appears to be a limit on the actual width of the string that shows up on screen.
Character Max Number in string Max Width Single Char Width
A 101 33.66953125 0.31992185
B 101 33.6261719 0.2765625
a 121 33.6166015 0.2474609
莿 55 33.9277344 0.5732422
Any string lengthier than about 34 MUnits (without any scaling) seems to cause the IndexError.If the string does turn out to be lengthier than 34 MUnits,
CairoText.submobjectswill be locked down to the number of characters whose length is lesser than 34 MUnits.For example, if I try
CairoText(101*"A"), everything works fine.CairoText.submobjectshas exactly 101 elements.BUT, if I try
CairoText(102*"A"),CairoText.submobjectsstill only has 101 elements, and that causes thelist index out of rangeerror whenCairoText.gen_charstries to generate the 102nd "A", with the nonexistent 102nd element ofCairoText.submobjects.The same goes for
103*"A",231*"A"and so on. In all cases with the letter "A" alone repeating more than 101 times,CairoText.submobjectshas only 101 elements.So I kept checking when the submobjects were actually created and in what order and traced it back to
SVGMobject.generate_points.And that is where I stopped investigating, because this _looks_ like a bug in
SVGMobject'sgenerate_pointsmethod, andSVGMobjectis scary.
Does this also explain why the following string fails? Because i wouldn't assume that the whitespace is so 'wide' and its just 30 occurances. It also doesn't result in a horizontally wide text but vertically one. I'd definetely double check the '\n' string below when trying to fix it. Might be an edge case.
# This string fails. If you remove one \n it is working.
s = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\na"
t = CairoText(s)
Most helpful comment
There appears to be a limit on the actual width of the string that shows up on screen.
| Character | Max Number in string | Max Width| Single Char Width |
| ----------- | ----------- | -----------|------------------|
| A | 101 | 33.66953125| 0.31992185
| B | 101 |33.6261719| 0.2765625|
|a| 121 | 33.6166015| 0.2474609|
|莿| 55| 33.9277344| 0.5732422|
Any string lengthier than about 34 MUnits (without any scaling) seems to cause the IndexError.
If the string does turn out to be lengthier than 34 MUnits,
CairoText.submobjectswill be locked down to the number of characters whose length is lesser than 34 MUnits.For example, if I try
CairoText(101*"A"), everything works fine.CairoText.submobjectshas exactly 101 elements.BUT, if I try
CairoText(102*"A"),CairoText.submobjectsstill only has 101 elements, and that causes thelist index out of rangeerror whenCairoText.gen_charstries to generate the 102nd "A", with the nonexistent 102nd element ofCairoText.submobjects.The same goes for
103*"A",231*"A"and so on. In all cases with the letter "A" alone repeating more than 101 times,CairoText.submobjectshas only 101 elements.So I kept checking when the submobjects were actually created and in what order and traced it back to
SVGMobject.generate_points.And that is where I stopped investigating, because this _looks_ like a bug in
SVGMobject'sgenerate_pointsmethod, andSVGMobjectis scary.