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 
     14 #define FPDF_CLIPPATH_MAX_TEXTS 1024
     15 
     16 CPDF_ClipPath::CPDF_ClipPath() {}
     17 
     18 CPDF_ClipPath::CPDF_ClipPath(const CPDF_ClipPath& that) : m_Ref(that.m_Ref) {}
     19 
     20 CPDF_ClipPath::~CPDF_ClipPath() {}
     21 
     22 size_t CPDF_ClipPath::GetPathCount() const {
     23   return m_Ref.GetObject()->m_PathAndTypeList.size();
     24 }
     25 
     26 CPDF_Path CPDF_ClipPath::GetPath(size_t i) const {
     27   return m_Ref.GetObject()->m_PathAndTypeList[i].first;
     28 }
     29 
     30 uint8_t CPDF_ClipPath::GetClipType(size_t i) const {
     31   return m_Ref.GetObject()->m_PathAndTypeList[i].second;
     32 }
     33 
     34 size_t CPDF_ClipPath::GetTextCount() const {
     35   return m_Ref.GetObject()->m_TextList.size();
     36 }
     37 
     38 CPDF_TextObject* CPDF_ClipPath::GetText(size_t i) const {
     39   return m_Ref.GetObject()->m_TextList[i].get();
     40 }
     41 
     42 CFX_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 
     78 void 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 
     94 void 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 
    105 void 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 
    115 CPDF_ClipPath::PathData::PathData() {}
    116 
    117 CPDF_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 
    127 CPDF_ClipPath::PathData::~PathData() {}
    128