| 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 "barcode.h" | |
| 24 #include "include/BC_Reader.h" | |
| 25 #include "include/BC_OneDReader.h" | |
| 26 #include "include/BC_CommonBitArray.h" | |
| 27 #include "include/BC_OnedCode128Reader.h" | |
| 28 const FX_INT32 CBC_OnedCode128Reader::CODE_PATTERNS[107][7] = { | |
| 29 {2, 1, 2, 2, 2, 2, 0}, | |
| 30 {2, 2, 2, 1, 2, 2, 0}, | |
| 31 {2, 2, 2, 2, 2, 1, 0}, | |
| 32 {1, 2, 1, 2, 2, 3, 0}, | |
| 33 {1, 2, 1, 3, 2, 2, 0}, | |
| 34 {1, 3, 1, 2, 2, 2, 0}, | |
| 35 {1, 2, 2, 2, 1, 3, 0}, | |
| 36 {1, 2, 2, 3, 1, 2, 0}, | |
| 37 {1, 3, 2, 2, 1, 2, 0}, | |
| 38 {2, 2, 1, 2, 1, 3, 0}, | |
| 39 {2, 2, 1, 3, 1, 2, 0}, | |
| 40 {2, 3, 1, 2, 1, 2, 0}, | |
| 41 {1, 1, 2, 2, 3, 2, 0}, | |
| 42 {1, 2, 2, 1, 3, 2, 0}, | |
| 43 {1, 2, 2, 2, 3, 1, 0}, | |
| 44 {1, 1, 3, 2, 2, 2, 0}, | |
| 45 {1, 2, 3, 1, 2, 2, 0}, | |
| 46 {1, 2, 3, 2, 2, 1, 0}, | |
| 47 {2, 2, 3, 2, 1, 1, 0}, | |
| 48 {2, 2, 1, 1, 3, 2, 0}, | |
| 49 {2, 2, 1, 2, 3, 1, 0}, | |
| 50 {2, 1, 3, 2, 1, 2, 0}, | |
| 51 {2, 2, 3, 1, 1, 2, 0}, | |
| 52 {3, 1, 2, 1, 3, 1, 0}, | |
| 53 {3, 1, 1, 2, 2, 2, 0}, | |
| 54 {3, 2, 1, 1, 2, 2, 0}, | |
| 55 {3, 2, 1, 2, 2, 1, 0}, | |
| 56 {3, 1, 2, 2, 1, 2, 0}, | |
| 57 {3, 2, 2, 1, 1, 2, 0}, | |
| 58 {3, 2, 2, 2, 1, 1, 0}, | |
| 59 {2, 1, 2, 1, 2, 3, 0}, | |
| 60 {2, 1, 2, 3, 2, 1, 0}, | |
| 61 {2, 3, 2, 1, 2, 1, 0}, | |
| 62 {1, 1, 1, 3, 2, 3, 0}, | |
| 63 {1, 3, 1, 1, 2, 3, 0}, | |
| 64 {1, 3, 1, 3, 2, 1, 0}, | |
| 65 {1, 1, 2, 3, 1, 3, 0}, | |
| 66 {1, 3, 2, 1, 1, 3, 0}, | |
| 67 {1, 3, 2, 3, 1, 1, 0}, | |
| 68 {2, 1, 1, 3, 1, 3, 0}, | |
| 69 {2, 3, 1, 1, 1, 3, 0}, | |
| 70 {2, 3, 1, 3, 1, 1, 0}, | |
| 71 {1, 1, 2, 1, 3, 3, 0}, | |
| 72 {1, 1, 2, 3, 3, 1, 0}, | |
| 73 {1, 3, 2, 1, 3, 1, 0}, | |
| 74 {1, 1, 3, 1, 2, 3, 0}, | |
| 75 {1, 1, 3, 3, 2, 1, 0}, | |
| 76 {1, 3, 3, 1, 2, 1, 0}, | |
| 77 {3, 1, 3, 1, 2, 1, 0}, | |
| 78 {2, 1, 1, 3, 3, 1, 0}, | |
| 79 {2, 3, 1, 1, 3, 1, 0}, | |
| 80 {2, 1, 3, 1, 1, 3, 0}, | |
| 81 {2, 1, 3, 3, 1, 1, 0}, | |
| 82 {2, 1, 3, 1, 3, 1, 0}, | |
| 83 {3, 1, 1, 1, 2, 3, 0}, | |
| 84 {3, 1, 1, 3, 2, 1, 0}, | |
| 85 {3, 3, 1, 1, 2, 1, 0}, | |
| 86 {3, 1, 2, 1, 1, 3, 0}, | |
| 87 {3, 1, 2, 3, 1, 1, 0}, | |
| 88 {3, 3, 2, 1, 1, 1, 0}, | |
| 89 {3, 1, 4, 1, 1, 1, 0}, | |
| 90 {2, 2, 1, 4, 1, 1, 0}, | |
| 91 {4, 3, 1, 1, 1, 1, 0}, | |
| 92 {1, 1, 1, 2, 2, 4, 0}, | |
| 93 {1, 1, 1, 4, 2, 2, 0}, | |
| 94 {1, 2, 1, 1, 2, 4, 0}, | |
| 95 {1, 2, 1, 4, 2, 1, 0}, | |
| 96 {1, 4, 1, 1, 2, 2, 0}, | |
| 97 {1, 4, 1, 2, 2, 1, 0}, | |
| 98 {1, 1, 2, 2, 1, 4, 0}, | |
| 99 {1, 1, 2, 4, 1, 2, 0}, | |
| 100 {1, 2, 2, 1, 1, 4, 0}, | |
| 101 {1, 2, 2, 4, 1, 1, 0}, | |
| 102 {1, 4, 2, 1, 1, 2, 0}, | |
| 103 {1, 4, 2, 2, 1, 1, 0}, | |
| 104 {2, 4, 1, 2, 1, 1, 0}, | |
| 105 {2, 2, 1, 1, 1, 4, 0}, | |
| 106 {4, 1, 3, 1, 1, 1, 0}, | |
| 107 {2, 4, 1, 1, 1, 2, 0}, | |
| 108 {1, 3, 4, 1, 1, 1, 0}, | |
| 109 {1, 1, 1, 2, 4, 2, 0}, | |
| 110 {1, 2, 1, 1, 4, 2, 0}, | |
| 111 {1, 2, 1, 2, 4, 1, 0}, | |
| 112 {1, 1, 4, 2, 1, 2, 0}, | |
| 113 {1, 2, 4, 1, 1, 2, 0}, | |
| 114 {1, 2, 4, 2, 1, 1, 0}, | |
| 115 {4, 1, 1, 2, 1, 2, 0}, | |
| 116 {4, 2, 1, 1, 1, 2, 0}, | |
| 117 {4, 2, 1, 2, 1, 1, 0}, | |
| 118 {2, 1, 2, 1, 4, 1, 0}, | |
| 119 {2, 1, 4, 1, 2, 1, 0}, | |
| 120 {4, 1, 2, 1, 2, 1, 0}, | |
| 121 {1, 1, 1, 1, 4, 3, 0}, | |
| 122 {1, 1, 1, 3, 4, 1, 0}, | |
| 123 {1, 3, 1, 1, 4, 1, 0}, | |
| 124 {1, 1, 4, 1, 1, 3, 0}, | |
| 125 {1, 1, 4, 3, 1, 1, 0}, | |
| 126 {4, 1, 1, 1, 1, 3, 0}, | |
| 127 {4, 1, 1, 3, 1, 1, 0}, | |
| 128 {1, 1, 3, 1, 4, 1, 0}, | |
| 129 {1, 1, 4, 1, 3, 1, 0}, | |
| 130 {3, 1, 1, 1, 4, 1, 0}, | |
| 131 {4, 1, 1, 1, 3, 1, 0}, | |
| 132 {2, 1, 1, 4, 1, 2, 0}, | |
| 133 {2, 1, 1, 2, 1, 4, 0}, | |
| 134 {2, 1, 1, 2, 3, 2, 0}, | |
| 135 {2, 3, 3, 1, 1, 1, 2} | |
| 136 }; | |
| 137 const FX_INT32 CBC_OnedCode128Reader::MAX_AVG_VARIANCE = (FX_INT32) (256 * 0.25f
); | |
| 138 const FX_INT32 CBC_OnedCode128Reader::MAX_INDIVIDUAL_VARIANCE = (FX_INT32) (256
* 0.7f); | |
| 139 const FX_INT32 CBC_OnedCode128Reader::CODE_SHIFT = 98; | |
| 140 const FX_INT32 CBC_OnedCode128Reader::CODE_CODE_C = 99; | |
| 141 const FX_INT32 CBC_OnedCode128Reader::CODE_CODE_B = 100; | |
| 142 const FX_INT32 CBC_OnedCode128Reader::CODE_CODE_A = 101; | |
| 143 const FX_INT32 CBC_OnedCode128Reader::CODE_FNC_1 = 102; | |
| 144 const FX_INT32 CBC_OnedCode128Reader::CODE_FNC_2 = 97; | |
| 145 const FX_INT32 CBC_OnedCode128Reader::CODE_FNC_3 = 96; | |
| 146 const FX_INT32 CBC_OnedCode128Reader::CODE_FNC_4_A = 101; | |
| 147 const FX_INT32 CBC_OnedCode128Reader::CODE_FNC_4_B = 100; | |
| 148 const FX_INT32 CBC_OnedCode128Reader::CODE_START_A = 103; | |
| 149 const FX_INT32 CBC_OnedCode128Reader::CODE_START_B = 104; | |
| 150 const FX_INT32 CBC_OnedCode128Reader::CODE_START_C = 105; | |
| 151 const FX_INT32 CBC_OnedCode128Reader::CODE_STOP = 106; | |
| 152 CBC_OnedCode128Reader::CBC_OnedCode128Reader() | |
| 153 { | |
| 154 } | |
| 155 CBC_OnedCode128Reader::~CBC_OnedCode128Reader() | |
| 156 { | |
| 157 } | |
| 158 CFX_Int32Array *CBC_OnedCode128Reader::FindStartPattern(CBC_CommonBitArray *row,
FX_INT32 &e) | |
| 159 { | |
| 160 FX_INT32 width = row->GetSize(); | |
| 161 FX_INT32 rowOffset = 0; | |
| 162 while (rowOffset < width) { | |
| 163 if (row->Get(rowOffset)) { | |
| 164 break; | |
| 165 } | |
| 166 rowOffset++; | |
| 167 } | |
| 168 FX_INT32 counterPosition = 0; | |
| 169 CFX_Int32Array counters; | |
| 170 counters.SetSize(6); | |
| 171 FX_INT32 patternStart = rowOffset; | |
| 172 FX_BOOL isWhite = FALSE; | |
| 173 FX_INT32 patternLength = counters.GetSize(); | |
| 174 for (FX_INT32 i = rowOffset; i < width; i++) { | |
| 175 FX_BOOL pixel = row->Get(i); | |
| 176 if (pixel ^ isWhite) { | |
| 177 counters[counterPosition]++; | |
| 178 } else { | |
| 179 if (counterPosition == patternLength - 1) { | |
| 180 FX_INT32 bestVariance = MAX_AVG_VARIANCE; | |
| 181 FX_INT32 bestMatch = -1; | |
| 182 for (FX_INT32 startCode = CODE_START_A; startCode <= CODE_START_
C; startCode++) { | |
| 183 FX_INT32 variance = PatternMatchVariance(&counters, &CODE_PA
TTERNS[startCode][0], MAX_INDIVIDUAL_VARIANCE); | |
| 184 if (variance < bestVariance) { | |
| 185 bestVariance = variance; | |
| 186 bestMatch = startCode; | |
| 187 } | |
| 188 } | |
| 189 if (bestMatch >= 0) { | |
| 190 FX_BOOL btemp2 = row->IsRange(FX_MAX(0, patternStart - (i -
patternStart) / 2), patternStart, FALSE, e); | |
| 191 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
| 192 if (btemp2) { | |
| 193 CFX_Int32Array *result = FX_NEW CFX_Int32Array; | |
| 194 result->SetSize(3); | |
| 195 (*result)[0] = patternStart; | |
| 196 (*result)[1] = i; | |
| 197 (*result)[2] = bestMatch; | |
| 198 return result; | |
| 199 } | |
| 200 } | |
| 201 patternStart += counters[0] + counters[1]; | |
| 202 for (FX_INT32 y = 2; y < patternLength; y++) { | |
| 203 counters[y - 2] = counters[y]; | |
| 204 } | |
| 205 counters[patternLength - 2] = 0; | |
| 206 counters[patternLength - 1] = 0; | |
| 207 counterPosition--; | |
| 208 } else { | |
| 209 counterPosition++; | |
| 210 } | |
| 211 counters[counterPosition] = 1; | |
| 212 isWhite = !isWhite; | |
| 213 } | |
| 214 } | |
| 215 e = BCExceptionNotFound; | |
| 216 return NULL; | |
| 217 } | |
| 218 FX_INT32 CBC_OnedCode128Reader::DecodeCode(CBC_CommonBitArray *row, CFX_Int32Arr
ay *counters, FX_INT32 rowOffset, FX_INT32 &e) | |
| 219 { | |
| 220 RecordPattern(row, rowOffset, counters, e); | |
| 221 BC_EXCEPTION_CHECK_ReturnValue(e, 0); | |
| 222 FX_INT32 bestVariance = MAX_AVG_VARIANCE; | |
| 223 FX_INT32 bestMatch = -1; | |
| 224 for (FX_INT32 d = 0; d < 107; d++) { | |
| 225 FX_INT32 variance = PatternMatchVariance(counters, &CODE_PATTERNS[d][0],
MAX_INDIVIDUAL_VARIANCE); | |
| 226 if (variance < bestVariance) { | |
| 227 bestVariance = variance; | |
| 228 bestMatch = d; | |
| 229 } | |
| 230 } | |
| 231 if (bestMatch >= 0) { | |
| 232 return bestMatch; | |
| 233 } else { | |
| 234 e = BCExceptionNotFound; | |
| 235 return 0; | |
| 236 } | |
| 237 return 0; | |
| 238 } | |
| 239 CFX_ByteString CBC_OnedCode128Reader::DecodeRow(FX_INT32 rowNumber, CBC_CommonBi
tArray *row, FX_INT32 hints, FX_INT32 &e) | |
| 240 { | |
| 241 CFX_Int32Array *startPatternInfo = FindStartPattern(row, e); | |
| 242 BC_EXCEPTION_CHECK_ReturnValue(e, ""); | |
| 243 FX_INT32 startCode = (*startPatternInfo)[2]; | |
| 244 FX_INT32 codeSet; | |
| 245 switch (startCode) { | |
| 246 case 103: | |
| 247 codeSet = CODE_CODE_A; | |
| 248 break; | |
| 249 case 104: | |
| 250 codeSet = CODE_CODE_B; | |
| 251 break; | |
| 252 case 105: | |
| 253 codeSet = CODE_CODE_C; | |
| 254 break; | |
| 255 default: | |
| 256 if(startPatternInfo != NULL) { | |
| 257 startPatternInfo->RemoveAll(); | |
| 258 delete startPatternInfo; | |
| 259 startPatternInfo = NULL; | |
| 260 } | |
| 261 e = BCExceptionFormatException; | |
| 262 return ""; | |
| 263 } | |
| 264 FX_BOOL done = FALSE; | |
| 265 FX_BOOL isNextShifted = FALSE; | |
| 266 CFX_ByteString result; | |
| 267 FX_INT32 lastStart = (*startPatternInfo)[0]; | |
| 268 FX_INT32 nextStart = (*startPatternInfo)[1]; | |
| 269 if(startPatternInfo != NULL) { | |
| 270 startPatternInfo->RemoveAll(); | |
| 271 delete startPatternInfo; | |
| 272 startPatternInfo = NULL; | |
| 273 } | |
| 274 CFX_Int32Array counters; | |
| 275 counters.SetSize(6); | |
| 276 FX_INT32 lastCode = 0; | |
| 277 FX_INT32 code = 0; | |
| 278 FX_INT32 checksumTotal = startCode; | |
| 279 FX_INT32 multiplier = 0; | |
| 280 FX_BOOL lastCharacterWasPrintable = TRUE; | |
| 281 while (!done) { | |
| 282 FX_BOOL unshift = isNextShifted; | |
| 283 isNextShifted = FALSE; | |
| 284 lastCode = code; | |
| 285 code = DecodeCode(row, &counters, nextStart, e); | |
| 286 BC_EXCEPTION_CHECK_ReturnValue(e, ""); | |
| 287 if (code != CODE_STOP) { | |
| 288 lastCharacterWasPrintable = TRUE; | |
| 289 } | |
| 290 if (code != CODE_STOP) { | |
| 291 multiplier++; | |
| 292 checksumTotal += multiplier * code; | |
| 293 } | |
| 294 lastStart = nextStart; | |
| 295 for (FX_INT32 i = 0; i < counters.GetSize(); i++) { | |
| 296 nextStart += counters[i]; | |
| 297 } | |
| 298 switch (code) { | |
| 299 case 103: | |
| 300 case 104: | |
| 301 case 105: | |
| 302 e = BCExceptionFormatException; | |
| 303 return ""; | |
| 304 } | |
| 305 switch (codeSet) { | |
| 306 case 101: | |
| 307 if (code < 64) { | |
| 308 result += (FX_CHAR) (' ' + code); | |
| 309 } else if (code < 96) { | |
| 310 result += (FX_CHAR) (code - 64); | |
| 311 } else { | |
| 312 if (code != CODE_STOP) { | |
| 313 lastCharacterWasPrintable = FALSE; | |
| 314 } | |
| 315 switch (code) { | |
| 316 case 102: | |
| 317 case 97: | |
| 318 case 96: | |
| 319 case 101: | |
| 320 break; | |
| 321 case 98: | |
| 322 isNextShifted = TRUE; | |
| 323 codeSet = CODE_CODE_B; | |
| 324 break; | |
| 325 case 100: | |
| 326 codeSet = CODE_CODE_B; | |
| 327 break; | |
| 328 case 99: | |
| 329 codeSet = CODE_CODE_C; | |
| 330 break; | |
| 331 case 106: | |
| 332 done = TRUE; | |
| 333 break; | |
| 334 } | |
| 335 } | |
| 336 break; | |
| 337 case 100: | |
| 338 if (code < 96) { | |
| 339 result += (FX_CHAR) (' ' + code); | |
| 340 } else { | |
| 341 if (code != CODE_STOP) { | |
| 342 lastCharacterWasPrintable = FALSE; | |
| 343 } | |
| 344 switch (code) { | |
| 345 case 102: | |
| 346 case 97: | |
| 347 case 96: | |
| 348 case 100: | |
| 349 break; | |
| 350 case 98: | |
| 351 isNextShifted = TRUE; | |
| 352 codeSet = CODE_CODE_A; | |
| 353 break; | |
| 354 case 101: | |
| 355 codeSet = CODE_CODE_A; | |
| 356 break; | |
| 357 case 99: | |
| 358 codeSet = CODE_CODE_C; | |
| 359 break; | |
| 360 case 106: | |
| 361 done = TRUE; | |
| 362 break; | |
| 363 } | |
| 364 } | |
| 365 break; | |
| 366 case 99: | |
| 367 if (code < 100) { | |
| 368 if (code < 10) { | |
| 369 result += '0'; | |
| 370 } | |
| 371 FX_CHAR temp[128]; | |
| 372 #if defined(_FX_WINAPI_PARTITION_APP_) | |
| 373 sprintf_s(temp, 128, "%d", code); | |
| 374 #else | |
| 375 sprintf(temp, "%d", code); | |
| 376 #endif | |
| 377 result += temp; | |
| 378 } else { | |
| 379 if (code != CODE_STOP) { | |
| 380 lastCharacterWasPrintable = FALSE; | |
| 381 } | |
| 382 switch (code) { | |
| 383 case 102: | |
| 384 break; | |
| 385 case 101: | |
| 386 codeSet = CODE_CODE_A; | |
| 387 break; | |
| 388 case 100: | |
| 389 codeSet = CODE_CODE_B; | |
| 390 break; | |
| 391 case 106: | |
| 392 done = TRUE; | |
| 393 break; | |
| 394 } | |
| 395 } | |
| 396 break; | |
| 397 } | |
| 398 if (unshift) { | |
| 399 codeSet = codeSet == CODE_CODE_A ? CODE_CODE_B : CODE_CODE_A; | |
| 400 } | |
| 401 } | |
| 402 FX_INT32 width = row->GetSize(); | |
| 403 while (nextStart < width && row->Get(nextStart)) { | |
| 404 nextStart++; | |
| 405 } | |
| 406 FX_BOOL boolT1 = row->IsRange(nextStart, FX_MIN(width, nextStart + (nextStar
t - lastStart) / 2), FALSE, e); | |
| 407 BC_EXCEPTION_CHECK_ReturnValue(e, ""); | |
| 408 if (!boolT1) { | |
| 409 e = BCExceptionNotFound; | |
| 410 return ""; | |
| 411 } | |
| 412 checksumTotal -= multiplier * lastCode; | |
| 413 if (checksumTotal % 103 != lastCode) { | |
| 414 e = BCExceptionChecksumException; | |
| 415 return ""; | |
| 416 } | |
| 417 FX_INT32 resultLength = result.GetLength(); | |
| 418 if (resultLength > 0 && lastCharacterWasPrintable) { | |
| 419 if (codeSet == CODE_CODE_C) { | |
| 420 result = result.Mid(0, result.GetLength() - 2); | |
| 421 } else { | |
| 422 result = result.Mid(0, result.GetLength() - 1); | |
| 423 } | |
| 424 } | |
| 425 if (result.GetLength() == 0) { | |
| 426 e = BCExceptionFormatException; | |
| 427 return ""; | |
| 428 } | |
| 429 return result; | |
| 430 } | |
| OLD | NEW |