Merge pull request #2120 from iced-rs/transform-primitive
`Transform` primitive
This commit is contained in:
commit
aea172543c
36 changed files with 625 additions and 295 deletions
|
|
@ -12,6 +12,7 @@ keywords.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags.workspace = true
|
bitflags.workspace = true
|
||||||
|
glam.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
num-traits.workspace = true
|
num-traits.workspace = true
|
||||||
smol_str.workspace = true
|
smol_str.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ mod rectangle;
|
||||||
mod shadow;
|
mod shadow;
|
||||||
mod shell;
|
mod shell;
|
||||||
mod size;
|
mod size;
|
||||||
|
mod transformation;
|
||||||
mod vector;
|
mod vector;
|
||||||
|
|
||||||
pub use alignment::Alignment;
|
pub use alignment::Alignment;
|
||||||
|
|
@ -75,6 +76,7 @@ pub use shadow::Shadow;
|
||||||
pub use shell::Shell;
|
pub use shell::Shell;
|
||||||
pub use size::Size;
|
pub use size::Size;
|
||||||
pub use text::Text;
|
pub use text::Text;
|
||||||
|
pub use transformation::Transformation;
|
||||||
pub use vector::Vector;
|
pub use vector::Vector;
|
||||||
pub use widget::Widget;
|
pub use widget::Widget;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,5 @@ pub enum Interaction {
|
||||||
ResizingHorizontally,
|
ResizingHorizontally,
|
||||||
ResizingVertically,
|
ResizingVertically,
|
||||||
NotAllowed,
|
NotAllowed,
|
||||||
|
ZoomIn,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,3 +26,11 @@ impl From<Pixels> for f32 {
|
||||||
pixels.0
|
pixels.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::ops::Mul<f32> for Pixels {
|
||||||
|
type Output = Pixels;
|
||||||
|
|
||||||
|
fn mul(self, rhs: f32) -> Self {
|
||||||
|
Pixels(self.0 * rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,9 @@ mod null;
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub use null::Null;
|
pub use null::Null;
|
||||||
|
|
||||||
use crate::{Background, Border, Color, Rectangle, Shadow, Size, Vector};
|
use crate::{
|
||||||
|
Background, Border, Color, Rectangle, Shadow, Size, Transformation, Vector,
|
||||||
|
};
|
||||||
|
|
||||||
/// A component that can be used by widgets to draw themselves on a screen.
|
/// A component that can be used by widgets to draw themselves on a screen.
|
||||||
pub trait Renderer: Sized {
|
pub trait Renderer: Sized {
|
||||||
|
|
@ -14,12 +16,24 @@ pub trait Renderer: Sized {
|
||||||
/// The layer will clip its contents to the provided `bounds`.
|
/// The layer will clip its contents to the provided `bounds`.
|
||||||
fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self));
|
fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self));
|
||||||
|
|
||||||
/// Applies a `translation` to the primitives recorded in the given closure.
|
/// Applies a [`Transformation`] to the primitives recorded in the given closure.
|
||||||
|
fn with_transformation(
|
||||||
|
&mut self,
|
||||||
|
transformation: Transformation,
|
||||||
|
f: impl FnOnce(&mut Self),
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Applies a translation to the primitives recorded in the given closure.
|
||||||
fn with_translation(
|
fn with_translation(
|
||||||
&mut self,
|
&mut self,
|
||||||
translation: Vector,
|
translation: Vector,
|
||||||
f: impl FnOnce(&mut Self),
|
f: impl FnOnce(&mut Self),
|
||||||
);
|
) {
|
||||||
|
self.with_transformation(
|
||||||
|
Transformation::translate(translation.x, translation.y),
|
||||||
|
f,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Fills a [`Quad`] with the provided [`Background`].
|
/// Fills a [`Quad`] with the provided [`Background`].
|
||||||
fn fill_quad(&mut self, quad: Quad, background: impl Into<Background>);
|
fn fill_quad(&mut self, quad: Quad, background: impl Into<Background>);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::alignment;
|
use crate::alignment;
|
||||||
use crate::renderer::{self, Renderer};
|
use crate::renderer::{self, Renderer};
|
||||||
use crate::text::{self, Text};
|
use crate::text::{self, Text};
|
||||||
use crate::{Background, Color, Font, Pixels, Point, Rectangle, Size, Vector};
|
use crate::{
|
||||||
|
Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation,
|
||||||
|
};
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
|
@ -21,9 +23,9 @@ impl Null {
|
||||||
impl Renderer for Null {
|
impl Renderer for Null {
|
||||||
fn with_layer(&mut self, _bounds: Rectangle, _f: impl FnOnce(&mut Self)) {}
|
fn with_layer(&mut self, _bounds: Rectangle, _f: impl FnOnce(&mut Self)) {}
|
||||||
|
|
||||||
fn with_translation(
|
fn with_transformation(
|
||||||
&mut self,
|
&mut self,
|
||||||
_translation: Vector,
|
_transformation: Transformation,
|
||||||
_f: impl FnOnce(&mut Self),
|
_f: impl FnOnce(&mut Self),
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
119
core/src/transformation.rs
Normal file
119
core/src/transformation.rs
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
use crate::{Point, Rectangle, Size, Vector};
|
||||||
|
|
||||||
|
use glam::{Mat4, Vec3, Vec4};
|
||||||
|
use std::ops::Mul;
|
||||||
|
|
||||||
|
/// A 2D transformation matrix.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub struct Transformation(Mat4);
|
||||||
|
|
||||||
|
impl Transformation {
|
||||||
|
/// A [`Transformation`] that preserves whatever is transformed.
|
||||||
|
pub const IDENTITY: Self = Self(Mat4::IDENTITY);
|
||||||
|
|
||||||
|
/// Creates an orthographic projection.
|
||||||
|
#[rustfmt::skip]
|
||||||
|
pub fn orthographic(width: u32, height: u32) -> Transformation {
|
||||||
|
Transformation(Mat4::orthographic_rh_gl(
|
||||||
|
0.0, width as f32,
|
||||||
|
height as f32, 0.0,
|
||||||
|
-1.0, 1.0
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a translate transformation.
|
||||||
|
pub fn translate(x: f32, y: f32) -> Transformation {
|
||||||
|
Transformation(Mat4::from_translation(Vec3::new(x, y, 0.0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a uniform scaling transformation.
|
||||||
|
pub fn scale(scaling: f32) -> Transformation {
|
||||||
|
Transformation(Mat4::from_scale(Vec3::new(scaling, scaling, 1.0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the scale factor of the [`Transformation`].
|
||||||
|
pub fn scale_factor(&self) -> f32 {
|
||||||
|
self.0.x_axis.x
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the translation of the [`Transformation`].
|
||||||
|
pub fn translation(&self) -> Vector {
|
||||||
|
Vector::new(self.0.w_axis.x, self.0.w_axis.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul for Transformation {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn mul(self, rhs: Self) -> Self {
|
||||||
|
Transformation(self.0 * rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<Transformation> for Point {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn mul(self, transformation: Transformation) -> Self {
|
||||||
|
let point = transformation
|
||||||
|
.0
|
||||||
|
.mul_vec4(Vec4::new(self.x, self.y, 1.0, 1.0));
|
||||||
|
|
||||||
|
Point::new(point.x, point.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<Transformation> for Vector {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn mul(self, transformation: Transformation) -> Self {
|
||||||
|
let new_vector = transformation
|
||||||
|
.0
|
||||||
|
.mul_vec4(Vec4::new(self.x, self.y, 1.0, 0.0));
|
||||||
|
|
||||||
|
Vector::new(new_vector.x, new_vector.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<Transformation> for Size {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn mul(self, transformation: Transformation) -> Self {
|
||||||
|
let new_size = transformation.0.mul_vec4(Vec4::new(
|
||||||
|
self.width,
|
||||||
|
self.height,
|
||||||
|
1.0,
|
||||||
|
0.0,
|
||||||
|
));
|
||||||
|
|
||||||
|
Size::new(new_size.x, new_size.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<Transformation> for Rectangle {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn mul(self, transformation: Transformation) -> Self {
|
||||||
|
let position = self.position();
|
||||||
|
let size = self.size();
|
||||||
|
|
||||||
|
Self::new(position * transformation, size * transformation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<[f32; 16]> for Transformation {
|
||||||
|
fn as_ref(&self) -> &[f32; 16] {
|
||||||
|
self.0.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Transformation> for [f32; 16] {
|
||||||
|
fn from(t: Transformation) -> [f32; 16] {
|
||||||
|
*t.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Transformation> for Mat4 {
|
||||||
|
fn from(transformation: Transformation) -> Self {
|
||||||
|
transformation.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,4 +7,4 @@ publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
iced.workspace = true
|
iced.workspace = true
|
||||||
iced.features = ["canvas"]
|
iced.features = ["canvas", "debug"]
|
||||||
|
|
|
||||||
10
examples/loupe/Cargo.toml
Normal file
10
examples/loupe/Cargo.toml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "loupe"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
|
||||||
|
edition = "2021"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
iced.workspace = true
|
||||||
|
iced.features = ["advanced", "debug"]
|
||||||
185
examples/loupe/src/main.rs
Normal file
185
examples/loupe/src/main.rs
Normal file
|
|
@ -0,0 +1,185 @@
|
||||||
|
use iced::widget::{button, column, container, text};
|
||||||
|
use iced::{Alignment, Element, Length, Sandbox, Settings};
|
||||||
|
|
||||||
|
use loupe::loupe;
|
||||||
|
|
||||||
|
pub fn main() -> iced::Result {
|
||||||
|
Counter::run(Settings::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Counter {
|
||||||
|
value: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum Message {
|
||||||
|
IncrementPressed,
|
||||||
|
DecrementPressed,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sandbox for Counter {
|
||||||
|
type Message = Message;
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
Self { value: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title(&self) -> String {
|
||||||
|
String::from("Counter - Iced")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, message: Message) {
|
||||||
|
match message {
|
||||||
|
Message::IncrementPressed => {
|
||||||
|
self.value += 1;
|
||||||
|
}
|
||||||
|
Message::DecrementPressed => {
|
||||||
|
self.value -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(&self) -> Element<Message> {
|
||||||
|
container(loupe(
|
||||||
|
3.0,
|
||||||
|
column![
|
||||||
|
button("Increment").on_press(Message::IncrementPressed),
|
||||||
|
text(self.value).size(50),
|
||||||
|
button("Decrement").on_press(Message::DecrementPressed)
|
||||||
|
]
|
||||||
|
.padding(20)
|
||||||
|
.align_items(Alignment::Center),
|
||||||
|
))
|
||||||
|
.width(Length::Fill)
|
||||||
|
.height(Length::Fill)
|
||||||
|
.center_x()
|
||||||
|
.center_y()
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod loupe {
|
||||||
|
use iced::advanced::layout::{self, Layout};
|
||||||
|
use iced::advanced::renderer;
|
||||||
|
use iced::advanced::widget::{self, Widget};
|
||||||
|
use iced::advanced::Renderer as _;
|
||||||
|
use iced::mouse;
|
||||||
|
use iced::{
|
||||||
|
Color, Element, Length, Rectangle, Renderer, Size, Theme,
|
||||||
|
Transformation,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn loupe<'a, Message>(
|
||||||
|
zoom: f32,
|
||||||
|
content: impl Into<Element<'a, Message>>,
|
||||||
|
) -> Loupe<'a, Message>
|
||||||
|
where
|
||||||
|
Message: 'static,
|
||||||
|
{
|
||||||
|
Loupe {
|
||||||
|
zoom,
|
||||||
|
content: content.into().explain(Color::BLACK),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Loupe<'a, Message> {
|
||||||
|
zoom: f32,
|
||||||
|
content: Element<'a, Message>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Message> Widget<Message, Theme, Renderer> for Loupe<'a, Message> {
|
||||||
|
fn tag(&self) -> widget::tree::Tag {
|
||||||
|
self.content.as_widget().tag()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state(&self) -> widget::tree::State {
|
||||||
|
self.content.as_widget().state()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn children(&self) -> Vec<widget::Tree> {
|
||||||
|
self.content.as_widget().children()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn diff(&self, tree: &mut widget::Tree) {
|
||||||
|
self.content.as_widget().diff(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> Size<Length> {
|
||||||
|
self.content.as_widget().size()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layout(
|
||||||
|
&self,
|
||||||
|
tree: &mut widget::Tree,
|
||||||
|
renderer: &Renderer,
|
||||||
|
limits: &layout::Limits,
|
||||||
|
) -> layout::Node {
|
||||||
|
self.content.as_widget().layout(tree, renderer, limits)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(
|
||||||
|
&self,
|
||||||
|
tree: &widget::Tree,
|
||||||
|
renderer: &mut Renderer,
|
||||||
|
theme: &Theme,
|
||||||
|
style: &renderer::Style,
|
||||||
|
layout: Layout<'_>,
|
||||||
|
cursor: mouse::Cursor,
|
||||||
|
viewport: &Rectangle,
|
||||||
|
) {
|
||||||
|
let bounds = layout.bounds();
|
||||||
|
|
||||||
|
if let Some(position) = cursor.position_in(bounds) {
|
||||||
|
renderer.with_layer(bounds, |renderer| {
|
||||||
|
renderer.with_transformation(
|
||||||
|
Transformation::translate(
|
||||||
|
bounds.x + position.x * (1.0 - self.zoom),
|
||||||
|
bounds.y + position.y * (1.0 - self.zoom),
|
||||||
|
) * Transformation::scale(self.zoom)
|
||||||
|
* Transformation::translate(-bounds.x, -bounds.y),
|
||||||
|
|renderer| {
|
||||||
|
self.content.as_widget().draw(
|
||||||
|
tree,
|
||||||
|
renderer,
|
||||||
|
theme,
|
||||||
|
style,
|
||||||
|
layout,
|
||||||
|
mouse::Cursor::Unavailable,
|
||||||
|
viewport,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self.content.as_widget().draw(
|
||||||
|
tree, renderer, theme, style, layout, cursor, viewport,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mouse_interaction(
|
||||||
|
&self,
|
||||||
|
_state: &widget::Tree,
|
||||||
|
layout: Layout<'_>,
|
||||||
|
cursor: mouse::Cursor,
|
||||||
|
_viewport: &Rectangle,
|
||||||
|
_renderer: &Renderer,
|
||||||
|
) -> mouse::Interaction {
|
||||||
|
if cursor.is_over(layout.bounds()) {
|
||||||
|
mouse::Interaction::ZoomIn
|
||||||
|
} else {
|
||||||
|
mouse::Interaction::Idle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Message> From<Loupe<'a, Message>>
|
||||||
|
for Element<'a, Message, Theme, Renderer>
|
||||||
|
where
|
||||||
|
Message: 'a,
|
||||||
|
{
|
||||||
|
fn from(loupe: Loupe<'a, Message>) -> Self {
|
||||||
|
Self::new(loupe)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -26,7 +26,6 @@ iced_futures.workspace = true
|
||||||
bitflags.workspace = true
|
bitflags.workspace = true
|
||||||
bytemuck.workspace = true
|
bytemuck.workspace = true
|
||||||
cosmic-text.workspace = true
|
cosmic-text.workspace = true
|
||||||
glam.workspace = true
|
|
||||||
half.workspace = true
|
half.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
once_cell.workspace = true
|
once_cell.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -102,10 +102,10 @@ impl<T: Damage> Damage for Primitive<T> {
|
||||||
.fold(Rectangle::with_size(Size::ZERO), |a, b| {
|
.fold(Rectangle::with_size(Size::ZERO), |a, b| {
|
||||||
Rectangle::union(&a, &b)
|
Rectangle::union(&a, &b)
|
||||||
}),
|
}),
|
||||||
Self::Translate {
|
Self::Transform {
|
||||||
translation,
|
transformation,
|
||||||
content,
|
content,
|
||||||
} => content.bounds() + *translation,
|
} => content.bounds() * *transformation,
|
||||||
Self::Cache { content } => content.bounds(),
|
Self::Cache { content } => content.bounds(),
|
||||||
Self::Custom(custom) => custom.bounds(),
|
Self::Custom(custom) => custom.bounds(),
|
||||||
}
|
}
|
||||||
|
|
@ -144,19 +144,19 @@ fn regions<T: Damage>(a: &Primitive<T>, b: &Primitive<T>) -> Vec<Rectangle> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
Primitive::Translate {
|
Primitive::Transform {
|
||||||
translation: translation_a,
|
transformation: transformation_a,
|
||||||
content: content_a,
|
content: content_a,
|
||||||
},
|
},
|
||||||
Primitive::Translate {
|
Primitive::Transform {
|
||||||
translation: translation_b,
|
transformation: transformation_b,
|
||||||
content: content_b,
|
content: content_b,
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
if translation_a == translation_b {
|
if transformation_a == transformation_b {
|
||||||
return regions(content_a, content_b)
|
return regions(content_a, content_b)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|r| r + *translation_a)
|
.map(|r| r * *transformation_a)
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
mod antialiasing;
|
mod antialiasing;
|
||||||
mod error;
|
mod error;
|
||||||
mod primitive;
|
mod primitive;
|
||||||
mod transformation;
|
|
||||||
mod viewport;
|
mod viewport;
|
||||||
|
|
||||||
pub mod backend;
|
pub mod backend;
|
||||||
|
|
@ -46,7 +45,6 @@ pub use gradient::Gradient;
|
||||||
pub use mesh::Mesh;
|
pub use mesh::Mesh;
|
||||||
pub use primitive::Primitive;
|
pub use primitive::Primitive;
|
||||||
pub use renderer::Renderer;
|
pub use renderer::Renderer;
|
||||||
pub use transformation::Transformation;
|
|
||||||
pub use viewport::Viewport;
|
pub use viewport::Viewport;
|
||||||
|
|
||||||
pub use iced_core as core;
|
pub use iced_core as core;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ use crate::core::image;
|
||||||
use crate::core::svg;
|
use crate::core::svg;
|
||||||
use crate::core::text;
|
use crate::core::text;
|
||||||
use crate::core::{
|
use crate::core::{
|
||||||
Background, Border, Color, Font, Pixels, Point, Rectangle, Shadow, Vector,
|
Background, Border, Color, Font, Pixels, Point, Rectangle, Shadow,
|
||||||
|
Transformation, Vector,
|
||||||
};
|
};
|
||||||
use crate::text::editor;
|
use crate::text::editor;
|
||||||
use crate::text::paragraph;
|
use crate::text::paragraph;
|
||||||
|
|
@ -104,12 +105,12 @@ pub enum Primitive<T> {
|
||||||
/// The content of the clip
|
/// The content of the clip
|
||||||
content: Box<Primitive<T>>,
|
content: Box<Primitive<T>>,
|
||||||
},
|
},
|
||||||
/// A primitive that applies a translation
|
/// A primitive that applies a [`Transformation`]
|
||||||
Translate {
|
Transform {
|
||||||
/// The translation vector
|
/// The [`Transformation`]
|
||||||
translation: Vector,
|
transformation: Transformation,
|
||||||
|
|
||||||
/// The primitive to translate
|
/// The primitive to transform
|
||||||
content: Box<Primitive<T>>,
|
content: Box<Primitive<T>>,
|
||||||
},
|
},
|
||||||
/// A cached primitive.
|
/// A cached primitive.
|
||||||
|
|
@ -125,12 +126,12 @@ pub enum Primitive<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Primitive<T> {
|
impl<T> Primitive<T> {
|
||||||
/// Creates a [`Primitive::Group`].
|
/// Groups the current [`Primitive`].
|
||||||
pub fn group(primitives: Vec<Self>) -> Self {
|
pub fn group(primitives: Vec<Self>) -> Self {
|
||||||
Self::Group { primitives }
|
Self::Group { primitives }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a [`Primitive::Clip`].
|
/// Clips the current [`Primitive`].
|
||||||
pub fn clip(self, bounds: Rectangle) -> Self {
|
pub fn clip(self, bounds: Rectangle) -> Self {
|
||||||
Self::Clip {
|
Self::Clip {
|
||||||
bounds,
|
bounds,
|
||||||
|
|
@ -138,10 +139,21 @@ impl<T> Primitive<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a [`Primitive::Translate`].
|
/// Translates the current [`Primitive`].
|
||||||
pub fn translate(self, translation: Vector) -> Self {
|
pub fn translate(self, translation: Vector) -> Self {
|
||||||
Self::Translate {
|
Self::Transform {
|
||||||
translation,
|
transformation: Transformation::translate(
|
||||||
|
translation.x,
|
||||||
|
translation.y,
|
||||||
|
),
|
||||||
|
content: Box::new(self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transforms the current [`Primitive`].
|
||||||
|
pub fn transform(self, transformation: Transformation) -> Self {
|
||||||
|
Self::Transform {
|
||||||
|
transformation,
|
||||||
content: Box::new(self),
|
content: Box::new(self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use crate::core::renderer;
|
||||||
use crate::core::svg;
|
use crate::core::svg;
|
||||||
use crate::core::text::Text;
|
use crate::core::text::Text;
|
||||||
use crate::core::{
|
use crate::core::{
|
||||||
Background, Color, Font, Pixels, Point, Rectangle, Size, Vector,
|
Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation,
|
||||||
};
|
};
|
||||||
use crate::text;
|
use crate::text;
|
||||||
use crate::Primitive;
|
use crate::Primitive;
|
||||||
|
|
@ -73,20 +73,20 @@ impl<B: Backend> Renderer<B> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Starts recording a translation.
|
/// Starts recording a translation.
|
||||||
pub fn start_translation(&mut self) -> Vec<Primitive<B::Primitive>> {
|
pub fn start_transformation(&mut self) -> Vec<Primitive<B::Primitive>> {
|
||||||
std::mem::take(&mut self.primitives)
|
std::mem::take(&mut self.primitives)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ends the recording of a translation.
|
/// Ends the recording of a translation.
|
||||||
pub fn end_translation(
|
pub fn end_transformation(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitives: Vec<Primitive<B::Primitive>>,
|
primitives: Vec<Primitive<B::Primitive>>,
|
||||||
translation: Vector,
|
transformation: Transformation,
|
||||||
) {
|
) {
|
||||||
let layer = std::mem::replace(&mut self.primitives, primitives);
|
let layer = std::mem::replace(&mut self.primitives, primitives);
|
||||||
|
|
||||||
self.primitives
|
self.primitives
|
||||||
.push(Primitive::group(layer).translate(translation));
|
.push(Primitive::group(layer).transform(transformation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,16 +99,16 @@ impl<B: Backend> iced_core::Renderer for Renderer<B> {
|
||||||
self.end_layer(current, bounds);
|
self.end_layer(current, bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_translation(
|
fn with_transformation(
|
||||||
&mut self,
|
&mut self,
|
||||||
translation: Vector,
|
transformation: Transformation,
|
||||||
f: impl FnOnce(&mut Self),
|
f: impl FnOnce(&mut Self),
|
||||||
) {
|
) {
|
||||||
let current = self.start_translation();
|
let current = self.start_transformation();
|
||||||
|
|
||||||
f(self);
|
f(self);
|
||||||
|
|
||||||
self.end_translation(current, translation);
|
self.end_transformation(current, transformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_quad(
|
fn fill_quad(
|
||||||
|
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
use glam::{Mat4, Vec3};
|
|
||||||
use std::ops::Mul;
|
|
||||||
|
|
||||||
/// A 2D transformation matrix.
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
||||||
pub struct Transformation(Mat4);
|
|
||||||
|
|
||||||
impl Transformation {
|
|
||||||
/// Get the identity transformation.
|
|
||||||
pub fn identity() -> Transformation {
|
|
||||||
Transformation(Mat4::IDENTITY)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an orthographic projection.
|
|
||||||
#[rustfmt::skip]
|
|
||||||
pub fn orthographic(width: u32, height: u32) -> Transformation {
|
|
||||||
Transformation(Mat4::orthographic_rh_gl(
|
|
||||||
0.0, width as f32,
|
|
||||||
height as f32, 0.0,
|
|
||||||
-1.0, 1.0
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a translate transformation.
|
|
||||||
pub fn translate(x: f32, y: f32) -> Transformation {
|
|
||||||
Transformation(Mat4::from_translation(Vec3::new(x, y, 0.0)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a scale transformation.
|
|
||||||
pub fn scale(x: f32, y: f32) -> Transformation {
|
|
||||||
Transformation(Mat4::from_scale(Vec3::new(x, y, 1.0)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mul for Transformation {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn mul(self, rhs: Self) -> Self {
|
|
||||||
Transformation(self.0 * rhs.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<[f32; 16]> for Transformation {
|
|
||||||
fn as_ref(&self) -> &[f32; 16] {
|
|
||||||
self.0.as_ref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Transformation> for [f32; 16] {
|
|
||||||
fn from(t: Transformation) -> [f32; 16] {
|
|
||||||
*t.as_ref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Transformation> for Mat4 {
|
|
||||||
fn from(transformation: Transformation) -> Self {
|
|
||||||
transformation.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
use crate::Transformation;
|
use crate::core::{Size, Transformation};
|
||||||
|
|
||||||
use iced_core::Size;
|
|
||||||
|
|
||||||
/// A viewing region for displaying computer graphics.
|
/// A viewing region for displaying computer graphics.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,10 @@ mod cache;
|
||||||
|
|
||||||
pub use cache::Cache;
|
pub use cache::Cache;
|
||||||
|
|
||||||
use crate::core::{Point, Rectangle, Size, Vector};
|
use crate::core::{Point, Rectangle, Size, Transformation, Vector};
|
||||||
use crate::graphics::geometry::{Fill, Path, Stroke, Text};
|
use crate::graphics::geometry::{Fill, Path, Stroke, Text};
|
||||||
use crate::Renderer;
|
use crate::Renderer;
|
||||||
|
|
||||||
pub enum Frame {
|
|
||||||
TinySkia(iced_tiny_skia::geometry::Frame),
|
|
||||||
#[cfg(feature = "wgpu")]
|
|
||||||
Wgpu(iced_wgpu::geometry::Frame),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Geometry {
|
|
||||||
TinySkia(iced_tiny_skia::Primitive),
|
|
||||||
#[cfg(feature = "wgpu")]
|
|
||||||
Wgpu(iced_wgpu::Primitive),
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! delegate {
|
macro_rules! delegate {
|
||||||
($frame:expr, $name:ident, $body:expr) => {
|
($frame:expr, $name:ident, $body:expr) => {
|
||||||
match $frame {
|
match $frame {
|
||||||
|
|
@ -28,6 +16,32 @@ macro_rules! delegate {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum Geometry {
|
||||||
|
TinySkia(iced_tiny_skia::Primitive),
|
||||||
|
#[cfg(feature = "wgpu")]
|
||||||
|
Wgpu(iced_wgpu::Primitive),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Geometry {
|
||||||
|
pub fn transform(self, transformation: Transformation) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::TinySkia(primitive) => {
|
||||||
|
Self::TinySkia(primitive.transform(transformation))
|
||||||
|
}
|
||||||
|
#[cfg(feature = "wgpu")]
|
||||||
|
Self::Wgpu(primitive) => {
|
||||||
|
Self::Wgpu(primitive.transform(transformation))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Frame {
|
||||||
|
TinySkia(iced_tiny_skia::geometry::Frame),
|
||||||
|
#[cfg(feature = "wgpu")]
|
||||||
|
Wgpu(iced_wgpu::geometry::Frame),
|
||||||
|
}
|
||||||
|
|
||||||
impl Frame {
|
impl Frame {
|
||||||
pub fn new(renderer: &Renderer, size: Size) -> Self {
|
pub fn new(renderer: &Renderer, size: Size) -> Self {
|
||||||
match renderer {
|
match renderer {
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,9 @@ pub use geometry::Geometry;
|
||||||
|
|
||||||
use crate::core::renderer;
|
use crate::core::renderer;
|
||||||
use crate::core::text::{self, Text};
|
use crate::core::text::{self, Text};
|
||||||
use crate::core::{Background, Color, Font, Pixels, Point, Rectangle, Vector};
|
use crate::core::{
|
||||||
|
Background, Color, Font, Pixels, Point, Rectangle, Transformation,
|
||||||
|
};
|
||||||
use crate::graphics::text::Editor;
|
use crate::graphics::text::Editor;
|
||||||
use crate::graphics::text::Paragraph;
|
use crate::graphics::text::Paragraph;
|
||||||
use crate::graphics::Mesh;
|
use crate::graphics::Mesh;
|
||||||
|
|
@ -97,20 +99,20 @@ impl core::Renderer for Renderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_translation(
|
fn with_transformation(
|
||||||
&mut self,
|
&mut self,
|
||||||
translation: Vector,
|
transformation: Transformation,
|
||||||
f: impl FnOnce(&mut Self),
|
f: impl FnOnce(&mut Self),
|
||||||
) {
|
) {
|
||||||
match self {
|
match self {
|
||||||
Self::TinySkia(renderer) => {
|
Self::TinySkia(renderer) => {
|
||||||
let primitives = renderer.start_translation();
|
let primitives = renderer.start_transformation();
|
||||||
|
|
||||||
f(self);
|
f(self);
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Self::TinySkia(renderer) => {
|
Self::TinySkia(renderer) => {
|
||||||
renderer.end_translation(primitives, translation);
|
renderer.end_transformation(primitives, transformation);
|
||||||
}
|
}
|
||||||
#[cfg(feature = "wgpu")]
|
#[cfg(feature = "wgpu")]
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
@ -118,14 +120,14 @@ impl core::Renderer for Renderer {
|
||||||
}
|
}
|
||||||
#[cfg(feature = "wgpu")]
|
#[cfg(feature = "wgpu")]
|
||||||
Self::Wgpu(renderer) => {
|
Self::Wgpu(renderer) => {
|
||||||
let primitives = renderer.start_translation();
|
let primitives = renderer.start_transformation();
|
||||||
|
|
||||||
f(self);
|
f(self);
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
#[cfg(feature = "wgpu")]
|
#[cfg(feature = "wgpu")]
|
||||||
Self::Wgpu(renderer) => {
|
Self::Wgpu(renderer) => {
|
||||||
renderer.end_translation(primitives, translation);
|
renderer.end_transformation(primitives, transformation);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,8 @@ pub use crate::core::color;
|
||||||
pub use crate::core::gradient;
|
pub use crate::core::gradient;
|
||||||
pub use crate::core::{
|
pub use crate::core::{
|
||||||
Alignment, Background, Border, Color, ContentFit, Degrees, Gradient,
|
Alignment, Background, Border, Color, ContentFit, Degrees, Gradient,
|
||||||
Length, Padding, Pixels, Point, Radians, Rectangle, Shadow, Size, Vector,
|
Length, Padding, Pixels, Point, Radians, Rectangle, Shadow, Size,
|
||||||
|
Transformation, Vector,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod clipboard {
|
pub mod clipboard {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
use tiny_skia::Size;
|
use tiny_skia::Size;
|
||||||
|
|
||||||
use crate::core::{Background, Color, Gradient, Rectangle, Vector};
|
use crate::core::{
|
||||||
|
Background, Color, Gradient, Rectangle, Transformation, Vector,
|
||||||
|
};
|
||||||
use crate::graphics::backend;
|
use crate::graphics::backend;
|
||||||
use crate::graphics::text;
|
use crate::graphics::text;
|
||||||
use crate::graphics::Viewport;
|
use crate::graphics::Viewport;
|
||||||
|
|
@ -106,7 +108,7 @@ impl Backend {
|
||||||
clip_mask,
|
clip_mask,
|
||||||
region,
|
region,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
Vector::ZERO,
|
Transformation::IDENTITY,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,7 +148,7 @@ impl Backend {
|
||||||
clip_mask: &mut tiny_skia::Mask,
|
clip_mask: &mut tiny_skia::Mask,
|
||||||
clip_bounds: Rectangle,
|
clip_bounds: Rectangle,
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
translation: Vector,
|
transformation: Transformation,
|
||||||
) {
|
) {
|
||||||
match primitive {
|
match primitive {
|
||||||
Primitive::Quad {
|
Primitive::Quad {
|
||||||
|
|
@ -164,7 +166,7 @@ impl Backend {
|
||||||
"Quad with non-normal height!"
|
"Quad with non-normal height!"
|
||||||
);
|
);
|
||||||
|
|
||||||
let physical_bounds = (*bounds + translation) * scale_factor;
|
let physical_bounds = (*bounds * transformation) * scale_factor;
|
||||||
|
|
||||||
if !clip_bounds.intersects(&physical_bounds) {
|
if !clip_bounds.intersects(&physical_bounds) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -173,11 +175,8 @@ impl Backend {
|
||||||
let clip_mask = (!physical_bounds.is_within(&clip_bounds))
|
let clip_mask = (!physical_bounds.is_within(&clip_bounds))
|
||||||
.then_some(clip_mask as &_);
|
.then_some(clip_mask as &_);
|
||||||
|
|
||||||
let transform = tiny_skia::Transform::from_translate(
|
let transform = into_transform(transformation)
|
||||||
translation.x,
|
.post_scale(scale_factor, scale_factor);
|
||||||
translation.y,
|
|
||||||
)
|
|
||||||
.post_scale(scale_factor, scale_factor);
|
|
||||||
|
|
||||||
// Make sure the border radius is not larger than the bounds
|
// Make sure the border radius is not larger than the bounds
|
||||||
let border_width = border
|
let border_width = border
|
||||||
|
|
@ -199,7 +198,7 @@ impl Backend {
|
||||||
y: bounds.y + shadow.offset.y - shadow.blur_radius,
|
y: bounds.y + shadow.offset.y - shadow.blur_radius,
|
||||||
width: bounds.width + shadow.blur_radius * 2.0,
|
width: bounds.width + shadow.blur_radius * 2.0,
|
||||||
height: bounds.height + shadow.blur_radius * 2.0,
|
height: bounds.height + shadow.blur_radius * 2.0,
|
||||||
} + translation)
|
} * transformation)
|
||||||
* scale_factor;
|
* scale_factor;
|
||||||
|
|
||||||
let radii = fill_border_radius
|
let radii = fill_border_radius
|
||||||
|
|
@ -451,7 +450,7 @@ impl Backend {
|
||||||
clip_bounds: text_clip_bounds,
|
clip_bounds: text_clip_bounds,
|
||||||
} => {
|
} => {
|
||||||
let physical_bounds =
|
let physical_bounds =
|
||||||
(*text_clip_bounds + translation) * scale_factor;
|
*text_clip_bounds * transformation * scale_factor;
|
||||||
|
|
||||||
if !clip_bounds.intersects(&physical_bounds) {
|
if !clip_bounds.intersects(&physical_bounds) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -462,11 +461,12 @@ impl Backend {
|
||||||
|
|
||||||
self.text_pipeline.draw_paragraph(
|
self.text_pipeline.draw_paragraph(
|
||||||
paragraph,
|
paragraph,
|
||||||
*position + translation,
|
*position,
|
||||||
*color,
|
*color,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
pixels,
|
pixels,
|
||||||
clip_mask,
|
clip_mask,
|
||||||
|
transformation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Primitive::Editor {
|
Primitive::Editor {
|
||||||
|
|
@ -476,7 +476,7 @@ impl Backend {
|
||||||
clip_bounds: text_clip_bounds,
|
clip_bounds: text_clip_bounds,
|
||||||
} => {
|
} => {
|
||||||
let physical_bounds =
|
let physical_bounds =
|
||||||
(*text_clip_bounds + translation) * scale_factor;
|
(*text_clip_bounds * transformation) * scale_factor;
|
||||||
|
|
||||||
if !clip_bounds.intersects(&physical_bounds) {
|
if !clip_bounds.intersects(&physical_bounds) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -487,11 +487,12 @@ impl Backend {
|
||||||
|
|
||||||
self.text_pipeline.draw_editor(
|
self.text_pipeline.draw_editor(
|
||||||
editor,
|
editor,
|
||||||
*position + translation,
|
*position,
|
||||||
*color,
|
*color,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
pixels,
|
pixels,
|
||||||
clip_mask,
|
clip_mask,
|
||||||
|
transformation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Primitive::Text {
|
Primitive::Text {
|
||||||
|
|
@ -507,7 +508,7 @@ impl Backend {
|
||||||
clip_bounds: text_clip_bounds,
|
clip_bounds: text_clip_bounds,
|
||||||
} => {
|
} => {
|
||||||
let physical_bounds =
|
let physical_bounds =
|
||||||
(*text_clip_bounds + translation) * scale_factor;
|
*text_clip_bounds * transformation * scale_factor;
|
||||||
|
|
||||||
if !clip_bounds.intersects(&physical_bounds) {
|
if !clip_bounds.intersects(&physical_bounds) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -518,7 +519,7 @@ impl Backend {
|
||||||
|
|
||||||
self.text_pipeline.draw_cached(
|
self.text_pipeline.draw_cached(
|
||||||
content,
|
content,
|
||||||
*bounds + translation,
|
*bounds,
|
||||||
*color,
|
*color,
|
||||||
*size,
|
*size,
|
||||||
*line_height,
|
*line_height,
|
||||||
|
|
@ -529,6 +530,7 @@ impl Backend {
|
||||||
scale_factor,
|
scale_factor,
|
||||||
pixels,
|
pixels,
|
||||||
clip_mask,
|
clip_mask,
|
||||||
|
transformation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Primitive::RawText(text::Raw {
|
Primitive::RawText(text::Raw {
|
||||||
|
|
@ -542,7 +544,7 @@ impl Backend {
|
||||||
};
|
};
|
||||||
|
|
||||||
let physical_bounds =
|
let physical_bounds =
|
||||||
(*text_clip_bounds + translation) * scale_factor;
|
*text_clip_bounds * transformation * scale_factor;
|
||||||
|
|
||||||
if !clip_bounds.intersects(&physical_bounds) {
|
if !clip_bounds.intersects(&physical_bounds) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -553,11 +555,12 @@ impl Backend {
|
||||||
|
|
||||||
self.text_pipeline.draw_raw(
|
self.text_pipeline.draw_raw(
|
||||||
&buffer,
|
&buffer,
|
||||||
*position + translation,
|
*position,
|
||||||
*color,
|
*color,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
pixels,
|
pixels,
|
||||||
clip_mask,
|
clip_mask,
|
||||||
|
transformation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#[cfg(feature = "image")]
|
#[cfg(feature = "image")]
|
||||||
|
|
@ -566,7 +569,7 @@ impl Backend {
|
||||||
filter_method,
|
filter_method,
|
||||||
bounds,
|
bounds,
|
||||||
} => {
|
} => {
|
||||||
let physical_bounds = (*bounds + translation) * scale_factor;
|
let physical_bounds = (*bounds * transformation) * scale_factor;
|
||||||
|
|
||||||
if !clip_bounds.intersects(&physical_bounds) {
|
if !clip_bounds.intersects(&physical_bounds) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -575,11 +578,8 @@ impl Backend {
|
||||||
let clip_mask = (!physical_bounds.is_within(&clip_bounds))
|
let clip_mask = (!physical_bounds.is_within(&clip_bounds))
|
||||||
.then_some(clip_mask as &_);
|
.then_some(clip_mask as &_);
|
||||||
|
|
||||||
let transform = tiny_skia::Transform::from_translate(
|
let transform = into_transform(transformation)
|
||||||
translation.x,
|
.post_scale(scale_factor, scale_factor);
|
||||||
translation.y,
|
|
||||||
)
|
|
||||||
.post_scale(scale_factor, scale_factor);
|
|
||||||
|
|
||||||
self.raster_pipeline.draw(
|
self.raster_pipeline.draw(
|
||||||
handle,
|
handle,
|
||||||
|
|
@ -602,7 +602,7 @@ impl Backend {
|
||||||
bounds,
|
bounds,
|
||||||
color,
|
color,
|
||||||
} => {
|
} => {
|
||||||
let physical_bounds = (*bounds + translation) * scale_factor;
|
let physical_bounds = (*bounds * transformation) * scale_factor;
|
||||||
|
|
||||||
if !clip_bounds.intersects(&physical_bounds) {
|
if !clip_bounds.intersects(&physical_bounds) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -614,7 +614,7 @@ impl Backend {
|
||||||
self.vector_pipeline.draw(
|
self.vector_pipeline.draw(
|
||||||
handle,
|
handle,
|
||||||
*color,
|
*color,
|
||||||
(*bounds + translation) * scale_factor,
|
(*bounds * transformation) * scale_factor,
|
||||||
pixels,
|
pixels,
|
||||||
clip_mask,
|
clip_mask,
|
||||||
);
|
);
|
||||||
|
|
@ -637,7 +637,7 @@ impl Backend {
|
||||||
y: bounds.y(),
|
y: bounds.y(),
|
||||||
width: bounds.width(),
|
width: bounds.width(),
|
||||||
height: bounds.height(),
|
height: bounds.height(),
|
||||||
} + translation)
|
} * transformation)
|
||||||
* scale_factor;
|
* scale_factor;
|
||||||
|
|
||||||
if !clip_bounds.intersects(&physical_bounds) {
|
if !clip_bounds.intersects(&physical_bounds) {
|
||||||
|
|
@ -651,11 +651,8 @@ impl Backend {
|
||||||
path,
|
path,
|
||||||
paint,
|
paint,
|
||||||
*rule,
|
*rule,
|
||||||
tiny_skia::Transform::from_translate(
|
into_transform(transformation)
|
||||||
translation.x,
|
.post_scale(scale_factor, scale_factor),
|
||||||
translation.y,
|
|
||||||
)
|
|
||||||
.post_scale(scale_factor, scale_factor),
|
|
||||||
clip_mask,
|
clip_mask,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -671,7 +668,7 @@ impl Backend {
|
||||||
y: bounds.y(),
|
y: bounds.y(),
|
||||||
width: bounds.width(),
|
width: bounds.width(),
|
||||||
height: bounds.height(),
|
height: bounds.height(),
|
||||||
} + translation)
|
} * transformation)
|
||||||
* scale_factor;
|
* scale_factor;
|
||||||
|
|
||||||
if !clip_bounds.intersects(&physical_bounds) {
|
if !clip_bounds.intersects(&physical_bounds) {
|
||||||
|
|
@ -685,11 +682,8 @@ impl Backend {
|
||||||
path,
|
path,
|
||||||
paint,
|
paint,
|
||||||
stroke,
|
stroke,
|
||||||
tiny_skia::Transform::from_translate(
|
into_transform(transformation)
|
||||||
translation.x,
|
.post_scale(scale_factor, scale_factor),
|
||||||
translation.y,
|
|
||||||
)
|
|
||||||
.post_scale(scale_factor, scale_factor),
|
|
||||||
clip_mask,
|
clip_mask,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -701,12 +695,12 @@ impl Backend {
|
||||||
clip_mask,
|
clip_mask,
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
translation,
|
transformation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Primitive::Translate {
|
Primitive::Transform {
|
||||||
translation: offset,
|
transformation: new_transformation,
|
||||||
content,
|
content,
|
||||||
} => {
|
} => {
|
||||||
self.draw_primitive(
|
self.draw_primitive(
|
||||||
|
|
@ -715,11 +709,11 @@ impl Backend {
|
||||||
clip_mask,
|
clip_mask,
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
translation + *offset,
|
transformation * *new_transformation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Primitive::Clip { bounds, content } => {
|
Primitive::Clip { bounds, content } => {
|
||||||
let bounds = (*bounds + translation) * scale_factor;
|
let bounds = (*bounds * transformation) * scale_factor;
|
||||||
|
|
||||||
if bounds == clip_bounds {
|
if bounds == clip_bounds {
|
||||||
self.draw_primitive(
|
self.draw_primitive(
|
||||||
|
|
@ -728,7 +722,7 @@ impl Backend {
|
||||||
clip_mask,
|
clip_mask,
|
||||||
bounds,
|
bounds,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
translation,
|
transformation,
|
||||||
);
|
);
|
||||||
} else if let Some(bounds) = clip_bounds.intersection(&bounds) {
|
} else if let Some(bounds) = clip_bounds.intersection(&bounds) {
|
||||||
if bounds.x + bounds.width <= 0.0
|
if bounds.x + bounds.width <= 0.0
|
||||||
|
|
@ -749,7 +743,7 @@ impl Backend {
|
||||||
clip_mask,
|
clip_mask,
|
||||||
bounds,
|
bounds,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
translation,
|
transformation,
|
||||||
);
|
);
|
||||||
|
|
||||||
adjust_clip_mask(clip_mask, clip_bounds);
|
adjust_clip_mask(clip_mask, clip_bounds);
|
||||||
|
|
@ -762,7 +756,7 @@ impl Backend {
|
||||||
clip_mask,
|
clip_mask,
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
translation,
|
transformation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -780,6 +774,19 @@ fn into_color(color: Color) -> tiny_skia::Color {
|
||||||
.expect("Convert color from iced to tiny_skia")
|
.expect("Convert color from iced to tiny_skia")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn into_transform(transformation: Transformation) -> tiny_skia::Transform {
|
||||||
|
let translation = transformation.translation();
|
||||||
|
|
||||||
|
tiny_skia::Transform {
|
||||||
|
sx: transformation.scale_factor(),
|
||||||
|
kx: 0.0,
|
||||||
|
ky: 0.0,
|
||||||
|
sy: transformation.scale_factor(),
|
||||||
|
tx: translation.x,
|
||||||
|
ty: translation.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn rounded_rectangle(
|
fn rounded_rectangle(
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
border_radius: [f32; 4],
|
border_radius: [f32; 4],
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::core::text::LineHeight;
|
use crate::core::text::LineHeight;
|
||||||
use crate::core::{Pixels, Point, Rectangle, Size, Vector};
|
use crate::core::{Pixels, Point, Rectangle, Size, Transformation, Vector};
|
||||||
use crate::graphics::geometry::fill::{self, Fill};
|
use crate::graphics::geometry::fill::{self, Fill};
|
||||||
use crate::graphics::geometry::stroke::{self, Stroke};
|
use crate::graphics::geometry::stroke::{self, Stroke};
|
||||||
use crate::graphics::geometry::{Path, Style, Text};
|
use crate::graphics::geometry::{Path, Style, Text};
|
||||||
|
|
@ -181,8 +181,8 @@ impl Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clip(&mut self, frame: Self, at: Point) {
|
pub fn clip(&mut self, frame: Self, at: Point) {
|
||||||
self.primitives.push(Primitive::Translate {
|
self.primitives.push(Primitive::Transform {
|
||||||
translation: Vector::new(at.x, at.y),
|
transformation: Transformation::translate(at.x, at.y),
|
||||||
content: Box::new(frame.into_primitive()),
|
content: Box::new(frame.into_primitive()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::core::alignment;
|
use crate::core::alignment;
|
||||||
use crate::core::text::{LineHeight, Shaping};
|
use crate::core::text::{LineHeight, Shaping};
|
||||||
use crate::core::{Color, Font, Pixels, Point, Rectangle, Size};
|
use crate::core::{
|
||||||
|
Color, Font, Pixels, Point, Rectangle, Size, Transformation,
|
||||||
|
};
|
||||||
use crate::graphics::text::cache::{self, Cache};
|
use crate::graphics::text::cache::{self, Cache};
|
||||||
use crate::graphics::text::editor;
|
use crate::graphics::text::editor;
|
||||||
use crate::graphics::text::font_system;
|
use crate::graphics::text::font_system;
|
||||||
|
|
@ -42,6 +44,7 @@ impl Pipeline {
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
pixels: &mut tiny_skia::PixmapMut<'_>,
|
pixels: &mut tiny_skia::PixmapMut<'_>,
|
||||||
clip_mask: Option<&tiny_skia::Mask>,
|
clip_mask: Option<&tiny_skia::Mask>,
|
||||||
|
transformation: Transformation,
|
||||||
) {
|
) {
|
||||||
use crate::core::text::Paragraph as _;
|
use crate::core::text::Paragraph as _;
|
||||||
|
|
||||||
|
|
@ -62,6 +65,7 @@ impl Pipeline {
|
||||||
scale_factor,
|
scale_factor,
|
||||||
pixels,
|
pixels,
|
||||||
clip_mask,
|
clip_mask,
|
||||||
|
transformation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,6 +77,7 @@ impl Pipeline {
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
pixels: &mut tiny_skia::PixmapMut<'_>,
|
pixels: &mut tiny_skia::PixmapMut<'_>,
|
||||||
clip_mask: Option<&tiny_skia::Mask>,
|
clip_mask: Option<&tiny_skia::Mask>,
|
||||||
|
transformation: Transformation,
|
||||||
) {
|
) {
|
||||||
use crate::core::text::Editor as _;
|
use crate::core::text::Editor as _;
|
||||||
|
|
||||||
|
|
@ -93,6 +98,7 @@ impl Pipeline {
|
||||||
scale_factor,
|
scale_factor,
|
||||||
pixels,
|
pixels,
|
||||||
clip_mask,
|
clip_mask,
|
||||||
|
transformation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,6 +116,7 @@ impl Pipeline {
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
pixels: &mut tiny_skia::PixmapMut<'_>,
|
pixels: &mut tiny_skia::PixmapMut<'_>,
|
||||||
clip_mask: Option<&tiny_skia::Mask>,
|
clip_mask: Option<&tiny_skia::Mask>,
|
||||||
|
transformation: Transformation,
|
||||||
) {
|
) {
|
||||||
let line_height = f32::from(line_height.to_absolute(size));
|
let line_height = f32::from(line_height.to_absolute(size));
|
||||||
|
|
||||||
|
|
@ -145,6 +152,7 @@ impl Pipeline {
|
||||||
scale_factor,
|
scale_factor,
|
||||||
pixels,
|
pixels,
|
||||||
clip_mask,
|
clip_mask,
|
||||||
|
transformation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,6 +164,7 @@ impl Pipeline {
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
pixels: &mut tiny_skia::PixmapMut<'_>,
|
pixels: &mut tiny_skia::PixmapMut<'_>,
|
||||||
clip_mask: Option<&tiny_skia::Mask>,
|
clip_mask: Option<&tiny_skia::Mask>,
|
||||||
|
transformation: Transformation,
|
||||||
) {
|
) {
|
||||||
let mut font_system = font_system().write().expect("Write font system");
|
let mut font_system = font_system().write().expect("Write font system");
|
||||||
|
|
||||||
|
|
@ -172,6 +181,7 @@ impl Pipeline {
|
||||||
scale_factor,
|
scale_factor,
|
||||||
pixels,
|
pixels,
|
||||||
clip_mask,
|
clip_mask,
|
||||||
|
transformation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,8 +202,9 @@ fn draw(
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
pixels: &mut tiny_skia::PixmapMut<'_>,
|
pixels: &mut tiny_skia::PixmapMut<'_>,
|
||||||
clip_mask: Option<&tiny_skia::Mask>,
|
clip_mask: Option<&tiny_skia::Mask>,
|
||||||
|
transformation: Transformation,
|
||||||
) {
|
) {
|
||||||
let bounds = bounds * scale_factor;
|
let bounds = bounds * transformation * scale_factor;
|
||||||
|
|
||||||
let x = match horizontal_alignment {
|
let x = match horizontal_alignment {
|
||||||
alignment::Horizontal::Left => bounds.x,
|
alignment::Horizontal::Left => bounds.x,
|
||||||
|
|
@ -211,7 +222,8 @@ fn draw(
|
||||||
|
|
||||||
for run in buffer.layout_runs() {
|
for run in buffer.layout_runs() {
|
||||||
for glyph in run.glyphs {
|
for glyph in run.glyphs {
|
||||||
let physical_glyph = glyph.physical((x, y), scale_factor);
|
let physical_glyph = glyph
|
||||||
|
.physical((x, y), scale_factor * transformation.scale_factor());
|
||||||
|
|
||||||
if let Some((buffer, placement)) = glyph_cache.allocate(
|
if let Some((buffer, placement)) = glyph_cache.allocate(
|
||||||
physical_glyph.cache_key,
|
physical_glyph.cache_key,
|
||||||
|
|
@ -229,7 +241,10 @@ fn draw(
|
||||||
pixels.draw_pixmap(
|
pixels.draw_pixmap(
|
||||||
physical_glyph.x + placement.left,
|
physical_glyph.x + placement.left,
|
||||||
physical_glyph.y - placement.top
|
physical_glyph.y - placement.top
|
||||||
+ (run.line_y * scale_factor).round() as i32,
|
+ (run.line_y
|
||||||
|
* scale_factor
|
||||||
|
* transformation.scale_factor())
|
||||||
|
.round() as i32,
|
||||||
pixmap,
|
pixmap,
|
||||||
&tiny_skia::PixmapPaint::default(),
|
&tiny_skia::PixmapPaint::default(),
|
||||||
tiny_skia::Transform::identity(),
|
tiny_skia::Transform::identity(),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::core::{Color, Size};
|
use crate::core::{Color, Size, Transformation};
|
||||||
use crate::graphics::backend;
|
use crate::graphics::backend;
|
||||||
use crate::graphics::color;
|
use crate::graphics::color;
|
||||||
use crate::graphics::{Transformation, Viewport};
|
use crate::graphics::Viewport;
|
||||||
use crate::primitive::pipeline;
|
use crate::primitive::pipeline;
|
||||||
use crate::primitive::{self, Primitive};
|
use crate::primitive::{self, Primitive};
|
||||||
use crate::quad;
|
use crate::quad;
|
||||||
|
|
@ -147,8 +147,8 @@ impl Backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !layer.meshes.is_empty() {
|
if !layer.meshes.is_empty() {
|
||||||
let scaled = transformation
|
let scaled =
|
||||||
* Transformation::scale(scale_factor, scale_factor);
|
transformation * Transformation::scale(scale_factor);
|
||||||
|
|
||||||
self.triangle_pipeline.prepare(
|
self.triangle_pipeline.prepare(
|
||||||
device,
|
device,
|
||||||
|
|
@ -161,8 +161,8 @@ impl Backend {
|
||||||
#[cfg(any(feature = "image", feature = "svg"))]
|
#[cfg(any(feature = "image", feature = "svg"))]
|
||||||
{
|
{
|
||||||
if !layer.images.is_empty() {
|
if !layer.images.is_empty() {
|
||||||
let scaled = transformation
|
let scaled =
|
||||||
* Transformation::scale(scale_factor, scale_factor);
|
transformation * Transformation::scale(scale_factor);
|
||||||
|
|
||||||
self.image_pipeline.prepare(
|
self.image_pipeline.prepare(
|
||||||
device,
|
device,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//! Build and draw geometry.
|
//! Build and draw geometry.
|
||||||
use crate::core::text::LineHeight;
|
use crate::core::text::LineHeight;
|
||||||
use crate::core::{Pixels, Point, Rectangle, Size, Vector};
|
use crate::core::{Pixels, Point, Rectangle, Size, Transformation, Vector};
|
||||||
use crate::graphics::color;
|
use crate::graphics::color;
|
||||||
use crate::graphics::geometry::fill::{self, Fill};
|
use crate::graphics::geometry::fill::{self, Fill};
|
||||||
use crate::graphics::geometry::{
|
use crate::graphics::geometry::{
|
||||||
|
|
@ -435,7 +435,7 @@ impl Frame {
|
||||||
pub fn clip(&mut self, frame: Frame, at: Point) {
|
pub fn clip(&mut self, frame: Frame, at: Point) {
|
||||||
let size = frame.size();
|
let size = frame.size();
|
||||||
let primitives = frame.into_primitives();
|
let primitives = frame.into_primitives();
|
||||||
let translation = Vector::new(at.x, at.y);
|
let transformation = Transformation::translate(at.x, at.y);
|
||||||
|
|
||||||
let (text, meshes) = primitives
|
let (text, meshes) = primitives
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
@ -443,12 +443,12 @@ impl Frame {
|
||||||
|
|
||||||
self.primitives.push(Primitive::Group {
|
self.primitives.push(Primitive::Group {
|
||||||
primitives: vec![
|
primitives: vec![
|
||||||
Primitive::Translate {
|
Primitive::Transform {
|
||||||
translation,
|
transformation,
|
||||||
content: Box::new(Primitive::Group { primitives: meshes }),
|
content: Box::new(Primitive::Group { primitives: meshes }),
|
||||||
},
|
},
|
||||||
Primitive::Translate {
|
Primitive::Transform {
|
||||||
translation,
|
transformation,
|
||||||
content: Box::new(Primitive::Clip {
|
content: Box::new(Primitive::Clip {
|
||||||
bounds: Rectangle::with_size(size),
|
bounds: Rectangle::with_size(size),
|
||||||
content: Box::new(Primitive::Group {
|
content: Box::new(Primitive::Group {
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@ mod vector;
|
||||||
|
|
||||||
use atlas::Atlas;
|
use atlas::Atlas;
|
||||||
|
|
||||||
use crate::core::{Rectangle, Size};
|
use crate::core::{Rectangle, Size, Transformation};
|
||||||
use crate::graphics::Transformation;
|
|
||||||
use crate::layer;
|
use crate::layer;
|
||||||
use crate::Buffer;
|
use crate::Buffer;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ pub use text::Text;
|
||||||
|
|
||||||
use crate::core;
|
use crate::core;
|
||||||
use crate::core::alignment;
|
use crate::core::alignment;
|
||||||
use crate::core::{Color, Font, Pixels, Point, Rectangle, Size, Vector};
|
use crate::core::{
|
||||||
|
Color, Font, Pixels, Point, Rectangle, Size, Transformation, Vector,
|
||||||
|
};
|
||||||
use crate::graphics;
|
use crate::graphics;
|
||||||
use crate::graphics::color;
|
use crate::graphics::color;
|
||||||
use crate::graphics::Viewport;
|
use crate::graphics::Viewport;
|
||||||
|
|
@ -104,7 +106,7 @@ impl<'a> Layer<'a> {
|
||||||
for primitive in primitives {
|
for primitive in primitives {
|
||||||
Self::process_primitive(
|
Self::process_primitive(
|
||||||
&mut layers,
|
&mut layers,
|
||||||
Vector::new(0.0, 0.0),
|
Transformation::IDENTITY,
|
||||||
primitive,
|
primitive,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
|
|
@ -115,7 +117,7 @@ impl<'a> Layer<'a> {
|
||||||
|
|
||||||
fn process_primitive(
|
fn process_primitive(
|
||||||
layers: &mut Vec<Self>,
|
layers: &mut Vec<Self>,
|
||||||
translation: Vector,
|
transformation: Transformation,
|
||||||
primitive: &'a Primitive,
|
primitive: &'a Primitive,
|
||||||
current_layer: usize,
|
current_layer: usize,
|
||||||
) {
|
) {
|
||||||
|
|
@ -130,9 +132,10 @@ impl<'a> Layer<'a> {
|
||||||
|
|
||||||
layer.text.push(Text::Paragraph {
|
layer.text.push(Text::Paragraph {
|
||||||
paragraph: paragraph.clone(),
|
paragraph: paragraph.clone(),
|
||||||
position: *position + translation,
|
position: *position,
|
||||||
color: *color,
|
color: *color,
|
||||||
clip_bounds: *clip_bounds + translation,
|
clip_bounds: *clip_bounds,
|
||||||
|
transformation,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Primitive::Editor {
|
Primitive::Editor {
|
||||||
|
|
@ -145,9 +148,10 @@ impl<'a> Layer<'a> {
|
||||||
|
|
||||||
layer.text.push(Text::Editor {
|
layer.text.push(Text::Editor {
|
||||||
editor: editor.clone(),
|
editor: editor.clone(),
|
||||||
position: *position + translation,
|
position: *position,
|
||||||
color: *color,
|
color: *color,
|
||||||
clip_bounds: *clip_bounds + translation,
|
clip_bounds: *clip_bounds,
|
||||||
|
transformation,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Primitive::Text {
|
Primitive::Text {
|
||||||
|
|
@ -166,31 +170,24 @@ impl<'a> Layer<'a> {
|
||||||
|
|
||||||
layer.text.push(Text::Cached(text::Cached {
|
layer.text.push(Text::Cached(text::Cached {
|
||||||
content,
|
content,
|
||||||
bounds: *bounds + translation,
|
bounds: *bounds + transformation.translation(),
|
||||||
size: *size,
|
size: *size * transformation.scale_factor(),
|
||||||
line_height: *line_height,
|
line_height: *line_height,
|
||||||
color: *color,
|
color: *color,
|
||||||
font: *font,
|
font: *font,
|
||||||
horizontal_alignment: *horizontal_alignment,
|
horizontal_alignment: *horizontal_alignment,
|
||||||
vertical_alignment: *vertical_alignment,
|
vertical_alignment: *vertical_alignment,
|
||||||
shaping: *shaping,
|
shaping: *shaping,
|
||||||
clip_bounds: *clip_bounds + translation,
|
clip_bounds: *clip_bounds * transformation,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
graphics::Primitive::RawText(graphics::text::Raw {
|
graphics::Primitive::RawText(raw) => {
|
||||||
buffer,
|
|
||||||
position,
|
|
||||||
color,
|
|
||||||
clip_bounds,
|
|
||||||
}) => {
|
|
||||||
let layer = &mut layers[current_layer];
|
let layer = &mut layers[current_layer];
|
||||||
|
|
||||||
layer.text.push(Text::Raw(graphics::text::Raw {
|
layer.text.push(Text::Raw {
|
||||||
buffer: buffer.clone(),
|
raw: raw.clone(),
|
||||||
position: *position + translation,
|
transformation,
|
||||||
color: *color,
|
});
|
||||||
clip_bounds: *clip_bounds + translation,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
Primitive::Quad {
|
Primitive::Quad {
|
||||||
bounds,
|
bounds,
|
||||||
|
|
@ -199,12 +196,10 @@ impl<'a> Layer<'a> {
|
||||||
shadow,
|
shadow,
|
||||||
} => {
|
} => {
|
||||||
let layer = &mut layers[current_layer];
|
let layer = &mut layers[current_layer];
|
||||||
|
let bounds = *bounds * transformation;
|
||||||
|
|
||||||
let quad = Quad {
|
let quad = Quad {
|
||||||
position: [
|
position: [bounds.x, bounds.y],
|
||||||
bounds.x + translation.x,
|
|
||||||
bounds.y + translation.y,
|
|
||||||
],
|
|
||||||
size: [bounds.width, bounds.height],
|
size: [bounds.width, bounds.height],
|
||||||
border_color: color::pack(border.color),
|
border_color: color::pack(border.color),
|
||||||
border_radius: border.radius.into(),
|
border_radius: border.radius.into(),
|
||||||
|
|
@ -226,7 +221,7 @@ impl<'a> Layer<'a> {
|
||||||
layer.images.push(Image::Raster {
|
layer.images.push(Image::Raster {
|
||||||
handle: handle.clone(),
|
handle: handle.clone(),
|
||||||
filter_method: *filter_method,
|
filter_method: *filter_method,
|
||||||
bounds: *bounds + translation,
|
bounds: *bounds * transformation,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Primitive::Svg {
|
Primitive::Svg {
|
||||||
|
|
@ -239,7 +234,7 @@ impl<'a> Layer<'a> {
|
||||||
layer.images.push(Image::Vector {
|
layer.images.push(Image::Vector {
|
||||||
handle: handle.clone(),
|
handle: handle.clone(),
|
||||||
color: *color,
|
color: *color,
|
||||||
bounds: *bounds + translation,
|
bounds: *bounds * transformation,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Primitive::Group { primitives } => {
|
Primitive::Group { primitives } => {
|
||||||
|
|
@ -247,7 +242,7 @@ impl<'a> Layer<'a> {
|
||||||
for primitive in primitives {
|
for primitive in primitives {
|
||||||
Self::process_primitive(
|
Self::process_primitive(
|
||||||
layers,
|
layers,
|
||||||
translation,
|
transformation,
|
||||||
primitive,
|
primitive,
|
||||||
current_layer,
|
current_layer,
|
||||||
);
|
);
|
||||||
|
|
@ -255,7 +250,7 @@ impl<'a> Layer<'a> {
|
||||||
}
|
}
|
||||||
Primitive::Clip { bounds, content } => {
|
Primitive::Clip { bounds, content } => {
|
||||||
let layer = &mut layers[current_layer];
|
let layer = &mut layers[current_layer];
|
||||||
let translated_bounds = *bounds + translation;
|
let translated_bounds = *bounds * transformation;
|
||||||
|
|
||||||
// Only draw visible content
|
// Only draw visible content
|
||||||
if let Some(clip_bounds) =
|
if let Some(clip_bounds) =
|
||||||
|
|
@ -266,19 +261,19 @@ impl<'a> Layer<'a> {
|
||||||
|
|
||||||
Self::process_primitive(
|
Self::process_primitive(
|
||||||
layers,
|
layers,
|
||||||
translation,
|
transformation,
|
||||||
content,
|
content,
|
||||||
layers.len() - 1,
|
layers.len() - 1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Primitive::Translate {
|
Primitive::Transform {
|
||||||
translation: new_translation,
|
transformation: new_transformation,
|
||||||
content,
|
content,
|
||||||
} => {
|
} => {
|
||||||
Self::process_primitive(
|
Self::process_primitive(
|
||||||
layers,
|
layers,
|
||||||
translation + *new_translation,
|
transformation * *new_transformation,
|
||||||
content,
|
content,
|
||||||
current_layer,
|
current_layer,
|
||||||
);
|
);
|
||||||
|
|
@ -286,7 +281,7 @@ impl<'a> Layer<'a> {
|
||||||
Primitive::Cache { content } => {
|
Primitive::Cache { content } => {
|
||||||
Self::process_primitive(
|
Self::process_primitive(
|
||||||
layers,
|
layers,
|
||||||
translation,
|
transformation,
|
||||||
content,
|
content,
|
||||||
current_layer,
|
current_layer,
|
||||||
);
|
);
|
||||||
|
|
@ -296,20 +291,15 @@ impl<'a> Layer<'a> {
|
||||||
graphics::Mesh::Solid { buffers, size } => {
|
graphics::Mesh::Solid { buffers, size } => {
|
||||||
let layer = &mut layers[current_layer];
|
let layer = &mut layers[current_layer];
|
||||||
|
|
||||||
let bounds = Rectangle::new(
|
let bounds =
|
||||||
Point::new(translation.x, translation.y),
|
Rectangle::with_size(*size) * transformation;
|
||||||
*size,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Only draw visible content
|
// Only draw visible content
|
||||||
if let Some(clip_bounds) =
|
if let Some(clip_bounds) =
|
||||||
layer.bounds.intersection(&bounds)
|
layer.bounds.intersection(&bounds)
|
||||||
{
|
{
|
||||||
layer.meshes.push(Mesh::Solid {
|
layer.meshes.push(Mesh::Solid {
|
||||||
origin: Point::new(
|
transformation,
|
||||||
translation.x,
|
|
||||||
translation.y,
|
|
||||||
),
|
|
||||||
buffers,
|
buffers,
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
});
|
});
|
||||||
|
|
@ -318,20 +308,15 @@ impl<'a> Layer<'a> {
|
||||||
graphics::Mesh::Gradient { buffers, size } => {
|
graphics::Mesh::Gradient { buffers, size } => {
|
||||||
let layer = &mut layers[current_layer];
|
let layer = &mut layers[current_layer];
|
||||||
|
|
||||||
let bounds = Rectangle::new(
|
let bounds =
|
||||||
Point::new(translation.x, translation.y),
|
Rectangle::with_size(*size) * transformation;
|
||||||
*size,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Only draw visible content
|
// Only draw visible content
|
||||||
if let Some(clip_bounds) =
|
if let Some(clip_bounds) =
|
||||||
layer.bounds.intersection(&bounds)
|
layer.bounds.intersection(&bounds)
|
||||||
{
|
{
|
||||||
layer.meshes.push(Mesh::Gradient {
|
layer.meshes.push(Mesh::Gradient {
|
||||||
origin: Point::new(
|
transformation,
|
||||||
translation.x,
|
|
||||||
translation.y,
|
|
||||||
),
|
|
||||||
buffers,
|
buffers,
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
});
|
});
|
||||||
|
|
@ -340,7 +325,7 @@ impl<'a> Layer<'a> {
|
||||||
},
|
},
|
||||||
primitive::Custom::Pipeline(pipeline) => {
|
primitive::Custom::Pipeline(pipeline) => {
|
||||||
let layer = &mut layers[current_layer];
|
let layer = &mut layers[current_layer];
|
||||||
let bounds = pipeline.bounds + translation;
|
let bounds = pipeline.bounds * transformation;
|
||||||
|
|
||||||
if let Some(clip_bounds) =
|
if let Some(clip_bounds) =
|
||||||
layer.bounds.intersection(&bounds)
|
layer.bounds.intersection(&bounds)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
//! A collection of triangle primitives.
|
//! A collection of triangle primitives.
|
||||||
use crate::core::{Point, Rectangle};
|
use crate::core::{Rectangle, Transformation};
|
||||||
use crate::graphics::mesh;
|
use crate::graphics::mesh;
|
||||||
|
|
||||||
/// A mesh of triangles.
|
/// A mesh of triangles.
|
||||||
|
|
@ -7,8 +7,8 @@ use crate::graphics::mesh;
|
||||||
pub enum Mesh<'a> {
|
pub enum Mesh<'a> {
|
||||||
/// A mesh of triangles with a solid color.
|
/// A mesh of triangles with a solid color.
|
||||||
Solid {
|
Solid {
|
||||||
/// The origin of the vertices of the [`Mesh`].
|
/// The [`Transformation`] for the vertices of the [`Mesh`].
|
||||||
origin: Point,
|
transformation: Transformation,
|
||||||
|
|
||||||
/// The vertex and index buffers of the [`Mesh`].
|
/// The vertex and index buffers of the [`Mesh`].
|
||||||
buffers: &'a mesh::Indexed<mesh::SolidVertex2D>,
|
buffers: &'a mesh::Indexed<mesh::SolidVertex2D>,
|
||||||
|
|
@ -18,8 +18,8 @@ pub enum Mesh<'a> {
|
||||||
},
|
},
|
||||||
/// A mesh of triangles with a gradient color.
|
/// A mesh of triangles with a gradient color.
|
||||||
Gradient {
|
Gradient {
|
||||||
/// The origin of the vertices of the [`Mesh`].
|
/// The [`Transformation`] for the vertices of the [`Mesh`].
|
||||||
origin: Point,
|
transformation: Transformation,
|
||||||
|
|
||||||
/// The vertex and index buffers of the [`Mesh`].
|
/// The vertex and index buffers of the [`Mesh`].
|
||||||
buffers: &'a mesh::Indexed<mesh::GradientVertex2D>,
|
buffers: &'a mesh::Indexed<mesh::GradientVertex2D>,
|
||||||
|
|
@ -31,11 +31,10 @@ pub enum Mesh<'a> {
|
||||||
|
|
||||||
impl Mesh<'_> {
|
impl Mesh<'_> {
|
||||||
/// Returns the origin of the [`Mesh`].
|
/// Returns the origin of the [`Mesh`].
|
||||||
pub fn origin(&self) -> Point {
|
pub fn transformation(&self) -> Transformation {
|
||||||
match self {
|
match self {
|
||||||
Self::Solid { origin, .. } | Self::Gradient { origin, .. } => {
|
Self::Solid { transformation, .. }
|
||||||
*origin
|
| Self::Gradient { transformation, .. } => *transformation,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::core::alignment;
|
use crate::core::alignment;
|
||||||
use crate::core::text;
|
use crate::core::text;
|
||||||
use crate::core::{Color, Font, Pixels, Point, Rectangle};
|
use crate::core::{Color, Font, Pixels, Point, Rectangle, Transformation};
|
||||||
use crate::graphics;
|
use crate::graphics;
|
||||||
use crate::graphics::text::editor;
|
use crate::graphics::text::editor;
|
||||||
use crate::graphics::text::paragraph;
|
use crate::graphics::text::paragraph;
|
||||||
|
|
@ -15,6 +15,7 @@ pub enum Text<'a> {
|
||||||
position: Point,
|
position: Point,
|
||||||
color: Color,
|
color: Color,
|
||||||
clip_bounds: Rectangle,
|
clip_bounds: Rectangle,
|
||||||
|
transformation: Transformation,
|
||||||
},
|
},
|
||||||
/// An editor.
|
/// An editor.
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
|
@ -23,11 +24,16 @@ pub enum Text<'a> {
|
||||||
position: Point,
|
position: Point,
|
||||||
color: Color,
|
color: Color,
|
||||||
clip_bounds: Rectangle,
|
clip_bounds: Rectangle,
|
||||||
|
transformation: Transformation,
|
||||||
},
|
},
|
||||||
/// Some cached text.
|
/// Some cached text.
|
||||||
Cached(Cached<'a>),
|
Cached(Cached<'a>),
|
||||||
/// Some raw text.
|
/// Some raw text.
|
||||||
Raw(graphics::text::Raw),
|
#[allow(missing_docs)]
|
||||||
|
Raw {
|
||||||
|
raw: graphics::text::Raw,
|
||||||
|
transformation: Transformation,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ mod solid;
|
||||||
use gradient::Gradient;
|
use gradient::Gradient;
|
||||||
use solid::Solid;
|
use solid::Solid;
|
||||||
|
|
||||||
use crate::core::{Background, Rectangle};
|
use crate::core::{Background, Rectangle, Transformation};
|
||||||
|
use crate::graphics;
|
||||||
use crate::graphics::color;
|
use crate::graphics::color;
|
||||||
use crate::graphics::{self, Transformation};
|
|
||||||
|
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
|
||||||
|
|
@ -319,7 +319,7 @@ impl Uniforms {
|
||||||
impl Default for Uniforms {
|
impl Default for Uniforms {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
transform: *Transformation::identity().as_ref(),
|
transform: *Transformation::IDENTITY.as_ref(),
|
||||||
scale: 1.0,
|
scale: 1.0,
|
||||||
_padding: [0.0; 3],
|
_padding: [0.0; 3],
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::core::alignment;
|
use crate::core::alignment;
|
||||||
use crate::core::{Rectangle, Size};
|
use crate::core::{Rectangle, Size, Transformation};
|
||||||
use crate::graphics::color;
|
use crate::graphics::color;
|
||||||
use crate::graphics::text::cache::{self, Cache};
|
use crate::graphics::text::cache::{self, Cache};
|
||||||
use crate::graphics::text::{font_system, to_color, Editor, Paragraph};
|
use crate::graphics::text::{font_system, to_color, Editor, Paragraph};
|
||||||
|
|
@ -109,7 +109,9 @@ impl Pipeline {
|
||||||
|
|
||||||
Some(Allocation::Cache(key))
|
Some(Allocation::Cache(key))
|
||||||
}
|
}
|
||||||
Text::Raw(text) => text.buffer.upgrade().map(Allocation::Raw),
|
Text::Raw { raw, .. } => {
|
||||||
|
raw.buffer.upgrade().map(Allocation::Raw)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
@ -124,11 +126,13 @@ impl Pipeline {
|
||||||
vertical_alignment,
|
vertical_alignment,
|
||||||
color,
|
color,
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
|
transformation,
|
||||||
) = match section {
|
) = match section {
|
||||||
Text::Paragraph {
|
Text::Paragraph {
|
||||||
position,
|
position,
|
||||||
color,
|
color,
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
|
transformation,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
use crate::core::text::Paragraph as _;
|
use crate::core::text::Paragraph as _;
|
||||||
|
|
@ -145,12 +149,14 @@ impl Pipeline {
|
||||||
paragraph.vertical_alignment(),
|
paragraph.vertical_alignment(),
|
||||||
*color,
|
*color,
|
||||||
*clip_bounds,
|
*clip_bounds,
|
||||||
|
*transformation,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text::Editor {
|
Text::Editor {
|
||||||
position,
|
position,
|
||||||
color,
|
color,
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
|
transformation,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
use crate::core::text::Editor as _;
|
use crate::core::text::Editor as _;
|
||||||
|
|
@ -167,6 +173,7 @@ impl Pipeline {
|
||||||
alignment::Vertical::Top,
|
alignment::Vertical::Top,
|
||||||
*color,
|
*color,
|
||||||
*clip_bounds,
|
*clip_bounds,
|
||||||
|
*transformation,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text::Cached(text) => {
|
Text::Cached(text) => {
|
||||||
|
|
@ -186,9 +193,13 @@ impl Pipeline {
|
||||||
text.vertical_alignment,
|
text.vertical_alignment,
|
||||||
text.color,
|
text.color,
|
||||||
text.clip_bounds,
|
text.clip_bounds,
|
||||||
|
Transformation::IDENTITY,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text::Raw(text) => {
|
Text::Raw {
|
||||||
|
raw,
|
||||||
|
transformation,
|
||||||
|
} => {
|
||||||
let Some(Allocation::Raw(buffer)) = allocation else {
|
let Some(Allocation::Raw(buffer)) = allocation else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
@ -198,18 +209,19 @@ impl Pipeline {
|
||||||
(
|
(
|
||||||
buffer.as_ref(),
|
buffer.as_ref(),
|
||||||
Rectangle::new(
|
Rectangle::new(
|
||||||
text.position,
|
raw.position,
|
||||||
Size::new(width, height),
|
Size::new(width, height),
|
||||||
),
|
),
|
||||||
alignment::Horizontal::Left,
|
alignment::Horizontal::Left,
|
||||||
alignment::Vertical::Top,
|
alignment::Vertical::Top,
|
||||||
text.color,
|
raw.color,
|
||||||
text.clip_bounds,
|
raw.clip_bounds,
|
||||||
|
*transformation,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let bounds = bounds * scale_factor;
|
let bounds = bounds * transformation * scale_factor;
|
||||||
|
|
||||||
let left = match horizontal_alignment {
|
let left = match horizontal_alignment {
|
||||||
alignment::Horizontal::Left => bounds.x,
|
alignment::Horizontal::Left => bounds.x,
|
||||||
|
|
@ -227,14 +239,15 @@ impl Pipeline {
|
||||||
alignment::Vertical::Bottom => bounds.y - bounds.height,
|
alignment::Vertical::Bottom => bounds.y - bounds.height,
|
||||||
};
|
};
|
||||||
|
|
||||||
let clip_bounds =
|
let clip_bounds = layer_bounds.intersection(
|
||||||
layer_bounds.intersection(&(clip_bounds * scale_factor))?;
|
&(clip_bounds * transformation * scale_factor),
|
||||||
|
)?;
|
||||||
|
|
||||||
Some(glyphon::TextArea {
|
Some(glyphon::TextArea {
|
||||||
buffer,
|
buffer,
|
||||||
left,
|
left,
|
||||||
top,
|
top,
|
||||||
scale: scale_factor,
|
scale: scale_factor * transformation.scale_factor(),
|
||||||
bounds: glyphon::TextBounds {
|
bounds: glyphon::TextBounds {
|
||||||
left: clip_bounds.x as i32,
|
left: clip_bounds.x as i32,
|
||||||
top: clip_bounds.y as i32,
|
top: clip_bounds.y as i32,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
//! Draw meshes of triangles.
|
//! Draw meshes of triangles.
|
||||||
mod msaa;
|
mod msaa;
|
||||||
|
|
||||||
use crate::core::Size;
|
use crate::core::{Size, Transformation};
|
||||||
use crate::graphics::{Antialiasing, Transformation};
|
use crate::graphics::Antialiasing;
|
||||||
use crate::layer::mesh::{self, Mesh};
|
use crate::layer::mesh::{self, Mesh};
|
||||||
use crate::Buffer;
|
use crate::Buffer;
|
||||||
|
|
||||||
|
|
@ -98,12 +98,10 @@ impl Layer {
|
||||||
let mut index_offset = 0;
|
let mut index_offset = 0;
|
||||||
|
|
||||||
for mesh in meshes {
|
for mesh in meshes {
|
||||||
let origin = mesh.origin();
|
|
||||||
let indices = mesh.indices();
|
let indices = mesh.indices();
|
||||||
|
|
||||||
let uniforms = Uniforms::new(
|
let uniforms =
|
||||||
transformation * Transformation::translate(origin.x, origin.y),
|
Uniforms::new(transformation * mesh.transformation());
|
||||||
);
|
|
||||||
|
|
||||||
index_offset +=
|
index_offset +=
|
||||||
self.index_buffer.write(queue, index_offset, indices);
|
self.index_buffer.write(queue, index_offset, indices);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use crate::core::mouse;
|
||||||
use crate::core::renderer;
|
use crate::core::renderer;
|
||||||
use crate::core::widget::tree::{self, Tree};
|
use crate::core::widget::tree::{self, Tree};
|
||||||
use crate::core::{
|
use crate::core::{
|
||||||
Clipboard, Element, Length, Rectangle, Shell, Size, Vector, Widget,
|
Clipboard, Element, Length, Rectangle, Shell, Size, Transformation, Widget,
|
||||||
};
|
};
|
||||||
use crate::graphics::geometry;
|
use crate::graphics::geometry;
|
||||||
|
|
||||||
|
|
@ -207,8 +207,8 @@ where
|
||||||
|
|
||||||
let state = tree.state.downcast_ref::<P::State>();
|
let state = tree.state.downcast_ref::<P::State>();
|
||||||
|
|
||||||
renderer.with_translation(
|
renderer.with_transformation(
|
||||||
Vector::new(bounds.x, bounds.y),
|
Transformation::translate(bounds.x, bounds.y),
|
||||||
|renderer| {
|
|renderer| {
|
||||||
renderer.draw(
|
renderer.draw(
|
||||||
self.program.draw(state, renderer, theme, bounds, cursor),
|
self.program.draw(state, renderer, theme, bounds, cursor),
|
||||||
|
|
|
||||||
|
|
@ -962,22 +962,21 @@ pub fn draw<Theme, Renderer, T>(
|
||||||
if let Some(cursor_position) = cursor.position() {
|
if let Some(cursor_position) = cursor.position() {
|
||||||
let bounds = layout.bounds();
|
let bounds = layout.bounds();
|
||||||
|
|
||||||
renderer.with_translation(
|
let translation = cursor_position
|
||||||
cursor_position
|
- Point::new(bounds.x + origin.x, bounds.y + origin.y);
|
||||||
- Point::new(bounds.x + origin.x, bounds.y + origin.y),
|
|
||||||
|renderer| {
|
renderer.with_translation(translation, |renderer| {
|
||||||
renderer.with_layer(bounds, |renderer| {
|
renderer.with_layer(bounds, |renderer| {
|
||||||
draw_pane(
|
draw_pane(
|
||||||
pane,
|
pane,
|
||||||
renderer,
|
renderer,
|
||||||
default_style,
|
default_style,
|
||||||
layout,
|
layout,
|
||||||
pane_cursor,
|
pane_cursor,
|
||||||
viewport,
|
viewport,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,11 +119,12 @@ impl<'a, Message, Theme> Widget<Message, Theme, Renderer> for QRCode<'a> {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let translation = Vector::new(bounds.x, bounds.y);
|
renderer.with_translation(
|
||||||
|
bounds.position() - Point::ORIGIN,
|
||||||
renderer.with_translation(translation, |renderer| {
|
|renderer| {
|
||||||
renderer.draw(vec![geometry]);
|
renderer.draw(vec![geometry]);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -385,6 +385,7 @@ pub fn mouse_interaction(
|
||||||
}
|
}
|
||||||
Interaction::ResizingVertically => winit::window::CursorIcon::NsResize,
|
Interaction::ResizingVertically => winit::window::CursorIcon::NsResize,
|
||||||
Interaction::NotAllowed => winit::window::CursorIcon::NotAllowed,
|
Interaction::NotAllowed => winit::window::CursorIcon::NotAllowed,
|
||||||
|
Interaction::ZoomIn => winit::window::CursorIcon::ZoomIn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue