1 // Copyright 2016 The PDFium Authors
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/cpdf_form.h"
8
9 #include <algorithm>
10 #include <memory>
11
12 #include "core/fpdfapi/page/cpdf_contentparser.h"
13 #include "core/fpdfapi/page/cpdf_imageobject.h"
14 #include "core/fpdfapi/page/cpdf_pageobject.h"
15 #include "core/fpdfapi/page/cpdf_pageobjectholder.h"
16 #include "core/fpdfapi/parser/cpdf_dictionary.h"
17 #include "core/fpdfapi/parser/cpdf_stream.h"
18 #include "core/fxge/dib/cfx_dibitmap.h"
19 #include "third_party/base/check_op.h"
20
21 CPDF_Form::RecursionState::RecursionState() = default;
22
23 CPDF_Form::RecursionState::~RecursionState() = default;
24
25 // static
ChooseResourcesDict(CPDF_Dictionary * pResources,CPDF_Dictionary * pParentResources,CPDF_Dictionary * pPageResources)26 CPDF_Dictionary* CPDF_Form::ChooseResourcesDict(
27 CPDF_Dictionary* pResources,
28 CPDF_Dictionary* pParentResources,
29 CPDF_Dictionary* pPageResources) {
30 if (pResources)
31 return pResources;
32 return pParentResources ? pParentResources : pPageResources;
33 }
34
CPDF_Form(CPDF_Document * pDoc,RetainPtr<CPDF_Dictionary> pPageResources,RetainPtr<CPDF_Stream> pFormStream)35 CPDF_Form::CPDF_Form(CPDF_Document* pDoc,
36 RetainPtr<CPDF_Dictionary> pPageResources,
37 RetainPtr<CPDF_Stream> pFormStream)
38 : CPDF_Form(pDoc,
39 std::move(pPageResources),
40 std::move(pFormStream),
41 nullptr) {}
42
CPDF_Form(CPDF_Document * pDoc,RetainPtr<CPDF_Dictionary> pPageResources,RetainPtr<CPDF_Stream> pFormStream,CPDF_Dictionary * pParentResources)43 CPDF_Form::CPDF_Form(CPDF_Document* pDoc,
44 RetainPtr<CPDF_Dictionary> pPageResources,
45 RetainPtr<CPDF_Stream> pFormStream,
46 CPDF_Dictionary* pParentResources)
47 : CPDF_PageObjectHolder(pDoc,
48 pFormStream->GetMutableDict(),
49 pPageResources,
50 pdfium::WrapRetain(ChooseResourcesDict(
51 pFormStream->GetMutableDict()
52 ->GetMutableDictFor("Resources")
53 .Get(),
54 pParentResources,
55 pPageResources.Get()))),
56 m_pFormStream(std::move(pFormStream)) {
57 LoadTransparencyInfo();
58 }
59
60 CPDF_Form::~CPDF_Form() = default;
61
ParseContent()62 void CPDF_Form::ParseContent() {
63 ParseContentInternal(nullptr, nullptr, nullptr, nullptr);
64 }
65
ParseContent(const CPDF_AllStates * pGraphicStates,const CFX_Matrix * pParentMatrix,RecursionState * recursion_state)66 void CPDF_Form::ParseContent(const CPDF_AllStates* pGraphicStates,
67 const CFX_Matrix* pParentMatrix,
68 RecursionState* recursion_state) {
69 ParseContentInternal(pGraphicStates, pParentMatrix, nullptr, recursion_state);
70 }
71
ParseContentForType3Char(CPDF_Type3Char * pType3Char)72 void CPDF_Form::ParseContentForType3Char(CPDF_Type3Char* pType3Char) {
73 ParseContentInternal(nullptr, nullptr, pType3Char, nullptr);
74 }
75
ParseContentInternal(const CPDF_AllStates * pGraphicStates,const CFX_Matrix * pParentMatrix,CPDF_Type3Char * pType3Char,RecursionState * recursion_state)76 void CPDF_Form::ParseContentInternal(const CPDF_AllStates* pGraphicStates,
77 const CFX_Matrix* pParentMatrix,
78 CPDF_Type3Char* pType3Char,
79 RecursionState* recursion_state) {
80 if (GetParseState() == ParseState::kParsed)
81 return;
82
83 if (GetParseState() == ParseState::kNotParsed) {
84 StartParse(std::make_unique<CPDF_ContentParser>(
85 GetStream(), this, pGraphicStates, pParentMatrix, pType3Char,
86 recursion_state ? recursion_state : &m_RecursionState));
87 }
88 DCHECK_EQ(GetParseState(), ParseState::kParsing);
89 ContinueParse(nullptr);
90 }
91
HasPageObjects() const92 bool CPDF_Form::HasPageObjects() const {
93 return GetPageObjectCount() != 0;
94 }
95
CalcBoundingBox() const96 CFX_FloatRect CPDF_Form::CalcBoundingBox() const {
97 if (GetPageObjectCount() == 0)
98 return CFX_FloatRect();
99
100 float left = 1000000.0f;
101 float right = -1000000.0f;
102 float bottom = 1000000.0f;
103 float top = -1000000.0f;
104 for (const auto& pObj : *this) {
105 const auto& rect = pObj->GetRect();
106 left = std::min(left, rect.left);
107 right = std::max(right, rect.right);
108 bottom = std::min(bottom, rect.bottom);
109 top = std::max(top, rect.top);
110 }
111 return CFX_FloatRect(left, bottom, right, top);
112 }
113
GetStream() const114 RetainPtr<const CPDF_Stream> CPDF_Form::GetStream() const {
115 return m_pFormStream;
116 }
117
118 absl::optional<std::pair<RetainPtr<CFX_DIBitmap>, CFX_Matrix>>
GetBitmapAndMatrixFromSoleImageOfForm() const119 CPDF_Form::GetBitmapAndMatrixFromSoleImageOfForm() const {
120 if (GetPageObjectCount() != 1)
121 return absl::nullopt;
122
123 CPDF_ImageObject* pImageObject = (*begin())->AsImage();
124 if (!pImageObject)
125 return absl::nullopt;
126
127 return {{pImageObject->GetIndependentBitmap(), pImageObject->matrix()}};
128 }
129