
    Hij-              
          U d Z ddlZddlmZ ddlmZmZmZmZm	Z	 ddl
mZ  ej                  e      ZdZdZdZd	Zd
ZdZeeez  z  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Z0g dZ1e2e	e3e3f      e4d <   da5ee	e3ee3   f      e4d!<   d"e	e3ee3   f   fd#Z6d$Z7d%Z8d&Z9d'Z:d(Z;d)Z<d*Z=d+Z>d,e?d"efd-Z@d.ed/e?d"dfd0ZAd.ed1e?d"dfd2ZBd.ed1e?d3e3d"dfd4ZCd.ed1e?d5e3d"dfd6ZDd.ed1e?d7e2d"dfd8ZEd.ed9e3d:ee3ef   d;ee3e3f   d"df
d<ZFd9e3d:ee3ef   d;ee3e3f   d"e?fd=ZGd>eHd?e3d"e3fd@ZI G dA dB      ZJy)CuG   PDF 렌더러 — 웹북 에피소드를 장페이지 PDF로 렌더링.    N)Path)AnyDictListOptionalTuple)FPDFg)\x@   $   iH  i@  i  iP  iPF  g      !@
            g%@	                              H   ))AppleSDGothicz*/System/Library/Fonts/AppleSDGothicNeo.ttc)NanumGothicz//usr/share/fonts/truetype/nanum/NanumGothic.ttf)NotoSansCJKz6/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc)r   z1/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc)MalgunGothiczC:/Windows/Fonts/malgun.ttf_KOREAN_FONT_CANDIDATES_resolved_fontreturnc                      t         t         S t        D ]A  \  } }t        |      j                         s t        j                  d| |       | |fa t         c S  t        j                  d       da t         S )zFind the first available Korean font. Returns (font_name, font_path).

    If no Korean font is found, returns ("Helvetica", None) as a fallback.
    z'PDF renderer: using Korean font %s (%s)zPDF renderer: no Korean font found, falling back to Helvetica. Korean text will not render correctly. Install fonts-nanum or fonts-noto-cjk on Linux.)	HelveticaN)r    r   r   existsloggerinfowarning)namepaths     N/Users/manta/Documents/Projects/TheRoad-I1/backend/app/modules/pdf_renderer.py_resolve_korean_fontr+   B   sn     !-
d:KKA4N"D\N!!	 . NN	:
 )N    )x   r-   r-   )   r.   r.   )r   r   r   )Z   r/   r/   )   r0   r0   )#   r1   r1   )d   r2   r2   )   r3   r3   page_heightc                     t        dt        | f      }|j                  d       t               \  }}|r|j	                  |d|       |j                  |t               |j                  t        t        t               |j                          |S )Npt)unitformatF)auto size)r	   WEBBOOK_PAGE_WIDTH_PTset_auto_page_breakr+   add_fontset_fontFONT_SIZE_BODYset_marginsWEBBOOK_SIDE_MARGIN_PTWEBBOOK_TOP_MARGIN_PTadd_page)r4   pdf	font_name	font_paths       r*   _new_webbook_pdfrI   e   sz    
D"7!E
FC'/1IyYI.LLL0OO 57M LLNJr,   rF   r<   c                 D    t               \  }}| j                  ||       y)z@Set font using the resolved Korean font (or Helvetica fallback).r;   N)r+   r@   )rF   r<   rG   _s       r*   	_set_fontrL   s   s    ')LIqLLL&r,   	content_wc                     | j                         }t        |dz  z   }d} | j                  t          | j	                  ||z
  |||z   |       | j                  t               y)z,Draw a subtle divider line between sections.r   (   N)get_yrC   set_draw_colorCOLOR_DIVIDERlinelnSPACING_BEFORE_SECTION_TITLE)rF   rM   ycenter_x	line_halfs        r*   _draw_section_dividerrY   y   sY    		A%	A5HIC&HHX	!1h&:A>FF'(r,   section_titlec                     t        | t                | j                  t          | j	                  |t
        |d       | j                  t               y)z0Draw section title centered with accent styling.CalignN)rL   FONT_SIZE_SECTION_TITLEset_text_colorCOLOR_SECTION_TITLE
multi_cellLINE_HEIGHT_SECTION_TITLErT   SPACING_AFTER_SECTION_TITLE)rF   rM   rZ   s      r*   _draw_section_titlere      sB     c*+C+,NN97cNRFF&'r,   captionc                     t        | t                | j                  t          | j	                  |t
        |d       | j                  t               y)z0Draw image caption in smaller italic-style text.r\   r]   N)rL   FONT_SIZE_CAPTIONr`   COLOR_CAPTIONrb   LINE_HEIGHT_CAPTIONrT   SPACING_AFTER_CAPTION)rF   rM   rf   s      r*   _draw_image_captionrl      sA     c$%C&NN917#NFFF !r,   
paragraphsc                     t        | t                | j                  t          |D ]0  }| j	                  |t
        |d       | j                  t               2 y)zDraw body paragraphs.Jr]   N)rL   rA   r`   
COLOR_BODYrb   LINE_HEIGHT_BODYrT   SPACING_AFTER_PARAGRAPH)rF   rM   rm   	paragraphs       r*   _draw_paragraphsrt      sJ     c>"C
#	y"2ISI&'  r,   package_titleepisodesection_imagesc                J   t         t        dz  z
  }t         t        z
  dz  }| j                  t        t               t        | t                | j                  t          | j                  |t        | dd       | j                  t               t        | t                | j                  t          | j                  |t        d|d    d       | j                  t                 | j                  t"          t        | t$               | j                  |t&        |d   d       | j                  t(               t        | t*                | j                  t,          | j                  |t.        |d	   d       | j                  t0               t3        | ||j5                  d
g              t7        |j5                  dg             D ]  \  }}|d   }|j5                  |      }	t9        |j5                  dd            }
|j5                  dd      }|j5                  dd      }|dkD  rt;        | |       |rt=        | ||       |j5                  dg       }|rt3        | ||       t        | t>                | j                  t@          t7        |j5                  dg       d      D ]  \  }}| j                  |tB        |d       | j                  tD               ||
k(  s:|	s=tG        |	      jI                         sW| jK                  tM        |	      |t        tN               | j                  tN        tP        z          |stS        | ||        |j5                  dg       }|rt3        | ||       | j                  tT                t3        | ||j5                  dg              y )Nr   z WEBBOOKLr]   zEPISODE episode_numberr\   titlesubtitleopener_paragraphssectionsstill_idimage_after_paragraph   rZ   r:   image_captionr   opening_paragraphsrm   )startro   )xwhclosing_paragraphscloser_paragraphs)+r=   rC   WEBBOOK_IMAGE_WIDTH_PTset_xyrD   rL   FONT_SIZE_HEADERr`   COLOR_HEADERrb   LINE_HEIGHT_HEADERrT   SPACING_AFTER_HEADERFONT_SIZE_EPISODE_LABELCOLOR_EPISODE_LABELLINE_HEIGHT_EPISODE_LABELSPACING_AFTER_EPISODE_LABELCOLOR_TITLEFONT_SIZE_TITLELINE_HEIGHT_TITLESPACING_AFTER_TITLEFONT_SIZE_SUBTITLECOLOR_SUBTITLELINE_HEIGHT_SUBTITLESPACING_AFTER_SUBTITLErt   get	enumerateintrY   re   rA   rp   rq   rr   r   r$   imagestrWEBBOOK_IMAGE_HEIGHT_PTSPACING_AFTER_IMAGErl   SPACING_AFTER_SECTION)rF   ru   rv   rw   rM   image_xsection_idxsectionr   
image_pathimage_afterrZ   r   openingparagraph_indexrs   closings                    r*   _draw_webbook_episoder      s<    &)?!)CDI$'==BG JJ%'<=c#$C%NN90]O82LTWNXFF  c*+C+,NN!
7+,-.	   FF&' C$c?#NN9/1ANMFF c%&C'NN92GJ4GsNSFF!" S)W[[1Db%IJ !*'++j"*E FW:&#''1
'++&=qABOR8OR8 ?!#y1 Y> ++2B7S)W5 	#~&J'*3KKb)+
&OY NN9&6	NMFF*+;.$++-		
O,-	   .1DDE 'YF'+
, ++2B7S)W5$%c !Gh S)W[[1Db%IJr,   c                     t        t              }|j                         5 }t        || ||       |j	                         t
        z   }d d d        t        t        t        t                    S # 1 sw Y   'xY w)Nru   rv   rw   )	rI   WEBBOOK_MAX_PAGE_HEIGHT_PToffset_renderingr   rP   SPACING_PAGE_BOTTOMmaxWEBBOOK_MIN_PAGE_HEIGHT_PTmin)ru   rv   rw   rF   dummy	estimateds         r*   _estimate_episode_page_heightr     so     5
6C				5')		
 KKM$77	 
  "&	2  
 	s   'A--A6rz   episode_titlec                     dj                  d |D              j                  d      j                         }|sd| d}d| dd| S )Nr:   c              3   D   K   | ]  }|j                         r|nd   yw)rK   N)isalnum).0chars     r*   	<genexpr>z%_episode_file_stub.<locals>.<genexpr>  s!      4ADC'Ms    rK   episode_02dweb_episode_)joinstriplower)rz   r   cleaneds      r*   _episode_file_stubr     sY    gg 4A eCj  ^C01.-Qwi88r,   c                   v    e Zd ZdZ	 ddeeef   deeef   dededef
dZdeeef   deeef   d	ede	e   fd
Z
y)PDFRendereru"   웹북 에피소드 PDF 렌더러.episode_dataimagesoutput_pathru   r!   c                     t        |||      }t        |      }t        ||||       |j                  j	                  dd       |j                  t        |             |S )aZ  Render one webbook episode as a long-page PDF.

        Args:
            episode_data: Single episode dict from webbook package.
            images: Map of still_id -> file path string.
            output_path: Where to save the PDF.
            package_title: Series title for the header.

        Returns:
            The output path.
        r   Tparentsexist_ok)r   rI   r   parentmkdiroutputr   )selfr   r   r   ru   r4   rF   s          r*   render_episodezPDFRenderer.render_episode&  si    $ 4' !

 {+' !		
 	   =

3{#$r,   package
output_dirc                    |j                  dd      }|j                  dd       g }|j                  dg       D ]B  }t        |d   |d         }|| dz  }| j                  ||||	       |j	                  |       D |S )
a  Render all webbook episodes as PDFs.

        Args:
            package: Full webbook package dict.
            images: Map of still_id -> file path string.
            output_dir: Directory for PDF output.

        Returns:
            List of output paths.
        series_titler:   Tr   episodesrz   r{   z.pdf)r   r   r   ru   )r   r   r   r   append)	r   r   r   r   ru   pathsrv   stubpdf_paths	            r*   
render_allzPDFRenderer.render_allH  s       NB75{{:r2G%()77+;D "tfDM1H$$+	    LL" 3 r,   N)r:   )__name__
__module____qualname____doc__r   r   r   r   r   r   r    r,   r*   r   r   #  s    ,   38n  S#X  	 
   
 D!c3h! S#X! 	!
 
d!r,   r   )Kr   loggingpathlibr   typingr   r   r   r   r   fpdfr	   	getLoggerr   r%   r=   rD   rC   r   SCENE_TARGET_WSCENE_TARGET_Hr   r   r   r   r   r   r   r_   rA   rh   r   r   r   r   rc   rq   rj   r   r   r   r   rr   r   r   rU   rd   rk   r   r   listr   __annotations__r    r+   r   r   r   r   ra   rp   ri   rR   floatrI   rL   rY   re   rl   rt   r   r   r   r   r   r   r,   r*   <module>r      s   M   3 3 			8	$      0N^4ST ! "                       !     2 eCHo.  7;sHSM123 :eC#$67 2 % " 
% D '4 'u ' ')t ) )$ )(	((03(	("	""*-"	"(	((-1(	(`K	`K `K #s(^	`K
 cN`K 
`KF #s(^ cN	
 *9s 93 93 9F Fr,   