Skip to content

Commit fe2ba6d

Browse files
naveen521kkPhilippImhofbehackl
authored
Use Manimpango (#878)
* Use manimpango * Remove MarkUp Text not yet supported * add manimpango as dep * remove MarkupText from __all__ * Fix CairoText * Remove test for Pango * Run black * Update ManimPango * Try fixing MacOS CI by restricting version of grpc * Try fixing MacOS CI - 2 * Make MarkupText use manimpango (#26) * Update ManimPango * update manimpango * Remove pango installation docs * remove ffi workaround from Dockerfile * troubleshooting: new entry for manimpango, hint for update for old pango problems Co-authored-by: Philipp Imhof <52650214+PhilippImhof@users.noreply.github.com> Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>
1 parent 4190072 commit fe2ba6d

File tree

8 files changed

+158
-528
lines changed

8 files changed

+158
-528
lines changed

docker/Dockerfile

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ COPY . /opt/manim
2626
WORKDIR /opt/manim
2727
RUN pip install --no-cache .
2828

29-
# ensure that ffi bindings are generated
30-
RUN python -c "import pangocairocffi"
31-
3229
# create working directory for user to mount local directory into
3330
WORKDIR /manim
3431
RUN chmod 666 /manim

docs/source/installation/mac.rst

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,6 @@ To install cairo:
1515
1616
brew install cairo
1717
18-
To install Pango and it dependencies:
19-
20-
.. code-block:: bash
21-
22-
brew install pkg-config
23-
brew install libffi
24-
brew install pango
25-
brew install glib
26-
27-
2818
To install ffmpeg:
2919

3020
.. code-block:: bash

docs/source/installation/troubleshooting.rst

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,28 @@ Troubleshooting
33

44
List of known installation problems.
55

6-
(Windows) OSError: dlopen() failed to load a library: pango?
7-
------------------------------------------------------------
8-
9-
If your manual installation of Manim (or even the installation using
10-
Chocolatey) fails with the error
6+
``pip install manim`` fails when installing manimpango?
7+
-------------------------------------------------------
8+
Most likely this means that pip was not able to use our pre-built wheels
9+
of ``manimpango``. Let us know (via our `Discord <https://discord.gg/mMRrZQW>`_
10+
or by opening a
11+
`new issue on GitHub <https://github.com/ManimCommunity/ManimPango/issues/new>`_)
12+
which architecture you would like to see supported, and we'll see what we
13+
can do about it.
14+
15+
To fix errors when installing ``manimpango``, you need to make sure you
16+
have all the necessary build requirements. Check out the detailed
17+
instructions given in
18+
`the BUILDING section <https://github.com/ManimCommunity/ManimPango#BUILDING>`_
19+
of the corresponding `GitHub repository <https://github.com/ManimCommunity/ManimPango>`_.
1120

12-
.. code-block::
1321

14-
OSError: dlopen() failed to load a library: pango / pango-1 / pango-1.0 / pango-1.0-0
15-
16-
possibly combined with alerts warning about procedure entry points
17-
``"deflateSetHeader"`` and ``"inflateReset2"`` that could not be
18-
located, you might run into an issue with a patched version of ``zlib1.dll``
19-
shipped by Intel, `as described here <https://github.com/msys2/MINGW-packages/issues/813>`_.
22+
(Windows) OSError: dlopen() failed to load a library: pango?
23+
------------------------------------------------------------
2024

21-
To resolve this issue, you can copy ``zlib1.dll`` from the directory
22-
provided for the Pango binaries to the directory Manim is installed to.
25+
This should be fixed in Manim's latest version, update
26+
using ``pip install --upgrade manim``.
2327

24-
For a more global solution (try at your own risk!), try renaming the
25-
file ``zlib1.dll`` located at ``C:\Program Files\Intel\Wifi\bin`` to
26-
something like ``zlib1.dll.bak`` -- and then try installing Manim again
27-
(either using ``pip install manim`` or with Chocolatey). Ensure that
28-
you are able to revert this name change in case you run into troubles
29-
with your WiFi (we did not get any reports about such a problem, however).
3028

3129

3230
Some letters are missing from TextMobject/TexMobject output?

docs/source/installation/win.rst

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,6 @@ You can install manim very easily using chocolatey, by typing the following comm
1818
And then you can skip all the other steps and move to installing :ref:`latex-installation`.
1919
Please see :doc:`troubleshooting` section for details about OSError.
2020

21-
Pango Installation
22-
******************
23-
24-
These steps would get you `libpango-1.0-0.dll` to your ``PATH`` along
25-
with other dependencies. You may probably have them before itself if
26-
you have installed `GTK <https://www.gtk.org/>`_ or any ``GTK``
27-
based app like emacs. If you have it you can just add it to your
28-
path and skip these steps.
29-
30-
1. Go to `Release Page
31-
<https://github.com/ManimCommunity/manim-windows/releases/latest>`_
32-
and download the one according to your PC architechture.
33-
34-
.. important:: Please download the ``zip`` file for architechture of python installed.
35-
It is possible to have installed ``x86`` python installed on ``x64`` PC.
36-
37-
2. Extract the zip file using File Explorer or 7z to the loaction you want to install.
38-
39-
.. code-block:: bash
40-
41-
7z x pango-windows-binaires-x64.zip -oC:\Pango
42-
43-
3. Finally, add it `PATH variable
44-
<https://www.computerhope.com/issues/ch000549.htm>`_.
45-
46-
4721
FFmpeg installation
4822
*******************
4923

manim/mobject/svg/text_mobject.py

Lines changed: 33 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,15 @@ def construct(self):
5353
from xml.sax.saxutils import escape
5454

5555
import cairo
56-
import cairocffi
57-
import pangocairocffi
58-
import pangocffi
56+
import manimpango
57+
from manimpango import PangoUtils, TextSetting, MarkupUtils
5958

6059
from ... import config, logger
6160
from ...constants import *
6261
from ...mobject.geometry import Dot
6362
from ...mobject.svg.svg_mobject import SVGMobject
6463
from ...mobject.types.vectorized_mobject import VGroup
65-
from ...utils.color import WHITE
66-
from ...utils.color import Colors
67-
64+
from ...utils.color import WHITE, Colors
6865

6966
TEXT_MOB_SCALE_FACTOR = 0.05
7067

@@ -103,68 +100,6 @@ def remove_invisible_chars(mobject):
103100
return mobject_without_dots
104101

105102

106-
class PangoUtils:
107-
@staticmethod
108-
def str2style(string: str) -> pangocffi.Style:
109-
"""Internally used function. Converts text to Pango Understandable Styles."""
110-
if string == NORMAL:
111-
return pangocffi.Style.NORMAL
112-
elif string == ITALIC:
113-
return pangocffi.Style.ITALIC
114-
elif string == OBLIQUE:
115-
return pangocffi.Style.OBLIQUE
116-
else:
117-
raise AttributeError("There is no Style Called %s" % string)
118-
119-
@staticmethod
120-
def str2weight(string: str) -> pangocffi.Weight:
121-
"""Internally used function. Convert text to Pango Understandable Weight"""
122-
if string == NORMAL:
123-
return pangocffi.Weight.NORMAL
124-
elif string == BOLD:
125-
return pangocffi.Weight.BOLD
126-
elif string == THIN:
127-
return pangocffi.Weight.THIN
128-
elif string == ULTRALIGHT:
129-
return pangocffi.Weight.ULTRALIGHT
130-
elif string == LIGHT:
131-
return pangocffi.Weight.LIGHT
132-
elif string == SEMILIGHT:
133-
return pangocffi.Weight.SEMILIGHT
134-
elif string == BOOK:
135-
return pangocffi.Weight.BOOK
136-
elif string == MEDIUM:
137-
return pangocffi.Weight.MEDIUM
138-
elif string == SEMIBOLD:
139-
return pangocffi.Weight.SEMIBOLD
140-
elif string == ULTRABOLD:
141-
return pangocffi.Weight.ULTRABOLD
142-
elif string == HEAVY:
143-
return pangocffi.Weight.HEAVY
144-
elif string == ULTRAHEAVY:
145-
return pangocffi.Weight.ULTRAHEAVY
146-
else:
147-
raise AttributeError("There is no Font Weight Called %s" % string)
148-
149-
@staticmethod
150-
def remove_last_M(file_name: str) -> None:
151-
with open(file_name, "r") as fpr:
152-
content = fpr.read()
153-
content = re.sub(r'Z M [^A-Za-z]*? "\/>', 'Z "/>', content)
154-
with open(file_name, "w") as fpw:
155-
fpw.write(content)
156-
157-
158-
class TextSetting(object):
159-
def __init__(self, start, end, font, slant, weight, line_num=-1):
160-
self.start = start
161-
self.end = end
162-
self.font = font
163-
self.slant = slant
164-
self.weight = weight
165-
self.line_num = line_num
166-
167-
168103
class CairoText(SVGMobject):
169104
"""Display (non-LaTeX) text.
170105
@@ -448,7 +383,7 @@ def text2svg(self):
448383
offset_x = 0
449384
last_line_num = 0
450385
for setting in settings:
451-
font = setting.font
386+
font = setting.font.decode("utf-8")
452387
slant = self.str2slant(setting.slant)
453388
weight = self.str2weight(setting.weight)
454389
text = self.text[setting.start : setting.end].replace("\n", " ")
@@ -1012,45 +947,22 @@ def text2svg(self):
1012947
file_name = os.path.join(dir_name, hash_name) + ".svg"
1013948
if os.path.exists(file_name):
1014949
return file_name
1015-
surface = cairocffi.SVGSurface(file_name, 600, 400)
1016-
context = cairocffi.Context(surface)
1017-
context.move_to(START_X, START_Y)
1018950
settings = self.text2settings()
1019-
offset_x = 0
1020-
last_line_num = 0
1021-
layout = pangocairocffi.create_layout(context)
1022-
layout.set_width(pangocffi.units_from_double(600))
1023-
for setting in settings:
1024-
family = setting.font
1025-
style = PangoUtils.str2style(setting.slant)
1026-
weight = PangoUtils.str2weight(setting.weight)
1027-
text = self.text[setting.start : setting.end].replace("\n", " ")
1028-
fontdesc = pangocffi.FontDescription()
1029-
fontdesc.set_size(pangocffi.units_from_double(size))
1030-
if family:
1031-
fontdesc.set_family(family)
1032-
fontdesc.set_style(style)
1033-
fontdesc.set_weight(weight)
1034-
layout.set_font_description(fontdesc)
1035-
if setting.line_num != last_line_num:
1036-
offset_x = 0
1037-
last_line_num = setting.line_num
1038-
context.move_to(
1039-
START_X + offset_x, START_Y + line_spacing * setting.line_num
1040-
)
1041-
pangocairocffi.update_layout(context, layout)
1042-
if disable_liga:
1043-
text = escape(text)
1044-
layout.set_markup(
1045-
f"<span font_features='liga=0,dlig=0,clig=0,hlig=0'>{text}</span>"
1046-
)
1047-
else:
1048-
layout.set_text(text)
1049-
logger.debug(f"Setting Text {text}")
1050-
pangocairocffi.show_layout(context, layout)
1051-
offset_x += pangocffi.units_to_double(layout.get_size()[0])
1052-
surface.finish()
1053-
return file_name
951+
width = 600
952+
height = 400
953+
954+
return manimpango.text2svg(
955+
settings,
956+
size,
957+
line_spacing,
958+
disable_liga,
959+
file_name,
960+
START_X,
961+
START_Y,
962+
width,
963+
height,
964+
self.text,
965+
)
1054966

1055967

1056968
class MarkupText(SVGMobject):
@@ -1360,32 +1272,22 @@ def text2svg(self):
13601272
file_name = os.path.join(dir_name, hash_name) + ".svg"
13611273
if os.path.exists(file_name):
13621274
return file_name
1363-
surface = cairocffi.SVGSurface(file_name, 600, 400)
1364-
context = cairocffi.Context(surface)
1365-
context.move_to(START_X, START_Y)
1366-
layout = pangocairocffi.create_layout(context)
1367-
layout.set_width(pangocffi.units_from_double(600))
1368-
1369-
fontdesc = pangocffi.FontDescription()
1370-
fontdesc.set_size(pangocffi.units_from_double(size))
1371-
if self.font:
1372-
fontdesc.set_family(self.font)
1373-
fontdesc.set_style(PangoUtils.str2style(self.slant))
1374-
fontdesc.set_weight(PangoUtils.str2weight(self.weight))
1375-
layout.set_font_description(fontdesc)
13761275

1377-
context.move_to(START_X, START_Y)
1378-
pangocairocffi.update_layout(context, layout)
1379-
if disable_liga:
1380-
layout.set_markup(
1381-
f"<span font_features='liga=0,dlig=0,clig=0,hlig=0'>{self.text}</span>"
1382-
)
1383-
else:
1384-
layout.set_markup(self.text)
13851276
logger.debug(f"Setting Text {self.text}")
1386-
pangocairocffi.show_layout(context, layout)
1387-
surface.finish()
1388-
return file_name
1277+
return MarkupUtils.text2svg(
1278+
self.text,
1279+
self.font,
1280+
self.slant,
1281+
self.weight,
1282+
size,
1283+
line_spacing,
1284+
disable_liga,
1285+
file_name,
1286+
START_X,
1287+
START_Y,
1288+
600, # width
1289+
400, # height
1290+
)
13891291

13901292
def _count_real_chars(self, s):
13911293
"""Counts characters that will be displayed.

0 commit comments

Comments
 (0)