Repository: typst/typst
File: crates/typst-layout/src/inline/line.rs (Rust)

Code before:
        if let Some(glyph) = text.glyphs.last() {
            if text.dir.is_positive()
                && TextElem::overhang_in(text.styles)
                && (line.items.len() > 1 || text.glyphs.len() > 1)
            {
                let amount = overhang(glyph.c) * glyph.x_advance.at(text.size);
                remaining += amount;
            }
        }
    }

    // Determine how much additional space is needed. The justification_ratio is
    // for the first step justification, extra_justification is for the last
    // step. For more info on multi-step justification, see Procedures for
    // Inter- Character Space Expansion in W3C document Chinese Layout
    // Requirements.
    let fr = line.fr();
    let mut justification_ratio = 0.0;
    let mut extra_justification = Abs::zero();

    let shrinkability = line.shrinkability();
    let stretchability = line.stretchability();
    if remaining < Abs::zero() && shrinkability > Abs::zero() {
        // Attempt to reduce the length of the line, using shrinkability.
        justification_ratio = (remaining / shrinkability).max(-1.0);

        remaining = (remaining + shrinkability).min(Abs::zero());
    } else if line.justify && fr.is_zero() {
        // Attempt to increase the length of the line, using stretchability.
        if stretchability > Abs::zero() {
            justification_ratio = (remaining / stretchability).min(1.0);
            remaining = (remaining - stretchability).max(Abs::zero());
        }

        let justifiables = line.justifiables();

        if justifiables > 0 && remaining > Abs::zero() {
            // Underfull line, distribute the extra space.
            extra_justification = remaining / justifiables as f64;
            remaining = Abs::zero();
        }
    }

    let mut top = Abs::zero();
    let mut bottom = Abs::zero();

    // Build the frames and determine the height and baseline.
    let mut frames = vec![];
    for item in line.items.iter() {
        let mut push = |offset: &mut Abs, frame: Frame| {
            let width = frame.width();

Review comment (suggestion):
It's probably best to leave a file untouched if there are no meaningful changes. From looking at the commit history this was because of previous changes being reverted.

Code after:
    world: &Tracked<'a, dyn World + 'a>,
    frame: &mut Frame,
    styles: StyleChain,
) {
    let mut baseline = styles.resolve(TextElem::baseline);
    let mut compensation = Abs::zero();
    if let Some(scripts) = styles.get_ref(TextElem::shift_settings) {
        let font_metrics = styles
            .get_ref(TextElem::font)
            .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.
#[allow(clippy::too_many_arguments)]
pub fn commit(
    engine: &mut Engine,
    p: &Preparation,
    line: &Line,
    width: Abs,
    full: Abs,
    locator: &mut SplitLocator<'_>,
) -> SourceResult<Frame> {
    let mut remaining = width - line.width - p.config.hanging_indent;
    let mut offset = Abs::zero();

    // We always build the line from left to right. In an LTR paragraph, we must
    // thus add the hanging indent to the offset. In an RTL paragraph, the
    // hanging indent arises naturally due to the line width.
    if p.config.dir == Dir::LTR {
        offset += p.config.hanging_indent;
    }

    // Handle hanging punctuation to the left.
    if let Some(text) = line.items.leading_text()
        && let Some(glyph) = text.glyphs.first()
        && !text.dir.is_positive()
        && text.styles.get(TextElem::overhang)
        && (line.items.len() > 1 || text.glyphs.len() > 1)