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 2007 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_CommonBitMatrix.h" 25 #include "BC_DataMatrixVersion.h" 26 #include "BC_DataMatrixBitMatrixParser.h" 27 CBC_DataMatrixBitMatrixParser::CBC_DataMatrixBitMatrixParser() { 28 m_mappingBitMatrix = NULL; 29 m_version = NULL; 30 m_readMappingMatrix = NULL; 31 } 32 void CBC_DataMatrixBitMatrixParser::Init(CBC_CommonBitMatrix* bitMatrix, 33 int32_t& e) { 34 int32_t dimension = bitMatrix->GetHeight(); 35 if (dimension < 8 || dimension > 144 || (dimension & 0x01) != 0) { 36 e = BCExceptionFormatException; 37 return; 38 } 39 m_version = ReadVersion(bitMatrix, e); 40 BC_EXCEPTION_CHECK_ReturnVoid(e); 41 m_mappingBitMatrix = ExtractDataRegion(bitMatrix, e); 42 BC_EXCEPTION_CHECK_ReturnVoid(e); 43 m_readMappingMatrix = new CBC_CommonBitMatrix(); 44 m_readMappingMatrix->Init(m_mappingBitMatrix->GetWidth(), 45 m_mappingBitMatrix->GetHeight()); 46 } 47 CBC_DataMatrixBitMatrixParser::~CBC_DataMatrixBitMatrixParser() { 48 if (m_mappingBitMatrix != NULL) { 49 delete m_mappingBitMatrix; 50 } 51 m_mappingBitMatrix = NULL; 52 if (m_readMappingMatrix != NULL) { 53 delete m_readMappingMatrix; 54 } 55 m_readMappingMatrix = NULL; 56 } 57 CBC_DataMatrixVersion* CBC_DataMatrixBitMatrixParser::GetVersion() { 58 return m_version; 59 } 60 CBC_DataMatrixVersion* CBC_DataMatrixBitMatrixParser::ReadVersion( 61 CBC_CommonBitMatrix* bitMatrix, 62 int32_t& e) { 63 int32_t rows = bitMatrix->GetHeight(); 64 int32_t columns = bitMatrix->GetWidth(); 65 CBC_DataMatrixVersion* temp = 66 CBC_DataMatrixVersion::GetVersionForDimensions(rows, columns, e); 67 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); 68 return temp; 69 } 70 CFX_ByteArray* CBC_DataMatrixBitMatrixParser::ReadCodewords(int32_t& e) { 71 CBC_AutoPtr<CFX_ByteArray> result(new CFX_ByteArray()); 72 result->SetSize(m_version->GetTotalCodewords()); 73 int32_t resultOffset = 0; 74 int32_t row = 4; 75 int32_t column = 0; 76 int32_t numRows = m_mappingBitMatrix->GetHeight(); 77 int32_t numColumns = m_mappingBitMatrix->GetWidth(); 78 FX_BOOL corner1Read = FALSE; 79 FX_BOOL corner2Read = FALSE; 80 FX_BOOL corner3Read = FALSE; 81 FX_BOOL corner4Read = FALSE; 82 do { 83 if ((row == numRows) && (column == 0) && !corner1Read) { 84 (*result)[resultOffset++] = (uint8_t)ReadCorner1(numRows, numColumns); 85 row -= 2; 86 column += 2; 87 corner1Read = TRUE; 88 } else if ((row == numRows - 2) && (column == 0) && 89 ((numColumns & 0x03) != 0) && !corner2Read) { 90 (*result)[resultOffset++] = (uint8_t)ReadCorner2(numRows, numColumns); 91 row -= 2; 92 column += 2; 93 corner2Read = TRUE; 94 } else if ((row == numRows + 4) && (column == 2) && 95 ((numColumns & 0x07) == 0) && !corner3Read) { 96 (*result)[resultOffset++] = (uint8_t)ReadCorner3(numRows, numColumns); 97 row -= 2; 98 column += 2; 99 corner3Read = TRUE; 100 } else if ((row == numRows - 2) && (column == 0) && 101 ((numColumns & 0x07) == 4) && !corner4Read) { 102 (*result)[resultOffset++] = (uint8_t)ReadCorner4(numRows, numColumns); 103 row -= 2; 104 column += 2; 105 corner4Read = TRUE; 106 } else { 107 do { 108 if ((row < numRows) && (column >= 0) && 109 !m_readMappingMatrix->Get(column, row)) { 110 if (resultOffset < (*result).GetSize()) { 111 (*result)[resultOffset++] = 112 (uint8_t)ReadUtah(row, column, numRows, numColumns); 113 } 114 } 115 row -= 2; 116 column += 2; 117 } while ((row >= 0) && (column < numColumns)); 118 row += 1; 119 column += 3; 120 do { 121 if ((row >= 0) && (column < numColumns) && 122 !m_readMappingMatrix->Get(column, row)) { 123 if (resultOffset < (*result).GetSize()) { 124 (*result)[resultOffset++] = 125 (uint8_t)ReadUtah(row, column, numRows, numColumns); 126 } 127 } 128 row += 2; 129 column -= 2; 130 } while ((row < numRows) && (column >= 0)); 131 row += 3; 132 column += 1; 133 } 134 } while ((row < numRows) || (column < numColumns)); 135 if (resultOffset != m_version->GetTotalCodewords()) { 136 e = BCExceptionFormatException; 137 return NULL; 138 } 139 return result.release(); 140 } 141 FX_BOOL CBC_DataMatrixBitMatrixParser::ReadModule(int32_t row, 142 int32_t column, 143 int32_t numRows, 144 int32_t numColumns) { 145 if (row < 0) { 146 row += numRows; 147 column += 4 - ((numRows + 4) & 0x07); 148 } 149 if (column < 0) { 150 column += numColumns; 151 row += 4 - ((numColumns + 4) & 0x07); 152 } 153 m_readMappingMatrix->Set(column, row); 154 return m_mappingBitMatrix->Get(column, row); 155 } 156 int32_t CBC_DataMatrixBitMatrixParser::ReadUtah(int32_t row, 157 int32_t column, 158 int32_t numRows, 159 int32_t numColumns) { 160 int32_t currentByte = 0; 161 if (ReadModule(row - 2, column - 2, numRows, numColumns)) { 162 currentByte |= 1; 163 } 164 currentByte <<= 1; 165 if (ReadModule(row - 2, column - 1, numRows, numColumns)) { 166 currentByte |= 1; 167 } 168 currentByte <<= 1; 169 if (ReadModule(row - 1, column - 2, numRows, numColumns)) { 170 currentByte |= 1; 171 } 172 currentByte <<= 1; 173 if (ReadModule(row - 1, column - 1, numRows, numColumns)) { 174 currentByte |= 1; 175 } 176 currentByte <<= 1; 177 if (ReadModule(row - 1, column, numRows, numColumns)) { 178 currentByte |= 1; 179 } 180 currentByte <<= 1; 181 if (ReadModule(row, column - 2, numRows, numColumns)) { 182 currentByte |= 1; 183 } 184 currentByte <<= 1; 185 if (ReadModule(row, column - 1, numRows, numColumns)) { 186 currentByte |= 1; 187 } 188 currentByte <<= 1; 189 if (ReadModule(row, column, numRows, numColumns)) { 190 currentByte |= 1; 191 } 192 return currentByte; 193 } 194 int32_t CBC_DataMatrixBitMatrixParser::ReadCorner1(int32_t numRows, 195 int32_t numColumns) { 196 int32_t currentByte = 0; 197 if (ReadModule(numRows - 1, 0, numRows, numColumns)) { 198 currentByte |= 1; 199 } 200 currentByte <<= 1; 201 if (ReadModule(numRows - 1, 1, numRows, numColumns)) { 202 currentByte |= 1; 203 } 204 currentByte <<= 1; 205 if (ReadModule(numRows - 1, 2, numRows, numColumns)) { 206 currentByte |= 1; 207 } 208 currentByte <<= 1; 209 if (ReadModule(0, numColumns - 2, numRows, numColumns)) { 210 currentByte |= 1; 211 } 212 currentByte <<= 1; 213 if (ReadModule(0, numColumns - 1, numRows, numColumns)) { 214 currentByte |= 1; 215 } 216 currentByte <<= 1; 217 if (ReadModule(1, numColumns - 1, numRows, numColumns)) { 218 currentByte |= 1; 219 } 220 currentByte <<= 1; 221 if (ReadModule(2, numColumns - 1, numRows, numColumns)) { 222 currentByte |= 1; 223 } 224 currentByte <<= 1; 225 if (ReadModule(3, numColumns - 1, numRows, numColumns)) { 226 currentByte |= 1; 227 } 228 return currentByte; 229 } 230 int32_t CBC_DataMatrixBitMatrixParser::ReadCorner2(int32_t numRows, 231 int32_t numColumns) { 232 int32_t currentByte = 0; 233 if (ReadModule(numRows - 3, 0, numRows, numColumns)) { 234 currentByte |= 1; 235 } 236 currentByte <<= 1; 237 if (ReadModule(numRows - 2, 0, numRows, numColumns)) { 238 currentByte |= 1; 239 } 240 currentByte <<= 1; 241 if (ReadModule(numRows - 1, 0, numRows, numColumns)) { 242 currentByte |= 1; 243 } 244 currentByte <<= 1; 245 if (ReadModule(0, numColumns - 4, numRows, numColumns)) { 246 currentByte |= 1; 247 } 248 currentByte <<= 1; 249 if (ReadModule(0, numColumns - 3, numRows, numColumns)) { 250 currentByte |= 1; 251 } 252 currentByte <<= 1; 253 if (ReadModule(0, numColumns - 2, numRows, numColumns)) { 254 currentByte |= 1; 255 } 256 currentByte <<= 1; 257 if (ReadModule(0, numColumns - 1, numRows, numColumns)) { 258 currentByte |= 1; 259 } 260 currentByte <<= 1; 261 if (ReadModule(1, numColumns - 1, numRows, numColumns)) { 262 currentByte |= 1; 263 } 264 return currentByte; 265 } 266 int32_t CBC_DataMatrixBitMatrixParser::ReadCorner3(int32_t numRows, 267 int32_t numColumns) { 268 int32_t currentByte = 0; 269 if (ReadModule(numRows - 1, 0, numRows, numColumns)) { 270 currentByte |= 1; 271 } 272 currentByte <<= 1; 273 if (ReadModule(numRows - 1, numColumns - 1, numRows, numColumns)) { 274 currentByte |= 1; 275 } 276 currentByte <<= 1; 277 if (ReadModule(0, numColumns - 3, numRows, numColumns)) { 278 currentByte |= 1; 279 } 280 currentByte <<= 1; 281 if (ReadModule(0, numColumns - 2, numRows, numColumns)) { 282 currentByte |= 1; 283 } 284 currentByte <<= 1; 285 if (ReadModule(0, numColumns - 1, numRows, numColumns)) { 286 currentByte |= 1; 287 } 288 currentByte <<= 1; 289 if (ReadModule(1, numColumns - 3, numRows, numColumns)) { 290 currentByte |= 1; 291 } 292 currentByte <<= 1; 293 if (ReadModule(1, numColumns - 2, numRows, numColumns)) { 294 currentByte |= 1; 295 } 296 currentByte <<= 1; 297 if (ReadModule(1, numColumns - 1, numRows, numColumns)) { 298 currentByte |= 1; 299 } 300 return currentByte; 301 } 302 int32_t CBC_DataMatrixBitMatrixParser::ReadCorner4(int32_t numRows, 303 int32_t numColumns) { 304 int32_t currentByte = 0; 305 if (ReadModule(numRows - 3, 0, numRows, numColumns)) { 306 currentByte |= 1; 307 } 308 currentByte <<= 1; 309 if (ReadModule(numRows - 2, 0, numRows, numColumns)) { 310 currentByte |= 1; 311 } 312 currentByte <<= 1; 313 if (ReadModule(numRows - 1, 0, numRows, numColumns)) { 314 currentByte |= 1; 315 } 316 currentByte <<= 1; 317 if (ReadModule(0, numColumns - 2, numRows, numColumns)) { 318 currentByte |= 1; 319 } 320 currentByte <<= 1; 321 if (ReadModule(0, numColumns - 1, numRows, numColumns)) { 322 currentByte |= 1; 323 } 324 currentByte <<= 1; 325 if (ReadModule(1, numColumns - 1, numRows, numColumns)) { 326 currentByte |= 1; 327 } 328 currentByte <<= 1; 329 if (ReadModule(2, numColumns - 1, numRows, numColumns)) { 330 currentByte |= 1; 331 } 332 currentByte <<= 1; 333 if (ReadModule(3, numColumns - 1, numRows, numColumns)) { 334 currentByte |= 1; 335 } 336 return currentByte; 337 } 338 CBC_CommonBitMatrix* CBC_DataMatrixBitMatrixParser::ExtractDataRegion( 339 CBC_CommonBitMatrix* bitMatrix, 340 int32_t& e) { 341 int32_t symbolSizeRows = m_version->GetSymbolSizeRows(); 342 int32_t symbolSizeColumns = m_version->GetSymbolSizeColumns(); 343 if (bitMatrix->GetHeight() != symbolSizeRows) { 344 e = BCExceptionCanNotCallGetDimensionOnNonSquareMatrix; 345 return NULL; 346 } 347 int32_t dataRegionSizeRows = m_version->GetDataRegionSizeRows(); 348 int32_t dataRegionSizeColumns = m_version->GetDataRegionSizeColumns(); 349 int32_t numDataRegionsRow = symbolSizeRows / dataRegionSizeRows; 350 int32_t numDataRegionsColumn = symbolSizeColumns / dataRegionSizeColumns; 351 int32_t sizeDataRegionRow = numDataRegionsRow * dataRegionSizeRows; 352 int32_t sizeDataRegionColumn = numDataRegionsColumn * dataRegionSizeColumns; 353 CBC_CommonBitMatrix* bitMatrixWithoutAlignment = new CBC_CommonBitMatrix(); 354 bitMatrixWithoutAlignment->Init(sizeDataRegionColumn, sizeDataRegionRow); 355 int32_t dataRegionRow; 356 for (dataRegionRow = 0; dataRegionRow < numDataRegionsRow; ++dataRegionRow) { 357 int32_t dataRegionRowOffset = dataRegionRow * dataRegionSizeRows; 358 int32_t dataRegionColumn; 359 for (dataRegionColumn = 0; dataRegionColumn < numDataRegionsColumn; 360 ++dataRegionColumn) { 361 int32_t dataRegionColumnOffset = dataRegionColumn * dataRegionSizeColumns; 362 int32_t i; 363 for (i = 0; i < dataRegionSizeRows; ++i) { 364 int32_t readRowOffset = 365 dataRegionRow * (dataRegionSizeRows + 2) + 1 + i; 366 int32_t writeRowOffset = dataRegionRowOffset + i; 367 int32_t j; 368 for (j = 0; j < dataRegionSizeColumns; ++j) { 369 int32_t readColumnOffset = 370 dataRegionColumn * (dataRegionSizeColumns + 2) + 1 + j; 371 if (bitMatrix->Get(readColumnOffset, readRowOffset)) { 372 int32_t writeColumnOffset = dataRegionColumnOffset + j; 373 bitMatrixWithoutAlignment->Set(writeColumnOffset, writeRowOffset); 374 } 375 } 376 } 377 } 378 } 379 return bitMatrixWithoutAlignment; 380 } 381