
    h                       S r SSKJr  SSKJrJrJrJrJrJ	r	J
r
Jr  SSKrSSKrSSKrSSKJrJr  SSKJrJrJrJrJrJr  SSKJrJrJrJrJrJrJ r   SSK!J"r"J#r#J$r$  SS	K%J&r&J'r'J(r(  \(       a  SS
K)J*r*J+r+J,r,  SSK-J.r.  SSK/J0r0  Sr1 " S S5      r2SGS jr3SHS jr4SIS jr5SJS jr6Sr7SKSLS jjr8SJS jr9SMSNS jjr:  SO     SPS jjr;SJS jr<SQSRS jjr=SSS jr>        STS jr?SUS jr@\R                  S\R4                  S\R8                  S \R6                  S!\R                  S"\R                  S#0rDS$rES%rFSVS& jrG " S' S(\
5      rH " S) S*5      rI " S+ S,\J5      rK " S- S.5      rL " S/ S05      rM " S1 S2\R                  5      rO " S3 S45      rP\R                  " S55      rR\R                  " S65      rS\R4                  \R8                  \R6                  \R                  \R                  S7.rT " S8 S95      rUSWS: jrVSXS; jrWSYSZS< jjrXSYS[S= jjrYS\S]S> jjrZS^S? jr[S@q\S_SA jr]S`SB jr^  Sa         SbSC jjr_\ 4ScSD jjr`\a" SE5      rbSdSF jrcg)ezL
Tools in this module should be as independent of DXF entities as possible!
    )annotations)IterableIteratorTYPE_CHECKINGUnionOptionalCallable
NamedTupleAnyN)	validatorconst)TextEntityAlignment
TextHAlignMTextParagraphAlignmentMTextLineAlignmentMTextStrokeMAP_MTEXT_ALIGN_TO_FLAGS)LEFTCENTERRIGHTBASELINEMIDDLETOPMAX_STR_LEN)Vec3Vec2UVec)rgb2intRGBint2rgb)TextMText	DXFEntity)Tagsfonts   c                  "   \ rS rSrSrSS jrSS jr\SS j5       r\SS j5       r	SS jr
    S           SS
 jjr     S             SS jjr        SS jr\\" SSS5      SSS	S4             SS jj5       rSrg)TextLine4   a  Helper class which represents a single line text entity
(e.g. :class:`~ezdxf.entities.Text`).

Args:
    text: content string
    font: ezdxf font definition like :class:`~ezdxf.fonts.fonts.MonospaceFont`
        or :class:`~ezdxf.fonts.fonts.TrueTypeFont`

c                X    X l         UR                  U5      U l        SU l        SU l        g )N      ?)_font
text_width_text_width
_stretch_x
_stretch_y)selftextfonts      B/var/www/html/env/lib/python3.13/site-packages/ezdxf/tools/text.py__init__TextLine.__init__?   s&    
"&//$"7!$!$    c                   [        U[        5      (       d   eSnSnU[        R                  [        R                  4;   aB  X2-
  R                  nU R
                  S:  a$  X`R
                  -  nU[        R                  :X  a  UnX@l        XPl        g)zSet stretch factors for FIT and ALIGNED alignments to fit the
text between `p1` and `p2`, only the distance between these points is
important. Other given `alignment` values are ignore.

r,   g&.>N)
isinstancer   FITALIGNED	magnituder/   r0   r1   )r2   	alignmentp1p2sxsydefined_lengths          r5   stretchTextLine.stretchE   s     )%89999,002E2M2MNN%'W$7$7N$&#&6&66 3 ; ;;Br8   c                4    U R                   U R                  -  $ )z)Returns the final (stretched) text width.)r/   r0   r2   s    r5   widthTextLine.widthW   s     $//11r8   c                \    U R                   R                  R                  U R                  -  $ )z*Returns the final (stretched) text height.)r-   measurementstotal_heightr1   rG   s    r5   heightTextLine.height\   s#     zz&&33dooEEr8   c                `    U R                   R                  R                  U R                  5      $ )z%Returns the scaled font measurements.)r-   rK   scaler1   rG   s    r5   font_measurementsTextLine.font_measurementsa   s!    zz&&,,T__==r8   r      rT   c                    U R                  5       n[        SUR                  5      [        U R                  UR                  5      /nU R	                  X#U5      n[
        R                  XqXU5      $ )aB  Returns the left and the right baseline vertex of the text line.

Args:
    insert: insertion location
    halign: horizontal alignment left=0, center=1, right=2
    valign: vertical alignment baseline=0, bottom=1, middle=2, top=3
    angle: text rotation in radians
    scale: scale in x- and y-axis as 2-tuple of float

r   )rQ   r   baselinerH   _shift_vectorr)   transform_2d)	r2   inserthalignvalignanglerP   fmverticesshifts	            r5   baseline_verticesTextLine.baseline_verticese   sd    $ ##%BKK R[[)
 ""626 $$XuUKKr8   c                H   U R                  5       n[        SUR                  5      [        U R                  UR                  5      [        U R                  UR                  5      [        SUR                  5      /nU R                  X#U5      n	[        R                  XXXV5      $ )a  Returns the corner vertices of the text line in the order
bottom left, bottom right, top right, top left.

Args:
    insert: insertion location
    halign: horizontal alignment left=0, center=1, right=2
    valign: vertical alignment baseline=0, bottom=1, middle=2, top=3
    angle: text rotation in radians
    scale: scale in x- and y-axis as 2-tuple of float
    oblique: shear angle (slanting) in x-direction in radians

r   )rQ   r   bottomrH   cap_toprW   r)   rX   )
r2   rY   rZ   r[   r\   rP   obliquer]   r^   r_   s
             r5   corner_verticesTextLine.corner_vertices   s    * ##%BIIRYY'RZZ(BJJ	
 ""626$$XuUTTr8   c                D    [        U R                  U5      [        X25      4$ N)_shift_xrH   _shift_y)r2   rZ   r[   r]   s       r5   rW   TextLine._shift_vector   s     

F+Xb-AAAr8   )r   r   c                r  ^^^	^
^ [         R                  " U 5      nU(       a"  [        R                  " U5      mU4S jU 5       n[        U5      m
T
(       a  U
4S jU 5       nUu  mm	TS:w  d  T	S:w  a  UU	4S jU 5       nT(       a  U4S jU 5       n[	        U5      nU Vs/ s H  oqU-   PM	     sn$ s  snf )ay  Transform any vertices from the text line located at the base
location at (0, 0) and alignment LEFT.

Args:
    vertices: iterable of vertices
    insert: insertion location
    shift: (shift-x, shift-y) as 2-tuple of float
    rotation: text rotation in radians
    scale: (scale-x, scale-y)  as 2-tuple of float
    oblique: shear angle (slanting) in x-direction in radians

c              3     >#    U  H5  n[        UR                  UR                  T-  -   UR                  5      v   M7     g 7fri   r   xy).0vslant_xs     r5   	<genexpr>(TextLine.transform_2d.<locals>.<genexpr>   s0     KAaccACC'M113377s   =A c              3  ,   >#    U  H	  oT-   v   M     g 7fri    )rr   rs   shift_vectors     r5   ru   rv      s     =9a\)9s   rT   c              3  p   >#    U  H+  n[        UR                  T-  UR                  T-  5      v   M-     g 7fri   ro   )rr   rs   scale_xscale_ys     r5   ru   rv      s+     OYaccGmQSS7];;Ys   36c              3  D   >#    U  H  oR                  T5      v   M     g 7fri   )rotate)rr   rs   rotations     r5   ru   rv      s     ?Y(++Ys    )r   generatemathtanr   )r^   rY   r_   r   rP   re   	vertices_rs   r{   r|   ry   rt   s      `    @@@@r5   rX   TextLine.transform_2d   s    D %)MM($;	 hhw'GKKI E{=9=I !a<7a<OYOI ?Y?I f$-.Iq
I...s   #B4)r-   r0   r1   r/   N)r3   strr4   fonts.AbstractFont)r>   r   r?   r   r@   r   returnNoner   float)r   fonts.FontMeasurements)r   r   r   rS   )rY   r   rZ   intr[   r   r\   r   rP   tuple[float, float]r   
list[Vec3])r   r   r   rS   r   )rY   r   rZ   r   r[   r   r\   r   rP   r   re   r   r   r   )rZ   r   r[   r   r]   r   r   r   )r^   zIterable[UVec]rY   r   r_   r   r   r   rP   r   re   r   r   r   )__name__
__module____qualname____firstlineno____doc__r6   rD   propertyrH   rM   rQ   r`   rf   rW   staticmethodr   rX   __static_attributes__rx   r8   r5   r)   r)   4   s   %$ 2 2 F F> %+LL L 	L
 L #L 
L> %+UU U 	U
 U #U U 
U>BB#&B,BB	B
  Aq!}%+%+8/ 8/8/ #8/ 	8/
 #8/ 8/ 
8/ 8/r8   r)   c                >    U[         :X  a  U * S-  $ U[        :X  a  U * $ g)Ng       @        )r   r   )total_widthrZ   s     r5   rj   rj      s)    |c!!|r8   c                   U[         :X  a  U R                  $ U[        :X  a  U R                  * U R                  S-  -   $ U[
        :X  a  U R                  * U R                  S-  -   $ U[        :X  a  U R                  * $ U R                  * $ )N   )	r   rV   r   rd   
cap_heightX_MIDDLErL   r   rc   )r]   r[   s     r5   rk   rk      sw    {{

{R]]Q...

{R__q000}

{II:r8   c                   U R                  5       nUS;   a  U R                  R                  nU R                  R                  nU[        R
                  [        R                  4;   a  [        n[        nX#4$ U[        R                  :X  a  [        n[        nX#4$ US:X  a5  [        R                  " U R                  R                  [        [        45      $ [!        SU 35      e)zReturn unified horizontal and vertical alignment.

horizontal alignment: left=0, center=1, right=2

vertical alignment: baseline=0, bottom=1, middle=2, top=3

Returns:
    tuple(halign, valign)

)TEXTATTRIBATTDEFMTEXTzinvalid DXF )dxftypedxfrZ   r[   r   r<   r;   r   r   r   r   r   getattachment_pointr   r   	TypeError)entityr   rZ   r[   s       r5   unified_alignmentr      s     nnG..""""j((*..99 FF ~ z(((FF~''++FJJ,G,G$PSUU
l7),
--r8   c                   Sn[        [        R                  " [        U 5      5      5      nUR                  (       a  UR                  5       nUS:X  a  UR                  S5      S:X  au  UR                  S5      R                  5       n[        R                  R                  U5      nU(       a  UR                  S5        X-  nM  US;   a  UR                  S5        M  UR                  S5        X-  nUR                  (       a  M  U$ )zReturns the plain text for :class:`~ezdxf.entities.Text`,
:class:`~ezdxf.entities.Attrib` and :class:`~ezdxf.entities.Attdef` content.
 %rT   r      kou)TextScannerr   fix_one_line_textcaret_decodehas_datapeeklowerr   SPECIAL_CHAR_ENCODINGr   consume)r3   resultscannercharcodeletters         r5   
plain_textr     s     F)55l46HIJG


||~3;||A#%||A,,.4488>OOA&$F5= OOA&# 


$ Mr8   	PNLlOoKkXc                j   / n[        [        [        U 5      5      5      nU(       Ga  UR                  5       nUS:X  a   UR                  5       nUS;   a  UR                  U5        GOUU[        ;   a2  US:X  a  UR                  S5        GO2US:X  a  UR                  S5        GOUS:H  nUnUR                  5       n US:w  a6  UR                  5       nU(       a  US:w  a  UR                  U5        US:w  a  M6  UnOUS	;   a  OUS
:X  a  U(       a  US   S
:X  a  UR                  5         U(       aj  UR                  5       n[        R                  R                  UR                  5       5      n	U	(       a  UR                  U	5        O8UR                  S
S
U45        O#UR                  U5        OUR                  U5        U(       a  GM  SR                  U5      n
U(       a  U
R                  S5      $ U
$ ! [         a     M8  f = f! [         a%    UR                  S5        UR                  U5         Ntf = f)ay  Returns the plain MTEXT content as a single string or  a list of
strings if `split` is ``True``. Replaces ``\P`` by ``\n`` and removes
other controls chars and inline codes.

This function is more than 4x faster than :func:`plain_mtext`, but does not
remove single letter inline commands with arguments without a terminating
semicolon like this ``"\C1red text"``.

.. note::

    Well behaved CAD applications and libraries always create inline codes
    for commands with arguments with a terminating semicolon like this
    ``"\C1;red text"``!

Args:
    text: MTEXT content string
    split: split content at line endings ``\P``

\\{}P
N S;z{}r   r   )listreversedr   pop
IndexErrorappendONE_CHAR_COMMANDScopyr   r   r   r   extendjoinsplit)r3   r   chars	raw_charsr   stacking
first_charsearch_charsr   r   r   s              r5   fast_plain_mtextr     s   ( EXl4012I
}}4< }} v~T"**3;LL&S[ LL%  3;!
(~~/
-#++//1#!LL.	 #+
 !-I
 T\S[Yr]c1$==?D"88<<TZZ\JFV,c3%56T"LLa )d WWU^F!&6<<2F2]  0 " -LL&LL,-s)   G2 <:H 8H 2
H ?H ,H21H2c                :    SS jn[         R                  " SX5      $ )zDXF stores some special characters using caret notation. This function
decodes this notation to normalize the representation of special characters
in the string.

see: https://en.wikipedia.org/wiki/Caret_notation

c                X    [        U R                  S5      5      n[        US-
  S-  5      $ )NrT   @   ~   )ordgroupchr)matchcs     r5   replace_match#caret_decode.<locals>.replace_match  s'    AAFc>""r8   z\^(.))r   zre.Matchr   r   )resub)r3   r   s     r5   r   r     s    # 66(M00r8   c                    / nSn XX1-    n[        U5      (       aK  [        U5      U:  a  UR                  U5        U$ X1-  nUS   S:X  a
  USS nUS-  nUR                  U5        OU$ Me  )z9Split the MTEXT content string into chunks of max `size`.r   r   ^NrT   )lenr   )ssizechunksposchunks        r5   split_mtext_stringr      s~    F
C

#u::5zD e$KCRyCcr
qMM% M r8   c           	        / n/ n[        [        5      tnnnnn	n
nnnSU-  n[        U 5       H  nUR                  nX:X  a  UR	                  UR
                  5        M1  X:X  d  X:X  a  UR	                  S5        MN  X:X  d  X:X  a2  UR	                  SR                  U5      5        UR                  5         M  X:X  a  UR	                  U5        M  X:X  d  M  UR
                  u  nnnUR	                  UU-   U-   5        M     U(       a   UR	                  SR                  U5      5        U(       a  U$ SR                  U5      $ )a  Returns the plain MTEXT content as a single string or a list of
strings if `split` is ``True``. Replaces ``\P`` by ``\n`` and removes
other controls chars and inline codes.

This function is much slower than :func:`fast_plain_mtext`, but removes all
inline codes.

Args:
    text: MTEXT content string
    split: split content at line endings ``\P``
    tabsize: count of replacement spaces for tabulators ``^I``

r   r   r   )iter	TokenTypeMTextParsertyper   datar   clear)r3   r   tabsizecontent	paragraph_wordstackspacenbsp	tabulatornew_paragraph
new_columntab_replacementtokentuprlwrdividers                      r5   plain_mtextr    s!   $ GI 	Y
		
GmO T"JJ9UZZ(Z19S!1?NN2779-.OO^_-Z %

CgS7]S01 # rwwy)*99Wr8   c                F    U R                  SS5      R                  SS5      $ )Nr   r   \Preplacer3   s    r5   escape_dxf_line_endingsr  N  s"     <<b!))$66r8   c                :   ^ SR                  U4S jU  5       5      $ )Nr   c              3  L   >#    U  H  n[        U5      (       a  TOUv   M     g 7fri   )is_non_printable_char)rr   r   replacements     r5   ru   3replace_non_printable_characters.<locals>.<genexpr>U  s!     P4a"7":":;A4s   !$)r   )r3   r  s    `r5    replace_non_printable_charactersr  T  s    77P4PPPr8   c                V    S[        U 5      s=:*  =(       a    S:  Os  =(       a    U S:g  $ )Nr       	)r   )r   s    r5   r  r  X  s"    D	B/44</r8   c                   U (       a  U R                  5       (       a  / $ [        R                  " SU 5      nU VVs/ s H,  n[        R                  " SU5        H  oU(       d  M  UPM     M.     nnn/ nSnSn	U H  nU(       + n
US:X  a	  U	(       a  M  Sn	US:X  a#  UR                  UR	                  5       5        SnMD  UR                  5       (       a  U(       d  U
(       a  X-  nMm  Mo  Ub@  U" X-   5      U:  a2  U(       d  X-  nM  UR                  UR	                  5       5        UnSn	M  X-  nM     U(       a4  UR                  5       (       d  UR                  UR	                  5       5        U$ s  snnf )a  Wrap text at ``\n`` and given `box_width`. This tool was developed for
usage with the MTEXT entity. This isn't the most straightforward word
wrapping algorithm, but it aims to match the behavior of AutoCAD.

Args:
    text: text to wrap, included ``\n`` are handled as manual line breaks
    box_width: wrapping length, ``None`` to just wrap at ``\n``
    get_text_width: callable which returns the width of the given string

z(\n)z(\s+)r   Fr   T)isspacer   r   r   rstrip)r3   	box_widthget_text_widthmanual_linesliner  tokenslinescurrent_lineline_just_wrappedon_first_lines              r5   	text_wrapr#  \  s?   " 4<<>>	88GT*L(PLD"((8T2JQaa2JaLFPEL!	9*!9LL,,./LYY[[}!  - $8H)II)U# %LLL!4!4!67#$L(,%!) , L0022\((*+L; Qs   %E0$
E0c                "   U R                  S5      (       d  [        U R                  5        S35      eU R                  (       aL  U R                  R                  R                  U R                  R                  5      nU(       a  UR                  $ g)z`Returns ``True`` if the associated text :class:`~ezdxf.entities.Textstyle`
is vertical stacked.
stylez& does not support the style attribute.F)	is_supported_dxf_attribr   r   docstylesr   r   r%  is_vertical_stacked)r3   r%  s     r5   is_text_vertical_stackedr*    sh     ''004<<>**PQRRxx##DHHNN3,,,r8   r   lrr   jd,01234567890c                D    [        U [        [        45      (       a  U S $ U $ )Ng)r:   r   r   )r   s    r5   rstrip0r3    s!    !c5\""AHr8   c                      \ rS rSr% SrSrS\S'   SrS\S'   SrS\S'   \	R                  rS\S	'   \" 5       rS
\S'   SS jrSrg)ParagraphPropertiesi  a  Stores all known MTEXT paragraph properties in a :class:`NamedTuple`.
Indentations and tab stops are multiples of the default text height
:attr:`MText.dxf.char_height`. E.g. :attr:`char_height` is 0.25 and
:attr:`indent` is 4, the real indentation is 4 x 0.25 = 1 drawing unit.
The default tabulator stops are 4, 8, 12, ... if no tabulator stops are
explicit defined.

Args:
     indent (float): left indentation of the first line, relative to :attr:`left`,
        which means an :attr:`indent` of 0 has always the same indentation
        as :attr:`left`
     left (float): left indentation of the paragraph except for the first line
     right (float): left indentation of the paragraph
     align: :class:`~ezdxf.lldxf.const.MTextParagraphAlignment` enum
     tab_stops: tuple of tabulator stops, as ``float`` or as ``str``,
        ``float`` values are left aligned tab stops, strings with prefix
        ``"c"`` are center aligned tab stops and strings with prefix ``"r"``
        are right aligned tab stops

r   r   indentleftrightr   aligntuple	tab_stopsc           	     |   / nU R                   (       a4  UR                  SU R                   S 35        UR                  [        5        U R                  (       a4  UR                  SU R                  S 35        UR                  [        5        U R                  (       a4  UR                  SU R                  S 35        UR                  [        5        U R
                  (       a:  UR                  S[        U R
                      35        UR                  [        5        U R                  (       aT  UR                  S[        R                  [        [        U R                  5      5       35        UR                  [        5        U(       a4  US   [        :X  a  UR                  5         SS	R                  U5      -   S
-   $ g	)zTReturns the MTEXT paragraph properties as MTEXT inline code
e.g. ``"\pxi-2,l2;"``.

ir2  r+  r,  qr  r   z\pxr   r   )r6  r   COMMAr7  r8  r9  _alignment_charr;  r   mapr3  r   )r2   argss     r5   tostringParagraphProperties.tostring  s+   
 ;;KK!DKK?+,KK99KK!DIIa=)*KK::KK!DJJq>*+KK::KK!ODJJ789:KK>>KK!EJJs7DNN'CDEFGKKBx5 
BGGDM)C//r8   rx   Nr   r   )r   r   r   r   r   r6  __annotations__r7  r8  r   DEFAULTr9  r:  r;  rC  r   rx   r8   r5   r5  r5    sJ    , FED%OE5%<%D%DE"D wIur8   r5  c                  B   \ rS rSrSrS)S*S jjrSrSrSrSr	Sr
SrS	rS
rSrSrSrSrSrSrSrSrS+S jrS+S jrS,S jrS rS-S.S jjrS/S jrS0S jrS/S jrS/S jrS1S jrS2S jr S3S jr!S4S jr"S5S6S  jjr#S+S! jr$S+S" jr%S+S# jr&S+S$ jr'S7S% jr(        S8S& jr)S'r*g()9MTextEditori  a  The :class:`MTextEditor` is a helper class to build MTEXT content
strings with support for inline codes to change color, font or
paragraph properties. The result is always accessible by the :attr:`text`
attribute or the magic :func:`__str__` function as
:code:`str(MTextEditor("text"))`.

All text building methods return `self` to implement a floating interface::

    e = MTextEditor("This example ").color("red").append("switches color to red.")
    mtext = msp.add_mtext(str(e))

The initial text height, color, text style and so on is determined by the
DXF attributes of the :class:`~ezdxf.entities.MText` entity.

.. warning::

    The :class:`MTextEditor` assembles just the inline code, which has to be
    parsed and rendered by the target CAD application, `ezdxf` has no influence
    to that result.

    Keep inline formatting as simple as possible, don't test the limits of its
    capabilities, this will not work across different CAD applications and keep
    the formatting in a logic manner like, do not change paragraph properties
    in the middle of a paragraph.

    **There is no official documentation for the inline codes!**

Args:
    text: init value of the MTEXT content string.

c                $    [        U5      U l        g ri   )r   r3   r2   r3   s     r5   r6   MTextEditor.__init__  s    I	r8   r	  z\N\L\l\O\o\K\k{}z\A0;z\A1;z\A2;\~z^Ic                0    U =R                   U-  sl         U $ )zAppend `text`.r  rK  s     r5   r   MTextEditor.append*  s    		T	r8   c                0    U =R                   U-  sl         U $ )z]
Append `text`::

    e = MTextEditor("First paragraph.\P")
    e += "Second paragraph.\P")

r  rK  s     r5   __iadd__MTextEditor.__iadd__/  s     			T	r8   c                    U R                   $ )z1Returns the MTEXT content attribute :attr:`text`.r  rG   s    r5   __str__MTextEditor.__str__:      yyr8   c                    SU l         g)z%Reset the content to an empty string.r   Nr  rG   s    r5   r   MTextEditor.clear>  s	    	r8   c           
     \    U R                  SU S[        U5       S[        U5       S35      $ )a  Set the text font by the font family name. Changing the font height
should be done by the :meth:`height` or the :meth:`scale_height` method.
The font family name is the name shown in font selection widgets in
desktop applications: "Arial", "Times New Roman", "Comic Sans MS".
Switching the codepage is not supported.

Args:
    name: font family name
    bold: flag
    italic: flag

z\fz|bz|ir   r   r   )r2   namebolditalics       r5   r4   MTextEditor.fontB  s0    & {{bbT2c&k]!DEEr8   c                @    U R                  S[        US5       S35      $ )a  Scale the text height by a `factor`. This scaling will accumulate,
which means starting at height 2.5 and scaling by 2 and again by 3 will
set the text height to 2.5 x 2 x 3 = 15. The current text height is not
stored in the :class:`MTextEditor`, you have to track the text height by
yourself! The initial text height is stored in the
:class:`~ezdxf.entities.MText` entity as DXF attribute
:class:`~ezdxf.entities.MText.dxf.char_height`.

\Hr   zx;r   roundr2   factors     r5   scale_heightMTextEditor.scale_heightW  s$     {{bvq!1 2"566r8   c                @    U R                  S[        US5       S35      $ )z.Set the absolute text height in drawing units.rh  r   r   ri  )r2   rM   s     r5   rM   MTextEditor.heightc  "    {{bvq!1 2!455r8   c                @    U R                  S[        US5       S35      $ )z#Set the absolute text width factor.z\Wr   r   ri  rk  s     r5   width_factorMTextEditor.width_factorg  rq  r8   c                @    U R                  S[        US5       S35      $ )z+Set the absolute character tracking factor.z\Tr   r   ri  rk  s     r5   char_tracking_factor MTextEditor.char_tracking_factork  rq  r8   c                >    U R                  S[        U5       S35      $ )zpSet the text oblique angle in degrees, vertical is 0, a value of 15
will lean the text 15 degree to the right.

z\Qr   rb  )r2   r\   s     r5   re   MTextEditor.obliqueo  s     
 {{bUA.//r8   c                b    U R                  [        R                  UR                  5          5      $ )zcSet the text color by color name: "red", "yellow", "green", "cyan",
"blue", "magenta" or "white".

)acir   MTEXT_COLOR_INDEXr   )r2   rc  s     r5   colorMTextEditor.colorv  s$    
 xx//

=>>r8   c                b    SUs=::  a  S::  a  O  OU R                  SU S35      $ [        S5      e)z3Set the text color by :ref:`ACI` in range [0, 256].r      z\Cr   zaci not in range [0, 256])r   
ValueErrorr2   r{  s     r5   r{  MTextEditor.aci}  s0    ?s?;;"SE|,,455r8   c                L    Uu  p#nU R                  S[        XCU45       S35      $ )z Set the text color as RGB value.z\cr   )r   r   )r2   rgbr,  r2  bs        r5   r  MTextEditor.rgb  s-    a{{b!!3 4A677r8   c                r    US;  a  [        SU 35      eUS:X  a  US-  nU R                  SU U U S35      $ )a  Append stacked text `upr` over `lwr`, argument `t` defines the
kind of stacking, the space " " after the "^" will be added
automatically to avoid caret decoding:

.. code-block:: none

    "^": vertical stacked without divider line, e.g. \SA^ B:
         A
         B

    "/": vertical stacked with divider line,  e.g. \SX/Y:
         X
         -
         Y

    "#": diagonal stacked, with slanting divider line, e.g. \S1#4:
         1/4

^/#zinvalid type symbol: r   r   z\Sr   )r  r   )r2   r  r  r  s       r5   r   MTextEditor.stack  sN    ( E>4QC8998HA{{baSQ/00r8   c                ,    U R                  SU S35      $ )zGroup `text`, all properties changed inside a group are reverted at
the end of the group. AutoCAD supports grouping up to 8 levels.

rS  rT  r   rK  s     r5   r   MTextEditor.group  s    
 {{RvR=))r8   c                ,    U R                  SU S35      $ )z)Append `text` with a line below the text.rM  rN  r  rK  s     r5   	underlineMTextEditor.underline      {{bb>**r8   c                ,    U R                  SU S35      $ )z)Append `text` with a line above the text.rO  rP  r  rK  s     r5   overlineMTextEditor.overline  r  r8   c                ,    U R                  SU S35      $ )z+Append `text` with a line through the text.rQ  rR  r  rK  s     r5   strike_throughMTextEditor.strike_through  r  r8   c                @    U R                  UR                  5       5      $ )zBSet paragraph properties by a :class:`ParagraphProperties` object.)r   rC  )r2   propss     r5   r   MTextEditor.paragraph  s    {{5>>+,,r8   c           	        ^  [        5       R                  [        U* S-  UU4S95      nUR                  SR	                  U 4S j[        X#5       5       5      5        T R                  [        U5      5      $ )u  Build bulleted lists by utilizing paragraph indentation and a
tabulator stop. Any string can be used as bullet. Indentation is
a multiple of the initial MTEXT char height (see also docs about
:class:`ParagraphProperties`), which means indentation in
drawing units is :attr:`MText.dxf.char_height` x `indent`.

Useful UTF bullets:

- "bull" U+2022 = • (Alt Numpad 7)
- "circle" U+25CB = ○ (Alt Numpad 9)

For numbered lists just use numbers as bullets::

    MTextEditor.bullet_list(
        indent=2,
        bullets=["1.", "2."],
        content=["first", "second"],
    )

Args:
    indent: content indentation as multiple of the initial MTEXT char height
    bullets: iterable of bullet strings, e.g. :code:`["-"] * 3`,
        for 3 dashes as bullet strings
    content: iterable of list item strings, one string per list item,
        list items should not contain new line or new paragraph commands.

g      ?)r6  r7  r;  r   c              3  f   >#    U  H&  u  pUTR                   -   U-   TR                  -   v   M(     g 7fri   )TABNEW_PARAGRAPH)rr   r  r   r2   s      r5   ru   *MTextEditor.bullet_list.<locals>.<genexpr>  s/      BW$!DHHq 4#5#55BWs   .1)rI  r   r5  r   r   zipr   r   )r2   r6  bulletsr   itemss   `    r5   bullet_listMTextEditor.bullet_list  sq    < ''w~!)
 	GG BEgBW 	

 zz#e*%%r8   r  N)r   r3   r   )r3   r   r   rI  rE  )FF)rc  r   rd  boolre  r  r   rI  )rl  r   r   rI  )rM   r   r   rI  )r\   r   r   rI  )rc  r   r   rI  )r{  r   r   rI  )r  r   r   rI  )r   )r  r   r  r   r  r   r   rI  )r  r5  r   rI  )r6  r   r  Iterable[str]r   r  r   rI  )+r   r   r   r   r   r6   NEW_LINEr  
NEW_COLUMNUNDERLINE_STARTUNDERLINE_STOPOVERSTRIKE_STARTOVERSTRIKE_STOPSTRIKE_STARTSTRIKE_STOPGROUP_START	GROUP_ENDALIGN_BOTTOMALIGN_MIDDLE	ALIGN_TOPNBSPr  r   rY  r\  r   r4   rm  rM   rs  rv  re   r}  r{  r  r   r   r  r  r  r   r  r   rx   r8   r5   rI  rI    s    @ HMJONOLKKILLID
C
	F*
76660?68
16*+++-*&*&&3*&>K*&	*&r8   rI  c                      \ rS rSrSrg)UnknownCommandi  rx   N)r   r   r   r   r   rx   r8   r5   r  r    s    r8   r  c                  R   \ rS rSrSrSS jrSS jr\rS rSS jr	\
SS j5       r\R                  SS j5       rSSS	 jjr\
SS
 j5       r\R                  SS j5       r\
SS j5       r\R                  SS j5       r\
SS j5       r\R                  SS j5       r\
SS j5       rSrg)MTextContexti  z0Internal class to store the MTEXT context state.c                    SSK Jn  SU l        SU l        SU l        S U l        [        R                  U l        UR                  " 5       U l
        SU l        SU l        SU l        SU l        [        5       U l        g )Nr   r%   F   r,   r   )ezdxf.fontsr&   _strokecontinue_stroke_acir  r   BOTTOMr9  FontFace	font_facer   rs  rv  re   r5  r   )r2   r&   s     r5   r6   MTextContext.__init__  se    %%*	"&'..
)!$#&+.!!,.r8   c                   [        5       nU R                  Ul        U R                  Ul        U R                  Ul        U R                  Ul        U R
                  Ul        U R                  Ul        U R                  Ul        U R                  Ul        U R                  Ul	        U R                  Ul
        U R                  Ul        U$ ri   )r  r  r  r  r  r9  r  r   rs  rv  re   r   )r2   ps     r5   __copy__MTextContext.__copy__  s    NLL	 00**nn**!%!:!:LL	nnr8   c                
   [        U R                  U R                  U R                  U R                  U R
                  U R                  U R                  U R                  U R                  U R                  U R                  45      $ ri   )hashr  r  r  r  r9  r  r   rs  rv  re   r   rG   s    r5   __hash__MTextContext.__hash__  sg    $$		

!!))
 	
r8   c                0    [        U 5      [        U5      :H  $ ri   )r  )r2   others     r5   __eq__MTextContext.__eq__  s    DzT%[((r8   c                    U R                   $ ri   )r  rG   s    r5   r{  MTextContext.aci"  r^  r8   c                T    SUs=::  a  S::  a  O  OXl         S U l        g [        S5      e)Nr   r  zaci not in range[0,256])r  r  r  r  s     r5   r{  r  &  s%    ?s?IDH677r8   c                j    U(       a  U =R                   U-  sl         gU =R                   U) -  sl         g)zSet/clear binary `stroke` flag in `self._stroke`.

Args:
    stroke: set/clear stroke flag
    state: ``True`` for setting, ``False`` for clearing

N)r  )r2   strokestates      r5   _set_stroke_stateMTextContext._set_stroke_state.  s%     LLF"LLLVG#Lr8   c                N    [        U R                  [        R                  -  5      $ ri   )r  r  r   	UNDERLINErG   s    r5   r  MTextContext.underline;  s    DLL;#8#8899r8   c                D    U R                  [        R                  U5        g ri   )r  r   r  r2   values     r5   r  r  ?  s    {44e<r8   c                N    [        U R                  [        R                  -  5      $ ri   )r  r  r   STRIKE_THROUGHrG   s    r5   r  MTextContext.strike_throughC  s    DLL;#=#==>>r8   c                D    U R                  [        R                  U5        g ri   )r  r   r  r  s     r5   r  r  G  s    {995Ar8   c                N    [        U R                  [        R                  -  5      $ ri   )r  r  r   OVERLINErG   s    r5   r  MTextContext.overlineK  s    DLL;#7#7788r8   c                D    U R                  [        R                  U5        g ri   )r  r   r  r  s     r5   r  r  O  s    {33U;r8   c                ,    [        U R                  5      $ ri   )r  r  rG   s    r5   has_any_strokeMTextContext.has_any_strokeS  s    DLL!!r8   )r  r  r9  r   rv  r  r  re   r   r  rs  Nr   r   )r   r  r   r  r   r   )r{  r   )T)r  r   r  r  r   r   )r  r  r   r   )r   r   r   r   r   r6   r  r   r  r  r   r{  setterr  r  r  r  r  r   rx   r8   r5   r  r    s    :/ D
")   	ZZ8 8$ : : = = ? ? B B 9 9 __< < " "r8   r  c                      \ rS rSrSrSS jr\SS j5       r\SS j5       rSS jr	SSS jjr
SSS jjrSSS	 jjrSSS
 jjrSSS jjrSS jrSS jrSS jrSS jrSrg)r   iX  )_text	_text_len_indexc                f    [        U5      U l        [        U R                  5      U l        SU l        g )Nr   )r   r  r   r  r  rK  s     r5   r6   TextScanner.__init__[  s#    Y
TZZr8   c                4    U R                   U R                  :  $ ri   r  r  rG   s    r5   is_emptyTextScanner.is_empty`  s    {{dnn,,r8   c                4    U R                   U R                  :  $ ri   r  rG   s    r5   r   TextScanner.has_datad  s    {{T^^++r8   c                     U R                   U R                     nU =R                  S-  sl        U$ ! [         a     gf = f)NrT   r   r  r  r   )r2   r   s     r5   r   TextScanner.geth  sB    	::dkk*DKK1K   		s   .2 
??c                P    US:  a  [        U5      eU =R                  U-  sl        g )NrT   )r  r  r2   counts     r5   r   TextScanner.consumep  s"    19U##ur8   c                .    U =R                   U-  sl         g)zconsume() without safety checkNr  r  s     r5   fast_consumeTextScanner.fast_consumeu  s    ur8   c                ~    US:  a  [        U5      e U R                  U R                  U-      $ ! [         a     gf = f)Nr   r   )r  r  r  r   r2   offsets     r5   r   TextScanner.peeky  sC    A:V$$	::dkkF233 		s   / 
<<c                \     U R                   U R                  U-      $ ! [         a     gf = f)zpeek() without safety checkr   r  r  s     r5   	fast_peekTextScanner.fast_peek  s1    	::dkkF233 		s    
++c                   U R                  U R                  U R                  S 5      nUR                  (       a  UR	                  5       nU(       a.  US:X  a(  UR	                  S5      U:X  a  UR                  S5        MV  XA:X  a  U R                  UR                  -   $ UR                  S5        UR                  (       a  M  g)a<  Return the index of the next `char`. If `escape` is True, backslash
escaped `chars` will be ignored e.g. "\;;" index of the next ";" is 1
if `escape` is False and 2 if `escape` is True. Returns -1 if `char`
was not found.

Args:
    char: single letter as string
    escape: ignore backslash escaped chars if True.

Nr   rT   r   r   )	__class__r  r  r   r   r   )r2   r   escaper   r   s        r5   findTextScanner.find  s     ..DKKM!:;A!t)Q4(?"y{{W^^33OOA  r8   c                h    XR                   :  a  [        U5      eU R                  U R                   U $ )zCReturns the substring from the current location until index < stop.)r  r   r  )r2   stops     r5   substrTextScanner.substr  s,    ++T""zz$++--r8   c                4    U R                   U R                  S $ )z,Returns the unprocessed part of the content.N)r  r  rG   s    r5   tailTextScanner.tail  s    zz$++-((r8   c                    U R                   $ ri   r  rG   s    r5   indexTextScanner.index  s    {{r8   c                    U R                   X $ ri   )r  )r2   startr  s      r5   substr2TextScanner.substr2  s    zz%%%r8   )r  r  r  Nr  r  rE  )rT   )r  r   r   r   )r   )r  r   r   r   F)r   r   r   r   )r  r   r   r   r  )r  r   r  r   r   r   )r   r   r   r   	__slots__r6   r   r  r   r   r   r  r   r	  r  r  r  r  r  r   rx   r8   r5   r   r   X  sf    0I
 - - , ,
..)&r8   r   c                  <    \ rS rSrSrSrSrSrSrSr	Sr
S	rS
rSrSrg)r   i  r   rT   r   r   r'         r     	   rx   N)r   r   r   r   NONEWORDSTACKSPACEr  	TABULATORr  r  WRAP_AT_DIMLINEPROPERTIES_CHANGEDr   rx   r8   r5   r   r     s5    DDEEDIMJOr8   r   c                  &    \ rS rSrSrSSS jjrSrg)
MTextTokeni  r   ctxr   Nc                (    Xl         X l        X0l        g ri   r.  )r2   r  r/  r   s       r5   r6   MTextToken.__init__  s     	!$	r8   )r/  r   r   ri   )r  r   r/  r  )r   r   r   r   r  r6   r   rx   r8   r5   r-  r-    s    'I r8   r-  z#[+-]?\d+(:?\.\d*)?(:?[eE][+-]?\d+)?z)[+-]?\d+(:?\.\d*)?(:?[eE][+-]?\d+)?([x]?))r+  r,  r   r-  r.  c                      \ rS rSrSr  S   SS jjrSS jrSS jrSS jrSS jr	SS	 jr
SS
 jrS S jrS S jrS S jrS S jrS!S jrS S jrS S jrS S jrS"S#S jjrS#S jrS"S#S jjrS S jrS S jrS rSrg)$r   i  a  Parses the MText content string and yields the content as tokens and
the current MText properties as MTextContext object. The context object is
treated internally as immutable object and should be treated by the client
the same way.

The parser works as iterator and yields MTextToken objects.

Args:
    content: MText content string
    ctx: initial MText context
    yield_property_commands: yield commands that change properties or context,
        default is ``False``

Nc                    Uc
  [        5       nX l        [        [        U5      5      U l        / U l        SU l        [        U5      U l        g NF)	r  r/  r   r   r   
_ctx_stack_continue_stroker  _yield_property_commands)r2   r   r/  yield_property_commandss       r5   r6   MTextParser.__init__  sC     ;.C"<#89.0 %(,-D(E%r8   c                "    U R                  5       $ ri   )parserG   s    r5   __iter__MTextParser.__iter__  s    zz|r8   c                N    U R                   R                  U R                  5        g ri   )r5  r   r/  rG   s    r5   push_ctxMTextParser.push_ctx  s    txx(r8   c                f    U R                   (       a   U R                   R                  5       U l        g g ri   )r5  r   r/  rG   s    r5   pop_ctxMTextParser.pop_ctx  s"    ??**,DH r8   c              #  r  ^ ^^^^^^	^
#    T R                   mTR                  mTR                  mS m[        R                  m[        R
                  m
UUU
4S jm	SUUUU UU	U
4S jjn U" 5       u  p#U(       a<  [        UT R                  U5      v   T(       a  [        TT R                  S 5      v   S mOg MO  7f)Nc                4   > T" 5         U (       a  UmTU 4$ US 4$ ri   rx   )r   r  r   followup_token
word_tokens     r5   word_and_token)MTextParser.parse.<locals>.word_and_token  s%    I!&!4''$;r8   c                 X  > Sn T	R                   (       Gaa  SnT" 5       nT	R                  5       nUS:X  Ga  T" S5      S;   a  SnT" 5         T" 5       nOU (       a  TU 4$ T" 5         T	R                  5       nUS:X  a  [        R                  S 4$ US:X  a  [        R
                  S 4$ US	:X  a  [        R                  S 4$ US
:X  a  [        R                  S 4$ US:X  a  T
R                  5       $ U(       aT   T
R                  U5        T
R                  (       a0  [        R                  T	R                  UT	R                  5       5      4$  GME  US:  a=  US:X  a  T" U [        R                  5      $ US:X  a  T" U [        R
                  5      $ SnOXUS:X  aR  T" S5      S:X  aF  T" S5      R                  5       n[         R"                  R                  U5      nU(       a
  T" S5        UnUS:X  a	  T" U T5      $ U(       dX  US:X  a&  U (       a  TU 4$ T" S5        T
R%                  5         GM"  US:X  a&  U (       a  TU 4$ T" S5        T
R'                  5         GMN  T" 5         US:  a  X-  n T	R                   (       a  GMa  U (       a  TU 4$ [        R(                  S 4$ ! [         a    XU-   -  n  GNbf = f)Nr   Fr   rT   r   T~r   r   Xr   r   r  r   r   r   rS  rT  )r   r  r   r   r  r  r  r*  parse_stackingparse_propertiesr7  r+  r  r  r)  r   r   r   r?  rB  r%  )r   r  r   cmd_start_indexcmdr   special_charr   r   r   r2   space_tokenrH  rG  s          r5   
next_token%MTextParser.parse.<locals>.next_token  s   D"""")--/T>Aw&(!%	!%  #-t#33	%kkm#:#,>>4#77#:#,#:#:D#@@#:#,#7#7#==#:#,#<#<d#BB#:#'#6#6#88& $ 5 5c :
 $(#@#@(1(D(D(/,;W]]_)*,& %& $A ! C<~-dI4G4GHH~-dI4K4KLL Fs]tAw#~7==?D#(#>#>#B#B4#HL#
!-S=)$<<}#-t#33#AJ MMO$3#-t#33#AJ LLN$ 	S=NDa """d !4'' ~~t++o $2 5 $ 45s   3J J)(J)r   ztuple[TokenType, Any])r   r  r	  r   r(  r&  r-  r/  )r2   rS  type_r   r   rF  r   r   rR  rH  rG  s   `   @@@@@@@r5   r;  MTextParser.parse  s      ,,&&  .2oo^^
	X	, X	,t $,KE $77!$^TXXtDD%)N s   B-B7c                   ^^^ U4S jmUU4S jmSUU4S jjnS	UU4S jjn[        U R                  SS95      mU" 5       u  p4U(       a  U" 5       OSn[        R                  X5U44$ )
a  Returns a tuple of strings: (numerator, denominator, type).
The numerator and denominator is always a single and can contain spaces,
which are not decoded as separate tokens. The type string is "^" for
a limit style fraction without a line, "/" for a horizontal fraction
and "#" for a diagonal fraction. If the expression does not contain
any stacking type char, the type and denominator string are empty "".

c                 J   > TR                  5       n [        U 5      S:  a  Sn U $ )Nr  r   )r   r   )r   stacking_scanners    r5   	peek_char-MTextParser.parse_stacking.<locals>.peek_charz  s&     %%'A1v{Hr8   c                 ~   > Sn T" 5       nUS:X  a  Sn TR                  S5        T" 5       nTR                  S5        X4$ )NFr   TrT   )r   )r  r   r[  rZ  s     r5   get_next_char1MTextParser.parse_stacking.<locals>.get_next_char  sF    FADy ((+K$$Q'9r8   c                    > Sn TR                   (       a0  T" 5       u  pU(       d	  US;   a  X4$ X-  n TR                   (       a  M0  U S4$ )Nr   r  r   )r   r   r  r^  rZ  s      r5   parse_numerator3MTextParser.parse_stacking.<locals>.parse_numerator  sJ    D"++)O	!u*7N		 #+++
 8Or8   c                 n   > Sn TR                   (       a   U T" 5       S   -  n TR                   (       a  M   U $ )Nr   r   ra  )r   r^  rZ  s    r5   parse_denominator5MTextParser.parse_stacking.<locals>.parse_denominator  s5    D"++** #+++Kr8   Tr  r   )r   ztuple[str, str]rE  )r   extract_expressionr   r'  )	r2   rb  re  	numeratorstacking_typedenominatorr^  r[  rZ  s	         @@@r5   rM  MTextParser.parse_stackingp  sh    				 		 	 't'>'>d'>'KL#2#4 	-:') GGGr8   c                   U R                   R                  5       nUS:X  a  SUl        SU l        GOUS:X  a!  SUl        UR                  (       d  SU l        GOeUS:X  a  SUl        SU l        GOOUS:X  a!  SUl        UR                  (       d  SU l        GO(US:X  a  SUl        SU l        GOUS:X  a   SUl        UR                  (       d  SU l        OUS	:X  a  U R                  U5        OUS
:X  a  U R                  U5        OUS:X  a  U R                  U5        OUS:X  a  U R                  U5        OUS:X  a  U R                  U5        OtUS:X  a  U R                  U5        O\US:X  a  U R                  U5        ODUS:X  a  U R                  U5        O,US:X  d  US:X  a  U R                  U5        O[!        SU 35      eU R                  Ul        X l         g )NLTr+  FOoKkACr   HWQTr  fFzunknown command: )r/  r   r  r6  r  r  r  parse_alignparse_aci_colorparse_rgb_colorparse_heightparse_widthparse_obliqueparse_char_trackingparse_paragraph_propertiesparse_font_propertiesr  r  )r2   rP  new_ctxs      r5   rN  MTextParser.parse_properties  s    ((--/#: $G$(D!CZ %G))(-%CZ#G$(D!CZ$G))(-%CZ%)G"$(D!CZ%*G"))(-%CZW%CZ  )CZ  )CZg&CZW%CZw'CZ$$W-CZ++G4CZ3#:&&w/ #4SE!:;;"&"7"7r8   c                    U R                   R                  5       nUS;   a  [        [        U5      5      Ul        O[        R
                  Ul        U R                  5         g )N012)r   r   r   r   r9  r  consume_optional_terminator)r2   r/  r   s      r5   r{  MTextParser.parse_align  sD    ||!5=*3t95CI*11CI((*r8   c                d    U R                  UR                  5      Ul        U R                  5         g ri   )parse_float_value_or_factorr   r  r2   r/  s     r5   r~  MTextParser.parse_height  s$    99#..I((*r8   c                d    U R                  UR                  5      Ul        U R                  5         g ri   )r  rs  r  r  s     r5   r  MTextParser.parse_width  s'    ;;C<L<LM((*r8   c                d    U R                  UR                  5      Ul        U R                  5         g ri   )r  rv  r  r  s     r5   r  MTextParser.parse_char_tracking  s,    #'#C#C$$$
  	((*r8   c                    U R                  SS9nU(       aH  UR                  S5      (       a  [        US S 5      nU[        U5      -  nU$ [        [        U5      5      nU$ )NTrelativerp   r   )extract_float_expressionendswithr   abs)r2   r  exprrl  s       r5   r  'MTextParser.parse_float_value_or_factor  sa    ,,d,;}}S!!tCRy)V$  E$K(r8   c                p    U R                  SS9nU(       a  [        U5      Ul        U R                  5         g )NFr  )r  r   re   r  )r2   r/  oblique_exprs      r5   r  MTextParser.parse_oblique  s0    44e4D-CK((*r8   c                    U R                  5       nU(       a  [        U5      nUS:  a  X1l        S Ul        U R	                  5         g )Ni  )extract_int_expressionr   r{  r  r  )r2   r/  aci_exprr{  s       r5   r|  MTextParser.parse_aci_color  s;    ..0h-CSy((*r8   c                    U R                  5       nU(       a+  [        [        U5      S-  5      u  p4n[        XTU5      Ul        U R                  5         g )Ni )r  r    r   r   r  r  )r2   r/  rgb_exprr  r2  r,  s         r5   r}  MTextParser.parse_rgb_color  sC    ..0c(mh67GA!!lCG((*r8   c                    SnU R                   R                  5       nU(       a  [        O[        n[        R
                  " XC5      nU(       a1  UR                  5       u  pgX6U nU R                   R                  U5        U$ Nr   )r   r  
RE_FLOAT_XRE_FLOATr   r   spanr   )r2   r  r   r  patternr   r  ends           r5   r  $MTextParser.extract_float_expression  s`    ||  " (*h'JE_FLL  %r8   c                    SnU R                   R                  5       n[        R                  " SU5      nU(       a1  UR	                  5       u  pEX$U nU R                   R                  U5        U$ )Nr   z\d+)r   r  r   r   r  r   )r2   r   r  r   r  r  s         r5   r  "MTextParser.extract_int_expression  sY    ||  "&JE_FLL  %r8   c                    U R                   R                  SUS9nUS:  a  U R                   R                  5       nOU R                   R                  U5      nU R                   R	                  [        U5      S-   5        U$ )zReturns the next expression from the current location until
the terminating ";". The terminating semicolon is not included.
Skips escaped "\;" semicolons if `escape` is True.

r   rg  r   rT   )r   r  r  r  r   r   )r2   r  r  r  s       r5   rh  MTextParser.extract_expression  si     ||  V 4!8<<$$&D<<&&t,DSY]+r8   c           	     l  ^^^ SU4S jjnSUU4S jjmU4S jm[        U R                  5       5      mUR                  u  p4pVnTR                  (       GaD  TR	                  5       nUS:X  a	  U" 5       nGOUS:X  a	  U" 5       nGOUS:X  a  U" 5       nOUS:X  a  OUS:X  a<  TR	                  5       n	[
        R	                  U	[        R                  5      nT" 5         OUS	:X  a  / nTR                  (       a  TR                  5       n
U
S:X  d  U
S
:X  a*  TR                  5         UR                  U
T" 5       -   5        O9T" 5       nU(       a  UR                  [        U5      5        OTR                  5         TR                  (       a  M  TR                  (       a  GMD  [        X4XV[        U5      5      Ul        g )Nc                 >   > Sn T" 5       nU(       a  [        U5      n U $ )Nr   )r   )r  r  parse_float_exprs     r5   parse_float;MTextParser.parse_paragraph_properties.<locals>.parse_float+  s!    E#%DdLr8   c                    > Sn TR                  5       n[        R                  " [        U5      nU(       a.  UR	                  5       u  p4XU n TR                  U5        T" 5         U $ r  )r  r   r   r  r  r   )r  r  r   r  r  paragraph_scannerskip_commass        r5   r  @MTextParser.parse_paragraph_properties.<locals>.parse_float_expr2  sW    D$))+DHHXt,E"ZZ\
#!))#.Kr8   c                 ~   > T R                  5       S:X  a(  T R                  S5        T R                  5       S:X  a  M'  g g )Nr/  rT   )r   r   )r  s   r5   r  ;MTextParser.parse_paragraph_properties.<locals>.skip_commas=  s5    #((*c1!))!, $((*c1r8   r=  r+  r,  rp   r>  r  r   r   rE  )r   rh  r   r   r   CHAR_TO_ALIGNr   rG  r   r   r   r   r5  r:  )r2   r/  r  r6  r7  r8  r9  r;  rP  
adjustmentrV  
float_exprr  r  r  s               @@@r5   r  &MTextParser.parse_paragraph_properties*  ss   			 			- ((?(?(AB03-eI(((#'')Ccz$"}#.224
%))*6M6U6UV	'00-224E|u|)113!((1A1C)CD%5%7
%%,,U:->? .557 (000!  (((: ,%i(8
r8   c                2   SSK Jn  U R                  5       R                  S5      nU(       ak  US   (       a`  US   nSnSnUSS   H7  nUR	                  S5      (       a  SnM  UR	                  S	5      (       d  M5  S
nM9     UR
                  " XEUS9Ul        g g g )Nr   r%   |Regulari  rT   b1i  i1Italic)familyr%  weight)r  r&   rh  r   
startswithr  r  )r2   r/  r&   partsrc  r%  r  parts           r5   r  !MTextParser.parse_font_propertiesd  s    %'')//4U1X8DEF ab	??4(( F__T**$E	 "
 "NN$FSCM 5r8   c                x    U R                   R                  5       S:X  a  U R                   R                  S5        g g )Nr   rT   )r   r   r   rG   s    r5   r  'MTextParser.consume_optional_terminatorv  s.    <<#%LL  # &r8   )r6  r5  r7  r/  r   r4  )r   r   r/  zOptional[MTextContext])r   zIterator[MTextToken]r  rU  )rP  r   r   r   )r/  r  r   r  rE  )r   r   r   r   r   r6   r<  r?  rB  r;  rM  rN  r{  r~  r  r  r  r  r|  r}  r  r  rh  r  r  r  r   rx   r8   r5   r   r     s    $ '+ %	FF $F)-tl-H^.`+++++++	8
tT$$r8   r   c                f    SnSnU  H  u  p4US:X  a  UnM  US:X  d  M  X$-  nM     [        X!-   5      $ )Nr   rT   r   )r  )tagsr  r   r   r  s        r5   load_mtext_contentr  {  sB    DG19DQYG	 
 #7>22r8   c                L    SU R                  SS5      R                  SS5      ;   $ )zDReturns `True` if `text` contains any MTEXT inline formatting codes.r   r	  r   rU  r
  r  s    r5   has_inline_formatting_codesr    s0     4<<rgr r8   c                B    U S-  n SU-   U s=:  =(       a    SU-
  :  $ s  $ )up  Returns ``True`` if the given text `angle` in degrees causes an upside
down text in the :ref:`WCS`. The strict flip range is 90° < `angle` < 270°,
the tolerance angle `tol` extends this range to: 90+tol < `angle` < 270-tol.
The angle is normalized to [0, 360).

Args:
    angle: text angle in degrees
    tol: tolerance range in which text flipping will be avoided

     v@g     V@g     p@rx   r\   tols     r5   is_upside_down_text_angler    s.     
UNE#:++++++r8   c                6    [        X5      (       a  U S-  n U S-  $ )zReturns a readable (upright) text angle in the range `angle` <= 90+tol or
`angle` >= 270-tol. The angle is normalized to [0, 360).

Args:
    angle: text angle in degrees
    tol: tolerance range in which text flipping will be avoided

g     f@r  )r  r  s     r5   upright_text_angler    s"     !,,5=r8   c                    U S-  U-  $ )zReturns the distance from baseline to baseline.

Args:
    cap_height: cap height of the line
    line_spacing: line spacing factor as percentage of 3-on-5 spacing

gy&1?rx   )r   line_spacings     r5   leadingr    s     ,,r8   c                   ^  SU 4S jjn[        T R                  U" 5       T R                  R                  SS5      T R                  R	                  S5      S9$ )a@  Estimate the width and height of a single column
:class:`~ezdxf.entities.MText` entity.

This function is faster than the :func:`~ezdxf.tools.text_size.mtext_size`
function, but the result is very inaccurate if inline codes are used or
line wrapping at the column border is involved!

Returns:
    Tuple[width, height]

c                 :  > SSK Jn   TR                  R                  S5      nTR                  nU(       aH  UR
                  R                  TR                  R                  S5      5      nUb  UR                  U5      $ U R                  " [        R                  US9$ )Nr   r%   char_heightr%  )r   )
r  r&   r   get_defaultr'  r(  r   	make_fontr   DEFAULT_TTF)r&   r   r'  r%  mtexts       r5   
_make_font*estimate_mtext_extents.<locals>._make_font  ss    %!II11-@
iiJJNN599#8#8#ABE z22u00ZHHr8   rH   r   line_spacing_factor)r   r4   column_widthr  )r   r   )estimate_mtext_content_extentsr3   r   r   r  )r  r  s   ` r5   estimate_mtext_extentsr    sI    	I *

\YY]]7C0!II112GH	 r8   )\(?c                    U q g)z7Set the global safety factor for MTEXT size estimation.N_SAFETY_FACTOR)rl  s    r5   set_estimation_safety_factorr    s	     Nr8   c                     Sq g)zZReset the global safety factor for MTEXT size estimation to the hard coded
default value.
r  Nr  rx   r8   r5   reset_estimation_safety_factorr    s	    
 Nr8   c                   SnSnUR                   R                  nUS:  n[        U SS9n[        U5      (       a  Sn	U H{  n
UR	                  U
5      nUS:X  a#  U
(       a  [        U
5      UR                  5       -  nU(       a'  U	[        R                  " X-  5      -  n	[        X5      nOU	S-  n	[        XK5      nM}     [        Xc5      U-
  nXi-  XS-
  -  -   nU[        -  U4$ )a3  Estimate the width and height of the :class:`~ezdxf.entities.MText`
content string. The result is very inaccurate if inline codes are used or
line wrapping at the column border is involved!
Column breaks ``\N`` will be ignored.

Args:
    content: the :class:`~ezdxf.entities.MText` content string
    font: font abstraction based on :class:`ezdxf.tools.fonts.AbstractFont`
    column_width: :attr:`MText.dxf.width` or 0.0 for an unrestricted column
        width
    line_spacing_factor: :attr:`MText.dxf.line_spacing_factor`

Returns:
    tuple[width, height]

r   T)r   r   rT   )rK   r   r   anyr.   r   space_widthr   ceilminmaxr  r  )r   r4   r  r  	max_widthrM   r   has_column_widthr  
line_countr  
line_widthspacings                r5   r  r    s    , IF))44J)C/'t<E
5zz
D.JQ4 !Y)9)9);;
dii
(ABB
 :
a
 I2I " *:ZG(71n+EE~%v--r8   c                J    [        U [        5      (       a  [        U 5      SU $ g)zaReturns a string with line breaks ``\n`` replaced by ``\P`` and the
length limited to `max_len`.
Nr   )r:   r   r  )r   max_lens     r5   safe_stringr  %  s&     !S&q)(733r8   z0123456789.c                   ^ SU4S jjnSU ;  a  U $ [        T5      mU R                  S5      nUS   /nUSS  H  nUR                  U" US5      5        M     SR                  U5      $ )zGScale all inline commands which define an absolute value by a `factor`.c                   > Sn X   [         ;   a  US-  nX   [         ;   a  M  X   S:X  a  U U  3$   [        U S U 5      T-  nUS nU U XS   3$ ! [         a     N,f = f! [         a    Sn N(f = f)Nr   rT   rp   z.3gr   )VALID_HEIGHT_CHARSr   r   r  )r  prefixr  new_sizer  rl  s        r5   _scale_leading_number:scale_mtext_inline_commands.<locals>._scale_leading_number4  s    	-#55
 -#55}# &** $	VFU^,v5HnE (5'&.!122  		
  	E	s'   A A A# 
A A #A21A2rh  r   rT   Nr   )r  r   r  r   r   r   )r  r   r   r   )r   rl  r  	old_parts	new_partsr  s    `    r5   scale_mtext_inline_commandsr  1  sp    3$ G[Fe$I%aL>I!".tU;<  779r8   )r   r   rZ   r   r   r   )r]   r   r[   r   r   r   )r   zUnion[Text, MText]r   ztuple[int, int])r3   r   r   r   r  )r3   r   r   Union[list[str], str])   )r   r   r   r   r   	list[str])Fr'   )r3   r   r   r   r   r  )u   ▯)r3   r   r  r   r   r   )r   r   r   r  )r3   r   r  zOptional[float]r  zCallable[[str], float]r   r
  )r3   r#   r   r  )r   r   r   r   )r  r$   r   r   )r3   r   r   r  )g      @)r\   r   r  r   r   r  )r\   r   r  r   r   r   )r,   )r   r   r  r   r   r   )r  r"   r   r   )rl  r   r   r   r  )r   r,   )
r   r   r4   r   r  r   r  r   r   r   )r   zOptional[str]r  r   r   r   )r   r   rl  r   r   r   )dr   
__future__r   typingr   r   r   r   r   r	   r
   r   enumr   r   ezdxf.lldxfr   r   ezdxf.enumsr   r   r   r   r   r   ezdxf.lldxf.constr   r   r   r   r   r   r   
ezdxf.mathr   r   r   ezdxf.colorsr   r   r    ezdxf.entitiesr!   r"   r#   ezdxf.lldxf.tagsr$   r  r&   r   r)   rj   rk   r   r   r   r   r   r   r  r  r  r  r#  r*  rG  	JUSTIFIEDDISTRIBUTEDr@  r?  DIGITSr3  r5  rI  	Exceptionr  r  r   IntEnumr   r-  compiler  r  r  r   r  r  r  r  r  r  r  r  r  r  r  setr   r  rx   r8   r5   <module>r     s   #	 	 	  	  (    ( ' . . 55%!j/ j/Z	.:<   dK3\1 , 7
7 7 	7t7Q01
11 +1 	1h ##R  #!!3""C%%s'' 		=* =Ho& o&d	Y 	j" j"ZU& U&p
 
  ::<=ZZDE
 
!	%	%	 	&	&	 	'	'	 	*	*	 	,	,f$ f$R3,
-@  !$	2.2.
2. 2. 	2.
 2.j 2=  ' r8   