Skip to content

fix: 1×1 래퍼 표 shortcut 다수 중첩 표 누락 수정 (#726)#817

Closed
oksure wants to merge 1 commit into
edwardkim:develfrom
oksure:contrib/fix-nested-table-wrapper
Closed

fix: 1×1 래퍼 표 shortcut 다수 중첩 표 누락 수정 (#726)#817
oksure wants to merge 1 commit into
edwardkim:develfrom
oksure:contrib/fix-nested-table-wrapper

Conversation

@oksure

@oksure oksure commented May 11, 2026

Copy link
Copy Markdown
Contributor

문제

table-vpos-01.hwpx 5쪽 nested 11×3 그리드가 SVG 출력에서 완전히 누락됩니다 (#726).

근본 원인

table_layout.rs의 1×1 래퍼 표 감지 최적화:

if let Some(nested) = cell.paragraphs.iter()
    .flat_map(|p| p.controls.iter())
    .find_map(|c| if let Control::Table(t) = c { Some(t) })
{
    return self.layout_table(..., nested, ...);
}

find_map이 첫 번째 Control::Table만 반환 후 즉시 return → 셀 안에 표가 2개 이상일 때 두 번째부터 렌더링 누락.

table-vpos-01.hwpx p.5 구조:

  • 외곽 1×1 래퍼 표
    • 셀[0] paras=2
      • p[0]: 제목 1×1 표 ✅ (find_map으로 찾음)
      • p[1]: 본문 11×3 그리드 ❌ (find_map 이후 return으로 스킵)

수정

셀 안 중첩 표가 정확히 1개일 때만 shortcut 적용. 2개 이상이면 일반 layout_table_cells 경로로 폴스루하여 모든 중첩 표 렌더링.

검증

SVG 내보내기 비교 (table-vpos-01.hwpx p.5):

항목 수정 전 수정 후
SVG 행 수 89 485
<text> 요소 55 343
CharOverlap 사각형 0 9
그리드 내용 없음 4대 추진전략 + 12대 추진과제 전체
  • cargo test — 전체 통과
  • cargo clippy -- -D warnings — 경고 없음

감사합니다.

1×1 래퍼 표 감지 최적화가 셀 안에 여러 중첩 표가 있을 때 첫 번째 표만
렌더링하고 나머지를 누락시키는 결함 수정.

근본 원인: find_map으로 첫 번째 Control::Table만 반환 후 즉시 return하여,
table-vpos-01.hwpx p.5의 외곽 1×1 셀 안 2개 표(제목 1×1 + 본문 11×3)
중 본문 11×3 그리드가 렌더링되지 않음.

수정: 셀 안 표가 정확히 1개일 때만 shortcut 적용, 다수 표 시 일반 경로로
폴스루하여 layout_table_cells에서 모든 중첩 표를 렌더링.

검증:
- table-vpos-01.hwpx p.5 SVG: 89행→485행, <text> 55→343개
- 4대 추진전략 + 12대 추진과제 전체 텍스트 + CharOverlap 사각형 9개 출력
- cargo test 전체 통과
- cargo clippy 경고 없음

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 11, 2026 05:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a rendering omission in the table layout engine where a 1×1 “wrapper table” shortcut caused nested tables beyond the first to be skipped, leading to missing SVG output for documents like table-vpos-01.hwpx (Issue #726).

Changes:

  • Restricts the 1×1 wrapper-table shortcut to cases where the wrapper cell contains exactly one nested table.
  • Falls back to the normal cell layout path when multiple nested tables exist, ensuring all nested tables render.
Comments suppressed due to low confidence (1)

src/renderer/layout/table_layout.rs:147

  • layout_table now only applies the 1×1 wrapper-table shortcut when the cell contains exactly one nested table. However, HeightMeasurer::measure_table_impl still shortcuts on any 1×1 wrapper with no visible text and uses find_map (first nested table only). For wrapper cells that contain 2+ nested tables (the case fixed here), this will under-measure the wrapper table height and can cause pagination/overlap/clipping issues since layout will render all nested tables but measurement will not account for them. Please update the height-measurement wrapper detection to use the same nested_table_count == 1 condition (or otherwise ensure measurement matches the new layout behavior).
        // 1x1 래퍼 표 감지: 외곽 표를 무시하고 내부 표를 직접 렌더링
        // 단, 셀 안에 표가 정확히 1개일 때만 shortcut 적용 (다수 표 시 일반 경로)
        if table.row_count == 1 && table.col_count == 1 && table.cells.len() == 1 {
            let cell = &table.cells[0];
            let has_visible_text = cell.paragraphs.iter()
                .any(|p| p.text.chars().any(|ch| !ch.is_whitespace() && ch != '\r' && ch != '\n'));
            let nested_table_count = cell.paragraphs.iter()
                .flat_map(|p| p.controls.iter())
                .filter(|c| matches!(c, Control::Table(_)))
                .count();
            if !has_visible_text && nested_table_count == 1 {
                if let Some(nested) = cell.paragraphs.iter()
                    .flat_map(|p| p.controls.iter())
                    .find_map(|c| if let Control::Table(t) = c { Some(t.as_ref()) } else { None })
                {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@edwardkim

Copy link
Copy Markdown
Owner

@oksure PR 검토 결과 본 PR 정정 영역 영역 이미 devel HEAD 영역 영역 해결됨 + Issue #726 영역 영역 진짜 본질 영역 영역 본 PR 영역 영역 무관 영역 영역 발견되어 close 후 분리 PR 재제출 권장드립니다.

본 환경 시각 비교 — devel HEAD vs PR #817 적용 후

작업지시자 요청 영역 영역 본 PR cherry-pick 후 5쪽 SVG 내보내기 비교:

=== before (devel HEAD, Task #688 가드) ===
text=343  polygon=0  image=0  path=2  lines=474  size=131K

=== after (PR #817 nested_table_count == 1 가드) ===
text=343  polygon=0  image=0  path=2  lines=474  size=131K

diff: byte-identical (exit code 0)

→ 두 SVG 영역 영역 완전 동일. PR 정정 영역 영역 본 환경 영역 영역 시각적/구조적 효과 부재.

본 PR 본질 영역 영역 Task #688 영역 영역 이미 해결됨

devel HEAD 영역 영역 src/renderer/layout/table_layout.rs::layout_table (Task #688, PR #694) — 다른 가드 영역 영역 동일 본질 해결:

// (Task #688) 셀 paragraphs 가 2개 이상이면 첫 nested 표만 unwrap 시 나머지
// paragraph 의 nested 표가 누락되므로 paragraphs.len() == 1 가드를 둔다.
if table.row_count == 1 && table.col_count == 1 && table.cells.len() == 1 {
    let cell = &table.cells[0];
    if cell.paragraphs.len() == 1 {  // ← Task #688 가드
        ...
    }
}

table-vpos-01.hwpx p.5 영역 영역 셀[0] paras=2paragraphs.len() == 1 가드 false → shortcut 우회 → 일반 경로 영역 영역 모든 nested table 정상 렌더링.

본 PR 영역 영역 nested_table_count == 1 가드 — 셀[0] 영역 영역 nested table 1개 (제목 1×1 표) 영역 영역 가드 true 영역 영역 shortcut 적용 영역 영역 — 그러나 결과적으로 SVG 영역 영역 두 가드 영역 영역 byte-identical (path 영역 영역 다른 분기 영역 영역 처리되지만 최종 출력 동일).

추가로, Task #688 영역 영역 외곽 박스 border 렌더링 보존 (exam_social.hwp pi=15 자료 박스 등 영역 영역 padding + border_fill 영역 영역 외곽 4 라인 추가) 영역 영역 정교한 정합 영역 영역 보존. 본 PR 영역 영역 적용 시 외곽 박스 border 회귀 가능성 영역 영역.

Issue #726 영역 영역 진짜 본질 — 화살표 도형 미출력

Issue #726 본문 영역 영역 명시된 결함:

samples/table-vpos-01.hwpx 5쪽 nested 11×3 그리드의 4대 그룹 사이 구분 도형 2개가 SVG 출력에서 누락. PDF 권위본은 4대 그룹 (참여소통/기본사회/공직혁신/공공 AX) 사이를 가르는 구분 도형이 보이는 반면, 본 환경 SVG 에서 해당 도형 2개가 보이지 않음.

본 환경 SVG 점검 (PR #817 적용 후에도 동일):

  • <polygon> 0개
  • <image> 0개
  • IR 영역 영역 셀[18] ctrl[0] 다각형: tac=true, wrap=TopAndBottom 영역 영역 1개 존재

→ 본 PR 영역 영역 nested table 출력 정정 (이미 Task #688 해결) 영역 영역 무관, 셀 안 다각형/도형 컨트롤 SVG 렌더링 경로 누락 영역 영역 별 본질.

분리 PR 가이드 (Issue #726 본질)

본 환경 영역 영역 점검 영역 영역 두 결함 후보 (Issue #726 본문):

후보 (a) — SVG renderer 다각형 미출력

src/renderer/ 도형 분기 (svg.rs / web_canvas.rs / paint/json.rs) 영역 영역 셀 안 다각형 컨트롤 (tac=true, wrap=TopAndBottom) 영역 영역 SVG 출력 경로 누락 또는 cell-clip 외부 위치.

진단 권장:

rhwp dump samples/table-vpos-01.hwpx -s 0 -p 34
# pi=34 nested 11×3 그리드 영역 영역 셀[18] ctrl[0] 다각형 1개 확인

후보 (b) — HWPX 파서 다각형 1개 누락

4 그룹 사이 구분 = 3 도형 영역 영역 PDF 영역 영역 보이는데 IR 영역 영역 1개만 — 셀[6]/셀[13] 영역 영역 ctrls=0 영역 영역 비어 있음. src/parser/hwpx/ table cell 안 GenShape 파싱 영역 영역 결함 가능성.

처리 결정

PR #815 영역 영역 본 PR 영역 영역 두 PR 연속 close 영역 영역 양해 부탁드립니다. PDF 권위본 영역 영역 직접 점검 + 본 환경 IR 영역 영역 dump 명령 점검 영역 영역 본질 진단 후 분리 PR 영역 영역 적극 환영합니다.

수고하셨습니다.

@edwardkim edwardkim closed this May 11, 2026
edwardkim added a commit that referenced this pull request May 11, 2026
- mydocs/pr/archives/pr_817_review.md (Task #688 이미 해결 + byte-identical SVG 분석)
- mydocs/pr/archives/pr_817_report.md (옵션 C 처리 결과 + Issue #726 진짜 본질 분리)
- mydocs/orders/20260512.md 신규 (5/12 사이클 시작)

핵심 본질:
- PR 본문 본질 (nested 11x3 그리드 누락) → Task #688 (PR #694, paragraphs.len() 가드 + 외곽 박스 border) 이미 해결
- 작업지시자 시각 비교 요청 → 5쪽 SVG byte-identical (diff exit code 0)
- Issue #726 진짜 본질 (4대 그룹 사이 화살표 도형 미출력) → 본 PR 무관, 별 PR 후속
- Issue #726 OPEN 유지

분리 PR 가이드:
- 후보 (a): src/renderer/ 도형 분기 (svg/canvas/paint json 4 backend)
- 후보 (b): src/parser/hwpx/ table cell GenShape 파싱
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants