Define behaviors of FPDF_RenderPageBitmap_Retail and FPDF_FFLDraw. Previously, PDFium only supported widget annotations to draw forms. As we've implemented other annotations, the behavior of FPDF_RenderPageBitmap_Retail and FPDF_FFLDraw changed. So, this CL clearly defines what needs to be done in FPDF_RenderPageBitmap_Retail and FPDF_FFLDraw. This CL first assumes that PDFium users will always call FPDF_RenderPageBitmap_Retail and FPDF_FFLDraw to render PDF pages, because otherwise they are not able to support PDF forms. FPDF_RenderPageBitmap_Retail should only deal with non-widget annotations, such as highlight, underline, text, etc. If FPDF_ANNOT flag is passed, non-widget annotations are drawn. Otherwise, they are hidden. FPDF_FFLDraw should only deal with annotations that requires user-interaction, such as widget annotations and popup annotation. Since popup annotation is associated with non-widget annotation, they should not be drawn if the associated annotation is hidden. Thus, if FPDF_ANNOT flag is passed, popup annotations are drawn. Otherwise, they are hidden. Widget annotations should be always drawn regardless of FPDF_ANNOT flag since they need to be always displayed for PDF forms. Also, roll DEPS for testing/corpus to 8485b30. BUG=pdfium:594 Review-Url: https://codereview.chromium.org/2323203002
diff --git a/DEPS b/DEPS index f87e9d6..e3ef8e8 100644 --- a/DEPS +++ b/DEPS
@@ -14,7 +14,7 @@ 'gmock_revision': '29763965ab52f24565299976b936d1265cb6a271', 'gtest_revision': '8245545b6dc9c4703e6496d1efd19e975ad2b038', 'icu_revision': '2341038bf72869a5683a893a2b319a48ffec7f62', - 'pdfium_tests_revision': '6608bf041de1104595d3e9c0c18cd411d4757446', + 'pdfium_tests_revision': '8485b3093524ddb7319e0381ab10c576e59d5091', 'skia_revision': '39f7a10a04a914384944d8bf62621144ac4eeaa3', 'tools_memory_revision': '427f10475e1a8d72424c29d00bf689122b738e5d', 'trace_event_revision': '54b8455be9505c2cb0cf5c26bb86739c236471aa',
diff --git a/core/fpdfapi/fpdf_render/fpdf_render.cpp b/core/fpdfapi/fpdf_render/fpdf_render.cpp index 887ea30..fbb0745 100644 --- a/core/fpdfapi/fpdf_render/fpdf_render.cpp +++ b/core/fpdfapi/fpdf_render/fpdf_render.cpp
@@ -100,7 +100,21 @@ m_AddFlags(0), m_pOCContext(nullptr), m_dwLimitCacheSize(1024 * 1024 * 100), - m_HalftoneLimit(-1) {} + m_HalftoneLimit(-1), + m_bDrawAnnots(false) {} + +CPDF_RenderOptions::CPDF_RenderOptions(const CPDF_RenderOptions& rhs) + : m_ColorMode(rhs.m_ColorMode), + m_BackColor(rhs.m_BackColor), + m_ForeColor(rhs.m_ForeColor), + m_Flags(rhs.m_Flags), + m_Interpolation(rhs.m_Interpolation), + m_AddFlags(rhs.m_AddFlags), + m_pOCContext(rhs.m_pOCContext), + m_dwLimitCacheSize(rhs.m_dwLimitCacheSize), + m_HalftoneLimit(rhs.m_HalftoneLimit), + m_bDrawAnnots(rhs.m_bDrawAnnots) {} + FX_ARGB CPDF_RenderOptions::TranslateColor(FX_ARGB argb) const { if (m_ColorMode == RENDER_COLOR_NORMAL) { return argb;
diff --git a/core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h b/core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h index 2590dbb..7c513ae 100644 --- a/core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h +++ b/core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h
@@ -36,6 +36,7 @@ class CPDF_RenderOptions { public: CPDF_RenderOptions(); + CPDF_RenderOptions(const CPDF_RenderOptions& rhs); FX_ARGB TranslateColor(FX_ARGB argb) const; int m_ColorMode; @@ -47,6 +48,7 @@ CPDF_OCContext* m_pOCContext; uint32_t m_dwLimitCacheSize; int m_HalftoneLimit; + bool m_bDrawAnnots; }; #endif // CORE_FPDFAPI_FPDF_RENDER_INCLUDE_CPDF_RENDEROPTIONS_H_
diff --git a/core/fpdfdoc/cpdf_annot.cpp b/core/fpdfdoc/cpdf_annot.cpp index 4e0b04e..0cc3596 100644 --- a/core/fpdfdoc/cpdf_annot.cpp +++ b/core/fpdfdoc/cpdf_annot.cpp
@@ -73,6 +73,16 @@ CPVT_GenerateAP::GenerateUnderlineAP(m_pDocument, m_pAnnotDict); } +bool CPDF_Annot::ShouldDrawAnnotation() { + if (IsAnnotationHidden(m_pAnnotDict)) + return false; + + if (m_nSubtype == CPDF_Annot::Subtype::POPUP && !m_bOpenState) + return false; + + return true; +} + void CPDF_Annot::ClearCachedAP() { m_APMap.clear(); } @@ -294,10 +304,7 @@ const CFX_Matrix* pUser2Device, AppearanceMode mode, const CPDF_RenderOptions* pOptions) { - if (IsAnnotationHidden(m_pAnnotDict)) - return FALSE; - - if (m_nSubtype == CPDF_Annot::Subtype::POPUP && !m_bOpenState) + if (!ShouldDrawAnnotation()) return FALSE; // It might happen that by the time this annotation instance was created, @@ -322,6 +329,16 @@ CPDF_RenderContext* pContext, const CFX_Matrix* pUser2Device, AppearanceMode mode) { + if (!ShouldDrawAnnotation()) + return FALSE; + + // It might happen that by the time this annotation instance was created, + // it was flagged as "hidden" (e.g. /F 2), and hence CPVT_GenerateAP decided + // to not "generate" its AP. + // If for a reason the object is no longer hidden, but still does not have + // its "AP" generated, generate it now. + GenerateAPIfNeeded(); + CFX_Matrix matrix; CPDF_Form* pForm = FPDFDOC_Annot_GetMatrix(pPage, this, mode, pUser2Device, matrix);
diff --git a/core/fpdfdoc/include/cpdf_annot.h b/core/fpdfdoc/include/cpdf_annot.h index eb9f02a..c16decc 100644 --- a/core/fpdfdoc/include/cpdf_annot.h +++ b/core/fpdfdoc/include/cpdf_annot.h
@@ -100,6 +100,7 @@ private: void GenerateAPIfNeeded(); + bool ShouldDrawAnnotation(); // For regular annotations, |m_pAnnotDict| is not owned. For // our artificially created popup annotations, |m_pAnnotDict|
diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.cpp b/fpdfsdk/cpdfsdk_annothandlermgr.cpp index 12362e3..0fd48d2 100644 --- a/fpdfsdk/cpdfsdk_annothandlermgr.cpp +++ b/fpdfsdk/cpdfsdk_annothandlermgr.cpp
@@ -93,9 +93,11 @@ void CPDFSDK_AnnotHandlerMgr::Annot_OnDraw(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { + CFX_Matrix* pUser2Device, + bool bDrawAnnots) { ASSERT(pAnnot); - GetAnnotHandler(pAnnot)->OnDraw(pPageView, pAnnot, pDevice, pUser2Device); + GetAnnotHandler(pAnnot)->OnDraw(pPageView, pAnnot, pDevice, pUser2Device, + bDrawAnnots); } FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnLButtonDown(
diff --git a/fpdfsdk/cpdfsdk_baannothandler.cpp b/fpdfsdk/cpdfsdk_baannothandler.cpp index 1007104..f0d67f4 100644 --- a/fpdfsdk/cpdfsdk_baannothandler.cpp +++ b/fpdfsdk/cpdfsdk_baannothandler.cpp
@@ -62,13 +62,16 @@ void CPDFSDK_BAAnnotHandler::OnDraw(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { + CFX_Matrix* pUser2Device, + bool bDrawAnnots) { #ifdef PDF_ENABLE_XFA if (pAnnot->IsXFAField()) return; #endif // PDF_ENABLE_XFA - static_cast<CPDFSDK_BAAnnot*>(pAnnot)->DrawAppearance( - pDevice, pUser2Device, CPDF_Annot::Normal, nullptr); + if (bDrawAnnots && pAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::POPUP) { + static_cast<CPDFSDK_BAAnnot*>(pAnnot)->DrawAppearance( + pDevice, pUser2Device, CPDF_Annot::Normal, nullptr); + } } void CPDFSDK_BAAnnotHandler::OnDelete(CPDFSDK_Annot* pAnnot) {}
diff --git a/fpdfsdk/cpdfsdk_widgethandler.cpp b/fpdfsdk/cpdfsdk_widgethandler.cpp index b490daa..8a061e5 100644 --- a/fpdfsdk/cpdfsdk_widgethandler.cpp +++ b/fpdfsdk/cpdfsdk_widgethandler.cpp
@@ -92,7 +92,8 @@ void CPDFSDK_WidgetHandler::OnDraw(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { + CFX_Matrix* pUser2Device, + bool bDrawAnnots) { if (pAnnot->IsSignatureWidget()) { static_cast<CPDFSDK_BAAnnot*>(pAnnot)->DrawAppearance( pDevice, pUser2Device, CPDF_Annot::Normal, nullptr);
diff --git a/fpdfsdk/cpdfsdk_xfawidgethandler.cpp b/fpdfsdk/cpdfsdk_xfawidgethandler.cpp index 7422011..8621f77 100644 --- a/fpdfsdk/cpdfsdk_xfawidgethandler.cpp +++ b/fpdfsdk/cpdfsdk_xfawidgethandler.cpp
@@ -46,7 +46,8 @@ void CPDFSDK_XFAWidgetHandler::OnDraw(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { + CFX_Matrix* pUser2Device, + bool bDrawAnnots) { ASSERT(pPageView); ASSERT(pAnnot);
diff --git a/fpdfsdk/fpdfformfill.cpp b/fpdfsdk/fpdfformfill.cpp index 449eac0..2ac6c60 100644 --- a/fpdfsdk/fpdfformfill.cpp +++ b/fpdfsdk/fpdfformfill.cpp
@@ -114,6 +114,7 @@ options.m_BackColor = 0xffffff; } options.m_AddFlags = flags >> 8; + options.m_bDrawAnnots = flags & FPDF_ANNOT; #ifdef PDF_ENABLE_XFA options.m_pOCContext = new CPDF_OCContext(pPDFDoc, CPDF_OCContext::View);
diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp index 1c0af1d..4e20751 100644 --- a/fpdfsdk/fpdfview.cpp +++ b/fpdfsdk/fpdfview.cpp
@@ -896,7 +896,7 @@ pContext->m_pAnnots.reset(new CPDF_AnnotList(pPage)); FX_BOOL bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY; pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext.get(), - bPrinting, &matrix, TRUE, nullptr); + bPrinting, &matrix, FALSE, nullptr); } pContext->m_pRenderer.reset(new CPDF_ProgressiveRenderer(
diff --git a/fpdfsdk/fsdk_mgr.cpp b/fpdfsdk/fsdk_mgr.cpp index 694e315..c8f387e 100644 --- a/fpdfsdk/fsdk_mgr.cpp +++ b/fpdfsdk/fsdk_mgr.cpp
@@ -12,6 +12,7 @@ #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_renderoptions.h" #include "core/fpdfdoc/include/cpdf_docjsactions.h" #include "core/fpdfdoc/include/cpdf_interform.h" #include "core/fxcrt/include/cfx_retain_ptr.h" @@ -581,7 +582,8 @@ CPDFSDK_AnnotIterator annotIterator(this, true); while (CPDFSDK_Annot* pSDKAnnot = annotIterator.Next()) { CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = pEnv->GetAnnotHandlerMgr(); - pAnnotHandlerMgr->Annot_OnDraw(this, pSDKAnnot, pDevice, pUser2Device); + pAnnotHandlerMgr->Annot_OnDraw(this, pSDKAnnot, pDevice, pUser2Device, + pOptions->m_bDrawAnnots); } }
diff --git a/fpdfsdk/include/cpdfsdk_annothandlermgr.h b/fpdfsdk/include/cpdfsdk_annothandlermgr.h index 540bd98..f4be66a 100644 --- a/fpdfsdk/include/cpdfsdk_annothandlermgr.h +++ b/fpdfsdk/include/cpdfsdk_annothandlermgr.h
@@ -48,7 +48,8 @@ virtual void Annot_OnDraw(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device); + CFX_Matrix* pUser2Device, + bool bDrawAnnots); virtual void Annot_OnMouseEnter(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot,
diff --git a/fpdfsdk/include/cpdfsdk_baannothandler.h b/fpdfsdk/include/cpdfsdk_baannothandler.h index 5425b0b..ba50df3 100644 --- a/fpdfsdk/include/cpdfsdk_baannothandler.h +++ b/fpdfsdk/include/cpdfsdk_baannothandler.h
@@ -44,7 +44,8 @@ void OnDraw(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) override; + CFX_Matrix* pUser2Device, + bool bDrawAnnots) override; void OnCreate(CPDFSDK_Annot* pAnnot) override; void OnLoad(CPDFSDK_Annot* pAnnot) override; void OnDelete(CPDFSDK_Annot* pAnnot) override;
diff --git a/fpdfsdk/include/cpdfsdk_widgethandler.h b/fpdfsdk/include/cpdfsdk_widgethandler.h index b8cb182..d34510d 100644 --- a/fpdfsdk/include/cpdfsdk_widgethandler.h +++ b/fpdfsdk/include/cpdfsdk_widgethandler.h
@@ -44,7 +44,8 @@ void OnDraw(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) override; + CFX_Matrix* pUser2Device, + bool bDrawAnnots) override; void OnCreate(CPDFSDK_Annot* pAnnot) override; void OnLoad(CPDFSDK_Annot* pAnnot) override; void OnDelete(CPDFSDK_Annot* pAnnot) override;
diff --git a/fpdfsdk/include/cpdfsdk_xfawidgethandler.h b/fpdfsdk/include/cpdfsdk_xfawidgethandler.h index 10eb1ee..dec2675 100644 --- a/fpdfsdk/include/cpdfsdk_xfawidgethandler.h +++ b/fpdfsdk/include/cpdfsdk_xfawidgethandler.h
@@ -39,7 +39,8 @@ void OnDraw(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) override; + CFX_Matrix* pUser2Device, + bool bDrawAnnots) override; void OnCreate(CPDFSDK_Annot* pAnnot) override; void OnLoad(CPDFSDK_Annot* pAnnot) override; void OnDelete(CPDFSDK_Annot* pAnnot) override;
diff --git a/fpdfsdk/include/ipdfsdk_annothandler.h b/fpdfsdk/include/ipdfsdk_annothandler.h index 289d480..d2f9010 100644 --- a/fpdfsdk/include/ipdfsdk_annothandler.h +++ b/fpdfsdk/include/ipdfsdk_annothandler.h
@@ -43,7 +43,8 @@ virtual void OnDraw(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) = 0; + CFX_Matrix* pUser2Device, + bool bDrawAnnots) = 0; virtual void OnCreate(CPDFSDK_Annot* pAnnot) = 0; virtual void OnLoad(CPDFSDK_Annot* pAnnot) = 0; virtual void OnDelete(CPDFSDK_Annot* pAnnot) = 0;
diff --git a/public/fpdf_formfill.h b/public/fpdf_formfill.h index 248bcd2..09674b0 100644 --- a/public/fpdf_formfill.h +++ b/public/fpdf_formfill.h
@@ -1483,7 +1483,8 @@ /** * Function: FPDF_FFLDraw -* Render FormFeilds on a page to a device independent bitmap. +* Render FormFields and popup window on a page to a device independent +*bitmap. * Parameters: * hHandle - Handle to the form fill module. Returned by *FPDFDOC_InitFormFillEnvironment. @@ -1508,13 +1509,15 @@ * Return Value: * None. * Comments: -* This method is designed to only render annotations and FormFields on -*the page. -* Without FPDF_ANNOT specified for flags, Rendering functions such as -*FPDF_RenderPageBitmap or FPDF_RenderPageBitmap_Start will only render page -*contents(without annotations) to a bitmap. -* In order to implement the FormFill functions,Implementation should -*call this method after rendering functions finish rendering the page contents. +* This function is designed to render annotations that are +*user-interactive, which are widget annotation (for FormFields) and popup +*annotation. +* With FPDF_ANNOT flag, this function will render popup annotation +*when users mouse-hover on non-widget annotation. Regardless of FPDF_ANNOT flag, +*this function will always render widget annotations for FormFields. +* In order to implement the FormFill functions, implementation should +*call this function after rendering functions, such as FPDF_RenderPageBitmap or +*FPDF_RenderPageBitmap_Start, finish rendering the page contents. **/ DLLEXPORT void STDCALL FPDF_FFLDraw(FPDF_FORMHANDLE hHandle, FPDF_BITMAP bitmap,
diff --git a/public/fpdf_progressive.h b/public/fpdf_progressive.h index f352ff9..ffc812d 100644 --- a/public/fpdf_progressive.h +++ b/public/fpdf_progressive.h
@@ -66,7 +66,10 @@ // 2 (rotated 180 degrees), 3 (rotated 90 degrees // counter-clockwise). // flags - 0 for normal display, or combination of flags -// defined above. +// defined in fpdfview.h. With FPDF_ANNOT flag, it +// renders all annotations that does not require +// user-interaction, which are all annotations except +// widget and popup annotations. // pause - The IFSDK_PAUSE interface.A callback mechanism // allowing the page rendering process // Return value:
diff --git a/public/fpdfview.h b/public/fpdfview.h index cbb577b..499124d 100644 --- a/public/fpdfview.h +++ b/public/fpdfview.h
@@ -595,7 +595,10 @@ // 2 (rotated 180 degrees) // 3 (rotated 90 degrees counter-clockwise) // flags - 0 for normal display, or combination of flags -// defined above. +// defined above. With FPDF_ANNOT flag, it renders all +// annotations that does not require user-interaction, +// which are all annotations except widget and popup +// annotations. // Return value: // None. DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc index 421df39..b78075e 100644 --- a/samples/pdfium_test.cc +++ b/samples/pdfium_test.cc
@@ -573,9 +573,9 @@ if (bitmap) { FPDF_DWORD fill_color = alpha ? 0x00000000 : 0xFFFFFFFF; FPDFBitmap_FillRect(bitmap, 0, 0, width, height, fill_color); - FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0); + FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, FPDF_ANNOT); - FPDF_FFLDraw(form, bitmap, page, 0, 0, width, height, 0, 0); + FPDF_FFLDraw(form, bitmap, page, 0, 0, width, height, 0, FPDF_ANNOT); int stride = FPDFBitmap_GetStride(bitmap); const char* buffer = reinterpret_cast<const char*>(FPDFBitmap_GetBuffer(bitmap));