Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(hwp): CharShape 남은 속성 파싱 #65

Merged
merged 1 commit into from
Nov 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
}