Add screenshot helpers to iced_test
This commit is contained in:
parent
ea614387f4
commit
085c8fae8d
10 changed files with 183 additions and 78 deletions
|
|
@ -1,8 +1,6 @@
|
||||||
//! Load and draw raster graphics.
|
//! Load and draw raster graphics.
|
||||||
pub use bytes::Bytes;
|
|
||||||
|
|
||||||
use crate::border;
|
use crate::border;
|
||||||
use crate::{Radians, Rectangle, Size};
|
use crate::{Bytes, Radians, Rectangle, Size};
|
||||||
|
|
||||||
use rustc_hash::FxHasher;
|
use rustc_hash::FxHasher;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ pub use transformation::Transformation;
|
||||||
pub use vector::Vector;
|
pub use vector::Vector;
|
||||||
pub use widget::Widget;
|
pub use widget::Widget;
|
||||||
|
|
||||||
|
pub use bytes::Bytes;
|
||||||
pub use smol_str::SmolStr;
|
pub use smol_str::SmolStr;
|
||||||
|
|
||||||
/// A function that can _never_ be called.
|
/// A function that can _never_ be called.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
//! Take screenshots of a window.
|
//! Take screenshots of a window.
|
||||||
use crate::{Rectangle, Size};
|
use crate::{Bytes, Rectangle, Size};
|
||||||
|
|
||||||
use bytes::Bytes;
|
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
/// Data of a screenshot, captured with `window::screenshot()`.
|
/// Data of a screenshot, captured with `window::screenshot()`.
|
||||||
|
|
@ -9,8 +8,8 @@ use std::fmt::{Debug, Formatter};
|
||||||
/// The `bytes` of this screenshot will always be ordered as `RGBA` in the `sRGB` color space.
|
/// The `bytes` of this screenshot will always be ordered as `RGBA` in the `sRGB` color space.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Screenshot {
|
pub struct Screenshot {
|
||||||
/// The bytes of the [`Screenshot`].
|
/// The RGBA bytes of the [`Screenshot`].
|
||||||
pub bytes: Bytes,
|
pub rgba: Bytes,
|
||||||
/// The size of the [`Screenshot`] in physical pixels.
|
/// The size of the [`Screenshot`] in physical pixels.
|
||||||
pub size: Size<u32>,
|
pub size: Size<u32>,
|
||||||
/// The scale factor of the [`Screenshot`]. This can be useful when converting between widget
|
/// The scale factor of the [`Screenshot`]. This can be useful when converting between widget
|
||||||
|
|
@ -23,7 +22,7 @@ impl Debug for Screenshot {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"Screenshot: {{ \n bytes: {}\n scale: {}\n size: {:?} }}",
|
"Screenshot: {{ \n bytes: {}\n scale: {}\n size: {:?} }}",
|
||||||
self.bytes.len(),
|
self.rgba.len(),
|
||||||
self.scale_factor,
|
self.scale_factor,
|
||||||
self.size
|
self.size
|
||||||
)
|
)
|
||||||
|
|
@ -33,12 +32,12 @@ impl Debug for Screenshot {
|
||||||
impl Screenshot {
|
impl Screenshot {
|
||||||
/// Creates a new [`Screenshot`].
|
/// Creates a new [`Screenshot`].
|
||||||
pub fn new(
|
pub fn new(
|
||||||
bytes: impl Into<Bytes>,
|
rgba: impl Into<Bytes>,
|
||||||
size: Size<u32>,
|
size: Size<u32>,
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
bytes: bytes.into(),
|
rgba: rgba.into(),
|
||||||
size,
|
size,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +64,7 @@ impl Screenshot {
|
||||||
let column_range = region.x as usize * PIXEL_SIZE
|
let column_range = region.x as usize * PIXEL_SIZE
|
||||||
..(region.x + region.width) as usize * PIXEL_SIZE;
|
..(region.x + region.width) as usize * PIXEL_SIZE;
|
||||||
|
|
||||||
let chopped = self.bytes.chunks(bytes_per_row).enumerate().fold(
|
let chopped = self.rgba.chunks(bytes_per_row).enumerate().fold(
|
||||||
vec![],
|
vec![],
|
||||||
|mut acc, (row, bytes)| {
|
|mut acc, (row, bytes)| {
|
||||||
if row_range.contains(&row) {
|
if row_range.contains(&row) {
|
||||||
|
|
@ -77,7 +76,7 @@ impl Screenshot {
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
bytes: Bytes::from(chopped),
|
rgba: Bytes::from(chopped),
|
||||||
size: Size::new(region.width, region.height),
|
size: Size::new(region.width, region.height),
|
||||||
scale_factor: self.scale_factor,
|
scale_factor: self.scale_factor,
|
||||||
})
|
})
|
||||||
|
|
@ -86,13 +85,13 @@ impl Screenshot {
|
||||||
|
|
||||||
impl AsRef<[u8]> for Screenshot {
|
impl AsRef<[u8]> for Screenshot {
|
||||||
fn as_ref(&self) -> &[u8] {
|
fn as_ref(&self) -> &[u8] {
|
||||||
&self.bytes
|
&self.rgba
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Screenshot> for Bytes {
|
impl From<Screenshot> for Bytes {
|
||||||
fn from(screenshot: Screenshot) -> Self {
|
fn from(screenshot: Screenshot) -> Self {
|
||||||
screenshot.bytes
|
screenshot.rgba
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ impl Example {
|
||||||
image::Handle::from_rgba(
|
image::Handle::from_rgba(
|
||||||
screenshot.size.width,
|
screenshot.size.width,
|
||||||
screenshot.size.height,
|
screenshot.size.height,
|
||||||
screenshot.bytes,
|
screenshot.rgba,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
@ -105,7 +105,7 @@ impl Example {
|
||||||
image::Handle::from_rgba(
|
image::Handle::from_rgba(
|
||||||
screenshot.size.width,
|
screenshot.size.width,
|
||||||
screenshot.size.height,
|
screenshot.size.height,
|
||||||
screenshot.bytes,
|
screenshot.rgba,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
self.crop_error = None;
|
self.crop_error = None;
|
||||||
|
|
@ -243,7 +243,7 @@ async fn save_to_png(screenshot: Screenshot) -> Result<String, PngError> {
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
img::save_buffer(
|
img::save_buffer(
|
||||||
&path,
|
&path,
|
||||||
&screenshot.bytes,
|
&screenshot.rgba,
|
||||||
screenshot.size.width,
|
screenshot.size.width,
|
||||||
screenshot.size.height,
|
screenshot.size.height,
|
||||||
ColorType::Rgba8,
|
ColorType::Rgba8,
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,8 @@ pub fn main() -> iced::Result {
|
||||||
application().run()
|
application().run()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn application() -> Application<impl Program<Message = Message>> {
|
fn application() -> Application<impl Program<Message = Message, Theme = Theme>>
|
||||||
|
{
|
||||||
iced::application(Todos::new, Todos::update, Todos::view)
|
iced::application(Todos::new, Todos::update, Todos::view)
|
||||||
.subscription(Todos::subscription)
|
.subscription(Todos::subscription)
|
||||||
.title(Todos::title)
|
.title(Todos::title)
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
#[cfg(feature = "image")]
|
#[cfg(feature = "image")]
|
||||||
pub use ::image as image_rs;
|
pub use ::image as image_rs;
|
||||||
|
|
||||||
use crate::core::Rectangle;
|
|
||||||
use crate::core::image;
|
use crate::core::image;
|
||||||
use crate::core::svg;
|
use crate::core::svg;
|
||||||
|
use crate::core::{Bytes, Rectangle};
|
||||||
|
|
||||||
/// A raster or vector image.
|
/// A raster or vector image.
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
|
@ -39,7 +39,7 @@ impl Image {
|
||||||
|
|
||||||
/// An image buffer.
|
/// An image buffer.
|
||||||
#[cfg(feature = "image")]
|
#[cfg(feature = "image")]
|
||||||
pub type Buffer = ::image::ImageBuffer<::image::Rgba<u8>, image::Bytes>;
|
pub type Buffer = ::image::ImageBuffer<::image::Rgba<u8>, Bytes>;
|
||||||
|
|
||||||
#[cfg(feature = "image")]
|
#[cfg(feature = "image")]
|
||||||
/// Tries to load an image by its [`Handle`].
|
/// Tries to load an image by its [`Handle`].
|
||||||
|
|
@ -127,11 +127,7 @@ pub fn load(handle: &image::Handle) -> Result<Buffer, image::Error> {
|
||||||
|
|
||||||
let rgba = operation.perform(image).into_rgba8();
|
let rgba = operation.perform(image).into_rgba8();
|
||||||
|
|
||||||
(
|
(rgba.width(), rgba.height(), Bytes::from(rgba.into_raw()))
|
||||||
rgba.width(),
|
|
||||||
rgba.height(),
|
|
||||||
image::Bytes::from(rgba.into_raw()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
image::Handle::Bytes(_, bytes) => {
|
image::Handle::Bytes(_, bytes) => {
|
||||||
let image = ::image::load_from_memory(bytes).map_err(to_error)?;
|
let image = ::image::load_from_memory(bytes).map_err(to_error)?;
|
||||||
|
|
@ -143,11 +139,7 @@ pub fn load(handle: &image::Handle) -> Result<Buffer, image::Error> {
|
||||||
|
|
||||||
let rgba = operation.perform(image).into_rgba8();
|
let rgba = operation.perform(image).into_rgba8();
|
||||||
|
|
||||||
(
|
(rgba.width(), rgba.height(), Bytes::from(rgba.into_raw()))
|
||||||
rgba.width(),
|
|
||||||
rgba.height(),
|
|
||||||
image::Bytes::from(rgba.into_raw()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
image::Handle::Rgba {
|
image::Handle::Rgba {
|
||||||
width,
|
width,
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@
|
||||||
use crate::core;
|
use crate::core;
|
||||||
use crate::core::mouse;
|
use crate::core::mouse;
|
||||||
use crate::core::renderer;
|
use crate::core::renderer;
|
||||||
|
use crate::core::time::Instant;
|
||||||
use crate::core::widget;
|
use crate::core::widget;
|
||||||
use crate::core::{Element, Point, Size};
|
use crate::core::window;
|
||||||
|
use crate::core::{Bytes, Element, Point, Size};
|
||||||
use crate::instruction;
|
use crate::instruction;
|
||||||
use crate::program;
|
use crate::program;
|
||||||
use crate::program::Program;
|
use crate::program::Program;
|
||||||
|
|
@ -15,7 +17,6 @@ use crate::runtime::futures::subscription;
|
||||||
use crate::runtime::futures::{Executor, Runtime};
|
use crate::runtime::futures::{Executor, Runtime};
|
||||||
use crate::runtime::task;
|
use crate::runtime::task;
|
||||||
use crate::runtime::user_interface;
|
use crate::runtime::user_interface;
|
||||||
use crate::runtime::window;
|
|
||||||
use crate::runtime::{Task, UserInterface};
|
use crate::runtime::{Task, UserInterface};
|
||||||
use crate::{Instruction, Selector};
|
use crate::{Instruction, Selector};
|
||||||
|
|
||||||
|
|
@ -209,50 +210,55 @@ impl<P: Program + 'static> Emulator<P> {
|
||||||
// TODO
|
// TODO
|
||||||
dbg!(action);
|
dbg!(action);
|
||||||
}
|
}
|
||||||
runtime::Action::Window(action) => match action {
|
runtime::Action::Window(action) => {
|
||||||
window::Action::Open(id, _settings, sender) => {
|
use crate::runtime::window;
|
||||||
self.window = id;
|
|
||||||
|
|
||||||
let _ = sender.send(self.window);
|
match action {
|
||||||
}
|
window::Action::Open(id, _settings, sender) => {
|
||||||
window::Action::GetOldest(sender)
|
self.window = id;
|
||||||
| window::Action::GetLatest(sender) => {
|
|
||||||
let _ = sender.send(Some(self.window));
|
let _ = sender.send(self.window);
|
||||||
}
|
}
|
||||||
window::Action::GetSize(id, sender) => {
|
window::Action::GetOldest(sender)
|
||||||
if id == self.window {
|
| window::Action::GetLatest(sender) => {
|
||||||
let _ = sender.send(self.size);
|
let _ = sender.send(Some(self.window));
|
||||||
|
}
|
||||||
|
window::Action::GetSize(id, sender) => {
|
||||||
|
if id == self.window {
|
||||||
|
let _ = sender.send(self.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window::Action::GetMaximized(id, sender) => {
|
||||||
|
if id == self.window {
|
||||||
|
let _ = sender.send(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window::Action::GetMinimized(id, sender) => {
|
||||||
|
if id == self.window {
|
||||||
|
let _ = sender.send(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window::Action::GetPosition(id, sender) => {
|
||||||
|
if id == self.window {
|
||||||
|
let _ = sender.send(Some(Point::ORIGIN));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window::Action::GetScaleFactor(id, sender) => {
|
||||||
|
if id == self.window {
|
||||||
|
let _ = sender.send(1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window::Action::GetMode(id, sender) => {
|
||||||
|
if id == self.window {
|
||||||
|
let _ =
|
||||||
|
sender.send(core::window::Mode::Windowed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// Ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window::Action::GetMaximized(id, sender) => {
|
}
|
||||||
if id == self.window {
|
|
||||||
let _ = sender.send(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window::Action::GetMinimized(id, sender) => {
|
|
||||||
if id == self.window {
|
|
||||||
let _ = sender.send(None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window::Action::GetPosition(id, sender) => {
|
|
||||||
if id == self.window {
|
|
||||||
let _ = sender.send(Some(Point::ORIGIN));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window::Action::GetScaleFactor(id, sender) => {
|
|
||||||
if id == self.window {
|
|
||||||
let _ = sender.send(1.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window::Action::GetMode(id, sender) => {
|
|
||||||
if id == self.window {
|
|
||||||
let _ = sender.send(core::window::Mode::Windowed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// Ignored
|
|
||||||
}
|
|
||||||
},
|
|
||||||
runtime::Action::System(action) => {
|
runtime::Action::System(action) => {
|
||||||
// TODO
|
// TODO
|
||||||
dbg!(action);
|
dbg!(action);
|
||||||
|
|
@ -435,6 +441,62 @@ impl<P: Program + 'static> Emulator<P> {
|
||||||
program.theme(&self.state, self.window)
|
program.theme(&self.state, self.window)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Takes a [`window::Screenshot`] of the current state of the [`Emulator`].
|
||||||
|
pub fn screenshot(
|
||||||
|
&mut self,
|
||||||
|
program: &P,
|
||||||
|
theme: &P::Theme,
|
||||||
|
scale_factor: f32,
|
||||||
|
) -> window::Screenshot {
|
||||||
|
use core::renderer::Headless;
|
||||||
|
|
||||||
|
let style = program.style(&self.state, theme);
|
||||||
|
|
||||||
|
let mut user_interface = UserInterface::build(
|
||||||
|
program.view(&self.state, self.window),
|
||||||
|
self.size,
|
||||||
|
self.cache.take().unwrap(),
|
||||||
|
&mut self.renderer,
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: Nested redraws!
|
||||||
|
let _ = user_interface.update(
|
||||||
|
&[core::Event::Window(window::Event::RedrawRequested(
|
||||||
|
Instant::now(),
|
||||||
|
))],
|
||||||
|
mouse::Cursor::Unavailable,
|
||||||
|
&mut self.renderer,
|
||||||
|
&mut self.clipboard,
|
||||||
|
&mut Vec::new(),
|
||||||
|
);
|
||||||
|
|
||||||
|
user_interface.draw(
|
||||||
|
&mut self.renderer,
|
||||||
|
theme,
|
||||||
|
&renderer::Style {
|
||||||
|
text_color: style.text_color,
|
||||||
|
},
|
||||||
|
mouse::Cursor::Unavailable,
|
||||||
|
);
|
||||||
|
|
||||||
|
let physical_size = Size::new(
|
||||||
|
(self.size.width * scale_factor).round() as u32,
|
||||||
|
(self.size.height * scale_factor).round() as u32,
|
||||||
|
);
|
||||||
|
|
||||||
|
let rgba = self.renderer.screenshot(
|
||||||
|
physical_size,
|
||||||
|
scale_factor,
|
||||||
|
style.background_color,
|
||||||
|
);
|
||||||
|
|
||||||
|
window::Screenshot {
|
||||||
|
rgba: Bytes::from(rgba),
|
||||||
|
size: physical_size,
|
||||||
|
scale_factor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Turns the [`Emulator`] into its internal state.
|
/// Turns the [`Emulator`] into its internal state.
|
||||||
pub fn into_state(self) -> (P::State, core::window::Id) {
|
pub fn into_state(self) -> (P::State, core::window::Id) {
|
||||||
(self.state, self.window)
|
(self.state, self.window)
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,10 @@ pub use instruction::Instruction;
|
||||||
pub use selector::Selector;
|
pub use selector::Selector;
|
||||||
pub use simulator::{Simulator, simulator};
|
pub use simulator::{Simulator, simulator};
|
||||||
|
|
||||||
|
use crate::core::Size;
|
||||||
|
use crate::core::time::{Duration, Instant};
|
||||||
|
use crate::core::window;
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
/// Runs an [`Ice`] test suite for the given [`Program`](program::Program).
|
/// Runs an [`Ice`] test suite for the given [`Program`](program::Program).
|
||||||
|
|
@ -213,3 +217,50 @@ pub fn run(
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Takes a screenshot of the given [`Program`](program::Program) with the given theme, viewport,
|
||||||
|
/// and scale factor after running it for the given [`Duration`].
|
||||||
|
pub fn screenshot<P: program::Program + 'static>(
|
||||||
|
program: P,
|
||||||
|
theme: &P::Theme,
|
||||||
|
viewport: impl Into<Size>,
|
||||||
|
scale_factor: f32,
|
||||||
|
duration: Duration,
|
||||||
|
) -> window::Screenshot {
|
||||||
|
use crate::runtime::futures::futures::channel::mpsc;
|
||||||
|
|
||||||
|
let (sender, mut receiver) = mpsc::channel(100);
|
||||||
|
|
||||||
|
let mut emulator = Emulator::new(
|
||||||
|
sender,
|
||||||
|
&program,
|
||||||
|
emulator::Mode::Immediate,
|
||||||
|
viewport.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if let Some(event) = receiver.try_next().ok().flatten() {
|
||||||
|
match event {
|
||||||
|
emulator::Event::Action(action) => {
|
||||||
|
emulator.perform(&program, action);
|
||||||
|
}
|
||||||
|
emulator::Event::Failed(_) => {
|
||||||
|
unreachable!(
|
||||||
|
"no instructions should be executed during a screenshot"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
emulator::Event::Ready => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if start.elapsed() >= duration {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::thread::sleep(Duration::from_millis(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
emulator.screenshot(&program, theme, scale_factor)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,7 @@ impl Snapshot {
|
||||||
let mut bytes = vec![0; n];
|
let mut bytes = vec![0; n];
|
||||||
let info = reader.next_frame(&mut bytes)?;
|
let info = reader.next_frame(&mut bytes)?;
|
||||||
|
|
||||||
Ok(self.screenshot.bytes == bytes[..info.buffer_size()])
|
Ok(self.screenshot.rgba == bytes[..info.buffer_size()])
|
||||||
} else {
|
} else {
|
||||||
if let Some(directory) = path.parent() {
|
if let Some(directory) = path.parent() {
|
||||||
fs::create_dir_all(directory)?;
|
fs::create_dir_all(directory)?;
|
||||||
|
|
@ -292,7 +292,7 @@ impl Snapshot {
|
||||||
encoder.set_color(png::ColorType::Rgba);
|
encoder.set_color(png::ColorType::Rgba);
|
||||||
|
|
||||||
let mut writer = encoder.write_header()?;
|
let mut writer = encoder.write_header()?;
|
||||||
writer.write_image_data(&self.screenshot.bytes)?;
|
writer.write_image_data(&self.screenshot.rgba)?;
|
||||||
writer.finish()?;
|
writer.finish()?;
|
||||||
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
|
|
@ -311,7 +311,7 @@ impl Snapshot {
|
||||||
|
|
||||||
let hash = {
|
let hash = {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
hasher.update(&self.screenshot.bytes);
|
hasher.update(&self.screenshot.rgba);
|
||||||
format!("{:x}", hasher.finalize())
|
format!("{:x}", hasher.finalize())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,7 @@ fn load_image<'a>(
|
||||||
|
|
||||||
#[cfg(all(feature = "image", not(target_arch = "wasm32")))]
|
#[cfg(all(feature = "image", not(target_arch = "wasm32")))]
|
||||||
mod worker {
|
mod worker {
|
||||||
|
use crate::core::Bytes;
|
||||||
use crate::core::image;
|
use crate::core::image;
|
||||||
use crate::graphics::Shell;
|
use crate::graphics::Shell;
|
||||||
use crate::image::atlas::{self, Atlas};
|
use crate::image::atlas::{self, Atlas};
|
||||||
|
|
@ -505,7 +506,7 @@ mod worker {
|
||||||
Load(image::Handle),
|
Load(image::Handle),
|
||||||
Upload {
|
Upload {
|
||||||
handle: image::Handle,
|
handle: image::Handle,
|
||||||
rgba: image::Bytes,
|
rgba: Bytes,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
},
|
},
|
||||||
|
|
@ -580,7 +581,7 @@ mod worker {
|
||||||
handle: image::Handle,
|
handle: image::Handle,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
rgba: image::Bytes,
|
rgba: Bytes,
|
||||||
callback: fn(&Shell),
|
callback: fn(&Shell),
|
||||||
) {
|
) {
|
||||||
let mut encoder = self.device.create_command_encoder(
|
let mut encoder = self.device.create_command_encoder(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue