Bidi Class
Definition
Important
Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
<h2>Bidi algorithm for ICU</h2>
This is an implementation of the Unicode Bidirectional Algorithm.
[Android.Runtime.Register("android/icu/text/Bidi", ApiSince=29, DoNotGenerateAcw=true)]
public class Bidi : Java.Lang.Object
[<Android.Runtime.Register("android/icu/text/Bidi", ApiSince=29, DoNotGenerateAcw=true)>]
type Bidi = class
inherit Object
- Inheritance
- Attributes
Remarks
<h2>Bidi algorithm for ICU</h2>
This is an implementation of the Unicode Bidirectional Algorithm. The algorithm is defined in the Unicode Standard Annex #9.
Note: Libraries that perform a bidirectional algorithm and reorder strings accordingly are sometimes called "Storage Layout Engines". ICU's Bidi and shaping (ArabicShaping) classes can be used at the core of such "Storage Layout Engines".
<h3>General remarks about the API:</h3>
The "limit" of a sequence of characters is the position just after their last character, i.e., one more than that position.
Some of the API methods provide access to "runs". Such a "run" is defined as a sequence of characters that are at the same embedding level after performing the Bidi algorithm.
<h3>Basic concept: paragraph</h3> A piece of text can be divided into several paragraphs by characters with the Bidi class Block Separator
. For handling of paragraphs, see: <ul> <li>#countParagraphs
<li>#getParaLevel
<li>#getParagraph
<li>#getParagraphByIndex
</ul>
<h3>Basic concept: text direction</h3> The direction of a piece of text may be: <ul> <li>#LTR
<li>#RTL
<li>#MIXED
<li>#NEUTRAL
</ul>
<h3>Basic concept: levels</h3>
Levels in this API represent embedding levels according to the Unicode Bidirectional Algorithm. Their low-order bit (even/odd value) indicates the visual direction.
Levels can be abstract values when used for the paraLevel
and embeddingLevels
arguments of setPara()
; there: <ul> <li>the high-order bit of an embeddingLevels[]
value indicates whether the using application is specifying the level of a character to override whatever the Bidi implementation would resolve it to.</li> <li>paraLevel
can be set to the pseudo-level values LEVEL_DEFAULT_LTR
and LEVEL_DEFAULT_RTL
.</li> </ul>
The related constants are not real, valid level values. DEFAULT_XXX
can be used to specify a default for the paragraph level for when the setPara()
method shall determine it but there is no strongly typed character in the input.
Note that the value for LEVEL_DEFAULT_LTR
is even and the one for LEVEL_DEFAULT_RTL
is odd, just like with normal LTR and RTL level values - these special values are designed that way. Also, the implementation assumes that MAX_EXPLICIT_LEVEL is odd.
Note: The numeric values of the related constants will not change: They are tied to the use of 7-bit byte values (plus the override bit) and of the byte data type in this API.
<b>See Also:</b> <ul> <li>#LEVEL_DEFAULT_LTR
<li>#LEVEL_DEFAULT_RTL
<li>#LEVEL_OVERRIDE
<li>#MAX_EXPLICIT_LEVEL
<li>#setPara
</ul>
<h3>Basic concept: Reordering Mode</h3> Reordering mode values indicate which variant of the Bidi algorithm to use.
<b>See Also:</b> <ul> <li>#setReorderingMode
<li>#REORDER_DEFAULT
<li>#REORDER_NUMBERS_SPECIAL
<li>#REORDER_GROUP_NUMBERS_WITH_R
<li>#REORDER_RUNS_ONLY
<li>#REORDER_INVERSE_NUMBERS_AS_L
<li>#REORDER_INVERSE_LIKE_DIRECT
<li>#REORDER_INVERSE_FOR_NUMBERS_SPECIAL
</ul>
<h3>Basic concept: Reordering Options</h3> Reordering options can be applied during Bidi text transformations.
<b>See Also:</b> <ul> <li>#setReorderingOptions
<li>#OPTION_DEFAULT
<li>#OPTION_INSERT_MARKS
<li>#OPTION_REMOVE_CONTROLS
<li>#OPTION_STREAMING
</ul>
<h4> Sample code for the ICU Bidi API </h4>
<h5>Rendering a paragraph with the ICU Bidi API</h5>
This is (hypothetical) sample code that illustrates how the ICU Bidi API could be used to render a paragraph of text. Rendering code depends highly on the graphics system, therefore this sample code must make a lot of assumptions, which may or may not match any existing graphics system's properties.
The basic assumptions are:
<ul> <li>Rendering is done from left to right on a horizontal line.</li> <li>A run of single-style, unidirectional text can be rendered at once. </li> <li>Such a run of text is passed to the graphics system with characters (code units) in logical order.</li> <li>The line-breaking algorithm is very complicated and Locale-dependent - and therefore its implementation omitted from this sample code.</li> </ul>
package android.icu.dev.test.bidi;
import android.icu.text.Bidi;
import android.icu.text.BidiRun;
public class Sample {
static final int styleNormal = 0;
static final int styleSelected = 1;
static final int styleBold = 2;
static final int styleItalics = 4;
static final int styleSuper=8;
static final int styleSub = 16;
static class StyleRun {
int limit;
int style;
public StyleRun(int limit, int style) {
this.limit = limit;
this.style = style;
}
}
static class Bounds {
int start;
int limit;
public Bounds(int start, int limit) {
this.start = start;
this.limit = limit;
}
}
static int getTextWidth(String text, int start, int limit,
StyleRun[] styleRuns, int styleRunCount) {
// simplistic way to compute the width
return limit - start;
}
// set limit and StyleRun limit for a line
// from text[start] and from styleRuns[styleRunStart]
// using Bidi.getLogicalRun(...)
// returns line width
static int getLineBreak(String text, Bounds line, Bidi para,
StyleRun styleRuns[], Bounds styleRun) {
// dummy return
return 0;
}
// render runs on a line sequentially, always from left to right
// prepare rendering a new line
static void startLine(byte textDirection, int lineWidth) {
System.out.println();
}
// render a run of text and advance to the right by the run width
// the text[start..limit-1] is always in logical order
static void renderRun(String text, int start, int limit,
byte textDirection, int style) {
}
// We could compute a cross-product
// from the style runs with the directional runs
// and then reorder it.
// Instead, here we iterate over each run type
// and render the intersections -
// with shortcuts in simple (and common) cases.
// renderParagraph() is the main function.
// render a directional run with
// (possibly) multiple style runs intersecting with it
static void renderDirectionalRun(String text, int start, int limit,
byte direction, StyleRun styleRuns[],
int styleRunCount) {
int i;
// iterate over style runs
if (direction == Bidi.LTR) {
int styleLimit;
for (i = 0; i < styleRunCount; ++i) {
styleLimit = styleRuns[i].limit;
if (start < styleLimit) {
if (styleLimit > limit) {
styleLimit = limit;
}
renderRun(text, start, styleLimit,
direction, styleRuns[i].style);
if (styleLimit == limit) {
break;
}
start = styleLimit;
}
}
} else {
int styleStart;
for (i = styleRunCount-1; i >= 0; --i) {
if (i > 0) {
styleStart = styleRuns[i-1].limit;
} else {
styleStart = 0;
}
if (limit >= styleStart) {
if (styleStart < start) {
styleStart = start;
}
renderRun(text, styleStart, limit, direction,
styleRuns[i].style);
if (styleStart == start) {
break;
}
limit = styleStart;
}
}
}
}
// the line object represents text[start..limit-1]
static void renderLine(Bidi line, String text, int start, int limit,
StyleRun styleRuns[], int styleRunCount) {
byte direction = line.getDirection();
if (direction != Bidi.MIXED) {
// unidirectional
if (styleRunCount <= 1) {
renderRun(text, start, limit, direction, styleRuns[0].style);
} else {
renderDirectionalRun(text, start, limit, direction,
styleRuns, styleRunCount);
}
} else {
// mixed-directional
int count, i;
BidiRun run;
try {
count = line.countRuns();
} catch (IllegalStateException e) {
e.printStackTrace();
return;
}
if (styleRunCount <= 1) {
int style = styleRuns[0].style;
// iterate over directional runs
for (i = 0; i < count; ++i) {
run = line.getVisualRun(i);
renderRun(text, run.getStart(), run.getLimit(),
run.getDirection(), style);
}
} else {
// iterate over both directional and style runs
for (i = 0; i < count; ++i) {
run = line.getVisualRun(i);
renderDirectionalRun(text, run.getStart(),
run.getLimit(), run.getDirection(),
styleRuns, styleRunCount);
}
}
}
}
static void renderParagraph(String text, byte textDirection,
StyleRun styleRuns[], int styleRunCount,
int lineWidth) {
int length = text.length();
Bidi para = new Bidi();
try {
para.setPara(text,
textDirection != 0 ? Bidi.LEVEL_DEFAULT_RTL
: Bidi.LEVEL_DEFAULT_LTR,
null);
} catch (Exception e) {
e.printStackTrace();
return;
}
byte paraLevel = (byte)(1 & para.getParaLevel());
StyleRun styleRun = new StyleRun(length, styleNormal);
if (styleRuns == null || styleRunCount <= 0) {
styleRuns = new StyleRun[1];
styleRunCount = 1;
styleRuns[0] = styleRun;
}
// assume styleRuns[styleRunCount-1].limit>=length
int width = getTextWidth(text, 0, length, styleRuns, styleRunCount);
if (width <= lineWidth) {
// everything fits onto one line
// prepare rendering a new line from either left or right
startLine(paraLevel, width);
renderLine(para, text, 0, length, styleRuns, styleRunCount);
} else {
// we need to render several lines
Bidi line = new Bidi(length, 0);
int start = 0, limit;
int styleRunStart = 0, styleRunLimit;
for (;;) {
limit = length;
styleRunLimit = styleRunCount;
width = getLineBreak(text, new Bounds(start, limit),
para, styleRuns,
new Bounds(styleRunStart, styleRunLimit));
try {
line = para.setLine(start, limit);
} catch (Exception e) {
e.printStackTrace();
return;
}
// prepare rendering a new line
// from either left or right
startLine(paraLevel, width);
if (styleRunStart > 0) {
int newRunCount = styleRuns.length - styleRunStart;
StyleRun[] newRuns = new StyleRun[newRunCount];
System.arraycopy(styleRuns, styleRunStart, newRuns, 0,
newRunCount);
renderLine(line, text, start, limit, newRuns,
styleRunLimit - styleRunStart);
} else {
renderLine(line, text, start, limit, styleRuns,
styleRunLimit - styleRunStart);
}
if (limit == length) {
break;
}
start = limit;
styleRunStart = styleRunLimit - 1;
if (start >= styleRuns[styleRunStart].limit) {
++styleRunStart;
}
}
}
}
public static void main(String[] args)
{
renderParagraph("Some Latin text...", Bidi.LTR, null, 0, 80);
renderParagraph("Some Hebrew text...", Bidi.RTL, null, 0, 60);
}
}
Java documentation for android.icu.text.Bidi
.
Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.
Constructors
Bidi() |
Allocate a |
Bidi(Char[], Int32, Byte[], Int32, Int32, BidiOptions) |
Create Bidi from the given text, embedding, and direction information. |
Bidi(IAttributedCharacterIterator) |
Create Bidi from the given paragraph of text. |
Bidi(Int32, Int32) |
Allocate a |
Bidi(IntPtr, JniHandleOwnership) | |
Bidi(String, BidiOptions) |
Create Bidi from the given paragraph of text and base direction. |
Fields
DirectionDefaultLeftToRight |
Obsolete.
Constant indicating that the base direction depends on the first strong directional character in the text according to the Unicode Bidirectional Algorithm. |
DirectionDefaultRightToLeft |
Obsolete.
Constant indicating that the base direction depends on the first strong directional character in the text according to the Unicode Bidirectional Algorithm. |
DirectionLeftToRight |
Obsolete.
Constant indicating base direction is left-to-right. |
DirectionRightToLeft |
Obsolete.
Constant indicating base direction is right-to-left. |
DoMirroring |
option bit for writeReordered(): replace characters with the "mirrored" property in RTL runs by their mirror-image mappings |
InsertLrmForNumeric |
option bit for writeReordered(): surround the run with LRMs if necessary; this is part of the approximate "inverse Bidi" algorithm |
KeepBaseCombining |
option bit for writeReordered(): keep combining characters after their base characters in RTL runs |
LevelDefaultLtr |
Paragraph level setting |
LevelDefaultRtl |
Paragraph level setting |
LevelOverride |
Bit flag for level input. |
Ltr |
Left-to-right text. |
MapNowhere |
Obsolete.
Special value which can be returned by the mapping methods when a logical index has no corresponding visual index or vice-versa. |
MaxExplicitLevel |
Maximum explicit embedding level. |
Mixed |
Mixed-directional text. |
Neutral |
No strongly directional text. |
OptionDefault |
Obsolete.
Option value for |
OptionInsertMarks |
Obsolete.
Option bit for |
OptionRemoveControls |
Obsolete.
Option bit for |
OptionStreaming |
Obsolete.
Option bit for |
OutputReverse |
option bit for writeReordered(): write the output in reverse order |
RemoveBidiControls |
option bit for writeReordered(): remove Bidi control characters (this does not affect INSERT_LRM_FOR_NUMERIC) |
ReorderDefault |
Reordering mode: Regular Logical to Visual Bidi algorithm according to Unicode. |
ReorderGroupNumbersWithR |
Reordering mode: Logical to Visual algorithm grouping numbers with adjacent R characters (reversible algorithm). |
ReorderInverseForNumbersSpecial |
Reordering mode: Inverse Bidi (Visual to Logical) algorithm for the
|
ReorderInverseLikeDirect |
Reordering mode: Visual to Logical algorithm equivalent to the regular Logical to Visual algorithm. |
ReorderInverseNumbersAsL |
Reordering mode: Visual to Logical algorithm which handles numbers
like L (same algorithm as selected by |
ReorderNumbersSpecial |
Reordering mode: Logical to Visual algorithm which handles numbers in a way which mimicks the behavior of Windows XP. |
ReorderRunsOnly |
Reordering mode: Reorder runs only to transform a Logical LTR string to the logical RTL string with the same display, or vice-versa. |
Rtl |
Right-to-left text. |
Properties
BaseLevel |
Return the base level (0 if left-to-right, 1 if right-to-left). |
Class |
Returns the runtime class of this |
CustomClassifier |
Gets the current custom class classifier used for Bidi class determination. -or- Set a custom Bidi classifier used by the UBA implementation for Bidi class determination. |
Direction |
Get the directionality of the text. |
Handle |
The handle to the underlying Android instance. (Inherited from Object) |
Inverse |
Is this |
IsLeftToRight |
Return true if the line is all left-to-right text and the base direction is left-to-right. |
IsMixed |
Return true if the line is not left-to-right or right-to-left. |
IsOrderParagraphsLTR |
Is this |
IsRightToLeft |
Return true if the line is all right-to-left text, and the base direction is right-to-left |
JniIdentityHashCode | (Inherited from Object) |
JniPeerMembers | |
Length |
Get the length of the text. |
ParaLevel |
Get the paragraph level of the text. |
PeerReference | (Inherited from Object) |
ProcessedLength |
Get the length of the source text processed by the last call to
|
ReorderingMode |
What is the requested reordering mode for a given Bidi object? -or- Modify the operation of the Bidi algorithm such that it implements some variant to the basic Bidi algorithm or approximates an "inverse Bidi" algorithm, depending on different values of the "reordering mode". |
ReorderingOptions |
What are the reordering options applied to a given Bidi object? -or- Specify which of the reordering options should be applied during Bidi transformations. |
ResultLength |
Get the length of the reordered text resulting from the last call to
|
RunCount |
Return the number of level runs. |
TextAsString |
Get the text. |
ThresholdClass | |
ThresholdType |
Methods
BaseIsLeftToRight() |
Return true if the base direction is left-to-right |
Clone() |
Creates and returns a copy of this object. (Inherited from Object) |
CountParagraphs() |
Get the number of paragraphs. |
CountRuns() |
Get the number of runs. |
CreateLineBidi(Int32, Int32) |
Create a Bidi object representing the bidi information on a line of text within the paragraph represented by the current Bidi. |
Dispose() | (Inherited from Object) |
Dispose(Boolean) | (Inherited from Object) |
Equals(Object) |
Indicates whether some other object is "equal to" this one. (Inherited from Object) |
GetBaseDirection(ICharSequence) |
Get the base direction of the text provided according to the Unicode Bidirectional Algorithm. |
GetBaseDirection(String) |
Get the base direction of the text provided according to the Unicode Bidirectional Algorithm. |
GetCustomizedClass(Int32) |
Retrieves the Bidi class for a given code point. |
GetHashCode() |
Returns a hash code value for the object. (Inherited from Object) |
GetLevelAt(Int32) |
Get the level for one character. |
GetLevels() |
Get an array of levels for each character. |
GetLogicalIndex(Int32) |
Get the logical text position from a visual position. |
GetLogicalMap() |
Get a logical-to-visual index map (array) for the characters in the
|
GetLogicalRun(Int32) |
Get a logical run. |
GetParagraph(Int32) |
Get a paragraph, given a position within the text. |
GetParagraphByIndex(Int32) |
Get a paragraph, given the index of this paragraph. |
GetParagraphIndex(Int32) |
Get the index of a paragraph, given a position within the text. |
GetRunLevel(Int32) |
Return the level of the nth logical run in this line. |
GetRunLimit(Int32) |
Return the index of the character past the end of the nth logical run in this line, as an offset from the start of the line. |
GetRunStart(Int32) |
Return the index of the character at the start of the nth logical run in this line, as an offset from the start of the line. |
GetText() |
Get the text. |
GetVisualIndex(Int32) |
Get the visual position from a logical text position. |
GetVisualMap() |
Get a visual-to-logical index map (array) for the characters in the
|
GetVisualRun(Int32) |
Get a |
InvertMap(Int32[]) |
Invert an index map. |
JavaFinalize() |
Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. (Inherited from Object) |
Notify() |
Wakes up a single thread that is waiting on this object's monitor. (Inherited from Object) |
NotifyAll() |
Wakes up all threads that are waiting on this object's monitor. (Inherited from Object) |
OrderParagraphsLTR(Boolean) |
Specify whether block separators must be allocated level zero, so that successive paragraphs will progress from left to right. |
ReorderLogical(Byte[]) |
This is a convenience method that does not use a |
ReorderVisual(Byte[]) |
This is a convenience method that does not use a |
ReorderVisually(Byte[], Int32, Object[], Int32, Int32) |
Reorder the objects in the array into visual order based on their levels. |
RequiresBidi(Char[], Int32, Int32) |
Return true if the specified text requires bidi analysis. |
SetContext(String, String) |
Set the context before a call to setPara(). |
SetHandle(IntPtr, JniHandleOwnership) |
Sets the Handle property. (Inherited from Object) |
SetLine(Int32, Int32) |
|
SetPara(Char[], SByte, Byte[]) |
Perform the Unicode Bidi algorithm. |
SetPara(IAttributedCharacterIterator) |
Perform the Unicode Bidi algorithm on a given paragraph, as defined in the Unicode Standard Annex #9, version 13, also described in The Unicode Standard, Version 4. |
SetPara(String, SByte, Byte[]) |
Perform the Unicode Bidi algorithm. |
ToArray<T>() | (Inherited from Object) |
ToString() |
Returns a string representation of the object. (Inherited from Object) |
UnregisterFromRuntime() | (Inherited from Object) |
Wait() |
Causes the current thread to wait until it is awakened, typically by being <em>notified</em> or <em>interrupted</em>. (Inherited from Object) |
Wait(Int64, Int32) |
Causes the current thread to wait until it is awakened, typically by being <em>notified</em> or <em>interrupted</em>, or until a certain amount of real time has elapsed. (Inherited from Object) |
Wait(Int64) |
Causes the current thread to wait until it is awakened, typically by being <em>notified</em> or <em>interrupted</em>, or until a certain amount of real time has elapsed. (Inherited from Object) |
WriteReordered(BidiOptions) |
Take a |
WriteReverse(String, BidiOptions) |
Reverse a Right-To-Left run of Unicode text. |
Explicit Interface Implementations
IJavaPeerable.Disposed() | (Inherited from Object) |
IJavaPeerable.DisposeUnlessReferenced() | (Inherited from Object) |
IJavaPeerable.Finalized() | (Inherited from Object) |
IJavaPeerable.JniManagedPeerState | (Inherited from Object) |
IJavaPeerable.SetJniIdentityHashCode(Int32) | (Inherited from Object) |
IJavaPeerable.SetJniManagedPeerState(JniManagedPeerStates) | (Inherited from Object) |
IJavaPeerable.SetPeerReference(JniObjectReference) | (Inherited from Object) |
Extension Methods
JavaCast<TResult>(IJavaObject) |
Performs an Android runtime-checked type conversion. |
JavaCast<TResult>(IJavaObject) | |
GetJniTypeName(IJavaPeerable) |
Gets the JNI name of the type of the instance |
JavaAs<TResult>(IJavaPeerable) |
Try to coerce |
TryJavaCast<TResult>(IJavaPeerable, TResult) |
Try to coerce |