Home | History | Annotate | Download | only in fpdf_page
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../../../include/fpdfapi/fpdf_page.h"
      8 #include "../../../include/fpdfapi/fpdf_module.h"
      9 #include "pageint.h"
     10 #if defined(_FPDFAPI_MINI_)
     11 extern const FX_LPCSTR _PDF_CharType;
     12 void CPDF_StreamContentParser::InputData(FX_LPCBYTE src_buf, FX_DWORD src_size)
     13 {
     14     if (m_Level > _FPDF_MAX_FORM_LEVEL_) {
     15         return;
     16     }
     17     for (FX_DWORD i = 0; i < src_size; i ++) {
     18         int ch = src_buf[i];
     19         int type = _PDF_CharType[ch];
     20 start:
     21         switch (m_WordState) {
     22             case 0:
     23                 if (type == 'W') {
     24                 } else if (type == 'N') {
     25                     m_WordState = 5;
     26                     m_pWordBuf[0] = ch;
     27                     m_WordSize = 1;
     28                 } else if (type == 'R') {
     29                     m_WordState = 4;
     30                     m_pWordBuf[0] = ch;
     31                     m_WordSize = 1;
     32                 } else switch (ch) {
     33                         case '/':
     34                             m_WordState = 2;
     35                             m_WordSize = 0;
     36                             break;
     37                         case '[':
     38                             StartArray();
     39                             break;
     40                         case ']':
     41                             EndArray();
     42                             break;
     43                         case '(':
     44                             m_WordState = 7;
     45                             m_StringLevel = 1;
     46                             m_StringState = 0;
     47                             m_StringBuf.Clear();
     48                             break;
     49                         case '<':
     50                             m_WordState = 3;
     51                             break;
     52                         case '>':
     53                             m_WordState = 8;
     54                             break;
     55                         case '%':
     56                             m_WordState = 1;
     57                             break;
     58                     }
     59                 break;
     60             case 1:
     61                 if (ch == '\n' || ch == '\r') {
     62                     m_WordState = 0;
     63                 }
     64                 break;
     65             case 2:
     66                 if (type != 'R' && type != 'N') {
     67                     EndName();
     68                     m_WordState = 0;
     69                     goto start;
     70                 }
     71                 if (m_WordSize < 256) {
     72                     m_pWordBuf[m_WordSize++] = ch;
     73                 }
     74                 break;
     75             case 3:
     76                 if (ch == '<') {
     77                     StartDict();
     78                     m_WordState = 0;
     79                 } else {
     80                     m_StringBuf.Clear();
     81                     m_WordState = 6;
     82                     goto start;
     83                 }
     84                 break;
     85             case 4:
     86                 if (type != 'R' && type != 'N') {
     87                     m_WordState = 0;
     88                     EndKeyword();
     89                     if (m_bAbort) {
     90                         return;
     91                     }
     92                     goto start;
     93                 }
     94                 if (m_WordSize < 256) {
     95                     m_pWordBuf[m_WordSize++] = ch;
     96                 }
     97                 break;
     98             case 5:
     99                 if (type != 'N') {
    100                     EndNumber();
    101                     m_WordState = 0;
    102                     goto start;
    103                 }
    104                 if (m_WordSize < 256) {
    105                     m_pWordBuf[m_WordSize++] = ch;
    106                 }
    107                 break;
    108             case 6:
    109                 if (ch == '>') {
    110                     EndHexString();
    111                     m_WordState = 0;
    112                 } else {
    113                     m_StringBuf.AppendByte(ch);
    114                 }
    115                 break;
    116             case 7:
    117                 switch (m_StringState) {
    118                     case 0:
    119                         if (ch == ')') {
    120                             m_StringLevel --;
    121                             if (m_StringLevel == 0) {
    122                                 EndString();
    123                                 m_WordState = 0;
    124                                 break;
    125                             }
    126                             m_StringBuf.AppendByte(')');
    127                         } else if (ch == '(') {
    128                             m_StringLevel ++;
    129                             m_StringBuf.AppendByte('(');
    130                         } else if (ch == '\\') {
    131                             m_StringState = 1;
    132                         } else {
    133                             m_StringBuf.AppendByte((char)ch);
    134                         }
    135                         break;
    136                     case 1:
    137                         if (ch >= '0' && ch <= '7') {
    138                             m_EscCode = ch - '0';
    139                             m_StringState = 2;
    140                             break;
    141                         }
    142                         if (ch == 'n') {
    143                             m_StringBuf.AppendByte('\n');
    144                         } else if (ch == 'r') {
    145                             m_StringBuf.AppendByte('\r');
    146                         } else if (ch == 't') {
    147                             m_StringBuf.AppendByte('\t');
    148                         } else if (ch == 'b') {
    149                             m_StringBuf.AppendByte('\b');
    150                         } else if (ch == 'f') {
    151                             m_StringBuf.AppendByte('\f');
    152                         } else if (ch == '\\') {
    153                             m_StringBuf.AppendByte('\\');
    154                         } else if (ch == '(') {
    155                             m_StringBuf.AppendByte('(');
    156                         } else if (ch == ')') {
    157                             m_StringBuf.AppendByte(')');
    158                         } else if (ch == '\r') {
    159                             m_StringState = 4;
    160                             break;
    161                         } else if (ch == '\n') {
    162                         } else {
    163                             m_StringBuf.AppendByte(ch);
    164                         }
    165                         m_StringState = 0;
    166                         break;
    167                     case 2:
    168                         if (ch >= '0' && ch <= '7') {
    169                             m_EscCode = m_EscCode * 8 + ch - '0';
    170                             m_StringState = 3;
    171                         } else {
    172                             m_StringBuf.AppendByte(m_EscCode);
    173                             m_StringState = 0;
    174                             goto start;
    175                         }
    176                         break;
    177                     case 3:
    178                         if (ch >= '0' && ch <= '7') {
    179                             m_EscCode = m_EscCode * 8 + ch - '0';
    180                             m_StringBuf.AppendByte(m_EscCode);
    181                             m_StringState = 0;
    182                         } else {
    183                             m_StringBuf.AppendByte(m_EscCode);
    184                             m_StringState = 0;
    185                             goto start;
    186                         }
    187                         break;
    188                     case 4:
    189                         m_StringState = 0;
    190                         if (ch != '\n') {
    191                             goto start;
    192                         }
    193                         break;
    194                 }
    195                 break;
    196             case 8:
    197                 m_WordState = 0;
    198                 if (ch == '>') {
    199                     EndDict();
    200                 } else {
    201                     goto start;
    202                 }
    203                 break;
    204             case 9:
    205                 switch (m_InlineImageState) {
    206                     case 0:
    207                         if (type == 'W' || type == 'D') {
    208                             m_InlineImageState = 1;
    209                             m_InlineWhiteChar = ch;
    210                         } else {
    211                             m_StringBuf.AppendByte(ch);
    212                         }
    213                         break;
    214                     case 1:
    215                         m_StringBuf.AppendByte(m_InlineWhiteChar);
    216                         if (ch == 'I') {
    217                             m_InlineImageState = 2;
    218                         } else {
    219                             m_InlineImageState = 0;
    220                             goto start;
    221                         }
    222                         break;
    223                     case 2:
    224                         if (ch == 'D') {
    225                             m_InlineImageState = 3;
    226                         } else {
    227                             m_StringBuf.AppendByte('I');
    228                             m_InlineImageState = 0;
    229                             goto start;
    230                         }
    231                         break;
    232                     case 3:
    233                         EndImageDict();
    234                         break;
    235                 }
    236                 break;
    237             case 10:
    238                 switch (m_InlineImageState) {
    239                     case 0:
    240                         if (type == 'W') {
    241                             m_InlineImageState = 1;
    242                             m_InlineWhiteChar = ch;
    243                         } else {
    244                             m_ImageSrcBuf.AppendByte(ch);
    245                         }
    246                         break;
    247                     case 1:
    248                         if (ch == 'E') {
    249                             m_InlineImageState = 2;
    250                         } else {
    251                             m_ImageSrcBuf.AppendByte(m_InlineWhiteChar);
    252                             m_InlineImageState = 0;
    253                             goto start;
    254                         }
    255                         break;
    256                     case 2:
    257                         if (ch == 'I') {
    258                             m_InlineImageState = 3;
    259                         } else {
    260                             m_ImageSrcBuf.AppendByte(m_InlineWhiteChar);
    261                             m_ImageSrcBuf.AppendByte('E');
    262                             m_InlineImageState = 0;
    263                             goto start;
    264                         }
    265                         break;
    266                     case 3:
    267                         if (type == 'W') {
    268                             EndInlineImage();
    269                         } else {
    270                             m_ImageSrcBuf.AppendByte(m_InlineWhiteChar);
    271                             m_ImageSrcBuf.AppendByte('E');
    272                             m_ImageSrcBuf.AppendByte('I');
    273                             m_InlineImageState = 0;
    274                             goto start;
    275                         }
    276                         break;
    277                 }
    278                 break;
    279             case 11:
    280                 if (m_InlineImageState < m_ImageSrcBuf.GetSize()) {
    281                     m_ImageSrcBuf.GetBuffer()[m_InlineImageState ++] = ch;
    282                 } else {
    283                     if (ch == 'I') {
    284                         EndInlineImage();
    285                     }
    286                 }
    287                 break;
    288         }
    289     }
    290 }
    291 void CPDF_StreamContentParser::Finish()
    292 {
    293     switch (m_WordState) {
    294         case 0:
    295             break;
    296         case 1:
    297             break;
    298         case 2:
    299             EndName();
    300             break;
    301         case 3:
    302             break;
    303         case 4:
    304             EndKeyword();
    305             break;
    306         case 5:
    307             EndNumber();
    308             break;
    309         case 6:
    310             EndHexString();
    311             break;
    312         case 7:
    313             EndString();
    314             break;
    315         case 8:
    316             break;
    317         case 9:
    318             break;
    319         case 10:
    320             EndInlineImage();
    321             break;
    322     }
    323     m_WordState = 0;
    324 }
    325 void CPDF_StreamContentParser::AddContainer(CPDF_Object* pObject)
    326 {
    327     if (m_ObjectSize) {
    328         m_pObjectState[m_ObjectSize] = SetToCurObj(pObject);
    329     }
    330     FXSYS_assert(m_ObjectSize < _FPDF_MAX_OBJECT_STACK_SIZE_);
    331     m_pObjectStack[m_ObjectSize++] = pObject;
    332 }
    333 FX_BOOL CPDF_StreamContentParser::SetToCurObj(CPDF_Object* pObject)
    334 {
    335     if (m_ObjectSize == 0) {
    336         AddObjectParam(pObject);
    337         return TRUE;
    338     }
    339     FX_BOOL bInArrayOrDict = TRUE;
    340     CPDF_Object* pCurObj = m_pObjectStack[m_ObjectSize - 1];
    341     if (pCurObj->GetType() == PDFOBJ_ARRAY) {
    342         ((CPDF_Array*)pCurObj)->Add(pObject, m_pDocument);
    343     } else {
    344         if (!m_bDictName && m_pDictName[0]) {
    345             ((CPDF_Dictionary*)pCurObj)->SetAt((FX_LPCSTR)m_pDictName, pObject, m_pDocument);
    346         } else {
    347             bInArrayOrDict = FALSE;
    348         }
    349         m_bDictName = TRUE;
    350     }
    351     return bInArrayOrDict;
    352 }
    353 void CPDF_StreamContentParser::StartArray()
    354 {
    355     if (m_ObjectSize)
    356         if (m_pObjectStack[0]->GetType() != PDFOBJ_DICTIONARY && m_pObjectStack[m_ObjectSize - 1]->GetType() == PDFOBJ_ARRAY) {
    357             return;
    358         }
    359     CPDF_Array* pArray = FX_NEW CPDF_Array;
    360     AddContainer(pArray);
    361 }
    362 void CPDF_StreamContentParser::EndArray()
    363 {
    364     if (m_ObjectSize == 0) {
    365         return;
    366     }
    367     CPDF_Object* pCurObj = m_pObjectStack[m_ObjectSize - 1];
    368     if (pCurObj->GetType() != PDFOBJ_ARRAY) {
    369         return;
    370     }
    371     m_ObjectSize --;
    372     if (m_ObjectSize == 0) {
    373         AddObjectParam(pCurObj);
    374     } else {
    375         if (!m_pObjectState[m_ObjectSize]) {
    376             pCurObj->Release();
    377         }
    378     }
    379     m_pObjectState[m_ObjectSize] = FALSE;
    380 }
    381 void CPDF_StreamContentParser::StartDict()
    382 {
    383     CPDF_Dictionary* pDict = FX_NEW CPDF_Dictionary;
    384     AddContainer(pDict);
    385     m_bDictName = TRUE;
    386 }
    387 void CPDF_StreamContentParser::EndDict()
    388 {
    389     if (m_ObjectSize == 0) {
    390         return;
    391     }
    392     CPDF_Object* pCurObj = m_pObjectStack[m_ObjectSize - 1];
    393     if (pCurObj->GetType() != PDFOBJ_DICTIONARY) {
    394         return;
    395     }
    396     m_ObjectSize --;
    397     if (m_ObjectSize == 0) {
    398         AddObjectParam(pCurObj);
    399     } else {
    400         if (!m_pObjectState[m_ObjectSize]) {
    401             pCurObj->Release();
    402         }
    403     }
    404     m_pObjectState[m_ObjectSize] = FALSE;
    405 }
    406 void CPDF_StreamContentParser::EndName()
    407 {
    408     if (m_ObjectSize == 0) {
    409         AddNameParam((FX_LPCSTR)m_pWordBuf, m_WordSize);
    410         return;
    411     }
    412     CPDF_Object* pCurObj = m_pObjectStack[m_ObjectSize - 1];
    413     if (pCurObj->GetType() == PDFOBJ_ARRAY) {
    414         ((CPDF_Array*)pCurObj)->AddName(CFX_ByteString(m_pWordBuf, m_WordSize));
    415     } else {
    416         if (m_bDictName) {
    417             FXSYS_memcpy32(m_pDictName, m_pWordBuf, m_WordSize);
    418             m_pDictName[m_WordSize] = 0;
    419         } else {
    420             if (m_pDictName[0] != 0) {
    421                 ((CPDF_Dictionary*)pCurObj)->SetAtName((FX_LPCSTR)m_pDictName, CFX_ByteString(m_pWordBuf, m_WordSize));
    422             }
    423         }
    424         m_bDictName = !m_bDictName;
    425     }
    426 }
    427 void CPDF_StreamContentParser::EndNumber()
    428 {
    429     if (m_ObjectSize == 0) {
    430         AddNumberParam((FX_LPCSTR)m_pWordBuf, m_WordSize);
    431         return;
    432     }
    433     CPDF_Number *pObj = FX_NEW CPDF_Number(CFX_ByteStringC(m_pWordBuf, m_WordSize));
    434     if (!SetToCurObj(pObj)) {
    435         pObj->Release();
    436     }
    437 }
    438 extern CFX_ByteString _FPDF_ByteStringFromHex(CFX_BinaryBuf& src_buf);
    439 void CPDF_StreamContentParser::EndHexString()
    440 {
    441     CPDF_String *pObj = FX_NEW CPDF_String(_FPDF_ByteStringFromHex(m_StringBuf), TRUE);
    442     if (!SetToCurObj(pObj)) {
    443         pObj->Release();
    444     }
    445 }
    446 void CPDF_StreamContentParser::EndString()
    447 {
    448     CPDF_String *pObj = FX_NEW CPDF_String(m_StringBuf.GetByteString());
    449     if (!SetToCurObj(pObj)) {
    450         pObj->Release();
    451     }
    452 }
    453 void CPDF_StreamContentParser::Handle_BeginImage(void)
    454 {
    455     m_WordState = 9;
    456     m_InlineImageState = 0;
    457     m_StringBuf.Clear();
    458 }
    459 void _PDF_ReplaceAbbr(CPDF_Object* pObj);
    460 void CPDF_StreamContentParser::EndImageDict()
    461 {
    462     if (m_StringBuf.GetSize() != m_LastImageDict.GetSize() ||
    463             FXSYS_memcmp32(m_StringBuf.GetBuffer(), m_LastImageDict.GetBuffer(), m_StringBuf.GetSize())) {
    464         m_WordState = 0;
    465         StartDict();
    466         InputData(m_StringBuf.GetBuffer(), m_StringBuf.GetSize());
    467         Finish();
    468         m_bSameLastDict = FALSE;
    469         if (m_pLastImageDict && m_bReleaseLastDict) {
    470             m_pLastImageDict->Release();
    471             m_pLastImageDict = NULL;
    472         }
    473         if (!m_ObjectSize) {
    474             m_InlineImageState = 0;
    475             return;
    476         }
    477         m_pLastImageDict = (CPDF_Dictionary*)m_pObjectStack[--m_ObjectSize];
    478         m_bReleaseLastDict = !m_pObjectState[m_ObjectSize];
    479         m_pObjectState[m_ObjectSize] = FALSE;
    480         _PDF_ReplaceAbbr(m_pLastImageDict);
    481         m_LastImageDict.TakeOver(m_StringBuf);
    482         if (m_pLastImageDict->KeyExist(FX_BSTRC("ColorSpace"))) {
    483             CPDF_Object* pCSObj = m_pLastImageDict->GetElementValue(FX_BSTRC("ColorSpace"));
    484             if (pCSObj->GetType() == PDFOBJ_NAME) {
    485                 CFX_ByteString name = pCSObj->GetString();
    486                 if (name != FX_BSTRC("DeviceRGB") && name != FX_BSTRC("DeviceGray") && name != FX_BSTRC("DeviceCMYK")) {
    487                     pCSObj = FindResourceObj(FX_BSTRC("ColorSpace"), name);
    488                     if (pCSObj) {
    489                         if (!pCSObj->GetObjNum()) {
    490                             pCSObj = pCSObj->Clone();
    491                         }
    492                         m_pLastImageDict->SetAt(FX_BSTRC("ColorSpace"), pCSObj, m_pDocument);
    493                     }
    494                 }
    495             }
    496         }
    497     } else {
    498         m_bSameLastDict = TRUE;
    499     }
    500     m_ImageSrcBuf.Clear();
    501     if (m_pLastCloneImageDict) {
    502         m_pLastCloneImageDict->Release();
    503     }
    504     m_pLastCloneImageDict = (CPDF_Dictionary*)m_pLastImageDict->Clone();
    505     if (m_pLastCloneImageDict->KeyExist(FX_BSTRC("Filter"))) {
    506         m_WordState = 10;
    507         m_InlineImageState = 0;
    508     } else {
    509         int width = m_pLastCloneImageDict->GetInteger(FX_BSTRC("Width"));
    510         int height = m_pLastCloneImageDict->GetInteger(FX_BSTRC("Height"));
    511         int OrigSize = 0;
    512         CPDF_Object* pCSObj = m_pLastCloneImageDict->GetElementValue(FX_BSTRC("ColorSpace"));
    513         if (pCSObj != NULL) {
    514             int bpc = m_pLastCloneImageDict->GetInteger(FX_BSTRC("BitsPerComponent"));
    515             int nComponents = 1;
    516             CPDF_ColorSpace* pCS = m_pDocument->LoadColorSpace(pCSObj);
    517             if (pCS == NULL) {
    518                 nComponents = 3;
    519             } else {
    520                 nComponents = pCS->CountComponents();
    521                 m_pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
    522             }
    523             int pitch = (width * bpc * nComponents + 7) / 8;
    524             OrigSize = pitch * height;
    525         } else {
    526             OrigSize = ((width + 7) / 8) * height;
    527         }
    528         m_ImageSrcBuf.AppendBlock(NULL, OrigSize);
    529         m_WordState = 11;
    530         m_InlineImageState = 0;
    531     }
    532 }
    533 void CPDF_StreamContentParser::EndInlineImage()
    534 {
    535     CFX_AffineMatrix ImageMatrix;
    536     ImageMatrix.Copy(m_pCurStates->m_CTM);
    537     ImageMatrix.Concat(m_mtContentToUser);
    538     m_LastImageData.CopyData(m_ImageSrcBuf.GetBuffer(), m_ImageSrcBuf.GetSize());
    539     CPDF_Stream* pStream = CPDF_Stream::Create(m_ImageSrcBuf.GetBuffer(), m_ImageSrcBuf.GetSize(),
    540                            m_pLastCloneImageDict);
    541     m_ImageSrcBuf.DetachBuffer();
    542     m_pLastCloneImageDict = NULL;
    543     CPDF_InlineImages* pImages = FX_NEW CPDF_InlineImages;
    544     pImages->m_pStream = pStream;
    545     SetGraphicStates(pImages, !m_pLastCloneImageDict->KeyExist(FX_BSTRC("ColorSpace")), FALSE, FALSE);
    546     pImages->AddMatrix(ImageMatrix);
    547     m_pObjectList->m_ObjectList.AddTail(pImages);
    548     m_WordState = 0;
    549 }
    550 #define FXDWORD_TRUE FXDWORD_FROM_LSBFIRST(0x65757274)
    551 #define FXDWORD_NULL FXDWORD_FROM_LSBFIRST(0x6c6c756e)
    552 #define FXDWORD_FALS FXDWORD_FROM_LSBFIRST(0x736c6166)
    553 void CPDF_StreamContentParser::EndKeyword()
    554 {
    555     CPDF_Object *pObj = NULL;
    556     if (m_WordSize == 4) {
    557         if (*(FX_DWORD*)m_pWordBuf == FXDWORD_TRUE) {
    558             pObj = CPDF_Boolean::Create(TRUE);
    559             if (!SetToCurObj(pObj)) {
    560                 pObj->Release();
    561             }
    562             return;
    563         } else if (*(FX_DWORD*)m_pWordBuf == FXDWORD_NULL) {
    564             pObj = CPDF_Null::Create();
    565             if (!SetToCurObj(pObj)) {
    566                 pObj->Release();
    567             }
    568             return;
    569         }
    570     } else if (m_WordSize == 5) {
    571         if (*(FX_DWORD*)m_pWordBuf == FXDWORD_FALS && m_pWordBuf[4] == 'e') {
    572             pObj = CPDF_Boolean::Create(FALSE);
    573             if (!SetToCurObj(pObj)) {
    574                 pObj->Release();
    575             }
    576             return;
    577         }
    578     }
    579     m_pWordBuf[m_WordSize] = 0;
    580     OnOperator((char*)m_pWordBuf);
    581     ClearAllParams();
    582 }
    583 #define PAGEPARSE_STAGE_PARSE			2
    584 #define PAGEPARSE_STAGE_CHECKCLIP		3
    585 CPDF_ContentParser::CPDF_ContentParser()
    586 {
    587     m_pParser = NULL;
    588     m_Status = Ready;
    589     m_pStreamFilter = NULL;
    590     m_pType3Char = NULL;
    591 }
    592 CPDF_ContentParser::~CPDF_ContentParser()
    593 {
    594     Clear();
    595 }
    596 void CPDF_ContentParser::Clear()
    597 {
    598     if (m_pParser) {
    599         delete m_pParser;
    600     }
    601     if (m_pStreamFilter) {
    602         delete m_pStreamFilter;
    603     }
    604     m_pParser = NULL;
    605     m_Status = Ready;
    606 }
    607 void CPDF_ContentParser::Start(CPDF_Page* pPage, CPDF_ParseOptions* pOptions)
    608 {
    609     if (m_Status != Ready || pPage == NULL || pPage->m_pDocument == NULL || pPage->m_pFormDict == NULL) {
    610         m_Status = Done;
    611         return;
    612     }
    613     m_pObjects = pPage;
    614     m_bForm = FALSE;
    615     if (pOptions) {
    616         m_Options = *pOptions;
    617     }
    618     CPDF_Object* pContent = pPage->m_pFormDict->GetElementValue(FX_BSTRC("Contents"));
    619     if (pContent == NULL) {
    620         m_Status = Done;
    621         return;
    622     }
    623     if (pContent->GetType() == PDFOBJ_STREAM) {
    624         m_nStreams = 1;
    625     } else if (pContent->GetType() == PDFOBJ_ARRAY) {
    626         m_nStreams = ((CPDF_Array*)pContent)->GetCount();
    627     } else {
    628         m_Status = Done;
    629         return;
    630     }
    631     m_Status = ToBeContinued;
    632     m_InternalStage = PAGEPARSE_STAGE_PARSE;
    633     m_CurrentOffset = 0;
    634     m_pParser = FX_NEW CPDF_StreamContentParser;
    635     m_pParser->Initialize();
    636     m_pParser->PrepareParse(pPage->m_pDocument, pPage->m_pResources, NULL, NULL, pPage,
    637                             pPage->m_pResources, &pPage->m_BBox, &m_Options, NULL, 0);
    638     m_pParser->m_pCurStates->m_ColorState.GetModify()->Default();
    639 }
    640 void CPDF_ContentParser::Start(CPDF_Form* pForm, CPDF_AllStates* pGraphicStates, CFX_AffineMatrix* pParentMatrix,
    641                                CPDF_Type3Char* pType3Char, CPDF_ParseOptions* pOptions, int level)
    642 {
    643     m_pType3Char = pType3Char;
    644     m_pObjects = pForm;
    645     m_bForm = TRUE;
    646     CFX_AffineMatrix form_matrix = pForm->m_pFormDict->GetMatrix(FX_BSTRC("Matrix"));
    647     if (pGraphicStates) {
    648         form_matrix.Concat(pGraphicStates->m_CTM);
    649     }
    650     CPDF_Array* pBBox = pForm->m_pFormDict->GetArray(FX_BSTRC("BBox"));
    651     CFX_FloatRect form_bbox;
    652     CPDF_Path ClipPath;
    653     if (pBBox) {
    654         form_bbox = pBBox->GetRect();
    655         ClipPath.New();
    656         ClipPath.AppendRect(form_bbox.left, form_bbox.bottom, form_bbox.right, form_bbox.top);
    657         ClipPath.Transform(&form_matrix);
    658         if (pParentMatrix) {
    659             ClipPath.Transform(pParentMatrix);
    660         }
    661         form_bbox.Transform(&form_matrix);
    662     }
    663     CPDF_Dictionary* pResources = pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
    664     m_pParser = FX_NEW CPDF_StreamContentParser;
    665     m_pParser->Initialize();
    666     m_pParser->PrepareParse(pForm->m_pDocument, pForm->m_pPageResources, pForm->m_pResources, pParentMatrix, pForm,
    667                             pResources, &form_bbox, pOptions, pGraphicStates, level);
    668     m_pParser->m_pCurStates->m_CTM = form_matrix;
    669     if (ClipPath.NotNull()) {
    670         m_pParser->m_pCurStates->m_ClipPath.AppendPath(ClipPath, FXFILL_WINDING, TRUE);
    671     }
    672     if (pForm->m_Transparency & PDFTRANS_GROUP) {
    673         CPDF_GeneralStateData* pData = m_pParser->m_pCurStates->m_GeneralState.GetModify();
    674         pData->m_BlendType = FXDIB_BLEND_NORMAL;
    675         pData->m_StrokeAlpha = 1.0f;
    676         pData->m_FillAlpha = 1.0f;
    677         pData->m_pSoftMask = NULL;
    678     }
    679     m_pStreamFilter = pForm->m_pFormStream->GetStreamFilter();
    680     m_nStreams = 1;
    681     m_Status = ToBeContinued;
    682     m_InternalStage = PAGEPARSE_STAGE_PARSE;
    683     m_CurrentOffset = 0;
    684 }
    685 void CPDF_ContentParser::Continue(IFX_Pause* pPause)
    686 {
    687     while (m_Status == ToBeContinued) {
    688         if (m_InternalStage == PAGEPARSE_STAGE_PARSE) {
    689             if (m_pStreamFilter == NULL) {
    690                 if (m_CurrentOffset == m_nStreams) {
    691                     m_InternalStage = PAGEPARSE_STAGE_CHECKCLIP;
    692                     if (m_pType3Char) {
    693                         m_pType3Char->m_bColored = m_pParser->m_bColored;
    694                         m_pType3Char->m_Width = FXSYS_round(m_pParser->m_Type3Data[0] * 1000);
    695                         m_pType3Char->m_BBox.left = FXSYS_round(m_pParser->m_Type3Data[2] * 1000);
    696                         m_pType3Char->m_BBox.bottom = FXSYS_round(m_pParser->m_Type3Data[3] * 1000);
    697                         m_pType3Char->m_BBox.right = FXSYS_round(m_pParser->m_Type3Data[4] * 1000);
    698                         m_pType3Char->m_BBox.top = FXSYS_round(m_pParser->m_Type3Data[5] * 1000);
    699                         m_pType3Char->m_bPageRequired = m_pParser->m_bResourceMissing;
    700                     }
    701                     delete m_pParser;
    702                     m_pParser = NULL;
    703                     continue;
    704                 }
    705                 CPDF_Object* pContent = m_pObjects->m_pFormDict->GetElementValue(FX_BSTRC("Contents"));
    706                 if (pContent->GetType() == PDFOBJ_STREAM) {
    707                     m_pStreamFilter = ((CPDF_Stream*)pContent)->GetStreamFilter();
    708                 } else {
    709                     CPDF_Stream* pStream = ((CPDF_Array*)pContent)->GetStream(m_CurrentOffset);
    710                     if (pStream == NULL) {
    711                         m_CurrentOffset ++;
    712                         continue;
    713                     }
    714                     m_pStreamFilter = pStream->GetStreamFilter();
    715                 }
    716             }
    717             FX_DWORD len = m_pStreamFilter->ReadBlock(m_pParser->m_pStreamBuf, STREAM_PARSE_BUFSIZE);
    718             m_pParser->InputData(m_pParser->m_pStreamBuf, len);
    719             if (m_pParser->m_bAbort) {
    720                 delete m_pStreamFilter;
    721                 m_pStreamFilter = NULL;
    722                 m_Status = Done;
    723                 delete m_pParser;
    724                 m_pParser = NULL;
    725                 return;
    726             }
    727             if (len < STREAM_PARSE_BUFSIZE) {
    728                 m_pParser->Finish();
    729                 m_CurrentOffset ++;
    730                 delete m_pStreamFilter;
    731                 m_pStreamFilter = NULL;
    732             }
    733             if (pPause && pPause->NeedToPauseNow()) {
    734                 return;
    735             }
    736         }
    737         if (m_InternalStage == PAGEPARSE_STAGE_CHECKCLIP) {
    738             FX_POSITION pos = m_pObjects->m_ObjectList.GetHeadPosition();
    739             while (pos) {
    740                 CPDF_PageObject* pObj = (CPDF_PageObject*)m_pObjects->m_ObjectList.GetNext(pos);
    741                 if (pObj == NULL) {
    742                     continue;
    743                 }
    744                 if (pObj->m_ClipPath.IsNull()) {
    745                     continue;
    746                 }
    747                 if (pObj->m_ClipPath.GetPathCount() != 1) {
    748                     continue;
    749                 }
    750                 if (pObj->m_ClipPath.GetTextCount()) {
    751                     continue;
    752                 }
    753                 CPDF_Path ClipPath = pObj->m_ClipPath.GetPath(0);
    754                 if (!ClipPath.IsRect() || pObj->m_Type == PDFPAGE_SHADING) {
    755                     continue;
    756                 }
    757                 CFX_FloatRect old_rect(ClipPath.GetPointX(0), ClipPath.GetPointY(0),
    758                                        ClipPath.GetPointX(2), ClipPath.GetPointY(2));
    759                 CFX_FloatRect obj_rect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top);
    760                 if (old_rect.Contains(obj_rect)) {
    761                     pObj->m_ClipPath.SetNull();
    762                 }
    763             }
    764             if (m_pObjects->m_ObjectList.GetCount() == 1) {
    765                 CPDF_PageObject* pObj = (CPDF_PageObject*)m_pObjects->m_ObjectList.GetAt(m_pObjects->m_ObjectList.GetHeadPosition());
    766                 if (pObj && pObj->m_Type == PDFPAGE_TEXT) {
    767                     CPDF_TextObject* pText = (CPDF_TextObject*)pObj;
    768                 }
    769             }
    770             m_Status = Done;
    771             return;
    772         }
    773     }
    774 }
    775 int CPDF_ContentParser::EstimateProgress()
    776 {
    777     if (m_Status == Ready) {
    778         return 0;
    779     }
    780     if (m_Status == Done) {
    781         return 100;
    782     }
    783     if (m_InternalStage == PAGEPARSE_STAGE_CHECKCLIP) {
    784         return 90;
    785     }
    786     if (m_pStreamFilter == NULL) {
    787         return 90 * m_CurrentOffset / m_nStreams;
    788     }
    789     int total_raw_size = m_pStreamFilter->GetStream()->GetRawSize() * m_nStreams;
    790     int parsed_raw_size = m_pStreamFilter->GetStream()->GetRawSize() * m_CurrentOffset +
    791                           m_pStreamFilter->GetSrcPos();
    792     return 90 * parsed_raw_size / total_raw_size;
    793 }
    794 CPDF_InlineImages::CPDF_InlineImages()
    795 {
    796     m_Type = PDFPAGE_INLINES;
    797     m_pStream = NULL;
    798     m_pBitmap = NULL;
    799 }
    800 CPDF_InlineImages::~CPDF_InlineImages()
    801 {
    802     if (m_pStream) {
    803         m_pStream->Release();
    804     }
    805     if (m_pBitmap) {
    806         delete m_pBitmap;
    807     }
    808 }
    809 void CPDF_InlineImages::AddMatrix(CFX_AffineMatrix& matrix)
    810 {
    811     m_Matrices.Add(matrix);
    812     CFX_FloatRect rect = matrix.GetUnitRect();
    813     if (m_Matrices.GetSize() > 1) {
    814         CFX_FloatRect rect1(m_Left, m_Bottom, m_Right, m_Top);
    815         rect.Union(rect1);
    816     }
    817     m_Left = rect.left;
    818     m_Right = rect.right;
    819     m_Top = rect.top;
    820     m_Bottom = rect.bottom;
    821 }
    822 #endif
    823