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