/// <summary> /// Perform the Unicode Bidi algorithm. /// </summary> /// <param name="text">The text that the Bidi algorithm will be performed on</param> /// <param name="paraLevel">Specifies the default level for the text; it is typically 0 (LTR) or 1 (RTL)</param> /// <param name="embeddingLevels">May be used to preset the embedding and override levels, ignoring characters like LRE and PDF in the text; /// a level overrides the directional property of its corresponding (same index) character if the level has the UBIDI_LEVEL_OVERRIDE bit set</param> /// <remarks> /// This function takes a piece of plain text containing one or more paragraphs, with or without externally specified embedding levels from styled /// text and computes the left-right-directionality of each character. /// /// If the entire text is all of the same directionality, then the function may not perform all the steps described by the algorithm, i.e., /// some levels may not be the same as if all steps were performed.This is not relevant for unidirectional text. /// /// For example, in pure LTR text with numbers the numbers would get a resolved level of 2 higher than the surrounding text according to the /// algorithm.This implementation may set all resolved levels to the same value in such a case. /// /// The text can be composed of multiple paragraphs. Occurrence of a block separator in the text terminates a paragraph, and whatever comes /// next starts a new paragraph.The exception to this rule is when a Carriage Return (CR) is followed by a Line Feed (LF). Both CR and LF are /// block separators, but in that case, the pair of characters is considered as terminating the preceding paragraph, and a new paragraph will /// be started by a character coming after the LF. /// </remarks> public void SetPara(string text, byte paraLevel, byte[] embeddingLevels) { if (_para != IntPtr.Zero) { Marshal.FreeHGlobal(_para); _para = IntPtr.Zero; } if (text == null) { throw new ArgumentNullException(nameof(text)); } // icu BiDi expects the para pointer to live for the life of the structure, so we have to stash it _para = Marshal.StringToHGlobalUni(text); NativeMethods.ubidi_setPara(_biDi, _para, text.Length, paraLevel, embeddingLevels, out var errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode, "BiDi analysis failed! " + errorCode); }