From 1d0ead7a6216fe27759250cf0216ba378077a51a Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Tue, 4 Aug 2015 16:47:15 -0700 Subject: [PATCH] Move W7 into a separate pass This is the first part of the fix for #8, and fixes servo/servo#6978. --- src/lib.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 10b99d7..d4a4a43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -684,14 +684,13 @@ mod implicit { /// /// http://www.unicode.org/reports/tr9/#Resolving_Weak_Types pub fn resolve_weak(sequence: &IsolatingRunSequence, classes: &mut [BidiClass]) { - // FIXME (#8): This function applies steps W1-W7 in a single pass. This can produce + // FIXME (#8): This function applies steps W1-W6 in a single pass. This can produce // incorrect results in cases where a "later" rule changes the value of `prev_class` seen // by an "earlier" rule. We should either split this into separate passes, or preserve // extra state so each rule can see the correct previous class. let mut prev_class = sequence.sos; let mut last_strong_is_al = false; - let mut last_strong_is_l = false; let mut et_run_indices = Vec::new(); // for W5 // Like sequence.runs.iter().flat_map(Clone::clone), but make indices itself clonable. @@ -713,12 +712,8 @@ mod implicit { classes[i] = AN; } else { // W5. If a run of ETs is adjacent to an EN, change the ETs to EN. - // W7. If the previous strong char was L, change all the ENs to L. - if last_strong_is_l { - classes[i] = L; - } for j in &et_run_indices { - classes[*j] = classes[i]; + classes[*j] = EN; } et_run_indices.clear(); } @@ -751,9 +746,8 @@ mod implicit { prev_class = classes[i]; match prev_class { - L => { last_strong_is_al = false; last_strong_is_l = true; } - R => { last_strong_is_al = false; last_strong_is_l = false; } - AL => { last_strong_is_al = true; last_strong_is_l = false; } + L | R => { last_strong_is_al = false; } + AL => { last_strong_is_al = true; } _ => {} } if prev_class != ET { @@ -764,6 +758,19 @@ mod implicit { et_run_indices.clear(); } } + + // W7. If the previous strong char was L, change EN to L. + let mut last_strong_is_l = sequence.sos == L; + for run in &sequence.runs { + for i in run.clone() { + match classes[i] { + EN if last_strong_is_l => { classes[i] = L; } + L => { last_strong_is_l = true; } + R | AL => { last_strong_is_l = false; } + _ => {} + } + } + } } /// 3.3.5 Resolving Neutral Types @@ -952,6 +959,8 @@ mod test { } assert_eq!(reorder("abc123"), "abc123"); + assert_eq!(reorder("1.-2"), "1.-2"); + assert_eq!(reorder("1-.2"), "1-.2"); assert_eq!(reorder("abc אבג"), "abc גבא"); assert_eq!(reorder("אבג abc"), "abc גבא"); assert_eq!(reorder("abc\u{2067}.-\u{2069}ghi"),