From d24b97ee1d065eff482355ea3ff82be59bb528b1 Mon Sep 17 00:00:00 2001 From: Artem Strygin Date: Wed, 9 Aug 2017 18:50:59 +0300 Subject: Unify of saving documents. In the original code the method of writing of objects depends on a much unpredictable factors: as: 1) Is there an updated version of the at least one object in the document. 2) The password is changed. 3) Was this object loaded earlier. 4) The Object is compressed and document have a password. With these factors it is difficult to predict what will be the final file. To reduce volatility use only one method that works in all cases mentioned. This method is parse then serialize. Change-Id: I3d7dcadd10abffbad68d1f993f2dd60b039ed989 Reviewed-on: https://pdfium-review.googlesource.com/9572 Commit-Queue: Art Snake Reviewed-by: dsinclair --- core/fpdfapi/edit/cpdf_creator.cpp | 35 +++++--------------- core/fpdfapi/edit/cpdf_creator_embeddertest.cpp | 43 +++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 27 deletions(-) create mode 100644 core/fpdfapi/edit/cpdf_creator_embeddertest.cpp (limited to 'core/fpdfapi/edit') diff --git a/core/fpdfapi/edit/cpdf_creator.cpp b/core/fpdfapi/edit/cpdf_creator.cpp index b347d45dce..9735460f41 100644 --- a/core/fpdfapi/edit/cpdf_creator.cpp +++ b/core/fpdfapi/edit/cpdf_creator.cpp @@ -323,34 +323,15 @@ bool CPDF_Creator::WriteOldIndirectObject(uint32_t objnum) { m_ObjectOffsets[objnum] = m_Archive->CurrentOffset(); bool bExistInMap = !!m_pDocument->GetIndirectObject(objnum); - const CPDF_Parser::ObjectType object_type = m_pParser->GetObjectType(objnum); - if (m_pParser->IsVersionUpdated() || m_bSecurityChanged || bExistInMap || - (object_type == CPDF_Parser::ObjectType::kCompressed && m_pEncryptDict)) { - CPDF_Object* pObj = m_pDocument->GetOrParseIndirectObject(objnum); - if (!pObj) { - m_ObjectOffsets.erase(objnum); - return true; - } - if (!WriteIndirectObj(pObj->GetObjNum(), pObj)) - return false; - if (!bExistInMap) - m_pDocument->DeleteIndirectObject(objnum); - } else { - std::vector buffer = m_pParser->GetIndirectBinary(objnum); - if (buffer.empty()) - return true; - if (object_type == CPDF_Parser::ObjectType::kCompressed) { - if (!m_Archive->WriteDWord(objnum) || - !m_Archive->WriteString(" 0 obj ") || - !m_Archive->WriteBlock(buffer.data(), buffer.size()) || - !m_Archive->WriteString("\r\nendobj\r\n")) { - return false; - } - } else { - if (!m_Archive->WriteBlock(buffer.data(), buffer.size())) - return false; - } + CPDF_Object* pObj = m_pDocument->GetOrParseIndirectObject(objnum); + if (!pObj) { + m_ObjectOffsets.erase(objnum); + return true; } + if (!WriteIndirectObj(pObj->GetObjNum(), pObj)) + return false; + if (!bExistInMap) + m_pDocument->DeleteIndirectObject(objnum); return true; } diff --git a/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp b/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp new file mode 100644 index 0000000000..def7d50a97 --- /dev/null +++ b/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include + +#include "core/fxcrt/fx_system.h" +#include "public/fpdf_annot.h" +#include "public/fpdf_edit.h" +#include "public/fpdfview.h" +#include "testing/embedder_test.h" +#include "testing/gtest/include/gtest/gtest.h" + +class CPDF_CreatorEmbedderTest : public EmbedderTest {}; + +TEST_F(CPDF_CreatorEmbedderTest, SavedDocsAreEqualAfterParse) { + ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf")); + // Save without additional data reading. + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + const std::string saved_doc_1 = GetString(); + ClearString(); + + { + // Do some read only operations. + ASSERT_GE(1, FPDF_GetPageCount(document())); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + FPDF_BITMAP new_bitmap = + RenderPageWithFlags(page, form_handle(), FPDF_ANNOT); + FPDFBitmap_Destroy(new_bitmap); + UnloadPage(page); + } + + // Save when we have additional loaded data. + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + const std::string saved_doc_2 = GetString(); + ClearString(); + + // The sizes of saved docs should be equal. + EXPECT_EQ(saved_doc_1.size(), saved_doc_2.size()); +} -- cgit v1.2.3