Skip to content

Commit 756a28e

Browse files
authored
Merge pull request #804 from naveen521kk/fix-liga
Allow disabling ligatures in Text
2 parents 8f191f9 + f28b9b5 commit 756a28e

File tree

2 files changed

+52
-24
lines changed

2 files changed

+52
-24
lines changed

manim/mobject/svg/code_mobject.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ def gen_line_numbers(self):
285285
line_spacing=self.line_spacing,
286286
alignment="right",
287287
font=self.font,
288+
disable_ligatures=True,
288289
stroke_width=self.stroke_width
289290
).scale(self.scale_factor)
290291
for i in line_numbers:
@@ -310,6 +311,7 @@ def gen_colored_lines(self):
310311
line_spacing=self.line_spacing,
311312
tab_width=self.tab_width,
312313
font=self.font,
314+
disable_ligatures=True,
313315
stroke_width=self.stroke_width
314316
).scale(self.scale_factor)
315317
for line_no in range(code.__len__()):

manim/mobject/svg/text_mobject.py

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ def construct(self):
4949
import hashlib
5050
import os
5151
import re
52+
from typing import Dict
53+
from xml.sax.saxutils import escape
5254

5355
import cairo
5456
import cairocffi
@@ -433,11 +435,6 @@ class Paragraph(VGroup):
433435
`weird <https://github.com/3b1b/manim/issues/1067>`_. Consider using
434436
:meth:`remove_invisible_chars` to resolve this issue.
435437
436-
.. note::
437-
438-
Due to issues with the Pango-powered :class:`.Text`, this class uses
439-
:class:`.CairoText`.
440-
441438
Parameters
442439
----------
443440
line_spacing : :class:`int`, optional
@@ -467,7 +464,7 @@ def __init__(self, *text, line_spacing=-1, alignment=None, **config):
467464
VGroup.__init__(self, **config)
468465

469466
lines_str = "\n".join(list(text))
470-
self.lines_text = CairoText(lines_str, **config)
467+
self.lines_text = Text(lines_str, **config)
471468
lines_str_list = lines_str.split("\n")
472469
self.chars = self.gen_chars(lines_str_list)
473470

@@ -724,28 +721,30 @@ def construct(self):
724721
def __init__(
725722
self,
726723
text: str,
727-
fill_opacity=1,
728-
stroke_width=0,
729-
color=WHITE,
730-
size=1,
731-
line_spacing=-1,
732-
font="",
724+
fill_opacity: int = 1,
725+
stroke_width: int = 0,
726+
color: str = WHITE,
727+
size: int = 1,
728+
line_spacing: int = -1,
729+
font: str = "",
733730
slant=NORMAL,
734731
weight=NORMAL,
735-
t2c=None,
736-
t2f=None,
737-
t2g=None,
738-
t2s=None,
739-
t2w=None,
740-
gradient=None,
741-
tab_width=4,
732+
t2c: Dict[str, str] = None,
733+
t2f: Dict[str, str] = None,
734+
t2g: Dict[str, tuple] = None,
735+
t2s: Dict[str, str] = None,
736+
t2w: Dict[str, str] = None,
737+
gradient: tuple = None,
738+
tab_width: int = 4,
742739
# Mobject
743-
height=None,
744-
width=None,
745-
should_center=True,
746-
unpack_groups=True,
740+
height: int = None,
741+
width: int = None,
742+
should_center: bool = True,
743+
unpack_groups: bool = True,
744+
disable_ligatures: bool = False,
747745
**kwargs,
748746
):
747+
749748
logger.info(
750749
"Text now uses Pango for rendering. "
751750
"In case of problems, the old implementation is available as CairoText."
@@ -780,6 +779,7 @@ def __init__(
780779
self.t2w = t2w
781780

782781
self.original_text = text
782+
self.disable_ligatures = disable_ligatures
783783
text_without_tabs = text
784784
if text.find("\t") != -1:
785785
text_without_tabs = text.replace("\t", " " * self.tab_width)
@@ -803,6 +803,9 @@ def __init__(
803803
**kwargs,
804804
)
805805
self.text = text
806+
if self.disable_ligatures:
807+
self.submobjects = [*self.gen_chars()]
808+
self.chars = VGroup(*self.submobjects)
806809
self.chars = VGroup(*self.submobjects)
807810
self.text = text_without_tabs.replace(" ", "").replace("\n", "")
808811
nppc = self.n_points_per_cubic_curve
@@ -835,6 +838,24 @@ def __init__(
835838
def __repr__(self):
836839
return f"Text({repr(self.original_text)})"
837840

841+
def gen_chars(self):
842+
chars = VGroup()
843+
submobjects_char_index = 0
844+
for char_index in range(self.text.__len__()):
845+
if self.text[char_index] in (" ", "\t", "\n"):
846+
space = Dot(redius=0, fill_opacity=0, stroke_opacity=0)
847+
if char_index == 0:
848+
space.move_to(self.submobjects[submobjects_char_index].get_center())
849+
else:
850+
space.move_to(
851+
self.submobjects[submobjects_char_index - 1].get_center()
852+
)
853+
chars.add(space)
854+
else:
855+
chars.add(self.submobjects[submobjects_char_index])
856+
submobjects_char_index += 1
857+
return chars
858+
838859
def remove_last_M(self, file_name: str): # pylint: disable=invalid-name
839860
"""Internally used. Use to format the rendered SVG files."""
840861
with open(file_name, "r") as fpr:
@@ -999,6 +1020,7 @@ def text2svg(self):
9991020
size = self.size * 10
10001021
line_spacing = self.line_spacing * 10
10011022
dir_name = config.get_dir("text_dir")
1023+
disable_liga = self.disable_ligatures
10021024
if not os.path.exists(dir_name):
10031025
os.makedirs(dir_name)
10041026
hash_name = self.text2hash()
@@ -1032,7 +1054,11 @@ def text2svg(self):
10321054
START_X + offset_x, START_Y + line_spacing * setting.line_num
10331055
)
10341056
pangocairocffi.update_layout(context, layout)
1035-
layout.set_text(text)
1057+
if disable_liga:
1058+
text = escape(text)
1059+
layout.set_markup(f"<span font_features='liga=0'>{text}</span>")
1060+
else:
1061+
layout.set_text(text)
10361062
logger.debug(f"Setting Text {text}")
10371063
pangocairocffi.show_layout(context, layout)
10381064
offset_x += pangocffi.units_to_double(layout.get_size()[0])

0 commit comments

Comments
 (0)