mirror of
https://github.com/typst/typst
synced 2025-08-21 18:24:14 +08:00
Extract logic into separate function
This commit is contained in:
parent
328a119703
commit
71b637396f
@ -736,7 +736,7 @@ fn shape_segment<'a>(
|
|||||||
base: usize,
|
base: usize,
|
||||||
text: &str,
|
text: &str,
|
||||||
mut families: impl Iterator<Item = &'a FontFamily> + Clone,
|
mut families: impl Iterator<Item = &'a FontFamily> + Clone,
|
||||||
script_settings: Option<ShiftSettings>,
|
shift_settings: Option<ShiftSettings>,
|
||||||
) {
|
) {
|
||||||
// Don't try shaping newlines, tabs, or default ignorables.
|
// Don't try shaping newlines, tabs, or default ignorables.
|
||||||
if text
|
if text
|
||||||
@ -803,51 +803,8 @@ fn shape_segment<'a>(
|
|||||||
// text extraction.
|
// text extraction.
|
||||||
buffer.set_flags(BufferFlags::REMOVE_DEFAULT_IGNORABLES);
|
buffer.set_flags(BufferFlags::REMOVE_DEFAULT_IGNORABLES);
|
||||||
|
|
||||||
// Those values determine how the rendered text should be transformed to
|
let (script_shift, script_compensation, scale) =
|
||||||
// display sub-/super-scripts properly. If the text is not scripted, or if
|
compute_synthesized_shift(ctx, text, &font, shift_settings);
|
||||||
// the OpenType feature can be used, the rendered text should not be
|
|
||||||
// transformed in any way, and so those values are neutral (`(0, 0, 1)`). If
|
|
||||||
// scripts should be synthesized, those values determine how to transform
|
|
||||||
// the rendered text to display scripts as expected.
|
|
||||||
let (script_shift, script_compensation, scale) = match script_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::<SubstitutionSubtable>(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),
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Prepare the shape plan. This plan depends on direction, script, language,
|
// Prepare the shape plan. This plan depends on direction, script, language,
|
||||||
// and features, but is independent from the text and can thus be memoized.
|
// and features, but is independent from the text and can thus be memoized.
|
||||||
@ -989,7 +946,7 @@ fn shape_segment<'a>(
|
|||||||
base + start,
|
base + start,
|
||||||
&text[start..end],
|
&text[start..end],
|
||||||
families.clone(),
|
families.clone(),
|
||||||
script_settings,
|
shift_settings,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -999,6 +956,62 @@ fn shape_segment<'a>(
|
|||||||
ctx.used.pop();
|
ctx.used.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a `(script_shift, script_compensation, scale)` triplet describing
|
||||||
|
/// how to synthesize scripts.
|
||||||
|
///
|
||||||
|
/// Those values determine how the rendered text should be transformed to
|
||||||
|
/// display sub-/super-scripts. If the text is not scripted, or if the OpenType
|
||||||
|
/// feature can be used, the rendered text should not be transformed in any way,
|
||||||
|
/// and so those values are neutral (`(0, 0, 1)`). If scripts should be
|
||||||
|
/// synthesized, those values determine how to transform the rendered text to
|
||||||
|
/// display scripts as expected.
|
||||||
|
fn compute_synthesized_shift(
|
||||||
|
ctx: &mut ShapingContext,
|
||||||
|
text: &str,
|
||||||
|
font: &Font,
|
||||||
|
settings: Option<ShiftSettings>,
|
||||||
|
) -> (Em, Em, Em) {
|
||||||
|
match 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::<SubstitutionSubtable>(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),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a shape plan.
|
/// Create a shape plan.
|
||||||
#[comemo::memoize]
|
#[comemo::memoize]
|
||||||
fn create_shape_plan(
|
fn create_shape_plan(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user