Merge branch 'master' into beacon

This commit is contained in:
Héctor Ramón Jiménez 2025-03-11 22:25:06 +01:00
commit ebfcb65841
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
41 changed files with 805 additions and 589 deletions

656
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -154,11 +154,11 @@ bincode = "1.3"
bitflags = "2.0" bitflags = "2.0"
bytemuck = { version = "1.0", features = ["derive"] } bytemuck = { version = "1.0", features = ["derive"] }
bytes = "1.6" bytes = "1.6"
cosmic-text = "0.12" cosmic-text = "0.13"
dark-light = "2.0" dark-light = "2.0"
futures = "0.3" futures = "0.3"
glam = "0.25" glam = "0.25"
glyphon = { git = "https://github.com/hecrj/glyphon.git", rev = "09712a70df7431e9a3b1ac1bbd4fb634096cb3b4" } cryoglyph = { git = "https://github.com/iced-rs/cryoglyph.git", rev = "be2defe4a13fd7c97c6f4c81e8e085463eb578dc" }
guillotiere = "0.6" guillotiere = "0.6"
half = "2.2" half = "2.2"
image = { version = "0.25", default-features = false } image = { version = "0.25", default-features = false }
@ -196,7 +196,7 @@ wasm-bindgen-futures = "0.4"
wasmtimer = "0.4.1" wasmtimer = "0.4.1"
web-sys = "0.3.69" web-sys = "0.3.69"
web-time = "1.1" web-time = "1.1"
wgpu = "23.0" wgpu = "24.0"
window_clipboard = "0.4.1" window_clipboard = "0.4.1"
winit = { git = "https://github.com/iced-rs/winit.git", rev = "11414b6aa45699f038114e61b4ddf5102b2d3b4b" } winit = { git = "https://github.com/iced-rs/winit.git", rev = "11414b6aa45699f038114e61b4ddf5102b2d3b4b" }

View file

@ -8,46 +8,17 @@ use iced::{
Color, Element, Font, Length, Pixels, Point, Rectangle, Size, Theme, Color, Element, Font, Length, Pixels, Point, Rectangle, Size, Theme,
}; };
use iced_wgpu::Renderer; use iced_wgpu::Renderer;
use iced_wgpu::wgpu;
criterion_main!(benches); criterion_main!(benches);
criterion_group!(benches, wgpu_benchmark); criterion_group!(benches, wgpu_benchmark);
#[allow(unused_results)] #[allow(unused_results)]
pub fn wgpu_benchmark(c: &mut Criterion) { pub fn wgpu_benchmark(c: &mut Criterion) {
c.bench_function("wgpu — canvas (light)", |b| {
benchmark(b, |_| scene(10));
});
c.bench_function("wgpu — canvas (heavy)", |b| {
benchmark(b, |_| scene(1_000));
});
c.bench_function("wgpu - layered text (light)", |b| {
benchmark(b, |_| layered_text(10));
});
c.bench_function("wgpu - layered text (heavy)", |b| {
benchmark(b, |_| layered_text(1_000));
});
c.bench_function("wgpu - dynamic text (light)", |b| {
benchmark(b, |i| dynamic_text(1_000, i));
});
c.bench_function("wgpu - dynamic text (heavy)", |b| {
benchmark(b, |i| dynamic_text(100_000, i));
});
}
fn benchmark<'a>(
bencher: &mut Bencher<'_>,
view: impl Fn(usize) -> Element<'a, (), Theme, Renderer>,
) {
use iced_futures::futures::executor; use iced_futures::futures::executor;
use iced_wgpu::graphics;
use iced_wgpu::graphics::Antialiasing;
use iced_wgpu::wgpu; use iced_wgpu::wgpu;
use iced_winit::core;
use iced_winit::runtime;
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(), backends: wgpu::Backends::all(),
..Default::default() ..Default::default()
}); });
@ -72,18 +43,53 @@ fn benchmark<'a>(
)) ))
.expect("request device"); .expect("request device");
c.bench_function("wgpu — canvas (light)", |b| {
benchmark(b, &adapter, &device, &queue, |_| scene(10));
});
c.bench_function("wgpu — canvas (heavy)", |b| {
benchmark(b, &adapter, &device, &queue, |_| scene(1_000));
});
c.bench_function("wgpu - layered text (light)", |b| {
benchmark(b, &adapter, &device, &queue, |_| layered_text(10));
});
c.bench_function("wgpu - layered text (heavy)", |b| {
benchmark(b, &adapter, &device, &queue, |_| layered_text(1_000));
});
c.bench_function("wgpu - dynamic text (light)", |b| {
benchmark(b, &adapter, &device, &queue, |i| dynamic_text(1_000, i));
});
c.bench_function("wgpu - dynamic text (heavy)", |b| {
benchmark(b, &adapter, &device, &queue, |i| dynamic_text(100_000, i));
});
}
fn benchmark<'a>(
bencher: &mut Bencher<'_>,
adapter: &wgpu::Adapter,
device: &wgpu::Device,
queue: &wgpu::Queue,
view: impl Fn(usize) -> Element<'a, (), Theme, Renderer>,
) {
use iced_wgpu::graphics;
use iced_wgpu::graphics::Antialiasing;
use iced_wgpu::wgpu;
use iced_winit::core;
use iced_winit::runtime;
let format = wgpu::TextureFormat::Bgra8UnormSrgb; let format = wgpu::TextureFormat::Bgra8UnormSrgb;
let mut engine = iced_wgpu::Engine::new( let mut engine = iced_wgpu::Engine::new(
&adapter, adapter,
&device, device,
&queue, queue,
format, format,
Some(Antialiasing::MSAAx4), Some(Antialiasing::MSAAx4),
); );
let mut renderer = let mut renderer =
Renderer::new(&device, &engine, Font::DEFAULT, Pixels::from(16)); Renderer::new(device, &engine, Font::DEFAULT, Pixels::from(16));
let viewport = let viewport =
graphics::Viewport::with_physical_size(Size::new(3840, 2160), 2.0); graphics::Viewport::with_physical_size(Size::new(3840, 2160), 2.0);
@ -135,8 +141,8 @@ fn benchmark<'a>(
renderer.present( renderer.present(
&mut engine, &mut engine,
&device, device,
&queue, queue,
&mut encoder, &mut encoder,
Some(Color::BLACK), Some(Color::BLACK),
format, format,
@ -144,7 +150,7 @@ fn benchmark<'a>(
&viewport, &viewport,
); );
let submission = engine.submit(&queue, encoder); let submission = engine.submit(queue, encoder);
let _ = device.poll(wgpu::Maintain::WaitForSubmissionIndex(submission)); let _ = device.poll(wgpu::Maintain::WaitForSubmissionIndex(submission));
i += 1; i += 1;
@ -184,8 +190,8 @@ fn scene<'a, Message: 'a>(n: usize) -> Element<'a, Message, Theme, Renderer> {
size: Pixels::from(16), size: Pixels::from(16),
line_height: text::LineHeight::default(), line_height: text::LineHeight::default(),
font: Font::DEFAULT, font: Font::DEFAULT,
horizontal_alignment: alignment::Horizontal::Left, align_x: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top, align_y: alignment::Vertical::Top,
shaping: text::Shaping::Basic, shaping: text::Shaping::Basic,
}); });
} }

View file

@ -87,11 +87,11 @@ impl text::Paragraph for () {
text::Difference::None text::Difference::None
} }
fn horizontal_alignment(&self) -> alignment::Horizontal { fn align_x(&self) -> text::Alignment {
alignment::Horizontal::Left text::Alignment::Default
} }
fn vertical_alignment(&self) -> alignment::Vertical { fn align_y(&self) -> alignment::Vertical {
alignment::Vertical::Top alignment::Vertical::Top
} }

View file

@ -34,10 +34,10 @@ pub struct Text<Content = String, Font = crate::Font> {
pub font: Font, pub font: Font,
/// The horizontal alignment of the [`Text`]. /// The horizontal alignment of the [`Text`].
pub horizontal_alignment: alignment::Horizontal, pub align_x: Alignment,
/// The vertical alignment of the [`Text`]. /// The vertical alignment of the [`Text`].
pub vertical_alignment: alignment::Vertical, pub align_y: alignment::Vertical,
/// The [`Shaping`] strategy of the [`Text`]. /// The [`Shaping`] strategy of the [`Text`].
pub shaping: Shaping, pub shaping: Shaping,
@ -46,6 +46,45 @@ pub struct Text<Content = String, Font = crate::Font> {
pub wrapping: Wrapping, pub wrapping: Wrapping,
} }
/// The alignment of some text.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Alignment {
/// No specific alignment.
///
/// Left-to-right text will be aligned to the left, while
/// right-to-left text will be aligned to the right.
#[default]
Default,
/// Align text to the left.
Left,
/// Center text.
Center,
/// Align text to the right.
Right,
/// Justify text.
Justified,
}
impl From<alignment::Horizontal> for Alignment {
fn from(alignment: alignment::Horizontal) -> Self {
match alignment {
alignment::Horizontal::Left => Self::Left,
alignment::Horizontal::Center => Self::Center,
alignment::Horizontal::Right => Self::Right,
}
}
}
impl From<crate::Alignment> for Alignment {
fn from(alignment: crate::Alignment) -> Self {
match alignment {
crate::Alignment::Start => Self::Left,
crate::Alignment::Center => Self::Center,
crate::Alignment::End => Self::Right,
}
}
}
/// The shaping strategy of some text. /// The shaping strategy of some text.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Shaping { pub enum Shaping {

View file

@ -1,6 +1,6 @@
//! Draw paragraphs. //! Draw paragraphs.
use crate::alignment; use crate::alignment;
use crate::text::{Difference, Hit, Span, Text}; use crate::text::{Alignment, Difference, Hit, Span, Text};
use crate::{Point, Rectangle, Size}; use crate::{Point, Rectangle, Size};
/// A text paragraph. /// A text paragraph.
@ -24,10 +24,10 @@ pub trait Paragraph: Sized + Default {
fn compare(&self, text: Text<(), Self::Font>) -> Difference; fn compare(&self, text: Text<(), Self::Font>) -> Difference;
/// Returns the horizontal alignment of the [`Paragraph`]. /// Returns the horizontal alignment of the [`Paragraph`].
fn horizontal_alignment(&self) -> alignment::Horizontal; fn align_x(&self) -> Alignment;
/// Returns the vertical alignment of the [`Paragraph`]. /// Returns the vertical alignment of the [`Paragraph`].
fn vertical_alignment(&self) -> alignment::Vertical; fn align_y(&self) -> alignment::Vertical;
/// Returns the minimum boundaries that can fit the contents of the /// Returns the minimum boundaries that can fit the contents of the
/// [`Paragraph`]. /// [`Paragraph`].
@ -92,8 +92,8 @@ impl<P: Paragraph> Plain<P> {
size: text.size, size: text.size,
line_height: text.line_height, line_height: text.line_height,
font: text.font, font: text.font,
horizontal_alignment: text.horizontal_alignment, align_x: text.align_x,
vertical_alignment: text.vertical_alignment, align_y: text.align_y,
shaping: text.shaping, shaping: text.shaping,
wrapping: text.wrapping, wrapping: text.wrapping,
}) { }) {
@ -108,13 +108,13 @@ impl<P: Paragraph> Plain<P> {
} }
/// Returns the horizontal alignment of the [`Paragraph`]. /// Returns the horizontal alignment of the [`Paragraph`].
pub fn horizontal_alignment(&self) -> alignment::Horizontal { pub fn align_x(&self) -> Alignment {
self.raw.horizontal_alignment() self.raw.align_x()
} }
/// Returns the vertical alignment of the [`Paragraph`]. /// Returns the vertical alignment of the [`Paragraph`].
pub fn vertical_alignment(&self) -> alignment::Vertical { pub fn align_y(&self) -> alignment::Vertical {
self.raw.vertical_alignment() self.raw.align_y()
} }
/// Returns the minimum boundaries that can fit the contents of the /// Returns the minimum boundaries that can fit the contents of the

View file

@ -32,7 +32,7 @@ use crate::{
Widget, Widget,
}; };
pub use text::{LineHeight, Shaping, Wrapping}; pub use text::{Alignment, LineHeight, Shaping, Wrapping};
/// A bunch of text. /// A bunch of text.
/// ///
@ -67,8 +67,8 @@ where
line_height: LineHeight, line_height: LineHeight,
width: Length, width: Length,
height: Length, height: Length,
horizontal_alignment: alignment::Horizontal, align_x: text::Alignment,
vertical_alignment: alignment::Vertical, align_y: alignment::Vertical,
font: Option<Renderer::Font>, font: Option<Renderer::Font>,
shaping: Shaping, shaping: Shaping,
wrapping: Wrapping, wrapping: Wrapping,
@ -89,8 +89,8 @@ where
font: None, font: None,
width: Length::Shrink, width: Length::Shrink,
height: Length::Shrink, height: Length::Shrink,
horizontal_alignment: alignment::Horizontal::Left, align_x: text::Alignment::Default,
vertical_alignment: alignment::Vertical::Top, align_y: alignment::Vertical::Top,
shaping: Shaping::default(), shaping: Shaping::default(),
wrapping: Wrapping::default(), wrapping: Wrapping::default(),
class: Theme::default(), class: Theme::default(),
@ -136,11 +136,8 @@ where
} }
/// Sets the [`alignment::Horizontal`] of the [`Text`]. /// Sets the [`alignment::Horizontal`] of the [`Text`].
pub fn align_x( pub fn align_x(mut self, alignment: impl Into<text::Alignment>) -> Self {
mut self, self.align_x = alignment.into();
alignment: impl Into<alignment::Horizontal>,
) -> Self {
self.horizontal_alignment = alignment.into();
self self
} }
@ -149,7 +146,7 @@ where
mut self, mut self,
alignment: impl Into<alignment::Vertical>, alignment: impl Into<alignment::Vertical>,
) -> Self { ) -> Self {
self.vertical_alignment = alignment.into(); self.align_y = alignment.into();
self self
} }
@ -245,8 +242,8 @@ where
self.line_height, self.line_height,
self.size, self.size,
self.font, self.font,
self.horizontal_alignment, self.align_x,
self.vertical_alignment, self.align_y,
self.shaping, self.shaping,
self.wrapping, self.wrapping,
) )
@ -290,8 +287,8 @@ pub fn layout<Renderer>(
line_height: LineHeight, line_height: LineHeight,
size: Option<Pixels>, size: Option<Pixels>,
font: Option<Renderer::Font>, font: Option<Renderer::Font>,
horizontal_alignment: alignment::Horizontal, align_x: text::Alignment,
vertical_alignment: alignment::Vertical, align_y: alignment::Vertical,
shaping: Shaping, shaping: Shaping,
wrapping: Wrapping, wrapping: Wrapping,
) -> layout::Node ) -> layout::Node
@ -312,8 +309,8 @@ where
size, size,
line_height, line_height,
font, font,
horizontal_alignment, align_x,
vertical_alignment, align_y,
shaping, shaping,
wrapping, wrapping,
}); });
@ -344,13 +341,13 @@ pub fn draw<Renderer>(
{ {
let bounds = layout.bounds(); let bounds = layout.bounds();
let x = match paragraph.horizontal_alignment() { let x = match paragraph.align_x() {
alignment::Horizontal::Left => bounds.x, Alignment::Default | Alignment::Left | Alignment::Justified => bounds.x,
alignment::Horizontal::Center => bounds.center_x(), Alignment::Center => bounds.center_x(),
alignment::Horizontal::Right => bounds.x + bounds.width, Alignment::Right => bounds.x + bounds.width,
}; };
let y = match paragraph.vertical_alignment() { let y = match paragraph.align_y() {
alignment::Vertical::Top => bounds.y, alignment::Vertical::Top => bounds.y,
alignment::Vertical::Center => bounds.center_y(), alignment::Vertical::Center => bounds.center_y(),
alignment::Vertical::Bottom => bounds.y + bounds.height, alignment::Vertical::Bottom => bounds.y + bounds.height,

View file

@ -150,12 +150,12 @@ impl<Message> canvas::Program<Message> for Clock {
-width * 2.0, -width * 2.0,
), ),
color: palette.secondary.strong.text, color: palette.secondary.strong.text,
horizontal_alignment: if rotate_factor > 0.0 { align_x: if rotate_factor > 0.0 {
alignment::Horizontal::Right alignment::Horizontal::Right
} else { } else {
alignment::Horizontal::Left alignment::Horizontal::Left
}, },
vertical_alignment: alignment::Vertical::Bottom, align_y: alignment::Vertical::Bottom,
font: Font::MONOSPACE, font: Font::MONOSPACE,
..canvas::Text::default() ..canvas::Text::default()
}); });
@ -173,8 +173,8 @@ impl<Message> canvas::Program<Message> for Clock {
size: (radius / 5.0).into(), size: (radius / 5.0).into(),
position: Point::new(x * 0.82, y * 0.82), position: Point::new(x * 0.82, y * 0.82),
color: palette.secondary.strong.text, color: palette.secondary.strong.text,
horizontal_alignment: alignment::Horizontal::Center, align_x: alignment::Horizontal::Center,
vertical_alignment: alignment::Vertical::Center, align_y: alignment::Vertical::Center,
font: Font::MONOSPACE, font: Font::MONOSPACE,
..canvas::Text::default() ..canvas::Text::default()
}); });

View file

@ -170,8 +170,8 @@ impl Theme {
}); });
let mut text = canvas::Text { let mut text = canvas::Text {
horizontal_alignment: alignment::Horizontal::Center, align_x: alignment::Horizontal::Center,
vertical_alignment: alignment::Vertical::Top, align_y: alignment::Vertical::Top,
size: Pixels(15.0), size: Pixels(15.0),
color: text_color, color: text_color,
..canvas::Text::default() ..canvas::Text::default()
@ -214,7 +214,7 @@ impl Theme {
}); });
} }
text.vertical_alignment = alignment::Vertical::Bottom; text.align_y = alignment::Vertical::Bottom;
let hsl = Hsl::from_color(Rgb::from(self.base)); let hsl = Hsl::from_color(Rgb::from(self.base));
for i in 0..self.len() { for i in 0..self.len() {

View file

@ -580,8 +580,8 @@ mod grid {
color: Color::WHITE, color: Color::WHITE,
size: 14.0.into(), size: 14.0.into(),
position: Point::new(frame.width(), frame.height()), position: Point::new(frame.width(), frame.height()),
horizontal_alignment: alignment::Horizontal::Right, align_x: alignment::Horizontal::Right,
vertical_alignment: alignment::Vertical::Bottom, align_y: alignment::Vertical::Bottom,
..Text::default() ..Text::default()
}; };

View file

@ -72,10 +72,9 @@ pub fn main() -> Result<(), winit::error::EventLoopError> {
); );
let clipboard = Clipboard::connect(window.clone()); let clipboard = Clipboard::connect(window.clone());
let backend = let backend = wgpu::Backends::from_env().unwrap_or_default();
wgpu::util::backend_bits_from_env().unwrap_or_default();
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
backends: backend, backends: backend,
..Default::default() ..Default::default()
}); });

View file

@ -1 +1 @@
0ef7325a79ce31c83759529ed478c8b4848c40c2867193624ef9673b9e21ff53 0e355b080ad33905145e9f70a3b29e2481197c8fc8f42491acd5358238ebbd5f

View file

@ -11,6 +11,7 @@ iced.features = ["image", "debug"]
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tracing-subscriber = "0.3" tracing-subscriber = "0.3"
open = "5"
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
iced.workspace = true iced.workspace = true

View file

@ -1,9 +1,11 @@
use iced::border;
use iced::widget::{Button, Column, Container, Slider}; use iced::widget::{Button, Column, Container, Slider};
use iced::widget::{ use iced::widget::{
button, center_x, center_y, checkbox, column, horizontal_space, image, button, center_x, center_y, checkbox, column, horizontal_space, image,
radio, row, scrollable, slider, text, text_input, toggler, vertical_space, radio, rich_text, row, scrollable, slider, span, text, text_input, toggler,
vertical_space,
}; };
use iced::{Center, Color, Element, Fill, Font, Pixels}; use iced::{Center, Color, Element, Fill, Font, Pixels, Theme};
pub fn main() -> iced::Result { pub fn main() -> iced::Result {
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
@ -54,6 +56,7 @@ pub enum Message {
ToggleTextInputIcon(bool), ToggleTextInputIcon(bool),
DebugToggled(bool), DebugToggled(bool),
TogglerChanged(bool), TogglerChanged(bool),
OpenTrunk,
} }
impl Tour { impl Tour {
@ -130,6 +133,10 @@ impl Tour {
Message::TogglerChanged(toggler) => { Message::TogglerChanged(toggler) => {
self.toggler = toggler; self.toggler = toggler;
} }
Message::OpenTrunk => {
#[cfg(not(target_arch = "wasm32"))]
let _ = open::that_in_background("https://trunkrs.dev");
}
} }
} }
@ -194,8 +201,8 @@ impl Tour {
fn welcome(&self) -> Column<Message> { fn welcome(&self) -> Column<Message> {
Self::container("Welcome!") Self::container("Welcome!")
.push( .push(
"This is a simple tour meant to showcase a bunch of widgets \ "This is a simple tour meant to showcase a bunch of \
that can be easily implemented on top of Iced.", widgets that can be easily implemented on top of Iced.",
) )
.push( .push(
"Iced is a cross-platform GUI library for Rust focused on \ "Iced is a cross-platform GUI library for Rust focused on \
@ -210,13 +217,31 @@ impl Tour {
built on top of wgpu, a graphics library supporting Vulkan, \ built on top of wgpu, a graphics library supporting Vulkan, \
Metal, DX11, and DX12.", Metal, DX11, and DX12.",
) )
.push({
let theme = Theme::default();
let palette = theme.extended_palette();
rich_text![
"Additionally, this tour can also run on WebAssembly ",
"by leveraging ",
span("trunk")
.color(palette.primary.base.color)
.background(palette.background.weakest.color)
.border(
border::rounded(2)
.width(1)
.color(palette.background.weak.color)
)
.padding([0, 2])
.font(Font::MONOSPACE)
.link(Message::OpenTrunk),
"."
]
.on_link_click(std::convert::identity)
})
.push( .push(
"Additionally, this tour can also run on WebAssembly thanks \ "You will need to interact with the UI in order to reach \
to dodrio, an experimental VDOM library for Rust.", the end!",
)
.push(
"You will need to interact with the UI in order to reach the \
end!",
) )
} }

View file

@ -142,8 +142,8 @@ impl<Message> canvas::Program<Message> for State {
} else { } else {
"Vectorial Text! 🎉" "Vectorial Text! 🎉"
}), }),
horizontal_alignment: alignment::Horizontal::Center, align_x: alignment::Horizontal::Center,
vertical_alignment: alignment::Vertical::Center, align_y: alignment::Vertical::Center,
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
..canvas::Text::default() ..canvas::Text::default()
}); });

View file

@ -130,6 +130,9 @@ pub enum SurfaceError {
/// There is no more memory left to allocate a new frame. /// There is no more memory left to allocate a new frame.
#[error("There is no more memory left to allocate a new frame")] #[error("There is no more memory left to allocate a new frame")]
OutOfMemory, OutOfMemory,
/// Acquiring a texture failed with a generic error.
#[error("Acquiring a texture failed with a generic error")]
Other,
} }
/// Contains information about the graphics (e.g. graphics adapter, graphics backend). /// Contains information about the graphics (e.g. graphics adapter, graphics backend).

View file

@ -10,11 +10,14 @@ pub struct Text {
/// The contents of the text /// The contents of the text
pub content: String, pub content: String,
/// The position of the text relative to the alignment properties. /// The position of the text relative to the alignment properties.
///
/// By default, this position will be relative to the top-left corner coordinate meaning that /// By default, this position will be relative to the top-left corner coordinate meaning that
/// if the horizontal and vertical alignments are unchanged, this property will tell where the /// if the horizontal and vertical alignments are unchanged, this property will tell where the
/// top-left corner of the text should be placed. /// top-left corner of the text should be placed.
///
/// By changing the horizontal_alignment and vertical_alignment properties, you are are able to /// By changing the horizontal_alignment and vertical_alignment properties, you are are able to
/// change what part of text is placed at this positions. /// change what part of text is placed at this positions.
///
/// For example, when the horizontal_alignment and vertical_alignment are set to Center, the /// For example, when the horizontal_alignment and vertical_alignment are set to Center, the
/// center of the text will be placed at the given position NOT the top-left coordinate. /// center of the text will be placed at the given position NOT the top-left coordinate.
pub position: Point, pub position: Point,
@ -27,9 +30,9 @@ pub struct Text {
/// The font of the text /// The font of the text
pub font: Font, pub font: Font,
/// The horizontal alignment of the text /// The horizontal alignment of the text
pub horizontal_alignment: alignment::Horizontal, pub align_x: alignment::Horizontal,
/// The vertical alignment of the text /// The vertical alignment of the text
pub vertical_alignment: alignment::Vertical, pub align_y: alignment::Vertical,
/// The shaping strategy of the text. /// The shaping strategy of the text.
pub shaping: Shaping, pub shaping: Shaping,
} }
@ -57,7 +60,7 @@ impl Text {
4, 4,
); );
let translation_x = match self.horizontal_alignment { let translation_x = match self.align_x {
alignment::Horizontal::Left => self.position.x, alignment::Horizontal::Left => self.position.x,
alignment::Horizontal::Center | alignment::Horizontal::Right => { alignment::Horizontal::Center | alignment::Horizontal::Right => {
let mut line_width = 0.0f32; let mut line_width = 0.0f32;
@ -66,7 +69,7 @@ impl Text {
line_width = line_width.max(line.w); line_width = line_width.max(line.w);
} }
if self.horizontal_alignment == alignment::Horizontal::Center { if self.align_x == alignment::Horizontal::Center {
self.position.x - line_width / 2.0 self.position.x - line_width / 2.0
} else { } else {
self.position.x - line_width self.position.x - line_width
@ -77,7 +80,7 @@ impl Text {
let translation_y = { let translation_y = {
let line_height = self.line_height.to_absolute(self.size); let line_height = self.line_height.to_absolute(self.size);
match self.vertical_alignment { match self.align_y {
alignment::Vertical::Top => self.position.y, alignment::Vertical::Top => self.position.y,
alignment::Vertical::Center => { alignment::Vertical::Center => {
self.position.y - line_height.0 / 2.0 self.position.y - line_height.0 / 2.0
@ -177,8 +180,8 @@ impl Default for Text {
size: Pixels(16.0), size: Pixels(16.0),
line_height: LineHeight::Relative(1.2), line_height: LineHeight::Relative(1.2),
font: Font::default(), font: Font::default(),
horizontal_alignment: alignment::Horizontal::Left, align_x: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top, align_y: alignment::Vertical::Top,
shaping: Shaping::Basic, shaping: Shaping::Basic,
} }
} }

View file

@ -11,7 +11,7 @@ pub use cosmic_text;
use crate::core::alignment; use crate::core::alignment;
use crate::core::font::{self, Font}; use crate::core::font::{self, Font};
use crate::core::text::{Shaping, Wrapping}; use crate::core::text::{Alignment, Shaping, Wrapping};
use crate::core::{Color, Pixels, Point, Rectangle, Size, Transformation}; use crate::core::{Color, Pixels, Point, Rectangle, Size, Transformation};
use std::borrow::Cow; use std::borrow::Cow;
@ -54,9 +54,9 @@ pub enum Text {
/// The font of the text. /// The font of the text.
font: Font, font: Font,
/// The horizontal alignment of the text. /// The horizontal alignment of the text.
horizontal_alignment: alignment::Horizontal, align_x: Alignment,
/// The vertical alignment of the text. /// The vertical alignment of the text.
vertical_alignment: alignment::Vertical, align_y: alignment::Vertical,
/// The shaping strategy of the text. /// The shaping strategy of the text.
shaping: Shaping, shaping: Shaping,
/// The clip bounds of the text. /// The clip bounds of the text.
@ -73,7 +73,7 @@ pub enum Text {
impl Text { impl Text {
/// Returns the visible bounds of the [`Text`]. /// Returns the visible bounds of the [`Text`].
pub fn visible_bounds(&self) -> Option<Rectangle> { pub fn visible_bounds(&self) -> Option<Rectangle> {
let (bounds, horizontal_alignment, vertical_alignment) = match self { let (bounds, align_x, align_y) = match self {
Text::Paragraph { Text::Paragraph {
position, position,
paragraph, paragraph,
@ -84,8 +84,8 @@ impl Text {
Rectangle::new(*position, paragraph.min_bounds) Rectangle::new(*position, paragraph.min_bounds)
.intersection(clip_bounds) .intersection(clip_bounds)
.map(|bounds| bounds * *transformation), .map(|bounds| bounds * *transformation),
Some(paragraph.horizontal_alignment), paragraph.align_x,
Some(paragraph.vertical_alignment), Some(paragraph.align_y),
), ),
Text::Editor { Text::Editor {
editor, editor,
@ -97,38 +97,38 @@ impl Text {
Rectangle::new(*position, editor.bounds) Rectangle::new(*position, editor.bounds)
.intersection(clip_bounds) .intersection(clip_bounds)
.map(|bounds| bounds * *transformation), .map(|bounds| bounds * *transformation),
None, Alignment::Default,
None, None,
), ),
Text::Cached { Text::Cached {
bounds, bounds,
clip_bounds, clip_bounds,
horizontal_alignment, align_x: horizontal_alignment,
vertical_alignment, align_y: vertical_alignment,
.. ..
} => ( } => (
bounds.intersection(clip_bounds), bounds.intersection(clip_bounds),
Some(*horizontal_alignment), *horizontal_alignment,
Some(*vertical_alignment), Some(*vertical_alignment),
), ),
Text::Raw { raw, .. } => (Some(raw.clip_bounds), None, None), Text::Raw { raw, .. } => {
(Some(raw.clip_bounds), Alignment::Default, None)
}
}; };
let mut bounds = bounds?; let mut bounds = bounds?;
if let Some(alignment) = horizontal_alignment { match align_x {
match alignment { Alignment::Default | Alignment::Left | Alignment::Justified => {}
alignment::Horizontal::Left => {} Alignment::Center => {
alignment::Horizontal::Center => { bounds.x -= bounds.width / 2.0;
bounds.x -= bounds.width / 2.0; }
} Alignment::Right => {
alignment::Horizontal::Right => { bounds.x -= bounds.width;
bounds.x -= bounds.width;
}
} }
} }
if let Some(alignment) = vertical_alignment { if let Some(alignment) = align_y {
match alignment { match alignment {
alignment::Vertical::Top => {} alignment::Vertical::Top => {}
alignment::Vertical::Center => { alignment::Vertical::Center => {
@ -242,15 +242,19 @@ impl PartialEq for Raw {
} }
/// Measures the dimensions of the given [`cosmic_text::Buffer`]. /// Measures the dimensions of the given [`cosmic_text::Buffer`].
pub fn measure(buffer: &cosmic_text::Buffer) -> Size { pub fn measure(buffer: &cosmic_text::Buffer) -> (Size, bool) {
let (width, height) = let (width, height, has_rtl) = buffer.layout_runs().fold(
buffer (0.0, 0.0, false),
.layout_runs() |(width, height, has_rtl), run| {
.fold((0.0, 0.0), |(width, height), run| { (
(run.line_w.max(width), height + run.line_height) run.line_w.max(width),
}); height + run.line_height,
has_rtl || run.rtl,
)
},
);
Size::new(width, height) (Size::new(width, height), has_rtl)
} }
/// Returns the attributes of the given [`Font`]. /// Returns the attributes of the given [`Font`].
@ -309,6 +313,16 @@ fn to_style(style: font::Style) -> cosmic_text::Style {
} }
} }
fn to_align(alignment: Alignment) -> Option<cosmic_text::Align> {
match alignment {
Alignment::Default => None,
Alignment::Left => Some(cosmic_text::Align::Left),
Alignment::Center => Some(cosmic_text::Align::Center),
Alignment::Right => Some(cosmic_text::Align::Right),
Alignment::Justified => Some(cosmic_text::Align::Justified),
}
}
/// Converts some [`Shaping`] strategy to a [`cosmic_text::Shaping`] strategy. /// Converts some [`Shaping`] strategy to a [`cosmic_text::Shaping`] strategy.
pub fn to_shaping(shaping: Shaping) -> cosmic_text::Shaping { pub fn to_shaping(shaping: Shaping) -> cosmic_text::Shaping {
match shaping { match shaping {

View file

@ -58,7 +58,16 @@ impl Cache {
text::to_shaping(key.shaping), text::to_shaping(key.shaping),
); );
let bounds = text::measure(&buffer); let (bounds, has_rtl) = text::measure(&buffer);
if has_rtl {
buffer.set_size(
font_system,
Some(bounds.width),
Some(bounds.height),
);
}
let _ = entry.insert(Entry { let _ = entry.insert(Entry {
buffer, buffer,
min_bounds: bounds, min_bounds: bounds,

View file

@ -178,10 +178,8 @@ impl editor::Editor for Editor {
.get(cursor.line) .get(cursor.line)
.expect("Cursor line should be present"); .expect("Cursor line should be present");
let layout = line let layout =
.layout_opt() line.layout_opt().expect("Line layout should be cached");
.as_ref()
.expect("Line layout should be cached");
let mut lines = layout.iter().enumerate(); let mut lines = layout.iter().enumerate();
@ -452,7 +450,10 @@ impl editor::Editor for Editor {
fn min_bounds(&self) -> Size { fn min_bounds(&self) -> Size {
let internal = self.internal(); let internal = self.internal();
text::measure(buffer_from_editor(&internal.editor)) let (bounds, _has_rtl) =
text::measure(buffer_from_editor(&internal.editor));
bounds
} }
fn update( fn update(
@ -706,11 +707,7 @@ fn highlight_line(
from: usize, from: usize,
to: usize, to: usize,
) -> impl Iterator<Item = (f32, f32)> + '_ { ) -> impl Iterator<Item = (f32, f32)> + '_ {
let layout = line let layout = line.layout_opt().map(Vec::as_slice).unwrap_or_default();
.layout_opt()
.as_ref()
.map(Vec::as_slice)
.unwrap_or_default();
layout.iter().map(move |visual_line| { layout.iter().map(move |visual_line| {
let start = visual_line let start = visual_line
@ -761,9 +758,7 @@ fn visual_lines_offset(line: usize, buffer: &cosmic_text::Buffer) -> i32 {
let visual_lines_offset: usize = buffer.lines[start..] let visual_lines_offset: usize = buffer.lines[start..]
.iter() .iter()
.take(end - start) .take(end - start)
.map(|line| { .map(|line| line.layout_opt().map(Vec::len).unwrap_or_default())
line.layout_opt().as_ref().map(Vec::len).unwrap_or_default()
})
.sum(); .sum();
visual_lines_offset as i32 * if scroll.line < line { 1 } else { -1 } visual_lines_offset as i32 * if scroll.line < line { 1 } else { -1 }

View file

@ -1,7 +1,7 @@
//! Draw paragraphs. //! Draw paragraphs.
use crate::core; use crate::core;
use crate::core::alignment; use crate::core::alignment;
use crate::core::text::{Hit, Shaping, Span, Text, Wrapping}; use crate::core::text::{Alignment, Hit, Shaping, Span, Text, Wrapping};
use crate::core::{Font, Point, Rectangle, Size}; use crate::core::{Font, Point, Rectangle, Size};
use crate::text; use crate::text;
@ -18,8 +18,8 @@ struct Internal {
font: Font, font: Font,
shaping: Shaping, shaping: Shaping,
wrapping: Wrapping, wrapping: Wrapping,
horizontal_alignment: alignment::Horizontal, align_x: Alignment,
vertical_alignment: alignment::Vertical, align_y: alignment::Vertical,
bounds: Size, bounds: Size,
min_bounds: Size, min_bounds: Size,
version: text::Version, version: text::Version,
@ -47,8 +47,8 @@ impl Paragraph {
Weak { Weak {
raw: Arc::downgrade(paragraph), raw: Arc::downgrade(paragraph),
min_bounds: paragraph.min_bounds, min_bounds: paragraph.min_bounds,
horizontal_alignment: paragraph.horizontal_alignment, align_x: paragraph.align_x,
vertical_alignment: paragraph.vertical_alignment, align_y: paragraph.align_y,
} }
} }
@ -89,13 +89,13 @@ impl core::text::Paragraph for Paragraph {
text::to_shaping(text.shaping), text::to_shaping(text.shaping),
); );
let min_bounds = text::measure(&buffer); let min_bounds = align(&mut buffer, &mut font_system, text.align_x);
Self(Arc::new(Internal { Self(Arc::new(Internal {
buffer, buffer,
font: text.font, font: text.font,
horizontal_alignment: text.horizontal_alignment, align_x: text.align_x,
vertical_alignment: text.vertical_alignment, align_y: text.align_y,
shaping: text.shaping, shaping: text.shaping,
wrapping: text.wrapping, wrapping: text.wrapping,
bounds: text.bounds, bounds: text.bounds,
@ -156,15 +156,16 @@ impl core::text::Paragraph for Paragraph {
}), }),
text::to_attributes(text.font), text::to_attributes(text.font),
text::to_shaping(text.shaping), text::to_shaping(text.shaping),
None,
); );
let min_bounds = text::measure(&buffer); let min_bounds = align(&mut buffer, &mut font_system, text.align_x);
Self(Arc::new(Internal { Self(Arc::new(Internal {
buffer, buffer,
font: text.font, font: text.font,
horizontal_alignment: text.horizontal_alignment, align_x: text.align_x,
vertical_alignment: text.vertical_alignment, align_y: text.align_y,
shaping: text.shaping, shaping: text.shaping,
wrapping: text.wrapping, wrapping: text.wrapping,
bounds: text.bounds, bounds: text.bounds,
@ -185,8 +186,10 @@ impl core::text::Paragraph for Paragraph {
Some(new_bounds.height), Some(new_bounds.height),
); );
let (min_bounds, _has_rtl) = text::measure(&paragraph.buffer);
paragraph.bounds = new_bounds; paragraph.bounds = new_bounds;
paragraph.min_bounds = text::measure(&paragraph.buffer); paragraph.min_bounds = min_bounds;
} }
fn compare(&self, text: Text<()>) -> core::text::Difference { fn compare(&self, text: Text<()>) -> core::text::Difference {
@ -200,8 +203,8 @@ impl core::text::Paragraph for Paragraph {
|| paragraph.font != text.font || paragraph.font != text.font
|| paragraph.shaping != text.shaping || paragraph.shaping != text.shaping
|| paragraph.wrapping != text.wrapping || paragraph.wrapping != text.wrapping
|| paragraph.horizontal_alignment != text.horizontal_alignment || paragraph.align_x != text.align_x
|| paragraph.vertical_alignment != text.vertical_alignment || paragraph.align_y != text.align_y
{ {
core::text::Difference::Shape core::text::Difference::Shape
} else if paragraph.bounds != text.bounds { } else if paragraph.bounds != text.bounds {
@ -211,12 +214,12 @@ impl core::text::Paragraph for Paragraph {
} }
} }
fn horizontal_alignment(&self) -> alignment::Horizontal { fn align_x(&self) -> Alignment {
self.internal().horizontal_alignment self.internal().align_x
} }
fn vertical_alignment(&self) -> alignment::Vertical { fn align_y(&self) -> alignment::Vertical {
self.internal().vertical_alignment self.internal().align_y
} }
fn min_bounds(&self) -> Size { fn min_bounds(&self) -> Size {
@ -353,6 +356,43 @@ impl core::text::Paragraph for Paragraph {
} }
} }
fn align(
buffer: &mut cosmic_text::Buffer,
font_system: &mut text::FontSystem,
alignment: Alignment,
) -> Size {
let (min_bounds, has_rtl) = text::measure(buffer);
let mut needs_relayout = has_rtl;
if let Some(align) = text::to_align(alignment) {
let has_multiple_lines = buffer.lines.len() > 1
|| buffer.lines.first().is_some_and(|line| {
line.layout_opt().is_some_and(|layout| layout.len() > 1)
});
if has_multiple_lines {
for line in &mut buffer.lines {
let _ = line.set_align(Some(align));
}
needs_relayout = true;
}
}
// TODO: Avoid relayout with some changes to `cosmic-text` (?)
if needs_relayout {
log::trace!("Relayouting paragraph...");
buffer.set_size(
font_system.raw(),
Some(min_bounds.width),
Some(min_bounds.height),
);
}
min_bounds
}
impl Default for Paragraph { impl Default for Paragraph {
fn default() -> Self { fn default() -> Self {
Self(Arc::new(Internal::default())) Self(Arc::new(Internal::default()))
@ -366,8 +406,8 @@ impl fmt::Debug for Paragraph {
f.debug_struct("Paragraph") f.debug_struct("Paragraph")
.field("font", &paragraph.font) .field("font", &paragraph.font)
.field("shaping", &paragraph.shaping) .field("shaping", &paragraph.shaping)
.field("horizontal_alignment", &paragraph.horizontal_alignment) .field("horizontal_alignment", &paragraph.align_x)
.field("vertical_alignment", &paragraph.vertical_alignment) .field("vertical_alignment", &paragraph.align_y)
.field("bounds", &paragraph.bounds) .field("bounds", &paragraph.bounds)
.field("min_bounds", &paragraph.min_bounds) .field("min_bounds", &paragraph.min_bounds)
.finish() .finish()
@ -378,8 +418,8 @@ impl PartialEq for Internal {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.font == other.font self.font == other.font
&& self.shaping == other.shaping && self.shaping == other.shaping
&& self.horizontal_alignment == other.horizontal_alignment && self.align_x == other.align_x
&& self.vertical_alignment == other.vertical_alignment && self.align_y == other.align_y
&& self.bounds == other.bounds && self.bounds == other.bounds
&& self.min_bounds == other.min_bounds && self.min_bounds == other.min_bounds
&& self.buffer.metrics() == other.buffer.metrics() && self.buffer.metrics() == other.buffer.metrics()
@ -396,8 +436,8 @@ impl Default for Internal {
font: Font::default(), font: Font::default(),
shaping: Shaping::default(), shaping: Shaping::default(),
wrapping: Wrapping::default(), wrapping: Wrapping::default(),
horizontal_alignment: alignment::Horizontal::Left, align_x: Alignment::Default,
vertical_alignment: alignment::Vertical::Top, align_y: alignment::Vertical::Top,
bounds: Size::ZERO, bounds: Size::ZERO,
min_bounds: Size::ZERO, min_bounds: Size::ZERO,
version: text::Version::default(), version: text::Version::default(),
@ -412,9 +452,9 @@ pub struct Weak {
/// The minimum bounds of the [`Paragraph`]. /// The minimum bounds of the [`Paragraph`].
pub min_bounds: Size, pub min_bounds: Size,
/// The horizontal alignment of the [`Paragraph`]. /// The horizontal alignment of the [`Paragraph`].
pub horizontal_alignment: alignment::Horizontal, pub align_x: Alignment,
/// The vertical alignment of the [`Paragraph`]. /// The vertical alignment of the [`Paragraph`].
pub vertical_alignment: alignment::Vertical, pub align_y: alignment::Vertical,
} }
impl Weak { impl Weak {

View file

@ -37,7 +37,7 @@ impl<T> Task<T> {
/// output with the given closure. /// output with the given closure.
pub fn perform<A>( pub fn perform<A>(
future: impl Future<Output = A> + MaybeSend + 'static, future: impl Future<Output = A> + MaybeSend + 'static,
f: impl Fn(A) -> T + MaybeSend + 'static, f: impl FnOnce(A) -> T + MaybeSend + 'static,
) -> Self ) -> Self
where where
T: MaybeSend + 'static, T: MaybeSend + 'static,

View file

@ -399,8 +399,8 @@ impl Engine {
size, size,
line_height, line_height,
font, font,
horizontal_alignment, align_x,
vertical_alignment, align_y,
shaping, shaping,
clip_bounds: text_bounds, // TODO clip_bounds: text_bounds, // TODO
} => { } => {
@ -420,8 +420,8 @@ impl Engine {
*size, *size,
*line_height, *line_height,
*font, *font,
*horizontal_alignment, *align_x,
*vertical_alignment, *align_y,
*shaping, *shaping,
pixels, pixels,
clip_mask, clip_mask,

View file

@ -231,8 +231,8 @@ impl geometry::frame::Backend for Frame {
size, size,
line_height: line_height.to_absolute(size), line_height: line_height.to_absolute(size),
font: text.font, font: text.font,
horizontal_alignment: text.horizontal_alignment, align_x: text.align_x.into(),
vertical_alignment: text.vertical_alignment, align_y: text.align_y,
shaping: text.shaping, shaping: text.shaping,
clip_bounds: Rectangle::with_size(Size::INFINITY), clip_bounds: Rectangle::with_size(Size::INFINITY),
}); });

View file

@ -86,8 +86,8 @@ impl Layer {
line_height: text.line_height.to_absolute(text.size) line_height: text.line_height.to_absolute(text.size)
* transformation.scale_factor(), * transformation.scale_factor(),
font: text.font, font: text.font,
horizontal_alignment: text.horizontal_alignment, align_x: text.align_x,
vertical_alignment: text.vertical_alignment, align_y: text.align_y,
shaping: text.shaping, shaping: text.shaping,
clip_bounds: clip_bounds * transformation, clip_bounds: clip_bounds * transformation,
}; };

View file

@ -1,5 +1,5 @@
use crate::core::alignment; use crate::core::alignment;
use crate::core::text::Shaping; use crate::core::text::{Alignment, Shaping};
use crate::core::{ use crate::core::{
Color, Font, Pixels, Point, Rectangle, Size, Transformation, Color, Font, Pixels, Point, Rectangle, Size, Transformation,
}; };
@ -61,8 +61,8 @@ impl Pipeline {
paragraph.buffer(), paragraph.buffer(),
Rectangle::new(position, paragraph.min_bounds()), Rectangle::new(position, paragraph.min_bounds()),
color, color,
paragraph.horizontal_alignment(), paragraph.align_x(),
paragraph.vertical_alignment(), paragraph.align_y(),
pixels, pixels,
clip_mask, clip_mask,
transformation, transformation,
@ -92,7 +92,7 @@ impl Pipeline {
editor.buffer(), editor.buffer(),
Rectangle::new(position, editor.bounds()), Rectangle::new(position, editor.bounds()),
color, color,
alignment::Horizontal::Left, Alignment::Default,
alignment::Vertical::Top, alignment::Vertical::Top,
pixels, pixels,
clip_mask, clip_mask,
@ -108,7 +108,7 @@ impl Pipeline {
size: Pixels, size: Pixels,
line_height: Pixels, line_height: Pixels,
font: Font, font: Font,
horizontal_alignment: alignment::Horizontal, horizontal_alignment: Alignment,
vertical_alignment: alignment::Vertical, vertical_alignment: alignment::Vertical,
shaping: Shaping, shaping: Shaping,
pixels: &mut tiny_skia::PixmapMut<'_>, pixels: &mut tiny_skia::PixmapMut<'_>,
@ -177,7 +177,7 @@ impl Pipeline {
), ),
), ),
color, color,
alignment::Horizontal::Left, Alignment::Default,
alignment::Vertical::Top, alignment::Vertical::Top,
pixels, pixels,
clip_mask, clip_mask,
@ -197,21 +197,21 @@ fn draw(
buffer: &cosmic_text::Buffer, buffer: &cosmic_text::Buffer,
bounds: Rectangle, bounds: Rectangle,
color: Color, color: Color,
horizontal_alignment: alignment::Horizontal, align_x: Alignment,
vertical_alignment: alignment::Vertical, align_y: alignment::Vertical,
pixels: &mut tiny_skia::PixmapMut<'_>, pixels: &mut tiny_skia::PixmapMut<'_>,
clip_mask: Option<&tiny_skia::Mask>, clip_mask: Option<&tiny_skia::Mask>,
transformation: Transformation, transformation: Transformation,
) { ) {
let bounds = bounds * transformation; let bounds = bounds * transformation;
let x = match horizontal_alignment { let x = match align_x {
alignment::Horizontal::Left => bounds.x, Alignment::Default | Alignment::Left | Alignment::Justified => bounds.x,
alignment::Horizontal::Center => bounds.x - bounds.width / 2.0, Alignment::Center => bounds.x - bounds.width / 2.0,
alignment::Horizontal::Right => bounds.x - bounds.width, Alignment::Right => bounds.x - bounds.width,
}; };
let y = match vertical_alignment { let y = match align_y {
alignment::Vertical::Top => bounds.y, alignment::Vertical::Top => bounds.y,
alignment::Vertical::Center => bounds.y - bounds.height / 2.0, alignment::Vertical::Center => bounds.y - bounds.height / 2.0,
alignment::Vertical::Bottom => bounds.y - bounds.height, alignment::Vertical::Bottom => bounds.y - bounds.height,

View file

@ -32,7 +32,7 @@ bitflags.workspace = true
bytemuck.workspace = true bytemuck.workspace = true
futures.workspace = true futures.workspace = true
glam.workspace = true glam.workspace = true
glyphon.workspace = true cryoglyph.workspace = true
guillotiere.workspace = true guillotiere.workspace = true
log.workspace = true log.workspace = true
rustc-hash.workspace = true rustc-hash.workspace = true

View file

@ -336,8 +336,8 @@ impl geometry::frame::Backend for Frame {
size, size,
line_height: line_height.to_absolute(size), line_height: line_height.to_absolute(size),
font: text.font, font: text.font,
horizontal_alignment: text.horizontal_alignment, align_x: text.align_x.into(),
vertical_alignment: text.vertical_alignment, align_y: text.align_y,
shaping: text.shaping, shaping: text.shaping,
clip_bounds: self.clip_bounds, clip_bounds: self.clip_bounds,
}); });

View file

@ -344,15 +344,15 @@ impl Atlas {
}); });
encoder.copy_buffer_to_texture( encoder.copy_buffer_to_texture(
wgpu::ImageCopyBuffer { wgpu::TexelCopyBufferInfo {
buffer: &buffer, buffer: &buffer,
layout: wgpu::ImageDataLayout { layout: wgpu::TexelCopyBufferLayout {
offset: offset as u64, offset: offset as u64,
bytes_per_row: Some(4 * image_width + padding), bytes_per_row: Some(4 * image_width + padding),
rows_per_image: Some(image_height), rows_per_image: Some(image_height),
}, },
}, },
wgpu::ImageCopyTexture { wgpu::TexelCopyTextureInfo {
texture: &self.texture, texture: &self.texture,
mip_level: 0, mip_level: 0,
origin: wgpu::Origin3d { origin: wgpu::Origin3d {
@ -407,7 +407,7 @@ impl Atlas {
} }
encoder.copy_texture_to_texture( encoder.copy_texture_to_texture(
wgpu::ImageCopyTexture { wgpu::TexelCopyTextureInfo {
texture: &self.texture, texture: &self.texture,
mip_level: 0, mip_level: 0,
origin: wgpu::Origin3d { origin: wgpu::Origin3d {
@ -417,7 +417,7 @@ impl Atlas {
}, },
aspect: wgpu::TextureAspect::default(), aspect: wgpu::TextureAspect::default(),
}, },
wgpu::ImageCopyTexture { wgpu::TexelCopyTextureInfo {
texture: &new_texture, texture: &new_texture,
mip_level: 0, mip_level: 0,
origin: wgpu::Origin3d { origin: wgpu::Origin3d {

View file

@ -103,8 +103,8 @@ impl Layer {
line_height: text.line_height.to_absolute(text.size) line_height: text.line_height.to_absolute(text.size)
* transformation.scale_factor(), * transformation.scale_factor(),
font: text.font, font: text.font,
horizontal_alignment: text.horizontal_alignment, align_x: text.align_x,
vertical_alignment: text.vertical_alignment, align_y: text.align_y,
shaping: text.shaping, shaping: text.shaping,
clip_bounds: clip_bounds * transformation, clip_bounds: clip_bounds * transformation,
}; };

View file

@ -1,4 +1,5 @@
use crate::core::alignment; use crate::core::alignment;
use crate::core::text::Alignment;
use crate::core::{Rectangle, Size, Transformation}; use crate::core::{Rectangle, Size, Transformation};
use crate::graphics::cache; use crate::graphics::cache;
use crate::graphics::color; use crate::graphics::color;
@ -12,10 +13,10 @@ use std::sync::{self, Arc};
pub use crate::graphics::Text; pub use crate::graphics::Text;
const COLOR_MODE: glyphon::ColorMode = if color::GAMMA_CORRECTION { const COLOR_MODE: cryoglyph::ColorMode = if color::GAMMA_CORRECTION {
glyphon::ColorMode::Accurate cryoglyph::ColorMode::Accurate
} else { } else {
glyphon::ColorMode::Web cryoglyph::ColorMode::Web
}; };
pub type Batch = Vec<Item>; pub type Batch = Vec<Item>;
@ -70,7 +71,7 @@ impl Cache {
} }
struct Upload { struct Upload {
renderer: glyphon::TextRenderer, renderer: cryoglyph::TextRenderer,
buffer_cache: BufferCache, buffer_cache: BufferCache,
transformation: Transformation, transformation: Transformation,
version: usize, version: usize,
@ -86,7 +87,7 @@ pub struct Storage {
} }
struct Group { struct Group {
atlas: glyphon::TextAtlas, atlas: cryoglyph::TextAtlas,
version: usize, version: usize,
should_trim: bool, should_trim: bool,
handle: Arc<()>, // Keeps track of active uploads handle: Arc<()>, // Keeps track of active uploads
@ -97,7 +98,7 @@ impl Storage {
Self::default() Self::default()
} }
fn get(&self, cache: &Cache) -> Option<(&glyphon::TextAtlas, &Upload)> { fn get(&self, cache: &Cache) -> Option<(&cryoglyph::TextAtlas, &Upload)> {
if cache.text.is_empty() { if cache.text.is_empty() {
return None; return None;
} }
@ -112,10 +113,10 @@ impl Storage {
&mut self, &mut self,
device: &wgpu::Device, device: &wgpu::Device,
queue: &wgpu::Queue, queue: &wgpu::Queue,
viewport: &glyphon::Viewport, viewport: &cryoglyph::Viewport,
encoder: &mut wgpu::CommandEncoder, encoder: &mut wgpu::CommandEncoder,
format: wgpu::TextureFormat, format: wgpu::TextureFormat,
state: &glyphon::Cache, state: &cryoglyph::Cache,
cache: &Cache, cache: &Cache,
new_transformation: Transformation, new_transformation: Transformation,
bounds: Rectangle, bounds: Rectangle,
@ -130,7 +131,7 @@ impl Storage {
); );
Group { Group {
atlas: glyphon::TextAtlas::with_color_mode( atlas: cryoglyph::TextAtlas::with_color_mode(
device, queue, state, format, COLOR_MODE, device, queue, state, format, COLOR_MODE,
), ),
version: 0, version: 0,
@ -175,7 +176,7 @@ impl Storage {
} }
} }
hash_map::Entry::Vacant(entry) => { hash_map::Entry::Vacant(entry) => {
let mut renderer = glyphon::TextRenderer::new( let mut renderer = cryoglyph::TextRenderer::new(
&mut group.atlas, &mut group.atlas,
device, device,
wgpu::MultisampleState::default(), wgpu::MultisampleState::default(),
@ -257,13 +258,13 @@ impl Storage {
} }
} }
pub struct Viewport(glyphon::Viewport); pub struct Viewport(cryoglyph::Viewport);
impl Viewport { impl Viewport {
pub fn update(&mut self, queue: &wgpu::Queue, resolution: Size<u32>) { pub fn update(&mut self, queue: &wgpu::Queue, resolution: Size<u32>) {
self.0.update( self.0.update(
queue, queue,
glyphon::Resolution { cryoglyph::Resolution {
width: resolution.width, width: resolution.width,
height: resolution.height, height: resolution.height,
}, },
@ -273,10 +274,10 @@ impl Viewport {
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
pub struct Pipeline { pub struct Pipeline {
state: glyphon::Cache, state: cryoglyph::Cache,
format: wgpu::TextureFormat, format: wgpu::TextureFormat,
atlas: glyphon::TextAtlas, atlas: cryoglyph::TextAtlas,
renderers: Vec<glyphon::TextRenderer>, renderers: Vec<cryoglyph::TextRenderer>,
prepare_layer: usize, prepare_layer: usize,
cache: BufferCache, cache: BufferCache,
} }
@ -287,8 +288,8 @@ impl Pipeline {
queue: &wgpu::Queue, queue: &wgpu::Queue,
format: wgpu::TextureFormat, format: wgpu::TextureFormat,
) -> Self { ) -> Self {
let state = glyphon::Cache::new(device); let state = cryoglyph::Cache::new(device);
let atlas = glyphon::TextAtlas::with_color_mode( let atlas = cryoglyph::TextAtlas::with_color_mode(
device, queue, &state, format, COLOR_MODE, device, queue, &state, format, COLOR_MODE,
); );
@ -320,7 +321,7 @@ impl Pipeline {
text, text,
} => { } => {
if self.renderers.len() <= self.prepare_layer { if self.renderers.len() <= self.prepare_layer {
self.renderers.push(glyphon::TextRenderer::new( self.renderers.push(cryoglyph::TextRenderer::new(
&mut self.atlas, &mut self.atlas,
device, device,
wgpu::MultisampleState::default(), wgpu::MultisampleState::default(),
@ -346,7 +347,7 @@ impl Pipeline {
Ok(()) => { Ok(()) => {
self.prepare_layer += 1; self.prepare_layer += 1;
} }
Err(glyphon::PrepareError::AtlasFull) => { Err(cryoglyph::PrepareError::AtlasFull) => {
// If the atlas cannot grow, then all bets are off. // If the atlas cannot grow, then all bets are off.
// Instead of panicking, we will just pray that the result // Instead of panicking, we will just pray that the result
// will be somewhat readable... // will be somewhat readable...
@ -417,7 +418,7 @@ impl Pipeline {
} }
pub fn create_viewport(&self, device: &wgpu::Device) -> Viewport { pub fn create_viewport(&self, device: &wgpu::Device) -> Viewport {
Viewport(glyphon::Viewport::new(device, &self.state)) Viewport(cryoglyph::Viewport::new(device, &self.state))
} }
pub fn end_frame(&mut self) { pub fn end_frame(&mut self) {
@ -431,15 +432,15 @@ impl Pipeline {
fn prepare( fn prepare(
device: &wgpu::Device, device: &wgpu::Device,
queue: &wgpu::Queue, queue: &wgpu::Queue,
viewport: &glyphon::Viewport, viewport: &cryoglyph::Viewport,
encoder: &mut wgpu::CommandEncoder, encoder: &mut wgpu::CommandEncoder,
renderer: &mut glyphon::TextRenderer, renderer: &mut cryoglyph::TextRenderer,
atlas: &mut glyphon::TextAtlas, atlas: &mut cryoglyph::TextAtlas,
buffer_cache: &mut BufferCache, buffer_cache: &mut BufferCache,
sections: &[Text], sections: &[Text],
layer_bounds: Rectangle, layer_bounds: Rectangle,
layer_transformation: Transformation, layer_transformation: Transformation,
) -> Result<(), glyphon::PrepareError> { ) -> Result<(), cryoglyph::PrepareError> {
let mut font_system = font_system().write().expect("Write font system"); let mut font_system = font_system().write().expect("Write font system");
let font_system = font_system.raw(); let font_system = font_system.raw();
@ -447,7 +448,7 @@ fn prepare(
Paragraph(Paragraph), Paragraph(Paragraph),
Editor(Editor), Editor(Editor),
Cache(text_cache::KeyHash), Cache(text_cache::KeyHash),
Raw(Arc<glyphon::Buffer>), Raw(Arc<cryoglyph::Buffer>),
} }
let allocations: Vec<_> = sections let allocations: Vec<_> = sections
@ -494,8 +495,8 @@ fn prepare(
let ( let (
buffer, buffer,
bounds, bounds,
horizontal_alignment, align_x,
vertical_alignment, align_y,
color, color,
clip_bounds, clip_bounds,
transformation, transformation,
@ -517,8 +518,8 @@ fn prepare(
( (
paragraph.buffer(), paragraph.buffer(),
Rectangle::new(*position, paragraph.min_bounds()), Rectangle::new(*position, paragraph.min_bounds()),
paragraph.horizontal_alignment(), paragraph.align_x(),
paragraph.vertical_alignment(), paragraph.align_y(),
*color, *color,
*clip_bounds, *clip_bounds,
*transformation, *transformation,
@ -540,7 +541,7 @@ fn prepare(
( (
editor.buffer(), editor.buffer(),
Rectangle::new(*position, editor.bounds()), Rectangle::new(*position, editor.bounds()),
alignment::Horizontal::Left, Alignment::Default,
alignment::Vertical::Top, alignment::Vertical::Top,
*color, *color,
*clip_bounds, *clip_bounds,
@ -549,8 +550,8 @@ fn prepare(
} }
Text::Cached { Text::Cached {
bounds, bounds,
horizontal_alignment, align_x,
vertical_alignment, align_y,
color, color,
clip_bounds, clip_bounds,
.. ..
@ -565,8 +566,8 @@ fn prepare(
( (
&entry.buffer, &entry.buffer,
Rectangle::new(bounds.position(), entry.min_bounds), Rectangle::new(bounds.position(), entry.min_bounds),
*horizontal_alignment, *align_x,
*vertical_alignment, *align_y,
*color, *color,
*clip_bounds, *clip_bounds,
Transformation::IDENTITY, Transformation::IDENTITY,
@ -591,7 +592,7 @@ fn prepare(
height.unwrap_or(layer_bounds.height), height.unwrap_or(layer_bounds.height),
), ),
), ),
alignment::Horizontal::Left, Alignment::Default,
alignment::Vertical::Top, alignment::Vertical::Top,
raw.color, raw.color,
raw.clip_bounds, raw.clip_bounds,
@ -602,13 +603,15 @@ fn prepare(
let bounds = bounds * transformation * layer_transformation; let bounds = bounds * transformation * layer_transformation;
let left = match horizontal_alignment { let left = match align_x {
alignment::Horizontal::Left => bounds.x, Alignment::Default | Alignment::Left | Alignment::Justified => {
alignment::Horizontal::Center => bounds.x - bounds.width / 2.0, bounds.x
alignment::Horizontal::Right => bounds.x - bounds.width, }
Alignment::Center => bounds.x - bounds.width / 2.0,
Alignment::Right => bounds.x - bounds.width,
}; };
let top = match vertical_alignment { let top = match align_y {
alignment::Vertical::Top => bounds.y, alignment::Vertical::Top => bounds.y,
alignment::Vertical::Center => bounds.y - bounds.height / 2.0, alignment::Vertical::Center => bounds.y - bounds.height / 2.0,
alignment::Vertical::Bottom => bounds.y - bounds.height, alignment::Vertical::Bottom => bounds.y - bounds.height,
@ -618,13 +621,13 @@ fn prepare(
&(clip_bounds * transformation * layer_transformation), &(clip_bounds * transformation * layer_transformation),
)?; )?;
Some(glyphon::TextArea { Some(cryoglyph::TextArea {
buffer, buffer,
left, left,
top, top,
scale: transformation.scale_factor() scale: transformation.scale_factor()
* layer_transformation.scale_factor(), * layer_transformation.scale_factor(),
bounds: glyphon::TextBounds { bounds: cryoglyph::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,
right: (clip_bounds.x + clip_bounds.width) as i32, right: (clip_bounds.x + clip_bounds.width) as i32,
@ -643,6 +646,6 @@ fn prepare(
atlas, atlas,
viewport, viewport,
text_areas, text_areas,
&mut glyphon::SwashCache::new(), &mut cryoglyph::SwashCache::new(),
) )
} }

View file

@ -54,7 +54,7 @@ impl Compositor {
settings: Settings, settings: Settings,
compatible_window: Option<W>, compatible_window: Option<W>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
backends: settings.backends, backends: settings.backends,
flags: if cfg!(feature = "strict-assertions") { flags: if cfg!(feature = "strict-assertions") {
wgpu::InstanceFlags::debugging() wgpu::InstanceFlags::debugging()
@ -81,12 +81,13 @@ impl Compositor {
.and_then(|window| instance.create_surface(window).ok()); .and_then(|window| instance.create_surface(window).ok());
let adapter_options = wgpu::RequestAdapterOptions { let adapter_options = wgpu::RequestAdapterOptions {
power_preference: wgpu::util::power_preference_from_env() power_preference: wgpu::PowerPreference::from_env().unwrap_or(
.unwrap_or(if settings.antialiasing.is_none() { if settings.antialiasing.is_none() {
wgpu::PowerPreference::LowPower wgpu::PowerPreference::LowPower
} else { } else {
wgpu::PowerPreference::HighPerformance wgpu::PowerPreference::HighPerformance
}), },
),
compatible_surface: compatible_surface.as_ref(), compatible_surface: compatible_surface.as_ref(),
force_fallback_adapter: false, force_fallback_adapter: false,
}; };
@ -261,6 +262,7 @@ pub fn present(
wgpu::SurfaceError::OutOfMemory => { wgpu::SurfaceError::OutOfMemory => {
Err(compositor::SurfaceError::OutOfMemory) Err(compositor::SurfaceError::OutOfMemory)
} }
wgpu::SurfaceError::Other => Err(compositor::SurfaceError::Other),
}, },
} }
} }
@ -278,7 +280,7 @@ impl graphics::Compositor for Compositor {
None | Some("wgpu") => { None | Some("wgpu") => {
let mut settings = Settings::from(settings); let mut settings = Settings::from(settings);
if let Some(backends) = wgpu::util::backend_bits_from_env() { if let Some(backends) = wgpu::Backends::from_env() {
settings.backends = backends; settings.backends = backends;
} }
@ -445,9 +447,9 @@ pub fn screenshot(
encoder.copy_texture_to_buffer( encoder.copy_texture_to_buffer(
texture.as_image_copy(), texture.as_image_copy(),
wgpu::ImageCopyBuffer { wgpu::TexelCopyBufferInfo {
buffer: &output_buffer, buffer: &output_buffer,
layout: wgpu::ImageDataLayout { layout: wgpu::TexelCopyBufferLayout {
offset: 0, offset: 0,
bytes_per_row: Some(dimensions.padded_bytes_per_row as u32), bytes_per_row: Some(dimensions.padded_bytes_per_row as u32),
rows_per_image: None, rows_per_image: None,

View file

@ -293,7 +293,7 @@ where
self.text_line_height, self.text_line_height,
self.text_size, self.text_size,
self.font, self.font,
alignment::Horizontal::Left, text::Alignment::Default,
alignment::Vertical::Top, alignment::Vertical::Top,
self.text_shaping, self.text_shaping,
self.text_wrapping, self.text_wrapping,
@ -416,8 +416,8 @@ where
size, size,
line_height: *line_height, line_height: *line_height,
bounds: bounds.size(), bounds: bounds.size(),
horizontal_alignment: alignment::Horizontal::Center, align_x: text::Alignment::Center,
vertical_alignment: alignment::Vertical::Center, align_y: alignment::Vertical::Center,
shaping: *shaping, shaping: *shaping,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::default(),
}, },

View file

@ -552,8 +552,8 @@ where
size: text_size, size: text_size,
line_height: self.text_line_height, line_height: self.text_line_height,
font: self.font.unwrap_or_else(|| renderer.default_font()), font: self.font.unwrap_or_else(|| renderer.default_font()),
horizontal_alignment: alignment::Horizontal::Left, align_x: text::Alignment::Default,
vertical_alignment: alignment::Vertical::Center, align_y: alignment::Vertical::Center,
shaping: self.text_shaping, shaping: self.text_shaping,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::default(),
}, },

View file

@ -371,8 +371,8 @@ where
size: text_size, size: text_size,
line_height: self.text_line_height, line_height: self.text_line_height,
font, font,
horizontal_alignment: alignment::Horizontal::Left, align_x: text::Alignment::Default,
vertical_alignment: alignment::Vertical::Center, align_y: alignment::Vertical::Center,
shaping: self.text_shaping, shaping: self.text_shaping,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::default(),
}; };
@ -639,8 +639,8 @@ where
bounds.width, bounds.width,
f32::from(line_height.to_absolute(size)), f32::from(line_height.to_absolute(size)),
), ),
horizontal_alignment: alignment::Horizontal::Right, align_x: text::Alignment::Right,
vertical_alignment: alignment::Vertical::Center, align_y: alignment::Vertical::Center,
shaping, shaping,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::default(),
}, },
@ -669,8 +669,8 @@ where
bounds.width - self.padding.horizontal(), bounds.width - self.padding.horizontal(),
f32::from(self.text_line_height.to_absolute(text_size)), f32::from(self.text_line_height.to_absolute(text_size)),
), ),
horizontal_alignment: alignment::Horizontal::Left, align_x: text::Alignment::Default,
vertical_alignment: alignment::Vertical::Center, align_y: alignment::Vertical::Center,
shaping: self.text_shaping, shaping: self.text_shaping,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::default(),
}, },

View file

@ -314,7 +314,7 @@ where
self.text_line_height, self.text_line_height,
self.text_size, self.text_size,
self.font, self.font,
alignment::Horizontal::Left, text::Alignment::Default,
alignment::Vertical::Top, alignment::Vertical::Top,
self.text_shaping, self.text_shaping,
self.text_wrapping, self.text_wrapping,

View file

@ -4,7 +4,7 @@ use crate::core::mouse;
use crate::core::renderer; use crate::core::renderer;
use crate::core::text::{Paragraph, Span}; use crate::core::text::{Paragraph, Span};
use crate::core::widget::text::{ use crate::core::widget::text::{
self, Catalog, LineHeight, Shaping, Style, StyleFn, Wrapping, self, Alignment, Catalog, LineHeight, Shaping, Style, StyleFn, Wrapping,
}; };
use crate::core::widget::tree::{self, Tree}; use crate::core::widget::tree::{self, Tree};
use crate::core::{ use crate::core::{
@ -31,7 +31,7 @@ pub struct Rich<
width: Length, width: Length,
height: Length, height: Length,
font: Option<Renderer::Font>, font: Option<Renderer::Font>,
align_x: alignment::Horizontal, align_x: Alignment,
align_y: alignment::Vertical, align_y: alignment::Vertical,
wrapping: Wrapping, wrapping: Wrapping,
class: Theme::Class<'a>, class: Theme::Class<'a>,
@ -56,7 +56,7 @@ where
width: Length::Shrink, width: Length::Shrink,
height: Length::Shrink, height: Length::Shrink,
font: None, font: None,
align_x: alignment::Horizontal::Left, align_x: Alignment::Default,
align_y: alignment::Vertical::Top, align_y: alignment::Vertical::Top,
wrapping: Wrapping::default(), wrapping: Wrapping::default(),
class: Theme::default(), class: Theme::default(),
@ -112,10 +112,7 @@ where
} }
/// Sets the [`alignment::Horizontal`] of the [`Rich`] text. /// Sets the [`alignment::Horizontal`] of the [`Rich`] text.
pub fn align_x( pub fn align_x(mut self, alignment: impl Into<Alignment>) -> Self {
mut self,
alignment: impl Into<alignment::Horizontal>,
) -> Self {
self.align_x = alignment.into(); self.align_x = alignment.into();
self self
} }
@ -476,8 +473,8 @@ fn layout<Link, Renderer>(
line_height: LineHeight, line_height: LineHeight,
size: Option<Pixels>, size: Option<Pixels>,
font: Option<Renderer::Font>, font: Option<Renderer::Font>,
horizontal_alignment: alignment::Horizontal, align_x: Alignment,
vertical_alignment: alignment::Vertical, align_y: alignment::Vertical,
wrapping: Wrapping, wrapping: Wrapping,
) -> layout::Node ) -> layout::Node
where where
@ -496,8 +493,8 @@ where
size, size,
line_height, line_height,
font, font,
horizontal_alignment, align_x,
vertical_alignment, align_y,
shaping: Shaping::Advanced, shaping: Shaping::Advanced,
wrapping, wrapping,
}; };
@ -513,8 +510,8 @@ where
size, size,
line_height, line_height,
font, font,
horizontal_alignment, align_x,
vertical_alignment, align_y,
shaping: Shaping::Advanced, shaping: Shaping::Advanced,
wrapping, wrapping,
}) { }) {

View file

@ -955,8 +955,8 @@ where
.unwrap_or_else(|| renderer.default_size()), .unwrap_or_else(|| renderer.default_size()),
line_height: self.line_height, line_height: self.line_height,
font, font,
horizontal_alignment: alignment::Horizontal::Left, align_x: text::Alignment::Default,
vertical_alignment: alignment::Vertical::Top, align_y: alignment::Vertical::Top,
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
wrapping: self.wrapping, wrapping: self.wrapping,
}, },

View file

@ -319,8 +319,8 @@ where
content: self.placeholder.as_str(), content: self.placeholder.as_str(),
bounds: Size::new(f32::INFINITY, text_bounds.height), bounds: Size::new(f32::INFINITY, text_bounds.height),
size: text_size, size: text_size,
horizontal_alignment: alignment::Horizontal::Left, align_x: text::Alignment::Default,
vertical_alignment: alignment::Vertical::Center, align_y: alignment::Vertical::Center,
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::default(),
}; };
@ -344,8 +344,8 @@ where
font: icon.font, font: icon.font,
size: icon.size.unwrap_or_else(|| renderer.default_size()), size: icon.size.unwrap_or_else(|| renderer.default_size()),
bounds: Size::new(f32::INFINITY, text_bounds.height), bounds: Size::new(f32::INFINITY, text_bounds.height),
horizontal_alignment: alignment::Horizontal::Center, align_x: text::Alignment::Center,
vertical_alignment: alignment::Vertical::Center, align_y: alignment::Vertical::Center,
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::default(),
}; };
@ -1727,8 +1727,8 @@ fn replace_paragraph<Renderer>(
content: &value.to_string(), content: &value.to_string(),
bounds: Size::new(f32::INFINITY, text_bounds.height), bounds: Size::new(f32::INFINITY, text_bounds.height),
size: text_size, size: text_size,
horizontal_alignment: alignment::Horizontal::Left, align_x: text::Alignment::Default,
vertical_alignment: alignment::Vertical::Center, align_y: alignment::Vertical::Center,
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::default(),
}); });

View file

@ -93,7 +93,7 @@ pub struct Toggler<
size: f32, size: f32,
text_size: Option<Pixels>, text_size: Option<Pixels>,
text_line_height: text::LineHeight, text_line_height: text::LineHeight,
text_alignment: alignment::Horizontal, text_alignment: text::Alignment,
text_shaping: text::Shaping, text_shaping: text::Shaping,
text_wrapping: text::Wrapping, text_wrapping: text::Wrapping,
spacing: f32, spacing: f32,
@ -127,7 +127,7 @@ where
size: Self::DEFAULT_SIZE, size: Self::DEFAULT_SIZE,
text_size: None, text_size: None,
text_line_height: text::LineHeight::default(), text_line_height: text::LineHeight::default(),
text_alignment: alignment::Horizontal::Left, text_alignment: text::Alignment::Default,
text_shaping: text::Shaping::default(), text_shaping: text::Shaping::default(),
text_wrapping: text::Wrapping::default(), text_wrapping: text::Wrapping::default(),
spacing: Self::DEFAULT_SIZE / 2.0, spacing: Self::DEFAULT_SIZE / 2.0,
@ -195,8 +195,11 @@ where
} }
/// Sets the horizontal alignment of the text of the [`Toggler`] /// Sets the horizontal alignment of the text of the [`Toggler`]
pub fn text_alignment(mut self, alignment: alignment::Horizontal) -> Self { pub fn text_alignment(
self.text_alignment = alignment; mut self,
alignment: impl Into<text::Alignment>,
) -> Self {
self.text_alignment = alignment.into();
self self
} }

View file

@ -338,8 +338,8 @@ where
.unwrap_or_else(|| renderer.default_size()), .unwrap_or_else(|| renderer.default_size()),
line_height: text::LineHeight::default(), line_height: text::LineHeight::default(),
font: renderer.default_font(), font: renderer.default_font(),
horizontal_alignment: alignment::Horizontal::Left, align_x: text::Alignment::Default,
vertical_alignment: alignment::Vertical::Top, align_y: alignment::Vertical::Top,
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
wrapping: text::Wrapping::None, wrapping: text::Wrapping::None,
}); });