diff --git a/core/src/com/google/zxing/WriterException.java b/core/src/com/google/zxing/WriterException.java index 721c8f3a8..0c19af01d 100644 --- a/core/src/com/google/zxing/WriterException.java +++ b/core/src/com/google/zxing/WriterException.java @@ -24,6 +24,10 @@ package com.google.zxing; */ public final class WriterException extends Exception { + public WriterException() { + super(); + } + public WriterException(String message) { super(message); } diff --git a/core/src/com/google/zxing/qrcode/QRCodeWriter.java b/core/src/com/google/zxing/qrcode/QRCodeWriter.java index b7ff1f05a..15211979d 100644 --- a/core/src/com/google/zxing/qrcode/QRCodeWriter.java +++ b/core/src/com/google/zxing/qrcode/QRCodeWriter.java @@ -60,11 +60,8 @@ public final class QRCodeWriter implements Writer { // TODO: Check hints for error correction level instead of hardcoding int errorCorrectionLevel = QRCode.EC_LEVEL_L; QRCode code = new QRCode(); - if (Encoder.Encode(new ByteArray(contents), errorCorrectionLevel, code)) { - return renderResult(code, width, height); - } else { - throw new WriterException("Could not generate a QR Code"); - } + Encoder.Encode(new ByteArray(contents), errorCorrectionLevel, code); + return renderResult(code, width, height); } // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses diff --git a/core/src/com/google/zxing/qrcode/encoder/BitVector.java b/core/src/com/google/zxing/qrcode/encoder/BitVector.java index c24753186..e4938af95 100644 --- a/core/src/com/google/zxing/qrcode/encoder/BitVector.java +++ b/core/src/com/google/zxing/qrcode/encoder/BitVector.java @@ -39,8 +39,9 @@ public final class BitVector { // Return the bit value at "index". public int at(final int index) { - Debug.DCHECK_LE(0, index); - Debug.DCHECK_LT(index, sizeInBits); + if (index < 0 || index >= sizeInBits) { + throw new IllegalArgumentException("Bad index: " + index); + } final int value = array[index >> 3] & 0xff; return (value >> (7 - (index & 0x7))) & 1; } @@ -59,7 +60,9 @@ public final class BitVector { // Append one bit to the bit vector. public void AppendBit(final int bit) { - Debug.DCHECK(bit == 0 || bit == 1); + if (!(bit == 0 || bit == 1)) { + throw new IllegalArgumentException("Bad bit"); + } final int num_bits_in_last_byte = sizeInBits & 0x7; // We'll expand array if we don't have bits in the last byte. if (num_bits_in_last_byte == 0) { @@ -79,7 +82,9 @@ public final class BitVector { // - AppendBits(0x00, 4) adds 0000. // - AppendBits(0xff, 8) adds 11111111. public void AppendBits(final int value, final int num_bits) { - Debug.DCHECK(num_bits >= 0 && num_bits <= 32); + if (num_bits < 0 || num_bits > 32) { + throw new IllegalArgumentException("Num bits must be between 0 and 32"); + } int num_bits_left = num_bits; while (num_bits_left > 0) { // Optimization for byte-oriented appending. @@ -105,7 +110,9 @@ public final class BitVector { // Modify the bit vector by XOR'ing with "other" public void XOR(final BitVector other) { - Debug.DCHECK_EQ(sizeInBits, other.size()); + if (sizeInBits != other.size()) { + throw new IllegalArgumentException("BitVector sizes don't match"); + } int sizeInBytes = (sizeInBits + 7) >> 3; for (int i = 0; i < sizeInBytes; ++i) { // The last byte could be incomplete (i.e. not have 8 bits in @@ -123,7 +130,7 @@ public final class BitVector { } else if (at(i) == 1) { result.append("1"); } else { - Debug.DCHECK(false); + throw new IllegalArgumentException("Byte isn't 0 or 1"); } } return result.toString(); diff --git a/core/src/com/google/zxing/qrcode/encoder/Debug.java b/core/src/com/google/zxing/qrcode/encoder/Debug.java deleted file mode 100644 index 03462294a..000000000 --- a/core/src/com/google/zxing/qrcode/encoder/Debug.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.encoder; - -/** - * JAVAPORT: Equivalent methods to the C++ versions. It's debateable whether these should throw or - * assert. We can revisit that decision, or remove these throughout the code later. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public class Debug { - - public static void LOG_ERROR(String message) { - // Can't use IllegalStateException unfortunately in J2ME - // TODO do something else with this anyway - throw new RuntimeException(message); - } - - public static void LOG_INFO(String message) { - // Chris M -- throwing RuntimeException in an INFO function seems terribly - // strange and violates my assumptions about logging information. Even - // ERROR is borderline since it's effectively going to go unchecked by most - // callers. There has to be a more general way to do this. - // throw new RuntimeException(message); - } - - public static void DCHECK(boolean condition) { - if (!condition) { - throw new RuntimeException(); - } - } - - public static void DCHECK_LT(int a, int b) { - DCHECK(a < b); - } - - public static void DCHECK_LE(int a, int b) { - DCHECK(a <= b); - } - - public static void DCHECK_GT(int a, int b) { - DCHECK(a > b); - } - - public static void DCHECK_GE(int a, int b) { - DCHECK(a >= b); - } - - public static void DCHECK_EQ(int a, int b) { - DCHECK(a == b); - } - -} diff --git a/core/src/com/google/zxing/qrcode/encoder/Encoder.java b/core/src/com/google/zxing/qrcode/encoder/Encoder.java index a9149507c..29d8d4860 100644 --- a/core/src/com/google/zxing/qrcode/encoder/Encoder.java +++ b/core/src/com/google/zxing/qrcode/encoder/Encoder.java @@ -20,6 +20,7 @@ import com.google.zxing.common.ByteMatrix; import com.google.zxing.common.ByteArray; import com.google.zxing.common.reedsolomon.GF256; import com.google.zxing.common.reedsolomon.ReedSolomonEncoder; +import com.google.zxing.WriterException; import java.util.Vector; @@ -41,8 +42,8 @@ public final class Encoder { private static final class RSBlockInfo { - int num_bytes; - int block_info[][]; + final int num_bytes; + final int[][] block_info; public RSBlockInfo(int num_bytes, int[][] block_info) { this.num_bytes = num_bytes; @@ -99,8 +100,8 @@ public final class Encoder { private static final class BlockPair { - private ByteArray dataBytes; - private ByteArray errorCorrectionBytes; + private final ByteArray dataBytes; + private final ByteArray errorCorrectionBytes; public BlockPair(ByteArray data, ByteArray errorCorrection) { dataBytes = data; @@ -125,35 +126,25 @@ public final class Encoder { // // Note that there is no way to encode bytes in MODE_KANJI. We might want to add EncodeWithMode() // with which clients can specify the encoding mode. For now, we don't need the functionality. - public static boolean Encode(final ByteArray bytes, int ec_level, QRCode qr_code) { + public static void Encode(final ByteArray bytes, int ec_level, QRCode qr_code) throws WriterException { // Step 1: Choose the mode (encoding). final int mode = ChooseMode(bytes); // Step 2: Append "bytes" into "data_bits" in appropriate encoding. BitVector data_bits = new BitVector(); - if (!AppendBytes(bytes, mode, data_bits)) { - return false; - } + AppendBytes(bytes, mode, data_bits); // Step 3: Initialize QR code that can contain "data_bits". final int num_input_bytes = data_bits.num_bytes(); - if (!InitQRCode(num_input_bytes, ec_level, mode, qr_code)) { - return false; - } + InitQRCode(num_input_bytes, ec_level, mode, qr_code); // Step 4: Build another bit vector that contains header and data. BitVector header_and_data_bits = new BitVector(); - if (!AppendModeInfo(qr_code.mode(), header_and_data_bits)) { - return false; - } - if (!AppendLengthInfo(bytes.size(), qr_code.version(), qr_code.mode(), header_and_data_bits)) { - return false; - } + AppendModeInfo(qr_code.mode(), header_and_data_bits); + AppendLengthInfo(bytes.size(), qr_code.version(), qr_code.mode(), header_and_data_bits); header_and_data_bits.AppendBitVector(data_bits); // Step 5: Terminate the bits properly. - if (!TerminateBits(qr_code.num_data_bytes(), header_and_data_bits)) { - return false; - } + TerminateBits(qr_code.num_data_bytes(), header_and_data_bits); // Step 6: Interleave data bits with error correction code. BitVector final_bits = new BitVector(); @@ -164,10 +155,6 @@ public final class Encoder { ByteMatrix matrix = new ByteMatrix(qr_code.matrix_width(), qr_code.matrix_width()); qr_code.set_mask_pattern(ChooseMaskPattern(final_bits, qr_code.ec_level(), qr_code.version(), matrix)); - if (qr_code.mask_pattern() == -1) { - // There was an error. - return false; - } // Step 8. Build the matrix and set it to "qr_code". MatrixUtil.BuildMatrix(final_bits, qr_code.ec_level(), qr_code.version(), @@ -175,10 +162,8 @@ public final class Encoder { qr_code.set_matrix(matrix); // Step 9. Make sure we have a valid QR Code. if (!qr_code.IsValid()) { - Debug.LOG_ERROR("Invalid QR code: " + qr_code.toString()); - return false; + throw new WriterException("Invalid QR code: " + qr_code.toString()); } - return true; } // Return the code point of the table used in alphanumeric mode. Return -1 if there is no @@ -198,7 +183,7 @@ public final class Encoder { // interpreted as one character in Shift_JIS, but also two characters in ISO-8859-1. // // JAVAPORT: This MODE_KANJI limitation sounds like a problem for us. - public static int ChooseMode(final ByteArray bytes) { + public static int ChooseMode(final ByteArray bytes) throws WriterException { boolean has_numeric = false; boolean has_alphanumeric = false; boolean has_other = false; @@ -220,15 +205,16 @@ public final class Encoder { return QRCode.MODE_NUMERIC; } // "bytes" must be empty to reach here. - Debug.DCHECK(bytes.empty()); + if (!bytes.empty()) { + throw new WriterException("Bytes left over"); + } return QRCode.MODE_8BIT_BYTE; } private static int ChooseMaskPattern(final BitVector bits, int ec_level, int version, - ByteMatrix matrix) { + ByteMatrix matrix) throws WriterException { if (!QRCode.IsValidMatrixWidth(matrix.width())) { - Debug.LOG_ERROR("Invalid matrix width: " + matrix.width()); - return -1; + throw new WriterException("Invalid matrix width: " + matrix.width()); } int min_penalty = Integer.MAX_VALUE; // Lower penalty is better. @@ -236,12 +222,9 @@ public final class Encoder { // We try all mask patterns to choose the best one. for (int i = 0; i < QRCode.kNumMaskPatterns; ++i) { final int mask_pattern = i; - if (!MatrixUtil.BuildMatrix(bits, ec_level, version, - mask_pattern, matrix)) { - return -1; - } + MatrixUtil.BuildMatrix(bits, ec_level, version, mask_pattern, matrix); final int penalty = MaskUtil.CalculateMaskPenalty(matrix); - Debug.LOG_INFO("mask_pattern: " + mask_pattern + ", " + "penalty: " + penalty); + System.out.println("mask_pattern: " + mask_pattern + ", " + "penalty: " + penalty); if (penalty < min_penalty) { min_penalty = penalty; best_mask_pattern = mask_pattern; @@ -252,13 +235,12 @@ public final class Encoder { // Initialize "qr_code" according to "num_input_bytes", "ec_level", and "mode". On success, modify // "qr_code" and return true. On error, return false. - private static boolean InitQRCode(int num_input_bytes, int ec_level, int mode, QRCode qr_code) { + private static void InitQRCode(int num_input_bytes, int ec_level, int mode, QRCode qr_code) throws WriterException { qr_code.set_ec_level(ec_level); qr_code.set_mode(mode); if (!QRCode.IsValidECLevel(ec_level)) { - Debug.LOG_ERROR("Invalid EC level: " + ec_level); - return false; + throw new WriterException("Invalid EC level: " + ec_level); } // In the following comments, we use numbers of Version 7-H. @@ -285,19 +267,17 @@ public final class Encoder { qr_code.set_num_ec_bytes(num_bytes - num_data_bytes); // num_matrix_width = 21 + 6 * 4 = 45 qr_code.set_matrix_width(21 + i * 4); - return true; + return; } } - Debug.LOG_ERROR("Cannot find proper rs block info (input data too big?)"); - return false; + throw new WriterException("Cannot find proper rs block info (input data too big?)"); } // Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24). - static boolean TerminateBits(int num_data_bytes, BitVector bits) { + static void TerminateBits(int num_data_bytes, BitVector bits) throws WriterException { final int capacity = num_data_bytes * 8; if (bits.size() > capacity) { - Debug.LOG_ERROR("data bits cannot fit in the QR Code" + bits.size() + " > " + capacity); - return false; + 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. for (int i = 0; i < 4 && bits.size() < capacity; ++i) { @@ -312,7 +292,9 @@ public final class Encoder { } } // Should be 8-bit aligned here. - Debug.DCHECK_EQ(0, bits.size() % 8); + if (bits.size() % 8 != 0) { + throw new WriterException("Number of bits is not a multiple of 8"); + } // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24). final int num_padding_bytes = num_data_bytes - bits.num_bytes(); for (int i = 0; i < num_padding_bytes; ++i) { @@ -322,8 +304,9 @@ public final class Encoder { bits.AppendBits(0x11, 8); } } - Debug.DCHECK_EQ(bits.size(), capacity); // Should be same. - return bits.size() == capacity; + if (bits.size() != capacity) { + throw new WriterException("Bits size does not equal capacity"); + } } // Get number of data bytes and number of error correction bytes for block id "block_id". Store @@ -331,8 +314,10 @@ public final class Encoder { // JISX0510:2004 (p.30) static void GetNumDataBytesAndNumECBytesForBlockID(int num_total_bytes, int num_data_bytes, int num_rs_blocks, int block_id, int[] num_data_bytes_in_block, - int[] num_ec_bytes_in_block) { - Debug.DCHECK_LT(block_id, num_rs_blocks); + int[] num_ec_bytes_in_block) throws WriterException { + if (block_id >= num_rs_blocks) { + throw new WriterException("Block ID too large"); + } // num_rs_blocks_in_group2 = 196 % 5 = 1 final int num_rs_blocks_in_group2 = num_total_bytes % num_rs_blocks; // num_rs_blocks_in_group1 = 5 - 1 = 4 @@ -353,15 +338,21 @@ public final class Encoder { num_data_bytes_in_group2; // Sanity checks. // 26 = 26 - Debug.DCHECK_EQ(num_ec_bytes_in_group1, num_ec_bytes_in_group2); + if (num_ec_bytes_in_group1 != num_ec_bytes_in_group2) { + throw new WriterException("EC bytes mismatch"); + } // 5 = 4 + 1. - Debug.DCHECK_EQ(num_rs_blocks, num_rs_blocks_in_group1 + num_rs_blocks_in_group2); + if (num_rs_blocks != num_rs_blocks_in_group1 + num_rs_blocks_in_group2) { + throw new WriterException("RS blocks mismatch"); + } // 196 = (13 + 26) * 4 + (14 + 26) * 1 - Debug.DCHECK_EQ(num_total_bytes, + if (num_total_bytes != ((num_data_bytes_in_group1 + num_ec_bytes_in_group1) * num_rs_blocks_in_group1) + ((num_data_bytes_in_group2 + num_ec_bytes_in_group2) * - num_rs_blocks_in_group2)); + num_rs_blocks_in_group2)) { + throw new WriterException("Total bytes mismatch"); + } if (block_id < num_rs_blocks_in_group1) { num_data_bytes_in_block[0] = num_data_bytes_in_group1; @@ -375,11 +366,13 @@ public final class Encoder { // Interleave "bits" with corresponding error correction bytes. On success, store the result in // "result" and return true. On error, return false. The interleave rule is complicated. See 8.6 // of JISX0510:2004 (p.37) for details. - static boolean InterleaveWithECBytes(final BitVector bits, int num_total_bytes, - int num_data_bytes, int num_rs_blocks, BitVector result) { + static void InterleaveWithECBytes(final BitVector bits, int num_total_bytes, + int num_data_bytes, int num_rs_blocks, BitVector result) throws WriterException { // "bits" must have "num_data_bytes" bytes of data. - Debug.DCHECK(bits.num_bytes() == num_data_bytes); + if (bits.num_bytes() != num_data_bytes) { + throw new WriterException("Number of bits and data bytes does not match"); + } // Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll // store the divided data bytes blocks and error correction bytes blocks into "blocks". @@ -406,7 +399,9 @@ public final class Encoder { max_num_ec_bytes = Math.max(max_num_ec_bytes, ec_bytes.size()); data_bytes_offset += num_data_bytes_in_block[0]; } - Debug.DCHECK_EQ(num_data_bytes, data_bytes_offset); + if (num_data_bytes != data_bytes_offset) { + throw new WriterException("Data bytes does not match offset"); + } // First, place data blocks. for (int i = 0; i < max_num_data_bytes; ++i) { @@ -426,12 +421,10 @@ public final class Encoder { } } } - if (num_total_bytes == result.num_bytes()) { // Should be same. - return true; - } - Debug.LOG_ERROR("Interleaving error: " + num_total_bytes + " and " + result.num_bytes() + + if (num_total_bytes != result.num_bytes()) { // Should be same. + throw new WriterException("Interleaving error: " + num_total_bytes + " and " + result.num_bytes() + " differ."); - return false; + } } static ByteArray GenerateECBytes(ByteArray data_bytes, int num_ec_bytes_in_block) { @@ -451,67 +444,60 @@ public final class Encoder { // Append mode info. On success, store the result in "bits" and return true. On error, return // false. - static boolean AppendModeInfo(int mode, BitVector bits) { + static void AppendModeInfo(int mode, BitVector bits) throws WriterException { final int code = QRCode.GetModeCode(mode); - if (code == -1) { - Debug.LOG_ERROR("Invalid mode: " + mode); - return false; - } bits.AppendBits(code, 4); - return true; } // Append length info. On success, store the result in "bits" and return true. On error, return // false. - static boolean AppendLengthInfo(int num_bytes, int version, int mode, BitVector bits) { + static void AppendLengthInfo(int num_bytes, int version, int mode, BitVector bits) throws WriterException { int num_letters = num_bytes; // In Kanji mode, a letter is represented in two bytes. if (mode == QRCode.MODE_KANJI) { - Debug.DCHECK_EQ(0, num_letters % 2); + if (num_letters % 2 != 0) { + throw new WriterException("Number of letters must be even"); + } num_letters /= 2; } final int num_bits = QRCode.GetNumBitsForLength(version, mode); - if (num_bits == -1) { - Debug.LOG_ERROR("num_bits unset"); - return false; - } if (num_letters > ((1 << num_bits) - 1)) { - Debug.LOG_ERROR(num_letters + "is bigger than" + ((1 << num_bits) - 1)); - return false; + throw new WriterException(num_letters + "is bigger than" + ((1 << num_bits) - 1)); } bits.AppendBits(num_letters, num_bits); - return true; } // Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits" // and return true. On error, return false. - static boolean AppendBytes(final ByteArray bytes, int mode, BitVector bits) { + static void AppendBytes(final ByteArray bytes, int mode, BitVector bits) throws WriterException { switch (mode) { case QRCode.MODE_NUMERIC: - return AppendNumericBytes(bytes, bits); - case QRCode.MODE_ALPHANUMERIC: - return AppendAlphanumericBytes(bytes, bits); - case QRCode.MODE_8BIT_BYTE: - return Append8BitBytes(bytes, bits); - case QRCode.MODE_KANJI: - return AppendKanjiBytes(bytes, bits); - default: + AppendNumericBytes(bytes, bits); break; + case QRCode.MODE_ALPHANUMERIC: + AppendAlphanumericBytes(bytes, bits); + break; + case QRCode.MODE_8BIT_BYTE: + Append8BitBytes(bytes, bits); + break; + case QRCode.MODE_KANJI: + AppendKanjiBytes(bytes, bits); + break; + default: + throw new WriterException("Invalid mode: " + mode); } - Debug.LOG_ERROR("Invalid mode: " + mode); - return false; } // Append "bytes" to "bits" using QRCode.MODE_NUMERIC mode. On success, store the result in "bits" // and return true. On error, return false. - static boolean AppendNumericBytes(final ByteArray bytes, BitVector bits) { + static void AppendNumericBytes(final ByteArray bytes, BitVector bits) throws WriterException { // Validate all the bytes first. for (int i = 0; i < bytes.size(); ++i) { int oneByte = bytes.at(i); if (oneByte < '0' || oneByte > '9') { - return false; + throw new WriterException("Non-digit found"); } } for (int i = 0; i < bytes.size();) { @@ -533,21 +519,20 @@ public final class Encoder { ++i; } } - return true; } // Append "bytes" to "bits" using QRCode.MODE_ALPHANUMERIC mode. On success, store the result in // "bits" and return true. On error, return false. - static boolean AppendAlphanumericBytes(final ByteArray bytes, BitVector bits) { + static void AppendAlphanumericBytes(final ByteArray bytes, BitVector bits) throws WriterException { for (int i = 0; i < bytes.size();) { final int code1 = GetAlphanumericCode(bytes.at(i)); if (code1 == -1) { - return false; + throw new WriterException(); } if (i + 1 < bytes.size()) { final int code2 = GetAlphanumericCode(bytes.at(i + 1)); if (code2 == -1) { - return false; + throw new WriterException(); } // Encode two alphanumeric letters in 11 bits. bits.AppendBits(code1 * 45 + code2, 11); @@ -558,29 +543,27 @@ public final class Encoder { ++i; } } - return true; } // Append "bytes" to "bits" using QRCode.MODE_8BIT_BYTE mode. On success, store the result in // "bits" and return true. On error, return false. - static boolean Append8BitBytes(final ByteArray bytes, BitVector bits) { + static void Append8BitBytes(final ByteArray bytes, BitVector bits) { for (int i = 0; i < bytes.size(); ++i) { bits.AppendBits(bytes.at(i), 8); } - return true; } // Append "bytes" to "bits" using QRCode.MODE_KANJI mode. On success, store the result in "bits" // and return true. On error, return false. See 8.4.5 of JISX0510:2004 (p.21) for how to encode // Kanji bytes. - static boolean AppendKanjiBytes(final ByteArray bytes, BitVector bits) { + static void AppendKanjiBytes(final ByteArray bytes, BitVector bits) throws WriterException { if (bytes.size() % 2 != 0) { - // JAVAPORT: Our log implementation throws, which causes the unit test to fail. - //Debug.LOG_ERROR("Invalid byte sequence: " + bytes); - return false; + throw new WriterException("Number of bytes must be even"); } for (int i = 0; i < bytes.size(); i += 2) { - Debug.DCHECK(IsValidKanji(bytes.at(i), bytes.at(i + 1))); + if (!IsValidKanji(bytes.at(i), bytes.at(i + 1))) { + throw new WriterException("Invalid Kanji at " + i); + } final int code = (bytes.at(i) << 8) | bytes.at(i + 1); int subtracted = -1; if (code >= 0x8140 && code <= 0x9ffc) { @@ -589,13 +572,11 @@ public final class Encoder { subtracted = code - 0xc140; } if (subtracted == -1) { - Debug.LOG_ERROR("Invalid byte sequence: " + bytes); - return false; + throw new WriterException("Invalid byte sequence: " + bytes); } final int encoded = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff); bits.AppendBits(encoded, 13); } - return true; } // Check if "byte1" and "byte2" can compose a valid Kanji letter (2-byte Shift_JIS letter). The diff --git a/core/src/com/google/zxing/qrcode/encoder/MaskUtil.java b/core/src/com/google/zxing/qrcode/encoder/MaskUtil.java index 19730afa7..8c0db187b 100644 --- a/core/src/com/google/zxing/qrcode/encoder/MaskUtil.java +++ b/core/src/com/google/zxing/qrcode/encoder/MaskUtil.java @@ -40,7 +40,7 @@ public final class MaskUtil { public static int ApplyMaskPenaltyRule1(final ByteMatrix matrix) { final int penalty = (ApplyMaskPenaltyRule1Internal(matrix, true) + ApplyMaskPenaltyRule1Internal(matrix, false)); - Debug.LOG_INFO("\tApplyMaskPenaltyRule1: " + penalty); + System.out.println("\tApplyMaskPenaltyRule1: " + penalty); return penalty; } @@ -59,7 +59,7 @@ public final class MaskUtil { } } } - Debug.LOG_INFO("\tApplyMaskPenaltyRule2: " + penalty); + System.out.println("\tApplyMaskPenaltyRule2: " + penalty); return penalty; } @@ -116,7 +116,7 @@ public final class MaskUtil { } } } - Debug.LOG_INFO("\tApplyMaskPenaltyRule3: " + penalty); + System.out.println("\tApplyMaskPenaltyRule3: " + penalty); return penalty; } @@ -144,14 +144,16 @@ public final class MaskUtil { final int num_total_cells = matrix.height() * matrix.width(); double dark_ratio = (double) num_dark_cells / num_total_cells; final int penalty = Math.abs((int) (dark_ratio * 100 - 50)) / 5 * 10; - Debug.LOG_INFO("\tApplyMaskPenaltyRule4: " + penalty); + System.out.println("\tApplyMaskPenaltyRule4: " + penalty); return penalty; } // Return the mask bit for "mask_pattern" at "x" and "y". See 8.8 of JISX0510:2004 for mask // pattern conditions. public static int GetDataMaskBit(final int mask_pattern, final int x, final int y) { - Debug.DCHECK(QRCode.IsValidMaskPattern(mask_pattern)); + if (!QRCode.IsValidMaskPattern(mask_pattern)) { + throw new IllegalArgumentException("Invalid mask pattern"); + } switch (mask_pattern) { case 0: return ((y + x) % 2 == 0) ? 1 : 0; @@ -169,11 +171,8 @@ public final class MaskUtil { return ((((y * x) % 2) + ((y * x) % 3)) % 2 == 0) ? 1 : 0; case 7: return ((((y * x) % 3) + ((y + x) % 2)) % 2 == 0) ? 1 : 0; - default: - ; } - Debug.LOG_ERROR("invalid mask pattern: " + mask_pattern); - return -1; + throw new IllegalArgumentException("invalid mask pattern: " + mask_pattern); } // Helper function for ApplyMaskPenaltyRule1. We need this for doing this calculation in both diff --git a/core/src/com/google/zxing/qrcode/encoder/MatrixUtil.java b/core/src/com/google/zxing/qrcode/encoder/MatrixUtil.java index c3c058210..a54ecd05d 100644 --- a/core/src/com/google/zxing/qrcode/encoder/MatrixUtil.java +++ b/core/src/com/google/zxing/qrcode/encoder/MatrixUtil.java @@ -17,6 +17,7 @@ package com.google.zxing.qrcode.encoder; import com.google.zxing.common.ByteMatrix; +import com.google.zxing.WriterException; /** * @author satorux@google.com (Satoru Takabayashi) - creator @@ -95,7 +96,7 @@ public final class MatrixUtil { }; // Type info cells at the left top corner. - private static int kTypeInfoCoordinates[][] = { + private static final int[][] kTypeInfoCoordinates = { {8, 0}, {8, 1}, {8, 2}, @@ -130,22 +131,16 @@ public final class MatrixUtil { // Build 2D matrix of QR Code from "data_bits" with "ec_level", "version" and "mask_pattern". On // success, store the result in "matrix" and return true. On error, return false. - public static boolean BuildMatrix(final BitVector data_bits, int ec_level, int version, - int mask_pattern, ByteMatrix matrix) { + public static void BuildMatrix(final BitVector data_bits, int ec_level, int version, + int mask_pattern, ByteMatrix matrix) throws WriterException { MatrixUtil.ClearMatrix(matrix); - if (!EmbedBasicPatterns(version, matrix)) { - return false; - } + EmbedBasicPatterns(version, matrix); // Type information appear with any version. - if (!EmbedTypeInfo(ec_level, mask_pattern, matrix)) { - return false; - } + EmbedTypeInfo(ec_level, mask_pattern, matrix); // Version info appear if version >= 7. - if (!MaybeEmbedVersionInfo(version, matrix)) { - return false; - } + MaybeEmbedVersionInfo(version, matrix); // Data should be embedded at end. - return EmbedDataBits(data_bits, mask_pattern, matrix); + EmbedDataBits(data_bits, mask_pattern, matrix); } // Embed basic patterns. On success, modify the matrix and return true. On error, return false. @@ -154,7 +149,7 @@ public final class MatrixUtil { // - Timing patterns // - Dark dot at the left bottom corner // - Position adjustment patterns, if need be - public static boolean EmbedBasicPatterns(int version, ByteMatrix matrix) { + public static void EmbedBasicPatterns(int version, ByteMatrix matrix) throws WriterException { // Let's get started with embedding big squares at corners. EmbedPositionDetectionPatternsAndSeparators(matrix); // Then, embed the dark dot at the left bottom corner. @@ -164,16 +159,12 @@ public final class MatrixUtil { MaybeEmbedPositionAdjustmentPatterns(version, matrix); // Timing patterns should be embedded after position adj. patterns. EmbedTimingPatterns(matrix); - return true; } - // Embed type information. On success, modify the matrix and return true. On error, return false. - public static boolean EmbedTypeInfo(int ec_level, int mask_pattern, ByteMatrix matrix) { + // Embed type information. On success, modify the matrix. + public static void EmbedTypeInfo(int ec_level, int mask_pattern, ByteMatrix matrix) throws WriterException { BitVector type_info_bits = new BitVector(); - if (!MakeTypeInfoBits(ec_level, mask_pattern, type_info_bits)) { - return false; - } - Debug.DCHECK_EQ(15, type_info_bits.size()); + MakeTypeInfoBits(ec_level, mask_pattern, type_info_bits); for (int i = 0; i < type_info_bits.size(); ++i) { // Place bits in LSB to MSB order. LSB (least significant bit) is the last value in @@ -197,22 +188,18 @@ public final class MatrixUtil { matrix.set(y2, x2, bit); } } - return true; } // Embed version information if need be. On success, modify the matrix and return true. On error, // return false. See 8.10 of JISX0510:2004 (p.47) for how to embed version information. Return // true on success, otherwise return false. - public static boolean MaybeEmbedVersionInfo(int version, ByteMatrix matrix) { + public static void MaybeEmbedVersionInfo(int version, ByteMatrix matrix) throws WriterException { if (version < 7) { // Version info is necessary if version >= 7. - return true; // Don't need version info. + return; // Don't need version info. } BitVector version_info_bits = new BitVector(); - if (!MakeVersionInfoBits(version, version_info_bits)) { - return false; - } + MakeVersionInfoBits(version, version_info_bits); - Debug.DCHECK_EQ(18, version_info_bits.size()); int bit_index = 6 * 3 - 1; // It will decrease from 17 to 0. for (int i = 0; i < 6; ++i) { for (int j = 0; j < 3; ++j) { @@ -225,13 +212,13 @@ public final class MatrixUtil { matrix.set(i, matrix.height() - 11 + j, bit); } } - return true; } // Embed "data_bits" using "mask_pattern". On success, modify the matrix and return true. On // error, return false. For debugging purposes, it skips masking process if "mask_pattern" is -1. // See 8.7 of JISX0510:2004 (p.38) for how to embed data bits. - public static boolean EmbedDataBits(final BitVector data_bits, int mask_pattern, ByteMatrix matrix) { + public static void EmbedDataBits(final BitVector data_bits, int mask_pattern, ByteMatrix matrix) + throws WriterException { int bit_index = 0; int direction = -1; // Start from the right bottom cell. @@ -249,7 +236,7 @@ public final class MatrixUtil { if (!IsEmpty(matrix.get(y, xx))) { continue; } - int bit = -1; + int bit; if (bit_index < data_bits.size()) { bit = data_bits.at(bit_index); ++bit_index; @@ -258,12 +245,10 @@ public final class MatrixUtil { // in 8.4.9 of JISX0510:2004 (p. 24). bit = 0; } - Debug.DCHECK(IsValidValue(bit)); // Skip masking if mask_pattern is -1. if (mask_pattern != -1) { final int mask = MaskUtil.GetDataMaskBit(mask_pattern, xx, y); - Debug.DCHECK(mask == 0 || mask == 1); bit ^= mask; } matrix.set(y, xx, bit); @@ -275,12 +260,9 @@ public final class MatrixUtil { x -= 2; // Move to the left. } // All bits should be consumed. - if (bit_index < data_bits.size()) { - Debug.LOG_ERROR("Not all bits consumed: " + bit_index + "/" + data_bits.size()); - return false; + if (bit_index != data_bits.size()) { + throw new WriterException("Not all bits consumed: " + bit_index + "/" + data_bits.size()); } - Debug.DCHECK_EQ(bit_index, data_bits.size()); - return true; } // Return the position of the most significant bit set (to one) in the "value". The most @@ -338,13 +320,10 @@ public final class MatrixUtil { // Make bit vector of type information. On success, store the result in "bits" and return true. // On error, return false. Encode error correction level and mask pattern. See 8.9 of // JISX0510:2004 (p.45) for details. - public static boolean MakeTypeInfoBits(int ec_level, final int mask_pattern, BitVector bits) { + public static void MakeTypeInfoBits(int ec_level, final int mask_pattern, BitVector bits) throws WriterException { final int ec_code = QRCode.GetECLevelCode(ec_level); - if (ec_code == -1) { - return false; - } if (!QRCode.IsValidMaskPattern(mask_pattern)) { - return false; + throw new WriterException("Invalid mask pattern"); } final int type_info = (ec_code << 3) | mask_pattern; bits.AppendBits(type_info, 5); @@ -357,24 +336,20 @@ public final class MatrixUtil { bits.XOR(mask_bits); if (bits.size() != 15) { // Just in case. - Debug.LOG_ERROR("should not happen but we got: " + bits.size()); - return false; + throw new WriterException("should not happen but we got: " + bits.size()); } - return true; } // Make bit vector of version information. On success, store the result in "bits" and return true. // On error, return false. See 8.10 of JISX0510:2004 (p.45) for details. - public static boolean MakeVersionInfoBits(int version, BitVector bits) { + public static void MakeVersionInfoBits(int version, BitVector bits) throws WriterException { bits.AppendBits(version, 6); final int bch_code = MatrixUtil.CalculateBCHCode(version, kVersionInfoPoly); bits.AppendBits(bch_code, 12); if (bits.size() != 18) { // Just in case. - Debug.LOG_ERROR("should not happen but we got: " + bits.size()); - return false; + throw new WriterException("should not happen but we got: " + bits.size()); } - return true; } // Check if "value" is empty. @@ -389,18 +364,22 @@ public final class MatrixUtil { value == 1); // Dark (black). } - private static void EmbedTimingPatterns(ByteMatrix matrix) { + private static void EmbedTimingPatterns(ByteMatrix matrix) throws WriterException { // -8 is for skipping position detection patterns (size 7), and two horizontal/vertical // separation patterns (size 1). Thus, 8 = 7 + 1. for (int i = 8; i < matrix.width() - 8; ++i) { final int bit = (i + 1) % 2; // Horizontal line. - Debug.DCHECK(IsValidValue(matrix.get(6, i))); + if (!IsValidValue(matrix.get(6, i))) { + throw new WriterException(); + } if (IsEmpty(matrix.get(6, i))) { matrix.set(6, i, bit); } // Vertical line. - Debug.DCHECK(IsValidValue(matrix.get(i, 6))); + if (!IsValidValue(matrix.get(i, 6))) { + throw new WriterException(); + } if (IsEmpty(matrix.get(i, 6))) { matrix.set(i, 6, bit); } @@ -408,29 +387,37 @@ public final class MatrixUtil { } // Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46) - private static void EmbedDarkDotAtLeftBottomCorner(ByteMatrix matrix) { - Debug.DCHECK(matrix.get(matrix.height() - 8, 8) != 0); + private static void EmbedDarkDotAtLeftBottomCorner(ByteMatrix matrix) throws WriterException { + if (matrix.get(matrix.height() - 8, 8) == 0) { + throw new WriterException(); + } matrix.set(matrix.height() - 8, 8, 1); } private static void EmbedHorizontalSeparationPattern(final int x_start, final int y_start, - ByteMatrix matrix) { + ByteMatrix matrix) throws WriterException { // We know the width and height. - Debug.DCHECK_EQ(8, kHorizontalSeparationPattern[0].length); - Debug.DCHECK_EQ(1, kHorizontalSeparationPattern.length); + if (kHorizontalSeparationPattern[0].length != 8 || kHorizontalSeparationPattern.length != 1) { + throw new WriterException("Bad horizontal separation pattern"); + } for (int x = 0; x < 8; ++x) { - Debug.DCHECK(IsEmpty(matrix.get(y_start, x_start + x))); + if (!IsEmpty(matrix.get(y_start, x_start + x))) { + throw new WriterException(); + } matrix.set(y_start, x_start + x, kHorizontalSeparationPattern[0][x]); } } private static void EmbedVerticalSeparationPattern(final int x_start, final int y_start, - ByteMatrix matrix) { + ByteMatrix matrix) throws WriterException { // We know the width and height. - Debug.DCHECK_EQ(1, kVerticalSeparationPattern[0].length); - Debug.DCHECK_EQ(7, kVerticalSeparationPattern.length); + if (kVerticalSeparationPattern[0].length != 1 || kVerticalSeparationPattern.length != 7) { + throw new WriterException("Bad vertical separation pattern"); + } for (int y = 0; y < 7; ++y) { - Debug.DCHECK(IsEmpty(matrix.get(y_start + y, x_start))); + if (!IsEmpty(matrix.get(y_start + y, x_start))) { + throw new WriterException(); + } matrix.set(y_start + y, x_start, kVerticalSeparationPattern[y][0]); } } @@ -439,33 +426,39 @@ public final class MatrixUtil { // almost identical, since we cannot write a function that takes 2D arrays in different sizes in // C/C++. We should live with the fact. private static void EmbedPositionAdjustmentPattern(final int x_start, final int y_start, - ByteMatrix matrix) { + ByteMatrix matrix) throws WriterException { // We know the width and height. - Debug.DCHECK_EQ(5, kPositionAdjustmentPattern[0].length); - Debug.DCHECK_EQ(5, kPositionAdjustmentPattern.length); + if (kPositionAdjustmentPattern[0].length != 5 || kPositionAdjustmentPattern.length != 5) { + throw new WriterException("Bad position adjustment"); + } for (int y = 0; y < 5; ++y) { for (int x = 0; x < 5; ++x) { - Debug.DCHECK(IsEmpty(matrix.get(y_start + y, x_start + x))); + if (!IsEmpty(matrix.get(y_start + y, x_start + x))) { + throw new WriterException(); + } matrix.set(y_start + y, x_start + x, kPositionAdjustmentPattern[y][x]); } } } private static void EmbedPositionDetectionPattern(final int x_start, final int y_start, - ByteMatrix matrix) { + ByteMatrix matrix) throws WriterException { // We know the width and height. - Debug.DCHECK_EQ(7, kPositionDetectionPattern[0].length); - Debug.DCHECK_EQ(7, kPositionDetectionPattern.length); + if (kPositionDetectionPattern[0].length != 7 || kPositionDetectionPattern.length != 7) { + throw new WriterException("Bad position detection pattern"); + } for (int y = 0; y < 7; ++y) { for (int x = 0; x < 7; ++x) { - Debug.DCHECK(IsEmpty(matrix.get(y_start + y, x_start + x))); + if (!IsEmpty(matrix.get(y_start + y, x_start + x))) { + throw new WriterException(); + } matrix.set(y_start + y, x_start + x, kPositionDetectionPattern[y][x]); } } } // Embed position detection patterns and surrounding vertical/horizontal separators. - private static void EmbedPositionDetectionPatternsAndSeparators(ByteMatrix matrix) { + private static void EmbedPositionDetectionPatternsAndSeparators(ByteMatrix matrix) throws WriterException { // Embed three big squares at corners. final int pdp_width = kPositionDetectionPattern[0].length; // Left top corner. @@ -497,7 +490,7 @@ public final class MatrixUtil { } // Embed position adjustment patterns if need be. - private static void MaybeEmbedPositionAdjustmentPatterns(final int version, ByteMatrix matrix) { + private static void MaybeEmbedPositionAdjustmentPatterns(final int version, ByteMatrix matrix) throws WriterException { if (version < 2) { // The patterns appear if version >= 2 return; } diff --git a/core/src/com/google/zxing/qrcode/encoder/QRCode.java b/core/src/com/google/zxing/qrcode/encoder/QRCode.java index c75a4265f..41410d522 100644 --- a/core/src/com/google/zxing/qrcode/encoder/QRCode.java +++ b/core/src/com/google/zxing/qrcode/encoder/QRCode.java @@ -17,6 +17,7 @@ package com.google.zxing.qrcode.encoder; import com.google.zxing.common.ByteMatrix; +import com.google.zxing.WriterException; /** * @author satorux@google.com (Satoru Takabayashi) - creator @@ -25,11 +26,11 @@ import com.google.zxing.common.ByteMatrix; public final class QRCode { // Magic numbers. - public static final int kMinVersion = 1; - public static final int kMaxVersion = 40; + private static final int kMinVersion = 1; + private static final int kMaxVersion = 40; // For matrix width, see 7.3.1 of JISX0510:2004 (p.5). - public static final int kMinMatrixWidth = 21; // Version 1 - public static final int kMaxMatrixWidth = 177; // Version 40 (21 + 4 * (40 -1)). + private static final int kMinMatrixWidth = 21; // Version 1 + private static final int kMaxMatrixWidth = 177; // Version 40 (21 + 4 * (40 -1)). public static final int kNumMaskPatterns = 8; // See table 3 of JISX0510:2004 (p.16) @@ -128,7 +129,10 @@ public final class QRCode { public int at(int x, int y) { // The value must be zero or one. int value = matrix_.get(y, x); - Debug.DCHECK(value == 0 || value == 1); + if (!(value == 0 || value == 1)) { + // this is really like an assert... not sure what better exception to use? + throw new RuntimeException("Bad value"); + } return value; } @@ -300,7 +304,7 @@ public final class QRCode { // Return the code of error correction level. On error, return -1. The codes of error correction // levels are defined in the table 22 of JISX0510:2004 (p.45). - public static int GetECLevelCode(final int ec_level) { + public static int GetECLevelCode(final int ec_level) throws WriterException { switch (ec_level) { case QRCode.EC_LEVEL_L: return 1; @@ -311,14 +315,13 @@ public final class QRCode { case QRCode.EC_LEVEL_H: return 2; default: - break; + throw new WriterException("Unknown EC level"); } - return -1; // Unknown error correction level. } // Return the code of mode. On error, return -1. The codes of modes are defined in the table 2 of // JISX0510:2004 (p.16). - public static int GetModeCode(final int mode) { + public static int GetModeCode(final int mode) throws WriterException { switch (mode) { case QRCode.MODE_NUMERIC: return 1; @@ -329,21 +332,18 @@ public final class QRCode { case QRCode.MODE_KANJI: return 8; default: - break; + throw new WriterException("Unknown mode: " + mode); } - return -1; // Unknown mode. } // Return the number of bits needed for representing the length info of QR Code with "version" and // "mode". On error, return -1. - public static int GetNumBitsForLength(int version, int mode) { + static int GetNumBitsForLength(int version, int mode) { if (!IsValidVersion(version)) { - Debug.LOG_ERROR("Invalid version: " + version); - return -1; + throw new IllegalArgumentException("Invalid version: " + version); } if (!IsValidMode(mode)) { - Debug.LOG_ERROR("Invalid mode: " + mode); - return -1; + throw new IllegalArgumentException("Invalid mode: " + mode); } if (version >= 1 && version <= 9) { return kNumBitsTable[0][mode]; @@ -351,10 +351,8 @@ public final class QRCode { return kNumBitsTable[1][mode]; } else if (version >= 27 && version <= 40) { return kNumBitsTable[2][mode]; - } else { - Debug.LOG_ERROR("Should not reach"); } - return -1; + throw new IllegalArgumentException("Bad version: " + version); } // Return true if the all values in the matrix are binary numbers. Otherwise, return false. diff --git a/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java b/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java index 7a11e4b83..9a13c98c1 100644 --- a/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java +++ b/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java @@ -17,6 +17,7 @@ package com.google.zxing.qrcode.encoder; import com.google.zxing.common.ByteArray; +import com.google.zxing.WriterException; import junit.framework.TestCase; /** @@ -25,7 +26,7 @@ import junit.framework.TestCase; */ public final class EncoderTestCase extends TestCase { - public void testGetAlphanumericCode() { + public void testGetAlphanumericCode() throws WriterException { // The first ten code points are numbers. for (int i = 0; i < 10; ++i) { assertEquals(i, Encoder.GetAlphanumericCode('0' + i)); @@ -53,7 +54,7 @@ public final class EncoderTestCase extends TestCase { assertEquals(-1, Encoder.GetAlphanumericCode('\0')); } - public void testChooseMode() { + public void testChooseMode() throws WriterException { // Numeric mode. assertEquals(QRCode.MODE_NUMERIC, Encoder.ChooseMode(new ByteArray("0"))); assertEquals(QRCode.MODE_NUMERIC, Encoder.ChooseMode(new ByteArray("0123456789"))); @@ -82,9 +83,9 @@ public final class EncoderTestCase extends TestCase { assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.ChooseMode(new ByteArray(dat3))); } - public void testEncode() { + public void testEncode() throws WriterException { QRCode qr_code = new QRCode(); - assertTrue(Encoder.Encode(new ByteArray("ABCDEF"), QRCode.EC_LEVEL_H, qr_code)); + Encoder.Encode(new ByteArray("ABCDEF"), QRCode.EC_LEVEL_H, qr_code); // The following is a valid QR Code that can be read by cell phones. String expected = "<<\n" + @@ -123,85 +124,99 @@ public final class EncoderTestCase extends TestCase { assertEquals(expected, qr_code.toString()); } - public void testAppendModeInfo() { + public void testAppendModeInfo() throws WriterException { BitVector bits = new BitVector(); - assertTrue(Encoder.AppendModeInfo(QRCode.MODE_NUMERIC, bits)); + Encoder.AppendModeInfo(QRCode.MODE_NUMERIC, bits); assertEquals("0001", bits.toString()); } - public void testAppendLengthInfo() { + public void testAppendLengthInfo() throws WriterException { { BitVector bits = new BitVector(); - assertTrue(Encoder.AppendLengthInfo(1, // 1 letter (1/1). + Encoder.AppendLengthInfo(1, // 1 letter (1/1). 1, // version 1. QRCode.MODE_NUMERIC, - bits)); + bits); assertEquals("0000000001", bits.toString()); // 10 bits. } { BitVector bits = new BitVector(); - assertTrue(Encoder.AppendLengthInfo(2, // 2 letters (2/1). + Encoder.AppendLengthInfo(2, // 2 letters (2/1). 10, // version 10. QRCode.MODE_ALPHANUMERIC, - bits)); + bits); assertEquals("00000000010", bits.toString()); // 11 bits. } { BitVector bits = new BitVector(); - assertTrue(Encoder.AppendLengthInfo(255, // 255 letter (255/1). + Encoder.AppendLengthInfo(255, // 255 letter (255/1). 27, // version 27. QRCode.MODE_8BIT_BYTE, - bits)); + bits); assertEquals("0000000011111111", bits.toString()); // 16 bits. } { BitVector bits = new BitVector(); - assertTrue(Encoder.AppendLengthInfo(1024, // 512 letters (1024/2). + Encoder.AppendLengthInfo(1024, // 512 letters (1024/2). 40, // version 40. QRCode.MODE_KANJI, - bits)); + bits); assertEquals("001000000000", bits.toString()); // 12 bits. } } - public void testAppendBytes() { + public void testAppendBytes() throws WriterException { { // Should use AppendNumericBytes. // 1 = 01 = 0001 in 4 bits. BitVector bits = new BitVector(); - assertTrue(Encoder.AppendBytes(new ByteArray("1"), QRCode.MODE_NUMERIC, bits)); + Encoder.AppendBytes(new ByteArray("1"), QRCode.MODE_NUMERIC, bits); assertEquals("0001" , bits.toString()); // 'A' cannot be encoded in MODE_NUMERIC. - assertFalse(Encoder.AppendBytes(new ByteArray("A"), QRCode.MODE_NUMERIC, bits)); + try { + Encoder.AppendBytes(new ByteArray("A"), QRCode.MODE_NUMERIC, bits); + fail("Should have thrown exception"); + } catch (WriterException we) { + // good + } } { // Should use AppendAlphanumericBytes. // A = 10 = 0xa = 001010 in 6 bits BitVector bits = new BitVector(); - assertTrue(Encoder.AppendBytes(new ByteArray("A"), QRCode.MODE_ALPHANUMERIC, bits)); + Encoder.AppendBytes(new ByteArray("A"), QRCode.MODE_ALPHANUMERIC, bits); assertEquals("001010" , bits.toString()); // Lower letters such as 'a' cannot be encoded in MODE_ALPHANUMERIC. - assertFalse(Encoder.AppendBytes(new ByteArray("a"), QRCode.MODE_ALPHANUMERIC, bits)); + try { + Encoder.AppendBytes(new ByteArray("a"), QRCode.MODE_ALPHANUMERIC, bits); + } catch (WriterException we) { + // good + } } { // Should use Append8BitBytes. // 0x61, 0x62, 0x63 BitVector bits = new BitVector(); - assertTrue(Encoder.AppendBytes(new ByteArray("abc"), QRCode.MODE_8BIT_BYTE, bits)); + Encoder.AppendBytes(new ByteArray("abc"), QRCode.MODE_8BIT_BYTE, bits); assertEquals("01100001" + "01100010" + "01100011", bits.toString()); // Anything can be encoded in QRCode.MODE_8BIT_BYTE. byte[] bytes = {0x00}; - assertTrue(Encoder.AppendBytes(new ByteArray(bytes), QRCode.MODE_8BIT_BYTE, bits)); + Encoder.AppendBytes(new ByteArray(bytes), QRCode.MODE_8BIT_BYTE, bits); } { // Should use AppendKanjiBytes. // 0x93, 0x5f BitVector bits = new BitVector(); byte[] bytes = {(byte)0x93,0x5f}; - assertTrue(Encoder.AppendBytes(new ByteArray(bytes), QRCode.MODE_KANJI, bits)); + Encoder.AppendBytes(new ByteArray(bytes), QRCode.MODE_KANJI, bits); assertEquals("0110110011111", bits.toString()); // ASCII characters can not be encoded in QRCode.MODE_KANJI. - assertFalse(Encoder.AppendBytes(new ByteArray("a"), QRCode.MODE_KANJI, bits)); + + try { + Encoder.AppendBytes(new ByteArray("a"), QRCode.MODE_KANJI, bits); + } catch (WriterException we) { + // good + } } } @@ -209,49 +224,49 @@ public final class EncoderTestCase extends TestCase { // TODO: should be implemented. } - public void testTerminateBits() { + public void testTerminateBits() throws WriterException { { BitVector v = new BitVector(); - assertTrue(Encoder.TerminateBits(0, v)); + Encoder.TerminateBits(0, v); assertEquals("", v.toString()); } { BitVector v = new BitVector(); - assertTrue(Encoder.TerminateBits(1, v)); + Encoder.TerminateBits(1, v); assertEquals("00000000", v.toString()); } { BitVector v = new BitVector(); v.AppendBits(0, 3); // Append 000 - assertTrue(Encoder.TerminateBits(1, v)); + Encoder.TerminateBits(1, v); assertEquals("00000000", v.toString()); } { BitVector v = new BitVector(); v.AppendBits(0, 5); // Append 00000 - assertTrue(Encoder.TerminateBits(1, v)); + Encoder.TerminateBits(1, v); assertEquals("00000000", v.toString()); } { BitVector v = new BitVector(); v.AppendBits(0, 8); // Append 00000000 - assertTrue(Encoder.TerminateBits(1, v)); + Encoder.TerminateBits(1, v); assertEquals("00000000", v.toString()); } { BitVector v = new BitVector(); - assertTrue(Encoder.TerminateBits(2, v)); + Encoder.TerminateBits(2, v); assertEquals("0000000011101100", v.toString()); } { BitVector v = new BitVector(); v.AppendBits(0, 1); // Append 0 - assertTrue(Encoder.TerminateBits(3, v)); + Encoder.TerminateBits(3, v); assertEquals("000000001110110000010001", v.toString()); } } - public void testGetNumDataBytesAndNumECBytesForBlockID() { + public void testGetNumDataBytesAndNumECBytesForBlockID() throws WriterException { int[] num_data_bytes = new int[1]; int[] num_ec_bytes = new int[1]; // Version 1-H. @@ -287,7 +302,7 @@ public final class EncoderTestCase extends TestCase { assertEquals(30, num_ec_bytes[0]); } - public void testInterleaveWithECBytes() { + public void testInterleaveWithECBytes() throws WriterException { { final byte[] data_bytes = {32, 65, (byte)205, 69, 41, (byte)220, 46, (byte)128, (byte)236}; BitVector in = new BitVector(); @@ -295,7 +310,7 @@ public final class EncoderTestCase extends TestCase { in.AppendBits(data_byte, 8); } BitVector out = new BitVector(); - assertTrue(Encoder.InterleaveWithECBytes(in, 26, 9, 1, out)); + Encoder.InterleaveWithECBytes(in, 26, 9, 1, out); final byte[] expected = { // Data bytes. 32, 65, (byte)205, 69, 41, (byte)220, 46, (byte)128, (byte)236, @@ -325,7 +340,7 @@ public final class EncoderTestCase extends TestCase { in.AppendBits(data_byte, 8); } BitVector out = new BitVector(); - assertTrue(Encoder.InterleaveWithECBytes(in, 134, 62, 4, out)); + Encoder.InterleaveWithECBytes(in, 134, 62, 4, out); final byte[] expected = { // Data bytes. 67, (byte)230, 54, 55, 70, (byte)247, 70, 71, 22, 7, 86, 87, 38, 23, 102, 103, 54, 39, @@ -351,100 +366,108 @@ public final class EncoderTestCase extends TestCase { } } - public void testAppendNumericBytes() { + public void testAppendNumericBytes() throws WriterException { { // 1 = 01 = 0001 in 4 bits. BitVector bits = new BitVector(); - assertTrue(Encoder.AppendNumericBytes(new ByteArray("1"), bits)); + Encoder.AppendNumericBytes(new ByteArray("1"), bits); assertEquals("0001" , bits.toString()); } { // 12 = 0xc = 0001100 in 7 bits. BitVector bits = new BitVector(); - assertTrue(Encoder.AppendNumericBytes(new ByteArray("12"), bits)); + Encoder.AppendNumericBytes(new ByteArray("12"), bits); assertEquals("0001100" , bits.toString()); } { // 123 = 0x7b = 0001111011 in 10 bits. BitVector bits = new BitVector(); - assertTrue(Encoder.AppendNumericBytes(new ByteArray("123"), bits)); + Encoder.AppendNumericBytes(new ByteArray("123"), bits); assertEquals("0001111011" , bits.toString()); } { // 1234 = "123" + "4" = 0001111011 + 0100 BitVector bits = new BitVector(); - assertTrue(Encoder.AppendNumericBytes(new ByteArray("1234"), bits)); + Encoder.AppendNumericBytes(new ByteArray("1234"), bits); assertEquals("0001111011" + "0100" , bits.toString()); } { // Empty. BitVector bits = new BitVector(); - assertTrue(Encoder.AppendNumericBytes(new ByteArray(""), bits)); + Encoder.AppendNumericBytes(new ByteArray(""), bits); assertEquals("" , bits.toString()); } { // Invalid data. BitVector bits = new BitVector(); - assertFalse(Encoder.AppendNumericBytes(new ByteArray("abc"), bits)); + try { + Encoder.AppendNumericBytes(new ByteArray("abc"), bits); + } catch (WriterException we) { + // good + } } } - public void testAppendAlphanumericBytes() { + public void testAppendAlphanumericBytes() throws WriterException { { // A = 10 = 0xa = 001010 in 6 bits BitVector bits = new BitVector(); - assertTrue(Encoder.AppendAlphanumericBytes(new ByteArray("A"), bits)); + Encoder.AppendAlphanumericBytes(new ByteArray("A"), bits); assertEquals("001010" , bits.toString()); } { // AB = 10 * 45 + 11 = 461 = 0x1cd = 00111001101 in 11 bits BitVector bits = new BitVector(); - assertTrue(Encoder.AppendAlphanumericBytes(new ByteArray("AB"), bits)); + Encoder.AppendAlphanumericBytes(new ByteArray("AB"), bits); assertEquals("00111001101", bits.toString()); } { // ABC = "AB" + "C" = 00111001101 + 001100 BitVector bits = new BitVector(); - assertTrue(Encoder.AppendAlphanumericBytes(new ByteArray("ABC"), bits)); + Encoder.AppendAlphanumericBytes(new ByteArray("ABC"), bits); assertEquals("00111001101" + "001100" , bits.toString()); } { // Empty. BitVector bits = new BitVector(); - assertTrue(Encoder.AppendAlphanumericBytes(new ByteArray(""), bits)); + Encoder.AppendAlphanumericBytes(new ByteArray(""), bits); assertEquals("" , bits.toString()); } { // Invalid data. BitVector bits = new BitVector(); - assertFalse(Encoder.AppendAlphanumericBytes(new ByteArray("abc"), bits)); + try { + Encoder.AppendAlphanumericBytes(new ByteArray("abc"), bits); + } catch (WriterException we) { + // good + } } } - public void testAppend8BitBytes() { + public void testAppend8BitBytes() throws WriterException { { // 0x61, 0x62, 0x63 BitVector bits = new BitVector(); - assertTrue(Encoder.Append8BitBytes(new ByteArray("abc"), bits)); + Encoder.Append8BitBytes(new ByteArray("abc"), bits); assertEquals("01100001" + "01100010" + "01100011", bits.toString()); } { // Empty. BitVector bits = new BitVector(); - assertTrue(Encoder.Append8BitBytes(new ByteArray(""), bits)); + Encoder.Append8BitBytes(new ByteArray(""), bits); assertEquals("", bits.toString()); } } // Numbers are from page 21 of JISX0510:2004 - public void testAppendKanjiBytes() { + public void testAppendKanjiBytes() throws WriterException { { BitVector bits = new BitVector(); byte[] dat1 = {(byte)0x93,0x5f}; - assertTrue(Encoder.AppendKanjiBytes(new ByteArray(dat1), bits)); + Encoder.AppendKanjiBytes(new ByteArray(dat1), bits); assertEquals("0110110011111", bits.toString()); byte[] dat2 = {(byte)0xe4,(byte)0xaa}; - assertTrue(Encoder.AppendKanjiBytes(new ByteArray(dat2), bits)); + Encoder.AppendKanjiBytes(new ByteArray(dat2), bits); assertEquals("0110110011111" + "1101010101010", bits.toString()); } } diff --git a/core/test/src/com/google/zxing/qrcode/encoder/MatrixUtilTestCase.java b/core/test/src/com/google/zxing/qrcode/encoder/MatrixUtilTestCase.java index 3131514a8..ce2b0d7fd 100644 --- a/core/test/src/com/google/zxing/qrcode/encoder/MatrixUtilTestCase.java +++ b/core/test/src/com/google/zxing/qrcode/encoder/MatrixUtilTestCase.java @@ -17,6 +17,7 @@ package com.google.zxing.qrcode.encoder; import com.google.zxing.common.ByteMatrix; +import com.google.zxing.WriterException; import junit.framework.TestCase; /** @@ -48,7 +49,7 @@ public final class MatrixUtilTestCase extends TestCase { assertEquals(-1, matrix.get(1, 1)); } - public void testEmbedBasicPatterns() { + public void testEmbedBasicPatterns() throws WriterException { { // Version 1. String expected = @@ -75,7 +76,7 @@ public final class MatrixUtilTestCase extends TestCase { " 1 1 1 1 1 1 1 0 \n"; ByteMatrix matrix = new ByteMatrix(21, 21); MatrixUtil.ClearMatrix(matrix); - assertTrue(MatrixUtil.EmbedBasicPatterns(1, matrix)); + MatrixUtil.EmbedBasicPatterns(1, matrix); assertEquals(expected, matrix.toString()); } { @@ -109,12 +110,12 @@ public final class MatrixUtilTestCase extends TestCase { " 1 1 1 1 1 1 1 0 \n"; ByteMatrix matrix = new ByteMatrix(25, 25); MatrixUtil.ClearMatrix(matrix); - assertTrue(MatrixUtil.EmbedBasicPatterns(2, matrix)); + MatrixUtil.EmbedBasicPatterns(2, matrix); assertEquals(expected, matrix.toString()); } } - public void testEmbedTypeInfo() { + public void testEmbedTypeInfo() throws WriterException { // Type info bits = 100000011001110. String expected = " 0 \n" + @@ -140,12 +141,11 @@ public final class MatrixUtilTestCase extends TestCase { " 1 \n"; ByteMatrix matrix = new ByteMatrix(21, 21); MatrixUtil.ClearMatrix(matrix); - boolean info_okay = MatrixUtil.EmbedTypeInfo(QRCode.EC_LEVEL_M, 5, matrix); - assertTrue(info_okay); + MatrixUtil.EmbedTypeInfo(QRCode.EC_LEVEL_M, 5, matrix); assertEquals(expected, matrix.toString()); } - public void testEmbedVersionInfo() { + public void testEmbedVersionInfo() throws WriterException { // Version info bits = 000111 110010 010100 String expected = " 0 0 1 \n" + @@ -173,11 +173,11 @@ public final class MatrixUtilTestCase extends TestCase { // since 45x45 matrix is too big to depict. ByteMatrix matrix = new ByteMatrix(21, 21); MatrixUtil.ClearMatrix(matrix); - assertTrue(MatrixUtil.MaybeEmbedVersionInfo(7, matrix)); + MatrixUtil.MaybeEmbedVersionInfo(7, matrix); assertEquals(expected, matrix.toString()); } - public void testEmbedDataBits() { + public void testEmbedDataBits() throws WriterException { // Cells other than basic patterns should be filled with zero. String expected = " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1\n" + @@ -205,11 +205,11 @@ public final class MatrixUtilTestCase extends TestCase { ByteMatrix matrix = new ByteMatrix(21, 21); MatrixUtil.ClearMatrix(matrix); MatrixUtil.EmbedBasicPatterns(1, matrix); - assertTrue(MatrixUtil.EmbedDataBits(bits, -1, matrix)); + MatrixUtil.EmbedDataBits(bits, -1, matrix); assertEquals(expected, matrix.toString()); } - public void testBuildMatrix() { + public void testBuildMatrix() throws WriterException { // From http://www.swetake.com/qr/qr7.html String expected = " 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 1 1 1 1 1 1\n" + @@ -241,11 +241,11 @@ public final class MatrixUtilTestCase extends TestCase { bits.AppendBits(c, 8); } ByteMatrix matrix = new ByteMatrix(21, 21); - assertTrue(MatrixUtil.BuildMatrix(bits, + MatrixUtil.BuildMatrix(bits, QRCode.EC_LEVEL_H, 1, // Version 1 3, // Mask pattern 3 - matrix)); + matrix); } public void testFindMSBSet() { @@ -277,20 +277,20 @@ public final class MatrixUtilTestCase extends TestCase { // We don't test a lot of cases in this function since we've already // tested them in TEST(CalculateBCHCode). - public void testMakeVersionInfoBits() { + public void testMakeVersionInfoBits() throws WriterException { // From Appendix D in JISX0510:2004 (p 68) BitVector bits = new BitVector(); - assertTrue(MatrixUtil.MakeVersionInfoBits(7, bits)); + MatrixUtil.MakeVersionInfoBits(7, bits); assertEquals("000111110010010100", bits.toString()); } // We don't test a lot of cases in this function since we've already // tested them in TEST(CalculateBCHCode). - public void testMakeTypeInfoInfoBits() { + public void testMakeTypeInfoInfoBits() throws WriterException { // From Appendix C in JISX0510:2004 (p 65) BitVector bits = new BitVector(); - assertTrue(MatrixUtil.MakeTypeInfoBits(QRCode.EC_LEVEL_M, - 5, bits)); + MatrixUtil.MakeTypeInfoBits(QRCode.EC_LEVEL_M, + 5, bits); assertEquals("100000011001110", bits.toString()); } } diff --git a/core/test/src/com/google/zxing/qrcode/encoder/QRCodeTestCase.java b/core/test/src/com/google/zxing/qrcode/encoder/QRCodeTestCase.java index 1d178e899..d7fc4970f 100644 --- a/core/test/src/com/google/zxing/qrcode/encoder/QRCodeTestCase.java +++ b/core/test/src/com/google/zxing/qrcode/encoder/QRCodeTestCase.java @@ -17,6 +17,7 @@ package com.google.zxing.qrcode.encoder; import com.google.zxing.common.ByteMatrix; +import com.google.zxing.WriterException; import junit.framework.TestCase; /** @@ -208,19 +209,29 @@ public final class QRCodeTestCase extends TestCase { assertEquals("UNKNOWN", QRCode.ECLevelToString(QRCode.NUM_EC_LEVELS)); } - public void testGetModeCode() { + public void testGetModeCode() throws WriterException { assertEquals(1, QRCode.GetModeCode(QRCode.MODE_NUMERIC)); assertEquals(2, QRCode.GetModeCode(QRCode.MODE_ALPHANUMERIC)); assertEquals(4, QRCode.GetModeCode(QRCode.MODE_8BIT_BYTE)); assertEquals(8, QRCode.GetModeCode(QRCode.MODE_KANJI)); - assertEquals(-1, QRCode.GetModeCode(QRCode.MODE_UNDEFINED)); + try { + QRCode.GetModeCode(QRCode.MODE_UNDEFINED); + fail("Should have thrown exception"); + } catch (WriterException we) { + // good + } } - public void testGetECLevelCode() { + public void testGetECLevelCode() throws WriterException { assertEquals(1, QRCode.GetECLevelCode(QRCode.EC_LEVEL_L)); assertEquals(0, QRCode.GetECLevelCode(QRCode.EC_LEVEL_M)); assertEquals(3, QRCode.GetECLevelCode(QRCode.EC_LEVEL_Q)); assertEquals(2, QRCode.GetECLevelCode(QRCode.EC_LEVEL_H)); - assertEquals(-1, QRCode.GetECLevelCode(QRCode.EC_LEVEL_UNDEFINED)); + try { + QRCode.GetECLevelCode(QRCode.EC_LEVEL_UNDEFINED); + fail("Should have thrown exception"); + } catch (WriterException we) { + // good + } } } diff --git a/core/test/src/com/google/zxing/qrcode/encoder/RendererTestCase.java b/core/test/src/com/google/zxing/qrcode/encoder/RendererTestCase.java deleted file mode 100644 index 2c5993431..000000000 --- a/core/test/src/com/google/zxing/qrcode/encoder/RendererTestCase.java +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.encoder; - -import junit.framework.TestCase; - -//#include "file/base/file.h" -//#include "testing/base/gunit.h" -//#include "testing/base/benchmark.h" -//#include "wireless/qrcode/qrcode.h" -//#include "wireless/qrcode/qrcode_encoder.h" -//#include "wireless/qrcode/qrcode_renderer.h" - -/** - * @author satorux@google.com (Satoru Takabayashi) - creator - * @author mysen@google.com (Chris Mysen) - ported from C++ - */ -public final class RendererTestCase extends TestCase { -// public void testRenderAsPNG() { -// QRCode qr_code = new QRCode(); -// assertTrue(Encoder.Encode(new ByteArray("http://www.google.com/"), -// QRCode.EC_LEVEL_M, qr_code)); -// String result; -// assertTrue(Renderer.RenderAsPNG(qr_code, 3, result)); -// assertFalse(result.length() == 0); -// // We don't test the result image in this test. We do that in -// // RegressionTest(). -// } -// -// public void testRenderAsPNGFromData() { -// QRCode qr_code = new QRCode(); -// assertTrue(Encoder.Encode(new ByteArray("http://www.google.com/"), -// QRCode.EC_LEVEL_M, qr_code)); -// String result1; -// assertTrue(Renderer.RenderAsPNG(qr_code, 3, result1)); -// -// String result2; -// assertTrue(Renderer.RenderAsPNGFromData("http://www.google.com/", -// QRCode.EC_LEVEL_M, 3, -// result2)); -// assertEquals(result1, result2); -// } -// -// // ec_level comes from QRCode.EC_LEVEL_[LMQH] -// static boolean Compare(final String bytes, final int ec_level, -// final int cell_size, final String golden_base_name) { -// String result; -// assertTrue(Renderer.RenderAsPNGFromData(bytes, ec_level, -// cell_size, result)); -// String golden_file_name = "test/data/qrcode_encode/" + -// golden_base_name; -// String golden; -// File.ReadFileToStringOrDie(golden_file_name, golden); -// return golden == result; -// } -// -// // Golden images are generated with "qrcode_sample.cc". The images -// // are checked with both eye balls and cell phones. -// public void testRegressionTest() { -// assertTrue(Compare("http://www.google.com/", QRCode.EC_LEVEL_M, 3, -// "renderer-test-01.png")); -// assertTrue(Compare("12345", QRCode.EC_LEVEL_L, 2, -// "renderer-test-02.png")); -// // Test in Katakana in Shift_JIS. -// byte[] dat = {(byte)0x83,0x65,(byte)0x83,0x58,(byte)0x83,0x67}; -// assertTrue(Compare(new String(dat), QRCode.EC_LEVEL_H, 5, -// "renderer-test-03.png")); -// } -}