Skip to content

Commit

Permalink
feat(hwp): 글상자 파싱 (#80)
Browse files Browse the repository at this point in the history
  • Loading branch information
hahnlee authored Nov 9, 2022
1 parent fb9e354 commit 18f9e88
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 2 deletions.
58 changes: 58 additions & 0 deletions crates/hwp/src/hwp/paragraph/control/draw_text.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use std::io::Read;

use byteorder::{LittleEndian, ReadBytesExt};

use crate::hwp::{
paragraph::control::paragraph_list::ParagraphList,
record::{tags::BodyTextRecord, RecordCursor},
version::Version,
};

/// 글상자
#[derive(Debug, Clone)]
pub struct DrawText {
/// 문단 리스트
pub paragraph_list: ParagraphList,
/// 글상자 텍스트 왼쪽 여백
pub margin_left: i16,
// 글상자 텍스트 오른쪽 여백
pub margin_right: i16,
/// 글상자 텍스트 위쪽 여백
pub margin_top: i16,
/// 글상자 텍스트 아래쪽 여백
pub margin_bottom: i16,
/// 텍스트 문자열의 최대 폭
pub last_width: u32,
/// 스펙에 정의되지 않은 바이트
pub unknown: Vec<u8>,
}

impl DrawText {
pub fn from_record_cursor(cursor: &mut RecordCursor, version: &Version) -> Self {
let record = cursor.current();
assert_eq!(record.tag_id, BodyTextRecord::HWPTAG_LIST_HEADER as u32);

let mut reader = record.get_data_reader();
let paragraph_list = ParagraphList::from_reader(&mut reader, cursor, version);

let margin_left = reader.read_i16::<LittleEndian>().unwrap();
let margin_right = reader.read_i16::<LittleEndian>().unwrap();
let margin_top = reader.read_i16::<LittleEndian>().unwrap();
let margin_bottom = reader.read_i16::<LittleEndian>().unwrap();

let last_width = reader.read_u32::<LittleEndian>().unwrap();

let mut unknown = vec![];
reader.read_to_end(&mut unknown).unwrap();

Self {
paragraph_list,
margin_left,
margin_right,
margin_top,
margin_bottom,
last_width,
unknown,
}
}
}
1 change: 1 addition & 0 deletions crates/hwp/src/hwp/paragraph/control/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod book_mark;
pub mod column;
pub mod common_properties;
pub mod container;
pub mod draw_text;
pub mod element_properties;
pub mod equation;
pub mod footnote_endnote;
Expand Down
67 changes: 65 additions & 2 deletions crates/hwp/src/hwp/paragraph/control/shape_object.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::hwp::{
paragraph::control::element_properties::ElementProperties,
record::{Record, RecordCursor},
paragraph::control::{draw_text::DrawText, element_properties::ElementProperties},
record::{tags::BodyTextRecord, Record, RecordCursor},
version::Version,
};

Expand All @@ -13,20 +13,29 @@ pub struct GenShapeObjectControl {
pub common_properties: CommonProperties,
/// 개체 요소 속성
pub element_properties: ElementProperties,
/// 글상자
pub draw_text: Option<DrawText>,
}

impl GenShapeObjectControl {
pub fn from_record(record: &mut Record, cursor: &mut RecordCursor, version: &Version) -> Self {
let common_properties = CommonProperties::from_record(record, cursor, version);
let element_properties = ElementProperties::from_record_cursor(cursor, true);

let draw_text = if cursor.record_id(BodyTextRecord::HWPTAG_LIST_HEADER as u32) {
Some(DrawText::from_record_cursor(cursor, version))
} else {
None
};

// TODO: (@hahnlee) children 파싱하기
let children = cursor.collect_children(record.level);
assert_ne!(children.len(), 0);

Self {
common_properties,
element_properties,
draw_text,
}
}
}
Expand All @@ -38,17 +47,26 @@ pub struct ShapeLineControl {
pub common_properties: CommonProperties,
/// 개체 요소 속성
pub element_properties: ElementProperties,
/// 글상자
pub draw_text: Option<DrawText>,
}

impl ShapeLineControl {
pub fn from_record(record: &mut Record, cursor: &mut RecordCursor, version: &Version) -> Self {
let common_properties = CommonProperties::from_record(record, cursor, version);
let element_properties = ElementProperties::from_record_cursor(cursor, false);

let draw_text = if cursor.record_id(BodyTextRecord::HWPTAG_LIST_HEADER as u32) {
Some(DrawText::from_record_cursor(cursor, version))
} else {
None
};

// TODO: (@hahnlee) 남은 데이터 파싱하기
Self {
common_properties,
element_properties,
draw_text,
}
}
}
Expand All @@ -60,17 +78,26 @@ pub struct ShapeRectangleControl {
pub common_properties: CommonProperties,
/// 개체 요소 속성
pub element_properties: ElementProperties,
/// 글상자
pub draw_text: Option<DrawText>,
}

impl ShapeRectangleControl {
pub fn from_record(record: &mut Record, cursor: &mut RecordCursor, version: &Version) -> Self {
let common_properties = CommonProperties::from_record(record, cursor, version);
let element_properties = ElementProperties::from_record_cursor(cursor, false);

let draw_text = if cursor.record_id(BodyTextRecord::HWPTAG_LIST_HEADER as u32) {
Some(DrawText::from_record_cursor(cursor, version))
} else {
None
};

// TODO: (@hahnlee) 남은 데이터 파싱하기
Self {
common_properties,
element_properties,
draw_text,
}
}
}
Expand All @@ -82,17 +109,26 @@ pub struct ShapeEllipseControl {
pub common_properties: CommonProperties,
/// 개체 요소 속성
pub element_properties: ElementProperties,
/// 글상자
pub draw_text: Option<DrawText>,
}

impl ShapeEllipseControl {
pub fn from_record(record: &mut Record, cursor: &mut RecordCursor, version: &Version) -> Self {
let common_properties = CommonProperties::from_record(record, cursor, version);
let element_properties = ElementProperties::from_record_cursor(cursor, false);

let draw_text = if cursor.record_id(BodyTextRecord::HWPTAG_LIST_HEADER as u32) {
Some(DrawText::from_record_cursor(cursor, version))
} else {
None
};

// TODO: (@hahnlee) 남은 데이터 파싱하기
Self {
common_properties,
element_properties,
draw_text,
}
}
}
Expand All @@ -104,17 +140,26 @@ pub struct ShapeArcControl {
pub common_properties: CommonProperties,
/// 개체 요소 속성
pub element_properties: ElementProperties,
/// 글상자
pub draw_text: Option<DrawText>,
}

impl ShapeArcControl {
pub fn from_record(record: &mut Record, cursor: &mut RecordCursor, version: &Version) -> Self {
let common_properties = CommonProperties::from_record(record, cursor, version);
let element_properties = ElementProperties::from_record_cursor(cursor, false);

let draw_text = if cursor.record_id(BodyTextRecord::HWPTAG_LIST_HEADER as u32) {
Some(DrawText::from_record_cursor(cursor, version))
} else {
None
};

// TODO: (@hahnlee) 남은 데이터 파싱하기
Self {
common_properties,
element_properties,
draw_text,
}
}
}
Expand All @@ -126,17 +171,26 @@ pub struct ShapePolygonControl {
pub common_properties: CommonProperties,
/// 개체 요소 속성
pub element_properties: ElementProperties,
/// 글상자
pub draw_text: Option<DrawText>,
}

impl ShapePolygonControl {
pub fn from_record(record: &mut Record, cursor: &mut RecordCursor, version: &Version) -> Self {
let common_properties = CommonProperties::from_record(record, cursor, version);
let element_properties = ElementProperties::from_record_cursor(cursor, false);

let draw_text = if cursor.record_id(BodyTextRecord::HWPTAG_LIST_HEADER as u32) {
Some(DrawText::from_record_cursor(cursor, version))
} else {
None
};

// TODO: (@hahnlee) 남은 데이터 파싱하기
Self {
common_properties,
element_properties,
draw_text,
}
}
}
Expand All @@ -148,17 +202,26 @@ pub struct ShapeCurveControl {
pub common_properties: CommonProperties,
/// 개체 요소 속성
pub element_properties: ElementProperties,
/// 글상자
pub draw_text: Option<DrawText>,
}

impl ShapeCurveControl {
pub fn from_record(record: &mut Record, cursor: &mut RecordCursor, version: &Version) -> Self {
let common_properties = CommonProperties::from_record(record, cursor, version);
let element_properties = ElementProperties::from_record_cursor(cursor, false);

let draw_text = if cursor.record_id(BodyTextRecord::HWPTAG_LIST_HEADER as u32) {
Some(DrawText::from_record_cursor(cursor, version))
} else {
None
};

// TODO: (@hahnlee) 남은 데이터 파싱하기
Self {
common_properties,
element_properties,
draw_text,
}
}
}
Binary file not shown.
17 changes: 17 additions & 0 deletions crates/hwp/tests/integration/project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,20 @@ fn check_shadow() {

assert_eq!(hwp.body_texts.sections.len(), 1);
}

#[test]
fn check_draw_text() {
let path = get_tests_path("integration/project/files/draw_text.hwp");
let file = fs::read(path).unwrap();

let hwp = HWP::from_bytes(&file);

assert_eq!(hwp.header.version.to_string(), "5.1.0.1");
assert_eq!(hwp.header.flags.compressed, true);
assert_eq!(hwp.header.flags.distributed, false);

assert_eq!(hwp.header.license.ccl, false);
assert_eq!(hwp.header.license.replication_restrictions, false);

assert_eq!(hwp.body_texts.sections.len(), 1);
}

0 comments on commit 18f9e88

Please sign in to comment.