From fed4adb003db228ac7fbc0510a21c25b50ae0cab Mon Sep 17 00:00:00 2001 From: Henrique Nakashima Date: Fri, 13 Jul 2018 19:47:22 +0000 Subject: Create API to remove a content mark from a page object. - FPDFPageObj_RemoveMark() Bug: pdfium:1037 Change-Id: I7ff320261d64e3ead45375ccc72301e7c64dd6e3 Reviewed-on: https://pdfium-review.googlesource.com/37710 Reviewed-by: Lei Zhang Commit-Queue: Henrique Nakashima --- core/fpdfapi/page/cpdf_contentmark.cpp | 14 ++++++++++ core/fpdfapi/page/cpdf_contentmark.h | 2 ++ fpdfsdk/fpdf_edit_embeddertest.cpp | 49 ++++++++++++++++++++++++++++++++++ fpdfsdk/fpdf_editpage.cpp | 15 +++++++++++ fpdfsdk/fpdf_view_c_api_test.c | 1 + public/fpdf_edit.h | 11 ++++++++ 6 files changed, 92 insertions(+) diff --git a/core/fpdfapi/page/cpdf_contentmark.cpp b/core/fpdfapi/page/cpdf_contentmark.cpp index 4932ee6231..615d31f3eb 100644 --- a/core/fpdfapi/page/cpdf_contentmark.cpp +++ b/core/fpdfapi/page/cpdf_contentmark.cpp @@ -73,6 +73,10 @@ void CPDF_ContentMark::AddMarkWithPropertiesDict( m_pMarkData->AddMarkWithPropertiesDict(std::move(name), pDict, property_name); } +bool CPDF_ContentMark::RemoveMark(CPDF_ContentMarkItem* pMarkItem) { + return m_pMarkData && m_pMarkData->RemoveMark(pMarkItem); +} + void CPDF_ContentMark::EnsureMarkDataExists() { if (!m_pMarkData) m_pMarkData = pdfium::MakeRetain(); @@ -160,6 +164,16 @@ void CPDF_ContentMark::MarkData::AddMarkWithPropertiesDict( m_Marks.push_back(pItem); } +bool CPDF_ContentMark::MarkData::RemoveMark(CPDF_ContentMarkItem* pMarkItem) { + for (auto it = m_Marks.begin(); it != m_Marks.end(); ++it) { + if (it->Get() == pMarkItem) { + m_Marks.erase(it); + return true; + } + } + return false; +} + void CPDF_ContentMark::MarkData::DeleteLastMark() { if (!m_Marks.empty()) m_Marks.pop_back(); diff --git a/core/fpdfapi/page/cpdf_contentmark.h b/core/fpdfapi/page/cpdf_contentmark.h index 8dc98370e6..4f678aff8e 100644 --- a/core/fpdfapi/page/cpdf_contentmark.h +++ b/core/fpdfapi/page/cpdf_contentmark.h @@ -35,6 +35,7 @@ class CPDF_ContentMark { void AddMarkWithPropertiesDict(ByteString name, CPDF_Dictionary* pDict, const ByteString& property_name); + bool RemoveMark(CPDF_ContentMarkItem* pMarkItem); void DeleteLastMark(); size_t FindFirstDifference(const CPDF_ContentMark* other) const; @@ -56,6 +57,7 @@ class CPDF_ContentMark { void AddMarkWithPropertiesDict(ByteString name, CPDF_Dictionary* pDict, const ByteString& property_name); + bool RemoveMark(CPDF_ContentMarkItem* pMarkItem); void DeleteLastMark(); private: diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp index ba790de654..9a03a4d5c8 100644 --- a/fpdfsdk/fpdf_edit_embeddertest.cpp +++ b/fpdfsdk/fpdf_edit_embeddertest.cpp @@ -692,6 +692,55 @@ TEST_F(FPDFEditEmbeddertest, RemoveMarkedObjectsPrime) { UnloadPage(page); } +TEST_F(FPDFEditEmbeddertest, RemoveMarks) { + // Load document with some text. + EXPECT_TRUE(OpenDocument("text_in_page_marked.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + constexpr int kExpectedObjectCount = 19; + CheckMarkCounts(page, 1, kExpectedObjectCount, 8, 4, 9, 1); + + // Remove all "Prime" content marks. + for (int i = 0; i < kExpectedObjectCount; ++i) { + FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i); + + int mark_count = FPDFPageObj_CountMarks(page_object); + for (int j = mark_count - 1; j >= 0; --j) { + FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j); + + char buffer[256]; + ASSERT_GT(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer)), 0u); + std::wstring name = + GetPlatformWString(reinterpret_cast(buffer)); + if (name == L"Prime") { + // Remove mark. + EXPECT_TRUE(FPDFPageObj_RemoveMark(page_object, mark)); + + // Verify there is now one fewer mark in the page object. + EXPECT_EQ(mark_count - 1, FPDFPageObj_CountMarks(page_object)); + } + } + } + + // Verify there are 0 "Prime" content marks now. + CheckMarkCounts(page, 1, kExpectedObjectCount, 0, 4, 9, 1); + + // Save the file. + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + UnloadPage(page); + + // Re-open the file and check the prime marks are not there anymore. + OpenSavedDocument(); + FPDF_PAGE saved_page = LoadSavedPage(0); + + CheckMarkCounts(saved_page, 1, kExpectedObjectCount, 0, 4, 9, 1); + + CloseSavedPage(saved_page); + CloseSavedDocument(); +} + TEST_F(FPDFEditEmbeddertest, MaintainMarkedObjects) { // Load document with some text. EXPECT_TRUE(OpenDocument("text_in_page_marked.pdf")); diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp index 3abdcdf0fc..808e330225 100644 --- a/fpdfsdk/fpdf_editpage.cpp +++ b/fpdfsdk/fpdf_editpage.cpp @@ -326,6 +326,21 @@ FPDFPageObj_AddMark(FPDF_PAGEOBJECT page_object, FPDF_BYTESTRING name) { return FPDFPageObjectMarkFromCPDFContentMarkItem(mark->GetItem(index)); } +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPageObj_RemoveMark(FPDF_PAGEOBJECT page_object, FPDF_PAGEOBJECTMARK mark) { + CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(page_object); + CPDF_ContentMarkItem* pMarkItem = + CPDFContentMarkItemFromFPDFPageObjectMark(mark); + if (!pPageObj || !pMarkItem) + return false; + + bool result = pPageObj->m_ContentMark.RemoveMark(pMarkItem); + if (result) + pPageObj->SetDirty(true); + + return result; +} + FPDF_EXPORT unsigned long FPDF_CALLCONV FPDFPageObjMark_GetName(FPDF_PAGEOBJECTMARK mark, void* buffer, diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c index a89bc2e775..96c9bfe289 100644 --- a/fpdfsdk/fpdf_view_c_api_test.c +++ b/fpdfsdk/fpdf_view_c_api_test.c @@ -162,6 +162,7 @@ int CheckPDFiumCApi() { CHK(FPDFPageObj_HasTransparency); CHK(FPDFPageObj_NewImageObj); CHK(FPDFPageObj_NewTextObj); + CHK(FPDFPageObj_RemoveMark); CHK(FPDFPageObj_SetBlendMode); CHK(FPDFPageObj_SetFillColor); CHK(FPDFPageObj_SetLineCap); diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h index e71b4edb94..e18f1cd260 100644 --- a/public/fpdf_edit.h +++ b/public/fpdf_edit.h @@ -329,6 +329,17 @@ FPDFPageObj_GetMark(FPDF_PAGEOBJECT page_object, unsigned long index); FPDF_EXPORT FPDF_PAGEOBJECTMARK FPDF_CALLCONV FPDFPageObj_AddMark(FPDF_PAGEOBJECT page_object, FPDF_BYTESTRING name); +// Experimental API. +// Removes a content |mark| from a |page_object|. +// The mark handle will be invalid after the removal. +// +// page_object - handle to a page object. +// mark - handle to a content mark in that object to remove. +// +// Returns TRUE if the operation succeeded, FALSE if it failed. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPageObj_RemoveMark(FPDF_PAGEOBJECT page_object, FPDF_PAGEOBJECTMARK mark); + // Experimental API. // Get name of a content mark. |buffer| is only modified if |buflen| is longer // than the length of the name. -- cgit v1.2.3