// Copyright 2020 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 "core/fpdfapi/render/cpdf_rendertiling.h"

#include <cmath>
#include <limits>
#include <memory>
#include <optional>
#include <utility>

#include "core/fpdfapi/page/cpdf_form.h"
#include "core/fpdfapi/page/cpdf_pageimagecache.h"
#include "core/fpdfapi/page/cpdf_tilingpattern.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/render/cpdf_rendercontext.h"
#include "core/fpdfapi/render/cpdf_renderoptions.h"
#include "core/fpdfapi/render/cpdf_renderstatus.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/span_util.h"
#include "core/fxge/cfx_renderdevice.h"
#include "core/fxge/dib/cfx_dibitmap.h"

namespace {

RetainPtr<CFX_DIBitmap> DrawPatternBitmap(
    CPDF_Document* doc,
    CPDF_PageImageCache* pCache,
    CPDF_TilingPattern* pPattern,
    CPDF_Form* pPatternForm,
    const CFX_Matrix& mtObject2Device,
    int width,
    int height,
    const CPDF_RenderOptions::Options& draw_options) {
  auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
  // TODO(crbug.com/42271020): Consider adding support for
  // `FXDIB_Format::kBgraPremul`
  if (!pBitmap->Create(width, height,
                       pPattern->colored() ? FXDIB_Format::kBgra
                                           : FXDIB_Format::k8bppMask)) {
    return nullptr;
  }
  CFX_RenderDevice bitmap_device;
  bitmap_device.AttachWithBackdropAndGroupKnockout(
      pBitmap, /*pBackdropBitmap=*/nullptr, /*bGroupKnockout=*/true);
  CFX_FloatRect cell_bbox =
      pPattern->pattern_to_form().TransformRect(pPattern->bbox());
  cell_bbox = mtObject2Device.TransformRect(cell_bbox);
  CFX_FloatRect bitmap_rect(0.0f, 0.0f, width, height);
  CFX_Matrix mtAdjust;
  mtAdjust.MatchRect(bitmap_rect, cell_bbox);

  CFX_Matrix mtPattern2Bitmap = mtObject2Device * mtAdjust;
  CPDF_RenderOptions options;
  if (!pPattern->colored()) {
    options.SetColorMode(CPDF_RenderOptions::kAlpha);
  }

  options.GetOptions() = draw_options;
  options.GetOptions().bForceHalftone = true;

  CPDF_RenderContext context(doc, nullptr, pCache);
  context.AppendLayer(pPatternForm, mtPattern2Bitmap);
  context.Render(&bitmap_device, nullptr, &options, nullptr);

  return pBitmap;
}

std::optional<int> CheckedFloatToInt(float value) {
  if (!pdfium::IsValueInRangeForNumericType<int>(value)) {
    return std::nullopt;
  }
  return static_cast<int>(value);
}

}  // namespace

// static
RetainPtr<CFX_DIBitmap> CPDF_RenderTiling::Draw(
    CPDF_RenderStatus* pRenderStatus,
    CPDF_PageObject* pPageObj,
    CPDF_TilingPattern* pPattern,
    CPDF_Form* pPatternForm,
    const CFX_Matrix& mtObj2Device,
    const FX_RECT& clip_box,
    bool bStroke) {
  const CFX_Matrix mtPattern2Device =
      pPattern->pattern_to_form() * mtObj2Device;

  CFX_FloatRect cell_bbox = mtPattern2Device.TransformRect(pPattern->bbox());

  float ceil_height = std::ceil(cell_bbox.Height());
  float ceil_width = std::ceil(cell_bbox.Width());

  // Validate the float will fit into the int when the conversion is done.
  if (!pdfium::IsValueInRangeForNumericType<int>(ceil_height) ||
      !pdfium::IsValueInRangeForNumericType<int>(ceil_width)) {
    return nullptr;
  }

  int width = static_cast<int>(ceil_width);
  int height = static_cast<int>(ceil_height);
  if (width <= 0) {
    width = 1;
  }
  if (height <= 0) {
    height = 1;
  }

  const float x_step = pPattern->x_step();
  const float y_step = pPattern->y_step();
  if (!std::isfinite(x_step) || !std::isfinite(y_step) || x_step == 0.0f ||
      y_step == 0.0f) {
    return nullptr;
  }

  CFX_FloatRect clip_box_p =
      mtPattern2Device.GetInverse().TransformRect(CFX_FloatRect(clip_box));
  std::optional<int> maybe_min_col = CheckedFloatToInt(
      std::ceil((clip_box_p.left - pPattern->bbox().right) / x_step));
  std::optional<int> maybe_max_col = CheckedFloatToInt(
      std::floor((clip_box_p.right - pPattern->bbox().left) / x_step));
  std::optional<int> maybe_min_row = CheckedFloatToInt(
      std::ceil((clip_box_p.bottom - pPattern->bbox().top) / y_step));
  std::optional<int> maybe_max_row = CheckedFloatToInt(
      std::floor((clip_box_p.top - pPattern->bbox().bottom) / y_step));
  if (!maybe_min_col.has_value() || !maybe_max_col.has_value() ||
      !maybe_min_row.has_value() || !maybe_max_row.has_value()) {
    return nullptr;
  }

  int min_col = maybe_min_col.value();
  int max_col = maybe_max_col.value();
  int min_row = maybe_min_row.value();
  int max_row = maybe_max_row.value();

  // Make sure we can fit the needed width * height into an int.
  if (height > std::numeric_limits<int>::max() / width) {
    return nullptr;
  }

  CFX_RenderDevice* pDevice = pRenderStatus->GetRenderDevice();
  CPDF_RenderContext* context = pRenderStatus->GetContext();
  const CPDF_RenderOptions& options = pRenderStatus->GetRenderOptions();
  if (width > clip_box.Width() || height > clip_box.Height() ||
      width * height > clip_box.Width() * clip_box.Height()) {
    std::unique_ptr<CPDF_GraphicStates> pStates;
    if (!pPattern->colored()) {
      pStates = CPDF_RenderStatus::CloneObjStates(&pPageObj->graphic_states(),
                                                  bStroke);
    } else if (pPageObj->AsPath()) {
      pStates = std::make_unique<CPDF_GraphicStates>();
      pStates->SetDefaultStates();
      pStates->mutable_general_state().SetFillAlpha(
          pPageObj->general_state().GetFillAlpha());
    }

    RetainPtr<const CPDF_Dictionary> pFormResource =
        pPatternForm->GetDict()->GetDictFor("Resources");
    for (int col = min_col; col <= max_col; col++) {
      for (int row = min_row; row <= max_row; row++) {
        CFX_PointF original = mtPattern2Device.Transform(
            CFX_PointF(col * pPattern->x_step(), row * pPattern->y_step()));
        CFX_Matrix matrix = mtObj2Device;
        matrix.Translate(original.x - mtPattern2Device.e,
                         original.y - mtPattern2Device.f);
        CFX_RenderDevice::StateRestorer restorer2(pDevice);
        CPDF_RenderStatus status(context, pDevice);
        status.SetOptions(options);
        status.SetTransparency(pPatternForm->GetTransparency());
        status.SetFormResource(pFormResource);
        status.SetDropObjects(pRenderStatus->GetDropObjects());
        status.Initialize(pRenderStatus, pStates.get());
        status.RenderObjectList(pPatternForm, matrix);
      }
    }
    return nullptr;
  }

  bool bAligned =
      pPattern->bbox().left == 0 && pPattern->bbox().bottom == 0 &&
      pPattern->bbox().right == pPattern->x_step() &&
      pPattern->bbox().top == pPattern->y_step() &&
      (mtPattern2Device.IsScaled() || mtPattern2Device.Is90Rotated());
  if (bAligned) {
    int orig_x = FXSYS_roundf(mtPattern2Device.e);
    int orig_y = FXSYS_roundf(mtPattern2Device.f);
    min_col = (clip_box.left - orig_x) / width;
    if (clip_box.left < orig_x) {
      min_col--;
    }

    max_col = (clip_box.right - orig_x) / width;
    if (clip_box.right <= orig_x) {
      max_col--;
    }

    min_row = (clip_box.top - orig_y) / height;
    if (clip_box.top < orig_y) {
      min_row--;
    }

    max_row = (clip_box.bottom - orig_y) / height;
    if (clip_box.bottom <= orig_y) {
      max_row--;
    }
  }
  float left_offset = cell_bbox.left - mtPattern2Device.e;
  float top_offset = cell_bbox.bottom - mtPattern2Device.f;
  RetainPtr<CFX_DIBitmap> pPatternBitmap;
  if (width * height < 16) {
    RetainPtr<CFX_DIBitmap> pEnlargedBitmap = DrawPatternBitmap(
        context->GetDocument(), context->GetPageCache(), pPattern, pPatternForm,
        mtObj2Device, 8, 8, options.GetOptions());
    pPatternBitmap = pEnlargedBitmap->StretchTo(
        width, height, FXDIB_ResampleOptions(), nullptr);
  } else {
    pPatternBitmap = DrawPatternBitmap(
        context->GetDocument(), context->GetPageCache(), pPattern, pPatternForm,
        mtObj2Device, width, height, options.GetOptions());
  }
  if (!pPatternBitmap) {
    return nullptr;
  }

  if (options.ColorModeIs(CPDF_RenderOptions::kGray)) {
    pPatternBitmap->ConvertColorScale(/*is_white_on_black=*/false);
  }

  FX_ARGB fill_argb = pRenderStatus->GetFillArgb(pPageObj);
  int clip_width = clip_box.right - clip_box.left;
  int clip_height = clip_box.bottom - clip_box.top;
  auto pScreen = pdfium::MakeRetain<CFX_DIBitmap>();
  if (!pScreen->Create(clip_width, clip_height, FXDIB_Format::kBgra)) {
    return nullptr;
  }

  pdfium::span<const uint8_t> src_buf = pPatternBitmap->GetBuffer();
  for (int col = min_col; col <= max_col; col++) {
    for (int row = min_row; row <= max_row; row++) {
      int start_x;
      int start_y;
      if (bAligned) {
        start_x =
            FXSYS_roundf(mtPattern2Device.e) + col * width - clip_box.left;
        start_y =
            FXSYS_roundf(mtPattern2Device.f) + row * height - clip_box.top;
      } else {
        CFX_PointF original = mtPattern2Device.Transform(
            CFX_PointF(col * pPattern->x_step(), row * pPattern->y_step()));

        FX_SAFE_INT32 safeStartX = FXSYS_roundf(original.x + left_offset);
        FX_SAFE_INT32 safeStartY = FXSYS_roundf(original.y + top_offset);

        safeStartX -= clip_box.left;
        safeStartY -= clip_box.top;
        if (!safeStartX.IsValid() || !safeStartY.IsValid()) {
          return nullptr;
        }

        start_x = safeStartX.ValueOrDie();
        start_y = safeStartY.ValueOrDie();
      }
      if (width == 1 && height == 1) {
        if (start_x < 0 || start_x >= clip_box.Width() || start_y < 0 ||
            start_y >= clip_box.Height()) {
          continue;
        }
        uint32_t* dest_buf = fxcrt::reinterpret_span<uint32_t>(
                                 pScreen->GetWritableScanline(start_y))
                                 .subspan(static_cast<size_t>(start_x))
                                 .data();
        if (pPattern->colored()) {
          const uint32_t* src_buf32 =
              fxcrt::reinterpret_span<const uint32_t>(src_buf).data();
          *dest_buf = *src_buf32;
        } else {
          *dest_buf = (*(src_buf.data()) << 24) | (fill_argb & 0xffffff);
        }
      } else {
        if (pPattern->colored()) {
          pScreen->CompositeBitmap(start_x, start_y, width, height,
                                   pPatternBitmap, 0, 0, BlendMode::kNormal);
        } else {
          pScreen->CompositeMask(start_x, start_y, width, height,
                                 pPatternBitmap, fill_argb, 0, 0,
                                 BlendMode::kNormal);
        }
      }
    }
  }
  return pScreen;
}
