Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * Copyright 2012 ZXing authors
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "ZXBoolArray.h"
  17. #import "ZXCode128Reader.h"
  18. #import "ZXCode128Writer.h"
  19. // Dummy characters used to specify control characters in input
  20. const unichar ZX_CODE128_ESCAPE_FNC_1 = L'\u00f1';
  21. const unichar ZX_CODE128_ESCAPE_FNC_2 = L'\u00f2';
  22. const unichar ZX_CODE128_ESCAPE_FNC_3 = L'\u00f3';
  23. const unichar ZX_CODE128_ESCAPE_FNC_4 = L'\u00f4';
  24. @implementation ZXCode128Writer
  25. - (ZXBitMatrix *)encode:(NSString *)contents format:(ZXBarcodeFormat)format width:(int)width height:(int)height hints:(ZXEncodeHints *)hints error:(NSError **)error {
  26. if (format != kBarcodeFormatCode128) {
  27. [NSException raise:NSInvalidArgumentException format:@"Can only encode CODE_128"];
  28. }
  29. return [super encode:contents format:format width:width height:height hints:hints error:error];
  30. }
  31. - (ZXBoolArray *)encode:(NSString *)contents {
  32. int length = (int)[contents length];
  33. // Check length
  34. if (length < 1 || length > 80) {
  35. [NSException raise:NSInvalidArgumentException format:@"Contents length should be between 1 and 80 characters, but got %d", length];
  36. }
  37. // Check content
  38. for (int i = 0; i < length; i++) {
  39. unichar c = [contents characterAtIndex:i];
  40. if (c < ' ' || c > '~') {
  41. switch (c) {
  42. case ZX_CODE128_ESCAPE_FNC_1:
  43. case ZX_CODE128_ESCAPE_FNC_2:
  44. case ZX_CODE128_ESCAPE_FNC_3:
  45. case ZX_CODE128_ESCAPE_FNC_4:
  46. break;
  47. default:
  48. [NSException raise:NSInvalidArgumentException format:@"Bad character in input: %C", c];
  49. }
  50. }
  51. }
  52. NSMutableArray *patterns = [NSMutableArray array]; // temporary storage for patterns
  53. int checkSum = 0;
  54. int checkWeight = 1;
  55. int codeSet = 0; // selected code (CODE_CODE_B or CODE_CODE_C)
  56. int position = 0; // position in contents
  57. while (position < length) {
  58. //Select code to use
  59. int requiredDigitCount = codeSet == ZX_CODE128_CODE_CODE_C ? 2 : 4;
  60. int newCodeSet;
  61. if ([self isDigits:contents start:position length:requiredDigitCount]) {
  62. newCodeSet = ZX_CODE128_CODE_CODE_C;
  63. } else {
  64. newCodeSet = ZX_CODE128_CODE_CODE_B;
  65. }
  66. //Get the pattern index
  67. int patternIndex;
  68. if (newCodeSet == codeSet) {
  69. // Encode the current character
  70. // First handle escapes
  71. switch ([contents characterAtIndex:position]) {
  72. case ZX_CODE128_ESCAPE_FNC_1:
  73. patternIndex = ZX_CODE128_CODE_FNC_1;
  74. break;
  75. case ZX_CODE128_ESCAPE_FNC_2:
  76. patternIndex = ZX_CODE128_CODE_FNC_2;
  77. break;
  78. case ZX_CODE128_ESCAPE_FNC_3:
  79. patternIndex = ZX_CODE128_CODE_FNC_3;
  80. break;
  81. case ZX_CODE128_ESCAPE_FNC_4:
  82. patternIndex = ZX_CODE128_CODE_FNC_4_B; // FIXME if this ever outputs Code A
  83. break;
  84. default:
  85. // Then handle normal characters otherwise
  86. if (codeSet == ZX_CODE128_CODE_CODE_B) {
  87. patternIndex = [contents characterAtIndex:position] - ' ';
  88. } else { // CODE_CODE_C
  89. patternIndex = [[contents substringWithRange:NSMakeRange(position, 2)] intValue];
  90. position++; // Also incremented below
  91. }
  92. }
  93. position++;
  94. } else {
  95. // Should we change the current code?
  96. // Do we have a code set?
  97. if (codeSet == 0) {
  98. // No, we don't have a code set
  99. if (newCodeSet == ZX_CODE128_CODE_CODE_B) {
  100. patternIndex = ZX_CODE128_CODE_START_B;
  101. } else {
  102. // CODE_CODE_C
  103. patternIndex = ZX_CODE128_CODE_START_C;
  104. }
  105. } else {
  106. // Yes, we have a code set
  107. patternIndex = newCodeSet;
  108. }
  109. codeSet = newCodeSet;
  110. }
  111. // Get the pattern
  112. NSMutableArray *pattern = [NSMutableArray array];
  113. for (int i = 0; i < sizeof(ZX_CODE128_CODE_PATTERNS[patternIndex]) / sizeof(int); i++) {
  114. [pattern addObject:@(ZX_CODE128_CODE_PATTERNS[patternIndex][i])];
  115. }
  116. [patterns addObject:pattern];
  117. // Compute checksum
  118. checkSum += patternIndex * checkWeight;
  119. if (position != 0) {
  120. checkWeight++;
  121. }
  122. }
  123. // Compute and append checksum
  124. checkSum %= 103;
  125. NSMutableArray *pattern = [NSMutableArray array];
  126. for (int i = 0; i < sizeof(ZX_CODE128_CODE_PATTERNS[checkSum]) / sizeof(int); i++) {
  127. [pattern addObject:@(ZX_CODE128_CODE_PATTERNS[checkSum][i])];
  128. }
  129. [patterns addObject:pattern];
  130. // Append stop code
  131. pattern = [NSMutableArray array];
  132. for (int i = 0; i < sizeof(ZX_CODE128_CODE_PATTERNS[ZX_CODE128_CODE_STOP]) / sizeof(int); i++) {
  133. [pattern addObject:@(ZX_CODE128_CODE_PATTERNS[ZX_CODE128_CODE_STOP][i])];
  134. }
  135. [patterns addObject:pattern];
  136. // Compute code width
  137. int codeWidth = 0;
  138. for (pattern in patterns) {
  139. for (int i = 0; i < pattern.count; i++) {
  140. codeWidth += [pattern[i] intValue];
  141. }
  142. }
  143. // Compute result
  144. ZXBoolArray *result = [[ZXBoolArray alloc] initWithLength:codeWidth];
  145. int pos = 0;
  146. for (NSArray *patternArray in patterns) {
  147. int patternLen = (int)[patternArray count];
  148. int pattern[patternLen];
  149. for (int i = 0; i < patternLen; i++) {
  150. pattern[i] = [patternArray[i] intValue];
  151. }
  152. pos += [self appendPattern:result pos:pos pattern:pattern patternLen:patternLen startColor:YES];
  153. }
  154. return result;
  155. }
  156. - (BOOL)isDigits:(NSString *)value start:(int)start length:(unsigned int)length {
  157. int end = start + length;
  158. int last = (int)[value length];
  159. for (int i = start; i < end && i < last; i++) {
  160. unichar c = [value characterAtIndex:i];
  161. if (c < '0' || c > '9') {
  162. if (c != ZX_CODE128_ESCAPE_FNC_1) {
  163. return NO;
  164. }
  165. end++; // ignore FNC_1
  166. }
  167. }
  168. return end <= last; // end > last if we've run out of string
  169. }
  170. @end