UnicodeBidi Class

Implements the Unicode Bidirectional Algorithm: the order in which text that mixes left-to-right and right-to-left scripts is displayed.

public static class UnicodeBidi

Remarks

The algorithm is the one of Unicode Standard Annex #9 for UnicodeProperties.UnicodeVersion, whatever the version of the runtime. It is applied in two steps, as the annex specifies: UnicodeBidi.ResolveLevels gives an embedding level to each UTF-16 code unit of a paragraph (rules P2 to I2); then, once the paragraph is broken into lines, UnicodeBidi.ResetLineLevels (rule L1) and UnicodeBidi.GetVisualOrder (rule L2) give the display order of each line. A character whose level is odd is displayed right to left.

Rule L3 (combining marks) is the responsibility of the code that shapes the text, and rule L4 (mirroring) is available through UnicodeProperties.TryGetBidiMirroringGlyph.

See also

Methods

NameDescription
GetParagraphLevel(ReadOnlySpan<char>, UnicodeBidiDirection)Gets the embedding level of a paragraph.
GetVisualOrder(ReadOnlySpan<byte>, Span<int>)Computes the display order of the elements of a line from their levels (rule L2).
GetVisualOrder(ReadOnlySpan<char>, ReadOnlySpan<byte>, Span<int>)Computes the display order of the UTF-16 code units of a line from their levels (rule L2).
GetWorkspaceLength(int)Gets the size of the workspace UnicodeBidi.ResolveLevels needs for a paragraph.
MayRequireBidi(ReadOnlySpan<char>)Determines whether a text can have a level other than 0.
ResetLineLevels(ReadOnlySpan<char>, int, Span<byte>)Resets the levels of the trailing white space of a line (rule L1).
ResolveLevels(ReadOnlySpan<char>, UnicodeBidiDirection, Span<byte>)Resolves the embedding level of each UTF-16 code unit of a paragraph.
ResolveLevels(ReadOnlySpan<char>, UnicodeBidiDirection, Span<byte>, Span<int>)Resolves the embedding level of each UTF-16 code unit of a paragraph, using a workspace provided by the caller.

GetParagraphLevel(ReadOnlySpan<char>, UnicodeBidiDirection)

UnicodeBidi.cs

Gets the embedding level of a paragraph.

public static int GetParagraphLevel(ReadOnlySpan<char> paragraph, UnicodeBidiDirection direction = UnicodeBidiDirection.Auto)

Parameters

paragraph ReadOnlySpan<char>
The text of the paragraph.
direction UnicodeBidiDirection
The direction of the paragraph.

Returns

int 0 for a left-to-right paragraph, 1 for a right-to-left one. With UnicodeBidiDirection.Auto, the direction is the one of the first strong character that is not inside an isolate (rules P2 and P3), and left-to-right when there is none.

Exceptions

ArgumentOutOfRangeException
direction is not a defined value.

GetVisualOrder overloads

GetVisualOrder(ReadOnlySpan<byte>, Span<int>)

UnicodeBidi.cs

Computes the display order of the elements of a line from their levels (rule L2).

public static void GetVisualOrder(ReadOnlySpan<byte> levels, Span<int> visualToLogical)
Parameters
levels ReadOnlySpan<byte>
The levels of the elements of the line, in the order of the text. An element is a code unit, a code point, or anything coarser that has one level, such as a run of text.
visualToLogical Span<int>
The buffer that receives, for each display position from left to right, the index of the element displayed there.
Exceptions
ArgumentException
visualToLogical is shorter than levels.
Remarks

The elements are reversed independently of each other. When they are the UTF-16 code units of a text, the two code units of a surrogate pair at an odd level are reversed too: use UnicodeBidi.GetVisualOrder, which keeps them in order.

GetVisualOrder(ReadOnlySpan<char>, ReadOnlySpan<byte>, Span<int>)

UnicodeBidi.cs

Computes the display order of the UTF-16 code units of a line from their levels (rule L2).

public static void GetVisualOrder(ReadOnlySpan<char> line, ReadOnlySpan<byte> levels, Span<int> visualToLogical)
Parameters
line ReadOnlySpan<char>
The text of the line.
levels ReadOnlySpan<byte>
The levels of the code units of line, as given by UnicodeBidi.ResolveLevels and UnicodeBidi.ResetLineLevels.
visualToLogical Span<int>
The buffer that receives, for each display position from left to right, the index of the code unit displayed there.
Exceptions
ArgumentException
levels or visualToLogical is shorter than line.
Remarks

The two code units of a surrogate pair stay in the order of the text, whatever their level: applying the order to a well-formed text gives a well-formed text. A pair has the level of its first code unit.

GetWorkspaceLength(int)

UnicodeBidi.cs

Gets the size of the workspace UnicodeBidi.ResolveLevels needs for a paragraph.

public static int GetWorkspaceLength(int textLength)

Parameters

textLength int
The number of UTF-16 code units of the paragraph.

Returns

int The number of elements of the workspace.

Exceptions

ArgumentOutOfRangeException
textLength is negative.
OverflowException
The size does not fit in an Int32.

MayRequireBidi(ReadOnlySpan<char>)

UnicodeBidi.cs

Determines whether a text can have a level other than 0.

public static bool MayRequireBidi(ReadOnlySpan<char> text)

Parameters

text ReadOnlySpan<char>
The text.

Returns

bool false when every level of the text is 0 for a paragraph direction that is UnicodeBidiDirection.LeftToRight or UnicodeBidiDirection.Auto: the text has no right-to-left character, no Arabic number and no explicit directional formatting character. The display order is then the order of the text.

ResetLineLevels(ReadOnlySpan<char>, int, Span<byte>)

UnicodeBidi.cs

Resets the levels of the trailing white space of a line (rule L1).

public static void ResetLineLevels(ReadOnlySpan<char> line, int paragraphLevel, Span<byte> levels)

Parameters

line ReadOnlySpan<char>
The text of the line.
paragraphLevel int
The embedding level of the paragraph, as returned by UnicodeBidi.ResolveLevels.
levels Span<byte>
The levels of the code units of line, modified in place.

Exceptions

ArgumentException
levels is shorter than line.
ArgumentOutOfRangeException
paragraphLevel is not 0 or 1.

Remarks

The paragraph level is given to the segment and paragraph separators, to the white space and isolate formatting characters before them, and to those at the end of the line: white space at the end of a line always follows the direction of the paragraph. Call it for each line, after the paragraph is broken into lines and before UnicodeBidi.GetVisualOrder.

ResolveLevels overloads

ResolveLevels(ReadOnlySpan<char>, UnicodeBidiDirection, Span<byte>)

UnicodeBidi.cs

Resolves the embedding level of each UTF-16 code unit of a paragraph.

public static int ResolveLevels(ReadOnlySpan<char> paragraph, UnicodeBidiDirection direction, Span<byte> levels)
Parameters
paragraph ReadOnlySpan<char>
The text of one paragraph. A paragraph separator, when there is one, is its last character.
direction UnicodeBidiDirection
The direction of the paragraph.
levels Span<byte>
The buffer that receives one level per code unit of paragraph.
Returns

int The embedding level of the paragraph: 0 or 1.

Exceptions
ArgumentException
levels is shorter than paragraph.
ArgumentOutOfRangeException
direction is not a defined value.
Remarks

The two code units of a surrogate pair have the same level. The characters that the algorithm removes (explicit embedding and override characters, boundary neutrals) have the level of the character before them, so that they stay with it.

This overload rents its workspace from the shared array pool when the paragraph is long.

ResolveLevels(ReadOnlySpan<char>, UnicodeBidiDirection, Span<byte>, Span<int>)

UnicodeBidi.cs

Resolves the embedding level of each UTF-16 code unit of a paragraph, using a workspace provided by the caller.

public static int ResolveLevels(ReadOnlySpan<char> paragraph, UnicodeBidiDirection direction, Span<byte> levels, Span<int> workspace)
Parameters
paragraph ReadOnlySpan<char>
The text of one paragraph. A paragraph separator, when there is one, is its last character.
direction UnicodeBidiDirection
The direction of the paragraph.
levels Span<byte>
The buffer that receives one level per code unit of paragraph.
workspace Span<int>
A buffer of at least UnicodeBidi.GetWorkspaceLength elements. Its content is overwritten.
Returns

int The embedding level of the paragraph: 0 or 1.

Exceptions
ArgumentException
levels is shorter than paragraph, or workspace is too small.
ArgumentOutOfRangeException
direction is not a defined value.
Remarks

See UnicodeBidi.ResolveLevels. This overload does not allocate.

Constants

NameDescription
MaxExplicitDepthThe greatest depth of explicit embeddings, overrides and isolates (max_depth). The greatest level is one more.

MaxExplicitDepth

The greatest depth of explicit embeddings, overrides and isolates (max_depth). The greatest level is one more.

public const int MaxExplicitDepth = 125