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

#include "core/fxge/win32/cfx_windowsdib.h"

#include <windows.h>

#include <vector>

#include "core/fxcrt/fx_memory_wrappers.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxge/cfx_gemodule.h"
#include "core/fxge/win32/cwin32_platform.h"

namespace {

void GetBitmapSize(HBITMAP hBitmap, int& w, int& h) {
  BITMAP bmp;
  GetObject(hBitmap, sizeof bmp, &bmp);
  w = bmp.bmWidth;
  h = bmp.bmHeight;
}

}  // namespace

// static
ByteString CFX_WindowsDIB::GetBitmapInfo(
    const RetainPtr<CFX_DIBitmap>& pBitmap) {
  int len = sizeof(BITMAPINFOHEADER);
  if (pBitmap->GetBPP() == 1 || pBitmap->GetBPP() == 8)
    len += sizeof(DWORD) * (int)(1 << pBitmap->GetBPP());

  ByteString result;
  {
    // Span's lifetime must end before ReleaseBuffer() below.
    pdfium::span<char> cspan = result.GetBuffer(len);
    BITMAPINFOHEADER* pbmih = reinterpret_cast<BITMAPINFOHEADER*>(cspan.data());
    memset(pbmih, 0, sizeof(BITMAPINFOHEADER));
    pbmih->biSize = sizeof(BITMAPINFOHEADER);
    pbmih->biBitCount = pBitmap->GetBPP();
    pbmih->biCompression = BI_RGB;
    pbmih->biHeight = -(int)pBitmap->GetHeight();
    pbmih->biPlanes = 1;
    pbmih->biWidth = pBitmap->GetWidth();
    if (pBitmap->GetBPP() == 8) {
      uint32_t* pPalette = (uint32_t*)(pbmih + 1);
      if (pBitmap->HasPalette()) {
        pdfium::span<const uint32_t> palette = pBitmap->GetPaletteSpan();
        for (int i = 0; i < 256; i++) {
          pPalette[i] = palette[i];
        }
      } else {
        for (int i = 0; i < 256; i++) {
          pPalette[i] = i * 0x010101;
        }
      }
    }
    if (pBitmap->GetBPP() == 1) {
      uint32_t* pPalette = (uint32_t*)(pbmih + 1);
      if (pBitmap->HasPalette()) {
        pPalette[0] = pBitmap->GetPaletteSpan()[0];
        pPalette[1] = pBitmap->GetPaletteSpan()[1];
      } else {
        pPalette[0] = 0;
        pPalette[1] = 0xffffff;
      }
    }
  }
  result.ReleaseBuffer(len);
  return result;
}

// static
RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi,
                                                    LPVOID pData,
                                                    bool bAlpha) {
  int width = pbmi->bmiHeader.biWidth;
  int height = pbmi->bmiHeader.biHeight;
  BOOL bBottomUp = true;
  if (height < 0) {
    height = -height;
    bBottomUp = false;
  }
  int pitch = (width * pbmi->bmiHeader.biBitCount + 31) / 32 * 4;
  auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
  FXDIB_Format format = bAlpha
                            ? (FXDIB_Format)(pbmi->bmiHeader.biBitCount + 0x200)
                            : (FXDIB_Format)pbmi->bmiHeader.biBitCount;
  if (!pBitmap->Create(width, height, format))
    return nullptr;

  memcpy(pBitmap->GetBuffer(), pData, pitch * height);
  if (bBottomUp) {
    std::vector<uint8_t, FxAllocAllocator<uint8_t>> temp_buf(pitch);
    int top = 0;
    int bottom = height - 1;
    while (top < bottom) {
      uint8_t* top_ptr = pBitmap->GetBuffer() + top * pitch;
      uint8_t* bottom_ptr = pBitmap->GetBuffer() + bottom * pitch;
      memcpy(temp_buf.data(), top_ptr, pitch);
      memcpy(top_ptr, bottom_ptr, pitch);
      memcpy(bottom_ptr, temp_buf.data(), pitch);
      top++;
      bottom--;
    }
  }
  if (pbmi->bmiHeader.biBitCount == 1) {
    for (int i = 0; i < 2; i++)
      pBitmap->SetPaletteArgb(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000);
  } else if (pbmi->bmiHeader.biBitCount == 8) {
    for (int i = 0; i < 256; i++)
      pBitmap->SetPaletteArgb(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000);
  }
  return pBitmap;
}

// static
HBITMAP CFX_WindowsDIB::GetDDBitmap(const RetainPtr<CFX_DIBitmap>& pBitmap,
                                    HDC hDC) {
  ByteString info = GetBitmapInfo(pBitmap);
  return CreateDIBitmap(hDC, (BITMAPINFOHEADER*)info.c_str(), CBM_INIT,
                        pBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(),
                        DIB_RGB_COLORS);
}

// static
RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromFile(const wchar_t* filename) {
  auto* pPlatform =
      static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform());
  if (pPlatform->m_GdiplusExt.IsAvailable()) {
    WINDIB_Open_Args_ args;
    args.flags = WINDIB_OPEN_PATHNAME;
    args.path_name = filename;
    return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
  }
  HBITMAP hBitmap = (HBITMAP)LoadImageW(nullptr, (wchar_t*)filename,
                                        IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  if (!hBitmap) {
    return nullptr;
  }
  HDC hDC = CreateCompatibleDC(nullptr);
  int width;
  int height;
  GetBitmapSize(hBitmap, width, height);
  auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
  if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
    DeleteDC(hDC);
    return nullptr;
  }
  ByteString info = GetBitmapInfo(pDIBitmap);
  int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
                      (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
  DeleteDC(hDC);
  if (!ret)
    return nullptr;
  return pDIBitmap;
}

// static
RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromFile(const char* filename) {
  return LoadFromFile(WideString::FromDefANSI(filename).c_str());
}

// static
RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) {
  auto* pPlatform =
      static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform());
  if (pPlatform->m_GdiplusExt.IsAvailable()) {
    return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
  }
  if (args.flags == WINDIB_OPEN_MEMORY) {
    return nullptr;
  }
  HBITMAP hBitmap = (HBITMAP)LoadImageW(nullptr, (wchar_t*)args.path_name,
                                        IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  if (!hBitmap) {
    return nullptr;
  }
  HDC hDC = CreateCompatibleDC(nullptr);
  int width, height;
  GetBitmapSize(hBitmap, width, height);
  auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
  if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
    DeleteDC(hDC);
    return nullptr;
  }
  ByteString info = GetBitmapInfo(pDIBitmap);
  int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
                      (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
  DeleteDC(hDC);
  if (!ret)
    return nullptr;
  return pDIBitmap;
}

CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height) {
  Create(width, height, FXDIB_Rgb, (uint8_t*)1, 0);
  BITMAPINFOHEADER bmih;
  memset(&bmih, 0, sizeof bmih);
  bmih.biSize = sizeof bmih;
  bmih.biBitCount = 24;
  bmih.biHeight = -height;
  bmih.biPlanes = 1;
  bmih.biWidth = width;
  LPVOID pData = nullptr;
  m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, &pData,
                               nullptr, 0);
  m_pBuffer.Reset(static_cast<uint8_t*>(pData));
  m_hMemDC = CreateCompatibleDC(hDC);
  m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap);
}

CFX_WindowsDIB::~CFX_WindowsDIB() {
  SelectObject(m_hMemDC, m_hOldBitmap);
  DeleteDC(m_hMemDC);
  DeleteObject(m_hBitmap);
}

// static
void CFX_WindowsDIB::LoadFromDevice(HDC hDC, int left, int top) {
  ::BitBlt(m_hMemDC, 0, 0, m_Width, m_Height, hDC, left, top, SRCCOPY);
}

void CFX_WindowsDIB::SetToDevice(HDC hDC, int left, int top) {
  ::BitBlt(hDC, left, top, m_Width, m_Height, m_hMemDC, 0, 0, SRCCOPY);
}
