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