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 "xfa/src/fxbarcode/barcode.h"
24 #include "xfa/src/fxbarcode/common/BC_CommonByteMatrix.h"
25 #include "BC_QRCoderErrorCorrectionLevel.h"
26 #include "BC_QRCoder.h"
27 #include "BC_QRCoderMaskUtil.h"
28 #include "BC_QRCoderMatrixUtil.h"
29 #include "BC_QRCoderBitVector.h"
30 const int32_t CBC_QRCoderMatrixUtil::POSITION_DETECTION_PATTERN[7][7] = {
31     {1, 1, 1, 1, 1, 1, 1},
32     {1, 0, 0, 0, 0, 0, 1},
33     {1, 0, 1, 1, 1, 0, 1},
34     {1, 0, 1, 1, 1, 0, 1},
35     {1, 0, 1, 1, 1, 0, 1},
36     {1, 0, 0, 0, 0, 0, 1},
37     {1, 1, 1, 1, 1, 1, 1}};
38 const int32_t CBC_QRCoderMatrixUtil::HORIZONTAL_SEPARATION_PATTERN[1][8] = {
39     {0, 0, 0, 0, 0, 0, 0, 0}};
40 const int32_t CBC_QRCoderMatrixUtil::VERTICAL_SEPARATION_PATTERN[7][1] =
41     {{0}, {0}, {0}, {0}, {0}, {0}, {0}};
42 const int32_t CBC_QRCoderMatrixUtil::POSITION_ADJUSTMENT_PATTERN[5][5] = {
43     {1, 1, 1, 1, 1},
44     {1, 0, 0, 0, 1},
45     {1, 0, 1, 0, 1},
46     {1, 0, 0, 0, 1},
47     {1, 1, 1, 1, 1}};
48 const int32_t
49     CBC_QRCoderMatrixUtil::POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[40][7] =
50         {
51             {-1, -1, -1, -1, -1, -1, -1},   {6, 18, -1, -1, -1, -1, -1},
52             {6, 22, -1, -1, -1, -1, -1},    {6, 26, -1, -1, -1, -1, -1},
53             {6, 30, -1, -1, -1, -1, -1},    {6, 34, -1, -1, -1, -1, -1},
54             {6, 22, 38, -1, -1, -1, -1},    {6, 24, 42, -1, -1, -1, -1},
55             {6, 26, 46, -1, -1, -1, -1},    {6, 28, 50, -1, -1, -1, -1},
56             {6, 30, 54, -1, -1, -1, -1},    {6, 32, 58, -1, -1, -1, -1},
57             {6, 34, 62, -1, -1, -1, -1},    {6, 26, 46, 66, -1, -1, -1},
58             {6, 26, 48, 70, -1, -1, -1},    {6, 26, 50, 74, -1, -1, -1},
59             {6, 30, 54, 78, -1, -1, -1},    {6, 30, 56, 82, -1, -1, -1},
60             {6, 30, 58, 86, -1, -1, -1},    {6, 34, 62, 90, -1, -1, -1},
61             {6, 28, 50, 72, 94, -1, -1},    {6, 26, 50, 74, 98, -1, -1},
62             {6, 30, 54, 78, 102, -1, -1},   {6, 28, 54, 80, 106, -1, -1},
63             {6, 32, 58, 84, 110, -1, -1},   {6, 30, 58, 86, 114, -1, -1},
64             {6, 34, 62, 90, 118, -1, -1},   {6, 26, 50, 74, 98, 122, -1},
65             {6, 30, 54, 78, 102, 126, -1},  {6, 26, 52, 78, 104, 130, -1},
66             {6, 30, 56, 82, 108, 134, -1},  {6, 34, 60, 86, 112, 138, -1},
67             {6, 30, 58, 86, 114, 142, -1},  {6, 34, 62, 90, 118, 146, -1},
68             {6, 30, 54, 78, 102, 126, 150}, {6, 24, 50, 76, 102, 128, 154},
69             {6, 28, 54, 80, 106, 132, 158}, {6, 32, 58, 84, 110, 136, 162},
70             {6, 26, 54, 82, 110, 138, 166}, {6, 30, 58, 86, 114, 142, 170},
71 };
72 const int32_t CBC_QRCoderMatrixUtil::TYPE_INFO_COORDINATES[15][2] = {
73     {8, 0}, {8, 1}, {8, 2}, {8, 3}, {8, 4}, {8, 5}, {8, 7}, {8, 8},
74     {7, 8}, {5, 8}, {4, 8}, {3, 8}, {2, 8}, {1, 8}, {0, 8},
75 };
76 const int32_t CBC_QRCoderMatrixUtil::VERSION_INFO_POLY = 0x1f25;
77 const int32_t CBC_QRCoderMatrixUtil::TYPE_INFO_POLY = 0x0537;
78 const int32_t CBC_QRCoderMatrixUtil::TYPE_INFO_MASK_PATTERN = 0x5412;
ClearMatrix(CBC_CommonByteMatrix * matrix,int32_t & e)79 void CBC_QRCoderMatrixUtil::ClearMatrix(CBC_CommonByteMatrix* matrix,
80                                         int32_t& e) {
81   if (matrix == NULL) {
82     e = BCExceptionNullPointer;
83     BC_EXCEPTION_CHECK_ReturnVoid(e);
84   }
85   matrix->clear((uint8_t)-1);
86 }
BuildMatrix(CBC_QRCoderBitVector * dataBits,CBC_QRCoderErrorCorrectionLevel * ecLevel,int32_t version,int32_t maskPattern,CBC_CommonByteMatrix * matrix,int32_t & e)87 void CBC_QRCoderMatrixUtil::BuildMatrix(
88     CBC_QRCoderBitVector* dataBits,
89     CBC_QRCoderErrorCorrectionLevel* ecLevel,
90     int32_t version,
91     int32_t maskPattern,
92     CBC_CommonByteMatrix* matrix,
93     int32_t& e) {
94   if (matrix == NULL) {
95     e = BCExceptionNullPointer;
96     BC_EXCEPTION_CHECK_ReturnVoid(e);
97   }
98   ClearMatrix(matrix, e);
99   BC_EXCEPTION_CHECK_ReturnVoid(e);
100   EmbedBasicPatterns(version, matrix, e);
101   BC_EXCEPTION_CHECK_ReturnVoid(e);
102   EmbedTypeInfo(ecLevel, maskPattern, matrix, e);
103   BC_EXCEPTION_CHECK_ReturnVoid(e);
104   MaybeEmbedVersionInfo(version, matrix, e);
105   BC_EXCEPTION_CHECK_ReturnVoid(e);
106   EmbedDataBits(dataBits, maskPattern, matrix, e);
107   BC_EXCEPTION_CHECK_ReturnVoid(e);
108 }
EmbedBasicPatterns(int32_t version,CBC_CommonByteMatrix * matrix,int32_t & e)109 void CBC_QRCoderMatrixUtil::EmbedBasicPatterns(int32_t version,
110                                                CBC_CommonByteMatrix* matrix,
111                                                int32_t& e) {
112   if (matrix == NULL) {
113     e = BCExceptionNullPointer;
114     BC_EXCEPTION_CHECK_ReturnVoid(e);
115   }
116   EmbedPositionDetectionPatternsAndSeparators(matrix, e);
117   BC_EXCEPTION_CHECK_ReturnVoid(e);
118   EmbedDarkDotAtLeftBottomCorner(matrix, e);
119   BC_EXCEPTION_CHECK_ReturnVoid(e);
120   MaybeEmbedPositionAdjustmentPatterns(version, matrix, e);
121   BC_EXCEPTION_CHECK_ReturnVoid(e);
122   EmbedTimingPatterns(matrix, e);
123   BC_EXCEPTION_CHECK_ReturnVoid(e);
124 }
EmbedTypeInfo(CBC_QRCoderErrorCorrectionLevel * ecLevel,int32_t maskPattern,CBC_CommonByteMatrix * matrix,int32_t & e)125 void CBC_QRCoderMatrixUtil::EmbedTypeInfo(
126     CBC_QRCoderErrorCorrectionLevel* ecLevel,
127     int32_t maskPattern,
128     CBC_CommonByteMatrix* matrix,
129     int32_t& e) {
130   if (matrix == NULL) {
131     e = BCExceptionNullPointer;
132     BC_EXCEPTION_CHECK_ReturnVoid(e);
133   }
134   CBC_QRCoderBitVector typeInfoBits;
135   typeInfoBits.Init();
136   MakeTypeInfoBits(ecLevel, maskPattern, &typeInfoBits, e);
137   BC_EXCEPTION_CHECK_ReturnVoid(e);
138   for (int32_t i = 0; i < typeInfoBits.Size(); i++) {
139     int32_t bit = typeInfoBits.At(typeInfoBits.Size() - 1 - i, e);
140     BC_EXCEPTION_CHECK_ReturnVoid(e);
141     int32_t x1 = TYPE_INFO_COORDINATES[i][0];
142     int32_t y1 = TYPE_INFO_COORDINATES[i][1];
143     matrix->Set(x1, y1, bit);
144     if (i < 8) {
145       int32_t x2 = matrix->GetWidth() - i - 1;
146       int32_t y2 = 8;
147       matrix->Set(x2, y2, bit);
148     } else {
149       int32_t x2 = 8;
150       int32_t y2 = matrix->GetHeight() - 7 + (i - 8);
151       matrix->Set(x2, y2, bit);
152     }
153   }
154 }
MaybeEmbedVersionInfo(int32_t version,CBC_CommonByteMatrix * matrix,int32_t & e)155 void CBC_QRCoderMatrixUtil::MaybeEmbedVersionInfo(int32_t version,
156                                                   CBC_CommonByteMatrix* matrix,
157                                                   int32_t& e) {
158   if (matrix == NULL) {
159     e = BCExceptionNullPointer;
160     BC_EXCEPTION_CHECK_ReturnVoid(e);
161   }
162   if (version < 7) {
163     return;
164   }
165   CBC_QRCoderBitVector versionInfoBits;
166   versionInfoBits.Init();
167   MakeVersionInfoBits(version, &versionInfoBits, e);
168   BC_EXCEPTION_CHECK_ReturnVoid(e);
169   int32_t bitIndex = 6 * 3 - 1;
170   for (int32_t i = 0; i < 6; i++) {
171     for (int32_t j = 0; j < 3; j++) {
172       int32_t bit = versionInfoBits.At(bitIndex, e);
173       BC_EXCEPTION_CHECK_ReturnVoid(e);
174       bitIndex--;
175       matrix->Set(i, matrix->GetHeight() - 11 + j, bit);
176       matrix->Set(matrix->GetHeight() - 11 + j, i, bit);
177     }
178   }
179 }
EmbedDataBits(CBC_QRCoderBitVector * dataBits,int32_t maskPattern,CBC_CommonByteMatrix * matrix,int32_t & e)180 void CBC_QRCoderMatrixUtil::EmbedDataBits(CBC_QRCoderBitVector* dataBits,
181                                           int32_t maskPattern,
182                                           CBC_CommonByteMatrix* matrix,
183                                           int32_t& e) {
184   if (matrix == NULL || dataBits == NULL) {
185     e = BCExceptionNullPointer;
186     BC_EXCEPTION_CHECK_ReturnVoid(e);
187   }
188   int32_t bitIndex = 0;
189   int32_t direction = -1;
190   int32_t x = matrix->GetWidth() - 1;
191   int32_t y = matrix->GetHeight() - 1;
192   while (x > 0) {
193     if (x == 6) {
194       x -= 1;
195     }
196     while (y >= 0 && y < matrix->GetHeight()) {
197       if (y == 6) {
198         y += direction;
199         continue;
200       }
201       for (int32_t i = 0; i < 2; i++) {
202         int32_t xx = x - i;
203         if (!IsEmpty(matrix->Get(xx, y))) {
204           continue;
205         }
206         int32_t bit;
207         if (bitIndex < dataBits->Size()) {
208           bit = dataBits->At(bitIndex, e);
209           BC_EXCEPTION_CHECK_ReturnVoid(e);
210           bitIndex++;
211         } else {
212           bit = 0;
213         }
214         if (maskPattern != -1) {
215           FX_BOOL bol =
216               CBC_QRCoderMaskUtil::GetDataMaskBit(maskPattern, xx, y, e);
217           BC_EXCEPTION_CHECK_ReturnVoid(e);
218           if (bol) {
219             bit ^= 0x01;
220           }
221         }
222         matrix->Set(xx, y, bit);
223       }
224       y += direction;
225     }
226     direction = -direction;
227     y += direction;
228     x -= 2;
229   }
230   if (bitIndex != dataBits->Size()) {
231     return;
232   }
233 }
CalculateBCHCode(int32_t value,int32_t poly)234 int32_t CBC_QRCoderMatrixUtil::CalculateBCHCode(int32_t value, int32_t poly) {
235   int32_t msbSetInPoly = FindMSBSet(poly);
236   value <<= msbSetInPoly - 1;
237   while (FindMSBSet(value) >= msbSetInPoly) {
238     value ^= poly << (FindMSBSet(value) - msbSetInPoly);
239   }
240   return value;
241 }
MakeTypeInfoBits(CBC_QRCoderErrorCorrectionLevel * ecLevel,int32_t maskPattern,CBC_QRCoderBitVector * bits,int32_t & e)242 void CBC_QRCoderMatrixUtil::MakeTypeInfoBits(
243     CBC_QRCoderErrorCorrectionLevel* ecLevel,
244     int32_t maskPattern,
245     CBC_QRCoderBitVector* bits,
246     int32_t& e) {
247   if (bits == NULL) {
248     e = BCExceptionNullPointer;
249     BC_EXCEPTION_CHECK_ReturnVoid(e);
250   }
251   if (!CBC_QRCoder::IsValidMaskPattern(maskPattern)) {
252     e = BCExceptionBadMask;
253     BC_EXCEPTION_CHECK_ReturnVoid(e);
254   }
255   int32_t typeInfo = (ecLevel->GetBits() << 3) | maskPattern;
256   BC_EXCEPTION_CHECK_ReturnVoid(e);
257   bits->AppendBits(typeInfo, 5, e);
258   int32_t bchCode = CalculateBCHCode(typeInfo, TYPE_INFO_POLY);
259   BC_EXCEPTION_CHECK_ReturnVoid(e);
260   bits->AppendBits(bchCode, 10, e);
261   CBC_QRCoderBitVector maskBits;
262   maskBits.Init();
263   maskBits.AppendBits(TYPE_INFO_MASK_PATTERN, 15, e);
264   BC_EXCEPTION_CHECK_ReturnVoid(e);
265   bits->XOR(&maskBits, e);
266   BC_EXCEPTION_CHECK_ReturnVoid(e);
267   if (bits->Size() != 15) {
268     e = BCExceptionBitSizeNot15;
269     BC_EXCEPTION_CHECK_ReturnVoid(e);
270   }
271 }
MakeVersionInfoBits(int32_t version,CBC_QRCoderBitVector * bits,int32_t & e)272 void CBC_QRCoderMatrixUtil::MakeVersionInfoBits(int32_t version,
273                                                 CBC_QRCoderBitVector* bits,
274                                                 int32_t& e) {
275   if (bits == NULL) {
276     e = BCExceptionNullPointer;
277     BC_EXCEPTION_CHECK_ReturnVoid(e);
278   }
279   bits->AppendBits(version, 6, e);
280   BC_EXCEPTION_CHECK_ReturnVoid(e);
281   int32_t bchCode = CalculateBCHCode(version, VERSION_INFO_POLY);
282   bits->AppendBits(bchCode, 12, e);
283   BC_EXCEPTION_CHECK_ReturnVoid(e);
284   if (bits->Size() != 18) {
285     e = BCExceptionBitSizeNot18;
286     BC_EXCEPTION_CHECK_ReturnVoid(e);
287   }
288 }
IsEmpty(int32_t value)289 FX_BOOL CBC_QRCoderMatrixUtil::IsEmpty(int32_t value) {
290   return (uint8_t)value == 0xff;
291 }
IsValidValue(int32_t value)292 FX_BOOL CBC_QRCoderMatrixUtil::IsValidValue(int32_t value) {
293   return ((uint8_t)value == 0xff || (uint8_t)value == 0x00 ||
294           (uint8_t)value == 0x01);
295 }
EmbedTimingPatterns(CBC_CommonByteMatrix * matrix,int32_t & e)296 void CBC_QRCoderMatrixUtil::EmbedTimingPatterns(CBC_CommonByteMatrix* matrix,
297                                                 int32_t& e) {
298   if (matrix == NULL) {
299     e = BCExceptionNullPointer;
300     BC_EXCEPTION_CHECK_ReturnVoid(e);
301   }
302   for (int32_t i = 8; i < matrix->GetWidth() - 8; i++) {
303     int32_t bit = (i + 1) % 2;
304     if (!IsValidValue(matrix->Get(i, 6))) {
305       e = BCExceptionInvalidateImageData;
306       BC_EXCEPTION_CHECK_ReturnVoid(e);
307     }
308     if (IsEmpty(matrix->Get(i, 6))) {
309       matrix->Set(i, 6, bit);
310     }
311     if (!IsValidValue(matrix->Get(6, i))) {
312       e = BCExceptionInvalidateImageData;
313       BC_EXCEPTION_CHECK_ReturnVoid(e);
314     }
315     if (IsEmpty(matrix->Get(6, i))) {
316       matrix->Set(6, i, bit);
317     }
318   }
319 }
EmbedDarkDotAtLeftBottomCorner(CBC_CommonByteMatrix * matrix,int32_t & e)320 void CBC_QRCoderMatrixUtil::EmbedDarkDotAtLeftBottomCorner(
321     CBC_CommonByteMatrix* matrix,
322     int32_t& e) {
323   if (matrix == NULL) {
324     e = BCExceptionNullPointer;
325     BC_EXCEPTION_CHECK_ReturnVoid(e);
326   }
327   if (matrix->Get(8, matrix->GetHeight() - 8) == 0) {
328     e = BCExceptionHeight_8BeZero;
329     BC_EXCEPTION_CHECK_ReturnVoid(e);
330   }
331   matrix->Set(8, matrix->GetHeight() - 8, 1);
332 }
EmbedHorizontalSeparationPattern(int32_t xStart,int32_t yStart,CBC_CommonByteMatrix * matrix,int32_t & e)333 void CBC_QRCoderMatrixUtil::EmbedHorizontalSeparationPattern(
334     int32_t xStart,
335     int32_t yStart,
336     CBC_CommonByteMatrix* matrix,
337     int32_t& e) {
338   if (matrix == NULL) {
339     e = BCExceptionNullPointer;
340     BC_EXCEPTION_CHECK_ReturnVoid(e);
341   }
342   for (int32_t x = 0; x < 8; x++) {
343     if (!IsEmpty(matrix->Get(xStart + x, yStart))) {
344       e = BCExceptionInvalidateData;
345       BC_EXCEPTION_CHECK_ReturnVoid(e)
346     }
347     matrix->Set(xStart + x, yStart, HORIZONTAL_SEPARATION_PATTERN[0][x]);
348   }
349 }
EmbedVerticalSeparationPattern(int32_t xStart,int32_t yStart,CBC_CommonByteMatrix * matrix,int32_t & e)350 void CBC_QRCoderMatrixUtil::EmbedVerticalSeparationPattern(
351     int32_t xStart,
352     int32_t yStart,
353     CBC_CommonByteMatrix* matrix,
354     int32_t& e) {
355   if (matrix == NULL) {
356     e = BCExceptionNullPointer;
357     BC_EXCEPTION_CHECK_ReturnVoid(e);
358   }
359   for (int32_t y = 0; y < 7; y++) {
360     if (!IsEmpty(matrix->Get(xStart, yStart + y))) {
361       e = BCExceptionInvalidateData;
362       BC_EXCEPTION_CHECK_ReturnVoid(e);
363     }
364     matrix->Set(xStart, yStart + y, VERTICAL_SEPARATION_PATTERN[y][0]);
365   }
366 }
EmbedPositionAdjustmentPattern(int32_t xStart,int32_t yStart,CBC_CommonByteMatrix * matrix,int32_t & e)367 void CBC_QRCoderMatrixUtil::EmbedPositionAdjustmentPattern(
368     int32_t xStart,
369     int32_t yStart,
370     CBC_CommonByteMatrix* matrix,
371     int32_t& e) {
372   if (matrix == NULL) {
373     e = BCExceptionNullPointer;
374     BC_EXCEPTION_CHECK_ReturnVoid(e);
375   }
376   for (int32_t y = 0; y < 5; y++) {
377     for (int32_t x = 0; x < 5; x++) {
378       if (!IsEmpty(matrix->Get(xStart + x, y + yStart))) {
379         e = BCExceptionInvalidateData;
380         BC_EXCEPTION_CHECK_ReturnVoid(e);
381       }
382       matrix->Set(xStart + x, yStart + y, POSITION_ADJUSTMENT_PATTERN[y][x]);
383     }
384   }
385 }
EmbedPositionDetectionPattern(int32_t xStart,int32_t yStart,CBC_CommonByteMatrix * matrix,int32_t & e)386 void CBC_QRCoderMatrixUtil::EmbedPositionDetectionPattern(
387     int32_t xStart,
388     int32_t yStart,
389     CBC_CommonByteMatrix* matrix,
390     int32_t& e) {
391   if (matrix == NULL) {
392     e = BCExceptionNullPointer;
393     BC_EXCEPTION_CHECK_ReturnVoid(e);
394   }
395   for (int32_t y = 0; y < 7; y++) {
396     for (int32_t x = 0; x < 7; x++) {
397       if (!IsEmpty(matrix->Get(xStart + x, yStart + y))) {
398         e = BCExceptionInvalidateData;
399         BC_EXCEPTION_CHECK_ReturnVoid(e);
400       }
401       matrix->Set(xStart + x, yStart + y, POSITION_DETECTION_PATTERN[y][x]);
402     }
403   }
404 }
EmbedPositionDetectionPatternsAndSeparators(CBC_CommonByteMatrix * matrix,int32_t & e)405 void CBC_QRCoderMatrixUtil::EmbedPositionDetectionPatternsAndSeparators(
406     CBC_CommonByteMatrix* matrix,
407     int32_t& e) {
408   if (matrix == NULL) {
409     e = BCExceptionNullPointer;
410     BC_EXCEPTION_CHECK_ReturnVoid(e);
411   }
412   int32_t pdpWidth = 7;
413   EmbedPositionDetectionPattern(0, 0, matrix, e);
414   BC_EXCEPTION_CHECK_ReturnVoid(e);
415   EmbedPositionDetectionPattern(matrix->GetWidth() - pdpWidth, 0, matrix, e);
416   BC_EXCEPTION_CHECK_ReturnVoid(e);
417   EmbedPositionDetectionPattern(0, matrix->GetWidth() - pdpWidth, matrix, e);
418   BC_EXCEPTION_CHECK_ReturnVoid(e);
419   int32_t hspWidth = 8;
420   EmbedHorizontalSeparationPattern(0, hspWidth - 1, matrix, e);
421   BC_EXCEPTION_CHECK_ReturnVoid(e);
422   EmbedHorizontalSeparationPattern(matrix->GetWidth() - hspWidth, hspWidth - 1,
423                                    matrix, e);
424   BC_EXCEPTION_CHECK_ReturnVoid(e);
425   EmbedHorizontalSeparationPattern(0, matrix->GetWidth() - hspWidth, matrix, e);
426   BC_EXCEPTION_CHECK_ReturnVoid(e);
427   int32_t vspSize = 7;
428   EmbedVerticalSeparationPattern(vspSize, 0, matrix, e);
429   BC_EXCEPTION_CHECK_ReturnVoid(e);
430   EmbedVerticalSeparationPattern(matrix->GetHeight() - vspSize - 1, 0, matrix,
431                                  e);
432   BC_EXCEPTION_CHECK_ReturnVoid(e);
433   EmbedVerticalSeparationPattern(vspSize, matrix->GetHeight() - vspSize, matrix,
434                                  e);
435   BC_EXCEPTION_CHECK_ReturnVoid(e);
436 }
MaybeEmbedPositionAdjustmentPatterns(int32_t version,CBC_CommonByteMatrix * matrix,int32_t & e)437 void CBC_QRCoderMatrixUtil::MaybeEmbedPositionAdjustmentPatterns(
438     int32_t version,
439     CBC_CommonByteMatrix* matrix,
440     int32_t& e) {
441   if (matrix == NULL) {
442     e = BCExceptionNullPointer;
443     BC_EXCEPTION_CHECK_ReturnVoid(e);
444   }
445   if (version < 2) {
446     return;
447   }
448   int32_t index = version - 1;
449   int32_t const* coordinates =
450       &(POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index][0]);
451   int32_t numCoordinate = 7;
452   for (int32_t i = 0; i < numCoordinate; i++) {
453     for (int32_t j = 0; j < numCoordinate; j++) {
454       int32_t y = coordinates[i];
455       int32_t x = coordinates[j];
456       if (x == -1 || y == -1) {
457         continue;
458       }
459       if (IsEmpty(matrix->Get(x, y))) {
460         EmbedPositionAdjustmentPattern(x - 2, y - 2, matrix, e);
461         BC_EXCEPTION_CHECK_ReturnVoid(e);
462       }
463     }
464   }
465 }
FindMSBSet(int32_t value)466 int32_t CBC_QRCoderMatrixUtil::FindMSBSet(int32_t value) {
467   int32_t numDigits = 0;
468   while (value != 0) {
469     value >>= 1;
470     ++numDigits;
471   }
472   return numDigits;
473 }
CBC_QRCoderMatrixUtil()474 CBC_QRCoderMatrixUtil::CBC_QRCoderMatrixUtil() {}
~CBC_QRCoderMatrixUtil()475 CBC_QRCoderMatrixUtil::~CBC_QRCoderMatrixUtil() {}
476