Add m_pDocument in CPDF_Color and check if page date has been forced clear
[pdfium.git] / core / src / fpdfapi / fpdf_page / fpdf_page_parser_new.cpp
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