#![forbid(unsafe_code)]
#![warn(missing_docs)]
use oxiui_core::{Color, UiError};
pub mod headless;
pub use headless::{
render_headless_once, render_headless_scene, PixelFormat, RgbaBuffer, HEADLESS_BG_COLOR,
};
pub mod framebuffer;
pub use framebuffer::Framebuffer;
pub mod clip;
pub use clip::{ClipRect, ClipStack};
pub mod draw;
pub use draw::{Canvas, SrcImage};
pub mod gradient;
pub use gradient::{lerp_color, GradientStop, LinearGradient, RadialGradient};
pub mod blend;
pub use blend::{blend_mode, blend_pixel, composite_into, BlendMode, RgbaUnit};
pub mod scanline;
pub use scanline::{fill_polygon, fill_triangle, FillRule};
pub mod path;
pub use path::{Cap, Join, Path, PathBuilder, StrokeStyle};
pub mod shadow;
pub use shadow::{box_shadow, gaussian_blur_alpha, GaussianCache};
pub mod dither;
pub use dither::{ordered_dither_rgba, BayerMatrix};
pub mod tile;
#[cfg(feature = "parallel")]
pub use tile::render_parallel;
pub use tile::{
collect_tiles, render_tiles, tiles_for, DirtyRegion, Tile, TileIter, DEFAULT_TILE_SIZE,
};
pub mod backend;
pub use backend::{blit_glyph_bitmap, SoftBackend};
#[cfg(feature = "theme")]
pub use oxiui_theme::ShadowSpec;
#[derive(Debug)]
pub enum SoftRenderError {
Io(String),
Png(String),
}
impl std::fmt::Display for SoftRenderError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SoftRenderError::Io(s) => write!(f, "soft-render I/O error: {s}"),
SoftRenderError::Png(s) => write!(f, "soft-render PNG error: {s}"),
}
}
}
impl std::error::Error for SoftRenderError {}
pub struct SoftRenderer {
_marker: std::marker::PhantomData<()>,
}
impl SoftRenderer {
pub fn new() -> Self {
Self {
_marker: std::marker::PhantomData,
}
}
pub fn clear_frame(&self, width: u32, height: u32, color: Color) -> Result<Vec<u32>, UiError> {
let fb = Framebuffer::with_fill(width, height, color);
Ok(fb.pixels().to_vec())
}
pub fn render<F>(&self, width: u32, height: u32, background: Color, draw_fn: F) -> Framebuffer
where
F: FnOnce(&mut Canvas<'_>),
{
let mut fb = Framebuffer::with_fill(width, height, background);
{
let mut canvas = Canvas::new(&mut fb);
draw_fn(&mut canvas);
}
fb
}
}
impl Default for SoftRenderer {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum AaMode {
None,
Msaa4x,
Supersampling,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ShadowQuality {
Off,
Low,
High,
}
#[derive(Clone, Debug, PartialEq)]
pub struct SoftRenderQuality {
pub aa_mode: AaMode,
pub shadow_quality: ShadowQuality,
}
impl SoftRenderQuality {
pub fn low() -> Self {
Self {
aa_mode: AaMode::None,
shadow_quality: ShadowQuality::Off,
}
}
pub fn balanced() -> Self {
Self {
aa_mode: AaMode::Supersampling,
shadow_quality: ShadowQuality::Low,
}
}
pub fn high() -> Self {
Self {
aa_mode: AaMode::Supersampling,
shadow_quality: ShadowQuality::High,
}
}
}
impl SoftRenderer {
pub fn with_size(_width: u32, _height: u32) -> Self {
Self {
_marker: std::marker::PhantomData,
}
}
}
impl SoftBackend {
pub fn with_quality(width: u32, height: u32, quality: SoftRenderQuality) -> Self {
let mut backend = Self::new(width, height);
backend.set_quality(quality);
backend
}
}
#[cfg(test)]
mod lib_tests {
use super::*;
#[test]
fn quality_low_aa_mode_is_none() {
let q = SoftRenderQuality::low();
assert_eq!(q.aa_mode, AaMode::None);
assert_eq!(q.shadow_quality, ShadowQuality::Off);
}
#[test]
fn quality_high_aa_mode_is_supersampling() {
let q = SoftRenderQuality::high();
assert_eq!(q.aa_mode, AaMode::Supersampling);
assert_eq!(q.shadow_quality, ShadowQuality::High);
}
#[test]
fn quality_balanced_preset() {
let q = SoftRenderQuality::balanced();
assert_eq!(q.aa_mode, AaMode::Supersampling);
assert_eq!(q.shadow_quality, ShadowQuality::Low);
}
#[test]
fn soft_renderer_with_size_constructs() {
let _r = SoftRenderer::with_size(100, 100);
}
#[test]
fn soft_backend_with_quality_low_constructs() {
let _b = SoftBackend::with_quality(50, 50, SoftRenderQuality::low());
}
#[test]
fn soft_backend_with_quality_high_constructs() {
let _b = SoftBackend::with_quality(50, 50, SoftRenderQuality::high());
}
#[test]
fn quality_clone_debug() {
let q = SoftRenderQuality::balanced();
let q2 = q.clone();
assert_eq!(q, q2);
let _ = format!("{:?}", q);
}
}