Skip to content

Commit

Permalink
use AlignmentOptions struct instead of bool parameter
Browse files Browse the repository at this point in the history
Signed-off-by: Nico Burns <nico@nicoburns.com>
  • Loading branch information
nicoburns committed Feb 18, 2025
1 parent 9751217 commit 3458d7d
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 88 deletions.
8 changes: 2 additions & 6 deletions examples/swash_render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use image::codecs::png::PngEncoder;
use image::{self, Pixel, Rgba, RgbaImage};
use parley::layout::{Alignment, Glyph, GlyphRun, Layout, PositionedLayoutItem};
use parley::style::{FontStack, FontWeight, StyleProperty, TextStyle};
use parley::{FontContext, InlineBox, LayoutContext};
use parley::{AlignmentOptions, FontContext, InlineBox, LayoutContext};
use std::fs::File;
use swash::scale::image::Content;
use swash::scale::{Render, ScaleContext, Scaler, Source, StrikeWith};
Expand Down Expand Up @@ -168,11 +168,7 @@ fn main() {

// Perform layout (including bidi resolution and shaping) with start alignment
layout.break_all_lines(max_advance);
layout.align(
max_advance,
Alignment::Start,
false, /* align_when_overflowing */
);
layout.align(max_advance, Alignment::Start, AlignmentOptions::default());

// Create image to render into
let width = layout.width().ceil() as u32 + (padding * 2);
Expand Down
10 changes: 3 additions & 7 deletions examples/tiny_skia_render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
)]

use parley::{
Alignment, FontContext, FontWeight, GenericFamily, GlyphRun, InlineBox, Layout, LayoutContext,
PositionedLayoutItem, StyleProperty,
Alignment, AlignmentOptions, FontContext, FontWeight, GenericFamily, GlyphRun, InlineBox,
Layout, LayoutContext, PositionedLayoutItem, StyleProperty,
};
use skrifa::{
instance::{LocationRef, NormalizedCoord, Size},
Expand Down Expand Up @@ -99,11 +99,7 @@ fn main() {

// Perform layout (including bidi resolution and shaping) with start alignment
layout.break_all_lines(max_advance);
layout.align(
max_advance,
Alignment::Start,
false, /* align_when_overflowing */
);
layout.align(max_advance, Alignment::Start, AlignmentOptions::default());
let width = layout.width().ceil() as u32;
let height = layout.height().ceil() as u32;
let padded_width = width + padding * 2;
Expand Down
31 changes: 26 additions & 5 deletions parley/src/layout/alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@ use super::{
};
use crate::style::Brush;

/// Additional options to fine tune alignment
#[derive(Debug, Clone)]
pub struct AlignmentOptions {
/// If set to `true`, "end" and "center" alignment will apply even if the line contents are
/// wider than the alignment width. If it is set to `false`, all overflowing lines will be
/// [`Alignment::Start`] aligned.
pub align_when_overflowing: bool,
}

#[expect(
clippy::derivable_impls,
reason = "Make default values explicit rather than relying on the implicit default value of bool"
)]
impl Default for AlignmentOptions {
fn default() -> Self {
Self {
align_when_overflowing: false,
}
}
}

/// Align the layout.
///
/// If [`Alignment::Justified`] is requested, clusters' [`ClusterData::advance`] will be adjusted.
Expand All @@ -15,12 +36,12 @@ pub(crate) fn align<B: Brush>(
layout: &mut LayoutData<B>,
alignment_width: Option<f32>,
alignment: Alignment,
align_when_overflowing: bool,
options: AlignmentOptions,
) {
layout.alignment_width = alignment_width.unwrap_or(layout.width);
layout.is_aligned_justified = alignment == Alignment::Justified;

align_impl::<_, false>(layout, alignment, align_when_overflowing);
align_impl::<_, false>(layout, alignment, options);
}

/// Removes previous justification applied to clusters.
Expand All @@ -29,7 +50,7 @@ pub(crate) fn align<B: Brush>(
/// layout.
pub(crate) fn unjustify<B: Brush>(layout: &mut LayoutData<B>) {
if layout.is_aligned_justified {
align_impl::<_, true>(layout, Alignment::Justified, false);
align_impl::<_, true>(layout, Alignment::Justified, Default::default());
layout.is_aligned_justified = false;
}
}
Expand All @@ -46,7 +67,7 @@ pub(crate) fn unjustify<B: Brush>(layout: &mut LayoutData<B>) {
fn align_impl<B: Brush, const UNDO_JUSTIFICATION: bool>(
layout: &mut LayoutData<B>,
alignment: Alignment,
align_when_overflowing: bool,
options: AlignmentOptions,
) {
// Whether the text base direction is right-to-left.
let is_rtl = layout.base_level & 1 == 1;
Expand All @@ -63,7 +84,7 @@ fn align_impl<B: Brush, const UNDO_JUSTIFICATION: bool>(
let free_space =
layout.alignment_width - line.metrics.advance + line.metrics.trailing_whitespace;

if !align_when_overflowing && free_space <= 0.0 {
if !options.align_when_overflowing && free_space <= 0.0 {
if is_rtl {
// In RTL text, right-align on overflow.
line.metrics.offset += free_space;
Expand Down
9 changes: 3 additions & 6 deletions parley/src/layout/cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,8 @@ impl Iterator for GlyphIter<'_> {
#[cfg(test)]
mod tests {
use crate::{
Alignment, Cluster, FontContext, Layout, LayoutContext, PositionedLayoutItem, StyleProperty,
Alignment, AlignmentOptions, Cluster, FontContext, Layout, LayoutContext,
PositionedLayoutItem, StyleProperty,
};

type Brush = ();
Expand All @@ -493,11 +494,7 @@ mod tests {
fn cluster_from_position_with_alignment(alignment: Alignment) {
let mut layout = create_unaligned_layout();
let width = layout.full_width();
layout.align(
Some(width + 100.),
alignment,
false, /* align_when_overflowing */
);
layout.align(Some(width + 100.), alignment, AlignmentOptions::default());
assert_eq!(
layout.len(),
1,
Expand Down
9 changes: 4 additions & 5 deletions parley/src/layout/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ use crate::layout::LayoutAccessibility;
#[cfg(feature = "accesskit")]
use accesskit::{Node, NodeId, TreeUpdate};

use super::AlignmentOptions;

/// Opaque representation of a generation.
///
/// Obtained from [`PlainEditor::generation`].
Expand Down Expand Up @@ -1038,11 +1040,8 @@ where
}
self.layout = builder.build(&self.buffer);
self.layout.break_all_lines(self.width);
self.layout.align(
self.width,
self.alignment,
false, /* align_when_overflowing */
);
self.layout
.align(self.width, self.alignment, AlignmentOptions::default());
self.selection = self.selection.refresh(&self.layout);
self.layout_dirty = false;
self.generation.nudge();
Expand Down
14 changes: 3 additions & 11 deletions parley/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use hashbrown::{HashMap, HashSet};
use swash::text::cluster::{Boundary, ClusterInfo};
use swash::{GlyphId, NormalizedCoord, Synthesis};

pub use alignment::AlignmentOptions;
pub use cluster::{Affinity, ClusterPath, ClusterSide};
pub use cursor::{Cursor, Selection};
pub use line::greedy::BreakLines;
Expand Down Expand Up @@ -181,23 +182,14 @@ impl<B: Brush> Layout<B> {
/// You must perform line breaking prior to aligning, through [`Layout::break_lines`] or
/// [`Layout::break_all_lines`]. If `container_width` is not specified, the layout's
/// [`Layout::width`] is used.
///
/// If `align_when_overflowing` is set to `true`, alignment will apply even if the line
/// contents are wider than the alignment width. If it is set to `false`, all overflowing lines
/// will be [`Alignment::Start`] aligned.
pub fn align(
&mut self,
container_width: Option<f32>,
alignment: Alignment,
align_when_overflowing: bool,
options: AlignmentOptions,
) {
unjustify(&mut self.data);
align(
&mut self.data,
container_width,
alignment,
align_when_overflowing,
);
align(&mut self.data, container_width, alignment, options);
}

/// Returns the index and `Line` object for the line containing the
Expand Down
6 changes: 3 additions & 3 deletions parley/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
//!
//! ```rust
//! use parley::{
//! Alignment, FontContext, FontWeight, InlineBox, Layout, LayoutContext, PositionedLayoutItem,
//! StyleProperty,
//! Alignment, AlignmentOptions, FontContext, FontWeight, InlineBox, Layout, LayoutContext,
//! PositionedLayoutItem, StyleProperty,
//! };
//!
//! // Create a FontContext (font database) and LayoutContext (scratch space).
Expand Down Expand Up @@ -53,7 +53,7 @@
//! // Run line-breaking and alignment on the Layout
//! const MAX_WIDTH : Option<f32> = Some(100.0);
//! layout.break_all_lines(MAX_WIDTH);
//! layout.align(MAX_WIDTH, Alignment::Start, false /* align_when_overflowing */);
//! layout.align(MAX_WIDTH, Alignment::Start, AlignmentOptions::default());
//!
//! // Inspect computed layout (see examples for more details)
//! let width = layout.width();
Expand Down
62 changes: 17 additions & 45 deletions parley/src/tests/test_basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use peniko::kurbo::Size;

use crate::{testenv, Alignment, InlineBox, WhiteSpaceCollapse};
use crate::{testenv, Alignment, AlignmentOptions, InlineBox, WhiteSpaceCollapse};

#[test]
fn plain_multiline_text() {
Expand All @@ -13,11 +13,7 @@ fn plain_multiline_text() {
let mut builder = env.ranged_builder(text);
let mut layout = builder.build(text);
layout.break_all_lines(None);
layout.align(
None,
Alignment::Start,
false, /* align_when_overflowing */
);
layout.align(None, Alignment::Start, AlignmentOptions::default());

env.check_layout_snapshot(&layout);
}
Expand All @@ -42,11 +38,7 @@ fn placing_inboxes() {
});
let mut layout = builder.build(text);
layout.break_all_lines(None);
layout.align(
None,
Alignment::Start,
false, /* align_when_overflowing */
);
layout.align(None, Alignment::Start, AlignmentOptions::default());
env.with_name(test_case_name).check_layout_snapshot(&layout);
}
}
Expand All @@ -67,11 +59,7 @@ fn only_inboxes_wrap() {
}
let mut layout = builder.build(text);
layout.break_all_lines(Some(40.0));
layout.align(
None,
Alignment::Middle,
false, /* align_when_overflowing */
);
layout.align(None, Alignment::Middle, AlignmentOptions::default());

env.check_layout_snapshot(&layout);
}
Expand Down Expand Up @@ -103,11 +91,7 @@ fn full_width_inbox() {
});
let mut layout = builder.build(text);
layout.break_all_lines(Some(100.));
layout.align(
None,
Alignment::Start,
false, /* align_when_overflowing */
);
layout.align(None, Alignment::Start, AlignmentOptions::default());
env.with_name(test_case_name).check_layout_snapshot(&layout);
}
}
Expand All @@ -120,7 +104,7 @@ fn trailing_whitespace() {
let mut builder = env.ranged_builder(text);
let mut layout = builder.build(text);
layout.break_all_lines(Some(45.));
layout.align(None, Alignment::Start, false);
layout.align(None, Alignment::Start, AlignmentOptions::default());

assert!(
layout.width() < layout.full_width(),
Expand Down Expand Up @@ -149,11 +133,7 @@ fn leading_whitespace() {
builder.push_text(" Line 2");
let (mut layout, _) = builder.build();
layout.break_all_lines(None);
layout.align(
None,
Alignment::Start,
false, /* align_when_overflowing */
);
layout.align(None, Alignment::Start, AlignmentOptions::default());
env.with_name(test_case_name).check_layout_snapshot(&layout);
}
}
Expand All @@ -172,11 +152,7 @@ fn base_level_alignment_ltr() {
let mut builder = env.ranged_builder(text);
let mut layout = builder.build(text);
layout.break_all_lines(Some(150.0));
layout.align(
Some(150.0),
alignment,
false, /* align_when_overflowing */
);
layout.align(Some(150.0), alignment, AlignmentOptions::default());
env.with_name(test_case_name).check_layout_snapshot(&layout);
}
}
Expand All @@ -195,7 +171,7 @@ fn base_level_alignment_rtl() {
let mut builder = env.ranged_builder(text);
let mut layout = builder.build(text);
layout.break_all_lines(Some(150.0));
layout.align(None, alignment, false /* align_when_overflowing */);
layout.align(None, alignment, AlignmentOptions::default());
env.with_name(test_case_name).check_layout_snapshot(&layout);
}
}
Expand All @@ -210,11 +186,7 @@ fn overflow_alignment_rtl() {
let mut builder = env.ranged_builder(text);
let mut layout = builder.build(text);
layout.break_all_lines(Some(1000.0));
layout.align(
Some(10.),
Alignment::Middle,
false, /* align_when_overflowing */
);
layout.align(Some(10.), Alignment::Middle, AlignmentOptions::default());
env.rendering_config().size = Some(Size::new(10., layout.height().into()));
env.check_layout_snapshot(&layout);
}
Expand All @@ -229,11 +201,11 @@ fn content_widths() {
let mut layout = builder.build(text);

layout.break_all_lines(Some(layout.min_content_width()));
layout.align(None, Alignment::Start, false);
layout.align(None, Alignment::Start, AlignmentOptions::default());
env.with_name("min").check_layout_snapshot(&layout);

layout.break_all_lines(Some(layout.max_content_width()));
layout.align(None, Alignment::Start, false);
layout.align(None, Alignment::Start, AlignmentOptions::default());
env.with_name("max").check_layout_snapshot(&layout);
}

Expand All @@ -247,11 +219,11 @@ fn content_widths_rtl() {
let mut layout = builder.build(text);

layout.break_all_lines(Some(layout.min_content_width()));
layout.align(None, Alignment::Start, false);
layout.align(None, Alignment::Start, AlignmentOptions::default());
env.with_name("min").check_layout_snapshot(&layout);

layout.break_all_lines(Some(layout.max_content_width()));
layout.align(None, Alignment::Start, false);
layout.align(None, Alignment::Start, AlignmentOptions::default());
assert!(
layout.width() <= layout.max_content_width(),
"Layout should never be wider than the max content width"
Expand All @@ -274,7 +246,7 @@ fn inbox_content_width() {
});
let mut layout = builder.build(text);
layout.break_all_lines(Some(layout.min_content_width()));
layout.align(None, Alignment::Start, false);
layout.align(None, Alignment::Start, AlignmentOptions::default());

env.with_name("full_width").check_layout_snapshot(&layout);
}
Expand All @@ -290,7 +262,7 @@ fn inbox_content_width() {
});
let mut layout = builder.build(text);
layout.break_all_lines(Some(layout.max_content_width()));
layout.align(None, Alignment::Start, false);
layout.align(None, Alignment::Start, AlignmentOptions::default());

assert!(
layout.width() <= layout.max_content_width(),
Expand Down Expand Up @@ -318,7 +290,7 @@ fn realign() {
layout.align(
Some(150.),
Alignment::Justified,
false, /* align_when_overflowing */
AlignmentOptions::default(),
);
}
env.check_layout_snapshot(&layout);
Expand Down

0 comments on commit 3458d7d

Please sign in to comment.