CPDF_ColorSpace* CPDF_StreamContentParser::FindColorSpace(
    const CFX_ByteString& name) {
  if (name == "Pattern") {
    return CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
  }
  if (name == "DeviceGray" || name == "DeviceCMYK" || name == "DeviceRGB") {
    CFX_ByteString defname = "Default";
    defname += name.Mid(7);
    CPDF_Object* pDefObj = FindResourceObj("ColorSpace", defname);
    if (!pDefObj) {
      if (name == "DeviceGray") {
        return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY);
      }
      if (name == "DeviceRGB") {
        return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB);
      }
      return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK);
    }
    return m_pDocument->LoadColorSpace(pDefObj);
  }
  CPDF_Object* pCSObj = FindResourceObj("ColorSpace", name);
  if (!pCSObj) {
    m_bResourceMissing = TRUE;
    return NULL;
  }
  return m_pDocument->LoadColorSpace(pCSObj);
}
void CPDF_StreamContentParser::Handle_SetExtendGraphState() {
  CFX_ByteString name = GetString(0);
  CPDF_Dictionary* pGS = ToDictionary(FindResourceObj("ExtGState", name));
  if (!pGS) {
    m_bResourceMissing = TRUE;
    return;
  }
  m_pCurStates->ProcessExtGS(pGS, this);
}
CPDF_Pattern* CPDF_StreamContentParser::FindPattern(const CFX_ByteString& name,
                                                    FX_BOOL bShading) {
  CPDF_Object* pPattern =
      FindResourceObj(bShading ? "Shading" : "Pattern", name);
  if (!pPattern || (!pPattern->IsDictionary() && !pPattern->IsStream())) {
    m_bResourceMissing = TRUE;
    return NULL;
  }
  return m_pDocument->LoadPattern(pPattern, bShading,
                                  &m_pCurStates->m_ParentMatrix);
}
void CPDF_StreamContentParser::Handle_ExecuteXObject() {
  CFX_ByteString name = GetString(0);
  if (name == m_LastImageName && m_pLastImage && m_pLastImage->GetStream() &&
      m_pLastImage->GetStream()->GetObjNum()) {
    AddImage(nullptr, m_pLastImage, FALSE);
    return;
  }

  if (m_Options.m_bTextOnly) {
    if (!m_pResources)
      return;

    CPDF_Dictionary* pList = m_pResources->GetDict("XObject");
    if (!pList && m_pPageResources && m_pResources != m_pPageResources)
      pList = m_pPageResources->GetDict("XObject");
    if (!pList)
      return;
    CPDF_Reference* pRes = ToReference(pList->GetElement(name));
    if (!pRes)
      return;

    FX_BOOL bForm;
    if (m_pDocument->IsFormStream(pRes->GetRefObjNum(), bForm) && !bForm)
      return;
  }

  CPDF_Stream* pXObject = ToStream(FindResourceObj("XObject", name));
  if (!pXObject) {
    m_bResourceMissing = TRUE;
    return;
  }

  CFX_ByteStringC type = pXObject->GetDict()
                             ? pXObject->GetDict()->GetConstString("Subtype")
                             : CFX_ByteStringC();
  if (type == "Image") {
    if (m_Options.m_bTextOnly) {
      return;
    }
    CPDF_ImageObject* pObj = AddImage(pXObject, NULL, FALSE);
    m_LastImageName = name;
    m_pLastImage = pObj->m_pImage;
    if (!m_pObjectList->m_bHasImageMask)
      m_pObjectList->m_bHasImageMask = m_pLastImage->IsMask();
  } else if (type == "Form") {
    AddForm(pXObject);
  } else {
    return;
  }
}
CPDF_Font* CPDF_StreamContentParser::FindFont(const CFX_ByteString& name) {
  CPDF_Dictionary* pFontDict = ToDictionary(FindResourceObj("Font", name));
  if (!pFontDict) {
    m_bResourceMissing = TRUE;
    return CPDF_Font::GetStockFont(m_pDocument, "Helvetica");
  }

  CPDF_Font* pFont = m_pDocument->LoadFont(pFontDict);
  if (pFont && pFont->GetType3Font()) {
    pFont->GetType3Font()->SetPageResources(m_pResources);
    pFont->GetType3Font()->CheckType3FontMetrics();
  }
  return pFont;
}
void CPDF_StreamContentParser::Handle_BeginMarkedContent_Dictionary() {
  if (!m_Options.m_bMarkedContent) {
    return;
  }
  CFX_ByteString tag = GetString(1);
  CPDF_Object* pProperty = GetObject(0);
  if (!pProperty) {
    return;
  }
  FX_BOOL bDirect = TRUE;
  if (pProperty->IsName()) {
    pProperty = FindResourceObj("Properties", pProperty->GetString());
    if (!pProperty)
      return;
    bDirect = FALSE;
  }
  if (CPDF_Dictionary* pDict = pProperty->AsDictionary()) {
    m_CurContentMark.GetModify()->AddMark(tag, pDict, bDirect);
  }
}
void CPDF_StreamContentParser::EndImageDict()
{
    if (m_StringBuf.GetSize() != m_LastImageDict.GetSize() ||
            FXSYS_memcmp32(m_StringBuf.GetBuffer(), m_LastImageDict.GetBuffer(), m_StringBuf.GetSize())) {
        m_WordState = 0;
        StartDict();
        InputData(m_StringBuf.GetBuffer(), m_StringBuf.GetSize());
        Finish();
        m_bSameLastDict = FALSE;
        if (m_pLastImageDict && m_bReleaseLastDict) {
            m_pLastImageDict->Release();
            m_pLastImageDict = NULL;
        }
        if (!m_ObjectSize) {
            m_InlineImageState = 0;
            return;
        }
        m_pLastImageDict = (CPDF_Dictionary*)m_pObjectStack[--m_ObjectSize];
        m_bReleaseLastDict = !m_pObjectState[m_ObjectSize];
        m_pObjectState[m_ObjectSize] = FALSE;
        _PDF_ReplaceAbbr(m_pLastImageDict);
        m_LastImageDict.TakeOver(m_StringBuf);
        if (m_pLastImageDict->KeyExist(FX_BSTRC("ColorSpace"))) {
            CPDF_Object* pCSObj = m_pLastImageDict->GetElementValue(FX_BSTRC("ColorSpace"));
            if (pCSObj->GetType() == PDFOBJ_NAME) {
                CFX_ByteString name = pCSObj->GetString();
                if (name != FX_BSTRC("DeviceRGB") && name != FX_BSTRC("DeviceGray") && name != FX_BSTRC("DeviceCMYK")) {
                    pCSObj = FindResourceObj(FX_BSTRC("ColorSpace"), name);
                    if (pCSObj) {
                        if (!pCSObj->GetObjNum()) {
                            pCSObj = pCSObj->Clone();
                        }
                        m_pLastImageDict->SetAt(FX_BSTRC("ColorSpace"), pCSObj, m_pDocument);
                    }
                }
            }
        }
    } else {
        m_bSameLastDict = TRUE;
    }
    m_ImageSrcBuf.Clear();
    if (m_pLastCloneImageDict) {
        m_pLastCloneImageDict->Release();
    }
    m_pLastCloneImageDict = (CPDF_Dictionary*)m_pLastImageDict->Clone();
    if (m_pLastCloneImageDict->KeyExist(FX_BSTRC("Filter"))) {
        m_WordState = 10;
        m_InlineImageState = 0;
    } else {
        int width = m_pLastCloneImageDict->GetInteger(FX_BSTRC("Width"));
        int height = m_pLastCloneImageDict->GetInteger(FX_BSTRC("Height"));
        int OrigSize = 0;
        CPDF_Object* pCSObj = m_pLastCloneImageDict->GetElementValue(FX_BSTRC("ColorSpace"));
        if (pCSObj != NULL) {
            int bpc = m_pLastCloneImageDict->GetInteger(FX_BSTRC("BitsPerComponent"));
            int nComponents = 1;
            CPDF_ColorSpace* pCS = m_pDocument->LoadColorSpace(pCSObj);
            if (pCS == NULL) {
                nComponents = 3;
            } else {
                nComponents = pCS->CountComponents();
                m_pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
            }
            int pitch = (width * bpc * nComponents + 7) / 8;
            OrigSize = pitch * height;
        } else {
            OrigSize = ((width + 7) / 8) * height;
        }
        m_ImageSrcBuf.AppendBlock(NULL, OrigSize);
        m_WordState = 11;
        m_InlineImageState = 0;
    }
}
void CPDF_StreamContentParser::Handle_BeginImage()
{
    FX_FILESIZE savePos = m_pSyntax->GetPos();
    CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
    while (1) {
        CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement();
        if (type == CPDF_StreamParser::Keyword) {
            CFX_ByteString bsKeyword(m_pSyntax->GetWordBuf(), m_pSyntax->GetWordSize());
            if (bsKeyword != FX_BSTRC("ID")) {
                m_pSyntax->SetPos(savePos);
                pDict->Release();
                return;
            }
        }
        if (type != CPDF_StreamParser::Name) {
            break;
        }
        CFX_ByteString key((const FX_CHAR*)m_pSyntax->GetWordBuf() + 1, m_pSyntax->GetWordSize() - 1);
        CPDF_Object* pObj = m_pSyntax->ReadNextObject();
        if (!key.IsEmpty()) {
            pDict->SetAt(key, pObj, m_pDocument);
        } else if (pObj) {
            pObj->Release();
        }
    }
    _PDF_ReplaceAbbr(pDict);
    CPDF_Object* pCSObj = NULL;
    if (pDict->KeyExist(FX_BSTRC("ColorSpace"))) {
        pCSObj = pDict->GetElementValue(FX_BSTRC("ColorSpace"));
        if (pCSObj->GetType() == PDFOBJ_NAME) {
            CFX_ByteString name = pCSObj->GetString();
            if (name != FX_BSTRC("DeviceRGB") && name != FX_BSTRC("DeviceGray") && name != FX_BSTRC("DeviceCMYK")) {
                pCSObj = FindResourceObj(FX_BSTRC("ColorSpace"), name);
                if (pCSObj && !pCSObj->GetObjNum()) {
                    pCSObj = pCSObj->Clone();
                    pDict->SetAt(FX_BSTRC("ColorSpace"), pCSObj, m_pDocument);
                }
            }
        }
    }
    CPDF_Stream* pStream = m_pSyntax->ReadInlineStream(m_pDocument, pDict, pCSObj, m_Options.m_bDecodeInlineImage);
    while (1) {
        CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement();
        if (type == CPDF_StreamParser::EndOfData) {
            break;
        }
        if (type != CPDF_StreamParser::Keyword) {
            continue;
        }
        if (m_pSyntax->GetWordSize() == 2 && m_pSyntax->GetWordBuf()[0] == 'E' &&
                m_pSyntax->GetWordBuf()[1] == 'I') {
            break;
        }
    }
    if (m_Options.m_bTextOnly) {
        if (pStream) {
            pStream->Release();
        } else {
            pDict->Release();
        }
        return;
    }
    pDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Image"));
    CPDF_ImageObject *pImgObj = AddImage(pStream, NULL, TRUE);
    if (!pImgObj) {
        if (pStream) {
            pStream->Release();
        } else {
            pDict->Release();
        }
    }
}