xref: /aosp_15_r20/external/pdfium/core/fpdfapi/page/cpdf_form.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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