blob: 757f4ef7f44b9e52368eb3c949d52301b52ea5be [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// 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/fxbarcode/common/BC_CommonByteMatrix.h"
24#include "xfa/fxbarcode/qrcode/BC_QRCoder.h"
25#include "xfa/fxbarcode/qrcode/BC_QRCoderBitVector.h"
26#include "xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h"
27#include "xfa/fxbarcode/qrcode/BC_QRCoderMaskUtil.h"
28#include "xfa/fxbarcode/qrcode/BC_QRCoderMatrixUtil.h"
29#include "xfa/fxbarcode/utils.h"
30
31const int32_t CBC_QRCoderMatrixUtil::POSITION_DETECTION_PATTERN[7][7] = {
32 {1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 1}, {1, 0, 1, 1, 1, 0, 1},
33 {1, 0, 1, 1, 1, 0, 1}, {1, 0, 1, 1, 1, 0, 1}, {1, 0, 0, 0, 0, 0, 1},
34 {1, 1, 1, 1, 1, 1, 1}};
35const int32_t CBC_QRCoderMatrixUtil::HORIZONTAL_SEPARATION_PATTERN[1][8] = {
36 {0, 0, 0, 0, 0, 0, 0, 0}};
37const int32_t CBC_QRCoderMatrixUtil::VERTICAL_SEPARATION_PATTERN[7][1] = {
38 {0}, {0}, {0}, {0}, {0}, {0}, {0}};
39const int32_t CBC_QRCoderMatrixUtil::POSITION_ADJUSTMENT_PATTERN[5][5] = {
40 {1, 1, 1, 1, 1},
41 {1, 0, 0, 0, 1},
42 {1, 0, 1, 0, 1},
43 {1, 0, 0, 0, 1},
44 {1, 1, 1, 1, 1}};
45const int32_t
46 CBC_QRCoderMatrixUtil::POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[40][7] =
47 // NOLINTNEXTLINE
48 {
49 {-1, -1, -1, -1, -1, -1, -1}, {6, 18, -1, -1, -1, -1, -1},
50 {6, 22, -1, -1, -1, -1, -1}, {6, 26, -1, -1, -1, -1, -1},
51 {6, 30, -1, -1, -1, -1, -1}, {6, 34, -1, -1, -1, -1, -1},
52 {6, 22, 38, -1, -1, -1, -1}, {6, 24, 42, -1, -1, -1, -1},
53 {6, 26, 46, -1, -1, -1, -1}, {6, 28, 50, -1, -1, -1, -1},
54 {6, 30, 54, -1, -1, -1, -1}, {6, 32, 58, -1, -1, -1, -1},
55 {6, 34, 62, -1, -1, -1, -1}, {6, 26, 46, 66, -1, -1, -1},
56 {6, 26, 48, 70, -1, -1, -1}, {6, 26, 50, 74, -1, -1, -1},
57 {6, 30, 54, 78, -1, -1, -1}, {6, 30, 56, 82, -1, -1, -1},
58 {6, 30, 58, 86, -1, -1, -1}, {6, 34, 62, 90, -1, -1, -1},
59 {6, 28, 50, 72, 94, -1, -1}, {6, 26, 50, 74, 98, -1, -1},
60 {6, 30, 54, 78, 102, -1, -1}, {6, 28, 54, 80, 106, -1, -1},
61 {6, 32, 58, 84, 110, -1, -1}, {6, 30, 58, 86, 114, -1, -1},
62 {6, 34, 62, 90, 118, -1, -1}, {6, 26, 50, 74, 98, 122, -1},
63 {6, 30, 54, 78, 102, 126, -1}, {6, 26, 52, 78, 104, 130, -1},
64 {6, 30, 56, 82, 108, 134, -1}, {6, 34, 60, 86, 112, 138, -1},
65 {6, 30, 58, 86, 114, 142, -1}, {6, 34, 62, 90, 118, 146, -1},
66 {6, 30, 54, 78, 102, 126, 150}, {6, 24, 50, 76, 102, 128, 154},
67 {6, 28, 54, 80, 106, 132, 158}, {6, 32, 58, 84, 110, 136, 162},
68 {6, 26, 54, 82, 110, 138, 166}, {6, 30, 58, 86, 114, 142, 170},
69};
70const int32_t CBC_QRCoderMatrixUtil::TYPE_INFO_COORDINATES[15][2] = {
71 {8, 0}, {8, 1}, {8, 2}, {8, 3}, {8, 4}, {8, 5}, {8, 7}, {8, 8},
72 {7, 8}, {5, 8}, {4, 8}, {3, 8}, {2, 8}, {1, 8}, {0, 8},
73};
74const int32_t CBC_QRCoderMatrixUtil::VERSION_INFO_POLY = 0x1f25;
75const int32_t CBC_QRCoderMatrixUtil::TYPE_INFO_POLY = 0x0537;
76const int32_t CBC_QRCoderMatrixUtil::TYPE_INFO_MASK_PATTERN = 0x5412;
77
78void CBC_QRCoderMatrixUtil::ClearMatrix(CBC_CommonByteMatrix* matrix,
79 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -070080 if (!matrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -040081 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -080082 if (e != BCExceptionNO)
83 return;
Dan Sinclair1770c022016-03-14 14:14:16 -040084 }
85 matrix->clear((uint8_t)-1);
86}
87void 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) {
thestig6dc1d772016-06-09 18:39:33 -070094 if (!matrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -040095 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -080096 if (e != BCExceptionNO)
97 return;
Dan Sinclair1770c022016-03-14 14:14:16 -040098 }
99 ClearMatrix(matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800100 if (e != BCExceptionNO)
101 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400102 EmbedBasicPatterns(version, matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800103 if (e != BCExceptionNO)
104 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400105 EmbedTypeInfo(ecLevel, maskPattern, matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800106 if (e != BCExceptionNO)
107 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400108 MaybeEmbedVersionInfo(version, matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800109 if (e != BCExceptionNO)
110 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400111 EmbedDataBits(dataBits, maskPattern, matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800112 if (e != BCExceptionNO)
113 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400114}
115void CBC_QRCoderMatrixUtil::EmbedBasicPatterns(int32_t version,
116 CBC_CommonByteMatrix* matrix,
117 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700118 if (!matrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400119 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800120 if (e != BCExceptionNO)
121 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400122 }
123 EmbedPositionDetectionPatternsAndSeparators(matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800124 if (e != BCExceptionNO)
125 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400126 EmbedDarkDotAtLeftBottomCorner(matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800127 if (e != BCExceptionNO)
128 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400129 MaybeEmbedPositionAdjustmentPatterns(version, matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800130 if (e != BCExceptionNO)
131 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400132 EmbedTimingPatterns(matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800133 if (e != BCExceptionNO)
134 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400135}
136void CBC_QRCoderMatrixUtil::EmbedTypeInfo(
137 CBC_QRCoderErrorCorrectionLevel* ecLevel,
138 int32_t maskPattern,
139 CBC_CommonByteMatrix* matrix,
140 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700141 if (!matrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400142 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800143 if (e != BCExceptionNO)
144 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400145 }
146 CBC_QRCoderBitVector typeInfoBits;
147 typeInfoBits.Init();
148 MakeTypeInfoBits(ecLevel, maskPattern, &typeInfoBits, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800149 if (e != BCExceptionNO)
150 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400151 for (int32_t i = 0; i < typeInfoBits.Size(); i++) {
152 int32_t bit = typeInfoBits.At(typeInfoBits.Size() - 1 - i, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800153 if (e != BCExceptionNO)
154 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400155 int32_t x1 = TYPE_INFO_COORDINATES[i][0];
156 int32_t y1 = TYPE_INFO_COORDINATES[i][1];
157 matrix->Set(x1, y1, bit);
158 if (i < 8) {
159 int32_t x2 = matrix->GetWidth() - i - 1;
160 int32_t y2 = 8;
161 matrix->Set(x2, y2, bit);
162 } else {
163 int32_t x2 = 8;
164 int32_t y2 = matrix->GetHeight() - 7 + (i - 8);
165 matrix->Set(x2, y2, bit);
166 }
167 }
168}
169void CBC_QRCoderMatrixUtil::MaybeEmbedVersionInfo(int32_t version,
170 CBC_CommonByteMatrix* matrix,
171 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700172 if (!matrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400173 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800174 if (e != BCExceptionNO)
175 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400176 }
177 if (version < 7) {
178 return;
179 }
180 CBC_QRCoderBitVector versionInfoBits;
181 versionInfoBits.Init();
182 MakeVersionInfoBits(version, &versionInfoBits, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800183 if (e != BCExceptionNO)
184 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400185 int32_t bitIndex = 6 * 3 - 1;
186 for (int32_t i = 0; i < 6; i++) {
187 for (int32_t j = 0; j < 3; j++) {
188 int32_t bit = versionInfoBits.At(bitIndex, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800189 if (e != BCExceptionNO)
190 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400191 bitIndex--;
192 matrix->Set(i, matrix->GetHeight() - 11 + j, bit);
193 matrix->Set(matrix->GetHeight() - 11 + j, i, bit);
194 }
195 }
196}
197void CBC_QRCoderMatrixUtil::EmbedDataBits(CBC_QRCoderBitVector* dataBits,
198 int32_t maskPattern,
199 CBC_CommonByteMatrix* matrix,
200 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700201 if (!matrix || !dataBits) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400202 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800203 if (e != BCExceptionNO)
204 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400205 }
206 int32_t bitIndex = 0;
207 int32_t direction = -1;
208 int32_t x = matrix->GetWidth() - 1;
209 int32_t y = matrix->GetHeight() - 1;
210 while (x > 0) {
211 if (x == 6) {
212 x -= 1;
213 }
214 while (y >= 0 && y < matrix->GetHeight()) {
215 if (y == 6) {
216 y += direction;
217 continue;
218 }
219 for (int32_t i = 0; i < 2; i++) {
220 int32_t xx = x - i;
221 if (!IsEmpty(matrix->Get(xx, y))) {
222 continue;
223 }
224 int32_t bit;
225 if (bitIndex < dataBits->Size()) {
226 bit = dataBits->At(bitIndex, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800227 if (e != BCExceptionNO)
228 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400229 bitIndex++;
230 } else {
231 bit = 0;
232 }
233 if (maskPattern != -1) {
tsepezd19e9122016-11-02 15:43:18 -0700234 bool bol = CBC_QRCoderMaskUtil::GetDataMaskBit(maskPattern, xx, y, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800235 if (e != BCExceptionNO)
236 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400237 if (bol) {
238 bit ^= 0x01;
239 }
240 }
241 matrix->Set(xx, y, bit);
242 }
243 y += direction;
244 }
245 direction = -direction;
246 y += direction;
247 x -= 2;
248 }
249 if (bitIndex != dataBits->Size()) {
250 return;
251 }
252}
253int32_t CBC_QRCoderMatrixUtil::CalculateBCHCode(int32_t value, int32_t poly) {
254 int32_t msbSetInPoly = FindMSBSet(poly);
255 value <<= msbSetInPoly - 1;
256 while (FindMSBSet(value) >= msbSetInPoly) {
257 value ^= poly << (FindMSBSet(value) - msbSetInPoly);
258 }
259 return value;
260}
261void CBC_QRCoderMatrixUtil::MakeTypeInfoBits(
262 CBC_QRCoderErrorCorrectionLevel* ecLevel,
263 int32_t maskPattern,
264 CBC_QRCoderBitVector* bits,
265 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700266 if (!bits) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400267 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800268 if (e != BCExceptionNO)
269 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400270 }
271 if (!CBC_QRCoder::IsValidMaskPattern(maskPattern)) {
272 e = BCExceptionBadMask;
Tom Sepezc8017b22017-01-31 13:02:10 -0800273 if (e != BCExceptionNO)
274 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400275 }
276 int32_t typeInfo = (ecLevel->GetBits() << 3) | maskPattern;
Tom Sepezc8017b22017-01-31 13:02:10 -0800277 if (e != BCExceptionNO)
278 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400279 bits->AppendBits(typeInfo, 5, e);
280 int32_t bchCode = CalculateBCHCode(typeInfo, TYPE_INFO_POLY);
Tom Sepezc8017b22017-01-31 13:02:10 -0800281 if (e != BCExceptionNO)
282 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400283 bits->AppendBits(bchCode, 10, e);
284 CBC_QRCoderBitVector maskBits;
285 maskBits.Init();
286 maskBits.AppendBits(TYPE_INFO_MASK_PATTERN, 15, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800287 if (e != BCExceptionNO)
288 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400289 bits->XOR(&maskBits, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800290 if (e != BCExceptionNO)
291 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400292 if (bits->Size() != 15) {
293 e = BCExceptionBitSizeNot15;
Tom Sepezc8017b22017-01-31 13:02:10 -0800294 if (e != BCExceptionNO)
295 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400296 }
297}
298void CBC_QRCoderMatrixUtil::MakeVersionInfoBits(int32_t version,
299 CBC_QRCoderBitVector* bits,
300 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700301 if (!bits) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400302 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800303 if (e != BCExceptionNO)
304 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400305 }
306 bits->AppendBits(version, 6, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800307 if (e != BCExceptionNO)
308 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400309 int32_t bchCode = CalculateBCHCode(version, VERSION_INFO_POLY);
310 bits->AppendBits(bchCode, 12, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800311 if (e != BCExceptionNO)
312 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400313 if (bits->Size() != 18) {
314 e = BCExceptionBitSizeNot18;
Tom Sepezc8017b22017-01-31 13:02:10 -0800315 if (e != BCExceptionNO)
316 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400317 }
318}
tsepezd19e9122016-11-02 15:43:18 -0700319bool CBC_QRCoderMatrixUtil::IsEmpty(int32_t value) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400320 return (uint8_t)value == 0xff;
321}
tsepezd19e9122016-11-02 15:43:18 -0700322bool CBC_QRCoderMatrixUtil::IsValidValue(int32_t value) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400323 return ((uint8_t)value == 0xff || (uint8_t)value == 0x00 ||
324 (uint8_t)value == 0x01);
325}
326void CBC_QRCoderMatrixUtil::EmbedTimingPatterns(CBC_CommonByteMatrix* matrix,
327 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700328 if (!matrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400329 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800330 if (e != BCExceptionNO)
331 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400332 }
333 for (int32_t i = 8; i < matrix->GetWidth() - 8; i++) {
334 int32_t bit = (i + 1) % 2;
335 if (!IsValidValue(matrix->Get(i, 6))) {
336 e = BCExceptionInvalidateImageData;
Tom Sepezc8017b22017-01-31 13:02:10 -0800337 if (e != BCExceptionNO)
338 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400339 }
340 if (IsEmpty(matrix->Get(i, 6))) {
341 matrix->Set(i, 6, bit);
342 }
343 if (!IsValidValue(matrix->Get(6, i))) {
344 e = BCExceptionInvalidateImageData;
Tom Sepezc8017b22017-01-31 13:02:10 -0800345 if (e != BCExceptionNO)
346 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400347 }
348 if (IsEmpty(matrix->Get(6, i))) {
349 matrix->Set(6, i, bit);
350 }
351 }
352}
353void CBC_QRCoderMatrixUtil::EmbedDarkDotAtLeftBottomCorner(
354 CBC_CommonByteMatrix* matrix,
355 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700356 if (!matrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400357 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800358 if (e != BCExceptionNO)
359 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400360 }
361 if (matrix->Get(8, matrix->GetHeight() - 8) == 0) {
362 e = BCExceptionHeight_8BeZero;
Tom Sepezc8017b22017-01-31 13:02:10 -0800363 if (e != BCExceptionNO)
364 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400365 }
366 matrix->Set(8, matrix->GetHeight() - 8, 1);
367}
368void CBC_QRCoderMatrixUtil::EmbedHorizontalSeparationPattern(
369 int32_t xStart,
370 int32_t yStart,
371 CBC_CommonByteMatrix* matrix,
372 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700373 if (!matrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400374 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800375 if (e != BCExceptionNO)
376 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400377 }
378 for (int32_t x = 0; x < 8; x++) {
379 if (!IsEmpty(matrix->Get(xStart + x, yStart))) {
380 e = BCExceptionInvalidateData;
Tom Sepezc8017b22017-01-31 13:02:10 -0800381 if (e != BCExceptionNO)
382 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400383 }
384 matrix->Set(xStart + x, yStart, HORIZONTAL_SEPARATION_PATTERN[0][x]);
385 }
386}
387void CBC_QRCoderMatrixUtil::EmbedVerticalSeparationPattern(
388 int32_t xStart,
389 int32_t yStart,
390 CBC_CommonByteMatrix* matrix,
391 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700392 if (!matrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400393 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800394 if (e != BCExceptionNO)
395 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400396 }
397 for (int32_t y = 0; y < 7; y++) {
398 if (!IsEmpty(matrix->Get(xStart, yStart + y))) {
399 e = BCExceptionInvalidateData;
Tom Sepezc8017b22017-01-31 13:02:10 -0800400 if (e != BCExceptionNO)
401 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400402 }
403 matrix->Set(xStart, yStart + y, VERTICAL_SEPARATION_PATTERN[y][0]);
404 }
405}
406void CBC_QRCoderMatrixUtil::EmbedPositionAdjustmentPattern(
407 int32_t xStart,
408 int32_t yStart,
409 CBC_CommonByteMatrix* matrix,
410 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700411 if (!matrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400412 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800413 if (e != BCExceptionNO)
414 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400415 }
416 for (int32_t y = 0; y < 5; y++) {
417 for (int32_t x = 0; x < 5; x++) {
418 if (!IsEmpty(matrix->Get(xStart + x, y + yStart))) {
419 e = BCExceptionInvalidateData;
Tom Sepezc8017b22017-01-31 13:02:10 -0800420 if (e != BCExceptionNO)
421 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400422 }
423 matrix->Set(xStart + x, yStart + y, POSITION_ADJUSTMENT_PATTERN[y][x]);
424 }
425 }
426}
427void CBC_QRCoderMatrixUtil::EmbedPositionDetectionPattern(
428 int32_t xStart,
429 int32_t yStart,
430 CBC_CommonByteMatrix* matrix,
431 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700432 if (!matrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400433 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800434 if (e != BCExceptionNO)
435 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400436 }
437 for (int32_t y = 0; y < 7; y++) {
438 for (int32_t x = 0; x < 7; x++) {
439 if (!IsEmpty(matrix->Get(xStart + x, yStart + y))) {
440 e = BCExceptionInvalidateData;
Tom Sepezc8017b22017-01-31 13:02:10 -0800441 if (e != BCExceptionNO)
442 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400443 }
444 matrix->Set(xStart + x, yStart + y, POSITION_DETECTION_PATTERN[y][x]);
445 }
446 }
447}
448void CBC_QRCoderMatrixUtil::EmbedPositionDetectionPatternsAndSeparators(
449 CBC_CommonByteMatrix* matrix,
450 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700451 if (!matrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400452 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800453 if (e != BCExceptionNO)
454 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400455 }
456 int32_t pdpWidth = 7;
457 EmbedPositionDetectionPattern(0, 0, matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800458 if (e != BCExceptionNO)
459 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400460 EmbedPositionDetectionPattern(matrix->GetWidth() - pdpWidth, 0, matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800461 if (e != BCExceptionNO)
462 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400463 EmbedPositionDetectionPattern(0, matrix->GetWidth() - pdpWidth, matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800464 if (e != BCExceptionNO)
465 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400466 int32_t hspWidth = 8;
467 EmbedHorizontalSeparationPattern(0, hspWidth - 1, matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800468 if (e != BCExceptionNO)
469 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400470 EmbedHorizontalSeparationPattern(matrix->GetWidth() - hspWidth, hspWidth - 1,
471 matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800472 if (e != BCExceptionNO)
473 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400474 EmbedHorizontalSeparationPattern(0, matrix->GetWidth() - hspWidth, matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800475 if (e != BCExceptionNO)
476 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400477 int32_t vspSize = 7;
478 EmbedVerticalSeparationPattern(vspSize, 0, matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800479 if (e != BCExceptionNO)
480 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400481 EmbedVerticalSeparationPattern(matrix->GetHeight() - vspSize - 1, 0, matrix,
482 e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800483 if (e != BCExceptionNO)
484 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400485 EmbedVerticalSeparationPattern(vspSize, matrix->GetHeight() - vspSize, matrix,
486 e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800487 if (e != BCExceptionNO)
488 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400489}
490void CBC_QRCoderMatrixUtil::MaybeEmbedPositionAdjustmentPatterns(
491 int32_t version,
492 CBC_CommonByteMatrix* matrix,
493 int32_t& e) {
thestig6dc1d772016-06-09 18:39:33 -0700494 if (!matrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400495 e = BCExceptionNullPointer;
Tom Sepezc8017b22017-01-31 13:02:10 -0800496 if (e != BCExceptionNO)
497 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400498 }
499 if (version < 2) {
500 return;
501 }
502 int32_t index = version - 1;
503 int32_t const* coordinates =
504 &(POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index][0]);
505 int32_t numCoordinate = 7;
506 for (int32_t i = 0; i < numCoordinate; i++) {
507 for (int32_t j = 0; j < numCoordinate; j++) {
508 int32_t y = coordinates[i];
509 int32_t x = coordinates[j];
510 if (x == -1 || y == -1) {
511 continue;
512 }
513 if (IsEmpty(matrix->Get(x, y))) {
514 EmbedPositionAdjustmentPattern(x - 2, y - 2, matrix, e);
Tom Sepezc8017b22017-01-31 13:02:10 -0800515 if (e != BCExceptionNO)
516 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400517 }
518 }
519 }
520}
521int32_t CBC_QRCoderMatrixUtil::FindMSBSet(int32_t value) {
522 int32_t numDigits = 0;
523 while (value != 0) {
524 value >>= 1;
525 ++numDigits;
526 }
527 return numDigits;
528}
529CBC_QRCoderMatrixUtil::CBC_QRCoderMatrixUtil() {}
530CBC_QRCoderMatrixUtil::~CBC_QRCoderMatrixUtil() {}