Update shaping logic

This commit is contained in:
Laurenz Stampfl 2025-03-11 23:01:56 +01:00
parent 6af9eb9bbd
commit 644996302a
3 changed files with 41 additions and 3 deletions

1
Cargo.lock generated
View File

@ -1345,7 +1345,6 @@ dependencies = [
[[package]]
name = "krilla"
version = "0.3.0"
source = "git+https://github.com/LaurenzV/krilla?rev=399dc59#399dc596fdb27fde3ca1eef27b74625affed199a"
dependencies = [
"base64",
"bumpalo",

View File

@ -70,7 +70,7 @@ if_chain = "1"
image = { version = "0.25.5", default-features = false, features = ["png", "jpeg", "gif"] }
indexmap = { version = "2", features = ["serde"] }
kamadak-exif = "0.6"
krilla = { git = "https://github.com/LaurenzV/krilla", rev = "399dc59", features = ["svg", "raster-images", "comemo", "rayon"] }
krilla = { path = "../krilla/crates/krilla", features = ["svg", "raster-images", "comemo", "rayon"] }
kurbo = "0.11"
libfuzzer-sys = "0.4"
lipsum = "0.9"

View File

@ -826,8 +826,47 @@ fn shape_segment<'a>(
if info.glyph_id != 0 && is_covered(cluster) {
// Determine the text range of the glyph.
let start = base + cluster;
// Assume we have the following sequence of (glyph_id, cluster):
// [(120, 0), (80, 0), (3, 3), (755, 4), (69, 4), (424, 13), (63, 13), (193, 25), (80, 25), (3, 31)
// We then want the sequence of (glyph_id, text_range) to look as follows:
// [(120, 0..3), (80, 0..3), (3, 3..4), (755, 4..13), (69, 4..13), (424, 13..25),
// (63, 13..25), (193, 25..31), (80, 25..31), (3, 31..x)]
// i.e. each glyph in the same cluster should be assigned the full text range. This
// is necessary because only this way can krilla properly assign `ActualText` attributes
// in complex shaping scenarios.
let offset = if ltr {
let mut e = i.checked_add(1);
loop {
if let Some(index) = e {
if let Some(end_info) = infos.get(index) {
if end_info.cluster == info.cluster {
e = index.checked_add(1);
continue;
}
}
}
break;
}
e
} else {
let mut e = i.checked_sub(1);
while let Some(index) = e {
if let Some(end_info) = infos.get(index) {
if end_info.cluster == info.cluster {
e = index.checked_sub(1);
} else {
break;
}
}
}
e
};
let end = base
+ if ltr { i.checked_add(1) } else { i.checked_sub(1) }
+ offset
.and_then(|last| infos.get(last))
.map_or(text.len(), |info| info.cluster as usize);