use crate::error::Result;
use crate::model::header_footer::HeaderFooterCollection;
use crate::model::page_layout::PageLayout;
use crate::parser::record::Record;
#[derive(Debug, Clone)]
pub struct PageDef {
pub width: u32,
pub height: u32,
pub left_margin: u32,
pub right_margin: u32,
pub top_margin: u32,
pub bottom_margin: u32,
pub header_margin: u32,
pub footer_margin: u32,
pub gutter_margin: u32,
pub properties: u32,
pub footnote_shape_id: u16,
pub page_border_fill_id: u16,
pub header_footer: HeaderFooterCollection,
pub layout: Option<PageLayout>,
}
impl PageDef {
pub fn from_record(record: &Record) -> Result<Self> {
let data = &record.data;
let mut width = 59528; let mut height = 84188; let mut left_margin = 8504; let mut right_margin = 8504; let mut top_margin = 5669; let mut bottom_margin = 4252; let footer_margin = 4252; let gutter_margin = 0;
let properties = 0;
if data.len() >= 8 {
let mut reader = record.data_reader();
if let Ok(w) = reader.read_u32() {
if w > 0 && w < 0x100000 {
width = w;
}
}
if let Ok(h) = reader.read_u32() {
if h > 0 && h < 0x100000 {
height = h;
}
}
if reader.remaining() >= 24 {
let m1 = reader.read_u32().unwrap_or(left_margin);
let m2 = reader.read_u32().unwrap_or(right_margin);
let m3 = reader.read_u32().unwrap_or(top_margin);
let m4 = reader.read_u32().unwrap_or(bottom_margin);
if m1 < width / 2 {
left_margin = m1;
}
if m2 < width / 2 {
right_margin = m2;
}
if m3 < height / 2 {
top_margin = m3;
}
if m4 < height / 2 {
bottom_margin = m4;
}
}
}
Ok(Self {
width,
height,
left_margin,
right_margin,
top_margin,
bottom_margin,
header_margin: footer_margin,
footer_margin,
gutter_margin,
properties,
footnote_shape_id: 0,
page_border_fill_id: 0,
header_footer: HeaderFooterCollection::new(),
layout: None,
})
}
pub fn is_landscape(&self) -> bool {
self.width > self.height
}
pub fn effective_width(&self) -> u32 {
self.width - self.left_margin - self.right_margin - self.gutter_margin
}
pub fn effective_height(&self) -> u32 {
self.height - self.top_margin - self.bottom_margin
}
pub fn new_default() -> Self {
Self {
width: 59528, height: 84188, left_margin: 8504, right_margin: 8504, top_margin: 5669, bottom_margin: 4252, header_margin: 4252, footer_margin: 4252, gutter_margin: 0,
properties: 0,
footnote_shape_id: 0,
page_border_fill_id: 0,
header_footer: HeaderFooterCollection::new(),
layout: None,
}
}
pub fn from_layout(layout: PageLayout) -> Self {
Self {
width: layout.width,
height: layout.height,
left_margin: layout.margins.left,
right_margin: layout.margins.right,
top_margin: layout.margins.top,
bottom_margin: layout.margins.bottom,
header_margin: layout.margins.header,
footer_margin: layout.margins.footer,
gutter_margin: layout.margins.gutter,
properties: 0, footnote_shape_id: 0,
page_border_fill_id: 0,
header_footer: HeaderFooterCollection::new(),
layout: Some(layout),
}
}
pub fn update_from_layout(&mut self, layout: PageLayout) {
self.width = layout.width;
self.height = layout.height;
self.left_margin = layout.margins.left;
self.right_margin = layout.margins.right;
self.top_margin = layout.margins.top;
self.bottom_margin = layout.margins.bottom;
self.header_margin = layout.margins.header;
self.footer_margin = layout.margins.footer;
self.gutter_margin = layout.margins.gutter;
self.layout = Some(layout);
}
pub fn get_layout(&self) -> PageLayout {
if let Some(layout) = &self.layout {
layout.clone()
} else {
PageLayout {
width: self.width,
height: self.height,
margins: crate::model::page_layout::PageMargins {
left: self.left_margin,
right: self.right_margin,
top: self.top_margin,
bottom: self.bottom_margin,
header: self.header_margin,
footer: self.footer_margin,
gutter: self.gutter_margin,
mirror_margins: false,
},
..Default::default()
}
}
}
pub fn to_bytes(&self) -> Vec<u8> {
use byteorder::{LittleEndian, WriteBytesExt};
use std::io::Cursor;
let mut data = Vec::new();
let mut writer = Cursor::new(&mut data);
writer.write_u32::<LittleEndian>(self.width).unwrap();
writer.write_u32::<LittleEndian>(self.height).unwrap();
writer.write_u32::<LittleEndian>(self.left_margin).unwrap();
writer.write_u32::<LittleEndian>(self.right_margin).unwrap();
writer.write_u32::<LittleEndian>(self.top_margin).unwrap();
writer
.write_u32::<LittleEndian>(self.bottom_margin)
.unwrap();
writer
.write_u32::<LittleEndian>(self.header_margin)
.unwrap();
writer
.write_u32::<LittleEndian>(self.footer_margin)
.unwrap();
writer
.write_u32::<LittleEndian>(self.gutter_margin)
.unwrap();
writer.write_u32::<LittleEndian>(self.properties).unwrap();
writer
.write_u16::<LittleEndian>(self.footnote_shape_id)
.unwrap();
writer
.write_u16::<LittleEndian>(self.page_border_fill_id)
.unwrap();
data
}
}