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

#include <memory>
#include <sstream>

#include "constants/page_object.h"
#include "core/fpdfapi/edit/cpdf_contentstream_write_utils.h"
#include "core/fpdfapi/page/cpdf_clippath.h"
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/page/cpdf_pageobject.h"
#include "core/fpdfapi/page/cpdf_path.h"
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_number.h"
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fxcrt/fx_string_wrappers.h"
#include "core/fxcrt/stl_util.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_path.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
#include "third_party/base/numerics/safe_conversions.h"
#include "third_party/base/span.h"

namespace {

void SetBoundingBox(CPDF_Page* page,
                    const ByteString& key,
                    const CFX_FloatRect& rect) {
  if (!page)
    return;

  page->GetMutableDict()->SetRectFor(key, rect);
  page->UpdateDimensions();
}

bool GetBoundingBox(const CPDF_Page* page,
                    const ByteString& key,
                    float* left,
                    float* bottom,
                    float* right,
                    float* top) {
  if (!page || !left || !bottom || !right || !top)
    return false;

  const CPDF_Array* pArray = page->GetDict()->GetArrayFor(key);
  if (!pArray)
    return false;

  *left = pArray->GetNumberAt(0);
  *bottom = pArray->GetNumberAt(1);
  *right = pArray->GetNumberAt(2);
  *top = pArray->GetNumberAt(3);
  return true;
}

RetainPtr<CPDF_Object> GetPageContent(CPDF_Dictionary* pPageDict) {
  return pPageDict->GetMutableDirectObjectFor(pdfium::page_object::kContents);
}

void OutputPath(fxcrt::ostringstream& buf, CPDF_Path path) {
  const CFX_Path* pPath = path.GetObject();
  if (!pPath)
    return;

  pdfium::span<const CFX_Path::Point> points = pPath->GetPoints();
  if (path.IsRect()) {
    CFX_PointF diff = points[2].m_Point - points[0].m_Point;
    buf << points[0].m_Point.x << " " << points[0].m_Point.y << " " << diff.x
        << " " << diff.y << " re\n";
    return;
  }

  for (size_t i = 0; i < points.size(); ++i) {
    buf << points[i].m_Point.x << " " << points[i].m_Point.y;
    CFX_Path::Point::Type point_type = points[i].m_Type;
    if (point_type == CFX_Path::Point::Type::kMove) {
      buf << " m\n";
    } else if (point_type == CFX_Path::Point::Type::kBezier) {
      buf << " " << points[i + 1].m_Point.x << " " << points[i + 1].m_Point.y
          << " " << points[i + 2].m_Point.x << " " << points[i + 2].m_Point.y;
      buf << " c";
      if (points[i + 2].m_CloseFigure)
        buf << " h";
      buf << "\n";

      i += 2;
    } else if (point_type == CFX_Path::Point::Type::kLine) {
      buf << " l";
      if (points[i].m_CloseFigure)
        buf << " h";
      buf << "\n";
    }
  }
}

}  // namespace

FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetMediaBox(FPDF_PAGE page,
                                                    float left,
                                                    float bottom,
                                                    float right,
                                                    float top) {
  SetBoundingBox(CPDFPageFromFPDFPage(page), pdfium::page_object::kMediaBox,
                 CFX_FloatRect(left, bottom, right, top));
}

FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetCropBox(FPDF_PAGE page,
                                                   float left,
                                                   float bottom,
                                                   float right,
                                                   float top) {
  SetBoundingBox(CPDFPageFromFPDFPage(page), pdfium::page_object::kCropBox,
                 CFX_FloatRect(left, bottom, right, top));
}

FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetBleedBox(FPDF_PAGE page,
                                                    float left,
                                                    float bottom,
                                                    float right,
                                                    float top) {
  SetBoundingBox(CPDFPageFromFPDFPage(page), pdfium::page_object::kBleedBox,
                 CFX_FloatRect(left, bottom, right, top));
}

FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetTrimBox(FPDF_PAGE page,
                                                   float left,
                                                   float bottom,
                                                   float right,
                                                   float top) {
  SetBoundingBox(CPDFPageFromFPDFPage(page), pdfium::page_object::kTrimBox,
                 CFX_FloatRect(left, bottom, right, top));
}

FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetArtBox(FPDF_PAGE page,
                                                  float left,
                                                  float bottom,
                                                  float right,
                                                  float top) {
  SetBoundingBox(CPDFPageFromFPDFPage(page), pdfium::page_object::kArtBox,
                 CFX_FloatRect(left, bottom, right, top));
}

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetMediaBox(FPDF_PAGE page,
                                                         float* left,
                                                         float* bottom,
                                                         float* right,
                                                         float* top) {
  return GetBoundingBox(CPDFPageFromFPDFPage(page),
                        pdfium::page_object::kMediaBox, left, bottom, right,
                        top);
}

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetCropBox(FPDF_PAGE page,
                                                        float* left,
                                                        float* bottom,
                                                        float* right,
                                                        float* top) {
  return GetBoundingBox(CPDFPageFromFPDFPage(page),
                        pdfium::page_object::kCropBox, left, bottom, right,
                        top);
}

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetBleedBox(FPDF_PAGE page,
                                                         float* left,
                                                         float* bottom,
                                                         float* right,
                                                         float* top) {
  return GetBoundingBox(CPDFPageFromFPDFPage(page),
                        pdfium::page_object::kBleedBox, left, bottom, right,
                        top);
}

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetTrimBox(FPDF_PAGE page,
                                                        float* left,
                                                        float* bottom,
                                                        float* right,
                                                        float* top) {
  return GetBoundingBox(CPDFPageFromFPDFPage(page),
                        pdfium::page_object::kTrimBox, left, bottom, right,
                        top);
}

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetArtBox(FPDF_PAGE page,
                                                       float* left,
                                                       float* bottom,
                                                       float* right,
                                                       float* top) {
  return GetBoundingBox(CPDFPageFromFPDFPage(page),
                        pdfium::page_object::kArtBox, left, bottom, right, top);
}

FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFPage_TransFormWithClip(FPDF_PAGE page,
                           const FS_MATRIX* matrix,
                           const FS_RECTF* clipRect) {
  if (!matrix && !clipRect)
    return false;

  CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
  if (!pPage)
    return false;

  RetainPtr<CPDF_Dictionary> pPageDict = pPage->GetMutableDict();
  RetainPtr<CPDF_Object> pContentObj = GetPageContent(pPageDict.Get());
  if (!pContentObj)
    return false;

  CPDF_Document* pDoc = pPage->GetDocument();
  if (!pDoc)
    return false;

  fxcrt::ostringstream text_buf;
  text_buf << "q ";

  if (clipRect) {
    CFX_FloatRect rect = CFXFloatRectFromFSRectF(*clipRect);
    rect.Normalize();

    WriteFloat(text_buf, rect.left) << " ";
    WriteFloat(text_buf, rect.bottom) << " ";
    WriteFloat(text_buf, rect.Width()) << " ";
    WriteFloat(text_buf, rect.Height()) << " re W* n ";
  }
  if (matrix) {
    CFX_Matrix m = CFXMatrixFromFSMatrix(*matrix);
    text_buf << m << " cm ";
  }

  CPDF_Stream* pStream =
      pDoc->NewIndirect<CPDF_Stream>(nullptr, 0, pDoc->New<CPDF_Dictionary>());
  pStream->SetDataFromStringstream(&text_buf);

  CPDF_Stream* pEndStream =
      pDoc->NewIndirect<CPDF_Stream>(nullptr, 0, pDoc->New<CPDF_Dictionary>());
  pEndStream->SetData(ByteStringView(" Q").raw_span());

  RetainPtr<CPDF_Array> pContentArray = ToArray(pContentObj);
  if (pContentArray) {
    pContentArray->InsertNewAt<CPDF_Reference>(0, pDoc, pStream->GetObjNum());
    pContentArray->AppendNew<CPDF_Reference>(pDoc, pEndStream->GetObjNum());
  } else if (pContentObj->IsStream() && !pContentObj->IsInline()) {
    pContentArray = pDoc->NewIndirect<CPDF_Array>();
    pContentArray->AppendNew<CPDF_Reference>(pDoc, pStream->GetObjNum());
    pContentArray->AppendNew<CPDF_Reference>(pDoc, pContentObj->GetObjNum());
    pContentArray->AppendNew<CPDF_Reference>(pDoc, pEndStream->GetObjNum());
    pPageDict->SetNewFor<CPDF_Reference>(pdfium::page_object::kContents, pDoc,
                                         pContentArray->GetObjNum());
  }

  // Need to transform the patterns as well.
  const CPDF_Dictionary* pRes =
      pPageDict->GetDictFor(pdfium::page_object::kResources);
  if (!pRes)
    return true;

  const CPDF_Dictionary* pPatternDict = pRes->GetDictFor("Pattern");
  if (!pPatternDict)
    return true;

  CPDF_DictionaryLocker locker(pPatternDict);
  for (const auto& it : locker) {
    RetainPtr<CPDF_Object> pObj = it.second;
    if (pObj->IsReference())
      pObj = pObj->GetMutableDirect();

    RetainPtr<CPDF_Dictionary> pDict;
    if (pObj->IsDictionary())
      pDict = pObj->AsDictionary();
    else if (CPDF_Stream* pObjStream = pObj->AsStream())
      pDict = pObjStream->GetMutableDict();
    else
      continue;

    if (matrix) {
      CFX_Matrix m = CFXMatrixFromFSMatrix(*matrix);
      pDict->SetMatrixFor("Matrix", pDict->GetMatrixFor("Matrix") * m);
    }
  }

  return true;
}

FPDF_EXPORT void FPDF_CALLCONV
FPDFPageObj_TransformClipPath(FPDF_PAGEOBJECT page_object,
                              double a,
                              double b,
                              double c,
                              double d,
                              double e,
                              double f) {
  CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(page_object);
  if (!pPageObj)
    return;

  CFX_Matrix matrix((float)a, (float)b, (float)c, (float)d, (float)e, (float)f);

  // Special treatment to shading object, because the ClipPath for shading
  // object is already transformed.
  if (!pPageObj->IsShading())
    pPageObj->TransformClipPath(matrix);
  pPageObj->TransformGeneralState(matrix);
}

FPDF_EXPORT FPDF_CLIPPATH FPDF_CALLCONV
FPDFPageObj_GetClipPath(FPDF_PAGEOBJECT page_object) {
  CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(page_object);
  if (!pPageObj)
    return nullptr;

  return FPDFClipPathFromCPDFClipPath(&pPageObj->m_ClipPath);
}

FPDF_EXPORT int FPDF_CALLCONV FPDFClipPath_CountPaths(FPDF_CLIPPATH clip_path) {
  CPDF_ClipPath* pClipPath = CPDFClipPathFromFPDFClipPath(clip_path);
  if (!pClipPath || !pClipPath->HasRef())
    return -1;

  return pdfium::base::checked_cast<int>(pClipPath->GetPathCount());
}

FPDF_EXPORT int FPDF_CALLCONV
FPDFClipPath_CountPathSegments(FPDF_CLIPPATH clip_path, int path_index) {
  CPDF_ClipPath* pClipPath = CPDFClipPathFromFPDFClipPath(clip_path);
  if (!pClipPath || !pClipPath->HasRef())
    return -1;

  if (path_index < 0 ||
      static_cast<size_t>(path_index) >= pClipPath->GetPathCount()) {
    return -1;
  }

  return fxcrt::CollectionSize<int>(pClipPath->GetPath(path_index).GetPoints());
}

FPDF_EXPORT FPDF_PATHSEGMENT FPDF_CALLCONV
FPDFClipPath_GetPathSegment(FPDF_CLIPPATH clip_path,
                            int path_index,
                            int segment_index) {
  CPDF_ClipPath* pClipPath = CPDFClipPathFromFPDFClipPath(clip_path);
  if (!pClipPath || !pClipPath->HasRef())
    return nullptr;

  if (path_index < 0 ||
      static_cast<size_t>(path_index) >= pClipPath->GetPathCount()) {
    return nullptr;
  }

  pdfium::span<const CFX_Path::Point> points =
      pClipPath->GetPath(path_index).GetPoints();
  if (!fxcrt::IndexInBounds(points, segment_index))
    return nullptr;

  return FPDFPathSegmentFromFXPathPoint(&points[segment_index]);
}

FPDF_EXPORT FPDF_CLIPPATH FPDF_CALLCONV FPDF_CreateClipPath(float left,
                                                            float bottom,
                                                            float right,
                                                            float top) {
  CPDF_Path Path;
  Path.AppendRect(left, bottom, right, top);

  auto pNewClipPath = std::make_unique<CPDF_ClipPath>();
  pNewClipPath->AppendPath(Path, CFX_FillRenderOptions::FillType::kEvenOdd);

  // Caller takes ownership.
  return FPDFClipPathFromCPDFClipPath(pNewClipPath.release());
}

FPDF_EXPORT void FPDF_CALLCONV FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath) {
  // Take ownership back from caller and destroy.
  std::unique_ptr<CPDF_ClipPath>(CPDFClipPathFromFPDFClipPath(clipPath));
}

FPDF_EXPORT void FPDF_CALLCONV FPDFPage_InsertClipPath(FPDF_PAGE page,
                                                       FPDF_CLIPPATH clipPath) {
  CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
  if (!pPage)
    return;

  RetainPtr<CPDF_Dictionary> pPageDict = pPage->GetMutableDict();
  RetainPtr<CPDF_Object> pContentObj = GetPageContent(pPageDict.Get());
  if (!pContentObj)
    return;

  fxcrt::ostringstream strClip;
  CPDF_ClipPath* pClipPath = CPDFClipPathFromFPDFClipPath(clipPath);
  for (size_t i = 0; i < pClipPath->GetPathCount(); ++i) {
    CPDF_Path path = pClipPath->GetPath(i);
    if (path.GetPoints().empty()) {
      // Empty clipping (totally clipped out)
      strClip << "0 0 m W n ";
    } else {
      OutputPath(strClip, path);
      if (pClipPath->GetClipType(i) ==
          CFX_FillRenderOptions::FillType::kWinding) {
        strClip << "W n\n";
      } else {
        strClip << "W* n\n";
      }
    }
  }
  CPDF_Document* pDoc = pPage->GetDocument();
  if (!pDoc)
    return;

  CPDF_Stream* pStream =
      pDoc->NewIndirect<CPDF_Stream>(nullptr, 0, pDoc->New<CPDF_Dictionary>());
  pStream->SetDataFromStringstream(&strClip);

  RetainPtr<CPDF_Array> pArray = ToArray(pContentObj);
  if (pArray) {
    pArray->InsertNewAt<CPDF_Reference>(0, pDoc, pStream->GetObjNum());
  } else if (pContentObj->IsStream() && !pContentObj->IsInline()) {
    CPDF_Array* pContentArray = pDoc->NewIndirect<CPDF_Array>();
    pContentArray->AppendNew<CPDF_Reference>(pDoc, pStream->GetObjNum());
    pContentArray->AppendNew<CPDF_Reference>(pDoc, pContentObj->GetObjNum());
    pPageDict->SetNewFor<CPDF_Reference>(pdfium::page_object::kContents, pDoc,
                                         pContentArray->GetObjNum());
  }
}
