123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- /*
- * 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 "ZXCode128Reader.h"
- #import "ZXCode128Writer.h"
-
- // Dummy characters used to specify control characters in input
- const unichar ZX_CODE128_ESCAPE_FNC_1 = L'\u00f1';
- const unichar ZX_CODE128_ESCAPE_FNC_2 = L'\u00f2';
- const unichar ZX_CODE128_ESCAPE_FNC_3 = L'\u00f3';
- const unichar ZX_CODE128_ESCAPE_FNC_4 = L'\u00f4';
-
- @implementation ZXCode128Writer
-
- - (ZXBitMatrix *)encode:(NSString *)contents format:(ZXBarcodeFormat)format width:(int)width height:(int)height hints:(ZXEncodeHints *)hints error:(NSError **)error {
- if (format != kBarcodeFormatCode128) {
- [NSException raise:NSInvalidArgumentException format:@"Can only encode CODE_128"];
- }
- return [super encode:contents format:format width:width height:height hints:hints error:error];
- }
-
- - (ZXBoolArray *)encode:(NSString *)contents {
- int length = (int)[contents length];
- // Check length
- if (length < 1 || length > 80) {
- [NSException raise:NSInvalidArgumentException format:@"Contents length should be between 1 and 80 characters, but got %d", length];
- }
- // Check content
- for (int i = 0; i < length; i++) {
- unichar c = [contents characterAtIndex:i];
- if (c < ' ' || c > '~') {
- switch (c) {
- case ZX_CODE128_ESCAPE_FNC_1:
- case ZX_CODE128_ESCAPE_FNC_2:
- case ZX_CODE128_ESCAPE_FNC_3:
- case ZX_CODE128_ESCAPE_FNC_4:
- break;
- default:
- [NSException raise:NSInvalidArgumentException format:@"Bad character in input: %C", c];
- }
- }
- }
-
- NSMutableArray *patterns = [NSMutableArray array]; // temporary storage for patterns
- int checkSum = 0;
- int checkWeight = 1;
- int codeSet = 0; // selected code (CODE_CODE_B or CODE_CODE_C)
- int position = 0; // position in contents
-
- while (position < length) {
- //Select code to use
- int requiredDigitCount = codeSet == ZX_CODE128_CODE_CODE_C ? 2 : 4;
- int newCodeSet;
- if ([self isDigits:contents start:position length:requiredDigitCount]) {
- newCodeSet = ZX_CODE128_CODE_CODE_C;
- } else {
- newCodeSet = ZX_CODE128_CODE_CODE_B;
- }
-
- //Get the pattern index
- int patternIndex;
- if (newCodeSet == codeSet) {
- // Encode the current character
- // First handle escapes
- switch ([contents characterAtIndex:position]) {
- case ZX_CODE128_ESCAPE_FNC_1:
- patternIndex = ZX_CODE128_CODE_FNC_1;
- break;
- case ZX_CODE128_ESCAPE_FNC_2:
- patternIndex = ZX_CODE128_CODE_FNC_2;
- break;
- case ZX_CODE128_ESCAPE_FNC_3:
- patternIndex = ZX_CODE128_CODE_FNC_3;
- break;
- case ZX_CODE128_ESCAPE_FNC_4:
- patternIndex = ZX_CODE128_CODE_FNC_4_B; // FIXME if this ever outputs Code A
- break;
- default:
- // Then handle normal characters otherwise
- if (codeSet == ZX_CODE128_CODE_CODE_B) {
- patternIndex = [contents characterAtIndex:position] - ' ';
- } else { // CODE_CODE_C
- patternIndex = [[contents substringWithRange:NSMakeRange(position, 2)] intValue];
- position++; // Also incremented below
- }
- }
- position++;
- } else {
- // Should we change the current code?
- // Do we have a code set?
- if (codeSet == 0) {
- // No, we don't have a code set
- if (newCodeSet == ZX_CODE128_CODE_CODE_B) {
- patternIndex = ZX_CODE128_CODE_START_B;
- } else {
- // CODE_CODE_C
- patternIndex = ZX_CODE128_CODE_START_C;
- }
- } else {
- // Yes, we have a code set
- patternIndex = newCodeSet;
- }
- codeSet = newCodeSet;
- }
-
- // Get the pattern
- NSMutableArray *pattern = [NSMutableArray array];
- for (int i = 0; i < sizeof(ZX_CODE128_CODE_PATTERNS[patternIndex]) / sizeof(int); i++) {
- [pattern addObject:@(ZX_CODE128_CODE_PATTERNS[patternIndex][i])];
- }
- [patterns addObject:pattern];
-
- // Compute checksum
- checkSum += patternIndex * checkWeight;
- if (position != 0) {
- checkWeight++;
- }
- }
-
- // Compute and append checksum
- checkSum %= 103;
- NSMutableArray *pattern = [NSMutableArray array];
- for (int i = 0; i < sizeof(ZX_CODE128_CODE_PATTERNS[checkSum]) / sizeof(int); i++) {
- [pattern addObject:@(ZX_CODE128_CODE_PATTERNS[checkSum][i])];
- }
- [patterns addObject:pattern];
-
- // Append stop code
- pattern = [NSMutableArray array];
- for (int i = 0; i < sizeof(ZX_CODE128_CODE_PATTERNS[ZX_CODE128_CODE_STOP]) / sizeof(int); i++) {
- [pattern addObject:@(ZX_CODE128_CODE_PATTERNS[ZX_CODE128_CODE_STOP][i])];
- }
- [patterns addObject:pattern];
-
- // Compute code width
- int codeWidth = 0;
- for (pattern in patterns) {
- for (int i = 0; i < pattern.count; i++) {
- codeWidth += [pattern[i] intValue];
- }
- }
-
- // Compute result
- ZXBoolArray *result = [[ZXBoolArray alloc] initWithLength:codeWidth];
- int pos = 0;
- for (NSArray *patternArray in patterns) {
- int patternLen = (int)[patternArray count];
- int pattern[patternLen];
- for (int i = 0; i < patternLen; i++) {
- pattern[i] = [patternArray[i] intValue];
- }
-
- pos += [self appendPattern:result pos:pos pattern:pattern patternLen:patternLen startColor:YES];
- }
-
- return result;
- }
-
- - (BOOL)isDigits:(NSString *)value start:(int)start length:(unsigned int)length {
- int end = start + length;
- int last = (int)[value length];
- for (int i = start; i < end && i < last; i++) {
- unichar c = [value characterAtIndex:i];
- if (c < '0' || c > '9') {
- if (c != ZX_CODE128_ESCAPE_FNC_1) {
- return NO;
- }
- end++; // ignore FNC_1
- }
- }
- return end <= last; // end > last if we've run out of string
- }
-
- @end
|