use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, OnceLock};
use iced::widget::image;
pub mod engines;
pub use engines::{Engine, PageType, PixelFormat, ViewId};
mod webview;
pub use basic::{Action, WebView};
pub use webview::{advanced, basic};
#[cfg(feature = "blitz")]
pub use engines::blitz::Blitz;
#[cfg(feature = "litehtml")]
pub use engines::litehtml::Litehtml;
#[cfg(feature = "servo")]
pub use engines::servo::Servo;
#[cfg(feature = "cef")]
pub use engines::cef_engine::{cef_subprocess_check, Cef};
pub(crate) mod util;
#[cfg(any(feature = "litehtml", feature = "blitz"))]
pub(crate) mod fetch;
static FRAME_GENERATION: AtomicU64 = AtomicU64::new(0);
fn next_generation() -> u64 {
FRAME_GENERATION.fetch_add(1, Ordering::Relaxed)
}
#[cfg_attr(
not(any(feature = "servo", feature = "cef", feature = "blitz")),
allow(dead_code)
)]
#[derive(Clone, Debug)]
pub struct FramePixels {
pub(crate) data: Arc<Vec<u8>>,
pub(crate) generation: u64,
}
#[derive(Clone, Debug)]
pub struct ImageInfo {
width: u32,
height: u32,
handle: Arc<OnceLock<image::Handle>>,
raw_pixels: Arc<Vec<u8>>,
generation: u64,
}
impl Default for ImageInfo {
fn default() -> Self {
Self::blank(Self::WIDTH, Self::HEIGHT)
}
}
impl ImageInfo {
const WIDTH: u32 = 800;
const HEIGHT: u32 = 800;
#[allow(dead_code)]
fn new(mut pixels: Vec<u8>, format: PixelFormat, width: u32, height: u32) -> Self {
pixels.truncate(pixels.len() / 4 * 4);
if let PixelFormat::Bgra = format {
pixels
.as_chunks_mut::<4>()
.0
.iter_mut()
.for_each(|chunk| chunk.swap(0, 2));
}
Self {
width,
height,
handle: Arc::new(OnceLock::new()),
raw_pixels: Arc::new(pixels),
generation: next_generation(),
}
}
pub fn as_handle(&self) -> image::Handle {
self.handle
.get_or_init(|| {
image::Handle::from_rgba(self.width, self.height, (*self.raw_pixels).clone())
})
.clone()
}
pub fn image_width(&self) -> u32 {
self.width
}
pub fn image_height(&self) -> u32 {
self.height
}
pub fn pixels(&self) -> FramePixels {
FramePixels {
data: Arc::clone(&self.raw_pixels),
generation: self.generation,
}
}
fn blank(width: u32, height: u32) -> Self {
let (w, h) = (width as usize)
.checked_mul(height as usize)
.and_then(|n| n.checked_mul(4))
.map_or((1u32, 1u32), |_| (width, height));
Self {
width: w,
height: h,
handle: Arc::new(OnceLock::new()),
raw_pixels: Arc::new(vec![255; w as usize * h as usize * 4]),
generation: next_generation(),
}
}
}