3
NZ7                 @   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mZ d dlm	Z	 d dl
T d dlT d dlmZmZmZmZ d dlmZ ddlT d ZdZdZd	Zd
ZdZdZd Zd ZdZdZdZd	Z dZ!dZ"dZ#d
Z$dZ%d Z&dZ'dZ(dZ)d	Z*dZ+dZ,dZ-d
Z.dZ/dZ0dZ1dZ2dZ3dZ4dZ5dZ6d Z7dZ8dZ9d
Z:dZ;dZ<dZ=dZ>d	Z?dZ@dZAdZdZd	Zd
ZdZd ZBdZCdZDdZEdZFd ZGdZHdZIdZJG dd deKZLG dd dejMZNG d d! d!eOZPdS )"    N)StringIO)BytesIO)*)deviceutilspmlcodes)cups                           	   
                     J   $   3   i  c               @   s   e Zd ZdddedfddZdd Zdd Zeeed	d
Zdd Z	dd Z
ee
e	dd
Zdd Zdd Zdd Zdd ZdddZdS )PMLFaxDeviceNFc             C   s$   t j| ||||| d | _d | _d S )N)	FaxDevice__init__send_fax_threadupload_log_thread)selfZ
device_uriprinter_namecallbackfax_typeZdisable_dbus r'   /usr/share/hplip/fax/pmlfax.pyr       s    zPMLFaxDevice.__init__c             C   s   | j tjt|S )N)setPMLr   OID_FAX_LOCAL_PHONE_NUMstr)r#   Znumr'   r'   r(   setPhoneNum   s    zPMLFaxDevice.setPhoneNumc             C   sD   t r*tj| jtjd jd}|jdS tj| jtjd S d S )Nr
   zutf-8)PY3r   	printablegetPMLr   r*   encodedecode)r#   datar'   r'   r(   getPhoneNum   s    
zPMLFaxDevice.getPhoneNumr*   )docc             C   s   | j tj|S )N)r)   r   OID_FAX_STATION_NAME)r#   namer'   r'   r(   setStationName   s    zPMLFaxDevice.setStationNamec             C   sD   t r*tj| jtjd jd}|jdS tj| jtjd S d S )Nr
   zutf-8)r-   r   r.   r/   r   r5   r0   r1   )r#   r2   r'   r'   r(   getStationName   s    
zPMLFaxDevice.getStationNamer5   c             C   s   d S )Nr'   )r#   r'   r'   r(   setDateAndTime   s    zPMLFaxDevice.setDateAndTimec             C   s(   | j  s t| | _| jj  dS dS d S )NTF)ZisUloadLogActiveZUploadLogThreadr"   start)r#   r'   r'   r(   	uploadLog   s
    

zPMLFaxDevice.uploadLogc             C   s   | j d k	r| j j S dS d S )NF)r"   isAlive)r#   r'   r'   r(   isUploadLogActive   s    

zPMLFaxDevice.isUploadLogActivec             C   s"   | j d k	r| j j r| j j  d S )N)r"   r<   join)r#   r'   r'   r(   waitForUploadLogThread   s    

z#PMLFaxDevice.waitForUploadLogThread c
       
      C   s>   | j  s6t| | j|||||||||	| _| jj  dS dS d S )NTF)ZisSendFaxActivePMLFaxSendThreadservicer!   r:   )
r#   phone_num_listfax_file_listcover_messagecover_re
cover_funcpreserve_formattingr$   update_queueevent_queuer'   r'   r(   	sendFaxes   s    
zPMLFaxDevice.sendFaxes)r@   r@   NFr@   NN)__name__
__module____qualname__ZFAX_TYPE_NONEr    r,   r3   property	phone_numr7   r8   station_namer9   r;   r=   r?   rK   r'   r'   r'   r(   r   }   s"     r   c               @   s   e Zd Zdd Zdd ZdS )PMLUploadLogThreadc             C   s   t jj|  || _d S )N)	threadingThreadr    dev)r#   rU   r'   r'   r(   r       s    zPMLUploadLogThread.__init__c             C   s  d}d}d}d}d}d}d}d}d	}	d
}
|}x||kr||krDq0||krNq0||krXq0||kr|}y| j j  W n6 tk
r } ztjd|j  t}W Y d d }~X n0X yt jtj	tj
 W n tk
r   t}Y nX q0||kr|}| j }|tjkr|}q0||kr6|}| j jtjtj | j jtjtj q0||kr|	}d}x|d7 }| j }|tjkrhP |tjtjfkrtjd t}P |dkrt}tjd P tjd qJW q0||	krq0||
kr0| j j  q0W d S )Nr   r               (   2   <   F   zUnable to open device (%s).r
   zCfg upload aborted!z Unable to get into active state!g      ?)rU   openErrorlogerrormsgSTATE_ERRORr)   r   ZOID_UPLOAD_TIMEOUTZDEFAULT_UPLOAD_TIMEOUTgetCfgUploadStateUPDN_STATE_IDLEZOID_FAX_CFG_UPLOAD_DATA_TYPEZ FAX_CFG_UPLOAD_DATA_TYPE_FAXLOGSOID_DEVICE_CFG_UPLOADUPDN_STATE_REQSTARTUPDN_STATE_XFERACTIVEUPDN_STATE_ERRORABORTUPDN_STATE_XFERDONEtimesleepclose)r#   
STATE_DONEZSTATE_ABORTSTATE_SUCCESS
STATE_BUSYZSTATE_DEVICE_OPENZSTATE_CHECK_IDLEZSTATE_REQUEST_STARTZSTATE_WAIT_FOR_ACTIVEZSTATE_UPLOAD_DATAZSTATE_DEVICE_CLOSEstateeZul_stateZtriesr'   r'   r(   run   sv    






zPMLUploadLogThread.runN)rL   rM   rN   r    rs   r'   r'   r'   r(   rR      s   rR   c               @   s   e Zd Zd$ddZdd Zdd	 Zd
d Zdd Zdd Zdd Z	d%ddZ
dd Zdd Zd&ddZdd Zdd Zd d! Zd"d# ZdS )'rA   r@   NFc             C   s$   t j| |||||||||	|
| d S )N)FaxSendThreadr    )r#   rU   rB   rC   rD   rE   rF   rG   rH   r$   rI   rJ   r'   r'   r(   r    +  s    zPMLFaxSendThread.__init__c       I      C   s  d}d}d}d}d}d}d}d}d	}	d
}
d}d}
d}d}d}| j  }|}g | _x||kr| j rh|}tjd|  ||krtjd | jtddf |}qR||krtjd | jtddf |}qR||krtjd | jt	ddf |}qR||krtjd | jt
ddf |}qR||krtjddx  |}zy| jj  W n8 tk
r| } ztjd|j  |}W Y d d }~X n`X y8| jj| _tjd| j  | jj| _tjd| j  W n$ tk
r   tjd |}Y nX W d | jj  X qR||krtjddy  | j|}qR||kr6tjddz  | j|}qR||krtjdd{  |	}y2t|}tjd|d    | jtd|d  f W n& tk
r   |}tjd! wRY nX | jd d  | _qR||	krtjd"d|  | j|}qR||
krtjd#d}  | j|}qR||kr*tjd$d~  | j|}qR||krtjd%d  |}d}d}d}d}d}d}d}d}d	}d
}d}d}d}d} d}!d&}"d'}#d(}$d)}%d*}&tj}'|}(xP|(|kr| j rtjd+ |}(|&r| j })|)tj tj!fkrtjd,|)  |}(|}tjd-||(f  |(|kr(d*}&|$}(|}q|(|krptjd. | j" }'tjd/|'tj#j$|'d0f  d*}&|$}(|}q|(|krtjd1 d*}&|$}(|}q|(|krtjd2 d*}&|$}(|}q|(|kr2tjd3d  |}(y| jj  W n8 tk
r } ztjd|j  |}(W Y d d }~X nX | jj%t&kr~|}(q|(|kr.tjd4d  y| jj'tj(\}*}+W n$ tk
r   tjd5 |}(Y nX |*tj)kr|}(tjd6 nt*j+d7t*j, }+tjd8|+  y| jj-tj(|+ W n$ tk
r   tjd9 |}(Y n2X | jj'tj(\}*},|,|+kr|}(ntjd: |}(q|(|krtjd;d  |}(| jj.t/krtjd< y| jj0  W n8 tk
r } ztjd=|j  |}(W Y d d }~X nX n
tjd> q|(|krtjd?d  |}(| j }-| j1 }.| j2 }/|-tj3ks|-tj4ks|-tj!kr|.tj5ks*|.tj6kr|/tj7ksB|/tj8kr|-tj3krZtjd@ n&tjdA | jj-tj9tj3 t*j:dB n|}(q|(|krtjdCd  |}(| j }-|-tj3krtjdD tjdE | jj-tj9tj; t*j:dF tjdG dF}0x|0dk rtjdH|0  y| j }-W n& tk
rD   tjdI |}(P Y nX |-tj krTP t*j:dF tjdE | jj-tj9tj; |0dF7 }0qW tjdJ |}(dK}&ntjdL |}(q|(|k	rDtjdMd  |}(y<| jj-tj<tj= | jj-tj>tj? tjdN | jj@  W n8 tk
	r> } ztjdO|j  |}(W Y d d }~X nX q|(|k	rtjdPd  |}(| jj.tAk	rtjd< y| jj0  W n$ tk
	r   tjdQ |}(Y nX n
tjd> q|(|k
rftjdRd  | }(tjdS|dT   tjdU | jBtCdKtDtEB tFB  |dT jGdV}1tjtH|1 | jI|1 y| jJ  W n$ tk

r`   tjdW |}(Y nX q|(| krtjdXd  |!}(yt| jKdY}2W n( tLk

r   tjdZ |}(wY nX y|2jMtN}3W n( tLk

r   tjdZ |}(wY nX | jO|3\
}4}5}6}7}8}9}:};}<}=|4d[kr,tjd\ |}(nrtjd]|4|5|6|7|8|9|:|;f  tjd^ | jBtPdKtD | jQ|6 y| jJ  W n$ tk
r   tjd_ |}(Y nX q|(|!krtjd`d  |"}(tR }>xtS|6D ],}?| j r|}(|(|krP y|2jMtT}3W n( tLk
r&   tjdZ |}(wY nX | jU|3\}@}A}B}C}D}=tjda|@|A|B|C|Df  |>jV|2jM|C |2jM|D}E|>jWd | jBtPtXdb | jY|@|7|8|A|B|; y|>jMtZ}FW n( tLk
r   tjdZ |}(wY nX |Fdkrtjdc |}(q| j[|F tZ}Gx|>jMtZ}F|GtZ7 }G| j }-|-tj4kr.|}(P | j r>|}(P |Fddkr| j\|B y| jJ  W n$ tk
r   tjdW |}(Y nX P n4y| jJ  W n& tk
r   tjdW |}(P Y nX | j1 }Hxb|Htj]kr&| jt^d|dT f t*j:de | j r |}(P | j }-|-tj4kr|}(P | j1 }HqW |(||fkrxb|Htj_kr| jt`d|dT f t*j:de | j rr|}(P | j }-|-tj4kr|}(P | j1 }Hq8W |Htjakr| jtb|@|dT f | jBtPddb | j[|F |(||fkrP qW |>jcd |>jWd qW q|(|"krttjdfd  |#}(tjdg | jBtPd*tF y| jJ  W n$ tk
rj   tjdW |}(Y nX d*}&q|(|#krBtjdhd  |#}(t*j:de | j1 }H|Htj]kr| jt^d|dT f tjdi np|Htjakr| jtb|@|dT f tjdj nD|Htj6tj7fkr |$}(|}tjdk n| jtb|@|dT f tjdl q|(|$krtjdmd  | jtdddf y| jj-tj(d W n  tk
r   tjdp Y nX |%}(n|(|%krtjdqd  |}(tjdr ytej  W n tfk
r   Y nX y|2j  W n tfk
r   Y nX | jj.tAkr6tjds | jjg  | jj-tj9tj3 t*j:dF | jj.t/krttjds | jjg  | jj  qW qR||krRtjdtd  | jhrtjdu| jK  ytijj| jK tjdv W n  tkk
r   tjdw Y nX |}qRW d S )Nr   r   rV   rW   rY   rZ   r[   r\   r]   P   Z   d   n   x      zSTATE=(%d, 0, 0)zAborted by user.r@   zSuccess.zError, aborting.zDevice busy, aborting.z%s State: Get sender infor   zUnable to open device (%s).zSender name=%szSender fax=%szPML get failed!z!%s State: Pre-render non-G3 filesz%s State: Get total page countz%s State: Next recipientzProcessing for recipient %sr6   zLast recipient.z%s State: Render cover pagez%s State: Handle single filez%s State: Merge multiple filesz%s State: Send fax            FzFax send aborted.zD/L error state=%dzSTATE=(%d, %d, 0)zFax send error.zError State=%d (%s)UnknownzFax device busy.zFax send success.z%s State: Open devicez%s State: Acquire fax tokenz Unable to acquire fax token (1).zSkipping token acquisition.z%d%m%Y%H:%M:%SzSetting token: %sz Unable to acquire fax token (2).z Unable to acquire fax token (3).z%s State: Early openzOpening fax channel.zUnable to open channel (%s).zSkipped.z%s State: Check idlezStarting in idle statezResetting to idle...g      ?z%s State: Request startzTry: 0z)Setting to up/down state request start...r
   zWaiting for active state...zTry: %dzPML/SNMP errorz Could not get into active state!TzCould not get into idle state!z%s State: Set paramsz Setting date and time on device.zPML/SNMP error (%s)z%s State: Late openzUnable to open channel.z%s State: Send dial stringszDialing: %sfaxzSending dial strings...asciizChannel write error.z%s State: Send fax headerrbzUnable to read fax file.s   hplip_g3zInvalid file header. Bad magic.z>Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%dzSending fax header...zUnable to write to channel.z%s State: Send pagesz%Page=%d PPR=%d RPP=%d BPP=%d Thumb=%d)
page_flagszNo data!    g      ?z%s State: Send EOSzEnd of stream...z%s State: Wait for completionzDialing ...zTransmitting ...zTransmitting done or idle ...zPending ...z%s State: Release fax token r   zUnable to release fax token.z%s State: Close sessionzClosing session...zClosing fax channel.z%s State: CleanupzRemoving merged file: %sZRemovedz	Not foundz********************z********************z********************z********************z********************z********************z********************z********************z********************z********************z********************z********************z********************z********************z********************z********************z********************z********************z********************z********************z********************z                z********************z********************)lZnext_recipient_genZrendered_file_listZcheck_for_cancelr`   debugra   Zwrite_queueZSTATUS_IDLEZSTATUS_COMPLETEDZSTATUS_ERRORZSTATUS_BUSYrU   r^   r_   rb   rQ   Zsender_namerP   Z
sender_faxrm   Z
pre_renderZcount_pagesnextZSTATUS_SENDING_TO_RECIPIENTStopIterationZrecipient_file_listZ
cover_pageZsingle_fileZmerge_filesr   ZDN_ERROR_NONEgetFaxDownloadStaterh   rj   getFaxDownloadErrorZDN_ERROR_STRgetZdevice_stateZDEVICE_STATE_NOT_FOUNDr/   ZOID_FAX_TOKENZERROR_MAX_OKrk   ZstrftimeZgmtimer)   r&   ZFAX_TYPE_BLACK_SEND_EARLY_OPENZopenFaxgetFaxJobTxStatusgetFaxJobRxStatusre   ri   FAXJOB_TX_STATUS_IDLEZFAXJOB_TX_STATUS_DONEFAXJOB_RX_STATUS_IDLEZFAXJOB_RX_STATUS_DONEOID_FAX_DOWNLOADrl   rg   ZOID_DEV_DOWNLOAD_TIMEOUTZDEFAULT_DOWNLOAD_TIMEOUTZOID_FAXJOB_TX_TYPEZFAXJOB_TX_TYPE_HOST_ONLYr9   ZFAX_TYPE_BLACK_SEND_LATE_OPENcreate_mfpdtf_fixed_headerDT_DIAL_STRINGSPAGE_FLAG_NEW_DOCPAGE_FLAG_END_DOCPAGE_FLAG_END_STREAMr0   reprcreate_mfpdtf_dial_stringswrite_streamfIOErrorreadZFILE_HEADER_SIZEZdecode_fax_headerDT_FAX_IMAGEScreate_mfpdtf_fax_headerr   rangeZPAGE_HEADER_SIZEZdecode_page_headerwriteseekPAGE_FLAG_NEW_PAGEcreate_sop_recordRASTER_DATA_SIZEcreate_raster_data_recordcreate_eop_recordZFAXJOB_TX_STATUS_DIALINGZSTATUS_DIALINGZFAXJOB_TX_STATUS_CONNECTINGZSTATUS_CONNECTINGZFAXJOB_TX_STATUS_TRANSMITTINGZSTATUS_SENDINGtruncateZSTATUS_CLEANUPZmm	NameErrorZcloseFaxZremove_temp_fileosremoveOSError)Ir#   rn   ZSTATE_ABORTEDro   rp   ZSTATE_READ_SENDER_INFOZSTATE_PRERENDERZSTATE_COUNT_PAGESZSTATE_NEXT_RECIPIENTZSTATE_COVER_PAGEZSTATE_SINGLE_FILEZSTATE_MERGE_FILESZSTATE_SEND_FAXZSTATE_CLEANUPrc   Znext_recipientrq   rr   Z	recipientZFAX_SEND_STATE_DONEZFAX_SEND_STATE_ABORTZFAX_SEND_STATE_ERRORZFAX_SEND_STATE_BUSYZFAX_SEND_STATE_SUCCESSZFAX_SEND_STATE_DEVICE_OPENZFAX_SEND_STATE_SET_TOKENZFAX_SEND_STATE_EARLY_OPENZFAX_SEND_STATE_SET_PARAMSZFAX_SEND_STATE_CHECK_IDLEZFAX_SEND_STATE_START_REQUESTZFAX_SEND_STATE_LATE_OPENZ FAX_SEND_STATE_SEND_DIAL_STRINGSZFAX_SEND_STATE_SEND_FAX_HEADERZFAX_SEND_STATE_SEND_PAGESZ!FAX_SEND_STATE_SEND_END_OF_STREAMZ FAX_SEND_STATE_WAIT_FOR_COMPLETEZFAX_SEND_STATE_RESET_TOKENZFAX_SEND_STATE_CLOSE_SESSIONZmonitor_stateZerror_stateZfax_send_stateZ	fax_stateresult_codetokenZcheck_tokenZdl_stateZ	tx_statusZ	rx_statusiZdial_stringsZffheadermagicversiontotal_pageshort_dpivert_dpiZ	page_sizeZ
resolutionencodingZ	reserved1Z	reserved2Zpageppage_numpprrppZbytes_to_readZthumbnail_bytesZ	thumbnailr2   Z
total_readstatusr'   r'   r(   rs   4  s   









































































































zPMLFaxSendThread.runc             C   s@   | j jtj\}}|r6tjd|tjj|df  |S tjS d S )NzD/L State=%d (%s)r   )	rU   r/   r   r   r`   r   UPDN_STATE_STRr   ri   )r#   r   rq   r'   r'   r(   r     s
    z$PMLFaxSendThread.getFaxDownloadStatec             C   s$   | j jtj\}}|r|S tjS d S )N)rU   r/   r   ZOID_FAX_DOWNLOAD_ERRORZDN_ERROR_UNKNOWN)r#   r   rq   r'   r'   r(   r     s    z$PMLFaxSendThread.getFaxDownloadErrorc             C   s@   | j jtj\}}|r6tjd|tjj|df  |S tjS d S )NzTx Status=%d (%s)r   )	rU   r/   r   ZOID_FAXJOB_TX_STATUSr`   r   ZFAXJOB_TX_STATUS_STRr   r   )r#   r   r   r'   r'   r(   r     s
    z"PMLFaxSendThread.getFaxJobTxStatusc             C   s@   | j jtj\}}|r6tjd|tjj|df  |S tjS d S )NzRx Status=%d (%s)r   )	rU   r/   r   ZOID_FAXJOB_RX_STATUSr`   r   ZFAXJOB_RX_STATUS_STRr   r   )r#   r   r   r'   r'   r(   r     s
    z"PMLFaxSendThread.getFaxJobRxStatusc             C   s@   | j jtj\}}|r6tjd|tjj|df  |S tjS d S )NzCfg Upload State = %d (%s)r   )	rU   r/   r   rf   r`   r   r   r   ri   )r#   r   rq   r'   r'   r(   rd     s
    z"PMLFaxSendThread.getCfgUploadStater   c             C   sH   t }|r*|tkr|t7 }n|tkr*|t7 }| jjtjdd||| d S )Nz<IHBBr   )	FIXED_HEADER_SIZEr    DIAL_STRINGS_VARIANT_HEADER_SIZEr   FAX_IMAGE_VARIANT_HEADER_SIZEstreamr   structpack)r#   Z	data_typeZsend_variantr   Z
header_lenr'   r'   r(   r     s    
z+PMLFaxSendThread.create_mfpdtf_fixed_headerc          	   C   s:   t jdttdd|d d }tjt| | jj| d S )Nz<BBHH51sr
   r   )	r   r   	MAJOR_VER	MINOR_VERr`   r   r   r   r   )r#   Znumberr   r'   r'   r(   r     s
    z+PMLFaxSendThread.create_mfpdtf_dial_stringsc             C   s.   | j j }| j jd | j jtjd| d S )Nr   z<I)r   tellr   r   r   r   )r#   sizer'   r'   r(   adjust_fixed_header_block_size  s    
z/PMLFaxSendThread.adjust_fixed_header_block_sizer
   c             C   s8   | j jtjdt|||||d|d||||d|d| d S )Nz<BBHHHIHHHHHHIHHHHr   )r   r   r   r   RT_START_PAGE)r#   r   r   r   r   r   r   Zbppr'   r'   r(   r     s    
z"PMLFaxSendThread.create_sop_recordc          	   C   s"   | j jtjdtddd|d d S )Nz<BBBBIIr   )r   r   r   r   RT_END_PAGE)r#   r   r'   r'   r(   r     s    z"PMLFaxSendThread.create_eop_recordc             C   s<   t |tkst| jjtjdtdt | | jj| d S )Nz<BBHr   )lenr   AssertionErrorr   r   r   r   	RT_RASTER)r#   r2   r'   r'   r(   r     s    z*PMLFaxSendThread.create_raster_data_recordc             C   s*   | j jtjdttt|tddddd d S )Nz<BBBHBI20s20s20sIr   r   )r   r   r   r   r   r   SRC_HOSTTTI_PREPENDED_TO_IMAGE)r#   r   r'   r'   r(   r     s    z)PMLFaxSendThread.create_mfpdtf_fax_headerc             C   s6   | j   | jj| jj  | jjd | jjd d S )Nr   )r   rU   ZwriteFaxr   getvaluer   r   )r#   r'   r'   r(   r     s    zPMLFaxSendThread.write_stream)r@   r@   NFr@   NN)Fr   )r
   )rL   rM   rN   r    rs   r   r   r   r   rd   r   r   r   r   r   r   r   r   r'   r'   r'   r(   rA   *  s(    
    x

	rA   )Qsysr   os.pathr   rk   rS   Zbase.sixext.movesr   ior   Zbase.gZ
base.codesbaser   r   r   r   Zprntr	   r   ZPAGE_FLAG_NONEr   ZPAGE_FLAG_END_PAGEr   r   r   r   r   ZMFPDTF_RASTER_BITMAPZMFPDTF_RASTER_GRAYMAPZMFPDTF_RASTER_MHZMFPDTF_RASTER_MRZMFPDTF_RASTER_MMRZMFPDTF_RASTER_RGBZMFPDTF_RASTER_YCC411ZMFPDTF_RASTER_JPEGZMFPDTF_RASTER_PCLZMFPDTF_RASTER_NOTZ
DT_UNKNOWNr   ZDT_SCANNED_IMAGESr   ZDT_DEMO_PAGESZDT_SPEED_DIALSZDT_FAX_LOGSZDT_CFG_PARMSZDT_LANG_STRSZDT_JUNK_FAX_CSIDSZDT_REPORT_STRSZDT_FONTSZDT_TTI_BITMAPZDT_COUNTERSZDT_DEF_PARMSZDT_SCAN_OPTIONSZDT_FW_JOB_TABLEr   r   r   r   ZIMAGE_VARIANT_HEADER_SIZEr   r   ZSOP_RECORD_SIZEZRASTER_RECORD_SIZEZEOP_RECORD_SIZEZDIAL_STRING_RECORD_SIZEZSRC_UNKNOWNr   ZSRC_SCANNERZSRC_HOST_THEN_SCANNERZSRC_SCANNER_THEN_HOSTZTTI_NONEr   ZTTI_OVERLAYED_ON_IMAGEr   r   r   rT   rR   rt   rA   r'   r'   r'   r(   <module>   s   WV