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