Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions harfrust/src/ot/shaper/use_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ fn reorder_syllable_use(start: usize, end: usize, buffer: &mut Buffer) {
& (rb_flag(SyllableType::ViramaTerminatedCluster as u32)
| rb_flag(SyllableType::SakotTerminatedCluster as u32)
| rb_flag(SyllableType::StandardCluster as u32)
| rb_flag(SyllableType::SymbolCluster as u32)
| rb_flag(SyllableType::BrokenCluster as u32)
| 0))
== 0
Expand Down Expand Up @@ -566,3 +567,36 @@ fn setup_masks(plan: &ShapePlan, _: &ShaperFont<'_, '_>, buffer: &mut Buffer) {
info.set_use_category(use_table::use_get_category(info.glyph_id as usize));
}
}

#[cfg(test)]
mod tests {
use super::super::use_machine::{find_syllables, SyllableType};
use super::*;

#[test]
fn symbol_clusters_reorder_prebase_marks() {
for base in [category::O, category::GB, category::SB] {
for mark in [category::VPre, category::VMPre] {
let mut buffer = Buffer::new();
buffer.push(0x111CD, 0);
buffer.push(0x111CE, 4);
buffer.info[0].set_use_category(base);
buffer.info[1].set_use_category(mark);
find_syllables(&mut buffer);
assert_eq!(
buffer.info[0].syllable() & 0x0F,
if base == category::GB {
SyllableType::StandardCluster
} else {
SyllableType::SymbolCluster
} as u8
);
reorder_syllable_use(0, 2, &mut buffer);
assert_eq!(buffer.info[0].glyph_id, 0x111CE);
assert_eq!(buffer.info[1].glyph_id, 0x111CD);
assert_eq!(buffer.info[0].cluster, 0);
assert_eq!(buffer.info[1].cluster, 0);
}
}
}
}
46 changes: 45 additions & 1 deletion harfrust/src/shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,9 +563,11 @@ fn form_clusters(buffer: &mut Buffer) {

fn ensure_native_direction(buffer: &mut Buffer) {
let dir = buffer.direction;
// Like HarfBuzz, use LTR when no script was detected; only explicitly
// directionless scripts should suppress native-direction conversion.
let mut hor = buffer
.script
.and_then(Direction::from_script)
.map_or(Some(Direction::LeftToRight), Direction::from_script)
.unwrap_or_default();

// Numeric runs in natively-RTL scripts are actually native-LTR, so we reset
Expand Down Expand Up @@ -812,3 +814,45 @@ fn propagate_flags(buffer: &mut Buffer) {
}
});
}

#[cfg(test)]
mod native_direction_tests {
use super::*;

#[test]
fn unspecified_script_keeps_emoji_graphemes_in_native_order() {
for script in [None, Some(Script::COMMON), Some(Script::UNKNOWN)] {
let mut buffer = Buffer::new();
buffer.push(0x1F44D, 0);
buffer.push(0x1F3FD, 4);
buffer.push(0x41, 8);
buffer.info[1].set_continuation(&mut buffer.scratch_flags);
buffer.script = script;
buffer.direction = Direction::RightToLeft;
ensure_native_direction(&mut buffer);
assert_eq!(buffer.direction, Direction::LeftToRight);
assert_eq!(buffer.info[0].glyph_id, 0x41);
assert_eq!(buffer.info[1].glyph_id, 0x1F44D);
assert_eq!(buffer.info[2].glyph_id, 0x1F3FD);
}
}

#[test]
fn explicitly_directionless_scripts_keep_requested_direction() {
for script in [
Script::OLD_HUNGARIAN,
Script::OLD_ITALIC,
Script::RUNIC,
Script::TIFINAGH,
] {
let mut buffer = Buffer::new();
buffer.push_str("ab");
buffer.script = Some(script);
buffer.direction = Direction::RightToLeft;
ensure_native_direction(&mut buffer);
assert_eq!(buffer.direction, Direction::RightToLeft);
assert_eq!(buffer.info[0].glyph_id, 0x61);
assert_eq!(buffer.info[1].glyph_id, 0x62);
}
}
}
16 changes: 13 additions & 3 deletions harfrust/src/unicode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,9 @@ pub(crate) mod modified_combining_class {
// Modify Telugu length marks (ccc=84, ccc=91).
// These are the only matras in the main Indic scripts range that have
// a non-zero ccc. That makes them reorder with the Halant that is
// ccc=9. Just zero them, we don't need them in our Indic shaper.
pub const CCC84: u8 = 0; // length mark
pub const CCC91: u8 = 0; // ai length mark
// ccc=9. Assign 4 and 5, which are otherwise unassigned.
pub const CCC84: u8 = 4; // length mark
pub const CCC91: u8 = 5; // ai length mark

// Thai
//
Expand Down Expand Up @@ -931,6 +931,16 @@ mod builtin {

#[cfg(test)]
mod tests {
#[test]
fn telugu_length_marks_reorder_before_virama() {
use super::CharExt;
assert_eq!(0x0C55u32.modified_combining_class(), 4);
assert_eq!(0x0C56u32.modified_combining_class(), 5);
assert_eq!(0x0C4Du32.modified_combining_class(), 9);
assert_eq!(super::combining_class(0x0C55), 84);
assert_eq!(super::combining_class(0x0C56), 91);
}

#[cfg(not(feature = "icu"))]
#[test]
fn unicode_18_scripts() {
Expand Down
Loading