summaryrefslogtreecommitdiff
path: root/core/fpdfapi/edit
diff options
context:
space:
mode:
authorJane Liu <janeliulwq@google.com>2017-06-26 13:24:23 -0400
committerChromium commit bot <commit-bot@chromium.org>2017-06-27 17:31:27 +0000
commit22eb7ae54e4351f70a5a01b0130c8b0dc713586c (patch)
tree7e2db8f7220b8c643cf3dd5c62281508155f8780 /core/fpdfapi/edit
parent62d5076d33ab2bbe0d70047ef98526cad427e631 (diff)
downloadpdfium-22eb7ae54e4351f70a5a01b0130c8b0dc713586c.tar.xz
Modified CPDF_PageContentGenerator to work with both Form and Page
CPDF_PageContentGenerator currently only works for CPDF_Page objects. However, CPDF_Form is also a CPDF_PageObjectHolder like CPDF_Page, and content streams can be generated for form objects too. This CL modifies the content generator to work with both forms and pages. The content generator will later be used on annotation objects' CPDF_Form to simplify the code for annotation AP stream generation. Change-Id: I1c50bdf0329d1f5788db23286ac72750355a10ed Reviewed-on: https://pdfium-review.googlesource.com/6837 Commit-Queue: Nicolás Peña <npm@chromium.org> Reviewed-by: dsinclair <dsinclair@chromium.org> Reviewed-by: Nicolás Peña <npm@chromium.org>
Diffstat (limited to 'core/fpdfapi/edit')
-rw-r--r--core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp38
-rw-r--r--core/fpdfapi/edit/cpdf_pagecontentgenerator.h8
-rw-r--r--core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp50
3 files changed, 74 insertions, 22 deletions
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index 8b39a7a136..508581f551 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -49,9 +49,10 @@ bool GetColor(const CPDF_Color* pColor, float* rgb) {
} // namespace
-CPDF_PageContentGenerator::CPDF_PageContentGenerator(CPDF_Page* pPage)
- : m_pPage(pPage), m_pDocument(m_pPage->m_pDocument.Get()) {
- for (const auto& pObj : *pPage->GetPageObjectList()) {
+CPDF_PageContentGenerator::CPDF_PageContentGenerator(
+ CPDF_PageObjectHolder* pObjHolder)
+ : m_pObjHolder(pObjHolder), m_pDocument(pObjHolder->m_pDocument.Get()) {
+ for (const auto& pObj : *pObjHolder->GetPageObjectList()) {
if (pObj)
m_pageObjects.emplace_back(pObj.get());
}
@@ -60,12 +61,14 @@ CPDF_PageContentGenerator::CPDF_PageContentGenerator(CPDF_Page* pPage)
CPDF_PageContentGenerator::~CPDF_PageContentGenerator() {}
void CPDF_PageContentGenerator::GenerateContent() {
+ ASSERT(m_pObjHolder->IsPage());
+
CPDF_Document* pDoc = m_pDocument.Get();
std::ostringstream buf;
if (!ProcessPageObjects(&buf))
return;
- CPDF_Dictionary* pPageDict = m_pPage->m_pFormDict.Get();
+ CPDF_Dictionary* pPageDict = m_pObjHolder->m_pFormDict.Get();
CPDF_Object* pContent =
pPageDict ? pPageDict->GetObjectFor("Contents") : nullptr;
CPDF_Stream* pStream = pDoc->NewIndirect<CPDF_Stream>();
@@ -111,14 +114,15 @@ CFX_ByteString CPDF_PageContentGenerator::RealizeResource(
uint32_t dwResourceObjNum,
const CFX_ByteString& bsType) {
ASSERT(dwResourceObjNum);
- if (!m_pPage->m_pResources) {
- m_pPage->m_pResources = m_pDocument->NewIndirect<CPDF_Dictionary>();
- m_pPage->m_pFormDict->SetNewFor<CPDF_Reference>(
- "Resources", m_pDocument.Get(), m_pPage->m_pResources->GetObjNum());
+ if (!m_pObjHolder->m_pResources) {
+ m_pObjHolder->m_pResources = m_pDocument->NewIndirect<CPDF_Dictionary>();
+ m_pObjHolder->m_pFormDict->SetNewFor<CPDF_Reference>(
+ "Resources", m_pDocument.Get(),
+ m_pObjHolder->m_pResources->GetObjNum());
}
- CPDF_Dictionary* pResList = m_pPage->m_pResources->GetDictFor(bsType);
+ CPDF_Dictionary* pResList = m_pObjHolder->m_pResources->GetDictFor(bsType);
if (!pResList)
- pResList = m_pPage->m_pResources->SetNewFor<CPDF_Dictionary>(bsType);
+ pResList = m_pObjHolder->m_pResources->SetNewFor<CPDF_Dictionary>(bsType);
CFX_ByteString name;
int idnum = 1;
@@ -137,7 +141,7 @@ CFX_ByteString CPDF_PageContentGenerator::RealizeResource(
bool CPDF_PageContentGenerator::ProcessPageObjects(std::ostringstream* buf) {
bool bDirty = false;
for (auto& pPageObj : m_pageObjects) {
- if (!pPageObj->IsDirty())
+ if (m_pObjHolder->IsPage() && !pPageObj->IsDirty())
continue;
bDirty = true;
if (CPDF_ImageObject* pImageObject = pPageObj->AsImage())
@@ -277,8 +281,8 @@ void CPDF_PageContentGenerator::ProcessGraphics(std::ostringstream* buf,
}
CFX_ByteString name;
- auto it = m_pPage->m_GraphicsMap.find(graphD);
- if (it != m_pPage->m_GraphicsMap.end()) {
+ auto it = m_pObjHolder->m_GraphicsMap.find(graphD);
+ if (it != m_pObjHolder->m_GraphicsMap.end()) {
name = it->second;
} else {
auto gsDict = pdfium::MakeUnique<CPDF_Dictionary>();
@@ -296,7 +300,7 @@ void CPDF_PageContentGenerator::ProcessGraphics(std::ostringstream* buf,
CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(gsDict));
uint32_t dwObjNum = pDict->GetObjNum();
name = RealizeResource(dwObjNum, "ExtGState");
- m_pPage->m_GraphicsMap[graphD] = name;
+ m_pObjHolder->m_GraphicsMap[graphD] = name;
}
*buf << "/" << PDF_NameEncode(name).c_str() << " gs ";
}
@@ -321,9 +325,9 @@ void CPDF_PageContentGenerator::ProcessText(std::ostringstream* buf,
else
return;
fontD.baseFont = pFont->GetBaseFont();
- auto it = m_pPage->m_FontsMap.find(fontD);
+ auto it = m_pObjHolder->m_FontsMap.find(fontD);
CFX_ByteString dictName;
- if (it != m_pPage->m_FontsMap.end()) {
+ if (it != m_pObjHolder->m_FontsMap.end()) {
dictName = it->second;
} else {
uint32_t dwObjNum = pFont->GetFontDict()->GetObjNum();
@@ -337,7 +341,7 @@ void CPDF_PageContentGenerator::ProcessText(std::ostringstream* buf,
dwObjNum = pDict->GetObjNum();
}
dictName = RealizeResource(dwObjNum, "Font");
- m_pPage->m_FontsMap[fontD] = dictName;
+ m_pObjHolder->m_FontsMap[fontD] = dictName;
}
*buf << "/" << PDF_NameEncode(dictName).c_str() << " "
<< pTextObj->GetFontSize() << " Tf ";
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
index 19a2faa6bf..2d90eb4465 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
@@ -16,22 +16,22 @@
class CPDF_Document;
class CPDF_ImageObject;
-class CPDF_Page;
class CPDF_PageObject;
+class CPDF_PageObjectHolder;
class CPDF_PathObject;
class CPDF_TextObject;
class CPDF_PageContentGenerator {
public:
- explicit CPDF_PageContentGenerator(CPDF_Page* pPage);
+ explicit CPDF_PageContentGenerator(CPDF_PageObjectHolder* pObjHolder);
~CPDF_PageContentGenerator();
void GenerateContent();
+ bool ProcessPageObjects(std::ostringstream* buf);
private:
friend class CPDF_PageContentGeneratorTest;
- bool ProcessPageObjects(std::ostringstream* buf);
void ProcessPath(std::ostringstream* buf, CPDF_PathObject* pPathObj);
void ProcessImage(std::ostringstream* buf, CPDF_ImageObject* pImageObj);
void ProcessGraphics(std::ostringstream* buf, CPDF_PageObject* pPageObj);
@@ -39,7 +39,7 @@ class CPDF_PageContentGenerator {
CFX_ByteString RealizeResource(uint32_t dwResourceObjNum,
const CFX_ByteString& bsType);
- CFX_UnownedPtr<CPDF_Page> const m_pPage;
+ CFX_UnownedPtr<CPDF_PageObjectHolder> const m_pObjHolder;
CFX_UnownedPtr<CPDF_Document> const m_pDocument;
std::vector<CFX_UnownedPtr<CPDF_PageObject>> m_pageObjects;
};
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
index 91389eef5f..ef186666f1 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
@@ -4,8 +4,12 @@
#include "core/fpdfapi/edit/cpdf_pagecontentgenerator.h"
+#include <memory>
+#include <utility>
+
#include "core/fpdfapi/cpdf_modulemgr.h"
#include "core/fpdfapi/font/cpdf_font.h"
+#include "core/fpdfapi/page/cpdf_form.h"
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/page/cpdf_pathobject.h"
#include "core/fpdfapi/page/cpdf_textobject.h"
@@ -34,7 +38,7 @@ class CPDF_PageContentGeneratorTest : public testing::Test {
CPDF_Dictionary* TestGetResource(CPDF_PageContentGenerator* pGen,
const CFX_ByteString& type,
const CFX_ByteString& name) {
- return pGen->m_pPage->m_pResources->GetDictFor(type)->GetDictFor(name);
+ return pGen->m_pObjHolder->m_pResources->GetDictFor(type)->GetDictFor(name);
}
void TestProcessText(CPDF_PageContentGenerator* pGen,
@@ -273,3 +277,47 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessText) {
EXPECT_EQ("FontDescriptor", fontDesc->GetStringFor("Type"));
EXPECT_EQ("Helvetica", fontDesc->GetStringFor("FontName"));
}
+
+TEST_F(CPDF_PageContentGeneratorTest, ProcessEmptyForm) {
+ auto pDoc = pdfium::MakeUnique<CPDF_Document>(nullptr);
+ pDoc->CreateNewDoc();
+ auto pDict = pdfium::MakeUnique<CPDF_Dictionary>();
+ auto pStream = pdfium::MakeUnique<CPDF_Stream>(nullptr, 0, std::move(pDict));
+
+ // Create an empty form.
+ auto pTestForm =
+ pdfium::MakeUnique<CPDF_Form>(pDoc.get(), nullptr, pStream.get());
+ pTestForm->ParseContent(nullptr, nullptr, nullptr);
+ ASSERT_TRUE(pTestForm->IsParsed());
+
+ // The generated stream for the empty form should be an empty string.
+ CPDF_PageContentGenerator generator(pTestForm.get());
+ std::ostringstream buf;
+ generator.ProcessPageObjects(&buf);
+ EXPECT_EQ("", CFX_ByteString(buf));
+}
+
+TEST_F(CPDF_PageContentGeneratorTest, ProcessFormWithPath) {
+ auto pDoc = pdfium::MakeUnique<CPDF_Document>(nullptr);
+ pDoc->CreateNewDoc();
+ auto pDict = pdfium::MakeUnique<CPDF_Dictionary>();
+ const char content[] =
+ "q 3.102 4.67 m 5.45 0.29 l 4.24 3.15 4.65 2.98 3.456 0.24 c 3.102 4.67 "
+ "l h f Q\n";
+ size_t buf_len = FX_ArraySize(content);
+ std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_len));
+ memcpy(buf.get(), content, buf_len);
+ auto pStream = pdfium::MakeUnique<CPDF_Stream>(std::move(buf), buf_len,
+ std::move(pDict));
+
+ // Create a form with a non-empty stream.
+ auto pTestForm =
+ pdfium::MakeUnique<CPDF_Form>(pDoc.get(), nullptr, pStream.get());
+ pTestForm->ParseContent(nullptr, nullptr, nullptr);
+ ASSERT_TRUE(pTestForm->IsParsed());
+
+ CPDF_PageContentGenerator generator(pTestForm.get());
+ std::ostringstream process_buf;
+ generator.ProcessPageObjects(&process_buf);
+ EXPECT_EQ(content, CFX_ByteString(process_buf));
+}