From e10509a3d2a1641984845d579963d574305ea6cc Mon Sep 17 00:00:00 2001 From: Jane Liu Date: Tue, 20 Jun 2017 16:47:41 -0400 Subject: Wrapper class for annotation dictionary + CPDF_Form Simple wrapper class for annotation + its path parsing form object. This will be used in APIs for extracting and setting annotation paths. Bug=pdfium:737 Change-Id: I2e8131672d087613213735295c6d01e377b956e7 Reviewed-on: https://pdfium-review.googlesource.com/6730 Reviewed-by: dsinclair Commit-Queue: dsinclair --- fpdfsdk/fpdfannot.cpp | 86 ++++++++++++++++++++++++++++++++------ fpdfsdk/fpdfannot_embeddertest.cpp | 8 ++++ fpdfsdk/fpdfedit_embeddertest.cpp | 3 +- fpdfsdk/fpdfview.cpp | 8 ---- fpdfsdk/fpdfview_c_api_test.c | 1 + public/fpdf_annot.h | 7 ++++ 6 files changed, 90 insertions(+), 23 deletions(-) diff --git a/fpdfsdk/fpdfannot.cpp b/fpdfsdk/fpdfannot.cpp index 90927fd396..6d47b04be2 100644 --- a/fpdfsdk/fpdfannot.cpp +++ b/fpdfsdk/fpdfannot.cpp @@ -8,6 +8,7 @@ #include +#include "core/fpdfapi/page/cpdf_form.h" #include "core/fpdfapi/page/cpdf_page.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" @@ -20,6 +21,8 @@ #include "core/fpdfdoc/cpvt_generateap.h" #include "fpdfsdk/fsdk_define.h" +namespace { + // These checks ensure the consistency of annotation subtype values across core/ // and public. static_assert(static_cast(CPDF_Annot::Subtype::UNKNOWN) == @@ -98,6 +101,46 @@ static_assert(static_cast(CPDF_Annot::Subtype::XFAWIDGET) == FPDF_ANNOT_XFAWIDGET, "CPDF_Annot::XFAWIDGET value mismatch"); +class CPDF_AnnotContext { + public: + CPDF_AnnotContext(CPDF_Dictionary* pAnnotDict, + CPDF_Page* pPage, + CPDF_Stream* pStream) + : m_pAnnotDict(pAnnotDict), m_pPage(pPage) { + SetForm(pStream); + } + ~CPDF_AnnotContext() {} + + bool HasForm() const { return !!m_pAnnotForm; } + + void SetForm(CPDF_Stream* pStream) { + if (!pStream) + return; + + m_pAnnotForm = pdfium::MakeUnique( + m_pPage->m_pDocument.Get(), m_pPage->m_pResources.Get(), pStream); + m_pAnnotForm->ParseContent(nullptr, nullptr, nullptr); + } + + CPDF_Form* GetForm() const { return m_pAnnotForm.get(); } + CPDF_Dictionary* GetAnnotDict() const { return m_pAnnotDict.Get(); } + + private: + std::unique_ptr m_pAnnotForm; + CFX_UnownedPtr m_pAnnotDict; + CFX_UnownedPtr m_pPage; +}; + +FPDF_ANNOTATION FPDFAnnotationFromCPDFAnnotContext(CPDF_AnnotContext* pAnnot) { + return static_cast(pAnnot); +} + +CPDF_AnnotContext* CPDFAnnotContextFromFPDFAnnotation(FPDF_ANNOTATION annot) { + return static_cast(annot); +} + +} // namespace + DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_IsSupportedSubtype(FPDF_ANNOTATION_SUBTYPE subtype) { return subtype == FPDF_ANNOT_CIRCLE || subtype == FPDF_ANNOT_HIGHLIGHT || @@ -121,8 +164,11 @@ FPDFPage_CreateAnnot(FPDF_PAGE page, pDict->SetNewFor("Subtype", CPDF_Annot::AnnotSubtypeToString( static_cast(subtype))); - if (annot) - *annot = FPDFAnnotationFromCPDFDictionary(pDict.get()); + if (annot) { + auto pNewAnnot = + pdfium::MakeUnique(pDict.get(), pPage, nullptr); + *annot = FPDFAnnotationFromCPDFAnnotContext(pNewAnnot.release()); + } CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArrayFor("Annots"); if (!pAnnotList) @@ -153,13 +199,19 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GetAnnot(FPDF_PAGE page, return false; CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(index)); - *annot = FPDFAnnotationFromCPDFDictionary(pDict); - return *annot ? true : false; + auto pNewAnnot = pdfium::MakeUnique(pDict, pPage, nullptr); + *annot = FPDFAnnotationFromCPDFAnnotContext(pNewAnnot.release()); + return true; +} + +DLLEXPORT void STDCALL FPDFPage_CloseAnnot(FPDF_ANNOTATION annot) { + delete CPDFAnnotContextFromFPDFAnnotation(annot); } DLLEXPORT FPDF_ANNOTATION_SUBTYPE STDCALL FPDFAnnot_GetSubtype(FPDF_ANNOTATION annot) { - CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFAnnotation(annot); + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); if (!pAnnotDict) return FPDF_ANNOT_UNKNOWN; @@ -173,7 +225,8 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_SetColor(FPDF_ANNOTATION annot, unsigned int G, unsigned int B, unsigned int A) { - CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFAnnotation(annot); + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); if (!pAnnotDict || R > 255 || G > 255 || B > 255 || A > 255) return false; @@ -201,7 +254,8 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_GetColor(FPDF_ANNOTATION annot, unsigned int* G, unsigned int* B, unsigned int* A) { - CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFAnnotation(annot); + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); if (!pAnnotDict || !R || !G || !B || !A) return false; @@ -267,7 +321,8 @@ FPDFAnnot_SetAttachmentPoints(FPDF_ANNOTATION annot, if (!annot || !FPDFAnnot_HasAttachmentPoints(annot)) return false; - CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFAnnotation(annot); + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); CPDF_Array* pQuadPoints = pAnnotDict->GetArrayFor("QuadPoints"); if (pQuadPoints) pQuadPoints->Clear(); @@ -292,7 +347,8 @@ FPDFAnnot_GetAttachmentPoints(FPDF_ANNOTATION annot, return false; CPDF_Array* pArray = - CPDFDictionaryFromFPDFAnnotation(annot)->GetArrayFor("QuadPoints"); + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict()->GetArrayFor( + "QuadPoints"); if (!pArray) return false; @@ -309,7 +365,8 @@ FPDFAnnot_GetAttachmentPoints(FPDF_ANNOTATION annot, DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_SetRect(FPDF_ANNOTATION annot, FS_RECTF rect) { - CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFAnnotation(annot); + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); if (!pAnnotDict) return false; @@ -328,7 +385,8 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_SetRect(FPDF_ANNOTATION annot, DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_GetRect(FPDF_ANNOTATION annot, FS_RECTF* rect) { - CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFAnnotation(annot); + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); if (!rect || !pAnnotDict) return false; @@ -346,7 +404,8 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_GetRect(FPDF_ANNOTATION annot, DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_SetText(FPDF_ANNOTATION annot, FPDFANNOT_TEXTTYPE type, FPDF_WIDESTRING text) { - CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFAnnotation(annot); + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); if (!pAnnotDict) return false; @@ -361,7 +420,8 @@ DLLEXPORT unsigned long STDCALL FPDFAnnot_GetText(FPDF_ANNOTATION annot, FPDFANNOT_TEXTTYPE type, void* buffer, unsigned long buflen) { - CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFAnnotation(annot); + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); if (!pAnnotDict) return 0; diff --git a/fpdfsdk/fpdfannot_embeddertest.cpp b/fpdfsdk/fpdfannot_embeddertest.cpp index e1da7cc2cd..85f9b68240 100644 --- a/fpdfsdk/fpdfannot_embeddertest.cpp +++ b/fpdfsdk/fpdfannot_embeddertest.cpp @@ -88,6 +88,7 @@ TEST_F(FPDFAnnotEmbeddertest, ExtractHighlightLongContent) { EXPECT_EQ(157.211182f, quadpoints.x4); EXPECT_EQ(706.264465f, quadpoints.y4); + FPDFPage_CloseAnnot(annot); UnloadPage(page); } @@ -130,6 +131,7 @@ TEST_F(FPDFAnnotEmbeddertest, ExtractInkMultiple) { EXPECT_EQ(475.336090f, rect.right); EXPECT_EQ(681.535034f, rect.top); + FPDFPage_CloseAnnot(annot); UnloadPage(page); } @@ -162,6 +164,8 @@ TEST_F(FPDFAnnotEmbeddertest, AddFirstTextAnnotation) { // Check that the subtype of the annotation is correct. EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot)); + FPDFPage_CloseAnnot(annot); + ASSERT_TRUE(FPDFPage_GetAnnot(page, 0, &annot)); EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot)); @@ -222,6 +226,7 @@ TEST_F(FPDFAnnotEmbeddertest, AddFirstTextAnnotation) { GetPlatformWString(reinterpret_cast(buf.data())) .c_str()); + FPDFPage_CloseAnnot(annot); UnloadPage(page); } @@ -242,12 +247,14 @@ TEST_F(FPDFAnnotEmbeddertest, AddAndSaveUnderlineAnnotation) { EXPECT_EQ(718.913940f, quadpoints.y1); EXPECT_EQ(157.211182f, quadpoints.x4); EXPECT_EQ(706.264465f, quadpoints.y4); + FPDFPage_CloseAnnot(annot); // Add an underline annotation to the page and set its quadpoints. ASSERT_TRUE(FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE, &annot)); quadpoints.x1 = 140.802643f; quadpoints.x3 = 140.802643f; ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, quadpoints)); + FPDFPage_CloseAnnot(annot); // Save the document, closing the page and document. EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); @@ -280,6 +287,7 @@ TEST_F(FPDFAnnotEmbeddertest, AddAndSaveUnderlineAnnotation) { EXPECT_NEAR(quadpoints.x4, new_quadpoints.x4, 0.001f); EXPECT_NEAR(quadpoints.y4, new_quadpoints.y4, 0.001f); + FPDFPage_CloseAnnot(new_annot); FPDF_ClosePage(new_page); FPDF_CloseDocument(new_doc); } diff --git a/fpdfsdk/fpdfedit_embeddertest.cpp b/fpdfsdk/fpdfedit_embeddertest.cpp index f7bade9155..fcf7e3903b 100644 --- a/fpdfsdk/fpdfedit_embeddertest.cpp +++ b/fpdfsdk/fpdfedit_embeddertest.cpp @@ -900,8 +900,7 @@ TEST_F(FPDFEditEmbeddertest, TransformAnnot) { ASSERT_TRUE(page); // Add an underline annotation to the page without specifying its rectangle. - FPDF_ANNOTATION annot; - ASSERT_TRUE(FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE, &annot)); + ASSERT_TRUE(FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE, nullptr)); // FPDFPage_TransformAnnots() should run without errors when modifying // annotation rectangles. diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp index 6eafdee407..68ef377dc8 100644 --- a/fpdfsdk/fpdfview.cpp +++ b/fpdfsdk/fpdfview.cpp @@ -305,14 +305,6 @@ CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) { #endif // PDF_ENABLE_XFA } -FPDF_ANNOTATION FPDFAnnotationFromCPDFDictionary(CPDF_Dictionary* pDict) { - return static_cast(pDict); -} - -CPDF_Dictionary* CPDFDictionaryFromFPDFAnnotation(FPDF_ANNOTATION annot) { - return static_cast(annot); -} - CPDF_PathObject* CPDFPathObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object) { return static_cast(page_object); } diff --git a/fpdfsdk/fpdfview_c_api_test.c b/fpdfsdk/fpdfview_c_api_test.c index c8fdc47b51..0deaf9db1e 100644 --- a/fpdfsdk/fpdfview_c_api_test.c +++ b/fpdfsdk/fpdfview_c_api_test.c @@ -39,6 +39,7 @@ int CheckPDFiumCApi() { CHK(FPDFPage_CreateAnnot); CHK(FPDFPage_GetAnnotCount); CHK(FPDFPage_GetAnnot); + CHK(FPDFPage_CloseAnnot); CHK(FPDFAnnot_GetSubtype); CHK(FPDFAnnot_SetColor); CHK(FPDFAnnot_GetColor); diff --git a/public/fpdf_annot.h b/public/fpdf_annot.h index adfddec566..bd18898695 100644 --- a/public/fpdf_annot.h +++ b/public/fpdf_annot.h @@ -97,6 +97,13 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GetAnnot(FPDF_PAGE page, int index, FPDF_ANNOTATION* annot); +// Close an annotation. Must be called when the annotation returned by +// FPDFPage_CreateAnnot() or FPDFPage_GetAnnot() is no longer needed. This +// function does not remove the annotation from the document. +// +// annot - handle to an annotation. +DLLEXPORT void STDCALL FPDFPage_CloseAnnot(FPDF_ANNOTATION annot); + // Get the subtype of an annotation. // // annot - handle to an annotation. -- cgit v1.2.3