o
    e                    @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z	 d dl
mZ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mZmZmZmZmZ ddlmZm Z  dd	l!m"Z" dd
l#m$Z$m%Z%m&Z& ddl'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z. ddl/m0Z0 ddl/m1Z2 ddl/m3Z3 ddl/m4Z5 ddl/m6Z7 ddl/m8Z8m9Z9m:Z:m;Z;m<Z< ddl/m=Z> ddl/m?Z@ ddl/mAZB ddl/mCZD ddl/mEZEmFZF ddlGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQmRZRmSZSmTZTmUZUmVZVmWZWmXZXmYZYmZZZm[Z[ ddlm\Z\m]Z]m^Z^m_Z_m`Z`maZambZb ecedZee9d ZfeFdZgG dd dZhdeeeief eiejee f deUfddZkd eQd!eid"eeelelelf eidf d#emd$emdeYfd%d&ZnG d'd( d(ehZodS ))    N)md5)BufferedReaderBufferedWriterBytesIOFileIO)Path)TracebackType)
AnyCallableDequeDictListOptionalTupleTypeUnioncast   )
PageObject_VirtualList)	PdfReader)_alg33_alg34_alg35)StrByteType
StreamType_get_max_pdf_version_headerb_deprecate_bookmarkdeprecate_with_replacementlogger_warning)AnnotationDictionaryAttributes)CatalogAttributes)CatalogDictionary)Core)EncryptionDictAttributes)FieldDictionaryAttributes	FieldFlag"FileSpecificationDictionaryEntriesGoToActionArgumentsInteractiveFormDictEntries)PageAttributes)PagesAttributes)StreamAttributes)TrailerKeys)TypFitArgumentsUserAccessPermissions)AnnotationBuilderArrayObjectBooleanObjectByteStringObjectContentStreamDecodedStreamObjectDestinationDictionaryObjectFloatObjectIndirectObject
NameObject
NullObjectNumberObject	PdfObjectRectangleObjectStreamObjectTextStringObject
TreeObjectcreate_string_object
hex_to_rgb)BorderArrayTypeFitType
LayoutTypeOutlineItemTypePagemodeTypeZoomArgsTypeZoomArgTypeic                   @   s	  e Zd ZdZddeddfddZddd	Zd
eee	  dee	 dee
 ddfddZedefddZejdeddfddZdee defddZdedefddZdedefddZdedeeegdf ddfddZddd Zdeddfd!d"Zdeddfd#d$Zdded&eddfd'd(Zdded&eddfd)d*Z	dd+ee d,ee defd-d.Zd,edefd/d0Z defd1d2Z!defd3d4Z"ede#e fd5d6Z$	dd7ee% d8ee% defd9d:Z&	dd7ee% d8ee% defd;d<Z'			%dd7ee(j) d8ee(j) d&edefd=d>Z*			%dd7ee(j) d8ee(j) d&edefd?d@Z+dAe,ddfdBdCZ-dAe,ddfdDdEZ.dFe,dGe/e,ef ddfdHdIZ0dJe,dKe/e,ef ddfdLdMZ1	ddNe2dOeeegdf  ddfdPdQZ3	ddNe2dOeeegdf  ddfdRdSZ4e5fdedTe6e,ef dUe7ddfdVdWZ8e5fdedTe6e,ef dUe7ddfdXdYZ9dNe2ddfdZd[Z:dNe2ddfd\d]Z;	ddNe2dOeeegdf  ddfd^d_Z<	ddNe2dOeeegdf  ddfd`daZ=ddbe>fdce,ddee, dee?dfe@ddf
dgdhZAdieBddfdjdkZCdie/eDef deEe?e/eFeGeHeIf f fdldmZJdieBde#e fdndoZKdieBdpe#e defdqdrZLdieBddfdsdtZMdue6e,ef ddfdvdwZNdue6e,ef ddfdxdyZOdze/ePeQeReSeeTeeUeVeWf
 ddfd{d|ZXdGedefd}d~ZYdedefddZZdedefddZ[de\fddZ]de\fddZ^dePfddZ_dePfddZ`	dde/ee\f de/de\ef defddZa	dde/ee\f de/de\ef defddZb	ddedee\ defddZceddd	ddeedee\ defddZfeddd	ddeedee\ defddZgeddd	ddeedee\ defddZh					dde,dede/de\ef dee/eEe%e%e%f e,f  de?de?deidejdefddZk					dde,dede/de\ef deeEe%e%e%f  de?de?deidejdefddZl					dde,dede/de\ef deeEe%e%e%f  de?de?deidejdefddZmdddZndedefddZodedefddZpde,dedefddZqde,dedefddZrdddZsdddZtdde?ddfddZu	dde?ddfddZvdde?ddfddZw	dde?ddfddZx	ddede,deydeeP ddf
ddƄZz	ddede,deydeeP ddf
ddȄZ{		ddededeydeeP deidejddfdd˄Z|		ddededeydeeP deidejddfdd̈́Z}dZ~dee fddЄZdee fdd҄Zde/eTef ddfddՄZdeddfddׄZedee fddلZejdeddfddلZedee fdd܄Zejdeddfdd܄ZdZdee fddZdee fddZdeddfddZdeddfddZedee fddZejdeddfddZedee fddZejdeddfddZd+ede6e,ef ddfddZdS )	PdfWriterz
    This class supports writing PDF files out, given pages produced by another
    class (typically :class:`PdfReader<PyPDF2.PdfReader>`).
     fileobjreturnNc                 C   s   d| _ g | _i | _t }|ttjtdttjt	dttj
t i | || _t }|tdttjdd i | || _t }|ttjttjttj| ji d | _|| _|| _d| _d S )Ns   %PDF-1.3z/Pagesr   z	/ProducerZPyPDF2zutf-16beF)_header_objects_idnum_hashr8   updater;   PATYPECOUNTr=   KIDSr2   _add_object_pagesrC   codecsBOM_UTF16_BEencode_infoCOZCATALOGZPAGES_root_root_objectrN   with_as_usage)selfrN   pagesinforoot rf   >D:\Projects\ConvertPro\env\Lib\site-packages\PyPDF2/_writer.py__init__   s:   
zPdfWriter.__init__c                 C   s
   d| _ | S )z+Store that writer is initialized by 'with'.T)ra   rb   rf   rf   rg   	__enter__   s   zPdfWriter.__enter__exc_typeexc	tracebackc                 C   s   | j r| | j  dS dS )zWrite data to the fileobj.N)rN   write)rb   rk   rl   rm   rf   rf   rg   __exit__   s   zPdfWriter.__exit__c                 C   s   | j S )z
        Header of the PDF document that is written.

        This should be something like b'%PDF-1.5'. It is recommended to set the
        lowest version that supports all features which are used within the
        PDF file.
        rP   ri   rf   rf   rg   
pdf_header   s   	zPdfWriter.pdf_header
new_headerc                 C   s
   || _ d S Nrp   )rb   rr   rf   rf   rg   rq      s   
objc                 C   s   | j | tt| j d| S )Nr   )rQ   appendr:   lenrb   rt   rf   rf   rg   rX      s   zPdfWriter._add_objectidoc                 C   s"   |j | kr	td| j|jd  S )Nzpdf must be selfr   )pdf
ValueErrorrQ   idnumrb   rx   rf   rf   rg   
get_object   s   
zPdfWriter.get_objectc                 C      t dd | |S )zU
        .. deprecated:: 1.28.0

            Use :meth:`get_object` instead.
        	getObjectr}   )r   r}   r|   rf   rf   rg   r         

zPdfWriter.getObjectpageactionc                 C   s   t t|tj tjksJ |jd ur&|jj}t|tr|	 }t
| j|| _| j|ttj< | |}t t| | j}||tj | t t|tj }t|d |ttj< d S )Nr   )r   strrT   rU   r^   ZPAGEry   rq   
isinstancer\   r   rY   r;   PARENTrX   r8   r}   rW   intrV   r=   )rb   r   r   otherZpage_indrc   Z
page_countrf   rf   rg   	_add_page   s   


zPdfWriter._add_pagec              
   C   s   z,| j }tj|vr| j ttjtt| jd| i ttj	}t
d| j tj |< W d S  tyG } ztdt| W Y d }~d S d }~ww )Nr   Tz&set_need_appearances_writer() catch : )r`   r#   Z	ACRO_FORMrS   r;   r:   rv   rQ   r*   ZNeedAppearancesr3   	Exceptionloggererrorrepr)rb   catalogZneed_appearancesrl   rf   rf   rg   set_need_appearances_writer   s   


z%PdfWriter.set_need_appearances_writerc                 C   s   |  |tj dS )a&  
        Add a page to this PDF file.

        The page is usually acquired from a :class:`PdfReader<PyPDF2.PdfReader>`
        instance.

        :param PageObject page: The page to add to the document. Should be
            an instance of :class:`PageObject<PyPDF2._page.PageObject>`
        N)r   listru   rb   r   rf   rf   rg   add_page   s   
zPdfWriter.add_pagec                 C      t dd | | dS )zS
        .. deprecated:: 1.28.0

            Use :meth:`add_page` instead.
        addPager   N)r   r   r   rf   rf   rg   r   	     
zPdfWriter.addPager   indexc                    s   |  | fdd dS )a  
        Insert a page in this PDF file. The page is usually acquired from a
        :class:`PdfReader<PyPDF2.PdfReader>` instance.

        :param PageObject page: The page to add to the document.
        :param int index: Position at which the page will be inserted.
        c                    s   |   |S rs   )insert)lpr   rf   rg   <lambda>  s    z'PdfWriter.insert_page.<locals>.<lambda>N)r   rb   r   r   rf   r   rg   insert_page  s   zPdfWriter.insert_pagec                 C      t dd | || dS )zV
        .. deprecated:: 1.28.0

            Use :meth:`insert_page` instead.
        
insertPager   N)r   r   r   rf   rf   rg   r     s   
zPdfWriter.insertPagepage_number
pageNumberc                 C   sr   |dur|durt dtddd |}|du r |du r t dttttf | | j}tt|t	j
 |  S )z
        Retrieve a page by number from this PDF file.

        :param int page_number: The page number to retrieve
            (pages begin at zero)
        :return: the page at the index given by *page_number*
        Nz)Please only use the page_number parameterzget_page(pageNumber)zget_page(page_number)4.0.0zPlease specify the page_number)rz   r   r   r   r   r	   r}   rY   r   rT   rW   )rb   r   r   rc   rf   rf   rg   get_page%  s   
zPdfWriter.get_pagec                 C   r~   )zd
        .. deprecated:: 1.28.0

            Use :code:`writer.pages[page_number]` instead.
        getPagezwriter.pages[page_number])r   r   )rb   r   rf   rf   rg   r   <  r   zPdfWriter.getPagec                 C   s*   t tttf | | j}t|td S )Nz/Count)r   r   r   r	   r}   rY   r   r;   )rb   rc   rf   rf   rg   _get_num_pagesE  s   zPdfWriter._get_num_pagesc                 C      t dd |  S )z\
        .. deprecated:: 1.28.0

            Use :code:`len(writer.pages)` instead.
        getNumPageszlen(writer.pages))r   r   ri   rf   rf   rg   r   I     
zPdfWriter.getNumPagesc                 C   s   t | j| jS )zNProperty that emulates a list of :class:`PageObject<PyPDF2._page.PageObject>`.)r   r   r   ri   rf   rf   rg   rc   R  s   zPdfWriter.pageswidthheightc                 C   s   t | ||}| | |S )a  
        Append a blank page to this PDF file and returns it. If no page size
        is specified, use the size of the last page.

        :param float width: The width of the new page expressed in default user
            space units.
        :param float height: The height of the new page expressed in default
            user space units.
        :return: the newly appended page
        :raises PageSizeNotDefinedError: if width and height are not defined
            and previous page does not exist.
        )r   create_blank_pager   )rb   r   r   r   rf   rf   rg   add_blank_pageW  s   
zPdfWriter.add_blank_pagec                 C      t dd | ||S )zY
        .. deprecated:: 1.28.0

            Use :meth:`add_blank_page` instead.
        addBlankPager   )r   r   )rb   r   r   rf   rf   rg   r   j     
zPdfWriter.addBlankPagec                 C   sX   |du s|du r|   d |kr| j| }|jj}|jj}t| ||}| || |S )a8  
        Insert a blank page to this PDF file and returns it. If no page size
        is specified, use the size of the last page.

        :param float width: The width of the new page expressed in default user
            space units.
        :param float height: The height of the new page expressed in default
            user space units.
        :param int index: Position to add the page.
        :return: the newly appended page
        :raises PageSizeNotDefinedError: if width and height are not defined
            and previous page does not exist.
        Nr   )r   rc   Zmediaboxr   r   r   r   r   )rb   r   r   r   Zoldpager   rf   rf   rg   insert_blank_pageu  s    
zPdfWriter.insert_blank_pagec                 C      t dd | |||S )zZ
        .. deprecated:: 1.28.0

            Use :meth:`insertBlankPage` instead.
        insertBlankPager   )r   r   )rb   r   r   r   rf   rf   rg   r     s   
zPdfWriter.insertBlankPage
javascriptc                 C   s   t  }|ttjtdtdtdtdtd| di | |}tt }t  }|tdt tt	j
tt||gii | | | jtd|tt	j
|i dS )	a  
        Add Javascript which will launch upon opening this PDF.

        :param str javascript: Your Javascript.

        >>> output.add_js("this.print({bUI:true,bSilent:false,bShrinkToFit:true});")
        # Example: This will launch the print window when the PDF is opened.
        z/Action/Sz/JavaScriptz/JS()z/OpenActionN)r8   rS   r;   rT   rU   rX   r   uuiduuid4CANAMESr2   rC   r`   )rb   r   jsZjs_indirect_objectZjs_string_nameZjs_name_treerf   rf   rg   add_js  s2   	




zPdfWriter.add_jsc                 C   r~   )zQ
        .. deprecated:: 1.28.0

            Use :meth:`add_js` instead.
        addJSr   )r   r   )rb   r   rf   rf   rg   r     r   zPdfWriter.addJSfilenamedatac                 C   s   t  }|| |ttjtdi t }|td|i t }|ttjtdttjt	|ttj
|i t }|ttjtt	||gi t }|td|i | jttj|i dS )a  
        Embed a file inside the PDF.

        :param str filename: The filename to display.
        :param str data: The data in the file.

        Reference:
        https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf
        Section 7.11.3
        z/EmbeddedFile/Fz	/Filespecz/EmbeddedFilesN)r6   set_datarS   r;   rT   rU   r8   r(   FrC   ZEFr   r   r2   r`   )rb   r   r   Z
file_entryZef_entryZfilespecZembedded_files_names_dictionaryZembedded_files_dictionaryrf   rf   rg   add_attachment  s4   





zPdfWriter.add_attachmentfnamefdatac                 C   r   )zY
        .. deprecated:: 1.28.0

            Use :meth:`add_attachment` instead.
        addAttachmentr   )r   r   )rb   r   r   rf   rf   rg   r   $  r   zPdfWriter.addAttachmentreaderafter_page_appendc                 C   sX   t |j}t | j}t|D ]}|j| }| | | j||  }t|r)|| qdS )a  
        Copy pages from reader to writer. Includes an optional callback parameter
        which is invoked after pages are appended to the writer.

        :param PdfReader reader: a PdfReader object from which to copy page
            annotations to this writer object.  The writer's annots
            will then be updated
        :param Callable[[PageObject], None] after_page_append:
            Callback function that is invoked after each page is appended to
            the writer. Signature includes a reference to the appended page
            (delegates to append_pages_from_reader). The single parameter of the
            callback is a reference to the page just appended to the document.
        N)rv   rc   ranger   callable)rb   r   r   Zreader_num_pagesZwriter_num_pagesZrpagenumZreader_pageZwriter_pagerf   rf   rg   append_pages_from_reader/  s   



z"PdfWriter.append_pages_from_readerc                 C   r   )zc
        .. deprecated:: 1.28.0

            Use :meth:`append_pages_from_reader` instead.
        appendPagesFromReaderr   N)r   r   rb   r   r   rf   rf   rg   r   N  s   

zPdfWriter.appendPagesFromReaderfieldsflagsc                 C   s  |    tj|vrtdt dS tt|tj D ]m}|tj |  }i }tj|v r0|tj }|D ]S}|	t
j|kro|	t
jdkrR|ttjt|| i |tt
jt|| i |rn|tt
jt|i q2|	t
j|kr|tt
jt|| i q2qdS )a  
        Update the form field values for a given page from a fields dictionary.

        Copy field texts and values from fields to page.
        If the field links to a parent object, add the information to the parent.

        :param PageObject page: Page reference from PDF writer where the
            annotations and field data will be updated.
        :param dict fields: a Python dictionary of field names (/T) and text
            values (/V)
        :param int flags: An integer (0 to 7). The first bit sets ReadOnly, the
            second bit sets Required, the third bit sets NoExport. See
            PDF Reference Table 8.70 for details.
        z No fields to update on this pageNz/Btn)r   PGANNOTSr    __name__r   rv   r}   r   getr&   TZFTrS   r;   r!   ZASVrA   ZFfr=   )rb   r   r   r   jZwriter_annotZwriter_parent_annotfieldrf   rf   rg   update_page_form_field_values[  sV   







z'PdfWriter.update_page_form_field_valuesc                 C   r   )zh
        .. deprecated:: 1.28.0

            Use :meth:`update_page_form_field_values` instead.
        updatePageFormFieldValuesr   )r   r   )rb   r   r   r   rf   rf   rg   r     s   z#PdfWriter.updatePageFormFieldValuesc                 C   s   t t|jtj | _dS )z
        Copy the reader document root to the writer.

        :param reader:  PdfReader from the document root should be copied.
        N)r   r8   trailerTKROOTr`   rb   r   rf   rf   rg   clone_reader_document_root  s   z$PdfWriter.clone_reader_document_rootc                 C   r   )ze
        .. deprecated:: 1.28.0

            Use :meth:`clone_reader_document_root` instead.
        cloneReaderDocumentRootr   N)r   r   r   rf   rf   rg   r     s   z!PdfWriter.cloneReaderDocumentRootc                 C   s   |  | | || dS )a)  
        Create a copy (clone) of a document from a PDF file reader

        :param reader: PDF file reader instance from which the clone
            should be created.
        :param Callable[[PageObject], None] after_page_append:
            Callback function that is invoked after each page is appended to
            the writer. Signature includes a reference to the appended page
            (delegates to append_pages_from_reader). The single parameter of the
            callback is a reference to the page just appended to the document.
        N)r   r   r   rf   rf   rg   clone_document_from_reader  s   
z$PdfWriter.clone_document_from_readerc                 C   r   )ze
        .. deprecated:: 1.28.0

            Use :meth:`clone_document_from_reader` instead.
        cloneDocumentFromReaderr   N)r   r   r   rf   rf   rg   r     s   
z!PdfWriter.cloneDocumentFromReaderTuser_pwd	owner_pwd
use_128bitpermissions_flagc                 C   sv  |du r|}|rd}d}t d}nd}d}t d}|}tt||||}	tttt d }
tttt d }t	|
|f| _
|dkrWt||	||
\}}n|dks]J t||||	||
d\}}t }td	|ttj< t||td
< |dkrt|d |ttj< t||ttj< t|	|ttj< t||ttj< t||ttj< | || _|| _dS )a  
        Encrypt this PDF file with the PDF Standard encryption handler.

        :param str user_pwd: The "user password", which allows for opening
            and reading the PDF file with the restrictions provided.
        :param str owner_pwd: The "owner password", which allows for
            opening the PDF files without any restrictions.  By default,
            the owner password is the same as the user password.
        :param bool use_128bit: flag as to whether to use 128bit
            encryption.  When false, 40bit encryption will be used.  By default,
            this flag is on.
        :param unsigned int permissions_flag: permissions as described in
            TABLE 3.20 of the PDF 1.7 specification. A bit value of 1 means the
            permission is grantend. Hence an integer value of -1 will set all
            flags.
            Bit position 3 is for printing, 4 is for modifying content, 5 and 6
            control annotations, 9 for form fields, 10 for extraction of
            text and graphics.
        N      g      0@r   g      @utf8Fz	/Standardz/V   )r   r4   r   r   r   timer\   digestrandomr2   _IDr   r   r8   r;   SAZFILTERr=   ZLENGTHEDROUPrX   _encrypt_encrypt_key)rb   r   r   r   r   r   revZkeylenr   r   ZID_1ZID_2r   keyencryptrf   rf   rg   r     s:   

zPdfWriter.encryptstreamc                 C   s   t |drd|jvrtd|j dt | js| | j| _| | j | 	|}| 
||}| | |td| d d S )NmodebzFile <zH> to write to is not in binary mode. It may not be written to correctly.z
startxref
z
%%EOF
)hasattrr   r    namer   r_   rX   r`   _sweep_indirect_references_write_header_write_xref_table_write_trailerrn   r   )rb   r   object_positionsxref_locationrf   rf   rg   write_stream  s   


zPdfWriter.write_streamc                 C   sX   d}|dkrt d| dt|ttfrt|d}d}| | | jr(|  ||fS )ae  
        Write the collection of pages added to this object out as a PDF file.

        :param stream: An object to write the file to.  The object can support
            the write method and the tell method, similar to a file object, or
            be a file path, just like the fileobj, just named it stream to keep
            existing workflow.
        FrM   zOutput(stream=z) is empty.wbT)rz   r   r   r   r   r  ra   close)rb   r   Zmy_filerf   rf   rg   rn   5  s   

zPdfWriter.writec           
      C   s   g }| | jd  | d t| jD ]y\}}| j| }|d ur|d }||  | tt|d  d }t| dr|| j	j
krtd|d d d }tddd d	 }| j| | }t|t| jd
 ksnJ t| }	|	d tdt| jd
  }||| | d q|S )N   
s   %
r   s    0 obj
r   z<ir   r   r         s   
endobj
)rn   rq   	enumeraterQ   ru   tellr   r   r   r   r{   structpackr   rv   r   r   minwrite_to_stream)
rb   r   r  irt   r{   r   Zpack1Zpack2Zmd5_hashrf   rf   rg   r   P  s*   


zPdfWriter._write_headerr  c                 C   s|   |  }|d |tdt| jd  d |tddddd	d
 |D ]}|t|dddd	d q*|S )Ns   xref
z0 r   
r   z0>10 i  z0>5z f 
z n 
)r
  rn   r   rv   rQ   )rb   r   r  r  offsetrf   rf   rg   r   g  s   
  zPdfWriter._write_xref_tablec                 C   s   | d t }|ttjtt| jd ttj	| j
ttj| ji t| dr2| j|ttj< t| dr?| j|ttj< ||d  d S )Ns   trailer
r   r   r   )rn   r8   rS   r;   r   SIZEr=   rv   rQ   r   r_   INFOr]   r   r   IDr   ZENCRYPTr  )rb   r   r   rf   rf   rg   r   p  s   


zPdfWriter._write_trailerinfosc                 C   s@   i }t | D ]\}}t||t|< q| | j| dS )z
        Add custom metadata to the output.

        :param dict infos: a Python dictionary where each key is a field
            and each value is your new metadata.
        N)r   itemsrC   r;   r}   r]   rS   )rb   r  argsr   valuerf   rf   rg   add_metadata  s   zPdfWriter.add_metadatac                 C   r   )zW
        .. deprecated:: 1.28.0

            Use :meth:`add_metadata` instead.
        addMetadatar  N)r   r  )rb   r  rf   rf   rg   r    r   zPdfWriter.addMetadatare   c                 C   sr  t  }g }d }g }d }|||||f t|r| \}}}}t|ttfrD| D ]\}}	||	|||d ur>||g ng f q,n"t|t	rf| 
|}t||vrf|t| || d d g f t|ttfrt|trz| 
| |}g }
|| |kr| gdd |D  }
|||< |
D ]}| j|d }|d ur| }|d ur|| j| < qt|sd S d S )Nc                 S   s   g | ]}|  qS rf   )
hash_value).0Zgrant_parentrf   rf   rg   
<listcomp>  s    z8PdfWriter._sweep_indirect_references.<locals>.<listcomp>)collectionsdequeru   rv   popr   r2   r8   r  r:   _resolve_indirect_objectr   r}   r@   rX   r  rR   )rb   re   stackZ
discoveredparentZgrant_parentsZ	key_or_idr   r   r  Zupdate_hashesZold_hashZindirect_refZindirect_ref_objrf   rf   rg   r     sX   
	

z$PdfWriter._sweep_indirect_referencesc                 C   s   t |jdr|jjjrtd|jjj |j|}|du r0td|jj	 d| dt	 t
 }| }|| jv r>| j| S |j| krNt|jd| | j|< n| || j|< | j| S )z
        Resolves indirect object to this pdf indirect objects.

        If it is a new object then it is added to self._objects
        and new idnum is given and generation is always 0.
        r   zI/O operation on closed file: NzUnable to resolve [z: z], returning NullObject insteadr   )r   ry   r   closedrz   r   r}   r    	__class__r   r<   r  rR   r:   r{   rX   )rb   r   Zreal_objr  rf   rf   rg   r"    s    



z"PdfWriter._resolve_indirect_objectc                 C   s0   | j |d }t|d| }| |ksJ |S Nr   r   )rQ   r   r:   r}   )rb   rt   r{   refrf   rf   rg   get_reference  s   zPdfWriter.get_referencec                 C   r~   )zX
        .. deprecated:: 1.28.0

            Use :meth:`get_reference` instead.
        getReferencer)  )r   r)  rw   rf   rf   rg   r*    r   zPdfWriter.getReferencec                 C   s|   t j| jv r'tt| jt j }| j|d }t|d| }| |ks%J |S t }|	i  | 
|}|| jtt j< |S r'  )r^   ZOUTLINESr`   r   rB   rQ   r   r:   r}   rS   rX   r;   )rb   outliner{   Zoutline_refrf   rf   rg   get_outline_root  s   

zPdfWriter.get_outline_rootc                 C   r   )z[
        .. deprecated:: 1.28.0

            Use :meth:`get_outline_root` instead.
        getOutlineRootr,  )r   r,  ri   rf   rf   rg   r-  &  r   zPdfWriter.getOutlineRootc                 C   st  t j| jv rt| jt j trtt| jt j }| j|d }t|d| }|	 |ks.J t j
|v rtt|t j
 trttt|t j
 }| j|d }t|d| }|	 |ksYJ t j|v rhtt|t j }|S t }||tt j< |S t }| |}||tt j
< t }||tt j< |S t }| |}|| jtt j< t }| |}||tt j
< t }||tt j< |S r'  )r   r   r`   r   r8   r   rQ   r   r:   r}   ZDESTSr2   r;   rX   )rb   namesr{   Z	names_refZdestsZ	dests_refndrf   rf   rg   get_named_dest_root/  sB   



zPdfWriter.get_named_dest_rootc                 C   r   )z^
        .. deprecated:: 1.28.0

            Use :meth:`get_named_dest_root` instead.
        getNamedDestRootr0  )r   r0  ri   rf   rf   rg   r1  V  r   zPdfWriter.getNamedDestRootdestr$  c                 C   s8   |d u r|   }tt| }| |}|||  |S rs   )r,  r   rB   r}   rX   Z	add_child)rb   r2  r$  dest_refrf   rf   rg   add_outline_item_destination_  s   
z&PdfWriter.add_outline_item_destinationc                 C   r   )zf
        .. deprecated:: 2.9.0

            Use :meth:`add_outline_item_destination` instead.
        add_bookmark_destinationr4  r   r4  rb   r2  r$  rf   rf   rg   r5  m  s   
z"PdfWriter.add_bookmark_destinationc                 C   r   )zg
        .. deprecated:: 1.28.0

            Use :meth:`add_outline_item_destination` instead.
        addBookmarkDestinationr4  r6  r7  rf   rf   rg   r8  |  s   z PdfWriter.addBookmarkDestinationoutline_item)bookmarkc           	      C   s   t  }t| D ]\}}||tt|< q	|| d|v rGt }tt|d }t| D ]\}}||tt|< q/| |}||td< | 	||S )N/A)
rB   r   r  r;   r   rS   r8   r   rX   r4  )	rb   r9  r$  Zoutline_item_objectkvr   Za_dict
action_refrf   rf   rg   add_outline_item_dict  s   

zPdfWriter.add_outline_item_dictc                 C   r   )z_
        .. deprecated:: 2.9.0

            Use :meth:`add_outline_item_dict` instead.
        add_bookmark_dictr?  r   r?  rb   r9  r$  rf   rf   rg   r@       
	zPdfWriter.add_bookmark_dictc                 C   r   )z`
        .. deprecated:: 1.28.0

            Use :meth:`add_outline_item_dict` instead.
        addBookmarkDictr?  rA  rB  rf   rf   rg   rD    rC  zPdfWriter.addBookmarkDictF/Fittitlepagenumcolorbolditalicfitr  c                 G   s   t |}	dd |D }
ttd| d |	t|g|
R  }| tttj|jttjtdi}t	|||||}|du rA| 
 }| ||S )a  
        Add an outline item (commonly referred to as a "Bookmark") to this PDF file.

        :param str title: Title to use for this outline item.
        :param int pagenum: Page number this outline item will point to.
        :param parent: A reference to a parent outline item to create nested
            outline items.
        :param tuple color: Color of the outline item's font as a red, green, blue tuple
            from 0.0 to 1.0 or as a Hex String (#RRGGBB)
        :param bool bold: Outline item font is bold
        :param bool italic: Outline item font is italic
        :param str fit: The fit of the destination page. See
            :meth:`add_link()<add_link>` for details.
        c                 S   s"   g | ]}|d u rt  nt|qS rs   )r<   r=   )r  arf   rf   rg   r    s    z.PdfWriter.add_outline_item.<locals>.<listcomp>/z outline item/GoToN)r=   r7   r;   rX   r8   r)   D
dest_arrayS_create_outline_itemr,  r4  )rb   rF  rG  r$  rH  rI  rJ  rK  r  page_refZ	zoom_argsr2  r>  r9  rf   rf   rg   add_outline_item  s,   zPdfWriter.add_outline_itemc           	      G   (   t dd | j|||||||g|R  S )zZ
        .. deprecated:: 2.9.0

            Use :meth:`add_outline_item` instead.
        add_bookmarkrT  r   rT  	rb   rF  rG  r$  rH  rI  rJ  rK  r  rf   rf   rg   rV       
zPdfWriter.add_bookmarkc           	      G   rU  )z[
        .. deprecated:: 1.28.0

            Use :meth:`add_outline_item` instead.
        addBookmarkrT  rW  rX  rf   rf   rg   rZ    rY  zPdfWriter.addBookmarkc                 C   s   t d)NzIThis method is not yet implemented. Use :meth:`add_outline_item` instead.)NotImplementedErrorri   rf   rf   rg   add_outline  s   zPdfWriter.add_outlinec                 C   s(   |  |}|  }||d |g |S )N/Title)rX   r0  extend)rb   r2  r3  r/  rf   rf   rg   add_named_destination_object  s   
z&PdfWriter.add_named_destination_objectc                 C   r~   )zg
        .. deprecated:: 1.28.0

            Use :meth:`add_named_destination_object` instead.
        addNamedDestinationObjectr_  )r   r_  )rb   r2  rf   rf   rg   r`    s   
z#PdfWriter.addNamedDestinationObjectc                 C   sv   |  | jtj | }t }|ttjt	|tt
jtdgttjtdi | |}|  }|||g |S )Ni:  rN  )r}   rY   rT   rW   r8   rS   r;   r)   rO  r2   r/   ZFIT_Hr=   rQ  rX   r0  r^  )rb   rF  rG  rS  r2  r3  r/  rf   rf   rg   add_named_destination)  s   

	zPdfWriter.add_named_destinationc                 C   r   )z`
        .. deprecated:: 1.28.0

            Use :meth:`add_named_destination` instead.
        addNamedDestinationra  )r   ra  )rb   rF  rG  rf   rf   rg   rb  :  r   zPdfWriter.addNamedDestinationc                 C   sR   t t| | j}t t|tj }|D ]}t t| |}tj|v r&|tj= qdS )z.Remove links and annotations from this output.N)	r   r8   r}   rY   r2   rT   rW   r   r   )rb   pg_dictrc   r   rS  rf   rf   rg   remove_linksE  s   
zPdfWriter.remove_linksc                 C   r   )zW
        .. deprecated:: 1.28.0

            Use :meth:`remove_links` instead.
        removeLinksrd  )r   rd  ri   rf   rf   rg   re  N  r   zPdfWriter.removeLinksignore_byte_string_objectc                 C   sf  t t| | j}t t|tj }d}|D ]}t t| |}|d  }t|ts/t||}g }d}	|j	D ]n\}
}|dv rO|
d }|rNt|t
sNt
 |
d< n6|dkrd|
d }|rct|t
sct
 |
d< n!|dkrtt|
d D ]}|rt|
d | t
st
 |
d |< qp|d	krd
}	|dkrd}	|	r||v rq6|dkrq6||
|f q6||_	|td| qdS )z
        Remove images from this output.

        :param bool ignore_byte_string_object: optional parameter
            to ignore ByteString Objects.
        )s   cm   w   J   j   M   ds   ri   is   gs   W   b   s   S   f   F   n   m   l   c   v   y   h   Bs   Dos   sh	/ContentsFs   Tj   'r      "r      TJ   qT   Qs   reN)r   r8   r}   rY   r2   rT   rW   r   r5   
operationsrA   r   rv   ru   __setitem__r;   )rb   rf  rc  rc   Zjump_operatorsr   rS  contentZ_operationsZseq_graphicsoperandsoperatortextr  rf   rf   rg   remove_imagesW  sX   



zPdfWriter.remove_imagesignoreByteStringObjectc                 C   r~   )zX
        .. deprecated:: 1.28.0

            Use :meth:`remove_images` instead.
        removeImagesr  )r   r  rb   r  rf   rf   rg   r       

zPdfWriter.removeImagesc                 C   st  t t| | j}t tt |tj }|D ]}t t| |}|d  }t	|t
s/t
||}|jD ]|\}}|dv rX|d }	|sKt	|	trJt |d< q2t	|	ttfrWt |d< q2|dkrz|d }	|smt	|	trlt |d< q2t	|	ttfryt |d< q2|dkrtt|d D ]'}
|st	|d |
 trt |d |
< qt	|d |
 ttfrt |d |
< qq2|td| qdS )z
        Remove text from this output.

        :param bool ignore_byte_string_object: optional parameter
            to ignore ByteString Objects.
        r{  r|  r   r~  r   r  N)r   r8   r}   rY   r   r:   rT   rW   r   r   r5   r  rA   r4   r   rv   r  r;   )rb   rf  rc  rc   r   rS  r  r  r  r  r  rf   rf   rg   remove_text  sN   







zPdfWriter.remove_textc                 C   r~   )zV
        .. deprecated:: 1.28.0

            Use :meth:`remove_text` instead.
        
removeTextr  )r   r  r  rf   rf   rg   r    r  zPdfWriter.removeTexturirectborderc                 C   s|  |  | jtj | }ttttf |  |}|dur=dd |dd D }t|dkr<t	dd |d D }|
| ntdgd }t|trNt|}n
t|trTnt|}t }	|	tdtd	td	t|i t }
|
ttjttjttjtd
ttj|ttj|tdtdttjt	|td|	i | |
}tj|v r|tj 
| dS t	|g|ttj< dS )a  
        Add an URI from a rectangular area to the specified page.
        This uses the basic structure of :meth:`add_link`

        :param int pagenum: index of the page on which to place the URI action.
        :param str uri: URI of resource to link to.
        :param Tuple[int, int, int, int] rect: :class:`RectangleObject<PyPDF2.generic.RectangleObject>` or array of four
            integers specifying the clickable rectangular area
            ``[xLL, yLL, xUR, yUR]``, or string in the form ``"[ xLL yLL xUR yUR ]"``.
        :param ArrayObject border: if provided, an array describing border-drawing
            properties. See the PDF spec for details. No border will be
            drawn if this argument is omitted.
        Nc                 S      g | ]}t |qS rf   r;   r  nrf   rf   rg   r        z%PdfWriter.add_uri.<locals>.<listcomp>r      c                 S   r  rf   r  r  rf   rf   rg   r    r  r   r   z/URI/Linkz/Hz/Ir;  )r}   rY   rT   rW   r   r   r   r	   rv   r2   ru   r=   r   r;   r?   r8   rS   rA   r!   r   r   r   ZSubtyper   ZRectZBorderrX   )rb   rG  r  r  r  Z	page_linkrS  Z
border_arrZdash_patternZlnk2ZlnkZlnk_refrf   rf   rg   add_uri  sJ   








zPdfWriter.add_uric                 C   s   t dd | ||||S )zR
        .. deprecated:: 1.28.0

            Use :meth:`add_uri` instead.
        addURIr  )r   r  )rb   rG  r  r  r  rf   rf   rg   r  )  s   
zPdfWriter.addURIpagedestc                 G   st   t dd t|tr| dd }tdd |dD }n
t|tr%nt|}tj|||||d}| j||d	S )
Nadd_link+add_annotation(AnnotationBuilder.link(...))r   c                 S   s    g | ]}t |d krt|qS r   )rv   float)r  numrf   rf   rg   r  H       z&PdfWriter.add_link.<locals>.<listcomp>r  )r  r  target_page_indexrK  fit_args)r   
annotation)	r   r   r   stripr?   splitr1   linkadd_annotation)rb   rG  r  r  r  rK  r  r  rf   rf   rg   r  8  s&   	

zPdfWriter.add_linkc                 G   s&   t ddd | j|||||g|R  S )zS
        .. deprecated:: 1.28.0

            Use :meth:`add_link` instead.
        addLinkr  r   )r   r  )rb   rG  r  r  r  rK  r  rf   rf   rg   r  X  s   zPdfWriter.addLink)z	/NoLayoutz/SinglePagez
/OneColumnz/TwoColumnLeftz/TwoColumnRightz/TwoPageLeftz/TwoPageRightc                 C   (   z	t t| jd W S  ty   Y d S w )N/PageLayout)r   rG   r`   KeyErrorri   rf   rf   rg   _get_page_layoutu  
   zPdfWriter._get_page_layoutc                 C   r   )Y
        .. deprecated:: 1.28.0

            Use :py:attr:`page_layout` instead.
        getPageLayoutpage_layout)r   r  ri   rf   rf   rg   r  {  r   zPdfWriter.getPageLayoutlayoutc                 C   sP   t |ts|| jvrtddd| jf t t|}| jtd|i dS )a  
        Set the page layout.

        :param str layout: The page layout to be used.

        .. list-table:: Valid ``layout`` arguments
           :widths: 50 200

           * - /NoLayout
             - Layout explicitly not specified
           * - /SinglePage
             - Show one page at a time
           * - /OneColumn
             - Show one column at a time
           * - /TwoColumnLeft
             - Show pages in two columns, odd-numbered pages on the left
           * - /TwoColumnRight
             - Show pages in two columns, odd-numbered pages on the right
           * - /TwoPageLeft
             - Show two pages at a time, odd-numbered pages on the left
           * - /TwoPageRight
             - Show two pages at a time, odd-numbered pages on the right
        zLayout should be one of: rM   r  N)r   r;   _valid_layoutsr    joinr   r`   rS   rb   r  rf   rf   rg   _set_page_layout  s   

zPdfWriter._set_page_layoutc                 C   r~   )r  zwriter.setPageLayout(val)zwriter.page_layout = val)r   r  r  rf   rf   rg   setPageLayout  s   
zPdfWriter.setPageLayoutc                 C      |   S )a  
        Page layout property.

        .. list-table:: Valid ``layout`` values
           :widths: 50 200

           * - /NoLayout
             - Layout explicitly not specified
           * - /SinglePage
             - Show one page at a time
           * - /OneColumn
             - Show one column at a time
           * - /TwoColumnLeft
             - Show pages in two columns, odd-numbered pages on the left
           * - /TwoColumnRight
             - Show pages in two columns, odd-numbered pages on the right
           * - /TwoPageLeft
             - Show two pages at a time, odd-numbered pages on the left
           * - /TwoPageRight
             - Show two pages at a time, odd-numbered pages on the right
        )r  ri   rf   rf   rg   r    s   zPdfWriter.page_layoutc                 C      |  | d S rs   )r  r  rf   rf   rg   r       c                 C      t dd | jS )r  
pageLayoutr  r   r  ri   rf   rf   rg   r       
zPdfWriter.pageLayoutc                 C      t dd || _dS )r  r  r  Nr  r  rf   rf   rg   r       

)z/UseNonez/UseOutlinesz
/UseThumbsz/FullScreenz/UseOCz/UseAttachmentsc                 C   r  )N	/PageMode)r   rI   r`   r  ri   rf   rf   rg   _get_page_mode  r  zPdfWriter._get_page_modec                 C   r   )W
        .. deprecated:: 1.28.0

            Use :py:attr:`page_mode` instead.
        getPageMode	page_mode)r   r  ri   rf   rf   rg   r    r   zPdfWriter.getPageModer   c                 C   sR   t |tr|}n|| jvrtdd| j t t|}| jtd|i dS )r  zMode should be one of: z, r  N)r   r;   _valid_modesr    r  r   r`   rS   )rb   r   Z	mode_namerf   rf   rg   set_page_mode  s   

zPdfWriter.set_page_modec                 C   r   )r  zwriter.setPageMode(val)zwriter.page_mode = valN)r   r  rb   r   rf   rf   rg   setPageMode	  r   zPdfWriter.setPageModec                 C   r  )a  
        Page mode property.

        .. list-table:: Valid ``mode`` values
           :widths: 50 200

           * - /UseNone
             - Do not show outline or thumbnails panels
           * - /UseOutlines
             - Show outline (aka bookmarks) panel
           * - /UseThumbs
             - Show page thumbnails panel
           * - /FullScreen
             - Fullscreen view
           * - /UseOC
             - Show Optional Content Group (OCG) panel
           * - /UseAttachments
             - Show attachments panel
        )r  ri   rf   rf   rg   r    s   zPdfWriter.page_modec                 C   r  rs   )r  r  rf   rf   rg   r  )  r  c                 C   r  )r  pageModer  r   r  ri   rf   rf   rg   r  -  r  zPdfWriter.pageModec                 C   r  )r  r  r  Nr  r  rf   rf   rg   r  7  r  r  c                 C   s   t tt|}| | jd | |td< | j| }|jd u r&t |td< |jd us-J |	ddkr\td|v r\t t
|td }ttd|d |d	 g|d
 R  }|j|td< | |}|j| d S )Nz/Kidsz/Pz/Annotsz/Subtyper  z/Destz	/LinkNamer  rK  r  )r   r8   _pdf_objectifyr}   rY   r;   rc   annotationsr2   r   dictr7   rP  rX   ru   )rb   r   r  to_addr   tmpr2  Zind_objrf   rf   rg   r  A  s$   


zPdfWriter.add_annotation)rM   )rO   rL   )rO   Nr  )NN)NNr   rs   )NNFFrE  )F)NrE  )r   
__module____qualname____doc__r   rh   rj   r   r   BaseExceptionr   ro   propertybytesrq   setterr>   r:   rX   r}   r   r   r
   r	   r   r   r   r   r   r   r   r   r   r   r   r   rc   r  r   r   decimalDecimalr   r   r   r   r   r   r   r   r   r   r   OPTIONAL_READ_WRITE_FIELDr   r'   r   r   r   r   r   r   ALL_DOCUMENT_PERMISSIONSboolr0   r   r   r  r   r   r   r   r   r   rn   r   r   r   r  r  r2   r3   r8   r9   r;   r=   rA   r<   r   r"  r)  r*  rB   r,  r-  r0  r1  r4  r5  r8  r   rH   r?  r@  rD  rF   rK   rT  rV  rZ  r\  r_  r`  ra  rb  rd  re  r  r  r  r  r?   r  r  r  r  r  rG   r  r  r  r  r  r  r  rI   r  r  r  r  r  r  r  rf   rf   rf   rg   rL   {   sj   
(



	

	


		



+	R


"


E




:

		
P#		'




	

6	

	






		N
-

H

%

	!						"	rL   rt   rO   c                 C   s   t | tr| S t | tr&t }|  D ]\}}t|}t|}|||< q|S t | tr<t }| D ]	}|	t| q0|S t | t
rN| drJt| S t| S t | ttfrYt| S tdt|  d)NrM  z
type(obj)=z! could not be casted to PdfObject)r   r>   r  r8   r  r;   r  r   r2   ru   r   
startswithrA   r   r  r9   r[  type)rt   r  r   r  Zname_keyZcasted_valueZarrelrf   rf   rg   r  Z  s.   





r  r>  rF  rH  rJ  rI  c                    s   t  }|td| tdt|i |r4t|trt|}td |tdt	 fdd|D i |s8|rQd}|r@|d7 }|rF|d	7 }|td
t
|i |S )Nr;  r]  z1.00000z/Cc                    s    g | ]}t t| qS rf   )r9   r  r  quantize)r  cprecrf   rg   r    r  z(_create_outline_item.<locals>.<listcomp>r   r   r   r   )rB   rS   r;   rC   r   r   rD   r  r  r2   r=   )r>  rF  rH  rJ  rI  r9  Zformat_flagrf   r  rg   rR  v  s0   

rR  c                       s*   e Zd Zdededdf fddZ  ZS )PdfFileWriterr  kwargsrO   Nc                    s    t dd t j|i | d S )Nr  rL   )r   superrh   )rb   r  r  r&  rf   rg   rh     s   
zPdfFileWriter.__init__)r   r  r  r	   rh   __classcell__rf   rf   r  rg   r    s    "r  )prZ   r  r  loggingr   r  r   r   hashlibr   ior   r   r   r   pathlibr   typesr   typingr	   r
   r   r   r   r   r   r   r   r   Z_pager   r   _readerr   Z	_securityr   r   r   _utilsr   r   r   r   r   r   r    	constantsr!   r"   r   r#   r$   r^   r%   r   r&   r'   r(   r)   r*   r+   r   r,   rT   r-   r   r.   r   r/   r0   Zgenericr1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rK   	getLoggerr   r   r  r  rL   r   r   r  r  r  rR  r  rf   rf   rf   rg   <module>   s|   0$	X$

             *l
#