// 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_bitmapcomposer.h"

#include <string.h>

#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxge/cfx_cliprgn.h"
#include "core/fxge/dib/cfx_dibitmap.h"

CFX_BitmapComposer::CFX_BitmapComposer() = default;

CFX_BitmapComposer::~CFX_BitmapComposer() = default;

void CFX_BitmapComposer::Compose(const RetainPtr<CFX_DIBitmap>& pDest,
                                 const CFX_ClipRgn* pClipRgn,
                                 int bitmap_alpha,
                                 uint32_t mask_color,
                                 const FX_RECT& dest_rect,
                                 bool bVertical,
                                 bool bFlipX,
                                 bool bFlipY,
                                 bool bRgbByteOrder,
                                 BlendMode blend_mode) {
  m_pBitmap = pDest;
  m_pClipRgn = pClipRgn;
  m_DestLeft = dest_rect.left;
  m_DestTop = dest_rect.top;
  m_DestWidth = dest_rect.Width();
  m_DestHeight = dest_rect.Height();
  m_BitmapAlpha = bitmap_alpha;
  m_MaskColor = mask_color;
  m_pClipMask = nullptr;
  if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::kRectI)
    m_pClipMask = pClipRgn->GetMask();
  m_bVertical = bVertical;
  m_bFlipX = bFlipX;
  m_bFlipY = bFlipY;
  m_bRgbByteOrder = bRgbByteOrder;
  m_BlendMode = blend_mode;
}

bool CFX_BitmapComposer::SetInfo(int width,
                                 int height,
                                 FXDIB_Format src_format,
                                 pdfium::span<const uint32_t> src_palette) {
  m_SrcFormat = src_format;
  if (!m_Compositor.Init(m_pBitmap->GetFormat(), src_format, width, src_palette,
                         m_MaskColor, m_BlendMode,
                         m_pClipMask != nullptr || (m_BitmapAlpha < 255),
                         m_bRgbByteOrder)) {
    return false;
  }
  if (m_bVertical) {
    m_pScanlineV.resize(m_pBitmap->GetBPP() / 8 * width + 4);
    m_pClipScanV.resize(m_pBitmap->GetHeight());
    if (m_pBitmap->HasAlphaMask())
      m_pScanlineAlphaV.resize(width + 4);
  }
  if (m_BitmapAlpha < 255) {
    m_pAddClipScan.resize(m_bVertical ? m_pBitmap->GetHeight()
                                      : m_pBitmap->GetWidth());
  }
  return true;
}

void CFX_BitmapComposer::DoCompose(uint8_t* dest_scan,
                                   pdfium::span<const uint8_t> src_scan,
                                   int dest_width,
                                   const uint8_t* clip_scan,
                                   pdfium::span<const uint8_t> src_extra_alpha,
                                   pdfium::span<uint8_t> dst_extra_alpha) {
  uint8_t* pAddClipScan = m_pAddClipScan.data();
  if (m_BitmapAlpha < 255) {
    if (clip_scan) {
      for (int i = 0; i < dest_width; ++i)
        pAddClipScan[i] = clip_scan[i] * m_BitmapAlpha / 255;
    } else {
      memset(pAddClipScan, m_BitmapAlpha, dest_width);
    }
    clip_scan = pAddClipScan;
  }
  if (m_SrcFormat == FXDIB_Format::k8bppMask) {
    m_Compositor.CompositeByteMaskLine(dest_scan, src_scan, dest_width,
                                       clip_scan, dst_extra_alpha);
  } else if (GetBppFromFormat(m_SrcFormat) == 8) {
    m_Compositor.CompositePalBitmapLine(dest_scan, src_scan, 0, dest_width,
                                        clip_scan, src_extra_alpha,
                                        dst_extra_alpha);
  } else {
    m_Compositor.CompositeRgbBitmapLine(dest_scan, src_scan, dest_width,
                                        clip_scan, src_extra_alpha,
                                        dst_extra_alpha);
  }
}

void CFX_BitmapComposer::ComposeScanline(
    int line,
    pdfium::span<const uint8_t> scanline,
    pdfium::span<const uint8_t> scan_extra_alpha) {
  if (m_bVertical) {
    ComposeScanlineV(line, scanline, scan_extra_alpha);
    return;
  }
  const uint8_t* clip_scan = nullptr;
  if (m_pClipMask) {
    clip_scan = m_pClipMask->GetBuffer() +
                (m_DestTop + line - m_pClipRgn->GetBox().top) *
                    m_pClipMask->GetPitch() +
                (m_DestLeft - m_pClipRgn->GetBox().left);
  }
  uint8_t* dest_scan = m_pBitmap->GetWritableScanline(line + m_DestTop).data();
  if (dest_scan) {
    FX_SAFE_UINT32 offset = m_DestLeft;
    offset *= m_pBitmap->GetBPP();
    offset /= 8;
    if (!offset.IsValid())
      return;

    // Help some compilers perform pointer arithmetic against safe numerics.
    dest_scan += static_cast<uint32_t>(offset.ValueOrDie());
  }
  pdfium::span<uint8_t> dest_alpha_scan =
      m_pBitmap->GetWritableAlphaMaskScanline(line + m_DestTop);
  if (!dest_alpha_scan.empty())
    dest_alpha_scan = dest_alpha_scan.subspan(m_DestLeft);

  DoCompose(dest_scan, scanline, m_DestWidth, clip_scan, scan_extra_alpha,
            dest_alpha_scan);
}

void CFX_BitmapComposer::ComposeScanlineV(
    int line,
    pdfium::span<const uint8_t> scanline,
    pdfium::span<const uint8_t> scan_extra_alpha) {
  int Bpp = m_pBitmap->GetBPP() / 8;
  int dest_pitch = m_pBitmap->GetPitch();
  int dest_alpha_pitch = m_pBitmap->GetAlphaMaskPitch();
  int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line);
  uint8_t* dest_buf = m_pBitmap->GetBuffer();
  if (dest_buf) {
    dest_buf += dest_x * Bpp + m_DestTop * dest_pitch;
    if (m_bFlipY)
      dest_buf += dest_pitch * (m_DestHeight - 1);
  }
  uint8_t* dest_alpha_buf = m_pBitmap->GetAlphaMaskBuffer();
  if (dest_alpha_buf) {
    dest_alpha_buf += dest_x + m_DestTop * dest_alpha_pitch;
    if (m_bFlipY)
      dest_alpha_buf += dest_alpha_pitch * (m_DestHeight - 1);
  }
  int y_step = dest_pitch;
  int y_alpha_step = dest_alpha_pitch;
  if (m_bFlipY) {
    y_step = -y_step;
    y_alpha_step = -y_alpha_step;
  }
  uint8_t* src_scan = m_pScanlineV.data();
  uint8_t* dest_scan = dest_buf;
  for (int i = 0; i < m_DestHeight; ++i) {
    for (int j = 0; j < Bpp; ++j)
      *src_scan++ = dest_scan[j];
    dest_scan += y_step;
  }
  uint8_t* src_alpha_scan = m_pScanlineAlphaV.data();
  uint8_t* dest_alpha_scan = dest_alpha_buf;
  if (dest_alpha_scan) {
    for (int i = 0; i < m_DestHeight; ++i) {
      *src_alpha_scan++ = *dest_alpha_scan;
      dest_alpha_scan += y_alpha_step;
    }
  }
  uint8_t* clip_scan = nullptr;
  if (m_pClipMask) {
    clip_scan = m_pClipScanV.data();
    int clip_pitch = m_pClipMask->GetPitch();
    const uint8_t* src_clip =
        m_pClipMask->GetBuffer() +
        (m_DestTop - m_pClipRgn->GetBox().top) * clip_pitch +
        (dest_x - m_pClipRgn->GetBox().left);
    if (m_bFlipY) {
      src_clip += clip_pitch * (m_DestHeight - 1);
      clip_pitch = -clip_pitch;
    }
    for (int i = 0; i < m_DestHeight; ++i) {
      clip_scan[i] = *src_clip;
      src_clip += clip_pitch;
    }
  }
  DoCompose(m_pScanlineV.data(), scanline, m_DestHeight, clip_scan,
            scan_extra_alpha, m_pScanlineAlphaV);
  src_scan = m_pScanlineV.data();
  dest_scan = dest_buf;
  for (int i = 0; i < m_DestHeight; ++i) {
    for (int j = 0; j < Bpp; ++j)
      dest_scan[j] = *src_scan++;
    dest_scan += y_step;
  }
  src_alpha_scan = m_pScanlineAlphaV.data();
  dest_alpha_scan = dest_alpha_buf;
  if (!dest_alpha_scan)
    return;
  for (int i = 0; i < m_DestHeight; ++i) {
    *dest_alpha_scan = *src_alpha_scan++;
    dest_alpha_scan += y_alpha_step;
  }
}
