• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_pageobjectholder.h"
8 
9 #include <algorithm>
10 #include <utility>
11 
12 #include "constants/transparency.h"
13 #include "core/fpdfapi/page/cpdf_allstates.h"
14 #include "core/fpdfapi/page/cpdf_contentparser.h"
15 #include "core/fpdfapi/page/cpdf_pageobject.h"
16 #include "core/fpdfapi/parser/cpdf_dictionary.h"
17 #include "core/fpdfapi/parser/cpdf_document.h"
18 #include "core/fxcrt/check.h"
19 #include "core/fxcrt/check_op.h"
20 #include "core/fxcrt/fx_extension.h"
21 #include "core/fxcrt/stl_util.h"
22 
operator <(const GraphicsData & other) const23 bool GraphicsData::operator<(const GraphicsData& other) const {
24   if (!FXSYS_SafeEQ(fillAlpha, other.fillAlpha))
25     return FXSYS_SafeLT(fillAlpha, other.fillAlpha);
26   if (!FXSYS_SafeEQ(strokeAlpha, other.strokeAlpha))
27     return FXSYS_SafeLT(strokeAlpha, other.strokeAlpha);
28   return blendType < other.blendType;
29 }
30 
operator <(const FontData & other) const31 bool FontData::operator<(const FontData& other) const {
32   if (baseFont != other.baseFont)
33     return baseFont < other.baseFont;
34   return type < other.type;
35 }
36 
CPDF_PageObjectHolder(CPDF_Document * pDoc,RetainPtr<CPDF_Dictionary> pDict,RetainPtr<CPDF_Dictionary> pPageResources,RetainPtr<CPDF_Dictionary> pResources)37 CPDF_PageObjectHolder::CPDF_PageObjectHolder(
38     CPDF_Document* pDoc,
39     RetainPtr<CPDF_Dictionary> pDict,
40     RetainPtr<CPDF_Dictionary> pPageResources,
41     RetainPtr<CPDF_Dictionary> pResources)
42     : m_pPageResources(std::move(pPageResources)),
43       m_pResources(std::move(pResources)),
44       m_pDict(std::move(pDict)),
45       m_pDocument(pDoc) {
46   DCHECK(m_pDict);
47 }
48 
49 CPDF_PageObjectHolder::~CPDF_PageObjectHolder() = default;
50 
IsPage() const51 bool CPDF_PageObjectHolder::IsPage() const {
52   return false;
53 }
54 
StartParse(std::unique_ptr<CPDF_ContentParser> pParser)55 void CPDF_PageObjectHolder::StartParse(
56     std::unique_ptr<CPDF_ContentParser> pParser) {
57   DCHECK_EQ(m_ParseState, ParseState::kNotParsed);
58   m_pParser = std::move(pParser);
59   m_ParseState = ParseState::kParsing;
60 }
61 
ContinueParse(PauseIndicatorIface * pPause)62 void CPDF_PageObjectHolder::ContinueParse(PauseIndicatorIface* pPause) {
63   if (m_ParseState == ParseState::kParsed)
64     return;
65 
66   DCHECK_EQ(m_ParseState, ParseState::kParsing);
67   if (m_pParser->Continue(pPause))
68     return;
69 
70   m_ParseState = ParseState::kParsed;
71   m_pDocument->IncrementParsedPageCount();
72   m_AllCTMs = m_pParser->TakeAllCTMs();
73 
74   m_pParser.reset();
75 }
76 
AddImageMaskBoundingBox(const CFX_FloatRect & box)77 void CPDF_PageObjectHolder::AddImageMaskBoundingBox(const CFX_FloatRect& box) {
78   m_MaskBoundingBoxes.push_back(box);
79 }
80 
TakeDirtyStreams()81 std::set<int32_t> CPDF_PageObjectHolder::TakeDirtyStreams() {
82   auto dirty_streams = std::move(m_DirtyStreams);
83   m_DirtyStreams.clear();
84   return dirty_streams;
85 }
86 
GraphicsMapSearch(const GraphicsData & gd)87 std::optional<ByteString> CPDF_PageObjectHolder::GraphicsMapSearch(
88     const GraphicsData& gd) {
89   auto it = m_GraphicsMap.find(gd);
90   if (it == m_GraphicsMap.end())
91     return std::nullopt;
92 
93   return it->second;
94 }
95 
GraphicsMapInsert(const GraphicsData & gd,const ByteString & str)96 void CPDF_PageObjectHolder::GraphicsMapInsert(const GraphicsData& gd,
97                                               const ByteString& str) {
98   m_GraphicsMap[gd] = str;
99 }
100 
FontsMapSearch(const FontData & fd)101 std::optional<ByteString> CPDF_PageObjectHolder::FontsMapSearch(
102     const FontData& fd) {
103   auto it = m_FontsMap.find(fd);
104   if (it == m_FontsMap.end())
105     return std::nullopt;
106 
107   return it->second;
108 }
109 
FontsMapInsert(const FontData & fd,const ByteString & str)110 void CPDF_PageObjectHolder::FontsMapInsert(const FontData& fd,
111                                            const ByteString& str) {
112   m_FontsMap[fd] = str;
113 }
114 
GetCTMAtBeginningOfStream(int32_t stream)115 CFX_Matrix CPDF_PageObjectHolder::GetCTMAtBeginningOfStream(int32_t stream) {
116   CHECK(stream >= 0 || stream == CPDF_PageObject::kNoContentStream);
117 
118   if (stream == 0 || m_AllCTMs.empty()) {
119     return CFX_Matrix();
120   }
121 
122   if (stream == CPDF_PageObject::kNoContentStream) {
123     return m_AllCTMs.rbegin()->second;
124   }
125 
126   // For all other cases, CTM at beginning of `stream` is the same value as CTM
127   // at the end of the previous stream.
128   return GetCTMAtEndOfStream(stream - 1);
129 }
130 
GetCTMAtEndOfStream(int32_t stream)131 CFX_Matrix CPDF_PageObjectHolder::GetCTMAtEndOfStream(int32_t stream) {
132   // This code should never need to calculate the CTM for the end of
133   // `CPDF_PageObject::kNoContentStream`, which uses a negative sentinel value.
134   // All other streams have a non-negative index.
135   CHECK_GE(stream, 0);
136 
137   if (m_AllCTMs.empty()) {
138     return CFX_Matrix();
139   }
140 
141   const auto it = m_AllCTMs.lower_bound(stream);
142   return it != m_AllCTMs.end() ? it->second : m_AllCTMs.rbegin()->second;
143 }
144 
LoadTransparencyInfo()145 void CPDF_PageObjectHolder::LoadTransparencyInfo() {
146   RetainPtr<const CPDF_Dictionary> pGroup = m_pDict->GetDictFor("Group");
147   if (!pGroup)
148     return;
149 
150   if (pGroup->GetByteStringFor(pdfium::transparency::kGroupSubType) !=
151       pdfium::transparency::kTransparency) {
152     return;
153   }
154   m_Transparency.SetGroup();
155   if (pGroup->GetIntegerFor(pdfium::transparency::kI))
156     m_Transparency.SetIsolated();
157 }
158 
GetActivePageObjectCount() const159 size_t CPDF_PageObjectHolder::GetActivePageObjectCount() const {
160   size_t count = 0;
161   for (const auto& page_object : m_PageObjectList) {
162     if (page_object->IsActive()) {
163       ++count;
164     }
165   }
166   return count;
167 }
168 
GetPageObjectByIndex(size_t index) const169 CPDF_PageObject* CPDF_PageObjectHolder::GetPageObjectByIndex(
170     size_t index) const {
171   return fxcrt::IndexInBounds(m_PageObjectList, index)
172              ? m_PageObjectList[index].get()
173              : nullptr;
174 }
175 
AppendPageObject(std::unique_ptr<CPDF_PageObject> pPageObj)176 void CPDF_PageObjectHolder::AppendPageObject(
177     std::unique_ptr<CPDF_PageObject> pPageObj) {
178   CHECK(pPageObj);
179   m_PageObjectList.push_back(std::move(pPageObj));
180 }
181 
RemovePageObject(CPDF_PageObject * pPageObj)182 std::unique_ptr<CPDF_PageObject> CPDF_PageObjectHolder::RemovePageObject(
183     CPDF_PageObject* pPageObj) {
184   auto it = std::find(std::begin(m_PageObjectList), std::end(m_PageObjectList),
185                       fxcrt::MakeFakeUniquePtr(pPageObj));
186   if (it == std::end(m_PageObjectList))
187     return nullptr;
188 
189   std::unique_ptr<CPDF_PageObject> result = std::move(*it);
190   m_PageObjectList.erase(it);
191 
192   int32_t content_stream = pPageObj->GetContentStream();
193   if (content_stream >= 0)
194     m_DirtyStreams.insert(content_stream);
195 
196   return result;
197 }
198 
ErasePageObjectAtIndex(size_t index)199 bool CPDF_PageObjectHolder::ErasePageObjectAtIndex(size_t index) {
200   if (index >= m_PageObjectList.size())
201     return false;
202 
203   m_PageObjectList.erase(m_PageObjectList.begin() + index);
204   return true;
205 }
206