2004-01-13 18:32:12 +00:00
|
|
|
package com.ibm.text.UCA;
|
|
|
|
|
2004-01-15 01:08:30 +00:00
|
|
|
import com.ibm.text.UCD.UCD_Types;
|
2004-01-13 18:32:12 +00:00
|
|
|
import com.ibm.text.utility.Utility;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* For generation of Implicit CEs
|
|
|
|
* @author Davis
|
|
|
|
*
|
|
|
|
* Cleaned up so that changes can be made more easily.
|
|
|
|
* Old values:
|
|
|
|
# First Implicit: E26A792D
|
|
|
|
# Last Implicit: E3DC70C0
|
|
|
|
# First CJK: E0030300
|
|
|
|
# Last CJK: E0A9DD00
|
|
|
|
# First CJK_A: E0A9DF00
|
|
|
|
# Last CJK_A: E0DE3100
|
|
|
|
|
|
|
|
*/
|
2004-01-15 01:08:30 +00:00
|
|
|
public class Implicit implements UCD_Types {
|
2004-01-13 18:32:12 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* constants
|
|
|
|
*/
|
|
|
|
static final boolean DEBUG = false;
|
|
|
|
|
|
|
|
static final long topByte = 0xFF000000L;
|
|
|
|
static final long bottomByte = 0xFFL;
|
|
|
|
static final long fourBytes = 0xFFFFFFFFL;
|
|
|
|
|
2004-01-16 01:03:28 +00:00
|
|
|
static final int MAX_INPUT = 0x220001; // 2 * Unicode range + 2
|
2004-01-13 18:32:12 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Testing function
|
|
|
|
* @param args ignored
|
|
|
|
*/
|
|
|
|
public static void main(String[] args) {
|
|
|
|
System.out.println("Start");
|
|
|
|
try {
|
|
|
|
Implicit foo = new Implicit(0xE0, 0xE4);
|
2004-01-15 01:08:30 +00:00
|
|
|
|
|
|
|
//int x = foo.getRawImplicit(0xF810);
|
2004-01-16 01:22:27 +00:00
|
|
|
foo.getRawFromImplicit(0xE20303E7);
|
2004-01-15 01:08:30 +00:00
|
|
|
|
2004-01-13 18:32:12 +00:00
|
|
|
int gap4 = foo.getGap4();
|
2004-01-16 01:03:28 +00:00
|
|
|
System.out.println("Gap4: " + gap4);
|
2004-01-13 18:32:12 +00:00
|
|
|
int gap3 = foo.getGap3();
|
|
|
|
int minTrail = foo.getMinTrail();
|
|
|
|
int maxTrail = foo.getMaxTrail();
|
|
|
|
long last = 0;
|
|
|
|
long current;
|
|
|
|
for (int i = 0; i <= MAX_INPUT; ++i) {
|
2004-01-16 01:22:27 +00:00
|
|
|
current = foo.getImplicitFromRaw(i) & fourBytes;
|
2004-01-15 01:08:30 +00:00
|
|
|
|
|
|
|
// check that it round-trips AND that all intervening ones are illegal
|
2004-01-16 01:22:27 +00:00
|
|
|
int roundtrip = foo.getRawFromImplicit((int)current);
|
2004-01-15 01:08:30 +00:00
|
|
|
if (roundtrip != i) {
|
|
|
|
foo.throwError("No roundtrip", i);
|
|
|
|
}
|
|
|
|
if (last != 0) {
|
|
|
|
for (long j = last + 1; j < current; ++j) {
|
2004-01-16 01:22:27 +00:00
|
|
|
roundtrip = foo.getRawFromImplicit((int)j);
|
2004-01-15 01:08:30 +00:00
|
|
|
// raise an error if it *doesn't* find an error
|
|
|
|
if (roundtrip != -1) {
|
|
|
|
foo.throwError("Fails to recognize illegal", j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// now do other consistency checks
|
2004-01-13 18:32:12 +00:00
|
|
|
long lastBottom = last & bottomByte;
|
|
|
|
long currentBottom = current & bottomByte;
|
|
|
|
long lastTop = last & topByte;
|
|
|
|
long currentTop = current & topByte;
|
|
|
|
|
|
|
|
// do some consistency checks
|
2004-01-15 01:08:30 +00:00
|
|
|
/*
|
2004-01-13 18:32:12 +00:00
|
|
|
long gap = current - last;
|
|
|
|
if (currentBottom != 0) { // if we are a 4-byte
|
|
|
|
// gap has to be at least gap4
|
|
|
|
// and gap from minTrail, maxTrail has to be at least gap4
|
|
|
|
if (gap <= gap4) foo.throwError("Failed gap4 between", i);
|
|
|
|
if (currentBottom < minTrail + gap4) foo.throwError("Failed gap4 before", i);
|
|
|
|
if (currentBottom > maxTrail - gap4) foo.throwError("Failed gap4 after", i);
|
|
|
|
} else { // we are a three-byte
|
|
|
|
gap = gap >> 8; // move gap down for comparison.
|
|
|
|
long current3Bottom = (current >> 8) & bottomByte;
|
|
|
|
if (gap <= gap3) foo.throwError("Failed gap3 between ", i);
|
|
|
|
if (current3Bottom < minTrail + gap3) foo.throwError("Failed gap3 before", i);
|
|
|
|
if (current3Bottom > maxTrail - gap3) foo.throwError("Failed gap3 after", i);
|
|
|
|
}
|
2004-01-15 01:08:30 +00:00
|
|
|
*/
|
2004-01-13 18:32:12 +00:00
|
|
|
// print out some values for spot-checking
|
|
|
|
if (lastTop != currentTop || i == 0x10000 || i == 0x110000) {
|
|
|
|
foo.show(i-3);
|
|
|
|
foo.show(i-2);
|
|
|
|
foo.show(i-1);
|
|
|
|
if (i == 0) {
|
|
|
|
// do nothing
|
|
|
|
} else if (lastBottom == 0 && currentBottom != 0) {
|
|
|
|
System.out.println("+ primary boundary, 4-byte CE's below");
|
|
|
|
} else if (lastTop != currentTop) {
|
|
|
|
System.out.println("+ primary boundary");
|
|
|
|
}
|
|
|
|
foo.show(i);
|
|
|
|
foo.show(i+1);
|
|
|
|
foo.show(i+2);
|
|
|
|
System.out.println("...");
|
|
|
|
}
|
|
|
|
last = current;
|
|
|
|
}
|
|
|
|
foo.show(MAX_INPUT-2);
|
|
|
|
foo.show(MAX_INPUT-1);
|
|
|
|
foo.show(MAX_INPUT);
|
|
|
|
} catch (Exception e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
} finally {
|
|
|
|
System.out.println("End");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-01-15 01:08:30 +00:00
|
|
|
private void throwError(String title, int cp) {
|
2004-01-16 01:22:27 +00:00
|
|
|
throw new IllegalArgumentException(title + "\t" + Utility.hex(cp) + "\t" + Utility.hex(getImplicitFromRaw(cp) & fourBytes));
|
2004-01-15 01:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void throwError(String title, long ce) {
|
|
|
|
throw new IllegalArgumentException(title + "\t" + Utility.hex(ce & fourBytes));
|
2004-01-13 18:32:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void show(int i) {
|
|
|
|
if (i >= 0 && i <= MAX_INPUT) {
|
2004-01-16 01:22:27 +00:00
|
|
|
System.out.println(Utility.hex(i) + "\t" + Utility.hex(getImplicitFromRaw(i) & fourBytes));
|
2004-01-13 18:32:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Precomputed by constructor
|
|
|
|
*/
|
|
|
|
int final3Multiplier;
|
|
|
|
int final4Multiplier;
|
|
|
|
int final3Count;
|
|
|
|
int final4Count;
|
|
|
|
int medialCount;
|
|
|
|
int min3Primary;
|
|
|
|
int min4Primary;
|
|
|
|
int max4Primary;
|
|
|
|
int minTrail;
|
|
|
|
int maxTrail;
|
2004-01-15 01:08:30 +00:00
|
|
|
int max3Trail;
|
|
|
|
int max4Trail;
|
2004-01-13 18:32:12 +00:00
|
|
|
int min4Boundary;
|
|
|
|
|
|
|
|
public int getGap4() {
|
|
|
|
return final4Multiplier - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getGap3() {
|
|
|
|
return final3Multiplier - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// old comment
|
2004-01-16 01:03:28 +00:00
|
|
|
// we must skip all 00, 01, 02, FF bytes, so most bytes have 252 values
|
2004-01-13 18:32:12 +00:00
|
|
|
// we must leave a gap of 01 between all values of the last byte, so the last byte has 126 values (3 byte case)
|
|
|
|
// we shift so that HAN all has the same first primary, for compression.
|
|
|
|
// for the 4 byte case, we make the gap as large as we can fit.
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Supply parameters for generating implicit CEs
|
|
|
|
*/
|
|
|
|
public Implicit(int minPrimary, int maxPrimary) {
|
|
|
|
// 13 is the largest 4-byte gap we can use without getting 2 four-byte forms.
|
2004-01-15 01:08:30 +00:00
|
|
|
this(minPrimary, maxPrimary, 0x03, 0xFE, 1, 1);
|
2004-01-13 18:32:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set up to generate implicits.
|
|
|
|
* @param minPrimary
|
|
|
|
* @param maxPrimary
|
|
|
|
* @param minTrail final byte
|
|
|
|
* @param maxTrail final byte
|
|
|
|
* @param gap3 the gap we leave for tailoring for 3-byte forms
|
2004-01-16 01:03:28 +00:00
|
|
|
* @param primaries3count number of 3-byte primarys we can use (normally 1)
|
2004-01-13 18:32:12 +00:00
|
|
|
*/
|
2004-01-15 01:08:30 +00:00
|
|
|
public Implicit(int minPrimary, int maxPrimary, int minTrail, int maxTrail, int gap3, int primaries3count) {
|
2004-01-13 18:32:12 +00:00
|
|
|
// some simple parameter checks
|
|
|
|
if (minPrimary < 0 || minPrimary >= maxPrimary || maxPrimary > 0xFF) throw new IllegalArgumentException("bad lead bytes");
|
|
|
|
if (minTrail < 0 || minTrail >= maxTrail || maxTrail > 0xFF) throw new IllegalArgumentException("bad trail bytes");
|
2004-01-16 01:03:28 +00:00
|
|
|
if (primaries3count < 1) throw new IllegalArgumentException("bad three-byte primaries");
|
2004-01-13 18:32:12 +00:00
|
|
|
|
|
|
|
this.minTrail = minTrail;
|
|
|
|
this.maxTrail = maxTrail;
|
|
|
|
|
|
|
|
min3Primary = minPrimary;
|
|
|
|
max4Primary = maxPrimary;
|
|
|
|
// compute constants for use later.
|
|
|
|
// number of values we can use in trailing bytes
|
2004-01-15 01:08:30 +00:00
|
|
|
// leave room for empty values between AND above, e.g. if gap = 2
|
|
|
|
// range 3..7 => +3 -4 -5 -6 -7: so 1 value
|
|
|
|
// range 3..8 => +3 -4 -5 +6 -7 -8: so 2 values
|
|
|
|
// range 3..9 => +3 -4 -5 +6 -7 -8 -9: so 2 values
|
|
|
|
final3Multiplier = gap3 + 1;
|
|
|
|
final3Count = (maxTrail - minTrail + 1) / final3Multiplier;
|
|
|
|
max3Trail = minTrail + (final3Count - 1) * final3Multiplier;
|
|
|
|
|
2004-01-13 18:32:12 +00:00
|
|
|
// medials can use full range
|
|
|
|
medialCount = (maxTrail - minTrail + 1);
|
|
|
|
// find out how many values fit in each form
|
|
|
|
int threeByteCount = medialCount * final3Count;
|
|
|
|
// now determine where the 3/4 boundary is.
|
|
|
|
// we use 3 bytes below the boundary, and 4 above
|
|
|
|
int primariesAvailable = maxPrimary - minPrimary + 1;
|
2004-01-16 01:03:28 +00:00
|
|
|
int primaries4count = primariesAvailable - primaries3count;
|
2004-01-15 01:08:30 +00:00
|
|
|
|
|
|
|
int min3ByteCoverage = primaries3count * threeByteCount;
|
|
|
|
min4Primary = minPrimary + primaries3count;
|
2004-01-13 18:32:12 +00:00
|
|
|
min4Boundary = min3ByteCoverage;
|
|
|
|
// Now expand out the multiplier for the 4 bytes, and redo.
|
2004-01-15 01:08:30 +00:00
|
|
|
|
2004-01-13 18:32:12 +00:00
|
|
|
int totalNeeded = MAX_INPUT - min4Boundary;
|
2004-01-15 01:08:30 +00:00
|
|
|
int neededPerPrimaryByte = divideAndRoundUp(totalNeeded, primaries4count);
|
2004-01-13 18:32:12 +00:00
|
|
|
if (DEBUG) System.out.println("neededPerPrimaryByte: " + neededPerPrimaryByte);
|
2004-01-16 01:03:28 +00:00
|
|
|
|
2004-01-13 18:32:12 +00:00
|
|
|
int neededPerFinalByte = divideAndRoundUp(neededPerPrimaryByte, medialCount * medialCount);
|
|
|
|
if (DEBUG) System.out.println("neededPerFinalByte: " + neededPerFinalByte);
|
2004-01-16 01:03:28 +00:00
|
|
|
|
2004-01-15 01:08:30 +00:00
|
|
|
int gap4 = (maxTrail - minTrail - 1) / neededPerFinalByte;
|
|
|
|
if (DEBUG) System.out.println("expandedGap: " + gap4);
|
|
|
|
if (gap4 < 1) throw new IllegalArgumentException("must have larger gap4s");
|
2004-01-16 01:03:28 +00:00
|
|
|
|
2004-01-15 01:08:30 +00:00
|
|
|
final4Multiplier = gap4 + 1;
|
2004-01-13 18:32:12 +00:00
|
|
|
final4Count = neededPerFinalByte;
|
2004-01-15 01:08:30 +00:00
|
|
|
max4Trail = minTrail + (final4Count - 1) * final4Multiplier;
|
2004-01-16 01:03:28 +00:00
|
|
|
|
|
|
|
if (primaries4count * medialCount * medialCount * final4Count < MAX_INPUT) {
|
|
|
|
throw new IllegalArgumentException("internal error");
|
|
|
|
}
|
2004-01-13 18:32:12 +00:00
|
|
|
if (DEBUG) {
|
|
|
|
System.out.println("final4Count: " + final4Count);
|
2004-01-16 01:03:28 +00:00
|
|
|
for (int counter = 0; counter < final4Count; ++counter) {
|
2004-01-13 18:32:12 +00:00
|
|
|
int value = minTrail + (1 + counter)*final4Multiplier;
|
|
|
|
System.out.println(counter + "\t" + value + "\t" + Utility.hex(value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static public int divideAndRoundUp(int a, int b) {
|
|
|
|
return 1 + (a-1)/b;
|
|
|
|
}
|
2004-01-15 01:08:30 +00:00
|
|
|
/**
|
2004-01-16 01:22:27 +00:00
|
|
|
* Converts implicit CE into raw integer
|
2004-01-15 01:08:30 +00:00
|
|
|
* @param implicit
|
|
|
|
* @return -1 if illegal format
|
|
|
|
*/
|
2004-01-16 01:22:27 +00:00
|
|
|
public int getRawFromImplicit(int implicit) {
|
2004-01-15 01:08:30 +00:00
|
|
|
int result;
|
|
|
|
int b3 = implicit & 0xFF;
|
|
|
|
implicit >>= 8;
|
|
|
|
int b2 = implicit & 0xFF;
|
|
|
|
implicit >>= 8;
|
|
|
|
int b1 = implicit & 0xFF;
|
|
|
|
implicit >>= 8;
|
|
|
|
int b0 = implicit & 0xFF;
|
|
|
|
|
|
|
|
// simple parameter checks
|
|
|
|
if (b0 < min3Primary || b0 > max4Primary
|
|
|
|
|| b1 < minTrail || b1 > maxTrail) return -1;
|
|
|
|
// normal offsets
|
|
|
|
b1 -= minTrail;
|
|
|
|
|
|
|
|
// take care of the final values, and compose
|
|
|
|
if (b0 < min4Primary) {
|
|
|
|
if (b2 < minTrail || b2 > max3Trail || b3 != 0) return -1;
|
|
|
|
b2 -= minTrail;
|
|
|
|
int remainder = b2 % final3Multiplier;
|
|
|
|
if (remainder != 0) return -1;
|
|
|
|
b0 -= min3Primary;
|
|
|
|
b2 /= final3Multiplier;
|
|
|
|
result = ((b0 * medialCount) + b1) * final3Count + b2;
|
|
|
|
} else {
|
|
|
|
if (b2 < minTrail || b2 > maxTrail
|
|
|
|
|| b3 < minTrail || b3 > max4Trail) return -1;
|
|
|
|
b2 -= minTrail;
|
|
|
|
b3 -= minTrail;
|
|
|
|
int remainder = b3 % final4Multiplier;
|
|
|
|
if (remainder != 0) return -1;
|
|
|
|
b3 /= final4Multiplier;
|
|
|
|
b0 -= min4Primary;
|
|
|
|
result = (((b0 * medialCount) + b1) * medialCount + b2) * final4Count + b3 + min4Boundary;
|
|
|
|
}
|
|
|
|
// final check
|
|
|
|
if (result < 0 || result > MAX_INPUT) return -1;
|
|
|
|
return result;
|
|
|
|
}
|
2004-01-13 18:32:12 +00:00
|
|
|
|
|
|
|
/**
|
2004-01-16 01:22:27 +00:00
|
|
|
* Generate the implicit CE, from raw integer.
|
|
|
|
* Left shifted to put the first byte at the top of an int.
|
2004-01-13 18:32:12 +00:00
|
|
|
* @param cp code point
|
|
|
|
* @return
|
|
|
|
*/
|
2004-01-16 01:22:27 +00:00
|
|
|
public int getImplicitFromRaw(int cp) {
|
2004-01-13 18:32:12 +00:00
|
|
|
if (cp < 0 || cp > MAX_INPUT) {
|
|
|
|
throw new IllegalArgumentException("Code point out of range " + Utility.hex(cp));
|
|
|
|
}
|
|
|
|
int last0 = cp - min4Boundary;
|
|
|
|
if (last0 < 0) {
|
|
|
|
int last1 = cp / final3Count;
|
|
|
|
last0 = cp % final3Count;
|
|
|
|
|
|
|
|
int last2 = last1 / medialCount;
|
|
|
|
last1 %= medialCount;
|
|
|
|
|
2004-01-15 01:08:30 +00:00
|
|
|
last0 = minTrail + last0*final3Multiplier; // spread out, leaving gap at start
|
2004-01-13 18:32:12 +00:00
|
|
|
last1 = minTrail + last1; // offset
|
|
|
|
last2 = min3Primary + last2; // offset
|
|
|
|
|
|
|
|
if (last2 >= min4Primary) {
|
|
|
|
throw new IllegalArgumentException("4-byte out of range: " + Utility.hex(cp) + ", " + Utility.hex(last2));
|
|
|
|
}
|
|
|
|
|
|
|
|
return (last2 << 24) + (last1 << 16) + (last0 << 8);
|
|
|
|
} else {
|
|
|
|
int last1 = last0 / final4Count;
|
|
|
|
last0 %= final4Count;
|
|
|
|
|
|
|
|
int last2 = last1 / medialCount;
|
|
|
|
last1 %= medialCount;
|
|
|
|
|
|
|
|
int last3 = last2 / medialCount;
|
|
|
|
last2 %= medialCount;
|
|
|
|
|
2004-01-15 01:08:30 +00:00
|
|
|
last0 = minTrail + last0*final4Multiplier; // spread out, leaving gap at start
|
2004-01-13 18:32:12 +00:00
|
|
|
last1 = minTrail + last1; // offset
|
|
|
|
last2 = minTrail + last2; // offset
|
|
|
|
last3 = min4Primary + last3; // offset
|
|
|
|
|
|
|
|
if (last3 > max4Primary) {
|
|
|
|
throw new IllegalArgumentException("4-byte out of range: " + Utility.hex(cp) + ", " + Utility.hex(last3));
|
|
|
|
}
|
|
|
|
|
|
|
|
return (last3 << 24) + (last2 << 16) + (last1 << 8) + last0;
|
|
|
|
}
|
|
|
|
}
|
2004-01-16 01:22:27 +00:00
|
|
|
/**
|
|
|
|
* Gets an Implicit from a code point. Internally,
|
|
|
|
* swaps (which produces a raw value 0..220000,
|
|
|
|
* then converts raw to implicit.
|
|
|
|
* @param cp
|
|
|
|
* @return
|
|
|
|
*/
|
2004-01-15 01:08:30 +00:00
|
|
|
public int getSwappedImplicit(int cp) {
|
|
|
|
if (DEBUG) System.out.println("Incoming: " + Utility.hex(cp));
|
2004-01-16 01:03:28 +00:00
|
|
|
|
2004-01-16 01:22:27 +00:00
|
|
|
// Produce Raw value
|
|
|
|
// note, we add 1 so that the first value is always empty!!
|
2004-01-16 01:03:28 +00:00
|
|
|
cp = Implicit.swapCJK(cp) + 1;
|
|
|
|
// we now have a range of numbers from 0 to 220000.
|
2004-01-15 01:08:30 +00:00
|
|
|
|
|
|
|
if (DEBUG) System.out.println("CJK swapped: " + Utility.hex(cp));
|
|
|
|
|
2004-01-16 01:22:27 +00:00
|
|
|
return getImplicitFromRaw(cp);
|
2004-01-15 01:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function used to:
|
|
|
|
* a) collapse the 2 different Han ranges from UCA into one (in the right order), and
|
|
|
|
* b) bump any non-CJK characters by 10FFFF.
|
|
|
|
* The relevant blocks are:
|
|
|
|
* A: 4E00..9FFF; CJK Unified Ideographs
|
|
|
|
* F900..FAFF; CJK Compatibility Ideographs
|
|
|
|
* B: 3400..4DBF; CJK Unified Ideographs Extension A
|
|
|
|
* 20000..XX; CJK Unified Ideographs Extension B (and others later on)
|
|
|
|
* As long as
|
|
|
|
* no new B characters are allocated between 4E00 and FAFF, and
|
|
|
|
* no new A characters are outside of this range,
|
|
|
|
* (very high probability) this simple code will work.
|
|
|
|
* The reordered blocks are:
|
|
|
|
* Block1 is CJK
|
|
|
|
* Block2 is CJK_COMPAT_USED
|
|
|
|
* Block3 is CJK_A
|
|
|
|
* (all contiguous)
|
|
|
|
* Any other CJK gets its normal code point
|
|
|
|
* Any non-CJK gets +10FFFF
|
|
|
|
* When we reorder Block1, we make sure that it is at the very start,
|
|
|
|
* so that it will use a 3-byte form.
|
|
|
|
* Warning: the we only pick up the compatibility characters that are
|
|
|
|
* NOT decomposed, so that block is smaller!
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int NON_CJK_OFFSET = 0x110000;
|
|
|
|
|
|
|
|
static int swapCJK(int i) {
|
|
|
|
|
|
|
|
if (i >= CJK_BASE) {
|
|
|
|
if (i < CJK_LIMIT) return i - CJK_BASE;
|
|
|
|
|
|
|
|
if (i < CJK_COMPAT_USED_BASE) return i + NON_CJK_OFFSET;
|
|
|
|
|
|
|
|
if (i < CJK_COMPAT_USED_LIMIT) return i - CJK_COMPAT_USED_BASE
|
|
|
|
+ (CJK_LIMIT - CJK_BASE);
|
|
|
|
if (i < CJK_B_BASE) return i + NON_CJK_OFFSET;
|
|
|
|
|
|
|
|
if (i < CJK_B_LIMIT) return i; // non-BMP-CJK
|
|
|
|
|
|
|
|
return i + NON_CJK_OFFSET; // non-CJK
|
|
|
|
}
|
|
|
|
if (i < CJK_A_BASE) return i + NON_CJK_OFFSET;
|
|
|
|
|
|
|
|
if (i < CJK_A_LIMIT) return i - CJK_A_BASE
|
|
|
|
+ (CJK_LIMIT - CJK_BASE)
|
|
|
|
+ (CJK_COMPAT_USED_LIMIT - CJK_COMPAT_USED_BASE);
|
|
|
|
return i + NON_CJK_OFFSET; // non-CJK
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-13 18:32:12 +00:00
|
|
|
/**
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public int getMinTrail() {
|
|
|
|
return minTrail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public int getMaxTrail() {
|
|
|
|
return maxTrail;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|