제안내용
현재 rhwp에는 PageRenderTree를 생성하는 내부 구조가 이미 구현되어 있습니다.
또한 WASM 환경에서는 getPageRenderTree(pageNum) 형태로 page render tree를 확인할 수 있는 경로도 존재합니다.
다만 WASM이 아닌 native 환경에서 rhwp core를 사용할 때, DocumentCore 수준에서 PageRenderTree를 안정적으로 가져오는 public API가 공식적으로 정리되어 있지 않습니다.
따라서 이미 존재하는 내부 구현을 native bridge에서 사용할 수 있도록 다음 API를 노출하는 것을 제안합니다.
pub fn build_page_render_tree(
&self,
page_num: u32,
) -> Result<PageRenderTree, HwpError>
이미지 렌더링을 위해서는 render tree의 ImageNode.bin_data_id가 참조하는 실제 이미지 바이너리 데이터도 조회할 수 있어야 하므로, 다음 API도 함께 필요합니다.
pub fn get_bin_data(
&self,
index: usize,
) -> Option<&[u8]>
이 제안은 새로운 render tree 구조를 추가하거나 renderer를 새로 구현하자는 것이 아닙니다.
이미 존재하는 PageRenderTree 생성 경로를 native bridge에서 사용할 수 있도록 public API 경계를 정리하자는 제안입니다.
배경
현재 rhwp의 렌더링 흐름에는 이미 page 단위 render tree가 사용되고 있습니다.
그러나 native viewer를 구현하려면 WASM API가 아니라 Rust core에서 직접 다음 정보를 가져올 수 있어야 합니다.
- 특정 페이지의
PageRenderTree
- render tree 안의 이미지 노드가 참조하는 실제 이미지 바이너리 데이터
현재 alhangeul-macos 프로젝트에서도 이 문제가 드러났습니다.
해당 프로젝트는 rhwp core를 사용해 macOS native viewer를 구현하고 있습니다. 하지만 native render tree bridge에 필요한 API가 현재 공식 release에 포함되어 있지 않아, 데모 빌드에서는 해당 API가 포함된 특정 commit을 기준으로 core를 사용하고 있습니다.
즉 문제는 PageRenderTree 기능이 없다는 것이 아니라, 이미 구현된 기능을 native bridge에서 안정적으로 사용할 수 있는 public API가 아직 release contract로 노출되어 있지 않다는 점입니다.
필요한 이유
1. native renderer가 기존 PageRenderTree를 직접 사용할 수 있음
native renderer는 rhwp core가 이미 계산한 layout 결과를 다시 계산할 필요가 없습니다.
PageRenderTree를 직접 가져올 수 있으면 다음과 같은 흐름이 가능합니다.
DocumentCore
-> build_page_render_tree(page_num)
-> PageRenderTree
-> native bridge
-> platform renderer
예를 들어 macOS에서는 PageRenderTree를 Swift model로 decode한 뒤 CoreGraphics/CoreText로 그릴 수 있습니다.
2. SVG 변환 없이 native graphics API로 렌더링할 수 있음
현재 native 환경에서 SVG 문자열을 받아 다시 rasterize하는 방식도 가능하지만, native viewer에서는 render tree를 직접 해석해 플랫폼 그래픽 API로 그리는 방식이 더 자연스럽습니다.
PageRenderTree bridge API가 있으면 native renderer는 다음 정보를 직접 사용할 수 있습니다.
- page size
- text run
- table / table cell
- shape node
- path command
- image node
- equation node
- transform / clipping 정보
3. 이미지 렌더링을 위해 image data 조회 API가 필요함
PageRenderTree의 이미지 노드는 bin_data_id를 참조합니다.
따라서 native renderer가 실제 이미지를 그리려면 bin_data_id에 대응하는 원본 이미지 bytes를 조회할 수 있어야 합니다.
이 때문에 build_page_render_tree와 함께 get_bin_data API도 필요합니다.
ImageNode.bin_data_id
-> get_bin_data(index)
-> image bytes
-> native image decode
-> draw image
4. 기존 구현을 작은 범위로 공식화할 수 있음
이 작업은 새로운 렌더링 구조를 설계하는 대규모 작업이 아니라, 기존 내부 구현을 외부 bridge 계층에서 사용할 수 있도록 정리하는 작은 범위의 작업으로 볼 수 있습니다.
예상 구현은 다음처럼 기존 내부 함수를 감싸는 형태가 될 수 있습니다.
pub fn build_page_render_tree(
&self,
page_num: u32,
) -> Result<PageRenderTree, HwpError> {
let tree = self.build_page_tree(page_num)?;
let _overflows = self.layout_engine.take_overflows();
Ok(tree)
}
이미지 데이터 조회 역시 기존 문서 내부 데이터를 반환하는 형태가 될 수 있습니다.
pub fn get_bin_data(
&self,
index: usize,
) -> Option<&[u8]> {
self.document
.bin_data_content
.get(index)
.map(|b| b.data.as_slice())
}
참고
관련 구현 사례로 다음 commit을 참고할 수 있습니다.
Add native render tree bridge APIs
alhangeul-macos 데모 빌드에서 필요했던 native render tree bridge API를 검증하기 위해, upstream rhwp의 기존 PageRenderTree 구현 위에 DocumentCore::build_page_render_tree와 DocumentCore::get_bin_data를 추가한 구현 사례입니다.
해당 commit에서는 다음 작업이 포함되어 있습니다.
DocumentCore::build_page_render_tree(page_num) 추가
DocumentCore::get_bin_data(index) 추가
- render tree 관련 타입에
serde::Serialize derive 추가
- 이미지 데이터는 JSON에 직접 넣지 않고
bin_data_id와 별도 data lookup으로 처리
이미 별도 commit에서 구현을 검증한 적이 있으므로, 이번 이슈의 초점은 새로운 구조 설계가 아니라 해당 방향을 upstream release line에 맞게 정리해 공식 API로 노출하는 것입니다.
이 commit의 방향을 upstream release line에 맞게 정리하면, native renderer에서 기존 PageRenderTree를 더 안정적으로 사용할 수 있을 것 같습니다.
제안범위
이번 이슈에서는 다음 범위만 다루면 충분할 것 같습니다.
DocumentCore::build_page_render_tree(page_num) public API 추가
DocumentCore::get_bin_data(index) public API 추가
- native bridge에서
PageRenderTree를 JSON으로 직렬화할 수 있도록 필요한 최소 Serialize 정리
ImageNode.bin_data_id와 get_bin_data(index)의 index 기준 문서화
- 기존 SVG / HTML / Canvas / WASM 렌더링 경로에 영향이 없는지 확인
완료 조건
- native bridge에서
DocumentCore::build_page_render_tree(page_num)를 호출할 수 있음
- native bridge에서
DocumentCore::get_bin_data(index)를 호출할 수 있음
PageRenderTree를 native bridge에서 직렬화해 사용할 수 있음
- 이미지 노드의
bin_data_id와 실제 이미지 데이터 조회 방식이 문서화됨
- 기존 렌더링 경로의 동작이 변경되지 않음
제안내용
현재 rhwp에는
PageRenderTree를 생성하는 내부 구조가 이미 구현되어 있습니다.또한 WASM 환경에서는
getPageRenderTree(pageNum)형태로 page render tree를 확인할 수 있는 경로도 존재합니다.다만 WASM이 아닌 native 환경에서 rhwp core를 사용할 때,
DocumentCore수준에서PageRenderTree를 안정적으로 가져오는 public API가 공식적으로 정리되어 있지 않습니다.따라서 이미 존재하는 내부 구현을 native bridge에서 사용할 수 있도록 다음 API를 노출하는 것을 제안합니다.
이미지 렌더링을 위해서는 render tree의
ImageNode.bin_data_id가 참조하는 실제 이미지 바이너리 데이터도 조회할 수 있어야 하므로, 다음 API도 함께 필요합니다.이 제안은 새로운 render tree 구조를 추가하거나 renderer를 새로 구현하자는 것이 아닙니다.
이미 존재하는
PageRenderTree생성 경로를 native bridge에서 사용할 수 있도록 public API 경계를 정리하자는 제안입니다.배경
현재 rhwp의 렌더링 흐름에는 이미 page 단위 render tree가 사용되고 있습니다.
그러나 native viewer를 구현하려면 WASM API가 아니라 Rust core에서 직접 다음 정보를 가져올 수 있어야 합니다.
PageRenderTree현재
alhangeul-macos프로젝트에서도 이 문제가 드러났습니다.해당 프로젝트는 rhwp core를 사용해 macOS native viewer를 구현하고 있습니다. 하지만 native render tree bridge에 필요한 API가 현재 공식 release에 포함되어 있지 않아, 데모 빌드에서는 해당 API가 포함된 특정 commit을 기준으로 core를 사용하고 있습니다.
즉 문제는
PageRenderTree기능이 없다는 것이 아니라, 이미 구현된 기능을 native bridge에서 안정적으로 사용할 수 있는 public API가 아직 release contract로 노출되어 있지 않다는 점입니다.필요한 이유
1. native renderer가 기존 PageRenderTree를 직접 사용할 수 있음
native renderer는 rhwp core가 이미 계산한 layout 결과를 다시 계산할 필요가 없습니다.
PageRenderTree를 직접 가져올 수 있으면 다음과 같은 흐름이 가능합니다.예를 들어 macOS에서는
PageRenderTree를 Swift model로 decode한 뒤 CoreGraphics/CoreText로 그릴 수 있습니다.2. SVG 변환 없이 native graphics API로 렌더링할 수 있음
현재 native 환경에서 SVG 문자열을 받아 다시 rasterize하는 방식도 가능하지만, native viewer에서는 render tree를 직접 해석해 플랫폼 그래픽 API로 그리는 방식이 더 자연스럽습니다.
PageRenderTreebridge API가 있으면 native renderer는 다음 정보를 직접 사용할 수 있습니다.3. 이미지 렌더링을 위해 image data 조회 API가 필요함
PageRenderTree의 이미지 노드는bin_data_id를 참조합니다.따라서 native renderer가 실제 이미지를 그리려면
bin_data_id에 대응하는 원본 이미지 bytes를 조회할 수 있어야 합니다.이 때문에
build_page_render_tree와 함께get_bin_dataAPI도 필요합니다.4. 기존 구현을 작은 범위로 공식화할 수 있음
이 작업은 새로운 렌더링 구조를 설계하는 대규모 작업이 아니라, 기존 내부 구현을 외부 bridge 계층에서 사용할 수 있도록 정리하는 작은 범위의 작업으로 볼 수 있습니다.
예상 구현은 다음처럼 기존 내부 함수를 감싸는 형태가 될 수 있습니다.
이미지 데이터 조회 역시 기존 문서 내부 데이터를 반환하는 형태가 될 수 있습니다.
참고
관련 구현 사례로 다음 commit을 참고할 수 있습니다.
Add native render tree bridge APIs
해당 commit에서는 다음 작업이 포함되어 있습니다.
DocumentCore::build_page_render_tree(page_num)추가DocumentCore::get_bin_data(index)추가serde::Serializederive 추가bin_data_id와 별도 data lookup으로 처리이미 별도 commit에서 구현을 검증한 적이 있으므로, 이번 이슈의 초점은 새로운 구조 설계가 아니라 해당 방향을 upstream release line에 맞게 정리해 공식 API로 노출하는 것입니다.
이 commit의 방향을 upstream release line에 맞게 정리하면, native renderer에서 기존
PageRenderTree를 더 안정적으로 사용할 수 있을 것 같습니다.제안범위
이번 이슈에서는 다음 범위만 다루면 충분할 것 같습니다.
DocumentCore::build_page_render_tree(page_num)public API 추가DocumentCore::get_bin_data(index)public API 추가PageRenderTree를 JSON으로 직렬화할 수 있도록 필요한 최소Serialize정리ImageNode.bin_data_id와get_bin_data(index)의 index 기준 문서화완료 조건
DocumentCore::build_page_render_tree(page_num)를 호출할 수 있음DocumentCore::get_bin_data(index)를 호출할 수 있음PageRenderTree를 native bridge에서 직렬화해 사용할 수 있음bin_data_id와 실제 이미지 데이터 조회 방식이 문서화됨