Skip to content

Commit

Permalink
fix view transition (#662)
Browse files Browse the repository at this point in the history
  • Loading branch information
jrmoulton authored Nov 4, 2024
1 parent 1d3fd5e commit e14eca8
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 75 deletions.
2 changes: 1 addition & 1 deletion examples/view-transition/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ edition = "2021"

[dependencies]
im.workspace = true
floem = { path = "../.." }
floem = { path = "../..", features = ["vello"], default-features = false}
41 changes: 19 additions & 22 deletions examples/view-transition/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
use floem::{
animate::Animation,
peniko::Color,
reactive::{RwSignal, SignalGet, SignalUpdate},
style::Style,
taffy::FlexWrap,
unit::{DurationUnitExt, UnitExt},
views::*,
IntoView,
};
use floem::{prelude::*, style::Style, taffy::FlexWrap, IntoView};
mod music_player;

#[derive(Clone, Copy, PartialEq)]
Expand All @@ -18,20 +9,20 @@ enum ViewSwitcher {
impl ViewSwitcher {
fn toggle(&mut self) {
*self = match self {
ViewSwitcher::One => ViewSwitcher::Two,
ViewSwitcher::Two => ViewSwitcher::One,
Self::One => Self::Two,
Self::Two => Self::One,
};
}

fn view(&self, state: RwSignal<Self>) -> impl IntoView {
fn view(self, state: RwSignal<Self>) -> impl IntoView {
match self {
ViewSwitcher::One => music_player::music_player().into_any(),
ViewSwitcher::Two => view_two(state).into_any(),
Self::One => music_player::music_player().into_any(),
Self::Two => view_two(state).into_any(),
}
.style(|s| s.scale(100.pct()))
.animation(|s| Animation::scale_effect(s).duration(3.seconds()))
.animation(|a| a.scale_effect().keyframe(0, |s| s.style(|s| s.size(0, 0))))
.clip()
.style(|s| s.padding(8))
.style(|s| s.padding(20))
.animation(|a| {
a.view_transition()
.keyframe(0, |f| f.style(|s| s.padding(0)))
Expand All @@ -47,13 +38,18 @@ fn app_view() -> impl IntoView {
let state = RwSignal::new(ViewSwitcher::One);

v_stack((
button("Switch views").action(move || state.update(|which| which.toggle())),
button("Switch views").action(move || state.update(ViewSwitcher::toggle)),
h_stack((
dyn_container(move || state.get(), move |which| which.view(state)),
empty()
.animation(move |a| a.scale_effect().with_duration(|a, d| a.delay(d)))
.animation(move |a| {
a.scale_effect()
.with_duration(|a, d| a.delay(d))
.keyframe(0, |s| s.style(|s| s.size(0, 0)))
})
.style(move |s| {
s.size(100, 100)
.scale(100.pct())
.border_radius(5)
.background(Color::RED)
.apply_if(state.get() == ViewSwitcher::Two, |s| s.hide())
Expand Down Expand Up @@ -88,8 +84,9 @@ fn view_two(view: RwSignal<ViewSwitcher>) -> impl IntoView {

fn box_shadow() -> Style {
Style::new()
.box_shadow_color(Color::BLACK.multiply_alpha(0.7))
.box_shadow_h_offset(3)
.box_shadow_v_offset(3.)
.box_shadow_color(Color::BLACK.multiply_alpha(0.5))
.box_shadow_h_offset(5.)
.box_shadow_v_offset(10.)
// .box_shadow_spread(1)
.box_shadow_blur(1.5)
}
16 changes: 8 additions & 8 deletions examples/view-transition/src/music_player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ enum PlayPause {
impl PlayPause {
fn toggle(&mut self) {
*self = match self {
PlayPause::Play => PlayPause::Pause,
PlayPause::Pause => PlayPause::Play,
Self::Play => Self::Pause,
Self::Pause => Self::Play,
};
}
fn view(&self) -> AnyView {
fn view(self) -> AnyView {
match self {
PlayPause::Play => svg(svg::PLAY).into_any(),
PlayPause::Pause => svg(svg::PAUSE).into_any(),
Self::Play => svg(svg::PLAY).into_any(),
Self::Pause => svg(svg::PAUSE).into_any(),
}
.animation(|a| Animation::scale_effect(a).run_on_remove(false))
}
Expand All @@ -88,14 +88,14 @@ pub fn music_player() -> impl IntoView {
let play_pause_state = RwSignal::new(PlayPause::Play);

let play_pause_button = container(
dyn_container(move || play_pause_state.get(), move |which| which.view()).class(ButtonClass),
dyn_container(move || play_pause_state.get(), PlayPause::view).class(ButtonClass),
)
.on_click_stop(move |_| play_pause_state.update(|which| which.toggle()));
.on_click_stop(move |_| play_pause_state.update(PlayPause::toggle));

let media_buttons = h_stack((
container(svg(svg::BACKWARD)).class(ButtonClass),
play_pause_button,
container(svg(svg::BACKWARD)).class(ButtonClass),
container(svg(svg::FORWARD)).class(ButtonClass),
))
.style(|s| {
s.align_self(Some(floem::taffy::AlignItems::Center))
Expand Down
8 changes: 4 additions & 4 deletions examples/view-transition/src/music_player/svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ pub const PAUSE: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0
<path fill-rule="evenodd" d="M6.75 5.25a.75.75 0 0 1 .75-.75H9a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H7.5a.75.75 0 0 1-.75-.75V5.25Zm7.5 0A.75.75 0 0 1 15 4.5h1.5a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H15a.75.75 0 0 1-.75-.75V5.25Z" clip-rule="evenodd" />
</svg>
"#;
// pub const FORWARD: &str = r#"b<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-6">
// <path d="M5.055 7.06C3.805 6.347 2.25 7.25 2.25 8.69v8.122c0 1.44 1.555 2.343 2.805 1.628L12 14.471v2.34c0 1.44 1.555 2.343 2.805 1.628l7.108-4.061c1.26-.72 1.26-2.536 0-3.256l-7.108-4.061C13.555 6.346 12 7.249 12 8.689v2.34L5.055 7.061Z" />
// </svg>
// "#;
pub const FORWARD: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-6">
<path d="M5.055 7.06C3.805 6.347 2.25 7.25 2.25 8.69v8.122c0 1.44 1.555 2.343 2.805 1.628L12 14.471v2.34c0 1.44 1.555 2.343 2.805 1.628l7.108-4.061c1.26-.72 1.26-2.536 0-3.256l-7.108-4.061C13.555 6.346 12 7.249 12 8.689v2.34L5.055 7.061Z" />
</svg>
"#;
pub const BACKWARD: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-6">
<path d="M9.195 18.44c1.25.714 2.805-.189 2.805-1.629v-2.34l6.945 3.968c1.25.715 2.805-.188 2.805-1.628V8.69c0-1.44-1.555-2.343-2.805-1.628L12 11.029v-2.34c0-1.44-1.555-2.343-2.805-1.628l-7.108 4.061c-1.26.72-1.26 2.536 0 3.256l7.108 4.061Z" />
</svg>
Expand Down
85 changes: 45 additions & 40 deletions vello/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub struct VelloRenderer {
window_scale: f64,
transform: Affine,
capture: bool,
font_cache: HashMap<(ID, usize), vello::peniko::Font>,
font_cache: HashMap<ID, vello::peniko::Font>,
}

impl VelloRenderer {
Expand Down Expand Up @@ -129,29 +129,29 @@ impl VelloRenderer {
self.window_scale = scale;
}

pub fn scale(&self) -> f64 {
pub const fn scale(&self) -> f64 {
self.window_scale
}

pub fn size(&self) -> Size {
pub const fn size(&self) -> Size {
Size::new(self.config.width as f64, self.config.height as f64)
}
}

impl Renderer for VelloRenderer {
fn begin(&mut self, capture: bool) {
if self.capture != capture {
if self.capture == capture {
self.scene.reset();
} else {
self.capture = capture;
if self.alt_scene.is_none() {
self.alt_scene = Some(Scene::new());
}
if let Some(scene) = self.alt_scene.as_mut() {
scene.reset()
scene.reset();
}
self.scene.reset();
mem::swap(&mut self.scene, self.alt_scene.as_mut().unwrap())
} else {
self.scene.reset();
mem::swap(&mut self.scene, self.alt_scene.as_mut().unwrap());
};
self.transform = Affine::IDENTITY;
}
Expand Down Expand Up @@ -203,9 +203,8 @@ impl Renderer for VelloRenderer {
fn fill<'b>(&mut self, path: &impl Shape, brush: impl Into<BrushRef<'b>>, blur_radius: f64) {
let brush: BrushRef<'b> = brush.into();
if blur_radius > 0. {
let color = match brush {
BrushRef::Solid(c) => c,
_ => return,
let BrushRef::Solid(color) = brush else {
return;
};
let rect = path.as_rounded_rect().unwrap_or_default().rect();

Expand All @@ -214,7 +213,7 @@ impl Renderer for VelloRenderer {
rect,
color,
blur_radius,
2.5,
3.,
);
} else {
self.scene.fill(
Expand Down Expand Up @@ -254,7 +253,7 @@ impl Renderer for VelloRenderer {
if let Some(run) = current_run.take() {
self.draw_glyph_run(
run,
transform.pre_translate((0., line.line_y as f64).into()),
transform.pre_translate((0., line.line_y.into()).into()),
);
}
current_run = Some(GlyphRun {
Expand All @@ -274,7 +273,7 @@ impl Renderer for VelloRenderer {
if let Some(run) = current_run.take() {
self.draw_glyph_run(
run,
transform.pre_translate((0., line.line_y as f64).into()),
transform.pre_translate((0., line.line_y.into()).into()),
);
}
}
Expand Down Expand Up @@ -310,26 +309,27 @@ impl Renderer for VelloRenderer {

let svg_size = svg.tree.size();

let scale_x = rect_width / svg_size.width() as f64;
let scale_y = rect_height / svg_size.height() as f64;
let scale_x = rect_width / f64::from(svg_size.width());
let scale_y = rect_height / f64::from(svg_size.height());

let translate_x = rect.min_x();
let translate_y = rect.min_y();

let new = if let Some(brush) = brush {
let brush = brush.into();
alpha_mask_scene(
rect.size(),
|scene| {
scene.append(&vello_svg::render_tree(svg.tree), None);
},
move |scene| {
scene.fill(Fill::NonZero, Affine::IDENTITY, brush, None, &rect);
},
)
} else {
vello_svg::render_tree(svg.tree)
};
let new = brush.map_or_else(
|| vello_svg::render_tree(svg.tree),
|brush| {
let brush = brush.into();
alpha_mask_scene(
rect.size(),
|scene| {
scene.append(&vello_svg::render_tree(svg.tree), None);
},
move |scene| {
scene.fill(Fill::NonZero, Affine::IDENTITY, brush, None, &rect);
},
)
},
);

// Apply transformations to fit the SVG within the provided rectangle
self.scene.append(
Expand Down Expand Up @@ -446,7 +446,7 @@ impl VelloRenderer {
let bytes_per_pixel = 4;
let buffer = self.device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: (width as u64 * height as u64 * bytes_per_pixel),
size: (u64::from(width * height) * bytes_per_pixel),
usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
Expand Down Expand Up @@ -480,7 +480,10 @@ impl VelloRenderer {
if let Ok(r) = rx.try_recv() {
break r.ok()?;
}
if let wgpu::MaintainResult::Ok = self.device.poll(wgpu::MaintainBase::Wait) {
if matches!(
self.device.poll(wgpu::MaintainBase::Wait),
wgpu::MaintainResult::Ok
) {
rx.recv().ok()?.ok()?;
break;
}
Expand Down Expand Up @@ -563,21 +566,23 @@ struct GlyphRun<'a> {
}

impl VelloRenderer {
fn get_font(&mut self, font_id: ID, metadata: usize) -> vello::peniko::Font {
let cache_key = (font_id, metadata);
self.font_cache.get(&cache_key).cloned().unwrap_or_else(|| {
let font = FONT_SYSTEM.lock().get_font(font_id).unwrap();
fn get_font(&mut self, font_id: ID) -> vello::peniko::Font {
self.font_cache.get(&font_id).cloned().unwrap_or_else(|| {
let mut font_system = FONT_SYSTEM.lock();
let font = font_system.get_font(font_id).unwrap();
let face = font_system.db().face(font_id).unwrap();
let font_data = font.data();
let font_index = 0; // For now, we're not using metadata for font index
let font_index = face.index;
drop(font_system);
let font =
vello::peniko::Font::new(Blob::new(Arc::new(font_data.to_vec())), font_index);
self.font_cache.insert(cache_key, font.clone());
self.font_cache.insert(font_id, font.clone());
font
})
}

fn draw_glyph_run(&mut self, run: GlyphRun, transform: Affine) {
let font = self.get_font(run.font_id, run.metadata);
let font = self.get_font(run.font_id);
self.scene
.draw_glyphs(&font)
.font_size(run.font_size)
Expand All @@ -587,7 +592,7 @@ impl VelloRenderer {
.draw(
Fill::NonZero,
run.glyphs.into_iter().map(|glyph| vello::Glyph {
id: glyph.glyph_id as u32,
id: glyph.glyph_id.into(),
x: glyph.x,
y: glyph.y,
}),
Expand Down

0 comments on commit e14eca8

Please sign in to comment.