| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| 6 // Original code is licensed as follows: | |
| 7 /* | |
| 8 * Copyright 2008 ZXing authors | |
| 9 * | |
| 10 * Licensed under the Apache License, Version 2.0 (the "License"); | |
| 11 * you may not use this file except in compliance with the License. | |
| 12 * You may obtain a copy of the License at | |
| 13 * | |
| 14 * http://www.apache.org/licenses/LICENSE-2.0 | |
| 15 * | |
| 16 * Unless required by applicable law or agreed to in writing, software | |
| 17 * distributed under the License is distributed on an "AS IS" BASIS, | |
| 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 19 * See the License for the specific language governing permissions and | |
| 20 * limitations under the License. | |
| 21 */ | |
| 22 | |
| 23 #include <algorithm> | |
| 24 | |
| 25 #include "xfa/src/fxbarcode/BC_Reader.h" | |
| 26 #include "xfa/src/fxbarcode/common/BC_CommonBitArray.h" | |
| 27 #include "xfa/src/fxbarcode/oned/BC_OneDReader.h" | |
| 28 #include "xfa/src/fxbarcode/oned/BC_OnedCode128Reader.h" | |
| 29 #include "xfa/src/fxbarcode/utils.h" | |
| 30 | |
| 31 const int32_t CBC_OnedCode128Reader::CODE_PATTERNS[107][7] = { | |
| 32 {2, 1, 2, 2, 2, 2, 0}, {2, 2, 2, 1, 2, 2, 0}, {2, 2, 2, 2, 2, 1, 0}, | |
| 33 {1, 2, 1, 2, 2, 3, 0}, {1, 2, 1, 3, 2, 2, 0}, {1, 3, 1, 2, 2, 2, 0}, | |
| 34 {1, 2, 2, 2, 1, 3, 0}, {1, 2, 2, 3, 1, 2, 0}, {1, 3, 2, 2, 1, 2, 0}, | |
| 35 {2, 2, 1, 2, 1, 3, 0}, {2, 2, 1, 3, 1, 2, 0}, {2, 3, 1, 2, 1, 2, 0}, | |
| 36 {1, 1, 2, 2, 3, 2, 0}, {1, 2, 2, 1, 3, 2, 0}, {1, 2, 2, 2, 3, 1, 0}, | |
| 37 {1, 1, 3, 2, 2, 2, 0}, {1, 2, 3, 1, 2, 2, 0}, {1, 2, 3, 2, 2, 1, 0}, | |
| 38 {2, 2, 3, 2, 1, 1, 0}, {2, 2, 1, 1, 3, 2, 0}, {2, 2, 1, 2, 3, 1, 0}, | |
| 39 {2, 1, 3, 2, 1, 2, 0}, {2, 2, 3, 1, 1, 2, 0}, {3, 1, 2, 1, 3, 1, 0}, | |
| 40 {3, 1, 1, 2, 2, 2, 0}, {3, 2, 1, 1, 2, 2, 0}, {3, 2, 1, 2, 2, 1, 0}, | |
| 41 {3, 1, 2, 2, 1, 2, 0}, {3, 2, 2, 1, 1, 2, 0}, {3, 2, 2, 2, 1, 1, 0}, | |
| 42 {2, 1, 2, 1, 2, 3, 0}, {2, 1, 2, 3, 2, 1, 0}, {2, 3, 2, 1, 2, 1, 0}, | |
| 43 {1, 1, 1, 3, 2, 3, 0}, {1, 3, 1, 1, 2, 3, 0}, {1, 3, 1, 3, 2, 1, 0}, | |
| 44 {1, 1, 2, 3, 1, 3, 0}, {1, 3, 2, 1, 1, 3, 0}, {1, 3, 2, 3, 1, 1, 0}, | |
| 45 {2, 1, 1, 3, 1, 3, 0}, {2, 3, 1, 1, 1, 3, 0}, {2, 3, 1, 3, 1, 1, 0}, | |
| 46 {1, 1, 2, 1, 3, 3, 0}, {1, 1, 2, 3, 3, 1, 0}, {1, 3, 2, 1, 3, 1, 0}, | |
| 47 {1, 1, 3, 1, 2, 3, 0}, {1, 1, 3, 3, 2, 1, 0}, {1, 3, 3, 1, 2, 1, 0}, | |
| 48 {3, 1, 3, 1, 2, 1, 0}, {2, 1, 1, 3, 3, 1, 0}, {2, 3, 1, 1, 3, 1, 0}, | |
| 49 {2, 1, 3, 1, 1, 3, 0}, {2, 1, 3, 3, 1, 1, 0}, {2, 1, 3, 1, 3, 1, 0}, | |
| 50 {3, 1, 1, 1, 2, 3, 0}, {3, 1, 1, 3, 2, 1, 0}, {3, 3, 1, 1, 2, 1, 0}, | |
| 51 {3, 1, 2, 1, 1, 3, 0}, {3, 1, 2, 3, 1, 1, 0}, {3, 3, 2, 1, 1, 1, 0}, | |
| 52 {3, 1, 4, 1, 1, 1, 0}, {2, 2, 1, 4, 1, 1, 0}, {4, 3, 1, 1, 1, 1, 0}, | |
| 53 {1, 1, 1, 2, 2, 4, 0}, {1, 1, 1, 4, 2, 2, 0}, {1, 2, 1, 1, 2, 4, 0}, | |
| 54 {1, 2, 1, 4, 2, 1, 0}, {1, 4, 1, 1, 2, 2, 0}, {1, 4, 1, 2, 2, 1, 0}, | |
| 55 {1, 1, 2, 2, 1, 4, 0}, {1, 1, 2, 4, 1, 2, 0}, {1, 2, 2, 1, 1, 4, 0}, | |
| 56 {1, 2, 2, 4, 1, 1, 0}, {1, 4, 2, 1, 1, 2, 0}, {1, 4, 2, 2, 1, 1, 0}, | |
| 57 {2, 4, 1, 2, 1, 1, 0}, {2, 2, 1, 1, 1, 4, 0}, {4, 1, 3, 1, 1, 1, 0}, | |
| 58 {2, 4, 1, 1, 1, 2, 0}, {1, 3, 4, 1, 1, 1, 0}, {1, 1, 1, 2, 4, 2, 0}, | |
| 59 {1, 2, 1, 1, 4, 2, 0}, {1, 2, 1, 2, 4, 1, 0}, {1, 1, 4, 2, 1, 2, 0}, | |
| 60 {1, 2, 4, 1, 1, 2, 0}, {1, 2, 4, 2, 1, 1, 0}, {4, 1, 1, 2, 1, 2, 0}, | |
| 61 {4, 2, 1, 1, 1, 2, 0}, {4, 2, 1, 2, 1, 1, 0}, {2, 1, 2, 1, 4, 1, 0}, | |
| 62 {2, 1, 4, 1, 2, 1, 0}, {4, 1, 2, 1, 2, 1, 0}, {1, 1, 1, 1, 4, 3, 0}, | |
| 63 {1, 1, 1, 3, 4, 1, 0}, {1, 3, 1, 1, 4, 1, 0}, {1, 1, 4, 1, 1, 3, 0}, | |
| 64 {1, 1, 4, 3, 1, 1, 0}, {4, 1, 1, 1, 1, 3, 0}, {4, 1, 1, 3, 1, 1, 0}, | |
| 65 {1, 1, 3, 1, 4, 1, 0}, {1, 1, 4, 1, 3, 1, 0}, {3, 1, 1, 1, 4, 1, 0}, | |
| 66 {4, 1, 1, 1, 3, 1, 0}, {2, 1, 1, 4, 1, 2, 0}, {2, 1, 1, 2, 1, 4, 0}, | |
| 67 {2, 1, 1, 2, 3, 2, 0}, {2, 3, 3, 1, 1, 1, 2}}; | |
| 68 | |
| 69 CBC_OnedCode128Reader::CBC_OnedCode128Reader() {} | |
| 70 CBC_OnedCode128Reader::~CBC_OnedCode128Reader() {} | |
| 71 CFX_Int32Array* CBC_OnedCode128Reader::FindStartPattern(CBC_CommonBitArray* row, | |
| 72 int32_t& e) { | |
| 73 int32_t width = row->GetSize(); | |
| 74 int32_t rowOffset = 0; | |
| 75 while (rowOffset < width) { | |
| 76 if (row->Get(rowOffset)) { | |
| 77 break; | |
| 78 } | |
| 79 rowOffset++; | |
| 80 } | |
| 81 int32_t counterPosition = 0; | |
| 82 CFX_Int32Array counters; | |
| 83 counters.SetSize(6); | |
| 84 int32_t patternStart = rowOffset; | |
| 85 FX_BOOL isWhite = FALSE; | |
| 86 int32_t patternLength = counters.GetSize(); | |
| 87 for (int32_t i = rowOffset; i < width; i++) { | |
| 88 FX_BOOL pixel = row->Get(i); | |
| 89 if (pixel ^ isWhite) { | |
| 90 counters[counterPosition]++; | |
| 91 } else { | |
| 92 if (counterPosition == patternLength - 1) { | |
| 93 int32_t bestVariance = MAX_AVG_VARIANCE; | |
| 94 int32_t bestMatch = -1; | |
| 95 for (int32_t startCode = CODE_START_A; startCode <= CODE_START_C; | |
| 96 startCode++) { | |
| 97 int32_t variance = PatternMatchVariance( | |
| 98 &counters, &CODE_PATTERNS[startCode][0], MAX_INDIVIDUAL_VARIANCE); | |
| 99 if (variance < bestVariance) { | |
| 100 bestVariance = variance; | |
| 101 bestMatch = startCode; | |
| 102 } | |
| 103 } | |
| 104 if (bestMatch >= 0) { | |
| 105 FX_BOOL btemp2 = | |
| 106 row->IsRange(std::max(0, patternStart - (i - patternStart) / 2), | |
| 107 patternStart, FALSE, e); | |
| 108 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
| 109 if (btemp2) { | |
| 110 CFX_Int32Array* result = new CFX_Int32Array; | |
| 111 result->SetSize(3); | |
| 112 (*result)[0] = patternStart; | |
| 113 (*result)[1] = i; | |
| 114 (*result)[2] = bestMatch; | |
| 115 return result; | |
| 116 } | |
| 117 } | |
| 118 patternStart += counters[0] + counters[1]; | |
| 119 for (int32_t y = 2; y < patternLength; y++) { | |
| 120 counters[y - 2] = counters[y]; | |
| 121 } | |
| 122 counters[patternLength - 2] = 0; | |
| 123 counters[patternLength - 1] = 0; | |
| 124 counterPosition--; | |
| 125 } else { | |
| 126 counterPosition++; | |
| 127 } | |
| 128 counters[counterPosition] = 1; | |
| 129 isWhite = !isWhite; | |
| 130 } | |
| 131 } | |
| 132 e = BCExceptionNotFound; | |
| 133 return NULL; | |
| 134 } | |
| 135 int32_t CBC_OnedCode128Reader::DecodeCode(CBC_CommonBitArray* row, | |
| 136 CFX_Int32Array* counters, | |
| 137 int32_t rowOffset, | |
| 138 int32_t& e) { | |
| 139 RecordPattern(row, rowOffset, counters, e); | |
| 140 BC_EXCEPTION_CHECK_ReturnValue(e, 0); | |
| 141 int32_t bestVariance = MAX_AVG_VARIANCE; | |
| 142 int32_t bestMatch = -1; | |
| 143 for (int32_t d = 0; d < 107; d++) { | |
| 144 int32_t variance = PatternMatchVariance(counters, &CODE_PATTERNS[d][0], | |
| 145 MAX_INDIVIDUAL_VARIANCE); | |
| 146 if (variance < bestVariance) { | |
| 147 bestVariance = variance; | |
| 148 bestMatch = d; | |
| 149 } | |
| 150 } | |
| 151 if (bestMatch >= 0) { | |
| 152 return bestMatch; | |
| 153 } else { | |
| 154 e = BCExceptionNotFound; | |
| 155 return 0; | |
| 156 } | |
| 157 return 0; | |
| 158 } | |
| 159 CFX_ByteString CBC_OnedCode128Reader::DecodeRow(int32_t rowNumber, | |
| 160 CBC_CommonBitArray* row, | |
| 161 int32_t hints, | |
| 162 int32_t& e) { | |
| 163 CFX_Int32Array* startPatternInfo = FindStartPattern(row, e); | |
| 164 BC_EXCEPTION_CHECK_ReturnValue(e, ""); | |
| 165 int32_t startCode = (*startPatternInfo)[2]; | |
| 166 int32_t codeSet; | |
| 167 switch (startCode) { | |
| 168 case 103: | |
| 169 codeSet = CODE_CODE_A; | |
| 170 break; | |
| 171 case 104: | |
| 172 codeSet = CODE_CODE_B; | |
| 173 break; | |
| 174 case 105: | |
| 175 codeSet = CODE_CODE_C; | |
| 176 break; | |
| 177 default: | |
| 178 if (startPatternInfo) { | |
| 179 startPatternInfo->RemoveAll(); | |
| 180 delete startPatternInfo; | |
| 181 startPatternInfo = NULL; | |
| 182 } | |
| 183 e = BCExceptionFormatException; | |
| 184 return ""; | |
| 185 } | |
| 186 FX_BOOL done = FALSE; | |
| 187 FX_BOOL isNextShifted = FALSE; | |
| 188 CFX_ByteString result; | |
| 189 int32_t lastStart = (*startPatternInfo)[0]; | |
| 190 int32_t nextStart = (*startPatternInfo)[1]; | |
| 191 if (startPatternInfo) { | |
| 192 startPatternInfo->RemoveAll(); | |
| 193 delete startPatternInfo; | |
| 194 startPatternInfo = NULL; | |
| 195 } | |
| 196 CFX_Int32Array counters; | |
| 197 counters.SetSize(6); | |
| 198 int32_t lastCode = 0; | |
| 199 int32_t code = 0; | |
| 200 int32_t checksumTotal = startCode; | |
| 201 int32_t multiplier = 0; | |
| 202 FX_BOOL lastCharacterWasPrintable = TRUE; | |
| 203 while (!done) { | |
| 204 FX_BOOL unshift = isNextShifted; | |
| 205 isNextShifted = FALSE; | |
| 206 lastCode = code; | |
| 207 code = DecodeCode(row, &counters, nextStart, e); | |
| 208 BC_EXCEPTION_CHECK_ReturnValue(e, ""); | |
| 209 if (code != CODE_STOP) { | |
| 210 lastCharacterWasPrintable = TRUE; | |
| 211 } | |
| 212 if (code != CODE_STOP) { | |
| 213 multiplier++; | |
| 214 checksumTotal += multiplier * code; | |
| 215 } | |
| 216 lastStart = nextStart; | |
| 217 for (int32_t i = 0; i < counters.GetSize(); i++) { | |
| 218 nextStart += counters[i]; | |
| 219 } | |
| 220 switch (code) { | |
| 221 case 103: | |
| 222 case 104: | |
| 223 case 105: | |
| 224 e = BCExceptionFormatException; | |
| 225 return ""; | |
| 226 } | |
| 227 switch (codeSet) { | |
| 228 case 101: | |
| 229 if (code < 64) { | |
| 230 result += (FX_CHAR)(' ' + code); | |
| 231 } else if (code < 96) { | |
| 232 result += (FX_CHAR)(code - 64); | |
| 233 } else { | |
| 234 if (code != CODE_STOP) { | |
| 235 lastCharacterWasPrintable = FALSE; | |
| 236 } | |
| 237 switch (code) { | |
| 238 case 102: | |
| 239 case 97: | |
| 240 case 96: | |
| 241 case 101: | |
| 242 break; | |
| 243 case 98: | |
| 244 isNextShifted = TRUE; | |
| 245 codeSet = CODE_CODE_B; | |
| 246 break; | |
| 247 case 100: | |
| 248 codeSet = CODE_CODE_B; | |
| 249 break; | |
| 250 case 99: | |
| 251 codeSet = CODE_CODE_C; | |
| 252 break; | |
| 253 case 106: | |
| 254 done = TRUE; | |
| 255 break; | |
| 256 } | |
| 257 } | |
| 258 break; | |
| 259 case 100: | |
| 260 if (code < 96) { | |
| 261 result += (FX_CHAR)(' ' + code); | |
| 262 } else { | |
| 263 if (code != CODE_STOP) { | |
| 264 lastCharacterWasPrintable = FALSE; | |
| 265 } | |
| 266 switch (code) { | |
| 267 case 102: | |
| 268 case 97: | |
| 269 case 96: | |
| 270 case 100: | |
| 271 break; | |
| 272 case 98: | |
| 273 isNextShifted = TRUE; | |
| 274 codeSet = CODE_CODE_A; | |
| 275 break; | |
| 276 case 101: | |
| 277 codeSet = CODE_CODE_A; | |
| 278 break; | |
| 279 case 99: | |
| 280 codeSet = CODE_CODE_C; | |
| 281 break; | |
| 282 case 106: | |
| 283 done = TRUE; | |
| 284 break; | |
| 285 } | |
| 286 } | |
| 287 break; | |
| 288 case 99: | |
| 289 if (code < 100) { | |
| 290 if (code < 10) { | |
| 291 result += '0'; | |
| 292 } | |
| 293 FX_CHAR temp[128]; | |
| 294 // TODO(dsinclair): Should this be snprintf? | |
| 295 sprintf(temp, "%d", code); | |
| 296 result += temp; | |
| 297 } else { | |
| 298 if (code != CODE_STOP) { | |
| 299 lastCharacterWasPrintable = FALSE; | |
| 300 } | |
| 301 switch (code) { | |
| 302 case 102: | |
| 303 break; | |
| 304 case 101: | |
| 305 codeSet = CODE_CODE_A; | |
| 306 break; | |
| 307 case 100: | |
| 308 codeSet = CODE_CODE_B; | |
| 309 break; | |
| 310 case 106: | |
| 311 done = TRUE; | |
| 312 break; | |
| 313 } | |
| 314 } | |
| 315 break; | |
| 316 } | |
| 317 if (unshift) { | |
| 318 codeSet = codeSet == CODE_CODE_A ? CODE_CODE_B : CODE_CODE_A; | |
| 319 } | |
| 320 } | |
| 321 int32_t width = row->GetSize(); | |
| 322 while (nextStart < width && row->Get(nextStart)) { | |
| 323 nextStart++; | |
| 324 } | |
| 325 FX_BOOL boolT1 = row->IsRange( | |
| 326 nextStart, std::min(width, nextStart + (nextStart - lastStart) / 2), | |
| 327 FALSE, e); | |
| 328 BC_EXCEPTION_CHECK_ReturnValue(e, ""); | |
| 329 if (!boolT1) { | |
| 330 e = BCExceptionNotFound; | |
| 331 return ""; | |
| 332 } | |
| 333 checksumTotal -= multiplier * lastCode; | |
| 334 if (checksumTotal % 103 != lastCode) { | |
| 335 e = BCExceptionChecksumException; | |
| 336 return ""; | |
| 337 } | |
| 338 int32_t resultLength = result.GetLength(); | |
| 339 if (resultLength > 0 && lastCharacterWasPrintable) { | |
| 340 if (codeSet == CODE_CODE_C) { | |
| 341 result = result.Mid(0, result.GetLength() - 2); | |
| 342 } else { | |
| 343 result = result.Mid(0, result.GetLength() - 1); | |
| 344 } | |
| 345 } | |
| 346 if (result.GetLength() == 0) { | |
| 347 e = BCExceptionFormatException; | |
| 348 return ""; | |
| 349 } | |
| 350 return result; | |
| 351 } | |
| OLD | NEW |