Skip to content
3 changes: 2 additions & 1 deletion examples/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::time::Instant;
use parley::fontique::Blob;
use parley::{
Alignment, AlignmentOptions, FontContext, FontFamily, FontWeight, GenericFamily, InlineBox,
Layout, LayoutContext, LineHeight, StyleProperty,
Layout, LayoutContext, LineHeight, StyleProperty, VerticalAlign,
};
use peniko::Color;

Expand Down Expand Up @@ -209,6 +209,7 @@ pub fn build_rich_layout(
index: 40,
width: 50.0,
height: 50.0,
vertical_align: VerticalAlign::Baseline,
});

let mut layout = builder.build(&config.text);
Expand Down
6 changes: 5 additions & 1 deletion examples/swash_render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ 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, LayoutContext, LineHeight};
use parley::{AlignmentOptions, FontContext, InlineBox, LayoutContext, LineHeight, VerticalAlign};
use std::fs::File;
use swash::FontRef;
use swash::scale::image::Content;
Expand Down Expand Up @@ -97,6 +97,7 @@ fn main() {
index: 0,
width: 50.0,
height: 50.0,
vertical_align: VerticalAlign::Baseline,
});

builder.push_text(&text[40..50]);
Expand All @@ -106,6 +107,7 @@ fn main() {
index: 50,
width: 50.0,
height: 30.0,
vertical_align: VerticalAlign::Baseline,
});

builder.push_text(&text[50..141]);
Expand Down Expand Up @@ -155,12 +157,14 @@ fn main() {
index: 40,
width: 50.0,
height: 50.0,
vertical_align: VerticalAlign::Baseline,
});
builder.push_inline_box(InlineBox {
id: 1,
index: 50,
width: 50.0,
height: 30.0,
vertical_align: VerticalAlign::Baseline,
});

// Build the builder into a Layout
Expand Down
3 changes: 2 additions & 1 deletion examples/tiny_skia_render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

use parley::{
Alignment, AlignmentOptions, FontContext, FontWeight, GenericFamily, GlyphRun, InlineBox,
Layout, LayoutContext, LineHeight, PositionedLayoutItem, StyleProperty,
Layout, LayoutContext, LineHeight, PositionedLayoutItem, StyleProperty, VerticalAlign,
};
use skrifa::{
GlyphId, MetadataProvider, OutlineGlyph,
Expand Down Expand Up @@ -91,6 +91,7 @@ fn main() {
index: 40,
width: 50.0,
height: 50.0,
vertical_align: VerticalAlign::Baseline,
});

// Build the builder into a Layout
Expand Down
5 changes: 5 additions & 0 deletions parley/src/inline_box.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright 2024 the Parley Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT

use crate::VerticalAlign;

/// A box to be laid out inline with text
#[derive(PartialEq, Debug, Clone)]
pub struct InlineBox {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strictly speaking, this is orthogonal to this PR (but it may be useful to implement it here anyway, and it could also land before this PR), but:

InlineBox ought to gain a first_baseline: Option field. If that is Some then the inline box ought to be aligned using that as it's baseline. If it is None then it would fallback to aligning using the full height of the box (aligning to the bottom of the box), which is the current behaviour.

In Blitz, we'd source this value from Taffy and set it here before running text layout.

Expand All @@ -14,4 +16,7 @@ pub struct InlineBox {
pub width: f32,
/// The height of the box in pixels
pub height: f32,
/// Vertical alignment of the box relative to the line baseline.
/// Defaults to `VerticalAlign::Baseline`.
pub vertical_align: VerticalAlign,
}
3 changes: 3 additions & 0 deletions parley/src/layout/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ pub(crate) struct LineItemData {
/// Advance (size in direction of text flow) for the run.
pub(crate) advance: f32,

/// Offset from the line baseline for vertical alignment (positive = down).
pub(crate) baseline_offset: f32,

// Fields that only apply to text runs (Ignored for boxes)
// TODO: factor this out?
/// True if the run is composed entirely of whitespace.
Expand Down
27 changes: 25 additions & 2 deletions parley/src/layout/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,23 @@ impl<'a, B: Brush> Iterator for GlyphRunIter<'a, B> {
LineItem::InlineBox(inline_box) => {
let x = self.offset + self.line.data.metrics.offset;

// Get baseline_offset from the corresponding LineItemData
let abs_item_idx = self.line.data.item_range.start + self.item_index;
let baseline_offset = self
.line
.layout
.data
.line_items
.get(abs_item_idx)
.map(|li| li.baseline_offset)
.unwrap_or(0.0);
Comment thread
nicoburns marked this conversation as resolved.
Outdated

self.item_index += 1;
self.glyph_start = 0;
self.offset += inline_box.width;
return Some(PositionedLayoutItem::InlineBox(PositionedInlineBox {
x,
y: self.line.data.metrics.baseline - inline_box.height,
y: self.line.data.metrics.baseline + baseline_offset - inline_box.height,
width: inline_box.width,
height: inline_box.height,
id: inline_box.id,
Expand All @@ -279,6 +290,18 @@ impl<'a, B: Brush> Iterator for GlyphRunIter<'a, B> {
advance += glyph.advance;
}
let style = run.layout.data.styles.get(style_index)?;

// Get baseline_offset from the corresponding LineItemData
let abs_item_idx = self.line.data.item_range.start + self.item_index;
let baseline_offset = self
.line
.layout
.data
.line_items
.get(abs_item_idx)
.map(|li| li.baseline_offset)
.unwrap_or(0.0);

let glyph_start = self.glyph_start;
self.glyph_start += glyph_count;
let offset = self.offset;
Expand All @@ -289,7 +312,7 @@ impl<'a, B: Brush> Iterator for GlyphRunIter<'a, B> {
glyph_start,
glyph_count,
offset: offset + self.line.data.metrics.offset,
baseline: self.line.data.metrics.baseline,
baseline: self.line.data.metrics.baseline + baseline_offset,
advance,
}));
}
Expand Down
Loading
Loading