1 // Copyright 2016 PDFium Authors. All rights reserved. 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_clippath.h" 8 9 #include <utility> 10 11 #include "core/fpdfapi/page/cpdf_path.h" 12 #include "core/fpdfapi/page/cpdf_textobject.h" 13 14 #define FPDF_CLIPPATH_MAX_TEXTS 1024 15 CPDF_ClipPath()16CPDF_ClipPath::CPDF_ClipPath() {} 17 CPDF_ClipPath(const CPDF_ClipPath & that)18CPDF_ClipPath::CPDF_ClipPath(const CPDF_ClipPath& that) : m_Ref(that.m_Ref) {} 19 ~CPDF_ClipPath()20CPDF_ClipPath::~CPDF_ClipPath() {} 21 GetPathCount() const22size_t CPDF_ClipPath::GetPathCount() const { 23 return m_Ref.GetObject()->m_PathAndTypeList.size(); 24 } 25 GetPath(size_t i) const26CPDF_Path CPDF_ClipPath::GetPath(size_t i) const { 27 return m_Ref.GetObject()->m_PathAndTypeList[i].first; 28 } 29 GetClipType(size_t i) const30uint8_t CPDF_ClipPath::GetClipType(size_t i) const { 31 return m_Ref.GetObject()->m_PathAndTypeList[i].second; 32 } 33 GetTextCount() const34size_t CPDF_ClipPath::GetTextCount() const { 35 return m_Ref.GetObject()->m_TextList.size(); 36 } 37 GetText(size_t i) const38CPDF_TextObject* CPDF_ClipPath::GetText(size_t i) const { 39 return m_Ref.GetObject()->m_TextList[i].get(); 40 } 41 GetClipBox() const42CFX_FloatRect CPDF_ClipPath::GetClipBox() const { 43 CFX_FloatRect rect; 44 bool bStarted = false; 45 if (GetPathCount() > 0) { 46 rect = GetPath(0).GetBoundingBox(); 47 for (size_t i = 1; i < GetPathCount(); ++i) { 48 CFX_FloatRect path_rect = GetPath(i).GetBoundingBox(); 49 rect.Intersect(path_rect); 50 } 51 bStarted = true; 52 } 53 54 CFX_FloatRect layer_rect; 55 bool bLayerStarted = false; 56 for (size_t i = 0; i < GetTextCount(); ++i) { 57 CPDF_TextObject* pTextObj = GetText(i); 58 if (!pTextObj) { 59 if (!bStarted) { 60 rect = layer_rect; 61 bStarted = true; 62 } else { 63 rect.Intersect(layer_rect); 64 } 65 bLayerStarted = false; 66 } else { 67 if (!bLayerStarted) { 68 layer_rect = CFX_FloatRect(pTextObj->GetBBox(nullptr)); 69 bLayerStarted = true; 70 } else { 71 layer_rect.Union(CFX_FloatRect(pTextObj->GetBBox(nullptr))); 72 } 73 } 74 } 75 return rect; 76 } 77 AppendPath(CPDF_Path path,uint8_t type,bool bAutoMerge)78void CPDF_ClipPath::AppendPath(CPDF_Path path, uint8_t type, bool bAutoMerge) { 79 PathData* pData = m_Ref.GetPrivateCopy(); 80 if (!pData->m_PathAndTypeList.empty() && bAutoMerge) { 81 const CPDF_Path& old_path = pData->m_PathAndTypeList.back().first; 82 if (old_path.IsRect()) { 83 CFX_PointF point0 = old_path.GetPoint(0); 84 CFX_PointF point2 = old_path.GetPoint(2); 85 CFX_FloatRect old_rect(point0.x, point0.y, point2.x, point2.y); 86 CFX_FloatRect new_rect = path.GetBoundingBox(); 87 if (old_rect.Contains(new_rect)) 88 pData->m_PathAndTypeList.pop_back(); 89 } 90 } 91 pData->m_PathAndTypeList.push_back(std::make_pair(path, type)); 92 } 93 AppendTexts(std::vector<std::unique_ptr<CPDF_TextObject>> * pTexts)94void CPDF_ClipPath::AppendTexts( 95 std::vector<std::unique_ptr<CPDF_TextObject>>* pTexts) { 96 PathData* pData = m_Ref.GetPrivateCopy(); 97 if (pData->m_TextList.size() + pTexts->size() <= FPDF_CLIPPATH_MAX_TEXTS) { 98 for (size_t i = 0; i < pTexts->size(); i++) 99 pData->m_TextList.push_back(std::move((*pTexts)[i])); 100 pData->m_TextList.push_back(nullptr); 101 } 102 pTexts->clear(); 103 } 104 Transform(const CFX_Matrix & matrix)105void CPDF_ClipPath::Transform(const CFX_Matrix& matrix) { 106 PathData* pData = m_Ref.GetPrivateCopy(); 107 for (auto& obj : pData->m_PathAndTypeList) 108 obj.first.Transform(&matrix); 109 for (auto& text : pData->m_TextList) { 110 if (text) 111 text->Transform(matrix); 112 } 113 } 114 PathData()115CPDF_ClipPath::PathData::PathData() {} 116 PathData(const PathData & that)117CPDF_ClipPath::PathData::PathData(const PathData& that) { 118 m_PathAndTypeList = that.m_PathAndTypeList; 119 120 m_TextList.resize(that.m_TextList.size()); 121 for (size_t i = 0; i < that.m_TextList.size(); ++i) { 122 if (that.m_TextList[i]) 123 m_TextList[i] = that.m_TextList[i]->Clone(); 124 } 125 } 126 ~PathData()127CPDF_ClipPath::PathData::~PathData() {} 128