diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..e5bd3bf --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding//java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java=UTF-8 diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeAlphaNumericToSegment.java b/java/src/main/java/io/nayuki/qrcodegen/MakeAlphaNumericToSegment.java new file mode 100644 index 0000000..66bd854 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeAlphaNumericToSegment.java @@ -0,0 +1,34 @@ +import java.util.Objects; + +public class MakeAlphaNumericToSegment implements MakeSegment { + + /** + * Returns a segment representing the specified text string encoded in alphanumeric mode. + * The characters allowed are: 0 to 9, A to Z (uppercase only), space, + * dollar, percent, asterisk, plus, hyphen, period, slash, colon. + * @param text the text (not {@code null}), with only certain characters allowed + * @return a segment (not {@code null}) containing the text + * @throws NullPointerException if the string is {@code null} + * @throws IllegalArgumentException if the string contains non-encodable characters + */ + public QrSegment excute(String text) { + Objects.requireNonNull(text); + if (!QrSegment.ALPHANUMERIC_REGEX.matcher(text).matches()) + throw new IllegalArgumentException("String contains unencodable characters in alphanumeric mode"); + + BitBuffer bitBuffer = new BitBuffer(); + changeAlphaNumericStringToSegment(text, bitBuffer); + return new QrSegment(QrSegment.Mode.ALPHANUMERIC, text.length(), bitBuffer); + } + + public static void changeAlphaNumericStringToSegment(String text, BitBuffer bitBuffer) { + int i; + for (i = 0; i <= text.length() - 2; i += 2) { // Process groups of 2 + int temp = QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; + temp += QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); + bitBuffer.appendBits(temp, 11); + } + if (i < text.length()) // 1 character remaining + bitBuffer.appendBits(QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeBytesToSegment.java b/java/src/main/java/io/nayuki/qrcodegen/MakeBytesToSegment.java new file mode 100644 index 0000000..807d574 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeBytesToSegment.java @@ -0,0 +1,36 @@ +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +public class MakeBytesToSegment implements MakeSegment { + + /** + * Returns a segment representing the specified binary data + * encoded in byte mode. All input byte arrays are acceptable. + *

Any text string can be converted to UTF-8 bytes ({@code + * s.getBytes(StandardCharsets.UTF_8)}) and encoded as a byte mode segment.

+ * @param data the binary data (not {@code null}) + * @return a segment (not {@code null}) containing the data + * @throws NullPointerException if the array is {@code null} + */ + public QrSegment excute(String text) { + byte[] data = text.getBytes(StandardCharsets.UTF_8)); + + Objects.requireNonNull(data); + BitBuffer bitBuffer = new BitBuffer(); + for (byte bits : data) + changeByteToSegment(bitBuffer, bits); + return new QrSegment(QrSegment.Mode.BYTE, data.length, bitBuffer); + } + + public QrSegment excuteForBytedata(byte[] data) { + Objects.requireNonNull(data); + BitBuffer bitBuffer = new BitBuffer(); + for (byte bits : data) + changeByteToSegment(bitBuffer, bits); + return new QrSegment(QrSegment.Mode.BYTE, data.length, bitBuffer); + } + + public static void changeByteToSegment(BitBuffer bitBuffer, byte bits) { + bitBuffer.appendBits(bits & 0xFF, 8); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeNumericToSegment.java b/java/src/main/java/io/nayuki/qrcodegen/MakeNumericToSegment.java new file mode 100644 index 0000000..3da7b7e --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeNumericToSegment.java @@ -0,0 +1,33 @@ +import java.util.Objects; + +public class MakeNumericToSegment implements MakeSegment { + + /** + * Returns a segment representing the specified string of decimal digits encoded in numeric mode. + * @param digits the text (not {@code null}), with only digits from 0 to 9 allowed + * @return a segment (not {@code null}) containing the text + * @throws NullPointerException if the string is {@code null} + * @throws IllegalArgumentException if the string contains non-digit characters + */ + public QrSegment excute(String digits) { + Objects.requireNonNull(digits); + if (containNonNumericCharaters(digits)) + throw new IllegalArgumentException("String contains non-numeric characters"); + + BitBuffer bitBuffer = new BitBuffer(); + changeNumericToSegment(digits, bitBuffer); + return new QrSegment(QrSegment.Mode.NUMERIC, digits.length(), bitBuffer); + } + + public static void changeNumericToSegment(String digits, BitBuffer bitBuffer) { + for (int i = 0; i < digits.length(); ) { // Consume up to 3 digits per iteration + int n = Math.min(digits.length() - i, 3); + bitBuffer.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); + i += n; + } + } + + public static boolean containNonNumericCharaters(String digits) { + return !QrSegment.NUMERIC_REGEX.matcher(digits).matches(); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeSegment.java b/java/src/main/java/io/nayuki/qrcodegen/MakeSegment.java new file mode 100644 index 0000000..ccca2ba --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeSegment.java @@ -0,0 +1,4 @@ + +public interface MakeSegment { + public QrSegment excute(String text); +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeSegmentFactory.java b/java/src/main/java/io/nayuki/qrcodegen/MakeSegmentFactory.java new file mode 100644 index 0000000..b21a516 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeSegmentFactory.java @@ -0,0 +1,15 @@ +public class MakeSegmentFactory { + public static MakeSegment getMakeSegment(String text) { + MakeSegment makeSegment = null; + + if (text.equals("")); // Leave result empty + else if (QrSegment.NUMERIC_REGEX.matcher(text).matches()) + makeSegment = new MakeNumericToSegment(); + else if (QrSegment.ALPHANUMERIC_REGEX.matcher(text).matches()) + makeSegment = new MakeAlphaNumericToSegment(); + else + makeSegment = new MakeBytesToSegment(); + + return makeSegment; + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java index f9316d7..0e25584 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java @@ -55,13 +55,13 @@ public final class QrCodeGeneratorDemo { String text = "Hello, world!"; // User-supplied Unicode text Ecc errCorLvl = Ecc.LOW; // Error correction level - QrCode qr = QrCode.encodeText(text, errCorLvl); // Make the QR Code symbol + QrCode qrCode = QrCode.encodeText(text, errCorLvl); // Make the QR Code symbol - BufferedImage img = qr.toImage(10, 4); // Convert to bitmap image + BufferedImage img = qrCode.toImage(10, 4); // Convert to bitmap image File imgFile = new File("hello-world-QR.png"); // File path for output ImageIO.write(img, "png", imgFile); // Write image to file - String svg = qr.toSvgString(4); // Convert to SVG XML code + String svg = qrCode.toSvgString(4); // Convert to SVG XML code File svgFile = new File("hello-world-QR.svg"); // File path for output Files.write(svgFile.toPath(), // Write image to file svg.getBytes(StandardCharsets.UTF_8)); @@ -70,22 +70,24 @@ public final class QrCodeGeneratorDemo { // Creates a variety of QR Codes that exercise different features of the library, and writes each one to file. private static void doVarietyDemo() throws IOException { - QrCode qr; + QrCode qrCode; // Numeric mode encoding (3.33 bits per digit) - qr = QrCode.encodeText("314159265358979323846264338327950288419716939937510", Ecc.MEDIUM); - writePng(qr.toImage(13, 1), "pi-digits-QR.png"); + + qrCode = QrCode.encodeText("314159265358979323846264338327950288419716939937510", Ecc.MEDIUM); + writePng(qrCode.toImage(13, 1), "pi-digits-QR.png"); // Alphanumeric mode encoding (5.5 bits per character) - qr = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", Ecc.HIGH); - writePng(qr.toImage(10, 2), "alphanumeric-QR.png"); + qrCode = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", Ecc.HIGH); + writePng(qrCode.toImage(10, 2), "alphanumeric-QR.png"); // Unicode text as UTF-8 - qr = QrCode.encodeText("こんにちwa、世界! αβγδ", Ecc.QUARTILE); - writePng(qr.toImage(10, 3), "unicode-QR.png"); + qrCode = QrCode.encodeText("占쎄괭占쎄뎐占쎄쾽占쎄굶wa占쎄낌�닟占쎈르塋딉옙 �뀭汝뷸Ь�걣", Ecc.QUARTILE); + writePng(qrCode.toImage(10, 3), "unicode-QR.png"); + // Moderately large QR Code using longer text (from Lewis Carroll's Alice in Wonderland) - qr = QrCode.encodeText( + qrCode = QrCode.encodeText( "Alice was beginning to get very tired of sitting by her sister on the bank, " + "and of having nothing to do: once or twice she had peeped into the book her sister was reading, " + "but it had no pictures or conversations in it, 'and what is the use of a book,' thought Alice " @@ -93,74 +95,87 @@ public final class QrCodeGeneratorDemo { + "for the hot day made her feel very sleepy and stupid), whether the pleasure of making a " + "daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly " + "a White Rabbit with pink eyes ran close by her.", Ecc.HIGH); - writePng(qr.toImage(6, 10), "alice-wonderland-QR.png"); + + writePng(qrCode.toImage(6, 10), "alice-wonderland-QR.png"); + } // Creates QR Codes with manually specified segments for better compactness. private static void doSegmentDemo() throws IOException { - QrCode qr; - List segs; + QrCode qrCode; + List segments; // Illustration "silver" String silver0 = "THE SQUARE ROOT OF 2 IS 1."; String silver1 = "41421356237309504880168872420969807856967187537694807317667973799"; - qr = QrCode.encodeText(silver0 + silver1, Ecc.LOW); - writePng(qr.toImage(10, 3), "sqrt2-monolithic-QR.png"); + + qrCode = QrCode.encodeText(silver0 + silver1, Ecc.LOW); + writePng(qrCode.toImage(10, 3), "sqrt2-monolithic-QR.png"); + - segs = Arrays.asList( + segments = Arrays.asList( QrSegment.makeAlphanumeric(silver0), QrSegment.makeNumeric(silver1)); - qr = QrCode.encodeSegments(segs, Ecc.LOW); - writePng(qr.toImage(10, 3), "sqrt2-segmented-QR.png"); + + qrCode = QrCode.encodeSegments(segments, Ecc.LOW); + writePng(qrCode.toImage(10, 3), "sqrt2-segmented-QR.png"); + // Illustration "golden" - String golden0 = "Golden ratio φ = 1."; + String golden0 = "Golden ratio 占쏙옙 = 1."; String golden1 = "6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374"; String golden2 = "......"; - qr = QrCode.encodeText(golden0 + golden1 + golden2, Ecc.LOW); - writePng(qr.toImage(8, 5), "phi-monolithic-QR.png"); + + qrCode = QrCode.encodeText(golden0 + golden1 + golden2, Ecc.LOW); + writePng(qrCode.toImage(8, 5), "phi-monolithic-QR.png"); + - segs = Arrays.asList( + segments = Arrays.asList( QrSegment.makeBytes(golden0.getBytes(StandardCharsets.UTF_8)), QrSegment.makeNumeric(golden1), QrSegment.makeAlphanumeric(golden2)); - qr = QrCode.encodeSegments(segs, Ecc.LOW); - writePng(qr.toImage(8, 5), "phi-segmented-QR.png"); + + qrCode = QrCode.encodeSegments(segments, Ecc.LOW); + writePng(qrCode.toImage(8, 5), "phi-segmented-QR.png"); // Illustration "Madoka": kanji, kana, Cyrillic, full-width Latin, Greek characters - String madoka = "「魔法少女まどか☆マギカ」って、 ИАИ desu κα?"; - qr = QrCode.encodeText(madoka, Ecc.LOW); - writePng(qr.toImage(9, 4), "madoka-utf8-QR.png"); + String madoka = "占쎈슞異몌쫲類앹빼阿잙뀍寃뀐옙寃묕옙嫄�占쎌겳占쎄묻占쎄텤占쎄텠占쎈씞寃귨옙寃랃옙怨ο옙占쏙옙�꺂癒믪꼨占쏙옙影�袁ы맀影�蹂⑺맟占쏙옙鰲��뀭塋딉옙"; + qrCode = QrCode.encodeText(madoka, Ecc.LOW); + writePng(qrCode.toImage(9, 4), "madoka-utf8-QR.png"); - segs = Arrays.asList(QrSegmentAdvanced.makeKanji(madoka)); - qr = QrCode.encodeSegments(segs, Ecc.LOW); - writePng(qr.toImage(9, 4), "madoka-kanji-QR.png"); + segments = Arrays.asList(QrSegmentAdvanced.makeKanji(madoka)); + qrCode = QrCode.encodeSegments(segments, Ecc.LOW); + writePng(qrCode.toImage(9, 4), "madoka-kanji-QR.png"); + + } // Creates QR Codes with the same size and contents but different mask patterns. private static void doMaskDemo() throws IOException { - QrCode qr; - List segs; + QrCode qrCode; + List segments; // Project Nayuki URL - segs = QrSegment.makeSegments("https://www.nayuki.io/"); - qr = QrCode.encodeSegments(segs, Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, -1, true); // Automatic mask - writePng(qr.toImage(8, 6), "project-nayuki-automask-QR.png"); - qr = QrCode.encodeSegments(segs, Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 3, true); // Force mask 3 - writePng(qr.toImage(8, 6), "project-nayuki-mask3-QR.png"); + + segments = QrSegment.makeSegments("https://www.nayuki.io/"); + qrCode = QrCode.encodeSegments(segments, Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, -1, true); // Automatic mask + writePng(qrCode.toImage(8, 6), "project-nayuki-automask-QR.png"); + qrCode = QrCode.encodeSegments(segments, Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 3, true); // Force mask 3 + writePng(qrCode.toImage(8, 6), "project-nayuki-mask3-QR.png"); // Chinese text as UTF-8 - segs = QrSegment.makeSegments("維基百科(Wikipedia,聆聽i/ˌwɪkᵻˈpiːdi.ə/)是一個自由內容、公開編輯且多語言的網路百科全書協作計畫"); - qr = QrCode.encodeSegments(segs, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 0, true); // Force mask 0 - writePng(qr.toImage(10, 3), "unicode-mask0-QR.png"); - qr = QrCode.encodeSegments(segs, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 1, true); // Force mask 1 - writePng(qr.toImage(10, 3), "unicode-mask1-QR.png"); - qr = QrCode.encodeSegments(segs, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 5, true); // Force mask 5 - writePng(qr.toImage(10, 3), "unicode-mask5-QR.png"); - qr = QrCode.encodeSegments(segs, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 7, true); // Force mask 7 - writePng(qr.toImage(10, 3), "unicode-mask7-QR.png"); + segments = QrSegment.makeSegments("力놂옙占쎌쓢占쎌뇥�뇖臾뺥렩Wikipedia塋딅슜嫄앾옙寃켲/占쎈샆�뎚藥�戮먮뒰i占쎈쫨i.占쏙옙/塋딅맚�궦鼇앾옙占쎈뿨�닅占쎈뎨占쎈�깍Ⅴ諛ㅿ옙怨⑸�띰옙堉�歷뜯몼�꽎鼇앸떱姨�亦껋쉮占쏙옙�돦力녠엽�윭占쎌뇥�뇖臾덈�뀐옙�럱占쎈쐭俑앹뮂怡ワ옙鍮�"); + qrCode = QrCode.encodeSegments(segments, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 0, true); // Force mask 0 + writePng(qrCode.toImage(10, 3), "unicode-mask0-QR.png"); + qrCode = QrCode.encodeSegments(segments, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 1, true); // Force mask 1 + writePng(qrCode.toImage(10, 3), "unicode-mask1-QR.png"); + qrCode = QrCode.encodeSegments(segments, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 5, true); // Force mask 5 + writePng(qrCode.toImage(10, 3), "unicode-mask5-QR.png"); + qrCode = QrCode.encodeSegments(segments, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 7, true); // Force mask 7 + writePng(qrCode.toImage(10, 3), "unicode-mask7-QR.png"); + } diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java index 54f3dbf..1cb9f44 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorWorker.java @@ -57,11 +57,11 @@ public final class QrCodeGeneratorWorker { boolean isAscii = true; byte[] data = new byte[length]; for (int i = 0; i < data.length; i++) { - int b = input.nextInt(); - if (b < 0 || b > 255) + int one_byte = input.nextInt(); + if (one_byte < 0 || one_byte > 255) throw new RuntimeException(); - data[i] = (byte)b; - isAscii &= b < 128; + data[i] = (byte)one_byte; + isAscii &= one_byte < 128; } // Read encoding parameters @@ -75,14 +75,15 @@ public final class QrCodeGeneratorWorker { throw new RuntimeException(); // Make segments for encoding - List segs; + List segments; if (isAscii) - segs = QrSegment.makeSegments(new String(data, StandardCharsets.US_ASCII)); + segments = QrSegment.makeSegments(new String(data, StandardCharsets.US_ASCII)); else - segs = Arrays.asList(QrSegment.makeBytes(data)); + segments = Arrays.asList(QrSegment.makeBytes(data)); try { // Try to make QR Code symbol - QrCode qr = QrCode.encodeSegments(segs, Ecc.values()[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0); + QrCode qr = QrCode.encodeSegments(segments, Ecc.values()[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0); + // Print grid of modules System.out.println(qr.version); for (int y = 0; y < qr.size; y++) { diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java index f416200..307f549 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrSegment.java @@ -29,6 +29,8 @@ import java.util.List; import java.util.Objects; import java.util.regex.Pattern; +import QrSegment.Mode; + /** * A segment of character/binary/control data in a QR Code symbol. @@ -46,7 +48,6 @@ import java.util.regex.Pattern; public final class QrSegment { /*---- Static factory functions (mid level) ----*/ - /** * Returns a segment representing the specified binary data * encoded in byte mode. All input byte arrays are acceptable. @@ -57,11 +58,9 @@ public final class QrSegment { * @throws NullPointerException if the array is {@code null} */ public static QrSegment makeBytes(byte[] data) { - Objects.requireNonNull(data); - BitBuffer bb = new BitBuffer(); - for (byte b : data) - bb.appendBits(b & 0xFF, 8); - return new QrSegment(Mode.BYTE, data.length, bb); + MakeBytesToSegment makeBytesToSegment = new MakeBytesToSegment(); + + return makeBytesToSegment.excuteForBytedata(data); } @@ -73,17 +72,9 @@ public final class QrSegment { * @throws IllegalArgumentException if the string contains non-digit characters */ public static QrSegment makeNumeric(String digits) { - Objects.requireNonNull(digits); - if (!NUMERIC_REGEX.matcher(digits).matches()) - throw new IllegalArgumentException("String contains non-numeric characters"); + MakeSegment makeSegment = new MakeNumericToSegment(); - BitBuffer bb = new BitBuffer(); - for (int i = 0; i < digits.length(); ) { // Consume up to 3 digits per iteration - int n = Math.min(digits.length() - i, 3); - bb.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); - i += n; - } - return new QrSegment(Mode.NUMERIC, digits.length(), bb); + return makeSegment.excute(digits); } @@ -97,23 +88,10 @@ public final class QrSegment { * @throws IllegalArgumentException if the string contains non-encodable characters */ public static QrSegment makeAlphanumeric(String text) { - Objects.requireNonNull(text); - if (!ALPHANUMERIC_REGEX.matcher(text).matches()) - throw new IllegalArgumentException("String contains unencodable characters in alphanumeric mode"); + MakeSegment makeSegment = new MakeAlphaNumericToSegment(); - BitBuffer bb = new BitBuffer(); - int i; - for (i = 0; i <= text.length() - 2; i += 2) { // Process groups of 2 - int temp = ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; - temp += ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); - bb.appendBits(temp, 11); - } - if (i < text.length()) // 1 character remaining - bb.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); - return new QrSegment(Mode.ALPHANUMERIC, text.length(), bb); + return makeSegment.excute(text); } - - /** * Returns a list of zero or more segments to represent the specified Unicode text string. * The result may use various segment modes and switch modes to optimize the length of the bit stream. @@ -121,22 +99,18 @@ public final class QrSegment { * @return a new mutable list (not {@code null}) of segments (not {@code null}) containing the text * @throws NullPointerException if the text is {@code null} */ + public static List makeSegments(String text) { Objects.requireNonNull(text); - // Select the most efficient segment encoding automatically - List result = new ArrayList<>(); - if (text.equals("")); // Leave result empty - else if (NUMERIC_REGEX.matcher(text).matches()) - result.add(makeNumeric(text)); - else if (ALPHANUMERIC_REGEX.matcher(text).matches()) - result.add(makeAlphanumeric(text)); - else - result.add(makeBytes(text.getBytes(StandardCharsets.UTF_8))); - return result; - } - + List segments = new ArrayList<>(); + + MakeSegment makeSegment = MakeSegmentFactory.getMakeSegment(text); + + segments.add(makeSegment.excute(text)); + return segments; + } /** * Returns a segment representing an Extended Channel Interpretation * (ECI) designator with the specified assignment value. @@ -144,21 +118,21 @@ public final class QrSegment { * @return a segment (not {@code null}) containing the data * @throws IllegalArgumentException if the value is outside the range [0, 106) */ - public static QrSegment makeEci(int assignVal) { - BitBuffer bb = new BitBuffer(); - if (assignVal < 0) + public static QrSegment makeEci(int assignValue) { + BitBuffer bitBuffer = new BitBuffer(); + if (assignValue < 0) throw new IllegalArgumentException("ECI assignment value out of range"); - else if (assignVal < (1 << 7)) - bb.appendBits(assignVal, 8); - else if (assignVal < (1 << 14)) { - bb.appendBits(2, 2); - bb.appendBits(assignVal, 14); - } else if (assignVal < 1_000_000) { - bb.appendBits(6, 3); - bb.appendBits(assignVal, 21); + else if (assignValue < (1 << 7)) + bitBuffer.appendBits(assignValue, 8); + else if (assignValue < (1 << 14)) { + bitBuffer.appendBits(2, 2); + bitBuffer.appendBits(assignValue, 14); + } else if (assignValue < 1_000_000) { + bitBuffer.appendBits(6, 3); + bitBuffer.appendBits(assignValue, 21); } else throw new IllegalArgumentException("ECI assignment value out of range"); - return new QrSegment(Mode.ECI, 0, bb); + return new QrSegment(Mode.ECI, 0, bitBuffer); } @@ -189,16 +163,15 @@ public final class QrSegment { * @throws NullPointerException if the mode or data is {@code null} * @throws IllegalArgumentException if the character count is negative */ - public QrSegment(Mode md, int numCh, BitBuffer data) { - mode = Objects.requireNonNull(md); + public QrSegment(Mode _mode, int _numberOfCharacters, BitBuffer data) { + mode = Objects.requireNonNull(_mode); Objects.requireNonNull(data); - if (numCh < 0) + if (_numberOfCharacters < 0) throw new IllegalArgumentException("Invalid value"); - numChars = numCh; + numberOfCharacters = _numberOfCharacters; this.data = data.clone(); // Make defensive copy } - /*---- Methods ----*/ /** @@ -213,22 +186,21 @@ public final class QrSegment { // Calculates the number of bits needed to encode the given segments at the given version. // Returns a non-negative number if successful. Otherwise returns -1 if a segment has too // many characters to fit its length field, or the total bits exceeds Integer.MAX_VALUE. - static int getTotalBits(List segs, int version) { - Objects.requireNonNull(segs); - long result = 0; - for (QrSegment seg : segs) { - Objects.requireNonNull(seg); - int ccbits = seg.mode.numCharCountBits(version); - if (seg.numChars >= (1 << ccbits)) + static int getTotalBits(List segments, int version) { + Objects.requireNonNull(segments); + long TotalBits = 0; + for (QrSegment segment : segments) { + Objects.requireNonNull(segment); + int characterCountBits = segment.mode.numCharCountBits(version); + if (segment.numberOfCharacters >= (1 << characterCountBits)) return -1; // The segment's length doesn't fit the field's bit width - result += 4L + ccbits + seg.data.bitLength(); - if (result > Integer.MAX_VALUE) + TotalBits += 4L + characterCountBits + segment.data.bitLength(); + if (TotalBits > Integer.MAX_VALUE) return -1; // The sum will overflow an int type } - return (int)result; + return (int)TotalBits; } - /*---- Constants ----*/ /** Describes precisely all strings that are encodable in numeric mode. To test whether a