use std::{
error::Error,
fmt,
io::{self},
};
use crate::{
interop::{MemoryStream, NativeStreamBase, RustStream},
prelude::*,
resources::NativeResourceProvider,
Canvas, Size,
};
use skia_bindings::{self as sb, SkRefCntBase};
use super::Svg;
pub type Dom = RCHandle<sb::SkSVGDOM>;
require_base_type!(sb::SkSVGDOM, sb::SkRefCnt);
impl NativeRefCountedBase for sb::SkSVGDOM {
type Base = SkRefCntBase;
}
impl fmt::Debug for Dom {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Dom").finish()
}
}
impl Dom {
pub fn read<R: io::Read>(
mut reader: R,
resource_provider: impl Into<NativeResourceProvider>,
) -> Result<Self, LoadError> {
let mut reader = RustStream::new(&mut reader);
let stream = reader.stream_mut();
let resource_provider = resource_provider.into();
let out = unsafe { sb::C_SkSVGDOM_MakeFromStream(stream, resource_provider.into_ptr()) };
Self::from_ptr(out).ok_or(LoadError)
}
pub fn from_str(
svg: impl AsRef<str>,
resource_provider: impl Into<NativeResourceProvider>,
) -> Result<Self, LoadError> {
Self::from_bytes(svg.as_ref().as_bytes(), resource_provider)
}
pub fn from_bytes(
svg: &[u8],
resource_provider: impl Into<NativeResourceProvider>,
) -> Result<Self, LoadError> {
let mut ms = MemoryStream::from_bytes(svg);
let resource_provider = resource_provider.into();
let out = unsafe {
sb::C_SkSVGDOM_MakeFromStream(
ms.native_mut().as_stream_mut(),
resource_provider.into_ptr(),
)
};
Self::from_ptr(out).ok_or(LoadError)
}
pub fn root(&self) -> Svg {
unsafe {
Svg::from_unshared_ptr(sb::C_SkSVGDOM_getRoot(self.native()) as *mut _)
.unwrap_unchecked()
}
}
pub fn render(&self, canvas: &Canvas) {
#[cfg(all(feature = "embed-icudtl", feature = "textlayout"))]
crate::icu::init();
unsafe { sb::SkSVGDOM::render(self.native() as &_, canvas.native_mut()) }
}
pub fn set_container_size(&mut self, size: impl Into<Size>) {
let size = size.into();
unsafe { sb::C_SkSVGDOM_setContainerSize(self.native_mut(), size.native()) }
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LoadError;
impl fmt::Display for LoadError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Failed to load svg (reason unknown)")
}
}
impl Error for LoadError {
fn description(&self) -> &str {
"Failed to load svg (reason unknown)"
}
}
impl From<LoadError> for io::Error {
fn from(other: LoadError) -> Self {
io::Error::other(other)
}
}