/// <summary> /// Reorders a series of runs from logical to visual order, returning the left most run. /// <see href="https://github.com/fribidi/linear-reorder/blob/f2f872257d4d8b8e137fcf831f254d6d4db79d3c/linear-reorder.c"/> /// </summary> /// <param name="run">The ordered bidi run.</param> /// <returns>The <see cref="OrderedBidiRun"/>.</returns> private static OrderedBidiRun LinearReOrder(OrderedBidiRun?run) { BidiRange?range = null; while (run != null) { var next = run.Next; while (range != null && range.Level > run.Level && range.Previous != null && range.Previous.Level >= run.Level) { range = BidiRange.MergeWithPrevious(range); } if (range != null && range.Level >= run.Level) { // Attach run to the range. if ((run.Level & 1) != 0) { // Odd, range goes to the right of run. run.Next = range.Left; range.Left = run; } else { // Even, range goes to the left of run. range.Right !.Next = run; range.Right = run; } range.Level = run.Level; } else { var r = new BidiRange(); r.Left = r.Right = run; r.Level = run.Level; r.Previous = range; range = r; } run = next; } while (range?.Previous != null) { range = BidiRange.MergeWithPrevious(range); } // Terminate. range !.Right !.Next = null; return(range.Left !); }
public static BidiRange MergeWithPrevious(BidiRange range) { var previous = range.Previous; BidiRange left; BidiRange right; if ((previous !.Level & 1) != 0) { // Odd, previous goes to the right of range. left = range; right = previous; }