*/
public final class CharacterSetECI extends ECI {
- private static final Hashtable VALUE_TO_ECI;
- static {
+ private static Hashtable VALUE_TO_ECI;
+ private static Hashtable NAME_TO_ECI;
+
+ private static void initialize() {
VALUE_TO_ECI = new Hashtable(29);
+ NAME_TO_ECI = new Hashtable(29);
// TODO figure out if these values are even right!
addCharacterSet(0, "Cp437");
- addCharacterSet(1, "ISO8859_1");
+ addCharacterSet(1, new String[] {"ISO8859_1", "ISO-8859-1"});
addCharacterSet(2, "Cp437");
- addCharacterSet(3, "ISO8859_1");
+ addCharacterSet(3, new String[] {"ISO8859_1", "ISO-8859-1"});
addCharacterSet(4, "ISO8859_2");
addCharacterSet(5, "ISO8859_3");
addCharacterSet(6, "ISO8859_4");
addCharacterSet(16, "ISO8859_14");
addCharacterSet(17, "ISO8859_15");
addCharacterSet(18, "ISO8859_16");
- addCharacterSet(20, "SJIS");
+ addCharacterSet(20, new String[] {"SJIS", "Shift_JIS"});
}
private final String encodingName;
}
private static void addCharacterSet(int value, String encodingName) {
- VALUE_TO_ECI.put(new Integer(value), new CharacterSetECI(value, encodingName));
+ CharacterSetECI eci = new CharacterSetECI(value, encodingName);
+ VALUE_TO_ECI.put(new Integer(value), eci);
+ NAME_TO_ECI.put(encodingName, eci);
+ }
+
+ private static void addCharacterSet(int value, String[] encodingNames) {
+ CharacterSetECI eci = new CharacterSetECI(value, encodingNames[0]);
+ VALUE_TO_ECI.put(new Integer(value), eci);
+ for (int i = 0; i < encodingNames.length; i++) {
+ NAME_TO_ECI.put(encodingNames[i], eci);
+ }
}
+ /**
+ * @param value character set ECI value
+ * @return {@link CharacterSetECI} representing ECI of given value, or null if it is legal but unsupported
+ * @throws IllegalArgumentException if ECI value is invalid
+ */
public static CharacterSetECI getCharacterSetECIByValue(int value) {
- CharacterSetECI eci = (CharacterSetECI) VALUE_TO_ECI.get(new Integer(value));
- if (eci == null) {
- throw new IllegalArgumentException("Unsupported value: " + value);
+ if (VALUE_TO_ECI == null) {
+ initialize();
+ }
+ if (value < 0 || value >= 900) {
+ throw new IllegalArgumentException("Bad ECI value: " + value);
+ }
+ return (CharacterSetECI) VALUE_TO_ECI.get(new Integer(value));
+ }
+
+ /**
+ * @param name character set ECI encoding name
+ * @return {@link CharacterSetECI} representing ECI for character encoding, or null if it is legal but unsupported
+ */
+ public static CharacterSetECI getCharacterSetECIByName(String name) {
+ if (NAME_TO_ECI == null) {
+ initialize();
}
- return eci;
+ return (CharacterSetECI) NAME_TO_ECI.get(name);
}
}
\ No newline at end of file
return value;
}
+ /**
+ * @param value ECI value
+ * @return {@link ECI} representing ECI of given value, or null if it is legal but unsupported
+ * @throws IllegalArgumentException if ECI value is invalid
+ */
public static ECI getECIByValue(int value) {
if (value < 0 || value > 999999) {
throw new IllegalArgumentException("Bad ECI value: " + value);
if (value < 900) { // Character set ECIs use 000000 - 000899
return CharacterSetECI.getCharacterSetECIByValue(value);
}
- throw new IllegalArgumentException("Unsupported ECI value: " + value);
+ return null;
}
}
bits.readBits(16);
} else if (mode.equals(Mode.ECI)) {
// Count doesn't apply to ECI
- try {
- int value = parseECIValue(bits);
- currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);
- } catch (IllegalArgumentException iae) {
+ int value = parseECIValue(bits);
+ currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);
+ if (currentCharacterSetECI == null) {
throw ReaderException.getInstance();
}
} else {
import com.google.zxing.EncodeHintType;
import com.google.zxing.common.ByteArray;
import com.google.zxing.common.ByteMatrix;
+import com.google.zxing.common.CharacterSetECI;
import com.google.zxing.common.reedsolomon.GF256;
import com.google.zxing.common.reedsolomon.ReedSolomonEncoder;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f
};
+ static final String DEFAULT_BYTE_MODE_ENCODING = "ISO-8859-1";
+
private Encoder() {
}
String characterEncoding = hints == null ? null : (String) hints.get(EncodeHintType.CHARACTER_SET);
if (characterEncoding == null) {
- characterEncoding = "ISO-8859-1";
+ characterEncoding = DEFAULT_BYTE_MODE_ENCODING;
}
// Step 1: Choose the mode (encoding).
// Step 4: Build another bit vector that contains header and data.
BitVector headerAndDataBits = new BitVector();
- appendModeInfo(qrCode.getMode(), headerAndDataBits);
- appendLengthInfo(content.length(), qrCode.getVersion(), qrCode.getMode(), headerAndDataBits);
+
+ // Step 4.5: Append ECI message if applicable
+ /*
+ if (mode == Mode.BYTE && !DEFAULT_BYTE_MODE_ENCODING.equals(characterEncoding)) {
+ CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(characterEncoding);
+ if (eci != null) {
+ appendECI(eci, headerAndDataBits);
+ }
+ }
+ */
+ appendModeInfo(mode, headerAndDataBits);
+ appendLengthInfo(content.length(), qrCode.getVersion(), mode, headerAndDataBits);
headerAndDataBits.appendBitVector(dataBits);
// Step 5: Terminate the bits properly.
throw new WriterException("data bits cannot fit in the QR Code" + bits.size() + " > " + capacity);
}
// Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details.
+ // TODO srowen says we can remove this for loop, since the 4 terminator bits are optional if the last byte
+ // has less than 4 bits left. So it amounts to padding the last byte with zeroes either way.
for (int i = 0; i < 4 && bits.size() < capacity; ++i) {
bits.appendBit(0);
}
}
}
+ static void appendECI(CharacterSetECI eci, BitVector bits) {
+ bits.appendBits(Mode.ECI.getBits(), 4);
+ bits.appendBits(eci.getValue(), 8); // This is correct for values up to 127, which is all we need now
+ }
+
}
// Should use appendNumericBytes.
// 1 = 01 = 0001 in 4 bits.
BitVector bits = new BitVector();
- Encoder.appendBytes("1", Mode.NUMERIC, bits);
+ Encoder.appendBytes("1", Mode.NUMERIC, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
assertEquals("0001" , bits.toString());
}
{
// Should use appendAlphanumericBytes.
// A = 10 = 0xa = 001010 in 6 bits
BitVector bits = new BitVector();
- Encoder.appendBytes("A", Mode.ALPHANUMERIC, bits);
+ Encoder.appendBytes("A", Mode.ALPHANUMERIC, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
assertEquals("001010" , bits.toString());
// Lower letters such as 'a' cannot be encoded in MODE_ALPHANUMERIC.
try {
- Encoder.appendBytes("a", Mode.ALPHANUMERIC, bits);
+ Encoder.appendBytes("a", Mode.ALPHANUMERIC, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
} catch (WriterException we) {
// good
}
// Should use append8BitBytes.
// 0x61, 0x62, 0x63
BitVector bits = new BitVector();
- Encoder.appendBytes("abc", Mode.BYTE, bits);
+ Encoder.appendBytes("abc", Mode.BYTE, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
assertEquals("011000010110001001100011", bits.toString());
// Anything can be encoded in QRCode.MODE_8BIT_BYTE.
- Encoder.appendBytes("\0", Mode.BYTE, bits);
+ Encoder.appendBytes("\0", Mode.BYTE, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
}
{
// Should use appendKanjiBytes.
// 0x93, 0x5f
BitVector bits = new BitVector();
- Encoder.appendBytes(shiftJISString(new byte[] {(byte)0x93,0x5f}), Mode.KANJI, bits);
+ Encoder.appendBytes(shiftJISString(new byte[] {(byte)0x93,0x5f}), Mode.KANJI, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
assertEquals("0110110011111", bits.toString());
}
}
{
// 0x61, 0x62, 0x63
BitVector bits = new BitVector();
- Encoder.append8BitBytes("abc", bits);
+ Encoder.append8BitBytes("abc", bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
assertEquals("01100001" + "01100010" + "01100011", bits.toString());
}
{
// Empty.
BitVector bits = new BitVector();
- Encoder.append8BitBytes("", bits);
+ Encoder.append8BitBytes("", bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
assertEquals("", bits.toString());
}
}