// 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 "../../../include/fpdfapi/fpdf_module.h"
#include "../../../include/fpdfapi/fpdf_render.h"
#include "../../../include/fxge/fx_ge.h"
#include "../fpdf_page/pageint.h"
#include "render_int.h"

CPDF_DocRenderData::CPDF_DocRenderData(CPDF_Document* pPDFDoc)
    : m_pPDFDoc(pPDFDoc), m_pFontCache(new CFX_FontCache) {}

CPDF_DocRenderData::~CPDF_DocRenderData() {
  Clear(TRUE);
}

void CPDF_DocRenderData::Clear(FX_BOOL bRelease) {
  for (auto it = m_Type3FaceMap.begin(); it != m_Type3FaceMap.end();) {
    auto curr_it = it++;
    CPDF_CountedObject<CPDF_Type3Cache>* cache = curr_it->second;
    if (bRelease || cache->use_count() < 2) {
      delete cache->get();
      delete cache;
      m_Type3FaceMap.erase(curr_it);
    }
  }

  for (auto it = m_TransferFuncMap.begin(); it != m_TransferFuncMap.end();) {
    auto curr_it = it++;
    CPDF_CountedObject<CPDF_TransferFunc>* value = curr_it->second;
    if (bRelease || value->use_count() < 2) {
      delete value->get();
      delete value;
      m_TransferFuncMap.erase(curr_it);
    }
  }

  if (m_pFontCache) {
    if (bRelease) {
      delete m_pFontCache;
      m_pFontCache = NULL;
    } else {
      m_pFontCache->FreeCache(FALSE);
    }
  }
}

CPDF_Type3Cache* CPDF_DocRenderData::GetCachedType3(CPDF_Type3Font* pFont) {
  CPDF_CountedObject<CPDF_Type3Cache>* pCache;
  auto it = m_Type3FaceMap.find(pFont);
  if (it == m_Type3FaceMap.end()) {
    CPDF_Type3Cache* pType3 = new CPDF_Type3Cache(pFont);
    pCache = new CPDF_CountedObject<CPDF_Type3Cache>(pType3);
    m_Type3FaceMap[pFont] = pCache;
  } else {
    pCache = it->second;
  }
  return pCache->AddRef();
}

void CPDF_DocRenderData::ReleaseCachedType3(CPDF_Type3Font* pFont) {
  auto it = m_Type3FaceMap.find(pFont);
  if (it != m_Type3FaceMap.end())
    it->second->RemoveRef();
}

class CPDF_RenderModule : public IPDF_RenderModule {
 public:
  CPDF_RenderModule() {}

 private:
  ~CPDF_RenderModule() override {}

  CPDF_DocRenderData* CreateDocData(CPDF_Document* pDoc) override;
  void DestroyDocData(CPDF_DocRenderData* p) override;
  void ClearDocData(CPDF_DocRenderData* p) override;

  CPDF_DocRenderData* GetRenderData() override { return &m_RenderData; }

  CPDF_PageRenderCache* CreatePageCache(CPDF_Page* pPage) override {
    return new CPDF_PageRenderCache(pPage);
  }

  void DestroyPageCache(CPDF_PageRenderCache* pCache) override;

  CPDF_RenderConfig* GetConfig() override { return &m_RenderConfig; }

  CPDF_DocRenderData m_RenderData;
  CPDF_RenderConfig m_RenderConfig;
};

CPDF_DocRenderData* CPDF_RenderModule::CreateDocData(CPDF_Document* pDoc) {
  return new CPDF_DocRenderData(pDoc);
}
void CPDF_RenderModule::DestroyDocData(CPDF_DocRenderData* pDocData) {
  delete pDocData;
}
void CPDF_RenderModule::ClearDocData(CPDF_DocRenderData* p) {
  if (p) {
    p->Clear(FALSE);
  }
}
void CPDF_RenderModule::DestroyPageCache(CPDF_PageRenderCache* pCache) {
  delete pCache;
}

void CPDF_ModuleMgr::InitRenderModule() {
  m_pRenderModule.reset(new CPDF_RenderModule);
}

CPDF_RenderOptions::CPDF_RenderOptions()
    : m_ColorMode(RENDER_COLOR_NORMAL),
      m_Flags(RENDER_CLEARTYPE),
      m_Interpolation(0),
      m_AddFlags(0),
      m_pOCContext(NULL),
      m_dwLimitCacheSize(1024 * 1024 * 100),
      m_HalftoneLimit(-1) {}
FX_ARGB CPDF_RenderOptions::TranslateColor(FX_ARGB argb) const {
  if (m_ColorMode == RENDER_COLOR_NORMAL) {
    return argb;
  }
  if (m_ColorMode == RENDER_COLOR_ALPHA) {
    return argb;
  }
  int a, r, g, b;
  ArgbDecode(argb, a, r, g, b);
  int gray = FXRGB2GRAY(r, g, b);
  if (m_ColorMode == RENDER_COLOR_TWOCOLOR) {
    int color = (r - gray) * (r - gray) + (g - gray) * (g - gray) +
                (b - gray) * (b - gray);
    if (gray < 35 && color < 20) {
      return ArgbEncode(a, m_ForeColor);
    }
    if (gray > 221 && color < 20) {
      return ArgbEncode(a, m_BackColor);
    }
    return argb;
  }
  int fr = FXSYS_GetRValue(m_ForeColor);
  int fg = FXSYS_GetGValue(m_ForeColor);
  int fb = FXSYS_GetBValue(m_ForeColor);
  int br = FXSYS_GetRValue(m_BackColor);
  int bg = FXSYS_GetGValue(m_BackColor);
  int bb = FXSYS_GetBValue(m_BackColor);
  r = (br - fr) * gray / 255 + fr;
  g = (bg - fg) * gray / 255 + fg;
  b = (bb - fb) * gray / 255 + fb;
  return ArgbEncode(a, r, g, b);
}

// static
int CPDF_RenderStatus::s_CurrentRecursionDepth = 0;

CPDF_RenderStatus::CPDF_RenderStatus() {
  m_pContext = NULL;
  m_bStopped = FALSE;
  m_pDevice = NULL;
  m_pCurObj = NULL;
  m_pStopObj = NULL;
  m_HalftoneLimit = 0;
  m_pObjectRenderer = NULL;
  m_bPrint = FALSE;
  m_Transparency = 0;
  m_DitherBits = 0;
  m_bDropObjects = FALSE;
  m_bStdCS = FALSE;
  m_GroupFamily = 0;
  m_bLoadMask = FALSE;
  m_pType3Char = NULL;
  m_T3FillColor = 0;
  m_pFormResource = NULL;
  m_pPageResource = NULL;
  m_curBlend = FXDIB_BLEND_NORMAL;
}

CPDF_RenderStatus::~CPDF_RenderStatus() {
  delete m_pObjectRenderer;
}

FX_BOOL CPDF_RenderStatus::Initialize(CPDF_RenderContext* pContext,
                                      CFX_RenderDevice* pDevice,
                                      const CFX_AffineMatrix* pDeviceMatrix,
                                      const CPDF_PageObject* pStopObj,
                                      const CPDF_RenderStatus* pParentState,
                                      const CPDF_GraphicStates* pInitialStates,
                                      const CPDF_RenderOptions* pOptions,
                                      int transparency,
                                      FX_BOOL bDropObjects,
                                      CPDF_Dictionary* pFormResource,
                                      FX_BOOL bStdCS,
                                      CPDF_Type3Char* pType3Char,
                                      FX_ARGB fill_color,
                                      FX_DWORD GroupFamily,
                                      FX_BOOL bLoadMask) {
  m_pContext = pContext;
  m_pDevice = pDevice;
  m_DitherBits = pDevice->GetDeviceCaps(FXDC_DITHER_BITS);
  m_bPrint = m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
  if (pDeviceMatrix) {
    m_DeviceMatrix = *pDeviceMatrix;
  }
  m_pStopObj = pStopObj;
  if (pOptions) {
    m_Options = *pOptions;
  }
  m_bDropObjects = bDropObjects;
  m_bStdCS = bStdCS;
  m_T3FillColor = fill_color;
  m_pType3Char = pType3Char;
  m_GroupFamily = GroupFamily;
  m_bLoadMask = bLoadMask;
  m_pFormResource = pFormResource;
  m_pPageResource = m_pContext->m_pPageResources;
  if (pInitialStates && !m_pType3Char) {
    m_InitialStates.CopyStates(*pInitialStates);
    if (pParentState) {
      CPDF_ColorStateData* pColorData =
          (CPDF_ColorStateData*)(const CPDF_ColorStateData*)
              m_InitialStates.m_ColorState;
      CPDF_ColorStateData* pParentData =
          (CPDF_ColorStateData*)(const CPDF_ColorStateData*)
              pParentState->m_InitialStates.m_ColorState;
      if (!pColorData || pColorData->m_FillColor.IsNull()) {
        CPDF_ColorStateData* pData = m_InitialStates.m_ColorState.GetModify();
        pData->m_FillRGB = pParentData->m_FillRGB;
        pData->m_FillColor.Copy(&pParentData->m_FillColor);
      }
      if (!pColorData || pColorData->m_StrokeColor.IsNull()) {
        CPDF_ColorStateData* pData = m_InitialStates.m_ColorState.GetModify();
        pData->m_StrokeRGB = pParentData->m_FillRGB;
        pData->m_StrokeColor.Copy(&pParentData->m_StrokeColor);
      }
    }
  } else {
    m_InitialStates.DefaultStates();
  }
  m_pObjectRenderer = NULL;
  m_Transparency = transparency;
  return TRUE;
}
void CPDF_RenderStatus::RenderObjectList(const CPDF_PageObjects* pObjs,
                                         const CFX_AffineMatrix* pObj2Device) {
  CFX_FloatRect clip_rect = m_pDevice->GetClipBox();
  CFX_AffineMatrix device2object;
  device2object.SetReverse(*pObj2Device);
  device2object.TransformRect(clip_rect);
  int index = 0;
  FX_POSITION pos = pObjs->GetFirstObjectPosition();
  while (pos) {
    index++;
    CPDF_PageObject* pCurObj = pObjs->GetNextObject(pos);
    if (pCurObj == m_pStopObj) {
      m_bStopped = TRUE;
      return;
    }
    if (!pCurObj) {
      continue;
    }
    if (pCurObj == NULL || pCurObj->m_Left > clip_rect.right ||
        pCurObj->m_Right < clip_rect.left ||
        pCurObj->m_Bottom > clip_rect.top ||
        pCurObj->m_Top < clip_rect.bottom) {
      continue;
    }
    RenderSingleObject(pCurObj, pObj2Device);
    if (m_bStopped) {
      return;
    }
  }
}
void CPDF_RenderStatus::RenderSingleObject(
    const CPDF_PageObject* pObj,
    const CFX_AffineMatrix* pObj2Device) {
  CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth);
  if (++s_CurrentRecursionDepth > kRenderMaxRecursionDepth) {
    return;
  }
  m_pCurObj = pObj;
  if (m_Options.m_pOCContext && pObj->m_ContentMark.NotNull()) {
    if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) {
      return;
    }
  }
  ProcessClipPath(pObj->m_ClipPath, pObj2Device);
  if (ProcessTransparency(pObj, pObj2Device)) {
    return;
  }
  ProcessObjectNoClip(pObj, pObj2Device);
}
FX_BOOL CPDF_RenderStatus::ContinueSingleObject(
    const CPDF_PageObject* pObj,
    const CFX_AffineMatrix* pObj2Device,
    IFX_Pause* pPause) {
  if (m_pObjectRenderer) {
    if (m_pObjectRenderer->Continue(pPause)) {
      return TRUE;
    }
    if (!m_pObjectRenderer->m_Result) {
      DrawObjWithBackground(pObj, pObj2Device);
    }
    delete m_pObjectRenderer;
    m_pObjectRenderer = NULL;
    return FALSE;
  }
  m_pCurObj = pObj;
  if (m_Options.m_pOCContext && pObj->m_ContentMark.NotNull())
    if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) {
      return FALSE;
    }
  ProcessClipPath(pObj->m_ClipPath, pObj2Device);
  if (ProcessTransparency(pObj, pObj2Device)) {
    return FALSE;
  }
  if (pObj->m_Type == PDFPAGE_IMAGE) {
    m_pObjectRenderer = IPDF_ObjectRenderer::Create(pObj->m_Type);
    if (!m_pObjectRenderer->Start(this, pObj, pObj2Device, FALSE)) {
      if (!m_pObjectRenderer->m_Result) {
        DrawObjWithBackground(pObj, pObj2Device);
      }
      delete m_pObjectRenderer;
      m_pObjectRenderer = NULL;
      return FALSE;
    }
    return ContinueSingleObject(pObj, pObj2Device, pPause);
  }
  ProcessObjectNoClip(pObj, pObj2Device);
  return FALSE;
}
IPDF_ObjectRenderer* IPDF_ObjectRenderer::Create(int type) {
  if (type != PDFPAGE_IMAGE) {
    return NULL;
  }
  return new CPDF_ImageRenderer;
}
FX_BOOL CPDF_RenderStatus::GetObjectClippedRect(
    const CPDF_PageObject* pObj,
    const CFX_AffineMatrix* pObj2Device,
    FX_BOOL bLogical,
    FX_RECT& rect) const {
  rect = pObj->GetBBox(pObj2Device);
  FX_RECT rtClip = m_pDevice->GetClipBox();
  if (!bLogical) {
    CFX_Matrix dCTM = m_pDevice->GetCTM();
    FX_FLOAT a = FXSYS_fabs(dCTM.a);
    FX_FLOAT d = FXSYS_fabs(dCTM.d);
    if (a != 1.0f || d != 1.0f) {
      rect.right = rect.left + (int32_t)FXSYS_ceil((FX_FLOAT)rect.Width() * a);
      rect.bottom = rect.top + (int32_t)FXSYS_ceil((FX_FLOAT)rect.Height() * d);
      rtClip.right =
          rtClip.left + (int32_t)FXSYS_ceil((FX_FLOAT)rtClip.Width() * a);
      rtClip.bottom =
          rtClip.top + (int32_t)FXSYS_ceil((FX_FLOAT)rtClip.Height() * d);
    }
  }
  rect.Intersect(rtClip);
  return rect.IsEmpty();
}
void CPDF_RenderStatus::DitherObjectArea(const CPDF_PageObject* pObj,
                                         const CFX_AffineMatrix* pObj2Device) {
  CFX_DIBitmap* pBitmap = m_pDevice->GetBitmap();
  if (pBitmap == NULL) {
    return;
  }
  FX_RECT rect;
  if (GetObjectClippedRect(pObj, pObj2Device, FALSE, rect)) {
    return;
  }
  if (m_DitherBits == 2) {
    static FX_ARGB pal[4] = {0, 85, 170, 255};
    pBitmap->DitherFS(pal, 4, &rect);
  } else if (m_DitherBits == 3) {
    static FX_ARGB pal[8] = {0, 36, 73, 109, 146, 182, 219, 255};
    pBitmap->DitherFS(pal, 8, &rect);
  } else if (m_DitherBits == 4) {
    static FX_ARGB pal[16] = {0,   17,  34,  51,  68,  85,  102, 119,
                              136, 153, 170, 187, 204, 221, 238, 255};
    pBitmap->DitherFS(pal, 16, &rect);
  }
}
void CPDF_RenderStatus::ProcessObjectNoClip(
    const CPDF_PageObject* pObj,
    const CFX_AffineMatrix* pObj2Device) {
  FX_BOOL bRet = FALSE;
  switch (pObj->m_Type) {
    case PDFPAGE_TEXT:
      bRet = ProcessText((CPDF_TextObject*)pObj, pObj2Device, NULL);
      break;
    case PDFPAGE_PATH:
      bRet = ProcessPath((CPDF_PathObject*)pObj, pObj2Device);
      break;
    case PDFPAGE_IMAGE:
      bRet = ProcessImage((CPDF_ImageObject*)pObj, pObj2Device);
      break;
    case PDFPAGE_SHADING:
      bRet = ProcessShading((CPDF_ShadingObject*)pObj, pObj2Device);
      break;
    case PDFPAGE_FORM:
      bRet = ProcessForm((CPDF_FormObject*)pObj, pObj2Device);
      break;
  }
  if (!bRet) {
    DrawObjWithBackground(pObj, pObj2Device);
  }
}
FX_BOOL CPDF_RenderStatus::DrawObjWithBlend(
    const CPDF_PageObject* pObj,
    const CFX_AffineMatrix* pObj2Device) {
  FX_BOOL bRet = FALSE;
  switch (pObj->m_Type) {
    case PDFPAGE_PATH:
      bRet = ProcessPath((CPDF_PathObject*)pObj, pObj2Device);
      break;
    case PDFPAGE_IMAGE:
      bRet = ProcessImage((CPDF_ImageObject*)pObj, pObj2Device);
      break;
    case PDFPAGE_FORM:
      bRet = ProcessForm((CPDF_FormObject*)pObj, pObj2Device);
      break;
  }
  return bRet;
}
void CPDF_RenderStatus::GetScaledMatrix(CFX_Matrix& matrix) const {
  CFX_Matrix dCTM = m_pDevice->GetCTM();
  matrix.a *= FXSYS_fabs(dCTM.a);
  matrix.d *= FXSYS_fabs(dCTM.d);
}
void CPDF_RenderStatus::DrawObjWithBackground(
    const CPDF_PageObject* pObj,
    const CFX_AffineMatrix* pObj2Device) {
  FX_RECT rect;
  if (GetObjectClippedRect(pObj, pObj2Device, FALSE, rect)) {
    return;
  }
  int res = 300;
  if (pObj->m_Type == PDFPAGE_IMAGE &&
      m_pDevice->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
    res = 0;
  }
  CPDF_ScaledRenderBuffer buffer;
  if (!buffer.Initialize(m_pContext, m_pDevice, &rect, pObj, &m_Options, res)) {
    return;
  }
  CFX_AffineMatrix matrix = *pObj2Device;
  matrix.Concat(*buffer.GetMatrix());
  GetScaledMatrix(matrix);
  CPDF_Dictionary* pFormResource = NULL;
  if (pObj->m_Type == PDFPAGE_FORM) {
    CPDF_FormObject* pFormObj = (CPDF_FormObject*)pObj;
    if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) {
      pFormResource =
          pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
    }
  }
  CPDF_RenderStatus status;
  status.Initialize(m_pContext, buffer.GetDevice(), buffer.GetMatrix(), NULL,
                    NULL, NULL, &m_Options, m_Transparency, m_bDropObjects,
                    pFormResource);
  status.RenderSingleObject(pObj, &matrix);
  buffer.OutputToDevice();
}
FX_BOOL CPDF_RenderStatus::ProcessForm(CPDF_FormObject* pFormObj,
                                       const CFX_AffineMatrix* pObj2Device) {
  CPDF_Dictionary* pOC =
      pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("OC"));
  if (pOC && m_Options.m_pOCContext &&
      !m_Options.m_pOCContext->CheckOCGVisible(pOC)) {
    return TRUE;
  }
  CFX_AffineMatrix matrix = pFormObj->m_FormMatrix;
  matrix.Concat(*pObj2Device);
  CPDF_Dictionary* pResources = NULL;
  if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) {
    pResources = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
  }
  CPDF_RenderStatus status;
  status.Initialize(m_pContext, m_pDevice, NULL, m_pStopObj, this, pFormObj,
                    &m_Options, m_Transparency, m_bDropObjects, pResources,
                    FALSE);
  status.m_curBlend = m_curBlend;
  m_pDevice->SaveState();
  status.RenderObjectList(pFormObj->m_pForm, &matrix);
  m_bStopped = status.m_bStopped;
  m_pDevice->RestoreState();
  return TRUE;
}
FX_BOOL IsAvailableMatrix(const CFX_AffineMatrix& 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;
}
FX_BOOL CPDF_RenderStatus::ProcessPath(CPDF_PathObject* pPathObj,
                                       const CFX_AffineMatrix* pObj2Device) {
  int FillType = pPathObj->m_FillType;
  FX_BOOL bStroke = pPathObj->m_bStroke;
  ProcessPathPattern(pPathObj, pObj2Device, FillType, bStroke);
  if (FillType == 0 && !bStroke) {
    return TRUE;
  }
  FX_DWORD fill_argb = 0;
  if (FillType) {
    fill_argb = GetFillArgb(pPathObj);
  }
  FX_DWORD stroke_argb = 0;
  if (bStroke) {
    stroke_argb = GetStrokeArgb(pPathObj);
  }
  CFX_AffineMatrix path_matrix = pPathObj->m_Matrix;
  path_matrix.Concat(*pObj2Device);
  if (!IsAvailableMatrix(path_matrix)) {
    return TRUE;
  }
  if (FillType && (m_Options.m_Flags & RENDER_RECT_AA)) {
    FillType |= FXFILL_RECT_AA;
  }
  if (m_Options.m_Flags & RENDER_FILL_FULLCOVER) {
    FillType |= FXFILL_FULLCOVER;
  }
  if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) {
    FillType |= FXFILL_NOPATHSMOOTH;
  }
  if (bStroke) {
    FillType |= FX_FILL_STROKE;
  }
  const CPDF_GeneralStateData* pGeneralData =
      ((CPDF_PageObject*)pPathObj)->m_GeneralState;
  if (pGeneralData && pGeneralData->m_StrokeAdjust) {
    FillType |= FX_STROKE_ADJUST;
  }
  if (m_pType3Char) {
    FillType |= FX_FILL_TEXT_MODE;
  }
  CFX_GraphStateData graphState(*pPathObj->m_GraphState);
  if (m_Options.m_Flags & RENDER_THINLINE) {
    graphState.m_LineWidth = 0;
  }
  return m_pDevice->DrawPath(pPathObj->m_Path, &path_matrix, &graphState,
                             fill_argb, stroke_argb, FillType, 0, NULL,
                             m_curBlend);
}
CPDF_TransferFunc* CPDF_RenderStatus::GetTransferFunc(CPDF_Object* pObj) const {
  ASSERT(pObj != NULL);
  CPDF_DocRenderData* pDocCache = m_pContext->m_pDocument->GetRenderData();
  if (!pDocCache) {
    return NULL;
  }
  return pDocCache->GetTransferFunc(pObj);
}
FX_ARGB CPDF_RenderStatus::GetFillArgb(const CPDF_PageObject* pObj,
                                       FX_BOOL bType3) const {
  CPDF_ColorStateData* pColorData =
      (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pObj->m_ColorState;
  if (m_pType3Char && !bType3 &&
      (!m_pType3Char->m_bColored ||
       (m_pType3Char->m_bColored &&
        (!pColorData || pColorData->m_FillColor.IsNull())))) {
    return m_T3FillColor;
  }
  if (!pColorData || pColorData->m_FillColor.IsNull()) {
    pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)
                     m_InitialStates.m_ColorState;
  }
  FX_COLORREF rgb = pColorData->m_FillRGB;
  if (rgb == (FX_DWORD)-1) {
    return 0;
  }
  const CPDF_GeneralStateData* pGeneralData = pObj->m_GeneralState;
  int alpha;
  if (pGeneralData) {
    alpha = (int32_t)(pGeneralData->m_FillAlpha * 255);
    if (pGeneralData->m_pTR) {
      if (!pGeneralData->m_pTransferFunc) {
        ((CPDF_GeneralStateData*)pGeneralData)->m_pTransferFunc =
            GetTransferFunc(pGeneralData->m_pTR);
      }
      if (pGeneralData->m_pTransferFunc) {
        rgb = pGeneralData->m_pTransferFunc->TranslateColor(rgb);
      }
    }
  } else {
    alpha = 255;
  }
  return m_Options.TranslateColor(ArgbEncode(alpha, rgb));
}
FX_ARGB CPDF_RenderStatus::GetStrokeArgb(const CPDF_PageObject* pObj) const {
  CPDF_ColorStateData* pColorData =
      (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pObj->m_ColorState;
  if (m_pType3Char && (!m_pType3Char->m_bColored ||
                       (m_pType3Char->m_bColored &&
                        (!pColorData || pColorData->m_StrokeColor.IsNull())))) {
    return m_T3FillColor;
  }
  if (!pColorData || pColorData->m_StrokeColor.IsNull()) {
    pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)
                     m_InitialStates.m_ColorState;
  }
  FX_COLORREF rgb = pColorData->m_StrokeRGB;
  if (rgb == (FX_DWORD)-1) {
    return 0;
  }
  const CPDF_GeneralStateData* pGeneralData = pObj->m_GeneralState;
  int alpha;
  if (pGeneralData) {
    alpha = (int32_t)(pGeneralData->m_StrokeAlpha * 255);
    if (pGeneralData->m_pTR) {
      if (!pGeneralData->m_pTransferFunc) {
        ((CPDF_GeneralStateData*)pGeneralData)->m_pTransferFunc =
            GetTransferFunc(pGeneralData->m_pTR);
      }
      if (pGeneralData->m_pTransferFunc) {
        rgb = pGeneralData->m_pTransferFunc->TranslateColor(rgb);
      }
    }
  } else {
    alpha = 255;
  }
  return m_Options.TranslateColor(ArgbEncode(alpha, rgb));
}
void CPDF_RenderStatus::ProcessClipPath(CPDF_ClipPath ClipPath,
                                        const CFX_AffineMatrix* pObj2Device) {
  if (ClipPath.IsNull()) {
    if (m_LastClipPath.IsNull()) {
      return;
    }
    m_pDevice->RestoreState(TRUE);
    m_LastClipPath.SetNull();
    return;
  }
  if (m_LastClipPath == ClipPath) {
    return;
  }
  m_LastClipPath = ClipPath;
  m_pDevice->RestoreState(TRUE);
  int nClipPath = ClipPath.GetPathCount();
  int i;
  for (i = 0; i < nClipPath; i++) {
    const CFX_PathData* pPathData = ClipPath.GetPath(i);
    if (pPathData == NULL) {
      continue;
    }
    if (pPathData->GetPointCount() == 0) {
      CFX_PathData EmptyPath;
      EmptyPath.AppendRect(-1, -1, 0, 0);
      int fill_mode = FXFILL_WINDING;
      m_pDevice->SetClip_PathFill(&EmptyPath, NULL, fill_mode);
    } else {
      int ClipType = ClipPath.GetClipType(i);
      m_pDevice->SetClip_PathFill(pPathData, pObj2Device, ClipType);
    }
  }
  int textcount = ClipPath.GetTextCount();
  if (textcount == 0) {
    return;
  }
  if (m_pDevice->GetDeviceClass() == FXDC_DISPLAY &&
      !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) {
    return;
  }
  CFX_PathData* pTextClippingPath = NULL;
  for (i = 0; i < textcount; i++) {
    CPDF_TextObject* pText = ClipPath.GetText(i);
    if (pText == NULL) {
      if (pTextClippingPath) {
        int fill_mode = FXFILL_WINDING;
        if (m_Options.m_Flags & RENDER_NOTEXTSMOOTH) {
          fill_mode |= FXFILL_NOPATHSMOOTH;
        }
        m_pDevice->SetClip_PathFill(pTextClippingPath, NULL, fill_mode);
        delete pTextClippingPath;
        pTextClippingPath = NULL;
      }
    } else {
      if (pTextClippingPath == NULL) {
        pTextClippingPath = new CFX_PathData;
      }
      ProcessText(pText, pObj2Device, pTextClippingPath);
    }
  }
  delete pTextClippingPath;
}
void CPDF_RenderStatus::DrawClipPath(CPDF_ClipPath ClipPath,
                                     const CFX_AffineMatrix* pObj2Device) {
  if (ClipPath.IsNull()) {
    return;
  }
  int fill_mode = 0;
  if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) {
    fill_mode |= FXFILL_NOPATHSMOOTH;
  }
  int nClipPath = ClipPath.GetPathCount();
  int i;
  for (i = 0; i < nClipPath; i++) {
    const CFX_PathData* pPathData = ClipPath.GetPath(i);
    if (pPathData == NULL) {
      continue;
    }
    CFX_GraphStateData stroke_state;
    if (m_Options.m_Flags & RENDER_THINLINE) {
      stroke_state.m_LineWidth = 0;
    }
    m_pDevice->DrawPath(pPathData, pObj2Device, &stroke_state, 0, 0xffff0000,
                        fill_mode);
  }
}
FX_BOOL CPDF_RenderStatus::SelectClipPath(CPDF_PathObject* pPathObj,
                                          const CFX_AffineMatrix* pObj2Device,
                                          FX_BOOL bStroke) {
  CFX_AffineMatrix path_matrix = pPathObj->m_Matrix;
  path_matrix.Concat(*pObj2Device);
  if (bStroke) {
    CFX_GraphStateData graphState(*pPathObj->m_GraphState);
    if (m_Options.m_Flags & RENDER_THINLINE) {
      graphState.m_LineWidth = 0;
    }
    return m_pDevice->SetClip_PathStroke(pPathObj->m_Path, &path_matrix,
                                         &graphState);
  }
  int fill_mode = pPathObj->m_FillType;
  if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) {
    fill_mode |= FXFILL_NOPATHSMOOTH;
  }
  return m_pDevice->SetClip_PathFill(pPathObj->m_Path, &path_matrix, fill_mode);
}
FX_BOOL CPDF_RenderStatus::ProcessTransparency(
    const CPDF_PageObject* pPageObj,
    const CFX_AffineMatrix* pObj2Device) {
  const CPDF_GeneralStateData* pGeneralState = pPageObj->m_GeneralState;
  int blend_type =
      pGeneralState ? pGeneralState->m_BlendType : FXDIB_BLEND_NORMAL;
  if (blend_type == FXDIB_BLEND_UNSUPPORTED) {
    return TRUE;
  }
  CPDF_Dictionary* pSMaskDict =
      pGeneralState ? (CPDF_Dictionary*)pGeneralState->m_pSoftMask : NULL;
  if (pSMaskDict) {
    if (pPageObj->m_Type == PDFPAGE_IMAGE &&
        ((CPDF_ImageObject*)pPageObj)
            ->m_pImage->GetDict()
            ->KeyExist(FX_BSTRC("SMask"))) {
      pSMaskDict = NULL;
    }
  }
  CPDF_Dictionary* pFormResource = NULL;
  FX_FLOAT group_alpha = 1.0f;
  int Transparency = m_Transparency;
  FX_BOOL bGroupTransparent = FALSE;
  if (pPageObj->m_Type == PDFPAGE_FORM) {
    CPDF_FormObject* pFormObj = (CPDF_FormObject*)pPageObj;
    const CPDF_GeneralStateData* pStateData =
        pFormObj->m_GeneralState.GetObject();
    if (pStateData) {
      group_alpha = pStateData->m_FillAlpha;
    }
    Transparency = pFormObj->m_pForm->m_Transparency;
    bGroupTransparent = Transparency & PDFTRANS_ISOLATED ? TRUE : FALSE;
    if (pFormObj->m_pForm->m_pFormDict) {
      pFormResource = pFormObj->m_pForm->m_pFormDict->GetDict("Resources");
    }
  }
  FX_BOOL bTextClip = FALSE;
  if (pPageObj->m_ClipPath.NotNull() && pPageObj->m_ClipPath.GetTextCount() &&
      m_pDevice->GetDeviceClass() == FXDC_DISPLAY &&
      !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) {
    bTextClip = TRUE;
  }
  if ((m_Options.m_Flags & RENDER_OVERPRINT) &&
      pPageObj->m_Type == PDFPAGE_IMAGE && pGeneralState &&
      pGeneralState->m_FillOP && pGeneralState->m_StrokeOP) {
    CPDF_Document* pDocument = NULL;
    CPDF_Page* pPage = NULL;
    if (m_pContext->m_pPageCache) {
      pPage = m_pContext->m_pPageCache->GetPage();
      pDocument = pPage->m_pDocument;
    } else {
      pDocument = ((CPDF_ImageObject*)pPageObj)->m_pImage->GetDocument();
    }
    CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : NULL;
    CPDF_Object* pCSObj = ((CPDF_ImageObject*)pPageObj)
                              ->m_pImage->GetStream()
                              ->GetDict()
                              ->GetElementValue(FX_BSTRC("ColorSpace"));
    CPDF_ColorSpace* pColorSpace =
        pDocument->LoadColorSpace(pCSObj, pPageResources);
    if (pColorSpace) {
      int format = pColorSpace->GetFamily();
      if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION ||
          format == PDFCS_DEVICEN) {
        blend_type = FXDIB_BLEND_DARKEN;
      }
      pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
    }
  }
  if (pSMaskDict == NULL && group_alpha == 1.0f &&
      blend_type == FXDIB_BLEND_NORMAL && !bTextClip && !bGroupTransparent) {
    return FALSE;
  }
  FX_BOOL isolated = Transparency & PDFTRANS_ISOLATED;
  if (m_bPrint) {
    FX_BOOL bRet = FALSE;
    int rendCaps = m_pDevice->GetRenderCaps();
    if (!((Transparency & PDFTRANS_ISOLATED) || pSMaskDict || bTextClip) &&
        (rendCaps & FXRC_BLEND_MODE)) {
      int oldBlend = m_curBlend;
      m_curBlend = blend_type;
      bRet = DrawObjWithBlend(pPageObj, pObj2Device);
      m_curBlend = oldBlend;
    }
    if (!bRet) {
      DrawObjWithBackground(pPageObj, pObj2Device);
    }
    return TRUE;
  }
  FX_RECT rect = pPageObj->GetBBox(pObj2Device);
  rect.Intersect(m_pDevice->GetClipBox());
  if (rect.IsEmpty()) {
    return TRUE;
  }
  CFX_Matrix deviceCTM = m_pDevice->GetCTM();
  FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a);
  FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d);
  int width = FXSYS_round((FX_FLOAT)rect.Width() * scaleX);
  int height = FXSYS_round((FX_FLOAT)rect.Height() * scaleY);
  CFX_FxgeDevice bitmap_device;
  CFX_DIBitmap* oriDevice = NULL;
  if (!isolated && (m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
    oriDevice = new CFX_DIBitmap;
    if (!m_pDevice->CreateCompatibleBitmap(oriDevice, width, height)) {
      return TRUE;
    }
    m_pDevice->GetDIBits(oriDevice, rect.left, rect.top);
  }
  if (!bitmap_device.Create(width, height, FXDIB_Argb, 0, oriDevice)) {
    return TRUE;
  }
  CFX_DIBitmap* bitmap = bitmap_device.GetBitmap();
  bitmap->Clear(0);
  CFX_AffineMatrix new_matrix = *pObj2Device;
  new_matrix.TranslateI(-rect.left, -rect.top);
  new_matrix.Scale(scaleX, scaleY);
  CFX_DIBitmap* pTextMask = NULL;
  if (bTextClip) {
    pTextMask = new CFX_DIBitmap;
    if (!pTextMask->Create(width, height, FXDIB_8bppMask)) {
      delete pTextMask;
      return TRUE;
    }
    pTextMask->Clear(0);
    CFX_FxgeDevice text_device;
    text_device.Attach(pTextMask);
    for (FX_DWORD i = 0; i < pPageObj->m_ClipPath.GetTextCount(); i++) {
      CPDF_TextObject* textobj = pPageObj->m_ClipPath.GetText(i);
      if (textobj == NULL) {
        break;
      }
      CFX_AffineMatrix text_matrix;
      textobj->GetTextMatrix(&text_matrix);
      CPDF_TextRenderer::DrawTextPath(
          &text_device, textobj->m_nChars, textobj->m_pCharCodes,
          textobj->m_pCharPos, textobj->m_TextState.GetFont(),
          textobj->m_TextState.GetFontSize(), &text_matrix, &new_matrix,
          textobj->m_GraphState, (FX_ARGB)-1, 0, NULL);
    }
  }
  CPDF_RenderStatus bitmap_render;
  bitmap_render.Initialize(m_pContext, &bitmap_device, NULL, m_pStopObj, NULL,
                           NULL, &m_Options, 0, m_bDropObjects, pFormResource,
                           TRUE);
  bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix);
  m_bStopped = bitmap_render.m_bStopped;
  if (pSMaskDict) {
    CFX_AffineMatrix smask_matrix;
    FXSYS_memcpy(&smask_matrix, pGeneralState->m_SMaskMatrix,
                 sizeof smask_matrix);
    smask_matrix.Concat(*pObj2Device);
    CFX_DIBSource* pSMaskSource = LoadSMask(pSMaskDict, &rect, &smask_matrix);
    if (pSMaskSource) {
      bitmap->MultiplyAlpha(pSMaskSource);
      delete pSMaskSource;
    }
  }
  if (pTextMask) {
    bitmap->MultiplyAlpha(pTextMask);
    delete pTextMask;
    pTextMask = NULL;
  }
  if (Transparency & PDFTRANS_GROUP && group_alpha != 1.0f) {
    bitmap->MultiplyAlpha((int32_t)(group_alpha * 255));
  }
  Transparency = m_Transparency;
  if (pPageObj->m_Type == PDFPAGE_FORM) {
    Transparency |= PDFTRANS_GROUP;
  }
  CompositeDIBitmap(bitmap, rect.left, rect.top, 0, 255, blend_type,
                    Transparency);
  delete oriDevice;
  return TRUE;
}
CFX_DIBitmap* CPDF_RenderStatus::GetBackdrop(const CPDF_PageObject* pObj,
                                             const FX_RECT& rect,
                                             int& left,
                                             int& top,
                                             FX_BOOL bBackAlphaRequired) {
  FX_RECT bbox = rect;
  bbox.Intersect(m_pDevice->GetClipBox());
  left = bbox.left;
  top = bbox.top;
  CFX_Matrix deviceCTM = m_pDevice->GetCTM();
  FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a);
  FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d);
  int width = FXSYS_round(bbox.Width() * scaleX);
  int height = FXSYS_round(bbox.Height() * scaleY);
  CFX_DIBitmap* pBackdrop = new CFX_DIBitmap;
  if (bBackAlphaRequired && !m_bDropObjects) {
    pBackdrop->Create(width, height, FXDIB_Argb);
  } else {
    m_pDevice->CreateCompatibleBitmap(pBackdrop, width, height);
  }
  if (pBackdrop->GetBuffer() == NULL) {
    delete pBackdrop;
    return NULL;
  }
  FX_BOOL bNeedDraw;
  if (pBackdrop->HasAlpha()) {
    bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT);
  } else {
    bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS);
  }
  if (!bNeedDraw) {
    m_pDevice->GetDIBits(pBackdrop, left, top);
    return pBackdrop;
  }
  CFX_AffineMatrix FinalMatrix = m_DeviceMatrix;
  FinalMatrix.TranslateI(-left, -top);
  FinalMatrix.Scale(scaleX, scaleY);
  pBackdrop->Clear(pBackdrop->HasAlpha() ? 0 : 0xffffffff);
  CFX_FxgeDevice device;
  device.Attach(pBackdrop);
  m_pContext->Render(&device, pObj, &m_Options, &FinalMatrix);
  return pBackdrop;
}
void CPDF_RenderContext::GetBackground(CFX_DIBitmap* pBuffer,
                                       const CPDF_PageObject* pObj,
                                       const CPDF_RenderOptions* pOptions,
                                       CFX_AffineMatrix* pFinalMatrix) {
  CFX_FxgeDevice device;
  device.Attach(pBuffer);

  FX_RECT rect(0, 0, device.GetWidth(), device.GetHeight());
  device.FillRect(&rect, 0xffffffff);
  Render(&device, pObj, pOptions, pFinalMatrix);
}
CPDF_GraphicStates* CPDF_RenderStatus::CloneObjStates(
    const CPDF_GraphicStates* pSrcStates,
    FX_BOOL bStroke) {
  if (!pSrcStates) {
    return NULL;
  }
  CPDF_GraphicStates* pStates = new CPDF_GraphicStates;
  pStates->CopyStates(*pSrcStates);
  CPDF_Color* pObjColor = bStroke ? pSrcStates->m_ColorState.GetStrokeColor()
                                  : pSrcStates->m_ColorState.GetFillColor();
  if (!pObjColor->IsNull()) {
    CPDF_ColorStateData* pColorData = pStates->m_ColorState.GetModify();
    pColorData->m_FillRGB =
        bStroke ? pSrcStates->m_ColorState.GetObject()->m_StrokeRGB
                : pSrcStates->m_ColorState.GetObject()->m_FillRGB;
    pColorData->m_StrokeRGB = pColorData->m_FillRGB;
  }
  return pStates;
}
CPDF_RenderContext::CPDF_RenderContext() {}
void CPDF_RenderContext::Create(CPDF_Document* pDoc,
                                CPDF_PageRenderCache* pPageCache,
                                CPDF_Dictionary* pPageResources,
                                FX_BOOL bFirstLayer) {
  m_pDocument = pDoc;
  m_pPageResources = pPageResources;
  m_pPageCache = pPageCache;
  m_bFirstLayer = bFirstLayer;
}
void CPDF_RenderContext::Create(CPDF_Page* pPage, FX_BOOL bFirstLayer) {
  m_pDocument = pPage->m_pDocument;
  m_pPageResources = pPage->m_pPageResources;
  m_pPageCache = pPage->GetRenderCache();
  m_bFirstLayer = bFirstLayer;
}
CPDF_RenderContext::~CPDF_RenderContext() {}
void CPDF_RenderContext::Clear() {
  m_pDocument = NULL;
  m_pPageResources = NULL;
  m_pPageCache = NULL;
  m_bFirstLayer = TRUE;
  m_ContentList.RemoveAll();
}
void CPDF_RenderContext::AppendObjectList(
    CPDF_PageObjects* pObjs,
    const CFX_AffineMatrix* pObject2Device) {
  _PDF_RenderItem* pItem = m_ContentList.AddSpace();
  pItem->m_pObjectList = pObjs;
  if (pObject2Device) {
    pItem->m_Matrix = *pObject2Device;
  } else {
    pItem->m_Matrix.SetIdentity();
  }
}
void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice,
                                const CPDF_RenderOptions* pOptions,
                                const CFX_AffineMatrix* pLastMatrix) {
  Render(pDevice, NULL, pOptions, pLastMatrix);
}
void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice,
                                const CPDF_PageObject* pStopObj,
                                const CPDF_RenderOptions* pOptions,
                                const CFX_AffineMatrix* pLastMatrix) {
  int count = m_ContentList.GetSize();
  for (int j = 0; j < count; j++) {
    pDevice->SaveState();
    _PDF_RenderItem* pItem = m_ContentList.GetDataPtr(j);
    if (pLastMatrix) {
      CFX_AffineMatrix FinalMatrix = pItem->m_Matrix;
      FinalMatrix.Concat(*pLastMatrix);
      CPDF_RenderStatus status;
      status.Initialize(this, pDevice, pLastMatrix, pStopObj, NULL, NULL,
                        pOptions, pItem->m_pObjectList->m_Transparency, FALSE,
                        NULL);
      status.RenderObjectList(pItem->m_pObjectList, &FinalMatrix);
      if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
        m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize);
      }
      if (status.m_bStopped) {
        pDevice->RestoreState();
        break;
      }
    } else {
      CPDF_RenderStatus status;
      status.Initialize(this, pDevice, NULL, pStopObj, NULL, NULL, pOptions,
                        pItem->m_pObjectList->m_Transparency, FALSE, NULL);
      status.RenderObjectList(pItem->m_pObjectList, &pItem->m_Matrix);
      if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
        m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize);
      }
      if (status.m_bStopped) {
        pDevice->RestoreState();
        break;
      }
    }
    pDevice->RestoreState();
  }
}
void CPDF_RenderContext::DrawObjectList(CFX_RenderDevice* pDevice,
                                        CPDF_PageObjects* pObjs,
                                        const CFX_AffineMatrix* pObject2Device,
                                        const CPDF_RenderOptions* pOptions) {
  AppendObjectList(pObjs, pObject2Device);
  Render(pDevice, pOptions);
}

CPDF_ProgressiveRenderer::CPDF_ProgressiveRenderer(
    CPDF_RenderContext* pContext,
    CFX_RenderDevice* pDevice,
    const CPDF_RenderOptions* pOptions)
    : m_Status(Ready),
      m_pContext(pContext),
      m_pDevice(pDevice),
      m_pOptions(pOptions),
      m_LayerIndex(0),
      m_ObjectIndex(0),
      m_ObjectPos(nullptr),
      m_PrevLastPos(nullptr) {}

CPDF_ProgressiveRenderer::~CPDF_ProgressiveRenderer() {
  if (m_pRenderStatus)
    m_pDevice->RestoreState();
}

void CPDF_ProgressiveRenderer::Start(IFX_Pause* pPause) {
  if (!m_pContext || !m_pDevice || m_Status != Ready) {
    m_Status = Failed;
    return;
  }
  m_Status = ToBeContinued;
  Continue(pPause);
}

#define RENDER_STEP_LIMIT 100
void CPDF_ProgressiveRenderer::Continue(IFX_Pause* pPause) {
  if (m_Status != ToBeContinued) {
    return;
  }
  FX_DWORD nLayers = m_pContext->m_ContentList.GetSize();
  for (; m_LayerIndex < nLayers; m_LayerIndex++) {
    _PDF_RenderItem* pItem = m_pContext->m_ContentList.GetDataPtr(m_LayerIndex);
    FX_POSITION LastPos = pItem->m_pObjectList->GetLastObjectPosition();
    if (m_ObjectPos == NULL) {
      if (LastPos == m_PrevLastPos) {
        if (!pItem->m_pObjectList->IsParsed()) {
          pItem->m_pObjectList->ContinueParse(pPause);
          if (!pItem->m_pObjectList->IsParsed()) {
            return;
          }
          LastPos = pItem->m_pObjectList->GetLastObjectPosition();
        }
      }
      if (LastPos == m_PrevLastPos) {
        if (m_pRenderStatus) {
          m_pRenderStatus.reset();
          m_pDevice->RestoreState();
          m_ObjectPos = NULL;
          m_PrevLastPos = NULL;
        }
        continue;
      }
      if (m_PrevLastPos) {
        m_ObjectPos = m_PrevLastPos;
        pItem->m_pObjectList->GetNextObject(m_ObjectPos);
      } else {
        m_ObjectPos = pItem->m_pObjectList->GetFirstObjectPosition();
      }
      m_PrevLastPos = LastPos;
    }
    if (!m_pRenderStatus) {
      m_ObjectPos = pItem->m_pObjectList->GetFirstObjectPosition();
      m_ObjectIndex = 0;
      m_pRenderStatus.reset(new CPDF_RenderStatus());
      m_pRenderStatus->Initialize(
          m_pContext, m_pDevice, NULL, NULL, NULL, NULL, m_pOptions,
          pItem->m_pObjectList->m_Transparency, FALSE, NULL);
      m_pDevice->SaveState();
      m_ClipRect = m_pDevice->GetClipBox();
      CFX_AffineMatrix device2object;
      device2object.SetReverse(pItem->m_Matrix);
      device2object.TransformRect(m_ClipRect);
    }
    int objs_to_go = CPDF_ModuleMgr::Get()
                         ->GetRenderModule()
                         ->GetConfig()
                         ->m_RenderStepLimit;
    while (m_ObjectPos) {
      CPDF_PageObject* pCurObj = pItem->m_pObjectList->GetObjectAt(m_ObjectPos);
      if (pCurObj && pCurObj->m_Left <= m_ClipRect.right &&
          pCurObj->m_Right >= m_ClipRect.left &&
          pCurObj->m_Bottom <= m_ClipRect.top &&
          pCurObj->m_Top >= m_ClipRect.bottom) {
        if (m_pRenderStatus->ContinueSingleObject(pCurObj, &pItem->m_Matrix,
                                                  pPause)) {
          return;
        }
        if (pCurObj->m_Type == PDFPAGE_IMAGE &&
            m_pRenderStatus->m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
          m_pContext->GetPageCache()->CacheOptimization(
              m_pRenderStatus->m_Options.m_dwLimitCacheSize);
        }
        if (pCurObj->m_Type == PDFPAGE_FORM ||
            pCurObj->m_Type == PDFPAGE_SHADING) {
          objs_to_go = 0;
        } else {
          objs_to_go--;
        }
      }
      m_ObjectIndex++;
      pItem->m_pObjectList->GetNextObject(m_ObjectPos);
      if (objs_to_go == 0) {
        if (pPause && pPause->NeedToPauseNow()) {
          return;
        }
        objs_to_go = CPDF_ModuleMgr::Get()
                         ->GetRenderModule()
                         ->GetConfig()
                         ->m_RenderStepLimit;
      }
    }
    if (!pItem->m_pObjectList->IsParsed()) {
      return;
    }
    m_pRenderStatus.reset();
    m_pDevice->RestoreState();
    m_ObjectPos = NULL;
    m_PrevLastPos = NULL;
    if (pPause && pPause->NeedToPauseNow()) {
      m_LayerIndex++;
      return;
    }
  }
  m_Status = Done;
}
int CPDF_ProgressiveRenderer::EstimateProgress() {
  if (!m_pContext) {
    return 0;
  }
  FX_DWORD nLayers = m_pContext->m_ContentList.GetSize();
  int nTotal = 0, nRendered = 0;
  for (FX_DWORD layer = 0; layer < nLayers; layer++) {
    _PDF_RenderItem* pItem = m_pContext->m_ContentList.GetDataPtr(layer);
    int nObjs = pItem->m_pObjectList->CountObjects();
    if (layer == m_LayerIndex) {
      nRendered += m_ObjectIndex;
    } else if (layer < m_LayerIndex) {
      nRendered += nObjs;
    }
    nTotal += nObjs;
  }
  if (nTotal == 0) {
    return 0;
  }
  return 100 * nRendered / nTotal;
}
CPDF_TransferFunc* CPDF_DocRenderData::GetTransferFunc(CPDF_Object* pObj) {
  if (!pObj)
    return nullptr;

  auto it = m_TransferFuncMap.find(pObj);
  if (it != m_TransferFuncMap.end()) {
    CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter = it->second;
    return pTransferCounter->AddRef();
  }

  CPDF_Function* pFuncs[3] = {nullptr, nullptr, nullptr};
  FX_BOOL bUniTransfer = TRUE;
  FX_BOOL bIdentity = TRUE;
  if (pObj->GetType() == PDFOBJ_ARRAY) {
    bUniTransfer = FALSE;
    CPDF_Array* pArray = (CPDF_Array*)pObj;
    if (pArray->GetCount() < 3)
      return nullptr;

    for (FX_DWORD i = 0; i < 3; ++i) {
      pFuncs[2 - i] = CPDF_Function::Load(pArray->GetElementValue(i));
      if (!pFuncs[2 - i]) {
        return nullptr;
      }
    }
  } else {
    pFuncs[0] = CPDF_Function::Load(pObj);
    if (!pFuncs[0]) {
      return nullptr;
    }
  }
  CPDF_TransferFunc* pTransfer = new CPDF_TransferFunc;
  pTransfer->m_pPDFDoc = m_pPDFDoc;
  CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter =
      new CPDF_CountedObject<CPDF_TransferFunc>(pTransfer);
  m_TransferFuncMap[pObj] = pTransferCounter;
  static const int kMaxOutputs = 16;
  FX_FLOAT output[kMaxOutputs];
  FXSYS_memset(output, 0, sizeof(output));
  FX_FLOAT input;
  int noutput;
  for (int v = 0; v < 256; ++v) {
    input = (FX_FLOAT)v / 255.0f;
    if (bUniTransfer) {
      if (pFuncs[0] && pFuncs[0]->CountOutputs() <= kMaxOutputs)
        pFuncs[0]->Call(&input, 1, output, noutput);
      int o = FXSYS_round(output[0] * 255);
      if (o != v)
        bIdentity = FALSE;
      for (int i = 0; i < 3; ++i) {
        pTransfer->m_Samples[i * 256 + v] = o;
      }
    } else {
      for (int i = 0; i < 3; ++i) {
        if (pFuncs[i] && pFuncs[i]->CountOutputs() <= kMaxOutputs) {
          pFuncs[i]->Call(&input, 1, output, noutput);
          int o = FXSYS_round(output[0] * 255);
          if (o != v)
            bIdentity = FALSE;
          pTransfer->m_Samples[i * 256 + v] = o;
        } else {
          pTransfer->m_Samples[i * 256 + v] = v;
        }
      }
    }
  }
  for (int i = 0; i < 3; ++i)
    delete pFuncs[i];

  pTransfer->m_bIdentity = bIdentity;
  return pTransferCounter->AddRef();
}

void CPDF_DocRenderData::ReleaseTransferFunc(CPDF_Object* pObj) {
  auto it = m_TransferFuncMap.find(pObj);
  if (it != m_TransferFuncMap.end())
    it->second->RemoveRef();
}
CPDF_RenderConfig::CPDF_RenderConfig() {
  m_HalftoneLimit = 0;
  m_RenderStepLimit = 100;
}
CPDF_RenderConfig::~CPDF_RenderConfig() {}
CPDF_DeviceBuffer::CPDF_DeviceBuffer() {
  m_pBitmap = NULL;
  m_pDevice = NULL;
  m_pContext = NULL;
  m_pObject = NULL;
}
CPDF_DeviceBuffer::~CPDF_DeviceBuffer() {
  delete m_pBitmap;
}
FX_BOOL CPDF_DeviceBuffer::Initialize(CPDF_RenderContext* pContext,
                                      CFX_RenderDevice* pDevice,
                                      FX_RECT* pRect,
                                      const CPDF_PageObject* pObj,
                                      int max_dpi) {
  m_pDevice = pDevice;
  m_pContext = pContext;
  m_Rect = *pRect;
  m_pObject = pObj;
  m_Matrix.TranslateI(-pRect->left, -pRect->top);
#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
  int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE);
  int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE);
  if (horz_size && vert_size && max_dpi) {
    int dpih =
        pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10);
    int dpiv =
        pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10);
    if (dpih > max_dpi) {
      m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f);
    }
    if (dpiv > max_dpi) {
      m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv);
    }
  }
#endif
  CFX_Matrix ctm = m_pDevice->GetCTM();
  FX_FLOAT fScaleX = FXSYS_fabs(ctm.a);
  FX_FLOAT fScaleY = FXSYS_fabs(ctm.d);
  m_Matrix.Concat(fScaleX, 0, 0, fScaleY, 0, 0);
  CFX_FloatRect rect(*pRect);
  m_Matrix.TransformRect(rect);
  FX_RECT bitmap_rect = rect.GetOutterRect();
  m_pBitmap = new CFX_DIBitmap;
  m_pBitmap->Create(bitmap_rect.Width(), bitmap_rect.Height(), FXDIB_Argb);
  return TRUE;
}
void CPDF_DeviceBuffer::OutputToDevice() {
  if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) {
    if (m_Matrix.a == 1.0f && m_Matrix.d == 1.0f) {
      m_pDevice->SetDIBits(m_pBitmap, m_Rect.left, m_Rect.top);
    } else {
      m_pDevice->StretchDIBits(m_pBitmap, m_Rect.left, m_Rect.top,
                               m_Rect.Width(), m_Rect.Height());
    }
  } else {
    CFX_DIBitmap buffer;
    m_pDevice->CreateCompatibleBitmap(&buffer, m_pBitmap->GetWidth(),
                                      m_pBitmap->GetHeight());
    m_pContext->GetBackground(&buffer, m_pObject, NULL, &m_Matrix);
    buffer.CompositeBitmap(0, 0, buffer.GetWidth(), buffer.GetHeight(),
                           m_pBitmap, 0, 0);
    m_pDevice->StretchDIBits(&buffer, m_Rect.left, m_Rect.top, m_Rect.Width(),
                             m_Rect.Height());
  }
}
CPDF_ScaledRenderBuffer::CPDF_ScaledRenderBuffer() {
  m_pBitmapDevice = NULL;
}
CPDF_ScaledRenderBuffer::~CPDF_ScaledRenderBuffer() {
  delete m_pBitmapDevice;
}
#define _FPDFAPI_IMAGESIZE_LIMIT_ (30 * 1024 * 1024)
FX_BOOL CPDF_ScaledRenderBuffer::Initialize(CPDF_RenderContext* pContext,
                                            CFX_RenderDevice* pDevice,
                                            FX_RECT* pRect,
                                            const CPDF_PageObject* pObj,
                                            const CPDF_RenderOptions* pOptions,
                                            int max_dpi) {
  FXSYS_assert(pRect != NULL);
  m_pDevice = pDevice;
  if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) {
    return TRUE;
  }
  m_pContext = pContext;
  m_Rect = *pRect;
  m_pObject = pObj;
  m_Matrix.TranslateI(-pRect->left, -pRect->top);
  int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE);
  int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE);
  if (horz_size && vert_size && max_dpi) {
    int dpih =
        pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10);
    int dpiv =
        pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10);
    if (dpih > max_dpi) {
      m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f);
    }
    if (dpiv > max_dpi) {
      m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv);
    }
  }
  m_pBitmapDevice = new CFX_FxgeDevice;
  FXDIB_Format dibFormat = FXDIB_Rgb;
  int32_t bpp = 24;
  if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_ALPHA_OUTPUT) {
    dibFormat = FXDIB_Argb;
    bpp = 32;
  }
  CFX_FloatRect rect;
  int32_t iWidth, iHeight, iPitch;
  while (1) {
    rect = *pRect;
    m_Matrix.TransformRect(rect);
    FX_RECT bitmap_rect = rect.GetOutterRect();
    iWidth = bitmap_rect.Width();
    iHeight = bitmap_rect.Height();
    iPitch = (iWidth * bpp + 31) / 32 * 4;
    if (iWidth * iHeight < 1) {
      return FALSE;
    }
    if (iPitch * iHeight <= _FPDFAPI_IMAGESIZE_LIMIT_ &&
        m_pBitmapDevice->Create(iWidth, iHeight, dibFormat)) {
      break;
    }
    m_Matrix.Scale(0.5f, 0.5f);
  }
  m_pContext->GetBackground(m_pBitmapDevice->GetBitmap(), m_pObject, pOptions,
                            &m_Matrix);
  return TRUE;
}
void CPDF_ScaledRenderBuffer::OutputToDevice() {
  if (m_pBitmapDevice) {
    m_pDevice->StretchDIBits(m_pBitmapDevice->GetBitmap(), m_Rect.left,
                             m_Rect.top, m_Rect.Width(), m_Rect.Height());
  }
}
FX_BOOL IPDF_OCContext::CheckObjectVisible(const CPDF_PageObject* pObj) {
  const CPDF_ContentMarkData* pData = pObj->m_ContentMark;
  int nItems = pData->CountItems();
  for (int i = 0; i < nItems; i++) {
    CPDF_ContentMarkItem& item = pData->GetItem(i);
    if (item.GetName() == FX_BSTRC("OC") &&
        item.GetParamType() == CPDF_ContentMarkItem::PropertiesDict) {
      CPDF_Dictionary* pOCG = (CPDF_Dictionary*)item.GetParam();
      if (!CheckOCGVisible(pOCG)) {
        return FALSE;
      }
    }
  }
  return TRUE;
}
