/* * Copyright 2014 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 "ZXAztecHighLevelEncoder.h" #import "ZXAztecState.h" #import "ZXAztecToken.h" #import "ZXBitArray.h" #import "ZXByteArray.h" @implementation ZXAztecState - (id)initWithToken:(ZXAztecToken *)token mode:(int)mode binaryBytes:(int)binaryBytes bitCount:(int)bitCount { if (self = [super init]) { _token = token; _mode = mode; _binaryShiftByteCount = binaryBytes; _bitCount = bitCount; } return self; } + (ZXAztecState *)initialState { return [[ZXAztecState alloc] initWithToken:[ZXAztecToken empty] mode:ZX_AZTEC_MODE_UPPER binaryBytes:0 bitCount:0]; } // Create a new state representing this state with a latch to a (not // necessary different) mode, and then a code. - (ZXAztecState *)latchAndAppend:(int)mode value:(int)value { int bitCount = self.bitCount; ZXAztecToken *token = self.token; if (mode != self.mode) { int latch = ZX_AZTEC_LATCH_TABLE[self.mode][mode]; token = [token add:latch & 0xFFFF bitCount:latch >> 16]; bitCount += latch >> 16; } int latchModeBitCount = mode == ZX_AZTEC_MODE_DIGIT ? 4 : 5; token = [token add:value bitCount:latchModeBitCount]; return [[ZXAztecState alloc] initWithToken:token mode:mode binaryBytes:0 bitCount:bitCount + latchModeBitCount]; } // Create a new state representing this state, with a temporary shift // to a different mode to output a single value. - (ZXAztecState *)shiftAndAppend:(int)mode value:(int)value { //assert binaryShiftByteCount == 0 && this.mode != mode; ZXAztecToken *token = self.token; int thisModeBitCount = self.mode == ZX_AZTEC_MODE_DIGIT ? 4 : 5; // Shifts exist only to UPPER and PUNCT, both with tokens size 5. token = [token add:ZX_AZTEC_SHIFT_TABLE[self.mode][mode] bitCount:thisModeBitCount]; token = [token add:value bitCount:5]; return [[ZXAztecState alloc] initWithToken:token mode:self.mode binaryBytes:0 bitCount:self.bitCount + thisModeBitCount + 5]; } // Create a new state representing this state, but an additional character // output in Binary Shift mode. - (ZXAztecState *)addBinaryShiftChar:(int)index { ZXAztecToken *token = self.token; int mode = self.mode; int bitCount = self.bitCount; if (self.mode == ZX_AZTEC_MODE_PUNCT || self.mode == ZX_AZTEC_MODE_DIGIT) { int latch = ZX_AZTEC_LATCH_TABLE[mode][ZX_AZTEC_MODE_UPPER]; token = [token add:latch & 0xFFFF bitCount:latch >> 16]; bitCount += latch >> 16; mode = ZX_AZTEC_MODE_UPPER; } int deltaBitCount = (self.binaryShiftByteCount == 0 || self.binaryShiftByteCount == 31) ? 18 : (self.binaryShiftByteCount == 62) ? 9 : 8; ZXAztecState *result = [[ZXAztecState alloc] initWithToken:token mode:mode binaryBytes:self.binaryShiftByteCount + 1 bitCount:bitCount + deltaBitCount]; if (result.binaryShiftByteCount == 2047 + 31) { // The string is as long as it's allowed to be. We should end it. result = [result endBinaryShift:index + 1]; } return result; } // Create the state identical to this one, but we are no longer in // Binary Shift mode. - (ZXAztecState *)endBinaryShift:(int)index { if (self.binaryShiftByteCount == 0) { return self; } ZXAztecToken *token = self.token; token = [token addBinaryShift:index - self.binaryShiftByteCount byteCount:self.binaryShiftByteCount]; return [[ZXAztecState alloc] initWithToken:token mode:self.mode binaryBytes:0 bitCount:self.bitCount]; } // Returns true if "this" state is better (or equal) to be in than "that" // state under all possible circumstances. - (BOOL)isBetterThanOrEqualTo:(ZXAztecState *)other { int mySize = self.bitCount + (ZX_AZTEC_LATCH_TABLE[self.mode][other.mode] >> 16); if (other.binaryShiftByteCount > 0 && (self.binaryShiftByteCount == 0 || self.binaryShiftByteCount > other.binaryShiftByteCount)) { mySize += 10; // Cost of entering Binary Shift mode. } return mySize <= other.bitCount; } - (ZXBitArray *)toBitArray:(ZXByteArray *)text { // Reverse the tokens, so that they are in the order that they should // be output NSMutableArray *symbols = [NSMutableArray array]; for (ZXAztecToken *token = [self endBinaryShift:text.length].token; token != nil; token = token.previous) { [symbols insertObject:token atIndex:0]; } ZXBitArray *bitArray = [[ZXBitArray alloc] init]; // Add each token to the result. for (ZXAztecToken *symbol in symbols) { [symbol appendTo:bitArray text:text]; } return bitArray; } - (NSString *)description { return [NSString stringWithFormat:@"%@ bits=%d bytes=%d", ZX_AZTEC_MODE_NAMES[self.mode], self.bitCount, self.binaryShiftByteCount]; } @end