Skip to content

Commit

Permalink
feat(hwp): CharShape 남은 속성 파싱 (#65)
Browse files Browse the repository at this point in the history
  • Loading branch information
hahnlee authored Nov 3, 2022
1 parent de30e48 commit 42f5256
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 20 deletions.
42 changes: 33 additions & 9 deletions crates/hwp/src/hwp/doc_info/bin_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use num_derive::FromPrimitive;
use crate::hwp::{
header::Header,
record::{reader::RecordReader, tags::DocInfoRecord, FromRecord, Record},
utils::bits::get_value_range, version::Version,
utils::bits::get_value_range,
version::Version,
};

#[derive(Debug)]
Expand Down Expand Up @@ -33,8 +34,8 @@ impl BinData {

pub fn compressed(&self, header: &Header) -> bool {
match self.properties.compress_mode {
0x0000 => header.flags.compressed,
0x0010 => true,
CompressMode::Default => header.flags.compressed,
CompressMode::Compress => true,
_ => false,
}
}
Expand Down Expand Up @@ -88,7 +89,7 @@ impl FromRecord for BinData {
}
}

#[repr(u16)]
#[repr(u8)]
#[derive(Debug, PartialEq, Eq, FromPrimitive)]
pub enum BinDataKind {
/// 그림 외부 파일 참조
Expand All @@ -99,23 +100,46 @@ pub enum BinDataKind {
Storage,
}

#[repr(u8)]
#[derive(Debug, PartialEq, Eq, FromPrimitive)]
pub enum CompressMode {
/// 스토리지의 디폴트 모드 따라감
Default,
/// 무조건 압축
Compress,
/// 무조건 압축하지 않음
None,
}

#[repr(u8)]
#[derive(Debug, PartialEq, Eq, FromPrimitive)]
pub enum BinDataStatus {
/// 아직 access 된 적이 없는 상태
Initial,
/// access에 성공하여 파일을 찾은 상태
Success,
/// access가 실패한 에러 상태
Failed,
/// 링크 access가 실패했으나 무시된 상태
Ignored,
}

#[derive(Debug)]
pub struct BinDataProperties {
/// 타입
pub kind: BinDataKind,
/// 압축 모드
pub compress_mode: u16,
pub compress_mode: CompressMode,
/// 상태
pub status: u16,
pub status: BinDataStatus,
}

impl BinDataProperties {
pub fn from_bits(bits: u16) -> Self {
// TODO: (@hahnlee) 남는 비트정보 보존
Self {
kind: BinDataKind::from_u16(get_value_range(bits, 0, 3)).unwrap(),
compress_mode: get_value_range(bits, 4, 5),
status: get_value_range(bits, 8, 9),
compress_mode: CompressMode::from_u16(get_value_range(bits, 4, 5)).unwrap(),
status: BinDataStatus::from_u16(get_value_range(bits, 8, 9)).unwrap(),
}
}
}
43 changes: 41 additions & 2 deletions crates/hwp/src/hwp/doc_info/border_fill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,56 @@ pub enum BackSlashDiagonalShape {
RightTopToBottomLeftEdge = 0b111,
}

#[repr(u8)]
#[derive(Debug, Clone, FromPrimitive)]
pub enum BorderKind {
/// 실선
Solid,
/// 긴 점선
Dash,
/// 점선
Dot,
/// -.-.-.-.
DashDot,
/// -..-..-..
DashDotDot,
/// Dash보다 긴 선분의 반복
LongDash,
/// Dot보다 큰 동그라미의 반복
Circle,
/// 2중선
DoubleSlim,
/// 가는선 + 굵은선 2중선
SlimThick,
/// 굵은선 + 가는선 2중선
TickSlim,
/// 가는선 + 굵은선 + 가는선 3중선
SlimTickSlim,
/// 물결
Wave,
/// 물결 2중선
DoubleWave,
/// 두꺼운 3D
Tick3D,
/// 두꺼운 3D(광원 반대)
Tick3DInset,
/// 3D 단선
Slim3D,
/// 3D 단선(광원 반대)
Slim3DInset,
}

#[derive(Debug, Clone)]
pub struct Border {
pub width: u8,
pub kind: u8,
pub kind: BorderKind,
pub color: ColorRef,
}

impl Border {
pub fn from_reader<T: Read>(reader: &mut T) -> Self {
Self {
kind: reader.read_u8().unwrap(),
kind: BorderKind::from_u8(reader.read_u8().unwrap()).unwrap(),
width: reader.read_u8().unwrap(),
color: ColorRef::from_u32(reader.read_u32::<LittleEndian>().unwrap()),
}
Expand Down
134 changes: 125 additions & 9 deletions crates/hwp/src/hwp/doc_info/char_shape.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
use byteorder::{LittleEndian, ReadBytesExt};
use num::FromPrimitive;
use num_derive::FromPrimitive;

use crate::hwp::{
color_ref::ColorRef,
record::{tags::DocInfoRecord, FromRecord, Record},
utils::bits::get_flag,
utils::bits::{get_flag, get_value_range},
version::Version,
};

use super::border_fill::BorderKind;

#[derive(Debug)]
pub struct CharShape {
/// 언어별 글꼴 ID(FaceID) 참조 값
Expand All @@ -25,6 +29,36 @@ pub struct CharShape {
pub italic: bool,
/// 진하게 여부
pub bold: bool,
/// 밑줄 종류
pub underline_kind: UnderlineKind,
/// 밑줄 모양
pub underline_shape: BorderKind,
/// 외곽선 종류
pub outline_kind: OutlineKind,
/// 그림자 종류
pub shadow_kind: ShadowKind,
/// 양각여부
pub emboss: bool,
/// 음각여부
pub engrave: bool,
/// 위 첨자 여부
pub supscript: bool,
/// 아래 첨자 여부
pub subscript: bool,
/// 취소선 여부
pub strike: bool,
/// 강조점 종류
pub sym_mark: SymMark,
/// 글꼴에 어울리는 빈칸 사용 여부
pub use_font_space: bool,
/// 취소선 모양
pub strike_shape: BorderKind,
/// Kerning 여부
pub use_kerning: bool,
/// 그림자 간격 X, -100%~100%
pub shadow_offset_x: u8,
/// 그림자 간격 Y, -100%~100%
pub shadow_offset_y: u8,
/// 글자 색
pub color: ColorRef,
/// 밑줄 색
Expand All @@ -36,7 +70,7 @@ pub struct CharShape {
/// 글자 테두리/배경 ID 참조 값 (5.0.2.1 이상)
pub border_fill_id: Option<u16>,
/// 취소선 색 (5.0.3.0 이상)
pub strikethrough_color: Option<ColorRef>,
pub strike_color: Option<ColorRef>,
}

impl FromRecord for CharShape {
Expand Down Expand Up @@ -104,12 +138,22 @@ impl FromRecord for CharShape {
let attribute = reader.read_u32::<LittleEndian>().unwrap();
let italic = get_flag(attribute, 0);
let bold = get_flag(attribute, 1);
// TODO: (@hahnlee) 나머지 파싱
let underline_kind = UnderlineKind::from_u32(get_value_range(attribute, 2, 3)).unwrap();
let underline_shape = BorderKind::from_u32(get_value_range(attribute, 4, 7)).unwrap();
let outline_kind = OutlineKind::from_u32(get_value_range(attribute, 8, 10)).unwrap();
let shadow_kind = ShadowKind::from_u32(get_value_range(attribute, 11, 12)).unwrap();
let emboss = get_flag(attribute, 13);
let engrave = get_flag(attribute, 14);
let supscript = get_flag(attribute, 15);
let subscript = get_flag(attribute, 16);
let strike = get_value_range(attribute, 18, 20) > 0;
let sym_mark = SymMark::from_u32(get_value_range(attribute, 21, 24)).unwrap();
let use_font_space = get_flag(attribute, 25);
let strike_shape = BorderKind::from_u32(get_value_range(attribute, 26, 29)).unwrap();
let use_kerning = get_flag(attribute, 30);

// TODO: (@hahnlee) 그림자 간격, -100%~100%
reader.read_u8().unwrap();
// TODO: (@hahnlee) 그림자 간격, -100%~100%
reader.read_u8().unwrap();
let shadow_offset_x = reader.read_u8().unwrap();
let shadow_offset_y = reader.read_u8().unwrap();

let color = ColorRef::from_u32(reader.read_u32::<LittleEndian>().unwrap());
let underline_color = ColorRef::from_u32(reader.read_u32::<LittleEndian>().unwrap());
Expand All @@ -122,7 +166,7 @@ impl FromRecord for CharShape {
None
};

let strikethrough_color = if *version >= Version::from_str("5.0.3.0") {
let strike_color = if *version >= Version::from_str("5.0.3.0") {
Some(ColorRef::from_u32(
reader.read_u32::<LittleEndian>().unwrap(),
))
Expand All @@ -139,12 +183,84 @@ impl FromRecord for CharShape {
base_size,
italic,
bold,
underline_kind,
underline_shape,
outline_kind,
shadow_kind,
emboss,
engrave,
supscript,
subscript,
strike,
sym_mark,
use_font_space,
strike_shape,
use_kerning,
shadow_offset_x,
shadow_offset_y,
color,
underline_color,
shade_color,
shadow_color,
border_fill_id,
strikethrough_color,
strike_color,
}
}
}

#[repr(u8)]
#[derive(Debug, FromPrimitive)]
pub enum UnderlineKind {
None,
Bottom,
Top,
}

#[repr(u8)]
#[derive(Debug, FromPrimitive)]
pub enum OutlineKind {
/// 없음
None,
/// 실선
Solid,
/// 점선
Dot,
/// 굵은 실선(두꺼운 선)
Tick,
/// 파선(긴 점선)
Dash,
/// 일점쇄선 (-.-.-.-.)
DashDot,
/// 이점쇄선 (-..-..-..)
DashDotDot,
}

#[repr(u8)]
#[derive(Debug, FromPrimitive)]
pub enum ShadowKind {
/// 없음
None,
/// 비연속
Drop,
/// 연속
Continuous,
}

#[repr(u8)]
#[derive(Debug, FromPrimitive)]
pub enum SymMark {
/// 없음
None,
/// 검정 동그라미 강조점
DotAbove,
/// 속 빈 동그라미 강조점̊̊̊̊̊̊̊̊̊
RingAbove,
/// ˇ
Caron,
/// ̃
Tilde,
/// ・
DotMiddle,
/// :
Colon,
}

0 comments on commit 42f5256

Please sign in to comment.