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/barcode.h" 26 #include "xfa/src/fxbarcode/BC_UtilCodingConvert.h" 27 #include "xfa/src/fxbarcode/common/BC_CommonByteArray.h" 28 #include "xfa/src/fxbarcode/common/BC_CommonByteMatrix.h" 29 #include "xfa/src/fxbarcode/common/reedsolomon/BC_ReedSolomon.h" 30 #include "xfa/src/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" 31 #include "BC_QRCoder.h" 32 #include "BC_QRCoderEncoder.h" 33 #include "BC_QRCoderMode.h" 34 #include "BC_QRCoderEncoder.h" 35 #include "BC_QRCoderECBlocks.h" 36 #include "BC_QRCoderVersion.h" 37 #include "BC_QRCoderBlockPair.h" 38 #include "BC_QRCoderMaskUtil.h" 39 #include "BC_QRCoderMatrixUtil.h" 40 #include "BC_QRCoderBitVector.h" 41 const int32_t CBC_QRCoderEncoder::m_alphaNumbericTable[] = { 42 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, 45 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, 46 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 47 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1}; 48 CBC_QRCoderEncoder::CBC_QRCoderEncoder() {} 49 CBC_QRCoderEncoder::~CBC_QRCoderEncoder() {} 50 class Make_Pair { 51 public: 52 CBC_QRCoderMode* m_mode; 53 CFX_ByteString m_string; 54 55 private: 56 Make_Pair(const Make_Pair& mode_string) {} 57 Make_Pair& operator=(Make_Pair& mode_string) { 58 if (this == &mode_string) { 59 return *this; 60 } 61 m_mode = mode_string.m_mode; 62 m_string = mode_string.m_string; 63 return *this; 64 } 65 66 public: 67 Make_Pair(CBC_QRCoderMode* mode, const CFX_ByteString& str) 68 : m_mode(mode), m_string(str) {} 69 ~Make_Pair() {} 70 }; 71 void CBC_QRCoderEncoder::Encode(const CFX_ByteString& content, 72 CBC_QRCoderErrorCorrectionLevel* ecLevel, 73 CBC_QRCoder* qrCode, 74 int32_t& e, 75 int32_t versionSpecify) { 76 if (versionSpecify == 0) { 77 EncodeWithAutoVersion(content, ecLevel, qrCode, e); 78 BC_EXCEPTION_CHECK_ReturnVoid(e) 79 } else if (versionSpecify > 0 && versionSpecify <= 40) { 80 EncodeWithSpecifyVersion(content, ecLevel, qrCode, versionSpecify, e); 81 BC_EXCEPTION_CHECK_ReturnVoid(e); 82 } else { 83 e = BCExceptionVersionMust1_40; 84 BC_EXCEPTION_CHECK_ReturnVoid(e); 85 } 86 } 87 void CBC_QRCoderEncoder::AppendECI(CBC_QRCoderBitVector* bits) {} 88 void CBC_QRCoderEncoder::AppendDataModeLenghInfo( 89 CFX_PtrArray& splitResult, 90 CBC_QRCoderBitVector& headerAndDataBits, 91 CBC_QRCoderMode* tempMode, 92 CBC_QRCoder* qrCode, 93 CFX_ByteString& encoding, 94 int32_t& e) { 95 for (int32_t i = 0; i < splitResult.GetSize(); i++) { 96 tempMode = ((Make_Pair*)splitResult[i])->m_mode; 97 if (tempMode == CBC_QRCoderMode::sGBK) { 98 AppendModeInfo(tempMode, &headerAndDataBits, e); 99 BC_EXCEPTION_CHECK_ReturnVoid(e); 100 AppendLengthInfo(((Make_Pair*)splitResult[i])->m_string.GetLength(), 101 qrCode->GetVersion(), tempMode, &headerAndDataBits, e); 102 BC_EXCEPTION_CHECK_ReturnVoid(e); 103 AppendBytes(((Make_Pair*)splitResult[i])->m_string, tempMode, 104 &headerAndDataBits, encoding, e); 105 BC_EXCEPTION_CHECK_ReturnVoid(e); 106 } else if (tempMode == CBC_QRCoderMode::sBYTE) { 107 CFX_ByteArray bytes; 108 CBC_UtilCodingConvert::LocaleToUtf8( 109 ((Make_Pair*)splitResult[i])->m_string, bytes); 110 AppendModeInfo(tempMode, &headerAndDataBits, e); 111 BC_EXCEPTION_CHECK_ReturnVoid(e); 112 AppendLengthInfo(bytes.GetSize(), qrCode->GetVersion(), tempMode, 113 &headerAndDataBits, e); 114 BC_EXCEPTION_CHECK_ReturnVoid(e); 115 Append8BitBytes(bytes, &headerAndDataBits, e); 116 BC_EXCEPTION_CHECK_ReturnVoid(e); 117 } else if (tempMode == CBC_QRCoderMode::sALPHANUMERIC) { 118 AppendModeInfo(tempMode, &headerAndDataBits, e); 119 BC_EXCEPTION_CHECK_ReturnVoid(e); 120 AppendLengthInfo(((Make_Pair*)splitResult[i])->m_string.GetLength(), 121 qrCode->GetVersion(), tempMode, &headerAndDataBits, e); 122 BC_EXCEPTION_CHECK_ReturnVoid(e); 123 AppendBytes(((Make_Pair*)splitResult[i])->m_string, tempMode, 124 &headerAndDataBits, encoding, e); 125 BC_EXCEPTION_CHECK_ReturnVoid(e); 126 } else if (tempMode == CBC_QRCoderMode::sNUMERIC) { 127 AppendModeInfo(tempMode, &headerAndDataBits, e); 128 BC_EXCEPTION_CHECK_ReturnVoid(e); 129 AppendLengthInfo(((Make_Pair*)splitResult[i])->m_string.GetLength(), 130 qrCode->GetVersion(), tempMode, &headerAndDataBits, e); 131 BC_EXCEPTION_CHECK_ReturnVoid(e); 132 AppendBytes(((Make_Pair*)splitResult[i])->m_string, tempMode, 133 &headerAndDataBits, encoding, e); 134 BC_EXCEPTION_CHECK_ReturnVoid(e); 135 } else { 136 e = BCExceptionUnknown; 137 BC_EXCEPTION_CHECK_ReturnVoid(e); 138 } 139 } 140 } 141 void CBC_QRCoderEncoder::SplitString(const CFX_ByteString& content, 142 CFX_PtrArray& result) { 143 int32_t index = 0, flag = 0; 144 while ( 145 (((uint8_t)content[index] >= 0xA1 && (uint8_t)content[index] <= 0xAA) || 146 ((uint8_t)content[index] >= 0xB0 && (uint8_t)content[index] <= 0xFA)) && 147 (index < content.GetLength())) { 148 index += 2; 149 } 150 if (index != flag) { 151 result.Add( 152 new Make_Pair(CBC_QRCoderMode::sGBK, content.Mid(flag, index - flag))); 153 } 154 flag = index; 155 if (index >= content.GetLength()) { 156 return; 157 } 158 while ( 159 GetAlphaNumericCode((uint8_t)content[index]) == -1 && 160 !(((uint8_t)content[index] >= 0xA1 && (uint8_t)content[index] <= 0xAA) || 161 ((uint8_t)content[index] >= 0xB0 && (uint8_t)content[index] <= 0xFA)) && 162 (index < content.GetLength())) { 163 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 164 if (IsDBCSLeadByte((uint8_t)content[index])) 165 #else 166 if ((uint8_t)content[index] > 127) 167 #endif 168 { 169 index += 2; 170 } else { 171 index++; 172 } 173 } 174 if (index != flag) { 175 result.Add( 176 new Make_Pair(CBC_QRCoderMode::sBYTE, content.Mid(flag, index - flag))); 177 } 178 flag = index; 179 if (index >= content.GetLength()) { 180 return; 181 } 182 while (FXSYS_Isdigit((uint8_t)content[index]) && 183 (index < content.GetLength())) { 184 index++; 185 } 186 if (index != flag) { 187 result.Add(new Make_Pair(CBC_QRCoderMode::sNUMERIC, 188 content.Mid(flag, index - flag))); 189 } 190 flag = index; 191 if (index >= content.GetLength()) { 192 return; 193 } 194 while (GetAlphaNumericCode((uint8_t)content[index]) != -1 && 195 (index < content.GetLength())) { 196 index++; 197 } 198 if (index != flag) { 199 result.Add(new Make_Pair(CBC_QRCoderMode::sALPHANUMERIC, 200 content.Mid(flag, index - flag))); 201 } 202 flag = index; 203 if (index >= content.GetLength()) { 204 return; 205 } 206 SplitString(content.Mid(index, content.GetLength() - index), result); 207 } 208 int32_t CBC_QRCoderEncoder::GetSpanByVersion(CBC_QRCoderMode* modeFirst, 209 CBC_QRCoderMode* modeSecond, 210 int32_t versionNum, 211 int32_t& e) { 212 if (versionNum == 0) { 213 return 0; 214 } 215 if ((modeFirst == CBC_QRCoderMode::sALPHANUMERIC) && 216 (modeSecond == CBC_QRCoderMode::sBYTE)) { 217 if (versionNum >= 1 && versionNum <= 9) { 218 return 11; 219 } else if (versionNum >= 10 && versionNum <= 26) { 220 return 15; 221 } else if (versionNum >= 27 && versionNum <= 40) { 222 return 16; 223 } else { 224 e = BCExceptionNoSuchVersion; 225 BC_EXCEPTION_CHECK_ReturnValue(e, 0); 226 } 227 } else if ((modeSecond == CBC_QRCoderMode::sALPHANUMERIC) && 228 (modeFirst == CBC_QRCoderMode::sNUMERIC)) { 229 if (versionNum >= 1 && versionNum <= 9) { 230 return 13; 231 } else if (versionNum >= 10 && versionNum <= 26) { 232 return 15; 233 } else if (versionNum >= 27 && versionNum <= 40) { 234 return 17; 235 } else { 236 e = BCExceptionNoSuchVersion; 237 BC_EXCEPTION_CHECK_ReturnValue(e, 0); 238 } 239 } else if ((modeSecond == CBC_QRCoderMode::sBYTE) && 240 (modeFirst == CBC_QRCoderMode::sNUMERIC)) { 241 if (versionNum >= 1 && versionNum <= 9) { 242 return 6; 243 } else if (versionNum >= 10 && versionNum <= 26) { 244 return 8; 245 } else if (versionNum >= 27 && versionNum <= 40) { 246 return 9; 247 } else { 248 e = BCExceptionNoSuchVersion; 249 BC_EXCEPTION_CHECK_ReturnValue(e, 0); 250 } 251 } 252 return -1; 253 } 254 void CBC_QRCoderEncoder::MergeString(CFX_PtrArray& result, 255 int32_t versionNum, 256 int32_t& e) { 257 Make_Pair* first = NULL; 258 Make_Pair* second = NULL; 259 size_t mergeNum = 0; 260 int32_t i; 261 for (i = 0; ((i < result.GetSize()) && (i + 1 < result.GetSize())); i++) { 262 first = (Make_Pair*)result[i]; 263 second = (Make_Pair*)result[i + 1]; 264 if (first->m_mode == CBC_QRCoderMode::sALPHANUMERIC) { 265 int32_t tmp = GetSpanByVersion(CBC_QRCoderMode::sALPHANUMERIC, 266 CBC_QRCoderMode::sBYTE, versionNum, e); 267 BC_EXCEPTION_CHECK_ReturnVoid(e); 268 if ((second->m_mode == CBC_QRCoderMode::sBYTE) && 269 (first->m_string.GetLength() < tmp)) { 270 CFX_ByteString str = first->m_string + second->m_string; 271 second->m_string = str; 272 delete first; 273 result.RemoveAt(i); 274 i--; 275 mergeNum++; 276 } 277 } else if (first->m_mode == CBC_QRCoderMode::sBYTE) { 278 if (second->m_mode == CBC_QRCoderMode::sBYTE) { 279 first->m_string += second->m_string; 280 delete second; 281 result.RemoveAt(i + 1); 282 i--; 283 mergeNum++; 284 } 285 } else if (first->m_mode == CBC_QRCoderMode::sNUMERIC) { 286 int32_t tmp = GetSpanByVersion(CBC_QRCoderMode::sNUMERIC, 287 CBC_QRCoderMode::sBYTE, versionNum, e); 288 BC_EXCEPTION_CHECK_ReturnVoid(e); 289 if ((second->m_mode == CBC_QRCoderMode::sBYTE) && 290 (first->m_string.GetLength() < tmp)) { 291 CFX_ByteString str = first->m_string + second->m_string; 292 second->m_string = str; 293 delete first; 294 result.RemoveAt(i); 295 i--; 296 mergeNum++; 297 } 298 tmp = GetSpanByVersion(CBC_QRCoderMode::sNUMERIC, 299 CBC_QRCoderMode::sALPHANUMERIC, versionNum, e); 300 BC_EXCEPTION_CHECK_ReturnVoid(e); 301 if ((second->m_mode == CBC_QRCoderMode::sALPHANUMERIC) && 302 (first->m_string.GetLength() < tmp)) { 303 CFX_ByteString str = first->m_string + second->m_string; 304 second->m_string = str; 305 delete first; 306 result.RemoveAt(i); 307 i--; 308 mergeNum++; 309 } 310 } 311 } 312 if (mergeNum == 0) { 313 return; 314 } 315 MergeString(result, versionNum, e); 316 BC_EXCEPTION_CHECK_ReturnVoid(e); 317 } 318 void CBC_QRCoderEncoder::InitQRCode(int32_t numInputBytes, 319 int32_t versionNumber, 320 CBC_QRCoderErrorCorrectionLevel* ecLevel, 321 CBC_QRCoderMode* mode, 322 CBC_QRCoder* qrCode, 323 int32_t& e) { 324 qrCode->SetECLevel(ecLevel); 325 qrCode->SetMode(mode); 326 CBC_QRCoderVersion* version = 327 CBC_QRCoderVersion::GetVersionForNumber(versionNumber, e); 328 BC_EXCEPTION_CHECK_ReturnVoid(e); 329 int32_t numBytes = version->GetTotalCodeWords(); 330 CBC_QRCoderECBlocks* ecBlocks = version->GetECBlocksForLevel(ecLevel); 331 int32_t numEcBytes = ecBlocks->GetTotalECCodeWords(); 332 int32_t numRSBlocks = ecBlocks->GetNumBlocks(); 333 int32_t numDataBytes = numBytes - numEcBytes; 334 if (numDataBytes >= numInputBytes + 3) { 335 qrCode->SetVersion(versionNumber); 336 qrCode->SetNumTotalBytes(numBytes); 337 qrCode->SetNumDataBytes(numDataBytes); 338 qrCode->SetNumRSBlocks(numRSBlocks); 339 qrCode->SetNumECBytes(numEcBytes); 340 qrCode->SetMatrixWidth(version->GetDimensionForVersion()); 341 return; 342 } 343 e = BCExceptionCannotFindBlockInfo; 344 BC_EXCEPTION_CHECK_ReturnVoid(e); 345 } 346 void CBC_QRCoderEncoder::EncodeWithSpecifyVersion( 347 const CFX_ByteString& content, 348 CBC_QRCoderErrorCorrectionLevel* ecLevel, 349 CBC_QRCoder* qrCode, 350 int32_t versionSpecify, 351 int32_t& e) { 352 CFX_ByteString encoding = "utf8"; 353 CBC_QRCoderMode* mode = CBC_QRCoderMode::sBYTE; 354 CFX_PtrArray splitResult; 355 CBC_QRCoderBitVector dataBits; 356 dataBits.Init(); 357 SplitString(content, splitResult); 358 MergeString(splitResult, versionSpecify, e); 359 BC_EXCEPTION_CHECK_ReturnVoid(e) CBC_QRCoderMode* tempMode = NULL; 360 for (int32_t i = 0; i < splitResult.GetSize(); i++) { 361 AppendBytes(((Make_Pair*)splitResult[i])->m_string, 362 ((Make_Pair*)splitResult[i])->m_mode, &dataBits, encoding, e); 363 if (e != BCExceptionNO) { 364 for (int32_t y = 0; y < splitResult.GetSize(); y++) { 365 delete (Make_Pair*)splitResult[y]; 366 } 367 splitResult.RemoveAll(); 368 return; 369 } 370 } 371 int32_t numInputBytes = dataBits.sizeInBytes(); 372 CBC_QRCoderBitVector headerAndDataBits; 373 headerAndDataBits.Init(); 374 InitQRCode(numInputBytes, versionSpecify, ecLevel, mode, qrCode, e); 375 if (e != BCExceptionNO) { 376 for (int32_t k = 0; k < splitResult.GetSize(); k++) { 377 delete (Make_Pair*)splitResult[k]; 378 } 379 splitResult.RemoveAll(); 380 return; 381 } 382 AppendDataModeLenghInfo(splitResult, headerAndDataBits, tempMode, qrCode, 383 encoding, e); 384 if (e != BCExceptionNO) { 385 for (int32_t k = 0; k < splitResult.GetSize(); k++) { 386 delete (Make_Pair*)splitResult[k]; 387 } 388 splitResult.RemoveAll(); 389 return; 390 } 391 numInputBytes = headerAndDataBits.sizeInBytes(); 392 TerminateBits(qrCode->GetNumDataBytes(), &headerAndDataBits, e); 393 if (e != BCExceptionNO) { 394 for (int32_t k = 0; k < splitResult.GetSize(); k++) { 395 delete (Make_Pair*)splitResult[k]; 396 } 397 splitResult.RemoveAll(); 398 return; 399 } 400 for (int32_t j = 0; j < splitResult.GetSize(); j++) { 401 delete (Make_Pair*)splitResult[j]; 402 } 403 splitResult.RemoveAll(); 404 CBC_QRCoderBitVector finalBits; 405 finalBits.Init(); 406 InterleaveWithECBytes(&headerAndDataBits, qrCode->GetNumTotalBytes(), 407 qrCode->GetNumDataBytes(), qrCode->GetNumRSBlocks(), 408 &finalBits, e); 409 BC_EXCEPTION_CHECK_ReturnVoid(e); 410 CBC_CommonByteMatrix* pDecoder = new CBC_CommonByteMatrix( 411 qrCode->GetMatrixWidth(), qrCode->GetMatrixWidth()); 412 pDecoder->Init(); 413 CBC_AutoPtr<CBC_CommonByteMatrix> matrix(pDecoder); 414 int32_t maskPattern = ChooseMaskPattern( 415 &finalBits, qrCode->GetECLevel(), qrCode->GetVersion(), matrix.get(), e); 416 BC_EXCEPTION_CHECK_ReturnVoid(e); 417 qrCode->SetMaskPattern(maskPattern); 418 CBC_QRCoderMatrixUtil::BuildMatrix(&finalBits, qrCode->GetECLevel(), 419 qrCode->GetVersion(), 420 qrCode->GetMaskPattern(), matrix.get(), e); 421 BC_EXCEPTION_CHECK_ReturnVoid(e); 422 qrCode->SetMatrix(matrix.release()); 423 if (!qrCode->IsValid()) { 424 e = BCExceptionInvalidQRCode; 425 BC_EXCEPTION_CHECK_ReturnVoid(e); 426 } 427 } 428 void CBC_QRCoderEncoder::EncodeWithAutoVersion( 429 const CFX_ByteString& content, 430 CBC_QRCoderErrorCorrectionLevel* ecLevel, 431 CBC_QRCoder* qrCode, 432 int32_t& e) { 433 CFX_ByteString encoding = "utf8"; 434 CBC_QRCoderMode* mode = CBC_QRCoderMode::sBYTE; 435 CFX_PtrArray splitResult; 436 CBC_QRCoderBitVector dataBits; 437 dataBits.Init(); 438 SplitString(content, splitResult); 439 MergeString(splitResult, 8, e); 440 BC_EXCEPTION_CHECK_ReturnVoid(e); 441 CBC_QRCoderMode* tempMode = NULL; 442 for (int32_t i = 0; i < splitResult.GetSize(); i++) { 443 AppendBytes(((Make_Pair*)splitResult[i])->m_string, 444 ((Make_Pair*)splitResult[i])->m_mode, &dataBits, encoding, e); 445 if (e != BCExceptionNO) { 446 for (int32_t l = 0; l < splitResult.GetSize(); l++) { 447 delete (Make_Pair*)splitResult[l]; 448 } 449 splitResult.RemoveAll(); 450 return; 451 } 452 } 453 int32_t numInputBytes = dataBits.sizeInBytes(); 454 InitQRCode(numInputBytes, ecLevel, mode, qrCode, e); 455 BC_EXCEPTION_CHECK_ReturnVoid(e) CBC_QRCoderBitVector headerAndDataBits; 456 headerAndDataBits.Init(); 457 tempMode = NULL; 458 int32_t versionNum = qrCode->GetVersion(); 459 sign: 460 AppendDataModeLenghInfo(splitResult, headerAndDataBits, tempMode, qrCode, 461 encoding, e); 462 if (e != BCExceptionNO) { 463 goto catchException; 464 } 465 numInputBytes = headerAndDataBits.sizeInBytes(); 466 TerminateBits(qrCode->GetNumDataBytes(), &headerAndDataBits, e); 467 if (e != BCExceptionNO) { 468 goto catchException; 469 } 470 catchException: 471 if (e != BCExceptionNO) { 472 int32_t e1 = BCExceptionNO; 473 InitQRCode(numInputBytes, ecLevel, mode, qrCode, e1); 474 if (e1 != BCExceptionNO) { 475 e = e1; 476 return; 477 } 478 versionNum++; 479 if (versionNum <= 40) { 480 headerAndDataBits.Clear(); 481 e = BCExceptionNO; 482 goto sign; 483 } else { 484 for (int32_t j = 0; j < splitResult.GetSize(); j++) { 485 delete (Make_Pair*)splitResult[j]; 486 } 487 splitResult.RemoveAll(); 488 return; 489 } 490 } 491 for (int32_t k = 0; k < splitResult.GetSize(); k++) { 492 delete (Make_Pair*)splitResult[k]; 493 } 494 splitResult.RemoveAll(); 495 CBC_QRCoderBitVector finalBits; 496 finalBits.Init(); 497 InterleaveWithECBytes(&headerAndDataBits, qrCode->GetNumTotalBytes(), 498 qrCode->GetNumDataBytes(), qrCode->GetNumRSBlocks(), 499 &finalBits, e); 500 BC_EXCEPTION_CHECK_ReturnVoid(e); 501 CBC_CommonByteMatrix* pDecoder = new CBC_CommonByteMatrix( 502 qrCode->GetMatrixWidth(), qrCode->GetMatrixWidth()); 503 pDecoder->Init(); 504 CBC_AutoPtr<CBC_CommonByteMatrix> matrix(pDecoder); 505 int32_t maskPattern = ChooseMaskPattern( 506 &finalBits, qrCode->GetECLevel(), qrCode->GetVersion(), matrix.get(), e); 507 BC_EXCEPTION_CHECK_ReturnVoid(e); 508 qrCode->SetMaskPattern(maskPattern); 509 CBC_QRCoderMatrixUtil::BuildMatrix(&finalBits, qrCode->GetECLevel(), 510 qrCode->GetVersion(), 511 qrCode->GetMaskPattern(), matrix.get(), e); 512 BC_EXCEPTION_CHECK_ReturnVoid(e) qrCode->SetMatrix(matrix.release()); 513 if (!qrCode->IsValid()) { 514 e = BCExceptionInvalidQRCode; 515 BC_EXCEPTION_CHECK_ReturnVoid(e); 516 } 517 } 518 void CBC_QRCoderEncoder::Encode(const CFX_WideString& content, 519 CBC_QRCoderErrorCorrectionLevel* ecLevel, 520 CBC_QRCoder* qrCode, 521 int32_t& e) { 522 CFX_ByteString encoding = "utf8"; 523 CFX_ByteString utf8Data; 524 CBC_UtilCodingConvert::UnicodeToUTF8(content, utf8Data); 525 CBC_QRCoderMode* mode = ChooseMode(utf8Data, encoding); 526 CBC_QRCoderBitVector dataBits; 527 dataBits.Init(); 528 AppendBytes(utf8Data, mode, &dataBits, encoding, e); 529 BC_EXCEPTION_CHECK_ReturnVoid(e); 530 int32_t numInputBytes = dataBits.sizeInBytes(); 531 InitQRCode(numInputBytes, ecLevel, mode, qrCode, e); 532 BC_EXCEPTION_CHECK_ReturnVoid(e); 533 CBC_QRCoderBitVector headerAndDataBits; 534 headerAndDataBits.Init(); 535 AppendModeInfo(mode, &headerAndDataBits, e); 536 BC_EXCEPTION_CHECK_ReturnVoid(e); 537 int32_t numLetters = mode == CBC_QRCoderMode::sBYTE ? dataBits.sizeInBytes() 538 : content.GetLength(); 539 AppendLengthInfo(numLetters, qrCode->GetVersion(), mode, &headerAndDataBits, 540 e); 541 BC_EXCEPTION_CHECK_ReturnVoid(e); 542 headerAndDataBits.AppendBitVector(&dataBits, e); 543 BC_EXCEPTION_CHECK_ReturnVoid(e) 544 TerminateBits(qrCode->GetNumDataBytes(), &headerAndDataBits, e); 545 BC_EXCEPTION_CHECK_ReturnVoid(e); 546 CBC_QRCoderBitVector finalBits; 547 finalBits.Init(); 548 InterleaveWithECBytes(&headerAndDataBits, qrCode->GetNumTotalBytes(), 549 qrCode->GetNumDataBytes(), qrCode->GetNumRSBlocks(), 550 &finalBits, e); 551 BC_EXCEPTION_CHECK_ReturnVoid(e); 552 CBC_CommonByteMatrix* pDecoder = new CBC_CommonByteMatrix( 553 qrCode->GetMatrixWidth(), qrCode->GetMatrixWidth()); 554 pDecoder->Init(); 555 CBC_AutoPtr<CBC_CommonByteMatrix> matrix(pDecoder); 556 int32_t maskPattern = ChooseMaskPattern( 557 &finalBits, qrCode->GetECLevel(), qrCode->GetVersion(), matrix.get(), e); 558 BC_EXCEPTION_CHECK_ReturnVoid(e); 559 qrCode->SetMaskPattern(maskPattern); 560 CBC_QRCoderMatrixUtil::BuildMatrix(&finalBits, qrCode->GetECLevel(), 561 qrCode->GetVersion(), 562 qrCode->GetMaskPattern(), matrix.get(), e); 563 BC_EXCEPTION_CHECK_ReturnVoid(e) qrCode->SetMatrix(matrix.release()); 564 if (!qrCode->IsValid()) { 565 e = BCExceptionInvalidQRCode; 566 BC_EXCEPTION_CHECK_ReturnVoid(e); 567 } 568 } 569 void CBC_QRCoderEncoder::TerminateBits(int32_t numDataBytes, 570 CBC_QRCoderBitVector* bits, 571 int32_t& e) { 572 int32_t capacity = numDataBytes << 3; 573 if (bits->Size() > capacity) { 574 e = BCExceptionDataTooMany; 575 BC_EXCEPTION_CHECK_ReturnVoid(e); 576 } 577 for (int32_t i = 0; i < 4 && bits->Size() < capacity; ++i) { 578 bits->AppendBit(0, e); 579 BC_EXCEPTION_CHECK_ReturnVoid(e); 580 } 581 int32_t numBitsInLastByte = bits->Size() % 8; 582 if (numBitsInLastByte > 0) { 583 int32_t numPaddingBits = 8 - numBitsInLastByte; 584 for (int32_t j = 0; j < numPaddingBits; ++j) { 585 bits->AppendBit(0, e); 586 BC_EXCEPTION_CHECK_ReturnVoid(e) 587 } 588 } 589 if (bits->Size() % 8 != 0) { 590 e = BCExceptionDigitLengthMustBe8; 591 BC_EXCEPTION_CHECK_ReturnVoid(e); 592 } 593 int32_t numPaddingBytes = numDataBytes - bits->sizeInBytes(); 594 for (int32_t k = 0; k < numPaddingBytes; ++k) { 595 if (k % 2 == 0) { 596 bits->AppendBits(0xec, 8, e); 597 BC_EXCEPTION_CHECK_ReturnVoid(e); 598 } else { 599 bits->AppendBits(0x11, 8, e); 600 BC_EXCEPTION_CHECK_ReturnVoid(e); 601 } 602 } 603 if (bits->Size() != capacity) { 604 e = BCExceptionBitsNotEqualCacity; 605 BC_EXCEPTION_CHECK_ReturnVoid(e); 606 } 607 } 608 int32_t CBC_QRCoderEncoder::ChooseMaskPattern( 609 CBC_QRCoderBitVector* bits, 610 CBC_QRCoderErrorCorrectionLevel* ecLevel, 611 int32_t version, 612 CBC_CommonByteMatrix* matrix, 613 int32_t& e) { 614 int32_t minPenalty = 65535; 615 int32_t bestMaskPattern = -1; 616 for (int32_t maskPattern = 0; maskPattern < CBC_QRCoder::NUM_MASK_PATTERNS; 617 maskPattern++) { 618 CBC_QRCoderMatrixUtil::BuildMatrix(bits, ecLevel, version, maskPattern, 619 matrix, e); 620 BC_EXCEPTION_CHECK_ReturnValue(e, 0); 621 int32_t penalty = CalculateMaskPenalty(matrix); 622 if (penalty < minPenalty) { 623 minPenalty = penalty; 624 bestMaskPattern = maskPattern; 625 } 626 } 627 return bestMaskPattern; 628 } 629 int32_t CBC_QRCoderEncoder::CalculateMaskPenalty(CBC_CommonByteMatrix* matrix) { 630 int32_t penalty = 0; 631 penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule1(matrix); 632 penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule2(matrix); 633 penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule3(matrix); 634 penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule4(matrix); 635 return penalty; 636 } 637 CBC_QRCoderMode* CBC_QRCoderEncoder::ChooseMode(const CFX_ByteString& content, 638 CFX_ByteString encoding) { 639 if (encoding.Compare("SHIFT_JIS") == 0) { 640 return CBC_QRCoderMode::sKANJI; 641 } 642 FX_BOOL hasNumeric = FALSE; 643 FX_BOOL hasAlphaNumeric = FALSE; 644 for (int32_t i = 0; i < content.GetLength(); i++) { 645 if (isdigit((uint8_t)content[i])) { 646 hasNumeric = TRUE; 647 } else if (GetAlphaNumericCode((uint8_t)content[i]) != -1) { 648 hasAlphaNumeric = TRUE; 649 } else { 650 return CBC_QRCoderMode::sBYTE; 651 } 652 } 653 if (hasAlphaNumeric) { 654 return CBC_QRCoderMode::sALPHANUMERIC; 655 } else if (hasNumeric) { 656 return CBC_QRCoderMode::sNUMERIC; 657 } 658 return CBC_QRCoderMode::sBYTE; 659 } 660 int32_t CBC_QRCoderEncoder::GetAlphaNumericCode(int32_t code) { 661 if (code < 96 && code >= 0) { 662 return m_alphaNumbericTable[code]; 663 } 664 return -1; 665 } 666 void CBC_QRCoderEncoder::AppendBytes(const CFX_ByteString& content, 667 CBC_QRCoderMode* mode, 668 CBC_QRCoderBitVector* bits, 669 CFX_ByteString encoding, 670 int32_t& e) { 671 if (mode == CBC_QRCoderMode::sNUMERIC) { 672 AppendNumericBytes(content, bits, e); 673 BC_EXCEPTION_CHECK_ReturnVoid(e); 674 } else if (mode == CBC_QRCoderMode::sALPHANUMERIC) { 675 AppendAlphaNumericBytes(content, bits, e); 676 BC_EXCEPTION_CHECK_ReturnVoid(e); 677 } else if (mode == CBC_QRCoderMode::sBYTE) { 678 Append8BitBytes(content, bits, encoding, e); 679 BC_EXCEPTION_CHECK_ReturnVoid(e); 680 } else if (mode == CBC_QRCoderMode::sKANJI) { 681 AppendKanjiBytes(content, bits, e); 682 BC_EXCEPTION_CHECK_ReturnVoid(e); 683 } else if (mode == CBC_QRCoderMode::sGBK) { 684 AppendGBKBytes(content, bits, e); 685 BC_EXCEPTION_CHECK_ReturnVoid(e); 686 } else { 687 e = BCExceptionUnsupportedMode; 688 BC_EXCEPTION_CHECK_ReturnVoid(e); 689 } 690 } 691 void CBC_QRCoderEncoder::AppendNumericBytes(const CFX_ByteString& content, 692 CBC_QRCoderBitVector* bits, 693 int32_t& e) { 694 int32_t length = content.GetLength(); 695 int32_t i = 0; 696 while (i < length) { 697 int32_t num1 = content[i] - '0'; 698 if (i + 2 < length) { 699 int32_t num2 = content[i + 1] - '0'; 700 int32_t num3 = content[i + 2] - '0'; 701 bits->AppendBits(num1 * 100 + num2 * 10 + num3, 10, e); 702 BC_EXCEPTION_CHECK_ReturnVoid(e) i += 3; 703 } else if (i + 1 < length) { 704 int32_t num2 = content[i + 1] - '0'; 705 bits->AppendBits(num1 * 10 + num2, 7, e); 706 BC_EXCEPTION_CHECK_ReturnVoid(e) i += 2; 707 } else { 708 bits->AppendBits(num1, 4, e); 709 BC_EXCEPTION_CHECK_ReturnVoid(e); 710 i++; 711 } 712 } 713 } 714 void CBC_QRCoderEncoder::AppendAlphaNumericBytes(const CFX_ByteString& content, 715 CBC_QRCoderBitVector* bits, 716 int32_t& e) { 717 int32_t length = content.GetLength(); 718 int32_t i = 0; 719 while (i < length) { 720 int32_t code1 = GetAlphaNumericCode(content[i]); 721 if (code1 == -1) { 722 e = BCExceptionInvalidateCharacter; 723 BC_EXCEPTION_CHECK_ReturnVoid(e); 724 } 725 if (i + 1 < length) { 726 int32_t code2 = GetAlphaNumericCode(content[i + 1]); 727 if (code2 == -1) { 728 e = BCExceptionInvalidateCharacter; 729 BC_EXCEPTION_CHECK_ReturnVoid(e); 730 } 731 bits->AppendBits(code1 * 45 + code2, 11, e); 732 BC_EXCEPTION_CHECK_ReturnVoid(e); 733 i += 2; 734 } else { 735 bits->AppendBits(code1, 6, e); 736 BC_EXCEPTION_CHECK_ReturnVoid(e) i++; 737 } 738 } 739 } 740 void CBC_QRCoderEncoder::AppendGBKBytes(const CFX_ByteString& content, 741 CBC_QRCoderBitVector* bits, 742 int32_t& e) { 743 int32_t length = content.GetLength(); 744 FX_DWORD value = 0; 745 for (int32_t i = 0; i < length; i += 2) { 746 value = (FX_DWORD)((uint8_t)content[i] << 8 | (uint8_t)content[i + 1]); 747 if (value <= 0xAAFE && value >= 0xA1A1) { 748 value -= 0xA1A1; 749 } else if (value <= 0xFAFE && value >= 0xB0A1) { 750 value -= 0xA6A1; 751 } else { 752 e = BCExceptionInvalidateCharacter; 753 BC_EXCEPTION_CHECK_ReturnVoid(e); 754 } 755 value = (FX_DWORD)((value >> 8) * 0x60) + (FX_DWORD)(value & 0xff); 756 bits->AppendBits(value, 13, e); 757 BC_EXCEPTION_CHECK_ReturnVoid(e); 758 } 759 } 760 void CBC_QRCoderEncoder::Append8BitBytes(const CFX_ByteString& content, 761 CBC_QRCoderBitVector* bits, 762 CFX_ByteString encoding, 763 int32_t& e) { 764 for (int32_t i = 0; i < content.GetLength(); i++) { 765 bits->AppendBits(content[i], 8, e); 766 BC_EXCEPTION_CHECK_ReturnVoid(e); 767 } 768 } 769 void CBC_QRCoderEncoder::Append8BitBytes(CFX_ByteArray& bytes, 770 CBC_QRCoderBitVector* bits, 771 int32_t& e) { 772 for (int32_t i = 0; i < bytes.GetSize(); i++) { 773 bits->AppendBits(bytes[i], 8, e); 774 BC_EXCEPTION_CHECK_ReturnVoid(e); 775 } 776 } 777 void CBC_QRCoderEncoder::AppendKanjiBytes(const CFX_ByteString& content, 778 CBC_QRCoderBitVector* bits, 779 int32_t& e) { 780 CFX_ByteArray bytes; 781 FX_DWORD value = 0; 782 for (int32_t i = 0; i < bytes.GetSize(); i += 2) { 783 value = (FX_DWORD)((uint8_t)(content[i] << 8) | (uint8_t)content[i + 1]); 784 if (value <= 0x9ffc && value >= 0x8140) { 785 value -= 0x8140; 786 } else if (value <= 0xebbf && value >= 0xe040) { 787 value -= 0xc140; 788 } else { 789 e = BCExceptionInvalidateCharacter; 790 BC_EXCEPTION_CHECK_ReturnVoid(e); 791 } 792 value = (FX_DWORD)((value >> 8) * 0xc0) + (FX_DWORD)(value & 0xff); 793 bits->AppendBits(value, 13, e); 794 BC_EXCEPTION_CHECK_ReturnVoid(e); 795 } 796 } 797 void CBC_QRCoderEncoder::InitQRCode(int32_t numInputBytes, 798 CBC_QRCoderErrorCorrectionLevel* ecLevel, 799 CBC_QRCoderMode* mode, 800 CBC_QRCoder* qrCode, 801 int32_t& e) { 802 qrCode->SetECLevel(ecLevel); 803 qrCode->SetMode(mode); 804 for (int32_t versionNum = 1; versionNum <= 40; versionNum++) { 805 CBC_QRCoderVersion* version = 806 CBC_QRCoderVersion::GetVersionForNumber(versionNum, e); 807 BC_EXCEPTION_CHECK_ReturnVoid(e); 808 int32_t numBytes = version->GetTotalCodeWords(); 809 CBC_QRCoderECBlocks* ecBlocks = version->GetECBlocksForLevel(ecLevel); 810 int32_t numEcBytes = ecBlocks->GetTotalECCodeWords(); 811 int32_t numRSBlocks = ecBlocks->GetNumBlocks(); 812 int32_t numDataBytes = numBytes - numEcBytes; 813 if (numDataBytes >= numInputBytes + 3) { 814 qrCode->SetVersion(versionNum); 815 qrCode->SetNumTotalBytes(numBytes); 816 qrCode->SetNumDataBytes(numDataBytes); 817 qrCode->SetNumRSBlocks(numRSBlocks); 818 qrCode->SetNumECBytes(numEcBytes); 819 qrCode->SetMatrixWidth(version->GetDimensionForVersion()); 820 return; 821 } 822 } 823 e = BCExceptionCannotFindBlockInfo; 824 BC_EXCEPTION_CHECK_ReturnVoid(e); 825 } 826 void CBC_QRCoderEncoder::AppendModeInfo(CBC_QRCoderMode* mode, 827 CBC_QRCoderBitVector* bits, 828 int32_t& e) { 829 bits->AppendBits(mode->GetBits(), 4, e); 830 if (mode == CBC_QRCoderMode::sGBK) { 831 bits->AppendBits(1, 4, e); 832 BC_EXCEPTION_CHECK_ReturnVoid(e); 833 } 834 } 835 void CBC_QRCoderEncoder::AppendLengthInfo(int32_t numLetters, 836 int32_t version, 837 CBC_QRCoderMode* mode, 838 CBC_QRCoderBitVector* bits, 839 int32_t& e) { 840 CBC_QRCoderVersion* qcv = CBC_QRCoderVersion::GetVersionForNumber(version, e); 841 BC_EXCEPTION_CHECK_ReturnVoid(e); 842 int32_t numBits = mode->GetCharacterCountBits(qcv, e); 843 BC_EXCEPTION_CHECK_ReturnVoid(e); 844 if (numBits > ((1 << numBits) - 1)) { 845 return; 846 } 847 if (mode == CBC_QRCoderMode::sGBK) { 848 bits->AppendBits(numLetters / 2, numBits, e); 849 BC_EXCEPTION_CHECK_ReturnVoid(e); 850 } 851 bits->AppendBits(numLetters, numBits, e); 852 BC_EXCEPTION_CHECK_ReturnVoid(e); 853 } 854 void CBC_QRCoderEncoder::InterleaveWithECBytes(CBC_QRCoderBitVector* bits, 855 int32_t numTotalBytes, 856 int32_t numDataBytes, 857 int32_t numRSBlocks, 858 CBC_QRCoderBitVector* result, 859 int32_t& e) { 860 if (bits->sizeInBytes() != numDataBytes) { 861 e = BCExceptionBitsBytesNotMatch; 862 BC_EXCEPTION_CHECK_ReturnVoid(e); 863 } 864 int32_t dataBytesOffset = 0; 865 int32_t maxNumDataBytes = 0; 866 int32_t maxNumEcBytes = 0; 867 CFX_PtrArray blocks; 868 int32_t i; 869 for (i = 0; i < numRSBlocks; i++) { 870 int32_t numDataBytesInBlock; 871 int32_t numEcBytesInBlosk; 872 GetNumDataBytesAndNumECBytesForBlockID(numTotalBytes, numDataBytes, 873 numRSBlocks, i, numDataBytesInBlock, 874 numEcBytesInBlosk); 875 CBC_CommonByteArray* dataBytes = new CBC_CommonByteArray; 876 dataBytes->Set(bits->GetArray(), dataBytesOffset, numDataBytesInBlock); 877 CBC_CommonByteArray* ecBytes = 878 GenerateECBytes(dataBytes, numEcBytesInBlosk, e); 879 BC_EXCEPTION_CHECK_ReturnVoid(e); 880 blocks.Add(new CBC_QRCoderBlockPair(dataBytes, ecBytes)); 881 maxNumDataBytes = std::max(maxNumDataBytes, dataBytes->Size()); 882 maxNumEcBytes = std::max(maxNumEcBytes, ecBytes->Size()); 883 dataBytesOffset += numDataBytesInBlock; 884 } 885 if (numDataBytes != dataBytesOffset) { 886 e = BCExceptionBytesNotMatchOffset; 887 BC_EXCEPTION_CHECK_ReturnVoid(e); 888 } 889 for (int32_t x = 0; x < maxNumDataBytes; x++) { 890 for (int32_t j = 0; j < blocks.GetSize(); j++) { 891 CBC_CommonByteArray* dataBytes = 892 ((CBC_QRCoderBlockPair*)blocks[j])->GetDataBytes(); 893 if (x < dataBytes->Size()) { 894 result->AppendBits(dataBytes->At(x), 8, e); 895 BC_EXCEPTION_CHECK_ReturnVoid(e); 896 } 897 } 898 } 899 for (int32_t y = 0; y < maxNumEcBytes; y++) { 900 for (int32_t l = 0; l < blocks.GetSize(); l++) { 901 CBC_CommonByteArray* ecBytes = 902 ((CBC_QRCoderBlockPair*)blocks[l])->GetErrorCorrectionBytes(); 903 if (y < ecBytes->Size()) { 904 result->AppendBits(ecBytes->At(y), 8, e); 905 BC_EXCEPTION_CHECK_ReturnVoid(e); 906 } 907 } 908 } 909 for (int32_t k = 0; k < blocks.GetSize(); k++) { 910 delete (CBC_QRCoderBlockPair*)blocks[k]; 911 } 912 if (numTotalBytes != result->sizeInBytes()) { 913 e = BCExceptionSizeInBytesDiffer; 914 BC_EXCEPTION_CHECK_ReturnVoid(e); 915 } 916 } 917 void CBC_QRCoderEncoder::GetNumDataBytesAndNumECBytesForBlockID( 918 int32_t numTotalBytes, 919 int32_t numDataBytes, 920 int32_t numRSBlocks, 921 int32_t blockID, 922 int32_t& numDataBytesInBlock, 923 int32_t& numECBytesInBlock) { 924 if (blockID >= numRSBlocks) { 925 return; 926 } 927 int32_t numRsBlocksInGroup2 = numTotalBytes % numRSBlocks; 928 int32_t numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2; 929 int32_t numTotalBytesInGroup1 = numTotalBytes / numRSBlocks; 930 int32_t numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1; 931 int32_t numDataBytesInGroup1 = numDataBytes / numRSBlocks; 932 int32_t numDataBytesInGroup2 = numDataBytesInGroup1 + 1; 933 int32_t numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1; 934 int32_t numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2; 935 if (blockID < numRsBlocksInGroup1) { 936 numDataBytesInBlock = numDataBytesInGroup1; 937 numECBytesInBlock = numEcBytesInGroup1; 938 } else { 939 numDataBytesInBlock = numDataBytesInGroup2; 940 numECBytesInBlock = numEcBytesInGroup2; 941 } 942 } 943 CBC_CommonByteArray* CBC_QRCoderEncoder::GenerateECBytes( 944 CBC_CommonByteArray* dataBytes, 945 int32_t numEcBytesInBlock, 946 int32_t& e) { 947 int32_t numDataBytes = dataBytes->Size(); 948 CFX_Int32Array toEncode; 949 toEncode.SetSize(numDataBytes + numEcBytesInBlock); 950 for (int32_t i = 0; i < numDataBytes; i++) { 951 toEncode[i] = (dataBytes->At(i)); 952 } 953 CBC_ReedSolomonEncoder encode(CBC_ReedSolomonGF256::QRCodeFild); 954 encode.Init(); 955 encode.Encode(&toEncode, numEcBytesInBlock, e); 956 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); 957 CBC_CommonByteArray* ecBytes = new CBC_CommonByteArray(numEcBytesInBlock); 958 for (int32_t j = 0; j < numEcBytesInBlock; j++) { 959 ecBytes->Set(j, toEncode[numDataBytes + j]); 960 } 961 return ecBytes; 962 } 963