From e858aa4b70db7408bda1aed71827d9eee1dd98c5 Mon Sep 17 00:00:00 2001 From: wileyrya Date: Wed, 31 May 2017 14:49:05 -0500 Subject: Fix content generation to only generate dirty page objects. BUG=pdfium:717 R=dsinclair@chromium.org,thestig@chromium.org Change-Id: I7e0e6fd301d40f9b5341d40cf11167b7748af243 Reviewed-on: https://pdfium-review.googlesource.com/6071 Reviewed-by: dsinclair Reviewed-by: Lei Zhang Commit-Queue: dsinclair --- fpdfsdk/fpdfedit_embeddertest.cpp | 84 +++++++++++++++++++++++++++++++++++++++ fpdfsdk/fpdfeditimg.cpp | 4 +- fpdfsdk/fpdfeditpage.cpp | 66 ++++++++++++++++-------------- fpdfsdk/fpdfeditpath.cpp | 9 +++++ 4 files changed, 132 insertions(+), 31 deletions(-) (limited to 'fpdfsdk') diff --git a/fpdfsdk/fpdfedit_embeddertest.cpp b/fpdfsdk/fpdfedit_embeddertest.cpp index 6045618411..f52848c81d 100644 --- a/fpdfsdk/fpdfedit_embeddertest.cpp +++ b/fpdfsdk/fpdfedit_embeddertest.cpp @@ -368,6 +368,90 @@ TEST_F(FPDFEditEmbeddertest, PathOnTopOfText) { UnloadPage(page); } +TEST_F(FPDFEditEmbeddertest, EditOverExistingContent) { + // Load document with existing content + EXPECT_TRUE(OpenDocument("bug_717.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_NE(nullptr, page); + + // Add a transparent rectangle on top of the existing content + FPDF_PAGEOBJECT red_rect2 = FPDFPageObj_CreateNewRect(90, 700, 25, 50); + EXPECT_TRUE(FPDFPath_SetFillColor(red_rect2, 255, 0, 0, 100)); + EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect2, FPDF_FILLMODE_ALTERNATE, 0)); + FPDFPage_InsertObject(page, red_rect2); + + // Add an opaque rectangle on top of the existing content + FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(115, 700, 25, 50); + 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); + + FPDF_BITMAP bitmap = RenderPage(page); + CompareBitmap(bitmap, 612, 792, "ad04e5bd0f471a9a564fb034bd0fb073"); + FPDFBitmap_Destroy(bitmap); + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + + // Now save the result, closing the page and document + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + FPDF_ClosePage(page); + + // Render the saved result + std::string new_file = GetString(); + FPDF_FILEACCESS file_access; + memset(&file_access, 0, sizeof(file_access)); + file_access.m_FileLen = new_file.size(); + file_access.m_GetBlock = GetBlockFromString; + file_access.m_Param = &new_file; + FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr); + ASSERT_NE(nullptr, new_doc); + EXPECT_EQ(1, FPDF_GetPageCount(new_doc)); + FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0); + ASSERT_NE(nullptr, new_page); + FPDF_BITMAP new_bitmap = RenderPage(new_page); + CompareBitmap(new_bitmap, 612, 792, "ad04e5bd0f471a9a564fb034bd0fb073"); + FPDFBitmap_Destroy(new_bitmap); + + ClearString(); + // Add another opaque rectangle on top of the existing content + FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(150, 700, 25, 50); + EXPECT_TRUE(FPDFPath_SetFillColor(green_rect, 0, 255, 0, 255)); + EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_ALTERNATE, 0)); + FPDFPage_InsertObject(new_page, green_rect); + + // Add another transparent rectangle on top of existing content + FPDF_PAGEOBJECT green_rect2 = FPDFPageObj_CreateNewRect(175, 700, 25, 50); + EXPECT_TRUE(FPDFPath_SetFillColor(green_rect2, 0, 255, 0, 100)); + EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect2, FPDF_FILLMODE_ALTERNATE, 0)); + FPDFPage_InsertObject(new_page, green_rect2); + new_bitmap = RenderPage(new_page); + CompareBitmap(new_bitmap, 612, 792, "4b5b00f824620f8c9b8801ebb98e1cdd"); + FPDFBitmap_Destroy(new_bitmap); + EXPECT_TRUE(FPDFPage_GenerateContent(new_page)); + + // Now save the result, closing the page and document + EXPECT_TRUE(FPDF_SaveAsCopy(new_doc, this, 0)); + FPDF_ClosePage(new_page); + FPDF_CloseDocument(new_doc); + + // Render the saved result + new_file = GetString(); + memset(&file_access, 0, sizeof(file_access)); + file_access.m_FileLen = new_file.size(); + file_access.m_GetBlock = GetBlockFromString; + file_access.m_Param = &new_file; + new_doc = FPDF_LoadCustomDocument(&file_access, nullptr); + ASSERT_NE(nullptr, new_doc); + EXPECT_EQ(1, FPDF_GetPageCount(new_doc)); + new_page = FPDF_LoadPage(new_doc, 0); + ASSERT_NE(nullptr, new_page); + new_bitmap = RenderPage(new_page); + CompareBitmap(new_bitmap, 612, 792, "4b5b00f824620f8c9b8801ebb98e1cdd"); + FPDFBitmap_Destroy(new_bitmap); + + FPDF_ClosePage(new_page); + FPDF_CloseDocument(new_doc); +} + TEST_F(FPDFEditEmbeddertest, AddStrokedPaths) { // Start with a blank page FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792); diff --git a/fpdfsdk/fpdfeditimg.cpp b/fpdfsdk/fpdfeditimg.cpp index 9f4b2968ee..fdc98e06e9 100644 --- a/fpdfsdk/fpdfeditimg.cpp +++ b/fpdfsdk/fpdfeditimg.cpp @@ -39,7 +39,7 @@ bool LoadJpegHelper(FPDF_PAGE* pages, pImgObj->GetImage()->SetJpegImageInline(pFile); else pImgObj->GetImage()->SetJpegImage(pFile); - + pImgObj->SetDirty(true); return true; } @@ -87,6 +87,7 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object, static_cast(c), static_cast(d), static_cast(e), static_cast(f))); pImgObj->CalcBoundingBox(); + pImgObj->SetDirty(true); return true; } @@ -106,5 +107,6 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFImageObj_SetBitmap(FPDF_PAGE* pages, CFX_RetainPtr holder(CFXBitmapFromFPDFBitmap(bitmap)); pImgObj->GetImage()->SetImage(holder); pImgObj->CalcBoundingBox(); + pImgObj->SetDirty(true); return true; } diff --git a/fpdfsdk/fpdfeditpage.cpp b/fpdfsdk/fpdfeditpage.cpp index a474414435..da156cd790 100644 --- a/fpdfsdk/fpdfeditpage.cpp +++ b/fpdfsdk/fpdfeditpage.cpp @@ -61,6 +61,38 @@ bool IsPageObject(CPDF_Page* pPage) { return pObject && !pObject->GetString().Compare("Page"); } +void CalcBoundingBox(CPDF_PageObject* pPageObj) { + switch (pPageObj->GetType()) { + case CPDF_PageObject::TEXT: { + break; + } + case CPDF_PageObject::PATH: { + CPDF_PathObject* pPathObj = pPageObj->AsPath(); + pPathObj->CalcBoundingBox(); + break; + } + case CPDF_PageObject::IMAGE: { + CPDF_ImageObject* pImageObj = pPageObj->AsImage(); + pImageObj->CalcBoundingBox(); + break; + } + case CPDF_PageObject::SHADING: { + CPDF_ShadingObject* pShadingObj = pPageObj->AsShading(); + pShadingObj->CalcBoundingBox(); + break; + } + case CPDF_PageObject::FORM: { + CPDF_FormObject* pFormObj = pPageObj->AsForm(); + pFormObj->CalcBoundingBox(); + break; + } + default: { + NOTREACHED(); + break; + } + } +} + } // namespace DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_CreateNewDocument() { @@ -144,37 +176,9 @@ DLLEXPORT void STDCALL FPDFPage_InsertObject(FPDF_PAGE page, CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!IsPageObject(pPage)) return; - + pPageObj->SetDirty(true); pPage->GetPageObjectList()->push_back(std::move(pPageObjHolder)); - switch (pPageObj->GetType()) { - case CPDF_PageObject::TEXT: { - break; - } - case CPDF_PageObject::PATH: { - CPDF_PathObject* pPathObj = pPageObj->AsPath(); - pPathObj->CalcBoundingBox(); - break; - } - case CPDF_PageObject::IMAGE: { - CPDF_ImageObject* pImageObj = pPageObj->AsImage(); - pImageObj->CalcBoundingBox(); - break; - } - case CPDF_PageObject::SHADING: { - CPDF_ShadingObject* pShadingObj = pPageObj->AsShading(); - pShadingObj->CalcBoundingBox(); - break; - } - case CPDF_PageObject::FORM: { - CPDF_FormObject* pFormObj = pPageObj->AsForm(); - pFormObj->CalcBoundingBox(); - break; - } - default: { - NOTREACHED(); - break; - } - } + CalcBoundingBox(pPageObj); } DLLEXPORT int STDCALL FPDFPage_CountObject(FPDF_PAGE page) { @@ -271,6 +275,7 @@ DLLEXPORT void STDCALL FPDFPageObj_SetBlendMode(FPDF_PAGEOBJECT page_object, return; pPageObj->m_GeneralState.SetBlendMode(blend_mode); + pPageObj->SetDirty(true); } DLLEXPORT void STDCALL FPDFPage_TransformAnnots(FPDF_PAGE page, @@ -327,6 +332,7 @@ FPDF_BOOL FPDFPageObj_SetFillColor(FPDF_PAGEOBJECT page_object, pPageObj->m_GeneralState.SetFillAlpha(A / 255.f); pPageObj->m_ColorState.SetFillColor( CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3); + pPageObj->SetDirty(true); return true; } diff --git a/fpdfsdk/fpdfeditpath.cpp b/fpdfsdk/fpdfeditpath.cpp index ad5ca9433f..f58d1e18a9 100644 --- a/fpdfsdk/fpdfeditpath.cpp +++ b/fpdfsdk/fpdfeditpath.cpp @@ -40,6 +40,7 @@ DLLEXPORT FPDF_BOOL FPDFPath_SetStrokeColor(FPDF_PAGEOBJECT path, pPathObj->m_GeneralState.SetStrokeAlpha(A / 255.f); pPathObj->m_ColorState.SetStrokeColor( CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3); + pPathObj->SetDirty(true); return true; } @@ -49,6 +50,7 @@ DLLEXPORT FPDF_BOOL FPDFPath_SetStrokeWidth(FPDF_PAGEOBJECT path, float width) { auto* pPathObj = static_cast(path); pPathObj->m_GraphState.SetLineWidth(width); + pPathObj->SetDirty(true); return true; } @@ -84,6 +86,7 @@ DLLEXPORT FPDF_BOOL FPDFPath_MoveTo(FPDF_PAGEOBJECT path, float x, float y) { auto* pPathObj = static_cast(path); pPathObj->m_Path.AppendPoint(CFX_PointF(x, y), FXPT_TYPE::MoveTo, false); + pPathObj->SetDirty(true); return true; } @@ -93,6 +96,7 @@ DLLEXPORT FPDF_BOOL FPDFPath_LineTo(FPDF_PAGEOBJECT path, float x, float y) { auto* pPathObj = static_cast(path); pPathObj->m_Path.AppendPoint(CFX_PointF(x, y), FXPT_TYPE::LineTo, false); + pPathObj->SetDirty(true); return true; } @@ -110,6 +114,7 @@ DLLEXPORT FPDF_BOOL FPDFPath_BezierTo(FPDF_PAGEOBJECT path, pPathObj->m_Path.AppendPoint(CFX_PointF(x1, y1), FXPT_TYPE::BezierTo, false); pPathObj->m_Path.AppendPoint(CFX_PointF(x2, y2), FXPT_TYPE::BezierTo, false); pPathObj->m_Path.AppendPoint(CFX_PointF(x3, y3), FXPT_TYPE::BezierTo, false); + pPathObj->SetDirty(true); return true; } @@ -122,6 +127,7 @@ DLLEXPORT FPDF_BOOL FPDFPath_Close(FPDF_PAGEOBJECT path) { return false; pPathObj->m_Path.ClosePath(); + pPathObj->SetDirty(true); return true; } @@ -140,6 +146,7 @@ DLLEXPORT FPDF_BOOL FPDFPath_SetDrawMode(FPDF_PAGEOBJECT path, else pPathObj->m_FillType = 0; pPathObj->m_bStroke = stroke != 0; + pPathObj->SetDirty(true); return true; } @@ -157,6 +164,7 @@ DLLEXPORT void STDCALL FPDFPath_SetLineJoin(FPDF_PAGEOBJECT path, CFX_GraphStateData::LineJoin lineJoin = static_cast(line_join); pPathObj->m_GraphState.SetLineJoin(lineJoin); + pPathObj->SetDirty(true); } DLLEXPORT void STDCALL FPDFPath_SetLineCap(FPDF_PAGEOBJECT path, int line_cap) { @@ -170,4 +178,5 @@ DLLEXPORT void STDCALL FPDFPath_SetLineCap(FPDF_PAGEOBJECT path, int line_cap) { CFX_GraphStateData::LineCap lineCap = static_cast(line_cap); pPathObj->m_GraphState.SetLineCap(lineCap); + pPathObj->SetDirty(true); } -- cgit v1.2.3