// 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 "core/src/fpdfapi/fpdf_page/pageint.h"

#include <algorithm>

#include "core/include/fpdfapi/cpdf_document.h"
#include "core/include/fpdfapi/fpdf_module.h"
#include "core/include/fpdfapi/fpdf_page.h"
#include "core/include/fpdfapi/fpdf_pageobj.h"
#include "core/include/fpdfapi/fpdf_render.h"
#include "core/src/fpdfapi/fpdf_render/render_int.h"
#include "third_party/base/stl_util.h"

namespace {

FX_FLOAT ClipFloat(FX_FLOAT f) {
  return std::max(0.0f, std::min(1.0f, f));
}

}  // namespace

void CPDF_GraphicStates::DefaultStates() {
  m_ColorState.New()->Default();
}
void CPDF_GraphicStates::CopyStates(const CPDF_GraphicStates& src) {
  m_ClipPath = src.m_ClipPath;
  m_GraphState = src.m_GraphState;
  m_ColorState = src.m_ColorState;
  m_TextState = src.m_TextState;
  m_GeneralState = src.m_GeneralState;
}
CPDF_ClipPathData::CPDF_ClipPathData() {
  m_PathCount = 0;
  m_pPathList = NULL;
  m_pTypeList = NULL;
  m_TextCount = 0;
  m_pTextList = NULL;
}
CPDF_ClipPathData::~CPDF_ClipPathData() {
  int i;
  delete[] m_pPathList;
  FX_Free(m_pTypeList);
  for (i = m_TextCount - 1; i > -1; i--)
    delete m_pTextList[i];
  FX_Free(m_pTextList);
}
CPDF_ClipPathData::CPDF_ClipPathData(const CPDF_ClipPathData& src) {
  m_pPathList = NULL;
  m_pPathList = NULL;
  m_pTextList = NULL;
  m_PathCount = src.m_PathCount;
  if (m_PathCount) {
    int alloc_size = m_PathCount;
    if (alloc_size % 8) {
      alloc_size += 8 - (alloc_size % 8);
    }
    m_pPathList = new CPDF_Path[alloc_size];
    for (int i = 0; i < m_PathCount; i++) {
      m_pPathList[i] = src.m_pPathList[i];
    }
    m_pTypeList = FX_Alloc(uint8_t, alloc_size);
    FXSYS_memcpy(m_pTypeList, src.m_pTypeList, m_PathCount);
  } else {
    m_pPathList = NULL;
    m_pTypeList = NULL;
  }
  m_TextCount = src.m_TextCount;
  if (m_TextCount) {
    m_pTextList = FX_Alloc(CPDF_TextObject*, m_TextCount);
    for (int i = 0; i < m_TextCount; i++) {
      if (src.m_pTextList[i]) {
        m_pTextList[i] = src.m_pTextList[i]->Clone();
      } else {
        m_pTextList[i] = NULL;
      }
    }
  } else {
    m_pTextList = NULL;
  }
}
void CPDF_ClipPathData::SetCount(int path_count, int text_count) {
  ASSERT(m_TextCount == 0 && m_PathCount == 0);
  if (path_count) {
    m_PathCount = path_count;
    int alloc_size = (path_count + 7) / 8 * 8;
    m_pPathList = new CPDF_Path[alloc_size];
    m_pTypeList = FX_Alloc(uint8_t, alloc_size);
  }
  if (text_count) {
    m_TextCount = text_count;
    m_pTextList = FX_Alloc(CPDF_TextObject*, text_count);
  }
}
CFX_FloatRect CPDF_ClipPath::GetClipBox() const {
  CFX_FloatRect rect;
  FX_BOOL bStarted = FALSE;
  int count = GetPathCount();
  if (count) {
    rect = GetPath(0).GetBoundingBox();
    for (int i = 1; i < count; i++) {
      CFX_FloatRect path_rect = GetPath(i).GetBoundingBox();
      rect.Intersect(path_rect);
    }
    bStarted = TRUE;
  }
  count = GetTextCount();
  if (count) {
    CFX_FloatRect layer_rect;
    FX_BOOL bLayerStarted = FALSE;
    for (int i = 0; i < count; i++) {
      CPDF_TextObject* pTextObj = GetText(i);
      if (!pTextObj) {
        if (!bStarted) {
          rect = layer_rect;
          bStarted = TRUE;
        } else {
          rect.Intersect(layer_rect);
        }
        bLayerStarted = FALSE;
      } else {
        if (!bLayerStarted) {
          layer_rect = CFX_FloatRect(pTextObj->GetBBox(nullptr));
          bLayerStarted = TRUE;
        } else {
          layer_rect.Union(CFX_FloatRect(pTextObj->GetBBox(nullptr)));
        }
      }
    }
  }
  return rect;
}
void CPDF_ClipPath::AppendPath(CPDF_Path path, int type, FX_BOOL bAutoMerge) {
  CPDF_ClipPathData* pData = GetModify();
  if (pData->m_PathCount && bAutoMerge) {
    CPDF_Path old_path = pData->m_pPathList[pData->m_PathCount - 1];
    if (old_path.IsRect()) {
      CFX_FloatRect old_rect(old_path.GetPointX(0), old_path.GetPointY(0),
                             old_path.GetPointX(2), old_path.GetPointY(2));
      CFX_FloatRect new_rect = path.GetBoundingBox();
      if (old_rect.Contains(new_rect)) {
        pData->m_PathCount--;
        pData->m_pPathList[pData->m_PathCount].SetNull();
      }
    }
  }
  if (pData->m_PathCount % 8 == 0) {
    CPDF_Path* pNewPath = new CPDF_Path[pData->m_PathCount + 8];
    for (int i = 0; i < pData->m_PathCount; i++) {
      pNewPath[i] = pData->m_pPathList[i];
    }
    delete[] pData->m_pPathList;
    uint8_t* pNewType = FX_Alloc(uint8_t, pData->m_PathCount + 8);
    FXSYS_memcpy(pNewType, pData->m_pTypeList, pData->m_PathCount);
    FX_Free(pData->m_pTypeList);
    pData->m_pPathList = pNewPath;
    pData->m_pTypeList = pNewType;
  }
  pData->m_pPathList[pData->m_PathCount] = path;
  pData->m_pTypeList[pData->m_PathCount] = (uint8_t)type;
  pData->m_PathCount++;
}
void CPDF_ClipPath::DeletePath(int index) {
  CPDF_ClipPathData* pData = GetModify();
  if (index >= pData->m_PathCount) {
    return;
  }
  pData->m_pPathList[index].SetNull();
  for (int i = index; i < pData->m_PathCount - 1; i++) {
    pData->m_pPathList[i] = pData->m_pPathList[i + 1];
  }
  pData->m_pPathList[pData->m_PathCount - 1].SetNull();
  FXSYS_memmove(pData->m_pTypeList + index, pData->m_pTypeList + index + 1,
                pData->m_PathCount - index - 1);
  pData->m_PathCount--;
}
#define FPDF_CLIPPATH_MAX_TEXTS 1024
void CPDF_ClipPath::AppendTexts(CPDF_TextObject** pTexts, int count) {
  CPDF_ClipPathData* pData = GetModify();
  if (pData->m_TextCount + count > FPDF_CLIPPATH_MAX_TEXTS) {
    for (int i = 0; i < count; i++) {
      delete pTexts[i];
    }
    return;
  }
  CPDF_TextObject** pNewList =
      FX_Alloc(CPDF_TextObject*, pData->m_TextCount + count + 1);
  if (pData->m_pTextList) {
    FXSYS_memcpy(pNewList, pData->m_pTextList,
                 pData->m_TextCount * sizeof(CPDF_TextObject*));
    FX_Free(pData->m_pTextList);
  }
  pData->m_pTextList = pNewList;
  for (int i = 0; i < count; i++) {
    pData->m_pTextList[pData->m_TextCount + i] = pTexts[i];
  }
  pData->m_pTextList[pData->m_TextCount + count] = NULL;
  pData->m_TextCount += count + 1;
}
void CPDF_ClipPath::Transform(const CFX_Matrix& matrix) {
  CPDF_ClipPathData* pData = GetModify();
  int i;
  for (i = 0; i < pData->m_PathCount; i++) {
    pData->m_pPathList[i].Transform(&matrix);
  }
  for (i = 0; i < pData->m_TextCount; i++)
    if (pData->m_pTextList[i]) {
      pData->m_pTextList[i]->Transform(matrix);
    }
}
CPDF_ColorStateData::CPDF_ColorStateData(const CPDF_ColorStateData& src) {
  m_FillColor.Copy(&src.m_FillColor);
  m_FillRGB = src.m_FillRGB;
  m_StrokeColor.Copy(&src.m_StrokeColor);
  m_StrokeRGB = src.m_StrokeRGB;
}
void CPDF_ColorStateData::Default() {
  m_FillRGB = m_StrokeRGB = 0;
  m_FillColor.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));
  m_StrokeColor.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));
}
void CPDF_ColorState::SetFillColor(CPDF_ColorSpace* pCS,
                                   FX_FLOAT* pValue,
                                   int nValues) {
  CPDF_ColorStateData* pData = GetModify();
  SetColor(pData->m_FillColor, pData->m_FillRGB, pCS, pValue, nValues);
}
void CPDF_ColorState::SetStrokeColor(CPDF_ColorSpace* pCS,
                                     FX_FLOAT* pValue,
                                     int nValues) {
  CPDF_ColorStateData* pData = GetModify();
  SetColor(pData->m_StrokeColor, pData->m_StrokeRGB, pCS, pValue, nValues);
}
void CPDF_ColorState::SetColor(CPDF_Color& color,
                               FX_DWORD& rgb,
                               CPDF_ColorSpace* pCS,
                               FX_FLOAT* pValue,
                               int nValues) {
  if (pCS) {
    color.SetColorSpace(pCS);
  } else if (color.IsNull()) {
    color.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));
  }
  if (color.m_pCS->CountComponents() > nValues) {
    return;
  }
  color.SetValue(pValue);
  int R, G, B;
  rgb = color.GetRGB(R, G, B) ? FXSYS_RGB(R, G, B) : (FX_DWORD)-1;
}
void CPDF_ColorState::SetFillPattern(CPDF_Pattern* pPattern,
                                     FX_FLOAT* pValue,
                                     int nValues) {
  CPDF_ColorStateData* pData = GetModify();
  pData->m_FillColor.SetValue(pPattern, pValue, nValues);
  int R, G, B;
  FX_BOOL ret = pData->m_FillColor.GetRGB(R, G, B);
  if (pPattern->m_PatternType == 1 &&
      ((CPDF_TilingPattern*)pPattern)->m_bColored && !ret) {
    pData->m_FillRGB = 0x00BFBFBF;
    return;
  }
  pData->m_FillRGB = ret ? FXSYS_RGB(R, G, B) : (FX_DWORD)-1;
}
void CPDF_ColorState::SetStrokePattern(CPDF_Pattern* pPattern,
                                       FX_FLOAT* pValue,
                                       int nValues) {
  CPDF_ColorStateData* pData = GetModify();
  pData->m_StrokeColor.SetValue(pPattern, pValue, nValues);
  int R, G, B;
  FX_BOOL ret = pData->m_StrokeColor.GetRGB(R, G, B);
  if (pPattern->m_PatternType == 1 &&
      ((CPDF_TilingPattern*)pPattern)->m_bColored && !ret) {
    pData->m_StrokeRGB = 0x00BFBFBF;
    return;
  }
  pData->m_StrokeRGB =
      pData->m_StrokeColor.GetRGB(R, G, B) ? FXSYS_RGB(R, G, B) : (FX_DWORD)-1;
}
CPDF_TextStateData::CPDF_TextStateData() {
  m_pFont = NULL;
  m_pDocument = NULL;
  m_FontSize = 1.0f;
  m_WordSpace = 0;
  m_CharSpace = 0;
  m_TextMode = 0;
  m_Matrix[0] = m_Matrix[3] = 1.0f;
  m_Matrix[1] = m_Matrix[2] = 0;
  m_CTM[0] = m_CTM[3] = 1.0f;
  m_CTM[1] = m_CTM[2] = 0;
}
CPDF_TextStateData::CPDF_TextStateData(const CPDF_TextStateData& src) {
  if (this == &src) {
    return;
  }
  FXSYS_memcpy(this, &src, sizeof(CPDF_TextStateData));
  if (m_pDocument && m_pFont) {
    m_pFont =
        m_pDocument->GetPageData()->GetFont(m_pFont->GetFontDict(), FALSE);
  }
}
CPDF_TextStateData::~CPDF_TextStateData() {
  if (m_pDocument && m_pFont) {
    CPDF_DocPageData* pPageData = m_pDocument->GetPageData();
    if (pPageData && !pPageData->IsForceClear()) {
      pPageData->ReleaseFont(m_pFont->GetFontDict());
    }
  }
}
void CPDF_TextState::SetFont(CPDF_Font* pFont) {
  CPDF_TextStateData* pStateData = GetModify();
  if (pStateData) {
    CPDF_Document* pDoc = pStateData->m_pDocument;
    CPDF_DocPageData* pPageData = pDoc ? pDoc->GetPageData() : NULL;
    if (pPageData && pStateData->m_pFont && !pPageData->IsForceClear()) {
      pPageData->ReleaseFont(pStateData->m_pFont->GetFontDict());
    }
    pStateData->m_pDocument = pFont ? pFont->m_pDocument : NULL;
    pStateData->m_pFont = pFont;
  }
}
FX_FLOAT CPDF_TextState::GetFontSizeV() const {
  FX_FLOAT* pMatrix = GetMatrix();
  FX_FLOAT unit = FXSYS_sqrt2(pMatrix[1], pMatrix[3]);
  FX_FLOAT size = unit * GetFontSize();
  return (FX_FLOAT)FXSYS_fabs(size);
}
FX_FLOAT CPDF_TextState::GetFontSizeH() const {
  FX_FLOAT* pMatrix = GetMatrix();
  FX_FLOAT unit = FXSYS_sqrt2(pMatrix[0], pMatrix[2]);
  FX_FLOAT size = unit * GetFontSize();
  return (FX_FLOAT)FXSYS_fabs(size);
}
FX_FLOAT CPDF_TextState::GetBaselineAngle() const {
  FX_FLOAT* m_Matrix = GetMatrix();
  return FXSYS_atan2(m_Matrix[2], m_Matrix[0]);
}
FX_FLOAT CPDF_TextState::GetShearAngle() const {
  FX_FLOAT* m_Matrix = GetMatrix();
  FX_FLOAT shear_angle = FXSYS_atan2(m_Matrix[1], m_Matrix[3]);
  return GetBaselineAngle() + shear_angle;
}
CPDF_GeneralStateData::CPDF_GeneralStateData() {
  FXSYS_memset(this, 0, sizeof(CPDF_GeneralStateData));
  FXSYS_strcpy((FX_CHAR*)m_BlendMode, "Normal");
  m_StrokeAlpha = 1.0f;
  m_FillAlpha = 1.0f;
  m_Flatness = 1.0f;
  m_Matrix.SetIdentity();
}
CPDF_GeneralStateData::CPDF_GeneralStateData(const CPDF_GeneralStateData& src) {
  FXSYS_memcpy(this, &src, sizeof(CPDF_GeneralStateData));
  if (src.m_pTransferFunc && src.m_pTransferFunc->m_pPDFDoc) {
    CPDF_DocRenderData* pDocCache =
        src.m_pTransferFunc->m_pPDFDoc->GetRenderData();
    if (!pDocCache) {
      return;
    }
    m_pTransferFunc = pDocCache->GetTransferFunc(m_pTR);
  }
}
CPDF_GeneralStateData::~CPDF_GeneralStateData() {
  if (m_pTransferFunc && m_pTransferFunc->m_pPDFDoc) {
    CPDF_DocRenderData* pDocCache = m_pTransferFunc->m_pPDFDoc->GetRenderData();
    if (!pDocCache) {
      return;
    }
    pDocCache->ReleaseTransferFunc(m_pTR);
  }
}
static int GetBlendType(const CFX_ByteStringC& mode) {
  switch (mode.GetID()) {
    case FXBSTR_ID('N', 'o', 'r', 'm'):
    case FXBSTR_ID('C', 'o', 'm', 'p'):
      return FXDIB_BLEND_NORMAL;
    case FXBSTR_ID('M', 'u', 'l', 't'):
      return FXDIB_BLEND_MULTIPLY;
    case FXBSTR_ID('S', 'c', 'r', 'e'):
      return FXDIB_BLEND_SCREEN;
    case FXBSTR_ID('O', 'v', 'e', 'r'):
      return FXDIB_BLEND_OVERLAY;
    case FXBSTR_ID('D', 'a', 'r', 'k'):
      return FXDIB_BLEND_DARKEN;
    case FXBSTR_ID('L', 'i', 'g', 'h'):
      return FXDIB_BLEND_LIGHTEN;
    case FXBSTR_ID('C', 'o', 'l', 'o'):
      if (mode.GetLength() == 10) {
        return FXDIB_BLEND_COLORDODGE;
      }
      if (mode.GetLength() == 9) {
        return FXDIB_BLEND_COLORBURN;
      }
      return FXDIB_BLEND_COLOR;
    case FXBSTR_ID('H', 'a', 'r', 'd'):
      return FXDIB_BLEND_HARDLIGHT;
    case FXBSTR_ID('S', 'o', 'f', 't'):
      return FXDIB_BLEND_SOFTLIGHT;
    case FXBSTR_ID('D', 'i', 'f', 'f'):
      return FXDIB_BLEND_DIFFERENCE;
    case FXBSTR_ID('E', 'x', 'c', 'l'):
      return FXDIB_BLEND_EXCLUSION;
    case FXBSTR_ID('H', 'u', 'e', 0):
      return FXDIB_BLEND_HUE;
    case FXBSTR_ID('S', 'a', 't', 'u'):
      return FXDIB_BLEND_SATURATION;
    case FXBSTR_ID('L', 'u', 'm', 'i'):
      return FXDIB_BLEND_LUMINOSITY;
  }
  return FXDIB_BLEND_NORMAL;
}
void CPDF_GeneralStateData::SetBlendMode(const CFX_ByteStringC& blend_mode) {
  if (blend_mode.GetLength() > 15) {
    return;
  }
  FXSYS_memcpy(m_BlendMode, blend_mode.GetPtr(), blend_mode.GetLength());
  m_BlendMode[blend_mode.GetLength()] = 0;
  m_BlendType = ::GetBlendType(blend_mode);
}
int RI_StringToId(const CFX_ByteString& ri) {
  FX_DWORD id = ri.GetID();
  if (id == FXBSTR_ID('A', 'b', 's', 'o')) {
    return 1;
  }
  if (id == FXBSTR_ID('S', 'a', 't', 'u')) {
    return 2;
  }
  if (id == FXBSTR_ID('P', 'e', 'r', 'c')) {
    return 3;
  }
  return 0;
}
void CPDF_GeneralState::SetRenderIntent(const CFX_ByteString& ri) {
  GetModify()->m_RenderIntent = RI_StringToId(ri);
}
CPDF_AllStates::CPDF_AllStates() {
  m_TextX = m_TextY = m_TextLineX = m_TextLineY = 0;
  m_TextLeading = 0;
  m_TextRise = 0;
  m_TextHorzScale = 1.0f;
}
CPDF_AllStates::~CPDF_AllStates() {}
void CPDF_AllStates::Copy(const CPDF_AllStates& src) {
  CopyStates(src);
  m_TextMatrix.Copy(src.m_TextMatrix);
  m_ParentMatrix.Copy(src.m_ParentMatrix);
  m_CTM.Copy(src.m_CTM);
  m_TextX = src.m_TextX;
  m_TextY = src.m_TextY;
  m_TextLineX = src.m_TextLineX;
  m_TextLineY = src.m_TextLineY;
  m_TextLeading = src.m_TextLeading;
  m_TextRise = src.m_TextRise;
  m_TextHorzScale = src.m_TextHorzScale;
}
void CPDF_AllStates::SetLineDash(CPDF_Array* pArray,
                                 FX_FLOAT phase,
                                 FX_FLOAT scale) {
  CFX_GraphStateData* pData = m_GraphState.GetModify();
  pData->m_DashPhase = phase * scale;
  pData->SetDashCount(pArray->GetCount());
  for (FX_DWORD i = 0; i < pArray->GetCount(); i++) {
    pData->m_DashArray[i] = pArray->GetNumberAt(i) * scale;
  }
}
void CPDF_AllStates::ProcessExtGS(CPDF_Dictionary* pGS,
                                  CPDF_StreamContentParser* pParser) {
  CPDF_GeneralStateData* pGeneralState = m_GeneralState.GetModify();
  for (const auto& it : *pGS) {
    const CFX_ByteString& key_str = it.first;
    CPDF_Object* pElement = it.second;
    CPDF_Object* pObject = pElement ? pElement->GetDirect() : nullptr;
    if (!pObject)
      continue;

    FX_DWORD key = key_str.GetID();
    switch (key) {
      case FXBSTR_ID('L', 'W', 0, 0):
        m_GraphState.GetModify()->m_LineWidth = pObject->GetNumber();
        break;
      case FXBSTR_ID('L', 'C', 0, 0):
        m_GraphState.GetModify()->m_LineCap =
            (CFX_GraphStateData::LineCap)pObject->GetInteger();
        break;
      case FXBSTR_ID('L', 'J', 0, 0):
        m_GraphState.GetModify()->m_LineJoin =
            (CFX_GraphStateData::LineJoin)pObject->GetInteger();
        break;
      case FXBSTR_ID('M', 'L', 0, 0):
        m_GraphState.GetModify()->m_MiterLimit = pObject->GetNumber();
        break;
      case FXBSTR_ID('D', 0, 0, 0): {
        CPDF_Array* pDash = pObject->AsArray();
        if (!pDash)
          break;

        CPDF_Array* pArray = pDash->GetArrayAt(0);
        if (!pArray)
          break;

        SetLineDash(pArray, pDash->GetNumberAt(1), 1.0f);
        break;
      }
      case FXBSTR_ID('R', 'I', 0, 0):
        m_GeneralState.SetRenderIntent(pObject->GetString());
        break;
      case FXBSTR_ID('F', 'o', 'n', 't'): {
        CPDF_Array* pFont = pObject->AsArray();
        if (!pFont)
          break;

        m_TextState.GetModify()->m_FontSize = pFont->GetNumberAt(1);
        m_TextState.SetFont(pParser->FindFont(pFont->GetStringAt(0)));
        break;
      }
      case FXBSTR_ID('T', 'R', 0, 0):
        if (pGS->KeyExist("TR2")) {
          continue;
        }
      case FXBSTR_ID('T', 'R', '2', 0):
        pGeneralState->m_pTR =
            (pObject && !pObject->IsName()) ? pObject : nullptr;
        break;
      case FXBSTR_ID('B', 'M', 0, 0): {
        CPDF_Array* pArray = pObject->AsArray();
        CFX_ByteString mode =
            pArray ? pArray->GetStringAt(0) : pObject->GetString();

        pGeneralState->SetBlendMode(mode);
        if (pGeneralState->m_BlendType > FXDIB_BLEND_MULTIPLY) {
          pParser->GetPageObjectHolder()->SetBackgroundAlphaNeeded(TRUE);
        }
        break;
      }
      case FXBSTR_ID('S', 'M', 'a', 's'):
        if (ToDictionary(pObject)) {
          pGeneralState->m_pSoftMask = pObject;
          FXSYS_memcpy(pGeneralState->m_SMaskMatrix,
                       &pParser->GetCurStates()->m_CTM, sizeof(CFX_Matrix));
        } else {
          pGeneralState->m_pSoftMask = NULL;
        }
        break;
      case FXBSTR_ID('C', 'A', 0, 0):
        pGeneralState->m_StrokeAlpha = ClipFloat(pObject->GetNumber());
        break;
      case FXBSTR_ID('c', 'a', 0, 0):
        pGeneralState->m_FillAlpha = ClipFloat(pObject->GetNumber());
        break;
      case FXBSTR_ID('O', 'P', 0, 0):
        pGeneralState->m_StrokeOP = pObject->GetInteger();
        if (!pGS->KeyExist("op")) {
          pGeneralState->m_FillOP = pObject->GetInteger();
        }
        break;
      case FXBSTR_ID('o', 'p', 0, 0):
        pGeneralState->m_FillOP = pObject->GetInteger();
        break;
      case FXBSTR_ID('O', 'P', 'M', 0):
        pGeneralState->m_OPMode = pObject->GetInteger();
        break;
      case FXBSTR_ID('B', 'G', 0, 0):
        if (pGS->KeyExist("BG2")) {
          continue;
        }
      case FXBSTR_ID('B', 'G', '2', 0):
        pGeneralState->m_pBG = pObject;
        break;
      case FXBSTR_ID('U', 'C', 'R', 0):
        if (pGS->KeyExist("UCR2")) {
          continue;
        }
      case FXBSTR_ID('U', 'C', 'R', '2'):
        pGeneralState->m_pUCR = pObject;
        break;
      case FXBSTR_ID('H', 'T', 0, 0):
        pGeneralState->m_pHT = pObject;
        break;
      case FXBSTR_ID('F', 'L', 0, 0):
        pGeneralState->m_Flatness = pObject->GetNumber();
        break;
      case FXBSTR_ID('S', 'M', 0, 0):
        pGeneralState->m_Smoothness = pObject->GetNumber();
        break;
      case FXBSTR_ID('S', 'A', 0, 0):
        pGeneralState->m_StrokeAdjust = pObject->GetInteger();
        break;
      case FXBSTR_ID('A', 'I', 'S', 0):
        pGeneralState->m_AlphaSource = pObject->GetInteger();
        break;
      case FXBSTR_ID('T', 'K', 0, 0):
        pGeneralState->m_TextKnockout = pObject->GetInteger();
        break;
    }
  }
  pGeneralState->m_Matrix = m_CTM;
}
CPDF_ContentMarkItem::CPDF_ContentMarkItem() {
  m_ParamType = None;
}
CPDF_ContentMarkItem::CPDF_ContentMarkItem(const CPDF_ContentMarkItem& src) {
  m_MarkName = src.m_MarkName;
  m_ParamType = src.m_ParamType;
  if (m_ParamType == DirectDict) {
    m_pParam = ToDictionary(src.m_pParam->Clone());
  } else {
    m_pParam = src.m_pParam;
  }
}
CPDF_ContentMarkItem::~CPDF_ContentMarkItem() {
  if (m_ParamType == DirectDict && m_pParam)
    m_pParam->Release();
}
FX_BOOL CPDF_ContentMarkItem::HasMCID() const {
  if (m_pParam &&
      (m_ParamType == DirectDict || m_ParamType == PropertiesDict)) {
    return m_pParam->KeyExist("MCID");
  }
  return FALSE;
}

CPDF_ContentMarkData::CPDF_ContentMarkData(const CPDF_ContentMarkData& src)
    : m_Marks(src.m_Marks) {}

int CPDF_ContentMarkData::CountItems() const {
  return pdfium::CollectionSize<int>(m_Marks);
}

int CPDF_ContentMarkData::GetMCID() const {
  for (const auto& mark : m_Marks) {
    CPDF_ContentMarkItem::ParamType type = mark.GetParamType();
    if (type == CPDF_ContentMarkItem::PropertiesDict ||
        type == CPDF_ContentMarkItem::DirectDict) {
      CPDF_Dictionary* pDict = mark.GetParam();
      if (pDict->KeyExist("MCID"))
        return pDict->GetIntegerBy("MCID");
    }
  }
  return -1;
}

void CPDF_ContentMarkData::AddMark(const CFX_ByteString& name,
                                   CPDF_Dictionary* pDict,
                                   FX_BOOL bDirect) {
  CPDF_ContentMarkItem item;
  item.SetName(name);
  if (pDict) {
    if (bDirect) {
      item.SetParam(CPDF_ContentMarkItem::DirectDict,
                    ToDictionary(pDict->Clone()));
    } else {
      item.SetParam(CPDF_ContentMarkItem::PropertiesDict, pDict);
    }
  }
  m_Marks.push_back(item);
}

void CPDF_ContentMarkData::DeleteLastMark() {
  if (!m_Marks.empty())
    m_Marks.pop_back();
}

FX_BOOL CPDF_ContentMark::HasMark(const CFX_ByteStringC& mark) const {
  if (!m_pObject) {
    return FALSE;
  }
  for (int i = 0; i < m_pObject->CountItems(); i++) {
    CPDF_ContentMarkItem& item = m_pObject->GetItem(i);
    if (item.GetName() == mark) {
      return TRUE;
    }
  }
  return FALSE;
}
FX_BOOL CPDF_ContentMark::LookupMark(const CFX_ByteStringC& mark,
                                     CPDF_Dictionary*& pDict) const {
  if (!m_pObject) {
    return FALSE;
  }
  for (int i = 0; i < m_pObject->CountItems(); i++) {
    CPDF_ContentMarkItem& item = m_pObject->GetItem(i);
    if (item.GetName() == mark) {
      pDict = NULL;
      if (item.GetParamType() == CPDF_ContentMarkItem::PropertiesDict ||
          item.GetParamType() == CPDF_ContentMarkItem::DirectDict) {
        pDict = item.GetParam();
      }
      return TRUE;
    }
  }
  return FALSE;
}
