| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 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 "core/fpdfapi/font/cpdf_type3char.h" |
| 10 #include "core/fpdfapi/page/cpdf_allstates.h" |
| 11 #include "core/fpdfapi/page/cpdf_form.h" |
| 12 #include "core/fpdfapi/page/cpdf_page.h" |
| 13 #include "core/fpdfapi/page/cpdf_pageobject.h" |
| 14 #include "core/fpdfapi/page/cpdf_path.h" |
| 15 #include "core/fpdfapi/parser/cpdf_array.h" |
| 16 #include "core/fpdfapi/parser/cpdf_dictionary.h" |
| 17 #include "core/fpdfapi/parser/cpdf_stream.h" |
| 18 #include "core/fpdfapi/parser/cpdf_stream_acc.h" |
| 19 #include "core/fxcrt/fx_safe_types.h" |
| 20 |
| 21 CPDF_ContentParser::CPDF_ContentParser() |
| 22 : m_Status(Ready), |
| 23 m_InternalStage(STAGE_GETCONTENT), |
| 24 m_pObjectHolder(nullptr), |
| 25 m_bForm(false), |
| 26 m_pType3Char(nullptr), |
| 27 m_pData(nullptr), |
| 28 m_Size(0), |
| 29 m_CurrentOffset(0) {} |
| 30 |
| 31 CPDF_ContentParser::~CPDF_ContentParser() { |
| 32 if (!m_pSingleStream) |
| 33 FX_Free(m_pData); |
| 34 } |
| 35 |
| 36 void CPDF_ContentParser::Start(CPDF_Page* pPage) { |
| 37 if (m_Status != Ready || !pPage || !pPage->m_pDocument || |
| 38 !pPage->m_pFormDict) { |
| 39 m_Status = Done; |
| 40 return; |
| 41 } |
| 42 m_pObjectHolder = pPage; |
| 43 m_bForm = false; |
| 44 m_Status = ToBeContinued; |
| 45 m_InternalStage = STAGE_GETCONTENT; |
| 46 m_CurrentOffset = 0; |
| 47 |
| 48 CPDF_Object* pContent = pPage->m_pFormDict->GetDirectObjectFor("Contents"); |
| 49 if (!pContent) { |
| 50 m_Status = Done; |
| 51 return; |
| 52 } |
| 53 if (CPDF_Stream* pStream = pContent->AsStream()) { |
| 54 m_nStreams = 0; |
| 55 m_pSingleStream.reset(new CPDF_StreamAcc); |
| 56 m_pSingleStream->LoadAllData(pStream, false); |
| 57 } else if (CPDF_Array* pArray = pContent->AsArray()) { |
| 58 m_nStreams = pArray->GetCount(); |
| 59 if (m_nStreams) |
| 60 m_StreamArray.resize(m_nStreams); |
| 61 else |
| 62 m_Status = Done; |
| 63 } else { |
| 64 m_Status = Done; |
| 65 } |
| 66 } |
| 67 |
| 68 void CPDF_ContentParser::Start(CPDF_Form* pForm, |
| 69 CPDF_AllStates* pGraphicStates, |
| 70 const CFX_Matrix* pParentMatrix, |
| 71 CPDF_Type3Char* pType3Char, |
| 72 int level) { |
| 73 m_pType3Char = pType3Char; |
| 74 m_pObjectHolder = pForm; |
| 75 m_bForm = true; |
| 76 CFX_Matrix form_matrix = pForm->m_pFormDict->GetMatrixFor("Matrix"); |
| 77 if (pGraphicStates) |
| 78 form_matrix.Concat(pGraphicStates->m_CTM); |
| 79 CPDF_Array* pBBox = pForm->m_pFormDict->GetArrayFor("BBox"); |
| 80 CFX_FloatRect form_bbox; |
| 81 CPDF_Path ClipPath; |
| 82 if (pBBox) { |
| 83 form_bbox = pBBox->GetRect(); |
| 84 ClipPath.Emplace(); |
| 85 ClipPath.AppendRect(form_bbox.left, form_bbox.bottom, form_bbox.right, |
| 86 form_bbox.top); |
| 87 ClipPath.Transform(&form_matrix); |
| 88 if (pParentMatrix) |
| 89 ClipPath.Transform(pParentMatrix); |
| 90 form_bbox.Transform(&form_matrix); |
| 91 if (pParentMatrix) |
| 92 form_bbox.Transform(pParentMatrix); |
| 93 } |
| 94 CPDF_Dictionary* pResources = pForm->m_pFormDict->GetDictFor("Resources"); |
| 95 m_pParser.reset(new CPDF_StreamContentParser( |
| 96 pForm->m_pDocument, pForm->m_pPageResources, pForm->m_pResources, |
| 97 pParentMatrix, pForm, pResources, &form_bbox, pGraphicStates, level)); |
| 98 m_pParser->GetCurStates()->m_CTM = form_matrix; |
| 99 m_pParser->GetCurStates()->m_ParentMatrix = form_matrix; |
| 100 if (ClipPath) { |
| 101 m_pParser->GetCurStates()->m_ClipPath.AppendPath(ClipPath, FXFILL_WINDING, |
| 102 true); |
| 103 } |
| 104 if (pForm->m_Transparency & PDFTRANS_GROUP) { |
| 105 CPDF_GeneralState* pState = &m_pParser->GetCurStates()->m_GeneralState; |
| 106 pState->SetBlendType(FXDIB_BLEND_NORMAL); |
| 107 pState->SetStrokeAlpha(1.0f); |
| 108 pState->SetFillAlpha(1.0f); |
| 109 pState->SetSoftMask(nullptr); |
| 110 } |
| 111 m_nStreams = 0; |
| 112 m_pSingleStream.reset(new CPDF_StreamAcc); |
| 113 m_pSingleStream->LoadAllData(pForm->m_pFormStream, false); |
| 114 m_pData = (uint8_t*)m_pSingleStream->GetData(); |
| 115 m_Size = m_pSingleStream->GetSize(); |
| 116 m_Status = ToBeContinued; |
| 117 m_InternalStage = STAGE_PARSE; |
| 118 m_CurrentOffset = 0; |
| 119 } |
| 120 |
| 121 void CPDF_ContentParser::Continue(IFX_Pause* pPause) { |
| 122 int steps = 0; |
| 123 while (m_Status == ToBeContinued) { |
| 124 if (m_InternalStage == STAGE_GETCONTENT) { |
| 125 if (m_CurrentOffset == m_nStreams) { |
| 126 if (!m_StreamArray.empty()) { |
| 127 FX_SAFE_UINT32 safeSize = 0; |
| 128 for (const auto& stream : m_StreamArray) { |
| 129 safeSize += stream->GetSize(); |
| 130 safeSize += 1; |
| 131 } |
| 132 if (!safeSize.IsValid()) { |
| 133 m_Status = Done; |
| 134 return; |
| 135 } |
| 136 m_Size = safeSize.ValueOrDie(); |
| 137 m_pData = FX_Alloc(uint8_t, m_Size); |
| 138 uint32_t pos = 0; |
| 139 for (const auto& stream : m_StreamArray) { |
| 140 FXSYS_memcpy(m_pData + pos, stream->GetData(), stream->GetSize()); |
| 141 pos += stream->GetSize(); |
| 142 m_pData[pos++] = ' '; |
| 143 } |
| 144 m_StreamArray.clear(); |
| 145 } else { |
| 146 m_pData = (uint8_t*)m_pSingleStream->GetData(); |
| 147 m_Size = m_pSingleStream->GetSize(); |
| 148 } |
| 149 m_InternalStage = STAGE_PARSE; |
| 150 m_CurrentOffset = 0; |
| 151 } else { |
| 152 CPDF_Array* pContent = |
| 153 m_pObjectHolder->m_pFormDict->GetArrayFor("Contents"); |
| 154 m_StreamArray[m_CurrentOffset].reset(new CPDF_StreamAcc); |
| 155 CPDF_Stream* pStreamObj = ToStream( |
| 156 pContent ? pContent->GetDirectObjectAt(m_CurrentOffset) : nullptr); |
| 157 m_StreamArray[m_CurrentOffset]->LoadAllData(pStreamObj, false); |
| 158 m_CurrentOffset++; |
| 159 } |
| 160 } |
| 161 if (m_InternalStage == STAGE_PARSE) { |
| 162 if (!m_pParser) { |
| 163 m_pParser.reset(new CPDF_StreamContentParser( |
| 164 m_pObjectHolder->m_pDocument, m_pObjectHolder->m_pPageResources, |
| 165 nullptr, nullptr, m_pObjectHolder, m_pObjectHolder->m_pResources, |
| 166 &m_pObjectHolder->m_BBox, nullptr, 0)); |
| 167 m_pParser->GetCurStates()->m_ColorState.SetDefault(); |
| 168 } |
| 169 if (m_CurrentOffset >= m_Size) { |
| 170 m_InternalStage = STAGE_CHECKCLIP; |
| 171 } else { |
| 172 m_CurrentOffset += |
| 173 m_pParser->Parse(m_pData + m_CurrentOffset, |
| 174 m_Size - m_CurrentOffset, PARSE_STEP_LIMIT); |
| 175 } |
| 176 } |
| 177 if (m_InternalStage == STAGE_CHECKCLIP) { |
| 178 if (m_pType3Char) { |
| 179 m_pType3Char->m_bColored = m_pParser->IsColored(); |
| 180 m_pType3Char->m_Width = |
| 181 FXSYS_round(m_pParser->GetType3Data()[0] * 1000); |
| 182 m_pType3Char->m_BBox.left = |
| 183 FXSYS_round(m_pParser->GetType3Data()[2] * 1000); |
| 184 m_pType3Char->m_BBox.bottom = |
| 185 FXSYS_round(m_pParser->GetType3Data()[3] * 1000); |
| 186 m_pType3Char->m_BBox.right = |
| 187 FXSYS_round(m_pParser->GetType3Data()[4] * 1000); |
| 188 m_pType3Char->m_BBox.top = |
| 189 FXSYS_round(m_pParser->GetType3Data()[5] * 1000); |
| 190 } |
| 191 for (auto& pObj : *m_pObjectHolder->GetPageObjectList()) { |
| 192 if (!pObj->m_ClipPath) |
| 193 continue; |
| 194 if (pObj->m_ClipPath.GetPathCount() != 1) |
| 195 continue; |
| 196 if (pObj->m_ClipPath.GetTextCount()) |
| 197 continue; |
| 198 CPDF_Path ClipPath = pObj->m_ClipPath.GetPath(0); |
| 199 if (!ClipPath.IsRect() || pObj->IsShading()) |
| 200 continue; |
| 201 CFX_FloatRect old_rect(ClipPath.GetPointX(0), ClipPath.GetPointY(0), |
| 202 ClipPath.GetPointX(2), ClipPath.GetPointY(2)); |
| 203 CFX_FloatRect obj_rect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, |
| 204 pObj->m_Top); |
| 205 if (old_rect.Contains(obj_rect)) |
| 206 pObj->m_ClipPath.SetNull(); |
| 207 } |
| 208 m_Status = Done; |
| 209 return; |
| 210 } |
| 211 steps++; |
| 212 if (pPause && pPause->NeedToPauseNow()) |
| 213 break; |
| 214 } |
| 215 } |
| OLD | NEW |