From 3a08d63b4b9d43b0fd250104ac98df5f53f579b8 Mon Sep 17 00:00:00 2001 From: Malo <57839069+MDLC01@users.noreply.github.com> Date: Sat, 19 Apr 2025 17:57:47 +0200 Subject: [PATCH] Apply baseline shift and italic compensation to non-textual elements --- crates/typst-layout/src/inline/collect.rs | 4 +-- crates/typst-layout/src/inline/line.rs | 31 +++++++++++++++++++---- crates/typst-layout/src/inline/mod.rs | 2 +- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/crates/typst-layout/src/inline/collect.rs b/crates/typst-layout/src/inline/collect.rs index 5a1b7b4fc..829f64b66 100644 --- a/crates/typst-layout/src/inline/collect.rs +++ b/crates/typst-layout/src/inline/collect.rs @@ -206,7 +206,7 @@ pub fn collect<'a>( } InlineItem::Frame(mut frame) => { frame.modify(&FrameModifiers::get_in(styles)); - apply_baseline_shift(&mut frame, styles); + apply_shift(&engine.world, &mut frame, styles); collector.push_item(Item::Frame(frame)); } } @@ -221,7 +221,7 @@ pub fn collect<'a>( let mut frame = layout_and_modify(styles, |styles| { layout_box(elem, engine, loc, styles, region) })?; - apply_baseline_shift(&mut frame, styles); + apply_shift(&engine.world, &mut frame, styles); collector.push_item(Item::Frame(frame)); } } else if let Some(elem) = child.to_packed::() { diff --git a/crates/typst-layout/src/inline/line.rs b/crates/typst-layout/src/inline/line.rs index 659d33f4a..3782f7034 100644 --- a/crates/typst-layout/src/inline/line.rs +++ b/crates/typst-layout/src/inline/line.rs @@ -5,7 +5,7 @@ use typst_library::engine::Engine; use typst_library::introspection::{SplitLocator, Tag}; use typst_library::layout::{Abs, Dir, Em, Fr, Frame, FrameItem, Point}; use typst_library::model::ParLineMarker; -use typst_library::text::{Lang, TextElem}; +use typst_library::text::{variant, Lang, TextElem}; use typst_utils::Numeric; use super::*; @@ -412,9 +412,30 @@ fn should_repeat_hyphen(pred_line: &Line, text: &str) -> bool { } } -/// Apply the current baseline shift to a frame. -pub fn apply_baseline_shift(frame: &mut Frame, styles: StyleChain) { - frame.translate(Point::with_y(TextElem::baseline_in(styles))); +/// Apply the current baseline shift and italic compensation to a frame. +pub fn apply_shift<'a>( + world: &Tracked<'a, dyn World + 'a>, + frame: &mut Frame, + styles: StyleChain, +) { + let mut baseline = TextElem::baseline_in(styles); + let mut compensation = Abs::zero(); + if let Some(scripts) = TextElem::subperscript_in(styles) { + let font_metrics = TextElem::font_in(styles) + .into_iter() + .find_map(|family| { + world + .book() + .select(family.as_str(), variant(styles)) + .and_then(|id| world.font(id)) + }) + .map_or(scripts.kind.default_metrics(), |f| { + scripts.kind.read_metrics(f.metrics()) + }); + baseline -= scripts.shift.unwrap_or(font_metrics.vertical_offset).resolve(styles); + compensation += font_metrics.horizontal_offset.resolve(styles); + } + frame.translate(Point::new(compensation, baseline)); } /// Commit to a line and build its frame. @@ -519,7 +540,7 @@ pub fn commit( let mut frame = layout_and_modify(*styles, |styles| { layout_box(elem, engine, loc.relayout(), styles, region) })?; - apply_baseline_shift(&mut frame, *styles); + apply_shift(&engine.world, &mut frame, *styles); push(&mut offset, frame); } else { offset += amount; diff --git a/crates/typst-layout/src/inline/mod.rs b/crates/typst-layout/src/inline/mod.rs index 5ef820d07..f5033b170 100644 --- a/crates/typst-layout/src/inline/mod.rs +++ b/crates/typst-layout/src/inline/mod.rs @@ -28,7 +28,7 @@ use typst_utils::{Numeric, SliceExt}; use self::collect::{collect, Item, Segment, SpanMapper}; use self::deco::decorate; use self::finalize::finalize; -use self::line::{apply_baseline_shift, commit, line, Line}; +use self::line::{apply_shift, commit, line, Line}; use self::linebreak::{linebreak, Breakpoint}; use self::prepare::{prepare, Preparation}; use self::shaping::{