How to draw on a winit window by using 'skia-safe'?

160 Views Asked by At

I want to draw on a winit window using skia-safe with less dependency, and I want to run it on multi-platforms(such as mobiles, desktop, and embedded).

I tried skia-safe's example 'gl-window', and it works, but it can't run on iOS/Android:

#![allow(dead_code)]

// cargo 1.45.1 / rustfmt 1.4.17-stable fails to process the relative path on Windows.
#[rustfmt::skip]
#[path = "../icon/renderer.rs"]
mod renderer;

#[cfg(target_os = "android")]
fn main() {
    println!("This example is not supported on Android (https://github.com/rust-windowing/winit/issues/948).")
}

#[cfg(target_os = "emscripten")]
fn main() {
    println!("This example is not supported on Emscripten (https://github.com/rust-windowing/glutin/issues/1349)")
}

#[cfg(target_os = "ios")]
fn main() {
    println!("This example is not supported on iOS (https://github.com/rust-windowing/glutin/issues/1448)")
}

I tried using softbuffer and tiny-skia, but in softbuffer's README it says:

✅: Present | ❌: Absent

AndroidNdk ❌
#![allow(unused)]
use softbuffer::{Context, Surface};
use winit::raw_window_handle::DrmWindowHandle;
use std::num::NonZeroU32;
use tiny_skia::{Color, FillRule, Paint, PathBuilder, Pixmap, Stroke, Transform};
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::WindowBuilder;

fn main() {
    let event_loop = EventLoop::new().unwrap();
    let window = WindowBuilder::new()
        .build(&event_loop)
        .unwrap();
    let context = Context::new(&window).unwrap();
    // let mut surface = Surface::new(&context, &window).unwrap();
    let mut surface = Surface::new(&context, &window).unwrap();

    let _  = event_loop.run(move |event, control_flow| {
        if let Event::WindowEvent { event, window_id } = event {
            match event {
                WindowEvent::CloseRequested => control_flow.exit(),
                WindowEvent::RedrawRequested => {
                    let (width, height) = {
                        // let size = window.inner_size();
                        // (size.width, size.height)
                        (1000, 1000)
                    };
                    surface
                        .resize(
                            NonZeroU32::new(width).unwrap(),
                            NonZeroU32::new(height).unwrap(),
                        )
                        .unwrap();

                    let mut pixmap = Pixmap::new(width, height).unwrap();
                    pixmap.fill(Color::WHITE);
                    let path = PathBuilder::from_circle(
                        (width / 2) as f32,
                        (height / 2) as f32,
                        (width.min(height) / 2) as f32,
                    )
                    .unwrap();
                    let mut paint = Paint::default();
                    paint.set_color_rgba8(0, 128, 128 , 255);
                    // paint.set_color_rgba8(0, 0, 0 , 255);
                    pixmap.fill_path(
                        &path,
                        &paint,
                        FillRule::EvenOdd,
                        Transform::identity(),
                        None,
                    );
                    paint.set_color_rgba8(255, 0, 0, 255);
                    let mut stroke = Stroke::default();
                    stroke.width = 10.0;
                    pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);

                    let mut buffer = surface.buffer_mut().unwrap();
                    for index in 0..(width * height) as usize {
                        buffer[index] = pixmap.data()[index * 4 + 2] as u32
                            | (pixmap.data()[index * 4 + 1] as u32) << 8
                            | (pixmap.data()[index * 4] as u32) << 16;
                    }

                    buffer.present().unwrap();
                },
                _ => ()
            }
        }
    }).unwrap();
}
0

There are 0 best solutions below