| OLD | NEW |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2016 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include "core/fpdfapi/page/pageint.h" | 7 #include "core/fpdfapi/page/pageint.h" |
| 8 | 8 |
| 9 #include <limits.h> | 9 #include <limits.h> |
| 10 | 10 |
| 11 #include "core/fpdfapi/cpdf_modulemgr.h" | 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" | 12 #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" | 13 #include "core/fpdfapi/parser/cpdf_array.h" |
| 20 #include "core/fpdfapi/parser/cpdf_boolean.h" | 14 #include "core/fpdfapi/parser/cpdf_boolean.h" |
| 21 #include "core/fpdfapi/parser/cpdf_dictionary.h" | 15 #include "core/fpdfapi/parser/cpdf_dictionary.h" |
| 22 #include "core/fpdfapi/parser/cpdf_document.h" | 16 #include "core/fpdfapi/parser/cpdf_document.h" |
| 23 #include "core/fpdfapi/parser/cpdf_name.h" | 17 #include "core/fpdfapi/parser/cpdf_name.h" |
| 24 #include "core/fpdfapi/parser/cpdf_null.h" | 18 #include "core/fpdfapi/parser/cpdf_null.h" |
| 25 #include "core/fpdfapi/parser/cpdf_number.h" | 19 #include "core/fpdfapi/parser/cpdf_number.h" |
| 26 #include "core/fpdfapi/parser/cpdf_stream.h" | 20 #include "core/fpdfapi/parser/cpdf_stream.h" |
| 27 #include "core/fpdfapi/parser/cpdf_stream_acc.h" | |
| 28 #include "core/fpdfapi/parser/cpdf_string.h" | 21 #include "core/fpdfapi/parser/cpdf_string.h" |
| 29 #include "core/fpdfapi/parser/fpdf_parser_decode.h" | 22 #include "core/fpdfapi/parser/fpdf_parser_decode.h" |
| 30 #include "core/fpdfapi/parser/fpdf_parser_utility.h" | 23 #include "core/fpdfapi/parser/fpdf_parser_utility.h" |
| 31 #include "core/fxcodec/fx_codec.h" | 24 #include "core/fxcodec/fx_codec.h" |
| 32 #include "core/fxcrt/fx_ext.h" | 25 #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 | 26 |
| 37 CCodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder( | 27 CCodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder( |
| 38 const uint8_t* src_buf, | 28 const uint8_t* src_buf, |
| 39 uint32_t src_size, | 29 uint32_t src_size, |
| 40 int width, | 30 int width, |
| 41 int height, | 31 int height, |
| 42 const CPDF_Dictionary* pParams); | 32 const CPDF_Dictionary* pParams); |
| 43 | 33 |
| 44 namespace { | 34 namespace { |
| 45 | 35 |
| 46 const uint32_t kMaxNestedArrayLevel = 512; | 36 const uint32_t kMaxNestedArrayLevel = 512; |
| 47 const uint32_t kMaxWordBuffer = 256; | 37 const uint32_t kMaxWordBuffer = 256; |
| 48 const FX_STRSIZE kMaxStringLength = 32767; | 38 const FX_STRSIZE kMaxStringLength = 32767; |
| 49 | 39 |
| 50 uint32_t DecodeAllScanlines(CCodec_ScanlineDecoder* pDecoder, | 40 uint32_t DecodeAllScanlines(CCodec_ScanlineDecoder* pDecoder, |
| 51 uint8_t*& dest_buf, | 41 uint8_t*& dest_buf, |
| 52 uint32_t& dest_size) { | 42 uint32_t& dest_size) { |
| 53 if (!pDecoder) { | 43 if (!pDecoder) |
| 54 return FX_INVALID_OFFSET; | 44 return FX_INVALID_OFFSET; |
| 55 } | |
| 56 int ncomps = pDecoder->CountComps(); | 45 int ncomps = pDecoder->CountComps(); |
| 57 int bpc = pDecoder->GetBPC(); | 46 int bpc = pDecoder->GetBPC(); |
| 58 int width = pDecoder->GetWidth(); | 47 int width = pDecoder->GetWidth(); |
| 59 int height = pDecoder->GetHeight(); | 48 int height = pDecoder->GetHeight(); |
| 60 int pitch = (width * ncomps * bpc + 7) / 8; | 49 int pitch = (width * ncomps * bpc + 7) / 8; |
| 61 if (height == 0 || pitch > (1 << 30) / height) { | 50 if (height == 0 || pitch > (1 << 30) / height) { |
| 62 delete pDecoder; | 51 delete pDecoder; |
| 63 return FX_INVALID_OFFSET; | 52 return FX_INVALID_OFFSET; |
| 64 } | 53 } |
| 65 dest_buf = FX_Alloc2D(uint8_t, pitch, height); | 54 dest_buf = FX_Alloc2D(uint8_t, pitch, height); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 82 int height, | 71 int height, |
| 83 CFX_ByteString& decoder, | 72 CFX_ByteString& decoder, |
| 84 CPDF_Dictionary* pParam, | 73 CPDF_Dictionary* pParam, |
| 85 uint8_t*& dest_buf, | 74 uint8_t*& dest_buf, |
| 86 uint32_t& dest_size) { | 75 uint32_t& dest_size) { |
| 87 if (decoder == "CCITTFaxDecode" || decoder == "CCF") { | 76 if (decoder == "CCITTFaxDecode" || decoder == "CCF") { |
| 88 CCodec_ScanlineDecoder* pDecoder = | 77 CCodec_ScanlineDecoder* pDecoder = |
| 89 FPDFAPI_CreateFaxDecoder(src_buf, limit, width, height, pParam); | 78 FPDFAPI_CreateFaxDecoder(src_buf, limit, width, height, pParam); |
| 90 return DecodeAllScanlines(pDecoder, dest_buf, dest_size); | 79 return DecodeAllScanlines(pDecoder, dest_buf, dest_size); |
| 91 } | 80 } |
| 92 if (decoder == "ASCII85Decode" || decoder == "A85") { | 81 if (decoder == "ASCII85Decode" || decoder == "A85") |
| 93 return A85Decode(src_buf, limit, dest_buf, dest_size); | 82 return A85Decode(src_buf, limit, dest_buf, dest_size); |
| 94 } | 83 if (decoder == "ASCIIHexDecode" || decoder == "AHx") |
| 95 if (decoder == "ASCIIHexDecode" || decoder == "AHx") { | |
| 96 return HexDecode(src_buf, limit, dest_buf, dest_size); | 84 return HexDecode(src_buf, limit, dest_buf, dest_size); |
| 97 } | |
| 98 if (decoder == "FlateDecode" || decoder == "Fl") { | 85 if (decoder == "FlateDecode" || decoder == "Fl") { |
| 99 return FPDFAPI_FlateOrLZWDecode(false, src_buf, limit, pParam, dest_size, | 86 return FPDFAPI_FlateOrLZWDecode(false, src_buf, limit, pParam, dest_size, |
| 100 dest_buf, dest_size); | 87 dest_buf, dest_size); |
| 101 } | 88 } |
| 102 if (decoder == "LZWDecode" || decoder == "LZW") { | 89 if (decoder == "LZWDecode" || decoder == "LZW") { |
| 103 return FPDFAPI_FlateOrLZWDecode(true, src_buf, limit, pParam, 0, dest_buf, | 90 return FPDFAPI_FlateOrLZWDecode(true, src_buf, limit, pParam, 0, dest_buf, |
| 104 dest_size); | 91 dest_size); |
| 105 } | 92 } |
| 106 if (decoder == "DCTDecode" || decoder == "DCT") { | 93 if (decoder == "DCTDecode" || decoder == "DCT") { |
| 107 CCodec_ScanlineDecoder* pDecoder = | 94 CCodec_ScanlineDecoder* pDecoder = |
| 108 CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder( | 95 CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder( |
| 109 src_buf, limit, width, height, 0, | 96 src_buf, limit, width, height, 0, |
| 110 !pParam || pParam->GetIntegerFor("ColorTransform", 1)); | 97 !pParam || pParam->GetIntegerFor("ColorTransform", 1)); |
| 111 return DecodeAllScanlines(pDecoder, dest_buf, dest_size); | 98 return DecodeAllScanlines(pDecoder, dest_buf, dest_size); |
| 112 } | 99 } |
| 113 if (decoder == "RunLengthDecode" || decoder == "RL") { | 100 if (decoder == "RunLengthDecode" || decoder == "RL") |
| 114 return RunLengthDecode(src_buf, limit, dest_buf, dest_size); | 101 return RunLengthDecode(src_buf, limit, dest_buf, dest_size); |
| 115 } | |
| 116 dest_size = 0; | 102 dest_size = 0; |
| 117 dest_buf = 0; | 103 dest_buf = 0; |
| 118 return (uint32_t)-1; | 104 return (uint32_t)-1; |
| 119 } | 105 } |
| 120 | 106 |
| 121 } // namespace | 107 } // namespace |
| 122 | 108 |
| 123 CPDF_StreamParser::CPDF_StreamParser(const uint8_t* pData, uint32_t dwSize) | 109 CPDF_StreamParser::CPDF_StreamParser(const uint8_t* pData, uint32_t dwSize) |
| 124 : m_pBuf(pData), | 110 : m_pBuf(pData), |
| 125 m_Size(dwSize), | 111 m_Size(dwSize), |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 | 186 |
| 201 OrigSize = ((width + 7) / 8); | 187 OrigSize = ((width + 7) / 8); |
| 202 } | 188 } |
| 203 if (height && OrigSize > INT_MAX / height) | 189 if (height && OrigSize > INT_MAX / height) |
| 204 return nullptr; | 190 return nullptr; |
| 205 | 191 |
| 206 OrigSize *= height; | 192 OrigSize *= height; |
| 207 uint8_t* pData = nullptr; | 193 uint8_t* pData = nullptr; |
| 208 uint32_t dwStreamSize; | 194 uint32_t dwStreamSize; |
| 209 if (Decoder.IsEmpty()) { | 195 if (Decoder.IsEmpty()) { |
| 210 if (OrigSize > m_Size - m_Pos) { | 196 if (OrigSize > m_Size - m_Pos) |
| 211 OrigSize = m_Size - m_Pos; | 197 OrigSize = m_Size - m_Pos; |
| 212 } | |
| 213 pData = FX_Alloc(uint8_t, OrigSize); | 198 pData = FX_Alloc(uint8_t, OrigSize); |
| 214 FXSYS_memcpy(pData, m_pBuf + m_Pos, OrigSize); | 199 FXSYS_memcpy(pData, m_pBuf + m_Pos, OrigSize); |
| 215 dwStreamSize = OrigSize; | 200 dwStreamSize = OrigSize; |
| 216 m_Pos += OrigSize; | 201 m_Pos += OrigSize; |
| 217 } else { | 202 } else { |
| 218 uint32_t dwDestSize = OrigSize; | 203 uint32_t dwDestSize = OrigSize; |
| 219 dwStreamSize = | 204 dwStreamSize = |
| 220 PDF_DecodeInlineStream(m_pBuf + m_Pos, m_Size - m_Pos, width, height, | 205 PDF_DecodeInlineStream(m_pBuf + m_Pos, m_Size - m_Pos, width, height, |
| 221 Decoder, pParam, pData, dwDestSize); | 206 Decoder, pParam, pData, dwDestSize); |
| 222 FX_Free(pData); | 207 FX_Free(pData); |
| 223 if ((int)dwStreamSize < 0) | 208 if (static_cast<int>(dwStreamSize) < 0) |
| 224 return nullptr; | 209 return nullptr; |
| 225 | 210 |
| 226 uint32_t dwSavePos = m_Pos; | 211 uint32_t dwSavePos = m_Pos; |
| 227 m_Pos += dwStreamSize; | 212 m_Pos += dwStreamSize; |
| 228 while (1) { | 213 while (1) { |
| 229 uint32_t dwPrevPos = m_Pos; | 214 uint32_t dwPrevPos = m_Pos; |
| 230 CPDF_StreamParser::SyntaxType type = ParseNextElement(); | 215 CPDF_StreamParser::SyntaxType type = ParseNextElement(); |
| 231 if (type == CPDF_StreamParser::EndOfData) | 216 if (type == CPDF_StreamParser::EndOfData) |
| 232 break; | 217 break; |
| 233 | 218 |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 if (memcmp(m_WordBuffer, "true", 4) == 0) | 406 if (memcmp(m_WordBuffer, "true", 4) == 0) |
| 422 return new CPDF_Boolean(true); | 407 return new CPDF_Boolean(true); |
| 423 | 408 |
| 424 if (memcmp(m_WordBuffer, "null", 4) == 0) | 409 if (memcmp(m_WordBuffer, "null", 4) == 0) |
| 425 return new CPDF_Null; | 410 return new CPDF_Null; |
| 426 } | 411 } |
| 427 | 412 |
| 428 return nullptr; | 413 return nullptr; |
| 429 } | 414 } |
| 430 | 415 |
| 416 // TODO(npm): the following methods are almost identical in cpdf_syntaxparser |
| 431 void CPDF_StreamParser::GetNextWord(bool& bIsNumber) { | 417 void CPDF_StreamParser::GetNextWord(bool& bIsNumber) { |
| 432 m_WordSize = 0; | 418 m_WordSize = 0; |
| 433 bIsNumber = true; | 419 bIsNumber = true; |
| 434 if (!PositionIsInBounds()) | 420 if (!PositionIsInBounds()) |
| 435 return; | 421 return; |
| 436 | 422 |
| 437 int ch = m_pBuf[m_Pos++]; | 423 int ch = m_pBuf[m_Pos++]; |
| 438 while (1) { | 424 while (1) { |
| 439 while (PDFCharIsWhitespace(ch)) { | 425 while (PDFCharIsWhitespace(ch)) { |
| 440 if (!PositionIsInBounds()) { | 426 if (!PositionIsInBounds()) { |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 | 622 |
| 637 if (buf.GetLength() > kMaxStringLength) | 623 if (buf.GetLength() > kMaxStringLength) |
| 638 return CFX_ByteString(buf.GetBuffer(), kMaxStringLength); | 624 return CFX_ByteString(buf.GetBuffer(), kMaxStringLength); |
| 639 | 625 |
| 640 return buf.MakeString(); | 626 return buf.MakeString(); |
| 641 } | 627 } |
| 642 | 628 |
| 643 bool CPDF_StreamParser::PositionIsInBounds() const { | 629 bool CPDF_StreamParser::PositionIsInBounds() const { |
| 644 return m_Pos < m_Size; | 630 return m_Pos < m_Size; |
| 645 } | 631 } |
| 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 } | |
| OLD | NEW |