정해진 PPT 템플릿(로고 · 색 · 머리말 · 꼬리말이 박힌 마스터와 레이아웃)에 내용을 채워 수십 장을 기계로 만드는 작업은, 기존 파일의 XML 을 다루는 순간 몇 가지 정해진 함정에 걸린다. 아래는 그 함정과 우회 방법이다.
PPTX 는 ZIP 으로 묶인 OOXML 문서다. 압축을 풀면 ppt/slides/slideN.xml, ppt/slideLayouts/, ppt/slideMasters/, ppt/media/, 그리고 각각의 _rels/ 가 나온다. 라이브러리를 쓰든 XML 을 직접 쓰든 최종 결과물은 같은 구조다.
도형은 만들어졌는데 글자가 렌더되지 않으면 <p:txBody> 래퍼를 빠뜨렸을 가능성이 높다. <a:bodyPr> · <a:lstStyle> · <a:p> 는 반드시 <p:txBody> 안에 있어야 한다.
<p:sp>
<p:nvSpPr>
<p:cNvPr id="5" name="본문"/>
<p:cNvSpPr txBox="1"/>
<p:nvPr/>
</p:nvSpPr>
<p:spPr>
<a:xfrm><a:off x="457200" y="1600200"/><a:ext cx="8229600" cy="3600000"/></a:xfrm>
<a:prstGeom prst="rect"><a:avLst/></a:prstGeom>
</p:spPr>
<p:txBody>
<a:bodyPr wrap="square"/>
<a:lstStyle/>
<a:p><a:r><a:rPr lang="ko-KR" sz="1100"/><a:t>본문 내용</a:t></a:r></a:p>
</p:txBody>
</p:sp>
빌드 자체는 성공하고 파일도 열리므로 오류로 드러나지 않는다. 렌더해 보기 전에는 알 수 없는 종류의 결함이다.
슬라이드에 제목 placeholder 를 두었는데도 "마스터 제목 스타일 편집" 이나 페이지 번호 자리의 # 이 내용과 겹쳐 보이는 경우가 있다. LibreOffice 로 렌더하거나 PDF 로 변환할 때 특히 잘 나타난다. 렌더러가 레이아웃 · 마스터의 placeholder 를 슬라이드 쪽 정의와 별개로 한 번 더 그리기 때문이다.
placeholder 를 슬라이드와 레이아웃 양쪽에 맞춰 넣는 시도, 레이아웃의 placeholder 를 화면 밖 좌표로 밀어내는 시도, 마스터의 titleStyle 을 비우는 시도는 렌더러에 따라 통하기도 하고 통하지 않기도 한다.
확실하게 통하는 방법은 placeholder 를 쓰지 않는 것이다.
도형 순서(z-order)는 XML 에 나오는 순서다. 덮개 사각형이 텍스트 박스보다 앞에 와야 한다. 다만 이 방법은 표지처럼 배경 이미지나 로고가 있는 슬라이드에서 그 요소까지 같이 가려 버리므로, 덮개는 콘텐츠 슬라이드에만 쓰고 크기를 필요한 만큼만 잡는다.
원하는 레이아웃의 슬라이드를 복제해 내용만 갈아 끼우면 서식이 그대로 유지된다. 복제 시 두 가지가 문제를 일으킨다.
ppt/_rels/presentation.xml.rels 와 ppt/presentation.xml 의 <p:sldIdLst> 를 함께 고쳐야 한다. sldId 의 id 값은 문서 안에서 고유해야 하고, 복제한 슬라이드를 그대로 두면 모두 같은 값이 되어 파워포인트가 파일을 복구 모드로 연다. r:id 도 각기 달라야 한다.
<p:sldIdLst>
<p:sldId id="256" r:id="rId2"/>
<p:sldId id="257" r:id="rId3"/>
<p:sldId id="258" r:id="rId4"/>
</p:sldIdLst>
그리고 ppt/media/ 에 넣은 이미지가 아직 어느 슬라이드에서도 참조되지 않으면, 미사용 리소스를 지우는 정리 단계에서 같이 사라진다. 이미지를 복사한 뒤 참조를 거는 것이 아니라, 참조를 건 다음 정리를 돌린다.
XML 이 유효한 것과 사람이 보기에 멀쩡한 것은 다르다. 텍스트 넘침, 도형이 꼬리말과 겹침, 표가 슬라이드 밖으로 나감, 줄바꿈 위치는 그려 보기 전에는 판별할 수 없다. 자동 생성의 마지막 단계는 언제나 렌더 확인이다.
soffice --headless --convert-to pdf --outdir ./out deck.pptx
pdftoppm -jpeg -r 96 ./out/deck.pdf ./out/slide
한 장씩 열어 보는 대신 전체를 한 장으로 붙여 훑으면 빠르다.
montage ./out/slide-*.jpg -tile 5x -geometry +4+4 ./out/grid.jpg
LibreOffice 렌더 결과는 파워포인트와 완전히 같지 않다. 글꼴 대체 때문에 줄바꿈 위치가 달라지므로, 넘침 여부는 여유를 두고 판단한다.
한국어 텍스트는 실행마다 글꼴을 명시한다. latin · ea · cs 를 함께 지정해야 영문과 한글이 따로 놀지 않는다.
<a:rPr lang="ko-KR" sz="1100">
<a:latin typeface="맑은 고딕"/>
<a:ea typeface="맑은 고딕"/>
<a:cs typeface="맑은 고딕"/>
</a:rPr>
렌더 환경에 해당 글꼴이 없으면 대체 글꼴로 그려진다. 리눅스에서 확인할 때는 Noto Sans CJK KR 을 설치해 둔다.
이모지는 글꼴에 따라 두부 문자로 깨진다. 강조가 필요하면 도형이나 색으로 처리하고 문서 안에 이모지를 넣지 않는다.
OOXML 좌표는 EMU(English Metric Unit)다. 글자 크기는 100분의 1 포인트 단위라 sz="1100" 이 11pt 다. 이 둘을 혼동하면 도형이 화면 밖으로 나가거나 글자가 보이지 않을 정도로 작아진다.
| 단위 | 환산 |
|---|---|
| 1 inch | 914,400 EMU |
| 1 cm | 360,000 EMU |
| 1 pt | 12,700 EMU |
| 글자 크기 1pt | sz="100" |
16:9 슬라이드 기본 크기는 13.333 × 7.5 인치, 즉 12,192,000 × 6,858,000 EMU 다.