diff --git a/examples/common/src/lib.rs b/examples/common/src/lib.rs index 1146adb7d..446cff1c8 100644 --- a/examples/common/src/lib.rs +++ b/examples/common/src/lib.rs @@ -14,7 +14,7 @@ use std::time::Instant; use parley::fontique::Blob; use parley::{ Alignment, AlignmentOptions, FontContext, FontFamily, FontWeight, GenericFamily, InlineBox, - InlineBoxKind, Layout, LayoutContext, LineHeight, StyleProperty, + InlineBoxKind, InlineBoxVerticalAlign, Layout, LayoutContext, LineHeight, StyleProperty, }; use peniko::Color; @@ -207,6 +207,7 @@ pub fn build_rich_layout( width: 50.0, height: 50.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); let mut layout = builder.build(&config.text); diff --git a/examples/swash_render/src/main.rs b/examples/swash_render/src/main.rs index 9baaab2c5..16b498fb0 100644 --- a/examples/swash_render/src/main.rs +++ b/examples/swash_render/src/main.rs @@ -10,7 +10,10 @@ use image::codecs::png::PngEncoder; use image::{self, Pixel, Rgba, RgbaImage}; use parley::layout::{Alignment, Glyph, GlyphRun, Layout, PositionedLayoutItem}; use parley::style::{FontFamily, FontWeight, StyleProperty, TextStyle}; -use parley::{AlignmentOptions, FontContext, InlineBox, InlineBoxKind, LayoutContext, LineHeight}; +use parley::{ + AlignmentOptions, FontContext, InlineBox, InlineBoxKind, InlineBoxVerticalAlign, LayoutContext, + LineHeight, +}; use std::fs::File; use swash::FontRef; use swash::scale::image::Content; @@ -99,6 +102,7 @@ fn main() { width: 50.0, height: 50.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); builder.push_text(&text[40..50]); @@ -110,6 +114,7 @@ fn main() { width: 50.0, height: 30.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); builder.push_text(&text[50..141]); @@ -161,6 +166,7 @@ fn main() { width: 50.0, height: 50.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); builder.push_inline_box(InlineBox { id: 1, @@ -169,6 +175,7 @@ fn main() { width: 50.0, height: 30.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); // Build the builder into a Layout diff --git a/examples/tiny_skia_render/src/main.rs b/examples/tiny_skia_render/src/main.rs index 6adb05c2e..28c2288e4 100644 --- a/examples/tiny_skia_render/src/main.rs +++ b/examples/tiny_skia_render/src/main.rs @@ -11,7 +11,8 @@ use parley::{ Alignment, AlignmentOptions, FontContext, FontWeight, GenericFamily, GlyphRun, InlineBox, - InlineBoxKind, Layout, LayoutContext, LineHeight, PositionedLayoutItem, StyleProperty, + InlineBoxKind, InlineBoxVerticalAlign, Layout, LayoutContext, LineHeight, PositionedLayoutItem, + StyleProperty, }; use skrifa::{ GlyphId, MetadataProvider, OutlineGlyph, @@ -93,6 +94,7 @@ fn main() { width: 50.0, height: 50.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); // Build the builder into a Layout diff --git a/parley/src/inline_box.rs b/parley/src/inline_box.rs index 4b65d8753..86707e8fe 100644 --- a/parley/src/inline_box.rs +++ b/parley/src/inline_box.rs @@ -20,6 +20,26 @@ pub struct InlineBox { /// /// If `None`, the baseline is the box's bottom edge. pub baseline: Option, + /// How the box is aligned within its line box. + pub vertical_align: InlineBoxVerticalAlign, +} + +/// How an [`InlineBox`] is aligned within its line box. +#[derive(PartialEq, Eq, Debug, Clone, Copy, Default)] +pub enum InlineBoxVerticalAlign { + /// The box's baseline is aligned with the line's baseline. + /// + /// This corresponds to `vertical-align: baseline` in CSS. + #[default] + Baseline, + /// The top of the box is aligned with the top of the line box. + /// + /// This corresponds to `vertical-align: top` in CSS. + Top, + /// The bottom of the box is aligned with the bottom of the line box. + /// + /// This corresponds to `vertical-align: bottom` in CSS. + Bottom, } /// Whether a box is in-flow (takes up space in the layout) or out-of-flow (e.g. absolutely positioned) diff --git a/parley/src/layout/line.rs b/parley/src/layout/line.rs index 60ff8bece..1cc647b30 100644 --- a/parley/src/layout/line.rs +++ b/parley/src/layout/line.rs @@ -7,7 +7,7 @@ use crate::layout::data::{LayoutItemKind, LineData}; use crate::layout::layout::Layout; use crate::layout::run::Run; use crate::style::Brush; -use crate::{InlineBox, InlineBoxKind}; +use crate::{InlineBox, InlineBoxKind, InlineBoxVerticalAlign}; use core::ops::Range; use parley_engine::Glyph; @@ -321,10 +321,19 @@ impl<'a, B: Brush> Iterator for GlyphRunIter<'a, B> { if inline_box.kind == InlineBoxKind::InFlow { self.offset += inline_box.width; } + let y = match inline_box.vertical_align { + InlineBoxVerticalAlign::Baseline => { + self.line.data.metrics.baseline + - inline_box.baseline.unwrap_or(inline_box.height) + } + InlineBoxVerticalAlign::Top => self.line.data.metrics.block_min_coord, + InlineBoxVerticalAlign::Bottom => { + self.line.data.metrics.block_max_coord - inline_box.height + } + }; return Some(PositionedLayoutItem::InlineBox(PositionedInlineBox { x, - y: self.line.data.metrics.baseline - - inline_box.baseline.unwrap_or(inline_box.height), + y, width: inline_box.width, height: inline_box.height, baseline: inline_box.baseline, diff --git a/parley/src/layout/line_break.rs b/parley/src/layout/line_break.rs index 09e350a7c..eb6dc0a65 100644 --- a/parley/src/layout/line_break.rs +++ b/parley/src/layout/line_break.rs @@ -17,7 +17,7 @@ use crate::layout::{ LineMetrics, Run, }; use crate::style::Brush; -use crate::{InlineBoxKind, OverflowWrap, TextWrapMode}; +use crate::{InlineBoxKind, InlineBoxVerticalAlign, OverflowWrap, TextWrapMode}; use core::ops::Range; use parley_engine::shape::Whitespace; @@ -90,6 +90,11 @@ struct LineBoxMetrics { /// /// Like [`Self::line_box`], these are in block flow direction. content_box: Extents, + /// The height of the tallest top- or bottom-aligned inline box on the line. + /// + /// Such boxes grow the line box if they are taller than it, but do not affect the + /// position of the baseline within it. + top_or_bottom_box_height: f32, } #[derive(Clone, Copy, Debug)] @@ -117,6 +122,13 @@ impl Default for Extents { } impl Extents { + fn max(self, other: Self) -> Self { + Self { + over: self.over.max(other.over), + under: self.under.max(other.under), + } + } + /// Resolve unset (default) extents to zero. fn or_zero(self) -> Self { if self.over == f32::NEG_INFINITY && self.under == f32::NEG_INFINITY { @@ -130,12 +142,36 @@ impl Extents { } } +/// Compute the extents of text over and under the baseline, distributing the leading +/// (the difference between the line height and the text's ascent + descent) equally +/// over and under the text (CSS 2 ยง 10.8.1). The leading (and thus the extents) may +/// be negative when the line height is smaller than ascent + descent. +fn text_extents(mut ascent: f32, mut descent: f32, line_height: f32, quantize: bool) -> Extents { + if quantize { + ascent = ascent.round(); + descent = descent.round(); + } + let half_leading = (line_height - (ascent + descent)) / 2.; + let over = if quantize { + ascent + half_leading.floor() + } else { + ascent + half_leading + }; + // Note the `under` part is *not* quantized. This is such that the exact line height is + // reached. For determining the line box block, add this to the baseline and then quantize + // by rounding. + Extents { + over, + under: line_height - over, + } +} + impl LineBoxMetrics { /// The line height seen so far. #[inline(always)] fn line_height(self) -> f32 { let line_box = self.line_box.or_zero(); - line_box.over + line_box.under + (line_box.over + line_box.under).max(self.top_or_bottom_box_height) } fn add_text(&mut self, metrics: &FontMetrics, line_height: f32, quantize: bool) { @@ -175,6 +211,14 @@ impl LineBoxMetrics { self.content_box.under = self.content_box.under.max(descent); } } + + /// Add an inline box aligned to the top or bottom of the line box rather than to the + /// baseline. Such a box only grows the line if it is taller than the line's height; it + /// does not affect the baseline's position within the line. + fn add_top_or_bottom_aligned_inline_box(&mut self, height: f32, quantize: bool) { + let height = if quantize { height.round() } else { height }; + self.top_or_bottom_box_height = self.top_or_bottom_box_height.max(height); + } } #[derive(Clone, Default)] @@ -316,6 +360,18 @@ impl Default for BreakerState { } } +/// How an inline box contributes to its line box's metrics, resolved from the box's +/// [`vertical_align`](InlineBox::vertical_align) and [`baseline`](InlineBox::baseline). +#[derive(Clone, Copy, Debug)] +pub enum InlineBoxAlignment { + /// The box is aligned to the line's baseline: `ascent` extends over it and `descent` + /// under it. + Baseline { ascent: f32, descent: f32 }, + /// The box is aligned to the top or bottom of the line box, growing the line to at + /// least `height` without affecting the baseline's position. + TopOrBottom { height: f32 }, +} + impl BreakerState { /// Add the atom currently being evaluated to the current line. /// @@ -347,22 +403,30 @@ impl BreakerState { /// Add an inline box to the line. /// - /// `ascent` and `descent` are the distances the box extends above and below the text baseline - /// respectively. A box with its bottom aligned to the baseline is simply one with a zero - /// descent. The box grows the line only insofar as it extends beyond the text. + /// `alignment` describes how the box contributes to the line's vertical metrics. Pass `None` + /// for boxes that should not affect them (e.g. out-of-flow boxes). pub fn append_inline_box_to_line( &mut self, next_x: f32, - ascent: f32, - descent: f32, + alignment: Option, quantize: bool, ) { self.item_idx += 1; self.line.items.end += 1; self.line.x = next_x; - self.line - .box_metrics - .add_inline_box(ascent, descent, quantize); + match alignment { + Some(InlineBoxAlignment::Baseline { ascent, descent }) => { + self.line + .box_metrics + .add_inline_box(ascent, descent, quantize); + } + Some(InlineBoxAlignment::TopOrBottom { height }) => { + self.line + .box_metrics + .add_top_or_bottom_aligned_inline_box(height, quantize); + } + None => {} + } self.update_max_height_exceeded(); } @@ -474,10 +538,11 @@ impl<'a, B: Brush> BreakLines<'a, B> { lines.swap(&mut layout.data); lines.lines.clear(); lines.line_items.clear(); + let state = BreakerState::default(); Self { layout, lines, - state: BreakerState::default(), + state, prev_state: None, done: false, } @@ -657,26 +722,9 @@ impl<'a, B: Brush> BreakLines<'a, B> { // and the portion below to its descent. By default (no explicit baseline) the // bottom of the box is aligned with the text baseline, i.e. the box is all // ascent and zero descent. Out-of-flow boxes contribute nothing. - let ( - width_contribution, - height_contribution, - ascent_contribution, - descent_contribution, - ) = match inline_box.kind { - InlineBoxKind::InFlow => { - let baseline = inline_box.baseline.unwrap_or(inline_box.height); - ( - inline_box.width, - inline_box.height, - baseline, - inline_box.height - baseline, - ) - } - // Negative infinity extents are a no-op when maxed into the line's - // extents, so out-of-flow boxes truly contribute nothing. - InlineBoxKind::OutOfFlow => { - (0.0, 0.0, f32::NEG_INFINITY, f32::NEG_INFINITY) - } + let (width_contribution, height_contribution) = match inline_box.kind { + InlineBoxKind::InFlow => (inline_box.width, inline_box.height), + InlineBoxKind::OutOfFlow => (0.0, 0.0), // If the box is a `CustomOutOfFlow` box then we yield control flow back to the caller. // It is then the caller's responsibility to handle placement of the box. InlineBoxKind::CustomOutOfFlow => { @@ -688,6 +736,25 @@ impl<'a, B: Brush> BreakLines<'a, B> { } }; + // Out-of-flow boxes do not contribute to the line's vertical metrics. + let alignment = match inline_box.kind { + InlineBoxKind::InFlow => Some(match inline_box.vertical_align { + InlineBoxVerticalAlign::Baseline => { + let baseline = inline_box.baseline.unwrap_or(height_contribution); + InlineBoxAlignment::Baseline { + ascent: baseline, + descent: height_contribution - baseline, + } + } + InlineBoxVerticalAlign::Top | InlineBoxVerticalAlign::Bottom => { + InlineBoxAlignment::TopOrBottom { + height: height_contribution, + } + } + }), + _ => None, + }; + // Compute the x position of the content being currently processed let next_x = self.state.line.x + width_contribution; @@ -706,8 +773,7 @@ impl<'a, B: Brush> BreakLines<'a, B> { self.state.append_inline_box_to_line( next_x, - ascent_contribution, - descent_contribution, + alignment, self.layout.data.quantize, ); @@ -719,8 +785,7 @@ impl<'a, B: Brush> BreakLines<'a, B> { // println!("BOX EMERGENCY BREAK"); self.state.append_inline_box_to_line( next_x, - ascent_contribution, - descent_contribution, + alignment, self.layout.data.quantize, ); BreakReason::Emergency @@ -972,8 +1037,7 @@ impl<'a, B: Brush> BreakLines<'a, B> { if inline_box.kind != InlineBoxKind::InFlow { self.state.append_inline_box_to_line( self.state.line.x, - f32::NEG_INFINITY, - f32::NEG_INFINITY, + None, self.layout.data.quantize, ); continue; @@ -990,11 +1054,23 @@ impl<'a, B: Brush> BreakLines<'a, B> { let next_x = self.state.line.x + inline_box.width; // The portion above the baseline is ascent, the rest descent. A box without an // explicit baseline is bottom-aligned, i.e. all ascent and zero descent. - let baseline = inline_box.baseline.unwrap_or(inline_box.height); + let alignment = match inline_box.vertical_align { + InlineBoxVerticalAlign::Baseline => { + let baseline = inline_box.baseline.unwrap_or(inline_box.height); + InlineBoxAlignment::Baseline { + ascent: baseline, + descent: inline_box.height - baseline, + } + } + InlineBoxVerticalAlign::Top | InlineBoxVerticalAlign::Bottom => { + InlineBoxAlignment::TopOrBottom { + height: inline_box.height, + } + } + }; self.state.append_inline_box_to_line( next_x, - baseline, - inline_box.height - baseline, + Some(alignment), self.layout.data.quantize, ); char_count += 1; @@ -1119,8 +1195,7 @@ impl<'a, B: Brush> BreakLines<'a, B> { if let YieldData::InlineBoxBreak(_) = yield_data { self.state.append_inline_box_to_line( self.state.line.x, - 0.0, - 0.0, + None, self.layout.data.quantize, ); } @@ -1301,7 +1376,7 @@ impl<'a, B: Brush> BreakLines<'a, B> { let quantize = self.layout.data.quantize; let mut line_box_extents = self.state.line.box_metrics.line_box; - let mut content_box_extents = self.state.line.box_metrics.content_box; + let content_box_extents = self.state.line.box_metrics.content_box; // Lines with content include the layout's strut (see `LayoutData::strut`): the extents // of a zero-width text run in the layout's root style. Lines without content (e.g. a @@ -1310,12 +1385,19 @@ impl<'a, B: Brush> BreakLines<'a, B> { if have_metrics && let Some(strut) = self.layout.data.strut { let strut_extents = text_extents(strut.ascent, strut.descent, strut.line_height, quantize); - line_box_extents.over = line_box_extents.over.max(strut_extents.over); - line_box_extents.under = line_box_extents.under.max(strut_extents.under); + line_box_extents = line_box_extents.max(strut_extents); } let mut line_box_extents = line_box_extents.or_zero(); let mut content_box_extents = content_box_extents.or_zero(); + + // Grow the line box to fit any top- or bottom-aligned inline boxes taller than it. + // The extra space is added below the baseline, keeping the baseline's position + // relative to the baseline-aligned content. + let top_or_bottom_box_height = self.state.line.box_metrics.top_or_bottom_box_height; + if line_box_extents.over + line_box_extents.under < top_or_bottom_box_height { + line_box_extents.under = top_or_bottom_box_height - line_box_extents.over; + } if !have_metrics && line.item_range.is_empty() && let Some(metrics) = prev_line_metrics diff --git a/parley/src/layout/mod.rs b/parley/src/layout/mod.rs index b23095c22..30f324795 100644 --- a/parley/src/layout/mod.rs +++ b/parley/src/layout/mod.rs @@ -31,7 +31,8 @@ pub use data::BreakReason; pub use layout::Layout; pub use line::{GlyphRun, Line, LineMetrics, PositionedInlineBox, PositionedLayoutItem}; pub use line_break::{ - BoxBreakData, BreakLines, BreakerState, LineBreakData, MaxHeightBreakData, YieldData, + BoxBreakData, BreakLines, BreakerState, InlineBoxAlignment, LineBreakData, MaxHeightBreakData, + YieldData, }; pub use run::Run; diff --git a/parley/src/lib.rs b/parley/src/lib.rs index 1aa7938a4..3a8b46f4a 100644 --- a/parley/src/lib.rs +++ b/parley/src/lib.rs @@ -26,8 +26,9 @@ //! //! ```rust //! use parley::{ -//! Alignment, AlignmentOptions, FontContext, FontWeight, InlineBox, InlineBoxKind, Layout, -//! LayoutContext, LineHeight, PositionedLayoutItem, StyleProperty, +//! Alignment, AlignmentOptions, FontContext, FontWeight, InlineBox, InlineBoxKind, +//! InlineBoxVerticalAlign, Layout, LayoutContext, LineHeight, PositionedLayoutItem, +//! StyleProperty, //! }; //! //! // Create a FontContext (font database) and LayoutContext (scratch space). @@ -47,7 +48,7 @@ //! builder.push(StyleProperty::FontWeight(FontWeight::new(600.0)), 0..4); //! //! // Add a box to be laid out inline with the text -//! builder.push_inline_box(InlineBox { id: 0, kind: InlineBoxKind::InFlow, index: 5, width: 50.0, height: 50.0, baseline: None }); +//! builder.push_inline_box(InlineBox { id: 0, kind: InlineBoxKind::InFlow, index: 5, width: 50.0, height: 50.0, baseline: None, vertical_align: InlineBoxVerticalAlign::default() }); //! //! // Build the builder into a Layout //! let mut layout: Layout<()> = builder.build(&TEXT); @@ -135,7 +136,7 @@ pub use parley_engine::break_overrides::{ pub use builder::{RangedBuilder, StyleRunBuilder, TreeBuilder}; pub use context::LayoutContext; pub use font::FontContext; -pub use inline_box::{InlineBox, InlineBoxKind}; +pub use inline_box::{InlineBox, InlineBoxKind, InlineBoxVerticalAlign}; #[doc(inline)] pub use layout::Layout; pub use util::BoundingBox; diff --git a/parley_tests/tests/basic.rs b/parley_tests/tests/basic.rs index b28f52466..7796f37fa 100644 --- a/parley_tests/tests/basic.rs +++ b/parley_tests/tests/basic.rs @@ -7,7 +7,8 @@ use crate::util::TestEnv; use crate::{test_name, util::ColorBrush}; use parley::{ Alignment, AlignmentOptions, BreakReason, ContentWidths, FontFamily, InlineBox, InlineBoxKind, - Layout, LineHeight, PositionedLayoutItem, StyleProperty, TextStyle, WhiteSpaceCollapse, + InlineBoxVerticalAlign, Layout, LineHeight, PositionedLayoutItem, StyleProperty, TextStyle, + WhiteSpaceCollapse, }; use peniko::color::{AlphaColor, Srgb, palette}; use peniko::kurbo::Size; @@ -71,6 +72,7 @@ fn placing_inboxes() { width: 10.0, height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); let mut layout = builder.build(text); layout.break_all_lines(None); @@ -93,6 +95,7 @@ fn only_inboxes_wrap() { width: 10.0, height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); } let mut layout = builder.build(text); @@ -116,6 +119,7 @@ fn full_width_inbox() { width: 10., height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); builder.push_inline_box(InlineBox { id: 1, @@ -124,6 +128,7 @@ fn full_width_inbox() { width, height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); builder.push_inline_box(InlineBox { id: 2, @@ -132,6 +137,7 @@ fn full_width_inbox() { width, height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); let mut layout = builder.build(text); layout.break_all_lines(Some(100.)); @@ -152,6 +158,7 @@ fn inbox_separated_by_whitespace() { width: 10., height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); builder.push_text(" "); builder.push_inline_box(InlineBox { @@ -161,6 +168,7 @@ fn inbox_separated_by_whitespace() { width: 10.0, height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); builder.push_text(" "); builder.push_inline_box(InlineBox { @@ -170,6 +178,7 @@ fn inbox_separated_by_whitespace() { width: 10.0, height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); builder.push_text(" "); builder.push_inline_box(InlineBox { @@ -179,6 +188,7 @@ fn inbox_separated_by_whitespace() { width: 10.0, height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); let (mut layout, _text) = builder.build(); layout.break_all_lines(Some(100.)); @@ -208,6 +218,7 @@ fn inbox_with_baseline() { width: 20.0, height: 30.0, baseline: Some(baseline), + vertical_align: InlineBoxVerticalAlign::default(), }); let mut layout = builder.build(text); layout.break_all_lines(None); @@ -232,6 +243,7 @@ fn inboxes_with_matching_baselines() { width: 15.0, height: 15.0, baseline: Some(10.0), + vertical_align: InlineBoxVerticalAlign::default(), }); builder.push_inline_box(InlineBox { id: 1, @@ -240,6 +252,7 @@ fn inboxes_with_matching_baselines() { width: 15.0, height: 40.0, baseline: Some(10.0), + vertical_align: InlineBoxVerticalAlign::default(), }); let mut layout = builder.build(text); layout.break_all_lines(None); @@ -269,6 +282,7 @@ fn inboxes_with_large_ascent_and_descent() { width: 15.0, height: 40.0, baseline: Some(38.0), + vertical_align: InlineBoxVerticalAlign::default(), }); // Large descent: the baseline is near the top of the box, so most of it is below the baseline. builder.push_inline_box(InlineBox { @@ -278,6 +292,7 @@ fn inboxes_with_large_ascent_and_descent() { width: 15.0, height: 40.0, baseline: Some(2.0), + vertical_align: InlineBoxVerticalAlign::default(), }); let mut layout = builder.build(text); layout.break_all_lines(None); @@ -309,6 +324,7 @@ fn inbox_below_baseline_keeps_grid() { width: 20.0, height: 15.0, baseline: Some(0.0), + vertical_align: InlineBoxVerticalAlign::default(), }); let mut layout = builder.build(text); layout.break_all_lines(None); @@ -661,6 +677,7 @@ fn inbox_content_width() { width: 100.0, height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); let mut layout = builder.build(text); let ContentWidths { @@ -683,6 +700,7 @@ fn inbox_content_width() { width: 10.0, height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); let mut layout = builder.build(text); let ContentWidths { diff --git a/parley_tests/tests/floats.rs b/parley_tests/tests/floats.rs index 366300a76..8304b71d1 100644 --- a/parley_tests/tests/floats.rs +++ b/parley_tests/tests/floats.rs @@ -6,7 +6,10 @@ use crate::{ test_name, util::{ColorBrush, draw_layout, render_to_pixmap, samples::LOREM_IPSUM}, }; -use parley::{Alignment, AlignmentOptions, InlineBox, InlineBoxKind, Layout, YieldData}; +use parley::{ + Alignment, AlignmentOptions, InlineBox, InlineBoxKind, InlineBoxVerticalAlign, Layout, + YieldData, +}; use peniko::{Color, kurbo::Rect}; use taffy::{Clear, FloatContext, FloatDirection}; @@ -59,6 +62,7 @@ fn float_simple() { width: 0.0, height: 0.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); } @@ -180,8 +184,7 @@ fn layout_floats( state.append_inline_box_to_line( box_break_data.advance, - 0.0, - 0.0, + None, true, // TODO: quantize is known to be `true` here, but perhaps we should expose // something like `Layout::quantized`. ); diff --git a/parley_tests/tests/issues.rs b/parley_tests/tests/issues.rs index a06e99c32..797d36a54 100644 --- a/parley_tests/tests/issues.rs +++ b/parley_tests/tests/issues.rs @@ -6,8 +6,8 @@ use crate::test_name; use crate::util::TestEnv; use parley::{ - Alignment, AlignmentOptions, FontFamily, InlineBox, InlineBoxKind, PositionedLayoutItem, - StyleProperty, TextWrapMode, + Alignment, AlignmentOptions, FontFamily, InlineBox, InlineBoxKind, InlineBoxVerticalAlign, + PositionedLayoutItem, StyleProperty, TextWrapMode, }; /// Test that rendering RTL text doesn't affect subsequent LTR layouts. @@ -136,6 +136,7 @@ fn issue_752() { width: 10.0, height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); let mut layout = builder.build(text); layout.break_all_lines(Some(100.0)); diff --git a/parley_tests/tests/line_break.rs b/parley_tests/tests/line_break.rs index ddd10f5f2..4e06046c3 100644 --- a/parley_tests/tests/line_break.rs +++ b/parley_tests/tests/line_break.rs @@ -9,7 +9,9 @@ use crate::test_name; use crate::util::TestEnv; use parley::style::FontFamily; -use parley::{Alignment, AlignmentOptions, InlineBox, InlineBoxKind, StyleProperty}; +use parley::{ + Alignment, AlignmentOptions, InlineBox, InlineBoxKind, InlineBoxVerticalAlign, StyleProperty, +}; #[test] fn break_by_length_basic() { @@ -105,6 +107,7 @@ fn break_by_length_with_inline_box() { width: 10.0, height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); let mut layout = builder.build(text); @@ -133,6 +136,7 @@ fn break_by_length_multiple_inline_boxes() { width: 10.0, height: 10.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); } let mut layout = builder.build(text); diff --git a/parley_tests/tests/lines.rs b/parley_tests/tests/lines.rs index 341e3f3e4..da91bfb71 100644 --- a/parley_tests/tests/lines.rs +++ b/parley_tests/tests/lines.rs @@ -10,7 +10,7 @@ use crate::test_name; use crate::util::{ColorBrush, TestEnv}; use parley::{ Affinity, Alignment, AlignmentOptions, BoundingBox, Brush, Cursor, InlineBox, InlineBoxKind, - Layout, Line, LineHeight, Selection, StyleProperty, + InlineBoxVerticalAlign, Layout, Line, LineHeight, Selection, StyleProperty, }; use peniko::kurbo::Size; @@ -141,6 +141,7 @@ fn build_layout>>( width: 50.0, height: 5.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); builder.push_inline_box(InlineBox { id: 1, @@ -149,6 +150,7 @@ fn build_layout>>( width: 50.0, height: 3.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); let mut layout = builder.build(TEXT); @@ -527,6 +529,7 @@ fn lines_negative_leading_inline_box_grows_line_box() { width: 12.0, height: box_height, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); let mut layout: Layout = builder.build(text); layout.break_all_lines(None); diff --git a/parley_tests/tests/out_of_flow_boxes.rs b/parley_tests/tests/out_of_flow_boxes.rs index 65eaba99e..7d8708e34 100644 --- a/parley_tests/tests/out_of_flow_boxes.rs +++ b/parley_tests/tests/out_of_flow_boxes.rs @@ -5,7 +5,10 @@ use crate::{ test_name, util::{ColorBrush, TestEnv}, }; -use parley::{Alignment, AlignmentOptions, InlineBox, InlineBoxKind, Layout, PositionedLayoutItem}; +use parley::{ + Alignment, AlignmentOptions, InlineBox, InlineBoxKind, InlineBoxVerticalAlign, Layout, + PositionedLayoutItem, +}; #[test] fn out_of_flow_box_has_no_effect_on_layout() { @@ -27,6 +30,7 @@ fn out_of_flow_box_has_no_effect_on_layout() { width: 9999.0, height: 9999.0, baseline: None, + vertical_align: InlineBoxVerticalAlign::default(), }); let layout_oof = builder_oof.build(text); let widths_oof = layout_oof.calculate_content_widths();