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 // static
ChooseResourcesDict(CPDF_Dictionary * pResources,CPDF_Dictionary * pParentResources,CPDF_Dictionary * pPageResources)22 CPDF_Dictionary* CPDF_Form::ChooseResourcesDict(
23 CPDF_Dictionary* pResources,
24 CPDF_Dictionary* pParentResources,
25 CPDF_Dictionary* pPageResources) {
26 if (pResources)
27 return pResources;
28 return pParentResources ? pParentResources : pPageResources;
29 }
30
CPDF_Form(CPDF_Document * pDoc,RetainPtr<CPDF_Dictionary> pPageResources,RetainPtr<CPDF_Stream> pFormStream)31 CPDF_Form::CPDF_Form(CPDF_Document* pDoc,
32 RetainPtr<CPDF_Dictionary> pPageResources,
33 RetainPtr<CPDF_Stream> pFormStream)
34 : CPDF_Form(pDoc,
35 std::move(pPageResources),
36 std::move(pFormStream),
37 nullptr) {}
38
CPDF_Form(CPDF_Document * pDoc,RetainPtr<CPDF_Dictionary> pPageResources,RetainPtr<CPDF_Stream> pFormStream,CPDF_Dictionary * pParentResources)39 CPDF_Form::CPDF_Form(CPDF_Document* pDoc,
40 RetainPtr<CPDF_Dictionary> pPageResources,
41 RetainPtr<CPDF_Stream> pFormStream,
42 CPDF_Dictionary* pParentResources)
43 : CPDF_PageObjectHolder(pDoc,
44 pFormStream->GetMutableDict(),
45 pPageResources,
46 pdfium::WrapRetain(ChooseResourcesDict(
47 pFormStream->GetMutableDict()
48 ->GetMutableDictFor("Resources")
49 .Get(),
50 pParentResources,
51 pPageResources.Get()))),
52 m_pFormStream(std::move(pFormStream)) {
53 LoadTransparencyInfo();
54 }
55
56 CPDF_Form::~CPDF_Form() = default;
57
ParseContent()58 void CPDF_Form::ParseContent() {
59 ParseContentInternal(nullptr, nullptr, nullptr, nullptr);
60 }
61
ParseContent(const CPDF_AllStates * pGraphicStates,const CFX_Matrix * pParentMatrix,std::set<const uint8_t * > * pParsedSet)62 void CPDF_Form::ParseContent(const CPDF_AllStates* pGraphicStates,
63 const CFX_Matrix* pParentMatrix,
64 std::set<const uint8_t*>* pParsedSet) {
65 ParseContentInternal(pGraphicStates, pParentMatrix, nullptr, pParsedSet);
66 }
67
ParseContentForType3Char(CPDF_Type3Char * pType3Char)68 void CPDF_Form::ParseContentForType3Char(CPDF_Type3Char* pType3Char) {
69 ParseContentInternal(nullptr, nullptr, pType3Char, nullptr);
70 }
71
ParseContentInternal(const CPDF_AllStates * pGraphicStates,const CFX_Matrix * pParentMatrix,CPDF_Type3Char * pType3Char,std::set<const uint8_t * > * pParsedSet)72 void CPDF_Form::ParseContentInternal(const CPDF_AllStates* pGraphicStates,
73 const CFX_Matrix* pParentMatrix,
74 CPDF_Type3Char* pType3Char,
75 std::set<const uint8_t*>* pParsedSet) {
76 if (GetParseState() == ParseState::kParsed)
77 return;
78
79 if (GetParseState() == ParseState::kNotParsed) {
80 StartParse(std::make_unique<CPDF_ContentParser>(
81 GetStream(), this, pGraphicStates, pParentMatrix, pType3Char,
82 pParsedSet ? pParsedSet : &m_ParsedSet));
83 }
84 DCHECK_EQ(GetParseState(), ParseState::kParsing);
85 ContinueParse(nullptr);
86 }
87
HasPageObjects() const88 bool CPDF_Form::HasPageObjects() const {
89 return GetPageObjectCount() != 0;
90 }
91
CalcBoundingBox() const92 CFX_FloatRect CPDF_Form::CalcBoundingBox() const {
93 if (GetPageObjectCount() == 0)
94 return CFX_FloatRect();
95
96 float left = 1000000.0f;
97 float right = -1000000.0f;
98 float bottom = 1000000.0f;
99 float top = -1000000.0f;
100 for (const auto& pObj : *this) {
101 const auto& rect = pObj->GetRect();
102 left = std::min(left, rect.left);
103 right = std::max(right, rect.right);
104 bottom = std::min(bottom, rect.bottom);
105 top = std::max(top, rect.top);
106 }
107 return CFX_FloatRect(left, bottom, right, top);
108 }
109
GetStream() const110 RetainPtr<const CPDF_Stream> CPDF_Form::GetStream() const {
111 return m_pFormStream;
112 }
113
114 absl::optional<std::pair<RetainPtr<CFX_DIBitmap>, CFX_Matrix>>
GetBitmapAndMatrixFromSoleImageOfForm() const115 CPDF_Form::GetBitmapAndMatrixFromSoleImageOfForm() const {
116 if (GetPageObjectCount() != 1)
117 return absl::nullopt;
118
119 CPDF_ImageObject* pImageObject = (*begin())->AsImage();
120 if (!pImageObject)
121 return absl::nullopt;
122
123 return {{pImageObject->GetIndependentBitmap(), pImageObject->matrix()}};
124 }
125