feat: Initial working prototype
This commit is contained in:
119
ui-iced/src/blur_hash.rs
Normal file
119
ui-iced/src/blur_hash.rs
Normal file
@@ -0,0 +1,119 @@
|
||||
use std::sync::{Arc, LazyLock, atomic::AtomicBool};
|
||||
|
||||
use iced::{Element, advanced::Widget, widget::Image};
|
||||
|
||||
use crate::shared_string::SharedString;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BlurHash {
|
||||
hash: SharedString,
|
||||
handle: Arc<iced::advanced::image::Handle>,
|
||||
width: u32,
|
||||
height: u32,
|
||||
punch: f32,
|
||||
}
|
||||
|
||||
impl BlurHash {
|
||||
pub fn recompute(&mut self) {
|
||||
let pixels = blurhash::decode(&self.hash, self.width, self.height, self.punch)
|
||||
.unwrap_or_else(|_| vec![0; (self.width * self.height * 4) as usize]);
|
||||
let handle = iced::advanced::image::Handle::from_rgba(self.width, self.height, pixels);
|
||||
self.handle = Arc::new(handle);
|
||||
}
|
||||
|
||||
pub fn new(hash: impl AsRef<str>) -> Self {
|
||||
let hash = SharedString::from(hash.as_ref().to_string());
|
||||
let pixels = blurhash::decode(&hash, 32, 32, 1.0).unwrap_or_else(|_| vec![0; 32 * 32 * 4]);
|
||||
let handle = iced::advanced::image::Handle::from_rgba(32, 32, pixels);
|
||||
let handle = Arc::new(handle);
|
||||
BlurHash {
|
||||
hash,
|
||||
handle,
|
||||
width: 32,
|
||||
height: 32,
|
||||
punch: 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn width(mut self, height: u32) -> Self {
|
||||
self.width = height;
|
||||
self.recompute();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn height(mut self, height: u32) -> Self {
|
||||
self.height = height;
|
||||
self.recompute();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn punch(mut self, punch: f32) -> Self {
|
||||
self.punch = punch;
|
||||
self.recompute();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer> for BlurHash
|
||||
where
|
||||
Renderer: iced::advanced::image::Renderer<Handle = iced::advanced::image::Handle>,
|
||||
{
|
||||
fn size(&self) -> iced::Size<iced::Length> {
|
||||
iced::Size {
|
||||
width: iced::Length::Fixed(self.width as f32),
|
||||
height: iced::Length::Fixed(self.height as f32),
|
||||
}
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
_tree: &mut iced::advanced::widget::Tree,
|
||||
renderer: &Renderer,
|
||||
limits: &iced::advanced::layout::Limits,
|
||||
) -> iced::advanced::layout::Node {
|
||||
iced::widget::image::layout(
|
||||
renderer,
|
||||
limits,
|
||||
&self.handle,
|
||||
self.width.into(),
|
||||
self.height.into(),
|
||||
None,
|
||||
iced::ContentFit::default(),
|
||||
iced::Rotation::default(),
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
_state: &iced::advanced::widget::Tree,
|
||||
renderer: &mut Renderer,
|
||||
_theme: &Theme,
|
||||
_style: &iced::advanced::renderer::Style,
|
||||
layout: iced::advanced::Layout<'_>,
|
||||
_cursor: iced::advanced::mouse::Cursor,
|
||||
_viewport: &iced::Rectangle,
|
||||
) {
|
||||
iced::widget::image::draw(
|
||||
renderer,
|
||||
layout,
|
||||
&self.handle,
|
||||
None,
|
||||
iced::border::Radius::default(),
|
||||
iced::ContentFit::default(),
|
||||
iced::widget::image::FilterMethod::default(),
|
||||
iced::Rotation::default(),
|
||||
1.0,
|
||||
1.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme, Renderer> From<BlurHash> for iced::Element<'a, Message, Theme, Renderer>
|
||||
where
|
||||
Renderer: iced::advanced::image::Renderer<Handle = iced::advanced::image::Handle>,
|
||||
{
|
||||
fn from(blur_hash: BlurHash) -> Element<'a, Message, Theme, Renderer> {
|
||||
iced::Element::new(blur_hash)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user