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

#include <math.h>
#include <algorithm>
#include <memory>
#include <utility>

#include "core/fpdfapi/page/cpdf_dib.h"
#include "core/fpdfapi/page/cpdf_docpagedata.h"
#include "core/fpdfapi/page/cpdf_iccprofile.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/compiler_specific.h"
#include "core/fxcrt/notreached.h"
#include "core/fxcrt/stl_util.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/dib/cfx_dibitmap.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(UNSAFE_TODO(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;
  }

  RetainPtr<CFX_DIBitmap> holder(CFXDIBitmapFromFPDFBitmap(bitmap));
  if (!holder) {
    return false;
  }
  CHECK(!holder->IsPremultiplied());

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

  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, or if the
  // source image has a color palette, convert it to a representation that does
  // not have a color palette, as there is no public API to access the palette.
  //
  // Otherwise, convert the source image to a bitmap directly,
  // retaining its color representation.
  //
  // Only return FPDF_BITMAPs in formats that FPDFBitmap_CreateEx() would
  // return.
  enum class ConversionOp {
    kRealize,
    kConvertTo8bppRgb,
    kConvertToRgb,
  };

  ConversionOp op;
  switch (pSource->GetFormat()) {
    case FXDIB_Format::k1bppMask:
    case FXDIB_Format::k8bppMask: {
      // Masks do not have palettes, so they can be safely converted to
      // `FXDIB_Format::k8bppRgb`.
      CHECK(!pSource->HasPalette());
      op = ConversionOp::kConvertTo8bppRgb;
      break;
    }
    case FXDIB_Format::k1bppRgb: {
      // If there is a palette, then convert to `FXDIB_Format::kBgr` to avoid
      // creating a bitmap with a palette.
      op = pSource->HasPalette() ? ConversionOp::kConvertToRgb
                                 : ConversionOp::kConvertTo8bppRgb;
      break;
    }
    case FXDIB_Format::k8bppRgb:
    case FXDIB_Format::kBgra:
    case FXDIB_Format::kBgr:
    case FXDIB_Format::kBgrx: {
      // If there is a palette, then convert to `FXDIB_Format::kBgr` to avoid
      // creating a bitmap with a palette.
      op = pSource->HasPalette() ? ConversionOp::kConvertToRgb
                                 : ConversionOp::kRealize;
      break;
    }
    case FXDIB_Format::kInvalid: {
      NOTREACHED();
    }
#if defined(PDF_USE_SKIA)
    case FXDIB_Format::kBgraPremul: {
      // TODO(crbug.com/355676038): Consider adding support for
      // `FXDIB_Format::kBgraPremul`
      NOTREACHED();
    }
#endif
  }

  RetainPtr<CFX_DIBitmap> pBitmap;
  switch (op) {
    case ConversionOp::kRealize:
      pBitmap = pSource->Realize();
      break;
    case ConversionOp::kConvertTo8bppRgb:
      pBitmap = pSource->ConvertTo(FXDIB_Format::k8bppRgb);
      break;
    case ConversionOp::kConvertToRgb:
      pBitmap = pSource->ConvertTo(FXDIB_Format::kBgr);
      break;
  }
  if (!pBitmap) {
    return nullptr;
  }

  CHECK(!pBitmap->HasPalette());
  CHECK(!pBitmap->IsPremultiplied());

  // Caller takes ownership.
  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();
  float output_width = std::ceil(hypotf(image_matrix.a, image_matrix.c));
  float output_height = std::ceil(hypotf(image_matrix.b, image_matrix.d));
  auto result_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
  if (!result_bitmap->Create(static_cast<int>(output_width),
                             static_cast<int>(output_height),
                             FXDIB_Format::kBgra)) {
    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|.
  const CFX_Matrix render_matrix(1, 0, 0, -1, 0, output_height);

  // Then take |image_matrix|'s offset into account.
  float min_x = image_matrix.e + std::min(image_matrix.a, image_matrix.c);
  float min_y = image_matrix.f + std::min(image_matrix.b, image_matrix.d);
  CFX_Matrix image_render_matrix = render_matrix;
  image_render_matrix.Translate(-min_x, min_y);

  // Apply the clip path if there is one.
  if (image->clip_path().HasRef()) {
    CFX_FloatRect output_rect(0, 0, output_width, output_height);
    CFX_FloatRect original_image_rect =
        image->original_matrix().TransformRect(CFX_FloatRect(0, 0, 1, 1));
    CFX_Matrix clip_render_matrix;
    clip_render_matrix.MatchRect(output_rect, original_image_rect);
    clip_render_matrix.Concat(render_matrix);
    status.ProcessClipPath(image->clip_path(), clip_render_matrix);
  }

  // Do the actual rendering.
  bool should_continue =
      renderer.Start(image, image_render_matrix, /*bStdCS=*/false);
  while (should_continue) {
    should_continue = renderer.Continue(/*pPause=*/nullptr);
  }

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

  CHECK(!result_bitmap->IsPremultiplied());

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

  // SAFETY: caller ensures `buffer` points to at least `buflen` bytes.
  return DecodeStreamMaybeCopyAndReturnLength(
      std::move(pImgStream),
      UNSAFE_BUFFERS(pdfium::make_span(static_cast<uint8_t*>(buffer),
                                       static_cast<size_t>(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;

  // SAFETY: caller ensures `buffer` points to at least `buflen` bytes.
  return GetRawStreamMaybeCopyAndReturnLength(
      std::move(pImgStream),
      UNSAFE_BUFFERS(pdfium::make_span(static_cast<uint8_t*>(buffer),
                                       static_cast<size_t>(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);

  // SAFETY: required from caller.
  return NulTerminateMaybeCopyAndReturnLength(
      bsFilter, UNSAFE_BUFFERS(SpanFromFPDFApiArgs(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();
  static 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().Get(), false,
      CPDF_ColorSpace::Family::kUnknown, false, {0, 0});
  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;
}

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_GetImagePixelSize(FPDF_PAGEOBJECT image_object,
                               unsigned int* width,
                               unsigned int* height) {
  CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
  if (!pImgObj || !width || !height) {
    return false;
  }

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

  *width = pImg->GetPixelWidth();
  *height = pImg->GetPixelHeight();
  return true;
}

FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_GetIccProfileDataDecoded(FPDF_PAGEOBJECT image_object,
                                      FPDF_PAGE page,
                                      uint8_t* buffer,
                                      size_t buflen,
                                      size_t* out_buflen) {
  CPDF_ImageObject* image_obj = CPDFImageObjectFromFPDFPageObject(image_object);
  CPDF_Page* pdf_page = CPDFPageFromFPDFPage(page);
  if (!image_obj || !pdf_page || !out_buflen) {
    return false;
  }

  RetainPtr<CPDF_Image> image = image_obj->GetImage();
  if (!image) {
    return false;
  }

  const CPDF_Stream* stream = image->GetStream();
  if (!stream) {
    return false;
  }

  RetainPtr<const CPDF_Dictionary> stream_dict = stream->GetDict();
  if (!stream_dict) {
    return false;
  }

  RetainPtr<const CPDF_Object> color_space_obj =
      stream_dict->GetDirectObjectFor("ColorSpace");
  RetainPtr<const CPDF_Dictionary> page_resources =
      pdf_page->GetPageResources();
  if (!page_resources) {
    return false;
  }

  CPDF_Document* document = pdf_page->GetDocument();
  if (!document) {
    return false;
  }

  auto* doc_data = CPDF_DocPageData::FromDocument(document);
  if (!doc_data) {
    return true;
  }

  RetainPtr<CPDF_ColorSpace> color_space =
      doc_data->GetColorSpace(color_space_obj.Get(), page_resources);
  if (!color_space) {
    return false;
  }

  RetainPtr<CPDF_IccProfile> icc_profile = color_space->GetIccProfile();
  if (!icc_profile || !icc_profile->IsValid()) {
    return false;
  }

  RetainPtr<const CPDF_StreamAcc> stream_acc = icc_profile->GetStreamAcc();

  pdfium::span<const uint8_t> data = stream_acc->GetSpan();
  *out_buflen = data.size();
  if (!buffer || buflen < *out_buflen) {
    return true;
  }

  // SAFETY: required from caller.
  auto result_span = UNSAFE_BUFFERS(SpanFromFPDFApiArgs(buffer, buflen));
  fxcrt::spancpy(result_span, data);
  return true;
}
