Replace FX_NEW with new, remove tests from fpdfapi
[pdfium.git] / core / src / fpdfapi / fpdf_page / fpdf_page_parser_old.cpp
index 2f0a18d..952fe1d 100644 (file)
-// Copyright 2014 PDFium Authors. All rights reserved.\r
-// Use of this source code is governed by a BSD-style license that can be\r
-// found in the LICENSE file.\r
\r
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
-\r
-#include "../../../include/fpdfapi/fpdf_page.h"\r
-#include "../../../include/fpdfapi/fpdf_module.h"\r
-#include "../../../include/fxcodec/fx_codec.h"\r
-#include "pageint.h"\r
-#include <limits.h>\r
-extern const FX_LPCSTR _PDF_OpCharType =\r
-    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"\r
-    "IIVIIIIVIIVIIIIIVVIIIIIIIIIIIIII"\r
-    "IIVVVVVVIVVVVVVIVVVVVIIVVIIIIIII"\r
-    "IIVVVVVVVVVVVVVVIVVVIIVVIVVIIIII"\r
-    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"\r
-    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"\r
-    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"\r
-    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII";\r
-FX_BOOL _PDF_HasInvalidOpChar(FX_LPCSTR op)\r
-{\r
-    if(!op) {\r
-        return FALSE;\r
-    }\r
-    FX_BYTE ch;\r
-    while((ch = *op++)) {\r
-        if(_PDF_OpCharType[ch] == 'I') {\r
-            return TRUE;\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-FX_DWORD CPDF_StreamContentParser::Parse(FX_LPCBYTE pData, FX_DWORD dwSize, FX_DWORD max_cost)\r
-{\r
-    if (m_Level > _FPDF_MAX_FORM_LEVEL_) {\r
-        return dwSize;\r
-    }\r
-    FX_DWORD InitObjCount = m_pObjectList->CountObjects();\r
-    CPDF_StreamParser syntax(pData, dwSize);\r
-    m_pSyntax = &syntax;\r
-    m_CompatCount = 0;\r
-    while (1) {\r
-        FX_DWORD cost = m_pObjectList->CountObjects() - InitObjCount;\r
-        if (max_cost && cost >= max_cost) {\r
-            break;\r
-        }\r
-        switch (syntax.ParseNextElement()) {\r
-            case CPDF_StreamParser::EndOfData:\r
-                return m_pSyntax->GetPos();\r
-            case CPDF_StreamParser::Keyword:\r
-                if(!OnOperator((char*)syntax.GetWordBuf()) && _PDF_HasInvalidOpChar((char*)syntax.GetWordBuf())) {\r
-                    m_bAbort = TRUE;\r
-                }\r
-                if (m_bAbort) {\r
-                    return m_pSyntax->GetPos();\r
-                }\r
-                ClearAllParams();\r
-                break;\r
-            case CPDF_StreamParser::Number:\r
-                AddNumberParam((char*)syntax.GetWordBuf(), syntax.GetWordSize());\r
-                break;\r
-            case CPDF_StreamParser::Name:\r
-                AddNameParam((FX_LPCSTR)syntax.GetWordBuf() + 1, syntax.GetWordSize() - 1);\r
-                break;\r
-            default:\r
-                AddObjectParam(syntax.GetObject());\r
-        }\r
-    }\r
-    return m_pSyntax->GetPos();\r
-}\r
-void _PDF_ReplaceAbbr(CPDF_Object* pObj);\r
-void CPDF_StreamContentParser::Handle_BeginImage()\r
-{\r
-    FX_FILESIZE savePos = m_pSyntax->GetPos();\r
-    CPDF_Dictionary* pDict = CPDF_Dictionary::Create();\r
-    while (1) {\r
-        CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement();\r
-        if (type == CPDF_StreamParser::Keyword) {\r
-            CFX_ByteString bsKeyword(m_pSyntax->GetWordBuf(), m_pSyntax->GetWordSize());\r
-            if (bsKeyword != FX_BSTRC("ID")) {\r
-                m_pSyntax->SetPos(savePos);\r
-                pDict->Release();\r
-                return;\r
-            }\r
-        }\r
-        if (type != CPDF_StreamParser::Name) {\r
-            break;\r
-        }\r
-        CFX_ByteString key((FX_LPCSTR)m_pSyntax->GetWordBuf() + 1, m_pSyntax->GetWordSize() - 1);\r
-        CPDF_Object* pObj = m_pSyntax->ReadNextObject();\r
-        if (!key.IsEmpty()) {\r
-            pDict->SetAt(key, pObj, m_pDocument);\r
-        } else {\r
-            pObj->Release();\r
-        }\r
-    }\r
-    _PDF_ReplaceAbbr(pDict);\r
-    CPDF_Object* pCSObj = NULL;\r
-    if (pDict->KeyExist(FX_BSTRC("ColorSpace"))) {\r
-        pCSObj = pDict->GetElementValue(FX_BSTRC("ColorSpace"));\r
-        if (pCSObj->GetType() == PDFOBJ_NAME) {\r
-            CFX_ByteString name = pCSObj->GetString();\r
-            if (name != FX_BSTRC("DeviceRGB") && name != FX_BSTRC("DeviceGray") && name != FX_BSTRC("DeviceCMYK")) {\r
-                pCSObj = FindResourceObj(FX_BSTRC("ColorSpace"), name);\r
-                if (pCSObj && !pCSObj->GetObjNum()) {\r
-                    pCSObj = pCSObj->Clone();\r
-                    pDict->SetAt(FX_BSTRC("ColorSpace"), pCSObj, m_pDocument);\r
-                }\r
-            }\r
-        }\r
-    }\r
-    CPDF_Stream* pStream = m_pSyntax->ReadInlineStream(m_pDocument, pDict, pCSObj, m_Options.m_bDecodeInlineImage);\r
-    while (1) {\r
-        CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement();\r
-        if (type == CPDF_StreamParser::EndOfData) {\r
-            break;\r
-        }\r
-        if (type != CPDF_StreamParser::Keyword) {\r
-            continue;\r
-        }\r
-        if (m_pSyntax->GetWordSize() == 2 && m_pSyntax->GetWordBuf()[0] == 'E' &&\r
-                m_pSyntax->GetWordBuf()[1] == 'I') {\r
-            break;\r
-        }\r
-    }\r
-    if (m_Options.m_bTextOnly) {\r
-        if (pStream) {\r
-            pStream->Release();\r
-        } else {\r
-            pDict->Release();\r
-        }\r
-        return;\r
-    }\r
-    pDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Image"));\r
-    CPDF_ImageObject *pImgObj = AddImage(pStream, NULL, TRUE);\r
-    if (!pImgObj) {\r
-        if (pStream) {\r
-            pStream->Release();\r
-        } else {\r
-            pDict->Release();\r
-        }\r
-    }\r
-}\r
-void CPDF_StreamContentParser::ParsePathObject()\r
-{\r
-    FX_FLOAT params[6] = {0};\r
-    int nParams = 0;\r
-    int last_pos = m_pSyntax->GetPos();\r
-    while (1) {\r
-        CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement();\r
-        FX_BOOL bProcessed = TRUE;\r
-        switch (type) {\r
-            case CPDF_StreamParser::EndOfData:\r
-                return;\r
-            case CPDF_StreamParser::Keyword: {\r
-                    int len = m_pSyntax->GetWordSize();\r
-                    if (len == 1) {\r
-                        switch (m_pSyntax->GetWordBuf()[0]) {\r
-                            case 'm':\r
-                                AddPathPoint(params[0], params[1], FXPT_MOVETO);\r
-                                nParams = 0;\r
-                                break;\r
-                            case 'l':\r
-                                AddPathPoint(params[0], params[1], FXPT_LINETO);\r
-                                nParams = 0;\r
-                                break;\r
-                            case 'c':\r
-                                AddPathPoint(params[0], params[1], FXPT_BEZIERTO);\r
-                                AddPathPoint(params[2], params[3], FXPT_BEZIERTO);\r
-                                AddPathPoint(params[4], params[5], FXPT_BEZIERTO);\r
-                                nParams = 0;\r
-                                break;\r
-                            case 'v':\r
-                                AddPathPoint(m_PathCurrentX, m_PathCurrentY, FXPT_BEZIERTO);\r
-                                AddPathPoint(params[0], params[1], FXPT_BEZIERTO);\r
-                                AddPathPoint(params[2], params[3], FXPT_BEZIERTO);\r
-                                nParams = 0;\r
-                                break;\r
-                            case 'y':\r
-                                AddPathPoint(params[0], params[1], FXPT_BEZIERTO);\r
-                                AddPathPoint(params[2], params[3], FXPT_BEZIERTO);\r
-                                AddPathPoint(params[2], params[3], FXPT_BEZIERTO);\r
-                                nParams = 0;\r
-                                break;\r
-                            case 'h':\r
-                                Handle_ClosePath();\r
-                                nParams = 0;\r
-                                break;\r
-                            default:\r
-                                bProcessed = FALSE;\r
-                                break;\r
-                        }\r
-                    } else if (len == 2) {\r
-                        if (m_pSyntax->GetWordBuf()[0] == 'r' && m_pSyntax->GetWordBuf()[1] == 'e') {\r
-                            AddPathRect(params[0], params[1], params[2], params[3]);\r
-                            nParams = 0;\r
-                        } else {\r
-                            bProcessed = FALSE;\r
-                        }\r
-                    } else {\r
-                        bProcessed = FALSE;\r
-                    }\r
-                    if (bProcessed) {\r
-                        last_pos = m_pSyntax->GetPos();\r
-                    }\r
-                    break;\r
-                }\r
-            case CPDF_StreamParser::Number: {\r
-                    if (nParams == 6) {\r
-                        break;\r
-                    }\r
-                    FX_BOOL bInteger;\r
-                    int value;\r
-                    FX_atonum(CFX_ByteStringC(m_pSyntax->GetWordBuf(), m_pSyntax->GetWordSize()), bInteger, &value);\r
-                    params[nParams++] = bInteger ? (FX_FLOAT)value : *(FX_FLOAT*)&value;\r
-                    break;\r
-                }\r
-            default:\r
-                bProcessed = FALSE;\r
-        }\r
-        if (!bProcessed) {\r
-            m_pSyntax->SetPos(last_pos);\r
-            return;\r
-        }\r
-    }\r
-}\r
-CPDF_StreamParser::CPDF_StreamParser(const FX_BYTE* pData, FX_DWORD dwSize)\r
-{\r
-    m_pBuf = pData;\r
-    m_Size = dwSize;\r
-    m_Pos = 0;\r
-    m_pLastObj = NULL;\r
-}\r
-CPDF_StreamParser::~CPDF_StreamParser()\r
-{\r
-    if (m_pLastObj) {\r
-        m_pLastObj->Release();\r
-    }\r
-}\r
-FX_DWORD _DecodeAllScanlines(ICodec_ScanlineDecoder* pDecoder, FX_LPBYTE& dest_buf, FX_DWORD& dest_size)\r
-{\r
-    if (pDecoder == NULL) {\r
-        return (FX_DWORD) - 1;\r
-    }\r
-    int ncomps = pDecoder->CountComps();\r
-    int bpc = pDecoder->GetBPC();\r
-    int width = pDecoder->GetWidth();\r
-    int height = pDecoder->GetHeight();\r
-    int pitch = (width * ncomps * bpc + 7) / 8;\r
-    if (height == 0 || pitch > (1 << 30) / height) {\r
-        delete pDecoder;\r
-        return -1;\r
-    }\r
-    dest_size = pitch * height;\r
-    dest_buf = FX_Alloc( FX_BYTE, dest_size);\r
-    for (int row = 0; row < height; row ++) {\r
-        FX_LPBYTE pLine = pDecoder->GetScanline(row);\r
-        if (pLine == NULL) {\r
-            break;\r
-        }\r
-        FXSYS_memcpy32(dest_buf + row * pitch, pLine, pitch);\r
-    }\r
-    FX_DWORD srcoff = pDecoder->GetSrcOffset();\r
-    delete pDecoder;\r
-    return srcoff;\r
-}\r
-ICodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,\r
-        const CPDF_Dictionary* pParams);\r
-FX_DWORD _A85Decode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size);\r
-FX_DWORD _HexDecode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size);\r
-FX_DWORD FPDFAPI_FlateOrLZWDecode(FX_BOOL bLZW, const FX_BYTE* src_buf, FX_DWORD src_size, CPDF_Dictionary* pParams,\r
-                                  FX_DWORD estimated_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size);\r
-FX_DWORD PDF_DecodeInlineStream(const FX_BYTE* src_buf, FX_DWORD limit,\r
-                                int width, int height, CFX_ByteString& decoder,\r
-                                CPDF_Dictionary* pParam, FX_LPBYTE& dest_buf, FX_DWORD& dest_size)\r
-{\r
-    if (decoder == FX_BSTRC("CCITTFaxDecode") || decoder == FX_BSTRC("CCF")) {\r
-        ICodec_ScanlineDecoder* pDecoder = FPDFAPI_CreateFaxDecoder(src_buf, limit, width, height, pParam);\r
-        return _DecodeAllScanlines(pDecoder, dest_buf, dest_size);\r
-    } else if (decoder == FX_BSTRC("ASCII85Decode") || decoder == FX_BSTRC("A85")) {\r
-        return _A85Decode(src_buf, limit, dest_buf, dest_size);\r
-    } else if (decoder == FX_BSTRC("ASCIIHexDecode") || decoder == FX_BSTRC("AHx")) {\r
-        return _HexDecode(src_buf, limit, dest_buf, dest_size);\r
-    } else if (decoder == FX_BSTRC("FlateDecode") || decoder == FX_BSTRC("Fl")) {\r
-        return FPDFAPI_FlateOrLZWDecode(FALSE, src_buf, limit, pParam, dest_size, dest_buf, dest_size);\r
-    } else if (decoder == FX_BSTRC("LZWDecode") || decoder == FX_BSTRC("LZW")) {\r
-        return FPDFAPI_FlateOrLZWDecode(TRUE, src_buf, limit, pParam, 0, dest_buf, dest_size);\r
-    } else if (decoder == FX_BSTRC("DCTDecode") || decoder == FX_BSTRC("DCT")) {\r
-        ICodec_ScanlineDecoder* pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(\r
-                                               src_buf, limit, width, height, 0, pParam ? pParam->GetInteger(FX_BSTRC("ColorTransform"), 1) : 1);\r
-        return _DecodeAllScanlines(pDecoder, dest_buf, dest_size);\r
-    } else if (decoder == FX_BSTRC("RunLengthDecode") || decoder == FX_BSTRC("RL")) {\r
-        return RunLengthDecode(src_buf, limit, dest_buf, dest_size);\r
-    }\r
-    dest_size = 0;\r
-    dest_buf = 0;\r
-    return (FX_DWORD) - 1;\r
-}\r
-extern const FX_LPCSTR _PDF_CharType;\r
-CPDF_Stream* CPDF_StreamParser::ReadInlineStream(CPDF_Document* pDoc, CPDF_Dictionary* pDict, CPDF_Object* pCSObj, FX_BOOL bDecode)\r
-{\r
-    if (m_Pos == m_Size) {\r
-        return NULL;\r
-    }\r
-    if (_PDF_CharType[m_pBuf[m_Pos]] == 'W') {\r
-        m_Pos ++;\r
-    }\r
-    CFX_ByteString Decoder;\r
-    CPDF_Dictionary* pParam = NULL;\r
-    CPDF_Object* pFilter = pDict->GetElementValue(FX_BSTRC("Filter"));\r
-    if (pFilter == NULL) {\r
-    } else if (pFilter->GetType() == PDFOBJ_ARRAY) {\r
-        Decoder = ((CPDF_Array*)pFilter)->GetString(0);\r
-        CPDF_Array* pParams = pDict->GetArray(FX_BSTRC("DecodeParms"));\r
-        if (pParams) {\r
-            pParam = pParams->GetDict(0);\r
-        }\r
-    } else {\r
-        Decoder = pFilter->GetString();\r
-        pParam = pDict->GetDict(FX_BSTRC("DecodeParms"));\r
-    }\r
-    FX_DWORD width = pDict->GetInteger(FX_BSTRC("Width"));\r
-    FX_DWORD height = pDict->GetInteger(FX_BSTRC("Height"));\r
-    FX_DWORD OrigSize = 0;\r
-    if (pCSObj != NULL) {\r
-        FX_DWORD bpc = pDict->GetInteger(FX_BSTRC("BitsPerComponent"));\r
-        FX_DWORD nComponents = 1;\r
-        CPDF_ColorSpace* pCS = pDoc->LoadColorSpace(pCSObj);\r
-        if (pCS == NULL) {\r
-            nComponents = 3;\r
-        } else {\r
-            nComponents = pCS->CountComponents();\r
-            pDoc->GetPageData()->ReleaseColorSpace(pCSObj);\r
-        }\r
-        FX_DWORD pitch = width;\r
-        if (bpc && pitch > INT_MAX / bpc) {\r
-            return NULL;\r
-        }\r
-        pitch *= bpc;\r
-        if (nComponents && pitch > INT_MAX / nComponents) {\r
-            return NULL;\r
-        }\r
-        pitch *= nComponents;\r
-        if (pitch > INT_MAX - 7) {\r
-            return NULL;\r
-        }\r
-        pitch += 7;\r
-        pitch /= 8;\r
-        OrigSize = pitch;\r
-    } else {\r
-        if (width > INT_MAX - 7) {\r
-            return NULL;\r
-        }\r
-        OrigSize = ((width + 7) / 8);\r
-    }\r
-    if (height && OrigSize > INT_MAX / height) {\r
-        return NULL;\r
-    }\r
-    OrigSize *= height;\r
-    FX_LPBYTE pData = NULL;\r
-    FX_DWORD dwStreamSize;\r
-    if (Decoder.IsEmpty()) {\r
-        if (OrigSize > m_Size - m_Pos) {\r
-            OrigSize = m_Size - m_Pos;\r
-        }\r
-        pData = FX_Alloc(FX_BYTE, OrigSize);\r
-        FXSYS_memcpy32(pData, m_pBuf + m_Pos, OrigSize);\r
-        dwStreamSize = OrigSize;\r
-        m_Pos += OrigSize;\r
-    } else {\r
-        FX_DWORD dwDestSize = OrigSize;\r
-        dwStreamSize = PDF_DecodeInlineStream(m_pBuf + m_Pos, m_Size - m_Pos, width, height, Decoder, pParam,\r
-                                              pData, dwDestSize);\r
-        if ((int)dwStreamSize < 0) {\r
-            return NULL;\r
-        }\r
-        if (bDecode) {\r
-            m_Pos += dwStreamSize;\r
-            dwStreamSize = dwDestSize;\r
-            if (pFilter->GetType() == PDFOBJ_ARRAY) {\r
-                ((CPDF_Array*)pFilter)->RemoveAt(0);\r
-                CPDF_Array* pParams = pDict->GetArray(FX_BSTRC("DecodeParms"));\r
-                if (pParams) {\r
-                    pParams->RemoveAt(0);\r
-                }\r
-            } else {\r
-                pDict->RemoveAt(FX_BSTRC("Filter"));\r
-                pDict->RemoveAt(FX_BSTRC("DecodeParms"));\r
-            }\r
-        } else {\r
-            if (pData) {\r
-                FX_Free(pData);\r
-            }\r
-            FX_DWORD dwSavePos = m_Pos;\r
-            m_Pos += dwStreamSize;\r
-            while (1) {\r
-                FX_DWORD dwPrevPos = m_Pos;\r
-                CPDF_StreamParser::SyntaxType type = ParseNextElement();\r
-                if (type == CPDF_StreamParser::EndOfData) {\r
-                    break;\r
-                }\r
-                if (type != CPDF_StreamParser::Keyword) {\r
-                    dwStreamSize += m_Pos - dwPrevPos;\r
-                    continue;\r
-                }\r
-                if (GetWordSize() == 2 && GetWordBuf()[0] == 'E' &&\r
-                        GetWordBuf()[1] == 'I') {\r
-                    m_Pos = dwPrevPos;\r
-                    break;\r
-                }\r
-                dwStreamSize += m_Pos - dwPrevPos;\r
-            }\r
-            m_Pos = dwSavePos;\r
-            pData = FX_Alloc(FX_BYTE, dwStreamSize);\r
-            FXSYS_memcpy32(pData, m_pBuf + m_Pos, dwStreamSize);\r
-            m_Pos += dwStreamSize;\r
-        }\r
-    }\r
-    pDict->SetAtInteger(FX_BSTRC("Length"), (int)dwStreamSize);\r
-    return CPDF_Stream::Create(pData, dwStreamSize, pDict);\r
-}\r
-#define MAX_WORD_BUFFER 256\r
-#define MAX_STRING_LENGTH      32767\r
-#define FXDWORD_TRUE FXDWORD_FROM_LSBFIRST(0x65757274)\r
-#define FXDWORD_NULL FXDWORD_FROM_LSBFIRST(0x6c6c756e)\r
-#define FXDWORD_FALS FXDWORD_FROM_LSBFIRST(0x736c6166)\r
-CPDF_StreamParser::SyntaxType CPDF_StreamParser::ParseNextElement()\r
-{\r
-    if (m_pLastObj) {\r
-        m_pLastObj->Release();\r
-        m_pLastObj = NULL;\r
-    }\r
-    m_WordSize = 0;\r
-    FX_BOOL bIsNumber = TRUE;\r
-    if (m_Pos >= m_Size) {\r
-        return EndOfData;\r
-    }\r
-    int ch = m_pBuf[m_Pos++];\r
-    int type = _PDF_CharType[ch];\r
-    while (1) {\r
-        while (type == 'W') {\r
-            if (m_Size <= m_Pos) {\r
-                return EndOfData;\r
-            }\r
-            ch = m_pBuf[m_Pos++];\r
-            type = _PDF_CharType[ch];\r
-        }\r
-        if (ch != '%') {\r
-            break;\r
-        }\r
-        while (1) {\r
-            if (m_Size <= m_Pos) {\r
-                return EndOfData;\r
-            }\r
-            ch = m_pBuf[m_Pos++];\r
-            if (ch == '\r' || ch == '\n') {\r
-                break;\r
-            }\r
-        }\r
-        type = _PDF_CharType[ch];\r
-    }\r
-    if (type == 'D' && ch != '/') {\r
-        m_Pos --;\r
-        m_pLastObj = ReadNextObject();\r
-        return Others;\r
-    }\r
-    while (1) {\r
-        if (m_WordSize < MAX_WORD_BUFFER) {\r
-            m_WordBuffer[m_WordSize++] = ch;\r
-        }\r
-        if (type != 'N') {\r
-            bIsNumber = FALSE;\r
-        }\r
-        if (m_Size <= m_Pos) {\r
-            break;\r
-        }\r
-        ch = m_pBuf[m_Pos++];\r
-        type = _PDF_CharType[ch];\r
-        if (type == 'D' || type == 'W') {\r
-            m_Pos --;\r
-            break;\r
-        }\r
-    }\r
-    m_WordBuffer[m_WordSize] = 0;\r
-    if (bIsNumber) {\r
-        return Number;\r
-    }\r
-    if (m_WordBuffer[0] == '/') {\r
-        return Name;\r
-    }\r
-    if (m_WordSize == 4) {\r
-        if (*(FX_DWORD*)m_WordBuffer == FXDWORD_TRUE) {\r
-            m_pLastObj = CPDF_Boolean::Create(TRUE);\r
-            return Others;\r
-        }\r
-        if (*(FX_DWORD*)m_WordBuffer == FXDWORD_NULL) {\r
-            m_pLastObj = CPDF_Null::Create();\r
-            return Others;\r
-        }\r
-    } else if (m_WordSize == 5) {\r
-        if (*(FX_DWORD*)m_WordBuffer == FXDWORD_FALS && m_WordBuffer[4] == 'e') {\r
-            m_pLastObj = CPDF_Boolean::Create(FALSE);\r
-            return Others;\r
-        }\r
-    }\r
-    return Keyword;\r
-}\r
-void CPDF_StreamParser::SkipPathObject()\r
-{\r
-    FX_DWORD command_startpos = m_Pos;\r
-    if (m_Pos >= m_Size) {\r
-        return;\r
-    }\r
-    int ch = m_pBuf[m_Pos++];\r
-    int type = _PDF_CharType[ch];\r
-    while (1) {\r
-        while (type == 'W') {\r
-            if (m_Pos >= m_Size) {\r
-                return;\r
-            }\r
-            ch = m_pBuf[m_Pos++];\r
-            type = _PDF_CharType[ch];\r
-        }\r
-        if (type != 'N') {\r
-            m_Pos = command_startpos;\r
-            return;\r
-        }\r
-        while (1) {\r
-            while (type != 'W') {\r
-                if (m_Pos >= m_Size) {\r
-                    return;\r
-                }\r
-                ch = m_pBuf[m_Pos++];\r
-                type = _PDF_CharType[ch];\r
-            }\r
-            while (type == 'W') {\r
-                if (m_Pos >= m_Size) {\r
-                    return;\r
-                }\r
-                ch = m_pBuf[m_Pos++];\r
-                type = _PDF_CharType[ch];\r
-            }\r
-            if (type == 'N') {\r
-                continue;\r
-            }\r
-            FX_DWORD op_startpos = m_Pos - 1;\r
-            while (type != 'W' && type != 'D') {\r
-                if (m_Pos >= m_Size) {\r
-                    return;\r
-                }\r
-                ch = m_pBuf[m_Pos++];\r
-                type = _PDF_CharType[ch];\r
-            }\r
-            if (m_Pos - op_startpos == 2) {\r
-                int op = m_pBuf[op_startpos];\r
-                if (op == 'm' || op == 'l' || op == 'c' || op == 'v' || op == 'y') {\r
-                    command_startpos = m_Pos;\r
-                    break;\r
-                }\r
-            } else if (m_Pos - op_startpos == 3) {\r
-                if (m_pBuf[op_startpos] == 'r' && m_pBuf[op_startpos + 1] == 'e') {\r
-                    command_startpos = m_Pos;\r
-                    break;\r
-                }\r
-            }\r
-            m_Pos = command_startpos;\r
-            return;\r
-        }\r
-    }\r
-}\r
-CPDF_Object* CPDF_StreamParser::ReadNextObject(FX_BOOL bAllowNestedArray, FX_BOOL bInArray)\r
-{\r
-    FX_BOOL bIsNumber;\r
-    GetNextWord(bIsNumber);\r
-    if (m_WordSize == 0) {\r
-        return NULL;\r
-    }\r
-    if (bIsNumber) {\r
-        m_WordBuffer[m_WordSize] = 0;\r
-        return CPDF_Number::Create(CFX_ByteStringC(m_WordBuffer, m_WordSize));\r
-    }\r
-    int first_char = m_WordBuffer[0];\r
-    if (first_char == '/') {\r
-        return CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));\r
-    }\r
-    if (first_char == '(') {\r
-        return CPDF_String::Create(ReadString());\r
-    }\r
-    if (first_char == '<') {\r
-        if (m_WordSize == 1) {\r
-            return CPDF_String::Create(ReadHexString(), TRUE);\r
-        }\r
-        CPDF_Dictionary* pDict = CPDF_Dictionary::Create();\r
-        while (1) {\r
-            GetNextWord(bIsNumber);\r
-            if (m_WordSize == 0) {\r
-                pDict->Release();\r
-                return NULL;\r
-            }\r
-            if (m_WordSize == 2 && m_WordBuffer[0] == '>') {\r
-                break;\r
-            }\r
-            if (m_WordBuffer[0] != '/') {\r
-                pDict->Release();\r
-                return NULL;\r
-            }\r
-            CFX_ByteString key = PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1));\r
-            CPDF_Object* pObj = ReadNextObject(TRUE);\r
-            if (pObj == NULL) {\r
-                if (pDict) {\r
-                    pDict->Release();\r
-                }\r
-                return NULL;\r
-            }\r
-            if (!key.IsEmpty()) {\r
-                pDict->SetAt(key, pObj);\r
-            } else {\r
-                pObj->Release();\r
-            }\r
-        }\r
-        return pDict;\r
-    }\r
-    if (first_char == '[') {\r
-        if (!bAllowNestedArray && bInArray) {\r
-            return NULL;\r
-        }\r
-        CPDF_Array* pArray = CPDF_Array::Create();\r
-        while (1) {\r
-            CPDF_Object* pObj = ReadNextObject(bAllowNestedArray, TRUE);\r
-            if (pObj == NULL) {\r
-                if (m_WordSize == 0 || m_WordBuffer[0] == ']') {\r
-                    return pArray;\r
-                }\r
-                if (m_WordBuffer[0] == '[') {\r
-                    continue;\r
-                }\r
-            } else {\r
-                pArray->Add(pObj);\r
-            }\r
-        }\r
-    }\r
-    if (m_WordSize == 4) {\r
-        if (*(FX_DWORD*)m_WordBuffer == FXDWORD_TRUE) {\r
-            return CPDF_Boolean::Create(TRUE);\r
-        }\r
-        if (*(FX_DWORD*)m_WordBuffer == FXDWORD_NULL) {\r
-            return CPDF_Null::Create();\r
-        }\r
-    } else if (m_WordSize == 5) {\r
-        if (*(FX_DWORD*)m_WordBuffer == FXDWORD_FALS && m_WordBuffer[4] == 'e') {\r
-            return CPDF_Boolean::Create(FALSE);\r
-        }\r
-    }\r
-    return NULL;\r
-}\r
-void CPDF_StreamParser::GetNextWord(FX_BOOL& bIsNumber)\r
-{\r
-    m_WordSize = 0;\r
-    bIsNumber = TRUE;\r
-    if (m_Size <= m_Pos) {\r
-        return;\r
-    }\r
-    int ch = m_pBuf[m_Pos++];\r
-    int type = _PDF_CharType[ch];\r
-    while (1) {\r
-        while (type == 'W') {\r
-            if (m_Size <= m_Pos) {\r
-                return;\r
-            }\r
-            ch = m_pBuf[m_Pos++];\r
-            type = _PDF_CharType[ch];\r
-        }\r
-        if (ch != '%') {\r
-            break;\r
-        }\r
-        while (1) {\r
-            if (m_Size <= m_Pos) {\r
-                return;\r
-            }\r
-            ch = m_pBuf[m_Pos++];\r
-            if (ch == '\r' || ch == '\n') {\r
-                break;\r
-            }\r
-        }\r
-        type = _PDF_CharType[ch];\r
-    }\r
-    if (type == 'D') {\r
-        bIsNumber = FALSE;\r
-        m_WordBuffer[m_WordSize++] = ch;\r
-        if (ch == '/') {\r
-            while (1) {\r
-                if (m_Size <= m_Pos) {\r
-                    return;\r
-                }\r
-                ch = m_pBuf[m_Pos++];\r
-                type = _PDF_CharType[ch];\r
-                if (type != 'R' && type != 'N') {\r
-                    m_Pos --;\r
-                    return;\r
-                }\r
-                if (m_WordSize < MAX_WORD_BUFFER) {\r
-                    m_WordBuffer[m_WordSize++] = ch;\r
-                }\r
-            }\r
-        } else if (ch == '<') {\r
-            if (m_Size <= m_Pos) {\r
-                return;\r
-            }\r
-            ch = m_pBuf[m_Pos++];\r
-            if (ch == '<') {\r
-                m_WordBuffer[m_WordSize++] = ch;\r
-            } else {\r
-                m_Pos --;\r
-            }\r
-        } else if (ch == '>') {\r
-            if (m_Size <= m_Pos) {\r
-                return;\r
-            }\r
-            ch = m_pBuf[m_Pos++];\r
-            if (ch == '>') {\r
-                m_WordBuffer[m_WordSize++] = ch;\r
-            } else {\r
-                m_Pos --;\r
-            }\r
-        }\r
-        return;\r
-    }\r
-    while (1) {\r
-        if (m_WordSize < MAX_WORD_BUFFER) {\r
-            m_WordBuffer[m_WordSize++] = ch;\r
-        }\r
-        if (type != 'N') {\r
-            bIsNumber = FALSE;\r
-        }\r
-        if (m_Size <= m_Pos) {\r
-            return;\r
-        }\r
-        ch = m_pBuf[m_Pos++];\r
-        type = _PDF_CharType[ch];\r
-        if (type == 'D' || type == 'W') {\r
-            m_Pos --;\r
-            break;\r
-        }\r
-    }\r
-}\r
-CFX_ByteString CPDF_StreamParser::ReadString()\r
-{\r
-    if (m_Size <= m_Pos) {\r
-        return CFX_ByteString();\r
-    }\r
-    int ch = m_pBuf[m_Pos++];\r
-    CFX_ByteTextBuf buf;\r
-    int parlevel = 0;\r
-    int status = 0, iEscCode = 0;\r
-    while (1) {\r
-        switch (status) {\r
-            case 0:\r
-                if (ch == ')') {\r
-                    if (parlevel == 0) {\r
-                        if (buf.GetLength() > MAX_STRING_LENGTH) {\r
-                            return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH);\r
-                        }\r
-                        return buf.GetByteString();\r
-                    }\r
-                    parlevel --;\r
-                    buf.AppendChar(')');\r
-                } else if (ch == '(') {\r
-                    parlevel ++;\r
-                    buf.AppendChar('(');\r
-                } else if (ch == '\\') {\r
-                    status = 1;\r
-                } else {\r
-                    buf.AppendChar((char)ch);\r
-                }\r
-                break;\r
-            case 1:\r
-                if (ch >= '0' && ch <= '7') {\r
-                    iEscCode = ch - '0';\r
-                    status = 2;\r
-                    break;\r
-                }\r
-                if (ch == 'n') {\r
-                    buf.AppendChar('\n');\r
-                } else if (ch == 'r') {\r
-                    buf.AppendChar('\r');\r
-                } else if (ch == 't') {\r
-                    buf.AppendChar('\t');\r
-                } else if (ch == 'b') {\r
-                    buf.AppendChar('\b');\r
-                } else if (ch == 'f') {\r
-                    buf.AppendChar('\f');\r
-                } else if (ch == '\r') {\r
-                    status = 4;\r
-                    break;\r
-                } else if (ch == '\n') {\r
-                } else {\r
-                    buf.AppendChar(ch);\r
-                }\r
-                status = 0;\r
-                break;\r
-            case 2:\r
-                if (ch >= '0' && ch <= '7') {\r
-                    iEscCode = iEscCode * 8 + ch - '0';\r
-                    status = 3;\r
-                } else {\r
-                    buf.AppendChar(iEscCode);\r
-                    status = 0;\r
-                    continue;\r
-                }\r
-                break;\r
-            case 3:\r
-                if (ch >= '0' && ch <= '7') {\r
-                    iEscCode = iEscCode * 8 + ch - '0';\r
-                    buf.AppendChar(iEscCode);\r
-                    status = 0;\r
-                } else {\r
-                    buf.AppendChar(iEscCode);\r
-                    status = 0;\r
-                    continue;\r
-                }\r
-                break;\r
-            case 4:\r
-                status = 0;\r
-                if (ch != '\n') {\r
-                    continue;\r
-                }\r
-                break;\r
-        }\r
-        if (m_Size <= m_Pos) {\r
-            break;\r
-        }\r
-        ch = m_pBuf[m_Pos++];\r
-    }\r
-    if (m_Size > m_Pos) {\r
-        ch = m_pBuf[m_Pos++];\r
-    }\r
-    if (buf.GetLength() > MAX_STRING_LENGTH) {\r
-        return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH);\r
-    }\r
-    return buf.GetByteString();\r
-}\r
-CFX_ByteString CPDF_StreamParser::ReadHexString()\r
-{\r
-    if (m_Size <= m_Pos) {\r
-        return CFX_ByteString();\r
-    }\r
-    int ch = m_pBuf[m_Pos++];\r
-    CFX_ByteTextBuf buf;\r
-    FX_BOOL bFirst = TRUE;\r
-    int code = 0;\r
-    while (1) {\r
-        if (ch == '>') {\r
-            break;\r
-        }\r
-        if (ch >= '0' && ch <= '9') {\r
-            if (bFirst) {\r
-                code = (ch - '0') * 16;\r
-            } else {\r
-                code += ch - '0';\r
-                buf.AppendChar((char)code);\r
-            }\r
-            bFirst = !bFirst;\r
-        } else if (ch >= 'A' && ch <= 'F') {\r
-            if (bFirst) {\r
-                code = (ch - 'A' + 10) * 16;\r
-            } else {\r
-                code += ch - 'A' + 10;\r
-                buf.AppendChar((char)code);\r
-            }\r
-            bFirst = !bFirst;\r
-        } else if (ch >= 'a' && ch <= 'f') {\r
-            if (bFirst) {\r
-                code = (ch - 'a' + 10) * 16;\r
-            } else {\r
-                code += ch - 'a' + 10;\r
-                buf.AppendChar((char)code);\r
-            }\r
-            bFirst = !bFirst;\r
-        }\r
-        if (m_Size <= m_Pos) {\r
-            break;\r
-        }\r
-        ch = m_pBuf[m_Pos++];\r
-    }\r
-    if (!bFirst) {\r
-        buf.AppendChar((char)code);\r
-    }\r
-    if (buf.GetLength() > MAX_STRING_LENGTH) {\r
-        return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH);\r
-    }\r
-    return buf.GetByteString();\r
-}\r
-#define PAGEPARSE_STAGE_GETCONTENT             1\r
-#define PAGEPARSE_STAGE_PARSE                  2\r
-#define PAGEPARSE_STAGE_CHECKCLIP              3\r
-CPDF_ContentParser::CPDF_ContentParser()\r
-{\r
-    m_pParser = NULL;\r
-    m_pStreamArray = NULL;\r
-    m_pSingleStream = NULL;\r
-    m_pData = NULL;\r
-    m_Status = Ready;\r
-    m_pType3Char = NULL;\r
-}\r
-CPDF_ContentParser::~CPDF_ContentParser()\r
-{\r
-    Clear();\r
-}\r
-void CPDF_ContentParser::Clear()\r
-{\r
-    if (m_pParser) {\r
-        delete m_pParser;\r
-    }\r
-    if (m_pSingleStream) {\r
-        delete m_pSingleStream;\r
-    }\r
-    if (m_pStreamArray) {\r
-        for (FX_DWORD i = 0; i < m_nStreams; i ++)\r
-            if (m_pStreamArray[i]) {\r
-                delete m_pStreamArray[i];\r
-            }\r
-        FX_Free(m_pStreamArray);\r
-    }\r
-    if (m_pData && m_pSingleStream == NULL) {\r
-        FX_Free((void*)m_pData);\r
-    }\r
-    m_pParser = NULL;\r
-    m_pStreamArray = NULL;\r
-    m_pSingleStream = NULL;\r
-    m_pData = NULL;\r
-    m_Status = Ready;\r
-}\r
-void CPDF_ContentParser::Start(CPDF_Page* pPage, CPDF_ParseOptions* pOptions)\r
-{\r
-    if (m_Status != Ready || pPage == NULL || pPage->m_pDocument == NULL || pPage->m_pFormDict == NULL) {\r
-        m_Status = Done;\r
-        return;\r
-    }\r
-    m_pObjects = pPage;\r
-    m_bForm = FALSE;\r
-    if (pOptions) {\r
-        m_Options = *pOptions;\r
-    }\r
-    m_Status = ToBeContinued;\r
-    m_InternalStage = PAGEPARSE_STAGE_GETCONTENT;\r
-    m_CurrentOffset = 0;\r
-    CPDF_Object* pContent = pPage->m_pFormDict->GetElementValue(FX_BSTRC("Contents"));\r
-    if (pContent == NULL) {\r
-        m_Status = Done;\r
-        return;\r
-    }\r
-    if (pContent->GetType() == PDFOBJ_STREAM) {\r
-        m_nStreams = 0;\r
-        m_pSingleStream = FX_NEW CPDF_StreamAcc;\r
-        m_pSingleStream->LoadAllData((CPDF_Stream*)pContent, FALSE);\r
-    } else if (pContent->GetType() == PDFOBJ_ARRAY) {\r
-        CPDF_Array* pArray = (CPDF_Array*)pContent;\r
-        m_nStreams = pArray->GetCount();\r
-        if (m_nStreams == 0) {\r
-            m_Status = Done;\r
-            return;\r
-        }\r
-        m_pStreamArray = FX_Alloc(CPDF_StreamAcc*, m_nStreams);\r
-        FXSYS_memset32(m_pStreamArray, 0, sizeof(CPDF_StreamAcc*) * m_nStreams);\r
-    } else {\r
-        m_Status = Done;\r
-        return;\r
-    }\r
-}\r
-void CPDF_ContentParser::Start(CPDF_Form* pForm, CPDF_AllStates* pGraphicStates,\r
-                               CFX_AffineMatrix* pParentMatrix, CPDF_Type3Char* pType3Char, CPDF_ParseOptions* pOptions, int level)\r
-{\r
-    m_pType3Char = pType3Char;\r
-    m_pObjects = pForm;\r
-    m_bForm = TRUE;\r
-    CFX_AffineMatrix form_matrix = pForm->m_pFormDict->GetMatrix(FX_BSTRC("Matrix"));\r
-    if (pGraphicStates) {\r
-        form_matrix.Concat(pGraphicStates->m_CTM);\r
-    }\r
-    CPDF_Array* pBBox = pForm->m_pFormDict->GetArray(FX_BSTRC("BBox"));\r
-    CFX_FloatRect form_bbox;\r
-    CPDF_Path ClipPath;\r
-    if (pBBox) {\r
-        form_bbox = pBBox->GetRect();\r
-        ClipPath.New();\r
-        ClipPath.AppendRect(form_bbox.left, form_bbox.bottom, form_bbox.right, form_bbox.top);\r
-        ClipPath.Transform(&form_matrix);\r
-        if (pParentMatrix) {\r
-            ClipPath.Transform(pParentMatrix);\r
-        }\r
-        form_bbox.Transform(&form_matrix);\r
-        if (pParentMatrix) {\r
-            form_bbox.Transform(pParentMatrix);\r
-        }\r
-    }\r
-    CPDF_Dictionary* pResources = pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));\r
-    m_pParser = FX_NEW CPDF_StreamContentParser;\r
-    m_pParser->Initialize();\r
-    m_pParser->PrepareParse(pForm->m_pDocument, pForm->m_pPageResources, pForm->m_pResources, pParentMatrix, pForm,\r
-                            pResources, &form_bbox, pOptions, pGraphicStates, level);\r
-    m_pParser->m_pCurStates->m_CTM = form_matrix;\r
-    m_pParser->m_pCurStates->m_ParentMatrix = form_matrix;\r
-    if (ClipPath.NotNull()) {\r
-        m_pParser->m_pCurStates->m_ClipPath.AppendPath(ClipPath, FXFILL_WINDING, TRUE);\r
-    }\r
-    if (pForm->m_Transparency & PDFTRANS_GROUP) {\r
-        CPDF_GeneralStateData* pData = m_pParser->m_pCurStates->m_GeneralState.GetModify();\r
-        pData->m_BlendType = FXDIB_BLEND_NORMAL;\r
-        pData->m_StrokeAlpha = 1.0f;\r
-        pData->m_FillAlpha = 1.0f;\r
-        pData->m_pSoftMask = NULL;\r
-    }\r
-    m_nStreams = 0;\r
-    m_pSingleStream = FX_NEW CPDF_StreamAcc;\r
-    if (pForm->m_pDocument) {\r
-        m_pSingleStream->LoadAllData(pForm->m_pFormStream, FALSE);\r
-    } else {\r
-        m_pSingleStream->LoadAllData(pForm->m_pFormStream, FALSE);\r
-    }\r
-    m_pData = (FX_LPBYTE)m_pSingleStream->GetData();\r
-    m_Size = m_pSingleStream->GetSize();\r
-    m_Status = ToBeContinued;\r
-    m_InternalStage = PAGEPARSE_STAGE_PARSE;\r
-    m_CurrentOffset = 0;\r
-}\r
-void CPDF_ContentParser::Continue(IFX_Pause* pPause)\r
-{\r
-    int steps = 0;\r
-    while (m_Status == ToBeContinued) {\r
-        if (m_InternalStage == PAGEPARSE_STAGE_GETCONTENT) {\r
-            if (m_CurrentOffset == m_nStreams) {\r
-                if (m_pStreamArray) {\r
-                    m_Size = 0;\r
-                    FX_DWORD i;\r
-                    for (i = 0; i < m_nStreams; i ++) {\r
-                        FX_DWORD size = m_pStreamArray[i]->GetSize();\r
-                        if (m_Size + size + 1 <= m_Size) {\r
-                                                       m_Status = Done;\r
-                                                       return;\r
-                        }\r
-                        m_Size += size + 1;\r
-                    }\r
-                    m_pData = FX_Alloc(FX_BYTE, m_Size);\r
-                    if (!m_pData) {\r
-                        m_Status = Done;\r
-                        return;\r
-                    }\r
-                    FX_DWORD pos = 0;\r
-                    for (i = 0; i < m_nStreams; i ++) {\r
-                        FXSYS_memcpy32(m_pData + pos, m_pStreamArray[i]->GetData(), m_pStreamArray[i]->GetSize());\r
-                        pos += m_pStreamArray[i]->GetSize() + 1;\r
-                        m_pData[pos - 1] = ' ';\r
-                        delete m_pStreamArray[i];\r
-                    }\r
-                    FX_Free(m_pStreamArray);\r
-                    m_pStreamArray = NULL;\r
-                } else {\r
-                    m_pData = (FX_LPBYTE)m_pSingleStream->GetData();\r
-                    m_Size = m_pSingleStream->GetSize();\r
-                }\r
-                m_InternalStage = PAGEPARSE_STAGE_PARSE;\r
-                m_CurrentOffset = 0;\r
-            } else {\r
-                CPDF_Array* pContent = m_pObjects->m_pFormDict->GetArray(FX_BSTRC("Contents"));\r
-                m_pStreamArray[m_CurrentOffset] = FX_NEW CPDF_StreamAcc;\r
-                CPDF_Stream* pStreamObj = (CPDF_Stream*)pContent->GetElementValue(m_CurrentOffset);\r
-                m_pStreamArray[m_CurrentOffset]->LoadAllData(pStreamObj, FALSE);\r
-                m_CurrentOffset ++;\r
-            }\r
-        }\r
-        if (m_InternalStage == PAGEPARSE_STAGE_PARSE) {\r
-            if (m_pParser == NULL) {\r
-                m_pParser = FX_NEW CPDF_StreamContentParser;\r
-                m_pParser->Initialize();\r
-                m_pParser->PrepareParse(m_pObjects->m_pDocument, m_pObjects->m_pPageResources, NULL, NULL, m_pObjects,\r
-                                        m_pObjects->m_pResources, &m_pObjects->m_BBox, &m_Options, NULL, 0);\r
-                m_pParser->m_pCurStates->m_ColorState.GetModify()->Default();\r
-            }\r
-            if (m_CurrentOffset >= m_Size) {\r
-                m_InternalStage = PAGEPARSE_STAGE_CHECKCLIP;\r
-            } else {\r
-                m_CurrentOffset += m_pParser->Parse(m_pData + m_CurrentOffset, m_Size - m_CurrentOffset, PARSE_STEP_LIMIT);\r
-                if (m_pParser->m_bAbort) {\r
-                    m_InternalStage = PAGEPARSE_STAGE_CHECKCLIP;\r
-                    continue;\r
-                }\r
-            }\r
-        }\r
-        if (m_InternalStage == PAGEPARSE_STAGE_CHECKCLIP) {\r
-            if (m_pType3Char) {\r
-                m_pType3Char->m_bColored = m_pParser->m_bColored;\r
-                m_pType3Char->m_Width = FXSYS_round(m_pParser->m_Type3Data[0] * 1000);\r
-                m_pType3Char->m_BBox.left = FXSYS_round(m_pParser->m_Type3Data[2] * 1000);\r
-                m_pType3Char->m_BBox.bottom = FXSYS_round(m_pParser->m_Type3Data[3] * 1000);\r
-                m_pType3Char->m_BBox.right = FXSYS_round(m_pParser->m_Type3Data[4] * 1000);\r
-                m_pType3Char->m_BBox.top = FXSYS_round(m_pParser->m_Type3Data[5] * 1000);\r
-            }\r
-            FX_POSITION pos = m_pObjects->m_ObjectList.GetHeadPosition();\r
-            while (pos) {\r
-                CPDF_PageObject* pObj = (CPDF_PageObject*)m_pObjects->m_ObjectList.GetNext(pos);\r
-                if (pObj->m_ClipPath.IsNull()) {\r
-                    continue;\r
-                }\r
-                if (pObj->m_ClipPath.GetPathCount() != 1) {\r
-                    continue;\r
-                }\r
-                if (pObj->m_ClipPath.GetTextCount()) {\r
-                    continue;\r
-                }\r
-                CPDF_Path ClipPath = pObj->m_ClipPath.GetPath(0);\r
-                if (!ClipPath.IsRect() || pObj->m_Type == PDFPAGE_SHADING) {\r
-                    continue;\r
-                }\r
-                CFX_FloatRect old_rect(ClipPath.GetPointX(0), ClipPath.GetPointY(0),\r
-                                       ClipPath.GetPointX(2), ClipPath.GetPointY(2));\r
-                CFX_FloatRect obj_rect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top);\r
-                if (old_rect.Contains(obj_rect)) {\r
-                    pObj->m_ClipPath.SetNull();\r
-                }\r
-            }\r
-            m_Status = Done;\r
-            return;\r
-        }\r
-        steps ++;\r
-        if (pPause && pPause->NeedToPauseNow()) {\r
-            break;\r
-        }\r
-    }\r
-}\r
-int CPDF_ContentParser::EstimateProgress()\r
-{\r
-    if (m_Status == Ready) {\r
-        return 0;\r
-    }\r
-    if (m_Status == Done) {\r
-        return 100;\r
-    }\r
-    if (m_InternalStage == PAGEPARSE_STAGE_GETCONTENT) {\r
-        return 10;\r
-    }\r
-    if (m_InternalStage == PAGEPARSE_STAGE_CHECKCLIP) {\r
-        return 90;\r
-    }\r
-    return 10 + 80 * m_CurrentOffset / m_Size;\r
-}\r
+// 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_page.h"
+#include "../../../include/fpdfapi/fpdf_module.h"
+#include "../../../include/fxcodec/fx_codec.h"
+#include "pageint.h"
+#include <limits.h>
+extern const FX_LPCSTR _PDF_OpCharType =
+    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
+    "IIVIIIIVIIVIIIIIVVIIIIIIIIIIIIII"
+    "IIVVVVVVIVVVVVVIVVVVVIIVVIIIIIII"
+    "IIVVVVVVVVVVVVVVIVVVIIVVIVVIIIII"
+    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
+    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
+    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
+    "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII";
+FX_BOOL _PDF_HasInvalidOpChar(FX_LPCSTR op)
+{
+    if(!op) {
+        return FALSE;
+    }
+    FX_BYTE ch;
+    while((ch = *op++)) {
+        if(_PDF_OpCharType[ch] == 'I') {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+class CPDF_StreamParserAutoClearer {
+  public:
+    CPDF_StreamParserAutoClearer(CPDF_StreamParser** scoped_variable, CPDF_StreamParser* new_parser)
+            : scoped_variable_(scoped_variable) {
+        *scoped_variable_ = new_parser;
+    }
+    ~CPDF_StreamParserAutoClearer() { *scoped_variable_ = NULL; }
+  private:
+    CPDF_StreamParser** scoped_variable_;
+};
+FX_DWORD CPDF_StreamContentParser::Parse(FX_LPCBYTE pData, FX_DWORD dwSize, FX_DWORD max_cost)
+{
+    if (m_Level > _FPDF_MAX_FORM_LEVEL_) {
+        return dwSize;
+    }
+    FX_DWORD InitObjCount = m_pObjectList->CountObjects();
+    CPDF_StreamParser syntax(pData, dwSize);
+    CPDF_StreamParserAutoClearer auto_clearer(&m_pSyntax, &syntax);
+    m_CompatCount = 0;
+    while (1) {
+        FX_DWORD cost = m_pObjectList->CountObjects() - InitObjCount;
+        if (max_cost && cost >= max_cost) {
+            break;
+        }
+        switch (syntax.ParseNextElement()) {
+            case CPDF_StreamParser::EndOfData:
+                return m_pSyntax->GetPos();
+            case CPDF_StreamParser::Keyword:
+                if(!OnOperator((char*)syntax.GetWordBuf()) && _PDF_HasInvalidOpChar((char*)syntax.GetWordBuf())) {
+                    m_bAbort = TRUE;
+                }
+                if (m_bAbort) {
+                    return m_pSyntax->GetPos();
+                }
+                ClearAllParams();
+                break;
+            case CPDF_StreamParser::Number:
+                AddNumberParam((char*)syntax.GetWordBuf(), syntax.GetWordSize());
+                break;
+            case CPDF_StreamParser::Name:
+                AddNameParam((FX_LPCSTR)syntax.GetWordBuf() + 1, syntax.GetWordSize() - 1);
+                break;
+            default:
+                AddObjectParam(syntax.GetObject());
+        }
+    }
+    return m_pSyntax->GetPos();
+}
+void _PDF_ReplaceAbbr(CPDF_Object* pObj);
+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((FX_LPCSTR)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();
+        }
+    }
+}
+void CPDF_StreamContentParser::ParsePathObject()
+{
+    FX_FLOAT params[6] = {0};
+    int nParams = 0;
+    int last_pos = m_pSyntax->GetPos();
+    while (1) {
+        CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement();
+        FX_BOOL bProcessed = TRUE;
+        switch (type) {
+            case CPDF_StreamParser::EndOfData:
+                return;
+            case CPDF_StreamParser::Keyword: {
+                    int len = m_pSyntax->GetWordSize();
+                    if (len == 1) {
+                        switch (m_pSyntax->GetWordBuf()[0]) {
+                            case 'm':
+                                AddPathPoint(params[0], params[1], FXPT_MOVETO);
+                                nParams = 0;
+                                break;
+                            case 'l':
+                                AddPathPoint(params[0], params[1], FXPT_LINETO);
+                                nParams = 0;
+                                break;
+                            case 'c':
+                                AddPathPoint(params[0], params[1], FXPT_BEZIERTO);
+                                AddPathPoint(params[2], params[3], FXPT_BEZIERTO);
+                                AddPathPoint(params[4], params[5], FXPT_BEZIERTO);
+                                nParams = 0;
+                                break;
+                            case 'v':
+                                AddPathPoint(m_PathCurrentX, m_PathCurrentY, FXPT_BEZIERTO);
+                                AddPathPoint(params[0], params[1], FXPT_BEZIERTO);
+                                AddPathPoint(params[2], params[3], FXPT_BEZIERTO);
+                                nParams = 0;
+                                break;
+                            case 'y':
+                                AddPathPoint(params[0], params[1], FXPT_BEZIERTO);
+                                AddPathPoint(params[2], params[3], FXPT_BEZIERTO);
+                                AddPathPoint(params[2], params[3], FXPT_BEZIERTO);
+                                nParams = 0;
+                                break;
+                            case 'h':
+                                Handle_ClosePath();
+                                nParams = 0;
+                                break;
+                            default:
+                                bProcessed = FALSE;
+                                break;
+                        }
+                    } else if (len == 2) {
+                        if (m_pSyntax->GetWordBuf()[0] == 'r' && m_pSyntax->GetWordBuf()[1] == 'e') {
+                            AddPathRect(params[0], params[1], params[2], params[3]);
+                            nParams = 0;
+                        } else {
+                            bProcessed = FALSE;
+                        }
+                    } else {
+                        bProcessed = FALSE;
+                    }
+                    if (bProcessed) {
+                        last_pos = m_pSyntax->GetPos();
+                    }
+                    break;
+                }
+            case CPDF_StreamParser::Number: {
+                    if (nParams == 6) {
+                        break;
+                    }
+                    FX_BOOL bInteger;
+                    int value;
+                    FX_atonum(CFX_ByteStringC(m_pSyntax->GetWordBuf(), m_pSyntax->GetWordSize()), bInteger, &value);
+                    params[nParams++] = bInteger ? (FX_FLOAT)value : *(FX_FLOAT*)&value;
+                    break;
+                }
+            default:
+                bProcessed = FALSE;
+        }
+        if (!bProcessed) {
+            m_pSyntax->SetPos(last_pos);
+            return;
+        }
+    }
+}
+CPDF_StreamParser::CPDF_StreamParser(const FX_BYTE* pData, FX_DWORD dwSize)
+{
+    m_pBuf = pData;
+    m_Size = dwSize;
+    m_Pos = 0;
+    m_pLastObj = NULL;
+}
+CPDF_StreamParser::~CPDF_StreamParser()
+{
+    if (m_pLastObj) {
+        m_pLastObj->Release();
+    }
+}
+FX_DWORD _DecodeAllScanlines(ICodec_ScanlineDecoder* pDecoder, FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
+{
+    if (pDecoder == NULL) {
+        return (FX_DWORD) - 1;
+    }
+    int ncomps = pDecoder->CountComps();
+    int bpc = pDecoder->GetBPC();
+    int width = pDecoder->GetWidth();
+    int height = pDecoder->GetHeight();
+    int pitch = (width * ncomps * bpc + 7) / 8;
+    if (height == 0 || pitch > (1 << 30) / height) {
+        delete pDecoder;
+        return -1;
+    }
+    dest_size = pitch * height;
+    dest_buf = FX_Alloc( FX_BYTE, dest_size);
+    for (int row = 0; row < height; row ++) {
+        FX_LPBYTE pLine = pDecoder->GetScanline(row);
+        if (pLine == NULL) {
+            break;
+        }
+        FXSYS_memcpy32(dest_buf + row * pitch, pLine, pitch);
+    }
+    FX_DWORD srcoff = pDecoder->GetSrcOffset();
+    delete pDecoder;
+    return srcoff;
+}
+ICodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
+        const CPDF_Dictionary* pParams);
+FX_DWORD _A85Decode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size);
+FX_DWORD _HexDecode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size);
+FX_DWORD FPDFAPI_FlateOrLZWDecode(FX_BOOL bLZW, const FX_BYTE* src_buf, FX_DWORD src_size, CPDF_Dictionary* pParams,
+                                  FX_DWORD estimated_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size);
+FX_DWORD PDF_DecodeInlineStream(const FX_BYTE* src_buf, FX_DWORD limit,
+                                int width, int height, CFX_ByteString& decoder,
+                                CPDF_Dictionary* pParam, FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
+{
+    if (decoder == FX_BSTRC("CCITTFaxDecode") || decoder == FX_BSTRC("CCF")) {
+        ICodec_ScanlineDecoder* pDecoder = FPDFAPI_CreateFaxDecoder(src_buf, limit, width, height, pParam);
+        return _DecodeAllScanlines(pDecoder, dest_buf, dest_size);
+    } else if (decoder == FX_BSTRC("ASCII85Decode") || decoder == FX_BSTRC("A85")) {
+        return _A85Decode(src_buf, limit, dest_buf, dest_size);
+    } else if (decoder == FX_BSTRC("ASCIIHexDecode") || decoder == FX_BSTRC("AHx")) {
+        return _HexDecode(src_buf, limit, dest_buf, dest_size);
+    } else if (decoder == FX_BSTRC("FlateDecode") || decoder == FX_BSTRC("Fl")) {
+        return FPDFAPI_FlateOrLZWDecode(FALSE, src_buf, limit, pParam, dest_size, dest_buf, dest_size);
+    } else if (decoder == FX_BSTRC("LZWDecode") || decoder == FX_BSTRC("LZW")) {
+        return FPDFAPI_FlateOrLZWDecode(TRUE, src_buf, limit, pParam, 0, dest_buf, dest_size);
+    } else if (decoder == FX_BSTRC("DCTDecode") || decoder == FX_BSTRC("DCT")) {
+        ICodec_ScanlineDecoder* pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(
+                                               src_buf, limit, width, height, 0, pParam ? pParam->GetInteger(FX_BSTRC("ColorTransform"), 1) : 1);
+        return _DecodeAllScanlines(pDecoder, dest_buf, dest_size);
+    } else if (decoder == FX_BSTRC("RunLengthDecode") || decoder == FX_BSTRC("RL")) {
+        return RunLengthDecode(src_buf, limit, dest_buf, dest_size);
+    }
+    dest_size = 0;
+    dest_buf = 0;
+    return (FX_DWORD) - 1;
+}
+CPDF_Stream* CPDF_StreamParser::ReadInlineStream(CPDF_Document* pDoc, CPDF_Dictionary* pDict, CPDF_Object* pCSObj, FX_BOOL bDecode)
+{
+    if (m_Pos == m_Size) {
+        return NULL;
+    }
+    if (PDF_CharType[m_pBuf[m_Pos]] == 'W') {
+        m_Pos ++;
+    }
+    CFX_ByteString Decoder;
+    CPDF_Dictionary* pParam = NULL;
+    CPDF_Object* pFilter = pDict->GetElementValue(FX_BSTRC("Filter"));
+    if (pFilter == NULL) {
+    } else if (pFilter->GetType() == PDFOBJ_ARRAY) {
+        Decoder = ((CPDF_Array*)pFilter)->GetString(0);
+        CPDF_Array* pParams = pDict->GetArray(FX_BSTRC("DecodeParms"));
+        if (pParams) {
+            pParam = pParams->GetDict(0);
+        }
+    } else {
+        Decoder = pFilter->GetString();
+        pParam = pDict->GetDict(FX_BSTRC("DecodeParms"));
+    }
+    FX_DWORD width = pDict->GetInteger(FX_BSTRC("Width"));
+    FX_DWORD height = pDict->GetInteger(FX_BSTRC("Height"));
+    FX_DWORD OrigSize = 0;
+    if (pCSObj != NULL) {
+        FX_DWORD bpc = pDict->GetInteger(FX_BSTRC("BitsPerComponent"));
+        FX_DWORD nComponents = 1;
+        CPDF_ColorSpace* pCS = pDoc->LoadColorSpace(pCSObj);
+        if (pCS == NULL) {
+            nComponents = 3;
+        } else {
+            nComponents = pCS->CountComponents();
+            pDoc->GetPageData()->ReleaseColorSpace(pCSObj);
+        }
+        FX_DWORD pitch = width;
+        if (bpc && pitch > INT_MAX / bpc) {
+            return NULL;
+        }
+        pitch *= bpc;
+        if (nComponents && pitch > INT_MAX / nComponents) {
+            return NULL;
+        }
+        pitch *= nComponents;
+        if (pitch > INT_MAX - 7) {
+            return NULL;
+        }
+        pitch += 7;
+        pitch /= 8;
+        OrigSize = pitch;
+    } else {
+        if (width > INT_MAX - 7) {
+            return NULL;
+        }
+        OrigSize = ((width + 7) / 8);
+    }
+    if (height && OrigSize > INT_MAX / height) {
+        return NULL;
+    }
+    OrigSize *= height;
+    FX_LPBYTE pData = NULL;
+    FX_DWORD dwStreamSize;
+    if (Decoder.IsEmpty()) {
+        if (OrigSize > m_Size - m_Pos) {
+            OrigSize = m_Size - m_Pos;
+        }
+        pData = FX_Alloc(FX_BYTE, OrigSize);
+        FXSYS_memcpy32(pData, m_pBuf + m_Pos, OrigSize);
+        dwStreamSize = OrigSize;
+        m_Pos += OrigSize;
+    } else {
+        FX_DWORD dwDestSize = OrigSize;
+        dwStreamSize = PDF_DecodeInlineStream(m_pBuf + m_Pos, m_Size - m_Pos, width, height, Decoder, pParam,
+                                              pData, dwDestSize);
+        if ((int)dwStreamSize < 0) {
+            return NULL;
+        }
+        if (bDecode) {
+            m_Pos += dwStreamSize;
+            dwStreamSize = dwDestSize;
+            if (pFilter->GetType() == PDFOBJ_ARRAY) {
+                ((CPDF_Array*)pFilter)->RemoveAt(0);
+                CPDF_Array* pParams = pDict->GetArray(FX_BSTRC("DecodeParms"));
+                if (pParams) {
+                    pParams->RemoveAt(0);
+                }
+            } else {
+                pDict->RemoveAt(FX_BSTRC("Filter"));
+                pDict->RemoveAt(FX_BSTRC("DecodeParms"));
+            }
+        } else {
+            if (pData) {
+                FX_Free(pData);
+            }
+            FX_DWORD dwSavePos = m_Pos;
+            m_Pos += dwStreamSize;
+            while (1) {
+                FX_DWORD dwPrevPos = m_Pos;
+                CPDF_StreamParser::SyntaxType type = ParseNextElement();
+                if (type == CPDF_StreamParser::EndOfData) {
+                    break;
+                }
+                if (type != CPDF_StreamParser::Keyword) {
+                    dwStreamSize += m_Pos - dwPrevPos;
+                    continue;
+                }
+                if (GetWordSize() == 2 && GetWordBuf()[0] == 'E' &&
+                        GetWordBuf()[1] == 'I') {
+                    m_Pos = dwPrevPos;
+                    break;
+                }
+                dwStreamSize += m_Pos - dwPrevPos;
+            }
+            m_Pos = dwSavePos;
+            pData = FX_Alloc(FX_BYTE, dwStreamSize);
+            FXSYS_memcpy32(pData, m_pBuf + m_Pos, dwStreamSize);
+            m_Pos += dwStreamSize;
+        }
+    }
+    pDict->SetAtInteger(FX_BSTRC("Length"), (int)dwStreamSize);
+    return CPDF_Stream::Create(pData, dwStreamSize, pDict);
+}
+#define MAX_WORD_BUFFER 256
+#define MAX_STRING_LENGTH      32767
+#define FXDWORD_TRUE FXDWORD_FROM_LSBFIRST(0x65757274)
+#define FXDWORD_NULL FXDWORD_FROM_LSBFIRST(0x6c6c756e)
+#define FXDWORD_FALS FXDWORD_FROM_LSBFIRST(0x736c6166)
+CPDF_StreamParser::SyntaxType CPDF_StreamParser::ParseNextElement()
+{
+    if (m_pLastObj) {
+        m_pLastObj->Release();
+        m_pLastObj = NULL;
+    }
+    m_WordSize = 0;
+    FX_BOOL bIsNumber = TRUE;
+    if (m_Pos >= m_Size) {
+        return EndOfData;
+    }
+    int ch = m_pBuf[m_Pos++];
+    int type = PDF_CharType[ch];
+    while (1) {
+        while (type == 'W') {
+            if (m_Size <= m_Pos) {
+                return EndOfData;
+            }
+            ch = m_pBuf[m_Pos++];
+            type = PDF_CharType[ch];
+        }
+        if (ch != '%') {
+            break;
+        }
+        while (1) {
+            if (m_Size <= m_Pos) {
+                return EndOfData;
+            }
+            ch = m_pBuf[m_Pos++];
+            if (ch == '\r' || ch == '\n') {
+                break;
+            }
+        }
+        type = PDF_CharType[ch];
+    }
+    if (type == 'D' && ch != '/') {
+        m_Pos --;
+        m_pLastObj = ReadNextObject();
+        return Others;
+    }
+    while (1) {
+        if (m_WordSize < MAX_WORD_BUFFER) {
+            m_WordBuffer[m_WordSize++] = ch;
+        }
+        if (type != 'N') {
+            bIsNumber = FALSE;
+        }
+        if (m_Size <= m_Pos) {
+            break;
+        }
+        ch = m_pBuf[m_Pos++];
+        type = PDF_CharType[ch];
+        if (type == 'D' || type == 'W') {
+            m_Pos --;
+            break;
+        }
+    }
+    m_WordBuffer[m_WordSize] = 0;
+    if (bIsNumber) {
+        return Number;
+    }
+    if (m_WordBuffer[0] == '/') {
+        return Name;
+    }
+    if (m_WordSize == 4) {
+        if (*(FX_DWORD*)m_WordBuffer == FXDWORD_TRUE) {
+            m_pLastObj = CPDF_Boolean::Create(TRUE);
+            return Others;
+        }
+        if (*(FX_DWORD*)m_WordBuffer == FXDWORD_NULL) {
+            m_pLastObj = CPDF_Null::Create();
+            return Others;
+        }
+    } else if (m_WordSize == 5) {
+        if (*(FX_DWORD*)m_WordBuffer == FXDWORD_FALS && m_WordBuffer[4] == 'e') {
+            m_pLastObj = CPDF_Boolean::Create(FALSE);
+            return Others;
+        }
+    }
+    return Keyword;
+}
+void CPDF_StreamParser::SkipPathObject()
+{
+    FX_DWORD command_startpos = m_Pos;
+    if (m_Pos >= m_Size) {
+        return;
+    }
+    int ch = m_pBuf[m_Pos++];
+    int type = PDF_CharType[ch];
+    while (1) {
+        while (type == 'W') {
+            if (m_Pos >= m_Size) {
+                return;
+            }
+            ch = m_pBuf[m_Pos++];
+            type = PDF_CharType[ch];
+        }
+        if (type != 'N') {
+            m_Pos = command_startpos;
+            return;
+        }
+        while (1) {
+            while (type != 'W') {
+                if (m_Pos >= m_Size) {
+                    return;
+                }
+                ch = m_pBuf[m_Pos++];
+                type = PDF_CharType[ch];
+            }
+            while (type == 'W') {
+                if (m_Pos >= m_Size) {
+                    return;
+                }
+                ch = m_pBuf[m_Pos++];
+                type = PDF_CharType[ch];
+            }
+            if (type == 'N') {
+                continue;
+            }
+            FX_DWORD op_startpos = m_Pos - 1;
+            while (type != 'W' && type != 'D') {
+                if (m_Pos >= m_Size) {
+                    return;
+                }
+                ch = m_pBuf[m_Pos++];
+                type = PDF_CharType[ch];
+            }
+            if (m_Pos - op_startpos == 2) {
+                int op = m_pBuf[op_startpos];
+                if (op == 'm' || op == 'l' || op == 'c' || op == 'v' || op == 'y') {
+                    command_startpos = m_Pos;
+                    break;
+                }
+            } else if (m_Pos - op_startpos == 3) {
+                if (m_pBuf[op_startpos] == 'r' && m_pBuf[op_startpos + 1] == 'e') {
+                    command_startpos = m_Pos;
+                    break;
+                }
+            }
+            m_Pos = command_startpos;
+            return;
+        }
+    }
+}
+CPDF_Object* CPDF_StreamParser::ReadNextObject(FX_BOOL bAllowNestedArray, FX_BOOL bInArray)
+{
+    FX_BOOL bIsNumber;
+    GetNextWord(bIsNumber);
+    if (m_WordSize == 0) {
+        return NULL;
+    }
+    if (bIsNumber) {
+        m_WordBuffer[m_WordSize] = 0;
+        return CPDF_Number::Create(CFX_ByteStringC(m_WordBuffer, m_WordSize));
+    }
+    int first_char = m_WordBuffer[0];
+    if (first_char == '/') {
+        return CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
+    }
+    if (first_char == '(') {
+        return CPDF_String::Create(ReadString());
+    }
+    if (first_char == '<') {
+        if (m_WordSize == 1) {
+            return CPDF_String::Create(ReadHexString(), TRUE);
+        }
+        CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
+        while (1) {
+            GetNextWord(bIsNumber);
+            if (m_WordSize == 0) {
+                pDict->Release();
+                return NULL;
+            }
+            if (m_WordSize == 2 && m_WordBuffer[0] == '>') {
+                break;
+            }
+            if (m_WordBuffer[0] != '/') {
+                pDict->Release();
+                return NULL;
+            }
+            CFX_ByteString key = PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1));
+            CPDF_Object* pObj = ReadNextObject(TRUE);
+            if (pObj == NULL) {
+                if (pDict) {
+                    pDict->Release();
+                }
+                return NULL;
+            }
+            if (!key.IsEmpty()) {
+                pDict->SetAt(key, pObj);
+            } else {
+                pObj->Release();
+            }
+        }
+        return pDict;
+    }
+    if (first_char == '[') {
+        if (!bAllowNestedArray && bInArray) {
+            return NULL;
+        }
+        CPDF_Array* pArray = CPDF_Array::Create();
+        while (1) {
+            CPDF_Object* pObj = ReadNextObject(bAllowNestedArray, TRUE);
+            if (pObj == NULL) {
+                if (m_WordSize == 0 || m_WordBuffer[0] == ']') {
+                    return pArray;
+                }
+                if (m_WordBuffer[0] == '[') {
+                    continue;
+                }
+            } else {
+                pArray->Add(pObj);
+            }
+        }
+    }
+    if (m_WordSize == 4) {
+        if (*(FX_DWORD*)m_WordBuffer == FXDWORD_TRUE) {
+            return CPDF_Boolean::Create(TRUE);
+        }
+        if (*(FX_DWORD*)m_WordBuffer == FXDWORD_NULL) {
+            return CPDF_Null::Create();
+        }
+    } else if (m_WordSize == 5) {
+        if (*(FX_DWORD*)m_WordBuffer == FXDWORD_FALS && m_WordBuffer[4] == 'e') {
+            return CPDF_Boolean::Create(FALSE);
+        }
+    }
+    return NULL;
+}
+void CPDF_StreamParser::GetNextWord(FX_BOOL& bIsNumber)
+{
+    m_WordSize = 0;
+    bIsNumber = TRUE;
+    if (m_Size <= m_Pos) {
+        return;
+    }
+    int ch = m_pBuf[m_Pos++];
+    int type = PDF_CharType[ch];
+    while (1) {
+        while (type == 'W') {
+            if (m_Size <= m_Pos) {
+                return;
+            }
+            ch = m_pBuf[m_Pos++];
+            type = PDF_CharType[ch];
+        }
+        if (ch != '%') {
+            break;
+        }
+        while (1) {
+            if (m_Size <= m_Pos) {
+                return;
+            }
+            ch = m_pBuf[m_Pos++];
+            if (ch == '\r' || ch == '\n') {
+                break;
+            }
+        }
+        type = PDF_CharType[ch];
+    }
+    if (type == 'D') {
+        bIsNumber = FALSE;
+        m_WordBuffer[m_WordSize++] = ch;
+        if (ch == '/') {
+            while (1) {
+                if (m_Size <= m_Pos) {
+                    return;
+                }
+                ch = m_pBuf[m_Pos++];
+                type = PDF_CharType[ch];
+                if (type != 'R' && type != 'N') {
+                    m_Pos --;
+                    return;
+                }
+                if (m_WordSize < MAX_WORD_BUFFER) {
+                    m_WordBuffer[m_WordSize++] = ch;
+                }
+            }
+        } else if (ch == '<') {
+            if (m_Size <= m_Pos) {
+                return;
+            }
+            ch = m_pBuf[m_Pos++];
+            if (ch == '<') {
+                m_WordBuffer[m_WordSize++] = ch;
+            } else {
+                m_Pos --;
+            }
+        } else if (ch == '>') {
+            if (m_Size <= m_Pos) {
+                return;
+            }
+            ch = m_pBuf[m_Pos++];
+            if (ch == '>') {
+                m_WordBuffer[m_WordSize++] = ch;
+            } else {
+                m_Pos --;
+            }
+        }
+        return;
+    }
+    while (1) {
+        if (m_WordSize < MAX_WORD_BUFFER) {
+            m_WordBuffer[m_WordSize++] = ch;
+        }
+        if (type != 'N') {
+            bIsNumber = FALSE;
+        }
+        if (m_Size <= m_Pos) {
+            return;
+        }
+        ch = m_pBuf[m_Pos++];
+        type = PDF_CharType[ch];
+        if (type == 'D' || type == 'W') {
+            m_Pos --;
+            break;
+        }
+    }
+}
+CFX_ByteString CPDF_StreamParser::ReadString()
+{
+    if (m_Size <= m_Pos) {
+        return CFX_ByteString();
+    }
+    int ch = m_pBuf[m_Pos++];
+    CFX_ByteTextBuf buf;
+    int parlevel = 0;
+    int status = 0, iEscCode = 0;
+    while (1) {
+        switch (status) {
+            case 0:
+                if (ch == ')') {
+                    if (parlevel == 0) {
+                        if (buf.GetLength() > MAX_STRING_LENGTH) {
+                            return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH);
+                        }
+                        return buf.GetByteString();
+                    }
+                    parlevel --;
+                    buf.AppendChar(')');
+                } else if (ch == '(') {
+                    parlevel ++;
+                    buf.AppendChar('(');
+                } else if (ch == '\\') {
+                    status = 1;
+                } else {
+                    buf.AppendChar((char)ch);
+                }
+                break;
+            case 1:
+                if (ch >= '0' && ch <= '7') {
+                    iEscCode = ch - '0';
+                    status = 2;
+                    break;
+                }
+                if (ch == 'n') {
+                    buf.AppendChar('\n');
+                } else if (ch == 'r') {
+                    buf.AppendChar('\r');
+                } else if (ch == 't') {
+                    buf.AppendChar('\t');
+                } else if (ch == 'b') {
+                    buf.AppendChar('\b');
+                } else if (ch == 'f') {
+                    buf.AppendChar('\f');
+                } else if (ch == '\r') {
+                    status = 4;
+                    break;
+                } else if (ch == '\n') {
+                } else {
+                    buf.AppendChar(ch);
+                }
+                status = 0;
+                break;
+            case 2:
+                if (ch >= '0' && ch <= '7') {
+                    iEscCode = iEscCode * 8 + ch - '0';
+                    status = 3;
+                } else {
+                    buf.AppendChar(iEscCode);
+                    status = 0;
+                    continue;
+                }
+                break;
+            case 3:
+                if (ch >= '0' && ch <= '7') {
+                    iEscCode = iEscCode * 8 + ch - '0';
+                    buf.AppendChar(iEscCode);
+                    status = 0;
+                } else {
+                    buf.AppendChar(iEscCode);
+                    status = 0;
+                    continue;
+                }
+                break;
+            case 4:
+                status = 0;
+                if (ch != '\n') {
+                    continue;
+                }
+                break;
+        }
+        if (m_Size <= m_Pos) {
+            break;
+        }
+        ch = m_pBuf[m_Pos++];
+    }
+    if (m_Size > m_Pos) {
+        ch = m_pBuf[m_Pos++];
+    }
+    if (buf.GetLength() > MAX_STRING_LENGTH) {
+        return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH);
+    }
+    return buf.GetByteString();
+}
+CFX_ByteString CPDF_StreamParser::ReadHexString()
+{
+    if (m_Size <= m_Pos) {
+        return CFX_ByteString();
+    }
+    int ch = m_pBuf[m_Pos++];
+    CFX_ByteTextBuf buf;
+    FX_BOOL bFirst = TRUE;
+    int code = 0;
+    while (1) {
+        if (ch == '>') {
+            break;
+        }
+        if (ch >= '0' && ch <= '9') {
+            if (bFirst) {
+                code = (ch - '0') * 16;
+            } else {
+                code += ch - '0';
+                buf.AppendChar((char)code);
+            }
+            bFirst = !bFirst;
+        } else if (ch >= 'A' && ch <= 'F') {
+            if (bFirst) {
+                code = (ch - 'A' + 10) * 16;
+            } else {
+                code += ch - 'A' + 10;
+                buf.AppendChar((char)code);
+            }
+            bFirst = !bFirst;
+        } else if (ch >= 'a' && ch <= 'f') {
+            if (bFirst) {
+                code = (ch - 'a' + 10) * 16;
+            } else {
+                code += ch - 'a' + 10;
+                buf.AppendChar((char)code);
+            }
+            bFirst = !bFirst;
+        }
+        if (m_Size <= m_Pos) {
+            break;
+        }
+        ch = m_pBuf[m_Pos++];
+    }
+    if (!bFirst) {
+        buf.AppendChar((char)code);
+    }
+    if (buf.GetLength() > MAX_STRING_LENGTH) {
+        return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH);
+    }
+    return buf.GetByteString();
+}
+#define PAGEPARSE_STAGE_GETCONTENT             1
+#define PAGEPARSE_STAGE_PARSE                  2
+#define PAGEPARSE_STAGE_CHECKCLIP              3
+CPDF_ContentParser::CPDF_ContentParser()
+{
+    m_pParser = NULL;
+    m_pStreamArray = NULL;
+    m_pSingleStream = NULL;
+    m_pData = NULL;
+    m_Status = Ready;
+    m_pType3Char = NULL;
+}
+CPDF_ContentParser::~CPDF_ContentParser()
+{
+    Clear();
+}
+void CPDF_ContentParser::Clear()
+{
+    if (m_pParser) {
+        delete m_pParser;
+    }
+    if (m_pSingleStream) {
+        delete m_pSingleStream;
+    }
+    if (m_pStreamArray) {
+        for (FX_DWORD i = 0; i < m_nStreams; i ++)
+            if (m_pStreamArray[i]) {
+                delete m_pStreamArray[i];
+            }
+        FX_Free(m_pStreamArray);
+    }
+    if (m_pData && m_pSingleStream == NULL) {
+        FX_Free((void*)m_pData);
+    }
+    m_pParser = NULL;
+    m_pStreamArray = NULL;
+    m_pSingleStream = NULL;
+    m_pData = NULL;
+    m_Status = Ready;
+}
+void CPDF_ContentParser::Start(CPDF_Page* pPage, CPDF_ParseOptions* pOptions)
+{
+    if (m_Status != Ready || pPage == NULL || pPage->m_pDocument == NULL || pPage->m_pFormDict == NULL) {
+        m_Status = Done;
+        return;
+    }
+    m_pObjects = pPage;
+    m_bForm = FALSE;
+    if (pOptions) {
+        m_Options = *pOptions;
+    }
+    m_Status = ToBeContinued;
+    m_InternalStage = PAGEPARSE_STAGE_GETCONTENT;
+    m_CurrentOffset = 0;
+    CPDF_Object* pContent = pPage->m_pFormDict->GetElementValue(FX_BSTRC("Contents"));
+    if (pContent == NULL) {
+        m_Status = Done;
+        return;
+    }
+    if (pContent->GetType() == PDFOBJ_STREAM) {
+        m_nStreams = 0;
+        m_pSingleStream = new CPDF_StreamAcc;
+        m_pSingleStream->LoadAllData((CPDF_Stream*)pContent, FALSE);
+    } else if (pContent->GetType() == PDFOBJ_ARRAY) {
+        CPDF_Array* pArray = (CPDF_Array*)pContent;
+        m_nStreams = pArray->GetCount();
+        if (m_nStreams == 0) {
+            m_Status = Done;
+            return;
+        }
+        m_pStreamArray = FX_Alloc(CPDF_StreamAcc*, m_nStreams);
+    } else {
+        m_Status = Done;
+        return;
+    }
+}
+void CPDF_ContentParser::Start(CPDF_Form* pForm, CPDF_AllStates* pGraphicStates,
+                               CFX_AffineMatrix* pParentMatrix, CPDF_Type3Char* pType3Char, CPDF_ParseOptions* pOptions, int level)
+{
+    m_pType3Char = pType3Char;
+    m_pObjects = pForm;
+    m_bForm = TRUE;
+    CFX_AffineMatrix form_matrix = pForm->m_pFormDict->GetMatrix(FX_BSTRC("Matrix"));
+    if (pGraphicStates) {
+        form_matrix.Concat(pGraphicStates->m_CTM);
+    }
+    CPDF_Array* pBBox = pForm->m_pFormDict->GetArray(FX_BSTRC("BBox"));
+    CFX_FloatRect form_bbox;
+    CPDF_Path ClipPath;
+    if (pBBox) {
+        form_bbox = pBBox->GetRect();
+        ClipPath.New();
+        ClipPath.AppendRect(form_bbox.left, form_bbox.bottom, form_bbox.right, form_bbox.top);
+        ClipPath.Transform(&form_matrix);
+        if (pParentMatrix) {
+            ClipPath.Transform(pParentMatrix);
+        }
+        form_bbox.Transform(&form_matrix);
+        if (pParentMatrix) {
+            form_bbox.Transform(pParentMatrix);
+        }
+    }
+    CPDF_Dictionary* pResources = pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
+    m_pParser = new CPDF_StreamContentParser;
+    m_pParser->Initialize();
+    m_pParser->PrepareParse(pForm->m_pDocument, pForm->m_pPageResources, pForm->m_pResources, pParentMatrix, pForm,
+                            pResources, &form_bbox, pOptions, pGraphicStates, level);
+    m_pParser->m_pCurStates->m_CTM = form_matrix;
+    m_pParser->m_pCurStates->m_ParentMatrix = form_matrix;
+    if (ClipPath.NotNull()) {
+        m_pParser->m_pCurStates->m_ClipPath.AppendPath(ClipPath, FXFILL_WINDING, TRUE);
+    }
+    if (pForm->m_Transparency & PDFTRANS_GROUP) {
+        CPDF_GeneralStateData* pData = m_pParser->m_pCurStates->m_GeneralState.GetModify();
+        pData->m_BlendType = FXDIB_BLEND_NORMAL;
+        pData->m_StrokeAlpha = 1.0f;
+        pData->m_FillAlpha = 1.0f;
+        pData->m_pSoftMask = NULL;
+    }
+    m_nStreams = 0;
+    m_pSingleStream = new CPDF_StreamAcc;
+    if (pForm->m_pDocument) {
+        m_pSingleStream->LoadAllData(pForm->m_pFormStream, FALSE);
+    } else {
+        m_pSingleStream->LoadAllData(pForm->m_pFormStream, FALSE);
+    }
+    m_pData = (FX_LPBYTE)m_pSingleStream->GetData();
+    m_Size = m_pSingleStream->GetSize();
+    m_Status = ToBeContinued;
+    m_InternalStage = PAGEPARSE_STAGE_PARSE;
+    m_CurrentOffset = 0;
+}
+void CPDF_ContentParser::Continue(IFX_Pause* pPause)
+{
+    int steps = 0;
+    while (m_Status == ToBeContinued) {
+        if (m_InternalStage == PAGEPARSE_STAGE_GETCONTENT) {
+            if (m_CurrentOffset == m_nStreams) {
+                if (m_pStreamArray) {
+                    m_Size = 0;
+                    FX_DWORD i;
+                    for (i = 0; i < m_nStreams; i ++) {
+                        FX_DWORD size = m_pStreamArray[i]->GetSize();
+                        if (m_Size + size + 1 <= m_Size) {
+                            m_Status = Done;
+                            return;
+                        }
+                        m_Size += size + 1;
+                    }
+                    m_pData = FX_Alloc(FX_BYTE, m_Size);
+                    if (!m_pData) {
+                        m_Status = Done;
+                        return;
+                    }
+                    FX_DWORD pos = 0;
+                    for (i = 0; i < m_nStreams; i ++) {
+                        FXSYS_memcpy32(m_pData + pos, m_pStreamArray[i]->GetData(), m_pStreamArray[i]->GetSize());
+                        pos += m_pStreamArray[i]->GetSize() + 1;
+                        m_pData[pos - 1] = ' ';
+                        delete m_pStreamArray[i];
+                    }
+                    FX_Free(m_pStreamArray);
+                    m_pStreamArray = NULL;
+                } else {
+                    m_pData = (FX_LPBYTE)m_pSingleStream->GetData();
+                    m_Size = m_pSingleStream->GetSize();
+                }
+                m_InternalStage = PAGEPARSE_STAGE_PARSE;
+                m_CurrentOffset = 0;
+            } else {
+                CPDF_Array* pContent = m_pObjects->m_pFormDict->GetArray(FX_BSTRC("Contents"));
+                m_pStreamArray[m_CurrentOffset] = new CPDF_StreamAcc;
+                CPDF_Stream* pStreamObj = (CPDF_Stream*)(pContent ? pContent->GetElementValue(m_CurrentOffset) : NULL);
+                m_pStreamArray[m_CurrentOffset]->LoadAllData(pStreamObj, FALSE);
+                m_CurrentOffset ++;
+            }
+        }
+        if (m_InternalStage == PAGEPARSE_STAGE_PARSE) {
+            if (m_pParser == NULL) {
+                m_pParser = new CPDF_StreamContentParser;
+                m_pParser->Initialize();
+                m_pParser->PrepareParse(m_pObjects->m_pDocument, m_pObjects->m_pPageResources, NULL, NULL, m_pObjects,
+                                        m_pObjects->m_pResources, &m_pObjects->m_BBox, &m_Options, NULL, 0);
+                m_pParser->m_pCurStates->m_ColorState.GetModify()->Default();
+            }
+            if (m_CurrentOffset >= m_Size) {
+                m_InternalStage = PAGEPARSE_STAGE_CHECKCLIP;
+            } else {
+                m_CurrentOffset += m_pParser->Parse(m_pData + m_CurrentOffset, m_Size - m_CurrentOffset, PARSE_STEP_LIMIT);
+                if (m_pParser->m_bAbort) {
+                    m_InternalStage = PAGEPARSE_STAGE_CHECKCLIP;
+                    continue;
+                }
+            }
+        }
+        if (m_InternalStage == PAGEPARSE_STAGE_CHECKCLIP) {
+            if (m_pType3Char) {
+                m_pType3Char->m_bColored = m_pParser->m_bColored;
+                m_pType3Char->m_Width = FXSYS_round(m_pParser->m_Type3Data[0] * 1000);
+                m_pType3Char->m_BBox.left = FXSYS_round(m_pParser->m_Type3Data[2] * 1000);
+                m_pType3Char->m_BBox.bottom = FXSYS_round(m_pParser->m_Type3Data[3] * 1000);
+                m_pType3Char->m_BBox.right = FXSYS_round(m_pParser->m_Type3Data[4] * 1000);
+                m_pType3Char->m_BBox.top = FXSYS_round(m_pParser->m_Type3Data[5] * 1000);
+            }
+            FX_POSITION pos = m_pObjects->m_ObjectList.GetHeadPosition();
+            while (pos) {
+                CPDF_PageObject* pObj = (CPDF_PageObject*)m_pObjects->m_ObjectList.GetNext(pos);
+                if (pObj->m_ClipPath.IsNull()) {
+                    continue;
+                }
+                if (pObj->m_ClipPath.GetPathCount() != 1) {
+                    continue;
+                }
+                if (pObj->m_ClipPath.GetTextCount()) {
+                    continue;
+                }
+                CPDF_Path ClipPath = pObj->m_ClipPath.GetPath(0);
+                if (!ClipPath.IsRect() || pObj->m_Type == PDFPAGE_SHADING) {
+                    continue;
+                }
+                CFX_FloatRect old_rect(ClipPath.GetPointX(0), ClipPath.GetPointY(0),
+                                       ClipPath.GetPointX(2), ClipPath.GetPointY(2));
+                CFX_FloatRect obj_rect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top);
+                if (old_rect.Contains(obj_rect)) {
+                    pObj->m_ClipPath.SetNull();
+                }
+            }
+            m_Status = Done;
+            return;
+        }
+        steps ++;
+        if (pPause && pPause->NeedToPauseNow()) {
+            break;
+        }
+    }
+}
+int CPDF_ContentParser::EstimateProgress()
+{
+    if (m_Status == Ready) {
+        return 0;
+    }
+    if (m_Status == Done) {
+        return 100;
+    }
+    if (m_InternalStage == PAGEPARSE_STAGE_GETCONTENT) {
+        return 10;
+    }
+    if (m_InternalStage == PAGEPARSE_STAGE_CHECKCLIP) {
+        return 90;
+    }
+    return 10 + 80 * m_CurrentOffset / m_Size;
+}