From 4ede209d9a1052a22707cd348826336d6b52191d Mon Sep 17 00:00:00 2001 From: Project Nayuki Date: Tue, 28 Aug 2018 19:10:47 +0000 Subject: [PATCH] Changed QrCode.getAlignmentPatternPositions() from static function to instance method, tweaked its logic, and updated comment - in all languages but differently in each. --- c/qrcodegen.c | 6 ++-- cpp/QrCode.cpp | 17 +++++------ cpp/QrCode.hpp | 8 +++--- java/io/nayuki/qrcodegen/QrCode.java | 23 +++++++-------- javascript/qrcodegen.js | 42 +++++++++++++--------------- python/qrcodegen.py | 19 ++++++------- rust/src/lib.rs | 16 +++++------ typescript/qrcodegen.ts | 24 +++++++--------- 8 files changed, 70 insertions(+), 85 deletions(-) diff --git a/c/qrcodegen.c b/c/qrcodegen.c index 2c041b7..8518c5f 100644 --- a/c/qrcodegen.c +++ b/c/qrcodegen.c @@ -447,8 +447,10 @@ static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uin } -// Calculates the positions of alignment patterns in ascending order for the given version number, -// storing them to the given array and returning an array length in the range [0, 7]. +// Calculates and stores an ascending list of positions of alignment patterns +// for this version number, returning the length of the list (in the range [0,7)). +// Each position is in the range [0,177), and are used on both the x and y axes. +// This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. testable int getAlignmentPatternPositions(int version, uint8_t result[7]) { if (version == 1) return 0; diff --git a/cpp/QrCode.cpp b/cpp/QrCode.cpp index 2d4fd3f..86b78f9 100644 --- a/cpp/QrCode.cpp +++ b/cpp/QrCode.cpp @@ -205,7 +205,7 @@ void QrCode::drawFunctionPatterns() { drawFinderPattern(3, size - 4); // Draw numerous alignment patterns - const vector alignPatPos = getAlignmentPatternPositions(version); + const vector alignPatPos = getAlignmentPatternPositions(); int numAlign = alignPatPos.size(); for (int i = 0; i < numAlign; i++) { for (int j = 0; j < numAlign; j++) { @@ -495,18 +495,15 @@ long QrCode::getPenaltyScore() const { } -vector QrCode::getAlignmentPatternPositions(int ver) { - if (ver < MIN_VERSION || ver > MAX_VERSION) - throw std::domain_error("Version number out of range"); - else if (ver == 1) +vector QrCode::getAlignmentPatternPositions() const { + if (version == 1) return vector(); else { - int numAlign = ver / 7 + 2; - int step = (ver == 32) ? 26 : - (ver*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2; - + int numAlign = version / 7 + 2; + int step = (version == 32) ? 26 : + (version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2; vector result; - for (int i = 0, pos = ver * 4 + 10; i < numAlign - 1; i++, pos -= step) + for (int i = 0, pos = size - 7; i < numAlign - 1; i++, pos -= step) result.insert(result.begin(), pos); result.insert(result.begin(), 6); return result; diff --git a/cpp/QrCode.hpp b/cpp/QrCode.hpp index f637513..733df6c 100644 --- a/cpp/QrCode.hpp +++ b/cpp/QrCode.hpp @@ -231,10 +231,10 @@ class QrCode final { /*---- Private static helper functions ----*/ - // Returns a set of positions of the alignment patterns in ascending order. These positions are - // used on both the x and y axes. Each value in the resulting array is in the range [0, 177). - // This stateless pure function could be implemented as table of 40 variable-length lists of unsigned bytes. - private: static std::vector getAlignmentPatternPositions(int ver); + // Returns an ascending list of positions of alignment patterns for this version number. + // Each position is in the range [0,177), and are used on both the x and y axes. + // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. + private: std::vector getAlignmentPatternPositions() const; // Returns the number of data bits that can be stored in a QR Code of the given version number, after diff --git a/java/io/nayuki/qrcodegen/QrCode.java b/java/io/nayuki/qrcodegen/QrCode.java index 4890fed..cf3ec07 100644 --- a/java/io/nayuki/qrcodegen/QrCode.java +++ b/java/io/nayuki/qrcodegen/QrCode.java @@ -333,7 +333,7 @@ public final class QrCode { drawFinderPattern(3, size - 4); // Draw numerous alignment patterns - int[] alignPatPos = getAlignmentPatternPositions(version); + int[] alignPatPos = getAlignmentPatternPositions(); int numAlign = alignPatPos.length; for (int i = 0; i < numAlign; i++) { for (int j = 0; j < numAlign; j++) { @@ -644,25 +644,22 @@ public final class QrCode { /*---- Private static helper functions ----*/ - // Returns a set of positions of the alignment patterns in ascending order. These positions are - // used on both the x and y axes. Each value in the resulting array is in the range [0, 177). - // This stateless pure function could be implemented as table of 40 variable-length lists of unsigned bytes. - private static int[] getAlignmentPatternPositions(int ver) { - if (ver < MIN_VERSION || ver > MAX_VERSION) - throw new IllegalArgumentException("Version number out of range"); - else if (ver == 1) + // Returns an ascending list of positions of alignment patterns for this version number. + // Each position is in the range [0,177), and are used on both the x and y axes. + // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. + private int[] getAlignmentPatternPositions() { + if (version == 1) return new int[]{}; else { - int numAlign = ver / 7 + 2; + int numAlign = version / 7 + 2; int step; - if (ver == 32) // Special snowflake + if (version == 32) // Special snowflake step = 26; else // step = ceil[(size - 13) / (numAlign*2 - 2)] * 2 - step = (ver*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2; - + step = (version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2; int[] result = new int[numAlign]; result[0] = 6; - for (int i = result.length - 1, pos = ver * 4 + 10; i >= 1; i--, pos -= step) + for (int i = result.length - 1, pos = size - 7; i >= 1; i--, pos -= step) result[i] = pos; return result; } diff --git a/javascript/qrcodegen.js b/javascript/qrcodegen.js index b2f6e34..f328298 100644 --- a/javascript/qrcodegen.js +++ b/javascript/qrcodegen.js @@ -203,7 +203,7 @@ var qrcodegen = new function() { drawFinderPattern(3, size - 4); // Draw numerous alignment patterns - var alignPatPos = QrCode.getAlignmentPatternPositions(version); + var alignPatPos = getAlignmentPatternPositions(); var numAlign = alignPatPos.length; for (var i = 0; i < numAlign; i++) { for (var j = 0; j < numAlign; j++) { @@ -488,6 +488,24 @@ var qrcodegen = new function() { } + // Returns an ascending list of positions of alignment patterns for this version number. + // Each position is in the range [0,177), and are used on both the x and y axes. + // This could be implemented as lookup table of 40 variable-length lists of integers. + function getAlignmentPatternPositions() { + if (version == 1) + return []; + else { + var numAlign = Math.floor(version / 7) + 2; + var step = (version == 32) ? 26 : + Math.ceil((size - 13) / (numAlign*2 - 2)) * 2; + var result = [6]; + for (var i = 0, pos = size - 7; i < numAlign - 1; i++, pos -= step) + result.splice(1, 0, pos); + return result; + } + } + + // Returns true iff the i'th bit of x is set to 1. function getBit(x, i) { return ((x >>> i) & 1) != 0; @@ -597,28 +615,6 @@ var qrcodegen = new function() { var QrCode = {}; // Private object to assign properties to. Not the same object as 'this.QrCode'. - // Returns a sequence of positions of the alignment patterns in ascending order. These positions are - // used on both the x and y axes. Each value in the resulting sequence is in the range [0, 177). - // This stateless pure function could be implemented as table of 40 variable-length lists of integers. - QrCode.getAlignmentPatternPositions = function(ver) { - if (ver < MIN_VERSION || ver > MAX_VERSION) - throw "Version number out of range"; - else if (ver == 1) - return []; - else { - var size = ver * 4 + 17; - var numAlign = Math.floor(ver / 7) + 2; - var step = (ver == 32) ? 26 : - Math.ceil((size - 13) / (numAlign*2 - 2)) * 2; - - var result = [6]; - for (var i = 0, pos = size - 7; i < numAlign - 1; i++, pos -= step) - result.splice(1, 0, pos); - return result; - } - }; - - // Returns the number of data bits that can be stored in a QR Code of the given version number, after // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. diff --git a/python/qrcodegen.py b/python/qrcodegen.py index 49cffd4..8865923 100644 --- a/python/qrcodegen.py +++ b/python/qrcodegen.py @@ -256,7 +256,7 @@ class QrCode(object): self._draw_finder_pattern(3, self._size - 4) # Draw numerous alignment patterns - alignpatpos = QrCode._get_alignment_pattern_positions(self._version) + alignpatpos = self._get_alignment_pattern_positions() numalign = len(alignpatpos) skips = ((0, 0), (0, numalign - 1), (numalign - 1, 0)) for i in range(numalign): @@ -486,21 +486,18 @@ class QrCode(object): # ---- Private static helper functions ---- - @staticmethod - def _get_alignment_pattern_positions(ver): - """Returns a sequence of positions of the alignment patterns in ascending order. These positions are - used on both the x and y axes. Each value in the resulting sequence is in the range [0, 177). - This stateless pure function could be implemented as table of 40 variable-length lists of integers.""" - if not (QrCode.MIN_VERSION <= ver <= QrCode.MAX_VERSION): - raise ValueError("Version number out of range") - elif ver == 1: + def _get_alignment_pattern_positions(self): + """Returns an ascending list of positions of alignment patterns for this version number. + Each position is in the range [0,177), and are used on both the x and y axes. + This could be implemented as lookup table of 40 variable-length lists of integers.""" + ver = self._version + if ver == 1: return [] else: numalign = ver // 7 + 2 step = 26 if (ver == 32) else \ (ver*4 + numalign*2 + 1) // (numalign*2 - 2) * 2 - start = ver * 4 + 10 - result = [(start - i * step) for i in range(numalign - 1)] + [6] + result = [(self._size - 7 - i * step) for i in range(numalign - 1)] + [6] return list(reversed(result)) diff --git a/rust/src/lib.rs b/rust/src/lib.rs index a3f651b..eec747b 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -288,7 +288,7 @@ impl QrCode { self.draw_finder_pattern(3, size - 4); // Draw numerous alignment patterns - let alignpatpos: Vec = QrCode::get_alignment_pattern_positions(self.version); + let alignpatpos: Vec = self.get_alignment_pattern_positions(); let numalign: usize = alignpatpos.len(); for i in 0 .. numalign { for j in 0 .. numalign { @@ -620,19 +620,19 @@ impl QrCode { /*---- Private static helper functions ----*/ - // Returns a set of positions of the alignment patterns in ascending order. These positions are - // used on both the x and y axes. Each value in the resulting list is in the range [0, 177). - // This stateless pure function could be implemented as table of 40 variable-length lists of unsigned bytes. - fn get_alignment_pattern_positions(ver: Version) -> Vec { - let ver = ver.value(); + // Returns an ascending list of positions of alignment patterns for this version number. + // Each position is in the range [0,177), and are used on both the x and y axes. + // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. + fn get_alignment_pattern_positions(&self) -> Vec { + let ver = self.version.value(); if ver == 1 { vec![] } else { let numalign: i32 = (ver as i32) / 7 + 2; let step: i32 = if ver == 32 { 26 } else {((ver as i32)*4 + numalign*2 + 1) / (numalign*2 - 2) * 2}; - let start = (ver as i32) * 4 + 10; - let mut result: Vec = (0 .. numalign - 1).map(|i| start - i * step).collect(); + let mut result: Vec = (0 .. numalign - 1).map( + |i| self.size - 7 - i * step).collect(); result.push(6); result.reverse(); result diff --git a/typescript/qrcodegen.ts b/typescript/qrcodegen.ts index 08205b4..108d30e 100644 --- a/typescript/qrcodegen.ts +++ b/typescript/qrcodegen.ts @@ -270,7 +270,7 @@ namespace qrcodegen { this.drawFinderPattern(3, this.size - 4); // Draw numerous alignment patterns - let alignPatPos: Array = QrCode.getAlignmentPatternPositions(this.version); + let alignPatPos: Array = this.getAlignmentPatternPositions(); let numAlign: int = alignPatPos.length; for (let i = 0; i < numAlign; i++) { for (let j = 0; j < numAlign; j++) { @@ -560,22 +560,18 @@ namespace qrcodegen { /*-- Private static helper functions QrCode --*/ - // Returns a sequence of positions of the alignment patterns in ascending order. These positions are - // used on both the x and y axes. Each value in the resulting sequence is in the range [0, 177). - // This stateless pure function could be implemented as table of 40 variable-length lists of integers. - private static getAlignmentPatternPositions(ver: int): Array { - if (ver < QrCode.MIN_VERSION || ver > QrCode.MAX_VERSION) - throw "Version number out of range"; - else if (ver == 1) + // Returns an ascending list of positions of alignment patterns for this version number. + // Each position is in the range [0,177), and are used on both the x and y axes. + // This could be implemented as lookup table of 40 variable-length lists of integers. + private getAlignmentPatternPositions(): Array { + if (this.version == 1) return []; else { - let size: int = ver * 4 + 17; - let numAlign: int = Math.floor(ver / 7) + 2; - let step: int = (ver == 32) ? 26 : - Math.ceil((size - 13) / (numAlign*2 - 2)) * 2; - + let numAlign: int = Math.floor(this.version / 7) + 2; + let step: int = (this.version == 32) ? 26 : + Math.ceil((this.size - 13) / (numAlign*2 - 2)) * 2; let result: Array = [6]; - for (let i = 0, pos = size - 7; i < numAlign - 1; i++, pos -= step) + for (let i = 0, pos = this.size - 7; i < numAlign - 1; i++, pos -= step) result.splice(1, 0, pos); return result; }