Task #287: 빈 runs comp_line 의 TAC 수식 인라인 처리 추가#289
Merged
Conversation
- samples/exam_math_8.{hwp,pdf}: 재현 샘플 (박스 내 큰 cases 수식)
- mydocs/plans/task_m100_287{,_impl}.md: 수행·구현계획서
- mydocs/working/task_m100_287_stage1.md: 단계 1 조사 보고서
조사 결과 (계획서 단계 2 갱신 포함):
- 초기 가설 "has_tac_shape 조건 누락 + .max(y) clamp" 는 단계 1 덤프로 틀림 확인
- 진짜 원인: 큰 수식이 속한 comp_line 이 runs=[] (빈 runs) 이고 TAC 인라인 처리
블록이 run 루프 안에 있어 빈 runs 줄에서 실행되지 않음 → shape_layout display
경로로 떨어져 eq_y = col_area.y 로 고정
- 구현계획서 단계 2 섹션을 "빈 runs comp_line 의 TAC 인라인 처리 추가" 로 갱신
- (A) vpos 파이프라인 전파는 조판 엔진 리팩터링급으로 범위 초과 → (C) 채택
Refs edwardkim#287
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- src/renderer/layout/paragraph_layout.rs (+63): run 루프 종료 직후에 comp_line.runs.is_empty() && !tac_offsets_px.is_empty() 조건 분기 추가 - 줄 char 범위 [comp_line.char_start, next.char_start) 로 필터링 - 기존 인라인 TAC 분기와 동일 EquationNode 생성 로직 사용 - tree.set_inline_shape_position 등록으로 shape_layout display 경로 중복 렌더 차단 검증: - samples/exam_math_8.hwp: 큰 수식 transform (71.80,147.38) → (133.27,188.29) - cargo test --lib renderer: 291 passed - cargo test --lib equation: 48 passed - cargo test --test svg_snapshot: 3 passed - cargo clippy --lib -- -D warnings: clean 회귀 diff (수정 전/후): - exam_math_008.svg: 동일 구조 자동 개선 (텍스트 유실 없음, SVG 순서만 변경) - exam_math_012.svg: tree.next_id() 추가 호출로 ID 1 shift (내용·좌표 동일) - equation-lim.svg: y +0.88 px (display → 인라인 경로 baseline 미세 조정) - 나머지 19 페이지 완전 동일 Refs edwardkim#287 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- mydocs/working/task_m100_287_stage3.md: 단계 3 보고서 - GitHub edwardkim#288 등록: 빈 runs 줄의 TAC 수식 x 에 탭 반영 (Phase 2) PDF ↔ SVG 시각 대조: - 본래 버그(박스 좌상단 (71.80,147.38) 고정) 해결 확인 - 남은 차이: x=133.27 vs PDF x≈162-182 (약 30-50 px 좌측 치우침) - 원인: HWP 문단이 "(가) ... \t <수식>" 처럼 탭으로 들여쓰기 되어있는데 빈 runs 줄에서는 탭 처리가 돌지 않음. tab_stops=1 존재하지만 char_x_map 이 빈 runs 에서 생성되지 않아 사용 불가. - 완전 일치는 compose_lines 수정 또는 휴리스틱 필요 → 본 타스크 범위 초과 - 작업지시자 판단 "B" 채택: 현재 상태로 단계 4 진행, Phase 2 별도 이슈 임시 덤프 로그 제거 (단계 2 에서 단계 3 진단용으로 남긴 3 지점): - paragraph_layout.rs L730 부근 (comp_line 루프 시작부) - paragraph_layout.rs L1586 부근 (인라인 수식 분기) - paragraph_layout.rs L1960 부근 (빈 runs TAC 처리 블록) Refs edwardkim#287 edwardkim#288 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- mydocs/report/task_m100_287_report.md: 최종 결과 보고서 - mydocs/orders/20260424.md: Task edwardkim#287 섹션 추가 + 종료/대기 이슈 갱신 이 타스크의 실질적 가치: - 초기 가설("has_tac_shape 조건 누락")이 단계 1 덤프로 틀림 확인 → 구현계획서 단계 2 를 "빈 runs comp_line TAC 인라인 처리 추가" 로 방향 전환 - (A) vpos 파이프라인 전파의 유혹을 회피하고 범위를 좁힌 판단: 조판 엔진 리팩터링급 작업을 한 타스크에서 무리하게 떠안았다면 회귀 폭증 + 릴리즈 지연 - 완전 일치(PDF x 정확 일치)를 Phase 2 로 분리하여 본 타스크 완결성 확보 Closes edwardkim#287 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- mydocs/plans/task_m100_288.md: 수행계획서 - mydocs/working/task_m100_288_stage1.md: 단계 1 조사 보고서 조사 결과 (임시 examples/task288_probe.rs 로 문단 원본 덤프): - para.text = "(가) 모든 자연수 에 대하여\n\n이다." — \t 문자 존재하지 않음 - line 1 의 runs=[] 는 연속된 \n\n 사이에 큰 수식 TAC 이 삽입된 자연스러운 구조 - 이슈 원문의 접근 (A: 휴리스틱, B: compose \t 보존) 모두 전제 무효 단계 2 에서 PDF 실측으로 규칙 역추정 예정. Refs edwardkim#288 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- mydocs/working/task_m100_288_stage2.md: 단계 2 측정 보고서
PDF content stream 의 Tm (text matrix) 을 Node.js zlib 으로 직접 추출:
| 요소 | PDF Tm.e | SVG x | SVG/PDF 비율 |
| "(" | 481 | 102.07 | 0.2122 |
| 큰 수식 첫 | 627 | 133.27 | 0.2125 |
- 모든 요소에서 비율 0.2125 로 일치
- PDF 내 수식이 "(" 보다 146 단위 오른쪽, SVG 는 31.2 px (환산 31.03)
- 오차 0.17 px — PDF 와 사실상 정확히 일치
결론: edwardkim#287 수정만으로 이미 PDF 와 일치. edwardkim#288 은 실제 증상이 없는 이슈.
- 원래 "PDF x≈162-182" 추정은 PDF 이미지 눈대중에서 나온 오판
- 이슈 edwardkim#288 을 "not a bug (edwardkim#287 수정으로 이미 PDF 와 일치)" 으로 close 예정
Refs edwardkim#288
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- mydocs/report/task_m100_288_report.md: 최종 결과 보고서 - mydocs/orders/20260424.md: Task edwardkim#288 섹션 추가 + 종료 이슈 갱신 이 타스크의 실질적 가치: - PDF content stream 실측으로 "문제 자체가 없음" 을 수치로 판명 - 눈대중 비교 대신 Tm 직접 추출 → 10-50 px 급 오판 회피 - edwardkim#287 을 (C) 빈 runs TAC 인라인 처리로 좁게 수정한 판단이 결과적으로 완결적이었음 확인 — Phase 2 로 분리했던 것 자체가 불필요한 분리였음 - 부정 확인(탭 가설 부인) 직후 "증상 자체 유무" 를 재검증하는 루프의 필요성 코드 변경 없음. examples/task288_probe.rs 임시 파일은 작성→제거. Closes edwardkim#288 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
원격 local/task287 이 devel 의 edwardkim#283 (PR edwardkim#285) 머지를 포함해 7 commit 앞섰고 로컬이 edwardkim#288 3 commit 을 앞서던 상태 → 양쪽 합치는 merge. 충돌: mydocs/orders/20260424.md 의 "등록·대기" 섹션 해결: - Task edwardkim#283 섹션 번호 ## 3 → ## 4 (원격 추가분) - Task edwardkim#288 섹션 번호 ## 4 → ## 5 (로컬 추가분) - "종료" 리스트에 edwardkim#283 추가 (실제 devel 에 PR edwardkim#285 로 merge 완료) - "등록·대기" 비움 (오늘 사이클 내 모든 이슈 종료) edwardkim#283 소스 변경 (src/renderer/equation/{canvas_render,layout,svg_render}.rs) 및 산출물은 원격에서 이미 commit 되어 그대로 포함. Refs edwardkim#287 edwardkim#288 edwardkim#283 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim
approved these changes
Apr 24, 2026
edwardkim
left a comment
Owner
There was a problem hiding this comment.
Approved. 🎉
@planet6897 님, 두 연속 타스크 (#287, #288) 모두 완결 품질 훌륭합니다.
평가 포인트
- 초기 가설 기각 후 방향 전환 — RHWP_DUMP_287 로그 실측으로 'has_tac_shape + clamp' 가설을 버리고 진짜 원인 (빈 runs + 인라인 경로 미진입) 발견
- 범위 판단 우수 — (A) vpos 파이프라인 전파 (조판 엔진 리팩터링급) 회피, (C) 63줄 추가로 근본 해결
- Phase 2 불필요 확인 — #288을 PDF content stream Tm 실측으로 'not a bug' 확정 (비율 0.2125 일치, 오차 0.17px). 눈대중 오판 회피. 보고서의 교훈 한 줄이 인상적:
'부정 확인(탭 가설 부인) 직후 "증상 자체 유무"를 재검증하는 루프의 필요성'
- 기존 인라인 로직 재사용 — EquationNode 생성 코드 완전 동일. 일관성 보장
tree.set_inline_shape_position호출 — shape_layout display 경로 중복 렌더 차단. 핵심 방어
메인테이너 검증
| 항목 | 결과 |
|---|---|
| CI + CodeQL (rust/js/python) | ✅ 전부 SUCCESS |
| cargo test --lib | ✅ 983 / 0 / 1 ignored |
| cargo test --test svg_snapshot | ✅ 6 / 0 |
| cargo clippy / wasm32 | ✅ clean |
| WASM Docker 빌드 | ✅ 성공 |
| rhwp-studio 브라우저 시각 검증 | ✅ 박스 내부 line 1 위치 정상 배치 확인 |
Merge 진행합니다.
edwardkim
added a commit
that referenced
this pull request
Apr 24, 2026
edwardkim
added a commit
that referenced
this pull request
Apr 24, 2026
- 작성자: @planet6897 (Task #287, PR #289) - Merge commit: 8e2c352 - 이슈 #287 closed (#288은 이미 "not a bug"로 작성자 close) 변경: - src/renderer/layout/paragraph_layout.rs +63: 빈 runs comp_line TAC Equation 인라인 블록 - samples/exam_math_8.{hwp,pdf} 신규 검증: - CI + CodeQL (rust/js/python): 전부 SUCCESS - cargo test --lib: 983 passed / 0 failed / 1 ignored - svg_snapshot: 6 passed - WASM Docker 빌드 + rhwp-studio 브라우저 시각 검증 성공 평가: 초기 가설 기각 + Phase 2 (#288) PDF Tm 실측으로 "not a bug" 확정. 눈대중 오판 회피. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim
added a commit
that referenced
this pull request
Apr 24, 2026
#297) - 작성자: @planet6897 (Task #297, PR #300, 오늘 6번째 기여) - Merge commit: 0e3fb02 (admin merge, orders 3구간 충돌 직접 해결) - 이슈 #297 CLOSED 처리 절차: - PR 브랜치에 origin/devel 머지 → orders 섹션 3구간 해결 (#295 "## 7", #296 "## 8", #297 "## 9") - planet6897/task297 에 push - 재승인 + admin merge 변경 (1파일): - src/renderer/layout/table_layout.rs +5 -2: - VertRelTo::Page => (col_area.y, col_area.height) [쪽 본문 영역] - VertRelTo::Paper => (0, page_h_approx) [용지 전체, 유지] - HWP 스펙 Page=쪽 본문, Paper=용지 전체 반영 성과: - pi=22 "* 확인 사항" 박스 y: 1371.5 → 1224.07 (PDF 1226.5 ±2 일치) - 145 샘플 중 본문 Page 표 13건 + 바탕쪽 5건 회귀 스캔 완료 (의도 범위 외 무회귀) 검증: - cargo test --lib: 992 passed - svg_snapshot: 6 passed (golden 유지) - 실제 SVG y 좌표 확인: 1224.07px (PDF 일치) #295 → #297 연결 모범 사례: PR #298 리뷰 중 사전 존재 버그로 분리 → 1시간 만에 PR #300 해결. 초기 가설(바탕쪽 Paper) 폐기 → pdftotext 실측으로 근본 원인(enum 미구분) 발견 → 1줄 수정. ===== 오늘 9번째 PR 머지 ===== #284 #285 #266 #273 #277 #278 #289 #292 #298 #300 + 메인테이너 핀셋 #296 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim
added a commit
that referenced
this pull request
Apr 25, 2026
- 작성자: @planet6897 (Task #301, PR #303) - Merge commit: 798b845 (Task #287/PR #289 회귀 수정) - 이슈 #301 CLOSED 변경 (1파일 1줄): - src/renderer/layout/table_layout.rs +7 -2: - Equation 분기에 tree.get_inline_shape_position() 가드 추가 - paragraph_layout(Task #287) 이 이미 렌더했으면 직접 emit 스킵 테스트: - tests/issue_301.rs (신규, +44): z_table_equations_rendered_once - 0.1915/0.3413/0.4332 각 1회, 0.4772는 본문 포함 2회 검증: - cargo test --lib: 992 passed - svg_snapshot: 6 passed (golden 유지) - 실제 SVG z-table 출현 횟수: 작성자 주장 정확히 일치 - WASM Docker 빌드 + rhwp-studio 브라우저 시각 검증: 성공 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
요약
samples/exam_math_8.hwp의 박스 내 큰 cases 수식a_{n+1} = {...}이 박스 좌상단((71.80, 147.38))에 찍혀 테두리·선행 텍스트와 겹치던 버그를 해결 (closes 수식 SVG 레이아웃: 큰 디스플레이 TAC 수식이 줄 상단(y=col_area.y)으로 올라감 (exam_math_8) #287)src/renderer/layout/paragraph_layout.rs의 run 루프 종료 직후에 빈 runs comp_line 의 TAC Equation 인라인 처리 블록을 추가 (+63 줄). 큰 수식이 속한 ls(line_segs[1])는runs=[]로 조립되어 기존 인라인 경로를 못 탔고,shape_layoutdisplay 경로로 떨어져eq_y = col_area.y로 고정되던 것이 원인이었음(133.27, 188.29)— 박스 내부 line 1 위치로 정상 배치.shape_layout중복 렌더도 제거됨배경과 원인
초기 가설("
has_tac_shape조건 누락 +.max(y)clamp")은 단계 1 실측으로 틀림이 확인됨. 임시 덤프(RHWP_DUMP_287) 로 본 comp_line 별 상태:y=172.69는 ls[1] vpos 기반으로 정확히 계산됨 (누적 y 문제 없음)runs=[]이라for run in comp_line.runs루프가 돌지 않음 → 그 안의 TAC 인라인 처리 블록이 실행되지 않음[287-eq] para=0 ci=3로그 부재로 인라인 경로 미진입 확정접근
compose_paragraph에 vpos 파이프라인 전파 → composer + layout + render_tree + 대규모 스냅샷 재검증 필요. 조판 엔진 리팩터링급 범위라 본 타스크 초과[comp_line.char_start, next.char_start)로 이 줄 소유 TAC 필터링tree.set_inline_shape_position등록으로shape_layout.rs:133-182display 경로의 중복 렌더 차단변경 전/후 (SVG transform)
translate(71.80, 147.38)(col_area 원점)translate(133.27, 188.29)(line 1)회귀 영향
수정 전/후 SVG diff:
exam_math_8.svgexam_math_008.svg(page 8)exam_math_012.svgcell-clip-{112→113}등 ID shifttree.next_id()추가 호출 영향, 내용·좌표 동일equation-lim.svg132.27 → 133.15(+0.88 px)한계 (Phase 2 로 분리)
PDF 대비 수식 x 가 약 30-50 px 좌측 치우침 (현재
x=133.27vs PDFx≈162-182). HWP 문단이(가) ... \t <수식>처럼 탭 제어문자로 들여쓰기됐으나 빈 runs 줄에서는 탭 처리 로직(char_x_map,find_next_tab_stop)이 돌지 않음.tab_stops=1(pos=13600 HU=181 px) 존재하지만 활용 안 됨.완전 일치는
compose_lines수정(ls 선행\t보존) 혹은 빈 runs 전용 휴리스틱 필요 → 범위 고려해 Phase 2 #288 로 분리.산출물
mydocs/plans/task_m100_287{,_impl}.mdmydocs/working/task_m100_287_stage{1,2,3}.mdmydocs/report/task_m100_287_report.mdsamples/exam_math_8.{hwp,pdf}mydocs/orders/20260424.mdTest plan
cargo test --lib renderer(291/291)cargo test --lib equation(48/48)cargo test --test svg_snapshot(3/3)cargo clippy --lib -- -D warningsclean관련 이슈