// Copyright 2017 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

#include "core/fxge/dib/cfx_imagestretcher.h"

#include <climits>
#include <tuple>

#include "core/fxcrt/fx_safe_types.h"
#include "core/fxge/dib/cfx_dibbase.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/dib/cstretchengine.h"
#include "core/fxge/fx_dib.h"
#include "third_party/base/ptr_util.h"
#include "third_party/base/stl_util.h"

namespace {

const int kMaxProgressiveStretchPixels = 1000000;

bool SourceSizeWithinLimit(int width, int height) {
  return !height || width < kMaxProgressiveStretchPixels / height;
}

FXDIB_Format GetStretchedFormat(const CFX_DIBBase& src) {
  FXDIB_Format format = src.GetFormat();
  if (format == FXDIB_1bppMask)
    return FXDIB_8bppMask;
  if (format == FXDIB_1bppRgb)
    return FXDIB_8bppRgb;
  if (format == FXDIB_8bppRgb && src.GetPalette())
    return FXDIB_Rgb;
  return format;
}

// Returns tuple c, m, y, k
std::tuple<int, int, int, int> CmykDecode(const uint32_t cmyk) {
  return std::make_tuple(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk),
                         FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk));
}

}  // namespace

CFX_ImageStretcher::CFX_ImageStretcher(ScanlineComposerIface* pDest,
                                       const RetainPtr<CFX_DIBBase>& pSource,
                                       int dest_width,
                                       int dest_height,
                                       const FX_RECT& bitmap_rect,
                                       const FXDIB_ResampleOptions& options)
    : m_pDest(pDest),
      m_pSource(pSource),
      m_ResampleOptions(options),
      m_bFlipX(false),
      m_bFlipY(false),
      m_DestWidth(dest_width),
      m_DestHeight(dest_height),
      m_ClipRect(bitmap_rect),
      m_DestFormat(GetStretchedFormat(*pSource)),
      m_DestBPP(GetBppFromFormat(m_DestFormat)),
      m_LineIndex(0) {
  ASSERT(m_ClipRect.Valid());
}

CFX_ImageStretcher::~CFX_ImageStretcher() {}

bool CFX_ImageStretcher::Start() {
  if (m_DestWidth == 0 || m_DestHeight == 0)
    return false;

  if (m_pSource->GetFormat() == FXDIB_1bppRgb && m_pSource->GetPalette()) {
    FX_ARGB pal[256];
    int a0;
    int r0;
    int g0;
    int b0;
    std::tie(a0, r0, g0, b0) = ArgbDecode(m_pSource->GetPaletteArgb(0));
    int a1;
    int r1;
    int g1;
    int b1;
    std::tie(a1, r1, g1, b1) = ArgbDecode(m_pSource->GetPaletteArgb(1));
    for (int i = 0; i < 256; ++i) {
      int a = a0 + (a1 - a0) * i / 255;
      int r = r0 + (r1 - r0) * i / 255;
      int g = g0 + (g1 - g0) * i / 255;
      int b = b0 + (b1 - b0) * i / 255;
      pal[i] = ArgbEncode(a, r, g, b);
    }
    if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat,
                          pal)) {
      return false;
    }
  } else if (m_pSource->GetFormat() == FXDIB_1bppCmyk &&
             m_pSource->GetPalette()) {
    FX_CMYK pal[256];
    int c0;
    int m0;
    int y0;
    int k0;
    std::tie(c0, m0, y0, k0) = CmykDecode(m_pSource->GetPaletteArgb(0));
    int c1;
    int m1;
    int y1;
    int k1;
    std::tie(c1, m1, y1, k1) = CmykDecode(m_pSource->GetPaletteArgb(1));
    for (int i = 0; i < 256; ++i) {
      int c = c0 + (c1 - c0) * i / 255;
      int m = m0 + (m1 - m0) * i / 255;
      int y = y0 + (y1 - y0) * i / 255;
      int k = k0 + (k1 - k0) * i / 255;
      pal[i] = CmykEncode(c, m, y, k);
    }
    if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat,
                          pal)) {
      return false;
    }
  } else if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(),
                               m_DestFormat, nullptr)) {
    return false;
  }

  if (m_ResampleOptions.bInterpolateDownsample)
    return StartQuickStretch();
  return StartStretch();
}

bool CFX_ImageStretcher::Continue(PauseIndicatorIface* pPause) {
  if (m_ResampleOptions.bInterpolateDownsample)
    return ContinueQuickStretch(pPause);
  return ContinueStretch(pPause);
}

RetainPtr<CFX_DIBBase> CFX_ImageStretcher::source() {
  return m_pSource;
}

bool CFX_ImageStretcher::StartStretch() {
  m_pStretchEngine = pdfium::MakeUnique<CStretchEngine>(
      m_pDest.Get(), m_DestFormat, m_DestWidth, m_DestHeight, m_ClipRect,
      m_pSource, m_ResampleOptions);
  m_pStretchEngine->StartStretchHorz();
  if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) {
    m_pStretchEngine->Continue(nullptr);
    return false;
  }
  return true;
}

bool CFX_ImageStretcher::ContinueStretch(PauseIndicatorIface* pPause) {
  return m_pStretchEngine && m_pStretchEngine->Continue(pPause);
}

bool CFX_ImageStretcher::StartQuickStretch() {
  if (m_DestWidth < 0) {
    m_bFlipX = true;
    m_DestWidth = -m_DestWidth;
  }
  if (m_DestHeight < 0) {
    m_bFlipY = true;
    m_DestHeight = -m_DestHeight;
  }
  uint32_t size = m_ClipRect.Width();
  if (size && m_DestBPP > static_cast<int>(INT_MAX / size))
    return false;

  size *= m_DestBPP;
  m_pScanline.reset(FX_Alloc(uint8_t, FxAlignToBoundary<4>(size / 8)));
  if (m_pSource->m_pAlphaMask) {
    m_pMaskScanline.reset(
        FX_Alloc(uint8_t, FxAlignToBoundary<4>(m_ClipRect.Width())));
  }
  if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) {
    ContinueQuickStretch(nullptr);
    return false;
  }
  return true;
}

bool CFX_ImageStretcher::ContinueQuickStretch(PauseIndicatorIface* pPause) {
  if (!m_pScanline)
    return false;

  int result_width = m_ClipRect.Width();
  int result_height = m_ClipRect.Height();
  int src_height = m_pSource->GetHeight();
  for (; m_LineIndex < result_height; ++m_LineIndex) {
    int dest_y;
    FX_SAFE_INT64 calc_buf;
    if (m_bFlipY) {
      dest_y = result_height - m_LineIndex - 1;
      calc_buf = m_DestHeight;
      calc_buf -= dest_y;
      calc_buf -= m_ClipRect.top;
      calc_buf -= 1;
      calc_buf *= src_height;
      calc_buf /= m_DestHeight;
    } else {
      dest_y = m_LineIndex;
      calc_buf = dest_y;
      calc_buf += m_ClipRect.top;
      calc_buf *= src_height;
      calc_buf /= m_DestHeight;
    }

    int src_y;
    if (!calc_buf.AssignIfValid(&src_y))
      return false;

    src_y = pdfium::clamp(src_y, 0, src_height - 1);
    if (m_pSource->SkipToScanline(src_y, pPause))
      return true;

    m_pSource->DownSampleScanline(src_y, m_pScanline.get(), m_DestBPP,
                                  m_DestWidth, m_bFlipX, m_ClipRect.left,
                                  result_width);
    if (m_pMaskScanline) {
      m_pSource->m_pAlphaMask->DownSampleScanline(
          src_y, m_pMaskScanline.get(), 1, m_DestWidth, m_bFlipX,
          m_ClipRect.left, result_width);
    }
    m_pDest->ComposeScanline(dest_y, m_pScanline.get(), m_pMaskScanline.get());
  }
  return false;
}
