diff --git a/crates/typst-layout/src/inline/shaping.rs b/crates/typst-layout/src/inline/shaping.rs index 842ddcc77..3c095bbf7 100644 --- a/crates/typst-layout/src/inline/shaping.rs +++ b/crates/typst-layout/src/inline/shaping.rs @@ -804,8 +804,11 @@ fn shape_segment<'a>( // text extraction. buffer.set_flags(BufferFlags::REMOVE_DEFAULT_IGNORABLES); - let (script_shift, script_compensation, scale) = - compute_synthesized_shift(ctx, text, &font); + let (script_shift, script_compensation, scale) = ctx + .shift_settings + .map_or((Em::zero(), Em::zero(), Em::one()), |settings| { + compute_synthesized_shift(ctx, text, &font, settings) + }); // Prepare the shape plan. This plan depends on direction, script, language, // and features, but is independent from the text and can thus be memoized. @@ -964,46 +967,46 @@ fn compute_synthesized_shift( ctx: &mut ShapingContext, text: &str, font: &Font, + settings: ShiftSettings, ) -> (Em, Em, Em) { - match ctx.shift_settings { - None => (Em::zero(), Em::zero(), Em::one()), - Some(settings) => settings - .typographic - .then(|| { - // If typographic scripts are enabled (i.e., we want to use the - // OpenType feature instead of synthesizing if possible), we add - // "subs"/"sups" to the feature list if supported by the font. - // In case of a problem, we just early exit - let gsub = font.rusty().tables().gsub?; - let subtable_index = - gsub.features.find(settings.kind.feature())?.lookup_indices.get(0)?; - let coverage = gsub - .lookups - .get(subtable_index)? - .subtables - .get::(0)? - .coverage(); - text.chars() - .all(|c| { - font.rusty().glyph_index(c).is_some_and(|i| coverage.contains(i)) - }) - .then(|| { - ctx.features.push(Feature::new(settings.kind.feature(), 1, ..)); - (Em::zero(), Em::zero(), Em::one()) - }) - }) - // Reunite the cases where `typographic` is `false` or where using - // the OpenType feature would not work. - .flatten() - .unwrap_or_else(|| { - let script_metrics = settings.kind.read_metrics(font.metrics()); - ( - settings.shift.unwrap_or(script_metrics.vertical_offset), - script_metrics.horizontal_offset, - settings.size.unwrap_or(script_metrics.height), - ) - }), - } + settings + .typographic + .then(|| { + // If typographic scripts are enabled (i.e., we want to use the + // OpenType feature instead of synthesizing if possible), we add + // "subs"/"sups" to the feature list if supported by the font. + // In case of a problem, we just early exit + let gsub = font.rusty().tables().gsub?; + let subtable_index = + gsub.features.find(settings.kind.feature())?.lookup_indices.get(0)?; + let coverage = gsub + .lookups + .get(subtable_index)? + .subtables + .get::(0)? + .coverage(); + text.chars() + .all(|c| { + font.rusty().glyph_index(c).is_some_and(|i| coverage.contains(i)) + }) + .then(|| { + ctx.features.push(Feature::new(settings.kind.feature(), 1, ..)); + // If we can use the OpenType feature, we can keep the text + // as is. + (Em::zero(), Em::zero(), Em::one()) + }) + }) + // Reunite the cases where `typographic` is `false` or where using the + // OpenType feature would not work. + .flatten() + .unwrap_or_else(|| { + let script_metrics = settings.kind.read_metrics(font.metrics()); + ( + settings.shift.unwrap_or(script_metrics.vertical_offset), + script_metrics.horizontal_offset, + settings.size.unwrap_or(script_metrics.height), + ) + }) } /// Create a shape plan.