diff --git a/src/io/nayuki/fastqrcodegen/BitBuffer.java b/src/io/nayuki/fastqrcodegen/BitBuffer.java
index 18e1027..fafafd5 100644
--- a/src/io/nayuki/fastqrcodegen/BitBuffer.java
+++ b/src/io/nayuki/fastqrcodegen/BitBuffer.java
@@ -27,24 +27,20 @@ import java.util.Arrays;
import java.util.Objects;
-/**
- * An appendable sequence of bits (0s and 1s). Mainly used by {@link QrSegment}.
- */
+// An appendable sequence of bits (0s and 1s), mainly used by QrSegment.
final class BitBuffer {
/*---- Fields ----*/
- int[] data;
+ int[] data; // In each 32-bit word, bits are filled from top down.
- int bitLength;
+ int bitLength; // Always non-negative.
/*---- Constructor ----*/
- /**
- * Constructs an empty bit buffer (length 0).
- */
+ // Creates an empty bit buffer.
public BitBuffer() {
data = new int[64];
bitLength = 0;
@@ -54,10 +50,7 @@ final class BitBuffer {
/*---- Methods ----*/
- /**
- * Returns the length of this sequence, which is a non-negative value.
- * @return the length of this sequence
- */
+ // Returns the bit at the given index, yielding 0 or 1.
public int getBit(int index) {
if (index < 0 || index >= bitLength)
throw new IndexOutOfBoundsException();
@@ -65,11 +58,8 @@ final class BitBuffer {
}
- /**
- * Returns an array representing this buffer's bits packed into bytes
- * in big endian. The current bit length must be a multiple of 8.
- * @return a new byte array (not {@code null}) representing this bit sequence
- */
+ // Returns a new array representing this buffer's bits packed into
+ // bytes in big endian. The current bit length must be a multiple of 8.
public byte[] getBytes() {
if (bitLength % 8 != 0)
throw new IllegalStateException("Data is not a whole number of bytes");
@@ -80,15 +70,8 @@ final class BitBuffer {
}
- /**
- * Appends the specified number of low-order bits of the specified value to this
- * buffer. Requires 0 ≤ len ≤ 31 and 0 ≤ val < 2len.
- * @param val the value to append
- * @param len the number of low-order bits in the value to take
- * @throws IllegalArgumentException if the value or number of bits is out of range
- * @throws IllegalStateException if appending the data
- * would make bitLength exceed Integer.MAX_VALUE
- */
+ // Appends the given number of low-order bits of the given value
+ // to this buffer. Requires 0 <= len <= 31 and 0 <= val < 2^len.
public void appendBits(int val, int len) {
if (len < 0 || len > 31 || val >>> len != 0)
throw new IllegalArgumentException("Value out of range");
@@ -114,14 +97,8 @@ final class BitBuffer {
}
- /**
- * Appends the specified sequence of bits to this buffer.
- * Requires 0 ≤ len ≤ 32 × vals.length.
- * @param vals the sequence of bits to append (not {@code null})
- * @param len the number of prefix bits to read from the array
- * @throws IllegalStateException if appending the data
- * would make bitLength exceed Integer.MAX_VALUE
- */
+ // Appends to this buffer the sequence of bits represented by the given
+ // word array and given bit length. Requires 0 <= len <= 32 * vals.length.
public void appendBits(int[] vals, int len) {
Objects.requireNonNull(vals);
if (len == 0)
diff --git a/src/io/nayuki/fastqrcodegen/QrCode.java b/src/io/nayuki/fastqrcodegen/QrCode.java
index e25f377..31c9a6e 100644
--- a/src/io/nayuki/fastqrcodegen/QrCode.java
+++ b/src/io/nayuki/fastqrcodegen/QrCode.java
@@ -215,9 +215,8 @@ public final class QrCode {
* −1), the resulting object still has a mask value between 0 and 7. */
public final int mask;
- // Private grid of modules/pixels:
-
- // The modules of this QR Code. Immutable after constructor finishes. Accessed through getModule().
+ // Private grid of modules of this QR Code, packed tightly into bits.
+ // Immutable after constructor finishes. Accessed through getModule().
private final int[] modules;
@@ -424,8 +423,8 @@ public final class QrCode {
}
- // Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
- // data area of this QR Code symbol. Function modules need to be marked off before this is called.
+ // Draws the given sequence of 8-bit codewords (data and error correction)
+ // onto the entire data area of this QR Code, based on the given bit indexes.
private void drawCodewords(int[] dataOutputBitIndexes, byte[] allCodewords) {
Objects.requireNonNull(dataOutputBitIndexes);
Objects.requireNonNull(allCodewords);
@@ -443,7 +442,7 @@ public final class QrCode {
// The function modules must be marked and the codeword bits must be drawn
// before masking. Due to the arithmetic of XOR, calling applyMask() with
// the same mask value a second time will undo the mask. A final well-formed
- // QR Code symbol needs exactly one (not zero, two, etc.) mask applied.
+ // QR Code needs exactly one (not zero, two, etc.) mask applied.
private void applyMask(int[] mask) {
if (mask.length != modules.length)
throw new IllegalArgumentException();
@@ -453,7 +452,7 @@ public final class QrCode {
// A messy helper function for the constructor. This QR Code must be in an unmasked state when this
- // method is called. The given argument is the requested mask, which is -1 for auto or 0 to 7 for fixed.
+ // method is called. The 'mask' argument is the requested mask, which is -1 for auto or 0 to 7 for fixed.
// This method applies and returns the actual mask chosen, from 0 to 7.
private int handleConstructorMasking(int[][] masks, int mask) {
if (mask == -1) { // Automatically choose best mask
diff --git a/src/io/nayuki/fastqrcodegen/QrTemplate.java b/src/io/nayuki/fastqrcodegen/QrTemplate.java
index 98cdeb7..b774cce 100644
--- a/src/io/nayuki/fastqrcodegen/QrTemplate.java
+++ b/src/io/nayuki/fastqrcodegen/QrTemplate.java
@@ -24,23 +24,28 @@
package io.nayuki.fastqrcodegen;
+// Stores the parts of a QR Code that depend only on the version number,
+// and does not depend on the data or error correction level or mask.
final class QrTemplate {
+ // Use this memoizer to get instances of this class.
public static final Memoizer MEMOIZER
= new Memoizer<>(QrTemplate::new);
- private final int version;
- private final int size;
+ private final int version; // In the range [1, 40].
+ private final int size; // Derived from version.
- final int[] template;
- final int[][] masks;
- final int[] dataOutputBitIndexes;
+ final int[] template; // Length and values depend on version.
+ final int[][] masks; // masks.length == 8, and masks[i].length == template.length.
+ final int[] dataOutputBitIndexes; // Length and values depend on version.
// Indicates function modules that are not subjected to masking. Discarded when constructor finishes.
+ // Otherwise when the constructor is running, isFunction.length == template.length.
private int[] isFunction;
+ // Creates a QR Code template for the given version number.
private QrTemplate(int ver) {
if (ver < QrCode.MIN_VERSION || ver > QrCode.MAX_VERSION)
throw new IllegalArgumentException("Version out of range");
@@ -56,6 +61,7 @@ final class QrTemplate {
}
+ // Reads this object's version field, and draws and marks all function modules.
private void drawFunctionPatterns() {
// Draw horizontal and vertical timing patterns
for (int i = 0; i < size; i++) {
@@ -101,7 +107,7 @@ final class QrTemplate {
darkenFunctionModule(size - 1 - i, 8, 0);
for (int i = 8; i < 15; i++)
darkenFunctionModule(8, size - 15 + i, 0);
- darkenFunctionModule(8, size - 8, 1);
+ darkenFunctionModule(8, size - 8, 1); // Always black
}
@@ -153,6 +159,7 @@ final class QrTemplate {
}
+ // Computes and returns a new array of masks, based on this object's various fields.
private int[][] generateMasks() {
int[][] result = new int[8][template.length];
for (int mask = 0; mask < result.length; mask++) {
@@ -180,6 +187,7 @@ final class QrTemplate {
}
+ // Computes and returns an array of bit indexes, based on this object's various fields.
private int[] generateZigzagScan() {
int[] result = new int[getNumRawDataModules(version) / 8 * 8];
int i = 0; // Bit index into the data
@@ -203,6 +211,7 @@ final class QrTemplate {
}
+ // Returns the value of the bit at the given coordinates in the given grid.
private int getModule(int[] grid, int x, int y) {
assert 0 <= x && x < size;
assert 0 <= y && y < size;
diff --git a/src/io/nayuki/fastqrcodegen/ReedSolomonGenerator.java b/src/io/nayuki/fastqrcodegen/ReedSolomonGenerator.java
index 971aa02..cb2def7 100644
--- a/src/io/nayuki/fastqrcodegen/ReedSolomonGenerator.java
+++ b/src/io/nayuki/fastqrcodegen/ReedSolomonGenerator.java
@@ -27,29 +27,31 @@ import java.util.Arrays;
import java.util.Objects;
+// Computes Reed-Solomon error correction codewords for given data codewords.
final class ReedSolomonGenerator {
+ // Use this memoizer to get instances of this class.
public static final Memoizer MEMOIZER
= new Memoizer<>(ReedSolomonGenerator::new);
// A table of size 256 * degree, where polynomialMultiply[i][j] = multiply(i, coefficients[j]).
- // 'coefficients' is the temporary array representing the coefficients of the divisor polynomial,
- // stored from highest to lowest power, excluding the leading term which is always 1.
- // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}.
+ // 'coefficients' is the temporary array computed in the constructor.
private byte[][] polynomialMultiply;
+ // Creates a Reed-Solomon ECC generator polynomial for the given degree.
private ReedSolomonGenerator(int degree) {
if (degree < 1 || degree > 255)
throw new IllegalArgumentException("Degree out of range");
- // Start with the monomial x^0
+ // The divisor polynomial, whose coefficients are stored from highest to lowest power.
+ // For example, x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}.
byte[] coefficients = new byte[degree];
- coefficients[degree - 1] = 1;
+ coefficients[degree - 1] = 1; // Start off with the monomial x^0
// Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
- // drop the highest term, and store the rest of the coefficients in order of descending powers.
+ // and drop the highest monomial term which is always 1x^degree.
// Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).
int root = 1;
for (int i = 0; i < degree; i++) {
@@ -70,15 +72,15 @@ final class ReedSolomonGenerator {
}
+ // Returns the error correction codeword for the given data polynomial and this divisor polynomial.
public void getRemainder(byte[] data, int dataOff, int dataLen, byte[] result) {
Objects.requireNonNull(data);
Objects.requireNonNull(result);
int degree = polynomialMultiply[0].length;
assert result.length == degree;
- // Compute the remainder by performing polynomial division
Arrays.fill(result, (byte)0);
- for (int i = dataOff, dataEnd = dataOff + dataLen; i < dataEnd; i++) {
+ for (int i = dataOff, dataEnd = dataOff + dataLen; i < dataEnd; i++) { // Polynomial division
byte[] table = polynomialMultiply[(data[i] ^ result[0]) & 0xFF];
for (int j = 0; j < degree - 1; j++)
result[j] = (byte)(result[j + 1] ^ table[j]);