Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: core/fpdfapi/page/fpdf_page_parser_old.cpp

Issue 2474303003: Clean up fpdf_page_parsers (Closed)
Patch Set: Fix includes, move method to namespace Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "core/fpdfapi/page/pageint.h"
8
9 #include <limits.h>
10
11 #include "core/fpdfapi/cpdf_modulemgr.h"
12 #include "core/fpdfapi/font/cpdf_type3char.h"
13 #include "core/fpdfapi/page/cpdf_allstates.h"
14 #include "core/fpdfapi/page/cpdf_docpagedata.h"
15 #include "core/fpdfapi/page/cpdf_form.h"
16 #include "core/fpdfapi/page/cpdf_page.h"
17 #include "core/fpdfapi/page/cpdf_pageobject.h"
18 #include "core/fpdfapi/page/cpdf_path.h"
19 #include "core/fpdfapi/parser/cpdf_array.h"
20 #include "core/fpdfapi/parser/cpdf_boolean.h"
21 #include "core/fpdfapi/parser/cpdf_dictionary.h"
22 #include "core/fpdfapi/parser/cpdf_document.h"
23 #include "core/fpdfapi/parser/cpdf_name.h"
24 #include "core/fpdfapi/parser/cpdf_null.h"
25 #include "core/fpdfapi/parser/cpdf_number.h"
26 #include "core/fpdfapi/parser/cpdf_stream.h"
27 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
28 #include "core/fpdfapi/parser/cpdf_string.h"
29 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
30 #include "core/fpdfapi/parser/fpdf_parser_utility.h"
31 #include "core/fxcodec/fx_codec.h"
32 #include "core/fxcrt/fx_ext.h"
33 #include "core/fxcrt/fx_safe_types.h"
34 #include "core/fxge/cfx_fxgedevice.h"
35 #include "core/fxge/cfx_renderdevice.h"
36
37 CCodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder(
38 const uint8_t* src_buf,
39 uint32_t src_size,
40 int width,
41 int height,
42 const CPDF_Dictionary* pParams);
43
44 namespace {
45
46 const uint32_t kMaxNestedArrayLevel = 512;
47 const uint32_t kMaxWordBuffer = 256;
48 const FX_STRSIZE kMaxStringLength = 32767;
49
50 uint32_t DecodeAllScanlines(CCodec_ScanlineDecoder* pDecoder,
51 uint8_t*& dest_buf,
52 uint32_t& dest_size) {
53 if (!pDecoder) {
54 return FX_INVALID_OFFSET;
55 }
56 int ncomps = pDecoder->CountComps();
57 int bpc = pDecoder->GetBPC();
58 int width = pDecoder->GetWidth();
59 int height = pDecoder->GetHeight();
60 int pitch = (width * ncomps * bpc + 7) / 8;
61 if (height == 0 || pitch > (1 << 30) / height) {
62 delete pDecoder;
63 return FX_INVALID_OFFSET;
64 }
65 dest_buf = FX_Alloc2D(uint8_t, pitch, height);
66 dest_size = pitch * height; // Safe since checked alloc returned.
67 for (int row = 0; row < height; row++) {
68 const uint8_t* pLine = pDecoder->GetScanline(row);
69 if (!pLine)
70 break;
71
72 FXSYS_memcpy(dest_buf + row * pitch, pLine, pitch);
73 }
74 uint32_t srcoff = pDecoder->GetSrcOffset();
75 delete pDecoder;
76 return srcoff;
77 }
78
79 uint32_t PDF_DecodeInlineStream(const uint8_t* src_buf,
80 uint32_t limit,
81 int width,
82 int height,
83 CFX_ByteString& decoder,
84 CPDF_Dictionary* pParam,
85 uint8_t*& dest_buf,
86 uint32_t& dest_size) {
87 if (decoder == "CCITTFaxDecode" || decoder == "CCF") {
88 CCodec_ScanlineDecoder* pDecoder =
89 FPDFAPI_CreateFaxDecoder(src_buf, limit, width, height, pParam);
90 return DecodeAllScanlines(pDecoder, dest_buf, dest_size);
91 }
92 if (decoder == "ASCII85Decode" || decoder == "A85") {
93 return A85Decode(src_buf, limit, dest_buf, dest_size);
94 }
95 if (decoder == "ASCIIHexDecode" || decoder == "AHx") {
96 return HexDecode(src_buf, limit, dest_buf, dest_size);
97 }
98 if (decoder == "FlateDecode" || decoder == "Fl") {
99 return FPDFAPI_FlateOrLZWDecode(false, src_buf, limit, pParam, dest_size,
100 dest_buf, dest_size);
101 }
102 if (decoder == "LZWDecode" || decoder == "LZW") {
103 return FPDFAPI_FlateOrLZWDecode(true, src_buf, limit, pParam, 0, dest_buf,
104 dest_size);
105 }
106 if (decoder == "DCTDecode" || decoder == "DCT") {
107 CCodec_ScanlineDecoder* pDecoder =
108 CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(
109 src_buf, limit, width, height, 0,
110 !pParam || pParam->GetIntegerFor("ColorTransform", 1));
111 return DecodeAllScanlines(pDecoder, dest_buf, dest_size);
112 }
113 if (decoder == "RunLengthDecode" || decoder == "RL") {
114 return RunLengthDecode(src_buf, limit, dest_buf, dest_size);
115 }
116 dest_size = 0;
117 dest_buf = 0;
118 return (uint32_t)-1;
119 }
120
121 } // namespace
122
123 CPDF_StreamParser::CPDF_StreamParser(const uint8_t* pData, uint32_t dwSize)
124 : m_pBuf(pData),
125 m_Size(dwSize),
126 m_Pos(0),
127 m_pLastObj(nullptr),
128 m_pPool(nullptr) {}
129
130 CPDF_StreamParser::CPDF_StreamParser(
131 const uint8_t* pData,
132 uint32_t dwSize,
133 const CFX_WeakPtr<CFX_ByteStringPool>& pPool)
134 : m_pBuf(pData),
135 m_Size(dwSize),
136 m_Pos(0),
137 m_pLastObj(nullptr),
138 m_pPool(pPool) {}
139
140 CPDF_StreamParser::~CPDF_StreamParser() {
141 if (m_pLastObj) {
142 m_pLastObj->Release();
143 }
144 }
145
146 CPDF_Stream* CPDF_StreamParser::ReadInlineStream(CPDF_Document* pDoc,
147 CPDF_Dictionary* pDict,
148 CPDF_Object* pCSObj) {
149 if (m_Pos == m_Size)
150 return nullptr;
151
152 if (PDFCharIsWhitespace(m_pBuf[m_Pos]))
153 m_Pos++;
154
155 CFX_ByteString Decoder;
156 CPDF_Dictionary* pParam = nullptr;
157 CPDF_Object* pFilter = pDict->GetDirectObjectFor("Filter");
158 if (pFilter) {
159 if (CPDF_Array* pArray = pFilter->AsArray()) {
160 Decoder = pArray->GetStringAt(0);
161 CPDF_Array* pParams = pDict->GetArrayFor("DecodeParms");
162 if (pParams)
163 pParam = pParams->GetDictAt(0);
164 } else {
165 Decoder = pFilter->GetString();
166 pParam = pDict->GetDictFor("DecodeParms");
167 }
168 }
169 uint32_t width = pDict->GetIntegerFor("Width");
170 uint32_t height = pDict->GetIntegerFor("Height");
171 uint32_t OrigSize = 0;
172 if (pCSObj) {
173 uint32_t bpc = pDict->GetIntegerFor("BitsPerComponent");
174 uint32_t nComponents = 1;
175 CPDF_ColorSpace* pCS = pDoc->LoadColorSpace(pCSObj);
176 if (pCS) {
177 nComponents = pCS->CountComponents();
178 pDoc->GetPageData()->ReleaseColorSpace(pCSObj);
179 } else {
180 nComponents = 3;
181 }
182 uint32_t pitch = width;
183 if (bpc && pitch > INT_MAX / bpc)
184 return nullptr;
185
186 pitch *= bpc;
187 if (nComponents && pitch > INT_MAX / nComponents)
188 return nullptr;
189
190 pitch *= nComponents;
191 if (pitch > INT_MAX - 7)
192 return nullptr;
193
194 pitch += 7;
195 pitch /= 8;
196 OrigSize = pitch;
197 } else {
198 if (width > INT_MAX - 7)
199 return nullptr;
200
201 OrigSize = ((width + 7) / 8);
202 }
203 if (height && OrigSize > INT_MAX / height)
204 return nullptr;
205
206 OrigSize *= height;
207 uint8_t* pData = nullptr;
208 uint32_t dwStreamSize;
209 if (Decoder.IsEmpty()) {
210 if (OrigSize > m_Size - m_Pos) {
211 OrigSize = m_Size - m_Pos;
212 }
213 pData = FX_Alloc(uint8_t, OrigSize);
214 FXSYS_memcpy(pData, m_pBuf + m_Pos, OrigSize);
215 dwStreamSize = OrigSize;
216 m_Pos += OrigSize;
217 } else {
218 uint32_t dwDestSize = OrigSize;
219 dwStreamSize =
220 PDF_DecodeInlineStream(m_pBuf + m_Pos, m_Size - m_Pos, width, height,
221 Decoder, pParam, pData, dwDestSize);
222 FX_Free(pData);
223 if ((int)dwStreamSize < 0)
224 return nullptr;
225
226 uint32_t dwSavePos = m_Pos;
227 m_Pos += dwStreamSize;
228 while (1) {
229 uint32_t dwPrevPos = m_Pos;
230 CPDF_StreamParser::SyntaxType type = ParseNextElement();
231 if (type == CPDF_StreamParser::EndOfData)
232 break;
233
234 if (type != CPDF_StreamParser::Keyword) {
235 dwStreamSize += m_Pos - dwPrevPos;
236 continue;
237 }
238 if (GetWordSize() == 2 && GetWordBuf()[0] == 'E' &&
239 GetWordBuf()[1] == 'I') {
240 m_Pos = dwPrevPos;
241 break;
242 }
243 dwStreamSize += m_Pos - dwPrevPos;
244 }
245 m_Pos = dwSavePos;
246 pData = FX_Alloc(uint8_t, dwStreamSize);
247 FXSYS_memcpy(pData, m_pBuf + m_Pos, dwStreamSize);
248 m_Pos += dwStreamSize;
249 }
250 pDict->SetIntegerFor("Length", (int)dwStreamSize);
251 return new CPDF_Stream(pData, dwStreamSize, pDict);
252 }
253
254 CPDF_StreamParser::SyntaxType CPDF_StreamParser::ParseNextElement() {
255 if (m_pLastObj) {
256 m_pLastObj->Release();
257 m_pLastObj = nullptr;
258 }
259
260 m_WordSize = 0;
261 bool bIsNumber = true;
262 if (!PositionIsInBounds())
263 return EndOfData;
264
265 int ch = m_pBuf[m_Pos++];
266 while (1) {
267 while (PDFCharIsWhitespace(ch)) {
268 if (!PositionIsInBounds())
269 return EndOfData;
270
271 ch = m_pBuf[m_Pos++];
272 }
273
274 if (ch != '%')
275 break;
276
277 while (1) {
278 if (!PositionIsInBounds())
279 return EndOfData;
280
281 ch = m_pBuf[m_Pos++];
282 if (PDFCharIsLineEnding(ch))
283 break;
284 }
285 }
286
287 if (PDFCharIsDelimiter(ch) && ch != '/') {
288 m_Pos--;
289 m_pLastObj = ReadNextObject(false, 0);
290 return Others;
291 }
292
293 while (1) {
294 if (m_WordSize < kMaxWordBuffer)
295 m_WordBuffer[m_WordSize++] = ch;
296
297 if (!PDFCharIsNumeric(ch))
298 bIsNumber = false;
299
300 if (!PositionIsInBounds())
301 break;
302
303 ch = m_pBuf[m_Pos++];
304
305 if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) {
306 m_Pos--;
307 break;
308 }
309 }
310
311 m_WordBuffer[m_WordSize] = 0;
312 if (bIsNumber)
313 return Number;
314
315 if (m_WordBuffer[0] == '/')
316 return Name;
317
318 if (m_WordSize == 4) {
319 if (memcmp(m_WordBuffer, "true", 4) == 0) {
320 m_pLastObj = new CPDF_Boolean(true);
321 return Others;
322 }
323 if (memcmp(m_WordBuffer, "null", 4) == 0) {
324 m_pLastObj = new CPDF_Null;
325 return Others;
326 }
327 } else if (m_WordSize == 5) {
328 if (memcmp(m_WordBuffer, "false", 5) == 0) {
329 m_pLastObj = new CPDF_Boolean(false);
330 return Others;
331 }
332 }
333 return Keyword;
334 }
335
336 CPDF_Object* CPDF_StreamParser::GetObject() {
337 CPDF_Object* pObj = m_pLastObj;
338 m_pLastObj = nullptr;
339 return pObj;
340 }
341
342 CPDF_Object* CPDF_StreamParser::ReadNextObject(bool bAllowNestedArray,
343 uint32_t dwInArrayLevel) {
344 bool bIsNumber;
345 GetNextWord(bIsNumber);
346 if (!m_WordSize)
347 return nullptr;
348
349 if (bIsNumber) {
350 m_WordBuffer[m_WordSize] = 0;
351 return new CPDF_Number(CFX_ByteStringC(m_WordBuffer, m_WordSize));
352 }
353
354 int first_char = m_WordBuffer[0];
355 if (first_char == '/') {
356 CFX_ByteString name =
357 PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1));
358 return new CPDF_Name(m_pPool ? m_pPool->Intern(name) : name);
359 }
360
361 if (first_char == '(') {
362 CFX_ByteString str = ReadString();
363 return new CPDF_String(m_pPool ? m_pPool->Intern(str) : str, false);
364 }
365
366 if (first_char == '<') {
367 if (m_WordSize == 1)
368 return new CPDF_String(ReadHexString(), true);
369
370 CPDF_Dictionary* pDict = new CPDF_Dictionary(m_pPool);
371 while (1) {
372 GetNextWord(bIsNumber);
373 if (m_WordSize == 2 && m_WordBuffer[0] == '>')
374 break;
375
376 if (!m_WordSize || m_WordBuffer[0] != '/') {
377 pDict->Release();
378 return nullptr;
379 }
380
381 CFX_ByteString key =
382 PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1));
383 CPDF_Object* pObj = ReadNextObject(true, 0);
384 if (!pObj) {
385 pDict->Release();
386 return nullptr;
387 }
388
389 if (key.IsEmpty())
390 pObj->Release();
391 else
392 pDict->SetFor(key, pObj);
393 }
394 return pDict;
395 }
396
397 if (first_char == '[') {
398 if ((!bAllowNestedArray && dwInArrayLevel) ||
399 dwInArrayLevel > kMaxNestedArrayLevel) {
400 return nullptr;
401 }
402
403 CPDF_Array* pArray = new CPDF_Array;
404 while (1) {
405 CPDF_Object* pObj = ReadNextObject(bAllowNestedArray, dwInArrayLevel + 1);
406 if (pObj) {
407 pArray->Add(pObj);
408 continue;
409 }
410
411 if (!m_WordSize || m_WordBuffer[0] == ']')
412 break;
413 }
414 return pArray;
415 }
416
417 if (m_WordSize == 5 && !memcmp(m_WordBuffer, "false", 5))
418 return new CPDF_Boolean(false);
419
420 if (m_WordSize == 4) {
421 if (memcmp(m_WordBuffer, "true", 4) == 0)
422 return new CPDF_Boolean(true);
423
424 if (memcmp(m_WordBuffer, "null", 4) == 0)
425 return new CPDF_Null;
426 }
427
428 return nullptr;
429 }
430
431 void CPDF_StreamParser::GetNextWord(bool& bIsNumber) {
432 m_WordSize = 0;
433 bIsNumber = true;
434 if (!PositionIsInBounds())
435 return;
436
437 int ch = m_pBuf[m_Pos++];
438 while (1) {
439 while (PDFCharIsWhitespace(ch)) {
440 if (!PositionIsInBounds()) {
441 return;
442 }
443 ch = m_pBuf[m_Pos++];
444 }
445
446 if (ch != '%')
447 break;
448
449 while (1) {
450 if (!PositionIsInBounds())
451 return;
452 ch = m_pBuf[m_Pos++];
453 if (PDFCharIsLineEnding(ch))
454 break;
455 }
456 }
457
458 if (PDFCharIsDelimiter(ch)) {
459 bIsNumber = false;
460 m_WordBuffer[m_WordSize++] = ch;
461 if (ch == '/') {
462 while (1) {
463 if (!PositionIsInBounds())
464 return;
465 ch = m_pBuf[m_Pos++];
466 if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) {
467 m_Pos--;
468 return;
469 }
470
471 if (m_WordSize < kMaxWordBuffer)
472 m_WordBuffer[m_WordSize++] = ch;
473 }
474 } else if (ch == '<') {
475 if (!PositionIsInBounds())
476 return;
477 ch = m_pBuf[m_Pos++];
478 if (ch == '<')
479 m_WordBuffer[m_WordSize++] = ch;
480 else
481 m_Pos--;
482 } else if (ch == '>') {
483 if (!PositionIsInBounds())
484 return;
485 ch = m_pBuf[m_Pos++];
486 if (ch == '>')
487 m_WordBuffer[m_WordSize++] = ch;
488 else
489 m_Pos--;
490 }
491 return;
492 }
493
494 while (1) {
495 if (m_WordSize < kMaxWordBuffer)
496 m_WordBuffer[m_WordSize++] = ch;
497 if (!PDFCharIsNumeric(ch))
498 bIsNumber = false;
499
500 if (!PositionIsInBounds())
501 return;
502 ch = m_pBuf[m_Pos++];
503 if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) {
504 m_Pos--;
505 break;
506 }
507 }
508 }
509
510 CFX_ByteString CPDF_StreamParser::ReadString() {
511 if (!PositionIsInBounds())
512 return CFX_ByteString();
513
514 uint8_t ch = m_pBuf[m_Pos++];
515 CFX_ByteTextBuf buf;
516 int parlevel = 0;
517 int status = 0;
518 int iEscCode = 0;
519 while (1) {
520 switch (status) {
521 case 0:
522 if (ch == ')') {
523 if (parlevel == 0) {
524 if (buf.GetLength() > kMaxStringLength) {
525 return CFX_ByteString(buf.GetBuffer(), kMaxStringLength);
526 }
527 return buf.MakeString();
528 }
529 parlevel--;
530 buf.AppendChar(')');
531 } else if (ch == '(') {
532 parlevel++;
533 buf.AppendChar('(');
534 } else if (ch == '\\') {
535 status = 1;
536 } else {
537 buf.AppendChar((char)ch);
538 }
539 break;
540 case 1:
541 if (ch >= '0' && ch <= '7') {
542 iEscCode = FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch));
543 status = 2;
544 break;
545 }
546 if (ch == 'n') {
547 buf.AppendChar('\n');
548 } else if (ch == 'r') {
549 buf.AppendChar('\r');
550 } else if (ch == 't') {
551 buf.AppendChar('\t');
552 } else if (ch == 'b') {
553 buf.AppendChar('\b');
554 } else if (ch == 'f') {
555 buf.AppendChar('\f');
556 } else if (ch == '\r') {
557 status = 4;
558 break;
559 } else if (ch == '\n') {
560 } else {
561 buf.AppendChar(ch);
562 }
563 status = 0;
564 break;
565 case 2:
566 if (ch >= '0' && ch <= '7') {
567 iEscCode =
568 iEscCode * 8 + FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch));
569 status = 3;
570 } else {
571 buf.AppendChar(iEscCode);
572 status = 0;
573 continue;
574 }
575 break;
576 case 3:
577 if (ch >= '0' && ch <= '7') {
578 iEscCode =
579 iEscCode * 8 + FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch));
580 buf.AppendChar(iEscCode);
581 status = 0;
582 } else {
583 buf.AppendChar(iEscCode);
584 status = 0;
585 continue;
586 }
587 break;
588 case 4:
589 status = 0;
590 if (ch != '\n') {
591 continue;
592 }
593 break;
594 }
595 if (!PositionIsInBounds())
596 break;
597
598 ch = m_pBuf[m_Pos++];
599 }
600 if (PositionIsInBounds())
601 ++m_Pos;
602
603 if (buf.GetLength() > kMaxStringLength) {
604 return CFX_ByteString(buf.GetBuffer(), kMaxStringLength);
605 }
606 return buf.MakeString();
607 }
608
609 CFX_ByteString CPDF_StreamParser::ReadHexString() {
610 if (!PositionIsInBounds())
611 return CFX_ByteString();
612
613 CFX_ByteTextBuf buf;
614 bool bFirst = true;
615 int code = 0;
616 while (PositionIsInBounds()) {
617 int ch = m_pBuf[m_Pos++];
618
619 if (ch == '>')
620 break;
621
622 if (!std::isxdigit(ch))
623 continue;
624
625 int val = FXSYS_toHexDigit(ch);
626 if (bFirst) {
627 code = val * 16;
628 } else {
629 code += val;
630 buf.AppendByte((uint8_t)code);
631 }
632 bFirst = !bFirst;
633 }
634 if (!bFirst)
635 buf.AppendChar((char)code);
636
637 if (buf.GetLength() > kMaxStringLength)
638 return CFX_ByteString(buf.GetBuffer(), kMaxStringLength);
639
640 return buf.MakeString();
641 }
642
643 bool CPDF_StreamParser::PositionIsInBounds() const {
644 return m_Pos < m_Size;
645 }
646
647 CPDF_ContentParser::CPDF_ContentParser()
648 : m_Status(Ready),
649 m_InternalStage(STAGE_GETCONTENT),
650 m_pObjectHolder(nullptr),
651 m_bForm(false),
652 m_pType3Char(nullptr),
653 m_pData(nullptr),
654 m_Size(0),
655 m_CurrentOffset(0) {}
656
657 CPDF_ContentParser::~CPDF_ContentParser() {
658 if (!m_pSingleStream)
659 FX_Free(m_pData);
660 }
661
662 void CPDF_ContentParser::Start(CPDF_Page* pPage) {
663 if (m_Status != Ready || !pPage || !pPage->m_pDocument ||
664 !pPage->m_pFormDict) {
665 m_Status = Done;
666 return;
667 }
668 m_pObjectHolder = pPage;
669 m_bForm = false;
670 m_Status = ToBeContinued;
671 m_InternalStage = STAGE_GETCONTENT;
672 m_CurrentOffset = 0;
673
674 CPDF_Object* pContent = pPage->m_pFormDict->GetDirectObjectFor("Contents");
675 if (!pContent) {
676 m_Status = Done;
677 return;
678 }
679 if (CPDF_Stream* pStream = pContent->AsStream()) {
680 m_nStreams = 0;
681 m_pSingleStream.reset(new CPDF_StreamAcc);
682 m_pSingleStream->LoadAllData(pStream, false);
683 } else if (CPDF_Array* pArray = pContent->AsArray()) {
684 m_nStreams = pArray->GetCount();
685 if (m_nStreams)
686 m_StreamArray.resize(m_nStreams);
687 else
688 m_Status = Done;
689 } else {
690 m_Status = Done;
691 }
692 }
693
694 void CPDF_ContentParser::Start(CPDF_Form* pForm,
695 CPDF_AllStates* pGraphicStates,
696 const CFX_Matrix* pParentMatrix,
697 CPDF_Type3Char* pType3Char,
698 int level) {
699 m_pType3Char = pType3Char;
700 m_pObjectHolder = pForm;
701 m_bForm = true;
702 CFX_Matrix form_matrix = pForm->m_pFormDict->GetMatrixFor("Matrix");
703 if (pGraphicStates) {
704 form_matrix.Concat(pGraphicStates->m_CTM);
705 }
706 CPDF_Array* pBBox = pForm->m_pFormDict->GetArrayFor("BBox");
707 CFX_FloatRect form_bbox;
708 CPDF_Path ClipPath;
709 if (pBBox) {
710 form_bbox = pBBox->GetRect();
711 ClipPath.Emplace();
712 ClipPath.AppendRect(form_bbox.left, form_bbox.bottom, form_bbox.right,
713 form_bbox.top);
714 ClipPath.Transform(&form_matrix);
715 if (pParentMatrix) {
716 ClipPath.Transform(pParentMatrix);
717 }
718 form_bbox.Transform(&form_matrix);
719 if (pParentMatrix) {
720 form_bbox.Transform(pParentMatrix);
721 }
722 }
723 CPDF_Dictionary* pResources = pForm->m_pFormDict->GetDictFor("Resources");
724 m_pParser.reset(new CPDF_StreamContentParser(
725 pForm->m_pDocument, pForm->m_pPageResources, pForm->m_pResources,
726 pParentMatrix, pForm, pResources, &form_bbox, pGraphicStates, level));
727 m_pParser->GetCurStates()->m_CTM = form_matrix;
728 m_pParser->GetCurStates()->m_ParentMatrix = form_matrix;
729 if (ClipPath) {
730 m_pParser->GetCurStates()->m_ClipPath.AppendPath(ClipPath, FXFILL_WINDING,
731 true);
732 }
733 if (pForm->m_Transparency & PDFTRANS_GROUP) {
734 CPDF_GeneralState* pState = &m_pParser->GetCurStates()->m_GeneralState;
735 pState->SetBlendType(FXDIB_BLEND_NORMAL);
736 pState->SetStrokeAlpha(1.0f);
737 pState->SetFillAlpha(1.0f);
738 pState->SetSoftMask(nullptr);
739 }
740 m_nStreams = 0;
741 m_pSingleStream.reset(new CPDF_StreamAcc);
742 m_pSingleStream->LoadAllData(pForm->m_pFormStream, false);
743 m_pData = (uint8_t*)m_pSingleStream->GetData();
744 m_Size = m_pSingleStream->GetSize();
745 m_Status = ToBeContinued;
746 m_InternalStage = STAGE_PARSE;
747 m_CurrentOffset = 0;
748 }
749
750 void CPDF_ContentParser::Continue(IFX_Pause* pPause) {
751 int steps = 0;
752 while (m_Status == ToBeContinued) {
753 if (m_InternalStage == STAGE_GETCONTENT) {
754 if (m_CurrentOffset == m_nStreams) {
755 if (!m_StreamArray.empty()) {
756 FX_SAFE_UINT32 safeSize = 0;
757 for (const auto& stream : m_StreamArray) {
758 safeSize += stream->GetSize();
759 safeSize += 1;
760 }
761 if (!safeSize.IsValid()) {
762 m_Status = Done;
763 return;
764 }
765 m_Size = safeSize.ValueOrDie();
766 m_pData = FX_Alloc(uint8_t, m_Size);
767 uint32_t pos = 0;
768 for (const auto& stream : m_StreamArray) {
769 FXSYS_memcpy(m_pData + pos, stream->GetData(), stream->GetSize());
770 pos += stream->GetSize();
771 m_pData[pos++] = ' ';
772 }
773 m_StreamArray.clear();
774 } else {
775 m_pData = (uint8_t*)m_pSingleStream->GetData();
776 m_Size = m_pSingleStream->GetSize();
777 }
778 m_InternalStage = STAGE_PARSE;
779 m_CurrentOffset = 0;
780 } else {
781 CPDF_Array* pContent =
782 m_pObjectHolder->m_pFormDict->GetArrayFor("Contents");
783 m_StreamArray[m_CurrentOffset].reset(new CPDF_StreamAcc);
784 CPDF_Stream* pStreamObj = ToStream(
785 pContent ? pContent->GetDirectObjectAt(m_CurrentOffset) : nullptr);
786 m_StreamArray[m_CurrentOffset]->LoadAllData(pStreamObj, false);
787 m_CurrentOffset++;
788 }
789 }
790 if (m_InternalStage == STAGE_PARSE) {
791 if (!m_pParser) {
792 m_pParser.reset(new CPDF_StreamContentParser(
793 m_pObjectHolder->m_pDocument, m_pObjectHolder->m_pPageResources,
794 nullptr, nullptr, m_pObjectHolder, m_pObjectHolder->m_pResources,
795 &m_pObjectHolder->m_BBox, nullptr, 0));
796 m_pParser->GetCurStates()->m_ColorState.SetDefault();
797 }
798 if (m_CurrentOffset >= m_Size) {
799 m_InternalStage = STAGE_CHECKCLIP;
800 } else {
801 m_CurrentOffset +=
802 m_pParser->Parse(m_pData + m_CurrentOffset,
803 m_Size - m_CurrentOffset, PARSE_STEP_LIMIT);
804 }
805 }
806 if (m_InternalStage == STAGE_CHECKCLIP) {
807 if (m_pType3Char) {
808 m_pType3Char->m_bColored = m_pParser->IsColored();
809 m_pType3Char->m_Width =
810 FXSYS_round(m_pParser->GetType3Data()[0] * 1000);
811 m_pType3Char->m_BBox.left =
812 FXSYS_round(m_pParser->GetType3Data()[2] * 1000);
813 m_pType3Char->m_BBox.bottom =
814 FXSYS_round(m_pParser->GetType3Data()[3] * 1000);
815 m_pType3Char->m_BBox.right =
816 FXSYS_round(m_pParser->GetType3Data()[4] * 1000);
817 m_pType3Char->m_BBox.top =
818 FXSYS_round(m_pParser->GetType3Data()[5] * 1000);
819 }
820 for (auto& pObj : *m_pObjectHolder->GetPageObjectList()) {
821 if (!pObj->m_ClipPath)
822 continue;
823 if (pObj->m_ClipPath.GetPathCount() != 1)
824 continue;
825 if (pObj->m_ClipPath.GetTextCount())
826 continue;
827 CPDF_Path ClipPath = pObj->m_ClipPath.GetPath(0);
828 if (!ClipPath.IsRect() || pObj->IsShading())
829 continue;
830 CFX_FloatRect old_rect(ClipPath.GetPointX(0), ClipPath.GetPointY(0),
831 ClipPath.GetPointX(2), ClipPath.GetPointY(2));
832 CFX_FloatRect obj_rect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right,
833 pObj->m_Top);
834 if (old_rect.Contains(obj_rect)) {
835 pObj->m_ClipPath.SetNull();
836 }
837 }
838 m_Status = Done;
839 return;
840 }
841 steps++;
842 if (pPause && pPause->NeedToPauseNow()) {
843 break;
844 }
845 }
846 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698