Introduce Image struct in core::image
This commit is contained in:
parent
974ae6d1e7
commit
92bd3ecd6b
19 changed files with 184 additions and 334 deletions
|
|
@ -7,6 +7,73 @@ use rustc_hash::FxHasher;
|
|||
use std::hash::{Hash, Hasher};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// A raster image that can be drawn.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Image<H = Handle> {
|
||||
/// The handle of the image.
|
||||
pub handle: H,
|
||||
|
||||
/// The filter method of the image.
|
||||
pub filter_method: FilterMethod,
|
||||
|
||||
/// The rotation to be applied to the image, from its center.
|
||||
pub rotation: Radians,
|
||||
|
||||
/// The opacity of the image.
|
||||
///
|
||||
/// 0 means transparent. 1 means opaque.
|
||||
pub opacity: f32,
|
||||
|
||||
/// If set to `true`, the image will be snapped to the pixel grid.
|
||||
///
|
||||
/// This can avoid graphical glitches, specially when using a
|
||||
/// [`FilterMethod::Nearest`].
|
||||
pub snap: bool,
|
||||
}
|
||||
|
||||
impl Image<Handle> {
|
||||
/// Creates a new [`Image`] with the given handle.
|
||||
pub fn new(handle: impl Into<Handle>) -> Self {
|
||||
Self {
|
||||
handle: handle.into(),
|
||||
filter_method: FilterMethod::default(),
|
||||
rotation: Radians(0.0),
|
||||
opacity: 1.0,
|
||||
snap: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the filter method of the [`Image`].
|
||||
pub fn filter_method(mut self, filter_method: FilterMethod) -> Self {
|
||||
self.filter_method = filter_method;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the rotation of the [`Image`].
|
||||
pub fn rotation(mut self, rotation: impl Into<Radians>) -> Self {
|
||||
self.rotation = rotation.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the opacity of the [`Image`].
|
||||
pub fn opacity(mut self, opacity: impl Into<f32>) -> Self {
|
||||
self.opacity = opacity.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets whether the [`Image`] should be snapped to the pixel grid.
|
||||
pub fn snap(mut self, snap: bool) -> Self {
|
||||
self.snap = snap;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Handle> for Image {
|
||||
fn from(handle: &Handle) -> Self {
|
||||
Image::new(handle.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// A handle of some image data.
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum Handle {
|
||||
|
|
@ -172,14 +239,6 @@ pub trait Renderer: crate::Renderer {
|
|||
/// Returns the dimensions of an image for the given [`Handle`].
|
||||
fn measure_image(&self, handle: &Self::Handle) -> Size<u32>;
|
||||
|
||||
/// Draws an image with the given [`Handle`] and inside the provided
|
||||
/// `bounds`.
|
||||
fn draw_image(
|
||||
&mut self,
|
||||
handle: Self::Handle,
|
||||
filter_method: FilterMethod,
|
||||
bounds: Rectangle,
|
||||
rotation: Radians,
|
||||
opacity: f32,
|
||||
);
|
||||
/// Draws an [`Image`] inside the provided `bounds`.
|
||||
fn draw_image(&mut self, image: Image<Self::Handle>, bounds: Rectangle);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ pub use element::Element;
|
|||
pub use event::Event;
|
||||
pub use font::Font;
|
||||
pub use gradient::Gradient;
|
||||
pub use image::Image;
|
||||
pub use layout::Layout;
|
||||
pub use length::Length;
|
||||
pub use overlay::Overlay;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::alignment;
|
||||
use crate::image;
|
||||
use crate::image::{self, Image};
|
||||
use crate::renderer::{self, Renderer};
|
||||
use crate::svg;
|
||||
use crate::text::{self, Text};
|
||||
|
|
@ -178,20 +178,14 @@ impl text::Editor for () {
|
|||
}
|
||||
|
||||
impl image::Renderer for () {
|
||||
type Handle = ();
|
||||
type Handle = image::Handle;
|
||||
|
||||
fn measure_image(&self, _handle: &Self::Handle) -> Size<u32> {
|
||||
Size::default()
|
||||
}
|
||||
|
||||
fn draw_image(
|
||||
&mut self,
|
||||
_handle: Self::Handle,
|
||||
_filter_method: image::FilterMethod,
|
||||
_bounds: Rectangle,
|
||||
_rotation: Radians,
|
||||
_opacity: f32,
|
||||
) {
|
||||
fn draw_image(&mut self, _image: Image, _bounds: Rectangle) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,11 +160,8 @@ impl<Message> canvas::Program<Message> for State {
|
|||
frame.translate(Vector::new(center.x, center.y));
|
||||
|
||||
frame.draw_image(
|
||||
&self.sun,
|
||||
Rectangle::with_radius(Self::SUN_RADIUS),
|
||||
image::FilterMethod::Linear,
|
||||
0,
|
||||
1.0,
|
||||
&self.sun,
|
||||
);
|
||||
|
||||
let orbit = Path::circle(Point::ORIGIN, Self::ORBIT_RADIUS);
|
||||
|
|
@ -189,22 +186,16 @@ impl<Message> canvas::Program<Message> for State {
|
|||
frame.translate(Vector::new(Self::ORBIT_RADIUS, 0.0));
|
||||
|
||||
frame.draw_image(
|
||||
&self.earth,
|
||||
Rectangle::with_radius(Self::EARTH_RADIUS),
|
||||
image::FilterMethod::Linear,
|
||||
rotation * 20.0,
|
||||
1.0,
|
||||
canvas::Image::new(&self.earth).rotation(rotation * 20.0),
|
||||
);
|
||||
|
||||
frame.rotate(rotation * 10.0);
|
||||
frame.translate(Vector::new(0.0, Self::MOON_DISTANCE));
|
||||
|
||||
frame.draw_image(
|
||||
&self.moon,
|
||||
Rectangle::with_radius(Self::MOON_RADIUS),
|
||||
image::FilterMethod::Linear,
|
||||
0,
|
||||
1.0,
|
||||
&self.moon,
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ pub use stroke::{LineCap, LineDash, LineJoin, Stroke};
|
|||
pub use style::Style;
|
||||
pub use text::Text;
|
||||
|
||||
pub use crate::core::Image;
|
||||
pub use crate::gradient::{self, Gradient};
|
||||
|
||||
use crate::cache::Cached;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
//! Draw and generate geometry.
|
||||
use crate::core::image;
|
||||
use crate::core::svg;
|
||||
use crate::core::{Color, Point, Radians, Rectangle, Size, Vector};
|
||||
use crate::geometry::{self, Fill, Path, Stroke, Text};
|
||||
use crate::geometry::{self, Fill, Image, Path, Stroke, Text};
|
||||
|
||||
/// The region of a surface that can be used to draw geometry.
|
||||
#[allow(missing_debug_implementations)]
|
||||
|
|
@ -79,21 +78,8 @@ where
|
|||
|
||||
/// Draws the given image on the [`Frame`] inside the given bounds.
|
||||
#[cfg(feature = "image")]
|
||||
pub fn draw_image(
|
||||
&mut self,
|
||||
handle: &image::Handle,
|
||||
bounds: Rectangle,
|
||||
filter_method: image::FilterMethod,
|
||||
rotation: impl Into<Radians>,
|
||||
opacity: f32,
|
||||
) {
|
||||
self.raw.draw_image(
|
||||
handle,
|
||||
bounds,
|
||||
filter_method,
|
||||
rotation.into(),
|
||||
opacity,
|
||||
);
|
||||
pub fn draw_image(&mut self, bounds: Rectangle, image: impl Into<Image>) {
|
||||
self.raw.draw_image(bounds, image);
|
||||
}
|
||||
|
||||
/// Stores the current transform of the [`Frame`] and executes the given
|
||||
|
|
@ -219,14 +205,7 @@ pub trait Backend: Sized {
|
|||
fill: impl Into<Fill>,
|
||||
);
|
||||
|
||||
fn draw_image(
|
||||
&mut self,
|
||||
handle: &image::Handle,
|
||||
bounds: Rectangle,
|
||||
filter_method: image::FilterMethod,
|
||||
rotation: Radians,
|
||||
opacity: f32,
|
||||
);
|
||||
fn draw_image(&mut self, bounds: Rectangle, image: impl Into<Image>);
|
||||
|
||||
fn draw_svg(
|
||||
&mut self,
|
||||
|
|
@ -285,15 +264,7 @@ impl Backend for () {
|
|||
|
||||
fn into_geometry(self) -> Self::Geometry {}
|
||||
|
||||
fn draw_image(
|
||||
&mut self,
|
||||
_handle: &image::Handle,
|
||||
_bounds: Rectangle,
|
||||
_filter_method: image::FilterMethod,
|
||||
_rotation: Radians,
|
||||
_opacity: f32,
|
||||
) {
|
||||
}
|
||||
fn draw_image(&mut self, _bounds: Rectangle, _image: impl Into<Image>) {}
|
||||
|
||||
fn draw_svg(
|
||||
&mut self,
|
||||
|
|
|
|||
|
|
@ -8,28 +8,8 @@ use crate::core::{image, svg, Color, Radians, Rectangle};
|
|||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Image {
|
||||
/// A raster image.
|
||||
Raster {
|
||||
/// The handle of a raster image.
|
||||
handle: image::Handle,
|
||||
Raster(image::Image, Rectangle),
|
||||
|
||||
/// The filter method of a raster image.
|
||||
filter_method: image::FilterMethod,
|
||||
|
||||
/// The bounds of the image.
|
||||
bounds: Rectangle,
|
||||
|
||||
/// The rotation of the image.
|
||||
rotation: Radians,
|
||||
|
||||
/// The opacity of the image.
|
||||
opacity: f32,
|
||||
|
||||
/// If set to `true`, the image will be snapped to the pixel grid.
|
||||
///
|
||||
/// This can avoid graphical glitches, specially when using a
|
||||
/// [`image::FilterMethod::Nearest`].
|
||||
snap: bool,
|
||||
},
|
||||
/// A vector image.
|
||||
Vector {
|
||||
/// The handle of a vector image.
|
||||
|
|
@ -53,10 +33,8 @@ impl Image {
|
|||
/// Returns the bounds of the [`Image`].
|
||||
pub fn bounds(&self) -> Rectangle {
|
||||
match self {
|
||||
Image::Raster {
|
||||
bounds, rotation, ..
|
||||
}
|
||||
| Image::Vector {
|
||||
Image::Raster(image, bounds) => bounds.rotate(image.rotation),
|
||||
Image::Vector {
|
||||
bounds, rotation, ..
|
||||
} => bounds.rotate(*rotation),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ use crate::core::image;
|
|||
use crate::core::renderer;
|
||||
use crate::core::svg;
|
||||
use crate::core::{
|
||||
self, Background, Color, Point, Radians, Rectangle, Size, Transformation,
|
||||
self, Background, Color, Image, Point, Radians, Rectangle, Size,
|
||||
Transformation,
|
||||
};
|
||||
use crate::graphics;
|
||||
use crate::graphics::compositor;
|
||||
|
|
@ -149,25 +150,8 @@ where
|
|||
delegate!(self, renderer, renderer.measure_image(handle))
|
||||
}
|
||||
|
||||
fn draw_image(
|
||||
&mut self,
|
||||
handle: Self::Handle,
|
||||
filter_method: image::FilterMethod,
|
||||
bounds: Rectangle,
|
||||
rotation: Radians,
|
||||
opacity: f32,
|
||||
) {
|
||||
delegate!(
|
||||
self,
|
||||
renderer,
|
||||
renderer.draw_image(
|
||||
handle,
|
||||
filter_method,
|
||||
bounds,
|
||||
rotation,
|
||||
opacity
|
||||
)
|
||||
);
|
||||
fn draw_image(&mut self, image: Image<A::Handle>, bounds: Rectangle) {
|
||||
delegate!(self, renderer, renderer.draw_image(image, bounds));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -441,11 +425,10 @@ where
|
|||
#[cfg(feature = "geometry")]
|
||||
mod geometry {
|
||||
use super::Renderer;
|
||||
use crate::core::image;
|
||||
use crate::core::svg;
|
||||
use crate::core::{Color, Point, Radians, Rectangle, Size, Vector};
|
||||
use crate::graphics::cache::{self, Cached};
|
||||
use crate::graphics::geometry::{self, Fill, Path, Stroke, Text};
|
||||
use crate::graphics::geometry::{self, Fill, Image, Path, Stroke, Text};
|
||||
|
||||
impl<A, B> geometry::Renderer for Renderer<A, B>
|
||||
where
|
||||
|
|
@ -574,25 +557,8 @@ mod geometry {
|
|||
delegate!(self, frame, frame.fill_text(text));
|
||||
}
|
||||
|
||||
fn draw_image(
|
||||
&mut self,
|
||||
handle: &image::Handle,
|
||||
bounds: Rectangle,
|
||||
filter_method: image::FilterMethod,
|
||||
rotation: Radians,
|
||||
opacity: f32,
|
||||
) {
|
||||
delegate!(
|
||||
self,
|
||||
frame,
|
||||
frame.draw_image(
|
||||
handle,
|
||||
bounds,
|
||||
filter_method,
|
||||
rotation,
|
||||
opacity
|
||||
)
|
||||
);
|
||||
fn draw_image(&mut self, bounds: Rectangle, image: impl Into<Image>) {
|
||||
delegate!(self, frame, frame.draw_image(bounds, image));
|
||||
}
|
||||
|
||||
fn draw_svg(
|
||||
|
|
|
|||
|
|
@ -550,14 +550,7 @@ impl Engine {
|
|||
) {
|
||||
match image {
|
||||
#[cfg(feature = "image")]
|
||||
Image::Raster {
|
||||
handle,
|
||||
filter_method,
|
||||
bounds,
|
||||
rotation,
|
||||
opacity,
|
||||
snap: _,
|
||||
} => {
|
||||
Image::Raster(raster, bounds) => {
|
||||
let physical_bounds = *bounds * _transformation;
|
||||
|
||||
if !_clip_bounds.intersects(&physical_bounds) {
|
||||
|
|
@ -568,7 +561,7 @@ impl Engine {
|
|||
.then_some(_clip_mask as &_);
|
||||
|
||||
let center = physical_bounds.center();
|
||||
let radians = f32::from(*rotation);
|
||||
let radians = f32::from(raster.rotation);
|
||||
|
||||
let transform = into_transform(_transformation).post_rotate_at(
|
||||
radians.to_degrees(),
|
||||
|
|
@ -577,10 +570,10 @@ impl Engine {
|
|||
);
|
||||
|
||||
self.raster_pipeline.draw(
|
||||
handle,
|
||||
*filter_method,
|
||||
&raster.handle,
|
||||
raster.filter_method,
|
||||
*bounds,
|
||||
*opacity,
|
||||
raster.opacity,
|
||||
_pixels,
|
||||
transform,
|
||||
clip_mask,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
use crate::core::image;
|
||||
use crate::core::svg;
|
||||
use crate::core::text::LineHeight;
|
||||
use crate::core::{Color, Pixels, Point, Radians, Rectangle, Size, Vector};
|
||||
use crate::graphics::cache::{self, Cached};
|
||||
use crate::graphics::geometry::fill::{self, Fill};
|
||||
use crate::graphics::geometry::stroke::{self, Stroke};
|
||||
use crate::graphics::geometry::{self, Path, Style};
|
||||
use crate::graphics::{Gradient, Image, Text};
|
||||
use crate::graphics::geometry::{self, Image, Path, Style};
|
||||
use crate::graphics::{self, Gradient, Text};
|
||||
use crate::Primitive;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
|
@ -15,7 +14,7 @@ use std::rc::Rc;
|
|||
pub enum Geometry {
|
||||
Live {
|
||||
text: Vec<Text>,
|
||||
images: Vec<Image>,
|
||||
images: Vec<graphics::Image>,
|
||||
primitives: Vec<Primitive>,
|
||||
clip_bounds: Rectangle,
|
||||
},
|
||||
|
|
@ -25,7 +24,7 @@ pub enum Geometry {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Cache {
|
||||
pub text: Rc<[Text]>,
|
||||
pub images: Rc<[Image]>,
|
||||
pub images: Rc<[graphics::Image]>,
|
||||
pub primitives: Rc<[Primitive]>,
|
||||
pub clip_bounds: Rectangle,
|
||||
}
|
||||
|
|
@ -61,7 +60,7 @@ pub struct Frame {
|
|||
transform: tiny_skia::Transform,
|
||||
stack: Vec<tiny_skia::Transform>,
|
||||
primitives: Vec<Primitive>,
|
||||
images: Vec<Image>,
|
||||
images: Vec<graphics::Image>,
|
||||
text: Vec<Text>,
|
||||
}
|
||||
|
||||
|
|
@ -283,25 +282,15 @@ impl geometry::frame::Backend for Frame {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw_image(
|
||||
&mut self,
|
||||
handle: &image::Handle,
|
||||
bounds: Rectangle,
|
||||
filter_method: image::FilterMethod,
|
||||
rotation: Radians,
|
||||
opacity: f32,
|
||||
) {
|
||||
fn draw_image(&mut self, bounds: Rectangle, image: impl Into<Image>) {
|
||||
let mut image = image.into();
|
||||
|
||||
let (bounds, external_rotation) =
|
||||
transform_rectangle(bounds, self.transform);
|
||||
|
||||
self.images.push(Image::Raster {
|
||||
handle: handle.clone(),
|
||||
filter_method,
|
||||
bounds,
|
||||
rotation: rotation + external_rotation,
|
||||
opacity,
|
||||
snap: false,
|
||||
});
|
||||
image.rotation += external_rotation;
|
||||
|
||||
self.images.push(graphics::Image::Raster(image, bounds));
|
||||
}
|
||||
|
||||
fn draw_svg(
|
||||
|
|
@ -315,7 +304,7 @@ impl geometry::frame::Backend for Frame {
|
|||
let (bounds, external_rotation) =
|
||||
transform_rectangle(bounds, self.transform);
|
||||
|
||||
self.images.push(Image::Vector {
|
||||
self.images.push(graphics::Image::Vector {
|
||||
handle: handle.clone(),
|
||||
bounds,
|
||||
color,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
use crate::core::renderer::Quad;
|
||||
use crate::core::svg;
|
||||
use crate::core::{
|
||||
image, renderer::Quad, svg, Background, Color, Point, Radians, Rectangle,
|
||||
Transformation,
|
||||
Background, Color, Image, Point, Radians, Rectangle, Transformation,
|
||||
};
|
||||
use crate::graphics;
|
||||
use crate::graphics::damage;
|
||||
use crate::graphics::layer;
|
||||
use crate::graphics::text::{Editor, Paragraph, Text};
|
||||
use crate::graphics::{self, Image};
|
||||
use crate::Primitive;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
|
@ -18,7 +19,7 @@ pub struct Layer {
|
|||
pub quads: Vec<(Quad, Background)>,
|
||||
pub primitives: Vec<Item<Primitive>>,
|
||||
pub text: Vec<Item<Text>>,
|
||||
pub images: Vec<Image>,
|
||||
pub images: Vec<graphics::Image>,
|
||||
}
|
||||
|
||||
impl Layer {
|
||||
|
|
@ -117,28 +118,14 @@ impl Layer {
|
|||
|
||||
pub fn draw_image(
|
||||
&mut self,
|
||||
image: &Image,
|
||||
image: graphics::Image,
|
||||
transformation: Transformation,
|
||||
) {
|
||||
match image {
|
||||
Image::Raster {
|
||||
handle,
|
||||
filter_method,
|
||||
bounds,
|
||||
rotation,
|
||||
opacity,
|
||||
snap: _,
|
||||
} => {
|
||||
self.draw_raster(
|
||||
handle.clone(),
|
||||
*filter_method,
|
||||
*bounds,
|
||||
transformation,
|
||||
*rotation,
|
||||
*opacity,
|
||||
);
|
||||
graphics::Image::Raster(raster, bounds) => {
|
||||
self.draw_raster(raster.clone(), bounds, transformation);
|
||||
}
|
||||
Image::Vector {
|
||||
graphics::Image::Vector {
|
||||
handle,
|
||||
color,
|
||||
bounds,
|
||||
|
|
@ -147,11 +134,11 @@ impl Layer {
|
|||
} => {
|
||||
self.draw_svg(
|
||||
handle.clone(),
|
||||
*color,
|
||||
*bounds,
|
||||
color,
|
||||
bounds,
|
||||
transformation,
|
||||
*rotation,
|
||||
*opacity,
|
||||
rotation,
|
||||
opacity,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -159,21 +146,11 @@ impl Layer {
|
|||
|
||||
pub fn draw_raster(
|
||||
&mut self,
|
||||
handle: image::Handle,
|
||||
filter_method: image::FilterMethod,
|
||||
image: Image,
|
||||
bounds: Rectangle,
|
||||
transformation: Transformation,
|
||||
rotation: Radians,
|
||||
opacity: f32,
|
||||
) {
|
||||
let image = Image::Raster {
|
||||
handle,
|
||||
filter_method,
|
||||
bounds: bounds * transformation,
|
||||
rotation,
|
||||
opacity,
|
||||
snap: false,
|
||||
};
|
||||
let image = graphics::Image::Raster(image, bounds * transformation);
|
||||
|
||||
self.images.push(image);
|
||||
}
|
||||
|
|
@ -187,7 +164,7 @@ impl Layer {
|
|||
rotation: Radians,
|
||||
opacity: f32,
|
||||
) {
|
||||
let svg = Image::Vector {
|
||||
let svg = graphics::Image::Vector {
|
||||
handle,
|
||||
color,
|
||||
bounds: bounds * transformation,
|
||||
|
|
@ -304,7 +281,7 @@ impl Layer {
|
|||
&previous.images,
|
||||
¤t.images,
|
||||
|image| vec![image.bounds().expand(1.0)],
|
||||
Image::eq,
|
||||
graphics::Image::eq,
|
||||
);
|
||||
|
||||
damage.extend(text);
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ impl graphics::geometry::Renderer for Renderer {
|
|||
);
|
||||
|
||||
for image in images {
|
||||
layer.draw_image(&image, transformation);
|
||||
layer.draw_image(image, transformation);
|
||||
}
|
||||
|
||||
layer.draw_text_group(text, clip_bounds, transformation);
|
||||
|
|
@ -354,7 +354,7 @@ impl graphics::geometry::Renderer for Renderer {
|
|||
);
|
||||
|
||||
for image in cache.images.iter() {
|
||||
layer.draw_image(image, transformation);
|
||||
layer.draw_image(image.clone(), transformation);
|
||||
}
|
||||
|
||||
layer.draw_text_cache(
|
||||
|
|
@ -381,23 +381,9 @@ impl core::image::Renderer for Renderer {
|
|||
self.engine.raster_pipeline.dimensions(handle)
|
||||
}
|
||||
|
||||
fn draw_image(
|
||||
&mut self,
|
||||
handle: Self::Handle,
|
||||
filter_method: core::image::FilterMethod,
|
||||
bounds: Rectangle,
|
||||
rotation: core::Radians,
|
||||
opacity: f32,
|
||||
) {
|
||||
fn draw_image(&mut self, image: core::Image, bounds: Rectangle) {
|
||||
let (layer, transformation) = self.layers.current_mut();
|
||||
layer.draw_raster(
|
||||
handle,
|
||||
filter_method,
|
||||
bounds,
|
||||
transformation,
|
||||
rotation,
|
||||
opacity,
|
||||
);
|
||||
layer.draw_raster(image, bounds, transformation);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//! Build and draw geometry.
|
||||
use crate::core::image;
|
||||
use crate::core::svg;
|
||||
use crate::core::text::LineHeight;
|
||||
use crate::core::{
|
||||
|
|
@ -9,11 +8,11 @@ use crate::graphics::cache::{self, Cached};
|
|||
use crate::graphics::color;
|
||||
use crate::graphics::geometry::fill::{self, Fill};
|
||||
use crate::graphics::geometry::{
|
||||
self, LineCap, LineDash, LineJoin, Path, Stroke, Style,
|
||||
self, Image, LineCap, LineDash, LineJoin, Path, Stroke, Style,
|
||||
};
|
||||
use crate::graphics::gradient::{self, Gradient};
|
||||
use crate::graphics::mesh::{self, Mesh};
|
||||
use crate::graphics::{self, Image, Text};
|
||||
use crate::graphics::{self, Text};
|
||||
use crate::text;
|
||||
use crate::triangle;
|
||||
|
||||
|
|
@ -27,7 +26,7 @@ use std::sync::Arc;
|
|||
pub enum Geometry {
|
||||
Live {
|
||||
meshes: Vec<Mesh>,
|
||||
images: Vec<Image>,
|
||||
images: Vec<graphics::Image>,
|
||||
text: Vec<Text>,
|
||||
},
|
||||
Cached(Cache),
|
||||
|
|
@ -36,7 +35,7 @@ pub enum Geometry {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Cache {
|
||||
pub meshes: Option<triangle::Cache>,
|
||||
pub images: Option<Arc<[Image]>>,
|
||||
pub images: Option<Arc<[graphics::Image]>>,
|
||||
pub text: Option<text::Cache>,
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +98,7 @@ pub struct Frame {
|
|||
clip_bounds: Rectangle,
|
||||
buffers: BufferStack,
|
||||
meshes: Vec<Mesh>,
|
||||
images: Vec<Image>,
|
||||
images: Vec<graphics::Image>,
|
||||
text: Vec<Text>,
|
||||
transforms: Transforms,
|
||||
fill_tessellator: tessellation::FillTessellator,
|
||||
|
|
@ -377,25 +376,15 @@ impl geometry::frame::Backend for Frame {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw_image(
|
||||
&mut self,
|
||||
handle: &image::Handle,
|
||||
bounds: Rectangle,
|
||||
filter_method: image::FilterMethod,
|
||||
rotation: Radians,
|
||||
opacity: f32,
|
||||
) {
|
||||
fn draw_image(&mut self, bounds: Rectangle, image: impl Into<Image>) {
|
||||
let mut image = image.into();
|
||||
|
||||
let (bounds, external_rotation) =
|
||||
self.transforms.current.transform_rectangle(bounds);
|
||||
|
||||
self.images.push(Image::Raster {
|
||||
handle: handle.clone(),
|
||||
filter_method,
|
||||
bounds,
|
||||
rotation: rotation + external_rotation,
|
||||
opacity,
|
||||
snap: false,
|
||||
});
|
||||
image.rotation += external_rotation;
|
||||
|
||||
self.images.push(graphics::Image::Raster(image, bounds));
|
||||
}
|
||||
|
||||
fn draw_svg(
|
||||
|
|
@ -409,7 +398,7 @@ impl geometry::frame::Backend for Frame {
|
|||
let (bounds, external_rotation) =
|
||||
self.transforms.current.transform_rectangle(bounds);
|
||||
|
||||
self.images.push(Image::Vector {
|
||||
self.images.push(graphics::Image::Vector {
|
||||
handle: handle.clone(),
|
||||
color,
|
||||
bounds,
|
||||
|
|
|
|||
|
|
@ -220,25 +220,18 @@ impl Pipeline {
|
|||
for image in images {
|
||||
match &image {
|
||||
#[cfg(feature = "image")]
|
||||
Image::Raster {
|
||||
handle,
|
||||
filter_method,
|
||||
bounds,
|
||||
rotation,
|
||||
opacity,
|
||||
snap,
|
||||
} => {
|
||||
Image::Raster(image, bounds) => {
|
||||
if let Some(atlas_entry) =
|
||||
cache.upload_raster(device, encoder, handle)
|
||||
cache.upload_raster(device, encoder, &image.handle)
|
||||
{
|
||||
add_instances(
|
||||
[bounds.x, bounds.y],
|
||||
[bounds.width, bounds.height],
|
||||
f32::from(*rotation),
|
||||
*opacity,
|
||||
*snap,
|
||||
f32::from(image.rotation),
|
||||
image.opacity,
|
||||
image.snap,
|
||||
atlas_entry,
|
||||
match filter_method {
|
||||
match image.filter_method {
|
||||
crate::core::image::FilterMethod::Nearest => {
|
||||
nearest_instances
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::core::{
|
||||
renderer, Background, Color, Point, Radians, Rectangle, Transformation,
|
||||
self, renderer, Background, Color, Point, Radians, Rectangle,
|
||||
Transformation,
|
||||
};
|
||||
use crate::graphics;
|
||||
use crate::graphics::color;
|
||||
|
|
@ -112,29 +113,10 @@ impl Layer {
|
|||
self.pending_text.push(text);
|
||||
}
|
||||
|
||||
pub fn draw_image(
|
||||
&mut self,
|
||||
image: &Image,
|
||||
transformation: Transformation,
|
||||
) {
|
||||
pub fn draw_image(&mut self, image: Image, transformation: Transformation) {
|
||||
match image {
|
||||
Image::Raster {
|
||||
handle,
|
||||
filter_method,
|
||||
bounds,
|
||||
rotation,
|
||||
opacity,
|
||||
snap,
|
||||
} => {
|
||||
self.draw_raster(
|
||||
handle.clone(),
|
||||
*filter_method,
|
||||
*bounds,
|
||||
transformation,
|
||||
*rotation,
|
||||
*opacity,
|
||||
*snap,
|
||||
);
|
||||
Image::Raster(image, bounds) => {
|
||||
self.draw_raster(image, bounds, transformation);
|
||||
}
|
||||
Image::Vector {
|
||||
handle,
|
||||
|
|
@ -145,11 +127,11 @@ impl Layer {
|
|||
} => {
|
||||
self.draw_svg(
|
||||
handle.clone(),
|
||||
*color,
|
||||
*bounds,
|
||||
color,
|
||||
bounds,
|
||||
transformation,
|
||||
*rotation,
|
||||
*opacity,
|
||||
rotation,
|
||||
opacity,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -157,22 +139,11 @@ impl Layer {
|
|||
|
||||
pub fn draw_raster(
|
||||
&mut self,
|
||||
handle: crate::core::image::Handle,
|
||||
filter_method: crate::core::image::FilterMethod,
|
||||
image: core::Image,
|
||||
bounds: Rectangle,
|
||||
transformation: Transformation,
|
||||
rotation: Radians,
|
||||
opacity: f32,
|
||||
snap: bool,
|
||||
) {
|
||||
let image = Image::Raster {
|
||||
handle,
|
||||
filter_method,
|
||||
bounds: bounds * transformation,
|
||||
rotation,
|
||||
opacity,
|
||||
snap,
|
||||
};
|
||||
let image = Image::Raster(image, bounds * transformation);
|
||||
|
||||
self.images.push(image);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -527,24 +527,9 @@ impl core::image::Renderer for Renderer {
|
|||
self.image_cache.borrow_mut().measure_image(handle)
|
||||
}
|
||||
|
||||
fn draw_image(
|
||||
&mut self,
|
||||
handle: Self::Handle,
|
||||
filter_method: core::image::FilterMethod,
|
||||
bounds: Rectangle,
|
||||
rotation: core::Radians,
|
||||
opacity: f32,
|
||||
) {
|
||||
fn draw_image(&mut self, image: core::Image, bounds: Rectangle) {
|
||||
let (layer, transformation) = self.layers.current_mut();
|
||||
layer.draw_raster(
|
||||
handle,
|
||||
filter_method,
|
||||
bounds,
|
||||
transformation,
|
||||
rotation,
|
||||
opacity,
|
||||
true,
|
||||
);
|
||||
layer.draw_raster(image, bounds, transformation);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -602,7 +587,7 @@ impl graphics::geometry::Renderer for Renderer {
|
|||
layer.draw_mesh_group(meshes, transformation);
|
||||
|
||||
for image in images {
|
||||
layer.draw_image(&image, transformation);
|
||||
layer.draw_image(image, transformation);
|
||||
}
|
||||
|
||||
layer.draw_text_group(text, transformation);
|
||||
|
|
@ -613,7 +598,7 @@ impl graphics::geometry::Renderer for Renderer {
|
|||
}
|
||||
|
||||
if let Some(images) = cache.images {
|
||||
for image in images.iter() {
|
||||
for image in images.iter().cloned() {
|
||||
layer.draw_image(image, transformation);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ pub use program::Program;
|
|||
|
||||
pub use crate::graphics::cache::Group;
|
||||
pub use crate::graphics::geometry::{
|
||||
fill, gradient, path, stroke, Fill, Gradient, LineCap, LineDash, LineJoin,
|
||||
Path, Stroke, Style, Text,
|
||||
fill, gradient, path, stroke, Fill, Gradient, Image, LineCap, LineDash,
|
||||
LineJoin, Path, Stroke, Style, Text,
|
||||
};
|
||||
|
||||
use crate::core;
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ use crate::core::mouse;
|
|||
use crate::core::renderer;
|
||||
use crate::core::widget::Tree;
|
||||
use crate::core::{
|
||||
ContentFit, Element, Layout, Length, Point, Rectangle, Rotation, Size,
|
||||
Vector, Widget,
|
||||
self, ContentFit, Element, Layout, Length, Point, Rectangle, Rotation,
|
||||
Size, Vector, Widget,
|
||||
};
|
||||
|
||||
pub use image::{FilterMethod, Handle};
|
||||
|
|
@ -181,11 +181,14 @@ pub fn draw<Renderer, Handle>(
|
|||
|
||||
let render = |renderer: &mut Renderer| {
|
||||
renderer.draw_image(
|
||||
handle.clone(),
|
||||
filter_method,
|
||||
core::Image {
|
||||
handle: handle.clone(),
|
||||
filter_method,
|
||||
rotation: rotation.radians(),
|
||||
opacity,
|
||||
snap: true,
|
||||
},
|
||||
drawing_bounds,
|
||||
rotation.radians(),
|
||||
opacity,
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ use crate::core::mouse;
|
|||
use crate::core::renderer;
|
||||
use crate::core::widget::tree::{self, Tree};
|
||||
use crate::core::{
|
||||
Clipboard, ContentFit, Element, Layout, Length, Pixels, Point, Radians,
|
||||
Rectangle, Shell, Size, Vector, Widget,
|
||||
Clipboard, ContentFit, Element, Image, Layout, Length, Pixels, Point,
|
||||
Radians, Rectangle, Shell, Size, Vector, Widget,
|
||||
};
|
||||
|
||||
/// A frame that displays an image with the ability to zoom in/out and pan.
|
||||
|
|
@ -349,11 +349,14 @@ where
|
|||
let render = |renderer: &mut Renderer| {
|
||||
renderer.with_translation(translation, |renderer| {
|
||||
renderer.draw_image(
|
||||
self.handle.clone(),
|
||||
self.filter_method,
|
||||
Image {
|
||||
handle: self.handle.clone(),
|
||||
filter_method: self.filter_method,
|
||||
rotation: Radians(0.0),
|
||||
opacity: 1.0,
|
||||
snap: true,
|
||||
},
|
||||
drawing_bounds,
|
||||
Radians(0.0),
|
||||
1.0,
|
||||
);
|
||||
});
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue