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

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

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

Powered by Google App Engine
This is Rietveld 408576698