diff --git a/examples/common/src/lib.rs b/examples/common/src/lib.rs index 37aa747ae..0dd67d37e 100644 --- a/examples/common/src/lib.rs +++ b/examples/common/src/lib.rs @@ -19,8 +19,8 @@ use std::time::Instant; use parley::VerticalAlign; use parley::fontique::Blob; use parley::{ - Alignment, AlignmentOptions, FontContext, FontFamily, FontWeight, GenericFamily, InlineBox, - InlineBoxKind, Layout, LayoutContext, LineHeight, StyleProperty, + FontContext, FontFamily, FontWeight, GenericFamily, InlineBox, InlineBoxKind, Layout, + LayoutContext, LineHeight, StyleProperty, }; use peniko::Color; @@ -156,7 +156,6 @@ pub fn build_simple_layout( let mut layout = builder.build(&config.text); layout.break_all_lines(config.max_advance); - layout.align(Alignment::Start, AlignmentOptions::default()); let width = layout.width().ceil() as u16; let height = layout.height().ceil() as u16; @@ -219,7 +218,6 @@ pub fn build_rich_layout( let mut layout = builder.build(&config.text); layout.break_all_lines(config.max_advance); - layout.align(Alignment::Start, AlignmentOptions::default()); let width = layout.width().ceil() as u16; let height = layout.height().ceil() as u16; diff --git a/examples/swash_render/src/main.rs b/examples/swash_render/src/main.rs index 4aacb9eef..60b31f326 100644 --- a/examples/swash_render/src/main.rs +++ b/examples/swash_render/src/main.rs @@ -9,9 +9,9 @@ use image::codecs::png::PngEncoder; use image::{self, Pixel, Rgba, RgbaImage}; use parley::VerticalAlign; -use parley::layout::{Alignment, Glyph, GlyphRun, Layout, PositionedLayoutItem}; +use parley::layout::{Glyph, GlyphRun, Layout, PositionedLayoutItem}; use parley::style::{FontFamily, FontWeight, StyleProperty, TextStyle}; -use parley::{AlignmentOptions, FontContext, InlineBox, InlineBoxKind, LayoutContext, LineHeight}; +use parley::{FontContext, InlineBox, InlineBoxKind, LayoutContext, LineHeight}; use std::fs::File; use swash::FontRef; use swash::scale::image::Content; @@ -192,7 +192,6 @@ fn main() { // Perform layout (including bidi resolution and shaping) with start alignment layout.break_all_lines(max_advance); - layout.align(Alignment::Start, AlignmentOptions::default()); // Create image to render into let width = layout.width().ceil() as u32 + (padding * 2); diff --git a/examples/tiny_skia_render/src/main.rs b/examples/tiny_skia_render/src/main.rs index 8cd36bbfb..bc4e2695f 100644 --- a/examples/tiny_skia_render/src/main.rs +++ b/examples/tiny_skia_render/src/main.rs @@ -11,8 +11,8 @@ use parley::VerticalAlign; use parley::{ - Alignment, AlignmentOptions, FontContext, FontWeight, GenericFamily, GlyphRun, InlineBox, - InlineBoxKind, Layout, LayoutContext, LineHeight, PositionedLayoutItem, StyleProperty, + FontContext, FontWeight, GenericFamily, GlyphRun, InlineBox, InlineBoxKind, Layout, + LayoutContext, LineHeight, PositionedLayoutItem, StyleProperty, }; use skrifa::{ GlyphId, MetadataProvider, OutlineGlyph, @@ -102,7 +102,6 @@ fn main() { // Perform layout (including bidi resolution and shaping) with start alignment layout.break_all_lines(max_advance); - layout.align(Alignment::Start, AlignmentOptions::default()); let width = layout.width().ceil() as u32; let height = layout.height().ceil() as u32; let padded_width = width + padding * 2; diff --git a/parley/README.md b/parley/README.md index 38abe06b2..32c4c4061 100644 --- a/parley/README.md +++ b/parley/README.md @@ -61,7 +61,7 @@ See the [examples](https://github.com/linebender/parley/tree/main/examples) dire ```rust use parley::{ - Alignment, AlignmentOptions, FontContext, FontWeight, InlineBox, InlineBoxKind, Layout, + FontContext, FontWeight, InlineBox, InlineBoxKind, Layout, LayoutContext, LineHeight, PositionedLayoutItem, StyleProperty, VerticalAlign, }; @@ -91,7 +91,6 @@ let mut layout: Layout<()> = builder.build(&TEXT); // Run line-breaking and alignment on the Layout const MAX_WIDTH : Option = Some(100.0); layout.break_all_lines(MAX_WIDTH); -layout.align(Alignment::Start, AlignmentOptions::default()); // Inspect computed layout (see examples for more details) let width = layout.width(); diff --git a/parley/src/editing/editor.rs b/parley/src/editing/editor.rs index 5d62d0075..3d4b0912c 100644 --- a/parley/src/editing/editor.rs +++ b/parley/src/editing/editor.rs @@ -107,10 +107,9 @@ where // Not all operations on `PlainEditor` need to operate on a // clean layout, and not all operations trigger a layout. layout_dirty: bool, - // TODO: We could avoid redoing the full text layout if only - // linebreaking or alignment were changed. + // TODO: We could avoid redoing the full text analysis if only + // dimensions or alignment were changed. // linebreak_dirty: bool, - // alignment_dirty: bool, alignment: Alignment, base_direction: BaseDirection, generation: Generation, @@ -1207,9 +1206,9 @@ where builder.push(StyleProperty::Underline(true), preedit_range.clone()); } builder.build_into(&mut self.layout, &self.buffer); - self.layout.break_all_lines(self.width); self.layout - .align(self.alignment, AlignmentOptions::default()); + .set_alignment(self.alignment, AlignmentOptions::default()); + self.layout.break_all_lines(self.width); self.selection = self.selection.refresh(&self.layout); self.layout_dirty = false; self.generation.nudge(); diff --git a/parley/src/layout/alignment.rs b/parley/src/layout/alignment.rs index 8396ca8bd..e4fafeeb3 100644 --- a/parley/src/layout/alignment.rs +++ b/parley/src/layout/alignment.rs @@ -34,7 +34,7 @@ pub enum Alignment { } /// Additional options to fine tune alignment -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] 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 @@ -44,11 +44,11 @@ pub struct AlignmentOptions { /// line that ends in an explicit line break. This corresponds to the CSS `text-align-last` /// property. /// - /// If set to `None`, those lines use the alignment passed to [`Layout::align`], except that - /// [`Alignment::Justify`] falls back to [`Alignment::Start`]. This is the behavior of + /// If set to `None`, those lines use the alignment passed to [`Layout::set_alignment`], except that + /// [`Alignment::Justify`] falls back to [`Alignment::Start`]. This is the behavior of /// `text-align-last: auto`. /// - /// [`Layout::align`]: crate::Layout::align + /// [`Layout::set_alignment`]: crate::Layout::set_alignment pub last_line_alignment: Option, } @@ -65,12 +65,13 @@ impl Default for AlignmentOptions { } } -/// Align the layout. -pub(crate) fn align( - layout: &mut LayoutData, - alignment: Alignment, - options: AlignmentOptions, -) { +/// Align the layout. This applies to the full layout at a time, because the alignment implicitly +/// uses the widest width in the layout if no max advance was provided. +/// +/// TODO: Evaluate whether aligning a line at a time might be faster (better cache locality?). +pub(crate) fn align(layout: &mut LayoutData) { + let alignment = layout.alignment_setting; + let options = layout.alignment_options; layout.alignment = Some(alignment); let is_rtl = layout.base_level.is_rtl(); diff --git a/parley/src/layout/cluster.rs b/parley/src/layout/cluster.rs index 9c887be97..e1b3f7172 100644 --- a/parley/src/layout/cluster.rs +++ b/parley/src/layout/cluster.rs @@ -548,7 +548,7 @@ mod tests { type Brush = (); - fn create_unaligned_layout() -> Layout { + fn create_layout(alignment: Alignment) -> Layout { let mut layout_ctx = LayoutContext::new(); // TODO: Use a test font let mut font_ctx = FontContext::new(); @@ -556,13 +556,13 @@ mod tests { let mut builder = layout_ctx.ranged_builder(&mut font_ctx, text, 1.0, true); builder.push_default(StyleProperty::FontSize(10.)); let mut layout = builder.build(text); + layout.set_alignment(alignment, AlignmentOptions::default()); layout.break_all_lines(None); layout } fn cluster_from_position_with_alignment(alignment: Alignment) { - let mut layout = create_unaligned_layout(); - layout.align(alignment, AlignmentOptions::default()); + let layout = create_layout(alignment); assert_eq!( layout.len(), 1, diff --git a/parley/src/layout/data.rs b/parley/src/layout/data.rs index 7398aefdd..ea2eec811 100644 --- a/parley/src/layout/data.rs +++ b/parley/src/layout/data.rs @@ -208,6 +208,14 @@ pub(crate) struct LayoutData { pub(crate) runs: Vec, pub(crate) items: Vec, + // Settings for line breaking and alignment + pub(crate) alignment_setting: super::Alignment, + pub(crate) alignment_options: super::AlignmentOptions, + /// The text-indent amount in layout units. + pub(crate) indent_amount: f32, + /// Options controlling text-indent behavior. + pub(crate) indent_options: IndentOptions, + // Output of line breaking /// The lines in the pub(crate) lines: Vec, @@ -228,12 +236,8 @@ pub(crate) struct LayoutData { pub(crate) height: f32, // Output of alignment - /// The alignment that was applied to the layout, if any. + /// The alignment that was applied when the layout was line broken, if any. pub(crate) alignment: Option, - /// The text-indent amount in layout units. - pub(crate) indent_amount: f32, - /// Options controlling text-indent behavior (each-line, hanging). - pub(crate) indent_options: IndentOptions, } impl Default for LayoutData { @@ -255,6 +259,8 @@ impl Default for LayoutData { lines: Vec::new(), line_items: Vec::new(), aligned_subtree_offsets: Vec::new(), + alignment_setting: super::Alignment::default(), + alignment_options: super::AlignmentOptions::default(), alignment: None, layout_max_advance: 0.0, indent_amount: 0.0, @@ -284,6 +290,8 @@ impl LayoutData { self.lines.clear(); self.line_items.clear(); self.aligned_subtree_offsets.clear(); + self.alignment_setting = super::Alignment::default(); + self.alignment_options = super::AlignmentOptions::default(); self.alignment = None; } diff --git a/parley/src/layout/layout.rs b/parley/src/layout/layout.rs index 79e40122e..0ae026ae1 100644 --- a/parley/src/layout/layout.rs +++ b/parley/src/layout/layout.rs @@ -3,7 +3,6 @@ use crate::IndentOptions; use crate::InlineBox; -use crate::layout::alignment::align; use crate::layout::data::LayoutData; use crate::layout::style_metrics::StyleMetrics; use crate::layout::{ @@ -88,9 +87,10 @@ impl Layout { self.data.text_len } - /// Returns the alignment that was applied to the layout by [`Layout::align`]. + /// Returns the alignment that was active when lines were most recently broken. /// - /// Returns `None` if the layout has not been aligned since it was last built. + /// This returns `None` if [`Layout::break_all_lines`] or [`Layout::break_lines`] have + /// not been called since the layout was last built or [cleared](Self::clear). pub fn alignment(&self) -> Option { self.data.alignment } @@ -267,14 +267,33 @@ impl Layout { /// available width for line breaking and offsetting content during alignment. Negative /// values cause the line to protrude beyond the start edge. /// - /// This must be called before [`Layout::break_all_lines`] or [`Layout::break_lines`], - /// and before [`Layout::align`]. + /// This must be called before [`Layout::break_all_lines`] or [`Layout::break_lines`]. + /// The text indentation is reset to zero when the layout is [cleared](Self::clear) or built into. pub fn set_text_indent(&mut self, amount: f32, options: IndentOptions) { self.data.indent_amount = amount; self.data.indent_options = options; } + /// Set the alignment for the layout. + /// + /// This only takes effect the next time [`Layout::break_all_lines`] or [`Layout::break_lines`] is called. + /// The currently active value can be read as [`Self::alignment`]. + /// + /// If a finite `max_advance` is supplied to `Layout::break_all_lines` then alignment will be applied + /// relative to that width. Otherwise alignment will be applied relative to the width of the + /// longest line as computed by line breaking. + /// + /// If line-specific `offset` and `max_advance` are set using the advanced methods on the `BreakLines` + /// struct then each line will be aligned individually within its line box. + /// + /// The alignment to be used is reset to [`Alignment::Start`] when the layout is [cleared](Self::clear) or built into. + pub fn set_alignment(&mut self, alignment: Alignment, options: AlignmentOptions) { + self.data.alignment_setting = alignment; + self.data.alignment_options = options; + } + /// Returns line breaker to compute lines for the layout. + // TODO: You must call [`BreakLines::finish`]? pub fn break_lines(&mut self) -> BreakLines<'_, B> { BreakLines::new(self) } @@ -285,21 +304,6 @@ impl Layout { .break_remaining(max_advance.unwrap_or(f32::MAX)); } - /// Apply alignment to the layout. - /// - /// You must perform line breaking prior to aligning, through [`Layout::break_lines`] or - /// [`Layout::break_all_lines`]. - /// - /// If a finite `max_advance` is supplied to `Layout::break_all_lines` then that width will be applied - /// relative to that width. Otherwise alignment will be applied relative to the width of the - /// longest line as computed by line breaking. - /// - /// If line-specific `offset` and `max_advance` are set using the advanced methods on the `BreakLines` - /// struct then each line will be aligned individually within its line box. - pub fn align(&mut self, alignment: Alignment, options: AlignmentOptions) { - align(&mut self.data, alignment, options); - } - /// Returns the index and `Line` object for the line containing the /// given byte `index` in the source text. pub(crate) fn line_for_byte_index(&self, index: usize) -> Option<(usize, Line<'_, B>)> { diff --git a/parley/src/layout/line_break.rs b/parley/src/layout/line_break.rs index 8e279345e..3016c0762 100644 --- a/parley/src/layout/line_break.rs +++ b/parley/src/layout/line_break.rs @@ -1645,6 +1645,8 @@ impl<'a, B: Brush> BreakLines<'a, B> { impl Drop for BreakLines<'_, B> { fn drop(&mut self) { + // TODO: Maybe move all of this into `finish`? + // Compute the overall width and height of the entire layout // The "width" excludes hanging whitespace. The "full_width" includes it. let mut layout_width = 0_f32; @@ -1683,6 +1685,8 @@ impl Drop for BreakLines<'_, B> { // Save the computed lines to the layout self.lines.swap(&mut self.layout.data); + + crate::layout::alignment::align(&mut self.layout.data); } } diff --git a/parley/src/layout/run.rs b/parley/src/layout/run.rs index fa7c64849..bd6e25825 100644 --- a/parley/src/layout/run.rs +++ b/parley/src/layout/run.rs @@ -138,7 +138,7 @@ impl<'a, B: Brush> Run<'a, B> { /// Returns the advance for the run. /// /// This includes the additional advances inserted for word spacing, letter spacing, and, if the - /// layout has been [aligned](Layout::align) with [`Justify`](crate::Alignment::Justify), the + /// layout has been [aligned](Layout::set_alignment) with [`Justify`](crate::Alignment::Justify), the /// justification. pub fn advance(&self) -> f32 { let spacing = self.line_spacing(); diff --git a/parley/src/lib.rs b/parley/src/lib.rs index 0df260400..0718a16a5 100644 --- a/parley/src/lib.rs +++ b/parley/src/lib.rs @@ -30,7 +30,7 @@ //! //! ```rust //! use parley::{ -//! Alignment, AlignmentOptions, FontContext, FontWeight, InlineBox, InlineBoxKind, Layout, +//! FontContext, FontWeight, InlineBox, InlineBoxKind, Layout, //! LayoutContext, LineHeight, PositionedLayoutItem, StyleProperty, VerticalAlign, //! }; //! @@ -60,7 +60,6 @@ //! // Run line-breaking and alignment on the Layout //! const MAX_WIDTH : Option = Some(100.0); //! layout.break_all_lines(MAX_WIDTH); -//! layout.align(Alignment::Start, AlignmentOptions::default()); //! //! // Inspect computed layout (see examples for more details) //! let width = layout.width(); diff --git a/parley/src/tests/test_layout.rs b/parley/src/tests/test_layout.rs index df6aab953..2a80fc170 100644 --- a/parley/src/tests/test_layout.rs +++ b/parley/src/tests/test_layout.rs @@ -18,8 +18,8 @@ fn clear_resets_to_new() { builder.push_default(FontFamily::from(FONT_FAMILY_LIST)); let mut layout = builder.build(TEXT); layout.set_text_indent(10., IndentOptions::default()); + layout.set_alignment(Alignment::Center, AlignmentOptions::default()); layout.break_all_lines(Some(50.)); - layout.align(Alignment::Center, AlignmentOptions::default()); assert!(layout.lines().len() > 1); assert!(layout.width() > 0.); assert!(layout.height() > 0.); diff --git a/parley_bench/benches/main.rs b/parley_bench/benches/main.rs index b6234f6c7..b6d2da81e 100644 --- a/parley_bench/benches/main.rs +++ b/parley_bench/benches/main.rs @@ -6,8 +6,7 @@ use tango_bench::tango_benchmarks; use parley_bench::benches::{ - content_widths, defaults, iterate_glyph_runs, line_breaking, long_line, page, - repeated_justification, spacing, styled, + content_widths, defaults, iterate_glyph_runs, line_breaking, long_line, page, spacing, styled, }; use parley_bench::fontique_benches::system_fonts_init; use parley_bench::query_benches::cursor; @@ -18,7 +17,6 @@ tango_benchmarks!( iterate_glyph_runs(), content_widths(), spacing(), - repeated_justification(), line_breaking(), long_line(), page(), diff --git a/parley_bench/src/benches.rs b/parley_bench/src/benches.rs index 5e94afb89..7c0a4a48e 100644 --- a/parley_bench/src/benches.rs +++ b/parley_bench/src/benches.rs @@ -37,7 +37,6 @@ pub fn defaults() -> Vec { let mut layout: Layout = builder.build(text); layout.break_all_lines(Some(MAX_ADVANCE)); - layout.align(Alignment::Start, AlignmentOptions::default()); black_box(layout); }); @@ -78,7 +77,6 @@ pub fn spacing() -> Vec { let mut layout: Layout = builder.build(text); layout.break_all_lines(Some(MAX_ADVANCE)); - layout.align(Alignment::Start, AlignmentOptions::default()); black_box(layout); }); @@ -89,59 +87,6 @@ pub fn spacing() -> Vec { .collect() } -/// Benchmark repeatedly justifying an already line-broken layout. -pub fn repeated_justification() -> [Benchmark; 1] { - const DISPLAY_SCALE: f32 = 1.0; - const QUANTIZE: bool = true; - const MAX_ADVANCE: f32 = 200.0 * DISPLAY_SCALE; - - let sample = get_samples() - .iter() - .find(|sample| sample.name == "latin" && sample.modification == "8000 characters") - .expect("the Latin 8000-character benchmark sample should exist"); - - [benchmark_fn( - format!( - "Repeated Justification - {} {}", - sample.name, sample.modification - ), - move |b| { - let text = &sample.text; - let mut layout = with_contexts(|font_cx, layout_cx| { - let mut builder = layout_cx.ranged_builder(font_cx, text, DISPLAY_SCALE, QUANTIZE); - builder.push_default(FontFamily::from(FONT_FAMILY_LIST)); - - let mut layout: Layout = builder.build(text); - layout.break_all_lines(Some(MAX_ADVANCE)); - layout - }); - - b.iter(move || { - layout.align(Alignment::Justify, AlignmentOptions::default()); - - // Pass to black box so the optimizer cannot optimize alignment away. - black_box( - layout - .lines() - .flat_map(|line| line.runs()) - .map(|run| run.advance()) - .sum::(), - ); - layout.align(Alignment::Start, AlignmentOptions::default()); - - // Pass to black box so the optimizer cannot optimize alignment away. - black_box( - layout - .lines() - .flat_map(|line| line.runs()) - .map(|run| run.advance()) - .sum::(), - ) - }) - }, - )] -} - /// Benchmark breaking a layout into lines. /// /// This is part of the work that'd be performed as, e.g., a window is being resized. @@ -160,7 +105,6 @@ pub fn line_breaking() -> Vec { fn break_lines(layout: &mut Layout, max_advance: Option) { layout.break_all_lines(max_advance); - layout.align(Alignment::Start, AlignmentOptions::default()); black_box((layout.len(), layout.width(), layout.height())); } @@ -269,8 +213,8 @@ fn build_wrapped_layout<'a>( ) -> Layout { const WRAPPED_MAX_ADVANCE: f32 = 200.; let mut layout = build_layout(text, styles); + layout.set_alignment(alignment, AlignmentOptions::default()); layout.break_all_lines(Some(WRAPPED_MAX_ADVANCE)); - layout.align(alignment, AlignmentOptions::default()); layout } @@ -568,7 +512,6 @@ fn build_unwrapped_layout<'a>( ) -> Layout { let mut layout = build_layout(text, styles); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); layout } @@ -585,8 +528,8 @@ pub fn long_line() -> Vec { builder.push_default(FontFamily::from(FONT_FAMILY_LIST)); let mut layout: Layout = builder.build(text); + layout.set_alignment(alignment, AlignmentOptions::default()); layout.break_all_lines(max_advance); - layout.align(alignment, AlignmentOptions::default()); black_box(layout); }); @@ -640,7 +583,6 @@ pub fn page() -> Vec { .iter_mut() .map(|layout| { layout.break_all_lines(Some(max_advance)); - layout.align(Alignment::Start, AlignmentOptions::default()); layout.len() }) .sum() diff --git a/parley_bench/src/query_benches.rs b/parley_bench/src/query_benches.rs index 19e8b15b9..6236dabc4 100644 --- a/parley_bench/src/query_benches.rs +++ b/parley_bench/src/query_benches.rs @@ -5,7 +5,7 @@ use crate::benches::build_layout; use crate::{ColorBrush, get_samples}; -use parley::{Affinity, Alignment, AlignmentOptions, Cursor, Layout, Selection}; +use parley::{Affinity, Cursor, Layout, Selection}; use std::hint::black_box; use tango_bench::{Benchmark, benchmark_fn}; @@ -19,7 +19,6 @@ const WIDE_MAX_ADVANCE: f32 = 10. * MAX_ADVANCE; fn build_and_break(text: &str, max_advance: Option) -> Layout { let mut layout = build_layout(text, []); layout.break_all_lines(max_advance); - layout.align(Alignment::Start, AlignmentOptions::default()); layout } diff --git a/parley_tests/snapshots/shaping_context_across_items-0.png b/parley_tests/snapshots/shaping_context_across_items-0.png index 9bb23cb8b..9bf5ce9bd 100644 Binary files a/parley_tests/snapshots/shaping_context_across_items-0.png and b/parley_tests/snapshots/shaping_context_across_items-0.png differ diff --git a/parley_tests/snapshots/test_cluster_info-arabic.png b/parley_tests/snapshots/test_cluster_info-arabic.png index 1639a0d68..b407a9bcd 100644 Binary files a/parley_tests/snapshots/test_cluster_info-arabic.png and b/parley_tests/snapshots/test_cluster_info-arabic.png differ diff --git a/parley_tests/tests/basic.rs b/parley_tests/tests/basic.rs index a55b48e4c..f415e8495 100644 --- a/parley_tests/tests/basic.rs +++ b/parley_tests/tests/basic.rs @@ -21,7 +21,6 @@ fn plain_multiline_text() { let builder = env.ranged_builder(text); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -77,7 +76,6 @@ fn placing_inboxes() { }); let mut layout = builder.build(&text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name(test_case_name).check_layout_snapshot(&layout); } } @@ -100,8 +98,8 @@ fn only_inboxes_wrap() { }); } let mut layout = builder.build(&text); + layout.set_alignment(Alignment::Center, AlignmentOptions::default()); layout.break_all_lines(Some(40.0)); - layout.align(Alignment::Center, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -142,7 +140,6 @@ fn full_width_inbox() { }); let mut layout = builder.build(text); layout.break_all_lines(Some(100.)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name(test_case_name).check_layout_snapshot(&layout); } } @@ -193,7 +190,6 @@ fn inbox_separated_by_whitespace() { }); let (mut layout, _text) = builder.build(); layout.break_all_lines(Some(100.)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -223,7 +219,6 @@ fn inbox_with_baseline() { }); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name(test_case_name).check_layout_snapshot(&layout); } } @@ -257,7 +252,6 @@ fn inboxes_with_matching_baselines() { }); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -297,7 +291,6 @@ fn inboxes_with_large_ascent_and_descent() { }); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); // The middle line (containing the boxes) should be tall enough to contain the first box's // ascent (38px) plus the second box's descent (40 - 2 = 38px). @@ -329,7 +322,6 @@ fn inbox_below_baseline_keeps_grid() { }); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); // Every line has the same 60px line height, so consecutive baselines must be exactly 60px // apart. The inline box on the middle line fits within the line and must not disturb this. @@ -359,7 +351,6 @@ fn trailing_whitespace_ltr() { let builder = env.ranged_builder(text); let mut layout = builder.build(text); layout.break_all_lines(Some(45.)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name("soft_wrap").check_layout_snapshot(&layout); } @@ -369,7 +360,6 @@ fn trailing_whitespace_ltr() { let builder = env.ranged_builder(text); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name("hard_wrap").check_layout_snapshot(&layout); } @@ -384,7 +374,6 @@ fn trailing_whitespace_rtl() { let builder = env.ranged_builder(text); let mut layout = builder.build(text); layout.break_all_lines(Some(45.)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name("soft_wrap").check_layout_snapshot(&layout); } @@ -394,7 +383,6 @@ fn trailing_whitespace_rtl() { let builder = env.ranged_builder(text); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name("hard_wrap").check_layout_snapshot(&layout); } @@ -412,7 +400,6 @@ fn trailing_whitespace_bidi() { let builder = env.ranged_builder(text); let mut layout = builder.build(text); layout.break_all_lines(Some(45.)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name(test_case_name).check_layout_snapshot(&layout); } @@ -426,7 +413,6 @@ fn trailing_whitespace_bidi() { let builder = env.ranged_builder(text); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name(test_case_name).check_layout_snapshot(&layout); } @@ -452,7 +438,6 @@ fn leading_whitespace() { builder.push_text(" Line 2"); let (mut layout, _) = builder.build(); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name(test_case_name).check_layout_snapshot(&layout); } } @@ -770,8 +755,8 @@ fn base_level_alignment_ltr() { let text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; let builder = env.ranged_builder(text); let mut layout = builder.build(text); + layout.set_alignment(alignment, AlignmentOptions::default()); layout.break_all_lines(Some(150.0)); - layout.align(alignment, AlignmentOptions::default()); env.with_name(test_case_name).check_layout_snapshot(&layout); } } @@ -789,8 +774,8 @@ fn base_level_alignment_rtl() { let text = "عند برمجة أجهزة الكمبيوتر، قد تجد نفسك فجأة في مواقف غريبة، مثل الكتابة بلغة لا تتحدثها فعليًا."; let builder = env.ranged_builder(text); let mut layout = builder.build(text); + layout.set_alignment(alignment, AlignmentOptions::default()); layout.break_all_lines(Some(150.0)); - layout.align(alignment, AlignmentOptions::default()); env.with_name(test_case_name).check_layout_snapshot(&layout); } } @@ -813,14 +798,14 @@ fn last_line_alignment() { ] { let builder = env.ranged_builder(text); let mut layout = builder.build(text); - layout.break_all_lines(Some(150.0)); - layout.align( + layout.set_alignment( alignment, AlignmentOptions { last_line_alignment: Some(last_line_alignment), ..AlignmentOptions::default() }, ); + layout.break_all_lines(Some(150.0)); env.with_name(&format!("{text_name}_{test_case_name}")) .check_layout_snapshot(&layout); } @@ -843,14 +828,14 @@ fn overflow_alignment_rtl() { ] { let builder = env.ranged_builder(text); let mut layout = builder.build(text); - layout.break_all_lines(Some(100.0)); - layout.align( + layout.set_alignment( alignment, AlignmentOptions { align_when_overflowing, ..AlignmentOptions::default() }, ); + layout.break_all_lines(Some(100.0)); env.with_name(test_case_name).check_layout_snapshot(&layout); } } @@ -868,8 +853,8 @@ fn dont_justify_space_inside_grapheme() { let builder = env.ranged_builder(text); let mut layout = builder.build(text); // Breaks after "cc ", leaving the first line one space to stretch. + layout.set_alignment(Alignment::Justify, AlignmentOptions::default()); layout.break_all_lines(Some(80.0)); - layout.align(Alignment::Justify, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -889,8 +874,8 @@ fn justify_with_overflowing_trailing_space() { let mut builder = env.ranged_builder(text); builder.push_default(StyleProperty::WordSpacing(48.0)); let mut layout = builder.build(text); + layout.set_alignment(Alignment::Justify, AlignmentOptions::default()); layout.break_all_lines(Some(280.0)); - layout.align(Alignment::Justify, AlignmentOptions::default()); env.check_layout_snapshot(&layout); @@ -917,8 +902,8 @@ fn justify_consecutive_spaces() { let text = "Foo bar baz supercalifragilistic.\n\nFoo bar baz supercalifragilistic."; let builder = env.ranged_builder(text); let mut layout = builder.build(text); + layout.set_alignment(Alignment::Justify, AlignmentOptions::default()); layout.break_all_lines(Some(150.0)); - layout.align(Alignment::Justify, AlignmentOptions::default()); env.check_layout_snapshot(&layout); @@ -956,8 +941,8 @@ fn justify_with_multiple_trailing_spaces() { // because of a font size change). builder.push(StyleProperty::FontSize(15.9), 10..11); let mut layout = builder.build(text); + layout.set_alignment(Alignment::Justify, AlignmentOptions::default()); layout.break_all_lines(Some(max_advance)); - layout.align(Alignment::Justify, AlignmentOptions::default()); env.check_cluster_snapshot(&layout, text, 12.0); } @@ -973,8 +958,8 @@ fn trailing_nbsp_doesnt_hang_but_also_doesnt_justify_ltr() { let builder = env.ranged_builder(text); let mut layout = builder.build(text); + layout.set_alignment(Alignment::Justify, AlignmentOptions::default()); layout.break_all_lines(Some(max_advance)); - layout.align(Alignment::Justify, AlignmentOptions::default()); env.check_cluster_snapshot(&layout, text, 12.0); } @@ -994,8 +979,8 @@ fn trailing_nbsp_doesnt_hang_but_also_doesnt_justify_rtl() { builder.push_default(StyleProperty::WordSpacing(12.0)); let mut layout = builder.build(text); + layout.set_alignment(Alignment::Justify, AlignmentOptions::default()); layout.break_all_lines(Some(max_advance)); - layout.align(Alignment::Justify, AlignmentOptions::default()); env.check_cluster_snapshot(&layout, text, 12.0); } @@ -1014,11 +999,9 @@ fn content_widths() { } = layout.calculate_content_widths(); layout.break_all_lines(Some(min_content_width)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name("min").check_layout_snapshot(&layout); layout.break_all_lines(Some(max_content_width)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name("max").check_layout_snapshot(&layout); } @@ -1037,11 +1020,9 @@ fn content_widths_rtl() { } = layout.calculate_content_widths(); layout.break_all_lines(Some(min_content_width)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name("min").check_layout_snapshot(&layout); layout.break_all_lines(Some(max_content_width)); - layout.align(Alignment::Start, AlignmentOptions::default()); assert!( layout.width() <= max_content_width, "Layout should never be wider than the max content width" @@ -1088,7 +1069,6 @@ fn text_range_rtl() { let builder = env.ranged_builder(text); let mut layout = builder.build(text); layout.break_all_lines(Some(100.0)); - layout.align(Alignment::Start, AlignmentOptions::default()); for line in layout.lines() { for item in line.items() { @@ -1104,19 +1084,16 @@ fn text_range_rtl() { } #[test] -/// Layouts can be re-line-broken and re-aligned. +/// Layouts can be re-line-broken, which re-aligns them. fn realign() { let mut env = TestEnv::new(test_name!(), None); let text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; let builder = env.ranged_builder(text); let mut layout = builder.build(text); - layout.break_all_lines(Some(150.0)); - for idx in 0..8 { - if [2, 3, 4].contains(&idx) { - layout.break_all_lines(Some(150.0)); - } - layout.align(Alignment::Justify, AlignmentOptions::default()); + layout.set_alignment(Alignment::Justify, AlignmentOptions::default()); + for _ in 0..4 { + layout.break_all_lines(Some(150.0)); } env.check_layout_snapshot(&layout); } @@ -1171,8 +1148,8 @@ fn realign_all() { for (max_advance, opts, _, _) in all_opts { let builder = env.ranged_builder(text); let mut layout = builder.build(text); + layout.set_alignment(alignment, opts); layout.break_all_lines(max_advance); - layout.align(alignment, opts); layouts.push(layout); } } @@ -1182,7 +1159,7 @@ fn realign_all() { let mut idx = 0; for (text_idx, (_, text_name)) in texts.iter().enumerate() { for (_, align_name) in alignments { - for (max_advance, _, ma_name, opts_name) in all_opts { + for (_, _, ma_name, opts_name) in all_opts { let layout = &layouts[idx]; idx += 1; @@ -1194,13 +1171,8 @@ fn realign_all() { for (top_alignment, align_name) in alignments { for (top_max_advance, top_opts, ma_name, opts_name) in all_opts { let mut top_layout = layout.clone(); - // Only break lines again if the max advance differs from base, - // because otherwise we already have the correct line breaks. - // We want to specifically test the optimization of skipping it. - if max_advance != top_max_advance { - top_layout.break_all_lines(top_max_advance); - } - top_layout.align(top_alignment, top_opts); + top_layout.set_alignment(top_alignment, top_opts); + top_layout.break_all_lines(top_max_advance); let top_name = format!("{text_name}_{align_name}_{opts_name}_{ma_name}"); //env.with_name(&top_name).check_layout_snapshot(&top_layout); @@ -1297,8 +1269,8 @@ fn trailing_whitespace_alignment_by_collapse_mode() { let mut builder = env.ranged_builder(text); builder.push_default(StyleProperty::WhiteSpaceCollapse(mode)); let mut layout = builder.build(text); + layout.set_alignment(Alignment::End, AlignmentOptions::default()); layout.break_all_lines(Some(60.0)); - layout.align(Alignment::End, AlignmentOptions::default()); env.with_name(test_case_name).check_layout_snapshot(&layout); let first_line_advance = layout.get(0).unwrap().metrics().advance; diff --git a/parley_tests/tests/content_widths.rs b/parley_tests/tests/content_widths.rs index 9b2effc20..ed1331e86 100644 --- a/parley_tests/tests/content_widths.rs +++ b/parley_tests/tests/content_widths.rs @@ -6,8 +6,8 @@ use crate::util::TestEnv; use crate::{test_name, util::ColorBrush}; use parley::{ - Alignment, AlignmentOptions, ContentWidths, IndentOptions, InlineBox, InlineBoxKind, Layout, - LineBreak, StyleProperty, TextWrapMode, VerticalAlign, WhiteSpaceCollapse, + ContentWidths, IndentOptions, InlineBox, InlineBoxKind, Layout, LineBreak, StyleProperty, + TextWrapMode, VerticalAlign, WhiteSpaceCollapse, }; /// Checks that calculated content widths agree with actual line breaking. @@ -222,7 +222,6 @@ fn inbox_content_width() { .. } = layout.calculate_content_widths(); layout.break_all_lines(Some(min_content_width)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name("full_width").check_layout_snapshot(&layout); } @@ -245,7 +244,6 @@ fn inbox_content_width() { .. } = layout.calculate_content_widths(); layout.break_all_lines(Some(max_content_width)); - layout.align(Alignment::Start, AlignmentOptions::default()); assert!( layout.width() <= max_content_width, diff --git a/parley_tests/tests/cursor.rs b/parley_tests/tests/cursor.rs index c7395fae8..a1048f419 100644 --- a/parley_tests/tests/cursor.rs +++ b/parley_tests/tests/cursor.rs @@ -12,10 +12,7 @@ use crate::{ test_name, util::{ColorBrush, CursorTest, TestEnv, env::create_font_context}, }; -use parley::{ - Affinity, Alignment, AlignmentOptions, BaseDirection, Cluster, ClusterPath, Cursor, - LayoutContext, Selection, -}; +use parley::{Affinity, BaseDirection, Cluster, ClusterPath, Cursor, LayoutContext, Selection}; #[test] fn cursor_previous_visual() { @@ -175,7 +172,6 @@ fn primary_caret_position() { builder.set_base_direction(direction); let mut layout = builder.build(text); layout.break_all_lines(wrap.then(|| layout.calculate_content_widths().min)); - layout.align(Alignment::Start, AlignmentOptions::default()); let (line, x) = layout.primary_caret(index).unwrap(); let left = line.metrics().offset + line.metrics().inline_min_coord; let edges = [(left, "left"), (left + line.metrics().advance, "right")]; diff --git a/parley_tests/tests/draw.rs b/parley_tests/tests/draw.rs index 04b6af355..c2b07645b 100644 --- a/parley_tests/tests/draw.rs +++ b/parley_tests/tests/draw.rs @@ -9,7 +9,7 @@ use crate::test_name; use crate::util::TestEnv; use parley::style::FontFamily; -use parley::{Alignment, AlignmentOptions, Layout, StyleProperty}; +use parley::{Layout, StyleProperty}; use peniko::kurbo::Affine; use super::util::ColorBrush; @@ -113,7 +113,6 @@ fn draw_underline_descenders() { builder.push_default(StyleProperty::FontSize(24.0)); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); layout }); } @@ -147,7 +146,6 @@ fn draw_bitmap_emoji() { builder.push_default(StyleProperty::FontSize(24.0)); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); layout }); } @@ -166,7 +164,6 @@ fn draw_colr_emoji() { builder.push_default(StyleProperty::FontSize(24.0)); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); layout }); } @@ -200,7 +197,6 @@ fn draw_colr_emoji_with_presentation_style() { let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); layout }); } @@ -231,7 +227,6 @@ fn draw_colr_emoji_with_presentation_style_without_setting_default_font() { let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); layout }); } diff --git a/parley_tests/tests/exclusions.rs b/parley_tests/tests/exclusions.rs index 0af7125bc..713b4747b 100644 --- a/parley_tests/tests/exclusions.rs +++ b/parley_tests/tests/exclusions.rs @@ -24,10 +24,9 @@ mod circle { let mut layout = builder.build(text); + layout.set_alignment(Alignment::Justify, AlignmentOptions::default()); apply_circle_breaking(&mut layout, diameter, line_height); - layout.align(Alignment::Justify, AlignmentOptions::default()); - env.rendering_config() .size .replace(Size::new(diameter as f64, diameter as f64)); @@ -111,10 +110,9 @@ mod waterfall { let mut layout = builder.build(text); + layout.set_alignment(alignment, AlignmentOptions::default()); apply_waterfall_breaking(&mut layout, layout_width, line_width, step); - layout.align(alignment, AlignmentOptions::default()); - env.with_name(test_case_name).check_layout_snapshot(&layout); } } @@ -176,10 +174,9 @@ mod zigzag { let mut layout = builder.build(text); + layout.set_alignment(alignment, AlignmentOptions::default()); apply_zigzag_breaking(&mut layout, width, offset); - layout.align(alignment, AlignmentOptions::default()); - env.with_name(test_case_name).check_layout_snapshot(&layout); } } diff --git a/parley_tests/tests/floats.rs b/parley_tests/tests/floats.rs index 8bc07309b..9d1e8e477 100644 --- a/parley_tests/tests/floats.rs +++ b/parley_tests/tests/floats.rs @@ -7,7 +7,7 @@ use crate::{ util::{ColorBrush, draw_layout, render_to_pixmap, samples::LOREM_IPSUM}, }; use parley::VerticalAlign; -use parley::{Alignment, AlignmentOptions, InlineBox, InlineBoxKind, Layout, YieldData}; +use parley::{InlineBox, InlineBoxKind, Layout, YieldData}; use peniko::{Color, kurbo::Rect}; use taffy::{Clear, FloatContext, FloatDirection}; @@ -67,7 +67,6 @@ fn float_simple() { let mut layout = builder.build(text); layout_floats(&mut layout, &mut floated_boxes, 300.0); - layout.align(Alignment::Start, AlignmentOptions::default()); render_and_check_float_layout(&mut env, &layout, &floated_boxes); } diff --git a/parley_tests/tests/issues.rs b/parley_tests/tests/issues.rs index 37b7e0bcc..44ec37e6f 100644 --- a/parley_tests/tests/issues.rs +++ b/parley_tests/tests/issues.rs @@ -23,7 +23,6 @@ fn issue_489() { let builder = env.ranged_builder(text); let mut layout = builder.build(text); layout.break_all_lines(Some(200.0)); - layout.align(Alignment::Start, AlignmentOptions::default()); assert!(layout.is_rtl()); } @@ -34,7 +33,6 @@ fn issue_489() { let builder = env.ranged_builder(text); let mut layout = builder.build(text); layout.break_all_lines(Some(200.0)); - layout.align(Alignment::Start, AlignmentOptions::default()); assert!(!layout.is_rtl()); @@ -82,8 +80,8 @@ And, finally, yet another sentence."#; ] { let builder = env.ranged_builder(text); let mut layout = builder.build(text); + layout.set_alignment(Alignment::Justify, AlignmentOptions::default()); layout.break_all_lines(Some(150.0)); - layout.align(Alignment::Justify, AlignmentOptions::default()); env.with_name(test_case_name).check_layout_snapshot(&layout); } } @@ -114,7 +112,6 @@ Third line that ends with newlines\n\n"; assert!(content_widths.max != 0.0); layout.break_all_lines(Some(content_widths.max)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name("max_context_with_mandatory_breaks") .check_layout_snapshot(&layout); } @@ -171,7 +168,6 @@ fn issue_748_language_subtags() { let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -200,7 +196,6 @@ fn inline_boxes_after_newline_max_content_width() { let content_widths = layout.calculate_content_widths(); layout.break_all_lines(Some(content_widths.max)); - layout.align(Alignment::Start, AlignmentOptions::default()); assert!( layout.width() <= content_widths.max, "Layout should never be wider than the max content width (width: {}, max: {})", diff --git a/parley_tests/tests/line_break.rs b/parley_tests/tests/line_break.rs index 4905b6616..867d73898 100644 --- a/parley_tests/tests/line_break.rs +++ b/parley_tests/tests/line_break.rs @@ -317,7 +317,6 @@ fn break_by_length_matches_max_advance_with_letter_spacing() { builder.push_default(StyleProperty::LetterSpacing(2.0)); let mut layout_max_advance = builder.build(text); layout_max_advance.break_all_lines(None); - layout_max_advance.align(Alignment::Start, AlignmentOptions::default()); // Count clusters per line from the max_advance layout using public API let cluster_counts: Vec = layout_max_advance @@ -335,7 +334,6 @@ fn break_by_length_matches_max_advance_with_letter_spacing() { breaker.break_next_with_length(*count); } breaker.finish(); - layout_by_length.align(Alignment::Start, AlignmentOptions::default()); // Compare the layouts - they should have the same line count assert_eq!( @@ -417,8 +415,8 @@ fn break_by_length_justified_last_line_start_aligned() { // Create layout with break_all_lines and justify let builder = env.ranged_builder(text); let mut layout_max_advance = builder.build(text); + layout_max_advance.set_alignment(Alignment::Justify, AlignmentOptions::default()); layout_max_advance.break_all_lines(Some(60.0)); // Force wrapping - layout_max_advance.align(Alignment::Justify, AlignmentOptions::default()); // Get cluster counts per line using public API let cluster_counts: Vec = layout_max_advance @@ -429,12 +427,12 @@ fn break_by_length_justified_last_line_start_aligned() { // Create layout with break_next_with_length and justify let builder2 = env.ranged_builder(text); let mut layout_by_length = builder2.build(text); + layout_by_length.set_alignment(Alignment::Justify, AlignmentOptions::default()); let mut breaker = layout_by_length.break_lines(); for count in &cluster_counts { breaker.break_next_with_length(*count); } breaker.finish(); - layout_by_length.align(Alignment::Justify, AlignmentOptions::default()); // Verify both layouts have the same number of lines assert_eq!(layout_max_advance.len(), layout_by_length.len()); diff --git a/parley_tests/tests/lines.rs b/parley_tests/tests/lines.rs index 935213b77..f4483cdf2 100644 --- a/parley_tests/tests/lines.rs +++ b/parley_tests/tests/lines.rs @@ -10,8 +10,8 @@ use crate::test_name; use crate::util::{ColorBrush, TestEnv}; use parley::VerticalAlign; use parley::{ - Affinity, Alignment, AlignmentOptions, BoundingBox, Brush, Cursor, InlineBox, InlineBoxKind, - Layout, Line, LineHeight, Selection, StyleProperty, + Affinity, BoundingBox, Brush, Cursor, InlineBox, InlineBoxKind, Layout, Line, LineHeight, + Selection, StyleProperty, }; use peniko::kurbo::Size; @@ -667,7 +667,6 @@ fn lines_line_height_metrics_relative() { let mut layout = builder.build(TEXT); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -681,7 +680,6 @@ fn lines_line_height_size_relative() { let mut layout = builder.build(TEXT); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -695,7 +693,6 @@ fn lines_line_height_absolute() { let mut layout = builder.build(TEXT); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -766,7 +763,6 @@ fn lines_revert_restores_line_height() { // "aaa B" fits, so the large glyphs are added to the first line before the line breaker // reverts to the break opportunity after the space. layout.break_all_lines(Some(95.0)); - layout.align(Alignment::Start, AlignmentOptions::default()); assert_eq!(layout.len(), 2); let heights: Vec = layout.lines().map(|l| l.metrics().line_height).collect(); @@ -786,7 +782,6 @@ fn lines_revert_restores_aligned_subtree_line_height() { let mut layout = builder.build(text); layout.break_all_lines(Some(95.0)); - layout.align(Alignment::Start, AlignmentOptions::default()); assert_eq!(layout.len(), 2); let heights: Vec = layout.lines().map(|l| l.metrics().line_height).collect(); @@ -828,7 +823,6 @@ fn lines_aligned_subtrees_grow_across_breaks() { } let (mut layout, _) = builder.build(); layout.break_all_lines(Some(130.0)); - layout.align(Alignment::Start, AlignmentOptions::default()); let metrics: Vec<(f32, f32)> = layout .lines() diff --git a/parley_tests/tests/out_of_flow_boxes.rs b/parley_tests/tests/out_of_flow_boxes.rs index b295a2698..200d6a2d6 100644 --- a/parley_tests/tests/out_of_flow_boxes.rs +++ b/parley_tests/tests/out_of_flow_boxes.rs @@ -6,7 +6,7 @@ use crate::{ util::{ColorBrush, TestEnv}, }; use parley::VerticalAlign; -use parley::{Alignment, AlignmentOptions, InlineBox, InlineBoxKind, Layout, PositionedLayoutItem}; +use parley::{InlineBox, InlineBoxKind, Layout, PositionedLayoutItem}; #[test] fn out_of_flow_box_has_no_effect_on_layout() { @@ -40,11 +40,9 @@ fn out_of_flow_box_has_no_effect_on_layout() { // Perform line breaking and alignment let mut layout_ref = layout_ref; layout_ref.break_all_lines(Some(100.0)); - layout_ref.align(Alignment::Start, AlignmentOptions::default()); let mut layout_oof = layout_oof; layout_oof.break_all_lines(Some(100.0)); - layout_oof.align(Alignment::Start, AlignmentOptions::default()); // Layout dimensions and line count should be unaffected assert_eq!(layout_ref.width(), layout_oof.width()); diff --git a/parley_tests/tests/styles/decorations.rs b/parley_tests/tests/styles/decorations.rs index 56988b05d..31b779023 100644 --- a/parley_tests/tests/styles/decorations.rs +++ b/parley_tests/tests/styles/decorations.rs @@ -5,8 +5,6 @@ use crate::test_name; use crate::util::{TestEnv, samples}; -use parley::AlignmentOptions; -use parley::layout::Alignment; use parley::style::StyleProperty; // ============================================================================ @@ -22,7 +20,6 @@ fn style_underline() { builder.push_default(StyleProperty::Underline(true)); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -38,7 +35,6 @@ fn style_underline_offset_values() { builder.push_default(StyleProperty::UnderlineOffset(Some(offset))); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); let name = if offset < 0.0 { format!("neg_{}", (-offset) as i32) @@ -60,7 +56,6 @@ fn style_underline_size_values() { builder.push_default(StyleProperty::UnderlineSize(Some(size))); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); let name = format!("size_{}", (size * 10.0) as i32); env.with_name(&name).check_layout_snapshot(&layout); @@ -76,7 +71,6 @@ fn style_underline_across_line_break() { builder.push_default(StyleProperty::Underline(true)); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -91,7 +85,6 @@ fn style_underline_partial_text() { builder.push(StyleProperty::Underline(true), 6..11); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -109,7 +102,6 @@ fn style_strikethrough() { builder.push_default(StyleProperty::Strikethrough(true)); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -125,7 +117,6 @@ fn style_strikethrough_offset_values() { builder.push_default(StyleProperty::StrikethroughOffset(Some(offset))); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); let name = if offset < 0.0 { format!("neg_{}", (-offset) as i32) @@ -147,7 +138,6 @@ fn style_strikethrough_size_values() { builder.push_default(StyleProperty::StrikethroughSize(Some(size))); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); let name = format!("size_{}", (size * 10.0) as i32); env.with_name(&name).check_layout_snapshot(&layout); @@ -168,7 +158,6 @@ fn style_underline_and_strikethrough() { builder.push_default(StyleProperty::Strikethrough(true)); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } diff --git a/parley_tests/tests/styles/font_selection.rs b/parley_tests/tests/styles/font_selection.rs index 34f25d39d..8d328ec9c 100644 --- a/parley_tests/tests/styles/font_selection.rs +++ b/parley_tests/tests/styles/font_selection.rs @@ -8,9 +8,8 @@ use std::borrow::Cow; use crate::test_name; use crate::util::{ColorBrush, TestEnv, samples}; use fontique::FontInfoOverride; -use parley::layout::Alignment; use parley::style::StyleProperty; -use parley::{AlignmentOptions, FontWeight, Layout}; +use parley::{FontWeight, Layout}; /// Helper to build a layout with a single font size applied fn build_with_font_size(env: &mut TestEnv, text: &str, size: f32) -> Layout { @@ -18,7 +17,6 @@ fn build_with_font_size(env: &mut TestEnv, text: &str, size: f32) -> Layout Lay builder.push_default(StyleProperty::LetterSpacing(spacing)); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); layout } @@ -39,7 +36,6 @@ fn build_with_word_spacing(env: &mut TestEnv, text: &str, spacing: f32) -> Layou builder.push_default(StyleProperty::WordSpacing(spacing)); let mut layout = builder.build(text); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); layout } diff --git a/parley_tests/tests/styles/vertical_align.rs b/parley_tests/tests/styles/vertical_align.rs index f4c8f30cf..d37f83df7 100644 --- a/parley_tests/tests/styles/vertical_align.rs +++ b/parley_tests/tests/styles/vertical_align.rs @@ -5,9 +5,8 @@ use crate::test_name; use crate::util::TestEnv; -use parley::layout::Alignment; use parley::style::StyleProperty; -use parley::{AlignmentOptions, InlineBox, InlineBoxKind, VerticalAlign}; +use parley::{InlineBox, InlineBoxKind, VerticalAlign}; /// Every keyword, applied to a span in the middle of a line of text. #[test] @@ -39,7 +38,6 @@ fn vertical_align_keywords() { builder.pop_style_span(); let (mut layout, _) = builder.build(); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name(name).check_layout_snapshot(&layout); } @@ -68,7 +66,6 @@ fn vertical_align_nested_super() { builder.pop_style_span(); let (mut layout, _) = builder.build(); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -87,7 +84,6 @@ fn vertical_align_ancestor_without_text() { builder.pop_style_span(); let (mut layout, _) = builder.build(); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -120,7 +116,6 @@ fn vertical_align_inline_boxes() { builder.pop_style_span(); let (mut layout, _) = builder.build(); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name(name).check_layout_snapshot(&layout); } @@ -149,7 +144,6 @@ fn vertical_align_tall_top_bottom() { builder.pop_style_span(); let (mut layout, _) = builder.build(); layout.break_all_lines(None); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name(name).check_layout_snapshot(&layout); } diff --git a/parley_tests/tests/text_indent.rs b/parley_tests/tests/text_indent.rs index c7eb40173..b31ec938b 100644 --- a/parley_tests/tests/text_indent.rs +++ b/parley_tests/tests/text_indent.rs @@ -18,8 +18,8 @@ fn build_indented_layout( let builder = env.ranged_builder(text); let mut layout = builder.build(text); layout.set_text_indent(indent_amount, indent_options); + layout.set_alignment(alignment, AlignmentOptions::default()); layout.break_all_lines(Some(wrap_width)); - layout.align(alignment, AlignmentOptions::default()); layout } diff --git a/parley_tests/tests/util/env.rs b/parley_tests/tests/util/env.rs index 12ff764aa..42ea096d0 100644 --- a/parley_tests/tests/util/env.rs +++ b/parley_tests/tests/util/env.rs @@ -10,9 +10,9 @@ use std::sync::Arc; use fontique::{Blob, Collection, CollectionOptions, SourceCache}; use parley::{ - BoundingBox, FontContext, FontFamily, FontFamilyName, Layout, LayoutContext, LineHeight, - PlainEditor, PlainEditorDriver, PositionedLayoutItem, RangedBuilder, StyleProperty, TextStyle, - TreeBuilder, + Alignment, AlignmentOptions, BoundingBox, FontContext, FontFamily, FontFamilyName, Layout, + LayoutContext, LineHeight, PlainEditor, PlainEditorDriver, PositionedLayoutItem, RangedBuilder, + StyleProperty, TextStyle, TreeBuilder, }; use peniko::{Color, kurbo::Size}; use vello_cpu::Pixmap; @@ -329,6 +329,8 @@ impl TestEnv { builder.push_default(StyleProperty::FontSize(char_info_font_size)); builder.push_default(StyleProperty::Brush(ColorBrush::new(CLUSTER_INFO_COLOR))); let mut grapheme_layout = builder.build(grapheme); + // TODO: Maybe Center or Start alignment would be better? + grapheme_layout.set_alignment(Alignment::Left, AlignmentOptions::default()); grapheme_layout.break_all_lines(Some(400.0)); grapheme_layouts.insert(grapheme.to_string(), grapheme_layout); } diff --git a/parley_tests/tests/whitespace.rs b/parley_tests/tests/whitespace.rs index a78616eff..a0d4bed3b 100644 --- a/parley_tests/tests/whitespace.rs +++ b/parley_tests/tests/whitespace.rs @@ -86,7 +86,8 @@ fn hanging_across_collapse_mode_boundary() { nearly_eq(line.metrics().hanging_advance, hanging); nearly_eq(layout.width(), full - hanging); // Overflowing lines aren't aligned by default. - layout.align(Alignment::Right, AlignmentOptions::default()); + layout.set_alignment(Alignment::Right, AlignmentOptions::default()); + layout.break_all_lines(Some(width)); nearly_eq( layout.get(0).unwrap().metrics().offset, (width - full + hanging).max(0.), @@ -255,9 +256,11 @@ fn break_spaces_retains_advance_at_forced_breaks_and_block_end() { nearly_eq(line.metrics().advance, full); nearly_eq(line.metrics().hanging_advance, 0.); nearly_eq(layout.calculate_content_widths().max, full); - layout.align(Alignment::Right, AlignmentOptions::default()); + layout.set_alignment(Alignment::Right, AlignmentOptions::default()); + layout.break_all_lines(Some(full + 20.)); nearly_eq(layout.get(0).unwrap().metrics().offset, 20.); - layout.align(Alignment::Center, AlignmentOptions::default()); + layout.set_alignment(Alignment::Center, AlignmentOptions::default()); + layout.break_all_lines(Some(full + 20.)); nearly_eq(layout.get(0).unwrap().metrics().offset, 10.); } } diff --git a/parley_tests/tests/wrap.rs b/parley_tests/tests/wrap.rs index 31ea4885d..fc0baf899 100644 --- a/parley_tests/tests/wrap.rs +++ b/parley_tests/tests/wrap.rs @@ -6,8 +6,7 @@ use crate::test_name; use crate::util::{ColorBrush, TestEnv}; use parley::{ - Alignment, AlignmentOptions, BreakReason, CHROMIUM_LINE_BREAK_OVERRIDE, OverflowWrap, - StyleProperty, TextWrapMode, WordBreak, + BreakReason, CHROMIUM_LINE_BREAK_OVERRIDE, OverflowWrap, StyleProperty, TextWrapMode, WordBreak, }; use peniko::color::palette::css; @@ -49,7 +48,6 @@ fn test_wrap_with_custom_text( let mut layout = builder.build(text); layout.break_all_lines(Some(wrap_width)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -143,7 +141,6 @@ fn overflow_wrap_anywhere_min_content_width() { let mut layout = builder.build(text); layout.break_all_lines(Some(layout.calculate_content_widths().min)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -158,7 +155,6 @@ fn overflow_wrap_break_word_min_content_width() { let mut layout = builder.build(text); layout.break_all_lines(Some(layout.calculate_content_widths().min)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.check_layout_snapshot(&layout); } @@ -225,7 +221,6 @@ fn word_break_break_all_min_content_width() { let mut layout = builder.build(text); layout.break_all_lines(Some(layout.calculate_content_widths().min)); - layout.align(Alignment::Start, AlignmentOptions::default()); // This snapshot will have slightly different line wrapping than the corresponding overflow-wrap test. This is to be // expected and matches browser/CSS behavior. env.check_layout_snapshot(&layout); @@ -260,7 +255,6 @@ fn word_break_keep_all() { let mut layout = builder.build(text); layout.break_all_lines(Some(wrap_width)); - layout.align(Alignment::Start, AlignmentOptions::default()); env.with_name(name).check_layout_snapshot(&layout); }; @@ -452,7 +446,6 @@ fn wrap_url_breaks_after_slash() { let mut layout = env.ranged_builder(text).build(text); layout.break_all_lines(Some(150.0)); - layout.align(Alignment::Start, AlignmentOptions::default()); assert!(layout.len() > 1); @@ -483,7 +476,6 @@ fn wrap_url_override_no_break_after_slash() { builder.set_line_break_override(Some(&CHROMIUM_LINE_BREAK_OVERRIDE)); let mut layout = builder.build(text); layout.break_all_lines(Some(wrap_width)); - layout.align(Alignment::Start, AlignmentOptions::default()); assert_eq!(layout.len(), 1);