Skip to content

Commit

Permalink
Merge pull request #2424 from iced-rs/feature/image-opacity
Browse files Browse the repository at this point in the history
Introduce dynamic `opacity` support for `Image` and `Svg`
  • Loading branch information
hecrj authored May 3, 2024
2 parents 38cf87c + afb4cb9 commit a94984d
Show file tree
Hide file tree
Showing 18 changed files with 150 additions and 41 deletions.
1 change: 1 addition & 0 deletions core/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,6 @@ pub trait Renderer: crate::Renderer {
filter_method: FilterMethod,
bounds: Rectangle,
rotation: Radians,
opacity: f32,
);
}
2 changes: 2 additions & 0 deletions core/src/renderer/null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ impl image::Renderer for () {
_filter_method: image::FilterMethod,
_bounds: Rectangle,
_rotation: Radians,
_opacity: f32,
) {
}
}
Expand All @@ -188,6 +189,7 @@ impl svg::Renderer for () {
_color: Option<Color>,
_bounds: Rectangle,
_rotation: Radians,
_opacity: f32,
) {
}
}
1 change: 1 addition & 0 deletions core/src/svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,6 @@ pub trait Renderer: crate::Renderer {
color: Option<Color>,
bounds: Rectangle,
rotation: Radians,
opacity: f32,
);
}
61 changes: 36 additions & 25 deletions examples/ferris/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub fn main() -> iced::Result {

struct Image {
width: f32,
opacity: f32,
rotation: Rotation,
content_fit: ContentFit,
spin: bool,
Expand All @@ -26,6 +27,7 @@ struct Image {
#[derive(Debug, Clone, Copy)]
enum Message {
WidthChanged(f32),
OpacityChanged(f32),
RotationStrategyChanged(RotationStrategy),
RotationChanged(Degrees),
ContentFitChanged(ContentFit),
Expand All @@ -39,6 +41,9 @@ impl Image {
Message::WidthChanged(width) => {
self.width = width;
}
Message::OpacityChanged(opacity) => {
self.opacity = opacity;
}
Message::RotationStrategyChanged(strategy) => {
self.rotation = match strategy {
RotationStrategy::Floating => {
Expand Down Expand Up @@ -97,14 +102,15 @@ impl Image {
.width(self.width)
.content_fit(self.content_fit)
.rotation(self.rotation)
.opacity(self.opacity)
)
.explain(Color::WHITE),
"I am Ferris!"
]
.spacing(20)
.align_items(Alignment::Center);

let sizing = row![
let fit = row![
pick_list(
[
ContentFit::Contain,
Expand All @@ -117,19 +123,6 @@ impl Image {
Message::ContentFitChanged
)
.width(Length::Fill),
column![
slider(100.0..=500.0, self.width, Message::WidthChanged),
text(format!("Width: {}px", self.width))
.size(12)
.line_height(1.0)
]
.spacing(2)
.align_items(Alignment::Center)
]
.spacing(10)
.align_items(Alignment::End);

let rotation = row![
pick_list(
[RotationStrategy::Floating, RotationStrategy::Solid],
Some(match self.rotation {
Expand All @@ -139,7 +132,21 @@ impl Image {
Message::RotationStrategyChanged,
)
.width(Length::Fill),
column![
]
.spacing(10)
.align_items(Alignment::End);

let properties = row![
with_value(
slider(100.0..=500.0, self.width, Message::WidthChanged),
format!("Width: {}px", self.width)
),
with_value(
slider(0.0..=1.0, self.opacity, Message::OpacityChanged)
.step(0.01),
format!("Opacity: {:.2}", self.opacity)
),
with_value(
row![
slider(
Degrees::RANGE,
Expand All @@ -153,20 +160,13 @@ impl Image {
]
.spacing(10)
.align_items(Alignment::Center),
text(format!(
"Rotation: {:.0}°",
f32::from(self.rotation.degrees())
))
.size(12)
.line_height(1.0)
]
.spacing(2)
.align_items(Alignment::Center)
format!("Rotation: {:.0}°", f32::from(self.rotation.degrees()))
)
]
.spacing(10)
.align_items(Alignment::End);

container(column![center(i_am_ferris), sizing, rotation].spacing(10))
container(column![fit, center(i_am_ferris), properties].spacing(10))
.padding(10)
.into()
}
Expand All @@ -176,6 +176,7 @@ impl Default for Image {
fn default() -> Self {
Self {
width: 300.0,
opacity: 1.0,
rotation: Rotation::default(),
content_fit: ContentFit::default(),
spin: false,
Expand All @@ -198,3 +199,13 @@ impl std::fmt::Display for RotationStrategy {
})
}
}

fn with_value<'a>(
control: impl Into<Element<'a, Message>>,
value: String,
) -> Element<'a, Message> {
column![control.into(), text(value).size(12).line_height(1.0)]
.spacing(2)
.align_items(Alignment::Center)
.into()
}
10 changes: 8 additions & 2 deletions graphics/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ pub enum Image {
/// The bounds of the image.
bounds: Rectangle,

/// The rotation of the image in radians
/// The rotation of the image.
rotation: Radians,

/// The opacity of the image.
opacity: f32,
},
/// A vector image.
Vector {
Expand All @@ -32,8 +35,11 @@ pub enum Image {
/// The bounds of the image.
bounds: Rectangle,

/// The rotation of the image in radians
/// The rotation of the image.
rotation: Radians,

/// The opacity of the image.
opacity: f32,
},
}

Expand Down
12 changes: 10 additions & 2 deletions renderer/src/fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,18 @@ where
filter_method: image::FilterMethod,
bounds: Rectangle,
rotation: Radians,
opacity: f32,
) {
delegate!(
self,
renderer,
renderer.draw_image(handle, filter_method, bounds, rotation)
renderer.draw_image(
handle,
filter_method,
bounds,
rotation,
opacity
)
);
}
}
Expand All @@ -179,11 +186,12 @@ where
color: Option<Color>,
bounds: Rectangle,
rotation: Radians,
opacity: f32,
) {
delegate!(
self,
renderer,
renderer.draw_svg(handle, color, bounds, rotation)
renderer.draw_svg(handle, color, bounds, rotation, opacity)
);
}
}
Expand Down
4 changes: 4 additions & 0 deletions tiny_skia/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,7 @@ impl Engine {
filter_method,
bounds,
rotation,
opacity,
} => {
let physical_bounds = *bounds * _transformation;

Expand All @@ -574,6 +575,7 @@ impl Engine {
handle,
*filter_method,
*bounds,
*opacity,
_pixels,
transform,
clip_mask,
Expand All @@ -585,6 +587,7 @@ impl Engine {
color,
bounds,
rotation,
opacity,
} => {
let physical_bounds = *bounds * _transformation;

Expand All @@ -608,6 +611,7 @@ impl Engine {
handle,
*color,
physical_bounds,
*opacity,
_pixels,
transform,
clip_mask,
Expand Down
4 changes: 4 additions & 0 deletions tiny_skia/src/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,14 @@ impl Layer {
bounds: Rectangle,
transformation: Transformation,
rotation: Radians,
opacity: f32,
) {
let image = Image::Raster {
handle,
filter_method,
bounds: bounds * transformation,
rotation,
opacity,
};

self.images.push(image);
Expand All @@ -140,12 +142,14 @@ impl Layer {
bounds: Rectangle,
transformation: Transformation,
rotation: Radians,
opacity: f32,
) {
let svg = Image::Vector {
handle,
color,
bounds: bounds * transformation,
rotation,
opacity,
};

self.images.push(svg);
Expand Down
12 changes: 11 additions & 1 deletion tiny_skia/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ impl core::image::Renderer for Renderer {
filter_method: core::image::FilterMethod,
bounds: Rectangle,
rotation: core::Radians,
opacity: f32,
) {
let (layer, transformation) = self.layers.current_mut();
layer.draw_image(
Expand All @@ -386,6 +387,7 @@ impl core::image::Renderer for Renderer {
bounds,
transformation,
rotation,
opacity,
);
}
}
Expand All @@ -405,9 +407,17 @@ impl core::svg::Renderer for Renderer {
color: Option<Color>,
bounds: Rectangle,
rotation: core::Radians,
opacity: f32,
) {
let (layer, transformation) = self.layers.current_mut();
layer.draw_svg(handle, color, bounds, transformation, rotation);
layer.draw_svg(
handle,
color,
bounds,
transformation,
rotation,
opacity,
);
}
}

Expand Down
2 changes: 2 additions & 0 deletions tiny_skia/src/raster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ impl Pipeline {
handle: &raster::Handle,
filter_method: raster::FilterMethod,
bounds: Rectangle,
opacity: f32,
pixels: &mut tiny_skia::PixmapMut<'_>,
transform: tiny_skia::Transform,
clip_mask: Option<&tiny_skia::Mask>,
Expand All @@ -56,6 +57,7 @@ impl Pipeline {
image,
&tiny_skia::PixmapPaint {
quality,
opacity,
..Default::default()
},
transform,
Expand Down
6 changes: 5 additions & 1 deletion tiny_skia/src/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ impl Pipeline {
handle: &Handle,
color: Option<Color>,
bounds: Rectangle,
opacity: f32,
pixels: &mut tiny_skia::PixmapMut<'_>,
transform: Transform,
clip_mask: Option<&tiny_skia::Mask>,
Expand All @@ -47,7 +48,10 @@ impl Pipeline {
bounds.x as i32,
bounds.y as i32,
image,
&tiny_skia::PixmapPaint::default(),
&tiny_skia::PixmapPaint {
opacity,
..tiny_skia::PixmapPaint::default()
},
transform,
clip_mask,
);
Expand Down
Loading

0 comments on commit a94984d

Please sign in to comment.