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.
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
7 #include "../../../include/fpdfapi/fpdf_page.h"
8 #include "../../../include/fpdfapi/fpdf_module.h"
9 #include "../../../include/fxcodec/fx_codec.h"
12 extern const FX_LPCSTR _PDF_OpCharType =
13 "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
14 "IIVIIIIVIIVIIIIIVVIIIIIIIIIIIIII"
15 "IIVVVVVVIVVVVVVIVVVVVIIVVIIIIIII"
16 "IIVVVVVVVVVVVVVVIVVVIIVVIVVIIIII"
17 "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
18 "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
19 "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
20 "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII";
21 FX_BOOL _PDF_HasInvalidOpChar(FX_LPCSTR op)
28 if(_PDF_OpCharType[ch] == 'I') {
34 class CPDF_StreamParserAutoClearer {
36 CPDF_StreamParserAutoClearer(CPDF_StreamParser** scoped_variable, CPDF_StreamParser* new_parser)
37 : scoped_variable_(scoped_variable) {
38 *scoped_variable_ = new_parser;
40 ~CPDF_StreamParserAutoClearer() { *scoped_variable_ = NULL; }
42 CPDF_StreamParser** scoped_variable_;
44 FX_DWORD CPDF_StreamContentParser::Parse(FX_LPCBYTE pData, FX_DWORD dwSize, FX_DWORD max_cost)
46 if (m_Level > _FPDF_MAX_FORM_LEVEL_) {
49 FX_DWORD InitObjCount = m_pObjectList->CountObjects();
50 CPDF_StreamParser syntax(pData, dwSize);
51 CPDF_StreamParserAutoClearer auto_clearer(&m_pSyntax, &syntax);
54 FX_DWORD cost = m_pObjectList->CountObjects() - InitObjCount;
55 if (max_cost && cost >= max_cost) {
58 switch (syntax.ParseNextElement()) {
59 case CPDF_StreamParser::EndOfData:
60 return m_pSyntax->GetPos();
61 case CPDF_StreamParser::Keyword:
62 if(!OnOperator((char*)syntax.GetWordBuf()) && _PDF_HasInvalidOpChar((char*)syntax.GetWordBuf())) {
66 return m_pSyntax->GetPos();
70 case CPDF_StreamParser::Number:
71 AddNumberParam((char*)syntax.GetWordBuf(), syntax.GetWordSize());
73 case CPDF_StreamParser::Name:
74 AddNameParam((FX_LPCSTR)syntax.GetWordBuf() + 1, syntax.GetWordSize() - 1);
77 AddObjectParam(syntax.GetObject());
80 return m_pSyntax->GetPos();
82 void _PDF_ReplaceAbbr(CPDF_Object* pObj);
83 void CPDF_StreamContentParser::Handle_BeginImage()
85 FX_FILESIZE savePos = m_pSyntax->GetPos();
86 CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
88 CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement();
89 if (type == CPDF_StreamParser::Keyword) {
90 CFX_ByteString bsKeyword(m_pSyntax->GetWordBuf(), m_pSyntax->GetWordSize());
91 if (bsKeyword != FX_BSTRC("ID")) {
92 m_pSyntax->SetPos(savePos);
97 if (type != CPDF_StreamParser::Name) {
100 CFX_ByteString key((FX_LPCSTR)m_pSyntax->GetWordBuf() + 1, m_pSyntax->GetWordSize() - 1);
101 CPDF_Object* pObj = m_pSyntax->ReadNextObject();
102 if (!key.IsEmpty()) {
103 pDict->SetAt(key, pObj, m_pDocument);
108 _PDF_ReplaceAbbr(pDict);
109 CPDF_Object* pCSObj = NULL;
110 if (pDict->KeyExist(FX_BSTRC("ColorSpace"))) {
111 pCSObj = pDict->GetElementValue(FX_BSTRC("ColorSpace"));
112 if (pCSObj->GetType() == PDFOBJ_NAME) {
113 CFX_ByteString name = pCSObj->GetString();
114 if (name != FX_BSTRC("DeviceRGB") && name != FX_BSTRC("DeviceGray") && name != FX_BSTRC("DeviceCMYK")) {
115 pCSObj = FindResourceObj(FX_BSTRC("ColorSpace"), name);
116 if (pCSObj && !pCSObj->GetObjNum()) {
117 pCSObj = pCSObj->Clone();
118 pDict->SetAt(FX_BSTRC("ColorSpace"), pCSObj, m_pDocument);
123 CPDF_Stream* pStream = m_pSyntax->ReadInlineStream(m_pDocument, pDict, pCSObj, m_Options.m_bDecodeInlineImage);
125 CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement();
126 if (type == CPDF_StreamParser::EndOfData) {
129 if (type != CPDF_StreamParser::Keyword) {
132 if (m_pSyntax->GetWordSize() == 2 && m_pSyntax->GetWordBuf()[0] == 'E' &&
133 m_pSyntax->GetWordBuf()[1] == 'I') {
137 if (m_Options.m_bTextOnly) {
145 pDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Image"));
146 CPDF_ImageObject *pImgObj = AddImage(pStream, NULL, TRUE);
155 void CPDF_StreamContentParser::ParsePathObject()
157 FX_FLOAT params[6] = {0};
159 int last_pos = m_pSyntax->GetPos();
161 CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement();
162 FX_BOOL bProcessed = TRUE;
164 case CPDF_StreamParser::EndOfData:
166 case CPDF_StreamParser::Keyword: {
167 int len = m_pSyntax->GetWordSize();
169 switch (m_pSyntax->GetWordBuf()[0]) {
171 AddPathPoint(params[0], params[1], FXPT_MOVETO);
175 AddPathPoint(params[0], params[1], FXPT_LINETO);
179 AddPathPoint(params[0], params[1], FXPT_BEZIERTO);
180 AddPathPoint(params[2], params[3], FXPT_BEZIERTO);
181 AddPathPoint(params[4], params[5], FXPT_BEZIERTO);
185 AddPathPoint(m_PathCurrentX, m_PathCurrentY, FXPT_BEZIERTO);
186 AddPathPoint(params[0], params[1], FXPT_BEZIERTO);
187 AddPathPoint(params[2], params[3], FXPT_BEZIERTO);
191 AddPathPoint(params[0], params[1], FXPT_BEZIERTO);
192 AddPathPoint(params[2], params[3], FXPT_BEZIERTO);
193 AddPathPoint(params[2], params[3], FXPT_BEZIERTO);
204 } else if (len == 2) {
205 if (m_pSyntax->GetWordBuf()[0] == 'r' && m_pSyntax->GetWordBuf()[1] == 'e') {
206 AddPathRect(params[0], params[1], params[2], params[3]);
215 last_pos = m_pSyntax->GetPos();
219 case CPDF_StreamParser::Number: {
225 FX_atonum(CFX_ByteStringC(m_pSyntax->GetWordBuf(), m_pSyntax->GetWordSize()), bInteger, &value);
226 params[nParams++] = bInteger ? (FX_FLOAT)value : *(FX_FLOAT*)&value;
233 m_pSyntax->SetPos(last_pos);
238 CPDF_StreamParser::CPDF_StreamParser(const FX_BYTE* pData, FX_DWORD dwSize)
245 CPDF_StreamParser::~CPDF_StreamParser()
248 m_pLastObj->Release();
251 FX_DWORD _DecodeAllScanlines(ICodec_ScanlineDecoder* pDecoder, FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
253 if (pDecoder == NULL) {
254 return (FX_DWORD) - 1;
256 int ncomps = pDecoder->CountComps();
257 int bpc = pDecoder->GetBPC();
258 int width = pDecoder->GetWidth();
259 int height = pDecoder->GetHeight();
260 int pitch = (width * ncomps * bpc + 7) / 8;
261 if (height == 0 || pitch > (1 << 30) / height) {
265 dest_buf = FX_Alloc2D(FX_BYTE, pitch, height);
266 dest_size = pitch * height; // Safe since checked alloc returned.
267 for (int row = 0; row < height; row ++) {
268 FX_LPBYTE pLine = pDecoder->GetScanline(row);
272 FXSYS_memcpy32(dest_buf + row * pitch, pLine, pitch);
274 FX_DWORD srcoff = pDecoder->GetSrcOffset();
278 ICodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
279 const CPDF_Dictionary* pParams);
280 FX_DWORD _A85Decode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size);
281 FX_DWORD _HexDecode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size);
282 FX_DWORD FPDFAPI_FlateOrLZWDecode(FX_BOOL bLZW, const FX_BYTE* src_buf, FX_DWORD src_size, CPDF_Dictionary* pParams,
283 FX_DWORD estimated_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size);
284 FX_DWORD PDF_DecodeInlineStream(const FX_BYTE* src_buf, FX_DWORD limit,
285 int width, int height, CFX_ByteString& decoder,
286 CPDF_Dictionary* pParam, FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
288 if (decoder == FX_BSTRC("CCITTFaxDecode") || decoder == FX_BSTRC("CCF")) {
289 ICodec_ScanlineDecoder* pDecoder = FPDFAPI_CreateFaxDecoder(src_buf, limit, width, height, pParam);
290 return _DecodeAllScanlines(pDecoder, dest_buf, dest_size);
291 } else if (decoder == FX_BSTRC("ASCII85Decode") || decoder == FX_BSTRC("A85")) {
292 return _A85Decode(src_buf, limit, dest_buf, dest_size);
293 } else if (decoder == FX_BSTRC("ASCIIHexDecode") || decoder == FX_BSTRC("AHx")) {
294 return _HexDecode(src_buf, limit, dest_buf, dest_size);
295 } else if (decoder == FX_BSTRC("FlateDecode") || decoder == FX_BSTRC("Fl")) {
296 return FPDFAPI_FlateOrLZWDecode(FALSE, src_buf, limit, pParam, dest_size, dest_buf, dest_size);
297 } else if (decoder == FX_BSTRC("LZWDecode") || decoder == FX_BSTRC("LZW")) {
298 return FPDFAPI_FlateOrLZWDecode(TRUE, src_buf, limit, pParam, 0, dest_buf, dest_size);
299 } else if (decoder == FX_BSTRC("DCTDecode") || decoder == FX_BSTRC("DCT")) {
300 ICodec_ScanlineDecoder* pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(
301 src_buf, limit, width, height, 0, pParam ? pParam->GetInteger(FX_BSTRC("ColorTransform"), 1) : 1);
302 return _DecodeAllScanlines(pDecoder, dest_buf, dest_size);
303 } else if (decoder == FX_BSTRC("RunLengthDecode") || decoder == FX_BSTRC("RL")) {
304 return RunLengthDecode(src_buf, limit, dest_buf, dest_size);
308 return (FX_DWORD) - 1;
310 CPDF_Stream* CPDF_StreamParser::ReadInlineStream(CPDF_Document* pDoc, CPDF_Dictionary* pDict, CPDF_Object* pCSObj, FX_BOOL bDecode)
312 if (m_Pos == m_Size) {
315 if (PDF_CharType[m_pBuf[m_Pos]] == 'W') {
318 CFX_ByteString Decoder;
319 CPDF_Dictionary* pParam = NULL;
320 CPDF_Object* pFilter = pDict->GetElementValue(FX_BSTRC("Filter"));
321 if (pFilter == NULL) {
322 } else if (pFilter->GetType() == PDFOBJ_ARRAY) {
323 Decoder = ((CPDF_Array*)pFilter)->GetString(0);
324 CPDF_Array* pParams = pDict->GetArray(FX_BSTRC("DecodeParms"));
326 pParam = pParams->GetDict(0);
329 Decoder = pFilter->GetString();
330 pParam = pDict->GetDict(FX_BSTRC("DecodeParms"));
332 FX_DWORD width = pDict->GetInteger(FX_BSTRC("Width"));
333 FX_DWORD height = pDict->GetInteger(FX_BSTRC("Height"));
334 FX_DWORD OrigSize = 0;
335 if (pCSObj != NULL) {
336 FX_DWORD bpc = pDict->GetInteger(FX_BSTRC("BitsPerComponent"));
337 FX_DWORD nComponents = 1;
338 CPDF_ColorSpace* pCS = pDoc->LoadColorSpace(pCSObj);
342 nComponents = pCS->CountComponents();
343 pDoc->GetPageData()->ReleaseColorSpace(pCSObj);
345 FX_DWORD pitch = width;
346 if (bpc && pitch > INT_MAX / bpc) {
350 if (nComponents && pitch > INT_MAX / nComponents) {
353 pitch *= nComponents;
354 if (pitch > INT_MAX - 7) {
361 if (width > INT_MAX - 7) {
364 OrigSize = ((width + 7) / 8);
366 if (height && OrigSize > INT_MAX / height) {
370 FX_LPBYTE pData = NULL;
371 FX_DWORD dwStreamSize;
372 if (Decoder.IsEmpty()) {
373 if (OrigSize > m_Size - m_Pos) {
374 OrigSize = m_Size - m_Pos;
376 pData = FX_Alloc(FX_BYTE, OrigSize);
377 FXSYS_memcpy32(pData, m_pBuf + m_Pos, OrigSize);
378 dwStreamSize = OrigSize;
381 FX_DWORD dwDestSize = OrigSize;
382 dwStreamSize = PDF_DecodeInlineStream(m_pBuf + m_Pos, m_Size - m_Pos, width, height, Decoder, pParam,
384 if ((int)dwStreamSize < 0) {
388 m_Pos += dwStreamSize;
389 dwStreamSize = dwDestSize;
390 if (pFilter->GetType() == PDFOBJ_ARRAY) {
391 ((CPDF_Array*)pFilter)->RemoveAt(0);
392 CPDF_Array* pParams = pDict->GetArray(FX_BSTRC("DecodeParms"));
394 pParams->RemoveAt(0);
397 pDict->RemoveAt(FX_BSTRC("Filter"));
398 pDict->RemoveAt(FX_BSTRC("DecodeParms"));
404 FX_DWORD dwSavePos = m_Pos;
405 m_Pos += dwStreamSize;
407 FX_DWORD dwPrevPos = m_Pos;
408 CPDF_StreamParser::SyntaxType type = ParseNextElement();
409 if (type == CPDF_StreamParser::EndOfData) {
412 if (type != CPDF_StreamParser::Keyword) {
413 dwStreamSize += m_Pos - dwPrevPos;
416 if (GetWordSize() == 2 && GetWordBuf()[0] == 'E' &&
417 GetWordBuf()[1] == 'I') {
421 dwStreamSize += m_Pos - dwPrevPos;
424 pData = FX_Alloc(FX_BYTE, dwStreamSize);
425 FXSYS_memcpy32(pData, m_pBuf + m_Pos, dwStreamSize);
426 m_Pos += dwStreamSize;
429 pDict->SetAtInteger(FX_BSTRC("Length"), (int)dwStreamSize);
430 return CPDF_Stream::Create(pData, dwStreamSize, pDict);
432 #define MAX_WORD_BUFFER 256
433 #define MAX_STRING_LENGTH 32767
434 #define FXDWORD_TRUE FXDWORD_FROM_LSBFIRST(0x65757274)
435 #define FXDWORD_NULL FXDWORD_FROM_LSBFIRST(0x6c6c756e)
436 #define FXDWORD_FALS FXDWORD_FROM_LSBFIRST(0x736c6166)
437 CPDF_StreamParser::SyntaxType CPDF_StreamParser::ParseNextElement()
440 m_pLastObj->Release();
444 FX_BOOL bIsNumber = TRUE;
445 if (m_Pos >= m_Size) {
448 int ch = m_pBuf[m_Pos++];
449 int type = PDF_CharType[ch];
451 while (type == 'W') {
452 if (m_Size <= m_Pos) {
455 ch = m_pBuf[m_Pos++];
456 type = PDF_CharType[ch];
462 if (m_Size <= m_Pos) {
465 ch = m_pBuf[m_Pos++];
466 if (ch == '\r' || ch == '\n') {
470 type = PDF_CharType[ch];
472 if (type == 'D' && ch != '/') {
474 m_pLastObj = ReadNextObject();
478 if (m_WordSize < MAX_WORD_BUFFER) {
479 m_WordBuffer[m_WordSize++] = ch;
484 if (m_Size <= m_Pos) {
487 ch = m_pBuf[m_Pos++];
488 type = PDF_CharType[ch];
489 if (type == 'D' || type == 'W') {
494 m_WordBuffer[m_WordSize] = 0;
498 if (m_WordBuffer[0] == '/') {
501 if (m_WordSize == 4) {
502 if (*(FX_DWORD*)m_WordBuffer == FXDWORD_TRUE) {
503 m_pLastObj = CPDF_Boolean::Create(TRUE);
506 if (*(FX_DWORD*)m_WordBuffer == FXDWORD_NULL) {
507 m_pLastObj = CPDF_Null::Create();
510 } else if (m_WordSize == 5) {
511 if (*(FX_DWORD*)m_WordBuffer == FXDWORD_FALS && m_WordBuffer[4] == 'e') {
512 m_pLastObj = CPDF_Boolean::Create(FALSE);
518 void CPDF_StreamParser::SkipPathObject()
520 FX_DWORD command_startpos = m_Pos;
521 if (m_Pos >= m_Size) {
524 int ch = m_pBuf[m_Pos++];
525 int type = PDF_CharType[ch];
527 while (type == 'W') {
528 if (m_Pos >= m_Size) {
531 ch = m_pBuf[m_Pos++];
532 type = PDF_CharType[ch];
535 m_Pos = command_startpos;
539 while (type != 'W') {
540 if (m_Pos >= m_Size) {
543 ch = m_pBuf[m_Pos++];
544 type = PDF_CharType[ch];
546 while (type == 'W') {
547 if (m_Pos >= m_Size) {
550 ch = m_pBuf[m_Pos++];
551 type = PDF_CharType[ch];
556 FX_DWORD op_startpos = m_Pos - 1;
557 while (type != 'W' && type != 'D') {
558 if (m_Pos >= m_Size) {
561 ch = m_pBuf[m_Pos++];
562 type = PDF_CharType[ch];
564 if (m_Pos - op_startpos == 2) {
565 int op = m_pBuf[op_startpos];
566 if (op == 'm' || op == 'l' || op == 'c' || op == 'v' || op == 'y') {
567 command_startpos = m_Pos;
570 } else if (m_Pos - op_startpos == 3) {
571 if (m_pBuf[op_startpos] == 'r' && m_pBuf[op_startpos + 1] == 'e') {
572 command_startpos = m_Pos;
576 m_Pos = command_startpos;
581 CPDF_Object* CPDF_StreamParser::ReadNextObject(FX_BOOL bAllowNestedArray, FX_BOOL bInArray)
584 GetNextWord(bIsNumber);
585 if (m_WordSize == 0) {
589 m_WordBuffer[m_WordSize] = 0;
590 return CPDF_Number::Create(CFX_ByteStringC(m_WordBuffer, m_WordSize));
592 int first_char = m_WordBuffer[0];
593 if (first_char == '/') {
594 return CPDF_Name::Create(PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
596 if (first_char == '(') {
597 return CPDF_String::Create(ReadString());
599 if (first_char == '<') {
600 if (m_WordSize == 1) {
601 return CPDF_String::Create(ReadHexString(), TRUE);
603 CPDF_Dictionary* pDict = CPDF_Dictionary::Create();
605 GetNextWord(bIsNumber);
606 if (m_WordSize == 0) {
610 if (m_WordSize == 2 && m_WordBuffer[0] == '>') {
613 if (m_WordBuffer[0] != '/') {
617 CFX_ByteString key = PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1));
618 CPDF_Object* pObj = ReadNextObject(TRUE);
625 if (!key.IsEmpty()) {
626 pDict->SetAt(key, pObj);
633 if (first_char == '[') {
634 if (!bAllowNestedArray && bInArray) {
637 CPDF_Array* pArray = CPDF_Array::Create();
639 CPDF_Object* pObj = ReadNextObject(bAllowNestedArray, TRUE);
641 if (m_WordSize == 0 || m_WordBuffer[0] == ']') {
644 if (m_WordBuffer[0] == '[') {
652 if (m_WordSize == 4) {
653 if (*(FX_DWORD*)m_WordBuffer == FXDWORD_TRUE) {
654 return CPDF_Boolean::Create(TRUE);
656 if (*(FX_DWORD*)m_WordBuffer == FXDWORD_NULL) {
657 return CPDF_Null::Create();
659 } else if (m_WordSize == 5) {
660 if (*(FX_DWORD*)m_WordBuffer == FXDWORD_FALS && m_WordBuffer[4] == 'e') {
661 return CPDF_Boolean::Create(FALSE);
666 void CPDF_StreamParser::GetNextWord(FX_BOOL& bIsNumber)
670 if (m_Size <= m_Pos) {
673 int ch = m_pBuf[m_Pos++];
674 int type = PDF_CharType[ch];
676 while (type == 'W') {
677 if (m_Size <= m_Pos) {
680 ch = m_pBuf[m_Pos++];
681 type = PDF_CharType[ch];
687 if (m_Size <= m_Pos) {
690 ch = m_pBuf[m_Pos++];
691 if (ch == '\r' || ch == '\n') {
695 type = PDF_CharType[ch];
699 m_WordBuffer[m_WordSize++] = ch;
702 if (m_Size <= m_Pos) {
705 ch = m_pBuf[m_Pos++];
706 type = PDF_CharType[ch];
707 if (type != 'R' && type != 'N') {
711 if (m_WordSize < MAX_WORD_BUFFER) {
712 m_WordBuffer[m_WordSize++] = ch;
715 } else if (ch == '<') {
716 if (m_Size <= m_Pos) {
719 ch = m_pBuf[m_Pos++];
721 m_WordBuffer[m_WordSize++] = ch;
725 } else if (ch == '>') {
726 if (m_Size <= m_Pos) {
729 ch = m_pBuf[m_Pos++];
731 m_WordBuffer[m_WordSize++] = ch;
739 if (m_WordSize < MAX_WORD_BUFFER) {
740 m_WordBuffer[m_WordSize++] = ch;
745 if (m_Size <= m_Pos) {
748 ch = m_pBuf[m_Pos++];
749 type = PDF_CharType[ch];
750 if (type == 'D' || type == 'W') {
756 CFX_ByteString CPDF_StreamParser::ReadString()
758 if (m_Size <= m_Pos) {
759 return CFX_ByteString();
761 int ch = m_pBuf[m_Pos++];
764 int status = 0, iEscCode = 0;
770 if (buf.GetLength() > MAX_STRING_LENGTH) {
771 return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH);
773 return buf.GetByteString();
777 } else if (ch == '(') {
780 } else if (ch == '\\') {
783 buf.AppendChar((char)ch);
787 if (ch >= '0' && ch <= '7') {
793 buf.AppendChar('\n');
794 } else if (ch == 'r') {
795 buf.AppendChar('\r');
796 } else if (ch == 't') {
797 buf.AppendChar('\t');
798 } else if (ch == 'b') {
799 buf.AppendChar('\b');
800 } else if (ch == 'f') {
801 buf.AppendChar('\f');
802 } else if (ch == '\r') {
805 } else if (ch == '\n') {
812 if (ch >= '0' && ch <= '7') {
813 iEscCode = iEscCode * 8 + ch - '0';
816 buf.AppendChar(iEscCode);
822 if (ch >= '0' && ch <= '7') {
823 iEscCode = iEscCode * 8 + ch - '0';
824 buf.AppendChar(iEscCode);
827 buf.AppendChar(iEscCode);
839 if (m_Size <= m_Pos) {
842 ch = m_pBuf[m_Pos++];
844 if (m_Size > m_Pos) {
845 ch = m_pBuf[m_Pos++];
847 if (buf.GetLength() > MAX_STRING_LENGTH) {
848 return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH);
850 return buf.GetByteString();
852 CFX_ByteString CPDF_StreamParser::ReadHexString()
854 if (m_Size <= m_Pos) {
855 return CFX_ByteString();
857 int ch = m_pBuf[m_Pos++];
859 FX_BOOL bFirst = TRUE;
865 if (ch >= '0' && ch <= '9') {
867 code = (ch - '0') * 16;
870 buf.AppendChar((char)code);
873 } else if (ch >= 'A' && ch <= 'F') {
875 code = (ch - 'A' + 10) * 16;
877 code += ch - 'A' + 10;
878 buf.AppendChar((char)code);
881 } else if (ch >= 'a' && ch <= 'f') {
883 code = (ch - 'a' + 10) * 16;
885 code += ch - 'a' + 10;
886 buf.AppendChar((char)code);
890 if (m_Size <= m_Pos) {
893 ch = m_pBuf[m_Pos++];
896 buf.AppendChar((char)code);
898 if (buf.GetLength() > MAX_STRING_LENGTH) {
899 return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH);
901 return buf.GetByteString();
903 #define PAGEPARSE_STAGE_GETCONTENT 1
904 #define PAGEPARSE_STAGE_PARSE 2
905 #define PAGEPARSE_STAGE_CHECKCLIP 3
906 CPDF_ContentParser::CPDF_ContentParser()
909 m_pStreamArray = NULL;
910 m_pSingleStream = NULL;
915 CPDF_ContentParser::~CPDF_ContentParser()
919 void CPDF_ContentParser::Clear()
924 if (m_pSingleStream) {
925 delete m_pSingleStream;
927 if (m_pStreamArray) {
928 for (FX_DWORD i = 0; i < m_nStreams; i ++)
929 if (m_pStreamArray[i]) {
930 delete m_pStreamArray[i];
932 FX_Free(m_pStreamArray);
934 if (m_pData && m_pSingleStream == NULL) {
935 FX_Free((void*)m_pData);
938 m_pStreamArray = NULL;
939 m_pSingleStream = NULL;
943 void CPDF_ContentParser::Start(CPDF_Page* pPage, CPDF_ParseOptions* pOptions)
945 if (m_Status != Ready || pPage == NULL || pPage->m_pDocument == NULL || pPage->m_pFormDict == NULL) {
952 m_Options = *pOptions;
954 m_Status = ToBeContinued;
955 m_InternalStage = PAGEPARSE_STAGE_GETCONTENT;
957 CPDF_Object* pContent = pPage->m_pFormDict->GetElementValue(FX_BSTRC("Contents"));
958 if (pContent == NULL) {
962 if (pContent->GetType() == PDFOBJ_STREAM) {
964 m_pSingleStream = new CPDF_StreamAcc;
965 m_pSingleStream->LoadAllData((CPDF_Stream*)pContent, FALSE);
966 } else if (pContent->GetType() == PDFOBJ_ARRAY) {
967 CPDF_Array* pArray = (CPDF_Array*)pContent;
968 m_nStreams = pArray->GetCount();
969 if (m_nStreams == 0) {
973 m_pStreamArray = FX_Alloc(CPDF_StreamAcc*, m_nStreams);
979 void CPDF_ContentParser::Start(CPDF_Form* pForm, CPDF_AllStates* pGraphicStates,
980 CFX_AffineMatrix* pParentMatrix, CPDF_Type3Char* pType3Char, CPDF_ParseOptions* pOptions, int level)
982 m_pType3Char = pType3Char;
985 CFX_AffineMatrix form_matrix = pForm->m_pFormDict->GetMatrix(FX_BSTRC("Matrix"));
986 if (pGraphicStates) {
987 form_matrix.Concat(pGraphicStates->m_CTM);
989 CPDF_Array* pBBox = pForm->m_pFormDict->GetArray(FX_BSTRC("BBox"));
990 CFX_FloatRect form_bbox;
993 form_bbox = pBBox->GetRect();
995 ClipPath.AppendRect(form_bbox.left, form_bbox.bottom, form_bbox.right, form_bbox.top);
996 ClipPath.Transform(&form_matrix);
998 ClipPath.Transform(pParentMatrix);
1000 form_bbox.Transform(&form_matrix);
1001 if (pParentMatrix) {
1002 form_bbox.Transform(pParentMatrix);
1005 CPDF_Dictionary* pResources = pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
1006 m_pParser = new CPDF_StreamContentParser;
1007 m_pParser->Initialize();
1008 m_pParser->PrepareParse(pForm->m_pDocument, pForm->m_pPageResources, pForm->m_pResources, pParentMatrix, pForm,
1009 pResources, &form_bbox, pOptions, pGraphicStates, level);
1010 m_pParser->m_pCurStates->m_CTM = form_matrix;
1011 m_pParser->m_pCurStates->m_ParentMatrix = form_matrix;
1012 if (ClipPath.NotNull()) {
1013 m_pParser->m_pCurStates->m_ClipPath.AppendPath(ClipPath, FXFILL_WINDING, TRUE);
1015 if (pForm->m_Transparency & PDFTRANS_GROUP) {
1016 CPDF_GeneralStateData* pData = m_pParser->m_pCurStates->m_GeneralState.GetModify();
1017 pData->m_BlendType = FXDIB_BLEND_NORMAL;
1018 pData->m_StrokeAlpha = 1.0f;
1019 pData->m_FillAlpha = 1.0f;
1020 pData->m_pSoftMask = NULL;
1023 m_pSingleStream = new CPDF_StreamAcc;
1024 if (pForm->m_pDocument) {
1025 m_pSingleStream->LoadAllData(pForm->m_pFormStream, FALSE);
1027 m_pSingleStream->LoadAllData(pForm->m_pFormStream, FALSE);
1029 m_pData = (FX_LPBYTE)m_pSingleStream->GetData();
1030 m_Size = m_pSingleStream->GetSize();
1031 m_Status = ToBeContinued;
1032 m_InternalStage = PAGEPARSE_STAGE_PARSE;
1033 m_CurrentOffset = 0;
1035 void CPDF_ContentParser::Continue(IFX_Pause* pPause)
1038 while (m_Status == ToBeContinued) {
1039 if (m_InternalStage == PAGEPARSE_STAGE_GETCONTENT) {
1040 if (m_CurrentOffset == m_nStreams) {
1041 if (m_pStreamArray) {
1044 for (i = 0; i < m_nStreams; i ++) {
1045 FX_DWORD size = m_pStreamArray[i]->GetSize();
1046 if (m_Size + size + 1 <= m_Size) {
1052 m_pData = FX_Alloc(FX_BYTE, m_Size);
1054 for (i = 0; i < m_nStreams; i ++) {
1055 FXSYS_memcpy32(m_pData + pos, m_pStreamArray[i]->GetData(), m_pStreamArray[i]->GetSize());
1056 pos += m_pStreamArray[i]->GetSize() + 1;
1057 m_pData[pos - 1] = ' ';
1058 delete m_pStreamArray[i];
1060 FX_Free(m_pStreamArray);
1061 m_pStreamArray = NULL;
1063 m_pData = (FX_LPBYTE)m_pSingleStream->GetData();
1064 m_Size = m_pSingleStream->GetSize();
1066 m_InternalStage = PAGEPARSE_STAGE_PARSE;
1067 m_CurrentOffset = 0;
1069 CPDF_Array* pContent = m_pObjects->m_pFormDict->GetArray(FX_BSTRC("Contents"));
1070 m_pStreamArray[m_CurrentOffset] = new CPDF_StreamAcc;
1071 CPDF_Stream* pStreamObj = (CPDF_Stream*)(pContent ? pContent->GetElementValue(m_CurrentOffset) : NULL);
1072 m_pStreamArray[m_CurrentOffset]->LoadAllData(pStreamObj, FALSE);
1076 if (m_InternalStage == PAGEPARSE_STAGE_PARSE) {
1077 if (m_pParser == NULL) {
1078 m_pParser = new CPDF_StreamContentParser;
1079 m_pParser->Initialize();
1080 m_pParser->PrepareParse(m_pObjects->m_pDocument, m_pObjects->m_pPageResources, NULL, NULL, m_pObjects,
1081 m_pObjects->m_pResources, &m_pObjects->m_BBox, &m_Options, NULL, 0);
1082 m_pParser->m_pCurStates->m_ColorState.GetModify()->Default();
1084 if (m_CurrentOffset >= m_Size) {
1085 m_InternalStage = PAGEPARSE_STAGE_CHECKCLIP;
1087 m_CurrentOffset += m_pParser->Parse(m_pData + m_CurrentOffset, m_Size - m_CurrentOffset, PARSE_STEP_LIMIT);
1088 if (m_pParser->m_bAbort) {
1089 m_InternalStage = PAGEPARSE_STAGE_CHECKCLIP;
1094 if (m_InternalStage == PAGEPARSE_STAGE_CHECKCLIP) {
1096 m_pType3Char->m_bColored = m_pParser->m_bColored;
1097 m_pType3Char->m_Width = FXSYS_round(m_pParser->m_Type3Data[0] * 1000);
1098 m_pType3Char->m_BBox.left = FXSYS_round(m_pParser->m_Type3Data[2] * 1000);
1099 m_pType3Char->m_BBox.bottom = FXSYS_round(m_pParser->m_Type3Data[3] * 1000);
1100 m_pType3Char->m_BBox.right = FXSYS_round(m_pParser->m_Type3Data[4] * 1000);
1101 m_pType3Char->m_BBox.top = FXSYS_round(m_pParser->m_Type3Data[5] * 1000);
1103 FX_POSITION pos = m_pObjects->m_ObjectList.GetHeadPosition();
1105 CPDF_PageObject* pObj = (CPDF_PageObject*)m_pObjects->m_ObjectList.GetNext(pos);
1106 if (pObj->m_ClipPath.IsNull()) {
1109 if (pObj->m_ClipPath.GetPathCount() != 1) {
1112 if (pObj->m_ClipPath.GetTextCount()) {
1115 CPDF_Path ClipPath = pObj->m_ClipPath.GetPath(0);
1116 if (!ClipPath.IsRect() || pObj->m_Type == PDFPAGE_SHADING) {
1119 CFX_FloatRect old_rect(ClipPath.GetPointX(0), ClipPath.GetPointY(0),
1120 ClipPath.GetPointX(2), ClipPath.GetPointY(2));
1121 CFX_FloatRect obj_rect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top);
1122 if (old_rect.Contains(obj_rect)) {
1123 pObj->m_ClipPath.SetNull();
1130 if (pPause && pPause->NeedToPauseNow()) {
1135 int CPDF_ContentParser::EstimateProgress()
1137 if (m_Status == Ready) {
1140 if (m_Status == Done) {
1143 if (m_InternalStage == PAGEPARSE_STAGE_GETCONTENT) {
1146 if (m_InternalStage == PAGEPARSE_STAGE_CHECKCLIP) {
1149 return 10 + 80 * m_CurrentOffset / m_Size;