summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--glow/src/backend.rs4
-rw-r--r--graphics/src/backend.rs1
-rw-r--r--graphics/src/layer.rs16
-rw-r--r--graphics/src/renderer.rs55
-rw-r--r--graphics/src/widget/text.rs2
-rw-r--r--native/src/renderer.rs8
-rw-r--r--native/src/renderer/null.rs11
-rw-r--r--native/src/renderer/text.rs20
-rw-r--r--native/src/user_interface.rs3
-rw-r--r--native/src/widget/text.rs34
-rw-r--r--wgpu/src/backend.rs4
11 files changed, 127 insertions, 31 deletions
diff --git a/glow/src/backend.rs b/glow/src/backend.rs
index b8e4bd4b..9212761e 100644
--- a/glow/src/backend.rs
+++ b/glow/src/backend.rs
@@ -48,7 +48,7 @@ impl Backend {
pub fn present<T: AsRef<str>>(
&mut self,
gl: &glow::Context,
- primitive: &Primitive,
+ primitives: &[Primitive],
viewport: &Viewport,
overlay_text: &[T],
) {
@@ -56,7 +56,7 @@ impl Backend {
let scale_factor = viewport.scale_factor() as f32;
let projection = viewport.projection();
- let mut layers = Layer::generate(primitive, viewport);
+ let mut layers = Layer::generate(primitives, viewport);
layers.push(Layer::overlay(overlay_text, viewport));
for layer in layers {
diff --git a/graphics/src/backend.rs b/graphics/src/backend.rs
index 7e0af2cc..b8ff5d21 100644
--- a/graphics/src/backend.rs
+++ b/graphics/src/backend.rs
@@ -16,7 +16,6 @@ pub trait Backend {
fn trim_measurements(&mut self) {}
}
-/// A graphics backend that supports text rendering.
pub trait Text {
/// The icon font of the backend.
const ICON_FONT: Font;
diff --git a/graphics/src/layer.rs b/graphics/src/layer.rs
index 9653a2e4..e5cb64c3 100644
--- a/graphics/src/layer.rs
+++ b/graphics/src/layer.rs
@@ -74,7 +74,7 @@ impl<'a> Layer<'a> {
/// Distributes the given [`Primitive`] and generates a list of layers based
/// on its contents.
pub fn generate(
- primitive: &'a Primitive,
+ primitives: &'a [Primitive],
viewport: &Viewport,
) -> Vec<Self> {
let first_layer =
@@ -82,12 +82,14 @@ impl<'a> Layer<'a> {
let mut layers = vec![first_layer];
- Self::process_primitive(
- &mut layers,
- Vector::new(0.0, 0.0),
- primitive,
- 0,
- );
+ for primitive in primitives {
+ Self::process_primitive(
+ &mut layers,
+ Vector::new(0.0, 0.0),
+ primitive,
+ 0,
+ );
+ }
layers
}
diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs
index cedffe7e..a708cb67 100644
--- a/graphics/src/renderer.rs
+++ b/graphics/src/renderer.rs
@@ -1,12 +1,14 @@
-use crate::{Backend, Defaults, Primitive};
+use crate::backend::{self, Backend};
+use crate::{Defaults, Primitive, Vector};
use iced_native::layout;
-use iced_native::{Element, Rectangle};
+use iced_native::renderer;
+use iced_native::{Color, Element, Font, Rectangle};
/// A backend-agnostic renderer that supports all the built-in widgets.
#[derive(Debug)]
pub struct Renderer<B: Backend> {
backend: B,
- primitive: Primitive,
+ primitives: Vec<Primitive>,
}
impl<B: Backend> Renderer<B> {
@@ -14,7 +16,7 @@ impl<B: Backend> Renderer<B> {
pub fn new(backend: B) -> Self {
Self {
backend,
- primitive: Primitive::None,
+ primitives: Vec::new(),
}
}
@@ -22,8 +24,8 @@ impl<B: Backend> Renderer<B> {
&self.backend
}
- pub fn present(&mut self, f: impl FnOnce(&mut B, &Primitive)) {
- f(&mut self.backend, &self.primitive);
+ pub fn present(&mut self, f: impl FnOnce(&mut B, &[Primitive])) {
+ f(&mut self.backend, &self.primitives);
}
}
@@ -45,5 +47,44 @@ where
layout
}
- fn with_layer(&mut self, _bounds: Rectangle, _f: impl FnOnce(&mut Self)) {}
+ fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) {
+ let current_primitives =
+ std::mem::replace(&mut self.primitives, Vec::new());
+
+ f(self);
+
+ let layer_primitives =
+ std::mem::replace(&mut self.primitives, current_primitives);
+
+ self.primitives.push(Primitive::Clip {
+ bounds,
+ offset: Vector::new(0, 0),
+ content: Box::new(Primitive::Group {
+ primitives: layer_primitives,
+ }),
+ });
+ }
+
+ fn clear(&mut self) {
+ self.primitives.clear();
+ }
+}
+
+impl<B> renderer::Text for Renderer<B>
+where
+ B: Backend + backend::Text,
+{
+ type Font = Font;
+
+ fn fill_text(&mut self, text: renderer::text::Section<'_, Self::Font>) {
+ self.primitives.push(Primitive::Text {
+ content: text.content.to_string(),
+ bounds: text.bounds,
+ size: text.size.unwrap_or(f32::from(self.backend.default_size())),
+ color: text.color.unwrap_or(Color::BLACK),
+ font: text.font,
+ horizontal_alignment: text.horizontal_alignment,
+ vertical_alignment: text.vertical_alignment,
+ });
+ }
}
diff --git a/graphics/src/widget/text.rs b/graphics/src/widget/text.rs
index 2ccd18a1..4ee2c616 100644
--- a/graphics/src/widget/text.rs
+++ b/graphics/src/widget/text.rs
@@ -15,8 +15,6 @@ impl<B> text::Renderer for Renderer<B>
where
B: Backend + backend::Text,
{
- type Font = Font;
-
fn default_size(&self) -> u16 {
self.backend().default_size()
}
diff --git a/native/src/renderer.rs b/native/src/renderer.rs
index 3784ff24..ca0aecec 100644
--- a/native/src/renderer.rs
+++ b/native/src/renderer.rs
@@ -19,13 +19,17 @@
//! [`text::Renderer`]: crate::widget::text::Renderer
//! [`Checkbox`]: crate::widget::Checkbox
//! [`checkbox::Renderer`]: crate::widget::checkbox::Renderer
+pub mod text;
+
+pub use text::Text;
#[cfg(debug_assertions)]
mod null;
#[cfg(debug_assertions)]
pub use null::Null;
-use crate::{layout, Element, Rectangle};
+use crate::layout;
+use crate::{Element, Rectangle};
/// A component that can take the state of a user interface and produce an
/// output for its users.
@@ -48,4 +52,6 @@ pub trait Renderer: Sized {
}
fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self));
+
+ fn clear(&mut self);
}
diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs
index 1ffca5c9..da758ebb 100644
--- a/native/src/renderer/null.rs
+++ b/native/src/renderer/null.rs
@@ -4,12 +4,13 @@ use crate::container;
use crate::pane_grid;
use crate::progress_bar;
use crate::radio;
+use crate::renderer::{self, Renderer};
use crate::scrollable;
use crate::slider;
use crate::text;
use crate::text_input;
use crate::toggler;
-use crate::{Font, Padding, Point, Rectangle, Renderer, Size};
+use crate::{Font, Padding, Point, Rectangle, Size};
/// A renderer that does nothing.
///
@@ -28,11 +29,17 @@ impl Renderer for Null {
type Defaults = ();
fn with_layer(&mut self, _bounds: Rectangle, _f: impl FnOnce(&mut Self)) {}
+
+ fn clear(&mut self) {}
}
-impl text::Renderer for Null {
+impl renderer::Text for Null {
type Font = Font;
+ fn fill_text(&mut self, _text: renderer::text::Section<'_, Self::Font>) {}
+}
+
+impl text::Renderer for Null {
fn default_size(&self) -> u16 {
20
}
diff --git a/native/src/renderer/text.rs b/native/src/renderer/text.rs
new file mode 100644
index 00000000..5c189d89
--- /dev/null
+++ b/native/src/renderer/text.rs
@@ -0,0 +1,20 @@
+use crate::alignment;
+use crate::{Color, Rectangle, Renderer};
+
+pub trait Text: Renderer {
+ /// The font type used.
+ type Font: Default + Copy;
+
+ fn fill_text(&mut self, section: Section<'_, Self::Font>);
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct Section<'a, Font> {
+ pub content: &'a str,
+ pub bounds: Rectangle,
+ pub size: Option<f32>,
+ pub color: Option<Color>,
+ pub font: Font,
+ pub horizontal_alignment: alignment::Horizontal,
+ pub vertical_alignment: alignment::Vertical,
+}
diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs
index 187c469a..c80aaf44 100644
--- a/native/src/user_interface.rs
+++ b/native/src/user_interface.rs
@@ -330,6 +330,9 @@ where
/// }
/// ```
pub fn draw(&mut self, renderer: &mut Renderer, cursor_position: Point) {
+ // TODO: Move to shell level (?)
+ renderer.clear();
+
let viewport = Rectangle::with_size(self.bounds);
let overlay = if let Some(mut overlay) =
diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs
index 9915a6e9..ea1ba7ac 100644
--- a/native/src/widget/text.rs
+++ b/native/src/widget/text.rs
@@ -1,6 +1,7 @@
//! Write some text for your users to read.
use crate::alignment;
use crate::layout;
+use crate::renderer;
use crate::{
Color, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget,
};
@@ -133,13 +134,35 @@ where
fn draw(
&self,
- _renderer: &mut Renderer,
+ renderer: &mut Renderer,
_defaults: &Renderer::Defaults,
- _layout: Layout<'_>,
+ layout: Layout<'_>,
_cursor_position: Point,
_viewport: &Rectangle,
) {
- // TODO
+ let bounds = layout.bounds();
+
+ let x = match self.horizontal_alignment {
+ alignment::Horizontal::Left => bounds.x,
+ alignment::Horizontal::Center => bounds.center_x(),
+ alignment::Horizontal::Right => bounds.x + bounds.width,
+ };
+
+ let y = match self.vertical_alignment {
+ alignment::Vertical::Top => bounds.y,
+ alignment::Vertical::Center => bounds.center_y(),
+ alignment::Vertical::Bottom => bounds.y + bounds.height,
+ };
+
+ renderer.fill_text(renderer::text::Section {
+ content: &self.content,
+ size: self.size.map(f32::from),
+ bounds: Rectangle { x, y, ..bounds },
+ color: self.color,
+ font: self.font,
+ horizontal_alignment: self.horizontal_alignment,
+ vertical_alignment: self.vertical_alignment,
+ });
}
fn hash_layout(&self, state: &mut Hasher) {
@@ -159,10 +182,7 @@ where
/// able to use [`Text`] in your user interface.
///
/// [renderer]: crate::Renderer
-pub trait Renderer: crate::Renderer {
- /// The font type used for [`Text`].
- type Font: Default + Copy;
-
+pub trait Renderer: renderer::Text {
/// Returns the default size of [`Text`].
fn default_size(&self) -> u16;
diff --git a/wgpu/src/backend.rs b/wgpu/src/backend.rs
index 56de553f..2597cef3 100644
--- a/wgpu/src/backend.rs
+++ b/wgpu/src/backend.rs
@@ -74,7 +74,7 @@ impl Backend {
staging_belt: &mut wgpu::util::StagingBelt,
encoder: &mut wgpu::CommandEncoder,
frame: &wgpu::TextureView,
- primitive: &Primitive,
+ primitives: &[Primitive],
viewport: &Viewport,
overlay_text: &[T],
) {
@@ -84,7 +84,7 @@ impl Backend {
let scale_factor = viewport.scale_factor() as f32;
let transformation = viewport.projection();
- let mut layers = Layer::generate(primitive, viewport);
+ let mut layers = Layer::generate(primitives, viewport);
layers.push(Layer::overlay(overlay_text, viewport));
for layer in layers {