@@ -49,6 +49,8 @@ def construct(self):
4949import hashlib
5050import os
5151import re
52+ from typing import Dict
53+ from xml .sax .saxutils import escape
5254
5355import cairo
5456import 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