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

#include <memory>
#include <utility>

#include "core/fpdfapi/page/cpdf_dib.h"
#include "core/fpdfapi/page/cpdf_image.h"
#include "core/fpdfapi/page/cpdf_imageobject.h"
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/page/cpdf_pageobject.h"
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_name.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/cpdf_stream_acc.h"
#include "core/fpdfapi/render/cpdf_imagerenderer.h"
#include "core/fpdfapi/render/cpdf_rendercontext.h"
#include "core/fpdfapi/render/cpdf_renderstatus.h"
#include "core/fxcrt/stl_util.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
#include "fpdfsdk/cpdfsdk_customaccess.h"
#include "fpdfsdk/cpdfsdk_helpers.h"

namespace {

// These checks ensure the consistency of colorspace values across core/ and
// public/.
static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceGray) ==
                  FPDF_COLORSPACE_DEVICEGRAY,
              "kDeviceGray value mismatch");
static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceRGB) ==
                  FPDF_COLORSPACE_DEVICERGB,
              "kDeviceRGB value mismatch");
static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceCMYK) ==
                  FPDF_COLORSPACE_DEVICECMYK,
              "kDeviceCMYK value mismatch");
static_assert(static_cast<int>(CPDF_ColorSpace::Family::kCalGray) ==
                  FPDF_COLORSPACE_CALGRAY,
              "kCalGray value mismatch");
static_assert(static_cast<int>(CPDF_ColorSpace::Family::kCalRGB) ==
                  FPDF_COLORSPACE_CALRGB,
              "kCalRGB value mismatch");
static_assert(static_cast<int>(CPDF_ColorSpace::Family::kLab) ==
                  FPDF_COLORSPACE_LAB,
              "kLab value mismatch");
static_assert(static_cast<int>(CPDF_ColorSpace::Family::kICCBased) ==
                  FPDF_COLORSPACE_ICCBASED,
              "kICCBased value mismatch");
static_assert(static_cast<int>(CPDF_ColorSpace::Family::kSeparation) ==
                  FPDF_COLORSPACE_SEPARATION,
              "kSeparation value mismatch");
static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceN) ==
                  FPDF_COLORSPACE_DEVICEN,
              "kDeviceN value mismatch");
static_assert(static_cast<int>(CPDF_ColorSpace::Family::kIndexed) ==
                  FPDF_COLORSPACE_INDEXED,
              "kIndexed value mismatch");
static_assert(static_cast<int>(CPDF_ColorSpace::Family::kPattern) ==
                  FPDF_COLORSPACE_PATTERN,
              "kPattern value mismatch");

RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
    FPDF_FILEACCESS* pFileAccess) {
  return pdfium::MakeRetain<CPDFSDK_CustomAccess>(pFileAccess);
}

CPDF_ImageObject* CPDFImageObjectFromFPDFPageObject(
    FPDF_PAGEOBJECT image_object) {
  CPDF_PageObject* pPageObject = CPDFPageObjectFromFPDFPageObject(image_object);
  return pPageObject ? pPageObject->AsImage() : nullptr;
}

bool LoadJpegHelper(FPDF_PAGE* pages,
                    int count,
                    FPDF_PAGEOBJECT image_object,
                    FPDF_FILEACCESS* file_access,
                    bool inline_jpeg) {
  CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
  if (!pImgObj)
    return false;

  if (!file_access)
    return false;

  if (pages) {
    for (int index = 0; index < count; index++) {
      CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]);
      if (pPage)
        pImgObj->GetImage()->ResetCache(pPage);
    }
  }

  RetainPtr<IFX_SeekableReadStream> pFile = MakeSeekableReadStream(file_access);
  if (inline_jpeg)
    pImgObj->GetImage()->SetJpegImageInline(std::move(pFile));
  else
    pImgObj->GetImage()->SetJpegImage(std::move(pFile));

  pImgObj->SetDirty(true);
  return true;
}

}  // namespace

FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV
FPDFPageObj_NewImageObj(FPDF_DOCUMENT document) {
  CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
  if (!pDoc)
    return nullptr;

  auto pImageObj = std::make_unique<CPDF_ImageObject>();
  pImageObj->SetImage(pdfium::MakeRetain<CPDF_Image>(pDoc));

  // Caller takes ownership.
  return FPDFPageObjectFromCPDFPageObject(pImageObj.release());
}

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_LoadJpegFile(FPDF_PAGE* pages,
                          int count,
                          FPDF_PAGEOBJECT image_object,
                          FPDF_FILEACCESS* file_access) {
  return LoadJpegHelper(pages, count, image_object, file_access, false);
}

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_LoadJpegFileInline(FPDF_PAGE* pages,
                                int count,
                                FPDF_PAGEOBJECT image_object,
                                FPDF_FILEACCESS* file_access) {
  return LoadJpegHelper(pages, count, image_object, file_access, true);
}

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object,
                       double a,
                       double b,
                       double c,
                       double d,
                       double e,
                       double f) {
  CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
  if (!pImgObj)
    return false;

  pImgObj->SetImageMatrix(CFX_Matrix(
      static_cast<float>(a), static_cast<float>(b), static_cast<float>(c),
      static_cast<float>(d), static_cast<float>(e), static_cast<float>(f)));
  pImgObj->SetDirty(true);
  return true;
}

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_SetBitmap(FPDF_PAGE* pages,
                       int count,
                       FPDF_PAGEOBJECT image_object,
                       FPDF_BITMAP bitmap) {
  CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
  if (!pImgObj)
    return false;

  if (!bitmap)
    return false;

  if (pages) {
    for (int index = 0; index < count; index++) {
      CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]);
      if (pPage)
        pImgObj->GetImage()->ResetCache(pPage);
    }
  }

  RetainPtr<CFX_DIBitmap> holder(CFXDIBitmapFromFPDFBitmap(bitmap));
  pImgObj->GetImage()->SetImage(holder);
  pImgObj->CalcBoundingBox();
  pImgObj->SetDirty(true);
  return true;
}

FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
FPDFImageObj_GetBitmap(FPDF_PAGEOBJECT image_object) {
  CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
  if (!pImgObj)
    return nullptr;

  RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
  if (!pImg)
    return nullptr;

  RetainPtr<CFX_DIBBase> pSource = pImg->LoadDIBBase();
  if (!pSource)
    return nullptr;

  // If the source image has a representation of 1 bit per pixel, then convert
  // it to a grayscale bitmap having 1 byte per pixel, since bitmaps have no
  // concept of bits. Otherwise, convert the source image to a bitmap directly,
  // retaining its color representation.
  RetainPtr<CFX_DIBitmap> pBitmap =
      pSource->GetBPP() == 1 ? pSource->ConvertTo(FXDIB_Format::k8bppRgb)
                             : pSource->Realize();

  return FPDFBitmapFromCFXDIBitmap(pBitmap.Leak());
}

FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
FPDFImageObj_GetRenderedBitmap(FPDF_DOCUMENT document,
                               FPDF_PAGE page,
                               FPDF_PAGEOBJECT image_object) {
  CPDF_Document* doc = CPDFDocumentFromFPDFDocument(document);
  if (!doc)
    return nullptr;

  CPDF_Page* optional_page = CPDFPageFromFPDFPage(page);
  if (optional_page && optional_page->GetDocument() != doc)
    return nullptr;

  CPDF_ImageObject* image = CPDFImageObjectFromFPDFPageObject(image_object);
  if (!image)
    return nullptr;

  // Create |result_bitmap|.
  const CFX_Matrix& image_matrix = image->matrix();
  int output_width = image_matrix.a;
  int output_height = image_matrix.d;
  auto result_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
  if (!result_bitmap->Create(output_width, output_height, FXDIB_Format::kArgb))
    return nullptr;

  // Set up all the rendering code.
  RetainPtr<CPDF_Dictionary> page_resources =
      optional_page ? optional_page->GetMutablePageResources() : nullptr;
  CPDF_RenderContext context(doc, std::move(page_resources),
                             /*pPageCache=*/nullptr);
  CFX_DefaultRenderDevice device;
  device.Attach(result_bitmap);
  CPDF_RenderStatus status(&context, &device);
  CPDF_ImageRenderer renderer(&status);

  // Need to first flip the image, as expected by |renderer|.
  CFX_Matrix render_matrix(1, 0, 0, -1, 0, output_height);

  // Then take |image_matrix|'s offset into account.
  render_matrix.Translate(-image_matrix.e, image_matrix.f);

  // Do the actual rendering.
  bool should_continue = renderer.Start(image, render_matrix,
                                        /*bStdCS=*/false, BlendMode::kNormal);
  while (should_continue)
    should_continue = renderer.Continue(/*pPause=*/nullptr);

  if (!renderer.GetResult())
    return nullptr;

#if defined(_SKIA_SUPPORT_)
  if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
    result_bitmap->UnPreMultiply();
#endif

  // Caller takes ownership.
  return FPDFBitmapFromCFXDIBitmap(result_bitmap.Leak());
}

FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFImageObj_GetImageDataDecoded(FPDF_PAGEOBJECT image_object,
                                 void* buffer,
                                 unsigned long buflen) {
  CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
  if (!pImgObj)
    return 0;

  RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
  if (!pImg)
    return 0;

  RetainPtr<const CPDF_Stream> pImgStream = pImg->GetStream();
  if (!pImgStream)
    return 0;

  return DecodeStreamMaybeCopyAndReturnLength(pImgStream.Get(), buffer, buflen);
}

FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFImageObj_GetImageDataRaw(FPDF_PAGEOBJECT image_object,
                             void* buffer,
                             unsigned long buflen) {
  CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
  if (!pImgObj)
    return 0;

  RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
  if (!pImg)
    return 0;

  RetainPtr<const CPDF_Stream> pImgStream = pImg->GetStream();
  if (!pImgStream)
    return 0;

  return GetRawStreamMaybeCopyAndReturnLength(pImgStream.Get(), buffer, buflen);
}

FPDF_EXPORT int FPDF_CALLCONV
FPDFImageObj_GetImageFilterCount(FPDF_PAGEOBJECT image_object) {
  CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
  if (!pImgObj)
    return 0;

  RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
  if (!pImg)
    return 0;

  RetainPtr<const CPDF_Dictionary> pDict = pImg->GetDict();
  if (!pDict)
    return 0;

  RetainPtr<const CPDF_Object> pFilter = pDict->GetDirectObjectFor("Filter");
  if (!pFilter)
    return 0;

  if (pFilter->IsArray())
    return fxcrt::CollectionSize<int>(*pFilter->AsArray());

  if (pFilter->IsName())
    return 1;

  return 0;
}

FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFImageObj_GetImageFilter(FPDF_PAGEOBJECT image_object,
                            int index,
                            void* buffer,
                            unsigned long buflen) {
  if (index < 0 || index >= FPDFImageObj_GetImageFilterCount(image_object))
    return 0;

  CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
  RetainPtr<const CPDF_Dictionary> pDict =
      pObj->AsImage()->GetImage()->GetDict();
  RetainPtr<const CPDF_Object> pFilter = pDict->GetDirectObjectFor("Filter");
  ByteString bsFilter = pFilter->IsName()
                            ? pFilter->AsName()->GetString()
                            : pFilter->AsArray()->GetByteStringAt(index);

  return NulTerminateMaybeCopyAndReturnLength(bsFilter, buffer, buflen);
}

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_GetImageMetadata(FPDF_PAGEOBJECT image_object,
                              FPDF_PAGE page,
                              FPDF_IMAGEOBJ_METADATA* metadata) {
  CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
  if (!pImgObj || !metadata)
    return false;

  RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
  if (!pImg)
    return false;

  metadata->marked_content_id =
      pImgObj->GetContentMarks()->GetMarkedContentID();

  const int nPixelWidth = pImg->GetPixelWidth();
  const int nPixelHeight = pImg->GetPixelHeight();
  metadata->width = nPixelWidth;
  metadata->height = nPixelHeight;

  const float nWidth = pImgObj->GetRect().Width();
  const float nHeight = pImgObj->GetRect().Height();
  constexpr int nPointsPerInch = 72;
  if (nWidth != 0 && nHeight != 0) {
    metadata->horizontal_dpi = nPixelWidth / nWidth * nPointsPerInch;
    metadata->vertical_dpi = nPixelHeight / nHeight * nPointsPerInch;
  }

  metadata->bits_per_pixel = 0;
  metadata->colorspace = FPDF_COLORSPACE_UNKNOWN;

  CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
  if (!pPage || !pPage->GetDocument() || !pImg->GetStream())
    return true;

  // A cross-document image may have come from the embedder.
  if (pPage->GetDocument() != pImg->GetDocument())
    return false;

  RetainPtr<CPDF_DIB> pSource = pImg->CreateNewDIB();
  CPDF_DIB::LoadState ret = pSource->StartLoadDIBBase(
      false, nullptr, pPage->GetPageResources(), false,
      CPDF_ColorSpace::Family::kUnknown, false);
  if (ret == CPDF_DIB::LoadState::kFail)
    return true;

  metadata->bits_per_pixel = pSource->GetBPP();
  if (pSource->GetColorSpace()) {
    metadata->colorspace =
        static_cast<int>(pSource->GetColorSpace()->GetFamily());
  }
  return true;
}
