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

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

Issue 2474303003: Clean up fpdf_page_parsers (Closed)
Patch Set: Remove PDF_ from namespace stuff 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 delete m_pLastObj;
142 }
143
144 CPDF_Stream* CPDF_StreamParser::ReadInlineStream(CPDF_Document* pDoc,
145 CPDF_Dictionary* pDict,
146 CPDF_Object* pCSObj) {
147 if (m_Pos == m_Size)
148 return nullptr;
149
150 if (PDFCharIsWhitespace(m_pBuf[m_Pos]))
151 m_Pos++;
152
153 CFX_ByteString Decoder;
154 CPDF_Dictionary* pParam = nullptr;
155 CPDF_Object* pFilter = pDict->GetDirectObjectFor("Filter");
156 if (pFilter) {
157 if (CPDF_Array* pArray = pFilter->AsArray()) {
158 Decoder = pArray->GetStringAt(0);
159 CPDF_Array* pParams = pDict->GetArrayFor("DecodeParms");
160 if (pParams)
161 pParam = pParams->GetDictAt(0);
162 } else {
163 Decoder = pFilter->GetString();
164 pParam = pDict->GetDictFor("DecodeParms");
165 }
166 }
167 uint32_t width = pDict->GetIntegerFor("Width");
168 uint32_t height = pDict->GetIntegerFor("Height");
169 uint32_t OrigSize = 0;
170 if (pCSObj) {
171 uint32_t bpc = pDict->GetIntegerFor("BitsPerComponent");
172 uint32_t nComponents = 1;
173 CPDF_ColorSpace* pCS = pDoc->LoadColorSpace(pCSObj);
174 if (pCS) {
175 nComponents = pCS->CountComponents();
176 pDoc->GetPageData()->ReleaseColorSpace(pCSObj);
177 } else {
178 nComponents = 3;
179 }
180 uint32_t pitch = width;
181 if (bpc && pitch > INT_MAX / bpc)
182 return nullptr;
183
184 pitch *= bpc;
185 if (nComponents && pitch > INT_MAX / nComponents)
186 return nullptr;
187
188 pitch *= nComponents;
189 if (pitch > INT_MAX - 7)
190 return nullptr;
191
192 pitch += 7;
193 pitch /= 8;
194 OrigSize = pitch;
195 } else {
196 if (width > INT_MAX - 7)
197 return nullptr;
198
199 OrigSize = ((width + 7) / 8);
200 }
201 if (height && OrigSize > INT_MAX / height)
202 return nullptr;
203
204 OrigSize *= height;
205 uint8_t* pData = nullptr;
206 uint32_t dwStreamSize;
207 if (Decoder.IsEmpty()) {
208 if (OrigSize > m_Size - m_Pos) {
209 OrigSize = m_Size - m_Pos;
210 }
211 pData = FX_Alloc(uint8_t, OrigSize);
212 FXSYS_memcpy(pData, m_pBuf + m_Pos, OrigSize);
213 dwStreamSize = OrigSize;
214 m_Pos += OrigSize;
215 } else {
216 uint32_t dwDestSize = OrigSize;
217 dwStreamSize =
218 PDF_DecodeInlineStream(m_pBuf + m_Pos, m_Size - m_Pos, width, height,
219 Decoder, pParam, pData, dwDestSize);
220 FX_Free(pData);
221 if ((int)dwStreamSize < 0)
222 return nullptr;
223
224 uint32_t dwSavePos = m_Pos;
225 m_Pos += dwStreamSize;
226 while (1) {
227 uint32_t dwPrevPos = m_Pos;
228 CPDF_StreamParser::SyntaxType type = ParseNextElement();
229 if (type == CPDF_StreamParser::EndOfData)
230 break;
231
232 if (type != CPDF_StreamParser::Keyword) {
233 dwStreamSize += m_Pos - dwPrevPos;
234 continue;
235 }
236 if (GetWordSize() == 2 && GetWordBuf()[0] == 'E' &&
237 GetWordBuf()[1] == 'I') {
238 m_Pos = dwPrevPos;
239 break;
240 }
241 dwStreamSize += m_Pos - dwPrevPos;
242 }
243 m_Pos = dwSavePos;
244 pData = FX_Alloc(uint8_t, dwStreamSize);
245 FXSYS_memcpy(pData, m_pBuf + m_Pos, dwStreamSize);
246 m_Pos += dwStreamSize;
247 }
248 pDict->SetIntegerFor("Length", (int)dwStreamSize);
249 return new CPDF_Stream(pData, dwStreamSize, pDict);
250 }
251
252 CPDF_StreamParser::SyntaxType CPDF_StreamParser::ParseNextElement() {
253 delete m_pLastObj;
254 m_pLastObj = nullptr;
255
256 m_WordSize = 0;
257 bool bIsNumber = true;
258 if (!PositionIsInBounds())
259 return EndOfData;
260
261 int ch = m_pBuf[m_Pos++];
262 while (1) {
263 while (PDFCharIsWhitespace(ch)) {
264 if (!PositionIsInBounds())
265 return EndOfData;
266
267 ch = m_pBuf[m_Pos++];
268 }
269
270 if (ch != '%')
271 break;
272
273 while (1) {
274 if (!PositionIsInBounds())
275 return EndOfData;
276
277 ch = m_pBuf[m_Pos++];
278 if (PDFCharIsLineEnding(ch))
279 break;
280 }
281 }
282
283 if (PDFCharIsDelimiter(ch) && ch != '/') {
284 m_Pos--;
285 m_pLastObj = ReadNextObject(false, 0);
286 return Others;
287 }
288
289 while (1) {
290 if (m_WordSize < kMaxWordBuffer)
291 m_WordBuffer[m_WordSize++] = ch;
292
293 if (!PDFCharIsNumeric(ch))
294 bIsNumber = false;
295
296 if (!PositionIsInBounds())
297 break;
298
299 ch = m_pBuf[m_Pos++];
300
301 if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) {
302 m_Pos--;
303 break;
304 }
305 }
306
307 m_WordBuffer[m_WordSize] = 0;
308 if (bIsNumber)
309 return Number;
310
311 if (m_WordBuffer[0] == '/')
312 return Name;
313
314 if (m_WordSize == 4) {
315 if (memcmp(m_WordBuffer, "true", 4) == 0) {
316 m_pLastObj = new CPDF_Boolean(true);
317 return Others;
318 }
319 if (memcmp(m_WordBuffer, "null", 4) == 0) {
320 m_pLastObj = new CPDF_Null;
321 return Others;
322 }
323 } else if (m_WordSize == 5) {
324 if (memcmp(m_WordBuffer, "false", 5) == 0) {
325 m_pLastObj = new CPDF_Boolean(false);
326 return Others;
327 }
328 }
329 return Keyword;
330 }
331
332 CPDF_Object* CPDF_StreamParser::GetObject() {
333 CPDF_Object* pObj = m_pLastObj;
334 m_pLastObj = nullptr;
335 return pObj;
336 }
337
338 CPDF_Object* CPDF_StreamParser::ReadNextObject(bool bAllowNestedArray,
339 uint32_t dwInArrayLevel) {
340 bool bIsNumber;
341 GetNextWord(bIsNumber);
342 if (!m_WordSize)
343 return nullptr;
344
345 if (bIsNumber) {
346 m_WordBuffer[m_WordSize] = 0;
347 return new CPDF_Number(CFX_ByteStringC(m_WordBuffer, m_WordSize));
348 }
349
350 int first_char = m_WordBuffer[0];
351 if (first_char == '/') {
352 CFX_ByteString name =
353 PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1));
354 return new CPDF_Name(m_pPool ? m_pPool->Intern(name) : name);
355 }
356
357 if (first_char == '(') {
358 CFX_ByteString str = ReadString();
359 return new CPDF_String(m_pPool ? m_pPool->Intern(str) : str, false);
360 }
361
362 if (first_char == '<') {
363 if (m_WordSize == 1)
364 return new CPDF_String(ReadHexString(), true);
365
366 CPDF_Dictionary* pDict = new CPDF_Dictionary(m_pPool);
367 while (1) {
368 GetNextWord(bIsNumber);
369 if (m_WordSize == 2 && m_WordBuffer[0] == '>')
370 break;
371
372 if (!m_WordSize || m_WordBuffer[0] != '/') {
373 delete pDict;
374 return nullptr;
375 }
376
377 CFX_ByteString key =
378 PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1));
379 CPDF_Object* pObj = ReadNextObject(true, 0);
380 if (!pObj) {
381 delete pDict;
382 return nullptr;
383 }
384
385 if (key.IsEmpty())
386 delete pObj;
387 else
388 pDict->SetFor(key, pObj);
389 }
390 return pDict;
391 }
392
393 if (first_char == '[') {
394 if ((!bAllowNestedArray && dwInArrayLevel) ||
395 dwInArrayLevel > kMaxNestedArrayLevel) {
396 return nullptr;
397 }
398
399 CPDF_Array* pArray = new CPDF_Array;
400 while (1) {
401 CPDF_Object* pObj = ReadNextObject(bAllowNestedArray, dwInArrayLevel + 1);
402 if (pObj) {
403 pArray->Add(pObj);
404 continue;
405 }
406
407 if (!m_WordSize || m_WordBuffer[0] == ']')
408 break;
409 }
410 return pArray;
411 }
412
413 if (m_WordSize == 5 && !memcmp(m_WordBuffer, "false", 5))
414 return new CPDF_Boolean(false);
415
416 if (m_WordSize == 4) {
417 if (memcmp(m_WordBuffer, "true", 4) == 0)
418 return new CPDF_Boolean(true);
419
420 if (memcmp(m_WordBuffer, "null", 4) == 0)
421 return new CPDF_Null;
422 }
423
424 return nullptr;
425 }
426
427 void CPDF_StreamParser::GetNextWord(bool& bIsNumber) {
428 m_WordSize = 0;
429 bIsNumber = true;
430 if (!PositionIsInBounds())
431 return;
432
433 int ch = m_pBuf[m_Pos++];
434 while (1) {
435 while (PDFCharIsWhitespace(ch)) {
436 if (!PositionIsInBounds()) {
437 return;
438 }
439 ch = m_pBuf[m_Pos++];
440 }
441
442 if (ch != '%')
443 break;
444
445 while (1) {
446 if (!PositionIsInBounds())
447 return;
448 ch = m_pBuf[m_Pos++];
449 if (PDFCharIsLineEnding(ch))
450 break;
451 }
452 }
453
454 if (PDFCharIsDelimiter(ch)) {
455 bIsNumber = false;
456 m_WordBuffer[m_WordSize++] = ch;
457 if (ch == '/') {
458 while (1) {
459 if (!PositionIsInBounds())
460 return;
461 ch = m_pBuf[m_Pos++];
462 if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) {
463 m_Pos--;
464 return;
465 }
466
467 if (m_WordSize < kMaxWordBuffer)
468 m_WordBuffer[m_WordSize++] = ch;
469 }
470 } else if (ch == '<') {
471 if (!PositionIsInBounds())
472 return;
473 ch = m_pBuf[m_Pos++];
474 if (ch == '<')
475 m_WordBuffer[m_WordSize++] = ch;
476 else
477 m_Pos--;
478 } else if (ch == '>') {
479 if (!PositionIsInBounds())
480 return;
481 ch = m_pBuf[m_Pos++];
482 if (ch == '>')
483 m_WordBuffer[m_WordSize++] = ch;
484 else
485 m_Pos--;
486 }
487 return;
488 }
489
490 while (1) {
491 if (m_WordSize < kMaxWordBuffer)
492 m_WordBuffer[m_WordSize++] = ch;
493 if (!PDFCharIsNumeric(ch))
494 bIsNumber = false;
495
496 if (!PositionIsInBounds())
497 return;
498 ch = m_pBuf[m_Pos++];
499 if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) {
500 m_Pos--;
501 break;
502 }
503 }
504 }
505
506 CFX_ByteString CPDF_StreamParser::ReadString() {
507 if (!PositionIsInBounds())
508 return CFX_ByteString();
509
510 uint8_t ch = m_pBuf[m_Pos++];
511 CFX_ByteTextBuf buf;
512 int parlevel = 0;
513 int status = 0;
514 int iEscCode = 0;
515 while (1) {
516 switch (status) {
517 case 0:
518 if (ch == ')') {
519 if (parlevel == 0) {
520 if (buf.GetLength() > kMaxStringLength) {
521 return CFX_ByteString(buf.GetBuffer(), kMaxStringLength);
522 }
523 return buf.MakeString();
524 }
525 parlevel--;
526 buf.AppendChar(')');
527 } else if (ch == '(') {
528 parlevel++;
529 buf.AppendChar('(');
530 } else if (ch == '\\') {
531 status = 1;
532 } else {
533 buf.AppendChar((char)ch);
534 }
535 break;
536 case 1:
537 if (ch >= '0' && ch <= '7') {
538 iEscCode = FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch));
539 status = 2;
540 break;
541 }
542 if (ch == 'n') {
543 buf.AppendChar('\n');
544 } else if (ch == 'r') {
545 buf.AppendChar('\r');
546 } else if (ch == 't') {
547 buf.AppendChar('\t');
548 } else if (ch == 'b') {
549 buf.AppendChar('\b');
550 } else if (ch == 'f') {
551 buf.AppendChar('\f');
552 } else if (ch == '\r') {
553 status = 4;
554 break;
555 } else if (ch == '\n') {
556 } else {
557 buf.AppendChar(ch);
558 }
559 status = 0;
560 break;
561 case 2:
562 if (ch >= '0' && ch <= '7') {
563 iEscCode =
564 iEscCode * 8 + FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch));
565 status = 3;
566 } else {
567 buf.AppendChar(iEscCode);
568 status = 0;
569 continue;
570 }
571 break;
572 case 3:
573 if (ch >= '0' && ch <= '7') {
574 iEscCode =
575 iEscCode * 8 + FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch));
576 buf.AppendChar(iEscCode);
577 status = 0;
578 } else {
579 buf.AppendChar(iEscCode);
580 status = 0;
581 continue;
582 }
583 break;
584 case 4:
585 status = 0;
586 if (ch != '\n') {
587 continue;
588 }
589 break;
590 }
591 if (!PositionIsInBounds())
592 break;
593
594 ch = m_pBuf[m_Pos++];
595 }
596 if (PositionIsInBounds())
597 ++m_Pos;
598
599 if (buf.GetLength() > kMaxStringLength) {
600 return CFX_ByteString(buf.GetBuffer(), kMaxStringLength);
601 }
602 return buf.MakeString();
603 }
604
605 CFX_ByteString CPDF_StreamParser::ReadHexString() {
606 if (!PositionIsInBounds())
607 return CFX_ByteString();
608
609 CFX_ByteTextBuf buf;
610 bool bFirst = true;
611 int code = 0;
612 while (PositionIsInBounds()) {
613 int ch = m_pBuf[m_Pos++];
614
615 if (ch == '>')
616 break;
617
618 if (!std::isxdigit(ch))
619 continue;
620
621 int val = FXSYS_toHexDigit(ch);
622 if (bFirst) {
623 code = val * 16;
624 } else {
625 code += val;
626 buf.AppendByte((uint8_t)code);
627 }
628 bFirst = !bFirst;
629 }
630 if (!bFirst)
631 buf.AppendChar((char)code);
632
633 if (buf.GetLength() > kMaxStringLength)
634 return CFX_ByteString(buf.GetBuffer(), kMaxStringLength);
635
636 return buf.MakeString();
637 }
638
639 bool CPDF_StreamParser::PositionIsInBounds() const {
640 return m_Pos < m_Size;
641 }
642
643 CPDF_ContentParser::CPDF_ContentParser()
644 : m_Status(Ready),
645 m_InternalStage(STAGE_GETCONTENT),
646 m_pObjectHolder(nullptr),
647 m_bForm(false),
648 m_pType3Char(nullptr),
649 m_pData(nullptr),
650 m_Size(0),
651 m_CurrentOffset(0) {}
652
653 CPDF_ContentParser::~CPDF_ContentParser() {
654 if (!m_pSingleStream)
655 FX_Free(m_pData);
656 }
657
658 void CPDF_ContentParser::Start(CPDF_Page* pPage) {
659 if (m_Status != Ready || !pPage || !pPage->m_pDocument ||
660 !pPage->m_pFormDict) {
661 m_Status = Done;
662 return;
663 }
664 m_pObjectHolder = pPage;
665 m_bForm = false;
666 m_Status = ToBeContinued;
667 m_InternalStage = STAGE_GETCONTENT;
668 m_CurrentOffset = 0;
669
670 CPDF_Object* pContent = pPage->m_pFormDict->GetDirectObjectFor("Contents");
671 if (!pContent) {
672 m_Status = Done;
673 return;
674 }
675 if (CPDF_Stream* pStream = pContent->AsStream()) {
676 m_nStreams = 0;
677 m_pSingleStream.reset(new CPDF_StreamAcc);
678 m_pSingleStream->LoadAllData(pStream, false);
679 } else if (CPDF_Array* pArray = pContent->AsArray()) {
680 m_nStreams = pArray->GetCount();
681 if (m_nStreams)
682 m_StreamArray.resize(m_nStreams);
683 else
684 m_Status = Done;
685 } else {
686 m_Status = Done;
687 }
688 }
689
690 void CPDF_ContentParser::Start(CPDF_Form* pForm,
691 CPDF_AllStates* pGraphicStates,
692 const CFX_Matrix* pParentMatrix,
693 CPDF_Type3Char* pType3Char,
694 int level) {
695 m_pType3Char = pType3Char;
696 m_pObjectHolder = pForm;
697 m_bForm = true;
698 CFX_Matrix form_matrix = pForm->m_pFormDict->GetMatrixFor("Matrix");
699 if (pGraphicStates) {
700 form_matrix.Concat(pGraphicStates->m_CTM);
701 }
702 CPDF_Array* pBBox = pForm->m_pFormDict->GetArrayFor("BBox");
703 CFX_FloatRect form_bbox;
704 CPDF_Path ClipPath;
705 if (pBBox) {
706 form_bbox = pBBox->GetRect();
707 ClipPath.Emplace();
708 ClipPath.AppendRect(form_bbox.left, form_bbox.bottom, form_bbox.right,
709 form_bbox.top);
710 ClipPath.Transform(&form_matrix);
711 if (pParentMatrix) {
712 ClipPath.Transform(pParentMatrix);
713 }
714 form_bbox.Transform(&form_matrix);
715 if (pParentMatrix) {
716 form_bbox.Transform(pParentMatrix);
717 }
718 }
719 CPDF_Dictionary* pResources = pForm->m_pFormDict->GetDictFor("Resources");
720 m_pParser.reset(new CPDF_StreamContentParser(
721 pForm->m_pDocument, pForm->m_pPageResources, pForm->m_pResources,
722 pParentMatrix, pForm, pResources, &form_bbox, pGraphicStates, level));
723 m_pParser->GetCurStates()->m_CTM = form_matrix;
724 m_pParser->GetCurStates()->m_ParentMatrix = form_matrix;
725 if (ClipPath) {
726 m_pParser->GetCurStates()->m_ClipPath.AppendPath(ClipPath, FXFILL_WINDING,
727 true);
728 }
729 if (pForm->m_Transparency & PDFTRANS_GROUP) {
730 CPDF_GeneralState* pState = &m_pParser->GetCurStates()->m_GeneralState;
731 pState->SetBlendType(FXDIB_BLEND_NORMAL);
732 pState->SetStrokeAlpha(1.0f);
733 pState->SetFillAlpha(1.0f);
734 pState->SetSoftMask(nullptr);
735 }
736 m_nStreams = 0;
737 m_pSingleStream.reset(new CPDF_StreamAcc);
738 m_pSingleStream->LoadAllData(pForm->m_pFormStream, false);
739 m_pData = (uint8_t*)m_pSingleStream->GetData();
740 m_Size = m_pSingleStream->GetSize();
741 m_Status = ToBeContinued;
742 m_InternalStage = STAGE_PARSE;
743 m_CurrentOffset = 0;
744 }
745
746 void CPDF_ContentParser::Continue(IFX_Pause* pPause) {
747 int steps = 0;
748 while (m_Status == ToBeContinued) {
749 if (m_InternalStage == STAGE_GETCONTENT) {
750 if (m_CurrentOffset == m_nStreams) {
751 if (!m_StreamArray.empty()) {
752 FX_SAFE_UINT32 safeSize = 0;
753 for (const auto& stream : m_StreamArray) {
754 safeSize += stream->GetSize();
755 safeSize += 1;
756 }
757 if (!safeSize.IsValid()) {
758 m_Status = Done;
759 return;
760 }
761 m_Size = safeSize.ValueOrDie();
762 m_pData = FX_Alloc(uint8_t, m_Size);
763 uint32_t pos = 0;
764 for (const auto& stream : m_StreamArray) {
765 FXSYS_memcpy(m_pData + pos, stream->GetData(), stream->GetSize());
766 pos += stream->GetSize();
767 m_pData[pos++] = ' ';
768 }
769 m_StreamArray.clear();
770 } else {
771 m_pData = (uint8_t*)m_pSingleStream->GetData();
772 m_Size = m_pSingleStream->GetSize();
773 }
774 m_InternalStage = STAGE_PARSE;
775 m_CurrentOffset = 0;
776 } else {
777 CPDF_Array* pContent =
778 m_pObjectHolder->m_pFormDict->GetArrayFor("Contents");
779 m_StreamArray[m_CurrentOffset].reset(new CPDF_StreamAcc);
780 CPDF_Stream* pStreamObj = ToStream(
781 pContent ? pContent->GetDirectObjectAt(m_CurrentOffset) : nullptr);
782 m_StreamArray[m_CurrentOffset]->LoadAllData(pStreamObj, false);
783 m_CurrentOffset++;
784 }
785 }
786 if (m_InternalStage == STAGE_PARSE) {
787 if (!m_pParser) {
788 m_pParser.reset(new CPDF_StreamContentParser(
789 m_pObjectHolder->m_pDocument, m_pObjectHolder->m_pPageResources,
790 nullptr, nullptr, m_pObjectHolder, m_pObjectHolder->m_pResources,
791 &m_pObjectHolder->m_BBox, nullptr, 0));
792 m_pParser->GetCurStates()->m_ColorState.SetDefault();
793 }
794 if (m_CurrentOffset >= m_Size) {
795 m_InternalStage = STAGE_CHECKCLIP;
796 } else {
797 m_CurrentOffset +=
798 m_pParser->Parse(m_pData + m_CurrentOffset,
799 m_Size - m_CurrentOffset, PARSE_STEP_LIMIT);
800 }
801 }
802 if (m_InternalStage == STAGE_CHECKCLIP) {
803 if (m_pType3Char) {
804 m_pType3Char->m_bColored = m_pParser->IsColored();
805 m_pType3Char->m_Width =
806 FXSYS_round(m_pParser->GetType3Data()[0] * 1000);
807 m_pType3Char->m_BBox.left =
808 FXSYS_round(m_pParser->GetType3Data()[2] * 1000);
809 m_pType3Char->m_BBox.bottom =
810 FXSYS_round(m_pParser->GetType3Data()[3] * 1000);
811 m_pType3Char->m_BBox.right =
812 FXSYS_round(m_pParser->GetType3Data()[4] * 1000);
813 m_pType3Char->m_BBox.top =
814 FXSYS_round(m_pParser->GetType3Data()[5] * 1000);
815 }
816 for (auto& pObj : *m_pObjectHolder->GetPageObjectList()) {
817 if (!pObj->m_ClipPath)
818 continue;
819 if (pObj->m_ClipPath.GetPathCount() != 1)
820 continue;
821 if (pObj->m_ClipPath.GetTextCount())
822 continue;
823 CPDF_Path ClipPath = pObj->m_ClipPath.GetPath(0);
824 if (!ClipPath.IsRect() || pObj->IsShading())
825 continue;
826 CFX_FloatRect old_rect(ClipPath.GetPointX(0), ClipPath.GetPointY(0),
827 ClipPath.GetPointX(2), ClipPath.GetPointY(2));
828 CFX_FloatRect obj_rect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right,
829 pObj->m_Top);
830 if (old_rect.Contains(obj_rect)) {
831 pObj->m_ClipPath.SetNull();
832 }
833 }
834 m_Status = Done;
835 return;
836 }
837 steps++;
838 if (pPause && pPause->NeedToPauseNow()) {
839 break;
840 }
841 }
842 }
OLDNEW
« no previous file with comments | « core/fpdfapi/page/fpdf_page_parser.cpp ('k') | core/fpdfapi/page/fpdf_page_parser_old_unittest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698