use crate::text::TextLayout;
use floem_renderer::gpu_resources::GpuResources;
use floem_renderer::Img;
use floem_tiny_skia_renderer::TinySkiaRenderer;
#[cfg(feature = "vello")]
use floem_vello_renderer::VelloRenderer;
#[cfg(not(feature = "vello"))]
use floem_vger_renderer::VgerRenderer;
use peniko::kurbo::{self, Affine, Rect, Shape, Size, Stroke};
use peniko::BrushRef;
#[allow(clippy::large_enum_variant)]
pub enum Renderer<W> {
#[cfg(feature = "vello")]
Vello(VelloRenderer),
#[cfg(not(feature = "vello"))]
Vger(VgerRenderer),
TinySkia(TinySkiaRenderer<W>),
Uninitialized {
scale: f64,
size: Size,
},
}
impl<W: wgpu::WindowHandle> Renderer<W> {
pub fn new(
window: W,
gpu_resources: GpuResources,
scale: f64,
size: Size,
font_embolden: f32,
) -> Self
where
W: Clone + 'static,
{
let size = Size::new(size.width.max(1.0), size.height.max(1.0));
let force_tiny_skia = std::env::var("FLOEM_FORCE_TINY_SKIA")
.ok()
.map(|val| val.as_str() == "1")
.unwrap_or(false);
#[cfg(feature = "vello")]
let vger_err = if !force_tiny_skia {
match VelloRenderer::new(
gpu_resources,
size.width as u32,
size.height as u32,
scale,
font_embolden,
) {
Ok(vger) => return Self::Vello(vger),
Err(err) => Some(err),
}
} else {
None
};
#[cfg(not(feature = "vello"))]
let vger_err = if !force_tiny_skia {
match VgerRenderer::new(
gpu_resources,
size.width as u32,
size.height as u32,
scale,
font_embolden,
) {
Ok(vger) => return Self::Vger(vger),
Err(err) => Some(err),
}
} else {
None
};
let tiny_skia_err = match TinySkiaRenderer::new(
window,
size.width as u32,
size.height as u32,
scale,
font_embolden,
) {
Ok(tiny_skia) => return Self::TinySkia(tiny_skia),
Err(err) => err,
};
if !force_tiny_skia {
panic!("Failed to create VgerRenderer: {}\nFailed to create TinySkiaRenderer: {tiny_skia_err}", vger_err.unwrap());
} else {
panic!("Failed to create TinySkiaRenderer: {tiny_skia_err}");
}
}
pub fn resize(&mut self, scale: f64, size: Size) {
let size = Size::new(size.width.max(1.0), size.height.max(1.0));
match self {
#[cfg(feature = "vello")]
Renderer::Vello(r) => r.resize(size.width as u32, size.height as u32, scale),
#[cfg(not(feature = "vello"))]
Renderer::Vger(r) => r.resize(size.width as u32, size.height as u32, scale),
Renderer::TinySkia(r) => r.resize(size.width as u32, size.height as u32, scale),
Renderer::Uninitialized { .. } => {}
}
}
pub fn set_scale(&mut self, scale: f64) {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(r) => r.set_scale(scale),
#[cfg(not(feature = "vello"))]
Renderer::Vger(r) => r.set_scale(scale),
Renderer::TinySkia(r) => r.set_scale(scale),
Renderer::Uninitialized {
scale: old_scale, ..
} => {
*old_scale = scale;
}
}
}
pub fn scale(&self) -> f64 {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(r) => r.scale(),
#[cfg(not(feature = "vello"))]
Renderer::Vger(r) => r.scale(),
Renderer::TinySkia(r) => r.scale(),
Renderer::Uninitialized { scale, .. } => *scale,
}
}
pub fn size(&self) -> Size {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(r) => r.size(),
#[cfg(not(feature = "vello"))]
Renderer::Vger(r) => r.size(),
Renderer::TinySkia(r) => r.size(),
Renderer::Uninitialized { size, .. } => *size,
}
}
}
impl<W: wgpu::WindowHandle> floem_renderer::Renderer for Renderer<W> {
fn begin(&mut self, capture: bool) {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(r) => {
r.begin(capture);
}
#[cfg(not(feature = "vello"))]
Renderer::Vger(r) => {
r.begin(capture);
}
Renderer::TinySkia(r) => {
r.begin(capture);
}
Renderer::Uninitialized { .. } => {}
}
}
fn clip(&mut self, shape: &impl Shape) {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(v) => {
v.clip(shape);
}
#[cfg(not(feature = "vello"))]
Renderer::Vger(v) => {
v.clip(shape);
}
Renderer::TinySkia(v) => {
v.clip(shape);
}
Renderer::Uninitialized { .. } => {}
}
}
fn clear_clip(&mut self) {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(v) => {
v.clear_clip();
}
#[cfg(not(feature = "vello"))]
Renderer::Vger(v) => {
v.clear_clip();
}
Renderer::TinySkia(v) => {
v.clear_clip();
}
Renderer::Uninitialized { .. } => {}
}
}
fn stroke<'b, 's>(
&mut self,
shape: &impl Shape,
brush: impl Into<BrushRef<'b>>,
stroke: &'s Stroke,
) {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(v) => {
v.stroke(shape, brush, stroke);
}
#[cfg(not(feature = "vello"))]
Renderer::Vger(v) => {
v.stroke(shape, brush, stroke);
}
Renderer::TinySkia(v) => {
v.stroke(shape, brush, stroke);
}
Renderer::Uninitialized { .. } => {}
}
}
fn fill<'b>(
&mut self,
path: &impl peniko::kurbo::Shape,
brush: impl Into<peniko::BrushRef<'b>>,
blur_radius: f64,
) {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(v) => {
v.fill(path, brush, blur_radius);
}
#[cfg(not(feature = "vello"))]
Renderer::Vger(v) => {
v.fill(path, brush, blur_radius);
}
Renderer::TinySkia(v) => {
v.fill(path, brush, blur_radius);
}
Renderer::Uninitialized { .. } => {}
}
}
fn draw_text(&mut self, layout: &TextLayout, pos: impl Into<kurbo::Point>) {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(v) => {
v.draw_text(layout, pos);
}
#[cfg(not(feature = "vello"))]
Renderer::Vger(v) => {
v.draw_text(layout, pos);
}
Renderer::TinySkia(v) => {
v.draw_text(layout, pos);
}
Renderer::Uninitialized { .. } => {}
}
}
fn draw_img(&mut self, img: Img<'_>, rect: Rect) {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(v) => {
v.draw_img(img, rect);
}
#[cfg(not(feature = "vello"))]
Renderer::Vger(v) => {
v.draw_img(img, rect);
}
Renderer::TinySkia(v) => {
v.draw_img(img, rect);
}
Renderer::Uninitialized { .. } => {}
}
}
fn draw_svg<'b>(
&mut self,
svg: floem_renderer::Svg<'b>,
rect: Rect,
brush: Option<impl Into<BrushRef<'b>>>,
) {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(v) => {
v.draw_svg(svg, rect, brush);
}
#[cfg(not(feature = "vello"))]
Renderer::Vger(v) => {
v.draw_svg(svg, rect, brush);
}
Renderer::TinySkia(v) => {
v.draw_svg(svg, rect, brush);
}
Renderer::Uninitialized { .. } => {}
}
}
fn transform(&mut self, transform: Affine) {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(v) => {
v.transform(transform);
}
#[cfg(not(feature = "vello"))]
Renderer::Vger(v) => {
v.transform(transform);
}
Renderer::TinySkia(v) => {
v.transform(transform);
}
Renderer::Uninitialized { .. } => {}
}
}
fn set_z_index(&mut self, z_index: i32) {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(v) => {
v.set_z_index(z_index);
}
#[cfg(not(feature = "vello"))]
Renderer::Vger(v) => {
v.set_z_index(z_index);
}
Renderer::TinySkia(v) => {
v.set_z_index(z_index);
}
Renderer::Uninitialized { .. } => {}
}
}
fn finish(&mut self) -> Option<peniko::Image> {
match self {
#[cfg(feature = "vello")]
Renderer::Vello(r) => r.finish(),
#[cfg(not(feature = "vello"))]
Renderer::Vger(r) => r.finish(),
Renderer::TinySkia(r) => r.finish(),
Renderer::Uninitialized { .. } => None,
}
}
}