6850113: Bidi class needs to be updated to support Unicode 5.1
Reviewed-by: okutsu
--- a/jdk/make/java/text/FILES_java.gmk Thu May 28 18:11:07 2009 +0400
+++ b/jdk/make/java/text/FILES_java.gmk Sat Jun 13 06:43:54 2009 +0900
@@ -76,6 +76,10 @@
sun/text/Normalizer.java \
sun/text/SupplementaryCharacterData.java \
sun/text/UCompactIntArray.java \
+ sun/text/bidi/BidiBase.java \
+ sun/text/bidi/BidiLine.java \
+ sun/text/bidi/BidiRun.java \
+ \
sun/text/normalizer/CharTrie.java \
sun/text/normalizer/CharacterIteratorWrapper.java \
sun/text/normalizer/ICUBinary.java \
--- a/jdk/make/sun/font/FILES_c.gmk Thu May 28 18:11:07 2009 +0400
+++ b/jdk/make/sun/font/FILES_c.gmk Sat Jun 13 06:43:54 2009 +0900
@@ -24,10 +24,6 @@
#
FILES_c_shared = \
- jbidi.c \
- ubidi.c \
- ubidiln.c \
- uchardir.c \
DrawGlyphList.c \
sunFont.c
--- a/jdk/make/sun/font/Makefile Thu May 28 18:11:07 2009 +0400
+++ b/jdk/make/sun/font/Makefile Sat Jun 13 06:43:54 2009 +0900
@@ -145,7 +145,6 @@
# Add to the ambient vpath to pick up files in subdirectories
#
vpath %.c $(PLATFORM_SRC)/native/$(PKGDIR)
-vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/bidi
vpath %.cpp $(SHARE_SRC)/native/$(PKGDIR)/layout
vpath %.cpp $(SHARE_SRC)/native/$(PKGDIR)
@@ -187,7 +186,6 @@
CPPFLAGS += -I$(SHARE_SRC)/native/$(PKGDIR) \
-I$(SHARE_SRC)/native/$(PKGDIR)/layout \
- -I$(SHARE_SRC)/native/$(PKGDIR)/bidi \
-I$(SHARE_SRC)/native/sun/awt/image/cvutils \
-I$(PLATFORM_SRC)/native/sun/awt \
-I$(SHARE_SRC)/native/sun/awt/debug \
--- a/jdk/make/sun/font/mapfile-vers Thu May 28 18:11:07 2009 +0400
+++ b/jdk/make/sun/font/mapfile-vers Sat Jun 13 06:43:54 2009 +0900
@@ -31,8 +31,6 @@
newLayoutTableCache;
freeLayoutTableCache;
isNullScalerContext;
- Java_java_text_Bidi_nativeBidiChars;
- Java_java_text_Bidi_nativeGetDirectionCode;
Java_sun_font_NullFontScaler_getNullScalerContext;
Java_sun_font_NullFontScaler_getGlyphImage;
Java_sun_font_FontManager_getPlatformFontVar;
--- a/jdk/make/sun/font/mapfile-vers.openjdk Thu May 28 18:11:07 2009 +0400
+++ b/jdk/make/sun/font/mapfile-vers.openjdk Sat Jun 13 06:43:54 2009 +0900
@@ -33,8 +33,6 @@
newLayoutTableCache;
freeLayoutTableCache;
isNullScalerContext;
- Java_java_text_Bidi_nativeBidiChars;
- Java_java_text_Bidi_nativeGetDirectionCode;
Java_sun_font_NullFontScaler_getNullScalerContext;
Java_sun_font_NullFontScaler_getGlyphImage;
Java_sun_font_FontManager_getPlatformFontVar;
--- a/jdk/src/share/classes/java/text/Bidi.java Thu May 28 18:11:07 2009 +0400
+++ b/jdk/src/share/classes/java/text/Bidi.java Sat Jun 13 06:43:54 2009 +0900
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,10 +35,7 @@
package java.text;
-import java.awt.Toolkit;
-import java.awt.font.TextAttribute;
-import java.awt.font.NumericShaper;
-import sun.text.CodePointIterator;
+import sun.text.bidi.BidiBase;
/**
* This class implements the Unicode Bidirectional Algorithm.
@@ -62,15 +59,6 @@
* @since 1.4
*/
public final class Bidi {
- byte dir;
- byte baselevel;
- int length;
- int[] runs;
- int[] cws;
-
- static {
- sun.font.FontManagerNativeLibrary.load();
- }
/** Constant indicating base direction is left-to-right. */
public static final int DIRECTION_LEFT_TO_RIGHT = 0;
@@ -94,7 +82,7 @@
*/
public static final int DIRECTION_DEFAULT_RIGHT_TO_LEFT = -1;
- private static final int DIR_MIXED = 2;
+ private BidiBase bidiBase;
/**
* Create Bidi from the given paragraph of text and base direction.
@@ -109,7 +97,7 @@
throw new IllegalArgumentException("paragraph is null");
}
- nativeBidiChars(this, paragraph.toCharArray(), 0, null, 0, paragraph.length(), flags);
+ bidiBase = new BidiBase(paragraph.toCharArray(), 0, null, 0, paragraph.length(), flags);
}
/**
@@ -142,67 +130,8 @@
throw new IllegalArgumentException("paragraph is null");
}
- int flags = DIRECTION_DEFAULT_LEFT_TO_RIGHT;
- byte[] embeddings = null;
-
- int start = paragraph.getBeginIndex();
- int limit = paragraph.getEndIndex();
- int length = limit - start;
- int n = 0;
- char[] text = new char[length];
- for (char c = paragraph.first(); c != paragraph.DONE; c = paragraph.next()) {
- text[n++] = c;
- }
-
- paragraph.first();
- try {
- Boolean runDirection = (Boolean)paragraph.getAttribute(TextAttribute.RUN_DIRECTION);
- if (runDirection != null) {
- if (TextAttribute.RUN_DIRECTION_LTR.equals(runDirection)) {
- flags = DIRECTION_LEFT_TO_RIGHT; // clears default setting
- } else {
- flags = DIRECTION_RIGHT_TO_LEFT;
- }
- }
- }
- catch (ClassCastException e) {
- }
-
- try {
- NumericShaper shaper = (NumericShaper)paragraph.getAttribute(TextAttribute.NUMERIC_SHAPING);
- if (shaper != null) {
- shaper.shape(text, 0, text.length);
- }
- }
- catch (ClassCastException e) {
- }
-
- int pos = start;
- do {
- paragraph.setIndex(pos);
- Object embeddingLevel = paragraph.getAttribute(TextAttribute.BIDI_EMBEDDING);
- int newpos = paragraph.getRunLimit(TextAttribute.BIDI_EMBEDDING);
-
- if (embeddingLevel != null) {
- try {
- int intLevel = ((Integer)embeddingLevel).intValue();
- if (intLevel >= -61 && intLevel < 61) {
- byte level = (byte)(intLevel < 0 ? (-intLevel | 0x80) : intLevel);
- if (embeddings == null) {
- embeddings = new byte[length];
- }
- for (int i = pos - start; i < newpos - start; ++i) {
- embeddings[i] = level;
- }
- }
- }
- catch (ClassCastException e) {
- }
- }
- pos = newpos;
- } while (pos < limit);
-
- nativeBidiChars(this, text, 0, embeddings, 0, text.length, flags);
+ bidiBase = new BidiBase(0, 0);
+ bidiBase.setPara(paragraph);
}
/**
@@ -240,46 +169,7 @@
" for embeddings of length: " + text.length);
}
- if (embeddings != null) {
- // native uses high bit to indicate override, not negative value, sigh
-
- for (int i = embStart, embLimit = embStart + paragraphLength; i < embLimit; ++i) {
- if (embeddings[i] < 0) {
- byte[] temp = new byte[paragraphLength];
- System.arraycopy(embeddings, embStart, temp, 0, paragraphLength);
-
- for (i -= embStart; i < paragraphLength; ++i) {
- if (temp[i] < 0) {
- temp[i] = (byte)(-temp[i] | 0x80);
- }
- }
-
- embeddings = temp;
- embStart = 0;
- break;
- }
- }
- }
-
- nativeBidiChars(this, text, textStart, embeddings, embStart, paragraphLength, flags);
- }
-
- /**
- * Private constructor used by line bidi.
- */
- private Bidi(int dir, int baseLevel, int length, int[] data, int[] cws) {
- reset(dir, baseLevel, length, data, cws);
- }
-
- /**
- * Private mutator used by native code.
- */
- private void reset(int dir, int baselevel, int length, int[] data, int[] cws) {
- this.dir = (byte)dir;
- this.baselevel = (byte)baselevel;
- this.length = length;
- this.runs = data;
- this.cws = cws;
+ bidiBase = new BidiBase(text, textStart, embeddings, embStart, paragraphLength, flags);
}
/**
@@ -290,96 +180,10 @@
* @param lineLimit the offset from the start of the paragraph to the limit of the line.
*/
public Bidi createLineBidi(int lineStart, int lineLimit) {
- if (lineStart == 0 && lineLimit == length) {
- return this;
- }
-
- int lineLength = lineLimit - lineStart;
- if (lineStart < 0 ||
- lineLimit < lineStart ||
- lineLimit > length) {
- throw new IllegalArgumentException("range " + lineStart +
- " to " + lineLimit +
- " is invalid for paragraph of length " + length);
- }
-
- if (runs == null) {
- return new Bidi(dir, baselevel, lineLength, null, null);
- } else {
- int cwspos = -1;
- int[] ncws = null;
- if (cws != null) {
- int cwss = 0;
- int cwsl = cws.length;
- while (cwss < cwsl) {
- if (cws[cwss] >= lineStart) {
- cwsl = cwss;
- while (cwsl < cws.length && cws[cwsl] < lineLimit) {
- cwsl++;
- }
- int ll = lineLimit-1;
- while (cwsl > cwss && cws[cwsl-1] == ll) {
- cwspos = ll; // record start of counter-directional whitespace
- --cwsl;
- --ll;
- }
-
- if (cwspos == lineStart) { // entire line is cws, so ignore
- return new Bidi(dir, baselevel, lineLength, null, null);
- }
+ AttributedString astr = new AttributedString("");
+ Bidi newBidi = new Bidi(astr.getIterator());
- int ncwslen = cwsl - cwss;
- if (ncwslen > 0) {
- ncws = new int[ncwslen];
- for (int i = 0; i < ncwslen; ++i) {
- ncws[i] = cws[cwss+i] - lineStart;
- }
- }
- break;
- }
- ++cwss;
- }
- }
-
- int[] nruns = null;
- int nlevel = baselevel;
- int limit = cwspos == -1 ? lineLimit : cwspos;
- int rs = 0;
- int rl = runs.length;
- int ndir = dir;
- for (; rs < runs.length; rs += 2) {
- if (runs[rs] > lineStart) {
- rl = rs;
- while (rl < runs.length && runs[rl] < limit) {
- rl += 2;
- }
- if ((rl > rs) || (runs[rs+1] != baselevel)) {
- rl += 2;
-
- if (cwspos != -1 && rl > rs && runs[rl-1] != baselevel) { // add level for cws
- nruns = new int[rl - rs + 2];
- nruns[rl - rs] = lineLength;
- nruns[rl - rs + 1] = baselevel;
- } else {
- limit = lineLimit;
- nruns = new int[rl - rs];
- }
-
- int n = 0;
- for (int i = rs; i < rl; i += 2) {
- nruns[n++] = runs[i] - lineStart;
- nruns[n++] = runs[i+1];
- }
- nruns[n-2] = limit - lineStart;
- } else {
- ndir = (runs[rs+1] & 0x1) == 0 ? DIRECTION_LEFT_TO_RIGHT : DIRECTION_RIGHT_TO_LEFT;
- }
- break;
- }
- }
-
- return new Bidi(ndir, baselevel, lineLength, nruns, ncws);
- }
+ return bidiBase.setLine(this, bidiBase, newBidi, newBidi.bidiBase,lineStart, lineLimit);
}
/**
@@ -388,7 +192,7 @@
* @return true if the line is not left-to-right or right-to-left.
*/
public boolean isMixed() {
- return dir == DIR_MIXED;
+ return bidiBase.isMixed();
}
/**
@@ -396,7 +200,7 @@
* @return true if the line is all left-to-right text and the base direction is left-to-right
*/
public boolean isLeftToRight() {
- return dir == DIRECTION_LEFT_TO_RIGHT;
+ return bidiBase.isLeftToRight();
}
/**
@@ -404,7 +208,7 @@
* @return true if the line is all right-to-left text, and the base direction is right-to-left
*/
public boolean isRightToLeft() {
- return dir == DIRECTION_RIGHT_TO_LEFT;
+ return bidiBase.isRightToLeft();
}
/**
@@ -412,7 +216,7 @@
* @return the length of text in the line
*/
public int getLength() {
- return length;
+ return bidiBase.getLength();
}
/**
@@ -420,7 +224,7 @@
* @return true if the base direction is left-to-right
*/
public boolean baseIsLeftToRight() {
- return (baselevel & 0x1) == 0;
+ return bidiBase.baseIsLeftToRight();
}
/**
@@ -428,7 +232,7 @@
* @return the base level
*/
public int getBaseLevel() {
- return baselevel;
+ return bidiBase.getParaLevel();
}
/**
@@ -438,17 +242,7 @@
* @return the resolved level of the character at offset
*/
public int getLevelAt(int offset) {
- if (runs == null || offset < 0 || offset >= length) {
- return baselevel;
- } else {
- int i = 0;
- do {
- if (offset < runs[i]) {
- return runs[i+1];
- }
- i += 2;
- } while (true);
- }
+ return bidiBase.getLevelAt(offset);
}
/**
@@ -456,7 +250,7 @@
* @return the number of level runs
*/
public int getRunCount() {
- return runs == null ? 1 : runs.length / 2;
+ return bidiBase.countRuns();
}
/**
@@ -465,7 +259,7 @@
* @return the level of the run
*/
public int getRunLevel(int run) {
- return runs == null ? baselevel : runs[run * 2 + 1];
+ return bidiBase.getRunLevel(run);
}
/**
@@ -475,7 +269,7 @@
* @return the start of the run
*/
public int getRunStart(int run) {
- return (runs == null || run == 0) ? 0 : runs[run * 2 - 2];
+ return bidiBase.getRunStart(run);
}
/**
@@ -486,7 +280,7 @@
* @return limit the limit of the run
*/
public int getRunLimit(int run) {
- return runs == null ? length : runs[run * 2];
+ return bidiBase.getRunLimit(run);
}
/**
@@ -501,16 +295,7 @@
* @return true if the range of characters requires bidi analysis
*/
public static boolean requiresBidi(char[] text, int start, int limit) {
- CodePointIterator cpi = CodePointIterator.create(text, start, limit);
- for (int cp = cpi.next(); cp != CodePointIterator.DONE; cp = cpi.next()) {
- if (cp > 0x0590) {
- int dc = nativeGetDirectionCode(cp);
- if ((RMASK & (1 << dc)) != 0) {
- return true;
- }
- }
- }
- return false;
+ return BidiBase.requiresBidi(text, start, limit);
}
/**
@@ -530,124 +315,14 @@
* @param count the number of objects to reorder
*/
public static void reorderVisually(byte[] levels, int levelStart, Object[] objects, int objectStart, int count) {
-
- if (count < 0) {
- throw new IllegalArgumentException("count " + count + " must be >= 0");
- }
- if (levelStart < 0 || levelStart + count > levels.length) {
- throw new IllegalArgumentException("levelStart " + levelStart + " and count " + count +
- " out of range [0, " + levels.length + "]");
- }
- if (objectStart < 0 || objectStart + count > objects.length) {
- throw new IllegalArgumentException("objectStart " + objectStart + " and count " + count +
- " out of range [0, " + objects.length + "]");
- }
-
- byte lowestOddLevel = (byte)(NUMLEVELS + 1);
- byte highestLevel = 0;
-
- // initialize mapping and levels
-
- int levelLimit = levelStart + count;
- for (int i = levelStart; i < levelLimit; i++) {
- byte level = levels[i];
- if (level > highestLevel) {
- highestLevel = level;
- }
-
- if ((level & 0x01) != 0 && level < lowestOddLevel) {
- lowestOddLevel = level;
- }
- }
-
- int delta = objectStart - levelStart;
-
- while (highestLevel >= lowestOddLevel) {
- int i = levelStart;
-
- for (;;) {
- while (i < levelLimit && levels[i] < highestLevel) {
- i++;
- }
- int begin = i++;
-
- if (begin == levelLimit) {
- break; // no more runs at this level
- }
-
- while (i < levelLimit && levels[i] >= highestLevel) {
- i++;
- }
- int end = i - 1;
-
- begin += delta;
- end += delta;
- while (begin < end) {
- Object temp = objects[begin];
- objects[begin] = objects[end];
- objects[end] = temp;
- ++begin;
- --end;
- }
- }
-
- --highestLevel;
- }
+ BidiBase.reorderVisually(levels, levelStart, objects, objectStart, count);
}
- private static final char NUMLEVELS = 62;
-
- private static final int RMASK =
- (1 << 1 /* U_RIGHT_TO_LEFT */) |
- (1 << 5 /* U_ARABIC_NUMBER */) |
- (1 << 13 /* U_RIGHT_TO_LEFT_ARABIC */) |
- (1 << 14 /* U_RIGHT_TO_LEFT_EMBEDDING */) |
- (1 << 15 /* U_RIGHT_TO_LEFT_OVERRIDE */);
-
- /** Access native bidi implementation. */
- private static native int nativeGetDirectionCode(int cp);
-
- /** Access native bidi implementation. */
- private static synchronized native void nativeBidiChars(Bidi bidi, char[] text, int textStart,
- byte[] embeddings, int embeddingStart,
- int length, int flags);
-
/**
* Display the bidi internal state, used in debugging.
*/
public String toString() {
- StringBuffer buf = new StringBuffer(super.toString());
- buf.append("[dir: " + dir);
- buf.append(" baselevel: " + baselevel);
- buf.append(" length: " + length);
- if (runs == null) {
- buf.append(" runs: null");
- } else {
- buf.append(" runs: [");
- for (int i = 0; i < runs.length; i += 2) {
- if (i != 0) {
- buf.append(' ');
- }
- buf.append(runs[i]); // limit
- buf.append('/');
- buf.append(runs[i+1]); // level
- }
- buf.append(']');
- }
- if (cws == null) {
- buf.append(" cws: null");
- } else {
- buf.append(" cws: [");
- for (int i = 0; i < cws.length; ++i) {
- if (i != 0) {
- buf.append(' ');
- }
- buf.append(Integer.toHexString(cws[i]));
- }
- buf.append(']');
- }
- buf.append(']');
+ return bidiBase.toString();
+ }
- return buf.toString();
- }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/text/bidi/BidiBase.java Sat Jun 13 06:43:54 2009 +0900
@@ -0,0 +1,3444 @@
+/*
+ * Portions Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ *******************************************************************************
+ * (C) Copyright IBM Corp. and others, 1996-2009 - All Rights Reserved *
+ * *
+ * The original version of this source code and documentation is copyrighted *
+ * and owned by IBM, These materials are provided under terms of a License *
+ * Agreement between IBM and Sun. This technology is protected by multiple *
+ * US and International patents. This notice and attribution to IBM may not *
+ * to removed. *
+ *******************************************************************************
+ */
+
+/* FOOD FOR THOUGHT: currently the reordering modes are a mixture of
+ * algorithm for direct BiDi, algorithm for inverse Bidi and the bizarre
+ * concept of RUNS_ONLY which is a double operation.
+ * It could be advantageous to divide this into 3 concepts:
+ * a) Operation: direct / inverse / RUNS_ONLY
+ * b) Direct algorithm: default / NUMBERS_SPECIAL / GROUP_NUMBERS_WITH_L
+ * c) Inverse algorithm: default / INVERSE_LIKE_DIRECT / NUMBERS_SPECIAL
+ * This would allow combinations not possible today like RUNS_ONLY with
+ * NUMBERS_SPECIAL.
+ * Also allow to set INSERT_MARKS for the direct step of RUNS_ONLY and
+ * REMOVE_CONTROLS for the inverse step.
+ * Not all combinations would be supported, and probably not all do make sense.
+ * This would need to document which ones are supported and what are the
+ * fallbacks for unsupported combinations.
+ */
+
+package sun.text.bidi;
+
+import java.awt.font.TextAttribute;
+import java.awt.font.NumericShaper;
+import java.io.IOException;
+import java.lang.reflect.Array;
+import java.text.AttributedCharacterIterator;
+import java.text.Bidi;
+import java.util.Arrays;
+import java.util.MissingResourceException;
+import sun.text.normalizer.UBiDiProps;
+import sun.text.normalizer.UCharacter;
+import sun.text.normalizer.UTF16;
+
+/**
+ *
+ * <h2>Bidi algorithm for ICU</h2>
+ *
+ * This is an implementation of the Unicode Bidirectional algorithm. The
+ * algorithm is defined in the <a
+ * href="http://www.unicode.org/unicode/reports/tr9/">Unicode Standard Annex #9</a>,
+ * version 13, also described in The Unicode Standard, Version 4.0 .
+ * <p>
+ *
+ * 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.
+ * <p>
+ *
+ * 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.
+ * <p>
+ *
+ * <h3>Basic concept: paragraph</h3>
+ * A piece of text can be divided into several paragraphs by characters
+ * with the Bidi class <code>Block Separator</code>. For handling of
+ * paragraphs, see:
+ * <ul>
+ * <li>{@link #countParagraphs}
+ * <li>{@link #getParaLevel}
+ * <li>{@link #getParagraph}
+ * <li>{@link #getParagraphByIndex}
+ * </ul>
+ *
+ * <h3>Basic concept: text direction</h3>
+ * The direction of a piece of text may be:
+ * <ul>
+ * <li>{@link #LTR}
+ * <li>{@link #RTL}
+ * <li>{@link #MIXED}
+ * </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.<p>
+ *
+ * Levels can be abstract values when used for the
+ * <code>paraLevel</code> and <code>embeddingLevels</code>
+ * arguments of <code>setPara()</code>; there:
+ * <ul>
+ * <li>the high-order bit of an <code>embeddingLevels[]</code>
+ * value indicates whether the using application is
+ * specifying the level of a character to <i>override</i> whatever the
+ * Bidi implementation would resolve it to.</li>
+ * <li><code>paraLevel</code> can be set to the
+ * pseudo-level values <code>LEVEL_DEFAULT_LTR</code>
+ * and <code>LEVEL_DEFAULT_RTL</code>.</li>
+ * </ul>
+ *
+ * <p>The related constants are not real, valid level values.
+ * <code>DEFAULT_XXX</code> can be used to specify
+ * a default for the paragraph level for
+ * when the <code>setPara()</code> method
+ * shall determine it but there is no
+ * strongly typed character in the input.<p>
+ *
+ * Note that the value for <code>LEVEL_DEFAULT_LTR</code> is even
+ * and the one for <code>LEVEL_DEFAULT_RTL</code> 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.
+ *
+ * <ul><b>See Also:</b>
+ * <li>{@link #LEVEL_DEFAULT_LTR}
+ * <li>{@link #LEVEL_DEFAULT_RTL}
+ * <li>{@link #LEVEL_OVERRIDE}
+ * <li>{@link #MAX_EXPLICIT_LEVEL}
+ * <li>{@link #setPara}
+ * </ul>
+ *
+ * <h3>Basic concept: Reordering Mode</h3>
+ * Reordering mode values indicate which variant of the Bidi algorithm to
+ * use.
+ *
+ * <ul><b>See Also:</b>
+ * <li>{@link #setReorderingMode}
+ * <li>{@link #REORDER_DEFAULT}
+ * <li>{@link #REORDER_NUMBERS_SPECIAL}
+ * <li>{@link #REORDER_GROUP_NUMBERS_WITH_R}
+ * <li>{@link #REORDER_RUNS_ONLY}
+ * <li>{@link #REORDER_INVERSE_NUMBERS_AS_L}
+ * <li>{@link #REORDER_INVERSE_LIKE_DIRECT}
+ * <li>{@link #REORDER_INVERSE_FOR_NUMBERS_SPECIAL}
+ * </ul>
+ *
+ * <h3>Basic concept: Reordering Options</h3>
+ * Reordering options can be applied during Bidi text transformations.
+ * <ul><b>See Also:</b>
+ * <li>{@link #setReorderingOptions}
+ * <li>{@link #OPTION_DEFAULT}
+ * <li>{@link #OPTION_INSERT_MARKS}
+ * <li>{@link #OPTION_REMOVE_CONTROLS}
+ * <li>{@link #OPTION_STREAMING}
+ * </ul>
+ *
+ *
+ * @author Simon Montagu, Matitiahu Allouche (ported from C code written by Markus W. Scherer)
+ * @stable ICU 3.8
+ *
+ *
+ * <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.
+ *
+ * <p>
+ * The basic assumptions are:
+ * </p>
+ * <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>
+ *
+ * <pre>
+ *
+ * package com.ibm.icu.dev.test.bidi;
+ *
+ * import com.ibm.icu.text.Bidi;
+ * import com.ibm.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);
+ * }
+ * }
+ *
+ * </pre>
+ */
+
+public class BidiBase {
+
+ class Point {
+ int pos; /* position in text */
+ int flag; /* flag for LRM/RLM, before/after */
+ }
+
+ class InsertPoints {
+ int size;
+ int confirmed;
+ Point[] points = new Point[0];
+ }
+
+ /** Paragraph level setting<p>
+ *
+ * Constant indicating that the base direction depends on the first strong
+ * directional character in the text according to the Unicode Bidirectional
+ * Algorithm. If no strong directional character is present,
+ * then set the paragraph level to 0 (left-to-right).<p>
+ *
+ * If this value is used in conjunction with reordering modes
+ * <code>REORDER_INVERSE_LIKE_DIRECT</code> or
+ * <code>REORDER_INVERSE_FOR_NUMBERS_SPECIAL</code>, the text to reorder
+ * is assumed to be visual LTR, and the text after reordering is required
+ * to be the corresponding logical string with appropriate contextual
+ * direction. The direction of the result string will be RTL if either
+ * the righmost or leftmost strong character of the source text is RTL
+ * or Arabic Letter, the direction will be LTR otherwise.<p>
+ *
+ * If reordering option <code>OPTION_INSERT_MARKS</code> is set, an RLM may
+ * be added at the beginning of the result string to ensure round trip
+ * (that the result string, when reordered back to visual, will produce
+ * the original source text).
+ * @see #REORDER_INVERSE_LIKE_DIRECT
+ * @see #REORDER_INVERSE_FOR_NUMBERS_SPECIAL
+ * @stable ICU 3.8
+ */
+ public static final byte INTERNAL_LEVEL_DEFAULT_LTR = (byte)0x7e;
+
+ /** Paragraph level setting<p>
+ *
+ * Constant indicating that the base direction depends on the first strong
+ * directional character in the text according to the Unicode Bidirectional
+ * Algorithm. If no strong directional character is present,
+ * then set the paragraph level to 1 (right-to-left).<p>
+ *
+ * If this value is used in conjunction with reordering modes
+ * <code>REORDER_INVERSE_LIKE_DIRECT</code> or
+ * <code>REORDER_INVERSE_FOR_NUMBERS_SPECIAL</code>, the text to reorder
+ * is assumed to be visual LTR, and the text after reordering is required
+ * to be the corresponding logical string with appropriate contextual
+ * direction. The direction of the result string will be RTL if either
+ * the righmost or leftmost strong character of the source text is RTL
+ * or Arabic Letter, or if the text contains no strong character;
+ * the direction will be LTR otherwise.<p>
+ *
+ * If reordering option <code>OPTION_INSERT_MARKS</code> is set, an RLM may
+ * be added at the beginning of the result string to ensure round trip
+ * (that the result string, when reordered back to visual, will produce
+ * the original source text).
+ * @see #REORDER_INVERSE_LIKE_DIRECT
+ * @see #REORDER_INVERSE_FOR_NUMBERS_SPECIAL
+ * @stable ICU 3.8
+ */
+ public static final byte INTERNAL_LEVEL_DEFAULT_RTL = (byte)0x7f;
+
+ /**
+ * Maximum explicit embedding level.
+ * (The maximum resolved level can be up to <code>MAX_EXPLICIT_LEVEL+1</code>).
+ * @stable ICU 3.8
+ */
+ public static final byte MAX_EXPLICIT_LEVEL = 61;
+
+ /**
+ * Bit flag for level input.
+ * Overrides directional properties.
+ * @stable ICU 3.8
+ */
+ public static final byte INTERNAL_LEVEL_OVERRIDE = (byte)0x80;
+
+ /**
+ * Special value which can be returned by the mapping methods when a
+ * logical index has no corresponding visual index or vice-versa. This may
+ * happen for the logical-to-visual mapping of a Bidi control when option
+ * <code>OPTION_REMOVE_CONTROLS</code> is
+ * specified. This can also happen for the visual-to-logical mapping of a
+ * Bidi mark (LRM or RLM) inserted by option
+ * <code>OPTION_INSERT_MARKS</code>.
+ * @see #getVisualIndex
+ * @see #getVisualMap
+ * @see #getLogicalIndex
+ * @see #getLogicalMap
+ * @see #OPTION_INSERT_MARKS
+ * @see #OPTION_REMOVE_CONTROLS
+ * @stable ICU 3.8
+ */
+ public static final int MAP_NOWHERE = -1;
+
+ /**
+ * Mixed-directional text.
+ * @stable ICU 3.8
+ */
+ public static final byte MIXED = 2;
+
+ /**
+ * option bit for writeReordered():
+ * replace characters with the "mirrored" property in RTL runs
+ * by their mirror-image mappings
+ *
+ * @see #writeReordered
+ * @stable ICU 3.8
+ */
+ public static final short DO_MIRRORING = 2;
+
+ /** Reordering mode: Regular Logical to Visual Bidi algorithm according to Unicode.
+ * @see #setReorderingMode
+ * @stable ICU 3.8
+ */
+ private static final short REORDER_DEFAULT = 0;
+
+ /** Reordering mode: Logical to Visual algorithm which handles numbers in
+ * a way which mimicks the behavior of Windows XP.
+ * @see #setReorderingMode
+ * @stable ICU 3.8
+ */
+ private static final short REORDER_NUMBERS_SPECIAL = 1;
+
+ /** Reordering mode: Logical to Visual algorithm grouping numbers with
+ * adjacent R characters (reversible algorithm).
+ * @see #setReorderingMode
+ * @stable ICU 3.8
+ */
+ private static final short REORDER_GROUP_NUMBERS_WITH_R = 2;
+
+ /** Reordering mode: Reorder runs only to transform a Logical LTR string
+ * to the logical RTL string with the same display, or vice-versa.<br>
+ * If this mode is set together with option
+ * <code>OPTION_INSERT_MARKS</code>, some Bidi controls in the source
+ * text may be removed and other controls may be added to produce the
+ * minimum combination which has the required display.
+ * @see #OPTION_INSERT_MARKS
+ * @see #setReorderingMode
+ * @stable ICU 3.8
+ */
+ private static final short REORDER_RUNS_ONLY = 3;
+
+ /** Reordering mode: Visual to Logical algorithm which handles numbers
+ * like L (same algorithm as selected by <code>setInverse(true)</code>.
+ * @see #setInverse
+ * @see #setReorderingMode
+ * @stable ICU 3.8
+ */
+ private static final short REORDER_INVERSE_NUMBERS_AS_L = 4;
+
+ /** Reordering mode: Visual to Logical algorithm equivalent to the regular
+ * Logical to Visual algorithm.
+ * @see #setReorderingMode
+ * @stable ICU 3.8
+ */
+ private static final short REORDER_INVERSE_LIKE_DIRECT = 5;
+
+ /** Reordering mode: Inverse Bidi (Visual to Logical) algorithm for the
+ * <code>REORDER_NUMBERS_SPECIAL</code> Bidi algorithm.
+ * @see #setReorderingMode
+ * @stable ICU 3.8
+ */
+ private static final short REORDER_INVERSE_FOR_NUMBERS_SPECIAL = 6;
+
+ /* Reordering mode values must be ordered so that all the regular logical to
+ * visual modes come first, and all inverse Bidi modes come last.
+ */
+ private static final short REORDER_LAST_LOGICAL_TO_VISUAL =
+ REORDER_NUMBERS_SPECIAL;
+
+ /**
+ * Option bit for <code>setReorderingOptions</code>:
+ * insert Bidi marks (LRM or RLM) when needed to ensure correct result of
+ * a reordering to a Logical order
+ *
+ * <p>This option must be set or reset before calling
+ * <code>setPara</code>.</p>
+ *
+ * <p>This option is significant only with reordering modes which generate
+ * a result with Logical order, specifically.</p>
+ * <ul>
+ * <li><code>REORDER_RUNS_ONLY</code></li>
+ * <li><code>REORDER_INVERSE_NUMBERS_AS_L</code></li>
+ * <li><code>REORDER_INVERSE_LIKE_DIRECT</code></li>
+ * <li><code>REORDER_INVERSE_FOR_NUMBERS_SPECIAL</code></li>
+ * </ul>
+ *
+ * <p>If this option is set in conjunction with reordering mode
+ * <code>REORDER_INVERSE_NUMBERS_AS_L</code> or with calling
+ * <code>setInverse(true)</code>, it implies option
+ * <code>INSERT_LRM_FOR_NUMERIC</code> in calls to method
+ * <code>writeReordered()</code>.</p>
+ *
+ * <p>For other reordering modes, a minimum number of LRM or RLM characters
+ * will be added to the source text after reordering it so as to ensure
+ * round trip, i.e. when applying the inverse reordering mode on the
+ * resulting logical text with removal of Bidi marks
+ * (option <code>OPTION_REMOVE_CONTROLS</code> set before calling
+ * <code>setPara()</code> or option
+ * <code>REMOVE_BIDI_CONTROLS</code> in
+ * <code>writeReordered</code>), the result will be identical to the
+ * source text in the first transformation.
+ *
+ * <p>This option will be ignored if specified together with option
+ * <code>OPTION_REMOVE_CONTROLS</code>. It inhibits option
+ * <code>REMOVE_BIDI_CONTROLS</code> in calls to method
+ * <code>writeReordered()</code> and it implies option
+ * <code>INSERT_LRM_FOR_NUMERIC</code> in calls to method
+ * <code>writeReordered()</code> if the reordering mode is
+ * <code>REORDER_INVERSE_NUMBERS_AS_L</code>.</p>
+ *
+ * @see #setReorderingMode
+ * @see #setReorderingOptions
+ * @see #INSERT_LRM_FOR_NUMERIC
+ * @see #REMOVE_BIDI_CONTROLS
+ * @see #OPTION_REMOVE_CONTROLS
+ * @see #REORDER_RUNS_ONLY
+ * @see #REORDER_INVERSE_NUMBERS_AS_L
+ * @see #REORDER_INVERSE_LIKE_DIRECT
+ * @see #REORDER_INVERSE_FOR_NUMBERS_SPECIAL
+ * @stable ICU 3.8
+ */
+ private static final int OPTION_INSERT_MARKS = 1;
+
+ /**
+ * Option bit for <code>setReorderingOptions</code>:
+ * remove Bidi control characters
+ *
+ * <p>This option must be set or reset before calling
+ * <code>setPara</code>.</p>
+ *
+ * <p>This option nullifies option
+ * <code>OPTION_INSERT_MARKS</code>. It inhibits option
+ * <code>INSERT_LRM_FOR_NUMERIC</code> in calls to method
+ * <code>writeReordered()</code> and it implies option
+ * <code>REMOVE_BIDI_CONTROLS</code> in calls to that method.</p>
+ *
+ * @see #setReorderingMode
+ * @see #setReorderingOptions
+ * @see #OPTION_INSERT_MARKS
+ * @see #INSERT_LRM_FOR_NUMERIC
+ * @see #REMOVE_BIDI_CONTROLS
+ * @stable ICU 3.8
+ */
+ private static final int OPTION_REMOVE_CONTROLS = 2;
+
+ /**
+ * Option bit for <code>setReorderingOptions</code>:
+ * process the output as part of a stream to be continued
+ *
+ * <p>This option must be set or reset before calling
+ * <code>setPara</code>.</p>
+ *
+ * <p>This option specifies that the caller is interested in processing
+ * large text object in parts. The results of the successive calls are
+ * expected to be concatenated by the caller. Only the call for the last
+ * part will have this option bit off.</p>
+ *
+ * <p>When this option bit is on, <code>setPara()</code> may process
+ * less than the full source text in order to truncate the text at a
+ * meaningful boundary. The caller should call
+ * <code>getProcessedLength()</code> immediately after calling
+ * <code>setPara()</code> in order to determine how much of the source
+ * text has been processed. Source text beyond that length should be
+ * resubmitted in following calls to <code>setPara</code>. The
+ * processed length may be less than the length of the source text if a
+ * character preceding the last character of the source text constitutes a
+ * reasonable boundary (like a block separator) for text to be continued.<br>
+ * If the last character of the source text constitutes a reasonable
+ * boundary, the whole text will be processed at once.<br>
+ * If nowhere in the source text there exists
+ * such a reasonable boundary, the processed length will be zero.<br>
+ * The caller should check for such an occurrence and do one of the following:
+ * <ul><li>submit a larger amount of text with a better chance to include
+ * a reasonable boundary.</li>
+ * <li>resubmit the same text after turning off option
+ * <code>OPTION_STREAMING</code>.</li></ul>
+ * In all cases, this option should be turned off before processing the last
+ * part of the text.</p>
+ *
+ * <p>When the <code>OPTION_STREAMING</code> option is used, it is
+ * recommended to call <code>orderParagraphsLTR()</code> with argument
+ * <code>orderParagraphsLTR</code> set to <code>true</code> before calling
+ * <code>setPara()</code> so that later paragraphs may be concatenated to
+ * previous paragraphs on the right.
+ * </p>
+ *
+ * @see #setReorderingMode
+ * @see #setReorderingOptions
+ * @see #getProcessedLength
+ * @see #orderParagraphsLTR
+ * @stable ICU 3.8
+ */
+ private static final int OPTION_STREAMING = 4;
+
+ /*
+ * Comparing the description of the Bidi algorithm with this implementation
+ * is easier with the same names for the Bidi types in the code as there.
+ * See UCharacterDirection
+ */
+ private static final byte L = 0;
+ private static final byte R = 1;
+ private static final byte EN = 2;
+ private static final byte ES = 3;
+ private static final byte ET = 4;
+ private static final byte AN = 5;
+ private static final byte CS = 6;
+ static final byte B = 7;
+ private static final byte S = 8;
+ private static final byte WS = 9;
+ private static final byte ON = 10;
+ private static final byte LRE = 11;
+ private static final byte LRO = 12;
+ private static final byte AL = 13;
+ private static final byte RLE = 14;
+ private static final byte RLO = 15;
+ private static final byte PDF = 16;
+ private static final byte NSM = 17;
+ private static final byte BN = 18;
+
+ private static final int MASK_R_AL = (1 << R | 1 << AL);
+
+ private static final char CR = '\r';
+ private static final char LF = '\n';
+
+ static final int LRM_BEFORE = 1;
+ static final int LRM_AFTER = 2;
+ static final int RLM_BEFORE = 4;
+ static final int RLM_AFTER = 8;
+
+ /*
+ * reference to parent paragraph object (reference to self if this object is
+ * a paragraph object); set to null in a newly opened object; set to a
+ * real value after a successful execution of setPara or setLine
+ */
+ BidiBase paraBidi;
+
+ final UBiDiProps bdp;
+
+ /* character array representing the current text */
+ char[] text;
+
+ /* length of the current text */
+ int originalLength;
+
+ /* if the option OPTION_STREAMING is set, this is the length of
+ * text actually processed by <code>setPara</code>, which may be shorter
+ * than the original length. Otherwise, it is identical to the original
+ * length.
+ */
+ public int length;
+
+ /* if option OPTION_REMOVE_CONTROLS is set, and/or Bidi
+ * marks are allowed to be inserted in one of the reordering modes, the
+ * length of the result string may be different from the processed length.
+ */
+ int resultLength;
+
+ /* indicators for whether memory may be allocated after construction */
+ boolean mayAllocateText;
+ boolean mayAllocateRuns;
+
+ /* arrays with one value per text-character */
+ byte[] dirPropsMemory = new byte[1];
+ byte[] levelsMemory = new byte[1];
+ byte[] dirProps;
+ byte[] levels;
+
+ /* must block separators receive level 0? */
+ boolean orderParagraphsLTR;
+
+ /* the paragraph level */
+ byte paraLevel;
+
+ /* original paraLevel when contextual */
+ /* must be one of DEFAULT_xxx or 0 if not contextual */
+ byte defaultParaLevel;
+
+ /* the following is set in setPara, used in processPropertySeq */
+
+ ImpTabPair impTabPair; /* reference to levels state table pair */
+
+ /* the overall paragraph or line directionality*/
+ byte direction;
+
+ /* flags is a bit set for which directional properties are in the text */
+ int flags;
+
+ /* lastArabicPos is index to the last AL in the text, -1 if none */
+ int lastArabicPos;
+
+ /* characters after trailingWSStart are WS and are */
+ /* implicitly at the paraLevel (rule (L1)) - levels may not reflect that */
+ int trailingWSStart;
+
+ /* fields for paragraph handling */
+ int paraCount; /* set in getDirProps() */
+ int[] parasMemory = new int[1];
+ int[] paras; /* limits of paragraphs, filled in
+ ResolveExplicitLevels() or CheckExplicitLevels() */
+
+ /* for single paragraph text, we only need a tiny array of paras (no allocation) */
+ int[] simpleParas = {0};
+
+ /* fields for line reordering */
+ int runCount; /* ==-1: runs not set up yet */
+ BidiRun[] runsMemory = new BidiRun[0];
+ BidiRun[] runs;
+
+ /* for non-mixed text, we only need a tiny array of runs (no allocation) */
+ BidiRun[] simpleRuns = {new BidiRun()};
+
+ /* mapping of runs in logical order to visual order */
+ int[] logicalToVisualRunsMap;
+
+ /* flag to indicate that the map has been updated */
+ boolean isGoodLogicalToVisualRunsMap;
+
+ /* for inverse Bidi with insertion of directional marks */
+ InsertPoints insertPoints = new InsertPoints();
+
+ /* for option OPTION_REMOVE_CONTROLS */
+ int controlCount;
+
+ /*
+ * Sometimes, bit values are more appropriate
+ * to deal with directionality properties.
+ * Abbreviations in these method names refer to names
+ * used in the Bidi algorithm.
+ */
+ static int DirPropFlag(byte dir) {
+ return (1 << dir);
+ }
+
+ /*
+ * The following bit is ORed to the property of characters in paragraphs
+ * with contextual RTL direction when paraLevel is contextual.
+ */
+ static final byte CONTEXT_RTL_SHIFT = 6;
+ static final byte CONTEXT_RTL = (byte)(1<<CONTEXT_RTL_SHIFT); // 0x40
+ static byte NoContextRTL(byte dir)
+ {
+ return (byte)(dir & ~CONTEXT_RTL);
+ }
+
+ /*
+ * The following is a variant of DirProp.DirPropFlag() which ignores the
+ * CONTEXT_RTL bit.
+ */
+ static int DirPropFlagNC(byte dir) {
+ return (1<<(dir & ~CONTEXT_RTL));
+ }
+
+ static final int DirPropFlagMultiRuns = DirPropFlag((byte)31);
+
+ /* to avoid some conditional statements, use tiny constant arrays */
+ static final int DirPropFlagLR[] = { DirPropFlag(L), DirPropFlag(R) };
+ static final int DirPropFlagE[] = { DirPropFlag(LRE), DirPropFlag(RLE) };
+ static final int DirPropFlagO[] = { DirPropFlag(LRO), DirPropFlag(RLO) };
+
+ static final int DirPropFlagLR(byte level) { return DirPropFlagLR[level & 1]; }
+ static final int DirPropFlagE(byte level) { return DirPropFlagE[level & 1]; }
+ static final int DirPropFlagO(byte level) { return DirPropFlagO[level & 1]; }
+
+ /*
+ * are there any characters that are LTR?
+ */
+ static final int MASK_LTR =
+ DirPropFlag(L)|DirPropFlag(EN)|DirPropFlag(AN)|DirPropFlag(LRE)|DirPropFlag(LRO);
+
+ /*
+ * are there any characters that are RTL?
+ */
+ static final int MASK_RTL = DirPropFlag(R)|DirPropFlag(AL)|DirPropFlag(RLE)|DirPropFlag(RLO);
+
+ /* explicit embedding codes */
+ private static final int MASK_LRX = DirPropFlag(LRE)|DirPropFlag(LRO);
+ private static final int MASK_RLX = DirPropFlag(RLE)|DirPropFlag(RLO);
+ private static final int MASK_EXPLICIT = MASK_LRX|MASK_RLX|DirPropFlag(PDF);
+ private static final int MASK_BN_EXPLICIT = DirPropFlag(BN)|MASK_EXPLICIT;
+
+ /* paragraph and segment separators */
+ private static final int MASK_B_S = DirPropFlag(B)|DirPropFlag(S);
+
+ /* all types that are counted as White Space or Neutral in some steps */
+ static final int MASK_WS = MASK_B_S|DirPropFlag(WS)|MASK_BN_EXPLICIT;
+ private static final int MASK_N = DirPropFlag(ON)|MASK_WS;
+
+ /* types that are neutrals or could becomes neutrals in (Wn) */
+ private static final int MASK_POSSIBLE_N = DirPropFlag(CS)|DirPropFlag(ES)|DirPropFlag(ET)|MASK_N;
+
+ /*
+ * These types may be changed to "e",
+ * the embedding type (L or R) of the run,
+ * in the Bidi algorithm (N2)
+ */
+ static final int MASK_EMBEDDING = DirPropFlag(NSM)|MASK_POSSIBLE_N;
+
+ /*
+ * the dirProp's L and R are defined to 0 and 1 values in UCharacterDirection.java
+ */
+ private static byte GetLRFromLevel(byte level)
+ {
+ return (byte)(level & 1);
+ }
+
+ private static boolean IsDefaultLevel(byte level)
+ {
+ return ((level & INTERNAL_LEVEL_DEFAULT_LTR) == INTERNAL_LEVEL_DEFAULT_LTR);
+ }
+
+ byte GetParaLevelAt(int index)
+ {
+ return (defaultParaLevel != 0) ?
+ (byte)(dirProps[index]>>CONTEXT_RTL_SHIFT) : paraLevel;
+ }
+
+ static boolean IsBidiControlChar(int c)
+ {
+ /* check for range 0x200c to 0x200f (ZWNJ, ZWJ, LRM, RLM) or
+ 0x202a to 0x202e (LRE, RLE, PDF, LRO, RLO) */
+ return (((c & 0xfffffffc) == 0x200c) || ((c >= 0x202a) && (c <= 0x202e)));
+ }
+
+ public void verifyValidPara()
+ {
+ if (this != this.paraBidi) {
+ throw new IllegalStateException("");
+ }
+ }
+
+ public void verifyValidParaOrLine()
+ {
+ BidiBase para = this.paraBidi;
+ /* verify Para */
+ if (this == para) {
+ return;
+ }
+ /* verify Line */
+ if ((para == null) || (para != para.paraBidi)) {
+ throw new IllegalStateException();
+ }
+ }
+
+ public void verifyRange(int index, int start, int limit)
+ {
+ if (index < start || index >= limit) {
+ throw new IllegalArgumentException("Value " + index +
+ " is out of range " + start + " to " + limit);
+ }
+ }
+
+ public void verifyIndex(int index, int start, int limit)
+ {
+ if (index < start || index >= limit) {
+ throw new ArrayIndexOutOfBoundsException("Index " + index +
+ " is out of range " + start + " to " + limit);
+ }
+ }
+
+ /**
+ * Allocate a <code>Bidi</code> object with preallocated memory
+ * for internal structures.
+ * This method provides a <code>Bidi</code> object like the default constructor
+ * but it also preallocates memory for internal structures
+ * according to the sizings supplied by the caller.<p>
+ * The preallocation can be limited to some of the internal memory
+ * by setting some values to 0 here. That means that if, e.g.,
+ * <code>maxRunCount</code> cannot be reasonably predetermined and should not
+ * be set to <code>maxLength</code> (the only failproof value) to avoid
+ * wasting memory, then <code>maxRunCount</code> could be set to 0 here
+ * and the internal structures that are associated with it will be allocated
+ * on demand, just like with the default constructor.
+ *
+ * @param maxLength is the maximum text or line length that internal memory
+ * will be preallocated for. An attempt to associate this object with a
+ * longer text will fail, unless this value is 0, which leaves the allocation
+ * up to the implementation.
+ *
+ * @param maxRunCount is the maximum anticipated number of same-level runs
+ * that internal memory will be preallocated for. An attempt to access
+ * visual runs on an object that was not preallocated for as many runs
+ * as the text was actually resolved to will fail,
+ * unless this value is 0, which leaves the allocation up to the implementation.<br><br>
+ * The number of runs depends on the actual text and maybe anywhere between
+ * 1 and <code>maxLength</code>. It is typically small.
+ *
+ * @throws IllegalArgumentException if maxLength or maxRunCount is less than 0
+ * @stable ICU 3.8
+ */
+ public BidiBase(int maxLength, int maxRunCount)
+ {
+ /* check the argument values */
+ if (maxLength < 0 || maxRunCount < 0) {
+ throw new IllegalArgumentException();
+ }
+
+ /* reset the object, all reference variables null, all flags false,
+ all sizes 0.
+ In fact, we don't need to do anything, since class members are
+ initialized as zero when an instance is created.
+ */
+ /*
+ mayAllocateText = false;
+ mayAllocateRuns = false;
+ orderParagraphsLTR = false;
+ paraCount = 0;
+ runCount = 0;
+ trailingWSStart = 0;
+ flags = 0;
+ paraLevel = 0;
+ defaultParaLevel = 0;
+ direction = 0;
+ */
+ /* get Bidi properties */
+ try {
+ bdp = UBiDiProps.getSingleton();
+ }
+ catch (IOException e) {
+ throw new MissingResourceException(e.getMessage(), "(BidiProps)", "");
+ }
+
+ /* allocate memory for arrays as requested */
+ if (maxLength > 0) {
+ getInitialDirPropsMemory(maxLength);
+ getInitialLevelsMemory(maxLength);
+ } else {
+ mayAllocateText = true;
+ }
+
+ if (maxRunCount > 0) {
+ // if maxRunCount == 1, use simpleRuns[]
+ if (maxRunCount > 1) {
+ getInitialRunsMemory(maxRunCount);
+ }
+ } else {
+ mayAllocateRuns = true;
+ }
+ }
+
+ /*
+ * We are allowed to allocate memory if object==null or
+ * mayAllocate==true for each array that we need.
+ *
+ * Assume sizeNeeded>0.
+ * If object != null, then assume size > 0.
+ */
+ private Object getMemory(String label, Object array, Class arrayClass,
+ boolean mayAllocate, int sizeNeeded)
+ {
+ int len = Array.getLength(array);
+
+ /* we have at least enough memory and must not allocate */
+ if (sizeNeeded == len) {
+ return array;
+ }
+ if (!mayAllocate) {
+ /* we must not allocate */
+ if (sizeNeeded <= len) {
+ return array;
+ }
+ throw new OutOfMemoryError("Failed to allocate memory for "
+ + label);
+ }
+ /* we may try to grow or shrink */
+ /* FOOD FOR THOUGHT: when shrinking it should be possible to avoid
+ the allocation altogether and rely on this.length */
+ try {
+ return Array.newInstance(arrayClass, sizeNeeded);
+ } catch (Exception e) {
+ throw new OutOfMemoryError("Failed to allocate memory for "
+ + label);
+ }
+ }
+
+ /* helper methods for each allocated array */
+ private void getDirPropsMemory(boolean mayAllocate, int len)
+ {
+ Object array = getMemory("DirProps", dirPropsMemory, Byte.TYPE, mayAllocate, len);
+ dirPropsMemory = (byte[]) array;
+ }
+
+ void getDirPropsMemory(int len)
+ {
+ getDirPropsMemory(mayAllocateText, len);
+ }
+
+ private void getLevelsMemory(boolean mayAllocate, int len)
+ {
+ Object array = getMemory("Levels", levelsMemory, Byte.TYPE, mayAllocate, len);
+ levelsMemory = (byte[]) array;
+ }
+
+ void getLevelsMemory(int len)
+ {
+ getLevelsMemory(mayAllocateText, len);
+ }
+
+ private void getRunsMemory(boolean mayAllocate, int len)
+ {
+ Object array = getMemory("Runs", runsMemory, BidiRun.class, mayAllocate, len);
+ runsMemory = (BidiRun[]) array;
+ }
+
+ void getRunsMemory(int len)
+ {
+ getRunsMemory(mayAllocateRuns, len);
+ }
+
+ /* additional methods used by constructor - always allow allocation */
+ private void getInitialDirPropsMemory(int len)
+ {
+ getDirPropsMemory(true, len);
+ }
+
+ private void getInitialLevelsMemory(int len)
+ {
+ getLevelsMemory(true, len);
+ }
+
+ private void getInitialParasMemory(int len)
+ {
+ Object array = getMemory("Paras", parasMemory, Integer.TYPE, true, len);
+ parasMemory = (int[]) array;
+ }
+
+ private void getInitialRunsMemory(int len)
+ {
+ getRunsMemory(true, len);
+ }
+
+/* perform (P2)..(P3) ------------------------------------------------------- */
+
+ private void getDirProps()
+ {
+ int i = 0, i0, i1;
+ flags = 0; /* collect all directionalities in the text */
+ int uchar;
+ byte dirProp;
+ byte paraDirDefault = 0; /* initialize to avoid compiler warnings */
+ boolean isDefaultLevel = IsDefaultLevel(paraLevel);
+ /* for inverse Bidi, the default para level is set to RTL if there is a
+ strong R or AL character at either end of the text */
+ lastArabicPos = -1;
+ controlCount = 0;
+
+ final int NOT_CONTEXTUAL = 0; /* 0: not contextual paraLevel */
+ final int LOOKING_FOR_STRONG = 1; /* 1: looking for first strong char */
+ final int FOUND_STRONG_CHAR = 2; /* 2: found first strong char */
+
+ int state;
+ int paraStart = 0; /* index of first char in paragraph */
+ byte paraDir; /* == CONTEXT_RTL within paragraphs
+ starting with strong R char */
+ byte lastStrongDir=0; /* for default level & inverse Bidi */
+ int lastStrongLTR=0; /* for STREAMING option */
+
+ if (isDefaultLevel) {
+ paraDirDefault = ((paraLevel & 1) != 0) ? CONTEXT_RTL : 0;
+ paraDir = paraDirDefault;
+ lastStrongDir = paraDirDefault;
+ state = LOOKING_FOR_STRONG;
+ } else {
+ state = NOT_CONTEXTUAL;
+ paraDir = 0;
+ }
+ /* count paragraphs and determine the paragraph level (P2..P3) */
+ /*
+ * see comment on constant fields:
+ * the LEVEL_DEFAULT_XXX values are designed so that
+ * their low-order bit alone yields the intended default
+ */
+
+ for (i = 0; i < originalLength; /* i is incremented in the loop */) {
+ i0 = i; /* index of first code unit */
+ uchar = UTF16.charAt(text, 0, originalLength, i);
+ i += Character.charCount(uchar);
+ i1 = i - 1; /* index of last code unit, gets the directional property */
+
+ dirProp = (byte)bdp.getClass(uchar);
+
+ flags |= DirPropFlag(dirProp);
+ dirProps[i1] = (byte)(dirProp | paraDir);
+ if (i1 > i0) { /* set previous code units' properties to BN */
+ flags |= DirPropFlag(BN);
+ do {
+ dirProps[--i1] = (byte)(BN | paraDir);
+ } while (i1 > i0);
+ }
+ if (state == LOOKING_FOR_STRONG) {
+ if (dirProp == L) {
+ state = FOUND_STRONG_CHAR;
+ if (paraDir != 0) {
+ paraDir = 0;
+ for (i1 = paraStart; i1 < i; i1++) {
+ dirProps[i1] &= ~CONTEXT_RTL;
+ }
+ }
+ continue;
+ }
+ if (dirProp == R || dirProp == AL) {
+ state = FOUND_STRONG_CHAR;
+ if (paraDir == 0) {
+ paraDir = CONTEXT_RTL;
+ for (i1 = paraStart; i1 < i; i1++) {
+ dirProps[i1] |= CONTEXT_RTL;
+ }
+ }
+ continue;
+ }
+ }
+ if (dirProp == L) {
+ lastStrongDir = 0;
+ lastStrongLTR = i; /* i is index to next character */
+ }
+ else if (dirProp == R) {
+ lastStrongDir = CONTEXT_RTL;
+ }
+ else if (dirProp == AL) {
+ lastStrongDir = CONTEXT_RTL;
+ lastArabicPos = i-1;
+ }
+ else if (dirProp == B) {
+ if (i < originalLength) { /* B not last char in text */
+ if (!((uchar == (int)CR) && (text[i] == (int)LF))) {
+ paraCount++;
+ }
+ if (isDefaultLevel) {
+ state=LOOKING_FOR_STRONG;
+ paraStart = i; /* i is index to next character */
+ paraDir = paraDirDefault;
+ lastStrongDir = paraDirDefault;
+ }
+ }
+ }
+ }
+ if (isDefaultLevel) {
+ paraLevel = GetParaLevelAt(0);
+ }
+
+ /* The following line does nothing new for contextual paraLevel, but is
+ needed for absolute paraLevel. */
+ flags |= DirPropFlagLR(paraLevel);
+
+ if (orderParagraphsLTR && (flags & DirPropFlag(B)) != 0) {
+ flags |= DirPropFlag(L);
+ }
+ }
+
+ /* perform (X1)..(X9) ------------------------------------------------------- */
+
+ /* determine if the text is mixed-directional or single-directional */
+ private byte directionFromFlags() {
+ /* if the text contains AN and neutrals, then some neutrals may become RTL */
+ if (!((flags & MASK_RTL) != 0 ||
+ ((flags & DirPropFlag(AN)) != 0 &&
+ (flags & MASK_POSSIBLE_N) != 0))) {
+ return Bidi.DIRECTION_LEFT_TO_RIGHT;
+ } else if ((flags & MASK_LTR) == 0) {
+ return Bidi.DIRECTION_RIGHT_TO_LEFT;
+ } else {
+ return MIXED;
+ }
+ }
+
+ /*
+ * Resolve the explicit levels as specified by explicit embedding codes.
+ * Recalculate the flags to have them reflect the real properties
+ * after taking the explicit embeddings into account.
+ *
+ * The Bidi algorithm is designed to result in the same behavior whether embedding
+ * levels are externally specified (from "styled text", supposedly the preferred
+ * method) or set by explicit embedding codes (LRx, RLx, PDF) in the plain text.
+ * That is why (X9) instructs to remove all explicit codes (and BN).
+ * However, in a real implementation, this removal of these codes and their index
+ * positions in the plain text is undesirable since it would result in
+ * reallocated, reindexed text.
+ * Instead, this implementation leaves the codes in there and just ignores them
+ * in the subsequent processing.
+ * In order to get the same reordering behavior, positions with a BN or an
+ * explicit embedding code just get the same level assigned as the last "real"
+ * character.
+ *
+ * Some implementations, not this one, then overwrite some of these
+ * directionality properties at "real" same-level-run boundaries by
+ * L or R codes so that the resolution of weak types can be performed on the
+ * entire paragraph at once instead of having to parse it once more and
+ * perform that resolution on same-level-runs.
+ * This limits the scope of the implicit rules in effectively
+ * the same way as the run limits.
+ *
+ * Instead, this implementation does not modify these codes.
+ * On one hand, the paragraph has to be scanned for same-level-runs, but
+ * on the other hand, this saves another loop to reset these codes,
+ * or saves making and modifying a copy of dirProps[].
+ *
+ *
+ * Note that (Pn) and (Xn) changed significantly from version 4 of the Bidi algorithm.
+ *
+ *
+ * Handling the stack of explicit levels (Xn):
+ *
+ * With the Bidi stack of explicit levels,
+ * as pushed with each LRE, RLE, LRO, and RLO and popped with each PDF,
+ * the explicit level must never exceed MAX_EXPLICIT_LEVEL==61.
+ *
+ * In order to have a correct push-pop semantics even in the case of overflows,
+ * there are two overflow counters:
+ * - countOver60 is incremented with each LRx at level 60
+ * - from level 60, one RLx increases the level to 61
+ * - countOver61 is incremented with each LRx and RLx at level 61
+ *
+ * Popping levels with PDF must work in the opposite order so that level 61
+ * is correct at the correct point. Underflows (too many PDFs) must be checked.
+ *
+ * This implementation assumes that MAX_EXPLICIT_LEVEL is odd.
+ */
+ private byte resolveExplicitLevels() {
+ int i = 0;
+ byte dirProp;
+ byte level = GetParaLevelAt(0);
+
+ byte dirct;
+ int paraIndex = 0;
+
+ /* determine if the text is mixed-directional or single-directional */
+ dirct = directionFromFlags();
+
+ /* we may not need to resolve any explicit levels, but for multiple
+ paragraphs we want to loop on all chars to set the para boundaries */
+ if ((dirct != MIXED) && (paraCount == 1)) {
+ /* not mixed directionality: levels don't matter - trailingWSStart will be 0 */
+ } else if ((paraCount == 1) &&
+ ((flags & MASK_EXPLICIT) == 0)) {
+ /* mixed, but all characters are at the same embedding level */
+ /* or we are in "inverse Bidi" */
+ /* and we don't have contextual multiple paragraphs with some B char */
+ /* set all levels to the paragraph level */
+ for (i = 0; i < length; ++i) {
+ levels[i] = level;
+ }
+ } else {
+ /* continue to perform (Xn) */
+
+ /* (X1) level is set for all codes, embeddingLevel keeps track of the push/pop operations */
+ /* both variables may carry the LEVEL_OVERRIDE flag to indicate the override status */
+ byte embeddingLevel = level;
+ byte newLevel;
+ byte stackTop = 0;
+
+ byte[] stack = new byte[MAX_EXPLICIT_LEVEL]; /* we never push anything >=MAX_EXPLICIT_LEVEL */
+ int countOver60 = 0;
+ int countOver61 = 0; /* count overflows of explicit levels */
+
+ /* recalculate the flags */
+ flags = 0;
+
+ for (i = 0; i < length; ++i) {
+ dirProp = NoContextRTL(dirProps[i]);
+ switch(dirProp) {
+ case LRE:
+ case LRO:
+ /* (X3, X5) */
+ newLevel = (byte)((embeddingLevel+2) & ~(INTERNAL_LEVEL_OVERRIDE | 1)); /* least greater even level */
+ if (newLevel <= MAX_EXPLICIT_LEVEL) {
+ stack[stackTop] = embeddingLevel;
+ ++stackTop;
+ embeddingLevel = newLevel;
+ if (dirProp == LRO) {
+ embeddingLevel |= INTERNAL_LEVEL_OVERRIDE;
+ }
+ /* we don't need to set LEVEL_OVERRIDE off for LRE
+ since this has already been done for newLevel which is
+ the source for embeddingLevel.
+ */
+ } else if ((embeddingLevel & ~INTERNAL_LEVEL_OVERRIDE) == MAX_EXPLICIT_LEVEL) {
+ ++countOver61;
+ } else /* (embeddingLevel & ~INTERNAL_LEVEL_OVERRIDE) == MAX_EXPLICIT_LEVEL-1 */ {
+ ++countOver60;
+ }
+ flags |= DirPropFlag(BN);
+ break;
+ case RLE:
+ case RLO:
+ /* (X2, X4) */
+ newLevel=(byte)(((embeddingLevel & ~INTERNAL_LEVEL_OVERRIDE) + 1) | 1); /* least greater odd level */
+ if (newLevel<=MAX_EXPLICIT_LEVEL) {
+ stack[stackTop] = embeddingLevel;
+ ++stackTop;
+ embeddingLevel = newLevel;
+ if (dirProp == RLO) {
+ embeddingLevel |= INTERNAL_LEVEL_OVERRIDE;
+ }
+ /* we don't need to set LEVEL_OVERRIDE off for RLE
+ since this has already been done for newLevel which is
+ the source for embeddingLevel.
+ */
+ } else {
+ ++countOver61;
+ }
+ flags |= DirPropFlag(BN);
+ break;
+ case PDF:
+ /* (X7) */
+ /* handle all the overflow cases first */
+ if (countOver61 > 0) {
+ --countOver61;
+ } else if (countOver60 > 0 && (embeddingLevel & ~INTERNAL_LEVEL_OVERRIDE) != MAX_EXPLICIT_LEVEL) {
+ /* handle LRx overflows from level 60 */
+ --countOver60;
+ } else if (stackTop > 0) {
+ /* this is the pop operation; it also pops level 61 while countOver60>0 */
+ --stackTop;
+ embeddingLevel = stack[stackTop];
+ /* } else { (underflow) */
+ }
+ flags |= DirPropFlag(BN);
+ break;
+ case B:
+ stackTop = 0;
+ countOver60 = 0;
+ countOver61 = 0;
+ level = GetParaLevelAt(i);
+ if ((i + 1) < length) {
+ embeddingLevel = GetParaLevelAt(i+1);
+ if (!((text[i] == CR) && (text[i + 1] == LF))) {
+ paras[paraIndex++] = i+1;
+ }
+ }
+ flags |= DirPropFlag(B);
+ break;
+ case BN:
+ /* BN, LRE, RLE, and PDF are supposed to be removed (X9) */
+ /* they will get their levels set correctly in adjustWSLevels() */
+ flags |= DirPropFlag(BN);
+ break;
+ default:
+ /* all other types get the "real" level */
+ if (level != embeddingLevel) {
+ level = embeddingLevel;
+ if ((level & INTERNAL_LEVEL_OVERRIDE) != 0) {
+ flags |= DirPropFlagO(level) | DirPropFlagMultiRuns;
+ } else {
+ flags |= DirPropFlagE(level) | DirPropFlagMultiRuns;
+ }
+ }
+ if ((level & INTERNAL_LEVEL_OVERRIDE) == 0) {
+ flags |= DirPropFlag(dirProp);
+ }
+ break;
+ }
+
+ /*
+ * We need to set reasonable levels even on BN codes and
+ * explicit codes because we will later look at same-level runs (X10).
+ */
+ levels[i] = level;
+ }
+ if ((flags & MASK_EMBEDDING) != 0) {
+ flags |= DirPropFlagLR(paraLevel);
+ }
+ if (orderParagraphsLTR && (flags & DirPropFlag(B)) != 0) {
+ flags |= DirPropFlag(L);
+ }
+
+ /* subsequently, ignore the explicit codes and BN (X9) */
+
+ /* again, determine if the text is mixed-directional or single-directional */
+ dirct = directionFromFlags();
+ }
+
+ return dirct;
+ }
+
+ /*
+ * Use a pre-specified embedding levels array:
+ *
+ * Adjust the directional properties for overrides (->LEVEL_OVERRIDE),
+ * ignore all explicit codes (X9),
+ * and check all the preset levels.
+ *
+ * Recalculate the flags to have them reflect the real properties
+ * after taking the explicit embeddings into account.
+ */
+ private byte checkExplicitLevels() {
+ byte dirProp;
+ int i;
+ this.flags = 0; /* collect all directionalities in the text */
+ byte level;
+ int paraIndex = 0;
+
+ for (i = 0; i < length; ++i) {
+ if (levels[i] == 0) {
+ levels[i] = paraLevel;
+ }
+ if (MAX_EXPLICIT_LEVEL < (levels[i]&0x7f)) {
+ if ((levels[i] & INTERNAL_LEVEL_OVERRIDE) != 0) {
+ levels[i] = (byte)(paraLevel|INTERNAL_LEVEL_OVERRIDE);
+ } else {
+ levels[i] = paraLevel;
+ }
+ }
+ level = levels[i];
+ dirProp = NoContextRTL(dirProps[i]);
+ if ((level & INTERNAL_LEVEL_OVERRIDE) != 0) {
+ /* keep the override flag in levels[i] but adjust the flags */
+ level &= ~INTERNAL_LEVEL_OVERRIDE; /* make the range check below simpler */
+ flags |= DirPropFlagO(level);
+ } else {
+ /* set the flags */
+ flags |= DirPropFlagE(level) | DirPropFlag(dirProp);
+ }
+
+ if ((level < GetParaLevelAt(i) &&
+ !((0 == level) && (dirProp == B))) ||
+ (MAX_EXPLICIT_LEVEL <level)) {
+ /* level out of bounds */
+ throw new IllegalArgumentException("level " + level +
+ " out of bounds at index " + i);
+ }
+ if ((dirProp == B) && ((i + 1) < length)) {
+ if (!((text[i] == CR) && (text[i + 1] == LF))) {
+ paras[paraIndex++] = i + 1;
+ }
+ }
+ }
+ if ((flags&MASK_EMBEDDING) != 0) {
+ flags |= DirPropFlagLR(paraLevel);
+ }
+
+ /* determine if the text is mixed-directional or single-directional */
+ return directionFromFlags();
+ }
+
+ /*********************************************************************/
+ /* The Properties state machine table */
+ /*********************************************************************/
+ /* */
+ /* All table cells are 8 bits: */
+ /* bits 0..4: next state */
+ /* bits 5..7: action to perform (if > 0) */
+ /* */
+ /* Cells may be of format "n" where n represents the next state */
+ /* (except for the rightmost column). */
+ /* Cells may also be of format "_(x,y)" where x represents an action */
+ /* to perform and y represents the next state. */
+ /* */
+ /*********************************************************************/
+ /* Definitions and type for properties state tables */
+ /*********************************************************************/
+ private static final int IMPTABPROPS_COLUMNS = 14;
+ private static final int IMPTABPROPS_RES = IMPTABPROPS_COLUMNS - 1;
+ private static short GetStateProps(short cell) {
+ return (short)(cell & 0x1f);
+ }
+ private static short GetActionProps(short cell) {
+ return (short)(cell >> 5);
+ }
+
+ private static final short groupProp[] = /* dirProp regrouped */
+ {
+ /* L R EN ES ET AN CS B S WS ON LRE LRO AL RLE RLO PDF NSM BN */
+ 0, 1, 2, 7, 8, 3, 9, 6, 5, 4, 4, 10, 10, 12, 10, 10, 10, 11, 10
+ };
+ private static final short _L = 0;
+ private static final short _R = 1;
+ private static final short _EN = 2;
+ private static final short _AN = 3;
+ private static final short _ON = 4;
+ private static final short _S = 5;
+ private static final short _B = 6; /* reduced dirProp */
+
+ /*********************************************************************/
+ /* */
+ /* PROPERTIES STATE TABLE */
+ /* */
+ /* In table impTabProps, */
+ /* - the ON column regroups ON and WS */
+ /* - the BN column regroups BN, LRE, RLE, LRO, RLO, PDF */
+ /* - the Res column is the reduced property assigned to a run */
+ /* */
+ /* Action 1: process current run1, init new run1 */
+ /* 2: init new run2 */
+ /* 3: process run1, process run2, init new run1 */
+ /* 4: process run1, set run1=run2, init new run2 */
+ /* */
+ /* Notes: */
+ /* 1) This table is used in resolveImplicitLevels(). */
+ /* 2) This table triggers actions when there is a change in the Bidi*/
+ /* property of incoming characters (action 1). */
+ /* 3) Most such property sequences are processed immediately (in */
+ /* fact, passed to processPropertySeq(). */
+ /* 4) However, numbers are assembled as one sequence. This means */
+ /* that undefined situations (like CS following digits, until */
+ /* it is known if the next char will be a digit) are held until */
+ /* following chars define them. */
+ /* Example: digits followed by CS, then comes another CS or ON; */
+ /* the digits will be processed, then the CS assigned */
+ /* as the start of an ON sequence (action 3). */
+ /* 5) There are cases where more than one sequence must be */
+ /* processed, for instance digits followed by CS followed by L: */
+ /* the digits must be processed as one sequence, and the CS */
+ /* must be processed as an ON sequence, all this before starting */
+ /* assembling chars for the opening L sequence. */
+ /* */
+ /* */
+ private static final short impTabProps[][] =
+ {
+/* L, R, EN, AN, ON, S, B, ES, ET, CS, BN, NSM, AL, Res */
+/* 0 Init */ { 1, 2, 4, 5, 7, 15, 17, 7, 9, 7, 0, 7, 3, _ON },
+/* 1 L */ { 1, 32+2, 32+4, 32+5, 32+7, 32+15, 32+17, 32+7, 32+9, 32+7, 1, 1, 32+3, _L },
+/* 2 R */ { 32+1, 2, 32+4, 32+5, 32+7, 32+15, 32+17, 32+7, 32+9, 32+7, 2, 2, 32+3, _R },
+/* 3 AL */ { 32+1, 32+2, 32+6, 32+6, 32+8, 32+16, 32+17, 32+8, 32+8, 32+8, 3, 3, 3, _R },
+/* 4 EN */ { 32+1, 32+2, 4, 32+5, 32+7, 32+15, 32+17, 64+10, 11, 64+10, 4, 4, 32+3, _EN },
+/* 5 AN */ { 32+1, 32+2, 32+4, 5, 32+7, 32+15, 32+17, 32+7, 32+9, 64+12, 5, 5, 32+3, _AN },
+/* 6 AL:EN/AN */ { 32+1, 32+2, 6, 6, 32+8, 32+16, 32+17, 32+8, 32+8, 64+13, 6, 6, 32+3, _AN },
+/* 7 ON */ { 32+1, 32+2, 32+4, 32+5, 7, 32+15, 32+17, 7, 64+14, 7, 7, 7, 32+3, _ON },
+/* 8 AL:ON */ { 32+1, 32+2, 32+6, 32+6, 8, 32+16, 32+17, 8, 8, 8, 8, 8, 32+3, _ON },
+/* 9 ET */ { 32+1, 32+2, 4, 32+5, 7, 32+15, 32+17, 7, 9, 7, 9, 9, 32+3, _ON },
+/*10 EN+ES/CS */ { 96+1, 96+2, 4, 96+5, 128+7, 96+15, 96+17, 128+7,128+14, 128+7, 10, 128+7, 96+3, _EN },
+/*11 EN+ET */ { 32+1, 32+2, 4, 32+5, 32+7, 32+15, 32+17, 32+7, 11, 32+7, 11, 11, 32+3, _EN },
+/*12 AN+CS */ { 96+1, 96+2, 96+4, 5, 128+7, 96+15, 96+17, 128+7,128+14, 128+7, 12, 128+7, 96+3, _AN },
+/*13 AL:EN/AN+CS */ { 96+1, 96+2, 6, 6, 128+8, 96+16, 96+17, 128+8, 128+8, 128+8, 13, 128+8, 96+3, _AN },
+/*14 ON+ET */ { 32+1, 32+2, 128+4, 32+5, 7, 32+15, 32+17, 7, 14, 7, 14, 14, 32+3, _ON },
+/*15 S */ { 32+1, 32+2, 32+4, 32+5, 32+7, 15, 32+17, 32+7, 32+9, 32+7, 15, 32+7, 32+3, _S },
+/*16 AL:S */ { 32+1, 32+2, 32+6, 32+6, 32+8, 16, 32+17, 32+8, 32+8, 32+8, 16, 32+8, 32+3, _S },
+/*17 B */ { 32+1, 32+2, 32+4, 32+5, 32+7, 32+15, 17, 32+7, 32+9, 32+7, 17, 32+7, 32+3, _B }
+ };
+
+ /*********************************************************************/
+ /* The levels state machine tables */
+ /*********************************************************************/
+ /* */
+ /* All table cells are 8 bits: */
+ /* bits 0..3: next state */
+ /* bits 4..7: action to perform (if > 0) */
+ /* */
+ /* Cells may be of format "n" where n represents the next state */
+ /* (except for the rightmost column). */
+ /* Cells may also be of format "_(x,y)" where x represents an action */
+ /* to perform and y represents the next state. */
+ /* */
+ /* This format limits each table to 16 states each and to 15 actions.*/
+ /* */
+ /*********************************************************************/
+ /* Definitions and type for levels state tables */
+ /*********************************************************************/
+ private static final int IMPTABLEVELS_COLUMNS = _B + 2;
+ private static final int IMPTABLEVELS_RES = IMPTABLEVELS_COLUMNS - 1;
+ private static short GetState(byte cell) { return (short)(cell & 0x0f); }
+ private static short GetAction(byte cell) { return (short)(cell >> 4); }
+
+ private static class ImpTabPair {
+ byte[][][] imptab;
+ short[][] impact;
+
+ ImpTabPair(byte[][] table1, byte[][] table2,
+ short[] act1, short[] act2) {
+ imptab = new byte[][][] {table1, table2};
+ impact = new short[][] {act1, act2};
+ }
+ }
+
+ /*********************************************************************/
+ /* */
+ /* LEVELS STATE TABLES */
+ /* */
+ /* In all levels state tables, */
+ /* - state 0 is the initial state */
+ /* - the Res column is the increment to add to the text level */
+ /* for this property sequence. */
+ /* */
+ /* The impact arrays for each table of a pair map the local action */
+ /* numbers of the table to the total list of actions. For instance, */
+ /* action 2 in a given table corresponds to the action number which */
+ /* appears in entry [2] of the impact array for that table. */
+ /* The first entry of all impact arrays must be 0. */
+ /* */
+ /* Action 1: init conditional sequence */
+ /* 2: prepend conditional sequence to current sequence */
+ /* 3: set ON sequence to new level - 1 */
+ /* 4: init EN/AN/ON sequence */
+ /* 5: fix EN/AN/ON sequence followed by R */
+ /* 6: set previous level sequence to level 2 */
+ /* */
+ /* Notes: */
+ /* 1) These tables are used in processPropertySeq(). The input */
+ /* is property sequences as determined by resolveImplicitLevels. */
+ /* 2) Most such property sequences are processed immediately */
+ /* (levels are assigned). */
+ /* 3) However, some sequences cannot be assigned a final level till */
+ /* one or more following sequences are received. For instance, */
+ /* ON following an R sequence within an even-level paragraph. */
+ /* If the following sequence is R, the ON sequence will be */
+ /* assigned basic run level+1, and so will the R sequence. */
+ /* 4) S is generally handled like ON, since its level will be fixed */
+ /* to paragraph level in adjustWSLevels(). */
+ /* */
+
+ private static final byte impTabL_DEFAULT[][] = /* Even paragraph level */
+ /* In this table, conditional sequences receive the higher possible level
+ until proven otherwise.
+ */
+ {
+ /* L, R, EN, AN, ON, S, B, Res */
+ /* 0 : init */ { 0, 1, 0, 2, 0, 0, 0, 0 },
+ /* 1 : R */ { 0, 1, 3, 3, 0x14, 0x14, 0, 1 },
+ /* 2 : AN */ { 0, 1, 0, 2, 0x15, 0x15, 0, 2 },
+ /* 3 : R+EN/AN */ { 0, 1, 3, 3, 0x14, 0x14, 0, 2 },
+ /* 4 : R+ON */ { 0x20, 1, 3, 3, 4, 4, 0x20, 1 },
+ /* 5 : AN+ON */ { 0x20, 1, 0x20, 2, 5, 5, 0x20, 1 }
+ };
+
+ private static final byte impTabR_DEFAULT[][] = /* Odd paragraph level */
+ /* In this table, conditional sequences receive the lower possible level
+ until proven otherwise.
+ */
+ {
+ /* L, R, EN, AN, ON, S, B, Res */
+ /* 0 : init */ { 1, 0, 2, 2, 0, 0, 0, 0 },
+ /* 1 : L */ { 1, 0, 1, 3, 0x14, 0x14, 0, 1 },
+ /* 2 : EN/AN */ { 1, 0, 2, 2, 0, 0, 0, 1 },
+ /* 3 : L+AN */ { 1, 0, 1, 3, 5, 5, 0, 1 },
+ /* 4 : L+ON */ { 0x21, 0, 0x21, 3, 4, 4, 0, 0 },
+ /* 5 : L+AN+ON */ { 1, 0, 1, 3, 5, 5, 0, 0 }
+ };
+
+ private static final short[] impAct0 = {0,1,2,3,4,5,6};
+
+ private static final ImpTabPair impTab_DEFAULT = new ImpTabPair(
+ impTabL_DEFAULT, impTabR_DEFAULT, impAct0, impAct0);
+
+ private static final byte impTabL_NUMBERS_SPECIAL[][] = { /* Even paragraph level */
+ /* In this table, conditional sequences receive the higher possible
+ level until proven otherwise.
+ */
+ /* L, R, EN, AN, ON, S, B, Res */
+ /* 0 : init */ { 0, 2, 1, 1, 0, 0, 0, 0 },
+ /* 1 : L+EN/AN */ { 0, 2, 1, 1, 0, 0, 0, 2 },
+ /* 2 : R */ { 0, 2, 4, 4, 0x13, 0, 0, 1 },
+ /* 3 : R+ON */ { 0x20, 2, 4, 4, 3, 3, 0x20, 1 },
+ /* 4 : R+EN/AN */ { 0, 2, 4, 4, 0x13, 0x13, 0, 2 }
+ };
+ private static final ImpTabPair impTab_NUMBERS_SPECIAL = new ImpTabPair(
+ impTabL_NUMBERS_SPECIAL, impTabR_DEFAULT, impAct0, impAct0);
+
+ private static final byte impTabL_GROUP_NUMBERS_WITH_R[][] = {
+ /* In this table, EN/AN+ON sequences receive levels as if associated with R
+ until proven that there is L or sor/eor on both sides. AN is handled like EN.
+ */
+ /* L, R, EN, AN, ON, S, B, Res */
+ /* 0 init */ { 0, 3, 0x11, 0x11, 0, 0, 0, 0 },
+ /* 1 EN/AN */ { 0x20, 3, 1, 1, 2, 0x20, 0x20, 2 },
+ /* 2 EN/AN+ON */ { 0x20, 3, 1, 1, 2, 0x20, 0x20, 1 },
+ /* 3 R */ { 0, 3, 5, 5, 0x14, 0, 0, 1 },
+ /* 4 R+ON */ { 0x20, 3, 5, 5, 4, 0x20, 0x20, 1 },
+ /* 5 R+EN/AN */ { 0, 3, 5, 5, 0x14, 0, 0, 2 }
+ };
+ private static final byte impTabR_GROUP_NUMBERS_WITH_R[][] = {
+ /* In this table, EN/AN+ON sequences receive levels as if associated with R
+ until proven that there is L on both sides. AN is handled like EN.
+ */
+ /* L, R, EN, AN, ON, S, B, Res */
+ /* 0 init */ { 2, 0, 1, 1, 0, 0, 0, 0 },
+ /* 1 EN/AN */ { 2, 0, 1, 1, 0, 0, 0, 1 },
+ /* 2 L */ { 2, 0, 0x14, 0x14, 0x13, 0, 0, 1 },
+ /* 3 L+ON */ { 0x22, 0, 4, 4, 3, 0, 0, 0 },
+ /* 4 L+EN/AN */ { 0x22, 0, 4, 4, 3, 0, 0, 1 }
+ };
+ private static final ImpTabPair impTab_GROUP_NUMBERS_WITH_R = new
+ ImpTabPair(impTabL_GROUP_NUMBERS_WITH_R,
+ impTabR_GROUP_NUMBERS_WITH_R, impAct0, impAct0);
+
+ private static final byte impTabL_INVERSE_NUMBERS_AS_L[][] = {
+ /* This table is identical to the Default LTR table except that EN and AN
+ are handled like L.
+ */
+ /* L, R, EN, AN, ON, S, B, Res */
+ /* 0 : init */ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ /* 1 : R */ { 0, 1, 0, 0, 0x14, 0x14, 0, 1 },
+ /* 2 : AN */ { 0, 1, 0, 0, 0x15, 0x15, 0, 2 },
+ /* 3 : R+EN/AN */ { 0, 1, 0, 0, 0x14, 0x14, 0, 2 },
+ /* 4 : R+ON */ { 0x20, 1, 0x20, 0x20, 4, 4, 0x20, 1 },
+ /* 5 : AN+ON */ { 0x20, 1, 0x20, 0x20, 5, 5, 0x20, 1 }
+ };
+ private static final byte impTabR_INVERSE_NUMBERS_AS_L[][] = {
+ /* This table is identical to the Default RTL table except that EN and AN
+ are handled like L.
+ */
+ /* L, R, EN, AN, ON, S, B, Res */
+ /* 0 : init */ { 1, 0, 1, 1, 0, 0, 0, 0 },
+ /* 1 : L */ { 1, 0, 1, 1, 0x14, 0x14, 0, 1 },
+ /* 2 : EN/AN */ { 1, 0, 1, 1, 0, 0, 0, 1 },
+ /* 3 : L+AN */ { 1, 0, 1, 1, 5, 5, 0, 1 },
+ /* 4 : L+ON */ { 0x21, 0, 0x21, 0x21, 4, 4, 0, 0 },
+ /* 5 : L+AN+ON */ { 1, 0, 1, 1, 5, 5, 0, 0 }
+ };
+ private static final ImpTabPair impTab_INVERSE_NUMBERS_AS_L = new ImpTabPair
+ (impTabL_INVERSE_NUMBERS_AS_L, impTabR_INVERSE_NUMBERS_AS_L,
+ impAct0, impAct0);
+
+ private static final byte impTabR_INVERSE_LIKE_DIRECT[][] = { /* Odd paragraph level */
+ /* In this table, conditional sequences receive the lower possible level
+ until proven otherwise.
+ */
+ /* L, R, EN, AN, ON, S, B, Res */
+ /* 0 : init */ { 1, 0, 2, 2, 0, 0, 0, 0 },
+ /* 1 : L */ { 1, 0, 1, 2, 0x13, 0x13, 0, 1 },
+ /* 2 : EN/AN */ { 1, 0, 2, 2, 0, 0, 0, 1 },
+ /* 3 : L+ON */ { 0x21, 0x30, 6, 4, 3, 3, 0x30, 0 },
+ /* 4 : L+ON+AN */ { 0x21, 0x30, 6, 4, 5, 5, 0x30, 3 },
+ /* 5 : L+AN+ON */ { 0x21, 0x30, 6, 4, 5, 5, 0x30, 2 },
+ /* 6 : L+ON+EN */ { 0x21, 0x30, 6, 4, 3, 3, 0x30, 1 }
+ };
+ private static final short[] impAct1 = {0,1,11,12};
+ private static final ImpTabPair impTab_INVERSE_LIKE_DIRECT = new ImpTabPair(
+ impTabL_DEFAULT, impTabR_INVERSE_LIKE_DIRECT, impAct0, impAct1);
+
+ private static final byte impTabL_INVERSE_LIKE_DIRECT_WITH_MARKS[][] = {
+ /* The case handled in this table is (visually): R EN L
+ */
+ /* L, R, EN, AN, ON, S, B, Res */
+ /* 0 : init */ { 0, 0x63, 0, 1, 0, 0, 0, 0 },
+ /* 1 : L+AN */ { 0, 0x63, 0, 1, 0x12, 0x30, 0, 4 },
+ /* 2 : L+AN+ON */ { 0x20, 0x63, 0x20, 1, 2, 0x30, 0x20, 3 },
+ /* 3 : R */ { 0, 0x63, 0x55, 0x56, 0x14, 0x30, 0, 3 },
+ /* 4 : R+ON */ { 0x30, 0x43, 0x55, 0x56, 4, 0x30, 0x30, 3 },
+ /* 5 : R+EN */ { 0x30, 0x43, 5, 0x56, 0x14, 0x30, 0x30, 4 },
+ /* 6 : R+AN */ { 0x30, 0x43, 0x55, 6, 0x14, 0x30, 0x30, 4 }
+ };
+ private static final byte impTabR_INVERSE_LIKE_DIRECT_WITH_MARKS[][] = {
+ /* The cases handled in this table are (visually): R EN L
+ R L AN L
+ */
+ /* L, R, EN, AN, ON, S, B, Res */
+ /* 0 : init */ { 0x13, 0, 1, 1, 0, 0, 0, 0 },
+ /* 1 : R+EN/AN */ { 0x23, 0, 1, 1, 2, 0x40, 0, 1 },
+ /* 2 : R+EN/AN+ON */ { 0x23, 0, 1, 1, 2, 0x40, 0, 0 },
+ /* 3 : L */ { 3 , 0, 3, 0x36, 0x14, 0x40, 0, 1 },
+ /* 4 : L+ON */ { 0x53, 0x40, 5, 0x36, 4, 0x40, 0x40, 0 },
+ /* 5 : L+ON+EN */ { 0x53, 0x40, 5, 0x36, 4, 0x40, 0x40, 1 },
+ /* 6 : L+AN */ { 0x53, 0x40, 6, 6, 4, 0x40, 0x40, 3 }
+ };
+ private static final short impAct2[] = {0,1,7,8,9,10};
+ private static final ImpTabPair impTab_INVERSE_LIKE_DIRECT_WITH_MARKS =
+ new ImpTabPair(impTabL_INVERSE_LIKE_DIRECT_WITH_MARKS,
+ impTabR_INVERSE_LIKE_DIRECT_WITH_MARKS, impAct0, impAct2);
+
+ private static final ImpTabPair impTab_INVERSE_FOR_NUMBERS_SPECIAL = new ImpTabPair(
+ impTabL_NUMBERS_SPECIAL, impTabR_INVERSE_LIKE_DIRECT, impAct0, impAct1);
+
+ private static final byte impTabL_INVERSE_FOR_NUMBERS_SPECIAL_WITH_MARKS[][] = {
+ /* The case handled in this table is (visually): R EN L
+ */
+ /* L, R, EN, AN, ON, S, B, Res */
+ /* 0 : init */ { 0, 0x62, 1, 1, 0, 0, 0, 0 },
+ /* 1 : L+EN/AN */ { 0, 0x62, 1, 1, 0, 0x30, 0, 4 },
+ /* 2 : R */ { 0, 0x62, 0x54, 0x54, 0x13, 0x30, 0, 3 },
+ /* 3 : R+ON */ { 0x30, 0x42, 0x54, 0x54, 3, 0x30, 0x30, 3 },
+ /* 4 : R+EN/AN */ { 0x30, 0x42, 4, 4, 0x13, 0x30, 0x30, 4 }
+ };
+ private static final ImpTabPair impTab_INVERSE_FOR_NUMBERS_SPECIAL_WITH_MARKS = new
+ ImpTabPair(impTabL_INVERSE_FOR_NUMBERS_SPECIAL_WITH_MARKS,
+ impTabR_INVERSE_LIKE_DIRECT_WITH_MARKS, impAct0, impAct2);
+
+ private class LevState {
+ byte[][] impTab; /* level table pointer */
+ short[] impAct; /* action map array */
+ int startON; /* start of ON sequence */
+ int startL2EN; /* start of level 2 sequence */
+ int lastStrongRTL; /* index of last found R or AL */
+ short state; /* current state */
+ byte runLevel; /* run level before implicit solving */
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ static final int FIRSTALLOC = 10;
+ /*
+ * param pos: position where to insert
+ * param flag: one of LRM_BEFORE, LRM_AFTER, RLM_BEFORE, RLM_AFTER
+ */
+ private void addPoint(int pos, int flag)
+ {
+ Point point = new Point();
+
+ int len = insertPoints.points.length;
+ if (len == 0) {
+ insertPoints.points = new Point[FIRSTALLOC];
+ len = FIRSTALLOC;
+ }
+ if (insertPoints.size >= len) { /* no room for new point */
+ Point[] savePoints = insertPoints.points;
+ insertPoints.points = new Point[len * 2];
+ System.arraycopy(savePoints, 0, insertPoints.points, 0, len);
+ }
+ point.pos = pos;
+ point.flag = flag;
+ insertPoints.points[insertPoints.size] = point;
+ insertPoints.size++;
+ }
+
+ /* perform rules (Wn), (Nn), and (In) on a run of the text ------------------ */
+
+ /*
+ * This implementation of the (Wn) rules applies all rules in one pass.
+ * In order to do so, it needs a look-ahead of typically 1 character
+ * (except for W5: sequences of ET) and keeps track of changes
+ * in a rule Wp that affect a later Wq (p<q).
+ *
+ * The (Nn) and (In) rules are also performed in that same single loop,
+ * but effectively one iteration behind for white space.
+ *
+ * Since all implicit rules are performed in one step, it is not necessary
+ * to actually store the intermediate directional properties in dirProps[].
+ */
+
+ private void processPropertySeq(LevState levState, short _prop,
+ int start, int limit) {
+ byte cell;
+ byte[][] impTab = levState.impTab;
+ short[] impAct = levState.impAct;
+ short oldStateSeq,actionSeq;
+ byte level, addLevel;
+ int start0, k;
+
+ start0 = start; /* save original start position */
+ oldStateSeq = levState.state;
+ cell = impTab[oldStateSeq][_prop];
+ levState.state = GetState(cell); /* isolate the new state */
+ actionSeq = impAct[GetAction(cell)]; /* isolate the action */
+ addLevel = (byte)impTab[levState.state][IMPTABLEVELS_RES];
+
+ if (actionSeq != 0) {
+ switch (actionSeq) {
+ case 1: /* init ON seq */
+ levState.startON = start0;
+ break;
+
+ case 2: /* prepend ON seq to current seq */
+ start = levState.startON;
+ break;
+
+ case 3: /* L or S after possible relevant EN/AN */
+ /* check if we had EN after R/AL */
+ if (levState.startL2EN >= 0) {
+ addPoint(levState.startL2EN, LRM_BEFORE);
+ }
+ levState.startL2EN = -1; /* not within previous if since could also be -2 */
+ /* check if we had any relevant EN/AN after R/AL */
+ if ((insertPoints.points.length == 0) ||
+ (insertPoints.size <= insertPoints.confirmed)) {
+ /* nothing, just clean up */
+ levState.lastStrongRTL = -1;
+ /* check if we have a pending conditional segment */
+ level = (byte)impTab[oldStateSeq][IMPTABLEVELS_RES];
+ if ((level & 1) != 0 && levState.startON > 0) { /* after ON */
+ start = levState.startON; /* reset to basic run level */
+ }
+ if (_prop == _S) { /* add LRM before S */
+ addPoint(start0, LRM_BEFORE);
+ insertPoints.confirmed = insertPoints.size;
+ }
+ break;
+ }
+ /* reset previous RTL cont to level for LTR text */
+ for (k = levState.lastStrongRTL + 1; k < start0; k++) {
+ /* reset odd level, leave runLevel+2 as is */
+ levels[k] = (byte)((levels[k] - 2) & ~1);
+ }
+ /* mark insert points as confirmed */
+ insertPoints.confirmed = insertPoints.size;
+ levState.lastStrongRTL = -1;
+ if (_prop == _S) { /* add LRM before S */
+ addPoint(start0, LRM_BEFORE);
+ insertPoints.confirmed = insertPoints.size;
+ }
+ break;
+
+ case 4: /* R/AL after possible relevant EN/AN */
+ /* just clean up */
+ if (insertPoints.points.length > 0)
+ /* remove all non confirmed insert points */
+ insertPoints.size = insertPoints.confirmed;
+ levState.startON = -1;
+ levState.startL2EN = -1;
+ levState.lastStrongRTL = limit - 1;
+ break;
+
+ case 5: /* EN/AN after R/AL + possible cont */
+ /* check for real AN */
+ if ((_prop == _AN) && (NoContextRTL(dirProps[start0]) == AN)) {
+ /* real AN */
+ if (levState.startL2EN == -1) { /* if no relevant EN already found */
+ /* just note the righmost digit as a strong RTL */
+ levState.lastStrongRTL = limit - 1;
+ break;
+ }
+ if (levState.startL2EN >= 0) { /* after EN, no AN */
+ addPoint(levState.startL2EN, LRM_BEFORE);
+ levState.startL2EN = -2;
+ }
+ /* note AN */
+ addPoint(start0, LRM_BEFORE);
+ break;
+ }
+ /* if first EN/AN after R/AL */
+ if (levState.startL2EN == -1) {
+ levState.startL2EN = start0;
+ }
+ break;
+
+ case 6: /* note location of latest R/AL */
+ levState.lastStrongRTL = limit - 1;
+ levState.startON = -1;
+ break;
+
+ case 7: /* L after R+ON/EN/AN */
+ /* include possible adjacent number on the left */
+ for (k = start0-1; k >= 0 && ((levels[k] & 1) == 0); k--) {
+ }
+ if (k >= 0) {
+ addPoint(k, RLM_BEFORE); /* add RLM before */
+ insertPoints.confirmed = insertPoints.size; /* confirm it */
+ }
+ levState.startON = start0;
+ break;
+
+ case 8: /* AN after L */
+ /* AN numbers between L text on both sides may be trouble. */
+ /* tentatively bracket with LRMs; will be confirmed if followed by L */
+ addPoint(start0, LRM_BEFORE); /* add LRM before */
+ addPoint(start0, LRM_AFTER); /* add LRM after */
+ break;
+
+ case 9: /* R after L+ON/EN/AN */
+ /* false alert, infirm LRMs around previous AN */
+ insertPoints.size=insertPoints.confirmed;
+ if (_prop == _S) { /* add RLM before S */
+ addPoint(start0, RLM_BEFORE);
+ insertPoints.confirmed = insertPoints.size;
+ }
+ break;
+
+ case 10: /* L after L+ON/AN */
+ level = (byte)(levState.runLevel + addLevel);
+ for (k=levState.startON; k < start0; k++) {
+ if (levels[k] < level) {
+ levels[k] = level;
+ }
+ }
+ insertPoints.confirmed = insertPoints.size; /* confirm inserts */
+ levState.startON = start0;
+ break;
+
+ case 11: /* L after L+ON+EN/AN/ON */
+ level = (byte)levState.runLevel;
+ for (k = start0-1; k >= levState.startON; k--) {
+ if (levels[k] == level+3) {
+ while (levels[k] == level+3) {
+ levels[k--] -= 2;
+ }
+ while (levels[k] == level) {
+ k--;
+ }
+ }
+ if (levels[k] == level+2) {
+ levels[k] = level;
+ continue;
+ }
+ levels[k] = (byte)(level+1);
+ }
+ break;
+
+ case 12: /* R after L+ON+EN/AN/ON */
+ level = (byte)(levState.runLevel+1);
+ for (k = start0-1; k >= levState.startON; k--) {
+ if (levels[k] > level) {
+ levels[k] -= 2;
+ }
+ }
+ break;
+
+ default: /* we should never get here */
+ throw new IllegalStateException("Internal ICU error in processPropertySeq");
+ }
+ }
+ if ((addLevel) != 0 || (start < start0)) {
+ level = (byte)(levState.runLevel + addLevel);
+ for (k = start; k < limit; k++) {
+ levels[k] = level;
+ }
+ }
+ }
+
+ private void resolveImplicitLevels(int start, int limit, short sor, short eor)
+ {
+ LevState levState = new LevState();
+ int i, start1, start2;
+ short oldStateImp, stateImp, actionImp;
+ short gprop, resProp, cell;
+ short nextStrongProp = R;
+ int nextStrongPos = -1;
+
+
+ /* check for RTL inverse Bidi mode */
+ /* FOOD FOR THOUGHT: in case of RTL inverse Bidi, it would make sense to
+ * loop on the text characters from end to start.
+ * This would need a different properties state table (at least different
+ * actions) and different levels state tables (maybe very similar to the
+ * LTR corresponding ones.
+ */
+ /* initialize for levels state table */
+ levState.startL2EN = -1; /* used for INVERSE_LIKE_DIRECT_WITH_MARKS */
+ levState.lastStrongRTL = -1; /* used for INVERSE_LIKE_DIRECT_WITH_MARKS */
+ levState.state = 0;
+ levState.runLevel = levels[start];
+ levState.impTab = impTabPair.imptab[levState.runLevel & 1];
+ levState.impAct = impTabPair.impact[levState.runLevel & 1];
+ processPropertySeq(levState, (short)sor, start, start);
+ /* initialize for property state table */
+ if (dirProps[start] == NSM) {
+ stateImp = (short)(1 + sor);
+ } else {
+ stateImp = 0;
+ }
+ start1 = start;
+ start2 = 0;
+
+ for (i = start; i <= limit; i++) {
+ if (i >= limit) {
+ gprop = eor;
+ } else {
+ short prop, prop1;
+ prop = NoContextRTL(dirProps[i]);
+ gprop = groupProp[prop];
+ }
+ oldStateImp = stateImp;
+ cell = impTabProps[oldStateImp][gprop];
+ stateImp = GetStateProps(cell); /* isolate the new state */
+ actionImp = GetActionProps(cell); /* isolate the action */
+ if ((i == limit) && (actionImp == 0)) {
+ /* there is an unprocessed sequence if its property == eor */
+ actionImp = 1; /* process the last sequence */
+ }
+ if (actionImp != 0) {
+ resProp = impTabProps[oldStateImp][IMPTABPROPS_RES];
+ switch (actionImp) {
+ case 1: /* process current seq1, init new seq1 */
+ processPropertySeq(levState, resProp, start1, i);
+ start1 = i;
+ break;
+ case 2: /* init new seq2 */
+ start2 = i;
+ break;
+ case 3: /* process seq1, process seq2, init new seq1 */
+ processPropertySeq(levState, resProp, start1, start2);
+ processPropertySeq(levState, _ON, start2, i);
+ start1 = i;
+ break;
+ case 4: /* process seq1, set seq1=seq2, init new seq2 */
+ processPropertySeq(levState, resProp, start1, start2);
+ start1 = start2;
+ start2 = i;
+ break;
+ default: /* we should never get here */
+ throw new IllegalStateException("Internal ICU error in resolveImplicitLevels");
+ }
+ }
+ }
+ /* flush possible pending sequence, e.g. ON */
+ processPropertySeq(levState, (short)eor, limit, limit);
+ }
+
+ /* perform (L1) and (X9) ---------------------------------------------------- */
+
+ /*
+ * Reset the embedding levels for some non-graphic characters (L1).
+ * This method also sets appropriate levels for BN, and
+ * explicit embedding types that are supposed to have been removed
+ * from the paragraph in (X9).
+ */
+ private void adjustWSLevels() {
+ int i;
+
+ if ((flags & MASK_WS) != 0) {
+ int flag;
+ i = trailingWSStart;
+ while (i > 0) {
+ /* reset a sequence of WS/BN before eop and B/S to the paragraph paraLevel */
+ while (i > 0 && ((flag = DirPropFlagNC(dirProps[--i])) & MASK_WS) != 0) {
+ if (orderParagraphsLTR && (flag & DirPropFlag(B)) != 0) {
+ levels[i] = 0;
+ } else {
+ levels[i] = GetParaLevelAt(i);
+ }
+ }
+
+ /* reset BN to the next character's paraLevel until B/S, which restarts above loop */
+ /* here, i+1 is guaranteed to be <length */
+ while (i > 0) {
+ flag = DirPropFlagNC(dirProps[--i]);
+ if ((flag & MASK_BN_EXPLICIT) != 0) {
+ levels[i] = levels[i + 1];
+ } else if (orderParagraphsLTR && (flag & DirPropFlag(B)) != 0) {
+ levels[i] = 0;
+ break;
+ } else if ((flag & MASK_B_S) != 0){
+ levels[i] = GetParaLevelAt(i);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ private int Bidi_Min(int x, int y) {
+ return x < y ? x : y;
+ }
+
+ private int Bidi_Abs(int x) {
+ return x >= 0 ? x : -x;
+ }
+
+ /**
+ * Perform the Unicode Bidi algorithm. It is defined in the
+ * <a href="http://www.unicode.org/unicode/reports/tr9/">Unicode Standard Annex #9</a>,
+ * version 13,
+ * also described in The Unicode Standard, Version 4.0 .<p>
+ *
+ * This method takes a piece of plain text containing one or more paragraphs,
+ * with or without externally specified embedding levels from <i>styled</i>
+ * text and computes the left-right-directionality of each character.<p>
+ *
+ * If the entire text is all of the same directionality, then
+ * the method 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.<br>
+ * 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.<p>
+ *
+ * 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.
+ *
+ * Although the text is passed here as a <code>String</code>, it is
+ * stored internally as an array of characters. Therefore the
+ * documentation will refer to indexes of the characters in the text.
+ *
+ * @param text contains the text that the Bidi algorithm will be performed
+ * on. This text can be retrieved with <code>getText()</code> or
+ * <code>getTextAsString</code>.<br>
+ *
+ * @param paraLevel specifies the default level for the text;
+ * it is typically 0 (LTR) or 1 (RTL).
+ * If the method shall determine the paragraph level from the text,
+ * then <code>paraLevel</code> can be set to
+ * either <code>LEVEL_DEFAULT_LTR</code>
+ * or <code>LEVEL_DEFAULT_RTL</code>; if the text contains multiple
+ * paragraphs, the paragraph level shall be determined separately for
+ * each paragraph; if a paragraph does not include any strongly typed
+ * character, then the desired default is used (0 for LTR or 1 for RTL).
+ * Any other value between 0 and <code>MAX_EXPLICIT_LEVEL</code>
+ * is also valid, with odd levels indicating RTL.
+ *
+ * @param embeddingLevels (in) 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
+ * <code>LEVEL_OVERRIDE</code> bit set.<br><br>
+ * Except for that bit, it must be
+ * <code>paraLevel<=embeddingLevels[]<=MAX_EXPLICIT_LEVEL</code>,
+ * with one exception: a level of zero may be specified for a
+ * paragraph separator even if <code>paraLevel>0</code> when multiple
+ * paragraphs are submitted in the same call to <code>setPara()</code>.<br><br>
+ * <strong>Caution: </strong>A reference to this array, not a copy
+ * of the levels, will be stored in the <code>Bidi</code> object;
+ * the <code>embeddingLevels</code>
+ * should not be modified to avoid unexpected results on subsequent
+ * Bidi operations. However, the <code>setPara()</code> and
+ * <code>setLine()</code> methods may modify some or all of the
+ * levels.<br><br>
+ * <strong>Note:</strong> the <code>embeddingLevels</code> array must
+ * have one entry for each character in <code>text</code>.
+ *
+ * @throws IllegalArgumentException if the values in embeddingLevels are
+ * not within the allowed range
+ *
+ * @see #LEVEL_DEFAULT_LTR
+ * @see #LEVEL_DEFAULT_RTL
+ * @see #LEVEL_OVERRIDE
+ * @see #MAX_EXPLICIT_LEVEL
+ * @stable ICU 3.8
+ */
+ void setPara(String text, byte paraLevel, byte[] embeddingLevels)
+ {
+ if (text == null) {
+ setPara(new char[0], paraLevel, embeddingLevels);
+ } else {
+ setPara(text.toCharArray(), paraLevel, embeddingLevels);
+ }
+ }
+
+ /**
+ * Perform the Unicode Bidi algorithm. It is defined in the
+ * <a href="http://www.unicode.org/unicode/reports/tr9/">Unicode Standard Annex #9</a>,
+ * version 13,
+ * also described in The Unicode Standard, Version 4.0 .<p>
+ *
+ * This method takes a piece of plain text containing one or more paragraphs,
+ * with or without externally specified embedding levels from <i>styled</i>
+ * text and computes the left-right-directionality of each character.<p>
+ *
+ * If the entire text is all of the same directionality, then
+ * the method 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.<br>
+ * 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.<p>
+ *
+ * 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.
+ *
+ * The text is stored internally as an array of characters. Therefore the
+ * documentation will refer to indexes of the characters in the text.
+ *
+ * @param chars contains the text that the Bidi algorithm will be performed
+ * on. This text can be retrieved with <code>getText()</code> or
+ * <code>getTextAsString</code>.<br>
+ *
+ * @param paraLevel specifies the default level for the text;
+ * it is typically 0 (LTR) or 1 (RTL).
+ * If the method shall determine the paragraph level from the text,
+ * then <code>paraLevel</code> can be set to
+ * either <code>LEVEL_DEFAULT_LTR</code>
+ * or <code>LEVEL_DEFAULT_RTL</code>; if the text contains multiple
+ * paragraphs, the paragraph level shall be determined separately for
+ * each paragraph; if a paragraph does not include any strongly typed
+ * character, then the desired default is used (0 for LTR or 1 for RTL).
+ * Any other value between 0 and <code>MAX_EXPLICIT_LEVEL</code>
+ * is also valid, with odd levels indicating RTL.
+ *
+ * @param embeddingLevels (in) 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
+ * <code>LEVEL_OVERRIDE</code> bit set.<br><br>
+ * Except for that bit, it must be
+ * <code>paraLevel<=embeddingLevels[]<=MAX_EXPLICIT_LEVEL</code>,
+ * with one exception: a level of zero may be specified for a
+ * paragraph separator even if <code>paraLevel>0</code> when multiple
+ * paragraphs are submitted in the same call to <code>setPara()</code>.<br><br>
+ * <strong>Caution: </strong>A reference to this array, not a copy
+ * of the levels, will be stored in the <code>Bidi</code> object;
+ * the <code>embeddingLevels</code>
+ * should not be modified to avoid unexpected results on subsequent
+ * Bidi operations. However, the <code>setPara()</code> and
+ * <code>setLine()</code> methods may modify some or all of the
+ * levels.<br><br>
+ * <strong>Note:</strong> the <code>embeddingLevels</code> array must
+ * have one entry for each character in <code>text</code>.
+ *
+ * @throws IllegalArgumentException if the values in embeddingLevels are
+ * not within the allowed range
+ *
+ * @see #LEVEL_DEFAULT_LTR
+ * @see #LEVEL_DEFAULT_RTL
+ * @see #LEVEL_OVERRIDE
+ * @see #MAX_EXPLICIT_LEVEL
+ * @stable ICU 3.8
+ */
+ public void setPara(char[] chars, byte paraLevel, byte[] embeddingLevels)
+ {
+ /* check the argument values */
+ if (paraLevel < INTERNAL_LEVEL_DEFAULT_LTR) {
+ verifyRange(paraLevel, 0, MAX_EXPLICIT_LEVEL + 1);
+ }
+ if (chars == null) {
+ chars = new char[0];
+ }
+
+ /* initialize the Bidi object */
+ this.paraBidi = null; /* mark unfinished setPara */
+ this.text = chars;
+ this.length = this.originalLength = this.resultLength = text.length;
+ this.paraLevel = paraLevel;
+ this.direction = Bidi.DIRECTION_LEFT_TO_RIGHT;
+ this.paraCount = 1;
+
+ /* Allocate zero-length arrays instead of setting to null here; then
+ * checks for null in various places can be eliminated.
+ */
+ dirProps = new byte[0];
+ levels = new byte[0];
+ runs = new BidiRun[0];
+ isGoodLogicalToVisualRunsMap = false;
+ insertPoints.size = 0; /* clean up from last call */
+ insertPoints.confirmed = 0; /* clean up from last call */
+
+ /*
+ * Save the original paraLevel if contextual; otherwise, set to 0.
+ */
+ if (IsDefaultLevel(paraLevel)) {
+ defaultParaLevel = paraLevel;
+ } else {
+ defaultParaLevel = 0;
+ }
+
+ if (length == 0) {
+ /*
+ * For an empty paragraph, create a Bidi object with the paraLevel and
+ * the flags and the direction set but without allocating zero-length arrays.
+ * There is nothing more to do.
+ */
+ if (IsDefaultLevel(paraLevel)) {
+ this.paraLevel &= 1;
+ defaultParaLevel = 0;
+ }
+ if ((this.paraLevel & 1) != 0) {
+ flags = DirPropFlag(R);
+ direction = Bidi.DIRECTION_RIGHT_TO_LEFT;
+ } else {
+ flags = DirPropFlag(L);
+ direction = Bidi.DIRECTION_LEFT_TO_RIGHT;
+ }
+
+ runCount = 0;
+ paraCount = 0;
+ paraBidi = this; /* mark successful setPara */
+ return;
+ }
+
+ runCount = -1;
+
+ /*
+ * Get the directional properties,
+ * the flags bit-set, and
+ * determine the paragraph level if necessary.
+ */
+ getDirPropsMemory(length);
+ dirProps = dirPropsMemory;
+ getDirProps();
+
+ /* the processed length may have changed if OPTION_STREAMING is set */
+ trailingWSStart = length; /* the levels[] will reflect the WS run */
+
+ /* allocate paras memory */
+ if (paraCount > 1) {
+ getInitialParasMemory(paraCount);
+ paras = parasMemory;
+ paras[paraCount - 1] = length;
+ } else {
+ /* initialize paras for single paragraph */
+ paras = simpleParas;
+ simpleParas[0] = length;
+ }
+
+ /* are explicit levels specified? */
+ if (embeddingLevels == null) {
+ /* no: determine explicit levels according to the (Xn) rules */
+ getLevelsMemory(length);
+ levels = levelsMemory;
+ direction = resolveExplicitLevels();
+ } else {
+ /* set BN for all explicit codes, check that all levels are 0 or paraLevel..MAX_EXPLICIT_LEVEL */
+ levels = embeddingLevels;
+ direction = checkExplicitLevels();
+ }
+
+ /*
+ * The steps after (X9) in the Bidi algorithm are performed only if
+ * the paragraph text has mixed directionality!
+ */
+ switch (direction) {
+ case Bidi.DIRECTION_LEFT_TO_RIGHT:
+ /* make sure paraLevel is even */
+ paraLevel = (byte)((paraLevel + 1) & ~1);
+
+ /* all levels are implicitly at paraLevel (important for getLevels()) */
+ trailingWSStart = 0;
+ break;
+ case Bidi.DIRECTION_RIGHT_TO_LEFT:
+ /* make sure paraLevel is odd */
+ paraLevel |= 1;
+
+ /* all levels are implicitly at paraLevel (important for getLevels()) */
+ trailingWSStart = 0;
+ break;
+ default:
+ this.impTabPair = impTab_DEFAULT;
+
+ /*
+ * If there are no external levels specified and there
+ * are no significant explicit level codes in the text,
+ * then we can treat the entire paragraph as one run.
+ * Otherwise, we need to perform the following rules on runs of
+ * the text with the same embedding levels. (X10)
+ * "Significant" explicit level codes are ones that actually
+ * affect non-BN characters.
+ * Examples for "insignificant" ones are empty embeddings
+ * LRE-PDF, LRE-RLE-PDF-PDF, etc.
+ */
+ if (embeddingLevels == null && paraCount <= 1 &&
+ (flags & DirPropFlagMultiRuns) == 0) {
+ resolveImplicitLevels(0, length,
+ GetLRFromLevel(GetParaLevelAt(0)),
+ GetLRFromLevel(GetParaLevelAt(length - 1)));
+ } else {
+ /* sor, eor: start and end types of same-level-run */
+ int start, limit = 0;
+ byte level, nextLevel;
+ short sor, eor;
+
+ /* determine the first sor and set eor to it because of the loop body (sor=eor there) */
+ level = GetParaLevelAt(0);
+ nextLevel = levels[0];
+ if (level < nextLevel) {
+ eor = GetLRFromLevel(nextLevel);
+ } else {
+ eor = GetLRFromLevel(level);
+ }
+
+ do {
+ /* determine start and limit of the run (end points just behind the run) */
+
+ /* the values for this run's start are the same as for the previous run's end */
+ start = limit;
+ level = nextLevel;
+ if ((start > 0) && (NoContextRTL(dirProps[start - 1]) == B)) {
+ /* except if this is a new paragraph, then set sor = para level */
+ sor = GetLRFromLevel(GetParaLevelAt(start));
+ } else {
+ sor = eor;
+ }
+
+ /* search for the limit of this run */
+ while (++limit < length && levels[limit] == level) {}
+
+ /* get the correct level of the next run */
+ if (limit < length) {
+ nextLevel = levels[limit];
+ } else {
+ nextLevel = GetParaLevelAt(length - 1);
+ }
+
+ /* determine eor from max(level, nextLevel); sor is last run's eor */
+ if ((level & ~INTERNAL_LEVEL_OVERRIDE) < (nextLevel & ~INTERNAL_LEVEL_OVERRIDE)) {
+ eor = GetLRFromLevel(nextLevel);
+ } else {
+ eor = GetLRFromLevel(level);
+ }
+
+ /* if the run consists of overridden directional types, then there
+ are no implicit types to be resolved */
+ if ((level & INTERNAL_LEVEL_OVERRIDE) == 0) {
+ resolveImplicitLevels(start, limit, sor, eor);
+ } else {
+ /* remove the LEVEL_OVERRIDE flags */
+ do {
+ levels[start++] &= ~INTERNAL_LEVEL_OVERRIDE;
+ } while (start < limit);
+ }
+ } while (limit < length);
+ }
+
+ /* reset the embedding levels for some non-graphic characters (L1), (X9) */
+ adjustWSLevels();
+
+ break;
+ }
+
+ resultLength += insertPoints.size;
+ paraBidi = this; /* mark successful setPara */
+ }
+
+ /**
+ * Perform the Unicode Bidi algorithm on a given paragraph, as defined in the
+ * <a href="http://www.unicode.org/unicode/reports/tr9/">Unicode Standard Annex #9</a>,
+ * version 13,
+ * also described in The Unicode Standard, Version 4.0 .<p>
+ *
+ * This method takes a paragraph of text and computes the
+ * left-right-directionality of each character. The text should not
+ * contain any Unicode block separators.<p>
+ *
+ * The RUN_DIRECTION attribute in the text, if present, determines the base
+ * direction (left-to-right or right-to-left). If not present, the base
+ * direction is computed using the Unicode Bidirectional Algorithm,
+ * defaulting to left-to-right if there are no strong directional characters
+ * in the text. This attribute, if present, must be applied to all the text
+ * in the paragraph.<p>
+ *
+ * The BIDI_EMBEDDING attribute in the text, if present, represents
+ * embedding level information. Negative values from -1 to -62 indicate
+ * overrides at the absolute value of the level. Positive values from 1 to
+ * 62 indicate embeddings. Where values are zero or not defined, the base
+ * embedding level as determined by the base direction is assumed.<p>
+ *
+ * The NUMERIC_SHAPING attribute in the text, if present, converts European
+ * digits to other decimal digits before running the bidi algorithm. This
+ * attribute, if present, must be applied to all the text in the paragraph.
+ *
+ * If the entire text is all of the same directionality, then
+ * the method 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.<br>
+ * 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.<p>
+ *
+ * @param paragraph a paragraph of text with optional character and
+ * paragraph attribute information
+ * @stable ICU 3.8
+ */
+ public void setPara(AttributedCharacterIterator paragraph)
+ {
+ byte paraLvl;
+ Boolean runDirection = (Boolean) paragraph.getAttribute(TextAttribute.RUN_DIRECTION);
+ NumericShaper shaper = (NumericShaper) paragraph.getAttribute(TextAttribute.NUMERIC_SHAPING);
+ if (runDirection == null) {
+ paraLvl = INTERNAL_LEVEL_DEFAULT_LTR;
+ } else {
+ paraLvl = (runDirection.equals(TextAttribute.RUN_DIRECTION_LTR)) ?
+ (byte)Bidi.DIRECTION_LEFT_TO_RIGHT : (byte)Bidi.DIRECTION_RIGHT_TO_LEFT;
+ }
+
+ byte[] lvls = null;
+ int len = paragraph.getEndIndex() - paragraph.getBeginIndex();
+ byte[] embeddingLevels = new byte[len];
+ char[] txt = new char[len];
+ int i = 0;
+ char ch = paragraph.first();
+ while (ch != AttributedCharacterIterator.DONE) {
+ txt[i] = ch;
+ Integer embedding = (Integer) paragraph.getAttribute(TextAttribute.BIDI_EMBEDDING);
+ if (embedding != null) {
+ byte level = embedding.byteValue();
+ if (level == 0) {
+ /* no-op */
+ } else if (level < 0) {
+ lvls = embeddingLevels;
+ embeddingLevels[i] = (byte)((0 - level) | INTERNAL_LEVEL_OVERRIDE);
+ } else {
+ lvls = embeddingLevels;
+ embeddingLevels[i] = level;
+ }
+ }
+ ch = paragraph.next();
+ ++i;
+ }
+
+ if (shaper != null) {
+ shaper.shape(txt, 0, len);
+ }
+ setPara(txt, paraLvl, lvls);
+ }
+
+ /**
+ * Specify whether block separators must be allocated level zero,
+ * so that successive paragraphs will progress from left to right.
+ * This method must be called before <code>setPara()</code>.
+ * Paragraph separators (B) may appear in the text. Setting them to level zero
+ * means that all paragraph separators (including one possibly appearing
+ * in the last text position) are kept in the reordered text after the text
+ * that they follow in the source text.
+ * When this feature is not enabled, a paragraph separator at the last
+ * position of the text before reordering will go to the first position
+ * of the reordered text when the paragraph level is odd.
+ *
+ * @param ordarParaLTR specifies whether paragraph separators (B) must
+ * receive level 0, so that successive paragraphs progress from left to right.
+ *
+ * @see #setPara
+ * @stable ICU 3.8
+ */
+ private void orderParagraphsLTR(boolean ordarParaLTR) {
+ orderParagraphsLTR = ordarParaLTR;
+ }
+
+ /**
+ * Get the directionality of the text.
+ *
+ * @return a value of <code>LTR</code>, <code>RTL</code> or <code>MIXED</code>
+ * that indicates if the entire text
+ * represented by this object is unidirectional,
+ * and which direction, or if it is mixed-directional.
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code> or <code>setLine</code>
+ *
+ * @see #LTR
+ * @see #RTL
+ * @see #MIXED
+ * @stable ICU 3.8
+ */
+ private byte getDirection()
+ {
+ verifyValidParaOrLine();
+ return direction;
+ }
+
+ /**
+ * Get the length of the text.
+ *
+ * @return The length of the text that the <code>Bidi</code> object was
+ * created for.
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code> or <code>setLine</code>
+ * @stable ICU 3.8
+ */
+ public int getLength()
+ {
+ verifyValidParaOrLine();
+ return originalLength;
+ }
+
+ /* paragraphs API methods ------------------------------------------------- */
+
+ /**
+ * Get the paragraph level of the text.
+ *
+ * @return The paragraph level. If there are multiple paragraphs, their
+ * level may vary if the required paraLevel is LEVEL_DEFAULT_LTR or
+ * LEVEL_DEFAULT_RTL. In that case, the level of the first paragraph
+ * is returned.
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code> or <code>setLine</code>
+ *
+ * @see #LEVEL_DEFAULT_LTR
+ * @see #LEVEL_DEFAULT_RTL
+ * @see #getParagraph
+ * @see #getParagraphByIndex
+ * @stable ICU 3.8
+ */
+ public byte getParaLevel()
+ {
+ verifyValidParaOrLine();
+ return paraLevel;
+ }
+
+ /**
+ * Get the index of a paragraph, given a position within the text.<p>
+ *
+ * @param charIndex is the index of a character within the text, in the
+ * range <code>[0..getProcessedLength()-1]</code>.
+ *
+ * @return The index of the paragraph containing the specified position,
+ * starting from 0.
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code> or <code>setLine</code>
+ * @throws IllegalArgumentException if charIndex is not within the legal range
+ *
+ * @see com.ibm.icu.text.BidiRun
+ * @see #getProcessedLength
+ * @stable ICU 3.8
+ */
+ public int getParagraphIndex(int charIndex)
+ {
+ verifyValidParaOrLine();
+ BidiBase bidi = paraBidi; /* get Para object if Line object */
+ verifyRange(charIndex, 0, bidi.length);
+ int paraIndex;
+ for (paraIndex = 0; charIndex >= bidi.paras[paraIndex]; paraIndex++) {
+ }
+ return paraIndex;
+ }
+
+ /**
+ * <code>setLine()</code> returns a <code>Bidi</code> object to
+ * contain the reordering information, especially the resolved levels,
+ * for all the characters in a line of text. This line of text is
+ * specified by referring to a <code>Bidi</code> object representing
+ * this information for a piece of text containing one or more paragraphs,
+ * and by specifying a range of indexes in this text.<p>
+ * In the new line object, the indexes will range from 0 to <code>limit-start-1</code>.<p>
+ *
+ * This is used after calling <code>setPara()</code>
+ * for a piece of text, and after line-breaking on that text.
+ * It is not necessary if each paragraph is treated as a single line.<p>
+ *
+ * After line-breaking, rules (L1) and (L2) for the treatment of
+ * trailing WS and for reordering are performed on
+ * a <code>Bidi</code> object that represents a line.<p>
+ *
+ * <strong>Important: </strong>the line <code>Bidi</code> object may
+ * reference data within the global text <code>Bidi</code> object.
+ * You should not alter the content of the global text object until
+ * you are finished using the line object.
+ *
+ * @param start is the line's first index into the text.
+ *
+ * @param limit is just behind the line's last index into the text
+ * (its last index +1).
+ *
+ * @return a <code>Bidi</code> object that will now represent a line of the text.
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code>
+ * @throws IllegalArgumentException if start and limit are not in the range
+ * <code>0<=start<limit<=getProcessedLength()</code>,
+ * or if the specified line crosses a paragraph boundary
+ *
+ * @see #setPara
+ * @see #getProcessedLength
+ * @stable ICU 3.8
+ */
+ public Bidi setLine(Bidi bidi, BidiBase bidiBase, Bidi newBidi, BidiBase newBidiBase, int start, int limit)
+ {
+ verifyValidPara();
+ verifyRange(start, 0, limit);
+ verifyRange(limit, 0, length+1);
+ if (getParagraphIndex(start) != getParagraphIndex(limit - 1)) {
+ /* the line crosses a paragraph boundary */
+ throw new IllegalArgumentException();
+ }
+
+ return BidiLine.setLine(bidi, this, newBidi, newBidiBase, start, limit);
+ }
+
+ /**
+ * Get the level for one character.
+ *
+ * @param charIndex the index of a character.
+ *
+ * @return The level for the character at <code>charIndex</code>.
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code> or <code>setLine</code>
+ * @throws IllegalArgumentException if charIndex is not in the range
+ * <code>0<=charIndex<getProcessedLength()</code>
+ *
+ * @see #getProcessedLength
+ * @stable ICU 3.8
+ */
+ public byte getLevelAt(int charIndex)
+ {
+ if (charIndex < 0 || charIndex >= length) {
+ return (byte)getBaseLevel();
+ }
+ verifyValidParaOrLine();
+ verifyRange(charIndex, 0, length);
+ return BidiLine.getLevelAt(this, charIndex);
+ }
+
+ /**
+ * Get an array of levels for each character.<p>
+ *
+ * Note that this method may allocate memory under some
+ * circumstances, unlike <code>getLevelAt()</code>.
+ *
+ * @return The levels array for the text,
+ * or <code>null</code> if an error occurs.
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code> or <code>setLine</code>
+ * @stable ICU 3.8
+ */
+ private byte[] getLevels()
+ {
+ verifyValidParaOrLine();
+ if (length <= 0) {
+ return new byte[0];
+ }
+ return BidiLine.getLevels(this);
+ }
+
+ /**
+ * Get the number of runs.
+ * This method may invoke the actual reordering on the
+ * <code>Bidi</code> object, after <code>setPara()</code>
+ * may have resolved only the levels of the text. Therefore,
+ * <code>countRuns()</code> may have to allocate memory,
+ * and may throw an exception if it fails to do so.
+ *
+ * @return The number of runs.
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code> or <code>setLine</code>
+ * @stable ICU 3.8
+ */
+ public int countRuns()
+ {
+ verifyValidParaOrLine();
+ BidiLine.getRuns(this);
+ return runCount;
+ }
+
+ /**
+ * Get a visual-to-logical index map (array) for the characters in the
+ * <code>Bidi</code> (paragraph or line) object.
+ * <p>
+ * Some values in the map may be <code>MAP_NOWHERE</code> if the
+ * corresponding text characters are Bidi marks inserted in the visual
+ * output by the option <code>OPTION_INSERT_MARKS</code>.
+ * <p>
+ * When the visual output is altered by using options of
+ * <code>writeReordered()</code> such as <code>INSERT_LRM_FOR_NUMERIC</code>,
+ * <code>KEEP_BASE_COMBINING</code>, <code>OUTPUT_REVERSE</code>,
+ * <code>REMOVE_BIDI_CONTROLS</code>, the logical positions returned may not
+ * be correct. It is advised to use, when possible, reordering options
+ * such as {@link #OPTION_INSERT_MARKS} and {@link #OPTION_REMOVE_CONTROLS}.
+ *
+ * @return an array of <code>getResultLength()</code>
+ * indexes which will reflect the reordering of the characters.<br><br>
+ * The index map will result in
+ * <code>indexMap[visualIndex]==logicalIndex</code>, where
+ * <code>indexMap</code> represents the returned array.
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code> or <code>setLine</code>
+ *
+ * @see #getLogicalMap
+ * @see #getLogicalIndex
+ * @see #getResultLength
+ * @see #MAP_NOWHERE
+ * @see #OPTION_INSERT_MARKS
+ * @see #writeReordered
+ * @stable ICU 3.8
+ */
+ private int[] getVisualMap()
+ {
+ /* countRuns() checks successful call to setPara/setLine */
+ countRuns();
+ if (resultLength <= 0) {
+ return new int[0];
+ }
+ return BidiLine.getVisualMap(this);
+ }
+
+ /**
+ * This is a convenience method that does not use a <code>Bidi</code> object.
+ * It is intended to be used for when an application has determined the levels
+ * of objects (character sequences) and just needs to have them reordered (L2).
+ * This is equivalent to using <code>getVisualMap()</code> on a
+ * <code>Bidi</code> object.
+ *
+ * @param levels is an array of levels that have been determined by
+ * the application.
+ *
+ * @return an array of <code>levels.length</code>
+ * indexes which will reflect the reordering of the characters.<p>
+ * The index map will result in
+ * <code>indexMap[visualIndex]==logicalIndex</code>, where
+ * <code>indexMap</code> represents the returned array.
+ *
+ * @stable ICU 3.8
+ */
+ private static int[] reorderVisual(byte[] levels)
+ {
+ return BidiLine.reorderVisual(levels);
+ }
+
+ /**
+ * Constant indicating that the base direction depends on the first strong
+ * directional character in the text according to the Unicode Bidirectional
+ * Algorithm. If no strong directional character is present, the base
+ * direction is left-to-right.
+ * @stable ICU 3.8
+ */
+ private static final int INTERNAL_DIRECTION_DEFAULT_LEFT_TO_RIGHT = 0x7e;
+
+ /**
+ * Constant indicating that the base direction depends on the first strong
+ * directional character in the text according to the Unicode Bidirectional
+ * Algorithm. If no strong directional character is present, the base
+ * direction is right-to-left.
+ * @stable ICU 3.8
+ */
+ private static final int INTERMAL_DIRECTION_DEFAULT_RIGHT_TO_LEFT = 0x7f;
+
+ /**
+ * Create Bidi from the given text, embedding, and direction information.
+ * The embeddings array may be null. If present, the values represent
+ * embedding level information. Negative values from -1 to -61 indicate
+ * overrides at the absolute value of the level. Positive values from 1 to
+ * 61 indicate embeddings. Where values are zero, the base embedding level
+ * as determined by the base direction is assumed.<p>
+ *
+ * Note: this constructor calls setPara() internally.
+ *
+ * @param text an array containing the paragraph of text to process.
+ * @param textStart the index into the text array of the start of the
+ * paragraph.
+ * @param embeddings an array containing embedding values for each character
+ * in the paragraph. This can be null, in which case it is assumed
+ * that there is no external embedding information.
+ * @param embStart the index into the embedding array of the start of the
+ * paragraph.
+ * @param paragraphLength the length of the paragraph in the text and
+ * embeddings arrays.
+ * @param flags a collection of flags that control the algorithm. The
+ * algorithm understands the flags DIRECTION_LEFT_TO_RIGHT,
+ * DIRECTION_RIGHT_TO_LEFT, DIRECTION_DEFAULT_LEFT_TO_RIGHT, and
+ * DIRECTION_DEFAULT_RIGHT_TO_LEFT. Other values are reserved.
+ *
+ * @throws IllegalArgumentException if the values in embeddings are
+ * not within the allowed range
+ *
+ * @see #DIRECTION_LEFT_TO_RIGHT
+ * @see #DIRECTION_RIGHT_TO_LEFT
+ * @see #DIRECTION_DEFAULT_LEFT_TO_RIGHT
+ * @see #DIRECTION_DEFAULT_RIGHT_TO_LEFT
+ * @stable ICU 3.8
+ */
+ public BidiBase(char[] text,
+ int textStart,
+ byte[] embeddings,
+ int embStart,
+ int paragraphLength,
+ int flags)
+ {
+ this(0, 0);
+ byte paraLvl;
+ switch (flags) {
+ case Bidi.DIRECTION_LEFT_TO_RIGHT:
+ default:
+ paraLvl = Bidi.DIRECTION_LEFT_TO_RIGHT;
+ break;
+ case Bidi.DIRECTION_RIGHT_TO_LEFT:
+ paraLvl = Bidi.DIRECTION_RIGHT_TO_LEFT;
+ break;
+ case Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT:
+ paraLvl = INTERNAL_LEVEL_DEFAULT_LTR;
+ break;
+ case Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT:
+ paraLvl = INTERNAL_LEVEL_DEFAULT_RTL;
+ break;
+ }
+ byte[] paraEmbeddings;
+ if (embeddings == null) {
+ paraEmbeddings = null;
+ } else {
+ paraEmbeddings = new byte[paragraphLength];
+ byte lev;
+ for (int i = 0; i < paragraphLength; i++) {
+ lev = embeddings[i + embStart];
+ if (lev < 0) {
+ lev = (byte)((- lev) | INTERNAL_LEVEL_OVERRIDE);
+ } else if (lev == 0) {
+ lev = paraLvl;
+ if (paraLvl > MAX_EXPLICIT_LEVEL) {
+ lev &= 1;
+ }
+ }
+ paraEmbeddings[i] = lev;
+ }
+ }
+ if (textStart == 0 && embStart == 0 && paragraphLength == text.length) {
+ setPara(text, paraLvl, paraEmbeddings);
+ } else {
+ char[] paraText = new char[paragraphLength];
+ System.arraycopy(text, textStart, paraText, 0, paragraphLength);
+ setPara(paraText, paraLvl, paraEmbeddings);
+ }
+ }
+
+ /**
+ * Return true if the line is not left-to-right or right-to-left. This means
+ * it either has mixed runs of left-to-right and right-to-left text, or the
+ * base direction differs from the direction of the only run of text.
+ *
+ * @return true if the line is not left-to-right or right-to-left.
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code>
+ * @stable ICU 3.8
+ */
+ public boolean isMixed()
+ {
+ return (!isLeftToRight() && !isRightToLeft());
+ }
+
+ /**
+ * Return true if the line is all left-to-right text and the base direction
+ * is left-to-right.
+ *
+ * @return true if the line is all left-to-right text and the base direction
+ * is left-to-right.
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code>
+ * @stable ICU 3.8
+ */
+ public boolean isLeftToRight()
+ {
+ return (getDirection() == Bidi.DIRECTION_LEFT_TO_RIGHT && (paraLevel & 1) == 0);
+ }
+
+ /**
+ * Return true if the line is all right-to-left text, and the base direction
+ * is right-to-left
+ *
+ * @return true if the line is all right-to-left text, and the base
+ * direction is right-to-left
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code>
+ * @stable ICU 3.8
+ */
+ public boolean isRightToLeft()
+ {
+ return (getDirection() == Bidi.DIRECTION_RIGHT_TO_LEFT && (paraLevel & 1) == 1);
+ }
+
+ /**
+ * Return true if the base direction is left-to-right
+ *
+ * @return true if the base direction is left-to-right
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code> or <code>setLine</code>
+ *
+ * @stable ICU 3.8
+ */
+ public boolean baseIsLeftToRight()
+ {
+ return (getParaLevel() == Bidi.DIRECTION_LEFT_TO_RIGHT);
+ }
+
+ /**
+ * Return the base level (0 if left-to-right, 1 if right-to-left).
+ *
+ * @return the base level
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code> or <code>setLine</code>
+ *
+ * @stable ICU 3.8
+ */
+ public int getBaseLevel()
+ {
+ return getParaLevel();
+ }
+
+ /**
+ * Compute the logical to visual run mapping
+ */
+ private void getLogicalToVisualRunsMap()
+ {
+ if (isGoodLogicalToVisualRunsMap) {
+ return;
+ }
+ int count = countRuns();
+ if ((logicalToVisualRunsMap == null) ||
+ (logicalToVisualRunsMap.length < count)) {
+ logicalToVisualRunsMap = new int[count];
+ }
+ int i;
+ long[] keys = new long[count];
+ for (i = 0; i < count; i++) {
+ keys[i] = ((long)(runs[i].start)<<32) + i;
+ }
+ Arrays.sort(keys);
+ for (i = 0; i < count; i++) {
+ logicalToVisualRunsMap[i] = (int)(keys[i] & 0x00000000FFFFFFFF);
+ }
+ keys = null;
+ isGoodLogicalToVisualRunsMap = true;
+ }
+
+ /**
+ * Return the level of the nth logical run in this line.
+ *
+ * @param run the index of the run, between 0 and <code>countRuns()-1</code>
+ *
+ * @return the level of the run
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code> or <code>setLine</code>
+ * @throws IllegalArgumentException if <code>run</code> is not in
+ * the range <code>0<=run<countRuns()</code>
+ * @stable ICU 3.8
+ */
+ public int getRunLevel(int run)
+ {
+ verifyValidParaOrLine();
+ BidiLine.getRuns(this);
+ if (runCount == 1) {
+ return getParaLevel();
+ }
+ verifyIndex(run, 0, runCount);
+ getLogicalToVisualRunsMap();
+ return runs[logicalToVisualRunsMap[run]].level;
+ }
+
+ /**
+ * 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.
+ *
+ * @param run the index of the run, between 0 and <code>countRuns()</code>
+ *
+ * @return the start of the run
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code> or <code>setLine</code>
+ * @throws IllegalArgumentException if <code>run</code> is not in
+ * the range <code>0<=run<countRuns()</code>
+ * @stable ICU 3.8
+ */
+ public int getRunStart(int run)
+ {
+ verifyValidParaOrLine();
+ BidiLine.getRuns(this);
+ if (runCount == 1) {
+ return 0;
+ } else if (run == runCount) {
+ return length;
+ }
+ verifyIndex(run, 0, runCount);
+ getLogicalToVisualRunsMap();
+ return runs[logicalToVisualRunsMap[run]].start;
+ }
+
+ /**
+ * 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. For example, this
+ * will return the length of the line for the last run on the line.
+ *
+ * @param run the index of the run, between 0 and <code>countRuns()</code>
+ *
+ * @return the limit of the run
+ *
+ * @throws IllegalStateException if this call is not preceded by a successful
+ * call to <code>setPara</code> or <code>setLine</code>
+ * @throws IllegalArgumentException if <code>run</code> is not in
+ * the range <code>0<=run<countRuns()</code>
+ * @stable ICU 3.8
+ */
+ public int getRunLimit(int run)
+ {
+ verifyValidParaOrLine();
+ BidiLine.getRuns(this);
+ if (runCount == 1) {
+ return length;
+ }
+ verifyIndex(run, 0, runCount);
+ getLogicalToVisualRunsMap();
+ int idx = logicalToVisualRunsMap[run];
+ int len = idx == 0 ? runs[idx].limit :
+ runs[idx].limit - runs[idx-1].limit;
+ return runs[idx].start + len;
+ }
+
+ /**
+ * Return true if the specified text requires bidi analysis. If this returns
+ * false, the text will display left-to-right. Clients can then avoid
+ * constructing a Bidi object. Text in the Arabic Presentation Forms area of
+ * Unicode is presumed to already be shaped and ordered for display, and so
+ * will not cause this method to return true.
+ *
+ * @param text the text containing the characters to test
+ * @param start the start of the range of characters to test
+ * @param limit the limit of the range of characters to test
+ *
+ * @return true if the range of characters requires bidi analysis
+ *
+ * @stable ICU 3.8
+ */
+ public static boolean requiresBidi(char[] text,
+ int start,
+ int limit)
+ {
+ final int RTLMask = (1 << Bidi.DIRECTION_RIGHT_TO_LEFT |
+ 1 << AL |
+ 1 << RLE |
+ 1 << RLO |
+ 1 << AN);
+
+ if (0 > start || start > limit || limit > text.length) {
+ throw new IllegalArgumentException("Value start " + start +
+ " is out of range 0 to " + limit);
+ }
+ for (int i = start; i < limit; ++i) {
+ if (Character.isHighSurrogate(text[i]) && i < (limit-1) &&
+ Character.isLowSurrogate(text[i+1])) {
+ if (((1 << UCharacter.getDirection(Character.codePointAt(text, i))) & RTLMask) != 0) {
+ return true;
+ }
+ } else if (((1 << UCharacter.getDirection(text[i])) & RTLMask) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Reorder the objects in the array into visual order based on their levels.
+ * This is a utility method to use when you have a collection of objects
+ * representing runs of text in logical order, each run containing text at a
+ * single level. The elements at <code>index</code> from
+ * <code>objectStart</code> up to <code>objectStart + count</code> in the
+ * objects array will be reordered into visual order assuming
+ * each run of text has the level indicated by the corresponding element in
+ * the levels array (at <code>index - objectStart + levelStart</code>).
+ *
+ * @param levels an array representing the bidi level of each object
+ * @param levelStart the start position in the levels array
+ * @param objects the array of objects to be reordered into visual order
+ * @param objectStart the start position in the objects array
+ * @param count the number of objects to reorder
+ * @stable ICU 3.8
+ */
+ public static void reorderVisually(byte[] levels,
+ int levelStart,
+ Object[] objects,
+ int objectStart,
+ int count)
+ {
+ if (0 > levelStart || levels.length <= levelStart) {
+ throw new IllegalArgumentException("Value levelStart " +
+ levelStart + " is out of range 0 to " +
+ (levels.length-1));
+ }
+ if (0 > objectStart || objects.length <= objectStart) {
+ throw new IllegalArgumentException("Value objectStart " +
+ levelStart + " is out of range 0 to " +
+ (objects.length-1));
+ }
+ if (0 > count || objects.length < (objectStart+count)) {
+ throw new IllegalArgumentException("Value count " +
+ levelStart + " is out of range 0 to " +
+ (objects.length - objectStart));
+ }
+ byte[] reorderLevels = new byte[count];
+ System.arraycopy(levels, levelStart, reorderLevels, 0, count);
+ int[] indexMap = reorderVisual(reorderLevels);
+ Object[] temp = new Object[count];
+ System.arraycopy(objects, objectStart, temp, 0, count);
+ for (int i = 0; i < count; ++i) {
+ objects[objectStart + i] = temp[indexMap[i]];
+ }
+ }
+
+ /**
+ * Display the bidi internal state, used in debugging.
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer(super.toString());
+
+ buf.append("[dir: " + direction);
+ buf.append(" baselevel: " + paraLevel);
+ buf.append(" length: " + length);
+ buf.append(" runs: ");
+ if (levels == null) {
+ buf.append("null");
+ } else {
+ buf.append('[');
+ buf.append(levels[0]);
+ for (int i = 0; i < levels.length; i++) {
+ buf.append(' ');
+ buf.append(levels[i]);
+ }
+ buf.append(']');
+ }
+ buf.append(" text: [0x");
+ buf.append(Integer.toHexString(text[0]));
+ for (int i = 0; i < text.length; i++) {
+ buf.append(" 0x");
+ buf.append(Integer.toHexString(text[i]));
+ }
+ buf.append(']');
+ buf.append(']');
+
+ return buf.toString();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/text/bidi/BidiLine.java Sat Jun 13 06:43:54 2009 +0900
@@ -0,0 +1,849 @@
+/*
+ * Portions Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ *******************************************************************************
+ * (C) Copyright IBM Corp. and others, 1996-2009 - All Rights Reserved *
+ * *
+ * The original version of this source code and documentation is copyrighted *
+ * and owned by IBM, These materials are provided under terms of a License *
+ * Agreement between IBM and Sun. This technology is protected by multiple *
+ * US and International patents. This notice and attribution to IBM may not *
+ * to removed. *
+ *******************************************************************************
+ */
+/* Written by Simon Montagu, Matitiahu Allouche
+ * (ported from C code written by Markus W. Scherer)
+ */
+
+package sun.text.bidi;
+
+import java.text.Bidi;
+import java.util.Arrays;
+
+public final class BidiLine {
+
+ /*
+ * General remarks about the functions in this file:
+ *
+ * These functions deal with the aspects of potentially mixed-directional
+ * text in a single paragraph or in a line of a single paragraph
+ * which has already been processed according to
+ * the Unicode 3.0 Bidi algorithm as defined in
+ * http://www.unicode.org/unicode/reports/tr9/ , version 13,
+ * also described in The Unicode Standard, Version 4.0.1 .
+ *
+ * This means that there is a Bidi object with a levels
+ * and a dirProps array.
+ * paraLevel and direction are also set.
+ * Only if the length of the text is zero, then levels==dirProps==NULL.
+ *
+ * The overall directionality of the paragraph
+ * or line is used to bypass the reordering steps if possible.
+ * Even purely RTL text does not need reordering there because
+ * the getLogical/VisualIndex() methods can compute the
+ * index on the fly in such a case.
+ *
+ * The implementation of the access to same-level-runs and of the reordering
+ * do attempt to provide better performance and less memory usage compared to
+ * a direct implementation of especially rule (L2) with an array of
+ * one (32-bit) integer per text character.
+ *
+ * Here, the levels array is scanned as soon as necessary, and a vector of
+ * same-level-runs is created. Reordering then is done on this vector.
+ * For each run of text positions that were resolved to the same level,
+ * only 8 bytes are stored: the first text position of the run and the visual
+ * position behind the run after reordering.
+ * One sign bit is used to hold the directionality of the run.
+ * This is inefficient if there are many very short runs. If the average run
+ * length is <2, then this uses more memory.
+ *
+ * In a further attempt to save memory, the levels array is never changed
+ * after all the resolution rules (Xn, Wn, Nn, In).
+ * Many methods have to consider the field trailingWSStart:
+ * if it is less than length, then there is an implicit trailing run
+ * at the paraLevel,
+ * which is not reflected in the levels array.
+ * This allows a line Bidi object to use the same levels array as
+ * its paragraph parent object.
+ *
+ * When a Bidi object is created for a line of a paragraph, then the
+ * paragraph's levels and dirProps arrays are reused by way of setting
+ * a pointer into them, not by copying. This again saves memory and forbids to
+ * change the now shared levels for (L1).
+ */
+
+ /* handle trailing WS (L1) -------------------------------------------------- */
+
+ /*
+ * setTrailingWSStart() sets the start index for a trailing
+ * run of WS in the line. This is necessary because we do not modify
+ * the paragraph's levels array that we just point into.
+ * Using trailingWSStart is another form of performing (L1).
+ *
+ * To make subsequent operations easier, we also include the run
+ * before the WS if it is at the paraLevel - we merge the two here.
+ *
+ * This method is called only from setLine(), so paraLevel is
+ * set correctly for the line even when contextual multiple paragraphs.
+ */
+
+ static void setTrailingWSStart(BidiBase bidiBase)
+ {
+ byte[] dirProps = bidiBase.dirProps;
+ byte[] levels = bidiBase.levels;
+ int start = bidiBase.length;
+ byte paraLevel = bidiBase.paraLevel;
+
+ /* If the line is terminated by a block separator, all preceding WS etc...
+ are already set to paragraph level.
+ Setting trailingWSStart to pBidi->length will avoid changing the
+ level of B chars from 0 to paraLevel in getLevels when
+ orderParagraphsLTR==TRUE
+ */
+ if (BidiBase.NoContextRTL(dirProps[start - 1]) == BidiBase.B) {
+ bidiBase.trailingWSStart = start; /* currently == bidiBase.length */
+ return;
+ }
+ /* go backwards across all WS, BN, explicit codes */
+ while (start > 0 &&
+ (BidiBase.DirPropFlagNC(dirProps[start - 1]) & BidiBase.MASK_WS) != 0) {
+ --start;
+ }
+
+ /* if the WS run can be merged with the previous run then do so here */
+ while (start > 0 && levels[start - 1] == paraLevel) {
+ --start;
+ }
+
+ bidiBase.trailingWSStart=start;
+ }
+
+ public static Bidi setLine(Bidi bidi, BidiBase paraBidi,
+ Bidi newBidi, BidiBase newBidiBase,
+ int start, int limit) {
+ int length;
+
+ BidiBase lineBidi = newBidiBase;
+
+ /* set the values in lineBidi from its paraBidi parent */
+ /* class members are already initialized to 0 */
+ // lineBidi.paraBidi = null; /* mark unfinished setLine */
+ // lineBidi.flags = 0;
+ // lineBidi.controlCount = 0;
+
+ length = lineBidi.length = lineBidi.originalLength =
+ lineBidi.resultLength = limit - start;
+
+ lineBidi.text = new char[length];
+ System.arraycopy(paraBidi.text, start, lineBidi.text, 0, length);
+ lineBidi.paraLevel = paraBidi.GetParaLevelAt(start);
+ lineBidi.paraCount = paraBidi.paraCount;
+ lineBidi.runs = new BidiRun[0];
+ if (paraBidi.controlCount > 0) {
+ int j;
+ for (j = start; j < limit; j++) {
+ if (BidiBase.IsBidiControlChar(paraBidi.text[j])) {
+ lineBidi.controlCount++;
+ }
+ }
+ lineBidi.resultLength -= lineBidi.controlCount;
+ }
+ /* copy proper subset of DirProps */
+ lineBidi.getDirPropsMemory(length);
+ lineBidi.dirProps = lineBidi.dirPropsMemory;
+ System.arraycopy(paraBidi.dirProps, start, lineBidi.dirProps, 0,
+ length);
+ /* copy proper subset of Levels */
+ lineBidi.getLevelsMemory(length);
+ lineBidi.levels = lineBidi.levelsMemory;
+ System.arraycopy(paraBidi.levels, start, lineBidi.levels, 0,
+ length);
+ lineBidi.runCount = -1;
+
+ if (paraBidi.direction != BidiBase.MIXED) {
+ /* the parent is already trivial */
+ lineBidi.direction = paraBidi.direction;
+
+ /*
+ * The parent's levels are all either
+ * implicitly or explicitly ==paraLevel;
+ * do the same here.
+ */
+ if (paraBidi.trailingWSStart <= start) {
+ lineBidi.trailingWSStart = 0;
+ } else if (paraBidi.trailingWSStart < limit) {
+ lineBidi.trailingWSStart = paraBidi.trailingWSStart - start;
+ } else {
+ lineBidi.trailingWSStart = length;
+ }
+ } else {
+ byte[] levels = lineBidi.levels;
+ int i, trailingWSStart;
+ byte level;
+
+ setTrailingWSStart(lineBidi);
+ trailingWSStart = lineBidi.trailingWSStart;
+
+ /* recalculate lineBidi.direction */
+ if (trailingWSStart == 0) {
+ /* all levels are at paraLevel */
+ lineBidi.direction = (byte)(lineBidi.paraLevel & 1);
+ } else {
+ /* get the level of the first character */
+ level = (byte)(levels[0] & 1);
+
+ /* if there is anything of a different level, then the line
+ is mixed */
+ if (trailingWSStart < length &&
+ (lineBidi.paraLevel & 1) != level) {
+ /* the trailing WS is at paraLevel, which differs from
+ levels[0] */
+ lineBidi.direction = BidiBase.MIXED;
+ } else {
+ /* see if levels[1..trailingWSStart-1] have the same
+ direction as levels[0] and paraLevel */
+ for (i = 1; ; i++) {
+ if (i == trailingWSStart) {
+ /* the direction values match those in level */
+ lineBidi.direction = level;
+ break;
+ } else if ((levels[i] & 1) != level) {
+ lineBidi.direction = BidiBase.MIXED;
+ break;
+ }
+ }
+ }
+ }
+
+ switch(lineBidi.direction) {
+ case Bidi.DIRECTION_LEFT_TO_RIGHT:
+ /* make sure paraLevel is even */
+ lineBidi.paraLevel = (byte)
+ ((lineBidi.paraLevel + 1) & ~1);
+
+ /* all levels are implicitly at paraLevel (important for
+ getLevels()) */
+ lineBidi.trailingWSStart = 0;
+ break;
+ case Bidi.DIRECTION_RIGHT_TO_LEFT:
+ /* make sure paraLevel is odd */
+ lineBidi.paraLevel |= 1;
+
+ /* all levels are implicitly at paraLevel (important for
+ getLevels()) */
+ lineBidi.trailingWSStart = 0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ newBidiBase.paraBidi = paraBidi; /* mark successful setLine */
+ return newBidi;
+ }
+
+ static byte getLevelAt(BidiBase bidiBase, int charIndex)
+ {
+ /* return paraLevel if in the trailing WS run, otherwise the real level */
+ if (bidiBase.direction != BidiBase.MIXED || charIndex >= bidiBase.trailingWSStart) {
+ return bidiBase.GetParaLevelAt(charIndex);
+ } else {
+ return bidiBase.levels[charIndex];
+ }
+ }
+
+ static byte[] getLevels(BidiBase bidiBase)
+ {
+ int start = bidiBase.trailingWSStart;
+ int length = bidiBase.length;
+
+ if (start != length) {
+ /* the current levels array does not reflect the WS run */
+ /*
+ * After the previous if(), we know that the levels array
+ * has an implicit trailing WS run and therefore does not fully
+ * reflect itself all the levels.
+ * This must be a Bidi object for a line, and
+ * we need to create a new levels array.
+ */
+ /* bidiBase.paraLevel is ok even if contextual multiple paragraphs,
+ since bidiBase is a line object */
+ Arrays.fill(bidiBase.levels, start, length, bidiBase.paraLevel);
+
+ /* this new levels array is set for the line and reflects the WS run */
+ bidiBase.trailingWSStart = length;
+ }
+ if (length < bidiBase.levels.length) {
+ byte[] levels = new byte[length];
+ System.arraycopy(bidiBase.levels, 0, levels, 0, length);
+ return levels;
+ }
+ return bidiBase.levels;
+ }
+
+ static BidiRun getLogicalRun(BidiBase bidiBase, int logicalPosition)
+ {
+ /* this is done based on runs rather than on levels since levels have
+ a special interpretation when REORDER_RUNS_ONLY
+ */
+ BidiRun newRun = new BidiRun(), iRun;
+ getRuns(bidiBase);
+ int runCount = bidiBase.runCount;
+ int visualStart = 0, logicalLimit = 0;
+ iRun = bidiBase.runs[0];
+
+ for (int i = 0; i < runCount; i++) {
+ iRun = bidiBase.runs[i];
+ logicalLimit = iRun.start + iRun.limit - visualStart;
+ if ((logicalPosition >= iRun.start) &&
+ (logicalPosition < logicalLimit)) {
+ break;
+ }
+ visualStart = iRun.limit;
+ }
+ newRun.start = iRun.start;
+ newRun.limit = logicalLimit;
+ newRun.level = iRun.level;
+ return newRun;
+ }
+
+ /* in trivial cases there is only one trivial run; called by getRuns() */
+ private static void getSingleRun(BidiBase bidiBase, byte level) {
+ /* simple, single-run case */
+ bidiBase.runs = bidiBase.simpleRuns;
+ bidiBase.runCount = 1;
+
+ /* fill and reorder the single run */
+ bidiBase.runs[0] = new BidiRun(0, bidiBase.length, level);
+ }
+
+ /* reorder the runs array (L2) ---------------------------------------------- */
+
+ /*
+ * Reorder the same-level runs in the runs array.
+ * Here, runCount>1 and maxLevel>=minLevel>=paraLevel.
+ * All the visualStart fields=logical start before reordering.
+ * The "odd" bits are not set yet.
+ *
+ * Reordering with this data structure lends itself to some handy shortcuts:
+ *
+ * Since each run is moved but not modified, and since at the initial maxLevel
+ * each sequence of same-level runs consists of only one run each, we
+ * don't need to do anything there and can predecrement maxLevel.
+ * In many simple cases, the reordering is thus done entirely in the
+ * index mapping.
+ * Also, reordering occurs only down to the lowest odd level that occurs,
+ * which is minLevel|1. However, if the lowest level itself is odd, then
+ * in the last reordering the sequence of the runs at this level or higher
+ * will be all runs, and we don't need the elaborate loop to search for them.
+ * This is covered by ++minLevel instead of minLevel|=1 followed
+ * by an extra reorder-all after the reorder-some loop.
+ * About a trailing WS run:
+ * Such a run would need special treatment because its level is not
+ * reflected in levels[] if this is not a paragraph object.
+ * Instead, all characters from trailingWSStart on are implicitly at
+ * paraLevel.
+ * However, for all maxLevel>paraLevel, this run will never be reordered
+ * and does not need to be taken into account. maxLevel==paraLevel is only reordered
+ * if minLevel==paraLevel is odd, which is done in the extra segment.
+ * This means that for the main reordering loop we don't need to consider
+ * this run and can --runCount. If it is later part of the all-runs
+ * reordering, then runCount is adjusted accordingly.
+ */
+ private static void reorderLine(BidiBase bidiBase, byte minLevel, byte maxLevel) {
+
+ /* nothing to do? */
+ if (maxLevel<=(minLevel|1)) {
+ return;
+ }
+
+ BidiRun[] runs;
+ BidiRun tempRun;
+ byte[] levels;
+ int firstRun, endRun, limitRun, runCount;
+
+ /*
+ * Reorder only down to the lowest odd level
+ * and reorder at an odd minLevel in a separate, simpler loop.
+ * See comments above for why minLevel is always incremented.
+ */
+ ++minLevel;
+
+ runs = bidiBase.runs;
+ levels = bidiBase.levels;
+ runCount = bidiBase.runCount;
+
+ /* do not include the WS run at paraLevel<=old minLevel except in the simple loop */
+ if (bidiBase.trailingWSStart < bidiBase.length) {
+ --runCount;
+ }
+
+ while (--maxLevel >= minLevel) {
+ firstRun = 0;
+
+ /* loop for all sequences of runs */
+ for ( ; ; ) {
+ /* look for a sequence of runs that are all at >=maxLevel */
+ /* look for the first run of such a sequence */
+ while (firstRun < runCount && levels[runs[firstRun].start] < maxLevel) {
+ ++firstRun;
+ }
+ if (firstRun >= runCount) {
+ break; /* no more such runs */
+ }
+
+ /* look for the limit run of such a sequence (the run behind it) */
+ for (limitRun = firstRun; ++limitRun < runCount &&
+ levels[runs[limitRun].start]>=maxLevel; ) {}
+
+ /* Swap the entire sequence of runs from firstRun to limitRun-1. */
+ endRun = limitRun - 1;
+ while (firstRun < endRun) {
+ tempRun = runs[firstRun];
+ runs[firstRun] = runs[endRun];
+ runs[endRun] = tempRun;
+ ++firstRun;
+ --endRun;
+ }
+
+ if (limitRun == runCount) {
+ break; /* no more such runs */
+ } else {
+ firstRun = limitRun + 1;
+ }
+ }
+ }
+
+ /* now do maxLevel==old minLevel (==odd!), see above */
+ if ((minLevel & 1) == 0) {
+ firstRun = 0;
+
+ /* include the trailing WS run in this complete reordering */
+ if (bidiBase.trailingWSStart == bidiBase.length) {
+ --runCount;
+ }
+
+ /* Swap the entire sequence of all runs. (endRun==runCount) */
+ while (firstRun < runCount) {
+ tempRun = runs[firstRun];
+ runs[firstRun] = runs[runCount];
+ runs[runCount] = tempRun;
+ ++firstRun;
+ --runCount;
+ }
+ }
+ }
+
+ /* compute the runs array --------------------------------------------------- */
+
+ static int getRunFromLogicalIndex(BidiBase bidiBase, int logicalIndex) {
+ BidiRun[] runs = bidiBase.runs;
+ int runCount = bidiBase.runCount, visualStart = 0, i, length, logicalStart;
+
+ for (i = 0; i < runCount; i++) {
+ length = runs[i].limit - visualStart;
+ logicalStart = runs[i].start;
+ if ((logicalIndex >= logicalStart) && (logicalIndex < (logicalStart+length))) {
+ return i;
+ }
+ visualStart += length;
+ }
+ /* we should never get here */
+ throw new IllegalStateException("Internal ICU error in getRunFromLogicalIndex");
+ }
+
+ /*
+ * Compute the runs array from the levels array.
+ * After getRuns() returns true, runCount is guaranteed to be >0
+ * and the runs are reordered.
+ * Odd-level runs have visualStart on their visual right edge and
+ * they progress visually to the left.
+ * If option OPTION_INSERT_MARKS is set, insertRemove will contain the
+ * sum of appropriate LRM/RLM_BEFORE/AFTER flags.
+ * If option OPTION_REMOVE_CONTROLS is set, insertRemove will contain the
+ * negative number of BiDi control characters within this run.
+ */
+ static void getRuns(BidiBase bidiBase) {
+ /*
+ * This method returns immediately if the runs are already set. This
+ * includes the case of length==0 (handled in setPara)..
+ */
+ if (bidiBase.runCount >= 0) {
+ return;
+ }
+ if (bidiBase.direction != BidiBase.MIXED) {
+ /* simple, single-run case - this covers length==0 */
+ /* bidiBase.paraLevel is ok even for contextual multiple paragraphs */
+ getSingleRun(bidiBase, bidiBase.paraLevel);
+ } else /* BidiBase.MIXED, length>0 */ {
+ /* mixed directionality */
+ int length = bidiBase.length, limit;
+ byte[] levels = bidiBase.levels;
+ int i, runCount;
+ byte level = BidiBase.INTERNAL_LEVEL_DEFAULT_LTR; /* initialize with no valid level */
+ /*
+ * If there are WS characters at the end of the line
+ * and the run preceding them has a level different from
+ * paraLevel, then they will form their own run at paraLevel (L1).
+ * Count them separately.
+ * We need some special treatment for this in order to not
+ * modify the levels array which a line Bidi object shares
+ * with its paragraph parent and its other line siblings.
+ * In other words, for the trailing WS, it may be
+ * levels[]!=paraLevel but we have to treat it like it were so.
+ */
+ limit = bidiBase.trailingWSStart;
+ /* count the runs, there is at least one non-WS run, and limit>0 */
+ runCount = 0;
+ for (i = 0; i < limit; ++i) {
+ /* increment runCount at the start of each run */
+ if (levels[i] != level) {
+ ++runCount;
+ level = levels[i];
+ }
+ }
+
+ /*
+ * We don't need to see if the last run can be merged with a trailing
+ * WS run because setTrailingWSStart() would have done that.
+ */
+ if (runCount == 1 && limit == length) {
+ /* There is only one non-WS run and no trailing WS-run. */
+ getSingleRun(bidiBase, levels[0]);
+ } else /* runCount>1 || limit<length */ {
+ /* allocate and set the runs */
+ BidiRun[] runs;
+ int runIndex, start;
+ byte minLevel = BidiBase.MAX_EXPLICIT_LEVEL + 1;
+ byte maxLevel=0;
+
+ /* now, count a (non-mergeable) WS run */
+ if (limit < length) {
+ ++runCount;
+ }
+
+ /* runCount > 1 */
+ bidiBase.getRunsMemory(runCount);
+ runs = bidiBase.runsMemory;
+
+ /* set the runs */
+ /* FOOD FOR THOUGHT: this could be optimized, e.g.:
+ * 464->444, 484->444, 575->555, 595->555
+ * However, that would take longer. Check also how it would
+ * interact with BiDi control removal and inserting Marks.
+ */
+ runIndex = 0;
+
+ /* search for the run limits and initialize visualLimit values with the run lengths */
+ i = 0;
+ do {
+ /* prepare this run */
+ start = i;
+ level = levels[i];
+ if (level < minLevel) {
+ minLevel = level;
+ }
+ if (level > maxLevel) {
+ maxLevel = level;
+ }
+
+ /* look for the run limit */
+ while (++i < limit && levels[i] == level) {}
+
+ /* i is another run limit */
+ runs[runIndex] = new BidiRun(start, i - start, level);
+ ++runIndex;
+ } while (i < limit);
+
+ if (limit < length) {
+ /* there is a separate WS run */
+ runs[runIndex] = new BidiRun(limit, length - limit, bidiBase.paraLevel);
+ /* For the trailing WS run, bidiBase.paraLevel is ok even
+ if contextual multiple paragraphs. */
+ if (bidiBase.paraLevel < minLevel) {
+ minLevel = bidiBase.paraLevel;
+ }
+ }
+
+ /* set the object fields */
+ bidiBase.runs = runs;
+ bidiBase.runCount = runCount;
+
+ reorderLine(bidiBase, minLevel, maxLevel);
+
+ /* now add the direction flags and adjust the visualLimit's to be just that */
+ /* this loop will also handle the trailing WS run */
+ limit = 0;
+ for (i = 0; i < runCount; ++i) {
+ runs[i].level = levels[runs[i].start];
+ limit = (runs[i].limit += limit);
+ }
+
+ /* Set the embedding level for the trailing WS run. */
+ /* For a RTL paragraph, it will be the *first* run in visual order. */
+ /* For the trailing WS run, bidiBase.paraLevel is ok even if
+ contextual multiple paragraphs. */
+ if (runIndex < runCount) {
+ int trailingRun = ((bidiBase.paraLevel & 1) != 0)? 0 : runIndex;
+ runs[trailingRun].level = bidiBase.paraLevel;
+ }
+ }
+ }
+
+ /* handle insert LRM/RLM BEFORE/AFTER run */
+ if (bidiBase.insertPoints.size > 0) {
+ BidiBase.Point point;
+ int runIndex, ip;
+ for (ip = 0; ip < bidiBase.insertPoints.size; ip++) {
+ point = bidiBase.insertPoints.points[ip];
+ runIndex = getRunFromLogicalIndex(bidiBase, point.pos);
+ bidiBase.runs[runIndex].insertRemove |= point.flag;
+ }
+ }
+
+ /* handle remove BiDi control characters */
+ if (bidiBase.controlCount > 0) {
+ int runIndex, ic;
+ char c;
+ for (ic = 0; ic < bidiBase.length; ic++) {
+ c = bidiBase.text[ic];
+ if (BidiBase.IsBidiControlChar(c)) {
+ runIndex = getRunFromLogicalIndex(bidiBase, ic);
+ bidiBase.runs[runIndex].insertRemove--;
+ }
+ }
+ }
+ }
+
+ static int[] prepareReorder(byte[] levels, byte[] pMinLevel, byte[] pMaxLevel)
+ {
+ int start;
+ byte level, minLevel, maxLevel;
+
+ if (levels == null || levels.length <= 0) {
+ return null;
+ }
+
+ /* determine minLevel and maxLevel */
+ minLevel = BidiBase.MAX_EXPLICIT_LEVEL + 1;
+ maxLevel = 0;
+ for (start = levels.length; start>0; ) {
+ level = levels[--start];
+ if (level > BidiBase.MAX_EXPLICIT_LEVEL + 1) {
+ return null;
+ }
+ if (level < minLevel) {
+ minLevel = level;
+ }
+ if (level > maxLevel) {
+ maxLevel = level;
+ }
+ }
+ pMinLevel[0] = minLevel;
+ pMaxLevel[0] = maxLevel;
+
+ /* initialize the index map */
+ int[] indexMap = new int[levels.length];
+ for (start = levels.length; start > 0; ) {
+ --start;
+ indexMap[start] = start;
+ }
+
+ return indexMap;
+ }
+
+ static int[] reorderVisual(byte[] levels)
+ {
+ byte[] aMinLevel = new byte[1];
+ byte[] aMaxLevel = new byte[1];
+ int start, end, limit, temp;
+ byte minLevel, maxLevel;
+
+ int[] indexMap = prepareReorder(levels, aMinLevel, aMaxLevel);
+ if (indexMap == null) {
+ return null;
+ }
+
+ minLevel = aMinLevel[0];
+ maxLevel = aMaxLevel[0];
+
+ /* nothing to do? */
+ if (minLevel == maxLevel && (minLevel & 1) == 0) {
+ return indexMap;
+ }
+
+ /* reorder only down to the lowest odd level */
+ minLevel |= 1;
+
+ /* loop maxLevel..minLevel */
+ do {
+ start = 0;
+
+ /* loop for all sequences of levels to reorder at the current maxLevel */
+ for ( ; ; ) {
+ /* look for a sequence of levels that are all at >=maxLevel */
+ /* look for the first index of such a sequence */
+ while (start < levels.length && levels[start] < maxLevel) {
+ ++start;
+ }
+ if (start >= levels.length) {
+ break; /* no more such runs */
+ }
+
+ /* look for the limit of such a sequence (the index behind it) */
+ for (limit = start; ++limit < levels.length && levels[limit] >= maxLevel; ) {}
+
+ /*
+ * Swap the entire interval of indexes from start to limit-1.
+ * We don't need to swap the levels for the purpose of this
+ * algorithm: the sequence of levels that we look at does not
+ * move anyway.
+ */
+ end = limit - 1;
+ while (start < end) {
+ temp = indexMap[start];
+ indexMap[start] = indexMap[end];
+ indexMap[end] = temp;
+
+ ++start;
+ --end;
+ }
+
+ if (limit == levels.length) {
+ break; /* no more such sequences */
+ } else {
+ start = limit + 1;
+ }
+ }
+ } while (--maxLevel >= minLevel);
+
+ return indexMap;
+ }
+
+ static int[] getVisualMap(BidiBase bidiBase)
+ {
+ /* fill a visual-to-logical index map using the runs[] */
+ BidiRun[] runs = bidiBase.runs;
+ int logicalStart, visualStart, visualLimit;
+ int allocLength = bidiBase.length > bidiBase.resultLength ? bidiBase.length
+ : bidiBase.resultLength;
+ int[] indexMap = new int[allocLength];
+
+ visualStart = 0;
+ int idx = 0;
+ for (int j = 0; j < bidiBase.runCount; ++j) {
+ logicalStart = runs[j].start;
+ visualLimit = runs[j].limit;
+ if (runs[j].isEvenRun()) {
+ do { /* LTR */
+ indexMap[idx++] = logicalStart++;
+ } while (++visualStart < visualLimit);
+ } else {
+ logicalStart += visualLimit - visualStart; /* logicalLimit */
+ do { /* RTL */
+ indexMap[idx++] = --logicalStart;
+ } while (++visualStart < visualLimit);
+ }
+ /* visualStart==visualLimit; */
+ }
+
+ if (bidiBase.insertPoints.size > 0) {
+ int markFound = 0, runCount = bidiBase.runCount;
+ int insertRemove, i, j, k;
+ runs = bidiBase.runs;
+ /* count all inserted marks */
+ for (i = 0; i < runCount; i++) {
+ insertRemove = runs[i].insertRemove;
+ if ((insertRemove & (BidiBase.LRM_BEFORE|BidiBase.RLM_BEFORE)) > 0) {
+ markFound++;
+ }
+ if ((insertRemove & (BidiBase.LRM_AFTER|BidiBase.RLM_AFTER)) > 0) {
+ markFound++;
+ }
+ }
+ /* move back indexes by number of preceding marks */
+ k = bidiBase.resultLength;
+ for (i = runCount - 1; i >= 0 && markFound > 0; i--) {
+ insertRemove = runs[i].insertRemove;
+ if ((insertRemove & (BidiBase.LRM_AFTER|BidiBase.RLM_AFTER)) > 0) {
+ indexMap[--k] = BidiBase.MAP_NOWHERE;
+ markFound--;
+ }
+ visualStart = i > 0 ? runs[i-1].limit : 0;
+ for (j = runs[i].limit - 1; j >= visualStart && markFound > 0; j--) {
+ indexMap[--k] = indexMap[j];
+ }
+ if ((insertRemove & (BidiBase.LRM_BEFORE|BidiBase.RLM_BEFORE)) > 0) {
+ indexMap[--k] = BidiBase.MAP_NOWHERE;
+ markFound--;
+ }
+ }
+ }
+ else if (bidiBase.controlCount > 0) {
+ int runCount = bidiBase.runCount, logicalEnd;
+ int insertRemove, length, i, j, k, m;
+ char uchar;
+ boolean evenRun;
+ runs = bidiBase.runs;
+ visualStart = 0;
+ /* move forward indexes by number of preceding controls */
+ k = 0;
+ for (i = 0; i < runCount; i++, visualStart += length) {
+ length = runs[i].limit - visualStart;
+ insertRemove = runs[i].insertRemove;
+ /* if no control found yet, nothing to do in this run */
+ if ((insertRemove == 0) && (k == visualStart)) {
+ k += length;
+ continue;
+ }
+ /* if no control in this run */
+ if (insertRemove == 0) {
+ visualLimit = runs[i].limit;
+ for (j = visualStart; j < visualLimit; j++) {
+ indexMap[k++] = indexMap[j];
+ }
+ continue;
+ }
+ logicalStart = runs[i].start;
+ evenRun = runs[i].isEvenRun();
+ logicalEnd = logicalStart + length - 1;
+ for (j = 0; j < length; j++) {
+ m = evenRun ? logicalStart + j : logicalEnd - j;
+ uchar = bidiBase.text[m];
+ if (!BidiBase.IsBidiControlChar(uchar)) {
+ indexMap[k++] = m;
+ }
+ }
+ }
+ }
+ if (allocLength == bidiBase.resultLength) {
+ return indexMap;
+ }
+ int[] newMap = new int[bidiBase.resultLength];
+ System.arraycopy(indexMap, 0, newMap, 0, bidiBase.resultLength);
+ return newMap;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/text/bidi/BidiRun.java Sat Jun 13 06:43:54 2009 +0900
@@ -0,0 +1,124 @@
+/*
+ * Portions Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ *******************************************************************************
+ * (C) Copyright IBM Corp. and others, 1996-2009 - All Rights Reserved *
+ * *
+ * The original version of this source code and documentation is copyrighted *
+ * and owned by IBM, These materials are provided under terms of a License *
+ * Agreement between IBM and Sun. This technology is protected by multiple *
+ * US and International patents. This notice and attribution to IBM may not *
+ * to removed. *
+ *******************************************************************************
+ */
+/* Written by Simon Montagu, Matitiahu Allouche
+ * (ported from C code written by Markus W. Scherer)
+ */
+
+package sun.text.bidi;
+
+/**
+ * A BidiRun represents a sequence of characters at the same embedding level.
+ * The Bidi algorithm decomposes a piece of text into sequences of characters
+ * at the same embedding level, each such sequence is called a <quote>run</quote>.
+ *
+ * <p>A BidiRun represents such a run by storing its essential properties,
+ * but does not duplicate the characters which form the run.
+ *
+ * <p>The "limit" of the run is the position just after the
+ * last character, i.e., one more than that position.
+ *
+ * <p>This class has no public constructor, and its members cannot be
+ * modified by users.
+ *
+ * @see com.ibm.icu.text.Bidi
+ */
+public class BidiRun {
+
+ int start; /* first logical position of the run */
+ int limit; /* last visual position of the run +1 */
+ int insertRemove; /* if >0, flags for inserting LRM/RLM before/after run,
+ if <0, count of bidi controls within run */
+ byte level;
+
+ /*
+ * Default constructor
+ *
+ * Note that members start and limit of a run instance have different
+ * meanings depending whether the run is part of the runs array of a Bidi
+ * object, or if it is a reference returned by getVisualRun() or
+ * getLogicalRun().
+ * For a member of the runs array of a Bidi object,
+ * - start is the first logical position of the run in the source text.
+ * - limit is one after the last visual position of the run.
+ * For a reference returned by getLogicalRun() or getVisualRun(),
+ * - start is the first logical position of the run in the source text.
+ * - limit is one after the last logical position of the run.
+ */
+ BidiRun()
+ {
+ this(0, 0, (byte)0);
+ }
+
+ /*
+ * Constructor
+ */
+ BidiRun(int start, int limit, byte embeddingLevel)
+ {
+ this.start = start;
+ this.limit = limit;
+ this.level = embeddingLevel;
+ }
+
+ /*
+ * Copy the content of a BidiRun instance
+ */
+ void copyFrom(BidiRun run)
+ {
+ this.start = run.start;
+ this.limit = run.limit;
+ this.level = run.level;
+ this.insertRemove = run.insertRemove;
+ }
+
+ /**
+ * Get level of run
+ */
+ public byte getEmbeddingLevel()
+ {
+ return level;
+ }
+
+ /**
+ * Check if run level is even
+ * @return true if the embedding level of this run is even, i.e. it is a
+ * left-to-right run.
+ */
+ boolean isEvenRun()
+ {
+ return (level & 1) == 0;
+ }
+
+}
--- a/jdk/src/share/classes/sun/text/normalizer/UCharacter.java Thu May 28 18:11:07 2009 +0400
+++ b/jdk/src/share/classes/sun/text/normalizer/UCharacter.java Sat Jun 13 06:43:54 2009 +0900
@@ -1,5 +1,5 @@
/*
- * Portions Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Portions Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -355,7 +355,7 @@
private static int getEuropeanDigit(int ch) {
if ((ch > 0x7a && ch < 0xff21)
|| ch < 0x41 || (ch > 0x5a && ch < 0x61)
- || ch > 0xff5a || (ch > 0xff31 && ch < 0xff41)) {
+ || ch > 0xff5a || (ch > 0xff3a && ch < 0xff41)) {
return -1;
}
if (ch <= 0x7a) {
--- a/jdk/src/share/native/sun/font/bidi/cmemory.h Thu May 28 18:11:07 2009 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Portions Copyright 2000 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/*
- * (C) Copyright IBM Corp. 1998, 1999 - All Rights Reserved
- *
- * The original version of this source code and documentation is
- * copyrighted and owned by IBM. These materials are provided
- * under terms of a License Agreement between IBM and Sun.
- * This technology is protected by multiple US and International
- * patents. This notice and attribution to IBM may not be removed.
- */
-
-/*
-* File CMEMORY.H
-*
-* Contains stdlib.h/string.h memory functions
-*
-* @author Bertrand A. Damiba
-*
-* Modification History:
-*
-* Date Name Description
-* 6/20/98 Bertrand Created.
-* 05/03/99 stephen Changed from functions to macros.
-*
-*******************************************************************************
-*/
-
-#ifndef CMEMORY_H
-#define CMEMORY_H
-
-#include <stdlib.h>
-#include <string.h>
-
-#define icu_malloc(size) malloc(size)
-#define icu_realloc(buffer, size) realloc(buffer, size)
-#define icu_free(buffer) free(buffer)
-#define icu_memcpy(dst, src, size) memcpy(dst, src, size)
-#define icu_memmove(dst, src, size) memmove(dst, src, size)
-#define icu_memset(buffer, mark, size) memset(buffer, mark, size)
-#define icu_memcmp(buffer1, buffer2, size) memcmp(buffer1, buffer2,size)
-
-#endif
--- a/jdk/src/share/native/sun/font/bidi/jbidi.c Thu May 28 18:11:07 2009 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-/*
- * Portions Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/*
- * (C) Copyright IBM Corp. 2000 - 2003 - All Rights Reserved
- *
- * The original version of this source code and documentation is
- * copyrighted and owned by IBM. These materials are provided
- * under terms of a License Agreement between IBM and Sun.
- * This technology is protected by multiple US and International
- * patents. This notice and attribution to IBM may not be removed.
- */
-
-// jni interface to native bidi from java
-
-#include <stdlib.h>
-#include "jbidi.h"
-
-#define U_COMMON_IMPLEMENTATION
-#include "ubidi.h"
-#include "ubidiimp.h"
-#include "uchardir.h"
-
-static jclass g_bidi_class = 0;
-static jmethodID g_bidi_reset = 0;
-
-static void resetBidi(JNIEnv *env, jclass cls, jobject bidi, jint dir, jint level, jint len, jintArray runs, jintArray cws) {
- if (!g_bidi_class) {
- g_bidi_class = (*env)->NewGlobalRef(env, cls);
- g_bidi_reset = (*env)->GetMethodID(env, g_bidi_class, "reset", "(III[I[I)V");
- }
-
- (*env)->CallVoidMethod(env, bidi, g_bidi_reset, dir, level, len, runs, cws);
-}
-
-JNIEXPORT jint JNICALL Java_java_text_Bidi_nativeGetDirectionCode
- (JNIEnv *env, jclass cls, jint cp)
-{
- return (jint)u_getDirection((uint32_t)cp);
-}
-
-JNIEXPORT void JNICALL Java_java_text_Bidi_nativeBidiChars
- (JNIEnv *env, jclass cls, jobject jbidi, jcharArray text, jint tStart, jbyteArray embs, jint eStart, jint length, jint dir)
-{
- UErrorCode err = U_ZERO_ERROR;
- UBiDi* bidi = ubidi_openSized(length, length, &err);
- if (!U_FAILURE(err)) {
- jchar *cText = (jchar*)(*env)->GetPrimitiveArrayCritical(env, text, NULL);
- if (cText) {
- UBiDiLevel baseLevel = (UBiDiLevel)dir;
- jbyte *cEmbs = 0;
- uint8_t *cEmbsAdj = 0;
- if (embs != NULL) {
- cEmbs = (jbyte*)(*env)->GetPrimitiveArrayCritical(env, embs, NULL);
- if (cEmbs) {
- cEmbsAdj = (uint8_t*)(cEmbs + eStart);
- }
- }
- ubidi_setPara(bidi, cText + tStart, length, baseLevel, cEmbsAdj, &err);
- if (cEmbs) {
- (*env)->ReleasePrimitiveArrayCritical(env, embs, cEmbs, JNI_ABORT);
- }
-
- (*env)->ReleasePrimitiveArrayCritical(env, text, cText, JNI_ABORT);
-
- if (!U_FAILURE(err)) {
- jint resDir = (jint)ubidi_getDirection(bidi);
- jint resLevel = (jint)ubidi_getParaLevel(bidi);
- jint resRunCount = 0;
- jintArray resRuns = 0;
- jintArray resCWS = 0;
- if (resDir == UBIDI_MIXED) {
- resRunCount = (jint)ubidi_countRuns(bidi, &err);
- if (!U_FAILURE(err)) {
- if (resRunCount) {
- jint* cResRuns = (jint*)calloc(resRunCount * 2, sizeof(jint));
- if (cResRuns) {
- int32_t limit = 0;
- UBiDiLevel level;
- jint *p = cResRuns;
- while (limit < length) {
- ubidi_getLogicalRun(bidi, limit, &limit, &level);
- *p++ = (jint)limit;
- *p++ = (jint)level;
- }
-
- {
- const DirProp *dp = bidi->dirProps;
- jint ccws = 0;
- jint n = 0;
- p = cResRuns;
- do {
- if ((*(p+1) ^ resLevel) & 0x1) {
- while (n < *p) {
- if (dp[n++] == WS) {
- ++ccws;
- }
- }
- } else {
- n = *p;
- }
- p += 2;
- } while (n < length);
-
- resCWS = (*env)->NewIntArray(env, ccws);
- if (resCWS) {
- jint* cResCWS = (jint*)(*env)->GetPrimitiveArrayCritical(env, resCWS, NULL);
- if (cResCWS) {
- jint ccws = 0;
- jint n = 0;
- p = cResRuns;
- do {
- if ((*(p+1) ^ resLevel) & 0x1) {
- while (n < *p) {
- if (dp[n] == WS) {
- cResCWS[ccws++] = n;
- }
- ++n;
- }
- } else {
- n = *p;
- }
- p += 2;
- } while (n < length);
- (*env)->ReleasePrimitiveArrayCritical(env, resCWS, cResCWS, 0);
- }
- }
- }
-
- resRuns = (*env)->NewIntArray(env, resRunCount * 2);
- if (resRuns) {
- (*env)->SetIntArrayRegion(env, resRuns, 0, resRunCount * 2, cResRuns);
- }
- free(cResRuns);
- }
- }
- }
- }
-
- resetBidi(env, cls, jbidi, resDir, resLevel, length, resRuns, resCWS);
- }
- }
- ubidi_close(bidi);
- }
-}
--- a/jdk/src/share/native/sun/font/bidi/jbidi.h Thu May 28 18:11:07 2009 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Portions Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/*
- * (C) Copyright IBM Corp. 2000 - 2003 - All Rights Reserved
- *
- * The original version of this source code and documentation is
- * copyrighted and owned by IBM. These materials are provided
- * under terms of a License Agreement between IBM and Sun.
- * This technology is protected by multiple US and International
- * patents. This notice and attribution to IBM may not be removed.
- */
-
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class Bidi */
-
-#ifndef _Included_Bidi
-#define _Included_Bidi
-#ifdef __cplusplus
-extern "C" {
-#endif
-#undef Bidi_DIR_LTR
-#define Bidi_DIR_LTR 0L
-#undef Bidi_DIR_RTL
-#define Bidi_DIR_RTL 1L
-#undef Bidi_DIR_DEFAULT_LTR
-#define Bidi_DIR_DEFAULT_LTR -2L
-#undef Bidi_DIR_DEFAULT_RTL
-#define Bidi_DIR_DEFAULT_RTL -1L
-#undef Bidi_DIR_MIXED
-#define Bidi_DIR_MIXED -1L
-#undef Bidi_DIR_MIN
-#define Bidi_DIR_MIN -2L
-#undef Bidi_DIR_MAX
-#define Bidi_DIR_MAX 1L
-
-JNIEXPORT jint JNICALL Java_java_text_Bidi_nativeGetDirectionCode
- (JNIEnv *, jclass, jint);
-
-JNIEXPORT void JNICALL Java_java_text_Bidi_nativeBidiChars
- (JNIEnv *, jclass, jobject, jcharArray, jint, jbyteArray, jint, jint, jint);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
--- a/jdk/src/share/native/sun/font/bidi/ubidi.c Thu May 28 18:11:07 2009 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1433 +0,0 @@
-/*
- * Portions Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/*
- * (C) Copyright IBM Corp. 1999-2003 - All Rights Reserved
- *
- * The original version of this source code and documentation is
- * copyrighted and owned by IBM. These materials are provided
- * under terms of a License Agreement between IBM and Sun.
- * This technology is protected by multiple US and International
- * patents. This notice and attribution to IBM may not be removed.
- */
-
-/*
-*
-******************************************************************************
-* file name: ubidi.c
-* encoding: US-ASCII
-* tab size: 8 (not used)
-* indentation:4
-*
-* created on: 1999jul27
-* created by: Markus W. Scherer
-*/
-
-/* set import/export definitions */
-#ifndef U_COMMON_IMPLEMENTATION
-# define U_COMMON_IMPLEMENTATION
-#endif
-
-#include "cmemory.h"
-#include "utypes.h"
-#include "uchardir.h"
-#include "ubidi.h"
-#include "ubidiimp.h"
-
-/*
- * General implementation notes:
- *
- * Throughout the implementation, there are comments like (W2) that refer to
- * rules of the BiDi algorithm in its version 5, in this example to the second
- * rule of the resolution of weak types.
- *
- * For handling surrogate pairs, where two UChar's form one "abstract" (or UTF-32)
- * character according to UTF-16, the second UChar gets the directional property of
- * the entire character assigned, while the first one gets a BN, a boundary
- * neutral, type, which is ignored by most of the algorithm according to
- * rule (X9) and the implementation suggestions of the BiDi algorithm.
- *
- * Later, adjustWSLevels() will set the level for each BN to that of the
- * following character (UChar), which results in surrogate pairs getting the
- * same level on each of their surrogates.
- *
- * In a UTF-8 implementation, the same thing could be done: the last byte of
- * a multi-byte sequence would get the "real" property, while all previous
- * bytes of that sequence would get BN.
- *
- * It is not possible to assign all those parts of a character the same real
- * property because this would fail in the resolution of weak types with rules
- * that look at immediately surrounding types.
- *
- * As a related topic, this implementation does not remove Boundary Neutral
- * types from the input, but ignores them whereever this is relevant.
- * For example, the loop for the resolution of the weak types reads
- * types until it finds a non-BN.
- * Also, explicit embedding codes are neither changed into BN nor removed.
- * They are only treated the same way real BNs are.
- * As stated before, adjustWSLevels() takes care of them at the end.
- * For the purpose of conformance, the levels of all these codes
- * do not matter.
- *
- * Note that this implementation never modifies the dirProps
- * after the initial setup.
- *
- *
- * In this implementation, the resolution of weak types (Wn),
- * neutrals (Nn), and the assignment of the resolved level (In)
- * are all done in one single loop, in resolveImplicitLevels().
- * Changes of dirProp values are done on the fly, without writing
- * them back to the dirProps array.
- *
- *
- * This implementation contains code that allows to bypass steps of the
- * algorithm that are not needed on the specific paragraph
- * in order to speed up the most common cases considerably,
- * like text that is entirely LTR, or RTL text without numbers.
- *
- * Most of this is done by setting a bit for each directional property
- * in a flags variable and later checking for whether there are
- * any LTR characters or any RTL characters, or both, whether
- * there are any explicit embedding codes, etc.
- *
- * If the (Xn) steps are performed, then the flags are re-evaluated,
- * because they will then not contain the embedding codes any more
- * and will be adjusted for override codes, so that subsequently
- * more bypassing may be possible than what the initial flags suggested.
- *
- * If the text is not mixed-directional, then the
- * algorithm steps for the weak type resolution are not performed,
- * and all levels are set to the paragraph level.
- *
- * If there are no explicit embedding codes, then the (Xn) steps
- * are not performed.
- *
- * If embedding levels are supplied as a parameter, then all
- * explicit embedding codes are ignored, and the (Xn) steps
- * are not performed.
- *
- * White Space types could get the level of the run they belong to,
- * and are checked with a test of (flags&MASK_EMBEDDING) to
- * consider if the paragraph direction should be considered in
- * the flags variable.
- *
- * If there are no White Space types in the paragraph, then
- * (L1) is not necessary in adjustWSLevels().
- */
-
-/* prototypes --------------------------------------------------------------- */
-
-static void
-getDirProps(UBiDi *pBiDi, const UChar *text);
-
-static UBiDiDirection
-resolveExplicitLevels(UBiDi *pBiDi);
-
-static UBiDiDirection
-checkExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode);
-
-static UBiDiDirection
-directionFromFlags(Flags flags);
-
-static void
-resolveImplicitLevels(UBiDi *pBiDi,
- int32_t start, int32_t limit,
- DirProp sor, DirProp eor);
-
-static void
-adjustWSLevels(UBiDi *pBiDi);
-
-/* to avoid some conditional statements, use tiny constant arrays */
-static const Flags flagLR[2]={ DIRPROP_FLAG(L), DIRPROP_FLAG(R) };
-static const Flags flagE[2]={ DIRPROP_FLAG(LRE), DIRPROP_FLAG(RLE) };
-static const Flags flagO[2]={ DIRPROP_FLAG(LRO), DIRPROP_FLAG(RLO) };
-
-#define DIRPROP_FLAG_LR(level) flagLR[(level)&1]
-#define DIRPROP_FLAG_E(level) flagE[(level)&1]
-#define DIRPROP_FLAG_O(level) flagO[(level)&1]
-
-/* UBiDi object management -------------------------------------------------- */
-
-U_CAPI UBiDi * U_EXPORT2
-ubidi_open(void)
-{
- UErrorCode errorCode=U_ZERO_ERROR;
- return ubidi_openSized(0, 0, &errorCode);
-}
-
-U_CAPI UBiDi * U_EXPORT2
-ubidi_openSized(int32_t maxLength, int32_t maxRunCount, UErrorCode *pErrorCode) {
- UBiDi *pBiDi;
-
- /* check the argument values */
- if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
- return NULL;
- } else if(maxLength<0 || maxRunCount<0) {
- *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
- return NULL; /* invalid arguments */
- }
-
- /* allocate memory for the object */
- pBiDi=(UBiDi *)icu_malloc(sizeof(UBiDi));
- if(pBiDi==NULL) {
- *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- }
-
- /* reset the object, all pointers NULL, all flags FALSE, all sizes 0 */
- icu_memset(pBiDi, 0, sizeof(UBiDi));
-
- /* allocate memory for arrays as requested */
- if(maxLength>0) {
- if( !getInitialDirPropsMemory(pBiDi, maxLength) ||
- !getInitialLevelsMemory(pBiDi, maxLength)
- ) {
- *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
- }
- } else {
- pBiDi->mayAllocateText=TRUE;
- }
-
- if(maxRunCount>0) {
- if(maxRunCount==1) {
- /* use simpleRuns[] */
- pBiDi->runsSize=sizeof(Run);
- } else if(!getInitialRunsMemory(pBiDi, maxRunCount)) {
- *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
- }
- } else {
- pBiDi->mayAllocateRuns=TRUE;
- }
-
- if(U_SUCCESS(*pErrorCode)) {
- return pBiDi;
- } else {
- ubidi_close(pBiDi);
- return NULL;
- }
-}
-
-/*
- * We are allowed to allocate memory if memory==NULL or
- * mayAllocate==TRUE for each array that we need.
- * We also try to grow and shrink memory as needed if we
- * allocate it.
- *
- * Assume sizeNeeded>0.
- * If *pMemory!=NULL, then assume *pSize>0.
- *
- * ### this realloc() may unnecessarily copy the old data,
- * which we know we don't need any more;
- * is this the best way to do this??
- */
-extern bool_t
-ubidi_getMemory(void **pMemory, int32_t *pSize, bool_t mayAllocate, int32_t sizeNeeded) {
- /* check for existing memory */
- if(*pMemory==NULL) {
- /* we need to allocate memory */
- if(mayAllocate && (*pMemory=icu_malloc(sizeNeeded))!=NULL) {
- *pSize=sizeNeeded;
- return TRUE;
- } else {
- return FALSE;
- }
- } else {
- /* there is some memory, is it enough or too much? */
- if(sizeNeeded>*pSize && !mayAllocate) {
- /* not enough memory, and we must not allocate */
- return FALSE;
- } else if(sizeNeeded!=*pSize && mayAllocate) {
- /* we may try to grow or shrink */
- void *memory;
-
- if((memory=icu_realloc(*pMemory, sizeNeeded))!=NULL) {
- *pMemory=memory;
- *pSize=sizeNeeded;
- return TRUE;
- } else {
- /* we failed to grow */
- return FALSE;
- }
- } else {
- /* we have at least enough memory and must not allocate */
- return TRUE;
- }
- }
-}
-
-U_CAPI void U_EXPORT2
-ubidi_close(UBiDi *pBiDi) {
- if(pBiDi!=NULL) {
- if(pBiDi->dirPropsMemory!=NULL) {
- icu_free(pBiDi->dirPropsMemory);
- }
- if(pBiDi->levelsMemory!=NULL) {
- icu_free(pBiDi->levelsMemory);
- }
- if(pBiDi->runsMemory!=NULL) {
- icu_free(pBiDi->runsMemory);
- }
- icu_free(pBiDi);
- }
-}
-
-/* set to approximate "inverse BiDi" ---------------------------------------- */
-
-U_CAPI void U_EXPORT2
-ubidi_setInverse(UBiDi *pBiDi, bool_t isInverse) {
- if(pBiDi!=NULL) {
- pBiDi->isInverse=isInverse;
- }
-}
-
-U_CAPI bool_t U_EXPORT2
-ubidi_isInverse(UBiDi *pBiDi) {
- if(pBiDi!=NULL) {
- return pBiDi->isInverse;
- } else {
- return FALSE;
- }
-}
-
-/* ubidi_setPara ------------------------------------------------------------ */
-
-U_CAPI void U_EXPORT2
-ubidi_setPara(UBiDi *pBiDi, const UChar *text, int32_t length,
- UBiDiLevel paraLevel, UBiDiLevel *embeddingLevels,
- UErrorCode *pErrorCode) {
- UBiDiDirection direction;
-
- /* check the argument values */
- if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
- return;
- } else if(pBiDi==NULL || text==NULL ||
- ((UBIDI_MAX_EXPLICIT_LEVEL<paraLevel) && !IS_DEFAULT_LEVEL(paraLevel)) ||
- length<-1
- ) {
- *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
- return;
- }
-
- if(length==-1) {
- // length=u_strlen(text);
- const UChar *p = text - 1;
- while(*++p);
- length = p - text;
- }
-
- /* initialize the UBiDi structure */
- pBiDi->text=text;
- pBiDi->length=length;
- pBiDi->paraLevel=paraLevel;
- pBiDi->direction=UBIDI_LTR;
- pBiDi->trailingWSStart=length; /* the levels[] will reflect the WS run */
-
- pBiDi->dirProps=NULL;
- pBiDi->levels=NULL;
- pBiDi->runs=NULL;
-
- if(length==0) {
- /*
- * For an empty paragraph, create a UBiDi object with the paraLevel and
- * the flags and the direction set but without allocating zero-length arrays.
- * There is nothing more to do.
- */
- if(IS_DEFAULT_LEVEL(paraLevel)) {
- pBiDi->paraLevel&=1;
- }
- if(paraLevel&1) {
- pBiDi->flags=DIRPROP_FLAG(R);
- pBiDi->direction=UBIDI_RTL;
- } else {
- pBiDi->flags=DIRPROP_FLAG(L);
- pBiDi->direction=UBIDI_LTR;
- }
-
- pBiDi->runCount=0;
- return;
- }
-
- pBiDi->runCount=-1;
-
- /*
- * Get the directional properties,
- * the flags bit-set, and
- * determine the partagraph level if necessary.
- */
- if(getDirPropsMemory(pBiDi, length)) {
- pBiDi->dirProps=pBiDi->dirPropsMemory;
- getDirProps(pBiDi, text);
- } else {
- *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
- return;
- }
-
- if (getLevelsMemory(pBiDi, length)) {
- pBiDi->levels=pBiDi->levelsMemory;
- /* are explicit levels specified? */
- if(embeddingLevels==NULL) {
- /* no: determine explicit levels according to the (Xn) rules */
- direction=resolveExplicitLevels(pBiDi);
- } else {
- /* set BN for all explicit codes, check that all levels are paraLevel..UBIDI_MAX_EXPLICIT_LEVEL */
- icu_memcpy(pBiDi->levels, embeddingLevels, length);
- direction=checkExplicitLevels(pBiDi, pErrorCode);
- if(U_FAILURE(*pErrorCode)) {
- return;
- }
- }
- } else {
- *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
- return;
- }
-
- /*
- * The steps after (X9) in the UBiDi algorithm are performed only if
- * the paragraph text has mixed directionality!
- */
- pBiDi->direction=direction;
- switch(direction) {
- case UBIDI_LTR:
- /* make sure paraLevel is even */
- pBiDi->paraLevel=(UBiDiLevel)((pBiDi->paraLevel+1)&~1);
-
- /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
- pBiDi->trailingWSStart=0;
- break;
- case UBIDI_RTL:
- /* make sure paraLevel is odd */
- pBiDi->paraLevel|=1;
-
- /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
- pBiDi->trailingWSStart=0;
- break;
- default:
- /*
- * If there are no external levels specified and there
- * are no significant explicit level codes in the text,
- * then we can treat the entire paragraph as one run.
- * Otherwise, we need to perform the following rules on runs of
- * the text with the same embedding levels. (X10)
- * "Significant" explicit level codes are ones that actually
- * affect non-BN characters.
- * Examples for "insignificant" ones are empty embeddings
- * LRE-PDF, LRE-RLE-PDF-PDF, etc.
- */
- if(embeddingLevels==NULL && !(pBiDi->flags&DIRPROP_FLAG_MULTI_RUNS)) {
- resolveImplicitLevels(pBiDi, 0, length,
- GET_LR_FROM_LEVEL(pBiDi->paraLevel),
- GET_LR_FROM_LEVEL(pBiDi->paraLevel));
- } else {
- /* sor, eor: start and end types of same-level-run */
- UBiDiLevel *levels=pBiDi->levels;
- int32_t start, limit=0;
- UBiDiLevel level, nextLevel;
- DirProp sor, eor;
-
- /* determine the first sor and set eor to it because of the loop body (sor=eor there) */
- level=pBiDi->paraLevel;
- nextLevel=levels[0];
- if(level<nextLevel) {
- eor=GET_LR_FROM_LEVEL(nextLevel);
- } else {
- eor=GET_LR_FROM_LEVEL(level);
- }
-
- do {
- /* determine start and limit of the run (end points just behind the run) */
-
- /* the values for this run's start are the same as for the previous run's end */
- sor=eor;
- start=limit;
- level=nextLevel;
-
- /* search for the limit of this run */
- while(++limit<length && levels[limit]==level) {}
-
- /* get the correct level of the next run */
- if(limit<length) {
- nextLevel=levels[limit];
- } else {
- nextLevel=pBiDi->paraLevel;
- }
-
- /* determine eor from max(level, nextLevel); sor is last run's eor */
- if((level&~UBIDI_LEVEL_OVERRIDE)<(nextLevel&~UBIDI_LEVEL_OVERRIDE)) {
- eor=GET_LR_FROM_LEVEL(nextLevel);
- } else {
- eor=GET_LR_FROM_LEVEL(level);
- }
-
- /* if the run consists of overridden directional types, then there
- are no implicit types to be resolved */
- if(!(level&UBIDI_LEVEL_OVERRIDE)) {
- resolveImplicitLevels(pBiDi, start, limit, sor, eor);
- } else {
- /* remove the UBIDI_LEVEL_OVERRIDE flags */
- do {
- levels[start++]&=~UBIDI_LEVEL_OVERRIDE;
- } while(start<limit);
- }
- } while(limit<length);
- }
-
- /* reset the embedding levels for some non-graphic characters (L1), (X9) */
- adjustWSLevels(pBiDi);
-
- /* for "inverse BiDi", ubidi_getRuns() modifies the levels of numeric runs following RTL runs */
- if(pBiDi->isInverse) {
- if(!ubidi_getRuns(pBiDi)) {
- *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
- return;
- }
- }
- break;
- }
-}
-
-/* perform (P2)..(P3) ------------------------------------------------------- */
-
-/*
- * Get the directional properties for the text,
- * calculate the flags bit-set, and
- * determine the partagraph level if necessary.
- */
-static void
-getDirProps(UBiDi *pBiDi, const UChar *text) {
- DirProp *dirProps=pBiDi->dirPropsMemory; /* pBiDi->dirProps is const */
-
- int32_t i=0, i0, i1, length=pBiDi->length;
- Flags flags=0; /* collect all directionalities in the text */
- UChar uchar;
- DirProp dirProp;
-
- if(IS_DEFAULT_LEVEL(pBiDi->paraLevel)) {
- /* determine the paragraph level (P2..P3) */
- for(;;) {
- uchar=text[i];
- if(!IS_FIRST_SURROGATE(uchar) || i+1==length || !IS_SECOND_SURROGATE(text[i+1])) {
- /* not a surrogate pair */
- flags|=DIRPROP_FLAG(dirProps[i]=dirProp=u_charDirection(uchar));
- } else {
- /* a surrogate pair */
- dirProps[i++]=BN; /* first surrogate in the pair gets the BN type */
- flags|=DIRPROP_FLAG(dirProps[i]=dirProp=u_surrogatePairDirection(uchar, text[i]))|DIRPROP_FLAG(BN);
- }
- ++i;
- if(dirProp==L) {
- pBiDi->paraLevel=0;
- break;
- } else if(dirProp==R || dirProp==AL) {
- pBiDi->paraLevel=1;
- break;
- } else if(i>=length) {
- /*
- * see comment in ubidi.h:
- * the DEFAULT_XXX values are designed so that
- * their bit 0 alone yields the intended default
- */
- pBiDi->paraLevel&=1;
- break;
- }
- }
- } else {
- flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
- }
-
- /* get the rest of the directional properties and the flags bits */
- while(i<length) {
- uchar=text[i];
- if(!IS_FIRST_SURROGATE(uchar) || i+1==length || !IS_SECOND_SURROGATE(text[i+1])) {
- /* not a surrogate pair */
- flags|=DIRPROP_FLAG(dirProps[i]=u_charDirection(uchar));
- } else {
- /* a surrogate pair */
- dirProps[i++]=BN; /* first surrogate in the pair gets the BN type */
- flags|=DIRPROP_FLAG(dirProps[i]=dirProp=u_surrogatePairDirection(uchar, text[i]))|DIRPROP_FLAG(BN);
- }
- ++i;
- }
- if(flags&MASK_EMBEDDING) {
- flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
- }
-
- pBiDi->flags=flags;
-}
-
-/* perform (X1)..(X9) ------------------------------------------------------- */
-
-/*
- * Resolve the explicit levels as specified by explicit embedding codes.
- * Recalculate the flags to have them reflect the real properties
- * after taking the explicit embeddings into account.
- *
- * The BiDi algorithm is designed to result in the same behavior whether embedding
- * levels are externally specified (from "styled text", supposedly the preferred
- * method) or set by explicit embedding codes (LRx, RLx, PDF) in the plain text.
- * That is why (X9) instructs to remove all explicit codes (and BN).
- * However, in a real implementation, this removal of these codes and their index
- * positions in the plain text is undesirable since it would result in
- * reallocated, reindexed text.
- * Instead, this implementation leaves the codes in there and just ignores them
- * in the subsequent processing.
- * In order to get the same reordering behavior, positions with a BN or an
- * explicit embedding code just get the same level assigned as the last "real"
- * character.
- *
- * Some implementations, not this one, then overwrite some of these
- * directionality properties at "real" same-level-run boundaries by
- * L or R codes so that the resolution of weak types can be performed on the
- * entire paragraph at once instead of having to parse it once more and
- * perform that resolution on same-level-runs.
- * This limits the scope of the implicit rules in effectively
- * the same way as the run limits.
- *
- * Instead, this implementation does not modify these codes.
- * On one hand, the paragraph has to be scanned for same-level-runs, but
- * on the other hand, this saves another loop to reset these codes,
- * or saves making and modifying a copy of dirProps[].
- *
- *
- * Note that (Pn) and (Xn) changed significantly from version 4 of the BiDi algorithm.
- *
- *
- * Handling the stack of explicit levels (Xn):
- *
- * With the BiDi stack of explicit levels,
- * as pushed with each LRE, RLE, LRO, and RLO and popped with each PDF,
- * the explicit level must never exceed UBIDI_MAX_EXPLICIT_LEVEL==61.
- *
- * In order to have a correct push-pop semantics even in the case of overflows,
- * there are two overflow counters:
- * - countOver60 is incremented with each LRx at level 60
- * - from level 60, one RLx increases the level to 61
- * - countOver61 is incremented with each LRx and RLx at level 61
- *
- * Popping levels with PDF must work in the opposite order so that level 61
- * is correct at the correct point. Underflows (too many PDFs) must be checked.
- *
- * This implementation assumes that UBIDI_MAX_EXPLICIT_LEVEL is odd.
- */
-
-static UBiDiDirection
-resolveExplicitLevels(UBiDi *pBiDi) {
- const DirProp *dirProps=pBiDi->dirProps;
- UBiDiLevel *levels=pBiDi->levels;
-
- int32_t i=0, length=pBiDi->length;
- Flags flags=pBiDi->flags; /* collect all directionalities in the text */
- DirProp dirProp;
- UBiDiLevel level=pBiDi->paraLevel;
-
- UBiDiDirection direction;
-
- /* determine if the text is mixed-directional or single-directional */
- direction=directionFromFlags(flags);
-
- /* we may not need to resolve any explicit levels */
- if(direction!=UBIDI_MIXED) {
- /* not mixed directionality: levels don't matter - trailingWSStart will be 0 */
- } else if(!(flags&MASK_EXPLICIT) || pBiDi->isInverse) {
- /* mixed, but all characters are at the same embedding level */
- /* or we are in "inverse BiDi" */
- /* set all levels to the paragraph level */
- for(i=0; i<length; ++i) {
- levels[i]=level;
- }
- } else {
- /* continue to perform (Xn) */
-
- /* (X1) level is set for all codes, embeddingLevel keeps track of the push/pop operations */
- /* both variables may carry the UBIDI_LEVEL_OVERRIDE flag to indicate the override status */
- UBiDiLevel embeddingLevel=level, newLevel, stackTop=0;
-
- UBiDiLevel stack[UBIDI_MAX_EXPLICIT_LEVEL]; /* we never push anything >=UBIDI_MAX_EXPLICIT_LEVEL */
- uint32_t countOver60=0, countOver61=0; /* count overflows of explicit levels */
-
- /* recalculate the flags */
- flags=0;
-
- /* since we assume that this is a single paragraph, we ignore (X8) */
- for(i=0; i<length; ++i) {
- dirProp=dirProps[i];
- switch(dirProp) {
- case LRE:
- case LRO:
- /* (X3, X5) */
- newLevel=(UBiDiLevel)((embeddingLevel+2)&~(UBIDI_LEVEL_OVERRIDE|1)); /* least greater even level */
- if(newLevel<=UBIDI_MAX_EXPLICIT_LEVEL) {
- stack[stackTop]=embeddingLevel;
- ++stackTop;
- embeddingLevel=newLevel;
- if(dirProp==LRO) {
- embeddingLevel|=UBIDI_LEVEL_OVERRIDE;
- } else {
- embeddingLevel&=~UBIDI_LEVEL_OVERRIDE;
- }
- } else if((embeddingLevel&~UBIDI_LEVEL_OVERRIDE)==UBIDI_MAX_EXPLICIT_LEVEL) {
- ++countOver61;
- } else /* (embeddingLevel&~UBIDI_LEVEL_OVERRIDE)==UBIDI_MAX_EXPLICIT_LEVEL-1 */ {
- ++countOver60;
- }
- flags|=DIRPROP_FLAG(BN);
- break;
- case RLE:
- case RLO:
- /* (X2, X4) */
- newLevel=(UBiDiLevel)(((embeddingLevel&~UBIDI_LEVEL_OVERRIDE)+1)|1); /* least greater odd level */
- if(newLevel<=UBIDI_MAX_EXPLICIT_LEVEL) {
- stack[stackTop]=embeddingLevel;
- ++stackTop;
- embeddingLevel=newLevel;
- if(dirProp==RLO) {
- embeddingLevel|=UBIDI_LEVEL_OVERRIDE;
- } else {
- embeddingLevel&=~UBIDI_LEVEL_OVERRIDE;
- }
- } else {
- ++countOver61;
- }
- flags|=DIRPROP_FLAG(BN);
- break;
- case PDF:
- /* (X7) */
- /* handle all the overflow cases first */
- if(countOver61>0) {
- --countOver61;
- } else if(countOver60>0 && (embeddingLevel&~UBIDI_LEVEL_OVERRIDE)!=UBIDI_MAX_EXPLICIT_LEVEL) {
- /* handle LRx overflows from level 60 */
- --countOver60;
- } else if(stackTop>0) {
- /* this is the pop operation; it also pops level 61 while countOver60>0 */
- --stackTop;
- embeddingLevel=stack[stackTop];
- /* } else { (underflow) */
- }
- flags|=DIRPROP_FLAG(BN);
- break;
- case B:
- /*
- * We do not really expect to see a paragraph separator (B),
- * but we should do something reasonable with it,
- * especially at the end of the text.
- */
- stackTop=0;
- countOver60=countOver61=0;
- embeddingLevel=level=pBiDi->paraLevel;
- flags|=DIRPROP_FLAG(B);
- break;
- case BN:
- /* BN, LRE, RLE, and PDF are supposed to be removed (X9) */
- /* they will get their levels set correctly in adjustWSLevels() */
- flags|=DIRPROP_FLAG(BN);
- break;
- default:
- /* all other types get the "real" level */
- if(level!=embeddingLevel) {
- level=embeddingLevel;
- if(level&UBIDI_LEVEL_OVERRIDE) {
- flags|=DIRPROP_FLAG_O(level)|DIRPROP_FLAG_MULTI_RUNS;
- } else {
- flags|=DIRPROP_FLAG_E(level)|DIRPROP_FLAG_MULTI_RUNS;
- }
- }
- if(!(level&UBIDI_LEVEL_OVERRIDE)) {
- flags|=DIRPROP_FLAG(dirProp);
- }
- break;
- }
-
- /*
- * We need to set reasonable levels even on BN codes and
- * explicit codes because we will later look at same-level runs (X10).
- */
- levels[i]=level;
- }
- if(flags&MASK_EMBEDDING) {
- flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
- }
-
- /* subsequently, ignore the explicit codes and BN (X9) */
-
- /* again, determine if the text is mixed-directional or single-directional */
- pBiDi->flags=flags;
- direction=directionFromFlags(flags);
- }
- return direction;
-}
-
-/*
- * Use a pre-specified embedding levels array:
- *
- * Adjust the directional properties for overrides (->LEVEL_OVERRIDE),
- * ignore all explicit codes (X9),
- * and check all the preset levels.
- *
- * Recalculate the flags to have them reflect the real properties
- * after taking the explicit embeddings into account.
- */
-static UBiDiDirection
-checkExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) {
- const DirProp *dirProps=pBiDi->dirProps;
- UBiDiLevel *levels=pBiDi->levels;
-
- int32_t i, length=pBiDi->length;
- Flags flags=0; /* collect all directionalities in the text */
- UBiDiLevel level, paraLevel=pBiDi->paraLevel;
-
- for(i=0; i<length; ++i) {
- // dlf: we special case levels array for java, 0 means base level, not actually 0
- if (levels[i] == 0) {
- levels[i] = paraLevel;
- }
- level=levels[i];
- if(level&UBIDI_LEVEL_OVERRIDE) {
- /* keep the override flag in levels[i] but adjust the flags */
- level&=~UBIDI_LEVEL_OVERRIDE; /* make the range check below simpler */
- flags|=DIRPROP_FLAG_O(level);
- } else {
- /* set the flags */
- flags|=DIRPROP_FLAG_E(level)|DIRPROP_FLAG(dirProps[i]);
- }
- if(level<paraLevel || UBIDI_MAX_EXPLICIT_LEVEL<level) {
- /* level out of bounds */
- *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
- return UBIDI_LTR;
- }
- }
- if(flags&MASK_EMBEDDING) {
- flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
- }
-
- /* determine if the text is mixed-directional or single-directional */
- pBiDi->flags=flags;
- return directionFromFlags(flags);
-}
-
-/* determine if the text is mixed-directional or single-directional */
-static UBiDiDirection
-directionFromFlags(Flags flags) {
- /* if the text contains AN and neutrals, then some neutrals may become RTL */
- if(!(flags&MASK_RTL || ((flags&DIRPROP_FLAG(AN)) && (flags&MASK_POSSIBLE_N)))) {
- return UBIDI_LTR;
- } else if(!(flags&MASK_LTR)) {
- return UBIDI_RTL;
- } else {
- return UBIDI_MIXED;
- }
-}
-
-/* perform rules (Wn), (Nn), and (In) on a run of the text ------------------ */
-
-/*
- * This implementation of the (Wn) rules applies all rules in one pass.
- * In order to do so, it needs a look-ahead of typically 1 character
- * (except for W5: sequences of ET) and keeps track of changes
- * in a rule Wp that affect a later Wq (p<q).
- *
- * historyOfEN is a variable-saver: it contains 4 boolean states;
- * a bit in it set to 1 means:
- * bit 0: the current code is an EN after W2
- * bit 1: the current code is an EN after W4
- * bit 2: the previous code was an EN after W2
- * bit 3: the previous code was an EN after W4
- * In other words, b0..1 have transitions of EN in the current iteration,
- * while b2..3 have the transitions of EN in the previous iteration.
- * A simple historyOfEN<<=2 suffices for the propagation.
- *
- * The (Nn) and (In) rules are also performed in that same single loop,
- * but effectively one iteration behind for white space.
- *
- * Since all implicit rules are performed in one step, it is not necessary
- * to actually store the intermediate directional properties in dirProps[].
- */
-
-#define EN_SHIFT 2
-#define EN_AFTER_W2 1
-#define EN_AFTER_W4 2
-#define EN_ALL 3
-#define PREV_EN_AFTER_W2 4
-#define PREV_EN_AFTER_W4 8
-
-static void
-resolveImplicitLevels(UBiDi *pBiDi,
- int32_t start, int32_t limit,
- DirProp sor, DirProp eor) {
- const DirProp *dirProps=pBiDi->dirProps;
- UBiDiLevel *levels=pBiDi->levels;
-
- int32_t i, next, neutralStart=-1;
- DirProp prevDirProp, dirProp, nextDirProp, lastStrong, beforeNeutral=L;
- UBiDiLevel numberLevel;
- uint8_t historyOfEN;
-
- /* initialize: current at sor, next at start (it is start<limit) */
- next=start;
- dirProp=lastStrong=sor;
- nextDirProp=dirProps[next];
- historyOfEN=0;
-
- if(pBiDi->isInverse) {
- /*
- * For "inverse BiDi", we set the levels of numbers just like for
- * regular L characters, plus a flag that ubidi_getRuns() will use
- * to set a similar flag on the corresponding output run.
- */
- numberLevel=levels[start];
- if(numberLevel&1) {
- ++numberLevel;
- }
- } else {
- /* normal BiDi: least greater even level */
- numberLevel=(UBiDiLevel)((levels[start]+2)&~1);
- }
-
- /*
- * In all steps of this implementation, BN and explicit embedding codes
- * must be treated as if they didn't exist (X9).
- * They will get levels set before a non-neutral character, and remain
- * undefined before a neutral one, but adjustWSLevels() will take care
- * of all of them.
- */
- while(DIRPROP_FLAG(nextDirProp)&MASK_BN_EXPLICIT) {
- if(++next<limit) {
- nextDirProp=dirProps[next];
- } else {
- nextDirProp=eor;
- break;
- }
- }
-
- /*
- * Note: at the end of this file, there is a prototype
- * of a version of this function that uses a statetable
- * at the core of this state machine.
- * If you make changes to this state machine,
- * please update that prototype as well.
- */
-
- /* loop for entire run */
- while(next<limit) {
- /* advance */
- prevDirProp=dirProp;
- dirProp=nextDirProp;
- i=next;
- do {
- if(++next<limit) {
- nextDirProp=dirProps[next];
- } else {
- nextDirProp=eor;
- break;
- }
- } while(DIRPROP_FLAG(nextDirProp)&MASK_BN_EXPLICIT);
- historyOfEN<<=EN_SHIFT;
-
- /* (W1..W7) */
- switch(dirProp) {
- case L:
- lastStrong=L;
- break;
- case R:
- lastStrong=R;
- break;
- case AL:
- /* (W3) */
- lastStrong=AL;
- dirProp=R;
- break;
- case EN:
- /* we have to set historyOfEN correctly */
- if(lastStrong==AL) {
- /* (W2) */
- dirProp=AN;
- } else {
- if(lastStrong==L) {
- /* (W7) */
- dirProp=L;
- }
- /* this EN stays after (W2) and (W4) - at least before (W7) */
- historyOfEN|=EN_ALL;
- }
- break;
- case ES:
- if( historyOfEN&PREV_EN_AFTER_W2 && /* previous was EN before (W4) */
- nextDirProp==EN && lastStrong!=AL /* next is EN and (W2) won't make it AN */
- ) {
- /* (W4) */
- if(lastStrong!=L) {
- dirProp=EN;
- } else {
- /* (W7) */
- dirProp=L;
- }
- historyOfEN|=EN_AFTER_W4;
- } else {
- /* (W6) */
- dirProp=ON;
- }
- break;
- case CS:
- if( historyOfEN&PREV_EN_AFTER_W2 && /* previous was EN before (W4) */
- nextDirProp==EN && lastStrong!=AL /* next is EN and (W2) won't make it AN */
- ) {
- /* (W4) */
- if(lastStrong!=L) {
- dirProp=EN;
- } else {
- /* (W7) */
- dirProp=L;
- }
- historyOfEN|=EN_AFTER_W4;
- } else if(prevDirProp==AN && /* previous was AN */
- (nextDirProp==AN || /* next is AN */
- (nextDirProp==EN && lastStrong==AL)) /* or (W2) will make it one */
- ) {
- /* (W4) */
- dirProp=AN;
- } else {
- /* (W6) */
- dirProp=ON;
- }
- break;
- case ET:
- /* get sequence of ET; advance only next, not current, previous or historyOfEN */
- if(next<limit) {
- while(DIRPROP_FLAG(nextDirProp)&MASK_ET_NSM_BN /* (W1), (X9) */) {
- if(++next<limit) {
- nextDirProp=dirProps[next];
- } else {
- nextDirProp=eor;
- break;
- }
- }
- }
-
- /* now process the sequence of ET like a single ET */
- if((historyOfEN&PREV_EN_AFTER_W4) || /* previous was EN before (W5) */
- (nextDirProp==EN && lastStrong!=AL) /* next is EN and (W2) won't make it AN */
- ) {
- /* (W5) */
- if(lastStrong!=L) {
- dirProp=EN;
- } else {
- /* (W7) */
- dirProp=L;
- }
- } else {
- /* (W6) */
- dirProp=ON;
- }
-
- /* apply the result of (W1), (W5)..(W7) to the entire sequence of ET */
- break;
- case NSM:
- /* (W1) */
- dirProp=prevDirProp;
- /* set historyOfEN back to prevDirProp's historyOfEN */
- historyOfEN>>=EN_SHIFT;
- /*
- * Technically, this should be done before the switch() in the form
- * if(nextDirProp==NSM) {
- * dirProps[next]=nextDirProp=dirProp;
- * }
- *
- * - effectively one iteration ahead.
- * However, whether the next dirProp is NSM or is equal to the current dirProp
- * does not change the outcome of any condition in (W2)..(W7).
- */
- break;
- default:
- break;
- }
-
- /* here, it is always [prev,this,next]dirProp!=BN; it may be next>i+1 */
-
- /* perform (Nn) - here, only L, R, EN, AN, and neutrals are left */
- /* for "inverse BiDi", treat neutrals like L */
- /* this is one iteration late for the neutrals */
- if(DIRPROP_FLAG(dirProp)&MASK_N) {
- if(neutralStart<0) {
- /* start of a sequence of neutrals */
- neutralStart=i;
- beforeNeutral=prevDirProp;
- }
- } else /* not a neutral, can be only one of { L, R, EN, AN } */ {
- /*
- * Note that all levels[] values are still the same at this
- * point because this function is called for an entire
- * same-level run.
- * Therefore, we need to read only one actual level.
- */
- UBiDiLevel level=levels[i];
-
- if(neutralStart>=0) {
- UBiDiLevel final;
- /* end of a sequence of neutrals (dirProp is "afterNeutral") */
- if(!(pBiDi->isInverse)) {
- if(beforeNeutral==L) {
- if(dirProp==L) {
- final=0; /* make all neutrals L (N1) */
- } else {
- final=level; /* make all neutrals "e" (N2) */
- }
- } else /* beforeNeutral is one of { R, EN, AN } */ {
- if(dirProp==L) {
- final=level; /* make all neutrals "e" (N2) */
- } else {
- final=1; /* make all neutrals R (N1) */
- }
- }
- } else {
- /* "inverse BiDi": collapse [before]dirProps L, EN, AN into L */
- if(beforeNeutral!=R) {
- if(dirProp!=R) {
- final=0; /* make all neutrals L (N1) */
- } else {
- final=level; /* make all neutrals "e" (N2) */
- }
- } else /* beforeNeutral is one of { R, EN, AN } */ {
- if(dirProp!=R) {
- final=level; /* make all neutrals "e" (N2) */
- } else {
- final=1; /* make all neutrals R (N1) */
- }
- }
- }
- /* perform (In) on the sequence of neutrals */
- if((level^final)&1) {
- /* do something only if we need to _change_ the level */
- do {
- ++levels[neutralStart];
- } while(++neutralStart<i);
- }
- neutralStart=-1;
- }
-
- /* perform (In) on the non-neutral character */
- /*
- * in the cases of (W5), processing a sequence of ET,
- * and of (X9), skipping BN,
- * there may be multiple characters from i to <next
- * that all get (virtually) the same dirProp and (really) the same level
- */
- if(dirProp==L) {
- if(level&1) {
- ++level;
- } else {
- i=next; /* we keep the levels */
- }
- } else if(dirProp==R) {
- if(!(level&1)) {
- ++level;
- } else {
- i=next; /* we keep the levels */
- }
- } else /* EN or AN */ {
- /* this level depends on whether we do "inverse BiDi" */
- level=numberLevel;
- }
-
- /* apply the new level to the sequence, if necessary */
- while(i<next) {
- levels[i++]=level;
- }
- }
- }
-
- /* perform (Nn) - here,
- the character after the the neutrals is eor, which is either L or R */
- /* this is one iteration late for the neutrals */
- if(neutralStart>=0) {
- /*
- * Note that all levels[] values are still the same at this
- * point because this function is called for an entire
- * same-level run.
- * Therefore, we need to read only one actual level.
- */
- UBiDiLevel level=levels[neutralStart], final;
-
- /* end of a sequence of neutrals (eor is "afterNeutral") */
- if(!(pBiDi->isInverse)) {
- if(beforeNeutral==L) {
- if(eor==L) {
- final=0; /* make all neutrals L (N1) */
- } else {
- final=level; /* make all neutrals "e" (N2) */
- }
- } else /* beforeNeutral is one of { R, EN, AN } */ {
- if(eor==L) {
- final=level; /* make all neutrals "e" (N2) */
- } else {
- final=1; /* make all neutrals R (N1) */
- }
- }
- } else {
- /* "inverse BiDi": collapse [before]dirProps L, EN, AN into L */
- if(beforeNeutral!=R) {
- if(eor!=R) {
- final=0; /* make all neutrals L (N1) */
- } else {
- final=level; /* make all neutrals "e" (N2) */
- }
- } else /* beforeNeutral is one of { R, EN, AN } */ {
- if(eor!=R) {
- final=level; /* make all neutrals "e" (N2) */
- } else {
- final=1; /* make all neutrals R (N1) */
- }
- }
- }
- /* perform (In) on the sequence of neutrals */
- if((level^final)&1) {
- /* do something only if we need to _change_ the level */
- do {
- ++levels[neutralStart];
- } while(++neutralStart<limit);
- }
- }
-}
-
-/* perform (L1) and (X9) ---------------------------------------------------- */
-
-/*
- * Reset the embedding levels for some non-graphic characters (L1).
- * This function also sets appropriate levels for BN, and
- * explicit embedding types that are supposed to have been removed
- * from the paragraph in (X9).
- */
-static void
-adjustWSLevels(UBiDi *pBiDi) {
- const DirProp *dirProps=pBiDi->dirProps;
- UBiDiLevel *levels=pBiDi->levels;
- int32_t i;
-
- if(pBiDi->flags&MASK_WS) {
- UBiDiLevel paraLevel=pBiDi->paraLevel;
- Flags flag;
-
- i=pBiDi->trailingWSStart;
- while(i>0) {
- /* reset a sequence of WS/BN before eop and B/S to the paragraph paraLevel */
- while(i>0 && DIRPROP_FLAG(dirProps[--i])&MASK_WS) {
- levels[i]=paraLevel;
- }
-
- /* reset BN to the next character's paraLevel until B/S, which restarts above loop */
- /* here, i+1 is guaranteed to be <length */
- while(i>0) {
- flag=DIRPROP_FLAG(dirProps[--i]);
- if(flag&MASK_BN_EXPLICIT) {
- levels[i]=levels[i+1];
- } else if(flag&MASK_B_S) {
- levels[i]=paraLevel;
- break;
- }
- }
- }
- }
-
- /* now remove the UBIDI_LEVEL_OVERRIDE flags, if any */
- /* (a separate loop can be optimized more easily by a compiler) */
- if(pBiDi->flags&MASK_OVERRIDE) {
- for(i=pBiDi->trailingWSStart; i>0;) {
- levels[--i]&=~UBIDI_LEVEL_OVERRIDE;
- }
- }
-}
-
-/* -------------------------------------------------------------------------- */
-
-U_CAPI UBiDiDirection U_EXPORT2
-ubidi_getDirection(const UBiDi *pBiDi) {
- if(pBiDi!=NULL) {
- return pBiDi->direction;
- } else {
- return UBIDI_LTR;
- }
-}
-
-U_CAPI const UChar * U_EXPORT2
-ubidi_getText(const UBiDi *pBiDi) {
- if(pBiDi!=NULL) {
- return pBiDi->text;
- } else {
- return NULL;
- }
-}
-
-U_CAPI int32_t U_EXPORT2
-ubidi_getLength(const UBiDi *pBiDi) {
- if(pBiDi!=NULL) {
- return pBiDi->length;
- } else {
- return 0;
- }
-}
-
-U_CAPI UBiDiLevel U_EXPORT2
-ubidi_getParaLevel(const UBiDi *pBiDi) {
- if(pBiDi!=NULL) {
- return pBiDi->paraLevel;
- } else {
- return 0;
- }
-}
-
-/* statetable prototype ----------------------------------------------------- */
-
-/*
- * This is here for possible future
- * performance work and is not compiled right now.
- */
-
-#if 0
-/*
- * This is a piece of code that could be part of ubidi.c/resolveImplicitLevels().
- * It replaces in the (Wn) state machine the switch()-if()-cascade with
- * just a few if()s and a state table.
- */
-
-/* use the state table only for the following dirProp's */
-#define MASK_W_TABLE (FLAG(L)|FLAG(R)|FLAG(AL)|FLAG(EN)|FLAG(ES)|FLAG(CS)|FLAG(ET)|FLAG(AN))
-
-/*
- * inputs:
- *
- * 0..1 historyOfEN - 2b
- * 2 prevDirProp==AN - 1b
- * 3..4 lastStrong, one of { L, R, AL, none } - 2b
- * 5..7 dirProp, one of { L, R, AL, EN, ES, CS, ET, AN } - 3b
- * 8..9 nextDirProp, one of { EN, AN, other }
- *
- * total: 10b=1024 states
- */
-enum { _L, _R, _AL, _EN, _ES, _CS, _ET, _AN, _OTHER }; /* lastStrong, dirProp */
-enum { __EN, __AN, __OTHER }; /* nextDirProp */
-
-#define LAST_STRONG_SHIFT 3
-#define DIR_PROP_SHIFT 5
-#define NEXT_DIR_PROP_SHIFT 8
-
-/* masks after shifting */
-#define LAST_STRONG_MASK 3
-#define DIR_PROP_MASK 7
-#define STATE_MASK 0x1f
-
-/* convert dirProp into _dirProp (above enum) */
-static DirProp inputDirProp[dirPropCount]={ _X<<DIR_PROP_SHIFT, ... };
-
-/* convert dirProp into __dirProp (above enum) */
-static DirProp inputNextDirProp[dirPropCount]={ __X<<NEXT_DIR_PROP_SHIFT, ... };
-
-/*
- * outputs:
- *
- * dirProp, one of { L, R, EN, AN, ON } - 3b
- *
- * 0..1 historyOfEN - 2b
- * 2 prevDirProp==AN - 1b
- * 3..4 lastStrong, one of { L, R, AL, none } - 2b
- * 5..7 new dirProp, one of { L, R, EN, AN, ON }
- *
- * total: 8 bits=1 byte per state
- */
-enum { ___L, ___R, ___EN, ___AN, ___ON, ___count };
-
-/* convert ___dirProp into dirProp (above enum) */
-static DirProp outputDirProp[___count]={ X, ... };
-
-/* state table */
-static uint8_t wnTable[1024]={ /* calculate with switch()-if()-cascade */ };
-
-static void
-resolveImplicitLevels(BiDi *pBiDi,
- Index start, Index end,
- DirProp sor, DirProp eor) {
- /* new variable */
- uint8_t state;
-
- /* remove variable lastStrong */
-
- /* set initial state (set lastStrong, the rest is 0) */
- state= sor==L ? 0 : _R<<LAST_STRONG_SHIFT;
-
- while(next<limit) {
- /* advance */
- prevDirProp=dirProp;
- dirProp=nextDirProp;
- i=next;
- do {
- if(++next<limit) {
- nextDirProp=dirProps[next];
- } else {
- nextDirProp=eor;
- break;
- }
- } while(FLAG(nextDirProp)&MASK_BN_EXPLICIT);
-
- /* (W1..W7) */
- /* ### This may be more efficient with a switch(dirProp). */
- if(FLAG(dirProp)&MASK_W_TABLE) {
- state=wnTable[
- ((int)state)|
- inputDirProp[dirProp]|
- inputNextDirProp[nextDirProp]
- ];
- dirProp=outputDirProp[state>>DIR_PROP_SHIFT];
- state&=STATE_MASK;
- } else if(dirProp==ET) {
- /* get sequence of ET; advance only next, not current, previous or historyOfEN */
- while(next<limit && FLAG(nextDirProp)&MASK_ET_NSM_BN /* (W1), (X9) */) {
- if(++next<limit) {
- nextDirProp=dirProps[next];
- } else {
- nextDirProp=eor;
- break;
- }
- }
-
- state=wnTable[
- ((int)state)|
- _ET<<DIR_PROP_SHIFT|
- inputNextDirProp[nextDirProp]
- ];
- dirProp=outputDirProp[state>>DIR_PROP_SHIFT];
- state&=STATE_MASK;
-
- /* apply the result of (W1), (W5)..(W7) to the entire sequence of ET */
- } else if(dirProp==NSM) {
- /* (W1) */
- dirProp=prevDirProp;
- /* keep prevDirProp's EN and AN states! */
- } else /* other */ {
- /* set EN and AN states to 0 */
- state&=LAST_STRONG_MASK<<LAST_STRONG_SHIFT;
- }
-
- /* perform (Nn) and (In) as usual */
- }
- /* perform (Nn) and (In) as usual */
-}
-#endif
--- a/jdk/src/share/native/sun/font/bidi/ubidi.h Thu May 28 18:11:07 2009 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,913 +0,0 @@
-/*
- * Portions Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/*
- * (C) Copyright IBM Corp. 1999-2003 - All Rights Reserved
- *
- * The original version of this source code and documentation is
- * copyrighted and owned by IBM. These materials are provided
- * under terms of a License Agreement between IBM and Sun.
- * This technology is protected by multiple US and International
- * patents. This notice and attribution to IBM may not be removed.
- */
-
-/*
-* file name: ubidi.h
-* encoding: US-ASCII
-* tab size: 8 (not used)
-* indentation:4
-*
-* created on: 1999jul27
-* created by: Markus W. Scherer
-*/
-
-#ifndef UBIDI_H
-#define UBIDI_H
-
-#include "utypes.h"
-#include "uchardir.h"
-
-/*
- * javadoc-style comments are intended to be transformed into HTML
- * using DOC++ - see
- * http://www.zib.de/Visual/software/doc++/index.html .
- *
- * The HTML documentation is created with
- * doc++ -H ubidi.h
- *
- * The following #define trick allows us to do it all in one file
- * and still be able to compile it.
- */
-#define DOCXX_TAG
-#define BIDI_SAMPLE_CODE
-
-/**
- * @name BiDi algorithm for ICU
- *
- * <h2>BiDi algorithm for ICU</h2>
- *
- * This is an implementation of the Unicode Bidirectional algorithm.
- * The algorithm is defined in the
- * <a href="http://www.unicode.org/unicode/reports/tr9/">Unicode Technical Report 9</a>,
- * version 5, also described in The Unicode Standard, Version 3.0 .<p>
- *
- * <h3>General remarks about the API:</h3>
- *
- * In functions with an error code parameter,
- * the <code>pErrorCode</code> pointer must be valid
- * and the value that it points to must not indicate a failure before
- * the function call. Otherwise, the function returns immediately.
- * After the function call, the value indicates success or failure.<p>
- *
- * The <quote>limit</quote> of a sequence of characters is the position just after their
- * last character, i.e., one more than that position.<p>
- *
- * Some of the API functions provide access to <quote>runs</quote>.
- * Such a <quote>run</quote> is defined as a sequence of characters
- * that are at the same embedding level
- * after performing the BiDi algorithm.<p>
- *
- * @author Markus W. Scherer
- */
-DOCXX_TAG
-/*@{*/
-
-/**
- * UBiDiLevel is the type of the level values in this
- * BiDi implementation.
- * It holds an embedding level and indicates the visual direction
- * by its bit 0 (even/odd value).<p>
- *
- * It can also hold non-level values for the
- * <code>paraLevel</code> and <code>embeddingLevels</code>
- * arguments of <code>ubidi_setPara()</code>; there:
- * <ul>
- * <li>bit 7 of an <code>embeddingLevels[]</code>
- * value indicates whether the using application is
- * specifying the level of a character to <i>override</i> whatever the
- * BiDi implementation would resolve it to.</li>
- * <li><code>paraLevel</code> can be set to the
- * pesudo-level values <code>UBIDI_DEFAULT_LTR</code>
- * and <code>UBIDI_DEFAULT_RTL</code>.</li>
- *
- * @see ubidi_setPara
- *
- * <p>The related constants are not real, valid level values.
- * <code>UBIDI_DEFAULT_XXX</code> can be used to specify
- * a default for the paragraph level for
- * when the <code>ubidi_setPara()</code> function
- * shall determine it but there is no
- * strongly typed character in the input.<p>
- *
- * Note that the value for <code>UBIDI_DEFAULT_LTR</code> is even
- * and the one for <code>UBIDI_DEFAULT_RTL</code> is odd,
- * just like with normal LTR and RTL level values -
- * these special values are designed that way. Also, the implementation
- * assumes that UBIDI_MAX_EXPLICIT_LEVEL is odd.
- *
- * @see UBIDI_DEFAULT_LTR
- * @see UBIDI_DEFAULT_RTL
- * @see UBIDI_LEVEL_OVERRIDE
- * @see UBIDI_MAX_EXPLICIT_LEVEL
- */
-typedef uint8_t UBiDiLevel;
-
-/** @memo If there is no strong character, then set the paragraph level to 0 (left-to-right). */
-#define UBIDI_DEFAULT_LTR 0xfe
-
-/** @memo If there is no strong character, then set the paragraph level to 1 (right-to-left). */
-#define UBIDI_DEFAULT_RTL 0xff
-
-/**
- * @memo Maximum explicit embedding level
- * (The maximum resolved level can be up to <code>UBIDI_MAX_EXPLICIT_LEVEL+1</code>).
- */
-#define UBIDI_MAX_EXPLICIT_LEVEL 61
-
-/** @memo Bit flag for level input: overrides directional properties. */
-#define UBIDI_LEVEL_OVERRIDE 0x80
-
-/**
- * @memo <code>UBiDiDirection</code> values indicate the text direction.
- */
-enum UBiDiDirection {
- /** @memo All left-to-right text. This is a 0 value. */
- UBIDI_LTR,
- /** @memo All right-to-left text. This is a 1 value. */
- UBIDI_RTL,
- /** @memo Mixed-directional text. */
- UBIDI_MIXED
-};
-
-typedef enum UBiDiDirection UBiDiDirection;
-
-/**
- * Forward declaration of the <code>UBiDi</code> structure for the declaration of
- * the API functions. Its fields are implementation-specific.<p>
- * This structure holds information about a paragraph of text
- * with BiDi-algorithm-related details, or about one line of
- * such a paragraph.<p>
- * Reordering can be done on a line, or on a paragraph which is
- * then interpreted as one single line.
- */
-struct UBiDi;
-
-typedef struct UBiDi UBiDi;
-
-/**
- * Allocate a <code>UBiDi</code> structure.
- * Such an object is initially empty. It is assigned
- * the BiDi properties of a paragraph by <code>ubidi_setPara()</code>
- * or the BiDi properties of a line of a paragraph by
- * <code>ubidi_getLine()</code>.<p>
- * This object can be reused for as long as it is not deallocated
- * by calling <code>ubidi_close()</code>.<p>
- * <code>ubidi_set()</code> will allocate additional memory for
- * internal structures as necessary.
- *
- * @return An empty <code>UBiDi</code> object.
- */
-U_CAPI UBiDi * U_EXPORT2
-ubidi_open();
-
-/**
- * Allocate a <code>UBiDi</code> structure with preallocated memory
- * for internal structures.
- * This function provides a <code>UBiDi</code> object like <code>ubidi_open()</code>
- * with no arguments, but it also preallocates memory for internal structures
- * according to the sizings supplied by the caller.<p>
- * Subsequent functions will not allocate any more memory, and are thus
- * guaranteed not to fail because of lack of memory.<p>
- * The preallocation can be limited to some of the internal memory
- * by setting some values to 0 here. That means that if, e.g.,
- * <code>maxRunCount</code> cannot be reasonably predetermined and should not
- * be set to <code>maxLength</code> (the only failproof value) to avoid
- * wasting memory, then <code>maxRunCount</code> could be set to 0 here
- * and the internal structures that are associated with it will be allocated
- * on demand, just like with <code>ubidi_open()</code>.
- *
- * @param maxLength is the maximum paragraph or line length that internal memory
- * will be preallocated for. An attempt to associate this object with a
- * longer text will fail, unless this value is 0, which leaves the allocation
- * up to the implementation.
- *
- * @param maxRunCount is the maximum anticipated number of same-level runs
- * that internal memory will be preallocated for. An attempt to access
- * visual runs on an object that was not preallocated for as many runs
- * as the text was actually resolved to will fail,
- * unless this value is 0, which leaves the allocation up to the implementation.<p>
- * The number of runs depends on the actual text and maybe anywhere between
- * 1 and <code>maxLength</code>. It is typically small.<p>
- *
- * @param pErrorCode must be a valid pointer to an error code value,
- * which must not indicate a failure before the function call.
- *
- * @return An empty <code>UBiDi</code> object with preallocated memory.
- */
-U_CAPI UBiDi * U_EXPORT2
-ubidi_openSized(int32_t maxLength, int32_t maxRunCount, UErrorCode *pErrorCode);
-
-/**
- * <code>ubidi_close()</code> must be called to free the memory
- * associated with a UBiDi object.<p>
- *
- * <strong>Important: </strong>
- * If a <code>UBiDi</code> object is the <quote>child</quote>
- * of another one (its <quote>parent</quote>), after calling
- * <code>ubidi_setLine()</code>, then the child object must
- * be destroyed (closed) or reused (by calling
- * <code>ubidi_setPara()</code> or <code>ubidi_setLine()</code>)
- * before the parent object.
- *
- * @param pBiDi is a <code>UBiDi</code> object.
- *
- * @see ubidi_setPara
- * @see ubidi_setLine
- */
-U_CAPI void U_EXPORT2
-ubidi_close(UBiDi *pBiDi);
-
-/**
- * Perform the Unicode BiDi algorithm. It is defined in the
- * <a href="http://www.unicode.org/unicode/reports/tr9/">Unicode Technical Report 9</a>,
- * version 5,
- * also described in The Unicode Standard, Version 3.0 .<p>
- *
- * This function takes a single plain text paragraph with or without
- * externally specified embedding levels from <quote>styled</quote> text
- * and computes the left-right-directionality of each character.<p>
- *
- * If the entire paragraph consists of text of only one direction, 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.<br>
- * 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.<p>
- *
- * The text must be externally split into separate paragraphs (rule P1).
- * Paragraph separators (B) should appear at most at the very end.
- *
- * @param pBiDi A <code>UBiDi</code> object allocated with <code>ubidi_open()</code>
- * which will be set to contain the reordering information,
- * especially the resolved levels for all the characters in <code>text</code>.
- *
- * @param text is a pointer to the single-paragraph text that the
- * BiDi algorithm will be performed on
- * (step (P1) of the algorithm is performed externally).
- * <strong>The text must be (at least) <code>length</code> long.</strong>
- *
- * @param length is the length of the text; if <code>length==-1</code> then
- * the text must be zero-terminated.
- *
- * @param paraLevel specifies the default level for the paragraph;
- * it is typically 0 (LTR) or 1 (RTL).
- * If the function shall determine the paragraph level from the text,
- * then <code>paraLevel</code> can be set to
- * either <code>UBIDI_DEFAULT_LTR</code>
- * or <code>UBIDI_DEFAULT_RTL</code>;
- * if there is no strongly typed character, then
- * the desired default is used (0 for LTR or 1 for RTL).
- * Any other value between 0 and <code>UBIDI_MAX_EXPLICIT_LEVEL</code> is also valid,
- * with odd levels indicating RTL.
- *
- * @param embeddingLevels (in) 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
- * <code>UBIDI_LEVEL_OVERRIDE</code> bit set.<p>
- * Except for that bit, it must be
- * <code>paraLevel<=embeddingLevels[]<=UBIDI_MAX_EXPLICIT_LEVEL</code>.<p>
- * <strong>Caution: </strong>A copy of this pointer, not of the levels,
- * will be stored in the <code>UBiDi</code> object;
- * the <code>embeddingLevels</code> array must not be
- * deallocated before the <code>UBiDi</code> structure is destroyed or reused,
- * and the <code>embeddingLevels</code>
- * should not be modified to avoid unexpected results on subsequent BiDi operations.
- * However, the <code>ubidi_setPara()</code> and
- * <code>ubidi_setLine()</code> functions may modify some or all of the levels.<p>
- * After the <code>UBiDi</code> object is reused or destroyed, the caller
- * must take care of the deallocation of the <code>embeddingLevels</code> array.<p>
- * <strong>The <code>embeddingLevels</code> array must be
- * at least <code>length</code> long.</strong>
- *
- * @param pErrorCode must be a valid pointer to an error code value,
- * which must not indicate a failure before the function call.
- */
-U_CAPI void U_EXPORT2
-ubidi_setPara(UBiDi *pBiDi, const UChar *text, int32_t length,
- UBiDiLevel paraLevel, UBiDiLevel *embeddingLevels,
- UErrorCode *pErrorCode);
-
-/**
- * <code>ubidi_getLine()</code> sets a <code>UBiDi</code> to
- * contain the reordering information, especially the resolved levels,
- * for all the characters in a line of text. This line of text is
- * specified by referring to a <code>UBiDi</code> object representing
- * this information for a paragraph of text, and by specifying
- * a range of indexes in this paragraph.<p>
- * In the new line object, the indexes will range from 0 to <code>limit-start</code>.<p>
- *
- * This is used after calling <code>ubidi_setPara()</code>
- * for a paragraph, and after line-breaking on that paragraph.
- * It is not necessary if the paragraph is treated as a single line.<p>
- *
- * After line-breaking, rules (L1) and (L2) for the treatment of
- * trailing WS and for reordering are performed on
- * a <code>UBiDi</code> object that represents a line.<p>
- *
- * <strong>Important: </strong><code>pLineBiDi</code> shares data with
- * <code>pParaBiDi</code>.
- * You must destroy or reuse <code>pLineBiDi</code> before <code>pParaBiDi</code>.
- * In other words, you must destroy or reuse the <code>UBiDi</code> object for a line
- * before the object for its parent paragraph.
- *
- * @param pParaBiDi is the parent paragraph object.
- *
- * @param start is the line's first index into the paragraph text.
- *
- * @param limit is just behind the line's last index into the paragraph text
- * (its last index +1).<br>
- * It must be <code>0<=start<=limit<=</code>paragraph length.
- *
- * @param pLineBiDi is the object that will now represent a line of the paragraph.
- *
- * @param pErrorCode must be a valid pointer to an error code value,
- * which must not indicate a failure before the function call.
- *
- * @see ubidi_setPara
- */
-U_CAPI void U_EXPORT2
-ubidi_setLine(const UBiDi *pParaBiDi,
- int32_t start, int32_t limit,
- UBiDi *pLineBiDi,
- UErrorCode *pErrorCode);
-
-/**
- * Get the directionality of the text.
- *
- * @param pBiDi is the paragraph or line <code>UBiDi</code> object.
- *
- * @return A <code>UBIDI_XXX</code> value that indicates if the entire text
- * represented by this object is unidirectional,
- * and which direction, or if it is mixed-directional.
- *
- * @see UBiDiDirection
- */
-U_CAPI UBiDiDirection U_EXPORT2
-ubidi_getDirection(const UBiDi *pBiDi);
-
-/**
- * Get the length of the text.
- *
- * @param pBiDi is the paragraph or line <code>UBiDi</code> object.
- *
- * @return The length of the text that the UBiDi object was created for.
- */
-U_CAPI int32_t U_EXPORT2
-ubidi_getLength(const UBiDi *pBiDi);
-
-/**
- * Get the paragraph level of the text.
- *
- * @param pBiDi is the paragraph or line <code>UBiDi</code> object.
- *
- * @return The paragraph level.
- *
- * @see UBiDiLevel
- */
-U_CAPI UBiDiLevel U_EXPORT2
-ubidi_getParaLevel(const UBiDi *pBiDi);
-
-/**
- * Get the level for one character.
- *
- * @param pBiDi is the paragraph or line <code>UBiDi</code> object.
- *
- * @param charIndex the index of a character.
- *
- * @return The level for the character at charIndex.
- *
- * @see UBiDiLevel
- */
-U_CAPI UBiDiLevel U_EXPORT2
-ubidi_getLevelAt(const UBiDi *pBiDi, int32_t charIndex);
-
-/**
- * Get an array of levels for each character.<p>
- *
- * Note that this function may allocate memory under some
- * circumstances, unlike <code>ubidi_getLevelAt()</code>.
- *
- * @param pBiDi is the paragraph or line <code>UBiDi</code> object.
- *
- * @param pErrorCode must be a valid pointer to an error code value,
- * which must not indicate a failure before the function call.
- *
- * @return The levels array for the text,
- * or <code>NULL</code> if an error occurs.
- *
- * @see UBiDiLevel
- */
-U_CAPI const UBiDiLevel * U_EXPORT2
-ubidi_getLevels(UBiDi *pBiDi, UErrorCode *pErrorCode);
-
-/**
- * Get a logical run.
- * This function returns information about a run and is used
- * to retrieve runs in logical order.<p>
- * This is especially useful for line-breaking on a paragraph.
- *
- * @param pBiDi is the paragraph or line <code>UBiDi</code> object.
- *
- * @param logicalStart is the first character of the run.
- *
- * @param pLogicalLimit will receive the limit of the run.
- * The l-value that you point to here may be the
- * same expression (variable) as the one for
- * <code>logicalStart</code>.
- * This pointer can be <code>NULL</code> if this
- * value is not necessary.
- *
- * @param pLevel will receive the level of the run.
- * This pointer can be <code>NULL</code> if this
- * value is not necessary.
- */
-U_CAPI void U_EXPORT2
-ubidi_getLogicalRun(const UBiDi *pBiDi, int32_t logicalStart,
- int32_t *pLogicalLimit, UBiDiLevel *pLevel);
-
-/**
- * Get the number of runs.
- * This function may invoke the actual reordering on the
- * <code>UBiDi</code> object, after <code>ubidi_setPara()</code>
- * may have resolved only the levels of the text. Therefore,
- * <code>ubidi_countRuns()</code> may have to allocate memory,
- * and may fail doing so.
- *
- * @param pBiDi is the paragraph or line <code>UBiDi</code> object.
- *
- * @param pErrorCode must be a valid pointer to an error code value,
- * which must not indicate a failure before the function call.
- *
- * @return The number of runs.
- */
-U_CAPI int32_t U_EXPORT2
-ubidi_countRuns(UBiDi *pBiDi, UErrorCode *pErrorCode);
-
-/**
- * Get one run's logical start, length, and directionality,
- * which can be 0 for LTR or 1 for RTL.
- * In an RTL run, the character at the logical start is
- * visually on the right of the displayed run.
- * The length is the number of characters in the run.<p>
- * <code>ubidi_countRuns()</code> should be called
- * before the runs are retrieved.
- *
- * @param pBiDi is the paragraph or line <code>UBiDi</code> object.
- *
- * @param runIndex is the number of the run in visual order, in the
- * range <code>[0..ubidi_countRuns(pBiDi)-1]</code>.
- *
- * @param pLogicalStart is the first logical character index in the text.
- * The pointer may be <code>NULL</code> if this index is not needed.
- *
- * @param pLength is the number of characters (at least one) in the run.
- * The pointer may be <code>NULL</code> if this is not needed.
- *
- * @return the directionality of the run,
- * <code>UBIDI_LTR==0</code> or <code>UBIDI_RTL==1</code>,
- * never <code>UBIDI_MIXED</code>.
- *
- * @see ubidi_countRuns
- *
- * Example:
- * <pre>
- * int32_t i, count=ubidi_countRuns(pBiDi),
- * logicalStart, visualIndex=0, length;
- * for(i=0; i<count; ++i) {
- * if(UBIDI_LTR==ubidi_getVisualRun(pBiDi, i, &logicalStart, &length)) {
- * do { // LTR
- * show_char(text[logicalStart++], visualIndex++);
- * } while(--length>0);
- * } else {
- * logicalStart+=length; // logicalLimit
- * do { // RTL
- * show_char(text[--logicalStart], visualIndex++);
- * } while(--length>0);
- * }
- * }
- * </pre>
- *
- * Note that in right-to-left runs, code like this places
- * modifier letters before base characters and second surrogates
- * before first ones.
- */
-U_CAPI UBiDiDirection U_EXPORT2
-ubidi_getVisualRun(UBiDi *pBiDi, int32_t runIndex,
- int32_t *pLogicalStart, int32_t *pLength);
-
-/**
- * Get the visual position from a logical text position.
- * If such a mapping is used many times on the same
- * <code>UBiDi</code> object, then calling
- * <code>ubidi_getLogicalMap()</code> is more efficient.<p>
- *
- * Note that in right-to-left runs, this mapping places
- * modifier letters before base characters and second surrogates
- * before first ones.
- *
- * @param pBiDi is the paragraph or line <code>UBiDi</code> object.
- *
- * @param logicalIndex is the index of a character in the text.
- *
- * @param pErrorCode must be a valid pointer to an error code value,
- * which must not indicate a failure before the function call.
- *
- * @return The visual position of this character.
- *
- * @see ubidi_getLogicalMap
- * @see ubidi_getLogicalIndex
- */
-U_CAPI int32_t U_EXPORT2
-ubidi_getVisualIndex(UBiDi *pBiDi, int32_t logicalIndex, UErrorCode *pErrorCode);
-
-/**
- * Get the logical text position from a visual position.
- * If such a mapping is used many times on the same
- * <code>UBiDi</code> object, then calling
- * <code>ubidi_getVisualMap()</code> is more efficient.<p>
- *
- * This is the inverse function to <code>ubidi_getVisualIndex()</code>.
- *
- * @param pBiDi is the paragraph or line <code>UBiDi</code> object.
- *
- * @param visualIndex is the visual position of a character.
- *
- * @param pErrorCode must be a valid pointer to an error code value,
- * which must not indicate a failure before the function call.
- *
- * @return The index of this character in the text.
- *
- * @see ubidi_getVisualMap
- * @see ubidi_getVisualIndex
- */
-U_CAPI int32_t U_EXPORT2
-ubidi_getLogicalIndex(UBiDi *pBiDi, int32_t visualIndex, UErrorCode *pErrorCode);
-
-/**
- * Get a logical-to-visual index map (array) for the characters in the UBiDi
- * (paragraph or line) object.
- *
- * @param pBiDi is the paragraph or line <code>UBiDi</code> object.
- *
- * @param indexMap is a pointer to an array of <code>ubidi_getLength()</code>
- * indexes which will reflect the reordering of the characters.
- * The array does not need to be initialized.<p>
- * The index map will result in <code>indexMap[logicalIndex]==visualIndex</code>.<p>
- *
- * @param pErrorCode must be a valid pointer to an error code value,
- * which must not indicate a failure before the function call.
- *
- * @see ubidi_getVisualMap
- * @see ubidi_getVisualIndex
- */
-U_CAPI void U_EXPORT2
-ubidi_getLogicalMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode);
-
-/**
- * Get a visual-to-logical index map (array) for the characters in the UBiDi
- * (paragraph or line) object.
- *
- * @param pBiDi is the paragraph or line <code>UBiDi</code> object.
- *
- * @param indexMap is a pointer to an array of <code>ubidi_getLength()</code>
- * indexes which will reflect the reordering of the characters.
- * The array does not need to be initialized.<p>
- * The index map will result in <code>indexMap[visualIndex]==logicalIndex</code>.<p>
- *
- * @param pErrorCode must be a valid pointer to an error code value,
- * which must not indicate a failure before the function call.
- *
- * @see ubidi_getLogicalMap
- * @see ubidi_getLogicalIndex
- */
-U_CAPI void U_EXPORT2
-ubidi_getVisualMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode);
-
-/**
- * This is a convenience function that does not use a UBiDi object.
- * It is intended to be used for when an application has determined the levels
- * of objects (character sequences) and just needs to have them reordered (L2).
- * This is equivalent to using <code>ubidi_getLogicalMap</code> on a
- * <code>UBiDi</code> object.
- *
- * @param levels is an array with <code>length</code> levels that have been determined by
- * the application.
- *
- * @param length is the number of levels in the array, or, semantically,
- * the number of objects to be reordered.
- * It must be <code>length>0</code>.
- *
- * @param indexMap is a pointer to an array of <code>length</code>
- * indexes which will reflect the reordering of the characters.
- * The array does not need to be initialized.<p>
- * The index map will result in <code>indexMap[logicalIndex]==visualIndex</code>.
- */
-U_CAPI void U_EXPORT2
-ubidi_reorderLogical(const UBiDiLevel *levels, int32_t length, int32_t *indexMap);
-
-/**
- * This is a convenience function that does not use a UBiDi object.
- * It is intended to be used for when an application has determined the levels
- * of objects (character sequences) and just needs to have them reordered (L2).
- * This is equivalent to using <code>ubidi_getVisualMap</code> on a
- * <code>UBiDi</code> object.
- *
- * @param levels is an array with <code>length</code> levels that have been determined by
- * the application.
- *
- * @param length is the number of levels in the array, or, semantically,
- * the number of objects to be reordered.
- * It must be <code>length>0</code>.
- *
- * @param indexMap is a pointer to an array of <code>length</code>
- * indexes which will reflect the reordering of the characters.
- * The array does not need to be initialized.<p>
- * The index map will result in <code>indexMap[visualIndex]==logicalIndex</code>.
- */
-U_CAPI void U_EXPORT2
-ubidi_reorderVisual(const UBiDiLevel *levels, int32_t length, int32_t *indexMap);
-
-/**
- * Invert an index map.
- * The one-to-one index mapping of the first map is inverted and written to
- * the second one.
- *
- * @param srcMap is an array with <code>length</code> indexes
- * which define the original mapping.
- *
- * @param destMap is an array with <code>length</code> indexes
- * which will be filled with the inverse mapping.
- *
- * @param length is the length of each array.
- */
-U_CAPI void U_EXPORT2
-ubidi_invertMap(const int32_t *srcMap, int32_t *destMap, int32_t length);
-
-/**
- * @name Sample code for the ICU BiDi API
- *
- * <h2>Rendering a paragraph with the ICU BiDi API</h2>
- *
- * 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.
- *
- * <p>The basic assumptions are:</p>
- * <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>
- *
- * <pre>
- * #include "ubidi.h"
- *
- * typedef enum {
- * styleNormal=0, styleSelected=1,
- * styleBold=2, styleItalics=4,
- * styleSuper=8, styleSub=16
- * } Style;
- *
- * typedef struct { int32_t limit; Style style; } StyleRun;
- *
- * int getTextWidth(const UChar *text, int32_t start, int32_t limit,
- * const StyleRun *styleRuns, int styleRunCount);
- *
- * // set *pLimit and *pStyleRunLimit for a line
- * // from text[start] and from styleRuns[styleRunStart]
- * // using ubidi_getLogicalRun(para, ...)
- * void getLineBreak(const UChar *text, int32_t start, int32_t *pLimit,
- * UBiDi *para,
- * const StyleRun *styleRuns, int styleRunStart, int *pStyleRunLimit,
- * int *pLineWidth);
- *
- * // render runs on a line sequentially, always from left to right
- *
- * // prepare rendering a new line
- * void startLine(UBiDiDirection textDirection, int lineWidth);
- *
- * // render a run of text and advance to the right by the run width
- * // the text[start..limit-1] is always in logical order
- * void renderRun(const UChar *text, int32_t start, int32_t limit,
- * UBiDiDirection textDirection, Style 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
- * void renderDirectionalRun(const UChar *text,
- * int32_t start, int32_t limit,
- * UBiDiDirection direction,
- * const StyleRun *styleRuns, int styleRunCount) {
- * int i;
- *
- * // iterate over style runs
- * if(direction==UBIDI_LTR) {
- * int styleLimit;
- *
- * for(i=0; i<styleRunCount; ++i) {
- * styleLimit=styleRun[i].limit;
- * if(start<styleLimit) {
- * if(styleLimit>limit) { styleLimit=limit; }
- * renderRun(text, start, styleLimit,
- * direction, styleRun[i].style);
- * if(styleLimit==limit) { break; }
- * start=styleLimit;
- * }
- * }
- * } else {
- * int styleStart;
- *
- * for(i=styleRunCount-1; i>=0; --i) {
- * if(i>0) {
- * styleStart=styleRun[i-1].limit;
- * } else {
- * styleStart=0;
- * }
- * if(limit>=styleStart) {
- * if(styleStart<start) { styleStart=start; }
- * renderRun(text, styleStart, limit,
- * direction, styleRun[i].style);
- * if(styleStart==start) { break; }
- * limit=styleStart;
- * }
- * }
- * }
- * }
- *
- * // the line object represents text[start..limit-1]
- * void renderLine(UBiDi *line, const UChar *text,
- * int32_t start, int32_t limit,
- * const StyleRun *styleRuns, int styleRunCount) {
- * UBiDiDirection direction=ubidi_getDirection(line);
- * if(direction!=UBIDI_MIXED) {
- * // unidirectional
- * if(styleRunCount<=1) {
- * renderRun(text, start, limit, direction, styleRuns[0].style);
- * } else {
- * renderDirectionalRun(text, start, limit,
- * direction, styleRuns, styleRunCount);
- * }
- * } else {
- * // mixed-directional
- * int32_t count, i, length;
- * UBiDiLevel level;
- *
- * count=ubidi_countRuns(para, pErrorCode);
- * if(U_SUCCESS(*pErrorCode)) {
- * if(styleRunCount<=1) {
- * Style style=styleRuns[0].style;
- *
- * // iterate over directional runs
- * for(i=0; i<count; ++i) {
- * direction=ubidi_getVisualRun(para, i, &start, &length);
- * renderRun(text, start, start+length, direction, style);
- * }
- * } else {
- * int32_t j;
- *
- * // iterate over both directional and style runs
- * for(i=0; i<count; ++i) {
- * direction=ubidi_getVisualRun(line, i, &start, &length);
- * renderDirectionalRun(text, start, start+length,
- * direction, styleRuns, styleRunCount);
- * }
- * }
- * }
- * }
- * }
- *
- * void renderParagraph(const UChar *text, int32_t length,
- * UBiDiDirection textDirection,
- * const StyleRun *styleRuns, int styleRunCount,
- * int lineWidth,
- * UErrorCode *pErrorCode) {
- * UBiDi *para;
- *
- * if(pErrorCode==NULL || U_FAILURE(*pErrorCode) || length<=0) {
- * return;
- * }
- *
- * para=ubidi_openSized(length, 0, pErrorCode);
- * if(para==NULL) { return; }
- *
- * ubidi_setPara(para, text, length,
- * textDirection ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR,
- * NULL, pErrorCode);
- * if(U_SUCCESS(*pErrorCode)) {
- * UBiDiLevel paraLevel=1&ubidi_getParaLevel(para);
- * StyleRun styleRun={ length, styleNormal };
- * int width;
- *
- * if(styleRuns==NULL || styleRunCount<=0) {
- * styleRunCount=1;
- * styleRuns=&styleRun;
- * }
- *
- * // assume styleRuns[styleRunCount-1].limit>=length
- *
- * 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 {
- * UBiDi *line;
- *
- * // we need to render several lines
- * line=ubidi_openSized(length, 0, pErrorCode);
- * if(line!=NULL) {
- * int32_t start=0, limit;
- * int styleRunStart=0, styleRunLimit;
- *
- * for(;;) {
- * limit=length;
- * styleRunLimit=styleRunCount;
- * getLineBreak(text, start, &limit, para,
- * styleRuns, styleRunStart, &styleRunLimit,
- * &width);
- * ubidi_setLine(para, start, limit, line, pErrorCode);
- * if(U_SUCCESS(*pErrorCode)) {
- * // prepare rendering a new line
- * // from either left or right
- * startLine(paraLevel, width);
- *
- * renderLine(line, text, start, limit,
- * styleRuns+styleRunStart,
- * styleRunLimit-styleRunStart);
- * }
- * if(limit==length) { break; }
- * start=limit;
- * styleRunStart=styleRunLimit-1;
- * if(start>=styleRuns[styleRunStart].limit) {
- * ++styleRunStart;
- * }
- * }
- *
- * ubidi_close(line);
- * }
- * }
- * }
- *
- * ubidi_close(para);
- * }
- * </pre>
- */
-BIDI_SAMPLE_CODE
-/*@{*/
-/*@}*/
-
-/*@}*/
-
-#endif
--- a/jdk/src/share/native/sun/font/bidi/ubidiimp.h Thu May 28 18:11:07 2009 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-/*
- * Portions Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/*
- * (C) Copyright IBM Corp. 1999-2003 - All Rights Reserved
- *
- * The original version of this source code and documentation is
- * copyrighted and owned by IBM. These materials are provided
- * under terms of a License Agreement between IBM and Sun.
- * This technology is protected by multiple US and International
- * patents. This notice and attribution to IBM may not be removed.
- */
-
-/*
-* file name: ubidiimp.h
-* encoding: US-ASCII
-* tab size: 8 (not used)
-* indentation:4
-*
-* created on: 1999aug06
-* created by: Markus W. Scherer
-*/
-
-#ifndef UBIDIIMP_H
-#define UBIDIIMP_H
-
-/* set import/export definitions */
-#ifdef U_COMMON_IMPLEMENTATION
-
-#include "utypes.h"
-#include "uchardir.h"
-
-/* miscellaneous definitions ---------------------------------------------- */
-
-typedef uint8_t DirProp;
-typedef uint32_t Flags;
-
-/* Comparing the description of the BiDi algorithm with this implementation
- is easier with the same names for the BiDi types in the code as there.
- See UCharDirection in uchar.h .
-*/
-enum {
- L= U_LEFT_TO_RIGHT,
- R= U_RIGHT_TO_LEFT,
- EN= U_EUROPEAN_NUMBER,
- ES= U_EUROPEAN_NUMBER_SEPARATOR,
- ET= U_EUROPEAN_NUMBER_TERMINATOR,
- AN= U_ARABIC_NUMBER,
- CS= U_COMMON_NUMBER_SEPARATOR,
- B= U_BLOCK_SEPARATOR,
- S= U_SEGMENT_SEPARATOR,
- WS= U_WHITE_SPACE_NEUTRAL,
- ON= U_OTHER_NEUTRAL,
- LRE=U_LEFT_TO_RIGHT_EMBEDDING,
- LRO=U_LEFT_TO_RIGHT_OVERRIDE,
- AL= U_RIGHT_TO_LEFT_ARABIC,
- RLE=U_RIGHT_TO_LEFT_EMBEDDING,
- RLO=U_RIGHT_TO_LEFT_OVERRIDE,
- PDF=U_POP_DIRECTIONAL_FORMAT,
- NSM=U_DIR_NON_SPACING_MARK,
- BN= U_BOUNDARY_NEUTRAL,
- dirPropCount
-};
-
-/*
- * Sometimes, bit values are more appropriate
- * to deal with directionality properties.
- * Abbreviations in these macro names refer to names
- * used in the BiDi algorithm.
- */
-#define DIRPROP_FLAG(dir) (1UL<<(dir))
-
-/* special flag for multiple runs from explicit embedding codes */
-#define DIRPROP_FLAG_MULTI_RUNS (1UL<<31)
-
-/* are there any characters that are LTR or RTL? */
-#define MASK_LTR (DIRPROP_FLAG(L)|DIRPROP_FLAG(EN)|DIRPROP_FLAG(AN)|DIRPROP_FLAG(LRE)|DIRPROP_FLAG(LRO))
-#define MASK_RTL (DIRPROP_FLAG(R)|DIRPROP_FLAG(AL)|DIRPROP_FLAG(RLE)|DIRPROP_FLAG(RLO))
-
-/* explicit embedding codes */
-#define MASK_LRX (DIRPROP_FLAG(LRE)|DIRPROP_FLAG(LRO))
-#define MASK_RLX (DIRPROP_FLAG(RLE)|DIRPROP_FLAG(RLO))
-#define MASK_OVERRIDE (DIRPROP_FLAG(LRO)|DIRPROP_FLAG(RLO))
-
-#define MASK_EXPLICIT (MASK_LRX|MASK_RLX|DIRPROP_FLAG(PDF))
-#define MASK_BN_EXPLICIT (DIRPROP_FLAG(BN)|MASK_EXPLICIT)
-
-/* paragraph and segment separators */
-#define MASK_B_S (DIRPROP_FLAG(B)|DIRPROP_FLAG(S))
-
-/* all types that are counted as White Space or Neutral in some steps */
-#define MASK_WS (MASK_B_S|DIRPROP_FLAG(WS)|MASK_BN_EXPLICIT)
-#define MASK_N (DIRPROP_FLAG(ON)|MASK_WS)
-
-/* all types that are included in a sequence of European Terminators for (W5) */
-#define MASK_ET_NSM_BN (DIRPROP_FLAG(ET)|DIRPROP_FLAG(NSM)|MASK_BN_EXPLICIT)
-
-/* types that are neutrals or could becomes neutrals in (Wn) */
-#define MASK_POSSIBLE_N (DIRPROP_FLAG(CS)|DIRPROP_FLAG(ES)|DIRPROP_FLAG(ET)|MASK_N)
-
-/*
- * These types may be changed to "e",
- * the embedding type (L or R) of the run,
- * in the BiDi algorithm (N2)
- */
-#define MASK_EMBEDDING (DIRPROP_FLAG(NSM)|MASK_POSSIBLE_N)
-
-/* the dirProp's L and R are defined to 0 and 1 values in UCharDirection */
-#define GET_LR_FROM_LEVEL(level) ((DirProp)((level)&1))
-
-#define IS_DEFAULT_LEVEL(level) (((level)&0xfe)==0xfe)
-
-/* handle surrogate pairs --------------------------------------------------- */
-/* Note: dlf added for java */
-#define IS_FIRST_SURROGATE(uchar) (((uchar)&0xfc00)==0xd800)
-#define IS_SECOND_SURROGATE(uchar) (((uchar)&0xfc00)==0xdc00)
-
-/* get the UTF-32 value directly from the surrogate pseudo-characters */
-#define SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000)
-#define GET_UTF_32(first, second) (((first)<<10UL)+(second)-SURROGATE_OFFSET)
-
-/* Run structure for reordering --------------------------------------------- */
-
-typedef struct Run {
- int32_t logicalStart, /* first character of the run; b31 indicates even/odd level */
- visualLimit; /* last visual position of the run +1 */
-} Run;
-
-/* in a Run, logicalStart will get this bit set if the run level is odd */
-#define INDEX_ODD_BIT (1UL<<31)
-
-#define MAKE_INDEX_ODD_PAIR(index, level) (index|((uint32_t)level<<31))
-#define ADD_ODD_BIT_FROM_LEVEL(x, level) ((x)|=((uint32_t)level<<31))
-#define REMOVE_ODD_BIT(x) ((x)&=~INDEX_ODD_BIT)
-
-#define GET_INDEX(x) (x&~INDEX_ODD_BIT)
-#define GET_ODD_BIT(x) ((uint32_t)x>>31)
-#define IS_ODD_RUN(x) ((x&INDEX_ODD_BIT)!=0)
-#define IS_EVEN_RUN(x) ((x&INDEX_ODD_BIT)==0)
-
-U_CFUNC bool_t
-ubidi_getRuns(UBiDi *pBiDi);
-
-/* UBiDi structure ----------------------------------------------------------- */
-
-struct UBiDi {
- /* alias pointer to the current text */
- const UChar *text;
-
- /* length of the current text */
- int32_t length;
-
- /* memory sizes in bytes */
- int32_t dirPropsSize, levelsSize, runsSize;
-
- /* allocated memory */
- DirProp *dirPropsMemory;
- UBiDiLevel *levelsMemory;
- Run *runsMemory;
-
- /* indicators for whether memory may be allocated after ubidi_open() */
- bool_t mayAllocateText, mayAllocateRuns;
-
- /* arrays with one value per text-character */
- const DirProp *dirProps;
- UBiDiLevel *levels;
-
- /* are we performing an approximation of the "inverse BiDi" algorithm? */
- bool_t isInverse;
-
- /* the paragraph level */
- UBiDiLevel paraLevel;
-
- /* the overall paragraph or line directionality - see UBiDiDirection */
- UBiDiDirection direction;
-
- /* flags is a bit set for which directional properties are in the text */
- Flags flags;
-
- /* characters after trailingWSStart are WS and are */
- /* implicitly at the paraLevel (rule (L1)) - levels may not reflect that */
- int32_t trailingWSStart;
-
- /* fields for line reordering */
- int32_t runCount; /* ==-1: runs not set up yet */
- Run *runs;
-
- /* for non-mixed text, we only need a tiny array of runs (no malloc()) */
- Run simpleRuns[1];
-};
-
-/* helper function to (re)allocate memory if allowed */
-extern bool_t
-ubidi_getMemory(void **pMemory, int32_t *pSize, bool_t mayAllocate, int32_t sizeNeeded);
-
-/* helper macros for each allocated array in UBiDi */
-#define getDirPropsMemory(pBiDi, length) \
- ubidi_getMemory((void **)&(pBiDi)->dirPropsMemory, &(pBiDi)->dirPropsSize, \
- (pBiDi)->mayAllocateText, (length))
-
-#define getLevelsMemory(pBiDi, length) \
- ubidi_getMemory((void **)&(pBiDi)->levelsMemory, &(pBiDi)->levelsSize, \
- (pBiDi)->mayAllocateText, (length))
-
-#define getRunsMemory(pBiDi, length) \
- ubidi_getMemory((void **)&(pBiDi)->runsMemory, &(pBiDi)->runsSize, \
- (pBiDi)->mayAllocateRuns, (length)*sizeof(Run))
-
-/* additional macros used by ubidi_open() - always allow allocation */
-#define getInitialDirPropsMemory(pBiDi, length) \
- ubidi_getMemory((void **)&(pBiDi)->dirPropsMemory, &(pBiDi)->dirPropsSize, \
- TRUE, (length))
-
-#define getInitialLevelsMemory(pBiDi, length) \
- ubidi_getMemory((void **)&(pBiDi)->levelsMemory, &(pBiDi)->levelsSize, \
- TRUE, (length))
-
-#define getInitialRunsMemory(pBiDi, length) \
- ubidi_getMemory((void **)&(pBiDi)->runsMemory, &(pBiDi)->runsSize, \
- TRUE, (length)*sizeof(Run))
-
-#endif
-
-#endif
--- a/jdk/src/share/native/sun/font/bidi/ubidiln.c Thu May 28 18:11:07 2009 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,996 +0,0 @@
-/*
- * Portions Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/*
- * (C) Copyright IBM Corp. 1999-2003 - All Rights Reserved
- *
- * The original version of this source code and documentation is
- * copyrighted and owned by IBM. These materials are provided
- * under terms of a License Agreement between IBM and Sun.
- * This technology is protected by multiple US and International
- * patents. This notice and attribution to IBM may not be removed.
- */
-
-/*
-* file name: ubidiln.c
-* encoding: US-ASCII
-* tab size: 8 (not used)
-* indentation:4
-*
-* created on: 1999aug06
-* created by: Markus W. Scherer
-*/
-
-/* set import/export definitions */
-#ifndef U_COMMON_IMPLEMENTATION
-# define U_COMMON_IMPLEMENTATION
-#endif
-
-#include "cmemory.h"
-#include "utypes.h"
-#include "uchardir.h"
-#include "ubidi.h"
-#include "ubidiimp.h"
-
-/*
- * General remarks about the functions in this file:
- *
- * These functions deal with the aspects of potentially mixed-directional
- * text in a single paragraph or in a line of a single paragraph
- * which has already been processed according to
- * the Unicode 3.0 BiDi algorithm as defined in
- * http://www.unicode.org/unicode/reports/tr9/ , version 5,
- * also described in The Unicode Standard, Version 3.0 .
- *
- * This means that there is a UBiDi object with a levels
- * and a dirProps array.
- * paraLevel and direction are also set.
- * Only if the length of the text is zero, then levels==dirProps==NULL.
- *
- * The overall directionality of the paragraph
- * or line is used to bypass the reordering steps if possible.
- * Even purely RTL text does not need reordering there because
- * the ubidi_getLogical/VisualIndex() functions can compute the
- * index on the fly in such a case.
- *
- * The implementation of the access to same-level-runs and of the reordering
- * do attempt to provide better performance and less memory usage compared to
- * a direct implementation of especially rule (L2) with an array of
- * one (32-bit) integer per text character.
- *
- * Here, the levels array is scanned as soon as necessary, and a vector of
- * same-level-runs is created. Reordering then is done on this vector.
- * For each run of text positions that were resolved to the same level,
- * only 8 bytes are stored: the first text position of the run and the visual
- * position behind the run after reordering.
- * One sign bit is used to hold the directionality of the run.
- * This is inefficient if there are many very short runs. If the average run
- * length is <2, then this uses more memory.
- *
- * In a further attempt to save memory, the levels array is never changed
- * after all the resolution rules (Xn, Wn, Nn, In).
- * Many functions have to consider the field trailingWSStart:
- * if it is less than length, then there is an implicit trailing run
- * at the paraLevel,
- * which is not reflected in the levels array.
- * This allows a line UBiDi object to use the same levels array as
- * its paragraph parent object.
- *
- * When a UBiDi object is created for a line of a paragraph, then the
- * paragraph's levels and dirProps arrays are reused by way of setting
- * a pointer into them, not by copying. This again saves memory and forbids to
- * change the now shared levels for (L1).
- */
-
-/* prototypes --------------------------------------------------------------- */
-
-static void
-setTrailingWSStart(UBiDi *pBiDi);
-
-static void
-getSingleRun(UBiDi *pBiDi, UBiDiLevel level);
-
-static void
-reorderLine(UBiDi *pBiDi, UBiDiLevel minLevel, UBiDiLevel maxLevel);
-
-static bool_t
-prepareReorder(const UBiDiLevel *levels, int32_t length,
- int32_t *indexMap,
- UBiDiLevel *pMinLevel, UBiDiLevel *pMaxLevel);
-
-/* ubidi_setLine ------------------------------------------------------------ */
-
-U_CAPI void U_EXPORT2
-ubidi_setLine(const UBiDi *pParaBiDi,
- int32_t start, int32_t limit,
- UBiDi *pLineBiDi,
- UErrorCode *pErrorCode) {
- int32_t length;
-
- /* check the argument values */
- if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
- return;
- } else if(pParaBiDi==NULL || pLineBiDi==NULL) {
- *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
- return;
- } else if(start<0 || start>limit || limit>pParaBiDi->length) {
- *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
- return;
- }
-
- /* set the values in pLineBiDi from its pParaBiDi parent */
- pLineBiDi->text=pParaBiDi->text+start;
- length=pLineBiDi->length=limit-start;
- pLineBiDi->paraLevel=pParaBiDi->paraLevel;
-
- pLineBiDi->runs=NULL;
- pLineBiDi->flags=0;
-
- if(length>0) {
- pLineBiDi->dirProps=pParaBiDi->dirProps+start;
- pLineBiDi->levels=pParaBiDi->levels+start;
- pLineBiDi->runCount=-1;
-
- if(pParaBiDi->direction!=UBIDI_MIXED) {
- /* the parent is already trivial */
- pLineBiDi->direction=pParaBiDi->direction;
-
- /*
- * The parent's levels are all either
- * implicitly or explicitly ==paraLevel;
- * do the same here.
- */
- if(pParaBiDi->trailingWSStart<=start) {
- pLineBiDi->trailingWSStart=0;
- } else if(pParaBiDi->trailingWSStart<limit) {
- pLineBiDi->trailingWSStart=pParaBiDi->trailingWSStart-start;
- } else {
- pLineBiDi->trailingWSStart=length;
- }
- } else {
- const UBiDiLevel *levels=pLineBiDi->levels;
- int32_t i, trailingWSStart;
- UBiDiLevel level;
-
- setTrailingWSStart(pLineBiDi);
- trailingWSStart=pLineBiDi->trailingWSStart;
-
- /* recalculate pLineBiDi->direction */
- if(trailingWSStart==0) {
- /* all levels are at paraLevel */
- pLineBiDi->direction=(UBiDiDirection)(pLineBiDi->paraLevel&1);
- } else {
- /* get the level of the first character */
- level=(UBiDiLevel)(levels[0]&1);
-
- /* if there is anything of a different level, then the line is mixed */
- if(trailingWSStart<length && (pLineBiDi->paraLevel&1)!=level) {
- /* the trailing WS is at paraLevel, which differs from levels[0] */
- pLineBiDi->direction=UBIDI_MIXED;
- } else {
- /* see if levels[1..trailingWSStart-1] have the same direction as levels[0] and paraLevel */
- i=1;
- for(;;) {
- if(i==trailingWSStart) {
- /* the direction values match those in level */
- pLineBiDi->direction=(UBiDiDirection)level;
- break;
- } else if((levels[i]&1)!=level) {
- pLineBiDi->direction=UBIDI_MIXED;
- break;
- }
- ++i;
- }
- }
- }
-
- switch(pLineBiDi->direction) {
- case UBIDI_LTR:
- /* make sure paraLevel is even */
- pLineBiDi->paraLevel=(UBiDiLevel)((pLineBiDi->paraLevel+1)&~1);
-
- /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
- pLineBiDi->trailingWSStart=0;
- break;
- case UBIDI_RTL:
- /* make sure paraLevel is odd */
- pLineBiDi->paraLevel|=1;
-
- /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
- pLineBiDi->trailingWSStart=0;
- break;
- default:
- break;
- }
- }
- } else {
- /* create an object for a zero-length line */
- pLineBiDi->direction=pLineBiDi->paraLevel&1 ? UBIDI_RTL : UBIDI_LTR;
- pLineBiDi->trailingWSStart=pLineBiDi->runCount=0;
-
- pLineBiDi->dirProps=NULL;
- pLineBiDi->levels=NULL;
- }
- return;
-}
-
-U_CAPI UBiDiLevel U_EXPORT2
-ubidi_getLevelAt(const UBiDi *pBiDi, int32_t charIndex) {
- /* return paraLevel if in the trailing WS run, otherwise the real level */
- if(pBiDi==NULL || charIndex<0 || pBiDi->length<=charIndex) {
- return 0;
- } else if(pBiDi->direction!=UBIDI_MIXED || charIndex>=pBiDi->trailingWSStart) {
- return pBiDi->paraLevel;
- } else {
- return pBiDi->levels[charIndex];
- }
-}
-
-U_CAPI const UBiDiLevel * U_EXPORT2
-ubidi_getLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) {
- int32_t start, length;
-
- if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
- return NULL;
- } else if(pBiDi==NULL || (length=pBiDi->length)<=0) {
- *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
- return NULL;
- }
-
- if((start=pBiDi->trailingWSStart)==length) {
- /* the current levels array reflects the WS run */
- return pBiDi->levels;
- }
-
- /*
- * After the previous if(), we know that the levels array
- * has an implicit trailing WS run and therefore does not fully
- * reflect itself all the levels.
- * This must be a UBiDi object for a line, and
- * we need to create a new levels array.
- */
-
- if(getLevelsMemory(pBiDi, length)) {
- UBiDiLevel *levels=pBiDi->levelsMemory;
-
- if(start>0 && levels!=pBiDi->levels) {
- icu_memcpy(levels, pBiDi->levels, start);
- }
- icu_memset(levels+start, pBiDi->paraLevel, length-start);
-
- /* this new levels array is set for the line and reflects the WS run */
- pBiDi->trailingWSStart=length;
- return pBiDi->levels=levels;
- } else {
- /* out of memory */
- *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- }
-}
-
-U_CAPI void U_EXPORT2
-ubidi_getLogicalRun(const UBiDi *pBiDi, int32_t logicalStart,
- int32_t *pLogicalLimit, UBiDiLevel *pLevel) {
- int32_t length;
-
- if(pBiDi==NULL || logicalStart<0 || (length=pBiDi->length)<=logicalStart) {
- return;
- }
-
- if(pBiDi->direction!=UBIDI_MIXED || logicalStart>=pBiDi->trailingWSStart) {
- if(pLogicalLimit!=NULL) {
- *pLogicalLimit=length;
- }
- if(pLevel!=NULL) {
- *pLevel=pBiDi->paraLevel;
- }
- } else {
- UBiDiLevel *levels=pBiDi->levels;
- UBiDiLevel level=levels[logicalStart];
-
- /* search for the end of the run */
- length=pBiDi->trailingWSStart;
- while(++logicalStart<length && level==levels[logicalStart]) {}
-
- if(pLogicalLimit!=NULL) {
- *pLogicalLimit=logicalStart;
- }
- if(pLevel!=NULL) {
- *pLevel=level;
- }
- }
-}
-
-/* handle trailing WS (L1) -------------------------------------------------- */
-
-/*
- * setTrailingWSStart() sets the start index for a trailing
- * run of WS in the line. This is necessary because we do not modify
- * the paragraph's levels array that we just point into.
- * Using trailingWSStart is another form of performing (L1).
- *
- * To make subsequent operations easier, we also include the run
- * before the WS if it is at the paraLevel - we merge the two here.
- */
-static void
-setTrailingWSStart(UBiDi *pBiDi) {
- /* pBiDi->direction!=UBIDI_MIXED */
-
- const DirProp *dirProps=pBiDi->dirProps;
- UBiDiLevel *levels=pBiDi->levels;
- int32_t start=pBiDi->length;
- UBiDiLevel paraLevel=pBiDi->paraLevel;
-
- /* go backwards across all WS, BN, explicit codes */
- while(start>0 && DIRPROP_FLAG(dirProps[start-1])&MASK_WS) {
- --start;
- }
-
- /* if the WS run can be merged with the previous run then do so here */
- while(start>0 && levels[start-1]==paraLevel) {
- --start;
- }
-
- pBiDi->trailingWSStart=start;
-}
-
-/* runs API functions ------------------------------------------------------- */
-
-U_CAPI int32_t U_EXPORT2
-ubidi_countRuns(UBiDi *pBiDi, UErrorCode *pErrorCode) {
- if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
- return -1;
- } else if(pBiDi==NULL || (pBiDi->runCount<0 && !ubidi_getRuns(pBiDi))) {
- *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
- return -1;
- } else {
- return pBiDi->runCount;
- }
-}
-
-U_CAPI UBiDiDirection U_EXPORT2
-ubidi_getVisualRun(UBiDi *pBiDi, int32_t runIndex,
- int32_t *pLogicalStart, int32_t *pLength) {
- if( pBiDi==NULL || runIndex<0 ||
- (pBiDi->runCount==-1 && !ubidi_getRuns(pBiDi)) ||
- runIndex>=pBiDi->runCount
- ) {
- return UBIDI_LTR;
- } else {
- int32_t start=pBiDi->runs[runIndex].logicalStart;
- if(pLogicalStart!=NULL) {
- *pLogicalStart=GET_INDEX(start);
- }
- if(pLength!=NULL) {
- if(runIndex>0) {
- *pLength=pBiDi->runs[runIndex].visualLimit-
- pBiDi->runs[runIndex-1].visualLimit;
- } else {
- *pLength=pBiDi->runs[0].visualLimit;
- }
- }
- return (UBiDiDirection)GET_ODD_BIT(start);
- }
-}
-
-/* compute the runs array --------------------------------------------------- */
-
-/*
- * Compute the runs array from the levels array.
- * After ubidi_getRuns() returns TRUE, runCount is guaranteed to be >0
- * and the runs are reordered.
- * Odd-level runs have visualStart on their visual right edge and
- * they progress visually to the left.
- */
-U_CFUNC bool_t
-ubidi_getRuns(UBiDi *pBiDi) {
- if(pBiDi->direction!=UBIDI_MIXED) {
- /* simple, single-run case - this covers length==0 */
- getSingleRun(pBiDi, pBiDi->paraLevel);
- } else /* UBIDI_MIXED, length>0 */ {
- /* mixed directionality */
- int32_t length=pBiDi->length, limit;
-
- /*
- * If there are WS characters at the end of the line
- * and the run preceding them has a level different from
- * paraLevel, then they will form their own run at paraLevel (L1).
- * Count them separately.
- * We need some special treatment for this in order to not
- * modify the levels array which a line UBiDi object shares
- * with its paragraph parent and its other line siblings.
- * In other words, for the trailing WS, it may be
- * levels[]!=paraLevel but we have to treat it like it were so.
- */
- limit=pBiDi->trailingWSStart;
- if(limit==0) {
- /* there is only WS on this line */
- getSingleRun(pBiDi, pBiDi->paraLevel);
- } else {
- UBiDiLevel *levels=pBiDi->levels;
- int32_t i, runCount;
- UBiDiLevel level=UBIDI_DEFAULT_LTR; /* initialize with no valid level */
-
- /* count the runs, there is at least one non-WS run, and limit>0 */
- runCount=0;
- for(i=0; i<limit; ++i) {
- /* increment runCount at the start of each run */
- if(levels[i]!=level) {
- ++runCount;
- level=levels[i];
- }
- }
-
- /*
- * We don't need to see if the last run can be merged with a trailing
- * WS run because setTrailingWSStart() would have done that.
- */
- if(runCount==1 && limit==length) {
- /* There is only one non-WS run and no trailing WS-run. */
- getSingleRun(pBiDi, levels[0]);
- } else /* runCount>1 || limit<length */ {
- /* allocate and set the runs */
- Run *runs;
- int32_t runIndex, start;
- UBiDiLevel minLevel=UBIDI_MAX_EXPLICIT_LEVEL+1, maxLevel=0;
-
- /* now, count a (non-mergable) WS run */
- if(limit<length) {
- ++runCount;
- }
-
- /* runCount>1 */
- if(getRunsMemory(pBiDi, runCount)) {
- runs=pBiDi->runsMemory;
- } else {
- return FALSE;
- }
-
- /* set the runs */
- /* this could be optimized, e.g.: 464->444, 484->444, 575->555, 595->555 */
- /* however, that would take longer and make other functions more complicated */
- runIndex=0;
-
- /* search for the run limits and initialize visualLimit values with the run lengths */
- i=0;
- do {
- /* prepare this run */
- start=i;
- level=levels[i];
- if(level<minLevel) {
- minLevel=level;
- }
- if(level>maxLevel) {
- maxLevel=level;
- }
-
- /* look for the run limit */
- while(++i<limit && levels[i]==level) {}
-
- /* i is another run limit */
- runs[runIndex].logicalStart=start;
- runs[runIndex].visualLimit=i-start;
- ++runIndex;
- } while(i<limit);
-
- if(limit<length) {
- /* there is a separate WS run */
- runs[runIndex].logicalStart=limit;
- runs[runIndex].visualLimit=length-limit;
- if(pBiDi->paraLevel<minLevel) {
- minLevel=pBiDi->paraLevel;
- }
- }
-
- /* set the object fields */
- pBiDi->runs=runs;
- pBiDi->runCount=runCount;
-
- reorderLine(pBiDi, minLevel, maxLevel);
-
- /* now add the direction flags and adjust the visualLimit's to be just that */
- ADD_ODD_BIT_FROM_LEVEL(runs[0].logicalStart, levels[runs[0].logicalStart]);
- limit=runs[0].visualLimit;
- for(i=1; i<runIndex; ++i) {
- ADD_ODD_BIT_FROM_LEVEL(runs[i].logicalStart, levels[runs[i].logicalStart]);
- limit=runs[i].visualLimit+=limit;
- }
-
- /* same for the trailing WS run */
- if(runIndex<runCount) {
- ADD_ODD_BIT_FROM_LEVEL(runs[i].logicalStart, pBiDi->paraLevel);
- runs[runIndex].visualLimit+=limit;
- }
- }
- }
- }
- return TRUE;
-}
-
-/* in trivial cases there is only one trivial run; called by ubidi_getRuns() */
-static void
-getSingleRun(UBiDi *pBiDi, UBiDiLevel level) {
- /* simple, single-run case */
- pBiDi->runs=pBiDi->simpleRuns;
- pBiDi->runCount=1;
-
- /* fill and reorder the single run */
- pBiDi->runs[0].logicalStart=MAKE_INDEX_ODD_PAIR(0, level);
- pBiDi->runs[0].visualLimit=pBiDi->length;
-}
-
-/* reorder the runs array (L2) ---------------------------------------------- */
-
-/*
- * Reorder the same-level runs in the runs array.
- * Here, runCount>1 and maxLevel>=minLevel>=paraLevel.
- * All the visualStart fields=logical start before reordering.
- * The "odd" bits are not set yet.
- *
- * Reordering with this data structure lends itself to some handy shortcuts:
- *
- * Since each run is moved but not modified, and since at the initial maxLevel
- * each sequence of same-level runs consists of only one run each, we
- * don't need to do anything there and can predecrement maxLevel.
- * In many simple cases, the reordering is thus done entirely in the
- * index mapping.
- * Also, reordering occurs only down to the lowest odd level that occurs,
- * which is minLevel|1. However, if the lowest level itself is odd, then
- * in the last reordering the sequence of the runs at this level or higher
- * will be all runs, and we don't need the elaborate loop to search for them.
- * This is covered by ++minLevel instead of minLevel|=1 followed
- * by an extra reorder-all after the reorder-some loop.
- * About a trailing WS run:
- * Such a run would need special treatment because its level is not
- * reflected in levels[] if this is not a paragraph object.
- * Instead, all characters from trailingWSStart on are implicitly at
- * paraLevel.
- * However, for all maxLevel>paraLevel, this run will never be reordered
- * and does not need to be taken into account. maxLevel==paraLevel is only reordered
- * if minLevel==paraLevel is odd, which is done in the extra segment.
- * This means that for the main reordering loop we don't need to consider
- * this run and can --runCount. If it is later part of the all-runs
- * reordering, then runCount is adjusted accordingly.
- */
-static void
-reorderLine(UBiDi *pBiDi, UBiDiLevel minLevel, UBiDiLevel maxLevel) {
- Run *runs;
- UBiDiLevel *levels;
- int32_t firstRun, endRun, limitRun, runCount,
- temp;
-
- /* nothing to do? */
- if(maxLevel<=(minLevel|1)) {
- return;
- }
-
- /*
- * Reorder only down to the lowest odd level
- * and reorder at an odd minLevel in a separate, simpler loop.
- * See comments above for why minLevel is always incremented.
- */
- ++minLevel;
-
- runs=pBiDi->runs;
- levels=pBiDi->levels;
- runCount=pBiDi->runCount;
-
- /* do not include the WS run at paraLevel<=old minLevel except in the simple loop */
- if(pBiDi->trailingWSStart<pBiDi->length) {
- --runCount;
- }
-
- while(--maxLevel>=minLevel) {
- firstRun=0;
-
- /* loop for all sequences of runs */
- for(;;) {
- /* look for a sequence of runs that are all at >=maxLevel */
- /* look for the first run of such a sequence */
- while(firstRun<runCount && levels[runs[firstRun].logicalStart]<maxLevel) {
- ++firstRun;
- }
- if(firstRun>=runCount) {
- break; /* no more such runs */
- }
-
- /* look for the limit run of such a sequence (the run behind it) */
- for(limitRun=firstRun; ++limitRun<runCount && levels[runs[limitRun].logicalStart]>=maxLevel;) {}
-
- /* Swap the entire sequence of runs from firstRun to limitRun-1. */
- endRun=limitRun-1;
- while(firstRun<endRun) {
- temp=runs[firstRun].logicalStart;
- runs[firstRun].logicalStart=runs[endRun].logicalStart;
- runs[endRun].logicalStart=temp;
-
- temp=runs[firstRun].visualLimit;
- runs[firstRun].visualLimit=runs[endRun].visualLimit;
- runs[endRun].visualLimit=temp;
-
- ++firstRun;
- --endRun;
- }
-
- if(limitRun==runCount) {
- break; /* no more such runs */
- } else {
- firstRun=limitRun+1;
- }
- }
- }
-
- /* now do maxLevel==old minLevel (==odd!), see above */
- if(!(minLevel&1)) {
- firstRun=0;
-
- /* include the trailing WS run in this complete reordering */
- if(pBiDi->trailingWSStart==pBiDi->length) {
- --runCount;
- }
-
- /* Swap the entire sequence of all runs. (endRun==runCount) */
- while(firstRun<runCount) {
- temp=runs[firstRun].logicalStart;
- runs[firstRun].logicalStart=runs[runCount].logicalStart;
- runs[runCount].logicalStart=temp;
-
- temp=runs[firstRun].visualLimit;
- runs[firstRun].visualLimit=runs[runCount].visualLimit;
- runs[runCount].visualLimit=temp;
-
- ++firstRun;
- --runCount;
- }
- }
-}
-
-/* reorder a line based on a levels array (L2) ------------------------------ */
-
-U_CAPI void U_EXPORT2
-ubidi_reorderLogical(const UBiDiLevel *levels, int32_t length, int32_t *indexMap) {
- int32_t start, limit, sumOfSosEos;
- UBiDiLevel minLevel, maxLevel;
-
- if(indexMap==NULL || !prepareReorder(levels, length, indexMap, &minLevel, &maxLevel)) {
- return;
- }
-
- /* nothing to do? */
- if(minLevel==maxLevel && (minLevel&1)==0) {
- return;
- }
-
- /* reorder only down to the lowest odd level */
- minLevel|=1;
-
- /* loop maxLevel..minLevel */
- do {
- start=0;
-
- /* loop for all sequences of levels to reorder at the current maxLevel */
- for(;;) {
- /* look for a sequence of levels that are all at >=maxLevel */
- /* look for the first index of such a sequence */
- while(start<length && levels[start]<maxLevel) {
- ++start;
- }
- if(start>=length) {
- break; /* no more such sequences */
- }
-
- /* look for the limit of such a sequence (the index behind it) */
- for(limit=start; ++limit<length && levels[limit]>=maxLevel;) {}
-
- /*
- * sos=start of sequence, eos=end of sequence
- *
- * The closed (inclusive) interval from sos to eos includes all the logical
- * and visual indexes within this sequence. They are logically and
- * visually contiguous and in the same range.
- *
- * For each run, the new visual index=sos+eos-old visual index;
- * we pre-add sos+eos into sumOfSosEos ->
- * new visual index=sumOfSosEos-old visual index;
- */
- sumOfSosEos=start+limit-1;
-
- /* reorder each index in the sequence */
- do {
- indexMap[start]=sumOfSosEos-indexMap[start];
- } while(++start<limit);
-
- /* start==limit */
- if(limit==length) {
- break; /* no more such sequences */
- } else {
- start=limit+1;
- }
- }
- } while(--maxLevel>=minLevel);
-}
-
-U_CAPI void U_EXPORT2
-ubidi_reorderVisual(const UBiDiLevel *levels, int32_t length, int32_t *indexMap) {
- int32_t start, end, limit, temp;
- UBiDiLevel minLevel, maxLevel;
-
- if(indexMap==NULL || !prepareReorder(levels, length, indexMap, &minLevel, &maxLevel)) {
- return;
- }
-
- /* nothing to do? */
- if(minLevel==maxLevel && (minLevel&1)==0) {
- return;
- }
-
- /* reorder only down to the lowest odd level */
- minLevel|=1;
-
- /* loop maxLevel..minLevel */
- do {
- start=0;
-
- /* loop for all sequences of levels to reorder at the current maxLevel */
- for(;;) {
- /* look for a sequence of levels that are all at >=maxLevel */
- /* look for the first index of such a sequence */
- while(start<length && levels[start]<maxLevel) {
- ++start;
- }
- if(start>=length) {
- break; /* no more such runs */
- }
-
- /* look for the limit of such a sequence (the index behind it) */
- for(limit=start; ++limit<length && levels[limit]>=maxLevel;) {}
-
- /*
- * Swap the entire interval of indexes from start to limit-1.
- * We don't need to swap the levels for the purpose of this
- * algorithm: the sequence of levels that we look at does not
- * move anyway.
- */
- end=limit-1;
- while(start<end) {
- temp=indexMap[start];
- indexMap[start]=indexMap[end];
- indexMap[end]=temp;
-
- ++start;
- --end;
- }
-
- if(limit==length) {
- break; /* no more such sequences */
- } else {
- start=limit+1;
- }
- }
- } while(--maxLevel>=minLevel);
-}
-
-static bool_t
-prepareReorder(const UBiDiLevel *levels, int32_t length,
- int32_t *indexMap,
- UBiDiLevel *pMinLevel, UBiDiLevel *pMaxLevel) {
- int32_t start;
- UBiDiLevel level, minLevel, maxLevel;
-
- if(levels==NULL || length<=0) {
- return FALSE;
- }
-
- /* determine minLevel and maxLevel */
- minLevel=UBIDI_MAX_EXPLICIT_LEVEL+1;
- maxLevel=0;
- for(start=length; start>0;) {
- level=levels[--start];
- if(level>UBIDI_MAX_EXPLICIT_LEVEL+1) {
- return FALSE;
- }
- if(level<minLevel) {
- minLevel=level;
- }
- if(level>maxLevel) {
- maxLevel=level;
- }
- }
- *pMinLevel=minLevel;
- *pMaxLevel=maxLevel;
-
- /* initialize the index map */
- for(start=length; start>0;) {
- --start;
- indexMap[start]=start;
- }
-
- return TRUE;
-}
-
-/* API functions for logical<->visual mapping ------------------------------- */
-
-U_CAPI int32_t U_EXPORT2
-ubidi_getVisualIndex(UBiDi *pBiDi, int32_t logicalIndex, UErrorCode *pErrorCode) {
- if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
- return 0;
- } else if(pBiDi==NULL) {
- *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
- return 0;
- } else if(logicalIndex<0 || pBiDi->length<=logicalIndex) {
- *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
- return 0;
- } else {
- /* we can do the trivial cases without the runs array */
- switch(pBiDi->direction) {
- case UBIDI_LTR:
- return logicalIndex;
- case UBIDI_RTL:
- return pBiDi->length-logicalIndex-1;
- default:
- if(pBiDi->runCount<0 && !ubidi_getRuns(pBiDi)) {
- *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
- return 0;
- } else {
- Run *runs=pBiDi->runs;
- int32_t i, visualStart=0, offset, length;
-
- /* linear search for the run, search on the visual runs */
- for(i=0;; ++i) {
- length=runs[i].visualLimit-visualStart;
- offset=logicalIndex-GET_INDEX(runs[i].logicalStart);
- if(offset>=0 && offset<length) {
- if(IS_EVEN_RUN(runs[i].logicalStart)) {
- /* LTR */
- return visualStart+offset;
- } else {
- /* RTL */
- return visualStart+length-offset-1;
- }
- }
- visualStart+=length;
- }
- }
- }
- }
-}
-
-U_CAPI int32_t U_EXPORT2
-ubidi_getLogicalIndex(UBiDi *pBiDi, int32_t visualIndex, UErrorCode *pErrorCode) {
- if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
- return 0;
- } else if(pBiDi==NULL) {
- *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
- return 0;
- } else if(visualIndex<0 || pBiDi->length<=visualIndex) {
- *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
- return 0;
- } else {
- /* we can do the trivial cases without the runs array */
- switch(pBiDi->direction) {
- case UBIDI_LTR:
- return visualIndex;
- case UBIDI_RTL:
- return pBiDi->length-visualIndex-1;
- default:
- if(pBiDi->runCount<0 && !ubidi_getRuns(pBiDi)) {
- *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
- return 0;
- } else {
- Run *runs=pBiDi->runs;
- int32_t i, runCount=pBiDi->runCount, start;
-
- if(runCount<=10) {
- /* linear search for the run */
- for(i=0; visualIndex>=runs[i].visualLimit; ++i) {}
- } else {
- /* binary search for the run */
- int32_t begin=0, limit=runCount;
-
- /* the middle if() will guaranteed find the run, we don't need a loop limit */
- for(;;) {
- i=(begin+limit)/2;
- if(visualIndex>=runs[i].visualLimit) {
- begin=i+1;
- } else if(i==0 || visualIndex>=runs[i-1].visualLimit) {
- break;
- } else {
- limit=i;
- }
- }
- }
-
- start=runs[i].logicalStart;
- if(IS_EVEN_RUN(start)) {
- /* LTR */
- /* the offset in runs[i] is visualIndex-runs[i-1].visualLimit */
- if(i>0) {
- visualIndex-=runs[i-1].visualLimit;
- }
- return GET_INDEX(start)+visualIndex;
- } else {
- /* RTL */
- return GET_INDEX(start)+runs[i].visualLimit-visualIndex-1;
- }
- }
- }
- }
-}
-
-U_CAPI void U_EXPORT2
-ubidi_getLogicalMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
- UBiDiLevel *levels;
-
- /* ubidi_getLevels() checks all of its and our arguments */
- if((levels=(UBiDiLevel *)ubidi_getLevels(pBiDi, pErrorCode))==NULL) {
- /* no op */
- } else if(indexMap==NULL) {
- *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
- } else {
- ubidi_reorderLogical(levels, pBiDi->length, indexMap);
- }
-}
-
-U_CAPI void U_EXPORT2
-ubidi_getVisualMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
- /* ubidi_countRuns() checks all of its and our arguments */
- if(ubidi_countRuns(pBiDi, pErrorCode)<=0) {
- /* no op */
- } else if(indexMap==NULL) {
- *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
- } else {
- /* fill a visual-to-logical index map using the runs[] */
- Run *runs=pBiDi->runs, *runsLimit=runs+pBiDi->runCount;
- int32_t logicalStart, visualStart, visualLimit;
-
- visualStart=0;
- for(; runs<runsLimit; ++runs) {
- logicalStart=runs->logicalStart;
- visualLimit=runs->visualLimit;
- if(IS_EVEN_RUN(logicalStart)) {
- do { /* LTR */
- *indexMap++ = logicalStart++;
- } while(++visualStart<visualLimit);
- } else {
- REMOVE_ODD_BIT(logicalStart);
- logicalStart+=visualLimit-visualStart; /* logicalLimit */
- do { /* RTL */
- *indexMap++ = --logicalStart;
- } while(++visualStart<visualLimit);
- }
- /* visualStart==visualLimit; */
- }
- }
-}
-
-U_CAPI void U_EXPORT2
-ubidi_invertMap(const int32_t *srcMap, int32_t *destMap, int32_t length) {
- if(srcMap!=NULL && destMap!=NULL) {
- srcMap+=length;
- while(length>0) {
- destMap[*--srcMap]=--length;
- }
- }
-}
--- a/jdk/src/share/native/sun/font/bidi/uchardir.c Thu May 28 18:11:07 2009 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,652 +0,0 @@
-/*
- * Portions Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/*
- * (C) Copyright IBM Corp. 1999-2003 - All Rights Reserved
- *
- * The original version of this source code and documentation is
- * copyrighted and owned by IBM. These materials are provided
- * under terms of a License Agreement between IBM and Sun.
- * This technology is protected by multiple US and International
- * patents. This notice and attribution to IBM may not be removed.
- */
-
-/*
-*
-* File UCHAR.CPP
-*
-* Modification History:
-*
-* Date Name Description
-* 11/30/1999 dfelt Creation. Extract from uchar.c, reduce to data
-* query only.
-********************************************************************************
-*/
-
-#include "uchardir.h"
-
-/* new 4.0 surrogate data */
-static uint32_t ASCII_START = 0x0;
-static uint32_t ASCII_LIMIT = 0x80;
-static uint8_t ASCII[] = {
- (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12,
- (uint8_t)0x12, (uint8_t)0x08, (uint8_t)0x07, (uint8_t)0x08, (uint8_t)0x09, (uint8_t)0x07, (uint8_t)0x12, (uint8_t)0x12,
- (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12,
- (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x12, (uint8_t)0x07, (uint8_t)0x07, (uint8_t)0x07, (uint8_t)0x08,
- (uint8_t)0x09, (uint8_t)0x0a, (uint8_t)0x0a, (uint8_t)0x04, (uint8_t)0x04, (uint8_t)0x04, (uint8_t)0x0a, (uint8_t)0x0a,
- (uint8_t)0x0a, (uint8_t)0x0a, (uint8_t)0x0a, (uint8_t)0x04, (uint8_t)0x06, (uint8_t)0x04, (uint8_t)0x06, (uint8_t)0x03,
- (uint8_t)0x02, (uint8_t)0x02, (uint8_t)0x02, (uint8_t)0x02, (uint8_t)0x02, (uint8_t)0x02, (uint8_t)0x02, (uint8_t)0x02,
- (uint8_t)0x02, (uint8_t)0x02, (uint8_t)0x06, (uint8_t)0x0a, (uint8_t)0x0a, (uint8_t)0x0a, (uint8_t)0x0a, (uint8_t)0x0a,
- (uint8_t)0x0a, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0a, (uint8_t)0x0a, (uint8_t)0x0a, (uint8_t)0x0a, (uint8_t)0x0a,
- (uint8_t)0x0a, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0a, (uint8_t)0x0a, (uint8_t)0x0a, (uint8_t)0x0a, (uint8_t)0x12,
-};
-static uint32_t RTL_START = 0x591;
-static uint32_t RTL_LIMIT = 0x671;
-static uint8_t RTL[] = {
- (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11,
- (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11,
- (uint8_t)0x11, (uint8_t)0x01, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11,
- (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11,
- (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11,
- (uint8_t)0x11, (uint8_t)0x01, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x01, (uint8_t)0x11, (uint8_t)0x01,
- (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x01, (uint8_t)0x11, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01,
- (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01,
- (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01,
- (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01,
- (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01,
- (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01,
- (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01,
- (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x01, (uint8_t)0x0d,
- (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d,
- (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x06, (uint8_t)0x0d, (uint8_t)0x0a, (uint8_t)0x0a, (uint8_t)0x11,
- (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d,
- (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d,
- (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d,
- (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d,
- (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d,
- (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d,
- (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d,
- (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11,
- (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11,
- (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x05,
- (uint8_t)0x05, (uint8_t)0x05, (uint8_t)0x05, (uint8_t)0x05, (uint8_t)0x05, (uint8_t)0x05, (uint8_t)0x05, (uint8_t)0x05,
- (uint8_t)0x05, (uint8_t)0x04, (uint8_t)0x05, (uint8_t)0x05, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x11,
-};
-static uint8_t t0[] = {
- (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x9b, (uint8_t)0xab, (uint8_t)0xca, (uint8_t)0x99,
- (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0xaa, (uint8_t)0xab,
- (uint8_t)0xcd, (uint8_t)0xd5, (uint8_t)0x55, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd5, (uint8_t)0x75, (uint8_t)0x74,
- (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x7d, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xd9,
- (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x9a, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99,
- (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99,
- (uint8_t)0x7d, (uint8_t)0x55, (uint8_t)0x55, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0x55, (uint8_t)0x33, (uint8_t)0xd0, (uint8_t)0xdd, (uint8_t)0xd3, (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0x0d,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88,
- (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x88,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0xdd, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0xd0,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0xdd, (uint8_t)0x0d, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x80, (uint8_t)0x88, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x18, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88,
- (uint8_t)0x88, (uint8_t)0x18, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88,
- (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x18, (uint8_t)0x88, (uint8_t)0x18,
- (uint8_t)0x18, (uint8_t)0x81, (uint8_t)0x81, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11,
- (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11,
- (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x72, (uint8_t)0xdd,
- (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22,
- (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22,
- (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x28, (uint8_t)0x88, (uint8_t)0x88,
- (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x82, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22,
- (uint8_t)0x66, (uint8_t)0x66, (uint8_t)0x66, (uint8_t)0x66, (uint8_t)0x66, (uint8_t)0x56, (uint8_t)0x62, (uint8_t)0x22,
- (uint8_t)0x82, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22,
- (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x82, (uint8_t)0x88,
- (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x82, (uint8_t)0x28, (uint8_t)0x8d, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x22,
- (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22,
- (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x29,
- (uint8_t)0x28, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22,
- (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x82, (uint8_t)0x22, (uint8_t)0x22,
- (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88,
- (uint8_t)0x08, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x80, (uint8_t)0x00,
- (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x00,
- (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x88, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x08, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x55, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x08, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x80, (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x00,
- (uint8_t)0x88, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x08, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x00,
- (uint8_t)0x05, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x80, (uint8_t)0x08,
- (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd5, (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x88,
- (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x88, (uint8_t)0x80, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x88, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x88, (uint8_t)0x80, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x08, (uint8_t)0x00, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x05,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x80,
- (uint8_t)0x08, (uint8_t)0x00, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x08, (uint8_t)0x80, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x88, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x08, (uint8_t)0x08, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0x00,
- (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x80,
- (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x80, (uint8_t)0x88, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88,
- (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x80, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x88,
- (uint8_t)0x80, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x88, (uint8_t)0x08, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0xc0, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0xd0, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x88, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x80, (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88,
- (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x05, (uint8_t)0x08, (uint8_t)0x00,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd8, (uint8_t)0x88, (uint8_t)0xc0,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x88, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0xdd, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0x0d,
- (uint8_t)0xdd, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0xdd,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0xdd,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0xd0,
- (uint8_t)0xcc, (uint8_t)0xcc, (uint8_t)0xcc, (uint8_t)0xcc, (uint8_t)0xcc, (uint8_t)0xc9, (uint8_t)0x99, (uint8_t)0x01,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xca, (uint8_t)0xee, (uint8_t)0xee, (uint8_t)0xec,
- (uint8_t)0x55, (uint8_t)0x55, (uint8_t)0x5d, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd0, (uint8_t)0x0d, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0c,
- (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99,
- (uint8_t)0x30, (uint8_t)0x00, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x55, (uint8_t)0xdd, (uint8_t)0xd0,
- (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x55, (uint8_t)0xdd, (uint8_t)0xd0,
- (uint8_t)0x55, (uint8_t)0x55, (uint8_t)0x55, (uint8_t)0x55, (uint8_t)0x55, (uint8_t)0x55, (uint8_t)0x55, (uint8_t)0x55,
- (uint8_t)0x55, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x80, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0xdd, (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xd0, (uint8_t)0xdd, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0xd0, (uint8_t)0xdd, (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0xdd,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x0d, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x50,
- (uint8_t)0x00, (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0xdd, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0xdd, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0xdd, (uint8_t)0x55, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd0, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33,
- (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x33, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x3d, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0x00,
- (uint8_t)0xdd, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xd0, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0x00, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0x0d, (uint8_t)0x0d,
- (uint8_t)0xdd, (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0xd0, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd0,
- (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd0,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0xcd, (uint8_t)0xdd, (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88,
- (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0xdd, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0xdd,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x8d, (uint8_t)0xd0, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0xdd, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0xdd, (uint8_t)0xdd,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d, (uint8_t)0xdd, (uint8_t)0xd0, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0xdd,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x0d,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x01, (uint8_t)0x81,
- (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x15, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11,
- (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0xdd,
- (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x22, (uint8_t)0x2d, (uint8_t)0x22,
- (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x7d, (uint8_t)0x70, (uint8_t)0xd7, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd5,
- (uint8_t)0xdd, (uint8_t)0x55, (uint8_t)0xdd, (uint8_t)0xd0, (uint8_t)0xd5, (uint8_t)0x5d, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x0d, (uint8_t)0xd5, (uint8_t)0x55, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd5, (uint8_t)0x75, (uint8_t)0x74,
- (uint8_t)0x55, (uint8_t)0xdd, (uint8_t)0xd5, (uint8_t)0x50, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xdd, (uint8_t)0xd0,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x09, (uint8_t)0x99, (uint8_t)0xdd, (uint8_t)0x00,
- (uint8_t)0x0d, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x09, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x99, (uint8_t)0x98, (uint8_t)0x88, (uint8_t)0x88,
- (uint8_t)0x88, (uint8_t)0x80, (uint8_t)0x08, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x00, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x88, (uint8_t)0x88, (uint8_t)0x00,
- (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x33,
- (uint8_t)0x09, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00, (uint8_t)0x00,
-};
-
-static uint8_t t1[] = {
- (uint8_t)0x00, (uint8_t)0x01, (uint8_t)0x02, (uint8_t)0x03, (uint8_t)0x04, (uint8_t)0x05, (uint8_t)0x04, (uint8_t)0x06,
- (uint8_t)0x07, (uint8_t)0x08, (uint8_t)0x09, (uint8_t)0x0a, (uint8_t)0x0b, (uint8_t)0x0c, (uint8_t)0x0b, (uint8_t)0x0c,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0d, (uint8_t)0x0e, (uint8_t)0x0e, (uint8_t)0x0f, (uint8_t)0x10,
- (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x12, (uint8_t)0x11, (uint8_t)0x13,
- (uint8_t)0x14, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x15,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x16, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x17, (uint8_t)0x18, (uint8_t)0x19, (uint8_t)0x1a, (uint8_t)0x1b, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1d, (uint8_t)0x1e, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x20, (uint8_t)0x21, (uint8_t)0x22, (uint8_t)0x23,
- (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x24, (uint8_t)0x25, (uint8_t)0x26,
- (uint8_t)0x27, (uint8_t)0x28, (uint8_t)0x1f, (uint8_t)0x11, (uint8_t)0x29, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f,
- (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x2a, (uint8_t)0x23, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x2b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x2c, (uint8_t)0x2d, (uint8_t)0x2e, (uint8_t)0x2f, (uint8_t)0x0b,
- (uint8_t)0x30, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x2c, (uint8_t)0x31, (uint8_t)0x0b, (uint8_t)0x2f, (uint8_t)0x32,
- (uint8_t)0x2b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x2c, (uint8_t)0x33, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x34,
- (uint8_t)0x2b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x2c, (uint8_t)0x35, (uint8_t)0x0b, (uint8_t)0x2f, (uint8_t)0x36,
- (uint8_t)0x30, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x37, (uint8_t)0x38, (uint8_t)0x39, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x3a, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x3b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x3c,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x3d, (uint8_t)0x3e, (uint8_t)0x3f, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x2c, (uint8_t)0x40, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x38, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x41, (uint8_t)0x42, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x43, (uint8_t)0x44, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x45, (uint8_t)0x46, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x47, (uint8_t)0x0b, (uint8_t)0x48, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x49,
- (uint8_t)0x4a, (uint8_t)0x4b, (uint8_t)0x11, (uint8_t)0x4c, (uint8_t)0x39, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x4d, (uint8_t)0x4e, (uint8_t)0x0b, (uint8_t)0x47, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x4f, (uint8_t)0x50, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x51, (uint8_t)0x0b, (uint8_t)0x51, (uint8_t)0x0b, (uint8_t)0x2f, (uint8_t)0x0b, (uint8_t)0x2f,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x52, (uint8_t)0x53, (uint8_t)0x54, (uint8_t)0x0b, (uint8_t)0x55,
- (uint8_t)0x56, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x57, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x58, (uint8_t)0x59, (uint8_t)0x5a, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x5b, (uint8_t)0x5c, (uint8_t)0x5d, (uint8_t)0x5d, (uint8_t)0x5e,
- (uint8_t)0x5f, (uint8_t)0x10, (uint8_t)0x60, (uint8_t)0x61, (uint8_t)0x10, (uint8_t)0x62, (uint8_t)0x63, (uint8_t)0x64,
- (uint8_t)0x65, (uint8_t)0x0b, (uint8_t)0x66, (uint8_t)0x67, (uint8_t)0x0b, (uint8_t)0x11, (uint8_t)0x68, (uint8_t)0x0b,
- (uint8_t)0x69, (uint8_t)0x6a, (uint8_t)0x6b, (uint8_t)0x6c, (uint8_t)0x6d, (uint8_t)0x6e, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x6f, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x70, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x05,
- (uint8_t)0x10, (uint8_t)0x71, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x04, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x72, (uint8_t)0x0b, (uint8_t)0x73, (uint8_t)0x0b, (uint8_t)0x74, (uint8_t)0x74,
- (uint8_t)0x74, (uint8_t)0x75, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x76, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x77, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x78,
- (uint8_t)0x10, (uint8_t)0x79, (uint8_t)0x79, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x7a, (uint8_t)0x10, (uint8_t)0x77, (uint8_t)0x10, (uint8_t)0x7b, (uint8_t)0x7c, (uint8_t)0x7d, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x7e, (uint8_t)0x10, (uint8_t)0x7f, (uint8_t)0x0b, (uint8_t)0x10, (uint8_t)0x80, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x78, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x10, (uint8_t)0x81, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x82,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x70, (uint8_t)0x0b, (uint8_t)0x80,
- (uint8_t)0x83, (uint8_t)0x10, (uint8_t)0x84, (uint8_t)0x85, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x86, (uint8_t)0x04, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x87,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x5e, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x10, (uint8_t)0x0b, (uint8_t)0x88,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x7d, (uint8_t)0x89, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x8a,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x8b, (uint8_t)0x0b, (uint8_t)0x8c,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x72, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x8d, (uint8_t)0x8e, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f,
- (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f,
- (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f,
- (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f,
- (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x8f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f,
- (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x90,
- (uint8_t)0x11, (uint8_t)0x0b, (uint8_t)0x91, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x92, (uint8_t)0x93, (uint8_t)0x1f,
- (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x1f, (uint8_t)0x27,
- (uint8_t)0x94, (uint8_t)0x03, (uint8_t)0x04, (uint8_t)0x05, (uint8_t)0x04, (uint8_t)0x05, (uint8_t)0x70, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x95, (uint8_t)0x96,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x97, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c, (uint8_t)0x1c,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x98, (uint8_t)0x99,
- (uint8_t)0x9a, (uint8_t)0x0b, (uint8_t)0x9b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x10, (uint8_t)0x72, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x9c, (uint8_t)0x74, (uint8_t)0x74, (uint8_t)0x74,
- (uint8_t)0x9d, (uint8_t)0x0b, (uint8_t)0x08, (uint8_t)0x08, (uint8_t)0x08, (uint8_t)0x08, (uint8_t)0x08, (uint8_t)0x08,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11,
- (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
- (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b, (uint8_t)0x0b,
-};
-
-static uint8_t ix[] = {
- (uint8_t)0x01, (uint8_t)0x23, (uint8_t)0x45, (uint8_t)0x67, (uint8_t)0x78, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x97, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x7a,
- (uint8_t)0xbc, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0xd7, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0xe7, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
- (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77, (uint8_t)0x77,
-};
-
-#define LOWBITS 4
-#define MEDBITS 7
-#define HIGHBITS (21 - MEDBITS - LOWBITS)
-
-#define HIGHSHIFT (LOWBITS + MEDBITS)
-
-#define BLOCKSIZE (1 << LOWBITS)
-#define IBLOCKSIZE (1 << MEDBITS)
-#define ISIZE (1 << HIGHBITS)
-
-#define BLOCKMASK (BLOCKSIZE - 1)
-#define IBLOCKMASK (IBLOCKSIZE - 1)
-#define IMASK (ISIZE - 1)
-
-static uint8_t jx2i[] = {
- 0, 1, 13, 2, 3, 4, 5, 6, 17, 18, 7, 8, 9, 10
-};
-
-static uint8_t x2i[] = {
- /* LRE RLE PDF LRO RLO */
- 11, 14, 16, 12, 15
-};
-
-static UCharDirection u_getDirectionInternal(uint32_t cp) {
- int dc;
- int n;
- int bi = cp & BLOCKMASK;
- int ibi = (cp >> LOWBITS) & IBLOCKMASK;
- int i = (cp >> HIGHSHIFT) & IMASK;
-
- n = ix[i >> 1];
- if ((i & 1) == 0) {
- n >>= 4;
- }
- n &= 0x0f;
- n = t1[n * IBLOCKSIZE + ibi];
- n = n * BLOCKSIZE + bi;
- dc = t0[n >> 1];
- if ((n & 1) == 0) {
- dc >>= 4;
- }
- dc &= 0x0f;
- if (dc > 13) {
- dc = x2i[cp - 0x202a];
- } else {
- dc = jx2i[dc];
- }
- return dc;
-}
-
-UCharDirection u_getDirection(uint32_t cp) {
- if (cp < ASCII_LIMIT) {
- return ASCII[cp];
- }
- if (cp < RTL_START) {
- return u_getDirectionInternal(cp);
- }
- if (cp < RTL_LIMIT) {
- return RTL[cp - RTL_START];
- }
- if (cp < 0x110000) {
- return u_getDirectionInternal(cp);
- }
- return 0;
-}
-
-UCharDirection
-u_charDirection(UChar ch) {
- return u_getDirection(ch);
-}
-
-#define LEAD_SURROGATE_SHIFT 10
-#define SURROGATE_OFFSET (0x010000 - (0xd800 << 10) - 0xdc00)
-
-UCharDirection
-u_surrogatePairDirection(UChar lead, UChar trail) {
- uint32_t cp = ((uint32_t)lead << LEAD_SURROGATE_SHIFT) + trail + SURROGATE_OFFSET;
- return u_getDirection(cp);
-}
--- a/jdk/src/share/native/sun/font/bidi/uchardir.h Thu May 28 18:11:07 2009 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Portions Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/*
- * (C) Copyright IBM Corp. 1999-2003 - All Rights Reserved
- *
- * The original version of this source code and documentation is
- * copyrighted and owned by IBM. These materials are provided
- * under terms of a License Agreement between IBM and Sun.
- * This technology is protected by multiple US and International
- * patents. This notice and attribution to IBM may not be removed.
- */
-
-/*
-*
-* File UCHARDIR.H
-*
-* Modification History:
-*
-* Date Name Description
-* 11/30/1999 dfelt Creation. Copied UCharDirection from uchar.h
-********************************************************************************
-*/
-
-#ifndef UCHARDIR_H
-#define UCHARDIR_H
-
-#include "utypes.h"
-
-/*===========================================================================*/
-/* Unicode version number */
-/*===========================================================================*/
-#define UNICODE_VERSION "3.0.0.beta"
-
-enum UCharDirection {
- U_LEFT_TO_RIGHT = 0,
- U_RIGHT_TO_LEFT = 1,
- U_EUROPEAN_NUMBER = 2,
- U_EUROPEAN_NUMBER_SEPARATOR = 3,
- U_EUROPEAN_NUMBER_TERMINATOR = 4,
- U_ARABIC_NUMBER = 5,
- U_COMMON_NUMBER_SEPARATOR = 6,
- U_BLOCK_SEPARATOR = 7,
- U_SEGMENT_SEPARATOR = 8,
- U_WHITE_SPACE_NEUTRAL = 9,
- U_OTHER_NEUTRAL = 10,
- U_LEFT_TO_RIGHT_EMBEDDING = 11,
- U_LEFT_TO_RIGHT_OVERRIDE = 12,
- U_RIGHT_TO_LEFT_ARABIC = 13,
- U_RIGHT_TO_LEFT_EMBEDDING = 14,
- U_RIGHT_TO_LEFT_OVERRIDE = 15,
- U_POP_DIRECTIONAL_FORMAT = 16,
- U_DIR_NON_SPACING_MARK = 17,
- U_BOUNDARY_NEUTRAL = 18,
- U_CHAR_DIRECTION_COUNT
-};
-
-typedef enum UCharDirection UCharDirection;
-
-/**
- * Returns the linguistic direction property of a character.
- * <P>
- * Returns the linguistic direction property of a character.
- * For example, 0x0041 (letter A) has the LEFT_TO_RIGHT directional
- * property.
- * @see UCharDirection
- */
-U_CAPI UCharDirection U_EXPORT2
-u_charDirection(UChar c);
-
-U_CAPI UCharDirection U_EXPORT2
-u_getDirection(uint32_t cp);
-
-U_CAPI UCharDirection U_EXPORT2
-u_surrogatePairDirection(UChar lead, UChar trail);
-
-#endif /*_UCHAR*/
-/*eof*/
--- a/jdk/src/share/native/sun/font/bidi/utypes.h Thu May 28 18:11:07 2009 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/*
- * Portions Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/*
- * (C) Copyright Taligent, Inc., 1996, 1997 *
- * (C) Copyright IBM Corp. 1998-2003 - All Rights Reserved
- *
- * The original version of this source code and documentation is
- * copyrighted and owned by IBM. These materials are provided
- * under terms of a License Agreement between IBM and Sun.
- * This technology is protected by multiple US and International
- * patents. This notice and attribution to IBM may not be removed.
- */
-
-/*
-*
-* FILE NAME : UTYPES.H (formerly ptypes.h)
-*
-* Date Name Description
-* 12/11/96 helena Creation.
-* 02/27/97 aliu Added typedefs for UClassID, int8, int16, int32,
-* uint8, uint16, and uint32.
-* 04/01/97 aliu Added XP_CPLUSPLUS and modified to work under C as
-* well as C++.
-* Modified to use memcpy() for icu_arrayCopy() fns.
-* 04/14/97 aliu Added TPlatformUtilities.
-* 05/07/97 aliu Added import/export specifiers (replacing the old
-* broken EXT_CLASS). Added version number for our
-* code. Cleaned up header.
-* 6/20/97 helena Java class name change.
-* 08/11/98 stephen UErrorCode changed from typedef to enum
-* 08/12/98 erm Changed T_ANALYTIC_PACKAGE_VERSION to 3
-* 08/14/98 stephen Added icu_arrayCopy() for int8_t, int16_t, int32_t
-* 12/09/98 jfitz Added BUFFER_OVERFLOW_ERROR (bug 1100066)
-* 04/20/99 stephen Cleaned up & reworked for autoconf.
-* Renamed to utypes.h.
-* 05/05/99 stephen Changed to use <inttypes.h>
-* 10/12/00 dfelt Adapted to use javavm types (plus juint from j2d)
-*******************************************************************************
-*/
-
-#ifndef UTYPES_H
-#define UTYPES_H
-
-// doesn't seem to be a way of getting around this
-
-//#if defined(WIN32) || defined(_WIN32)
-// not needed since we don't export to another dll
-
-#if 0
-
-#define U_EXPORT __declspec(dllexport)
-#define U_EXPORT2
-#define U_IMPORT __declspec(dllimport)
-
-#else
-
-#define U_EXPORT
-#define U_EXPORT2
-#define U_IMPORT
-
-#endif
-
-#ifdef XP_CPLUSPLUS
-# define U_CFUNC extern "C"
-# define U_CDECL_BEGIN extern "C" {
-# define U_CDECL_END }
-#else
-# define U_CFUNC
-# define U_CDECL_BEGIN
-# define U_CDECL_END
-#endif
-#define U_CAPI U_CFUNC U_EXPORT
-
-// defines jboolean, jchar, jshort, and jint via jni_md.h
-#include "jni.h"
-// defines jubyte, jushort, juint
-#include "j2d_md.h"
-
-typedef jboolean bool_t;
-
-/*
- * win32 does not have standard definitions for the following:
- */
-#ifdef WIN32
-
-#ifndef __int8_t_defined
-typedef jbyte int8_t;
-typedef jshort int16_t;
-typedef jint int32_t;
-#endif
-
-typedef jubyte uint8_t;
-typedef jushort uint16_t;
-typedef juint uint32_t;
-
-#endif /* WIN32 */
-
-/*===========================================================================*/
-/* Unicode character */
-/*===========================================================================*/
-typedef uint16_t UChar;
-
-
-/** Error code to replace exception handling */
-enum UErrorCode {
- U_ERROR_INFO_START = -128, /* Start of information results (semantically successful) */
- U_USING_FALLBACK_ERROR = -128,
- U_USING_DEFAULT_ERROR = -127,
- U_ERROR_INFO_LIMIT,
-
- U_ZERO_ERROR = 0, /* success */
-
- U_ILLEGAL_ARGUMENT_ERROR = 1, /* Start of codes indicating failure */
- U_MISSING_RESOURCE_ERROR = 2,
- U_INVALID_FORMAT_ERROR = 3,
- U_FILE_ACCESS_ERROR = 4,
- U_INTERNAL_PROGRAM_ERROR = 5, /* Indicates a bug in the library code */
- U_MESSAGE_PARSE_ERROR = 6,
- U_MEMORY_ALLOCATION_ERROR = 7, /* Memory allocation error */
- U_INDEX_OUTOFBOUNDS_ERROR = 8,
- U_PARSE_ERROR = 9, /* Equivalent to Java ParseException */
- U_INVALID_CHAR_FOUND = 10, /* In the Character conversion routines: Invalid character or sequence was encountered*/
- U_TRUNCATED_CHAR_FOUND = 11, /* In the Character conversion routines: More bytes are required to complete the conversion successfully*/
- U_ILLEGAL_CHAR_FOUND = 12, /* In codeset conversion: a sequence that does NOT belong in the codepage has been encountered*/
- U_INVALID_TABLE_FORMAT = 13, /* Conversion table file found, but corrupted*/
- U_INVALID_TABLE_FILE = 14, /* Conversion table file not found*/
- U_BUFFER_OVERFLOW_ERROR = 15, /* A result would not fit in the supplied buffer */
- U_UNSUPPORTED_ERROR = 16, /* Requested operation not supported in current context */
- U_ERROR_LIMIT
-};
-
-#ifndef XP_CPLUSPLUS
-typedef enum UErrorCode UErrorCode;
-#endif
-
-/* Use the following to determine if an UErrorCode represents */
-/* operational success or failure. */
-#ifdef XP_CPLUSPLUS
-inline bool_t U_SUCCESS(UErrorCode code) { return (bool_t)(code<=U_ZERO_ERROR); }
-inline bool_t U_FAILURE(UErrorCode code) { return (bool_t)(code>U_ZERO_ERROR); }
-#else
-#define U_SUCCESS(x) ((x)<=U_ZERO_ERROR)
-#define U_FAILURE(x) ((x)>U_ZERO_ERROR)
-#endif
-
-#ifndef TRUE
-# define TRUE 1
-#endif
-#ifndef FALSE
-# define FALSE 0
-#endif
-
-// UTYPES_H
-#endif
--- a/jdk/src/share/native/sun/font/layout/LETypes.h Thu May 28 18:11:07 2009 +0400
+++ b/jdk/src/share/native/sun/font/layout/LETypes.h Sat Jun 13 06:43:54 2009 +0900
@@ -36,7 +36,8 @@
#define LE_USE_CMEMORY
#ifdef LE_USE_CMEMORY
-#include "cmemory.h"
+#include <stdlib.h>
+#include <string.h>
#endif
#ifndef _LP64
--- a/jdk/test/java/text/Bidi/BidiBug.java Thu May 28 18:11:07 2009 +0400
+++ b/jdk/test/java/text/Bidi/BidiBug.java Sat Jun 13 06:43:54 2009 +0900
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4827312
+ * @bug 4827312 6850113
* @summary verify that argument validity check is not fooled by overflow
*/
public class BidiBug {
@@ -33,9 +33,9 @@
java.text.Bidi bidi = new java.text.Bidi(new char[20],10,buff,Integer.MAX_VALUE-3,4,1);
}
catch (IllegalArgumentException e) {
- System.out.println(e);
+ System.out.println("Passed: " + e);
return; // success
}
- throw new RuntimeException("didn't throw error, though we didn't crash either");
+ throw new RuntimeException("Failed: Bidi didn't throw error, though we didn't crash either");
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Bidi/BidiConformance.java Sat Jun 13 06:43:54 2009 +0900
@@ -0,0 +1,2334 @@
+/*
+ * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6850113
+ * @summary confirm the behavior of new Bidi implementation. (Backward compatibility)
+ */
+
+import java.awt.font.NumericShaper;
+import java.awt.font.TextAttribute;
+import java.text.AttributedString;
+import java.text.Bidi;
+import java.util.Arrays;
+
+public class BidiConformance {
+
+ /* internal flags */
+ private static boolean error = false;
+ private static boolean verbose = false;
+ private static boolean abort = false;
+
+ public static void main(String[] args) {
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i];
+ if (arg.equals("-verbose")) {
+ verbose = true;
+ } else if (arg.equals("-abort")) {
+ abort = true;
+ }
+ }
+
+ BidiConformance bc = new BidiConformance();
+ bc.test();
+
+ if (error) {
+ throw new RuntimeException("Failed.");
+ } else {
+ System.out.println("Passed.");
+ }
+ }
+
+ private void test() {
+ testConstants();
+ testConstructors();
+ testMethods();
+
+ testMethods4Constructor1(); // Bidi(AttributedCharacterIterator)
+ testMethods4Constructor2(); // Bidi(String, int)
+ testMethods4Constructor3(); // Bidi(char[], ...)
+ }
+
+ private void testConstants() {
+ System.out.println("*** Test constants");
+
+ checkResult("Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT",
+ -2, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
+ checkResult("Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT",
+ -1, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
+ checkResult("Bidi.DIRECTION_LEFT_TO_RIGHT",
+ 0, Bidi.DIRECTION_LEFT_TO_RIGHT);
+ checkResult("Bidi.DIRECTION_RIGHT_TO_LEFT",
+ 1, Bidi.DIRECTION_RIGHT_TO_LEFT);
+ }
+
+ private void testConstructors() {
+ System.out.println("*** Test constructors");
+
+ testConstructor1(); // Bidi(AttributedCharacterIterator)
+ testConstructor2(); // Bidi(String, int)
+ testConstructor3(); // Bidi(char[], ...)
+ }
+
+ private void testMethods() {
+ System.out.println("*** Test methods");
+
+ testMethod_createLineBidi1();
+ testMethod_createLineBidi2();
+ testMethod_getLevelAt();
+ testMethod_getRunLevel();
+ testMethod_getRunLimit();
+ testMethod_getRunStart();
+ testMethod_reorderVisually1();
+ testMethod_reorderVisually2();
+ testMethod_requiresBidi();
+ }
+
+ private void testMethods4Constructor1() {
+ System.out.println("*** Test methods for constructor 1");
+
+ String paragraph;
+ Bidi bidi;
+ NumericShaper ns = NumericShaper.getShaper(NumericShaper.ARABIC);
+
+ for (int textNo = 0; textNo < data4Constructor1.length; textNo++) {
+ paragraph = data4Constructor1[textNo][0];
+ int start = paragraph.indexOf('<')+1;
+ int limit = paragraph.indexOf('>');
+ int testNo;
+
+ System.out.println("*** Test textNo=" + textNo +
+ ": Bidi(AttributedCharacterIterator\"" +
+ toReadableString(paragraph) + "\") " +
+ " start=" + start + ", limit=" + limit);
+
+ // Test 0
+ testNo = 0;
+ System.out.println(" Test#" + testNo +": RUN_DIRECTION_LTR");
+ AttributedString astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_LTR);
+ bidi = new Bidi(astr.getIterator());
+
+ callTestEachMethod4Constructor1(textNo, testNo, bidi);
+
+ // Test 1
+ ++testNo;
+ System.out.println(" Test#" + testNo +
+ ": RUN_DIRECTION_LTR, BIDI_EMBEDDING(1)");
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_LTR);
+ astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(1),
+ start, limit);
+ bidi = new Bidi(astr.getIterator());
+ callTestEachMethod4Constructor1(textNo, testNo, bidi);
+
+ // Test 2
+ ++testNo;
+ System.out.println(" Test#" + testNo +
+ ": RUN_DIERCTION_LTR, BIDI_EMBEDDING(2)");
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_LTR);
+ astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(2),
+ start, limit);
+ bidi = new Bidi(astr.getIterator());
+ callTestEachMethod4Constructor1(textNo, testNo, bidi);
+
+ // Test 3
+ ++testNo;
+ System.out.println(" Test#" + testNo +
+ ": RUN_DIRECTIOIN_LTR, BIDI_EMBEDDING(-3)");
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_LTR);
+ astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-3),
+ start, limit);
+ bidi = new Bidi(astr.getIterator());
+ callTestEachMethod4Constructor1(textNo, testNo, bidi);
+
+ // Test 4
+ ++testNo;
+ System.out.println(" Test#" + testNo +
+ ": RUN_DIRECTION_LTR, BIDI_EMBEDDING(-4)");
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_LTR);
+ astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-4),
+ start, limit);
+ bidi = new Bidi(astr.getIterator());
+ callTestEachMethod4Constructor1(textNo, testNo, bidi);
+
+ // Test 5
+ ++testNo;
+ System.out.println(" Test#" + testNo + ": RUN_DIRECTION_RTL");
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_RTL);
+ bidi = new Bidi(astr.getIterator());
+ callTestEachMethod4Constructor1(textNo, testNo, bidi);
+
+ // Test 6
+ ++testNo;
+ System.out.println(" Test#" + testNo +
+ ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(1)");
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_RTL);
+ astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(1),
+ start, limit);
+ try {
+ bidi = new Bidi(astr.getIterator());
+ callTestEachMethod4Constructor1(textNo, testNo, bidi);
+ }
+ catch (IllegalArgumentException e) {
+ errorHandling(" Unexpected exception: " + e);
+ }
+
+ // Test 7
+ ++testNo;
+ System.out.println(" Test#" + testNo +
+ ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(2)");
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_RTL);
+ astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(2),
+ start, limit);
+ try {
+ bidi = new Bidi(astr.getIterator());
+ callTestEachMethod4Constructor1(textNo, testNo, bidi);
+ }
+ catch (IllegalArgumentException e) {
+ errorHandling(" Unexpected exception: " + e);
+ }
+
+ // Test 8
+ ++testNo;
+ System.out.println(" Test#" + testNo +
+ ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(-3)");
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_RTL);
+ astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-3),
+ start, limit);
+ try {
+ bidi = new Bidi(astr.getIterator());
+ callTestEachMethod4Constructor1(textNo, testNo, bidi);
+ }
+ catch (IllegalArgumentException e) {
+ errorHandling(" Unexpected exception: " + e);
+ }
+
+ // Test 9
+ ++testNo;
+ System.out.println(" Test#" + testNo +
+ ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(-4)");
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_RTL);
+ astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-4),
+ start, limit);
+ try {
+ bidi = new Bidi(astr.getIterator());
+ callTestEachMethod4Constructor1(textNo, testNo, bidi);
+ }
+ catch (IllegalArgumentException e) {
+ errorHandling(" Unexpected exception: " + e);
+ }
+
+ // Test 10
+ ++testNo;
+ System.out.println(" Test#" + testNo +
+ ": TextAttribute not specified");
+ astr = new AttributedString(paragraph);
+ bidi = new Bidi(astr.getIterator());
+ callTestEachMethod4Constructor1(textNo, testNo, bidi);
+
+ // Test 11
+ ++testNo;
+ System.out.println(" Test#" + testNo +
+ ": RUN_DIRECTION_LTR, NUMERIC_SHAPING(ARABIC)");
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_LTR);
+ astr.addAttribute(TextAttribute.NUMERIC_SHAPING, ns);
+ bidi = new Bidi(astr.getIterator());
+ callTestEachMethod4Constructor1(textNo, testNo, bidi);
+
+ // Test 12
+ ++testNo;
+ System.out.println(" Test#" + testNo +
+ ": RUN_DIRECTION_RTL, NUMERIC_SHAPING(ARABIC)");
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_RTL);
+ astr.addAttribute(TextAttribute.NUMERIC_SHAPING, ns);
+ bidi = new Bidi(astr.getIterator());
+ callTestEachMethod4Constructor1(textNo, testNo, bidi);
+ }
+ }
+
+ private void testMethods4Constructor2() {
+ System.out.println("*** Test methods for constructor 2");
+
+ String paragraph;
+ Bidi bidi;
+
+ for (int textNo = 0; textNo < data4Constructor2.length; textNo++) {
+ paragraph = data4Constructor2[textNo][0];
+ for (int flagNo = 0; flagNo < FLAGS.length; flagNo++) {
+ int flag = FLAGS[flagNo];
+
+ System.out.println("*** Test textNo=" + textNo +
+ ": Bidi(\"" + toReadableString(paragraph) +
+ "\", " + getFlagName(flag) + ")");
+
+ bidi = new Bidi(paragraph, flag);
+ callTestEachMethod4Constructor2(textNo, flagNo, bidi);
+ }
+ }
+ }
+
+ private void testMethods4Constructor3() {
+ System.out.println("*** Test methods for constructor 3");
+
+ String paragraph;
+ Bidi bidi;
+
+ for (int textNo = 0; textNo < data4Constructor3.length; textNo++) {
+ paragraph = data4Constructor3[textNo][0];
+ char[] c = paragraph.toCharArray();
+ int start = paragraph.indexOf('<')+1;
+ byte[][] embeddings = (c.length < emb4Constructor3[1][0].length) ?
+ emb4Constructor3[0] : emb4Constructor3[1];
+ for (int flagNo = 0; flagNo < FLAGS.length; flagNo++) {
+ int flag = FLAGS[flagNo];
+ for (int embNo = 0; embNo < embeddings.length; embNo++) {
+ int dataNo = flagNo * FLAGS.length + embNo;
+
+ System.out.println("*** Test textNo=" + textNo +
+ ": Bidi(char[]\"" + toReadableString(paragraph) +
+ "\", 0, embeddings={" + toString(embeddings[embNo]) +
+ "}, " + c.length + ", " +
+ getFlagName(flag) + ")" + " dataNo=" + dataNo);
+
+ try {
+ bidi = new Bidi(c, 0, embeddings[embNo], 0,
+ c.length, flag);
+ callTestEachMethod4Constructor3(textNo, dataNo, bidi);
+ }
+ catch (Exception e) {
+ errorHandling(" Unexpected exception: " + e);
+ }
+ }
+ }
+ }
+ }
+
+ private void testConstructor1() {
+ Bidi bidi;
+
+ try {
+ bidi = new Bidi(null);
+ errorHandling("Bidi((AttributedCharacterIterator)null) " +
+ "should throw an IAE.");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (NullPointerException e) {
+ errorHandling("Bidi((AttributedCharacterIterator)null) " +
+ "should not throw an NPE but an IAE.");
+ }
+
+ String paragraph = data4Constructor1[1][0];
+ int start = paragraph.indexOf('<')+1;
+ int limit = paragraph.indexOf('>');
+ AttributedString astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_RTL);
+ astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-61),
+ start, limit);
+ try {
+ bidi = new Bidi(astr.getIterator());
+ for (int i = start; i < limit; i++) {
+ if (bidi.getLevelAt(i) != 61) {
+ errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" +
+ i + ") should not be " + bidi.getLevelAt(i) +
+ " but 60 when BIDI_EMBEDDING is -61.");
+ }
+ }
+ }
+ catch (Exception e) {
+ errorHandling(" Unexpected exception: " + e);
+ }
+
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_RTL);
+ astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-62),
+ start, limit);
+ try {
+ bidi = new Bidi(astr.getIterator());
+ for (int i = start; i < limit; i++) {
+ if (bidi.getLevelAt(i) != 1) {
+ errorHandling("Bidi(AttributedCharacterIterator).getLevelAt() " +
+ "should be 1 when BIDI_EMBEDDING is -62.");
+ }
+ }
+ }
+ catch (Exception e) {
+ errorHandling(" Unexpected exception: " + e);
+ }
+
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_RTL);
+ astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(60),
+ start, limit);
+ try {
+ bidi = new Bidi(astr.getIterator());
+ for (int i = start; i < limit; i++) {
+ if (bidi.getLevelAt(i) != 61) {
+ errorHandling("Bidi(AttributedCharacterIterator).getLevelAt() " +
+ "should be 61 when BIDI_EMBEDDING is 60.");
+ }
+ }
+ }
+ catch (Exception e) {
+ errorHandling(" Unexpected exception: " + e);
+ }
+
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_RTL);
+ astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(61),
+ start, limit);
+ try {
+ bidi = new Bidi(astr.getIterator());
+ for (int i = start; i < limit; i++) {
+ if (bidi.getLevelAt(i) != 61) {
+ errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" +
+ i + ") should not be " + bidi.getLevelAt(i) +
+ " but 61 when BIDI_EMBEDDING is 61.");
+ }
+ }
+ }
+ catch (Exception e) {
+ errorHandling(" Unexpected exception: " + e);
+ }
+
+ astr = new AttributedString(paragraph);
+ astr.addAttribute(TextAttribute.RUN_DIRECTION,
+ TextAttribute.RUN_DIRECTION_RTL);
+ astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(62),
+ start, limit);
+ try {
+ bidi = new Bidi(astr.getIterator());
+ for (int i = start; i < limit; i++) {
+ if (bidi.getLevelAt(i) != 1) {
+ errorHandling("Bidi(AttributedCharacterIterator).getLevelAt()" +
+ " should not be " + bidi.getLevelAt(i) +
+ " but 1 when BIDI_EMBEDDING is 62.");
+ }
+ }
+ }
+ catch (Exception e) {
+ errorHandling(" Unexpected exception: " + e);
+ }
+ }
+
+ private void testConstructor2() {
+ Bidi bidi;
+
+ try {
+ bidi = new Bidi(null, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
+ errorHandling("Bidi((String)null, DIRECTION_DEFAULT_LEFT_TO_RIGHT)" +
+ " should throw an IAE.");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (NullPointerException e) {
+ errorHandling("Bidi((String)null, DIRECTION_DEFAULT_LEFT_TO_RIGHT) " +
+ "should not throw an NPE but an IAE.");
+ }
+
+ try {
+ bidi = new Bidi("abc", -3);
+ }
+ catch (Exception e) {
+ errorHandling("Bidi(\"abc\", -3) should not throw an exception: " +
+ e);
+ }
+
+ try {
+ bidi = new Bidi("abc", 2);
+ }
+ catch (Exception e) {
+ errorHandling("Bidi(\"abc\", 2) should not throw an exception: " +
+ e);
+ }
+ }
+
+ private void testConstructor3() {
+ char[] text = {'a', 'b', 'c', 'd', 'e'};
+ byte[] embeddings = {0, 0, 0, 0, 0};
+ Bidi bidi;
+
+ try {
+ bidi = new Bidi(null, 0, embeddings, 0, 5,
+ Bidi.DIRECTION_LEFT_TO_RIGHT);
+ errorHandling("Bidi(char[], ...) should throw an IAE " +
+ "when text=null.");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (NullPointerException e) {
+ errorHandling("Bidi(char[], ...) should not throw an NPE " +
+ "but an IAE when text=null.");
+ }
+
+ try {
+ bidi = new Bidi(text, -1, embeddings, 0, 5,
+ Bidi.DIRECTION_LEFT_TO_RIGHT);
+ errorHandling("Bidi(char[], ...) should throw an IAE " +
+ "when textStart is incorrect(-1: too small).");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ errorHandling("Bidi(char[], ...) should not throw an NPE " +
+ "but an IAE when textStart is incorrect(-1: too small).");
+ }
+
+ try {
+ bidi = new Bidi(text, 4, embeddings, 0, 2,
+ Bidi.DIRECTION_LEFT_TO_RIGHT);
+ errorHandling("Bidi(char[], ...) should throw an IAE " +
+ "when textStart is incorrect(4: too large).");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ errorHandling("Bidi(char[], ...) should not throw an NPE " +
+ "but an IAE when textStart is incorrect(4: too large).");
+ }
+
+ byte[] actualLevels = new byte[text.length];
+ byte[] validEmbeddings1 = {0, -61, -60, -2, -1};
+ byte[] expectedLevels1 = {0, 61, 60, 2, 1};
+ try {
+ bidi = new Bidi(text, 0, validEmbeddings1, 0, 5,
+ Bidi.DIRECTION_LEFT_TO_RIGHT);
+ for (int i = 0; i < text.length; i++) {
+ actualLevels[i] = (byte)bidi.getLevelAt(i);
+ }
+ if (!Arrays.equals(expectedLevels1, actualLevels)) {
+ errorHandling("Bidi(char[], ...).getLevelAt()" +
+ " should be {" + toString(actualLevels) +
+ "} when embeddings are {" +
+ toString(expectedLevels1) + "}.");
+ }
+ }
+ catch (Exception e) {
+ errorHandling("Bidi(char[], ...) should not throw an exception " +
+ "when embeddings is valid(-61).");
+ }
+
+ byte[] validEmbeddings2 = {0, 61, 60, 2, 1};
+ byte[] expectedLevels2 = {0, 62, 60, 2, 2};
+ try {
+ bidi = new Bidi(text, 0, validEmbeddings2, 0, 5,
+ Bidi.DIRECTION_LEFT_TO_RIGHT);
+ for (int i = 0; i < text.length; i++) {
+ actualLevels[i] = (byte)bidi.getLevelAt(i);
+ }
+ if (!Arrays.equals(expectedLevels2, actualLevels)) {
+ errorHandling("Bidi(char[], ...).getLevelAt()" +
+ " should be {" + toString(actualLevels) +
+ "} when embeddings are {" +
+ toString(expectedLevels2) + "}.");
+ }
+ }
+ catch (Exception e) {
+ errorHandling("Bidi(char[], ...) should not throw an exception " +
+ "when embeddings is valid(61).");
+ }
+
+ byte[] invalidEmbeddings1 = {0, -62, 0, 0, 0};
+ try {
+ bidi = new Bidi(text, 0, invalidEmbeddings1, 0, 5,
+ Bidi.DIRECTION_LEFT_TO_RIGHT);
+ if (bidi.getLevelAt(1) != 0) {
+ errorHandling("Bidi(char[], ...).getLevelAt(1) should be 0 " +
+ "when embeddings[1] is -62.");
+ }
+ }
+ catch (Exception e) {
+ errorHandling("Bidi(char[], ...) should not throw an exception " +
+ "even when embeddings includes -62.");
+ }
+
+ byte[] invalidEmbeddings2 = {0, 62, 0, 0, 0};
+ try {
+ bidi = new Bidi(text, 0, invalidEmbeddings2, 0, 5,
+ Bidi.DIRECTION_LEFT_TO_RIGHT);
+ if (bidi.getLevelAt(1) != 0) {
+ errorHandling("Bidi(char[], ...).getLevelAt(1) should be 0 " +
+ "when embeddings[1] is 62.");
+ }
+ }
+ catch (Exception e) {
+ errorHandling("Bidi(char[], ...) should not throw an exception " +
+ "even when embeddings includes 62.");
+ }
+
+ try {
+ bidi = new Bidi(text, 0, embeddings, 0, -1,
+ Bidi.DIRECTION_LEFT_TO_RIGHT);
+ errorHandling("Bidi(char[], ...) should throw an IAE " +
+ "when paragraphLength=-1(too small).");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (NegativeArraySizeException e) {
+ errorHandling("Bidi(char[], ...) should not throw an NASE " +
+ "but an IAE when paragraphLength=-1(too small).");
+ }
+
+ try {
+ bidi = new Bidi(text, 0, embeddings, 0, 6,
+ Bidi.DIRECTION_LEFT_TO_RIGHT);
+ errorHandling("Bidi(char[], ...) should throw an IAE " +
+ "when paragraphLength=6(too large).");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ errorHandling("Bidi(char[], ...) should not throw an AIOoBE " +
+ "but an IAE when paragraphLength=6(too large).");
+ }
+
+ try {
+ bidi = new Bidi(text, 0, embeddings, 0, 4, -3);
+ }
+ catch (Exception e) {
+ errorHandling("Bidi(char[], ...) should not throw an exception " +
+ "even when flag=-3(too small).");
+ }
+
+ try {
+ bidi = new Bidi(text, 0, embeddings, 0, 5, 2);
+ }
+ catch (Exception e) {
+ errorHandling("Bidi(char[], ...) should not throw an exception " +
+ "even when flag=2(too large).");
+ }
+ }
+
+ private void callTestEachMethod4Constructor1(int textNo,
+ int testNo,
+ Bidi bidi) {
+ testEachMethod(bidi,
+ data4Constructor1[textNo][0],
+ data4Constructor1[textNo][testNo+1],
+ baseIsLTR4Constructor1[textNo][testNo],
+ isLTR_isRTL4Constructor1[textNo][0][testNo],
+ isLTR_isRTL4Constructor1[textNo][1][testNo]);
+System.out.println(bidi.toString());
+ }
+
+ 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]);
+System.out.println(bidi.toString());
+ }
+
+ 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]);
+System.out.println(bidi.toString());
+ }
+
+ private StringBuilder sb = new StringBuilder();
+ private void testEachMethod(Bidi bidi,
+ String text,
+ String expectedLevels,
+ boolean expectedBaseIsLTR,
+ boolean expectedIsLTR,
+ boolean expectedIsRTL
+ ) {
+ /* Test baseIsLeftToRight() */
+ boolean actualBoolean = bidi.baseIsLeftToRight();
+ checkResult("baseIsLeftToRight()", expectedBaseIsLTR, actualBoolean);
+
+ /* Test getBaseLevel() */
+ int expectedInt = (expectedBaseIsLTR) ? 0 : 1;
+ int actualInt = bidi.getBaseLevel();
+ checkResult("getBaseLevel()", expectedInt, actualInt);
+
+ /* Test getLength() */
+ expectedInt = text.length();
+ actualInt = bidi.getLength();
+ checkResult("getLength()", expectedInt, actualInt);
+
+ /* Test getLevelAt() */
+ sb.setLength(0);
+ for (int i = 0; i < text.length(); i++) {
+ sb.append(bidi.getLevelAt(i));
+ }
+ checkResult("getLevelAt()", expectedLevels, sb.toString());
+
+ /* Test getRunCount() */
+ expectedInt = getRunCount(expectedLevels);
+ actualInt = bidi.getRunCount();
+ checkResult("getRunCount()", expectedInt, actualInt);
+
+ /* Test getRunLevel(), getRunLimit() and getRunStart() */
+ if (expectedInt == actualInt) {
+ int runCount = expectedInt;
+ int[] expectedRunLevels = getRunLevels_int(runCount, expectedLevels);
+ int[] expectedRunLimits = getRunLimits(runCount, expectedLevels);
+ int[] expectedRunStarts = getRunStarts(runCount, expectedLevels);
+ int[] actualRunLevels = new int[runCount];
+ int[] actualRunLimits = new int[runCount];
+ int[] actualRunStarts = new int[runCount];
+
+ for (int k = 0; k < runCount; k++) {
+ actualRunLevels[k] = bidi.getRunLevel(k);
+ actualRunLimits[k] = bidi.getRunLimit(k);
+ actualRunStarts[k] = bidi.getRunStart(k);
+ }
+
+ checkResult("getRunLevel()", expectedRunLevels, actualRunLevels);
+ checkResult("getRunStart()", expectedRunStarts, actualRunStarts);
+ checkResult("getRunLimit()", expectedRunLimits, actualRunLimits);
+ }
+
+ /* Test isLeftToRight() */
+ boolean expectedBoolean = expectedIsLTR;
+ actualBoolean = bidi.isLeftToRight();
+ checkResult("isLeftToRight()", expectedBoolean, actualBoolean);
+
+ /* Test isMixed() */
+ expectedBoolean = !(expectedIsLTR || expectedIsRTL);
+ actualBoolean = bidi.isMixed();
+ checkResult("isMixed()", expectedBoolean, actualBoolean);
+
+ /* Test isRightToLeft() */
+ expectedBoolean = expectedIsRTL;
+ actualBoolean = bidi.isRightToLeft();
+ checkResult("isRightToLeft()", expectedBoolean, actualBoolean);
+ }
+
+ private int getRunCount(String levels) {
+ int len = levels.length();
+ char c = levels.charAt(0);
+ int runCount = 1;
+
+ for (int index = 1; index < len; index++) {
+ if (levels.charAt(index) != c) {
+ runCount++;
+ c = levels.charAt(index);
+ }
+ }
+
+ return runCount;
+ }
+
+ private int[] getRunLevels_int(int runCount, String levels) {
+ int[] array = new int[runCount];
+ int len = levels.length();
+ char c = levels.charAt(0);
+ int i = 0;
+ array[i++] = c - '0';
+
+ for (int index = 1; index < len; index++) {
+ if (levels.charAt(index) != c) {
+ c = levels.charAt(index);
+ array[i++] = c - '0';
+ }
+ }
+
+ return array;
+ }
+
+ private byte[] getRunLevels_byte(int runCount, String levels) {
+ byte[] array = new byte[runCount];
+ int len = levels.length();
+ char c = levels.charAt(0);
+ int i = 0;
+ array[i++] = (byte)(c - '0');
+
+ for (int index = 1; index < len; index++) {
+ if (levels.charAt(index) != c) {
+ c = levels.charAt(index);
+ array[i++] = (byte)(c - '0');
+ }
+ }
+
+ return array;
+ }
+
+ private int[] getRunLimits(int runCount, String levels) {
+ int[] array = new int[runCount];
+ int len = levels.length();
+ char c = levels.charAt(0);
+ int i = 0;
+
+ for (int index = 1; index < len; index++) {
+ if (levels.charAt(index) != c) {
+ c = levels.charAt(index);
+ array[i++] = index;
+ }
+ }
+ array[i] = len;
+
+ return array;
+ }
+
+ private int[] getRunStarts(int runCount, String levels) {
+ int[] array = new int[runCount];
+ int len = levels.length();
+ char c = levels.charAt(0);
+ int i = 1;
+
+ for (int index = 1; index < len; index++) {
+ if (levels.charAt(index) != c) {
+ c = levels.charAt(index);
+ array[i++] = index;
+ }
+ }
+
+ return array;
+ }
+
+ private String[] getObjects(int runCount, String text, String levels) {
+ String[] array = new String[runCount];
+ int[] runLimits = getRunLimits(runCount, levels);
+ int runStart = 0;
+
+ for (int i = 0; i < runCount; i++) {
+ array[i] = text.substring(runStart, runLimits[i]);
+ runStart = runLimits[i];
+ }
+
+ return array;
+ }
+
+ private void testMethod_createLineBidi1() {
+ System.out.println("*** Test createLineBidi() 1");
+
+ String str = " ABC 123. " + HebrewABC + " " + NKo123 + ". ABC 123";
+
+ int lineStart = str.indexOf('.') + 2;
+ int lineLimit = str.lastIndexOf('.') + 2;
+ Bidi bidi = new Bidi(str, FLAGS[0]);
+ Bidi lineBidi = bidi.createLineBidi(lineStart, lineLimit);
+
+ checkResult("getBaseLevel()",
+ bidi.getBaseLevel(), lineBidi.getBaseLevel());
+ checkResult("getLevelAt(5)",
+ bidi.getLevelAt(lineStart+5), lineBidi.getLevelAt(5));
+ }
+
+ private void testMethod_createLineBidi2() {
+ System.out.println("*** Test createLineBidi() 2");
+
+ Bidi bidi = new Bidi(data4Constructor1[0][0], FLAGS[0]);
+ int len = data4Constructor1[0][0].length();
+
+ try {
+ Bidi lineBidi = bidi.createLineBidi(0, len);
+ }
+ catch (Exception e) {
+ errorHandling("createLineBidi(0, textLength)" +
+ " should not throw an exception.");
+ }
+
+ try {
+ Bidi lineBidi = bidi.createLineBidi(-1, len);
+ errorHandling("createLineBidi(-1, textLength)" +
+ " should throw an IAE.");
+ }
+ catch (IllegalArgumentException e) {
+ }
+
+ try {
+ Bidi lineBidi = bidi.createLineBidi(0, len+1);
+ errorHandling("createLineBidi(0, textLength+1)" +
+ " should throw an IAE.");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ }
+
+ /*
+ * Confirm that getLevelAt() doesn't throw an exception for invalid offset
+ * unlike ICU4J.
+ */
+ private void testMethod_getLevelAt() {
+ System.out.println("*** Test getLevelAt()");
+
+ Bidi bidi = new Bidi(data4Constructor1[1][0], FLAGS[0]);
+ int len = data4Constructor1[1][0].length();
+
+ try {
+ int level = bidi.getLevelAt(-1);
+ if (level != bidi.getBaseLevel()) {
+ errorHandling("getLevelAt(-1) returned a wrong level." +
+ " Expected=" + bidi.getBaseLevel() + ", got=" + level);
+ }
+ }
+ catch (Exception e) {
+ errorHandling("getLevelAt(-1) should not throw an exception.");
+ }
+
+ try {
+ int level = bidi.getLevelAt(len+1);
+ if (level != bidi.getBaseLevel()) {
+ errorHandling("getLevelAt(textLength+1)" +
+ " returned a wrong level." +
+ " Expected=" + bidi.getBaseLevel() + ", got=" + level);
+ }
+ }
+ catch (Exception e) {
+ errorHandling("getLevelAt(-1) should not throw an exception.");
+ }
+ }
+
+ private void testMethod_getRunLevel() {
+ System.out.println("*** Test getRunLevel()");
+
+ String str = "ABC 123";
+ int length = str.length();
+ Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
+
+ try {
+ if (bidi.getRunLevel(-1) != 0 || // runCount - 2
+ bidi.getRunLevel(0) != 0 || // runCount - 1
+ bidi.getRunLevel(1) != 0 || // runCount
+ bidi.getRunLevel(2) != 0) { // runCount + 1
+ errorHandling("getRunLevel() should return 0" +
+ " when getRunCount() is 1.");
+ }
+ }
+ catch (Exception e) {
+ errorHandling("getRunLevel() should not throw an exception " +
+ "when getRunCount() is 1.");
+ }
+
+ str = "ABC " + HebrewABC + " 123";
+ length = str.length();
+ bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
+
+ try {
+ bidi.getRunLevel(-1);
+ errorHandling("getRunLevel() should throw an AIOoBE " +
+ "when run is -1(too small).");
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ }
+ catch (IllegalArgumentException e) {
+ errorHandling("getRunLevel() should not throw an IAE " +
+ "but an AIOoBE when run is -1(too small).");
+ }
+
+ try {
+ bidi.getRunLevel(0);
+ bidi.getRunLevel(1);
+ bidi.getRunLevel(2);
+ }
+ catch (Exception e) {
+ errorHandling("getRunLevel() should not throw an exception" +
+ " when run is from 0 to 2(runCount-1).");
+ }
+
+ try {
+ bidi.getRunLevel(3);
+ errorHandling("getRunLevel() should throw an AIOoBE" +
+ " when run is 3(same as runCount).");
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ }
+ catch (IllegalArgumentException e) {
+ errorHandling("getRunLevel() should not throw an IAE " +
+ "but an AIOoBE when run is 3(same as runCount).");
+ }
+ }
+
+ private void testMethod_getRunLimit() {
+ System.out.println("*** Test getRunLimit()");
+
+ String str = "ABC 123";
+ int length = str.length();
+ Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
+
+ try {
+ if (bidi.getRunLimit(-1) != length || // runCount - 2
+ bidi.getRunLimit(0) != length || // runCount - 1
+ bidi.getRunLimit(1) != length || // runCount
+ bidi.getRunLimit(2) != length) { // runCount + 1
+ errorHandling("getRunLimit() should return " + length +
+ " when getRunCount() is 1.");
+ }
+ }
+ catch (Exception e) {
+ errorHandling("getRunLimit() should not throw an exception " +
+ "when getRunCount() is 1.");
+ }
+
+ str = "ABC " + ArabicABC + " 123";
+ length = str.length();
+ bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
+
+ try {
+ bidi.getRunLimit(-1);
+ errorHandling("getRunLimit() should throw an AIOoBE " +
+ "when run is -1(too small).");
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ }
+ catch (IllegalArgumentException e) {
+ errorHandling("getRunLimit() should not throw an IAE " +
+ "but an AIOoBE when run is -1(too small).");
+ }
+
+ try {
+ bidi.getRunLimit(0);
+ bidi.getRunLimit(1);
+ bidi.getRunLimit(2);
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ errorHandling("getRunLimit() should not throw an AIOOBE " +
+ "when run is from 0 to 2(runCount-1).");
+ }
+
+ try {
+ bidi.getRunLimit(3);
+ errorHandling("getRunLimit() should throw an AIOoBE " +
+ "when run is 3(same as runCount).");
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ }
+ catch (IllegalArgumentException e) {
+ errorHandling("getRunLimit() should not throw an IAE " +
+ "but an AIOoBE when run is 3(same as runCount).");
+ }
+ }
+
+ private void testMethod_getRunStart() {
+ System.out.println("*** Test getRunStart()");
+
+ String str = "ABC 123";
+ int length = str.length();
+ Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
+
+ try {
+ if (bidi.getRunStart(-1) != 0 || // runCount - 2
+ bidi.getRunStart(0) != 0 || // runCount - 1
+ bidi.getRunStart(1) != 0 || // runCount
+ bidi.getRunStart(2) != 0) { // runCount + 1
+ errorHandling("getRunStart() should return 0" +
+ " when getRunCount() is 1.");
+ }
+ }
+ catch (Exception e) {
+ errorHandling("getRunLimit() should not throw an exception" +
+ " when getRunCount() is 1.");
+ }
+
+ str = "ABC " + NKoABC + " 123";
+ length = str.length();
+ bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
+
+ try {
+ bidi.getRunStart(-1);
+ errorHandling("getRunStart() should throw an AIOoBE" +
+ " when run is -1(too small).");
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ }
+ catch (IllegalArgumentException e) {
+ errorHandling("getRunStart() should not throw an IAE " +
+ "but an AIOoBE when run is -1(too small).");
+ }
+
+ try {
+ bidi.getRunStart(0);
+ bidi.getRunStart(1);
+ bidi.getRunStart(2);
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ errorHandling("getRunStart() should not throw an AIOOBE " +
+ "when run is from 0 to 2(runCount-1).");
+ }
+
+ try {
+ if (bidi.getRunStart(3) != length) {
+ errorHandling("getRunStart() should return " + length +
+ " when run is 3(same as runCount).");
+ }
+ }
+ catch (Exception e) {
+ errorHandling("getRunStart() should not throw an exception " +
+ "when run is 3(same as runCount).");
+ }
+
+ try {
+ bidi.getRunStart(4);
+ errorHandling("getRunStart() should throw an AIOoBE " +
+ "when run is runCount+1(too large).");
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ }
+ catch (IllegalArgumentException e) {
+ errorHandling("getRunStart() should not throw an IAE " +
+ "but an AIOoBE when run is runCount+1(too large).");
+ }
+ }
+
+ 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);
+ }
+ }
+
+ private void testMethod_reorderVisually2() {
+ System.out.println("*** Test reorderVisually() 2");
+
+ Object[] objects = data4reorderVisually[0][0];
+ byte[] levels = getLevels(data4reorderVisually[0]);
+ int count = objects.length;
+ int llen = levels.length;
+ int olen = objects.length;
+
+ try {
+ Bidi.reorderVisually(null, 0, objects, 0, count);
+ errorHandling("reorderVisually() should throw a NPE " +
+ "when levels is null.");
+ }
+ catch (NullPointerException e) {
+ }
+
+ try {
+ Bidi.reorderVisually(levels, -1, objects, 0, count);
+ errorHandling("reorderVisually() should throw an IAE " +
+ "when levelStart is -1.");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ errorHandling("reorderVisually() should not throw an AIOoBE " +
+ "but an IAE when levelStart is -1.");
+ }
+
+ try {
+ Bidi.reorderVisually(levels, llen, objects, 0, count);
+ errorHandling("reorderVisually() should throw an IAE " +
+ "when levelStart is 6(levels.length).");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ errorHandling("reorderVisually() should not throw an AIOoBE " +
+ "but an IAE when levelStart is 6(levels.length).");
+ }
+
+ try {
+ Bidi.reorderVisually(levels, 0, null, 0, count);
+ errorHandling("reorderVisually() should throw a NPE" +
+ " when objects is null.");
+ }
+ catch (NullPointerException e) {
+ }
+
+ try {
+ Bidi.reorderVisually(levels, 0, objects, -1, count);
+ errorHandling("reorderVisually() should throw an IAE" +
+ " when objectStart is -1.");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ errorHandling("reorderVisually() should not throw an AIOoBE " +
+ "but an IAE when objectStart is -1.");
+ }
+
+ try {
+ Bidi.reorderVisually(levels, 0, objects, 6, objects.length);
+ errorHandling("reorderVisually() should throw an IAE " +
+ "when objectStart is 6(objects.length).");
+ }
+ catch (IllegalArgumentException e) {
+ }
+
+ try {
+ Bidi.reorderVisually(levels, 0, objects, 0, -1);
+ errorHandling("reorderVisually() should throw an IAE " +
+ "when count is -1.");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (NegativeArraySizeException e) {
+ errorHandling("reorderVisually() should not throw an NASE " +
+ "but an IAE when count is -1.");
+ }
+
+ try {
+ Bidi.reorderVisually(levels, 0, objects, 0, count+1);
+ errorHandling("reorderVisually() should throw an IAE " +
+ "when count is 7(objects.length+1).");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ errorHandling("reorderVisually() should not throw an AIOoBE " +
+ "but an IAE when count is 7(objects.length+1).");
+ }
+
+ try {
+ Bidi.reorderVisually(levels, 0, objects, 0, 0);
+ checkResult("reorderVisually(count=0)",
+ data4reorderVisually[0][0], objects);
+ }
+ catch (Exception e) {
+ errorHandling("reorderVisually() should not throw an exception" +
+ " when count is 0.");
+ }
+ }
+
+ private void testMethod_requiresBidi() {
+ System.out.println("*** Test requiresBidi()");
+
+ String paragraph;
+ char[] text;
+ Bidi bidi;
+
+ for (int textNo = 0; textNo < data4Constructor2.length; textNo++) {
+ paragraph = data4Constructor2[textNo][0];
+ text = paragraph.toCharArray();
+ boolean rBidi = Bidi.requiresBidi(text, 0, text.length);
+ if (rBidi != requiresBidi4Constructor2[textNo]) {
+ error = true;
+ System.err.println("Unexpected requiresBidi() value" +
+ " for requiresBidi(\"" + paragraph + "\", " + 0 + ", " +
+ text.length + ")." +
+ "\n Expected: " + requiresBidi4Constructor2[textNo] +
+ "\n Got : " + rBidi);
+ } else if (verbose) {
+ System.out.println(" Okay : requiresBidi() for" +
+ " requiresBidi(\"" + paragraph + "\", " + 0 + ", " +
+ text.length + ") Got: " + rBidi);
+ }
+ }
+
+ char[] txt = {'A', 'B', 'C', 'D', 'E'};
+ int textLength = txt.length;
+
+ try {
+ Bidi.requiresBidi(txt, -1, textLength);
+ errorHandling("requiresBidi() should throw an IAE" +
+ " when start is -1(too small).");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ errorHandling("requiresBidi() should not throw an AIOoBE " +
+ "but an IAE when start is -1(too small).");
+ }
+
+ try {
+ Bidi.requiresBidi(txt, textLength, textLength);
+ }
+ catch (Exception e) {
+ errorHandling("requiresBidi() should not throw an exception " +
+ "when start is textLength.");
+ }
+
+ try {
+ Bidi.requiresBidi(txt, textLength+1, textLength);
+ errorHandling("requiresBidi() should throw an IAE" +
+ " when start is textLength+1(too large).");
+ }
+ catch (IllegalArgumentException e) {
+ }
+
+ try {
+ Bidi.requiresBidi(txt, 0, -1);
+ errorHandling("requiresBidi() should throw an IAE" +
+ " when limit is -1(too small).");
+ }
+ catch (IllegalArgumentException e) {
+ }
+
+ try {
+ Bidi.requiresBidi(txt, 0, textLength+1);
+ errorHandling("requiresBidi() should throw an IAE" +
+ " when limit is textLength+1(too large).");
+ }
+ catch (IllegalArgumentException e) {
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ errorHandling("requiresBidi() should not throw an AIOoBE " +
+ "but an IAE when limit is textLength+1(too large).");
+ }
+ }
+
+ private void checkResult(String name,
+ int expectedValue,
+ int actualValue) {
+ if (expectedValue != actualValue) {
+ errorHandling("Unexpected " + name + " value." +
+ " Expected: " + expectedValue + " Got: " + actualValue);
+ } else if (verbose) {
+ System.out.println(" Okay : " + name + " = " + actualValue);
+ }
+ }
+
+ private void checkResult(String name,
+ boolean expectedValue,
+ boolean actualValue) {
+ if (expectedValue != actualValue) {
+ errorHandling("Unexpected " + name + " value." +
+ " Expected: " + expectedValue + " Got: " + actualValue);
+ } else if (verbose) {
+ System.out.println(" Okay : " + name + " = " + actualValue);
+ }
+ }
+
+ private void checkResult(String name,
+ String expectedValue,
+ String actualValue) {
+ if (!expectedValue.equals(actualValue)) {
+ errorHandling("Unexpected " + name + " value." +
+ "\n\tExpected: \"" + expectedValue + "\"" +
+ "\n\tGot: \"" + actualValue + "\"");
+ } else if (verbose) {
+ System.out.println(" Okay : " + name + " = \"" +
+ actualValue + "\"");
+ }
+ }
+
+ private void checkResult(String name,
+ int[] expectedValues,
+ int[] actualValues) {
+ if (!Arrays.equals(expectedValues, actualValues)) {
+ errorHandling("Unexpected " + name + " value." +
+ "\n\tExpected: " + toString(expectedValues) + "" +
+ "\n\tGot: " + toString(actualValues) + "");
+ } else if (verbose) {
+ System.out.println(" Okay : " + name + " = " +
+ toString(actualValues));
+ }
+ }
+
+ private void checkResult(String name,
+ Object[] expectedValues,
+ Object[] actualValues) {
+ if (!Arrays.equals(expectedValues, actualValues)) {
+ errorHandling("Unexpected " + name + " value." +
+ "\n\tExpected: [" + toString(expectedValues) +
+ "]\n\tGot: [" + toString(actualValues) + "]");
+ } else if (verbose) {
+ System.out.println(" Okay : " + name + " Reordered objects = [" +
+ toString(actualValues) + "]");
+ }
+ }
+
+ private void errorHandling(String msg) {
+ if (abort) {
+ throw new RuntimeException("Error: " + msg);
+ } else {
+ error = true;
+ System.err.println("**Error:" + msg);
+ }
+ }
+
+ private String toString(int[] values) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < values.length-1; i++) {
+ sb.append((int)values[i]);
+ sb.append(' ');
+ }
+ sb.append((int)values[values.length-1]);
+
+ return sb.toString();
+ }
+
+ private String toString(byte[] values) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < values.length-1; i++) {
+ sb.append((byte)values[i]);
+ sb.append(' ');
+ }
+ sb.append((byte)values[values.length-1]);
+
+ return sb.toString();
+ }
+
+ private String toString(Object[] values) {
+ StringBuilder sb = new StringBuilder();
+ String name;
+
+ for (int i = 0; i < values.length-1; i++) {
+ if ((name = getStringName((String)values[i])) != null) {
+ sb.append(name);
+ sb.append(", ");
+ } else {
+ sb.append('"');
+ sb.append((String)values[i]);
+ sb.append("\", ");
+ }
+ }
+ if ((name = getStringName((String)values[values.length-1])) != null) {
+ sb.append(name);
+ } else {
+ sb.append('"');
+ sb.append((String)values[values.length-1]);
+ sb.append('\"');
+ }
+
+ return sb.toString();
+ }
+
+ private String getStringName(String str) {
+ if (ArabicABC.equals(str)) return "ArabicABC";
+ else if (Arabic123.equals(str)) return "Arabic123";
+ else if (PArabicABC.equals(str)) return "ArabicABC(Presentation form)";
+ else if (HebrewABC.equals(str)) return "HebrewABC";
+ else if (KharoshthiABC.equals(str)) return "KharoshthiABC(RTL)";
+ else if (Kharoshthi123.equals(str)) return "Kharoshthi123(RTL)";
+ else if (NKoABC.equals(str)) return "NKoABC(RTL)";
+ else if (NKo123.equals(str)) return "NKo123(RTL)";
+ else if (OsmanyaABC.equals(str)) return "OsmanyaABC(LTR)";
+ else if (Osmanya123.equals(str)) return "Osmanya123(LTR)";
+ else return null;
+ }
+
+ private String getFlagName(int flag) {
+ if (flag == -2 || flag == 0x7e) return FLAGNAMES[0];
+ else if (flag == -1 || flag == 0x7f) return FLAGNAMES[1];
+ else if (flag == 0) return FLAGNAMES[2];
+ else if (flag == 1) return FLAGNAMES[3];
+ else return "Unknown(0x" + Integer.toHexString(flag) + ")";
+ }
+
+ private String toReadableString(String str) {
+ String s = str;
+
+ s = s.replaceAll(ArabicABC, "ArabicABC");
+ s = s.replaceAll(Arabic123, "Arabic123");
+ s = s.replaceAll(PArabicABC, "ArabicABC(Presentation form)");
+ s = s.replaceAll(HebrewABC, "HebrewABC");
+ s = s.replaceAll(KharoshthiABC, "KharoshthiABC");
+ s = s.replaceAll(Kharoshthi123, "Kharoshthi123");
+ s = s.replaceAll(NKoABC, "NKoABC");
+ s = s.replaceAll(NKo123, "NKo123");
+ s = s.replaceAll(OsmanyaABC, "OsmanyaABC");
+ s = s.replaceAll(Osmanya123, "Osmanya123");
+
+ return s;
+ }
+
+ private byte[] getLevels(Object[][] data) {
+ int levelLength = data[0].length;
+ byte[] array = new byte[levelLength];
+ int textIndex = 0;
+
+ for (int i = 0; i < levelLength; i++) {
+ array[i] = (byte)(((String)data[1][0]).charAt(textIndex) - '0');
+ textIndex += ((String)data[0][i]).length();
+ }
+
+ return array;
+ }
+
+
+ /* Bidi pubilc constants */
+ private static final int[] FLAGS = {
+ Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT, // -2 (0x7e in ICU4J)
+ Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT, // -1 (0x7f in ICU4J)
+ Bidi.DIRECTION_LEFT_TO_RIGHT, // 0
+ Bidi.DIRECTION_RIGHT_TO_LEFT // 1
+ };
+
+ /* Bidi pubilc constants names */
+ private static final String[] FLAGNAMES = {
+ "DIRECTION_DEFAULT_LEFT_TO_RIGHT", // -2
+ "DIRECTION_DEFAULT_RIGHT_TO_LEFT", // -1
+ "DIRECTION_LEFT_TO_RIGHT", // 0
+ "DIRECTION_RIGHT_TO_LEFT", // 1
+ };
+
+ /* Bidirectional Character Types */
+ private static final char L = '\u200E';
+ private static final char R = '\u202F';
+ private static final char LRE = '\u202A';
+ private static final char RLE = '\u202B';
+ private static final char PDF = '\u202C';
+ private static final char LRO = '\u202D';
+ private static final char RLO = '\u202E';
+
+ /*
+ * 0x05D0-0x05EA: [R] Hewbrew letters (Strong)
+ * 0x0627-0x063A: [AL] Arabic letters (Strong)
+ * 0x0660-0x0669: [AN] Arabic-Indic digits (Weak)
+ * 0x07CA-0x07E7: [R] NKo letters (Strong)
+ * 0x07C0-0x07C9: [R] NKo digits (Strong)
+ * 0xFE50-0xFEFF: [AL] Arabic presentaion form (Strong)
+ * 0x10480-0x1049D: [L] Osmanya letters (Strong)
+ * 0x104A0-0x104A9: [L] Osmanya digits (Strong)
+ * 0x10A10-0x10A33: [R] Kharoshthi letters (Strong)
+ * 0x10A40-0x10A43: [R] Kharoshthi digits (Strong)
+ *
+ * 0x200E: [L] Left-to-right mark (Implicit, Strong)
+ * 0x200F: [R] Right-to-left mark (Implicit, Strong)
+ * 0x202A: [LRE] Left-to-right embedding (Explicit, Strong)
+ * 0x202B: [RLE] Right-to-left embedding (Explicit, Strong)
+ * 0x202C: [PDF] Pop directional formatting (Explicit, Weak)
+ * 0x202D: [LRO] Left-to-right override (Explicit, Strong)
+ * 0x202E: [RLO] Right-to-left override (Explicit, Strong)
+ */
+
+ /* Right-to-left */
+ private static String ArabicABC = "\u0627\u0628\u0629";
+ private static String Arabic123 = "\u0661\u0662\u0663";
+ private static String PArabicABC = "\uFE97\uFE92\uFE8E";
+ private static String HebrewABC = "\u05D0\u05D1\u05D2";
+ private static String KharoshthiABC =
+ new String(Character.toChars(0x10A10)) +
+ new String(Character.toChars(0x10A11)) +
+ new String(Character.toChars(0x10A12));
+ private static String Kharoshthi123 =
+ new String(Character.toChars(0x10A40)) +
+ new String(Character.toChars(0x10A41)) +
+ new String(Character.toChars(0x10A42));
+ private static String NKoABC = "\u07CA\u07CB\u07CC";
+ private static String NKo123 = "\u07C1\u07C2\u07C3";
+
+ /* Left-to-right */
+ private static String OsmanyaABC =
+ new String(Character.toChars(0x10480)) +
+ new String(Character.toChars(0x10481)) +
+ new String(Character.toChars(0x10482));
+ private static String Osmanya123 =
+ new String(Character.toChars(0x104A0)) +
+ new String(Character.toChars(0x104A1)) +
+ new String(Character.toChars(0x104A2));
+
+ /* --------------------------------------------------------------------- */
+
+ /*
+ * Test data for Bidi(char[], ...) constructor and methods
+ */
+
+ /* Text for Bidi processing and its levels */
+ private static String[][] data4Constructor1 = {
+ /* For Text #0 */
+ {"abc <ABC XYZ> xyz.",
+ "000000000000000000", "000002222222000000", "000000000000000000",
+ "000003333333000000", "000000000000000000",
+ "222222222222222221", "222222222222222221", "222222222222222221",
+ "222113333333112221", "222224444444222221",
+ "000000000000000000", "000000000000000000", "222222222222222221"},
+
+ /* For Text #1 */
+ {"ABC <" + HebrewABC + " " + NKo123 + "> XYZ.",
+ "000001111111000000", "000001111111000000", "000003333333000000",
+ "000003333333000000", "000000000000000000",
+ "222111111111112221", "222111111111112221", "222223333333222221",
+ "222113333333112221", "222224444444222221",
+ "000001111111000000", "000001111111000000", "222111111111112221"},
+
+ /* For Text #2 */
+ {NKoABC + " <ABC XYZ> " + NKo123 + ".",
+ "111000000000001110", "111112222222111110", "111002222222001110",
+ "111113333333111110", "111004444444001110",
+ "111112222222111111", "111112222222111111", "111112222222111111",
+ "111111111111111111", "111114444444111111",
+ "111112222222111111", "111000000000001110", "111112222222111111"},
+
+ /* For Text #3 */
+ {HebrewABC + " <" + ArabicABC + " " + Arabic123 + "> " + NKo123 + ".",
+ "111111111222111110", "111111111222111110", "111003333444001110",
+ "111113333333111110", "111004444444001110",
+ "111111111222111111", "111111111222111111", "111113333444111111",
+ "111111111111111111", "111114444444111111",
+ "111111111222111111", "111111111222111110", "111111111222111111"},
+
+ /* For Text #4 */
+ {"abc <" + NKoABC + " 123> xyz.",
+ "000001111222000000", "000001111222000000", "000003333444000000",
+ "000003333333000000", "000000000000000000",
+ "222111111222112221", "222111111222112221", "222223333444222221",
+ "222113333333112221", "222224444444222221",
+ "000001111222000000", "000001111222000000", "222111111222112221"},
+
+ /* For Text #5 */
+ {"abc <ABC " + NKo123 + "> xyz.",
+ "000000000111000000", "000002221111000000", "000002222333000000",
+ "000003333333000000", "000000000000000000",
+ "222222221111112221", "222222221111112221", "222222222333222221",
+ "222113333333112221", "222224444444222221",
+ "000000000111000000", "000000000111000000", "222222221111112221"},
+
+ /* For Text #6 */
+ {ArabicABC + " <" + NKoABC + " 123" + "> " + Arabic123 + ".",
+ "111111111222112220", "111111111222112220", "111003333444002220",
+ "111113333333112220", "111004444444002220",
+ "111111111222112221", "111111111222112221", "111113333444112221",
+ "111113333333112221", "111114444444112221",
+ "111111111222112221", "111111111222112220", "111111111222112221"},
+
+ /* For Text #7 */
+ {ArabicABC + " <XYZ " + NKoABC + "> " + Arabic123 + ".",
+ "111000000111112220", "111112221111112220", "111002222333002220",
+ "111113333333112220", "111004444444002220",
+ "111112221111112221", "111112221111112221", "111112222333112221",
+ "111113333333112221", "111114444444112221",
+ "111112221111112221", "111000000111112220", "111112221111112221"},
+
+ /* For Text #8 */
+ {OsmanyaABC + " <" + KharoshthiABC + " " + Kharoshthi123 + "> " +
+ Osmanya123 + ".",
+ "000000001111111111111000000000", "000000001111111111111000000000",
+ "000000003333333333333000000000", "000000003333333333333000000000",
+ "000000000000000000000000000000",
+ "222222111111111111111112222221", "222222111111111111111112222221",
+ "222222223333333333333222222221", "222222113333333333333112222221",
+ "222222224444444444444222222221",
+ "000000001111111111111000000000", "000000001111111111111000000000",
+ "222222111111111111111112222221"},
+
+ /* For Text #9 */
+ {KharoshthiABC + " <" + OsmanyaABC + " " + Osmanya123 + "> " +
+ Kharoshthi123 + ".",
+ "111111000000000000000001111110", "111111112222222222222111111110",
+ "111111002222222222222001111110", "111111113333333333333111111110",
+ "111111004444444444444001111110",
+ "111111112222222222222111111111", "111111112222222222222111111111",
+ "111111112222222222222111111111", "111111111111111111111111111111",
+ "111111114444444444444111111111",
+ "111111112222222222222111111111", "111111000000000000000001111110",
+ "111111112222222222222111111111"},
+ };
+
+ /* Golden data for baseIsLeftToRight() results */
+ private static boolean[][] baseIsLTR4Constructor1 = {
+ /* For Text #0 */
+ {true, true, true, true, true,
+ false, false, false, false, false,
+ true, true, false},
+
+ /* For Text #1 */
+ {true, true, true, true, true,
+ false, false, false, false, false,
+ true, true, false},
+
+ /* For Text #2 */
+ {true, true, true, true, true,
+ false, false, false, false, false,
+ false, true, false},
+
+ /* For Text #3 */
+ {true, true, true, true, true,
+ false, false, false, false, false,
+ false, true, false},
+
+ /* For Text #4 */
+ {true, true, true, true, true,
+ false, false, false, false, false,
+ true, true, false},
+
+ /* For Text #5 */
+ {true, true, true, true, true,
+ false, false, false, false, false,
+ true, true, false},
+
+ /* For Text #6 */
+ {true, true, true, true, true,
+ false, false, false, false, false,
+ false, true, false},
+
+ /* For Text #7 */
+ {true, true, true, true, true,
+ false, false, false, false, false,
+ false, true, false},
+
+ /* For Text #8 */
+ {true, true, true, true, true,
+ false, false, false, false, false,
+ true, true, false},
+
+ /* For Text #9 */
+ {true, true, true, true, true,
+ false, false, false, false, false,
+ false, true, false},
+ };
+
+ /* Golden data for isLeftToRight() & isRightToLeft() results */
+ private static boolean[][][] isLTR_isRTL4Constructor1 = {
+ /* For Text #0 */
+ /* isLeftToRight() results */
+ {{true, false, true, false, true,
+ false, false, false, false, false,
+ true, true, false},
+ /* isRightToLeft() results */
+ {false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, false}},
+
+ /* For Text #1 */
+ /* isLeftToRight() results */
+ {{false, false, false, false, true,
+ false, false, false, false, false,
+ false, false, false},
+ /* isRightToLeft() results */
+ {false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, false}},
+
+ /* For Text #2 */
+ /* isLeftToRight() results */
+ {{false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, false},
+ /* isRightToLeft() results */
+ {false, false, false, false, false,
+ false, false, false, true, false,
+ false, false, false}},
+
+ /* For Text #3 */
+ /* isLeftToRight() results */
+ {{false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, false},
+ /* isRightToLeft() results */
+ {false, false, false, false, false,
+ false, false, false, true, false,
+ false, false, false}},
+
+ /* For Text #4 */
+ /* isLeftToRight() results */
+ {{false, false, false, false, true,
+ false, false, false, false, false,
+ false, false, false},
+ /* isRightToLeft() results */
+ {false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, false}},
+
+ /* For Text #5 */
+ /* isLeftToRight() results */
+ {{false, false, false, false, true,
+ false, false, false, false, false,
+ false, false, false},
+ /* isRightToLeft() results */
+ {false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, false}},
+
+ /* For Text #6 */
+ /* isLeftToRight() results */
+ {{false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, false},
+ /* isRightToLeft() results */
+ {false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, false}},
+
+ /* For Text #7 */
+ /* isLeftToRight() results */
+ {{false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, false},
+ /* isRightToLeft() results */
+ {false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, false}},
+
+ /* For Text #8 */
+ /* isLeftToRight() results */
+ {{false, false, false, false, true,
+ false, false, false, false, false,
+ false, false, false},
+ /* isRightToLeft() results */
+ {false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, false}},
+
+ /* For Text #9 */
+ /* isLeftToRight() results */
+ {{false, false, false, false, false,
+ false, false, false, false, false,
+ false, false, false},
+ /* isRightToLeft() results */
+ {false, false, false, false, false,
+ false, false, false, true, false,
+ false, false, false}},
+ };
+
+ /* --------------------------------------------------------------------- */
+
+ /*
+ * Test data for Bidi(String, int) constructor and methods
+ */
+
+ /* Text for Bidi processing and its levels */
+ private static String[][] data4Constructor2 = {
+ /* For Text #0 */
+ {" ABC 123.",
+ "000000000", "000000000", "000000000", "122222221"},
+
+ /* For Text #1 */
+ {" ABC " + HebrewABC + " " + NKo123 + " 123.",
+ "00000111111112220", "00000111111112220", "00000111111112220",
+ "12221111111112221"},
+
+ /* For Text #2 */
+ {" ABC " + ArabicABC + " " + Arabic123 + " 123.",
+ "00000111122212220", "00000111122212220", "00000111122212220",
+ "12221111122212221"},
+
+ /* For Text #3 */
+ {" " + NKoABC + " ABC 123 " + NKo123 + ".",
+ "11111222222211111", "11111222222211111", "01110000000001110",
+ "11111222222211111"},
+
+ /* For Text #4 */
+ {" " + ArabicABC + " ABC 123 " + Arabic123 + ".",
+ "11111222222212221", "11111222222212221", "01110000000002220",
+ "11111222222212221"},
+
+ /* For Text #5 */
+ {" " + HebrewABC + " " + NKo123 + ".",
+ "111111111", "111111111", "011111110", "111111111"},
+
+ /* For Text #6 */
+ {" " + ArabicABC + " " + Arabic123 + ".",
+ "111112221", "111112221", "011112220", "111112221"},
+
+ /* For Text #7 */
+ {" " + KharoshthiABC + " " + Kharoshthi123 + ".",
+ "111111111111111", "111111111111111", "011111111111110",
+ "111111111111111"},
+
+ /* For Text #8 */
+ {L + HebrewABC + " " + NKo123 + ".",
+ "011111110", "011111110", "011111110", "211111111"},
+
+ /* For Text #9 */
+ {R + "ABC " + Osmanya123 + ".",
+ "000000000000", "000000000000", "000000000000", "122222222221"},
+
+ /* For Text #10 */
+ {"ABC " + PArabicABC + " " + PArabicABC + " 123",
+ "000011111111222", "000011111111222", "000011111111222",
+ "222111111111222"},
+
+ /* For Text #11 */
+ {RLE + "ABC " + HebrewABC + " " + NKo123 + "." + PDF,
+ "22221111111110", "22221111111110", "22221111111110",
+ "44443333333331"},
+
+ /* For Text #12 */
+ {"He said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF + ".\"",
+ "000000000222211111111000", "000000000222211111111000",
+ "000000000222211111111000", "222222211444433333333111"},
+
+ /* For Text #13 */
+ {LRO + "He said \"" + RLE + "ABC " + NKoABC + " " + NKo123 + PDF +
+ ".\"" + PDF,
+ "22222222224444333333332220", "22222222224444333333332220",
+ "22222222224444333333332220", "22222222224444333333332221"},
+
+ /* For Text #14 */
+ {LRO + "He said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF +
+ ".\"", // PDF missing
+ "2222222222444433333333222", "2222222222444433333333222",
+ "2222222222444433333333222", "2222222222444433333333222"},
+
+ /* For Text #15 */
+ {"Did you say '" + LRE + "he said \"" + RLE + "ABC " + HebrewABC +
+ " " + NKo123 + PDF + "\"" + PDF + "'?",
+ "0000000000000222222222244443333333322000",
+ "0000000000000222222222244443333333322000",
+ "0000000000000222222222244443333333322000",
+ "2222222222222222222222244443333333322111"},
+
+ /* For Text #16 */
+ {RLO + "Did you say '" + LRE + "he said \"" + RLE + "ABC " +
+ HebrewABC + " " + NKo123 + PDF + "\"" + PDF + "'?" + PDF,
+ "111111111111112222222222444433333333221110",
+ "111111111111112222222222444433333333221110",
+ "111111111111112222222222444433333333221110",
+ "333333333333334444444444666655555555443331"},
+
+ /* For Text #17 */
+ {RLO + "Did you say '" + LRE + "he said \"" + RLE + "ABC " +
+ HebrewABC + " " + NKo123 + PDF + "\"" + PDF + "'?", // PDF missing
+ "11111111111111222222222244443333333322111",
+ "11111111111111222222222244443333333322111",
+ "11111111111111222222222244443333333322111",
+ "33333333333333444444444466665555555544333"},
+
+ /* For Text #18 */
+ {" ABC (" + ArabicABC + " " + Arabic123 + ") 123.",
+ "0000001111222112220", "0000001111222112220",
+ "0000001111222112220", "1222111111222112221"},
+
+ /* For Text #19 */
+ {" " + HebrewABC + " (ABC 123) " + NKo123 + ".",
+ "1111112222222111111", "1111112222222111111",
+ "0111000000000001110", "1111112222222111111"},
+
+ /* For Text #20 */
+ {" He said \"" + RLE + "ABC " + NKoABC + " " + NKo123 + PDF + ".\" ",
+ "00000000002222111111110000", "00000000002222111111110000",
+ "00000000002222111111110000", "12222222114444333333331111"},
+
+ /* For Text #21 */
+ {" Did you say '" + LRE + "he said \"" + RLE + "ABC " + HebrewABC +
+ " " + NKo123 + PDF + "\"" + PDF + "'? ",
+ "000000000000002222222222444433333333220000",
+ "000000000000002222222222444433333333220000",
+ "000000000000002222222222444433333333220000",
+ "122222222222222222222222444433333333221111"},
+
+ /* For Text #22 */
+ {RLE + OsmanyaABC + " " + KharoshthiABC + " " + Kharoshthi123 + "." +
+ PDF,
+ "22222221111111111111110", "22222221111111111111110",
+ "22222221111111111111110", "44444443333333333333331"},
+ };
+
+ /* Golden data for baseIsLeftToRight() results */
+ private static boolean[][] baseIsLTR4Constructor2 = {
+ /* For Text #0 - $4 */
+ {true, true, true, false},
+ {true, true, true, false},
+ {true, true, true, false},
+ {false, false, true, false},
+ {false, false, true, false},
+
+ /* For Text #5 - $9 */
+ {false, false, true, false},
+ {false, false, true, false},
+ {false, false, true, false},
+ {true, true, true, false},
+ {true, true, true, false},
+
+ /* For Text #10 - $14 */
+ {true, true, true, false},
+ {true, true, true, false},
+ {true, true, true, false},
+ {true, true, true, false},
+ {true, true, true, false},
+
+ /* For Text #15 - $19 */
+ {true, true, true, false},
+ {true, true, true, false},
+ {true, true, true, false},
+ {true, true, true, false},
+ {false, false, true, false},
+
+ /* For Text #20 - $22 */
+ {true, true, true, false},
+ {true, true, true, false},
+ {true, true, true, false},
+ };
+
+ /* Golden data for isLeftToRight() & isRightToLeft() results */
+ private static boolean[][][] isLTR_isRTL4Constructor2 = {
+ /* isLeftToRight() results & isRightToLeft() results */
+ /* For Text #0 - $4 */
+ {{true, true, true, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+
+ /* For Text #5 - $9 */
+ {{false, false, false, false}, {true, true, false, true }},
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {true, true, false, true }},
+ {{false, false, false, false}, {false, false, false, false}},
+ {{true, true, true, false}, {false, false, false, false}},
+
+ /* For Text #10 - $14 */
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+
+ /* For Text #15 - $19 */
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+
+ /* For Text #20 - $22 */
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+ {{false, false, false, false}, {false, false, false, false}},
+ };
+
+ /* Golden data for requiresBidi() results */
+ private static boolean[] requiresBidi4Constructor2 = {
+ /* For Text #0 - $9 */
+ false, true, true, true, true,
+ true, true, true, true, false,
+
+ /* For Text #10 - $19 */
+ true, true, true, true, true,
+ true, true, true, true, true,
+
+ /* For Text #20 - $22 */
+ true, true, true,
+ };
+
+ /* --------------------------------------------------------------------- */
+
+ /*
+ * Test data for Bidi(char[], ...) constructor and methods
+ */
+
+ /* Enbeddings */
+ private static byte[][][] emb4Constructor3 = {
+ /* Embeddings for paragraphs which don't include surrogate pairs. */
+ {{0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, -3, -3, -3, -3, -3, -3, -3, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, -4, -4, -4, -4, -4, -4, -4, 0, 0, 0, 0, 0, 0}},
+
+ /* Embeddings for paragraphs which include surrogate pairs. */
+ {{ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, 0, 0,
+ -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, 0, 0,
+ -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+ };
+
+ /* Text for Bidi processing and its levels */
+ private static String[][] data4Constructor3 = {
+ /* For Text #0 */
+ {"abc <ABC XYZ> xyz.",
+ /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
+ "000002222222000000", "000000000000000000",
+ "000003333333000000", "000000000000000000",
+ /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
+ "222222222222222221", "222222222222222221",
+ "222113333333112221", "222224444444222221",
+ /* DIRECTION_LEFT_TO_RIGHT */
+ "000002222222000000", "000000000000000000",
+ "000003333333000000", "000000000000000000",
+ /* DIRECTION_RIGHT_TO_LEFT */
+ "222222222222222221", "222222222222222221",
+ "222113333333112221", "222224444444222221"},
+
+ /* For Text #1 */
+ {"ABC <" + HebrewABC + " " + NKo123 + "> XYZ.",
+ /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
+ "000001111111000000", "000003333333000000",
+ "000003333333000000", "000000000000000000",
+ /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
+ "222111111111112221", "222223333333222221",
+ "222113333333112221", "222224444444222221",
+ /* DIRECTION_LEFT_TO_RIGHT */
+ "000001111111000000", "000003333333000000",
+ "000003333333000000", "000000000000000000",
+ /* DIRECTION_RIGHT_TO_LEFT */
+ "222111111111112221", "222223333333222221",
+ "222113333333112221", "222224444444222221"},
+
+ /* For Text #2 */
+ {NKoABC + " <ABC XYZ> " + NKo123 + ".",
+ /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
+ "111112222222111111", "111112222222111111",
+ "111111111111111111", "111114444444111111",
+ /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
+ "111112222222111111", "111112222222111111",
+ "111111111111111111", "111114444444111111",
+ /* DIRECTION_LEFT_TO_RIGHT */
+ "111112222222111110", "111002222222001110",
+ "111113333333111110", "111004444444001110",
+ /* DIRECTION_RIGHT_TO_LEFT */
+ "111112222222111111", "111112222222111111",
+ "111111111111111111", "111114444444111111"},
+
+ /* For Text #3 */
+ {HebrewABC + " <" + ArabicABC + " " + Arabic123 + "> " + NKo123 + ".",
+ /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
+ "111111111222111111", "111113333444111111",
+ "111111111111111111", "111114444444111111",
+ /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
+ "111111111222111111", "111113333444111111",
+ "111111111111111111", "111114444444111111",
+ /* DIRECTION_LEFT_TO_RIGHT */
+ "111111111222111110", "111003333444001110",
+ "111113333333111110", "111004444444001110",
+ /* DIRECTION_RIGHT_TO_LEFT */
+ "111111111222111111", "111113333444111111",
+ "111111111111111111", "111114444444111111"},
+
+ /* For Text #4 */
+ {"abc <123 456> xyz.",
+ /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
+ "000002221222000000", "000000000000000000",
+ "000003333333000000", "000000000000000000",
+ /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
+ "222222222222222221", "222222222222222221",
+ "222113333333112221", "222224444444222221",
+ /* DIRECTION_LEFT_TO_RIGHT */
+ "000002221222000000", "000000000000000000",
+ "000003333333000000", "000000000000000000",
+ /* DIRECTION_RIGHT_TO_LEFT */
+ "222222222222222221", "222222222222222221",
+ "222113333333112221", "222224444444222221"},
+
+ /* For Text #5 */
+ {OsmanyaABC + " <" + KharoshthiABC + " " + Kharoshthi123 + "> " +
+ Osmanya123 + ".",
+ /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
+ "000000001111111111111000000000", "000000003333333333333000000000",
+ "000000003333333333333000000000", "000000000000000000000000000000",
+ /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
+ "222222111111111111111112222221", "222222223333333333333222222221",
+ "222222113333333333333112222221", "222222224444444444444222222221",
+ /* DIRECTION_LEFT_TO_RIGHT */
+ "000000001111111111111000000000", "000000003333333333333000000000",
+ "000000003333333333333000000000", "000000000000000000000000000000",
+ /* DIRECTION_RIGHT_TO_LEFT */
+ "222222111111111111111112222221", "222222223333333333333222222221",
+ "222222113333333333333112222221", "222222224444444444444222222221"},
+
+ /* For Text #6 */
+ {KharoshthiABC + " <" + OsmanyaABC + " " + Osmanya123 + "> " +
+ Kharoshthi123 + ".",
+ /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
+ "111111112222222222222111111111", "111111112222222222222111111111",
+ "111111111111111111111111111111", "111111114444444444444111111111",
+ /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
+ "111111112222222222222111111111", "111111112222222222222111111111",
+ "111111111111111111111111111111", "111111114444444444444111111111",
+ /* DIRECTION_LEFT_TO_RIGHT */
+ "111111112222222222222111111110", "111111002222222222222001111110",
+ "111111113333333333333111111110", "111111004444444444444001111110",
+ /* DIRECTION_RIGHT_TO_LEFT */
+ "111111112222222222222111111111", "111111112222222222222111111111",
+ "111111111111111111111111111111", "111111114444444444444111111111"},
+ };
+
+ /* Golden data for baseIsLeftToRight() results */
+ private static boolean[][] baseIsLTR4Constructor3 = {
+ /* For Text #0 */
+ {true, true, true, true, // DIRECTION_DEFAULT_LEFT_TO_RIGHT
+ true, true, true, true, // DIRECTION_DEFAULT_RIGHT_TO_LEFT
+ true, true, true, true, // DIRECTION_LEFT_TO_RIGHT
+ false, false, false, false}, // DIRECTION_RIGHT_TO_LEFT
+
+ /* For Text #1 */
+ {true, true, true, true,
+ true, true, true, true,
+ true, true, true, true,
+ false, false, false, false},
+
+ /* For Text #2 */
+ {false, false, false, false,
+ false, false, false, false,
+ true, true, true, true,
+ false, false, false, false},
+
+ /* For Text #3 */
+ {false, false, false, false,
+ false, false, false, false,
+ true, true, true, true,
+ false, false, false, false},
+
+ /* For Text #4 */
+ {true, true, true, true,
+ true, true, true, true,
+ true, true, true, true,
+ false, false, false, false},
+
+ /* For Text #5 */
+ {true, true, true, true,
+ true, true, true, true,
+ true, true, true, true,
+ false, false, false, false},
+
+ /* For Text #6 */
+ {false, false, false, false,
+ false, false, false, false,
+ true, true, true, true,
+ false, false, false, false},
+ };
+
+ /* Golden data for isLeftToRight() & isRightToLeft() results */
+ private static boolean[][][] isLTR_isRTL4Constructor3 = {
+ /* For Text #0 */
+ /* isLeftToRight() results */
+ {{false, true, false, true, // DIRECTION_DEFAULT_LEFT_TO_RIGHT
+ false, false, false, false, // DIRECTION_DEFAULT_RIGHT_TO_LEFT
+ false, true, false, true, // DIRECTION_LEFT_TO_RIGHT
+ false, false, false, false}, // DIRECTION_RIGHT_TO_LEFT
+ /* isRightToLeft() results */
+ {false, false, false, false, // DIRECTION_DEFAULT_LEFT_TO_RIGHT
+ false, false, false, false, // DIRECTION_DEFAULT_RIGHT_TO_LEFT
+ false, false, false, false, // DIRECTION_LEFT_TO_RIGHT
+ false, false, false, false}}, // DIRECTION_RIGHT_TO_LEFTT
+
+ /* For Text #1 */
+ /* isLeftToRight() results */
+ {{false, false, false, true,
+ false, false, false, false,
+ false, false, false, true,
+ false, false, false, false},
+ /* isRightToLeft() results */
+ {false, false, false, false,
+ false, false, false, false,
+ false, false, false, false,
+ false, false, false, false}},
+
+ /* For Text #2 */
+ /* isLeftToRight() results */
+ {{false, false, false, false,
+ false, false, false, false,
+ false, false, false, false,
+ false, false, false, false},
+ /* isRightToLeft() results */
+ {false, false, true, false,
+ false, false, true, false,
+ false, false, false, false,
+ false, false, true, false}},
+
+ /* For Text #3 */
+ /* isLeftToRight() results */
+ {{false, false, false, false,
+ false, false, false, false,
+ false, false, false, false,
+ false, false, false, false},
+ /* isRightToLeft() results */
+ {false, false, true, false,
+ false, false, true, false,
+ false, false, false, false,
+ false, false, true, false}},
+
+ /* For Text #4 */
+ /* isLeftToRight() results */
+ {{false, true, false, true,
+ false, false, false, false,
+ false, true, false, true,
+ false, false, false, false },
+ /* isRightToLeft() results */
+ {false, false, false, false,
+ false, false, false, false,
+ false, false, false, false,
+ false, false, false, false}},
+
+ /* For Text #5 */
+ /* isLeftToRight() results */
+ {{false, false, false, true,
+ false, false, false, false,
+ false, false, false, true,
+ false, false, false, false},
+ /* isRightToLeft() results */
+ {false, false, false, false,
+ false, false, false, false,
+ false, false, false, false,
+ false, false, false, false}},
+
+ /* For Text #6 */
+ /* isLeftToRight() results */
+ {{false, false, false, false,
+ false, false, false, false,
+ false, false, false, false,
+ false, false, false, false},
+ /* isRightToLeft() results */
+ {false, false, true, false,
+ false, false, true, false,
+ false, false, false, false,
+ false, false, true, false}},
+ };
+
+ /* --------------------------------------------------------------------- */
+
+ /*
+ * Test data for reorderVisually() methods
+ */
+
+ private static Object[][][] data4reorderVisually = {
+ {{"ABC", " ", "abc", " ", ArabicABC, "."}, // Original text
+ {"000000001110"}, // levels
+ {"ABC", " ", "abc", " ", ArabicABC, "."}}, // Reordered text
+
+ {{"ABC", " ", HebrewABC, " ", NKoABC, "."},
+ {"222111111111"},
+ {".", NKoABC, " ", HebrewABC, " ", "ABC"}},
+
+ {{OsmanyaABC, " ", HebrewABC, " ", KharoshthiABC, "."},
+ {"222222111111111111"},
+ {".", KharoshthiABC, " ", HebrewABC, " ", OsmanyaABC,}},
+
+ {{"ABC", " ", Osmanya123, " ", "\"", OsmanyaABC, " ", Kharoshthi123,
+ " ", KharoshthiABC, ".", "\""},
+ {"0000000000002222221111111111111100"},
+ {"ABC", " ", Osmanya123, " ", "\"", KharoshthiABC, " ", Kharoshthi123,
+ " ", OsmanyaABC, ".", "\""}},
+ };
+
+}
--- a/jdk/test/java/text/Bidi/BidiEmbeddingTest.java Thu May 28 18:11:07 2009 +0400
+++ b/jdk/test/java/text/Bidi/BidiEmbeddingTest.java Sat Jun 13 06:43:54 2009 +0900
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4396492 4396496 4778510
+ * @bug 4396492 4396496 4778510 6850113
* @summary verify that the embedding values processed by the bidi code use negative values to
* indicate overrides, rather than using bit 7. Also tests Bidi without loading awt classes to
* confirm that Bidi can be used without awt. Verify that embedding level 0 is properly mapped
@@ -89,10 +89,12 @@
" at level " + bidi2.getRunLevel(i));
}
- System.out.println(bidi2);
+ System.out.println(bidi2 + "\n");
if (bidi.getRunCount() != 3 || bidi2.getRunCount() != 3) {
throw new Error("Bidi run count incorrect");
+ } else {
+ System.out.println("test1() passed.\n");
}
}
@@ -123,10 +125,12 @@
" at level " + bidi.getRunLevel(i));
}
- System.out.println(bidi);
+ 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");
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Bidi/Bug6850113.java Sat Jun 13 06:43:54 2009 +0900
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @test
+ * @bug 6850113
+ * @summary Verify the return value of digit() for some digits.
+ */
+
+import sun.text.normalizer.UCharacter;
+
+public class Bug6850113 {
+
+ public static void main(String[] args) {
+ boolean err = false;
+
+ // Fullwidth Latin capital letters
+ for (int i = 0xff21, j = 10; i <= 0xff3a; i++, j++) {
+ if (UCharacter.digit(i, 36) != j) {
+ err = true;
+ System.out.println("Error: UCharacter.digit(0x" +
+ Integer.toHexString(i) + ", 36) returned " +
+ UCharacter.digit(i, 36) + ", expected=" + j);
+ }
+ }
+
+ // Fullwidth Latin small letters
+ for (int i = 0xff41, j = 10; i <= 0xff5a; i++, j++) {
+ if (UCharacter.digit(i, 36) != j) {
+ err = true;
+ System.out.println("Error: UCharacter.digit(0x" +
+ Integer.toHexString(i) + ", 36) returned " +
+ UCharacter.digit(i, 36) + ", expected=" + j);
+ }
+ }
+
+ if (err) {
+ throw new RuntimeException("UCharacter.digit(): Wrong return value");
+ }
+ }
+}