
    lj'                       d Z ddlmZ ddlZg dZddlZddlZddlZddlm	Z	m
Z
mZ ddlmZ ddlmZ ddlmZ dd	lmZmZ ddlZddlZdd
lmZmZmZ ddlmZmZ ddlT ddlm Z  ddl!m"Z" ddl#m$Z$m%Z% ddl&m'Z' ddl(m)Z)m*Z*m+Z+ erddlm,Z, ddl&m'Z' dZ-dZ.dZ/g dZd$dZ0 G d de$          Z1 G d de"          Z2 G d de"          Z3ed%d#            Z4dS )&u  Mobjects used for displaying (non-LaTeX) text.

.. note::
   Just as you can use :class:`~.Tex` and :class:`~.MathTex` (from the module :mod:`~.tex_mobject`)
   to insert LaTeX to your videos, you can use :class:`~.Text` to to add normal text.

.. important::

   See the corresponding tutorial :ref:`using-text-objects`, especially for information about fonts.


The simplest way to add text to your animations is to use the :class:`~.Text` class. It uses the Pango library to render text.
With Pango, you are also able to render non-English alphabets like `你好` or  `こんにちは` or `안녕하세요` or `مرحبا بالعالم`.

Examples
--------

.. manim:: HelloWorld
    :save_last_frame:

    class HelloWorld(Scene):
        def construct(self):
            text = Text('Hello world').scale(3)
            self.add(text)

.. manim:: TextAlignment
    :save_last_frame:

    class TextAlignment(Scene):
        def construct(self):
            title = Text("K-means clustering and Logistic Regression", color=WHITE)
            title.scale(0.75)
            self.add(title.to_edge(UP))

            t1 = Text("1. Measuring").set_color(WHITE)

            t2 = Text("2. Clustering").set_color(WHITE)

            t3 = Text("3. Regression").set_color(WHITE)

            t4 = Text("4. Prediction").set_color(WHITE)

            x = VGroup(t1, t2, t3, t4).arrange(direction=DOWN, aligned_edge=LEFT).scale(0.7).next_to(ORIGIN,DR)
            x.set_opacity(0.5)
            x.submobjects[1].set_opacity(1)
            self.add(x)

    )annotationsN)Text	Paragraph
MarkupTextregister_font)IterableIteratorSequence)contextmanager)chain)Path)TYPE_CHECKINGAny)MarkupUtils
PangoUtilsTextSetting)configlogger)*)Dot)
SVGMobject)VGroupVMobject)Point3D)
ManimColorParsableManimColorcolor_gradient)Selfg?g333333?g333333@mobjectr   returnc                    t                      }t          | d         t                     r2| D ].}|                    t          d |D                                  /n |j        d | D               |S )a8  Function to remove unwanted invisible characters from some mobjects.

    Parameters
    ----------
    mobject
        Any SVGMobject from which we want to remove unwanted invisible characters.

    Returns
    -------
    :class:`~.SVGMobject`
        The SVGMobject without unwanted invisible characters.
    r   c              3  D   K   | ]}t          |t                    |V  d S N
isinstancer   .0ks     Z/home/agentuser/manim-venv/lib/python3.11/site-packages/manim/mobject/text/text_mobject.py	<genexpr>z)remove_invisible_chars.<locals>.<genexpr>k   s1      CCQ
1c0B0BCqCCCCCC    c              3  D   K   | ]}t          |t                    |V  d S r#   r$   r&   s     r)   r*   z)remove_invisible_chars.<locals>.<genexpr>n   s1      "P"PZ3=O=O"P1"P"P"P"P"P"Pr+   )r   r%   add)r   mobject_without_dotssubmobs      r)   remove_invisible_charsr0   Z   s     "88'!*f%% R 	 	F $$CC&CCCCC   	
 	! "P"Pg"P"P"PQQr+   c                  \     e Zd ZdZdddd fdZddZddZddZddZd dZ	d!dZ
 xZS )"r   a  Display a paragraph of text.

    For a given :class:`.Paragraph` ``par``, the attribute ``par.chars`` is a
    :class:`.VGroup` containing all the lines. In this context, every line is
    constructed as a :class:`.VGroup` of characters contained in the line.


    Parameters
    ----------
    line_spacing
        Represents the spacing between lines. Defaults to -1, which means auto.
    alignment
        Defines the alignment of paragraph. Defaults to None. Possible values are "left", "right" or "center".

    Examples
    --------
    Normal usage::

        paragraph = Paragraph(
            "this is a awesome",
            "paragraph",
            "With \nNewlines",
            "\tWith Tabs",
            "  With Spaces",
            "With Alignments",
            "center",
            "left",
            "right",
        )

    Remove unwanted invisible characters::

        self.play(Transform(remove_invisible_chars(paragraph.chars[0:2]),
                            remove_invisible_chars(paragraph.chars[3][0:3]))

    N)line_spacing	alignmenttextstrr3   floatr4   
str | Nonekwargsr   c                  || _         || _        |                    dd          | _        t	                                                       d                    t          |                    }t          |fd|i|| _	        |
                    d          }|                     |          | _        t          | j                  | j        gt          | j                  z  g| _        d | j        d         D             | _         | j        | j        d           |                     t%          j        g d                     | j        r|                     | j                   d S d S )Ndisable_ligaturesF
r3   c                6    g | ]}|                                 S  )
get_center)r'   lines     r)   
<listcomp>z&Paragraph.__init__.<locals>.<listcomp>   s"    'T'T'Td(9(9'T'T'Tr+   r   )r   r   r   )r3   r4   getconsider_spaces_as_charssuper__init__joinlistr   
lines_textsplit
_gen_charscharslenlineslines_initial_positionsr-   move_tonparray_set_all_lines_alignments)selfr3   r4   r5   r9   	lines_strlines_str_list	__class__s          r)   rE   zParagraph.__init__   sB    )"(.

3F(N(N%IId4jj))	yNN|NvNN"..__^44
4:&&(83tz??(JK
'T'TdjQRm'T'T'T$$*Q-  RXiii(()))> 	;**4>:::::	; 	;r+   rU   rG   r    r   c                   d} |                                              }t          t          |                    D ]}||         }| j        rt          |          }n d}|D ]}|                                s|dz  }|                     |                                                          ||         j        | j        j        |||z              ||z  }| j        r|dz  }|S )a$  Function to convert a list of plain strings to a VGroup of VGroups of chars.

        Parameters
        ----------
        lines_str_list
            List of plain text strings.

        Returns
        -------
        :class:`~.VGroup`
            The generated 2d-VGroup of chars.
        r      )get_group_classrangerL   rC   isspacer-   rH   rK   )rS   rU   char_index_counterrK   line_noline_str
char_countchars           r)   rJ   zParagraph._gen_chars   s    &$$&&((S0011 	( 	(G%g.H , ( ]]


$ ( (D<<>> ("a
II,d**,,..///E'N&&);j)HH 
 *,, ( #a'"r+   c                    t          t          | j        d                             D ]}|                     ||           | S )zFunction to set all line's alignment to a specific value.

        Parameters
        ----------
        alignment
            Defines the alignment of paragraph. Possible values are "left", "right", "center".
        r   )rZ   rL   rM   _change_alignment_for_a_linerS   r4   r]   s      r)   rR   z#Paragraph._set_all_lines_alignments   sI     SA//00 	B 	BG--iAAAAr+   r]   intc                2    |                      ||           | S )a8  Function to set one line's alignment to a specific value.

        Parameters
        ----------
        alignment
            Defines the alignment of paragraph. Possible values are "left", "right", "center".
        line_no
            Defines the line number for which we want to set given alignment.
        )rb   rc   s      r)   _set_line_alignmentzParagraph._set_line_alignment   s     	)))W===r+   c                   dgt          | j        d                   z  | j        d<   t          t          | j        d                             D ]=}| |                             |                                 | j        |         z              >| S )z)Set all lines to their initial positions.Nr   rX   )rL   rM   rZ   rO   r?   rN   rS   r]   s     r)   #_set_all_lines_to_initial_positionsz-Paragraph._set_all_lines_to_initial_positions   s    TZ]!3!33
1SA//00 	 	GM!!!!D$@$II    r+   c                    d| j         d         |<   | |                             |                                 | j        |         z              | S )zFunction to set one line to initial positions.

        Parameters
        ----------
        line_no
            Defines the line number for which we want to set given alignment.
        NrX   )rM   rO   r?   rN   rh   s     r)   _set_line_to_initial_positionz'Paragraph._set_line_to_initial_position   sH     "&
1gWdoo//$2Nw2WWXXXr+   Nonec                d   || j         d         |<   | j         d         |         dk    rh| |                             t          j        |                                 d         | |                                         d         dg                     dS | j         d         |         dk    ry| |                             t          j        |                                 d         | |         j        dz  z
  | |                                         d         dg                     dS | j         d         |         dk    ry| |                             t          j        |                                 d         | |         j        dz  z   | |                                         d         dg                     dS dS )a;  Function to change one line's alignment to a specific value.

        Parameters
        ----------
        alignment
            Defines the alignment of paragraph. Possible values are "left", "right", "center".
        line_no
            Defines the line number for which we want to set given alignment.
        rX   centerr   right   leftN)rM   rO   rP   rQ   r?   	get_rightwidthget_leftrc   s      r)   rb   z&Paragraph._change_alignment_for_a_line  s    "+
1g:a=!X--M!!$//++A.W0H0H0J0J10MqQRR     Z]7#w..M!!((+d7m.AA.EEW002215      Z]7#v--M!!*T']-@1-DDW002215      .-r+   )r5   r6   r3   r7   r4   r8   r9   r   )rU   rG   r    r   )r4   r6   r    r   )r4   r6   r]   rd   r    r   )r    r   )r]   rd   r    r   )r4   r6   r]   rd   r    rl   )__name__
__module____qualname____doc__rE   rJ   rR   rf   ri   rk   rb   __classcell__rV   s   @r)   r   r   r   s        # #P ! $	; ; ; ; ; ; ; ;0& & & &P
 
 
 
      
 
 
 
" " " " " " " "r+   r   c                      e Zd ZdZeej        dLd                        Zdddedd	e	e	ddddddd
ddddddfdM fd.Z
dNd/ZedOd0            Zej        dPd3            ZdQd5ZdRd8ZdSd:ZdTd@ZdUdDZdVdFZdWdGZdSdHZdXdY fdKZ xZS )Zr   u  Display (non-LaTeX) text rendered using `Pango <https://pango.org/>`_.

    Text objects behave like a :class:`.VGroup`-like iterable of all characters
    in the given text. In particular, slicing is possible.

    Parameters
    ----------
    text
        The text that needs to be created as a mobject.
    font
        The font family to be used to render the text. This is either a system font or
        one loaded with `register_font()`. Note that font family names may be different
        across operating systems.
    warn_missing_font
        If True (default), Manim will issue a warning if the font does not exist in the
        (case-sensitive) list of fonts returned from `manimpango.list_fonts()`.

    Returns
    -------
    :class:`Text`
        The mobject-like :class:`.VGroup`.

    Examples
    ---------

    .. manim:: Example1Text
        :save_last_frame:

        class Example1Text(Scene):
            def construct(self):
                text = Text('Hello world').scale(3)
                self.add(text)

    .. manim:: TextColorExample
        :save_last_frame:

        class TextColorExample(Scene):
            def construct(self):
                text1 = Text('Hello world', color=BLUE).scale(3)
                text2 = Text('Hello world', gradient=(BLUE, GREEN)).scale(3).next_to(text1, DOWN)
                self.add(text1, text2)

    .. manim:: TextItalicAndBoldExample
        :save_last_frame:

        class TextItalicAndBoldExample(Scene):
            def construct(self):
                text1 = Text("Hello world", slant=ITALIC)
                text2 = Text("Hello world", t2s={'world':ITALIC})
                text3 = Text("Hello world", weight=BOLD)
                text4 = Text("Hello world", t2w={'world':BOLD})
                text5 = Text("Hello world", t2c={'o':YELLOW}, disable_ligatures=True)
                text6 = Text(
                    "Visit us at docs.manim.community",
                    t2c={"docs.manim.community": YELLOW},
                    disable_ligatures=True,
               )
                text6.scale(1.3).shift(DOWN)
                self.add(text1, text2, text3, text4, text5 , text6)
                Group(*self.mobjects).arrange(DOWN, buff=.8).set(height=config.frame_height-LARGE_BUFF)

    .. manim:: TextMoreCustomization
            :save_last_frame:

            class TextMoreCustomization(Scene):
                def construct(self):
                    text1 = Text(
                        'Google',
                        t2c={'[:1]': '#3174f0', '[1:2]': '#e53125',
                             '[2:3]': '#fbb003', '[3:4]': '#3174f0',
                             '[4:5]': '#269a43', '[5:]': '#e53125'}, font_size=58).scale(3)
                    self.add(text1)

    As :class:`Text` uses Pango to render text, rendering non-English
    characters is easily possible:

    .. manim:: MultipleFonts
        :save_last_frame:

        class MultipleFonts(Scene):
            def construct(self):
                morning = Text("வணக்கம்", font="sans-serif")
                japanese = Text(
                    "日本へようこそ", t2c={"日本": BLUE}
                )  # works same as ``Text``.
                mess = Text("Multi-Language", weight=BOLD)
                russ = Text("Здравствуйте मस नम म ", font="sans-serif")
                hin = Text("नमस्ते", font="sans-serif")
                arb = Text(
                    "صباح الخير \n تشرفت بمقابلتك", font="sans-serif"
                )  # don't mix RTL and LTR languages nothing shows up then ;-)
                chinese = Text("臂猿「黛比」帶著孩子", font="sans-serif")
                self.add(morning, japanese, mess, russ, hin, arb, chinese)
                for i,mobj in enumerate(self.mobjects):
                    mobj.shift(DOWN*(i-3))


    .. manim:: PangoRender
        :quality: low

        class PangoRender(Scene):
            def construct(self):
                morning = Text("வணக்கம்", font="sans-serif")
                self.play(Write(morning))
                self.wait(2)

    Tests
    -----

    Check that the creation of :class:`~.Text` works::

        >>> Text('The horse does not eat cucumber salad.')
        Text('The horse does not eat cucumber salad.')

    r    	list[str]c                 ,    t          j                    } | S r#   
manimpango
list_fontsvalues    r)   	font_listzText.font_list       &022r+   g      ?r   Nr2       TFr5   r6   fill_opacityr7   stroke_widthcolorParsableManimColor | None	font_sizer3   fontslantweightt2cdict[str, str] | Nonet2ft2g.dict[str, Iterable[ParsableManimColor]] | Nonet2st2wgradient#Iterable[ParsableManimColor] | None	tab_widthrd   warn_missing_fontboolheightfloat | Noners   should_centerr;   use_svg_cacher9   r   c           
     j	  # || _         |r|rt                                          }|                                dk    rd}||vr|                                |v r|                                }nq|                                |v r|                                }nF|                                |v r|                                }nt          j        d| d| d           || _        t          |          | _
        || _        |	| _        || _        || _        |
i }
|i }|i }|i }|i }|                    d|
          }
|                    d|          }|                    d|          }|                    d	|          }|                    d
|          }|
J |J |J |J |J d |
                                D             | _        || _        || _        || _        || _        || _        || _        |}|                    d          dk    r|                    dd| j        z            }|| _        | j         dk    r| j
        | j
        t6          z  z   | _         n| j
        | j
        | j         z  z   | _         |rt9          |          nt;                      j        }|                     |                                           }tC          j"        |            tG                      j$        |f||||||d| || _        | j        rg | %                                | _&         | '                                | j&         | _(        |                    dd                              dd          | _        | j)        }| D ]}tU          |j+                  dk    r|j+        }|d         }tU          |          | j,        k    s
J |            g #|dk    rd#fd} nd#fd} t[          |          D ]n\  }!}"#.                    |"           |!tU          |          dz
  k    r>|!dz   |z  dk    r2t_          |"||!dz            k              r | |           ||!dz            }o | |           ta          j1        #d          |_+        ||| 2                    tf                     | j4        | _5        d S )N
sans-serifsansFont  not in .
text2color	text2fonttext2gradient
text2slanttext2weightc                X    i | ]'\  }}|t          |                                          (S r>   )r   to_hex)r'   r(   vs      r)   
<dictcomp>z!Text.__init__.<locals>.<dictcomp>  s0    #V#V#V$!QAz!}}';';'='=#V#V#Vr+   	r2    )r   r   r   rs   r   r   r   r<   r      endr   r    rl   c                4    d         }||| z   dz  | gz  d S Nr2   rp   r>   r   startclosed_curve_pointss     r)   add_line_toz"Text.__init__.<locals>.add_line_to'  5    /3E'), '''r+   c                N    d         }|||z   | z   dz  || z   | z   dz  | gz  d S Nr2   r   r>   r   s     r)   r   z"Text.__init__.<locals>.add_line_to2  K    /3E',1s*a/	, '''r+   rX   rp   ndminr   r   r    rl   )6r3   r   r   lower
capitalizetitler   warningr   r7   
_font_sizer   r   r   r   popitemsr   r   r   r   r   original_textr;   findreplacer5   DEFAULT_LINE_SPACING_SCALEr   r   r   	_text2svgr   r   remove_last_MrD   rE   rJ   submobjectsrY   rK   n_points_per_curverL   pointsdim	enumerateappendanyrP   rQ   scaleTEXT_MOB_SCALE_FACTORr   initial_height)%rS   r5   r   r   r   r   r3   r   r   r   r   r   r   r   r   r   r   r   r   rs   r   r;   r   r9   
fonts_listtext_without_tabsparsed_color	file_namenppceachr   curve_startr   indexpointr   rV   s%                                      @r)   rE   zText.__init__  sC   6 ) 	H% 	H))Jzz|||++:%%??$$
22??,,DDZZ\\Z//::<<DDZZ\\Z//::<<DDN#F4#F#F#F#F#FGGG		** 
 ";C;C;C;C;Cjjs++jjc**jj#..jjs++jj,,#V#V#))++#V#V#V#&<?#&#&!!2 99T??b   $T33G H H%	""$/4N"NN  !%$/DDU2U UD8=#S:e#4#4#48::CSNN<#6#6#8#899	 +++		
%%''		
 		
 		
 		
 		
 	! 	43!2!23D+T))++T-=>
%--c266>>tRHH	& 7	A 7	AD4;1$$[F )K{##tx////// 24 qyy            !*& 1 1 4 4u#**5111S[[1_,,d*a//EVEAI%6677 0  K,,,"("3KK$$$(#6a@@@DKK>emJJ,---"kr+   c                2    dt          | j                   dS )NzText()reprr   rS   s    r)   __repr__zText.__repr__Q  s    2tD.//2222r+   c                V    | j         | j        z  t          z  dz  | j        z  t          z  S Ng333333@r   r   r   r   DEFAULT_FONT_SIZEr   s    r)   r   zText.font_sizeT  A     K!"#$  o	
   	
r+   font_valrl   c                j    |dk    rt          d          |                     || j        z             d S Nr   z!font_size must be greater than 0.
ValueErrorr   r   rS   r   s     r)   r   zText.font_size_  ;     q==@AAAJJx$.011111r+   r   c                >    |                                              }d}t          t          | j                            D ]}| j        |                                         rt          ddd          }|dk    r3|                    | j        |                                                    n5|                    | j        |dz
                                                      |	                    |           |	                    | j        |                    |dz  }|S )Nr   )radiusr   stroke_opacityrX   )
rY   rZ   rL   r5   r[   r   rO   r   r?   r-   )rS   rK   submobjects_char_index
char_indexspaces        r)   rJ   zText._gen_charsg  s   &$$&&((!"DI// 	, 	,Jy$,,.. ,11QGGG??MM$"23I"J"U"U"W"WXXXXMM()?!)CDOOQQ   		%    		$*+ABCCC&!+&&r+   wordlist[tuple[int, int]]c                   t          j        d|          }|r|                    d          dk    r"t          |                    d                    nd}|                    d          dk    r"t          |                    d                    nt	          |          }|dk     rt	          |          |z   n|}|dk     rt	          |          |z   n|}||fgS g }|                    |          }|dk    rS|                    ||t	          |          z   f           |                    ||t	          |          z             }|dk    S|S )z*Finds the indexes of ``text`` in ``word``.z\[([0-9\-]{0,}):([0-9\-]{0,})\]rX   r   r   rp   r2   )rematchgrouprd   rL   r   r   )rS   r   r5   tempr   r   indexesr   s           r)   _find_indexeszText._find_indexesy  s<   x:DAA 	*.**Q--2*=*=C

1&&&1E(,

1(;(;#djjmm$$$TC).CII%%E%(1WW#d))c//#C  		$rkkNNE53t99#45666IIdECII$566E rkk r+   r   c                v   d| j         z   | j        z   | j        z   t          |          z   }|t          | j                  t          | j                  z   t          | j                  z   t          | j                  z   z  }|t          | j                  t          | j	                  z   z  }|t          | j
                  z  }|t          | j                  z  }| j        |z   }t          j                    }|                    |                                           |                                dd         S )(Generates ``sha256`` hash for file name.PANGON   )r   r   r   r6   r   r   r   r   r3   r   r;   r   r5   hashlibsha256updateencode	hexdigestrS   r   settingsid_strhashers        r)   
_text2hashzText._text2hash  s    di$*,t{:SZZG 	 	CMMCMM1CMMACMMQQC)**S-A-AAAC.///C&&&X%!!fmmoo&&&!!#2#&&r+   left_settingr   right_settingdefault_argsdict[str, Iterable[str]]c                   |j         |j         k     }|rt          j        |          nt          j        |          }|r|j         n|j         |_        |j        |_         |s|j        |_         |D ]}t          ||          }t          ||          }||         }	||	k    rKt          ||          |	k    r7t	          d| j        |j        |j                   dd| d| d| dz             t          ||||	k    r|n|           |S )NzAmbiguous style for text 'z':'z' cannot be both 'z' and 'z'.)r   copyr   getattrr   r5   setattr)
rS   r  r  r  	containednew_settingargrq   ro   defaults
             r)   _merge_settingszText._merge_settings  sC    "%(88	1:Xdi---	-@X@X1:PM--@P(. 	2 + 1M 		L 		LC<--DM3//E"3'Gw7=##>#>'#I#I g=;NQ^Qb;b1cgggG#GGGGeGGGH   M3UKKKKr+   t2xs$Sequence[tuple[dict[str, str], str]]list[TextSetting]c           	         g }t          t          d |D                        }|D ]Sfd|D             }|                     | j                  D ]&\  }}|                    t          ||fi |           'T|S )Nc              3  H   K   | ]\  }}g |                                 V  d S r#   )keys)r'   t2x_s      r)   r*   z/Text._get_settings_from_t2xs.<locals>.<genexpr>  s2      @@a}}@@@@@@r+   c                Z    i | ]'\  }}||v rt          |                   n|         (S r>   )r6   )r'   r"  r  r  r   s      r)   r   z0Text._get_settings_from_t2xs.<locals>.<dictcomp>  sL        C ts{{ST^^^S8I  r+   )setr   r   r5   r   r   )	rS   r  r  r
  t2xwordssetting_argsr   r   r   s	     `     @r)   _get_settings_from_t2xszText._get_settings_from_t2xs  s    
 u@@4@@@ABB 		I 		ID     !%	  L #00tyAA I I
sE3 G G, G GHHHHIr+   dict[str, Any]c           
        g }t          j         |          }| j        rt          | j        t          | j                            }t          t          | j                            D ]C}||                                         |d<   |                    t          ||dz   fi |           D| j	        
                                D ]\  }}t          |t          |                    }|                     || j                  D ]\\  }}	t          ||	          D ]F}|||z
                                           |d<   |                    t          ||dz   fi |           G]|S )Nr   rX   )r  r   r   rL   r5   rZ   r   r   r   r   r   r   )
rS   r  r
  argscolorsir   r   r   r   s
             r)   _get_settings_from_gradientz Text._get_settings_from_gradient  sr    y&&= 	?'5dmS^^'T'TF3ty>>** ? ? &q	 0 0 2 2WAq1u = = = =>>>>"hnn.. 	C 	CND(#Hc$ii88F"00tyAA C C
suc** C CA$*1u9$5$<$<$>$>DMOOK1q5$A$AD$A$ABBBBCC r+   c                     j         df j        df j        df j        dfg} fd|D             }                     ||          }|                                         |                     |                    d            t          |          D ]\  }}|dz   t          |          k    r n||dz            }|j
        |j        k    r                     |||          }|dz   }	|	t          |          k     rD||	         j        |j        k     r.|	dz  }	|	t          |          k     r||	         j        |j        k     .|                    |	|           |                                }
d	}|D ]:}|j        |k    r&|
                    t!          ||j        fi |           |j
        };|t           j                  k    r3|
                    t!          |t           j                  fi |           t%          |
d
           }d	}t'          j        d j                  r                     d j                  D ]\  }}|D ]{}|j        dk    r||_        ||j
        k     r\|dz  }t          j        |          }||_
        ||_        ||_        |                    |           |                    d             n||D ]}|j        dk    r||_        |S )z7Converts the texts and styles to a setting for parsing.r   r   r   r   c                H    i | ]\  }}||d k    rt          |          nS )r   )r  )r'   r#  r  r   rS   s      r)   r   z'Text._text2settings.<locals>.<dictcomp>  sC     (
 (
 (
EKQCsg~~s###5(
 (
 (
r+   c                    | j         S r#   r   settings    r)   <lambda>z%Text._text2settings.<locals>.<lambda>  s    '- r+   )keyrX   r   c                    | j         S r#   r2  r3  s    r)   r5  z%Text._text2settings.<locals>.<lambda>  s    W] r+   z\nr<   r2   c                    | j         S r#   r2  r3  s    r)   r5  z%Text._text2settings.<locals>.<lambda>  s    '- r+   )r   r   r   r   r(  extendr.  sortr   rL   r   r   r  insertr  r   r   r5   sortedr   searchr   line_num)rS   r   r  r  r
  r   r4  next_settingr  	new_indextemp_settingsr   r>  	for_startfor_ends   ``             r)   _text2settingszText._text2settings  sR    XvXwXx Xw	2
(
 (
 (
 (
 (
OS(
 (
 (
 //lCC88FFGGG 	77888'11 	8 	8NE7qyCMM))#EAI.L{\///"227L,WW!AI	H-- +1K4EEENI H-- +1K4EEE 	;777 ! 	  	 G}%%$$[%V%V%V%VWWWKEEC	NN""  UC	NN!S!Sl!S!STTT--J-JKKK9UDI&& 	&*&8&8ty&I&I  "	7'  G'2--+3( 7;.. A&*i&8&8&-,3)/7, 444 *G*GHHH /   	, 	,G2%%#+ r+   c                D   | j         }| j        }|t          z  }|t          z  }t          j        d          }|                    dd           |                     |          }||dz   z  }|                                r"t          |	                                          }n| 
                    |          }t          d         }	t          d         }
t          j        |||| j        t          |	                                          t          t          |	|
| j        
  
        }|S )$Convert the text to SVG using Pango.text_dirTparentsexist_ok.svgpixel_widthpixel_height)r   r3   TEXT2SVG_ADJUSTMENT_FACTORr   get_dirmkdirr  existsr6   resolverD  r   text2svgr;   START_XSTART_Yr5   )rS   r   sizer3   dir_name	hash_namer   svg_filer
  rs   r   s              r)   r   zText._text2svg  s   (**22>*--td333OOE**		F 23	 	9,,..//HH**511H=)EN+F!*&I%%''((	 H r+   propagate_colorsr   c                    t           j        t          j        k    r!t	                                                       n<t           j        t          j        k    r"t	                                          |           | S )N)rZ  )r   rendererRendererTypeOPENGLrD   init_colorsCAIRO)rS   rZ  rV   s     r)   r_  zText.init_colors>  s]    ?l111GG!!!!_ 222GG1ABBBr+   r    r|   ).r5   r6   r   r7   r   r7   r   r   r   r7   r3   r7   r   r6   r   r6   r   r6   r   r   r   r   r   r   r   r   r   r   r   r   r   rd   r   r   r   r   rs   r   r   r   r;   r   r   r   r9   r   r    r6   r    r7   r   r7   r    rl   )r    r   )r   r6   r5   r6   r    r   r   r   r    r6   )r  r   r  r   r  r  r    r   )r  r  r  r  r    r  )r  r)  r    r  )r   r   r    r  )T)rZ  r   r    r   )ru   rv   rw   rx   staticmethod	functoolscacher   r   NORMALrE   r   propertyr   setterrJ   r   r  r  r(  r.  rD  r   r_  ry   rz   s   @r)   r   r   +  s       r rh _   _ \ "+/, %)%)>B%)%)8<"&#"""'#1i* i* i* i* i* i* i*V3 3 3 3 
 
 
 X
 2 2 2 2   $   $' ' ' '   4   &   &A A A AF       D          r+   r   c                       e Zd ZdZeej        d7d                        Zdddedd	e	e	d
dddddd
dfd8 fd'Z
ed9d(            Zej        d:d+            Zd;d-Zd<d.Zd=d0Zd>d2Zd?d4Zd>d5Zd@d6Z xZS )Ar   u2  Display (non-LaTeX) text rendered using `Pango <https://pango.org/>`_.

    Text objects behave like a :class:`.VGroup`-like iterable of all characters
    in the given text. In particular, slicing is possible.

    **What is PangoMarkup?**

    PangoMarkup is a small markup language like html and it helps you avoid using
    "range of characters" while coloring or styling a piece a Text. You can use
    this language with :class:`~.MarkupText`.

    A simple example of a marked-up string might be::

        <span foreground="blue" size="x-large">Blue text</span> is <i>cool</i>!"

    and it can be used with :class:`~.MarkupText` as

    .. manim:: MarkupExample
        :save_last_frame:

        class MarkupExample(Scene):
            def construct(self):
                text = MarkupText('<span foreground="blue" size="x-large">Blue text</span> is <i>cool</i>!"')
                self.add(text)

    A more elaborate example would be:

    .. manim:: MarkupElaborateExample
        :save_last_frame:

        class MarkupElaborateExample(Scene):
            def construct(self):
                text = MarkupText(
                    '<span foreground="purple">ا</span><span foreground="red">َ</span>'
                    'ل<span foreground="blue">ْ</span>ع<span foreground="red">َ</span>ر'
                    '<span foreground="red">َ</span>ب<span foreground="red">ِ</span>ي'
                    '<span foreground="green">ّ</span><span foreground="red">َ</span>ة'
                    '<span foreground="blue">ُ</span>'
                )
                self.add(text)

    PangoMarkup can also contain XML features such as numeric character
    entities such as ``&#169;`` for © can be used too.

    The most general markup tag is ``<span>``, then there are some
    convenience tags.

    Here is a list of supported tags:

    - ``<b>bold</b>``, ``<i>italic</i>`` and ``<b><i>bold+italic</i></b>``
    - ``<u>underline</u>`` and ``<s>strike through</s>``
    - ``<tt>typewriter font</tt>``
    - ``<big>bigger font</big>`` and ``<small>smaller font</small>``
    - ``<sup>superscript</sup>`` and ``<sub>subscript</sub>``
    - ``<span underline="double" underline_color="green">double underline</span>``
    - ``<span underline="error">error underline</span>``
    - ``<span overline="single" overline_color="green">overline</span>``
    - ``<span strikethrough="true" strikethrough_color="red">strikethrough</span>``
    - ``<span font_family="sans">temporary change of font</span>``
    - ``<span foreground="red">temporary change of color</span>``
    - ``<span fgcolor="red">temporary change of color</span>``
    - ``<gradient from="YELLOW" to="RED">temporary gradient</gradient>``

    For ``<span>`` markup, colors can be specified either as
    hex triples like ``#aabbcc`` or as named CSS colors like
    ``AliceBlue``.
    The ``<gradient>`` tag is handled by Manim rather than
    Pango, and supports hex triplets or Manim constants like
    ``RED`` or ``RED_A``.
    If you want to use Manim constants like ``RED_A`` together
    with ``<span>``, you will need to use Python's f-String
    syntax as follows::

        MarkupText(f'<span foreground="{RED_A}">here you go</span>')

    If your text contains ligatures, the :class:`MarkupText` class may
    incorrectly determine the first and last letter when creating the
    gradient. This is due to the fact that ``fl`` are two separate characters,
    but might be set as one single glyph - a ligature. If your language
    does not depend on ligatures, consider setting ``disable_ligatures``
    to ``True``. If you must use ligatures, the ``gradient`` tag supports an optional
    attribute ``offset`` which can be used to compensate for that error.

    For example:

    - ``<gradient from="RED" to="YELLOW" offset="1">example</gradient>`` to *start* the gradient one letter earlier
    - ``<gradient from="RED" to="YELLOW" offset=",1">example</gradient>`` to *end* the gradient one letter earlier
    - ``<gradient from="RED" to="YELLOW" offset="2,1">example</gradient>`` to *start* the gradient two letters earlier and *end* it one letter earlier

    Specifying a second offset may be necessary if the text to be colored does
    itself contain ligatures. The same can happen when using HTML entities for
    special chars.

    When using ``underline``, ``overline`` or ``strikethrough`` together with
    ``<gradient>`` tags, you will also need to use the offset, because
    underlines are additional paths in the final :class:`SVGMobject`.
    Check out the following example.

    Escaping of special characters: ``>`` **should** be written as ``&gt;``
    whereas ``<`` and ``&`` *must* be written as ``&lt;`` and
    ``&amp;``.

    You can find more information about Pango markup formatting at the
    corresponding documentation page:
    `Pango Markup <https://docs.gtk.org/Pango/pango_markup.html>`_.
    Please be aware that not all features are supported by this class and that
    the ``<gradient>`` tag mentioned above is not supported by Pango.

    Parameters
    ----------

    text
        The text that needs to be created as mobject.
    fill_opacity
        The fill opacity, with 1 meaning opaque and 0 meaning transparent.
    stroke_width
        Stroke width.
    font_size
        Font size.
    line_spacing
        Line spacing.
    font
        Global font setting for the entire text. Local overrides are possible.
    slant
        Global slant setting, e.g. `NORMAL` or `ITALIC`. Local overrides are possible.
    weight
        Global weight setting, e.g. `NORMAL` or `BOLD`. Local overrides are possible.
    gradient
        Global gradient setting. Local overrides are possible.
    warn_missing_font
        If True (default), Manim will issue a warning if the font does not exist in the
        (case-sensitive) list of fonts returned from `manimpango.list_fonts()`.

    Returns
    -------
    :class:`MarkupText`
        The text displayed in form of a :class:`.VGroup`-like mobject.

    Examples
    ---------

    .. manim:: BasicMarkupExample
        :save_last_frame:

        class BasicMarkupExample(Scene):
            def construct(self):
                text1 = MarkupText("<b>foo</b> <i>bar</i> <b><i>foobar</i></b>")
                text2 = MarkupText("<s>foo</s> <u>bar</u> <big>big</big> <small>small</small>")
                text3 = MarkupText("H<sub>2</sub>O and H<sub>3</sub>O<sup>+</sup>")
                text4 = MarkupText("type <tt>help</tt> for help")
                text5 = MarkupText(
                    '<span underline="double">foo</span> <span underline="error">bar</span>'
                )
                group = VGroup(text1, text2, text3, text4, text5).arrange(DOWN)
                self.add(group)

    .. manim:: ColorExample
        :save_last_frame:

        class ColorExample(Scene):
            def construct(self):
                text1 = MarkupText(
                    f'all in red <span fgcolor="{YELLOW}">except this</span>', color=RED
                )
                text2 = MarkupText("nice gradient", gradient=(BLUE, GREEN))
                text3 = MarkupText(
                    'nice <gradient from="RED" to="YELLOW">intermediate</gradient> gradient',
                    gradient=(BLUE, GREEN),
                )
                text4 = MarkupText(
                    'fl ligature <gradient from="RED" to="YELLOW">causing trouble</gradient> here'
                )
                text5 = MarkupText(
                    'fl ligature <gradient from="RED" to="YELLOW" offset="1">defeated</gradient> with offset'
                )
                text6 = MarkupText(
                    'fl ligature <gradient from="RED" to="YELLOW" offset="1">floating</gradient> inside'
                )
                text7 = MarkupText(
                    'fl ligature <gradient from="RED" to="YELLOW" offset="1,1">floating</gradient> inside'
                )
                group = VGroup(text1, text2, text3, text4, text5, text6, text7).arrange(DOWN)
                self.add(group)

    .. manim:: UnderlineExample
        :save_last_frame:

        class UnderlineExample(Scene):
            def construct(self):
                text1 = MarkupText(
                    '<span underline="double" underline_color="green">bla</span>'
                )
                text2 = MarkupText(
                    '<span underline="single" underline_color="green">xxx</span><gradient from="#ffff00" to="RED">aabb</gradient>y'
                )
                text3 = MarkupText(
                    '<span underline="single" underline_color="green">xxx</span><gradient from="#ffff00" to="RED" offset="-1">aabb</gradient>y'
                )
                text4 = MarkupText(
                    '<span underline="double" underline_color="green">xxx</span><gradient from="#ffff00" to="RED">aabb</gradient>y'
                )
                text5 = MarkupText(
                    '<span underline="double" underline_color="green">xxx</span><gradient from="#ffff00" to="RED" offset="-2">aabb</gradient>y'
                )
                group = VGroup(text1, text2, text3, text4, text5).arrange(DOWN)
                self.add(group)

    .. manim:: FontExample
        :save_last_frame:

        class FontExample(Scene):
            def construct(self):
                text1 = MarkupText(
                    'all in sans <span font_family="serif">except this</span>', font="sans"
                )
                text2 = MarkupText(
                    '<span font_family="serif">mixing</span> <span font_family="sans">fonts</span> <span font_family="monospace">is ugly</span>'
                )
                text3 = MarkupText("special char > or &gt;")
                text4 = MarkupText("special char &lt; and &amp;")
                group = VGroup(text1, text2, text3, text4).arrange(DOWN)
                self.add(group)

    .. manim:: NewlineExample
        :save_last_frame:

        class NewlineExample(Scene):
            def construct(self):
                text = MarkupText('foooo<span foreground="red">oo\nbaa</span>aar')
                self.add(text)

    .. manim:: NoLigaturesExample
        :save_last_frame:

        class NoLigaturesExample(Scene):
            def construct(self):
                text1 = MarkupText('fl<gradient from="RED" to="GREEN">oat</gradient>ing')
                text2 = MarkupText('fl<gradient from="RED" to="GREEN">oat</gradient>ing', disable_ligatures=True)
                group = VGroup(text1, text2).arrange(DOWN)
                self.add(group)


    As :class:`MarkupText` uses Pango to render text, rendering non-English
    characters is easily possible:

    .. manim:: MultiLanguage
        :save_last_frame:

        class MultiLanguage(Scene):
            def construct(self):
                morning = MarkupText("வணக்கம்", font="sans-serif")
                japanese = MarkupText(
                    '<span fgcolor="blue">日本</span>へようこそ'
                )  # works as in ``Text``.
                mess = MarkupText("Multi-Language", weight=BOLD)
                russ = MarkupText("Здравствуйте मस नम म ", font="sans-serif")
                hin = MarkupText("नमस्ते", font="sans-serif")
                chinese = MarkupText("臂猿「黛比」帶著孩子", font="sans-serif")
                group = VGroup(morning, japanese, mess, russ, hin, chinese).arrange(DOWN)
                self.add(group)

    You can justify the text by passing :attr:`justify` parameter.

    .. manim:: JustifyText

        class JustifyText(Scene):
            def construct(self):
                ipsum_text = (
                    "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
                    "Praesent feugiat metus sit amet iaculis pulvinar. Nulla posuere "
                    "quam a ex aliquam, eleifend consectetur tellus viverra. Aliquam "
                    "fermentum interdum justo, nec rutrum elit pretium ac. Nam quis "
                    "leo pulvinar, dignissim est at, venenatis nisi."
                )
                justified_text = MarkupText(ipsum_text, justify=True).scale(0.4)
                not_justified_text = MarkupText(ipsum_text, justify=False).scale(0.4)
                just_title = Title("Justified")
                njust_title = Title("Not Justified")
                self.add(njust_title, not_justified_text)
                self.play(
                    FadeOut(not_justified_text),
                    FadeIn(justified_text),
                    FadeOut(njust_title),
                    FadeIn(just_title),
                )
                self.wait(1)

    Tests
    -----

    Check that the creation of :class:`~.MarkupText` works::

        >>> MarkupText('The horse does not eat cucumber salad.')
        MarkupText('The horse does not eat cucumber salad.')

    r    r|   c                 ,    t          j                    } | S r#   r~   r   s    r)   r   zMarkupText.font_listp  r   r+   rX   r   Nr2   r   Fr   Tr5   r6   r   r7   r   r   r   r   r3   r   r   r   justifyr   r   r   r   rd   r   
int | Noners   r   r;   r   r9   r   c           	     
  # || _         || _        |r|rt                                          }|                                dk    rd}||vr|                                |v r|                                }nq|                                |v r|                                }nF|                                |v r|                                }nt          j        d| d| d           || _	        t          |          | _        || _        |	| _        || _        || _        |
| _        || _        || _        |}d|v r|                    dd| j        z            }|                                 }t+          |          dk    rt          j        d	           |                                 }t/          j        | j                   }|rt3          |          | j        d
k    r| j        | j        t4          z  z   | _        n| j        | j        | j        z  z   | _        |rt7          |          nt9                      j        }|                     |          }t?          j         |            tC                      j"        |f|||||d|  | #                                | j$         | _%        |                    dd                              dd          | _         | j&        }| D ]}t+          |j'                  dk    r|j'        }|d         }t+          |          | j(        k    s
J |            g #|dk    rd#fd}nd#fd}tS          |          D ]n\  }} #*                    |            |t+          |          dz
  k    r>|dz   |z  dk    r2tW          | ||dz            k              r ||           ||dz            }o ||           tY          j-        #d          |_'        | j        r | j.        | j          |D ]d}!| j%        |!d         |!d         z
  |!d         |!d         z
  |!d         z
           /                    | 0                    |!d                              e|D ]t}" | j%        |"d         |"d         z
  |"d         |"d         z
  |"d         z
           j.        | 0                    |"d                   | 0                    |"d                   f  u||| 1                    td                     | j3        | _4        d S )Nr   r   r   r   r   r   r   r   z[Using <color> tags in MarkupText is deprecated. Please use <span foreground="..."> instead.r2   )r   r   r   rs   r   r   r<   r   r   r   r    rl   c                4    d         }||| z   dz  | gz  d S r   r>   r   s     r)   r   z(MarkupText.__init__.<locals>.add_line_to  r   r+   c                N    d         }|||z   | z   dz  || z   | z   dz  | gz  d S r   r>   r   s     r)   r   z(MarkupText.__init__.<locals>.add_line_to  r   r+   rX   rp   r   r   start_offset
end_offsetr   fromtor   )5r5   r3   r   r   r   r   r   r   r   r   r7   r   r   r   r   r   rn  r   r;   r   _extract_color_tagsrL   _extract_gradient_tagsr   validater   r   r   r   r   r   r   r   rD   rE   rY   r   rK   r   r   r   r   r   r   rP   rQ   set_color_by_gradient	set_color_parse_colorr   r   r   r   )%rS   r5   r   r   r   r   r3   r   r   r   rn  r   r   r   rs   r   r;   r   r9   r   r   colormapgradientmapvalidate_errorr   r   r   r   r   r   r   r   r   colgradr   rV   s%                                      @r)   rE   zMarkupText.__init__v  s   * 	#/ 	H% 	H))Jzz|||++:%%??$$
22??,,DDZZ\\Z//::<<DDZZ\\Z//::<<DDN#F4#F#F#F#F#FGGG		**
 "!!2 4<< $T33G H H++--x==1Nm   1133$-di88 	-^,,,""$/4N"NN  !%$/DDU2U UD8=#S:e#4#4#48::CSNN<00	 +++	
%%'	
 	
 	
 	
 	
 ,T))++T-=>
%--c266>>tRHH	& 5	A 5	AD4;1$$[F )K{##tx////// 24 qyy            !*& 1 1 
4 
4u#**5111S[[1_,,d*a//EVEAI%6677 0
  K,,,"("3KK$$$(#6a@@@DKK= 	7&D&66 	9 	9CJGs>22SZn%6&l#6$ $ i))#g,778888 	 	D$DJW^ 44tE{~&8'|$8% % $##DL1143D3DT$Z3P3PQ   >emJJ,---"kr+   c                V    | j         | j        z  t          z  dz  | j        z  t          z  S r   r   r   s    r)   r   zMarkupText.font_size  r   r+   r   rl   c                j    |dk    rt          d          |                     || j        z             d S r   r   r   s     r)   r   zMarkupText.font_size%  r   r+   r   c                   d| j         z   | j        z   | j        z   t          |                                                                          z   }|t          | j                  t          | j                  z   z  }|t          | j	                  z  }|t          | j
                  z  }| j        |z   }t          j                    }|                    |                                           |                                dd         S )r  MARKUPPANGONr  )r   r   r   r   r   r   r6   r3   r   r;   rn  r5   r  r  r  r  r  r	  s        r)   r  zMarkupText._text2hash-  s     ij k &&((..00	1 	 	C)**S-A-AAAC.///C%%%X%!!fmmoo&&&!!#2#&&r+   c                   t          |          }| j        }| j        }|t          z  }|t          z  }t	          j        d          }|                    dd           |                     |          }||dz   z  }|                                r"t          |
                                          }n| d|                                 d| j         dn| j        }t          j        d	| j                    t          j        || j        | j        | j        ||| j        t          |
                                          t*          t,          d
d| j        d          }|S )rF  rG  TrH  rK  Nz<span foreground="z">z</span>zSetting Text iX  i  i  )rn  pango_width)r   r   r3   rN  r   rO  rP  r  rQ  r6   rR  r   r5   r   debugr   rS  r   r   r   r;   rT  rU  rn  )	rS   r   rV  r3   rW  rX  r   rY  
final_texts	            r)   r   zMarkupText._text2svg>  sd   5!!"/**22>*--td333OOE**		F 23	 		 1 1 3 344HH $ JU\\^^IItyIIIIY 
 L444555"+	
&I%%''((  H  r+   sc                    d}d}t          j        dd|          }|D ]6}|dk    r|dz  }|dk    r|dk    r|dz  }|dk    r|dk    r|dk    r|dz  }7|S )	zCounts characters that will be displayed.

        This is needed for partial coloring or gradients, because space
        counts to the text's `len`, but has no corresponding character.
        r   z&[^;]+;x<rX   >r   r   )r   sub)rS   r  countlevelcs        r)   _count_real_charszMarkupText._count_real_charsf  s     F9c1%% 	 	ACxx
CxxEAII
ca4iiEQJJ
r+   list[dict[str, Any]]c           
     "   t          j        d| j        t           j                  }g }|D ]6}|                     | j        d|                    d                             }||                     |                    d                    z   }|                    d          r(|                    d                              d          ndg}|d         rt          |d                   nd}t          |          dk    r|d         rt          |d                   nd}|
                    |||                    d          |                    d          ||d	           8t          j        d
d| j        dt           j                  | _        |S )zUsed to determine which parts (if any) of the string should be formatted
        with a gradient.

        Removes the ``<gradient>`` tag, as it is not part of Pango's markup and would cause an error.
        zP<gradient\s+from="([^"]+)"\s+to="([^"]+)"(\s+offset="([^"]+)")?>(.+?)</gradient>Nr      r   ,rp   rX   )r   r   ru  rv  rs  rt  z<gradient[^>]+>(.+?)</gradient>\1r  flagsr   finditerr   Sr  r   r   rI   rd   rL   r   r  r5   )	rS   tagsr~  tagr   r   offsetsrs  rt  s	            r)   rx  z!MarkupText._extract_gradient_tagsy  s    {_D
 

 -/ 	 	C**4+=n		!n+MNNE$001>>>C141Fciill((---A3G.5aj?3wqz???aL,/LLA,=,='!*,=WQZRSJ"IIaLL))A,,$0", 	 	 	 	 F-udiqPRPT
 
 
	 r+   r  c                r    t          j        d|          r|S t          |                                          S )z8Parse color given in ``<color>`` or ``<gradient>`` tags.z#[0-9a-f]{6})r   r   r   r   )rS   r  s     r)   r|  zMarkupText._parse_color  s3    8NC(( 	,Jc??))+++r+   c           	        t          j        d| j        t           j                  }g }|D ]"}|                     | j        d|                    d                             }||                     |                    d                    z   }|                    d          r(|                    d                              d          ndg}|d         rt          |d                   nd}t          |          dk    r|d         rt          |d                   nd}|
                    |||                    d          ||d	           $t          j        d
d| j        dt           j                  | _        |S )aX  Used to determine which parts (if any) of the string should be formatted
        with a custom color.

        Removes the ``<color>`` tag, as it is not part of Pango's markup and would cause an error.

        Note: Using the ``<color>`` tags is deprecated. As soon as the legacy syntax is gone, this function
        will be removed.
        z:<color\s+col="([^"]+)"(\s+offset="([^"]+)")?>(.+?)</color>Nr   r   r   r  rp   rX   )r   r   r   rs  rt  z<color[^>]+>(.+?)</color>r  r  r  )	rS   r  r}  r  r   r   r  rs  rt  s	            r)   rw  zMarkupText._extract_color_tags  sn    {ID
 
 *, 	 	C**4+=n		!n+MNNE$001>>>C141Fciill((---A3G.5aj?3wqz???aL,/LLA,=,='!*,=WQZRSJOO" YYq\\$0",     F'	"$
 
 
	 r+   c                2    dt          | j                   dS )NzMarkupText(r   r   r   s    r)   r   zMarkupText.__repr__  s    8T$"4558888r+   ra  )$r5   r6   r   r7   r   r7   r   r   r   r7   r3   r7   r   r6   r   r6   r   r6   rn  r   r   r   r   rd   r   ro  rs   ro  r   r   r;   r   r   r   r9   r   rc  rd  re  )r   r   r    r6   )r  r6   r    rd   )r    r  )r  r6   r    r6   rb  )ru   rv   rw   rx   rf  rg  rh  r   r   ri  rE   rj  r   rk  r  r   r  rx  r|  rw  r   ry   rz   s   @r)   r   r   F  s       g gR	 _   _ \  +/, 8<! ""'"&%b* b* b* b* b* b* b*H 
 
 
 X
 2 2 2 2' ' ' '"& & & &P   &       D, , , ,# # # #J9 9 9 9 9 9 9 9r+   r   	font_file
str | PathIterator[None]c              #  j  K   t          t          j                  j                                        }t          |           |dz  | z  |dz  | z  || z  g}|D ]U}|                                }|                                r+|}t          j        d|                                            nVd|  d| }t          |          	 t          j        t          |                    sJ dV  t          j        t          |                     dS # t          j        t          |                     w xY w)a  Temporarily add a font file to Pango's search path.

    This searches for the font_file at various places. The order it searches it described below.

    1. Absolute path.
    2. In ``assets/fonts`` folder.
    3. In ``font/`` folder.
    4. In the same directory.

    Parameters
    ----------
    font_file
        The font file to add.

    Examples
    --------
    Use ``with register_font(...)`` to add a font file to search
    path.

    .. code-block:: python

        with register_font("path/to/font_file.ttf"):
            a = Text("Hello", font="Custom Font Name")

    Raises
    ------
    FileNotFoundError:
        If the font doesn't exists.

    AttributeError:
        If this method is used on macOS.

    .. important ::

        This method is available for macOS for ``ManimPango>=v0.2.3``. Using this
        method with previous releases will raise an :class:`AttributeError` on macOS.
    zassets/fontsfontszFound file at %szCan't find z. Checked paths: N)r   r   
input_fileparentrR  rQ  r   r  absoluteFileNotFoundErrorr   r   r6   unregister_font)r  input_folderpossible_pathspath	file_patherrors         r)   r   r     sA     N )**199;;LY~%	1w*y 	N  ' '||~~;;== 	IL+Y-?-?-A-ABBBE	
 KiJJ.JJ&&&3'I77777"3y>>22222
"3y>>2222s   'D #D2)r   r   r    r   )r  r  r    r  )5rx   
__future__r   rg  __all__r  r  r   collections.abcr   r	   r
   
contextlibr   	itertoolsr   pathlibr   typingr   r   r   numpyrP   r   r   r   manimr   r   manim.constantsmanim.mobject.geometry.arcr   manim.mobject.svg.svg_mobjectr   &manim.mobject.types.vectorized_mobjectr   r   manim.typingr   manim.utils.colorr   r   r   r   r   r   rN  r0   r   r   r   r   r>   r+   r)   <module>r     s  / /b # " " " " "    
>
>
>   				 8 8 8 8 8 8 8 8 8 8 % % % % % %             % % % % % % % %         ; ; ; ; ; ; ; ; ; ;                     * * * * * * 4 4 4 4 4 4 C C C C C C C C             L L L L L L L L L L %$$$$$$     
>
>
>       0v v v v v v v vrX X X X X: X X XvB
9 B
9 B
9 B
9 B
9 B
9 B
9 B
9J ;3 ;3 ;3 ;3 ;3 ;3r+   