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 #ifndef CORE_FPDFAPI_PAGE_CPDF_PAGEOBJECTHOLDER_H_ 8 #define CORE_FPDFAPI_PAGE_CPDF_PAGEOBJECTHOLDER_H_ 9 10 #include <stddef.h> 11 #include <stdint.h> 12 13 #include <deque> 14 #include <map> 15 #include <memory> 16 #include <optional> 17 #include <set> 18 #include <utility> 19 #include <vector> 20 21 #include "core/fpdfapi/page/cpdf_transparency.h" 22 #include "core/fpdfapi/parser/cpdf_dictionary.h" 23 #include "core/fxcrt/bytestring.h" 24 #include "core/fxcrt/fx_coordinates.h" 25 #include "core/fxcrt/retain_ptr.h" 26 #include "core/fxcrt/unowned_ptr.h" 27 #include "core/fxge/dib/fx_dib.h" 28 29 class CPDF_ContentParser; 30 class CPDF_Document; 31 class CPDF_PageObject; 32 class PauseIndicatorIface; 33 34 // These structs are used to keep track of resources that have already been 35 // generated in the page object holder. 36 struct GraphicsData { 37 float fillAlpha; 38 float strokeAlpha; 39 BlendMode blendType; 40 41 bool operator<(const GraphicsData& other) const; 42 }; 43 44 struct FontData { 45 ByteString baseFont; 46 ByteString type; 47 48 bool operator<(const FontData& other) const; 49 }; 50 51 class CPDF_PageObjectHolder { 52 public: 53 enum class ParseState : uint8_t { kNotParsed, kParsing, kParsed }; 54 55 // Key: The stream index. 56 // Value: The current transformation matrix at the end of the stream. 57 using CTMMap = std::map<int32_t, CFX_Matrix>; 58 59 using iterator = std::deque<std::unique_ptr<CPDF_PageObject>>::iterator; 60 using const_iterator = 61 std::deque<std::unique_ptr<CPDF_PageObject>>::const_iterator; 62 63 CPDF_PageObjectHolder(CPDF_Document* pDoc, 64 RetainPtr<CPDF_Dictionary> pDict, 65 RetainPtr<CPDF_Dictionary> pPageResources, 66 RetainPtr<CPDF_Dictionary> pResources); 67 virtual ~CPDF_PageObjectHolder(); 68 69 virtual bool IsPage() const; 70 71 void StartParse(std::unique_ptr<CPDF_ContentParser> pParser); 72 void ContinueParse(PauseIndicatorIface* pPause); GetParseState()73 ParseState GetParseState() const { return m_ParseState; } 74 GetDocument()75 CPDF_Document* GetDocument() const { return m_pDocument; } GetDict()76 RetainPtr<const CPDF_Dictionary> GetDict() const { return m_pDict; } GetMutableDict()77 RetainPtr<CPDF_Dictionary> GetMutableDict() { return m_pDict; } GetResources()78 RetainPtr<const CPDF_Dictionary> GetResources() const { return m_pResources; } GetMutableResources()79 RetainPtr<CPDF_Dictionary> GetMutableResources() { return m_pResources; } SetResources(RetainPtr<CPDF_Dictionary> pDict)80 void SetResources(RetainPtr<CPDF_Dictionary> pDict) { 81 m_pResources = std::move(pDict); 82 } GetPageResources()83 RetainPtr<const CPDF_Dictionary> GetPageResources() const { 84 return m_pPageResources; 85 } GetMutablePageResources()86 RetainPtr<CPDF_Dictionary> GetMutablePageResources() { 87 return m_pPageResources; 88 } GetPageObjectCount()89 size_t GetPageObjectCount() const { return m_PageObjectList.size(); } 90 size_t GetActivePageObjectCount() const; 91 CPDF_PageObject* GetPageObjectByIndex(size_t index) const; 92 void AppendPageObject(std::unique_ptr<CPDF_PageObject> pPageObj); 93 94 // Remove `pPageObj` if present, and transfer ownership to the caller. 95 std::unique_ptr<CPDF_PageObject> RemovePageObject(CPDF_PageObject* pPageObj); 96 bool ErasePageObjectAtIndex(size_t index); 97 begin()98 iterator begin() { return m_PageObjectList.begin(); } begin()99 const_iterator begin() const { return m_PageObjectList.begin(); } 100 end()101 iterator end() { return m_PageObjectList.end(); } end()102 const_iterator end() const { return m_PageObjectList.end(); } 103 GetBBox()104 const CFX_FloatRect& GetBBox() const { return m_BBox; } 105 GetTransparency()106 const CPDF_Transparency& GetTransparency() const { return m_Transparency; } BackgroundAlphaNeeded()107 bool BackgroundAlphaNeeded() const { return m_bBackgroundAlphaNeeded; } SetBackgroundAlphaNeeded(bool needed)108 void SetBackgroundAlphaNeeded(bool needed) { 109 m_bBackgroundAlphaNeeded = needed; 110 } 111 HasImageMask()112 bool HasImageMask() const { return !m_MaskBoundingBoxes.empty(); } GetMaskBoundingBoxes()113 const std::vector<CFX_FloatRect>& GetMaskBoundingBoxes() const { 114 return m_MaskBoundingBoxes; 115 } 116 void AddImageMaskBoundingBox(const CFX_FloatRect& box); HasDirtyStreams()117 bool HasDirtyStreams() const { return !m_DirtyStreams.empty(); } 118 std::set<int32_t> TakeDirtyStreams(); 119 120 std::optional<ByteString> GraphicsMapSearch(const GraphicsData& gd); 121 void GraphicsMapInsert(const GraphicsData& gd, const ByteString& str); 122 123 std::optional<ByteString> FontsMapSearch(const FontData& fd); 124 void FontsMapInsert(const FontData& fd, const ByteString& str); 125 126 // `stream` must be non-negative or `CPDF_PageObject::kNoContentStream`. 127 CFX_Matrix GetCTMAtBeginningOfStream(int32_t stream); 128 129 // `stream` must be non-negative. 130 CFX_Matrix GetCTMAtEndOfStream(int32_t stream); 131 132 protected: 133 void LoadTransparencyInfo(); 134 135 RetainPtr<CPDF_Dictionary> m_pPageResources; 136 RetainPtr<CPDF_Dictionary> m_pResources; 137 std::map<GraphicsData, ByteString> m_GraphicsMap; 138 std::map<FontData, ByteString> m_FontsMap; 139 CFX_FloatRect m_BBox; 140 CPDF_Transparency m_Transparency; 141 142 private: 143 bool m_bBackgroundAlphaNeeded = false; 144 ParseState m_ParseState = ParseState::kNotParsed; 145 RetainPtr<CPDF_Dictionary> const m_pDict; 146 UnownedPtr<CPDF_Document> m_pDocument; 147 std::vector<CFX_FloatRect> m_MaskBoundingBoxes; 148 std::unique_ptr<CPDF_ContentParser> m_pParser; 149 std::deque<std::unique_ptr<CPDF_PageObject>> m_PageObjectList; 150 151 CTMMap m_AllCTMs; 152 153 // The indexes of Content streams that are dirty and need to be regenerated. 154 std::set<int32_t> m_DirtyStreams; 155 }; 156 157 #endif // CORE_FPDFAPI_PAGE_CPDF_PAGEOBJECTHOLDER_H_ 158