summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenrique Nakashima <hnakashima@chromium.org>2018-03-15 15:25:16 +0000
committerChromium commit bot <commit-bot@chromium.org>2018-03-15 15:25:16 +0000
commit35841fa4e3dbf8f9146f78def048c4a287894a8a (patch)
tree2252389ad952f6bdb0c9a55b6441f3b195e38ff3
parentd14dd4316d04f0982c340ad25bb283198a4d5c32 (diff)
downloadpdfium-35841fa4e3dbf8f9146f78def048c4a287894a8a.tar.xz
Create FPDFPage_RemoveObject().
This call removes a page object from a page. We currently offer an API to insert these objects, but not to remove. Bug: pdfium:1037 Change-Id: I35ff596f9e7c87a39051f0cb1de40a5bec40fee5 Reviewed-on: https://pdfium-review.googlesource.com/28492 Reviewed-by: dsinclair <dsinclair@chromium.org> Commit-Queue: Henrique Nakashima <hnakashima@chromium.org>
-rw-r--r--core/fpdfapi/page/cpdf_page.cpp14
-rw-r--r--core/fpdfapi/page/cpdf_page.h1
-rw-r--r--fpdfsdk/fpdfannot_embeddertest.cpp6
-rw-r--r--fpdfsdk/fpdfedit_embeddertest.cpp90
-rw-r--r--fpdfsdk/fpdfeditpage.cpp19
-rw-r--r--fpdfsdk/fpdfview_c_api_test.c1
-rw-r--r--public/fpdf_edit.h13
7 files changed, 144 insertions, 0 deletions
diff --git a/core/fpdfapi/page/cpdf_page.cpp b/core/fpdfapi/page/cpdf_page.cpp
index ba93f4a7d3..0c8d63de71 100644
--- a/core/fpdfapi/page/cpdf_page.cpp
+++ b/core/fpdfapi/page/cpdf_page.cpp
@@ -180,6 +180,20 @@ int CPDF_Page::GetPageRotation() const {
return (rotate < 0) ? (rotate + 4) : rotate;
}
+bool CPDF_Page::RemoveObject(CPDF_PageObject* pPageObj) {
+ pdfium::FakeUniquePtr<CPDF_PageObject> p(pPageObj);
+
+ auto* pPageObjectList = GetPageObjectList();
+ auto it =
+ std::find(std::begin(*pPageObjectList), std::end(*pPageObjectList), p);
+ if (it == std::end(*pPageObjectList))
+ return false;
+
+ it->release();
+ pPageObjectList->erase(it);
+ return true;
+}
+
bool GraphicsData::operator<(const GraphicsData& other) const {
if (fillAlpha != other.fillAlpha)
return fillAlpha < other.fillAlpha;
diff --git a/core/fpdfapi/page/cpdf_page.h b/core/fpdfapi/page/cpdf_page.h
index c7aa12e474..995d99cf4e 100644
--- a/core/fpdfapi/page/cpdf_page.h
+++ b/core/fpdfapi/page/cpdf_page.h
@@ -54,6 +54,7 @@ class CPDF_Page : public CPDF_PageObjectHolder {
View* GetView() const { return m_pView; }
void SetView(View* pView) { m_pView = pView; }
+ bool RemoveObject(CPDF_PageObject* pPageObj);
private:
void StartParse();
diff --git a/fpdfsdk/fpdfannot_embeddertest.cpp b/fpdfsdk/fpdfannot_embeddertest.cpp
index 70e184dd41..4e32b19ff9 100644
--- a/fpdfsdk/fpdfannot_embeddertest.cpp
+++ b/fpdfsdk/fpdfannot_embeddertest.cpp
@@ -575,6 +575,7 @@ TEST_F(FPDFAnnotEmbeddertest, AddAndModifyPath) {
// Check that this annotation has one path object and retrieve it.
EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
+ ASSERT_EQ(32, FPDFPage_CountObjects(page));
FPDF_PAGEOBJECT path = FPDFAnnot_GetObject(annot.get(), 1);
EXPECT_FALSE(path);
path = FPDFAnnot_GetObject(annot.get(), 0);
@@ -601,6 +602,10 @@ TEST_F(FPDFAnnotEmbeddertest, AddAndModifyPath) {
EXPECT_TRUE(FPDFAnnot_AppendObject(annot.get(), dot));
EXPECT_EQ(2, FPDFAnnot_GetObjectCount(annot.get()));
+ // The object is in the annontation, not in the page, so the page object
+ // array should not change.
+ ASSERT_EQ(32, FPDFPage_CountObjects(page));
+
// Check that the page with an annotation with two paths renders correctly.
{
std::unique_ptr<void, FPDFBitmapDeleter> bitmap =
@@ -611,6 +616,7 @@ TEST_F(FPDFAnnotEmbeddertest, AddAndModifyPath) {
// Delete the newly added path object.
EXPECT_TRUE(FPDFAnnot_RemoveObject(annot.get(), 1));
EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot.get()));
+ ASSERT_EQ(32, FPDFPage_CountObjects(page));
}
// Check that the page renders the same as before.
diff --git a/fpdfsdk/fpdfedit_embeddertest.cpp b/fpdfsdk/fpdfedit_embeddertest.cpp
index 3fc6cae8b4..ec403c74b3 100644
--- a/fpdfsdk/fpdfedit_embeddertest.cpp
+++ b/fpdfsdk/fpdfedit_embeddertest.cpp
@@ -381,6 +381,96 @@ TEST_F(FPDFEditEmbeddertest, AddPaths) {
VerifySavedDocument(612, 792, kLastMD5);
}
+TEST_F(FPDFEditEmbeddertest, RemovePageObject) {
+ // Load document with some text.
+ EXPECT_TRUE(OpenDocument("hello_world.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+// Show how the original file looks like.
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char kOriginalMD5[] = "b90475ca64d1348c3bf5e2b77ad9187a";
+#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
+ const char kOriginalMD5[] = "e5a6fa28298db07484cd922f3e210c88";
+#else
+ const char kOriginalMD5[] = "2baa4c0e1758deba1b9c908e1fbd04ed";
+#endif
+ {
+ std::unique_ptr<void, FPDFBitmapDeleter> page_bitmap =
+ RenderPageWithFlags(page, nullptr, 0);
+ CompareBitmap(page_bitmap.get(), 200, 200, kOriginalMD5);
+ }
+
+ // Get the "Hello, world!" text object and remove it.
+ ASSERT_EQ(2, FPDFPage_CountObjects(page));
+ FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 0);
+ ASSERT_TRUE(page_object);
+ EXPECT_TRUE(FPDFPage_RemoveObject(page, page_object));
+
+// Verify the "Hello, world!" text is gone.
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char kRemovedMD5[] = "af760c4702467cb1492a57fb8215efaa";
+#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
+ const char kRemovedMD5[] = "72be917349bf7004a5c39661fe1fc433";
+#else
+ const char kRemovedMD5[] = "b76df015fe88009c3c342395df96abf1";
+#endif
+ {
+ std::unique_ptr<void, FPDFBitmapDeleter> page_bitmap =
+ RenderPageWithFlags(page, nullptr, 0);
+ CompareBitmap(page_bitmap.get(), 200, 200, kRemovedMD5);
+ }
+ ASSERT_EQ(1, FPDFPage_CountObjects(page));
+
+ UnloadPage(page);
+ FPDFPageObj_Destroy(page_object);
+}
+
+TEST_F(FPDFEditEmbeddertest, AddAndRemovePaths) {
+ // Start with a blank page.
+ FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
+ ASSERT_TRUE(page);
+
+ // Render the blank page and verify it's a blank bitmap.
+ const char kBlankMD5[] = "1940568c9ba33bac5d0b1ee9558c76b3";
+ {
+ std::unique_ptr<void, FPDFBitmapDeleter> page_bitmap =
+ RenderPageWithFlags(page, nullptr, 0);
+ CompareBitmap(page_bitmap.get(), 612, 792, kBlankMD5);
+ }
+ ASSERT_EQ(0, FPDFPage_CountObjects(page));
+
+ // Add a red rectangle.
+ FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
+ ASSERT_TRUE(red_rect);
+ EXPECT_TRUE(FPDFPath_SetFillColor(red_rect, 255, 0, 0, 255));
+ EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
+ FPDFPage_InsertObject(page, red_rect);
+ const char kRedRectangleMD5[] = "66d02eaa6181e2c069ce2ea99beda497";
+ {
+ std::unique_ptr<void, FPDFBitmapDeleter> page_bitmap =
+ RenderPageWithFlags(page, nullptr, 0);
+ CompareBitmap(page_bitmap.get(), 612, 792, kRedRectangleMD5);
+ }
+ EXPECT_EQ(1, FPDFPage_CountObjects(page));
+
+ // Remove rectangle and verify it does not render anymore and the bitmap is
+ // back to a blank one.
+ EXPECT_TRUE(FPDFPage_RemoveObject(page, red_rect));
+ {
+ std::unique_ptr<void, FPDFBitmapDeleter> page_bitmap =
+ RenderPageWithFlags(page, nullptr, 0);
+ CompareBitmap(page_bitmap.get(), 612, 792, kBlankMD5);
+ }
+ EXPECT_EQ(0, FPDFPage_CountObjects(page));
+
+ // Trying to remove an object not in the page should return false.
+ EXPECT_FALSE(FPDFPage_RemoveObject(page, red_rect));
+
+ FPDF_ClosePage(page);
+ FPDFPageObj_Destroy(red_rect);
+}
+
TEST_F(FPDFEditEmbeddertest, PathsPoints) {
CreateNewDocument();
FPDF_PAGEOBJECT img = FPDFPageObj_NewImageObj(document_);
diff --git a/fpdfsdk/fpdfeditpage.cpp b/fpdfsdk/fpdfeditpage.cpp
index ca2cf3fb6e..800613348b 100644
--- a/fpdfsdk/fpdfeditpage.cpp
+++ b/fpdfsdk/fpdfeditpage.cpp
@@ -174,10 +174,25 @@ FPDF_EXPORT void FPDF_CALLCONV FPDFPage_InsertObject(FPDF_PAGE page,
if (!IsPageObject(pPage))
return;
pPageObj->SetDirty(true);
+
+ // TODO(hnakashima): Move into CPDF_Page.
pPage->GetPageObjectList()->push_back(std::move(pPageObjHolder));
CalcBoundingBox(pPageObj);
}
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPage_RemoveObject(FPDF_PAGE page, FPDF_PAGEOBJECT page_obj) {
+ CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(page_obj);
+ if (!pPageObj)
+ return false;
+
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!IsPageObject(pPage))
+ return false;
+
+ return pPage->RemoveObject(pPageObj);
+}
+
FPDF_EXPORT int FPDF_CALLCONV FPDFPage_CountObject(FPDF_PAGE page) {
return FPDFPage_CountObjects(page);
}
@@ -186,6 +201,8 @@ FPDF_EXPORT int FPDF_CALLCONV FPDFPage_CountObjects(FPDF_PAGE page) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!IsPageObject(pPage))
return -1;
+
+ // TODO(hnakashima): Move into CPDF_Page.
return pdfium::CollectionSize<int>(*pPage->GetPageObjectList());
}
@@ -194,6 +211,8 @@ FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV FPDFPage_GetObject(FPDF_PAGE page,
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!IsPageObject(pPage))
return nullptr;
+
+ // TODO(hnakashima): Move into CPDF_Page.
return pPage->GetPageObjectList()->GetPageObjectByIndex(index);
}
diff --git a/fpdfsdk/fpdfview_c_api_test.c b/fpdfsdk/fpdfview_c_api_test.c
index 193050e84a..2a0b230ca5 100644
--- a/fpdfsdk/fpdfview_c_api_test.c
+++ b/fpdfsdk/fpdfview_c_api_test.c
@@ -129,6 +129,7 @@ int CheckPDFiumCApi() {
CHK(FPDFPage_GetRotation);
CHK(FPDFPage_SetRotation);
CHK(FPDFPage_InsertObject);
+ CHK(FPDFPage_RemoveObject);
CHK(FPDFPage_CountObject);
CHK(FPDFPage_CountObjects);
CHK(FPDFPage_GetObject);
diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h
index 54735a3bde..1e84e8f7ff 100644
--- a/public/fpdf_edit.h
+++ b/public/fpdf_edit.h
@@ -148,6 +148,19 @@ FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetRotation(FPDF_PAGE page, int rotate);
FPDF_EXPORT void FPDF_CALLCONV FPDFPage_InsertObject(FPDF_PAGE page,
FPDF_PAGEOBJECT page_obj);
+// Experimental API.
+// Remove |page_obj| from |page|.
+//
+// page - handle to a page
+// page_obj - handle to a page object to be removed.
+//
+// Returns TRUE on success.
+//
+// Ownership is transferred to the caller. Call FPDFPageObj_Destroy() to free
+// it.
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPage_RemoveObject(FPDF_PAGE page, FPDF_PAGEOBJECT page_obj);
+
// Get number of page objects inside |page|.
//
// page - handle to a page.