kordoc 4.24.3 → 4.24.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/README.md +5 -5
  2. package/dist/{-Q56U3KCA.js → -WND2HWVH.js} +11 -11
  3. package/dist/{chunk-3EWXRIPH.js → chunk-3LSHLWTX.js} +3 -3
  4. package/dist/{chunk-HNX2I7D6.js → chunk-44E52JJ7.js} +2 -2
  5. package/dist/{chunk-XNNMMYFO.js → chunk-47MTLP4U.js} +2 -2
  6. package/dist/{chunk-42FSKT7R.js → chunk-4XVL3OBP.js} +2 -2
  7. package/dist/{chunk-OAOM7IEI.js → chunk-5AHG3XY3.js} +11 -11
  8. package/dist/{chunk-6ZRZLV3J.cjs → chunk-6A4KYMQR.cjs} +2 -2
  9. package/dist/{chunk-6ZRZLV3J.cjs.map → chunk-6A4KYMQR.cjs.map} +1 -1
  10. package/dist/{chunk-EWCJCWTT.js → chunk-6CPBNK5O.js} +2 -2
  11. package/dist/{chunk-FZT34MUI.js → chunk-A5JDO52L.js} +4 -4
  12. package/dist/{chunk-4X73CGIL.js → chunk-AKIJTKEA.js} +2 -2
  13. package/dist/{chunk-YG4YOPK6.cjs → chunk-BODFTRWA.cjs} +3 -3
  14. package/dist/{chunk-YG4YOPK6.cjs.map → chunk-BODFTRWA.cjs.map} +1 -1
  15. package/dist/{chunk-XAZ5RGVG.js → chunk-BYYZUFPC.js} +11 -8
  16. package/dist/chunk-BYYZUFPC.js.map +1 -0
  17. package/dist/{chunk-Q2QKRE4P.js → chunk-D4YWVZHD.js} +2 -2
  18. package/dist/{chunk-33NZN73M.js → chunk-DTADAHJD.js} +2 -2
  19. package/dist/{chunk-XZOAE2Q7.js → chunk-E7N6BUJT.js} +12 -9
  20. package/dist/chunk-E7N6BUJT.js.map +1 -0
  21. package/dist/{chunk-I2QETSZN.js → chunk-FK3JPTHI.js} +2 -2
  22. package/dist/{chunk-AEEQN6L3.js → chunk-GGVHKYKZ.js} +2 -2
  23. package/dist/{chunk-PMX5CPK5.js → chunk-JHUW5PKO.js} +8 -7
  24. package/dist/chunk-JHUW5PKO.js.map +1 -0
  25. package/dist/{chunk-VFEI2GIE.cjs → chunk-KFQNG2EA.cjs} +3 -3
  26. package/dist/{chunk-VFEI2GIE.cjs.map → chunk-KFQNG2EA.cjs.map} +1 -1
  27. package/dist/{chunk-PHZDAHZC.js → chunk-LBOXKGAH.js} +3 -3
  28. package/dist/{chunk-JILIA5EV.cjs → chunk-LJ7U7MFN.cjs} +31 -28
  29. package/dist/chunk-LJ7U7MFN.cjs.map +1 -0
  30. package/dist/{chunk-W6O7KBOD.js → chunk-MC4DPT4I.js} +2 -2
  31. package/dist/{chunk-KXHNIHLC.js → chunk-MMPBJGWQ.js} +2 -2
  32. package/dist/{chunk-NKDPCALC.js → chunk-QTJTBCTZ.js} +4 -4
  33. package/dist/{chunk-N65EY5BI.cjs → chunk-TPKP3WQU.cjs} +6 -6
  34. package/dist/{chunk-N65EY5BI.cjs.map → chunk-TPKP3WQU.cjs.map} +1 -1
  35. package/dist/{chunk-EEXIFCXC.js → chunk-VBY3JQL2.js} +2 -2
  36. package/dist/{chunk-TZ753B6A.js → chunk-WMDGGQXJ.js} +2 -2
  37. package/dist/{chunk-HTG3VVET.cjs → chunk-WN5X4DT3.cjs} +24 -24
  38. package/dist/{chunk-HTG3VVET.cjs.map → chunk-WN5X4DT3.cjs.map} +1 -1
  39. package/dist/{chunk-HU7POUBS.js → chunk-YBCW544D.js} +2 -2
  40. package/dist/{chunk-J45OVEUM.js → chunk-YEYNBH5W.js} +112 -23
  41. package/dist/chunk-YEYNBH5W.js.map +1 -0
  42. package/dist/chunks-2UDUNVGQ.js +10 -0
  43. package/dist/cli.js +30 -30
  44. package/dist/{formula-2BPHF6O7.cjs → formula-6DJAY3KI.cjs} +9 -9
  45. package/dist/{formula-2BPHF6O7.cjs.map → formula-6DJAY3KI.cjs.map} +1 -1
  46. package/dist/{formula-IREEAC4T.js → formula-MPBZ7OMN.js} +3 -3
  47. package/dist/{formula-EA5GDCUD.js → formula-NA3LD35B.js} +4 -4
  48. package/dist/{image-ocr-LGOFUS3O.js → image-ocr-6TGDXUAS.js} +9 -9
  49. package/dist/{image-ocr-CCTE7HX3.cjs → image-ocr-REM4LZKX.cjs} +17 -17
  50. package/dist/{image-ocr-CCTE7HX3.cjs.map → image-ocr-REM4LZKX.cjs.map} +1 -1
  51. package/dist/{image-ocr-JQJC5HWK.js → image-ocr-THA5BASF.js} +6 -6
  52. package/dist/index.cjs +740 -650
  53. package/dist/index.cjs.map +1 -1
  54. package/dist/index.js +118 -28
  55. package/dist/index.js.map +1 -1
  56. package/dist/mcp.js +23 -23
  57. package/dist/{model-bundle-YW62Y6UD.js → model-bundle-3YDTJ6EQ.js} +5 -5
  58. package/dist/{models-AAL3IS2R.js → models-M7AX7VIN.js} +5 -5
  59. package/dist/{parse-worker-v2-3JAHV7NY.js → parse-worker-v2-3ZMFWDFW.js} +12 -12
  60. package/dist/{parser-HE45CCSG.cjs → parser-GIDYL5LH.cjs} +158 -158
  61. package/dist/{parser-HE45CCSG.cjs.map → parser-GIDYL5LH.cjs.map} +1 -1
  62. package/dist/{parser-ZBP5GOQK.js → parser-MNNJSFEZ.js} +9 -9
  63. package/dist/{parser-4FCKKJ2N.js → parser-TD4VZDGY.js} +12 -12
  64. package/dist/{pdf-ocr-HFAEOA7W.js → pdf-ocr-5HEVZKG5.js} +6 -6
  65. package/dist/{pdf-ocr-Q4TPGDDI.js → pdf-ocr-6BAOQ6CY.js} +9 -9
  66. package/dist/pdf-ocr-NOSNTEDS.cjs +31 -0
  67. package/dist/{pdf-ocr-7MDCLWAA.cjs.map → pdf-ocr-NOSNTEDS.cjs.map} +1 -1
  68. package/dist/{profile-io-EDQTKLLL.js → profile-io-H4WQIGN6.js} +3 -3
  69. package/dist/{rasterize-VD2XGHUJ.js → rasterize-EOPWJWBO.js} +3 -3
  70. package/dist/{redact-doc-TBIBQJCT.js → redact-doc-BBZVAA3I.js} +11 -11
  71. package/dist/{render-J5KAZAQH.js → render-ZZ4CGJ6J.js} +7 -7
  72. package/dist/seal-RRYFKTEQ.js +10 -0
  73. package/dist/{setup-5LYHCQRU.js → setup-UIPKBNLA.js} +3 -3
  74. package/dist/visual-DLLRTF6C.js +21 -0
  75. package/dist/{watch-YP4IWM75.js → watch-OXQ6O5HD.js} +12 -12
  76. package/package.json +1 -1
  77. package/dist/chunk-J45OVEUM.js.map +0 -1
  78. package/dist/chunk-JILIA5EV.cjs.map +0 -1
  79. package/dist/chunk-PMX5CPK5.js.map +0 -1
  80. package/dist/chunk-XAZ5RGVG.js.map +0 -1
  81. package/dist/chunk-XZOAE2Q7.js.map +0 -1
  82. package/dist/chunks-REYSCBPB.js +0 -10
  83. package/dist/pdf-ocr-7MDCLWAA.cjs +0 -31
  84. package/dist/seal-H2JNAZU7.js +0 -10
  85. package/dist/visual-7EO6GR3M.js +0 -21
  86. /package/dist/{-Q56U3KCA.js.map → -WND2HWVH.js.map} +0 -0
  87. /package/dist/{chunk-3EWXRIPH.js.map → chunk-3LSHLWTX.js.map} +0 -0
  88. /package/dist/{chunk-HNX2I7D6.js.map → chunk-44E52JJ7.js.map} +0 -0
  89. /package/dist/{chunk-XNNMMYFO.js.map → chunk-47MTLP4U.js.map} +0 -0
  90. /package/dist/{chunk-42FSKT7R.js.map → chunk-4XVL3OBP.js.map} +0 -0
  91. /package/dist/{chunk-OAOM7IEI.js.map → chunk-5AHG3XY3.js.map} +0 -0
  92. /package/dist/{chunk-EWCJCWTT.js.map → chunk-6CPBNK5O.js.map} +0 -0
  93. /package/dist/{chunk-FZT34MUI.js.map → chunk-A5JDO52L.js.map} +0 -0
  94. /package/dist/{chunk-4X73CGIL.js.map → chunk-AKIJTKEA.js.map} +0 -0
  95. /package/dist/{chunk-Q2QKRE4P.js.map → chunk-D4YWVZHD.js.map} +0 -0
  96. /package/dist/{chunk-33NZN73M.js.map → chunk-DTADAHJD.js.map} +0 -0
  97. /package/dist/{chunk-I2QETSZN.js.map → chunk-FK3JPTHI.js.map} +0 -0
  98. /package/dist/{chunk-AEEQN6L3.js.map → chunk-GGVHKYKZ.js.map} +0 -0
  99. /package/dist/{chunk-PHZDAHZC.js.map → chunk-LBOXKGAH.js.map} +0 -0
  100. /package/dist/{chunk-W6O7KBOD.js.map → chunk-MC4DPT4I.js.map} +0 -0
  101. /package/dist/{chunk-KXHNIHLC.js.map → chunk-MMPBJGWQ.js.map} +0 -0
  102. /package/dist/{chunk-NKDPCALC.js.map → chunk-QTJTBCTZ.js.map} +0 -0
  103. /package/dist/{chunk-EEXIFCXC.js.map → chunk-VBY3JQL2.js.map} +0 -0
  104. /package/dist/{chunk-TZ753B6A.js.map → chunk-WMDGGQXJ.js.map} +0 -0
  105. /package/dist/{chunk-HU7POUBS.js.map → chunk-YBCW544D.js.map} +0 -0
  106. /package/dist/{chunks-REYSCBPB.js.map → chunks-2UDUNVGQ.js.map} +0 -0
  107. /package/dist/{formula-IREEAC4T.js.map → formula-MPBZ7OMN.js.map} +0 -0
  108. /package/dist/{formula-EA5GDCUD.js.map → formula-NA3LD35B.js.map} +0 -0
  109. /package/dist/{image-ocr-LGOFUS3O.js.map → image-ocr-6TGDXUAS.js.map} +0 -0
  110. /package/dist/{image-ocr-JQJC5HWK.js.map → image-ocr-THA5BASF.js.map} +0 -0
  111. /package/dist/{model-bundle-YW62Y6UD.js.map → model-bundle-3YDTJ6EQ.js.map} +0 -0
  112. /package/dist/{models-AAL3IS2R.js.map → models-M7AX7VIN.js.map} +0 -0
  113. /package/dist/{parse-worker-v2-3JAHV7NY.js.map → parse-worker-v2-3ZMFWDFW.js.map} +0 -0
  114. /package/dist/{parser-ZBP5GOQK.js.map → parser-MNNJSFEZ.js.map} +0 -0
  115. /package/dist/{parser-4FCKKJ2N.js.map → parser-TD4VZDGY.js.map} +0 -0
  116. /package/dist/{pdf-ocr-HFAEOA7W.js.map → pdf-ocr-5HEVZKG5.js.map} +0 -0
  117. /package/dist/{pdf-ocr-Q4TPGDDI.js.map → pdf-ocr-6BAOQ6CY.js.map} +0 -0
  118. /package/dist/{profile-io-EDQTKLLL.js.map → profile-io-H4WQIGN6.js.map} +0 -0
  119. /package/dist/{rasterize-VD2XGHUJ.js.map → rasterize-EOPWJWBO.js.map} +0 -0
  120. /package/dist/{redact-doc-TBIBQJCT.js.map → redact-doc-BBZVAA3I.js.map} +0 -0
  121. /package/dist/{render-J5KAZAQH.js.map → render-ZZ4CGJ6J.js.map} +0 -0
  122. /package/dist/{seal-H2JNAZU7.js.map → seal-RRYFKTEQ.js.map} +0 -0
  123. /package/dist/{setup-5LYHCQRU.js.map → setup-UIPKBNLA.js.map} +0 -0
  124. /package/dist/{visual-7EO6GR3M.js.map → visual-DLLRTF6C.js.map} +0 -0
  125. /package/dist/{watch-YP4IWM75.js.map → watch-OXQ6O5HD.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/render/svg-render.ts","../src/render/layout.ts","../src/hwpx/hft-latin-widths.ts","../src/hwpx/face-width-fix.ts","../src/hwpx/seoul-font-widths.ts","../src/hwpx/font-metrics.ts","../src/hwpx/text-metrics.ts","../src/hwpx/para-heading.ts","../src/hwpx/notes.ts","../src/render/para-model.ts","../src/render/reflow-tables.ts","../src/render/para-number.ts","../src/render/reflow-cache.ts","../src/render/reflow-fragments.ts","../src/render/reflow-borders.ts","../src/render/reflow.ts","../src/render/font-env.ts","../src/render/scene.ts","../src/render/page-stories.ts","../src/render/table-pages.ts","../src/render/shape-geometry.ts","../src/render/object-anchor.ts","../src/render/equation-text.ts","../src/hwpx/equation.ts","../src/hwp5/equation.ts","../src/render/svg-content.ts","../src/hwp5/record.ts","../src/toc-entry.ts","../src/hwp5/images.ts","../src/hwp5/aes.ts","../src/hwp5/crypto.ts","../src/hwp5/cfb-lenient.ts","../src/hwp5/pw-crypto.ts","../src/hwp5/page-boundary.ts","../src/hwp5/table-ids.ts","../src/hwp5/numbering.ts","../src/hwp5/ir-assemble.ts","../src/hwp5/body.ts","../src/hwp5/parser.ts","../src/render/hwp5-scene.ts","../src/render/document.ts","../src/detect.ts","../src/render/html.ts","../src/print/renderer.ts","../src/render/pdf.ts","../src/render/regions.ts"],"sourcesContent":["/**\n * 레이아웃 보존 렌더 — HWPX 조판 캐시(lineseg·cellAddr·hp:pos)를 SVG 절대배치로 그린다.\n *\n * 조판 엔진 없음: 한컴이 저장 시 기록한 좌표를 그대로 사용한다. 따라서\n * 한컴(또는 조판 캐시를 기록하는 편집기)에서 저장한 파일만 렌더 가능 —\n * markdownToHwpx 산출물엔 linesegarray가 없어 KordocError를 던진다.\n *\n * 좌표 산식(실측 검증 — .claude/plans/render-poc/findings.md):\n * - 단위 HWPUNIT(1/7200in), pt = /100. 최상위 문단 lineseg = 본문영역 로컬,\n * 셀 문단 = 셀 로컬. PARA 밀어내기 개체 anchor = 호스트vp − (omTop+h+omBottom) 역산.\n * - horzsize는 줄 \"영역\" 폭(텍스트 폭 아님) — 마지막 줄이 아닌 줄은 원본 줄바꿈에\n * 맞춰 textLength로 고정하고, 마지막 줄만 paraPr 정렬(LEFT 자연폭/CENTER/RIGHT/배분)을 적용.\n * - 좌표 속성엔 uint32로 저장된 음수가 섞여 있다(toInt32 필수).\n * - 표 열은 span 제약 경계 전파로, 행은 rs=1 max + 콘텐츠 초과 성장으로 푼다.\n *\n * 페이지: 최상위 lineseg vertpos는 페이지 로컬(페이지마다 0부터 리셋)이므로 역행\n * 지점을 페이지 경계로 감지, 전 페이지를 세로 스택으로 그린다(페이지별 흰 배경 +\n * 클립). 페이지에 걸친 표는 시작 페이지에서 잘린다(조판 캐시에 분할점이 없음).\n *\n * 범위: section0 한정(다중 구역은 첫 구역만), 수식·그리기개체 도형은 미지원(경고 수집).\n */\n\nimport JSZip from \"jszip\"\nimport { KordocError, compareSectionPaths, precheckZipSize } from \"../utils.js\"\nimport { createXmlParser, findChildByLocalName, MAX_DECOMPRESS_SIZE, MAX_ZIP_ENTRIES } from \"../hwpx/parser-shared.js\"\nimport { toInt32, tableColumnBoundaries, type SpanConstraint } from \"./layout.js\"\nimport { measureTextWidth, faceClassOf, type WrapMode } from \"../hwpx/text-metrics.js\"\nimport { parseRenderStyles, hwpxAppMajor, hwpxAppBuild, DEFAULT_CHAR, type RenderStyles, type RenderBorderEdge, type RenderParaGeom } from \"./head-styles.js\"\nimport { reflowSection, glyphWidth } from \"./reflow.js\"\nimport { hasKoPubSubst, kopubSubstituted } from \"./font-env.js\"\nimport { mapPuaText } from \"../shared/pua.js\"\nimport { latexToPlain } from \"./equation-text.js\"\nimport { hwpEquationToLatex } from \"../hwp5/equation.js\"\nimport { RegionCollector, type PageBBox, type RenderRegion, type RenderScene } from \"./scene.js\"\nimport { formatHeadNumber, nextParaNumber, type NumberCounters } from \"./para-number.js\"\nimport { ln, elements, num, findFirst, type Seg, type ParaChar, OBJ_TAGS, FORM_TAGS, type ParaObj, type ParaModel, buildPara, prepareDeletedRanges, tabAdvance, type ExtentMemo, cellContentExtent, collectCells, measureTableHeight, measureTableRowHeights, captionOf, captionExtra, cellColumns } from \"./para-model.js\"\nimport { endNoteLayout, footNoteStories, pageStories } from \"./page-stories.js\"\nimport { cellLineBoxes, planTableRows, type CellFloatSpan, type RowPiece } from \"./table-pages.js\"\nimport { subFloatBottoms } from \"./reflow-tables.js\"\nimport { mulAffine, objectGeometry, renderingMatrix, shapeGeometry, rotatedBounds, SHAPE_TAGS, type Affine, type RegionRotation } from \"./shape-geometry.js\"\nimport { anchorObject, linePushedBy } from \"./object-anchor.js\"\nimport { readZipEntry } from \"../hwpx/parser-shared.js\"\nimport { escapeXml, pt, ptNum, pageNo, bboxOf, regionOpenTag, parentId, emit, warnOnce, drawPara, cellParaTop, type PageGeom, type Ctx, type PaintJob } from \"./svg-content.js\"\nexport { escapeXml } from \"./svg-content.js\"\nexport { buildPara, measureTableHeight, tabAdvance, type Seg, type ParaChar, type ParaModel, type ExtentMemo } from \"./para-model.js\"\n\nexport interface RenderSvgOptions {\n /** 이미지 1장당 허용 최대 바이트 (기본 40MB) */\n maxImageBytes?: number\n /** 검색어 형광펜 — 텍스트 조각 내 매치 구간에 배경 rect (대소문자 무시).\n * charPr(스타일) 경계에 걸친 매치는 칠하지 못한다. */\n highlights?: string[]\n /** Tier-2 reflow — 조판 캐시(linesegarray) 없는 파일도 순수 TS 조판으로 렌더.\n * 캐시가 있으면 무시(한컴본은 캐시 재생). 기본 false(캐시 없으면 KordocError). */\n reflow?: boolean\n /** reflow 줄바꿈 폴백 모드 — 'keep'(어절) / 'charAll'(글자). 문단 paraPr에\n * breakSetting 선언이 있으면 그 값이 우선하며(BREAK_WORD=어절, KEEP_WORD=글자 —\n * 이름 역전 주의), 이 옵션은 선언 없는 문단에만 적용된다. */\n reflowMode?: WrapMode\n}\n\nexport interface RenderSvgResult {\n svg: string\n /** 페이지 폭 (pt) */\n width: number\n /** 전체 캔버스 높이 (pt) — 페이지 세로 스택 + 간격 */\n height: number\n /** 렌더된 페이지 수 */\n pageCount: number\n warnings: string[]\n stats: { texts: number; images: number; tables: number; shapes: number }\n /** 개체 region(페이지 로컬 pt bbox·결정적 id) — #75 */\n regions: RenderRegion[]\n}\n\n// ─── XML 헬퍼 ─────────────────────────────────────\n\n// ─── 표 ───────────────────────────────────────────\n\nfunction edgeLine(x1: number, y1: number, x2: number, y2: number, e: RenderBorderEdge): string {\n const dash = /DASH|DOT/.test(e.type) ? ` stroke-dasharray=\"${e.type.includes(\"DOT\") ? \"1,1.5\" : \"3,1.5\"}\"` : \"\"\n return `<line x1=\"${pt(x1)}\" y1=\"${pt(y1)}\" x2=\"${pt(x2)}\" y2=\"${pt(y2)}\" stroke=\"${escapeXml(e.color)}\" stroke-width=\"${e.widthPt.toFixed(2)}\"${dash}/>`\n}\n\n/**\n * 본문 표가 이어지는 쪽 수 — drawTable 과 같은 행 조각 계획(planTableRows: 행 단위 넘김, CELL 표는 칸 줄 경계에서 가름).\n * 프리패스가 표 뒤 문단의 쪽을 표가 끝나는 쪽으로 보내는 데 쓴다(한컴 저장본: 쪽을 넘는 표 뒤 문단 vertpos 는 표 끝 쪽 기준)\n */\nfunction tableContPages(tbl: Element, ty: number, MT: number, BODY_H: number, memo: ExtentMemo, slack = 0, floatSpan?: CellFloatSpan, nested = false, contMT = MT): { pages: number; endY: number } {\n const pcs = planTableRows(tbl, collectCells(tbl), measureTableRowHeights(tbl, memo), ty, MT, BODY_H, slack, floatSpan, nested, contMT).flat()\n const last = pcs.reduce((a, b) => (b.page > a.page || (b.page === a.page && b.y + b.h > a.y + a.h) ? b : a), pcs[0] ?? { page: 0, y: ty, h: 0 })\n return { pages: last.page, endY: last.y + last.h }\n}\n\n/**\n * 갈린 칸 줄에 앵커한 떠 있는 표가 쪽을 넘는 만큼(planTableRows 의 CellFloatSpan) — 표 위 = 앵커 줄 위 + 바깥 위 여백 + 세로 오프셋.\n * 칸 안 개체는 글을 밀지 않으므로 줄 위 기준이다(한컴 저장본: 칸 안 70행 표의 앵커 줄 horzsize 0, 표는 그 줄 자리부터 세 쪽)\n */\nfunction cellFloatSpan(MT: number, BODY_H: number, memo: ExtentMemo, slack: number): CellFloatSpan {\n return (seg, top, contMT) => {\n const lsa = seg.parentNode as Element | null, p = lsa?.parentNode as Element | null\n if (!p || ln(p) !== \"p\") return undefined\n const segs = elements(lsa!).filter(e => ln(e) === \"lineseg\"), k = segs.indexOf(seg)\n const m = buildPara(p)\n let best: { pages: number; endY: number; el?: Element } | undefined\n for (const o of m.objs) {\n if (o.tag !== \"tbl\" || o.inline) continue\n const pos = findChildByLocalName(o.el, \"pos\")\n if ((pos?.getAttribute(\"vertRelTo\") ?? \"PARA\") !== \"PARA\") continue\n const segK = Math.max(0, m.segs.findIndex((sg, i) => sg.textpos <= o.index && (i === m.segs.length - 1 || m.segs[i + 1].textpos > o.index)))\n if (segK !== k) continue\n // 앵커 줄이 이 표에 밀려 저장됐으면(줄 = 앞 문단 끝 + 표) 표는 줄 위가 아니라 문단 위에서 시작한다 — 그릴 때와 같다\n const segV = num(seg, \"vertpos\"), pTop = cellParaTop(p, memo.paraGeom ?? new Map())\n const start = linePushedBy(o, segV, pTop) ? top - (segV - (pTop ?? segV)) : top\n const ty = start + num(findChildByLocalName(o.el, \"outMargin\"), \"top\") + Math.max(0, toInt32(pos?.getAttribute(\"vertOffset\") ?? undefined, 0))\n const span = tableContPages(o.el, ty, MT, BODY_H, memo, slack, cellFloatSpan(MT, BODY_H, memo, slack), true, contMT)\n if (span.pages > 0 && (!best || span.pages > best.pages)) best = { ...span, el: o.el }\n }\n return best\n }\n}\n\nfunction drawTable(tbl: Element, tx: number, ty: number, ctx: Ctx, depth: number): void {\n if (depth > 16) { warnOnce(ctx, \"depth\", \"중첩 깊이 16 초과 — 이하 생략\"); return }\n ctx.stats.tables++\n const tblSz = findChildByLocalName(tbl, \"sz\")\n const cells = collectCells(tbl)\n if (cells.length === 0 || cells.length > 4096) return\n\n const nCols = Math.max(...cells.map(c => c.ca + c.cs))\n const nRows = Math.max(...cells.map(c => c.ra + c.rs))\n const colCons: SpanConstraint[] = cells.map(c => ({ a: c.ca, b: c.ca + c.cs, size: c.w }))\n // 행마다 칸 너비 합이 다르게 저장된 표는 칸을 이은 가장 긴 길이 표 너비에 닿으면 그 경계(tableColumnBoundaries) —\n // 모든 열을 덮는 행 중 칸 너비 합이 표 너비와 같은 행이 있는지도 넘긴다\n const tblW = num(tblSz, \"width\")\n const rowSum = new Map<number, { cover: number; w: number }>()\n for (const c of cells) { const r = rowSum.get(c.ra) ?? { cover: 0, w: 0 }; r.cover += c.cs; r.w += c.w; rowSum.set(c.ra, r) }\n const noExactRow = ![...rowSum.values()].some(r => r.cover === nCols && Math.abs(r.w - tblW) <= 2)\n const colX = tableColumnBoundaries(colCons, nCols, tblW || undefined, noExactRow)\n // 행 높이는 쪽 프리패스(tableContPages)·재배치와 같은 모델 — 칸 간격(cellSpacing)도 행에 든다\n const rowH = measureTableRowHeights(tbl, ctx.extentMemo)\n const rowY: number[] = [0]\n for (let r = 0; r < nRows; r++) rowY.push(rowY[r] + rowH[r])\n\n // 표 region — 페이지에 걸친 표는 시작 페이지에서 잘려 그려지므로(조판 캐시에 분할점 없음) 시작 페이지\n // 조각만 기록하고 경고한다. sourceId = hp:tbl id (IR 표와의 조인 키, #76)\n const tblH = rowY[nRows]\n if (ty + tblH > ctx.pageH + 100) warnOnce(ctx, \"table-split\", \"페이지에 걸친 표 — 분할 지오메트리가 없어 시작 페이지 영역만 region 으로 기록\")\n const tblId = ctx.regions.add(\"table\", bboxOf(ctx, tx, ty, colX[nCols], tblH), { sourceId: tbl.getAttribute(\"id\") ?? undefined, parentId: parentId(ctx) })\n emit(ctx, regionOpenTag(tblId, \"table\", pageNo(ctx)))\n ctx.parentStack.push(tblId)\n\n // 본문 쪽을 넘는 표는 행 단위로 다음 쪽에 이어 그린다 — 행 바닥이 본문 바닥을 넘으면 그 행부터 다음 쪽 맨 위(쪽이 모자라면 늘린다).\n // repeatHeader 면 머리 행(칸 header=\"1\")을 이어진 쪽마다 다시 그린다. 쪽마다 적어도 한 행은 놓는다(행보다 낮은 쪽은 잘린다)\n const startPage = ctx.page\n let hdrRows = 0\n if (tbl.getAttribute(\"repeatHeader\") === \"1\") while (hdrRows < nRows && cells.some(c => c.ra === hdrRows) && cells.filter(c => c.ra === hdrRows).every(c => c.el.getAttribute(\"header\") === \"1\")) hdrRows++\n // 행 조각 계획 — 칸 안 나눔(CELL) 표는 행을 칸 줄 경계에서 갈라 다음 쪽에 잇는다(table-pages.ts, 쪽 프리패스와 같은 계획)\n const slack = ctx.geom.PH - ctx.geom.MT - ctx.geom.BODY_H\n // 갈린 칸 안의 떠 있는 표도 쪽에서 가른다(칸 안 중첩 표 — 그 칸 계획이 이 표가 끝나는 쪽을 셌다)\n const splitHere = depth === 1 || (!!ctx.splitCell && findChildByLocalName(tbl, \"pos\")?.getAttribute(\"treatAsChar\") !== \"1\")\n const plan = splitHere ? planTableRows(tbl, cells, rowH, ty, ctx.geom.MT, ctx.geom.BODY_H, slack, cellFloatSpan(ctx.geom.MT, ctx.geom.BODY_H, ctx.extentMemo, slack), depth !== 1, depth !== 1 && ctx.splitContMT !== undefined ? ctx.splitContMT : ctx.geom.MT) : rowH.map((h, r) => [{ page: 0, y: ty + rowY[r], h }] as RowPiece[])\n const splitSaved = ctx.splitCell\n ctx.splitCell = false\n for (const pc of plan.flat()) for (const [el, py] of pc.place ?? []) (ctx.objPlace ??= new Map()).set(el, { page: startPage + pc.page, y: py })\n const contPages = [...new Set(plan.flat().map(pc => pc.page).filter(pg => pg > 0))].map(pg => startPage + pg)\n while (ctx.pages.length <= Math.max(startPage, ...contPages)) ctx.pages.push([])\n // 1패스: 배경 → 2패스: 콘텐츠 → 3패스: 테두리 (테두리가 배경/콘텐츠 위)\n type CellGeom = { c: typeof cells[number]; page: number; x: number; y: number; w: number; h: number; pieces?: RowPiece[] }\n const xw = (c: typeof cells[number]) => ({ x: tx + colX[c.ca], w: colX[Math.min(c.ca + c.cs, nCols)] - colX[c.ca] })\n const geom: CellGeom[] = []\n for (const c of cells) {\n const pcs = plan[c.ra]\n if (c.rs === 1 && pcs.length > 1) {\n // 갈린 행 — 조각마다 칸 틀, 내용은 첫 조각에서 조각별로 나눠 그린다\n pcs.forEach((pc, k) => geom.push({ c, page: startPage + pc.page, ...xw(c), y: pc.y, h: pc.h, pieces: k === 0 ? pcs : [] }))\n continue\n }\n // 쪽을 넘는 여러 행 칸 — 쪽마다 그 쪽에 놓인 행만큼 칸 틀, 저장 부분(칸 줄 vertpos 되돌아감)을 쪽 순서대로 나눠 그린다.\n // 부분이 없으면 내용은 첫 쪽 틀 안에서 맞춘다(같은 판 PDF: 네 행 칸 \"2.4 광커플러\" 가 앞 쪽 몫 가운데, 다음 쪽은 빈 틀)\n if (c.rs > 1) {\n const span = plan.slice(c.ra, Math.min(c.ra + c.rs, nRows)).flat()\n const pages = [...new Set(span.map(pc => pc.page))]\n if (pages.length > 1) {\n const bs = cellLineBoxes(c)\n const partTop = (k: number) => bs.find(b => b.part === k)\n const groups: RowPiece[] = pages.map((pg, k) => {\n const on = span.filter(pc => pc.page === pg)\n const y0 = Math.min(...on.map(pc => pc.y)), y1 = Math.max(...on.map(pc => pc.y + pc.h))\n const from = k === 0 ? 0 : partTop(k)?.origin ?? Number.POSITIVE_INFINITY\n const to = k === pages.length - 1 ? Number.POSITIVE_INFINITY : partTop(k + 1)?.top ?? Number.POSITIVE_INFINITY\n return { page: pg, y: y0, h: y1 - y0, range: new Map([[c.el, [from, to] as [number, number]]]) }\n })\n groups.forEach((pc, k) => geom.push({ c, page: startPage + pc.page, ...xw(c), y: pc.y, h: pc.h, pieces: k === 0 ? groups : [] }))\n continue\n }\n }\n const h = c.rs === 1 ? pcs[0].h : rowY[Math.min(c.ra + c.rs, nRows)] - rowY[c.ra]\n geom.push({ c, page: startPage + pcs[0].page, ...xw(c), y: pcs[0].y, h })\n }\n // 반복 머리 행은 이어진 쪽 표 위에 — 갈린 칸 안 표면 그 칸 내용 위(splitContMT)에서\n const contBase = depth !== 1 && ctx.splitContMT !== undefined ? ctx.splitContMT : ctx.geom.MT\n for (const page of contPages) for (const c of cells) if (c.ra < hdrRows) geom.push({ c, page, ...xw(c), y: contBase + num(findChildByLocalName(tbl, \"outMargin\"), \"top\") + rowY[c.ra], h: rowY[Math.min(c.ra + c.rs, nRows)] - rowY[c.ra] })\n for (const g of geom) {\n ctx.page = g.page\n const bf = g.c.bfId != null ? ctx.styles.borderFill.get(g.c.bfId) : undefined\n if (bf?.fill) emit(ctx, `<rect x=\"${pt(g.x)}\" y=\"${pt(g.y)}\" width=\"${pt(g.w)}\" height=\"${pt(g.h)}\" fill=\"${escapeXml(bf.fill)}\"/>`)\n }\n for (const g of geom) {\n const { c } = g\n if (!c.sub || (g.pieces && g.pieces.length === 0)) continue\n ctx.page = g.page\n if (g.pieces) {\n // 갈린 칸 — 줄마다 그 줄이 든 조각의 쪽·위치로(첫 조각 위 기준 vertpos 로 잠시 바꿔 그린 뒤 되돌린다)\n const base = g.pieces[0].y + c.marginT\n const boxes = cellLineBoxes(c)\n const contV = new Map(boxes.map(b => [b.seg, b.top]))\n const pieceOf = (v: number): number => Math.max(0, g.pieces!.findIndex(pc => { const r = pc.range?.get(c.el); return !!r && v >= r[0] && v < r[1] }))\n // 세로 가운데·아래 칸은 첫 쪽 조각이 그 조각 내용([조각 원점, 마지막 줄 바닥])을 조각 안에서 맞춘다(한컴 PDF: 두 쪽에 갈린 가운데 칸의 첫 쪽이 8pt 내려옴).\n // 가운데 조각은 저장 vertpos 자리 그대로다(같은 판이 저장·인쇄한 PDF: 가운데 칸 둘째 쪽부터 글이 저장 자리 — 서식 3개·쪽 40개 넘는 칸 하나)\n const va = c.sub.getAttribute(\"vertAlign\") ?? \"TOP\"\n // 마지막 조각은 칸 저장 몫으로 내용보다 클 수 있다(두 쪽 나눔) — 그 남는 높이 안에서 맞춘다(같은 판 PDF: 마지막 조각 글이 남는 몫의 절반 아래)\n const lastK = g.pieces.length - 1\n const pieceOff = g.pieces.map((pc, k) => {\n if (va === \"TOP\" || (k > 0 && k < lastK) || pc.fill) return 0\n const from = pc.range?.get(c.el)?.[0] ?? 0\n const bottoms = boxes.filter(b => pieceOf(b.top) === k).map(b => b.bottom - from)\n if (k > 0) for (const f of subFloatBottoms(c.sub!)) { const b = boxes.find(x => x.seg === f.seg); if (b && pieceOf(b.top) === k) bottoms.push(b.top + f.bottom - f.v0 - from) }\n if (!bottoms.length) return 0\n const free = pc.h - c.marginT - c.marginB - Math.max(...bottoms)\n return Math.max(0, va === \"CENTER\" ? free / 2 : free)\n })\n for (const p of elements(c.sub)) {\n if (ln(p) !== \"p\") continue\n const lsa = findChildByLocalName(p, \"linesegarray\"), segs = lsa ? elements(lsa).filter(e => ln(e) === \"lineseg\") : []\n const saved = segs.map(sg => sg.getAttribute(\"vertpos\"))\n const pages = segs.map(sg => {\n const v = contV.get(sg) ?? num(sg, \"vertpos\")\n const k = pieceOf(v)\n const pc = g.pieces![k], from = pc.range?.get(c.el)?.[0] ?? 0\n sg.setAttribute(\"vertpos\", String(v - from + pc.y + c.marginT + pieceOff[k] - base))\n return startPage + pc.page\n })\n ctx.splitCell = splitHere\n // 이 칸 안 표가 이어지는 쪽의 시작 — 바깥 표의 이어진 쪽 위(머리 행 아래) + 칸 위 여백\n const contMTSaved = ctx.splitContMT\n // 겹친 중첩이면 바깥 겹이 이어진 쪽에서 시작하는 자리부터 쌓는다(이 표가 갈린 칸 안 표면 그 칸 내용 위)\n ctx.splitContMT = (depth > 1 && contMTSaved !== undefined ? contMTSaved : ctx.geom.MT) + num(findChildByLocalName(tbl, \"outMargin\"), \"top\") + rowY[hdrRows] + c.marginT\n drawPara(p, g.x + c.marginL, base, g.w - c.marginL - c.marginR, ctx, depth + 1, pages)\n ctx.splitContMT = contMTSaved\n ctx.splitCell = false\n segs.forEach((sg, i) => sg.setAttribute(\"vertpos\", saved[i] ?? \"0\"))\n }\n continue\n }\n // 칸보다 넓은 인라인 개체는 칸 경계에서 잘린다(한컴 PDF: 칸 폭 157pt 칸의 167pt 사진이 칸 안쪽까지만 보인다)\n const innerW = g.w - c.marginL - c.marginR\n const overWide = elements(c.sub).some(q => ln(q) === \"p\" && buildPara(q).objs.some(o => o.inline && o.tag === \"pic\" && o.width > innerW + 50))\n if (overWide) {\n const cid = `cclip${ctx.defs.length}`\n ctx.defs.push(`<clipPath id=\"${cid}\"><rect x=\"${pt(g.x)}\" y=\"${pt(g.y)}\" width=\"${pt(g.w)}\" height=\"${pt(g.h)}\"/></clipPath>`)\n emit(ctx, `<g clip-path=\"url(#${cid})\">`)\n }\n const innerH = g.h - c.marginT - c.marginB\n const extent = cellContentExtent(c, ctx.extentMemo)\n const va = c.sub.getAttribute(\"vertAlign\") ?? \"TOP\"\n let yoff = 0\n if (va === \"CENTER\") yoff = Math.max(0, (innerH - extent) / 2)\n else if (va === \"BOTTOM\") yoff = Math.max(0, innerH - extent)\n // 칸 안 다단 — 줄 vertpos 가 되돌아갈 때마다 다음 단: 그 줄들을 단 폭 + 간격만큼 오른쪽에 그린다(줄 horzpos 를 잠시 옮긴다)\n // (한컴 PDF: 2단 칸의 17~31번 항목이 오른쪽 단)\n const cols = cellColumns(c.sub)\n const moved: Array<[Element, string | null]> = []\n if (cols) {\n const colW = (innerW - cols.gap * (cols.n - 1)) / cols.n\n let col = 0, prevV = Number.NEGATIVE_INFINITY\n for (const p of elements(c.sub)) if (ln(p) === \"p\") {\n const lsa = findChildByLocalName(p, \"linesegarray\")\n for (const sg of lsa ? elements(lsa) : []) if (ln(sg) === \"lineseg\") {\n const v = num(sg, \"vertpos\")\n if (v < prevV) col = Math.min(cols.n - 1, col + 1)\n prevV = v\n if (col > 0) { moved.push([sg, sg.getAttribute(\"horzpos\")]); sg.setAttribute(\"horzpos\", String(num(sg, \"horzpos\") + Math.round(col * (colW + cols.gap)))) }\n }\n }\n }\n for (const p of elements(c.sub)) {\n if (ln(p) !== \"p\") continue\n drawPara(p, g.x + c.marginL, g.y + c.marginT + yoff, g.w - c.marginL - c.marginR, ctx, depth + 1)\n }\n for (const [sg, hp] of moved) sg.setAttribute(\"horzpos\", hp ?? \"0\")\n if (overWide) { ctx.page = g.page; emit(ctx, \"</g>\") }\n }\n for (const g of geom) {\n ctx.page = g.page\n const bf = g.c.bfId != null ? ctx.styles.borderFill.get(g.c.bfId) : undefined\n if (!bf) continue\n if (bf.top) emit(ctx, edgeLine(g.x, g.y, g.x + g.w, g.y, bf.top))\n if (bf.bottom) emit(ctx, edgeLine(g.x, g.y + g.h, g.x + g.w, g.y + g.h, bf.bottom))\n if (bf.left) emit(ctx, edgeLine(g.x, g.y, g.x, g.y + g.h, bf.left))\n if (bf.right) emit(ctx, edgeLine(g.x + g.w, g.y, g.x + g.w, g.y + g.h, bf.right))\n }\n ctx.page = startPage\n ctx.splitCell = splitSaved\n ctx.parentStack.pop()\n emit(ctx, \"</g>\")\n}\n\n// ─── 이미지 ───────────────────────────────────────\n\n/**\n * 이미지 심볼 등록(바이너리당 1회) — dataURI를 defs에 한 번만 넣고 <use>로 참조한다.\n * occurrence마다 dataURI를 재emit하면 반복 참조 문서에서 SVG 문자열이 기하급수로\n * 커져 RangeError/OOM (소형 입력 DoS). viewBox 100×100 + preserveAspectRatio none\n * 이라 <use width/height>가 기존 <image width/height> stretch와 동일하게 스케일된다.\n */\nfunction imageSymbol(loaded: { dataUri: string; symId?: string }, ctx: Ctx): string {\n if (!loaded.symId) {\n loaded.symId = `bin${ctx.defs.length}`\n ctx.defs.push(\n `<symbol id=\"${loaded.symId}\" viewBox=\"0 0 100 100\" preserveAspectRatio=\"none\">` +\n `<image width=\"100\" height=\"100\" preserveAspectRatio=\"none\" href=\"${loaded.dataUri}\"/></symbol>`,\n )\n }\n return loaded.symId\n}\n\nfunction drawPic(pic: Element, x: number, y: number, ctx: Ctx): void {\n const sz = findChildByLocalName(pic, \"sz\")\n let w = num(sz, \"width\", 5669), h = num(sz, \"height\", 5669)\n // 돌린 사진 — sz 는 돌린 외접 상자, 그림은 curSz 틀로 그 상자 중심에 놓고 돌린다 (objectGeometry, #116)\n const cur = findChildByLocalName(pic, \"curSz\")\n const rotated = objectGeometry(pic, x, y, num(cur, \"width\") || w, num(cur, \"height\") || h, w, h)\n if (rotated.rotation) { x = rotated.x; y = rotated.y; w = rotated.w; h = rotated.h; ctx.regionRotations.push(rotated.rotation) }\n drawPicFrame(pic, x, y, w, h, rotated.transform, ctx)\n if (rotated.rotation) ctx.regionRotations.pop()\n}\n\nfunction drawPicFrame(pic: Element, x: number, y: number, w: number, h: number, transform: string, ctx: Ctx): void {\n const img = findFirst(pic, \"img\")\n const ref = img?.getAttribute(\"binaryItemIDRef\")\n const loaded = ref != null ? ctx.images.get(ref) : undefined\n const imgId = ctx.regions.add(\"image\", bboxOf(ctx, x, y, w, h), { sourceId: ref ?? undefined, parentId: parentId(ctx) })\n emit(ctx, regionOpenTag(imgId, \"image\", pageNo(ctx)))\n const close = transform ? \"</g></g>\" : \"</g>\"\n if (transform) emit(ctx, `<g transform=\"${transform}\">`)\n if (!loaded) {\n emit(ctx, `<rect x=\"${pt(x)}\" y=\"${pt(y)}\" width=\"${pt(w)}\" height=\"${pt(h)}\" fill=\"#eee\" stroke=\"#c00\" stroke-width=\"0.5\"/>`)\n warnOnce(ctx, `img:${ref}`, `이미지 바이너리 누락: ${ref ?? \"(ref 없음)\"}`)\n emit(ctx, close)\n return\n }\n ctx.stats.images++\n // imgClip 좌표계는 imgDim(이미지 내용 상자) 기준이다 — orgSz(최초 삽입 크기)가 아니다.\n // 실측(데모 코퍼스 pic 267개): clip==dim 254개(크롭 없음)·실제 크롭 8개 모두 dim 기준.\n // orgSz 로 비교하면 리사이즈된 로고(dim<org)가 좌상단 코너로 잘못 잘려 로고가 깨진다.\n const clip = findChildByLocalName(pic, \"imgClip\")\n const imgDim = findChildByLocalName(pic, \"imgDim\")\n const orgSz = findChildByLocalName(pic, \"orgSz\")\n const dimW = num(imgDim, \"dimwidth\"), dimH = num(imgDim, \"dimheight\")\n // 참조(전체 내용) 공간: imgDim 우선, 없으면 orgSz 폴백\n const refW = dimW > 0 ? dimW : num(orgSz, \"width\")\n const refH = dimH > 0 ? dimH : num(orgSz, \"height\")\n const cl = num(clip, \"left\"), ct = num(clip, \"top\")\n const cr = num(clip, \"right\", refW), cb = num(clip, \"bottom\", refH)\n const cropped =\n refW > 0 && refH > 0 && clip != null && (cl > 0 || ct > 0 || cr < refW || cb < refH) && cr > cl && cb > ct\n const symId = imageSymbol(loaded, ctx)\n if (cropped) {\n // 참조 좌표계 viewBox로 크롭 창을 내고, 이미지는 전체 내용 크기로 깐다\n emit(ctx,\n `<svg x=\"${pt(x)}\" y=\"${pt(y)}\" width=\"${pt(w)}\" height=\"${pt(h)}\" viewBox=\"${pt(cl)} ${pt(ct)} ${pt(cr - cl)} ${pt(cb - ct)}\" preserveAspectRatio=\"none\">` +\n `<use href=\"#${symId}\" x=\"0\" y=\"0\" width=\"${pt(refW)}\" height=\"${pt(refH)}\"/></svg>`,\n )\n } else {\n emit(ctx, `<use href=\"#${symId}\" x=\"${pt(x)}\" y=\"${pt(y)}\" width=\"${pt(w)}\" height=\"${pt(h)}\"/>`)\n }\n emit(ctx, close)\n}\n\nfunction sniffMime(name: string, bytes: Uint8Array): string {\n const lower = name.toLowerCase()\n if (lower.endsWith(\".png\") || (bytes.length > 4 && bytes[0] === 0x89 && bytes[1] === 0x50)) return \"image/png\"\n if (lower.endsWith(\".bmp\") || (bytes.length > 2 && bytes[0] === 0x42 && bytes[1] === 0x4d)) return \"image/bmp\"\n if (lower.endsWith(\".gif\") || (bytes.length > 3 && bytes[0] === 0x47 && bytes[1] === 0x49 && bytes[2] === 0x46)) return \"image/gif\"\n if (lower.endsWith(\".svg\")) return \"image/svg+xml\"\n if (bytes.length > 3 && bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff) return \"image/jpeg\"\n return \"image/jpeg\"\n}\n\n// ─── 엔트리 ───────────────────────────────────────\n\n/** 구역 하나의 페이지 지오메트리 (HWPUNIT) */\nfunction readSectionGeom(root: Element): PageGeom {\n const pagePr = findFirst(root, \"pagePr\")\n const margin = pagePr ? findChildByLocalName(pagePr, \"margin\") : null\n let PW = num(pagePr, \"width\", 59528), PH = num(pagePr, \"height\", 84188)\n // 용지 방향 — width/height는 용지 원방향(세로) 치수로 저장되고 landscape=\"NARROWLY\"가\n // 가로(90° 회전)를 뜻한다(WIDELY=세로). 무시하면 가로 문서의 오른쪽이 잘린다\n // (실측: 가로 A4 문서 lineseg 줄폭 78520 = 84188 − 좌우마진, 세로폭 59528 초과).\n if (pagePr?.getAttribute(\"landscape\") === \"NARROWLY\" && PW < PH) {\n const t = PW; PW = PH; PH = t\n }\n // 제본 여백(gutter) — 왼쪽(LEFT_ONLY·맞쪽 홀수 쪽) 또는 위(TOP_BOTTOM)에 더해 본문을 줄인다\n // (한컴 PDF: 왼쪽 5669 + 제본 500 문서의 본문 그림 x 61.7pt, 저장 줄 폭 47688 = 59528 − 5669×2 − 500 을 4 단위로)\n const gutterType = pagePr?.getAttribute(\"gutterType\") ?? \"LEFT_ONLY\", gutter = num(margin, \"gutter\", 0)\n const gL = gutterType === \"TOP_BOTTOM\" ? 0 : gutter, gT = gutterType === \"TOP_BOTTOM\" ? gutter : 0\n const ML = num(margin, \"left\", 8504) + gL\n const MT = num(margin, \"top\", 5668) + num(margin, \"header\", 0) + gT\n const BODY_H = PH - MT - num(margin, \"bottom\", 4252) - num(margin, \"footer\", 0)\n const BODY_W = PW - ML - num(margin, \"right\", 8504)\n // 맞쪽 — 짝수 쪽은 좌우 여백이 바뀐다(제본 여백은 안쪽 = 짝수 쪽 오른쪽). 한컴 PDF: 왼쪽 7086·오른쪽 14173 교재의 짝수 쪽 그림이 70.9pt 오른쪽\n const mirrorDx = gutterType === \"LEFT_RIGHT\" ? num(margin, \"right\", 8504) - ML : 0\n return { PW, PH, ML, MT, BODY_W, BODY_H, ...(mirrorDx ? { mirrorDx } : {}) }\n}\n\n/** 렌더된 구역 — 페이지 버퍼 + 페이지 크기(구역별 pagePr 상이 가능) */\ninterface RenderedSection { pages: string[][]; PW: number; pageH: number; clipId: string }\n\n/**\n * 구역 하나를 렌더 → 페이지 버퍼. 공유 자원(styles/images/defs/warnings/stats)은 ctx로 넘겨\n * 이미지 심볼·통계·경고가 전 구역에 누적되게 한다(dataURI 중복·페이지 카운트 정합).\n */\n/** 최상위 문단 캐시가 쓸 수 없는지 — 쪽 나누기 없이 vertpos 0 인 문단이 셋 이상 잇달고, 그 앞 문단들 높이 합이 본문 높이 절반 이하 */\nfunction staleTopCache(root: Element, BODY_H: number): boolean {\n if (BODY_H <= 0) return false\n let run = 0, sum = 0\n for (const p of elements(root)) {\n if (ln(p) !== \"p\") continue\n const lsa = findChildByLocalName(p, \"linesegarray\")\n const segs = lsa ? elements(lsa).filter(e => ln(e) === \"lineseg\") : []\n if (!segs.length) continue\n const v = num(segs[0], \"vertpos\")\n if (v !== 0 || p.getAttribute(\"pageBreak\") === \"1\" || p.getAttribute(\"columnBreak\") === \"1\") { run = 0; sum = 0; continue }\n if (run >= 2 && sum <= BODY_H / 2) return true\n const last = segs[segs.length - 1]\n sum += num(last, \"vertpos\") + num(last, \"vertsize\") + num(last, \"spacing\")\n run++\n }\n return false\n}\n\n/**\n * 조판 캐시가 쪽 절대 좌표로 적혔는지 — 왼 여백 자리 이후에서 시작해 본문 폭을 넘는 최상위 줄이 셋 이상이고 줄의 1/5 이상.\n * 본문 기준 캐시의 줄은 본문 폭 안이다(쪽 기준으로 적은 문서: 줄 시작 7090·9185 = 왼 여백 6750 + 들여쓰기, 줄 끝 54110 > 본문 폭 47800)\n */\nfunction absoluteTopCache(root: Element, ML: number, BODY_W: number): boolean {\n let tot = 0, over = 0\n for (const p of elements(root)) {\n if (ln(p) !== \"p\") continue\n const lsa = findChildByLocalName(p, \"linesegarray\")\n for (const sg of lsa ? elements(lsa) : []) {\n if (ln(sg) !== \"lineseg\" || num(sg, \"horzsize\") <= 0) continue\n tot++\n const hp = num(sg, \"horzpos\")\n if (hp >= ML - 500 && hp + num(sg, \"horzsize\") > BODY_W + 500) over++\n }\n }\n return over >= 3 && over * 5 >= tot\n}\n\nfunction renderSectionToPages(\n root: Element,\n geom: PageGeom,\n ctxBase: Omit<Ctx, \"pages\" | \"page\" | \"geom\" | \"pageH\" | \"paintJobs\" | \"regionRotations\">,\n doReflow: boolean,\n reflowMode: WrapMode,\n masters: Element[] = [],\n hasDeletionMarkers = true,\n lastSection = true,\n): { pages: string[][]; pageH: number } {\n const { PW, PH, ML, MT, BODY_W, BODY_H } = geom\n // Tier-2 reflow — 캐시 없는 문단에 linesegarray 합성 주입. 혼합 캐시 문서(한컴\n // 저장본을 프로그램 편집해 일부 문단만 캐시 없음)도 reflow 옵션이면 진입한다 —\n // 전량 캐시 문서는 전 문단 skip(Tier-1 무회귀)이라 no-op.\n if (hasDeletionMarkers) prepareDeletedRanges(root)\n // 망가진 조판 캐시 — 쪽 나누기 없는 최상위 문단이 셋 이상 잇달아 vertpos 0 인데 앞 문단들 높이 합이 쪽 절반도 안 되면 한컴 캐시일 수 없다\n // (rhwp 시험 문서: 전 문단 vertpos 0 → 문단마다 새 쪽 33쪽, 한컴 PDF 2쪽). 최상위 문단 캐시를 버리고 다시 조판한다\n const degenerate = staleTopCache(root, BODY_H)\n if (degenerate) {\n for (const p of elements(root)) if (ln(p) === \"p\") { const lsa = findChildByLocalName(p, \"linesegarray\"); if (lsa) p.removeChild(lsa) }\n ctxBase.warnings.push(\"조판 캐시가 맞지 않아(최상위 문단이 모두 같은 자리) 다시 조판해 렌더\")\n }\n // 쪽 절대 좌표로 적힌 캐시 — 본문·칸·글상자 줄이 모두 쪽 기준이라(칸 줄 시작 24610, 글상자 줄 = 상자 쪽 위치) 전부 버리고 다시 조판한다.\n // 그대로 쓰면 본문이 왼 여백만큼 오른쪽으로 밀려 잘리고 글상자 글은 상자 좌표의 두 배 자리(쪽 밖)에 그려졌다\n const absolute = !degenerate && absoluteTopCache(root, ML, BODY_W)\n if (absolute) {\n for (const lsa of Array.from(root.getElementsByTagName(\"*\") as unknown as Element[]).filter(e => ln(e) === \"linesegarray\")) lsa.parentNode?.removeChild(lsa)\n ctxBase.warnings.push(\"조판 캐시가 쪽 기준 좌표로 적혀 있어 다시 조판해 렌더\")\n }\n // 캐시 없는 최상위 문단이 섞인 문서(한컴 저장본에 개체만 든 문단 하나가 캐시 없이 남은 경우 등) — reflow 는 캐시 있는 문단은 그대로 두고\n // 없는 문단만 흐름 위치에 채운다. 종전엔 그 문단 개체를 쪽 맨 위(문단 원점)에 그렸다(보도자료 끝 로고 표가 1쪽 위에)\n // 칸·글상자·머리말 안 문단도 본다(한컴 저장본 꼬리말 글상자 문단이 캐시 없이 남아 그 안 표가 바깥 여백 없이 그려지던 것)\n const mixed = !doReflow && !degenerate && !absolute && Array.from(root.getElementsByTagName(\"*\") as unknown as Element[]).some(p => ln(p) === \"p\" && !findChildByLocalName(p, \"linesegarray\"))\n if (doReflow || degenerate || absolute || mixed) reflowSection(root, ctxBase.styles, { BODY_W, BODY_H }, reflowMode)\n\n // 페이지 분할 프리패스 — 최상위 lineseg vertpos는 페이지 로컬(페이지마다 0부터)이라\n // 역행 지점이 곧 페이지 경계다. 다단(colCount>1)은 단 이동도 vertpos가 리셋되지만\n // horzpos가 오른쪽으로 점프하므로, horzpos가 왼쪽으로 돌아올 때만 새 페이지로 본다.\n // vertpos \"동일\"도 문단 첫 seg + horzpos 비전진이면 경계다 — 페이지 전체가 표 하나인\n // 문단이 연속되면 vertpos가 매 페이지 0으로 같아서 strict 역행만으론 못 가른다\n // (의사일정표류: v0 문단 연속 → 뒤 페이지들이 전부 한 페이지에 겹침).\n // 문단 내부의 vertpos 동일 seg는 개체 좌우로 갈라진 같은 줄(h 우측 점프)이라 제외.\n const colPr = findFirst(root, \"colPr\")\n const multiCol = num(colPr, \"colCount\", 1) > 1\n // 다단 lineseg 의 horzpos 는 단 기준 지역 좌표일 수 있다(한컴 저장 2단 시험지: 오른쪽 단도 horzpos 0) — 그러면 vertpos 리셋마다 단을 세고\n // 단 오프셋을 더해 그린다. 단 오프셋이 이미 든 문서(오른쪽 단 horzpos ≥ 단 폭)는 종전대로 horzpos 가 왼쪽으로 돌아올 때 새 쪽\n const nCol = multiCol ? num(colPr, \"colCount\", 1) : 1, colGap = multiCol ? num(colPr, \"sameGap\", 0) : 0\n const colW = (BODY_W - colGap * (nCol - 1)) / nCol\n let localCols = multiCol\n if (multiCol) for (const p of elements(root)) {\n if (ln(p) !== \"p\") continue\n const lsa = findChildByLocalName(p, \"linesegarray\")\n for (const s of lsa ? elements(lsa) : []) if (ln(s) === \"lineseg\" && num(s, \"horzpos\") >= colW) { localCols = false; break }\n if (!localCols) break\n }\n const paraSegPages = new Map<Element, number[]>()\n const paraTops = new Map<Element, number>()\n /** 앞 쪽 끝에서 시작해 이 쪽으로 넘어온 떠 있는 표 — 쪽·위(그리기가 그 자리에 그린다) */\n const backPlace = new Map<Element, { page: number; y: number }>()\n const geom0 = ctxBase.styles.paraGeom\n /** 본문 표가 이어지는 마지막 쪽 */\n let tableEndPage = -1\n let nPages = 1\n let maxTopV = 0\n {\n let prevV = Number.NEGATIVE_INFINITY\n let prevH = Number.NEGATIVE_INFINITY\n // 앞 줄의 끝(vertpos + vertsize + spacing) — 같은 vertpos 가 다시 와도 앞 줄이 그 자리에서 끝났으면(줄간격 음수로 겹친 줄) 새 쪽이 아니다.\n // 쪽 아래쪽의 같은 vertpos 도 새 쪽이 아니다 — 첫 빈 줄 감추기로 쪽 바닥 아래에 남긴 빈 문단들은 한 자리에 겹쳐 저장된다\n let prevEnd = Number.NEGATIVE_INFINITY\n let cur = 0, col = 0\n /** 쪽을 넘는 표가 끝나는 쪽 — 그 뒤 첫 쪽 리셋은 여기로 */\n let pendingEnd = 0, pendingEndY = 0\n let lastEnd = 0, lastPage = -1\n /** 앞 문단 아래 간격 — 문단 영역 위는 앞 문단 끝 + 이 간격(한컴 저장본: 아래 간격 600 뒤 문단의 떠 있는 표가 그 자리 + vertOffset) */\n let lastSA = 0\n /** 바로 앞 줄 — 쪽 바닥을 넘친 줄을 새 쪽으로 옮길 때 */\n let prevSeg: { s: Element; p: Element; pages: number[]; idx: number; vs: number; sp: number } | undefined\n for (const p of elements(root)) {\n if (ln(p) !== \"p\") continue\n const lsa = findChildByLocalName(p, \"linesegarray\")\n const segEls = lsa ? elements(lsa).filter(s => ln(s) === \"lineseg\") : []\n const pagesOf: number[] = []\n let paraFirst = true\n for (const s of segEls) {\n const v = num(s, \"vertpos\")\n const h = num(s, \"horzpos\")\n if (localCols) {\n // 지역 좌표 다단 — 리셋마다 다음 단, 마지막 단 다음은 새 쪽\n if (v < prevV || (paraFirst && v === prevV && h <= prevH && v === 0 && prevEnd > v)) {\n // 쪽 나누기 문단은 남은 단을 건너 새 쪽\n if (paraFirst && p.getAttribute(\"pageBreak\") === \"1\") { col = 0; cur++ } else if (++col >= nCol) { col = 0; cur++ }\n }\n if (col > 0) s.setAttribute(\"horzpos\", String(h + Math.round(col * (colW + colGap))))\n } else {\n if (paraFirst && pendingEnd > cur) {\n // 앞 문단의 표가 쪽을 넘어 pendingEnd 쪽에서 끝났다 — 이 문단은 그 쪽(표 끝 아래), 표 끝보다 위에 저장돼 있으면 다음 쪽\n cur = v < pendingEndY - 100 ? pendingEnd + 1 : pendingEnd\n pendingEnd = 0\n } else {\n const brk = v < prevV\n ? (!multiCol || h <= prevH)\n : (v === prevV && h <= prevH && prevEnd > v && v < BODY_H / 2)\n // 쪽 나누기 문단은 저장 vertpos 가 되돌아가지 않았어도 새 쪽 — 한컴 PDF: 쪽 나누기 목차 문단이 vertpos 1500 으로 저장돼도 다음 쪽 맨 위\n // 본문 아래쪽에 저장된 쪽 나누기 문단도 첫 줄이 제 위아래 개체에 밀린 자리(= 바깥 위 + 높이 + 바깥 아래, 새 쪽 맨 위 기준)면 새 쪽 —\n // 한컴 PDF: 줄 64320·66927 이 표 64038·66645(+바깥 여백)에 밀린 서식 표가 둘 다 다음 쪽 맨 위\n const pbrk = !brk && paraFirst && prevV !== Number.NEGATIVE_INFINITY && p.getAttribute(\"pageBreak\") === \"1\" &&\n (v < BODY_H / 2 || buildPara(p).objs.some(o => !o.inline && (o.el.getAttribute(\"textWrap\") ?? \"TOP_AND_BOTTOM\") === \"TOP_AND_BOTTOM\" &&\n (findChildByLocalName(o.el, \"pos\")?.getAttribute(\"vertRelTo\") ?? \"PARA\") === \"PARA\" && linePushedBy(o, v, 0)))\n // 쪽 위쪽에서 앞 줄 끝보다 위에 시작하는 첫 줄은, 둘을 합치면 본문 높이를 넘으면 새 쪽이다 — 한컴은 쪽마다 쪽을 채우는\n // 인라인 표를 vertpos 0·700 으로 저장한다(한컴 PDF 2쪽, 0 으로 되돌아가지 않아 1쪽에 겹쳐 그리던 것)\n const obrk = !brk && !pbrk && !multiCol && paraFirst && v > prevV && v < prevEnd - 100 && prevEnd + num(s, \"vertsize\") > BODY_H && v < BODY_H / 2\n if (brk || pbrk || obrk) cur++\n // 쪽 바닥을 넘친 줄 다음에서 쪽이 바뀌고 그다음 줄이 그 줄을 새 쪽 맨 위에 둔 자리면(vertpos = 앞 줄 높이 + 간격), 넘친 줄도 새 쪽 맨 위다\n // — 한컴은 그 줄 vertpos 를 앞 쪽 값(73135, 본문 높이 72852)으로 저장하고 PDF 에선 다음 쪽 맨 위에 찍는다\n if (brk && prevSeg && prevV + prevSeg.vs > BODY_H && v === prevSeg.vs + prevSeg.sp && prevSeg.pages[prevSeg.idx] === cur - 1) {\n prevSeg.pages[prevSeg.idx] = cur\n prevSeg.s.setAttribute(\"vertpos\", \"0\")\n if (prevSeg.idx === 0) paraTops.set(prevSeg.p, 0)\n if (prevSeg.p !== p) { lastPage = cur; lastEnd = v; lastSA = 0 }\n }\n }\n }\n paraFirst = false\n pagesOf.push(cur)\n prevSeg = { s, p, pages: pagesOf, idx: pagesOf.length - 1, vs: num(s, \"vertsize\"), sp: num(s, \"spacing\") }\n maxTopV = Math.max(maxTopV, v + num(s, \"textheight\", 1000))\n prevV = v\n prevH = h\n prevEnd = v + num(s, \"vertsize\") + num(s, \"spacing\")\n }\n paraSegPages.set(p, pagesOf)\n const prevEnd0 = lastEnd, prevPage0 = lastPage\n if (segEls.length) paraTops.set(p, pagesOf[0] === lastPage ? lastEnd + lastSA : 0)\n if (segEls.length) { const ls = segEls[segEls.length - 1]; lastEnd = num(ls, \"vertpos\") + num(ls, \"vertsize\") + num(ls, \"spacing\"); lastPage = pagesOf[pagesOf.length - 1]; lastSA = geom0.get(p.getAttribute(\"paraPrIDRef\") ?? \"\")?.spaceAfter ?? 0 }\n // 이 문단의 본문 표가 쪽을 넘어 이어지면, 다음 쪽 리셋은 표가 끝나는 쪽으로\n if (!localCols && segEls.length) {\n const m0 = buildPara(p)\n for (const o of m0.objs) {\n if (o.tag !== \"tbl\") continue\n const pos = findChildByLocalName(o.el, \"pos\"), om = findChildByLocalName(o.el, \"outMargin\")\n if (!o.inline && (pos?.getAttribute(\"vertRelTo\") ?? \"PARA\") !== \"PARA\") continue\n // 앵커 글자가 든 줄(떠 있는 개체도 — anchorObject 와 같다)\n const segK = Math.max(0, m0.segs.findIndex((sg, k) => sg.textpos <= o.index && (k === m0.segs.length - 1 || m0.segs[k + 1].textpos > o.index)))\n const segV = num(segEls[segK], \"vertpos\")\n // 떠 있는 표 위치는 anchorObject 와 같은 규칙 — 글을 밀어낸 표(줄이 표 아래에 있음)는 줄 위쪽\n const h = Math.max(o.height, measureTableHeight(o.el, ctxBase.extentMemo)), omT = num(om, \"top\"), omB = num(om, \"bottom\")\n const pushed = segV - (omT + h + omB)\n // 새 쪽 첫 줄에 앵커한 위아래 표가 앵커 줄보다 높고, 앞 쪽 끝(앞 문단 끝)에서 시작해 가르면 그 끝이 앵커 줄 바로 위면 — 한컴은 표를 앞 쪽 끝에서\n // 시작해 이 쪽으로 넘기고 앵커 줄을 표 끝 아래에 저장한다(한컴 PDF: 21행 연락처 표가 앞 쪽 13행·이 쪽 8행, 앵커 줄 13086 = 8행 + 바깥 여백)\n if (!o.inline && segK === 0 && pushed < -100 && prevPage0 >= 0 && pagesOf[0] === prevPage0 + 1 && (o.el.getAttribute(\"textWrap\") ?? \"TOP_AND_BOTTOM\") === \"TOP_AND_BOTTOM\") {\n const back = tableContPages(o.el, MT + prevEnd0 + omT, MT, BODY_H, ctxBase.extentMemo, PH - MT - BODY_H, cellFloatSpan(MT, BODY_H, ctxBase.extentMemo, PH - MT - BODY_H))\n if (back.pages === 1 && Math.abs(back.endY - MT + omB - segV) <= 300) { backPlace.set(o.el, { page: prevPage0, y: MT + prevEnd0 + omT }); continue }\n }\n const nTb = m0.objs.filter(q => !q.inline && (q.el.getAttribute(\"textWrap\") ?? \"TOP_AND_BOTTOM\") === \"TOP_AND_BOTTOM\").length\n // 글을 밀지 않는 개체(어울림·글 앞뒤)는 그리기와 같이 문단 시작 기준(첫 줄이 개체 아래로 밀려 저장됐으면 문단 영역 위 + 위 간격)\n const wrapP = o.el.getAttribute(\"textWrap\") ?? \"TOP_AND_BOTTOM\"\n const pTop = paraTops.get(p), sbP = m0.paraPrId != null ? geom0.get(m0.paraPrId)?.spaceBefore ?? 0 : 0\n // 글 없는 문단의 줄 제자리 — 그리기(svg-content)와 같이 개체만큼 밀려 저장된 줄은 빼고\n const stay = nTb < 2 && !m0.objs.some(q => q.inline) && !m0.chars.some(c => c.ch !== \"\" && !c.nb && c.ch.trim() !== \"\") &&\n !(!o.inline && wrapP === \"TOP_AND_BOTTOM\" && linePushedBy(o, segV, pTop))\n const nonPush = wrapP !== \"TOP_AND_BOTTOM\" && pTop !== undefined && segV > pTop + sbP + 100 ? pTop + sbP : undefined\n const voP = Math.max(0, toInt32(pos?.getAttribute(\"vertOffset\") ?? undefined, 0))\n const paraStart = segK === 0 && pTop !== undefined && pTop < segV ? pTop : segV\n // 오프셋이 앵커 줄 높이 이상인 개체는 줄 아래 — 그리기(anchorObject)와 같다\n const below = !o.inline && wrapP === \"TOP_AND_BOTTOM\" && voP + omT >= num(segEls[segK], \"textheight\") && !linePushedBy(o, segV, pTop)\n const ty = o.inline ? MT + segV + omT : nonPush !== undefined ? MT + nonPush + omT + voP : MT + (below ? segV - (segK === 0 ? sbP : 0) : stay ? segV - sbP : pushed - voP >= -100 ? pushed - voP : paraStart) + omT + voP\n const span = tableContPages(o.el, ty, MT, BODY_H, ctxBase.extentMemo, PH - MT - BODY_H, cellFloatSpan(MT, BODY_H, ctxBase.extentMemo, PH - MT - BODY_H))\n // 쪽을 넘는 표 아래 앵커 문단의 쪽 리셋 뒤 줄은 표가 끝나는 쪽 다음부터 — 한컴은 앵커 줄을 저장 높이(sz) 기준 표 바닥 아래에 두고,\n // 리셋 뒤 줄은 표가 다 끝난 뒤의 쪽 기준으로 저장한다(한컴 PDF: 칸 글로 세 쪽에 걸친 틀 표(sz 67886) 아래 68223 앵커 줄 뒤\n // 리셋 줄의 인라인 틀 표가 4쪽 맨 위). 리셋이 없는 문단은 다음 문단을 표 끝 쪽으로 보내는 종전 규칙. 표 위 = 앵커 줄 − sz − 바깥 아래 여백\n const anchorPage = pagesOf[segK]\n const sp = !o.inline && !stay && nonPush === undefined && segV - (omT + o.height + omB) >= -100 && pagesOf.some((pg, j) => j > segK && pg > anchorPage)\n ? tableContPages(o.el, MT + segV - o.height - omB, MT, BODY_H, ctxBase.extentMemo, PH - MT - BODY_H, cellFloatSpan(MT, BODY_H, ctxBase.extentMemo, PH - MT - BODY_H))\n : undefined\n if (sp && sp.pages > 0) {\n for (let j = segK + 1; j < pagesOf.length; j++) if (pagesOf[j] > anchorPage) pagesOf[j] += sp.pages\n cur += sp.pages\n lastPage = pagesOf[pagesOf.length - 1]\n continue\n }\n if (span.pages > 0 && (pagesOf[0] ?? cur) + span.pages > pendingEnd) { pendingEnd = (pagesOf[0] ?? cur) + span.pages; pendingEndY = span.endY - MT }\n }\n }\n nPages = Math.max(nPages, cur + 1, pendingEnd + 1)\n tableEndPage = Math.max(tableEndPage, pendingEnd)\n }\n }\n\n // 문서 끝의 빈 문단만 든 쪽은 찍지 않는다(한컴 PDF: 쪽 나누기 걸린 빈 끝 문단이 있는 서식 14개가 그 쪽 없이 끝난다 — 구역 사이의 빈 쪽은\n // 찍는다, 편람 양면 간지). 글·개체가 있는 마지막 쪽(이어지는 표 포함)까지만 두고, 그 뒤 빈 문단은 그 쪽에 남긴다\n if (lastSection) {\n let lastContent = -1\n for (const p of elements(root)) {\n if (ln(p) !== \"p\") continue\n const pg = paraSegPages.get(p)\n if (!pg?.length) continue\n const pm = buildPara(p)\n if (pm.objs.length || pm.chars.some(c => c.ch.trim() !== \"\" || !!c.ctrlText)) lastContent = Math.max(lastContent, ...pg)\n }\n const contentOnly = lastContent\n lastContent = Math.max(lastContent, tableEndPage)\n // 쪽 나누기 없이 넘어간 빈 끝 문단은, 앞 쪽 내용(개체 포함)이 본문 안에 다 들고 쪽을 넘는 떠 있는 표 때문이 아니면 그 쪽을 찍는다\n // (한컴 PDF: 본문 67918 에 든 인라인 표 66698 뒤 빈 문단 → 2쪽. 본문보다 큰 인라인 표 76123 뒤 빈 문단 → 1쪽)\n let keepTrail = false\n if (lastContent >= 0 && nPages - 1 > lastContent && tableEndPage <= contentOnly) {\n let firstTrail: Element | undefined\n for (const p of elements(root)) if (ln(p) === \"p\" && (paraSegPages.get(p) ?? []).some(x => x > lastContent)) { firstTrail = p; break }\n let fits = true\n for (const p of elements(root)) {\n if (ln(p) !== \"p\") continue\n const pg = paraSegPages.get(p)\n if (!pg?.includes(lastContent)) continue\n const pm = buildPara(p)\n pm.segs.forEach((sg, k) => {\n if (pg[k] !== lastContent) return\n let h = sg.textheight\n for (const o of pm.objs) if (o.inline) h = Math.max(h, o.height)\n if (sg.vertpos + h > BODY_H) fits = false\n })\n }\n keepTrail = !!firstTrail && firstTrail.getAttribute(\"pageBreak\") !== \"1\" && fits\n }\n if (lastContent >= 0 && nPages - 1 > lastContent && !keepTrail) {\n for (const [p, pg] of paraSegPages) if (pg.some(x => x > lastContent)) paraSegPages.set(p, pg.map(x => Math.min(x, lastContent)))\n nPages = lastContent + 1\n }\n }\n // 리셋이 없는데 본문이 페이지를 넘는 파일(누적 vertpos 기록본) 방어 —\n // 한 페이지로 두되 캔버스만 내용 끝까지 늘려 잘림을 막는다. (region 클램프에 쓰므로 그리기 전에 확정)\n const pageH = nPages === 1 ? Math.max(PH, MT + maxTopV + 2000) : PH\n // 미주 배치를 먼저 — 미주로 늘어난 쪽에도 머리말·꼬리말·바탕쪽이 붙는다\n const ens = endNoteLayout(root, paraSegPages, geom)\n const ctx: Ctx = {\n ...ctxBase,\n pages: Array.from({ length: Math.max(nPages, ens?.pageCount ?? 0) }, () => []),\n page: 0,\n geom,\n pageH,\n paintJobs: [],\n regionRotations: [],\n }\n // 맞쪽 짝수 쪽 — 본문·각주·미주는 이동 묶음으로, 바탕쪽·머리말·꼬리말은 영역 원점을 옮긴다(용지 기준 개체는 제자리)\n const mirrorDx = (page: number): number => (geom.mirrorDx && (ctx.pageBase + page + 1) % 2 === 0 ? geom.mirrorDx : 0)\n for (const story of pageStories(root, masters, paraSegPages, ctx.pages.length, ctx.pageBase, geom)) {\n prepareDeletedRanges(story.sub)\n if (doReflow) reflowSection(story.sub, ctx.styles, { BODY_W: story.width, BODY_H: 0 }, reflowMode)\n const draw = (): void => {\n ctx.page = story.page\n for (const p of elements(story.sub)) if (ln(p) === \"p\") drawPara(p, story.x + mirrorDx(story.page), story.y, story.width, ctx, 0)\n }\n if (story.layer !== undefined) ctx.paintJobs!.push({ page: story.page, layer: story.layer, z: 0, draw })\n else draw()\n }\n ctx.page = 0\n const bodyStart = ctx.pages.map(b => b.length)\n if (geom.mirrorDx) ctx.bodyDx = mirrorDx\n ctx.cols = multiCol ? { w: colW, gap: colGap } : undefined\n ctx.paraTops = paraTops\n if (backPlace.size) ctx.objPlace = new Map([...(ctx.objPlace ?? []), ...backPlace])\n for (const p of elements(root)) {\n if (ln(p) !== \"p\") continue\n drawPara(p, ML, MT, BODY_W, ctx, 0, paraSegPages.get(p))\n }\n ctx.cols = undefined\n ctx.paraTops = undefined\n // 쪽 아래 각주 — 구분선과 각주 내용(본문 바닥에서 각주 영역만큼 위)\n const notes = footNoteStories(root, paraSegPages, geom)\n for (const r of notes.rules) {\n ctx.page = r.page\n emit(ctx, `<line x1=\"${pt(r.x)}\" y1=\"${pt(r.y)}\" x2=\"${pt(r.x + r.length)}\" y2=\"${pt(r.y)}\" stroke=\"${escapeXml(r.color)}\" stroke-width=\"${(r.widthMm * 2.834645).toFixed(2)}\"/>`)\n }\n for (const story of notes.stories) {\n ctx.page = story.page\n for (const p of elements(story.sub)) if (ln(p) === \"p\") drawPara(p, story.x, story.y, story.width, ctx, 0)\n }\n // 미주 — 본문 끝 뒤에 단·쪽을 넘기며 흘린다(쪽이 모자라면 늘린다 — 쪽 수는 머리말·바탕쪽 전에 정했다)\n if (ens) {\n for (const r of ens.rules) {\n ctx.page = r.page\n emit(ctx, `<line x1=\"${pt(r.x)}\" y1=\"${pt(r.y)}\" x2=\"${pt(r.x + r.length)}\" y2=\"${pt(r.y)}\" stroke=\"${escapeXml(r.color)}\" stroke-width=\"${(r.widthMm * 2.834645).toFixed(2)}\"/>`)\n }\n // 미주 문단의 떠 있는 개체도 앵커 줄이 든 단 기준(미주 줄 horzpos 에 단 오프셋을 넣었다)\n ctx.cols = multiCol ? { w: colW, gap: colGap } : undefined\n for (const e of ens.paras) drawPara(e.p, ML, MT, BODY_W, ctx, 0, e.pages)\n ctx.cols = undefined\n }\n const wrapMirror = (bufs: string[][], from: (page: number) => number): void => {\n for (let page = 0; page < bufs.length; page++) {\n const dx = mirrorDx(page), at = from(page)\n if (!dx || !bufs[page] || bufs[page].length <= at) continue\n bufs[page].splice(at, 0, `<g transform=\"translate(${pt(dx)} 0)\">`)\n bufs[page].push(\"</g>\")\n }\n }\n ctx.bodyDx = undefined\n wrapMirror(ctx.pages, page => bodyStart[page] ?? 0)\n // 쪽 테두리·단 구분선(미주 쪽 포함), 쪽 번호 — 그 컨트롤이 나온 쪽부터 쪽 아래(또는 위) 여백에 \"기호 N 기호\". 글자 크기는 10pt 고정,\n // 기준선은 아래 여백 위(한컴 PDF 실측: 글자 모양 크기와 무관하게 9.95pt, 가로 쪽 가운데, 기준선 = 쪽 높이 − 아래 여백 − 약 225). pageHiding hidePageNum 쪽은 뺀다\n const allPages = new Map(paraSegPages)\n for (const e of ens?.paras ?? []) allPages.set(e.p, e.pages)\n drawPageDecor(root, allPages, ctx, localCols ? nCol : 1, colW, colGap)\n drawPageNumbers(root, paraSegPages, ctx)\n ctx.page = 0\n const normal = ctx.pages\n const jobs = ctx.paintJobs!\n ctx.paintJobs = null\n const behind = Array.from({ length: ctx.pages.length }, () => [] as string[])\n const front = Array.from({ length: ctx.pages.length }, () => [] as string[])\n for (const job of jobs.sort((a, b) => a.layer - b.layer || a.z - b.z)) {\n ctx.pages = job.layer < 0 ? behind : front\n const before = ctx.pages.map(b => b.length)\n ctx.bodyDx = job.body ? mirrorDx : undefined\n job.draw()\n ctx.bodyDx = undefined\n if (job.body && geom.mirrorDx) wrapMirror(ctx.pages, page => before[page] ?? 0)\n }\n // 떠 있는 표가 쪽을 넘겨 이어지면 behind/front 쪽 버퍼가 늘어난다 — 세 버퍼 중 가장 긴 쪽 수로 맞춘다\n const total = Math.max(normal.length, behind.length, front.length)\n ctx.pages = Array.from({ length: total }, (_, page) => [...(behind[page] ?? []), ...(normal[page] ?? []), ...(front[page] ?? [])])\n return { pages: ctx.pages, pageH }\n}\n\n/**\n * 쪽 테두리(secPr pageBorderFill)와 단 구분선(colPr colLine).\n * 테두리는 용지 가장자리에서 오프셋만큼 안쪽 사각형(한컴 PDF 실측: 오프셋 왼쪽 1984 → x 19.84pt, 위 5669 → y 56.69pt), 쪽 짝·홀은 type 으로 고른다.\n * 단 구분선은 단 사이 가운데에 본문 위부터 그 쪽 마지막 줄 바닥까지(PDF: 두 단 시험지 297.6pt, 68.0 → 쪽마다 내용 끝)\n */\nfunction drawPageDecor(root: Element, paraPages: Map<Element, number[]>, ctx: Ctx, nCol: number, colW: number, colGap: number): void {\n const { PW, PH, ML, MT } = ctx.geom\n const secPr = findFirst(root, \"secPr\")\n const fills = secPr ? elements(secPr).filter(e => ln(e) === \"pageBorderFill\") : []\n const pageBottoms = new Map<number, number>()\n if (nCol > 1) for (const p of elements(root)) if (ln(p) === \"p\") {\n const lsa = findChildByLocalName(p, \"linesegarray\"), pages = paraPages.get(p) ?? []\n elements(lsa ?? p).filter(e => ln(e) === \"lineseg\").forEach((seg, k) => {\n const pg = pages[k] ?? pages[0] ?? 0\n pageBottoms.set(pg, Math.max(pageBottoms.get(pg) ?? 0, num(seg, \"vertpos\") + num(seg, \"vertsize\")))\n })\n }\n const colPr = findFirst(root, \"colPr\"), colLine = colPr ? findChildByLocalName(colPr, \"colLine\") : null\n for (let page = 0; page < ctx.pages.length; page++) {\n const n = ctx.pageBase + page + 1\n // 양쪽(BOTH) 항목이 선·배경을 가지면 그것, 아니면 그 쪽 짝·홀 항목(한컴 저장본은 세 항목을 늘 쓰고, PDF 는 BOTH 테두리를 홀·짝 쪽 모두에 그린다)\n const visible = (f: Element | undefined) => { const b = f ? ctx.styles.borderFill.get(f.getAttribute(\"borderFillIDRef\") ?? \"\") : undefined; return b && (b.top || b.bottom || b.left || b.right || b.fill) ? b : undefined }\n const both = fills.find(f => (f.getAttribute(\"type\") ?? \"BOTH\") === \"BOTH\"), parity = fills.find(f => f.getAttribute(\"type\") === (n % 2 ? \"ODD\" : \"EVEN\"))\n const pf = visible(both) ? both : parity\n const bf = visible(pf)\n ctx.page = page\n if (pf && bf && (bf.top || bf.bottom || bf.left || bf.right || bf.fill)) {\n const off = findChildByLocalName(pf, \"offset\")\n const x0 = num(off, \"left\"), y0 = num(off, \"top\"), x1 = PW - num(off, \"right\"), y1 = PH - num(off, \"bottom\")\n if (bf.fill && pf.getAttribute(\"fillArea\") !== \"NONE\") ctx.pages[page].unshift(`<rect x=\"${pt(x0)}\" y=\"${pt(y0)}\" width=\"${pt(x1 - x0)}\" height=\"${pt(y1 - y0)}\" fill=\"${escapeXml(bf.fill)}\"/>`)\n if (bf.top) emit(ctx, edgeLine(x0, y0, x1, y0, bf.top))\n if (bf.bottom) emit(ctx, edgeLine(x0, y1, x1, y1, bf.bottom))\n if (bf.left) emit(ctx, edgeLine(x0, y0, x0, y1, bf.left))\n if (bf.right) emit(ctx, edgeLine(x1, y0, x1, y1, bf.right))\n }\n const bottom = pageBottoms.get(page)\n if (colLine && (colLine.getAttribute(\"type\") ?? \"NONE\") !== \"NONE\" && bottom) {\n const edge: RenderBorderEdge = { type: colLine.getAttribute(\"type\") ?? \"SOLID\", widthPt: (Number.parseFloat(colLine.getAttribute(\"width\") ?? \"0.12\") || 0.12) * 2.834645, color: colLine.getAttribute(\"color\") ?? \"#000000\" }\n for (let c = 1; c < nCol; c++) { const x = ML + c * (colW + colGap) - colGap / 2; emit(ctx, edgeLine(x, MT, x, MT + bottom, edge)) }\n }\n }\n}\n\nfunction drawPageNumbers(root: Element, paraPages: Map<Element, number[]>, ctx: Ctx): void {\n let decl: { el: Element; page: number; prId: string | null } | undefined\n const hidden = new Set<number>()\n for (const p of elements(root)) if (ln(p) === \"p\") {\n const page = paraPages.get(p)?.[0] ?? 0\n for (const run of elements(p)) if (ln(run) === \"run\") for (const ctrl of elements(run)) if (ln(ctrl) === \"ctrl\") {\n const pn = findChildByLocalName(ctrl, \"pageNum\"), ph = findChildByLocalName(ctrl, \"pageHiding\")\n if (pn && !decl) decl = { el: pn, page, prId: run.getAttribute(\"charPrIDRef\") }\n if (ph && num(ph, \"hidePageNum\")) hidden.add(page)\n }\n }\n if (!decl) return\n const pos = decl.el.getAttribute(\"pos\") ?? \"BOTTOM_CENTER\"\n if (pos === \"NONE\") return\n const side = decl.el.getAttribute(\"sideChar\") ?? \"\"\n // 글꼴은 \"쪽 번호\" 스타일의 글자 모양(한컴 PDF: 그 스타일이 굴림이면 굴림, 함초롬돋움이면 함초롬돋움 — 컨트롤이 든 글자 모양과 무관). 크기는 10pt 고정\n const pnId = ctx.styles.pageNumCharPr ?? decl.prId\n const st = (pnId != null ? ctx.styles.charPr.get(pnId) : undefined) ?? DEFAULT_CHAR\n const { PH, ML, BODY_W } = ctx.geom\n const pagePr = findFirst(root, \"pagePr\"), margin = pagePr ? findChildByLocalName(pagePr, \"margin\") : null\n const h = 1000\n for (let page = decl.page; page < ctx.pages.length; page++) {\n if (hidden.has(page)) continue\n const n = ctx.pageBase + page + 1\n const text = side ? `${side} ${formatHeadNumber(n, decl.el.getAttribute(\"formatType\") ?? \"DIGIT\")} ${side}` : formatHeadNumber(n, decl.el.getAttribute(\"formatType\") ?? \"DIGIT\")\n const w = measureTextWidth(text, h, 100, { faceClass: faceClassOf(st.face) })\n // 가운데는 본문 영역 가운데(같은 판 한컴 PDF: 왼 5669·오른 6028 여백 쪽의 \"- 1 -\" 이 용지 가운데보다 1.8pt 왼쪽)\n const x = /LEFT/.test(pos) ? ML : /RIGHT/.test(pos) ? ML + BODY_W - w : ML + (BODY_W - w) / 2\n // 아래쪽 번호는 꼬리말 영역 바닥(아래 여백 위)에 놓인다 — 꼬리말 영역이 0 이면 아래 여백 가운데 위(한컴 PDF: 아래 2834·꼬리말 0 쪽 번호 기준선 쪽 위에서 825.3pt)\n const y = /^TOP/.test(pos) ? num(margin, \"top\", 5668) - 225 : num(margin, \"footer\", 0) > 0 ? PH - num(margin, \"bottom\", 4252) - 225 : PH - Math.round(num(margin, \"bottom\", 4252) / 2) - 243\n const attrs = [`x=\"${pt(x)}\"`, `y=\"${pt(y)}\"`, `font-size=\"${pt(h)}\"`]\n if (st.fontFamily) attrs.push(`font-family=\"${escapeXml(st.fontFamily)}\"`)\n ctx.page = page\n emit(ctx, `<text ${attrs.join(\" \")}>${escapeXml(text)}</text>`)\n }\n}\n\n/** 내부 렌더 산출 — 구역별 페이지 버퍼 + 공유 defs·region. 세로 스택/페이지별 SVG 조립의 공통 입력 */\nexport interface InternalRender {\n sections: RenderedSection[]\n defs: string[]\n warnings: string[]\n stats: Ctx[\"stats\"]\n regions: RenderRegion[]\n}\n\n/** 이미지 참조(binaryItemIDRef) → dataURI (심볼 id 는 렌더 중 발급) */\nexport type RenderImages = Ctx[\"images\"]\n\n/** 렌더할 구역 DOM — HWPX section*.xml 또는 HWP5 어댑터가 합성한 동형 DOM (hwp5-scene) */\nexport interface SectionRoot {\n root: Element\n index: number\n masterPages?: Element[]\n /** False only when the source XML proved no deletion markers; custom DOMs default to scanning. */\n hasDeletionMarkers?: boolean\n}\n\nexport interface SectionRenderInput {\n styles: RenderStyles\n images: RenderImages\n /** 로딩 단계 경고를 이어받아 렌더 경고를 누적한다 */\n warnings: string[]\n reflow: boolean\n reflowMode: WrapMode\n highlights?: string[]\n}\n\n/**\n * 구역 DOM 들 → 페이지 버퍼 (포맷 무관 공용 단계). 공유 자원(styles/images/defs/warnings/stats/region)은\n * 전 구역에 누적된다 — 이미지 심볼 dataURI 중복 방지·전역 페이지 번호·결정적 region id.\n */\nexport function renderSectionRoots(sections: SectionRoot[], input: SectionRenderInput): InternalRender {\n const ctxBase: Omit<Ctx, \"pages\" | \"page\" | \"geom\" | \"pageH\" | \"paintJobs\" | \"regionRotations\"> = {\n draw: { table: drawTable, pic: drawPic, picFrame: drawPicFrame },\n styles: input.styles, images: input.images, defs: [],\n highlights: (input.highlights ?? []).map(s => s.trim().toLowerCase()).filter(s => s.length > 0),\n warnings: input.warnings, warned: new Set(), stats: { texts: 0, images: 0, tables: 0, shapes: 0 },\n extentMemo: { cell: new WeakMap(), table: new WeakMap(), paraGeom: input.styles.paraGeom },\n regions: new RegionCollector(), parentStack: [], pageBase: 0, nums: new Map(),\n }\n const rendered: RenderedSection[] = []\n // 문서 끝의 빈 구역(글·개체 없는 문단만)은 찍지 않는다 — 한컴 PDF: 서식 뒤 빈 구역 둘이 붙은 문서가 서식 2쪽만으로 끝난다.\n // 내용 있는 마지막 구역이 문서의 마지막 구역 역할(끝 빈 쪽 버림)을 한다\n const hasContent = (root: Element): boolean => elements(root).some(p => {\n if (ln(p) !== \"p\") return false\n const pm = buildPara(p)\n return pm.objs.length > 0 || pm.chars.some(c => c.ch.trim() !== \"\" || !!c.ctrlText)\n })\n let lastIdx = sections.length - 1\n while (lastIdx > 0 && !hasContent(sections[lastIdx].root)) lastIdx--\n for (const [k, { root, index, masterPages, hasDeletionMarkers }] of sections.entries()) {\n if (k > lastIdx) break\n const geom = readSectionGeom(root)\n const { pages, pageH } = renderSectionToPages(root, geom, ctxBase, input.reflow, input.reflowMode, masterPages, hasDeletionMarkers, k === lastIdx)\n rendered.push({ pages, PW: geom.PW, pageH, clipId: `pgclip${index}` })\n ctxBase.pageBase += pages.length\n }\n if (rendered.length === 0) throw new KordocError(\"렌더할 구역이 없습니다\")\n return { sections: rendered, defs: ctxBase.defs, warnings: input.warnings, stats: ctxBase.stats, regions: ctxBase.regions.regions }\n}\n\nconst SVG_FONT_FAMILY = `'HCR Batang','함초롬바탕','Hancom Batang',AppleMyungjo,'Noto Serif CJK KR',serif`\n\n/**\n * HWPX(한컴 저장본) → 구역별 페이지 버퍼. 조판 캐시(linesegarray)가 없는 구역은 reflow 옵션으로\n * 합성 조판(없으면 그 구역 생략); 렌더 가능한 구역이 하나도 없으면 KordocError.\n */\nasync function renderHwpxInternal(input: ArrayBuffer | Uint8Array, options?: RenderSvgOptions): Promise<InternalRender> {\n const maxImg = options?.maxImageBytes ?? 40 * 1024 * 1024\n // 압축폭탄 가드 — 파서 진입점과 동일하게 압축해제 전 central directory 선언 크기를 검사한다.\n // 렌더 이미지 캡은 f.async 로 엔트리를 전량 압축해제한 뒤에야 크기를 보므로, 단일 BinData\n // 압축폭탄(수 GB 선언)이 캡을 우회해 OOM 을 유발하던 것을 원천 차단한다 (reflow-1).\n const ab = input instanceof Uint8Array\n ? input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength) as ArrayBuffer\n : input\n precheckZipSize(ab, MAX_DECOMPRESS_SIZE, MAX_ZIP_ENTRIES)\n let zip: JSZip\n try {\n zip = await JSZip.loadAsync(input)\n } catch {\n throw new KordocError(\"HWPX(ZIP) 형식이 아닙니다 — 렌더는 HWPX만 지원\")\n }\n // 모든 구역 파일 (section0, section1, … — 파서와 같은 번호 순. 이름 정렬이면 section10 이 section2 앞에 온다)\n const secFiles = zip.file(/Contents\\/section\\d+\\.xml$/i).sort((a, b) => compareSectionPaths(a.name, b.name))\n if (secFiles.length === 0) throw new KordocError(\"Contents/section0.xml 없음 — HWPX가 아니거나 손상됨\")\n\n const warnings: string[] = []\n const headFile = zip.file(\"Contents/header.xml\") ?? zip.file(\"Contents/head.xml\")\n const verFile = zip.file(\"version.xml\")\n const verXml = verFile ? await readZipEntry(verFile, \"text\") : undefined\n const appMajor = hwpxAppMajor(verXml), appBuild = hwpxAppBuild(verXml)\n const headXml = headFile ? await readZipEntry(headFile, \"text\") : undefined\n let styles: RenderStyles = headXml\n ? parseRenderStyles(headXml, { appMajor, appBuild })\n : { charPr: new Map(), paraAlign: new Map(), paraGeom: new Map(), borderFill: new Map() }\n if (!headFile) warnings.push(\"header.xml 없음 — 기본 스타일로 렌더\")\n\n // 구역 XML 선로딩 + 크기 가드\n const secXmls: string[] = []\n for (const f of secFiles) {\n const xml = await readZipEntry(f, \"text\")\n if (xml.length > MAX_DECOMPRESS_SIZE) throw new KordocError(\"섹션 XML이 허용 크기를 초과\")\n secXmls.push(xml)\n }\n\n // KoPub 이 없는 PC 에서 대체 글꼴로 조판된 문서 — 저장 줄 나눔이 대체 글꼴 폭에 맞으면 그 폭으로 그린다(font-env)\n if (headXml && hasKoPubSubst(headXml)) {\n const alt = parseRenderStyles(headXml, { appMajor, appBuild, substKoPub: true })\n if (kopubSubstituted(secXmls, styles, alt)) styles = alt\n }\n\n const masterPages = new Map<string, Element>()\n const masterXmls: string[] = []\n for (const file of zip.file(/Contents\\/masterpage[^/]*\\.xml$/i)) {\n const xml = await readZipEntry(file, \"text\")\n if (xml.length > MAX_DECOMPRESS_SIZE) throw new KordocError(\"바탕쪽 XML이 허용 크기를 초과\")\n const root = createXmlParser().parseFromString(xml, \"text/xml\").documentElement as unknown as Element\n if (root && ln(root) === \"masterPage\") {\n masterPages.set(root.getAttribute(\"id\") || file.name.replace(/^.*\\/|\\.xml$/g, \"\"), root)\n masterXmls.push(xml)\n }\n }\n\n // BinData 매니페스트 (id → href) — content.hpf 우선, 파일명 휴리스틱 폴백\n const binmap = new Map<string, string>()\n const hpf = zip.file(/content\\.hpf$/i)[0]\n if (hpf) {\n const man = await readZipEntry(hpf, \"text\")\n for (const m of man.matchAll(/<[^>]*\\bid=\"([^\"]+)\"[^>]*\\bhref=\"(BinData\\/[^\"]+)\"[^>]*>/g)) binmap.set(m[1], m[2])\n for (const m of man.matchAll(/<[^>]*\\bhref=\"(BinData\\/[^\"]+)\"[^>]*\\bid=\"([^\"]+)\"[^>]*>/g)) binmap.set(m[2], m[1])\n }\n // 참조된 이미지만 선로딩 — 전 구역 ref 합집합 (DOM 워크 전에 async 구간 종료).\n // 장당 캡(maxImg) 외에 개수·누적 바이트 캡 — distinct 다수/대형 반복 참조로\n // 렌더 경로에서만 OOM 가능하던 구멍(파서 경로의 ZIP bomb 가드에 상응)\n const MAX_IMAGE_REFS = 256\n const MAX_TOTAL_IMAGE_BYTES = 128 * 1024 * 1024\n const images: Ctx[\"images\"] = new Map()\n const refs = new Set<string>()\n for (const xml of [...secXmls, ...masterXmls]) for (const m of xml.matchAll(/binaryItemIDRef=\"([^\"]+)\"/g)) refs.add(m[1])\n let totalImgBytes = 0\n for (const ref of refs) {\n if (images.size >= MAX_IMAGE_REFS) {\n warnings.push(`이미지 ${refs.size}종 중 ${MAX_IMAGE_REFS}종만 로딩 — 개수 한도 초과분 생략`)\n break\n }\n let href = binmap.get(ref)\n if (!href) {\n const cand = zip.file(new RegExp(`BinData/.*${ref.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}`, \"i\"))[0]\n href = cand?.name\n }\n if (!href) continue\n const f = zip.file(href) ?? zip.file(\"Contents/\" + href)\n if (!f) continue\n const bytes = await readZipEntry(f, \"uint8array\")\n if (bytes.length > maxImg) {\n warnings.push(`이미지 ${href} ${(bytes.length / 1048576).toFixed(1)}MB — 한도 초과로 생략`)\n continue\n }\n if (totalImgBytes + bytes.length > MAX_TOTAL_IMAGE_BYTES) {\n warnings.push(`이미지 누적 ${Math.round(MAX_TOTAL_IMAGE_BYTES / 1048576)}MB 한도 초과 — 이후 생략`)\n break\n }\n totalImgBytes += bytes.length\n images.set(ref, { dataUri: `data:${sniffMime(href, bytes)};base64,${Buffer.from(bytes).toString(\"base64\")}` })\n }\n\n // 구역 XML → DOM. 조판 캐시 없는 구역은 reflow 옵션이 없으면 생략\n const roots: SectionRoot[] = []\n let noCacheSkipped = false\n /** 앞 구역까지 정의된 짝수·홀수 쪽 바탕쪽 — 한쪽만 정의한 구역은 나머지 한쪽을 이어받는다 */\n const lastParity = new Map<string, Element>()\n for (let si = 0; si < secXmls.length; si++) {\n const secXml = secXmls[si]\n // 태그 마크업만 매치 — 본문 텍스트에 \"linesegarray\"가 있어도 캐시로 오판하지 않는다\n // (본문의 <는 XML에서 &lt;로 이스케이프되므로 리터럴 <…linesegarray는 태그뿐)\n const hasCache = /<(?:[A-Za-z][\\w.-]*:)?linesegarray[\\s/>]/.test(secXml)\n if (!hasCache && !options?.reflow) {\n noCacheSkipped = true\n warnings.push(`구역 ${si}: 조판 캐시 없음 — reflow 옵션 필요, 생략`)\n continue\n }\n const doc = createXmlParser().parseFromString(secXml, \"text/xml\")\n const root = doc.documentElement as unknown as Element\n if (!root) { warnings.push(`구역 ${si} XML 파싱 실패 — 생략`); continue }\n const secPr = findFirst(root, \"secPr\")\n const referenced = secPr ? elements(secPr).filter(el => ln(el) === \"masterPage\").map(el => masterPages.get(el.getAttribute(\"idRef\") || \"\")).filter((el): el is Element => !!el) : []\n // 짝·홀 쪽 바탕쪽 중 한쪽만 정의한 구역은 다른 쪽을 앞 구역에서 이어받는다(한컴 PDF: 짝수·홀수를 정의한 1구역 뒤 홀수만 정의한\n // 2~10구역의 짝수 쪽마다 1구역 짝수 바탕쪽 머리말 — 짝수를 새로 정의한 11구역부터 바뀜). 양쪽(BOTH)을 정의하면 이어받지 않는다\n const typeOf = (m: Element): string => m.getAttribute(\"type\") || \"BOTH\"\n const has = (t: string): boolean => referenced.some(m => typeOf(m) === t)\n if (!has(\"BOTH\")) for (const [t, other] of [[\"EVEN\", \"ODD\"], [\"ODD\", \"EVEN\"]] as const) {\n const prev = lastParity.get(t)\n if (prev && !has(t) && has(other)) referenced.unshift(prev)\n }\n for (const m of referenced) if (typeOf(m) === \"EVEN\" || typeOf(m) === \"ODD\") lastParity.set(typeOf(m), m)\n if (has(\"BOTH\")) lastParity.clear()\n roots.push({ root, index: si, masterPages: referenced, hasDeletionMarkers: secXml.includes(\"deleteBegin\") || secXml.includes(\"deleteEnd\") })\n }\n\n if (roots.length === 0) {\n if (noCacheSkipped) {\n throw new KordocError(\"조판 캐시(linesegarray) 없음 — 한컴에서 저장한 HWPX만 렌더 가능 (reflow 옵션으로 합성 렌더 가능)\")\n }\n throw new KordocError(\"렌더할 구역이 없습니다 — HWPX가 손상되었을 수 있습니다\")\n }\n return renderSectionRoots(roots, { styles, images, warnings, reflow: !!options?.reflow, reflowMode: options?.reflowMode ?? \"keep\", highlights: options?.highlights })\n}\n\n/**\n * HWPX(한컴 저장본) → 레이아웃 보존 SVG. **전 구역(section*)을 세로 스택으로** 렌더한다.\n * 조판 캐시(linesegarray)가 없는 구역은 reflow 옵션으로 합성 조판(없으면 그 구역 생략);\n * 렌더 가능한 구역이 하나도 없으면 KordocError.\n */\nexport async function renderHwpxToSvg(input: ArrayBuffer | Uint8Array, options?: RenderSvgOptions): Promise<RenderSvgResult> {\n const r = await renderHwpxInternal(input, options)\n // 전 구역 페이지를 세로 스택으로 조립 (구역마다 page 크기 상이 가능 → 구역별 clip)\n const GAP = 2400 // 페이지 사이 시각 간격 (24pt)\n const clipDefs: string[] = []\n const groups: string[] = []\n let y = 0\n let maxPW = 0\n let pageNo = 0\n for (const rs of r.sections) {\n maxPW = Math.max(maxPW, rs.PW)\n clipDefs.push(`<clipPath id=\"${rs.clipId}\"><rect x=\"0\" y=\"0\" width=\"${pt(rs.PW)}\" height=\"${pt(rs.pageH)}\"/></clipPath>`)\n for (const buf of rs.pages) {\n pageNo++\n groups.push(\n `<g data-page=\"${pageNo}\" transform=\"translate(0 ${pt(y)})\">` +\n `<rect width=\"${pt(rs.PW)}\" height=\"${pt(rs.pageH)}\" fill=\"white\" stroke=\"#c9c7c4\" stroke-width=\"0.75\"/>` +\n `<g clip-path=\"url(#${rs.clipId})\">\\n${buf.join(\"\\n\")}\\n</g></g>`,\n )\n y += rs.pageH + GAP\n }\n }\n const totalH = Math.max(0, y - GAP)\n\n // width/height는 pt 단위 명시 — 단위 없는 px로 두면 A4 실물(96dpi 기준)보다 25% 작게 보인다 (v3.10.1)\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${pt(maxPW)} ${pt(totalH)}\" width=\"${pt(maxPW)}pt\" height=\"${pt(totalH)}pt\" font-family=\"${SVG_FONT_FAMILY}\" xml:space=\"preserve\">\\n` +\n `<defs>${clipDefs.join(\"\")}${r.defs.join(\"\")}</defs>\\n` +\n `${groups.join(\"\\n\")}\\n</svg>`\n return { svg, width: Math.round(maxPW) / 100, height: Math.round(totalH) / 100, pageCount: pageNo, warnings: r.warnings, stats: r.stats, regions: r.regions }\n}\n\n/** 페이지별 독립 SVG 산출 — RenderScene 과 선택 페이지의 standalone SVG (#75 Task 3) */\nexport interface HwpxPagesResult {\n scene: RenderScene\n /** 페이지 번호(1-based) → standalone SVG. 선택된 페이지만 조립 */\n pageSvgs: Map<number, string>\n}\n\n/**\n * 페이지 버퍼 → 페이지별 독립 SVG + RenderScene (포맷 무관 조립 단계). `select` 가 있으면 그 페이지만 조립한다\n * (그리기 자체는 전 페이지 — 조립·래스터가 비싼 단계). 페이지 SVG 는 페이지 로컬 좌표(세로 스택 오프셋 없음),\n * 사용된 이미지 심볼만 defs 에 싣는다.\n */\nexport function assemblePageSvgs(\n r: InternalRender,\n format: RenderScene[\"format\"],\n select?: Set<number> | ((pageCount: number) => Set<number>),\n): HwpxPagesResult {\n const pages: RenderScene[\"pages\"] = []\n const pageSvgs = new Map<number, string>()\n const pageCount = r.sections.reduce((n, rs) => n + rs.pages.length, 0)\n const chosen = typeof select === \"function\" ? select(pageCount) : select\n let pageNo = 0\n for (const rs of r.sections) {\n for (const buf of rs.pages) {\n pageNo++\n pages.push({ page: pageNo, width: ptNum(rs.PW), height: ptNum(rs.pageH) })\n if (chosen && !chosen.has(pageNo)) continue\n const body = buf.join(\"\\n\")\n const used = new Set<string>()\n for (const m of body.matchAll(/href=\"#(bin\\d+)\"/g)) used.add(m[1])\n const defs = r.defs.filter(d => { const m = /<symbol id=\"(bin\\d+)\"/.exec(d); return m ? used.has(m[1]) : true })\n const clipId = `pgclip${pageNo}`\n pageSvgs.set(pageNo,\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${pt(rs.PW)} ${pt(rs.pageH)}\" width=\"${pt(rs.PW)}pt\" height=\"${pt(rs.pageH)}pt\" font-family=\"${SVG_FONT_FAMILY}\" xml:space=\"preserve\" data-page=\"${pageNo}\">\\n` +\n `<defs><clipPath id=\"${clipId}\"><rect x=\"0\" y=\"0\" width=\"${pt(rs.PW)}\" height=\"${pt(rs.pageH)}\"/></clipPath>${defs.join(\"\")}</defs>\\n` +\n `<rect width=\"${pt(rs.PW)}\" height=\"${pt(rs.pageH)}\" fill=\"white\"/>\\n` +\n `<g clip-path=\"url(#${clipId})\">\\n${body}\\n</g>\\n</svg>`)\n }\n }\n const scene: RenderScene = { format, pages, regions: r.regions, warnings: r.warnings, stats: { texts: r.stats.texts, tables: r.stats.tables, images: r.stats.images, shapes: r.stats.shapes } }\n return { scene, pageSvgs }\n}\n\n/** HWPX → 페이지별 독립 SVG (#75 Task 3). HWP5 는 hwp5-scene 의 renderHwp5Pages 가 같은 조립 단계를 쓴다 */\nexport async function renderHwpxPages(\n input: ArrayBuffer | Uint8Array,\n options?: RenderSvgOptions,\n select?: Set<number> | ((pageCount: number) => Set<number>),\n): Promise<HwpxPagesResult> {\n const r = await renderHwpxInternal(input, options)\n return assemblePageSvgs(r, \"hwpx\", select)\n}\n","/**\n * 레이아웃 보존 렌더 — 순수 계산 유틸 (XML 무접촉).\n * 좌표 산식은 .claude/plans/render-poc/findings.md에서 실측 검증된 모델.\n * 단위: HWPUNIT(1/7200in), pt 변환은 /100.\n */\n\n/** HWPX 좌표 속성은 uint32로 저장된 음수가 섞여 있다 (예: vertOffset=4294967103 = -193) */\nexport function toInt32(v: string | undefined, fallback = 0): number {\n if (v == null || v === \"\") return fallback\n const n = Number(v)\n if (!Number.isFinite(n)) return fallback\n return n > 0x7fffffff ? n - 0x100000000 : n\n}\n\n/** 셀 하나가 주는 경계 제약: boundary[a] + size = boundary[b] */\nexport interface SpanConstraint {\n a: number\n b: number\n size: number\n}\n\n/**\n * 표 열 경계 솔버 — 경계 전파.\n * 결재문서 트레일러처럼 41열 그리드에 span-1 셀이 거의 없어도,\n * x[ca+cs] = x[ca] + w 제약을 고정점까지 전파하면 전 경계가 풀린다 (실측 검증).\n * 미해결 경계는 인접 확정 경계 사이 균등 보간.\n */\nexport function solveBoundaries(constraints: SpanConstraint[], count: number, total?: number): number[] {\n const x = new Array<number | undefined>(count + 1).fill(undefined)\n x[0] = 0\n if (total != null && total > 0) x[count] = total\n let changed = true\n let guard = 0\n while (changed && guard++ < count + 8) {\n changed = false\n for (const c of constraints) {\n if (c.a < 0 || c.b > count || c.a >= c.b) continue\n const xa = x[c.a]\n const xb = x[c.b]\n if (xa != null && xb == null) {\n x[c.b] = xa + c.size\n changed = true\n } else if (xb != null && xa == null) {\n x[c.a] = xb - c.size\n changed = true\n }\n }\n }\n // 잔여 미해결 경계 — 좌우 확정 경계 사이 균등 보간\n let i = 0\n while (i <= count) {\n if (x[i] != null) { i++; continue }\n let lo = i - 1\n let hi = i\n while (hi <= count && x[hi] == null) hi++\n const loV = x[lo] as number\n const hiV = hi <= count ? (x[hi] as number) : loV + (hi - lo) * 1000\n const n = hi - lo\n for (let k = 1; k < n; k++) x[lo + k] = loV + ((hiV - loV) * k) / n\n if (hi > count) x[count] = hiV\n i = hi\n }\n // 단조 보정 (모순 제약 방어)\n const out = x as number[]\n for (let k = 1; k <= count; k++) if (out[k] < out[k - 1]) out[k] = out[k - 1]\n return out\n}\n\n/**\n * 열 경계 = 칸을 왼쪽부터 이은 가장 긴 길(x[b] = max(x[a] + 칸 너비), 열 너비는 음수가 아니다). 행마다 칸 너비 합이 다르게 저장된\n * 표에서 한컴은 경계마다 거기서 끝나는 칸 중 가장 먼 끝을 잡는다 — 그 길의 끝이 표 sz 너비와 같다. 전체 폭 칸은 끝만 정하므로 빼고\n * 잰다(빼지 않으면 그 칸 하나로 끝이 늘 표 너비가 된다). tight[k] 는 경계 k 가 그 가장 긴 길 위에 있는가(x[k] + 끝까지 가장 긴 길 = 끝).\n * 닿지 않는 경계가 있으면 null\n */\nexport function longestPathBoundaries(constraints: SpanConstraint[], count: number): { x: number[]; tight: boolean[] } | null {\n const inner = constraints.filter(c => c.a >= 0 && c.b <= count && c.a < c.b && !(c.a === 0 && c.b === count))\n const x = new Array<number>(count + 1).fill(Number.NEGATIVE_INFINITY)\n x[0] = 0\n for (let k = 1; k <= count; k++) {\n for (const c of inner) if (c.b === k && x[c.a] > Number.NEGATIVE_INFINITY) x[k] = Math.max(x[k], x[c.a] + c.size)\n if (x[k] === Number.NEGATIVE_INFINITY) return null\n x[k] = Math.max(x[k], x[k - 1])\n }\n const y = new Array<number>(count + 1).fill(Number.NEGATIVE_INFINITY)\n y[count] = 0\n for (let k = count - 1; k >= 0; k--) {\n y[k] = y[k + 1]\n for (const c of inner) if (c.a === k && y[c.b] > Number.NEGATIVE_INFINITY) y[k] = Math.max(y[k], c.size + y[c.b])\n }\n return { x, tight: x.map((v, k) => Math.abs(v + y[k] - x[count]) <= 2) }\n}\n\n/**\n * 표 열 경계 — 기본은 전파식(solveBoundaries). 가장 긴 길의 끝이 표 sz 너비(total)와 같고 전파식과 다른 경계가 모두 그 길 위에\n * 있으면 가장 긴 길을 쓴다(같은 판 PDF: 통계표 열 경계 9개가 0.1pt 안, 전파식은 먼저 나온 칸 너비로 4~23pt 어긋났다 — 코퍼스 표\n * 10,968개 중 46개가 이 조건)\n */\nexport function tableColumnBoundaries(constraints: SpanConstraint[], count: number, total?: number, noExactRow = false): number[] {\n const prop = solveBoundaries(constraints, count, total)\n if (!total || total <= 0) return prop\n const lp = longestPathBoundaries(constraints, count)\n // 칸 너비 합이 표 너비와 같은 행이 없으면(표 너비가 가장 긴 길에서 나왔으면) 길 위에 있지 않은 경계도 가장 긴 길 값 —\n // 같은 판 PDF: 그런 서식 표의 열 경계 11개가 다 가장 긴 길(전파식 7개). 같은 행이 있으면 종전대로 길 위 경계만(원자력 서식은 전파식이 맞다)\n return lp && Math.abs(lp.x[count] - total) <= 2 && (noExactRow || lp.x.every((v, k) => Math.abs(v - prop[k]) <= 2 || lp.tight[k])) ? lp.x : prop\n}\n\n/**\n * 표 행 높이 솔버 — rowSpan=1 셀의 max가 기본, rowSpan>1은 잔여 균등분배.\n * h=1 더미 셀(헤어라인 행 장식)이 섞이므로 열과 달리 max 방식이 안전.\n * grow: 셀 콘텐츠(사진 등)가 설계 높이를 넘으면 초과분만큼 행이 자란다 —\n * 사진대지 실측: 설계 16441 + 사진 22209 → 행 22209, 표 sz 합치 정확 일치.\n */\nexport function solveRowHeights(\n cells: { rowAddr: number; rowSpan: number; height: number; contentH?: number }[],\n rowCount: number,\n maxTotal = Number.POSITIVE_INFINITY,\n shrinkLast = false,\n): number[] {\n const h = new Array<number>(rowCount).fill(0)\n for (const c of cells) {\n if (c.rowSpan === 1 && c.rowAddr >= 0 && c.rowAddr < rowCount) {\n h[c.rowAddr] = Math.max(h[c.rowAddr], c.height)\n }\n }\n // 콘텐츠 초과 성장 (rowSpan=1 셀만 — 사진 셀 케이스). 여러 행 칸의 잔여 분배보다 먼저 — 자란 행만큼 잔여가 준다\n // (한컴 PDF: 4행 병합 칸 17749 안의 사진 행이 10419 → 10690 으로 자라 병합 칸 마지막 행이 100, 먼저 나누면 384)\n for (const c of cells) {\n if (c.rowSpan === 1 && c.contentH != null && c.rowAddr >= 0 && c.rowAddr < rowCount) {\n if (c.contentH > h[c.rowAddr]) h[c.rowAddr] = c.contentH\n }\n }\n // rowSpan>1 셀 — 포함 행 중 미확정(0) 행에 잔여를 준다. 미확정 행이 하나뿐인 칸부터 되풀이해 풀고(엇갈려 병합한 표는 그것만으로\n // 행 높이가 다 정해진다), 더 못 풀 때만 남은 칸을 문서 순서로 균등 분배한다\n const spans = cells.filter(c => c.rowSpan > 1).map(c => {\n const rows: number[] = []\n for (let r = c.rowAddr; r < Math.min(c.rowAddr + c.rowSpan, rowCount); r++) rows.push(r)\n return { c, rows }\n })\n const done = new Set<number>()\n const solve = (k: number, evenOnly: boolean): boolean => {\n const { c, rows } = spans[k]\n const known = rows.reduce((s, r) => s + h[r], 0)\n const missing = rows.filter(r => h[r] === 0)\n if (missing.length === 0) { done.add(k); return false }\n if (evenOnly && missing.length !== 1) return false\n done.add(k)\n if (c.height <= known) return false\n const each = (c.height - known) / missing.length\n for (const r of missing) h[r] = each\n return true\n }\n // 미확정 행은 위에서부터 — 그 행에서 끝나는 여러 행 칸의 (저장 높이 − 앞 행 합) 중 큰 값(앞 행이 다 정해진 칸만). 문서 순서로 풀면\n // 위에서 시작한 큰 병합 칸이 아래 행을 먼저 정했다(같은 판 PDF: 13행 칸 22322 가 정한 28행 1953 대신 2행 칸 1666 − 27행 1382 = 284,\n // 29행은 3행 칸 3866 에 맞춰 2200 — 칸 틀 16.5pt·22.1pt)\n for (let r = 0; r < rowCount; r++) {\n if (h[r] !== 0) continue\n let need = 0\n for (const { c, rows } of spans) if (rows[rows.length - 1] === r && rows.slice(0, -1).every(q => h[q] > 0)) need = Math.max(need, c.height - rows.slice(0, -1).reduce((t, q) => t + h[q], 0))\n if (need > 0) h[r] = need\n }\n for (let again = true; again;) { again = false; for (let k = 0; k < spans.length; k++) if (!done.has(k) && solve(k, true)) again = true }\n for (let k = 0; k < spans.length; k++) if (!done.has(k)) solve(k, false)\n // 여러 행 칸의 저장 높이가 (한 행 칸으로 이미 정해진) 그 행들 합보다 크면 모자란 만큼 마지막 행이 자란다 — 끝 행이 위인 칸부터\n // 채워 겹친 칸이 같은 모자람을 두 번 키우지 않게 하고, 표 높이(maxTotal, 저장 sz)를 넘겨 키우지 않는다(쪽을 넘는 표의 sz 는 첫 쪽 조각).\n // 한컴 저장 표 sz: 이런 칸이 있는 표 105개 중 78개가 키운 합과 같고, 키우지 않은 합과 같은 표는 없다\n // (같은 판 PDF: 2행 병합 칸 882 의 두 행이 2 + 782 → 8.75pt)\n let total = h.reduce((s, x) => s + x, 0)\n for (const { c, rows } of [...spans].sort((a, b) => a.rows[a.rows.length - 1] - b.rows[b.rows.length - 1] || b.rows[0] - a.rows[0])) {\n const known = rows.reduce((s, r) => s + h[r], 0)\n const add = Math.min(c.height - known, maxTotal - total)\n if (rows.length && add > 0) { h[rows[rows.length - 1]] += add; total += add }\n }\n // 칸 저장 높이로 쌓은 행 합이 표 높이(sz)를 넘으면 마지막 행이 줄어 표 높이에 맞는다 — 마지막 행 칸 내용이 줄인 행에 다 들 때만\n // (쪽을 넘는 표의 sz 는 첫 쪽 조각이라 줄이면 내용이 안 든다). 본문 표만 — 칸 안 표는 줄지 않고 넘친다(같은 판 PDF: 칸 안 빈 서식 표 뒤 빈 쪽). 같은 판 한컴 PDF: 칸 16425 세 행 사진 표(sz 48016)의 마지막 행 15166,\n // 칸 21090 인 마지막 행(sz 22537 − 앞 행 1764 = 20773, PDF 20749~20773)\n const last = rowCount - 1, over = total - maxTotal\n const lastCells = cells.filter(c => c.rowAddr + c.rowSpan - 1 === last)\n // 마지막 행까지 내려오는 여러 행 칸은 그 칸 내용이 줄인 칸 높이(행 합 − 넘침)에 들면 된다(같은 판 PDF: 17행 \"계속\" 칸이 걸친 표의 마지막 행 2149 − 488)\n const spanH = (c: { rowAddr: number; rowSpan: number }) => h.slice(c.rowAddr, c.rowAddr + c.rowSpan).reduce((t, x) => t + x, 0)\n if (shrinkLast && over > 0 && last >= 0 && lastCells.length && lastCells.every(c => c.contentH != null && c.contentH <= (c.rowSpan === 1 ? h[last] : spanH(c)) - over)) h[last] -= over\n return h\n}\n\n// 자연폭 계산은 hwpx/text-metrics.ts의 함초롬바탕 실측 advance 테이블(measureTextWidth)을 재사용한다.\n","/**\n * HFT 글꼴(한양·HCI·신명 계열 등)의 영문(0x21~0x7E) 글자 폭(em×1000). 공백은 measureTextWidth 가 따로 잰다.\n */\nexport const HFT_LATIN: Record<string, number[]> = {\n \"#견고딕\": [264,422,528,528,950,616,278,278,278,370,570,278,370,278,500,528,528,528,528,528,528,528,528,528,528,278,278,600,600,600,528,760,634,669,686,686,598,563,721,686,264,510,651,545,845,686,722,634,722,669,616,563,686,580,897,616,616,598,296,500,296,600,1000,278,528,580,528,580,528,299,563,545,229,229,510,229,826,545,563,580,580,334,493,316,545,493,739,510,493,475,296,222,296,600],\n \"#견명조\": [274,411,615,776,957,854,250,500,500,375,724,261,465,271,500,421,421,421,421,421,421,421,421,421,421,210,210,333,592,333,570,990,745,630,650,688,635,640,675,675,358,480,689,575,830,675,670,575,680,622,512,680,732,732,823,695,695,542,245,500,245,403,1000,250,462,495,417,513,410,371,483,580,315,345,625,338,832,570,452,500,500,480,398,410,588,518,775,575,500,440,333,271,333,1000],\n \"#공작\": [208,400,640,469,906,635,208,208,208,313,1000,208,313,208,490,448,448,448,448,448,448,448,448,448,448,208,208,500,989,500,260,990,615,448,614,688,417,417,635,635,208,260,521,417,790,635,792,469,792,521,469,469,635,635,948,521,573,573,208,490,208,333,1000,208,469,521,469,521,469,260,469,521,208,260,469,209,792,521,521,521,521,313,365,313,521,469,688,417,469,417,333,271,333,979],\n \"#궁서\": [270,400,640,479,968,689,250,270,270,322,900,270,313,270,500,458,458,458,458,458,458,458,458,458,458,270,270,500,750,500,406,989,665,521,521,625,521,479,625,677,322,417,594,521,844,677,625,521,625,583,458,573,625,625,926,573,573,479,270,500,270,500,1000,250,427,521,406,521,406,302,438,521,250,250,521,250,729,521,458,479,479,354,354,302,521,542,729,521,479,427,333,270,333,990],\n \"#그래픽\": [208,400,640,469,906,636,208,208,208,313,800,208,313,208,500,448,448,448,448,448,448,448,448,448,448,208,208,500,989,500,260,990,615,448,614,688,417,417,635,635,208,260,521,417,790,635,792,469,792,521,469,469,635,635,948,521,573,573,208,500,208,333,1000,208,469,521,469,521,469,260,469,521,208,260,469,209,792,521,521,521,521,313,365,313,521,469,688,417,469,417,333,271,333,979],\n \"#디나루\": [269,443,579,579,1039,655,289,259,259,365,624,289,404,289,500,579,579,579,579,579,579,579,579,579,579,289,289,624,624,624,579,832,674,712,751,732,635,596,789,751,269,540,694,579,905,751,790,674,790,712,674,596,751,635,963,635,674,635,259,500,259,600,1000,289,559,616,559,616,559,308,596,579,231,231,540,231,886,579,596,616,616,395,520,327,579,520,789,539,520,499,333,222,333,600],\n \"#빅\": [344,400,990,667,969,844,281,396,396,500,990,396,438,323,500,688,688,688,688,688,688,688,688,688,688,344,344,500,990,500,561,990,698,668,573,708,542,542,729,729,354,406,719,531,854,760,771,668,771,708,594,542,687,708,980,729,708,615,427,500,427,406,1000,281,604,614,427,614,594,375,604,594,312,312,625,312,896,604,594,614,614,427,469,375,594,572,802,667,572,552,333,427,333,990],\n \"#세고딕\": [219,300,640,479,844,677,208,333,333,333,1000,208,333,208,500,479,479,479,479,479,479,479,479,479,479,208,208,479,990,479,479,990,594,594,656,656,542,542,687,656,208,438,615,563,750,656,708,594,708,594,542,542,656,594,865,583,635,521,333,500,333,333,1000,208,542,542,479,542,479,281,542,542,208,208,479,208,760,542,542,542,542,323,438,260,521,427,646,427,427,427,333,250,333,969],\n \"#세나루\": [219,400,640,479,844,677,208,333,333,333,1000,208,333,208,500,479,479,479,479,479,479,479,479,479,479,208,208,479,990,479,479,990,594,594,656,656,542,542,687,656,208,438,615,563,750,656,708,594,708,594,542,542,656,594,865,583,635,521,333,500,333,333,1000,208,542,542,479,542,479,281,542,542,208,208,479,208,760,542,542,542,542,323,438,260,521,427,646,427,427,427,333,250,333,969],\n \"#세명조\": [500,500,990,990,990,990,240,500,500,500,788,240,500,240,500,500,500,500,500,500,500,500,500,500,500,500,500,500,990,500,500,990,854,708,677,708,719,691,771,781,333,458,781,719,979,781,750,688,750,719,625,760,781,844,1075,781,781,656,500,500,500,419,1000,240,510,563,479,563,479,375,563,573,250,250,563,250,885,573,479,552,563,375,417,375,563,573,823,573,573,438,333,271,333,990],\n \"#수암A\": [283,283,473,473,756,614,189,283,283,377,510,236,283,236,300,362,362,362,362,362,362,362,362,362,362,236,236,510,510,510,425,680,513,393,387,462,351,306,480,459,198,261,432,315,561,486,522,384,531,396,396,363,447,387,570,435,405,429,217,300,217,390,1000,189,339,432,351,414,387,252,387,372,192,207,390,189,519,372,408,414,414,243,306,261,375,321,471,357,369,348,217,145,217,390],\n \"#수암B\": [283,283,473,473,756,614,189,283,283,377,510,236,283,236,300,362,362,362,362,362,362,362,362,362,362,236,236,510,510,510,425,680,513,393,387,462,351,306,480,459,198,261,432,315,561,486,522,384,531,396,396,363,447,387,570,435,405,429,217,300,217,390,1000,189,339,432,351,414,387,252,387,372,192,207,390,189,519,372,408,414,414,243,306,261,375,321,471,357,369,348,217,145,217,390],\n \"#신그래픽\": [500,500,500,1000,1000,1000,250,500,500,500,600,500,500,500,500,616,616,616,616,616,616,616,616,616,616,500,500,500,500,500,500,1000,763,721,721,756,686,634,774,756,281,440,669,651,826,721,791,651,791,721,651,686,739,739,950,686,686,616,500,500,500,500,1000,250,580,634,563,634,598,316,598,616,265,348,563,264,950,616,606,634,634,370,545,316,616,616,915,563,616,563,500,500,500,1000],\n \"#신디나루\": [269,443,579,579,1039,655,289,259,259,365,624,289,404,289,500,579,579,579,579,579,579,579,579,579,579,289,289,624,624,624,579,832,674,712,751,732,635,596,789,751,269,540,694,579,905,751,790,674,790,712,674,596,751,635,963,635,674,635,259,500,259,600,1000,289,559,616,559,616,559,308,596,579,231,231,540,231,886,579,596,616,616,395,520,327,579,520,789,539,520,499,333,222,333,600],\n \"#신명조\": [500,500,990,990,990,990,240,500,500,500,788,240,500,240,500,500,500,500,500,500,500,500,500,500,500,500,500,500,990,500,500,990,854,708,677,708,719,691,771,781,333,458,781,719,979,781,750,688,750,719,625,760,781,844,1075,781,781,656,500,500,500,419,1000,240,510,563,479,563,479,375,563,573,250,250,563,250,885,573,479,552,563,375,417,375,563,573,823,573,573,438,333,271,333,990],\n \"#신문견고\": [264,422,528,528,950,616,278,278,278,370,570,278,370,278,500,528,528,528,528,528,528,528,528,528,528,278,278,600,600,600,528,760,634,669,686,686,598,563,721,686,264,510,651,545,845,686,722,634,722,669,616,563,686,580,897,616,616,598,296,500,296,600,1000,278,528,580,528,580,528,299,563,545,229,229,510,229,826,545,563,580,580,334,493,316,545,493,739,510,493,475,296,222,296,600],\n \"#신문견명\": [274,411,615,776,957,854,250,500,500,375,724,261,465,271,500,421,421,421,421,421,421,421,421,421,421,210,210,333,592,333,570,990,745,630,650,688,635,640,675,675,358,480,689,575,830,675,670,575,680,622,512,680,732,732,823,695,695,542,245,500,245,403,1000,250,462,495,417,513,410,371,483,580,315,345,625,338,832,570,452,500,500,480,398,410,588,518,775,575,500,440,333,271,333,1000],\n \"#신문고딕\": [250,350,990,500,850,688,250,500,500,375,850,333,503,333,500,500,500,500,500,500,500,500,500,500,500,500,500,500,822,500,500,1000,650,650,650,650,600,552,712,650,250,465,689,574,821,650,700,600,700,650,590,550,650,600,821,629,629,582,333,500,333,458,1000,250,572,550,500,525,540,270,525,525,250,250,500,250,825,535,540,540,540,400,458,300,525,500,729,500,500,489,250,250,250,1000],\n \"#신문명조\": [500,408,936,550,850,680,271,500,500,500,789,333,500,333,500,521,521,521,521,521,521,521,521,521,521,500,500,500,800,500,500,1000,729,630,600,689,630,640,670,725,333,425,725,600,870,725,650,580,640,650,550,725,700,650,950,680,710,580,333,500,333,470,1000,271,480,500,430,525,440,375,570,580,270,270,550,285,800,540,470,520,520,400,400,350,520,560,780,580,550,460,250,400,250,1000],\n \"#신문태고\": [264,422,528,528,950,616,278,278,278,351,570,264,370,264,500,475,475,475,475,475,475,475,475,475,475,278,278,570,570,570,528,684,570,602,617,617,539,507,649,617,237,459,585,491,760,617,650,570,650,602,554,507,617,522,807,554,554,539,296,500,296,600,1000,278,475,522,475,522,475,269,507,491,206,206,459,206,744,491,507,522,522,301,444,285,491,444,665,459,444,427,296,222,296,600],\n \"#신문태명\": [500,500,990,990,990,990,250,500,500,485,990,250,513,250,500,500,500,500,500,500,500,500,500,500,500,500,500,500,949,500,500,990,823,710,688,760,740,751,771,824,432,551,833,700,915,833,739,729,760,813,677,751,823,776,958,781,770,640,500,500,500,395,1000,250,573,625,500,625,563,354,563,604,312,354,604,333,906,625,573,604,604,479,437,396,615,552,763,535,563,479,333,271,333,990],\n \"#신세고딕\": [219,300,640,479,844,677,208,333,333,333,1000,208,333,208,500,479,479,479,479,479,479,479,479,479,479,208,208,479,990,479,479,990,594,594,656,656,542,542,687,656,208,438,615,563,750,656,708,594,708,594,542,542,656,594,865,583,635,521,333,500,333,333,1000,208,542,542,479,542,479,281,542,542,208,208,479,208,760,542,542,542,542,323,438,260,521,427,646,427,427,427,333,250,333,969],\n \"#신세나루\": [219,400,640,479,844,677,208,333,333,333,1000,208,333,208,500,479,479,479,479,479,479,479,479,479,479,208,208,479,990,479,479,990,594,594,656,656,542,542,687,656,208,438,615,563,750,656,708,594,708,594,542,542,656,594,865,583,635,521,333,500,333,333,1000,208,542,542,479,542,479,281,542,542,208,208,479,208,760,542,542,542,542,323,438,260,521,427,646,427,427,427,333,250,333,969],\n \"#신중명조\": [333,479,968,500,968,1000,240,500,500,500,788,240,458,240,500,479,479,479,479,479,479,479,479,479,479,479,479,500,968,500,500,990,729,729,729,833,729,667,781,844,437,500,833,667,979,812,739,667,729,781,573,729,781,729,980,802,781,604,458,500,458,479,1000,240,521,552,437,552,438,312,479,552,281,313,551,281,844,552,500,552,552,385,406,385,552,552,729,500,552,437,312,273,312,989],\n \"#신태명조\": [500,500,990,990,990,990,250,500,500,485,990,250,513,250,500,500,500,500,500,500,500,500,500,500,500,500,500,500,949,500,500,990,823,710,688,760,740,751,771,824,432,551,833,700,915,833,739,729,760,813,677,751,823,776,958,781,770,640,500,500,500,395,1000,250,573,625,500,625,563,354,563,604,312,354,604,333,906,625,573,604,604,479,437,396,615,552,763,535,563,479,333,271,333,990],\n \"#중고딕\": [250,300,990,500,989,635,250,500,500,374,989,300,500,300,500,500,500,500,500,500,500,500,500,500,500,500,500,500,1000,500,500,990,562,614,625,656,563,552,677,656,250,333,677,540,833,677,656,583,656,625,625,550,593,583,822,552,583,530,500,500,500,390,1000,250,562,562,476,552,531,324,542,552,250,300,500,250,833,552,521,552,552,386,500,355,525,475,696,475,475,427,333,271,333,990],\n \"#중명조\": [333,479,968,500,968,1000,240,500,500,500,788,240,458,240,500,479,479,479,479,479,479,479,479,479,479,479,479,500,968,500,500,990,729,729,729,833,729,667,781,844,437,500,833,667,979,812,739,667,729,781,573,729,781,729,980,802,781,604,458,500,458,479,1000,240,521,552,437,552,438,312,479,552,281,313,551,281,844,552,500,552,552,385,406,385,552,552,729,500,552,437,312,273,312,989],\n \"#태고딕\": [264,422,528,528,950,616,264,278,278,351,570,264,370,264,500,475,475,475,475,475,475,475,475,475,475,278,278,570,570,570,528,684,570,602,617,617,539,507,649,617,237,459,585,491,760,617,650,570,650,602,554,507,617,522,807,554,554,539,296,500,296,600,1000,264,475,522,475,522,475,269,507,491,206,206,459,206,744,491,507,522,522,301,444,285,491,444,665,459,444,427,296,222,296,600],\n \"#태그래픽\": [208,416,625,469,947,635,250,260,260,625,989,250,312,208,489,469,469,469,469,469,469,469,469,469,469,208,208,500,750,500,312,989,572,520,635,687,416,416,687,635,260,312,520,416,791,635,791,469,791,520,469,520,635,550,947,520,520,520,260,489,260,420,1000,250,468,520,468,520,468,260,468,520,260,260,468,260,791,520,520,520,520,364,364,270,520,468,687,416,468,468,333,270,333,989],\n \"#태명조\": [500,500,990,990,990,990,250,500,500,485,990,250,513,250,500,500,500,500,500,500,500,500,500,500,500,500,500,500,949,500,500,990,823,710,688,760,740,751,771,824,432,551,833,700,915,833,739,729,760,813,677,751,823,776,958,781,770,640,500,500,500,395,1000,250,573,625,500,625,563,354,563,604,312,354,604,333,906,625,573,604,604,479,437,396,615,552,763,535,563,479,333,271,333,990],\n \"#태신명조\": [485,388,582,570,951,951,242,485,485,485,951,388,475,388,485,519,519,519,519,519,519,519,519,519,519,485,485,485,951,485,582,951,689,694,682,738,676,575,747,744,294,556,731,597,858,706,723,585,738,715,606,638,729,706,921,730,655,650,485,485,485,485,1000,242,579,588,506,585,503,356,550,647,297,326,638,300,911,650,535,606,573,429,503,367,632,550,800,591,559,482,485,485,485,970],\n \"#필기\": [302,400,640,459,821,656,260,427,427,469,668,260,333,260,500,469,469,469,469,469,469,469,469,469,469,260,313,500,969,500,344,991,719,615,465,667,465,565,513,615,513,542,625,563,771,565,615,511,615,615,615,615,615,565,860,705,535,565,479,500,479,312,1000,260,490,395,395,490,410,370,462,490,263,310,473,350,690,489,505,563,485,445,395,290,490,440,690,535,464,415,312,271,312,989],\n \"#헤드라인A\": [229,417,625,375,688,594,188,260,260,323,990,188,302,188,500,406,406,406,406,406,406,406,406,406,406,188,188,500,750,500,417,990,459,458,437,469,364,364,469,479,239,417,458,375,625,490,479,437,490,459,406,400,479,427,667,448,437,375,292,500,292,427,900,188,395,407,375,407,385,245,396,396,218,229,396,219,594,396,395,407,407,292,375,281,395,374,614,374,374,285,333,271,333,990],\n \"#헤드라인B\": [229,417,625,375,688,594,188,260,260,323,990,188,302,188,500,406,406,406,406,406,406,406,406,406,406,188,188,500,750,500,417,990,459,458,437,469,364,364,469,479,239,417,458,375,625,490,479,437,490,459,406,400,479,427,667,448,437,375,292,500,292,427,900,188,395,407,375,407,385,245,396,396,218,229,396,219,594,396,395,407,407,292,375,281,395,374,614,374,374,285,333,271,333,990],\n \"#화명조A\": [333,479,968,500,968,1000,250,500,500,400,1000,240,458,240,500,479,479,479,479,479,479,479,479,479,479,479,479,450,968,500,500,990,729,729,729,833,729,667,781,844,437,502,833,667,979,812,739,667,729,781,573,729,781,729,980,802,781,604,458,500,458,479,1000,250,521,552,437,552,438,312,479,552,281,313,551,281,844,552,500,552,552,385,406,385,552,552,729,500,552,437,312,273,312,989],\n \"#화명조B\": [333,479,968,500,968,1000,250,500,500,400,1000,240,458,240,500,479,479,479,479,479,479,479,479,479,479,479,479,450,968,500,500,990,729,729,729,833,729,667,781,844,437,502,833,667,979,812,739,667,729,781,573,729,781,729,980,802,781,604,458,500,458,479,1000,250,521,552,437,552,438,312,479,552,281,313,551,281,844,552,500,552,552,385,406,385,552,552,729,500,552,437,312,273,312,989],\n \"AmeriGarmnd BT\": [274,328,769,495,824,661,169,275,275,500,833,248,329,248,274,495,495,495,495,495,495,495,495,495,495,274,274,833,833,833,381,986,658,607,603,735,547,498,726,774,330,385,715,494,828,768,738,548,738,597,442,603,716,658,995,713,662,603,329,274,329,1000,500,500,411,495,384,493,395,274,494,493,236,236,495,250,768,498,449,495,495,330,329,328,494,442,662,440,442,385,500,500,500,833],\n \"Baskerville BT\": [301,331,769,549,798,766,170,330,330,500,833,274,332,274,272,549,549,549,549,549,549,549,549,549,549,301,301,833,833,833,440,986,662,714,714,769,659,606,768,877,439,440,768,659,933,823,823,606,823,713,550,728,824,766,987,767,713,601,328,272,328,1000,500,500,494,547,439,607,496,322,551,606,276,276,550,275,882,608,550,608,554,437,382,328,607,497,717,549,497,441,500,500,500,833],\n \"Blippo Blk BT\": [278,370,769,551,655,583,192,312,312,500,833,275,269,275,347,551,551,551,551,551,551,551,551,551,551,292,292,833,833,833,495,1000,616,588,787,734,477,495,657,616,315,347,644,366,843,597,787,588,787,611,403,569,597,606,843,569,602,569,278,347,278,1000,500,500,593,593,574,593,569,347,588,537,269,287,528,269,782,537,574,593,593,347,389,347,537,435,782,519,537,537,500,500,500,833],\n \"Bodoni Bd BT\": [329,345,769,604,948,765,178,370,370,500,833,302,376,302,273,604,604,604,604,604,604,604,604,604,604,329,329,833,833,833,440,986,659,713,658,766,659,606,714,768,383,440,767,605,823,715,769,657,769,713,548,659,710,659,933,657,659,547,370,273,370,1000,500,500,492,553,493,553,492,328,491,549,275,287,547,275,823,549,547,553,553,438,383,330,549,493,660,549,493,440,500,500,500,833],\n \"Bodoni Bk BT\": [296,331,769,500,823,712,170,312,312,500,833,250,329,250,272,500,500,500,500,500,500,500,500,500,500,296,296,833,833,833,440,986,623,605,601,658,603,547,658,713,329,385,655,548,767,659,659,546,659,658,491,548,656,618,878,659,611,547,312,272,312,1000,500,500,439,494,438,496,438,274,439,494,275,264,493,274,713,493,438,493,496,329,384,273,493,437,603,441,439,382,500,500,500,833],\n \"BroadwayEngraved BT\": [385,356,769,698,835,830,185,404,404,421,833,349,520,349,424,698,698,698,698,698,698,698,698,698,698,367,367,833,833,833,611,986,790,773,782,804,729,697,833,816,438,671,757,697,1000,808,816,809,816,809,633,687,805,790,970,787,756,651,403,424,403,1000,500,500,690,676,620,676,650,408,690,671,385,408,660,385,878,671,650,676,676,536,516,461,671,687,945,738,652,667,500,500,500,833],\n \"BrushScript BT\": [294,314,769,567,567,586,163,420,420,405,833,283,440,283,274,567,567,567,567,567,567,567,567,567,567,294,294,833,833,833,383,1000,716,657,678,751,661,660,678,768,477,496,732,511,935,713,586,696,678,733,657,568,806,568,862,715,733,642,420,274,420,1000,500,500,452,373,323,457,322,325,435,411,255,328,421,270,606,403,359,458,438,348,344,287,438,386,549,348,410,355,500,500,500,833],\n \"CentSchbook BT\": [296,335,769,546,823,809,172,356,356,500,833,273,329,273,278,546,546,546,546,546,546,546,546,546,546,296,296,833,833,833,440,986,706,699,694,765,713,660,778,833,398,530,772,660,925,817,778,684,778,714,603,704,809,706,946,703,669,603,356,278,356,1000,500,500,523,560,448,559,488,343,523,604,301,275,581,301,882,611,515,560,559,444,440,389,602,522,762,526,520,485,500,500,500,833],\n \"CommercialScript BT\": [347,331,769,421,617,620,170,347,347,463,833,211,347,211,340,421,421,421,421,421,421,421,421,421,421,273,273,833,833,833,435,986,716,829,685,743,542,719,678,733,620,528,721,637,732,648,562,678,629,866,602,616,886,597,903,677,681,484,347,340,347,1000,500,500,477,409,316,490,357,329,477,488,275,274,423,280,731,527,388,474,481,335,293,285,492,416,655,346,507,404,500,500,500,833],\n \"Cooper Blk BT\": [384,356,769,623,935,972,185,477,477,557,833,311,386,311,272,623,623,623,623,623,623,623,623,623,623,369,369,833,833,833,570,986,864,772,791,839,734,696,865,863,460,679,881,680,974,866,845,716,845,827,696,735,863,814,1093,845,723,661,477,278,477,1000,500,500,608,686,571,698,571,457,607,736,405,407,750,403,993,738,639,716,697,569,494,479,735,679,992,660,660,566,500,500,500,833],\n \"GoudyOlSt BT\": [328,328,769,495,786,822,169,370,370,500,833,248,331,248,278,495,495,495,495,495,495,495,495,495,495,272,272,833,833,833,365,986,752,595,683,741,562,527,722,771,321,321,675,551,878,759,788,547,788,646,530,659,733,711,991,659,602,549,370,278,370,1000,500,500,450,486,442,508,444,273,439,539,251,249,501,255,766,541,493,493,500,338,343,329,517,485,657,493,424,355,500,500,500,833],\n \"HCI Acacia\": [295,309,721,553,775,758,352,367,367,424,605,275,330,275,436,553,553,553,553,553,553,553,553,553,553,275,275,605,605,605,592,865,740,572,812,744,535,484,871,682,225,480,592,461,918,740,869,592,869,605,498,426,654,701,959,609,592,479,352,605,352,672,498,352,682,682,646,686,650,312,672,609,199,203,502,199,938,609,654,682,682,301,389,340,607,553,830,479,535,424,352,672,352,605],\n \"HCI Bellflower\": [301,379,600,619,898,799,219,301,301,439,600,320,398,320,600,619,619,619,619,619,619,619,619,619,619,320,320,600,600,600,539,820,680,740,740,799,721,641,799,799,340,600,721,600,920,740,799,619,820,721,660,619,779,699,959,721,641,641,301,600,301,600,498,219,578,619,520,619,520,320,539,660,301,301,619,301,939,660,561,619,578,439,520,379,680,520,779,561,539,479,279,600,279,600],\n \"HCI Centaurea\": [279,219,680,439,680,779,238,260,219,420,520,219,279,219,340,439,439,439,439,439,439,439,439,439,439,260,238,520,520,520,379,699,619,600,520,699,619,578,619,680,379,398,660,578,840,699,600,539,600,600,461,498,740,641,879,561,561,619,238,479,320,520,498,238,420,420,340,439,340,320,398,439,238,219,439,238,619,461,398,439,398,301,320,320,461,439,680,420,398,439,238,520,238,520],\n \"HCI Hollyhock\": [277,354,555,555,889,668,221,332,332,389,582,277,332,277,277,555,555,555,555,555,555,555,555,555,555,277,277,582,582,582,555,1016,668,668,723,723,668,609,777,723,277,498,668,555,832,723,777,668,777,723,668,609,723,668,943,668,668,609,277,277,277,469,555,221,555,555,498,555,555,277,555,555,221,221,498,221,832,555,555,555,555,332,498,277,555,498,723,498,498,498,334,260,334,582],\n \"HCI Hollyhock Narrow\": [227,291,455,455,729,547,182,273,273,318,479,227,273,227,227,455,455,455,455,455,455,455,455,455,455,227,227,479,479,479,455,832,547,547,592,592,547,502,637,592,227,410,547,455,684,592,637,547,637,592,547,502,592,547,773,547,547,502,227,227,227,385,455,182,455,455,410,455,455,227,455,455,182,182,410,182,684,455,455,455,455,273,410,227,455,410,592,410,410,410,273,213,273,479],\n \"HCI Morning Glory\": [295,389,555,555,832,814,203,332,332,498,605,277,332,277,277,555,555,555,555,555,555,555,555,555,555,277,277,605,605,605,443,736,723,723,723,777,723,668,777,832,406,555,777,668,943,814,777,668,777,723,631,668,814,723,980,703,703,609,332,605,332,605,498,203,555,555,443,572,498,332,537,609,314,295,592,314,889,609,498,572,555,443,463,389,609,537,777,537,537,480,332,605,332,605],\n \"HCI Poppy\": [277,369,605,498,840,777,277,332,332,389,605,248,332,248,605,498,498,498,498,498,498,498,498,498,498,248,248,605,605,605,443,746,777,609,707,773,609,555,762,830,336,332,727,609,945,830,785,604,785,668,525,613,777,723,998,668,668,668,332,605,332,605,498,277,498,553,443,609,479,332,555,582,291,232,555,291,883,582,547,600,561,395,424,324,604,564,832,516,555,498,332,605,332,605],\n \"HCI Tulip\": [332,406,498,498,832,777,332,332,332,498,564,248,332,248,277,498,498,498,498,498,498,498,498,498,498,277,277,564,564,564,443,920,723,668,668,723,609,555,723,723,332,389,723,609,889,723,723,555,723,668,555,609,723,723,943,723,723,609,332,277,332,469,498,332,443,498,443,498,443,332,498,498,277,277,498,277,777,498,498,498,498,332,389,277,498,498,723,498,498,443,479,199,479,539],\n \"HY둥근고딕\": [333,333,500,500,833,667,333,417,417,500,500,333,500,333,500,500,500,500,500,500,500,500,500,500,500,333,333,583,500,583,500,1000,667,667,750,667,667,583,750,667,250,500,667,583,917,750,750,667,750,667,667,667,667,667,833,667,667,667,500,500,500,500,500,333,583,583,583,583,583,250,583,583,250,250,500,250,917,583,583,583,583,333,583,250,583,500,833,583,583,583,500,500,500,750],\n \"Hobo BT\": [292,314,769,549,880,843,163,331,331,500,833,274,332,274,275,549,549,549,549,549,549,549,549,549,549,275,275,833,833,833,422,1000,659,602,604,641,568,568,632,712,328,377,604,532,841,718,696,606,660,640,605,603,660,624,822,584,584,567,365,275,365,1000,500,500,495,531,459,533,494,329,476,533,257,294,494,258,809,532,530,531,535,421,457,329,533,475,677,458,476,422,500,500,500,833],\n \"Newtext Bk BT\": [307,288,769,625,967,781,149,406,406,418,833,312,342,312,303,625,625,625,625,625,625,625,625,625,625,336,336,833,833,833,605,1000,727,741,675,744,694,619,748,745,253,508,762,608,915,749,759,659,759,739,652,647,747,725,961,713,715,615,406,303,406,1000,500,500,592,621,540,619,593,382,619,612,222,239,590,218,956,616,606,620,620,400,558,426,616,583,900,585,573,498,500,500,500,833],\n \"OCR-A BT\": [618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,1000,1000,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,1000],\n \"OCR-B-10 BT\": [602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602],\n \"Orator10 BT\": [602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602],\n \"Orbit-B BT\": [231,300,769,694,426,715,155,259,259,500,833,347,448,347,396,694,694,694,694,694,694,694,694,694,694,199,199,833,833,833,574,1000,727,683,684,697,543,524,684,726,236,613,674,578,787,697,696,679,696,687,669,645,699,613,787,662,638,648,259,396,259,1000,500,500,519,535,523,535,529,326,527,525,220,220,531,220,687,535,522,514,514,421,523,337,535,495,674,495,525,494,500,500,500,833],\n \"Stencil BT\": [333,356,769,616,759,750,185,447,447,500,833,333,444,333,278,616,616,616,616,616,616,616,616,616,616,333,333,833,833,833,500,986,720,701,653,698,625,620,676,743,398,593,748,616,792,676,701,674,701,725,606,660,704,671,900,681,692,581,447,278,447,1000,500,500,720,701,653,698,625,620,676,743,398,593,748,616,792,676,701,674,701,725,606,660,704,671,900,681,692,581,500,500,500,833],\n \"Swis721 Lt BT\": [312,269,769,532,810,660,139,316,316,500,833,266,327,266,292,532,532,532,532,532,532,532,532,532,532,289,289,833,833,833,491,1000,616,640,696,697,605,568,749,704,237,481,639,520,815,704,757,604,757,647,606,532,697,568,859,587,560,569,330,292,330,1000,500,500,536,577,516,581,530,266,579,541,206,218,484,206,834,539,558,580,581,307,491,271,541,463,692,446,466,464,500,500,500,833],\n \"수식\": [500,375,500,500,1000,875,375,375,375,550,1000,500,1000,500,500,500,500,500,500,500,500,500,500,500,500,375,375,500,1000,500,500,825,875,750,750,750,750,750,750,875,375,500,875,750,1000,875,750,750,750,750,625,813,875,875,1000,813,813,625,387,450,387,500,1000,375,500,563,500,563,500,375,625,563,313,313,625,313,875,563,500,563,563,375,500,375,563,625,875,625,563,500,375,250,375,500],\n \"신명 견고딕\": [500,400,690,690,1000,1000,400,500,500,500,1000,400,500,400,500,690,690,690,690,690,690,690,690,690,690,500,500,500,1000,500,690,1000,775,776,773,835,716,660,814,833,328,652,788,661,1073,896,895,735,854,771,774,718,894,844,1147,848,790,718,500,500,500,500,500,400,657,704,589,702,648,421,701,709,333,334,653,333,1085,713,700,705,704,475,590,475,706,654,955,647,653,584,500,500,500,1000],\n \"신명 견명조\": [500,400,680,680,1000,1000,400,500,500,500,1000,400,500,400,500,680,680,680,680,680,680,680,680,680,680,500,500,500,1000,500,680,1000,756,809,782,846,790,756,839,861,457,682,854,748,996,823,834,764,836,835,692,742,833,762,985,740,752,703,500,500,500,500,500,400,724,757,637,753,673,453,722,808,438,415,792,419,1069,797,707,774,749,621,600,546,792,715,992,730,726,665,500,500,500,1000],\n \"신명 궁서\": [500,400,720,720,1000,1000,400,500,500,500,1000,400,500,400,500,720,720,720,720,720,720,720,720,720,720,500,500,500,1000,500,720,1000,871,811,750,830,770,734,813,888,474,711,863,738,1050,847,770,750,750,831,631,741,814,862,1051,891,858,746,500,500,500,500,500,400,689,673,590,690,630,506,649,756,429,378,732,422,1055,751,632,715,695,611,609,490,735,733,941,767,735,663,500,500,500,1000],\n \"신명 디나루\": [500,400,660,660,1000,1000,400,500,500,500,1000,400,500,400,500,660,660,660,660,660,660,660,660,660,660,500,500,500,1000,500,660,1000,782,713,764,771,761,730,819,771,340,585,710,689,872,769,818,719,819,767,712,746,771,726,988,683,716,742,500,500,500,500,500,400,662,622,565,622,618,480,620,628,294,294,562,294,896,627,621,623,622,467,574,456,627,567,783,573,559,649,500,500,500,1000],\n \"신명 세고딕\": [500,400,650,650,1000,1000,400,500,500,500,1000,400,500,400,500,650,650,650,650,650,650,650,650,650,650,500,500,500,1000,500,650,1000,720,752,797,775,672,613,845,785,261,587,719,620,921,784,833,710,836,749,733,641,782,689,1002,666,658,650,500,500,500,500,500,400,617,678,629,677,634,347,657,637,264,264,589,264,945,637,657,678,677,371,595,335,637,553,838,569,548,557,500,500,500,1000],\n \"신명 세나루\": [500,400,650,650,1000,1000,400,500,500,500,1000,400,500,400,500,650,650,650,650,650,650,650,650,650,650,500,500,500,1000,500,650,1000,719,752,796,775,703,644,845,785,270,587,714,651,921,784,833,710,836,749,734,702,782,689,1003,669,657,708,500,500,500,500,500,400,648,678,628,677,634,408,657,637,274,274,589,274,945,637,657,678,677,402,595,396,637,559,839,572,548,614,500,500,500,1000],\n \"신명 세명조\": [500,400,620,620,1000,1000,400,500,500,500,1000,400,500,400,500,620,620,620,620,620,620,620,620,620,620,500,500,500,1000,500,620,1000,787,739,727,773,658,661,759,780,337,485,775,647,929,789,755,602,769,726,693,672,765,767,978,749,757,626,500,500,500,500,500,400,553,564,520,573,554,372,560,582,266,313,572,318,845,587,562,573,565,383,484,345,598,627,842,598,587,534,500,500,500,1000],\n \"신명 순명조\": [500,400,600,600,1000,1000,400,500,500,500,1000,400,500,400,500,600,600,600,600,600,600,600,600,600,600,500,500,500,1000,500,600,1000,725,798,788,846,771,692,850,847,374,654,769,646,961,792,845,659,854,753,711,671,834,742,969,768,689,683,500,500,500,500,500,400,648,705,607,708,605,389,620,745,372,371,703,372,1027,748,644,706,663,500,607,451,768,607,859,644,698,563,500,500,500,1000],\n \"신명 신그래픽\": [500,400,620,620,1000,1000,400,500,500,500,1000,400,500,400,500,620,620,620,620,620,620,620,620,620,620,500,500,500,1000,500,620,1000,779,696,756,759,694,663,811,755,299,558,698,619,867,752,812,719,808,758,698,656,754,725,1010,720,710,641,500,500,500,500,500,400,571,619,521,619,575,400,573,578,244,243,519,243,860,578,574,577,577,363,528,315,577,524,747,550,502,511,500,500,500,1000],\n \"신명 신명조\": [500,400,640,640,1000,1000,400,500,500,500,1000,400,500,400,500,640,640,640,640,640,640,640,640,640,640,500,500,500,1000,500,640,1000,778,780,783,836,781,751,836,894,434,611,818,729,1008,876,840,731,842,788,691,726,874,779,1034,764,763,670,500,500,500,500,500,400,618,619,508,639,561,374,581,672,354,337,659,356,947,673,563,640,612,483,528,456,673,603,835,600,600,548,500,500,500,1000],\n \"신명 신문고딕\": [500,500,500,1000,1000,1000,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,1000,666,666,721,721,666,610,777,721,277,500,666,555,832,721,777,666,1000,721,666,610,721,666,943,666,666,610,500,500,500,500,500,500,555,555,500,555,555,277,555,555,221,221,500,221,832,555,625,555,555,332,500,277,555,500,721,500,500,500,500,500,500,500],\n \"신명 신문명조\": [500,500,500,1000,1000,1000,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,1000,658,685,685,764,658,606,737,764,342,395,711,579,948,764,764,606,764,632,553,632,737,658,948,632,632,579,500,500,500,500,500,500,474,553,474,553,500,289,553,579,263,237,553,263,843,553,527,527,553,395,448,309,553,474,711,527,500,448,500,500,500,500],\n \"신명 신신명조\": [500,400,600,600,1000,1000,400,500,500,500,1000,400,500,400,500,600,600,600,600,600,600,600,600,600,600,500,500,500,1000,500,600,1000,803,848,778,827,775,744,828,885,441,610,808,727,994,865,834,725,835,779,689,721,863,771,1015,755,759,670,500,500,500,500,500,400,620,617,514,640,565,384,581,669,363,352,657,366,933,669,568,639,614,520,534,461,670,601,825,598,598,552,500,500,500,1000],\n \"신명 중고딕\": [500,400,680,680,1000,1000,400,500,500,500,1000,400,500,400,500,680,680,680,680,680,680,680,680,680,680,500,500,500,1000,500,680,1000,816,772,775,785,714,678,889,831,319,653,786,653,1066,895,888,714,854,775,769,719,889,779,1149,847,731,697,500,500,500,500,500,400,644,694,584,696,643,457,699,703,323,322,598,323,1050,700,697,693,694,458,583,382,705,634,929,651,635,527,500,500,500,1000],\n \"신명 중명조\": [500,400,620,620,1000,1000,400,500,500,500,1000,400,500,400,500,620,620,620,620,620,620,620,620,620,620,500,500,500,1000,500,620,1000,821,816,823,888,819,789,879,938,462,647,861,770,1057,919,881,770,883,829,728,765,918,821,1084,806,805,708,500,500,500,500,500,400,654,654,539,674,594,386,627,710,380,363,697,382,998,709,597,674,648,515,561,486,710,636,878,636,635,580,500,500,500,1000],\n \"신명 태고딕\": [500,400,690,690,1000,1000,400,500,500,500,1000,400,500,400,500,690,690,690,690,690,690,690,690,690,690,500,500,500,1000,500,690,1000,849,766,826,829,764,733,881,825,360,628,768,689,937,822,882,789,878,828,768,706,824,795,1075,790,780,711,500,500,500,500,500,400,641,689,591,644,645,417,643,648,314,313,589,313,930,648,644,647,647,433,598,379,647,594,817,620,572,581,500,500,500,1000],\n \"신명 태명조\": [500,400,710,710,1000,1000,400,500,500,500,1000,400,500,400,500,710,710,710,710,710,710,710,710,710,710,500,500,500,1000,500,710,1000,725,798,788,846,771,692,850,847,374,654,769,646,961,792,845,659,854,753,711,671,834,742,969,768,689,683,500,500,500,500,500,400,648,705,607,708,605,389,620,745,372,371,703,372,1027,748,644,706,663,500,607,451,768,607,859,644,698,563,500,500,500,1000],\n \"양재 매화\": [315,362,563,563,711,648,181,353,353,436,563,300,203,287,353,563,563,563,563,563,563,563,563,563,563,300,300,500,563,500,483,719,558,633,524,602,512,504,568,603,300,475,593,469,733,584,591,578,616,604,476,517,603,540,712,589,514,504,384,353,384,500,500,500,488,490,433,490,427,289,459,493,232,245,478,233,678,477,461,513,521,373,350,340,466,422,609,479,444,394,563,500,563,667],\n \"양재 튼튼B\": [330,326,771,598,707,625,179,347,347,508,833,308,833,308,290,598,598,598,598,598,598,598,598,598,598,330,330,833,833,833,549,996,621,667,668,672,606,581,709,691,286,412,645,513,761,683,710,603,740,643,638,590,663,610,865,612,557,568,347,290,347,996,508,508,528,553,526,553,532,292,549,546,248,252,521,248,811,546,545,553,553,358,522,300,546,458,718,474,458,486,508,508,508,833],\n \"오이\": [415,320,673,591,716,729,186,458,458,384,522,229,514,229,402,600,600,600,600,600,600,600,600,600,600,350,350,402,496,402,428,792,686,578,578,664,587,634,720,608,574,764,531,626,802,716,759,578,811,626,591,729,677,673,837,686,677,643,402,400,402,509,462,251,561,488,522,522,557,488,479,471,264,350,522,229,690,518,574,574,522,552,509,496,552,514,703,509,505,514,445,199,445,565],\n \"옥수수\": [276,466,775,592,811,671,265,500,500,500,741,265,500,265,528,500,500,500,500,500,500,500,500,500,500,265,265,500,729,500,532,807,609,630,581,666,616,628,712,698,296,405,624,623,771,765,712,602,743,651,592,507,680,599,779,652,666,669,500,551,500,436,780,265,591,528,476,536,543,522,535,501,225,285,518,225,701,476,495,513,517,493,493,433,463,458,641,484,459,484,357,281,357,783],\n \"타이프\": [615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615],\n \"태 나무\": [348,403,528,528,840,528,270,333,333,442,614,270,348,270,473,528,528,528,528,528,528,528,528,528,528,270,270,614,614,614,403,809,825,661,731,754,551,497,825,934,333,348,754,551,1067,895,879,606,879,645,528,571,809,676,1012,715,583,622,333,473,333,614,512,317,551,551,418,583,473,333,528,583,293,293,528,293,864,583,551,551,551,379,418,309,567,512,809,497,473,442,333,239,333,614],\n \"펜흘림\": [227,409,769,454,690,387,304,269,269,324,833,227,345,227,199,495,495,495,495,495,495,495,495,495,495,250,250,833,833,833,308,1000,671,509,519,731,442,602,493,641,326,331,612,543,827,688,546,437,500,421,662,577,649,560,771,410,565,412,269,553,269,626,500,500,417,408,324,456,324,257,414,449,218,271,440,243,623,449,344,472,414,345,347,271,449,417,586,412,442,352,500,500,500,833],\n \"한양견고딕\": [334,483,579,561,908,712,262,368,376,416,519,327,518,325,339,562,562,562,562,562,562,562,562,562,562,323,323,721,519,701,611,1000,722,722,722,722,667,611,778,722,278,556,722,611,833,722,778,667,768,722,667,611,722,667,944,667,667,611,337,342,337,428,500,266,556,611,556,611,556,333,611,611,278,278,556,278,889,611,611,611,611,389,556,333,611,556,778,556,556,500,402,302,400,501],\n \"한양견명조\": [406,492,467,630,948,838,390,406,384,528,638,284,640,314,419,562,562,562,562,562,562,562,562,562,562,338,339,741,641,737,562,937,818,808,750,798,722,699,813,828,379,510,857,692,982,813,798,677,812,747,684,819,818,802,1068,801,795,648,394,420,387,422,500,382,548,594,519,581,522,436,628,598,312,324,598,308,893,616,556,582,585,445,525,382,597,629,869,630,612,512,455,311,454,500],\n \"한양그래픽\": [312,438,500,640,868,844,312,375,375,501,562,238,562,237,426,500,500,500,500,500,500,500,500,500,500,312,312,625,562,625,525,1000,633,570,656,643,478,460,675,608,213,365,575,501,793,642,745,527,752,557,613,619,612,595,892,569,629,534,375,432,375,344,1000,312,485,499,468,502,473,342,511,455,266,301,452,240,812,516,505,509,538,349,468,332,528,482,738,443,457,420,438,250,438,500],\n \"한양신명조\": [325,423,450,602,920,814,386,395,374,524,567,235,572,244,390,500,500,500,500,500,500,500,500,500,500,276,292,729,570,734,511,920,794,704,690,749,677,654,742,784,337,450,792,645,959,777,748,629,755,703,648,774,773,780,1037,754,769,599,362,397,352,429,500,382,509,556,485,543,482,352,588,560,277,314,557,274,858,564,516,534,548,405,486,351,562,581,840,590,574,474,418,280,421,500],\n \"한양중고딕\": [248,420,535,529,867,643,240,288,281,369,518,246,518,245,263,500,500,500,500,500,500,500,500,500,500,247,245,583,519,582,524,999,632,629,699,693,649,594,751,689,246,470,631,539,803,692,749,637,754,692,636,584,688,632,904,619,619,585,253,283,253,448,500,256,534,527,483,531,532,255,529,529,195,196,473,195,809,529,539,535,531,310,480,255,531,479,697,470,466,485,310,237,306,500],\n}\n","/**\n * 글꼴별 글자 폭 보정(em×1000) — font-metrics.ts 의 폭표 위에 덮어쓴다. TTF 글꼴은 글꼴 단위 폭 ÷ unitsPerEm 을 반올림하지 않은\n * 소수 그대로 둔다(595.703125 = 610/1024): 한컴은 글자 폭을 4·MulDiv(글꼴 폭, ⌊크기/4⌋, unitsPerEm) 로 재므로 em×1000 정수로 줄이면\n * 크기에 따라 1 HWPUNIT 씩 어긋난다. 글꼴에 없는 글자는 한컴이 대체 글꼴로 찍는 폭이다.\n * 가운뎃점(U+00B7)·KoPub바탕체 숫자 등 저장본 줄 나눔에 맞춘 값은 폭표 쪽을 남겼다.\n * 폭표가 없던 글꼴(시스템·산세리프·Gulim·배달의민족 도현 …)은 이 표로 새 표를 연다 — 표에 없는 영문은 반각, 한글은 FACE_CJK(없으면 1em).\n */\nexport const FACE_WIDTH_FIX: Record<string, Record<number, number>> = {\n \"맑은 고딕\": {\n 0x21:289.0625, 0x22:395.01953125, 0x23:606.4453125, 0x24:550.78125, 0x25:836.42578125, 0x26:817.87109375, 0x27:231.93359375, 0x28:304.6875, 0x29:304.6875, 0x2a:424.8046875,\n 0x2b:700.68359375, 0x2c:218.75, 0x2d:410.15625, 0x2e:218.75, 0x2f:395.99609375, 0x30:550.78125, 0x31:550.78125, 0x32:550.78125, 0x33:550.78125, 0x34:550.78125,\n 0x35:550.78125, 0x36:550.78125, 0x37:550.78125, 0x38:550.78125, 0x39:550.78125, 0x3a:218.75, 0x3b:218.75, 0x3d:700.68359375, 0x3f:459.9609375, 0x40:979.4921875,\n 0x41:658.203125, 0x42:583.49609375, 0x43:634.765625, 0x44:717.28515625, 0x45:517.08984375, 0x46:498.53515625, 0x47:701.66015625, 0x48:724.609375, 0x49:270.01953125, 0x4a:359.86328125,\n 0x4b:590.33203125, 0x4c:479.98046875, 0x4d:916.9921875, 0x4e:765.13671875, 0x4f:773.4375, 0x50:570.80078125, 0x51:773.4375, 0x52:609.86328125, 0x53:542.96875, 0x54:533.69140625,\n 0x55:702.63671875, 0x56:634.27734375, 0x57:953.61328125, 0x58:601.07421875, 0x59:563.4765625, 0x5a:582.51953125, 0x5b:304.6875, 0x5d:304.6875, 0x5f:425.78125, 0x60:271.97265625,\n 0x61:520.01953125, 0x62:600.5859375, 0x63:472.65625, 0x64:602.05078125, 0x65:535.15625, 0x66:316.40625, 0x67:602.05078125, 0x68:578.61328125, 0x69:246.09375, 0x6a:246.09375,\n 0x6b:505.859375, 0x6c:246.09375, 0x6d:879.8828125, 0x6e:578.125, 0x6f:599.12109375, 0x70:600.5859375, 0x71:602.05078125, 0x72:353.515625, 0x73:433.10546875, 0x74:344.7265625,\n 0x75:578.125, 0x76:487.3046875, 0x77:736.328125, 0x78:464.84375, 0x79:492.67578125, 0x7a:461.9140625, 0x7b:304.6875, 0x7c:239.2578125, 0x7d:304.6875, 0x7e:700.68359375,\n 0xa7:457.51953125, 0xb0:386.71875, 0xb1:700.68359375, 0xb7:218.75, 0xd7:700.68359375, 0xdc:891, 0xea:891, 0xed:246.09375, 0xf8:599.12109375, 0xfa:578.125,\n 0xfe:892, 0x152:892, 0x17d:892, 0x17e:313, 0x2bc:128, 0x3b1:628.90625, 0x2011:300, 0x2013:513.18359375, 0x2014:1025.87890625, 0x2018:230.95703125,\n 0x2019:230.95703125, 0x201c:378.90625, 0x201d:378.90625, 0x2022:417.48046875, 0x2023:590, 0x2024:292, 0x2027:288, 0x2032:230.95703125, 0x203b:799.8046875, 0x2043:681,\n 0x2103:950.1953125, 0x2160:950.1953125, 0x2161:950.1953125, 0x2162:950.1953125, 0x2163:950.1953125, 0x2164:950.1953125, 0x2165:950.1953125, 0x2166:950.1953125, 0x2167:950.1953125, 0x2168:950.1953125,\n 0x2190:950.1953125, 0x2191:950.1953125, 0x2192:950.1953125, 0x2193:950.1953125, 0x2194:950.1953125, 0x21b3:970, 0x21cb:970, 0x21cc:970, 0x21d0:970, 0x21d2:950.1953125,\n 0x21e0:970, 0x21e2:970, 0x21e8:970, 0x220e:970, 0x2218:970, 0x2219:314.94140625, 0x221a:666.50390625, 0x223c:684.08203125, 0x2264:701.171875, 0x2265:701.171875,\n 0x22c4:970, 0x246f:970, 0x2470:970, 0x2471:970, 0x2472:970, 0x2473:970, 0x25aa:970, 0x25ab:970, 0x25ad:970, 0x25b4:970,\n 0x25b8:970, 0x25e6:970, 0x25fe:970, 0x2610:970, 0x2713:970, 0x274d:970, 0x275a:970, 0x2776:970, 0x2777:970, 0x2778:970,\n 0x2779:970, 0x277a:970, 0x2780:970, 0x2781:970, 0x2782:970, 0x2783:970, 0x2784:970, 0x2785:970, 0x278a:970, 0x278b:970,\n 0x278c:970, 0x278d:970, 0x278e:970, 0x278f:970, 0x2790:970, 0x2791:970, 0x279c:970, 0x27a1:970, 0x27a2:970, 0x27f7:970,\n 0x2981:970, 0x300a:618, 0x300b:618, 0x300c:570.80078125, 0x300d:570.80078125, 0x300e:517.08984375, 0x300f:517.08984375, 0x3010:536, 0x3011:536, 0x3014:487.79296875,\n 0x3015:487.79296875, 0x30fb:970, 0x3251:970, 0x3252:970, 0x3253:970, 0x3254:970, 0x3255:970, 0x3256:970, 0xff62:485, 0xff63:485,\n 0xff65:485, 0xffed:485,\n 0x2026:770, 0x3008:557, 0x3009:557,\n },\n \"한양신명조\": {\n 0xb1:617, 0xb7:384, 0xd7:616, 0xe8:1067, 0xfe:892, 0x3a9:717, 0x3b4:542, 0x3b8:708, 0x2013:1000, 0x2018:230,\n 0x2019:230, 0x201c:441, 0x201d:441, 0x2023:1000, 0x2053:688, 0x2218:1000, 0x25cb:1000, 0x300c:1000, 0x300d:1000,\n 0xff62:500, 0xff63:500,\n 0x2027:500,\n },\n \"KoPub바탕체 Light\": {\n 0x36:573, 0x37:573, 0x38:573, 0x3a:312, 0x50:612, 0x17e:313, 0x2024:174, 0x21d1:1000, 0x2219:500, 0x2460:900,\n 0x25aa:1000, 0x2740:1000, 0x2f30:900, 0x2f83:900, 0x2f9d:900, 0x3260:900, 0x3261:900, 0x3262:900, 0x3264:900, 0x326e:900,\n 0x326f:900, 0x3270:900, 0x3271:900, 0x327b:900, 0x339c:900, 0x339d:900, 0x33a1:900, 0x4e0a:900, 0x4e0d:900, 0x4e3b:900,\n 0x4ee3:900, 0x4fe1:900, 0x5168:900, 0x516c:900, 0x5370:900, 0x53d7:900, 0x540d:900, 0x5730:900, 0x5b98:900, 0x5be6:900,\n 0x5ef3:900, 0x5f71:900, 0x6027:900, 0x611f:900, 0x637a:900, 0x6848:900, 0x6b63:900, 0x6c7a:900, 0x71b1:900, 0x7406:900,\n 0x767c:900, 0x7684:900, 0x771e:900, 0x77e5:900, 0x793e:900, 0x79c1:900, 0x7f72:900, 0x7fa9:900, 0x8077:900, 0x8ab2:900,\n 0x8b70:900, 0x8ecd:900, 0x9060:900, 0x958b:900, 0x9593:900, 0x9694:900, 0xf000:500, 0xff0a:900, 0xff0b:900, 0xff0d:900,\n 0xff1a:900, 0xff21:900, 0xff3b:900, 0xff3d:900, 0xff62:500, 0xff63:500, 0xff65:500,\n },\n \"바탕\": {\n 0x21:312.5, 0x22:416.9921875, 0x23:623.046875, 0x25:855.46875, 0x26:833.0078125, 0x28:376.953125, 0x29:376.953125, 0x2b:833.0078125, 0x2c:291.9921875, 0x2e:291.9921875,\n 0x30:595.703125, 0x31:595.703125, 0x32:595.703125, 0x33:595.703125, 0x34:595.703125, 0x35:595.703125, 0x36:595.703125, 0x37:595.703125, 0x38:595.703125, 0x39:595.703125,\n 0x3a:333.0078125, 0x3b:333.0078125, 0x41:736.328125, 0x42:708.0078125, 0x43:708.0078125, 0x44:734.375, 0x45:671.875, 0x46:644.53125, 0x47:740.234375, 0x48:765.625,\n 0x49:326.171875, 0x4a:425.78125, 0x4b:746.09375, 0x4c:638.671875, 0x4d:894.53125, 0x4e:775.390625, 0x4f:736.328125, 0x50:654.296875, 0x51:738.28125, 0x52:671.875,\n 0x55:775.390625, 0x57:945.3125, 0x58:687.5, 0x59:685.546875, 0x5c:1000, 0x60:583.0078125, 0x61:541.9921875, 0x62:576.171875, 0x63:541.9921875, 0x64:576.171875,\n 0x65:576.171875, 0x66:365.234375, 0x67:583.0078125, 0x68:574.21875, 0x69:289.0625, 0x6a:291.9921875, 0x6b:572.265625, 0x6c:291.9921875, 0x6d:845.703125, 0x6e:570.3125,\n 0x6f:583.0078125, 0x70:574.21875, 0x71:574.21875, 0x72:439.453125, 0x73:519.53125, 0x74:359.375, 0x75:566.40625, 0x76:572.265625, 0x77:808.59375, 0x78:605.46875,\n 0x79:587.890625, 0xb0:437.5, 0xb1:812.5, 0xb7:333.0078125, 0xd7:812.5, 0xe7:519.53125, 0xe9:541.9921875, 0x387:313.4765625, 0x3b1:543.9453125, 0x2018:291.9921875,\n 0x2019:291.9921875, 0x2023:466, 0x2024:174, 0x2027:174, 0x202f:500, 0x2032:264.6484375, 0x2053:688, 0x2113:418.9453125, 0x2206:613.28125, 0x2219:264.6484375,\n 0x25a0:889.6484375, 0x25a1:889.6484375, 0x25b2:914.0625, 0x25bc:914.0625, 0x25fe:970, 0x26ac:970, 0x3007:1000, 0xff62:500, 0xff63:500,\n },\n \"휴먼명조\": {\n 0x21:203.125, 0x23:656.25, 0x26:769.53125, 0x27:289.0625, 0x28:312.5, 0x29:312.5, 0x2c:269.53125, 0x2e:269.53125, 0x2f:312.5, 0x3a:269.53125,\n 0x3b:269.53125, 0x3f:429.6875, 0x40:777.34375, 0x41:660.15625, 0x42:601.5625, 0x43:640.625, 0x44:679.6875, 0x46:582.03125, 0x47:703.125, 0x48:679.6875,\n 0x49:257.8125, 0x4a:394.53125, 0x4b:644.53125, 0x4c:578.125, 0x4d:781.25, 0x4e:691.40625, 0x4f:714.84375, 0x50:574.21875, 0x51:687.5, 0x52:652.34375,\n 0x53:496.09375, 0x55:675.78125, 0x56:664.0625, 0x57:933.59375, 0x58:710.9375, 0x59:671.875, 0x5a:597.65625, 0x5b:320.3125, 0x5d:320.3125, 0x61:507.8125,\n 0x62:542.96875, 0x63:484.375, 0x64:507.8125, 0x65:523.4375, 0x66:390.625, 0x67:515.625, 0x68:554.6875, 0x6a:265.625, 0x6b:523.4375, 0x6d:796.875,\n 0x6e:550.78125, 0x6f:511.71875, 0x70:539.0625, 0x71:539.0625, 0x72:402.34375, 0x73:410.15625, 0x74:339.84375, 0x75:539.0625, 0x76:539.0625, 0x77:722.65625,\n 0x78:488.28125, 0x79:511.71875, 0x7a:453.125, 0xc0:750, 0xc1:750, 0xc9:666, 0xd1:750, 0xe8:541, 0xe9:541, 0xea:541,\n 0xed:291, 0xf3:541, 0xfb:541, 0xfc:541, 0xfe:893, 0x17e:313, 0x2003:500, 0x2013:432, 0x2014:861, 0x201e:371,\n 0x2219:500, 0xff62:500, 0xff63:500, 0xff65:500,\n },\n \"HCI Tulip\": {\n 0x4a:388, 0x5e:468, 0x73:388,\n 0xa7:485, 0xb0:407, 0xb1:611, 0xb6:479, 0xb7:384, 0xd7:611, 0xe9:491, 0xf1:561, 0xf7:621, 0xfc:561,\n 0x2018:331, 0x2019:331, 0x201a:292, 0x201c:442, 0x201d:442,\n },\n // 진하게 HFT 영문 — 획을 넓히지 않고 굵은 글꼴 폭으로 잰다(한글 2022 줄 나눔: 영문 90자 × 크기 800~2000)\n // HCI Tulip: 맞출 수 없던 여는 괄호·} 는 보통 폭. HCI Hollyhock·Poppy: ( [ { < 는 짝 ) ] } > 의 폭. ASCII 밖 영문(·‘’“”×÷°±§¶éüñ‚)도 실측\n \"HCI Poppy Bold\": {\n 0x20:500, 0x21:277, 0x22:399, 0x23:605, 0x24:498, 0x25:890, 0x26:825, 0x27:277, 0x28:332, 0x29:332,\n 0x2a:444, 0x2b:605, 0x2c:248, 0x2d:332, 0x2e:248, 0x2f:294, 0x30:498, 0x31:498, 0x32:498, 0x33:498,\n 0x34:498, 0x35:498, 0x36:498, 0x37:498, 0x38:498, 0x39:498, 0x3a:248, 0x3b:248, 0x3c:605, 0x3d:605,\n 0x3e:605, 0x3f:443, 0x40:746, 0x41:777, 0x42:669, 0x43:724, 0x44:825, 0x45:609, 0x46:555, 0x47:825,\n 0x48:830, 0x49:388, 0x4a:388, 0x4b:776, 0x4c:609, 0x4d:997, 0x4e:830, 0x4f:825, 0x50:608, 0x51:825,\n 0x52:724, 0x53:608, 0x54:669, 0x55:777, 0x56:776, 0x57:998, 0x58:668, 0x59:668, 0x5a:668, 0x5b:332,\n 0x5c:605, 0x5d:332, 0x5e:605, 0x5f:498, 0x60:277, 0x61:498, 0x62:608, 0x63:443, 0x64:609, 0x65:498,\n 0x66:388, 0x67:555, 0x68:608, 0x69:331, 0x6a:331, 0x6b:608, 0x6c:331, 0x6d:890, 0x6e:608, 0x6f:554,\n 0x70:608, 0x71:608, 0x72:388, 0x73:444, 0x74:331, 0x75:608, 0x76:554, 0x77:832, 0x78:498, 0x79:555,\n 0x7a:498, 0x7b:308, 0x7c:605, 0x7d:308, 0x7e:605, 0xa7:536, 0xb0:459, 0xb1:669, 0xb6:527, 0xb7:432,\n 0xd7:669, 0xe9:541, 0xf1:611, 0xf7:669, 0xfc:611, 0x2018:276, 0x2019:276, 0x201a:292, 0x201c:499, 0x201d:499,\n },\n \"HCI Hollyhock Bold\": {\n 0x20:500, 0x21:332, 0x22:473, 0x23:555, 0x24:555, 0x25:889, 0x26:722, 0x27:276, 0x28:332, 0x29:332,\n 0x2a:389, 0x2b:582, 0x2c:277, 0x2d:332, 0x2e:277, 0x2f:277, 0x30:555, 0x31:555, 0x32:555, 0x33:555,\n 0x34:555, 0x35:555, 0x36:555, 0x37:555, 0x38:555, 0x39:555, 0x3a:332, 0x3b:332, 0x3c:582, 0x3d:582,\n 0x3e:582, 0x3f:610, 0x40:975, 0x41:722, 0x42:722, 0x43:723, 0x44:723, 0x45:668, 0x46:609, 0x47:777,\n 0x48:723, 0x49:277, 0x4a:555, 0x4b:722, 0x4c:610, 0x4d:832, 0x4e:723, 0x4f:777, 0x50:668, 0x51:777,\n 0x52:723, 0x53:668, 0x54:609, 0x55:723, 0x56:668, 0x57:943, 0x58:668, 0x59:668, 0x5a:609, 0x5b:332,\n 0x5c:277, 0x5d:332, 0x5e:582, 0x5f:555, 0x60:277, 0x61:555, 0x62:610, 0x63:555, 0x64:610, 0x65:555,\n 0x66:332, 0x67:610, 0x68:610, 0x69:277, 0x6a:277, 0x6b:555, 0x6c:277, 0x6d:889, 0x6e:610, 0x6f:610,\n 0x70:610, 0x71:610, 0x72:389, 0x73:555, 0x74:332, 0x75:610, 0x76:555, 0x77:777, 0x78:555, 0x79:555,\n 0x7a:498, 0x7b:389, 0x7c:279, 0x7d:389, 0x7e:582,\n 0xa7:694, 0xb0:469, 0xb1:715, 0xb6:611, 0xb7:432, 0xd7:669, 0xe9:585, 0xf1:579, 0xf7:669, 0xfc:579,\n 0x2018:276, 0x2019:276, 0x201a:292, 0x201c:499, 0x201d:499,\n },\n \"HCI Tulip Bold\": {\n 0x20:500, 0x21:332, 0x22:555, 0x23:498, 0x24:498, 0x25:1000, 0x26:832, 0x27:332, 0x28:332, 0x29:332,\n 0x2a:498, 0x2b:570, 0x2c:248, 0x2d:332, 0x2e:248, 0x2f:277, 0x30:498, 0x31:498, 0x32:498, 0x33:498,\n 0x34:498, 0x35:498, 0x36:498, 0x37:498, 0x38:498, 0x39:498, 0x3a:332, 0x3b:332, 0x3c:564, 0x3d:570,\n 0x3e:570, 0x3f:499, 0x40:930, 0x41:723, 0x42:668, 0x43:722, 0x44:723, 0x45:668, 0x46:610, 0x47:777,\n 0x48:777, 0x49:388, 0x4a:499, 0x4b:777, 0x4c:668, 0x4d:943, 0x4e:723, 0x4f:777, 0x50:610, 0x51:777,\n 0x52:722, 0x53:555, 0x54:668, 0x55:723, 0x56:723, 0x57:1000, 0x58:723, 0x59:723, 0x5a:668, 0x5b:332,\n 0x5c:277, 0x5d:332, 0x5e:581, 0x5f:498, 0x60:332, 0x61:499, 0x62:555, 0x63:443, 0x64:555, 0x65:443,\n 0x66:332, 0x67:498, 0x68:555, 0x69:277, 0x6a:332, 0x6b:555, 0x6c:277, 0x6d:832, 0x6e:555, 0x6f:498,\n 0x70:555, 0x71:555, 0x72:443, 0x73:388, 0x74:332, 0x75:555, 0x76:498, 0x77:723, 0x78:498, 0x79:498,\n 0x7a:443, 0x7b:479, 0x7c:218, 0x7d:479, 0x7e:520,\n 0xa7:536, 0xb0:459, 0xb1:669, 0xb6:527, 0xb7:432, 0xd7:669, 0xe9:541, 0xf1:611, 0xf7:669, 0xfc:611,\n 0x2018:331, 0x2019:331, 0x201a:292, 0x201c:499, 0x201d:499,\n },\n \"HCI Poppy\": {\n 0xad:375, 0xb7:384, 0xd7:611, 0xf7:621, 0x387:313, 0x3b1:540, 0x2013:431, 0x2014:860, 0x2024:174, 0x2026:830,\n 0x2027:174, 0x203b:762, 0x2219:500,\n 0xa7:485, 0xb0:407, 0xb1:611, 0xb6:479, 0xe9:491, 0xf1:561, 0xfc:561, 0x2018:276, 0x2019:276, 0x201a:292,\n 0x201c:499, 0x201d:499,\n },\n \"함초롬돋움\": {\n 0xf0:891, 0xf8:582, 0xfe:892, 0x21e8:970, 0x3007:970, 0x33a1:971, 0xff62:485, 0xff63:485, 0xff65:485,\n },\n \"KoPub돋움체 Light\": {\n 0x2a:446, 0x2e:300, 0xe8:1067, 0x2022:463, 0x2024:174, 0x2027:174, 0x2219:500, 0x25aa:1000, 0x25c9:1000, 0x279e:1000,\n 0x300d:450, 0x318d:900, 0x339c:900, 0x33a1:900, 0xf000:1000, 0xff06:900, 0xff0a:900, 0xff0d:900, 0xff3b:900, 0xff3d:900,\n 0xff62:500, 0xff63:500, 0xff65:500,\n },\n \"HYSinMyeongJo-Medium\": {\n 0x22:416.015625, 0x25:916.015625, 0x26:833.0078125, 0x2b:833.0078125, 0x2c:291.015625, 0x2d:833.0078125, 0x2e:291.015625, 0x2f:375, 0x3a:333.0078125, 0x3b:333.0078125,\n 0x41:791.015625, 0x42:708.0078125, 0x43:708.0078125, 0x44:750, 0x45:708.0078125, 0x46:666.015625, 0x47:750, 0x49:375, 0x4a:500, 0x4b:791.015625,\n 0x4c:666.015625, 0x4e:791.015625, 0x4f:750, 0x50:666.015625, 0x52:708.0078125, 0x53:666.015625, 0x54:791.015625, 0x56:750, 0x58:708.0078125, 0x61:541.015625,\n 0x62:583.0078125, 0x63:541.015625, 0x64:583.0078125, 0x65:583.0078125, 0x66:375, 0x67:583.0078125, 0x68:583.0078125, 0x69:291.015625, 0x6b:583.0078125, 0x6c:291.015625,\n 0x6d:875, 0x6e:583.0078125, 0x6f:583.0078125, 0x70:583.0078125, 0x72:458.0078125, 0x73:541.015625, 0x74:375, 0x75:583.0078125, 0x76:583.0078125, 0x77:833.0078125,\n 0x78:625, 0x79:625, 0x7a:500, 0xb0:1000, 0x2013:431, 0x2024:174, 0x2027:174,\n },\n \"Arial\": {\n 0x20:277.83203125, 0x22:354.98046875, 0x25:889.16015625, 0x28:333.0078125, 0x29:333.0078125, 0x2b:583.984375, 0x2c:277.83203125, 0x2d:333.0078125, 0x2e:277.83203125, 0x2f:277.83203125,\n 0x30:556.15234375, 0x31:556.15234375, 0x32:556.15234375, 0x33:556.15234375, 0x34:556.15234375, 0x35:556.15234375, 0x36:556.15234375, 0x37:556.15234375, 0x38:556.15234375, 0x39:556.15234375,\n 0x3a:277.83203125, 0x3b:277.83203125, 0x3d:583.984375, 0x3f:556.15234375, 0x41:666.9921875, 0x42:666.9921875, 0x43:722.16796875, 0x44:722.16796875, 0x45:666.9921875, 0x46:610.83984375,\n 0x47:777.83203125, 0x48:722.16796875, 0x49:277.83203125, 0x4b:666.9921875, 0x4c:556.15234375, 0x4d:833.0078125, 0x4e:722.16796875, 0x4f:777.83203125, 0x50:666.9921875, 0x51:777.83203125,\n 0x52:722.16796875, 0x53:666.9921875, 0x54:610.83984375, 0x55:722.16796875, 0x56:666.9921875, 0x57:943.84765625, 0x58:666.9921875, 0x59:666.9921875, 0x5a:610.83984375, 0x61:556.15234375,\n 0x62:556.15234375, 0x64:556.15234375, 0x65:556.15234375, 0x66:277.83203125, 0x67:556.15234375, 0x68:556.15234375, 0x69:222.16796875, 0x6a:222.16796875, 0x6c:222.16796875, 0x6d:833.0078125,\n 0x6e:556.15234375, 0x6f:556.15234375, 0x70:556.15234375, 0x71:556.15234375, 0x72:333.0078125, 0x74:277.83203125, 0x75:556.15234375, 0x77:722.16796875, 0xb7:333.0078125, 0xe9:556.15234375,\n 0xf4:556.15234375, 0x2013:556.15234375, 0x2019:222.16796875, 0x201c:333.0078125, 0x201d:333.0078125, 0x2219:277.83203125, 0x278c:1000, 0xac00:1000, 0xac01:1000, 0xac04:1000,\n 0xac1c:1000, 0xac1d:1000, 0xac70:1000, 0xac74:1000, 0xac80:1000, 0xac8c:1000, 0xaca9:1000, 0xacac:1000, 0xacb0:1000, 0xacbd:1000,\n 0xacc4:1000, 0xace0:1000, 0xacf5:1000, 0xacfc:1000, 0xad00:1000, 0xad11:1000, 0xad50:1000, 0xad6c:1000, 0xad6d:1000, 0xaddc:1000,\n 0xadf8:1000, 0xadf9:1000, 0xadfc:1000, 0xae00:1000, 0xae30:1000, 0xae43:1000, 0xb09c:1000, 0xb0a8:1000, 0xb0b4:1000, 0xb108:1000,\n 0xb110:1000, 0xb124:1000, 0xb144:1000, 0xb178:1000, 0xb204:1000, 0xb274:1000, 0xb294:1000, 0xb2a5:1000, 0xb2c8:1000, 0xb2dd:1000,\n 0xb2e4:1000, 0xb2e8:1000, 0xb2ec:1000, 0xb2f4:1000, 0xb2f9:1000, 0xb300:1000, 0xb354:1000, 0xb370:1000, 0xb378:1000, 0xb3c4:1000,\n 0xb3c5:1000, 0xb3d9:1000, 0xb4c8:1000, 0xb4dc:1000, 0xb4dd:1000, 0xb4f1:1000, 0xb514:1000, 0xb529:1000, 0xb77c:1000, 0xb78c:1000,\n 0xb798:1000, 0xb799:1000, 0xb79c:1000, 0xb7a8:1000, 0xb7ab:1000, 0xb7b5:1000, 0xb7c9:1000, 0xb7ec:1000, 0xb808:1000, 0xb80c:1000,\n 0xb825:1000, 0xb840:1000, 0xb85c:1000, 0xb85d:1000, 0xb860:1000, 0xb8cc:1000, 0xb8e8:1000, 0xb958:1000, 0xb974:1000, 0xb9ac:1000,\n 0xb9c1:1000, 0xb9c8:1000, 0xb9cc:1000, 0xb9dd:1000, 0xba74:1000, 0xba85:1000, 0xbaa8:1000, 0xbaa9:1000, 0xbb34:1000, 0xbb38:1000,\n 0xbb3c:1000, 0xbbf8:1000, 0xbbfc:1000, 0xbc0f:1000, 0xbc18:1000, 0xbc1c:1000, 0xbc29:1000, 0xbc30:1000, 0xbc84:1000, 0xbc8c:1000,\n 0xbc94:1000, 0xbca0:1000, 0xbcf4:1000, 0xbcf8:1000, 0xbd80:1000, 0xbd84:1000, 0xbdf0:1000, 0xbe0c:1000, 0xbe14:1000, 0xbe44:1000,\n 0xc0ac:1000, 0xc0b0:1000, 0xc0c1:1000, 0xc0dd:1000, 0xc11c:1000, 0xc11d:1000, 0xc124:1000, 0xc12d:1000, 0xc131:1000, 0xc138:1000,\n 0xc13c:1000, 0xc140:1000, 0xc154:1000, 0xc158:1000, 0xc18c:1000, 0xc18d:1000, 0xc194:1000, 0xc1a1:1000, 0xc1fc:1000, 0xc218:1000,\n 0xc220:1000, 0xc288:1000, 0xc2a4:1000, 0xc2b5:1000, 0xc2dc:1000, 0xc2e0:1000, 0xc2e4:1000, 0xc2ec:1000, 0xc2ed:1000, 0xc2f1:1000,\n 0xc544:1000, 0xc548:1000, 0xc57d:1000, 0xc591:1000, 0xc5b4:1000, 0xc5c5:1000, 0xc5c6:1000, 0xc5d4:1000, 0xc5ec:1000, 0xc5ed:1000,\n 0xc5f0:1000, 0xc601:1000, 0xc608:1000, 0xc624:1000, 0xc628:1000, 0xc635:1000, 0xc640:1000, 0xc644:1000, 0xc678:1000, 0xc6a9:1000,\n 0xc6b0:1000, 0xc6b4:1000, 0xc6cc:1000, 0xc6d0:1000, 0xc6d4:1000, 0xc704:1000, 0xc708:1000, 0xc720:1000, 0xc721:1000, 0xc728:1000,\n 0xc73c:1000, 0xc744:1000, 0xc751:1000, 0xc758:1000, 0xc774:1000, 0xc778:1000, 0xc785:1000, 0xc790:1000, 0xc791:1000, 0xc7a5:1000,\n 0xc7ac:1000, 0xc800:1000, 0xc801:1000, 0xc804:1000, 0xc810:1000, 0xc811:1000, 0xc815:1000, 0xc81c:1000, 0xc81d:1000, 0xc870:1000,\n 0xc8fc:1000, 0xc900:1000, 0xc911:1000, 0xc988:1000, 0xc99d:1000, 0xc9c0:1000, 0xc9c1:1000, 0xc9c4:1000, 0xc9c8:1000, 0xc9d1:1000,\n 0xc9d5:1000, 0xcc29:1000, 0xcc38:1000, 0xcc44:1000, 0xcca0:1000, 0xccad:1000, 0xccb4:1000, 0xcd5c:1000, 0xcd94:1000, 0xcd95:1000,\n 0xcd9c:1000, 0xcda9:1000, 0xcde8:1000, 0xce20:1000, 0xce21:1000, 0xce58:1000, 0xce68:1000, 0xce74:1000, 0xcee4:1000, 0xcf13:1000,\n 0xcf58:1000, 0xd050:1000, 0xd06c:1000, 0xd074:1000, 0xd0a4:1000, 0xd0c0:1000, 0xd0c4:1000, 0xd0c8:1000, 0xd0d0:1000, 0xd130:1000,\n 0xd134:1000, 0xd138:1000, 0xd14c:1000, 0xd150:1000, 0xd1a0:1000, 0xd1b5:1000, 0xd2b8:1000, 0xd2f0:1000, 0xd300:1000, 0xd30c:1000,\n 0xd310:1000, 0xd398:1000, 0xd3ec:1000, 0xd3fc:1000, 0xd45c:1000, 0xd504:1000, 0xd508:1000, 0xd50c:1000, 0xd544:1000, 0xd558:1000,\n 0xd559:1000, 0xd55c:1000, 0xd568:1000, 0xd574:1000, 0xd575:1000, 0xd589:1000, 0xd5a5:1000, 0xd5c8:1000, 0xd5d8:1000, 0xd604:1000,\n 0xd611:1000, 0xd615:1000, 0xd638:1000, 0xd640:1000, 0xd64d:1000, 0xd654:1000, 0xd655:1000, 0xd658:1000, 0xd65c:1000, 0xd68d:1000,\n 0xd750:1000,\n },\n \"한양견고딕\": {\n 0x30:563, 0x31:563, 0x32:563, 0x33:563, 0x34:563, 0x35:563, 0x36:563, 0x37:563, 0x39:563, 0xb7:381,\n 0x2019:300,\n },\n \"한컴 고딕\": {\n 0x26:892, 0x3b:297, 0x42:627, 0x46:554, 0x50:586, 0x57:961, 0x68:592, 0x79:530, 0xdc:891, 0x374:240,\n 0x2018:303, 0x201c:446, 0x201d:446, 0x2022:586, 0x2027:288, 0x2219:970, 0x25aa:970, 0x25b8:970, 0x25e6:970, 0x2714:970,\n 0x278a:970, 0x2981:970, 0x3010:486, 0x3011:486, 0xf000:970, 0xff62:485, 0xff63:485,\n },\n \"필기\": {\n 0x28:500, 0x29:500, 0x2c:500, 0x2d:500, 0x2e:500, 0x30:500, 0x31:500, 0x32:500, 0x33:500, 0x35:500,\n 0x36:500, 0x39:500, 0x3a:500, 0x60:500, 0x2018:500, 0x2019:500, 0x201c:500, 0x201d:500, 0x2024:1000,\n },\n \"KoPub돋움체 Medium\": {\n 0x2e:300, 0x17e:313, 0x2013:431, 0xf000:1000, 0xff1e:900, 0xff62:500, 0xff63:500, 0xff65:500,\n },\n \"신명 태명조\": {\n 0xb7:384, 0x2018:200,\n },\n \"신명 태고딕\": {\n 0xb7:381, 0x2018:200, 0x2019:200, 0x2024:174, 0x203b:762,\n },\n \"#신명조\": {\n 0xb7:384,\n },\n \"신명 중고딕\": {\n 0xb7:381,\n },\n \"HCI Hollyhock\": {\n 0x2018:220, 0x2019:220, 0x201c:331, 0x201d:331, 0x2024:174, 0x2027:174, 0x2219:500,\n 0xa7:638, 0xb0:424, 0xb1:669, 0xb6:561, 0xb7:379, 0xd7:621, 0xe9:532, 0xf1:527, 0xf7:621, 0xfc:532,\n 0x201a:292,\n },\n \"시스템\": {\n 0x28:300, 0x29:250, 0x2a:330, 0x2b:485, 0x2c:200, 0x2d:406, 0x2e:180, 0x2f:390, 0x30:485, 0x31:485,\n 0x32:485, 0x33:485, 0x36:485, 0x3a:234, 0x41:589, 0x42:594, 0x43:602, 0x46:520, 0x48:616, 0x4b:584,\n 0x4e:627, 0x50:572, 0x53:564, 0x54:550, 0x57:808, 0x58:566, 0x61:442, 0x63:456, 0x65:464, 0x66:270,\n 0x67:497, 0x68:478, 0x69:176, 0x6c:168, 0x6e:478, 0x6f:478, 0x70:494, 0x72:296, 0x73:426, 0x74:300,\n 0x75:478, 0x76:436, 0x79:433, 0x201c:322, 0x304b:800, 0x306a:867, 0x5b57:1000, 0x6bcd:1000, 0x6ce8:1000, 0x6f22:1000,\n 0x8a9e:1000, 0x97f3:1000, 0xac00:880, 0xac01:880, 0xac08:880, 0xac1c:880, 0xacbd:880, 0xacc4:880, 0xace0:880, 0xacfc:880,\n 0xad6c:880, 0xadf8:880, 0xae00:880, 0xae30:880, 0xaf34:880, 0xafb8:880, 0xb098:880, 0xb0b1:880, 0xb137:880, 0xb294:880,\n 0xb2a5:880, 0xb2e4:880, 0xb2e8:880, 0xb2ec:880, 0xb2f9:880, 0xb300:880, 0xb358:880, 0xb3c4:880, 0xb3d9:880, 0xb454:880,\n 0xb4dc:880, 0xb4e4:880, 0xb4f1:880, 0xb530:880, 0xb610:880, 0xb77c:880, 0xb798:880, 0xb7ec:880, 0xb808:880, 0xb825:880,\n 0xb85c:880, 0xb85d:880, 0xb978:880, 0xb9ac:880, 0xb9b0:880, 0xb9bc:880, 0xb9c8:880, 0xb9cc:880, 0xb9e4:880, 0xb9e8:880,\n 0xb9f5:880, 0xba38:880, 0xba3c:880, 0xba54:880, 0xbaa8:880, 0xbb35:880, 0xbb38:880, 0xbbf8:880, 0xbc14:880, 0xbc1c:880,\n 0xbc29:880, 0xbc30:880, 0xbc84:880, 0xbcc0:880, 0xbcf4:880, 0xbcf8:880, 0xbd88:880, 0xbe0c:880, 0xbe14:880, 0xbe68:880,\n 0xc0ac:880, 0xc0b0:880, 0xc0bd:880, 0xc0c1:880, 0xc11c:880, 0xc124:880, 0xc158:880, 0xc18c:880, 0xc1a1:880, 0xc218:880,\n 0xc26c:880, 0xc2a4:880, 0xc2dc:880, 0xc2dd:880, 0xc2e0:880, 0xc544:880, 0xc558:880, 0xc55e:880, 0xc5b4:880, 0xc5b8:880,\n 0xc5d0:880, 0xc5ec:880, 0xc5f4:880, 0xc624:880, 0xc635:880, 0xc640:880, 0xc6a9:880, 0xc6b0:880, 0xc6b4:880, 0xc6d0:880,\n 0xc6f9:880, 0xc704:880, 0xc73c:880, 0xc740:880, 0xc74c:880, 0xc758:880, 0xc774:880, 0xc778:880, 0xc77c:880, 0xc785:880,\n 0xc790:880, 0xc7a5:880, 0xc800:880, 0xc804:880, 0xc815:880, 0xc820:880, 0xc870:880, 0xc911:880, 0xc9c0:880, 0xc9c1:880,\n 0xc9d1:880, 0xcabd:880, 0xcc0d:880, 0xcc28:880, 0xcc38:880, 0xcc3e:880, 0xcc45:880, 0xccb4:880, 0xcd95:880, 0xcd9c:880,\n 0xcef4:880, 0xd06c:880, 0xd130:880, 0xd14c:880, 0xd14d:880, 0xd1b5:880, 0xd2b8:880, 0xd2c0:880, 0xd30c:880, 0xd310:880,\n 0xd329:880, 0xd37c:880, 0xd398:880, 0xd3b8:880, 0xd3c9:880, 0xd45c:880, 0xd4e8:880, 0xd504:880, 0xd53c:880, 0xd53d:880,\n 0xd558:880, 0xd55c:880, 0xd569:880, 0xd5a5:880, 0xd638:880, 0xd648:880, 0xd654:880, 0xd655:880, 0xd658:880, 0xd68c:880,\n 0xd734:880, 0xf000:1000,\n },\n \"산세리프\": {\n 0x21:500, 0x22:500, 0x23:500, 0x24:500, 0x27:500, 0x2a:500, 0x3a:500, 0x3b:500, 0x3d:500, 0x41:500,\n 0x42:500, 0x43:500, 0x44:500, 0x45:500, 0x46:500, 0x48:500, 0x49:500, 0x4b:500, 0x4c:500, 0x4d:500,\n 0x4e:500, 0x4f:500, 0x50:500, 0x52:500, 0x53:500, 0x54:500, 0x55:500, 0x56:500, 0x57:500, 0x5b:500,\n 0x5c:500, 0x5d:500, 0x60:500, 0x61:500, 0x63:500, 0x64:500, 0x65:500, 0x68:500, 0x69:500, 0x6c:500,\n 0x6d:500, 0x6e:500, 0x6f:500, 0x70:500, 0x72:500, 0x73:500, 0x74:500, 0x77:500,\n },\n \"HY견명조\": {\n 0x21:666.015625, 0x22:583.0078125, 0x23:750, 0x24:750, 0x25:958.0078125, 0x26:958.0078125, 0x27:416.015625, 0x28:458.0078125, 0x29:458.0078125, 0x2a:666.015625,\n 0x2b:708.0078125, 0x2c:375, 0x2d:708.0078125, 0x2e:375, 0x2f:500, 0x30:666.015625, 0x31:666.015625, 0x32:666.015625, 0x33:666.015625, 0x34:666.015625,\n 0x35:666.015625, 0x36:666.015625, 0x37:666.015625, 0x38:666.015625, 0x39:666.015625, 0x3a:416.015625, 0x3b:416.015625, 0x3c:625, 0x3d:708.0078125, 0x3e:625,\n 0x3f:666.015625, 0x40:958.0078125, 0x41:833.0078125, 0x42:791.015625, 0x43:791.015625, 0x44:833.0078125, 0x45:750, 0x46:708.0078125, 0x47:833.0078125, 0x48:916.015625,\n 0x49:458.0078125, 0x4a:541.015625, 0x4b:916.015625, 0x4c:750, 0x4d:958.0078125, 0x4e:875, 0x4f:875, 0x50:750, 0x51:875, 0x52:791.015625,\n 0x53:708.0078125, 0x54:875, 0x55:833.0078125, 0x56:791.015625, 0x57:1000, 0x58:833.0078125, 0x59:791.015625, 0x5a:708.0078125, 0x5b:458.0078125, 0x5c:500,\n 0x5d:458.0078125, 0x5e:583.0078125, 0x5f:500, 0x60:250, 0x61:583.0078125, 0x62:625, 0x63:583.0078125, 0x64:625, 0x65:625, 0x66:458.0078125,\n 0x67:625, 0x68:708.0078125, 0x69:416.015625, 0x6a:375, 0x6b:708.0078125, 0x6c:416.015625, 0x6d:958.0078125, 0x6e:666.015625, 0x6f:625, 0x70:666.015625,\n 0x71:666.015625, 0x72:500, 0x73:541.015625, 0x74:458.0078125, 0x75:625, 0x76:625, 0x77:875, 0x78:666.015625, 0x79:625, 0x7a:541.015625,\n 0x7b:416.015625, 0x7c:333.0078125, 0x7d:416.015625, 0x7e:750, 0x2019:1000, 0x2024:174, 0x2160:1000, 0x2163:1000, 0x2164:1000, 0x223c:1000,\n 0x25a1:1000, 0x25aa:1000, 0x25cb:1000, 0x33a1:1000, 0xf000:1000,\n },\n \"HY그래픽M\": {\n 0x21:333.0078125, 0x22:458.0078125, 0x23:583.0078125, 0x24:666.015625, 0x25:958.0078125, 0x26:875, 0x27:333.0078125, 0x28:375, 0x29:375, 0x2a:583.0078125,\n 0x2b:583.0078125, 0x2c:250, 0x2d:583.0078125, 0x2e:250, 0x2f:458.0078125, 0x30:583.0078125, 0x31:583.0078125, 0x32:583.0078125, 0x33:583.0078125, 0x34:583.0078125,\n 0x35:583.0078125, 0x36:583.0078125, 0x37:583.0078125, 0x38:583.0078125, 0x39:583.0078125, 0x3a:375, 0x3b:375, 0x3c:583.0078125, 0x3d:583.0078125, 0x3e:583.0078125,\n 0x3f:541.015625, 0x40:1000, 0x41:708.0078125, 0x42:666.015625, 0x43:708.0078125, 0x44:708.0078125, 0x45:583.0078125, 0x46:541.015625, 0x47:750, 0x48:666.015625,\n 0x49:291.015625, 0x4a:333.0078125, 0x4b:666.015625, 0x4c:541.015625, 0x4d:875, 0x4e:708.0078125, 0x4f:791.015625, 0x50:666.015625, 0x51:791.015625, 0x52:666.015625,\n 0x53:666.015625, 0x54:666.015625, 0x55:708.0078125, 0x56:625, 0x57:916.015625, 0x58:625, 0x59:625, 0x5a:583.0078125, 0x5b:375, 0x5c:458.0078125,\n 0x5d:375, 0x5e:458.0078125, 0x5f:500, 0x60:250, 0x61:541.015625, 0x62:583.0078125, 0x63:541.015625, 0x64:583.0078125, 0x65:583.0078125, 0x66:375,\n 0x67:541.015625, 0x68:541.015625, 0x69:291.015625, 0x6a:291.015625, 0x6b:541.015625, 0x6c:291.015625, 0x6d:833.0078125, 0x6e:541.015625, 0x6f:583.0078125, 0x70:583.0078125,\n 0x71:583.0078125, 0x72:375, 0x73:500, 0x74:375, 0x75:583.0078125, 0x76:500, 0x77:750, 0x78:500, 0x79:458.0078125, 0x7a:458.0078125,\n 0x7b:416.015625, 0x7c:291.015625, 0x7d:416.015625, 0x7e:583.0078125, 0x119e:1000, 0x201c:1000, 0x201d:1000, 0x2160:1000, 0x2161:1000, 0x2162:1000,\n 0x2163:1000, 0x25cb:1000, 0x27a1:1000, 0xf000:1000,\n },\n \"Gulim\": {\n 0x21:333.0078125, 0x22:375, 0x23:750, 0x24:597.65625, 0x25:875, 0x26:687.5, 0x27:283.203125, 0x28:375, 0x29:375, 0x2a:500,\n 0x2b:625, 0x2c:333.984375, 0x2d:625, 0x2e:333.984375, 0x2f:416.9921875, 0x30:574.21875, 0x31:574.21875, 0x32:574.21875, 0x33:574.21875, 0x34:574.21875,\n 0x35:574.21875, 0x36:574.21875, 0x37:574.21875, 0x38:574.21875, 0x39:574.21875, 0x3a:333.984375, 0x3b:333.984375, 0x3c:625, 0x3d:625, 0x3e:625,\n 0x3f:541.9921875, 0x40:1000, 0x41:645.5078125, 0x42:676.7578125, 0x43:717.7734375, 0x44:721.6796875, 0x45:625, 0x46:595.703125, 0x47:769.53125, 0x48:730.46875,\n 0x49:269.53125, 0x4a:500, 0x4b:634.765625, 0x4c:542.96875, 0x4d:812.5, 0x4e:699.21875, 0x4f:769.53125, 0x50:636.71875, 0x51:773.4375, 0x52:666.015625,\n 0x53:632.8125, 0x54:582.03125, 0x55:710.9375, 0x56:599.609375, 0x57:894.53125, 0x58:625, 0x59:625, 0x5a:625, 0x5b:500, 0x5c:916.9921875,\n 0x5d:500, 0x5e:541.9921875, 0x5f:500, 0x60:333.0078125, 0x61:562.5, 0x62:605.46875, 0x63:572.265625, 0x64:605.46875, 0x65:567.3828125, 0x66:341.796875,\n 0x67:605.46875, 0x68:571.2890625, 0x69:241.2109375, 0x6a:241.2109375, 0x6b:500, 0x6c:231.4453125, 0x6d:861.328125, 0x6e:580.078125, 0x6f:605.46875, 0x70:605.46875,\n 0x71:605.46875, 0x72:333.0078125, 0x73:525.390625, 0x74:313.4765625, 0x75:570.3125, 0x76:500, 0x77:750, 0x78:500, 0x79:500, 0x7a:500,\n 0x7b:500, 0x7c:500, 0x7d:500, 0x7e:791.9921875, 0x2013:500,\n },\n \"배달의민족 도현\": {\n 0x21:380, 0x22:378, 0x23:931, 0x24:697, 0x25:869, 0x26:751, 0x27:234, 0x28:310, 0x29:310, 0x2a:651,\n 0x2b:560, 0x2c:236, 0x2d:594, 0x2e:250, 0x2f:494, 0x30:687, 0x31:424, 0x32:608, 0x33:629, 0x34:700,\n 0x35:657, 0x36:694, 0x37:659, 0x38:672, 0x39:639, 0x3a:273, 0x3b:277, 0x3c:430, 0x3d:562, 0x3e:442,\n 0x3f:584, 0x40:875, 0x41:667, 0x42:665, 0x43:688, 0x44:712, 0x45:712, 0x46:690, 0x47:700, 0x48:709,\n 0x49:286, 0x4a:597, 0x4b:673, 0x4c:690, 0x4d:756, 0x4e:706, 0x4f:700, 0x50:677, 0x51:737, 0x52:708,\n 0x53:729, 0x54:632, 0x55:706, 0x56:667, 0x57:1075, 0x58:648, 0x59:630, 0x5a:661, 0x5b:388, 0x5c:910,\n 0x5d:376, 0x5e:486, 0x5f:521, 0x60:207, 0x61:605, 0x62:607, 0x63:564, 0x64:595, 0x65:632, 0x66:457,\n 0x67:607, 0x68:617, 0x69:257, 0x6a:254, 0x6b:580, 0x6c:270, 0x6d:1021, 0x6e:632, 0x6f:595, 0x70:598,\n 0x71:612, 0x72:532, 0x73:593, 0x74:425, 0x75:625, 0x76:561, 0x77:933, 0x78:568, 0x79:556, 0x7a:530,\n 0x7b:417, 0x7c:243, 0x7d:407, 0x7e:676, 0x2460:960, 0x2461:960,\n },\n \"Dotum\": {\n 0x21:333.984375, 0x22:416.9921875, 0x23:625, 0x24:500, 0x25:916.9921875, 0x26:708.984375, 0x27:291.015625, 0x28:375, 0x29:375, 0x2a:583.0078125,\n 0x2b:582.03125, 0x2c:375, 0x2d:589.84375, 0x2e:375, 0x2f:416.9921875, 0x30:583.0078125, 0x31:583.0078125, 0x32:583.0078125, 0x33:583.0078125, 0x34:583.0078125,\n 0x35:583.0078125, 0x36:583.0078125, 0x37:583.0078125, 0x38:583.0078125, 0x39:583.0078125, 0x3a:339.84375, 0x3b:339.84375, 0x3c:625, 0x3d:583.984375, 0x3e:625,\n 0x3f:583.0078125, 0x40:1000, 0x41:666.9921875, 0x42:679.6875, 0x43:720.703125, 0x44:724.609375, 0x45:628.90625, 0x46:599.609375, 0x47:750, 0x48:722.65625,\n 0x49:257.8125, 0x4a:484.375, 0x4b:656.25, 0x4c:541.015625, 0x4d:808.59375, 0x4e:697.265625, 0x4f:750, 0x50:642.578125, 0x51:750, 0x52:667.96875,\n 0x53:638.671875, 0x54:583.0078125, 0x55:724.609375, 0x56:601.5625, 0x57:892.578125, 0x58:603.515625, 0x59:601.5625, 0x5a:603.515625, 0x5b:500, 0x5c:958.0078125,\n 0x5d:500, 0x5e:625, 0x5f:500, 0x60:332.03125, 0x61:583.0078125, 0x62:599.609375, 0x63:558.59375, 0x64:603.515625, 0x65:558.59375, 0x66:343.75,\n 0x67:597.65625, 0x68:560.546875, 0x69:228.515625, 0x6a:228.515625, 0x6b:509.765625, 0x6c:230.46875, 0x6d:916.9921875, 0x6e:568.359375, 0x6f:599.609375, 0x70:601.5625,\n 0x71:603.515625, 0x72:320.3125, 0x73:515.625, 0x74:312.5, 0x75:554.6875, 0x76:474.609375, 0x77:724.609375, 0x78:478.515625, 0x79:480.46875, 0x7a:482.421875,\n 0x7b:500, 0x7c:500, 0x7d:500, 0x7e:791.015625, 0x5fc5:1000, 0x7121:1000,\n },\n \"Palatino Linotype\": {\n 0x21:277.83203125, 0x22:371.09375, 0x23:479.00390625, 0x24:500, 0x25:839.84375, 0x26:777.83203125, 0x27:208.0078125, 0x28:333.0078125, 0x29:333.0078125, 0x2a:389.16015625,\n 0x2b:500, 0x2c:250, 0x2d:333.0078125, 0x2e:250, 0x2f:320.3125, 0x30:500, 0x31:500, 0x32:500, 0x33:500, 0x34:500,\n 0x35:500, 0x36:500, 0x37:500, 0x38:500, 0x39:500, 0x3a:250, 0x3b:250, 0x3c:500, 0x3d:500, 0x3e:500,\n 0x3f:443.84765625, 0x40:683.10546875, 0x41:777.83203125, 0x42:610.83984375, 0x43:708.984375, 0x44:773.92578125, 0x45:610.83984375, 0x46:556.15234375, 0x47:763.18359375, 0x48:832.03125,\n 0x49:336.9140625, 0x4a:333.0078125, 0x4b:726.07421875, 0x4c:610.83984375, 0x4d:945.80078125, 0x4e:831.0546875, 0x4f:786.1328125, 0x50:604.00390625, 0x51:786.1328125, 0x52:667.96875,\n 0x53:524.90234375, 0x54:612.79296875, 0x55:777.83203125, 0x56:722.16796875, 0x57:1000, 0x58:666.9921875, 0x59:666.9921875, 0x5a:666.9921875, 0x5b:333.0078125, 0x5c:605.95703125,\n 0x5d:333.0078125, 0x5e:500, 0x5f:500, 0x60:333.0078125, 0x61:500, 0x62:553.22265625, 0x63:443.84765625, 0x64:610.83984375, 0x65:479.00390625, 0x66:333.0078125,\n 0x67:556.15234375, 0x68:582.03125, 0x69:291.015625, 0x6a:233.88671875, 0x6b:556.15234375, 0x6c:291.015625, 0x6d:882.8125, 0x6e:582.03125, 0x6f:545.8984375, 0x70:601.07421875,\n 0x71:560.05859375, 0x72:395.01953125, 0x73:423.828125, 0x74:326.171875, 0x75:603.02734375, 0x76:564.94140625, 0x77:833.984375, 0x78:516.11328125, 0x79:556.15234375, 0x7a:500,\n 0x7b:333.0078125, 0x7c:500, 0x7d:333.0078125, 0x7e:500,\n },\n \"학교안심 포스터 B\": {\n 0x21:327, 0x22:488, 0x23:605, 0x24:703, 0x25:796, 0x26:800, 0x27:258, 0x28:361, 0x29:361, 0x2a:446,\n 0x2b:624, 0x2c:291, 0x2d:588, 0x2e:291, 0x2f:521, 0x30:610, 0x31:610, 0x32:610, 0x33:610, 0x34:610,\n 0x35:610, 0x36:610, 0x37:610, 0x38:610, 0x39:610, 0x3a:291, 0x3b:291, 0x3c:625, 0x3d:638, 0x3e:625,\n 0x3f:616, 0x40:875, 0x41:763, 0x42:747, 0x43:747, 0x44:747, 0x45:716, 0x46:632, 0x47:800, 0x48:801,\n 0x49:327, 0x4a:612, 0x4b:794, 0x4c:651, 0x4d:928, 0x4e:802, 0x4f:823, 0x50:694, 0x51:808, 0x52:747,\n 0x53:687, 0x54:662, 0x55:781, 0x56:734, 0x57:987, 0x58:732, 0x59:733, 0x5a:666, 0x5b:361, 0x5c:521,\n 0x5d:361, 0x5e:608, 0x5f:588, 0x60:309, 0x61:598, 0x62:630, 0x63:611, 0x64:629, 0x65:611, 0x66:380,\n 0x67:629, 0x68:623, 0x69:313, 0x6a:313, 0x6b:606, 0x6c:315, 0x6d:941, 0x6e:624, 0x6f:633, 0x70:629,\n 0x71:626, 0x72:410, 0x73:548, 0x74:374, 0x75:624, 0x76:571, 0x77:866, 0x78:588, 0x79:569, 0x7a:525,\n 0x7b:386, 0x7c:320, 0x7d:385, 0x7e:624,\n },\n \"문체부 바탕체\": {\n 0x35:583, 0x2027:174,\n },\n \"Tahoma\": {\n 0x21:332.03125, 0x22:401.3671875, 0x23:727.5390625, 0x24:545.8984375, 0x25:976.5625, 0x26:673.828125, 0x27:210.9375, 0x28:382.8125, 0x29:382.8125, 0x2a:545.8984375,\n 0x2b:727.5390625, 0x2c:302.734375, 0x2d:363.28125, 0x2e:302.734375, 0x2f:382.32421875, 0x30:545.8984375, 0x31:545.8984375, 0x32:545.8984375, 0x33:545.8984375, 0x34:545.8984375,\n 0x35:545.8984375, 0x36:545.8984375, 0x37:545.8984375, 0x38:545.8984375, 0x39:545.8984375, 0x3a:353.515625, 0x3b:353.515625, 0x3c:727.5390625, 0x3d:727.5390625, 0x3e:727.5390625,\n 0x3f:473.6328125, 0x40:909.1796875, 0x41:599.609375, 0x42:589.35546875, 0x43:600.5859375, 0x44:678.22265625, 0x45:561.03515625, 0x46:521.484375, 0x47:667.48046875, 0x48:675.29296875,\n 0x49:373.046875, 0x4a:416.50390625, 0x4b:587.890625, 0x4c:497.55859375, 0x4d:770.5078125, 0x4e:667.48046875, 0x4f:707.51953125, 0x50:551.26953125, 0x51:707.51953125, 0x52:620.60546875,\n 0x53:557.12890625, 0x54:583.984375, 0x55:655.76171875, 0x56:596.6796875, 0x57:901.85546875, 0x58:580.56640625, 0x59:576.171875, 0x5a:559.08203125, 0x5b:382.8125, 0x5c:382.32421875,\n 0x5d:382.8125, 0x5e:727.5390625, 0x5f:545.8984375, 0x60:545.8984375, 0x61:524.90234375, 0x62:552.734375, 0x63:461.42578125, 0x64:552.734375, 0x65:526.3671875, 0x66:318.359375,\n 0x67:552.734375, 0x68:557.6171875, 0x69:228.515625, 0x6a:281.73828125, 0x6b:498.046875, 0x6c:228.515625, 0x6d:839.84375, 0x6e:557.6171875, 0x6f:542.96875, 0x70:552.734375,\n 0x71:552.734375, 0x72:360.3515625, 0x73:446.2890625, 0x74:334.47265625, 0x75:557.6171875, 0x76:498.046875, 0x77:742.1875, 0x78:495.1171875, 0x79:498.046875, 0x7a:444.3359375,\n 0x7b:480.46875, 0x7c:382.32421875, 0x7d:480.46875, 0x7e:727.5390625,\n },\n \"양재튼튼체B\": {\n 0x21:346, 0x22:344, 0x23:808, 0x24:627, 0x25:741, 0x26:655, 0x27:189, 0x28:365, 0x29:365, 0x2a:532,\n 0x2b:873, 0x2c:324, 0x2d:873, 0x2e:325, 0x2f:373, 0x30:627, 0x31:627, 0x32:627, 0x33:627, 0x34:627,\n 0x35:627, 0x36:627, 0x37:627, 0x38:627, 0x39:627, 0x3a:346, 0x3b:346, 0x3c:873, 0x3d:873, 0x3e:873,\n 0x3f:575, 0x40:1044, 0x41:651, 0x42:699, 0x43:700, 0x44:705, 0x45:636, 0x46:609, 0x47:743, 0x48:725,\n 0x49:302, 0x4a:432, 0x4b:676, 0x4c:538, 0x4d:798, 0x4e:716, 0x4f:744, 0x50:632, 0x51:776, 0x52:674,\n 0x53:669, 0x54:619, 0x55:695, 0x56:640, 0x57:907, 0x58:642, 0x59:584, 0x5a:596, 0x5b:365, 0x5c:306,\n 0x5d:365, 0x5e:1042, 0x5f:532, 0x60:532, 0x61:554, 0x62:580, 0x63:552, 0x64:580, 0x65:558, 0x66:308,\n 0x67:575, 0x68:572, 0x69:262, 0x6a:265, 0x6b:547, 0x6c:262, 0x6d:848, 0x6e:572, 0x6f:571, 0x70:580,\n 0x71:580, 0x72:376, 0x73:548, 0x74:315, 0x75:572, 0x76:480, 0x77:751, 0x78:497, 0x79:480, 0x7a:510,\n 0x7b:532, 0x7c:532, 0x7d:532, 0x7e:873, 0xb7:976, 0x2191:976, 0x25b8:1000, 0xb85c:1022, 0xb9c8:1023, 0xbaa8:1023,\n 0xc81c:1023, 0xcc28:1023, 0xd1a0:1023, 0xd559:1023,\n },\n \"KBL 점프체 B TTF\": {\n 0x21:260, 0x22:365, 0x23:989, 0x24:586, 0x25:949, 0x26:796, 0x27:209, 0x28:412, 0x29:412, 0x2a:585,\n 0x2b:601, 0x2c:281, 0x2d:600, 0x2e:275, 0x2f:587, 0x30:700, 0x31:450, 0x32:668, 0x33:685, 0x34:700,\n 0x35:668, 0x36:688, 0x37:664, 0x38:690, 0x39:688, 0x3a:370, 0x3b:370, 0x3c:478, 0x3d:700, 0x3e:478,\n 0x3f:623, 0x40:1000, 0x41:795, 0x42:725, 0x43:660, 0x44:718, 0x45:718, 0x46:673, 0x47:710, 0x48:720,\n 0x49:220, 0x4a:460, 0x4b:734, 0x4c:605, 0x4d:936, 0x4e:710, 0x4f:720, 0x50:674, 0x51:755, 0x52:680,\n 0x53:699, 0x54:642, 0x55:711, 0x56:756, 0x57:1144, 0x58:756, 0x59:720, 0x5a:677, 0x5b:412, 0x5c:587,\n 0x5d:412, 0x5e:633, 0x5f:600, 0x60:287, 0x61:665, 0x62:684, 0x63:634, 0x64:671, 0x65:670, 0x66:453,\n 0x67:649, 0x68:694, 0x69:220, 0x6a:315, 0x6b:698, 0x6c:305, 0x6d:992, 0x6e:686, 0x6f:696, 0x70:696,\n 0x71:696, 0x72:545, 0x73:668, 0x74:600, 0x75:690, 0x76:666, 0x77:944, 0x78:688, 0x79:654, 0x7a:627,\n 0x7b:502, 0x7c:280, 0x7d:502, 0x7e:770, 0xacb0:890, 0xacc4:950, 0xb204:840, 0xbaa9:840, 0xc138:950, 0xc5f0:890,\n 0xc758:880, 0xc801:890, 0xc8fc:840,\n },\n \"IM혜민 Bold\": {\n 0x21:333, 0x22:376, 0x23:763, 0x24:691, 0x25:721, 0x26:641, 0x27:227, 0x28:363, 0x29:362, 0x2a:444,\n 0x2b:564, 0x2c:228, 0x2d:562, 0x2e:235, 0x2f:405, 0x30:675, 0x31:675, 0x32:675, 0x33:675, 0x34:675,\n 0x35:675, 0x36:675, 0x37:675, 0x38:675, 0x39:675, 0x3a:268, 0x3b:265, 0x3c:460, 0x3d:551, 0x3e:461,\n 0x3f:631, 0x40:901, 0x41:627, 0x42:653, 0x43:656, 0x44:630, 0x45:613, 0x46:567, 0x47:694, 0x48:658,\n 0x49:333, 0x4a:595, 0x4b:667, 0x4c:613, 0x4d:745, 0x4e:702, 0x4f:694, 0x50:613, 0x51:694, 0x52:610,\n 0x53:650, 0x54:617, 0x55:682, 0x56:594, 0x57:793, 0x58:580, 0x59:604, 0x5a:647, 0x5b:383, 0x5c:522,\n 0x5d:414, 0x5e:541, 0x5f:525, 0x60:250, 0x61:503, 0x62:563, 0x63:515, 0x64:545, 0x65:541, 0x66:424,\n 0x67:527, 0x68:555, 0x69:266, 0x6a:435, 0x6b:503, 0x6c:272, 0x6d:671, 0x6e:539, 0x6f:529, 0x70:529,\n 0x71:529, 0x72:443, 0x73:534, 0x74:490, 0x75:547, 0x76:530, 0x77:625, 0x78:472, 0x79:540, 0x7a:540,\n 0x7b:462, 0x7c:464, 0x7d:451, 0x7e:597, 0x201c:364, 0x201d:366, 0xace0:925, 0xb294:925, 0xb3c4:925, 0xb974:925,\n 0xbaa8:925, 0xbb34:925, 0xc694:925,\n },\n \"HY울릉도B\": {\n 0x21:404.296875, 0x22:393.5546875, 0x23:898.4375, 0x24:625, 0x25:974.609375, 0x26:827.1484375, 0x27:250, 0x28:375, 0x29:375, 0x2a:625,\n 0x2b:875, 0x2c:333.0078125, 0x2d:875, 0x2e:333.0078125, 0x2f:382.8125, 0x30:662.109375, 0x31:662.109375, 0x32:662.109375, 0x33:662.109375, 0x34:662.109375,\n 0x35:662.109375, 0x36:662.109375, 0x37:662.109375, 0x38:662.109375, 0x39:662.109375, 0x3a:333.0078125, 0x3b:333.0078125, 0x3c:875, 0x3d:875, 0x3e:875,\n 0x3f:660.15625, 0x40:1042.96875, 0x41:737.3046875, 0x42:594.7265625, 0x43:833.0078125, 0x44:756.8359375, 0x45:526.3671875, 0x46:509.765625, 0x47:869.140625, 0x48:686.5234375,\n 0x49:294.921875, 0x4a:504.8828125, 0x4b:645.5078125, 0x4c:491.2109375, 0x4d:907.2265625, 0x4e:743.1640625, 0x4f:875.9765625, 0x50:602.5390625, 0x51:875, 0x52:610.3515625,\n 0x53:550.78125, 0x54:500.9765625, 0x55:645.5078125, 0x56:673.828125, 0x57:931.640625, 0x58:677.734375, 0x59:625, 0x5a:587.890625, 0x5b:375, 0x5c:375,\n 0x5d:375, 0x5e:791.9921875, 0x5f:500, 0x60:250, 0x61:731.4453125, 0x62:732.421875, 0x63:704.1015625, 0x64:729.4921875, 0x65:718.75, 0x66:383.7890625,\n 0x67:710.9375, 0x68:651.3671875, 0x69:287.109375, 0x6a:287.109375, 0x6b:577.1484375, 0x6c:287.109375, 0x6d:955.078125, 0x6e:651.3671875, 0x6f:718.75, 0x70:730.46875,\n 0x71:730.46875, 0x72:366.2109375, 0x73:470.703125, 0x74:352.5390625, 0x75:651.3671875, 0x76:561.5234375, 0x77:769.53125, 0x78:546.875, 0x79:604.4921875, 0x7a:508.7890625,\n 0x7b:541.9921875, 0x7c:541.9921875, 0x7d:541.9921875, 0x7e:791.9921875, 0xb7:1000,\n },\n \"신명 태그래픽\": {\n 0x2018:185, 0x2019:185, 0x2024:1000, 0x203b:1000, 0x2460:1000, 0x2463:1000, 0x25a1:1000, 0x25c6:1000, 0x25cb:1000, 0x261e:1000,\n 0x3007:1000, 0x3010:1000, 0x3011:1000,\n },\n // HFT 고딕(고정폭)은 ‘’“” 가 반각이다 — 나머지는 고정폭 그대로(영문 반각·그 밖 전각)\n \"고딕\": {\n 0x2018:500, 0x2019:500, 0x201c:500, 0x201d:500,\n },\n \"굴림\": {\n 0x2024:176, 0x2027:300,\n },\n \"한컴바탕\": {\n 0x2024:176, 0x2026:863,\n },\n \"한양중고딕\": {\n 0x2013:1000, 0x2027:500,\n 0xa7:638, 0xb0:424, 0xb1:669, 0xb6:561, 0xb7:379, 0xd7:621, 0xe9:532, 0xf1:527, 0xf7:621, 0xfc:532,\n 0x2018:224, 0x2019:224, 0x201a:292, 0x201c:375, 0x201d:375,\n },\n}\n\n/** 위 표 중 폭표가 없던 글꼴의 한글 음절 폭(em×1000) — 없으면 1000 */\nexport const FACE_CJK: Record<string, number> = { \"배달의민족 도현\": 960, \"학교안심 포스터 B\": 980, \"양재튼튼체B\": 1024, \"KBL 점프체 B TTF\": 930, \"IM혜민 Bold\": 930 }\n\n/** 글꼴의 빈칸(U+0020) 폭(em×1000) — 글자 모양이 글꼴 빈칸을 쓸 때(useFontSpace=\"1\"). 없는 글꼴은 반각 */\nexport const FACE_SPACE: Record<string, number> = {\n \"맑은 고딕\": 351.5625, \"배달의민족 도현\": 320, \"한컴 윤고딕 230\": 350, \"휴먼명조\": 500, \"HY헤드라인M\": 333.0078125, \"HY견명조\": 333.0078125,\n \"HY신명조\": 333.0078125, \"HYSinMyeongJo-Medium\": 333.0078125, \"KBL 점프체 B TTF\": 200, \"KBL 점프체 R TTF\": 200, \"바탕\": 333.0078125,\n \"돋움\": 333.984375, \"굴림\": 333.0078125, \"함초롬바탕\": 300, \"함초롬돋움\": 300, \"한컴돋움\": 333.0078125, \"Arial\": 277.83203125, \"Times New Roman\": 250,\n \"KoPub바탕체 Light\": 312, \"KoPub바탕체 Medium\": 312, \"KoPub바탕체 Bold\": 312, \"KoPubWorld바탕체 Light\": 312,\n \"KoPub돋움체 Light\": 290, \"KoPub돋움체 Medium\": 290, \"KoPub돋움체 Bold\": 290, \"KoPubWorld돋움체 Light\": 290,\n}\n\n/**\n * 한글 2024 이전 판으로 저장된 문서의 글자 폭(em×1000) — 2024 와 다른 것만. 한글 2022 줄 나눔(같은 글자 반복 문단, 크기 1000~1700,\n * TTF·HFT 같음): 휴먼명조 ‘’“”·ㆍ□◦▪ 는 전각, … 0.864, • 0.464, – 0.430, ‧ 0.173, ․ 0.176. 명조(HFT) 는 ·‘’“” 반각, – 전각, ‧ 반각\n */\nexport const BEFORE_2024_WIDTH: Record<string, Record<number, number>> = {\n // TTF 신명조의 대체 큰따옴표 — 원본 PDF의 Haansoft Batang /W 370. 한양신명조 HFT와 별개다.\n \"신명조\": { 0x201c:370, 0x201d:370 },\n \"휴먼명조\": {\n 0xb7:1000, 0x2013:430, 0x2018:1000, 0x2019:1000, 0x201c:1000, 0x201d:1000, 0x2022:464, 0x2026:864, 0x25a1:1000, 0x25aa:1000,\n 0x25e6:1000, 0x318d:1000, 0x2024:176, 0x2027:173,\n },\n \"명조\": {\n 0xb7:500, 0x2013:1000, 0x2018:500, 0x2019:500, 0x201c:500, 0x201d:500, 0x2027:500,\n },\n}\n","/**\n * 서울남산체·서울한강체 글자 폭(em×1000, unitsPerEm 1000 정수) — 굵기(L·M·B·EB)마다 한글·영문 폭이 같아 계열당 표 하나.\n * 한글 음절(U+AC00~D7A3)은 [폭, 개수] 연속 구간, 나머지(영문·기호·자모)는 폭별 코드 구간(\"a1-a3 b0\", 16진). 표에 없는 글자는 대체 폭.\n * 한컴 저장본(서울 결재문서 2016~2017, 08서울남산체·한강체): 칸 안 \"○ 건강상태 확인 및 감염방지 요령\" 17000(1em) → 한 줄 16312 폭에 든다\n */\nconst NAMSAN_HANGUL = [906,28,915,28,906,28,915,28,864,28,915,28,864,28,915,28,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28,924,28,935,28,924,28,935,28,884,28,935,28,884,28,935,28,900,28,940,28,958,28,898,28,900,56,898,28,958,28,898,28,900,56,898,28,884,28,906,28,915,28,906,28,915,28,864,28,915,28,864,28,915,28,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28,906,28,915,28,906,28,915,28,864,28,915,28,864,28,915,28,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28,924,28,935,28,924,28,935,28,884,28,935,28,884,28,935,28,900,28,940,28,958,28,898,28,900,56,898,28,958,28,898,28,900,56,898,28,884,28,906,28,915,28,906,28,915,28,864,28,915,28,864,28,915,28,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28,906,28,915,28,906,28,915,28,864,28,915,28,864,28,915,28,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28,906,28,915,28,906,28,915,28,864,28,915,28,864,28,915,28,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28,924,28,935,28,924,28,935,28,884,28,935,28,884,28,935,28,900,28,940,28,958,28,898,28,900,56,898,28,958,28,898,28,900,56,898,28,884,28,906,28,915,28,906,28,915,28,864,28,915,28,864,28,915,28,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28,924,28,935,28,924,28,935,28,884,28,935,28,884,28,935,28,900,28,940,28,958,28,898,28,900,56,898,28,958,28,898,28,900,56,898,28,884,28,906,28,935,1,915,27,906,28,935,1,915,27,864,28,935,1,915,27,864,28,935,1,915,27,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28,906,28,915,28,906,28,915,28,864,28,915,28,864,28,915,28,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28,924,28,935,28,924,28,935,28,884,28,935,28,884,28,935,28,900,28,940,28,958,28,898,28,900,56,898,28,958,28,898,28,900,56,898,28,884,28,906,28,915,28,906,28,915,28,864,28,915,28,864,28,915,28,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28,906,28,915,28,906,28,915,28,864,28,915,28,864,28,915,28,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28,906,28,915,28,906,28,915,28,864,28,915,28,864,28,915,28,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28,906,28,915,28,906,28,915,28,864,28,915,28,864,28,915,28,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28,906,28,935,1,915,27,906,28,935,1,915,27,864,28,935,1,915,27,864,28,935,1,915,27,900,28,924,28,939,28,878,28,900,56,878,28,939,28,878,28,900,56,878,28,850,28]\nconst NAMSAN_OTHER: Record<number, string> = { 193:\"207d-207e\", 221:\"201b\", 234:\"131\", 240:\"2018-2019\", 241:\"69 6c\", 252:\"49\", 253:\"2c 2e 2d0\", 258:\"b0 2032\", 260:\"6a\", 276:\"2051\", 280:\"399\", 281:\"3002\", 286:\"b7\", 304:\"2997-2998\", 309:\"60\", 310:\"b8 2db 3001\", 313:\"3016-3017\", 318:\"21 3b9\", 322:\"2bc\", 328:\"27\", 331:\"2985-2986\", 342:\"7c\", 348:\"300c-300d\", 355:\"167\", 358:\"300e-300f 3014-3015\", 359:\"5b 5d\", 375:\"74\", 384:\"28-29\", 386:\"a7\", 387:\"b2-b3 b9 2081-2083\", 388:\"2f 5c\", 390:\"4a\", 396:\"140 201f\", 398:\"66 72\", 400:\"2035-2036 301e-301f\", 405:\"3018-3019\", 406:\"2a 2074 2084\", 408:\"82 ad 433 2013\", 409:\"3a-3b\", 412:\"201c-201d\", 415:\"207f\", 418:\"22\", 423:\"2202\", 428:\"2d\", 432:\"2033\", 442:\"3b6 3be\", 449:\"73\", 450:\"2034 3010-3011\", 455:\"300a-300b\", 458:\"7b 7d 3b5 437\", 460:\"133 3c4 442 207a-207c\", 468:\"3f 43a\", 469:\"204c-204d\", 470:\"443\", 472:\"3a3 2211\", 476:\"3b3 3bb\", 477:\"5e\", 478:\"7a\", 480:\"445\", 483:\"138 3ba\", 484:\"3008-3009\", 490:\"393 3bd 413\", 492:\"142\", 495:\"44f\", 500:\"79\", 504:\"44c\", 505:\"438-439 43d 43f\", 506:\"13f\", 508:\"5f\", 510:\"78 430 441 44d\", 513:\"4c\", 514:\"432\", 516:\"76\", 518:\"6b\", 521:\"46\", 523:\"447\", 524:\"3b4\", 525:\"395 401 415 435 451 2203\", 528:\"446\", 530:\"3a4 422\", 532:\"53\", 533:\"43b\", 534:\"166\", 535:\"3c1 440\", 537:\"434\", 538:\"61 63 65 3b8\", 540:\"396 417\", 541:\"3c5\", 545:\"3b7\", 547:\"45 39e\", 548:\"24 141\", 550:\"423\", 551:\"431\", 552:\"30-39\", 554:\"14b\", 558:\"3a5\", 560:\"a8 3a1 3a7 3bf 3c7 420 43e\", 564:\"3bc\", 568:\"3c0\", 569:\"3b1\", 570:\"5a 62 64 67-68 6e 70-71 75\", 572:\"2025\", 576:\"3c6\", 578:\"425\", 582:\"6f\", 583:\"2b 50 f0\", 585:\"3c3 44a\", 589:\"411\", 590:\"392 39a 412 41a 42f\", 591:\"127\", 592:\"3c-3e 4b 7e fe 42c\", 593:\"de\", 594:\"52\", 596:\"111\", 602:\"42 f8\", 603:\"54\", 604:\"59\", 606:\"df\", 611:\"3b2\", 614:\"2200\", 615:\"391 394 39b 410 212b\", 616:\"58\", 629:\"43c 448\", 635:\"427\", 640:\"421 42d\", 644:\"56\", 646:\"436\", 647:\"23\", 650:\"41 449\", 653:\"43\", 655:\"44b\", 659:\"44\", 660:\"48 4e 397 3a0 41d 41f 220f\", 662:\"b1 d7 f7\", 670:\"132 39d 418\", 672:\"14a\", 673:\"55\", 674:\"3a8 3c8\", 682:\"47 426\", 685:\"414\", 686:\"aa ba 3a9\", 690:\"44e\", 696:\"419\", 708:\"d0\", 710:\"77 398\", 720:\"41b\", 730:\"39f 41e\", 731:\"149\", 733:\"126\", 743:\"4f\", 744:\"42a\", 750:\"3a6 424\", 759:\"a4\", 763:\"d8\", 764:\"51\", 765:\"3c9\", 777:\"26\", 817:\"6d\", 821:\"e6\", 830:\"42b\", 834:\"4d\", 840:\"39c 41c 428 444\", 846:\"153\", 848:\"c6\", 850:\"416\", 852:\"2103\", 858:\"85 2026\", 860:\"429\", 865:\"25\", 874:\"57\", 900:\"42e 203e 3131-3163 3165-318e ff01-ff3b ff3d-ff5d ffe3 ffe6\", 920:\"ae 20ac\", 925:\"152\", 940:\"81 83-84 a1-a3 a5 ab-ac b4 b6 bb-bf 2c7 2d8-2da 2dc-2dd 3d5 2014-2016 2020-2022 2030 2039-203c 2042 2047 2049 204e 2109 2113 2116 2121-2122 2126 2153-2154 215b-215e 2160-2169 2170-2179 2190-2199 219c-219d 21b0-21b4 21b6-21b7 21bc 21c0 21c4-21c5 21cd 21cf-21d4 21e0-21e3 21e6-21e9 21f0 2206-2209 220b-220c 2213 221a 221d-2220 2222 2225-222c 222e 2234-2235 2237 223c-223d 2243 2245 2248 2250-2253 225a 2260-2262 2264-2267 226a-226b 226e-2273 2276-2277 2279-227b 2280-2287 228a-228b 2295-2297 2299 22a3-22a5 22bb-22bc 22ce-22cf 22da-22db 22ee 2306 2312 2314 2460-2487 249c-24e9 24eb-24f4 2500-2503 250c-254b 2588 2592 25a0-25a9 25ad 25b1-25b3 25b5-25b7 25b9 25bc-25bd 25bf-25c1 25c3 25c6-25d1 25e6 25ef 25fb-25fc 2605-2606 260e-2610 261c-261f 262f 2640 2642 2660-2661 2663-266a 266c-266d 266f 2716 271a 2720 2723 2731 273d 273f-2741 2747 274d 2756 2776-277f 278a-2794 279b-279c 279e 27a1 27a4 27b2 27b5 2934-2937 2939 2962-2965 2981 29a3 29be-29bf 29c8 2a26 2a38 2a72 2a8b-2a8c 2a91-2a92 2ac5-2ac6 2acb-2acc 2ae8 3000 3003 3012-3013 301c 3020 3036 3041-3093 30a1-30f6 3164 3200-321c 3231 3239 3251-325a 3260-327b 327e-327f 328a-3290 3294 329e 32a5 3380-3384 3388-33cb 33cf-33d0 33d3 33d6 33d8 33db-33dd ff3c ff5e ffe0-ffe2 ffe5\", 960:\"20a9\", 1000:\"40\" }\nconst HANGANG_HANGUL = [910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56,920,28,900,28,920,28,900,28,860,28,900,28,860,28,900,56,920,28,900,28,860,28,900,56,860,28,900,28,860,28,900,56,860,56,910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56,910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56,920,28,900,28,920,28,900,28,860,28,900,28,860,28,900,56,920,28,900,28,860,28,900,56,860,28,900,28,860,28,900,56,860,56,910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56,910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56,910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56,920,28,900,28,920,28,900,28,860,28,900,28,860,28,900,56,920,28,900,28,860,28,900,56,860,28,900,28,860,28,900,56,860,56,910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56,920,28,900,28,920,28,900,28,860,28,900,28,860,28,900,56,920,28,900,28,860,28,900,56,860,28,900,28,860,28,900,56,860,56,910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56,910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56,920,28,900,28,920,28,900,28,860,28,900,28,860,28,900,56,920,28,900,28,860,28,900,56,860,28,900,28,860,28,900,56,860,56,910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56,910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56,910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56,910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56,910,28,890,28,910,28,890,28,850,28,890,28,850,28,890,28,900,28,910,28,890,28,850,28,900,56,850,28,890,28,850,28,900,56,850,56]\nconst HANGANG_OTHER: Record<number, string> = { 208:\"2d9\", 216:\"207d-207e\", 226:\"2bc 201b\", 246:\"131\", 264:\"69 6c\", 267:\"49\", 270:\"2032\", 274:\"2da\", 278:\"6a\", 280:\"399\", 281:\"b0 3002\", 282:\"2051\", 286:\"3b9\", 291:\"3016-3017\", 295:\"b7\", 299:\"2d0\", 306:\"2c 2e 60 2018-2019\", 309:\"b4\", 310:\"b8 2db 3001\", 326:\"21 27 3a-3b\", 330:\"2035-2036\", 336:\"28-29\", 339:\"7c\", 340:\"3018-3019\", 348:\"74 300c-300d\", 357:\"2a 5b 5d\", 358:\"167 300e-300f 3014-3015\", 370:\"3010-3011\", 371:\"66\", 387:\"b2-b3 b9 2074 207f 2081-2084\", 404:\"201f\", 406:\"a7 301e-301f\", 408:\"72 3c4\", 410:\"140\", 413:\"2f 5c\", 415:\"2dd\", 418:\"22 2d 82 ad\", 427:\"73\", 431:\"2d8\", 435:\"2033\", 439:\"2c7\", 444:\"2202\", 448:\"442\", 451:\"4a 300b\", 455:\"300a\", 459:\"7a-7b 7d\", 462:\"78\", 464:\"3b5\", 470:\"433 207a-207c\", 479:\"5e 204c-204d\", 480:\"3bb\", 484:\"3008-3009\", 489:\"142 445\", 490:\"3b3\", 492:\"201c-201d\", 494:\"138 3ba 43a 443\", 498:\"79 3b6 3be 437\", 510:\"5f 133\", 512:\"3bd\", 513:\"76\", 515:\"3f\", 516:\"423\", 519:\"53\", 520:\"61\", 522:\"6b\", 524:\"44f\", 527:\"3b8\", 528:\"63\", 530:\"f0 13f 141 430\", 531:\"3b2\", 532:\"393 413\", 534:\"a8 432 44d\", 535:\"435 441 451\", 538:\"3c1\", 540:\"30-39\", 541:\"58\", 544:\"65\", 545:\"434 44c\", 546:\"431\", 550:\"24\", 553:\"3c5\", 554:\"46\", 557:\"5a\", 561:\"3a5 3a7 425\", 562:\"4c\", 563:\"3c7\", 564:\"2211\", 565:\"71\", 566:\"166 3a4 3c3 422\", 568:\"3b4\", 570:\"3c6\", 571:\"64 440\", 572:\"45\", 573:\"14b\", 575:\"3a3\", 576:\"39a\", 578:\"6f\", 579:\"59 42f\", 580:\"2203\", 581:\"f8 fe 396 3a1 3bf 420 43e\", 582:\"70\", 583:\"111 3c0\", 584:\"3b1\", 585:\"3b7\", 586:\"2b 3c-3e 438-439 43d\", 587:\"43b\", 588:\"3bc 43f\", 591:\"62 395 401 415\", 592:\"4b 67\", 593:\"2025\", 594:\"df\", 595:\"212b 2200\", 596:\"7e 447\", 598:\"de\", 599:\"68\", 602:\"6e 417\", 603:\"75\", 606:\"52 391 394 39b 410 41a\", 607:\"50\", 608:\"41 54\", 609:\"42c\", 618:\"127\", 621:\"56 411\", 627:\"392 412\", 630:\"42\", 634:\"39e\", 637:\"23\", 638:\"446\", 642:\"44a\", 647:\"421 42d\", 653:\"3a8 3c8\", 657:\"14a\", 661:\"436\", 665:\"43\", 670:\"44 43c\", 673:\"39d\", 674:\"4e\", 675:\"48\", 676:\"3a9\", 679:\"427\", 680:\"418-419 220f\", 686:\"55\", 687:\"424\", 688:\"b1 d7 f7\", 689:\"47\", 693:\"397 3a0 41d 41f\", 697:\"77\", 699:\"aa ba 398\", 711:\"41b\", 736:\"3a6\", 737:\"44e\", 738:\"d0\", 739:\"132\", 743:\"4f 51 44b\", 745:\"426\", 749:\"42a\", 753:\"414\", 754:\"39f 41e\", 759:\"a4 126\", 775:\"149\", 777:\"d8\", 786:\"3c9\", 800:\"2103\", 810:\"448\", 816:\"e6\", 817:\"444\", 835:\"153\", 838:\"3251-325a\", 839:\"3012 301c 3231 3239 33cb\", 840:\"416 2109\", 846:\"6d 39c 41c\", 849:\"57\", 851:\"26 42b\", 853:\"4d\", 862:\"449\", 864:\"428\", 877:\"25\", 890:\"85 2026\", 900:\"81 203e\", 916:\"429\", 924:\"42e\", 925:\"c6\", 940:\"83-84 a1-a3 a5 ab-ac ae b6 bb-bf 2dc 3d5 2013-2016 2020-2022 2034 2039-203c 2042 2047 2049 204e 20ac 2113 2116 2121-2122 2126 2153-2154 215b-215e 2160-2169 2170-2179 2190-2199 219c-219d 21b0-21b4 21b6-21b7 21bc 21c0 21c4-21c5 21cd 21cf-21d4 21e0-21e3 21e6-21e9 21f0 2206-2209 220b-220c 2213 221a 221d-2220 2222 2225-222c 222e 2234-2235 2237 223c-223d 2243 2245 2248 2250-2253 225a 2260-2262 2264-2267 226a-226b 226e-2273 2276-2277 2279-227b 2280-2287 228a-228b 2295-2297 2299 22a3-22a5 22bb-22bc 22ce-22cf 22da-22db 22ee 2306 2312 2314 2460-2487 249c-24e9 24eb-24f4 2500-2503 250c-254b 2588 2592 25a0-25a9 25ad 25b1-25b3 25b5-25b7 25b9 25bc-25bd 25bf-25c1 25c3 25c6-25d1 25e6 25ef 25fb-25fc 2605-2606 260e-2610 261c-261f 262f 2640 2642 2660-2661 2663-266a 266c-266d 266f 2716 271a 2720 2723 2731 273d 273f-2741 2747 274d 2756 2776-277f 278a-2794 279b-279c 279e 27a1 27a4 27b2 27b5 2934-2937 2939 2962-2965 2981 2985-2986 2997-2998 29a3 29be-29bf 29c8 2a26 2a38 2a72 2a8b-2a8c 2a91-2a92 2ac5-2ac6 2acb-2acc 2ae8 3000 3003 3013 3020 3036 3041-3093 30a1-30f6 3131-318e 3200-321c 3260-3264 3266-327b 327e-327f 328a-3290 3294 329e 32a5 3380-3384 3388-33ca 33cf-33d0 33d3 33d6 33d8 33db-33dd ff01-ff5e ffe0-ffe3 ffe5-ffe6\", 950:\"20a9\", 984:\"2030\", 987:\"152\", 1000:\"3265\", 1020:\"40\" }\n\n/** 표를 글자 코드 → 폭(em×1000) 사전으로 푼다 */\nfunction expand(hangul: number[], other: Record<number, string>): Map<number, number> {\n const m = new Map<number, number>()\n let cp = 0xac00\n for (let i = 0; i < hangul.length; i += 2) { for (let k = 0; k < hangul[i + 1]; k++, cp++) if (hangul[i]) m.set(cp, hangul[i]) }\n for (const [w, list] of Object.entries(other)) for (const r of list.split(\" \")) {\n const [a, b] = r.split(\"-\").map(x => parseInt(x, 16))\n for (let c = a; c <= (b ?? a); c++) m.set(c, Number(w))\n }\n return m\n}\n\n/** 글꼴 이름 → 폭 사전(굵기·08 접두 이름 모두). 세로쓰기 글꼴은 고정폭이라 뺀다 */\nexport function seoulFontWidths(): Record<string, Map<number, number>> {\n const namsan = expand(NAMSAN_HANGUL, NAMSAN_OTHER), hangang = expand(HANGANG_HANGUL, HANGANG_OTHER)\n const out: Record<string, Map<number, number>> = {}\n for (const w of [\"L\", \"M\", \"B\", \"EB\"]) for (const pre of [\"08\", \"\"]) { out[`${pre}서울남산체 ${w}`] = namsan; out[`${pre}서울한강체 ${w}`] = hangang }\n return out\n}\n","/**\n * 생성용 실글꼴 advance 폭표 (em×1000) — 공문서 v5 엔진이 쓰는 글꼴의 hmtx 실측값.\n *\n * 한컴오피스 번들 TTF(한컴돋움·HY견고딕·휴먼명조·HY헤드라인M·굴림체·굴림·맑은 고딕·함초롬돋움)에서\n * 폭 계산에 필요한 수치만 뽑았다: ASCII 95자 + 전각(cjk)과 다른 기호 예외. 한글 음절·자모·\n * 원문자·도형 등 나머지는 전부 cjk 폭(글꼴 안에서 균일 — 전수 확인)이다. 글꼴에 없는 글리프는\n * 한컴이 대체 글꼴로 그리므로 cjk 폭으로 둔다(HY견고딕은 KS X 1001 2,350자만 있다).\n *\n * 검증: 이 표 + 공백 0.5em(useFontSpace=0) + ASCII 연속열 한 단어 + 금칙 규칙으로 한글 2024(윈도)가\n * 조판한 v5 보고서 PDF 본문 154줄의 줄바꿈 위치를 전부 재현했다. bold 는 폭이 같다(실결재 대조).\n * 공백(0x20) 칸은 한컴 고정 반각(500)이다 — measureTextWidth 가 spaceEm 으로 따로 처리한다.\n *\n * 휴먼명조·맑은 고딕·KoPub 바탕·돋움 표의 글자 몇십 개(‘’·가운뎃점·숫자·문장부호 등)는 hmtx 대신 한컴 저장 lineseg 에서\n * 줄 나눔에 맞춘 폭이다 — 한컴이 그 글자를 hmtx 와 다른 폭으로 조판한다(두 줄 이상 문단 반쪽 검증 +17·+30·+23·+16,\n * reflow 전 경로 87.5% → 88.7%). FIT_* 표는 hmtx 가 없는 글꼴을 같은 방법으로 통째로 맞춘 것이다.\n *\n * PDF_* 표는 코퍼스의 한컴 PDF(HWPX 짝)에 임베드된 글꼴의 /W 글리프 폭을 ToUnicode 로 모은 실측이다. 글꼴마다 reflow 전 경로로\n * 맞춤 표와 비교해 나은 쪽만 쓴다 — 바탕은 실측 hmtx 보다 맞춤 표가 한컴 줄바꿈에 맞아(본문 −112문단) 맞춤 표를 남겼다.\n */\n\nimport { HFT_LATIN } from \"./hft-latin-widths.js\"\nimport { FACE_CJK, FACE_SPACE, FACE_WIDTH_FIX } from \"./face-width-fix.js\"\nimport { seoulFontWidths } from \"./seoul-font-widths.js\"\n\ninterface FontMetrics {\n /** 한글 음절(가) 폭 = 표에 없는 비ASCII 기본값 */\n cjk: number\n /** 0x20~0x7E advance */\n ascii: number[]\n /** cjk 폭과 다른 비ASCII 기호 */\n ex: Record<number, number>\n /** 한자(CJK 통합 한자) 폭 — 표에 없으면 cjk. 한글과 한자 폭이 다른 글꼴(함초롬돋움 한글 970·한자 1000, KoPub돋움 872·900) */\n han?: number\n}\n\n/** KoPub 서체(한국출판인회의 무료 배포 TTF·OTF) hmtx 실측 — 굵기(Light·Medium·Bold)끼리 폭이 같아 가족마다 한 표.\n * 한글 음절 폭이 바탕 0.936em·돋움 0.872em 으로 1em 이 아니라 근사 폭으로 재면 줄바꿈이 크게 어긋난다\n * (법령·보도자료 코퍼스 두 줄 이상 문단 1,050개: 한컴 저장 lineseg 대조) */\nconst KOPUB_BATANG: FontMetrics = {\n cjk: 936,\n ascii: [312,312,312,573,573,745,789,312,312,312,419,648,312,503,312,468,573,573,573,573,573,573,580,550,540,573,260,312,484,556,484,468,834,668,640,708,770,590,554,768,770,352,358,746,552,874,778,812,\n 450,816,672,532,652,740,686,954,708,706,638,312,468,312,477,540,312,558,606,536,592,548,360,548,624,324,282,564,288,900,612,612,632,596,416,432,350,604,506,772,588,516,476,312,468,312,648],\n ex: {\n 0xa1:312, 0xa2:536, 0xa3:555, 0xa4:900, 0xa5:706, 0xa7:450, 0xa8:900, 0xa9:900, 0xaa:900, 0xab:440, 0xad:900, 0xae:900,\n 0xb0:450, 0xb1:900, 0xb2:280, 0xb3:280, 0xb4:900, 0xb6:900, 0xb7:440, 0xb8:450, 0xb9:280, 0xba:280, 0xbb:440, 0xbc:900,\n 0xbd:900, 0xbe:900, 0xbf:468, 0xc6:900, 0xd0:900, 0xd7:900, 0xd8:900, 0xde:900, 0xdf:620, 0xe6:900, 0xf0:900, 0xf7:900,\n 0xf8:900, 0xfe:900, 0x2002:500, 0x2003:1000, 0x2004:333, 0x2005:250, 0x2006:167, 0x2007:556, 0x2009:278, 0x200a:83, 0x2012:625, 0x2013:495,\n 0x2014:1000, 0x2015:900, 0x2016:335, 0x2018:312, 0x2019:312, 0x201c:404, 0x201d:404, 0x2020:900, 0x2021:900, 0x2022:400, 0x2023:400, 0x2025:900,\n 0x2026:900, 0x2027:900, 0x2030:900, 0x2032:450, 0x2033:450, 0x203b:900, 0x2044:167, 0x2070:280, 0x2074:280, 0x2075:280, 0x2076:280, 0x2077:280,\n 0x2078:280, 0x2079:280, 0x207f:346, 0x2080:280, 0x2081:280, 0x2082:280, 0x2083:280, 0x2084:280, 0x2085:280, 0x2086:280, 0x2087:280, 0x2088:280,\n 0x2089:280, 0x20a9:894, 0x20ac:900, 0x2103:900, 0x2109:900, 0x2113:900, 0x2116:900, 0x2121:900, 0x2122:900, 0x2126:900, 0x212b:900, 0x2153:900,\n 0x2154:900, 0x2155:900, 0x2156:900, 0x2157:900, 0x2158:900, 0x2159:900, 0x215a:900, 0x215b:900, 0x215c:900, 0x215d:900, 0x215e:900, 0x215f:900,\n 0x2160:900, 0x2161:900, 0x2162:900, 0x2163:900, 0x2164:900, 0x2165:900, 0x2166:900, 0x2167:900, 0x2168:900, 0x2169:900, 0x2170:900, 0x2171:900,\n 0x2172:900, 0x2173:900, 0x2174:900, 0x2175:900, 0x2176:900, 0x2177:900, 0x2178:900, 0x2179:900, 0x2190:900, 0x2191:900, 0x2192:900, 0x2193:900,\n 0x2194:900, 0x2195:900, 0x2196:900, 0x2197:900, 0x2198:900, 0x2199:900, 0x21d2:900, 0x21d4:900, 0x2200:900, 0x2202:450, 0x2203:900, 0x2207:900,\n 0x2208:900, 0x220b:900, 0x220f:900, 0x2211:900, 0x2212:570, 0x221a:900, 0x221d:900, 0x221e:900, 0x2220:900, 0x2225:900, 0x2227:900, 0x2228:900,\n 0x2229:900, 0x222a:900, 0x222b:900, 0x222c:900, 0x222e:900, 0x2234:900, 0x2235:900, 0x223c:900, 0x223d:900, 0x2252:900, 0x2260:900, 0x2261:900,\n 0x2264:900, 0x2265:900, 0x226a:900, 0x226b:900, 0x2282:900, 0x2283:900, 0x2286:900, 0x2287:900, 0x2299:900, 0x22a5:900, 0x22ef:900, 0x2312:900,\n 0x2460:910, 0x2461:900, 0x2462:900, 0x2463:900, 0x2464:900, 0x2465:900, 0x2466:900, 0x2467:900, 0x2468:900, 0x2469:900, 0x246a:900, 0x246b:900,\n 0x246c:900, 0x246d:900, 0x246e:900, 0x246f:900, 0x2470:900, 0x2471:900, 0x2472:900, 0x2473:900, 0x2474:900, 0x2475:900, 0x2476:900, 0x2477:900,\n 0x2478:900, 0x2479:900, 0x247a:900, 0x247b:900, 0x247c:900, 0x247d:900, 0x247e:900, 0x247f:900, 0x2480:900, 0x2481:900, 0x2482:900, 0x2483:900,\n 0x2484:900, 0x2485:900, 0x2486:900, 0x2487:900, 0x249c:900, 0x249d:900, 0x249e:900, 0x249f:900, 0x24a0:900, 0x24a1:900, 0x24a2:900, 0x24a3:900,\n 0x24a4:900, 0x24a5:900, 0x24a6:900, 0x24a7:900, 0x24a8:900, 0x24a9:900, 0x24aa:900, 0x24ab:900, 0x24ac:900, 0x24ad:900, 0x24ae:900, 0x24af:900,\n 0x24b0:900, 0x24b1:900, 0x24b2:900, 0x24b3:900, 0x24b4:900, 0x24b5:900, 0x24b6:900, 0x24b7:900, 0x24b8:900, 0x24b9:900, 0x24ba:900, 0x24bb:900,\n 0x24bc:900, 0x24bd:900, 0x24be:900, 0x24bf:900, 0x24c0:900, 0x24c1:900, 0x24c2:900, 0x24c3:900, 0x24c4:900, 0x24c5:900, 0x24c6:900, 0x24c7:900,\n 0x24c8:900, 0x24c9:900, 0x24ca:900, 0x24cb:900, 0x24cc:900, 0x24cd:900, 0x24ce:900, 0x24cf:900, 0x24d0:900, 0x24d1:900, 0x24d2:900, 0x24d3:900,\n 0x24d4:900, 0x24d5:900, 0x24d6:900, 0x24d7:900, 0x24d8:900, 0x24d9:900, 0x24da:900, 0x24db:900, 0x24dc:900, 0x24dd:900, 0x24de:900, 0x24df:900,\n 0x24e0:900, 0x24e1:900, 0x24e2:900, 0x24e3:900, 0x24e4:900, 0x24e5:900, 0x24e6:900, 0x24e7:900, 0x24e8:900, 0x24e9:900, 0x24ea:900, 0x24eb:900,\n 0x24ec:900, 0x24ed:900, 0x24ee:900, 0x24ef:900, 0x24f0:900, 0x24f1:900, 0x24f2:900, 0x24f3:900, 0x24f4:900, 0x24ff:900, 0x2500:900, 0x2501:900,\n 0x2502:900, 0x2503:900, 0x250c:900, 0x250d:900, 0x250e:900, 0x250f:900, 0x2510:900, 0x2511:900, 0x2512:900, 0x2513:900, 0x2514:900, 0x2515:900,\n 0x2516:900, 0x2517:900, 0x2518:900, 0x2519:900, 0x251a:900, 0x251b:900, 0x251c:900, 0x251d:900, 0x251e:900, 0x251f:900, 0x2520:900, 0x2521:900,\n 0x2522:900, 0x2523:900, 0x2524:900, 0x2525:900, 0x2526:900, 0x2527:900, 0x2528:900, 0x2529:900, 0x252a:900, 0x252b:900, 0x252c:900, 0x252d:900,\n 0x252e:900, 0x252f:900, 0x2530:900, 0x2531:900, 0x2532:900, 0x2533:900, 0x2534:900, 0x2535:900, 0x2536:900, 0x2537:900, 0x2538:900, 0x2539:900,\n 0x253a:900, 0x253b:900, 0x253c:900, 0x253d:900, 0x253e:900, 0x253f:900, 0x2540:900, 0x2541:900, 0x2542:900, 0x2543:900, 0x2544:900, 0x2545:900,\n 0x2546:900, 0x2547:900, 0x2548:900, 0x2549:900, 0x254a:900, 0x254b:900, 0x2592:900, 0x25a0:900, 0x25a1:900, 0x25a3:900, 0x25a4:900, 0x25a5:900,\n 0x25a6:900, 0x25a7:900, 0x25a8:900, 0x25a9:900, 0x25b2:900, 0x25b3:900, 0x25b6:900, 0x25b7:900, 0x25bc:900, 0x25bd:900, 0x25c0:900, 0x25c1:900,\n 0x25c6:900, 0x25c7:900, 0x25c8:900, 0x25cb:900, 0x25ce:900, 0x25cf:900, 0x25d0:900, 0x25d1:900, 0x25e6:600, 0x2605:900, 0x2606:900, 0x260e:900,\n 0x260f:900, 0x261c:900, 0x261e:900, 0x2640:900, 0x2642:900, 0x2660:900, 0x2661:900, 0x2663:900, 0x2664:900, 0x2665:900, 0x2667:900, 0x2668:900,\n 0x2669:900, 0x266a:900, 0x266c:900, 0x266d:900, 0x274c:900, 0x2776:900, 0x2777:900, 0x2778:900, 0x2779:900, 0x277a:900, 0x277b:900, 0x277c:900,\n 0x277d:900, 0x277e:900, 0x277f:900, 0x2780:900, 0x2781:900, 0x2782:900, 0x2783:900, 0x2784:900, 0x2785:900, 0x2786:900, 0x2787:900, 0x2788:900,\n 0x2789:900, 0x278a:900, 0x278b:900, 0x278c:900, 0x278d:900, 0x278e:900, 0x278f:900, 0x2790:900, 0x2791:900, 0x2792:900, 0x2793:900, 0x3000:900,\n 0x3001:450, 0x3002:450, 0x3003:900, 0x3008:450, 0x3009:450, 0x300a:450, 0x300b:450, 0x300c:450, 0x300d:450, 0x300e:450, 0x300f:450, 0x3010:450,\n 0x3011:450, 0x3013:900, 0x3014:450, 0x3015:450, 0x318d:900, 0xff62:290, 0xff63:720, 0xff65:490, 0xf080f:560,\n },\n}\n\nconst KOPUB_DOTUM: FontMetrics = {\n cjk: 872,\n ascii: [290,300,320,590,590,874,706,180,310,310,500,590,300,570,240,446,563,563,563,563,563,563,563,563,563,563,316,316,425,590,425,486,882,662,664,664,713,609,555,712,718,283,500,609,555,872,718,\n 758,609,758,664,601,555,718,621,990,609,609,555,310,446,310,434,490,291,506,562,506,562,562,341,562,562,232,232,506,232,891,562,549,562,562,341,506,341,562,504,802,506,504,451,310,386,310,527],\n han: 900, // 한자 — 한컴 PDF 임베드 글꼴 /W 실측\n ex: {\n 0xa1:300, 0xa2:506, 0xa3:533, 0xa4:900, 0xa5:520, 0xa7:450, 0xa8:900, 0xa9:706, 0xaa:900, 0xab:533, 0xad:900, 0xae:900,\n 0xb0:450, 0xb1:900, 0xb2:280, 0xb3:280, 0xb4:900, 0xb6:900, 0xb7:450, 0xb8:450, 0xb9:280, 0xba:319, 0xbb:533, 0xbc:799,\n 0xbd:799, 0xbe:799, 0xbf:486, 0xc6:900, 0xd0:900, 0xd7:900, 0xd8:900, 0xde:900, 0xdf:600, 0xe6:900, 0xf0:900, 0xf7:900,\n 0xf8:900, 0xfe:900, 0x2002:500, 0x2003:1000, 0x2004:333, 0x2005:250, 0x2006:167, 0x2007:556, 0x2009:278, 0x200a:83, 0x2012:625, 0x2013:495,\n 0x2014:1000, 0x2015:900, 0x2016:335, 0x2018:290, 0x2019:290, 0x201c:410, 0x201d:410, 0x2020:900, 0x2021:900, 0x2022:400, 0x2023:400, 0x2025:900,\n 0x2026:900, 0x2027:300, 0x2030:900, 0x2032:450, 0x2033:450, 0x203b:900, 0x2044:167, 0x2070:280, 0x2074:280, 0x2075:280, 0x2076:280, 0x2077:280,\n 0x2078:280, 0x2079:280, 0x207f:280, 0x2080:280, 0x2081:280, 0x2082:280, 0x2083:280, 0x2084:280, 0x2085:280, 0x2086:280, 0x2087:280, 0x2088:280,\n 0x2089:280, 0x20a9:894, 0x20ac:900, 0x2103:900, 0x2109:900, 0x2113:900, 0x2116:900, 0x2121:900, 0x2122:900, 0x2126:900, 0x212b:900, 0x2153:799,\n 0x2154:799, 0x2155:799, 0x2156:799, 0x2157:799, 0x2158:799, 0x2159:799, 0x215a:799, 0x215b:799, 0x215c:799, 0x215d:799, 0x215e:799, 0x215f:799,\n 0x2160:900, 0x2161:900, 0x2162:900, 0x2163:900, 0x2164:900, 0x2165:900, 0x2166:900, 0x2167:900, 0x2168:900, 0x2169:900, 0x2170:900, 0x2171:900,\n 0x2172:900, 0x2173:900, 0x2174:900, 0x2175:900, 0x2176:900, 0x2177:900, 0x2178:900, 0x2179:900, 0x2190:900, 0x2191:900, 0x2192:900, 0x2193:900,\n 0x2194:900, 0x2195:900, 0x2196:900, 0x2197:900, 0x2198:900, 0x2199:900, 0x21d2:900, 0x21d4:900, 0x2200:900, 0x2202:450, 0x2203:900, 0x2207:900,\n 0x2208:900, 0x220b:900, 0x220f:900, 0x2211:900, 0x2212:570, 0x2219:460, 0x221a:900, 0x221d:900, 0x221e:900, 0x2220:900, 0x2225:900, 0x2227:900,\n 0x2228:900, 0x2229:900, 0x222a:900, 0x222b:900, 0x222c:900, 0x222e:900, 0x2234:900, 0x2235:900, 0x223c:900, 0x223d:900, 0x2252:900, 0x2260:900,\n 0x2261:900, 0x2264:900, 0x2265:900, 0x226a:900, 0x226b:900, 0x2282:900, 0x2283:900, 0x2286:900, 0x2287:900, 0x2299:900, 0x22a5:900, 0x22ef:900,\n 0x2312:900, 0x2460:900, 0x2461:900, 0x2462:900, 0x2463:900, 0x2464:900, 0x2465:900, 0x2466:900, 0x2467:900, 0x2468:900, 0x2469:900, 0x246a:900,\n 0x246b:900, 0x246c:900, 0x246d:900, 0x246e:900, 0x246f:900, 0x2470:900, 0x2471:900, 0x2472:900, 0x2473:900, 0x2474:900, 0x2475:900, 0x2476:900,\n 0x2477:900, 0x2478:900, 0x2479:900, 0x247a:900, 0x247b:900, 0x247c:900, 0x247d:900, 0x247e:900, 0x247f:900, 0x2480:900, 0x2481:900, 0x2482:900,\n 0x2483:900, 0x2484:900, 0x2485:900, 0x2486:900, 0x2487:900, 0x249c:900, 0x249d:900, 0x249e:900, 0x249f:900, 0x24a0:900, 0x24a1:900, 0x24a2:900,\n 0x24a3:900, 0x24a4:900, 0x24a5:900, 0x24a6:900, 0x24a7:900, 0x24a8:900, 0x24a9:900, 0x24aa:900, 0x24ab:900, 0x24ac:900, 0x24ad:900, 0x24ae:900,\n 0x24af:900, 0x24b0:900, 0x24b1:900, 0x24b2:900, 0x24b3:900, 0x24b4:900, 0x24b5:900, 0x24b6:900, 0x24b7:900, 0x24b8:900, 0x24b9:900, 0x24ba:900,\n 0x24bb:900, 0x24bc:900, 0x24bd:900, 0x24be:900, 0x24bf:900, 0x24c0:900, 0x24c1:900, 0x24c2:900, 0x24c3:900, 0x24c4:900, 0x24c5:900, 0x24c6:900,\n 0x24c7:900, 0x24c8:900, 0x24c9:900, 0x24ca:900, 0x24cb:900, 0x24cc:900, 0x24cd:900, 0x24ce:900, 0x24cf:900, 0x24d0:900, 0x24d1:900, 0x24d2:900,\n 0x24d3:900, 0x24d4:900, 0x24d5:900, 0x24d6:900, 0x24d7:900, 0x24d8:900, 0x24d9:900, 0x24da:900, 0x24db:900, 0x24dc:900, 0x24dd:900, 0x24de:900,\n 0x24df:900, 0x24e0:900, 0x24e1:900, 0x24e2:900, 0x24e3:900, 0x24e4:900, 0x24e5:900, 0x24e6:900, 0x24e7:900, 0x24e8:900, 0x24e9:900, 0x24ea:900,\n 0x24eb:900, 0x24ec:900, 0x24ed:900, 0x24ee:900, 0x24ef:900, 0x24f0:900, 0x24f1:900, 0x24f2:900, 0x24f3:900, 0x24f4:900, 0x24ff:900, 0x2500:900,\n 0x2501:900, 0x2502:900, 0x2503:900, 0x250c:900, 0x250d:900, 0x250e:900, 0x250f:900, 0x2510:900, 0x2511:900, 0x2512:900, 0x2513:900, 0x2514:900,\n 0x2515:900, 0x2516:900, 0x2517:900, 0x2518:900, 0x2519:900, 0x251a:900, 0x251b:900, 0x251c:900, 0x251d:900, 0x251e:900, 0x251f:900, 0x2520:900,\n 0x2521:900, 0x2522:900, 0x2523:900, 0x2524:900, 0x2525:900, 0x2526:900, 0x2527:900, 0x2528:900, 0x2529:900, 0x252a:900, 0x252b:900, 0x252c:900,\n 0x252d:900, 0x252e:900, 0x252f:900, 0x2530:900, 0x2531:900, 0x2532:900, 0x2533:900, 0x2534:900, 0x2535:900, 0x2536:900, 0x2537:900, 0x2538:900,\n 0x2539:900, 0x253a:900, 0x253b:900, 0x253c:900, 0x253d:900, 0x253e:900, 0x253f:900, 0x2540:900, 0x2541:900, 0x2542:900, 0x2543:900, 0x2544:900,\n 0x2545:900, 0x2546:900, 0x2547:900, 0x2548:900, 0x2549:900, 0x254a:900, 0x254b:900, 0x2592:900, 0x25a0:900, 0x25a1:900, 0x25a3:900, 0x25a4:900,\n 0x25a5:900, 0x25a6:900, 0x25a7:900, 0x25a8:900, 0x25a9:900, 0x25b2:900, 0x25b3:900, 0x25b6:900, 0x25b7:900, 0x25bc:900, 0x25bd:900, 0x25c0:900,\n 0x25c1:900, 0x25c6:900, 0x25c7:900, 0x25c8:900, 0x25cb:900, 0x25ce:900, 0x25cf:900, 0x25d0:900, 0x25d1:900, 0x25e6:600, 0x2605:900, 0x2606:900,\n 0x260e:900, 0x260f:900, 0x261c:900, 0x261e:900, 0x2640:900, 0x2642:900, 0x2660:900, 0x2661:900, 0x2663:900, 0x2664:900, 0x2665:900, 0x2667:900,\n 0x2668:900, 0x2669:900, 0x266a:900, 0x266c:900, 0x266d:900, 0x274c:900, 0x2776:900, 0x2777:900, 0x2778:900, 0x2779:900, 0x277a:900, 0x277b:900,\n 0x277c:900, 0x277d:900, 0x277e:900, 0x277f:900, 0x2780:900, 0x2781:900, 0x2782:900, 0x2783:900, 0x2784:900, 0x2785:900, 0x2786:900, 0x2787:900,\n 0x2788:900, 0x2789:900, 0x278a:900, 0x278b:900, 0x278c:900, 0x278d:900, 0x278e:900, 0x278f:900, 0x2790:900, 0x2791:900, 0x2792:900, 0x2793:900,\n 0x3000:900, 0x3001:450, 0x3002:450, 0x3003:900, 0x3008:450, 0x3009:450, 0x300a:450, 0x300b:450, 0x300c:450, 0x300d:470, 0x300e:450, 0x300f:450,\n 0x3010:450, 0x3011:450, 0x3013:900, 0x3014:450, 0x3015:450, 0xff62:290, 0xff63:750, 0xff65:520, 0xf02fc:680,\n },\n}\n\nconst KOPUB_WORLD_BATANG: FontMetrics = {\n cjk: 936,\n ascii: [312,312,312,573,573,745,789,312,312,312,419,648,312,503,312,468,573,573,573,573,573,573,573,573,573,573,312,312,484,556,484,468,834,668,640,708,770,590,554,768,770,352,358,746,552,874,778,\n 812,612,816,672,532,652,740,686,954,708,706,638,312,468,312,477,540,312,558,606,536,592,548,360,548,624,324,282,564,288,900,612,612,632,596,416,432,350,604,506,772,588,516,476,312,468,312,648],\n ex: {\n 0xa0:290, 0xa1:312, 0xa2:536, 0xa3:555, 0xa4:533, 0xa5:706, 0xa6:468, 0xa7:450, 0xa8:900, 0xa9:900, 0xaa:328, 0xab:440,\n 0xac:625, 0xad:433, 0xae:900, 0xaf:529, 0xb0:437, 0xb1:900, 0xb2:280, 0xb3:280, 0xb4:312, 0xb5:604, 0xb6:416, 0xb7:312,\n 0xb8:833, 0xb9:280, 0xba:280, 0xbb:440, 0xbc:900, 0xbd:900, 0xbe:900, 0xbf:468, 0xc0:668, 0xc1:668, 0xc2:668, 0xc3:668,\n 0xc4:668, 0xc5:668, 0xc6:967, 0xc7:708, 0xc8:590, 0xc9:590, 0xca:590, 0xcb:590, 0xcc:352, 0xcd:352, 0xce:352, 0xcf:352,\n 0xd0:770, 0xd1:778, 0xd2:812, 0xd3:812, 0xd4:812, 0xd5:812, 0xd6:812, 0xd7:900, 0xd8:812, 0xd9:740, 0xda:740, 0xdb:740,\n 0xdc:740, 0xdd:706, 0xde:612, 0xdf:601, 0xe0:558, 0xe1:558, 0xe2:558, 0xe3:558, 0xe4:558, 0xe5:558, 0xe6:860, 0xe7:536,\n 0xe8:548, 0xe9:548, 0xea:548, 0xeb:548, 0xec:324, 0xed:324, 0xee:324, 0xef:324, 0xf0:573, 0xf1:612, 0xf2:612, 0xf3:612,\n 0xf4:612, 0xf5:612, 0xf6:612, 0xf7:900, 0xf8:612, 0xf9:604, 0xfa:604, 0xfb:604, 0xfc:604, 0xfd:516, 0xfe:632, 0xff:516,\n 0x2002:500, 0x2003:1000, 0x2004:333, 0x2005:250, 0x2006:167, 0x2007:556, 0x2009:278, 0x200a:83, 0x2012:625, 0x2013:495, 0x2014:1000, 0x2015:900,\n 0x2016:335, 0x2018:312, 0x2019:312, 0x201c:404, 0x201d:404, 0x2020:900, 0x2021:900, 0x2022:400, 0x2023:400, 0x2025:900, 0x2026:900, 0x2027:900,\n 0x2030:900, 0x2032:450, 0x2033:450, 0x203b:900, 0x2044:167, 0x2070:280, 0x2074:280, 0x2075:280, 0x2076:280, 0x2077:280, 0x2078:280, 0x2079:280,\n 0x207f:346, 0x2080:280, 0x2081:280, 0x2082:280, 0x2083:280, 0x2084:280, 0x2085:280, 0x2086:280, 0x2087:280, 0x2088:280, 0x2089:280, 0x20a9:894,\n 0x20aa:765, 0x20ac:900, 0x2103:900, 0x2109:900, 0x2113:900, 0x2116:900, 0x2121:900, 0x2122:900, 0x2126:900, 0x212b:900, 0x2153:900, 0x2154:900,\n 0x2155:900, 0x2156:900, 0x2157:900, 0x2158:900, 0x2159:900, 0x215a:900, 0x215b:900, 0x215c:900, 0x215d:900, 0x215e:900, 0x215f:900, 0x2160:900,\n 0x2161:900, 0x2162:900, 0x2163:900, 0x2164:900, 0x2165:900, 0x2166:900, 0x2167:900, 0x2168:900, 0x2169:900, 0x2170:900, 0x2171:900, 0x2172:900,\n 0x2173:900, 0x2174:900, 0x2175:900, 0x2176:900, 0x2177:900, 0x2178:900, 0x2179:900, 0x2190:900, 0x2191:900, 0x2192:900, 0x2193:900, 0x2194:900,\n 0x2195:900, 0x2196:900, 0x2197:900, 0x2198:900, 0x2199:900, 0x21d2:900, 0x21d4:900, 0x2200:900, 0x2202:450, 0x2203:900, 0x2207:900, 0x2208:900,\n 0x220b:900, 0x220f:900, 0x2211:900, 0x2212:570, 0x221a:900, 0x221d:900, 0x221e:900, 0x2220:900, 0x2225:900, 0x2227:900, 0x2228:900, 0x2229:900,\n 0x222a:900, 0x222b:900, 0x222c:900, 0x222e:900, 0x2234:900, 0x2235:900, 0x223c:900, 0x223d:900, 0x2252:900, 0x2260:900, 0x2261:900, 0x2264:900,\n 0x2265:900, 0x226a:900, 0x226b:900, 0x2282:900, 0x2283:900, 0x2286:900, 0x2287:900, 0x2299:900, 0x22a5:900, 0x22ef:900, 0x2312:900, 0x2460:900,\n 0x2461:900, 0x2462:900, 0x2463:900, 0x2464:900, 0x2465:900, 0x2466:900, 0x2467:900, 0x2468:900, 0x2469:900, 0x246a:900, 0x246b:900, 0x246c:900,\n 0x246d:900, 0x246e:900, 0x246f:900, 0x2470:900, 0x2471:900, 0x2472:900, 0x2473:900, 0x2474:900, 0x2475:900, 0x2476:900, 0x2477:900, 0x2478:900,\n 0x2479:900, 0x247a:900, 0x247b:900, 0x247c:900, 0x247d:900, 0x247e:900, 0x247f:900, 0x2480:900, 0x2481:900, 0x2482:900, 0x2483:900, 0x2484:900,\n 0x2485:900, 0x2486:900, 0x2487:900, 0x249c:900, 0x249d:900, 0x249e:900, 0x249f:900, 0x24a0:900, 0x24a1:900, 0x24a2:900, 0x24a3:900, 0x24a4:900,\n 0x24a5:900, 0x24a6:900, 0x24a7:900, 0x24a8:900, 0x24a9:900, 0x24aa:900, 0x24ab:900, 0x24ac:900, 0x24ad:900, 0x24ae:900, 0x24af:900, 0x24b0:900,\n 0x24b1:900, 0x24b2:900, 0x24b3:900, 0x24b4:900, 0x24b5:900, 0x24b6:900, 0x24b7:900, 0x24b8:900, 0x24b9:900, 0x24ba:900, 0x24bb:900, 0x24bc:900,\n 0x24bd:900, 0x24be:900, 0x24bf:900, 0x24c0:900, 0x24c1:900, 0x24c2:900, 0x24c3:900, 0x24c4:900, 0x24c5:900, 0x24c6:900, 0x24c7:900, 0x24c8:900,\n 0x24c9:900, 0x24ca:900, 0x24cb:900, 0x24cc:900, 0x24cd:900, 0x24ce:900, 0x24cf:900, 0x24d0:900, 0x24d1:900, 0x24d2:900, 0x24d3:900, 0x24d4:900,\n 0x24d5:900, 0x24d6:900, 0x24d7:900, 0x24d8:900, 0x24d9:900, 0x24da:900, 0x24db:900, 0x24dc:900, 0x24dd:900, 0x24de:900, 0x24df:900, 0x24e0:900,\n 0x24e1:900, 0x24e2:900, 0x24e3:900, 0x24e4:900, 0x24e5:900, 0x24e6:900, 0x24e7:900, 0x24e8:900, 0x24e9:900, 0x24ea:900, 0x24eb:900, 0x24ec:900,\n 0x24ed:900, 0x24ee:900, 0x24ef:900, 0x24f0:900, 0x24f1:900, 0x24f2:900, 0x24f3:900, 0x24f4:900, 0x24ff:900, 0x2500:900, 0x2501:900, 0x2502:900,\n 0x2503:900, 0x250c:900, 0x250d:900, 0x250e:900, 0x250f:900, 0x2510:900, 0x2511:900, 0x2512:900, 0x2513:900, 0x2514:900, 0x2515:900, 0x2516:900,\n 0x2517:900, 0x2518:900, 0x2519:900, 0x251a:900, 0x251b:900, 0x251c:900, 0x251d:900, 0x251e:900, 0x251f:900, 0x2520:900, 0x2521:900, 0x2522:900,\n 0x2523:900, 0x2524:900, 0x2525:900, 0x2526:900, 0x2527:900, 0x2528:900, 0x2529:900, 0x252a:900, 0x252b:900, 0x252c:900, 0x252d:900, 0x252e:900,\n 0x252f:900, 0x2530:900, 0x2531:900, 0x2532:900, 0x2533:900, 0x2534:900, 0x2535:900, 0x2536:900, 0x2537:900, 0x2538:900, 0x2539:900, 0x253a:900,\n 0x253b:900, 0x253c:900, 0x253d:900, 0x253e:900, 0x253f:900, 0x2540:900, 0x2541:900, 0x2542:900, 0x2543:900, 0x2544:900, 0x2545:900, 0x2546:900,\n 0x2547:900, 0x2548:900, 0x2549:900, 0x254a:900, 0x254b:900, 0x2592:900, 0x25a0:900, 0x25a1:900, 0x25a3:900, 0x25a4:900, 0x25a5:900, 0x25a6:900,\n 0x25a7:900, 0x25a8:900, 0x25a9:900, 0x25b2:900, 0x25b3:900, 0x25b6:900, 0x25b7:900, 0x25bc:900, 0x25bd:900, 0x25c0:900, 0x25c1:900, 0x25c6:900,\n 0x25c7:900, 0x25c8:900, 0x25cb:900, 0x25ce:900, 0x25cf:900, 0x25d0:900, 0x25d1:900, 0x25e6:600, 0x2605:900, 0x2606:900, 0x260e:900, 0x260f:900,\n 0x261c:900, 0x261e:900, 0x2640:900, 0x2642:900, 0x2660:900, 0x2661:900, 0x2663:900, 0x2664:900, 0x2665:900, 0x2667:900, 0x2668:900, 0x2669:900,\n 0x266a:900, 0x266c:900, 0x266d:900, 0x274c:900, 0x2776:900, 0x2777:900, 0x2778:900, 0x2779:900, 0x277a:900, 0x277b:900, 0x277c:900, 0x277d:900,\n 0x277e:900, 0x277f:900, 0x2780:900, 0x2781:900, 0x2782:900, 0x2783:900, 0x2784:900, 0x2785:900, 0x2786:900, 0x2787:900, 0x2788:900, 0x2789:900,\n 0x278a:900, 0x278b:900, 0x278c:900, 0x278d:900, 0x278e:900, 0x278f:900, 0x2790:900, 0x2791:900, 0x2792:900, 0x2793:900, 0x3000:900, 0x3001:450,\n 0x3002:450, 0x3003:900, 0x3008:450, 0x3009:450, 0x300a:450, 0x300b:450, 0x300c:450, 0x300d:450, 0x300e:450, 0x300f:450, 0x3010:450, 0x3011:450,\n 0x3013:900, 0x3014:450, 0x3015:450, 0x302e:250, 0x302f:250,\n },\n}\n\nconst KOPUB_WORLD_DOTUM: FontMetrics = {\n cjk: 872,\n ascii: [290,300,320,590,590,874,706,180,310,310,446,590,300,570,300,446,563,563,563,563,563,563,563,563,563,563,316,316,425,590,425,486,882,662,664,664,713,609,555,712,718,283,500,609,555,872,718,\n 758,609,758,664,601,555,718,621,990,609,609,555,310,446,310,434,490,291,506,562,506,562,562,341,562,562,232,232,506,232,891,562,549,562,562,341,506,341,562,504,802,506,504,451,310,386,310,527],\n han: 900, // 한자 — 한컴 PDF 임베드 글꼴 /W 실측\n ex: {\n 0xa0:290, 0xa1:300, 0xa2:506, 0xa3:533, 0xa4:533, 0xa5:520, 0xa6:257, 0xa7:533, 0xa8:320, 0xa9:706, 0xaa:506, 0xab:533,\n 0xac:559, 0xad:433, 0xae:706, 0xaf:529, 0xb0:383, 0xb1:526, 0xb2:280, 0xb3:280, 0xb4:319, 0xb5:552, 0xb6:523, 0xb7:319,\n 0xb8:833, 0xb9:280, 0xba:319, 0xbb:533, 0xbc:799, 0xbd:799, 0xbe:799, 0xbf:486, 0xc0:662, 0xc1:662, 0xc2:662, 0xc3:662,\n 0xc4:662, 0xc5:662, 0xc6:967, 0xc7:664, 0xc8:609, 0xc9:609, 0xca:609, 0xcb:609, 0xcc:283, 0xcd:283, 0xce:283, 0xcf:283,\n 0xd0:713, 0xd1:718, 0xd2:758, 0xd3:758, 0xd4:758, 0xd5:758, 0xd6:758, 0xd7:559, 0xd8:758, 0xd9:718, 0xda:718, 0xdb:718,\n 0xdc:718, 0xdd:609, 0xde:655, 0xdf:585, 0xe0:506, 0xe1:506, 0xe2:506, 0xe3:506, 0xe4:506, 0xe5:506, 0xe6:857, 0xe7:506,\n 0xe8:562, 0xe9:562, 0xea:562, 0xeb:562, 0xec:232, 0xed:232, 0xee:232, 0xef:232, 0xf0:556, 0xf1:562, 0xf2:549, 0xf3:549,\n 0xf4:549, 0xf5:549, 0xf6:549, 0xf7:526, 0xf8:549, 0xf9:562, 0xfa:562, 0xfb:562, 0xfc:562, 0xfd:504, 0xfe:562, 0xff:504,\n 0x2002:500, 0x2003:1000, 0x2004:333, 0x2005:250, 0x2006:167, 0x2007:556, 0x2009:278, 0x200a:83, 0x2012:625, 0x2013:495, 0x2014:1000, 0x2015:900,\n 0x2016:335, 0x2018:290, 0x2019:290, 0x201c:410, 0x201d:410, 0x2020:900, 0x2021:900, 0x2022:400, 0x2023:400, 0x2025:900, 0x2026:900, 0x2027:900,\n 0x2030:900, 0x2032:450, 0x2033:450, 0x203b:900, 0x2044:167, 0x2070:280, 0x2074:280, 0x2075:280, 0x2076:280, 0x2077:280, 0x2078:280, 0x2079:280,\n 0x207f:280, 0x2080:280, 0x2081:280, 0x2082:280, 0x2083:280, 0x2084:280, 0x2085:280, 0x2086:280, 0x2087:280, 0x2088:280, 0x2089:280, 0x20a9:894,\n 0x20aa:788, 0x20ac:900, 0x2103:900, 0x2109:900, 0x2113:900, 0x2116:900, 0x2121:900, 0x2122:900, 0x2126:900, 0x212b:900, 0x2153:799, 0x2154:799,\n 0x2155:799, 0x2156:799, 0x2157:799, 0x2158:799, 0x2159:799, 0x215a:799, 0x215b:799, 0x215c:799, 0x215d:799, 0x215e:799, 0x215f:799, 0x2160:900,\n 0x2161:900, 0x2162:900, 0x2163:900, 0x2164:900, 0x2165:900, 0x2166:900, 0x2167:900, 0x2168:900, 0x2169:900, 0x2170:900, 0x2171:900, 0x2172:900,\n 0x2173:900, 0x2174:900, 0x2175:900, 0x2176:900, 0x2177:900, 0x2178:900, 0x2179:900, 0x2190:900, 0x2191:900, 0x2192:900, 0x2193:900, 0x2194:900,\n 0x2195:900, 0x2196:900, 0x2197:900, 0x2198:900, 0x2199:900, 0x21d2:900, 0x21d4:900, 0x2200:900, 0x2202:450, 0x2203:900, 0x2207:900, 0x2208:900,\n 0x220b:900, 0x220f:900, 0x2211:900, 0x2212:570, 0x221a:900, 0x221d:900, 0x221e:900, 0x2220:900, 0x2225:900, 0x2227:900, 0x2228:900, 0x2229:900,\n 0x222a:900, 0x222b:900, 0x222c:900, 0x222e:900, 0x2234:900, 0x2235:900, 0x223c:900, 0x223d:900, 0x2252:900, 0x2260:900, 0x2261:900, 0x2264:900,\n 0x2265:900, 0x226a:900, 0x226b:900, 0x2282:900, 0x2283:900, 0x2286:900, 0x2287:900, 0x2299:900, 0x22a5:900, 0x22ef:900, 0x2312:900, 0x2460:900,\n 0x2461:900, 0x2462:900, 0x2463:900, 0x2464:900, 0x2465:900, 0x2466:900, 0x2467:900, 0x2468:900, 0x2469:900, 0x246a:900, 0x246b:900, 0x246c:900,\n 0x246d:900, 0x246e:900, 0x246f:900, 0x2470:900, 0x2471:900, 0x2472:900, 0x2473:900, 0x2474:900, 0x2475:900, 0x2476:900, 0x2477:900, 0x2478:900,\n 0x2479:900, 0x247a:900, 0x247b:900, 0x247c:900, 0x247d:900, 0x247e:900, 0x247f:900, 0x2480:900, 0x2481:900, 0x2482:900, 0x2483:900, 0x2484:900,\n 0x2485:900, 0x2486:900, 0x2487:900, 0x249c:900, 0x249d:900, 0x249e:900, 0x249f:900, 0x24a0:900, 0x24a1:900, 0x24a2:900, 0x24a3:900, 0x24a4:900,\n 0x24a5:900, 0x24a6:900, 0x24a7:900, 0x24a8:900, 0x24a9:900, 0x24aa:900, 0x24ab:900, 0x24ac:900, 0x24ad:900, 0x24ae:900, 0x24af:900, 0x24b0:900,\n 0x24b1:900, 0x24b2:900, 0x24b3:900, 0x24b4:900, 0x24b5:900, 0x24b6:900, 0x24b7:900, 0x24b8:900, 0x24b9:900, 0x24ba:900, 0x24bb:900, 0x24bc:900,\n 0x24bd:900, 0x24be:900, 0x24bf:900, 0x24c0:900, 0x24c1:900, 0x24c2:900, 0x24c3:900, 0x24c4:900, 0x24c5:900, 0x24c6:900, 0x24c7:900, 0x24c8:900,\n 0x24c9:900, 0x24ca:900, 0x24cb:900, 0x24cc:900, 0x24cd:900, 0x24ce:900, 0x24cf:900, 0x24d0:900, 0x24d1:900, 0x24d2:900, 0x24d3:900, 0x24d4:900,\n 0x24d5:900, 0x24d6:900, 0x24d7:900, 0x24d8:900, 0x24d9:900, 0x24da:900, 0x24db:900, 0x24dc:900, 0x24dd:900, 0x24de:900, 0x24df:900, 0x24e0:900,\n 0x24e1:900, 0x24e2:900, 0x24e3:900, 0x24e4:900, 0x24e5:900, 0x24e6:900, 0x24e7:900, 0x24e8:900, 0x24e9:900, 0x24ea:900, 0x24eb:900, 0x24ec:900,\n 0x24ed:900, 0x24ee:900, 0x24ef:900, 0x24f0:900, 0x24f1:900, 0x24f2:900, 0x24f3:900, 0x24f4:900, 0x24ff:900, 0x2500:900, 0x2501:900, 0x2502:900,\n 0x2503:900, 0x250c:900, 0x250d:900, 0x250e:900, 0x250f:900, 0x2510:900, 0x2511:900, 0x2512:900, 0x2513:900, 0x2514:900, 0x2515:900, 0x2516:900,\n 0x2517:900, 0x2518:900, 0x2519:900, 0x251a:900, 0x251b:900, 0x251c:900, 0x251d:900, 0x251e:900, 0x251f:900, 0x2520:900, 0x2521:900, 0x2522:900,\n 0x2523:900, 0x2524:900, 0x2525:900, 0x2526:900, 0x2527:900, 0x2528:900, 0x2529:900, 0x252a:900, 0x252b:900, 0x252c:900, 0x252d:900, 0x252e:900,\n 0x252f:900, 0x2530:900, 0x2531:900, 0x2532:900, 0x2533:900, 0x2534:900, 0x2535:900, 0x2536:900, 0x2537:900, 0x2538:900, 0x2539:900, 0x253a:900,\n 0x253b:900, 0x253c:900, 0x253d:900, 0x253e:900, 0x253f:900, 0x2540:900, 0x2541:900, 0x2542:900, 0x2543:900, 0x2544:900, 0x2545:900, 0x2546:900,\n 0x2547:900, 0x2548:900, 0x2549:900, 0x254a:900, 0x254b:900, 0x2592:900, 0x25a0:900, 0x25a1:900, 0x25a3:900, 0x25a4:900, 0x25a5:900, 0x25a6:900,\n 0x25a7:900, 0x25a8:900, 0x25a9:900, 0x25b2:900, 0x25b3:900, 0x25b6:900, 0x25b7:900, 0x25bc:900, 0x25bd:900, 0x25c0:900, 0x25c1:900, 0x25c6:900,\n 0x25c7:900, 0x25c8:900, 0x25cb:900, 0x25ce:900, 0x25cf:900, 0x25d0:900, 0x25d1:900, 0x25e6:600, 0x2605:900, 0x2606:900, 0x260e:900, 0x260f:900,\n 0x261c:900, 0x261e:900, 0x2640:900, 0x2642:900, 0x2660:900, 0x2661:900, 0x2663:900, 0x2664:900, 0x2665:900, 0x2667:900, 0x2668:900, 0x2669:900,\n 0x266a:900, 0x266c:900, 0x266d:900, 0x274c:900, 0x2776:900, 0x2777:900, 0x2778:900, 0x2779:900, 0x277a:900, 0x277b:900, 0x277c:900, 0x277d:900,\n 0x277e:900, 0x277f:900, 0x2780:900, 0x2781:900, 0x2782:900, 0x2783:900, 0x2784:900, 0x2785:900, 0x2786:900, 0x2787:900, 0x2788:900, 0x2789:900,\n 0x278a:900, 0x278b:900, 0x278c:900, 0x278d:900, 0x278e:900, 0x278f:900, 0x2790:900, 0x2791:900, 0x2792:900, 0x2793:900, 0x3000:900, 0x3001:450,\n 0x3002:450, 0x3003:900, 0x3008:450, 0x3009:450, 0x300a:450, 0x300b:450, 0x300c:450, 0x300d:450, 0x300e:450, 0x300f:450, 0x3010:450, 0x3011:450,\n 0x3013:900, 0x3014:450, 0x3015:450, 0x302e:250, 0x302f:250,\n },\n}\n\n/** 한컴 저장본 lineseg 맞춤 폭표 — 실측 폭표가 없는 글꼴. 한컴이 줄을 나눈 위치(두 줄 이상 문단)에 맞게 글자별 em 을 고른 값이다.\n * 문단을 둘로 나눠 한쪽으로 고르고 다른 쪽으로 검증했다(주석의 검증 정답 수). 고르지 않은 글자는 한글 음절 폭·함초롬 영문 폭 그대로 */\n/** HYSinMyeongJo-Medium — 한컴 저장 lineseg 맞춤(두 줄 이상 문단 326개, 검증 문단 정답 106→126/163).\n * 괄호·쉼표·마침표·숫자·<>·[]는 한컴 PDF 임베드 글꼴 /W 실측(괄호 500·쉼표 291·숫자 625 — 맞춤값은 280·730·180·552 로 엇갈렸다) */\nconst FIT_HYSinMyeongJo_Medium: FontMetrics = {\n cjk: 1000,\n ascii: [500,320,320,610,610,830,724,320,500,500,550,550,291,930,291,550,625,625,625,625,625,625,625,625,625,625,320,320,599,550,599,550,830,706,810,685,719,627,617,683,734,780,315,660,605,839,734,732,\n 603,705,660,627,664,731,706,910,705,705,626,500,550,500,550,550,320,569,597,552,597,536,356,562,635,287,288,582,287,907,635,588,597,579,478,496,356,635,563,720,542,543,486,320,320,320,550],\n ex: {\n 0xb0:291,\n },\n}\n\n\n/** 바탕 — 한컴 PDF 임베드 글꼴 /W 실측에서 출발해 한컴 저장 lineseg 에 맞춤(두 줄 이상 문단 반쪽 검증 1,818/1,875 — 맞춤만으로는 1,749) */\nconst PDFFIT_바탕: FontMetrics = {\n cjk: 1000,\n ascii: [333,312,416,623,610,855,833,250,376,376,500,833,291,625,291,375,595,595,595,595,595,595,595,595,595,595,333,333,625,625,625,500,1000,736,708,708,734,671,644,740,765,326,425,746,638,894,775,\n 736,654,738,671,625,750,775,750,945,687,685,625,500,550,500,550,500,583,541,576,541,576,576,365,583,574,289,291,572,291,845,570,583,574,574,439,519,359,566,572,808,605,587,500,320,320,320,750],\n ex: {\n 0xa0:500, 0xad:375, 0xb0:437, 0xb1:812, 0xb7:333, 0xd7:812, 0xe7:519, 0xe9:541, 0x2da:312, 0x387:313, 0x3b1:543, 0x3b2:654,\n 0x3b8:708, 0x3bc:541, 0x3c1:522, 0x200b:240, 0x2013:500, 0x2018:291, 0x2019:291, 0x201a:291, 0x201c:500, 0x201d:500, 0x2022:375, 0x2024:200,\n 0x2027:170, 0x2032:264, 0x2033:391, 0x2113:418, 0x2191:750, 0x2193:750, 0x2206:613, 0x221a:548, 0x2261:812, 0x25a0:889, 0x25a1:889, 0x25aa:375,\n 0x25b2:914, 0x25ba:750, 0x25bc:914, 0x25ca:774, 0x25e6:375, 0x3007:500, 0xff62:320, 0xff63:690, 0xff65:500,\n },\n}\n\n/** 필기 — 한컴 저장 lineseg 맞춤(두 줄 이상 문단 59개, 검증 문단 정답 21→27/29) */\nconst FIT_필기: FontMetrics = {\n cjk: 1000,\n ascii: [500,320,320,610,610,830,724,320,320,320,550,550,490,550,320,550,550,550,550,550,550,550,550,550,550,550,320,320,550,550,550,550,830,706,605,685,719,627,617,683,734,305,315,660,605,839,734,732,\n 603,705,660,627,664,731,706,910,705,705,626,320,550,320,550,550,320,569,597,552,597,536,356,562,635,287,288,582,287,907,635,588,597,579,478,496,356,635,563,720,542,543,486,320,320,320,550],\n ex: {\n 0x2018:150,\n },\n}\n\n/** 한양신명조 — 영문은 한컴 PDF 임베드 Type3 글꼴 실측(HCI Poppy 와 같은 영문 글리프), 한글 1000. 기호(ex)는 한컴 저장 lineseg 맞춤.\n * 하이픈은 0.541em(신구조문 대비표 \"-----\" 줄 PDF 진행 폭 207개 중앙값). 괄호는 한컴 PDF Type3 글자 진행 폭 중앙값 ( 393·) 376.\n * 영문 대소문자(Q·Z·j·q·z 제외)도 한컴 PDF Type3 진행 폭 중앙값 — HCI Poppy 폭보다 넓다(T 612 → 783, S 524 → 651)\n * 영문 칸(0x21~0x7E)은 아래에서 HFT 영문 폭표로 덮인다 — 하이픈 0.572em, T 774\n * (한컴 저장 lineseg 대조: 두 줄 이상 문단 줄 시작 24,100 → 24,134, 한양신명조 칸 문단 1,169 → 1,194/1,269) */\nconst FIT_한양신명조: FontMetrics = {\n cjk: 1000,\n ascii: [500,277,369,610,610,839,777,277,393,376,388,605,248,541,248,605,498,498,498,498,498,498,498,498,498,498,248,320,605,550,605,443,746,795,700,690,750,675,652,747,783,337,458,790,650,964,783,747,\n 627,705,707,651,783,771,783,1036,752,771,626,332,550,332,550,550,277,506,554,482,542,482,349,590,560,277,288,554,277,860,566,518,542,579,410,492,349,566,578,843,591,578,498,320,320,320,605],\n ex: {\n 0xb1:798, 0xb7:320, 0x1112:1000, 0x119e:1000, 0x11ab:1000, 0x2018:277, 0x2019:277, 0x201c:498, 0x201d:498, 0x2024:1000, 0x2103:1000, 0x2460:1000,\n 0x2461:1000, 0x2462:1000, 0x25cb:930, 0x274d:1000, 0x300c:1100, 0x300d:1020, 0x318d:1000, 0xff62:280, 0xff63:1000,\n },\n}\n\n/** KBL 점프체 R·B — 글꼴 advance 폭(영문·숫자). 한글은 대부분 1em(1만 1172자 중 8392자) */\nconst TTF_KBL_JUMP_R: FontMetrics = { cjk: 1000, ascii: [200,230,323,989,586,949,796,199,392,392,574,620,251,600,245,557,680,430,648,665,680,648,668,634,670,668,340,338,448,680,448,613,1000,706,705,640,698,698,653,690,700,210,440,714,585,916,690,700,654,735,660,679,622,701,736,1124,736,700,657,392,557,392,633,600,257,645,674,614,674,645,453,634,674,180,305,648,275,972,666,676,676,676,525,648,580,660,646,924,668,634,617,482,260,482,770], ex: {} }\nconst TTF_KBL_JUMP_B: FontMetrics = { cjk: 1000, ascii: [200,260,365,989,586,949,796,209,412,412,585,601,281,600,275,587,700,450,668,685,700,668,688,664,690,688,370,370,478,700,478,623,1000,795,725,660,718,718,673,710,720,220,460,734,605,936,710,720,674,755,680,699,642,711,756,1144,756,720,677,412,587,412,633,600,287,665,684,634,671,670,453,649,694,220,315,698,305,992,686,696,696,696,545,668,600,690,666,944,688,654,627,502,280,502,770], ex: {} }\n\n/** Batang — 한컴 저장 lineseg 맞춤(두 줄 이상 문단 76개, 검증 문단 정답 22→29/38) */\nconst FIT_Batang: FontMetrics = {\n cjk: 1000,\n ascii: [500,320,320,610,610,830,724,320,320,320,550,550,320,550,320,380,550,870,550,550,550,550,550,550,550,550,320,320,550,550,550,550,830,706,605,685,719,627,617,683,734,305,315,660,605,839,734,732,\n 603,705,660,627,710,731,706,910,705,705,626,320,550,320,550,550,320,569,597,552,597,370,356,562,635,287,288,582,287,907,600,588,597,579,478,290,356,635,840,720,542,543,486,320,320,320,550],\n ex: {\n },\n}\n\n/** 서울한강체 — 한컴 PDF 임베드 Type0 글꼴 /W 실측(SeoulHangangM, 글자 459개). 한글은 글자마다 850~920, 없는 글자는 중앙값 900. 빈 ASCII 는 비슷한 폭 추정 */\nconst PDF_서울한강체: FontMetrics = {\n cjk: 900,\n ascii: [336,400,400,400,400,400,400,400,336,336,357,400,306,418,306,413,540,540,540,540,540,540,540,540,540,540,326,400,400,400,400,515,400,608,630,665,670,572,554,600,600,267,600,592,600,853,674,743,607,600,606,519,600,600,621,849,600,600,600,357,400,357,400,400,400,520,540,528,571,544,371,592,599,264,540,522,264,846,602,578,582,540,408,427,348,603,513,540,540,540,540,400,400,400,596],\n ex: {\n 0xb7:295, 0x2018:306, 0x2019:306, 0x201c:492, 0x201d:492, 0x2022:940, 0x203b:940, 0x2192:940, 0x2460:940, 0x2461:940, 0x2462:940, 0x2463:940, 0x2464:940, 0x261e:940, 0x3009:484, 0x300c:348,\n 0x300d:348, 0xac00:910, 0xac01:910, 0xac04:910, 0xac10:910, 0xac16:910, 0xac19:910, 0xac1c:890, 0xac70:850, 0xac74:850, 0xac80:850, 0xac83:850, 0xac8c:890, 0xaca0:890, 0xaca9:850, 0xacac:850,\n 0xacb0:850, 0xacbd:850, 0xacc4:890, 0xace0:900, 0xacf5:900, 0xacfc:910, 0xad00:910, 0xad50:900, 0xad6c:900, 0xad6d:900, 0xad70:900, 0xad8c:850, 0xaddc:900, 0xadf8:900, 0xadfc:900, 0xae08:900,\n 0xae09:900, 0xae30:850, 0xae38:850, 0xae4a:850, 0xae4c:920, 0xae68:900, 0xaed8:900, 0xb098:910, 0xb09c:910, 0xb0a8:910, 0xb0b4:890, 0xb10c:850, 0xb124:890, 0xb137:890, 0xb144:850, 0xb179:900,\n 0xb192:900, 0xb204:900, 0xb220:850, 0xb258:850, 0xb274:900, 0xb290:900, 0xb294:900, 0xb2a5:900, 0xb2c8:850, 0xb2cc:850, 0xb2d8:850, 0xb2e4:910, 0xb2e8:910, 0xb2ec:910, 0xb2f4:910, 0xb2f9:910,\n 0xb300:890, 0xb354:850, 0xb370:890, 0xb3c4:900, 0xb3c5:900, 0xb3d9:900, 0xb418:850, 0xb41c:850, 0xb420:850, 0xb428:850, 0xb450:900, 0xb4a4:850, 0xb4dc:900, 0xb4dd:900, 0xb4e0:900, 0xb4e4:900,\n 0xb4ec:900, 0xb4f1:900, 0xb514:850, 0xb530:920, 0xb54c:900, 0xb5a4:860, 0xb5bb:860, 0xb610:900, 0xb73b:900, 0xb77c:910, 0xb77d:910, 0xb780:910, 0xb78c:910, 0xb798:890, 0xb7b5:910, 0xb7c9:910,\n 0xb7ec:850, 0xb7f0:850, 0xb824:850, 0xb825:850, 0xb828:850, 0xb839:850, 0xb840:890, 0xb85c:900, 0xb85d:900, 0xb8b0:850, 0xb8cc:900, 0xb8e8:900, 0xb958:900, 0xb960:900, 0xb974:900, 0xb978:900,\n 0xb97c:900, 0xb9ac:850, 0xb9ad:850, 0xb9bc:850, 0xb9bd:850, 0xb9bf:850, 0xb9c8:910, 0xb9c9:910, 0xb9cc:910, 0xb9d0:910, 0xb9dd:910, 0xb9de:910, 0xb9e4:890, 0xb9f7:890, 0xba54:890, 0xba70:850,\n 0xba74:850, 0xba85:850, 0xbaa8:900, 0xbaa9:900, 0xbb34:900, 0xbb38:900, 0xbb3c:900, 0xbbc0:900, 0xbbf8:850, 0xbbfc:850, 0xbc00:850, 0xbc0f:850, 0xbc14:910, 0xbc15:910, 0xbc16:910, 0xbc18:910,\n 0xbc1b:910, 0xbc1c:910, 0xbc29:910, 0xbc30:890, 0xbc84:850, 0xbc88:850, 0xbc94:850, 0xbc95:850, 0xbcc0:850, 0xbcc4:850, 0xbcd1:850, 0xbcf4:900, 0xbcf5:900, 0xbcf8:900, 0xbcfc:900, 0xbd80:900,\n 0xbd84:900, 0xbd88:900, 0xbd99:900, 0xbe0c:900, 0xbe14:900, 0xbe44:850, 0xbe48:850, 0xbe59:850, 0xbe60:920, 0xbfd0:900, 0xc0ac:910, 0xc0ad:910, 0xc0b0:910, 0xc0c1:910, 0xc0c8:890, 0xc0c9:890,\n 0xc0dd:890, 0xc11c:850, 0xc11d:850, 0xc120:850, 0xc124:850, 0xc131:850, 0xc138:890, 0xc140:890, 0xc15c:850, 0xc18c:900, 0xc18d:900, 0xc190:900, 0xc1a1:900, 0xc1c4:890, 0xc218:900, 0xc21c:900,\n 0xc220:900, 0xc2a4:900, 0xc2a8:900, 0xc2b5:900, 0xc2dc:850, 0xc2dd:850, 0xc2e0:850, 0xc2e4:850, 0xc2ec:850, 0xc368:860, 0xc544:910, 0xc548:910, 0xc54a:910, 0xc54c:910, 0xc554:910, 0xc558:910,\n 0xc559:910, 0xc57c:910, 0xc57d:910, 0xc591:910, 0xc5b4:850, 0xc5b8:850, 0xc5bb:850, 0xc5bc:850, 0xc5c5:850, 0xc5c6:850, 0xc5c7:850, 0xc5c8:850, 0xc5d0:890, 0xc5d1:890, 0xc5d4:890, 0xc5ec:850,\n 0xc5ed:850, 0xc5f0:850, 0xc5f4:850, 0xc600:850, 0xc601:850, 0xc608:890, 0xc624:900, 0xc628:900, 0xc62c:900, 0xc640:910, 0xc644:910, 0xc678:850, 0xc694:900, 0xc6a9:900, 0xc6b0:900, 0xc6b4:900,\n 0xc6b8:900, 0xc6c0:900, 0xc6cc:850, 0xc6d0:850, 0xc6d4:850, 0xc6f9:890, 0xc704:850, 0xc720:900, 0xc721:900, 0xc724:900, 0xc728:900, 0xc73c:900, 0xc740:900, 0xc744:900, 0xc74c:900, 0xc758:850,\n 0xc774:850, 0xc778:850, 0xc77c:850, 0xc784:850, 0xc785:850, 0xc788:850, 0xc790:910, 0xc791:910, 0xc794:910, 0xc7a5:910, 0xc7ac:890, 0xc7c1:890, 0xc800:850, 0xc801:850, 0xc804:850, 0xc808:850,\n 0xc810:850, 0xc811:850, 0xc815:850, 0xc81c:890, 0xc838:850, 0xc870:900, 0xc874:900, 0xc885:900, 0xc8fc:900, 0xc900:900, 0xc911:900, 0xc989:900, 0xc99d:900, 0xc9c0:850, 0xc9c1:850, 0xc9c4:850,\n 0xc9c8:850, 0xc9d0:850, 0xc9d1:850, 0xc9d5:850, 0xcabd:900, 0xcc28:910, 0xcc2c:910, 0xcc38:910, 0xcc45:890, 0xcc98:850, 0xcca0:850, 0xcca8:850, 0xccad:850, 0xccb4:890, 0xccd0:850, 0xcd08:900,\n 0xcd2c:910, 0xcd5c:850, 0xcd94:900, 0xcd95:900, 0xcd9c:900, 0xcda9:900, 0xcde8:850, 0xce20:900, 0xce58:850, 0xce59:850, 0xce68:850, 0xce6d:850, 0xce74:910, 0xce94:890, 0xcef4:850, 0xcf1c:850,\n 0xcf54:900, 0xcf58:900, 0xd06c:900, 0xd074:900, 0xd07c:900, 0xd0a4:850, 0xd0c0:910, 0xd0c1:910, 0xd0dc:890, 0xd0dd:890, 0xd130:850, 0xd138:850, 0xd14c:890, 0xd150:890, 0xd15c:890, 0xd1a0:900,\n 0xd1b5:900, 0xd2b8:900, 0xd2b9:900, 0xd30c:910, 0xd310:910, 0xd328:890, 0xd398:890, 0xd3b8:850, 0xd3c9:850, 0xd3d0:890, 0xd3ec:900, 0xd45c:900, 0xd504:900, 0xd53c:850, 0xd544:850, 0xd558:910,\n 0xd559:910, 0xd55c:910, 0xd560:910, 0xd568:910, 0xd569:910, 0xd56d:910, 0xd574:890, 0xd588:890, 0xd589:890, 0xd5c8:850, 0xd601:850, 0xd604:850, 0xd611:850, 0xd615:850, 0xd638:900, 0xd639:900,\n 0xd648:900, 0xd64d:900, 0xd654:910, 0xd655:910, 0xd658:910, 0xd65c:910, 0xd669:910, 0xd68c:850, 0xd68d:850, 0xd6a8:900, 0xd6c4:900, 0xd6c8:900, 0xd6fc:890, 0xd734:900, 0xd788:850, 0xff0a:940,\n },\n}\n\n/** HCI Poppy — 한컴 PDF 임베드 Type3 글꼴 /Widths 실측(HCI Poppy 영문 문서 696개의 PDF, 84자). PDF 에 없는 글자만 lineseg 맞춤값 */\nconst FIT_HCI_Poppy: FontMetrics = {\n cjk: 1000,\n ascii: [500,277,369,610,610,839,777,277,332,332,388,605,248,332,248,605,498,498,498,498,498,498,498,498,498,498,248,320,605,550,605,443,746,777,609,707,773,609,554,761,830,335,332,726,609,945,830,785,603,705,667,525,613,777,722,998,667,705,626,332,550,332,550,550,277,498,552,443,609,478,332,554,582,291,288,554,291,882,582,546,599,579,394,423,324,603,564,832,515,554,498,320,320,320,605],\n ex: {\n 0xb7:360, 0x2018:277, 0x2019:277, 0x201c:498, 0x201d:498,\n },\n}\n\n/** HCI Tulip — 한컴 저장 lineseg 맞춤(두 줄 이상 문단 69개, 검증 문단 정답 25→30/34) */\nconst FIT_HCI_Tulip: FontMetrics = {\n cjk: 1000,\n ascii: [500,320,320,610,610,830,724,320,320,320,550,550,300,550,320,550,550,290,550,550,550,550,550,550,550,550,320,320,550,550,550,550,830,706,605,685,719,627,617,683,734,305,315,660,605,839,734,732,\n 603,705,660,627,664,731,706,910,705,705,626,320,550,320,550,550,320,569,597,552,597,536,356,562,635,287,288,582,287,907,635,588,597,579,478,496,356,635,563,720,542,543,486,320,320,320,550],\n ex: {\n 0x2018:180, 0x2019:930, 0x201c:280,\n },\n}\n\n/** 한컴바탕 — 한컴 PDF 임베드 글꼴 /W 실측(Haansoft Batang·HaansoftBatang, 글자 1305개, 빈 ASCII 는 종전 값) */\nconst PDF_한컴바탕: FontMetrics = {\n cjk: 1000,\n ascii: [333,416,416,610,610,916,833,250,500,500,500,833,291,833,291,333,583,583,583,583,583,583,583,583,583,583,333,333,833,833,833,500,1000,750,666,666,708,666,625,708,750,375,458,750,625,916,750,\n 708,625,708,666,625,750,750,708,958,666,666,625,500,550,500,550,500,320,500,541,500,541,541,375,541,541,291,291,541,291,833,541,541,541,541,416,500,375,541,541,791,583,583,458,320,583,320,791],\n ex: {\n 0xa0:500, 0xb0:436, 0xb1:811, 0xb3:359, 0xb7:333, 0xd7:811, 0xf7:811, 0x2bc:178, 0x2d0:218, 0x2d1:218, 0x2ee:353, 0x387:313,\n 0x3c0:565, 0x55b:161, 0x966:458, 0x16eb:280, 0x2002:500, 0x200b:500, 0x2013:430, 0x2014:860, 0x2018:269, 0x2019:269, 0x201c:370, 0x201d:370,\n 0x2022:462, 0x2023:465, 0x2024:173, 0x2026:830, 0x2027:173, 0x202f:500, 0x2032:269, 0x2033:436, 0x2035:269, 0x203b:761, 0x20dd:0, 0x2218:500,\n 0x2219:500, 0x3000:500, 0x302e:0, 0xff62:500, 0xff63:500, 0xff65:500, 0xffeb:500, 0xffed:500,\n },\n}\n\n/** 돋움 — 한컴 PDF 임베드 글꼴 /W 실측(Dotum, 글자 898개, 빈 ASCII 는 종전 값) */\nconst PDF_돋움: FontMetrics = {\n cjk: 1000,\n ascii: [333,320,416,610,500,916,708,291,375,375,583,582,375,589,375,416,583,583,583,583,583,583,583,583,583,583,339,320,625,583,625,583,1000,666,679,720,724,628,599,750,722,257,484,656,541,808,697,\n 750,642,750,667,638,583,724,601,892,603,601,603,500,550,500,550,500,320,583,599,558,603,558,343,597,560,228,228,509,230,916,568,599,601,603,320,515,312,554,474,724,478,480,482,500,320,500,791],\n ex: {\n 0xa0:500, 0xad:500, 0xb7:332, 0xd7:833, 0x2018:291, 0x2019:291, 0x201c:458, 0x201d:458, 0x2022:375, 0x2113:500, 0x2191:750, 0x2219:291,\n 0x221a:500, 0x25a0:889, 0x25a1:889, 0x25b2:914, 0x25bc:914, 0x25e6:375,\n },\n}\n\n/** 궁서 — 한컴 PDF 임베드 글꼴 /W 실측(Gungsuh, 글자 595개, 빈 ASCII 는 종전 값) */\nconst PDF_궁서: FontMetrics = {\n cjk: 1000,\n ascii: [333,416,320,610,610,666,724,291,416,416,500,625,333,832,333,375,583,583,583,583,583,583,583,583,583,583,333,320,708,625,708,550,830,687,683,687,678,657,656,683,702,462,562,687,625,812,711,\n 672,651,705,660,619,648,712,706,792,666,705,626,500,550,500,550,550,320,613,637,615,637,610,356,637,650,287,288,641,287,875,635,657,597,655,478,583,356,635,563,720,542,543,486,320,320,320,791],\n ex: {\n 0xa0:500, 0xb7:332, 0x2018:333, 0x2019:333, 0x201c:500, 0x201d:500, 0x2113:525, 0x25a1:889,\n },\n}\n\n/** HY신명조 — 한컴 PDF 임베드 글꼴 /W 실측(H2mjsM·HYSinMyeongJo-Medium, 글자 909개, 빈 ASCII 는 종전 값) */\nconst PDF_HY신명조: FontMetrics = {\n cjk: 1000,\n ascii: [333,320,416,610,610,916,724,320,500,500,500,833,291,833,291,375,625,625,625,625,625,625,625,625,625,625,333,320,599,833,599,550,1000,791,708,708,750,708,666,750,791,375,500,791,666,916,791,\n 750,666,705,708,666,791,791,750,1000,708,708,626,500,550,500,550,550,320,541,583,541,583,583,375,583,583,291,288,583,291,875,583,583,583,579,458,541,375,583,583,833,625,625,500,320,320,320,750],\n ex: {\n\n },\n}\n\n/** HY중고딕 — 한컴 PDF 임베드 글꼴 /W 실측(H2gtrM, 글자 596개, 빈 ASCII 는 종전 값) */\nconst PDF_HY중고딕: FontMetrics = {\n cjk: 1000,\n ascii: [333,320,320,833,610,916,750,250,416,416,583,833,375,833,375,375,583,583,583,583,583,583,583,583,583,583,416,320,541,833,541,550,1000,666,708,750,750,666,625,833,750,291,541,708,583,875,750,\n 791,666,705,708,666,583,750,625,916,625,625,625,416,550,416,550,550,320,583,625,583,625,583,375,625,583,250,250,541,250,916,625,625,625,625,333,541,333,583,500,750,500,500,500,320,320,320,750],\n ex: {\n\n },\n}\n\n/** HY궁서 — 한컴 PDF 임베드 글꼴 /W 실측(HYgsrB, 글자 613개, 빈 ASCII 는 종전 값) */\nconst PDF_HY궁서: FontMetrics = {\n cjk: 1000,\n ascii: [333,320,416,610,610,666,583,320,416,416,500,625,333,832,333,375,583,583,583,583,583,583,583,583,583,583,333,320,708,550,708,583,830,687,683,687,678,657,656,700,702,462,315,687,605,839,711,\n 672,651,705,702,619,648,712,682,910,666,705,626,320,550,320,550,550,320,613,637,615,637,610,500,637,650,469,288,641,500,875,646,657,655,579,583,583,562,645,645,750,542,647,551,320,320,320,791],\n ex: {\n\n },\n}\n\n/** 휴먼고딕 — 한컴 PDF 임베드 글꼴 /W 실측(휴먼고딕, 글자 558개, 빈 ASCII 는 종전 값) */\nconst PDF_휴먼고딕: FontMetrics = {\n cjk: 1000,\n ascii: [500,261,320,610,610,843,724,281,312,312,500,500,289,500,238,312,503,503,503,503,503,503,503,503,503,503,257,246,500,550,500,515,830,597,562,593,574,539,500,648,734,195,315,597,492,714,585,\n 675,535,705,550,554,539,578,613,910,589,578,626,320,550,320,550,550,320,500,597,500,527,531,285,539,500,195,288,496,195,765,500,527,519,579,359,464,312,503,507,720,542,476,486,320,320,320,500],\n ex: {\n\n },\n}\n\n/** 한컴 윤고딕 230 — 한컴 PDF 임베드 글꼴 /W 실측(HaanYGodic23, 글자 487개, 빈 ASCII 는 종전 값) */\nconst PDF_한컴_윤고딕_230: FontMetrics = {\n cjk: 900,\n ascii: [350,408,320,610,610,857,748,320,380,380,480,680,350,660,350,480,750,479,601,619,621,619,628,558,636,628,350,320,500,550,500,550,860,733,702,773,733,627,635,792,734,308,315,714,611,859,734,\n 794,680,800,693,664,645,733,743,913,684,680,626,400,550,400,550,550,320,678,675,552,597,629,354,562,650,308,288,582,308,883,649,629,672,579,429,496,354,640,563,720,542,543,486,320,320,320,900],\n ex: {\n 0xb7:340, 0x2018:240, 0x2019:240, 0x201c:410, 0x201d:410, 0x300c:400, 0x300d:400, 0x3010:450, 0x3011:450, 0x4e0a:920, 0x4e0b:920, 0x5168:920,\n 0x65b0:920, 0x6708:920, 0x793e:920, 0x8eca:920, 0xffff:1000,\n },\n}\n\n/** 한컴 윤고딕 240 — 한컴 PDF 임베드 글꼴 /W 실측(HaanYGodic24, 글자 397개, 빈 ASCII 는 종전 값) */\nconst PDF_한컴_윤고딕_240: FontMetrics = {\n cjk: 900,\n ascii: [350,320,320,610,610,830,724,320,380,380,480,680,350,660,350,480,750,479,601,619,621,619,628,558,636,628,350,320,550,550,550,550,830,733,702,773,719,664,617,792,734,308,543,714,611,859,734,\n 794,680,705,660,664,645,733,706,913,705,705,626,400,550,400,550,550,320,678,597,616,678,629,356,562,650,308,288,582,308,883,649,588,672,579,478,496,354,640,563,720,542,543,486,320,320,320,900],\n ex: {\n 0xb7:340, 0x2018:240, 0x2019:240, 0x300c:360, 0x300d:360, 0x300e:360, 0x300f:360, 0x3010:450, 0x3011:450, 0x4e2d:920, 0x4ee5:920, 0x524d:920,\n 0x5931:920, 0x5f8c:920, 0x6a5f:920, 0x73fe:920, 0x7f8e:920, 0xffff:1000,\n },\n}\n\n/** 한컴 윤고딕 250 — 한컴 PDF 임베드 글꼴 /W 실측(HaanYGodic25, 글자 227개, 빈 ASCII 는 종전 값) */\nconst PDF_한컴_윤고딕_250: FontMetrics = {\n cjk: 900,\n ascii: [350,320,320,610,610,830,848,320,480,480,550,550,450,760,450,550,850,579,701,719,721,719,728,550,736,728,450,320,550,550,550,550,830,833,605,873,833,627,617,892,734,408,643,814,605,959,734,\n 732,603,705,793,627,745,731,706,1013,784,705,626,320,550,320,550,550,320,569,597,552,597,536,356,562,635,287,288,582,287,907,635,588,597,579,478,496,356,635,563,720,542,543,486,320,320,320,1000],\n ex: {\n 0xb7:340, 0x2019:240, 0xffff:1000,\n },\n}\n\n/** 한컴산뜻돋움 — 한컴 PDF 임베드 글꼴 /W 실측(HanSantteutDotumRegular, 글자 476개, 빈 ASCII 는 종전 값) */\nconst PDF_한컴산뜻돋움: FontMetrics = {\n cjk: 932,\n ascii: [264,320,320,610,610,892,724,320,446,446,446,583,297,583,297,446,583,583,583,583,583,583,583,583,583,583,297,320,446,550,446,669,830,644,627,639,719,627,554,710,718,247,410,626,529,884,734,\n 732,586,705,660,592,621,731,706,961,705,705,626,446,550,446,550,550,320,560,597,552,597,536,356,562,635,287,288,530,287,892,635,588,597,579,478,475,357,635,563,720,542,543,486,320,320,320,669],\n ex: {\n 0xb7:446, 0x2018:303, 0x2019:303, 0x201c:446, 0x201d:446, 0x2022:586, 0x300c:486, 0x300d:486, 0x5c0d:1000,\n },\n}\n\n/** 한컴 고딕 — 한컴 PDF 임베드 글꼴 /W 실측(HancomGothicRegular, 글자 397개, 빈 ASCII 는 종전 값) */\nconst PDF_한컴_고딕: FontMetrics = {\n cjk: 932,\n ascii: [264,320,320,610,610,892,724,320,446,446,446,583,297,583,297,446,583,583,583,583,583,583,583,583,583,583,297,320,446,550,446,550,830,644,605,639,721,596,617,710,718,247,315,626,605,884,710,\n 752,603,705,610,592,621,731,635,910,617,705,626,446,550,446,550,550,320,560,588,490,588,559,340,588,635,244,288,530,244,892,592,577,588,579,383,475,357,592,530,788,542,543,486,320,320,320,669],\n ex: {\n 0xb7:446, 0x2019:303, 0x524d:1000, 0x73fe:1000, 0xf076:891, 0xf0a7:458,\n },\n}\n\n/** 한양중고딕 — 한컴 PDF 임베드 글꼴 /W 실측(한양중고딕·HY-Junggothic, 글자 67개, 빈 ASCII 는 종전 값) */\nconst PDF_한양중고딕: FontMetrics = {\n cjk: 1000,\n ascii: [0,320,320,610,610,867,724,320,288,281,369,518,246,518,245,263,500,500,500,500,500,500,500,500,500,500,247,320,583,519,582,550,830,632,629,699,693,649,594,683,734,246,315,660,539,803,734,\n 799,637,705,692,636,584,731,632,954,880,705,626,320,550,320,550,550,320,534,527,483,531,532,356,562,529,195,288,473,195,809,529,539,535,579,310,480,255,531,479,720,542,466,486,320,320,320,500],\n ex: {\n 0xb7:381, 0xd7:620, 0x2018:225, 0x2019:225, 0x201c:375, 0x201d:375,\n },\n}\n\n/** 나눔고딕 — 한컴 PDF 임베드 글꼴 /W 실측(NanumGothic, 글자 508개, 빈 ASCII 는 종전 값) */\nconst PDF_나눔고딕: FontMetrics = {\n cjk: 940,\n ascii: [280,320,430,606,610,830,727,303,363,363,606,654,303,363,303,375,606,606,606,606,606,606,606,606,606,606,303,320,547,654,547,550,872,727,606,672,727,576,503,683,727,242,315,641,484,969,727,\n 787,577,787,622,545,545,727,666,910,666,705,626,363,550,363,550,545,320,545,606,484,606,545,356,606,606,242,288,520,242,908,606,606,606,579,363,424,363,606,484,848,510,464,486,320,320,320,654],\n ex: {\n 0xb7:290, 0xd7:592, 0x2018:185, 0x2019:185, 0x201c:350, 0x201d:350, 0x300c:351, 0x300d:351, 0x3010:374, 0x3011:382,\n },\n}\n\n/** HY울릉도M — 한컴 PDF 임베드 글꼴 /W 실측(HYwulM, 글자 404개, 빈 ASCII 는 종전 값) */\nconst PDF_HY울릉도M: FontMetrics = {\n cjk: 1000,\n ascii: [333,366,320,610,610,948,810,320,362,362,550,862,321,862,321,349,630,630,630,630,630,630,630,630,630,630,321,320,862,550,862,596,830,712,577,818,742,627,617,683,734,272,490,617,471,895,728,\n 863,603,867,586,516,481,630,642,916,705,705,626,362,550,362,550,550,320,714,597,675,717,696,356,562,634,264,288,582,264,907,635,588,597,579,342,496,338,634,563,720,542,543,486,320,320,320,779],\n ex: {\n\n },\n}\n\n/** HY그래픽 — 한컴 PDF 임베드 글꼴 /W 실측(HYgprM·H2gprM, 글자 314개, 빈 ASCII 는 종전 값) */\nconst PDF_HY그래픽: FontMetrics = {\n cjk: 1000,\n ascii: [333,320,320,583,610,830,875,320,375,375,583,583,250,583,250,458,583,583,583,583,583,583,583,583,583,583,375,320,583,583,583,541,1000,708,666,708,708,627,617,750,666,291,333,660,605,839,708,\n 732,603,705,666,627,664,708,625,910,705,625,626,375,550,375,550,500,320,541,583,541,583,583,375,541,541,291,291,541,291,833,541,583,583,583,375,500,375,583,500,750,500,458,486,320,320,320,583],\n ex: {\n\n },\n}\n\n/** 경기천년바탕 Regular — 한컴 PDF 임베드 글꼴 /W 실측(GyeonggiBatangR, 글자 412개, 빈 ASCII 는 종전 값) */\nconst PDF_경기천년바탕_Regular: FontMetrics = {\n cjk: 910,\n ascii: [300,320,320,610,610,830,724,320,333,333,500,550,250,524,250,278,500,500,500,500,500,500,500,500,500,500,296,320,550,550,564,468,830,706,605,685,719,627,617,683,734,305,315,660,605,839,734,\n 732,603,670,660,627,664,731,706,910,705,705,626,333,550,333,550,550,320,493,597,552,597,496,356,533,543,287,288,524,287,786,635,527,529,579,392,496,320,635,563,690,482,543,486,320,320,320,541],\n ex: {\n 0xb7:300, 0x2018:220, 0x2019:220, 0x201c:380, 0x201d:380, 0x203b:960, 0x2192:960, 0x2460:1000, 0x2461:1000, 0x2462:1000, 0x2463:1000, 0x2464:1000,\n 0x25a0:960, 0x25cb:960, 0x260e:900, 0x300c:500, 0x300d:500, 0x4e3b:920, 0x4e8b:920, 0x52d9:920, 0x5584:920, 0x6148:920, 0x6240:920, 0xffff:1000,\n },\n}\n\n/** Arial Narrow — 한컴 PDF 임베드 글꼴 /W 실측(ArialNarrow, 글자 75개, 빈 ASCII 는 종전 값) */\nconst PDF_Arial_Narrow: FontMetrics = {\n cjk: 1000,\n ascii: [228,320,320,610,610,830,546,157,272,272,318,550,228,272,228,228,456,456,456,456,456,456,456,456,456,456,228,320,550,479,550,550,830,546,546,591,591,546,500,638,591,228,410,546,456,683,591,\n 638,546,638,591,546,500,591,546,773,546,546,626,320,550,320,550,550,320,456,456,410,456,456,228,456,456,182,182,410,182,683,456,456,456,456,272,410,228,456,410,591,410,410,410,320,320,320,550],\n ex: {\n 0xb0:399, 0xffff:228,\n },\n}\n\n/** Times New Roman — 한컴 PDF 임베드 글꼴 /W 실측(TimesNewRomanPSMT, 글자 95개, 빈 ASCII 는 종전 값) */\nconst PDF_Times_New_Roman: FontMetrics = {\n cjk: 1000,\n ascii: [250,333,408,500,500,833,724,180,333,333,500,563,250,333,250,277,500,500,500,500,500,500,500,500,500,500,277,277,563,563,563,443,920,722,666,666,722,610,556,722,722,333,389,722,610,889,722,\n 722,556,705,666,556,610,722,722,943,722,722,626,333,277,333,550,500,333,443,500,443,500,443,333,500,500,277,277,500,277,777,500,500,500,500,333,389,277,500,500,722,500,500,443,479,320,479,550],\n ex: {\n 0x2018:333, 0x2019:333, 0x201c:443, 0x201d:443, 0x2e31:333, 0xffff:777,\n },\n}\n\n/** Arial — 한컴 PDF 임베드 글꼴 /W 실측(ArialMT, 글자 84개, 빈 ASCII 는 종전 값) */\nconst PDF_Arial: FontMetrics = {\n cjk: 996,\n ascii: [277,320,320,610,610,889,724,320,333,333,550,583,277,333,277,277,556,556,556,556,556,556,556,556,556,556,277,277,550,583,550,550,830,666,666,722,722,666,610,777,722,277,500,666,556,833,722,\n 777,666,705,722,666,610,722,666,943,666,666,610,320,550,320,550,550,320,556,556,500,556,556,277,556,556,222,222,500,222,833,556,556,556,556,333,500,277,556,500,722,500,500,500,320,320,320,550],\n ex: {\n 0xb7:333, 0xe7:500, 0xe9:556, 0xf4:556, 0x2014:1000, 0x2019:222, 0x201c:333, 0x201d:333, 0x2192:1000, 0x2219:277, 0xffff:750,\n },\n}\n\nconst FONTS: Record<string, FontMetrics> = {\n \"한컴돋움\": {\n cjk: 1000,\n ascii: [500,334,415,625,500,915,709,290,375,375,583,580,375,590,375,415,583,583,583,583,583,583,583,583,583,583,340,340,625,584,625,583,1000,665,680,720,725,629,600,750,724,259,484,655,540,810,695,750,\n 644,750,668,640,583,725,600,894,604,600,604,500,333,500,625,500,330,583,600,560,600,560,344,599,560,229,229,510,230,800,568,600,600,600,320,515,313,568,475,725,479,480,480,500,500,500,790],\n ex: {\n 0xa7:561, 0xb0:405, 0xb1:833, 0xb4:333, 0xb7:331, 0xd7:833, 0xf7:833, 0x2010:261, 0x2011:314, 0x2012:431, 0x2013:500, 0x2014:687,\n 0x2016:429, 0x2017:548, 0x2018:291, 0x2019:291, 0x201a:291, 0x201b:291, 0x201c:458, 0x201d:458, 0x201e:458, 0x201f:458, 0x2020:562, 0x2021:562,\n 0x2022:463, 0x2023:466, 0x2024:174, 0x2025:566, 0x2026:830, 0x2027:301, 0x202f:500, 0x2032:335, 0x2033:563, 0x2034:734, 0x2035:335, 0x2036:563,\n 0x2037:734, 0x2038:408, 0x2039:375, 0x203a:375, 0x203c:625, 0x203d:465, 0x203e:500, 0x203f:804, 0x2040:804, 0x2041:356, 0x2043:224, 0x2044:734,\n 0x2045:320, 0x2046:320, 0x2048:656, 0x2049:656, 0x204a:456, 0x204b:562, 0x204c:562, 0x204d:562, 0x2050:804, 0x2218:500, 0x2219:500,\n },\n },\n \"HY견고딕\": {\n cjk: 1000,\n ascii: [500,416,583,708,625,958,791,333,458,458,541,666,375,666,375,416,625,625,625,625,625,625,625,625,625,625,375,375,583,666,583,708,1000,791,791,791,791,708,666,833,791,375,583,833,666,875,791,833,\n 708,833,791,750,708,791,708,1000,750,750,708,458,416,458,541,500,250,625,666,625,666,625,375,666,666,375,333,666,375,958,666,666,666,666,458,625,416,666,625,833,625,625,583,500,375,500,666],\n ex: {},\n },\n \"휴먼명조\": {\n cjk: 1000,\n ascii: [500,203,500,656,504,750,770,289,313,313,500,500,262,500,270,313,500,500,500,500,500,500,500,500,500,500,270,270,500,500,500,430,777,660,602,641,680,625,582,703,680,258,395,645,578,781,691,715,\n 574,688,652,496,625,676,660,934,711,672,598,320,313,320,363,500,324,508,543,484,508,523,391,516,555,250,266,523,250,797,551,512,539,539,402,410,340,539,539,723,488,512,453,293,203,293,500],\n ex: {\n 0xb7:990, 0x200b:700, 0x2018:220, 0x2019:590, 0x2022:530, 0x2024:1030, 0x2027:420, 0x25a1:1060, 0x25aa:1104, 0x25e6:1010, 0x318d:1010, 0xff62:300,\n 0xff63:630, 0xff65:530,\n },\n },\n \"HY헤드라인M\": {\n cjk: 1000,\n ascii: [500,250,375,833,584,791,625,208,291,291,333,583,208,583,208,375,583,583,583,583,583,583,583,583,583,583,250,265,458,587,458,583,853,583,625,625,625,458,458,625,625,250,333,583,416,791,583,583,\n 541,583,583,583,500,625,625,916,583,541,485,333,384,333,542,500,324,583,583,583,583,625,375,591,583,250,338,541,250,833,583,625,583,594,416,541,375,583,541,791,500,500,416,417,292,417,708],\n ex: {},\n },\n \"굴림체\": {\n cjk: 1000,\n ascii: [500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,\n 500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500],\n ex: {\n 0x2013:500, 0x2014:500, 0x2017:500, 0x201a:500, 0x201b:500, 0x201e:500, 0x2022:500, 0x2039:500, 0x203a:500, 0x203c:500, 0x203e:500, 0x2044:500,\n 0x2105:500, 0x212e:500, 0x21a8:500, 0x2206:500, 0x2212:500, 0x2215:500, 0x2219:500, 0x221f:500, 0x2248:500, 0x2550:500, 0x2551:500, 0x2552:500,\n 0x2553:500, 0x2554:500, 0x2555:500, 0x2556:500, 0x2557:500, 0x2558:500, 0x2559:500, 0x255a:500, 0x255b:500, 0x255c:500, 0x255d:500, 0x255e:500,\n 0x255f:500, 0x2560:500, 0x2561:500, 0x2562:500, 0x2563:500, 0x2564:500, 0x2565:500, 0x2566:500, 0x2567:500, 0x2568:500, 0x2569:500, 0x256a:500,\n 0x256b:500, 0x256c:500, 0x2580:500, 0x2584:500, 0x2588:500, 0x258c:500, 0x2590:500, 0x2591:500, 0x2593:500, 0x25aa:500, 0x25ab:500, 0x25ac:500,\n 0x25ba:500, 0x25c4:500, 0x25ca:500, 0x25d8:500, 0x25d9:500, 0x25e6:500, 0x263a:500, 0x263b:500, 0x263c:500, 0x2666:500, 0x266b:500,\n },\n },\n \"굴림\": {\n cjk: 1000,\n ascii: [500,333,375,750,598,875,688,283,375,375,500,625,334,625,334,417,574,574,574,574,574,574,574,574,574,574,334,334,625,625,625,542,1000,646,677,718,722,625,596,770,730,270,500,635,543,813,699,770,\n 637,773,666,633,582,711,600,895,625,625,625,500,917,500,542,500,333,563,605,572,605,567,342,605,571,241,241,500,231,861,580,605,605,605,333,525,313,570,500,750,500,500,500,500,500,500,792],\n ex: {\n 0xa7:563, 0xb0:375, 0xb1:833, 0xb4:375, 0xb7:375, 0xd7:833, 0xf7:833, 0x2013:500, 0x2015:688, 0x2017:500, 0x2018:333, 0x2019:333,\n 0x201a:333, 0x201b:333, 0x201c:500, 0x201d:500, 0x201e:500, 0x2020:563, 0x2021:563, 0x2022:375, 0x2032:375, 0x2033:500, 0x2039:375, 0x203a:375,\n 0x203c:625, 0x203e:500, 0x2044:417, 0x2105:846, 0x2113:500, 0x2126:750, 0x212e:750, 0x215b:563, 0x215c:563, 0x215d:563, 0x215e:563, 0x2191:750,\n 0x2193:750, 0x2195:750, 0x21a8:750, 0x2202:563, 0x2206:613, 0x220f:688, 0x2211:813, 0x2212:833, 0x2215:417, 0x2219:250, 0x221a:549, 0x221e:913,\n 0x221f:982, 0x2229:719, 0x222b:375, 0x2248:833, 0x2260:833, 0x2261:833, 0x2264:833, 0x2265:833, 0x25a0:890, 0x25a1:890, 0x25aa:375, 0x25ab:375,\n 0x25b2:914, 0x25ba:750, 0x25bc:914, 0x25c4:750, 0x25ca:774, 0x25e6:375, 0x263c:916, 0x2640:625, 0x2642:625, 0x2660:750, 0x2663:844, 0x2665:793,\n 0x2666:774, 0x266a:688, 0x266b:763,\n },\n },\n \"맑은 고딕\": {\n // 숫자 3·9, %, T, l, ①·④ 는 한컴 PDF 임베드 맑은 고딕 /W 실측(숫자는 고정폭 551 — 맞춤 490·510 은 과적합). 쉼표·마침표·가운뎃점은\n // 실측 218 보다 맞춤 210 이 한컴 줄바꿈에 맞아(두 줄+ −13문단) 그대로 둔다\n cjk: 1000,\n ascii: [500,289,395,606,551,836,818,232,305,300,425,701,210,410,210,396,551,551,551,551,551,551,551,551,551,551,219,219,701,701,701,460,979,658,583,635,717,517,499,702,725,270,360,590,480,917,765,773,\n 571,773,610,543,533,703,634,954,601,563,583,305,764,305,701,426,272,520,601,473,602,535,316,602,579,246,246,506,246,880,578,599,601,602,354,433,345,578,487,736,465,493,462,305,239,305,701],\n ex: {\n 0xa7:458, 0xb0:387, 0xb1:701, 0xb4:288, 0xb7:210, 0xd7:701, 0xf7:701, 0x2013:513, 0x2014:1026, 0x2018:231, 0x2019:231, 0x201a:231,\n 0x201c:379, 0x201d:379, 0x201e:379, 0x2020:382, 0x2021:382, 0x2022:417, 0x2024:500, 0x2025:437, 0x2026:740, 0x2027:250, 0x2030:1238, 0x2032:231,\n 0x2033:379, 0x2039:322, 0x203a:322, 0x203b:800, 0x203c:578, 0x2047:920, 0x2048:749, 0x2049:749, 0x2103:950, 0x2109:950, 0x2113:332, 0x2116:1146,\n 0x2121:950, 0x2122:793, 0x2126:774, 0x212b:696, 0x2153:950, 0x2154:950, 0x215b:943, 0x215c:981, 0x215d:982, 0x215e:913, 0x2160:950, 0x2161:950,\n 0x2162:950, 0x2163:950, 0x2164:950, 0x2165:950, 0x2166:950, 0x2167:950, 0x2168:950, 0x2169:950, 0x2170:950, 0x2171:950, 0x2172:950, 0x2173:950,\n 0x2174:950, 0x2175:950, 0x2176:950, 0x2177:950, 0x2178:950, 0x2179:950, 0x2190:950, 0x2191:950, 0x2192:950, 0x2193:950, 0x2194:950, 0x2195:950,\n 0x2196:950, 0x2197:950, 0x2198:950, 0x2199:950, 0x21d2:950, 0x21d4:950, 0x2200:696, 0x2202:546, 0x2203:548, 0x2207:713, 0x2208:950, 0x220b:950,\n 0x220f:771, 0x2211:631, 0x2219:315, 0x221a:667, 0x221d:838, 0x221e:839, 0x2220:667, 0x2225:684, 0x2227:684, 0x2228:684, 0x2229:950, 0x222a:950,\n 0x222b:551, 0x222c:950, 0x222e:545, 0x2234:667, 0x2235:667, 0x223c:684, 0x223d:684, 0x2252:684, 0x2260:701, 0x2261:684, 0x2264:701, 0x2265:701,\n 0x226a:950, 0x226b:950, 0x2282:950, 0x2283:950, 0x2286:950, 0x2287:950, 0x2299:950, 0x22a5:950, 0x2460:1000, 0x2463:1000, 0x25aa:890, 0x25cc:594,\n 0x2640:625, 0x2642:715, 0x2669:538, 0x266a:688, 0x266c:932, 0x266d:573, 0x3008:542, 0x3009:542, 0x300a:596, 0x300b:596, 0x300c:571, 0x300d:571,\n 0x300e:517, 0x300f:517, 0x3010:518, 0x3011:518, 0x3014:488, 0x3015:488, 0x302e:333, 0x302f:333, 0xff62:350, 0xff63:770, 0xff65:650, 0xffed:530,\n 0xf02fb:740,\n },\n },\n \"함초롬돋움\": {\n cjk: 970,\n ascii: [500,333,339,686,626,853,761,260,313,313,498,548,258,466,270,374,550,550,550,550,550,550,550,550,550,550,312,312,600,534,600,570,865,654,664,633,701,625,609,645,694,317,515,664,584,826,728,676,\n 660,681,683,617,573,702,594,897,607,581,584,338,373,329,562,532,373,563,581,513,578,567,336,563,594,271,268,559,258,919,595,582,552,552,427,513,349,595,469,760,483,466,479,372,342,372,546],\n han: 1000, // 한자 — 한컴 PDF 임베드 글꼴 /W 실측\n ex: {\n 0xa7:486, 0xb0:306, 0xb1:782, 0xb4:240, 0xb7:294, 0xd7:587, 0xf7:670, 0x2010:237, 0x2011:300, 0x2012:398, 0x2013:348, 0x2014:522,\n 0x2015:672, 0x2016:368, 0x2017:419, 0x2018:288, 0x2019:288, 0x201a:288, 0x201b:288, 0x201c:451, 0x201d:453, 0x201e:451, 0x201f:488, 0x2020:518,\n 0x2021:448, 0x2022:586, 0x2023:590, 0x2024:288, 0x2025:544, 0x2026:702, 0x2027:288, 0x2030:892, 0x2031:956, 0x2032:304, 0x2033:488, 0x2034:550,\n 0x2035:304, 0x2036:488, 0x2037:544, 0x2038:494, 0x2039:448, 0x203a:448, 0x203b:690, 0x203c:502, 0x203d:556, 0x203e:348, 0x203f:941, 0x2040:941,\n 0x2041:517, 0x2042:764, 0x2043:681, 0x2044:359, 0x2045:343, 0x2046:343, 0x2047:930, 0x2048:688, 0x2049:712, 0x204a:549, 0x204b:543, 0x204c:573,\n 0x204d:573, 0x204e:551, 0x204f:297, 0x2050:941, 0x2051:436, 0x2052:610, 0x2053:523, 0x2054:941, 0x2055:468, 0x2056:595, 0x2057:625, 0x2058:690,\n 0x2059:690, 0x205a:494, 0x205b:630, 0x205c:678, 0x205d:494, 0x205e:494, 0x2135:520, 0x2136:526, 0x2137:320, 0x2138:471, 0x261c:1012, 0x261e:1012,\n 0x3008:500, 0x3009:500, 0x300a:500, 0x300b:500, 0x300c:500, 0x300d:500, 0x300e:500, 0x300f:500, 0x3010:500, 0x3011:500, 0x3014:500, 0x3015:500,\n 0x3016:500, 0x3017:500, 0x3018:500, 0x3019:500, 0x301a:500, 0x301b:500, 0x302c:246, 0x302d:246, 0x303f:485,\n },\n },\n \"KoPub바탕체 Light\": KOPUB_BATANG, \"KoPub바탕체 Medium\": KOPUB_BATANG, \"KoPub바탕체 Bold\": KOPUB_BATANG,\n \"KoPub돋움체 Light\": KOPUB_DOTUM, \"KoPub돋움체 Medium\": KOPUB_DOTUM, \"KoPub돋움체 Bold\": KOPUB_DOTUM,\n \"KoPubWorld바탕체 Light\": KOPUB_WORLD_BATANG, \"KoPubWorld바탕체 Medium\": KOPUB_WORLD_BATANG, \"KoPubWorld바탕체 Bold\": KOPUB_WORLD_BATANG, \"KoPubWorld바탕체_Pro Light\": KOPUB_WORLD_BATANG, \"KoPubWorld바탕체_Pro Medium\": KOPUB_WORLD_BATANG, \"KoPubWorld바탕체_Pro Bold\": KOPUB_WORLD_BATANG,\n \"KoPubWorld돋움체 Light\": KOPUB_WORLD_DOTUM, \"KoPubWorld돋움체 Medium\": KOPUB_WORLD_DOTUM, \"KoPubWorld돋움체 Bold\": KOPUB_WORLD_DOTUM, \"KoPubWorld돋움체_Pro Light\": KOPUB_WORLD_DOTUM, \"KoPubWorld돋움체_Pro Medium\": KOPUB_WORLD_DOTUM, \"KoPubWorld돋움체_Pro Bold\": KOPUB_WORLD_DOTUM,\n \"Arial\": PDF_Arial,\n \"HYSinMyeongJo-Medium\": FIT_HYSinMyeongJo_Medium,\n \"궁서\": PDF_궁서,\n \"돋움\": PDF_돋움,\n \"바탕\": PDFFIT_바탕,\n \"필기\": FIT_필기,\n \"한양신명조\": FIT_한양신명조,\n \"한양중고딕\": PDF_한양중고딕,\n \"한컴 고딕\": PDF_한컴_고딕,\n \"한컴바탕\": PDF_한컴바탕,\n \"한컴산뜻돋움\": PDF_한컴산뜻돋움,\n \"Batang\": FIT_Batang,\n \"08서울한강체 L\": PDF_서울한강체, \"08서울한강체 M\": PDF_서울한강체, \"08서울한강체 B\": PDF_서울한강체, \"08서울한강체 EB\": PDF_서울한강체,\n \"HCI Poppy\": FIT_HCI_Poppy,\n \"HCI Tulip\": FIT_HCI_Tulip,\n \"한컴 윤고딕 230\": PDF_한컴_윤고딕_230,\n \"HY신명조\": PDF_HY신명조,\n \"HY중고딕\": PDF_HY중고딕,\n \"HY궁서\": PDF_HY궁서,\n \"휴먼고딕\": PDF_휴먼고딕,\n \"한컴 윤고딕 240\": PDF_한컴_윤고딕_240,\n \"한컴 윤고딕 250\": PDF_한컴_윤고딕_250,\n \"나눔고딕\": PDF_나눔고딕,\n \"HY울릉도M\": PDF_HY울릉도M,\n \"HY그래픽\": PDF_HY그래픽,\n \"경기천년바탕 Regular\": PDF_경기천년바탕_Regular,\n \"Arial Narrow\": PDF_Arial_Narrow,\n \"Times New Roman\": PDF_Times_New_Roman,\n \"KBL 점프체 R TTF\": TTF_KBL_JUMP_R, \"KBL 점프체 B TTF\": TTF_KBL_JUMP_B,\n}\n\n// HFT 글꼴의 영문 폭(hft-latin-widths.ts)이 영문 칸을 정한다 — 위 표의 영문 칸(PDF 실측·저장본 추정)보다 우선.\n// 표가 없던 HFT 글꼴(HCI Hollyhock·한양견명조·#신명조 등)은 한글 1em 표를 새로 만든다\nfor (const [face, w] of Object.entries(HFT_LATIN)) {\n const m = FONTS[face]\n FONTS[face] = m ? { ...m, ascii: [m.ascii[0], ...w] } : { cjk: 1000, ascii: [500, ...w], ex: {} }\n}\n\n// 글꼴별 글자 폭 보정(face-width-fix.ts)이 위 표보다 우선 — 같은 표를 나눠 쓰는 굵기(KoPub Light·Medium …)는 따로 복사한다\nfor (const [face, fix] of Object.entries(FACE_WIDTH_FIX)) {\n // 폭표가 없던 글꼴은 표를 새로 연다 — 표에 없는 영문은 반각\n const m = FONTS[face] ?? { cjk: FACE_CJK[face] ?? 1000, ascii: new Array(95).fill(500), ex: {} }, ascii = [...m.ascii], ex = { ...m.ex }\n for (const [c, w] of Object.entries(fix)) {\n const cp = Number(c)\n if (cp >= 0x20 && cp <= 0x7e) ascii[cp - 0x20] = w\n else ex[cp] = w\n }\n FONTS[face] = { ...m, ascii, ex }\n}\n\n// 굴림체·돋움체 — 두 글꼴은 글자 폭이 모두 같다. 비ASCII 반각(0.5em) 글자 359자, 나머지는 1em\n// (한컴 PDF: 두 글꼴 줄 안의 −·•·◦ 가 그 글꼴로 0.5em 에 찍힌다. 돋움체는 종전엔 고정폭 근사로 비ASCII 를 모두 1em 으로 쟀다)\nconst CHE_HALF = \"0-1f 7f a0 a2-a3 a5-a6 a9 ab-ac af b5 bb c0-c5 c7-cf d1-d6 d9-dd e0-e5 e7-ef f1-f6 f9-fd ff-110 112-125 128-130 134-137 139-13e 143-148 14c-151 \" +\n \"154-165 168-17f 192 1fa-1ff 2c6 2c9 2dc 37e 384-38a 38c 38e-390 3aa-3b0 3c2 3ca-3ce 402-40c 40e-40f 452-45c 45e-45f 490-491 1e80-1e85 1ef2-1ef3 \" +\n \"2013-2014 2017 201a-201b 201e 2022 2039-203a 203c 203e 2044 20a3-20a4 20a7 20a9 2105 212e 21a8 2206 2212 2215 2219 221f 2248 2302 2310 2320-2321 \" +\n \"2550-256c 2580 2584 2588 258c 2590-2591 2593 25aa-25ac 25ba 25c4 25ca 25d8-25d9 25e6 263a-263c 2666 266b fb01-fb02\"\nconst cheEx: Record<number, number> = { ...FONTS[\"굴림체\"].ex }\nfor (const r of CHE_HALF.split(\" \")) { const [a, b] = r.split(\"-\").map(x => parseInt(x, 16)); for (let c = a; c <= (b ?? a); c++) cheEx[c] = 500 }\nFONTS[\"굴림체\"] = FONTS[\"돋움체\"] = { ...FONTS[\"굴림체\"], ex: cheEx }\n\n// 서울남산체·서울한강체 — 한글 음절도 글자마다 폭이 다르다(seoul-font-widths.ts). 표에 없는 글자는 반각·1em 대체\n// 이미 표가 있는 이름(08서울한강체 M 등)은 그 표를 두고 빠진 글자만 채운다\nfor (const [face, wm] of Object.entries(seoulFontWidths())) {\n const m = FONTS[face], ascii = m ? [...m.ascii] : new Array(95).fill(500), ex: Record<number, number> = m ? { ...m.ex } : {}\n for (const [cp, w] of wm) { if (cp > 0x20 && cp <= 0x7e) { if (!m) ascii[cp - 0x20] = w } else if (cp > 0x7e && !(cp in ex)) ex[cp] = w }\n FONTS[face] = m ? { ...m, ex } : { cjk: 1000, ascii, ex }\n}\n\n/** 글꼴 빈칸 폭(em×1000) — useFontSpace=\"1\" 글자 모양용. 모르는 글꼴은 undefined(반각으로 잰다) */\nexport function fontSpaceEm(face: string | null | undefined): number | undefined {\n return face ? FACE_SPACE[face.trim()] : undefined\n}\n\n/** 실측 폭표가 있는 글꼴인지 */\nexport function hasFontMetrics(face: string | null | undefined): boolean {\n return !!face && Object.prototype.hasOwnProperty.call(FONTS, face.trim())\n}\n\n/** 폭표에 그 글자가 따로 있는가(영문 칸 ASCII 이거나 표의 추가 글자) */\nexport function fontHasGlyph(face: string, cp: number): boolean {\n if (!hasFontMetrics(face)) return false\n return (cp >= 0x20 && cp <= 0x7e) || FONTS[face.trim()].ex[cp] !== undefined\n}\n\n/** 코드포인트 advance(em×1000). 폭표 없는 글꼴은 null — 호출부가 근사 클래스로 폴백 */\nexport function fontAdvanceEm1000(face: string, cp: number): number | null {\n if (!hasFontMetrics(face)) return null\n const m = FONTS[face.trim()]\n if (cp >= 0x20 && cp <= 0x7e) return m.ascii[cp - 0x20]\n return m.ex[cp] ?? (HANCOM_FALLBACK_W[cp] ?? (isHalfwidthForm(cp) ? 500 : m.han !== undefined && isHanja(cp) ? m.han : m.cjk))\n}\n\n/**\n * 글꼴에 없는 글자의 대체 폭(em×1000) — 한컴은 그 글자를 한컴바탕(Haansoft Batang)으로 찍는다(한컴 PDF: 바탕·윤고딕·휴먼명조 줄 안의\n * 가운뎃점 ‧ 이 Haansoft Batang 0.173em 으로 303번). 표에 그 글자가 따로 있으면(실측 글꼴이 가진 글자) 표 값이 먼저다.\n * – ⇨ ∘ ‣ 〇 도 다른 글꼴 문단 안에서 한컴바탕으로 찍힌다(대체 글자 수집: 윤고딕·HY헤드라인M·돋움체·바탕) — 폭은 한컴바탕 /W\n * U+F0A7은 Wingdings-Regular 대체다 — 돋움체·맑은 고딕 PDF의 임베드 hmtx937/upem2048(정수 /W457).\n */\nexport const HANCOM_FALLBACK_W: Record<number, number> = { 0x2024: 173, 0x2027: 173, 0x2013: 430, 0x21e8: 1000, 0x2218: 500, 0x2023: 465, 0x3007: 1000, 0xf0a7: 937 / 2048 * 1000, 0xf09f: 937 / 2048 * 1000, 0xf06e: 1529 / 2048 * 1000 }\n/**\n * 기호 글꼴 사적 영역(U+F020~F0FF, 워드 기호 글꼴 글자)은 글꼴에 없으면 Wingdings-Regular 로 찍힌다 — 그 진행폭(hmtx, unitsPerEm 2048)이\n * 대체 폭이다(짝 PDF 20개의 이 영역 글자 전부 Wingdings-Regular: 맑은 고딕 문단 \"영양기능성분\" 의 F09E 가 1em 이 아니라 0.313em 이라\n * 한 줄에 든다). 위 표의 F0A7·F09F·F06E 와 같은 값. F0A0 은 글꼴 빈칸 폭으로 찍는다(text-metrics) — 키는 낮은 두 자리 16진\n */\nconst WINGDINGS_ADV: Record<number, string> = { 641:\"9e a0\", 789:\"fa\", 937:\"73 9f a7\", 938:\"27\", 987:\"f9\", 1086:\"7d 7e\", 1124:\"47 48\", 1135:\"35\", 1183:\"77\", 1203:\"41\", 1233:\"36\", 1301:\"fb\",\n 1332:\"53\", 1352:\"4e\", 1381:\"43 44\", 1420:\"58\", 1431:\"32 33\", 1480:\"57\", 1529:\"55 56 6c 6e 74\", 1589:\"e3 e4 e5 e6\", 1597:\"69\", 1601:\"f5 f6 f7 f8\", 1609:\"fc\", 1624:\"42\", 1627:\"59 d7 d8\",\n 1660:\"f1 f2 f4\", 1665:\"54\", 1727:\"4a 4b 4c\", 1739:\"4f\", 1787:\"eb ec ed ee\", 1803:\"52\", 1813:\"5a\", 1819:\"51\",\n 1825:\"3b 3e 5d 6f 70 71 72 76 7a a1 a2 a3 a4 a5 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 d9 da db dc dd de e1 e2 e9 ea ef f0\",\n 1826:\"29 34 3c 3d 49 5b 7b 7c 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 fd fe\", 1830:\"25\", 1834:\"5c\", 1863:\"3f 40\", 1902:\"66\", 1911:\"63\", 1924:\"3a\", 1927:\"62\", 1929:\"45 46\",\n 1937:\"64\", 1941:\"38\", 1951:\"6d a6\", 1974:\"60\", 2006:\"df e0\", 2020:\"75\", 2048:\"20 96 97 98 99 9a 9b 9c 9d cb cc cd ce cf d0 d1 d2 d3 d4\", 2099:\"65\", 2110:\"21\", 2119:\"ff\", 2146:\"c7 c8 c9 ca\",\n 2150:\"6a\", 2159:\"5f\", 2171:\"78 79 f3\", 2181:\"68\", 2186:\"e7 e8\", 2196:\"37\", 2208:\"39\", 2220:\"28\", 2230:\"50\", 2233:\"61\", 2245:\"30 67\", 2275:\"4d\", 2319:\"2a 2b\", 2344:\"22\", 2368:\"5e\", 2399:\"2c 2d\",\n 2492:\"26\", 2566:\"d5 d6\", 2603:\"6b\", 2665:\"23\", 2751:\"31\", 2752:\"24\", 2951:\"2e\", 2956:\"2f\" }\nfor (const [adv, list] of Object.entries(WINGDINGS_ADV)) for (const c of list.split(\" \")) {\n const cp = 0xf000 + parseInt(c, 16)\n if (cp !== 0xf0a0 && !(cp in HANCOM_FALLBACK_W)) HANCOM_FALLBACK_W[cp] = Number(adv) / 2048 * 1000\n}\n\n/** CJK 통합 한자(확장 A·호환 포함) */\nfunction isHanja(cp: number): boolean {\n return (cp >= 0x4e00 && cp <= 0x9fff) || (cp >= 0x3400 && cp <= 0x4dbf) || (cp >= 0xf900 && cp <= 0xfaff)\n}\n\n/**\n * 문단 계산 전에 폭표를 한 번 선택한다 — 글자마다 글꼴명 trim·조회하지 않는다.\n * fallback=false 는 글머리표 예약 폭(useInstWidth=\"0\")이다 — 비ASCII 글자는 글자별 폭·대체 폭 없이 글꼴 기본 칸 폭으로 잡는다\n * (한컴 PDF: 돋움체 글머리표 \"−\" 는 0.5em 으로 찍히는데 본문은 1em + 간격 뒤에서 시작한다)\n */\nexport function fontWidthFn(face: string, fallback = true): ((cp: number) => number) | null {\n if (!hasFontMetrics(face)) return null\n const m = FONTS[face.trim()]\n // 표에 따로 없는 반각 형태(U+FF61~FFDC·FFE8~FFEE, 「 」 ・ 등)는 반각 — 한컴 PDF 임베드 글꼴 실측 500\n return cp => cp >= 0x20 && cp <= 0x7e ? m.ascii[cp - 0x20] : (fallback ? m.ex[cp] ?? HANCOM_FALLBACK_W[cp] : undefined) ?? (isHalfwidthForm(cp) ? 500 : m.han !== undefined && isHanja(cp) ? m.han : m.cjk)\n}\n\n/** 유니코드 반각 형태 블록 */\nexport function isHalfwidthForm(cp: number): boolean {\n return (cp >= 0xff61 && cp <= 0xffdc) || (cp >= 0xffe8 && cp <= 0xffee)\n}\n","/**\n * 한글 조판 텍스트 폭 계산 — 함초롬바탕(HCR Batang) 실측 advance 테이블\n *\n * 공문서 표준 본문 글꼴인 함초롬바탕 정품 TTF(한컴 공개 배포)의 hmtx advance를\n * upem=1000 기준으로 추출한 값이다. Bold도 advance가 Regular와 완전히 동일함을\n * 전수 확인했다(한컴이 굵기 간 폭을 통일해 제작). 한글 음절 11,172자 전수 = 970,\n * 한자 = 1000, 전각형·원문자·도형·화살표·단위기호 = 970으로 균일하다.\n *\n * 단위: em×1000. 실제 폭(HWPUNIT) = w/1000 × charPr.height × ratio(장평)/100.\n * (1em = 글자크기 = charPr.height HWPUNIT — 1pt = 100 HWPUNIT이므로)\n *\n * 공백: HWP는 charPr useFontSpace=0(기본)일 때 글꼴의 space advance(0.30em) 대신\n * 반각 고정폭(0.50em)을 쓴다 — kordoc 생성 문서는 모두 useFontSpace=0이므로\n * 기본 SPACE_EM=500. (글꼴값을 쓰려면 measure 옵션 fontSpace로 300 지정)\n *\n * 다른 글꼴(맑은 고딕 등)도 한글=전각 균일·숫자≈0.55em의 동일 부류 구조라\n * 이 테이블로 근사한다(오차 수 % 이내 — 공문서 본문은 어차피 함초롬바탕 관행).\n */\n\nimport { HANCOM_FALLBACK_W, fontWidthFn, hasFontMetrics, isHalfwidthForm } from \"./font-metrics.js\"\n\n/** ASCII 0x20~0x7E advance (em×1000). 0x20은 useFontSpace=1일 때의 글꼴값(300) */\nconst ASCII_W = [\n 300, 320, 320, 610, 610, 830, 724, 320, 320, 320, 550, 550, 320, 550, 320, 550, // 0x20-0x2F\n 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 320, 320, 550, 550, 550, 550, // 0x30-0x3F\n 830, 706, 605, 685, 719, 627, 617, 683, 734, 305, 315, 660, 605, 839, 734, 732, // 0x40-0x4F\n 603, 705, 660, 627, 664, 731, 706, 910, 705, 705, 626, 320, 550, 320, 550, 550, // 0x50-0x5F\n 320, 569, 597, 552, 597, 536, 356, 562, 635, 287, 288, 582, 287, 907, 635, 588, // 0x60-0x6F\n 597, 579, 478, 496, 356, 635, 563, 720, 542, 543, 486, 320, 320, 320, 550, 0, // 0x70-0x7E(+DEL)\n]\n\n/** 개별 실측 예외 기호 (em×1000) */\nconst SYM_W: Record<number, number> = {\n 0xa0: 300, 0xa3: 568, 0xa5: 707, 0xa7: 498, 0xab: 440, 0xac: 564, 0xb0: 291,\n 0xb1: 798, 0xb6: 606, 0xb7: 320, 0xbb: 440, 0xd7: 617, 0xf7: 678,\n 0x2013: 625, 0x2014: 875, 0x2015: 875, 0x2018: 320, 0x2019: 320, 0x201c: 480, 0x201d: 480,\n 0x2020: 558, 0x2021: 438, 0x2025: 640, 0x2026: 960, 0x2030: 988, 0x2032: 335, 0x2033: 474,\n 0x203b: 770, 0x20ac: 656, 0x261c: 1012, 0x261e: 1012,\n 0x274d: 970, // ❍ 2단계 부호(일부 중앙부처) — 미실측, ○ 와 같은 전각으로 둔다\n // 한컴 PDF 임베드 HCRBatang /W 실측 — 종전 기본값 550 으로 떨어지던 기호\n 0x2bc: 164, 0x2022: 399, 0x2023: 369, 0x2024: 289, 0x2027: 289,\n}\n\n/** 코드포인트의 advance(em×1000). 미상 문자는 CJK권 970 / 라틴권 550 폴백 */\nexport function charWidthEm1000(cp: number): number {\n if (cp >= 0x20 && cp <= 0x7e) return ASCII_W[cp - 0x20]\n const sym = SYM_W[cp]\n if (sym !== undefined) return sym\n if (isHalfwidthForm(cp)) return 500 // 반각 형태 「 」 ・\n if (cp >= 0xac00 && cp <= 0xd7a3) return 970 // 한글 음절 (전수 균일 확인)\n if (cp >= 0x1100 && cp <= 0x11ff) return 970 // 옛한글 자모\n if (cp >= 0x3131 && cp <= 0x318e) return 970 // 호환 자모 (ㆍ 포함)\n if ((cp >= 0x4e00 && cp <= 0x9fff) || (cp >= 0xf900 && cp <= 0xfaff)) return 1000 // 한자\n if ((cp >= 0x3008 && cp <= 0x3011) || (cp >= 0x3014 && cp <= 0x301b)) return 500 // 「」『』〈〉《》〔〕【】\n if (cp === 0x3000) return 970 // 전각 공백\n if (cp >= 0x2160 && cp <= 0x2183) return 970 // 로마숫자 Ⅰ~Ⅻ (한글 글꼴 전각)\n if (cp >= 0x2190 && cp <= 0x22ff) return 970 // 화살표·수학 기호\n if (cp >= 0x2460 && cp <= 0x24ff) return 970 // 원문자 ①⑴\n if (cp >= 0x25a0 && cp <= 0x26ff) return 970 // 도형 □○◆★\n if (cp >= 0x3200 && cp <= 0x33ff) return 970 // 괄호한글 ㉮·단위 ㎡㎏\n if (cp >= 0xff01 && cp <= 0xff60) return 970 // 전각형 !~\n // 기술 기호 ⌜⌟·상자 선 ━│┌·딩뱃 ❶➊➀ 는 전각(한컴 PDF HCRBatang 실측 970), 한컴 사용자 기호(보충 사용 영역)는 반각 몫 485\n if ((cp >= 0x2300 && cp <= 0x23ff) || (cp >= 0x2500 && cp <= 0x259f) || (cp >= 0x2700 && cp <= 0x27bf)) return 970\n if (cp >= 0xf0000) return 485\n return cp >= 0x2e80 ? 970 : 550\n}\n\n/** 폭 없는 문자 — 폭 없는 공백·연결자(U+200B~200D·2060·FEFF)와 결합 부호(U+0300~036F). 어느 글꼴로 재든 0(한컴 PDF 실측 0) */\nfunction isZeroWidthCp(cp: number): boolean {\n return (cp >= 0x200b && cp <= 0x200d) || cp === 0x2060 || cp === 0xfeff || (cp >= 0x300 && cp <= 0x36f)\n}\n\n/** HWP 공백 폭(em×1000) — useFontSpace=0(기본): 반각 고정 500 / =1: 글꼴값 300 */\nexport const SPACE_EM_FIXED = 500\nexport const SPACE_EM_FONT = 300\n\n/**\n * 폭 테이블 클래스 — 'hcr'(함초롬 실측, 기본) / 'fixedPitch'(고정폭 글꼴:\n * ASCII 0.5em·그 외 1.0em). 굴림체·돋움체·바탕체·궁서체('체' 접미 = 고정폭)와 옛 HFT 기본 글꼴 명조·고딕이\n * 대상 — 전자결재 변환기 산출물의 지배 본문 글꼴. 한글이 HCR(0.97em)보다 3%\n * 넓어 함초롬 테이블로 재면 줄당 1~2자 과대적재로 wrap 지점이 어긋난다\n * (bench/verify-linebreak.mjs seoul 코퍼스 실측: fixedPitch 테이블로 74/75 일치. 한컴 저장본 HFT 명조 문단 1,782개 중 1,776개·고딕 89개 중 83개 일치).\n */\nconst FIXED_PITCH_FACES = /^(굴림체|돋움체|바탕체|궁서체|명조|고딕)$/\nexport type FaceClass = \"hcr\" | \"fixedPitch\" | \"gothic\" | \"cjk\" | `font:${string}`\n\n/**\n * HWP 글꼴명 → 폭 테이블 클래스. 미상/미지정은 hcr (기존 동작 불변).\n * 'gothic'(v5): 한컴돋움·맑은 고딕·HY견고딕·HY헤드라인M 등 굵은 고딕 — 한글 1.0em·ASCII 0.6em으로\n * 함초롬(0.97/0.55)보다 넉넉히 잡는다. 표 열폭·□ 한 줄 맞춤이 실렌더보다 좁게 재어 꺾이던 것 방지.\n */\nexport function faceClassOf(face: string | null | undefined): FaceClass {\n if (face && hasFontMetrics(face)) return `font:${face.trim()}`\n return face && FIXED_PITCH_FACES.test(face.trim()) ? \"fixedPitch\" : \"hcr\"\n}\n\n/**\n * 진하게(bold) 글자의 폭 더하기(em×1000) — 굵은 글꼴이 따로 없는 옛 HFT 글꼴(한양·휴먼 계열(휴먼명조 제외)·명조·고딕·필기)은\n * 한컴이 획을 두껍게 그리며 글자마다 폭을 50 넓힌다(한글 2022 줄 나눔: 고딕·명조·한양신명조·휴먼명조, 크기 600~1700·자간 −9~+5·장평 90~100\n * 같은 글자 반복 문단 323개가 모두 50 에서만 맞는다 — 46 이면 55개가 한 글자씩 더 든다),\n * 굵은 글꼴이 있는 바탕·맑은 고딕·함초롬·휴먼명조 등은 더하면 나빠진다. 휴먼명조도 글꼴 항목이 HFT(fontface font type=\"HFT\")면 굵은 글꼴이\n * 없어 넓힌다(TTF 휴먼명조와 HFT 휴먼명조를 함께 쓰는 문서 27개: 휴먼명조 문단 줄 시작 일치 88.9% → 91.5%).\n * HFT 항목의 #세나루·강낭콩(HWP 3 문서 영문·제목 글꼴)·HCI Tulip·신명 태고딕도 넓힌다(두 줄 이상 문단 +16·+2·+4).\n * 휴먼 계열(휴먼고딕 등)도 휴먼명조처럼 HFT 항목일 때만 넓힌다 — TTF 휴먼고딕은 굵은 글꼴이 있다(보도자료 휴먼고딕 TTF 진하게 문단 +6)\n * 한양 계열도 HFT 항목일 때만 — TTF 한양해서(HYhaeseo)는 넓히지 않는다(한글 2022 재조판: 시험지 굵은 한양해서 줄)\n */\nexport function syntheticBoldEm(face: string | null | undefined, hft = false): number {\n if (!face) return 0\n const f = face.trim()\n return /^(명조|고딕|필기)$/.test(f) || (hft && (/^(한양|휴먼)/.test(f) || /^(#세나루|강낭콩|HCI Tulip|신명 태고딕)$/.test(f))) ? 50 : 0\n}\n\n/** 한컴 글꼴의 영문 이름 → 한글 이름(같은 글꼴). 한컴 PDF 에 같은 이름으로 박히고 폭도 같다(Haansoft Batang 괄호 0.5em = 한컴바탕) */\nconst REFLOW_FACE_ALIAS: Record<string, string> = {\n \"Haansoft Batang\": \"한컴바탕\", \"Haansoft Dotum\": \"한컴돋움\", \"HCR Batang\": \"함초롬바탕\", \"HCR Dotum\": \"함초롬돋움\",\n}\n\n/**\n * reflow(조판 캐시 없는 문단) 폭 클래스 — 실측 폭표·고정폭은 faceClassOf 와 같고, 폭표 없는 한글 글꼴은 'cjk'(한글 1em).\n * 함초롬만 함초롬 폭으로 둔다. 한컴 저장본 두 줄 이상 문단 22,577개 대조: 줄 시작 전부 일치 39.4% → 49.8%(이 클래스만)\n */\nexport function faceClassForReflow(face: string | null | undefined): FaceClass {\n face = face && (REFLOW_FACE_ALIAS[face.trim()] ?? face)\n const c = faceClassOf(face)\n if (c !== \"hcr\" || !face || /^함초롬/.test(face.trim())) return c\n return \"cjk\"\n}\n\n/**\n * 생성(v5) 전용 폭 클래스 — 렌더(reflow)는 faceClassOf 그대로(게이트 baseline 불변).\n * 실측 폭표(font-metrics.ts)가 있는 글꼴은 그 표(`font:이름`), 없으면 근사 클래스 — 굵은 고딕 계열은\n * 'gothic'으로 넉넉히 재어 표 열폭·□ 한 줄 맞춤이 실렌더에서 꺾이지 않게 한다.\n * 폭표 없는 그 밖의 글꼴(바탕·한양신명조 …)도 'gothic'(한글 1em) — 함초롬 계열만 한글 0.97em 이고 실측한 다른 한글 글꼴 7종은\n * 전부 1em 이라, 함초롬 폭으로 재면 □ 한 줄 맞춤이 실렌더에서 넘친다(기관 서식 국세청 □ 바탕 14pt, 조판 예측기와 같은 가정).\n */\nexport function faceClassForGen(face: string | null | undefined): FaceClass {\n if (!face) return \"hcr\"\n const f = face.trim()\n if (hasFontMetrics(f)) return `font:${f}`\n if (FIXED_PITCH_FACES.test(f)) return \"fixedPitch\"\n if (/^함초롬/.test(f)) return \"hcr\"\n return \"gothic\"\n}\n\n/**\n * 고딕 근사 advance(em×1000) — 한컴돋움·맑은 고딕 계열 실렌더 대비 보수적으로:\n * 대문자 0.72 · 소문자 0.56 · 숫자 0.58 · 괄호 0.35 · 마침표류 0.28 · 그 외 ASCII 0.5 · 전각 1.0\n * (실측: \"DT_1YL21161\" 한컴돋움 12pt 셀이 함초롬 테이블(0.55)로는 25% 좁게 재어져 글자 분해)\n */\nfunction gothicWidthEm1000(cp: number): number {\n if (cp >= 0x80) return 1000\n if (cp >= 0x41 && cp <= 0x5a) return 720\n if (cp >= 0x61 && cp <= 0x7a) return 560\n if (cp >= 0x30 && cp <= 0x39) return 580\n if (cp === 0x28 || cp === 0x29 || cp === 0x5b || cp === 0x5d) return 350\n if (cp === 0x2e || cp === 0x2c || cp === 0x3a || cp === 0x3b || cp === 0x27) return 280\n return 500\n}\n\n/** 폭표 없는 한글 글꼴 advance(em×1000) — 자모·한글·한자·전각 기호(U+1100 이후)는 1em, 그 아래(ASCII·라틴)는 함초롬 폭.\n * 실측 한글 글꼴(바탕·돋움·한양신명조·HY신명조·한컴바탕 …)의 음절 폭은 1em 이고 함초롬 계열만 0.97em 이다 */\nfunction cjkWidthEm1000(cp: number): number {\n return isHalfwidthForm(cp) ? 500 : cp >= 0x1100 ? 1000 : charWidthEm1000(cp)\n}\n\n/** 고정폭 글꼴 advance(em×1000) — ASCII 반각 500, 그 외 전각 1000 */\nfunction fixedPitchWidthEm1000(cp: number): number {\n return cp < 0x80 || isHalfwidthForm(cp) ? 500 : 1000\n}\n\n/** 보충 사용자 영역에서 전각으로 조판되는 한컴 기호 — U+F0000~F02FB·U+F035F~F03F4(글머리 동그라미 숫자·가운데점 등), 그 밖은 반각 */\nconst isPuaFull = (cp: number): boolean => cp <= 0xf02fb || (cp >= 0xf035f && cp <= 0xf03f4)\n\n/** 폭 클래스 → advance 함수. `font:이름` 은 실측 폭표(없는 글꼴명이면 gothic 근사) */\nfunction widthFnOf(faceClass: FaceClass | undefined, fallback = true): (cp: number) => number {\n const base = baseWidthFnOf(faceClass, fallback)\n // 한컴 사용자 기호(보충 사용 영역 U+F0000~, HWP3 기호 글자)는 어느 글꼴로 재든 반각 0.5em — 폭표 글꼴은 이 글자가 없어 1em 으로 잡혔다\n // (한컴 PDF: 한양신명조 머리말 기호 85자 뒤 그림 x = 왼 여백 + 85 × 0.503em)\n // 단 U+F0000~F02FB·U+F035F~F03F4 는 전각 1em(한컴 PDF: \"󰊵 인력 양성\" 기호 폭 14.94pt / 15pt 글자, 맑은 고딕 12pt 글머리\n // 가운데점 U+F02EF 11.64pt. 글머리 동그라미 숫자 7자만 1em 으로 재면 두 줄+ 문단 +10·렌더 글 위치 +0.8%p, U+F02FC 부터는 반각이 맞다)\n // 딩뱃 원문자 ❶~➓(U+2776~2793)는 함초롬 글꼴(970)·한컴바탕에만 있다 — 다른 글꼴은 한컴바탕으로 대체돼 1em\n // (한컴 PDF: 한컴 윤고딕 230 문단의 ➌ 이 Haansoft Batang 15pt 로 15.0pt)\n const hcr = faceClass === \"hcr\" || faceClass === \"font:함초롬돋움\" || faceClass === \"font:함초롬바탕\"\n // 기호 사설 영역의 U+F0A0(워드 기호 글꼴의 묶음 빈칸)은 그 글꼴의 빈칸 폭 — 한컴 PDF: 함초롬바탕 14pt 자간 −8 칸 글 안의 U+F0A0 이\n // U+00A0 로 3.96pt(= 0.3em 빈칸 388 + 격자). 1em 으로 재면 한 줄 칸 글이 두 줄로 꺾였다\n const f = (cp: number): number => (cp >= 0xf0000 ? (isPuaFull(cp) ? 1000 : 500) : cp === 0xf0a0 ? base(0x20) : !hcr && cp >= 0x2776 && cp <= 0x2793 ? 1000 : base(cp))\n // 실측 폭표 없는 reflow 근사 클래스(고정폭·한글 1em)도 글꼴에 없는 글자는 한컴바탕 대체 폭 — 함초롬(hcr)은 그 글자를 가진다\n if (fallback && (faceClass === \"fixedPitch\" || faceClass === \"cjk\")) return cp => (isZeroWidthCp(cp) ? 0 : HANCOM_FALLBACK_W[cp] ?? f(cp))\n return cp => (isZeroWidthCp(cp) ? 0 : f(cp))\n}\n\nfunction baseWidthFnOf(faceClass: FaceClass | undefined, fallback = true): (cp: number) => number {\n if (faceClass === \"fixedPitch\") return fixedPitchWidthEm1000\n if (faceClass === \"gothic\") return cp => (isHalfwidthForm(cp) ? 500 : gothicWidthEm1000(cp))\n if (faceClass === \"cjk\") return cjkWidthEm1000\n if (faceClass?.startsWith(\"font:\")) {\n const face = faceClass.slice(5)\n return fontWidthFn(face, fallback) ?? gothicWidthEm1000\n }\n return charWidthEm1000\n}\n\n/** 공백류 — 일반 공백과 묶음 빈칸(U+00A0 → hp:nbSpace)은 한컴 고정 반각 공백 폭 */\nfunction isSpaceCp(cp: number): boolean {\n return cp === 0x20 || cp === 0xa0\n}\n\nexport interface MeasureOptions {\n /** 공백 폭(em×1000). 기본 SPACE_EM_FIXED(500) = useFontSpace 0 */\n spaceEm?: number\n /** 자간(charPr spacing %) — 글자폭의 %가 문자마다 추가 */\n spacingPct?: number\n /** 폭 테이블 클래스 — 기본 'hcr' (함초롬 실측 테이블) */\n faceClass?: FaceClass\n}\n\n/**\n * 텍스트 폭(HWPUNIT). height=charPr height(pt×100), ratioPct=장평 %.\n * 결과는 float — 호출부에서 비교 시 ±0.5 HWPUNIT 오차 허용 권장.\n */\nexport function measureTextWidth(\n text: string,\n height: number,\n ratioPct: number,\n opts?: MeasureOptions,\n): number {\n const spaceEm = opts?.spaceEm ?? SPACE_EM_FIXED\n const spacing = opts?.spacingPct ?? 0\n const widthEm = widthFnOf(opts?.faceClass)\n let em = 0\n for (const ch of text) {\n const cp = ch.codePointAt(0)!\n // 고정폭 빈칸(U+2005)은 1/4em — hancomCharWidth 와 같다(한컴 PDF: \"【\"+고정폭 빈칸 10.5pt, 15pt 글자)\n const w = cp === 0x2005 ? 250 : isSpaceCp(cp) ? spaceEm : widthEm(cp)\n em += w * (1 + spacing / 100)\n }\n return (em / 1000) * height * (ratioPct / 100)\n}\n\n/** MulDiv — 반올림(0 에서 멀어지는 쪽) */\nexport function mulDiv(a: number, b: number, c: number): number {\n const e = a * b\n return Math.trunc(e < 0 ? (e - c / 2) / c : (e + c / 2) / c)\n}\n\n/**\n * 한컴 조판의 글자 폭(HWPUNIT) — 글자마다 4 단위로 양자화한다(한컴 저장본 줄 나눔과 맞는 산식).\n * 글자: 장평 100 이면 4·MulDiv(폭, ⌊크기/4⌋, 1000), 아니면 4·⌊폭·⌊크기/4⌋·장평/(100·1000)⌋.\n * 공백(useFontSpace 0): 4·⌊크기/8⌋ (장평 ≠ 100 이면 4·MulDiv(⌊크기/8⌋, 장평, 100)). 자간: + 4·MulDiv(⌊폭/4⌋, 자간, 100)\n */\nexport function hancomCharWidth(ch: string, height: number, ratioPct: number, spacingPct: number, faceClass?: FaceClass, emAdd = 0, fallback = true): number {\n // emAdd: 글자 폭(em×1000)에 더하는 몫 — 합성 굵기(syntheticBoldEm). 공백에는 붙지 않는다\n const cp = ch.codePointAt(0)!\n let w: number\n if (cp === 0x2005) {\n // 고정폭 빈칸(hp:fwSpace → U+2005) — 1/4em, 어절 경계이며 줄 끝에 걸칠 수 있다. 장평·자간은 공백처럼 받는다\n // (코퍼스 fwSpace 문단 816개: 공백 0.5em 으로 재면 두 줄+ 67.5%, 1/4em 89.6% — 0.2~0.25em 이 평탄한 꼭대기)\n const s = Math.trunc(height / 16)\n w = 4 * (ratioPct === 100 ? s : mulDiv(s, ratioPct, 100))\n } else if (isSpaceCp(cp)) {\n const s = Math.trunc(height / 8)\n w = 4 * (ratioPct === 100 ? s : mulDiv(s, ratioPct, 100))\n } else return hancomEmWidth(widthFnOf(faceClass, fallback)(cp) + emAdd, height, ratioPct, spacingPct)\n if (spacingPct) w += 4 * mulDiv(Math.trunc(w / 4), spacingPct, 100)\n return w\n}\n\n/** 폭(em×1000)이 정해진 글자의 한컴 조판 폭 — hancomCharWidth 의 글자 산식 */\nexport function hancomEmWidth(em: number, height: number, ratioPct: number, spacingPct: number): number {\n const q = Math.trunc(height / 4)\n let w = ratioPct === 100 ? 4 * mulDiv(em, q, 1000) : 4 * Math.trunc(em * q * ratioPct / 100000)\n if (spacingPct) w += 4 * mulDiv(Math.trunc(w / 4), spacingPct, 100)\n return w\n}\n\n// ─── 줄바꿈 시뮬레이션 (한컴 조판 모델 — 실측 linesegarray 98% 일치 검증) ───\n//\n// 검증: bench/verify-linebreak.mjs — 서울 정보소통광장 실제 결재문서의 linesegarray\n// (한컴 계열 조판기가 계산한 줄 시작 오프셋)와 대조. 고정폭 글꼴 버킷에서 98%\n// (56/57 줄바꿈점, 미스는 코퍼스 좌표계 노이즈) 일치. 이 과정에서 확정된 규칙:\n// - 공백 폭 = 0.5em 고정(useFontSpace=0), 장평·자간 모두 공백에도 적용\n// - 자간 = 글자폭 × (1+spacing/100)\n// - 줄 끝 공백은 hang (줄바꿈을 유발하지 않음)\n// - 금칙: 시작금칙(닫는 부호 줄머리 금지)은 직전 글자 1개를 동반해 다음 줄로\n// (밀어내기), 끝금칙(여는 괄호 줄끝 금지)은 그 글자를 다음 줄로 내림\n\n/** 줄머리 금지(시작금칙) 문자 — 한컴 기본 */\nconst FORBID_START = new Set([...\"!%),.:;?]}¢°′″℃〉》」』】〕!%),.:;?]}₩~…·、。〃\"])\n/** 줄끝 금지(끝금칙) 문자 — 한컴 기본 */\nconst FORBID_END = new Set([...\"$([{£¥〈《「『【〔$([{₩\"])\n\n/** 한컴 기본 금칙 집합(한컴 기본값) — 줄머리 금지 */\nconst HANCOM_FORBID_START = new Set([...\"!%),.:;>?]^`}~°·〉》」』】〕〗〙〛・!%),.:;>?]^`}~・ぁぃぅぇぉっゃゅょゎァィゥェォッャュョヮヵヶ、。〃々ー゛゜ゝゞヽヾ’”․‥…‰‱′″‴‵‶‷℃℉\"])\n/** 한컴 기본 금칙 집합 — 줄끝 금지(통화 기호 U+20A0~20AC 포함) */\nconst HANCOM_FORBID_END = new Set([...\"(<[\\\\{§‘“〈《「『【〔〖〘〚$(<[\{¢£¥₩$¢£¤¥৲৳฿\", ...Array.from({ length: 13 }, (_, i) => String.fromCharCode(0x20a0 + i))])\n\nexport type WrapMode = \"keep\" | \"charAll\"\n\nconst isWrapSpace = (ch: string | undefined): boolean => ch === \" \" || ch === \"\\u2005\"\n\ninterface PreparedWrap { units: string[]; advances: number[]; steps: number[] }\n\n/** 한 문단의 장평·자간 후보 사이에서 문자 해독과 글꼴 폭표 조회만 재사용한다. */\nexport function prepareWrap(text: string, mode: WrapMode, opts?: MeasureOptions): PreparedWrap {\n const widthEm = widthFnOf(opts?.faceClass), spaceEm = opts?.spaceEm ?? SPACE_EM_FIXED\n const advances: number[] = [], steps: number[] = []\n let i = 0\n for (const ch of text) {\n const cp = ch.codePointAt(0)!\n advances[i] = cp === 0x2005 ? 250 : isSpaceCp(cp) ? spaceEm : widthEm(cp)\n steps[i] = ch.length\n i += ch.length\n }\n return { units: splitWrapUnits(text, mode), advances, steps }\n}\n\nfunction splitWrapUnits(text: string, mode: WrapMode, latinBreak = false): string[] {\n // 영문 단어 끊기(breakLatinWord=\"BREAK_WORD\" — 영문은 이름 그대로): 영문 글자도 한 글자씩 끊는다\n // 글자 단위에서 폭 없는 컨트롤(U+2060 — 하이퍼링크 필드 시작 등)은 뒤 글자와 한 단위 — 한컴은 그 컨트롤을 다음 줄 머리에 둔다\n // (한컴 저장 lineseg: 각주 끝 \" \" 뒤 하이퍼링크 URL 의 줄 시작이 필드 시작 컨트롤 자리. 두 줄 이상 문단 +32)\n if (latinBreak) return text.match(mode === \"keep\" ? /[ \\u2005]+|[\\x21-\\x7e]|[^ \\u2005\\x21-\\x7e]+/gu : /[ \\u2005]+|[^ \\u2005](?:\\u00a0[^ \\u2005\\u00a0]?)*/gu) ?? []\n // 글자 단위에서도 영문(ASCII 와 한컴 언어 분류 '영문' — U+00A1~024F, ‘’“” 등 U+2018~201F)이 이어지면 한 단어다\n // (한글 2022 줄 나눔: \"’’’…\"·\"···…\" 문단은 긴 단어로 쪼개져 금칙 없이 줄마다 들어가는 만큼 든다. 두 줄 이상 문단 +13, 2022 재조판 +14)\n // 낱말 머리의 필드 끝(U+FDD0)은 따로 — 앞 줄 끝에 붙고 뒤 낱말만 다음 줄로 간다(누름틀 끝 + 줄보다 넓은 표)\n return text.match(mode === \"keep\" ? /[ \\u2005]+|\\ufdd0+(?=[^ \\u2005\\ufdd0])|[^ \\u2005]+/gu : /[ \\u2005]+|\\u2060*(?:[\\x21-\\x7e\\u00a1-\\u024f\\u2018-\\u201f]+|[^ \\u2005])(?:\\u00a0(?:[\\x21-\\x7e\\u00a1-\\u024f\\u2018-\\u201f]+|[^ \\u2005\\u00a0])?)*/gu) ?? []\n}\n\nexport interface WrapOptions extends MeasureOptions {\n /** UTF-16 단위별 실폭(HWPUNIT) — 주면 height·장평·폭 클래스 대신 쓴다(여러 run 문단, 탭 전진폭) */\n widths?: number[]\n /** 같은 text·mode·글꼴·공백 폭으로 준비한 원 폭 — 한 문단 압축 후보에만 재사용 */\n prepared?: PreparedWrap\n /** 공백 최소값(paraPr condense, %) — 줄 가용폭에 그 줄 공백 폭 합 × condense% 를 더한다 */\n condensePct?: number\n /** 금칙 집합 — 'hancom' 이면 한컴 기본 집합(reflow), 아니면 생성기 실측 집합 */\n kinsoku?: \"hancom\"\n /** 오른쪽 탭 자리 — 그 뒤 글은 한컴이 탭 자리에 맞춰 놓으므로 넘침 판정에서 마지막 글자 자간을 빼지 않는다 */\n rightTabs?: Set<number>\n /** 한글 2024 이전 판 저장 문서 — 금칙 규칙이 다르다(영문 단어 안 쪼개기엔 금칙 없음, 줄머리 금지 글자는 최대 둘까지 함께 내림) */\n before2024?: boolean\n /** widths 중 자간 몫(UTF-16 단위별) — 한컴은 넘침 판정에 마지막 글자의 자간을 넣지 않는다(판정 뒤 x 에 더한다) */\n spacings?: number[]\n /** 줄 번호(0부터)별 가용 폭 — 주면 firstWidth·contWidth 대신 쓴다(떠 있는 개체 둘레로 줄이 좁아질 때) */\n lineWidth?: (line: number) => number\n /** 영문 단어도 글자 단위로 끊는다(breakLatinWord=\"BREAK_WORD\") */\n latinBreak?: boolean\n}\n\nexport interface WrapResult {\n /** 줄 수 */\n lines: number\n /** 각 줄의 시작 오프셋(UTF-16) — [0, …] */\n starts: number[]\n /** 마지막 줄 텍스트 폭(HWPUNIT) */\n lastLineWidth: number\n}\n\n/**\n * 문단 줄바꿈 시뮬레이션.\n * mode 'keep' = 어절 단위(공문서 모드 — 저장 속성 breakNonLatinWord=\"BREAK_WORD\", 이름 역전 주의),\n * mode 'charAll' = 글자 단위(breakNonLatinWord=\"KEEP_WORD\" — 한글 기본값·전자결재 변환기).\n * 한 어절이 줄보다 길면 keep에서도 글자 단위로 강제 분해 — 한컴처럼 다음 줄로 넘긴 뒤 쪼갠다(앞 줄은 벌어진다).\n *\n * @param text 문단 전체 텍스트(항목 부호 포함)\n * @param firstWidth 첫 줄 가용 폭(HWPUNIT)\n * @param contWidth 둘째 줄부터 가용 폭(HWPUNIT) — 내어쓰기 반영\n * @param height charPr height (pt×100)\n * @param ratioPct 장평 %\n */\nexport function simulateWrap(\n text: string,\n firstWidth: number,\n contWidth: number,\n height: number,\n ratioPct: number,\n mode: WrapMode = \"keep\",\n opts?: WrapOptions,\n): WrapResult {\n // 강제 줄바꿈(\\n — hp:lineBreak): 그 뒤는 새 줄이다. 조각마다 따로 채우고 \\n(폭 0)은 앞 줄 끝에 남긴다\n if (!opts?.prepared && text.includes(\"\\n\")) {\n const starts: number[] = []\n let off = 0, lastLineWidth = 0\n for (;;) {\n const end = text.indexOf(\"\\n\", off), stop = end < 0 ? text.length : end, li = starts.length\n const lw = opts?.lineWidth\n const sub = simulateWrap(text.slice(off, stop), li === 0 ? firstWidth : contWidth, contWidth, height, ratioPct, mode, {\n ...opts,\n widths: opts?.widths?.slice(off, stop),\n spacings: opts?.spacings?.slice(off, stop),\n lineWidth: lw ? (i: number) => lw(li + i) : undefined,\n })\n for (const st of sub.starts) starts.push(off + st)\n lastLineWidth = sub.lastLineWidth\n if (end < 0) break\n off = end + 1\n }\n return { lines: starts.length, starts, lastLineWidth }\n }\n const EPS = 0.5\n const spaceEm = opts?.spaceEm ?? SPACE_EM_FIXED\n const spacing = opts?.spacingPct ?? 0\n const prepared = opts?.prepared\n const widthEm = prepared ? null : widthFnOf(opts?.faceClass)\n const k = (height * ratioPct) / 100 / 1000\n const unitW = opts?.widths\n const forbidStart = opts?.kinsoku === \"hancom\" ? HANCOM_FORBID_START : FORBID_START\n const forbidEnd = opts?.kinsoku === \"hancom\" ? HANCOM_FORBID_END : FORBID_END\n const condense = opts?.condensePct ?? 0\n /** 한컴 조판 모드(reflow) — 한컴 금칙 집합과 공백에서 줄 끝내기 규칙 */\n const hancom = opts?.kinsoku === \"hancom\"\n const spAt = opts?.spacings\n /** [from, to) 마지막 글자의 자간 몫 — 넘침 판정에서 뺀다 */\n const lastSp = (from: number, to: number): number => {\n if (!spAt || to <= from) return 0\n // 그 줄에서 오른쪽 탭을 지난 글은 한컴이 탭 자리에 맞춰 놓는다 — 마지막 글자 자간을 빼지 않는다(한글 2022: 차례 \"…한계⇥ 2\" 가 줄 폭에 꼭 맞아 한 줄)\n if (opts?.rightTabs?.size) for (const t of opts.rightTabs) if (t >= lineStart() && t < to) return 0\n let i = to - 1\n if (i > from && /[\\uDC00-\\uDFFF]/.test(text[i])) i--\n return spAt[i] ?? 0\n }\n /** i 위치(UTF-16) 글자 ch 의 폭 — widths 가 있으면 그 값(서로게이트 쌍은 두 칸 합) */\n const charWAt = (i: number, ch: string): number => {\n if (unitW) return (unitW[i] ?? 0) + (ch.length === 2 ? unitW[i + 1] ?? 0 : 0)\n if (prepared) return prepared.advances[i] * (1 + spacing / 100) * k\n const cp = ch.codePointAt(0)!\n return (cp === 0x2005 ? 250 : isSpaceCp(cp) ? spaceEm : widthEm!(cp)) * (1 + spacing / 100) * k\n }\n const rangeW = (from: number, to: number): number => {\n let w = 0\n if (prepared && !unitW) {\n for (let i = from; i < to; i += prepared.steps[i]) w += prepared.advances[i] * (1 + spacing / 100) * k\n return w\n }\n for (let i = from; i < to;) {\n const ch = String.fromCodePoint(text.codePointAt(i)!)\n w += charWAt(i, ch)\n i += ch.length\n }\n return w\n }\n\n // u 플래그 필수 — 없으면 astral 문자(𝐀·이모지 등)가 서로게이트 반쪽 2개로 쪼개져 폭이 2배로 계산된다.\n // 글자 단위에서도 ASCII 연속열(\"1.):\", \"LLM),\")은 한 단어 — breakLatinWord=KEEP_WORD(한글 2024 실렌더 PDF 대조).\n // 묶음 빈칸(U+00A0)은 어느 모드에서도 끊지 않는다 — 글자 단위에선 앞뒤 단위를 하나로 묶는다\n const units = prepared?.units ?? splitWrapUnits(text, mode, opts?.latinBreak)\n\n const starts = [0]\n let lineW = 0\n const lineWidth = opts?.lineWidth\n let avail = lineWidth ? lineWidth(0) : firstWidth\n let pos = 0\n /** 지금 줄의 공백 폭 합 — 공백 최소값(condense)만큼 공백이 줄어 가용폭이 늘어난다. 자간을 빼기 전 공백 폭으로 잰다\n * (한컴 저장 lineseg: 자간 −3% 공백 572(자간 전 588)인 공백 최소값 50% 문단이 588 로 재야 42자 — 두 줄 이상 문단 줄 시작 24,143 → 24,209) */\n let spaceW = 0\n /** 이 줄에 공백 아닌 글자가 나왔는가 — 한컴은 줄 첫머리 공백을 공백 최소값 합에 넣지 않는다 */\n let realSeen = false\n /** 한컴: 공백에 닿았을 때 이미 줄 폭에 닿아 이 줄이 끝남 — 다음 낱말은 공백 최소값으로 남는 폭이 있어도 다음 줄로 */\n let lineEnded = false\n /** 이 줄에 놓인 공백 아닌 단위 수 — 한컴은 폭 0 컨트롤도 줄의 내용으로 쳐서, 그 뒤에서 넘치는 단위는 다음 줄로 보낸다 */\n let placed = 0\n const empty = (): boolean => lineW === 0 && (!hancom || placed === 0)\n const cap = (): number => avail + (condense > 0 ? Math.trunc(spaceW * condense / 100) : 0) + EPS\n const lineStart = (): number => starts[starts.length - 1]\n\n /** 유닛(시작 unitPos, 폭 w)이 안 들어갈 때 줄바꿈 + 금칙 보정. split = 초장 유닛을 글자로 쪼개는 중 */\n const breakBefore = (unitPos: number, w: number, split = false): void => {\n let bp = unitPos\n const u = text[unitPos]\n const prevStart = (end: number): number => end - (end >= 2 && /[\\uDC00-\\uDFFF]/.test(text[end - 1]) && /[\\uD800-\\uDBFF]/.test(text[end - 2]) ? 2 : 1)\n // 시작금칙: 줄머리 금지 문자면 직전 글자 1개를 함께 내린다 (밀어내기)\n // 줄에 안 드는 단어(영문 단어·어절)를 글자로 쪼갤 때는 줄머리 금칙을 보지 않는다(칸 글 \"(92.5%\" + \")\" 는 \")\" 가 줄머리, 2024 저장본 \"(94.6\" + \"%)\").\n // 2024 이전 판은 줄끝 금칙도 보지 않고(어절 단위 칸 \"인구(\" + \"명)\"), 내린 글자도 줄머리 금지면 한 글자 더(최대 둘) 내린다(한글 2022: \"가×41」」가…\" → 둘째 줄이 \"」」\" 앞 글자부터)\n const old = opts?.before2024\n const splitIn = opts?.kinsoku === \"hancom\" && split && u !== undefined && !isWrapSpace(u) && !isWrapSpace(text[bp - 1])\n const inWord = old && splitIn\n if (!splitIn && u !== undefined && forbidStart.has(u) && prevStart(bp) > lineStart() && !isWrapSpace(text[bp - 1])) {\n bp = prevStart(bp)\n if (old && forbidStart.has(text[bp]) && prevStart(bp) > lineStart() && !isWrapSpace(text[bp - 1])) bp = prevStart(bp)\n }\n // 끝금칙: 남는 줄 끝이 여는 괄호류면 그 글자(들)도 함께 내린다 — 줄이 통째로 여는 괄호류뿐이면 내리지 않는다\n // (한글 2022: \"((((…\"·\"‘‘‘‘…\" 문단은 줄마다 들어가는 만큼 채운다. 줄 첫 글자는 남겨 한 글자씩 나르던 것)\n while (!inWord && bp - 1 >= lineStart() && forbidEnd.has(text[bp - 1])) bp--\n if (bp <= lineStart()) bp = unitPos\n starts.push(bp)\n avail = lineWidth ? lineWidth(starts.length - 1) : contWidth\n spaceW = 0\n realSeen = w > 0\n lineEnded = false\n placed = unitPos > bp ? 1 : 0\n for (let i = bp; i < unitPos; i++) {\n if (!isWrapSpace(text[i])) realSeen = true\n else if (text[i] === \" \" && condense > 0 && (realSeen || !hancom)) spaceW += rangeW(i, i + 1) - (spAt?.[i] ?? 0)\n }\n lineW = rangeW(bp, unitPos) + w\n }\n /** 금칙 보정 없이 at 에서 새 줄 — 한컴이 공백에서 줄을 끝낼 때(금칙은 낱말이 넘칠 때만 본다) */\n const breakAt = (at: number, leadW: number): void => {\n starts.push(at)\n avail = lineWidth ? lineWidth(starts.length - 1) : contWidth\n spaceW = 0\n realSeen = false\n lineEnded = false\n placed = 0\n lineW = leadW\n }\n\n for (const u of units) {\n if (isWrapSpace(u[0])) {\n if (hancom) {\n // 한컴: 공백마다 x 가 이미 줄 폭(공백 최소값 전)에 닿았으면 이 줄은 끝난다. 그 공백 덩어리는 앞 두 칸까지만\n // 이 줄에 남고 셋째 칸부터 다음 줄로 간다(굴림체 \"같이 | 알려\"). 닿지 않은 공백은 줄 끝에 걸린다(hang)\n let k = 0\n for (; k < u.length; k++) {\n if (!lineEnded && lineW >= avail) lineEnded = true\n // 고정폭 빈칸은 이미 끝난 줄에 더 걸지 않고 다음 줄 머리로 보낸다.\n if (lineEnded && (k >= 2 || u[k] === \"\\u2005\") && pos + k > lineStart()) break\n if (!lineEnded) {\n const sw = rangeW(pos + k, pos + k + 1)\n lineW += sw\n if (realSeen && u[k] === \" \") spaceW += sw - (spAt?.[pos + k] ?? 0)\n }\n }\n if (k < u.length) breakAt(pos + k, rangeW(pos + k, pos + u.length))\n pos += u.length\n continue\n }\n const sw = rangeW(pos, pos + u.length)\n lineW += sw // 줄 끝 공백은 hang\n for (let k = 0; k < u.length; k++) if (u[k] === \" \") spaceW += rangeW(pos + k, pos + k + 1)\n pos += u.length\n continue\n }\n // 필드 끝 컨트롤(reflow 가 비문자 U+FDD0 으로 넣는다)은 줄이 넘쳤어도 그 줄 끝에 붙는다\n // (한컴 저장본: 누름틀 시작 + 줄보다 넓은 표 + 누름틀 끝 = 두 줄. 떠 있는 개체 앵커 같은 다른 폭 0 컨트롤은 다음 줄로 간다)\n if (u === \"\\ufdd0\") { placed++; pos += u.length; continue }\n // 전각 빈칸(U+3000)이 넘치면 공백처럼 줄 끝에 건다(한컴 저장본: 칸 글 \"100.0 \"·\"공사종류 \" 가 한 줄)\n if (u === \"\\u3000\" && !empty() && lineW + rangeW(pos, pos + 1) - lastSp(pos, pos + 1) > cap()) { lineW += rangeW(pos, pos + 1); placed++; pos += u.length; continue }\n if (lineEnded) breakAt(pos, 0)\n const w = rangeW(pos, pos + u.length)\n if (lineW + w - lastSp(pos, pos + u.length) <= cap()) {\n lineW += w\n realSeen = true\n placed++\n pos += u.length\n continue\n }\n if (empty() || w > (lineWidth ? lineWidth(starts.length) : contWidth) + EPS) {\n // 빈 줄이거나 다음 줄에도 안 들어가는 초장 유닛 — 글자 단위 강제 분해. 어절 단위에서는 한컴이 먼저 다음 줄로\n // 넘긴 뒤 쪼갠다(코퍼스 어절 단위 문단 400개: 넘긴 뒤 347·제자리 340 일치, 갈리는 13건은 넘긴 뒤가 맞음)\n // 글자 단위 줄의 영문 단어(영문은 단어 유지)도 같다 — 한컴 저장본: 각주 번호 뒤 긴 URL 은 다음 줄부터 쪼갠다\n if ((mode === \"keep\" || /^\\u2060*[\\x21-\\x7e\\u00a1-\\u024f\\u2018-\\u201f]{2,}/.test(u)) && !empty()) breakBefore(pos, 0)\n let sub = 0\n for (const ch of u) {\n const c = charWAt(pos + sub, ch)\n if (lineW + c - lastSp(pos + sub, pos + sub + ch.length) > cap() && !empty() && ch !== \"\\u3000\" && ch !== \"\\ufdd0\") breakBefore(pos + sub, 0, true)\n lineW += c\n realSeen = true\n placed++\n sub += ch.length\n }\n pos += u.length\n continue\n }\n breakBefore(pos, w)\n placed++\n pos += u.length\n }\n return { lines: starts.length, starts, lastLineWidth: lineW }\n}\n\n/** @deprecated simulateWrap(text, …, 'keep') 별칭 — 하위 호환 */\nexport function simulateWrapKeepWord(\n text: string,\n firstWidth: number,\n contWidth: number,\n height: number,\n ratioPct: number,\n opts?: MeasureOptions,\n): WrapResult {\n return simulateWrap(text, firstWidth, contWidth, height, ratioPct, \"keep\", opts)\n}\n\n/**\n * 한두 글자(짧은 꼬리)가 다음 줄로 넘어간 문단을 장평 축소로 한 줄 줄일 수 있는지\n * 탐색. baseRatio에서 줄 수 N≥2일 때 r=baseRatio-1…minRatio를 내려가며 처음으로\n * 줄 수가 줄어드는(가장 큰) r을 반환. 불가능하면 null.\n * (실무 관행: 공무원이 문단 장평을 95→92 등으로 줄여 orphan을 위로 당기는 조작의 자동화.\n * keep 모드로 판정 — 글자 단위 조판은 항상 keep 이하의 줄 수라 함께 만족된다.)\n */\nexport function fitRatioForFewerLines(\n text: string,\n firstWidth: number,\n contWidth: number,\n height: number,\n baseRatio: number,\n minRatio: number,\n opts?: MeasureOptions,\n): number | null {\n const base = simulateWrap(text, firstWidth, contWidth, height, baseRatio, \"keep\", opts)\n if (base.lines < 2) return null\n for (let r = baseRatio - 1; r >= minRatio; r--) {\n const sim = simulateWrap(text, firstWidth, contWidth, height, r, \"keep\", opts)\n if (sim.lines < base.lines) return r\n }\n return null\n}\n","/**\n * 항목부호 자동번호 포맷 해석 (parser.ts에서 분리).\n * 한글 음절/자모·로마자·원숫자 시퀀스와 numbering 카운터로 문단머리 문자열 생성.\n */\n\nimport type { WalkCtx } from \"./parser-shared.js\"\nimport { hangulOrdinal, circledNumber, circledHangul, romanNumeral } from \"../shared/numbering.js\"\n\n// ─── 자동번호 포맷 ───────────────────────────────────\n\nconst HANGUL_JAMO_SEQ = \"ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎ\"\n\n/** 자동번호 카운터 값 → numFormat에 따른 표시 문자열 (각주·미주 번호 notes.ts 공용) */\nexport function formatHeadNumber(n: number, numFormat: string): string {\n if (n === 0 && numFormat === \"DIGIT\") return \"0\" // start=\"0\"은 유효값 — 시퀀스 포맷은 1-based라 아래 클램프 유지\n if (n <= 0) n = 1\n switch (numFormat) {\n case \"DIGIT\": return String(n)\n // 서수 시퀀스는 생성기(gongmun.ts)와 단일 소스 (v4.0.5) — 종전 mod-14 순환은\n // 15번째 형제를 다시 '가'로 만들어 한글 실렌더(가→하→거→너 단모음 연속)와 어긋났다\n case \"CIRCLED_DIGIT\": return n <= 50 ? circledNumber(n - 1) : `(${n})`\n case \"HANGUL_SYLLABLE\": return hangulOrdinal(n - 1)\n case \"CIRCLED_HANGUL_SYLLABLE\": return n <= 14 ? circledHangul(n - 1) : hangulOrdinal(n - 1)\n case \"HANGUL_JAMO\": return HANGUL_JAMO_SEQ[(n - 1) % HANGUL_JAMO_SEQ.length]\n case \"CIRCLED_HANGUL_JAMO\": return n <= 14 ? String.fromCodePoint(0x3260 + n - 1) : HANGUL_JAMO_SEQ[(n - 1) % 14]\n case \"LATIN_CAPITAL\": return String.fromCharCode(0x41 + ((n - 1) % 26))\n case \"LATIN_SMALL\": return String.fromCharCode(0x61 + ((n - 1) % 26))\n case \"CIRCLED_LATIN_CAPITAL\": return n <= 26 ? String.fromCodePoint(0x24b6 + n - 1) : String.fromCharCode(0x41 + ((n - 1) % 26))\n case \"CIRCLED_LATIN_SMALL\": return n <= 26 ? String.fromCodePoint(0x24d0 + n - 1) : String.fromCharCode(0x61 + ((n - 1) % 26))\n case \"ROMAN_CAPITAL\": return romanNumeral(n, true)\n case \"ROMAN_SMALL\": return romanNumeral(n, false)\n default: return String(n)\n }\n}\n\n/** 문단의 자동번호/글머리표/개요 해석 결과 */\nexport interface ResolvedParaHeading {\n /** 문단 텍스트 앞에 붙일 접두 (\"1.\", \"가.\", \"①\", \"-\" 등) */\n prefix?: string\n /** OUTLINE 문단의 헤딩 레벨 (1-6) */\n headingLevel?: number\n}\n\n/**\n * hp:p paraPrIDRef → paraPr heading(NUMBER/BULLET/OUTLINE) 해석.\n * NUMBER/OUTLINE은 7수준 카운터 상태기계 사용 — 같은 numbering id에서\n * 레벨별 카운터 증가, 상위 레벨 증가 시 하위 리셋. 한글은 빈 번호 문단도\n * 번호를 소비하므로 텍스트 없는 문단에서도 호출해 카운터를 진행시킨다\n * (v4.0.5 — 접두는 호출부가 텍스트 있을 때만 사용).\n */\nexport function resolveParaHeading(paraEl: Element, ctx: WalkCtx): ResolvedParaHeading | null {\n const sm = ctx.styleMap\n if (!sm) return null\n // 명명 스타일 기반 헤딩 — \"개요 N\" 스타일 참조 문단은 OUTLINE 없이도 헤딩.\n // (공문서 생성기가 개요 번호 렌더 결함을 피해 OUTLINE 대신 스타일명으로 의미 보존)\n const styleId = paraEl.getAttribute(\"styleIDRef\")\n let styleHeading: number | undefined\n if (styleId && styleId !== \"0\") {\n const st = sm.styles.get(styleId)\n const m = st && /^개요\\s*([1-6])$/.exec(st.name)\n if (m) styleHeading = Math.min(parseInt(m[1], 10), 6)\n }\n const prId = paraEl.getAttribute(\"paraPrIDRef\")\n if (!prId) return styleHeading ? { headingLevel: styleHeading } : null\n const ref = sm.paraHeadings.get(prId)\n if (!ref) return styleHeading ? { headingLevel: styleHeading } : null\n\n if (ref.type === \"BULLET\") {\n const char = sm.bullets.get(ref.idRef)\n return char ? { prefix: char } : null\n }\n\n // NUMBER는 idRef가 numbering id, OUTLINE은 secPr outlineShapeIDRef가 numbering id\n const numId = ref.type === \"OUTLINE\" ? (ctx.outlineNumId || \"1\") : ref.idRef\n const level = Math.min(ref.level + 1, 10) // 0-based 속성 → 1-based paraHead 레벨\n const headingLevel = ref.type === \"OUTLINE\" ? Math.min(ref.level + 1, 6) : undefined\n const numDef = sm.numberings.get(numId)\n if (!numDef) return headingLevel ? { headingLevel } : null\n\n let counters = ctx.shared.numState.get(numId)\n // 미사용 센티널은 -1 — 0을 쓰면 start=\"0\" numbering이 매번 미사용으로 오판돼 증가하지 않는다\n if (!counters) { counters = new Array(11).fill(-1); ctx.shared.numState.set(numId, counters) }\n const head = numDef.heads.get(level)\n counters[level] = counters[level] < 0 ? (head?.start ?? 1) : counters[level] + 1\n for (let l = level + 1; l <= 10; l++) counters[l] = -1\n\n // ^N 치환 — 참조 레벨의 카운터를 그 레벨의 numFormat으로 변환 (예: \"^1.\" → \"1.\")\n // 서식 텍스트가 명시적으로 빈 paraHead(한컴 \"번호 없음\" 개요, 생성기 왕복 포함)는\n // 접두를 발명하지 않는다 — 폴백 \"^N.\"은 해당 레벨 정의 자체가 없을 때만.\n const fmtText = head ? head.text.trim() : `^${level}.`\n const prefix = fmtText.replace(/\\^(10|[1-9])/g, (_, d) => {\n const lv = parseInt(d, 10)\n const refHead = numDef.heads.get(lv)\n // 카운터 0은 유효값(start=\"0\") — 미사용(-1)일 때만 start 폴백\n const n = counters![lv] >= 0 ? counters![lv] : (refHead?.start ?? 1)\n return formatHeadNumber(n, refHead?.numFormat || \"DIGIT\")\n })\n // 레벨 숫자가 아닌 글자(공백·기호) 앞의 ^ 는 한컴이 그리지 않는다 — 서식 \"^ □\"·\"^ ㅇ\" 이 한컴 PDF 에서\n // \"□\"·\"ㅇ\" 로만 나온다(정책브리핑 156775690, Hwp 2022). 문자·숫자 앞(^N 등)은 근거가 없어 그대로 둔다\n .replace(/\\^(?![\\p{L}\\p{N}])/gu, \"\")\n .trim()\n return { prefix: prefix || undefined, headingLevel }\n}\n\n","/**\n * 각주·미주 번호 표기 (v4.14.3) — 본문 참조 부호(\"1)\"·\"문1)\"·\"*\")와 주석 본문 머리 번호.\n *\n * 한컴은 각주/미주 개체 자리에 참조 부호를 그리고, 주석 영역 첫머리에는 주석 본문 안의\n * hp:autoNum(numType=FOOTNOTE|ENDNOTE)이 같은 부호를 그린다. hp:t 원문엔 둘 다 없다\n * (한컴 PDF 실렌더: footnote-01 \"플라스틱 액체1)와 …\" / 주석 \"1) 플라스틱 액체란\",\n * 3-09월_교육_통합 본문 \"문1)\" / 미주 \"문1) ④\"). HWP5 파서(body.ts applyNoteEffect)와\n * 같은 표기라 hwp↔hwpx 쌍 대조가 맞는다.\n *\n * 파서(section-walker)와 패치 매퍼(roundtrip)가 같은 규칙을 쓰도록 DOM 비의존 순수 함수로 둔다 —\n * 매퍼는 파서가 끼운 부호를 문단 텍스트에서 되빼야 소스맵 대조가 된다.\n */\n\nimport { formatHeadNumber } from \"./para-heading.js\"\nimport { findChildByLocalName } from \"../shared/xml.js\"\n\n/** secPr footNotePr/endNotePr > autoNumFormat 또는 hp:autoNum > autoNumFormat — 리터럴 문자 속성 */\nexport interface NoteNumberFormat {\n /** DIGIT·USER_CHAR·CIRCLED_DIGIT 등 (para-heading numFormat 과 같은 이름) */\n type: string\n userChar: string\n prefixChar: string\n suffixChar: string\n}\n\n/** hp:footNote/hp:endNote 여는 태그 속성 — 코드포인트 10진 문자열 그대로 (없으면 null) */\nexport interface NoteAttrs {\n number?: string | null\n prefixChar?: string | null\n suffixChar?: string | null\n userChar?: string | null\n}\n\n/** 코드포인트 10진 속성 → 문자. 속성 없음은 undefined(구역 기본값으로), 0 은 \"\" */\nfunction codePointAttr(v: string | null | undefined): string | undefined {\n if (v == null || v === \"\") return undefined\n const n = parseInt(v, 10)\n if (!Number.isFinite(n) || n < 0 || n > 0x10ffff) return undefined\n return n === 0 ? \"\" : String.fromCodePoint(n)\n}\n\n/** 속성 조회 함수로 autoNumFormat 읽기 — DOM(getAttribute)·정규식 스캐너 공용 */\nexport function noteFormatFrom(get: (name: string) => string | null | undefined): NoteNumberFormat {\n return {\n type: get(\"type\") || \"DIGIT\",\n userChar: get(\"userChar\") ?? \"\",\n prefixChar: get(\"prefixChar\") ?? \"\",\n suffixChar: get(\"suffixChar\") ?? \"\",\n }\n}\n\n/** 번호 본체 — USER_CHAR 는 사용자 문자, 나머지는 자동번호 서식 */\nfunction noteCore(num: number, fmt: NoteNumberFormat, userChar?: string): string {\n if (fmt.type === \"USER_CHAR\") return userChar ?? fmt.userChar\n return formatHeadNumber(num, fmt.type)\n}\n\n/**\n * 본문 참조 부호 — 개체 속성(number·prefixChar·suffixChar·userChar)이 우선, 없으면 구역\n * 번호 모양(secPr footNotePr/endNotePr). 둘 다 없으면 한컴 기본 \"N)\".\n * (한컴은 기본값과 같은 장식 속성을 생략해 저장한다 — USER_CHAR \"*\" 각주는 suffixChar 없이\n * 구역 모양 suffixChar=\"\" 만 가진다, issue6044)\n */\nexport function noteRefMark(attrs: NoteAttrs, fmt?: NoteNumberFormat): string {\n const f = fmt ?? { type: \"DIGIT\", userChar: \"\", prefixChar: \"\", suffixChar: \")\" }\n const n = parseInt(attrs.number ?? \"\", 10)\n const prefix = codePointAttr(attrs.prefixChar) ?? f.prefixChar\n const suffix = codePointAttr(attrs.suffixChar) ?? f.suffixChar\n return prefix + noteCore(Number.isFinite(n) ? n : 1, f, codePointAttr(attrs.userChar)) + suffix\n}\n\n/** 주석 본문 안 hp:autoNum(FOOTNOTE|ENDNOTE) 표기 — autoNumFormat 리터럴 그대로 */\nexport function noteAutoNumText(num: string | null | undefined, fmt: NoteNumberFormat): string {\n const n = parseInt(num ?? \"\", 10)\n return fmt.prefixChar + noteCore(Number.isFinite(n) ? n : 1, fmt) + fmt.suffixChar\n}\n\n/**\n * 본문에 그리는 자동번호 종류 — 주석 머리 번호(FOOTNOTE·ENDNOTE)와 캡션 번호(PICTURE·TABLE·EQUATION,\n * \"<그림 1>\" — 한컴 실렌더·HWP5 파서 모두 방출). 쪽번호(PAGE·TOTAL_PAGE)는 머리말·꼬리말 쪽번호\n * 크롬이라 종전대로 미방출\n */\nexport function isRenderedAutoNum(numType: string | null | undefined): boolean {\n return numType === \"FOOTNOTE\" || numType === \"ENDNOTE\" || numType === \"PICTURE\" || numType === \"TABLE\" || numType === \"EQUATION\"\n}\n\n// ─── DOM 어댑터 (파서 전용) ───────────────────────────\n\n/** hp:footNote/hp:endNote 요소 → 속성 묶음 */\nexport function noteAttrsOf(el: Element): NoteAttrs {\n return {\n number: el.getAttribute(\"number\"),\n prefixChar: el.getAttribute(\"prefixChar\"),\n suffixChar: el.getAttribute(\"suffixChar\"),\n userChar: el.getAttribute(\"userChar\"),\n }\n}\n\n/** 구역 첫 secPr 의 footNotePr/endNotePr > autoNumFormat */\nexport function readSectionNoteFormats(root: Element): { footnote?: NoteNumberFormat; endnote?: NoteNumberFormat } {\n const out: { footnote?: NoteNumberFormat; endnote?: NoteNumberFormat } = {}\n const pick = (names: string[]): NoteNumberFormat | undefined => {\n for (const name of names) {\n const els = root.getElementsByTagName(name)\n if (els.length === 0) continue\n const f = findChildByLocalName(els[0], \"autoNumFormat\")\n return f ? noteFormatFrom(n => f.getAttribute(n)) : undefined\n }\n return undefined\n }\n out.footnote = pick([\"hp:footNotePr\", \"footNotePr\"])\n out.endnote = pick([\"hp:endNotePr\", \"endNotePr\"])\n return out\n}\n\n/** hp:autoNum 요소 → 표기 (주석·캡션 번호), 쪽번호 등 다른 종류면 \"\" */\nexport function noteAutoNumOf(el: Element): string {\n if (!isRenderedAutoNum(el.getAttribute(\"numType\"))) return \"\"\n const f = findChildByLocalName(el, \"autoNumFormat\")\n return noteAutoNumText(el.getAttribute(\"num\"), noteFormatFrom(n => f?.getAttribute(n)))\n}\n","/**\n * 렌더 문단 모델·표 높이 측정 — HWPX 문단을 슬롯 스트림(글자·필러·탭)과 개체 목록으로 만들고, 표 실효 높이를 잰다.\n * 그리기(svg-render)와 조판 합성(reflow)이 공유하는 순수 계층 — 그리기 코드에 의존하지 않는다.\n */\n\nimport { findChildByLocalName } from \"../hwpx/parser-shared.js\"\nimport { noteAttrsOf, noteAutoNumOf, noteRefMark, readSectionNoteFormats } from \"../hwpx/notes.js\"\nimport { toInt32, solveRowHeights } from \"./layout.js\"\nimport { type RenderParaGeom } from \"./head-styles.js\"\n\nexport function ln(el: Element): string {\n return (el.tagName || \"\").replace(/^[^:]+:/, \"\")\n}\n\nexport function elements(el: Element): Element[] {\n const out: Element[] = []\n const children = el.childNodes\n if (!children) return out\n for (let i = 0; i < children.length; i++) {\n if (children[i].nodeType === 1) out.push(children[i] as Element)\n }\n return out\n}\n\nexport function num(el: Element | null, attr: string, fallback = 0): number {\n return el ? toInt32(el.getAttribute(attr) ?? undefined, fallback) : fallback\n}\n\nexport function findFirst(el: Element, name: string, depth = 0): Element | null {\n if (depth > 64) return null\n for (const ch of elements(el)) {\n if (ln(ch) === name) return ch\n const found = findFirst(ch, name, depth + 1)\n if (found) return found\n }\n return null\n}\n\nexport interface Seg { textpos: number; vertpos: number; horzpos: number; horzsize: number; textheight: number; baseline: number; spacing?: number }\n\n/** tab: 탭 컨트롤 첫 슬롯(나머지 7슬롯은 필러) — 폭은 줄 조판 때 탭 정지점으로 정한다. tabW: 저장된 hp:tab width.\n * nb: 묶음 빈칸(hp:nbSpace) — 그리기는 공백, 줄바꿈은 끊지 않는 빈칸(U+00A0). br: 강제 줄바꿈(hp:lineBreak) — 폭 0, 뒤 글은 새 줄.\n * ctrlText: 컨트롤이 그리는 글(주석 머리 번호 \"1)\" 등 hp:autoNum, 각주·미주 본문 참조 번호) — 줄 채우기에서 그 글의 폭을 차지한다.\n * ctrlSup: 그 글을 위첨자 크기로 잰다(각주·미주 본문 참조 번호). fieldEnd: 필드 끝 컨트롤 — 넘친 줄에도 그 줄 끝에 붙는다.\n * tabRight: 오른쪽 탭(hp:tab type 2) — 그 뒤 글은 탭 자리에 맞춰 놓인다 */\nexport interface ParaChar { ch: string; prId: string | null; tab?: boolean; tabW?: number; tabRight?: boolean; nb?: boolean; ctrl?: boolean; br?: boolean; ctrlText?: string; ctrlSup?: boolean; fieldEnd?: boolean; note?: Element }\n\n/** 렌더 대상 개체 태그 — 이 외(도형류)는 경고 후 생략 */\n/** 양식 컨트롤 — 글자처럼 취급하면 그 크기로 줄을 차지한다(한컴 저장본: 체크 상자 높이 1984 줄 = 1984, 기준선 85%) */\nexport const FORM_TAGS = new Set([\"checkBtn\", \"radioBtn\", \"btn\", \"comboBox\", \"listBox\", \"edit\", \"scrollBar\"])\nexport const OBJ_TAGS = new Set([\"tbl\", \"pic\", \"container\", \"equation\", \"rect\", \"ellipse\", \"polygon\", \"curv\", \"curve\", \"line\", \"arc\", \"ole\", \"textart\", ...FORM_TAGS])\n\n/** omL/omR: 글자처럼 취급하는 개체(TAC)의 outMargin 좌/우(HWPUNIT) — 한글은 TAC 개체를 \"outMargin 포함\n * 폭의 문자\"로 배치한다: 가로 전진폭 = om좌 + 개체 폭 + om우, 개체 자체는 pen + om좌\n * (rhwp #3396 동종. 수식도 같다 — 한컴 저장 lineseg: 수식 outMargin 좌우 56 을 넣으면 두 줄 이상 문단 줄 시작 일치 +184). */\nexport interface ParaObj { el: Element; tag: string; index: number; inline: boolean; width: number; height: number; omL: number; omR: number }\n\n/** runs: run 마다 시작 슬롯과 글자 모양 — 글 없는 run(문단 끝 빈 hp:t 등)도 그 자리 줄의 높이에 든다 */\nexport interface ParaModel { chars: ParaChar[]; segs: Seg[]; objs: ParaObj[]; paraPrId: string | null; runs: { at: number; prId: string | null }[] }\n\n/** hp:t 안에서 1슬롯을 차지하는 문자형 컨트롤 (HWP5 문자 스트림 모델) —\n * 탭(0x09)은 char가 아니라 inline 컨트롤 = 8슬롯(16바이트)이라 여기 넣으면 안 된다\n * (record.ts 0x09 처리의 i+=14와 같은 모델. 1슬롯로 세면 탭당 7슬롯씩 줄 경계가 밀린다) */\nexport const CHAR_CTRL_1SLOT = new Set([\"lineBreak\", \"hyphen\", \"hypen\", \"nbSpace\", \"fwSpace\"])\n\nconst noteFmtCache = new WeakMap<object, ReturnType<typeof readSectionNoteFormats>>()\n/** 문단이 속한 구역의 각주·미주 번호 모양(secPr) — 구역 루트별로 한 번 읽는다 */\nfunction sectionNoteFormats(p: Element): ReturnType<typeof readSectionNoteFormats> {\n const root = p.ownerDocument?.documentElement as unknown as Element | null\n if (!root) return {}\n let f = noteFmtCache.get(root)\n if (!f) { f = readSectionNoteFormats(root); noteFmtCache.set(root, f) }\n return f\n}\n\n/** lineseg textpos 정합용 0폭 필러 슬롯 — 컨트롤이 차지하는 문자 위치를 채운다 */\nexport function pushFillers(chars: ParaChar[], n: number, prId: string | null): void {\n for (let i = 0; i < n; i++) chars.push({ ch: \"\", prId })\n}\n\n/**\n * hp:t 내용을 슬롯 스트림으로 변환 — lineseg textpos 는 HWP5 문자 스트림 기준이라\n * 텍스트 1문자=1슬롯(서로게이트 쌍은 2), tab 등 문자형 컨트롤도 1슬롯을 차지한다.\n * markpen 등 래퍼 요소는 슬롯 없이 내용만 재귀한다.\n * (탭 폭은 planLines 가 탭 정지점 — 내어쓰기용 자동 탭·기본 40pt 간격 — 으로 정한다)\n * 한컴 저장본은 변경 추적 삭제 표지(deleteBegin/End)를 hp:t 안에 둔다 — 슬롯 없이 del.deleted 만 바꾸고, 삭제 구간 글자는 빈 슬롯\n * (파서 section-walker 와 같은 최종본). 종전엔 hp:t 안 표지를 못 읽어 지운 글을 그렸다\n */\nexport function pushTextSlots(t: Element, chars: ParaChar[], prId: string | null, depth: number, del: { deleted: number } = { deleted: 0 }): void {\n if (depth > 32) return\n const kids = t.childNodes\n if (!kids) return\n for (let i = 0; i < kids.length; i++) {\n const c = kids[i]\n if (c.nodeType === 3 || c.nodeType === 4) { // CDATA(4) 포함 — 누락 시 해당 런이 렌더에서 사라진다\n for (const cp of c.textContent ?? \"\") {\n chars.push({ ch: del.deleted ? \"\" : cp, prId })\n if (cp.length === 2) chars.push({ ch: \"\", prId }) // UTF-16 두 번째 유닛 슬롯\n }\n } else if (c.nodeType === 1) {\n const el = c as Element\n const tag = ln(el)\n if (tag === \"deleteBegin\" || tag === \"deleteEnd\") {\n del.deleted = deletionDelta(el, del.deleted)\n } else if (tag === \"tab\") {\n // inline 컨트롤 8슬롯 — 첫 슬롯에 탭 표지(폭은 planLines 가 탭 정지점으로), 나머지는 필러\n if (del.deleted) pushFillers(chars, 8, prId)\n else {\n const width = num(el, \"width\", -1)\n chars.push({ ch: \"\", prId, tab: true, ...(width >= 0 ? { tabW: width } : {}), ...(el.getAttribute(\"type\") === \"2\" ? { tabRight: true } : {}) })\n pushFillers(chars, 7, prId)\n }\n } else if (tag === \"titleMark\") {\n // 제목 차례 표시도 inline 컨트롤 8슬롯(HWP5 0x08) — 폭 없음. 0슬롯으로 세면 그 문단 줄 경계가 8씩 밀린다\n pushFillers(chars, 8, prId)\n } else if (CHAR_CTRL_1SLOT.has(tag)) {\n chars.push(del.deleted ? { ch: \"\", prId } : tag === \"nbSpace\" ? { ch: \" \", prId, nb: true } : tag === \"lineBreak\" ? { ch: \"\", prId, br: true } : { ch: tag === \"fwSpace\" ? \"\\u2005\" : \"\", prId })\n } else {\n pushTextSlots(el, chars, prId, depth + 1, del)\n }\n }\n }\n}\n\n// Each section/subList is a separate text story. Keep deletion ranges across its\n// paragraphs without removing DOM nodes: cached lineseg.textpos still counts them.\nconst deletedStarts = new WeakMap<Element, number>()\nconst deletedControls = new WeakMap<Element, boolean>()\nexport function isDeletedControl(el: Element): boolean { return deletedControls.get(el) === true }\nfunction deletionDelta(ctrl: Element, depth: number, xmlDepth = 0): number {\n if (xmlDepth > 64) return depth\n if (ln(ctrl) === \"deleteBegin\") return depth + 1\n if (ln(ctrl) === \"deleteEnd\") return Math.max(0, depth - 1)\n if (ln(ctrl) === \"ctrl\") for (const ch of elements(ctrl)) depth = deletionDelta(ch, depth, xmlDepth + 1)\n return depth\n}\nexport function prepareDeletedRanges(root: Element, depth = 0): void {\n if (depth > 64) return\n let deleted = 0\n for (const p of elements(root)) {\n if (ln(p) !== \"p\") continue\n deletedStarts.set(p, deleted)\n const scan = (el: Element, xmlDepth: number): void => {\n if (xmlDepth > 64) return\n if (ln(el) === \"ctrl\" || ln(el) === \"t\") for (const ch of elements(el)) scan(ch, xmlDepth + 1)\n else {\n if (ln(el) === \"deleteBegin\" || ln(el) === \"deleteEnd\") deleted = deletionDelta(el, deleted)\n deletedControls.set(el, deleted > 0)\n }\n }\n for (const ch of elements(p)) {\n if (ln(ch) === \"run\") for (const el of elements(ch)) scan(el, depth + 2)\n else if (ln(ch) === \"deleteBegin\" || ln(ch) === \"deleteEnd\") scan(ch, depth + 1)\n }\n }\n // Nested table cells, headers, and shape text have independent deletion state.\n function nested(el: Element, depth: number): void {\n if (depth > 64) return\n for (const ch of elements(el)) {\n if (ln(ch) === \"subList\") prepareDeletedRanges(ch, depth + 1)\n else nested(ch, depth + 1)\n }\n }\n nested(root, depth)\n}\n\nexport function buildPara(p: Element): ParaModel {\n const chars: ParaChar[] = []\n const objs: ParaObj[] = []\n let segs: Seg[] = []\n const runs: ParaModel[\"runs\"] = []\n let deleted = deletedStarts.get(p) ?? 0\n let secSlots = 0\n for (const runEl of elements(p)) {\n const tag = ln(runEl)\n if (tag === \"run\") {\n const prId = runEl.getAttribute(\"charPrIDRef\")\n runs.push({ at: chars.length, prId })\n for (const ch of elements(runEl)) {\n const cn = ln(ch)\n if (cn === \"t\") {\n const del = { deleted }\n pushTextSlots(ch, chars, prId, 0, del)\n deleted = del.deleted\n } else if (OBJ_TAGS.has(cn)) {\n const sz = findChildByLocalName(ch, \"sz\")\n const pos = findChildByLocalName(ch, \"pos\")\n // 그리기 도형은 hp:sz가 없다 — curSz(>0) → orgSz 폴백\n // 돌리지 않은 글상자(drawText 를 품은 도형)는 지금 크기 curSz 가 실크기 — sz 가 낡아 다를 때 한컴 줄 높이는 curSz 를 따른다\n // (한컴 저장본: 글자처럼 취급한 글상자 186개 전부 줄 높이 ≈ curSz, sz 를 따른 줄 0 — 그림·다각형은 sz).\n // 돌린 도형의 sz 는 돌린 뒤 외접 크기라 sz 를 따른다(270° 글상자: sz 14585×2760·curSz 2760×14585, 줄 2760)\n const cur = findChildByLocalName(ch, \"curSz\")\n const rot = num(findChildByLocalName(ch, \"rotationInfo\"), \"angle\") % 360\n const box = findChildByLocalName(ch, \"drawText\") && !rot && num(cur, \"width\") > 0 && num(cur, \"height\") > 0 && num(cur, \"height\") < 2 ** 31\n const w = box ? num(cur, \"width\") : num(sz, \"width\") || num(cur, \"width\") || num(findChildByLocalName(ch, \"orgSz\"), \"width\")\n const h = box ? num(cur, \"height\") : num(sz, \"height\") || num(cur, \"height\") || num(findChildByLocalName(ch, \"orgSz\"), \"height\")\n const inline = pos?.getAttribute(\"treatAsChar\") === \"1\"\n // 글자처럼 취급하는 개체는 outMargin 좌/우를 가로 배선 (ParaObj.omL 주석 — rhwp #3396 동종)\n const om = inline ? findChildByLocalName(ch, \"outMargin\") : null\n if (!deleted) objs.push({\n el: ch, tag: cn, index: chars.length,\n inline,\n width: w, height: h,\n omL: num(om, \"left\"), omR: num(om, \"right\"),\n })\n // 확장 컨트롤(GSO 등)은 문자 스트림에서 8슬롯 — 실측: 데모 코퍼스 1,132개\n // 멀티라인 문단에서 textpos 가 8슬롯 블록 중간에 걸린 경계 0건\n pushFillers(chars, 8, prId)\n // 떠 있는 개체(treatAsChar 0)도 폭 0 의 줄 내용 — 넘친 줄 뒤에 오면 다음 줄로 간다(인라인 개체는 reflow 가 폭을 준다)\n if (!inline) chars[chars.length - 8].ctrl = true\n } else {\n if (cn === \"ctrl\" || cn === \"deleteBegin\" || cn === \"deleteEnd\") deleted = deletionDelta(ch, deleted)\n // secPr·ctrl(구역/단 정의)·필드 등 나머지 run 자식도 확장/인라인 컨트롤 8슬롯\n pushFillers(chars, 8, prId)\n // 구역·단 정의가 아닌 컨트롤(쪽 번호·필드 등)은 폭 0 이어도 줄의 내용이다 — 한컴은 그 뒤에서 넘치는 개체를 다음 줄로 보낸다\n if (cn === \"secPr\" || (cn === \"ctrl\" && findChildByLocalName(ch, \"colPr\"))) secSlots += 8\n else {\n const slot = chars[chars.length - 8]\n slot.ctrl = true\n const an = cn === \"ctrl\" ? findChildByLocalName(ch, \"autoNum\") : null\n // 각주·미주 본문 참조 번호(\"1)\", \"문9)\")는 위첨자 크기로 그 글 폭을 차지한다 — 구역 번호 모양의 supscript 값과 무관\n // (한컴 저장 lineseg: 위첨자로 재면 두 줄 이상 문단 줄 시작 일치 +201, 본래 크기면 +173)\n const note = cn === \"ctrl\" ? findChildByLocalName(ch, \"footNote\") ?? findChildByLocalName(ch, \"endNote\") : null\n const t = an ? noteAutoNumOf(an) : note ? noteRefMark(noteAttrsOf(note), sectionNoteFormats(p)[ln(note) === \"endNote\" ? \"endnote\" : \"footnote\"]) : \"\"\n if (t) slot.ctrlText = t\n if (note) { slot.ctrlSup = true; slot.note = note }\n if (cn === \"ctrl\" && findChildByLocalName(ch, \"fieldEnd\")) slot.fieldEnd = true\n // 글자 겹치기(hp:compose)는 겹친 글자 수와 상관없이 한 글자 칸(1em) 폭을 차지한다 — 폭만 재는 전각 빈칸으로 둔다\n // (한컴 저장본: 겹치기 문서 16개 두 줄 이상 문단 +14. 폭 0 이면 그 문단 첫 줄에 글자가 더 들어갔다)\n if (cn === \"compose\" && ch.getAttribute(\"composeText\")) slot.ctrlText = \"\\u3000\"\n }\n }\n }\n } else if (tag === \"deleteBegin\" || tag === \"deleteEnd\") {\n // These compatibility markers live outside the run's character stream.\n deleted = deletionDelta(runEl, deleted)\n } else if (tag === \"linesegarray\") {\n // 미주·각주 머리 줄은 baseline 0 으로 저장되곤 한다(한컴 저장본 639줄, 전부 주석 안) — 한컴 PDF 는 보통 기준선(높이 85%)에 그린다\n segs = elements(runEl).filter(s => ln(s) === \"lineseg\").map(s => {\n const th = num(s, \"textheight\", 1000), bl = num(s, \"baseline\", 850)\n return { textpos: num(s, \"textpos\"), vertpos: num(s, \"vertpos\"), horzpos: num(s, \"horzpos\"), horzsize: num(s, \"horzsize\"), textheight: th, baseline: bl === 0 && th > 0 ? Math.round(th * 0.85) : bl, spacing: num(s, \"spacing\") }\n })\n }\n }\n // 구역·단 정의를 빼고 센 줄 시작 — 둘째 줄부터가 첫 글·개체 앞(구역·단 정의 칸 안)에 떨어지면 그 칸을 더해 읽는다\n // (한컴 PDF: 구역 첫 문단의 글자처럼 취급한 서식 표 둘 — 둘째 줄 textpos 8 = 둘째 표, 1쪽 앞면·2쪽 뒷면)\n if (secSlots > 0 && segs.length > 1) {\n let lead = 0\n while (lead < chars.length && chars[lead].ch === \"\" && !chars[lead].ctrl && !objs.some(o => o.index === lead)) lead++\n if (segs.slice(1).some(s => s.textpos < lead)) segs = segs.map((s, k) => k > 0 ? { ...s, textpos: s.textpos + secSlots } : s)\n }\n return { chars, segs, objs, paraPrId: p.getAttribute(\"paraPrIDRef\"), runs }\n}\n\n/**\n * 표·그림 캡션(hp:caption) — 위·아래 캡션은 개체 높이에 캡션 글 높이(마지막 줄 아래 끝, 줄 간격 몫 제외) + 간격(gap)을 더한다\n * (한컴 저장 lineseg 실측: 캡션 한 줄 1200 + gap 850 = 표 줄이 2050 높다). 왼쪽·오른쪽 캡션은 높이를 더하지 않는다\n */\nexport function captionOf(el: Element): { side: string; h: number; gap: number; width: number; sub: Element } | null {\n const cap = findChildByLocalName(el, \"caption\")\n const sub = cap ? findChildByLocalName(cap, \"subList\") : null\n if (!cap || !sub) return null\n let h = 0\n for (const p of elements(sub)) {\n if (ln(p) !== \"p\") continue\n const lsa = findChildByLocalName(p, \"linesegarray\")\n if (lsa) for (const sg of elements(lsa)) if (ln(sg) === \"lineseg\") h = Math.max(h, num(sg, \"vertpos\") + num(sg, \"vertsize\"))\n }\n const side = cap.getAttribute(\"side\") ?? \"BOTTOM\"\n return { side, h, gap: num(cap, \"gap\"), width: num(cap, side === \"LEFT\" || side === \"RIGHT\" ? \"width\" : \"lastWidth\") || num(cap, \"width\"), sub }\n}\n\n/** 위·아래 캡션이 개체 높이에 더하는 몫 */\nexport function captionExtra(el: Element): number {\n const c = captionOf(el)\n return c && (c.side === \"TOP\" || c.side === \"BOTTOM\") ? c.h + c.gap : 0\n}\n\n/** 한컴 기본 탭 간격 40pt (실결재 secPr tabStopVal 4000) */\nexport const DEFAULT_TAB_HU = 4000\n\n/**\n * 탭 전진폭 — x 는 문단 왼쪽 여백 기준. 첫 줄은 내어쓰기용 자동 탭(autoTabLeft)이면 내어쓰기 위치가\n * 정지점(법제처 서식 \"(a)⇥\" 실측: 부호폭 + 탭폭 = 내어쓰기). 그 밖엔 저장된 폭(한컴이 조판 때 잰 값 —\n * 문서 고유 탭 정의를 대신한다 — 명시적 0폭도 보존), 없으면 기본 간격 배수.\n */\n/** 선택한 앞머리 폭과 본문까지의 간격. 예약 폭은 원래 글꼴, 실폭은 대체 글꼴까지 반영해 호출부에서 잰다. */\nexport function paraHeadAdvance(head: NonNullable<RenderParaGeom[\"bullet\"]>, offsetHeight: number, width: number): number {\n return width + (head.offsetPct ? Math.trunc(offsetHeight * head.offset / 100) : head.offset)\n}\n\nexport function tabAdvance(x: number, firstLine: boolean, geom: RenderParaGeom | undefined, saved?: number): number {\n const hang = geom && geom.marginIntent < 0 ? -geom.marginIntent : 0\n if (firstLine && geom?.autoTabLeft && hang > 0 && x < hang - 0.5) return hang - x\n if (saved != null && saved >= 0) return saved\n return (Math.floor(x / DEFAULT_TAB_HU) + 1) * DEFAULT_TAB_HU - x\n}\n\nexport interface CellModel {\n el: Element\n ca: number; ra: number; cs: number; rs: number\n w: number; h: number\n bfId: string | null\n sub: Element | null\n marginL: number; marginR: number; marginT: number; marginB: number\n}\n\n/**\n * 셀/표 측정 메모 — drawTable(rowH·yoff)과 cellContentExtent↔measureTableHeight 상호재귀가\n * 중첩 단계마다 하위 표를 재측정해 지수적으로 불어나는 것을 캡. 렌더 1회 안에서만 공유\n * (reflow의 DOM 변형은 드로잉 시작 전에 끝나므로 캐시가 stale해지지 않는다).\n */\nexport interface ExtentMemo {\n cell: WeakMap<Element, number>\n table: WeakMap<Element, number>\n /** 문단 기하(id별) — 있으면 떠 있는 개체를 문단 위 간격 앞(문단 영역 위)에 놓는다 */\n paraGeom?: Map<string, RenderParaGeom>\n}\n\n/** 셀 콘텐츠 세로 범위 — 줄(vp+th) + 인라인 개체(중첩표·treatAsChar) + PARA 앵커 개체(anchor+h) 최대값 */\n/** 칸 안 다단(subList 첫 문단의 colPr colCount ≥ 2) — 단 수·간격. 다단 칸은 줄 vertpos 가 되돌아가면 다음 단이다(쪽 나눔이 아니다) */\nexport function cellColumns(sub: Element | null): { n: number; gap: number } | null {\n const p0 = sub ? elements(sub).find(q => ln(q) === \"p\") : undefined\n const cp = p0 ? findFirst(p0, \"colPr\") : null\n const n = cp ? Number(cp.getAttribute(\"colCount\")) || 1 : 1\n return n > 1 ? { n, gap: num(cp, \"sameGap\") } : null\n}\n\nexport function cellContentExtent(cell: CellModel, memo?: ExtentMemo): number {\n if (!cell.sub) return 0\n const hit = memo?.cell.get(cell.el)\n if (hit !== undefined) return hit\n const cols = cellColumns(cell.sub)\n let ext = 0\n // 한컴이 칸을 쪽에서 갈라 저장했으면 줄 vertpos 가 다음 쪽 기준 0 으로 되돌아간다 — 되돌아가는 곳마다 앞 줄 끝(+간격)에 이어 잰다\n // (같은 vertpos 가 같거나 왼쪽에서 다시 오는 곳도 — table-pages cellLineBoxes 와 같은 판정)\n let shift = 0, prevV = Number.NEGATIVE_INFINITY, prevH = 0, prevEnd = 0\n for (const p of elements(cell.sub)) {\n if (ln(p) !== \"p\") continue\n const m = buildPara(p)\n const paraStart = prevEnd\n let firstShift = shift\n const lineTops: number[] = []\n m.segs.forEach((s, k) => {\n if ((s.vertpos < prevV || (s.vertpos === prevV && s.horzpos <= prevH && prevEnd - shift > s.vertpos)) && !cols) shift = prevEnd - s.vertpos\n if (k === 0) firstShift = shift\n lineTops.push(s.vertpos + shift)\n prevV = s.vertpos\n prevH = s.horzpos\n prevEnd = s.vertpos + shift + s.textheight + (s.spacing ?? 0)\n ext = Math.max(ext, s.vertpos + s.textheight + shift)\n })\n const baseV = (m.segs[0]?.vertpos ?? 0) + firstShift\n for (const o of m.objs) {\n if (o.inline) {\n // 인라인 개체(중첩 표·treatAsChar 이미지)는 줄 위치에서 개체 높이만큼 아래로 뻗는다.\n // 이를 빼먹으면 중첩 표를 담은 셀 높이가 과소측정돼 표지 중첩표가 겹친다(리뷰: 셀 성장 누락).\n const h = o.tag === \"tbl\" ? Math.max(o.height, measureTableHeight(o.el, memo)) : o.height\n let line = 0\n while (line + 1 < m.segs.length && m.segs[line + 1].textpos <= o.index) line++\n ext = Math.max(ext, (lineTops[line] ?? baseV) + h)\n continue\n }\n const pos = findChildByLocalName(o.el, \"pos\")\n if ((pos?.getAttribute(\"vertRelTo\") ?? \"PARA\") !== \"PARA\") continue\n const om = findChildByLocalName(o.el, \"outMargin\")\n // 문단 기준 음수 vertOffset 은 문단 위에서 멈춘다(렌더와 같다) — 한컴 PDF: vertOffset −167 그림을 품은 칸의 행이 그림 높이만큼 자란다\n const vo = num(pos, \"vertOffset\")\n // 줄을 민 개체는 줄 바로 위에서 끝난다 — 아래 오프셋도 줄 위쪽 몫(렌더 anchorObject 와 같다. 같은 판 PDF: 칸 첫 문단의 vertOffset 17070 표가 칸을 그만큼 더 키우던 것)\n const pushed = baseV - (Math.max(0, vo) + num(om, \"top\") + o.height + num(om, \"bottom\"))\n // 글을 밀지 않은 개체는 문단 영역 위(문단 위 간격 앞)에 놓인다 — 한컴 저장본: 위 간격 500 문단의 9795 그림 → 행 높이 9795 + 칸 여백\n // 줄 위에 두면 앞 문단과 겹칠 개체는 줄을 밀지 않았다 — 줄 자리에서 시작한다(한컴 PDF: 앞 문단 끝 65,946 에 저장된 빈 문단 줄의 8,408 표가 그 줄부터 다음 쪽까지)\n const anchor = pushed >= (paraStart > 0 ? paraStart - 100 : -100) ? pushed : baseV - (memo?.paraGeom?.get(p.getAttribute(\"paraPrIDRef\") ?? \"\")?.spaceBefore ?? 0)\n // 떠 있는 표도 행으로 잰 높이까지 — 쪽을 넘는 표의 저장 sz 는 첫 쪽 조각뿐이다(한컴 PDF: sz 67,874 인 26행 안쪽 표가 행 합 142,876 으로 세 쪽)\n const oh = o.tag === \"tbl\" ? Math.max(o.height, measureTableHeight(o.el, memo)) : o.height\n // 바깥 아래 여백까지 — 같은 판 한컴 PDF: 바깥 여백 283 인 칸 안 떠 있는 표 65,396 을 품은 행이 65,396 + 283 × 2 + 칸 여백\n ext = Math.max(ext, anchor + num(om, \"top\") + Math.max(0, vo) + oh + num(om, \"bottom\"))\n }\n }\n memo?.cell.set(cell.el, ext)\n return ext\n}\n\n/** tbl의 셀 모델 수집 — drawTable과 measureTableHeight가 같은 셀 해석을 공유 */\n/** 칸 여백 한 변 — 없거나 HWP5 의 \"표 기본값\" 표시(0xFFFF 등 16비트 상한 근처)면 표 안 여백 */\nexport function cellMarginOf(cm: Element | null, side: string, def: number): number {\n const v = cm ? num(cm, side, def) : def\n return v >= 0x8000 ? def : v\n}\n\nexport function collectCells(tbl: Element): CellModel[] {\n const inMargin = findChildByLocalName(tbl, \"inMargin\")\n const defL = num(inMargin, \"left\", 141), defR = num(inMargin, \"right\", 141)\n const defT = num(inMargin, \"top\", 141), defB = num(inMargin, \"bottom\", 141)\n\n const cells: CellModel[] = []\n for (const tr of elements(tbl)) {\n if (ln(tr) !== \"tr\") continue\n for (const tc of elements(tr)) {\n if (ln(tc) !== \"tc\") continue\n const addr = findChildByLocalName(tc, \"cellAddr\")\n const span = findChildByLocalName(tc, \"cellSpan\")\n const csz = findChildByLocalName(tc, \"cellSz\")\n // hasMargin=\"0\" 이면 칸 여백(cellMargin)은 무시하고 표 안 여백(inMargin)을 쓴다 (한컴 저장 lineseg 실측: 칸 16893 − 142×2 → 16608, cellMargin 494 아님)\n const cm = tc.getAttribute(\"hasMargin\") === \"0\" ? null : findChildByLocalName(tc, \"cellMargin\")\n if (!addr || !csz) continue\n cells.push({\n el: tc,\n // 음수 주소(uint32 역변환·손상 입력) 방어 — colX/rowY 인덱스 이탈로 NaN 좌표 방지\n ca: Math.max(0, num(addr, \"colAddr\")), ra: Math.max(0, num(addr, \"rowAddr\")),\n cs: Math.max(1, num(span, \"colSpan\", 1)), rs: Math.max(1, num(span, \"rowSpan\", 1)),\n w: num(csz, \"width\"), h: num(csz, \"height\"),\n bfId: tc.getAttribute(\"borderFillIDRef\"),\n sub: findChildByLocalName(tc, \"subList\"),\n marginL: cellMarginOf(cm, \"left\", defL), marginR: cellMarginOf(cm, \"right\", defR),\n marginT: cellMarginOf(cm, \"top\", defT), marginB: cellMarginOf(cm, \"bottom\", defB),\n })\n }\n }\n return cells\n}\n\n/** 표 행마다 실효 높이(HWPUNIT) — measureTableHeight 와 같은 모델. 쪽에 걸친 표를 행 단위로 나눌 때 쓴다.\n * 칸 간격(cellSpacing)은 행마다 위에 한 번, 마지막 행 아래에 한 번 더 든다 — 여러 행 칸의 높이는 그 사이 간격을 품는다\n * (한컴 저장본: 16행 표 행 합 33168 + 255 × 17 = 표 높이 37503, 쪽을 넘은 표 뒤 문단도 행마다 255 씩 아래) */\nfunction inCell(el: Element): boolean {\n for (let n = el.parentNode as Element | null; n; n = n.parentNode as Element | null) if (ln(n) === \"tc\") return true\n return false\n}\n\n/** 한컴이 칸을 쪽에서 갈라 저장했나 — 칸 줄 vertpos 가 되돌아간다 */\nfunction splitSaved(c: CellModel): boolean {\n let prev = Number.NEGATIVE_INFINITY\n for (const p of c.sub ? elements(c.sub) : []) {\n if (ln(p) !== \"p\") continue\n for (const s of buildPara(p).segs) { if (s.vertpos < prev) return true; prev = s.vertpos }\n }\n return false\n}\n\nexport function measureTableRowHeights(tbl: Element, memo?: ExtentMemo): number[] {\n const cells = collectCells(tbl)\n if (cells.length === 0 || cells.length > 4096) return []\n const nRows = Math.max(...cells.map(c => c.ra + c.rs))\n const sp = num(tbl, \"cellSpacing\")\n const rows = solveRowHeights(\n // 여러 행 칸은 내용(+ 칸 여백)이 저장 높이보다 크면 내용 높이로 — 솔버가 모자란 만큼 그 칸 마지막 행을 키운다\n // (같은 판 PDF: 두 줄 든 2행 병합 칸 내용 2882 > 저장 2564 → 둘째 행이 318 자라고 첫 행은 그대로)\n cells.map(c => ({ rowAddr: c.ra, rowSpan: c.rs, height: (c.rs > 1 ? Math.max(c.h, cellContentExtent(c, memo) + c.marginT + c.marginB) : c.h) - sp * (c.rs - 1), contentH: cellContentExtent(c, memo) + c.marginT + c.marginB })),\n nRows,\n num(findChildByLocalName(tbl, \"sz\"), \"height\") - (sp > 0 ? sp * (nRows + 1) : 0) || Number.POSITIVE_INFINITY,\n !inCell(tbl) && !cells.some(c => c.ra + c.rs === nRows && splitSaved(c)),\n )\n if (sp > 0) { for (let r = 0; r < rows.length; r++) rows[r] += sp; rows[rows.length - 1] += sp }\n return rows\n}\n\n/**\n * 표 실효 높이(HWPUNIT) — drawTable의 rowH 모델(solveRowHeights + 셀 콘텐츠 성장) 그대로.\n * 선언 hp:sz는 셀 콘텐츠로 자란 높이를 모르므로, reflow가 표 뒤 문단을 실제 그려질\n * 표 바닥 아래로 배치할 때 이 값을 쓴다. 셀 lineseg가 있어야 성장분이 측정된다.\n */\nexport function measureTableHeight(tbl: Element, memo?: ExtentMemo): number {\n const hit = memo?.table.get(tbl)\n if (hit !== undefined) return hit\n const rowH = measureTableRowHeights(tbl, memo)\n let sum = 0\n for (const h of rowH) sum += h\n memo?.table.set(tbl, sum)\n return sum\n}\n","/** 표 행 나눔과 하위 목록 조판. 본문 조판 함수는 인자로 받아 중첩 흐름을 이어간다. */\nimport { buildPara, collectCells, findFirst, measureTableHeight, measureTableRowHeights, captionExtra, captionOf, cellContentExtent, cellMarginOf, OBJ_TAGS, elements, ln, num } from \"./para-model.js\"\nimport { type RenderStyles, type RenderParaGeom } from \"./head-styles.js\"\nimport { type NumberCounters } from \"./para-number.js\"\nimport { type WrapMode } from \"../hwpx/text-metrics.js\"\nimport { findChildByLocalName } from \"../hwpx/parser-shared.js\"\nimport { solveRowHeights } from \"./layout.js\"\n\ntype BlockFlow = (container: Element, doc: Document, styles: RenderStyles, areaW: number, mode: WrapMode,\n counter: { n: number; bodyW?: number; endNoteW?: number; nums?: NumberCounters }, bodyH: number) => void\n\n/**\n * 글 없는 문단에 앵커된 떠 있는 위아래 배치 표(문단 기준)가 lim 을 넘으면 행 단위로 쪽을 나눠, 마지막 쪽에서 표 바닥(outMargin 아래 포함)을 돌려준다.\n * 행은 (행 바닥 + outMargin 아래) ≤ 쪽 바닥일 때까지 그 쪽에 놓인다. 그런 표가 없으면 undefined\n */\n/** 글 없는 문단의 어울림(SQUARE) 표가 쪽 바닥을 넘는지 — 위아래 배치와 달리 문단 바닥을 밀지 않아 따로 본다.\n * 넘으면 위아래 배치 표처럼 행 단위로 나뉜다(한컴 저장본: 새 쪽 맨 위의 어울림 CELL 표 칸 줄이 쪽마다 0 부터) */\nexport function squareTableOver(p: Element, startV: number, lim: number, withText = false, areaW = 0): boolean {\n const m = buildPara(p)\n if (!withText && m.chars.some(c => c.ch !== \"\")) return false\n return m.objs.some(o => {\n if (o.inline || o.tag !== \"tbl\" || o.el.getAttribute(\"textWrap\") !== \"SQUARE\") return false\n const pb = o.el.getAttribute(\"pageBreak\")\n if (pb !== \"CELL\" && pb !== \"TABLE\") return false\n const pos = findChildByLocalName(o.el, \"pos\"), om = findChildByLocalName(o.el, \"outMargin\")\n if ((pos?.getAttribute(\"vertRelTo\") ?? \"PARA\") !== \"PARA\") return false\n const vo = num(pos, \"vertOffset\"), voS = Math.max(0, vo >= 2 ** 31 ? vo - 2 ** 32 : vo)\n if (withText && Math.max(0, num(pos, \"horzOffset\")) + num(om, \"left\") + o.width + num(om, \"right\") < areaW - 1440) return false\n return startV + voS + num(om, \"top\") + (withText ? measureTableHeight(o.el) : Math.max(o.height, measureTableHeight(o.el))) + num(om, \"bottom\") > lim\n })\n}\n\n/** 글머리표 문단인 빈 호스트에 위아래 배치 표만 있다 — 줄은 표 아래로 간다(공백 호스트처럼) */\nexport function bulletEmptyHost(p: Element, g?: RenderParaGeom): boolean {\n if (!g?.bullet) return false\n const m = buildPara(p)\n return m.objs.length > 0 && !m.chars.some(c => c.ch !== \"\" && c.ch.trim() !== \"\") && m.objs.every(o => !o.inline && o.tag === \"tbl\" && o.el.getAttribute(\"textWrap\") === \"TOP_AND_BOTTOM\")\n}\n\nexport function hasTbFloat(p: Element): boolean {\n return buildPara(p).objs.some(o => !o.inline && o.el.getAttribute(\"textWrap\") === \"TOP_AND_BOTTOM\" && (findChildByLocalName(o.el, \"pos\")?.getAttribute(\"vertRelTo\") ?? \"PARA\") === \"PARA\")\n}\n\nexport function m0Objs(p: Element): Element | undefined {\n return buildPara(p).objs.find(o => !o.inline && o.tag === \"tbl\")?.el\n}\n\n/** 칸 내용(+ 칸 여백)만으로 잰 표 높이 — 저장된 칸 높이(cellSz)는 보지 않는다 */\nfunction contentTableHeight(tbl: Element): number {\n const cells = collectCells(tbl)\n if (!cells.length) return 0\n const n = Math.max(...cells.map(c => c.ra + c.rs))\n return solveRowHeights(cells.map(c => ({ rowAddr: c.ra, rowSpan: c.rs, height: c.rs === 1 ? cellContentExtent(c) + c.marginT + c.marginB : 0, contentH: c.rs === 1 ? undefined : cellContentExtent(c) + c.marginT + c.marginB })), n).reduce((a, b) => a + b, 0)\n}\n\n/** 글 있는 문단의 오프셋(> 0) 위아래 배치 나눔 표가 쪽 바닥을 넘는가 — top 은 문단 영역 위(위 간격 앞) */\nexport function bandTableOver(p: Element, top: number, lim: number): boolean {\n const m = buildPara(p)\n if (!m.chars.some(c => c.ch !== \"\" && c.ch.trim() !== \"\")) return false\n return m.objs.some(o => {\n if (o.inline || o.tag !== \"tbl\" || o.el.getAttribute(\"textWrap\") !== \"TOP_AND_BOTTOM\") return false\n const pb = o.el.getAttribute(\"pageBreak\")\n if (pb !== \"CELL\" && pb !== \"TABLE\") return false\n const pos = findChildByLocalName(o.el, \"pos\"), om = findChildByLocalName(o.el, \"outMargin\")\n if ((pos?.getAttribute(\"vertRelTo\") ?? \"PARA\") !== \"PARA\") return false\n const vo = num(pos, \"vertOffset\")\n if (vo <= 0 || vo >= 2 ** 31) return false\n return top + vo + num(om, \"top\") + contentTableHeight(o.el) + num(om, \"bottom\") > lim\n })\n}\n\nexport function splitFloatTableRemainder(p: Element, startV: number, lim: number, bodyH: number, styles?: RenderStyles, withText = false, notes?: SplitNotes): number | undefined {\n const m = buildPara(p)\n if (!withText && m.chars.some(c => c.ch !== \"\")) return undefined\n let best: number | undefined, whole = true\n for (const o of m.objs) {\n if (o.inline || o.tag !== \"tbl\" || !(o.el.getAttribute(\"textWrap\") === \"TOP_AND_BOTTOM\" || o.el.getAttribute(\"textWrap\") === \"SQUARE\")) continue\n const pos = findChildByLocalName(o.el, \"pos\")\n if ((pos?.getAttribute(\"vertRelTo\") ?? \"PARA\") !== \"PARA\") continue\n const b = splitTableRows(o.el, startV + Math.max(0, num(pos, \"vertOffset\")), lim, bodyH, styles, notes)\n if (b !== undefined) { best = Math.max(best ?? 0, b); whole &&= splitWhole }\n }\n splitWhole = best !== undefined && whole\n return best\n}\n\n/**\n * 표를 쪽 바닥에서 나눈다 — 행 단위(pageBreak=TABLE)와 칸 안 나눔(CELL — 넘치는 행은 쪽 바닥에서 갈라 나머지를 다음 쪽 맨 위에).\n * top 은 표 바깥 여백 위쪽 자리. 마지막 쪽에서 표 바닥(outMargin 아래 포함)을 돌려준다. 나누지 않는 표는 undefined.\n * 칸 안에서 갈린 칸의 줄은 쪽마다 0 부터 다시 적는다(rebaseSplitCells)\n */\n/** 마지막 splitTableRows 가 첫 행부터 안 들어 표를 통째로 다음 쪽으로 옮겼는가 */\nexport let splitWhole = false\n/** 표 칸 안 각주 — 첫 쪽에 이미 놓인 각주(n0·s0)와 각주 영역 높이 함수 */\ninterface SplitNotes { n0: number; s0: number; area: (n: number, sum: number) => number }\n/** 마지막 splitTableRows 가 쪽을 넘겼을 때 표가 끝나는 쪽에 남기는 칸 안 각주(수·높이 합) */\nexport let splitNotesLast = { n: 0, s: 0 }\n/** 마지막 splitTableRows 가 행을 다음 쪽으로 넘겼는가(아니면 표가 그 쪽에 다 든다) */\nexport let splitMovedLast = false\nfunction noteBottom(fn: Element): number {\n const sub = findChildByLocalName(fn, \"subList\")\n let bottom = 0\n for (const q of sub ? elements(sub) : []) {\n if (ln(q) !== \"p\") continue\n const lsa = findChildByLocalName(q, \"linesegarray\")\n for (const seg of lsa ? elements(lsa) : []) if (ln(seg) === \"lineseg\") bottom = Math.max(bottom, num(seg, \"vertpos\") + num(seg, \"vertsize\"))\n }\n return bottom\n}\nfunction splitTableRows(tbl: Element, top: number, lim: number, bodyH: number, styles?: RenderStyles, notes?: SplitNotes): number | undefined {\n splitWhole = false\n splitNotesLast = { n: 0, s: 0 }\n const mode = tbl.getAttribute(\"pageBreak\")\n if (mode !== \"TABLE\" && mode !== \"CELL\") return undefined\n const om = findChildByLocalName(tbl, \"outMargin\")\n const outB = num(om, \"bottom\")\n const rows = measureTableRowHeights(tbl)\n if (rows.length === 0) return undefined\n const outT = num(om, \"top\")\n // 위·아래 캡션은 표에 한 번만 선다 — 위 캡션은 첫 조각 앞, 아래 캡션은 마지막 조각 뒤(새 쪽마다 되풀이하지 않는다)\n const cap = captionOf(tbl)\n const capTop = cap?.side === \"TOP\" ? cap.h + cap.gap : 0, capBottom = cap?.side === \"BOTTOM\" ? cap.h + cap.gap : 0\n // 머리 행 반복(repeatHeader)이면 새 쪽마다 앞쪽 머리 행(칸 header=\"1\")이 먼저 선다(한컴 저장본: 103행 조문 표의 칸 줄이 쪽마다 머리 행 아래에서 다시 시작)\n let headH = 0\n if (tbl.getAttribute(\"repeatHeader\") === \"1\") {\n const heads = new Set<number>()\n for (const c of collectCells(tbl)) if (c.el.getAttribute(\"header\") === \"1\") for (let r = c.ra; r < c.ra + c.rs; r++) heads.add(r)\n for (let r = 0; heads.has(r) && r < rows.length; r++) headH += rows[r]\n }\n // 넘치는 행은 다음 쪽 맨 위(outMargin 위 아래)로 — 첫 쪽에서 첫 행부터 넘치면 표째 넘어간다. 새 쪽 첫 행은 넘쳐도 그 쪽에 둔다\n let y = top + outT + capTop, floor = lim, moved = false\n // 칸 안 각주 — 본문이 먼저다: 쪽에서 처음 나오는 표 안 각주만 앞 두 줄 몫으로 그 쪽 바닥을 올리고(나머지 줄은 다음 쪽으로 이어진다),\n // 뒤 각주는 다음 쪽으로 미뤄 바닥을 올리지 않는다(한컴 저장본: 칸 안 각주 6개인 7행 표가 첫 쪽에 5행 11645(= 저장 표 높이) —\n // 첫 각주 네 줄 중 두 줄 2072 만 첫 쪽, 나머지 각주는 다음 쪽)\n const rowNoteLines: number[][][] = rows.map(() => [])\n let allN = 0, allS = 0\n if (notes) for (const c of collectCells(tbl)) for (const fn of Array.from(c.el.getElementsByTagName(\"hp:footNote\") as unknown as Element[])) {\n rowNoteLines[Math.min(c.ra, rows.length - 1)].push(Array.from(fn.getElementsByTagName(\"hp:lineseg\") as unknown as Element[]).map(sg => num(sg, \"vertpos\") + num(sg, \"vertsize\")))\n allN++; allS += noteBottom(fn)\n }\n /** 이 쪽 바닥을 올리는 표 안 각주(쪽의 첫 각주 앞 두 줄) · 앞 쪽들에 놓고 온 몫 */\n let nN = 0, nS = 0, placed = 0\n const fl = (): number => (notes && nN > 0 ? Math.min(floor, bodyH - notes.area((moved ? 0 : notes.n0) + nN, (moved ? 0 : notes.s0) + nS)) : floor)\n // 칸 간격(cellSpacing) — 쪽에서 갈린 행 조각도 위아래에 간격을 하나씩 둔다(행 높이에는 measureTableRowHeights 가 넣었다)\n // (한컴 저장본: 간격 255 표의 갈린 칸이 쪽 바닥에서 한 줄 일찍 끊긴다)\n const sp = num(tbl, \"cellSpacing\")\n const cells = mode === \"CELL\" ? collectCells(tbl) : []\n const tableCells = mode === \"TABLE\" ? collectCells(tbl) : []\n const record = mode === \"CELL\" ? new Map<Element, number[]>() : undefined\n const carries = new Map<Element, Map<number, number>>()\n for (let r = 0; r < rows.length; r++) {\n let h = rows[r]\n for (const ls of rowNoteLines[r]) if (nN === 0 && ls.length) { nN = 1; nS = ls[Math.min(1, ls.length - 1)] }\n if (mode === \"CELL\") {\n // 행을 칸 줄 경계에서 가른다 — 칸마다 쪽에 드는 줄까지 이 쪽, 나머지 줄은 다음 쪽 맨 위에서 칸 여백과 함께\n const from = new Map<Element, number>(), bases = new Map<Element, number>()\n while (y + h + outB > fl() && bodyH - outT - outB > 0) {\n // 이어지는 쪽에서 행을 가를 때는 칸 줄이 쪽 바닥에서 100 넘게 떨어져야 든다(한컴 저장본: 이어지는 쪽에서 넘어간 줄의 남았을 여유 21~98,\n // 남은 줄은 114 이상), 첫 쪽에서는 20(넘어간 줄의 남았을 여유 18, 남은 줄 23). 행 전체가 쪽에 들면 그 행은 가르지 않는다(편람: 바닥 가까이에서 끝나는 행이 그 쪽에 남는다)\n // 쪽에 남는 행 조각은 남은 높이보다 101 작고, 칸 높이를 고정한 표(noAdjust)는 2 작다 — 한컴 저장본: 칸 안 나눔 표의 저장 높이 = 첫 쪽 조각,\n // 조각이 남은 높이 − 101~102 인 표 52곳은 모두 고정 아님, − 2 인 표 10곳은 모두 고정. 고정 표는 칸 저장 높이를 쪽마다 나눠 가져\n // 위 정렬 칸도 저장 높이 − 조각이 다음 쪽 몫이다(위 정렬 29,198 칸 = 첫 쪽 11,058 + 다음 쪽 18,140 — 남은 글만 세면 797 모자람)\n const fixedRows = tbl.getAttribute(\"noAdjust\") === \"1\"\n const rem = cellRowRemainder(cells, r, fl() - outB - y - (moved ? 100 : 20) - 2 * sp, from, record, bases, carries, styles, bodyH - outT - outB, fl() - outB - y - (fixedRows ? 2 : 101) - 2 * sp, fixedRows)\n // 마지막 행의 칸 줄이 이 쪽에 다 들면(넘는 것은 저장된 행의 빈 높이뿐) 표는 이 쪽에서 끝난다 — 다음 쪽에 바깥 여백만 남기지 않는다\n // (한컴 저장본: 글이 다 든 21090 행이 쪽 바닥을 넘는 3행 표 뒤 빈 문단이 다음 쪽 0, 종전 566)\n if (rem === 0 && r === rows.length - 1) break\n if (rem === undefined || rem + sp + (r === rows.length - 1 ? sp : 0) >= h) {\n if (moved && y === outT + headH) break\n if (!moved && r === 0) splitWhole = true\n } else h = rem + sp + (r === rows.length - 1 ? sp : 0)\n y = outT + headH; floor = bodyH; moved = true; placed += nS; nN = 0; nS = 0\n }\n y += h\n continue\n }\n // 여러 행 칸이 묶은 행들은 쪼개지 않는다 — 묶음 첫 행에서 묶음 전체가 이 쪽에 안 들면 묶음째 다음 쪽(렌더 planTableRows 와 같다)\n let need = h\n if (!tableCells.some(c => c.ra < r && c.ra + c.rs > r)) {\n let end = r + 1\n for (let grown = true; grown;) { grown = false; for (const c of tableCells) if (c.ra >= r && c.ra < end && c.ra + c.rs > end) { end = c.ra + c.rs; grown = true } }\n const groupH = rows.slice(r, end).reduce((a, b) => a + b, 0)\n if (end > r + 1 && groupH <= bodyH - outT - outB - headH) need = groupH\n }\n if (y + need + outB > fl() && !(moved && y === outT + headH)) { if (!moved && r === 0) splitWhole = true; y = outT + headH; floor = bodyH; moved = true; placed += nS; nN = 0; nS = 0 }\n y += h\n }\n if (record) rebaseSplitCells(record, carries, styles)\n // 앞 쪽들에 놓고 온 몫을 뺀 표 안 각주는 표가 끝나는 쪽 각주로 남긴다(뒤 문단의 쪽 바닥)\n if (moved) splitNotesLast = { n: allN, s: Math.max(0, allS - placed) }\n splitMovedLast = moved\n return y + capBottom + outB\n}\n\n/**\n * 칸 안 나눔(CELL) 행을 쪽에 남은 높이 avail 에서 가를 때 다음 쪽으로 넘어가는 행 높이. 칸마다 (칸 위 여백 + 줄 바닥) ≤ avail − 칸 아래 여백 인 줄까지\n * 이 쪽에 두고, 남은 줄(첫 남은 줄 위 ~ 내용 끝)에 칸 위아래 여백을 더한다. 어느 칸도 한 줄을 못 넣으면 undefined(행째 다음 쪽)\n */\nfunction cellRowRemainder(cells: ReturnType<typeof collectCells>, row: number, avail: number, from: Map<Element, number>, record?: Map<Element, number[]>, bases?: Map<Element, number>, carries?: Map<Element, Map<number, number>>, styles?: RenderStyles, contH = 0, piece = Infinity, fixedRows = false): number | undefined {\n // from: 칸마다 앞 쪽들에 이미 놓은 내용 위치 — 그 위치부터의 줄만 이 쪽에 채운다(가른 뒤 갱신)\n // bases: 그 쪽 조각의 기준 — 자르기 직전 줄의 끝(줄 위치 + 높이 + 간격). 넘어간 줄은 그만큼 올라와 0 부터 다시 적힌다(rebaseSplitCells)\n let rem = 0, any = false, placed = false\n const cuts: [Element, number, number][] = []\n for (const c of cells) {\n if (c.ra !== row || c.rs !== 1 || !c.sub) continue\n const off = from.get(c.el) ?? 0, base = bases?.get(c.el) ?? 0\n // 쪽 바닥을 넘는 칸 안 위아래 배치 개체는 다음 쪽 맨 위로 옮겨 간다(vertOffset 은 버린다) — 이 쪽의 뒤 글은 개체에 밀리지 않고 이어지며,\n // 다음 쪽 글은 그 개체 아래에서 시작한다(한컴 저장본: 큰 칸 안 그림 바깥 852 + 13924 + 캡션 2050 + 852 = 다음 쪽 첫 줄 17678)\n const limAbs = base + avail - c.marginB - c.marginT\n let carry = 0, carryFrom = Infinity\n let splitAt: { bottom: number; rem: number } | undefined\n for (let guard = 0; guard < 16; guard++) {\n const f = subFloatBottoms(c.sub).find(f => f.v0 >= off && f.lineBottom <= limAbs && f.bottom > limAbs && f.v0 < carryFrom)\n if (!f) break\n // 나뉘는 표는 이 쪽에 드는 행까지 남기고 나머지 행만 다음 쪽 맨 위로 — 뒤 글은 그 아래(한컴 저장본: 첫 행 2797 이 쪽 바닥 74837 까지 들고\n // 나머지 7행 34766 + 바깥 140×2 = 다음 쪽 첫 줄 35046)\n if (f.rows?.length) {\n let y = f.bottom - f.carry + f.outT!, k = 0\n while (k < f.rows.length && y + f.rows[k] <= limAbs) y += f.rows[k++]\n // 행이 모두 들면(바깥 아래 여백만 넘침) 표는 이 쪽에 그대로, 뒤 글만 다음 쪽 맨 위에서(한컴 저장본: 표 바닥 74636 뒤 빈 문단이 다음 쪽 0)\n if (k === f.rows.length) break\n // 표는 같은 나눔으로 재귀해 쪽마다 가르고(칸 안 나눔은 칸 줄 경계에서, 여러 쪽이면 쪽마다), 마지막 쪽의 표 바닥 아래에서 뒤 글이 이어진다 —\n // 중첩 칸 줄도 쪽마다 다시 적힌다(한컴 저장본: 머리 행 반복 70행 표가 두 쪽을 넘겨 끝난 뒤 다음 줄 10132). 첫 행부터 안 드는 TABLE 표는 표째 옮긴다\n if ((k > 0 || f.el?.getAttribute(\"pageBreak\") === \"CELL\") && contH > 0 && f.el) {\n const nested = splitTableRows(f.el, f.bottom - f.carry - base, avail - c.marginB - c.marginT, contH - c.marginT - c.marginB, styles)\n const rem = nested ?? (k > 0 ? f.outT! + f.rows.slice(k).reduce((a, b) => a + b, 0) + f.outB! : undefined)\n if (rem !== undefined) { splitAt = { bottom: f.bottom, rem }; carryFrom = f.v0; break }\n }\n }\n const delta = f.bottom - f.hostEnd\n if (delta > 0) for (const p of elements(c.sub)) if (ln(p) === \"p\") { const lsa = findChildByLocalName(p, \"linesegarray\"); for (const sg of lsa ? elements(lsa) : []) if (ln(sg) === \"lineseg\" && num(sg, \"vertpos\") >= f.bottom) sg.setAttribute(\"vertpos\", String(num(sg, \"vertpos\") - delta)) }\n carry = Math.max(carry, f.carry); carryFrom = f.v0\n }\n const segs: Element[] = []\n for (const p of elements(c.sub)) if (ln(p) === \"p\") {\n const lsa = findChildByLocalName(p, \"linesegarray\")\n for (const sg of lsa ? elements(lsa) : []) if (ln(sg) === \"lineseg\" && num(sg, \"vertpos\") >= off) segs.push(sg)\n }\n if (segs.length === 0) continue\n any = true\n const lines = segs.map(sg => [num(sg, \"vertpos\") - base, num(sg, \"vertpos\") + num(sg, \"vertsize\") - base] as [number, number])\n const end = Math.max(...lines.map(l => l[1]))\n const k = lines.findIndex(l => c.marginT + l[1] > avail - c.marginB)\n if (k < 0) {\n // 모든 줄을 이 쪽에 놓았다. 저장된 행의 빈 높이는 다음 쪽 내용이 아니다.\n placed = true\n // 줄은 다 들어도 옮겨 간 개체가 있으면 그 개체가 다음 쪽 조각이다(한컴 저장본: 그림 칸의 빈 줄은 이 쪽에, 그림은 다음 쪽 맨 위)\n if (carry > 0) rem = Math.max(rem, c.marginT + carry + c.marginB)\n cuts.push([c.el, base + end + 1, base]); continue\n }\n if (k > 0) placed = true\n let nb = k > 0 ? num(segs[k - 1], \"vertpos\") + num(segs[k - 1], \"vertsize\") + num(segs[k - 1], \"spacing\") + spaceAfterAt(segs[k - 1], styles) : base\n const cutV = num(segs[k], \"vertpos\")\n for (const f of subFloatBottoms(c.sub)) if (f.v0 >= off && f.v0 < cutV && f.bottom <= cutV) nb = Math.max(nb, f.bottom)\n if (splitAt && cutV >= splitAt.bottom) { nb = Math.max(nb, splitAt.bottom); carry = splitAt.rem - (cutV - splitAt.bottom) }\n if (carry > 0 && cutV > carryFrom) { nb -= carry; const m = carries?.get(c.sub) ?? new Map<number, number>(); m.set(cutV, carry); carries?.set(c.sub, m) }\n cuts.push([c.el, base + lines[k][0], nb])\n rem = Math.max(rem, end + base - nb + c.marginT + c.marginB)\n // 가운데·아래 정렬 칸(과 칸 높이 고정 표의 모든 칸)은 글이 덜 차도 저장 높이만큼 선다 — 처음 가르는 칸은 저장 높이에서 이 쪽 조각(piece)을 뺀 만큼이 다음 쪽 몫\n // (한컴 저장본: 가운데 정렬 83,780 칸이 첫 쪽 55,937 + 다음 쪽 27,843 — 남은 글만 세면 24,176 이라 뒤 문단이 3,667 위로 올라왔다)\n if (off === 0 && (fixedRows || /^(CENTER|BOTTOM)$/.test(c.sub.getAttribute(\"vertAlign\") ?? \"\"))) rem = Math.max(rem, c.h - piece)\n }\n if (!(any && placed)) return undefined\n for (const [el, v, nb] of cuts) { from.set(el, v); bases?.set(el, nb) }\n if (record) for (const c of cells) {\n if (c.ra !== row || c.rs !== 1 || !c.sub) continue\n const v = from.get(c.el)\n if (v === undefined) continue\n const list = record.get(c.sub) ?? []\n // 끝까지 다 든 칸(줄 끝 + 1)은 자른 자리가 아니다\n let last = 0\n for (const p of elements(c.sub)) if (ln(p) === \"p\") { const lsa = findChildByLocalName(p, \"linesegarray\"); for (const sg of lsa ? elements(lsa) : []) if (ln(sg) === \"lineseg\") last = Math.max(last, num(sg, \"vertpos\") + num(sg, \"vertsize\")) }\n if (v <= last && !list.includes(v)) { list.push(v); record.set(c.sub, list) }\n }\n return rem\n}\n\n/** 글이 공백뿐인 문단(빈칸 하나 이상, 인라인 개체 없음) */\nexport function spacesHost(p: Element): boolean {\n const m = buildPara(p)\n return m.chars.some(c => c.ch === \" \") && m.chars.every(c => c.ch === \"\" || c.ch === \" \") && !m.objs.some(o => o.inline)\n}\n\n/** 칸 안 문단에 앵커된 위아래 배치 개체 — 앵커 문단 첫 줄 위치·그 줄 바닥·문단 글 끝(간격 포함), 개체 바닥(vertOffset·바깥 여백·캡션 포함),\n * 다음 쪽으로 옮겨 갈 때 차지하는 높이(vertOffset 뺀 것).\n * 칸이 쪽에서 갈릴 때 자르기 직전 개체 바닥도 새 조각의 기준이 된다 — 개체에 밀려 넘어간 문단은 새 쪽 0 에서\n * (한컴 저장본: 큰 칸 안 표 바닥 74636 에 밀린 빈 문단이 다음 쪽 0, 종전엔 표 몫 7936 이 새 쪽 위에 남았다) */\nexport interface SubFloat { v0: number; bottom: number; carry: number; hostEnd: number; lineBottom: number; rows?: number[]; outT?: number; outB?: number; el?: Element; seg?: Element }\nexport function subFloatBottoms(sub: Element): SubFloat[] {\n const out: SubFloat[] = []\n for (const p of elements(sub)) {\n if (ln(p) !== \"p\") continue\n const lsa = findChildByLocalName(p, \"linesegarray\"), segs = lsa ? elements(lsa).filter(e => ln(e) === \"lineseg\") : [], seg = segs[0]\n if (!seg) continue\n const last = segs[segs.length - 1], hostEnd = num(last, \"vertpos\") + num(last, \"vertsize\") + num(last, \"spacing\")\n for (const run of elements(p)) {\n if (ln(run) !== \"run\") continue\n for (const o of elements(run)) {\n if (!OBJ_TAGS.has(ln(o)) || o.getAttribute(\"textWrap\") !== \"TOP_AND_BOTTOM\") continue\n const pos = findChildByLocalName(o, \"pos\")\n if (pos?.getAttribute(\"treatAsChar\") === \"1\" || (pos?.getAttribute(\"vertRelTo\") ?? \"PARA\") !== \"PARA\") continue\n const om = findChildByLocalName(o, \"outMargin\"), sz = findChildByLocalName(o, \"sz\")\n const h = (ln(o) === \"tbl\" ? Math.max(num(sz, \"height\"), measureTableHeight(o)) : num(sz, \"height\")) + captionExtra(o)\n const vo = num(pos, \"vertOffset\"), v0 = num(seg, \"vertpos\"), carry = num(om, \"top\") + h + num(om, \"bottom\")\n const voS = Math.max(0, vo >= 2 ** 31 ? vo - 2 ** 32 : vo)\n const split = ln(o) === \"tbl\" && (o.getAttribute(\"pageBreak\") === \"CELL\" || o.getAttribute(\"pageBreak\") === \"TABLE\")\n const rowInfo = split ? { rows: measureTableRowHeights(o), outT: num(om, \"top\"), outB: num(om, \"bottom\"), el: o } : {}\n // 공백만 있는 호스트는 줄이 개체 아래에 있다 — 개체 자리는 그 줄 위(옮겨 가면 줄도 제자리로 올라온다)\n if (spacesHost(p)) { const top0 = v0 - voS - carry; out.push({ v0: top0, bottom: v0, carry, hostEnd: top0, lineBottom: top0 + num(seg, \"vertsize\"), ...rowInfo, seg }); continue }\n out.push({ v0, bottom: v0 + voS + carry, carry, hostEnd, lineBottom: v0 + num(seg, \"vertsize\"), ...rowInfo, seg })\n }\n }\n }\n return out\n}\n\n/** 칸 안에서 쪽이 갈린 칸의 줄을 조각마다 다시 적는다 — 넘어간 줄은 자르기 직전 줄의 끝(줄 위치 + 높이 + 간격)을 0 으로\n * (한컴 저장본: 쪽을 넘는 큰 칸의 줄 vertpos 가 쪽마다 0 부터 — 문단 위 간격 1500 인 문단이 새 쪽 1500) */\n/** 문단 마지막 줄이면 그 문단의 아래 간격 — 쪽이 바뀌면 앞 문단 아래 간격은 새 쪽에 남지 않는다(다음 문단 위 간격만 남는다)\n * (한컴 저장본: 아래 간격 570 문단 뒤에서 갈린 칸의 다음 쪽 첫 줄 0) */\nfunction spaceAfterAt(sg: Element, styles?: RenderStyles): number {\n if (!styles) return 0\n const lsa = sg.parentNode as Element | null, p = lsa?.parentNode as Element | null\n if (!lsa || !p) return 0\n const segs = elements(lsa).filter(e => ln(e) === \"lineseg\")\n if (segs[segs.length - 1] !== sg) return 0\n return styles.paraGeom.get(p.getAttribute(\"paraPrIDRef\") ?? \"\")?.spaceAfter ?? 0\n}\n\nfunction rebaseSplitCells(record: Map<Element, number[]>, carries?: Map<Element, Map<number, number>>, styles?: RenderStyles): void {\n for (const [sub, cuts] of record) {\n const segs: Element[] = []\n for (const p of elements(sub)) if (ln(p) === \"p\") { const lsa = findChildByLocalName(p, \"linesegarray\"); for (const sg of lsa ? elements(lsa) : []) if (ln(sg) === \"lineseg\") segs.push(sg) }\n const old = segs.map(sg => num(sg, \"vertpos\"))\n const floats = subFloatBottoms(sub)\n const sorted = [...cuts].sort((a, b) => a - b)\n const bases = sorted.map(c => {\n let base = 0\n segs.forEach((sg, i) => { if (old[i] < c) base = Math.max(base, old[i] + num(sg, \"vertsize\") + num(sg, \"spacing\") + spaceAfterAt(sg, styles)) })\n for (const f of floats) if (f.v0 < c && f.bottom <= c) base = Math.max(base, f.bottom)\n return base - (carries?.get(sub)?.get(c) ?? 0)\n })\n segs.forEach((sg, i) => {\n let j = -1\n for (let k = 0; k < sorted.length; k++) if (old[i] >= sorted[k]) j = k\n if (j >= 0) sg.setAttribute(\"vertpos\", String(old[i] - bases[j]))\n })\n }\n}\n\n/** 문단에 앵커된, 쪽 아래에 붙은 위아래 배치 개체가 본문 바닥에서 차지하는 높이(바깥 여백·vertOffset 포함). 없으면 0 */\nexport function pageBottomReserve(p: Element): number {\n let r = 0\n for (const run of elements(p)) {\n if (ln(run) !== \"run\") continue\n for (const o of elements(run)) {\n if (!OBJ_TAGS.has(ln(o)) || o.getAttribute(\"textWrap\") !== \"TOP_AND_BOTTOM\") continue\n const pos = findChildByLocalName(o, \"pos\")\n if (pos?.getAttribute(\"treatAsChar\") === \"1\" || pos?.getAttribute(\"vertRelTo\") !== \"PAGE\" || pos?.getAttribute(\"vertAlign\") !== \"BOTTOM\") continue\n const om = findChildByLocalName(o, \"outMargin\"), sz = findChildByLocalName(o, \"sz\")\n const h = ln(o) === \"tbl\" ? Math.max(num(sz, \"height\"), measureTableHeight(o)) : num(sz, \"height\")\n r = Math.max(r, num(pos, \"vertOffset\") + num(om, \"top\") + h + num(om, \"bottom\"))\n }\n }\n return r\n}\n\n/** 문단 run 의 단 정의(ctrl>colPr) → 단 폭. 같은 폭이면 (본문 폭 − 간격×(단 수−1)) ÷ 단 수, 아니면 첫 단(colSz) 폭. 없으면 undefined */\nexport function columnWidthIn(p: Element, bodyW: number): number | undefined {\n for (const run of elements(p)) {\n if (ln(run) !== \"run\") continue\n for (const ch of elements(run)) {\n if (ln(ch) !== \"ctrl\") continue\n const col = findChildByLocalName(ch, \"colPr\")\n if (!col) continue\n const n = Math.max(1, num(col, \"colCount\", 1))\n if (n === 1) return bodyW\n if (col.getAttribute(\"sameSz\") !== \"0\") return Math.trunc((bodyW - num(col, \"sameGap\") * (n - 1)) / n)\n const first = findChildByLocalName(col, \"colSz\")\n return first ? num(first, \"width\", bodyW) : bodyW\n }\n }\n return undefined\n}\n\n/**\n * 문단 run 안 표 칸 밖의 하위 목록 reflow — 머리말·꼬리말은 구역 본문 폭, 각주는 noteW(본문 흐름이면 그 단 폭 —\n * 2단 문서의 미주 lineseg 폭 = 단 폭), 미주는 구역 끝의 단 폭(counter.endNoteW, 없으면 noteW),\n * 도형 글상자(drawText)와 표 캡션은 저장된 글 영역 폭(lastWidth, 글상자는 안 여백을 뺀다).\n * 종전엔 건너뛰어 캐시 없는 문서에서 이 안의 글이 줄 정보 없이 남았다\n */\nexport function reflowSubListsIn(p: Element, doc: Document, styles: RenderStyles, mode: WrapMode, counter: { n: number; bodyW?: number; endNoteW?: number; nums?: NumberCounters }, flow: BlockFlow, noteW = counter.bodyW): void {\n const visit = (el: Element): void => {\n for (const ch of elements(el)) {\n const t = ln(ch)\n if (t === \"footNote\" || t === \"endNote\" || t === \"header\" || t === \"footer\") {\n const sub = findChildByLocalName(ch, \"subList\"), w = t === \"endNote\" ? counter.endNoteW ?? noteW : t === \"footNote\" ? noteW : counter.bodyW\n if (sub && w) flow(sub, doc, styles, w, mode, counter, 0)\n continue\n }\n if (t === \"drawText\" || t === \"caption\") {\n // 글상자는 안 여백(textMargin 좌우)을 뺀 폭 — 한컴 저장 lineseg 실측: lastWidth 30907 − 283×2 → 30340\n const sub = findChildByLocalName(ch, \"subList\"), tm = findChildByLocalName(ch, \"textMargin\")\n // 글 영역 폭이 없으면(lastWidth 를 안 적은 문서) 글상자는 도형 폭\n const textW = num(ch, \"lastWidth\") || (t === \"caption\" ? num(ch, \"width\") : num(findChildByLocalName(el, \"sz\"), \"width\"))\n const w = textW - num(tm, \"left\") - num(tm, \"right\")\n if (sub && w > 0) flow(sub, doc, styles, w, mode, counter, 0)\n continue\n }\n if (t === \"tr\" || t === \"subList\" || t === \"linesegarray\") continue\n visit(ch)\n }\n }\n for (const run of elements(p)) if (ln(run) === \"run\") visit(run)\n}\n\n/** 문단 run 안의 표를 찾아 각 셀 subList를 셀 로컬로 reflow (중첩 재귀) */\nexport function reflowTablesIn(p: Element, doc: Document, styles: RenderStyles, mode: WrapMode, counter: { n: number; bodyW?: number; endNoteW?: number; nums?: NumberCounters }, flow: BlockFlow): void {\n for (const run of elements(p)) {\n if (ln(run) !== \"run\") continue\n for (const obj of elements(run)) {\n if (ln(obj) !== \"tbl\") continue\n const inM = findChildByLocalName(obj, \"inMargin\")\n // 한 칸짜리 칸의 폭은 그 열에서 가장 넓은 칸 폭 — 한컴 저장 lineseg 실측: 열 1 칸 22393 이 같은 열 다른 행 22396 기준으로 21264 (여백 566×2)\n const colMax = new Map<number, number>()\n for (const tr of elements(obj)) for (const tc of elements(tr)) {\n if (ln(tc) !== \"tc\" || num(findChildByLocalName(tc, \"cellSpan\"), \"colSpan\", 1) !== 1) continue\n const c = num(findChildByLocalName(tc, \"cellAddr\"), \"colAddr\"), w = num(findChildByLocalName(tc, \"cellSz\"), \"width\")\n colMax.set(c, Math.max(colMax.get(c) ?? 0, w))\n }\n // 열 경계 = 그 경계에서 끝나는 칸들의 가장 먼 끝(왼쪽 경계 + 칸 폭) — 행마다 칸 폭 합이 다르면 짧은 행의 끝 칸이 늘어난다\n // (한컴 저장본: 565 + 7287 로 끝나는 행 아래 565 + 565 + 6320 행의 끝 칸 줄 폭 6440 = 7852 − 1130 − 여백 282)\n const xs: number[] = []\n {\n const cl = [] as Array<[number, number, number]>\n for (const tr of elements(obj)) for (const tc of elements(tr)) if (ln(tc) === \"tc\") cl.push([num(findChildByLocalName(tc, \"cellAddr\"), \"colAddr\"), num(findChildByLocalName(tc, \"cellSpan\"), \"colSpan\", 1), num(findChildByLocalName(tc, \"cellSz\"), \"width\")])\n cl.sort((p, q) => p[0] - q[0]); xs[0] = 0\n for (const [c, sp, w] of cl) xs[c + sp] = Math.max(xs[c + sp] ?? 0, (xs[c] ?? 0) + w)\n }\n for (const tr of elements(obj)) {\n if (ln(tr) !== \"tr\") continue\n for (const tc of elements(tr)) {\n if (ln(tc) !== \"tc\") continue\n const csz = findChildByLocalName(tc, \"cellSz\")\n // hasMargin=\"0\" 이면 표 안 여백(inMargin) — collectCells 와 같은 해석\n const cm = tc.getAttribute(\"hasMargin\") === \"0\" ? null : findChildByLocalName(tc, \"cellMargin\")\n // 모든 열에 걸친 칸은 표 폭 — 한컴 저장 lineseg 실측: 7열 병합 칸 47899 가 표 폭 47943 기준으로 47660 (여백 141×2). 일부 열 병합은 제 폭\n const span = num(findChildByLocalName(tc, \"cellSpan\"), \"colSpan\", 1)\n let cellW = span === 1 ? colMax.get(num(findChildByLocalName(tc, \"cellAddr\"), \"colAddr\")) ?? num(csz, \"width\")\n : span === num(obj, \"colCnt\") ? num(findChildByLocalName(obj, \"sz\"), \"width\") || num(csz, \"width\") : num(csz, \"width\")\n const ca = num(findChildByLocalName(tc, \"cellAddr\"), \"colAddr\")\n const gw = xs[ca + span] !== undefined && xs[ca] !== undefined ? xs[ca + span] - xs[ca] : 0\n if (gw > cellW) cellW = gw\n const mL = cellMarginOf(cm, \"left\", num(inM, \"left\", 141))\n const mR = cellMarginOf(cm, \"right\", num(inM, \"right\", 141))\n const areaW = Math.max(500, cellW - mL - mR)\n const sub = findChildByLocalName(tc, \"subList\")\n if (sub) flow(sub, doc, styles, areaW, mode, counter, 0)\n }\n }\n }\n }\n}\n","/**\n * 문단 번호(paraPr heading NUMBER) 머리 글 — reflow(앞머리 폭)와 그리기가 같은 번호를 쓴다.\n * 번호 정의의 수준별 머리(`^1.`·`(^3)`)에서 ^N 자리에 N 수준 번호를 그 수준 형식(numFormat)으로 넣는다.\n * 번호는 문서 순서로 센다 — 어떤 수준이 나오면 그 수준이 하나 늘고 더 깊은 수준은 처음부터 다시 센다.\n */\n\nimport type { NumberHead, RenderParaGeom } from \"./head-styles.js\"\n\n/** 번호 정의 id → 수준별 현재 번호(1부터 수준 인덱스) */\nexport type NumberCounters = Map<string, number[]>\n\nconst HANGUL_SYLLABLE = \"가나다라마바사아자차카타파하\"\nconst HANGUL_JAMO = \"ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎ\"\nconst IDEOGRAPH = \"一二三四五六七八九十\"\n\nfunction roman(n: number): string {\n const t: Array<[number, string]> = [[1000, \"M\"], [900, \"CM\"], [500, \"D\"], [400, \"CD\"], [100, \"C\"], [90, \"XC\"], [50, \"L\"], [40, \"XL\"], [10, \"X\"], [9, \"IX\"], [5, \"V\"], [4, \"IV\"], [1, \"I\"]]\n let s = \"\"\n for (const [v, r] of t) while (n >= v) { s += r; n -= v }\n return s\n}\n\n/** 번호 n(1부터)을 한컴 번호 형식으로 */\nexport function formatHeadNumber(n: number, format: string): string {\n const cyc = (set: string): string => set[(n - 1) % set.length]\n switch (format) {\n case \"HANGUL_SYLLABLE\": return cyc(HANGUL_SYLLABLE)\n case \"HANGUL_JAMO\": return cyc(HANGUL_JAMO)\n case \"CIRCLED_DIGIT\": return n >= 1 && n <= 20 ? String.fromCodePoint(0x245f + n) : String(n)\n case \"CIRCLED_HANGUL_SYLLABLE\": return String.fromCodePoint(0x326e + (n - 1) % 14)\n case \"CIRCLED_HANGUL_JAMO\": return String.fromCodePoint(0x3260 + (n - 1) % 14)\n case \"LATIN_SMALL\": return String.fromCharCode(0x61 + (n - 1) % 26)\n case \"LATIN_CAPITAL\": return String.fromCharCode(0x41 + (n - 1) % 26)\n case \"ROMAN_SMALL\": return roman(n).toLowerCase()\n case \"ROMAN_CAPITAL\": return roman(n)\n case \"IDEOGRAPH\": return n >= 1 && n <= 10 ? IDEOGRAPH[n - 1] : String(n)\n default: return String(n)\n }\n}\n\n/** 문단 하나의 번호를 세고 머리 글을 돌려준다. 번호 문단이 아니면 \"\" */\nexport function nextParaNumber(counters: NumberCounters, geom: RenderParaGeom | undefined): string {\n const num = geom?.number\n if (!num) return \"\"\n const cur = counters.get(num.id) ?? []\n const head = num.heads.get(num.level)\n cur[num.level] = (cur[num.level] ?? (head?.start ?? 1) - 1) + 1\n cur.length = num.level + 1 // 더 깊은 수준은 다시 센다\n counters.set(num.id, cur)\n // 수준 숫자가 없는 ^ 는 찍지 않는다(한컴 PDF: 머리 \"^ □\" 문단이 \" □\" 로 시작)\n return (head?.text ?? \"\").replace(/\\^(\\d)?/g, (_m, d: string | undefined) => {\n if (d === undefined) return \"\"\n const lv = Number(d), h: NumberHead | undefined = num.heads.get(lv)\n return formatHeadNumber(cur[lv] ?? h?.start ?? 1, h?.format ?? \"DIGIT\")\n })\n}\n","import { toInt32 } from \"./layout.js\"\n\n/** 저장 문단의 마지막 쪽·단 바닥. 같은 높이의 줄 조각은 가장 낮은 바닥을 유지한다. */\nexport function cachedParagraphBottom(lsa: Element, bodyFlow: boolean): number {\n let bottom = Number.NEGATIVE_INFINITY, previousV = Number.NEGATIVE_INFINITY\n for (let i = 0; i < lsa.childNodes.length; i++) {\n const seg = lsa.childNodes[i] as Element\n if (seg.nodeType !== 1 || seg.localName !== \"lineseg\") continue\n const num = (name: string, fallback = 0) => toInt32(seg.getAttribute(name) ?? undefined, fallback)\n const v = num(\"vertpos\")\n if (bodyFlow && v < previousV) bottom = Number.NEGATIVE_INFINITY\n bottom = Math.max(bottom, v + Math.max(num(\"vertsize\", 1000), num(\"textheight\", 1000)) + num(\"spacing\"))\n previousV = v\n }\n return bottom\n}\n","interface FragmentText {\n text: string; widths: number[]; spacings: number[]; slots: number[]; start: number; end: number\n}\n\n/** 글자 하나가 들어가지 않는 앞 조각은 공백만 채운다. 기존 물리줄의 글자 범위가 유지될 때만 분리한다. */\nexport function appendNarrowLineFragments(parent: Element, seg: Element, free: Array<[number, number]> | undefined,\n box: [number, number] | undefined, flow: FragmentText): boolean {\n if (!free || !box) return false\n const parts = free.filter(([a, b]) => b - a >= 1440)\n if (parts.length < 2 || parts.at(-1)![0] !== box[0] || parts.at(-1)![1] - box[0] !== box[1]) return false\n const { text, widths, spacings, slots, start, end } = flow\n if (/[\\t\\n\\u00a0\\u2005\\ufdd0\\ufffc]/.test(text.slice(start, end))) return false\n let ink = start\n while (ink < end && (text[ink] === \" \" || text[ink] === \"\\u2060\" && widths[ink] === 0)) ink++\n if (text.slice(ink, end).includes(\"\\u2060\")) return false\n if (ink === end || parts.slice(0, -1).some(([a, b]) => (widths[ink] ?? 0) - (spacings[ink] ?? 0) <= b - a)) return false\n const fragments: Array<{ offset: number; x: number; width: number }> = []\n let cursor = start\n for (const [a, b] of parts.slice(0, -1)) {\n const offset = cursor\n let w = 0\n while (cursor < ink && w + widths[cursor] <= b - a) w += widths[cursor++]\n fragments.push({ offset, x: a, width: b - a })\n }\n let rest = 0\n for (let i = cursor; i < end; i++) rest += widths[i]\n let last = end - 1\n if (last > cursor && /[\\uDC00-\\uDFFF]/.test(text[last])) last--\n rest -= spacings[last] ?? 0\n if (rest > box[1] + 0.5) return false\n let next = end\n while (next < text.length && text[next] === \" \") next++\n if (next < text.length && rest + (widths[next] ?? 0) - (spacings[next] ?? 0) <= box[1] + 0.5) return false\n fragments.push({ offset: cursor, x: box[0], width: box[1] })\n fragments.forEach((f, i) => {\n const part = seg.cloneNode(false) as Element\n if (i > 0) part.setAttribute(\"textpos\", String(slots[f.offset]))\n part.setAttribute(\"horzpos\", String(f.x)); part.setAttribute(\"horzsize\", String(f.width))\n parent.appendChild(part)\n })\n return true\n}\n","/** 글자 테두리가 줄 상자에 더하는 높이. */\nimport type { ParaModel } from \"./para-model.js\"\nimport type { RenderStyles } from \"./head-styles.js\"\n\nexport function lineBorderBox(model: ParaModel, styles: RenderStyles, start: number, end: number): [number, number, boolean] {\n const empty = model.chars.length === 0 && model.objs.length === 0\n let top = 0, all = 0\n const include = (prId: string | null): void => {\n const st = prId != null ? styles.charPr.get(prId) : undefined\n const f = st?.borderFill != null ? styles.borderFill.get(st.borderFill) : undefined\n if (!f || (!f.top && !f.bottom)) return\n // 빈 run은 선의 양쪽 정수 반폭을 더한다(0.3mm 저장본: 42×2 = 84HU).\n const width = (pt: number): number => empty ? 2 * Math.trunc(pt * 50) : Math.trunc(pt * 100)\n const t = f.top ? width(f.top.widthPt) : 0, b = f.bottom ? width(f.bottom.widthPt) : 0\n top = Math.max(top, st!.height + t); all = Math.max(all, st!.height + t + b)\n }\n if (empty) for (const run of model.runs) include(run.prId)\n else for (let i = start; i < end; i++) if (model.chars[i].ch) include(model.chars[i].prId)\n return [top, all, empty && all > 0]\n}\n","/**\n * Tier-2 reflow — 조판 캐시(linesegarray)가 없는 문단에 좌표를 합성 주입한다.\n *\n * 한컴은 저장 시 각 줄의 좌표(vertpos/horzpos/…)를 linesegarray로 캐시한다.\n * markdownToHwpx 산출물·에이전트 생성본·편집본엔 이 캐시가 없어 svg-render가\n * KordocError로 거부한다. reflow는 `simulateWrap`(수평, 실측 98% 일치)과 세로 모델\n * (실측 — `.claude/plans/render-poc/findings.md`)로 lineseg를 계산해 DOM\n * `<hp:p>`에 `<hp:linesegarray>`를 append → 그 뒤는 기존 렌더 파이프가 그대로 소비한다.\n *\n * 세로 모델(HWPUNIT): textheight = 줄 지배 charPr.height, baseline = round(0.85×th),\n * 줄 pitch = round(th × lineSpacing%/100), spacing(leading) = pitch − th.\n * 문단 세로 흐름 = 본문영역 로컬 누적(다음문단 = 이전끝 + pitch + next + prev).\n *\n * 원칙: 한컴본 캐시는 절대 건드리지 않는다(Tier-1 무회귀). segs가 있는 문단은 건너뛴다.\n * Phase 3(v4.0.4): 개체 세로 흐름 — float(TOP_AND_BOTTOM)는 텍스트를 outMargin 포함\n * 개체 아래로 밀고, PAGE/PAPER 앵커·BEHIND/IN_FRONT는 흐름 불참, inline 표는 실효높이\n * +leading 전진. 혼합 캐시 문서는 캐시 문단의 한컴 좌표로 커서를 이어 받는다\n * (seoul 코퍼스 자기일관성 59/59 — 36264961 전 문단 d=0 실측).\n */\n\nimport { buildPara, findFirst, isDeletedControl, measureTableHeight, tabAdvance, paraHeadAdvance, captionExtra, OBJ_TAGS, type ExtentMemo, type ParaObj } from \"./para-model.js\"\nimport { squareTableOver, bulletEmptyHost, hasTbFloat, m0Objs, bandTableOver, splitFloatTableRemainder, spacesHost, subFloatBottoms, pageBottomReserve, columnWidthIn, reflowSubListsIn, reflowTablesIn, splitWhole, splitNotesLast, splitMovedLast, type SubFloat } from \"./reflow-tables.js\"\nimport { nextParaNumber, type NumberCounters } from \"./para-number.js\"\nimport { simulateWrap, hancomCharWidth, hancomEmWidth, faceClassForReflow, mulDiv, syntheticBoldEm, type WrapMode } from \"../hwpx/text-metrics.js\"\nimport { BEFORE_2024_WIDTH } from \"../hwpx/face-width-fix.js\"\nimport { fontSpaceEm, fontHasGlyph } from \"../hwpx/font-metrics.js\"\nimport { DEFAULT_CHAR, DEFAULT_PARA_GEOM, type RenderCharStyle, type RenderStyles, type RenderParaGeom } from \"./head-styles.js\"\nimport { findChildByLocalName } from \"../hwpx/parser-shared.js\"\nimport { toInt32 } from \"./layout.js\"\nimport { cachedParagraphBottom } from \"./reflow-cache.js\"\nimport { appendNarrowLineFragments } from \"./reflow-fragments.js\"\nimport { lineBorderBox } from \"./reflow-borders.js\"\n\n/** 표 높이 측정용 새 memo — reflow 는 줄을 고쳐 쓰므로 캐시는 매번 새로, 문단 기하는 떠 있는 개체 위치(문단 위 간격 앞)에 쓴다 */\nconst geomMemo = (styles: RenderStyles): ExtentMemo => ({ cell: new WeakMap(), table: new WeakMap(), paraGeom: styles.paraGeom })\n\n/** lineseg flags 고정값 (한컴 저장본 실측 — 0x60000) */\nconst LINESEG_FLAGS = \"393216\"\n/** baseline / textheight 비율 (실측 94/94 일치) */\nconst BASELINE_RATIO = 0.85\n\n/**\n * 글꼴에 어울리는 줄 높이(fontLineHeight)의 글꼴 위·아래 높이(em 비) — 한컴 저장 lineseg 실측:\n * 맑은 고딕 1200 → 줄 1598·기준선 1307(2230/2048 + 497/2048), 바탕·돋움·굴림·HY 계열 1000 → 1000·858(1758/2048 + 290/2048),\n * 휴먼명조 1000 → 1054·859, KoPub돋움체 Light 1200 → 1320·1020. 표에 없는 글꼴(옛 HFT 등)은 높이 그대로·기준선 85%.\n * 셋째 값이 참이면 아래 높이를 반올림한다 — 맑은 고딕 아래 496/2048: 1100 → 266, 1200 → 291, 2000 → 484, 2100 → 509(한컴 저장본 칸 제목 줄 2662·2796)\n */\nconst FONT_LINE_METRICS: Array<[RegExp, number, number, boolean?]> = [\n [/^맑은 고딕/, 2230 / 2048, 496 / 2048, true],\n [/^(바탕|돋움|굴림|궁서)(체)?$|^한컴바탕$|^HY/, 1758 / 2048, 290 / 2048],\n [/^휴먼명조$/, 0.859, 0.195],\n [/^KoPub(World)?(돋움|바탕)체 Light$/, 0.85, 0.25],\n]\nfunction fontLineMetrics(face: string | undefined, hft?: boolean): [number, number, boolean?] | undefined {\n if (!face || hft && face.trim() === \"한컴바탕\") return undefined\n for (const [re, a, d, up] of FONT_LINE_METRICS) if (re.test(face.trim())) return [a, d, up]\n return undefined\n}\n\nfunction ln(el: Element): string {\n return (el.tagName || \"\").replace(/^[^:]+:/, \"\")\n}\n\nfunction elements(el: Element): Element[] {\n const out: Element[] = []\n const kids = el.childNodes\n if (!kids) return out\n for (let i = 0; i < kids.length; i++) if (kids[i].nodeType === 1) out.push(kids[i] as Element)\n return out\n}\n\nfunction num(el: Element | null, attr: string, fallback = 0): number {\n return el ? toInt32(el.getAttribute(attr) ?? undefined, fallback) : fallback\n}\n\n/** 문단의 합성 linesegarray 줄들의 vertpos를 delta만큼 이동 (페이지 로컬 리셋용) */\nfunction shiftParaVert(p: Element, delta: number): void {\n for (const lsa of elements(p)) {\n if (ln(lsa) !== \"linesegarray\") continue\n for (const seg of elements(lsa)) {\n if (ln(seg) !== \"lineseg\") continue\n seg.setAttribute(\"vertpos\", String(num(seg, \"vertpos\") + delta))\n }\n }\n}\n\nexport interface ReflowGeom {\n BODY_W: number\n BODY_H: number\n}\n\n/** 조합형 자모 — 첫소리(L)·가운뎃소리(V)·끝소리(T) */\nconst isJamoL = (cp: number): boolean => (cp >= 0x1100 && cp <= 0x115f) || (cp >= 0xa960 && cp <= 0xa97c)\nconst isJamoV = (cp: number): boolean => (cp >= 0x1160 && cp <= 0x11a7) || (cp >= 0xd7b0 && cp <= 0xd7c6)\nconst isJamoT = (cp: number): boolean => (cp >= 0x11a8 && cp <= 0x11ff) || (cp >= 0xd7cb && cp <= 0xd7fb)\nconst isJamoLV = (cp: number): boolean => isJamoL(cp) || isJamoV(cp)\nconst isJamoVT = (cp: number): boolean => isJamoV(cp) || isJamoT(cp)\n/** 옛한글 자모 잇기 — 첫소리·가운뎃소리 뒤의 가운뎃소리·끝소리 자모는 앞 글자에 합쳐져 폭이 없다(ᄒ+ᆞ+ᆫ = 1em) */\nexport const joinsJamo = (prevCp: number, cp: number): boolean => isJamoVT(cp) && isJamoLV(prevCp)\n\n/** 한컴 언어 분류 '영문'(U+0250 미만·U+1E00~1FFF·‘’“” 등 U+2018~201F) — 그 글자는 영문 글꼴·장평·자간·상대크기로 잰다 */\nconst isLatinCp = (cp: number): boolean => cp < 0x250 || (cp >= 0x1e00 && cp < 0x2000) || (cp >= 0x2018 && cp < 0x2020)\n\n/**\n * 한컴 언어 분류 — 글자는 제 언어 칸(fontRef)의 글꼴·장평·자간·상대크기로 잰다(한글 2022 줄 나눔: 칸마다 장평을 달리 준 글자 129종).\n * 한글(자모·음절) · 영문 · 한자(CJK 한자) · 일어(가나·〒) · 기호(나머지 — 문장부호·화살표·도형·「」、。·원문자·단위·전각·그리스·키릴).\n * 사용자 영역(PUA)은 한글 칸 그대로 둔다(미측정)\n */\nexport function hancomLangOf(cp: number): \"latin\" | \"hangul\" | \"hanja\" | \"japanese\" | \"symbol\" {\n if (isLatinCp(cp)) return \"latin\"\n if ((cp >= 0x1100 && cp < 0x1200) || (cp >= 0x3130 && cp < 0x3190) || (cp >= 0xa960 && cp < 0xa980) || (cp >= 0xac00 && cp < 0xd800)) return \"hangul\"\n if ((cp >= 0x3400 && cp < 0x4dc0) || (cp >= 0x4e00 && cp < 0xa000) || (cp >= 0xf900 && cp < 0xfb00) || (cp >= 0x20000 && cp < 0x30000)) return \"hanja\"\n if ((cp >= 0x3040 && cp < 0x3100) || (cp >= 0x31f0 && cp < 0x3200) || cp === 0x3012) return \"japanese\"\n if ((cp >= 0xe000 && cp < 0xf900) || cp >= 0xf0000) return \"hangul\"\n return \"symbol\"\n}\n\n/**\n * 한컴 조판의 글자 폭과 그 중 자간 몫(HWPUNIT). 글자는 제 언어(한글/영문)의 글꼴·장평·상대크기로, 첨자는 크기 16/25 로 잰다.\n * 공백은 한글 크기·장평으로 재고 자간만 영문 값을 쓴다(한컴 저장본과 같은 규칙)\n */\nexport function glyphWidth(ch: string, st: RenderCharStyle, fallback = true): { w: number; sp: number } {\n const cp = ch.codePointAt(0)!\n const space = cp === 0x20 || cp === 0xa0\n const lang = space ? \"hangul\" : hancomLangOf(cp)\n const L = space || lang === \"hangul\" ? undefined : st[lang]\n const rel = space ? st.rel ?? 100 : L ? L.rel : st.rel ?? 100\n let h = rel !== 100 ? mulDiv(st.height, rel, 100) : st.height\n if (!space && st.script) h = mulDiv(h, 16, 25)\n const ratio = L ? L.ratio : st.ratio\n const spacing = space ? st.latin?.spacing ?? st.spacing : L ? L.spacing : st.spacing\n // 진하게 HFT 글자는 굵은 글꼴 폭표(HCI Tulip Bold 등)에 그 글자가 있으면 그것으로 잰다(획 넓히기 없이)\n // Batang(영문 이름)은 2024 이전 판에선 바탕 — 한글 2022 는 Batang 으로 적힌 문서를 다시 저장하면 바탕으로 적고 줄 나눔도 바탕과 같다.\n // 2024 판은 한컴바탕으로 잰다(2024 저장본 Batang 문단 두 줄+ 1,342 → 1,384 / 1,451)\n const face1 = L?.face ?? st.face\n const face0 = face1 === \"Batang\" ? st.before2024 ? \"바탕\" : \"한컴바탕\" : face1\n const boldFace = !space && st.bold && (L ? L.hft : st.hft) && face0 && fontHasGlyph(`${face0} Bold`, cp) ? `${face0} Bold` : undefined\n // 한글 2024 이전 판은 일부 기호 폭이 2024 와 다르다(BEFORE_2024_WIDTH) — 그 폭(em×1000)으로 잰다\n // 2024 새 빌드는 휴먼명조 ‘ ’ 도 같은 폭 312(한컴 저장본: 2024 3901 저장 휴먼명조 문단 — 종전 216·588 이면 ‘강력’ 줄이 한 글자 일찍 끊긴다)\n // 휴먼명조 ‧(U+2027)은 2024 초기 빌드(“ ” 반각 전, 3901 미만)도 옛 폭 0.173em(한컴 저장본: 2024 빌드 2725 문단이 그 폭으로 한 줄)\n const oldEm = st.halfQuote && face0 === \"휴먼명조\" && (cp === 0x201c || cp === 0x201d) ? 500 : st.halfQuote && !st.before2024 && face0 === \"휴먼명조\" && (cp === 0x2018 || cp === 0x2019) ? 312 : st.before2024 && face0 && !(face0 === \"신명조\" && (st.halfQuote || (L?.face ? L.hft : st.hft))) ? BEFORE_2024_WIDTH[face0]?.[cp] : !st.halfQuote && face0 === \"휴먼명조\" && cp === 0x2027 ? BEFORE_2024_WIDTH[face0]?.[cp] : undefined\n const fc = faceClassForReflow(boldFace ?? face0)\n // 글꼴 빈칸(useFontSpace=\"1\"): 빈칸도 글자처럼 4·MulDiv(글꼴 빈칸 폭, ⌊크기/4⌋, 1000) — 반각이 아니다\n const fsEm = space && st.fontSpace ? fontSpaceEm(st.face) : undefined\n if (fsEm !== undefined) {\n const q = Math.trunc(h / 4), b = ratio === 100 ? 4 * mulDiv(fsEm, q, 1000) : 4 * Math.trunc(fsEm * q * ratio / 100000)\n const s = spacing ? 4 * mulDiv(Math.trunc(b / 4), spacing, 100) : 0\n return { w: b + s, sp: s }\n }\n const bAdd = !space && st.bold && !boldFace ? syntheticBoldEm(L?.face ?? st.face, L ? L.hft : st.hft) : 0\n if (oldEm !== undefined) {\n const b0 = hancomEmWidth(oldEm + bAdd, h, ratio, 0), w0 = spacing ? hancomEmWidth(oldEm + bAdd, h, ratio, spacing) : b0\n return { w: w0, sp: w0 - b0 }\n }\n const base = hancomCharWidth(ch, h, ratio, 0, fc, bAdd, fallback)\n const w = spacing ? hancomCharWidth(ch, h, ratio, spacing, fc, bAdd, fallback) : base\n return { w, sp: w - base }\n}\n\n/** 어울림(SQUARE·TIGHT·THROUGH) 개체가 글 흐름에서 차지하는 영역 — 그 흐름(본문·칸) 좌표 */\ninterface WrapZone { top: number; bottom: number; left: number; right: number; flow: string; anchor?: number; carry?: number; nextPage?: boolean }\n\n/** 줄 pitch(다음 줄 vertpos 증분, HWPUNIT) — lineSpacing type별 */\nfunction pitchFor(height: number, geom: RenderParaGeom): number {\n const v = geom.lineSpacingValue\n switch (geom.lineSpacingType) {\n // 줄 간격 몫(spacing)은 4 HWPUNIT 단위 — 높이를 먼저 ⌊h/4⌋ 로 내린 뒤 %를 곱해 0에서 먼 쪽으로 반올림한다. 한컴 저장 lineseg 실측:\n // 1400 × 155% → 4·round(350 × 0.55 = 192.5) = 772, 1500 × 90% → −152, 1250 × 160% → 4·round(312 × 0.6 = 187.2) = 748(750 아님),\n // 1270 × 155% → 696. 100% 미만이면 spacing 은 음수다\n case \"PERCENT\": { const e = (Math.trunc(height / 4) * (v - 100)) / 100; return height + 4 * Math.sign(e) * Math.floor(Math.abs(e) + 0.5) }\n case \"FIXED\": return Math.max(0, v) // 고정 줄높이(HWPUNIT) — 0 이면 줄이 겹친다(한컴 저장본: 고정 0 문단의 줄 13개 모두 spacing = −줄 높이)\n case \"AT_LEAST\": return Math.max(v, height)\n default: return Math.round(height * 1.6) // BETWEEN_LINES 등 — 기본 160% 근사\n }\n}\n\n/**\n * 문단 하나의 linesegarray를 합성해 p에 삽입.\n * @returns 세로 흐름 갱신값 (캐시 있어 건너뛴 경우 null)\n */\nfunction reflowPara(\n p: Element,\n doc: Document,\n styles: RenderStyles,\n areaW: number,\n startV: number,\n mode: WrapMode,\n zones: WrapZone[] = [],\n nums: NumberCounters = new Map(),\n /** 본문 흐름인가 — 표 칸 등 하위 목록에서는 떠 있는 위아래 배치 개체가 글을 밀지 않는다 */\n bodyFlow = true,\n /** 쪽 본문 높이(본문 흐름일 때) — 쪽 바닥을 넘는 어울림 개체는 통째로 다음 쪽 위로 */\n pageH = 0,\n): { paraBottom: number; floatFloor: number; textBottom: number; spaceAfter: number } | null {\n const m = buildPara(p)\n const geom = styles.paraGeom.get(m.paraPrId ?? \"\") ?? DEFAULT_PARA_GEOM\n // 문단 번호는 조판 캐시가 있는 문단도 센다(뒤 문단 번호가 밀리지 않게)\n const numText = nextParaNumber(nums, geom)\n if (m.segs.length > 0) return null // 이미 캐시 있음 — Tier-1 무회귀\n\n // 실텍스트 + UTF-16 유닛 → chars 슬롯 인덱스 매핑 (서로게이트 쌍은 슬롯 1개, 유닛 2개).\n // 폭은 글자마다 제 charPr(글꼴·크기·장평·자간)로 — 부호 run 과 압축된 내용 run 이 섞인 문단도 한컴과 같게.\n // 탭은 \"\\t\" 한 글자로 넣고 폭 = 탭 전진폭(첫 줄 기준 — 항목부호 뒤 내어쓰기용 자동 탭).\n // 묶음 빈칸은 U+00A0 — 공백 폭이지만 줄을 끊지 않는다(\"2026. 9. 23.\"·\"3억 원\")\n const realIdx: number[] = []\n /** 오른쪽 탭 자리(text 의 UTF-16 위치) */\n const rightTabs = new Set<number>()\n /** 오른쪽 탭 폭 다시 재기 — widths 자리·탭 앞 x·탭 뒤 글 폭(줄 폭이 정해진 뒤 맞춘다) */\n const rightTabFit: Array<{ wi: number; x: number; after: number }> = []\n const widths: number[] = []\n const spacings: number[] = []\n let text = \"\"\n let x = Math.max(geom.marginIntent, 0) // 탭 정지점은 왼쪽 여백 기준 — 첫 줄 들여쓰기만큼 들어가서 시작\n // 글자처럼 취급하는 개체(treatAsChar 표·그림)는 폭(outMargin 좌우 포함)을 가진 글자 하나로 줄 채우기에 넣는다 —\n // 한컴도 개체를 그 폭의 글자로 줄에 채운다. 넓은 표 두 개는 줄을 하나씩 차지한다(정답 lineseg textpos 0·8)\n const inlineAt = new Map<number, ParaObj>()\n for (const o of m.objs) if (o.inline) inlineAt.set(o.index, o)\n for (let i = 0; i < m.chars.length; i++) {\n const c = m.chars[i]\n const io = inlineAt.get(i)\n if (io) {\n const adv = io.omL + io.width + io.omR\n realIdx.push(i); widths.push(adv); spacings.push(0); text += \"\\ufffc\"; x += adv\n continue\n }\n if (c.tab) {\n let adv = tabAdvance(x, true, geom, c.tabW)\n if (c.tabRight) {\n rightTabs.add(text.length)\n // 오른쪽 탭은 한컴이 조판 때마다 탭 폭을 다시 잰다 — 저장 폭으로 탭 뒤 글이 줄 끝을 넘으면 줄 끝에서 끝나게 줄인다\n // (한컴 저장본: 차례 \"…작성·활용⇥ 259\" 가 저장 탭 폭으로는 31 넘치지만 한 줄)\n let after = 0\n for (let k = i + 1; k < m.chars.length && !m.chars[k].tab; k++) {\n const ck = m.chars[k]\n if (!ck.ch) continue\n after += glyphWidth(ck.ch, (ck.prId != null ? styles.charPr.get(ck.prId) : undefined) ?? DEFAULT_CHAR).w\n }\n rightTabFit.push({ wi: widths.length, x, after })\n }\n realIdx.push(i); widths.push(adv); spacings.push(0); text += \"\\t\"; x += adv\n continue\n }\n if (c.ctrl) {\n // 컨트롤 — 줄의 내용으로 친다(뒤에서 넘치는 개체는 다음 줄로). 주석 머리 번호(\"1)\")처럼 글을 그리는 컨트롤은\n // 그 글 폭의 한 덩어리(미주 lineseg 실측: 8.0pt 문단이 \"1) \" 몫만큼 일찍 꺾인다), 쪽 번호·필드 등은 폭 0\n let w = 0\n if (c.ctrlText) {\n const st0 = (c.prId != null ? styles.charPr.get(c.prId) : undefined) ?? DEFAULT_CHAR\n // 주석 번호 폭은 한글 2024 가 진하게를 빼고 잰다(2024 저장 시험지 미주 +15) — 2024 이전 판은 진하게 그대로(한글 2022 재조판)\n const st1a = styles.before2024 ? st0 : { ...st0, bold: false }\n // 주석 머리 번호(\"17)\")에는 자간을 매기지 않는다(한글 2022 줄 나눔: 바탕 9pt 자간 −5 각주 130개 — 자간을 넣으면 두 자리 번호 문단이 한 글자 더 든다)\n const st1 = c.ctrlSup ? st1a : { ...st1a, spacing: 0, ...(st1a.latin ? { latin: { ...st1a.latin, spacing: 0 } } : {}) }\n // 각주·미주 본문 참조 번호는 글자 크기의 3/4 로 잰다(한글 2022 줄 나눔: 번호 1~3자리 모두 75~77% 에서 맞는다. 위첨자 16/25 는 좁다)\n const st = c.ctrlSup ? { ...st1, height: mulDiv(st1.height, 3, 4) } : st1\n for (const ch of c.ctrlText) w += glyphWidth(ch, st).w\n }\n realIdx.push(i); widths.push(w); spacings.push(0); text += w > 0 ? \"\\ufffc\" : c.fieldEnd ? \"\\ufdd0\" : \"\\u2060\"; x += w\n continue\n }\n if (c.br) {\n // 강제 줄바꿈 — 그 뒤 글은 새 줄(simulateWrap 이 \\n 에서 끊는다)\n realIdx.push(i); widths.push(0); spacings.push(0); text += \"\\n\"; x = Math.max(0, -geom.marginIntent)\n continue\n }\n if (c.ch === \"\") continue\n const st = (c.prId != null ? styles.charPr.get(c.prId) : undefined) ?? DEFAULT_CHAR\n // 폭 테이블: 고정폭 글꼴(굴림체류)은 전용 클래스 — 함초롬 테이블(한글 0.97em)로 재면 줄당 1~2자\n // 과대적재로 wrap 이 어긋난다 (seoul 코퍼스 3건 실측). 폭표 없는 한글 글꼴은 한글 1em(faceClassForReflow).\n // 글자 폭은 한컴처럼 글자마다 4 단위로 양자화하고, 언어별 글꼴·장평·자간·상대크기와 첨자 크기를 따른다(glyphWidth)\n // 옛한글: 첫소리 자모 뒤의 가운뎃소리·끝소리 자모는 한 글자로 합쳐진다 — 폭은 첫소리 자리의 한 글자 몫뿐(ᄒ+ᆞ+ᆫ = 1em)\n const cp = c.ch.codePointAt(0)!\n const joins = joinsJamo(text.codePointAt(text.length - 1) ?? 0, cp)\n const { w, sp } = joins ? { w: 0, sp: 0 } : glyphWidth(c.ch, st)\n for (let u = 0; u < c.ch.length; u++) { realIdx.push(i); widths.push(u === 0 ? w : 0); spacings.push(u === 0 ? sp : 0) }\n text += c.nb ? \"\\u00a0\" : c.ch\n x += w\n }\n\n // 문단 지배 charPr — 첫 실문자 우선(줄 높이·기준선. 가로 폭은 위 widths 가 글자별로 잰다)\n let domChar = DEFAULT_CHAR\n for (const c of m.chars) {\n if (c.ch !== \"\" && c.prId != null) {\n const st = styles.charPr.get(c.prId)\n if (st) { domChar = st; break }\n }\n }\n // 실문자가 없는 문단(빈 줄·개체 전용)도 run의 charPrIDRef가 줄높이를 지배한다 —\n // DEFAULT_CHAR(1000)로 재면 빈 문단 pitch가 본문(예: 1300→2080)보다 작아 이후\n // 문단 전체가 위로 밀린다 (seoul 코퍼스 36264961 실측 −480×빈줄 누적)\n if (domChar === DEFAULT_CHAR) {\n for (const run of elements(p)) {\n if (ln(run) !== \"run\") continue\n const st = styles.charPr.get(run.getAttribute(\"charPrIDRef\") ?? \"\")\n if (st) { domChar = st; break }\n }\n }\n const height = domChar.height || 1000\n\n const marginL = geom.marginLeft\n // 한컴은 영역 폭(본문·단·칸 안쪽)을 4 HWPUNIT 단위로 내린 뒤 문단 여백을 빼고, 1440(0.5 cm) 보다 좁히지 않는다\n // (저장 lineseg horzsize 실측: 본문 48190 → 48188, 본문 39686 − 왼쪽 여백 1850 → 37834(빼고 내리면 37836), 칸 폭 200~1400 → 1440)\n const avail = Math.max(1440, Math.floor(areaW / 4) * 4 - marginL - geom.marginRight)\n // hanging(intent<0): 둘째 줄부터 |intent| 더 들어감 → contWidth 축소·contHorz 우측 이동.\n // 들여쓰기(intent>0)는 첫 줄을 그만큼 좁혀 채운다 — lineseg horzsize 는 한컴처럼 들여쓰기를 빼지 않은 폭으로 둔다\n const firstWidth = avail\n // 글머리표: 글자 폭 + 간격(textOffset — % 면 글자 크기의 %)만큼 첫 줄이, autoIndent 면 둘째 줄부터도 좁게 찬다\n // (한컴 저장 lineseg 260문단: 맞는 문단 65 → 235. 간격을 글머리표 폭의 % 로 보면 224)\n // 문단 번호도 같다 — 머리 글(\"1.\"·\"가)\") 폭 + 간격 (한컴 저장본 번호 문단 대조)\n const bu = geom.bullet ?? (numText && geom.number ? { ch: numText, ...geom.number } : undefined)\n const bst = (bu?.charPrId != null ? styles.charPr.get(bu.charPrId) : undefined) ?? domChar\n let headW = 0\n if (bu) for (const ch of bu.ch) headW += glyphWidth(ch, bst, bu.useInstWidth !== false).w\n const bulletW = bu ? paraHeadAdvance(bu, height, headW) : 0\n const contBullet = bu?.autoIndent ? bulletW : 0\n // 칸 subList lineWrap=\"SQUEEZE\"(자간 줄여 한 줄)면 글은 줄을 바꾸지 않는다 — 명시적 줄 나눔만(한컴 저장본 SQUEEZE 칸 문단 4,316개 전부 한 줄, 줄 나눔 있는 35개만 여러 줄).\n // 문단 모양의 한 줄로 입력(breakSetting lineWrap=\"SQUEEZE\")도 같다(한컴 저장본: 돋움체 칸 \"(mansikzang@korea.kr)\" 10500 이 칸 폭 9680 에 한 줄. 줄 수 +56)\n const squeeze = (p.parentNode as Element | null)?.getAttribute?.(\"lineWrap\") === \"SQUEEZE\" || !!geom.squeeze\n const NO_WRAP = 1e9\n // 2024 이전 판은 들여쓰기와 글머리표 몫 중 큰 쪽만 첫 줄을 좁힌다(한컴 2022 저장본·2022 재조판: 들여쓰기 295·글머리표 1356 문단이 45251 + 295 폭에 한 줄),\n // 2024 는 둘을 더한다(2024 저장 글머리표 문서)\n // 들여쓰기가 줄 폭 이상이면 한컴은 들여쓰기를 두지 않는다(한컴 저장본: 들여쓰기 32580 문단이 폭 6108 칸에 \"담당 공무원\" 한 줄)\n const intentPos = geom.marginIntent >= avail ? 0 : Math.max(0, geom.marginIntent)\n const firstWrapWidth = squeeze ? NO_WRAP : Math.max(500, avail - (styles.before2024 && bulletW > 0 ? Math.max(intentPos, bulletW) : intentPos + bulletW))\n // 한글 2024 저장본의 번호·글머리표 문단은 공백 압축(condense) 없이 채운다(같은 문서를 압축 0 으로 바꿔 다시 조판하면 저장본 줄 나눔과 같다) —\n // 초기 빌드(early2024)는 압축한다\n const condenseUse = !styles.before2024 && !styles.early2024 && (geom.number || geom.bullet) ? 0 : geom.condense\n for (const r of rightTabFit) {\n const edge = avail - bulletW\n if (r.x + widths[r.wi] + r.after > edge && edge - r.x - r.after >= 0) widths[r.wi] = edge - r.x - r.after\n }\n // 내어쓰기(intent<0)는 둘째 줄부터 그만큼 좁게 채우되, lineseg 의 horzpos·horzsize 는 들여쓰기처럼 바꾸지 않는다\n // (한컴 저장본 내어쓰기 문단 수천 개 전부 둘째 줄 horzpos = 왼쪽 여백 — 그리기가 내어쓰기만큼 민다)\n const contSegWidth = avail\n // 내어쓰기로 남는 폭이 한 글자도 안 되면(칸 7496 에 −10152) 한컴은 둘째 줄부터도 온 폭으로 채운다 — 폭 500 으로 묶으면 한 글자씩 끊긴다\n const hang = avail + Math.min(0, geom.marginIntent) - contBullet\n const contWidth = squeeze ? NO_WRAP : hang < height ? avail - contBullet : hang\n const contHorz = marginL\n\n // 문단 paraPr의 breakSetting이 있으면 그 선언(어절/글자)을 따르고, 없으면 호출자 모드\n const paraMode = geom.wrapMode ?? mode\n const pitch = pitchFor(height, geom)\n\n // ── 떠 있는 개체(treatAsChar=0)의 세로 흐름 (Phase 3 — 한컴 실측 모델, 36264961) ──\n // · TOP_AND_BOTTOM + PARA 앵커: 개체가 문단 상단을 차지하고 텍스트는 outTop+개체높이+outBottom 아래부터 흐른다\n // (두문 결재표 실측: 140+16653+852=17645 정확 일치)\n // · SQUARE·TIGHT·THROUGH(어울림) + PARA 앵커: 글이 개체 둘레로 흐른다 — 개체 영역(위 = max(문단 시작 + vertOffset, 앵커 줄 위),\n // 아래 = 위 + 높이 + outBottom, 옆 = horzOffset − outLeft ~ + 폭 + outRight)과 세로로 겹치는 줄은 남는 폭으로 줄고\n // (정답 lineseg horzpos 12994 = 그림 폭 12144 + outRight 850), 개체는 다음 문단을 밀지 않는다\n // · BEHIND_TEXT/IN_FRONT_OF_TEXT 또는 PAGE/PAPER 앵커: 본문 흐름에 불참 (페이지 하단 직인 스탬프가 커서를 밀던 것 제거) — 단 용지 기준 어울림 개체는\n // 본문 좌표로 옮긴 영역이 같은 쪽 줄을 좁히고, 용지 기준 위 정렬 위아래 배치 개체는 온 폭 띠가 된다\n let floatBelow = 0 // 텍스트 시작을 아래로 미는 float 개체 바닥 (문단 로컬)\n let firstFloatVo = 0 // 첫 위아래 배치 개체의 vertOffset — 글 시작보다 아래면 개체는 글 사이에 끼는 띠가 된다\n /** 앵커 글자가 첫 줄 뒤에 있는 위아래 배치 개체(앵커 칸 위치·높이) — 그 앵커 줄 앞에 낀다 */\n const lineFloats: Array<{ index: number; h: number }> = []\n let objBottom = startV\n // 글자처럼 취급하는 글상자는 안 글이 sz 보다 길면 그 글 높이만큼 자란다(한컴 저장본: sz 1249 인 조건 상자 줄 높이 = 안 글 바닥 7629 + 안 여백 425×2)\n const effHOf = (o: ParaObj): number => (o.tag === \"tbl\" ? Math.max(o.height, measureTableHeight(o.el, geomMemo(styles))) : o.inline ? Math.max(o.height, drawTextHeight(o.el)) : o.height) + captionExtra(o.el)\n let cellFloatBottom = 0, cellTextBelow = 0\n // 칸 안 위아래 배치 개체의 호스트가 공백뿐이면 그 줄은 개체 아래로 내려간다(빈 문단은 제자리) — 한컴 저장본: 칸 안 공백 호스트 8개 중 7개가\n // 개체 바닥 아래(18538 + 1920 + 바깥 283×2 + 표 8328 = 29352), 글자 없는 호스트는 130개가 제자리\n const spacesOnly = spacesHost(p)\n const zoneStart = zones.length\n // 본문의 공백뿐인 호스트는 글 있는 문단처럼 띠를 따른다 — 줄이 개체 세로 오프셋 안에 들면 제자리, 아니면 개체 아래\n // (한컴 저장본: 공백 호스트 29개 중 27개 — 오프셋 289 표 6252 뒤 줄 68526 = 61703 + 289 + 141 + 6252 + 141, 오프셋 1624 위 줄 1500 은 제자리)\n // 겹침 허용(allowOverlap) 위아래 배치 그림만 든 빈 문단도 줄이 그림 아래로 간다(한컴 저장본: 그림 35580 + 바깥 852×2 + 캡션 뒤 줄 39136, 빈 문단 3개 모두 — 같은 꼴 글상자 8개는 제자리)\n const OVP = bodyFlow && m.objs.length > 0 && !m.chars.some(c => c.ch !== \"\" && c.ch.trim() !== \"\") && m.objs.every(o => !o.inline && o.tag === \"pic\" && o.el.getAttribute(\"textWrap\") === \"TOP_AND_BOTTOM\" && findChildByLocalName(o.el, \"pos\")?.getAttribute(\"allowOverlap\") === \"1\")\n // 글머리표 문단인 빈 호스트에 위아래 배치 표만 있으면 줄도 표 아래로 간다(한컴 저장본: 그런 문단 5개 모두 줄이 표 아래, 글머리표 없는 빈 호스트 345개 중 줄 위 306)\n const spacesText = bodyFlow && (spacesOnly || !!OVP || bulletEmptyHost(p, geom))\n const textish = m.chars.some(c => c.ch !== \"\" && !c.nb && c.ch.trim() !== \"\") || m.objs.some(o => o.inline) || spacesText\n for (const o of m.objs) {\n if (o.inline) continue\n const pos = findChildByLocalName(o.el, \"pos\")\n const om = findChildByLocalName(o.el, \"outMargin\")\n const outT = num(om, \"top\"), outB = num(om, \"bottom\")\n const wrapAttr = o.el.getAttribute(\"textWrap\") ?? \"\"\n if (wrapAttr === \"BEHIND_TEXT\" || wrapAttr === \"IN_FRONT_OF_TEXT\") continue\n const vertRel = pos?.getAttribute(\"vertRelTo\") ?? \"PARA\"\n // 용지 기준 어울림 개체 — 본문 좌표(용지 좌표에서 본문 원점을 뺀다)로 영역을 둔다. 같은 쪽의 뒤 문단 줄도 피해 간다\n // (한컴 저장본: 용지 왼쪽 3872 + 바깥 852 그림 35840 옆 줄 horzpos 37164 = 3872 − 왼쪽 여백 4252 + 852 + 35840 + 852)\n // 용지 기준 위 정렬 위아래 배치 개체는 같은 쪽 뒤 글이 겹치지 못하는 온 폭 띠다 — 띠에 닿는 줄부터 띠 아래로, 쪽에 안 들면 다음 쪽\n // (한컴 PDF: 용지 위 48283 그림 27084 에 닿은 문단이 새 쪽 800 — 종전엔 흐름에서 빼 그림 자리에 글을 겹쳤다)\n const paperBand = wrapAttr === \"TOP_AND_BOTTOM\" && (pos?.getAttribute(\"vertAlign\") ?? \"TOP\") === \"TOP\"\n if (vertRel === \"PAPER\" && bodyFlow && (wrapAttr !== \"TOP_AND_BOTTOM\" || paperBand)) {\n const [oxL, oyT, paperW] = paperOrigin(p)\n const hRel = pos?.getAttribute(\"horzRelTo\") ?? \"COLUMN\", hAlign = pos?.getAttribute(\"horzAlign\") ?? \"LEFT\"\n const ho = num(pos, \"horzOffset\"), base = hRel === \"PAPER\" ? -oxL : hRel === \"PARA\" ? marginL : 0, span = hRel === \"PAPER\" ? paperW : hRel === \"PARA\" ? avail : areaW\n const x0 = base + (hAlign === \"RIGHT\" ? span - ho - o.width : hAlign === \"CENTER\" ? (span - o.width) / 2 + ho : ho)\n const vo0 = Math.max(0, num(pos, \"vertOffset\")), top = vertRel === \"PAPER\" ? vo0 - oyT : vo0\n const omLx = num(om, \"left\"), omRx = num(om, \"right\")\n const xs = hAlign === \"RIGHT\" ? x0 - omRx : hAlign === \"CENTER\" ? x0 : x0 + omLx\n // 세로도 가로처럼 개체 자리 = 오프셋 + 바깥 위 — 영역 아래 = 오프셋 + 바깥 위 + 높이 + 바깥 아래\n // (한컴 저장본: 용지 위 5668(= 본문 위) 그림 26440, 바깥 852 — 27360 줄까지 좁고 28800 줄부터 온 폭)\n zones.push({ top, bottom: top + outT + effHOf(o) + outB, left: paperBand ? -1e9 : xs - omLx, right: paperBand ? 1e9 : xs + o.width + omRx, flow: o.el.getAttribute(\"textFlow\") ?? \"BOTH_SIDES\", anchor: o.index })\n continue\n }\n if (vertRel === \"PAGE\" || vertRel === \"PAPER\") continue\n const vo = Math.max(0, num(pos, \"vertOffset\"))\n // vertOffset 은 부호 없는 32비트로 저장된다(4294960072 = −7224) — 위로 올린 개체는 문단 위에서 멈춘다\n const voRaw = num(pos, \"vertOffset\"), voSigned = Math.max(0, voRaw >= 2 ** 31 ? voRaw - 2 ** 32 : voRaw)\n const effH = effHOf(o)\n // 단(문단) 밖으로 완전히 나간 위아래 배치 개체는 이 흐름의 글을 밀지 않는다 — 한컴 저장본: 가운데 정렬 + horzOffset 22531 로 단 오른쪽 밖에\n // 놓인 그림(20400)의 빈 앵커 문단 다음 줄이 바로 이어진다(시험지 문서 9개)\n if (wrapAttr === \"TOP_AND_BOTTOM\") {\n const hR = pos?.getAttribute(\"horzRelTo\") ?? \"COLUMN\", hA = pos?.getAttribute(\"horzAlign\") ?? \"LEFT\"\n const hoff = num(pos, \"horzOffset\"), b0 = hR === \"PARA\" ? marginL : 0, sp = hR === \"PARA\" ? avail : areaW\n const xL = b0 + (hA === \"RIGHT\" ? sp - hoff - o.width : hA === \"CENTER\" ? (sp - o.width) / 2 + hoff : hoff)\n if ((hR === \"COLUMN\" || hR === \"PARA\") && (xL >= areaW || xL + o.width <= 0)) continue\n }\n if (wrapAttr === \"TOP_AND_BOTTOM\") {\n // 표 칸 안에서는 그 문단의 글을 밀지 않는다(한컴 저장본: 칸 안 떠 있는 위아래 개체 문단 202개 중 201개가 첫 줄 vertpos 0) —\n // 다음 문단은 개체 바닥(문단 위치 + vertOffset + 바깥 위 + 높이 + 바깥 아래) 아래에서 시작한다(칸 안 위아래 개체 뒤 문단 114개)\n // 같은 문단의 위아래 배치 개체는 겹치지 않고 차례로 쌓인다 — 위치 = max(앞 개체 바닥, vertOffset)\n // (한컴 저장본: 보도자료 머리 표 셋 3481·2797·12846 + 바깥 여백 283×2 씩 = 첫 줄 vertpos 20822)\n if (bodyFlow) {\n // 앵커 글자가 첫 줄 뒤에 있으면 개체는 그 앵커 줄 위에 끼고, 그 줄부터 개체 아래로(한컴 저장본: 연락처 문단 인라인 표 줄 56218,\n // 떠 있는 표 3764 + 566 뒤 둘째 줄 64776) — 줄을 나눈 뒤 정한다\n if (voSigned === 0 && textish) { lineFloats.push({ index: o.index, h: outT + effH + outB }); continue }\n if (floatBelow === 0) firstFloatVo = voSigned\n floatBelow = Math.max(floatBelow, voSigned) + outT + effH + outB\n } else if (spacesOnly) cellTextBelow = Math.max(cellTextBelow, voSigned + outT + effH + outB)\n else cellFloatBottom = Math.max(cellFloatBottom, voSigned + outT + effH + outB)\n continue\n }\n const hRel = pos?.getAttribute(\"horzRelTo\") ?? \"COLUMN\", hAlign = pos?.getAttribute(\"horzAlign\") ?? \"LEFT\"\n const ho = num(pos, \"horzOffset\"), base = hRel === \"PARA\" ? marginL : 0, span = hRel === \"PARA\" ? avail : areaW\n const x0 = base + (hAlign === \"RIGHT\" ? span - ho - o.width : hAlign === \"CENTER\" ? (span - o.width) / 2 + ho : ho)\n const top = startV - (bodyFlow && vertRel === \"PARA\" && wrapAttr === \"SQUARE\" ? geom.spaceBefore : 0) + vo\n // 개체 자리 = 오프셋 + 바깥 왼쪽(오른쪽 정렬은 − 바깥 오른쪽) — 한컴 PDF 실측(렌더러와 같다). 영역은 바깥 여백까지\n const omLx = num(om, \"left\"), omRx = num(om, \"right\")\n const xs = hAlign === \"RIGHT\" ? x0 - omRx : hAlign === \"CENTER\" ? x0 : x0 + omLx\n // carry: 쪽 바닥을 넘어 다음 쪽 위로 옮겨질 때 그 쪽 위부터 막는 높이(바깥 위 + 높이 + 바깥 아래 — 세로 오프셋은 버린다, 칸 안 넘김과 같다.\n // 한컴 저장본: 오프셋 3566 + 바깥 510 + 그림 25554 + 캡션 3450 인 그림이 넘어간 쪽에서 30000 줄까지 좁고 32000 줄부터 온 폭)\n // 쪽 바닥을 넘는 개체는 이 쪽에 두지 않고 통째로 다음 쪽 맨 위로 — 이 쪽 줄은 좁히지 않는다(한컴 저장본: 바닥 근처 문단의 어울림 그림 22713 이\n // 그 문단과 뒤 문단 줄을 온 폭으로 두고 다음 쪽 첫 줄부터 좁힌다)\n const nextPage = pageH > 0 && top + effH + outB > pageH\n zones.push({ top: nextPage ? -1 : top, bottom: nextPage ? -1 : top + effH + outB, left: xs - omLx, right: xs + o.width + omRx, flow: o.el.getAttribute(\"textFlow\") ?? \"BOTH_SIDES\", anchor: nextPage ? undefined : o.index, carry: outT + effH + outB, ...(nextPage ? { nextPage } : {}) })\n }\n // 글 없는 문단(개체·컨트롤만)은 줄이 제자리에 남고 개체가 문단 바닥을 민다 — 한컴 저장본: 두문 표만 있는 첫 문단 줄 vertpos 0, 다음 문단 17645\n // 글자처럼 취급하는 개체(인라인 표·그림)도 줄을 차지하는 내용이다 — 한컴 저장본: 떠 있는 머리 표(4741 + 바깥 566) 아래 인라인 표 줄 vertpos 5307\n const hasText = textish\n // 그런 개체가 둘 이상이면 빈 줄도 그 아래로 내려간다(한컴 저장본: 머리 표 셋인 첫 문단 19개 중 17개, 하나면 181개 중 178개가 제자리)\n const nFloat = m.objs.filter(o => !o.inline && o.el.getAttribute(\"textWrap\") === \"TOP_AND_BOTTOM\" && (findChildByLocalName(o.el, \"pos\")?.getAttribute(\"vertRelTo\") ?? \"PARA\") === \"PARA\").length\n // 위아래 배치 개체는 문단 영역 맨 위(문단 위 간격 앞)에 놓이고, 글은 max(위 간격 뒤, 개체 바닥)에서 시작한다 — 위 간격을 개체 아래에 더하지 않는다.\n // 글 없는 문단의 개체 바닥은 다음 문단 첫 줄의 바닥선이다(그 문단 위 간격도 더하지 않는다). 한컴 저장본: 위 간격 1000 인 두문 표 문단 첫 줄 17645\n // (= 140 + 16653 + 852), 위 간격 500 인 빈 문단의 표 25320 + 10895 = 다음 문단 36215\n const areaTop = bodyFlow ? startV - (geom.spaceBefore ?? 0) : startV\n let floatFloor = 0\n if (!hasText && nFloat < 2) { objBottom = areaTop + floatBelow; if (bodyFlow) floatFloor = objBottom; floatBelow = 0 }\n // 글 있는 문단에서 개체가 글 시작보다 아래에 놓이면(vertOffset) 글을 밀지 않고 띠가 된다 — 띠와 겹치는 줄부터 띠 아래로\n // (한컴 저장본: vertOffset 6770 표 위 두 줄은 문단 위치 그대로 25805·27885)\n let band: [number, number] | undefined\n if (floatBelow > 0 && hasText && areaTop + firstFloatVo > startV) {\n band = [areaTop + firstFloatVo, areaTop + floatBelow]; floatBelow = 0\n // 띠는 뒤 문단에도 영역으로 남는다 — 띠 위에서 끝나는 뒤 문단은 제자리, 띠에 닿는 문단부터 띠 아래로\n // (한컴 저장본: 오프셋 3022 표 띠 36235~ 위의 빈 문단 35213 은 그대로, 그다음 문단이 표 바닥 54688)\n }\n let textStartV = floatBelow > 0 ? Math.max(startV, areaTop + floatBelow) : startV\n if (cellTextBelow > 0) textStartV = Math.max(textStartV, startV + cellTextBelow)\n // 앞 문단의 어울림 개체가 첫 줄 자리를 거의 다 덮으면(남는 틈 1440 미만) 문단은 그 개체 아래에서 시작한다\n // (한컴 저장본: 본문보다 넓은 어울림 그림 아래 문단들이 그림 바닥 41121 부터. 틈에 한 글자씩 넣던 것)\n // 문단이 글자처럼 취급한 개체로 시작하면 그 개체(바깥 여백 포함)가 들 틈이어야 한다(한컴 저장본: 폭 41552 인라인 표가 앞 문단 그림 옆 틈 25139 에 안 들어 그림 아래 27183)\n const firstInline = m.objs.find(o => o.inline)\n const needW = firstInline && !m.chars.slice(0, firstInline.index).some(c => c.ch !== \"\" && c.ch.trim() !== \"\") ? Math.max(1440, firstInline.omL + firstInline.width + firstInline.omR) : 1440\n for (let guard = 0; guard < 8 && zoneStart > 0; guard++) {\n const y0 = textStartV, y1 = y0 + height\n let free: Array<[number, number]> = [[marginL, marginL + avail]], bottom = -1\n for (const z of zones.slice(0, zoneStart)) {\n if (!(y1 > z.top && y0 < z.bottom)) continue\n bottom = Math.max(bottom, z.bottom)\n free = free.flatMap(([a, b]): Array<[number, number]> => (z.right <= a || z.left >= b ? [[a, b] as [number, number]] : [[a, Math.max(a, z.left)] as [number, number], [Math.min(b, z.right), b] as [number, number]]).filter(([c, d]) => d - c > 0))\n }\n if (bottom < 0 || free.some(([a, b]) => b - a >= needW)) break\n textStartV = bottom\n }\n\n /** 줄 i 의 [horzpos, horzsize] — 어울림 개체와 세로로 겹치면 남는 폭(넓은 쪽, LEFT_ONLY/RIGHT_ONLY 는 그쪽) */\n const lineBox: Array<[number, number] | undefined> = []\n /** 줄 i 가 양쪽에 걸친 어울림 개체 사이에 남긴 조각들(왼쪽부터) — 둘 이상일 때만 */\n const lineParts: Array<Array<[number, number]> | undefined> = []\n const collisionHeights: number[] = []\n const boxAt = (i: number): [number, number] | undefined => {\n if (!zones.length) return undefined\n if (i in lineBox) return lineBox[i]\n const y0 = textStartV + i * pitch, y1 = y0 + Math.max(height, collisionHeights[i] ?? 0)\n let free: Array<[number, number]> = [[marginL, marginL + avail]], hit = false, flow = \"BOTH_SIDES\"\n for (const z of zones) {\n if (!(y1 > z.top && y0 < z.bottom)) continue\n hit = true; flow = z.flow\n free = free.flatMap(([a, b]): Array<[number, number]> => {\n const parts: Array<[number, number]> = z.right <= a || z.left >= b ? [[a, b]] : [[a, Math.max(a, z.left)], [Math.min(b, z.right), b]]\n return parts.filter(([c, d]) => d - c > 0)\n })\n }\n let box: [number, number] | undefined\n if (hit) {\n const pick = flow === \"LEFT_ONLY\" ? free[0] : flow === \"RIGHT_ONLY\" ? free[free.length - 1] : free.reduce((x, y) => (y[1] - y[0] > x[1] - x[0] ? y : x), free[0] ?? [marginL, marginL])\n box = pick ? [pick[0], pick[1] - pick[0]] : [marginL, 0]\n if (flow === \"BOTH_SIDES\" && free.length > 1) lineParts[i] = free\n }\n lineBox[i] = box\n return box\n }\n const lineWidth = zones.length\n ? (i: number): number => {\n const b = boxAt(i)\n // 한글 2024 는 왼쪽 어울림 개체가 깎은 줄에서 개체 오른쪽에 문단 왼쪽 여백을 한 번 더 띄운다 — 저장 horzpos 는 개체 끝 그대로\n // (2024 저장본: 왼쪽 여백 850 문단, 개체 끝 2269·폭 35149 줄 넷의 나눔이 모두 폭 34299 로만 맞는다. 같은 문서의 한글 2022 재조판은 35149)\n const w = b ? b[1] - (!styles.before2024 && b[0] > marginL ? marginL : 0) : avail\n return Math.max(500, i === 0 ? w - intentPos - bulletW : w + Math.min(0, geom.marginIntent) - contBullet)\n }\n : undefined\n const own = zones.slice(zoneStart)\n if (own.length && text.length) {\n // 이 문단의 어울림 개체는 앵커 글자가 놓인 줄보다 위로 가지 않는다 — 개체 영역 없이 먼저 나눠 앵커 줄을 찾는다\n // (한컴 저장본: vertOffset 0 인 그림이 셋째 줄에 앵커되면 첫 두 줄은 온 폭, 셋째 줄부터 좁다. 어울림 문단 줄 시작 일치 20 → 61 / 73)\n const keep = zones.slice(0, zoneStart)\n const saved = zones.splice(0, zones.length, ...keep)\n lineBox.length = 0\n const pre = simulateWrap(text, firstWrapWidth, contWidth, height, 100, paraMode, { widths, spacings, condensePct: condenseUse, kinsoku: \"hancom\", before2024: styles.before2024, lineWidth: zones.length ? lineWidth : undefined, latinBreak: geom.latinBreak , rightTabs })\n zones.splice(0, zones.length, ...saved)\n lineBox.length = 0\n for (const z of own) {\n const k = realIdx.indexOf(z.anchor!)\n if (k < 0) continue\n let li = 0\n for (let j = 1; j < pre.starts.length; j++) if (pre.starts[j] <= k) li = j\n const h = z.bottom - z.top, lineTop = textStartV + li * pitch\n if (lineTop > z.top) { z.top = lineTop; z.bottom = lineTop + h }\n // 앵커 글자가 줄 중간이고 개체가 그 줄 위보다 아래서 시작하면 앵커 줄은 좁히지 않는다(한컴 저장본: 문단 끝에 앵커한 오프셋 2650 그림 옆 둘째 줄이 온 폭)\n else if (z.top > lineTop && k > pre.starts[li]) z.top = Math.max(z.top, lineTop + pitch)\n }\n }\n // 글 있는 문단의 어울림 개체가 첫 줄 자리를 다 덮으면(남는 틈 1440 미만) 글은 그 개체 아래에서 시작한다\n // (한컴 저장본: 본문 폭 어울림 표 아래 한 줄 — 틈에 한 글자씩 넣던 것. 그림만 있는 문단은 줄이 제자리)\n if (own.length && textish) {\n for (let guard = 0; guard < 8; guard++) {\n const y0 = textStartV, y1 = y0 + height\n let free: Array<[number, number]> = [[marginL, marginL + avail]], bottom = -1\n for (const z of zones) {\n if (!(y1 > z.top && y0 < z.bottom)) continue\n bottom = Math.max(bottom, z.bottom)\n free = free.flatMap(([a, b]): Array<[number, number]> => (z.right <= a || z.left >= b ? [[a, b] as [number, number]] : [[a, Math.max(a, z.left)] as [number, number], [Math.min(b, z.right), b] as [number, number]]).filter(([c, d]) => d - c > 0))\n }\n if (bottom < 0 || free.some(([a, b]) => b - a >= 1440)) break\n textStartV = bottom\n lineBox.length = 0; lineParts.length = 0\n }\n }\n const wrapLines = () => text.length === 0\n ? { lines: 1, starts: [0], lastLineWidth: 0 }\n : simulateWrap(text, firstWrapWidth, contWidth, height, 100, paraMode, { widths, spacings, condensePct: condenseUse, kinsoku: \"hancom\", before2024: styles.before2024, lineWidth, latinBreak: geom.latinBreak , rightTabs })\n let wrap = wrapLines()\n // 그림이 밀려난 줄도 충돌을 발견한 높이는 유지한다. 다시 넓혀 같은 그림을 끌어오는 진동을 막는다.\n if (zones.length) for (let pass = 0; pass < text.length; pass++) {\n let changed = false\n for (const o of m.objs) if (o.inline) {\n const k = realIdx.indexOf(o.index), om = findChildByLocalName(o.el, \"outMargin\")\n if (k < 0) continue\n let li = 0\n for (let j = 1; j < wrap.starts.length; j++) if (wrap.starts[j] <= k) li = j\n const h = num(om, \"top\") + effHOf(o) + num(om, \"bottom\")\n if (h > Math.max(height, collisionHeights[li] ?? 0)) { collisionHeights[li] = h; changed = true }\n }\n if (!changed) break\n lineBox.length = 0; lineParts.length = 0\n wrap = wrapLines()\n }\n\n // · inline(treatAsChar=1): 그 줄의 높이가 된다 — outMargin 포함 높이\n /** 줄마다 인라인 개체 높이(outMargin 위아래 포함)의 최대 — 그 줄 높이가 된다 */\n const lineObjH = new Array<number>(wrap.starts.length).fill(0)\n /** 줄마다 인라인 개체의 기준선 위 높이(윗부분) 최대 — 수식은 높이 × baseLine%, 그 밖의 개체는 85% */\n const lineObjAsc = new Array<number>(wrap.starts.length).fill(0)\n /** 줄마다 '줄 간격에 영향'(pos affectLSpacing=\"1\") 개체가 있는지 — 그 줄은 줄 간격 몫을 개체까지 든 줄 높이로 잰다 */\n const lineObjLs = new Array<boolean>(wrap.starts.length).fill(false)\n const lineOf = (slot: number): number => {\n let li = 0\n for (let k = 1; k < wrap.starts.length; k++) if ((wrap.starts[k] < realIdx.length ? realIdx[wrap.starts[k]] : Infinity) <= slot) li = k\n return li\n }\n for (const o of m.objs) {\n if (!o.inline) continue\n const om = findChildByLocalName(o.el, \"outMargin\")\n const li = lineOf(o.index)\n const h = num(om, \"top\") + effHOf(o) + num(om, \"bottom\")\n // 폭을 넘긴 표를 시도했던 컨트롤 전용 줄은 점유 높이를 남긴다. 실제 줄 전진은 글자 높이 그대로다.\n if (o.tag === \"tbl\" && li > 0 && o.omL + o.width + o.omR > (lineWidth?.(li - 1) ?? (li === 1 ? firstWrapWidth : contWidth))\n && /^[\\u2060\\ufdd0]+$/.test(text.slice(wrap.starts[li - 1], wrap.starts[li]))) collisionHeights[li - 1] = Math.max(collisionHeights[li - 1] ?? 0, h)\n lineObjH[li] = Math.max(lineObjH[li], h)\n if (findChildByLocalName(o.el, \"pos\")?.getAttribute(\"affectLSpacing\") === \"1\") lineObjLs[li] = true\n // 수식 기준선: 한컴 저장 lineseg 631줄 전부 일치(높이 900·baseLine 86 → 774)\n const bl = o.tag === \"equation\" ? Number(o.el.getAttribute(\"baseLine\")) : NaN\n lineObjAsc[li] = Math.max(lineObjAsc[li], Math.round(h * (Number.isFinite(bl) ? bl / 100 : BASELINE_RATIO)))\n }\n\n const lsa = doc.createElement(\"hp:linesegarray\")\n // 가운데 배치 세로쓰기 하위 목록의 자동 기준선은 글줄 중앙이다(저장본 29문단).\n const subList = p.parentNode as Element | null\n const verticalCenter = subList?.getAttribute?.(\"vertAlign\") === \"CENTER\" && [\"VERTICAL\", \"VERTICALALL\"].includes(subList.getAttribute(\"textDirection\") ?? \"\")\n let v = textStartV\n let firstAcc = 0\n // 실텍스트 없는 문단(인라인 표·개체만)의 textpos는 0 — chars.length로 폴백하면\n // planLines의 plan.start가 개체 index보다 커져 advanceTo 가로 전진에서 개체가\n // 전부 빠지고 같은 x에 겹쳐 그려진다 (공문 결재란 라벨표∩스탬프표 겹침의 원인)\n // 첫 줄은 늘 0 — 문단 앞 컨트롤(구역·단 정의, 개체) 슬롯도 첫 줄에 속한다(한컴 저장 lineseg)\n // 줄 나눔으로 끝난 문단의 마지막 빈 줄은 문단 끝 칸에서 시작한다(한컴 저장본: \"·네이버AI⏎\" 둘째 줄 textpos 8)\n const textposOf = wrap.starts.map((startReal, li) => (li === 0 ? 0 : startReal < realIdx.length ? realIdx[startReal] : realIdx.length ? m.chars.length : 0))\n const heightOf = (prId: string | null): number => (prId != null ? styles.charPr.get(prId)?.height : undefined) || 0\n /** 줄 li 의 글자 높이 — 그 줄 슬롯의 글자와 그 자리 run(마지막 줄은 문단 끝 빈 run 까지) 중 가장 큰 글자 크기.\n * 한컴 저장 lineseg 실측: 표 run 1200 + 문단 끝 빈 run 1500 → 줄간격 180% 의 spacing 1200(1500 기준) */\n const lineTextH = (li: number): number => {\n const s = textposOf[li], last = li === wrap.starts.length - 1, e = last ? m.chars.length : textposOf[li + 1]\n let h = 0\n for (let k = s; k < e; k++) h = Math.max(h, heightOf(m.chars[k].prId))\n for (const r of m.runs) if (r.at >= s && (last ? r.at <= e : r.at < e)) h = Math.max(h, heightOf(r.prId))\n // 문단 번호·글머리표 머리 글은 첫 줄의 글이다 — 머리 글자 모양이 더 크면 첫 줄이 그 높이(한컴 저장본: 1000 문제 발문의 번호 글자 1200 → 줄 1200·간격 960)\n if (li === 0 && bu?.charPrId != null) h = Math.max(h, heightOf(bu.charPrId))\n return h || height\n }\n /** 글꼴에 어울리는 줄 높이 — 줄 li 의 글자마다 글꼴 위·아래 높이로 [줄 높이, 기준선]. 글 없는 줄·표에 없는 글꼴만이면 undefined */\n const fontLineOf = (li: number): [number, number] | undefined => {\n if (!geom.fontLineHeight) return undefined\n const s = textposOf[li], e = li === wrap.starts.length - 1 ? m.chars.length : textposOf[li + 1]\n // ASCII 공백뿐인 줄은 명목 높이 그대로, 글이 있는 줄은 공백 run의 글꼴 높이도 포함한다.\n if (!m.chars.slice(s, e).some(c => c.ch && c.ch !== \" \")) return undefined\n let h = 0, b = 0, any = false\n for (let k = s; k < e; k++) {\n const c = m.chars[k]\n if (!c.ch) continue\n const st = c.prId != null ? styles.charPr.get(c.prId) : undefined\n if (!st) continue\n const cp = c.ch.codePointAt(0)!\n const font = c.ch !== \" \" && st.latin && isLatinCp(cp) ? st.latin : st\n const fm = fontLineMetrics(font.face, font.hft)\n any = true\n // 글꼴 줄 높이 = 반올림한 ascent + 버린 descent(한컴 저장본: 맑은 고딕 1100 → 1198 + 266 = 1464, 1200 → 1307 + 291 = 1598)\n h = Math.max(h, fm ? Math.round(st.height * fm[0]) + (fm[2] ? Math.round : Math.trunc)(st.height * fm[1]) : st.height)\n b = Math.max(b, fm ? Math.round(st.height * fm[0]) : Math.round(st.height * BASELINE_RATIO))\n }\n return any ? [h, b] : undefined\n }\n const natW = widths.reduce((a, w) => a + w, 0) + spacings.reduce((a, w) => a + w, 0)\n for (let li = 0; li < wrap.starts.length; li++) {\n const textpos = textposOf[li]\n // 개체가 있는 줄은 개체 높이가 줄 높이·글자 높이, 기준선은 그 85% (한컴 저장 lineseg 실측: 표 h 3679 + 여백 566 = 4245, 기준선 3608).\n // 줄 간격 몫은 그 줄 글자 높이로 정한다(개체 줄도 — 표 줄 spacing −600 = 1500 × (60% − 100%))\n const fl = fontLineOf(li)\n // 테두리 있는 글자는 글자 상자가 테두리만큼 크다 — 줄 글 높이는 위·아래 테두리까지, 줄 높이(vertsize)는 위 테두리까지\n // (한컴 저장본: 1000 글자 0.15mm 테두리 → 1042·1084, 1200 글자 0.1mm → 1228·1256, 1100 줄의 1000 테두리 글자는 그대로)\n const [boxTop, boxAll, emptyBorder] = lineBorderBox(m, styles, textposOf[li], textposOf[li + 1] ?? m.chars.length)\n const textH0 = fl ? Math.max(fl[0], lineTextH(li)) : lineTextH(li)\n const textH = Math.max(textH0, boxAll)\n // 글 없이 수식만 든 줄은 수식이 글자보다 낮아도 줄 높이가 수식 높이다 — 줄 간격은 글자 높이로(한컴 저장본: 높이 32 수식 줄 vertsize 32, spacing 720 = 1200 × 60%)\n const objOnly = lineObjH[li] > 0 && lineObjH[li] < textH && (() => { const s0 = textposOf[li], e = li === wrap.starts.length - 1 ? m.chars.length : textposOf[li + 1]; for (let k = s0; k < e; k++) { const c = m.chars[k]; if (c.ch && c.ch.trim() !== \"\") return false } return m.objs.some(o => o.inline && o.tag === \"equation\" && lineOf(o.index) === li) })()\n // 글 없이 표만 든 문단 끝 줄은 줄 높이가 표(바깥 여백 포함)와 문단 끝 run 의 글자 크기 중 큰 것 — 표를 담은 run 의 글자 크기는 줄 높이에\n // 들지 않고 줄 간격 몫만 정한다(한컴 저장본: 2600 run 의 1848 표 + 1500 빈 run → 줄 2414·간격 −260 = 2600 × 90%, 표와 빈 글이 한 2600 run 이면 2600).\n // 기준선도 그 둘로(2414 × 85% = 2052)\n const endH = li === wrap.starts.length - 1 && lineObjH[li] > 0 && lineObjH[li] < textH && !m.chars.slice(textposOf[li]).some(c => c.ch && c.ch.trim() !== \"\") &&\n m.objs.some(o => o.inline && o.tag === \"tbl\" && lineOf(o.index) === li) ? heightOf(m.runs[m.runs.length - 1]?.prId ?? null) : -1\n const lineH = objOnly ? lineObjH[li] : endH >= 0 ? Math.max(lineObjH[li], endH) : Math.max(textH, lineObjH[li])\n // 줄간격 100% 미만이면 음수 — 다음 줄·문단이 그만큼 겹쳐 올라온다. '줄 간격에 영향' 개체 줄은 개체까지 든 줄 높이로\n // (한컴 저장본: 140% 문단의 표 줄 60333 → spacing 24132, 그 표 아닌 개체 줄은 글자 높이 1300 → 520)\n // 고정 줄 간격은 개체 줄도 그 간격만 나아간다(한컴 저장본: 고정 1800 문단의 표 줄 20500 → spacing −18700)\n const spBase = lineObjLs[li] || geom.lineSpacingType === \"FIXED\" ? lineH : textH\n const spacing = pitchFor(spBase, geom) - spBase\n if (band && v < band[1] && v + lineH > band[0]) v = band[1]\n // 이 줄에 앵커된(첫 줄이 아니면) 위아래 배치 개체는 줄 위에 끼고 줄은 그 아래 — 첫 줄 앵커는 종전대로 문단 위를 차지\n for (const lf of lineFloats) if (lineOf(lf.index) === li) { if (li > 0) v += lf.h; else { firstAcc += lf.h; v = Math.max(v, areaTop + firstAcc) } }\n const vertpos = v\n // 다음 줄 첫 글자가 큰 run의 시작이면 앞줄 점유 상자에도 든다. 글높이·기준선·줄 전진은 자체 높이를 유지한다.\n const nextStart = textposOf[li + 1], nextChar = m.chars[nextStart]\n const boundaryH = !m.objs.length && !geom.fontLineHeight && nextChar?.ch.trim() &&\n m.runs.some(r => r.at === nextStart && r.prId === nextChar.prId) ? heightOf(nextChar.prId) : 0\n const occupiedH = Math.max(lineH, collisionHeights[li] ?? 0, boundaryH)\n v += lineH + spacing\n const isFirst = li === 0\n const seg = doc.createElement(\"hp:lineseg\")\n seg.setAttribute(\"textpos\", String(textpos))\n seg.setAttribute(\"vertpos\", String(vertpos))\n seg.setAttribute(\"vertsize\", String(emptyBorder ? textH0 : occupiedH === textH && boxAll > textH0 ? Math.max(textH0, boxTop) : occupiedH))\n seg.setAttribute(\"textheight\", String(lineH))\n // 기준선 = 글자(높이의 85%)와 개체 윗부분 중 가장 높은 것 — 줄 높이는 그 둘의 합이 아니라 가장 큰 높이다(수식 1650·1050 줄 → 1650, 기준선 924).\n // 문단 세로 정렬이 가운데면 기준선이 줄 가운데(개체 줄 2817 → 1408, 글 줄 1100 → 550), 아래면 줄 바닥(1100 → 1100)\n // 위 정렬이면 0(한컴 저장본: 세로 정렬 TOP 문단의 줄 668개 모두 baseline 0)\n seg.setAttribute(\"baseline\", String(geom.vertAlign === \"TOP\" ? 0 : geom.vertAlign === \"CENTER\" || verticalCenter && (!geom.vertAlign || geom.vertAlign === \"BASELINE\") ? Math.floor(lineH / 2) : geom.vertAlign === \"BOTTOM\" ? lineH : endH >= 0 ? Math.max(Math.round(endH * BASELINE_RATIO), lineObjAsc[li]) : Math.max(fl ? fl[1] : Math.round(textH0 * BASELINE_RATIO), boxTop > textH0 ? Math.round(boxTop * BASELINE_RATIO) : 0, lineObjAsc[li])))\n seg.setAttribute(\"spacing\", String(spacing))\n let box = boxAt(li)\n // 한 줄 문단이 양쪽에 빈 자리를 남긴 어울림 개체 옆에 오고 글이 왼쪽 조각에 다 들면, 왼쪽 조각에 두고 남은 조각마다\n // 문단 끝 다음 자리의 빈 조각을 둔다(한컴 저장본: 그림 양옆 빈 문단 [0, 왼쪽] [1, 오른쪽], \" - QR코드\" [0, 왼쪽] [10, 오른쪽] — 같은 vertpos)\n // 1440(0.2인치)보다 좁은 조각은 비운다 — 한글 2022 재조판: 왼쪽 조각 1439 는 오른쪽 조각 하나, 1440 은 두 조각\n const fit = wrap.starts.length === 1 && lineObjH[li] === 0 ? lineParts[li]?.filter(([a, b]) => b - a >= 1440) : undefined\n const parts = fit && fit.length > 1 && natW <= fit[0][1] - fit[0][0] - Math.max(0, geom.marginIntent) ? fit : undefined\n if (parts) box = [parts[0][0], parts[0][1] - parts[0][0]]\n seg.setAttribute(\"horzpos\", String(box ? box[0] : isFirst ? marginL : contHorz))\n seg.setAttribute(\"horzsize\", String(box ? box[1] : isFirst ? firstWidth : contSegWidth))\n seg.setAttribute(\"flags\", LINESEG_FLAGS)\n if (paraMode === \"charAll\" && !inlineAt.size && !geom.marginIntent && !bulletW && !condenseUse && appendNarrowLineFragments(lsa, seg, lineParts[li], box,\n { text, widths, spacings, slots: realIdx, start: wrap.starts[li], end: wrap.starts[li + 1] ?? text.length })) continue\n lsa.appendChild(seg)\n for (const [a, b] of parts?.slice(1) ?? []) {\n const more = seg.cloneNode(false) as Element\n more.setAttribute(\"textpos\", String(m.chars.length + 1))\n more.setAttribute(\"horzpos\", String(a))\n more.setAttribute(\"horzsize\", String(b - a))\n lsa.appendChild(more)\n }\n }\n p.appendChild(lsa)\n\n // 문단 바닥 = 텍스트 줄 흐름(float 개체 아래부터)과 개체 바닥 중 큰 쪽.\n // 표는 셀 콘텐츠 성장으로 선언 sz보다 커질 수 있어 drawTable과 같은 실효 높이를 쓴다\n // (셀 lineseg 필요 — reflowBlockFlow가 reflowTablesIn을 먼저 돌린다).\n const textBottom = v\n // 칸 안 개체 바닥은 다음 문단의 하한이다 — 문단 아래·위 간격을 그 위에 더하지 않는다(한컴 저장본: 아래 간격 300 문단의 표 바닥 25319 = 다음 문단 첫 줄)\n if (cellFloatBottom > 0) floatFloor = Math.max(floatFloor, startV + cellFloatBottom)\n if (band) zones.push({ top: band[0], bottom: band[1], left: -1e9, right: 1e9, flow: \"BOTH_SIDES\" })\n return { paraBottom: Math.max(textBottom, objBottom), floatFloor, textBottom, spaceAfter: geom.spaceAfter }\n}\n\n/** 문단에 앵커된, 쪽 위에 붙은 위아래 배치 개체가 차지하는 띠 [위, 아래](바깥 여백 포함). 없으면 [0, 0] */\nconst originMemo = new WeakMap<object, [number, number, number]>()\n/** 본문 영역의 용지 위 원점 [왼쪽, 위]과 용지 폭 — 왼쪽 여백 + 제본(LEFT), 위 여백 + 머리말 (+ 제본 TOP_BOTTOM) */\nfunction paperOrigin(p: Element): [number, number, number] {\n const d = p.ownerDocument as unknown as object\n const hit = originMemo.get(d)\n if (hit) return hit\n const pagePr = (p.ownerDocument?.getElementsByTagName(\"hp:pagePr\")[0] ?? null) as unknown as Element | null\n const mg = pagePr ? findChildByLocalName(pagePr, \"margin\") : null\n const tb = pagePr?.getAttribute(\"gutterType\") === \"TOP_BOTTOM\", gut = num(mg, \"gutter\")\n const o: [number, number, number] = [num(mg, \"left\", 8504) + (tb ? 0 : gut), num(mg, \"top\", 5668) + num(mg, \"header\") + (tb ? gut : 0), num(pagePr, \"width\", 59528)]\n originMemo.set(d, o)\n return o\n}\n\n/** 쪽이 넘어갈 때 — 쪽 바닥을 넘는 문단 기준 어울림 개체는 다음 쪽 위로 옮겨 그 쪽의 줄을 좁힌다(나머지 영역은 버린다).\n * 한컴 저장본: 쪽 아래 56427 문단의 그림(오프셋 3566, 높이 25554, 바깥 510)이 다음 쪽 0~30000 줄을 좁히고 32000 줄부터 온 폭 */\nfunction carryZones(zones: WrapZone[], bodyH: number, oneColumn: boolean): void {\n // 다단(단 폭 흐름)은 개체가 다음 단으로 가므로 옮기지 않는다(시험지 2단 문서: 옮기면 손해)\n const moved = oneColumn ? zones.filter(z => z.carry !== undefined && (z.bottom > bodyH || z.nextPage)).map(z => ({ ...z, top: 0, bottom: z.carry!, carry: undefined, nextPage: undefined })) : []\n zones.length = 0\n zones.push(...moved)\n}\n\nfunction pageTopBand(p: Element): [number, number] {\n let top = Infinity, bot = 0\n for (const run of elements(p)) {\n if (ln(run) !== \"run\") continue\n for (const o of elements(run)) {\n if (!OBJ_TAGS.has(ln(o)) || o.getAttribute(\"textWrap\") !== \"TOP_AND_BOTTOM\") continue\n const pos = findChildByLocalName(o, \"pos\")\n if (pos?.getAttribute(\"treatAsChar\") === \"1\" || pos?.getAttribute(\"vertRelTo\") !== \"PAGE\" || (pos?.getAttribute(\"vertAlign\") ?? \"TOP\") !== \"TOP\") continue\n const om = findChildByLocalName(o, \"outMargin\"), sz = findChildByLocalName(o, \"sz\")\n const h = ln(o) === \"tbl\" ? Math.max(num(sz, \"height\"), measureTableHeight(o)) : num(sz, \"height\")\n const vo = Math.max(0, num(pos, \"vertOffset\"))\n top = Math.min(top, vo); bot = Math.max(bot, vo + num(om, \"top\") + h + num(om, \"bottom\"))\n }\n }\n return bot > 0 ? [top, bot] : [0, 0]\n}\n\n/** 도형 글상자(drawText)의 글 높이 — 안 글 lineseg 바닥 + 안 여백 위·아래. 글상자가 없으면 0 */\nfunction drawTextHeight(el: Element): number {\n const dt = findChildByLocalName(el, \"drawText\")\n const sub = dt ? findChildByLocalName(dt, \"subList\") : null\n if (!sub) return 0\n let bottom = 0\n for (const q of elements(sub)) {\n if (ln(q) !== \"p\") continue\n const lsa = findChildByLocalName(q, \"linesegarray\")\n for (const seg of lsa ? elements(lsa) : []) if (ln(seg) === \"lineseg\") bottom = Math.max(bottom, num(seg, \"vertpos\") + num(seg, \"vertsize\"))\n }\n const tm = findChildByLocalName(dt!, \"textMargin\")\n return bottom > 0 ? bottom + num(tm, \"top\") + num(tm, \"bottom\") : 0\n}\n\n/** 구역 각주 모양의 간격(secPr footNotePr noteSpacing) — 구분선 위·아래, 각주 사이 */\nfunction footNoteSpacing(root: Element): { above: number; below: number; between: number } {\n const pr = root.getElementsByTagName(\"hp:footNotePr\")[0] as unknown as Element | undefined\n const sp = pr ? findChildByLocalName(pr, \"noteSpacing\") : null\n return { above: num(sp, \"aboveLine\", 850), below: num(sp, \"belowLine\", 567), between: num(sp, \"betweenNotes\", 283) }\n}\n\n/** 각주 하위 목록 높이 — lineseg 바닥(이미 reflow 된 것) */\nfunction footNoteBottom(fn: Element): number {\n const sub = findChildByLocalName(fn, \"subList\")\n let bottom = 0\n for (const q of sub ? elements(sub) : []) {\n if (ln(q) !== \"p\") continue\n const lsa = findChildByLocalName(q, \"linesegarray\")\n for (const seg of lsa ? elements(lsa) : []) if (ln(seg) === \"lineseg\") bottom = Math.max(bottom, num(seg, \"vertpos\") + num(seg, \"vertsize\"))\n }\n return bottom\n}\n\n/** 문단에 든 각주마다 [높이, 참조 글자 자리] — 본문 참조는 그 컨트롤 칸, 표 칸·글상자 안 각주는 그 개체 칸 */\nfunction footNoteRefs(p: Element): Array<[number, number]> {\n const m = buildPara(p)\n const out: Array<[number, number]> = []\n m.chars.forEach((c, i) => { if (c.note && ln(c.note) === \"footNote\") out.push([footNoteBottom(c.note), i]) })\n for (const o of m.objs) for (const fn of Array.from(o.el.getElementsByTagName(\"hp:footNote\") as unknown as Element[])) out.push([footNoteBottom(fn), o.index])\n return out\n}\n\n/** 문단에 든 각주마다 높이 — 하위 목록 lineseg 바닥(이미 reflow 된 것). 문단 안 표 칸·글상자에 붙은 각주도 그 쪽 각주다 */\nfunction footNoteHeights(p: Element, ownOnly = false): number[] {\n const out: number[] = []\n // (한컴 저장본: 그림 표 칸 안 각주 4줄이 있는 쪽은 본문 바닥이 그만큼 올라 다음 제목이 새 쪽으로)\n for (const fn of Array.from(p.getElementsByTagName(\"hp:footNote\") as unknown as Element[])) {\n const sub = findChildByLocalName(fn, \"subList\")\n if (!sub) continue\n // ownOnly: 쪽에서 갈리는 떠 있는 표(CELL·TABLE) 칸 안의 각주는 뺀다\n if (ownOnly) {\n let a: Node | null = fn.parentNode, inSplit = false\n while (a && a !== p) { const e = a as Element; if (ln(e) === \"tbl\" && (e.getAttribute(\"pageBreak\") === \"CELL\" || e.getAttribute(\"pageBreak\") === \"TABLE\") && findChildByLocalName(e, \"pos\")?.getAttribute(\"treatAsChar\") !== \"1\") inSplit = true; a = a.parentNode }\n if (inSplit) continue\n }\n let bottom = 0\n for (const q of elements(sub)) {\n if (ln(q) !== \"p\") continue\n const lsa = findChildByLocalName(q, \"linesegarray\")\n for (const seg of lsa ? elements(lsa) : []) if (ln(seg) === \"lineseg\") bottom = Math.max(bottom, num(seg, \"vertpos\") + num(seg, \"vertsize\"))\n }\n out.push(bottom)\n }\n return out\n}\n\n/**\n * 한 블록 컨테이너(본문 root 또는 셀 subList) 안 문단들을 세로 흐름으로 reflow.\n * @param bodyH 최상위(본문)일 때만 >0 — 문단 단위 자동 페이지 나눔(vertpos 페이지 로컬 리셋).\n * 셀 subList는 0(페이지 나눔 없음).\n */\nfunction reflowBlockFlow(\n container: Element,\n doc: Document,\n styles: RenderStyles,\n areaW: number,\n mode: WrapMode,\n counter: { n: number; bodyW?: number; endNoteW?: number; nums?: NumberCounters },\n bodyH: number,\n): void {\n let cursorV = 0\n let prevSpaceAfter = 0\n /** 앞 문단(글 없는)의 떠 있는 개체 바닥 — 다음 문단 첫 줄은 그 아래(간격을 더하지 않는다) */\n let floatFloor = 0\n /** 이 쪽(단)에 놓인 각주 수·높이 합 */\n let pageNotes = 0, pageFoot = 0\n /** 쪽 끝 줄과 함께 안 들어 다음 쪽으로 넘긴 각주 수·높이 */\n let carryNotes = 0, carryFoot = 0\n /** 앞 문단까지 이 쪽에 놓인 내용 바닥(끝 줄 바닥, 쪽을 넘긴 표는 그 나머지 바닥) — 넘친 각주를 잴 때 */\n let contentBottom = 0\n /** 떠 있는 표가 쪽 바닥을 넘어 나뉘어 이 문단 뒤로 새 쪽이 시작됐다 — 앞 쪽 각주는 새 쪽 각주 영역에 들지 않는다 */\n let splitPage = false\n const footSp = footNoteSpacing(container)\n /** 이 흐름에 앵커된 어울림 개체 영역 — 뒤 문단의 줄도 피해 간다 */\n const zones: WrapZone[] = []\n /** 이 쪽에서 글이 내려갈 수 있는 바닥 — 쪽 아래에 붙은 위아래 배치 개체(결재란 표 등)가 있으면 그만큼 올라온다 */\n let pageLimit = bodyH\n /** 바로 앞에 놓은 문단(쪽에 걸치지 않고 제자리에 놓인 경우만) — '다음 문단과 함께' 처리용 */\n let prevPlaced: { p: Element; startV: number; top: number; h: number; spaceAfter: number; keepWithNext: boolean } | undefined\n // 구역 본문의 다단(colPr colCount>1) — 단 정의가 나온 문단부터 단 폭으로 채운다(한컴 다단 편집 lineseg horzsize 실측)\n const bodyFlow = areaW === counter.bodyW && bodyH > 0\n // 첫 빈 줄 감추기(secPr visibility hideFirstEmptyLine) — 새 쪽 맨 위에 올 빈 문단(이어진 둘까지)은 앞 쪽 바닥 아래에 남긴다(새 쪽은 다음 글부터)\n const vis = bodyH > 0 ? findFirst(container, \"visibility\") : null\n const hideFirstEmpty = vis?.getAttribute(\"hideFirstEmptyLine\") === \"1\"\n /** 이어서 쪽 바닥 아래에 감춘 빈 문단 수 — 둘까지만 감추고 셋째부터는 새 쪽 맨 위에 놓는다\n * (한컴 저장본: 빈 문단 둘이 같은 자리 74144·74144 에 감춰지고 다음 개체 문단이 새 쪽 0, 이어진 빈 문단 셋째는 새 쪽 0) */\n let hidPrev = 0\n // 칸 안 다단 — 단 폭으로 채우고, 단 나누기 문단은 다음 단 맨 위(한컴 저장본: 2단 칸의 단 나누기 문단 vertpos 0, 줄 폭 19420)\n const cellW = areaW\n let cellCols = 1, cellCol = 0\n for (const p of elements(container)) {\n if (ln(p) !== \"p\") continue\n if (bodyFlow) { const colW = columnWidthIn(p, counter.bodyW!); if (colW !== undefined) areaW = colW }\n else if (bodyH === 0) {\n const colW = columnWidthIn(p, cellW)\n if (colW !== undefined) { cellCols = colW === cellW ? 1 : Math.round((cellW + 1) / (colW + 1)); areaW = colW }\n if (cellCols > 1 && cellCol < cellCols - 1 && cursorV > 0 && p.getAttribute(\"columnBreak\") === \"1\") { cellCol++; cursorV = 0; prevSpaceAfter = 0 }\n }\n // 문단 안 표 셀을 먼저 셀 로컬 좌표로 reflow (본문 세로 흐름과 무관) —\n // reflowPara의 표 실효높이 측정이 셀 lineseg를 읽으므로 호스트 문단보다 앞서야 한다\n reflowTablesIn(p, doc, styles, mode, counter, reflowBlockFlow)\n reflowSubListsIn(p, doc, styles, mode, counter, reflowBlockFlow, bodyFlow ? areaW : undefined)\n const g = styles.paraGeom.get(p.getAttribute(\"paraPrIDRef\") ?? \"\")\n const cursorBefore = cursorV\n let startV = Math.max(cursorV + prevSpaceAfter + (g?.spaceBefore ?? 0), floatFloor)\n floatFloor = 0\n // 쪽 위에 붙은 위아래 배치 개체(vertRelTo=PAGE·vertAlign=TOP, 두문 결재표 등)는 그 아래부터 글을 놓는다(한컴 저장본: 첫 줄 vertpos 17304 = 표 바닥)\n if (bodyH > 0) { const [top, bot] = pageTopBand(p); if (bot > 0 && top <= startV && startV < bot) startV = bot }\n const numsBefore: NumberCounters = new Map([...(counter.nums ?? [])].map(([k, v]) => [k, v.slice()]))\n const zonesBefore = zones.length\n let res = reflowPara(p, doc, styles, areaW, startV, mode, zones, counter.nums, bodyH > 0, bodyH)\n // 앞 문단의 띠에 밀려 첫 줄이 띠 아래로 간 문단은 앵커 개체도 함께 옮긴다 — 띠 바닥에서 다시 조판\n // (한컴 저장본: 띠 표 바닥 22846 에 밀린 위 간격 1416 문단의 표가 22846 − 1416 + 오프셋 2638 에, 다음 문단은 그 바닥 35236)\n if (res && bodyFlow) {\n const lsa0 = findChildByLocalName(p, \"linesegarray\"), s0 = lsa0 ? elements(lsa0).find(e => ln(e) === \"lineseg\") : undefined\n const v0 = s0 ? num(s0, \"vertpos\") : startV\n const bandZ = v0 > startV ? zones.slice(0, zonesBefore).find(z => z.left <= -1e8 && z.bottom === v0 && z.top < v0) : undefined\n if (bandZ && hasTbFloat(p)) {\n p.removeChild(lsa0!)\n zones.length = zonesBefore\n res = reflowPara(p, doc, styles, areaW, v0, mode, zones, new Map([...numsBefore].map(([k, v]) => [k, v.slice()])), bodyH > 0, bodyH)\n startV = v0\n }\n }\n if (!res) {\n // 캐시 보유 문단(Tier-1) — 한컴 실좌표로 커서를 전진시킨다. 혼합 캐시 문서\n // (한컴 저장본을 프로그램 편집해 일부 문단만 캐시가 없는 경우)에서 캐시 없는\n // 문단이 흐름 위치 대신 0에 겹쳐 그려지던 결함 수정 (36264961 실측: 캐시 문단\n // p18 57165+1300+780 → 캐시 없는 p19가 정확히 59245에 붙는다).\n const lsa = findChildByLocalName(p, \"linesegarray\")\n if (lsa) {\n const bottom = cachedParagraphBottom(lsa, bodyFlow)\n if (Number.isFinite(bottom)) {\n cursorV = bottom\n prevSpaceAfter = g?.spaceAfter ?? 0\n }\n }\n continue\n }\n const paraH = res.paraBottom - startV\n // 페이지 넘김은 줄 단위다: 줄 vertpos + vertsize 가 본문 높이를 넘으면 그 줄부터 다음 쪽 맨 위(0)에서 이어진다\n // (간격 몫은 넣지 않는다 — 한컴 저장본에서 쪽에 걸친 문단 97개 중 86개, 나머지는 칸 안 쪽 나눔). 문단 첫 줄은 쪽보다 높아도\n // 쪽 중간에서 넘치면 새 쪽 맨 위로(한컴 저장본: 쪽 높이 표 75704 뒤 쪽보다 153 높은 표 문단이 새 쪽 0, 68984 의 표 줄 71603 도 새 쪽 0).\n // 명시적 쪽 나눔(hp:p pageBreak=\"1\" — 한컴 '쪽 나누기' 저장 속성)과 첫 줄부터 넘치는 문단은 문단째 다음 쪽으로.\n // 단 나누기(hp:p columnBreak=\"1\")도 같다 — 새 단 맨 위(다단 문서는 단마다 본문 높이로 쪽처럼 흐른다)\n const explicitBreak = bodyH > 0 && startV > 0 && (p.getAttribute(\"pageBreak\") === \"1\" || p.getAttribute(\"columnBreak\") === \"1\" || !!g?.pageBreakBefore)\n const lines = bodyH > 0 ? elements(findChildByLocalName(p, \"linesegarray\") ?? p).filter(e => ln(e) === \"lineseg\") : []\n // 쪽 아래에 붙은 위아래 배치 개체(vertRelTo=PAGE·vertAlign=BOTTOM)는 그 쪽 바닥을 개체 몫만큼 올린다 — 앵커 문단이 그 위에 못 들어가면\n // 문단째(개체와 함께) 다음 쪽으로(한컴 저장본: 결재란 표 26793 이 붙은 끝 문단이 새 쪽 0 에서 시작)\n const reserve = bodyH > 0 ? pageBottomReserve(p) : 0\n // 쪽 아래 각주 영역은 본문 바닥을 올린다 — 이 쪽에 놓인 문단의 각주 + 이 문단의 각주, 구분선 위·아래 간격과 각주 사이 간격 포함\n // (한컴 저장본: 각주 900·2072 둘인 쪽은 본문 71714 − (850 + 567 + 2972 + 283) = 67042 까지, 68136 에 닿는 줄은 다음 쪽)\n const fns = bodyH > 0 ? footNoteHeights(p) : []\n const footArea = (n: number, sum: number): number => (n > 0 ? footSp.above + footSp.below + sum + footSp.between * (n - 1) : 0)\n const fnSum = fns.reduce((a, b) => a + b, 0)\n const limFoot = bodyH - footArea(pageNotes + fns.length, pageFoot + fnSum)\n const lim = Math.min(reserve > 0 ? Math.min(pageLimit, bodyH - reserve) : pageLimit, limFoot)\n // 쪽에서 갈리는 떠 있는 표의 칸 안 각주는 앵커 줄과 함께 세지 않는다 — 표를 행으로 가를 때 행이 놓인 쪽의 각주로 센다\n // (한컴 저장본: 칸 안 각주 6개인 7행 표의 빈 앵커 줄 53532 는 제자리, 표는 행마다 각주 영역을 올리며 갈린다)\n const fnsOwn = fns.length ? footNoteHeights(p, true) : fns, ownSum = fnsOwn.reduce((a, b) => a + b, 0)\n const limOwn = fnsOwn.length < fns.length ? Math.min(reserve > 0 ? Math.min(pageLimit, bodyH - reserve) : pageLimit, bodyH - footArea(pageNotes + fnsOwn.length, pageFoot + ownSum)) : lim\n // 줄마다 쪽 바닥 — 그 줄까지 참조된 각주만 이 쪽 각주 영역에 든다(쪽에 걸친 문단: 뒤 줄의 각주는 다음 쪽)\n const refs = bodyH > 0 && fns.length ? footNoteRefs(p) : []\n const tpOf = (seg: Element): number => num(seg, \"textpos\")\n const limAt = (i: number): number => {\n if (!refs.length) return lim\n const end = i + 1 < lines.length ? tpOf(lines[i + 1]) : Number.POSITIVE_INFINITY\n // 둘째 줄부터는 그 줄 자신의 각주를 빼고 잰다 — 줄은 들고 각주만 안 들면 줄은 이 쪽, 각주는 다음 쪽(아래)\n const inn = refs.filter(([, at]) => at < (i > 0 ? tpOf(lines[i]) : end))\n const base = reserve > 0 ? Math.min(pageLimit, bodyH - reserve) : pageLimit\n return Math.min(base, bodyH - footArea(pageNotes + inn.length, pageFoot + inn.reduce((a, [h]) => a + h, 0)))\n }\n // 줄 바닥이 쪽 바닥과 같으면 넘친 것으로 본다(+1) — 저장본에 본문 높이에서 딱 끝나는 줄은 없고, 그런 줄은 다음 쪽 맨 위(한컴 저장본: 68718 + 1300 = 70018 인 줄이 새 쪽 0)\n const lineBottom = (seg: Element): number => num(seg, \"vertpos\") + num(seg, \"vertsize\") + (reserve > 0 ? num(seg, \"spacing\") : 0) + 1\n let firstOver = lines.length > 0 && startV > 0 && lineBottom(lines[0]) > (limOwn !== lim ? limOwn : limAt(0))\n // 글머리표 빈 호스트의 줄은 표 아래 — 넘침은 줄이 아니라 표(행 나눔)로 본다\n const BUH = bodyH > 0 && bulletEmptyHost(p, g)\n if (firstOver && BUH) firstOver = false\n let hidden = false\n if (firstOver && hideFirstEmpty && lines.length === 1 && hidPrev < 2) {\n const pm = buildPara(p)\n if (pm.objs.length === 0 && !pm.chars.some(c => c.ch.trim() !== \"\")) { firstOver = false; hidden = true }\n }\n /** 줄 단위 쪽 넘김으로 뒤 줄들이 옮겨 간 양(음수) — 0 이면 쪽이 안 나뉘었다 */\n let off = 0\n // 넘치는 첫 줄 번호 — 외톨이줄 보호면 쪽 끝 첫 줄 하나만 남기지 않고(문단째), 다음 쪽에 마지막 줄 하나만 보내지 않는다(한 줄 앞에서)\n let cut = -1\n if (!explicitBreak && !firstOver && lines.length > 1) {\n cut = lines.findIndex((seg, i) => i > 0 && lineBottom(seg) > limAt(i) && num(seg, \"vertsize\") <= bodyH)\n if (cut > 0 && g?.widowOrphan && lines.length >= 3 && cut === lines.length - 1) cut--\n }\n // 외톨이줄 보호로 첫 줄만 남거나, 문단 보호(keepLines)면 쪽에 걸치지 않고 문단째 넘긴다\n const orphan = (cut === 1 && !!g?.widowOrphan) || (cut > 0 && !!g?.keepLines)\n if (cut > 0 && !orphan) {\n for (let i = cut; i < lines.length; i++) {\n const seg = lines[i]\n let vp = num(seg, \"vertpos\") + off\n const vs = num(seg, \"vertsize\")\n if (i === cut || (vp > 0 && vp + vs > bodyH && vs <= bodyH)) { off -= vp; vp = 0; carryZones(zones, bodyH, areaW === counter.bodyW) }\n seg.setAttribute(\"vertpos\", String(vp))\n }\n }\n if (explicitBreak || firstOver || orphan || (bodyH > 0 && startV > 0 && lines.length === 0 && res.paraBottom > bodyH && paraH <= bodyH)) {\n // 다음 쪽으로 옮기는 문단이 옛 자리에서 넣은 제 개체 영역은 버린다 — 새 쪽에서 다시 조판하면 새 자리에 다시 생긴다(남기면 넘어간 개체로 새 쪽 위를 막는다.\n // 한컴 PDF: 쪽 나누기 빈 문단의 어울림 표 55942 가 새 쪽 맨 위, 줄도 0)\n const own = zones.length > zonesBefore\n zones.length = zonesBefore\n if (zones.length || own) {\n // 앞 쪽의 어울림 개체는 새 쪽 줄을 좁히지 않는다 — 비우고 새 쪽 상단에서 다시 조판(쪽 바닥을 넘어 옮겨지는 개체만 남긴다)\n carryZones(zones, bodyH, areaW === counter.bodyW)\n const lsa = findChildByLocalName(p, \"linesegarray\")\n if (lsa) p.removeChild(lsa)\n const zb = zones.length\n const sb0 = g?.spaceBefore ?? 0\n let moveRes = reflowPara(p, doc, styles, areaW, sb0, mode, zones, new Map([...numsBefore].map(([k, v]) => [k, v.slice()])), true, bodyH)! // 번호는 이미 셌다 — 센 직전 상태로 다시\n // 옮겨 온 개체 띠에 밀린 첫 줄이면 앵커 표도 그 아래로(위 띠 규칙과 같다)\n const lsaM = findChildByLocalName(p, \"linesegarray\"), sM = lsaM ? elements(lsaM).find(e => ln(e) === \"lineseg\") : undefined\n const vM = sM ? num(sM, \"vertpos\") : sb0\n if (vM > sb0 && zones.slice(0, zb).some(z => z.left <= -1e8 && z.bottom === vM && z.top < vM) && hasTbFloat(p)) {\n p.removeChild(lsaM!); zones.length = zb\n moveRes = reflowPara(p, doc, styles, areaW, vM, mode, zones, new Map([...numsBefore].map(([k, v]) => [k, v.slice()])), true, bodyH)!\n }\n cursorV = moveRes.paraBottom\n // 새 쪽 맨 위로 옮긴 글 없는 문단의 어울림 표가 그 쪽보다 길면 그 쪽부터 행 단위로 나눈다\n if (bodyH > 0 && squareTableOver(p, 0, bodyH)) {\n const split2 = splitFloatTableRemainder(p, 0, bodyH, bodyH, styles)\n if (split2 !== undefined) { cursorV = 0; floatFloor = split2; zones.length = 0; splitPage = true }\n }\n } else {\n // 새 페이지 상단으로 이동 → 프리패스가 vertpos 역행 감지. 문단 위 간격은 새 쪽에서도 남는다(한컴 저장본: 새 쪽 첫 줄 vertpos = prev 1200)\n const top = g?.spaceBefore ?? 0\n shiftParaVert(p, top - startV)\n cursorV = paraH + top\n // 새 쪽으로 옮겨서도 쪽보다 높으면(쪽 나누기 문단의 긴 떠 있는 표) 그 표를 그 쪽부터 나눈다\n if (bodyH > 0 && (top + paraH > bodyH || squareTableOver(p, top, bodyH))) {\n const split2 = splitFloatTableRemainder(p, top, bodyH, bodyH, styles)\n if (split2 !== undefined) { cursorV = 0; floatFloor = split2; zones.length = 0; splitPage = true }\n }\n // 앞 문단이 '다음 문단과 함께'면 그 문단도 새 쪽으로 — 앞 문단을 새 쪽 위에 두고 이 문단을 그 아래로\n if (prevPlaced?.keepWithNext && prevPlaced.startV > prevPlaced.top) {\n shiftParaVert(prevPlaced.p, prevPlaced.top - prevPlaced.startV)\n const base = prevPlaced.top + prevPlaced.h + prevPlaced.spaceAfter\n shiftParaVert(p, base)\n cursorV += base\n }\n }\n } else {\n cursorV = (res.floatFloor > 0 && off === 0 ? res.textBottom : res.paraBottom) + off\n if (res.floatFloor > 0 && off === 0) floatFloor = res.floatFloor\n // 글 없는 앵커 문단의 떠 있는 위아래 배치 표가 쪽 바닥을 넘으면 행 단위로 다음 쪽으로 나뉜다 — 다음 문단은 다음 쪽의 남은 행 아래\n // (한컴 저장본: 1쪽에 행 바닥 + outMargin 아래가 본문 높이 안에 드는 22행, 2쪽에 8행 × 1482 + 141 = 다음 문단 vertpos 11997)\n // 표는 문단 위 여백 앞에서 가른다 — 글머리표 빈 호스트 경로와 같다(한컴 저장본: 위 여백 500 문단의 2행 칸 안 나눔 표의 첫 조각\n // 11,058(= 저장 표 높이 12,840 − 앞 행 1,782)은 위 여백 앞에서 재야 쪽 바닥 안에 든다)\n const split = bodyH > 0 && off === 0 && (res.paraBottom > lim || squareTableOver(p, startV, lim)) ? splitFloatTableRemainder(p, startV - (g?.spaceBefore ?? 0), limOwn, bodyH, styles, false, { n0: pageNotes + fnsOwn.length, s0: pageFoot + ownSum, area: footArea }) : undefined\n // 오프셋 둔 표가 첫 행부터 안 들어 통째로 다음 쪽 맨 위로 가면(다음 쪽에 다 들 때) 이 쪽은 표 자리부터 띠 — 그 위에 드는 뒤 글은 이 쪽에 남고,\n // 다음 쪽 글은 그 표 아래에서(한컴 저장본: 오프셋 3022 그림 표 23062 의 빈 앵커 59941 뒤 문단 61941 은 제자리, 그다음은 새 쪽 23628 = 283 + 23062 + 283)\n const tEl = split !== undefined && splitWhole ? m0Objs(p) : undefined\n const tVo = tEl ? num(findChildByLocalName(tEl, \"pos\"), \"vertOffset\") : 0\n const tOm = tEl ? findChildByLocalName(tEl, \"outMargin\") : null\n if (tEl && tVo > 0 && tVo < 2 ** 31 && num(tOm, \"top\") + measureTableHeight(tEl) + num(tOm, \"bottom\") <= bodyH) {\n const tTop = startV - (g?.spaceBefore ?? 0) + tVo\n zones.push({ top: tTop, bottom: Math.max(bodyH + 1, tTop + 1), left: -1e9, right: 1e9, flow: \"BOTH_SIDES\", carry: split })\n floatFloor = 0; cursorV = res.textBottom\n } else if (split !== undefined && splitMovedLast) {\n cursorV = 0; floatFloor = split; zones.length = 0; splitPage = true\n // 줄이 표 아래에 있는 호스트(글머리표 빈 문단)는 줄도 마지막 쪽의 표 나머지 아래로\n const own = BUH ? elements(findChildByLocalName(p, \"linesegarray\") ?? p).filter(e => ln(e) === \"lineseg\") : []\n if (own.length) {\n const d = split - num(own[0], \"vertpos\")\n for (const sg of own) sg.setAttribute(\"vertpos\", String(num(sg, \"vertpos\") + d))\n cursorV = res.textBottom + d; floatFloor = 0\n }\n }\n // 글 있는 앵커 문단도 옆에 글 들 폭이 없는 어울림 나눔 표가 쪽 바닥을 넘으면 행 단위로 나뉘고, 문단 글은 마지막 쪽의 표 아래로 간다\n // (한컴 저장본: 폭 47903 표가 다음 쪽에서 끝난 뒤 앵커 글 줄이 표 바닥 아래, 다음 문단도 그 아래)\n else if (bodyH > 0 && off === 0 && squareTableOver(p, startV, lim, true, areaW)) {\n const split3 = splitFloatTableRemainder(p, startV, lim, bodyH, styles, true)\n const lsa = findChildByLocalName(p, \"linesegarray\")\n const own = lsa ? elements(lsa).filter(e => ln(e) === \"lineseg\") : []\n // 글 줄이 표 위끝(문단 위 + 세로 오프셋 + 바깥 여백 위)보다 위에서 끝나면 글은 제자리, 다음 문단만 마지막 쪽의 표 나머지 아래로\n // (한컴 저장본: 오프셋 2829 어울림 36행 표의 앵커 글 한 줄 41803 은 첫 쪽 제자리, 다음 문단은 셋째 쪽 표 나머지 아래 29276)\n const sq = m0Objs(p), sqPos = sq ? findChildByLocalName(sq, \"pos\") : null\n const sqVo = num(sqPos, \"vertOffset\"), sqTop = startV + Math.max(0, sqVo >= 2 ** 31 ? sqVo - 2 ** 32 : sqVo) + num(sq ? findChildByLocalName(sq, \"outMargin\") : null, \"top\")\n if (split3 !== undefined && sq && own.length && own.every(sg => num(sg, \"vertpos\") + num(sg, \"vertsize\") <= sqTop)) {\n cursorV = 0; floatFloor = split3; zones.length = 0; splitPage = true\n } else if (split3 !== undefined && own.length) {\n const d = split3 - num(own[0], \"vertpos\")\n for (const sg of own) sg.setAttribute(\"vertpos\", String(num(sg, \"vertpos\") + d))\n cursorV = res.textBottom + d; zones.length = 0; splitPage = true\n }\n }\n // 글 있는 문단의 띠(글 아래 오프셋) 위아래 배치 표가 쪽 바닥을 넘으면 행 단위로 나뉜다 — 문단 글은 제자리(띠 위), 다음 문단은 마지막 쪽의 표 아래\n // (한컴 저장본: 오프셋 2636 표의 앵커 \"조직 및 인력\" 7100 은 제자리, 다음 문단은 다음 쪽 표 나머지 아래 68152). 넘침은 칸 내용 높이로 본다(묵은 칸 높이는 안 봄)\n else if (bodyH > 0 && off === 0 && bandTableOver(p, startV - (g?.spaceBefore ?? 0), lim)) {\n const BU = BUH\n const split4 = splitFloatTableRemainder(p, startV - (g?.spaceBefore ?? 0), BU ? limOwn : lim, bodyH, styles, true, BU ? { n0: pageNotes + fnsOwn.length, s0: pageFoot + ownSum, area: footArea } : undefined)\n if (split4 !== undefined) {\n cursorV = 0; floatFloor = split4; zones.length = 0; splitPage = true\n const own = BU && splitMovedLast ? elements(findChildByLocalName(p, \"linesegarray\") ?? p).filter(e => ln(e) === \"lineseg\") : []\n if (own.length) {\n const d = split4 - num(own[0], \"vertpos\")\n for (const sg of own) sg.setAttribute(\"vertpos\", String(num(sg, \"vertpos\") + d))\n cursorV = res.textBottom + d; floatFloor = 0\n }\n }\n }\n }\n // 쪽 바닥 아래에 감춘 빈 문단은 높이를 차지하지 않는다 — 커서·아래 간격을 그 문단 앞 그대로 둔다\n // (한컴 저장본: 감춘 빈 문단이 이어지면 56197·56197 처럼 겹치고, 위 간격 800 인 감춘 문단 55899 뒤 위 간격 0 문단은 55099)\n const keepCursor = hidden && !explicitBreak\n hidPrev = hidden ? hidPrev + 1 : 0\n prevPlaced = off === 0 && !(explicitBreak || firstOver || orphan) ? { p, startV, top: g?.spaceBefore ?? 0, h: paraH, spaceAfter: res.spaceAfter, keepWithNext: !!g?.keepWithNext } : undefined\n // 새 쪽으로 넘어갔으면 바닥을 되돌리고, 이 문단의 쪽 아래 개체가 있는 쪽이면 그 몫을 남긴다\n const moved = explicitBreak || firstOver || orphan || off !== 0\n pageLimit = reserve > 0 ? bodyH - reserve : moved ? bodyH : Math.min(pageLimit, reserve > 0 ? bodyH - reserve : pageLimit)\n if (moved && refs.length && cut > 0 && !orphan && !explicitBreak && !firstOver) {\n // 쪽에 걸친 문단: 넘어간 줄의 각주만 새 쪽 각주\n // 쪽 끝 줄의 각주가 그 줄과 함께 안 들면(줄만 남았으면) 그 각주도 다음 쪽\n // (한컴 저장본: 각주 900 참조 줄 68915 는 각주 영역 850 + 567 + 900 과 함께 본문 71714 에 안 들지만 그 쪽 끝 줄로 남는다)\n const lastKept = lines[cut - 1], fromKept = tpOf(lastKept)\n const keptRefs = refs.filter(([, at]) => at >= fromKept && at < tpOf(lines[cut]))\n const before = refs.filter(([, at]) => at < fromKept)\n const pushed = keptRefs.length && cut > 1 && lineBottom(lastKept) > bodyH - footArea(pageNotes + before.length + keptRefs.length, pageFoot + [...before, ...keptRefs].reduce((a2, [h]) => a2 + h, 0))\n const from = pushed ? fromKept : tpOf(lines[cut]), mv = refs.filter(([, at]) => at >= from)\n pageNotes = mv.length; pageFoot = mv.reduce((a, [h]) => a + h, 0)\n pageNotes += carryNotes; pageFoot += carryFoot; carryNotes = 0; carryFoot = 0\n } else if (moved) {\n // 앞 쪽 각주가 그 쪽 내용 바닥 아래에 다 안 들면 남는 몫은 다음 쪽 각주 영역으로 이어진다(본문이 먼저 — 각주 많은 표가 그 쪽에 다 들고,\n // 한컴 저장본: 칸 안 각주 18개 표 다음 쪽은 본문이 30000 근처에서 끊긴다)\n {\n const prevBottom = off !== 0 && cut > 0 ? num(lines[cut - 1], \"vertpos\") + num(lines[cut - 1], \"vertsize\") : contentBottom\n const excess = footArea(pageNotes, pageFoot) - (bodyH - prevBottom)\n if (excess > 0 && pageNotes > 0) { carryNotes += 1; carryFoot += excess }\n }\n pageNotes = fns.length + carryNotes; pageFoot = fnSum + carryFoot; carryNotes = 0; carryFoot = 0\n } else if (splitPage) { pageNotes = splitNotesLast.n; pageFoot = splitNotesLast.s; carryNotes = 0; carryFoot = 0 } else {\n // 쪽 끝 줄이 제 각주와 함께 안 드는데 문단이 그 쪽에서 끝났으면 그 각주는 다음 쪽 각주 영역으로 넘어간다\n const last = lines[lines.length - 1]\n const lastRefs = last && lines.length > 1 ? refs.filter(([, at]) => at >= tpOf(last)) : []\n const lastSum = lastRefs.reduce((a, [h]) => a + h, 0)\n if (lastRefs.length && lineBottom(last) > bodyH - footArea(pageNotes + fns.length, pageFoot + fnSum)) {\n pageNotes += fns.length - lastRefs.length; pageFoot += fnSum - lastSum; carryNotes += lastRefs.length; carryFoot += lastSum\n } else { pageNotes += fns.length; pageFoot += fnSum }\n }\n {\n const lsa2 = findChildByLocalName(p, \"linesegarray\"), segs2 = lsa2 ? elements(lsa2).filter(e => ln(e) === \"lineseg\") : [], lastSeg = segs2[segs2.length - 1]\n const lb = lastSeg ? num(lastSeg, \"vertpos\") + num(lastSeg, \"vertsize\") : 0\n contentBottom = splitPage ? floatFloor : keepCursor ? contentBottom : Math.max(lb, res.floatFloor > 0 && off === 0 ? floatFloor : 0)\n }\n splitPage = false\n if (keepCursor) cursorV = cursorBefore\n else prevSpaceAfter = res.spaceAfter\n counter.n++\n }\n}\n\n/**\n * section root의 조판 캐시 없는 문단에 linesegarray를 합성 주입한다(표 셀 재귀 포함).\n * 반환: 합성한 문단 수.\n * (Phase 2~3: 최상위 텍스트 + 표 셀 내부. 개체 밀어내기·자동 페이지 분할은 후속.)\n */\nexport function reflowSection(\n root: Element,\n styles: RenderStyles,\n geom: ReflowGeom,\n mode: WrapMode = \"keep\",\n): number {\n const doc = root.ownerDocument as unknown as Document\n // 미주는 구역 끝에 모여 놓인다 — 폭은 구역 끝의 단 폭(중간에 2단으로 바뀐 구역의 미주 lineseg 폭 = 그 단 폭)\n let endNoteW: number | undefined\n for (const p of elements(root)) if (ln(p) === \"p\") endNoteW = columnWidthIn(p, geom.BODY_W) ?? endNoteW\n const counter = { n: 0, bodyW: geom.BODY_W, endNoteW, nums: new Map() as NumberCounters }\n reflowBlockFlow(root, doc, styles, geom.BODY_W, mode, counter, geom.BODY_H)\n if (geom.BODY_H > 0) flowEndNotes(root, geom.BODY_H)\n return counter.n\n}\n\n/**\n * 구역 끝 미주를 단(쪽) 높이로 흘린다 — 미주 줄은 미주 첫 줄 기준(0)으로 적히고, 단 바닥을 넘는 줄부터 다음 단 맨 위 0 에서 다시 센다.\n * 미주는 본문 끝 줄 바닥 + 구분선 위·아래 간격에서 시작하고, 미주 사이는 앞 미주 끝 줄 바닥 + 미주 사이 간격\n * (한컴 저장본: 2단 시험지 해설 미주 46개, 단 높이 75117·미주 사이 1984 로 흘리면 단 넘김 902곳 중 894곳이 맞는다)\n */\nfunction flowEndNotes(root: Element, bodyH: number): void {\n const notes: Element[] = []\n let last: Element | undefined\n for (const p of elements(root)) {\n if (ln(p) !== \"p\") continue\n const lsa = findChildByLocalName(p, \"linesegarray\"), segs = lsa ? elements(lsa).filter(e => ln(e) === \"lineseg\") : []\n if (segs.length) last = segs[segs.length - 1]\n for (const run of elements(p)) if (ln(run) === \"run\") for (const ctrl of elements(run)) if (ln(ctrl) === \"ctrl\") {\n // 렌더(endNoteLayout)와 같은 미주 — 지워진 변경 추적 미주는 뺀다\n const en = findChildByLocalName(ctrl, \"endNote\"), sub = en && !isDeletedControl(en) ? findChildByLocalName(en, \"subList\") : null\n if (sub) notes.push(sub)\n }\n }\n if (!notes.length || !last) return\n const pr = findFirst(root, \"endNotePr\"), sp = pr ? findChildByLocalName(pr, \"noteSpacing\") : null\n let y = num(last, \"vertpos\") + num(last, \"vertsize\") + num(sp, \"aboveLine\", 0) + num(sp, \"belowLine\", 567)\n /** 단 바닥을 넘어 다음 단 맨 위로 옮겨 간 개체 몫 — 다음 단 첫 줄은 그 아래에서 */\n let pend = 0\n notes.forEach((sub, ni) => {\n if (ni > 0) y += num(sp, \"betweenNotes\", 283)\n // 첫 단 조각은 미주 첫 줄 기준(off = 미주 시작 자리), 단을 넘긴 뒤로는 그 단 맨 위 기준\n let base = y, off = y, shift = 0\n // 단 바닥을 넘는 위아래 배치 개체는 칸 안 나눔처럼 다음 단 맨 위로 옮겨 가고 이 단의 뒤 글은 개체에 밀리지 않는다(한컴 저장본: 그림 11694 뒤 줄이\n // 앞 줄 + 1352 에 그대로). 칸 안 나눔(CELL) 표는 드는 행만 남기고 나머지 행 + 바깥 위아래 여백이 다음 단 맨 위 — 뒤 글은 그 아래\n // (한컴 저장본: 3행 표의 첫 행 1182 가 단 바닥에 남고 다음 단 첫 줄 283 + 1182 + 1407 + 283 = 3155)\n let forced: { at: number; rem: number } | undefined\n const floats = subFloatBottoms(sub), done = new Set<SubFloat>()\n for (const q of elements(sub)) {\n if (ln(q) !== \"p\") continue\n const lsa = findChildByLocalName(q, \"linesegarray\")\n for (const seg of lsa ? elements(lsa) : []) {\n if (ln(seg) !== \"lineseg\") continue\n const raw0 = num(seg, \"vertpos\"), vs = num(seg, \"vertsize\")\n for (const f of floats) {\n if (done.has(f) || raw0 < f.bottom) continue\n done.add(f)\n if (!(base + f.lineBottom - shift <= bodyH && base + f.bottom - shift > bodyH)) continue\n if (f.rows?.length && f.el?.getAttribute(\"pageBreak\") === \"CELL\") {\n let yy = base + f.bottom - f.carry - shift + f.outT!, k = 0\n while (k < f.rows.length && yy + f.rows[k] <= bodyH) yy += f.rows[k++]\n if (k === f.rows.length) continue\n forced = { at: f.bottom, rem: f.outT! + f.rows.slice(k).reduce((a, b) => a + b, 0) + f.outB! }\n continue\n }\n shift += f.bottom - f.hostEnd; pend = Math.max(pend, f.carry)\n }\n const raw = raw0 - shift\n let v = base + raw\n if (forced && raw0 >= forced.at) { base = forced.rem - forced.at + shift; v = base + raw; off = 0; forced = undefined }\n else if (v + vs > bodyH && v > 0) { base = pend - raw; v = pend; off = 0; pend = 0 }\n seg.setAttribute(\"vertpos\", String(v - off))\n y = v + vs\n }\n }\n })\n}\n","/**\n * 작성 PC 글꼴 환경 추정 — KoPub 글꼴 항목에 대체 글꼴(substFont)이 적힌 문서는 KoPub 이 없는 PC 에서 그 대체 글꼴로 조판·인쇄됐을\n * 수 있다(같은 판 한컴 PDF 가 KoPub 자리를 Haansoft Batang 으로 찍고, 저장 줄 나눔도 그 폭이다). 렌더는 저장 줄 나눔을 그대로 쓰므로\n * 그 줄 나눔으로 환경을 가린다 — 구역을 두 글꼴 폭으로 각각 다시 꺾어 저장 줄 시작과 같은 문단이 더 많은 쪽.\n * 조판(reflow) 자체는 선언 글꼴 그대로다(저장 줄로 고른 폭을 다시 저장 줄과 견주면 순환이다).\n */\n\nimport { createXmlParser } from \"../hwpx/parser-shared.js\"\nimport { reflowSection } from \"./reflow.js\"\nimport { elements, ln, num } from \"./para-model.js\"\nimport type { RenderStyles } from \"./head-styles.js\"\n\n/** KoPub TTF 글꼴 항목에 대체 글꼴이 적혀 있는가 */\nexport function hasKoPubSubst(headXml: string): boolean {\n return /<hh:font\\b[^>]*\\bface=\"KoPub[^\"]*\"[^>]*\\btype=\"TTF\"[^>]*>\\s*<hh:substFont\\b/.test(headXml)\n}\n\n/** 문단마다 저장 줄 시작(두 줄 이상 문단만) — 문서 순서 */\nfunction lineStarts(root: Element): Array<string | null> {\n const out: Array<string | null> = []\n for (const p of Array.from(root.getElementsByTagName(\"hp:p\")) as unknown as Element[]) {\n const lsa = elements(p).find(e => ln(e) === \"linesegarray\")\n const segs = lsa ? elements(lsa).filter(e => ln(e) === \"lineseg\") : []\n out.push(segs.length >= 2 ? segs.map(s => s.getAttribute(\"textpos\") ?? \"0\").join(\",\") : null)\n }\n return out\n}\n\n/** 구역을 styles 폭으로 다시 꺾은 뒤 저장 줄 시작과 같은 두 줄+ 문단 수 */\nfunction matchCount(xml: string, saved: Array<string | null>, styles: RenderStyles): number {\n const root = createXmlParser().parseFromString(xml, \"text/xml\").documentElement as unknown as Element\n const pagePr = root.getElementsByTagName(\"hp:pagePr\")[0] as unknown as Element | undefined\n if (!pagePr) return 0\n const margin = pagePr.getElementsByTagName(\"hp:margin\")[0] as unknown as Element | undefined\n let PW = num(pagePr, \"width\", 59528), PH = num(pagePr, \"height\", 84188)\n if (pagePr.getAttribute(\"landscape\") === \"NARROWLY\" && PW < PH) [PW, PH] = [PH, PW]\n const gutterTB = pagePr.getAttribute(\"gutterType\") === \"TOP_BOTTOM\", gutter = num(margin ?? null, \"gutter\", 0)\n const BODY_W = PW - num(margin ?? null, \"left\", 8504) - num(margin ?? null, \"right\", 8504) - (gutterTB ? 0 : gutter)\n const BODY_H = PH - num(margin ?? null, \"top\", 5668) - num(margin ?? null, \"header\", 0) - num(margin ?? null, \"bottom\", 4252) - num(margin ?? null, \"footer\", 0) - (gutterTB ? gutter : 0)\n // 저장 줄을 지우고 다시 꺾는다(남겨 두면 조판이 저장 줄을 그대로 쓴다)\n for (const p of Array.from(root.getElementsByTagName(\"hp:p\")) as unknown as Element[]) {\n const lsa = elements(p).find(e => ln(e) === \"linesegarray\")\n if (lsa) p.removeChild(lsa)\n }\n reflowSection(root, styles, { BODY_W, BODY_H })\n const got = lineStarts(root)\n let n = 0\n saved.forEach((s, i) => { if (s !== null && s === got[i]) n++ })\n return n\n}\n\n/** 대체 글꼴 폭(alt)이 선언 글꼴 폭(base)보다 저장 줄 나눔을 뚜렷이 더 많이 맞히면 true */\nexport function kopubSubstituted(secXmls: string[], base: RenderStyles, alt: RenderStyles): boolean {\n // 두 줄+ 문단 60개쯤이면 갈린다 — 큰 문서를 통째로 두 번 다시 꺾지 않게 앞 구역부터 그만큼만\n let a = 0, b = 0, seen = 0\n for (const xml of secXmls) {\n const saved = lineStarts(createXmlParser().parseFromString(xml, \"text/xml\").documentElement as unknown as Element)\n a += matchCount(xml, saved, base)\n b += matchCount(xml, saved, alt)\n seen += saved.filter(x => x !== null).length\n if (seen >= 60) break\n }\n // 뚜렷할 때만 — 두 폭의 차가 몇 문단뿐이면 줄 나눔이 글꼴 말고 다른 까닭으로 갈린 것이다\n return b >= a + 5 && b > a * 1.1\n}\n","/**\n * 공유 렌더 장면(RenderScene) 계약 — HWPX/HWP5 어댑터가 채우고 SVG·HTML·래스터·PDF·crop 이 소비한다 (#75).\n *\n * 좌표 규약: 공개 bbox 는 **pt**, **페이지 로컬**(물리 페이지 좌상단 원점), 페이지 번호 **1-based**.\n * 한 논리 개체가 여러 페이지에 걸치면 `regions` 에 페이지별 조각을 여럿 둔다(세로 스택 전역 좌표 금지).\n * region id 는 같은 문서·같은 옵션이면 결정적 — 그리기(문서) 순서로 유형별 일련번호를 매긴다.\n */\n\nexport type RenderSourceFormat = \"hwpx\" | \"hwp\"\n\nexport type RenderObjectType = \"paragraph\" | \"table\" | \"image\" | \"shape\" | \"equation\" | \"unknown\"\n\nexport interface PageBBox {\n /** 1-based 페이지 */\n page: number\n /** pt, 페이지 로컬, 좌상단 원점 */\n x: number\n y: number\n width: number\n height: number\n}\n\nexport interface RenderRegion {\n /** 결정적 id — `table-000017` 꼴 */\n id: string\n type: RenderObjectType\n /** 첫 조각의 페이지 (편의 필드) */\n page: number\n /** 페이지별 조각 — 한 논리 개체가 여러 물리 페이지에 걸칠 수 있다 */\n regions: PageBBox[]\n /** 원본 식별자(HWPX `hp:tbl id` 등) — 있을 때만 */\n sourceId?: string\n /** 중첩 표·셀 안 이미지·문단 안 개체의 부모 region */\n parentId?: string\n}\n\nexport interface ScenePage {\n page: number\n /** pt */\n width: number\n height: number\n}\n\nexport interface RenderScene {\n format: RenderSourceFormat\n pages: ScenePage[]\n regions: RenderRegion[]\n warnings: string[]\n stats: { texts: number; tables: number; images: number; shapes: number }\n}\n\n/** 유형별 일련번호 → 결정적 id (`table-000017`). seq 는 1-based */\nexport function regionId(type: RenderObjectType, seq: number): string {\n return `${type}-${String(seq).padStart(6, \"0\")}`\n}\n\n/** 두 bbox 의 합집합 (같은 페이지 가정) */\nexport function unionBBox(a: PageBBox, b: PageBBox): PageBBox {\n const x = Math.min(a.x, b.x), y = Math.min(a.y, b.y)\n return { page: a.page, x, y, width: Math.max(a.x + a.width, b.x + b.width) - x, height: Math.max(a.y + a.height, b.y + b.height) - y }\n}\n\n/**\n * region 수집기 — 어댑터가 그리는 순서대로 `add()` 하면 유형별 카운터로 id 를 발급한다.\n * 같은 논리 개체의 추가 페이지 조각은 `addFragment()`.\n */\nexport class RegionCollector {\n readonly regions: RenderRegion[] = []\n private readonly counters = new Map<RenderObjectType, number>()\n\n add(type: RenderObjectType, bbox: PageBBox, extra: { sourceId?: string; parentId?: string } = {}): string {\n const seq = (this.counters.get(type) ?? 0) + 1\n this.counters.set(type, seq)\n const id = regionId(type, seq)\n const region: RenderRegion = { id, type, page: bbox.page, regions: [bbox] }\n if (extra.sourceId) region.sourceId = extra.sourceId\n if (extra.parentId) region.parentId = extra.parentId\n this.regions.push(region)\n return id\n }\n\n addFragment(id: string, bbox: PageBBox): void {\n const r = this.regions.find((x) => x.id === id)\n if (!r) return\n // 같은 페이지 조각은 합집합, 다른 페이지면 새 조각\n const same = r.regions.find((f) => f.page === bbox.page)\n if (same) Object.assign(same, unionBBox(same, bbox))\n else r.regions.push(bbox)\n }\n}\n","/** Page decorations are separate stories: their line positions never split body pages. */\nimport { findChildByLocalName } from \"../hwpx/parser-shared.js\"\nimport { elements, findFirst, isDeletedControl, ln, num } from \"./para-model.js\"\n\nexport interface PageStory { sub: Element; page: number; x: number; y: number; width: number; layer?: -2 | 2 }\nexport function pageStories(root: Element, masters: Element[], paraPages: Map<Element, number[]>, pageCount: number, pageBase: number,\n geom: { ML: number; MT: number; PH: number; BODY_W: number }): PageStory[] {\n const secPr = findFirst(root, \"secPr\"), visibility = secPr && findChildByLocalName(secPr, \"visibility\")\n const pagePr = secPr && findChildByLocalName(secPr, \"pagePr\"), margin = pagePr && findChildByLocalName(pagePr, \"margin\")\n const declarations: Array<{ el: Element; page: number; kind: string }> = []\n const hidden = new Map<number, Set<string>>()\n for (const p of elements(root)) if (ln(p) === \"p\") {\n const page = paraPages.get(p)?.[0] ?? 0\n for (const run of elements(p)) if (ln(run) === \"run\") for (const ctrl of elements(run)) if (ln(ctrl) === \"ctrl\") {\n for (const el of elements(ctrl)) {\n if (isDeletedControl(el)) continue\n const kind = ln(el)\n if (kind === \"header\" || kind === \"footer\") declarations.push({ el, page, kind })\n else if (kind === \"pageHiding\") {\n const kinds = hidden.get(page) ?? new Set<string>()\n for (const name of [\"Header\", \"Footer\", \"MasterPage\"]) if (num(el, `hide${name}`)) kinds.add(name)\n hidden.set(page, kinds)\n }\n }\n }\n }\n const parity = (type: string, n: number): boolean => type === \"BOTH\" || (type === \"ODD\" && n % 2 === 1) || (type === \"EVEN\" && n % 2 === 0)\n const out: PageStory[] = []\n for (let page = 0; page < pageCount; page++) {\n const n = pageBase + page + 1\n const hides = (name: string): boolean => hidden.get(page)?.has(name) === true || (page === 0 && num(visibility, `hideFirst${name}`) !== 0)\n if (!hides(\"MasterPage\")) {\n // ODD/EVEN replace BOTH on their pages; they are not an overlay.\n const matching = masters.filter(m => m.getAttribute(\"type\") === (n % 2 ? \"ODD\" : \"EVEN\"))\n const both = masters.filter(m => (m.getAttribute(\"type\") || \"BOTH\") === \"BOTH\")\n const normal = (matching.length ? matching : both).slice(-1)\n const specific = masters.filter(m => m.getAttribute(\"type\") === \"LAST_PAGE\" ? page === pageCount - 1 : m.getAttribute(\"type\") === \"OPTIONAL_PAGE\" && num(m, \"pageNumber\") === page + 1)\n const special = specific.slice(-1)\n const selected = special.length && !num(special[0], \"pageDuplicate\") ? special : [...normal, ...special]\n for (const master of selected) {\n const sub = findChildByLocalName(master, \"subList\")\n if (sub) out.push({ sub, page, x: geom.ML, y: geom.MT, width: geom.BODY_W, layer: num(master, \"pageFront\") ? 2 : -2 })\n }\n }\n for (const kind of [\"header\", \"footer\"]) {\n if (hides(kind === \"header\" ? \"Header\" : \"Footer\")) continue\n const eligible = declarations.filter(d => d.kind === kind && d.page <= page && parity(d.el.getAttribute(\"applyPageType\") || \"BOTH\", n))\n const decl = eligible[eligible.length - 1]\n const sub = decl && findChildByLocalName(decl.el, \"subList\")\n if (sub) out.push({ sub, page, x: geom.ML, y: kind === \"header\" ? num(margin, \"top\", 5668) : geom.PH - num(margin, \"bottom\", 4252) - num(margin, \"footer\"), width: geom.BODY_W })\n }\n }\n return out\n}\n\n/** 각주 구분선 — 쪽 아래 각주 영역 맨 위 */\nexport interface NoteRule { page: number; x: number; y: number; length: number; widthMm: number; color: string }\n\n/**\n * 쪽 아래 각주 — 쪽마다 그 쪽에 놓인 문단의 각주를 모아 본문 바닥에서 각주 영역만큼 위에 놓는다(reflow 의 쪽 바닥 계산과 같은 모양):\n * 영역 = 구분선 위 간격(aboveLine) + 구분선 아래 간격(belowLine) + 각주 높이 합 + 각주 사이 간격(betweenNotes) × (개수 − 1).\n * 구분선은 왼쪽 여백에서 길이만큼(length −1 = 기본 5cm, 한컴 PDF 실측 14173). 각주 높이는 하위 목록 lineseg 바닥\n */\nexport function footNoteStories(root: Element, paraPages: Map<Element, number[]>, geom: { ML: number; MT: number; BODY_W: number; BODY_H: number }): { stories: PageStory[]; rules: NoteRule[] } {\n const pr = findFirst(root, \"footNotePr\")\n const sp = pr ? findChildByLocalName(pr, \"noteSpacing\") : null, line = pr ? findChildByLocalName(pr, \"noteLine\") : null\n const above = num(sp, \"aboveLine\", 850), below = num(sp, \"belowLine\", 567), between = num(sp, \"betweenNotes\", 283)\n const byPage = new Map<number, Array<{ sub: Element; h: number }>>()\n for (const p of elements(root)) if (ln(p) === \"p\") {\n const page = paraPages.get(p)?.[0] ?? 0\n for (const run of elements(p)) if (ln(run) === \"run\") for (const ctrl of elements(run)) if (ln(ctrl) === \"ctrl\") {\n const fn = findChildByLocalName(ctrl, \"footNote\")\n const sub = fn && !isDeletedControl(fn) ? findChildByLocalName(fn, \"subList\") : null\n if (!sub) continue\n let h = 0\n for (const q of elements(sub)) if (ln(q) === \"p\") {\n const lsa = findChildByLocalName(q, \"linesegarray\")\n for (const seg of lsa ? elements(lsa) : []) if (ln(seg) === \"lineseg\") h = Math.max(h, num(seg, \"vertpos\") + num(seg, \"vertsize\"))\n }\n const list = byPage.get(page) ?? []\n list.push({ sub, h })\n byPage.set(page, list)\n }\n }\n const stories: PageStory[] = [], rules: NoteRule[] = []\n const lenAttr = num(line, \"length\", -1), widthMm = Number.parseFloat(line?.getAttribute(\"width\") ?? \"0.12\") || 0.12\n const lineType = line?.getAttribute(\"type\") ?? \"SOLID\"\n for (const [page, notes] of byPage) {\n const area = above + below + notes.reduce((a, n) => a + n.h, 0) + between * (notes.length - 1)\n const top = geom.MT + geom.BODY_H - area\n if (lineType !== \"NONE\") rules.push({ page, x: geom.ML, y: top + above, length: lenAttr > 0 ? lenAttr : 14173, widthMm, color: line?.getAttribute(\"color\") ?? \"#000000\" })\n let y = top + above + below\n for (const n of notes) { stories.push({ sub: n.sub, page, x: geom.ML, y, width: geom.BODY_W }); y += n.h + between }\n }\n return { stories, rules }\n}\n\n/**\n * 미주 — 구역 본문 끝(마지막 줄 바닥) 뒤에 차례로 흘린다. 구분선은 본문 끝 + aboveLine, 미주는 구분선 + belowLine 부터, 미주 사이는 betweenNotes.\n * 단(colPr)을 채우면 다음 단, 마지막 단이면 다음 쪽 맨 위로 줄 단위로 넘어간다. 미주 하위 목록 lineseg 는 미주마다 0 부터인 지역 좌표라\n * 여기서 쪽 로컬 vertpos 와 단 오프셋을 더한 horzpos 로 다시 쓴다(한컴 PDF: 2단 시험지 미주 구분선 = 본문 끝 줄 바닥, 첫 미주 = 그 아래 576)\n */\nexport function endNoteLayout(root: Element, paraPages: Map<Element, number[]>, geom: { ML: number; MT: number; BODY_W: number; BODY_H: number }): { paras: Array<{ p: Element; pages: number[] }>; rules: NoteRule[]; pageCount: number } | null {\n const notes: Element[] = []\n let last: { seg: Element; page: number } | null = null\n /** 구역 끝에 걸린 단 정의 — 미주는 구역 끝의 단으로 흐른다(한컴 PDF: 1단으로 시작해 2단으로 바뀐 구역의 미주가 두 단) */\n let endColPr: Element | null = null\n for (const p of elements(root)) if (ln(p) === \"p\") {\n const lsa = findChildByLocalName(p, \"linesegarray\"), segs = lsa ? elements(lsa).filter(e => ln(e) === \"lineseg\") : []\n const pages = paraPages.get(p) ?? []\n if (segs.length) last = { seg: segs[segs.length - 1], page: pages[segs.length - 1] ?? pages[0] ?? 0 }\n for (const run of elements(p)) if (ln(run) === \"run\") for (const ctrl of elements(run)) if (ln(ctrl) === \"ctrl\") {\n endColPr = findChildByLocalName(ctrl, \"colPr\") ?? endColPr\n const en = findChildByLocalName(ctrl, \"endNote\")\n const sub = en && !isDeletedControl(en) ? findChildByLocalName(en, \"subList\") : null\n if (sub) notes.push(sub)\n }\n }\n if (!notes.length || !last) return null\n const pr = findFirst(root, \"endNotePr\")\n const sp = pr ? findChildByLocalName(pr, \"noteSpacing\") : null, line = pr ? findChildByLocalName(pr, \"noteLine\") : null\n const above = num(sp, \"aboveLine\", 0), below = num(sp, \"belowLine\", 567), between = num(sp, \"betweenNotes\", 283)\n const colPr = endColPr ?? findFirst(root, \"colPr\"), nCol = Math.max(1, num(colPr, \"colCount\", 1)), gap = nCol > 1 ? num(colPr, \"sameGap\", 0) : 0\n const colW = (geom.BODY_W - gap * (nCol - 1)) / nCol\n let page = last.page\n let col = nCol > 1 ? Math.min(nCol - 1, Math.max(0, Math.round(num(last.seg, \"horzpos\") / (colW + gap)))) : 0\n let y = num(last.seg, \"vertpos\") + num(last.seg, \"vertsize\") + above\n const rules: NoteRule[] = []\n const lenAttr = num(line, \"length\", -1), widthMm = Number.parseFloat(line?.getAttribute(\"width\") ?? \"0.12\") || 0.12\n if ((line?.getAttribute(\"type\") ?? \"SOLID\") !== \"NONE\") rules.push({ page, x: geom.ML + col * (colW + gap), y: geom.MT + y, length: lenAttr > 0 ? lenAttr : 14173, widthMm, color: line?.getAttribute(\"color\") ?? \"#000000\" })\n y += below\n const next = (): void => { if (++col >= nCol) { col = 0; page++ } y = 0 }\n const out: Array<{ p: Element; pages: number[] }> = []\n notes.forEach((sub, ni) => {\n if (ni > 0) y += between\n let base = y\n // 미주 줄 vertpos 는 미주 첫 줄 기준(0)이고, 단을 넘긴 문단은 그 문단 첫 줄 기준 0 부터 다시 센다 — 되돌아간 줄은 앞 줄(+간격) 뒤에 잇고,\n // 단 넘김은 줄이 단 바닥을 넘을 때 일어난다(한컴 PDF 시험지 해설: 되돌아간 2298 줄은 왼쪽 단 바닥, 다음 줄 2750 이 오른쪽 단 맨 위 0,\n // 떠 있는 그래프 6852 + 97 − 2750 = 4199 ↔ PDF 4197)\n let prevRaw = Number.NEGATIVE_INFINITY, flowEnd = y\n for (const q of elements(sub)) if (ln(q) === \"p\") {\n const lsa = findChildByLocalName(q, \"linesegarray\"), segs = lsa ? elements(lsa).filter(e => ln(e) === \"lineseg\") : []\n const pages: number[] = []\n for (const seg of segs) {\n const raw = num(seg, \"vertpos\")\n if (raw < prevRaw) base = flowEnd - raw\n prevRaw = raw\n let v = base + raw\n const vs = num(seg, \"vertsize\")\n if (v + vs > geom.BODY_H && v > 0) { const shift = v; next(); base -= shift; v = 0 }\n seg.setAttribute(\"vertpos\", String(v))\n seg.setAttribute(\"horzpos\", String(num(seg, \"horzpos\") + col * (colW + gap)))\n pages.push(page)\n y = v + vs\n flowEnd = y + num(seg, \"spacing\")\n }\n out.push({ p: q, pages })\n }\n })\n return { paras: out, rules, pageCount: page + 1 }\n}\n\n","/**\n * 쪽을 넘는 본문 표의 행 배치 — 표 그리기(drawTable)와 쪽 프리패스가 같은 계획을 쓴다.\n * 행 바닥이 본문 바닥을 넘으면: 칸 안 나눔(pageBreak=CELL) 표는 행을 칸 줄 경계에서 갈라 남은 줄을 다음 쪽 맨 위(머리 행 아래)에,\n * 그 밖의 표는 그 행부터 다음 쪽으로 넘긴다. 쪽마다 적어도 한 행(조각)은 놓는다. 칸을 가르는 규칙은 reflow 와 같다 —\n * 칸마다 (칸 위 여백 + 줄 바닥) ≤ 남은 높이 − 칸 아래 여백 인 줄까지 이 쪽, 남은 줄에 칸 위아래 여백을 더한 높이가 다음 쪽 조각.\n */\n\nimport { elements, ln, num, cellColumns, cellContentExtent, type CellModel } from \"./para-model.js\"\nimport { findChildByLocalName } from \"../hwpx/parser-shared.js\"\nimport { subFloatBottoms } from \"./reflow-tables.js\"\n\n/**\n * 행 하나가 한 쪽에 놓인 조각 — page 는 표 시작 쪽에서 센 쪽 차이, y 는 절대 위치. range 는 칸마다 이 조각에 그릴 내용 vertpos [from, to).\n * place 는 이 조각에 옮겨 그릴 칸 안 떠 있는 개체의 위(절대 y)\n */\n/** fill — 칸 줄에 앵커한 떠 있는 표가 이 조각 바닥 너머로 이어진다(칸 세로 정렬 없이 저장 자리에 그린다) */\nexport interface RowPiece { page: number; y: number; h: number; range?: Map<Element, [number, number]>; place?: Map<Element, number>; fill?: boolean }\n\n/** 칸 문단의 겹치지 않는(allowOverlap=0) 떠 있는 문단 기준 개체 — 위 오프셋(음수는 0)과 바깥 여백 포함 높이 */\nfunction stackedFloats(c: CellModel): Array<{ el: Element; vo: number; h: number; omT: number }> {\n const out: Array<{ el: Element; vo: number; h: number; omT: number }> = []\n for (const p of c.sub ? elements(c.sub) : []) if (ln(p) === \"p\") for (const run of elements(p)) if (ln(run) === \"run\") for (const o of elements(run)) {\n if (ln(o) !== \"pic\") continue\n const pos = findChildByLocalName(o, \"pos\")\n if (!pos || pos.getAttribute(\"treatAsChar\") === \"1\" || (pos.getAttribute(\"vertRelTo\") ?? \"PARA\") !== \"PARA\" || pos.getAttribute(\"allowOverlap\") !== \"0\") continue\n const wrap = o.getAttribute(\"textWrap\") ?? \"TOP_AND_BOTTOM\"\n if (wrap !== \"SQUARE\" && wrap !== \"TOP_AND_BOTTOM\") continue\n const om = findChildByLocalName(o, \"outMargin\"), raw = num(pos, \"vertOffset\")\n out.push({ el: o, vo: Math.max(0, raw >= 2 ** 31 ? raw - 2 ** 32 : raw), h: num(findChildByLocalName(o, \"sz\"), \"height\") + num(om, \"top\") + num(om, \"bottom\"), omT: num(om, \"top\") })\n }\n return out\n}\n\n/**\n * 칸 subList 최상위 문단 줄 — 연속 좌표 [위, 아래]와 그 줄. 한컴이 이미 칸을 쪽에서 갈라 저장한 칸은 줄 vertpos 가 다음 쪽 기준 0 으로\n * 되돌아간다(한컴 저장본: 20020 → 0) — 되돌아가는 곳마다 앞 줄 끝(+간격)에 잇는다. 첫 줄(vertpos 0)만 앞 쪽에 남기고 가른 칸은\n * 다음 줄도 0 이라 되돌아가지 않는다 — 같은 vertpos 가 같거나 왼쪽 가로 위치에서 다시 오면 그것도 쪽 나눔이다(본문 쪽 판정과 같다)\n */\nexport function cellLineBoxes(c: CellModel): Array<{ seg: Element; top: number; bottom: number; part: number; origin: number }> {\n const out: Array<{ seg: Element; top: number; bottom: number; part: number; origin: number }> = []\n let shift = 0, prevV = Number.NEGATIVE_INFINITY, prevH = 0, prevSavedEnd = 0, prevEnd = 0, part = 0\n // 칸 안 다단은 되돌아감이 다음 단이다 — 쪽 나눔으로 잇지 않는다\n const cols = cellColumns(c.sub)\n for (const p of c.sub ? elements(c.sub) : []) if (ln(p) === \"p\") {\n const lsa = findChildByLocalName(p, \"linesegarray\")\n for (const sg of lsa ? elements(lsa) : []) if (ln(sg) === \"lineseg\") {\n const v = num(sg, \"vertpos\"), hz = num(sg, \"horzpos\")\n // 앞 줄이 그 자리에서 끝났으면(간격 음수로 겹친 빈 문단) 같은 vertpos 라도 쪽 나눔이 아니다\n if ((v < prevV || (v === prevV && hz <= prevH && prevSavedEnd > v)) && !cols) { shift = prevEnd - v; part++ }\n prevV = v\n prevH = hz\n prevSavedEnd = v + num(sg, \"vertsize\") + num(sg, \"spacing\")\n const top = v + shift, bottom = top + num(sg, \"vertsize\")\n prevEnd = bottom + num(sg, \"spacing\")\n // origin = 이 부분(쪽)의 저장 좌표 0 의 연속 좌표 — 쪽 안 줄 위치는 저장 vertpos 그대로(앞 간격 포함)\n out.push({ seg: sg, top, bottom, part, origin: shift })\n }\n }\n return out\n}\nfunction cellLines(c: CellModel): [number, number][] {\n return cellLineBoxes(c).map(b => [b.top, b.bottom])\n}\n\n/**\n * @param rowH 행 높이(그리기와 같은 값)\n * @param ty 표 위(절대), MT·BODY_H 본문 위·높이. BODY_H 0 이면 나누지 않는다\n * @returns 행마다 조각 목록\n */\n/**\n * 갈린 칸 줄(seg, 그 줄 위 절대 y)에 앵커한 떠 있는 표가 쪽을 넘으면 그 표 마지막 조각의 쪽 차이와 바닥(절대). nested 는 그런 칸 안의 표 계획.\n * contMT 는 이어진 쪽에서 그 칸 내용이 시작하는 자리(바깥 표의 이어진 쪽 위 + 칸 위 여백) — 안쪽 표는 거기서 다시 시작한다\n */\nexport type CellFloatSpan = (seg: Element, top: number, contMT?: number) => { pages: number; endY: number; el?: Element } | undefined\n\n/**\n * 여러 행 칸의 저장 부분(칸 줄 vertpos 되돌아감) 경계 행 — 부분마다 그 높이(+칸 여백)를 채운 다음 행에서 다음 부분이 시작한다.\n * 부분 높이를 채우는 행 경계가 칸 안에 없으면 버린다\n */\nexport function spanPartRows(cells: CellModel[], rowY: number[]): Set<number> {\n const out = new Set<number>()\n for (const c of cells) {\n if (c.rs < 2) continue\n const bs = cellLineBoxes(c)\n const parts = bs.length ? bs[bs.length - 1].part : 0\n let s = c.ra\n for (let k = 0; k < parts; k++) {\n const inK = bs.filter(b => b.part === k)\n if (!inK.length) break\n const ext = Math.max(...inK.map(b => b.bottom)) - inK[0].origin + c.marginT + c.marginB\n let r = s + 1\n while (r < c.ra + c.rs && rowY[r] - rowY[s] < ext - 100) r++\n if (r >= c.ra + c.rs) break\n out.add(r); s = r\n }\n }\n return out\n}\n\nexport function planTableRows(tbl: Element, cells: CellModel[], rowH: number[], ty: number, MT: number, BODY_H: number, slack = 0, floatSpan?: CellFloatSpan, nested = false, contMT = MT): RowPiece[][] {\n // 갈린 칸 안의 표는 아래 여백으로 넘치지 않는다 — 본문 바닥에서 가른다(한컴 PDF: 칸 안 서식 표가 본문 바닥 아래 34pt 를 다음 쪽 맨 위에)\n if (nested) slack = 0\n const nRows = rowH.length\n const rowY = [0]\n for (const h of rowH) rowY.push(rowY[rowY.length - 1] + h)\n const plain = (): RowPiece[][] => rowH.map((h, r) => [{ page: 0, y: ty + rowY[r], h }])\n const pageBottom = MT + BODY_H\n // 첫 쪽에서 표 전체가 아래 여백 안에서 끝나면 가르지 않는다(한컴 PDF: 쪽보다 조금 큰 서식 표 하나짜리 문서가 1쪽)\n // 겹치지 않게 쌓이는 칸 안 개체가 행보다 높으면 쌓은 높이로 판정한다(아래 쌓기 조각)\n const stackOver = tbl.getAttribute(\"pageBreak\") === \"CELL\" && rowH.some((h, r) => {\n const rc = cells.filter(c => c.ra === r && c.rs === 1)\n if (rc.length !== 1) return false\n const st = stackedFloats(rc[0])\n return st.length >= 2 && st.reduce((a, f) => a + f.h, 0) > h\n })\n // 한컴이 칸 줄을 쪽에서 갈라 저장한 표(칸 안 줄 vertpos 가 되돌아감)는 아래 여백으로 넘치지 않는다 — 저장본이 이미 다음 쪽 조각을 적었다\n // (한컴 PDF: 아래 여백 안에서 끝날 서식 표가 칸 줄 되돌아간 자리부터 2쪽)\n if (slack > 0 && ty + rowY[nRows] > pageBottom && ty + rowY[nRows] <= pageBottom + slack && cells.some(c => cellLineBoxes(c).some(b => b.part > 0))) slack = 0\n // 저장 표 높이(sz)가 안쪽 행 경계와 같아도 — 한컴이 첫 쪽 조각만 sz 에 적었다(행 사이에서 가른 표) — 넘침 여유를 주지 않는다\n // (같은 판이 저장·인쇄한 한컴 PDF: sz 71,649 = 26행 경계인 27행 표의 마지막 행이 다음 쪽)\n if (slack > 0 && ty + rowY[nRows] > pageBottom && ty + rowY[nRows] <= pageBottom + slack) {\n const declared = num(findChildByLocalName(tbl, \"sz\"), \"height\")\n if (rowY.some((v, k) => k > 0 && k < nRows && Math.abs(v - declared) <= 2)) slack = 0\n }\n if (BODY_H <= 0 || (ty + rowY[nRows] <= pageBottom + slack) && !stackOver) return plain()\n // 글자처럼 취급하는 표는 쪽에서 가르지 않는다 — 쪽 맨 위에 있으면 그 쪽에 잘리고(한컴 PDF: 용지를 6567 넘는 인라인 서식 표도 1쪽),\n // 아니면 표째 다음 쪽 맨 위로(한컴 PDF: 앞 표 아래 49105 에 저장된 인라인 표가 다음 쪽에 찍힌다)\n if (findChildByLocalName(tbl, \"pos\")?.getAttribute(\"treatAsChar\") === \"1\") {\n // 넘침은 저장된 표 높이(sz)로 판정 — 칸 안 떠 있는 개체까지 잰 높이는 한컴 줄 높이보다 클 수 있다(쪽 영역 밖 그림)\n const declared = num(findChildByLocalName(tbl, \"sz\"), \"height\") || rowY[nRows]\n if (ty - MT < 2000 || ty + declared <= pageBottom + slack) return plain()\n return rowH.map((h, r) => [{ page: 1, y: MT + rowY[r], h }])\n }\n let hdrRows = 0\n if (tbl.getAttribute(\"repeatHeader\") === \"1\") while (hdrRows < nRows && cells.some(c => c.ra === hdrRows) && cells.filter(c => c.ra === hdrRows).every(c => c.el.getAttribute(\"header\") === \"1\")) hdrRows++\n // 이어진 쪽의 표는 본문 위 + 표 바깥 위 여백에서 다시 시작한다(한컴 PDF: 바깥 위 여백 283 인 표의 이어진 쪽 칸 틀이 본문 위 아래 2.8pt)\n // 갈린 칸 안의 표는 이어진 쪽에서 그 칸 내용 위(contMT)부터 — 한컴 PDF: 바깥 표 여백 141·칸 위 여백 283 아래 안쪽 표 여백 141 에서 다시 시작\n const contTop = contMT + num(findChildByLocalName(tbl, \"outMargin\"), \"top\") + rowY[hdrRows]\n const outB = num(findChildByLocalName(tbl, \"outMargin\"), \"bottom\")\n const cellSplit = tbl.getAttribute(\"pageBreak\") === \"CELL\"\n const out: RowPiece[][] = []\n // 문단을 따라 흐르는 표가 쪽 위가 아닌 자리에서 첫 행을 못 놓으면(칸 첫 줄도 안 들거나 행이 넘치면) 다음 행처럼 표째 다음 쪽 맨 위로\n // (같은 판이 저장·인쇄한 한컴 PDF: 쪽 바닥 72749 에 앵커한 위아래 배치 10행 표가 통째 다음 쪽 — 저장본도 표 뒤 문단이 다음 쪽 vertpos 23096 = 표 sz)\n const flows = (findChildByLocalName(tbl, \"pos\")?.getAttribute(\"vertRelTo\") ?? \"PARA\") === \"PARA\"\n let page = 0, y = ty, first = !flows || ty - MT < 2000\n const spanStarts = cellSplit ? spanPartRows(cells, rowY) : new Set<number>()\n for (let r = 0; r < nRows; r++) {\n let h = rowH[r]\n const pieces: RowPiece[] = []\n // 여러 행 칸을 한컴이 쪽에서 갈라 저장했으면 다음 부분이 시작하는 행부터 다음 쪽(같은 판 PDF: 세 행 칸 \"다음 상한까지 …\" 의\n // 둘째 부분 50~1000 이 다음 쪽 \"범주Ⅲ\" 행부터, 앞 쪽은 첫 부분 높이를 채운 행까지)\n if (!first && r >= hdrRows && spanStarts.has(r)) { page++; y = contTop; first = true }\n // 칸 안 나눔은 이 행의 한 행짜리 칸 줄로 가른다(reflow 와 같다) — 여러 행에 걸친 칸은 가르지 않고 그 행 위치에 그린다\n const rowCells = cells.filter(c => c.ra === r && c.rs === 1)\n const splittable = cellSplit && r >= hdrRows && rowCells.length > 0\n // 한 칸 행의 겹치지 않는 떠 있는 개체가 쪽을 넘게 쌓이면 개체째 다음 쪽 맨 위로 — 조각은 그 쪽 개체 바닥 + 칸 아래 여백까지\n // (한컴 PDF: 칸 하나의 쪽 높이 사진 다섯 장이 쪽마다 한 장, 둘째 쪽부터는 위 오프셋 −3360 을 버리고 칸 위 여백 아래)\n const stack = splittable && rowCells.length === 1 ? stackedFloats(rowCells[0]) : []\n if (stack.length >= 2) {\n const c = rowCells[0]\n let top = y, bottom = y + c.marginT, k = 0\n const pcs: RowPiece[] = []\n let place = new Map<Element, number>()\n for (const f of stack) {\n let at = k === 0 ? top + c.marginT + f.vo : bottom\n if (k > 0 && at + f.h > pageBottom - c.marginB) {\n pcs.push({ page, y: top, h: bottom - top + c.marginB, range: new Map([[c.el, pcs.length ? [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY] : [0, Number.POSITIVE_INFINITY]]]), place })\n page++; top = contTop; place = new Map(); at = top + c.marginT; bottom = at\n }\n place.set(f.el, at + f.omT)\n bottom = Math.max(bottom, at + f.h); k++\n }\n if (pcs.length) {\n pcs.push({ page, y: top, h: bottom - top + c.marginB, range: new Map([[c.el, [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY]]]), place })\n out.push(pcs)\n y = bottom + c.marginB; first = false\n continue\n }\n }\n // 한컴이 이 행을 이미 쪽에서 갈라 저장했으면(칸 줄 vertpos 되돌아감) 그 자리 그대로 가른다\n const boxes = splittable ? new Map(rowCells.map(c => [c.el, cellLineBoxes(c)] as const)) : undefined\n const hParts = boxes ? Math.max(0, ...[...boxes.values()].flatMap(bs => bs.map(b => b.part))) : 0\n if (boxes && hParts > 0) {\n // 첫 조각의 첫 줄도 이 쪽 남은 자리에 안 들면 행째 다음 쪽에서 가른다 — 칸 줄 나눔과 같은 판정(위 여백 + 줄 바닥 ≤ 남은 높이 − 아래 여백)\n // (같은 판이 저장·인쇄한 한컴 PDF: 쪽 바닥 858 남은 자리의 갈라 저장한 행은 다음 쪽 맨 위부터 저장 줄 0~73600)\n if (!first && rowCells.some(c => { const b = (boxes.get(c.el) ?? []).find(x => x.part === 0); return !!b && c.marginT + b.bottom - b.origin > pageBottom - y - c.marginB })) { page++; y = contTop; first = true }\n const declared = num(findChildByLocalName(tbl, \"sz\"), \"height\")\n /** 부분 첫 줄에 앵커한 표로 이미 앞 쪽을 채운 줄 — 아래 '부분 줄의 표' 넘김에서 다시 세지 않는다 */\n const led = new Set<Element>()\n let firstPh = 0\n for (let k = 0; k <= hParts; k++) {\n // 부분 첫 줄이 그 줄에 앵커한 쪽을 넘는 표의 끝 쪽 기준으로 저장됐으면(표 아래로 밀린 줄) 표는 이 부분 시작 쪽 맨 위부터 그리고,\n // 부분 줄은 표가 끝나는 쪽에서 — 사이 쪽은 줄 없는 조각(한컴 PDF: 칸이 갈린 뒤 첫 줄 30744 = 네 쪽에 걸친 표 끝 쪽 아래의 줄, 표는 앞 쪽 맨 위)\n if (k > 0 && floatSpan) {\n let lead = 0, place: Map<Element, number> | undefined\n for (const c of rowCells) {\n const b = (boxes.get(c.el) ?? []).find(x => x.part === k)\n if (!b) continue\n const f = floatSpan(b.seg, y + c.marginT, contTop + c.marginT)\n if (f?.el && f.pages > 0 && f.pages > lead && Math.abs(contTop + c.marginT + b.top - b.origin - f.endY) < 3000) { lead = f.pages; place = new Map([[f.el, y + c.marginT]]); led.add(b.seg) }\n }\n if (lead > 0) {\n const none = new Map(rowCells.map(c => [c.el, [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY] as [number, number]]))\n for (let e = 0; e < lead; e++) pieces.push({ page: page + e, y: contTop, h: pageBottom - contTop, range: none, place: e === 0 ? place : undefined })\n page += lead\n }\n }\n const range = new Map<Element, [number, number]>()\n let ext = 0, toNext = 0\n for (const c of rowCells) {\n const bs = boxes.get(c.el) ?? []\n const inK = bs.filter(b => b.part === k), next = bs.find(b => b.part > k)\n // 조각 원점 = 이 부분의 저장 좌표 0 — 첫 줄 앞 간격(저장 vertpos)을 살린다(한컴 PDF: 갈린 칸 쪽 첫 줄이 vertpos 1000 만큼 아래)\n const from = inK[0]?.origin ?? next?.origin ?? Number.POSITIVE_INFINITY\n range.set(c.el, [from, next?.top ?? Number.POSITIVE_INFINITY])\n if (inK.length) ext = Math.max(ext, inK[inK.length - 1].bottom - from + c.marginT + c.marginB)\n // 마지막 조각은 그 조각 줄에 앵커한 위아래 배치 개체 바닥까지 — 한컴 PDF: 갈린 칸 둘째 쪽 끝 줄에 앵커한 6행 표(8556) 아래 칸 여백까지가 조각\n if (k === hParts && inK.length && c.sub) for (const f of subFloatBottoms(c.sub)) {\n const b = bs.find(x => x.seg === f.seg)\n if (b && b.part === k) ext = Math.max(ext, b.top + f.bottom - f.v0 - from + c.marginT + c.marginB)\n }\n if (inK.length && next) toNext = Math.max(toNext, next.top - from + c.marginT + c.marginB)\n }\n const last = k === hParts\n // 한컴은 갈라 저장한 표의 sz 높이에 첫 쪽 높이를 담는다(PDF: 첫 쪽 상자 65300, sz 65362) — 가운데 쪽은 다음 쪽 첫 줄 위까지 + 칸 여백(PDF 68820, 계산 68810)\n // (sz 가 첫 부분 내용보다 작으면 저장값이 첫 쪽 높이가 아니다 — 쪽 바닥까지). 첫 쪽 조각은 그 행 칸 저장 높이와 이 쪽 내용 중 큰 것을 넘지 않는다\n // (같은 판이 저장·인쇄한 한컴 PDF: 48행 표의 갈린 행 첫 쪽 칸 틀이 칸 높이 2116 에서 끝나고 쪽 바닥까지 17pt 가 빈다 — 가운데 칸 글도 그 안에서 맞춘다)\n const cellH = Math.max(0, ...rowCells.map(c => num(findChildByLocalName(c.el, \"cellSz\"), \"height\")))\n const firstH = Math.min(declared > 0 && ty + declared - y >= ext ? Math.min(pageBottom - y, ty + declared - y) : pageBottom - y, Math.max(ext, cellH))\n // 두 쪽에 갈린 행의 가운데·아래 정렬 칸(칸 높이 고정 표는 모든 칸)은 글이 덜 차도 저장 높이만큼 선다 — 다음 쪽 조각은 칸 저장 높이에서\n // 첫 쪽 조각을 뺀 만큼(조판과 같은 규칙. 같은 판 PDF: 가운데 정렬 63,539 칸의 다음 쪽 조각 305.58pt, 남은 글만 세면 304.26pt)\n // (몫이 다음 쪽에 다 들지 않으면 칸 저장 높이는 두 쪽 나눔과 맞지 않는다 — 한컴이라면 또 갈랐을 것이니 남은 글만 센다)\n const share = last && k === 1 ? Math.max(0, ...rowCells.filter(c => tbl.getAttribute(\"noAdjust\") === \"1\" || /^(CENTER|BOTTOM)$/.test(c.sub?.getAttribute(\"vertAlign\") ?? \"\")).map(c => c.h - firstPh).filter(v => v <= pageBottom - contTop)) : 0\n const ph = last ? Math.max(ext, share) : k === 0 ? firstH : toNext > 0 ? Math.min(pageBottom - contTop, toNext) : pageBottom - contTop\n if (k === 0) firstPh = ph\n pieces.push({ page, y, h: ph, range })\n if (!last) {\n // 이 부분 줄에 앵커한 떠 있는 표가 쪽을 넘으면(칸 안 중첩 표) 다음 부분은 그 표가 끝나는 쪽 — 사이 쪽은 줄 없는 조각(칸 틀만).\n // 다음 부분 첫 줄이 표 끝보다 위에 저장돼 있으면 그다음 쪽(한컴 PDF: 쪽 셋에 걸친 칸 안 표 뒤 칸 글이 표 끝 쪽 아래)\n let span = 0, spanEnd = 0\n if (floatSpan) for (const c of rowCells) {\n const bs = (boxes.get(c.el) ?? []).filter(b => b.part === k), from = bs[0]?.origin ?? 0\n for (const b of bs) { if (led.has(b.seg)) continue; const f = floatSpan(b.seg, y + c.marginT + b.top - from, contTop + c.marginT); if (f && f.pages > span) { span = f.pages; spanEnd = f.endY } }\n }\n if (span > 0) {\n const nextTop = Math.min(...rowCells.map(c => { const b = (boxes.get(c.el) ?? []).find(x => x.part === k + 1); return b ? contTop + c.marginT + b.top - b.origin : Number.POSITIVE_INFINITY }))\n const skip = nextTop < spanEnd - 100 ? span + 1 : span\n for (let e = 1; e < skip; e++) pieces.push({ page: page + e, y: contTop, h: pageBottom - contTop, range: new Map(rowCells.map(c => [c.el, [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY]])) })\n page += skip\n } else page++\n y = contTop; first = true\n } else h = ph\n }\n out.push(pieces)\n y += h; first = false\n continue\n }\n // 갈라 저장되지 않은 칸의 줄에 앵커한 떠 있는 표가 쪽을 넘으면 칸 틀은 그 표가 끝나는 쪽까지 잇는다 — 칸 줄은 다 첫 조각,\n // 사이 쪽은 줄 없는 조각, 끝 쪽 조각은 표 바닥 + 칸 아래 여백까지(같은 판이 저장·인쇄한 한컴 PDF: 칸 하나짜리 별표 서식 안의 26행 표가 세 쪽)\n if (boxes && floatSpan) {\n let span = 0, spanEnd = 0, mB = 0\n for (const c of rowCells) for (const b of boxes.get(c.el) ?? []) {\n const f = floatSpan(b.seg, y + c.marginT + b.top, contTop + c.marginT)\n if (f && f.pages > span) { span = f.pages; spanEnd = f.endY; mB = c.marginB }\n }\n if (span > 0) {\n const none = new Map(rowCells.map(c => [c.el, [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY] as [number, number]]))\n pieces.push({ page, y, h: pageBottom - y, range: new Map(rowCells.map(c => [c.el, [0, Number.POSITIVE_INFINITY] as [number, number]])), fill: true })\n for (let e = 1; e < span; e++) pieces.push({ page: page + e, y: contTop, h: pageBottom - contTop, range: none, fill: true })\n page += span\n const endH = Math.max(0, spanEnd - contTop) + mB\n pieces.push({ page, y: contTop, h: endH, range: none })\n out.push(pieces)\n y = contTop + endH; first = false\n continue\n }\n }\n // 칸 안 나눔 표도 행 바닥 + 표 바깥 아래 여백이 본문 바닥 안이어야 그 쪽에 다 놓인다 — 조판(splitTableRows)과 같은 판정\n // (같은 판 한컴 PDF: 남은 10,527 에 행 바닥 10,389 가 들어도 바깥 아래 283 을 더하면 넘어 그 행부터 다음 쪽, 저장 sz 9,107 = 앞 쪽 몫)\n if (splittable && y + h + outB > pageBottom) {\n const from = new Map<Element, number>()\n const lines = new Map(rowCells.map(c => [c.el, cellLines(c)] as const))\n while (y + h + outB > pageBottom && BODY_H > rowY[hdrRows]) {\n const avail = pageBottom - y - outB\n let rem = 0, placed = false, allFit = true, blocked = false\n const cuts: [Element, number, number][] = []\n for (const c of rowCells) {\n const off = from.get(c.el) ?? 0\n const ls = (lines.get(c.el) ?? []).filter(l => l[0] >= off)\n if (!ls.length) { cuts.push([c.el, off, off]); continue }\n const end = Math.max(...ls.map(l => l[1]))\n const k = ls.findIndex(l => c.marginT + (l[1] - off) > avail - c.marginB)\n if (k < 0) { cuts.push([c.el, off, end + 1]); continue }\n allFit = false\n if (k > 0) placed = true\n // 첫 줄부터 못 놓는 칸이 있으면(그림 줄 등) 행을 가르지 않고 행째 다음 쪽 — 한컴 PDF: 섬네일 칸이 안 드는 수상작 행이 글 칸 첫 줄까지 다음 쪽\n else if (off === 0) blocked = true\n cuts.push([c.el, off, ls[k][0]])\n rem = Math.max(rem, end - ls[k][0] + c.marginT + c.marginB)\n }\n if (allFit) {\n // 칸 글은 다 들어가고 행 높이만 쪽을 넘는다 — 다음 쪽에 통째로 들어가는 행이면 행째 다음 쪽(한컴 PDF: 저장 높이 21905 사진 행이\n // 쪽 바닥에서 잘리지 않고 다음 쪽 맨 위에서 시작), 다음 쪽에도 안 들어가면 이 쪽 바닥까지(남는 높이는 버린다)\n // 이 행에서 시작하는 여러 행 칸의 글도 이 쪽 조각에 들어야 한다(같은 판 한컴 PDF: 두 줄 병합 칸이 쪽 바닥 남은 자리에 안 드는 연락처 표가 통째 다음 쪽)\n const spanCells = cells.filter(c => c.ra === r && c.rs > 1)\n if (!first && h <= pageBottom - contTop && [...rowCells, ...spanCells].some(c => cellContentExtent(c) + c.marginT + c.marginB > avail)) { page++; y = contTop; first = true; break }\n // 갈린 칸 안의 표는 남는 행 높이를 버리지 않고 다음 쪽 맨 위에 잇는다(같은 PDF: 빈 행 조각 34pt). 본문 표는 이 쪽 바닥까지\n if (nested && avail > 0) {\n pieces.push({ page, y, h: avail, range: new Map(rowCells.map(c => [c.el, [from.get(c.el) ?? 0, Number.POSITIVE_INFINITY]])) })\n for (const c of rowCells) from.set(c.el, Number.POSITIVE_INFINITY)\n page++; y = contTop; first = true; h -= avail\n continue\n }\n h = avail\n break\n }\n if (blocked && !first) { page++; y = contTop; first = true; continue }\n if (!placed) {\n // 이 쪽에 한 줄도 못 놓는다 — 쪽 맨 위면 그대로 넘치게 두고, 아니면 행째 다음 쪽\n if (first) break\n page++; y = contTop; first = true\n continue\n }\n pieces.push({ page, y, h: avail, range: new Map(cuts.map(([el, a, b]) => [el, [a, b]])) })\n for (const [el, , b] of cuts) from.set(el, b)\n page++; y = contTop; first = true; h = rem\n }\n pieces.push({ page, y, h, range: new Map(rowCells.map(c => [c.el, [from.get(c.el) ?? 0, Number.POSITIVE_INFINITY]])) })\n out.push(pieces)\n y += h; first = false\n continue\n }\n // 행 단위 표는 행 바닥 + 표 바깥 아래 여백이 본문 바닥을 넘으면 그 행부터 다음 쪽 — reflow 와 같은 판정(한컴 PDF: 바깥 아래 141 인\n // 96행 표가 바닥 70018 에 행 바닥 69901 이 드는데도 그 행을 다음 쪽 머리 행 아래로 넘긴다). 칸 안 나눔 표의 행은 위에서 칸 줄로 가른다\n if (!first && y + h + (cellSplit ? 0 : outB) > pageBottom && r >= hdrRows) { page++; y = contTop; first = true }\n // 칸을 쪼개지 않는 표(나눔 TABLE)는 여러 행 칸이 묶은 행들을 쪼갤 수 없다 — 묶음 첫 행에서 묶음 전체가 이 쪽에 안 들면 묶음째 다음 쪽\n // (한컴 PDF: 두 행 병합 칸 \"3 BOM 자동 작성 정확도\" 묶음의 첫 행이 앞 쪽에 들어도 두 행을 함께 다음 쪽 맨 위로)\n else if (!first && tbl.getAttribute(\"pageBreak\") === \"TABLE\" && r >= hdrRows && !cells.some(c => c.ra < r && c.ra + c.rs > r)) {\n let end = r + 1\n for (let grown = true; grown;) { grown = false; for (const c of cells) if (c.ra >= r && c.ra < end && c.ra + c.rs > end) { end = c.ra + c.rs; grown = true } }\n const groupH = rowY[Math.min(end, nRows)] - rowY[r]\n if (end > r + 1 && y + groupH + outB > pageBottom && groupH <= pageBottom - contTop) { page++; y = contTop; first = true }\n }\n out.push([{ page, y, h }])\n y += h; first = false\n }\n return out\n}\n","/** HWPX drawing geometry and paints, shared by the page renderer's shape regions. */\nimport { findChildByLocalName } from \"../hwpx/parser-shared.js\"\nimport { elements, ln, num, type ParaObj } from \"./para-model.js\"\nimport { docColor } from \"./head-styles.js\"\n\nconst pt = (u: number): string => String(Math.round(u) / 100)\nconst esc = (s: string): string => s.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/g, \"\").replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\")\nexport const SHAPE_TAGS = new Set([\"rect\", \"ellipse\", \"line\", \"polygon\", \"curv\", \"curve\", \"arc\"])\nexport interface RegionRotation { angle: number; cx: number; cy: number }\n/** SVG matrix(a b c d e f) — x' = a·x + c·y + e, y' = b·x + d·y + f (HWPUNIT) */\nexport type Affine = [number, number, number, number, number, number]\ninterface Box { x: number; y: number; w: number; h: number }\nexport function rotatedBounds(box: Box, rotations: Array<RegionRotation | Affine>): Box {\n if (!rotations.length) return box\n let points = [[box.x, box.y], [box.x + box.w, box.y], [box.x + box.w, box.y + box.h], [box.x, box.y + box.h]]\n // SVG nested groups apply the innermost transform first.\n for (let i = rotations.length - 1; i >= 0; i--) {\n const r = rotations[i]\n if (Array.isArray(r)) { points = points.map(([x, y]) => [r[0] * x + r[2] * y + r[4], r[1] * x + r[3] * y + r[5]]); continue }\n const { angle, cx, cy } = r\n const a = angle * Math.PI / 180, c = Math.cos(a), s = Math.sin(a)\n points = points.map(([x, y]) => [cx + c * (x - cx) - s * (y - cy), cy + s * (x - cx) + c * (y - cy)])\n }\n const x = Math.min(...points.map(p => p[0])), y = Math.min(...points.map(p => p[1]))\n return { x, y, w: Math.max(...points.map(p => p[0])) - x, h: Math.max(...points.map(p => p[1])) - y }\n}\nexport function mulAffine(m: Affine, n: Affine): Affine {\n return [m[0] * n[0] + m[2] * n[1], m[1] * n[0] + m[3] * n[1], m[0] * n[2] + m[2] * n[3], m[1] * n[2] + m[3] * n[3],\n m[0] * n[4] + m[2] * n[5] + m[4], m[1] * n[4] + m[3] * n[5] + m[5]]\n}\n\n/**\n * 묶음 안 개체의 renderingInfo — transMatrix·scaMatrix·rotMatrix 를 적힌 순서로 곱하면 개체 원본(orgSz) 좌표가 최상위 묶음의\n * 상자 좌표로 간다(e1 e2 e3 / e4 e5 e6 = x'·y' 행). 위례선 트램 보도자료 지도 묶음 실측: 지도 사진 48443×63972 → 0~42907 × 0~44754\n * (최상위 묶음 curSz 42907×44780), 노선 곡선 첫 점 → 지도 폭 0.77 지점(한컴 PDF 와 같다). 행렬이 없으면 null\n */\nexport function renderingMatrix(el: Element): Affine | null {\n const info = findChildByLocalName(el, \"renderingInfo\")\n if (!info) return null\n let m: Affine | null = null\n // 크기·회전 짝은 점에 크기를 먼저, 회전을 나중에 건다(R·S) — 한컴 PDF: 270° 회전 사진(세로 스캔 59580×84180)의 둘째 짝 크기가\n // 13889×21422 로 줄인 뒤 돌려 묶음 틀 21422×13889 를 꽉 채운다. 적힌 순서(S·R)로 곱하면 돌린 뒤 줄여 틀 밖으로 비뚤어졌다\n let pendingS: Affine | null = null\n const apply = (n: Affine): void => { m = m ? mulAffine(m, n) : n }\n for (const c of elements(info)) {\n const tag = ln(c)\n if (tag !== \"transMatrix\" && tag !== \"scaMatrix\" && tag !== \"rotMatrix\") continue\n const n: Affine = [num(c, \"e1\", 1), num(c, \"e4\"), num(c, \"e2\"), num(c, \"e5\", 1), num(c, \"e3\"), num(c, \"e6\")]\n if (tag === \"scaMatrix\") { if (pendingS) apply(pendingS); pendingS = n; continue }\n if (tag === \"rotMatrix\" && pendingS) { apply(mulAffine(n, pendingS)); pendingS = null; continue }\n apply(n)\n }\n if (pendingS) apply(pendingS)\n return m\n}\n\nexport interface ObjectGeometry {\n x: number; y: number; w: number; h: number\n bbox: { x: number; y: number; w: number; h: number }\n transform: string\n rotation?: RegionRotation\n}\n\n/**\n * 회전 개체 — 한컴 저장본은 sz 가 틀(curSz)을 돌린 외접 상자이고 pos·offset 이 그 상자 자리다(회전 사진 ta-pic-001-r: 13668×12686 을\n * 34° 돌린 외접 18425×18160, rotationInfo center 가 그 상자 중심 · 270° 다각형 2536×4798 → sz 4798×2536). 틀 중심을 외접 상자(x, y, boxW, boxH)\n * 중심에 두고 그 점을 축으로 돌린다 — 다른 회전 중심도 같은 외접 상자에 놓이면 평행 이동만 다르다. 종전엔 틀을 상자 왼쪽 위에 두고\n * orgSz 비율로 중심을 잡아 실문서의 회전 도형이 어긋났고, 사진·묶음 개체는 회전을 읽지 않았다(#116)\n */\nexport function objectGeometry(el: Element, x: number, y: number, w: number, h: number, boxW = w, boxH = h): ObjectGeometry {\n const rot = findChildByLocalName(el, \"rotationInfo\")\n const angle = num(rot, \"angle\") % 360\n if (!angle) return { x, y, w, h, bbox: { x, y, w, h }, transform: \"\" }\n const cx = x + boxW / 2, cy = y + boxH / 2\n const fx = cx - w / 2, fy = cy - h / 2\n const rotation = { angle, cx: Math.round(cx), cy: Math.round(cy) }\n return { x: fx, y: fy, w, h, bbox: rotatedBounds({ x: fx, y: fy, w, h }, [rotation]), rotation, transform: `rotate(${angle} ${pt(cx)} ${pt(cy)})` }\n}\n\ninterface PaintImage { dataUri: string; paintId?: string }\nfunction shapeFill(el: Element, defs: string[], images: Map<string, PaintImage>, warn: (key: string, text: string) => void): string {\n const brush = findChildByLocalName(el, \"fillBrush\")\n const win = brush && findChildByLocalName(brush, \"winBrush\")\n const face = win?.getAttribute(\"faceColor\")\n if (docColor(face)) return esc(face!)\n const grad = brush && findChildByLocalName(brush, \"gradation\")\n if (grad) {\n const colors = elements(grad).filter(c => ln(c) === \"color\").map(c => docColor(c.getAttribute(\"value\"), \"#000000\")!)\n if (!colors.length) return \"none\"\n const type = grad.getAttribute(\"type\") ?? \"LINEAR\"\n if (type !== \"LINEAR\" && type !== \"RADIAL\") {\n warn(`gradient:${type}`, `그라데이션(${type}) 미지원 — 첫 색으로 채움`)\n return esc(colors[0])\n }\n const id = `paint${defs.length}`\n const opacity = Math.max(0, Math.min(1, 1 - num(grad, \"alpha\") / 255))\n const stops = colors.map((color, i) => `<stop offset=\"${colors.length === 1 ? 0 : i / (colors.length - 1)}\" stop-color=\"${esc(color)}\" stop-opacity=\"${opacity}\"/>`).join(\"\")\n if (type === \"RADIAL\") defs.push(`<radialGradient id=\"${id}\" cx=\"${num(grad, \"centerX\", 50)}%\" cy=\"${num(grad, \"centerY\", 50)}%\">${stops}</radialGradient>`)\n else {\n const a = num(grad, \"angle\") * Math.PI / 180, dx = Math.cos(a) / 2, dy = -Math.sin(a) / 2\n defs.push(`<linearGradient id=\"${id}\" x1=\"${0.5 - dx}\" y1=\"${0.5 - dy}\" x2=\"${0.5 + dx}\" y2=\"${0.5 + dy}\">${stops}</linearGradient>`)\n }\n return `url(#${id})`\n }\n const imgBrush = brush && findChildByLocalName(brush, \"imgBrush\")\n const img = imgBrush && findChildByLocalName(imgBrush, \"img\")\n if (imgBrush && img) {\n const ref = img.getAttribute(\"binaryItemIDRef\") ?? \"\"\n const loaded = images.get(ref)\n if (!loaded) { warn(`brush-image:${ref}`, `그림 채움 이미지(${ref}) 없음 — 채움 생략`); return \"none\" }\n const mode = imgBrush.getAttribute(\"mode\") ?? \"TOTAL\"\n if (mode !== \"TOTAL\") { warn(`brush-mode:${mode}`, `그림 채움(${mode}) 미지원 — 채움 생략`); return \"none\" }\n if (loaded.paintId) return `url(#${loaded.paintId})`\n const id = `paint${defs.length}`\n // Embed in the paint definition; standalone page assembly can discard unused\n // image symbols without accidentally removing a pattern's referenced image.\n defs.push(`<pattern id=\"${id}\" width=\"1\" height=\"1\" patternContentUnits=\"objectBoundingBox\"><image href=\"${esc(loaded.dataUri)}\" width=\"1\" height=\"1\" preserveAspectRatio=\"none\"/></pattern>`)\n loaded.paintId = id\n return `url(#${id})`\n }\n return \"none\"\n}\n\n/** local — 묶음 안 개체를 원본(orgSz) 좌표로 그린다(배율·회전은 바깥 renderingInfo 행렬 그룹이 맡는다) */\nexport function shapeGeometry(o: ParaObj, boxX: number, boxY: number, defs: string[], images: Map<string, PaintImage>, warn: (key: string, text: string) => void, local = false): ObjectGeometry & { svg: string } {\n const el = o.el, org = findChildByLocalName(el, \"orgSz\"), cur = findChildByLocalName(el, \"curSz\")\n const ow = num(org, \"width\"), oh = num(org, \"height\")\n const w = (local ? ow : num(cur, \"width\")) || ow || num(cur, \"width\") || o.width\n const h = (local ? oh : num(cur, \"height\")) || oh || num(cur, \"height\") || o.height\n const geometry: ObjectGeometry = local ? { x: boxX, y: boxY, w, h, bbox: { x: boxX, y: boxY, w, h }, transform: \"\" }\n : objectGeometry(el, boxX, boxY, w, h, o.width || w, o.height || h)\n const { x, y } = geometry\n const sx = ow > 0 ? w / ow : 1, sy = oh > 0 ? h / oh : 1\n const line = findChildByLocalName(el, \"lineShape\"), style = line?.getAttribute(\"style\") ?? \"SOLID\"\n const color = esc(docColor(line?.getAttribute(\"color\"), \"#000000\")!)\n const strokeW = style === \"NONE\" ? 0 : Math.max(0.2, (num(line, \"width\", 33) / 100) * 2.834645)\n const dash = /DASH|DOT/.test(style) ? ` stroke-dasharray=\"${style.includes(\"DOT\") ? \"1,1.5\" : \"3,1.5\"}\"` : \"\"\n // 묶음 행렬 안(local)에서는 선 굵기를 배율로 늘리지 않는다 — 한컴은 묶음 크기를 바꿔도 선 굵기가 그대로\n const keepWidth = local ? ` vector-effect=\"non-scaling-stroke\"` : \"\"\n const stroke = strokeW ? ` stroke=\"${color}\" stroke-width=\"${strokeW.toFixed(2)}\"${dash}${keepWidth}` : \"\"\n const fill = ` fill=\"${shapeFill(el, defs, images, warn)}\"`\n let svg = \"\"\n if (o.tag === \"rect\") svg = `<rect x=\"${pt(x)}\" y=\"${pt(y)}\" width=\"${pt(w)}\" height=\"${pt(h)}\"${fill}${stroke}/>`\n else if (o.tag === \"ellipse\") svg = `<ellipse cx=\"${pt(x + w / 2)}\" cy=\"${pt(y + h / 2)}\" rx=\"${pt(w / 2)}\" ry=\"${pt(h / 2)}\"${fill}${stroke}/>`\n else if (o.tag === \"line\") {\n const s = findChildByLocalName(el, \"startPt\"), e = findChildByLocalName(el, \"endPt\")\n svg = `<line x1=\"${pt(x + num(s, \"x\") * sx)}\" y1=\"${pt(y + num(s, \"y\") * sy)}\" x2=\"${pt(x + num(e, \"x\") * sx)}\" y2=\"${pt(y + num(e, \"y\") * sy)}\" stroke=\"${color}\" stroke-width=\"${(strokeW || 0.3).toFixed(2)}\"${dash}${keepWidth}/>`\n } else if (o.tag === \"polygon\" || o.tag === \"curv\") {\n const pts = elements(el).filter(c => ln(c) === \"pt\").map(c => `${pt(x + num(c, \"x\") * sx)},${pt(y + num(c, \"y\") * sy)}`)\n if (pts.length >= 2) svg = `<polygon points=\"${pts.join(\" \")}\"${fill}${stroke}/>`\n } else if (o.tag === \"curve\") {\n // CURVE 조각도 점을 잇는다 — 한컴은 곡선을 촘촘한 점(약 200 HWPUNIT 간격)으로 펴서 조각마다 담는다(위례선 트램 보도자료 실측).\n // 종전엔 CURVE 조각이 하나라도 있으면 통째 생략해, 곡선 덮개가 가리던 자리가 드러났다(#116)\n const segs = elements(el).filter(c => ln(c) === \"seg\")\n if (segs.length) {\n let path = \"\", lastX: number | undefined, lastY: number | undefined\n for (const s of segs) {\n const x1 = num(s, \"x1\"), y1 = num(s, \"y1\"), x2 = num(s, \"x2\"), y2 = num(s, \"y2\")\n if (x1 !== lastX || y1 !== lastY) path += `M${pt(x + x1 * sx)} ${pt(y + y1 * sy)}`\n path += `L${pt(x + x2 * sx)} ${pt(y + y2 * sy)}`\n lastX = x2; lastY = y2\n }\n svg = `<path d=\"${path}\"${fill}${stroke}/>`\n }\n } else if (o.tag === \"arc\") svg = `<ellipse cx=\"${pt(x + w / 2)}\" cy=\"${pt(y + h / 2)}\" rx=\"${pt(w / 2)}\" ry=\"${pt(h / 2)}\" fill=\"none\"${stroke || ` stroke=\"${color}\" stroke-width=\"0.3\"`}/>`\n return { ...geometry, svg }\n}\n","/** 떠 있는 개체의 기준계와 문단 원점 해석. 그리기 문맥에서 필요한 기하만 받는다. */\nimport { findChildByLocalName } from \"../hwpx/parser-shared.js\"\nimport { num, measureTableHeight, type ParaObj, type ExtentMemo } from \"./para-model.js\"\n\ninterface AnchorContext {\n geom: { PW: number; PH: number; ML: number; MT: number; BODY_W: number; BODY_H: number }\n extentMemo: ExtentMemo\n bodyDx?: (page: number) => number\n page: number\n}\n\n/**\n * 글 없는 문단(위아래 개체 하나)의 줄이 개체에 밀려 저장됐는가 — 줄 = 문단 영역 위 + 바깥 위 + 저장 높이 + 바깥 아래.\n * 그런 줄은 제자리가 아니라 밀어내기 규칙을 따른다(한컴 저장본: 빈 문단 줄 68081 = 앞 문단 끝 7365 + 그림 60716)\n */\nexport function linePushedBy(o: ParaObj, lineV: number, paraTop: number | undefined): boolean {\n if (paraTop === undefined) return false\n const om = findChildByLocalName(o.el, \"outMargin\")\n // 문단 기준 아래 오프셋도 개체 몫이다(한컴 저장본: vertOffset 750 표에 밀린 빈 문단 줄 33738 = 앞 문단 끝 29540 + 750 + 바깥 여백 + 표 2882)\n const pos = findChildByLocalName(o.el, \"pos\")\n const raw = num(pos, \"vertOffset\"), vo = (pos?.getAttribute(\"vertRelTo\") ?? \"PARA\") === \"PARA\" ? Math.max(0, raw >= 2 ** 31 ? raw - 2 ** 32 : raw) : 0\n return Math.abs(lineV - (vo + num(om, \"top\") + o.height + num(om, \"bottom\")) - paraTop) <= 10\n}\n\nexport function anchorObject(o: ParaObj, ox: number, oy: number, baseV: number, areaW: number, ctx: AnchorContext, anchorLineV?: number, stayLine: number | false = false, paraStartV?: number, lineH?: number, lineSB = 0, anchorAt: \"end\" | \"mid\" | \"top\" = \"end\"): { x: number; y: number } {\n const { PW, PH, ML, MT, BODY_W, BODY_H } = ctx.geom\n const pos = findChildByLocalName(o.el, \"pos\")\n const om = findChildByLocalName(o.el, \"outMargin\")\n const omT = num(om, \"top\"), omB = num(om, \"bottom\")\n // 표는 셀 콘텐츠 성장으로 선언 sz보다 커질 수 있다 — reflow가 실효높이로 밀어낸 만큼\n // 되돌려야 표가 뒤 문단 위에 겹치지 않는다 (한컴 저장본은 sz가 실높이라 차이 없음)\n const w = o.width, h = o.tag === \"tbl\" ? Math.max(o.height, measureTableHeight(o.el, ctx.extentMemo)) : o.height\n if (!pos) return { x: ox, y: oy + baseV }\n const voRaw = num(pos, \"vertOffset\"), voS = voRaw >= 2 ** 31 ? voRaw - 2 ** 32 : voRaw\n // 문단 기준 개체를 위로 올린 오프셋(부호 없는 32비트 저장 −12126)은 문단 위에서 멈춘다 — reflow 와 같은 규칙(꼬리말 글상자가 121pt 위로 뜨던 것)\n const vo = (pos.getAttribute(\"vertRelTo\") ?? \"PARA\") === \"PARA\" ? Math.max(0, voS) : voS\n const ho = num(pos, \"horzOffset\")\n const vrel = pos.getAttribute(\"vertRelTo\") ?? \"PARA\"\n const hrel = pos.getAttribute(\"horzRelTo\") ?? \"PARA\"\n const va = pos.getAttribute(\"vertAlign\") ?? \"TOP\"\n const ha = pos.getAttribute(\"horzAlign\") ?? \"LEFT\"\n const wrap = o.el.getAttribute(\"textWrap\") ?? \"TOP_AND_BOTTOM\"\n\n let y: number\n if (vrel === \"PAPER\") {\n // 용지 기준 세로도 가로처럼 바깥 여백을 더한다(한컴 PDF: 바깥 위 852 인 용지 기준 그림이 vertOffset 5720 보다 8.5pt 아래)\n y = va === \"BOTTOM\" ? PH - h - vo - omB : va === \"CENTER\" ? (PH - h) / 2 + vo : vo + omT\n } else if (vrel === \"PAGE\") {\n y = va === \"BOTTOM\" ? MT + BODY_H - h - vo : va === \"CENTER\" ? MT + (BODY_H - h) / 2 + vo : MT + vo\n } else if (wrap === \"TOP_AND_BOTTOM\") {\n // PARA 밀어내기 역산 — 호스트 문단 vp가 개체(여백 포함)만큼 밀렸다는 모델 (실측 일치).\n // 음수면 밀지 않은 개체(빈 호스트 줄 등)로 보고 현재 흐름 y 사용.\n // 앵커 글자가 든 줄 기준 — 첫 줄 뒤에 앵커된 개체는 그 줄 위에 끼어 있다(reflow 와 같은 규칙, 한컴 저장본 연락처 표)\n const lineV = anchorLineV ?? baseV\n // 줄을 민 개체는 줄 바로 위에서 끝난다 — 아래 오프셋도 줄 위쪽 몫이다(문단 위 + 오프셋 + 바깥 위 + 높이 + 바깥 아래 = 줄)\n const pushed = lineV - (vo + omT + h + omB)\n // 글 없는 문단(위아래 개체 하나)의 줄은 제자리 — 개체는 줄 위치에서 시작한다(reflow 와 같은 규칙, 저장본 178/181). 꼬리말 글상자가 꼬리말 위로 뜨던 것\n // 글을 밀지 않은(줄 아래에 놓인) 첫 줄 앵커 개체는 문단 영역 위(앞 문단 끝, 위 간격 앞) 기준 — 한컴 PDF: 위 간격 뒤 줄 20056 의\n // 표가 앞 문단 끝 18856 + vertOffset 에 찍힌다(줄 기준이면 12pt 아래)\n // 첫 줄 뒤 앵커 개체가 세로 오프셋으로 앵커 줄보다 아래 놓이면 줄을 밀지 않는다 — 개체 위 = 앵커 줄 위 + 오프셋\n // (한컴 PDF: 인라인 표 줄 다음 줄에 앵커한 vertOffset 8455 로고 표가 그 줄 위 + 84.55pt + 바깥 위, 미는 모델이면 42.5pt 위)\n // 첫 줄에 앵커한 개체도 오프셋이 그 줄 높이 이상이면 줄 아래 — 줄을 밀지 않고 문단 영역 위(줄 − 위 간격) + 오프셋(한컴 저장본: 글 뒤에 앵커한\n // vertOffset 1877 표 아래 문단이 줄 24922 + 1877 + 표 높이, 미는 모델이면 앞 표 위에 겹쳐 그렸다). 앞 문단 줄 끝이 아니라 줄 자리에서 잰다 —\n // 앞 문단의 떠 있는 표 아래로 밀려 저장된 줄(한컴 저장본: 표 끝 34181 에 저장된 그림 문단 줄, 그림은 그 아래 783)\n // 줄이 바로 이 개체에 밀려 저장됐으면(문단 위 + 오프셋 + 개체 = 줄) 줄 아래가 아니다\n const below = lineH !== undefined && vo + omT >= lineH && !(paraStartV !== undefined && Math.abs(pushed - paraStartV) <= 10)\n const anchor = below ? lineV - lineSB : stayLine !== false ? lineV - stayLine : pushed >= -100 ? pushed : paraStartV !== undefined ? paraStartV : lineV\n y = oy + anchor + omT + vo\n } else {\n // BEHIND_TEXT/IN_FRONT/SQUARE — 문단을 밀지 않는 개체는 문단 원점 흐름 배치(어울림은 앵커 줄보다 위로 못 간다), 바깥 위 여백만큼 아래\n // (한컴 PDF: 바깥 위 850 인 어울림 사진이 vertOffset 자리보다 8.5pt 아래 — 가로가 바깥 왼쪽을 더하는 것과 같다)\n const origin = vrel === \"PARA\" && wrap === \"SQUARE\" ? paraStartV ?? baseV : baseV\n // 첫 줄 뒤 줄에 앵커한 어울림 개체는 그 줄 위 + 오프셋(위아래 배치의 나중 줄 앵커와 같다 — 같은 판 한컴 PDF: 여섯째 줄 24640 에 앵커한\n // vertOffset 2080 사진이 24640 + 2080, 문단 위 + 오프셋이면 20.5pt 위)\n // 문단 끝(뒤 글 없음)에 앵커한 것만 그 줄 기준. 문단 중간 글자 앵커는 앵커 줄보다 위로 못 가지만, 첫 줄부터 앵커 줄만큼 좁게 저장된\n // 문단(anchorAt \"top\")은 문단 위 기준(같은 판 한컴 PDF: 둘째 줄 글자에 앵커한 vertOffset 0 사진이 첫 줄 자리)\n const later = vrel === \"PARA\" && wrap === \"SQUARE\" && anchorAt === \"end\" && anchorLineV !== undefined && anchorLineV > baseV\n const midLater = vrel === \"PARA\" && wrap === \"SQUARE\" && anchorAt === \"top\" && anchorLineV !== undefined && anchorLineV > baseV\n y = later ? oy + anchorLineV + vo + omT : oy + Math.max(origin + vo, wrap === \"SQUARE\" && !midLater && anchorLineV !== undefined ? anchorLineV : -Infinity) + omT\n }\n\n let x: number\n // 바깥 여백: 왼쪽 정렬은 오프셋 + 바깥 왼쪽, 오른쪽 정렬은 − 바깥 오른쪽(한컴 PDF: 바깥 왼쪽 283 인 떠 있는 표 x = 왼 여백 + 2.83pt)\n const omL = num(om, \"left\"), omR = num(om, \"right\")\n if (hrel === \"PAGE\") {\n x = ha === \"RIGHT\" ? ML + BODY_W - w - ho - omR : ha === \"CENTER\" ? ML + (BODY_W - w) / 2 + ho : ML + ho + omL\n } else if (hrel === \"PAPER\") {\n // 용지 기준은 맞쪽 이동 묶음 밖 좌표 — 묶음 이동만큼 되돌린다\n x = (ha === \"RIGHT\" ? PW - w - ho - omR : ha === \"CENTER\" ? (PW - w) / 2 + ho : ho + omL) - (ctx.bodyDx?.(ctx.page) ?? 0)\n } else {\n // PARA/COLUMN — 현재 텍스트 영역 기준 (셀 안이면 셀 내부 폭. COLUMN을 페이지\n // 단으로 읽으면 셀 안 개체가 페이지 왼쪽으로 튄다 — 사진대지 우측 셀 실측)\n x = ha === \"RIGHT\" ? ox + areaW - w - ho - omR : ha === \"CENTER\" ? ox + (areaW - w) / 2 + ho : ox + ho + omL\n }\n return { x, y }\n}\n\n","/**\n * 수식(hp:equation 스크립트 → LaTeX)을 한 줄 유니코드 글로 — 렌더러가 수식 상자 안에 읽을 수 있는 대체 글을 그릴 때 쓴다.\n * 분수는 a/b, 제곱근은 √, 위·아래 첨자는 첨자 문자(없는 글자는 ^(…)·_(…)), 그리스 문자·연산 기호는 유니코드로 바꾼다.\n */\n\nconst SYMBOLS: Record<string, string> = {\n alpha: \"α\", beta: \"β\", gamma: \"γ\", delta: \"δ\", epsilon: \"ε\", varepsilon: \"ε\", zeta: \"ζ\", eta: \"η\", theta: \"θ\", vartheta: \"ϑ\",\n iota: \"ι\", kappa: \"κ\", lambda: \"λ\", mu: \"μ\", nu: \"ν\", xi: \"ξ\", pi: \"π\", rho: \"ρ\", sigma: \"σ\", tau: \"τ\", upsilon: \"υ\",\n phi: \"φ\", varphi: \"φ\", chi: \"χ\", psi: \"ψ\", omega: \"ω\", Gamma: \"Γ\", Delta: \"Δ\", Theta: \"Θ\", Lambda: \"Λ\", Xi: \"Ξ\", Pi: \"Π\",\n Sigma: \"Σ\", Phi: \"Φ\", Psi: \"Ψ\", Omega: \"Ω\",\n times: \"×\", cdot: \"·\", div: \"÷\", pm: \"±\", mp: \"∓\", le: \"≤\", leq: \"≤\", ge: \"≥\", geq: \"≥\", ne: \"≠\", neq: \"≠\", approx: \"≈\",\n equiv: \"≡\", sim: \"∼\", infty: \"∞\", rightarrow: \"→\", leftarrow: \"←\", Rightarrow: \"⇒\", Leftarrow: \"⇐\", leftrightarrow: \"↔\",\n Leftrightarrow: \"⇔\", to: \"→\", angle: \"∠\", triangle: \"△\", perp: \"⊥\", parallel: \"∥\", circ: \"∘\", degree: \"°\",\n sum: \"Σ\", prod: \"Π\", int: \"∫\", oint: \"∮\", partial: \"∂\", nabla: \"∇\", in: \"∈\", notin: \"∉\", subset: \"⊂\", supset: \"⊃\",\n subseteq: \"⊆\", supseteq: \"⊇\", cup: \"∪\", cap: \"∩\", emptyset: \"∅\", forall: \"∀\", exists: \"∃\", therefore: \"∴\", because: \"∵\",\n prime: \"′\", cdots: \"⋯\", ldots: \"…\", dots: \"…\", vdots: \"⋮\", lim: \"lim\", log: \"log\", ln: \"ln\", sin: \"sin\", cos: \"cos\", tan: \"tan\",\n sec: \"sec\", csc: \"csc\", cot: \"cot\", exp: \"exp\", max: \"max\", min: \"min\", quad: \" \", qquad: \" \", \",\": \" \", \";\": \" \", \"!\": \"\",\n \"{\": \"{\", \"}\": \"}\", \"|\": \"‖\", backslash: \"\\\\\", lbrace: \"{\", rbrace: \"}\", langle: \"⟨\", rangle: \"⟩\",\n}\nconst SUP: Record<string, string> = { \"0\": \"⁰\", \"1\": \"¹\", \"2\": \"²\", \"3\": \"³\", \"4\": \"⁴\", \"5\": \"⁵\", \"6\": \"⁶\", \"7\": \"⁷\", \"8\": \"⁸\", \"9\": \"⁹\", \"+\": \"⁺\", \"-\": \"⁻\", \"=\": \"⁼\", \"(\": \"⁽\", \")\": \"⁾\", n: \"ⁿ\", i: \"ⁱ\", x: \"ˣ\", \"′\": \"′\" }\n// 문자 아래 첨자(ₙ·ₖ)는 흔한 글꼴에 없어 빈 상자로 그려진다 — 숫자·기호만 첨자 문자로\nconst SUB: Record<string, string> = { \"0\": \"₀\", \"1\": \"₁\", \"2\": \"₂\", \"3\": \"₃\", \"4\": \"₄\", \"5\": \"₅\", \"6\": \"₆\", \"7\": \"₇\", \"8\": \"₈\", \"9\": \"₉\", \"+\": \"₊\", \"-\": \"₋\", \"=\": \"₌\", \"(\": \"₍\", \")\": \"₎\" }\n\n/** LaTeX → 한 줄 유니코드 글 */\nexport function latexToPlain(latex: string): string {\n let i = 0\n const s = latex\n const skipWs = (): void => { while (i < s.length && s[i] === \" \") i++ }\n /** 인자 하나 — {…} 묶음이거나 명령·글자 하나 */\n const arg = (): string => {\n skipWs()\n if (s[i] === \"{\") { i++; const v = seq(\"}\"); i++; return v }\n return atom()\n }\n const wrap = (v: string): string => (v.length > 1 && !/^[\\w.′]+$|^\\(.*\\)$/u.test(v) ? `(${v})` : v)\n const script = (v: string, map: Record<string, string>, mark: string): string => {\n const t = v.trim()\n return [...t].every(c => map[c]) ? [...t].map(c => map[c]).join(\"\") : `${mark}${wrap(t)}`\n }\n const atom = (): string => {\n const c = s[i]\n if (c === undefined) return \"\"\n if (c === \"\\\\\") {\n i++\n let name = \"\"\n if (/[A-Za-z]/.test(s[i] ?? \"\")) while (/[A-Za-z]/.test(s[i] ?? \"\")) name += s[i++]\n else name = s[i++] ?? \"\"\n if (name === \"frac\") { const a = arg(), b = arg(); return `${wrap(a.trim())}/${wrap(b.trim())}` }\n if (name === \"sqrt\") { skipWs(); let root = \"\"; if (s[i] === \"[\") { i++; root = seq(\"]\"); i++ } const a = arg(); return `${root ? script(root, SUP, \"\") : \"\"}√${wrap(a.trim())}` }\n if (name === \"left\" || name === \"right\" || name === \"big\" || name === \"Big\" || name === \"bigg\" || name === \"Bigg\") { skipWs(); const d = s[i] === \"\\\\\" ? atom() : s[i++] ?? \"\"; return d === \".\" ? \"\" : d }\n if (name === \"overline\" || name === \"bar\" || name === \"hat\" || name === \"vec\" || name === \"dot\" || name === \"tilde\") {\n const a = arg().trim(), mark = { overline: \"̅\", bar: \"̄\", hat: \"̂\", vec: \"⃗\", dot: \"̇\", tilde: \"̃\" }[name]!\n return [...a].map(ch => ch + mark).join(\"\")\n }\n if (name === \"mathrm\" || name === \"text\" || name === \"rm\" || name === \"mathbf\" || name === \"it\" || name === \"mathit\" || name === \"operatorname\") return name === \"rm\" || name === \"it\" ? \"\" : arg()\n return SYMBOLS[name] ?? name\n }\n i++\n if (c === \"{\") { const v = seq(\"}\"); i++; return v }\n if (c === \"^\") return script(arg(), SUP, \"^\")\n if (c === \"_\") return script(arg(), SUB, \"_\")\n if (c === \"~\" || c === \"`\") return \" \"\n return c\n }\n const seq = (end: string): string => {\n let out = \"\"\n while (i < s.length && s[i] !== end) {\n if (s[i] === \" \") { i++; continue }\n out += atom()\n }\n return out\n }\n return seq(\"\\u0000\").replace(/\\s+/g, \" \").trim()\n}\n","/**\n * HWPX/HWP equation script → LaTeX\n *\n * Ported from hml-equation-parser (Python, Apache 2.0)\n * https://github.com/OpenBapul/hml-equation-parser\n * Copyright 2018 Open Bapul\n * See THIRD_PARTY/hml-equation-parser.txt for the full license.\n *\n * Entry point: `hmlToLatex(script)`.\n *\n * Notes:\n * - The input is the raw text of <hp:script> inside <hp:equation>, i.e.\n * Hancom's mini equation language (\"HULK-style\"). Example:\n * x = { -b +- SQRT { b^2 -4ac } } over {2a}\n * is converted to:\n * x = \\frac { -b +- \\sqrt { b^2 -4ac } }{2a}\n * - The algorithm is a direct port of hulkEqParser.py / hulkReplaceMethod.py\n * with the same 5-pass rewrite (frac → rootOf → matrix → bar → brace).\n */\n\ninterface MatrixMapping {\n begin: string\n end: string\n removeOutterBrackets: boolean\n}\n\n// ─── convertMap (from convertMap.json) ────────────────────────────────────\n// Single-token replacements (applied to each whitespace-delimited token).\n// Exported for equation-generate.ts: 예약어 도출 + 전 토큰 왕복 테스트 (PR #39).\nexport const CONVERT_MAP: Record<string, string> = {\n TIMES: \"\\\\times\", times: \"\\\\times\",\n LEFT: \"\\\\left\", RIGHT: \"\\\\right\",\n under: \"\\\\underline\",\n SMALLSUM: \"\\\\sum\", sum: \"\\\\sum\",\n SMALLPROD: \"\\\\prod\", prod: \"\\\\prod\",\n SMALLINTER: \"\\\\cap\",\n CUP: \"\\\\cup\",\n OPLUS: \"\\\\oplus\", OMINUS: \"\\\\ominus\", OTIMES: \"\\\\otimes\", ODIV: \"\\\\oslash\", ODOT: \"\\\\odot\",\n LOR: \"\\\\lor\", LAND: \"\\\\land\",\n SUBSET: \"\\\\subset\", SUPERSET: \"\\\\supset\", SUBSETEQ: \"\\\\subseteq\", SUPSETEQ: \"\\\\supseteq\",\n IN: \"\\\\in\", OWNS: \"\\\\owns\", NOTIN: \"\\\\notin\",\n LEQ: \"\\\\leq\", GEQ: \"\\\\geq\",\n \"<<\": \"\\\\ll\", \">>\": \"\\\\gg\", \"<<<\": \"\\\\lll\", \">>>\": \"\\\\ggg\",\n PREC: \"\\\\prec\", SUCC: \"\\\\succ\",\n UPLUS: \"\\\\uplus\",\n \"±\": \"\\\\pm\", \"+-\": \"\\\\pm\", \"-+\": \"\\\\mp\", \"÷\": \"\\\\div\",\n cdot: \"\\\\cdot\",\n CIRC: \"\\\\circ\", BULLET: \"\\\\bullet\", DEG: \" ^\\\\circ\",\n AST: \"\\\\ast\", STAR: \"\\\\bigstar\", BIGCIRC: \"\\\\bigcirc\",\n EMPTYSET: \"\\\\emptyset\",\n THEREFORE: \"\\\\therefore\", BECAUSE: \"\\\\because\", EXIST: \"\\\\exists\",\n // 한글 수식 편집기는 소문자 therefore·because 도 같은 기호로 그린다(#148) — 생성 쪽 정준형은 대문자(equation-generate COMMAND_MAP)\n therefore: \"\\\\therefore\", because: \"\\\\because\",\n \"!=\": \"\\\\neq\",\n SMCOPROD: \"\\\\coprod\", coprod: \"\\\\coprod\",\n SQCAP: \"\\\\sqcap\", SQCUP: \"\\\\sqcup\",\n SQSUBSET: \"\\\\sqsubset\", SQSUBSETEQ: \"\\\\sqsubseteq\",\n BIGSQCUP: \"\\\\bigsqcup\",\n BIGOPLUS: \"\\\\bigoplus\", BIGOTIMES: \"\\\\bigotimes\", BIGODOT: \"\\\\bigodot\", BIGUPLUS: \"\\\\biguplus\",\n inter: \"\\\\bigcap\", union: \"\\\\bigcup\",\n BIGOMINUS: \"{\\\\Large\\\\ominus}\", BIGODIV: \"{\\\\Large\\\\oslash}\",\n UNDEROVER: \"\",\n SIM: \"\\\\sim\", APPROX: \"\\\\approx\", SIMEQ: \"\\\\simeq\", CONG: \"\\\\cong\",\n \"==\": \"\\\\equiv\",\n DIAMOND: \"\\\\diamond\", FORALL: \"\\\\forall\",\n prime: \"'\", Partial: \"\\\\partial\", INF: \"\\\\infty\", PROPTO: \"\\\\propto\",\n lim: \"\\\\lim\", Lim: \"\\\\lim\",\n larrow: \"\\\\leftarrow\", \"->\": \"\\\\rightarrow\",\n uparrow: \"\\\\uparrow\", downarrow: \"\\\\downarrow\",\n LARROW: \"\\\\Leftarrow\", RARROW: \"\\\\Rightarrow\",\n UPARROW: \"\\\\Uparrow\", DOWNARROW: \"\\\\Downarrow\",\n udarrow: \"\\\\updownarrow\",\n \"<->\": \"\\\\leftrightarrow\",\n UDARROW: \"\\\\Updownarrow\", LRARROW: \"\\\\Leftrightarrow\",\n NWARROW: \"\\\\nwarrow\", SEARROW: \"\\\\searrow\", NEARROW: \"\\\\nearrow\", SWARROW: \"\\\\swarrow\",\n HOOKLEFT: \"\\\\hookleftarrow\", HOOKRIGHT: \"\\\\hookrightarrow\",\n PVER: \"\\\\|\", MAPSTO: \"\\\\mapsto\",\n CDOTS: \"\\\\cdots\", LDOTS: \"\\\\ldots\", VDOTS: \"\\\\vdots\", DDOTS: \"\\\\ddots\",\n DAGGER: \"\\\\dagger\", DDAGGER: \"\\\\ddagger\", DOTEQ: \"\\\\doteq\",\n image: \"\\\\fallingdotseq\", REIMAGE: \"\\\\risingdotseq\",\n ASYMP: \"\\\\asymp\", ISO: \"\\\\Bumpeq\",\n DSUM: \"\\\\dotplus\", XOR: \"\\\\veebar\",\n TRIANGLE: \"\\\\triangle\", NABLA: \"\\\\nabla\",\n ANGLE: \"\\\\angle\", MSANGLE: \"\\\\measuredangle\", SANGLE: \"\\\\sphericalangle\",\n VDASH: \"\\\\vdash\", DASHV: \"\\\\dashv\",\n BOT: \"\\\\bot\", TOP: \"\\\\top\", MODELS: \"\\\\models\",\n LAPLACE: \"\\\\mathcal{L}\",\n CENTIGRADE: \"^{\\\\circ}C\", FAHRENHEIT: \"^{\\\\circ}F\",\n LSLANT: \"\\\\diagup\", RSLANT: \"\\\\diagdown\",\n\n sqrt: \"\\\\sqrt\",\n int: \"\\\\int\", dint: \"\\\\iint\", tint: \"\\\\iiint\", oint: \"\\\\oint\",\n\n alpha: \"\\\\alpha\", beta: \"\\\\beta\", gamma: \"\\\\gamma\", delta: \"\\\\delta\",\n epsilon: \"\\\\epsilon\", zeta: \"\\\\zeta\", eta: \"\\\\eta\", theta: \"\\\\theta\",\n iota: \"\\\\iota\", kappa: \"\\\\kappa\", lambda: \"\\\\lambda\", mu: \"\\\\mu\",\n nu: \"\\\\nu\", xi: \"\\\\xi\", omicron: \"\\\\omicron\", pi: \"\\\\pi\",\n rho: \"\\\\rho\", sigma: \"\\\\sigma\", tau: \"\\\\tau\", upsilon: \"\\\\upsilon\",\n phi: \"\\\\phi\", chi: \"\\\\chi\", psi: \"\\\\psi\", omega: \"\\\\omega\",\n ALPHA: \"A\", BETA: \"B\", GAMMA: \"\\\\Gamma\", DELTA: \"\\\\Delta\",\n EPSILON: \"E\", ZETA: \"Z\", ETA: \"H\", THETA: \"\\\\Theta\",\n IOTA: \"I\", KAPPA: \"K\", LAMBDA: \"\\\\Lambda\", MU: \"M\",\n NU: \"N\", XI: \"\\\\Xi\", OMICRON: \"O\", PI: \"\\\\Pi\",\n RHO: \"P\", SIGMA: \"\\\\Sigma\", TAU: \"T\", UPSILON: \"\\\\Upsilon\",\n PHI: \"\\\\Phi\", CHI: \"X\", PSI: \"\\\\Psi\", OMEGA: \"\\\\Omega\",\n\n \"⌈\": \"\\\\lceil\", \"⌉\": \"\\\\rceil\",\n \"⌊\": \"\\\\lfloor\", \"⌋\": \"\\\\rfloor\",\n \"∥\": \"\\\\|\",\n \"⊐\": \"\\\\sqsupset\", \"⊒\": \"\\\\sqsupseteq\",\n\n odint: \"\\\\mathop ∯\",\n otint: \"\\\\mathop ∰\",\n BIGSQCAP: \"\\\\mathop ⨅\",\n ATT: \"\\\\mathop ※\",\n HUND: \"\\\\mathop ‰\",\n THOU: \"\\\\mathop ‱\",\n IDENTICAL: \"\\\\mathop ∷\",\n RTANGLE: \"\\\\mathop ⊾\",\n BASE: \"\\\\mathop ⌂\",\n BENZENE: \"\\\\mathop ⌬\",\n}\n\n// Tokens rewritten to a HULK-prefixed marker, then expanded in second passes.\nexport const MIDDLE_CONVERT_MAP: Record<string, string> = {\n matrix: \"HULKMATRIX\",\n pmatrix: \"HULKPMATRIX\",\n bmatrix: \"HULKBMATRIX\",\n dmatrix: \"HULKDMATRIX\",\n eqalign: \"HULKEQALIGN\",\n cases: \"HULKCASE\",\n vec: \"HULKVEC\",\n dyad: \"HULKDYAD\",\n acute: \"HULKACUTE\",\n grave: \"HULKGRAVE\",\n dot: \"HULKDOT\",\n ddot: \"HULKDDOT\",\n bar: \"HULKBAR\",\n hat: \"HULKHAT\",\n check: \"HULKCHECK\",\n arch: \"HULKARCH\",\n tilde: \"HULKTILDE\",\n BOX: \"HULKBOX\",\n OVERBRACE: \"HULKOVERBRACE\",\n UNDERBRACE: \"HULKUNDERBRACE\",\n}\n\nconst BAR_CONVERT_MAP: Record<string, string> = {\n HULKVEC: \"\\\\overrightarrow\",\n HULKDYAD: \"\\\\overleftrightarrow\",\n HULKACUTE: \"\\\\acute\",\n HULKGRAVE: \"\\\\grave\",\n HULKDOT: \"\\\\dot\",\n HULKDDOT: \"\\\\ddot\",\n HULKBAR: \"\\\\overline\",\n HULKHAT: \"\\\\widehat\",\n HULKCHECK: \"\\\\check\",\n HULKARCH: \"\\\\overset{\\\\frown}\",\n HULKTILDE: \"\\\\widetilde\",\n HULKBOX: \"\\\\boxed\",\n}\n\nconst MATRIX_CONVERT_MAP: Record<string, MatrixMapping> = {\n HULKMATRIX: { begin: \"\\\\begin{matrix}\", end: \"\\\\end{matrix}\", removeOutterBrackets: true },\n HULKPMATRIX: { begin: \"\\\\begin{pmatrix}\", end: \"\\\\end{pmatrix}\", removeOutterBrackets: true },\n HULKBMATRIX: { begin: \"\\\\begin{bmatrix}\", end: \"\\\\end{bmatrix}\", removeOutterBrackets: true },\n HULKDMATRIX: { begin: \"\\\\begin{vmatrix}\", end: \"\\\\end{vmatrix}\", removeOutterBrackets: true },\n HULKCASE: { begin: \"\\\\begin{cases}\", end: \"\\\\end{cases}\", removeOutterBrackets: true },\n HULKEQALIGN: { begin: \"\\\\eqalign{\", end: \"}\", removeOutterBrackets: false },\n}\n\nconst BRACE_CONVERT_MAP: Record<string, string> = {\n HULKOVERBRACE: \"\\\\overbrace\",\n HULKUNDERBRACE: \"\\\\underbrace\",\n}\n\n// ─── Bracket scanning helpers ─────────────────────────────────────────────\n\n/**\n * Find a matching `{...}` pair at/after `startIdx`. Returns [start, end) such that eqString.slice(start, end)\n * is the full bracketed substring including the `{` and `}`.\n * Throws when no matching bracket exists.\n * (역방향 탐색은 replaceFrac 이 출력 배열 꼬리에서 직접 한다 — 문자열 전체를 뒤집던 방식이 over 마다 O(n))\n */\nfunction findBrackets(eqString: string, startIdx: number): [number, number] {\n const startCur = eqString.indexOf(\"{\", startIdx)\n if (startCur === -1) throw new Error(\"cannot find bracket\")\n let bracketCount = 1\n for (let i = startCur + 1; i < eqString.length; i++) {\n const ch = eqString[i]\n if (ch === \"{\") bracketCount += 1\n else if (ch === \"}\") bracketCount -= 1\n if (bracketCount === 0) return [startCur, i + 1]\n }\n throw new Error(\"cannot find bracket\")\n}\n\n/**\n * From a cursor inside a bracketed group, walk backward to the enclosing\n * `{` and return the outer `{...}` span.\n */\nfunction findOutterBrackets(eqString: string, startIdx: number): [number, number] {\n const outer = findEnclosingBrackets(eqString, startIdx)\n if (!outer) throw new Error(\"cannot find bracket\")\n return outer\n}\n\n/**\n * Find the nearest `{...}` group that actually encloses `startIdx`.\n * A previous closed group such as `_ { x } HULKBAR { y }` must not be\n * treated as the outer wrapper for `HULKBAR`.\n */\nfunction findEnclosingBrackets(eqString: string, startIdx: number): [number, number] | null {\n let depth = 0\n for (let idx = startIdx - 1; idx >= 0; idx--) {\n const ch = eqString[idx]\n if (ch === \"}\") {\n depth += 1\n } else if (ch === \"{\") {\n if (depth > 0) {\n depth -= 1\n continue\n }\n try {\n const [start, end] = findBrackets(eqString, idx)\n if (start === idx && end > startIdx) return [start, end]\n } catch {\n return null\n }\n return null\n }\n }\n return null\n}\n\n// ─── Rewrite passes ───────────────────────────────────────────────────────\n\n/**\n * \"...\" 리터럴과 \\text{...} 스팬을 동일 길이 필러로 가린 사본 — 예약어(over/root/of)\n * 검색이 리터럴 내부 부분문자열을 연산자로 오인하지 않게 한다 (인덱스 정렬 보존).\n * 따옴표 홀수(비페어)면 해당 구간은 못 가리고 기존 동작으로 남는다.\n */\nfunction maskLiteralSpans(eqString: string): string {\n return eqString\n .replace(/\"[^\"]*\"/g, (m) => \"￿\".repeat(m.length))\n .replace(/\\\\text\\{[^}]*\\}/g, (m) => \"￿\".repeat(m.length))\n}\n\n/** 공백 경계의 독립 토큰으로만 예약어 검색 (리터럴 스팬 마스킹). 없으면 -1 */\nfunction findKeywordToken(eqString: string, word: string, from = 0): number {\n const masked = maskLiteralSpans(eqString)\n for (let i = masked.indexOf(word, from); i !== -1; i = masked.indexOf(word, i + 1)) {\n const okL = i === 0 || /\\s/.test(masked[i - 1])\n const okR = i + word.length === masked.length || /\\s/.test(masked[i + word.length])\n if (okL && okR) return i\n }\n return -1\n}\n\n/**\n * `{1} over {2}` → `\\frac{1}{2}`. over 토큰을 왼쪽부터 한 번 훑으며 출력 배열 꼬리에서 분자를 바꾼다.\n * 종전엔 over 하나마다 식 전체를 다시 가리고(maskLiteralSpans)·뒤집고(findBrackets 역방향)·이어 붙여\n * over n 개에 O(n²)였다(×2000 1.25초, ×4000 5.3초). 가림은 입력에서 한 번만 한다 — hmlToLatex 토큰화 뒤라\n * 치환이 따옴표를 더하거나 빼지 않고, \\text{…} 안은 공백이 없어 over 토큰이 생기지 않으므로 매번 가린 것과 같다.\n * 원소는 한 글자(치환이 넣는 \"\\\\frac\" 만 한 원소 — 중괄호·공백이 없어 역방향 훑기에 글자열과 같다).\n */\nfunction replaceFrac(eqString: string): string {\n const hmlFrac = \"over\"\n const masked = maskLiteralSpans(eqString)\n const out: string[] = []\n let pos = 0 // eqString 에서 out 으로 옮긴 끝\n for (let cursor = masked.indexOf(hmlFrac); cursor !== -1; cursor = masked.indexOf(hmlFrac, cursor + 1)) {\n const okL = cursor === 0 || /\\s/.test(masked[cursor - 1])\n const okR = cursor + hmlFrac.length === masked.length || /\\s/.test(masked[cursor + hmlFrac.length])\n if (!okL || !okR) continue\n for (; pos < cursor; pos++) out.push(eqString[pos])\n // 분자는 over 바로 앞(공백 스킵)의 인접 토큰 — 왼쪽 가장 가까운 } 그룹을 잡아\n // 그 사이 콘텐츠를 무음 삭제하던 것 방지 (sqrt {x} + 1 over 2 에서 \" + 1 \" 증발)\n let end = out.length\n // 공백류 클래스를 findKeywordToken 경계(/\\s/)와 일치시켜 다중줄 스크립트의 분자 무음\n // 유실 방지 — over 앞뒤가 \\n·\\t·nbsp 여도 분자 경계를 옳게 잡는다 (eqrt-3/eqrt-2 정합)\n while (end > 0 && /\\s/.test(out[end - 1])) end--\n let numStart = end\n if (end > 0 && out[end - 1] === \"}\") {\n // 짝 { 까지 거꾸로 (없으면 종전 findBrackets 예외와 같이 여기서 멈춘다)\n let depth = 0\n for (numStart = end - 1; numStart >= 0; numStart--) {\n if (out[numStart] === \"}\") depth++\n else if (out[numStart] === \"{\" && --depth === 0) break\n }\n if (numStart < 0) break\n out.length = end\n out.splice(numStart, 0, \"\\\\frac\")\n } else {\n while (numStart > 0 && !/\\s/.test(out[numStart - 1])) numStart--\n if (numStart === end) break // 빈 분자\n out.length = end\n out.splice(numStart, 0, \"\\\\frac\", \"{\")\n out.push(\"}\")\n }\n pos = cursor + hmlFrac.length\n }\n return out.join(\"\") + eqString.slice(pos)\n}\n\n/** `root {1} of {2}` → `\\sqrt[1]{2}` */\nfunction replaceRootOf(eqString: string): string {\n while (true) {\n const rootCursor = findKeywordToken(eqString, \"root\")\n if (rootCursor === -1) break\n try {\n const elem1 = findBrackets(eqString, rootCursor)\n // of는 root의 지수 그룹 뒤에서만 유효 — 전역 첫 매치는 리터럴/선행 텍스트를 오인한다\n const ofCursor = findKeywordToken(eqString, \"of\", elem1[1])\n if (ofCursor === -1) return eqString\n const elem2 = findBrackets(eqString, ofCursor)\n const e1 = eqString.slice(elem1[0] + 1, elem1[1] - 1)\n const e2 = eqString.slice(elem2[0] + 1, elem2[1] - 1)\n eqString =\n eqString.slice(0, rootCursor) +\n \"\\\\sqrt\" +\n \"[\" + e1 + \"]\" +\n \"{\" + e2 + \"}\" +\n eqString.slice(elem2[1] + 1)\n } catch {\n return eqString\n }\n }\n return eqString\n}\n\n/** matrix/pmatrix/bmatrix/dmatrix/cases/eqalign expansion. */\nfunction replaceAllMatrix(eqString: string): string {\n const replaceElements = (bracketStr: string): string => {\n let inner = bracketStr.slice(1, -1) // strip outer `{` `}`\n inner = inner.replace(/#/g, \" \\\\\\\\ \")\n inner = inner.replace(/&amp;/g, \"&\")\n return inner\n }\n\n const replaceMatrix = (input: string, matStr: string, matElem: MatrixMapping): string => {\n while (true) {\n const cursor = input.indexOf(matStr)\n if (cursor === -1) break\n try {\n const [eStart, eEnd] = findBrackets(input, cursor)\n const elem = replaceElements(input.slice(eStart, eEnd))\n let beforeMat: string\n let afterMat: string\n const outer = matElem.removeOutterBrackets ? findEnclosingBrackets(input, cursor) : null\n if (outer && outer[1] >= eEnd) {\n const [bStart, bEnd] = outer\n beforeMat = input.slice(0, bStart)\n afterMat = input.slice(bEnd)\n } else {\n beforeMat = input.slice(0, cursor)\n afterMat = input.slice(eEnd)\n }\n input = beforeMat + matElem.begin + elem + matElem.end + afterMat\n } catch {\n return input\n }\n }\n return input\n }\n\n for (const [matKey, matElem] of Object.entries(MATRIX_CONVERT_MAP)) {\n eqString = replaceMatrix(eqString, matKey, matElem)\n }\n return eqString\n}\n\n/** vec/hat/bar/dot/ddot/tilde/… (HULK-prefixed) → LaTeX accent. */\nfunction replaceAllBar(eqString: string): string {\n const replaceBar = (input: string, barStr: string, barElem: string): string => {\n while (true) {\n const cursor = input.indexOf(barStr)\n if (cursor === -1) break\n try {\n const [eStart, eEnd] = findBrackets(input, cursor)\n const elem = input.slice(eStart, eEnd)\n const outer = findEnclosingBrackets(input, cursor)\n const [replaceStart, replaceEnd] = outer && outer[1] >= eEnd ? outer : [cursor, eEnd]\n const beforeBar = input.slice(0, replaceStart)\n const afterBar = input.slice(replaceEnd)\n input = beforeBar + barElem + elem + afterBar\n } catch {\n return input\n }\n }\n return input\n }\n\n for (const [barKey, barElem] of Object.entries(BAR_CONVERT_MAP)) {\n eqString = replaceBar(eqString, barKey, barElem)\n }\n return eqString\n}\n\n/** overbrace/underbrace: `BRACE {body} {label}` → `\\overbrace{body}^{label}` */\nfunction replaceAllBrace(eqString: string): string {\n const replaceBrace = (input: string, braceStr: string, braceElem: string): string => {\n while (true) {\n const cursor = input.indexOf(braceStr)\n if (cursor === -1) break\n try {\n const [eStart1, eEnd1] = findBrackets(input, cursor)\n const [eStart2, eEnd2] = findBrackets(input, eEnd1)\n const elem1 = input.slice(eStart1, eEnd1)\n const elem2 = input.slice(eStart2, eEnd2)\n const beforeBrace = input.slice(0, cursor)\n const afterBrace = input.slice(eEnd2)\n input = beforeBrace + braceElem + elem1 + \"^\" + elem2 + afterBrace\n } catch {\n return input\n }\n }\n return input\n }\n\n for (const [braceKey, braceElem] of Object.entries(BRACE_CONVERT_MAP)) {\n eqString = replaceBrace(eqString, braceKey, braceElem)\n }\n return eqString\n}\n\n/** After single-token pass, fix `\\left {` → `\\left \\{` and `\\right }` → `\\right \\}`. */\nfunction replaceBracket(strList: string[]): string[] {\n for (let i = 0; i < strList.length; i++) {\n if (strList[i] === \"{\" && i > 0 && strList[i - 1] === \"\\\\left\") strList[i] = \"\\\\{\"\n if (strList[i] === \"}\" && i > 0 && strList[i - 1] === \"\\\\right\") strList[i] = \"\\\\}\"\n }\n return strList\n}\n\n/**\n * Convert an HWPX equation script (mini Hancom equation language) to LaTeX.\n * Returns the converted LaTeX body (without `$` delimiters).\n */\nexport function hmlToLatex(hmlEqStr: string): string {\n if (!hmlEqStr) return \"\"\n\n // 스크립트 안 줄바꿈·탭은 공백 — HULK 행 구분은 `#` 이고 개행은 서식일 뿐이다. 남기면 토큰에\n // 붙어 LaTeX 로 새고(`5x+a \\\\ ⏎ }`), 인라인 수식 `$…$` 이 줄을 넘어 수식으로 인식되지 않는다 (math-001 cases)\n let s = hmlEqStr.replace(/[\\r\\n\\t]+/g, \" \").replace(/`/g, \" \")\n s = s.replace(/\\{/g, \" { \").replace(/\\}/g, \" } \").replace(/&/g, \" & \")\n\n let tokens = s.split(\" \")\n for (let i = 0; i < tokens.length; i++) {\n const t = tokens[i]\n // hasOwn 필수 — `in`은 Object.prototype 키(constructor·toString 등)에도 걸려\n // 수식 토큰이 그 이름이면 함수가 치환값이 된다 (출력에 native code 주입/무음 삭제)\n if (Object.hasOwn(CONVERT_MAP, t)) tokens[i] = CONVERT_MAP[t]\n else if (Object.hasOwn(MIDDLE_CONVERT_MAP, t)) tokens[i] = MIDDLE_CONVERT_MAP[t]\n else {\n // EqEdit 리터럴 따옴표(\"int\" 등 — 명령 해석 차단용) → \\text{...}로 복원.\n // 생성기(equation-generate.ts)의 \\text→\"...\" 출력과 고정점을 이룬다.\n // 공백 포함 다중 토큰 인용은 기존대로 통과 (토큰 단위라 식별 불가).\n const quoted = /^\"(.+)\"$/.exec(t)\n if (quoted) tokens[i] = `\\\\text{${quoted[1]}}`\n }\n }\n tokens = tokens.filter(tok => tok.length !== 0)\n tokens = replaceBracket(tokens)\n\n let out = tokens.join(\" \")\n out = replaceFrac(out)\n out = replaceRootOf(out)\n out = replaceAllMatrix(out)\n out = replaceAllBar(out)\n out = replaceAllBrace(out)\n\n return out\n}\n","/**\n * HWP5 수식 레코드(EQEDIT) 스크립트 → LaTeX.\n *\n * HWP5의 EQEDIT 레코드도 HWPX <hp:script>와 같은 한컴 EqEdit 언어라\n * 구조 변환(분수·근호·행렬·액센트·토큰 매핑)은 hwpx/equation.ts(hmlToLatex)를\n * 정본으로 재사용한다. 이 모듈은 HWP5 실문서에서 관측되는 표기 편차\n * (소문자 예약어·붙여쓴 첨자·유니코드 연산자·글꼴 지시자)를 정본 토크나이저가\n * 인식할 수 있는 형태로 정규화하는 호환 프리패스만 담당한다.\n */\n\nimport { CONVERT_MAP, MIDDLE_CONVERT_MAP, hmlToLatex } from \"../hwpx/equation.js\"\n\n/**\n * 정본 CONVERT_MAP에 (해당 표기로는) 없는 hwp5 지원 어휘 → LaTeX 직접 치환.\n * 키는 소문자 — 대소문자 무관 매칭(구 hwp5 동작 보존). 정본에 정확히 있는\n * 토큰(IN, GEQ, ALPHA 등)이 우선이라 여기까지 오지 않는다.\n */\nconst WORD_ALIASES: Record<string, string> = {\n // 삼각/로그 함수 — 정본 맵 부재\n sin: \"\\\\sin\", cos: \"\\\\cos\", tan: \"\\\\tan\", sec: \"\\\\sec\", csc: \"\\\\csc\", cot: \"\\\\cot\",\n log: \"\\\\log\", ln: \"\\\\ln\",\n // 연산자·관계 기호 (정본은 대문자 키만 보유)\n divide: \"\\\\div\", div: \"\\\\div\",\n le: \"\\\\leq\", ge: \"\\\\geq\", geq: \"\\\\geq\", deg: \"^\\\\circ\",\n rarrow: \"\\\\rightarrow\", lrarrow: \"\\\\leftrightarrow\",\n rightarrow: \"\\\\rightarrow\", leftarrow: \"\\\\leftarrow\",\n in: \"\\\\in\", notin: \"\\\\notin\", emptyset: \"\\\\emptyset\",\n subset: \"\\\\subset\", nsubset: \"\\\\nsubseteq\",\n cup: \"\\\\cup\", cap: \"\\\\cap\", smallinter: \"\\\\cap\", smallsum: \"\\\\sum\",\n sim: \"\\\\sim\", circ: \"\\\\circ\", bot: \"\\\\perp\",\n partial: \"\\\\partial\", nabla: \"\\\\nabla\",\n angle: \"\\\\angle\", triangle: \"\\\\triangle\",\n inf: \"\\\\infty\",\n left: \"\\\\left\", right: \"\\\\right\",\n // 글꼴 지시자 — 제거\n rm: \"\", it: \"\",\n}\n\n/** 구조 예약어 — hmlToLatex가 소문자만 인식하므로 대소문자 무관 입력을 접는다 */\nconst STRUCTURAL_FOLD = new Set([\"over\", \"root\", \"of\"])\n\n/** 어절 단위 사전 정규화 — 정본 키 우선, 없으면 소문자 별칭/정본 키로 폴드 */\nfunction normalizeWords(input: string): string {\n return input.replace(/(?<![\\\\A-Za-z0-9])([A-Za-z][A-Za-z0-9]*)(?![A-Za-z0-9])/g, word => {\n // hasOwn 필수 — `in`은 Object.prototype 키에도 걸린다 (hwpx/equation.ts 동일 주석 참조)\n if (Object.hasOwn(CONVERT_MAP, word) || Object.hasOwn(MIDDLE_CONVERT_MAP, word)) return word\n const lower = word.toLowerCase()\n if (STRUCTURAL_FOLD.has(lower)) return lower\n if (Object.hasOwn(WORD_ALIASES, lower)) return WORD_ALIASES[lower]\n if (lower !== word && (Object.hasOwn(CONVERT_MAP, lower) || Object.hasOwn(MIDDLE_CONVERT_MAP, lower))) return lower\n return word\n })\n}\n\n/** 첨자 정규화 — 공백 제거 후 미괄호 인자를 중괄호로 감싸고, 정본 토큰화용으로 분리 */\nfunction normalizeScripts(input: string): string {\n return input\n .replace(/\\s*\\^\\s*/g, \"^\")\n .replace(/\\s*_\\s*/g, \"_\")\n .replace(/\\^(?!\\{)([^\\s{}_^]+)/g, \"^{$1}\")\n .replace(/_(?!\\{)([^\\s{}_^]+)/g, \"_{$1}\")\n // \"sum_{k}\"가 통짜 토큰으로 남지 않게 ^/_를 독립 토큰으로 분리 (LaTeX 의미 동일)\n .replace(/([_^])/g, \" $1 \")\n}\n\n/** 붙여쓴/유니코드 연산자 → LaTeX (정본 토큰 맵은 공백 분리 토큰만 인식) */\nfunction normalizeOperators(input: string): string {\n return input\n .replace(/\\+-/g, \" \\\\pm \")\n .replace(/-\\+/g, \" \\\\mp \")\n .replace(/\\/\\//g, \" \\\\parallel \")\n .replace(/!=/g, \" \\\\neq \")\n .replace(/<=/g, \" \\\\leq \")\n .replace(/>=/g, \" \\\\geq \")\n .replace(/==/g, \" \\\\equiv \")\n .replace(/△/g, \" \\\\triangle \")\n .replace(/□/g, \" \\\\square \")\n .replace(/‧/g, \" \\\\cdot \")\n}\n\nexport function hwpEquationToLatex(equation: string): string {\n let s = equation.replace(/\\0/g, \"\").replace(/\\s+/g, \" \").trim()\n if (!s) return \"\"\n\n s = normalizeScripts(s)\n s = normalizeOperators(s)\n s = normalizeWords(s)\n // 미괄호 근호 지수(\"root n of {x}\") — 정본 replaceRootOf는 중괄호 그룹만 인식\n s = s.replace(/\\broot\\s+(?!\\{)(\\S+)\\s+of(?![A-Za-z0-9])/gi, \"root { $1 } of\")\n\n return hmlToLatex(s).replace(/\\s+/g, \" \").trim()\n}\n","/** 문단·글상자·그룹 개체 그리기와 페이지 출력 문맥. */\n\nimport { findChildByLocalName } from \"../hwpx/parser-shared.js\"\nimport { measureTextWidth, faceClassOf } from \"../hwpx/text-metrics.js\"\nimport { DEFAULT_CHAR, type RenderStyles } from \"./head-styles.js\"\nimport { glyphWidth, joinsJamo } from \"./reflow.js\"\nimport { mapPuaText } from \"../shared/pua.js\"\nimport { latexToPlain } from \"./equation-text.js\"\nimport { hwpEquationToLatex } from \"../hwp5/equation.js\"\nimport { RegionCollector, type PageBBox } from \"./scene.js\"\nimport { nextParaNumber, type NumberCounters } from \"./para-number.js\"\nimport { ln, elements, num, type Seg, type ParaChar, OBJ_TAGS, FORM_TAGS, type ParaObj, type ParaModel, buildPara, tabAdvance, paraHeadAdvance, type ExtentMemo, cellContentExtent, measureTableHeight, captionOf, captionExtra } from \"./para-model.js\"\nimport { planTableRows } from \"./table-pages.js\"\nimport { mulAffine, objectGeometry, renderingMatrix, shapeGeometry, rotatedBounds, SHAPE_TAGS, type Affine, type RegionRotation } from \"./shape-geometry.js\"\nimport { anchorObject, linePushedBy } from \"./object-anchor.js\"\n\nexport function escapeXml(s: string): string {\n return s\n // XML 1.0 금지 C0 제어문자 제거(탭 0x09·개행 0x0A·CR 0x0D는 유지) — 남기면 산출 SVG가\n // 불법 XML이라 뷰어·브라우저가 그 페이지 렌더를 통째로 중단한다(\"PCDATA invalid Char value\").\n // gen-ids.escapeXml·source-map.escapeXmlText와 같은 계약 (rhwp #3382 동종)\n .replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/g, \"\")\n .replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\")\n}\n\n// ─── 내부 모델 ────────────────────────────────────\n\n/** mirrorDx — 맞쪽(gutterType LEFT_RIGHT) 짝수 쪽의 본문 가로 이동(오른쪽 여백 − 왼쪽 여백). 짝수 쪽은 좌우 여백이 바뀐다 */\nexport interface PageGeom { PW: number; PH: number; ML: number; MT: number; BODY_W: number; BODY_H: number; mirrorDx?: number }\n\nexport interface Ctx {\n draw: {\n table: (tbl: Element, x: number, y: number, ctx: Ctx, depth: number) => void\n pic: (pic: Element, x: number, y: number, ctx: Ctx) => void\n picFrame: (pic: Element, x: number, y: number, w: number, h: number, transform: string, ctx: Ctx) => void\n }\n /** 최상위 문단의 문단 영역 위(앞 문단 끝, 새 쪽이면 0) — 첫 줄이 개체 아래로 밀려 저장된 문단의 개체 기준 */\n paraTops?: Map<Element, number>\n /** 다단 구역의 단 폭·간격 — 최상위 떠 있는 개체의 단(COLUMN·PARA) 기준을 앵커 줄의 단으로 잡는다 */\n cols?: { w: number; gap: number }\n /** 쪽에서 갈린 본문 표 칸의 문단을 그리는 중 — 그 문단의 떠 있는 표도 쪽에서 가른다 */\n splitCell?: boolean\n /** 갈린 칸 안 표가 이어지는 쪽에서 다시 시작하는 자리(바깥 표의 이어진 쪽 위 + 칸 위 여백) */\n splitContMT?: number\n /** 본문(맞쪽 이동 묶음 안)을 그리는 중 — 쪽마다 본문 가로 이동량. region·용지 기준 개체는 이만큼 보정한다 */\n bodyDx?: (page: number) => number\n /** 행 계획이 옮긴 칸 안 떠 있는 개체의 쪽·위(절대 y) — 쪽을 넘게 쌓인 개체(planTableRows place) */\n objPlace?: Map<Element, { page: number; y: number }>\n /** 페이지별 SVG 버퍼 — emit()이 현재 페이지(page)로 라우팅 */\n pages: string[][]\n /** 현재 그리는 페이지 인덱스 — 최상위 문단만 갱신, 셀/중첩 콘텐츠는 호스트 페이지 상속 */\n page: number\n geom: PageGeom\n styles: RenderStyles\n images: Map<string, { dataUri: string; symId?: string; orgW?: number; orgH?: number }>\n /** 이미지 심볼 defs — dataURI는 여기 1회만, 본문은 <use> 참조 (occurrence당 재emit 금지) */\n defs: string[]\n /** 검색어 형광펜 (소문자 정규화, 빈 문자열 제거) */\n highlights: string[]\n /** 문단 번호 카운터 — 그리는 순서(문서 순서)로 센다. 전 구역 공유 */\n nums: NumberCounters\n warnings: string[]\n warned: Set<string>\n stats: { texts: number; images: number; tables: number; shapes: number }\n /** 셀/표 측정 메모 — 중첩표 지수 재계산 캡 (렌더 1회 공유) */\n extentMemo: ExtentMemo\n /** 개체 region 수집 — 그리는 순서로 결정적 id (#75). 전 구역 공유 */\n regions: RegionCollector\n /** 현재 열린 부모 region id 스택 (표 셀 콘텐츠·문단 개체·도형 글상자) */\n parentStack: string[]\n /** 앞선 구역들의 페이지 수 누계 — 전역 1-based 페이지 = pageBase + page + 1 */\n pageBase: number\n /** 이 구역 페이지의 실높이(HWPUNIT) — 단일 페이지 캔버스 연장 포함. region 하단 클램프용 */\n pageH: number\n paintJobs: PaintJob[] | null\n /** Same ancestor rotations as the SVG groups containing this object's paint. */\n regionRotations: Array<RegionRotation | Affine>\n}\nexport interface PaintJob { page: number; layer: number; z: number; draw: () => void; body?: boolean }\n\nexport const pt = (u: number): string => String(Math.round(u) / 100)\n/** HWPUNIT → pt (소수 둘째 자리) */\nexport const ptNum = (u: number): number => Math.round(u) / 100\n\n/** 현재 그리는 페이지의 전역 1-based 번호 */\nexport function pageNo(ctx: Ctx): number { return ctx.pageBase + ctx.page + 1 }\n\n/** HWPUNIT 사각형 → 페이지 로컬 pt bbox. 페이지 하단을 넘는 높이는 잘라 기록(분할 지오메트리 없음) */\nexport function bboxOf(ctx: Ctx, x: number, y: number, w: number, h: number): PageBBox {\n const b = rotatedBounds({ x, y, w, h }, ctx.regionRotations)\n if (ctx.bodyDx) b.x += ctx.bodyDx(ctx.page)\n const clippedH = Math.max(0, Math.min(b.h, ctx.pageH - b.y))\n return { page: pageNo(ctx), x: ptNum(b.x), y: ptNum(b.y), width: ptNum(Math.max(0, b.w)), height: ptNum(clippedH) }\n}\n\nexport function regionOpenTag(id: string, type: string, page: number): string {\n return `<g data-kordoc-id=\"${id}\" data-kordoc-type=\"${type}\" data-kordoc-page=\"${page}\">`\n}\n\nexport function parentId(ctx: Ctx): string | undefined {\n return ctx.parentStack.length ? ctx.parentStack[ctx.parentStack.length - 1] : undefined\n}\n\nexport function emit(ctx: Ctx, s: string): void {\n ctx.pages[ctx.page].push(s)\n}\n\nexport function warnOnce(ctx: Ctx, key: string, msg: string): void {\n if (ctx.warned.has(key)) return\n ctx.warned.add(key)\n ctx.warnings.push(msg)\n}\n\n// ─── 문단 모델 구축 ────────────────────────────────\n\n// ─── 줄 렌더 (run별 charPr + 정렬) ──────────────────\n\ninterface LinePlan {\n seg: Seg\n /** 줄 시작 x 보정 (정렬) */\n xoff: number\n /** 텍스트 조각 폭 스케일 */\n scale: number\n /** 양쪽 정렬 줄의 빈칸마다 더하는 폭(HWPUNIT) — 한컴은 남는 폭을 빈칸에만 나눈다 */\n spaceAdd: number\n /** spaceAdd 를 받는 빈칸의 시작(줄 앞 빈칸 뒤) */\n spFrom: number\n /** 넘친 양쪽 정렬 줄에서 빈칸 아닌 글자마다 더하는 폭(HWPUNIT, 음수) — 빈칸이 줄 수 있는 몫을 넘은 나머지 */\n charAdd?: number\n start: number\n end: number\n /** 탭 슬롯 → 전진폭(HWPUNIT, 스케일 불변) */\n tabs: Map<number, number>\n /** 이 인덱스 앞(줄의 마지막 탭까지)은 스케일 없이 — 양쪽 정렬은 마지막 탭 뒤 글에만 걸린다 */\n fixedTo: number\n /** 줄 끝 공백을 뺀 끝 — 줄 끝 공백은 걸리기만 하고(hang) 정렬·그리기에서 빠진다 */\n textEnd: number\n /** 첫 줄 앞에 그릴 글머리표 — x 는 줄 글 시작 바로 앞 */\n bullet?: { ch: string; w: number; prId: string | null }\n}\n\nfunction charW(c: ParaChar, styles: RenderStyles, prev?: ParaChar): number {\n const st = (c.prId != null ? styles.charPr.get(c.prId) : undefined) ?? DEFAULT_CHAR\n if (c.ch === \"\" && c.ctrlText) return measureTextWidth(c.ctrlText, c.ctrlSup ? Math.round(st.height * 3 / 4) : st.height, st.ratio, { spacingPct: st.spacing, faceClass: faceClassOf(st.face) })\n // 글자 폭은 reflow 와 같은 한컴 폭 — 언어별(영문) 글꼴·장평·상대크기, 4 단위 양자화, 첨자 16/25, 합성 굵기.\n // 옛한글 자모는 reflow 와 같이 앞 자모에 합쳐 잰다\n let w = 0, last = prev?.ch ? prev.ch.codePointAt(prev.ch.length - 1) ?? 0 : 0\n for (const ch of c.ch) { const cp = ch.codePointAt(0)!; if (!joinsJamo(last, cp)) w += glyphWidth(ch, st).w; last = cp }\n return w\n}\n\n/** 줄 자연폭 = 텍스트 조각 + 인라인 개체 폭 (개체 폭은 스케일 불변, TAC 표는 outMargin 좌/우 포함) */\nfunction lineNaturalWidth(m: ParaModel, styles: RenderStyles, start: number, end: number): { text: number; obj: number } {\n let text = 0\n for (let i = start; i < end && i < m.chars.length; i++) text += charW(m.chars[i], styles, m.chars[i - 1])\n let obj = 0\n for (const o of m.objs) if (o.inline && o.index >= start && o.index < end) obj += o.omL + o.width + o.omR\n return { text, obj }\n}\n\n/** numText: 문단 번호 머리 글(\"1.\"·\"가)\") — 글머리표처럼 첫 줄 앞에 그리고 그만큼 들인다 */\nfunction planLines(m: ParaModel, styles: RenderStyles, numText = \"\"): LinePlan[] {\n const align = (m.paraPrId != null ? styles.paraAlign.get(m.paraPrId) : undefined) ?? \"JUSTIFY\"\n const geom = m.paraPrId != null ? styles.paraGeom.get(m.paraPrId) : undefined\n const hang = geom && geom.marginIntent < 0 ? -geom.marginIntent : 0\n // 줄 앞머리 — 한컴 lineseg 의 horzpos·horzsize 는 첫 줄 들여쓰기(양수 intent)·둘째 줄부터의 내어쓰기(음수 intent)·글머리표를 빼지 않는다\n // (들여쓰기 문단 645개·내어쓰기 문단 수천 개 전부 horzpos = 왼쪽 여백). 글은 그만큼 들어가서 시작하고, 양쪽 정렬도 남는 폭에 맞춘다.\n // 글머리표는 autoIndent 면 둘째 줄부터도 들인다\n const bu = geom?.bullet ?? (numText && geom?.number ? { ch: numText, ...geom.number } : undefined)\n const firstPr = m.chars.find(c => c.ch !== \"\")?.prId ?? null\n const bst = (bu?.charPrId != null ? styles.charPr.get(bu.charPrId) : firstPr != null ? styles.charPr.get(firstPr) : undefined) ?? DEFAULT_CHAR\n const headW = bu?.useInstWidth === false ? [...bu.ch].reduce((w, ch) => w + glyphWidth(ch, bst, false).w, 0) : bu ? measureTextWidth(bu.ch, bst.height, bst.ratio, { spacingPct: bst.spacing, faceClass: faceClassOf(bst.face) }) : 0\n const bulletW = bu ? paraHeadAdvance(bu, bst.height, headW) : 0\n const plans: LinePlan[] = []\n // 탭 앞 x 에는 글자처럼 취급하는 개체 폭(바깥 여백 좌우 포함)도 든다 — reflow 와 같다. 빼면 내어쓰기 자동 탭이 개체 폭만큼 더 길어진다\n // (한컴 PDF: 체크칸 사각형 978 뒤 \"KZ⇥Kazakhstan\" 의 탭이 내어쓰기 위치에 선다 — 빼고 재면 9.6pt 오른쪽)\n const inlineW = new Map<number, number>()\n for (const o of m.objs) if (o.inline) inlineW.set(o.index, o.omL + o.width + o.omR)\n for (let i = 0; i < m.segs.length; i++) {\n const seg = m.segs[i]\n const start = seg.textpos\n const end = i + 1 < m.segs.length ? m.segs[i + 1].textpos : Math.max(m.chars.length, start)\n // 탭 해석 — 자연폭으로 정지점을 잡고, 마지막 탭까지는 스케일 없이 고정폭으로 둔다\n const tabs = new Map<number, number>()\n const lead = i === 0 ? Math.max(geom?.marginIntent ?? 0, 0) + bulletW : hang + (bu?.autoIndent ? bulletW : 0)\n let x = (i === 0 ? Math.max(geom?.marginIntent ?? 0, 0) : hang) + (i === 0 || bu?.autoIndent ? bulletW : 0) // 첫 줄은 들여쓰기(양수 intent)만큼 들어가서 시작\n let fixedTo = start\n let fixedW = 0\n for (let k = start; k < end && k < m.chars.length; k++) {\n const c = m.chars[k]\n const ow = inlineW.get(k)\n if (ow !== undefined) { x += ow; continue }\n if (!c.tab) { x += charW(c, styles, m.chars[k - 1]); continue }\n const adv = tabAdvance(x, i === 0, geom, c.tabW)\n tabs.set(k, adv)\n x += adv\n fixedTo = k + 1\n }\n if (fixedTo > start) fixedW = lineNaturalWidth(m, styles, start, fixedTo).text + [...tabs.values()].reduce((a, b) => a + b, 0)\n // 줄 끝 공백 제외 — 어절 줄바꿈은 줄마다 끝에 공백이 걸린다. 넣고 늘이면 글이 오른쪽 끝에 못 닿는다\n // 강제 줄바꿈 앞 공백도 줄 끝 공백이다(같은 판 한컴 PDF: \"… 아시아 ⏎\" 가운데 정렬 제목이 공백 빼고 가운데 — 넣으면 공백 반 폭 6.4pt 왼쪽)\n let textEnd = Math.min(end, m.chars.length)\n while (textEnd > fixedTo && m.chars[textEnd - 1].br) textEnd--\n while (textEnd > fixedTo && m.chars[textEnd - 1].ch === \" \") textEnd--\n const nat = lineNaturalWidth(m, styles, fixedTo, textEnd)\n for (const o of m.objs) if (o.inline && o.index >= textEnd && o.index < end) nat.obj += o.omL + o.width + o.omR\n nat.obj += fixedW\n for (const o of m.objs) if (o.inline && o.index >= start && o.index < fixedTo) nat.obj += o.omL + o.width + o.omR\n // 강제 줄바꿈(lineBreak)으로 끝난 줄도 마지막 줄처럼 늘이지 않는다 — 한컴 PDF: 양쪽 정렬 문단의 줄바꿈 줄이 자연 폭(114pt, 늘였다면 131pt)\n let brEnd = false\n for (let k = start; k < end && k < m.chars.length; k++) if (m.chars[k].br) brEnd = true\n const isLast = i === m.segs.length - 1 || brEnd\n let xoff = 0\n let scale = 1\n const lineW = seg.horzsize - lead\n const avail = lineW - nat.obj\n // 줄 끝 글자 뒤에는 자간을 두지 않는다 — 정렬·늘이기 폭에서 마지막 글자의 자간 몫을 뺀다(조판 넘침 판정과 같다)\n // (같은 판이 저장·인쇄한 한컴 PDF: 자간 −16% 26pt 가운데 정렬 제목 줄의 끝 글자 전진폭 25.19pt, 다른 한글 21.23pt)\n let lastSp = 0\n if (fixedTo === start) {\n let k = textEnd - 1\n while (k >= start && m.chars[k].ch === \"\") k--\n if (k >= start) {\n const c = m.chars[k], st = (c.prId != null ? styles.charPr.get(c.prId) : undefined) ?? DEFAULT_CHAR\n const cps = [...c.ch]\n lastSp = glyphWidth(cps[cps.length - 1], st).sp\n }\n }\n // 늘이기는 양쪽 정렬의 중간 줄·배분 정렬만 — 왼쪽·가운데·오른쪽 정렬은 줄마다 자연 폭으로 그 자리에 맞춘다\n // (한컴 PDF: 가운데 정렬 문단의 첫 줄이 가운데, 종전엔 중간 줄을 정렬과 무관하게 줄 폭에 늘였다)\n const stretch = align === \"JUSTIFY\" || align === \"DISTRIBUTE\" || align === \"DISTRIBUTE_SPACE\"\n let spaceAdd = 0, spaceFrom = fixedTo, charAdd = 0\n // 넘친 줄(자연 폭 > 줄 폭)은 빈칸을 제 폭의 20% 까지만 줄이고 나머지는 빈칸 아닌 글자마다 똑같이 줄인다 — 정렬과 공백 최소값(condense)에\n // 상관없다. 같은 판 한컴 PDF 넘친 줄 90여 개(글자마다 PDF 전진 − 자연 폭): 빈칸 몫은 −140(14pt 빈칸 700 의 20%)에서 멈추고\n // 글자 몫 = (모자람 − 빈칸 몫) / 글자 수 — 양쪽 정렬 3296·빈칸 7·글자 37 → −62(PDF −62), 가운데 정렬 마지막 줄 936·글자 10 → −93(PDF −93),\n // 왼쪽 정렬 3252·빈칸 13·글자 38 → −44(PDF −44). 모자람이 빈칸 몫 안이면 빈칸만(536·빈칸 10 → −54, PDF −52·글자 0)\n const squeeze = (spFrom: number): void => {\n const short = nat.text - lastSp - avail\n let nSp = 0, cap = 0, nG = 0\n for (let k = spFrom; k < textEnd; k++) { const c = m.chars[k]; if (c.ch === \" \") { nSp++; cap += charW(c, styles, m.chars[k - 1]) * 0.2 } else if (c.ch && !c.tab) nG++ }\n if (nSp > 0) { spaceAdd = -Math.min(short, cap) / nSp; spaceFrom = spFrom }\n if (short > cap && nG > 0) charAdd = -(short - (nSp > 0 ? cap : 0)) / nG\n }\n if (nat.text > 0 && stretch && (!isLast || align === \"DISTRIBUTE\" || align === \"DISTRIBUTE_SPACE\")) {\n // 줄바꿈이 고정된 중간 줄·배분정렬 — 줄 영역 폭에 맞춰 고정 (원본 조판 재현). 양쪽 정렬·빈칸 배분은 남는 폭을 빈칸에만 나눈다\n // (한컴 PDF: 양쪽 정렬 줄 30개 모두 빈칸 아닌 글자의 늘임 0~5 HWPUNIT, 늘임은 빈칸에). 빈칸 없는 줄·배분 정렬은 글자 전체를 늘인다\n let nSp = 0, spFrom = fixedTo\n // 줄 앞 빈칸은 늘이지 않는다 — 컨트롤(누름틀·떠 있는 개체 앵커)이 앞에 있으면 그 뒤 빈칸은 줄 앞이 아니다\n // (같은 판 한컴 PDF: 누름틀로 시작하는 양쪽 정렬 줄의 첫 빈칸이 다른 빈칸처럼 늘어난다)\n while (spFrom < textEnd && (m.chars[spFrom].ch === \" \" || m.chars[spFrom].ch === \"\") && !m.chars[spFrom].ctrl) spFrom++\n for (let k = spFrom; k < textEnd; k++) if (m.chars[k].ch === \" \") nSp++\n if (nSp > 0 && align !== \"DISTRIBUTE\") {\n spaceAdd = (avail - nat.text + lastSp) / nSp; spaceFrom = spFrom\n if (spaceAdd < 0) squeeze(spFrom)\n }\n else scale = avail > 0 ? avail / nat.text : 1\n } else if (nat.text + nat.obj > 0 && (isLast || !stretch)) {\n const w = nat.text + nat.obj - lastSp\n if (align === \"CENTER\") xoff = Math.max(0, (lineW - w) / 2)\n else if (align === \"RIGHT\") xoff = Math.max(0, lineW - w)\n }\n // 늘이지 않는 줄(왼쪽·가운데·오른쪽 정렬, 마지막 줄)도 넘치면 같은 규칙으로 줄인다 — 저장 줄 나눔이 그렇게 한 줄에 넣은 것이다\n if (spaceAdd === 0 && charAdd === 0 && scale === 1 && nat.text - lastSp > avail) {\n let spFrom = fixedTo\n while (spFrom < textEnd && (m.chars[spFrom].ch === \" \" || m.chars[spFrom].ch === \"\") && !m.chars[spFrom].ctrl) spFrom++\n squeeze(spFrom)\n }\n if (!Number.isFinite(scale) || scale <= 0) scale = 1\n scale = Math.min(4, Math.max(0.25, scale))\n plans.push({ seg, xoff: xoff + lead, scale, spaceAdd, spFrom: spaceFrom, ...(charAdd ? { charAdd } : {}), start, end, tabs, fixedTo, textEnd, ...(i === 0 && bu ? { bullet: { ch: bu.ch, w: bulletW, prId: bu.charPrId ?? firstPr } } : {}) })\n }\n return plans\n}\n\n/** 줄 안 [start, upto) 구간의 전진폭 (텍스트×스케일 + 인라인 개체 — TAC 표는 outMargin 좌/우 포함) */\nfunction advanceTo(m: ParaModel, styles: RenderStyles, plan: LinePlan, upto: number): number {\n let x = 0\n for (let i = plan.start; i < upto && i < m.chars.length; i++) {\n const c = m.chars[i], inStretch = i >= plan.spFrom && i < plan.textEnd\n x += c.tab ? plan.tabs.get(i) ?? 0 : charW(c, styles, m.chars[i - 1]) * (i < plan.fixedTo ? 1 : plan.scale) + (inStretch && c.ch === \" \" ? plan.spaceAdd : 0) + (inStretch && plan.charAdd && c.ch && c.ch !== \" \" ? plan.charAdd : 0)\n }\n for (const o of m.objs) if (o.inline && o.index >= plan.start && o.index < upto) x += o.omL + o.width + o.omR\n return x\n}\n\n// ─── 문단 드로잉 ───────────────────────────────────\n\n/**\n * @param segPages 최상위 문단 전용 — seg 인덱스별 페이지 배정 (vertpos 리셋 감지 결과).\n * 셀/중첩 콘텐츠는 전달하지 않아 호스트의 ctx.page 를 상속한다.\n */\nexport function drawPara(p: Element, ox: number, oy: number, areaW: number, ctx: Ctx, depth: number, segPages?: number[]): void {\n if (depth > 16) { warnOnce(ctx, \"depth\", \"중첩 깊이 16 초과 — 이하 생략\"); return }\n const m = buildPara(p)\n const numText = nextParaNumber(ctx.nums, m.paraPrId != null ? ctx.styles.paraGeom.get(m.paraPrId) : undefined)\n if (m.segs.length === 0) {\n // 조판 캐시 없는 문단 — 개체만이라도 문단 원점에 배치. 텍스트는 무음 생략 금지\n if (m.chars.some(c => c.ch !== \"\")) {\n warnOnce(ctx, \"no-lineseg\", \"조판 캐시 없는 문단 텍스트 생략 — reflow 옵션으로 합성 가능\")\n }\n for (const o of m.objs) {\n const { x, y } = o.inline ? { x: ox, y: oy } : anchorObject(o, ox, oy, 0, areaW, ctx)\n drawObject(o, x, y, 0, areaW, ctx, depth)\n }\n return\n }\n const plans = planLines(m, ctx.styles, numText)\n const baseV = m.segs[0].vertpos\n\n // 문단 region — 실문자가 있는 문단만. 줄(lineseg) 영역의 페이지별 합집합, 페이지가 바뀌면 조각을 나눈다.\n // SVG 는 페이지 버퍼별로 <g data-kordoc-*> 래퍼를 열고 닫는다(개체는 별도 region, parentId=문단).\n const hasText = m.chars.some(c => c.ch !== \"\" && c.ch.trim() !== \"\")\n let paraRegionId: string | null = null\n let gOpenOn = -1\n\n for (let li = 0; li < plans.length; li++) {\n const plan = plans[li]\n if (segPages && segPages[li] !== undefined) ctx.page = segPages[li]\n const { seg } = plan\n if (hasText) {\n const lineBox = bboxOf(ctx, ox + seg.horzpos, oy + seg.vertpos, seg.horzsize, seg.textheight)\n if (paraRegionId === null) paraRegionId = ctx.regions.add(\"paragraph\", lineBox, { parentId: parentId(ctx) })\n else ctx.regions.addFragment(paraRegionId, lineBox)\n if (gOpenOn !== ctx.page) {\n if (gOpenOn >= 0) ctx.pages[gOpenOn].push(\"</g>\")\n emit(ctx, regionOpenTag(paraRegionId, \"paragraph\", pageNo(ctx)))\n gOpenOn = ctx.page\n }\n }\n // charPr 단위 조각으로 분할\n let i = plan.start\n let cursor = ox + seg.horzpos + plan.xoff\n const y = oy + seg.vertpos + seg.baseline\n // 문단 세로 정렬 가운데·아래 — 저장 baseline 은 줄 가운데(높이/2)·줄 바닥이고, 한컴은 글자 상자(기준선 85%)를 거기에 맞춘다:\n // 가운데면 기준선 = 줄 가운데 + 0.35·글자 크기, 아래면 줄 바닥 − 0.15·글자 크기(한컴 PDF: 가운데 정렬 칸 숫자가 3.9pt 아래)\n const pva = m.paraPrId != null ? ctx.styles.paraGeom.get(m.paraPrId)?.vertAlign : undefined\n const glyphY = (h: number): number => y + (pva === \"CENTER\" ? Math.round(h * 0.35) : pva === \"BOTTOM\" ? -Math.round(h * 0.15) : 0)\n if (plan.bullet) {\n const bs = (plan.bullet.prId != null ? ctx.styles.charPr.get(plan.bullet.prId) : undefined) ?? DEFAULT_CHAR\n const attrs = [`x=\"${pt(cursor - plan.bullet.w)}\"`, `y=\"${pt(glyphY(bs.height))}\"`, `font-size=\"${pt(bs.height)}\"`]\n if (bs.fontFamily) attrs.push(`font-family=\"${escapeXml(bs.fontFamily)}\"`)\n if (bs.color) attrs.push(`fill=\"${escapeXml(bs.color)}\"`)\n emit(ctx, `<text ${attrs.join(\" \")}>${escapeXml(plan.bullet.ch)}</text>`)\n ctx.stats.texts++\n }\n while (i < plan.end && i < m.chars.length) {\n if (i >= plan.textEnd && m.chars[i].ch === \" \") { i++; continue }\n // 필러 슬롯(컨트롤·서로게이트 자리)은 그리지 않고 건너뛴다 —\n // 인라인 개체의 폭 전진은 개체 첫 슬롯에서 1회 수행\n if (m.chars[i].ch === \"\") {\n // 글을 그리는 컨트롤(주석 머리 번호 \"1)\"·각주·미주 본문 참조 번호) — reflow 와 같은 폭으로 그 자리에 그린다(참조 번호는 위첨자 크기·위로)\n const ct = m.chars[i].ctrlText\n if (ct) {\n const cs0 = (m.chars[i].prId != null ? ctx.styles.charPr.get(m.chars[i].prId!) : undefined) ?? DEFAULT_CHAR\n const sup = !!m.chars[i].ctrlSup, fh = sup ? Math.round(cs0.height * 16 / 25) : cs0.height\n const cw = measureTextWidth(ct, sup ? Math.round(cs0.height * 3 / 4) : fh, cs0.ratio, { spacingPct: cs0.spacing, faceClass: faceClassOf(cs0.face) })\n const attrs = [`x=\"${pt(cursor)}\"`, `y=\"${pt(glyphY(cs0.height) - (sup ? Math.round(cs0.height * 0.35) : 0))}\"`, `font-size=\"${pt(fh)}\"`]\n if (cs0.fontFamily) attrs.push(`font-family=\"${escapeXml(cs0.fontFamily)}\"`)\n if (cs0.color) attrs.push(`fill=\"${escapeXml(cs0.color)}\"`)\n emit(ctx, `<text ${attrs.join(\" \")}>${escapeXml(ct)}</text>`)\n ctx.stats.texts++\n cursor += cw * plan.scale\n }\n if (m.chars[i].tab) cursor += plan.tabs.get(i) ?? 0\n for (const o of m.objs) if (o.inline && o.index === i) cursor += o.omL + o.width + o.omR\n i++\n continue\n }\n // 마지막 탭 앞(부호 등)은 양쪽 정렬 스케일 없이 — 탭 뒤 내용 시작이 정지점에 정확히 선다\n const scale = i < plan.fixedTo ? 1 : plan.scale\n const prId = m.chars[i].prId\n let j = i\n let piece = \"\"\n // 필러에서 멈추므로 piece 안은 실문자뿐 — 개체 경계 절단이 자연 발생\n while (j < plan.end && j < m.chars.length && m.chars[j].prId === prId && m.chars[j].ch !== \"\" && !(j >= plan.textEnd && m.chars[j].ch === \" \")) { piece += m.chars[j].ch; j++ }\n // 연속 공백(2+) 경계 절단 — 공백 폭 오차(한컴 0.5em 고정 vs 뷰어 폰트)를\n // 공백 구간에 가둔다 (공무원 스페이스 정렬 원문에서 글자 벌어짐 방지)\n // (문자열 인덱스를 슬롯 오프셋으로 쓴다 — 서로게이트 쌍이 섞이면 1슬롯 오차, 무시)\n {\n const cut = piece.search(/ {2,}/)\n if (cut > 0) { piece = piece.slice(0, cut); j = i + cut }\n else if (cut === 0) {\n const runEnd = piece.match(/^ +/)![0].length\n piece = piece.slice(0, runEnd); j = i + runEnd\n }\n }\n const st = (prId != null ? ctx.styles.charPr.get(prId) : undefined) ?? DEFAULT_CHAR\n\n // 텍스트 세그먼트 1개를 렌더하고 전진폭 반환. hit=true 면 형광펜 배경 rect 를\n // 텍스트 앞에 깐다. 세그먼트마다 자체 textLength 를 쓰므로 rect(hit)와 글자가\n // 완전히 같은 폭·위치로 계산돼 형광펜이 어긋나지 않는다.\n // 위·아래 첨자 — 크기 16/25, 위첨자 기준선은 0.44·크기 위(한컴 PDF 위첨자 61문서: 9.59pt/15pt, 올림 0.434~0.446·크기). 아래첨자 높이는 실측 없음 — 기준선 그대로\n const fh = st.script ? Math.round(st.height * 16 / 25) : st.height\n const raise = st.script === \"sup\" ? Math.round(st.height * 0.44) : 0\n // 조각 폭 = 글자마다 한컴 폭(charW 와 같다 — 양쪽 정렬 계획과 그리기가 같은 폭을 쓴다)\n const measure = (text: string): number => { let w = 0, last = 0; for (const ch of text) { const cp = ch.codePointAt(0)!; if (!joinsJamo(last, cp)) w += glyphWidth(ch, st).w; last = cp } return w }\n // 늘임을 받는 빈칸 수 — 이 조각이 줄 앞 빈칸(spFrom 앞)에서 시작하면 그 빈칸은 뺀다\n const skipLead = Math.max(0, plan.spFrom - i)\n const spacesIn = (text: string): number => {\n let n = 0, k = 0\n for (const c of text) { if (c === \" \" && !(k < skipLead && text === piece)) n++; k++ }\n return n\n }\n const renderSeg = (text: string, cx: number, hit: boolean): number => {\n const sw = measure(text) * scale + (plan.spaceAdd && i >= plan.fixedTo ? plan.spaceAdd * spacesIn(text) : 0) + (plan.charAdd && i >= plan.fixedTo ? plan.charAdd * [...text].filter(ch => ch !== \" \").length : 0)\n // 글자 음영 — 글자 상자(기준선 위 0.85·크기부터 크기만큼, 한컴 PDF 13pt 글자의 음영 상자 13.07pt)\n if (st.shade) emit(ctx, `<rect x=\"${pt(cx)}\" y=\"${pt(glyphY(st.height) - Math.round(st.height * 0.85))}\" width=\"${pt(sw)}\" height=\"${pt(st.height)}\" fill=\"${escapeXml(st.shade)}\"/>`)\n if (hit) {\n emit(ctx, `<rect x=\"${pt(cx)}\" y=\"${pt(oy + seg.vertpos)}\" width=\"${pt(sw)}\" height=\"${pt(seg.textheight)}\" fill=\"#ffd54f\" fill-opacity=\"0.45\"/>`)\n }\n if (text.trim().length > 0) {\n const attrs: string[] = [`x=\"${pt(cx)}\"`, `y=\"${pt(glyphY(st.height) - raise)}\"`, `font-size=\"${pt(fh)}\"`]\n if (st.fontFamily) attrs.push(`font-family=\"${escapeXml(st.fontFamily)}\"`)\n if ([...text].length > 1 && sw > 50) {\n attrs.push(`textLength=\"${pt(sw)}\"`, `lengthAdjust=\"${scale < 1 ? \"spacingAndGlyphs\" : \"spacing\"}\"`)\n }\n if (st.bold) attrs.push(`font-weight=\"bold\"`)\n if (st.italic) attrs.push(`font-style=\"italic\"`)\n if (st.underline) attrs.push(`text-decoration=\"underline\"`)\n if (st.color) attrs.push(`fill=\"${escapeXml(st.color)}\"`)\n // 한컴 기호 PUA(Wingdings 계열·보충 사용자 영역)는 파서와 같은 표로 표준 기호로 바꿔 그린다 — 폭은 원래 글자로 쟀다(뷰어에 그 글꼴이 없어 빈 상자가 되던 것)\n emit(ctx, `<text ${attrs.join(\" \")}>${escapeXml(mapPuaText(text))}</text>`)\n ctx.stats.texts++\n }\n return sw\n }\n\n // 형광펜 매치 구간 수집 → 병합(겹침 제거) → [평문·매치·평문…] 분할 렌더\n const merged: Array<[number, number]> = []\n if (ctx.highlights.length > 0 && piece.trim().length > 0) {\n const found: Array<[number, number]> = []\n const lower = piece.toLowerCase()\n for (const term of ctx.highlights) {\n for (let f = lower.indexOf(term); f !== -1; f = lower.indexOf(term, f + term.length)) {\n found.push([f, f + term.length])\n }\n }\n found.sort((a, b) => a[0] - b[0])\n for (const [s, e] of found) {\n const tail = merged[merged.length - 1]\n if (tail && s <= tail[1]) tail[1] = Math.max(tail[1], e)\n else merged.push([s, e])\n }\n }\n\n if (merged.length === 0) {\n cursor += renderSeg(piece, cursor, false)\n } else {\n let segCur = cursor\n let last = 0\n for (const [s, e] of merged) {\n segCur += renderSeg(piece.slice(last, s), segCur, false)\n segCur += renderSeg(piece.slice(s, e), segCur, true)\n last = e\n }\n segCur += renderSeg(piece.slice(last), segCur, false)\n cursor = segCur\n }\n i = j\n }\n }\n if (gOpenOn >= 0) ctx.pages[gOpenOn].push(\"</g>\")\n\n // 개체 배치 — 인라인은 소속 줄 위치, 앵커는 hp:pos 해석. 개체 region 의 부모는 문단(없으면 상위)\n if (paraRegionId) ctx.parentStack.push(paraRegionId)\n /** 위아래 배치 개체 쌓기 — 개체마다 문단 영역 위에서 센 위치 */\n let tbStack: Map<Element, number> | undefined\n let tbStackTop: number | undefined\n for (const o of m.objs) {\n if (o.inline) {\n let planIdx = 0\n for (let k = 0; k < plans.length; k++) {\n const pl = plans[k]\n if (pl.start <= o.index && (o.index < pl.end || k === plans.length - 1)) planIdx = k\n }\n const plan = plans[planIdx]\n if (segPages && segPages[planIdx] !== undefined) ctx.page = segPages[planIdx]\n // TAC 표 괘선은 pen + outMargin좌 (advanceTo는 o.index 앞까지라 자신의 om 미포함)\n const x = ox + plan.seg.horzpos + plan.xoff + advanceTo(m, ctx.styles, plan, o.index) + o.omL\n // 개체가 줄보다 낮으면 baseline 위에 얹고, 줄을 채우는 개체(th==h)는 줄 상단\n // 수식은 제 기준선(높이 × baseLine%)을 줄 기준선에 맞춘다\n // 그림은 높이의 85% 가 기준선 위, 15% 는 아래(한컴 PDF: 기준선 2960 줄의 그림 2834·3276·3482 위가 줄 위 아래 551·175·0 — reflow 기준선 모델과 같다)\n // 그림자 있는 사진은 그림자까지 든 높이로 줄을 짠다 — 줄 높이가 사진보다 크고 기준선이 그 85% 면 사진은 줄 맨 위(같은 판 한컴 PDF:\n // 그림자 거리 300 인 34978 사진의 줄 35962·기준선 30568 = 0.85 × 35962, 사진 위가 줄 위)\n const shadowed = o.tag === \"pic\" && !!findChildByLocalName(findChildByLocalName(o.el, \"effects\") ?? o.el, \"shadow\") && plan.seg.textheight > o.height && Math.abs(plan.seg.baseline - Math.round(plan.seg.textheight * 0.85)) <= 2\n const eqAsc = o.tag === \"equation\" && Number(o.el.getAttribute(\"baseLine\")) > 0 ? Math.round(o.height * Number(o.el.getAttribute(\"baseLine\")) / 100) : shadowed ? Math.round(plan.seg.textheight * 0.85) : o.tag === \"pic\" ? Math.round(o.height * 0.85) : o.height\n // 바깥 여백: 개체(+아래 여백)는 기준선 위에 얹되 줄 위 + 위 여백보다 위로는 안 간다(한컴 PDF: 줄을 채우는 인라인 표 = 줄 위 + outMargin 위)\n const iom = findChildByLocalName(o.el, \"outMargin\"), iomT = num(iom, \"top\"), iomB = num(iom, \"bottom\")\n const yTop = oy + plan.seg.vertpos + Math.max(iomT, plan.seg.baseline - eqAsc - iomB - captionExtra(o.el))\n drawObject(o, x, yTop, baseV, areaW, ctx, depth)\n } else {\n // 앵커 좌표는 첫 seg(baseV) 기준이므로 첫 seg 의 페이지에 귀속\n if (segPages && segPages[0] !== undefined) ctx.page = segPages[0]\n // 다단 본문의 단·문단 기준 개체는 앵커 첫 줄이 든 단을 영역으로(한컴 PDF 실측: 오른쪽 단 문단의 CENTER 개체 = 오른쪽 단 + (단 폭 − 폭)/2 + 오프셋)\n let ax = ox, aw = areaW\n if (depth === 0 && ctx.cols && plans[0]) {\n const col = Math.floor((plans[0].seg.horzpos + 1) / (ctx.cols.w + ctx.cols.gap))\n ax = ox + col * (ctx.cols.w + ctx.cols.gap); aw = ctx.cols.w\n }\n // 어울림(SQUARE) 개체 위 = max(문단 위 + vertOffset, 앵커 줄 위) — reflow 의 zoneStart 와 같은 규칙\n let anchorLineV: number | undefined\n let anchorLineH = 0\n let anchorSeg: Seg | undefined\n let anchorK = -1\n plans.forEach((pl, k) => { if (pl.start <= o.index) { anchorLineV = pl.seg.vertpos; anchorLineH = pl.seg.textheight; anchorSeg = pl.seg; anchorK = k } })\n // 첫 줄이 개체 아래로 밀려 저장된 문단(줄이 문단 영역 위 + 위 간격보다 아래) — 글을 밀지 않는 개체는 문단 시작 기준\n let objBaseV = baseV\n const pTop = depth === 0 ? ctx.paraTops?.get(p) : undefined\n const wrapA = o.el.getAttribute(\"textWrap\") ?? \"TOP_AND_BOTTOM\"\n const top0 = pTop ?? (depth > 0 && wrapA !== \"TOP_AND_BOTTOM\" ? cellParaTop(p, ctx.styles.paraGeom) : undefined)\n if (top0 !== undefined && wrapA !== \"TOP_AND_BOTTOM\") {\n const start = top0 + (m.paraPrId != null ? ctx.styles.paraGeom.get(m.paraPrId)?.spaceBefore ?? 0 : 0)\n if (baseV > start + 100) { objBaseV = start; if (anchorLineV === baseV) anchorLineV = start }\n // 칸 안 문단의 글 뒤·앞·어울림 개체는 위 간격 앞(칸 안 문단 영역 위)이 원점이다(같은 판 한컴 PDF: 위 간격 500 칸 문단의 vertOffset 0 글 뒤 그림이 줄보다 5pt 위)\n else if (depth > 0 && start > top0 && Math.abs(baseV - start) <= 100) { objBaseV = top0; if (anchorLineV === baseV) anchorLineV = top0 }\n }\n const tbFloats = m.objs.filter(q => !q.inline && (q.el.getAttribute(\"textWrap\") ?? \"TOP_AND_BOTTOM\") === \"TOP_AND_BOTTOM\" && (findChildByLocalName(q.el, \"pos\")?.getAttribute(\"vertRelTo\") ?? \"PARA\") === \"PARA\").length\n let stay = tbFloats < 2 && !m.objs.some(q => q.inline) && !m.chars.some(c => c.ch !== \"\" && !c.nb && c.ch.trim() !== \"\")\n // 제자리 줄 문단의 개체는 문단 영역 위(위 간격 앞)에 놓인다 — reflow 와 같다(한컴 PDF: 위 간격 1000 문단의 표가 줄보다 10pt 위)\n const sbA = m.paraPrId != null ? ctx.styles.paraGeom.get(m.paraPrId)?.spaceBefore ?? 0 : 0\n // 줄이 개체만큼 밀려 저장됐으면 제자리가 아니다 — 줄 자리에 두면 그림이 쪽 밖으로 밀려났다\n // 칸 안 문단은 칸 안 앞 문단 끝과 견준다(한컴 PDF: 칸 안 빈 문단 줄 31301 = 앞 문단 끝 7920 + 바깥 여백 + 표 23099 — 표는 줄 위)\n if (stay && wrapA === \"TOP_AND_BOTTOM\" && linePushedBy(o, anchorLineV ?? baseV, pTop ?? (depth > 0 ? cellParaTop(p, ctx.styles.paraGeom) : undefined))) stay = false\n // 앵커 줄이 다음 쪽 첫 줄로 넘어간 문단의 위아래 개체는 앞 쪽, 그 줄이 앞 쪽에 이어졌을 자리(앞 줄 끝 + 줄 간격)에 남는다\n // (한컴 PDF: 인라인 표 줄 64153 뒤 둘째 줄(저장 vertpos 0, 다음 쪽)에 앵커한 글상자가 앞 쪽 표 줄 아래 — 다음 쪽 줄 자리를 앞 쪽에 쓰면 쪽 맨 위)\n let carried: number | undefined\n if (segPages && anchorK > 0 && segPages[anchorK] !== segPages[0] && segPages[anchorK - 1] === segPages[0] && wrapA === \"TOP_AND_BOTTOM\" &&\n (findChildByLocalName(o.el, \"pos\")?.getAttribute(\"vertRelTo\") ?? \"PARA\") === \"PARA\") {\n const s0 = plans[anchorK - 1].seg\n carried = s0.vertpos + s0.textheight + (s0.spacing ?? 0)\n }\n const firstLine = anchorLineV === undefined || anchorLineV === baseV\n let { x, y } = anchorObject(o, ax, oy, objBaseV, aw, ctx, anchorLineV, stay ? sbA : false, (firstLine || wrapA === \"SQUARE\") && pTop !== undefined && pTop < baseV ? pTop : undefined, anchorLineH, firstLine ? sbA : 0,\n // 문단 중간 글자 앵커인데 첫 줄부터 앵커 줄만큼 좁게 저장됐으면 개체는 문단 위에 있다(같은 판 한컴 PDF: 둘째 줄 앵커 사진, 네 줄 모두 34602)\n m.chars.slice(o.index).some(c => c.ch.trim() !== \"\") && !!anchorSeg && plans.length > 0 && plans[0].seg !== anchorSeg &&\n Math.abs(plans[0].seg.horzsize - anchorSeg.horzsize) <= 100 && anchorSeg.horzpos + anchorSeg.horzsize < aw - 1000 ? \"top\" : m.chars.slice(o.index).some(c => c.ch.trim() !== \"\") ? \"mid\" : \"end\")\n if (carried !== undefined) {\n const posC = findChildByLocalName(o.el, \"pos\"), rawC = num(posC, \"vertOffset\")\n y = oy + carried + num(findChildByLocalName(o.el, \"outMargin\"), \"top\") + Math.max(0, rawC >= 2 ** 31 ? rawC - 2 ** 32 : rawC)\n }\n // 같은 문단의 위아래 배치 개체 둘 이상은 문단 영역 위부터 겹치지 않고 차례로 쌓인다 — reflow 와 같은 규칙\n // (한컴 PDF: 보도자료 머리 표 셋 3481·2797·12846 이 쪽 위부터 차례로, 첫 줄 20822 는 그 아래)\n // 칸 안 문단도 같다 — 문단 위는 칸 안 앞 문단 끝(같은 판 한컴 PDF: 칸 첫 문단의 vertOffset 2072·6986·17070 표 셋이 칸 위부터 그 자리에)\n let stackTop = depth === 0 ? pTop ?? 0 : cellParaTop(p, ctx.styles.paraGeom)\n if (tbFloats >= 2 && wrapA === \"TOP_AND_BOTTOM\" && stackTop !== undefined) {\n if (!tbStack) {\n // 문서 순서(앵커 글자 순)로 쌓는다 — 개체 목록은 그리는 순서일 수 있다. 겹침 허용(allowOverlap=1) 개체는 쌓지 않는다\n // (한컴 PDF: 겹침 허용 글상자 둘은 같은 자리에 겹친다)\n tbStack = new Map()\n // 가로로 겹치는 앞 개체 아래로만 쌓는다 — 옆에 나란한 개체(가로 오프셋 24181, 세로 −1630)는 제 오프셋 자리\n const placed: { x0: number; x1: number; bottom: number }[] = []\n const stackable = m.objs.filter(q => !q.inline && (q.el.getAttribute(\"textWrap\") ?? \"TOP_AND_BOTTOM\") === \"TOP_AND_BOTTOM\" && (findChildByLocalName(q.el, \"pos\")?.getAttribute(\"vertRelTo\") ?? \"PARA\") === \"PARA\" && findChildByLocalName(q.el, \"pos\")?.getAttribute(\"allowOverlap\") !== \"1\")\n for (const q of stackable.length >= 2 ? stackable.sort((a, b) => a.index - b.index) : []) {\n const posQ = findChildByLocalName(q.el, \"pos\"), omQ = findChildByLocalName(q.el, \"outMargin\"), raw = num(posQ, \"vertOffset\")\n const x0 = num(posQ, \"horzOffset\"), x1 = x0 + num(omQ, \"left\") + q.width + num(omQ, \"right\")\n const below = Math.max(0, ...placed.filter(r => r.x0 < x1 && x0 < r.x1).map(r => r.bottom))\n // 칸 안에선 위로 올린 오프셋이 문단 위에서 멈춘다(anchorObject 와 같다)\n const top = Math.max(below, depth > 0 ? Math.max(0, raw) : raw)\n tbStack.set(q.el, top + num(omQ, \"top\"))\n placed.push({ x0, x1, bottom: top + num(omQ, \"top\") + (q.tag === \"tbl\" ? Math.max(q.height, measureTableHeight(q.el, ctx.extentMemo)) : q.height) + num(omQ, \"bottom\") })\n }\n // 칸 안: 줄이 쌓은 개체 아래로 밀려 저장됐으면 문단 위 = 줄 − 쌓은 높이 — 앞 문단의 떠 있는 표가 칸 안 앞 문단 끝보다 아래로 뻗었다\n // (같은 판 PDF: 앞 문단 끝 1600, 줄 4532 − 쌓은 1700 = 2832 에 두 표)\n if (depth > 0 && placed.length) tbStackTop = Math.max(stackTop, baseV - Math.max(...placed.map(r => r.bottom)))\n }\n if (depth > 0 && tbStackTop !== undefined) stackTop = tbStackTop\n const st = tbStack.get(o.el)\n if (st !== undefined) y = oy + stackTop + st\n }\n const moved = ctx.objPlace?.get(o.el)\n if (moved) {\n const pg = ctx.page\n ctx.page = moved.page\n drawObject(o, x, moved.y, baseV, areaW, ctx, depth)\n ctx.page = pg\n } else drawObject(o, x, y, baseV, areaW, ctx, depth)\n }\n }\n if (paraRegionId) ctx.parentStack.pop()\n}\n\n/** hp:pos 기준계 해석 → 개체 좌상단 절대좌표 (tac=0) */\n/** 칸 안 문단의 영역 위 — 앞 문단 끝 줄(vertpos + 높이 + 간격) + 앞 문단 아래 간격, 첫 문단은 0. 앞 문단 줄이 없으면 모른다.\n * 글을 밀지 않는 개체가 첫 줄을 덮어 줄이 개체 아래로 저장된 칸 문단도 개체는 문단 위 기준이다(한컴 PDF: 칸 안 글 뒤 앵커 그림 −80 이 칸 위에, 글 줄 2551 은 그 아래) */\nexport function cellParaTop(p: Element, geom: RenderStyles[\"paraGeom\"]): number | undefined {\n let prev = p.previousSibling as Element | null\n while (prev && ln(prev) !== \"p\") prev = prev.previousSibling as Element | null\n if (!prev) return 0\n const lsa = findChildByLocalName(prev, \"linesegarray\")\n const segs = lsa ? elements(lsa).filter(e => ln(e) === \"lineseg\") : []\n if (!segs.length) return undefined\n const last = segs[segs.length - 1]\n return num(last, \"vertpos\") + num(last, \"vertsize\") + num(last, \"spacing\") + (geom.get(prev.getAttribute(\"paraPrIDRef\") ?? \"\")?.spaceAfter ?? 0)\n}\n\n\nfunction drawObject(o: ParaObj, x: number, y: number, baseV: number, areaW: number, ctx: Ctx, depth: number): void {\n if (!o.inline && depth === 0 && ctx.paintJobs) {\n const wrap = o.el.getAttribute(\"textWrap\")\n const layer = wrap === \"BEHIND_TEXT\" ? -1 : wrap === \"IN_FRONT_OF_TEXT\" ? 1 : 0\n const page = ctx.page, parents = [...ctx.parentStack]\n ctx.paintJobs.push({ page, layer, z: num(o.el, \"zOrder\"), body: !!ctx.bodyDx, draw: () => {\n ctx.page = page\n const saved = ctx.parentStack\n ctx.parentStack = parents\n drawObject(o, x, y, baseV, areaW, ctx, depth)\n ctx.parentStack = saved\n } })\n return\n }\n // 캡션 — 위 캡션은 개체를 캡션 높이 + 간격만큼 내리고, 아래 캡션은 개체 바닥 + 간격에, 왼쪽·오른쪽은 옆에 그린다\n const cap = o.tag === \"tbl\" || o.tag === \"pic\" ? captionOf(o.el) : null\n if (cap) {\n const objH = o.tag === \"tbl\" ? Math.max(o.height, measureTableHeight(o.el, ctx.extentMemo)) : o.height\n let ox = x, oy = y, cx = x, cy = y\n if (cap.side === \"TOP\") oy = y + cap.h + cap.gap\n else if (cap.side === \"LEFT\") ox = x + cap.width + cap.gap\n else if (cap.side === \"RIGHT\") cx = x + o.width + cap.gap\n else cy = y + objH + cap.gap\n for (const cp of elements(cap.sub)) if (ln(cp) === \"p\") drawPara(cp, cx, cy, cap.width, ctx, depth + 1)\n x = ox; y = oy\n }\n if (o.tag === \"tbl\") ctx.draw.table(o.el, x, y, ctx, depth + 1)\n else if (o.tag === \"pic\") ctx.draw.pic(o.el, x, y, ctx)\n else if (o.tag === \"container\") {\n if (drawGroupByMatrix(o, x, y, baseV, areaW, ctx, depth)) return\n // 그리기개체 묶음(행렬 없음 — HWP5 장면) — 자식 개체를 컨테이너 원점 기준으로 재귀 배치\n for (const ch of elements(o.el)) {\n const tag = ln(ch)\n if (!OBJ_TAGS.has(tag)) continue\n const sz = findChildByLocalName(ch, \"sz\")\n const off = findChildByLocalName(ch, \"offset\")\n const sub: ParaObj = { el: ch, tag, index: 0, inline: true, width: num(sz, \"width\"), height: num(sz, \"height\"), omL: 0, omR: 0 }\n drawObject(sub, x + num(off, \"x\"), y + num(off, \"y\"), baseV, areaW, ctx, depth + 1)\n }\n } else if (o.tag === \"equation\") {\n // 수식 — 수식 조판 대신 스크립트를 한 줄 유니코드 글(a/b·√·첨자)로 상자 폭에 맞춰 그린다. 기준선 = 상자 위 + 높이 × baseLine%\n const script = findChildByLocalName(o.el, \"script\")?.textContent ?? \"\"\n const text = script ? latexToPlain(hwpEquationToLatex(script)) : \"\"\n if (text && o.width > 0) {\n const bl = Number(o.el.getAttribute(\"baseLine\")), size = num(o.el, \"baseUnit\", 1000)\n const by = y + Math.round(o.height * (Number.isFinite(bl) && bl > 0 ? bl / 100 : 0.85))\n const color = o.el.getAttribute(\"textColor\")\n const attrs = [`x=\"${pt(x)}\"`, `y=\"${pt(by)}\"`, `font-size=\"${pt(size)}\"`, `font-family=\"'Times New Roman','HCR Batang','Noto Serif KR',serif\"`]\n if ([...text].length > 1) attrs.push(`textLength=\"${pt(o.width)}\"`, `lengthAdjust=\"spacingAndGlyphs\"`)\n if (color && color !== \"#000000\") attrs.push(`fill=\"${escapeXml(color)}\"`)\n emit(ctx, `<text ${attrs.join(\" \")}>${escapeXml(text)}</text>`)\n ctx.stats.texts++\n }\n } else if (SHAPE_TAGS.has(o.tag)) {\n drawShape(o, x, y, ctx, depth)\n } else if (!FORM_TAGS.has(o.tag)) {\n // 양식 컨트롤(체크 상자 등)은 줄에서 자리만 차지하고 그리지 않는다(종전과 같이)\n warnOnce(ctx, `shape:${o.tag}`, `개체(${o.tag}) 렌더 미지원 — 생략`)\n }\n}\n\n/**\n * 묶음(hp:container) — 안쪽 개체마다 renderingInfo 행렬로 원본 좌표를 최상위 묶음 상자에 놓는다(배율·회전·중첩 묶음 한 번에).\n * 최상위 묶음 자기 행렬이 그리는 상자를 묶음 자리(x, y)에 맞춘다. 종전엔 offset 만 더해 배율 묶음(지도·도식)의 그림이 작게,\n * 곡선·도형이 엉뚱한 자리에 크게 그려졌다(#116). 행렬 없는 묶음(HWP5 장면)은 false — 종전 offset 경로\n */\nfunction drawGroupByMatrix(o: ParaObj, x: number, y: number, baseV: number, areaW: number, ctx: Ctx, depth: number): boolean {\n const top = renderingMatrix(o.el)\n const leaves: Element[] = []\n const collect = (el: Element): boolean => {\n for (const ch of elements(el)) {\n const tag = ln(ch)\n if (!OBJ_TAGS.has(tag)) continue\n if (tag === \"container\") { if (!collect(ch)) return false }\n else if (renderingMatrix(ch)) leaves.push(ch)\n else return false\n }\n return true\n }\n if (!top || !collect(o.el)) return false\n const org = findChildByLocalName(o.el, \"orgSz\")\n const box = rotatedBounds({ x: 0, y: 0, w: num(org, \"width\"), h: num(org, \"height\") }, [top])\n const base: Affine = [1, 0, 0, 1, x - box.x, y - box.y]\n for (const leaf of leaves) {\n const m = mulAffine(base, renderingMatrix(leaf)!)\n const tag = ln(leaf), lorg = findChildByLocalName(leaf, \"orgSz\")\n const w = num(lorg, \"width\") || num(findChildByLocalName(leaf, \"curSz\"), \"width\")\n const h = num(lorg, \"height\") || num(findChildByLocalName(leaf, \"curSz\"), \"height\")\n ctx.regionRotations.push(m)\n emit(ctx, `<g transform=\"matrix(${m.slice(0, 4).map(v => Math.round(v * 1e6) / 1e6).join(\" \")} ${pt(m[4])} ${pt(m[5])})\">`)\n const sub: ParaObj = { el: leaf, tag, index: 0, inline: true, width: w, height: h, omL: 0, omR: 0 }\n if (tag === \"pic\") ctx.draw.picFrame(leaf, 0, 0, w, h, \"\", ctx)\n else if (SHAPE_TAGS.has(tag)) drawShape(sub, 0, 0, ctx, depth + 1, [Math.hypot(m[0], m[1]) || 1, Math.hypot(m[2], m[3]) || 1])\n else drawObject(sub, 0, 0, baseV, areaW, ctx, depth + 1)\n emit(ctx, \"</g>\")\n ctx.regionRotations.pop()\n }\n return true\n}\n\n// ─── 그리기 도형 ───────────────────────────────────\n/** groupScale — 묶음 행렬 안에서 원본 좌표로 그릴 때 그 행렬의 가로·세로 배율. 글상자 글은 배율을 되돌려 그린다(아래) */\nfunction drawShape(o: ParaObj, x: number, y: number, ctx: Ctx, depth: number, groupScale?: [number, number]): void {\n const geometry = shapeGeometry(o, x, y, ctx.defs, ctx.images, (key, msg) => warnOnce(ctx, key, msg), !!groupScale)\n // Transform original corners through every ancestor and this shape's rotation\n // before bounding once. An intermediate axis-aligned box inflates nested crops.\n const b = geometry\n if (geometry.rotation) ctx.regionRotations.push(geometry.rotation)\n ctx.stats.shapes++\n const shapeId = ctx.regions.add(\"shape\", bboxOf(ctx, b.x, b.y, b.w, b.h), { parentId: parentId(ctx) })\n emit(ctx, regionOpenTag(shapeId, \"shape\", pageNo(ctx)))\n ctx.parentStack.push(shapeId)\n if (geometry.transform) emit(ctx, `<g transform=\"${geometry.transform}\">`)\n emit(ctx, geometry.svg)\n const dt = findChildByLocalName(o.el, \"drawText\")\n const sub = dt ? findChildByLocalName(dt, \"subList\") : null\n // 글은 틀 자리(돌린 도형은 외접 상자 안으로 옮긴 틀, objectGeometry)에서. 묶음 안 도형은 글 줄 배치(lineseg)가 이미 배율 뒤\n // 단위라 행렬의 배율만 되돌린다 — 글자는 늘어나지 않고 회전만 따른다 (한컴: 묶음 크기를 바꿔도 글자 크기는 그대로)\n if (sub) {\n const [sx, sy] = groupScale ?? [1, 1]\n const unscale = sx !== 1 || sy !== 1\n if (unscale) { emit(ctx, `<g transform=\"scale(${1 / sx} ${1 / sy})\">`); ctx.regionRotations.push([1 / sx, 0, 0, 1 / sy, 0, 0]) }\n // 글상자 안 여백(drawText textMargin) — 글은 틀 안쪽 여백만큼 들어간 자리에서(한컴 PDF: 여백 283 글상자의 로고 표 x = 틀 + 2.83pt)\n const tm = dt ? findChildByLocalName(dt, \"textMargin\") : null\n const mL = num(tm, \"left\"), mR = num(tm, \"right\"), mT = num(tm, \"top\"), mB = num(tm, \"bottom\")\n // 글상자 세로 정렬(subList vertAlign) — 칸과 같이 안쪽 높이에서 내용 높이를 뺀 나머지의 절반(가운데)·전부(아래)만큼 내린다\n // (한컴 PDF: 안쪽 6804 에 내용 5860 인 가운데 정렬 글상자의 글이 4.7pt 아래)\n const va = sub.getAttribute(\"vertAlign\") ?? \"TOP\"\n let yoff = 0\n // 떠 있는 개체가 든 글상자는 내용 높이를 잴 근거가 없어 맞추지 않는다(한컴 PDF: 떠 있는 안쪽 글상자를 품은 가운데 글상자가 제자리)\n const floats = elements(sub).some(q => ln(q) === \"p\" && buildPara(q).objs.some(ob => !ob.inline))\n if (!floats && (va === \"CENTER\" || va === \"BOTTOM\")) {\n const extent = cellContentExtent({ el: dt!, ca: 0, ra: 0, cs: 1, rs: 1, w: 0, h: 0, bfId: null, sub, marginL: 0, marginR: 0, marginT: 0, marginB: 0 }, ctx.extentMemo)\n const free = geometry.h * sy - mT - mB - extent\n yoff = Math.max(0, va === \"CENTER\" ? free / 2 : free)\n }\n // 안 여백·세로 정렬 몫은 묶음 배율을 받지 않는다 — 배율을 되돌린 좌표에 그대로 더한다\n // (한컴 PDF: 세로 3.68배로 늘린 묶음 글상자의 글이 안 위 여백 283 만큼만 아래, 배율을 곱하면 7.8pt 더 내려갔다)\n for (const p of elements(sub)) if (ln(p) === \"p\") drawPara(p, geometry.x * sx + mL, geometry.y * sy + mT + yoff, geometry.w * sx - mL - mR, ctx, depth + 1)\n if (unscale) { ctx.regionRotations.pop(); emit(ctx, \"</g>\") }\n }\n if (geometry.rotation) ctx.regionRotations.pop()\n if (geometry.transform) emit(ctx, \"</g>\")\n ctx.parentStack.pop()\n emit(ctx, \"</g>\")\n}\n","/** HWP 5.x 레코드 리더, UTF-16LE 텍스트 추출, 스트림 압축해제 */\n\nimport type { ScriptKind } from \"../script-tags.js\"\nimport { inflateRawSync, inflateSync } from \"zlib\"\nimport { KordocError } from \"../utils.js\"\nimport { TOC_LEADER } from \"../toc-entry.js\"\nimport type { Edges } from \"../table/layout-frames.js\"\n\n// ─── 레코드 태그 상수 ────────────────────────────────\n\nexport const TAG_PARA_HEADER = 0x0042\nexport const TAG_PARA_TEXT = 0x0043\nexport const TAG_CHAR_SHAPE = 0x0044\nexport const TAG_PARA_SHAPE = 0x0045\n/** 0x45의 스펙상 정체 — 본문 문단의 줄 조판 정보(HWPTAG_BEGIN+53). TAG_PARA_SHAPE는 역사적 오명 */\nexport const TAG_PARA_LINE_SEG = 0x0045\nexport const TAG_CTRL_HEADER = 0x0047\nexport const TAG_LIST_HEADER = 0x0048\nexport const TAG_TABLE = 0x004d\nexport const TAG_SHAPE_COMPONENT = 0x004c // HWPTAG_BEGIN + 60\nexport const TAG_SHAPE_COMPONENT_PICTURE = 0x0055 // HWPTAG_BEGIN + 69\nexport const TAG_SHAPE_COMPONENT_CONTAINER = 0x0056 // HWPTAG_BEGIN + 70\nexport const TAG_CTRL_DATA = 0x0057 // HWPTAG_BEGIN + 71\nexport const TAG_EQEDIT = 0x0058\n\n// DocInfo 태그 (스타일 정보 해석용) — HWPTAG_BEGIN(0x0010) 기준\nexport const TAG_ID_MAPPINGS = 0x0011 // HWPTAG_BEGIN + 1\nexport const TAG_BORDER_FILL = 0x0014 // HWPTAG_BEGIN + 4\nexport const TAG_BIN_DATA = 0x0012 // HWPTAG_BEGIN + 2\nexport const TAG_FACE_NAME = 0x0013 // HWPTAG_BEGIN + 3\nexport const TAG_DOC_CHAR_SHAPE = 0x0015 // HWPTAG_BEGIN + 5\nexport const TAG_NUMBERING = 0x0017 // HWPTAG_BEGIN + 7\nexport const TAG_BULLET = 0x0018 // HWPTAG_BEGIN + 8\nexport const TAG_DOC_PARA_SHAPE = 0x0019 // HWPTAG_BEGIN + 9\nexport const TAG_DOC_STYLE = 0x001a // HWPTAG_BEGIN + 10\n\n// 특수 문자 코드 (UTF-16LE) — HWP 5.0 바이너리 스펙 + rhwp 검증\n// 3가지 카테고리: char(2바이트), inline(16바이트), extended(16바이트)\n// char: 0, 13, 24-31 — 제어문자만, 확장 데이터 없음\n// inline: 4-9, 19-20 — 제어문자(2) + 확장(14) = 16바이트\n// extended: 1-3, 10-12, 14-18, 21-23 — 제어문자(2) + 확장(14) = 16바이트\nconst CHAR_LINE = 0x0000 // char: 줄바꿈\nconst CHAR_SECTION_BREAK = 0x000a // char: 강제 줄 나눔(line break, 2바이트). 구역/단 정의는 코드2(extended)라 혼동 주의\nconst CHAR_PARA = 0x000d // char: 문단 끝\nconst CHAR_TAB = 0x0009 // inline: 탭\nconst CHAR_HYPHEN = 0x0018 // char: 하이픈 (스펙 코드 24 — pyhwp HYPHEN, hwp3 SIMPLE_CTRL 24/25와 동일)\nconst CHAR_NBSP = 0x001e // char: 묶음 빈칸(비분리 공백, 스펙 코드 30 — pyhwp NONBREAK_SPACE)\nconst CHAR_FIXED_WIDTH = 0x001f // char: 고정폭 빈칸 (스펙 코드 31 — pyhwp FIXWIDTH_SPACE). 25~29(0x19~0x1d)는 예약\n\n// FileHeader 플래그\nexport const FLAG_COMPRESSED = 1 << 0\nexport const FLAG_ENCRYPTED = 1 << 1\nexport const FLAG_DISTRIBUTION = 1 << 2\nexport const FLAG_DRM = 1 << 4\n/** 변경 내용 추적 문서 — 한컴은 이 비트가 서 있으면 BodyText(지금 내용)가 아니라 ViewText(지운 글까지 표시한 사본)를 그린다 */\nexport const FLAG_TRACK_CHANGES = 1 << 14\n\n// ─── 레코드 구조 ─────────────────────────────────────\n\nexport interface HwpRecord {\n tagId: number\n level: number\n size: number\n data: Buffer\n}\n\nexport interface HwpFileHeader {\n signature: string\n versionMajor: number\n flags: number\n}\n\n// ─── 레코드 리더 ─────────────────────────────────────\n\n/** 최대 레코드 수 — 비정상 파일에 의한 메모리 폭주 방지 */\nconst MAX_RECORDS = 500_000\n\nexport function readRecords(data: Buffer): HwpRecord[] {\n const records: HwpRecord[] = []\n let offset = 0\n\n while (offset + 4 <= data.length && records.length < MAX_RECORDS) {\n const header = data.readUInt32LE(offset)\n offset += 4\n\n const tagId = header & 0x3ff\n const level = (header >> 10) & 0x3ff\n let size = (header >> 20) & 0xfff\n\n // 확장 크기\n if (size === 0xfff) {\n if (offset + 4 > data.length) break\n size = data.readUInt32LE(offset)\n offset += 4\n }\n\n if (offset + size > data.length) break\n records.push({ tagId, level, size, data: data.subarray(offset, offset + size) })\n offset += size\n }\n\n return records\n}\n\n// ─── 스트림 압축 해제 ────────────────────────────────\n\n/** 압축 해제 최대 크기 (100MB) — decompression bomb 방지 */\nconst MAX_DECOMPRESS_SIZE = 100 * 1024 * 1024\n\nexport function decompressStream(data: Buffer): Buffer {\n const opts = { maxOutputLength: MAX_DECOMPRESS_SIZE }\n if (data.length >= 2 && data[0] === 0x78) {\n try { return inflateSync(data, opts) } catch { /* fallback to raw */ }\n }\n return inflateRawSync(data, opts)\n}\n\n// ─── FileHeader 파싱 ─────────────────────────────────\n\nexport function parseFileHeader(data: Buffer): HwpFileHeader {\n if (data.length < 40) throw new KordocError(\"FileHeader가 너무 짧습니다 (최소 40바이트)\")\n const sig = data.subarray(0, 32).toString(\"utf8\").replace(/\\0+$/, \"\")\n return {\n signature: sig,\n versionMajor: data[35],\n flags: data.readUInt32LE(36),\n }\n}\n\n// ─── 스타일 정보 구조 ────────────────────────────────\n\n/** DocInfo에서 추출한 문단 모양 (PARA_SHAPE) */\nexport interface HwpParaShape {\n /** 문단 머리 종류 (attr1 bits 23-24): 0=없음, 1=개요, 2=번호, 3=글머리표 */\n headType: number\n /** 문단 수준 (attr1 bits 25-27): 0-6 → 1-7수준 */\n paraLevel: number\n /** 번호/글머리표 ID (1-based) — headType=2면 numbering, 3이면 bullet 인덱스 */\n numberingId: number\n}\n\n/** DocInfo BIN_DATA 항목 — binDataId(1-based 레코드 순서) → BinData 스토리지 매핑 */\nexport interface HwpBinDataItem {\n /** 0=link(외부 파일), 1=embedding, 2=storage */\n kind: \"link\" | \"embed\" | \"storage\"\n /** BinData 스토리지 엔트리 번호 — 스트림명 \"BIN%04X.ext\" (16진) */\n storageId: number\n /** 확장자 (예: \"jpg\") */\n extension: string\n}\n\n/** DocInfo NUMBERING — 문단 번호 정의 (7수준) */\nexport interface HwpNumbering {\n /** 수준별(0-6) 번호 형식 문자열 (예: \"^1.\") — ^N은 N수준 번호로 치환 */\n levelFormats: string[]\n /** 수준별 번호 모양 코드 (HWP 표 43: 0=숫자, 1=원숫자, 8=가나다, 12=일이삼, 13=一二三 등) */\n numberFormats: number[]\n /** 수준별 시작 번호 (5.0.2.5+, 기본 1) */\n startNumbers: number[]\n}\n\n/** DocInfo BULLET — 글머리표 문자 */\nexport interface HwpBullet {\n /** 글머리표 문자 (PUA 가능 — 출력 시 mapPuaText로 정규화됨), U+FFFF=이미지 글머리표 */\n char: string\n}\n\n/** DocInfo에서 추출한 글자 모양 (CHAR_SHAPE) */\nexport interface HwpCharShape {\n /** 글꼴 크기 (단위: 0.1pt, 예: 100 = 10pt) */\n fontSize: number\n /**\n * 속성 플래그 (HWP5 바이너리 스펙 1.1 기준):\n * bit 0 = italic, bit 1 = bold, bit 2 = underline, bit 3 = outline\n * 검증 완료: 공식 스펙 + pyhwp/hwp.js 등 오픈소스 파서와 일치 (v1.7)\n */\n attrFlags: number\n}\n\n/** DocInfo에서 추출한 스타일 */\nexport interface HwpStyle {\n name: string\n /** 한글 이름 (UTF-16LE) */\n nameKo: string\n /** 연결된 charShape 인덱스 */\n charShapeId: number\n /** 연결된 paraShape 인덱스 */\n paraShapeId: number\n /** 스타일 타입: 0=paragraph, 1=character */\n type: number\n}\n\n/** DocInfo 파싱 결과 */\nexport interface HwpDocInfo {\n charShapes: HwpCharShape[]\n paraShapes: HwpParaShape[]\n styles: HwpStyle[]\n /** BIN_DATA 항목 (1-based binDataId → binData[id-1]) */\n binData: HwpBinDataItem[]\n /** NUMBERING 정의 (1-based numberingId → numberings[id-1]) */\n numberings: HwpNumbering[]\n /** BULLET 정의 (1-based bulletId → bullets[id-1]) */\n bullets: HwpBullet[]\n /** BORDER_FILL 의 보이는 변 (1-based borderFillId → borderEdges[id-1]) — 보이지 않는 틀 표 풀기 (v4.17.0) */\n borderEdges: Edges[]\n}\n\n/** length-prefixed UTF-16LE 문자열 읽기 (HWP WCHAR 배열) */\nfunction readHwpString(data: Buffer, offset: number): { value: string; next: number } {\n if (offset + 2 > data.length) return { value: \"\", next: data.length }\n const len = data.readUInt16LE(offset)\n const start = offset + 2\n const end = start + len * 2\n if (len === 0 || end > data.length) return { value: \"\", next: start }\n return { value: data.subarray(start, end).toString(\"utf16le\"), next: end }\n}\n\n/** DocInfo 레코드들에서 스타일 정보 추출 */\nexport function parseDocInfo(records: HwpRecord[]): HwpDocInfo {\n const charShapes: HwpCharShape[] = []\n const paraShapes: HwpParaShape[] = []\n const styles: HwpStyle[] = []\n const binData: HwpBinDataItem[] = []\n const numberings: HwpNumbering[] = []\n const bullets: HwpBullet[] = []\n const borderEdges: Edges[] = []\n\n for (const rec of records) {\n // BORDER_FILL — 속성 u16@0 · 변 4개(왼/오/위/아래) @2+6k = 종류 u8(0 없음) · 굵기 u8 · COLORREF u32 (render/hwp5-scene 과 같은 해독).\n // 흰 선(0xFFFFFF)은 흰 바탕에 안 보인다\n if (rec.tagId === TAG_BORDER_FILL) {\n const seen = (k: number): boolean => {\n const o = 2 + 6 * k\n return rec.data.length >= o + 6 && rec.data[o] !== 0 && (rec.data.readUInt32LE(o + 2) & 0xffffff) !== 0xffffff\n }\n borderEdges.push({ l: seen(0), r: seen(1), t: seen(2), b: seen(3) })\n }\n\n // PARA_SHAPE — 문단 모양 (rhwp doc_info.rs parse_para_shape)\n // attr1(u32@0) 비트 팩: bits 23-24 = 머리 종류, bits 25-27 = 문단 수준\n // numberingId: u16@30 (attr1 4 + 여백/간격 i32*6 = 24 + tabDefId 2 → offset 30)\n if (rec.tagId === TAG_DOC_PARA_SHAPE && rec.data.length >= 4) {\n const attr1 = rec.data.readUInt32LE(0)\n const headType = (attr1 >>> 23) & 0x03\n const paraLevel = (attr1 >>> 25) & 0x07\n const numberingId = rec.data.length >= 32 ? rec.data.readUInt16LE(30) : 0\n paraShapes.push({ headType, paraLevel, numberingId })\n }\n\n // BIN_DATA — binDataId(레코드 순서 1-based) → 스토리지 ID(16진)/확장자 매핑\n // (rhwp doc_info.rs parse_bin_data: attr u16 → type/compression/status)\n if (rec.tagId === TAG_BIN_DATA && rec.data.length >= 2) {\n const attr = rec.data.readUInt16LE(0)\n const typeBits = attr & 0x000f\n if (typeBits === 0) {\n // link: absPath + relPath (외부 파일 — 스토리지 없음)\n binData.push({ kind: \"link\", storageId: 0, extension: \"\" })\n } else {\n const storageId = rec.data.length >= 4 ? rec.data.readUInt16LE(2) : 0\n const { value: extension } = readHwpString(rec.data, 4)\n binData.push({ kind: typeBits === 2 ? \"storage\" : \"embed\", storageId, extension })\n }\n }\n\n // NUMBERING — 문단 번호 정의 (rhwp doc_info.rs parse_numbering, HWP 표 40/41)\n if (rec.tagId === TAG_NUMBERING && rec.data.length >= 14) {\n const levelFormats: string[] = []\n const numberFormats: number[] = []\n const startNumbers: number[] = [1, 1, 1, 1, 1, 1, 1]\n let offset = 0\n for (let level = 0; level < 7; level++) {\n if (offset + 12 > rec.data.length) {\n levelFormats.push(\"\")\n numberFormats.push(0)\n continue\n }\n // 문단 머리 정보(12B): attr(u32) + widthAdjust(i16) + textDistance(i16) + charShapeId(u32)\n const attr = rec.data.readUInt32LE(offset)\n numberFormats.push((attr >>> 5) & 0x0f)\n offset += 12\n // 번호 형식 문자열 (가변)\n const { value, next } = readHwpString(rec.data, offset)\n levelFormats.push(value)\n offset = next\n }\n // 시작 번호 (u16) + 수준별 시작 번호 (5.0.2.5+, u32×7)\n let baseStart = 1\n if (offset + 2 <= rec.data.length) {\n baseStart = rec.data.readUInt16LE(offset) || 1\n offset += 2\n }\n for (let level = 0; level < 7; level++) {\n if (offset + 4 <= rec.data.length) {\n startNumbers[level] = rec.data.readUInt32LE(offset) || 1\n offset += 4\n } else {\n startNumbers[level] = baseStart\n }\n }\n numberings.push({ levelFormats, numberFormats, startNumbers })\n }\n\n // BULLET — 글머리표 (rhwp doc_info.rs parse_bullet, HWP 표 44)\n // 머리 정보(12B) 다음 WCHAR가 글머리표 문자\n if (rec.tagId === TAG_BULLET && rec.data.length >= 14) {\n const code = rec.data.readUInt16LE(12)\n bullets.push({ char: code > 0 ? String.fromCharCode(code) : \"•\" })\n }\n\n if (rec.tagId === TAG_DOC_CHAR_SHAPE && rec.data.length >= 18) {\n // HWP5 CHAR_SHAPE 구조 (바이너리 스펙 1.1 기준):\n // faceId: 7개 언어 * u16 = 14바이트 (offset 0-13)\n // ratio: 7개 언어 * u8 = 7바이트 (offset 14-20)\n // spacing: 7개 언어 * s8 = 7바이트 (offset 21-27)\n // relSize: 7개 언어 * u8 = 7바이트 (offset 28-34)\n // charOffset: 7개 언어 * s8 = 7바이트 (offset 35-41)\n // baseSize: u32 at offset 42 (단위: 0.1pt)\n // attrFlags: u32 at offset 46 (bit0=italic, bit1=bold) — 공식 스펙 검증 완료\n if (rec.data.length >= 50) {\n const fontSize = rec.data.readUInt32LE(42) // 단위: 0.1pt\n const attrFlags = rec.data.readUInt32LE(46)\n charShapes.push({ fontSize, attrFlags })\n } else {\n // 짧은 레코드 — 스타일 정보 없음\n charShapes.push({ fontSize: 0, attrFlags: 0 })\n }\n }\n\n if (rec.tagId === TAG_DOC_STYLE && rec.data.length >= 8) {\n try {\n // STYLE 구조: nameLen(u16) + name(UTF-16LE) + nameKoLen(u16) + nameKo(UTF-16LE)\n // + type(u8) + nextStyleId(u16) + langId(s16) + paraShapeId(u16) + charShapeId(u16)\n let offset = 0\n const nameLen = rec.data.readUInt16LE(offset); offset += 2\n const nameBytes = nameLen * 2\n const name = nameBytes > 0 && offset + nameBytes <= rec.data.length\n ? rec.data.subarray(offset, offset + nameBytes).toString(\"utf16le\")\n : \"\"\n offset += nameBytes\n\n let nameKo = \"\"\n if (offset + 2 <= rec.data.length) {\n const nameKoLen = rec.data.readUInt16LE(offset); offset += 2\n const nameKoBytes = nameKoLen * 2\n if (nameKoBytes > 0 && offset + nameKoBytes <= rec.data.length) {\n nameKo = rec.data.subarray(offset, offset + nameKoBytes).toString(\"utf16le\")\n }\n offset += nameKoBytes\n }\n\n // type(u8) + nextStyleId(u8) + langId(s16) + paraShapeId(u16) + charShapeId(u16)\n // 주의: nextStyleId는 스펙상 BYTE — 2바이트 스킵하면 paraShapeId가 256배수로 깨짐 (off-by-one 버그 수정)\n const type = offset < rec.data.length ? rec.data.readUInt8(offset) : 0; offset += 1\n offset += 1 // nextStyleId (BYTE)\n offset += 2 // langId\n const paraShapeId = offset + 2 <= rec.data.length ? rec.data.readUInt16LE(offset) : 0; offset += 2\n const charShapeId = offset + 2 <= rec.data.length ? rec.data.readUInt16LE(offset) : 0\n\n styles.push({ name, nameKo, charShapeId, paraShapeId, type })\n } catch {\n // 파싱 실패 — 스킵\n }\n }\n }\n\n return { charShapes, paraShapes, styles, binData, numberings, bullets, borderEdges }\n}\n\n// ─── UTF-16LE 텍스트 추출 (21가지 제어문자 처리) ─────\n\nexport type InlineControlResolver = (ctrlId: string) => string | null | undefined\n\n/**\n * 확장 컨트롤(CTRL_HEADER 보유) 기반 인라인 치환 콜백.\n * - ctrlIdx: 문단 내 확장 컨트롤 등장 순서 (0-based, CTRL_HEADER 자식 레코드 순서와 1:1)\n * - ctrlId: u32 정규화 ID — 파일의 LE DWORD를 그대로 읽은 값 (\"tbl \" → 0x74626c20)\n * 인라인 컨트롤(4-9, 19-20 — CTRL_HEADER 없음)은 ctrlIdx = -1로 호출된다.\n */\nexport type IndexedControlResolver = (ctrlIdx: number, ctrlId: number) => string | null | undefined\n\n/** FIELD_BEGIN(0x03)/FIELD_END(0x04) 스택 페어링으로 복원한 필드 anchor 범위 */\nexport interface HwpFieldRange {\n /** state.text 기준 시작 인덱스 */\n start: number\n /** state.text 기준 끝 인덱스 (exclusive) */\n end: number\n /** FIELD_BEGIN 컨트롤의 확장 컨트롤 인덱스 (CTRL_HEADER 순서) */\n ctrlIdx: number\n}\n\n/** 문단 단위 PARA_TEXT 누적 상태 — 여러 PARA_TEXT 레코드에 걸친 컨트롤 인덱스/필드 스택 유지 */\nexport interface ParaTextState {\n text: string\n ctrlIdx: number\n fieldStack: Array<{ start: number; ctrlIdx: number }>\n fieldRanges: HwpFieldRange[]\n /** 레코드 끝 상위 서로게이트 반쪽과 □ 로 낸 자리 — 다음 레코드 첫 하위 반쪽과 한 글자로 되돌린다 */\n loneHigh?: number\n loneHighAt?: number\n /** 리터럴 \"$\"·\"<\" 를 LITERAL_DOLLAR_MARK·LITERAL_LT_MARK 한 글자로 — 본문 파서만 켠다. 필드 범위가 글자 위치라\n * 두 글자 \"\\$\" 를 바로 넣지 않고, 필드 처리 뒤 본문 파서가 \"\\$\" 로 바꾼다(escapeLiteralDollar 규약) */\n dollarMark?: boolean\n /** 채움 탭을 TOC_LEADER 표지로 — 본문 파서만 켜고 문단 글을 다 모은 뒤 takeTocLeaders 로 보통 탭이 된다 */\n tocLeaders?: boolean\n /** 글자 위치(문단 WCHAR 순번)의 첨자 종류 — 문단 글자 모양(PARA_CHAR_SHAPE) 위치표로 본문 파서가 채운다.\n * 있으면 첨자 글자를 <sup>·<sub> 로 감싼다(제어 문자·개체 자리에서는 닫는다) */\n scriptAt?: (pos: number) => ScriptKind | null\n /** 지금 열린 첨자 태그 */\n script?: ScriptKind | null\n /** 앞 PARA_TEXT 레코드까지의 WCHAR 수 — 글자 모양 위치는 문단 전체 기준 */\n wpos?: number\n}\n\n/** 리터럴 \"$\" 표지 (dollarMark) — 유니코드 비문자라 문서 글에 나오지 않는다 */\nexport const LITERAL_DOLLAR_MARK = \"\\uFDD0\"\n/** 리터럴 \"<\" 표지 (dollarMark 와 함께) — 첨자 태그(scriptAt)와 원문 글자 \"<sub>\" 를 가른다 (#122, escapeLiteralTags) */\nexport const LITERAL_LT_MARK = \"\\uFDD1\"\nconst LITERAL_LT_TAG = /\\uFDD1(?=\\/?(?:u|sup|sub)>)/g\n\n/** 필드 처리 뒤 리터럴 \"<\" 표지를 글로 — 태그 모양(\"<sub>\"·\"</sup>\"·\"<u>\")이면 \\<, 아니면 < (escapeLiteralTags 규약) */\nexport function resolveLiteralLt(text: string): string {\n return text.includes(LITERAL_LT_MARK) ? text.replace(LITERAL_LT_TAG, \"\\\\<\").replaceAll(LITERAL_LT_MARK, \"<\") : text\n}\n\nexport function createParaTextState(): ParaTextState {\n return { text: \"\", ctrlIdx: 0, fieldStack: [], fieldRanges: [] }\n}\n\nexport function extractText(data: Buffer): string {\n return extractTextWithControls(data)\n}\n\n/** 레거시 인터페이스 — ctrlId를 on-disk 바이트 순서 ASCII 문자열로 받는 resolver */\nexport function extractTextWithControls(data: Buffer, resolveControl?: InlineControlResolver): string {\n const state = createParaTextState()\n appendParaText(state, data, resolveControl\n ? (_idx, id) => resolveControl(ctrlIdToDiskAscii(id))\n : undefined)\n return state.text\n}\n\n/** u32 컨트롤 ID → on-disk 바이트 순서 ASCII (LE 저장이므로 역순 문자열, 예: 0x74626c20 → \" lbt\") */\nfunction ctrlIdToDiskAscii(id: number): string {\n return String.fromCharCode(id & 0xff, (id >>> 8) & 0xff, (id >>> 16) & 0xff, (id >>> 24) & 0xff)\n}\n\n/** 한컴 PUA-A 접힘 영역 — HWP5 WCHAR 의 U+A000~U+A48C(이 글자 음절) ↔ U+F0000~U+F048C. 관찰 범위만 (v4.12.2) */\nconst HANCOM_FOLDED_PUA_START = 0xa000\nconst HANCOM_FOLDED_PUA_END = 0xa48c\nconst HANCOM_FOLDED_PUA_SHIFT = 0xf0000 - 0xa000\n\n/** 확장 전용 컨트롤 문자 (CTRL_HEADER 자식 레코드 1개와 대응) — rhwp is_extended_only_ctrl_char */\nexport function isExtendedOnlyCtrlChar(ch: number): boolean {\n return (ch >= 1 && ch <= 3) || (ch >= 11 && ch <= 12) || (ch >= 14 && ch <= 18) || (ch >= 21 && ch <= 23)\n}\n\n/**\n * PARA_TEXT 레코드 1개를 상태에 누적.\n * 텍스트 추출 + 확장 컨트롤 인라인 치환 + FIELD_BEGIN/END 범위 추적을 동시에 수행한다.\n */\nexport function appendParaText(state: ParaTextState, data: Buffer, resolveControl?: IndexedControlResolver): void {\n let result = \"\"\n let i = 0\n const wbase = state.wpos ?? 0\n // 첨자 태그 전환 — 보이는 글자 앞에서 그 자리 글자 모양대로 열고, 제어 문자 앞에서는 닫는다\n const setScript = (want: ScriptKind | null): void => {\n const cur = state.script ?? null\n if (cur === want) return\n if (cur) result += `</${cur}>`\n if (want) result += `<${want}>`\n state.script = want\n }\n // 앞 레코드 끝의 상위 반쪽(□ 로 냈다)과 이 레코드 첫 하위 반쪽은 한 글자 — 문단 글이 여러 레코드로 나뉜 자리\n if (state.loneHighAt !== undefined) {\n const lo = data.length >= 2 ? data.readUInt16LE(0) : 0\n if (lo >= 0xdc00 && lo <= 0xdfff && state.loneHighAt === state.text.length - 1) {\n state.text = state.text.slice(0, -1) + String.fromCharCode(state.loneHigh!, lo)\n i = 2\n }\n state.loneHighAt = undefined\n }\n // 필드 범위는 state.text 기준 인덱스로 기록\n const base = state.text.length\n\n const resolveAt = (byteOffset: number, extended: boolean): void => {\n const ctrlId = data.readUInt32LE(byteOffset)\n const idx = extended ? state.ctrlIdx : -1\n const replacement = resolveControl?.(idx, ctrlId)\n if (replacement) result += replacement\n if (extended) state.ctrlIdx++\n }\n\n while (i + 1 < data.length) {\n const ch = data.readUInt16LE(i)\n if (state.scriptAt) setScript(ch >= 0x0020 ? state.scriptAt(wbase + i / 2) : null)\n i += 2\n\n switch (ch) {\n // ── char 타입 (2바이트만, 확장 데이터 없음) ──\n case CHAR_LINE: result += \"\\n\"; break\n case CHAR_SECTION_BREAK: { // 강제 줄 나눔(char 2바이트). 단, 뒤에 0x000b 수식 래퍼가 오는 경우만 확장 처리\n // 일부 HWP5 문서는 수식 placeholder를 0x000a + 0x000b + ctrlId + payload + 0x000b로 저장한다.\n if (i + 16 <= data.length && data.readUInt16LE(i) === 0x000b) {\n resolveAt(i + 2, true)\n i += 16\n break\n }\n // bare 0x000a = char 타입 줄바꿈(2바이트, 확장 데이터 없음) — 뒤 14바이트 소비 금지(줄마다 7글자 증발 버그).\n result += \"\\n\"\n break\n }\n case CHAR_PARA: break // 문단 끝\n // 하이픈(24)은 한컴이 그리지 않는다 — 한컴 PDF·rhwp export-hwpx 모두 \"60g/㎡\"(licbyl2 17855137,\n // 전 코퍼스 유일 출현). 실렌더가 진실이므로 방출하지 않는다 (v4.12.3, 종전 \"-\")\n case CHAR_HYPHEN: break\n case CHAR_NBSP: result += \"\\u00a0\"; break // 진짜 NBSP\n case CHAR_FIXED_WIDTH: result += \" \"; break // 고정폭 공백\n\n // ── inline 타입 (2바이트 + 14바이트 확장) ──\n // 확장 u16[7] 중 [2] 의 하위 바이트 = 채움 모양(0 없음·3 점선 …), 상위 = 탭 종류+1 (rhwp tab_extended 실측).\n // 채움 탭도 보통 탭 — 채움선은 글이 아니고 뒤 글(목차 쪽 번호 등)은 남긴다 (HWPX section-walker \"tab\" 과 같은 정책)\n // 본문 파서(tocLeaders)는 목차 항목 판정까지 채움 탭을 TOC_LEADER 표지로 받는다 (#121)\n case CHAR_TAB:\n result += state.tocLeaders && i + 6 <= data.length && (data.readUInt16LE(i + 4) & 0xff) !== 0 ? TOC_LEADER : \"\\t\"\n if (i + 14 <= data.length) i += 14\n break\n\n default:\n if (ch >= 0x0001 && ch <= 0x001f) {\n // rhwp 기준 3-카테고리 분류:\n // extended(1-3, 11-12, 14-18, 21-23) + inline(4-9, 19-20) → 14바이트 스킵\n // char(24-31) → 스킵 없음 (24,30,31은 switch에서 처리, 25-29는 예약 — 출력 없이 통과)\n const isExtended = isExtendedOnlyCtrlChar(ch)\n const isInline = (ch >= 4 && ch <= 9) || (ch >= 19 && ch <= 20)\n if ((isExtended || isInline) && i + 14 <= data.length) {\n if (ch === 0x0003) {\n // FIELD_BEGIN: anchor 시작 위치 + 컨트롤 인덱스 push\n state.fieldStack.push({ start: base + result.length, ctrlIdx: state.ctrlIdx })\n } else if (ch === 0x0004) {\n // FIELD_END: 스택 페어링 → anchor 범위 확정\n const open = state.fieldStack.pop()\n if (open) {\n state.fieldRanges.push({ start: open.start, end: base + result.length, ctrlIdx: open.ctrlIdx })\n }\n }\n resolveAt(i, isExtended)\n i += 14\n }\n } else if (ch >= 0x0020) {\n // HWP5 문자는 2바이트 WCHAR 라 한컴 Supplementary PUA-A(U+F0000대) 기호를 담을 수 없다 —\n // 한컴은 U+A000 + (code − 0xF0000) 으로 접어 저장한다(이 글자 음절 블록, 한국어 문서에는\n // 안 나온다). 결재란 \"(인)\"(F012B)이 A12B 로 들어 있는 법령 별지서식 실측 — rhwp export-hwpx\n // 도 같은 자리를 F012B→\"(인)\" 으로 복원한다. 펴서 mapPuaText(pua.ts) 표에 넘기고, 매핑 없는\n // 코드는 종전 PUA-A 정책(sanitizeText 제거)을 따른다 (v4.12.2)\n if (ch >= HANCOM_FOLDED_PUA_START && ch <= HANCOM_FOLDED_PUA_END) {\n result += String.fromCodePoint(ch + HANCOM_FOLDED_PUA_SHIFT)\n break\n }\n // UTF-16 surrogate pair 처리 (BMP 외 문자: 이모지, CJK 확장 등)\n if (ch >= 0xd800 && ch <= 0xdbff && i + 1 < data.length) {\n const lo = data.readUInt16LE(i)\n if (lo >= 0xdc00 && lo <= 0xdfff) {\n i += 2\n const codePoint = ((ch - 0xd800) << 10) + (lo - 0xdc00) + 0x10000\n result += String.fromCodePoint(codePoint)\n break\n }\n }\n // 짝 없는 서로게이트 반쪽 — 한글은 같은 자리를 □ 로 보여 주고 HWPX 로 저장할 때도 □ 를 쓴다. 반쪽을 그대로 내면\n // JSON 에 \\udfda 로 남고 UTF-8 로 쓰면 U+FFFD 가 된다 (rhwp cff474c8d #6873, 한글 HWPX 정본 대조). 레코드 끝의 상위 반쪽은\n // 자리를 남겨 다음 PARA_TEXT 레코드가 하위 반쪽으로 시작하면 한 글자로 되돌린다\n if (ch >= 0xd800 && ch <= 0xdfff) {\n result += \"\\u25a1\"\n if (ch <= 0xdbff && i >= data.length) { state.loneHigh = ch; state.loneHighAt = base + result.length - 1 }\n break\n }\n result += !state.dollarMark ? String.fromCharCode(ch) : ch === 0x24 ? LITERAL_DOLLAR_MARK : ch === 0x3c ? LITERAL_LT_MARK : String.fromCharCode(ch)\n }\n break\n }\n }\n\n if (state.scriptAt) setScript(null)\n state.wpos = wbase + Math.floor(data.length / 2)\n state.text += result\n}\n\n/** HWP5 EQEDIT(0x58) 레코드에서 한글 수식 스크립트 원문 추출 */\nexport function extractEquationText(data: Buffer): string | null {\n if (data.length < 6) return null\n\n const scriptLength = data.readUInt16LE(4)\n const scriptStart = 6\n const scriptEnd = scriptStart + scriptLength * 2\n if (scriptLength <= 0 || scriptEnd > data.length) return null\n\n const equation = data.subarray(scriptStart, scriptEnd).toString(\"utf16le\").replace(/\\0+/g, \"\").trim()\n return equation || null\n}\n","/**\n * HWPX·HWP5 목차 항목 — 줄마다 \"글 + 채움 탭 + 쪽 번호\"뿐인 문단. 채움 탭 뒤 글을 남기면서(4.17.0) 쪽 번호가 제목 글에 붙어\n * 본문 제목과 다른 제목으로 outline·breadcrumb 에 들어갔다(#121). 글은 그대로 두고 제목으로 올리지 않는다\n * (PDF table-roles TOC_BLOCKS 와 같은 규칙). 일정 줄 \"의견 조사 ····· 10~11월\" 은 쪽 번호가 아니라 목차가 아니다.\n */\n\nimport type { IRBlock } from \"./types.js\"\n\n/** 채움 탭 표지 — 문단 글을 다 모은 뒤 목차 판정을 하고 보통 탭으로 바꾼다 */\nexport const TOC_LEADER = \"\\x1F\"\nconst LEADERS = /\\x1F/g\n/** 목차 쪽 번호 — 아라비아·로마 숫자, 장-쪽(\"3-12\"), 가운데 쪽(\"- 5 -\") */\nconst PAGE_LABEL = /^(?:\\d{1,4}|[ivxlc]{1,7}|\\d{1,3}\\s*[-–]\\s*\\d{1,4}|[-–]\\s*\\d{1,4}\\s*[-–])$/i\n\n/** 제목 추정(개요 번호·글꼴 크기·\"제N장\")에서 뺄 목차 항목 블록 */\nexport const TOC_ENTRY_BLOCKS = new WeakSet<IRBlock>()\n\n/** 채움 탭 표지를 보통 탭으로 바꾸고, 문단이 목차 항목인지 돌려준다 (\\x1E 는 글자취급 표 경계) */\nexport function takeTocLeaders(text: string): { text: string; tocEntry: boolean } {\n if (!text.includes(TOC_LEADER)) return { text, tocEntry: false }\n const lines = text.replace(/\\x1E/g, \"\").split(\"\\n\").filter(l => l.trim())\n const tocEntry = lines.length > 0 && lines.every(l => {\n const at = l.lastIndexOf(TOC_LEADER)\n return at > 0 && /\\S/.test(l.slice(0, at).replace(LEADERS, \"\")) && PAGE_LABEL.test(l.slice(at + 1).trim())\n })\n return { text: text.replace(LEADERS, \"\\t\"), tocEntry }\n}\n","/**\n * HWP5 BinData 이미지 추출.\n *\n * - DocInfo BIN_DATA의 binDataId(1-based) → storage_id 매핑은 parser.ts(pictureToImageBlock)에서 수행\n * - 이 모듈은 BinData 스토리지 엔트리(\"BIN%04X.ext\" — storage_id는 16진!)를 storageId 키로 수집하고\n * 블록 트리(셀 내부 blocks 포함)의 image 블록과 매칭해 ExtractedImage로 변환한다.\n */\n\nimport { decompressStream } from \"./record.js\"\nimport type { LenientCfbContainer } from \"./cfb-lenient.js\"\nimport type { ExtractedImage, IRBlock, ParseWarning } from \"../types.js\"\n\n/** CFB FileIndex 엔트리 (cfb 모듈 호환 최소 형태) */\nexport interface BinCfbEntry { name?: string; content?: Buffer | Uint8Array }\n\n/** MIME 타입 매직바이트 판별 */\nexport function detectImageMime(data: Buffer | Uint8Array): string | null {\n if (data.length < 4) return null\n if (data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4e && data[3] === 0x47) return \"image/png\"\n if (data[0] === 0xff && data[1] === 0xd8 && data[2] === 0xff) return \"image/jpeg\"\n if (data[0] === 0x47 && data[1] === 0x49 && data[2] === 0x46) return \"image/gif\"\n if (data[0] === 0x42 && data[1] === 0x4d) return \"image/bmp\"\n if (data[0] === 0xd7 && data[1] === 0xcd && data[2] === 0xc6 && data[3] === 0x9a) return \"image/wmf\"\n // 배치 헤더 없는 표준 WMF — mtType 1(메모리)·2(디스크) + mtHeaderSize 9워드. 한컴 BinData 의 .wmf 는 대개 이 꼴\n // (법령 서식 BIN0001.wmf 실측 01 00 09 00 00 03). 종전엔 \"알 수 없는 형식\"이라 셀에 [이미지: …] 글이 박혔다\n if ((data[0] === 0x01 || data[0] === 0x02) && data[1] === 0x00 && data[2] === 0x09 && data[3] === 0x00) return \"image/wmf\"\n if (data[0] === 0x01 && data[1] === 0x00 && data[2] === 0x00 && data[3] === 0x00) return \"image/emf\"\n // TIFF — 리틀(II*\\0)·빅(MM\\0*) 엔디언 (행정업무편람 BIN016C.TIF 실측)\n if ((data[0] === 0x49 && data[1] === 0x49 && data[2] === 0x2a && data[3] === 0x00) || (data[0] === 0x4d && data[1] === 0x4d && data[2] === 0x00 && data[3] === 0x2a)) return \"image/tiff\"\n return null\n}\n\n/** MIME → 추출 파일 확장자 (HWPX images.ts mimeToExt 와 같은 표) */\nfunction mimeExt(mime: string): string {\n if (mime.includes(\"jpeg\")) return \"jpg\"\n if (mime.includes(\"png\")) return \"png\"\n if (mime.includes(\"gif\")) return \"gif\"\n if (mime.includes(\"bmp\")) return \"bmp\"\n if (mime.includes(\"tiff\")) return \"tif\"\n if (mime.includes(\"wmf\")) return \"wmf\"\n if (mime.includes(\"emf\")) return \"emf\"\n return \"bin\"\n}\n\n/**\n * BinData 페이로드 정규화 — 항목별 압축 플래그가 문서 압축 플래그와 다를 수 있으므로\n * 매직바이트가 안 보이면 압축 해제를 시도하고, 실패하면 원본 유지.\n */\nfunction normalizeBinPayload(data: Buffer): Buffer {\n if (detectImageMime(data)) return data\n try {\n const inflated = decompressStream(data)\n if (inflated.length > 0) return inflated\n } catch { /* 비압축 데이터 */ }\n return data\n}\n\n/** BinData 스토리지 엔트리명 — \"BIN%04X.ext\" (storage_id는 16진!) */\nconst BIN_ENTRY_RE = /(?:^|\\/)BIN([0-9A-Fa-f]{4,8})(?:\\.[^./\\\\]*)?$/\n\n/** 블록 트리 재귀 깊이 상한 — hwpx collectImageBlocks(MAX_XML_DEPTH)와 동일 값.\n * 손상/악성 문서의 자기참조·초심층 트리 스택 오버플로 방지 */\nconst MAX_BLOCK_DEPTH = 200\n\n/** 블록 트리(셀 내부 blocks 포함)에서 image 블록 수집.\n * hwpx 쪽과 안전장치 합집합: depth 가드 + children 순회 (둘 다 수행) */\nfunction collectImageBlocks(blocks: IRBlock[], out: IRBlock[], depth = 0): void {\n if (depth > MAX_BLOCK_DEPTH) return\n for (const b of blocks) {\n if (b.type === \"image\") out.push(b)\n if (b.table) {\n for (const row of b.table.cells) {\n for (const cell of row) {\n if (cell.blocks) collectImageBlocks(cell.blocks, out, depth + 1)\n }\n }\n }\n if (b.children) collectImageBlocks(b.children, out, depth + 1)\n }\n}\n\n/**\n * 이미지 sentinel(\"![image](hwp5bin:ID)\")을 추출된 파일명으로 치환 — 표 셀 텍스트, 그리고 머리말·각주·캡션처럼\n * 표를 평문으로 편 글(ir-assemble tableFlatText)에도 남으므로 블록 트리 전체(문단 글·각주·캡션·셀)를 훑는다.\n * 파일명이 없으면(BinData 없음·페이지 필터로 스윕 안 함) \"[이미지]\"\n */\nconst IMAGE_SENTINEL_RE = /!\\[image\\]\\(hwp5bin:(\\d+)\\)/g\nfunction resolveImageSentinels(blocks: IRBlock[], renamed: Map<number, string>, depth = 0): void {\n if (depth > MAX_BLOCK_DEPTH) return\n const fix = (s: string): string => s.includes(\"hwp5bin:\")\n ? s.replace(IMAGE_SENTINEL_RE, (_m, idStr: string) => {\n const filename = renamed.get(Number(idStr))\n return filename ? `![image](${filename})` : \"[이미지]\"\n })\n : s\n for (const b of blocks) {\n if (b.text) b.text = fix(b.text)\n if (b.footnoteText) b.footnoteText = fix(b.footnoteText)\n if (b.table) {\n if (b.table.caption) b.table.caption = fix(b.table.caption)\n for (const row of b.table.cells) {\n for (const cell of row) {\n cell.text = fix(cell.text)\n if (cell.blocks) resolveImageSentinels(cell.blocks, renamed, depth + 1)\n }\n }\n }\n if (b.children) resolveImageSentinels(b.children, renamed, depth + 1)\n if (b.footnoteBlocks) resolveImageSentinels(b.footnoteBlocks, renamed, depth + 1)\n }\n}\n\n/** binDataMap 기반 이미지 블록 해결 — strict/lenient·HWP3 공용 */\nexport function resolveImageBlocks(\n binDataMap: Map<number, { data: Buffer; name: string }>,\n blocks: IRBlock[],\n warnings: ParseWarning[],\n sweepUnreferenced?: boolean,\n): ExtractedImage[] {\n const imageBlocks: IRBlock[] = []\n collectImageBlocks(blocks, imageBlocks)\n\n const images: ExtractedImage[] = []\n const renamed = new Map<number, string>()\n // 같은 BinData를 참조하는 개체가 수천 개일 수 있다(도형 반복 등) — storageId당\n // 1회만 변환·추출하고 데이터 버퍼를 공유한다 (블록마다 복사하면 메모리 폭발)\n const resolved = new Map<number, { filename: string; data: Uint8Array; mime: string } | null>()\n let imageIndex = 0\n\n for (const block of imageBlocks) {\n if (!block.text) continue\n const storageId = parseInt(block.text, 10)\n if (isNaN(storageId)) continue\n\n let img = resolved.get(storageId)\n if (img === undefined) {\n const bin = binDataMap.get(storageId)\n if (!bin) {\n warnings.push({ page: block.pageNumber, message: `BinData ${storageId} 없음`, code: \"SKIPPED_IMAGE\" })\n resolved.set(storageId, null)\n } else {\n const mime = detectImageMime(bin.data)\n if (!mime) {\n warnings.push({ page: block.pageNumber, message: `BinData ${storageId}: 알 수 없는 이미지 형식`, code: \"SKIPPED_IMAGE\" })\n resolved.set(storageId, null)\n } else {\n imageIndex++\n const ext = mimeExt(mime)\n img = { filename: `image_${String(imageIndex).padStart(3, \"0\")}.${ext}`, data: new Uint8Array(bin.data), mime }\n resolved.set(storageId, img)\n images.push({ filename: img.filename, data: img.data, mimeType: img.mime, source: bin.name })\n renamed.set(storageId, img.filename)\n }\n }\n img = resolved.get(storageId)\n }\n\n if (!img) {\n const bin = binDataMap.get(storageId)\n block.type = \"paragraph\"\n block.text = bin ? `[이미지: ${bin.name}]` : `[이미지: BinData ${storageId}]`\n continue\n }\n block.text = img.filename\n block.imageData = { data: img.data, mimeType: img.mime, filename: binDataMap.get(storageId)!.name }\n }\n\n // 본문 미참조 BinData 이미지 스윕 — pic 컨트롤이 닿지 않는 이미지(셀 배경 등)를\n // 문서 끝에 image 블록으로 보강한다. 이미지가 아닌 스트림(OLE 등)은 건너뛴다.\n if (sweepUnreferenced) {\n for (const [storageId, bin] of [...binDataMap.entries()].sort((a, b) => a[0] - b[0])) {\n if (resolved.has(storageId)) continue\n const mime = detectImageMime(bin.data)\n if (!mime) continue\n imageIndex++\n const ext = mimeExt(mime)\n const filename = `image_${String(imageIndex).padStart(3, \"0\")}.${ext}`\n const data = new Uint8Array(bin.data)\n images.push({ filename, data, mimeType: mime, source: bin.name })\n blocks.push({ type: \"image\", text: filename, imageData: { data, mimeType: mime, filename: bin.name } })\n // 머리말·각주 안 표를 편 글의 sentinel 도 이 파일을 가리킨다 (본문 image 블록이 없던 그림)\n renamed.set(storageId, filename)\n }\n }\n\n resolveImageSentinels(blocks, renamed)\n return images\n}\n\n/** BinData 스토리지의 모든 파일을 FileIndex 순회로 수집 — 엔트리명은 \"BIN%04X.ext\" 16진.\n * 파서(이미지 추출)와 렌더 어댑터(#75 HWP5)가 공유한다 */\nexport function collectHwp5BinData(fileIndex: BinCfbEntry[] | undefined, readStream?: (path: string) => Buffer | null): Map<number, { data: Buffer; name: string }> {\n const binDataMap = new Map<number, { data: Buffer; name: string }>()\n if (fileIndex) {\n for (const entry of fileIndex) {\n if (!entry?.name || !entry.content) continue\n const match = entry.name.match(BIN_ENTRY_RE)\n if (!match) continue\n const idx = parseInt(match[1], 16)\n const raw = readStream ? readStream(`/BinData/${entry.name}`) : Buffer.from(entry.content)\n if (!raw) continue\n const data = normalizeBinPayload(raw)\n binDataMap.set(idx, { data, name: entry.name })\n }\n }\n return binDataMap\n}\n\n/** Lenient CFB: BinData 엔트리 수집 — 엔트리명 \"BIN%04X.ext\" 16진 */\nexport function collectHwp5BinDataLenient(lcfb: LenientCfbContainer, readStream = lcfb.findStream): Map<number, { data: Buffer; name: string }> {\n const binDataMap = new Map<number, { data: Buffer; name: string }>()\n const binRe = /^BIN([0-9A-Fa-f]{4,8})(?:\\.|$)/\n for (const e of lcfb.entries()) {\n const match = e.name.match(binRe)\n if (!match) continue\n const idx = parseInt(match[1], 16)\n // 경로로 찾는다 — 맨 이름은 같은 이름이 둘이면 고르지 않는다 (cfb-lenient findEntryByPath)\n const raw = readStream(`/BinData/${e.name}`) ?? readStream(e.name)\n if (!raw) continue\n binDataMap.set(idx, { data: normalizeBinPayload(raw), name: e.name })\n }\n return binDataMap\n}\n\n/** OLE2 BinData 스토리지(FileIndex)에서 이미지 추출, blocks의 image 블록과 매핑 */\nexport function extractHwp5Images(\n fileIndex: BinCfbEntry[] | undefined,\n blocks: IRBlock[],\n warnings: ParseWarning[],\n sweepUnreferenced?: boolean,\n readStream?: (path: string) => Buffer | null,\n): ExtractedImage[] {\n const binDataMap = collectHwp5BinData(fileIndex, readStream)\n\n if (binDataMap.size === 0) {\n // 이미지 블록이 있는데 BinData가 없으면 sentinel 정리만 수행\n resolveImageSentinels(blocks, new Map())\n return []\n }\n return resolveImageBlocks(binDataMap, blocks, warnings, sweepUnreferenced)\n}\n\n/** Lenient CFB: BinData 이미지 추출 */\nexport function extractHwp5ImagesLenient(\n lcfb: LenientCfbContainer,\n blocks: IRBlock[],\n warnings: ParseWarning[],\n sweepUnreferenced?: boolean,\n readStream?: (path: string) => Buffer | null,\n): ExtractedImage[] {\n const binDataMap = collectHwp5BinDataLenient(lcfb, readStream)\n if (binDataMap.size === 0) {\n resolveImageSentinels(blocks, new Map())\n return []\n }\n return resolveImageBlocks(binDataMap, blocks, warnings, sweepUnreferenced)\n}\n","/**\n * AES-128 ECB 순수 JS 구현 — 배포용 HWP 복호화 전용.\n * 외부 의존성 없음 (kordoc 제로 네이티브 의존성 원칙 유지).\n * 참조: rhwp (MIT) src/parser/crypto.rs + FIPS-197 (AES 표준)\n */\n\n// ── S-Box & 역 S-Box ──\n\nconst S_BOX = new Uint8Array([\n 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,\n 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,\n 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,\n 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,\n 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,\n 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,\n 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,\n 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,\n 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,\n 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,\n 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,\n 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,\n 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,\n 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,\n 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,\n 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16,\n])\n\nconst INV_S_BOX = new Uint8Array([\n 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,\n 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,\n 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,\n 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,\n 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,\n 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,\n 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,\n 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,\n 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,\n 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,\n 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,\n 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,\n 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,\n 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,\n 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,\n 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d,\n])\n\n// ── RCON (라운드 상수) ──\n\nconst RCON = new Uint8Array([0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36])\n\n// ── GF(2^8) 곱셈 ──\n\nfunction gmul(a: number, b: number): number {\n let p = 0\n for (let i = 0; i < 8; i++) {\n if (b & 1) p ^= a\n const hi = a & 0x80\n a = (a << 1) & 0xff\n if (hi) a ^= 0x1b\n b >>= 1\n }\n return p\n}\n\n// ── 키 확장 (AES-128: 4 words → 44 words) ──\n\nfunction expandKey(key: Uint8Array): Uint32Array {\n const w = new Uint32Array(44)\n\n // 첫 4 words: 원본 키\n for (let i = 0; i < 4; i++) {\n w[i] = (key[4 * i] << 24) | (key[4 * i + 1] << 16) | (key[4 * i + 2] << 8) | key[4 * i + 3]\n }\n\n for (let i = 4; i < 44; i++) {\n let temp = w[i - 1]\n if (i % 4 === 0) {\n // RotWord + SubWord + RCON\n temp = ((temp << 8) | (temp >>> 24)) >>> 0\n temp = (S_BOX[(temp >>> 24) & 0xff] << 24) |\n (S_BOX[(temp >>> 16) & 0xff] << 16) |\n (S_BOX[(temp >>> 8) & 0xff] << 8) |\n S_BOX[temp & 0xff]\n temp = (temp ^ (RCON[i / 4 - 1] << 24)) >>> 0\n }\n w[i] = (w[i - 4] ^ temp) >>> 0\n }\n\n return w\n}\n\n// ── AES-128 단일 블록 복호화 (16바이트) ──\n\nfunction decryptBlock(block: Uint8Array, roundKeys: Uint32Array): Uint8Array {\n // state를 4x4 column-major 배열로 로드\n const s = new Uint8Array(16)\n for (let i = 0; i < 16; i++) s[i] = block[i]\n\n // AddRoundKey (round 10)\n addRoundKey(s, roundKeys, 10)\n\n // Rounds 9 → 1\n for (let round = 9; round >= 1; round--) {\n invShiftRows(s)\n invSubBytes(s)\n addRoundKey(s, roundKeys, round)\n invMixColumns(s)\n }\n\n // Final round (round 0)\n invShiftRows(s)\n invSubBytes(s)\n addRoundKey(s, roundKeys, 0)\n\n return s\n}\n\nfunction addRoundKey(s: Uint8Array, w: Uint32Array, round: number): void {\n const base = round * 4\n for (let c = 0; c < 4; c++) {\n const k = w[base + c]\n s[c * 4] ^= (k >>> 24) & 0xff\n s[c * 4 + 1] ^= (k >>> 16) & 0xff\n s[c * 4 + 2] ^= (k >>> 8) & 0xff\n s[c * 4 + 3] ^= k & 0xff\n }\n}\n\nfunction invSubBytes(s: Uint8Array): void {\n for (let i = 0; i < 16; i++) s[i] = INV_S_BOX[s[i]]\n}\n\nfunction invShiftRows(s: Uint8Array): void {\n // Row 0: no shift\n // Row 1: shift right 1\n let t = s[13]; s[13] = s[9]; s[9] = s[5]; s[5] = s[1]; s[1] = t\n // Row 2: shift right 2\n t = s[2]; s[2] = s[10]; s[10] = t\n t = s[6]; s[6] = s[14]; s[14] = t\n // Row 3: shift right 3 (= left 1)\n t = s[3]; s[3] = s[7]; s[7] = s[11]; s[11] = s[15]; s[15] = t\n}\n\nfunction invMixColumns(s: Uint8Array): void {\n for (let c = 0; c < 4; c++) {\n const i = c * 4\n const a0 = s[i], a1 = s[i + 1], a2 = s[i + 2], a3 = s[i + 3]\n s[i] = gmul(a0, 0x0e) ^ gmul(a1, 0x0b) ^ gmul(a2, 0x0d) ^ gmul(a3, 0x09)\n s[i + 1] = gmul(a0, 0x09) ^ gmul(a1, 0x0e) ^ gmul(a2, 0x0b) ^ gmul(a3, 0x0d)\n s[i + 2] = gmul(a0, 0x0d) ^ gmul(a1, 0x09) ^ gmul(a2, 0x0e) ^ gmul(a3, 0x0b)\n s[i + 3] = gmul(a0, 0x0b) ^ gmul(a1, 0x0d) ^ gmul(a2, 0x09) ^ gmul(a3, 0x0e)\n }\n}\n\n// ── 공개 API ──\n\n/** AES-128 ECB 복호화. data 길이는 16의 배수여야 함. */\nexport function aes128EcbDecrypt(data: Uint8Array, key: Uint8Array): Uint8Array {\n if (key.length !== 16) throw new Error(\"AES-128 키는 16바이트여야 합니다\")\n if (data.length % 16 !== 0) throw new Error(\"AES ECB 입력은 16바이트의 배수여야 합니다\")\n\n const roundKeys = expandKey(key)\n const out = new Uint8Array(data.length)\n\n for (let offset = 0; offset < data.length; offset += 16) {\n const block = data.subarray(offset, offset + 16)\n const decrypted = decryptBlock(block, roundKeys)\n out.set(decrypted, offset)\n }\n\n return out\n}\n","/**\n * HWP 배포용(distribution) 문서 복호화.\n *\n * 배포용 HWP는 ViewText/Section{N} 스트림에 암호화된 본문을 저장.\n * 첫 레코드(HWPTAG_DISTRIBUTE_DOC_DATA)의 256바이트 payload에서 AES 키를 추출한 뒤\n * 나머지 데이터를 AES-128 ECB로 복호화.\n *\n * 알고리즘 참조: rhwp (MIT) src/parser/crypto.rs\n * 포맷 참조: HWP 5.0 바이너리 스펙 — 배포용 문서 구조\n */\n\nimport { aes128EcbDecrypt } from \"./aes.js\"\nimport { decompressStream } from \"./record.js\"\n\n// ── MSVC LCG (Linear Congruential Generator) ──\n\n/** MSVC CRT rand() 호환 LCG */\nclass MsvcLcg {\n private seed: number\n\n constructor(seed: number) {\n this.seed = seed >>> 0 // u32로 강제\n }\n\n /** 0 ~ 0x7FFF 범위 난수 반환 (MSVC rand() 호환) */\n rand(): number {\n // MSVC LCG: seed = seed * 214013 + 2531011\n // JS에서 32bit 정수 오버플로우를 정확히 재현하기 위해 Math.imul 사용\n this.seed = (Math.imul(this.seed, 214013) + 2531011) >>> 0\n return (this.seed >>> 16) & 0x7fff\n }\n}\n\n// ── 배포용 문서 256바이트 payload 복호화 ──\n\n/**\n * DISTRIBUTE_DOC_DATA 레코드의 256바이트 payload를 LCG+XOR로 복호화.\n *\n * 구조:\n * - bytes[0..4]: LCG seed (u32 LE)\n * - bytes[4..256]: XOR 암호화된 데이터\n *\n * XOR 규칙: LCG에서 키 바이트를 뽑고, n = (lcg.rand() & 0xF) + 1 바이트마다 키 교체\n */\nfunction decryptDistributePayload(payload: Uint8Array): Uint8Array {\n if (payload.length < 256) throw new Error(\"배포용 payload가 256바이트 미만입니다\")\n\n const seed = (payload[0] | (payload[1] << 8) | (payload[2] << 16) | (payload[3] << 24)) >>> 0\n const lcg = new MsvcLcg(seed)\n\n const result = new Uint8Array(payload.subarray(0, 256)) // 원본 복사\n\n // rhwp 호환: i=0부터 시작하여 n 카운터를 소비하되, i<4는 XOR 스킵 (seed 보존)\n // i=4부터 시작하면 LCG 시퀀스가 어긋남 — i=0~3에서도 n을 소비해야 정확함\n let i = 0\n let n = 0\n let key = 0\n\n while (i < 256) {\n if (n === 0) {\n key = lcg.rand() & 0xff\n n = (lcg.rand() & 0x0f) + 1\n }\n if (i >= 4) {\n result[i] ^= key\n }\n i++\n n--\n }\n\n return result\n}\n\n// ── AES 키 추출 ──\n\n/**\n * 복호화된 256바이트 payload에서 AES-128 키(16바이트) 추출.\n * offset = 4 + (decrypted[0] & 0x0F)\n */\nfunction extractAesKey(decryptedPayload: Uint8Array): Uint8Array {\n const offset = 4 + (decryptedPayload[0] & 0x0f)\n if (offset + 16 > decryptedPayload.length) {\n throw new Error(\"AES 키 추출 실패: 오프셋이 payload 범위를 초과합니다\")\n }\n return decryptedPayload.slice(offset, offset + 16)\n}\n\n// ── 레코드 헤더 파싱 ──\n\n/** HWP 레코드 헤더에서 tag_id와 size 추출 */\nfunction parseRecordHeader(data: Uint8Array, offset: number): { tagId: number; size: number; headerSize: number } {\n if (offset + 4 > data.length) throw new Error(\"레코드 헤더 파싱 실패: 데이터 부족\")\n\n const header = (data[offset] | (data[offset + 1] << 8) | (data[offset + 2] << 16) | (data[offset + 3] << 24)) >>> 0\n const tagId = header & 0x3ff\n let size = (header >>> 20) & 0xfff\n let headerSize = 4\n\n if (size === 0xfff) {\n if (offset + 8 > data.length) throw new Error(\"확장 레코드 크기 파싱 실패: 데이터 부족\")\n size = (data[offset + 4] | (data[offset + 5] << 8) | (data[offset + 6] << 16) | (data[offset + 7] << 24)) >>> 0\n headerSize = 8\n }\n\n return { tagId, size, headerSize }\n}\n\n// ── 공개 API ──\n\n/** HWPTAG_DISTRIBUTE_DOC_DATA 태그 ID (HWPTAG_BEGIN + 12 = 0x10 + 12 = 0x1C = 28) */\nconst TAG_DISTRIBUTE_DOC_DATA = 0x10 + 12 // = 28\n\n/**\n * ViewText 스트림을 복호화하여 일반 BodyText 레코드 데이터로 변환.\n *\n * @param viewTextRaw ViewText/Section{N} 스트림의 원본 바이트\n * @param compressed FileHeader의 compressed 플래그\n * @returns 복호화된 레코드 데이터 (readRecords()로 파싱 가능)\n */\nexport function decryptViewText(viewTextRaw: Buffer, compressed: boolean): Buffer {\n const data = new Uint8Array(viewTextRaw)\n\n // 1. 첫 레코드 파싱 (DISTRIBUTE_DOC_DATA)\n const rec = parseRecordHeader(data, 0)\n if (rec.tagId !== TAG_DISTRIBUTE_DOC_DATA) {\n throw new Error(`배포용 문서의 첫 레코드가 DISTRIBUTE_DOC_DATA(${TAG_DISTRIBUTE_DOC_DATA})가 아닙니다 (실제: ${rec.tagId})`)\n }\n\n const payloadStart = rec.headerSize\n const payloadEnd = payloadStart + rec.size\n if (payloadEnd > data.length || rec.size < 256) {\n throw new Error(\"배포용 payload가 유효하지 않습니다\")\n }\n\n // 2. 256바이트 payload 복호화 (LCG + XOR)\n const payload = data.subarray(payloadStart, payloadStart + 256)\n const decryptedPayload = decryptDistributePayload(payload)\n\n // 3. AES-128 키 추출\n const aesKey = extractAesKey(decryptedPayload)\n\n // 4. 나머지 데이터를 AES-128 ECB 복호화\n const encryptedStart = payloadEnd\n const encryptedData = data.subarray(encryptedStart)\n\n if (encryptedData.length === 0) {\n throw new Error(\"배포용 문서에 암호화된 본문 데이터가 없습니다\")\n }\n\n // AES ECB는 16바이트 블록 단위 — 패딩 처리\n const alignedLen = encryptedData.length - (encryptedData.length % 16)\n if (alignedLen === 0) {\n throw new Error(\"암호화된 데이터가 너무 짧습니다 (16바이트 미만)\")\n }\n\n const alignedData = encryptedData.subarray(0, alignedLen)\n const decrypted = aes128EcbDecrypt(alignedData, aesKey)\n\n // 5. 압축 해제 (compressed 플래그가 설정된 경우)\n if (compressed) {\n try {\n return decompressStream(Buffer.from(decrypted))\n } catch {\n // 압축이 아닐 수도 있음 — 그대로 반환\n return Buffer.from(decrypted)\n }\n }\n\n return Buffer.from(decrypted)\n}\n\n// 테스트용 내부 함수 export\nexport { MsvcLcg as _MsvcLcg, decryptDistributePayload as _decryptDistributePayload, extractAesKey as _extractAesKey }\n","/**\n * Lenient CFB (Compound File Binary / OLE2) 파서.\n *\n * 표준 cfb 모듈이 FAT 검증 실패로 거부하는 손상된 HWP 파일을 열기 위한 폴백.\n * 직접 헤더/FAT/디렉토리를 파싱하여 스트림 데이터를 추출.\n *\n * 참조: rhwp (MIT) src/parser/cfb_reader.rs (LenientCfbReader)\n * 참조: MS-CFB spec (https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cfb)\n */\n\nimport { decompressStream } from \"./record.js\"\n\n// ── 상수 ──\n\nconst CFB_MAGIC = Buffer.from([0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1])\nconst END_OF_CHAIN = 0xfffffffe\nconst FREE_SECT = 0xffffffff\n\n/** 순환 감지용 최대 체인 길이 */\nconst MAX_CHAIN_LENGTH = 1_000_000\n/** 최대 디렉토리 엔트리 수 */\nconst MAX_DIR_ENTRIES = 100_000\n/** 최대 스트림 크기 (100MB) */\nconst MAX_STREAM_SIZE = 100 * 1024 * 1024\n\n// ── 디렉토리 엔트리 ──\n\ninterface DirEntry {\n name: string\n type: number // 0=unknown, 1=storage, 2=stream, 5=root\n startSector: number\n size: number\n /** 형제 트리 왼쪽·오른쪽, 스토리지의 첫 자식 (디렉터리 엔트리 번호) */\n left: number\n right: number\n child: number\n}\n\n// ── CFB 컨테이너 ──\n\nexport interface LenientCfbContainer {\n /** 이름 기반 스트림 탐색 */\n findStream(path: string): Buffer | null\n /** 디렉토리 엔트리 목록 */\n entries(): DirEntry[]\n}\n\n// ── 구현 ──\n\nexport function parseLenientCfb(data: Buffer): LenientCfbContainer {\n if (data.length < 512) throw new Error(\"CFB 파일이 너무 짧습니다 (최소 512바이트)\")\n if (!data.subarray(0, 8).equals(CFB_MAGIC)) throw new Error(\"CFB 매직 바이트 불일치\")\n\n // ── 헤더 파싱 ──\n\n const sectorSizeShift = data.readUInt16LE(30)\n if (sectorSizeShift < 7 || sectorSizeShift > 16) throw new Error(\"유효하지 않은 섹터 크기 시프트: \" + sectorSizeShift)\n const sectorSize = 1 << sectorSizeShift // 보통 512\n const miniSectorSizeShift = data.readUInt16LE(32)\n if (miniSectorSizeShift > 16) throw new Error(\"유효하지 않은 미니 섹터 크기 시프트: \" + miniSectorSizeShift)\n const miniSectorSize = 1 << miniSectorSizeShift // 보통 64\n\n const headerFatSectorCount = data.readUInt32LE(44)\n if (headerFatSectorCount > 10000) throw new Error(\"FAT 섹터 수가 너무 많습니다: \" + headerFatSectorCount)\n // 실 파일 크기 sanity — FAT 엔트리는 파일 내 실존 섹터 수를 넘을 수 없다\n // (헤더 카운트 뻥튀기로 인한 fatTable 할당 증폭 방지: ~130KB 파일이 655MB 할당하던 버그)\n const maxRealSectors = Math.ceil(Math.max(0, data.length - 512) / sectorSize)\n const maxFatSectors = Math.max(1, Math.ceil(maxRealSectors / (sectorSize / 4)))\n const fatSectorCount = Math.min(headerFatSectorCount, maxFatSectors)\n const firstDirSector = data.readUInt32LE(48)\n const miniStreamCutoff = data.readUInt32LE(56) // 보통 4096\n const firstMiniFatSector = data.readUInt32LE(60)\n const miniFatSectorCount = data.readUInt32LE(64)\n const firstDifatSector = data.readUInt32LE(68)\n const difatSectorCount = data.readUInt32LE(72)\n\n // ── 유틸 ──\n\n function sectorOffset(id: number): number {\n return 512 + id * sectorSize\n }\n\n function readSectorData(id: number): Buffer {\n const off = sectorOffset(id)\n if (off + sectorSize > data.length) return Buffer.alloc(0)\n return data.subarray(off, off + sectorSize)\n }\n\n // ── DIFAT → FAT 섹터 목록 ──\n\n const fatSectors: number[] = []\n\n // 헤더 내 DIFAT (최대 109개)\n for (let i = 0; i < 109 && fatSectors.length < fatSectorCount; i++) {\n const sid = data.readUInt32LE(76 + i * 4)\n if (sid === FREE_SECT || sid === END_OF_CHAIN) break\n fatSectors.push(sid)\n }\n\n // 추가 DIFAT 섹터 체인\n let difatSector = firstDifatSector\n const visitedDifat = new Set<number>()\n for (let d = 0; d < difatSectorCount && difatSector !== END_OF_CHAIN && difatSector !== FREE_SECT; d++) {\n if (visitedDifat.has(difatSector)) break\n visitedDifat.add(difatSector)\n\n const buf = readSectorData(difatSector)\n if (buf.length < sectorSize) break // 파일 범위 밖 DIFAT 섹터(빈 버퍼) — readUInt32LE RangeError 방지, lenient 중단\n const entriesPerSector = (sectorSize / 4) - 1 // 마지막 4바이트는 다음 DIFAT 포인터\n for (let i = 0; i < entriesPerSector && fatSectors.length < fatSectorCount; i++) {\n const sid = buf.readUInt32LE(i * 4)\n if (sid === FREE_SECT || sid === END_OF_CHAIN) continue\n fatSectors.push(sid)\n }\n difatSector = buf.readUInt32LE(entriesPerSector * 4)\n }\n\n // ── FAT 테이블 구축 ──\n\n const entriesPerFatSector = sectorSize / 4\n const fatTable = new Uint32Array(fatSectors.length * entriesPerFatSector)\n\n for (let fi = 0; fi < fatSectors.length; fi++) {\n const buf = readSectorData(fatSectors[fi])\n for (let i = 0; i < entriesPerFatSector; i++) {\n fatTable[fi * entriesPerFatSector + i] = i * 4 + 3 < buf.length\n ? buf.readUInt32LE(i * 4)\n : FREE_SECT\n }\n }\n\n // ── 체인 리더 (순환 방지) ──\n\n function readChain(startSector: number, maxBytes: number): Buffer {\n if (startSector === END_OF_CHAIN || startSector === FREE_SECT) return Buffer.alloc(0)\n if (maxBytes > MAX_STREAM_SIZE) throw new Error(\"스트림이 너무 큽니다\")\n\n const chunks: Buffer[] = []\n let current = startSector\n let totalRead = 0\n const visited = new Set<number>()\n\n while (current !== END_OF_CHAIN && current !== FREE_SECT && totalRead < maxBytes) {\n if (visited.has(current)) break // 순환 감지\n if (visited.size > MAX_CHAIN_LENGTH) break\n visited.add(current)\n\n const buf = readSectorData(current)\n const remaining = maxBytes - totalRead\n chunks.push(remaining < sectorSize ? buf.subarray(0, remaining) : buf)\n totalRead += Math.min(buf.length, remaining)\n\n current = current < fatTable.length ? fatTable[current] : END_OF_CHAIN\n }\n\n return Buffer.concat(chunks)\n }\n\n // ── Mini-FAT 테이블 ──\n\n let miniFatTable: Uint32Array | null = null\n\n function getMiniFatTable(): Uint32Array {\n if (miniFatTable) return miniFatTable\n\n if (miniFatSectorCount === 0 || firstMiniFatSector === END_OF_CHAIN) {\n miniFatTable = new Uint32Array(0)\n return miniFatTable\n }\n\n const miniFatData = readChain(firstMiniFatSector, miniFatSectorCount * sectorSize)\n const entries = miniFatData.length / 4\n miniFatTable = new Uint32Array(entries)\n for (let i = 0; i < entries; i++) {\n miniFatTable[i] = miniFatData.readUInt32LE(i * 4)\n }\n return miniFatTable\n }\n\n // ── 디렉토리 엔트리 파싱 ──\n\n const dirData = readChain(firstDirSector, MAX_DIR_ENTRIES * 128)\n const dirEntries: DirEntry[] = []\n\n for (let offset = 0; offset + 128 <= dirData.length && dirEntries.length < MAX_DIR_ENTRIES; offset += 128) {\n const nameLen = dirData.readUInt16LE(offset + 64) // 바이트 수 (null 포함)\n if (nameLen <= 0 || nameLen > 64) {\n dirEntries.push({ name: \"\", type: 0, startSector: 0, size: 0, left: FREE_SECT, right: FREE_SECT, child: FREE_SECT })\n continue\n }\n\n const nameBytes = nameLen - 2 // null terminator 제외\n const name = nameBytes > 0\n ? dirData.subarray(offset, offset + nameBytes).toString(\"utf16le\")\n : \"\"\n\n const type = dirData[offset + 66]\n const startSector = dirData.readUInt32LE(offset + 116)\n // CFBv3에서는 size가 u32 (offset 120), v4에서는 u64\n const size = dirData.readUInt32LE(offset + 120)\n\n dirEntries.push({ name, type, startSector, size, left: dirData.readUInt32LE(offset + 68), right: dirData.readUInt32LE(offset + 72), child: dirData.readUInt32LE(offset + 76) })\n }\n\n // ── Root 엔트리에서 미니 스트림 추출 ──\n\n let miniStreamData: Buffer | null = null\n\n function getMiniStream(): Buffer {\n if (miniStreamData) return miniStreamData\n const root = dirEntries[0]\n if (!root || root.type !== 5) {\n miniStreamData = Buffer.alloc(0)\n return miniStreamData\n }\n miniStreamData = readChain(root.startSector, root.size || MAX_STREAM_SIZE)\n return miniStreamData\n }\n\n // ── 미니 스트림에서 읽기 ──\n\n function readMiniStream(startSector: number, size: number): Buffer {\n const mft = getMiniFatTable()\n const ms = getMiniStream()\n if (mft.length === 0 || ms.length === 0) return Buffer.alloc(0)\n\n const chunks: Buffer[] = []\n let current = startSector\n let totalRead = 0\n const visited = new Set<number>()\n\n while (current !== END_OF_CHAIN && current !== FREE_SECT && totalRead < size) {\n if (visited.has(current)) break\n if (visited.size > MAX_CHAIN_LENGTH) break\n visited.add(current)\n\n const off = current * miniSectorSize\n const remaining = size - totalRead\n const chunkSize = Math.min(miniSectorSize, remaining)\n if (off + chunkSize <= ms.length) {\n chunks.push(ms.subarray(off, off + chunkSize))\n }\n totalRead += chunkSize\n\n current = current < mft.length ? mft[current] : END_OF_CHAIN\n }\n\n return Buffer.concat(chunks)\n }\n\n // ── 스트림 읽기 (일반/미니 자동 분기) ──\n\n function readStreamData(entry: DirEntry): Buffer {\n if (entry.size === 0) return Buffer.alloc(0)\n if (entry.size < miniStreamCutoff) {\n const miniResult = readMiniStream(entry.startSector, entry.size)\n // 미니스트림이 비어있으면 일반 체인으로 폴백 (lenient)\n if (miniResult.length > 0) return miniResult\n }\n return readChain(entry.startSector, entry.size)\n }\n\n // ── 경로 기반 탐색 ──\n\n /** 스토리지의 자식 가운데 이름이 같은 엔트리 — 형제 트리를 따라간다 (순환·범위 밖 번호는 건너뛴다) */\n function findChild(parent: DirEntry, name: string): DirEntry | null {\n const pending = [parent.child]\n const visited = new Set<number>()\n while (pending.length) {\n const id = pending.pop()!\n if (id === END_OF_CHAIN || id === FREE_SECT || id >= dirEntries.length || visited.has(id)) continue\n visited.add(id)\n const e = dirEntries[id]\n if (e.name === name) return e\n pending.push(e.left, e.right)\n }\n return null\n }\n\n // 루트에서 경로 조각마다 스토리지를 따라 내려간다. 이름만 비교하면 BodyText/Section0 과 ViewText/Section0 처럼 이름이 같은\n // 스트림 가운데 디렉터리에 먼저 나오는 쪽이 잡혀, 비배포 문서에서 암호화된 ViewText 를 본문으로 읽다 글이 통째로 빠졌다\n // (rhwp ce6bca037·4b1f1179b). 트리가 깨진 입력은 이름으로 찾되, 같은 이름이 둘 이상이면 어느 쪽인지 모르니 고르지 않는다\n function findEntryByPath(path: string): DirEntry | null {\n const parts = path.replace(/^\\//, \"\").split(\"/\").filter(Boolean)\n const last = parts.pop()\n if (last === undefined) return null\n const root = dirEntries.find(e => e.type === 5)\n if (root) {\n let current: DirEntry | null = root\n for (const part of parts) {\n const next: DirEntry | null = current ? findChild(current, part) : null\n current = next && next.type === 1 ? next : null\n }\n const hit = current ? findChild(current, last) : null\n if (hit && (hit.type === 1 || hit.type === 2 || hit.type === 5)) return hit\n }\n const named = dirEntries.filter(e => e.name === last && (e.type === 1 || e.type === 2 || e.type === 5))\n return named.length === 1 ? named[0] : null\n }\n\n // ── 공개 API ──\n\n return {\n findStream(path: string): Buffer | null {\n // \\005 prefix 처리 (SummaryInformation)\n const normalized = path.replace(/^\\//, \"\")\n const entry = findEntryByPath(normalized)\n if (!entry || entry.type !== 2) return null\n const stream = readStreamData(entry)\n return stream.length > 0 ? stream : null\n },\n\n entries(): DirEntry[] {\n return dirEntries.filter(e => e.type === 2) // stream만\n },\n }\n}\n","/**\n * 비밀번호로 보호된 HWP5 문서 복호화 (EncryptVersion 4).\n *\n * 배포용(ViewText) 문서와는 완전히 다른 방식이다 — 이쪽은 사용자가 지정한 열기 암호로\n * `DocInfo`·`BodyText/Section*`·`BinData/*`·`Scripts/*` 스트림을 각각 복호한다.\n *\n * 키 = SHA-1(인터리브(비밀번호))[0..16]\n * 본문 = AES-128 **비트 단위 CFB**(CFB-1) 복호 — IV 0, 레지스터는 스트림 전역\n *\n * CFB-1 이라 16바이트마다 AES 블록 연산을 128회 수행한다(바이트당 8회). 표준 AES 대비\n * 128배 연산량이라, 블록 암호기 객체를 스트림당 하나만 만들어 재사용한다.\n *\n * 알고리즘 참조: rhwp (MIT) src/parser/crypto.rs — 원 출처는 volexity/hwp-extract\n * (BSD-3-Clause) 의 encrypt.py.\n */\n\nimport { createCipheriv, createHash } from \"crypto\"\nimport { KordocError } from \"../utils.js\"\n\n/** FileHeader 의 EncryptVersion(u32 LE) 위치 */\nconst ENCRYPT_VERSION_OFFSET = 44\n/** 우리가 아는 유일한 비밀번호 암호화 버전 */\nconst SUPPORTED_ENCRYPT_VERSION = 4\n/** 키 유도 인터리브의 첫 \"이전 바이트\" 시드 */\nconst KEY_SEED = 236\n\n/** FileHeader 에서 EncryptVersion 을 읽는다. 짧으면 0. */\nexport function readEncryptVersion(fileHeader: Uint8Array): number {\n if (fileHeader.length < ENCRYPT_VERSION_OFFSET + 4) return 0\n return (\n (fileHeader[ENCRYPT_VERSION_OFFSET] |\n (fileHeader[ENCRYPT_VERSION_OFFSET + 1] << 8) |\n (fileHeader[ENCRYPT_VERSION_OFFSET + 2] << 16) |\n (fileHeader[ENCRYPT_VERSION_OFFSET + 3] << 24)) >>>\n 0\n )\n}\n\n/**\n * 비밀번호 → AES-128 키 16바이트.\n *\n * 각 비밀번호 바이트 앞에 \"이전 바이트를 1비트 왼쪽 회전한 값\"을 끼워 넣어 길이 2배의\n * 버퍼를 만들고, 그 SHA-1 다이제스트 앞 16바이트를 키로 쓴다. 첫 바이트의 \"이전 값\"은\n * 시드 상수 236.\n */\nexport function derivePasswordKey(password: Uint8Array): Buffer {\n const buf = Buffer.alloc(password.length * 2)\n for (let i = 0; i < password.length; i++) {\n const prev = i === 0 ? KEY_SEED : password[i - 1]\n buf[i * 2] = ((prev << 1) | (prev >> 7)) & 0xff // ROL 1\n buf[i * 2 + 1] = password[i]\n }\n return createHash(\"sha1\").update(buf).digest().subarray(0, 16)\n}\n\n/** 16바이트 배수로 패드. 이미 배수면 그대로(참조 구현과 동일). */\nfunction padToBlock(data: Uint8Array): Buffer {\n const rem = data.length % 16\n if (rem === 0) return Buffer.from(data)\n const amount = 16 - rem\n return Buffer.concat([Buffer.from(data), Buffer.alloc(amount, amount)])\n}\n\n/** 128비트 레지스터를 1비트 왼쪽 시프트하고 최하위 비트에 feedback 을 넣는다 */\nfunction shiftRegister(reg: Uint8Array, feedbackBit: number): void {\n for (let i = 0; i < 15; i++) {\n reg[i] = ((reg[i] << 1) | (reg[i + 1] >> 7)) & 0xff\n }\n reg[15] = ((reg[15] << 1) | (feedbackBit & 1)) & 0xff\n}\n\n/**\n * AES-128 비트 단위 CFB 복호.\n *\n * 복호에도 AES 는 **암호화 방향**을 쓴다(CFB 의 정의). 레지스터는 블록마다 리셋하지 않고\n * 스트림 전체에서 이어진다. IV 는 0.\n */\nfunction decryptAesCfb1(data: Buffer, key: Buffer): Buffer {\n // ECB 는 블록 간 체이닝이 없어 Cipher 객체 하나를 계속 재사용해도 안전하다.\n // 매 블록 새로 만들면 128배 호출이라 감당이 안 된다.\n const cipher = createCipheriv(\"aes-128-ecb\", key, null)\n cipher.setAutoPadding(false)\n\n const register = new Uint8Array(16)\n const registerBuf = Buffer.alloc(16)\n const out = Buffer.alloc(data.length)\n\n for (let offset = 0; offset < data.length; offset += 16) {\n const len = Math.min(16, data.length - offset)\n const chunk = Buffer.alloc(16)\n data.copy(chunk, 0, offset, offset + len)\n\n for (let i = 0; i < 128; i++) {\n registerBuf.set(register)\n const keystreamMsb = cipher.update(registerBuf)[0]\n\n const byteIdx = i >> 3\n const bitInByte = i & 7\n // 되먹임은 **암호문** 비트 — XOR 로 평문이 되기 전 값을 넣어야 한다\n const cipherBit = (chunk[byteIdx] >> (7 - bitInByte)) & 1\n shiftRegister(register, cipherBit)\n\n chunk[byteIdx] ^= (keystreamMsb & 0x80) >> bitInByte\n }\n\n chunk.copy(out, offset, 0, len)\n }\n\n return out\n}\n\n/**\n * 암호 스트림 복호 (압축 해제는 하지 않음).\n * CFB 는 길이를 보존하므로 정렬용으로 덧붙인 패딩은 결과에서 잘라낸다.\n */\nexport function decryptPasswordStream(raw: Uint8Array, password: string): Buffer {\n const key = derivePasswordKey(Buffer.from(password, \"utf8\"))\n return decryptAesCfb1(padToBlock(raw), key).subarray(0, raw.length)\n}\n\n/** DocInfo 선두에 반드시 오는 레코드 (HWPTAG_BEGIN + 0 / + 1) */\nconst TAG_DOCUMENT_PROPERTIES = 0x0010\nconst TAG_ID_MAPPINGS = 0x0011\n\n/**\n * 복호한 DocInfo 가 실제 HWP 문서인지 확인한다.\n *\n * 비밀번호가 틀리면 복호 결과가 난수인데, 파서의 DocInfo·섹션 경로는 실패를 경고로\n * 흡수하도록 되어 있어 **\"성공했는데 내용이 쓰레기\"** 인 결과가 나온다. 압축 문서는\n * inflate 가 곧 무결성 검사지만 비압축 문서는 그것도 없으므로, DocInfo 가 반드시\n * 갖는 선두 레코드 두 종으로 확인한다.\n *\n * @param readRecords 레코드 리더 (순환 import 회피용 주입)\n */\nexport function assertDecryptedDocInfo(\n data: Buffer,\n readRecords: (buf: Buffer) => Array<{ tagId: number }>,\n): void {\n const wrong = () =>\n new KordocError(\"비밀번호가 일치하지 않거나 암호화 데이터가 손상되었습니다.\")\n let records: Array<{ tagId: number }>\n try {\n records = readRecords(data)\n } catch {\n throw wrong()\n }\n if (records[0]?.tagId !== TAG_DOCUMENT_PROPERTIES) throw wrong()\n if (!records.some(r => r.tagId === TAG_ID_MAPPINGS)) throw wrong()\n}\n\n/** EncryptVersion 을 검사하고 미지원이면 던진다 */\nexport function assertSupportedEncryptVersion(version: number): void {\n if (version !== SUPPORTED_ENCRYPT_VERSION) {\n // 구버전(1~3)을 같은 알고리즘으로 풀면 결과가 쓰레기인데도 \"비밀번호 오답\"으로\n // 보고돼 사용자가 암호를 계속 다시 입력하게 된다 — 방식이 다르다고 분명히 알린다.\n throw new KordocError(\n `지원하지 않는 HWP 암호화 버전입니다 (EncryptVersion=${version}, 지원: ${SUPPORTED_ENCRYPT_VERSION})`,\n )\n }\n}\n","/**\n * HWP 5.x 실제 페이지 경계 복원 (#66) — PARA_LINE_SEG(0x45) 조판 캐시로\n * 섹션 내 top-level 문단별 실제 페이지 배정을 계산한다.\n *\n * 알고리즘은 hwpx/page-boundary.ts와 동일한 신호 4종 (그쪽 헤더 주석 참조).\n * HWP5 매핑 (bench/corpus/pairs hwp↔hwpx 10쌍 전수 일치로 검증):\n * - lineseg → PARA_LINE_SEG 36바이트 엔트리 (v=+4 i32, h=+24 i32; 태그 +32의\n * bit0 \"페이지 첫 줄\"은 저장본에서 항상 0 — 못 씀)\n * - pageBreak → PARA_HEADER 데이터 offset 11(문단 나눔 종류)의 bit2(쪽 나누기)\n * - top 문단 → PARA_HEADER level 0, 그 lineseg는 level 1\n * - 표 셀 → CTRL_HEADER('tbl ') level 1 → LIST_HEADER level 2(셀 주소\n * col u16@8·row u16@10) → 셀 직접 문단은 같은 level 2, lineseg level 3\n * (중첩 표는 level 4/5라 자연 배제)\n */\n\nimport type { HwpRecord } from \"./record.js\"\nimport { TAG_PARA_HEADER, TAG_PARA_LINE_SEG, TAG_CTRL_HEADER, TAG_LIST_HEADER } from \"./record.js\"\n\n/** 이 값 이상에서 시작하는 역행은 페이지 상단 리셋이 아니다 (신호 4 판별, HWPUNIT) */\nconst MIDPAGE_V = 2000\n\n/** \"tbl \" 컨트롤 ID — LE 저장(\" lbt\")을 readUInt32LE로 읽은 BE 상수 (parser.ts CTRL_TBL과 동일) */\nconst CTRL_ID_TBL = 0x74626c20\n\n/** 섹션 페이지 감지 결과 */\nexport interface Hwp5SectionPageDetect {\n /** top-level 문단 순번(등장 순서) → 섹션 내 0-based 페이지 (문단 시작 위치 기준) */\n pageAtPara: number[]\n /** 섹션이 차지하는 페이지 수 (≥1) */\n pages: number\n /** 조판 캐시 신뢰 가능 여부 — top-level 문단 전부가 LINE_SEG를 가질 때만 true */\n usable: boolean\n}\n\n/** 표 컨트롤 범위의 내부 페이지 나눔 수 — 행별 max(셀 직접 문단 흐름 리셋) 합산 */\nfunction tableIntraBreaks(records: HwpRecord[], start: number, end: number): number {\n const rowMax = new Map<number, number>()\n let curRow = -1\n let prevV = Number.NEGATIVE_INFINITY\n let resets = 0\n const flush = () => {\n if (curRow >= 0) rowMax.set(curRow, Math.max(rowMax.get(curRow) ?? 0, resets))\n resets = 0\n prevV = Number.NEGATIVE_INFINITY\n }\n for (let i = start; i < end; i++) {\n const rec = records[i]\n if (rec.tagId === TAG_LIST_HEADER && rec.level === 2 && rec.data.length >= 12) {\n flush()\n curRow = rec.data.readUInt16LE(10)\n } else if (rec.tagId === TAG_PARA_LINE_SEG && rec.level === 3 && curRow >= 0) {\n for (let off = 0; off + 36 <= rec.data.length; off += 36) {\n const v = rec.data.readInt32LE(off + 4)\n if (v < prevV) resets++\n prevV = v\n }\n }\n }\n flush()\n let sum = 0\n for (const v of rowMax.values()) sum += v\n return sum\n}\n\n/**\n * 섹션 레코드에서 top-level 문단별 페이지 배정을 계산한다.\n * 반환 pageAtPara의 인덱스는 parseParagraphList가 만나는 top-level 문단 순서와 같다.\n */\nexport function detectHwp5SectionPages(records: HwpRecord[]): Hwp5SectionPageDetect {\n const pageAtPara: number[] = []\n let cur = 0\n let prevV = Number.NEGATIVE_INFINITY\n let prevH = Number.NEGATIVE_INFINITY\n let first = true\n let suppressMidReset = false\n let parasWithSegs = 0\n\n let i = 0\n while (i < records.length) {\n const rec = records[i]\n if (rec.tagId !== TAG_PARA_HEADER || rec.level !== 0) {\n i++\n continue\n }\n let j = i + 1\n while (j < records.length && records[j].level > 0) j++\n\n // 문단 나눔 종류(offset 11): bit0 구역, bit1 다단, bit2 쪽, bit3 단\n const divideSort = rec.data.length >= 12 ? rec.data.readUInt8(11) : 0\n const explicit = (divideSort & 0x04) !== 0\n let brokeByExplicit = false\n if (explicit && !first) {\n cur++\n brokeByExplicit = true\n suppressMidReset = false\n }\n\n let paraFirst = true\n let startPage = cur\n let hadSegs = false\n let intraAdd = 0\n for (let k = i + 1; k < j; k++) {\n const r = records[k]\n if (r.tagId === TAG_PARA_LINE_SEG && r.level === 1) {\n hadSegs = true\n for (let off = 0; off + 36 <= r.data.length; off += 36) {\n const v = r.data.readInt32LE(off + 4)\n const h = r.data.readInt32LE(off + 24)\n // HWPX 쪽 다단 예외(colCount>1일 때 h 우측 점프 배제)는 여기선 미적용 —\n // pairs 10쌍에서 HWPX와 결과 동일 검증. 다단 HWP5에서 어긋나면 그쪽 규칙 이식\n const brk = v < prevV || (paraFirst && v === prevV && h <= prevH)\n if (brk && !(paraFirst && brokeByExplicit)) {\n if (paraFirst && suppressMidReset && v >= MIDPAGE_V) {\n // 신호 4: 분할 표 꼬리 아래 재개 — 같은 경계\n } else {\n cur++\n }\n }\n if (paraFirst) {\n suppressMidReset = false\n startPage = cur\n }\n paraFirst = false\n prevV = v\n prevH = h\n }\n }\n // 신호 3: top-level 표(CTRL_HEADER 'tbl ', level 1)의 내부 분할\n if (r.tagId === TAG_CTRL_HEADER && r.level === 1 && r.data.length >= 4\n && r.data.readUInt32LE(0) === CTRL_ID_TBL) {\n let ce = k + 1\n while (ce < j && records[ce].level > 1) ce++\n intraAdd += tableIntraBreaks(records, k + 1, ce)\n k = ce - 1\n }\n }\n if (hadSegs) parasWithSegs++\n pageAtPara.push(startPage)\n first = false\n if (intraAdd > 0) {\n cur += intraAdd\n suppressMidReset = true\n }\n i = j\n }\n\n return {\n pageAtPara,\n pages: cur + 1,\n usable: pageAtPara.length > 0 && parasWithSegs === pageAtPara.length,\n }\n}\n","/**\n * HWP5 표 순번 (#75 Task 7 · #76 조인 키) — 섹션 레코드에서 표 컨트롤(CTRL_HEADER 'tbl ')을 문서(레코드) 순서로\n * 번호 매긴다. 파서(IRTable.sourceId)와 렌더 어댑터(RenderRegion.sourceId)가 **같은 프리패스**로 키를 얻어야\n * 중첩 표·머리말 안 표·깊이 상한으로 한쪽만 건너뛰는 개체가 있어도 번호가 어긋나지 않는다.\n * HWPX 의 `hp:tbl id` 에 해당하며, 형식은 `t{전역 1-based 순번}` (여러 구역은 base 누적).\n */\n\nimport { TAG_CTRL_HEADER, type HwpRecord } from \"./record.js\"\n\n/** \"tbl \" — LE 저장(\" lbt\")을 readUInt32LE 로 읽은 BE 상수 (parser.ts CTRL_TBL 과 동일) */\nconst CTRL_ID_TBL = 0x74626c20\n\nfunction swap32(id: number): number {\n return (((id & 0xff) << 24) | (((id >>> 8) & 0xff) << 16) | (((id >>> 16) & 0xff) << 8) | ((id >>> 24) & 0xff)) >>> 0\n}\n\nexport function isHwp5TableCtrl(rec: HwpRecord): boolean {\n if (rec.tagId !== TAG_CTRL_HEADER || rec.data.length < 4) return false\n const id = rec.data.readUInt32LE(0)\n return id === CTRL_ID_TBL || swap32(id) === CTRL_ID_TBL\n}\n\n/** 레코드 인덱스(CTRL_HEADER 위치) → sourceId. count 는 이 섹션의 표 수(다음 섹션 base 로 누적) */\nexport function indexHwp5Tables(records: HwpRecord[], base = 0): { ids: Map<number, string>; count: number } {\n const ids = new Map<number, string>()\n let n = 0\n for (let i = 0; i < records.length; i++) {\n if (isHwp5TableCtrl(records[i])) { n++; ids.set(i, `t${base + n}`) }\n }\n return { ids, count: n }\n}\n","/**\n * HWP5 문단번호/글머리표 — 7수준 카운터 상태기계 + ^N 형식 치환 + 번호 포맷터.\n *\n * 출처: rhwp (MIT) renderer/layout.rs NumberingState::advance,\n * renderer/layout/utils.rs expand_numbering_format, renderer/mod.rs format_number.\n */\n\nimport type { HwpNumbering } from \"./record.js\"\nimport { hangulOrdinal, circledNumber, circledHangul, romanNumeral } from \"../shared/numbering.js\"\n\n// ─── 7수준 카운터 상태기계 ───────────────────────────\n\n/**\n * 문단 번호 카운터 (수준별 1-7).\n * HWP 동작:\n * - 같은 numberingId 연속 = \"앞 번호 이어\" (카운터 유지)\n * - 다른 id (히스토리 있음) = \"이전 번호 이어\" (히스토리 복원)\n * - 다른 id (히스토리 없음) = 상위 수준 상속 + 현재 수준 이하 리셋\n */\nexport class NumberingState {\n private currentId = 0\n private counters: number[] = [0, 0, 0, 0, 0, 0, 0]\n private history = new Map<number, number[]>()\n\n /** 번호 문단 처리: 카운터 갱신 후 수준별 카운터 스냅샷 반환 */\n advance(numberingId: number, level: number): number[] {\n const lv = Math.min(Math.max(level, 0), 6)\n\n if (this.currentId !== numberingId) {\n if (this.currentId !== 0) this.history.set(this.currentId, [...this.counters])\n const saved = this.history.get(numberingId)\n if (saved) {\n this.counters = [...saved]\n } else {\n const prev = this.counters\n this.counters = [0, 0, 0, 0, 0, 0, 0]\n for (let i = 0; i < lv; i++) this.counters[i] = prev[i]\n }\n this.currentId = numberingId\n }\n\n this.counters[lv]++\n for (let i = lv + 1; i < 7; i++) this.counters[i] = 0\n return [...this.counters]\n }\n}\n\n// ─── 번호 포맷터 ─────────────────────────────────────\n\nexport type NumFmt =\n | \"digit\" | \"circled\" | \"romanUpper\" | \"romanLower\" | \"latinUpper\" | \"latinLower\"\n | \"ganada\" | \"circledGanada\" | \"jamo\" | \"circledJamo\" | \"hangulNum\" | \"hanjaNum\"\n\n/** HWP 표 43 (문단 머리 번호 형식 코드) → NumFmt */\nfunction headFormatToNumFmt(code: number): NumFmt {\n switch (code) {\n case 1: return \"circled\"\n case 2: return \"romanUpper\"\n case 3: return \"romanLower\"\n case 4: return \"latinUpper\"\n case 5: return \"latinLower\"\n case 8: return \"ganada\"\n case 9: return \"circledGanada\"\n case 10: return \"jamo\"\n case 11: return \"circledJamo\"\n case 12: return \"hangulNum\"\n case 13: return \"hanjaNum\"\n default: return \"digit\"\n }\n}\n\n/** HWP 표 134 (자동번호/쪽번호 모양 코드) → NumFmt */\nexport function shapeFormatToNumFmt(code: number): NumFmt {\n switch (code) {\n case 1: return \"circled\"\n case 2: return \"romanUpper\"\n case 3: return \"romanLower\"\n case 4: return \"latinUpper\"\n case 5: return \"latinLower\"\n case 6: return \"ganada\"\n case 7: return \"hangulNum\"\n case 8: return \"hanjaNum\"\n default: return \"digit\"\n }\n}\n\nconst JAMO = \"ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎ\"\nconst CIRCLED_JAMO = \"㉠㉡㉢㉣㉤㉥㉦㉧㉨㉩㉪㉫㉬㉭\"\n\nfunction fromTable(n: number, table: string): string {\n return n >= 1 && n <= table.length ? table[n - 1] : String(n)\n}\n\nfunction formatLatin(n: number, upper: boolean): string {\n if (n <= 0) return \"\"\n let result = \"\"\n let num = n\n while (num > 0) {\n num--\n result = String.fromCharCode((upper ? 65 : 97) + (num % 26)) + result\n num = Math.floor(num / 26)\n }\n return result\n}\n\n/** 한글/한자 숫자 (일이삼 / 一二三) — 만 단위까지 */\nfunction formatEastAsianNumber(n: number, digits: string[], units: string[], zero: string): string {\n if (n === 0) return zero\n if (n < 0 || n > 99999) return String(n)\n let result = \"\"\n let num = n\n let unit = 0\n while (num > 0) {\n const d = num % 10\n if (d > 0) {\n const digitStr = d === 1 && unit > 0 ? \"\" : digits[d]\n result = digitStr + units[unit] + result\n }\n num = Math.floor(num / 10)\n unit++\n }\n return result\n}\n\nconst HANGUL_DIGITS = [\"\", \"일\", \"이\", \"삼\", \"사\", \"오\", \"육\", \"칠\", \"팔\", \"구\"]\nconst HANGUL_UNITS = [\"\", \"십\", \"백\", \"천\", \"만\"]\nconst HANJA_DIGITS = [\"\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\", \"七\", \"八\", \"九\"]\nconst HANJA_UNITS = [\"\", \"十\", \"百\", \"千\", \"萬\"]\n\n/** 번호 → 문자열 (rhwp format_number 포팅 — 시퀀스 폴백은 shared/numbering 정본 규칙) */\nexport function formatNumber(n: number, fmt: NumFmt): string {\n switch (fmt) {\n case \"circled\": return n >= 1 ? circledNumber(n - 1) : String(n)\n case \"romanUpper\": return romanNumeral(n, true)\n case \"romanLower\": return romanNumeral(n, false)\n case \"latinUpper\": return formatLatin(n, true) || String(n)\n case \"latinLower\": return formatLatin(n, false) || String(n)\n case \"ganada\": return n >= 1 ? hangulOrdinal(n - 1) : String(n)\n case \"circledGanada\": return n >= 1 ? circledHangul(n - 1) : String(n)\n case \"jamo\": return fromTable(n, JAMO)\n case \"circledJamo\": return fromTable(n, CIRCLED_JAMO)\n case \"hangulNum\": return formatEastAsianNumber(n, HANGUL_DIGITS, HANGUL_UNITS, \"영\")\n case \"hanjaNum\": return formatEastAsianNumber(n, HANJA_DIGITS, HANJA_UNITS, \"零\")\n default: return String(n)\n }\n}\n\n// ─── ^N 형식 치환 ────────────────────────────────────\n\n/**\n * 번호 형식 문자열의 `^1`~`^7` 제어코드를 실제 번호로 치환.\n * (rhwp expand_numbering_format 포팅 — 시작번호 보정: counter>0이면 (start-1)+counter)\n */\nexport function expandNumberingFormat(formatStr: string, counters: number[], numbering: HwpNumbering): string {\n let result = \"\"\n let i = 0\n while (i < formatStr.length) {\n const ch = formatStr[i]\n if (ch === \"^\" && i + 1 < formatStr.length && formatStr[i + 1] >= \"1\" && formatStr[i + 1] <= \"7\") {\n const levelRef = formatStr.charCodeAt(i + 1) - 48 // '1'..'7' → 1..7\n const idx = levelRef - 1\n const counterVal = counters[idx] ?? 0\n const start = numbering.startNumbers[idx] ?? 1\n const num = counterVal > 0 ? start - 1 + counterVal : start\n result += formatNumber(num, headFormatToNumFmt(numbering.numberFormats[idx] ?? 0))\n i += 2\n continue\n }\n // 레벨 숫자가 아닌 글자(공백·기호) 앞의 ^ 는 한컴이 그리지 않는다 — HWPX para-heading 과 같은 규칙\n // (\"^ □\" → \"□\", 정책브리핑 156775690 한컴 PDF). 문자·숫자 앞은 근거가 없어 그대로 둔다\n if (ch === \"^\" && !/[\\p{L}\\p{N}]/u.test(formatStr[i + 1] ?? \"\")) {\n i++\n continue\n }\n result += ch\n i++\n }\n return result\n}\n","/**\n * 문단·셀 IR 조립 — HWP5(body.ts)·HWP3(hwp3/parser.ts) 공용.\n *\n * 두 바이너리 파서가 레코드/문자 스트림에서 뽑은 문단 글·개체 블록·좌표 셀을 HWPX 파서와 같은 IR 모양으로\n * 조립한다: 글자처럼 취급 표 앞뒤 글 분할(#49/#50), 셀 평탄화 줄 모델(#52), 머리말·각주 안 표 평탄화,\n * 좌표 셀 → builder 직접 배치(후행 빈 열 트림 계약)와 손상 표(겹친 앵커) 정리.\n */\n\nimport { buildTable, convertTableToText, MAX_COLS, MAX_ROWS } from \"../table/builder.js\"\nimport type { CellContext, IRBlock, IRTable, InlineStyle } from \"../types.js\"\nimport { CELL_EDGES, type Edges } from \"../table/layout-frames.js\"\nimport { TOC_ENTRY_BLOCKS } from \"../toc-entry.js\"\n\n/** 글자처럼 취급 표 자리 표지 — 문단 글을 표 앞뒤로 나눈다 (HWPX section-walker 와 같은 문자) */\nexport const INLINE_TABLE_MARK = \"\\x1E\"\n\n/**\n * 셀 평탄화에서 앞 줄에 공백으로 잇는 블록 — 글자처럼 취급 표와 그 뒤 조각은 한 줄이다\n * (HWPX completeTable/flush 의 lineOpen 규칙 #52). emitParagraphBlocks 가 표시하고 cellTextFromBlocks 가 읽는다\n */\nconst INLINE_JOIN = new WeakSet<IRBlock>()\n\n/** 문단에 딸린 개체 (컨트롤 순서) */\nexport interface ParaObject {\n /** 개체 파생 블록 (표·그림·글상자) */\n blocks: IRBlock[]\n /** 표 개체 — 앞 글 조각을 먼저 내보낸다 */\n table: boolean\n /** 글자처럼 취급 표 — 문단 글에 INLINE_TABLE_MARK 자리가 있다 */\n inline: boolean\n}\n\nexport interface ParaEmitInput {\n /** 필드 편집·리더 절단을 마친 문단 글 (INLINE_TABLE_MARK 포함 가능) */\n text: string\n headMarker: string | null\n /** 개요 제목 수준 (0 = 본문) */\n headingLevel: number\n /** 목차 항목(채움 탭 + 쪽 번호 줄) — 글자 크기·\"제N장\" 제목 추정에서 뺀다 (#121) */\n tocEntry?: boolean\n style?: InlineStyle\n /** 각주/미주 (\"1) 내용\") */\n footnotes: string[]\n /** 주석 안에 표가 있을 때 주석 본문 구조 블록 — IRBlock.footnoteBlocks 로 (#149, HWP5) */\n footnoteBlocks?: IRBlock[]\n objects: ParaObject[]\n pageNumber?: number\n}\n\n/** 문단 1개 → [문단 블록(들), 개체 블록] */\nexport function emitParagraphBlocks(p: ParaEmitInput): IRBlock[] {\n const { headMarker, style, footnotes, footnoteBlocks, objects, pageNumber } = p\n const blocks: IRBlock[] = []\n // 취소선·밑줄 문단(법령 개정문 삭제·개정 표시 등)은 ~~…~~ / <u>…</u> 로 방출 —\n // 대표(최빈) 스타일 기준이라 문단 전체가 그어진 경우만 잡는다 (부분 서식은 미지원)\n const decorate = (t: string): string => {\n let deco = style?.strike ? `~~${t}~~` : t\n if (style?.underline) deco = `<u>${deco}</u>`\n return deco\n }\n\n if (p.text.includes(INLINE_TABLE_MARK)) {\n // 글자처럼 취급 표가 있는 문단 — 표 앞 조각을 표 직전에 방출해 원문 순서를 지킨다(HWPX walkParagraphChildren\n // onTbl 대칭: 떠 있는 표도 앞 조각을 먼저 내고, 그리기 개체는 조각을 당기지 않는다). 조각은 본문 문단\n // (개요 제목 승격 없음 — HWPX 와 같다), 문단 머리표는 첫 글 조각에, 스타일·각주는 첫 블록에\n const segments = p.text.split(INLINE_TABLE_MARK)\n let segIdx = 0\n let first = true\n let lineOpen = false\n let markerPending = !!headMarker\n const flush = (): void => {\n if (segIdx >= segments.length) return\n const s = segments[segIdx++].replace(/\\$\\$/g, \"$ $\").trim()\n if (!s) return\n let t = decorate(s)\n if (markerPending) { t = `${headMarker} ${t}`; markerPending = false }\n const block: IRBlock = { type: \"paragraph\", text: t, pageNumber }\n if (first) {\n if (style) block.style = style\n if (footnotes.length > 0) block.footnoteText = footnotes.join(\"; \")\n if (footnoteBlocks) block.footnoteBlocks = footnoteBlocks\n first = false\n }\n if (lineOpen) INLINE_JOIN.add(block)\n lineOpen = true\n blocks.push(block)\n }\n for (const obj of objects) {\n if (obj.table) {\n flush()\n if (obj.inline && lineOpen) for (const b of obj.blocks) INLINE_JOIN.add(b)\n lineOpen = obj.inline\n }\n blocks.push(...obj.blocks)\n }\n while (segIdx < segments.length) flush()\n // 글 조각이 하나도 없는 각주 anchor — 각주 내용 자체를 문단으로 보존 (아래 단일 문단 경로와 같다)\n if (first && footnotes.length > 0) blocks.unshift({ type: \"paragraph\", text: `(주: ${footnotes.join(\"; \")})`, pageNumber })\n return blocks\n }\n\n const trimmed = p.text.replace(/\\$\\$/g, \"$ $\").trim()\n if (trimmed) {\n const block: IRBlock = {\n type: p.headingLevel > 0 ? \"heading\" : \"paragraph\",\n text: headMarker ? `${headMarker} ${trimmed}` : trimmed,\n pageNumber,\n }\n if (p.headingLevel > 0) block.level = p.headingLevel\n if (p.tocEntry) TOC_ENTRY_BLOCKS.add(block)\n if (style) {\n block.style = style\n if (style.strike || style.underline) block.text = headMarker ? `${headMarker} ${decorate(trimmed)}` : decorate(trimmed)\n }\n if (footnotes.length > 0) block.footnoteText = footnotes.join(\"; \")\n if (footnoteBlocks) block.footnoteBlocks = footnoteBlocks\n blocks.push(block)\n } else if (footnotes.length > 0) {\n // 본문 없는 각주 anchor — 각주 내용 자체를 문단으로 보존\n blocks.push({ type: \"paragraph\", text: `(주: ${footnotes.join(\"; \")})`, pageNumber })\n }\n for (const obj of objects) blocks.push(...obj.blocks)\n return blocks\n}\n\n// ─── 평문 평탄화 ─────────────────────────────────────\n\n/**\n * 표 → 평문 — 셀은 \" / \", 행은 줄바꿈(convertTableToText), 캡션 먼저. HWPX completeTable·buildSubListTable 과 같은 모양.\n * 셀 이미지 sentinel(\"![image](hwp5bin:N)\")은 남긴다 — images.ts 가 블록 트리 전체에서 추출 파일명으로 편다\n * (HWPX 도 머리말 표 이미지 셀을 \"![image](…)\" 로 남긴다). 종전엔 머리말·각주의 표를 건너뛰어 표 글이 통째로 사라졌다\n */\nexport function tableFlatText(table: IRTable): string {\n const flat = convertTableToText(table.cells)\n return table.caption ? table.caption + (flat ? \"\\n\" + flat : \"\") : flat\n}\n\n/** 블록 리스트 → 평문 (각주 인라인 포함, 표는 평탄화, 이미지는 제외) — 머리말·각주·캡션용 */\nexport function blocksPlainText(blocks: IRBlock[], sep: string): string {\n const parts: string[] = []\n for (const b of blocks) {\n if (b.type === \"image\") continue\n if (b.type === \"table\") {\n const flat = b.table ? tableFlatText(b.table) : \"\"\n if (flat) parts.push(flat)\n continue\n }\n if (b.text) {\n let t = b.text\n if (b.footnoteText) t += ` (주: ${b.footnoteText})`\n parts.push(t)\n }\n }\n return parts.join(sep).trim()\n}\n\n/**\n * 셀 문단 블록 → 하위 호환 셀 텍스트 (문단 평탄화 + 이미지 표지 + 중첩표 평문).\n * 글자처럼 취급 표와 그 뒤 조각은 앞 줄에 공백으로 잇는다(INLINE_JOIN). 셀 문단의 각주는 문단 글에 접어 넣는다 —\n * HWPX 셀 블록과 같은 IR(블록 text 에 \"(주: …)\"); footnoteText 로 따로 두면 병합 셀 HTML 경로(blocks 직렬화)가\n * 각주를 버렸다. hasStructure = 셀에 blocks 를 달 구조(이미지·중첩표)가 있는가\n */\nexport function cellTextFromBlocks(blocks: IRBlock[]): { text: string; hasStructure: boolean } {\n let text = \"\"\n const add = (part: string, b: IRBlock): void => { text += (text ? (INLINE_JOIN.has(b) ? \" \" : \"\\n\") : \"\") + part }\n let hasStructure = false\n for (const b of blocks) {\n if (b.type === \"image\" && b.text) {\n add(`![image](hwp5bin:${b.text})`, b)\n hasStructure = true\n } else if (b.type === \"table\" && b.table) {\n // flattenLayoutTables 경유 시를 위한 평문 — 구조는 blocks가 보존\n const flat = tableFlatText(b.table)\n if (flat) add(flat, b)\n hasStructure = true\n } else if (b.text) {\n if (b.footnoteText) {\n b.text += ` (주: ${b.footnoteText})`\n delete b.footnoteText\n delete b.footnoteBlocks\n }\n add(b.text, b)\n }\n }\n return { text, hasStructure }\n}\n\n// ─── 좌표 셀 → IRTable ──────────────────────────────\n\n/** 좌표를 가진 셀 (HWP5 LIST_HEADER colAddr/rowAddr, HWP3 셀 기하에서 복원한 좌표) */\nexport interface AddressedCell extends CellContext {\n blocks?: IRBlock[]\n isHeader?: boolean\n /** 칸의 보이는 변 (셀 borderFillId → DocInfo BORDER_FILL) — IR 칸의 CELL_EDGES 로 */\n edges?: Edges\n}\n\n/**\n * 좌표 셀 겹침 정리 (손상 파일) — 먼저 나온 셀이 칸을 차지한다. 앵커가 앞 셀 영역에 떨어진 셀은 글·구조를\n * 앞 셀에 이어 붙이고(한컴은 겹쳐 그릴 뿐 글을 버리지 않는다), 앞 셀 영역을 덮는 병합은 겹치지 않을 때까지\n * 줄인다. builder 직접 배치는 뒤 셀이 앞 앵커를 덮어써 글이 사라진다. 정상 표는 입력 그대로(같은 객체) 통과\n */\nfunction resolveCellOverlaps<T extends AddressedCell>(cells: T[], rows: number, cols: number): T[] {\n const owner = new Map<number, T>()\n const out: T[] = []\n for (const cell of cells) {\n const r0 = cell.rowAddr ?? 0, c0 = cell.colAddr ?? 0\n const hit = owner.get(r0 * cols + c0)\n if (hit) {\n if (cell.blocks?.length) {\n hit.blocks = [...(hit.blocks ?? (hit.text ? [{ type: \"paragraph\" as const, text: hit.text }] : [])), ...cell.blocks]\n }\n if (cell.text.trim()) hit.text = hit.text.trim() ? `${hit.text}\\n${cell.text}` : cell.text\n continue\n }\n // 첫 행에서 먼저 차지된 열 앞까지, 그 폭으로 먼저 차지된 행 앞까지 줄인다(표 안 칸만 한 번씩 훑는다).\n // 겹침이 없으면 span 을 건드리지 않는다 — 표 밖으로 뻗은 span 도 종전대로 builder 에 맡긴다\n const csIn = Math.max(1, Math.min(cell.colSpan, cols - c0))\n let cs = cell.colSpan\n for (let c = c0 + 1; c < c0 + csIn; c++) if (owner.has(r0 * cols + c)) { cs = c - c0; break }\n const rsIn = Math.max(1, Math.min(cell.rowSpan, rows - r0))\n let rs = cell.rowSpan\n scan: for (let r = r0 + 1; r < r0 + rsIn; r++) {\n for (let c = c0; c < c0 + Math.min(cs, csIn); c++) if (owner.has(r * cols + c)) { rs = r - r0; break scan }\n }\n const placed = cs === cell.colSpan && rs === cell.rowSpan ? cell : { ...cell, colSpan: cs, rowSpan: rs }\n for (let r = r0; r < Math.min(r0 + rs, rows); r++) for (let c = c0; c < Math.min(c0 + cs, cols); c++) owner.set(r * cols + c, placed)\n out.push(placed)\n }\n return out\n}\n\n/**\n * 좌표 셀 → IRTable — HWPX(table-build.ts)와 같은 builder 직접 배치(buildTableDirect)를 태워 표 계약\n * (후행 빈 열 트림 + 잘린 열에 걸친 span 절단, keepAnchoredEmptyCols 면 앵커 열 보존)을 맞춘다. HWP5 종전 경로는\n * 자체 그리드를 그대로 IRTable 로 내 빈 입력란 열이 남았다 — 같은 문서 HWPX 보다 1~9열 넓음(서식 표 300+ 실측).\n * 행 묶음은 rowAddr 기준(HWPX <tr> 과 같은 경계), 셀 blocks·제목 셀은 좌표로 재부착.\n * 손상 레코드(행·열 0, 표 밖 앵커)는 표를 버리지 않고 셀 좌표까지 넓힌다 — 글 손실 금지\n */\nexport function buildAddressedTable(cells: AddressedCell[], rows: number, cols: number, keepAnchoredEmptyCols?: boolean): IRTable | null {\n for (const c of cells) {\n rows = Math.max(rows, Math.min((c.rowAddr ?? 0) + 1, MAX_ROWS))\n cols = Math.max(cols, Math.min((c.colAddr ?? 0) + 1, MAX_COLS))\n }\n const placed = resolveCellOverlaps(cells, rows, cols)\n const byRow: AddressedCell[][] = Array.from({ length: rows }, () => [])\n for (const c of placed) {\n const r = c.rowAddr ?? 0\n if (r < rows && (c.colAddr ?? 0) < cols) byRow[r].push(c)\n }\n const table = buildTable(byRow, { keepAnchoredEmptyCols })\n if (table.rows === 0) return null\n for (const c of placed) {\n // 보이는 변은 글 대조 없이 좌표 자리 칸에 — 빈 칸도 테두리를 가진다\n if (c.edges) {\n const at = table.cells[c.rowAddr ?? 0]?.[c.colAddr ?? 0]\n if (at) CELL_EDGES.set(at, c.edges)\n }\n if (!c.blocks?.length && !c.isHeader) continue\n const target = table.cells[c.rowAddr ?? 0]?.[c.colAddr ?? 0]\n // 겹친 앵커로 합쳐진 셀·잘린 열의 앵커는 텍스트가 달라 붙지 않는다\n if (!target || target.text !== c.text.trim()) continue\n if (c.blocks?.length) target.blocks = c.blocks\n if (c.isHeader) target.isHeader = true\n }\n return table\n}\n","/** HWP 5.x 본문 파서 — 섹션 레코드 → 문단 리스트·컨트롤 디스패치(표·그리기 개체·수식·각주·머리말·필드) → IRBlock */\n\nimport { tidyScriptTags, type ScriptKind } from \"../script-tags.js\"\nimport {\n extractEquationText, createParaTextState, appendParaText, LITERAL_DOLLAR_MARK, LITERAL_LT_MARK, resolveLiteralLt, TAG_PARA_HEADER, TAG_PARA_TEXT, TAG_CHAR_SHAPE,\n TAG_CTRL_HEADER, TAG_LIST_HEADER, TAG_TABLE, TAG_EQEDIT, TAG_SHAPE_COMPONENT, TAG_SHAPE_COMPONENT_CONTAINER,\n TAG_SHAPE_COMPONENT_PICTURE, type HwpRecord, type HwpDocInfo, type IndexedControlResolver,\n} from \"./record.js\"\nimport { NumberingState, expandNumberingFormat, formatNumber, shapeFormatToNumFmt } from \"./numbering.js\"\nimport { hwpEquationToLatex } from \"./equation.js\"\nimport { buildTable, flattenLayoutTables, markNonLayoutTable, MAX_COLS, MAX_ROWS } from \"../table/builder.js\"\nimport {\n INLINE_TABLE_MARK, blocksPlainText, buildAddressedTable, cellTextFromBlocks, emitParagraphBlocks,\n} from \"./ir-assemble.js\"\nimport type { CellContext, IRBlock, IRTable, ParseOptions, ParseWarning, InlineStyle } from \"../types.js\"\nimport type { Edges } from \"../table/layout-frames.js\"\nimport { sanitizeHref } from \"../utils.js\"\nimport { takeTocLeaders } from \"../toc-entry.js\"\nimport { composeText } from \"../shared/pua.js\"\n\n/** 중첩표/글상자 재귀 깊이 상한 — 표 \"중첩 단계\" 기준.\n * 실무 문서 중첩은 2~3단이라 8이면 충분하며, 바이너리 파싱 비용상\n * filler/소스맵(16)보다 보수적으로 둔다. hwpx MAX_XML_DEPTH(200)는\n * XML 요소 깊이라 좌표계가 다름 — 상수 통일 대상 아님 */\nconst MAX_NEST_DEPTH = 8\n\n// ─── 컨트롤 ID (u32 LE 정규화) ───────────────────────\n// HWP는 ctrl_id를 DWORD(LE)로 저장한다. \"tbl \"은 파일에 [0x20,0x6c,0x62,0x74](\" lbt\")로\n// 기록되므로, readUInt32LE로 읽으면 BE 문자열 상수 0x74626c20과 일치한다 (rhwp tags.rs 방식).\n\n/** 4바이트 ASCII 문자열 → u32 컨트롤 ID 상수 (\"tbl \" → 0x74626c20) */\nfunction cid(s: string): number {\n return ((s.charCodeAt(0) << 24) | (s.charCodeAt(1) << 16) | (s.charCodeAt(2) << 8) | s.charCodeAt(3)) >>> 0\n}\n\nconst CTRL_TBL = cid(\"tbl \") // 표\nconst CTRL_GSO = cid(\"gso \") // 그리기 개체 (그림/글상자)\nconst CTRL_EQED = cid(\"eqed\") // 수식\nconst CTRL_HEAD = cid(\"head\") // 머리말\nconst CTRL_FOOT = cid(\"foot\") // 꼬리말\nconst CTRL_FN = cid(\"fn \") // 각주\nconst CTRL_EN = cid(\"en \") // 미주\nconst CTRL_ATNO = cid(\"atno\") // 자동 번호\nconst CTRL_NWNO = cid(\"nwno\") // 새 번호\nconst CTRL_PGNP = cid(\"pgnp\") // 쪽 번호 위치\nconst CTRL_PGHD = cid(\"pghd\") // 감추기\nconst CTRL_IDXM = cid(\"idxm\") // 찾아보기 표식\nconst CTRL_BOKM = cid(\"bokm\") // 책갈피\nconst CTRL_TCPS = cid(\"tcps\") // 글자 겹침\nconst CTRL_TDUT = cid(\"tdut\") // 덧말\nconst CTRL_TCMT = cid(\"tcmt\") // 숨은 설명\nconst CTRL_SECD = cid(\"secd\") // 구역 정의\nconst CTRL_COLD = cid(\"cold\") // 단 정의\nconst CTRL_FORM = cid(\"form\") // 양식 개체\nconst CTRL_OLE = cid(\"ole \") // OLE 개체\nconst FIELD_HLK = cid(\"%hlk\") // 필드: 하이퍼링크\nconst FIELD_CLK = cid(\"%clk\") // 필드: 누름틀\n\nconst KNOWN_CTRL_IDS = new Set([\n CTRL_TBL, CTRL_GSO, CTRL_EQED, CTRL_HEAD, CTRL_FOOT, CTRL_FN, CTRL_EN,\n CTRL_ATNO, CTRL_NWNO, CTRL_PGNP, CTRL_PGHD, CTRL_IDXM, CTRL_BOKM,\n CTRL_TCPS, CTRL_TDUT, CTRL_TCMT, CTRL_SECD, CTRL_COLD, CTRL_FORM, CTRL_OLE,\n])\n\n/** 필드 컨트롤 여부 (첫 바이트 '%') */\nfunction isFieldCtrlId(id: number): boolean {\n return (id >>> 24) === 0x25\n}\n\n/** 바이트 순서 뒤집기 — 비표준 작성기의 BE 저장 ctrl_id 방어 */\nfunction swap32(id: number): number {\n return (((id & 0xff) << 24) | (((id >>> 8) & 0xff) << 16) | (((id >>> 16) & 0xff) << 8) | ((id >>> 24) & 0xff)) >>> 0\n}\n\n/** LE로 읽은 ctrl_id를 정규화 — 알려진 ID/필드가 아니고 스왑하면 일치할 때만 스왑 */\nfunction normalizeCtrlId(raw: number): number {\n if (KNOWN_CTRL_IDS.has(raw) || isFieldCtrlId(raw)) return raw\n const sw = swap32(raw)\n if (KNOWN_CTRL_IDS.has(sw) || isFieldCtrlId(sw)) return sw\n return raw\n}\n\n// ─── 수식 ────────────────────────────────────────────\n\nfunction formatEquationForMarkdown(equation: string): string {\n const normalized = hwpEquationToLatex(equation)\n if (!normalized) return \"\"\n return `$${normalized.replace(/\\$/g, \"\\\\$\")}$`\n}\n\n/** 컨트롤 자식 레코드 범위에서 EQEDIT 수식 추출 */\nfunction extractEquationFromSlice(records: HwpRecord[], start: number, end: number): string | null {\n for (let i = start; i < end; i++) {\n if (records[i].tagId !== TAG_EQEDIT) continue\n const equation = extractEquationText(records[i].data)\n return equation ? formatEquationForMarkdown(equation) : null\n }\n return null\n}\n\n// ─── 본문 파싱 (문단 리스트 + 컨트롤 디스패치) ───────\n\n/** 문서 전역 파싱 상태 — 섹션 간 유지 (번호 카운터, 머리말/꼬리말 등) */\nexport interface Hwp5DocState {\n numbering: NumberingState\n /** 구역 정의(secd)의 개요 번호 ID */\n outlineNumberingId: number\n /** 자동 번호 종류(0=쪽,1=각주,2=미주,3=그림,4=표,5=수식)별 다음 번호 */\n autoCounters: Map<number, number>\n headerTexts: Set<string>\n /** 목차 항목 글 — 표 칸에서 풀려 나온 문단도 제목 추정에서 뺀다 (#121, HWPX SectionShared.tocTexts 와 같은 구실) */\n tocTexts: Set<string>\n headerBlocks: IRBlock[]\n footerBlocks: IRBlock[]\n /** 표 후행 빈 열(앵커 있는 입력란) 보존 — ParseOptions.keepTrailingEmptyCols (#47) */\n keepTrailingEmptyCols?: boolean\n /** 미기입 누름틀 안내문도 본문에 — ParseOptions.includeFieldPlaceholders (#92) */\n includeFieldPlaceholders?: boolean\n}\n\nexport function createHwp5DocState(): Hwp5DocState {\n return {\n numbering: new NumberingState(),\n outlineNumberingId: 0,\n autoCounters: new Map(),\n headerTexts: new Set(),\n tocTexts: new Set(),\n headerBlocks: [],\n footerBlocks: [],\n }\n}\n\ninterface Hwp5Ctx {\n docInfo: HwpDocInfo | null\n warnings: ParseWarning[]\n sectionNum: number\n doc: Hwp5DocState\n depth: number\n /** 현재 페이지 (#66) — layout 모드에서 top-level 문단마다 갱신, 셀/중첩은 호스트 상속.\n * 섹션 근사 모드에선 sectionNum 고정 */\n page: number\n /** 프리패스 페이지 맵 — base: 이전 섹션 누적 페이지, pageAtPara: top-level 문단 순번별 페이지 */\n pageMap?: { base: number; pageAtPara: number[] }\n /** 지금까지 만난 top-level 문단 수 (pageAtPara 인덱스) */\n topOrdinal: number\n /** 표 CTRL_HEADER 레코드 인덱스 → sourceId (table-ids.ts 프리패스, 렌더 region 조인 키 #76) */\n tableIds?: Map<number, string>\n}\n\n/** 섹션 레코드 → IRBlock[] (테스트에서 직접 사용 가능하도록 export) */\nexport function parseSection(\n records: HwpRecord[],\n docInfo: HwpDocInfo | null,\n warnings: ParseWarning[],\n sectionNum: number,\n doc?: Hwp5DocState,\n pageMap?: { base: number; pageAtPara: number[] },\n tableIds?: Map<number, string>,\n): IRBlock[] {\n const ctx: Hwp5Ctx = {\n docInfo, warnings, sectionNum, doc: doc ?? createHwp5DocState(), depth: 0,\n page: pageMap ? pageMap.base + 1 : sectionNum, pageMap, topOrdinal: 0, tableIds,\n }\n return parseParagraphList(records, 0, records.length, ctx)\n}\n\n/**\n * 레코드 범위에서 문단 리스트 파싱 (rhwp body_text.rs parse_paragraph_list 패턴).\n * 표 셀/글상자/머리말/각주 내부에서도 동일하게 재귀 사용된다.\n */\nfunction parseParagraphList(records: HwpRecord[], start: number, end: number, ctx: Hwp5Ctx): IRBlock[] {\n const blocks: IRBlock[] = []\n let i = start\n while (i < end) {\n if (records[i].tagId === TAG_PARA_HEADER) {\n const baseLevel = records[i].level\n // 실제 페이지 갱신 (#66) — 프리패스의 top-level 문단 열거와 같은 순서(level 0)\n if (baseLevel === 0 && ctx.depth === 0 && ctx.pageMap) {\n const pg = ctx.pageMap.pageAtPara[ctx.topOrdinal]\n if (pg !== undefined) ctx.page = ctx.pageMap.base + pg + 1\n ctx.topOrdinal++\n }\n let j = i + 1\n while (j < end && records[j].level > baseLevel) j++\n blocks.push(...parseParagraph(records, i, j, ctx))\n i = j\n } else {\n i++\n }\n }\n return blocks\n}\n\n/** 문단 내 CTRL_HEADER 1개의 파싱 상태 */\ninterface ParsedCtrl {\n /** 정규화된 컨트롤 ID (u32, BE 문자열 상수와 비교 가능) */\n id: number\n /** LE로 읽은 원본 ID — PARA_TEXT 인라인 컨트롤과의 대조용 */\n idRaw: number\n /** CTRL_HEADER 레코드 데이터 (ctrl_id 4바이트 포함) */\n data: Buffer\n childStart: number\n childEnd: number\n /** 인라인 치환 텍스트 (수식/자동번호/각주 마커) */\n inlineText?: string\n /** 문단 뒤에 붙는 블록 (표/이미지/글상자) */\n afterBlocks?: IRBlock[]\n /** 각주/미주 내용 (\"1) 내용\" 형식) */\n footnote?: string\n /** 각주/미주 본문 블록(머리 번호 포함, 그림 제외) — 주석 안 표를 IRBlock.footnoteBlocks 로 (#149) */\n noteBlocks?: IRBlock[]\n /** 주석 본문에 표가 있는가 */\n noteHasTable?: boolean\n /** 하이퍼링크 URL (%hlk) */\n href?: string\n /** 미기입 누름틀(%clk, 속성 bit 15 = 0)의 안내문 — 본문 run 에 같은 글이 있으면 값이 아니다 */\n guide?: string\n /** resolver 중복 매칭 방지 */\n resolved?: boolean\n}\n\n/** 문단 1개 파싱 → [문단 블록?, ...컨트롤 파생 블록] */\nfunction parseParagraph(records: HwpRecord[], start: number, end: number, ctx: Hwp5Ctx): IRBlock[] {\n const header = records[start]\n const baseLevel = header.level\n const paraShapeId = header.data.length >= 10 ? header.data.readUInt16LE(8) : -1\n\n const textRecords: Buffer[] = []\n const charShapeIds: number[] = []\n /** 글자 모양 위치표 [WCHAR 위치, charShapeId] — 첨자 판정 */\n const charShapeRuns: Array<[number, number]> = []\n const ctrls: ParsedCtrl[] = []\n\n let i = start + 1\n while (i < end) {\n const rec = records[i]\n\n if (rec.tagId === TAG_CTRL_HEADER && rec.level === baseLevel + 1 && rec.data.length >= 4) {\n // 컨트롤 자식 레코드 범위 수집 (rhwp parse_paragraph 패턴)\n const childStart = i + 1\n let j = childStart\n while (j < end && records[j].level > baseLevel + 1) j++\n const idRaw = rec.data.readUInt32LE(0)\n ctrls.push({ id: normalizeCtrlId(idRaw), idRaw, data: rec.data, childStart, childEnd: j })\n i = j\n continue\n }\n\n if (rec.tagId === TAG_PARA_TEXT && rec.level === baseLevel + 1) {\n textRecords.push(rec.data)\n } else if (rec.tagId === TAG_CHAR_SHAPE && rec.level === baseLevel + 1 && rec.data.length >= 8) {\n // 구조: [position(u32) + charShapeId(u32)] * N\n for (let offset = 0; offset + 7 < rec.data.length; offset += 8) {\n charShapeIds.push(rec.data.readUInt32LE(offset + 4))\n charShapeRuns.push([rec.data.readUInt32LE(offset), rec.data.readUInt32LE(offset + 4)])\n }\n }\n i++\n }\n\n // 컨트롤별 효과 계산 (인라인 치환/파생 블록/각주/링크)\n for (const ctrl of ctrls) {\n applyCtrlEffect(ctrl, records, ctx)\n // 글자처럼 취급 표는 문단 글 흐름 안의 자리 — 표지를 심어 앞뒤 글을 나눈다 (#49/#50 HWPX 대칭)\n if (ctrl.id === CTRL_TBL && ctrl.afterBlocks && ctrl.data.length >= 8 && (ctrl.data.readUInt32LE(4) & 1)) {\n ctrl.inlineText = INLINE_TABLE_MARK\n }\n }\n\n // 텍스트 렌더링 — 확장 컨트롤 인덱스 ↔ CTRL_HEADER 순서 매핑\n const state = createParaTextState()\n state.dollarMark = true\n state.tocLeaders = true\n state.scriptAt = scriptLookup(charShapeRuns, ctx.docInfo)\n const resolver: IndexedControlResolver = (idx, id) => {\n let ctrl = idx >= 0 && idx < ctrls.length ? ctrls[idx] : undefined\n if (!ctrl || (ctrl.idRaw !== id && ctrl.id !== id)) {\n ctrl = ctrls.find(c => !c.resolved && (c.idRaw === id || c.id === id))\n }\n if (!ctrl) return null\n ctrl.resolved = true\n return ctrl.inlineText ?? null\n }\n for (const data of textRecords) {\n appendParaText(state, data, resolver)\n }\n\n // FIELD_BEGIN/END 범위 — 시작 위치 내림차순으로 안전하게 치환. 하이퍼링크는 [anchor](url),\n // 미기입 누름틀의 안내문 run 은 지운다(한컴은 화면에만 흐리게 보이고 인쇄하지 않는다 — PDF 실측)\n let text = state.text\n if (state.fieldRanges.length > 0) {\n const ranges = [...state.fieldRanges].sort((a, b) => b.start - a.start)\n const applied: Array<[number, number]> = []\n for (const r of ranges) {\n const ctrl = ctrls[r.ctrlIdx]\n if (!ctrl || r.end <= r.start) continue\n if (applied.some(([s, e]) => r.start < e && r.end > s)) continue\n const anchor = text.slice(r.start, r.end)\n if (ctrl.guide !== undefined) {\n if (ctx.doc.includeFieldPlaceholders) continue\n const plain = anchor.replaceAll(LITERAL_DOLLAR_MARK, \"$\").replaceAll(LITERAL_LT_MARK, \"<\") // 안내문 원문과 맞댄다\n if (plain === ctrl.guide || plain.trimEnd() === ctrl.guide) {\n text = text.slice(0, r.start) + text.slice(r.end)\n applied.push([r.start, r.end])\n }\n continue\n }\n if (!ctrl.href) continue\n const href = sanitizeHref(ctrl.href)\n if (!href) continue\n if (!anchor.trim() || anchor.includes(INLINE_TABLE_MARK)) continue\n text = text.slice(0, r.start) + `[${anchor}](${href})` + text.slice(r.end)\n applied.push([r.start, r.end])\n }\n }\n // 리터럴 $ → \\$ (필드 위치를 다 쓴 뒤라 이제 두 글자로 늘려도 된다, escapeLiteralDollar 규약)\n if (text.includes(LITERAL_DOLLAR_MARK)) text = text.replaceAll(LITERAL_DOLLAR_MARK, \"\\\\$\")\n text = resolveLiteralLt(text)\n // 글자마다 여닫은 첨자 태그 정리 — HWPX section-walker 와 같은 꼴로\n text = tidyScriptTags(text)\n // 목차 항목(채움 탭 + 쪽 번호 줄) 판정 — 채움 탭 표지는 여기서 보통 탭이 된다 (#121, HWPX 와 같은 규칙)\n const toc = takeTocLeaders(text)\n text = toc.text\n\n // 문단번호/글머리표/개요 처리 (DocInfo PARA_SHAPE headType)\n let headingLevel = 0\n let headMarker: string | null = null\n const ps = ctx.docInfo && paraShapeId >= 0 && paraShapeId < ctx.docInfo.paraShapes.length\n ? ctx.docInfo.paraShapes[paraShapeId]\n : null\n if (ps && ps.headType > 0) {\n if (ps.headType === 1) {\n // 개요 — paraLevel 0-6 → heading 1-6 (개요 7수준은 H6로 클램프). 목차 항목은 개요 문단 모양을 빌려도 제목이 아니다\n if (!toc.tocEntry) headingLevel = Math.min(ps.paraLevel + 1, 6)\n }\n if (ps.headType === 1 || ps.headType === 2) {\n // 개요/번호 → NUMBERING 카운터 전진 + ^N 치환\n const nid = ps.numberingId || (ps.headType === 1 ? ctx.doc.outlineNumberingId : 0)\n const numbering = nid >= 1 ? ctx.docInfo?.numberings[nid - 1] : undefined\n if (numbering) {\n const counters = ctx.doc.numbering.advance(nid, ps.paraLevel)\n const fmt = numbering.levelFormats[Math.min(ps.paraLevel, 6)]\n if (fmt) {\n const headText = expandNumberingFormat(fmt, counters, numbering)\n if (headText) headMarker = headText\n }\n }\n } else if (ps.headType === 3) {\n // 글머리표 — U+FFFF는 이미지 글머리표 (문자 렌더링 불가)\n const bullet = ps.numberingId >= 1 ? ctx.docInfo?.bullets[ps.numberingId - 1] : undefined\n if (bullet && bullet.char !== \"￿\") headMarker = bullet.char\n }\n }\n\n if (toc.tocEntry) for (const line of text.split(\"\\n\")) if (line.trim()) {\n ctx.doc.tocTexts.add(line.trim())\n if (headMarker) ctx.doc.tocTexts.add(`${headMarker} ${line.trim()}`)\n }\n return emitParagraphBlocks({\n text,\n headMarker,\n headingLevel,\n tocEntry: toc.tocEntry,\n style: ctx.docInfo && charShapeIds.length > 0 ? resolveCharStyle(charShapeIds, ctx.docInfo) : undefined,\n footnotes: ctrls.filter(c => c.footnote).map(c => c.footnote!),\n footnoteBlocks: ctrls.some(c => c.noteHasTable) ? ctrls.flatMap(c => c.footnote ? c.noteBlocks ?? [] : []) : undefined,\n // 컨트롤 파생 블록 (표/이미지/글상자) — 컨트롤 순서대로\n objects: ctrls.filter(c => c.afterBlocks).map(c => ({ blocks: c.afterBlocks!, table: c.id === CTRL_TBL, inline: c.inlineText === INLINE_TABLE_MARK })),\n pageNumber: ctx.page,\n })\n}\n\n/** 컨트롤 종류별 디스패치 (rhwp control.rs parse_control 대응) */\nfunction applyCtrlEffect(ctrl: ParsedCtrl, records: HwpRecord[], ctx: Hwp5Ctx): void {\n switch (ctrl.id) {\n case CTRL_TBL: {\n const table = parseTableControl(ctrl, records, ctx)\n if (table) ctrl.afterBlocks = [{ type: \"table\", table, pageNumber: ctx.page }]\n return\n }\n case CTRL_GSO: {\n const blocks = parseGsoControl(ctrl, records, ctx)\n if (blocks.length > 0) ctrl.afterBlocks = blocks\n return\n }\n case CTRL_EQED: {\n const eq = extractEquationFromSlice(records, ctrl.childStart, ctrl.childEnd)\n if (eq) ctrl.inlineText = eq\n return\n }\n case CTRL_FN:\n case CTRL_EN: {\n applyNoteEffect(ctrl, records, ctx, ctrl.id === CTRL_FN ? 1 : 2)\n return\n }\n case CTRL_HEAD:\n case CTRL_FOOT: {\n applyHeaderFooterEffect(ctrl, records, ctx, ctrl.id === CTRL_HEAD)\n return\n }\n case CTRL_ATNO: {\n // 자동 번호 (표 144): attr(u32) + number(u16) + 사용자기호 + 앞장식 + 뒤장식 (WCHAR)\n if (ctrl.data.length >= 8) {\n const attr = ctrl.data.readUInt32LE(4)\n const type = attr & 0x0f\n const format = (attr >>> 4) & 0xff\n const num = ctx.doc.autoCounters.get(type) ?? 1\n ctx.doc.autoCounters.set(type, num + 1)\n const prefix = ctrl.data.length >= 14 ? wcharAt(ctrl.data, 12) : \"\"\n const suffix = ctrl.data.length >= 16 ? wcharAt(ctrl.data, 14) : \"\"\n ctrl.inlineText = `${prefix}${formatNumber(num, shapeFormatToNumFmt(format))}${suffix}`\n }\n return\n }\n case CTRL_NWNO: {\n // 새 번호 지정 — 해당 종류의 카운터를 재설정 (표시 없음)\n if (ctrl.data.length >= 10) {\n const attr = ctrl.data.readUInt32LE(4)\n const type = attr & 0x0f\n const num = ctrl.data.readUInt16LE(8)\n if (num > 0) ctx.doc.autoCounters.set(type, num)\n }\n return\n }\n case CTRL_SECD: {\n // 구역 정의 — 개요 번호 ID (ctrl_id 4 + flags 4 + 간격 2*3 + tab 4 = offset 18)\n if (ctrl.data.length >= 20) {\n ctx.doc.outlineNumberingId = ctrl.data.readUInt16LE(18)\n }\n return\n }\n case CTRL_OLE: {\n ctx.warnings.push({ page: ctx.page, message: \"스킵된 OLE 개체\", code: \"SKIPPED_OLE\" })\n return\n }\n // 글자 겹침 — ctrl id 뒤 글자 수(WORD)·겹친 글자(WCHAR[n])·테두리 종류(BYTE, 0 = 없음). 종전엔 건너뛰어 법령 서식 원 번호(⑯·⑰)가 빠졌다\n case CTRL_TCPS: {\n const d = ctrl.data, n = d.length >= 6 ? d.readUInt16LE(4) : 0\n if (n > 0 && d.length >= 6 + 2 * n) ctrl.inlineText = composeText(d.toString(\"utf16le\", 6, 6 + 2 * n), (d[6 + 2 * n] ?? 0) !== 0)\n return\n }\n // 숨은 설명/단 정의/쪽번호 위치/감추기/찾아보기/책갈피/덧말 — 본문 텍스트 없음 또는 의도적 스킵\n case CTRL_TCMT:\n case CTRL_COLD:\n case CTRL_PGNP:\n case CTRL_PGHD:\n case CTRL_IDXM:\n case CTRL_BOKM:\n case CTRL_TDUT:\n case CTRL_FORM:\n return\n default: {\n if (isFieldCtrlId(ctrl.id)) {\n applyFieldEffect(ctrl)\n return\n }\n // 알 수 없는 컨트롤 — LIST_HEADER 문단 리스트가 있으면 텍스트 보존 (정보손실 방지)\n const blocks = parseListHeaderParagraphs(ctrl, records, ctx)\n if (blocks.length > 0) ctrl.afterBlocks = blocks\n }\n }\n}\n\n/** WCHAR 1글자 읽기 (0이면 빈 문자열) */\nfunction wcharAt(data: Buffer, offset: number): string {\n const code = data.readUInt16LE(offset)\n return code > 0 ? String.fromCharCode(code) : \"\"\n}\n\n/** 컨트롤 자식에서 첫 LIST_HEADER 이후의 문단 리스트 파싱 (rhwp find_list_header_paragraphs) */\nfunction parseListHeaderParagraphs(ctrl: ParsedCtrl, records: HwpRecord[], ctx: Hwp5Ctx): IRBlock[] {\n if (ctx.depth >= MAX_NEST_DEPTH) return []\n for (let i = ctrl.childStart; i < ctrl.childEnd; i++) {\n if (records[i].tagId === TAG_LIST_HEADER) {\n return parseParagraphList(records, i + 1, ctrl.childEnd, { ...ctx, depth: ctx.depth + 1 })\n }\n }\n return []\n}\n\n/** 각주('fn ')/미주('en ') — 번호 + 장식문자 + 내용 (rhwp parse_footnote_control) */\nfunction applyNoteEffect(ctrl: ParsedCtrl, records: HwpRecord[], ctx: Hwp5Ctx, autoType: number): void {\n // ctrl 데이터: ctrl_id(4) + number(u32) + before(WCHAR) + after(WCHAR) + numberShape(u32)\n // 번호는 각주 내용 안의 atno(자동번호)가 같은 카운터를 소비하므로 peek만 하고,\n // 내용 파싱 후 카운터가 안 움직였으면(atno 없음) 직접 전진시킨다 (rhwp assign_auto_numbers 정합)\n const num = ctx.doc.autoCounters.get(autoType) ?? 1\n\n let before = \"\"\n let after = \"\"\n let shape = 0\n if (ctrl.data.length >= 12) {\n before = wcharAt(ctrl.data, 8)\n after = wcharAt(ctrl.data, 10)\n }\n if (ctrl.data.length >= 16) {\n shape = ctrl.data.readUInt32LE(12) & 0xff\n }\n const formatted = formatNumber(num, shapeFormatToNumFmt(shape))\n const marker = before || after ? `${before}${formatted}${after}` : `${formatted})`\n\n const blocks = parseListHeaderParagraphs(ctrl, records, ctx)\n const content = blocksPlainText(blocks, \" \")\n if ((ctx.doc.autoCounters.get(autoType) ?? 1) <= num) {\n ctx.doc.autoCounters.set(autoType, num + 1)\n }\n ctrl.inlineText = marker\n // 각주 내용 첫머리의 atno가 이미 같은 마커를 생성했으면 중복 방지\n if (content) ctrl.footnote = content.startsWith(marker) ? content : `${marker} ${content}`\n // 주석 본문 구조 — HWPX collectSubListContent 와 같은 모양(글·표, 그림 제외, 머리 번호는 footnote 와 같게) (#149)\n if (content) {\n const kept = blocks.filter(b => b.type !== \"image\")\n ctrl.noteBlocks = content.startsWith(marker) ? kept : [{ type: \"paragraph\", text: marker, pageNumber: ctx.page }, ...kept]\n ctrl.noteHasTable = kept.some(b => b.type === \"table\" && b.table)\n }\n}\n\n/** 머리말('head')/꼬리말('foot') — 문서당 1회, 동일 텍스트 중복 제거 */\nfunction applyHeaderFooterEffect(ctrl: ParsedCtrl, records: HwpRecord[], ctx: Hwp5Ctx, isHeader: boolean): void {\n const text = blocksPlainText(parseListHeaderParagraphs(ctrl, records, ctx), \"\\n\")\n if (!text) return\n const key = (isHeader ? \"h:\" : \"f:\") + text\n if (ctx.doc.headerTexts.has(key)) return\n ctx.doc.headerTexts.add(key)\n const block: IRBlock = { type: \"paragraph\", text, pageNumber: ctx.page }\n if (isHeader) ctx.doc.headerBlocks.push(block)\n else ctx.doc.footerBlocks.push(block)\n}\n\n/** 필드 컨트롤(%hlk/%clk 등) — command 파싱 (rhwp parse_field_control, 표 154) */\nfunction applyFieldEffect(ctrl: ParsedCtrl): void {\n if (ctrl.id === FIELD_HLK) {\n const command = parseFieldCommand(ctrl.data)\n if (command) {\n const url = hyperlinkUrlFromCommand(command)\n if (url) ctrl.href = url\n }\n } else if (ctrl.id === FIELD_CLK && ctrl.data.length >= 8 && !(ctrl.data.readUInt32LE(4) & (1 << 15))) {\n // 누름틀 — 속성 bit 15(내용 수정됨)가 꺼진 미기입 필드는 한컴이 안내문(command Direction)을 본문 run 으로\n // 저장해 두고 화면에만 흐리게 그린다(인쇄·PDF 에 없음). 같은 글이면 값이 아니므로 parseParagraph 가 지운다\n // (rhwp clear_initial_field_texts 와 같은 이중 조건 — 수정됨 비트 + 안내문 일치)\n const command = parseFieldCommand(ctrl.data)\n const guide = command ? clickHereGuide(command) : undefined\n if (guide) ctrl.guide = guide\n }\n // 그 밖의 필드: anchor 텍스트는 PARA_TEXT에 있으므로 그대로 보존됨\n}\n\n/** 누름틀 command 의 안내문 — `Direction:wstring:<N>:` 뒤 N자 (UTF-16) */\nfunction clickHereGuide(command: string): string | undefined {\n const m = /Direction:wstring:(\\d+):/.exec(command)\n if (!m) return undefined\n const start = m.index + m[0].length\n return command.slice(start, start + Number(m[1])) || undefined\n}\n\n/** 필드 CTRL_HEADER 데이터에서 command 추출 — ctrl_id(4) + 속성(4) + 기타(1) + len(u16) + UTF-16LE */\nfunction parseFieldCommand(data: Buffer): string | null {\n if (data.length < 11) return null\n const cmdLen = data.readUInt16LE(9)\n if (cmdLen === 0) return null\n const start = 11\n const end = start + cmdLen * 2\n if (end > data.length) return null\n return data.subarray(start, end).toString(\"utf16le\").replace(/\\0+$/, \"\")\n}\n\n/** %hlk command에서 URL 추출 — 첫 ';' 구분 토큰 ('\\;' 이스케이프 존중). mailto/책갈피(#) 포함 */\nfunction hyperlinkUrlFromCommand(command: string): string | null {\n let url = \"\"\n for (let i = 0; i < command.length; i++) {\n const c = command[i]\n if (c === \"\\\\\" && i + 1 < command.length) {\n url += command[i + 1]\n i++\n continue\n }\n if (c === \";\") break\n url += c\n }\n url = url.trim()\n return url.length > 0 && url.length < 2000 ? url : null\n}\n\n// ─── 표 파싱 ─────────────────────────────────────────\n\n/** HWP5 셀 — CellContext + 중첩 구조 */\ninterface Hwp5Cell extends CellContext {\n blocks?: IRBlock[]\n isHeader?: boolean\n /** 칸의 보이는 변 (LIST_HEADER borderFillId u16@32 → DocInfo BORDER_FILL) */\n edges?: Edges\n /** 칸 높이가 A4 용지보다 크다 — 여러 쪽에 걸친 칸 */\n pageSpanning?: boolean\n}\n\n/** A4 용지 높이 (HWPUNIT, 297mm) — 이보다 높은 칸은 한 쪽에 들어갈 수 없다 */\nconst A4_HEIGHT = 84188\n\n/** 레이아웃 표 해체(flattenLayoutTables)는 여러 쪽에 걸친 칸이 있는 본문 상자만 — 나머지 표는 같은 문서의 HWPX 처럼 표로 둔다.\n * 보도자료 본문 전체를 9쪽짜리 3×1 상자에 담은 문서(rhwp issue3637)는 표로 두면 문서가 거대한 HTML 칸 하나가 된다 */\nfunction keepUnlessPageSpanning(table: IRTable, cells: Hwp5Cell[]): void {\n if (!cells.some(c => c.pageSpanning)) markNonLayoutTable(table)\n}\n\n/**\n * 표 컨트롤 파싱 (rhwp parse_table_control).\n * HWPTAG_TABLE 레코드 '이전'의 LIST_HEADER는 캡션, '이후'는 셀.\n */\nfunction parseTableControl(ctrl: ParsedCtrl, records: HwpRecord[], ctx: Hwp5Ctx): IRTable | null {\n if (ctx.depth >= MAX_NEST_DEPTH) return null\n const { childStart, childEnd } = ctrl\n // sourceId — CTRL_HEADER 레코드 인덱스(childStart − 1)로 프리패스 순번을 찾는다 (렌더 어댑터와 같은 키)\n const sourceId = ctx.tableIds?.get(childStart - 1)\n\n // HWPTAG_TABLE 레코드에서 행/열 수 — 직계 자식 레벨(CTRL_HEADER + 1)의 것만. 캡션 문단 안 표는 자기 TABLE\n // 레코드를 바깥 TABLE 보다 먼저 방출하므로 첫 TABLE 을 집으면 행/열이 그 표 것이 되고 캡션이 잘린다\n // (rhwp #3528 — 저장 순서 CTRL_HEADER → 캡션 LIST_HEADER·문단 → TABLE → 셀). hwp5-patch 스캔과 같은 규칙\n const directLevel = records[childStart - 1].level + 1\n let rows = 0\n let cols = 0\n let tableIdx = -1\n for (let i = childStart; i < childEnd; i++) {\n if (records[i].tagId === TAG_TABLE && records[i].level === directLevel && records[i].data.length >= 8) {\n rows = Math.min(records[i].data.readUInt16LE(4), MAX_ROWS)\n cols = Math.min(records[i].data.readUInt16LE(6), MAX_COLS)\n tableIdx = i\n break\n }\n }\n if (tableIdx < 0) return null\n\n // 캡션: TABLE 레코드 이전의 LIST_HEADER\n let caption: string | undefined\n for (let i = childStart; i < tableIdx; i++) {\n if (records[i].tagId === TAG_LIST_HEADER) {\n const capBlocks = parseParagraphList(records, i + 1, tableIdx, { ...ctx, depth: ctx.depth + 1 })\n const capText = blocksPlainText(capBlocks, \" \")\n if (capText) caption = capText\n break\n }\n }\n\n // 셀: TABLE 레코드 이후의 LIST_HEADER\n const cells: Hwp5Cell[] = []\n let i = tableIdx + 1\n while (i < childEnd) {\n const rec = records[i]\n if (rec.tagId === TAG_LIST_HEADER) {\n const cellLevel = rec.level\n let j = i + 1\n while (j < childEnd) {\n const r = records[j]\n if (r.level < cellLevel) break\n if (r.level === cellLevel && (r.tagId === TAG_LIST_HEADER || r.tagId === TAG_TABLE)) break\n j++\n }\n cells.push(parseCell(records, i, j, ctx))\n i = j\n continue\n }\n i++\n }\n\n if (cells.length === 0) return null\n\n // colAddr/rowAddr 절대 좌표 — builder 직접 배치로 HWPX 와 같은 표 계약(후행 빈 열 트림 등, ir-assemble.ts)\n if (cells.some(c => c.colAddr !== undefined && c.rowAddr !== undefined)) {\n const table = buildAddressedTable(cells, rows, cols, ctx.doc.keepTrailingEmptyCols)\n if (!table) return null\n if (caption) table.caption = caption\n if (sourceId) table.sourceId = sourceId\n keepUnlessPageSpanning(table, cells)\n return table\n }\n\n // 좌표 없는 셀 + 행·열 0 손상 레코드 — 셀마다 한 행으로 (글 손실 금지)\n if (rows === 0 || cols === 0) { rows = Math.min(cells.length, MAX_ROWS); cols = 1 }\n const cellRows = arrangeCells(rows, cols, cells)\n const table = buildTable(cellRows, { keepAnchoredEmptyCols: ctx.doc.keepTrailingEmptyCols })\n if (caption && table.rows > 0) table.caption = caption\n if (sourceId && table.rows > 0) table.sourceId = sourceId\n keepUnlessPageSpanning(table, cells)\n return table.rows > 0 ? table : null\n}\n\n/**\n * 표 셀 파싱 (rhwp parse_cell) — LIST_HEADER 구조:\n * paraCount(u16) + listAttr(u32) + widthRef(u16) + colAddr(u16) + rowAddr(u16) + colSpan(u16) + rowSpan(u16)\n * offset: 0 2 6 8 10 12 14\n * widthRef bit 2 = 제목 셀(is_header).\n * 셀 내부 문단 리스트는 재귀 파싱 — 중첩표는 IRCell.blocks에 IRBlock(type:'table')로 보존.\n */\nfunction parseCell(records: HwpRecord[], lhIdx: number, end: number, ctx: Hwp5Ctx): Hwp5Cell {\n const rec = records[lhIdx]\n let colSpan = 1\n let rowSpan = 1\n let colAddr: number | undefined\n let rowAddr: number | undefined\n let isHeader = false\n if (rec.data.length >= 16) {\n isHeader = (rec.data.readUInt16LE(6) & 0x04) !== 0\n colAddr = rec.data.readUInt16LE(8)\n rowAddr = rec.data.readUInt16LE(10)\n const cs = rec.data.readUInt16LE(12)\n const rs = rec.data.readUInt16LE(14)\n if (cs > 0) colSpan = Math.min(cs, MAX_COLS)\n if (rs > 0) rowSpan = Math.min(rs, MAX_ROWS)\n }\n\n const blocks = ctx.depth < MAX_NEST_DEPTH\n ? parseParagraphList(records, lhIdx + 1, end, { ...ctx, depth: ctx.depth + 1 })\n : []\n\n // 하위 호환 텍스트: 문단 평탄화 + 이미지 sentinel + 중첩표 평문 (각주는 문단 글에 접힌다)\n const { text, hasStructure } = cellTextFromBlocks(blocks)\n const cell: Hwp5Cell = { text, colSpan, rowSpan, colAddr, rowAddr }\n if (hasStructure && blocks.length > 0) cell.blocks = blocks\n if (isHeader) cell.isHeader = true\n if (rec.data.length >= 24 && rec.data.readUInt32LE(20) > A4_HEIGHT) cell.pageSpanning = true\n if (rec.data.length >= 34) {\n const borderFillId = rec.data.readUInt16LE(32)\n const definitions = ctx.docInfo?.borderEdges\n // 1-based 목록이 확인되면 0은 선 없음이다. 정의가 없는 파일은 미상으로 유지한다.\n const edges = borderFillId === 0 && definitions?.length\n ? { t: false, b: false, l: false, r: false }\n : definitions?.[borderFillId - 1]\n if (edges) cell.edges = edges\n }\n return cell\n}\n\n/** colAddr 없는 셀(짧은 LIST_HEADER)의 순차 배치 폴백 — 좌표가 있으면 parseTableControl 이 builder 직접 배치 */\nfunction arrangeCells(rows: number, cols: number, cells: Hwp5Cell[]): Hwp5Cell[][] {\n const grid: (Hwp5Cell | null)[][] = Array.from({ length: rows }, () => Array(cols).fill(null))\n let cellIdx = 0\n for (let r = 0; r < rows && cellIdx < cells.length; r++) {\n for (let c = 0; c < cols && cellIdx < cells.length; c++) {\n if (grid[r][c] !== null) continue\n const cell = cells[cellIdx++]\n grid[r][c] = cell\n\n for (let dr = 0; dr < cell.rowSpan; dr++) {\n for (let dc = 0; dc < cell.colSpan; dc++) {\n if (dr === 0 && dc === 0) continue\n if (r + dr < rows && c + dc < cols)\n grid[r + dr][c + dc] = { text: \"\", colSpan: 1, rowSpan: 1 }\n }\n }\n }\n }\n return grid.map(row => row.map(c => c || { text: \"\", colSpan: 1, rowSpan: 1 }))\n}\n\n// ─── 그리기 개체(GSO) 파싱 ───────────────────────────\n\n/**\n * GSO 컨트롤 파싱 (rhwp parse_gso_control).\n * - SHAPE_COMPONENT '이전' LIST_HEADER = 캡션\n * - SHAPE_COMPONENT '이후' 첫 LIST_HEADER = 글상자 문단 리스트\n * - SHAPE_COMPONENT_PICTURE 레코드 → binDataId(고정 오프셋 71) → 이미지 블록\n */\nfunction parseGsoControl(ctrl: ParsedCtrl, records: HwpRecord[], ctx: Hwp5Ctx): IRBlock[] {\n if (ctx.depth >= MAX_NEST_DEPTH) return []\n const { childStart, childEnd } = ctrl\n const blocks: IRBlock[] = []\n\n // 첫 SHAPE_COMPONENT(_CONTAINER) 위치\n let scIdx = -1\n for (let i = childStart; i < childEnd; i++) {\n const t = records[i].tagId\n if (t === TAG_SHAPE_COMPONENT || t === TAG_SHAPE_COMPONENT_CONTAINER) {\n scIdx = i\n break\n }\n }\n\n // 캡션: SHAPE_COMPONENT 이전의 LIST_HEADER\n if (scIdx > childStart) {\n for (let i = childStart; i < scIdx; i++) {\n if (records[i].tagId === TAG_LIST_HEADER) {\n blocks.push(...parseParagraphList(records, i + 1, scIdx, { ...ctx, depth: ctx.depth + 1 }))\n break\n }\n }\n }\n\n // 글상자: SHAPE_COMPONENT 이후 첫 LIST_HEADER부터 끝까지\n const scanStart = scIdx >= 0 ? scIdx + 1 : childStart\n let textListIdx = -1\n for (let i = scanStart; i < childEnd; i++) {\n if (records[i].tagId === TAG_LIST_HEADER) {\n textListIdx = i\n break\n }\n }\n\n // 그림: 글상자 리스트 이전 구간에서 SHAPE_COMPONENT_PICTURE 스캔\n // (글상자 내부의 중첩 gso 그림은 문단 리스트 재귀에서 처리되므로 이중 집계 없음)\n const picEnd = textListIdx >= 0 ? textListIdx : childEnd\n for (let i = scanStart; i < picEnd; i++) {\n if (records[i].tagId === TAG_SHAPE_COMPONENT_PICTURE) {\n const img = pictureToImageBlock(records[i].data, ctx)\n if (img) blocks.push(img)\n }\n }\n\n if (textListIdx >= 0) {\n blocks.push(...parseParagraphList(records, textListIdx + 1, childEnd, { ...ctx, depth: ctx.depth + 1 }))\n }\n\n return blocks\n}\n\n/**\n * SHAPE_COMPONENT_PICTURE → 이미지 블록.\n * rhwp parse_picture(shape.rs)의 고정 레이아웃:\n * borderColor(4) + borderWidth(4) + borderAttr(4) + 꼭짓점 x4/y4(32) + crop(16)\n * + padding(8) + 밝기(1)/대비(1)/효과(1) = 71 → binDataId(u16 @71)\n * binDataId는 DocInfo BIN_DATA 1-based 인덱스 → storage_id로 변환 (스트림명 BIN%04X 16진).\n */\nfunction pictureToImageBlock(data: Buffer, ctx: Hwp5Ctx): IRBlock | null {\n if (data.length < 73) return null\n const binDataId = data.readUInt16LE(71)\n if (binDataId === 0) return null\n\n const item = ctx.docInfo?.binData[binDataId - 1]\n if (item?.kind === \"link\") {\n ctx.warnings.push({ page: ctx.page, message: `외부 연결 이미지 (binDataId ${binDataId})`, code: \"SKIPPED_IMAGE\" })\n return null\n }\n // DocInfo BIN_DATA가 없으면 binDataId == storageId 관례에 폴백\n const storageId = item && item.storageId > 0 ? item.storageId : binDataId\n return { type: \"image\", text: String(storageId), pageNumber: ctx.page }\n}\n\n// ─── 스타일 ──────────────────────────────────────────\n\n/**\n * 글자 위치 → 첨자 종류. CharShape attr bit 15 = 위 첨자, bit 16 = 아래 첨자(HWP5 스펙 표 35 — 계량법 별표\n * \"10⁴ m²\" 의 위첨자 글자 모양 id 가 HWPX supscript charPr id 와 같음을 실측). 첨자 글자 모양이 없으면 undefined\n */\nfunction scriptLookup(runs: Array<[number, number]>, docInfo: HwpDocInfo | null): ((pos: number) => ScriptKind | null) | undefined {\n if (!docInfo || !runs.length) return undefined\n const kindOf = (id: number): ScriptKind | null => {\n const f = docInfo.charShapes[id]?.attrFlags ?? 0\n return f & (1 << 15) ? \"sup\" : f & (1 << 16) ? \"sub\" : null\n }\n if (!runs.some(([, id]) => kindOf(id))) return undefined\n let k = -1 // 글자 위치는 늘어나는 순서로 묻는다 — 커서를 앞으로만(되돌아가면 처음부터)\n return (pos) => {\n if (k >= 0 && runs[k][0] > pos) k = -1\n while (k + 1 < runs.length && runs[k + 1][0] <= pos) k++\n return k >= 0 ? kindOf(runs[k][1]) : null\n }\n}\n\n/** CHAR_SHAPE ID 배열에서 대표 스타일 결정 (최빈값) */\nfunction resolveCharStyle(charShapeIds: number[], docInfo: HwpDocInfo): InlineStyle | undefined {\n if (charShapeIds.length === 0 || docInfo.charShapes.length === 0) return undefined\n\n // 가장 많이 나타나는 charShapeId 사용\n const freq = new Map<number, number>()\n let maxCount = 0, dominantId = charShapeIds[0]\n for (const id of charShapeIds) {\n const count = (freq.get(id) || 0) + 1\n freq.set(id, count)\n if (count > maxCount) { maxCount = count; dominantId = id }\n }\n\n const cs = docInfo.charShapes[dominantId]\n if (!cs) return undefined\n\n const style: InlineStyle = {}\n if (cs.fontSize > 0) style.fontSize = cs.fontSize / 10 // 0.1pt → pt\n if (cs.attrFlags & 0x01) style.italic = true\n if (cs.attrFlags & 0x02) style.bold = true\n if (hasRealStrike(cs.attrFlags)) style.strike = true\n if (hasRealUnderline(cs.attrFlags)) style.underline = true\n\n return (style.fontSize || style.bold || style.italic || style.strike || style.underline) ? style : undefined\n}\n\n/**\n * CharShape attr 의 취소선 판정 — 비트(18-20)만 믿으면 안 된다: 한컴은 취소선 없는\n * 문자에도 1을 기본값으로 넣는다. 진짜 판별자는 취소선 모양(bit 26-29)이며, 취소선이\n * 없으면 표 27 선 종류(0~12)가 아닌 placeholder(15 등)가 들어온다. 알 수 없는 값은\n * fail-closed 로 no-strike (rhwp 0a967e0d, HWPX isRealStrikeShape 와 같은 원리).\n */\nexport function hasRealStrike(attrFlags: number): boolean {\n const strikeBits = (attrFlags >> 18) & 0x07\n const shapeId = (attrFlags >> 26) & 0x0f\n return strikeBits !== 0 && shapeId <= 12\n}\n\n/**\n * CharShape attr 의 밑줄 판정 — bit 2-3 밑줄 종류 (0=없음, 1=글자 아래, 3=글자 위;\n * rhwp doc_info 직렬화와 동일 레이아웃). 취소선과 달리 종류 비트 자체가 판별자다\n * (HWPX 실측: 밑줄 없는 charPr 는 type=\"NONE\"=비트 0). BOTTOM(1)만 인정 —\n * 윗줄(3)·미지 값은 fail-closed.\n */\nexport function hasRealUnderline(attrFlags: number): boolean {\n return ((attrFlags >> 2) & 0x03) === 1\n}\n","/** HWP 5.x 바이너리 파서 — OLE2 컨테이너 → 섹션 → Markdown */\n\nimport {\n readRecords, decompressStream, parseFileHeader, parseDocInfo, FLAG_COMPRESSED, FLAG_ENCRYPTED,\n FLAG_DISTRIBUTION, FLAG_DRM, type HwpRecord, type HwpDocInfo, type HwpFileHeader,\n} from \"./record.js\"\nimport { extractHwp5Images, extractHwp5ImagesLenient, collectHwp5BinData, collectHwp5BinDataLenient } from \"./images.js\"\nimport { inlineImagesIntoMarkdown } from \"../image/transcode.js\"\nimport { decryptViewText } from \"./crypto.js\"\nimport { parseLenientCfb, type LenientCfbContainer } from \"./cfb-lenient.js\"\nimport { blocksToMarkdown, flattenLayoutTables, dedupeRunningHeaders } from \"../table/builder.js\"\nimport { unframeLayoutTables } from \"../table/layout-frames.js\"\nimport type { IRBlock, DocumentMetadata, InternalParseResult, ParseOptions, ParseWarning, OutlineItem } from \"../types.js\"\nimport { HEADING_RATIO_H1, HEADING_RATIO_H2, HEADING_RATIO_H3 } from \"../types.js\"\nimport { assertDecryptedDocInfo, assertSupportedEncryptVersion, decryptPasswordStream, readEncryptVersion } from \"./pw-crypto.js\"\nimport { KordocError } from \"../utils.js\"\nimport { TOC_ENTRY_BLOCKS } from \"../toc-entry.js\"\nimport { parsePageRange } from \"../page-range.js\"\nimport { detectHwp5SectionPages, type Hwp5SectionPageDetect } from \"./page-boundary.js\"\nimport { indexHwp5Tables } from \"./table-ids.js\"\nimport { parseSection, createHwp5DocState } from \"./body.js\"\n\nexport { parseSection, createHwp5DocState, hasRealStrike, hasRealUnderline, type Hwp5DocState } from \"./body.js\"\n\nimport { createRequire } from \"module\"\nconst require = createRequire(import.meta.url)\nconst CFB: CfbModule = require(\"cfb\")\n\ninterface CfbEntry { name?: string; content?: Buffer | Uint8Array }\ninterface CfbContainer { FileIndex?: CfbEntry[] }\ninterface CfbModule {\n parse(data: Buffer): CfbContainer\n find(cfb: CfbContainer, path: string): CfbEntry | null\n}\n\n/** 최대 섹션 수 — 비정상 파일에 의한 무한 루프 방지 */\nconst MAX_SECTIONS = 100\n/** 누적 압축 해제 최대 크기 (100MB) */\nconst MAX_TOTAL_DECOMPRESS = 100 * 1024 * 1024\n\n/**\n * 열린 HWP5 컨테이너 — 파서와 렌더 어댑터(#75 Task 7)가 공유하는 스트림 접근 계층.\n * strict CFB → lenient 폴백, DRM 거부, 암호 문서 복호(findStream 에 내장), 압축·배포용 플래그.\n */\nexport interface Hwp5Container {\n cfb: CfbContainer | null\n lenientCfb: LenientCfbContainer | null\n header: HwpFileHeader\n compressed: boolean\n distribution: boolean\n encrypted: boolean\n /** 스트림 읽기 — 암호 문서는 복호를 거친다 */\n findStream: (path: string) => Buffer | null\n warnings: ParseWarning[]\n}\n\nexport function openHwp5Container(buffer: Buffer, options?: Pick<ParseOptions, \"password\">): Hwp5Container {\n // CFB 파싱: strict 먼저, 실패 시 lenient 폴백\n let cfb: CfbContainer | null = null\n let lenientCfb: LenientCfbContainer | null = null\n const warnings: ParseWarning[] = []\n\n try {\n cfb = CFB.parse(buffer)\n } catch {\n try {\n lenientCfb = parseLenientCfb(buffer)\n warnings.push({ message: \"손상된 CFB 컨테이너 — lenient 모드로 복구\", code: \"LENIENT_CFB_RECOVERY\" })\n } catch {\n throw new KordocError(\"CFB 컨테이너 파싱 실패 (strict 및 lenient 모두)\")\n }\n }\n\n // CFB 래퍼: strict/lenient 통합 인터페이스\n const readRawStream = (path: string): Buffer | null => {\n if (cfb) {\n const entry = CFB.find(cfb, path)\n return entry?.content ? Buffer.from(entry.content) : null\n }\n return lenientCfb!.findStream(path)\n }\n\n const headerData = readRawStream(\"/FileHeader\")\n if (!headerData) throw new KordocError(\"FileHeader 스트림 없음\")\n const header = parseFileHeader(headerData)\n if (header.signature !== \"HWP Document File\") throw new KordocError(\"HWP 시그니처 불일치\")\n if (header.flags & FLAG_DRM) throw new KordocError(\"DRM 보호된 HWP는 지원하지 않습니다\")\n\n // 비밀번호 암호 문서 — FileHeader 외 모든 스트림이 AES-CFB 로 암호화되어 있다.\n // 복호를 findStream 래퍼에 끼워 넣어 이후 경로가 평문 문서와 같아지게 한다.\n const encrypted = (header.flags & FLAG_ENCRYPTED) !== 0\n if (encrypted) {\n if (!options?.password) {\n throw new KordocError(\"암호로 보호된 HWP 문서입니다. password 옵션에 열기 암호를 지정하세요.\")\n }\n assertSupportedEncryptVersion(readEncryptVersion(headerData))\n }\n const password = encrypted ? options!.password! : undefined\n const findStream = (path: string): Buffer | null => {\n const raw = readRawStream(path)\n if (!raw || !password) return raw\n return decryptPasswordStream(raw, password)\n }\n\n const compressed = (header.flags & FLAG_COMPRESSED) !== 0\n const distribution = (header.flags & FLAG_DISTRIBUTION) !== 0\n\n // 암호 문서는 여기서 비밀번호를 검증한다 — DocInfo·섹션 파싱은 실패를 경고로 흡수해서,\n // 오답으로 나온 난수 데이터가 \"성공했는데 내용이 쓰레기\"인 결과로 흘러가기 때문이다.\n if (encrypted) {\n const rawDocInfo = findStream(\"/DocInfo\")\n if (!rawDocInfo) throw new KordocError(\"DocInfo 스트림 없음\")\n let docInfoData: Buffer\n try {\n docInfoData = compressed ? decompressStream(rawDocInfo) : rawDocInfo\n } catch {\n throw new KordocError(\"비밀번호가 일치하지 않거나 암호화 데이터가 손상되었습니다.\")\n }\n assertDecryptedDocInfo(docInfoData, readRecords)\n }\n\n return { cfb, lenientCfb, header, compressed, distribution, encrypted, findStream, warnings }\n}\n\n/** DocInfo 원시 레코드 (best-effort) — 렌더 어댑터가 FACE_NAME·BORDER_FILL 등 파서가 안 쓰는 레코드를 읽는다 */\nexport function readHwp5DocInfoRecords(c: Hwp5Container): HwpRecord[] | null {\n try {\n const raw = c.findStream(\"/DocInfo\")\n if (!raw) return null\n return readRecords(c.compressed ? decompressStream(raw) : raw)\n } catch {\n return null\n }\n}\n\n/** 섹션 원시 스트림 — 배포용은 복호+압축해제 완료, 그 외는 readHwp5SectionRecords 가 압축을 푼다 */\nexport function readHwp5SectionStreams(c: Hwp5Container): Buffer[] {\n return c.distribution\n ? (c.cfb ? findViewTextSections(c.cfb, c.compressed) : findViewTextSectionsLenient(c.lenientCfb!, c.compressed))\n : c.encrypted\n ? findSectionsVia(c.findStream)\n : (c.cfb ? findSections(c.cfb) : findSectionsLenient(c.lenientCfb!))\n}\n\n/** 섹션 스트림 → 레코드 (누적 압축해제 상한). 실패한 섹션은 null + PARTIAL_PARSE 경고 */\nexport function readHwp5SectionRecords(c: Hwp5Container, sections: Buffer[], warnings: ParseWarning[]): (HwpRecord[] | null)[] {\n const out: (HwpRecord[] | null)[] = []\n let totalDecompressed = 0\n for (let si = 0; si < sections.length; si++) {\n try {\n // 배포용 문서는 findViewTextSections에서 이미 복호화+압축해제 완료\n const data = (!c.distribution && c.compressed) ? decompressStream(Buffer.from(sections[si])) : Buffer.from(sections[si])\n totalDecompressed += data.length\n if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new KordocError(\"총 압축 해제 크기 초과 (decompression bomb 의심)\")\n out.push(readRecords(data))\n } catch (secErr) {\n if (secErr instanceof KordocError) throw secErr\n out.push(null)\n warnings.push({ page: si + 1, message: `섹션 ${si + 1} 파싱 실패: ${secErr instanceof Error ? secErr.message : \"알 수 없는 오류\"}`, code: \"PARTIAL_PARSE\" })\n }\n }\n return out\n}\n\n/** BinData 스토리지 — storageId(16진 BIN%04X) → 바이트(항목별 압축 정규화) */\nexport function readHwp5BinData(c: Hwp5Container): Map<number, { data: Buffer; name: string }> {\n const readStream = c.encrypted ? c.findStream : undefined\n return c.cfb ? collectHwp5BinData(c.cfb.FileIndex, readStream) : collectHwp5BinDataLenient(c.lenientCfb!, readStream)\n}\n\nexport function parseHwp5Document(buffer: Buffer, options?: ParseOptions): InternalParseResult {\n const c = openHwp5Container(buffer, options)\n const { cfb, lenientCfb, compressed, encrypted, findStream, warnings } = c\n\n const metadata: DocumentMetadata = {\n version: `${c.header.versionMajor}.x`,\n }\n if (cfb) extractHwp5Metadata(cfb, metadata)\n\n // DocInfo 파싱 (스타일 정보 추출)\n // 암호 문서는 복호를 거치는 findStream 경로로 — cfb 직접 접근은 암호문을 읽는다\n const docInfo = cfb && !encrypted\n ? parseDocInfoStream(cfb, compressed)\n : parseDocInfoFromStream(findStream(\"/DocInfo\"), compressed)\n\n const sections = readHwp5SectionStreams(c)\n if (sections.length === 0) throw new KordocError(\"섹션 스트림을 찾을 수 없습니다\")\n\n // (#66) 1단계: 섹션 레코드 확보 + 실제 페이지 프리패스 — 조판 캐시(PARA_LINE_SEG)가\n // 전 섹션에서 신뢰 가능하면 layout 모드(실제 페이지), 아니면 종전 섹션 근사.\n const sectionRecords = readHwp5SectionRecords(c, sections, warnings)\n const sectionDetects: (Hwp5SectionPageDetect | null)[] = sectionRecords.map(r => r ? detectHwp5SectionPages(r) : null)\n // 표 순번(sourceId) 프리패스 — 렌더 어댑터(#75)와 같은 규칙(table-ids.ts)\n const sectionTableIds: Map<number, string>[] = []\n {\n let base = 0\n for (const r of sectionRecords) {\n const ix = indexHwp5Tables(r ?? [], base)\n sectionTableIds.push(ix.ids)\n base += ix.count\n }\n }\n\n const layoutPages = sectionDetects.length > 0 && sectionDetects.every(d => d != null && d.usable)\n metadata.pageMode = layoutPages ? \"layout\" : \"section\"\n metadata.pageCount = layoutPages\n ? Math.max(sectionDetects.reduce((sum, d) => sum + (d?.pages ?? 0), 0), 1)\n : sections.length\n const pageFilter = options?.pages ? parsePageRange(options.pages, metadata.pageCount) : null\n if (pageFilter && !layoutPages) {\n warnings.push({ code: \"PAGE_BOUNDARY_APPROXIMATE\", message: \"조판 캐시가 없어 pages 필터를 섹션 단위 근사로 적용했습니다\" })\n }\n\n // 2단계: 본문 파싱 — layout 모드는 전 섹션 파싱 후 블록 단위 필터,\n // 섹션 근사는 종전(v4.7.2까지)처럼 섹션 스킵\n let bodyBlocks: IRBlock[] = []\n const doc = createHwp5DocState()\n doc.keepTrailingEmptyCols = options?.keepTrailingEmptyCols\n doc.includeFieldPlaceholders = options?.includeFieldPlaceholders\n let parsedSections = 0\n let pageBase = 0\n for (let si = 0; si < sections.length; si++) {\n const records = sectionRecords[si]\n if (!records) continue\n const detect = sectionDetects[si]!\n if (!layoutPages && pageFilter && !pageFilter.has(si + 1)) continue\n try {\n const sectionBlocks = parseSection(records, docInfo, warnings, si + 1, doc,\n layoutPages ? { base: pageBase, pageAtPara: detect.pageAtPara } : undefined, sectionTableIds[si])\n bodyBlocks.push(...sectionBlocks)\n parsedSections++\n options?.onProgress?.(parsedSections, sections.length)\n } catch (secErr) {\n if (secErr instanceof KordocError) throw secErr\n warnings.push({ page: si + 1, message: `섹션 ${si + 1} 파싱 실패: ${secErr instanceof Error ? secErr.message : \"알 수 없는 오류\"}`, code: \"PARTIAL_PARSE\" })\n } finally {\n pageBase += detect.pages\n }\n }\n\n // layout 모드 페이지 필터 — 실제 페이지 기준 블록 필터링\n if (pageFilter && layoutPages) {\n bodyBlocks = bodyBlocks.filter(b => b.pageNumber != null && pageFilter.has(b.pageNumber))\n }\n\n // 머리말은 문서 맨 앞, 꼬리말은 맨 뒤에 1회 출력\n const blocks: IRBlock[] = [...doc.headerBlocks, ...bodyBlocks, ...doc.footerBlocks]\n\n // BinData에서 이미지 추출 — 전체 파싱 시 본문 미참조 BinData 이미지도 스윕\n const images = cfb\n ? extractHwp5Images(cfb.FileIndex, blocks, warnings, !pageFilter, encrypted ? findStream : undefined)\n : extractHwp5ImagesLenient(lenientCfb!, blocks, warnings, !pageFilter, encrypted ? findStream : undefined)\n\n // 레이아웃 테이블 해체 (heading 감지 전에 수행하여 해체된 텍스트도 heading 감지 대상). 칸 테두리가 보이는 표는 풀지 않는다 —\n // 종전엔 3행 이하·글 많은 표를 테두리와 상관없이 풀어 같은 문서의 HWPX 표 118개가 사라지고 틀 안 중첩표가 바깥 단부터 풀렸다\n let flatBlocks = flattenLayoutTables(blocks)\n // 보이지 않는 틀 표 풀기 (v4.17.0) — 칸 테두리로 선 없는 틀은 글로, 칸으로 조립한 분수는 수식으로\n if (options?.layoutTables !== \"keep\") flatBlocks = unframeLayoutTables(flatBlocks, !!options?.keepTrailingEmptyCols)\n // 페이지 레이아웃 표의 반복 러닝 헤더 중복 제거 — opt-in (기본 off).\n // 위치 정보가 없는 HWP5 특성상 정당한 번호매김 반복(붙임별 재번호)까지 오삭제할 수\n // 있어 옵션이 켜졌을 때만 수행하고, 실제 제거가 있으면 경고로 가시화한다.\n if (options?.dedupeRunningHeaders) {\n const deduped = dedupeRunningHeaders(flatBlocks)\n const removed = flatBlocks.length - deduped.length\n if (removed > 0) warnings.push({ message: `반복 러닝 헤더 ${removed}개 제거`, code: \"HIDDEN_TEXT_FILTERED\" })\n flatBlocks = deduped\n }\n\n // 스타일 기반 헤딩 감지\n if (docInfo) {\n detectHwp5Headings(flatBlocks, docInfo, doc.tocTexts)\n }\n\n // outline 구축\n const outline: OutlineItem[] = flatBlocks\n .filter(b => b.type === \"heading\" && b.level && b.text)\n .map(b => ({ level: b.level!, text: b.text!, pageNumber: b.pageNumber }))\n\n let markdown = blocksToMarkdown(flatBlocks, { tableFormat: options?.tableFormat })\n // 이미지 인라인 옵션 — BMP→PNG 압축 후 base64 data URI 로 치환 (AI 에이전트 자체 완결형 마크다운)\n if (options?.inlineImages && options.images !== false && images.length > 0) {\n try {\n markdown = inlineImagesIntoMarkdown(markdown, images, { compress: true })\n } catch (inlineErr) {\n // 설계 계약상 bmpToPng 는 실패 시 null 을 반환하지만, 극단 입력·Node 버전차로 할당이\n // throw 하면 전체 파싱이 죽지 않도록 원본(비인라인) 마크다운을 유지하고 경고만 남긴다.\n warnings.push({ message: `이미지 인라인 실패 — 원본 파일 참조로 폴백: ${inlineErr instanceof Error ? inlineErr.message : \"알 수 없는 오류\"}`, code: \"SKIPPED_IMAGE\" })\n }\n }\n return { markdown, blocks: flatBlocks, metadata, outline: outline.length > 0 ? outline : undefined, warnings: warnings.length > 0 ? warnings : undefined, images: images.length > 0 ? images : undefined }\n}\n\n/** DocInfo 스트림 파싱 (best-effort) */\nfunction parseDocInfoStream(cfb: CfbContainer, compressed: boolean): HwpDocInfo | null {\n try {\n const entry = CFB.find(cfb, \"/DocInfo\")\n if (!entry?.content) return null\n const data = compressed ? decompressStream(Buffer.from(entry.content)) : Buffer.from(entry.content)\n const records = readRecords(data)\n return parseDocInfo(records)\n } catch {\n return null\n }\n}\n\n/** DocInfo — Buffer에서 직접 파싱 (lenient용) */\nfunction parseDocInfoFromStream(raw: Buffer | null, compressed: boolean): HwpDocInfo | null {\n if (!raw) return null\n try {\n const data = compressed ? decompressStream(raw) : raw\n return parseDocInfo(readRecords(data))\n } catch {\n return null\n }\n}\n\n/** 스타일 기반 헤딩 감지 — 큰 폰트 + 짧은 텍스트 → heading */\nfunction detectHwp5Headings(blocks: IRBlock[], docInfo: HwpDocInfo, tocTexts?: Set<string>): void {\n // 기본(본문) 폰트 크기 = 블록 폰트 크기의 텍스트 길이 가중 최빈값.\n // 공문서는 바탕글(10pt)과 다른 크기(13-14pt)로 본문을 쓰는 경우가 많아\n // 바탕글 스타일을 기준으로 삼으면 본문 전체가 헤딩으로 오검출된다 (실증: 보도자료 24/24).\n let baseFontSize = 0\n const sizeFreq = new Map<number, number>()\n for (const b of blocks) {\n if (b.style?.fontSize && b.text) {\n sizeFreq.set(b.style.fontSize, (sizeFreq.get(b.style.fontSize) || 0) + b.text.length)\n }\n }\n let maxWeight = 0\n for (const [size, weight] of sizeFreq) {\n if (weight > maxWeight) { maxWeight = weight; baseFontSize = size }\n }\n\n // 블록 스타일이 전혀 없으면 \"바탕글\", \"본문\" 등 본문 스타일로 폴백\n if (baseFontSize === 0) {\n for (const style of docInfo.styles) {\n const name = (style.nameKo || style.name).toLowerCase()\n if (name.includes(\"바탕\") || name.includes(\"본문\") || name === \"normal\" || name === \"body\") {\n const cs = docInfo.charShapes[style.charShapeId]\n // cs.fontSize는 0.1pt 단위 → pt로 변환 (블록의 style.fontSize와 동일 단위)\n if (cs?.fontSize > 0) { baseFontSize = cs.fontSize / 10; break }\n }\n }\n }\n\n if (baseFontSize <= 0) return\n\n for (const block of blocks) {\n // 개요 수준(outlineLevel)으로 이미 heading이 된 블록은 스킵\n if (block.type === \"heading\") continue\n if (block.type !== \"paragraph\" || !block.text || TOC_ENTRY_BLOCKS.has(block) || tocTexts?.has(block.text.trim())) continue\n const text = block.text.trim()\n if (text.length === 0 || text.length > 200) continue\n if (/^\\d+$/.test(text)) continue\n\n let level = 0\n\n // 폰트 크기 비율 기반 헤딩 감지 (스타일 정보가 있을 때만)\n if (block.style?.fontSize && baseFontSize > 0) {\n const ratio = block.style.fontSize / baseFontSize\n if (ratio >= HEADING_RATIO_H1) level = 1\n else if (ratio >= HEADING_RATIO_H2) level = 2\n else if (ratio >= HEADING_RATIO_H3) level = 3\n }\n\n // \"제N장/절/편\" 패턴 → H2, \"제N조\" 패턴 → H3 (스타일 유무 무관)\n if (/^제\\d+[장절편]\\s/.test(text) && text.length <= 50) {\n if (level === 0) level = 2\n } else if (/^제\\d+(조의?\\d*)\\s*[\\((]/.test(text) && text.length <= 80) {\n if (level === 0) level = 3\n }\n\n if (level > 0) {\n block.type = \"heading\"\n block.level = level\n }\n }\n}\n\n// ─── 메타데이터 추출 (best-effort) ───────────────────\n\nconst VT_I2 = 0x02, VT_LPSTR = 0x1e, VT_LPWSTR = 0x1f, VT_FILETIME = 0x40\n/** VT_LPSTR 코드 페이지 → TextDecoder 레이블 (1250~1258 은 windows-N) */\nconst CODE_PAGE_LABELS: Record<number, string> = { 949: \"euc-kr\", 932: \"shift_jis\", 936: \"gbk\", 950: \"big5\", 65001: \"utf-8\" }\n\n/**\n * OLE2 SummaryInformation 스트림에서 제목/작성자/설명/키워드/날짜 추출.\n * HWP5는 \\005HwpSummaryInformation 또는 \\005SummaryInformation에 저장.\n * OLE2 Property Set 포맷의 간이 파싱 — 실패 시 조용히 무시.\n * 한컴 HwpSummaryInformation(FMTID 9FA2B660-1061-11D4-B4C6-006097C09D8C)은 코드 페이지 속성 없이 문자열을 전부\n * VT_LPWSTR 로 쓴다(코퍼스 1,435건 전부) — 종전엔 VT_LPSTR 만 읽어 제목·지은이가 한 번도 안 나왔다.\n */\nfunction extractHwp5Metadata(cfb: CfbContainer, metadata: DocumentMetadata): void {\n try {\n // HWP 전용 SummaryInformation 먼저, 없으면 표준 OLE2\n const summaryEntry =\n CFB.find(cfb, \"/\\x05HwpSummaryInformation\") ||\n CFB.find(cfb, \"/\\x05SummaryInformation\")\n if (!summaryEntry?.content) return\n\n const data = Buffer.from(summaryEntry.content)\n if (data.length < 48) return\n\n // OLE2 Property Set Header: byte order(2) + version(2) + OS(4) + CLSID(16) + numSets(4) = 28\n // Then FMTID(16) + offset(4)\n const numSets = data.readUInt32LE(24)\n if (numSets === 0) return\n\n const setOffset = data.readUInt32LE(44)\n if (setOffset >= data.length - 8) return\n\n // Property Set: size(4) + numProperties(4) + [propertyId(4) + offset(4)] * N\n const numProps = data.readUInt32LE(setOffset + 4)\n if (numProps === 0 || numProps > 100) return\n\n // 속성 ID → 값 위치(type 4바이트부터). 코드 페이지(1)가 문자열 뒤에 올 수 있어 표를 먼저 모은다\n const props = new Map<number, number>()\n for (let i = 0; i < numProps; i++) {\n const entryOffset = setOffset + 8 + i * 8\n if (entryOffset + 8 > data.length) break\n const propOffset = setOffset + data.readUInt32LE(entryOffset + 4)\n if (propOffset + 8 <= data.length) props.set(data.readUInt32LE(entryOffset), propOffset)\n }\n const cpAt = props.get(1) // PID_CODEPAGE (VT_I2) — VT_LPSTR 해석용\n const codePage = cpAt !== undefined && data.readUInt32LE(cpAt) === VT_I2 ? data.readUInt16LE(cpAt + 4) : 0\n const text = (id: number) => { const at = props.get(id); return at === undefined ? undefined : readPropString(data, at, codePage) }\n const time = (id: number) => { const at = props.get(id); return at === undefined ? undefined : readPropFileTime(data, at) }\n\n // SummaryInformation 번호(한컴 FMTID 도 같음): 2 제목·3 주제·4 지은이·5 키워드·6 설명·12 만든 날짜·13 마지막 저장.\n // HWPX 짝 content.hpf 의 opf:title·subject·creator·keyword·description·CreatedDate 와 같은 값(한컴 저장 쌍 209건 실측).\n // 설명이 비면 주제 — HWPX metadata.ts(description → subject)·PDF(Subject) 와 같은 자리\n const title = text(2), author = text(4), description = text(6) || text(3)\n if (title) metadata.title = title\n if (author) metadata.author = author\n if (description) metadata.description = description\n const keywords = text(5)?.split(/[,;]/).map(k => k.trim()).filter(Boolean)\n if (keywords?.length) metadata.keywords = keywords\n const createdAt = time(12), modifiedAt = time(13)\n if (createdAt) metadata.createdAt = createdAt\n if (modifiedAt) metadata.modifiedAt = modifiedAt\n } catch {\n // best-effort — 실패 시 조용히 무시\n }\n}\n\n/**\n * 문자열 속성 값 (at = type 위치). VT_LPWSTR: 글자 수(UTF-16 단위, NUL 포함) + UTF-16LE,\n * VT_LPSTR: 바이트 수(NUL 포함) + 코드 페이지 문자열(1200 = UTF-16LE, 없음·모름 = UTF-8 — 종전 동작).\n * 값 뒤 4바이트 정렬 패딩은 오프셋 표로 찾으므로 무관\n */\nfunction readPropString(data: Buffer, at: number, codePage: number): string | undefined {\n const type = data.readUInt32LE(at)\n const unit = type === VT_LPWSTR ? 2 : type === VT_LPSTR ? 1 : 0\n const count = data.readUInt32LE(at + 4)\n if (!unit || count === 0 || count > 10000 || at + 8 + count * unit > data.length) return undefined\n const bytes = data.subarray(at + 8, at + 8 + count * unit)\n let s: string\n if (unit === 2 || codePage === 1200) s = bytes.toString(\"utf16le\")\n else {\n const label = CODE_PAGE_LABELS[codePage] ?? (codePage >= 1250 && codePage <= 1258 ? `windows-${codePage}` : \"utf-8\")\n try { s = new TextDecoder(label).decode(bytes) } catch { s = bytes.toString(\"utf8\") } // ICU 없는 Node — 레이블 미지원\n }\n const nul = s.indexOf(\"\\0\")\n return (nul >= 0 ? s.slice(0, nul) : s).trim() || undefined\n}\n\n/** VT_FILETIME — 1601-01-01 UTC 부터 100ns 단위 u64 → ISO 8601 초 단위(content.hpf CreatedDate 꼴). 0(미기록)은 undefined */\nfunction readPropFileTime(data: Buffer, at: number): string | undefined {\n if (data.readUInt32LE(at) !== VT_FILETIME || at + 12 > data.length) return undefined\n const ticks = data.readBigUInt64LE(at + 4)\n if (ticks === 0n) return undefined\n // 초로 먼저 나눠 정수 연산 — u64 를 double 로 옮기면 정각 값이 1초 앞당겨질 수 있다\n return new Date((Number(ticks / 10000000n) - 11644473600) * 1000).toISOString().replace(\".000Z\", \"Z\")\n}\n\n/** 메타데이터만 추출 (전체 파싱 없이) — MCP parse_metadata용 */\nexport function extractHwp5MetadataOnly(buffer: Buffer): DocumentMetadata {\n const cfb = CFB.parse(buffer)\n const headerEntry = CFB.find(cfb, \"/FileHeader\")\n if (!headerEntry?.content) throw new KordocError(\"FileHeader 스트림 없음\")\n const header = parseFileHeader(Buffer.from(headerEntry.content))\n if (header.signature !== \"HWP Document File\") throw new KordocError(\"HWP 시그니처 불일치\")\n\n const metadata: DocumentMetadata = {\n version: `${header.versionMajor}.x`,\n }\n extractHwp5Metadata(cfb, metadata)\n\n const sections = findSections(cfb)\n metadata.pageCount = sections.length\n\n return metadata\n}\n\n/** 배포용 문서: ViewText/Section{N} 스트림을 복호화하여 반환 */\nfunction findViewTextSections(cfb: CfbContainer, compressed: boolean): Buffer[] {\n const sections: Array<{ idx: number; content: Buffer }> = []\n\n for (let i = 0; i < MAX_SECTIONS; i++) {\n const entry = CFB.find(cfb, `/ViewText/Section${i}`)\n if (!entry?.content) break\n try {\n const decrypted = decryptViewText(Buffer.from(entry.content), compressed)\n sections.push({ idx: i, content: decrypted })\n } catch {\n // 복호화 실패 시 해당 섹션 스킵\n break\n }\n }\n\n return sections.sort((a, b) => a.idx - b.idx).map(s => s.content)\n}\n\n/** 스트림 리더로 BodyText 섹션 수집 — 압축 해제는 호출부가 맡는다(findSections와 같은 계약) */\nfunction findSectionsVia(read: (path: string) => Buffer | null): Buffer[] {\n const sections: Buffer[] = []\n for (let i = 0; i < MAX_SECTIONS; i++) {\n const raw = read(`/BodyText/Section${i}`)\n if (!raw) break\n sections.push(raw)\n }\n return sections\n}\n\nfunction findSections(cfb: CfbContainer): Buffer[] {\n const sections: Array<{ idx: number; content: Buffer }> = []\n\n for (let i = 0; i < MAX_SECTIONS; i++) {\n const entry = CFB.find(cfb, `/BodyText/Section${i}`)\n if (!entry?.content) break\n sections.push({ idx: i, content: Buffer.from(entry.content) })\n }\n\n if (sections.length === 0 && cfb.FileIndex) {\n for (const entry of cfb.FileIndex) {\n if (sections.length >= MAX_SECTIONS) break\n if (entry.name?.startsWith(\"Section\") && entry.content) {\n const idx = parseInt(entry.name.replace(\"Section\", \"\"), 10) || 0\n sections.push({ idx, content: Buffer.from(entry.content) })\n }\n }\n }\n\n return sections.sort((a, b) => a.idx - b.idx).map(s => s.content)\n}\n\n/** Lenient CFB: raw BodyText streams — readHwp5SectionRecords applies decompression once. */\nfunction findSectionsLenient(lcfb: LenientCfbContainer): Buffer[] {\n const sections: Array<{ idx: number; content: Buffer }> = []\n let totalBytes = 0\n for (let i = 0; i < MAX_SECTIONS; i++) {\n const raw = lcfb.findStream(`/BodyText/Section${i}`) ?? lcfb.findStream(`Section${i}`)\n if (!raw) break\n totalBytes += raw.length\n if (totalBytes > MAX_TOTAL_DECOMPRESS) throw new KordocError(\"총 압축 해제 크기 초과 (decompression bomb 의심)\")\n sections.push({ idx: i, content: raw })\n }\n if (sections.length === 0) {\n // fallback: 이름에 \"Section\" 포함된 스트림\n for (const e of lcfb.entries()) {\n if (sections.length >= MAX_SECTIONS) break\n if (e.name.startsWith(\"Section\")) {\n const idx = parseInt(e.name.replace(\"Section\", \"\"), 10) || 0\n const raw = lcfb.findStream(e.name)\n if (raw) {\n totalBytes += raw.length\n if (totalBytes > MAX_TOTAL_DECOMPRESS) throw new KordocError(\"총 압축 해제 크기 초과 (decompression bomb 의심)\")\n sections.push({ idx, content: raw })\n }\n }\n }\n }\n return sections.sort((a, b) => a.idx - b.idx).map(s => s.content)\n}\n\n/** Lenient CFB: ViewText/Section{N} 복호화 — 누적 크기 추적 */\nfunction findViewTextSectionsLenient(lcfb: LenientCfbContainer, compressed: boolean): Buffer[] {\n const sections: Array<{ idx: number; content: Buffer }> = []\n let totalDecompressed = 0\n for (let i = 0; i < MAX_SECTIONS; i++) {\n const raw = lcfb.findStream(`/ViewText/Section${i}`) ?? lcfb.findStream(`Section${i}`)\n if (!raw) break\n try {\n const content = decryptViewText(raw, compressed)\n totalDecompressed += content.length\n if (totalDecompressed > MAX_TOTAL_DECOMPRESS) throw new KordocError(\"총 압축 해제 크기 초과 (decompression bomb 의심)\")\n sections.push({ idx: i, content })\n } catch { break }\n }\n return sections.sort((a, b) => a.idx - b.idx).map(s => s.content)\n}\n","/**\n * HWP5 렌더 어댑터 (#75 Task 7) — BodyText 레코드(PARA_LINE_SEG·CTRL_HEADER/TABLE/LIST_HEADER·SHAPE_COMPONENT(_PICTURE))를\n * HWPX 조판 캐시와 같은 뜻의 section DOM 으로 합성해 공용 SVG 렌더러(svg-render)에 넘긴다.\n *\n * 근거: 같은 문서를 한컴이 HWPX 로 저장하면 lineseg(textpos/vertpos/horzpos/horzsize)·cellAddr/cellSz·pos/sz/outMargin 이\n * HWP5 레코드 값과 1:1 이다(bench/corpus/pairs hwp↔hwpx 실측, 2026-09-06). 그리기(페이지 분할·표 격자·이미지·region)는\n * svg-render 하나가 맡고, 이 모듈은 레코드 → 속성 번역만 한다. 목표는 픽셀 파리티가 아니라 **결정적·페이지 로컬 region**.\n *\n * 레코드 레이아웃(pairs 실측 · 스펙 5.0 rev1.3):\n * - PARA_LINE_SEG 36B: textpos u32 | vertpos i32 | lineHeight | textHeight | baseline | spacing | horzpos | horzsize | flags\n * - CTRL_HEADER 개체 공통 attr u32@4: bit0 treatAsChar · bit3-4 vertRelTo(0 PAPER/1 PAGE/2 PARA) · bit5-7 vertAlign ·\n * bit8-9 horzRelTo(0 PAPER/1 PAGE/2 COLUMN/3 PARA) · bit10-12 horzAlign · bit21-23 textWrap(0 SQUARE/1 TOP_AND_BOTTOM/2 BEHIND/3 FRONT);\n * vertOffset i32@8 · horzOffset@12 · width u32@16 · height@20 · outMargin u16×4@28(l r t b)\n * - TABLE: rows u16@4 · cols@6 · inMargin u16×4@10. LIST_HEADER(셀): attr u32@2(bit5-6 vertAlign) · col u16@8 row@10 cs@12 rs@14 ·\n * w u32@16 h@20 · margin u16×4@24 · borderFillId u16@32 (parser.ts parseCell 과 동일)\n * - SHAPE_COMPONENT(gso 직속): \"gso \"@0 · chid@4 · offset i32@8/@12 · orgSz u32@20/@24 · curSz@28/@32. 묶음($con) 안 자식은 4바이트\n * 접두가 없어 chid@0 · offset@4/@8 · orgSz@16/@20 · curSz@24/@28 (licbyl 18018145 실측, 중첩 묶음도 같은 꼴). PICTURE: crop i32×4@44 · binDataId u16@71\n * - DocInfo BORDER_FILL: 속성 u16@0 · 변 4개(왼/오/위/아래) = @2+6k (type u8 · width u8 · COLORREF) · 대각선 @26 · 채우기 type u32@32 ·\n * 배경 COLORREF@36 (pairs header.xml 대조: type 1=SOLID·8=DOUBLE_SLIM, width 1=0.12mm·6=0.4mm·7=0.5mm, 배경 0xFFFFFFFF=없음).\n * CHAR_SHAPE: faceId u16@0 · ratio u8@14 · spacing i8@21 · relSize u8@28 · baseSize@42(1/100pt) · attr@46(bit0 italic·bit1 bold·bit2-3 underline) · color@52\n *\n * 한계(HWPX 경로와 동일): 머리말·꼬리말·각주 미렌더, 수식·OLE 경고, 조판 캐시(LINE_SEG) 없는 비한컴 저장본 문단은 reflow 폴백.\n * 한컴 접힘 PUA-A(결재란 \"(인)\" 등)는 글리프 복원을 우선해 그 문단 안에서만 슬롯이 어긋날 수 있다.\n */\n\nimport {\n TAG_PARA_HEADER, TAG_PARA_TEXT, TAG_CHAR_SHAPE, TAG_PARA_LINE_SEG, TAG_CTRL_HEADER, TAG_LIST_HEADER, TAG_TABLE,\n TAG_SHAPE_COMPONENT, TAG_SHAPE_COMPONENT_PICTURE, TAG_ID_MAPPINGS, TAG_FACE_NAME, TAG_DOC_CHAR_SHAPE, TAG_DOC_PARA_SHAPE,\n isExtendedOnlyCtrlChar, parseDocInfo, type HwpRecord, type HwpDocInfo,\n} from \"../hwp5/record.js\"\nimport { openHwp5Container, readHwp5DocInfoRecords, readHwp5SectionStreams, readHwp5SectionRecords, readHwp5BinData } from \"../hwp5/parser.js\"\nimport { indexHwp5Tables } from \"../hwp5/table-ids.js\"\nimport { detectImageMime } from \"../hwp5/images.js\"\nimport { mapPuaText } from \"../shared/pua.js\"\nimport { createXmlParser } from \"../hwpx/parser-shared.js\"\nimport { hwpFaceToCssStack, DEFAULT_PARA_GEOM, type RenderStyles, type RenderBorderEdge, type RenderBorderFill, type ParaAlign } from \"./head-styles.js\"\nimport { renderSectionRoots, assemblePageSvgs, escapeXml, type RenderSvgOptions, type HwpxPagesResult, type SectionRoot, type RenderImages } from \"./svg-render.js\"\nimport { KordocError } from \"../utils.js\"\nimport type { ParseWarning } from \"../types.js\"\n\n// record.ts 미정의 태그 (HWPTAG_BEGIN = 0x10)\nconst TAG_BORDER_FILL = 0x0014 // +4\nconst TAG_PAGE_DEF = 0x0049 // +57\nconst TAG_SHAPE_COMPONENT_LINE = 0x004e // +62\nconst TAG_SHAPE_COMPONENT_POLYGON = 0x0052 // +66\nconst TAG_SHAPE_COMPONENT_CURVE = 0x0053 // +67\n\n/** 4바이트 ASCII → u32 (LE 저장을 readUInt32LE 로 읽은 값과 비교) */\nfunction cid(s: string): number {\n return ((s.charCodeAt(0) << 24) | (s.charCodeAt(1) << 16) | (s.charCodeAt(2) << 8) | s.charCodeAt(3)) >>> 0\n}\nfunction swap32(id: number): number {\n return (((id & 0xff) << 24) | (((id >>> 8) & 0xff) << 16) | (((id >>> 16) & 0xff) << 8) | ((id >>> 24) & 0xff)) >>> 0\n}\nconst CTRL_TBL = cid(\"tbl \"), CTRL_GSO = cid(\"gso \"), CTRL_SECD = cid(\"secd\"), CTRL_COLD = cid(\"cold\"), CTRL_EQED = cid(\"eqed\")\nconst CHID_PIC = cid(\"$pic\"), CHID_REC = cid(\"$rec\"), CHID_LIN = cid(\"$lin\"), CHID_ELL = cid(\"$ell\"), CHID_POL = cid(\"$pol\"),\n CHID_CUR = cid(\"$cur\"), CHID_ARC = cid(\"$arc\"), CHID_CON = cid(\"$con\")\nconst KNOWN = new Set([CTRL_TBL, CTRL_GSO, CTRL_SECD, CTRL_COLD, CTRL_EQED, CHID_PIC, CHID_REC, CHID_LIN, CHID_ELL, CHID_POL, CHID_CUR, CHID_ARC, CHID_CON])\n/** 비표준 작성기의 BE 저장 id 방어 — 알려진 id 로 스왑 일치할 때만 */\nfunction normId(raw: number): number {\n if (KNOWN.has(raw)) return raw\n const sw = swap32(raw)\n return KNOWN.has(sw) ? sw : raw\n}\n\n/** COLORREF(0x00BBGGRR) → #RRGGBB. 상위 바이트가 있으면(0xFFFFFFFF 등 \"없음\") null */\nfunction colorHex(c: number): string | null {\n if ((c >>> 24) !== 0) return null\n const h = (v: number) => v.toString(16).padStart(2, \"0\").toUpperCase()\n return `#${h(c & 0xff)}${h((c >>> 8) & 0xff)}${h((c >>> 16) & 0xff)}`\n}\n\n// ─── DocInfo → RenderStyles ────────────────────────\n\n/** 테두리선 굵기 코드(u8) → mm (스펙 표 26) */\nconst BORDER_WIDTH_MM = [0.1, 0.12, 0.15, 0.2, 0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0]\n/** 테두리선 종류 코드(u8) → HWPX type 명 (0 없음 · 1 실선 · 8 이중선, pairs 실측) */\nconst BORDER_TYPE = [\"NONE\", \"SOLID\", \"DASH\", \"DOT\", \"DASH_DOT\", \"DASH_DOT_DOT\", \"LONG_DASH\", \"CIRCLE\", \"DOUBLE_SLIM\", \"SLIM_THICK\", \"THICK_SLIM\", \"SLIM_THICK_SLIM\", \"WAVE\", \"DOUBLE_WAVE\", \"THICK_3D\", \"THICK_3D_LIFTED\", \"3D\", \"3D_LIFTED\"]\nconst MM_TO_PT = 2.834645\n\nfunction borderEdge(d: Buffer, o: number): RenderBorderEdge | undefined {\n const type = d[o]\n if (type === 0) return undefined\n const mm = BORDER_WIDTH_MM[d[o + 1]] ?? 0.12\n return { type: BORDER_TYPE[type] ?? \"SOLID\", widthPt: mm * MM_TO_PT, color: colorHex(d.readUInt32LE(o + 2)) ?? \"#000000\" }\n}\n\nfunction borderFillOf(d: Buffer): RenderBorderFill {\n const bf: RenderBorderFill = {}\n if (d.length < 26) return bf\n const l = borderEdge(d, 2), r = borderEdge(d, 8), t = borderEdge(d, 14), b = borderEdge(d, 20)\n if (l) bf.left = l\n if (r) bf.right = r\n if (t) bf.top = t\n if (b) bf.bottom = b\n if (d.length >= 40) {\n const fillType = d.readUInt32LE(32)\n if (fillType & 1) { const bg = colorHex(d.readUInt32LE(36)); if (bg) bf.fill = bg }\n }\n return bf\n}\n\n/** FACE_NAME: attr u8@0 · 이름(len u16 + WCHAR)@1 */\nfunction readFaceName(d: Buffer): string {\n if (d.length < 3) return \"\"\n const len = d.readUInt16LE(1)\n const end = 3 + len * 2\n return end <= d.length ? d.subarray(3, end).toString(\"utf16le\") : \"\"\n}\n\nconst PARA_ALIGNS: ParaAlign[] = [\"JUSTIFY\", \"LEFT\", \"RIGHT\", \"CENTER\", \"DISTRIBUTE\", \"DISTRIBUTE_SPACE\"]\nconst LINE_SPACING_TYPES = [\"PERCENT\", \"FIXED\", \"BETWEEN_LINES\", \"AT_LEAST\"]\n\n/** DocInfo 레코드 → 렌더 스타일 테이블. id 는 HWPX 와 같은 규약(charPr/paraPr 0-based · borderFill 1-based) */\nexport function buildHwp5RenderStyles(records: HwpRecord[]): RenderStyles {\n const idm = records.find(r => r.tagId === TAG_ID_MAPPINGS)\n const hangulCount = idm && idm.data.length >= 8 ? idm.data.readUInt32LE(4) : Number.POSITIVE_INFINITY\n const faces: string[] = []\n for (const r of records) {\n if (r.tagId !== TAG_FACE_NAME) continue\n if (faces.length >= hangulCount) break\n faces.push(readFaceName(r.data))\n }\n const charPr: RenderStyles[\"charPr\"] = new Map()\n let ci = 0\n for (const r of records) {\n if (r.tagId !== TAG_DOC_CHAR_SHAPE) continue\n const d = r.data\n const id = String(ci++)\n if (d.length < 50) { charPr.set(id, { height: 1000, bold: false, italic: false, underline: false, ratio: 100, spacing: 0 }); continue }\n const face = faces[d.readUInt16LE(0)]\n const rel = d[28] || 100\n const attr = d.readUInt32LE(46)\n const color = d.length >= 56 ? colorHex(d.readUInt32LE(52)) : null\n // 음영 색 @60 (글자색 52·밑줄색 56 다음, HWPX shadeColor 와 짝 문서 대조로 일치) — 흰색은 HWPX 와 같이 생략\n const shade = d.length >= 64 ? colorHex(d.readUInt32LE(60)) : null\n charPr.set(id, {\n height: Math.max(100, Math.round(d.readInt32LE(42) * rel / 100)),\n bold: (attr & 2) !== 0, italic: (attr & 1) !== 0, underline: ((attr >>> 2) & 3) !== 0,\n ratio: d[14] || 100, spacing: d.readInt8(21),\n ...(color && color !== \"#000000\" ? { color } : {}),\n ...(shade && shade !== \"#FFFFFF\" ? { shade } : {}),\n ...(face ? { fontFamily: hwpFaceToCssStack(face), face } : {}),\n })\n }\n const paraAlign: RenderStyles[\"paraAlign\"] = new Map()\n const paraGeom: RenderStyles[\"paraGeom\"] = new Map()\n let pi = 0\n for (const r of records) {\n if (r.tagId !== TAG_DOC_PARA_SHAPE) continue\n const d = r.data\n const id = String(pi++)\n if (d.length < 28) { paraAlign.set(id, \"JUSTIFY\"); paraGeom.set(id, { ...DEFAULT_PARA_GEOM }); continue }\n const attr1 = d.readUInt32LE(0)\n paraAlign.set(id, PARA_ALIGNS[(attr1 >>> 2) & 7] ?? \"JUSTIFY\")\n paraGeom.set(id, {\n lineSpacingType: LINE_SPACING_TYPES[attr1 & 3] ?? \"PERCENT\",\n lineSpacingValue: d.length >= 54 ? d.readUInt32LE(50) : d.readInt32LE(24),\n marginLeft: d.readInt32LE(4), marginRight: d.readInt32LE(8), marginIntent: d.readInt32LE(12),\n spaceBefore: d.readInt32LE(16), spaceAfter: d.readInt32LE(20),\n })\n }\n const borderFill: RenderStyles[\"borderFill\"] = new Map()\n let bi = 0\n for (const r of records) if (r.tagId === TAG_BORDER_FILL) borderFill.set(String(++bi), borderFillOf(r.data))\n // \"쪽 번호\" 스타일 글자 모양 — 한컴은 쪽 번호를 이 글꼴로 찍는다(HWPX 와 같다)\n const pnStyle = parseDocInfo(records).styles.find(st => [st.name, st.nameKo].some(n => n === \"쪽 번호\" || n === \"Page Number\"))\n return { charPr, paraAlign, paraGeom, borderFill, ...(pnStyle ? { pageNumCharPr: String(pnStyle.charShapeId) } : {}) }\n}\n\n// ─── BodyText → section DOM(XML) ───────────────────\n\nexport interface Hwp5SectionXmlContext {\n /** CTRL_HEADER 레코드 인덱스 → 표 sourceId (table-ids.ts) */\n tableIds: Map<number, string>\n /** binDataId(DocInfo 1-based) → 이미지 참조(binaryItemIDRef). null 이면 외부 연결 등 미참조 */\n imageRef: (binDataId: number) => string | null\n warnings: string[]\n}\n\ninterface CtrlRef { idx: number; id: number; start: number; end: number; used?: boolean }\n\nconst VREL = [\"PAPER\", \"PAGE\", \"PARA\", \"PARA\"], HREL = [\"PAPER\", \"PAGE\", \"COLUMN\", \"PARA\"]\nconst VALIGN = [\"TOP\", \"CENTER\", \"BOTTOM\", \"TOP\", \"BOTTOM\"], HALIGN = [\"LEFT\", \"CENTER\", \"RIGHT\", \"LEFT\", \"RIGHT\"]\nconst WRAP = [\"SQUARE\", \"TOP_AND_BOTTOM\", \"BEHIND_TEXT\", \"IN_FRONT_OF_TEXT\"]\n\ninterface ObjCommon { tac: boolean; wrap: string; w: number; h: number; posXml: string }\n\n/** 개체 공통 속성(CTRL_HEADER) → hp:sz/pos/outMargin */\nfunction objCommon(d: Buffer): ObjCommon {\n if (d.length < 36) return { tac: true, wrap: \"SQUARE\", w: 0, h: 0, posXml: `<hp:sz width=\"0\" height=\"0\"/><hp:pos treatAsChar=\"1\" vertRelTo=\"PARA\" horzRelTo=\"PARA\" vertAlign=\"TOP\" horzAlign=\"LEFT\" vertOffset=\"0\" horzOffset=\"0\"/>` }\n const a = d.readUInt32LE(4)\n const tac = (a & 1) !== 0\n const w = d.readUInt32LE(16), h = d.readUInt32LE(20)\n const posXml = `<hp:sz width=\"${w}\" height=\"${h}\"/>` +\n `<hp:pos treatAsChar=\"${tac ? 1 : 0}\" vertRelTo=\"${VREL[(a >>> 3) & 3]}\" horzRelTo=\"${HREL[(a >>> 8) & 3]}\" vertAlign=\"${VALIGN[(a >>> 5) & 7] ?? \"TOP\"}\" horzAlign=\"${HALIGN[(a >>> 10) & 7] ?? \"LEFT\"}\" vertOffset=\"${d.readInt32LE(8)}\" horzOffset=\"${d.readInt32LE(12)}\"/>` +\n `<hp:outMargin left=\"${d.readUInt16LE(28)}\" right=\"${d.readUInt16LE(30)}\" top=\"${d.readUInt16LE(32)}\" bottom=\"${d.readUInt16LE(34)}\"/>`\n return { tac, wrap: WRAP[(a >>> 21) & 7] ?? \"SQUARE\", w, h, posXml }\n}\n\n/** 한컴 PUA-A 접힘 영역 (record.ts 와 동일 범위) */\nconst FOLD_START = 0xa000, FOLD_END = 0xa48c, FOLD_SHIFT = 0xf0000 - 0xa000\n\n/** 텍스트 1글자 (제어문자 아님). XML 에 못 들어가는 코드는 U+FFFD */\nfunction textChar(ch: number): string {\n if (ch >= FOLD_START && ch <= FOLD_END) {\n const mapped = mapPuaText(String.fromCodePoint(ch + FOLD_SHIFT))\n // 매핑 없으면 PUA 그대로 돌아온다 — 글리프가 없으니 비운다\n return /[\\u{F0000}-\\u{FFFFF}]/u.test(mapped) ? \"\" : mapped\n }\n if (ch === 0xfffe || ch === 0xffff || (ch >= 0xd800 && ch <= 0xdfff)) return \"�\"\n return String.fromCharCode(ch)\n}\n\n/** [start,end) 안의 `level` 문단 전부 → hp:p 나열 */\nfunction paragraphsXml(records: HwpRecord[], start: number, end: number, level: number, ctx: Hwp5SectionXmlContext, depth: number): string {\n if (depth > 16) return \"\"\n let out = \"\"\n let i = start\n while (i < end) {\n const r = records[i]\n if (r.tagId === TAG_PARA_HEADER && r.level === level) {\n let j = i + 1\n while (j < end && records[j].level > level) j++\n out += paragraphXml(records, i, j, level, ctx, depth)\n i = j\n } else i++\n }\n return out\n}\n\nfunction paragraphXml(records: HwpRecord[], i: number, j: number, level: number, ctx: Hwp5SectionXmlContext, depth: number): string {\n const hdr = records[i]\n const paraShapeId = hdr.data.length >= 10 ? hdr.data.readUInt16LE(8) : 0\n const texts: Buffer[] = []\n const shapes: Array<[number, number]> = []\n const segs: Buffer[] = []\n const ctrls: CtrlRef[] = []\n let k = i + 1\n while (k < j) {\n const r = records[k]\n if (r.level === level + 1) {\n if (r.tagId === TAG_PARA_TEXT) texts.push(r.data)\n else if (r.tagId === TAG_CHAR_SHAPE) { for (let o = 0; o + 8 <= r.data.length; o += 8) shapes.push([r.data.readUInt32LE(o), r.data.readUInt32LE(o + 4)]) }\n else if (r.tagId === TAG_PARA_LINE_SEG) segs.push(r.data)\n else if (r.tagId === TAG_CTRL_HEADER && r.data.length >= 4) {\n let e = k + 1\n while (e < j && records[e].level > level + 1) e++\n ctrls.push({ idx: k, id: normId(r.data.readUInt32LE(0)), start: k + 1, end: e })\n k = e\n continue\n }\n }\n k++\n }\n const text = texts.length === 1 ? texts[0] : Buffer.concat(texts)\n\n // 확장 컨트롤 문자(ctrlIdx 순) ↔ CTRL_HEADER 순서 매핑 — record.ts 의 resolver 규약, 어긋나면 같은 id 의 미사용 컨트롤\n const ctrlElement = (ctrlIdx: number, rawId: number): string => {\n const id = normId(rawId)\n let c: CtrlRef | undefined = ctrls[ctrlIdx]\n if (!c || c.used || c.id !== id) c = ctrls.find(x => !x.used && x.id === id)\n if (!c) return \"<hp:ctrl/>\"\n c.used = true\n switch (c.id) {\n case CTRL_TBL: return tableXml(records, c, level, ctx, depth)\n case CTRL_GSO: return gsoXml(records, c, level, ctx, depth)\n case CTRL_SECD: return secPrXml(records, c)\n case CTRL_COLD: { const a = records[c.idx].data.length >= 8 ? records[c.idx].data.readUInt32LE(4) : 0; return `<hp:colPr colCount=\"${Math.max(1, (a >>> 2) & 0xff)}\"/>` }\n case CTRL_EQED: { const oc = objCommon(records[c.idx].data); return `<hp:equation textWrap=\"${oc.wrap}\">${oc.posXml}</hp:equation>` }\n default: return \"<hp:ctrl/>\"\n }\n }\n\n // 슬롯 모델(record.ts appendParaText 와 동일): 문자 1 · 문자형 제어 1 · 인라인/확장 제어 8. charShape 경계에서 run 교체\n // 문단 나눔 종류(PARA_HEADER offset 11): bit2 쪽 나누기·bit3 단 나누기 — HWPX pageBreak·columnBreak 와 같은 뜻(쪽 감지가 쓴다)\n const divideSort = hdr.data.length >= 12 ? hdr.data.readUInt8(11) : 0\n const breaks = `${divideSort & 0x04 ? ` pageBreak=\"1\"` : \"\"}${divideSort & 0x08 ? ` columnBreak=\"1\"` : \"\"}`\n let out = `<hp:p paraPrIDRef=\"${paraShapeId}\" styleIDRef=\"0\"${breaks}>`\n let shapeIdx = 0\n let run: string[] = []\n let textBuf = \"\"\n const flushText = () => { if (textBuf) { run.push(`<hp:t>${escapeXml(textBuf)}</hp:t>`); textBuf = \"\" } }\n const openRun = (id: number) => { out += `<hp:run charPrIDRef=\"${id}\">` }\n const closeRun = () => { flushText(); out += run.join(\"\") + \"</hp:run>\"; run = [] }\n openRun(shapes[0]?.[1] ?? 0)\n let pos = 0, ctrlIdx = 0, o = 0\n const switchShape = () => {\n while (shapeIdx + 1 < shapes.length && pos >= shapes[shapeIdx + 1][0]) { shapeIdx++; closeRun(); openRun(shapes[shapeIdx][1]) }\n }\n while (o + 1 < text.length) {\n switchShape()\n const ch = text.readUInt16LE(o)\n o += 2\n if (ch === 0x0d) break\n if (ch >= 0x20) {\n if (ch >= 0xd800 && ch <= 0xdbff && o + 1 < text.length) {\n const lo = text.readUInt16LE(o)\n if (lo >= 0xdc00 && lo <= 0xdfff) { textBuf += String.fromCharCode(ch, lo); o += 2; pos += 2; continue }\n }\n textBuf += textChar(ch)\n pos++\n continue\n }\n switch (ch) {\n case 0x09: flushText(); run.push(\"<hp:tab/>\"); o += 14; pos += 8; break\n case 0x0a: {\n flushText(); run.push(\"<hp:lineBreak/>\"); pos++\n // 수식 placeholder 0x0a+0x0b (record.ts 와 동일 특례)\n if (o + 16 <= text.length && text.readUInt16LE(o) === 0x000b) { run.push(ctrlElement(ctrlIdx++, text.readUInt32LE(o + 2))); o += 16; pos += 8 }\n break\n }\n case 0x00: flushText(); run.push(\"<hp:lineBreak/>\"); pos++; break\n case 0x1e: flushText(); run.push(\"<hp:nbSpace/>\"); pos++; break\n case 0x1f: flushText(); run.push(\"<hp:fwSpace/>\"); pos++; break\n case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: flushText(); run.push(\"<hp:hyphen/>\"); pos++; break\n default: {\n const isInline = (ch >= 4 && ch <= 9) || ch === 19 || ch === 20\n if ((isExtendedOnlyCtrlChar(ch) || isInline) && o + 14 <= text.length) {\n flushText()\n if (isExtendedOnlyCtrlChar(ch)) run.push(ctrlElement(ctrlIdx++, text.readUInt32LE(o)))\n else run.push(\"<hp:ctrl/>\")\n o += 14\n pos += 8\n } else pos++\n }\n }\n }\n closeRun()\n // 텍스트가 비어 있어도 컨트롤(secd 등)은 문자 스트림에 있다 — 문자 스트림에 없는 잔여 컨트롤은 문단 끝에 붙인다\n const rest = ctrls.filter(c => !c.used && (c.id === CTRL_TBL || c.id === CTRL_GSO || c.id === CTRL_SECD || c.id === CTRL_COLD))\n if (rest.length > 0) {\n openRun(shapes[0]?.[1] ?? 0)\n for (const c of rest) { const el = ctrlElement(ctrls.indexOf(c), c.id); run.push(el) }\n closeRun()\n }\n if (segs.length > 0) {\n out += \"<hp:linesegarray>\"\n for (const s of segs) {\n for (let off = 0; off + 36 <= s.length; off += 36) {\n out += `<hp:lineseg textpos=\"${s.readUInt32LE(off)}\" vertpos=\"${s.readInt32LE(off + 4)}\" vertsize=\"${s.readInt32LE(off + 8)}\" textheight=\"${s.readInt32LE(off + 12)}\" baseline=\"${s.readInt32LE(off + 16)}\" spacing=\"${s.readInt32LE(off + 20)}\" horzpos=\"${s.readInt32LE(off + 24)}\" horzsize=\"${s.readInt32LE(off + 28)}\" flags=\"${s.readUInt32LE(off + 32)}\"/>`\n }\n }\n out += \"</hp:linesegarray>\"\n }\n return out + \"</hp:p>\"\n}\n\n/** 구역 정의(secd) → hp:secPr/pagePr (PAGE_DEF: width u32@0 height@4 left@8 right@12 top@16 bottom@20 header@24 footer@28 gutter@32 attr@36) */\nfunction secPrXml(records: HwpRecord[], c: CtrlRef): string {\n for (let k = c.start; k < c.end; k++) {\n const r = records[k]\n if (r.tagId !== TAG_PAGE_DEF || r.data.length < 36) continue\n const d = r.data\n const u = (o: number) => d.readUInt32LE(o)\n const landscape = d.length >= 40 && (u(36) & 1) === 1 ? \"NARROWLY\" : \"WIDELY\"\n return `<hp:secPr><hp:pagePr landscape=\"${landscape}\" width=\"${u(0)}\" height=\"${u(4)}\"><hp:margin left=\"${u(8)}\" right=\"${u(12)}\" top=\"${u(16)}\" bottom=\"${u(20)}\" header=\"${u(24)}\" footer=\"${u(28)}\" gutter=\"${u(32)}\"/></hp:pagePr></hp:secPr>`\n }\n return \"<hp:secPr/>\"\n}\n\nconst CELL_VALIGN = [\"TOP\", \"CENTER\", \"BOTTOM\", \"TOP\"]\n\n/** 표 컨트롤 → hp:tbl (셀 = TABLE 레코드 뒤 LIST_HEADER + 같은 level 의 문단들, parser.ts parseTableControl 과 같은 분할) */\nfunction tableXml(records: HwpRecord[], c: CtrlRef, level: number, ctx: Hwp5SectionXmlContext, depth: number): string {\n const common = objCommon(records[c.idx].data)\n const cellLevel = level + 2\n let tableIdx = -1\n for (let k = c.start; k < c.end; k++) if (records[k].tagId === TAG_TABLE && records[k].level === cellLevel && records[k].data.length >= 18) { tableIdx = k; break }\n if (tableIdx < 0) return \"<hp:ctrl/>\"\n const t = records[tableIdx].data\n const rows = t.readUInt16LE(4), cols = t.readUInt16LE(6)\n const inMargin = `<hp:inMargin left=\"${t.readUInt16LE(10)}\" right=\"${t.readUInt16LE(12)}\" top=\"${t.readUInt16LE(14)}\" bottom=\"${t.readUInt16LE(16)}\"/>`\n let caption = \"\"\n for (let k = c.start; k < tableIdx; k++) {\n const r = records[k]\n if (r.tagId !== TAG_LIST_HEADER || r.level !== cellLevel || r.data.length < 22) continue\n // TABLE 앞 직계 문단 리스트는 캡션이다. 캡션 안의 중첩표는 아래 paragraphsXml에서 처리한다.\n const d = r.data, side = [\"LEFT\", \"RIGHT\", \"TOP\", \"BOTTOM\"][d.readUInt32LE(8) & 3]\n const paras = paragraphsXml(records, k + 1, tableIdx, cellLevel, ctx, depth + 1)\n caption = `<hp:caption side=\"${side}\" width=\"${d.readUInt32LE(12)}\" gap=\"${d.readUInt16LE(16)}\" lastWidth=\"${d.readUInt32LE(18)}\"><hp:subList>${paras}</hp:subList></hp:caption>`\n break\n }\n let cells = \"\"\n let k = tableIdx + 1\n while (k < c.end) {\n const r = records[k]\n if (r.tagId === TAG_LIST_HEADER && r.level === cellLevel) {\n let e = k + 1\n while (e < c.end) {\n const x = records[e]\n if (x.level < cellLevel) break\n if (x.level === cellLevel && (x.tagId === TAG_LIST_HEADER || x.tagId === TAG_TABLE)) break\n e++\n }\n cells += cellXml(records, k, e, cellLevel, ctx, depth)\n k = e\n continue\n }\n k++\n }\n if (!cells) return \"<hp:ctrl/>\"\n const id = ctx.tableIds.get(c.idx)\n // 표 속성 bit 0~1 = 쪽 경계에서 나눔(0 나누지 않음·1 TABLE·2 CELL), bit 2 = 제목 행 반복 (짝 HWPX 표 385개 전부 일치)\n const tattr = t.readUInt32LE(0)\n const pageBreak = [\"NONE\", \"TABLE\", \"CELL\", \"CELL\"][tattr & 3]\n return `<hp:tbl${id ? ` id=\"${id}\"` : \"\"} textWrap=\"${common.wrap}\" pageBreak=\"${pageBreak}\" repeatHeader=\"${(tattr >>> 2) & 1}\" rowCnt=\"${rows}\" colCnt=\"${cols}\" cellSpacing=\"0\">${common.posXml}${inMargin}${caption}<hp:tr>${cells}</hp:tr></hp:tbl>`\n}\n\nfunction cellXml(records: HwpRecord[], lh: number, end: number, cellLevel: number, ctx: Hwp5SectionXmlContext, depth: number): string {\n const d = records[lh].data\n if (d.length < 34) return \"\"\n // 문단 리스트 헤더 = 문단 수 UINT16 · 미상 UINT16 · 속성 UINT32(오프셋 4) — 세로 정렬 bit 5~6, 제목 칸 bit 18\n // (짝 HWPX 대조: 칸 1,469개 세로 정렬·제목 칸 전부 일치. 종전엔 오프셋 2 를 읽어 모든 칸이 위 정렬이었다)\n const attr = d.readUInt32LE(4)\n const vAlign = CELL_VALIGN[(attr >>> 5) & 3]\n const paras = paragraphsXml(records, lh + 1, end, cellLevel, ctx, depth + 1)\n return `<hp:tc borderFillIDRef=\"${d.readUInt16LE(32)}\" header=\"${(attr >>> 18) & 1}\"><hp:subList vertAlign=\"${vAlign}\">${paras}</hp:subList>` +\n `<hp:cellAddr colAddr=\"${d.readUInt16LE(8)}\" rowAddr=\"${d.readUInt16LE(10)}\"/><hp:cellSpan colSpan=\"${Math.max(1, d.readUInt16LE(12))}\" rowSpan=\"${Math.max(1, d.readUInt16LE(14))}\"/>` +\n `<hp:cellSz width=\"${d.readUInt32LE(16)}\" height=\"${d.readUInt32LE(20)}\"/><hp:cellMargin left=\"${d.readUInt16LE(24)}\" right=\"${d.readUInt16LE(26)}\" top=\"${d.readUInt16LE(28)}\" bottom=\"${d.readUInt16LE(30)}\"/></hp:tc>`\n}\n\ninterface ShapeComp { idx: number; chid: number; xoff: number; yoff: number; orgW: number; orgH: number; curW: number; curH: number }\n\n/** nested=묶음 안 자식(4바이트 접두 없음) */\nfunction readShapeComp(records: HwpRecord[], idx: number, nested = false): ShapeComp | null {\n const d = records[idx].data\n const b = nested ? 0 : 4\n if (d.length < b + 32) return null\n return { idx, chid: normId(d.readUInt32LE(b)), xoff: d.readInt32LE(b + 4), yoff: d.readInt32LE(b + 8), orgW: d.readUInt32LE(b + 16), orgH: d.readUInt32LE(b + 20), curW: d.readUInt32LE(b + 24), curH: d.readUInt32LE(b + 28) }\n}\n\n/** 묶음 자식들 — 컨테이너 SHAPE_COMPONENT 바로 아래 level 의 SHAPE_COMPONENT 만, 각 자식 범위는 다음 형제 전까지(중첩 묶음 재귀) */\nfunction containerChildrenXml(records: HwpRecord[], scIdx: number, end: number, ctx: Hwp5SectionXmlContext): string {\n const childLevel = records[scIdx].level + 1\n let out = \"\"\n for (let k = scIdx + 1; k < end; k++) {\n if (records[k].tagId !== TAG_SHAPE_COMPONENT || records[k].level !== childLevel) continue\n const child = readShapeComp(records, k, true)\n if (!child) continue\n let e = k + 1\n while (e < end && !(records[e].tagId === TAG_SHAPE_COMPONENT && records[e].level <= childLevel)) e++\n const sizeXml = `<hp:sz width=\"${child.curW}\" height=\"${child.curH}\"/><hp:offset x=\"${child.xoff}\" y=\"${child.yoff}\"/>`\n out += child.chid === CHID_CON\n ? `<hp:container>${sizeXml}${containerChildrenXml(records, k, e, ctx)}</hp:container>`\n : shapeElement(records, child, k, e, sizeXml, \"\", ctx)\n k = e - 1\n }\n return out\n}\n\n/** 그리기 개체(gso) → hp:pic / rect / ellipse / line / polygon / curv / arc / container / ole */\nfunction gsoXml(records: HwpRecord[], c: CtrlRef, level: number, ctx: Hwp5SectionXmlContext, depth: number): string {\n const common = objCommon(records[c.idx].data)\n let scIdx = -1\n for (let k = c.start; k < c.end; k++) if (records[k].tagId === TAG_SHAPE_COMPONENT) { scIdx = k; break }\n const sc = scIdx >= 0 ? readShapeComp(records, scIdx) : null\n if (!sc) return `<hp:ole textWrap=\"${common.wrap}\">${common.posXml}</hp:ole>`\n // 글상자 문단 리스트: SHAPE_COMPONENT 뒤 첫 LIST_HEADER(같은 level+2)\n let textList = -1\n for (let k = scIdx + 1; k < c.end; k++) if (records[k].tagId === TAG_LIST_HEADER && records[k].level === level + 2) { textList = k; break }\n const geomEnd = textList >= 0 ? textList : c.end\n const drawText = textList >= 0 ? `<hp:drawText><hp:subList>${paragraphsXml(records, textList + 1, c.end, level + 2, ctx, depth + 1)}</hp:subList></hp:drawText>` : \"\"\n if (sc.chid === CHID_CON) return `<hp:container textWrap=\"${common.wrap}\">${common.posXml}${containerChildrenXml(records, scIdx, geomEnd, ctx)}</hp:container>`\n return shapeElement(records, sc, scIdx, geomEnd, common.posXml, drawText, ctx, common.wrap)\n}\n\n/** chid 별 개체 요소. geometry 레코드는 [scIdx, end) 에서 찾는다 */\nfunction shapeElement(records: HwpRecord[], sc: ShapeComp, scIdx: number, end: number, posXml: string, drawText: string, ctx: Hwp5SectionXmlContext, wrap?: string): string {\n const sizes = `<hp:orgSz width=\"${sc.orgW}\" height=\"${sc.orgH}\"/><hp:curSz width=\"${sc.curW}\" height=\"${sc.curH}\"/>`\n // 부유 개체의 textWrap — 없으면 렌더러가 TOP_AND_BOTTOM(밀어내기 역산)으로 보고 BEHIND/FRONT 개체(직인·워터마크)를 위로 올린다\n const wa = wrap ? ` textWrap=\"${wrap}\"` : \"\"\n const find = (tag: number): Buffer | null => { for (let k = scIdx + 1; k < end; k++) if (records[k].tagId === tag) return records[k].data; return null }\n if (sc.chid === CHID_PIC) {\n const p = find(TAG_SHAPE_COMPONENT_PICTURE)\n let img = \"<hp:img/>\", clip = \"\"\n if (p && p.length >= 73) {\n const ref = ctx.imageRef(p.readUInt16LE(71))\n img = ref ? `<hp:img binaryItemIDRef=\"${ref}\"/>` : \"<hp:img/>\"\n const cl = p.readInt32LE(44), ct = p.readInt32LE(48), cr = p.readInt32LE(52), cb = p.readInt32LE(56)\n if ((cl > 0 || ct > 0 || cr > 0 || cb > 0) && sc.orgW - cr > cl && sc.orgH - cb > ct) {\n clip = `<hp:imgClip left=\"${Math.max(0, cl)}\" top=\"${Math.max(0, ct)}\" right=\"${sc.orgW - Math.max(0, cr)}\" bottom=\"${sc.orgH - Math.max(0, cb)}\"/>`\n }\n }\n return `<hp:pic${wa}>${posXml}${sizes}<hp:imgDim dimwidth=\"${sc.orgW}\" dimheight=\"${sc.orgH}\"/>${clip}${img}</hp:pic>`\n }\n const line = `<hp:lineShape color=\"#000000\" width=\"12\" style=\"SOLID\"/>`\n if (sc.chid === CHID_LIN) {\n const l = find(TAG_SHAPE_COMPONENT_LINE)\n const pts = l && l.length >= 16\n ? `<hp:startPt x=\"${l.readInt32LE(0)}\" y=\"${l.readInt32LE(4)}\"/><hp:endPt x=\"${l.readInt32LE(8)}\" y=\"${l.readInt32LE(12)}\"/>`\n : `<hp:startPt x=\"0\" y=\"0\"/><hp:endPt x=\"${sc.orgW}\" y=\"${sc.orgH}\"/>`\n return `<hp:line${wa}>${posXml}${sizes}${line}${pts}</hp:line>`\n }\n if (sc.chid === CHID_POL || sc.chid === CHID_CUR) {\n const g = find(sc.chid === CHID_POL ? TAG_SHAPE_COMPONENT_POLYGON : TAG_SHAPE_COMPONENT_CURVE)\n let pts = \"\"\n if (g && g.length >= 2) {\n const n = Math.min(g.readInt16LE(0), 4096)\n for (let k = 0; k < n && 2 + k * 8 + 8 <= g.length; k++) pts += `<hp:pt x=\"${g.readInt32LE(2 + k * 8)}\" y=\"${g.readInt32LE(6 + k * 8)}\"/>`\n }\n const tag = sc.chid === CHID_POL ? \"polygon\" : \"curv\"\n return `<hp:${tag}${wa}>${posXml}${sizes}${line}${pts}${drawText}</hp:${tag}>`\n }\n const tag = sc.chid === CHID_REC ? \"rect\" : sc.chid === CHID_ELL ? \"ellipse\" : sc.chid === CHID_ARC ? \"arc\" : \"ole\"\n return `<hp:${tag}${wa}>${posXml}${sizes}${line}${drawText}</hp:${tag}>`\n}\n\n/** 섹션 레코드 → HWPX 동형 section XML (svg-render 가 읽는 요소·속성만) */\nexport function hwp5SectionToXml(records: HwpRecord[], ctx: Hwp5SectionXmlContext): string {\n return `<hs:sec xmlns:hs=\"http://www.hancom.co.kr/hwpml/2011/section\" xmlns:hp=\"http://www.hancom.co.kr/hwpml/2011/paragraph\" xmlns:hc=\"http://www.hancom.co.kr/hwpml/2011/core\">` +\n paragraphsXml(records, 0, records.length, 0, ctx, 0) + \"</hs:sec>\"\n}\n\n// ─── 엔트리 ───────────────────────────────────────\n\nexport interface RenderHwp5Options extends RenderSvgOptions {\n /** 암호 문서 열기 암호 */\n password?: string\n}\n\n/**\n * 레코드 단위 렌더 — 컨테이너를 이미 연 호출자(테스트·재사용)용. `secRecords` 의 null 구역은 생략.\n * 이미지는 참조된 BinData 만 dataURI 로 싣는다(HWPX 경로와 같은 장당·누적 한도).\n */\nexport function renderHwp5Records(\n docInfo: HwpDocInfo | null,\n styles: RenderStyles,\n secRecords: (HwpRecord[] | null)[],\n binData: Map<number, { data: Buffer; name: string }>,\n options?: RenderHwp5Options,\n select?: Set<number> | ((pageCount: number) => Set<number>),\n warnings: string[] = [],\n): HwpxPagesResult {\n const maxImg = options?.maxImageBytes ?? 40 * 1024 * 1024\n const MAX_TOTAL_IMAGE_BYTES = 128 * 1024 * 1024\n const images: RenderImages = new Map()\n let totalImgBytes = 0\n const imageRef = (binDataId: number): string | null => {\n if (binDataId <= 0) return null\n const item = docInfo?.binData[binDataId - 1]\n if (item?.kind === \"link\") return null\n const storageId = item && item.storageId > 0 ? item.storageId : binDataId\n const ref = `bin${storageId}`\n if (images.has(ref)) return ref\n const entry = binData.get(storageId)\n if (!entry) return ref // 누락은 렌더러가 placeholder + 경고\n if (entry.data.length > maxImg) { warnings.push(`이미지 ${entry.name} ${(entry.data.length / 1048576).toFixed(1)}MB — 한도 초과로 생략`); return ref }\n if (totalImgBytes + entry.data.length > MAX_TOTAL_IMAGE_BYTES) { warnings.push(`이미지 누적 ${Math.round(MAX_TOTAL_IMAGE_BYTES / 1048576)}MB 한도 초과 — 이후 생략`); return ref }\n totalImgBytes += entry.data.length\n images.set(ref, { dataUri: `data:${detectImageMime(entry.data) ?? \"image/jpeg\"};base64,${entry.data.toString(\"base64\")}` })\n return ref\n }\n const roots: SectionRoot[] = []\n let base = 0\n for (let si = 0; si < secRecords.length; si++) {\n const recs = secRecords[si]\n if (!recs) continue\n const { ids, count } = indexHwp5Tables(recs, base)\n base += count\n const xml = hwp5SectionToXml(recs, { tableIds: ids, imageRef, warnings })\n const doc = createXmlParser().parseFromString(xml, \"text/xml\")\n const root = doc.documentElement as unknown as Element\n if (!root) { warnings.push(`구역 ${si} 합성 DOM 생성 실패 — 생략`); continue }\n roots.push({ root, index: si })\n }\n if (roots.length === 0) throw new KordocError(\"렌더할 구역이 없습니다 — HWP 가 손상되었을 수 있습니다\")\n const r = renderSectionRoots(roots, { styles, images, warnings, reflow: !!options?.reflow, reflowMode: options?.reflowMode ?? \"keep\", highlights: options?.highlights })\n return assemblePageSvgs(r, \"hwp\", select)\n}\n\n/** HWP5(OLE2) → 페이지별 독립 SVG + RenderScene. renderHwpxPages 와 같은 계약 (#75 Task 7) */\nexport function renderHwp5Pages(\n input: ArrayBuffer | Uint8Array,\n options?: RenderHwp5Options,\n select?: Set<number> | ((pageCount: number) => Set<number>),\n): HwpxPagesResult {\n const buf = Buffer.from(input instanceof Uint8Array ? input : new Uint8Array(input))\n const c = openHwp5Container(buf, options)\n const warnings: string[] = c.warnings.map(w => w.message)\n const docInfoRecords = readHwp5DocInfoRecords(c)\n if (!docInfoRecords) warnings.push(\"DocInfo 없음 — 기본 스타일로 렌더\")\n const styles = buildHwp5RenderStyles(docInfoRecords ?? [])\n const docInfo = docInfoRecords ? parseDocInfo(docInfoRecords) : null\n const sections = readHwp5SectionStreams(c)\n if (sections.length === 0) throw new KordocError(\"섹션 스트림을 찾을 수 없습니다\")\n const parseWarnings: ParseWarning[] = []\n const secRecords = readHwp5SectionRecords(c, sections, parseWarnings)\n for (const w of parseWarnings) warnings.push(w.message)\n return renderHwp5Records(docInfo, styles, secRecords, readHwp5BinData(c), options, select, warnings)\n}\n","/**\n * 통합 문서 렌더 API (#75 Task 3·8) — 입력(경로/버퍼) → 포맷 감지 → 어댑터 → RenderScene + 페이지 SVG\n * → SVG/HTML/PNG/JPEG/PDF 자산. 다운스트림은 RenderScene 만 알면 된다.\n *\n * hwpx → HWPX 어댑터(svg-render, 조판 캐시 재생·reflow 폴백)\n * hwp → HWP5 어댑터(hwp5-scene: 레코드 → 동형 section DOM → 같은 렌더러)\n * 기타 → 미지원\n */\n\nimport { readFile } from \"node:fs/promises\"\nimport { detectFormat, detectZipFormat } from \"../detect.js\"\nimport { KordocError, toArrayBuffer } from \"../utils.js\"\nimport { parsePageRange } from \"../page-range.js\"\nimport { renderHwpxPages } from \"./svg-render.js\"\nimport { renderHwp5Pages } from \"./hwp5-scene.js\"\nimport type { WrapMode } from \"../hwpx/text-metrics.js\"\nimport type { RenderScene, RenderSourceFormat } from \"./scene.js\"\nimport { renderSceneToHtml } from \"./html.js\"\nimport { rasterizePageSvg } from \"./rasterize.js\"\nimport { renderHtmlToPdf } from \"./pdf.js\"\n\nexport type RenderFormat = \"svg\" | \"html\" | \"png\" | \"jpeg\" | \"pdf\"\n\nexport interface SceneRenderOptions {\n /** 1-based 페이지 선택 — [2,3] 또는 \"1-3,7\". 미지정이면 전 페이지 */\n pages?: number[] | string\n /** 조판 캐시 없는 HWPX 를 순수 TS 조판으로 렌더 (기본 true — 캐시가 있으면 무시) */\n reflow?: boolean\n /** 암호 HWP5 열기 암호 */\n password?: string\n reflowMode?: WrapMode\n highlights?: string[]\n maxImageBytes?: number\n}\n\nexport interface SceneRenderResult {\n scene: RenderScene\n /** 선택된 페이지의 standalone SVG (페이지 로컬 좌표) */\n pageSvgs: Map<number, string>\n}\n\nexport interface RenderDocumentOptions extends SceneRenderOptions {\n format: RenderFormat\n /** 래스터 출력 최대 폭 px */\n maxWidthPx?: number\n /** JPEG 품질 */\n quality?: number\n /** PDF 용 Chromium 실행 파일 */\n browserExecutablePath?: string\n /** HTML/PDF 문서 제목 */\n title?: string\n}\n\nexport interface RenderAsset {\n format: RenderFormat\n /** 페이지 단위 산출은 page, 문서 단위(HTML/PDF)는 없음 */\n page?: number\n data: string | Buffer\n /** 픽셀(래스터) 또는 pt(SVG) */\n width?: number\n height?: number\n /** 래스터 pt→px 실배율 */\n scale?: number\n mimeType?: string\n}\n\nexport interface RenderDocumentResult {\n scene: RenderScene\n assets: RenderAsset[]\n}\n\nexport type RenderInput = string | ArrayBuffer | Buffer | Uint8Array\n\nasync function loadBuffer(input: RenderInput): Promise<ArrayBuffer> {\n if (typeof input === \"string\") {\n try {\n return toArrayBuffer(await readFile(input))\n } catch (err) {\n const code = err instanceof Error && \"code\" in err ? (err as NodeJS.ErrnoException).code : undefined\n throw new KordocError(code === \"ENOENT\" ? `파일을 찾을 수 없습니다: ${input}` : `파일 읽기 실패: ${input}`)\n }\n }\n if (Buffer.isBuffer(input)) return toArrayBuffer(input)\n if (input instanceof Uint8Array) return input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength) as ArrayBuffer\n return input\n}\n\n/** 입력 포맷 → 렌더 어댑터 종류 (hwpx | hwp). OLE2 는 HWP5 로 본다 — 세부 판정(HWP3·암호)은 어댑터가 */\nasync function sourceFormatOf(buffer: ArrayBuffer): Promise<RenderSourceFormat> {\n const format = detectFormat(buffer)\n if (format === \"hwpx\") {\n const zip = await detectZipFormat(buffer)\n if (zip === \"hwpx\" || zip === \"unknown\") return \"hwpx\"\n throw new KordocError(`렌더 미지원 형식(${zip}) — 레이아웃 렌더는 HWPX·HWP 만 지원합니다`)\n }\n if (format === \"hwp\") return \"hwp\"\n throw new KordocError(`렌더 미지원 형식(${format}) — 레이아웃 렌더는 HWPX·HWP 만 지원합니다`)\n}\n\n/**\n * 문서 → RenderScene + 선택 페이지 SVG. 페이지 선택은 조립 단계에서 걸러 비선택 페이지의 SVG 문자열을 만들지 않는다.\n * 선택 결과가 비면(범위 밖) KordocError.\n */\nexport async function renderDocumentToScene(input: RenderInput, options: SceneRenderOptions = {}): Promise<SceneRenderResult> {\n const buffer = await loadBuffer(input)\n const source = await sourceFormatOf(buffer)\n const select = options.pages !== undefined\n ? (pageCount: number) => {\n const set = parsePageRange(options.pages!, pageCount)\n if (set.size === 0) throw new KordocError(`선택한 페이지가 없습니다 — 문서는 ${pageCount}쪽 (pages: ${JSON.stringify(options.pages)})`)\n return set\n }\n : undefined\n const renderOptions = { reflow: options.reflow ?? true, reflowMode: options.reflowMode, highlights: options.highlights, maxImageBytes: options.maxImageBytes }\n const { scene, pageSvgs } = source === \"hwp\"\n ? renderHwp5Pages(buffer, { ...renderOptions, password: options.password }, select)\n : await renderHwpxPages(buffer, renderOptions, select)\n return { scene, pageSvgs }\n}\n\n/** 통합 렌더 — 포맷별 자산. 래스터·PDF 는 선택 페이지만 처리한다 */\nexport async function renderDocument(input: RenderInput, options: RenderDocumentOptions): Promise<RenderDocumentResult> {\n const { scene, pageSvgs } = await renderDocumentToScene(input, options)\n const pageNos = [...pageSvgs.keys()].sort((a, b) => a - b)\n const sizeOf = (n: number) => scene.pages.find(p => p.page === n)!\n const assets: RenderAsset[] = []\n switch (options.format) {\n case \"svg\":\n for (const n of pageNos) { const p = sizeOf(n); assets.push({ format: \"svg\", page: n, data: pageSvgs.get(n)!, width: p.width, height: p.height, mimeType: \"image/svg+xml\" }) }\n break\n case \"html\":\n assets.push({ format: \"html\", data: renderSceneToHtml(scene, pageSvgs, { title: options.title }), mimeType: \"text/html\" })\n break\n case \"png\":\n case \"jpeg\":\n for (const n of pageNos) {\n const p = sizeOf(n)\n const r = await rasterizePageSvg(pageSvgs.get(n)!, p.width, p.height, { format: options.format, maxWidthPx: options.maxWidthPx, quality: options.quality })\n assets.push({ format: options.format, page: n, data: r.data, width: r.widthPx, height: r.heightPx, scale: r.scale, mimeType: r.mimeType })\n }\n break\n case \"pdf\": {\n const html = renderSceneToHtml(scene, pageSvgs, { title: options.title })\n assets.push({ format: \"pdf\", data: await renderHtmlToPdf(html, { browserExecutablePath: options.browserExecutablePath }), mimeType: \"application/pdf\" })\n break\n }\n default:\n throw new KordocError(`알 수 없는 렌더 포맷: ${String(options.format)} (svg|html|png|jpeg|pdf)`)\n }\n return { scene, assets }\n}\n","/** 매직 바이트 기반 파일 포맷 감지 */\n\nimport JSZip from \"jszip\"\nimport type { FileType } from \"./types.js\"\nimport { parseLenientCfb } from \"./hwp5/cfb-lenient.js\"\n\n/** 매직 바이트 뷰 생성 (복사 없이 view) */\nfunction magicBytes(buffer: ArrayBuffer): Uint8Array {\n return new Uint8Array(buffer, 0, Math.min(4, buffer.byteLength))\n}\n\n/** ZIP 파일 여부: PK\\x03\\x04 */\nexport function isZipFile(buffer: ArrayBuffer): boolean {\n const b = magicBytes(buffer)\n return b[0] === 0x50 && b[1] === 0x4b && b[2] === 0x03 && b[3] === 0x04\n}\n\n/** HWPX (ZIP 기반 한컴 문서): PK\\x03\\x04 — 하위 호환용 */\nexport function isHwpxFile(buffer: ArrayBuffer): boolean {\n return isZipFile(buffer)\n}\n\n/** HWP 5.x (OLE2 바이너리 한컴 문서): \\xD0\\xCF\\x11\\xE0 */\nexport function isOldHwpFile(buffer: ArrayBuffer): boolean {\n const b = magicBytes(buffer)\n return b[0] === 0xd0 && b[1] === 0xcf && b[2] === 0x11 && b[3] === 0xe0\n}\n\n/**\n * HWP 3.x (한글 워드프로세서 3.0): \"HWP Document File V3.00 \\x1A\\x01\\x02\\x03\\x04\\x05\" 30 byte.\n * CFB(OLE2) 컨테이너 아닌 단일 binary stream — isOldHwpFile 과 magic 이 다르다.\n */\nconst HWP3_PREFIX = new TextEncoder().encode(\"HWP Document File V3.00\")\nexport function isHwp3File(buffer: ArrayBuffer): boolean {\n if (buffer.byteLength < HWP3_PREFIX.length) return false\n const head = new Uint8Array(buffer, 0, HWP3_PREFIX.length)\n for (let i = 0; i < HWP3_PREFIX.length; i++) {\n if (head[i] !== HWP3_PREFIX[i]) return false\n }\n return true\n}\n\n/** PDF 문서: %PDF */\nexport function isPdfFile(buffer: ArrayBuffer): boolean {\n const b = magicBytes(buffer)\n return b[0] === 0x25 && b[1] === 0x50 && b[2] === 0x44 && b[3] === 0x46\n}\n\n/** 래스터 이미지 (PNG/JPEG/WebP) — OCR 파싱 경로로 라우팅 */\nexport function isImageFile(buffer: ArrayBuffer): boolean {\n if (buffer.byteLength < 12) return false\n const b = new Uint8Array(buffer, 0, 12)\n // PNG: \\x89PNG\n if (b[0] === 0x89 && b[1] === 0x50 && b[2] === 0x4e && b[3] === 0x47) return true\n // JPEG: \\xFF\\xD8\\xFF\n if (b[0] === 0xff && b[1] === 0xd8 && b[2] === 0xff) return true\n // WebP: RIFF....WEBP\n if (b[0] === 0x52 && b[1] === 0x49 && b[2] === 0x46 && b[3] === 0x46 &&\n b[8] === 0x57 && b[9] === 0x45 && b[10] === 0x42 && b[11] === 0x50) return true\n return false\n}\n\n/** HWPML (XML 기반 한컴 문서): <?xml ... <HWPML */\nexport function isHwpmlFile(buffer: ArrayBuffer): boolean {\n const bytes = new Uint8Array(buffer, 0, Math.min(512, buffer.byteLength))\n const head = new TextDecoder(\"utf-8\", { fatal: false }).decode(bytes).replace(/^\\uFEFF/, \"\")\n return head.trimStart().startsWith(\"<?xml\") && head.includes(\"<HWPML\")\n}\n\n/** 동기 포맷 감지 — ZIP은 모두 \"hwpx\"로 반환 (하위 호환) */\nexport function detectFormat(buffer: ArrayBuffer): FileType {\n if (buffer.byteLength < 4) return \"unknown\"\n if (isHwp3File(buffer)) return \"hwp3\"\n if (isZipFile(buffer)) return \"hwpx\"\n if (isOldHwpFile(buffer)) return \"hwp\"\n if (isPdfFile(buffer)) return \"pdf\"\n if (isHwpmlFile(buffer)) return \"hwpml\"\n if (isImageFile(buffer)) return \"image\"\n return \"unknown\"\n}\n\n/**\n * OLE2 컨테이너 내부 스트림 기반 포맷 세분화.\n * HWP 5.x, XLS 모두 OLE2이므로 스트림 이름으로 구분.\n * - \"Workbook\" 또는 \"Book\" → 'xls'\n * - 그 외 (FileHeader 등) → 'hwp'\n */\nexport function detectOle2Format(buffer: ArrayBuffer): \"hwp\" | \"xls\" | \"unknown\" {\n try {\n const cfb = parseLenientCfb(Buffer.from(buffer))\n const names = cfb.entries().map(e => e.name)\n if (names.includes(\"Workbook\") || names.includes(\"Book\")) return \"xls\"\n if (names.includes(\"FileHeader\")) return \"hwp\"\n // FileHeader 없어도 BodyText/DocInfo 있으면 hwp\n if (names.some(n => n === \"DocInfo\" || n.startsWith(\"Section\"))) return \"hwp\"\n return \"unknown\"\n } catch {\n return \"unknown\"\n }\n}\n\n/**\n * ZIP 내부 구조 기반 포맷 세분화.\n * HWPX, XLSX, DOCX, PPTX 모두 ZIP이므로 내부 파일로 구분.\n */\nexport async function detectZipFormat(buffer: ArrayBuffer): Promise<\"hwpx\" | \"xlsx\" | \"docx\" | \"pptx\" | \"unknown\"> {\n try {\n const zip = await JSZip.loadAsync(buffer)\n // XLSX: xl/workbook.xml\n if (zip.file(\"xl/workbook.xml\")) return \"xlsx\"\n // DOCX: word/document.xml\n if (zip.file(\"word/document.xml\")) return \"docx\"\n // PPTX: HWPX로 오인하지 않도록 presentation.xml 로 감지\n if (zip.file(\"ppt/presentation.xml\")) return \"pptx\"\n // HWPX: Contents/ 또는 content.hpf 또는 mimetype\n if (zip.file(\"Contents/content.hpf\") || zip.file(\"mimetype\")) return \"hwpx\"\n // 기타 ZIP 내에 section 파일이 있으면 HWPX로 추정\n const hasSection = Object.keys(zip.files).some(f => f.startsWith(\"Contents/\"))\n if (hasSection) return \"hwpx\"\n return \"unknown\"\n } catch {\n return \"unknown\"\n }\n}\n","/**\n * 레이아웃 보존 HTML — 페이지별 standalone SVG 를 `.kordoc-page[data-page]` 로 감싼 자급자족 문서 (#75 Task 4).\n * 의미 HTML(IRBlock → <h1>/<p>/<table>) 이 아니다 — 원본 조판 재현이 목적. CDN·외부 자원 없음.\n * 인쇄 CSS(@page 크기 = 첫 페이지 크기, 페이지마다 break-after) 를 포함해 PDF 경로가 그대로 소비한다.\n */\n\nimport type { RenderScene } from \"./scene.js\"\nimport { escapeXml } from \"./svg-render.js\"\n\nexport interface SceneHtmlOptions {\n /** <title> — 기본 \"kordoc\" */\n title?: string\n}\n\n/**\n * @param scene 페이지 크기 메타(전 페이지)\n * @param pageSvgs 페이지 번호 → standalone SVG (선택된 페이지만 있어도 된다 — 있는 페이지만 방출)\n */\nexport function renderSceneToHtml(scene: RenderScene, pageSvgs: Map<number, string>, options: SceneHtmlOptions = {}): string {\n const title = escapeXml(options.title ?? \"kordoc\")\n const first = scene.pages.find(p => pageSvgs.has(p.page)) ?? scene.pages[0]\n const pageSize = first ? `${first.width}pt ${first.height}pt` : \"auto\"\n const pages = [...pageSvgs.keys()].sort((a, b) => a - b).map(n => {\n const meta = scene.pages.find(p => p.page === n)\n const size = meta ? ` style=\"width:${meta.width}pt;height:${meta.height}pt\"` : \"\"\n return `<div class=\"kordoc-page\" data-page=\"${n}\"${size}>${pageSvgs.get(n)}</div>`\n })\n return `<!doctype html>\n<html lang=\"ko\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'none'; img-src data:; font-src data:; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'\">\n<title>${title}</title>\n<style>\nhtml, body { margin: 0; background: #e9e8e6; }\n.kordoc-document { display: flex; flex-direction: column; align-items: center; gap: 16px; padding: 16px 0; }\n.kordoc-page { position: relative; background: white; box-shadow: 0 1px 4px rgba(0,0,0,.25); }\n.kordoc-page > svg { display: block; width: 100%; height: 100%; }\n@page { size: ${pageSize}; margin: 0; }\n@media print {\n html, body { background: white; }\n .kordoc-document { gap: 0; padding: 0; }\n .kordoc-page { box-shadow: none; break-after: page; page-break-after: always; }\n .kordoc-page:last-child { break-after: auto; page-break-after: auto; }\n}\n</style>\n</head>\n<body>\n<div class=\"kordoc-document\">\n${pages.join(\"\\n\")}\n</div>\n</body>\n</html>\n`\n}\n","/**\n * Print Renderer — Markdown / IRBlock[] → PDF (puppeteer-core 기반).\n *\n * 흐름:\n * blocks → markdown (blocksToMarkdown)\n * markdown → HTML (markdown-it)\n * HTML + 프리셋 CSS → PDF (puppeteer-core)\n *\n * puppeteer-core는 optional peer dep. 미설치 시 markdownToPdf는 명확한 에러를 던지지만\n * `renderHtml()`은 항상 동작 (외부 PDF 엔진과 결합용).\n *\n * 참조: docs/SPEC.md §1.3\n */\n\nimport { existsSync } from \"fs\"\nimport MarkdownIt from \"markdown-it\"\nimport type { IRBlock } from \"../types.js\"\nimport { blocksToMarkdown } from \"../table/builder.js\"\nimport { KordocError, escapeHtml } from \"../utils.js\"\n\n// ─── 타입 ─────────────────────────────────────────\n\nexport type PrintPreset = \"default\" | \"gov-formal\" | \"compact\"\n\nexport interface PageMargin {\n top: string | number // mm 또는 CSS string (\"20mm\", \"1in\")\n right: string | number\n bottom: string | number\n left: string | number\n}\n\nexport interface PrintOptions {\n preset?: PrintPreset\n pageSize?: \"A4\" | \"Letter\"\n orientation?: \"portrait\" | \"landscape\"\n margin?: PageMargin\n /** 페이지 머리글 (HTML 허용, gov-formal 프리셋에서 자동 표시) */\n header?: string\n /** 페이지 바닥글 (HTML 허용) */\n footer?: string\n /** 워터마크 텍스트 (대각선 회색) */\n watermark?: string\n /** 사용자 정의 추가 CSS */\n extraCss?: string\n}\n\n// ─── 프리셋 CSS ───────────────────────────────────\n\nconst PRESETS: Record<PrintPreset, string> = {\n default: `\n @page { size: A4; margin: 20mm; }\n body { font-family: 'Pretendard', 'Malgun Gothic', '맑은 고딕', sans-serif; font-size: 11pt; line-height: 1.6; color: #111; }\n h1 { font-size: 20pt; margin: 1em 0 0.5em; }\n h2 { font-size: 16pt; margin: 1em 0 0.4em; }\n h3 { font-size: 13pt; margin: 0.8em 0 0.3em; }\n p { margin: 0.4em 0; }\n table { border-collapse: collapse; margin: 0.6em 0; width: 100%; }\n th, td { border: 1px solid #555; padding: 4px 8px; text-align: left; vertical-align: top; }\n th { background: #f0f0f0; }\n code { background: #f5f5f5; padding: 1px 4px; border-radius: 2px; font-family: 'D2Coding', Consolas, monospace; }\n pre { background: #f5f5f5; padding: 8px; border-radius: 4px; overflow-x: auto; }\n blockquote { border-left: 3px solid #ccc; padding-left: 12px; color: #555; margin: 0.6em 0; }\n img { max-width: 100%; }\n `,\n \"gov-formal\": `\n @page { size: A4; margin: 25mm 20mm; }\n body { font-family: '함초롬바탕', 'HCR Batang', 'Batang', 'Malgun Gothic', serif; font-size: 11pt; line-height: 1.7; color: #000; }\n h1 { font-size: 18pt; text-align: center; margin: 0.5em 0 1em; letter-spacing: 0.05em; }\n h2 { font-size: 14pt; margin: 1em 0 0.4em; border-bottom: 1px solid #999; padding-bottom: 2px; }\n h3 { font-size: 12pt; margin: 0.8em 0 0.3em; }\n p { margin: 0.3em 0; text-indent: 1em; }\n table { border-collapse: collapse; margin: 0.8em 0; width: 100%; }\n th, td { border: 1px solid #000; padding: 5px 8px; vertical-align: top; }\n th { background: #e8e8e8; font-weight: normal; }\n blockquote { border-left: 2px solid #555; padding-left: 12px; margin: 0.6em 0; }\n `,\n compact: `\n @page { size: A4; margin: 10mm; }\n body { font-family: 'Pretendard', 'Malgun Gothic', sans-serif; font-size: 9pt; line-height: 1.4; color: #111; }\n h1 { font-size: 14pt; margin: 0.5em 0 0.3em; }\n h2 { font-size: 12pt; margin: 0.5em 0 0.3em; }\n h3 { font-size: 10pt; margin: 0.4em 0 0.2em; }\n p { margin: 0.2em 0; }\n table { border-collapse: collapse; margin: 0.3em 0; width: 100%; font-size: 8pt; }\n th, td { border: 1px solid #777; padding: 2px 4px; }\n th { background: #f0f0f0; }\n `,\n}\n\n// ─── HTML 생성 ─────────────────────────────────\n\nconst md = new MarkdownIt({\n html: true,\n linkify: true,\n breaks: false,\n})\n\n// Markdown can come from documents. Keep only the small HTML vocabulary emitted by\n// blocksToMarkdown for merged/nested tables and underlining; render other raw tags as text.\n// Image cells may point into the CLI's per-document folder images/<document>/ (#98).\nconst SAFE_RAW_TAG = /^(?:<\\/?(?:table|thead|tbody|tfoot|tr|th|td|u)>|<br\\s*\\/?>|<(?:th|td)(?: (?:colspan|rowspan)=\"[1-9]\\d*\"){1,2}>|<img src=\"(?:images\\/(?:[^\"'<>\\/\\s]+\\/)?)?image_\\d+\\.(?:png|jpe?g|gif|webp|bmp)\" alt=\"image\">)$/i\nfunction sanitizeRawHtml(raw: string): string {\n return raw.replace(/<[^>]*>|</g, tag => SAFE_RAW_TAG.test(tag) ? tag : escapeHtml(tag))\n}\nmd.renderer.rules.html_block = (tokens, idx) => sanitizeRawHtml(tokens[idx].content)\nmd.renderer.rules.html_inline = (tokens, idx) => sanitizeRawHtml(tokens[idx].content)\n\n/**\n * Markdown 또는 IRBlock[] → HTML 문자열.\n * 외부 PDF 엔진(weasyprint, wkhtmltopdf 등)과 결합 가능.\n */\nexport function renderHtml(\n markdown: string,\n options?: PrintOptions,\n): string {\n const preset = options?.preset ?? \"default\"\n const css = PRESETS[preset] + (options?.extraCss ?? \"\")\n const body = md.render(markdown)\n\n const watermark = options?.watermark\n ? `<div class=\"watermark\">${escapeHtml(options.watermark)}</div>`\n : \"\"\n const watermarkCss = options?.watermark\n ? `\n .watermark {\n position: fixed;\n top: 50%; left: 50%;\n transform: translate(-50%, -50%) rotate(-30deg);\n font-size: 80pt;\n color: rgba(0,0,0,0.08);\n pointer-events: none;\n z-index: 9999;\n white-space: nowrap;\n }`\n : \"\"\n\n return `<!DOCTYPE html>\n<html lang=\"ko\">\n<head>\n<meta charset=\"utf-8\">\n<meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'none'; img-src 'self' data:; font-src 'self' data:; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'\">\n<style>${css}${watermarkCss}</style>\n</head>\n<body>\n${watermark}\n${body}\n</body>\n</html>`\n}\n\n// ─── PDF 생성 ─────────────────────────────────\n\n/**\n * 인쇄용 Chromium 을 띄워 잠근 페이지를 준다 — print(htmlToPdf)·render(renderHtmlToPdf) 두 기동 지점 공용.\n * 페이지 글은 문서에서 온 글이라 정적 조판만 필요하다: JS 를 끄고 data:·about: 밖의 요청(원격 http·로컬 file:)은\n * 전부 막는다. v4.14.4 까지는 문서가 병합 셀·마크다운 이미지로 심은 <img onerror>·<script>·![](http://…) 가\n * 헤드리스 Chrome 에서 실행되고 밖으로 요청했다 — KORDOC_OFFLINE(assertNetworkAllowed)은 Node fetch 만 막아\n * Chromium 요청은 샜다. 기동 timeout 90초: CI(Node 22)가 부하 중 기본 30초 안에 WS 엔드포인트를 못 받아\n * 실패했다(같은 커밋 재실행은 통과한 플레이크)\n */\n/**\n * Chromium 샌드박스 인자 — 기본은 샌드박스를 켠다(신뢰할 수 없는 문서의 그림·글꼴을 디코딩하므로 렌더러 탈출을 막는다).\n * root 로 도는 Linux(컨테이너)는 Chromium 이 샌드박스 기동을 거부해 끄고, 그 밖엔 KORDOC_CHROMIUM_NO_SANDBOX=1 로만 끈다\n */\nexport function chromiumSandboxArgs(env: NodeJS.ProcessEnv = process.env, isRootLinux = process.platform === \"linux\" && process.getuid?.() === 0): string[] {\n return env.KORDOC_CHROMIUM_NO_SANDBOX === \"1\" || isRootLinux ? [\"--no-sandbox\", \"--disable-setuid-sandbox\"] : []\n}\n\nexport async function launchLockedPage(puppeteer: typeof import(\"puppeteer-core\"), executablePath: string) {\n const browser = await puppeteer.default.launch({\n executablePath,\n headless: true,\n timeout: 90_000,\n args: chromiumSandboxArgs(),\n })\n try {\n const page = await browser.newPage()\n await page.setJavaScriptEnabled(false)\n await page.setRequestInterception(true)\n page.on(\"request\", (req) => {\n if (/^(?:data|about):/i.test(req.url())) void req.continue()\n else void req.abort()\n })\n return { browser, page }\n } catch (err) {\n await browser.close()\n throw err\n }\n}\n\n/**\n * puppeteer-core로 HTML → PDF 변환.\n * 환경에 Chromium 실행 파일 필요 (PUPPETEER_EXECUTABLE_PATH 환경변수 또는 자동 감지).\n */\nasync function htmlToPdf(html: string, options?: PrintOptions): Promise<Buffer> {\n let puppeteer: typeof import(\"puppeteer-core\")\n try {\n puppeteer = await import(\"puppeteer-core\")\n } catch {\n throw new KordocError(\n \"PDF 생성에 puppeteer-core가 필요합니다. 설치: npm install puppeteer-core\",\n )\n }\n\n const executablePath =\n process.env.PUPPETEER_EXECUTABLE_PATH ?? findChromiumPath()\n if (!executablePath) {\n throw new KordocError(\n \"Chromium 실행 파일을 찾을 수 없습니다. PUPPETEER_EXECUTABLE_PATH 환경변수를 설정하세요.\",\n )\n }\n\n const { browser, page } = await launchLockedPage(puppeteer, executablePath)\n try {\n // puppeteer 25 부터 setContent 의 waitUntil 에서 networkidle0 이 빠짐. 같은 의미\n // (연결 0개가 500ms 유지)를 waitForNetworkIdle 로.\n await page.setContent(html, { waitUntil: \"load\" })\n await page.waitForNetworkIdle({ idleTime: 500, concurrency: 0 })\n\n const margin = options?.margin\n const pdf = await page.pdf({\n format: options?.pageSize ?? \"A4\",\n landscape: options?.orientation === \"landscape\",\n printBackground: true,\n margin: margin\n ? {\n top: toCss(margin.top),\n right: toCss(margin.right),\n bottom: toCss(margin.bottom),\n left: toCss(margin.left),\n }\n : undefined,\n displayHeaderFooter: !!(options?.header || options?.footer),\n headerTemplate: options?.header ?? \"<div></div>\",\n footerTemplate:\n options?.footer ??\n '<div style=\"font-size:8pt;width:100%;text-align:center;color:#777;\"><span class=\"pageNumber\"></span>/<span class=\"totalPages\"></span></div>',\n })\n return Buffer.from(pdf)\n } finally {\n await browser.close()\n }\n}\n\nfunction toCss(v: string | number): string {\n return typeof v === \"number\" ? `${v}mm` : v\n}\n\n/** Windows/Mac/Linux의 일반적 Chrome 경로 자동 감지 */\nexport function findChromiumPath(): string | null {\n // 사용자가 명시 안 했으면 OS 표준 경로 시도\n // Windows\n const win = [\n \"C:\\\\Program Files\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe\",\n \"C:\\\\Program Files (x86)\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe\",\n process.env.LOCALAPPDATA + \"\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe\",\n \"C:\\\\Program Files\\\\Microsoft\\\\Edge\\\\Application\\\\msedge.exe\",\n \"C:\\\\Program Files (x86)\\\\Microsoft\\\\Edge\\\\Application\\\\msedge.exe\",\n ]\n // Mac\n const mac = [\n \"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome\",\n \"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge\",\n ]\n // Linux\n const linux = [\"/usr/bin/google-chrome\", \"/usr/bin/chromium-browser\", \"/usr/bin/chromium\"]\n\n const candidates =\n process.platform === \"win32\" ? win : process.platform === \"darwin\" ? mac : linux\n\n for (const p of candidates) {\n if (p && existsSync(p)) return p\n }\n return null\n}\n\n/** Markdown → PDF (Buffer). */\nexport async function markdownToPdf(\n markdown: string,\n options?: PrintOptions,\n): Promise<Buffer> {\n const html = renderHtml(markdown, options)\n return htmlToPdf(html, options)\n}\n\n/** IRBlock[] → PDF (Buffer). */\nexport async function blocksToPdf(\n blocks: IRBlock[],\n options?: PrintOptions,\n): Promise<Buffer> {\n const markdown = blocksToMarkdown(blocks)\n return markdownToPdf(markdown, options)\n}\n","/**\n * 레이아웃 HTML → PDF (#75 Task 6). 그리기를 다시 구현하지 않고 페이지 SVG 를 담은 HTML 을 Chromium 이 인쇄한다.\n * puppeteer-core 는 optional peer dep, Chromium 은 번들하지 않는다 — 없으면 KordocError(조치 안내).\n */\n\nimport { KordocError } from \"../utils.js\"\nimport { findChromiumPath, launchLockedPage } from \"../print/renderer.js\"\n\nexport interface ScenePdfOptions {\n /** Chromium 실행 파일 — 미지정 시 PUPPETEER_EXECUTABLE_PATH → OS 표준 경로 자동 탐지 */\n browserExecutablePath?: string\n}\n\n/** 레이아웃 HTML(renderSceneToHtml 산출) → PDF. @page 크기·break-after 는 HTML 의 인쇄 CSS 가 담당 */\nexport async function renderHtmlToPdf(html: string, options: ScenePdfOptions = {}): Promise<Buffer> {\n let puppeteer: typeof import(\"puppeteer-core\")\n try {\n puppeteer = await import(\"puppeteer-core\")\n } catch {\n throw new KordocError(\"PDF 렌더에는 puppeteer-core 가 필요합니다 (npm install puppeteer-core). SVG/HTML/PNG 는 Chromium 없이 됩니다\")\n }\n const executablePath = options.browserExecutablePath ?? process.env.PUPPETEER_EXECUTABLE_PATH ?? findChromiumPath()\n if (!executablePath) {\n throw new KordocError(\"Chromium 실행 파일을 찾을 수 없습니다 — browserExecutablePath 옵션 또는 PUPPETEER_EXECUTABLE_PATH 환경변수를 지정하세요\")\n }\n // JS 끔·data:/about: 밖 요청 차단·기동 90초 — 인쇄 렌더러와 같은 잠금 (launchLockedPage 주석)\n const { browser, page } = await launchLockedPage(puppeteer, executablePath)\n try {\n await page.setContent(html, { waitUntil: \"load\" })\n const pdf = await page.pdf({ printBackground: true, preferCSSPageSize: true })\n return Buffer.from(pdf)\n } finally {\n await browser.close()\n }\n}\n","/**\n * region crop (#75 Task 5) — RenderScene 의 페이지 로컬 bbox 를 래스터 실배율로 픽셀 환산해 잘라낸다.\n * DPI 를 여기서 다시 추정하지 않는다: pixel = pt × rasterize 가 돌려준 scale.\n * 의미 판단(진짜 표인지 조직도인지)은 하지 않는다 — 렌더러가 표라고 아는 개체를 자르는 것뿐.\n */\n\nimport { KordocError } from \"../utils.js\"\nimport type { PageBBox, RenderObjectType, RenderRegion } from \"./scene.js\"\nimport { renderDocumentToScene, type RenderInput, type SceneRenderOptions } from \"./document.js\"\nimport { loadSharp, rasterizePageSvg, type RasterFormat } from \"./rasterize.js\"\n\nexport interface ExtractRegionOptions extends Pick<SceneRenderOptions, \"pages\" | \"reflow\" | \"reflowMode\"> {\n /** 기본 전 유형 */\n types?: RenderObjectType[]\n format?: RasterFormat\n /** bbox 둘레 여백(pt) — 페이지 안으로 클램프 */\n paddingPt?: number\n /** 페이지 래스터 최대 폭 px (crop 해상도) */\n maxWidthPx?: number\n quality?: number\n /** region 선별 — sourceId·id 로 특정 개체만 자를 때 (extractTables). types 필터 뒤에 적용 */\n filter?: (region: RenderRegion) => boolean\n}\n\nexport interface RegionAsset {\n region: RenderRegion\n page: number\n bbox: PageBBox\n mimeType: \"image/png\" | \"image/jpeg\"\n data: Buffer\n widthPx: number\n heightPx: number\n}\n\nexport interface PixelRect { left: number; top: number; width: number; height: number }\n\n/**\n * bbox(pt) → 페이지 픽셀 사각형. 여백 포함 후 페이지 안으로 클램프, 최소 1×1px.\n * 페이지 밖 bbox 는 페이지 가장자리 1px 로 잘려 sharp.extract 에 음수·범위 밖이 절대 가지 않는다.\n */\nexport function cropRect(bbox: PageBBox, scale: number, pageWidthPx: number, pageHeightPx: number, paddingPt = 0): PixelRect {\n const W = Math.max(1, Math.floor(pageWidthPx)), H = Math.max(1, Math.floor(pageHeightPx))\n const clamp = (v: number, hi: number) => Math.min(Math.max(0, v), hi)\n let left = clamp(Math.floor((bbox.x - paddingPt) * scale), W - 1)\n let top = clamp(Math.floor((bbox.y - paddingPt) * scale), H - 1)\n const right = clamp(Math.ceil((bbox.x + bbox.width + paddingPt) * scale), W)\n const bottom = clamp(Math.ceil((bbox.y + bbox.height + paddingPt) * scale), H)\n const width = Math.max(1, right - left), height = Math.max(1, bottom - top)\n if (left + width > W) left = W - width\n if (top + height > H) top = H - height\n return { left, top, width, height }\n}\n\n/** 렌더러가 아는 개체(표·이미지·문단·도형)를 페이지 이미지에서 잘라낸다. 페이지당 래스터 1회 */\nexport async function extractRenderedRegions(input: RenderInput, options: ExtractRegionOptions = {}): Promise<RegionAsset[]> {\n const { scene, pageSvgs } = await renderDocumentToScene(input, { pages: options.pages, reflow: options.reflow, reflowMode: options.reflowMode })\n const types = options.types ? new Set(options.types) : null\n const format = options.format ?? \"png\"\n const wanted = scene.regions.filter(r => (!types || types.has(r.type)) && (!options.filter || options.filter(r)))\n const byPage = new Map<number, Array<{ region: RenderRegion; bbox: PageBBox }>>()\n for (const r of wanted) for (const b of r.regions) if (pageSvgs.has(b.page)) (byPage.get(b.page) ?? byPage.set(b.page, []).get(b.page)!).push({ region: r, bbox: b })\n if (byPage.size === 0) return []\n const sharp = await loadSharp()\n const out: RegionAsset[] = []\n for (const [page, items] of [...byPage.entries()].sort((a, b) => a[0] - b[0])) {\n const meta = scene.pages.find(p => p.page === page)\n if (!meta) throw new KordocError(`페이지 ${page} 메타 없음`)\n const raster = await rasterizePageSvg(pageSvgs.get(page)!, meta.width, meta.height, { format, maxWidthPx: options.maxWidthPx, quality: options.quality })\n for (const { region, bbox } of items) {\n const rect = cropRect(bbox, raster.scale, raster.widthPx, raster.heightPx, options.paddingPt ?? 0)\n const pipeline = sharp(raster.data).extract(rect)\n const data = format === \"jpeg\" ? await pipeline.jpeg({ quality: options.quality ?? 85 }).toBuffer() : await pipeline.png().toBuffer()\n out.push({ region, page, bbox, mimeType: raster.mimeType, data, widthPx: rect.width, heightPx: rect.height })\n }\n }\n // 문서(region) 순서 유지 — 페이지 순회로 섞인 것을 region 등장 순으로 되돌린다\n const order = new Map(scene.regions.map((r, i) => [r.id, i]))\n out.sort((a, b) => (order.get(a.region.id)! - order.get(b.region.id)!) || (a.page - b.page))\n return out\n}\n"],"mappings":"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AAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAC/X,uBAAQ,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,uBAAQ,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GA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AAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EACnY,6BAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EACpY,6BAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EACpY,6BAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,6BAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,6BAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACnY,6BAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACnY,6BAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACnY,6BAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,uBAAQ,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,uBAAQ,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,uBAAQ,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACjY,6BAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,uBAAQ,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACjY,6BAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,iBAAO,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAChY,8BAAU,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,8BAAU,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,wBAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACpY,wBAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACpY,kBAAkB,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAC3Y,kBAAkB,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAC3Y,iBAAiB,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAC3Y,gBAAgB,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACzY,gBAAgB,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACzY,uBAAuB,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACjZ,kBAAkB,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAC5Y,kBAAkB,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAC3Y,uBAAuB,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAChZ,iBAAiB,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAA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KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAC1Y,wBAAwB,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAChZ,qBAAqB,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAC7Y,aAAa,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACrY,aAAa,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACrY,8BAAU,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACnY,WAAW,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACrY,iBAAiB,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAC3Y,YAAY,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EACvY,eAAe,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACvY,eAAe,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACvY,cAAc,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACxY,cAAc,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,K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KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EAC1Y,mCAAU,CAAC,KAAI,KAAI,KAAI,KAAI,KAAK,KAAK,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EACxY,mCAAU,CAAC,KAAI,KAAI,KAAI,KAAI,KAAK,KAAK,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EACzY,mCAAU,CAAC,KAAI,KAAI,KAAI,KAAI,KAAK,KAAK,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EACzY,mCAAU,CAAC,KAAI,KAAI,KAAI,KAAI,KAAK,KAAK,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EACxY,mCAAU,CAAC,KAAI,KAAI,KAAI,KAAI,KAAK,KAAK,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAK,KAAI,KAAI,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KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EAC1Y,mCAAU,CAAC,KAAI,KAAI,KAAI,KAAI,KAAK,KAAK,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EAC3Y,mCAAU,CAAC,KAAI,KAAI,KAAI,KAAI,KAAK,KAAK,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EAC1Y,mCAAU,CAAC,KAAI,KAAI,KAAI,KAAI,KAAK,KAAK,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EACzY,mCAAU,CAAC,KAAI,KAAI,KAAI,KAAI,KAAK,KAAK,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAI;AAAA,EACzY,6BAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EACjY,8BAAU,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,gBAAM,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAC9X,sBAAO,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAC/X,sBAAO,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAC/X,uBAAQ,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,sBAAO,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAChY,kCAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,kCAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,MAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,GAAG;AAAA,EAClY,kCAAS,CAAC,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAK,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KAAI,KA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AA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAC/F,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAC/F,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAC/F,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAC/F,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,EAC3G;AAAA,EACA,sBAAsB;AAAA,IACpB,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAC/F,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAC/F,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAA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OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,MAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAC5H,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM,OAAO;AAAA,IAAM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AK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,MAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IACnH,OAAO;AAAA,IAAK,OAAO;AAAA,EACrB;AAAA,EACA,4BAAQ;AAAA,IACN,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,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AA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAC/F,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAC/F,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK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;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAM,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAChG,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAM,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAChG,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAC/F,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAC/F,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAC/F,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3G,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,EACjC;AAAA,EACA,uBAAa;AAAA,IACX,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAC/F,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,IAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAC/F,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AA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AG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IA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AAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,I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AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAClM;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,EAAG;AAAA,EAC7L,IAAI;AAAA,IACF,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAM,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAI,MAAO;AAAA,IAAK,MAAO;AAAA,IACvI,MAAO;AAAA,IAAM,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC5I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3I,OAAO;AAAA,IAAK,OAAO;AAAA,IA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AAI,MAAO;AAAA,IAAK,MAAO;AAAA,IACvI,MAAO;AAAA,IAAM,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC5I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3I,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3I,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3I,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3I,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,QAAQ;AAAA,EAC1G;AACF;AAEA,IAAM,qBAAkC;AAAA,EACtC,KAAK;AAAA,EACL,OAAO;AAAA,IAAC;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAC9L;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,EAAG;AAAA,EACjM,IAAI;AAAA,IACF,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,MAAO;AAAA,IAAK,MAAO;AAAA,IAAM,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAI,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAM,MAAO;AAAA,IAC5I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3I,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3I,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3I,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3I,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,EACzD;AACF;AAEA,IAAM,oBAAiC;AAAA,EACrC,KAAK;AAAA,EACL,OAAO;AAAA,IAAC;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAC9L;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,EAAG;AAAA,EACjM,KAAK;AAAA;AAAA,EACL,IAAI;AAAA,IACF,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IAAK,KAAK;AAAA,IACnH,MAAO;AAAA,IAAK,MAAO;AAAA,IAAM,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAI,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAM,MAAO;AAAA,IAC5I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAC3I,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,MAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA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AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,MAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAC3L,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,OAAO;AAAA,IAAK,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,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAC3I,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAC3I,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAC3I,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAC3I,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAC3I,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAK,MAAO;AAAA,MAAM,MAAO;AAAA,MAC5I,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OAAO;AAAA,MAC3I,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OAAO;AAAA,MAAK,OA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;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAC7E,CAAC;AAED,IAAM,YAAY,IAAI,WAAW;AAAA,EAC/B;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC3E;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;A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","names":["starts","k","sw","num","depth","f","k","rem","p","formatHeadNumber","num","num","pt","ln","elements","num","w","st","hRel","hAlign","ho","base","span","x0","top","omLx","omRx","xs","x","x","y","pt","fh","pt","splitSaved","va","cid","formatHeadNumber","pageNo","MAX_DECOMPRESS_SIZE","TAG_ID_MAPPINGS","readRecords","CTRL_ID_TBL","num","swap32","num","i","table","require","TAG_BORDER_FILL","cid","swap32","CTRL_TBL","CTRL_GSO","CTRL_SECD","CTRL_COLD","CTRL_EQED","o","ctrlIdx","k","tag","JSZip","JSZip"]}