123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- /*
- * Copyright 2012 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 "ZXBoolArray.h"
- #import "ZXCodaBarReader.h"
- #import "ZXCodaBarWriter.h"
-
- const unichar ZX_CODA_START_END_CHARS[] = {'A', 'B', 'C', 'D'};
- const unichar ZX_CODA_ALT_START_END_CHARS[] = {'T', 'N', '*', 'E'};
- const unichar ZX_CHARS_WHICH_ARE_TEN_LENGTH_EACH_AFTER_DECODED[] = {'/', ':', '+', '.'};
- static unichar ZX_CODA_DEFAULT_GUARD;
-
- @implementation ZXCodaBarWriter
-
- + (void)initialize {
- if ([self class] != [ZXCodaBarWriter class]) return;
-
- ZX_CODA_DEFAULT_GUARD = ZX_CODA_START_END_CHARS[0];
- }
-
- - (ZXBoolArray *)encode:(NSString *)contents {
- if ([contents length] < 2) {
- // Can't have a start/end guard, so tentatively add default guards
- contents = [NSString stringWithFormat:@"%C%@%C", ZX_CODA_DEFAULT_GUARD, contents, ZX_CODA_DEFAULT_GUARD];
- } else {
- // Verify input and calculate decoded length.
- unichar firstChar = [[contents uppercaseString] characterAtIndex:0];
- unichar lastChar = [[contents uppercaseString] characterAtIndex:contents.length - 1];
- BOOL startsNormal = [ZXCodaBarReader arrayContains:ZX_CODA_START_END_CHARS length:sizeof(ZX_CODA_START_END_CHARS) / sizeof(unichar) key:firstChar];
- BOOL endsNormal = [ZXCodaBarReader arrayContains:ZX_CODA_START_END_CHARS length:sizeof(ZX_CODA_START_END_CHARS) / sizeof(unichar) key:lastChar];
- BOOL startsAlt = [ZXCodaBarReader arrayContains:ZX_CODA_ALT_START_END_CHARS length:sizeof(ZX_CODA_ALT_START_END_CHARS) / sizeof(unichar) key:firstChar];
- BOOL endsAlt = [ZXCodaBarReader arrayContains:ZX_CODA_ALT_START_END_CHARS length:sizeof(ZX_CODA_ALT_START_END_CHARS) / sizeof(unichar) key:lastChar];
- if (startsNormal) {
- if (!endsNormal) {
- @throw [NSException exceptionWithName:NSInvalidArgumentException
- reason:[NSString stringWithFormat:@"Invalid start/end guards: %@", contents]
- userInfo:nil];
- }
- // else already has valid start/end
- } else if (startsAlt) {
- if (!endsAlt) {
- @throw [NSException exceptionWithName:NSInvalidArgumentException
- reason:[NSString stringWithFormat:@"Invalid start/end guards: %@", contents]
- userInfo:nil];
- }
- // else already has valid start/end
- } else {
- // Doesn't start with a guard
- if (endsNormal || endsAlt) {
- @throw [NSException exceptionWithName:NSInvalidArgumentException
- reason:[NSString stringWithFormat:@"Invalid start/end guards: %@", contents]
- userInfo:nil];
- }
- // else doesn't end with guard either, so add a default
- contents = [NSString stringWithFormat:@"%C%@%C", ZX_CODA_DEFAULT_GUARD, contents, ZX_CODA_DEFAULT_GUARD];
- }
- }
-
- // The start character and the end character are decoded to 10 length each.
- int resultLength = 20;
- for (int i = 1; i < contents.length - 1; i++) {
- if (([contents characterAtIndex:i] >= '0' && [contents characterAtIndex:i] <= '9') ||
- [contents characterAtIndex:i] == '-' || [contents characterAtIndex:i] == '$') {
- resultLength += 9;
- } else if ([ZXCodaBarReader arrayContains:ZX_CHARS_WHICH_ARE_TEN_LENGTH_EACH_AFTER_DECODED length:4 key:[contents characterAtIndex:i]]) {
- resultLength += 10;
- } else {
- @throw [NSException exceptionWithName:NSInvalidArgumentException
- reason:[NSString stringWithFormat:@"Cannot encode : '%C'", [contents characterAtIndex:i]]
- userInfo:nil];
- }
- }
- // A blank is placed between each character.
- resultLength += contents.length - 1;
-
- ZXBoolArray *result = [[ZXBoolArray alloc] initWithLength:resultLength];
- int position = 0;
- for (int index = 0; index < contents.length; index++) {
- unichar c = [[contents uppercaseString] characterAtIndex:index];
- if (index == 0 || index == contents.length - 1) {
- // The start/end chars are not in the CodaBarReader.ALPHABET.
- switch (c) {
- case 'T':
- c = 'A';
- break;
- case 'N':
- c = 'B';
- break;
- case '*':
- c = 'C';
- break;
- case 'E':
- c = 'D';
- break;
- }
- }
- int code = 0;
- for (int i = 0; i < ZX_CODA_ALPHABET_LEN; i++) {
- // Found any, because I checked above.
- if (c == ZX_CODA_ALPHABET[i]) {
- code = ZX_CODA_CHARACTER_ENCODINGS[i];
- break;
- }
- }
- BOOL color = YES;
- int counter = 0;
- int bit = 0;
- while (bit < 7) { // A character consists of 7 digit.
- result.array[position] = color;
- position++;
- if (((code >> (6 - bit)) & 1) == 0 || counter == 1) {
- color = !color; // Flip the color.
- bit++;
- counter = 0;
- } else {
- counter++;
- }
- }
- if (index < contents.length - 1) {
- result.array[position] = NO;
- position++;
- }
- }
- return result;
- }
-
- @end
|