Introduce text::Alignment with Justified support

This commit is contained in:
Héctor Ramón Jiménez 2025-03-11 02:25:44 +01:00
parent e45d4b5cb6
commit 0e4a392731
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
30 changed files with 227 additions and 195 deletions

View file

@ -30,9 +30,9 @@ pub struct Text {
/// The font of the text
pub font: Font,
/// The horizontal alignment of the text
pub horizontal_alignment: alignment::Horizontal,
pub align_x: alignment::Horizontal,
/// The vertical alignment of the text
pub vertical_alignment: alignment::Vertical,
pub align_y: alignment::Vertical,
/// The shaping strategy of the text.
pub shaping: Shaping,
}
@ -60,7 +60,7 @@ impl Text {
4,
);
let translation_x = match self.horizontal_alignment {
let translation_x = match self.align_x {
alignment::Horizontal::Left => self.position.x,
alignment::Horizontal::Center | alignment::Horizontal::Right => {
let mut line_width = 0.0f32;
@ -69,7 +69,7 @@ impl Text {
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
} else {
self.position.x - line_width
@ -80,7 +80,7 @@ impl Text {
let translation_y = {
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::Center => {
self.position.y - line_height.0 / 2.0
@ -180,8 +180,8 @@ impl Default for Text {
size: Pixels(16.0),
line_height: LineHeight::Relative(1.2),
font: Font::default(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
align_x: alignment::Horizontal::Left,
align_y: alignment::Vertical::Top,
shaping: Shaping::Basic,
}
}

View file

@ -11,7 +11,7 @@ pub use cosmic_text;
use crate::core::alignment;
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 std::borrow::Cow;
@ -54,9 +54,9 @@ pub enum Text {
/// The font of the text.
font: Font,
/// The horizontal alignment of the text.
horizontal_alignment: Option<alignment::Horizontal>,
align_x: Alignment,
/// The vertical alignment of the text.
vertical_alignment: alignment::Vertical,
align_y: alignment::Vertical,
/// The shaping strategy of the text.
shaping: Shaping,
/// The clip bounds of the text.
@ -73,7 +73,7 @@ pub enum Text {
impl Text {
/// Returns the visible bounds of the [`Text`].
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 {
position,
paragraph,
@ -84,8 +84,8 @@ impl Text {
Rectangle::new(*position, paragraph.min_bounds)
.intersection(clip_bounds)
.map(|bounds| bounds * *transformation),
paragraph.horizontal_alignment,
Some(paragraph.vertical_alignment),
paragraph.align_x,
Some(paragraph.align_y),
),
Text::Editor {
editor,
@ -97,38 +97,38 @@ impl Text {
Rectangle::new(*position, editor.bounds)
.intersection(clip_bounds)
.map(|bounds| bounds * *transformation),
None,
Alignment::Default,
None,
),
Text::Cached {
bounds,
clip_bounds,
horizontal_alignment,
vertical_alignment,
align_x: horizontal_alignment,
align_y: vertical_alignment,
..
} => (
bounds.intersection(clip_bounds),
*horizontal_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?;
if let Some(alignment) = horizontal_alignment {
match alignment {
alignment::Horizontal::Left => {}
alignment::Horizontal::Center => {
bounds.x -= bounds.width / 2.0;
}
alignment::Horizontal::Right => {
bounds.x -= bounds.width;
}
match align_x {
Alignment::Default | Alignment::Left | Alignment::Justified => {}
Alignment::Center => {
bounds.x -= bounds.width / 2.0;
}
Alignment::Right => {
bounds.x -= bounds.width;
}
}
if let Some(alignment) = vertical_alignment {
if let Some(alignment) = align_y {
match alignment {
alignment::Vertical::Top => {}
alignment::Vertical::Center => {
@ -313,11 +313,13 @@ fn to_style(style: font::Style) -> cosmic_text::Style {
}
}
fn to_align(alignment: alignment::Horizontal) -> cosmic_text::Align {
fn to_align(alignment: Alignment) -> Option<cosmic_text::Align> {
match alignment {
alignment::Horizontal::Left => cosmic_text::Align::Left,
alignment::Horizontal::Center => cosmic_text::Align::Center,
alignment::Horizontal::Right => cosmic_text::Align::Right,
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),
}
}

View file

@ -1,7 +1,7 @@
//! Draw paragraphs.
use crate::core;
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::text;
@ -18,8 +18,8 @@ struct Internal {
font: Font,
shaping: Shaping,
wrapping: Wrapping,
horizontal_alignment: Option<alignment::Horizontal>,
vertical_alignment: alignment::Vertical,
align_x: Alignment,
align_y: alignment::Vertical,
bounds: Size,
min_bounds: Size,
version: text::Version,
@ -47,8 +47,8 @@ impl Paragraph {
Weak {
raw: Arc::downgrade(paragraph),
min_bounds: paragraph.min_bounds,
horizontal_alignment: paragraph.horizontal_alignment,
vertical_alignment: paragraph.vertical_alignment,
align_x: paragraph.align_x,
align_y: paragraph.align_y,
}
}
@ -89,14 +89,13 @@ impl core::text::Paragraph for Paragraph {
text::to_shaping(text.shaping),
);
let min_bounds =
align(&mut buffer, &mut font_system, text.horizontal_alignment);
let min_bounds = align(&mut buffer, &mut font_system, text.align_x);
Self(Arc::new(Internal {
buffer,
font: text.font,
horizontal_alignment: text.horizontal_alignment,
vertical_alignment: text.vertical_alignment,
align_x: text.align_x,
align_y: text.align_y,
shaping: text.shaping,
wrapping: text.wrapping,
bounds: text.bounds,
@ -160,14 +159,13 @@ impl core::text::Paragraph for Paragraph {
None,
);
let min_bounds =
align(&mut buffer, &mut font_system, text.horizontal_alignment);
let min_bounds = align(&mut buffer, &mut font_system, text.align_x);
Self(Arc::new(Internal {
buffer,
font: text.font,
horizontal_alignment: text.horizontal_alignment,
vertical_alignment: text.vertical_alignment,
align_x: text.align_x,
align_y: text.align_y,
shaping: text.shaping,
wrapping: text.wrapping,
bounds: text.bounds,
@ -205,8 +203,8 @@ impl core::text::Paragraph for Paragraph {
|| paragraph.font != text.font
|| paragraph.shaping != text.shaping
|| paragraph.wrapping != text.wrapping
|| paragraph.horizontal_alignment != text.horizontal_alignment
|| paragraph.vertical_alignment != text.vertical_alignment
|| paragraph.align_x != text.align_x
|| paragraph.align_y != text.align_y
{
core::text::Difference::Shape
} else if paragraph.bounds != text.bounds {
@ -216,12 +214,12 @@ impl core::text::Paragraph for Paragraph {
}
}
fn horizontal_alignment(&self) -> Option<alignment::Horizontal> {
self.internal().horizontal_alignment
fn align_x(&self) -> Alignment {
self.internal().align_x
}
fn vertical_alignment(&self) -> alignment::Vertical {
self.internal().vertical_alignment
fn align_y(&self) -> alignment::Vertical {
self.internal().align_y
}
fn min_bounds(&self) -> Size {
@ -361,12 +359,12 @@ impl core::text::Paragraph for Paragraph {
fn align(
buffer: &mut cosmic_text::Buffer,
font_system: &mut text::FontSystem,
align_x: Option<alignment::Horizontal>,
alignment: Alignment,
) -> Size {
let (min_bounds, has_rtl) = text::measure(buffer);
let mut needs_relayout = has_rtl;
if let Some(align_x) = align_x {
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)
@ -374,7 +372,7 @@ fn align(
if has_multiple_lines {
for line in &mut buffer.lines {
let _ = line.set_align(Some(text::to_align(align_x)));
let _ = line.set_align(Some(align));
}
needs_relayout = true;
@ -408,8 +406,8 @@ impl fmt::Debug for Paragraph {
f.debug_struct("Paragraph")
.field("font", &paragraph.font)
.field("shaping", &paragraph.shaping)
.field("horizontal_alignment", &paragraph.horizontal_alignment)
.field("vertical_alignment", &paragraph.vertical_alignment)
.field("horizontal_alignment", &paragraph.align_x)
.field("vertical_alignment", &paragraph.align_y)
.field("bounds", &paragraph.bounds)
.field("min_bounds", &paragraph.min_bounds)
.finish()
@ -420,8 +418,8 @@ impl PartialEq for Internal {
fn eq(&self, other: &Self) -> bool {
self.font == other.font
&& self.shaping == other.shaping
&& self.horizontal_alignment == other.horizontal_alignment
&& self.vertical_alignment == other.vertical_alignment
&& self.align_x == other.align_x
&& self.align_y == other.align_y
&& self.bounds == other.bounds
&& self.min_bounds == other.min_bounds
&& self.buffer.metrics() == other.buffer.metrics()
@ -438,8 +436,8 @@ impl Default for Internal {
font: Font::default(),
shaping: Shaping::default(),
wrapping: Wrapping::default(),
horizontal_alignment: None,
vertical_alignment: alignment::Vertical::Top,
align_x: Alignment::Default,
align_y: alignment::Vertical::Top,
bounds: Size::ZERO,
min_bounds: Size::ZERO,
version: text::Version::default(),
@ -454,9 +452,9 @@ pub struct Weak {
/// The minimum bounds of the [`Paragraph`].
pub min_bounds: Size,
/// The horizontal alignment of the [`Paragraph`].
pub horizontal_alignment: Option<alignment::Horizontal>,
pub align_x: Alignment,
/// The vertical alignment of the [`Paragraph`].
pub vertical_alignment: alignment::Vertical,
pub align_y: alignment::Vertical,
}
impl Weak {