/*
|
* Copyright 2013 ZXing authors
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
|
#import "ZXDataMatrixDefaultPlacement.h"
|
|
@implementation ZXDataMatrixDefaultPlacement
|
|
- (id)initWithCodewords:(NSString *)codewords numcols:(int)numcols numrows:(int)numrows {
|
if (self = [super init]) {
|
_codewords = [codewords copy];
|
_numcols = numcols;
|
_numrows = numrows;
|
_bitsLen = numcols * numrows;
|
_bits = (int8_t *)malloc(_bitsLen * sizeof(int8_t));
|
memset(_bits, -1, _bitsLen); //Initialize with "not set" value
|
}
|
|
return self;
|
}
|
|
- (void)dealloc {
|
if (_bits != NULL) {
|
free(_bits);
|
_bits = NULL;
|
}
|
}
|
|
- (BOOL)bitAtCol:(int)col row:(int)row {
|
return self.bits[row * self.numcols + col] == 1;
|
}
|
|
- (void)setBitAtCol:(int)col row:(int)row bit:(BOOL)bit {
|
self.bits[row * self.numcols + col] = bit ? (int8_t) 1 : (int8_t) 0;
|
}
|
|
- (BOOL)hasBitAtCol:(int)col row:(int)row {
|
return self.bits[row * self.numcols + col] >= 0;
|
}
|
|
- (void)place {
|
int pos = 0;
|
int row = 4;
|
int col = 0;
|
|
do {
|
/* repeatedly first check for one of the special corner cases, then... */
|
if ((row == self.numrows) && (col == 0)) {
|
[self corner1:pos++];
|
}
|
if ((row == self.numrows - 2) && (col == 0) && ((self.numcols % 4) != 0)) {
|
[self corner2:pos++];
|
}
|
if ((row == self.numrows - 2) && (col == 0) && (self.numcols % 8 == 4)) {
|
[self corner3:pos++];
|
}
|
if ((row == self.numrows + 4) && (col == 2) && ((self.numcols % 8) == 0)) {
|
[self corner4:pos++];
|
}
|
/* sweep upward diagonally, inserting successive characters... */
|
do {
|
if ((row < self.numrows) && (col >= 0) && ![self hasBitAtCol:col row:row]) {
|
[self utahAtRow:row col:col pos:pos++];
|
}
|
row -= 2;
|
col += 2;
|
} while (row >= 0 && (col < self.numcols));
|
row++;
|
col += 3;
|
|
/* and then sweep downward diagonally, inserting successive characters, ... */
|
do {
|
if ((row >= 0) && (col < self.numcols) && ![self hasBitAtCol:col row:row]) {
|
[self utahAtRow:row col:col pos:pos++];
|
}
|
row += 2;
|
col -= 2;
|
} while ((row < self.numrows) && (col >= 0));
|
row += 3;
|
col++;
|
|
/* ...until the entire array is scanned */
|
} while ((row < self.numrows) || (col < self.numcols));
|
|
/* Lastly, if the lower righthand corner is untouched, fill in fixed pattern */
|
if (![self hasBitAtCol:self.numcols - 1 row:self.numrows - 1]) {
|
[self setBitAtCol:self.numcols - 1 row:self.numrows - 1 bit:YES];
|
[self setBitAtCol:self.numcols - 2 row:self.numrows - 2 bit:YES];
|
}
|
}
|
|
- (void)moduleAtRow:(int)row col:(int)col pos:(int)pos bit:(int)bit {
|
if (row < 0) {
|
row += self.numrows;
|
col += 4 - ((self.numrows + 4) % 8);
|
}
|
if (col < 0) {
|
col += self.numcols;
|
row += 4 - ((self.numcols + 4) % 8);
|
}
|
// Note the conversion:
|
int v = [self.codewords characterAtIndex:pos];
|
v &= 1 << (8 - bit);
|
[self setBitAtCol:col row:row bit:v != 0];
|
}
|
|
/**
|
* Places the 8 bits of a utah-shaped symbol character in ECC200.
|
*
|
* @param row the row
|
* @param col the column
|
* @param pos character position
|
*/
|
- (void)utahAtRow:(int)row col:(int)col pos:(int)pos {
|
[self moduleAtRow:row - 2 col:col - 2 pos:pos bit:1];
|
[self moduleAtRow:row - 2 col:col - 1 pos:pos bit:2];
|
[self moduleAtRow:row - 1 col:col - 2 pos:pos bit:3];
|
[self moduleAtRow:row - 1 col:col - 1 pos:pos bit:4];
|
[self moduleAtRow:row - 1 col:col pos:pos bit:5];
|
[self moduleAtRow:row col:col - 2 pos:pos bit:6];
|
[self moduleAtRow:row col:col - 1 pos:pos bit:7];
|
[self moduleAtRow:row col:col pos:pos bit:8];
|
}
|
|
- (void)corner1:(int)pos {
|
[self moduleAtRow:self.numrows - 1 col:0 pos:pos bit:1];
|
[self moduleAtRow:self.numrows - 1 col:1 pos:pos bit:2];
|
[self moduleAtRow:self.numrows - 1 col:2 pos:pos bit:3];
|
[self moduleAtRow:0 col:self.numcols - 2 pos:pos bit:4];
|
[self moduleAtRow:0 col:self.numcols - 1 pos:pos bit:5];
|
[self moduleAtRow:1 col:self.numcols - 1 pos:pos bit:6];
|
[self moduleAtRow:2 col:self.numcols - 1 pos:pos bit:7];
|
[self moduleAtRow:3 col:self.numcols - 1 pos:pos bit:8];
|
}
|
|
- (void)corner2:(int)pos {
|
[self moduleAtRow:self.numrows - 3 col:0 pos:pos bit:1];
|
[self moduleAtRow:self.numrows - 2 col:0 pos:pos bit:2];
|
[self moduleAtRow:self.numrows - 1 col:0 pos:pos bit:3];
|
[self moduleAtRow:0 col:self.numcols - 4 pos:pos bit:4];
|
[self moduleAtRow:0 col:self.numcols - 3 pos:pos bit:5];
|
[self moduleAtRow:0 col:self.numcols - 2 pos:pos bit:6];
|
[self moduleAtRow:0 col:self.numcols - 1 pos:pos bit:7];
|
[self moduleAtRow:1 col:self.numcols - 1 pos:pos bit:8];
|
}
|
|
- (void)corner3:(int)pos {
|
[self moduleAtRow:self.numrows - 3 col:0 pos:pos bit:1];
|
[self moduleAtRow:self.numrows - 2 col:0 pos:pos bit:2];
|
[self moduleAtRow:self.numrows - 1 col:0 pos:pos bit:3];
|
[self moduleAtRow:0 col:self.numcols - 2 pos:pos bit:4];
|
[self moduleAtRow:0 col:self.numcols - 1 pos:pos bit:5];
|
[self moduleAtRow:1 col:self.numcols - 1 pos:pos bit:6];
|
[self moduleAtRow:2 col:self.numcols - 1 pos:pos bit:7];
|
[self moduleAtRow:3 col:self.numcols - 1 pos:pos bit:8];
|
}
|
|
- (void)corner4:(int)pos {
|
[self moduleAtRow:self.numrows - 1 col:0 pos:pos bit:1];
|
[self moduleAtRow:self.numrows - 1 col:self.numcols - 1 pos:pos bit:2];
|
[self moduleAtRow:0 col:self.numcols - 3 pos:pos bit:3];
|
[self moduleAtRow:0 col:self.numcols - 2 pos:pos bit:4];
|
[self moduleAtRow:0 col:self.numcols - 1 pos:pos bit:5];
|
[self moduleAtRow:1 col:self.numcols - 3 pos:pos bit:6];
|
[self moduleAtRow:1 col:self.numcols - 2 pos:pos bit:7];
|
[self moduleAtRow:1 col:self.numcols - 1 pos:pos bit:8];
|
}
|
|
@end
|