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,
// 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;

View File

@ -205,7 +205,7 @@ void QrCode::drawFunctionPatterns() {
drawFinderPattern(3, size - 4);
// Draw numerous alignment patterns
const vector<int> alignPatPos = getAlignmentPatternPositions(version);
const vector<int> 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<int> 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<int> QrCode::getAlignmentPatternPositions() const {
if (version == 1)
return vector<int>();
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<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(), 6);
return result;

View File

@ -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<int> 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<int> getAlignmentPatternPositions() const;
// 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);
// 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;
}

View File

@ -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.

View File

@ -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))

View File

@ -288,7 +288,7 @@ impl QrCode {
self.draw_finder_pattern(3, size - 4);
// 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();
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<i32> {
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<i32> {
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<i32> = (0 .. numalign - 1).map(|i| start - i * step).collect();
let mut result: Vec<i32> = (0 .. numalign - 1).map(
|i| self.size - 7 - i * step).collect();
result.push(6);
result.reverse();
result

View File

@ -270,7 +270,7 @@ namespace qrcodegen {
this.drawFinderPattern(3, this.size - 4);
// Draw numerous alignment patterns
let alignPatPos: Array<int> = QrCode.getAlignmentPatternPositions(this.version);
let alignPatPos: Array<int> = 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<int> {
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<int> {
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<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);
return result;
}