use std::ptr;
use haru_types::HaruError;
use haru_types::LineCap;
use haru_types::Rect;
use haru_types::RenderingMode;
use haru_types::TextAlign;
use crate::font::PdfFont;
use crate::haru_bindings as hb;
use crate::haru_types;
use crate::haru_types::ImageFit;
use crate::prelude::PdfImage;
#[derive(Debug, Copy, Clone)]
pub struct PdfPage {
pub page: hb::HPDF_Page,
}
impl PdfPage {
pub fn arc(
&self,
x: f32,
y: f32,
radius: f32,
ang1: f32,
ang2: f32,
) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_Arc(self.page, x, y, radius, ang1, ang2) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn begin_text(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_BeginText(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn circle(&self, x: f32, y: f32, radius: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_Circle(self.page, x, y, radius) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn clip(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_Clip(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn close_path(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_ClosePath(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn close_path_stroke(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_ClosePathStroke(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn close_path_eofill_stroke(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_ClosePathEofillStroke(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(0)),
}
}
pub fn close_path_fill_stroke(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_ClosePathFillStroke(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(0)),
}
}
pub fn concat(
&self,
a: f32,
b: f32,
c: f32,
d: f32,
x: f32,
y: f32,
) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_Concat(self.page, a, b, c, d, x, y) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn curve_to(
&self,
x1: f32,
y1: f32,
x2: f32,
y2: f32,
x3: f32,
y3: f32,
) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_CurveTo(self.page, x1, y1, x2, y2, x3, y3) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn curve_to2(&self, x2: f32, y2: f32, x3: f32, y3: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_CurveTo2(self.page, x2, y2, x3, y3) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn curve_to3(&self, x1: f32, y1: f32, x3: f32, y3: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_CurveTo3(self.page, x1, y1, x3, y3) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn ellipse(&self, x: f32, y: f32, xray: f32, yray: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_Ellipse(self.page, x, y, xray, yray) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn end_path(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_EndPath(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn end_text(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_EndText(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn eo_clip(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_Eoclip(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn eo_fill(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_Eofill(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn eo_fill_stroke(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_EofillStroke(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn fill(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_Fill(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn fill_stroke(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_FillStroke(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn g_restore(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_GRestore(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn g_save(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_GSave(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn line_to(&self, x: f32, y: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_LineTo(self.page, x, y) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_char_space(&self, value: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetCharSpace(self.page, value) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_cmyk_fill(&self, c: f32, m: f32, y: f32, k: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetCMYKFill(self.page, c, m, y, k) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_cmyk_stroke(&self, c: f32, m: f32, y: f32, k: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetCMYKStroke(self.page, c, m, y, k) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_font_and_size(&self, font: PdfFont, size: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetFontAndSize(self.page, font.font_ref, size) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_gray_fill(&self, gray: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetGrayFill(self.page, gray) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_gray_stroke(&self, gray: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetGrayStroke(self.page, gray) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_horizontal_scalling(&self, value: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetHorizontalScalling(self.page, value) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_line_cap(&self, line_cap: LineCap) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetLineCap(self.page, line_cap as u32) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_line_join(&self, line_join: haru_types::LineJoin) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetLineJoin(self.page, line_join as u32) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_miter_limit(&self, miter_limit: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetMiterLimit(self.page, miter_limit) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_line_width(&self, line_width: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetLineWidth(self.page, line_width) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn move_text_pos(&self, x: f32, y: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_MoveTextPos(self.page, x, y) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn move_text_pos2(&self, x: f32, y: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_MoveTextPos2(self.page, x, y) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn move_to(&self, x: f32, y: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_MoveTo(self.page, x, y) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn move_to_next_line(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_MoveToNextLine(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn rectangle(&self, x: f32, y: f32, width: f32, height: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_Rectangle(self.page, x, y, width, height) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_width(&self, width: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetWidth(self.page, width) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_height(&self, height: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetHeight(self.page, height) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_text_rendering_mode(&self, mode: RenderingMode) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetTextRenderingMode(self.page, mode as u32) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn mtrx_rotate(&self, degrees: f32) -> Result<&Self, HaruError> {
let x = degrees.to_radians();
let result = unsafe {
hb::HPDF_Page_Concat(self.page, x.cos(), x.sin(), -x.sin(), x.cos(), 0.0, 0.0)
};
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn mtrx_translate(&self, x: f32, y: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_Concat(self.page, 1.0, 0.0, 0.0, 1.0, x, y) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn get_width(&self) -> f32 {
unsafe { hb::HPDF_Page_GetWidth(self.page) }
}
pub fn get_height(&self) -> f32 {
unsafe { hb::HPDF_Page_GetHeight(self.page) }
}
pub fn set_rgb_fill(&self, r: f32, g: f32, b: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetRGBFill(self.page, r, g, b) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_rgb_stroke(&self, r: f32, g: f32, b: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetRGBStroke(self.page, r, g, b) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_text_leading(&self, value: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetTextLeading(self.page, value) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_text_matrix(
&self,
a: f32,
b: f32,
c: f32,
d: f32,
x: f32,
y: f32,
) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetTextMatrix(self.page, a, b, c, d, x, y) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_text_rise(&self, value: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetTextRise(self.page, value) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn set_word_space(&self, value: f32) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_SetWordSpace(self.page, value) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn show_text(&self, text: &str) -> Result<&Self, HaruError> {
let text = std::ffi::CString::new(text).unwrap();
let result = unsafe { hb::HPDF_Page_ShowText(self.page, text.as_ptr()) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn draw_image(&self, image: &PdfImage, rect: &Rect) -> Result<&Self, HaruError> {
let result = unsafe {
hb::HPDF_Page_DrawImage(
self.page,
image.image_ref,
rect.x,
rect.y,
rect.width,
rect.height,
)
};
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn draw_image_fit(
&self,
image: &PdfImage,
rect: Rect,
fit: ImageFit,
align_h: haru_types::ImageAlign,
align_v: haru_types::ImageAlign,
) -> Result<&Self, HaruError> {
let img_width = image.get_width()? as f32;
let img_height = image.get_height()? as f32;
let mut effective_x = rect.x;
let mut effective_y = rect.y;
let mut effective_width = rect.width;
let mut effective_height = rect.height;
match fit {
ImageFit::Fill => {}
ImageFit::FitWidth => {
let ratio = rect.width / img_width;
effective_width = img_width * ratio;
effective_height = img_height * ratio;
}
ImageFit::FitHeight => {
let ratio = rect.height / img_height;
effective_width = img_width * ratio;
effective_height = img_height * ratio;
}
ImageFit::FitBoth => {
let width_ratio = rect.width / img_width;
let height_ratio = rect.height / img_height;
let ratio = width_ratio.min(height_ratio);
effective_width = img_width * ratio;
effective_height = img_height * ratio;
}
ImageFit::Cover => {
let width_ratio = rect.width / img_width;
let height_ratio = rect.height / img_height;
let ratio = width_ratio.max(height_ratio);
effective_width = img_width * ratio;
effective_height = img_height * ratio;
}
}
match align_h {
haru_types::ImageAlign::Start => {
}
haru_types::ImageAlign::End => {
effective_x = rect.x + rect.width - effective_width;
}
haru_types::ImageAlign::Center => {
effective_x = rect.x + (rect.width - effective_width) / 2.0;
}
}
match align_v {
haru_types::ImageAlign::Start => {
}
haru_types::ImageAlign::End => {
effective_y = rect.y + rect.height - effective_height;
}
haru_types::ImageAlign::Center => {
effective_y = rect.y + (rect.height - effective_height) / 2.0;
}
}
let result = unsafe {
hb::HPDF_Page_DrawImage(
self.page,
image.image_ref,
effective_x,
effective_y,
effective_width,
effective_height,
)
};
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn show_text_next_line(&self, text: &str) -> Result<&Self, HaruError> {
let text = std::ffi::CString::new(text).unwrap();
let result = unsafe { hb::HPDF_Page_ShowTextNextLine(self.page, text.as_ptr()) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn show_text_next_line_ex(
&self,
word_space: f32,
char_space: f32,
text: &str,
) -> Result<&Self, HaruError> {
let text = std::ffi::CString::new(text).unwrap();
let result = unsafe {
hb::HPDF_Page_ShowTextNextLineEx(self.page, word_space, char_space, text.as_ptr())
};
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn stroke(&self) -> Result<&Self, HaruError> {
let result = unsafe { hb::HPDF_Page_Stroke(self.page) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn text_out(&self, x: f32, y: f32, text: &str) -> Result<&Self, HaruError> {
let text = std::ffi::CString::new(text).unwrap();
let result = unsafe { hb::HPDF_Page_TextOut(self.page, x, y, text.as_ptr()) };
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
pub fn text_rect(
&self,
left: f32,
top: f32,
right: f32,
bottom: f32,
text: &str,
align: TextAlign,
) -> Result<&Self, HaruError> {
let text = std::ffi::CString::new(text).unwrap();
let result = unsafe {
hb::HPDF_Page_TextRect(
self.page,
left,
top,
right,
bottom,
text.as_ptr(),
align.to_hpdf_text_align(),
ptr::null_mut(),
)
};
match result {
0 => Ok(self),
_ => Err(HaruError::from(result)),
}
}
}