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_)
11extern const FX_LPCSTR _PDF_CharType;
12void 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];
20start:
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}
291void 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}
325void 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}
333FX_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}
353void 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}
362void 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}
381void CPDF_StreamContentParser::StartDict()
382{
383    CPDF_Dictionary* pDict = FX_NEW CPDF_Dictionary;
384    AddContainer(pDict);
385    m_bDictName = TRUE;
386}
387void 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}
406void 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}
427void 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}
438extern CFX_ByteString _FPDF_ByteStringFromHex(CFX_BinaryBuf& src_buf);
439void 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}
446void CPDF_StreamContentParser::EndString()
447{
448    CPDF_String *pObj = FX_NEW CPDF_String(m_StringBuf.GetByteString());
449    if (!SetToCurObj(pObj)) {
450        pObj->Release();
451    }
452}
453void CPDF_StreamContentParser::Handle_BeginImage(void)
454{
455    m_WordState = 9;
456    m_InlineImageState = 0;
457    m_StringBuf.Clear();
458}
459void _PDF_ReplaceAbbr(CPDF_Object* pObj);
460void 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}
533void 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)
553void 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
585CPDF_ContentParser::CPDF_ContentParser()
586{
587    m_pParser = NULL;
588    m_Status = Ready;
589    m_pStreamFilter = NULL;
590    m_pType3Char = NULL;
591}
592CPDF_ContentParser::~CPDF_ContentParser()
593{
594    Clear();
595}
596void 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}
607void 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}
640void 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}
685void 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}
775int 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}
794CPDF_InlineImages::CPDF_InlineImages()
795{
796    m_Type = PDFPAGE_INLINES;
797    m_pStream = NULL;
798    m_pBitmap = NULL;
799}
800CPDF_InlineImages::~CPDF_InlineImages()
801{
802    if (m_pStream) {
803        m_pStream->Release();
804    }
805    if (m_pBitmap) {
806        delete m_pBitmap;
807    }
808}
809void 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