Introduce draw_with_bounds to canvas::Cache
Also: - Change `Rectangle::INFINITE` to have coordinates at `f32::NEG_INFINITY` - Change `Frame::with_clip` to _not_ adjust the coordinate system - Rename `Size::INFINITY` to `INFINITE`
This commit is contained in:
parent
c1f7345ceb
commit
f2aa570aac
13 changed files with 56 additions and 45 deletions
|
|
@ -12,7 +12,7 @@ impl Limits {
|
||||||
/// No limits
|
/// No limits
|
||||||
pub const NONE: Limits = Limits {
|
pub const NONE: Limits = Limits {
|
||||||
min: Size::ZERO,
|
min: Size::ZERO,
|
||||||
max: Size::INFINITY,
|
max: Size::INFINITE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Creates new [`Limits`] with the given minimum and maximum [`Size`].
|
/// Creates new [`Limits`] with the given minimum and maximum [`Size`].
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,11 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rectangle<f32> {
|
impl Rectangle<f32> {
|
||||||
/// A rectangle starting at [`Point::ORIGIN`] with infinite width and height.
|
/// A rectangle starting at negative infinity and with infinite width and height.
|
||||||
pub const INFINITE: Self = Self::new(Point::ORIGIN, Size::INFINITY);
|
pub const INFINITE: Self = Self::new(
|
||||||
|
Point::new(f32::NEG_INFINITY, f32::NEG_INFINITY),
|
||||||
|
Size::INFINITE,
|
||||||
|
);
|
||||||
|
|
||||||
/// Creates a new [`Rectangle`] with its top-left corner in the given
|
/// Creates a new [`Rectangle`] with its top-left corner in the given
|
||||||
/// [`Point`] and with the provided [`Size`].
|
/// [`Point`] and with the provided [`Size`].
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ impl Size {
|
||||||
pub const UNIT: Size = Size::new(1., 1.);
|
pub const UNIT: Size = Size::new(1., 1.);
|
||||||
|
|
||||||
/// A [`Size`] with infinite width and height.
|
/// A [`Size`] with infinite width and height.
|
||||||
pub const INFINITY: Size = Size::new(f32::INFINITY, f32::INFINITY);
|
pub const INFINITE: Size = Size::new(f32::INFINITY, f32::INFINITY);
|
||||||
|
|
||||||
/// Returns the minimum of each component of this size and another.
|
/// Returns the minimum of each component of this size and another.
|
||||||
pub fn min(self, other: Self) -> Self {
|
pub fn min(self, other: Self) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ pub use crate::core::{Image, Svg};
|
||||||
pub use crate::gradient::{self, Gradient};
|
pub use crate::gradient::{self, Gradient};
|
||||||
|
|
||||||
use crate::cache::Cached;
|
use crate::cache::Cached;
|
||||||
use crate::core::{self, Size};
|
use crate::core::{self, Rectangle};
|
||||||
|
|
||||||
/// A renderer capable of drawing some [`Self::Geometry`].
|
/// A renderer capable of drawing some [`Self::Geometry`].
|
||||||
pub trait Renderer: core::Renderer {
|
pub trait Renderer: core::Renderer {
|
||||||
|
|
@ -31,7 +31,7 @@ pub trait Renderer: core::Renderer {
|
||||||
type Frame: frame::Backend<Geometry = Self::Geometry>;
|
type Frame: frame::Backend<Geometry = Self::Geometry>;
|
||||||
|
|
||||||
/// Creates a new [`Self::Frame`].
|
/// Creates a new [`Self::Frame`].
|
||||||
fn new_frame(&self, size: Size) -> Self::Frame;
|
fn new_frame(&self, bounds: Rectangle) -> Self::Frame;
|
||||||
|
|
||||||
/// Draws the given [`Self::Geometry`].
|
/// Draws the given [`Self::Geometry`].
|
||||||
fn draw_geometry(&mut self, geometry: Self::Geometry);
|
fn draw_geometry(&mut self, geometry: Self::Geometry);
|
||||||
|
|
@ -42,7 +42,7 @@ impl Renderer for () {
|
||||||
type Geometry = ();
|
type Geometry = ();
|
||||||
type Frame = ();
|
type Frame = ();
|
||||||
|
|
||||||
fn new_frame(&self, _size: Size) -> Self::Frame {}
|
fn new_frame(&self, _bounds: Rectangle) -> Self::Frame {}
|
||||||
|
|
||||||
fn draw_geometry(&mut self, _geometry: Self::Geometry) {}
|
fn draw_geometry(&mut self, _geometry: Self::Geometry) {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::cache::{self, Cached};
|
use crate::cache::{self, Cached};
|
||||||
use crate::core::Size;
|
use crate::core::{Rectangle, Size};
|
||||||
use crate::geometry::{self, Frame};
|
use crate::geometry::{self, Frame};
|
||||||
|
|
||||||
pub use cache::Group;
|
pub use cache::Group;
|
||||||
|
|
@ -17,7 +17,7 @@ where
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct Data<T> {
|
struct Data<T> {
|
||||||
bounds: Size,
|
bounds: Rectangle,
|
||||||
geometry: T,
|
geometry: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ where
|
||||||
/// [`Cache`].
|
/// [`Cache`].
|
||||||
///
|
///
|
||||||
/// The closure will only be called when
|
/// The closure will only be called when
|
||||||
/// - the bounds have changed since the previous draw call.
|
/// - the size has changed since the previous draw call.
|
||||||
/// - the [`Cache`] is empty or has been explicitly cleared.
|
/// - the [`Cache`] is empty or has been explicitly cleared.
|
||||||
///
|
///
|
||||||
/// Otherwise, the previously stored geometry will be returned. The
|
/// Otherwise, the previously stored geometry will be returned. The
|
||||||
|
|
@ -62,7 +62,21 @@ where
|
||||||
pub fn draw(
|
pub fn draw(
|
||||||
&self,
|
&self,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
bounds: Size,
|
size: Size,
|
||||||
|
draw_fn: impl FnOnce(&mut Frame<Renderer>),
|
||||||
|
) -> Renderer::Geometry {
|
||||||
|
self.draw_with_bounds(renderer, Rectangle::with_size(size), draw_fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draws geometry using the provided closure and stores it in the
|
||||||
|
/// [`Cache`].
|
||||||
|
///
|
||||||
|
/// Analogous to [`draw`](Self::draw), but takes a clipping [`Rectangle`] instead of
|
||||||
|
/// a [`Size`].
|
||||||
|
pub fn draw_with_bounds(
|
||||||
|
&self,
|
||||||
|
renderer: &Renderer,
|
||||||
|
bounds: Rectangle,
|
||||||
draw_fn: impl FnOnce(&mut Frame<Renderer>),
|
draw_fn: impl FnOnce(&mut Frame<Renderer>),
|
||||||
) -> Renderer::Geometry {
|
) -> Renderer::Geometry {
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
@ -82,7 +96,7 @@ where
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut frame = Frame::new(renderer, bounds);
|
let mut frame = Frame::with_bounds(renderer, bounds);
|
||||||
draw_fn(&mut frame);
|
draw_fn(&mut frame);
|
||||||
|
|
||||||
let geometry = frame.into_geometry().cache(self.raw.group(), previous);
|
let geometry = frame.into_geometry().cache(self.raw.group(), previous);
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,17 @@ where
|
||||||
Renderer: geometry::Renderer,
|
Renderer: geometry::Renderer,
|
||||||
{
|
{
|
||||||
/// Creates a new [`Frame`] with the given dimensions.
|
/// Creates a new [`Frame`] with the given dimensions.
|
||||||
|
///
|
||||||
|
/// Any geometry drawn outside of the dimensions will be clipped.
|
||||||
|
/// If you need further control, use [`with_bounds`](Self::with_bounds).
|
||||||
pub fn new(renderer: &Renderer, size: Size) -> Self {
|
pub fn new(renderer: &Renderer, size: Size) -> Self {
|
||||||
|
Self::with_bounds(renderer, Rectangle::with_size(size))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new [`Frame`] with the given clip bounds.
|
||||||
|
pub fn with_bounds(renderer: &Renderer, bounds: Rectangle) -> Self {
|
||||||
Self {
|
Self {
|
||||||
raw: renderer.new_frame(size),
|
raw: renderer.new_frame(bounds),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -409,13 +409,13 @@ mod geometry {
|
||||||
type Geometry = Geometry<A::Geometry, B::Geometry>;
|
type Geometry = Geometry<A::Geometry, B::Geometry>;
|
||||||
type Frame = Frame<A::Frame, B::Frame>;
|
type Frame = Frame<A::Frame, B::Frame>;
|
||||||
|
|
||||||
fn new_frame(&self, size: iced_graphics::core::Size) -> Self::Frame {
|
fn new_frame(&self, bounds: Rectangle) -> Self::Frame {
|
||||||
match self {
|
match self {
|
||||||
Self::Primary(renderer) => {
|
Self::Primary(renderer) => {
|
||||||
Frame::Primary(renderer.new_frame(size))
|
Frame::Primary(renderer.new_frame(bounds))
|
||||||
}
|
}
|
||||||
Self::Secondary(renderer) => {
|
Self::Secondary(renderer) => {
|
||||||
Frame::Secondary(renderer.new_frame(size))
|
Frame::Secondary(renderer.new_frame(bounds))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,21 +64,14 @@ pub struct Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Frame {
|
impl Frame {
|
||||||
pub fn new(size: Size) -> Self {
|
pub fn new(bounds: Rectangle) -> Self {
|
||||||
Self::with_clip(Rectangle::with_size(size))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_clip(clip_bounds: Rectangle) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
clip_bounds,
|
clip_bounds: bounds,
|
||||||
stack: Vec::new(),
|
stack: Vec::new(),
|
||||||
primitives: Vec::new(),
|
primitives: Vec::new(),
|
||||||
images: Vec::new(),
|
images: Vec::new(),
|
||||||
text: Vec::new(),
|
text: Vec::new(),
|
||||||
transform: tiny_skia::Transform::from_translate(
|
transform: tiny_skia::Transform::identity(),
|
||||||
clip_bounds.x,
|
|
||||||
clip_bounds.y,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -238,7 +231,7 @@ impl geometry::frame::Backend for Frame {
|
||||||
align_x: text.align_x,
|
align_x: text.align_x,
|
||||||
align_y: text.align_y,
|
align_y: text.align_y,
|
||||||
shaping: text.shaping,
|
shaping: text.shaping,
|
||||||
clip_bounds: Rectangle::with_size(Size::INFINITY),
|
clip_bounds: Rectangle::with_size(Size::INFINITE),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
text.draw_with(|path, color| self.fill(&path, color));
|
text.draw_with(|path, color| self.fill(&path, color));
|
||||||
|
|
@ -265,7 +258,7 @@ impl geometry::frame::Backend for Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draft(&mut self, clip_bounds: Rectangle) -> Self {
|
fn draft(&mut self, clip_bounds: Rectangle) -> Self {
|
||||||
Self::with_clip(clip_bounds)
|
Self::new(clip_bounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paste(&mut self, frame: Self) {
|
fn paste(&mut self, frame: Self) {
|
||||||
|
|
|
||||||
|
|
@ -294,8 +294,8 @@ impl graphics::geometry::Renderer for Renderer {
|
||||||
type Geometry = Geometry;
|
type Geometry = Geometry;
|
||||||
type Frame = geometry::Frame;
|
type Frame = geometry::Frame;
|
||||||
|
|
||||||
fn new_frame(&self, size: core::Size) -> Self::Frame {
|
fn new_frame(&self, bounds: Rectangle) -> Self::Frame {
|
||||||
geometry::Frame::new(size)
|
geometry::Frame::new(bounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_geometry(&mut self, geometry: Self::Geometry) {
|
fn draw_geometry(&mut self, geometry: Self::Geometry) {
|
||||||
|
|
|
||||||
|
|
@ -105,13 +105,8 @@ pub struct Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Frame {
|
impl Frame {
|
||||||
/// Creates a new [`Frame`] with the given [`Size`].
|
|
||||||
pub fn new(size: Size) -> Frame {
|
|
||||||
Self::with_clip(Rectangle::with_size(size))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new [`Frame`] with the given clip bounds.
|
/// Creates a new [`Frame`] with the given clip bounds.
|
||||||
pub fn with_clip(bounds: Rectangle) -> Frame {
|
pub fn new(bounds: Rectangle) -> Frame {
|
||||||
Frame {
|
Frame {
|
||||||
clip_bounds: bounds,
|
clip_bounds: bounds,
|
||||||
buffers: BufferStack::new(),
|
buffers: BufferStack::new(),
|
||||||
|
|
@ -120,9 +115,7 @@ impl Frame {
|
||||||
text: Vec::new(),
|
text: Vec::new(),
|
||||||
transforms: Transforms {
|
transforms: Transforms {
|
||||||
previous: Vec::new(),
|
previous: Vec::new(),
|
||||||
current: Transform(lyon::math::Transform::translation(
|
current: Transform(lyon::math::Transform::identity()),
|
||||||
bounds.x, bounds.y,
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
fill_tessellator: tessellation::FillTessellator::new(),
|
fill_tessellator: tessellation::FillTessellator::new(),
|
||||||
stroke_tessellator: tessellation::StrokeTessellator::new(),
|
stroke_tessellator: tessellation::StrokeTessellator::new(),
|
||||||
|
|
@ -409,7 +402,7 @@ impl geometry::frame::Backend for Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draft(&mut self, clip_bounds: Rectangle) -> Frame {
|
fn draft(&mut self, clip_bounds: Rectangle) -> Frame {
|
||||||
Frame::with_clip(clip_bounds)
|
Frame::new(clip_bounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paste(&mut self, frame: Frame) {
|
fn paste(&mut self, frame: Frame) {
|
||||||
|
|
|
||||||
|
|
@ -760,8 +760,8 @@ impl graphics::geometry::Renderer for Renderer {
|
||||||
type Geometry = Geometry;
|
type Geometry = Geometry;
|
||||||
type Frame = geometry::Frame;
|
type Frame = geometry::Frame;
|
||||||
|
|
||||||
fn new_frame(&self, size: core::Size) -> Self::Frame {
|
fn new_frame(&self, bounds: Rectangle) -> Self::Frame {
|
||||||
geometry::Frame::new(size)
|
geometry::Frame::new(bounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_geometry(&mut self, geometry: Self::Geometry) {
|
fn draw_geometry(&mut self, geometry: Self::Geometry) {
|
||||||
|
|
|
||||||
|
|
@ -394,7 +394,7 @@ where
|
||||||
if self.snap_within_viewport {
|
if self.snap_within_viewport {
|
||||||
viewport.size()
|
viewport.size()
|
||||||
} else {
|
} else {
|
||||||
Size::INFINITY
|
Size::INFINITE
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.shrink(Padding::new(self.padding)),
|
.shrink(Padding::new(self.padding)),
|
||||||
|
|
@ -508,7 +508,7 @@ where
|
||||||
&defaults,
|
&defaults,
|
||||||
layout.children().next().unwrap(),
|
layout.children().next().unwrap(),
|
||||||
cursor_position,
|
cursor_position,
|
||||||
&Rectangle::with_size(Size::INFINITY),
|
&Rectangle::with_size(Size::INFINITE),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -346,7 +346,7 @@ where
|
||||||
|
|
||||||
self.content = Renderer::Paragraph::with_spans(Text {
|
self.content = Renderer::Paragraph::with_spans(Text {
|
||||||
content: &spans,
|
content: &spans,
|
||||||
bounds: Size::INFINITY,
|
bounds: Size::INFINITE,
|
||||||
size: preedit
|
size: preedit
|
||||||
.text_size
|
.text_size
|
||||||
.unwrap_or_else(|| renderer.default_size()),
|
.unwrap_or_else(|| renderer.default_size()),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue