Skip to content

Commit

Permalink
chore: code optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
li-jia-nan committed Jan 8, 2025
1 parent fd675ed commit 0ef7aef
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 34 deletions.
80 changes: 46 additions & 34 deletions src/libs/qrcodegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ function appendBits(val: number, len: number, bb: number[]): void {
let i = len - 1;
i >= 0;
i-- // Append bit by bit
)
) {
bb.push((val >>> i) & 1);
}
}

// Returns true iff the i'th bit of x is set to 1.
Expand Down Expand Up @@ -112,7 +113,9 @@ export class QrSegment {
// can be converted to UTF-8 bytes and encoded as a byte mode segment.
public static makeBytes(data: Readonly<number[]>): QrSegment {
const bb: number[] = [];
for (const b of data) appendBits(b, 8, bb);
for (const b of data) {
appendBits(b, 8, bb);
}
return new QrSegment(Mode.BYTE, data.length, bb);
}

Expand Down Expand Up @@ -258,8 +261,9 @@ export class QrSegment {
const str = encodeURI(input);
const result: number[] = [];
for (let i = 0; i < str.length; i++) {
if (str.charAt(i) != '%') result.push(str.charCodeAt(i));
else {
if (str.charAt(i) != '%') {
result.push(str.charCodeAt(i));
} else {
result.push(parseInt(str.substring(i + 1, i + 3), 16));
i += 2;
}
Expand Down Expand Up @@ -315,7 +319,7 @@ export class QrCode {
// bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
// The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
public static encodeBinary(data: Readonly<number[]>, ecl: Ecc): QrCode {
const seg: QrSegment = QrSegment.makeBytes(data);
const seg = QrSegment.makeBytes(data);
return QrCode.encodeSegments([seg], ecl);
}

Expand Down Expand Up @@ -346,23 +350,24 @@ export class QrCode {
) ||
mask < -1 ||
mask > 7
)
) {
throw new RangeError('Invalid value');
}

// Find the minimal version number to use
let version: number;
let dataUsedBits: number;
for (version = minVersion; ; version++) {
const dataCapacityBits: number =
QrCode.getNumDataCodewords(version, oriEcl) * 8; // Number of data bits available
const dataCapacityBits = QrCode.getNumDataCodewords(version, oriEcl) * 8; // Number of data bits available
const usedBits: number = QrSegment.getTotalBits(segs, version);
if (usedBits <= dataCapacityBits) {
dataUsedBits = usedBits;
break; // This version number is found to be suitable
}
if (version >= maxVersion)
if (version >= maxVersion) {
// All versions in the range could not fit the given data
throw new RangeError('Data too long');
}
}
let ecl: Ecc = oriEcl;
// Increase the error correction level while the data still fits in the current version number
Expand Down Expand Up @@ -408,7 +413,9 @@ export class QrCode {
while (dataCodewords.length * 8 < bb.length) {
dataCodewords.push(0);
}
bb.forEach((b, i) => (dataCodewords[i >>> 3] |= b << (7 - (i & 7))));
bb.forEach((b, i) => {
dataCodewords[i >>> 3] |= b << (7 - (i & 7));
});

// Create the QR Code object
return new QrCode(version, ecl, dataCodewords, mask);
Expand Down Expand Up @@ -460,16 +467,19 @@ export class QrCode {
this.version = version;
this.errorCorrectionLevel = errorCorrectionLevel;
// Check scalar arguments
if (version < QrCode.MIN_VERSION || version > QrCode.MAX_VERSION)
if (version < QrCode.MIN_VERSION || version > QrCode.MAX_VERSION) {
throw new RangeError('Version value out of range');
}
if (msk < -1 || msk > 7) {
throw new RangeError('Mask value out of range');
}
this.size = version * 4 + 17;

// Initialize both grids to be size*size arrays of Boolean false
const row: boolean[] = [];
for (let i = 0; i < this.size; i++) row.push(false);
for (let i = 0; i < this.size; i++) {
row.push(false);
}
for (let i = 0; i < this.size; i++) {
this.modules.push(row.slice()); // Initially all light
this.isFunction.push(row.slice());
Expand Down Expand Up @@ -570,7 +580,9 @@ export class QrCode {
assert(bits >>> 15 == 0);

// Draw first copy
for (let i = 0; i <= 5; i++) this.setFunctionModule(8, i, getBit(bits, i));
for (let i = 0; i <= 5; i++) {
this.setFunctionModule(8, i, getBit(bits, i));
}
this.setFunctionModule(8, 7, getBit(bits, 6));
this.setFunctionModule(8, 8, getBit(bits, 7));
this.setFunctionModule(7, 8, getBit(bits, 8));
Expand Down Expand Up @@ -658,19 +670,15 @@ export class QrCode {
throw new RangeError('Invalid argument');
}
// Calculate parameter numbers
const numBlocks: number =
QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver];
const blockEccLen: number =
QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver];
const rawCodewords: number = Math.floor(
QrCode.getNumRawDataModules(ver) / 8,
);
const numShortBlocks: number = numBlocks - (rawCodewords % numBlocks);
const shortBlockLen: number = Math.floor(rawCodewords / numBlocks);
const numBlocks = QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver];
const blockEccLen = QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver];
const rawCodewords = Math.floor(QrCode.getNumRawDataModules(ver) / 8);
const numShortBlocks = numBlocks - (rawCodewords % numBlocks);
const shortBlockLen = Math.floor(rawCodewords / numBlocks);

// Split data numbero blocks and append ECC to each block
const blocks: number[][] = [];
const rsDiv: number[] = QrCode.reedSolomonComputeDivisor(blockEccLen);
const rsDiv = QrCode.reedSolomonComputeDivisor(blockEccLen);
for (let i = 0, k = 0; i < numBlocks; i++) {
const dat = data.slice(
k,
Expand Down Expand Up @@ -854,8 +862,9 @@ export class QrCode {

// Balance of dark and light modules
let dark: number = 0;
for (const row of this.modules)
for (const row of this.modules) {
dark = row.reduce((sum, color) => sum + (color ? 1 : 0), dark);
}
const total: number = this.size * this.size; // Note that size is odd, so dark/total != 1/2
// Compute the smallest numbereger k >= 0 such that (45-5k)% <= dark/total <= (55+5k)%
const k: number = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1;
Expand All @@ -874,14 +883,15 @@ export class QrCode {
if (this.version == 1) {
return [];
} else {
const numAlign: number = Math.floor(this.version / 7) + 2;
const step: number =
const numAlign = Math.floor(this.version / 7) + 2;
const step =
this.version == 32
? 26
: Math.ceil((this.version * 4 + 4) / (numAlign * 2 - 2)) * 2;
const result: number[] = [6];
for (let pos = this.size - 7; result.length < numAlign; pos -= step)
for (let pos = this.size - 7; result.length < numAlign; pos -= step) {
result.splice(1, 0, pos);
}
return result;
}
}
Expand Down Expand Up @@ -925,7 +935,9 @@ export class QrCode {
// Polynomial coefficients are 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 unumber8 array [255, 8, 93].
const result: number[] = [];
for (let i = 0; i < degree - 1; i++) result.push(0);
for (let i = 0; i < degree - 1; i++) {
result.push(0);
}
result.push(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}),
Expand All @@ -949,15 +961,15 @@ export class QrCode {
private static reedSolomonComputeRemainder(
data: Readonly<number[]>,
divisor: Readonly<number[]>,
): number[] {
) {
const result = divisor.map<number>(() => 0);
for (const b of data) {
// Polynomial division
const factor: number = b ^ (result.shift() as number);
const factor = b ^ result.shift();
result.push(0);
divisor.forEach(
(coef, i) => (result[i] ^= QrCode.reedSolomonMultiply(coef, factor)),
);
divisor.forEach((coef, i) => {
result[i] ^= QrCode.reedSolomonMultiply(coef, factor);
});
}
return result;
}
Expand Down Expand Up @@ -1016,7 +1028,7 @@ export class QrCode {
private finderPenaltyAddHistory(
oriCurrentRunLength: number,
runHistory: number[],
): void {
) {
let currentRunLength = oriCurrentRunLength;
if (runHistory[0] == 0) {
currentRunLength += this.size; // Add light border to initial run
Expand Down
1 change: 1 addition & 0 deletions src/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export const generatePath = (modules: Modules, margin: number = 0) => {
});
return ops.join('');
};

/**
* Excavate modules
* @param modules
Expand Down

0 comments on commit 0ef7aef

Please sign in to comment.