mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 14:21:16 +00:00
Small image handling cleanup
Use a dedicated structure for femtovg based textures
This commit is contained in:
parent
1793ef4d77
commit
ad0d2f04e1
2 changed files with 50 additions and 45 deletions
|
@ -38,6 +38,7 @@ fontdb = { version = "0.5.1", default-features = false }
|
||||||
resvg = { version= "0.13", optional = true, default-features = false }
|
resvg = { version= "0.13", optional = true, default-features = false }
|
||||||
usvg = { version= "0.13", optional = true, default-features = false }
|
usvg = { version= "0.13", optional = true, default-features = false }
|
||||||
tiny-skia = { version= "0.4.2", optional = true, default-features = false }
|
tiny-skia = { version= "0.4.2", optional = true, default-features = false }
|
||||||
|
derive_more = "0.99.5"
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
web_sys = { version = "0.3", package = "web-sys", features=["console", "WebGlContextAttributes"] }
|
web_sys = { version = "0.3", package = "web-sys", features=["console", "WebGlContextAttributes"] }
|
||||||
|
|
|
@ -15,33 +15,48 @@ use sixtyfps_corelib::{graphics::Size, slice::Slice, Property, Resource, SharedS
|
||||||
|
|
||||||
use super::{CanvasRc, GLItemRenderer, GLRendererData};
|
use super::{CanvasRc, GLItemRenderer, GLRendererData};
|
||||||
|
|
||||||
|
struct Texture {
|
||||||
|
id: femtovg::ImageId,
|
||||||
|
canvas: CanvasRc,
|
||||||
|
/// If present, this boolean property indicates whether the image has been uploaded yet or
|
||||||
|
/// if that operation is still pending. If not present, then the image *is* available. This is
|
||||||
|
/// used for remote HTML image loading and the property will be used to correctly track dependencies
|
||||||
|
/// to graphics items that query for the size.
|
||||||
|
upload_pending: Option<core::pin::Pin<Box<Property<bool>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Texture {
|
||||||
|
fn size(&self) -> Option<Size> {
|
||||||
|
if self
|
||||||
|
.upload_pending
|
||||||
|
.as_ref()
|
||||||
|
.map_or(false, |pending_property| pending_property.as_ref().get())
|
||||||
|
{
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
self.canvas
|
||||||
|
.borrow()
|
||||||
|
.image_info(self.id)
|
||||||
|
.map(|info| [info.width() as f32, info.height() as f32].into())
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Texture {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.canvas.borrow_mut().delete_image(self.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(derive_more::From)]
|
||||||
enum ImageData {
|
enum ImageData {
|
||||||
Texture {
|
Texture(Texture),
|
||||||
id: femtovg::ImageId,
|
|
||||||
canvas: CanvasRc,
|
|
||||||
/// If present, this boolean property indicates whether the image has been uploaded yet or
|
|
||||||
/// if that operation is still pending. If not present, then the image *is* available. This is
|
|
||||||
/// used for remote HTML image loading and the property will be used to correctly track dependencies
|
|
||||||
/// to graphics items that query for the size.
|
|
||||||
upload_pending: Option<core::pin::Pin<Box<Property<bool>>>>,
|
|
||||||
},
|
|
||||||
DecodedImage(image::DynamicImage),
|
DecodedImage(image::DynamicImage),
|
||||||
#[cfg(feature = "svg")]
|
#[cfg(feature = "svg")]
|
||||||
SVG(usvg::Tree),
|
SVG(usvg::Tree),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for ImageData {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
match self {
|
|
||||||
ImageData::Texture { id, canvas, .. } => {
|
|
||||||
canvas.borrow_mut().delete_image(*id);
|
|
||||||
}
|
|
||||||
ImageData::DecodedImage(..) => {}
|
|
||||||
ImageData::SVG(..) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct CachedImage(RefCell<ImageData>);
|
pub(crate) struct CachedImage(RefCell<ImageData>);
|
||||||
|
|
||||||
impl CachedImage {
|
impl CachedImage {
|
||||||
|
@ -54,11 +69,14 @@ impl CachedImage {
|
||||||
image_id: femtovg::ImageId,
|
image_id: femtovg::ImageId,
|
||||||
upload_pending_notifier: Option<core::pin::Pin<Box<Property<bool>>>>,
|
upload_pending_notifier: Option<core::pin::Pin<Box<Property<bool>>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self(RefCell::new(ImageData::Texture {
|
Self(RefCell::new(
|
||||||
id: image_id,
|
Texture {
|
||||||
canvas: canvas.clone(),
|
id: image_id,
|
||||||
upload_pending: upload_pending_notifier,
|
canvas: canvas.clone(),
|
||||||
}))
|
upload_pending: upload_pending_notifier,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "svg")]
|
#[cfg(feature = "svg")]
|
||||||
|
@ -216,11 +234,11 @@ impl CachedImage {
|
||||||
}
|
}
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
*img = ImageData::Texture { id: image_id, canvas: canvas.clone(), upload_pending: None }
|
*img = Texture { id: image_id, canvas: canvas.clone(), upload_pending: None }.into()
|
||||||
};
|
};
|
||||||
|
|
||||||
match &img {
|
match &img {
|
||||||
ImageData::Texture { id, .. } => *id,
|
ImageData::Texture(Texture { id, .. }) => *id,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,32 +247,18 @@ impl CachedImage {
|
||||||
use image::GenericImageView;
|
use image::GenericImageView;
|
||||||
|
|
||||||
match &*self.0.borrow() {
|
match &*self.0.borrow() {
|
||||||
ImageData::Texture { id, canvas, upload_pending } => {
|
ImageData::Texture(texture) => texture.size(),
|
||||||
if upload_pending
|
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |pending_property| pending_property.as_ref().get())
|
|
||||||
{
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
canvas
|
|
||||||
.borrow()
|
|
||||||
.image_info(*id)
|
|
||||||
.map(|info| (info.width() as f32, info.height() as f32))
|
|
||||||
.ok()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImageData::DecodedImage(decoded_image) => {
|
ImageData::DecodedImage(decoded_image) => {
|
||||||
let (width, height) = decoded_image.dimensions();
|
let (width, height) = decoded_image.dimensions();
|
||||||
Some((width as f32, height as f32))
|
Some([width as f32, height as f32].into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "svg")]
|
#[cfg(feature = "svg")]
|
||||||
ImageData::SVG(tree) => {
|
ImageData::SVG(tree) => {
|
||||||
let size = tree.svg_node().size.to_screen_size();
|
let size = tree.svg_node().size.to_screen_size();
|
||||||
Some((size.width() as f32, size.height() as f32))
|
Some([size.width() as f32, size.height() as f32].into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map(|(width, height)| euclid::size2(width, height))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue