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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Copyright 2013 9 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 "ZXDataMatrixC40Encoder.h"
  17. #import "ZXDataMatrixEncoderContext.h"
  18. #import "ZXDataMatrixHighLevelEncoder.h"
  19. #import "ZXDataMatrixSymbolInfo.h"
  20. @implementation ZXDataMatrixC40Encoder
  21. - (int)encodingMode {
  22. return [ZXDataMatrixHighLevelEncoder c40Encodation];
  23. }
  24. - (void)encode:(ZXDataMatrixEncoderContext *)context {
  25. //step C
  26. NSMutableString *buffer = [NSMutableString string];
  27. while ([context hasMoreCharacters]) {
  28. unichar c = [context currentChar];
  29. context.pos++;
  30. int lastCharSize = [self encodeChar:c buffer:buffer];
  31. int unwritten = ((int)buffer.length / 3) * 2;
  32. int curCodewordCount = context.codewordCount + unwritten;
  33. [context updateSymbolInfoWithLength:curCodewordCount];
  34. int available = context.symbolInfo.dataCapacity - curCodewordCount;
  35. if (![context hasMoreCharacters]) {
  36. //Avoid having a single C40 value in the last triplet
  37. NSMutableString *removed = [NSMutableString string];
  38. if ((buffer.length % 3) == 2) {
  39. if (available < 2 || available > 2) {
  40. lastCharSize = [self backtrackOneCharacter:context buffer:buffer removed:removed lastCharSize:lastCharSize];
  41. }
  42. }
  43. while ((buffer.length % 3) == 1
  44. && ((lastCharSize <= 3 && available != 1) || lastCharSize > 3)) {
  45. lastCharSize = [self backtrackOneCharacter:context buffer:buffer removed:removed lastCharSize:lastCharSize];
  46. }
  47. break;
  48. }
  49. NSUInteger count = buffer.length;
  50. if ((count % 3) == 0) {
  51. int newMode = [ZXDataMatrixHighLevelEncoder lookAheadTest:context.message startpos:context.pos currentMode:[self encodingMode]];
  52. if (newMode != [self encodingMode]) {
  53. [context signalEncoderChange:newMode];
  54. break;
  55. }
  56. }
  57. }
  58. [self handleEOD:context buffer:buffer];
  59. }
  60. - (int)backtrackOneCharacter:(ZXDataMatrixEncoderContext *)context buffer:(NSMutableString *)buffer
  61. removed:(NSMutableString *)removed lastCharSize:(int)lastCharSize {
  62. NSUInteger count = buffer.length;
  63. [buffer deleteCharactersInRange:NSMakeRange(count - lastCharSize, lastCharSize)];
  64. context.pos--;
  65. unichar c = context.currentChar;
  66. lastCharSize = [self encodeChar:c buffer:removed];
  67. [context resetSymbolInfo]; //Deal with possible reduction in symbol size
  68. return lastCharSize;
  69. }
  70. - (void)writeNextTriplet:(ZXDataMatrixEncoderContext *)context buffer:(NSMutableString *)buffer {
  71. [context writeCodewords:[self encodeToCodewords:buffer startpos:0]];
  72. [buffer deleteCharactersInRange:NSMakeRange(0, 3)];
  73. }
  74. /**
  75. * Handle "end of data" situations
  76. */
  77. - (void)handleEOD:(ZXDataMatrixEncoderContext *)context buffer:(NSMutableString *)buffer {
  78. int unwritten = ((int)buffer.length / 3) * 2;
  79. int rest = buffer.length % 3;
  80. int curCodewordCount = context.codewordCount + unwritten;
  81. [context updateSymbolInfoWithLength:curCodewordCount];
  82. int available = context.symbolInfo.dataCapacity - curCodewordCount;
  83. if (rest == 2) {
  84. [buffer appendString:@"\0"]; //Shift 1
  85. while (buffer.length >= 3) {
  86. [self writeNextTriplet:context buffer:buffer];
  87. }
  88. if ([context hasMoreCharacters]) {
  89. [context writeCodeword:[ZXDataMatrixHighLevelEncoder c40Unlatch]];
  90. }
  91. } else if (available == 1 && rest == 1) {
  92. while (buffer.length >= 3) {
  93. [self writeNextTriplet:context buffer:buffer];
  94. }
  95. if ([context hasMoreCharacters]) {
  96. [context writeCodeword:[ZXDataMatrixHighLevelEncoder c40Unlatch]];
  97. }
  98. // else no latch
  99. context.pos--;
  100. } else if (rest == 0) {
  101. while (buffer.length >= 3) {
  102. [self writeNextTriplet:context buffer:buffer];
  103. }
  104. if (available > 0 || [context hasMoreCharacters]) {
  105. [context writeCodeword:[ZXDataMatrixHighLevelEncoder c40Unlatch]];
  106. }
  107. } else {
  108. @throw [NSException exceptionWithName:@"IllegalStateException"
  109. reason:@"Unexpected case. Please report!"
  110. userInfo:nil];
  111. }
  112. [context signalEncoderChange:[ZXDataMatrixHighLevelEncoder asciiEncodation]];
  113. }
  114. - (int)encodeChar:(unichar)c buffer:(NSMutableString *)sb {
  115. if (c == ' ') {
  116. [sb appendString:@"\3"];
  117. return 1;
  118. } else if (c >= '0' && c <= '9') {
  119. [sb appendFormat:@"%C", (unichar) (c - 48 + 4)];
  120. return 1;
  121. } else if (c >= 'A' && c <= 'Z') {
  122. [sb appendFormat:@"%C", (unichar) (c - 65 + 14)];
  123. return 1;
  124. } else if (c >= '\0' && c <= (unichar)0x001f) {
  125. [sb appendString:@"\0"]; //Shift 1 Set
  126. [sb appendFormat:@"%C", c];
  127. return 2;
  128. } else if (c >= '!' && c <= '/') {
  129. [sb appendString:@"\1"]; //Shift 2 Set
  130. [sb appendFormat:@"%C", (unichar) (c - 33)];
  131. return 2;
  132. } else if (c >= ':' && c <= '@') {
  133. [sb appendString:@"\1"]; //Shift 2 Set
  134. [sb appendFormat:@"%C", (unichar) (c - 58 + 15)];
  135. return 2;
  136. } else if (c >= '[' && c <= '_') {
  137. [sb appendString:@"\1"]; //Shift 2 Set
  138. [sb appendFormat:@"%C", (unichar) (c - 91 + 22)];
  139. return 2;
  140. } else if (c >= '\u0060' && c <= (unichar)0x007f) {
  141. [sb appendString:@"\2"]; //Shift 3 Set
  142. [sb appendFormat:@"%C", (unichar) (c - 96)];
  143. return 2;
  144. } else if (c >= (unichar)0x0080) {
  145. [sb appendFormat:@"\1%C", (unichar)0x001e]; //Shift 2, Upper Shift
  146. int len = 2;
  147. len += [self encodeChar:(unichar) (c - 128) buffer:sb];
  148. return len;
  149. } else {
  150. @throw [NSException exceptionWithName:@"IllegalStateException"
  151. reason:[NSString stringWithFormat:@"Illegal character: %C", c]
  152. userInfo:nil];
  153. }
  154. }
  155. - (NSString *)encodeToCodewords:(NSString *)sb startpos:(int)startPos {
  156. unichar c1 = [sb characterAtIndex:startPos];
  157. unichar c2 = [sb characterAtIndex:startPos + 1];
  158. unichar c3 = [sb characterAtIndex:startPos + 2];
  159. int v = (1600 * c1) + (40 * c2) + c3 + 1;
  160. unichar cw1 = (unichar) (v / 256);
  161. unichar cw2 = (unichar) (v % 256);
  162. return [NSString stringWithFormat:@"%C%C", cw1, cw2];
  163. }
  164. @end