use crate::prelude::*;
use std::ffi::CString;
#[derive(Debug)]
pub enum LineCap {
Butt,
Round,
ProjectingSquare,
}
#[derive(Debug)]
pub enum LineJoin {
Miter,
Round,
Bevel,
}
#[derive(Debug)]
pub enum TextRenderingMode {
Fill,
Stroke,
FillThenStroke,
Invisible,
FillClipping,
StrokeClipping,
FillStrokeClipping,
Clipping,
}
#[derive(Debug)]
pub enum PageSize {
Letter,
Legal,
A3,
A4,
A5,
B4,
B5,
Executive,
US4x6,
US4x8,
US5x7,
Comm10,
}
#[derive(Debug)]
pub enum PageDirection {
Portrait,
Landscape,
}
#[derive(Debug)]
pub enum TextAlignment {
Left,
Right,
Center,
Justify,
}
pub struct Page<'a> {
page: libharu_sys::HPDF_Page,
doc: &'a Document,
}
impl<'a> Page<'a> {
pub(crate) fn new(doc: &'a Document, page: libharu_sys::HPDF_Page) -> Self {
Self { page, doc }
}
#[inline]
pub(crate) fn handle(&self) -> libharu_sys::HPDF_Page {
self.page
}
pub fn height(&self) -> anyhow::Result<Real> {
let ret = unsafe {
libharu_sys::HPDF_Page_GetHeight(self.handle())
};
Ok(ret)
}
pub fn set_height(&self, val: Real) -> anyhow::Result<()> {
let status = unsafe {
libharu_sys::HPDF_Page_SetHeight(self.handle(), val)
};
if status != 0 {
anyhow::bail!("HPDF_Page_SetHeight failed (status={})", status);
}
Ok(())
}
pub fn width(&self) -> anyhow::Result<Real> {
let ret = unsafe {
libharu_sys::HPDF_Page_GetWidth(self.handle())
};
Ok(ret)
}
pub fn set_width(&self, val: Real) -> anyhow::Result<()> {
let status = unsafe {
libharu_sys::HPDF_Page_SetWidth(self.handle(), val)
};
if status != 0 {
anyhow::bail!("HPDF_Page_SetWidth failed (status={})", status);
}
Ok(())
}
pub fn line_width(&self) -> Real {
unsafe {
libharu_sys::HPDF_Page_GetLineWidth(self.handle())
}
}
pub fn gsave(&self) -> anyhow::Result<()> {
let status = unsafe {
libharu_sys::HPDF_Page_GSave(self.handle())
};
if status != 0 {
anyhow::bail!("HPDF_Page_GSave failed (status={})", status);
}
Ok(())
}
pub fn grestore(&self) -> anyhow::Result<()> {
let status = unsafe {
libharu_sys::HPDF_Page_GRestore(self.handle())
};
if status != 0 {
anyhow::bail!("HPDF_Page_GRestore failed (status={})", status);
}
Ok(())
}
pub fn current_font(&self) -> anyhow::Result<Font> {
let font = unsafe {
libharu_sys::HPDF_Page_GetCurrentFont(self.handle())
};
if font == std::ptr::null_mut() {
anyhow::bail!("HPDF_Page_GetCurrentFont failed");
}
Ok(Font::new(self.doc, font))
}
pub fn current_font_size(&self) -> anyhow::Result<Real> {
let ret = unsafe {
libharu_sys::HPDF_Page_GetCurrentFontSize(self.handle())
};
Ok(ret)
}
pub fn text_width(&self, txt: &str) -> anyhow::Result<Real> {
let txt = CString::new(txt)?;
let ret = unsafe {
libharu_sys::HPDF_Page_TextWidth(self.handle(), std::mem::transmute(txt.as_ptr()))
};
Ok(ret)
}
pub fn measure_text(&self, text: &str, width: Real, wordwrap: bool) -> anyhow::Result<(usize, Real)> {
let orig_text = text.clone();
let text = CString::new(text)?;
let wordwrap = match wordwrap {
true => 1,
false => 0,
};
let mut real_width = 0.0;
let ret = unsafe {
libharu_sys::HPDF_Page_MeasureText(self.handle(), text.as_ptr() as *const i8, width, wordwrap, &mut real_width)
};
let ret = ret as usize;
let ret = if !orig_text.is_char_boundary(ret) {
let mut new_ret = 0;
for i in 1..ret {
if orig_text.is_char_boundary(ret-i) {
new_ret = ret - i;
break;
}
}
new_ret
}
else {
ret
};
Ok((ret as usize, real_width))
}
pub fn measure_text_bytes(&self, text: &[u8], width: Real, wordwrap: bool) -> anyhow::Result<(usize, Real)> {
let text = CString::new(text)?;
let wordwrap = match wordwrap {
true => 1,
false => 0,
};
let mut real_width = 0.0;
let ret = unsafe {
libharu_sys::HPDF_Page_MeasureText(self.handle(), text.as_ptr() as *const i8, width, wordwrap, &mut real_width)
};
Ok((ret as usize, real_width))
}
pub fn text_leading(&self) -> anyhow::Result<Real> {
let leading = unsafe {
libharu_sys::HPDF_Page_GetTextLeading(self.handle())
};
Ok(leading)
}
pub fn current_text_pos(&self) -> anyhow::Result<Point> {
let point = unsafe {
libharu_sys::HPDF_Page_GetCurrentTextPos(self.handle())
};
Ok(Point{x:point.x, y:point.y})
}
pub fn clear_dash(&self) -> anyhow::Result<()> {
let status = unsafe {
libharu_sys::HPDF_Page_SetDash(self.handle(), std::ptr::null_mut(), 0, 0)
};
if status != 0 {
anyhow::bail!("HPDF_Page_SetDash failed (status={})", status);
}
Ok(())
}
pub fn rgb_fill(&self) -> anyhow::Result<Color> {
let c = unsafe {
libharu_sys::HPDF_Page_GetRGBFill(self.handle())
};
Ok(Color{ red: c.r, green: c.g, blue: c.b })
}
pub fn create_destination(&self) -> anyhow::Result<Destination> {
let dst = unsafe {
libharu_sys::HPDF_Page_CreateDestination(self.handle())
};
if dst == std::ptr::null_mut() {
anyhow::bail!("HPDF_Page_CreateDestination failed");
}
Ok(Destination::new(self, dst))
}
pub fn current_pos(&self) -> anyhow::Result<Point> {
let point = unsafe {
libharu_sys::HPDF_Page_GetCurrentPos(self.handle())
};
Ok(Point{ x: point.x, y: point.y })
}
pub fn set_size(&self, size: PageSize, direction: PageDirection) -> anyhow::Result<()> {
let size = match size {
PageSize::Letter => libharu_sys::HPDF_PageSizes::HPDF_PAGE_SIZE_LETTER,
PageSize::Legal => libharu_sys::HPDF_PageSizes::HPDF_PAGE_SIZE_LEGAL,
PageSize::A3 => libharu_sys::HPDF_PageSizes::HPDF_PAGE_SIZE_A3,
PageSize::A4 => libharu_sys::HPDF_PageSizes::HPDF_PAGE_SIZE_A4,
PageSize::A5 => libharu_sys::HPDF_PageSizes::HPDF_PAGE_SIZE_A5,
PageSize::B4 => libharu_sys::HPDF_PageSizes::HPDF_PAGE_SIZE_B4,
PageSize::B5 => libharu_sys::HPDF_PageSizes::HPDF_PAGE_SIZE_B5,
PageSize::Executive => libharu_sys::HPDF_PageSizes::HPDF_PAGE_SIZE_EXECUTIVE,
PageSize::US4x6 => libharu_sys::HPDF_PageSizes::HPDF_PAGE_SIZE_US4x6,
PageSize::US4x8 => libharu_sys::HPDF_PageSizes::HPDF_PAGE_SIZE_US4x8,
PageSize::US5x7 => libharu_sys::HPDF_PageSizes::HPDF_PAGE_SIZE_US5x7,
PageSize::Comm10 => libharu_sys::HPDF_PageSizes::HPDF_PAGE_SIZE_COMM10,
};
let direction = match direction {
PageDirection::Portrait => libharu_sys::HPDF_PageDirection::HPDF_PAGE_PORTRAIT,
PageDirection::Landscape => libharu_sys::HPDF_PageDirection::HPDF_PAGE_LANDSCAPE,
};
let status = unsafe {
libharu_sys::HPDF_Page_SetSize(self.handle(), size, direction)
};
if status != 0 {
anyhow::bail!("HPDF_Page_SetSize failed (status={})", status);
}
Ok(())
}
pub fn set_rotate(&self, angle: u16) -> anyhow::Result<()> {
let status = unsafe {
libharu_sys::HPDF_Page_SetRotate(self.handle(), angle)
};
if status != 0 {
anyhow::bail!("HPDF_Page_SetRotate failed (status={})", status);
}
Ok(())
}
pub fn draw_image<T>(&self, img: &Image, pos: T, width: Real, height: Real) -> anyhow::Result<()>
where
T: Into<Point>
{
let pos = pos.into();
let status = unsafe {
libharu_sys::HPDF_Page_DrawImage(
self.handle(),
img.handle(),
pos.x,
pos.y,
width, height)
};
if status != 0 {
anyhow::bail!("HPDF_Page_DrawImage failed (status={})", status);
}
Ok(())
}
}