use crate::{interop::DynamicMemoryWStream, prelude::*, Canvas, Data, Rect, Size};
use core::fmt;
use skia_bindings::{self as sb, SkDocument, SkRefCntBase};
use std::{pin::Pin, ptr};
pub struct Document<State = state::Open> {
document: RCHandle<SkDocument>,
stream: Pin<Box<DynamicMemoryWStream>>,
state: State,
}
require_type_equality!(sb::SkDocument_INHERITED, sb::SkRefCnt);
impl NativeRefCountedBase for SkDocument {
type Base = SkRefCntBase;
}
impl<State: fmt::Debug> fmt::Debug for Document<State> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Document")
.field("state", &self.state)
.finish()
}
}
pub mod state {
use crate::Canvas;
use skia_bindings::SkCanvas;
use std::{fmt, ptr};
#[derive(Debug)]
pub struct Open {
pub(crate) pages: usize,
}
pub struct OnPage {
pub(crate) page: usize,
pub(crate) canvas: ptr::NonNull<SkCanvas>,
}
impl fmt::Debug for OnPage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OnPage")
.field("page", &self.page)
.field(
"canvas",
Canvas::borrow_from_native(unsafe { self.canvas.as_ref() }),
)
.finish()
}
}
}
impl<State> Document<State> {
pub fn abort(mut self) {
unsafe { self.document.native_mut().abort() }
drop(self)
}
}
impl Document<state::Open> {
pub(crate) fn new(
stream: Pin<Box<DynamicMemoryWStream>>,
document: RCHandle<SkDocument>,
) -> Self {
Document {
document,
stream,
state: state::Open { pages: 0 },
}
}
pub fn pages(&self) -> usize {
self.state.pages
}
pub fn begin_page(
mut self,
size: impl Into<Size>,
content: Option<&Rect>,
) -> Document<state::OnPage> {
let size = size.into();
let canvas = unsafe {
self.document.native_mut().beginPage(
size.width,
size.height,
content.native_ptr_or_null(),
)
};
Document {
stream: self.stream,
document: self.document,
state: state::OnPage {
canvas: ptr::NonNull::new(canvas).unwrap(),
page: self.state.pages + 1,
},
} as _
}
pub fn close(mut self) -> Data {
unsafe {
self.document.native_mut().close();
};
self.stream.detach_as_data()
}
}
impl Document<state::OnPage> {
pub fn page(&self) -> usize {
self.state.page
}
pub fn canvas(&mut self) -> &mut Canvas {
Canvas::borrow_from_native_mut(unsafe { self.state.canvas.as_mut() })
}
pub fn end_page(mut self) -> Document {
unsafe {
self.document.native_mut().endPage();
}
Document {
stream: self.stream,
document: self.document,
state: state::Open {
pages: self.state.page,
},
}
}
}