From 0fc185ea8a3a7028e566c05cc323e50ebce32d62 Mon Sep 17 00:00:00 2001 From: Nicolas Pena Date: Wed, 8 Feb 2017 12:13:20 -0500 Subject: Add EmbedderTest for adding and filling paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PathObject uses GraphState to obtain the bounding box, so I set defaults, according to Table 4.2 of PDF spec 1.7. Not testing stroke for now because the default line width seems to be too small and is not being rendered. Methodology: add the test methods to the RenderPage method in pdfium_test, and run with --png and --md5. Check that the png is reasonable with respect to the expected result, and use the output md5 on the embeddertest. BUG=pdfium:661 Change-Id: I674fe3a68374c8d58cd99aaf9dad66e29e057281 Reviewed-on: https://pdfium-review.googlesource.com/2554 Reviewed-by: Tom Sepez Reviewed-by: dsinclair Commit-Queue: Nicolás Peña --- core/fxge/ge/cfx_graphstate.cpp | 4 +- fpdfsdk/fpdfedit_embeddertest.cpp | 128 +++++++++++++++++++++++++++++++++++--- fpdfsdk/fpdfeditpath.cpp | 2 + 3 files changed, 125 insertions(+), 9 deletions(-) diff --git a/core/fxge/ge/cfx_graphstate.cpp b/core/fxge/ge/cfx_graphstate.cpp index 7eb6d3d853..6357aa51a4 100644 --- a/core/fxge/ge/cfx_graphstate.cpp +++ b/core/fxge/ge/cfx_graphstate.cpp @@ -30,7 +30,7 @@ void CFX_GraphState::SetLineDash(CPDF_Array* pArray, } FX_FLOAT CFX_GraphState::GetLineWidth() const { - return m_Ref.GetObject()->m_LineWidth; + return m_Ref.GetObject() ? m_Ref.GetObject()->m_LineWidth : 1.f; } void CFX_GraphState::SetLineWidth(FX_FLOAT width) { @@ -53,7 +53,7 @@ void CFX_GraphState::SetLineJoin(CFX_GraphStateData::LineJoin join) { } FX_FLOAT CFX_GraphState::GetMiterLimit() const { - return m_Ref.GetObject()->m_MiterLimit; + return m_Ref.GetObject() ? m_Ref.GetObject()->m_MiterLimit : 10.f; } void CFX_GraphState::SetMiterLimit(FX_FLOAT limit) { diff --git a/fpdfsdk/fpdfedit_embeddertest.cpp b/fpdfsdk/fpdfedit_embeddertest.cpp index 40bed3a565..4a67c1720b 100644 --- a/fpdfsdk/fpdfedit_embeddertest.cpp +++ b/fpdfsdk/fpdfedit_embeddertest.cpp @@ -5,6 +5,7 @@ #include #include +#include "core/fxcrt/fx_system.h" #include "public/fpdf_edit.h" #include "public/fpdfview.h" #include "testing/embedder_test.h" @@ -140,16 +141,129 @@ TEST_F(FPDFEditEmbeddertest, RasterizePDF) { EXPECT_EQ(1, FPDF_GetPageCount(document_)); FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0); EXPECT_NE(nullptr, new_page); - int width = static_cast(FPDF_GetPageWidth(new_page)); - int height = static_cast(FPDF_GetPageHeight(new_page)); - int alpha = FPDFPage_HasTransparency(new_page) ? 1 : 0; - FPDF_BITMAP new_bitmap = FPDFBitmap_Create(width, height, alpha); - FPDF_DWORD fill_color = alpha ? 0x00000000 : 0xFFFFFFFF; - FPDFBitmap_FillRect(new_bitmap, 0, 0, width, height, fill_color); - FPDF_RenderPageBitmap(new_bitmap, new_page, 0, 0, width, height, 0, 0); + FPDF_BITMAP new_bitmap = RenderPage(new_page); CompareBitmap(new_bitmap, 612, 792, kAllBlackMd5sum); FPDF_ClosePage(new_page); FPDF_CloseDocument(new_doc); FPDFBitmap_Destroy(new_bitmap); } } + +TEST_F(FPDFEditEmbeddertest, AddPaths) { + // Start with a blank page + FPDF_DOCUMENT doc = FPDF_CreateNewDocument(); + FPDF_PAGE page = FPDFPage_New(doc, 0, 612, 792); + + // We will first add a red rectangle + FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20); + ASSERT_NE(nullptr, red_rect); + // Expect false when trying to set colors out of range + EXPECT_FALSE(FPDFPath_SetStrokeColor(red_rect, 100, 100, 100, 300)); + EXPECT_FALSE(FPDFPath_SetFillColor(red_rect, 200, 256, 200, 0)); + + // Fill rectangle with red and insert to the page + 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); + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + FPDF_BITMAP page_bitmap = RenderPage(page); + CompareBitmap(page_bitmap, 612, 792, "66d02eaa6181e2c069ce2ea99beda497"); + FPDFBitmap_Destroy(page_bitmap); + + // Now add to that a green rectangle with some medium alpha + FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(100, 100, 40, 40); + EXPECT_TRUE(FPDFPath_SetFillColor(green_rect, 0, 255, 0, 128)); + EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_WINDING, 0)); + FPDFPage_InsertObject(page, green_rect); + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + page_bitmap = RenderPage(page); + CompareBitmap(page_bitmap, 612, 792, "7b0b87604594e773add528fae567a558"); + FPDFBitmap_Destroy(page_bitmap); + + // Add a black triangle. + FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(400, 100); + EXPECT_TRUE(FPDFPath_SetFillColor(black_path, 0, 0, 0, 200)); + EXPECT_TRUE(FPDFPath_SetDrawMode(black_path, FPDF_FILLMODE_ALTERNATE, 0)); + EXPECT_TRUE(FPDFPath_LineTo(black_path, 400, 200)); + EXPECT_TRUE(FPDFPath_LineTo(black_path, 300, 100)); + EXPECT_TRUE(FPDFPath_Close(black_path)); + FPDFPage_InsertObject(page, black_path); + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + page_bitmap = RenderPage(page); + CompareBitmap(page_bitmap, 612, 792, "eadc8020a14dfcf091da2688733d8806"); + FPDFBitmap_Destroy(page_bitmap); + + // Now add a more complex blue path. + FPDF_PAGEOBJECT blue_path = FPDFPageObj_CreateNewPath(200, 200); + EXPECT_TRUE(FPDFPath_SetFillColor(blue_path, 0, 0, 255, 255)); + EXPECT_TRUE(FPDFPath_SetDrawMode(blue_path, FPDF_FILLMODE_WINDING, 0)); + EXPECT_TRUE(FPDFPath_LineTo(blue_path, 230, 230)); + EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 250, 250, 280, 280, 300, 300)); + EXPECT_TRUE(FPDFPath_LineTo(blue_path, 325, 325)); + EXPECT_TRUE(FPDFPath_LineTo(blue_path, 350, 325)); + EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 375, 330, 390, 360, 400, 400)); + EXPECT_TRUE(FPDFPath_Close(blue_path)); + FPDFPage_InsertObject(page, blue_path); + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + page_bitmap = RenderPage(page); + CompareBitmap(page_bitmap, 612, 792, "9823e1a21bd9b72b6a442ba4f12af946"); + FPDFBitmap_Destroy(page_bitmap); + + // Now save the result, closing the page and document + EXPECT_TRUE(FPDF_SaveAsCopy(doc, this, 0)); + FPDF_ClosePage(page); + FPDF_CloseDocument(doc); + std::string new_file = GetString(); + + // Render the saved result + 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, "9823e1a21bd9b72b6a442ba4f12af946"); + FPDFBitmap_Destroy(new_bitmap); + FPDF_ClosePage(new_page); + FPDF_CloseDocument(new_doc); +} + +TEST_F(FPDFEditEmbeddertest, PathOnTopOfText) { + // Load document with some text + EXPECT_TRUE(OpenDocument("hello_world.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_NE(nullptr, page); + + // Add an opaque rectangle on top of some of the text. + FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(20, 100, 50, 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); + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + + // Add a transparent triangle on top of other part of the text. + FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(20, 50); + EXPECT_TRUE(FPDFPath_SetFillColor(black_path, 0, 0, 0, 100)); + EXPECT_TRUE(FPDFPath_SetDrawMode(black_path, FPDF_FILLMODE_ALTERNATE, 0)); + EXPECT_TRUE(FPDFPath_LineTo(black_path, 30, 80)); + EXPECT_TRUE(FPDFPath_LineTo(black_path, 40, 10)); + EXPECT_TRUE(FPDFPath_Close(black_path)); + FPDFPage_InsertObject(page, black_path); + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + + // Render and check the result. Text is slightly different on Mac. + FPDF_BITMAP bitmap = RenderPage(page); +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + const char md5[] = "2f7c0deee10a9490538e195af64beb67"; +#else + const char md5[] = "17c942c76ff229200f2c98073bb60d85"; +#endif + CompareBitmap(bitmap, 200, 200, md5); + FPDFBitmap_Destroy(bitmap); + UnloadPage(page); +} diff --git a/fpdfsdk/fpdfeditpath.cpp b/fpdfsdk/fpdfeditpath.cpp index 1641510ca1..1d3673c2ae 100644 --- a/fpdfsdk/fpdfeditpath.cpp +++ b/fpdfsdk/fpdfeditpath.cpp @@ -11,6 +11,7 @@ DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_CreateNewPath(float x, float y) { CPDF_PathObject* pPathObj = new CPDF_PathObject; pPathObj->m_Path.AppendPoint(x, y, FXPT_TYPE::MoveTo, false); + pPathObj->DefaultStates(); return pPathObj; } @@ -20,6 +21,7 @@ DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_CreateNewRect(float x, float h) { CPDF_PathObject* pPathObj = new CPDF_PathObject; pPathObj->m_Path.AppendRect(x, y, x + w, y + h); + pPathObj->DefaultStates(); return pPathObj; } -- cgit v1.2.3