pub mod assets;
pub mod core;
pub mod font;
pub mod language;
pub mod layout;
pub mod render;
pub mod runtime;
use std::{collections::HashMap, path::PathBuf, rc::Rc};
use anyhow::Context;
use skia_safe::{Data, Image};
use crate::{
assets::DefaultAssetProvider,
core::{ImageWrap, Value},
font::{FontFile, FontManager},
language::parser::Parser,
layout::build_layout_tree,
render::{RenderOptions, context::RenderContext},
runtime::Runtime,
};
#[derive(Debug)]
pub struct SeruOption {
pub allow_network_asset: bool,
pub asset_root: Option<PathBuf>,
pub load_system_fonts: bool,
pub fonts: Vec<FontFile>,
}
pub struct Seru {
runtime: Runtime,
font_manager: Rc<FontManager>,
}
impl Seru {
pub fn new() -> anyhow::Result<Self> {
Ok(Self::new_with_options(&SeruOption {
allow_network_asset: true,
asset_root: None,
load_system_fonts: true,
fonts: vec![],
})?)
}
pub fn new_with_options(options: &SeruOption) -> anyhow::Result<Self> {
let font_manager = Rc::new(FontManager::new(options.load_system_fonts, &options.fonts)?);
let asset_provider = Rc::new(DefaultAssetProvider {
allow_network_asset: options.allow_network_asset,
asset_root: options.asset_root.clone(),
});
let mut runtime = Runtime::new(RenderContext {
font_manager: font_manager.clone(),
asset_provider,
});
runtime.register_builtin_functions();
Ok(Self {
runtime,
font_manager,
})
}
pub fn load_str(&mut self, src: &str) -> anyhow::Result<()> {
let prog = Parser::from_src(src)?.parse()?;
self.runtime.evaluate(&prog)?;
Ok(())
}
pub fn load_image(&self, image: &[u8]) -> Option<Value> {
let image = Image::from_encoded(Data::new_copy(image))?;
Some(Value::Image(ImageWrap(image)))
}
pub fn render(
&mut self,
component: &str,
args: HashMap<String, Value>,
options: RenderOptions,
) -> anyhow::Result<Vec<u8>> {
let node = self
.runtime
.build_render_tree(component, args)?
.context("component returned no render node")?;
let layout = build_layout_tree(
&node,
options.width as usize,
options.height as usize,
&self.font_manager,
)?;
render::render(&options, &layout, &self.font_manager)
}
}