Home | History | Annotate | Download | only in fpdfdoc
      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/fpdfdoc/cpdf_annotlist.h"
      8 
      9 #include <memory>
     10 #include <utility>
     11 
     12 #include "core/fpdfapi/page/cpdf_page.h"
     13 #include "core/fpdfapi/parser/cpdf_document.h"
     14 #include "core/fpdfapi/parser/cpdf_name.h"
     15 #include "core/fpdfapi/parser/cpdf_number.h"
     16 #include "core/fpdfapi/parser/cpdf_reference.h"
     17 #include "core/fpdfapi/parser/cpdf_string.h"
     18 #include "core/fpdfapi/render/cpdf_renderoptions.h"
     19 #include "core/fpdfdoc/cpdf_annot.h"
     20 #include "core/fpdfdoc/cpdf_interform.h"
     21 #include "core/fpdfdoc/cpdf_occontext.h"
     22 #include "core/fpdfdoc/cpvt_generateap.h"
     23 #include "core/fxge/cfx_renderdevice.h"
     24 #include "third_party/base/ptr_util.h"
     25 
     26 namespace {
     27 
     28 std::unique_ptr<CPDF_Annot> CreatePopupAnnot(CPDF_Annot* pAnnot,
     29                                              CPDF_Document* pDocument) {
     30   CPDF_Dictionary* pParentDict = pAnnot->GetAnnotDict();
     31   if (!pParentDict)
     32     return nullptr;
     33 
     34   // TODO(jaepark): We shouldn't strip BOM for some strings and not for others.
     35   // See pdfium:593.
     36   CFX_WideString sContents = pParentDict->GetUnicodeTextFor("Contents");
     37   if (sContents.IsEmpty())
     38     return nullptr;
     39 
     40   auto pAnnotDict =
     41       pdfium::MakeUnique<CPDF_Dictionary>(pDocument->GetByteStringPool());
     42   pAnnotDict->SetNewFor<CPDF_Name>("Type", "Annot");
     43   pAnnotDict->SetNewFor<CPDF_Name>("Subtype", "Popup");
     44   pAnnotDict->SetNewFor<CPDF_String>("T", pParentDict->GetStringFor("T"),
     45                                      false);
     46   pAnnotDict->SetNewFor<CPDF_String>("Contents", sContents.UTF8Encode(), false);
     47 
     48   CFX_FloatRect rect = pParentDict->GetRectFor("Rect");
     49   rect.Normalize();
     50   CFX_FloatRect popupRect(0, 0, 200, 200);
     51   popupRect.Translate(rect.left, rect.bottom - popupRect.Height());
     52 
     53   pAnnotDict->SetRectFor("Rect", popupRect);
     54   pAnnotDict->SetNewFor<CPDF_Number>("F", 0);
     55 
     56   auto pPopupAnnot =
     57       pdfium::MakeUnique<CPDF_Annot>(std::move(pAnnotDict), pDocument);
     58   pAnnot->SetPopupAnnot(pPopupAnnot.get());
     59   return pPopupAnnot;
     60 }
     61 
     62 }  // namespace
     63 
     64 CPDF_AnnotList::CPDF_AnnotList(CPDF_Page* pPage)
     65     : m_pDocument(pPage->m_pDocument) {
     66   if (!pPage->m_pFormDict)
     67     return;
     68 
     69   CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayFor("Annots");
     70   if (!pAnnots)
     71     return;
     72 
     73   CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
     74   CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
     75   bool bRegenerateAP = pAcroForm && pAcroForm->GetBooleanFor("NeedAppearances");
     76   for (size_t i = 0; i < pAnnots->GetCount(); ++i) {
     77     CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(i));
     78     if (!pDict)
     79       continue;
     80     const CFX_ByteString subtype = pDict->GetStringFor("Subtype");
     81     if (subtype == "Popup") {
     82       // Skip creating Popup annotations in the PDF document since PDFium
     83       // provides its own Popup annotations.
     84       continue;
     85     }
     86     pAnnots->ConvertToIndirectObjectAt(i, m_pDocument);
     87     m_AnnotList.push_back(pdfium::MakeUnique<CPDF_Annot>(pDict, m_pDocument));
     88     if (bRegenerateAP && subtype == "Widget" &&
     89         CPDF_InterForm::IsUpdateAPEnabled()) {
     90       FPDF_GenerateAP(m_pDocument, pDict);
     91     }
     92   }
     93 
     94   size_t nAnnotListSize = m_AnnotList.size();
     95   for (size_t i = 0; i < nAnnotListSize; ++i) {
     96     std::unique_ptr<CPDF_Annot> pPopupAnnot(
     97         CreatePopupAnnot(m_AnnotList[i].get(), m_pDocument));
     98     if (pPopupAnnot)
     99       m_AnnotList.push_back(std::move(pPopupAnnot));
    100   }
    101 }
    102 
    103 CPDF_AnnotList::~CPDF_AnnotList() {}
    104 
    105 void CPDF_AnnotList::DisplayPass(CPDF_Page* pPage,
    106                                  CFX_RenderDevice* pDevice,
    107                                  CPDF_RenderContext* pContext,
    108                                  bool bPrinting,
    109                                  const CFX_Matrix* pMatrix,
    110                                  bool bWidgetPass,
    111                                  CPDF_RenderOptions* pOptions,
    112                                  FX_RECT* clip_rect) {
    113   for (const auto& pAnnot : m_AnnotList) {
    114     bool bWidget = pAnnot->GetSubtype() == CPDF_Annot::Subtype::WIDGET;
    115     if ((bWidgetPass && !bWidget) || (!bWidgetPass && bWidget))
    116       continue;
    117 
    118     uint32_t annot_flags = pAnnot->GetFlags();
    119     if (annot_flags & ANNOTFLAG_HIDDEN)
    120       continue;
    121 
    122     if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0)
    123       continue;
    124 
    125     if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW))
    126       continue;
    127 
    128     if (pOptions) {
    129       CFX_RetainPtr<CPDF_OCContext> pOCContext = pOptions->m_pOCContext;
    130       CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict();
    131       if (pOCContext && pAnnotDict &&
    132           !pOCContext->CheckOCGVisible(pAnnotDict->GetDictFor("OC"))) {
    133         continue;
    134       }
    135     }
    136     CFX_FloatRect annot_rect_f = pAnnot->GetRect();
    137     CFX_Matrix matrix = *pMatrix;
    138     if (clip_rect) {
    139       matrix.TransformRect(annot_rect_f);
    140 
    141       FX_RECT annot_rect = annot_rect_f.GetOuterRect();
    142       annot_rect.Intersect(*clip_rect);
    143       if (annot_rect.IsEmpty())
    144         continue;
    145     }
    146     if (pContext) {
    147       pAnnot->DrawInContext(pPage, pContext, &matrix, CPDF_Annot::Normal);
    148     } else if (!pAnnot->DrawAppearance(pPage, pDevice, &matrix,
    149                                        CPDF_Annot::Normal, pOptions)) {
    150       pAnnot->DrawBorder(pDevice, &matrix, pOptions);
    151     }
    152   }
    153 }
    154 
    155 void CPDF_AnnotList::DisplayAnnots(CPDF_Page* pPage,
    156                                    CFX_RenderDevice* pDevice,
    157                                    CPDF_RenderContext* pContext,
    158                                    bool bPrinting,
    159                                    const CFX_Matrix* pUser2Device,
    160                                    uint32_t dwAnnotFlags,
    161                                    CPDF_RenderOptions* pOptions,
    162                                    FX_RECT* pClipRect) {
    163   if (dwAnnotFlags & ANNOTFLAG_INVISIBLE) {
    164     DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, false,
    165                 pOptions, pClipRect);
    166   }
    167   if (dwAnnotFlags & ANNOTFLAG_HIDDEN) {
    168     DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, true,
    169                 pOptions, pClipRect);
    170   }
    171 }
    172 
    173 void CPDF_AnnotList::DisplayAnnots(CPDF_Page* pPage,
    174                                    CPDF_RenderContext* pContext,
    175                                    bool bPrinting,
    176                                    const CFX_Matrix* pMatrix,
    177                                    bool bShowWidget,
    178                                    CPDF_RenderOptions* pOptions) {
    179   uint32_t dwAnnotFlags = bShowWidget ? ANNOTFLAG_INVISIBLE | ANNOTFLAG_HIDDEN
    180                                       : ANNOTFLAG_INVISIBLE;
    181   DisplayAnnots(pPage, nullptr, pContext, bPrinting, pMatrix, dwAnnotFlags,
    182                 pOptions, nullptr);
    183 }
    184