// Copyright 2014 The PDFium Authors
// 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

#include "fxbarcode/BC_TwoDimWriter.h"

#include <algorithm>

#include "core/fxcrt/check.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_graphstatedata.h"
#include "core/fxge/cfx_path.h"
#include "core/fxge/cfx_renderdevice.h"
#include "fxbarcode/BC_Writer.h"
#include "fxbarcode/common/BC_CommonBitMatrix.h"

CBC_TwoDimWriter::CBC_TwoDimWriter(bool bFixedSize)
    : m_bFixedSize(bFixedSize) {}

CBC_TwoDimWriter::~CBC_TwoDimWriter() = default;

bool CBC_TwoDimWriter::RenderResult(pdfium::span<const uint8_t> code,
                                    int32_t codeWidth,
                                    int32_t codeHeight) {
  if (code.empty())
    return false;

  m_inputWidth = codeWidth;
  m_inputHeight = codeHeight;
  int32_t tempWidth = m_inputWidth + 2;
  int32_t tempHeight = m_inputHeight + 2;
  const float module_size =
      std::clamp<float>(std::min(m_ModuleWidth, m_ModuleHeight), 1.0f, 8.0f);
  FX_SAFE_INT32 scaledWidth = tempWidth;
  FX_SAFE_INT32 scaledHeight = tempHeight;
  scaledWidth *= module_size;
  scaledHeight *= module_size;
  m_outputWidth = scaledWidth.ValueOrDie();
  m_outputHeight = scaledHeight.ValueOrDie();

  if (m_bFixedSize) {
    if (m_Width < m_outputWidth || m_Height < m_outputHeight) {
      return false;
    }
  } else {
    if (m_Width > m_outputWidth || m_Height > m_outputHeight) {
      int32_t width_factor = static_cast<int32_t>(
          floor(static_cast<float>(m_Width) / m_outputWidth));
      int32_t height_factor = static_cast<int32_t>(
          floor(static_cast<float>(m_Height) / m_outputHeight));
      width_factor = std::max(width_factor, 1);
      height_factor = std::max(height_factor, 1);

      m_outputWidth *= width_factor;
      m_outputHeight *= height_factor;
    }
  }
  m_multiX =
      static_cast<int32_t>(ceil(static_cast<float>(m_outputWidth) / tempWidth));
  m_multiY = static_cast<int32_t>(
      ceil(static_cast<float>(m_outputHeight) / tempHeight));
  if (m_bFixedSize) {
    m_multiX = std::min(m_multiX, m_multiY);
    m_multiY = m_multiX;
  }

  m_leftPadding = std::max((m_Width - m_outputWidth) / 2, 0);
  m_topPadding = std::max((m_Height - m_outputHeight) / 2, 0);

  m_output = std::make_unique<CBC_CommonBitMatrix>(m_inputWidth, m_inputHeight);
  for (int32_t y = 0; y < m_inputHeight; ++y) {
    for (int32_t x = 0; x < m_inputWidth; ++x) {
      if (code[x + y * m_inputWidth] == 1)
        m_output->Set(x, y);
    }
  }
  return true;
}

void CBC_TwoDimWriter::RenderDeviceResult(CFX_RenderDevice* device,
                                          const CFX_Matrix& matrix) {
  DCHECK(m_output);

  CFX_GraphStateData stateData;
  CFX_Path path;
  path.AppendRect(0, 0, m_Width, m_Height);
  device->DrawPath(path, &matrix, &stateData, kBackgroundColor,
                   kBackgroundColor, CFX_FillRenderOptions::EvenOddOptions());
  int32_t leftPos = m_leftPadding;
  int32_t topPos = m_topPadding;

  CFX_Matrix matri = matrix;
  if (m_Width < m_outputWidth && m_Height < m_outputHeight) {
    CFX_Matrix matriScale(static_cast<float>(m_Width) / m_outputWidth, 0.0, 0.0,
                          static_cast<float>(m_Height) / m_outputHeight, 0.0,
                          0.0);
    matriScale.Concat(matrix);
    matri = matriScale;
  }

  CFX_GraphStateData data;
  for (int32_t x = 0; x < m_inputWidth; x++) {
    for (int32_t y = 0; y < m_inputHeight; y++) {
      if (m_output->Get(x, y)) {
        // In the output, each module is shifted by 1 due to the one module
        // padding added to create quiet areas.
        int start_x_output = x + 1;
        int end_x_output = x + 2;
        int start_y_output = y + 1;
        int end_y_output = y + 2;

        CFX_Path rect;
        rect.AppendRect(leftPos + start_x_output * m_multiX,
                        topPos + start_y_output * m_multiY,
                        leftPos + end_x_output * m_multiX,
                        topPos + end_y_output * m_multiY);
        device->DrawPath(rect, &matri, &data, kBarColor, 0,
                         CFX_FillRenderOptions::WindingOptions());
      }
    }
  }
}
