From 3b6c7e9669df2545fc3b19d9f03364c1040a5ab0 Mon Sep 17 00:00:00 2001 From: jaepark Date: Wed, 20 Jul 2016 14:18:04 -0700 Subject: Move CPDF_Annot and CPDF_AnnotList to their own header. Review-Url: https://codereview.chromium.org/2163133002 --- BUILD.gn | 5 +- core/fpdfdoc/cpdf_annot.cpp | 248 ++++++++++++++++++++++++++++ core/fpdfdoc/cpdf_annot.h | 70 ++++++++ core/fpdfdoc/cpdf_annotlist.cpp | 132 +++++++++++++++ core/fpdfdoc/cpdf_annotlist.h | 64 ++++++++ core/fpdfdoc/doc_annot.cpp | 355 ---------------------------------------- core/fpdfdoc/include/fpdf_doc.h | 91 +--------- pdfium.gyp | 5 +- 8 files changed, 524 insertions(+), 446 deletions(-) create mode 100644 core/fpdfdoc/cpdf_annot.cpp create mode 100644 core/fpdfdoc/cpdf_annot.h create mode 100644 core/fpdfdoc/cpdf_annotlist.cpp create mode 100644 core/fpdfdoc/cpdf_annotlist.h delete mode 100644 core/fpdfdoc/doc_annot.cpp diff --git a/BUILD.gn b/BUILD.gn index 9c9d865c5d..5426860f90 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -197,6 +197,10 @@ static_library("fpdfdoc") { sources = [ "core/fpdfdoc/clines.cpp", "core/fpdfdoc/clines.h", + "core/fpdfdoc/cpdf_annot.cpp", + "core/fpdfdoc/cpdf_annot.h", + "core/fpdfdoc/cpdf_annotlist.cpp", + "core/fpdfdoc/cpdf_annotlist.h", "core/fpdfdoc/cpdf_variabletext.cpp", "core/fpdfdoc/cpvt_color.cpp", "core/fpdfdoc/cpvt_color.h", @@ -216,7 +220,6 @@ static_library("fpdfdoc") { "core/fpdfdoc/ctypeset.cpp", "core/fpdfdoc/ctypeset.h", "core/fpdfdoc/doc_action.cpp", - "core/fpdfdoc/doc_annot.cpp", "core/fpdfdoc/doc_basic.cpp", "core/fpdfdoc/doc_bookmark.cpp", "core/fpdfdoc/doc_form.cpp", diff --git a/core/fpdfdoc/cpdf_annot.cpp b/core/fpdfdoc/cpdf_annot.cpp new file mode 100644 index 0000000000..dcdd89c3f4 --- /dev/null +++ b/core/fpdfdoc/cpdf_annot.cpp @@ -0,0 +1,248 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfdoc/cpdf_annot.h" + +#include "core/fpdfapi/fpdf_page/include/cpdf_form.h" +#include "core/fpdfapi/fpdf_page/include/cpdf_page.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" +#include "core/fpdfapi/fpdf_render/include/cpdf_rendercontext.h" +#include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h" +#include "core/fxge/include/fx_ge.h" + +CPDF_Annot::CPDF_Annot(CPDF_Dictionary* pDict, CPDF_Document* pDocument) + : m_pAnnotDict(pDict), + m_pDocument(pDocument), + m_sSubtype(m_pAnnotDict->GetStringBy("Subtype")) {} + +CPDF_Annot::~CPDF_Annot() { + ClearCachedAP(); +} + +void CPDF_Annot::ClearCachedAP() { + for (const auto& pair : m_APMap) { + delete pair.second; + } + m_APMap.clear(); +} +CFX_ByteString CPDF_Annot::GetSubType() const { + return m_sSubtype; +} + +void CPDF_Annot::GetRect(CFX_FloatRect& rect) const { + if (!m_pAnnotDict) { + return; + } + rect = m_pAnnotDict->GetRectBy("Rect"); + rect.Normalize(); +} + +uint32_t CPDF_Annot::GetFlags() const { + return m_pAnnotDict->GetIntegerBy("F"); +} + +CPDF_Stream* FPDFDOC_GetAnnotAP(CPDF_Dictionary* pAnnotDict, + CPDF_Annot::AppearanceMode mode) { + CPDF_Dictionary* pAP = pAnnotDict->GetDictBy("AP"); + if (!pAP) { + return nullptr; + } + const FX_CHAR* ap_entry = "N"; + if (mode == CPDF_Annot::Down) + ap_entry = "D"; + else if (mode == CPDF_Annot::Rollover) + ap_entry = "R"; + if (!pAP->KeyExist(ap_entry)) + ap_entry = "N"; + + CPDF_Object* psub = pAP->GetDirectObjectBy(ap_entry); + if (!psub) + return nullptr; + if (CPDF_Stream* pStream = psub->AsStream()) + return pStream; + + if (CPDF_Dictionary* pDict = psub->AsDictionary()) { + CFX_ByteString as = pAnnotDict->GetStringBy("AS"); + if (as.IsEmpty()) { + CFX_ByteString value = pAnnotDict->GetStringBy("V"); + if (value.IsEmpty()) { + CPDF_Dictionary* pParentDict = pAnnotDict->GetDictBy("Parent"); + value = pParentDict ? pParentDict->GetStringBy("V") : CFX_ByteString(); + } + if (value.IsEmpty() || !pDict->KeyExist(value)) + as = "Off"; + else + as = value; + } + return pDict->GetStreamBy(as); + } + return nullptr; +} + +CPDF_Form* CPDF_Annot::GetAPForm(const CPDF_Page* pPage, AppearanceMode mode) { + CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pAnnotDict, mode); + if (!pStream) + return nullptr; + + auto it = m_APMap.find(pStream); + if (it != m_APMap.end()) + return it->second; + + CPDF_Form* pNewForm = + new CPDF_Form(m_pDocument, pPage->m_pResources, pStream); + pNewForm->ParseContent(nullptr, nullptr, nullptr); + m_APMap[pStream] = pNewForm; + return pNewForm; +} + +static CPDF_Form* FPDFDOC_Annot_GetMatrix(const CPDF_Page* pPage, + CPDF_Annot* pAnnot, + CPDF_Annot::AppearanceMode mode, + const CFX_Matrix* pUser2Device, + CFX_Matrix& matrix) { + CPDF_Form* pForm = pAnnot->GetAPForm(pPage, mode); + if (!pForm) { + return nullptr; + } + CFX_FloatRect form_bbox = pForm->m_pFormDict->GetRectBy("BBox"); + CFX_Matrix form_matrix = pForm->m_pFormDict->GetMatrixBy("Matrix"); + form_matrix.TransformRect(form_bbox); + CFX_FloatRect arect; + pAnnot->GetRect(arect); + matrix.MatchRect(arect, form_bbox); + matrix.Concat(*pUser2Device); + return pForm; +} +FX_BOOL CPDF_Annot::DrawAppearance(CPDF_Page* pPage, + CFX_RenderDevice* pDevice, + const CFX_Matrix* pUser2Device, + AppearanceMode mode, + const CPDF_RenderOptions* pOptions) { + CFX_Matrix matrix; + CPDF_Form* pForm = + FPDFDOC_Annot_GetMatrix(pPage, this, mode, pUser2Device, matrix); + if (!pForm) { + return FALSE; + } + CPDF_RenderContext context(pPage); + context.AppendLayer(pForm, &matrix); + context.Render(pDevice, pOptions, nullptr); + return TRUE; +} +FX_BOOL CPDF_Annot::DrawInContext(const CPDF_Page* pPage, + CPDF_RenderContext* pContext, + const CFX_Matrix* pUser2Device, + AppearanceMode mode) { + CFX_Matrix matrix; + CPDF_Form* pForm = + FPDFDOC_Annot_GetMatrix(pPage, this, mode, pUser2Device, matrix); + if (!pForm) { + return FALSE; + } + pContext->AppendLayer(pForm, &matrix); + return TRUE; +} +void CPDF_Annot::DrawBorder(CFX_RenderDevice* pDevice, + const CFX_Matrix* pUser2Device, + const CPDF_RenderOptions* pOptions) { + if (GetSubType() == "Popup") { + return; + } + uint32_t annot_flags = GetFlags(); + if (annot_flags & ANNOTFLAG_HIDDEN) { + return; + } + bool bPrinting = pDevice->GetDeviceClass() == FXDC_PRINTER || + (pOptions && (pOptions->m_Flags & RENDER_PRINTPREVIEW)); + if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) { + return; + } + if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW)) { + return; + } + CPDF_Dictionary* pBS = m_pAnnotDict->GetDictBy("BS"); + char style_char; + FX_FLOAT width; + CPDF_Array* pDashArray = nullptr; + if (!pBS) { + CPDF_Array* pBorderArray = m_pAnnotDict->GetArrayBy("Border"); + style_char = 'S'; + if (pBorderArray) { + width = pBorderArray->GetNumberAt(2); + if (pBorderArray->GetCount() == 4) { + pDashArray = pBorderArray->GetArrayAt(3); + if (!pDashArray) { + return; + } + size_t nLen = pDashArray->GetCount(); + size_t i = 0; + for (; i < nLen; ++i) { + CPDF_Object* pObj = pDashArray->GetDirectObjectAt(i); + if (pObj && pObj->GetInteger()) { + break; + } + } + if (i == nLen) { + return; + } + style_char = 'D'; + } + } else { + width = 1; + } + } else { + CFX_ByteString style = pBS->GetStringBy("S"); + pDashArray = pBS->GetArrayBy("D"); + style_char = style[1]; + width = pBS->GetNumberBy("W"); + } + if (width <= 0) { + return; + } + CPDF_Array* pColor = m_pAnnotDict->GetArrayBy("C"); + uint32_t argb = 0xff000000; + if (pColor) { + int R = (int32_t)(pColor->GetNumberAt(0) * 255); + int G = (int32_t)(pColor->GetNumberAt(1) * 255); + int B = (int32_t)(pColor->GetNumberAt(2) * 255); + argb = ArgbEncode(0xff, R, G, B); + } + CFX_GraphStateData graph_state; + graph_state.m_LineWidth = width; + if (style_char == 'D') { + if (pDashArray) { + size_t dash_count = pDashArray->GetCount(); + if (dash_count % 2) { + dash_count++; + } + graph_state.m_DashArray = FX_Alloc(FX_FLOAT, dash_count); + graph_state.m_DashCount = dash_count; + size_t i; + for (i = 0; i < pDashArray->GetCount(); ++i) { + graph_state.m_DashArray[i] = pDashArray->GetNumberAt(i); + } + if (i < dash_count) { + graph_state.m_DashArray[i] = graph_state.m_DashArray[i - 1]; + } + } else { + graph_state.m_DashArray = FX_Alloc(FX_FLOAT, 2); + graph_state.m_DashCount = 2; + graph_state.m_DashArray[0] = graph_state.m_DashArray[1] = 3 * 1.0f; + } + } + CFX_FloatRect rect; + GetRect(rect); + CFX_PathData path; + width /= 2; + path.AppendRect(rect.left + width, rect.bottom + width, rect.right - width, + rect.top - width); + int fill_type = 0; + if (pOptions && (pOptions->m_Flags & RENDER_NOPATHSMOOTH)) { + fill_type |= FXFILL_NOPATHSMOOTH; + } + pDevice->DrawPath(&path, pUser2Device, &graph_state, argb, argb, fill_type); +} diff --git a/core/fpdfdoc/cpdf_annot.h b/core/fpdfdoc/cpdf_annot.h new file mode 100644 index 0000000000..b5d9186fd3 --- /dev/null +++ b/core/fpdfdoc/cpdf_annot.h @@ -0,0 +1,70 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFDOC_CPDF_ANNOT_H_ +#define CORE_FPDFDOC_CPDF_ANNOT_H_ + +#include +#include + +#include "core/fxcrt/include/fx_coordinates.h" +#include "core/fxcrt/include/fx_string.h" +#include "core/fxcrt/include/fx_system.h" + +class CFX_RenderDevice; +class CPDF_Dictionary; +class CPDF_Document; +class CPDF_Form; +class CPDF_Page; +class CPDF_RenderContext; +class CPDF_RenderOptions; +class CPDF_Stream; + +#define ANNOTFLAG_INVISIBLE 0x0001 +#define ANNOTFLAG_HIDDEN 0x0002 +#define ANNOTFLAG_PRINT 0x0004 +#define ANNOTFLAG_NOZOOM 0x0008 +#define ANNOTFLAG_NOROTATE 0x0010 +#define ANNOTFLAG_NOVIEW 0x0020 +#define ANNOTFLAG_READONLY 0x0040 +#define ANNOTFLAG_LOCKED 0x0080 +#define ANNOTFLAG_TOGGLENOVIEW 0x0100 + +class CPDF_Annot { + public: + enum AppearanceMode { Normal, Rollover, Down }; + + CPDF_Annot(CPDF_Dictionary* pDict, CPDF_Document* pDocument); + ~CPDF_Annot(); + + CFX_ByteString GetSubType() const; + uint32_t GetFlags() const; + void GetRect(CFX_FloatRect& rect) const; + const CPDF_Dictionary* GetAnnotDict() const { return m_pAnnotDict; } + CPDF_Dictionary* GetAnnotDict() { return m_pAnnotDict; } + FX_BOOL DrawAppearance(CPDF_Page* pPage, + CFX_RenderDevice* pDevice, + const CFX_Matrix* pUser2Device, + AppearanceMode mode, + const CPDF_RenderOptions* pOptions); + FX_BOOL DrawInContext(const CPDF_Page* pPage, + CPDF_RenderContext* pContext, + const CFX_Matrix* pUser2Device, + AppearanceMode mode); + void ClearCachedAP(); + void DrawBorder(CFX_RenderDevice* pDevice, + const CFX_Matrix* pUser2Device, + const CPDF_RenderOptions* pOptions); + CPDF_Form* GetAPForm(const CPDF_Page* pPage, AppearanceMode mode); + + private: + CPDF_Dictionary* const m_pAnnotDict; + CPDF_Document* const m_pDocument; + const CFX_ByteString m_sSubtype; + std::map m_APMap; +}; + +#endif // CORE_FPDFDOC_CPDF_ANNOT_H_ diff --git a/core/fpdfdoc/cpdf_annotlist.cpp b/core/fpdfdoc/cpdf_annotlist.cpp new file mode 100644 index 0000000000..8b8c0e98bb --- /dev/null +++ b/core/fpdfdoc/cpdf_annotlist.cpp @@ -0,0 +1,132 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfdoc/cpdf_annotlist.h" + +#include "core/fpdfapi/fpdf_page/include/cpdf_page.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_reference.h" +#include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h" +#include "core/fpdfdoc/cpdf_annot.h" +#include "core/fpdfdoc/cpvt_generateap.h" + +CPDF_AnnotList::CPDF_AnnotList(CPDF_Page* pPage) + : m_pDocument(pPage->m_pDocument) { + if (!pPage->m_pFormDict) + return; + + CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayBy("Annots"); + if (!pAnnots) + return; + + CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); + CPDF_Dictionary* pAcroForm = pRoot->GetDictBy("AcroForm"); + FX_BOOL bRegenerateAP = + pAcroForm && pAcroForm->GetBooleanBy("NeedAppearances"); + for (size_t i = 0; i < pAnnots->GetCount(); ++i) { + CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(i)); + if (!pDict) + continue; + + uint32_t dwObjNum = pDict->GetObjNum(); + if (dwObjNum == 0) { + dwObjNum = m_pDocument->AddIndirectObject(pDict); + CPDF_Reference* pAction = new CPDF_Reference(m_pDocument, dwObjNum); + pAnnots->InsertAt(i, pAction); + pAnnots->RemoveAt(i + 1); + pDict = pAnnots->GetDictAt(i); + } + m_AnnotList.push_back( + std::unique_ptr(new CPDF_Annot(pDict, m_pDocument))); + if (bRegenerateAP && pDict->GetStringBy("Subtype") == "Widget" && + CPDF_InterForm::IsUpdateAPEnabled()) { + FPDF_GenerateAP(m_pDocument, pDict); + } + } +} + +CPDF_AnnotList::~CPDF_AnnotList() {} + +void CPDF_AnnotList::DisplayPass(CPDF_Page* pPage, + CFX_RenderDevice* pDevice, + CPDF_RenderContext* pContext, + FX_BOOL bPrinting, + CFX_Matrix* pMatrix, + FX_BOOL bWidgetPass, + CPDF_RenderOptions* pOptions, + FX_RECT* clip_rect) { + for (const auto& pAnnot : m_AnnotList) { + bool bWidget = pAnnot->GetSubType() == "Widget"; + if ((bWidgetPass && !bWidget) || (!bWidgetPass && bWidget)) + continue; + + uint32_t annot_flags = pAnnot->GetFlags(); + if (annot_flags & ANNOTFLAG_HIDDEN) + continue; + + if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) + continue; + + if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW)) + continue; + + if (pOptions) { + CPDF_OCContext* pOCContext = pOptions->m_pOCContext; + CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict(); + if (pOCContext && pAnnotDict && + !pOCContext->CheckOCGVisible(pAnnotDict->GetDictBy("OC"))) { + continue; + } + } + CFX_FloatRect annot_rect_f; + pAnnot->GetRect(annot_rect_f); + CFX_Matrix matrix = *pMatrix; + if (clip_rect) { + annot_rect_f.Transform(&matrix); + FX_RECT annot_rect = annot_rect_f.GetOutterRect(); + annot_rect.Intersect(*clip_rect); + if (annot_rect.IsEmpty()) { + continue; + } + } + if (pContext) { + pAnnot->DrawInContext(pPage, pContext, &matrix, CPDF_Annot::Normal); + } else if (!pAnnot->DrawAppearance(pPage, pDevice, &matrix, + CPDF_Annot::Normal, pOptions)) { + pAnnot->DrawBorder(pDevice, &matrix, pOptions); + } + } +} + +void CPDF_AnnotList::DisplayAnnots(CPDF_Page* pPage, + CFX_RenderDevice* pDevice, + CPDF_RenderContext* pContext, + FX_BOOL bPrinting, + CFX_Matrix* pUser2Device, + uint32_t dwAnnotFlags, + CPDF_RenderOptions* pOptions, + FX_RECT* pClipRect) { + if (dwAnnotFlags & ANNOTFLAG_INVISIBLE) { + DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, FALSE, + pOptions, pClipRect); + } + if (dwAnnotFlags & ANNOTFLAG_HIDDEN) { + DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, TRUE, + pOptions, pClipRect); + } +} + +void CPDF_AnnotList::DisplayAnnots(CPDF_Page* pPage, + CPDF_RenderContext* pContext, + FX_BOOL bPrinting, + CFX_Matrix* pMatrix, + FX_BOOL bShowWidget, + CPDF_RenderOptions* pOptions) { + uint32_t dwAnnotFlags = bShowWidget ? ANNOTFLAG_INVISIBLE | ANNOTFLAG_HIDDEN + : ANNOTFLAG_INVISIBLE; + DisplayAnnots(pPage, nullptr, pContext, bPrinting, pMatrix, dwAnnotFlags, + pOptions, nullptr); +} diff --git a/core/fpdfdoc/cpdf_annotlist.h b/core/fpdfdoc/cpdf_annotlist.h new file mode 100644 index 0000000000..afe85f33af --- /dev/null +++ b/core/fpdfdoc/cpdf_annotlist.h @@ -0,0 +1,64 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFDOC_CPDF_ANNOTLIST_H_ +#define CORE_FPDFDOC_CPDF_ANNOTLIST_H_ + +#include +#include + +#include "core/fxcrt/include/fx_coordinates.h" +#include "core/fxcrt/include/fx_system.h" + +class CFX_RenderDevice; +class CPDF_Annot; +class CPDF_Document; +class CPDF_Page; +class CPDF_RenderContext; +class CPDF_RenderOptions; + +class CPDF_AnnotList { + public: + explicit CPDF_AnnotList(CPDF_Page* pPage); + ~CPDF_AnnotList(); + + void DisplayAnnots(CPDF_Page* pPage, + CPDF_RenderContext* pContext, + FX_BOOL bPrinting, + CFX_Matrix* pMatrix, + FX_BOOL bShowWidget, + CPDF_RenderOptions* pOptions); + + void DisplayAnnots(CPDF_Page* pPage, + CFX_RenderDevice* pDevice, + CPDF_RenderContext* pContext, + FX_BOOL bPrinting, + CFX_Matrix* pMatrix, + uint32_t dwAnnotFlags, + CPDF_RenderOptions* pOptions, + FX_RECT* pClipRect); + + size_t Count() const { return m_AnnotList.size(); } + CPDF_Annot* GetAt(size_t index) const { return m_AnnotList[index].get(); } + const std::vector>& All() const { + return m_AnnotList; + } + + private: + void DisplayPass(CPDF_Page* pPage, + CFX_RenderDevice* pDevice, + CPDF_RenderContext* pContext, + FX_BOOL bPrinting, + CFX_Matrix* pMatrix, + FX_BOOL bWidget, + CPDF_RenderOptions* pOptions, + FX_RECT* clip_rect); + + CPDF_Document* const m_pDocument; + std::vector> m_AnnotList; +}; + +#endif // CORE_FPDFDOC_CPDF_ANNOTLIST_H_ diff --git a/core/fpdfdoc/doc_annot.cpp b/core/fpdfdoc/doc_annot.cpp deleted file mode 100644 index e1a976005b..0000000000 --- a/core/fpdfdoc/doc_annot.cpp +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fpdfapi/fpdf_page/include/cpdf_form.h" -#include "core/fpdfapi/fpdf_page/include/cpdf_page.h" -#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" -#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" -#include "core/fpdfapi/fpdf_parser/include/cpdf_reference.h" -#include "core/fpdfapi/fpdf_render/include/cpdf_rendercontext.h" -#include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h" -#include "core/fpdfdoc/cpvt_generateap.h" -#include "core/fpdfdoc/include/fpdf_doc.h" -#include "core/fxge/include/fx_ge.h" - -CPDF_AnnotList::CPDF_AnnotList(CPDF_Page* pPage) - : m_pDocument(pPage->m_pDocument) { - if (!pPage->m_pFormDict) - return; - - CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayBy("Annots"); - if (!pAnnots) - return; - - CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); - CPDF_Dictionary* pAcroForm = pRoot->GetDictBy("AcroForm"); - FX_BOOL bRegenerateAP = - pAcroForm && pAcroForm->GetBooleanBy("NeedAppearances"); - for (size_t i = 0; i < pAnnots->GetCount(); ++i) { - CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(i)); - if (!pDict) - continue; - - uint32_t dwObjNum = pDict->GetObjNum(); - if (dwObjNum == 0) { - dwObjNum = m_pDocument->AddIndirectObject(pDict); - CPDF_Reference* pAction = new CPDF_Reference(m_pDocument, dwObjNum); - pAnnots->InsertAt(i, pAction); - pAnnots->RemoveAt(i + 1); - pDict = pAnnots->GetDictAt(i); - } - m_AnnotList.push_back( - std::unique_ptr(new CPDF_Annot(pDict, m_pDocument))); - if (bRegenerateAP && pDict->GetStringBy("Subtype") == "Widget" && - CPDF_InterForm::IsUpdateAPEnabled()) { - FPDF_GenerateAP(m_pDocument, pDict); - } - } -} - -CPDF_AnnotList::~CPDF_AnnotList() {} - -void CPDF_AnnotList::DisplayPass(CPDF_Page* pPage, - CFX_RenderDevice* pDevice, - CPDF_RenderContext* pContext, - FX_BOOL bPrinting, - CFX_Matrix* pMatrix, - FX_BOOL bWidgetPass, - CPDF_RenderOptions* pOptions, - FX_RECT* clip_rect) { - for (const auto& pAnnot : m_AnnotList) { - bool bWidget = pAnnot->GetSubType() == "Widget"; - if ((bWidgetPass && !bWidget) || (!bWidgetPass && bWidget)) - continue; - - uint32_t annot_flags = pAnnot->GetFlags(); - if (annot_flags & ANNOTFLAG_HIDDEN) - continue; - - if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) - continue; - - if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW)) - continue; - - if (pOptions) { - CPDF_OCContext* pOCContext = pOptions->m_pOCContext; - CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict(); - if (pOCContext && pAnnotDict && - !pOCContext->CheckOCGVisible(pAnnotDict->GetDictBy("OC"))) { - continue; - } - } - CFX_FloatRect annot_rect_f; - pAnnot->GetRect(annot_rect_f); - CFX_Matrix matrix = *pMatrix; - if (clip_rect) { - annot_rect_f.Transform(&matrix); - FX_RECT annot_rect = annot_rect_f.GetOutterRect(); - annot_rect.Intersect(*clip_rect); - if (annot_rect.IsEmpty()) { - continue; - } - } - if (pContext) { - pAnnot->DrawInContext(pPage, pContext, &matrix, CPDF_Annot::Normal); - } else if (!pAnnot->DrawAppearance(pPage, pDevice, &matrix, - CPDF_Annot::Normal, pOptions)) { - pAnnot->DrawBorder(pDevice, &matrix, pOptions); - } - } -} - -void CPDF_AnnotList::DisplayAnnots(CPDF_Page* pPage, - CFX_RenderDevice* pDevice, - CPDF_RenderContext* pContext, - FX_BOOL bPrinting, - CFX_Matrix* pUser2Device, - uint32_t dwAnnotFlags, - CPDF_RenderOptions* pOptions, - FX_RECT* pClipRect) { - if (dwAnnotFlags & 0x01) { - DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, FALSE, - pOptions, pClipRect); - } - if (dwAnnotFlags & 0x02) { - DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, TRUE, - pOptions, pClipRect); - } -} - -CPDF_Annot::CPDF_Annot(CPDF_Dictionary* pDict, CPDF_Document* pDocument) - : m_pAnnotDict(pDict), - m_pDocument(pDocument), - m_sSubtype(m_pAnnotDict->GetStringBy("Subtype")) {} - -CPDF_Annot::~CPDF_Annot() { - ClearCachedAP(); -} - -void CPDF_Annot::ClearCachedAP() { - for (const auto& pair : m_APMap) { - delete pair.second; - } - m_APMap.clear(); -} -CFX_ByteString CPDF_Annot::GetSubType() const { - return m_sSubtype; -} - -void CPDF_Annot::GetRect(CFX_FloatRect& rect) const { - if (!m_pAnnotDict) { - return; - } - rect = m_pAnnotDict->GetRectBy("Rect"); - rect.Normalize(); -} - -uint32_t CPDF_Annot::GetFlags() const { - return m_pAnnotDict->GetIntegerBy("F"); -} - -CPDF_Stream* FPDFDOC_GetAnnotAP(CPDF_Dictionary* pAnnotDict, - CPDF_Annot::AppearanceMode mode) { - CPDF_Dictionary* pAP = pAnnotDict->GetDictBy("AP"); - if (!pAP) { - return nullptr; - } - const FX_CHAR* ap_entry = "N"; - if (mode == CPDF_Annot::Down) - ap_entry = "D"; - else if (mode == CPDF_Annot::Rollover) - ap_entry = "R"; - if (!pAP->KeyExist(ap_entry)) - ap_entry = "N"; - - CPDF_Object* psub = pAP->GetDirectObjectBy(ap_entry); - if (!psub) - return nullptr; - if (CPDF_Stream* pStream = psub->AsStream()) - return pStream; - - if (CPDF_Dictionary* pDict = psub->AsDictionary()) { - CFX_ByteString as = pAnnotDict->GetStringBy("AS"); - if (as.IsEmpty()) { - CFX_ByteString value = pAnnotDict->GetStringBy("V"); - if (value.IsEmpty()) { - CPDF_Dictionary* pParentDict = pAnnotDict->GetDictBy("Parent"); - value = pParentDict ? pParentDict->GetStringBy("V") : CFX_ByteString(); - } - if (value.IsEmpty() || !pDict->KeyExist(value)) - as = "Off"; - else - as = value; - } - return pDict->GetStreamBy(as); - } - return nullptr; -} - -CPDF_Form* CPDF_Annot::GetAPForm(const CPDF_Page* pPage, AppearanceMode mode) { - CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pAnnotDict, mode); - if (!pStream) - return nullptr; - - auto it = m_APMap.find(pStream); - if (it != m_APMap.end()) - return it->second; - - CPDF_Form* pNewForm = - new CPDF_Form(m_pDocument, pPage->m_pResources, pStream); - pNewForm->ParseContent(nullptr, nullptr, nullptr); - m_APMap[pStream] = pNewForm; - return pNewForm; -} - -static CPDF_Form* FPDFDOC_Annot_GetMatrix(const CPDF_Page* pPage, - CPDF_Annot* pAnnot, - CPDF_Annot::AppearanceMode mode, - const CFX_Matrix* pUser2Device, - CFX_Matrix& matrix) { - CPDF_Form* pForm = pAnnot->GetAPForm(pPage, mode); - if (!pForm) { - return nullptr; - } - CFX_FloatRect form_bbox = pForm->m_pFormDict->GetRectBy("BBox"); - CFX_Matrix form_matrix = pForm->m_pFormDict->GetMatrixBy("Matrix"); - form_matrix.TransformRect(form_bbox); - CFX_FloatRect arect; - pAnnot->GetRect(arect); - matrix.MatchRect(arect, form_bbox); - matrix.Concat(*pUser2Device); - return pForm; -} -FX_BOOL CPDF_Annot::DrawAppearance(CPDF_Page* pPage, - CFX_RenderDevice* pDevice, - const CFX_Matrix* pUser2Device, - AppearanceMode mode, - const CPDF_RenderOptions* pOptions) { - CFX_Matrix matrix; - CPDF_Form* pForm = - FPDFDOC_Annot_GetMatrix(pPage, this, mode, pUser2Device, matrix); - if (!pForm) { - return FALSE; - } - CPDF_RenderContext context(pPage); - context.AppendLayer(pForm, &matrix); - context.Render(pDevice, pOptions, nullptr); - return TRUE; -} -FX_BOOL CPDF_Annot::DrawInContext(const CPDF_Page* pPage, - CPDF_RenderContext* pContext, - const CFX_Matrix* pUser2Device, - AppearanceMode mode) { - CFX_Matrix matrix; - CPDF_Form* pForm = - FPDFDOC_Annot_GetMatrix(pPage, this, mode, pUser2Device, matrix); - if (!pForm) { - return FALSE; - } - pContext->AppendLayer(pForm, &matrix); - return TRUE; -} -void CPDF_Annot::DrawBorder(CFX_RenderDevice* pDevice, - const CFX_Matrix* pUser2Device, - const CPDF_RenderOptions* pOptions) { - if (GetSubType() == "Popup") { - return; - } - uint32_t annot_flags = GetFlags(); - if (annot_flags & ANNOTFLAG_HIDDEN) { - return; - } - bool bPrinting = pDevice->GetDeviceClass() == FXDC_PRINTER || - (pOptions && (pOptions->m_Flags & RENDER_PRINTPREVIEW)); - if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) { - return; - } - if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW)) { - return; - } - CPDF_Dictionary* pBS = m_pAnnotDict->GetDictBy("BS"); - char style_char; - FX_FLOAT width; - CPDF_Array* pDashArray = nullptr; - if (!pBS) { - CPDF_Array* pBorderArray = m_pAnnotDict->GetArrayBy("Border"); - style_char = 'S'; - if (pBorderArray) { - width = pBorderArray->GetNumberAt(2); - if (pBorderArray->GetCount() == 4) { - pDashArray = pBorderArray->GetArrayAt(3); - if (!pDashArray) { - return; - } - size_t nLen = pDashArray->GetCount(); - size_t i = 0; - for (; i < nLen; ++i) { - CPDF_Object* pObj = pDashArray->GetDirectObjectAt(i); - if (pObj && pObj->GetInteger()) { - break; - } - } - if (i == nLen) { - return; - } - style_char = 'D'; - } - } else { - width = 1; - } - } else { - CFX_ByteString style = pBS->GetStringBy("S"); - pDashArray = pBS->GetArrayBy("D"); - style_char = style[1]; - width = pBS->GetNumberBy("W"); - } - if (width <= 0) { - return; - } - CPDF_Array* pColor = m_pAnnotDict->GetArrayBy("C"); - uint32_t argb = 0xff000000; - if (pColor) { - int R = (int32_t)(pColor->GetNumberAt(0) * 255); - int G = (int32_t)(pColor->GetNumberAt(1) * 255); - int B = (int32_t)(pColor->GetNumberAt(2) * 255); - argb = ArgbEncode(0xff, R, G, B); - } - CFX_GraphStateData graph_state; - graph_state.m_LineWidth = width; - if (style_char == 'D') { - if (pDashArray) { - size_t dash_count = pDashArray->GetCount(); - if (dash_count % 2) { - dash_count++; - } - graph_state.m_DashArray = FX_Alloc(FX_FLOAT, dash_count); - graph_state.m_DashCount = dash_count; - size_t i; - for (i = 0; i < pDashArray->GetCount(); ++i) { - graph_state.m_DashArray[i] = pDashArray->GetNumberAt(i); - } - if (i < dash_count) { - graph_state.m_DashArray[i] = graph_state.m_DashArray[i - 1]; - } - } else { - graph_state.m_DashArray = FX_Alloc(FX_FLOAT, 2); - graph_state.m_DashCount = 2; - graph_state.m_DashArray[0] = graph_state.m_DashArray[1] = 3 * 1.0f; - } - } - CFX_FloatRect rect; - GetRect(rect); - CFX_PathData path; - width /= 2; - path.AppendRect(rect.left + width, rect.bottom + width, rect.right - width, - rect.top - width); - int fill_type = 0; - if (pOptions && (pOptions->m_Flags & RENDER_NOPATHSMOOTH)) { - fill_type |= FXFILL_NOPATHSMOOTH; - } - pDevice->DrawPath(&path, pUser2Device, &graph_state, argb, argb, fill_type); -} diff --git a/core/fpdfdoc/include/fpdf_doc.h b/core/fpdfdoc/include/fpdf_doc.h index 887b0dc5b1..edcec239f6 100644 --- a/core/fpdfdoc/include/fpdf_doc.h +++ b/core/fpdfdoc/include/fpdf_doc.h @@ -14,6 +14,8 @@ #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" #include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h" +#include "core/fpdfdoc/cpdf_annot.h" +#include "core/fpdfdoc/cpdf_annotlist.h" #include "core/fxge/include/fx_dib.h" class CFDF_Document; @@ -22,8 +24,6 @@ class CFX_RenderDevice; class CPDF_AAction; class CPDF_Action; class CPDF_ActionFields; -class CPDF_Annot; -class CPDF_AnnotList; class CPDF_ApSettings; class CPDF_Bookmark; class CPDF_BookmarkTree; @@ -306,93 +306,6 @@ class CPDF_Link { CPDF_Dictionary* m_pDict; }; -#define ANNOTFLAG_INVISIBLE 0x0001 -#define ANNOTFLAG_HIDDEN 0x0002 -#define ANNOTFLAG_PRINT 0x0004 -#define ANNOTFLAG_NOZOOM 0x0008 -#define ANNOTFLAG_NOROTATE 0x0010 -#define ANNOTFLAG_NOVIEW 0x0020 -#define ANNOTFLAG_READONLY 0x0040 -#define ANNOTFLAG_LOCKED 0x0080 -#define ANNOTFLAG_TOGGLENOVIEW 0x0100 - -class CPDF_Annot { - public: - enum AppearanceMode { Normal, Rollover, Down }; - - CPDF_Annot(CPDF_Dictionary* pDict, CPDF_Document* pDocument); - ~CPDF_Annot(); - - CFX_ByteString GetSubType() const; - uint32_t GetFlags() const; - void GetRect(CFX_FloatRect& rect) const; - const CPDF_Dictionary* GetAnnotDict() const { return m_pAnnotDict; } - CPDF_Dictionary* GetAnnotDict() { return m_pAnnotDict; } - FX_BOOL DrawAppearance(CPDF_Page* pPage, - CFX_RenderDevice* pDevice, - const CFX_Matrix* pUser2Device, - AppearanceMode mode, - const CPDF_RenderOptions* pOptions); - FX_BOOL DrawInContext(const CPDF_Page* pPage, - CPDF_RenderContext* pContext, - const CFX_Matrix* pUser2Device, - AppearanceMode mode); - void ClearCachedAP(); - void DrawBorder(CFX_RenderDevice* pDevice, - const CFX_Matrix* pUser2Device, - const CPDF_RenderOptions* pOptions); - CPDF_Form* GetAPForm(const CPDF_Page* pPage, AppearanceMode mode); - - private: - CPDF_Dictionary* const m_pAnnotDict; - CPDF_Document* const m_pDocument; - const CFX_ByteString m_sSubtype; - std::map m_APMap; -}; - -class CPDF_AnnotList { - public: - explicit CPDF_AnnotList(CPDF_Page* pPage); - ~CPDF_AnnotList(); - - void DisplayAnnots(CPDF_Page* pPage, - CPDF_RenderContext* pContext, - FX_BOOL bPrinting, - CFX_Matrix* pMatrix, - FX_BOOL bShowWidget, - CPDF_RenderOptions* pOptions) { - DisplayAnnots(pPage, nullptr, pContext, bPrinting, pMatrix, - bShowWidget ? 3 : 1, pOptions, nullptr); - } - - void DisplayAnnots(CPDF_Page* pPage, - CFX_RenderDevice* pDevice, - CPDF_RenderContext* pContext, - FX_BOOL bPrinting, - CFX_Matrix* pMatrix, - uint32_t dwAnnotFlags, - CPDF_RenderOptions* pOptions, - FX_RECT* pClipRect); - size_t Count() const { return m_AnnotList.size(); } - CPDF_Annot* GetAt(size_t index) const { return m_AnnotList[index].get(); } - const std::vector>& All() const { - return m_AnnotList; - } - - protected: - void DisplayPass(CPDF_Page* pPage, - CFX_RenderDevice* pDevice, - CPDF_RenderContext* pContext, - FX_BOOL bPrinting, - CFX_Matrix* pMatrix, - FX_BOOL bWidget, - CPDF_RenderOptions* pOptions, - FX_RECT* clip_rect); - - CPDF_Document* const m_pDocument; - std::vector> m_AnnotList; -}; - #define COLORTYPE_TRANSPARENT 0 #define COLORTYPE_GRAY 1 #define COLORTYPE_RGB 2 diff --git a/pdfium.gyp b/pdfium.gyp index 0faf6fdf44..ecef4a7838 100644 --- a/pdfium.gyp +++ b/pdfium.gyp @@ -182,6 +182,10 @@ 'core/fpdfdoc/include/fpdf_doc.h', 'core/fpdfdoc/include/fpdf_tagged.h', 'core/fpdfdoc/cpdf_variabletext.cpp', + 'core/fpdfdoc/cpdf_annot.cpp', + 'core/fpdfdoc/cpdf_annot.h', + 'core/fpdfdoc/cpdf_annotlist.cpp', + 'core/fpdfdoc/cpdf_annotlist.h', 'core/fpdfdoc/cpvt_color.cpp', 'core/fpdfdoc/cpvt_color.h', 'core/fpdfdoc/cpvt_dash.h', @@ -200,7 +204,6 @@ 'core/fpdfdoc/ctypeset.cpp', 'core/fpdfdoc/ctypeset.h', 'core/fpdfdoc/doc_action.cpp', - 'core/fpdfdoc/doc_annot.cpp', 'core/fpdfdoc/doc_basic.cpp', 'core/fpdfdoc/doc_bookmark.cpp', 'core/fpdfdoc/doc_form.cpp', -- cgit v1.2.3