
    h5jB                       d Z ddlmZ ddlZddlmZmZ ddlmZ ddl	m
Z
 ddlmZ ddl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mZmZmZ ddlmZ ddlmZ ddl m!Z!m"Z"m#Z#m$Z$m%Z% erddl&m'Z'  ejP                  e)      Z* edg d      Z+ e+dddd      Z, e+dddd      Z- e+dddd      Z. e+dddd      Z/ e+dddd      Z0 e+dddd      Z1 e+dddd      Z2 e+dddd      Z3 G d de      Z4 G d de      Z5 G d de5      Z6 G d de5      Z7 G d de6      Z8d,d Z9d-d!Z: G d" d#      Z;e G d$ d%             Z< G d& d'      Z= G d( d)      Z> G d* d+      Z?y).a  Low-level module for generating PDF content streams.

Most users should use another library such as reportlab for a more intuitive
interface. In particular, it does not have a text layout engine and only has
rudimentary font management.

This module is useful if you need full manual control over how
content streams are generated. OCRmyPDF, for example, uses this module to
to generate OCR text with precise text positioning on the page in a way that
isn't possible (or desirable) with reportlab or other libraries.
    )annotationsN)ABCabstractmethod)
namedtuple)contextmanager)	dataclassDecimal)Enum)BytesIO)Path)TYPE_CHECKINGcast)ContentStreamInstructionMatrixPdf)CHARNAMES_TO_UNICODE)unparse_content_stream)Array
DictionaryNameOperatorStringImageColor)redgreenbluealpha   g      ?c                      e Zd ZdZdZ	 dZy)TextDirectionzEnumeration for text direction.r!      N)__name__
__module____qualname____doc__LTRRTL     D/var/www/html/qr/venv/lib/python3.12/site-packages/pikepdf/canvas.pyr#   r#   5   s    )
C%
C6r,   r#   c                  R    e Zd ZdZe	 dddd	 	 	 	 	 	 	 	 	 dd       Zed	d       Zy)
FontzBase class for fonts.r   char_spacingword_spacingc                    y)FEstimate the width of a text string when rendered with the given font.Nr+   selftextfontsizer1   r2   s        r-   
text_widthzFont.text_widthA       r,   c                     y)aN  Register the font.

        Create several data structures in the Pdf to describe the font.

        After registering the font, the returned object should be added to the
        /Resources dictionary of any page or Form XObject that uses the font. For
        example one might write:

        ```python
        page.Resources.Font[Name.Arial] = font.register(pdf)
        ```

        The same object can be used for multiple pages or Form XObjects, since it is
        an indirect object.

        Returns a Dictionary suitable for insertion into a /Resources /Font dictionary.
        Nr+   r6   pdfs     r-   registerzFont.registerL   r:   r,   Nr!   
r7   str | bytesr8   float | int | Decimalr1   int | Decimalr2   rC   returnrB   r=   r   rD   r   )r%   r&   r'   r(   r   r9   r>   r+   r,   r-   r/   r/   >   su     +,U
 '(&'UU (U
 $U $U 
U U  r,   r/   c                  v    e Zd ZdZeedd              Zeedd              Zeedd              Zed	d       Z	y)
DimensionedFontzBase class for fonts that have dimensional information.

    Specifically, these fonts can provide leading and ascent/descent values, and
    encode strings to the encoding used by the font.

    .. versionadded:: 9.8.1
    c                     y)zHDefault leading (line spacing) value for this font; 0 if not applicable.Nr+   r6   s    r-   leadingzDimensionedFont.leadingj   r:   r,   c                     y)z.The max height of the font above the baseline.Nr+   rI   s    r-   ascentzDimensionedFont.ascento   r:   r,   c                     y)z.The max height of the font below the baseline.Nr+   rI   s    r-   descentzDimensionedFont.descentt   r:   r,   c                     y)z2Encode a string in the encoding used by this font.Nr+   r6   r7   s     r-   encodezDimensionedFont.encodey   r:   r,   N)rD   zDecimal | int)rD   zDecimal | int | Noner7   strrD   bytes)
r%   r&   r'   r(   propertyr   rJ   rL   rN   rQ   r+   r,   r-   rG   rG   a   ss     W  W =  = =  = A Ar,   rG   c                  >    e Zd ZdZ	 dddd	 	 	 	 	 	 	 	 	 ddZd	dZy)
	Helveticaa  Helvetica font.

    Helvetica is one of the 14 PDF standard fonts that can typically be counted on being
    present even if not embedded in the PDF document. However, starting with PDF 2.0,
    PDF processors are no longer guaranteed to have these fonts. See 9.6.2.2.
    r   r0   c                   t               )r4   )NotImplementedErrorr5   s        r-   r9   zHelvetica.text_width   s     "##r,   c                    |j                  t        t        j                  t        j                  t        j
                              S )Register the font.)BaseFontTypeSubtype)make_indirectr   r   rW   r/   Type1r<   s     r-   r>   zHelvetica.register   s2      YY


 	
r,   Nr?   r@   rE   )r%   r&   r'   r(   r9   r>   r+   r,   r-   rW   rW   ~   sS     +,	$
 '(&'	$	$ (	$
 $	$ $	$ 
	$
r,   rW   c                      e Zd ZU dZded<   dZddZedd       ZddZ	e
dd       Ze
dd	       Ze
dd
       ZddZ	 d	 	 	 	 	 ddZ	 d	 	 	 	 	 ddZddZddZ	 d	 	 	 	 	 ddZ	 dddd	 	 	 	 	 	 	 	 	 d dZy)!
SimpleFonta  Font implementation designed to work with Type 1 Fonts and TrueType fonts.

    As described in section 9.6 of the PDF spec.

    See also section 9.8: Font Descriptors.

    The PDF spec also considers Type3 fonts to be "Simple Fonts", but Type3 fonts are
    not implemented here.
    r   dataNc                    t         j                  |vs;|j                  t         j                  t         j                  t         j                  fvrt        d|      || _        y)z=Create a SimpleFont instance from a font resource dictionary.zDFont resource dictionary does not describe a Type1 or TrueType font:N)r   r^   r`   MMType1TrueType
ValueErrorrc   )r6   rc   s     r-   __init__zSimpleFont.__init__   sQ    <<t#t||JJLLMM<
 (

 V  	r,   c           	        ||j                   vr9t        d| ddj                  |j                   j                                d      |j                   |   }t	        |t
              st        d| dt        |              | |      S )z3Load a font from the specified resource dictionary.z!Cannot find font information for z (Available fonts: z, )zFont data for z is not a dictionary, but a )r/   LookupErrorjoinkeys
isinstancer   	TypeErrortype)clsnameresource_dict	font_datas       r-   loadzSimpleFont.load   s     })))3D6 :%%)YY}/A/A/F/F/H%I$J!M  "&&t,	)Z0 &B4	?BST  9~r,   c                8    |j                  | j                        S )r[   )r_   rc   r<   s     r-   r>   zSimpleFont.register   s      ++r,   c                    t         j                  | j                  j                  v r*t	        d| j                  j                  j                        S y)z!Returns leading for a SimpleFont.rC   r   )r   Leadingrc   FontDescriptorr   rI   s    r-   rJ   zSimpleFont.leading   s:     <<499333)A)A)I)IJJr,   c                ^    t        t        | j                  j                  j                        S )z Returns ascent for a SimpleFont.)r   r
   rc   ry   AscentrI   s    r-   rL   zSimpleFont.ascent   s!     GTYY55<<==r,   c                ^    t        t        | j                  j                  j                        S )z!Returns descent for a SimpleFont.)r   r
   rc   ry   DescentrI   s    r-   rN   zSimpleFont.descent   s!     GTYY55==>>r,   c                   t        |t              r| j                  |      }t        |t        t        t
        f      rt        |d         }| j                  j                  t        j                        }||t        |      ndz
  }t        j                  | j                  v rKt        | j                  j                        |kD  r)t        t        | j                  j                  |         }|S t        j                  | j                  j                   v r0t        t        | j                  j                   j                        }|S t        d      }|S )zGet the (unscaled) width of the character, in glyph-space units.

        Args:
            char: The character to check. May be a char code, or a string containing a
                single character.
        r   )rn   rS   rQ   rT   	bytearray
memoryviewintrc   getr   	FirstCharWidthslenr   r
   MissingWidthry   )r6   char
first_char	char_codewidths        r-   unscaled_char_widthzSimpleFont.unscaled_char_width   s     dC ;;t$DdUIz:;tAw<DYY]]4>>2
J4JZPQR	;;$))#DII,<,<(=	(I$))"2"29"=>E
 	 $))":"::$))":":"G"GHE  AJEr,   c                (    t        d      }||z  |z  S )a  Convert width from glyph space to text space, scaling by font size.

        Scaling based on the nominal height (see 9.2.2):

        "This standard is arranged so that the nominal height of tightly spaced lines of
        text is 1 unit. ... The standard-size font shall then be scaled to be usable."

        This means, essentially, that a font size of 1 means a character is 1 text-space
        unit high, and a font size of 12 is 12 text-space units high. Assuming no text
        scaling is in place (such as via the text matrix), and the PDF has not set a
        user-defined unit in the page dictionary, then text space units will be points
        (defined as 1/72 of an inch).
          r	   r6   r   r8   glyph_space_ratios       r-   convert_widthzSimpleFont.convert_width   s    $ $DM))X55r,   c                (    t        d      }||z  |z  S )zHConvert width from text space back to glyph space, scaling by font size.r   r	   r   s       r-   convert_width_reversez SimpleFont.convert_width_reverse  s     $DM))X55r,   c                @   t         j                  | j                  vrt        d      t	        | j                  j                  t               r4| j                  |t        t         | j                  j                              S t	        | j                  j                  t              rt        t        | j                  j                        }t         j                  |v rT|j                  t         j                        }| j                  |t        t        |j                        t        d|            S t         j                  |vrt        d      | j                  |t        t         |j                              S t        dt        | j                  j                               )a  Encode a string in the encoding used by this font.

        This currently only works with fonts that use the WinAnsiEncoding or the
        MacRomanEncoding. Differences maps are supported, though with a limited
        set of recognized character names.
        z1Cannot encode without explicitly defined encodingName | NonezUnsupported encoding type: )r   Encodingrc   rY   rn   _encode_namedr   r   Differencesr   BaseEncoding_encode_diffmapr   ro   rp   )r6   r7   encoding_dictbase_encodings       r-   rQ   zSimpleFont.encode  sC    ==		) &C  dii(($/%%dDtyy7I7I,JKKdii((*5 TYY-?-?@M=0 - 1 1$2C2C D++ 9 9:6 
   5)G  %%dD}7Q7Q,RSS5d499;M;M6N5OPQQr,   c                j   |t         j                  k(  rt        d      |t         j                  k(  r|j	                  d      S |t         j
                  k(  r|j	                  d      S |t         j                  k(  rt        d      |t         j                  k(  r|j	                  d      S t        d|      )Nz!Cannot encode to StandardEncodingcp1252	mac_romanz"Cannot encode to MacExpertEncodingpdfdoc_pikepdfzUnknown encoding:)	r   StandardEncodingrY   WinAnsiEncodingrQ   MacRomanEncodingMacExpertEncodingPDFDocEncodingrg   )r6   r7   encodings      r-   r   zSimpleFont._encode_named4  s    t,,, &&IJJt+++;;x((t,,,;;{++t--- &&JKKt*** ;;/00,h77r,   c                   | j                   t        |      | _         t               }|D ]  }|| j                   v r|j                  | j                   |          0|"|j	                  | j                  ||             T|j                         r|j                  t        |             t        j                  dt        |       d        |S )NzNo mapping for z in current encoding; skipped)_diffmap_cache_differences_map_lookupr   appendextendr   isasciiordlogwarningrepr)r6   r7   diffmapr   resultr   s         r-   r   zSimpleFont._encode_diffmapG  s     &"9'"BD 		YDt***d11$78*d00}EFc$i( od4j\9VWX		Y r,   r   r0   c               
   d}t        d      }t        |t              r| j                  |      }|D ]$  }|| j	                  |      |z   z  }||k(  s ||z  }& t        |t
              rt        |      }| j                  ||      S )ak  Get the width of the string.

        This is the width of the string when rendered with the current font, scaled by
        the given font size.

        Args:
            text: The string to check
            fontsize: The target font size in text-space units. (Assuming text space
                isn't being scaled, this means the font size in points.)
            char_spacing: Additional space that will be added between each character.
                May be negative.
            word_spacing: Additional space that will be added after each ASCII space
                character (' '). May be negative.
        r    )r   rn   rS   rQ   r   floatr
   r   )r6   r7   r8   r1   r2   r   ascii_spacebytes           r-   r9   zSimpleFont.text_widthY  s    ,  !#hdC ;;t$D 	&D
 T--d3lBBE{"%	& h&x(H!!%22r,   )rc   r   )rr   r   rs   r   rD   rb   rE   )rD   rC   )rD   r
   )r   zint | bytes | strrD   r
   r?   )r   rC   r8   rC   rD   rC   rR   )r7   rS   r   r   N)r7   rS   r   r   r   r   r@   )r%   r&   r'   r(   __annotations__r   rh   classmethodru   r>   rU   rJ   rL   rN   r   r   r   rQ   r   r   r9   r+   r,   r-   rb   rb      s/    N  ,   > >
 ? ?
0 ?@6"6.;6	6, ?@6"6.;6	6R>8( GK"'8C* +,$3
 '(&'$3$3 ($3
 $$3 $$3 
$3r,   rb   c              #  l   K   d}| D ])  }t        |t              r||f |dz  }t        |      }+ yw)aT  Parses a Differences map to ``(char_code, char_name)`` pairs.

    This procedure is as described in 9.6.5.1.

    Here, ``char_code`` refers to the byte value of the character as it would appear in
    a text content stream using this font; it is the PDF encoding, not the true unicode
    character code. The corresponding ``char_name`` refers to the name of the glyph. The
    name is used by Type1 and Type3 fonts to look up the actual glyph used from the
    font.

    A partial mapping of glyph names to true unicode characters is available at
    pikepdf._data.CHARNAMES_TO_UNICODE`.
    r   r!   N)rn   r   r   )r   countervalues      r-   _parse_differences_mapr     sD      G !eT"5. qLG %jG!s   24c                    i }t        |       D ]  \  }}	 ||t        t        |         <    |S # t        $ r$ t        j                  dt        |              Y Lw xY w)as  Convert a Differences map (See 9.6.5.1) to a Python dict.

    The Python dict maps unicode characters to the character index value.

    The character index values are the byte values used in actual text content streams.

    If the difference map encodes characters whose names aren't recognized, they will be
    omitted from the final map, and a warning emitted.
    z*Unknown character name in difference map: )r   r   rS   KeyErrorr   r   )r   diffindexrr   s       r-   r   r     so     D-g6 Rt	R49D%c$i01R
 K  	RKKDSYKPQ	Rs   .*AAc                     e Zd ZdZd Zd%dZd&dZd Zd Zd'dZ	d Z
d	 Zd(d
Zd)dZd Zd*dZd+dZd+dZd+dZd'dZd,dZd-dZd.dZd/dZd.dZ	 	 	 	 	 	 d0dZd Zd Zd Zd Zd1dZd2dZd2dZ d Z!d3d Z"d4d"Z#d5d#Z$d6d$Z%y!)7ContentStreamBuilderzContent stream builder.c                "    t               | _        yzInitialize.N)r   _streamrI   s    r-   rh   zContentStreamBuilder.__init__  s     {r,   c                H    | xj                   t        |g      dz   z  c_         y )N   
)r   r   r6   insts     r-   _appendzContentStreamBuilder._append  s    .v6>>r,   c                    t        |t              r | xj                  |j                  z  c_        y| xj                  |dz   z  c_        y)zAppend another content stream.r   N)rn   r   r   )r6   others     r-   r   zContentStreamBuilder.extend  s1    e12LLEMM)LLLEEM)Lr,   c                R    t        g t        d            }| j                  |       | S )Save the graphics state.qr   r   r   r   s     r-   pushzContentStreamBuilder.push  #    'HSM:Tr,   c                R    t        g t        d            }| j                  |       | S )zRestore the graphics state.Qr   r   s     r-   popzContentStreamBuilder.pop  r   r,   c                f    t        |j                  t        d            }| j                  |       | S )zConcatenate matrix.cmr   	shorthandr   r   r6   matrixr   s      r-   r   zContentStreamBuilder.cm  s)    '(8(8(4.ITr,   c                R    t        g t        d            }| j                  |       | S )zBegin text object.

        All text operations must be contained within a text object, and are invalid
        otherwise. The text matrix and font are reset for each text object. Text objects
        may not be nested.
        BTr   r   s     r-   
begin_textzContentStreamBuilder.begin_text  s%     (HTN;Tr,   c                R    t        g t        d            }| j                  |       | S )zEnd text object.ETr   r   s     r-   end_textzContentStreamBuilder.end_text  s#    'HTN;Tr,   c                j    t        |t        |      gt        d            }| j                  |       | S )Begin marked content sequence.)MCIDBDC)r   r   r   r   )r6   mctypemcidr   s       r-   begin_marked_content_proplistz2ContentStreamBuilder.begin_marked_content_proplist  s2    'ZT*+Xe_
 	Tr,   c                T    t        |gt        d            }| j                  |       | S )r   BMCr   )r6   r   r   s      r-   begin_marked_contentz)ContentStreamBuilder.begin_marked_content  s%    '(5/BTr,   c                R    t        g t        d            }| j                  |       | S )zEnd marked content sequence.EMCr   r   s     r-   end_marked_contentz'ContentStreamBuilder.end_marked_content  s#    'HUO<Tr,   c                V    t        ||gt        d            }| j                  |       | S )a  Set text font and size.

        This operator is mandatory in order to show text. Any text object which attempts
        to show text without first calling this operator is invalid.

        The font name must match an entry in the current resources dictionary. The font
        size is expressed in text-space units. Assuming no text scaling is in place, and
        the PDF has not set a user-defined unit in the page dictionary, then text space
        units will be points (defined as 1/72 of an inch).
        Tfr   )r6   fontsizer   s       r-   set_text_fontz"ContentStreamBuilder.set_text_font  s)     (thtnETr,   c                T    t        |gt        d            }| j                  |       | S )ar  Set the character spacing (Tc) for future text operations.

        This is a value, measured in unscaled text-space units, which will be used to
        adjust the spacing between characters. A value of 0 (the default) means that,
        for each rendered glyph, the cursor will advance only the actual width of the
        glyph. Positive values will result in additional space between characters, and
        negative values will cause glyphs to overlap.

        In vertical writing, the sign works opposite of what one might expect: a
        positive value shrinks the space, and a negative value increases it.
        Tcr   r6   r   r   s      r-   set_text_char_spacingz*ContentStreamBuilder.set_text_char_spacing  s'     (?Tr,   c                T    t        |gt        d            }| j                  |       | S )af  Set the word spacing (Tw) for future text operations.

        This is a value, measured in unscaled text-space units, which will be added to
        the width of any ASCII space characters.

        In vertical writing, the sign works opposite of what one might expect: a
        positive value shrinks the space, and a negative value increases it.
        Twr   r   s      r-   set_text_word_spacingz*ContentStreamBuilder.set_text_word_spacing  '     (?Tr,   c                T    t        |gt        d            }| j                  |       | S )zSet the leading value (TL) for future text operations.

        This is the vertical spacing between lines. Specifically, it is defined as the
        distance between the baseline of the previous line to the baseline of the next
        line.
        TLr   r   s      r-   set_text_leadingz%ContentStreamBuilder.set_text_leading#  s'     (?Tr,   c                f    t        |j                  t        d            }| j                  |       | S )a  Set text matrix.

        The text matrix defines the conversion between text-space and page-space, in
        terms of both scaling and translation. If this matrix scales the text, then
        it redefines text-space units as being some scale factor of page-space units.
        Tmr   r   s      r-   set_text_matrixz$ContentStreamBuilder.set_text_matrix.  s+     ((8(8(4.ITr,   c                T    t        |gt        d            }| j                  |       | S )Set text rendering mode.Trr   )r6   moder   s      r-   set_text_renderingz'ContentStreamBuilder.set_text_rendering9  s%    '?Tr,   c                T    t        |gt        d            }| j                  |       | S )Set text horizontal scaling.Tzr   )r6   scaler   s      r-   set_text_horizontal_scalingz0ContentStreamBuilder.set_text_horizontal_scaling?  s%    '$@Tr,   c                z    t        t        t        |      g      gt        d            }| j	                  |       | S )z^Show text.

        The text must be encoded in character codes expected by the font.
        TJ)r   r   r   r   r   r6   encodedr   s      r-   	show_textzContentStreamBuilder.show_textE  s4     (w/@)A(BHTNSTr,   c                t    t        t        d |D              gt        d            }| j                  |       | S )a)  Show text, with manual spacing (kerning) options.

        Arguments are either bytes, which represent the actual text to show, or numbers,
        which move the cursor. The units for the numbers are expressed in thousandths
        of a text-space unit (thus typically equivalent to a glyph-space unit).

        For horizontal writing, positive values move the cursor left, and negative
        right. For vertical writing, positive values move down and negative up.

        The text must be encoded in character codes expected by the font.
        c              3  V   K   | ]!  }t        |t              rt        |      n| # y wr   )rn   rT   r   ).0parts     r-   	<genexpr>z>ContentStreamBuilder.show_text_with_kerning.<locals>.<genexpr>b  s'      JNJtU$;F4LEs   ')r  )r   r   r   r   )r6   partsr   s      r-   show_text_with_kerningz+ContentStreamBuilder.show_text_with_kerningT  sD     ( RW 
 TN
 	Tr,   c                f    t        t        |      gt        d            }| j                  |       | S )a  Advance to the next line and show text.

        The text must be encoded in character codes expected by the font.

        This is functionally equivalent to ``move_cursor_new_line()`` followed by
        ``show_text_string(encoded)``, but in a single operation.
        'r   r   r   r   r  s      r-   show_text_linez#ContentStreamBuilder.show_text_linek  s,     ((98C=ITr,   c                j    t        ||t        |      gt        d            }| j                  |       | S )ac  Advance to the next line and show text.

        The text must be encoded in character codes expected by the font.

        This is functionally equivalent to ``set_text_char_spacing(char_spacing)`` and
        ``set_text_word_spacing()``, followed by ``move_cursor_new_line()`` and then
        ``show_text(encoded)``, all in a single operation.
        "r  )r6   r  r2   r1   r   s        r-   show_text_line_with_spacingz0ContentStreamBuilder.show_text_line_with_spacingw  s5     (<98C=
 	Tr,   c                V    t        ||gt        d            }| j                  |       | S )a  Move cursor by the given offset, relative to the start of the current line.

        This operator modifies the both current text matrix and the text line matrix.
        This means that, in addition to moving the current cursor, the new cursor will
        also be defined as the start of a new line.

        The new position will be redefined as the new start of the line even if the y
        offset is 0; what to a user may look like a single line of text could be encoded
        in the PDF content stream as multiple "lines". It's not uncommon for PDFs to be
        written with every word as a separate "line", allowing the PDF writer to
        explicitly define the spacing between each word.
        Tdr   )r6   dxdyr   s       r-   move_cursorz ContentStreamBuilder.move_cursor  s)     (R(4.ATr,   c                R    t        g t        d            }| j                  |       | S )a  Move cursor to the start of the next line.

        This moves down by the current leading value, and resets the x position back to
        the value it had at the beginning of the current line.

        This operator modifies the both current text matrix and the text line matrix.
        This means that, in addition to moving the current cursor, the new cursor will
        also be defined as the start of a new line.

        The value this operation moves the cursor is set using ``set_text_leading``.
        zT*r   r   s     r-   move_cursor_new_linez)ContentStreamBuilder.move_cursor_new_line  s%     (HTN;Tr,   c                R    t        g t        d            }| j                  |       | S )Stroke and close path.sr   r   s     r-   stroke_and_closez%ContentStreamBuilder.stroke_and_close  r   r,   c                R    t        g t        d            }| j                  |       | S )r(  fr   r   s     r-   fillzContentStreamBuilder.fill  r   r,   c                Z    t        ||||gt        d            }| j                  |       | S )zAppend rectangle to path.rer   )r6   xywhr   s         r-   append_rectanglez%ContentStreamBuilder.append_rectangle  s+    'Aq!htnETr,   c                X    t        |||gt        d            }| j                  |       | S )zSet RGB stroke color.RGr   r6   rgbr   s        r-   set_stroke_colorz%ContentStreamBuilder.set_stroke_color  )    'Aq	8D>BTr,   c                X    t        |||gt        d            }| j                  |       | S )zSet RGB fill color.rgr   r7  s        r-   set_fill_colorz#ContentStreamBuilder.set_fill_color  r<  r,   c                T    t        |gt        d            }| j                  |       | S )Set line width.r2  r   )r6   r   r   s      r-   set_line_widthz#ContentStreamBuilder.set_line_width  s%    '#?Tr,   c                    t        ||gt        d            t        ||gt        d            g}| j                  |d          | j                  |d          | S )z
Draw line.mlr   r!   r   )r6   x1y1x2y2instss         r-   linezContentStreamBuilder.line  sV     %b"Xx}=$b"Xx}=
 	U1XU1Xr,   Nc                    |g }t        |t        t        z        r||f}d}t        ||gt	        d            }| j                  |       | S )Set dashes.r   d)rn   r   r   r   r   r   )r6   arrayphaser   s       r-   
set_dasheszContentStreamBuilder.set_dashes  sM    =EeS5[)ENEE'FTr,   c                T    t        |gt        d            }| j                  |       | S )zDraw XObject.

        Add instructions to render an XObject. The XObject must be
        defined in the document.

        Args:
            name: Name of XObject
        Dor   )r6   rr   r   s      r-   draw_xobjectz!ContentStreamBuilder.draw_xobject  r   r,   c                ,    t        | j                        S )zBuild content stream.)rT   r   rI   s    r-   buildzContentStreamBuilder.build  s    T\\""r,   )r   r   )r   zContentStreamBuilder | bytesr   r   )r   r   r   r   )r   r   )r   r   r   int | float | Decimal)r   rX  )r  r   )r  r   )r  rT   )r  zbytes | int | float | Decimal)r  rT   r2   r   r1   r   )r0  r   r1  r   r2  r   r3  r   )r8  r   r9  r   r:  r   )rF  r   rG  r   rH  r   rI  r   Nr   )rr   r   )rD   rT   )&r%   r&   r'   r(   rh   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r  r  r$  r&  r*  r-  r4  r;  r?  rB  rK  rQ  rT  rV  r+   r,   r-   r   r     s    !#?*	 		.
,/?B"" 	#r,   r   c                  &    e Zd ZU dZded<   ded<   y)LoadedImagezcLoaded image.

    This class is used to track images that have been loaded into a
    canvas.
    r   rr   zImage.ImageimageN)r%   r&   r'   r(   r   r+   r,   r-   r[  r[    s     Jr,   r[  c                      e Zd ZdZdddZddZddZd Zd ZddZ	dd	Z
dd
Zd Zd Zd Zedddd       ZddZy)_CanvasAccessorz;Contains all drawing methods class for drawing on a Canvas.Nc                6    || _         ||ng | _        d| _        y rY  )_cs_images_stack_depth)r6   csimagess      r-   rh   z_CanvasAccessor.__init__  s    !'!3vr,   c                    |j                   |j                  |j                  }}}| j                  j	                  |||       | S )zSet stroke color.)r   r   r   r`  r;  r6   colorr8  r9  r:  s        r-   stroke_colorz_CanvasAccessor.stroke_color  s6    ))U[[%**a1!!!Q*r,   c                    |j                   |j                  |j                  }}}| j                  j	                  |||       | S )zSet fill color.)r   r   r   r`  r?  rf  s        r-   
fill_colorz_CanvasAccessor.fill_color  s6    ))U[[%**a11a(r,   c                <    | j                   j                  |       | S )rA  )r`  rB  )r6   r   s     r-   
line_widthz_CanvasAccessor.line_width  s    &r,   c                v    | j                   j                  ||||       | j                   j                          | S )z"Draw line from (x1,y1) to (x2,y2).)r`  rK  r*  )r6   rF  rG  rH  rI  s        r-   rK  z_CanvasAccessor.line  s-    b"b"%!!#r,   c                    | j                   j                  ||||       |r| j                   j                          | S | j                   j                          | S )zDDraw optionally filled rectangle at (x,y) with width w and height h.)r`  r4  r-  r*  )r6   r0  r1  r2  r3  r-  s         r-   rectz_CanvasAccessor.rect  sH    !!!Q1-HHMMO  HH%%'r,   c           
     ,   | j                  t        |dd|||            5  t        |t        t        z        rddlm}  |j                  |      }|j                          |j                  dk(  r|j                  d      }|j                  dvrt        d|j                         t        j                  d	      }t        ||      }| j                  j!                  |       | j"                  j%                  |       d
d
d
       | S # 1 sw Y   | S xY w)z.Draw image at (x,y) with width w and height h.r   r   r   PRGB)1Lrs  zUnsupported image mode: Im)prefixN)
save_stater   rn   r   rS   PILr   openru   r  convertrg   r   randomr[  ra  r   r`  rT  )	r6   r\  r0  r1  r   heightr   rr   lis	            r-   
draw_imagez_CanvasAccessor.draw_image(  s    __uaFAq A_B 	(%,%"

5)JJLzzS e,zz!22 #;EJJ<!HII;;d+DT5)BLL#HH!!$'	( 	( s   CD		Dc                    | j                   j                  |j                          | j                   j                          | S )zDraw text object.)r`  r   r   rP   s     r-   	draw_textz_CanvasAccessor.draw_text:  s+    !r,   c                8     | j                   j                  |  | S )rM  )r`  rQ  )r6   argss     r-   dashesz_CanvasAccessor.dashes@  s    T"r,   c                d    | j                   j                          | xj                  dz  c_        | S )r   r!   )r`  r   rb  rI   s    r-   r   z_CanvasAccessor.pushE  s%    Qr,   c                d    | j                   j                          | xj                  dz  c_        | S )z$Restore the previous graphics state.r!   )r`  r   rb  rI   s    r-   r   z_CanvasAccessor.popK  s%    Qr,   rq  c             #  z   K   | j                          || j                  |       |  | j                          yw)zSave the graphics state and restore it on exit.

        Optionally, concatenate a transformation matrix. Implements
        the commonly used pattern of:

            q cm ... Q
        N)r   r   r   )r6   r   s     r-   rx  z_CanvasAccessor.save_stateQ  s/      			>GGBK

s   9;c                <    | j                   j                  |       | S )z>Concatenate a new transformation matrix to the current matrix.)r`  r   r6   r   s     r-   r   z_CanvasAccessor.cm`  s    Fr,   r   )rc  r   )rg  r   )r-  bool)r\  zPath | str | Image.Image)r7   Text)r   zMatrix | NonerW  )r%   r&   r'   r(   rh   rh  rj  rl  rK  ro  r  r  r  r   r   r   rx  r   r+   r,   r-   r^  r^     sX    E

$
 04  r,   r^  c                  J    e Zd ZdZd	dZd
dZedd       ZddZddZ	ddZ
y)Canvasa>  Canvas for rendering PDFs with pikepdf.

    All drawing is done on a pikepdf canvas using the ``.do`` property.
    This interface manages the graphics state of the canvas.

    A Canvas can be exported as a single page Pdf using ``.to_pdf``. This Pdf can
    then be merged into other PDFs or written to a file.
    c                  || _         t        j                         | _        | j                  j	                  |      | _        t        t               t                     | j
                  _        t               | _	        g | _
        t        | j                  | j                        | _        | j                  j                          y)zInitialize a canvas.)	page_size)r/   XObjectN)r  r   new_pdfadd_blank_page_pager   	Resourcesr   r`  ra  r^  	_accessordor   )r6   r  s     r-   rh   zCanvas.__init__p  sz    "GGI	YY--	-B
)z|Z\R

')*,(4<<@r,   c                |    |j                  | j                        | j                  j                  j                  |<   y)zAdd a font to the page.N)r>   r  r  r  r/   )r6   resource_namer   s      r-   add_fontzCanvas.add_font{  s)    37==3K

!!-0r,   c                    | j                   S )z,Do operations on the current graphics state.)r  rI   s    r-   r  z	Canvas.do  s     ~~r,   c           
        | j                   j                  |j                  j                         |j                  j                  |j                  j
                  |j                  j                  dv rt        j                  nt        j                  t        j                  t        j                  |j                  j                  dk(  rd      S d      S )N)rt  ru  rt  r!      )WidthHeight
ColorSpacer]   r^   BitsPerComponent)r  make_streamr\  tobytesr   r}  r  r   
DeviceGray	DeviceRGBr  r   )r6   r~  s     r-   _save_imagezCanvas._save_image  s    yy$$HH((..88??#%88==J#>DNNJJ"$((--3"6Q % 

 
	
 => % 

 
	
r,   c                ~   | j                   j                          | j                  j                  dk7  rt        j                  d       | j                  j                  | j                  j                               | j                  _        | j                  D ]>  }| j                  |      | j                  j                  j                  |j                   <   @ t#               }| j                  j%                  |       |j'                  d       t)        j*                  |      }| j                   j-                          |S )z'Render the canvas as a single page PDF.r   zNGraphics state stack is not empty when page saved - rendering may be incorrect)r  r   r  rb  r   r   r  r  r`  rV  r  Contentsra  r  r  r  rr   r   saveseekr   rz  r   )r6   r~  bior   s       r-   to_pdfzCanvas.to_pdf  s    >>&&!+KK- #ii33DHHNN4DE

,, 	IB484D4DR4HDJJ  ((1	Ii		s# 	r,   Nc                B    | j                         j                  ||      S r   )r  _repr_mimebundle_)r6   includeexcludes      r-   r  zCanvas._repr_mimebundle_  s    {{}..w@@r,   )r  ztuple[int | float, int | float])r  r   r   r/   )rD   r^  )r~  r[  )rD   r   )NN)r%   r&   r'   r(   rh   r  rU   r  r  r  r  r+   r,   r-   r  r  f  s6    	L  
(Ar,   r  c                  X    e Zd ZdZej
                  fdZd
dZd ZddZ	ddZ
d Zd Zy	)r  z3Text object for rendering text on a pikepdf canvas.c                d    t               | _        | j                  j                          || _        yr   )r   r`  r   
_direction)r6   	directions     r-   rh   zText.__init__  s#    ')#r,   c                >    | j                   j                  ||       | S )zSet font and size.)r`  r   )r6   r   r   s      r-   r   z	Text.font  s    tT*r,   c                <    | j                   j                  |       | S )r  )r`  r  )r6   r  s     r-   render_modezText.render_mode  s    ##D)r,   c                <    | j                   j                  |       | S )zSet text matrix.)r`  r  r  s     r-   text_transformzText.text_transform  s      (r,   c                   t        |t              rd|j                  d      z   }n|}| j                  t        j
                  k(  r| j                  j                  |       | S | j                  j                  t        j                         | j                  j                  |       | j                  j                          | S )aU  Show text.

        The text must be encoded in character codes expected by the font.
        If a text string is passed, it will be encoded as UTF-16BE.
        Text rendering will not work properly if the font's character
        codes are not consistent with UTF-16BE. This is a rudimentary
        interface. You've been warned.
        s   zutf-16be)rn   rS   rQ   r  r#   r)   r`  r  r   r   ReversedCharsr   )r6   r7   r  s      r-   showz	Text.show  s     dC !DKK
$;;GG??m///HHw'
  HH))$*<*<=HHw'HH'')r,   c                <    | j                   j                  |       | S )r	  )r`  r  )r6   r  s     r-   horiz_scalezText.horiz_scale  s    ,,U3r,   c                >    | j                   j                  ||       | S )zMove cursor.)r`  r$  )r6   r0  r1  s      r-   r$  zText.move_cursor  s    Q"r,   N)r   r   r   r   rW  )r7   rA   )r%   r&   r'   r(   r#   r)   rh   r   r  r  r  r  r$  r+   r,   r-   r  r    s1    =!.!2!2 $


*
r,   r  )r   r   )r   r   rD   dict)@r(   
__future__r   loggingabcr   r   collectionsr   
contextlibr   dataclassesr   decimalr
   enumr   ior   pathlibr   typingr   r   pikepdf._corer   r   r   pikepdf._datar   pikepdf.modelsr   pikepdf.objectsr   r   r   r   r   ry  r   	getLoggerr%   r   r   BLACKWHITEBLUECYANGREEN	DARKGREENMAGENTAREDr#   r/   rG   rW   rb   r   r   r   r[  r^  r  r  r+   r,   r-   <module>r     s  
 #  # " % !     & ? ? . 1 E E g! 	7=>aAqaAqQ1aQ1aaAq!S!Q	
1a
Aq!Q7D 7 3  FAd A:
 
<a3 a3H!8&B# B#J
   c cL@A @AF5 5r,   