use super::prelude::*;
#[derive(Debug, Clone, DataSize)]
pub struct PageRc(pub(crate) RcRef<PagesNode>);
impl Deref for PageRc {
type Target = Page;
fn deref(&self) -> &Page {
match *self.0 {
PagesNode::Leaf(ref page) => page,
_ => unreachable!(),
}
}
}
impl PageRc {
pub fn create(page: Page, update: &mut impl Updater) -> Result<PageRc> {
Ok(PageRc(update.create(PagesNode::Leaf(page))?))
}
pub fn update(page: Page, old_page: &PageRc, update: &mut impl Updater) -> Result<PageRc> {
update
.update(old_page.get_ref(), PagesNode::Leaf(page))
.map(PageRc)
}
pub fn get_ref(&self) -> PlainRef {
self.0.inner
}
}
impl Object for PageRc {
fn from_primitive(p: Primitive, resolve: &impl Resolve) -> Result<PageRc> {
let node = t!(RcRef::from_primitive(p, resolve));
match *node {
PagesNode::Tree(_) => Err(PdfError::WrongDictionaryType {
expected: "Page".into(),
found: "Pages".into(),
}),
PagesNode::Leaf(_) => Ok(PageRc(node)),
}
}
}
impl ObjectWrite for PageRc {
fn to_primitive(&self, update: &mut impl Updater) -> Result<Primitive> {
self.0.to_primitive(update)
}
}
#[derive(Debug, Clone, DeepClone, DataSize)]
pub struct PagesRc {
inner: RcRef<PagesNode>
}
impl Deref for PagesRc {
type Target = PageTree;
fn deref(&self) -> &PageTree {
match *self.inner {
PagesNode::Tree(ref tree) => tree,
_ => unreachable!(),
}
}
}
impl PagesRc {
pub fn create(tree: PageTree, update: &mut impl Updater) -> Result<PagesRc> {
Ok(PagesRc { inner: update.create(PagesNode::Tree(tree))? })
}
}
impl Object for PagesRc {
fn from_primitive(p: Primitive, resolve: &impl Resolve) -> Result<PagesRc> {
let node = t!(RcRef::from_primitive(p, resolve));
match *node {
PagesNode::Leaf(_) => Err(PdfError::WrongDictionaryType {
expected: "Pages".into(),
found: "Page".into(),
}),
PagesNode::Tree(_) => Ok(PagesRc { inner: node }),
}
}
}
impl ObjectWrite for PagesRc {
fn to_primitive(&self, update: &mut impl Updater) -> Result<Primitive> {
self.inner.to_primitive(update)
}
}
#[derive(Object, ObjectWrite, Debug, Clone, DeepClone, DataSize)]
#[pdf(Type = "Page?")]
pub struct Page {
#[pdf(key = "Parent")]
pub parent: PagesRc,
#[pdf(key = "Resources")]
pub resources: Option<MaybeRef<Resources>>,
#[pdf(key = "MediaBox")]
pub media_box: Option<Rectangle>,
#[pdf(key = "CropBox")]
pub crop_box: Option<Rectangle>,
#[pdf(key = "TrimBox")]
pub trim_box: Option<Rectangle>,
#[pdf(key = "Contents")]
pub contents: Option<Content>,
#[pdf(key = "Rotate", default = "0")]
pub rotate: i32,
#[pdf(key = "Metadata")]
pub metadata: Option<Primitive>,
#[pdf(key = "LGIDict")]
pub lgi: Option<Primitive>,
#[pdf(key = "VP")]
pub vp: Option<Primitive>,
#[pdf(key = "Annots")]
pub annotations: Lazy<Vec<MaybeRef<Annot>>>,
#[pdf(key = "AA")]
pub aa: Option<AdditionalPageActions>,
#[pdf(other)]
pub other: Dictionary,
}
#[derive(Object, ObjectWrite, Debug, Clone, DeepClone, DataSize, Default)]
pub struct AdditionalPageActions {
#[pdf(key = "O")]
pub open: Option<Action>,
#[pdf(key = "C")]
pub close: Option<Action>,
}
#[derive(Object, ObjectWrite, Debug, Clone, DeepClone, DataSize, Default)]
pub struct AdditionalFormActions {
#[pdf(key = "E")]
pub mouse_enter: Option<Action>,
#[pdf(key = "X")]
pub mouse_exit: Option<Action>,
#[pdf(key = "D")]
pub mouse_down: Option<Action>,
#[pdf(key = "U")]
pub mouse_up: Option<Action>,
#[pdf(key = "Fo")]
pub input_focus: Option<Action>,
#[pdf(key = "Bl")]
pub input_blur: Option<Action>,
#[pdf(key = "PO")]
pub page_open: Option<Action>,
#[pdf(key = "PC")]
pub page_close: Option<Action>,
#[pdf(key = "PV")]
pub page_visible: Option<Action>,
#[pdf(key = "PI")]
pub page_invisible: Option<Action>,
}
fn inherit<'a, T: 'a, F>(mut parent: &'a PageTree, f: F) -> Result<Option<T>>
where
F: Fn(&'a PageTree) -> Option<T>,
{
loop {
match (&parent.parent, f(parent)) {
(_, Some(t)) => return Ok(Some(t)),
(Some(ref p), None) => parent = p,
(None, None) => return Ok(None),
}
}
}
impl Page {
pub fn new(parent: PagesRc) -> Page {
Page {
parent,
media_box: None,
crop_box: None,
trim_box: None,
resources: None,
contents: None,
rotate: 0,
metadata: None,
lgi: None,
vp: None,
aa: None,
other: Dictionary::new(),
annotations: Default::default(),
}
}
pub fn media_box(&self) -> Result<Rectangle> {
match self.media_box {
Some(b) => Ok(b),
None => {
inherit(&self.parent, |pt| pt.media_box)?.ok_or_else(|| PdfError::MissingEntry {
typ: "Page",
field: "MediaBox".into(),
})
}
}
}
pub fn crop_box(&self) -> Result<Rectangle> {
match self.crop_box {
Some(b) => Ok(b),
None => match inherit(&self.parent, |pt| pt.crop_box)? {
Some(b) => Ok(b),
None => self.media_box(),
},
}
}
pub fn resources(&self) -> Result<&MaybeRef<Resources>> {
match self.resources {
Some(ref r) => Ok(r),
None => inherit(&self.parent, |pt| pt.resources.as_ref())?.ok_or_else(|| {
PdfError::MissingEntry {
typ: "Page",
field: "Resources".into(),
}
}),
}
}
}
impl SubType<PagesNode> for Page {}
#[derive(Object, DataSize, Clone, Debug, ObjectWrite)]
pub struct PageLabel {
#[pdf(key = "S")]
pub style: Option<Counter>,
#[pdf(key = "P")]
pub prefix: Option<PdfString>,
#[pdf(key = "St")]
pub start: Option<usize>,
}