// 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_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/numerics/safe_conversions.h"
#include "core/fxcrt/span.h"
#include "core/fxcrt/stl_util.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_path.h"
#include "fpdfsdk/cpdfsdk_helpers.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,
                    ByteStringView key,
                    float* left,
                    float* bottom,
                    float* right,
                    float* top) {
  if (!page || !left || !bottom || !right || !top) {
    return false;
  }

  RetainPtr<const CPDF_Array> pArray = page->GetDict()->GetArrayFor(key);
  if (!pArray) {
    return false;
  }

  *left = pArray->GetFloatAt(0);
  *bottom = pArray->GetFloatAt(1);
  *right = pArray->GetFloatAt(2);
  *top = pArray->GetFloatAt(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].point_ - points[0].point_;
    buf << points[0].point_.x << " " << points[0].point_.y << " " << diff.x
        << " " << diff.y << " re\n";
    return;
  }

  for (size_t i = 0; i < points.size(); ++i) {
    buf << points[i].point_.x << " " << points[i].point_.y;
    CFX_Path::Point::Type point_type = points[i].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].point_.x << " " << points[i + 1].point_.y
          << " " << points[i + 2].point_.x << " " << points[i + 2].point_.y;
      buf << " c";
      if (points[i + 2].close_figure_) {
        buf << " h";
      }
      buf << "\n";

      i += 2;
    } else if (point_type == CFX_Path::Point::Type::kLine) {
      buf << " l";
      if (points[i].close_figure_) {
        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();
    WriteRect(text_buf, rect) << " re W* n ";
  }
  if (matrix) {
    WriteMatrix(text_buf, CFXMatrixFromFSMatrix(*matrix)) << " cm ";
  }

  auto pStream = pDoc->NewIndirect<CPDF_Stream>(pDoc->New<CPDF_Dictionary>());
  pStream->SetDataFromStringstream(&text_buf);

  auto pEndStream =
      pDoc->NewIndirect<CPDF_Stream>(pDoc->New<CPDF_Dictionary>());
  pEndStream->SetData(ByteStringView(" Q").unsigned_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.
  RetainPtr<const CPDF_Dictionary> pRes =
      pPageDict->GetDictFor(pdfium::page_object::kResources);
  if (!pRes) {
    return true;
  }

  RetainPtr<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> dict;
    if (pObj->IsDictionary()) {
      dict.Reset(pObj->AsMutableDictionary());
    } else if (CPDF_Stream* pObjStream = pObj->AsMutableStream()) {
      dict = pObjStream->GetMutableDict();
    } else {
      continue;
    }

    if (matrix) {
      CFX_Matrix m = CFXMatrixFromFSMatrix(*matrix);
      dict->SetMatrixFor("Matrix", dict->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);
  }
}

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->mutable_clip_path());
}

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::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;
  }

  auto pStream = pDoc->NewIndirect<CPDF_Stream>(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()) {
    auto 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());
  }
}
