U
    Bb                    @   sH  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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 d dlmZ ddlmZmZ ddlmZ ddlmZmZmZ 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) ddl%m*Z+ ddl%m,Z- ddl%m.Z.m/Z/m0Z0m1Z1m2Z2 ddl%m3Z4 ddl%m5Z6 ddl%m7Z8 ddl%m9Z: ddl%m;Z;m<Z< ddl=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZP ddlQmRZRmSZSmTZTmUZUmVZVmWZWmXZX eYeZZ[e/d Z\e<dZ]G dd dZ^eee_ef e_e`ee f eJdddZaG dd de^ZbdS )    N)md5)	AnyCallableDequeDictListOptionalTupleUnioncast)PdfReadWarning   )
PageObject_VirtualList)	PdfReader)_alg33_alg34_alg35)
StreamType_get_max_pdf_version_headerb_deprecate_with_replacement)AnnotationDictionaryAttributes)CatalogAttributes)CatalogDictionary)Core)EncryptionDictAttributes)FieldDictionaryAttributes	FieldFlag"FileSpecificationDictionaryEntriesGoToActionArgumentsInteractiveFormDictEntries)PageAttributes)PagesAttributes)StreamAttributes)TrailerKeys)TypFitArgumentsUserAccessPermissions)ArrayObjectBooleanObjectByteStringObjectContentStreamDecodedStreamObjectDestinationDictionaryObjectFloatObjectIndirectObject
NameObject
NullObjectNumberObject	PdfObjectRectangleObjectStreamObjectTextStringObject
TreeObject_create_bookmarkcreate_string_object)BookmarkTypesBorderArrayTypeFitType
LayoutTypePagemodeTypeZoomArgsTypeZoomArgTypeic                   @   s  e Zd ZdZddddZeedddZejeddd	dZe	e
 ed
ddZee
dddZee
dddZeeeegdf ddddZddddZeddddZeddddZdeeddddZdeeddd d!Zde	e e	e ed"d#d$Zeed%d&d'Zedd(d)Zedd*d+Zeee dd,d-Zde	e e	e ed.d/d0Z de	e e	e ed.d1d2Z!de	e"j# e	e"j# eed3d4d5Z$de	e"j# e	e"j# eed3d6d7Z%e&dd8d9d:Z'e&dd8d;d<Z(e&e)e&ef dd=d>d?Z*e&e)e&ef dd@dAdBZ+de,e	eegdf  ddCdDdEZ-de,e	eegdf  ddCdFdGZ.e/fee0e&ef e1ddHdIdJZ2e/fee0e&ef e1ddHdKdLZ3e,ddMdNdOZ4e,ddMdPdQZ5de,e	eegdf  ddCdRdSZ6de,e	eegdf  ddCdTdUZ7ddVe8fe&e	e& e9e:ddWdXdYZ;e<ddZd[d\Z=e<ee dZd]d^Z>e<ee ed_d`daZ?e<ddZdbdcZ@e0e&ef ddddedfZAe0e&ef ddddgdhZBe)eCeDeEeFeeGe
eHeIeJf
 ddidjdkZKeedldmdnZLe
ed
dodpZMe
ed
dqdrZNeOddsdtZPeOddudvZQeCddwdxZReCddydzZSde)eeOf e)deOef ed{d|d}ZTdee	eO ed{d~dZUdeVe	eO edddZWdeVe	eO edddZXde&ee)deOef e	eYeeef  e9e9eZe[ed	ddZ\de&ee)deOef e	eYeeef  e9e9eZe[ed	ddZ]e
edddZ^e
edddZ_e&eedddZ`e&eedddZaddddZbddddZcde9ddddZdde9ddddZede9ddddZfde9ddddZgdee&ehe	eC ddddZidee&ehe	eC ddddZjdeeehe	eC eZe[ddddZkdeeehe	eC eZe[ddddZldZme	en dddZoe	en dddZpe)eGenf ddddZqenddddZree	en dddZsesjenddddZsee	en dddZtetjenddddZtdZue	ev dddZwe	ev dddZxevddÜddńZyevddÜddǄZzee	ev dddɄZ{e{jevddÜddɄZ{ee	ev ddd̄Z|e|jevddÜdd̄Z|ee0e&ef ddΜddЄZ}dS )	PdfWriterz
    This class supports writing PDF files out, given pages produced by another
    class (typically :class:`PdfReader<PyPDF2.PdfReader>`).
    N)returnc                 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 S )Ns   %PDF-1.3z/Pagesr   z	/ProducerZPyPDF2zutf-16be)_header_objects_idnum_hashr.   updater1   PATYPECOUNTr3   KIDSr(   _add_object_pagesr:   codecsBOM_UTF16_BEencode_infoCOZCATALOGZPAGES_root_root_object)selfpagesinforoot rY   2/tmp/pip-unpacked-wheel-weujb6sz/PyPDF2/_writer.py__init__|   sB          zPdfWriter.__init__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.
        rD   rU   rY   rY   rZ   
pdf_header   s    	zPdfWriter.pdf_header)
new_headerrC   c                 C   s
   || _ d S Nr\   )rU   r_   rY   rY   rZ   r^      s    objrC   c                 C   s   | j | tt| j d| S )Nr   )rE   appendr0   lenrU   rb   rY   rY   rZ   rL      s    zPdfWriter._add_object)idorC   c                 C   s"   |j | krtd| j|jd  S )Nzpdf must be selfr   )pdf
ValueErrorrE   idnumrU   rf   rY   rY   rZ   
get_object   s    
zPdfWriter.get_objectc                 C   s   t dd | |S )zU
        .. deprecated:: 1.28.0

            Use :meth:`get_object` instead.
        	getObjectrk   )r   rk   rj   rY   rY   rZ   rl      s    
zPdfWriter.getObject)pageactionrC   c                 C   s   |t j tjkst|jd k	rF|jj}t|tr8|	 }t
| j|| _| j|tt j< | |}tt| | j}||t j | tt|t j }t|d |tt j< d S )Nr   )rH   rI   rR   ZPAGEAssertionErrorrg   r^   
isinstancestrrP   r   rM   r1   PARENTrL   r   r.   rk   rK   intrJ   r3   )rU   rm   rn   otherZpage_indrV   Z
page_countrY   rY   rZ   	_add_page   s    


zPdfWriter._add_pagec              
   C   s   zV| j }tj|kr6| j ttjtt| jd| i ttj	}t
d| j tj |< W n2 tk
r } ztdt| W 5 d }~X Y nX d S )Nr   Tz&set_need_appearances_writer() catch : )rT   r   Z	ACRO_FORMrG   r1   r0   rd   rE   r!   ZNeedAppearancesr)   	Exceptionloggererrorrepr)rU   catalogZneed_appearancesexcrY   rY   rZ   set_need_appearances_writer   s     
   
z%PdfWriter.set_need_appearances_writer)rm   rC   c                 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)ru   listrc   rU   rm   rY   rY   rZ   add_page   s    
zPdfWriter.add_pagec                 C   s   t dd | | dS )zS
        .. deprecated:: 1.28.0

            Use :meth:`add_page` instead.
        addPager   N)r   r   r~   rY   rY   rZ   r      s    
zPdfWriter.addPager   )rm   indexrC   c                    s   |  | fdd dS )aw  
        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.  This
            argument should be an instance of :class:`PageObject<PyPDF2._page.PageObject>`.
        :param int index: Position at which the page will be inserted.
        c                    s   |   |S r`   )insert)lpr   rY   rZ   <lambda>      z'PdfWriter.insert_page.<locals>.<lambda>N)ru   rU   rm   r   rY   r   rZ   insert_page   s    	zPdfWriter.insert_pagec                 C   s   t dd | || dS )zV
        .. deprecated:: 1.28.0

            Use :meth:`insert_page` instead.
        
insertPager   N)r   r   r   rY   rY   rZ   r     s    
zPdfWriter.insertPage)page_number
pageNumberrC   c                 C   sn   |dk	r*|dk	rt dntddd |}|dkrB|dkrBt dttttf | | j}|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)z4.0.0zPlease specify the page_number)
rh   r   r   r   rq   r   rk   rM   rH   rK   )rU   r   r   rV   rY   rY   rZ   get_page  s    

  zPdfWriter.get_page)r   rC   c                 C   s   t dd | |S )zd
        .. deprecated:: 1.28.0

            Use :code:`writer.pages[page_number]` instead.
        getPagezwriter.pages[page_number])r   r   )rU   r   rY   rY   rZ   r   )  s    
zPdfWriter.getPagec                 C   s*   t tttf | | j}t|td S )Nz/Count)r   r   rq   r   rk   rM   rs   r1   )rU   rV   rY   rY   rZ   _get_num_pages2  s    zPdfWriter._get_num_pagesc                 C   s   t dd |  S )z\
        .. deprecated:: 1.28.0

            Use :code:`len(writer.pages)` instead.
        getNumPageszlen(writer.pages))r   r   r]   rY   rY   rZ   r   6  s    
zPdfWriter.getNumPagesc                 C   s   t | j| jS )zNProperty that emulates a list of :class:`PageObject<PyPDF2._page.PageObject>`.)r   r   r   r]   rY   rY   rZ   rV   ?  s    zPdfWriter.pages)widthheightrC   c                 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   )rU   r   r   rm   rY   rY   rZ   add_blank_pageD  s    
zPdfWriter.add_blank_pagec                 C   s   t dd | ||S )zY
        .. deprecated:: 1.28.0

            Use :meth:`add_blank_page` instead.
        addBlankPager   )r   r   )rU   r   r   rY   rY   rZ   r   W  s    
zPdfWriter.addBlankPage)r   r   r   rC   c                 C   sX   |dks |dk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   rV   Zmediaboxr   r   r   r   r   )rU   r   r   r   Zoldpagerm   rY   rY   rZ   insert_blank_pageb  s     
zPdfWriter.insert_blank_pagec                 C   s   t dd | |||S )zZ
        .. deprecated:: 1.28.0

            Use :meth:`insertBlankPage` instead.
        insertBlankPager   )r   r   )rU   r   r   r   rY   rY   rZ   r   }  s    
zPdfWriter.insertBlankPage)
javascriptrC   c                 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)r.   rG   r1   rH   rI   rL   rq   uuidZuuid4CANAMESr(   r:   rT   )rU   r   ZjsZjs_indirect_objectZjs_string_nameZjs_name_treerY   rY   rZ   add_js  s@    	   
  

  zPdfWriter.add_jsc                 C   s   t dd | |S )zQ
        .. deprecated:: 1.28.0

            Use :meth:`add_js` instead.
        addJSr   )r   r   )rU   r   rY   rY   rZ   r     s    
zPdfWriter.addJS)filenamedatarC   c                 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/EmbeddedFilez/Fz	/Filespecz/EmbeddedFilesN)r,   set_datarG   r1   rH   rI   r.   r   Fr:   ZEFr   r   r(   rT   )rU   r   r   Z
file_entryZef_entryZfilespecZembedded_files_names_dictionaryZembedded_files_dictionaryrY   rY   rZ   add_attachment  s<    
    

zPdfWriter.add_attachment)fnamefdatarC   c                 C   s   t dd | ||S )zY
        .. deprecated:: 1.28.0

            Use :meth:`add_attachment` instead.
        addAttachmentr   )r   r   )rU   r   r   rY   rY   rZ   r     s    
zPdfWriter.addAttachment)readerafter_page_appendrC   c                 C   sX   t |j}t | j}t|D ]6}|j| }| | | j||  }t|r|| qdS )aO  
        Copy pages from reader to writer. Includes an optional callback parameter
        which is invoked after pages are appended to the writer.

        :param reader: a PdfReader object from which to copy page
            annotations to this writer object.  The writer's annots
            will then be updated
        :callback after_page_append (function): Callback function that is invoked after
            each page is appended to the writer. Callback signature:
        :param writer_pageref (PDF page reference): Reference to the page
            appended to the writer.
        N)rd   rV   ranger   callable)rU   r   r   Zreader_num_pagesZwriter_num_pagesZrpagenumZreader_pageZwriter_pagerY   rY   rZ   append_pages_from_reader  s    



z"PdfWriter.append_pages_from_readerc                 C   s   t dd | || dS )zc
        .. deprecated:: 1.28.0

            Use :meth:`append_pages_from_reader` instead.
        appendPagesFromReaderr   N)r   r   rU   r   r   rY   rY   rZ   r   :  s    

zPdfWriter.appendPagesFromReader)rm   fieldsflagsrC   c                 C   s   |    tt|tj D ]}|tj |  }i }tj|krH|tj }|D ]}|tj	|kr|tj
dkr|ttjt|| i |ttjt|| i |r|ttjt|i qL|tj	|krL|ttjt|| i qLq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 page: Page reference from PDF writer where the annotations
            and field data will be updated.
        :param fields: a Python dictionary of field names (/T) and text
            values (/V)
        :param 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/BtnN)r|   r   rd   PGANNOTSrk   rr   getr   TZFTrG   r1   r   ZASVr7   ZFfr3   )rU   rm   r   r   jZwriter_annotZwriter_parent_annotfieldrY   rY   rZ   update_page_form_field_valuesG  sN    


   z'PdfWriter.update_page_form_field_valuesc                 C   s   t dd | |||S )zh
        .. deprecated:: 1.28.0

            Use :meth:`update_page_form_field_values` instead.
        updatePageFormFieldValuesr   )r   r   )rU   rm   r   r   rY   rY   rZ   r     s
     z#PdfWriter.updatePageFormFieldValues)r   rC   c                 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.
        :callback after_page_append:
        N)r   r.   trailerTKROOTrT   rU   r   rY   rY   rZ   clone_reader_document_root  s    z$PdfWriter.clone_reader_document_rootc                 C   s   t dd | | dS )ze
        .. deprecated:: 1.28.0

            Use :meth:`clone_reader_document_root` instead.
        cloneReaderDocumentRootr   N)r   r   r   rY   rY   rZ   r     s
     z!PdfWriter.cloneReaderDocumentRootc                 C   s   |  | | || dS )a2  
        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.
        :callback after_page_append (function): Callback function that is invoked after
            each page is appended to the writer. Signature includes a reference to the
            appended page (delegates to appendPagesFromReader). Callback signature:

            :param writer_pageref (PDF page reference): Reference to the page just
                appended to the document.
        N)r   r   r   rY   rY   rZ   clone_document_from_reader  s    
z$PdfWriter.clone_document_from_readerc                 C   s   t dd | || dS )ze
        .. deprecated:: 1.28.0

            Use :meth:`clone_document_from_reader` instead.
        cloneDocumentFromReaderr   N)r   r   r   rY   rY   rZ   r     s
    
 z!PdfWriter.cloneDocumentFromReaderT)user_pwd	owner_pwd
use_128bitpermissions_flagrC   c                 C   sx  |dk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rt||	||
\}}n$|dkstt||||	||
d\}}t }td	|ttj< t||td
< |dkrt|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   )rs   r*   r   r   ry   timerP   digestrandomr(   _IDr   ro   r   r.   r1   SAZFILTERr3   ZLENGTHEDROUPrL   _encrypt_encrypt_key)rU   r   r   r   r   r   revZkeylenr   r   ZID_1ZID_2r   keyencryptrY   rY   rZ   r     s:    

zPdfWriter.encrypt)streamrC   c                 C   s   t |dr(d|jkr(td|j d | js<| | j| _| | j | 	|}| 
||}| | |td| d dS )z
        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 must support
            the write method and the tell method, similar to a file object.
        modebzFile <zH> to write to is not in binary mode. It may not be written to correctly.z
startxref
z
%%EOF
N)hasattrr   warningswarnnamerS   rL   rT   _sweep_indirect_references_write_header_write_xref_table_write_trailerwriter   )rU   r   object_positionsxref_locationrY   rY   rZ   r     s    


zPdfWriter.writec           
      C   s$  g }| | jd  | d t| jD ]\}}| j| }|d k	r(|d }||  | tt|d  d }t| dr|| j	j
krtd|d d d }tddd d	 }| j| | }t|t| jd
 kstt| }	|	d tdt| jd
  }||| | d q(|S )N   
s   %
r   s    0 obj
r   z<ir   r   r         s   
endobj
)r   r^   	enumeraterE   rc   tellr   rq   r   r   ri   structpackr   rd   ro   r   r   minwrite_to_stream)
rU   r   r   irb   ri   r   Zpack1Zpack2Zmd5_hashrY   rY   rZ   r   %  s(    

zPdfWriter._write_header)r   r   rC   c                 C   s|   |  }|d |tdt| jd  d |tddddd	d
 |D ]"}|t|dddd	d qT|S )Ns   xref
z0 r   
r   z0>10 i  z0>5z f 
z n 
)r   r   r   rd   rE   )rU   r   r   r   offsetrY   rY   rZ   r   <  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rd| j|ttj< t| dr~| j|ttj< ||d  d S )Ns   trailer
r   r   r   )r   r.   rG   r1   r   ZSIZEr3   rd   rE   r   rS   INFOrQ   r   r   ZIDr   ZENCRYPTr   )rU   r   r   rY   rY   rZ   r   E  s     
   

zPdfWriter._write_trailer)infosrC   c                 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}   itemsr:   r1   rk   rQ   rG   )rU   r   argsr   valuerY   rY   rZ   add_metadataU  s    zPdfWriter.add_metadatac                 C   s   t dd | | dS )zW
        .. deprecated:: 1.28.0

            Use :meth:`add_metadata` instead.
        addMetadatar   N)r   r   )rU   r   rY   rY   rZ   r   a  s    
zPdfWriter.addMetadata)rX   rC   c                 C   sr  t  }g }d }g }d }|||||f t|rn| \}}}}t|ttfr| D ],\}}	||	|||d k	r~||g ng f qZnDt|t	r| 
|}t||kr|t| || d d g f t|ttfr*t|tr| 
| |}g }
|| |kr(| gdd |D  }
|||< |
D ]>}| j|d }|d k	r,| }|d k	r,|| j| < q,q*d S )Nc                 S   s   g | ]}|  qS rY   )
hash_value).0Zgrant_parentrY   rY   rZ   
<listcomp>  s    z8PdfWriter._sweep_indirect_references.<locals>.<listcomp>)collectionsdequerc   rd   poprp   r(   r.   r   r0   _resolve_indirect_objectrq   rk   r6   rL   r   rF   )rU   rX   stackZ
discoveredparentZgrant_parentsZ	key_or_idr   r   r   Zupdate_hashesZold_hashZindirect_refZindirect_ref_objrY   rY   rZ   r   j  sR    





z$PdfWriter._sweep_indirect_references)r   rC   c                 C   s   t |jdr*|jjjr*td|jjj |j|}|dkrbtd|j	j
 d| dt t }| }|| jkr~| j| S |j| krt|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   rg   r   closedrh   r   rk   r   r   	__class____name__r   r2   r   rF   r0   ri   rL   )rU   r   Zreal_objr   rY   rY   rZ   r    s     


z"PdfWriter._resolve_indirect_objectc                 C   s0   | j |d }t|d| }| |ks,t|S Nr   r   )rE   r   r0   rk   ro   )rU   rb   ri   refrY   rY   rZ   get_reference  s    zPdfWriter.get_referencec                 C   s   t dd | |S )zX
        .. deprecated:: 1.28.0

            Use :meth:`get_reference` instead.
        getReferencer
  )r   r
  re   rY   rY   rZ   r    s    
zPdfWriter.getReferencec                 C   sz   t j| jkrLtt| jt j }| j|d }t|d| }| |ksvt	n*t }|
i  | |}|| jtt j< |S r  )rR   ZOUTLINESrT   r   r8   rE   r   r0   rk   ro   rG   rL   r1   )rU   outlineri   Zoutline_refrY   rY   rZ   get_outline_root  s    

zPdfWriter.get_outline_rootc                 C   s   t dd |  S )z[
        .. deprecated:: 1.28.0

            Use :meth:`get_outline_root` instead.
        getOutlineRootr  )r   r  r]   rY   rY   rZ   r    s    
zPdfWriter.getOutlineRootc                 C   sr  t j| jkrt| jt j trtt| jt j }| j|d }t|d| }|	 |ks`t
t j|krt|t j trtt|t j }| j|d }t|d| }|	 |kst
t j|krtt|t j }nt }||tt j< n2t }| |}||tt j< t }||tt j< nRt }| |}|| jtt j< t }| |}||tt j< t }||tt j< |S r  )r   r   rT   rp   r.   r   rE   r   r0   rk   ro   ZDESTSr(   r1   rL   )rU   namesri   Z	names_refZdestsZ	dests_refndrY   rY   rZ   get_named_dest_root  s>    
 



zPdfWriter.get_named_dest_rootc                 C   s   t dd |  S )z^
        .. deprecated:: 1.28.0

            Use :meth:`get_named_dest_root` instead.
        getNamedDestRootr  )r   r  r]   rY   rY   rZ   r  +  s    
zPdfWriter.getNamedDestRoot)destr  rC   c                 C   s8   |d kr|   }tt| }| |}|||  |S r`   )r  r   r8   rk   rL   Z	add_child)rU   r  r  dest_refrY   rY   rZ   add_bookmark_destination4  s    
z"PdfWriter.add_bookmark_destinationc                 C   s   t dd | ||S )zc
        .. deprecated:: 1.28.0

            Use :meth:`add_bookmark_destination` instead.
        addBookmarkDestinationr  )r   r  )rU   r  r  rY   rY   rZ   r  B  s    
z PdfWriter.addBookmarkDestination)bookmarkr  rC   c           	      C   s   t  }t| D ]\}}||tt|< q|| d|krt }tt|d }t| D ]\}}||tt|< q^| |}||td< | 	||S )N/A)
r8   r}   r   r1   rq   rG   r.   r   rL   r  )	rU   r  r  Zbookmark_objkvrn   Za_dict
action_refrY   rY   rZ   add_bookmark_dictM  s    

zPdfWriter.add_bookmark_dictc                 C   s   t dd | ||S )z\
        .. deprecated:: 1.28.0

            Use :meth:`add_bookmark_dict` instead.
        addBookmarkDictr  )r   r  )rU   r  r  rY   rY   rZ   r  _  s    
zPdfWriter.addBookmarkDictF/Fit)	titlepagenumr  colorbolditalicfitr   rC   c                 G   s   t |}	dd |D }
ttd| d |	t|f|
 }| tttj|jttjtdi}t	|||||}|dkr| 
 }| ||S )aG  
        Add a bookmark to this PDF file.

        :param str title: Title to use for this bookmark.
        :param int pagenum: Page number this bookmark will point to.
        :param parent: A reference to a parent bookmark to create nested
            bookmarks.
        :param tuple color: Color of the bookmark as a red, green, blue tuple
            from 0.0 to 1.0
        :param bool bold: Bookmark is bold
        :param bool italic: Bookmark is italic
        :param str fit: The fit of the destination page. See
            :meth:`addLink()<addLink>` for details.
        c                 S   s"   g | ]}|d krt  nt|qS r`   r2   r3   r   arY   rY   rZ   r     s    z*PdfWriter.add_bookmark.<locals>.<listcomp>/z	 bookmark/GoToN)r3   r-   r1   rL   r.   r    D
dest_arraySr9   r  r  )rU   r  r   r  r!  r"  r#  r$  r   page_ref	zoom_argsr  r  r  rY   rY   rZ   add_bookmarkj  s0        zPdfWriter.add_bookmarkc           	      G   s&   t dd | j|||||||f| S )zW
        .. deprecated:: 1.28.0

            Use :meth:`add_bookmark` instead.
        addBookmarkr/  )r   r/  )	rU   r  r   r  r!  r"  r#  r$  r   rY   rY   rZ   r0    s    
      zPdfWriter.addBookmark)r  rC   c                 C   s(   |  |}|  }||d |g |S )Nz/Title)rL   r  extend)rU   r  r  r  rY   rY   rZ   add_named_destination_object  s    
z&PdfWriter.add_named_destination_objectc                 C   s   t dd | |S )zg
        .. deprecated:: 1.28.0

            Use :meth:`add_named_destination_object` instead.
        addNamedDestinationObjectr2  )r   r2  )rU   r  rY   rY   rZ   r3    s
     z#PdfWriter.addNamedDestinationObject)r  r   rC   c                 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:  r)  )rk   rM   rH   rK   r.   rG   r1   r    r*  r(   r&   ZFIT_Hr3   r,  rL   r  r1  )rU   r  r   r-  r  r  r  rY   rY   rZ   add_named_destination  s      	
zPdfWriter.add_named_destinationc                 C   s   t dd | ||S )z`
        .. deprecated:: 1.28.0

            Use :meth:`add_named_destination` instead.
        addNamedDestinationr4  )r   r4  )rU   r  r   rY   rY   rZ   r5    s    
zPdfWriter.addNamedDestinationc                 C   sR   t t| | j}t t|tj }|D ]&}t t| |}tj|kr&|tj= q&dS )z.Remove links and annotations from this output.N)	r   r.   rk   rM   r(   rH   rK   r   r   )rU   pg_dictrV   rm   r-  rY   rY   rZ   remove_links  s    
zPdfWriter.remove_linksc                 C   s   t dd |  S )zW
        .. deprecated:: 1.28.0

            Use :meth:`remove_links` instead.
        removeLinksr7  )r   r7  r]   rY   rY   rZ   r8    s    
zPdfWriter.removeLinks)ignore_byte_string_objectrC   c                 C   st  t t| | j}t t|tj }d}|D ]B}t t| |}|d  }t|ts`t||}g }d}	|j	D ]\}
}|dkr|
d }|rt|t
st
 |
d< nn|dkr|
d }|rt|t
st
 |
d< nD|dkrtt|
d D ](}|rt|
d | t
st
 |
d |< q|d	krd
}	|dkr*d}	|	r<||kr<qn|dkrHqn||
|f qn||_	|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   r.   rk   rM   r(   rH   rK   rp   r+   
operationsr7   r   rd   rc   __setitem__r1   )rU   r9  r6  rV   Zjump_operatorsrm   r-  contentZ_operationsZseq_graphicsoperandsoperatortextr   rY   rY   rZ   remove_images  sV    


  

 


zPdfWriter.remove_images)ignoreByteStringObjectrC   c                 C   s   t dd | |S )zX
        .. deprecated:: 1.28.0

            Use :meth:`remove_images` instead.
        removeImagesr[  )r   r[  rU   r\  rY   rY   rZ   r]  =  s    
zPdfWriter.removeImagesc                 C   s  t t| | j}t tt |tj }|D ]Z}t tt	t
f | |}|d  }t|tsht||}|jD ]\}}|dkr|d }	|st|	trt |d< nt|	ttfrt |d< qn|dkr|d }	|st|	trt |d< nt|	ttfrtt |d< qn|dkrntt|d D ]V}
|sJt|d |
 trpt |d |
< n&t|d |
 ttfrt |d |
< qqn|td| q*dS )z
        Remove text from this output.

        :param bool ignore_byte_string_object: optional parameter
            to ignore ByteString Objects.
        rN  rO  r   rQ  r   rR  N)r   r.   rk   rM   r   r0   rH   rK   r   rq   r   rp   r+   rU  r7   r*   r   rd   rV  r1   )rU   r9  r6  rV   rm   r-  rW  rX  rY  rZ  r   rY   rY   rZ   remove_textH  sB    






 zPdfWriter.remove_textc                 C   s   t dd | |S )zV
        .. deprecated:: 1.28.0

            Use :meth:`remove_text` instead.
        
removeTextr_  )r   r_  r^  rY   rY   rZ   r`  t  s    
zPdfWriter.removeText)r   urirectborderrC   c                 C   s|  |  | jtj | }ttttf |  |}|dk	rzdd |dd D }t|dkrt	dd |d D }|
| ntdgd }t|trt|}nt|trn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|krd|tj 
| n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 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 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   s   g | ]}t |qS rY   r1   r   nrY   rY   rZ   r     s     z%PdfWriter.add_uri.<locals>.<listcomp>r      c                 S   s   g | ]}t |qS rY   rd  re  rY   rY   rZ   r     s     r   r   z/URI/Linkz/Hz/Ir  )rk   rM   rH   rK   r   r   rq   r   rd   r(   rc   r3   rp   r1   r5   r.   rG   r7   r   Typer   r   ZSubtyper   ZRectZBorderrL   )rU   r   ra  rb  rc  	page_linkr-  
border_arrdash_patternZlnk2lnklnk_refrY   rY   rZ   add_uri  sZ    


         
zPdfWriter.add_uric                 C   s   t dd | ||||S )zR
        .. deprecated:: 1.28.0

            Use :meth:`add_uri` instead.
        addURIro  )r   ro  )rU   r   ra  rb  rc  rY   rY   rZ   rp    s    
zPdfWriter.addURI)r   pagedestrb  rc  r$  r   rC   c                 G   s  t tttf | | j}|tj | }|tj | }	t tttf | |}
|dk	rdd |dd D }t|dkrt	dd |d D }|
| ntdgd }t|trt|}nt|trnt|}dd |D }ttd	|	t|f| }ttd
ttjtdtdtd|td|tdt	|td|ji}| |}tj|
krh|
tj 
| nt	|g|
ttj< dS )a  
        Add an internal link from a rectangular area to the specified page.

        :param int pagenum: index of the page on which to place the link.
        :param int pagedest: index of the page to which the link should go.
        :param 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 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.
        :param str fit: Page fit or 'zoom' option (see below). Additional arguments may need
            to be supplied. Passing ``None`` will be read as a null value for that coordinate.

        .. list-table:: Valid ``zoom`` arguments (see Table 8.2 of the PDF 1.7 reference for details)
           :widths: 50 200

           * - /Fit
             - No additional arguments
           * - /XYZ
             - [left] [top] [zoomFactor]
           * - /FitH
             - [top]
           * - /FitV
             - [left]
           * - /FitR
             - [left] [bottom] [right] [top]
           * - /FitB
             - No additional arguments
           * - /FitBH
             - [top]
           * - /FitBV
             - [left]
        Nc                 S   s   g | ]}t |qS rY   rd  re  rY   rY   rZ   r     s     z&PdfWriter.add_link.<locals>.<listcomp>r   rg  c                 S   s   g | ]}t |qS rY   rd  re  rY   rY   rZ   r     s     r   c                 S   s"   g | ]}|d krt  nt|qS r`   r%  r&  rY   rY   rZ   r     s    z	/LinkNamez/Typez/Subtyperh  /Pz/Rectz/Borderz/Dest)r   r   rq   r   rk   rM   rH   rK   rd   r(   rc   r3   rp   r1   r5   r-   r.   r   r   r+  rL   )rU   r   rq  rb  rc  r$  r   Z	pages_objrj  Z	page_destr-  rk  rl  r.  r  rm  rn  rY   rY   rZ   add_link  sX    +


        

zPdfWriter.add_linkc                 G   s"   t dd | j|||||f| S )zS
        .. deprecated:: 1.28.0

            Use :meth:`add_link` instead.
        addLinkrs  )r   rs  )rU   r   rq  rb  rc  r$  r   rY   rY   rZ   rt  )  s    
zPdfWriter.addLink)z	/NoLayoutz/SinglePagez
/OneColumnz/TwoColumnLeftz/TwoColumnRightz/TwoPageLeftz/TwoPageRightc                 C   s.   zt t| jd W S  tk
r(   Y d S X d S )N/PageLayout)r   r>   rT   KeyErrorr]   rY   rY   rZ   _get_page_layoutD  s    zPdfWriter._get_page_layoutc                 C   s   t dd |  S )Y
        .. deprecated:: 1.28.0

            Use :py:attr:`page_layout` instead.
        getPageLayoutpage_layout)r   rw  r]   rY   rY   rZ   ry  J  s    
zPdfWriter.getPageLayout)layoutrC   c                 C   sP   t |ts8|| jkr0tddd| jf  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:  ru  N)rp   r1   _valid_layoutsr   r   joinrT   rG   rU   r{  rY   rY   rZ   _set_page_layoutS  s    

zPdfWriter._set_page_layoutc                 C   s   t dd | |S )rx  zwriter.setPageLayout(val)zwriter.page_layout = val)r   r  r  rY   rY   rZ   setPageLayouts  s
     zPdfWriter.setPageLayoutc                 C   s   |   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
        )rw  r]   rY   rY   rZ   rz  ~  s    zPdfWriter.page_layoutc                 C   s   |  | d S r`   )r  r  rY   rY   rZ   rz    s    c                 C   s   t dd | jS )rx  
pageLayoutrz  r   rz  r]   rY   rY   rZ   r    s    
zPdfWriter.pageLayoutc                 C   s   t dd || _dS )rx  r  rz  Nr  r  rY   rY   rZ   r    s    
)z/UseNonez/UseOutlinesz
/UseThumbsz/FullScreenz/UseOCz/UseAttachmentsc                 C   s.   zt t| jd W S  tk
r(   Y d S X d S )N	/PageMode)r   r?   rT   rv  r]   rY   rY   rZ   _get_page_mode  s    zPdfWriter._get_page_modec                 C   s   t dd |  S )W
        .. deprecated:: 1.28.0

            Use :py:attr:`page_mode` instead.
        getPageMode	page_mode)r   r  r]   rY   rY   rZ   r    s    
zPdfWriter.getPageMode)r   rC   c                 C   sR   t |tr|}n*|| jkr2tdd| j  t|}| jtd|i dS )r  zMode should be one of: z, r  N)rp   r1   _valid_modesr   r   r~  rT   rG   )rU   r   Z	mode_namerY   rY   rZ   set_page_mode  s    

zPdfWriter.set_page_modec                 C   s   t dd | | dS )r  zwriter.setPageMode(val)zwriter.page_mode = valN)r   r  rU   r   rY   rY   rZ   setPageMode  s    
zPdfWriter.setPageModec                 C   s   |   S )a   
        Page mode property.

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

           * - /UseNone
             - Do not show outlines or thumbnails panels
           * - /UseOutlines
             - Show outlines (aka bookmarks) panel
           * - /UseThumbs
             - Show page thumbnails panel
           * - /FullScreen
             - Fullscreen view
           * - /UseOC
             - Show Optional Content Group (OCG) panel
           * - /UseAttachments
             - Show attachments panel
        )r  r]   rY   rY   rZ   r    s    zPdfWriter.page_modec                 C   s   |  | d S r`   )r  r  rY   rY   rZ   r    s    c                 C   s   t dd | jS )r  pageModer  r   r  r]   rY   rY   rZ   r    s    
zPdfWriter.pageModec                 C   s   t dd || _dS )r  r  r  Nr  r  rY   rY   rZ   r    s    
)r   
annotationrC   c                 C   st   t tt|}| | jd | |td< | j| }|jd krLt |td< |jd k	sZt	| 
|}|j| d S )Nz/Kidsrr  z/Annots)r   r.   _pdf_objectifyrk   rM   r1   rV   annotationsr(   ro   rL   rc   )rU   r   r  to_addrm   Zind_objrY   rY   rZ   add_annotation  s    


zPdfWriter.add_annotation)r   )r   )NN)NN)NN)NNr   )NNr   )N)N)N)N)N)N)N)N)NNFFr  )NNFFr  )F)F)F)F)N)N)Nr  )Nr  )~r  
__module____qualname____doc__r[   propertybytesr^   setterr   r4   r0   rL   rk   rl   r   r   r   ru   r|   r   r   rs   r   r   r   r   r   r   r   rV   floatr   r   decimalDecimalr   r   rq   r   r   r
   r   r   r   r   r   OPTIONAL_READ_WRITE_FIELDr   r   r   r   r   r   r   r   ALL_DOCUMENT_PERMISSIONSboolr'   r   r   r   r   r   r   r   r   r(   r)   r.   r/   r1   r3   r7   r2   r   r  r
  r  r8   r  r  r  r  r  r  r;   r  r  r	   r=   rA   r/  r0  r2  r3  r4  r5  r7  r8  r[  r]  r_  r`  r5   ro  rp  rs  rt  r}  r>   rw  ry  r  r  rz  r  r  r?   r  r  r  r  r  r  r  rY   rY   rY   rZ   rB   v   sF  &

 	
    		              +	S 
 ! 
B
	  :	P#		' 
           3      		N -  H   ]  
	 							rB   ra   c                 C   s   t | tr| S t | trLt }|  D ] \}}t|}t|}|||< q&|S t | trxt }| D ]}|	t| q`|S t | t
r| drt| S t| S n*t | ttfrt| S tdt|  dd S )Nr(  z
type(obj)=z! could not be casted to PdfObject)rp   r4   dictr.   r   r1   r  r}   r(   rc   rq   
startswithr7   rs   r  r/   NotImplementedErrortype)rb   r  r   r   Zname_keyZcasted_valueZarrelrY   rY   rZ   r    s.    






r  c                       s&   e Zd Zeedd fddZ  ZS )PdfFileWriterN)r   kwargsrC   c                    s   t dd t j|| d S )Nr  rB   )r   superr[   )rU   r   r  r  rY   rZ   r[   7  s    
zPdfFileWriter.__init__)r  r  r  r   r[   __classcell__rY   rY   r  rZ   r  6  s   r  )crN   r   r  loggingr   r   r   r   r   hashlibr   typingr   r   r   r   r   r   r	   r
   r   ZPyPDF2.errorsr   Z_pager   r   Z_readerr   Z	_securityr   r   r   _utilsr   r   r   r   	constantsr   r   r   r   r   rR   r   r   r   r   r   r    r!   r"   r   r#   rH   r$   r   r%   r   r&   r'   Zgenericr(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   typesr;   r<   r=   r>   r?   r@   rA   	getLoggerr  rw   r  r  rB   rq   rs   r  r  rY   rY   rY   rZ   <module>   s^   ,T$

             1(