// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
// Original code is licensed as follows:
/*
 * Copyright 2007 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "../barcode.h"
#include "BC_CommonBitArray.h"
#include "BC_CommonBitMatrix.h"
CBC_CommonBitMatrix::CBC_CommonBitMatrix() {
  m_width = 0;
  m_height = 0;
  m_rowSize = 0;
  m_bits = NULL;
}
void CBC_CommonBitMatrix::Init(int32_t dimension) {
  m_width = dimension;
  m_height = dimension;
  int32_t rowSize = (m_height + 31) >> 5;
  m_rowSize = rowSize;
  m_bits = FX_Alloc(int32_t, m_rowSize * m_height);
  FXSYS_memset(m_bits, 0, m_rowSize * m_height * sizeof(int32_t));
}
void CBC_CommonBitMatrix::Init(int32_t width, int32_t height) {
  m_width = width;
  m_height = height;
  int32_t rowSize = (width + 31) >> 5;
  m_rowSize = rowSize;
  m_bits = FX_Alloc(int32_t, m_rowSize * m_height);
  FXSYS_memset(m_bits, 0, m_rowSize * m_height * sizeof(int32_t));
}
CBC_CommonBitMatrix::~CBC_CommonBitMatrix() {
  if (m_bits != NULL) {
    FX_Free(m_bits);
  }
  m_bits = NULL;
  m_height = m_width = m_rowSize = 0;
}
FX_BOOL CBC_CommonBitMatrix::Get(int32_t x, int32_t y) {
  int32_t offset = y * m_rowSize + (x >> 5);
  if (offset >= m_rowSize * m_height || offset < 0) {
    return false;
  }
  return ((((FX_DWORD)m_bits[offset]) >> (x & 0x1f)) & 1) != 0;
}
int32_t* CBC_CommonBitMatrix::GetBits() {
  return m_bits;
}
void CBC_CommonBitMatrix::Set(int32_t x, int32_t y) {
  int32_t offset = y * m_rowSize + (x >> 5);
  if (offset >= m_rowSize * m_height || offset < 0) {
    return;
  }
  m_bits[offset] |= 1 << (x & 0x1f);
}
void CBC_CommonBitMatrix::Flip(int32_t x, int32_t y) {
  int32_t offset = y * m_rowSize + (x >> 5);
  m_bits[offset] ^= 1 << (x & 0x1f);
}
void CBC_CommonBitMatrix::Clear() {
  FXSYS_memset(m_bits, 0, m_rowSize * m_height * sizeof(int32_t));
}
void CBC_CommonBitMatrix::SetRegion(int32_t left,
                                    int32_t top,
                                    int32_t width,
                                    int32_t height,
                                    int32_t& e) {
  if (top < 0 || left < 0) {
    e = BCExceptionLeftAndTopMustBeNonnegative;
    return;
  }
  if (height < 1 || width < 1) {
    e = BCExceptionHeightAndWidthMustBeAtLeast1;
    return;
  }
  int32_t right = left + width;
  int32_t bottom = top + height;
  if (m_height < bottom || m_width < right) {
    e = BCExceptionRegionMustFitInsideMatrix;
    return;
  }
  int32_t y;
  for (y = top; y < bottom; y++) {
    int32_t offset = y * m_rowSize;
    int32_t x;
    for (x = left; x < right; x++) {
      m_bits[offset + (x >> 5)] |= 1 << (x & 0x1f);
    }
  }
}
CBC_CommonBitArray* CBC_CommonBitMatrix::GetRow(int32_t y,
                                                CBC_CommonBitArray* row) {
  CBC_CommonBitArray* rowArray = NULL;
  if (row == NULL || row->GetSize() < m_width) {
    rowArray = new CBC_CommonBitArray(m_width);
  } else {
    rowArray = new CBC_CommonBitArray(row);
  }
  int32_t offset = y * m_rowSize;
  int32_t x;
  for (x = 0; x < m_rowSize; x++) {
    rowArray->SetBulk(x << 5, m_bits[offset + x]);
  }
  return rowArray;
}
void CBC_CommonBitMatrix::SetRow(int32_t y, CBC_CommonBitArray* row) {
  int32_t l = y * m_rowSize;
  for (int32_t i = 0; i < m_rowSize; i++) {
    m_bits[l] = row->GetBitArray()[i];
    l++;
  }
}
void CBC_CommonBitMatrix::SetCol(int32_t y, CBC_CommonBitArray* col) {
  for (int32_t i = 0; i < col->GetBits().GetSize(); i++) {
    m_bits[i * m_rowSize + y] = col->GetBitArray()[i];
  }
}
int32_t CBC_CommonBitMatrix::GetWidth() {
  return m_width;
}
int32_t CBC_CommonBitMatrix::GetHeight() {
  return m_height;
}
int32_t CBC_CommonBitMatrix::GetRowSize() {
  return m_rowSize;
}
int32_t CBC_CommonBitMatrix::GetDimension(int32_t& e) {
  if (m_width != m_height) {
    e = BCExceptionCanNotCallGetDimensionOnNonSquareMatrix;
    return 0;
  }
  return m_width;
}
