From 144107d3ca6ddd2724a460c4da4a20e6e1b7f1b7 Mon Sep 17 00:00:00 2001 From: Henrique Nakashima Date: Tue, 10 Jul 2018 21:04:05 +0000 Subject: Create API for adding content marks and setting their params. This CL creates the following new functions in the public API: - FPDFPageObj_AddMark - FPDFPageObjMark_SetIntParam - FPDFPageObjMark_SetStringParam Bug: pdfium:1037 Change-Id: Icabf3fdd8e8153b9156bab807a3708d38a9365d8 Reviewed-on: https://pdfium-review.googlesource.com/37330 Commit-Queue: Henrique Nakashima Reviewed-by: Lei Zhang --- fpdfsdk/cpdfsdk_helpers.h | 6 +-- fpdfsdk/fpdf_edit_embeddertest.cpp | 77 ++++++++++++++++++++++++++++++++++++++ fpdfsdk/fpdf_editpage.cpp | 64 ++++++++++++++++++++++++++++++- fpdfsdk/fpdf_view_c_api_test.c | 3 ++ 4 files changed, 146 insertions(+), 4 deletions(-) (limited to 'fpdfsdk') diff --git a/fpdfsdk/cpdfsdk_helpers.h b/fpdfsdk/cpdfsdk_helpers.h index 88e05302fe..4fd85cfc72 100644 --- a/fpdfsdk/cpdfsdk_helpers.h +++ b/fpdfsdk/cpdfsdk_helpers.h @@ -139,12 +139,12 @@ inline CPDF_PageObject* CPDFPageObjectFromFPDFPageObject( } inline FPDF_PAGEOBJECTMARK FPDFPageObjectMarkFromCPDFContentMarkItem( - const CPDF_ContentMarkItem* mark) { + CPDF_ContentMarkItem* mark) { return reinterpret_cast(mark); } -inline const CPDF_ContentMarkItem* CPDFContentMarkItemFromFPDFPageObjectMark( +inline CPDF_ContentMarkItem* CPDFContentMarkItemFromFPDFPageObjectMark( FPDF_PAGEOBJECTMARK mark) { - return reinterpret_cast(mark); + return reinterpret_cast(mark); } inline FPDF_PAGERANGE FPDFPageRangeFromCPDFArray(const CPDF_Array* range) { diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp index a490162e15..a9eca92a4e 100644 --- a/fpdfsdk/fpdf_edit_embeddertest.cpp +++ b/fpdfsdk/fpdf_edit_embeddertest.cpp @@ -2021,6 +2021,83 @@ TEST_F(FPDFEditEmbeddertest, SaveAndRender) { VerifySavedDocument(612, 792, md5); } +TEST_F(FPDFEditEmbeddertest, AddMarkedText) { + // Start with a blank page. + FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792); + + const CPDF_Font* stock_font = CPDF_Font::GetStockFont(cpdf_doc(), "Arial"); + const uint8_t* data = stock_font->GetFont()->GetFontData(); + const uint32_t size = stock_font->GetFont()->GetSize(); + ScopedFPDFFont font( + FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, 0)); + ASSERT_TRUE(font.get()); + + // Add some text to the page. + FPDF_PAGEOBJECT text_object = + FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f); + + EXPECT_TRUE(text_object); + std::unique_ptr text1 = + GetFPDFWideString(L"I am testing my loaded font, WEE."); + EXPECT_TRUE(FPDFText_SetText(text_object, text1.get())); + FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 400, 400); + FPDFPage_InsertObject(page, text_object); + + // Add a mark with the tag "TestMarkName" to that text. + EXPECT_EQ(0, FPDFPageObj_CountMarks(text_object)); + FPDF_PAGEOBJECTMARK mark = FPDFPageObj_AddMark(text_object, "TestMarkName"); + EXPECT_TRUE(mark); + EXPECT_EQ(1, FPDFPageObj_CountMarks(text_object)); + EXPECT_EQ(mark, FPDFPageObj_GetMark(text_object, 0)); + char buffer[256]; + EXPECT_GT(FPDFPageObjMark_GetName(mark, buffer, 256), 0u); + std::wstring name = + GetPlatformWString(reinterpret_cast(buffer)); + EXPECT_EQ(L"TestMarkName", name); + + // Add parameters: + // - int "IntKey" : 42 + // - string "StringKey": "StringValue" + EXPECT_EQ(0, FPDFPageObjMark_CountParams(mark)); + EXPECT_TRUE(FPDFPageObjMark_SetIntParam(document(), mark, "IntKey", 42)); + EXPECT_TRUE(FPDFPageObjMark_SetStringParam(document(), mark, "StringKey", + "StringValue")); + EXPECT_EQ(2, FPDFPageObjMark_CountParams(mark)); + + // Check the two parameters can be retrieved. + EXPECT_EQ(FPDF_OBJECT_NUMBER, + FPDFPageObjMark_GetParamValueTypeByKey(mark, "IntKey")); + int int_value; + EXPECT_TRUE( + FPDFPageObjMark_GetParamIntValueByKey(mark, "IntKey", &int_value)); + EXPECT_EQ(42, int_value); + + EXPECT_EQ(FPDF_OBJECT_STRING, + FPDFPageObjMark_GetParamValueTypeByKey(mark, "StringKey")); + unsigned long out_buffer_len; + EXPECT_TRUE(FPDFPageObjMark_GetParamStringValueByKey( + mark, "StringKey", buffer, 256, &out_buffer_len)); + EXPECT_GT(out_buffer_len, 0u); + name = GetPlatformWString(reinterpret_cast(buffer)); + EXPECT_EQ(L"StringValue", name); + +// Render and check the bitmap is the expected one. +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5[] = "17d2b6cd574cf66170b09c8927529a94"; +#else + const char md5[] = "70592859010ffbf532a2237b8118bcc4"; +#endif + { + ScopedFPDFBitmap page_bitmap = RenderPageWithFlags(page, nullptr, 0); + CompareBitmap(page_bitmap.get(), 612, 792, md5); + } + + FPDF_ClosePage(page); + + // TODO(pdfium:1118): Save, then re-open the file and check the changes were + // kept in the saved .pdf. +} + TEST_F(FPDFEditEmbeddertest, ExtractImageBitmap) { ASSERT_TRUE(OpenDocument("embedded_images.pdf")); FPDF_PAGE page = LoadPage(0); diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp index d275559107..8a1200885a 100644 --- a/fpdfsdk/fpdf_editpage.cpp +++ b/fpdfsdk/fpdf_editpage.cpp @@ -125,6 +125,30 @@ GetMarkParamPairAtIndex(FPDF_PAGEOBJECTMARK mark, unsigned long index) { return nullptr; } +CPDF_Dictionary* GetOrCreateMarkParamsDict(FPDF_DOCUMENT document, + FPDF_PAGEOBJECTMARK mark) { + CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); + if (!pDoc) + return nullptr; + + CPDF_ContentMarkItem* pMarkItem = + CPDFContentMarkItemFromFPDFPageObjectMark(mark); + if (!pMarkItem) + return nullptr; + + CPDF_Dictionary* pParams = pMarkItem->GetParam(); + + // If the Params dict does not exist, create a new one. + if (!pParams) { + auto new_dict = + pdfium::MakeUnique(pDoc->GetByteStringPool()); + pParams = new_dict.get(); + pMarkItem->SetDirectDict(std::move(new_dict)); + } + + return pParams; +} + unsigned int GetUnsignedAlpha(float alpha) { return static_cast(alpha * 255.f + 0.5f); } @@ -293,7 +317,19 @@ FPDFPageObj_GetMark(FPDF_PAGEOBJECT page_object, unsigned long index) { if (index >= mark->CountItems()) return nullptr; - return FPDFPageObjectMarkFromCPDFContentMarkItem(&mark->GetItem(index)); + return FPDFPageObjectMarkFromCPDFContentMarkItem(mark->GetItem(index)); +} + +FPDF_EXPORT FPDF_PAGEOBJECTMARK FPDF_CALLCONV +FPDFPageObj_AddMark(FPDF_PAGEOBJECT page_object, FPDF_BYTESTRING name) { + if (!page_object) + return nullptr; + + auto* mark = &CPDFPageObjectFromFPDFPageObject(page_object)->m_ContentMark; + mark->AddMark(name, nullptr, true); + unsigned long index = mark->CountItems() - 1; + + return FPDFPageObjectMarkFromCPDFContentMarkItem(mark->GetItem(index)); } FPDF_EXPORT unsigned long FPDF_CALLCONV @@ -456,6 +492,32 @@ FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT pageObject) { return false; } +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPageObjMark_SetIntParam(FPDF_DOCUMENT document, + FPDF_PAGEOBJECTMARK mark, + FPDF_BYTESTRING key, + int value) { + CPDF_Dictionary* pParams = GetOrCreateMarkParamsDict(document, mark); + if (!pParams) + return false; + + pParams->SetNewFor(key, value); + return true; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPageObjMark_SetStringParam(FPDF_DOCUMENT document, + FPDF_PAGEOBJECTMARK mark, + FPDF_BYTESTRING key, + FPDF_BYTESTRING value) { + CPDF_Dictionary* pParams = GetOrCreateMarkParamsDict(document, mark); + if (!pParams) + return false; + + pParams->SetNewFor(key, value, false); + return true; +} + FPDF_EXPORT int FPDF_CALLCONV FPDFPageObj_GetType(FPDF_PAGEOBJECT pageObject) { if (!pageObject) return FPDF_PAGEOBJ_UNKNOWN; diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c index 51b5884e80..53d5a77cfd 100644 --- a/fpdfsdk/fpdf_view_c_api_test.c +++ b/fpdfsdk/fpdf_view_c_api_test.c @@ -145,6 +145,9 @@ int CheckPDFiumCApi() { CHK(FPDFPageObjMark_GetParamStringValueByKey); CHK(FPDFPageObjMark_GetParamValueType); CHK(FPDFPageObjMark_GetParamValueTypeByKey); + CHK(FPDFPageObjMark_SetIntParam); + CHK(FPDFPageObjMark_SetStringParam); + CHK(FPDFPageObj_AddMark); CHK(FPDFPageObj_CountMarks); CHK(FPDFPageObj_CreateNewPath); CHK(FPDFPageObj_CreateNewRect); -- cgit v1.2.3