// Copyright 2016 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_renderstatus.h"

#include <stdint.h>

#include <algorithm>
#include <memory>
#include <numeric>
#include <set>
#include <utility>
#include <vector>

#include "build/build_config.h"
#include "constants/transparency.h"
#include "core/fpdfapi/font/cpdf_font.h"
#include "core/fpdfapi/font/cpdf_type3char.h"
#include "core/fpdfapi/font/cpdf_type3font.h"
#include "core/fpdfapi/page/cpdf_docpagedata.h"
#include "core/fpdfapi/page/cpdf_form.h"
#include "core/fpdfapi/page/cpdf_formobject.h"
#include "core/fpdfapi/page/cpdf_function.h"
#include "core/fpdfapi/page/cpdf_graphicstates.h"
#include "core/fpdfapi/page/cpdf_image.h"
#include "core/fpdfapi/page/cpdf_imageobject.h"
#include "core/fpdfapi/page/cpdf_occontext.h"
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/page/cpdf_pageimagecache.h"
#include "core/fpdfapi/page/cpdf_pageobject.h"
#include "core/fpdfapi/page/cpdf_pathobject.h"
#include "core/fpdfapi/page/cpdf_shadingobject.h"
#include "core/fpdfapi/page/cpdf_shadingpattern.h"
#include "core/fpdfapi/page/cpdf_textobject.h"
#include "core/fpdfapi/page/cpdf_tilingpattern.h"
#include "core/fpdfapi/page/cpdf_transferfunc.h"
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "core/fpdfapi/render/cpdf_docrenderdata.h"
#include "core/fpdfapi/render/cpdf_imagerenderer.h"
#include "core/fpdfapi/render/cpdf_rendercontext.h"
#include "core/fpdfapi/render/cpdf_renderoptions.h"
#include "core/fpdfapi/render/cpdf_rendershading.h"
#include "core/fpdfapi/render/cpdf_rendertiling.h"
#include "core/fpdfapi/render/cpdf_textrenderer.h"
#include "core/fpdfapi/render/cpdf_type3cache.h"
#include "core/fxcrt/autorestorer.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/compiler_specific.h"
#include "core/fxcrt/containers/contains.h"
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fx_2d_size.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/notreached.h"
#include "core/fxcrt/span.h"
#include "core/fxcrt/stl_util.h"
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxcrt/zip.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_gemodule.h"
#include "core/fxge/cfx_glyphbitmap.h"
#include "core/fxge/cfx_path.h"
#include "core/fxge/cfx_renderdevice.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/fx_font.h"
#include "core/fxge/renderdevicedriver_iface.h"
#include "core/fxge/text_char_pos.h"
#include "core/fxge/text_glyph_pos.h"

#if BUILDFLAG(IS_WIN)
#include "core/fpdfapi/render/cpdf_scaledrenderbuffer.h"
#endif

namespace {

constexpr int kRenderMaxRecursionDepth = 64;
int g_CurrentRecursionDepth = 0;

CFX_FillRenderOptions GetFillOptionsForDrawPathWithBlend(
    const CPDF_RenderOptions::Options& options,
    const CPDF_PathObject* path_obj,
    CFX_FillRenderOptions::FillType fill_type,
    bool is_stroke,
    bool is_type3_char) {
  CFX_FillRenderOptions fill_options(fill_type);
  if (fill_type != CFX_FillRenderOptions::FillType::kNoFill &&
      options.bRectAA) {
    fill_options.rect_aa = true;
  }
  if (options.bNoPathSmooth) {
    fill_options.aliased_path = true;
  }
  if (path_obj->general_state().GetStrokeAdjust()) {
    fill_options.adjust_stroke = true;
  }
  if (is_stroke) {
    fill_options.stroke = true;
  }
  if (is_type3_char) {
    fill_options.text_mode = true;
  }

  return fill_options;
}

CFX_FillRenderOptions GetFillOptionsForDrawTextPath(
    const CPDF_RenderOptions::Options& options,
    const CPDF_TextObject* text_obj,
    bool is_stroke,
    bool is_fill) {
  CFX_FillRenderOptions fill_options;
  if (is_stroke && is_fill) {
    fill_options.stroke = true;
    fill_options.stroke_text_mode = true;
  }
  if (text_obj->general_state().GetStrokeAdjust()) {
    fill_options.adjust_stroke = true;
  }
  if (options.bNoTextSmooth) {
    fill_options.aliased_path = true;
  }

  return fill_options;
}

FXDIB_Format GetFormatForLuminosity(bool is_luminosity) {
  if (!is_luminosity) {
    return FXDIB_Format::k8bppMask;
  }
#if BUILDFLAG(IS_APPLE)
  return FXDIB_Format::kBgrx;
#else  // BUILDFLAG(IS_APPLE)
#if defined(PDF_USE_SKIA)
  if (CFX_GEModule::Get()->UseSkiaRenderer()) {
    return FXDIB_Format::kBgrx;
  }
#endif  // defined(PDF_USE_SKIA)
  return FXDIB_Format::kBgr;
#endif  // BUILDFLAG(IS_APPLE)
}

bool IsAvailableMatrix(const CFX_Matrix& matrix) {
  if (matrix.a == 0 || matrix.d == 0) {
    return matrix.b != 0 && matrix.c != 0;
  }

  if (matrix.b == 0 || matrix.c == 0) {
    return matrix.a != 0 && matrix.d != 0;
  }

  return true;
}

bool MissingFillColor(const CPDF_ColorState* pColorState) {
  return !pColorState->HasRef() || pColorState->GetFillColor()->IsNull();
}

bool MissingStrokeColor(const CPDF_ColorState* pColorState) {
  return !pColorState->HasRef() || pColorState->GetStrokeColor()->IsNull();
}

bool Type3CharMissingFillColor(const CPDF_Type3Char* pChar,
                               const CPDF_ColorState* pColorState) {
  return pChar && (!pChar->colored() || MissingFillColor(pColorState));
}

bool Type3CharMissingStrokeColor(const CPDF_Type3Char* pChar,
                                 const CPDF_ColorState* pColorState) {
  return pChar && (!pChar->colored() || MissingStrokeColor(pColorState));
}

}  // namespace

CPDF_RenderStatus::CPDF_RenderStatus(CPDF_RenderContext* context,
                                     CFX_RenderDevice* pDevice)
    : context_(context), device_(pDevice) {}

CPDF_RenderStatus::~CPDF_RenderStatus() = default;

void CPDF_RenderStatus::Initialize(const CPDF_RenderStatus* pParentStatus,
                                   const CPDF_GraphicStates* pInitialStates) {
#if BUILDFLAG(IS_WIN)
  print_ = device_->GetDeviceType() == DeviceType::kPrinter;
#endif
  page_resource_.Reset(context_->GetPageResources());
  if (pInitialStates && !type3_char_) {
    initial_states_ = *pInitialStates;
    if (pParentStatus) {
      if (!initial_states_.color_state().HasFillColor()) {
        initial_states_.mutable_color_state().SetFillColorRef(
            pParentStatus->initial_states_.color_state().GetFillColorRef());
        *initial_states_.mutable_color_state().GetMutableFillColor() =
            *pParentStatus->initial_states_.color_state().GetFillColor();
      }
      if (!initial_states_.color_state().HasStrokeColor()) {
        initial_states_.mutable_color_state().SetStrokeColorRef(
            pParentStatus->initial_states_.color_state().GetStrokeColorRef());
        *initial_states_.mutable_color_state().GetMutableStrokeColor() =
            *pParentStatus->initial_states_.color_state().GetStrokeColor();
      }
    }
  } else {
    initial_states_.SetDefaultStates();
  }
}

void CPDF_RenderStatus::RenderObjectList(
    const CPDF_PageObjectHolder* pObjectHolder,
    const CFX_Matrix& mtObj2Device) {
  CFX_FloatRect clip_rect = mtObj2Device.GetInverse().TransformRect(
      CFX_FloatRect(device_->GetClipBox()));
  for (const auto& pCurObj : *pObjectHolder) {
    if (pCurObj.get() == stop_obj_) {
      stopped_ = true;
      return;
    }
    if (!pCurObj || !pCurObj->IsActive()) {
      continue;
    }

    if (pCurObj->GetRect().left > clip_rect.right ||
        pCurObj->GetRect().right < clip_rect.left ||
        pCurObj->GetRect().bottom > clip_rect.top ||
        pCurObj->GetRect().top < clip_rect.bottom) {
      continue;
    }
    RenderSingleObject(pCurObj.get(), mtObj2Device);
    if (stopped_) {
      return;
    }
  }
}

void CPDF_RenderStatus::RenderSingleObject(CPDF_PageObject* pObj,
                                           const CFX_Matrix& mtObj2Device) {
  AutoRestorer<int> restorer(&g_CurrentRecursionDepth);
  if (++g_CurrentRecursionDepth > kRenderMaxRecursionDepth) {
    return;
  }
  cur_obj_ = pObj;
  if (!options_.CheckPageObjectVisible(pObj)) {
    return;
  }
  ProcessClipPath(pObj->clip_path(), mtObj2Device);
  if (ProcessTransparency(pObj, mtObj2Device)) {
    return;
  }
  ProcessObjectNoClip(pObj, mtObj2Device);
}

bool CPDF_RenderStatus::ContinueSingleObject(CPDF_PageObject* pObj,
                                             const CFX_Matrix& mtObj2Device,
                                             PauseIndicatorIface* pPause) {
  if (image_renderer_) {
    if (image_renderer_->Continue(pPause)) {
      return true;
    }

    if (!image_renderer_->GetResult()) {
      DrawObjWithBackground(pObj, mtObj2Device);
    }
    image_renderer_.reset();
    return false;
  }

  cur_obj_ = pObj;
  if (!options_.CheckPageObjectVisible(pObj)) {
    return false;
  }

  ProcessClipPath(pObj->clip_path(), mtObj2Device);
  if (ProcessTransparency(pObj, mtObj2Device)) {
    return false;
  }

  if (!pObj->IsImage()) {
    ProcessObjectNoClip(pObj, mtObj2Device);
    return false;
  }

  image_renderer_ = std::make_unique<CPDF_ImageRenderer>(this);
  if (!image_renderer_->Start(pObj->AsImage(), mtObj2Device,
                              /*bStdCS=*/false)) {
    if (!image_renderer_->GetResult()) {
      DrawObjWithBackground(pObj, mtObj2Device);
    }
    image_renderer_.reset();
    return false;
  }
  return ContinueSingleObject(pObj, mtObj2Device, pPause);
}

FX_RECT CPDF_RenderStatus::GetObjectClippedRect(
    const CPDF_PageObject* pObj,
    const CFX_Matrix& mtObj2Device) const {
  FX_RECT rect = pObj->GetTransformedBBox(mtObj2Device);
  rect.Intersect(device_->GetClipBox());
  return rect;
}

void CPDF_RenderStatus::ProcessObjectNoClip(CPDF_PageObject* pObj,
                                            const CFX_Matrix& mtObj2Device) {
  bool bRet = false;
  switch (pObj->GetType()) {
    case CPDF_PageObject::Type::kText:
      bRet = ProcessText(pObj->AsText(), mtObj2Device, nullptr);
      break;
    case CPDF_PageObject::Type::kPath:
      bRet = ProcessPath(pObj->AsPath(), mtObj2Device);
      break;
    case CPDF_PageObject::Type::kImage:
      bRet = ProcessImage(pObj->AsImage(), mtObj2Device);
      break;
    case CPDF_PageObject::Type::kShading:
      ProcessShading(pObj->AsShading(), mtObj2Device);
      return;
    case CPDF_PageObject::Type::kForm:
      bRet = ProcessForm(pObj->AsForm(), mtObj2Device);
      break;
  }
  if (!bRet) {
    DrawObjWithBackground(pObj, mtObj2Device);
  }
}

bool CPDF_RenderStatus::DrawObjWithBlend(CPDF_PageObject* pObj,
                                         const CFX_Matrix& mtObj2Device) {
  switch (pObj->GetType()) {
    case CPDF_PageObject::Type::kPath:
      return ProcessPath(pObj->AsPath(), mtObj2Device);
    case CPDF_PageObject::Type::kImage:
      return ProcessImage(pObj->AsImage(), mtObj2Device);
    case CPDF_PageObject::Type::kForm:
      return ProcessForm(pObj->AsForm(), mtObj2Device);
    case CPDF_PageObject::Type::kText:
    case CPDF_PageObject::Type::kShading:
      return false;
  }
}

void CPDF_RenderStatus::DrawObjWithBackground(CPDF_PageObject* pObj,
                                              const CFX_Matrix& mtObj2Device) {
  FX_RECT rect = GetObjectClippedRect(pObj, mtObj2Device);
  if (rect.IsEmpty()) {
    return;
  }

  const bool needs_buffer = !device_->RenderCapGetBits();
  if (!needs_buffer) {
    DrawObjWithBackgroundToDevice(pObj, mtObj2Device, device_, CFX_Matrix());
    return;
  }

#if BUILDFLAG(IS_WIN)
  CPDF_ScaledRenderBuffer buffer(device_, rect);
  int res = (pObj->IsImage() && IsPrint()) ? 0 : 300;
  if (!buffer.Initialize(context_, pObj, options_, res)) {
    return;
  }

  DrawObjWithBackgroundToDevice(pObj, mtObj2Device, buffer.GetDevice(),
                                buffer.GetMatrix());
  buffer.OutputToDevice();
#else
  NOTREACHED();
#endif
}

void CPDF_RenderStatus::DrawObjWithBackgroundToDevice(
    CPDF_PageObject* obj,
    const CFX_Matrix& object_to_device,
    CFX_RenderDevice* device,
    const CFX_Matrix& device_matrix) {
  RetainPtr<const CPDF_Dictionary> pFormResource;
  const CPDF_FormObject* pFormObj = obj->AsForm();
  if (pFormObj) {
    pFormResource = pFormObj->form()->GetDict()->GetDictFor("Resources");
  }

  CPDF_RenderStatus status(context_, device);
  status.SetOptions(options_);
  status.SetDeviceMatrix(device_matrix);
  status.SetTransparency(transparency_);
  status.SetDropObjects(drop_objects_);
  status.SetFormResource(std::move(pFormResource));
  status.SetInGroup(in_group_);
  status.Initialize(nullptr, nullptr);
  status.RenderSingleObject(obj, object_to_device * device_matrix);
}

bool CPDF_RenderStatus::ProcessForm(const CPDF_FormObject* pFormObj,
                                    const CFX_Matrix& mtObj2Device) {
  RetainPtr<const CPDF_Dictionary> pOC =
      pFormObj->form()->GetDict()->GetDictFor("OC");
  if (pOC && !options_.CheckOCGDictVisible(pOC.Get())) {
    return true;
  }

  CFX_Matrix matrix = pFormObj->form_matrix() * mtObj2Device;
  RetainPtr<const CPDF_Dictionary> pResources =
      pFormObj->form()->GetDict()->GetDictFor("Resources");
  CPDF_RenderStatus status(context_, device_);
  status.SetOptions(options_);
  status.SetStopObject(stop_obj_);
  status.SetTransparency(transparency_);
  status.SetDropObjects(drop_objects_);
  status.SetFormResource(std::move(pResources));
  status.SetInGroup(in_group_);
  status.Initialize(this, &pFormObj->graphic_states());
  {
    CFX_RenderDevice::StateRestorer restorer(device_);
    status.RenderObjectList(pFormObj->form(), matrix);
    stopped_ = status.stopped_;
  }
  return true;
}

bool CPDF_RenderStatus::ProcessPath(CPDF_PathObject* path_obj,
                                    const CFX_Matrix& mtObj2Device) {
  CFX_FillRenderOptions::FillType fill_type = path_obj->filltype();
  bool stroke = path_obj->stroke();
  ProcessPathPattern(path_obj, mtObj2Device, &fill_type, &stroke);
  if (fill_type == CFX_FillRenderOptions::FillType::kNoFill && !stroke) {
    return true;
  }

  // If the option to convert fill paths to stroke is enabled for forced color,
  // set |fill_type| to FillType::kNoFill and |stroke| to true.
  CPDF_RenderOptions::Options& options = options_.GetOptions();
  if (options_.ColorModeIs(CPDF_RenderOptions::Type::kForcedColor) &&
      options.bConvertFillToStroke &&
      fill_type != CFX_FillRenderOptions::FillType::kNoFill) {
    stroke = true;
    fill_type = CFX_FillRenderOptions::FillType::kNoFill;
  }

  uint32_t fill_argb = fill_type != CFX_FillRenderOptions::FillType::kNoFill
                           ? GetFillArgb(path_obj)
                           : 0;
  uint32_t stroke_argb = stroke ? GetStrokeArgb(path_obj) : 0;
  CFX_Matrix path_matrix = path_obj->matrix() * mtObj2Device;
  if (!IsAvailableMatrix(path_matrix)) {
    return true;
  }

  return device_->DrawPath(
      *path_obj->path().GetObject(), &path_matrix,
      path_obj->graph_state().GetObject(), fill_argb, stroke_argb,
      GetFillOptionsForDrawPathWithBlend(options, path_obj, fill_type, stroke,
                                         type3_char_));
}

RetainPtr<CPDF_TransferFunc> CPDF_RenderStatus::GetTransferFunc(
    RetainPtr<const CPDF_Object> pObj) const {
  DCHECK(pObj);
  auto* pDocCache = CPDF_DocRenderData::FromDocument(context_->GetDocument());
  return pDocCache ? pDocCache->GetTransferFunc(std::move(pObj)) : nullptr;
}

FX_ARGB CPDF_RenderStatus::GetFillArgb(CPDF_PageObject* pObj) const {
  if (Type3CharMissingFillColor(type3_char_, &pObj->color_state())) {
    return t3_fill_color_;
  }

  return GetFillArgbForType3(pObj);
}

FX_ARGB CPDF_RenderStatus::GetFillArgbForType3(CPDF_PageObject* pObj) const {
  const CPDF_ColorState* pColorState = &pObj->color_state();
  if (MissingFillColor(pColorState)) {
    pColorState = &initial_states_.color_state();
  }

  FX_COLORREF colorref = pColorState->GetFillColorRef();
  if (colorref == 0xFFFFFFFF) {
    return 0;
  }

  int32_t alpha =
      static_cast<int32_t>((pObj->general_state().GetFillAlpha() * 255));
  RetainPtr<const CPDF_Object> pTR = pObj->general_state().GetTR();
  if (pTR) {
    if (!pObj->general_state().GetTransferFunc()) {
      pObj->mutable_general_state().SetTransferFunc(
          GetTransferFunc(std::move(pTR)));
    }
    if (pObj->general_state().GetTransferFunc()) {
      colorref =
          pObj->general_state().GetTransferFunc()->TranslateColor(colorref);
    }
  }
  return options_.TranslateObjectFillColor(
      AlphaAndColorRefToArgb(alpha, colorref), pObj->GetType());
}

FX_ARGB CPDF_RenderStatus::GetStrokeArgb(CPDF_PageObject* pObj) const {
  const CPDF_ColorState* pColorState = &pObj->color_state();
  if (Type3CharMissingStrokeColor(type3_char_, pColorState)) {
    return t3_fill_color_;
  }

  if (MissingStrokeColor(pColorState)) {
    pColorState = &initial_states_.color_state();
  }

  FX_COLORREF colorref = pColorState->GetStrokeColorRef();
  if (colorref == 0xFFFFFFFF) {
    return 0;
  }

  int32_t alpha = static_cast<int32_t>(pObj->general_state().GetStrokeAlpha() *
                                       255);  // not rounded.
  RetainPtr<const CPDF_Object> pTR = pObj->general_state().GetTR();
  if (pTR) {
    if (!pObj->general_state().GetTransferFunc()) {
      pObj->mutable_general_state().SetTransferFunc(
          GetTransferFunc(std::move(pTR)));
    }
    if (pObj->general_state().GetTransferFunc()) {
      colorref =
          pObj->general_state().GetTransferFunc()->TranslateColor(colorref);
    }
  }
  return options_.TranslateObjectStrokeColor(
      AlphaAndColorRefToArgb(alpha, colorref), pObj->GetType());
}

void CPDF_RenderStatus::ProcessClipPath(const CPDF_ClipPath& ClipPath,
                                        const CFX_Matrix& mtObj2Device) {
  if (!ClipPath.HasRef()) {
    if (last_clip_path_.HasRef()) {
      device_->RestoreState(true);
      last_clip_path_.SetNull();
    }
    return;
  }
  if (last_clip_path_ == ClipPath) {
    return;
  }

  last_clip_path_ = ClipPath;
  device_->RestoreState(true);
  for (size_t i = 0; i < ClipPath.GetPathCount(); ++i) {
    const CFX_Path* pPath = ClipPath.GetPath(i).GetObject();
    if (!pPath) {
      continue;
    }

    if (pPath->GetPoints().empty()) {
      CFX_Path empty_path;
      empty_path.AppendRect(-1, -1, 0, 0);
      device_->SetClip_PathFill(empty_path, nullptr,
                                CFX_FillRenderOptions::WindingOptions());
    } else {
      device_->SetClip_PathFill(*pPath, &mtObj2Device,
                                CFX_FillRenderOptions(ClipPath.GetClipType(i)));
    }
  }

  if (ClipPath.GetTextCount() == 0) {
    return;
  }

  if (!IsPrint() && !device_->RenderCapSoftClip()) {
    return;
  }

  std::unique_ptr<CFX_Path> pTextClippingPath;
  for (size_t i = 0; i < ClipPath.GetTextCount(); ++i) {
    CPDF_TextObject* pText = ClipPath.GetText(i);
    if (pText) {
      if (!pTextClippingPath) {
        pTextClippingPath = std::make_unique<CFX_Path>();
      }
      ProcessText(pText, mtObj2Device, pTextClippingPath.get());
      continue;
    }

    if (!pTextClippingPath) {
      continue;
    }

    CFX_FillRenderOptions fill_options(CFX_FillRenderOptions::WindingOptions());
    if (options_.GetOptions().bNoTextSmooth) {
      fill_options.aliased_path = true;
    }
    device_->SetClip_PathFill(*pTextClippingPath, nullptr, fill_options);
    pTextClippingPath.reset();
  }
}

bool CPDF_RenderStatus::ClipPattern(const CPDF_PageObject* page_obj,
                                    const CFX_Matrix& mtObj2Device,
                                    bool stroke) {
  if (page_obj->IsPath()) {
    return SelectClipPath(page_obj->AsPath(), mtObj2Device, stroke);
  }
  if (page_obj->IsImage()) {
    device_->SetClip_Rect(page_obj->GetTransformedBBox(mtObj2Device));
    return true;
  }
  return false;
}

bool CPDF_RenderStatus::SelectClipPath(const CPDF_PathObject* path_obj,
                                       const CFX_Matrix& mtObj2Device,
                                       bool stroke) {
  CFX_Matrix path_matrix = path_obj->matrix() * mtObj2Device;
  if (stroke) {
    return device_->SetClip_PathStroke(*path_obj->path().GetObject(),
                                       &path_matrix,
                                       path_obj->graph_state().GetObject());
  }
  CFX_FillRenderOptions fill_options(path_obj->filltype());
  if (options_.GetOptions().bNoPathSmooth) {
    fill_options.aliased_path = true;
  }
  return device_->SetClip_PathFill(*path_obj->path().GetObject(), &path_matrix,
                                   fill_options);
}

bool CPDF_RenderStatus::ProcessTransparency(CPDF_PageObject* pPageObj,
                                            const CFX_Matrix& mtObj2Device) {
  const BlendMode blend_type = pPageObj->general_state().GetBlendType();
  RetainPtr<CPDF_Dictionary> pSMaskDict =
      pPageObj->mutable_general_state().GetMutableSoftMask();
  if (pSMaskDict) {
    if (pPageObj->IsImage() &&
        pPageObj->AsImage()->GetImage()->GetDict()->KeyExist("SMask")) {
      pSMaskDict = nullptr;
    }
  }
  RetainPtr<const CPDF_Dictionary> pFormResource;
  float group_alpha = 1.0f;
  float initial_alpha = 1.0f;
  CPDF_Transparency transparency = transparency_;
  bool bGroupTransparent = false;
  const CPDF_FormObject* pFormObj = pPageObj->AsForm();
  if (pFormObj) {
    group_alpha = pFormObj->general_state().GetFillAlpha();
    transparency = pFormObj->form()->GetTransparency();
    bGroupTransparent = transparency.IsIsolated();
    pFormResource = pFormObj->form()->GetDict()->GetDictFor("Resources");
    initial_alpha = initial_states_.general_state().GetFillAlpha();
  }
  bool bTextClip = !IsPrint() && pPageObj->clip_path().HasRef() &&
                   pPageObj->clip_path().GetTextCount() > 0 &&
                   !device_->RenderCapSoftClip();
  if (!pSMaskDict && group_alpha == 1.0f && blend_type == BlendMode::kNormal &&
      !bTextClip && !bGroupTransparent && initial_alpha == 1.0f) {
    return false;
  }
#if BUILDFLAG(IS_WIN)
  if (IsPrint()) {
    DrawObjWithBackground(pPageObj, mtObj2Device);
    return true;
  }
#endif
  FX_RECT rect = pPageObj->GetTransformedBBox(mtObj2Device);
  rect.Intersect(device_->GetClipBox());
  if (rect.IsEmpty()) {
    return true;
  }

  const int width = rect.Width();
  const int height = rect.Height();
  RetainPtr<CFX_DIBitmap> backdrop;
  if (!transparency.IsIsolated() && device_->RenderCapGetBits()) {
    backdrop = pdfium::MakeRetain<CFX_DIBitmap>();
    if (!device_->CreateCompatibleBitmap(backdrop, width, height)) {
      return true;
    }
    device_->GetDIBits(backdrop, rect.left, rect.top);
  }
  std::unique_ptr<CFX_RenderDevice> bitmap_device =
      CFX_RenderDevice::CreateForNewBitmapWithBackdrop(
          width, height, GetCompatibleArgbFormat(), std::move(backdrop));
  if (!bitmap_device) {
    return true;
  }

  CFX_Matrix new_matrix = mtObj2Device;
  new_matrix.Translate(-rect.left, -rect.top);

  RetainPtr<CFX_DIBitmap> text_mask_bitmap;
  if (bTextClip) {
    text_mask_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
    if (!text_mask_bitmap->Create(width, height, FXDIB_Format::k8bppMask)) {
      return true;
    }

    std::unique_ptr<CFX_RenderDevice> text_device =
        CFX_RenderDevice::CreateForBitmap(text_mask_bitmap);
    if (!text_device) {
      return true;
    }
    for (size_t i = 0; i < pPageObj->clip_path().GetTextCount(); ++i) {
      CPDF_TextObject* textobj = pPageObj->clip_path().GetText(i);
      if (!textobj) {
        break;
      }

      // TODO(thestig): Should we check the return value here?
      CPDF_TextRenderer::DrawTextPath(
          text_device.get(), textobj->GetCharCodes(),
          textobj->GetCharPositions(), textobj->text_state().GetFont().Get(),
          textobj->text_state().GetFontSize(), textobj->GetTextMatrix(),
          &new_matrix, textobj->graph_state().GetObject(), 0xffffffff, 0,
          nullptr, CFX_FillRenderOptions());
    }
  }
  CPDF_RenderStatus bitmap_render(context_, bitmap_device.get());
  bitmap_render.SetOptions(options_);
  bitmap_render.SetStopObject(stop_obj_);
  bitmap_render.SetStdCS(true);
  bitmap_render.SetDropObjects(drop_objects_);
  bitmap_render.SetFormResource(std::move(pFormResource));
  bitmap_render.SetInGroup(transparency.IsGroup());
  bitmap_render.Initialize(nullptr, nullptr);
  bitmap_render.ProcessObjectNoClip(pPageObj, new_matrix);
  stopped_ = bitmap_render.stopped_;
  if (pSMaskDict) {
    CFX_Matrix smask_matrix =
        *pPageObj->general_state().GetSMaskMatrix() * mtObj2Device;
    RetainPtr<CFX_DIBitmap> smask_bitmap =
        LoadSMask(pSMaskDict.Get(), rect, smask_matrix);
    if (smask_bitmap) {
      bitmap_device->MultiplyAlphaMask(std::move(smask_bitmap));
    }
  }
  if (text_mask_bitmap) {
    bitmap_device->MultiplyAlphaMask(std::move(text_mask_bitmap));
  }
  if (transparency.IsGroup()) {
    bitmap_device->MultiplyAlpha(group_alpha);
  }
  if (initial_alpha != 1.0f && !in_group_) {
    bitmap_device->MultiplyAlpha(initial_alpha);
  }
  transparency = transparency_;
  if (pPageObj->IsForm()) {
    transparency.SetGroup();
  }
  CompositeDIBitmap(bitmap_device->GetBitmap(), rect.left, rect.top,
                    /*mask_argb=*/0, /*alpha=*/1.0f, blend_type, transparency);
  return true;
}

FX_RECT CPDF_RenderStatus::GetClippedBBox(const FX_RECT& rect) const {
  FX_RECT bbox = rect;
  bbox.Intersect(device_->GetClipBox());
  return bbox;
}

RetainPtr<CFX_DIBitmap> CPDF_RenderStatus::GetBackdrop(
    const CPDF_PageObject* pObj,
    const FX_RECT& bbox,
    bool bBackAlphaRequired) {
  int width = bbox.Width();
  int height = bbox.Height();
  auto backdrop = pdfium::MakeRetain<CFX_DIBitmap>();
  if (bBackAlphaRequired && !drop_objects_) {
    // TODO(crbug.com/42271020): Consider adding support for
    // `FXDIB_Format::kBgraPremul`
    if (!backdrop->Create(width, height, FXDIB_Format::kBgra)) {
      return nullptr;
    }
  } else {
    if (!device_->CreateCompatibleBitmap(backdrop, width, height)) {
      return nullptr;
    }
  }

  bool should_fetch_bits = backdrop->IsAlphaFormat()
                               ? device_->RenderCapAlphaOutput()
                               : device_->RenderCapGetBits();

  if (should_fetch_bits) {
    device_->GetDIBits(backdrop, bbox.left, bbox.top);
    return backdrop;
  }
  CFX_Matrix FinalMatrix = device_matrix_;
  FinalMatrix.Translate(-bbox.left, -bbox.top);
  if (!backdrop->IsAlphaFormat()) {
    backdrop->Clear(0xffffffff);
  }

  std::unique_ptr<CFX_RenderDevice> device =
      CFX_RenderDevice::CreateForBitmap(backdrop);
  if (!device) {
    return nullptr;
  }
  context_->Render(device.get(), pObj, &options_, &FinalMatrix);
  return backdrop;
}

std::unique_ptr<CPDF_GraphicStates> CPDF_RenderStatus::CloneObjStates(
    const CPDF_GraphicStates* pSrcStates,
    bool stroke) {
  if (!pSrcStates) {
    return nullptr;
  }

  auto pStates = std::make_unique<CPDF_GraphicStates>(*pSrcStates);
  const CPDF_Color* pObjColor = stroke
                                    ? pSrcStates->color_state().GetStrokeColor()
                                    : pSrcStates->color_state().GetFillColor();
  if (!pObjColor->IsNull()) {
    pStates->mutable_color_state().SetFillColorRef(
        stroke ? pSrcStates->color_state().GetStrokeColorRef()
               : pSrcStates->color_state().GetFillColorRef());
    pStates->mutable_color_state().SetStrokeColorRef(
        pStates->color_state().GetFillColorRef());
  }
  return pStates;
}

bool CPDF_RenderStatus::ProcessText(CPDF_TextObject* textobj,
                                    const CFX_Matrix& mtObj2Device,
                                    CFX_Path* clipping_path) {
  if (textobj->GetCharCodes().empty()) {
    return true;
  }

  const TextRenderingMode text_render_mode =
      textobj->text_state().GetTextMode();
  if (text_render_mode == TextRenderingMode::MODE_INVISIBLE) {
    return true;
  }

  RetainPtr<CPDF_Font> pFont = textobj->text_state().GetFont();
  if (pFont->IsType3Font()) {
    return ProcessType3Text(textobj, mtObj2Device);
  }

  bool is_fill = false;
  bool is_stroke = false;
  bool is_clip = false;
  if (clipping_path) {
    is_clip = true;
  } else {
    switch (text_render_mode) {
      case TextRenderingMode::MODE_FILL:
      case TextRenderingMode::MODE_FILL_CLIP:
        is_fill = true;
        break;
      case TextRenderingMode::MODE_STROKE:
      case TextRenderingMode::MODE_STROKE_CLIP:
        if (pFont->HasFace()) {
          is_stroke = true;
        } else {
          is_fill = true;
        }
        break;
      case TextRenderingMode::MODE_FILL_STROKE:
      case TextRenderingMode::MODE_FILL_STROKE_CLIP:
        is_fill = true;
        if (pFont->HasFace()) {
          is_stroke = true;
        }
        break;
      case TextRenderingMode::MODE_INVISIBLE:
        // Already handled above, but the compiler is not smart enough to
        // realize it.
        NOTREACHED();
      case TextRenderingMode::MODE_CLIP:
        return true;
      case TextRenderingMode::MODE_UNKNOWN:
        NOTREACHED();
    }
  }
  FX_ARGB stroke_argb = 0;
  FX_ARGB fill_argb = 0;
  bool bPattern = false;
  if (is_stroke) {
    if (textobj->color_state().GetStrokeColor()->IsPattern()) {
      bPattern = true;
    } else {
      stroke_argb = GetStrokeArgb(textobj);
    }
  }
  if (is_fill) {
    if (textobj->color_state().GetFillColor()->IsPattern()) {
      bPattern = true;
    } else {
      fill_argb = GetFillArgb(textobj);
    }
  }
  CFX_Matrix text_matrix = textobj->GetTextMatrix();
  if (!IsAvailableMatrix(text_matrix)) {
    return true;
  }

  float font_size = textobj->text_state().GetFontSize();
  if (bPattern) {
    DrawTextPathWithPattern(textobj, mtObj2Device, pFont.Get(), font_size,
                            text_matrix, is_fill, is_stroke);
    return true;
  }
  if (is_clip || is_stroke) {
    const CFX_Matrix* pDeviceMatrix = &mtObj2Device;
    CFX_Matrix device_matrix;
    if (is_stroke) {
      pdfium::span<const float, 4> pCTM = textobj->text_state().GetCTM();
      if (pCTM[0] != 1.0f || pCTM[3] != 1.0f) {
        CFX_Matrix ctm(pCTM[0], pCTM[1], pCTM[2], pCTM[3], 0, 0);
        text_matrix *= ctm.GetInverse();
        device_matrix = ctm * mtObj2Device;
        pDeviceMatrix = &device_matrix;
      }
    }
    return CPDF_TextRenderer::DrawTextPath(
        device_, textobj->GetCharCodes(), textobj->GetCharPositions(),
        pFont.Get(), font_size, text_matrix, pDeviceMatrix,
        textobj->graph_state().GetObject(), fill_argb, stroke_argb,
        clipping_path,
        GetFillOptionsForDrawTextPath(options_.GetOptions(), textobj, is_stroke,
                                      is_fill));
  }
  text_matrix.Concat(mtObj2Device);
  return CPDF_TextRenderer::DrawNormalText(
      device_, textobj->GetCharCodes(), textobj->GetCharPositions(),
      pFont.Get(), font_size, text_matrix, fill_argb, options_);
}

// TODO(npm): Font fallback for type 3 fonts? (Completely separate code!!)
bool CPDF_RenderStatus::ProcessType3Text(CPDF_TextObject* textobj,
                                         const CFX_Matrix& mtObj2Device) {
  CPDF_Type3Font* pType3Font = textobj->text_state().GetFont()->AsType3Font();
  if (pdfium::Contains(type3_font_cache_, pType3Font)) {
    return true;
  }

  FX_ARGB fill_argb = GetFillArgbForType3(textobj);
  int fill_alpha = FXARGB_A(fill_argb);
#if BUILDFLAG(IS_WIN)
  if (IsPrint() && fill_alpha < 255) {
    return false;
  }
#endif

  CFX_Matrix text_matrix = textobj->GetTextMatrix();
  CFX_Matrix char_matrix = pType3Font->GetFontMatrix();
  float font_size = textobj->text_state().GetFontSize();
  char_matrix.Scale(font_size, font_size);

  // Must come before |glyphs|, because |glyphs| points into |refTypeCache|.
  std::set<RetainPtr<CPDF_Type3Cache>> refTypeCache;
  std::vector<TextGlyphPos> glyphs;
  if (!IsPrint()) {
    glyphs.resize(textobj->GetCharCodes().size());
  }

  for (size_t iChar = 0; iChar < textobj->GetCharCodes().size(); ++iChar) {
    uint32_t charcode = textobj->GetCharCodes()[iChar];
    if (charcode == static_cast<uint32_t>(-1)) {
      continue;
    }

    CPDF_Type3Char* pType3Char = pType3Font->LoadChar(charcode);
    if (!pType3Char) {
      continue;
    }

    CFX_Matrix matrix = char_matrix;
    matrix.e += textobj->GetCharPositions()[iChar];
    matrix.Concat(text_matrix);
    matrix.Concat(mtObj2Device);
    if (!pType3Char->LoadBitmapFromSoleImageOfForm()) {
      if (!glyphs.empty()) {
        for (size_t i = 0; i < iChar; ++i) {
          const TextGlyphPos& glyph = glyphs[i];
          if (!glyph.glyph_) {
            continue;
          }

          std::optional<CFX_Point> point = glyph.GetOrigin({0, 0});
          if (!point.has_value()) {
            continue;
          }

          device_->SetBitMask(glyph.glyph_->GetBitmap(), point->x, point->y,
                              fill_argb);
        }
        glyphs.clear();
      }

      std::unique_ptr<CPDF_GraphicStates> pStates =
          CloneObjStates(&textobj->graphic_states(), false);
      CPDF_RenderOptions options = options_;
      options.GetOptions().bForceHalftone = true;
      options.GetOptions().bRectAA = true;

      const auto* pForm = static_cast<const CPDF_Form*>(pType3Char->form());
      RetainPtr<const CPDF_Dictionary> pFormResource =
          pForm->GetDict()->GetDictFor("Resources");

      if (fill_alpha == 255) {
        CPDF_RenderStatus status(context_, device_);
        status.SetOptions(options);
        status.SetTransparency(pForm->GetTransparency());
        status.SetType3Char(pType3Char);
        status.SetFillColor(fill_argb);
        status.SetDropObjects(drop_objects_);
        status.SetFormResource(std::move(pFormResource));
        status.Initialize(this, pStates.get());
        status.type3_font_cache_ = type3_font_cache_;
        status.type3_font_cache_.emplace_back(pType3Font);

        CFX_RenderDevice::StateRestorer restorer(device_);
        status.RenderObjectList(pForm, matrix);
      } else {
        FX_RECT rect =
            matrix.TransformRect(pForm->CalcBoundingBox()).GetOuterRect();
        if (!rect.Valid()) {
          continue;
        }

        // TODO(crbug.com/42271020): Consider adding support for
        // `FXDIB_Format::kBgraPremul`
        std::unique_ptr<CFX_RenderDevice> bitmap_device =
            CFX_RenderDevice::CreateForNewBitmap(rect.Width(), rect.Height(),
                                                 FXDIB_Format::kBgra);
        if (!bitmap_device) {
          return true;
        }
        CPDF_RenderStatus status(context_, bitmap_device.get());
        status.SetOptions(options);
        status.SetTransparency(pForm->GetTransparency());
        status.SetType3Char(pType3Char);
        status.SetFillColor(fill_argb);
        status.SetDropObjects(drop_objects_);
        status.SetFormResource(std::move(pFormResource));
        status.Initialize(this, pStates.get());
        status.type3_font_cache_ = type3_font_cache_;
        status.type3_font_cache_.emplace_back(pType3Font);
        matrix.Translate(-rect.left, -rect.top);
        status.RenderObjectList(pForm, matrix);
        device_->SetDIBits(bitmap_device->GetBitmap(), rect.left, rect.top);
      }
    } else if (pType3Char->GetBitmap()) {
#if BUILDFLAG(IS_WIN)
      if (IsPrint()) {
        CFX_Matrix image_matrix = pType3Char->matrix() * matrix;
        CPDF_ImageRenderer renderer(this);
        if (renderer.Start(pType3Char->GetBitmap(), fill_argb, image_matrix,
                           FXDIB_ResampleOptions(), false)) {
          renderer.Continue(nullptr);
        }
        if (!renderer.GetResult()) {
          return false;
        }
        continue;
      }
#endif

      CPDF_Document* doc = pType3Font->GetDocument();
      RetainPtr<CPDF_Type3Cache> pCache =
          CPDF_DocRenderData::FromDocument(doc)->GetCachedType3(pType3Font);

      const CFX_GlyphBitmap* pBitmap = pCache->LoadGlyph(charcode, matrix);
      if (!pBitmap) {
        continue;
      }

      refTypeCache.insert(std::move(pCache));

      CFX_Point origin(FXSYS_roundf(matrix.e), FXSYS_roundf(matrix.f));
      if (glyphs.empty()) {
        FX_SAFE_INT32 left = origin.x;
        left += pBitmap->left();
        if (!left.IsValid()) {
          continue;
        }

        FX_SAFE_INT32 top = origin.y;
        top -= pBitmap->top();
        if (!top.IsValid()) {
          continue;
        }

        device_->SetBitMask(pBitmap->GetBitmap(), left.ValueOrDie(),
                            top.ValueOrDie(), fill_argb);
      } else {
        glyphs[iChar].glyph_ = pBitmap;
        glyphs[iChar].origin_ = origin;
      }
    }
  }

  if (glyphs.empty()) {
    return true;
  }

  FX_RECT rect = GetGlyphsBBox(glyphs, /*anti_alias_is_lcd=*/false);
  auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
  if (!bitmap->Create(rect.Width(), rect.Height(), FXDIB_Format::k8bppMask)) {
    return true;
  }

  for (const TextGlyphPos& glyph : glyphs) {
    if (!glyph.glyph_) {
      continue;
    }

    RetainPtr<const CFX_DIBitmap> glyph_bitmap = glyph.glyph_->GetBitmap();
    if (!glyph_bitmap->IsMaskFormat()) {
      continue;
    }

    std::optional<CFX_Point> point = glyph.GetOrigin({rect.left, rect.top});
    if (!point.has_value()) {
      continue;
    }

    bitmap->CompositeMask(
        point->x, point->y, glyph.glyph_->GetBitmap()->GetWidth(),
        glyph.glyph_->GetBitmap()->GetHeight(), glyph.glyph_->GetBitmap(),
        fill_argb, /*src_left=*/0, /*src_top=*/0, BlendMode::kNormal);
  }
  device_->SetBitMask(std::move(bitmap), rect.left, rect.top, fill_argb);
  return true;
}

void CPDF_RenderStatus::DrawTextPathWithPattern(const CPDF_TextObject* textobj,
                                                const CFX_Matrix& mtObj2Device,
                                                CPDF_Font* pFont,
                                                float font_size,
                                                const CFX_Matrix& mtTextMatrix,
                                                bool fill,
                                                bool stroke) {
  if (!stroke) {
    std::vector<std::unique_ptr<CPDF_TextObject>> pCopy;
    pCopy.push_back(textobj->Clone());

    CPDF_PathObject path;
    path.set_filltype(CFX_FillRenderOptions::FillType::kWinding);
    path.mutable_clip_path().CopyClipPath(last_clip_path_);
    path.mutable_clip_path().AppendTexts(&pCopy);
    path.mutable_color_state() = textobj->color_state();
    path.mutable_general_state() = textobj->general_state();
    path.path().AppendFloatRect(textobj->GetRect());
    path.SetRect(textobj->GetRect());

    AutoRestorer<UnownedPtr<const CPDF_PageObject>> restorer2(&cur_obj_);
    RenderSingleObject(&path, mtObj2Device);
    return;
  }

  std::vector<TextCharPos> char_pos_list = pFont->GetCharPosList(
      textobj->GetCharCodes(), textobj->GetCharPositions(), font_size);
  for (const TextCharPos& charpos : char_pos_list) {
    auto* font = charpos.fallback_font_position_ == -1
                     ? pFont->GetFont()
                     : pFont->GetFontFallback(charpos.fallback_font_position_);
    const CFX_Path* pPath =
        font->LoadGlyphPath(charpos.glyph_index_, charpos.font_char_width_);
    if (!pPath) {
      continue;
    }

    CPDF_PathObject path;
    path.mutable_graph_state() = textobj->graph_state();
    path.mutable_color_state() = textobj->color_state();

    CFX_Matrix matrix = charpos.GetEffectiveMatrix(CFX_Matrix(
        font_size, 0, 0, font_size, charpos.origin_.x, charpos.origin_.y));
    matrix.Concat(mtTextMatrix);
    path.set_stroke(stroke);
    path.set_filltype(fill ? CFX_FillRenderOptions::FillType::kWinding
                           : CFX_FillRenderOptions::FillType::kNoFill);
    path.path().Append(*pPath, &matrix);
    path.SetPathMatrix(CFX_Matrix());
    ProcessPath(&path, mtObj2Device);
  }
}

void CPDF_RenderStatus::DrawShadingPattern(CPDF_ShadingPattern* pattern,
                                           const CPDF_PageObject* pPageObj,
                                           const CFX_Matrix& mtObj2Device,
                                           bool stroke) {
  if (!pattern->Load()) {
    return;
  }

  CFX_RenderDevice::StateRestorer restorer(device_);
  if (!ClipPattern(pPageObj, mtObj2Device, stroke)) {
    return;
  }

  FX_RECT rect = GetObjectClippedRect(pPageObj, mtObj2Device);
  if (rect.IsEmpty()) {
    return;
  }

  CFX_Matrix matrix = pattern->pattern_to_form() * mtObj2Device;
  int alpha =
      FXSYS_roundf(255 * (stroke ? pPageObj->general_state().GetStrokeAlpha()
                                 : pPageObj->general_state().GetFillAlpha()));
  CPDF_RenderShading::Draw(device_, context_, cur_obj_, pattern, matrix, rect,
                           alpha, options_);
}

void CPDF_RenderStatus::ProcessShading(const CPDF_ShadingObject* pShadingObj,
                                       const CFX_Matrix& mtObj2Device) {
  FX_RECT rect = GetObjectClippedRect(pShadingObj, mtObj2Device);
  if (rect.IsEmpty()) {
    return;
  }

  CFX_Matrix matrix = pShadingObj->matrix() * mtObj2Device;
  CPDF_RenderShading::Draw(
      device_, context_, cur_obj_, pShadingObj->pattern(), matrix, rect,
      FXSYS_roundf(255 * pShadingObj->general_state().GetFillAlpha()),
      options_);
}

void CPDF_RenderStatus::DrawTilingPattern(CPDF_TilingPattern* pattern,
                                          CPDF_PageObject* pPageObj,
                                          const CFX_Matrix& mtObj2Device,
                                          bool stroke) {
  const std::unique_ptr<CPDF_Form> pPatternForm = pattern->Load(pPageObj);
  if (!pPatternForm) {
    return;
  }

  CFX_RenderDevice::StateRestorer restorer(device_);
  if (!ClipPattern(pPageObj, mtObj2Device, stroke)) {
    return;
  }

  FX_RECT clip_box = device_->GetClipBox();
  if (clip_box.IsEmpty()) {
    return;
  }

  RetainPtr<CFX_DIBitmap> screen =
      CPDF_RenderTiling::Draw(this, pPageObj, pattern, pPatternForm.get(),
                              mtObj2Device, clip_box, stroke);
  if (!screen) {
    return;
  }

  static constexpr FX_ARGB kMask = 0;
  CompositeDIBitmap(std::move(screen), clip_box.left, clip_box.top, kMask,
                    /*alpha=*/1.0f, BlendMode::kNormal, CPDF_Transparency());
}

void CPDF_RenderStatus::DrawPathWithPattern(CPDF_PathObject* path_obj,
                                            const CFX_Matrix& mtObj2Device,
                                            const CPDF_Color* pColor,
                                            bool stroke) {
  RetainPtr<CPDF_Pattern> pattern = pColor->GetPattern();
  if (!pattern) {
    return;
  }

  if (CPDF_TilingPattern* pTilingPattern = pattern->AsTilingPattern()) {
    DrawTilingPattern(pTilingPattern, path_obj, mtObj2Device, stroke);
  } else if (CPDF_ShadingPattern* pShadingPattern =
                 pattern->AsShadingPattern()) {
    DrawShadingPattern(pShadingPattern, path_obj, mtObj2Device, stroke);
  }
}

void CPDF_RenderStatus::ProcessPathPattern(
    CPDF_PathObject* path_obj,
    const CFX_Matrix& mtObj2Device,
    CFX_FillRenderOptions::FillType* fill_type,
    bool* stroke) {
  DCHECK(fill_type);
  DCHECK(stroke);

  if (*fill_type != CFX_FillRenderOptions::FillType::kNoFill) {
    const CPDF_Color& FillColor = *path_obj->color_state().GetFillColor();
    if (FillColor.IsPattern()) {
      DrawPathWithPattern(path_obj, mtObj2Device, &FillColor, false);
      *fill_type = CFX_FillRenderOptions::FillType::kNoFill;
    }
  }
  if (*stroke) {
    const CPDF_Color& StrokeColor = *path_obj->color_state().GetStrokeColor();
    if (StrokeColor.IsPattern()) {
      DrawPathWithPattern(path_obj, mtObj2Device, &StrokeColor, true);
      *stroke = false;
    }
  }
}

bool CPDF_RenderStatus::ProcessImage(CPDF_ImageObject* pImageObj,
                                     const CFX_Matrix& mtObj2Device) {
  CPDF_ImageRenderer render(this);
  if (render.Start(pImageObj, mtObj2Device, std_cs_)) {
    render.Continue(nullptr);
  }
  return render.GetResult();
}

void CPDF_RenderStatus::CompositeDIBitmap(
    RetainPtr<CFX_DIBitmap> bitmap,
    int left,
    int top,
    FX_ARGB mask_argb,
    float alpha,
    BlendMode blend_mode,
    const CPDF_Transparency& transparency) {
  CHECK(bitmap);

  if (blend_mode == BlendMode::kNormal) {
    if (bitmap->IsMaskFormat()) {
#if BUILDFLAG(IS_WIN)
      FX_ARGB fill_argb = options_.TranslateColor(mask_argb);
      if (alpha != 1.0f) {
        auto& bgra = reinterpret_cast<FX_BGRA_STRUCT<uint8_t>&>(fill_argb);
        bgra.alpha *= FXSYS_roundf(alpha * 255) / 255;
      }
      if (device_->SetBitMask(bitmap, left, top, fill_argb)) {
        return;
      }
#else
      NOTREACHED();
#endif
    } else {
      if (alpha != 1.0f) {
#if defined(PDF_USE_SKIA)
        if (CFX_GEModule::Get()->UseSkiaRenderer()) {
          CFX_Matrix matrix = CFX_RenderDevice::GetFlipMatrix(
              bitmap->GetWidth(), bitmap->GetHeight(), left, top);
          device_->StartDIBits(std::move(bitmap), alpha, /*argb=*/0, matrix,
                               FXDIB_ResampleOptions());
          return;
        }
#endif
        bitmap->MultiplyAlpha(alpha);
      }
      if (device_->SetDIBits(bitmap, left, top)) {
        return;
      }
    }
  }
  bool bIsolated = transparency.IsIsolated();
  bool bBackAlphaRequired =
      blend_mode != BlendMode::kNormal && bIsolated && !drop_objects_;
  bool bGetBackGround = device_->RenderCapAlphaOutput() ||
                        (!device_->RenderCapAlphaOutput() &&
                         device_->RenderCapGetBits() && !bBackAlphaRequired);
  if (bGetBackGround) {
    if (bIsolated || !transparency.IsGroup()) {
      if (!bitmap->IsMaskFormat()) {
        device_->SetDIBitsWithBlend(std::move(bitmap), left, top, blend_mode);
      }
      return;
    }

    FX_RECT rect(left, top, left + bitmap->GetWidth(),
                 top + bitmap->GetHeight());
    rect.Intersect(device_->GetClipBox());
    RetainPtr<CFX_DIBitmap> pClone;
    if (device_->GetBackDrop() && device_->GetBitmap()) {
      pClone = device_->GetBackDrop()->ClipTo(rect);
      if (!pClone) {
        return;
      }

      pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
                              device_->GetBitmap(), rect.left, rect.top,
                              BlendMode::kNormal);
      left = std::min(left, 0);
      top = std::min(top, 0);
      if (bitmap->IsMaskFormat()) {
#if BUILDFLAG(IS_WIN)
        pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(),
                              bitmap, mask_argb, left, top, blend_mode);
#else
        NOTREACHED();
#endif
      } else {
        pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
                                bitmap, left, top, blend_mode);
      }
    } else {
      pClone = bitmap;
    }
    if (device_->GetBackDrop()) {
      device_->SetDIBits(pClone, rect.left, rect.top);
    } else {
      if (!bitmap->IsMaskFormat()) {
        device_->SetDIBitsWithBlend(std::move(bitmap), rect.left, rect.top,
                                    blend_mode);
      }
    }
    return;
  }

  FX_RECT bbox = GetClippedBBox(
      FX_RECT(left, top, left + bitmap->GetWidth(), top + bitmap->GetHeight()));
  RetainPtr<CFX_DIBitmap> backdrop = GetBackdrop(
      cur_obj_, bbox, blend_mode != BlendMode::kNormal && bIsolated);
  if (!backdrop) {
    return;
  }

  const int width = bitmap->GetWidth();
  const int height = bitmap->GetHeight();
  if (bitmap->IsMaskFormat()) {
#if BUILDFLAG(IS_WIN)
    backdrop->CompositeMask(left - bbox.left, top - bbox.top, width, height,
                            std::move(bitmap), mask_argb, 0, 0, blend_mode);
#else
    NOTREACHED();
#endif
  } else {
    backdrop->CompositeBitmap(left - bbox.left, top - bbox.top, width, height,
                              std::move(bitmap), 0, 0, blend_mode);
  }

  auto new_backdrop = pdfium::MakeRetain<CFX_DIBitmap>();
  CHECK(new_backdrop->Create(backdrop->GetWidth(), backdrop->GetHeight(),
                             FXDIB_Format::kBgrx));
  new_backdrop->Clear(0xffffffff);
  new_backdrop->CompositeBitmap(0, 0, new_backdrop->GetWidth(),
                                new_backdrop->GetHeight(), std::move(backdrop),
                                0, 0, BlendMode::kNormal);
  device_->SetDIBits(std::move(new_backdrop), bbox.left, bbox.top);
}

RetainPtr<CFX_DIBitmap> CPDF_RenderStatus::LoadSMask(
    CPDF_Dictionary* smask_dict,
    const FX_RECT& clip_rect,
    const CFX_Matrix& smask_matrix) {
  RetainPtr<CPDF_Stream> pGroup =
      smask_dict->GetMutableStreamFor(pdfium::transparency::kG);
  if (!pGroup) {
    return nullptr;
  }

  std::unique_ptr<CPDF_Function> pFunc;
  RetainPtr<const CPDF_Object> pFuncObj =
      smask_dict->GetDirectObjectFor(pdfium::transparency::kTR);
  if (pFuncObj && (pFuncObj->IsDictionary() || pFuncObj->IsStream())) {
    pFunc = CPDF_Function::Load(std::move(pFuncObj));
  }

  CFX_Matrix matrix = smask_matrix;
  matrix.Translate(-clip_rect.left, -clip_rect.top);

  CPDF_Form form(context_->GetDocument(), context_->GetMutablePageResources(),
                 pGroup);
  form.ParseContent();

  bool bLuminosity =
      smask_dict->GetByteStringFor(pdfium::transparency::kSoftMaskSubType) !=
      pdfium::transparency::kAlpha;
  const int width = clip_rect.Width();
  const int height = clip_rect.Height();
  const FXDIB_Format format = GetFormatForLuminosity(bLuminosity);
  std::unique_ptr<CFX_RenderDevice> bitmap_device =
      CFX_RenderDevice::CreateForNewBitmap(width, height, format);
  if (!bitmap_device) {
    return nullptr;
  }

  CPDF_ColorSpace::Family nCSFamily = CPDF_ColorSpace::Family::kUnknown;
  const FX_ARGB background_color =
      bLuminosity
          ? GetBackgroundColor(smask_dict, pGroup->GetDict().Get(), &nCSFamily)
          : 0;
  bitmap_device->Clear(background_color);

  RetainPtr<const CPDF_Dictionary> pFormResource =
      form.GetDict()->GetDictFor("Resources");
  CPDF_RenderOptions options;
  options.SetColorMode(bLuminosity ? CPDF_RenderOptions::kNormal
                                   : CPDF_RenderOptions::kAlpha);
  CPDF_RenderStatus status(context_, bitmap_device.get());
  status.SetOptions(options);
  status.SetGroupFamily(nCSFamily);
  status.SetLoadMask(bLuminosity);
  status.SetStdCS(true);
  status.SetFormResource(std::move(pFormResource));
  status.SetDropObjects(drop_objects_);
  status.Initialize(nullptr, nullptr);
  status.RenderObjectList(&form, matrix);

  auto result_mask = pdfium::MakeRetain<CFX_DIBitmap>();
  if (!result_mask->Create(width, height, FXDIB_Format::k8bppMask)) {
    return nullptr;
  }

  pdfium::span<uint8_t> dest_buf = result_mask->GetWritableBuffer();
  RetainPtr<const CFX_DIBitmap> bitmap = bitmap_device->GetBitmap();
  pdfium::span<const uint8_t> src_buf = bitmap->GetBuffer();
  const int dest_pitch = result_mask->GetPitch();
  const int src_pitch = bitmap->GetPitch();
  DataVector<uint8_t> transfers(256);
  if (pFunc) {
    std::vector<float> results(pFunc->OutputCount());
    for (size_t i = 0; i < transfers.size(); ++i) {
      float input = i / 255.0f;
      pFunc->Call(pdfium::span_from_ref(input), results);
      transfers[i] = FXSYS_roundf(results[0] * 255);
    }
  } else {
    // Fill |transfers| with 0, 1, ... N.
    std::iota(transfers.begin(), transfers.end(), 0);
  }

  if (bLuminosity) {
    const int bytes_per_pixel = bitmap->GetBPP() / 8;
    for (int row = 0; row < height; row++) {
      const size_t dest_offset = Fx2DSizeOrDie(row, dest_pitch);
      const size_t src_offset = Fx2DSizeOrDie(row, src_pitch);
      uint8_t* dest_pos = dest_buf.subspan(dest_offset).data();
      const uint8_t* src_pos = src_buf.subspan(src_offset).data();
      for (int col = 0; col < width; col++) {
        UNSAFE_TODO({
          *dest_pos++ = transfers[FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos)];
          src_pos += bytes_per_pixel;
        });
      }
    }
    return result_mask;
  }

  src_buf = src_buf.first(Fx2DSizeOrDie(dest_pitch, height));
  if (pFunc) {
    for (auto [in, out] : fxcrt::Zip(src_buf, dest_buf)) {
      out = transfers[in];
    }
    return result_mask;
  }

  fxcrt::Copy(src_buf, dest_buf);
  return result_mask;
}

FX_ARGB CPDF_RenderStatus::GetBackgroundColor(
    const CPDF_Dictionary* pSMaskDict,
    const CPDF_Dictionary* group_dict,
    CPDF_ColorSpace::Family* pCSFamily) {
  static constexpr FX_ARGB kDefaultColor = ArgbEncode(255, 0, 0, 0);
  RetainPtr<const CPDF_Array> pBC =
      pSMaskDict->GetArrayFor(pdfium::transparency::kBC);
  if (!pBC) {
    return kDefaultColor;
  }

  RetainPtr<const CPDF_Object> pCSObj;
  RetainPtr<const CPDF_Dictionary> pGroup =
      group_dict ? group_dict->GetDictFor("Group") : nullptr;
  if (pGroup) {
    pCSObj = pGroup->GetDirectObjectFor(pdfium::transparency::kCS);
  }
  RetainPtr<CPDF_ColorSpace> pCS =
      CPDF_DocPageData::FromDocument(context_->GetDocument())
          ->GetColorSpace(pCSObj.Get(), nullptr);
  if (!pCS) {
    return kDefaultColor;
  }

  CPDF_ColorSpace::Family family = pCS->GetFamily();
  if (family == CPDF_ColorSpace::Family::kLab || pCS->IsSpecial() ||
      (family == CPDF_ColorSpace::Family::kICCBased && !pCS->IsNormal())) {
    return kDefaultColor;
  }

  // Store Color Space Family to use in CPDF_RenderStatus::Initialize().
  *pCSFamily = family;

  uint32_t comps = std::max(8u, pCS->ComponentCount());
  size_t count = std::min<size_t>(8, pBC->size());
  std::vector<float> floats = ReadArrayElementsToVector(pBC.Get(), count);
  floats.resize(comps);

  auto rgb = pCS->GetRGBOrZerosOnError(floats);
  return ArgbEncode(255, static_cast<int>(rgb.red * 255),
                    static_cast<int>(rgb.green * 255),
                    static_cast<int>(rgb.blue * 255));
}

FXDIB_Format CPDF_RenderStatus::GetCompatibleArgbFormat() const {
#if defined(PDF_USE_SKIA)
  if (device_->CanUseARGBPremul()) {
    return FXDIB_Format::kBgraPremul;
  }
#endif
  return FXDIB_Format::kBgra;
}
