Changed QrCode.getAlignmentPatternPositions() from static function to instance method, tweaked its logic, and updated comment - in all languages but differently in each.

This commit is contained in:
Project Nayuki 2018-08-28 19:10:47 +00:00
parent 565f1d7481
commit 4ede209d9a
8 changed files with 70 additions and 85 deletions

View File

@ -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, // Calculates and stores an ascending list of positions of alignment patterns
// storing them to the given array and returning an array length in the range [0, 7]. // 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]) { testable int getAlignmentPatternPositions(int version, uint8_t result[7]) {
if (version == 1) if (version == 1)
return 0; return 0;

View File

@ -205,7 +205,7 @@ void QrCode::drawFunctionPatterns() {
drawFinderPattern(3, size - 4); drawFinderPattern(3, size - 4);
// Draw numerous alignment patterns // Draw numerous alignment patterns
const vector<int> alignPatPos = getAlignmentPatternPositions(version); const vector<int> alignPatPos = getAlignmentPatternPositions();
int numAlign = alignPatPos.size(); int numAlign = alignPatPos.size();
for (int i = 0; i < numAlign; i++) { for (int i = 0; i < numAlign; i++) {
for (int j = 0; j < numAlign; j++) { for (int j = 0; j < numAlign; j++) {
@ -495,18 +495,15 @@ long QrCode::getPenaltyScore() const {
} }
vector<int> QrCode::getAlignmentPatternPositions(int ver) { vector<int> QrCode::getAlignmentPatternPositions() const {
if (ver < MIN_VERSION || ver > MAX_VERSION) if (version == 1)
throw std::domain_error("Version number out of range");
else if (ver == 1)
return vector<int>(); return vector<int>();
else { else {
int numAlign = ver / 7 + 2; int numAlign = version / 7 + 2;
int step = (ver == 32) ? 26 : int step = (version == 32) ? 26 :
(ver*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2; (version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2;
vector<int> result; vector<int> 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(), pos);
result.insert(result.begin(), 6); result.insert(result.begin(), 6);
return result; return result;

View File

@ -231,10 +231,10 @@ class QrCode final {
/*---- Private static helper functions ----*/ /*---- Private static helper functions ----*/
// Returns a set of positions of the alignment patterns in ascending order. These positions are // Returns an ascending list of positions of alignment patterns for this version number.
// used on both the x and y axes. Each value in the resulting array is in the range [0, 177). // Each position is in the range [0,177), and are used on both the x and y axes.
// This stateless pure function could be implemented as table of 40 variable-length lists of unsigned bytes. // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes.
private: static std::vector<int> getAlignmentPatternPositions(int ver); private: std::vector<int> getAlignmentPatternPositions() const;
// Returns the number of data bits that can be stored in a QR Code of the given version number, after // Returns the number of data bits that can be stored in a QR Code of the given version number, after

View File

@ -333,7 +333,7 @@ public final class QrCode {
drawFinderPattern(3, size - 4); drawFinderPattern(3, size - 4);
// Draw numerous alignment patterns // Draw numerous alignment patterns
int[] alignPatPos = getAlignmentPatternPositions(version); int[] alignPatPos = getAlignmentPatternPositions();
int numAlign = alignPatPos.length; int numAlign = alignPatPos.length;
for (int i = 0; i < numAlign; i++) { for (int i = 0; i < numAlign; i++) {
for (int j = 0; j < numAlign; j++) { for (int j = 0; j < numAlign; j++) {
@ -644,25 +644,22 @@ public final class QrCode {
/*---- Private static helper functions ----*/ /*---- Private static helper functions ----*/
// Returns a set of positions of the alignment patterns in ascending order. These positions are // Returns an ascending list of positions of alignment patterns for this version number.
// used on both the x and y axes. Each value in the resulting array is in the range [0, 177). // Each position is in the range [0,177), and are used on both the x and y axes.
// This stateless pure function could be implemented as table of 40 variable-length lists of unsigned bytes. // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes.
private static int[] getAlignmentPatternPositions(int ver) { private int[] getAlignmentPatternPositions() {
if (ver < MIN_VERSION || ver > MAX_VERSION) if (version == 1)
throw new IllegalArgumentException("Version number out of range");
else if (ver == 1)
return new int[]{}; return new int[]{};
else { else {
int numAlign = ver / 7 + 2; int numAlign = version / 7 + 2;
int step; int step;
if (ver == 32) // Special snowflake if (version == 32) // Special snowflake
step = 26; step = 26;
else // step = ceil[(size - 13) / (numAlign*2 - 2)] * 2 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]; int[] result = new int[numAlign];
result[0] = 6; 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; result[i] = pos;
return result; return result;
} }

View File

@ -203,7 +203,7 @@ var qrcodegen = new function() {
drawFinderPattern(3, size - 4); drawFinderPattern(3, size - 4);
// Draw numerous alignment patterns // Draw numerous alignment patterns
var alignPatPos = QrCode.getAlignmentPatternPositions(version); var alignPatPos = getAlignmentPatternPositions();
var numAlign = alignPatPos.length; var numAlign = alignPatPos.length;
for (var i = 0; i < numAlign; i++) { for (var i = 0; i < numAlign; i++) {
for (var j = 0; j < numAlign; j++) { 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. // Returns true iff the i'th bit of x is set to 1.
function getBit(x, i) { function getBit(x, i) {
return ((x >>> i) & 1) != 0; 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'. 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 // 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. // 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. // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.

View File

@ -256,7 +256,7 @@ class QrCode(object):
self._draw_finder_pattern(3, self._size - 4) self._draw_finder_pattern(3, self._size - 4)
# Draw numerous alignment patterns # Draw numerous alignment patterns
alignpatpos = QrCode._get_alignment_pattern_positions(self._version) alignpatpos = self._get_alignment_pattern_positions()
numalign = len(alignpatpos) numalign = len(alignpatpos)
skips = ((0, 0), (0, numalign - 1), (numalign - 1, 0)) skips = ((0, 0), (0, numalign - 1), (numalign - 1, 0))
for i in range(numalign): for i in range(numalign):
@ -486,21 +486,18 @@ class QrCode(object):
# ---- Private static helper functions ---- # ---- Private static helper functions ----
@staticmethod def _get_alignment_pattern_positions(self):
def _get_alignment_pattern_positions(ver): """Returns an ascending list of positions of alignment patterns for this version number.
"""Returns a sequence of positions of the alignment patterns in ascending order. These positions are Each position is in the range [0,177), and are used on both the x and y axes.
used on both the x and y axes. Each value in the resulting sequence is in the range [0, 177). This could be implemented as lookup table of 40 variable-length lists of integers."""
This stateless pure function could be implemented as table of 40 variable-length lists of integers.""" ver = self._version
if not (QrCode.MIN_VERSION <= ver <= QrCode.MAX_VERSION): if ver == 1:
raise ValueError("Version number out of range")
elif ver == 1:
return [] return []
else: else:
numalign = ver // 7 + 2 numalign = ver // 7 + 2
step = 26 if (ver == 32) else \ step = 26 if (ver == 32) else \
(ver*4 + numalign*2 + 1) // (numalign*2 - 2) * 2 (ver*4 + numalign*2 + 1) // (numalign*2 - 2) * 2
start = ver * 4 + 10 result = [(self._size - 7 - i * step) for i in range(numalign - 1)] + [6]
result = [(start - i * step) for i in range(numalign - 1)] + [6]
return list(reversed(result)) return list(reversed(result))

View File

@ -288,7 +288,7 @@ impl QrCode {
self.draw_finder_pattern(3, size - 4); self.draw_finder_pattern(3, size - 4);
// Draw numerous alignment patterns // Draw numerous alignment patterns
let alignpatpos: Vec<i32> = QrCode::get_alignment_pattern_positions(self.version); let alignpatpos: Vec<i32> = self.get_alignment_pattern_positions();
let numalign: usize = alignpatpos.len(); let numalign: usize = alignpatpos.len();
for i in 0 .. numalign { for i in 0 .. numalign {
for j in 0 .. numalign { for j in 0 .. numalign {
@ -620,19 +620,19 @@ impl QrCode {
/*---- Private static helper functions ----*/ /*---- Private static helper functions ----*/
// Returns a set of positions of the alignment patterns in ascending order. These positions are // Returns an ascending list of positions of alignment patterns for this version number.
// used on both the x and y axes. Each value in the resulting list is in the range [0, 177). // Each position is in the range [0,177), and are used on both the x and y axes.
// This stateless pure function could be implemented as table of 40 variable-length lists of unsigned bytes. // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes.
fn get_alignment_pattern_positions(ver: Version) -> Vec<i32> { fn get_alignment_pattern_positions(&self) -> Vec<i32> {
let ver = ver.value(); let ver = self.version.value();
if ver == 1 { if ver == 1 {
vec![] vec![]
} else { } else {
let numalign: i32 = (ver as i32) / 7 + 2; let numalign: i32 = (ver as i32) / 7 + 2;
let step: i32 = if ver == 32 { 26 } else let step: i32 = if ver == 32 { 26 } else
{((ver as i32)*4 + numalign*2 + 1) / (numalign*2 - 2) * 2}; {((ver as i32)*4 + numalign*2 + 1) / (numalign*2 - 2) * 2};
let start = (ver as i32) * 4 + 10; let mut result: Vec<i32> = (0 .. numalign - 1).map(
let mut result: Vec<i32> = (0 .. numalign - 1).map(|i| start - i * step).collect(); |i| self.size - 7 - i * step).collect();
result.push(6); result.push(6);
result.reverse(); result.reverse();
result result

View File

@ -270,7 +270,7 @@ namespace qrcodegen {
this.drawFinderPattern(3, this.size - 4); this.drawFinderPattern(3, this.size - 4);
// Draw numerous alignment patterns // Draw numerous alignment patterns
let alignPatPos: Array<int> = QrCode.getAlignmentPatternPositions(this.version); let alignPatPos: Array<int> = this.getAlignmentPatternPositions();
let numAlign: int = alignPatPos.length; let numAlign: int = alignPatPos.length;
for (let i = 0; i < numAlign; i++) { for (let i = 0; i < numAlign; i++) {
for (let j = 0; j < numAlign; j++) { for (let j = 0; j < numAlign; j++) {
@ -560,22 +560,18 @@ namespace qrcodegen {
/*-- Private static helper functions QrCode --*/ /*-- Private static helper functions QrCode --*/
// Returns a sequence of positions of the alignment patterns in ascending order. These positions are // Returns an ascending list of positions of alignment patterns for this version number.
// used on both the x and y axes. Each value in the resulting sequence is in the range [0, 177). // Each position is in the range [0,177), and are used on both the x and y axes.
// This stateless pure function could be implemented as table of 40 variable-length lists of integers. // This could be implemented as lookup table of 40 variable-length lists of integers.
private static getAlignmentPatternPositions(ver: int): Array<int> { private getAlignmentPatternPositions(): Array<int> {
if (ver < QrCode.MIN_VERSION || ver > QrCode.MAX_VERSION) if (this.version == 1)
throw "Version number out of range";
else if (ver == 1)
return []; return [];
else { else {
let size: int = ver * 4 + 17; let numAlign: int = Math.floor(this.version / 7) + 2;
let numAlign: int = Math.floor(ver / 7) + 2; let step: int = (this.version == 32) ? 26 :
let step: int = (ver == 32) ? 26 : Math.ceil((this.size - 13) / (numAlign*2 - 2)) * 2;
Math.ceil((size - 13) / (numAlign*2 - 2)) * 2;
let result: Array<int> = [6]; let result: Array<int> = [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); result.splice(1, 0, pos);
return result; return result;
} }