下面列出了怎么用java.text.Bidi的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* This method determines if the direction of a substring is right-to-left.
* If the string is empty that determination is based on the default system language
* Locale.getDefault().
* The method can handle invalid substring definitions (start > end etc.), in which case the
* method returns False.
*
* @return True if the text direction is right-to-left, false otherwise.
*/
public static boolean isRTL(CharSequence s, int start, int end) {
if (s == null || s.length() == 0) {
// empty string --> determine the direction from the default language
return isRTL(Locale.getDefault());
}
if (start == end) {
// if no character is selected we need to expand the selection
start = Math.max(0, --start);
if (start == end) {
end = Math.min(s.length(), ++end);
}
}
try {
Bidi bidi = new Bidi(s.subSequence(start, end).toString(), Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
return ! bidi.baseIsLeftToRight();
}
catch (IndexOutOfBoundsException e) {
return false;
}
}
/**
* Create a TextLine from the text. chars is just the text in the iterator.
*/
public static TextLine standardCreateTextLine(FontRenderContext frc,
AttributedCharacterIterator text,
char[] chars,
float[] baselineOffsets) {
StyledParagraph styledParagraph = new StyledParagraph(text, chars);
Bidi bidi = new Bidi(text);
if (bidi.isLeftToRight()) {
bidi = null;
}
int layoutFlags = 0; // no extra info yet, bidi determines run and line direction
TextLabelFactory factory = new TextLabelFactory(frc, chars, bidi, layoutFlags);
boolean isDirectionLTR = true;
if (bidi != null) {
isDirectionLTR = bidi.baseIsLeftToRight();
}
return createLineFromText(chars, styledParagraph, factory, isDirectionLTR, baselineOffsets);
}
private TextLine makeTextLineOnRange(int startPos, int limitPos) {
int[] charsLtoV = null;
byte[] charLevels = null;
if (fBidi != null) {
Bidi lineBidi = fBidi.createLineBidi(startPos, limitPos);
charLevels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(charLevels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components = makeComponentsOnRange(startPos, limitPos);
return new TextLine(fFrc,
components,
fBaselineOffsets,
fChars,
startPos,
limitPos,
charsLtoV,
charLevels,
fIsDirectionLTR);
}
/**
* Create a TextLine from the Font and character data over the
* range. The range is relative to both the StyledParagraph and the
* character array.
*/
public static TextLine createLineFromText(char[] chars,
StyledParagraph styledParagraph,
TextLabelFactory factory,
boolean isDirectionLTR,
float[] baselineOffsets) {
factory.setLineContext(0, chars.length);
Bidi lineBidi = factory.getLineBidi();
int[] charsLtoV = null;
byte[] levels = null;
if (lineBidi != null) {
levels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(levels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components =
getComponents(styledParagraph, chars, 0, chars.length, charsLtoV, levels, factory);
return new TextLine(factory.getFontRenderContext(), components, baselineOffsets,
chars, 0, chars.length, charsLtoV, levels, isDirectionLTR);
}
/**
* Create a TextLine from the Font and character data over the
* range. The range is relative to both the StyledParagraph and the
* character array.
*/
public static TextLine createLineFromText(char[] chars,
StyledParagraph styledParagraph,
TextLabelFactory factory,
boolean isDirectionLTR,
float[] baselineOffsets) {
factory.setLineContext(0, chars.length);
Bidi lineBidi = factory.getLineBidi();
int[] charsLtoV = null;
byte[] levels = null;
if (lineBidi != null) {
levels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(levels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components =
getComponents(styledParagraph, chars, 0, chars.length, charsLtoV, levels, factory);
return new TextLine(factory.getFontRenderContext(), components, baselineOffsets,
chars, 0, chars.length, charsLtoV, levels, isDirectionLTR);
}
/**
* Return the level of each character into the levels array starting at start.
* This is a convenience method for clients who prefer to use an explicit levels
* array instead of iterating over the runs.
*
* @param levels the array to receive the character levels
* @param start the starting offset into the array
* @throws IndexOutOfBoundsException if {@code start} is less than 0 or
* {@code start + getLength()} is greater than {@code levels.length}.
*/
public static void getLevels(Bidi bidi, byte[] levels, int start) {
int limit = start + bidi.getLength();
if (start < 0 || limit > levels.length) {
throw new IndexOutOfBoundsException("levels.length = " + levels.length +
" start: " + start + " limit: " + limit);
}
int runCount = bidi.getRunCount();
int p = start;
for (int i = 0; i < runCount; ++i) {
int rlimit = start + bidi.getRunLimit(i);
byte rlevel = (byte)bidi.getRunLevel(i);
while (p < rlimit) {
levels[p++] = rlevel;
}
}
}
/**
* Return the level of each character into the levels array starting at start.
* This is a convenience method for clients who prefer to use an explicit levels
* array instead of iterating over the runs.
*
* @param levels the array to receive the character levels
* @param start the starting offset into the the array
* @throws IndexOutOfBoundsException if <code>start</code> is less than 0 or
* <code>start + getLength()</code> is greater than <code>levels.length</code>.
*/
public static void getLevels(Bidi bidi, byte[] levels, int start) {
int limit = start + bidi.getLength();
if (start < 0 || limit > levels.length) {
throw new IndexOutOfBoundsException("levels.length = " + levels.length +
" start: " + start + " limit: " + limit);
}
int runCount = bidi.getRunCount();
int p = start;
for (int i = 0; i < runCount; ++i) {
int rlimit = start + bidi.getRunLimit(i);
byte rlevel = (byte)bidi.getRunLevel(i);
while (p < rlimit) {
levels[p++] = rlevel;
}
}
}
private TextLine makeTextLineOnRange(int startPos, int limitPos) {
int[] charsLtoV = null;
byte[] charLevels = null;
if (fBidi != null) {
Bidi lineBidi = fBidi.createLineBidi(startPos, limitPos);
charLevels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(charLevels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components = makeComponentsOnRange(startPos, limitPos);
return new TextLine(fFrc,
components,
fBaselineOffsets,
fChars,
startPos,
limitPos,
charsLtoV,
charLevels,
fIsDirectionLTR);
}
/**
* Create a TextLine from the Font and character data over the
* range. The range is relative to both the StyledParagraph and the
* character array.
*/
public static TextLine createLineFromText(char[] chars,
StyledParagraph styledParagraph,
TextLabelFactory factory,
boolean isDirectionLTR,
float[] baselineOffsets) {
factory.setLineContext(0, chars.length);
Bidi lineBidi = factory.getLineBidi();
int[] charsLtoV = null;
byte[] levels = null;
if (lineBidi != null) {
levels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(levels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components =
getComponents(styledParagraph, chars, 0, chars.length, charsLtoV, levels, factory);
return new TextLine(factory.getFontRenderContext(), components, baselineOffsets,
chars, 0, chars.length, charsLtoV, levels, isDirectionLTR);
}
/**
* Create a TextLine from the Font and character data over the
* range. The range is relative to both the StyledParagraph and the
* character array.
*/
public static TextLine createLineFromText(char[] chars,
StyledParagraph styledParagraph,
TextLabelFactory factory,
boolean isDirectionLTR,
float[] baselineOffsets) {
factory.setLineContext(0, chars.length);
Bidi lineBidi = factory.getLineBidi();
int[] charsLtoV = null;
byte[] levels = null;
if (lineBidi != null) {
levels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(levels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components =
getComponents(styledParagraph, chars, 0, chars.length, charsLtoV, levels, factory);
return new TextLine(factory.getFontRenderContext(), components, baselineOffsets,
chars, 0, chars.length, charsLtoV, levels, isDirectionLTR);
}
private TextLine makeTextLineOnRange(int startPos, int limitPos) {
int[] charsLtoV = null;
byte[] charLevels = null;
if (fBidi != null) {
Bidi lineBidi = fBidi.createLineBidi(startPos, limitPos);
charLevels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(charLevels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components = makeComponentsOnRange(startPos, limitPos);
return new TextLine(fFrc,
components,
fBaselineOffsets,
fChars,
startPos,
limitPos,
charsLtoV,
charLevels,
fIsDirectionLTR);
}
private TextLine makeTextLineOnRange(int startPos, int limitPos) {
int[] charsLtoV = null;
byte[] charLevels = null;
if (fBidi != null) {
Bidi lineBidi = fBidi.createLineBidi(startPos, limitPos);
charLevels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(charLevels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components = makeComponentsOnRange(startPos, limitPos);
return new TextLine(fFrc,
components,
fBaselineOffsets,
fChars,
startPos,
limitPos,
charsLtoV,
charLevels,
fIsDirectionLTR);
}
/**
* Create a TextLine from the Font and character data over the
* range. The range is relative to both the StyledParagraph and the
* character array.
*/
public static TextLine createLineFromText(char[] chars,
StyledParagraph styledParagraph,
TextLabelFactory factory,
boolean isDirectionLTR,
float[] baselineOffsets) {
factory.setLineContext(0, chars.length);
Bidi lineBidi = factory.getLineBidi();
int[] charsLtoV = null;
byte[] levels = null;
if (lineBidi != null) {
levels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(levels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components =
getComponents(styledParagraph, chars, 0, chars.length, charsLtoV, levels, factory);
return new TextLine(factory.getFontRenderContext(), components, baselineOffsets,
chars, 0, chars.length, charsLtoV, levels, isDirectionLTR);
}
/**
* Return the level of each character into the levels array starting at start.
* This is a convenience method for clients who prefer to use an explicit levels
* array instead of iterating over the runs.
*
* @param levels the array to receive the character levels
* @param start the starting offset into the the array
* @throws IndexOutOfBoundsException if <code>start</code> is less than 0 or
* <code>start + getLength()</code> is greater than <code>levels.length</code>.
*/
public static void getLevels(Bidi bidi, byte[] levels, int start) {
int limit = start + bidi.getLength();
if (start < 0 || limit > levels.length) {
throw new IndexOutOfBoundsException("levels.length = " + levels.length +
" start: " + start + " limit: " + limit);
}
int runCount = bidi.getRunCount();
int p = start;
for (int i = 0; i < runCount; ++i) {
int rlimit = start + bidi.getRunLimit(i);
byte rlevel = (byte)bidi.getRunLevel(i);
while (p < rlimit) {
levels[p++] = rlevel;
}
}
}
/**
* Create a TextLine from the Font and character data over the
* range. The range is relative to both the StyledParagraph and the
* character array.
*/
public static TextLine createLineFromText(char[] chars,
StyledParagraph styledParagraph,
TextLabelFactory factory,
boolean isDirectionLTR,
float[] baselineOffsets) {
factory.setLineContext(0, chars.length);
Bidi lineBidi = factory.getLineBidi();
int[] charsLtoV = null;
byte[] levels = null;
if (lineBidi != null) {
levels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(levels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components =
getComponents(styledParagraph, chars, 0, chars.length, charsLtoV, levels, factory);
return new TextLine(factory.getFontRenderContext(), components, baselineOffsets,
chars, 0, chars.length, charsLtoV, levels, isDirectionLTR);
}
/**
* Create a TextLine from the Font and character data over the
* range. The range is relative to both the StyledParagraph and the
* character array.
*/
public static TextLine createLineFromText(char[] chars,
StyledParagraph styledParagraph,
TextLabelFactory factory,
boolean isDirectionLTR,
float[] baselineOffsets) {
factory.setLineContext(0, chars.length);
Bidi lineBidi = factory.getLineBidi();
int[] charsLtoV = null;
byte[] levels = null;
if (lineBidi != null) {
levels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(levels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components =
getComponents(styledParagraph, chars, 0, chars.length, charsLtoV, levels, factory);
return new TextLine(factory.getFontRenderContext(), components, baselineOffsets,
chars, 0, chars.length, charsLtoV, levels, isDirectionLTR);
}
/**
* Create a TextLine from the Font and character data over the
* range. The range is relative to both the StyledParagraph and the
* character array.
*/
public static TextLine createLineFromText(char[] chars,
StyledParagraph styledParagraph,
TextLabelFactory factory,
boolean isDirectionLTR,
float[] baselineOffsets) {
factory.setLineContext(0, chars.length);
Bidi lineBidi = factory.getLineBidi();
int[] charsLtoV = null;
byte[] levels = null;
if (lineBidi != null) {
levels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(levels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components =
getComponents(styledParagraph, chars, 0, chars.length, charsLtoV, levels, factory);
return new TextLine(factory.getFontRenderContext(), components, baselineOffsets,
chars, 0, chars.length, charsLtoV, levels, isDirectionLTR);
}
private TextLine makeTextLineOnRange(int startPos, int limitPos) {
int[] charsLtoV = null;
byte[] charLevels = null;
if (fBidi != null) {
Bidi lineBidi = fBidi.createLineBidi(startPos, limitPos);
charLevels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(charLevels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components = makeComponentsOnRange(startPos, limitPos);
return new TextLine(fFrc,
components,
fBaselineOffsets,
fChars,
startPos,
limitPos,
charsLtoV,
charLevels,
fIsDirectionLTR);
}
/**
* Create a TextLine from the Font and character data over the
* range. The range is relative to both the StyledParagraph and the
* character array.
*/
public static TextLine createLineFromText(char[] chars,
StyledParagraph styledParagraph,
TextLabelFactory factory,
boolean isDirectionLTR,
float[] baselineOffsets) {
factory.setLineContext(0, chars.length);
Bidi lineBidi = factory.getLineBidi();
int[] charsLtoV = null;
byte[] levels = null;
if (lineBidi != null) {
levels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(levels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components =
getComponents(styledParagraph, chars, 0, chars.length, charsLtoV, levels, factory);
return new TextLine(factory.getFontRenderContext(), components, baselineOffsets,
chars, 0, chars.length, charsLtoV, levels, isDirectionLTR);
}
private TextLine makeTextLineOnRange(int startPos, int limitPos) {
int[] charsLtoV = null;
byte[] charLevels = null;
if (fBidi != null) {
Bidi lineBidi = fBidi.createLineBidi(startPos, limitPos);
charLevels = BidiUtils.getLevels(lineBidi);
int[] charsVtoL = BidiUtils.createVisualToLogicalMap(charLevels);
charsLtoV = BidiUtils.createInverseMap(charsVtoL);
}
TextLineComponent[] components = makeComponentsOnRange(startPos, limitPos);
return new TextLine(fFrc,
components,
fBaselineOffsets,
fChars,
startPos,
limitPos,
charsLtoV,
charLevels,
fIsDirectionLTR);
}
/**
* Create a TextLine from the text. chars is just the text in the iterator.
*/
public static TextLine standardCreateTextLine(FontRenderContext frc,
AttributedCharacterIterator text,
char[] chars,
float[] baselineOffsets) {
StyledParagraph styledParagraph = new StyledParagraph(text, chars);
Bidi bidi = new Bidi(text);
if (bidi.isLeftToRight()) {
bidi = null;
}
int layoutFlags = 0; // no extra info yet, bidi determines run and line direction
TextLabelFactory factory = new TextLabelFactory(frc, chars, bidi, layoutFlags);
boolean isDirectionLTR = true;
if (bidi != null) {
isDirectionLTR = bidi.baseIsLeftToRight();
}
return createLineFromText(chars, styledParagraph, factory, isDirectionLTR, baselineOffsets);
}
public void init(TestEnvironment env, Result results) {
super.init(env, results);
chars1 = new char[chars.length + 2];
System.arraycopy(chars, 0, chars1, 1, chars.length);
ci = new ArrayCI(chars1, 1, chars.length);
gv = font.createGlyphVector(frc, text);
glyphs = gv.getGlyphCodes(0, gv.getNumGlyphs(), null);
flags = Bidi.requiresBidi(chars, 0, chars.length)
? Font.LAYOUT_LEFT_TO_RIGHT
: Font.LAYOUT_RIGHT_TO_LEFT;
}
/**
* Initialize a factory to produce glyph arrays.
* @param frc the FontRenderContext to use for the arrays to be produced.
* @param text the text of the paragraph.
* @param bidi the bidi information for the paragraph text, or null if the
* entire text is left-to-right text.
*/
public TextLabelFactory(FontRenderContext frc,
char[] text,
Bidi bidi,
int flags) {
this.frc = frc;
this.text = text.clone();
this.bidi = bidi;
this.flags = flags;
this.lineBidi = bidi;
this.lineStart = 0;
this.lineLimit = text.length;
}
private void testMethod_reorderVisually1() {
System.out.println("*** Test reorderVisually() 1");
for (int textNo = 0; textNo < data4reorderVisually.length; textNo++) {
Object[] objects = data4reorderVisually[textNo][0];
byte[] levels = getLevels(data4reorderVisually[textNo]);
Object[] expectedObjects = data4reorderVisually[textNo][2];
Bidi.reorderVisually(levels, 0, objects, 0, objects.length);
checkResult("textNo=" + textNo + ": reorderVisually(levels=[" +
toString(levels) + "], objects=[" + toString(objects) + "])",
expectedObjects, objects);
}
}
public void init(TestEnvironment env, Result results) {
super.init(env, results);
int flags = Font.LAYOUT_LEFT_TO_RIGHT;
if (Bidi.requiresBidi(chars, 0, chars.length)) { // assume rtl
flags = Font.LAYOUT_RIGHT_TO_LEFT;
}
gv = font.layoutGlyphVector(frc, chars, 0, chars.length, flags);
// gv options
}
static void test2() {
String target = "BACK WARDS";
String str = "If this text is >" + target + "< the test passed.";
int length = str.length();
int start = str.indexOf(target);
int limit = start + target.length();
System.out.println("start: " + start + " limit: " + limit);
AttributedString astr = new AttributedString(str);
astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL);
astr.addAttribute(TextAttribute.BIDI_EMBEDDING,
new Integer(-3),
start,
limit);
Bidi bidi = new Bidi(astr.getIterator());
for (int i = 0; i < bidi.getRunCount(); ++i) {
System.out.println("run " + i +
" from " + bidi.getRunStart(i) +
" to " + bidi.getRunLimit(i) +
" at level " + bidi.getRunLevel(i));
}
System.out.println(bidi + "\n");
if (bidi.getRunCount() != 6) { // runs of spaces and angles at embedding bound,s and final period, each get level 1
throw new Error("Bidi embedding processing failed");
} else {
System.out.println("test2() passed.\n");
}
}
static void test2() {
String target = "BACK WARDS";
String str = "If this text is >" + target + "< the test passed.";
int length = str.length();
int start = str.indexOf(target);
int limit = start + target.length();
System.out.println("start: " + start + " limit: " + limit);
AttributedString astr = new AttributedString(str);
astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL);
astr.addAttribute(TextAttribute.BIDI_EMBEDDING,
new Integer(-3),
start,
limit);
Bidi bidi = new Bidi(astr.getIterator());
for (int i = 0; i < bidi.getRunCount(); ++i) {
System.out.println("run " + i +
" from " + bidi.getRunStart(i) +
" to " + bidi.getRunLimit(i) +
" at level " + bidi.getRunLevel(i));
}
System.out.println(bidi + "\n");
if (bidi.getRunCount() != 6) { // runs of spaces and angles at embedding bound,s and final period, each get level 1
throw new Error("Bidi embedding processing failed");
} else {
System.out.println("test2() passed.\n");
}
}
private void callTestEachMethod4Constructor2(int textNo,
int flagNo,
Bidi bidi) {
testEachMethod(bidi,
data4Constructor2[textNo][0],
data4Constructor2[textNo][flagNo+1],
baseIsLTR4Constructor2[textNo][flagNo],
isLTR_isRTL4Constructor2[textNo][0][flagNo],
isLTR_isRTL4Constructor2[textNo][1][flagNo]);
}
private void callTestEachMethod4Constructor3(int textNo,
int dataNo,
Bidi bidi) {
testEachMethod(bidi,
data4Constructor3[textNo][0],
data4Constructor3[textNo][dataNo+1],
baseIsLTR4Constructor3[textNo][dataNo],
isLTR_isRTL4Constructor3[textNo][0][dataNo],
isLTR_isRTL4Constructor3[textNo][1][dataNo]);
}
public static void main(String[] args) {
boolean err = false;
String string = "\u05D0\u05D1\u05D2";
Bidi bidi = new Bidi(string, Bidi.DIRECTION_LEFT_TO_RIGHT);
int result = bidi.getRunCount();
if (result != 1) {
System.err.println("Incorrect run count: " + result);
err = true;
}
result = bidi.getRunStart(0);
if (result != 0) {
System.err.println("Incorrect run start: " + result);
err = true;
}
result = bidi.getRunLimit(0);
if (result != 3) {
System.err.println("Incorrect run limit: " + result);
err = true;
}
result = bidi.getRunLevel(0);
if (result != 1) {
System.err.println("Incorrect run level: " + result);
err = true;
}
if (err) {
throw new RuntimeException("Failed.");
}
}