From 7ac87770a990fe8eba24745306352d49418a66c8 Mon Sep 17 00:00:00 2001 From: Jaeook Ryu Date: Wed, 6 May 2026 09:02:04 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20Picture=20flip/rotation=20=EB=88=84?= =?UTF-8?q?=EB=9D=BD=20=ED=9A=8C=EA=B7=80=20=EC=A0=95=EC=A0=95=20=E2=80=94?= =?UTF-8?q?=20Task=20#519=20=EC=A0=95=EC=A0=95=20=EC=9E=AC=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20(closes=20#618)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 증상: samples/exam_eng.hwp 4페이지 28번 박스 종이-말림 데코레이션 그림이 horz_flip+vert_flip 속성을 가지고 있으나 SVG 출력에 transform 래퍼가 누락되어 잘못된 위치(우하단)로 렌더되어 본문과 겹쳐 보이지 않음. 원인: Task #519 (#519, 7ead89d) 의 정정이 local/devel 에는 머지되었으나 stream/devel 로의 승격이 한 번도 일어나지 않음. local/devel..stream/devel 의 첫부모 경로상 Task #519 묶음 머지 a7e43f9 가 부재 — `git branch -a --contains 7ead89d` 결과는 local/devel + local/task* 만 표시. 정정: 6 ImageNode 생성 지점에 transform: extract_shape_transform(&pic.shape_attr) 재적용. extract_shape_transform 헬퍼는 utils.rs:109 에 그대로 살아있어 신규 단위 변환 코드 0줄. - src/renderer/layout.rs:2851 (TAC Picture / col_node) - src/renderer/layout/picture_footnote.rs:117,328 (layout_picture / layout_floating_picture) - src/renderer/layout/paragraph_layout.rs:1834,2108,2218 (TAC 인라인 3 사이트) - src/renderer/layout/table_cell_content.rs:644 (셀 내부 Picture; 명시적 ShapeTransform::default() → extract_shape_transform 교체) 검증: - cargo test --lib: 1134 passed (회귀 0) - cargo test --test svg_snapshot: 6/6 passed - cargo clippy --lib -- -D warnings: clean - exam_eng.hwp 8페이지 SVG diff: 페이지 4만 2 lines 변경 ( 래퍼 1쌍 추가), 다른 7개 페이지 byte-identical - export-svg p4 transform 래퍼 카운트: 0 → 1 (Q28 그림에 horz/vert flip 적용) 회귀 방지 후속 권고: 묶음 머지 a7e43f9 (Task #517/#518/#519/#520/#521/#523/#528) 의 다른 task 들도 stream/devel 누락 가능성 점검 필요. --- src/renderer/layout.rs | 1 + src/renderer/layout/paragraph_layout.rs | 5 ++++- src/renderer/layout/picture_footnote.rs | 4 +++- src/renderer/layout/table_cell_content.rs | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/renderer/layout.rs b/src/renderer/layout.rs index c6280703c..4d9d2119b 100644 --- a/src/renderer/layout.rs +++ b/src/renderer/layout.rs @@ -2856,6 +2856,7 @@ impl LayoutEngine { effect: pic.image_attr.effect, brightness: pic.image_attr.brightness, contrast: pic.image_attr.contrast, + transform: utils::extract_shape_transform(&pic.shape_attr), ..ImageNode::new(bin_data_id, image_data) }), BoundingBox::new(pic_x, pic_y, pic_w, pic_h), diff --git a/src/renderer/layout/paragraph_layout.rs b/src/renderer/layout/paragraph_layout.rs index 681e3a97c..3879afbb5 100644 --- a/src/renderer/layout/paragraph_layout.rs +++ b/src/renderer/layout/paragraph_layout.rs @@ -13,7 +13,7 @@ use super::super::{TextStyle, ShapeStyle, TabStop, hwpunit_to_px, px_to_hwpunit, use super::{LayoutEngine, CellContext}; use super::text_measurement::{resolved_to_text_style, estimate_text_width, compute_char_positions, extract_tab_leaders_with_extended, find_next_tab_stop}; use super::border_rendering::create_border_line_nodes; -use super::utils::{resolve_numbering_id, expand_numbering_format, numbering_format_to_number_format, find_bin_data}; +use super::utils::{resolve_numbering_id, expand_numbering_format, numbering_format_to_number_format, find_bin_data, extract_shape_transform}; /// lineseg baseline_distance를 폰트 어센트 기준으로 보정한다. /// CENTER 문단 수직정렬 등으로 baseline이 50% 이하로 설정된 경우, @@ -1830,6 +1830,7 @@ impl LayoutEngine { brightness: pic.image_attr.brightness, contrast: pic.image_attr.contrast, text_wrap: Some(pic.common.text_wrap), + transform: extract_shape_transform(&pic.shape_attr), ..ImageNode::new(bin_data_id, image_data) }), BoundingBox::new(x, img_y, tac_w, pic_h), @@ -2104,6 +2105,7 @@ impl LayoutEngine { brightness: pic.image_attr.brightness, contrast: pic.image_attr.contrast, text_wrap: Some(pic.common.text_wrap), + transform: extract_shape_transform(&pic.shape_attr), ..ImageNode::new(bin_data_id, image_data) }), BoundingBox::new(x, img_y, tac_w, pic_h), @@ -2214,6 +2216,7 @@ impl LayoutEngine { brightness: pic.image_attr.brightness, contrast: pic.image_attr.contrast, text_wrap: Some(pic.common.text_wrap), + transform: extract_shape_transform(&pic.shape_attr), ..ImageNode::new(bin_data_id, image_data) }), BoundingBox::new(img_x, img_y, tac_w, pic_h), diff --git a/src/renderer/layout/picture_footnote.rs b/src/renderer/layout/picture_footnote.rs index b5cf86f20..9a64cf4a0 100644 --- a/src/renderer/layout/picture_footnote.rs +++ b/src/renderer/layout/picture_footnote.rs @@ -14,7 +14,7 @@ use super::super::style_resolver::ResolvedStyleSet; use super::super::{hwpunit_to_px, StrokeDash, LineStyle, TextStyle, AutoNumberCounter, format_number, NumberFormat as NumFmt}; use super::LayoutEngine; use super::border_rendering::border_width_to_px; -use super::utils::find_bin_data; +use super::utils::{extract_shape_transform, find_bin_data}; use super::text_measurement::{resolved_to_text_style, estimate_text_width}; impl LayoutEngine { @@ -114,6 +114,7 @@ impl LayoutEngine { brightness: picture.image_attr.brightness, contrast: picture.image_attr.contrast, text_wrap: Some(picture.common.text_wrap), + transform: extract_shape_transform(&picture.shape_attr), ..ImageNode::new(bin_data_id, image_data) }), BoundingBox::new(pic_x, pic_y, pic_width, pic_height), @@ -324,6 +325,7 @@ impl LayoutEngine { brightness: picture.image_attr.brightness, contrast: picture.image_attr.contrast, text_wrap: Some(picture.common.text_wrap), + transform: extract_shape_transform(&picture.shape_attr), ..ImageNode::new(bin_data_id, image_data) }), BoundingBox::new(adjusted_pic_x, pic_y, pic_width, pic_height), diff --git a/src/renderer/layout/table_cell_content.rs b/src/renderer/layout/table_cell_content.rs index 4ab28704a..7e705f276 100644 --- a/src/renderer/layout/table_cell_content.rs +++ b/src/renderer/layout/table_cell_content.rs @@ -13,7 +13,7 @@ use super::super::{hwpunit_to_px, TextStyle, ShapeStyle}; use super::{LayoutEngine, CellContext, CellPathEntry}; use super::border_rendering::{build_row_col_x, collect_cell_borders, render_edge_borders, render_transparent_borders}; use super::text_measurement::{resolved_to_text_style, is_cjk_char, is_vertical_rotate_char, vertical_substitute_char}; -use super::utils::find_bin_data; +use super::utils::{extract_shape_transform, find_bin_data}; impl LayoutEngine { /// 세로쓰기 셀의 텍스트를 수직 방향으로 배치한다. @@ -641,7 +641,7 @@ impl LayoutEngine { control_index: Some(ctrl_idx), fill_mode: None, original_size: None, - transform: ShapeTransform::default(), + transform: extract_shape_transform(&pic.shape_attr), crop: None, original_size_hu: None, effect: pic.image_attr.effect,