summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorHenrique Nakashima <hnakashima@chromium.org>2018-06-14 16:22:30 +0000
committerChromium commit bot <commit-bot@chromium.org>2018-06-14 16:22:30 +0000
commit27cf78d88fdb44bd246cd17bcc712225388e9134 (patch)
tree437b128710bc065d70d642022483d83b9cc641ef /core
parente16ffd4fc3f286ebfaf7820351d4fee680deca88 (diff)
downloadpdfium-27cf78d88fdb44bd246cd17bcc712225388e9134.tar.xz
Rewrite content stream regeneration.
Loop through the dirty page objects and streams and regenerate all streams that are dirty. Bug: pdfium:1051 Change-Id: I837b5a7cd9542b7777e7c7ae7ac9cc75f69f30b5 Reviewed-on: https://pdfium-review.googlesource.com/34330 Commit-Queue: Henrique Nakashima <hnakashima@chromium.org> Reviewed-by: dsinclair <dsinclair@chromium.org>
Diffstat (limited to 'core')
-rw-r--r--core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp105
-rw-r--r--core/fpdfapi/edit/cpdf_pagecontentgenerator.h4
-rw-r--r--core/fpdfapi/page/cpdf_pageobject.h6
3 files changed, 82 insertions, 33 deletions
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index 19994fa57f..ba8d03d7f9 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -6,6 +6,9 @@
#include "core/fpdfapi/edit/cpdf_pagecontentgenerator.h"
+#include <map>
+#include <memory>
+#include <set>
#include <tuple>
#include <utility>
@@ -73,33 +76,67 @@ void CPDF_PageContentGenerator::GenerateContent() {
std::map<int32_t, std::unique_ptr<std::ostringstream>>
CPDF_PageContentGenerator::GenerateModifiedStreams() {
- auto buf = pdfium::MakeUnique<std::ostringstream>();
+ // Make sure default graphics are created.
+ (void)GetOrCreateDefaultGraphics();
+ // Figure out which streams are dirty.
+ std::set<int32_t> all_dirty_streams;
+ for (auto& pPageObj : m_pageObjects) {
+ if (pPageObj->IsDirty())
+ all_dirty_streams.insert(pPageObj->GetContentStream());
+ }
+ const std::set<int32_t>* marked_dirty_streams =
+ m_pObjHolder->GetDirtyStreams();
+ all_dirty_streams.insert(marked_dirty_streams->begin(),
+ marked_dirty_streams->end());
+
+ // Start regenerating dirty streams.
std::map<int32_t, std::unique_ptr<std::ostringstream>> streams;
- if (GenerateStreamWithNewObjects(buf.get()))
- streams[CPDF_PageObject::kNoContentStream] = std::move(buf);
+ std::map<int32_t, bool> stream_is_empty;
- // TODO(pdfium:1051): Generate other streams and add to |streams|.
+ for (int32_t dirty_stream : all_dirty_streams) {
+ std::unique_ptr<std::ostringstream> buf =
+ pdfium::MakeUnique<std::ostringstream>();
- return streams;
-}
+ // Set the default graphic state values
+ *buf << "q\n";
+ if (!m_pObjHolder->GetLastCTM().IsIdentity())
+ *buf << m_pObjHolder->GetLastCTM().GetInverse() << " cm\n";
-bool CPDF_PageContentGenerator::GenerateStreamWithNewObjects(
- std::ostringstream* buf) {
- // Set the default graphic state values
- *buf << "q\n";
- if (!m_pObjHolder->GetLastCTM().IsIdentity())
- *buf << m_pObjHolder->GetLastCTM().GetInverse() << " cm\n";
- ProcessDefaultGraphics(buf);
-
- // Process the page objects
- if (!ProcessPageObjects(buf))
- return false;
+ ProcessDefaultGraphics(buf.get());
- // Return graphics to original state
- *buf << "Q\n";
+ streams[dirty_stream] = std::move(buf);
+ stream_is_empty[dirty_stream] = true;
+ }
- return true;
+ // Process the page objects, write into each dirty stream.
+ for (auto& pPageObj : m_pageObjects) {
+ int stream_index = pPageObj->GetContentStream();
+ auto it = streams.find(stream_index);
+ if (it == streams.end())
+ continue;
+
+ std::ostringstream* buf = it->second.get();
+ stream_is_empty[stream_index] = false;
+ ProcessPageObject(buf, pPageObj.Get());
+ }
+
+ // Finish dirty streams.
+ for (int32_t dirty_stream : all_dirty_streams) {
+ std::ostringstream* buf = streams[dirty_stream].get();
+ if (stream_is_empty[dirty_stream]) {
+ // Clear to show that this stream needs to be deleted.
+ buf->str("");
+ } else {
+ // Return graphics to original state
+ *buf << "Q\n";
+ }
+ }
+
+ // Clear dirty streams in m_pObjHolder
+ m_pObjHolder->ClearDirtyStreams();
+
+ return streams;
}
void CPDF_PageContentGenerator::UpdateContentStreams(
@@ -124,6 +161,9 @@ void CPDF_PageContentGenerator::UpdateContentStreams(
page_content_manager.GetStreamByIndex(stream_index);
ASSERT(old_stream);
+ // TODO(pdfium:1051): Remove streams that are now empty. If buf is empty,
+ // remove this instead of setting the data.
+
old_stream->SetData(buf);
}
}
@@ -162,21 +202,28 @@ bool CPDF_PageContentGenerator::ProcessPageObjects(std::ostringstream* buf) {
continue;
bDirty = true;
- if (CPDF_ImageObject* pImageObject = pPageObj->AsImage())
- ProcessImage(buf, pImageObject);
- else if (CPDF_PathObject* pPathObj = pPageObj->AsPath())
- ProcessPath(buf, pPathObj);
- else if (CPDF_TextObject* pTextObj = pPageObj->AsText())
- ProcessText(buf, pTextObj);
- pPageObj->SetDirty(false);
+ ProcessPageObject(buf, pPageObj.Get());
}
return bDirty;
}
void CPDF_PageContentGenerator::UpdateStreamlessPageObjects(
int new_content_stream_index) {
- // TODO(pdfium:1051): Mark page objects that did not have a content stream
- // with the new content stream index.
+ for (auto& pPageObj : m_pageObjects) {
+ if (pPageObj->GetContentStream() == CPDF_PageObject::kNoContentStream)
+ pPageObj->SetContentStream(new_content_stream_index);
+ }
+}
+
+void CPDF_PageContentGenerator::ProcessPageObject(std::ostringstream* buf,
+ CPDF_PageObject* pPageObj) {
+ if (CPDF_ImageObject* pImageObject = pPageObj->AsImage())
+ ProcessImage(buf, pImageObject);
+ else if (CPDF_PathObject* pPathObj = pPageObj->AsPath())
+ ProcessPath(buf, pPathObj);
+ else if (CPDF_TextObject* pTextObj = pPageObj->AsText())
+ ProcessText(buf, pTextObj);
+ pPageObj->SetDirty(false);
}
void CPDF_PageContentGenerator::ProcessImage(std::ostringstream* buf,
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
index 04adf1c1d2..13b8431f18 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
@@ -35,6 +35,7 @@ class CPDF_PageContentGenerator {
private:
friend class CPDF_PageContentGeneratorTest;
+ void ProcessPageObject(std::ostringstream* buf, CPDF_PageObject* pPageObj);
void ProcessPath(std::ostringstream* buf, CPDF_PathObject* pPathObj);
void ProcessImage(std::ostringstream* buf, CPDF_ImageObject* pImageObj);
void ProcessGraphics(std::ostringstream* buf, CPDF_PageObject* pPageObj);
@@ -49,9 +50,6 @@ class CPDF_PageContentGenerator {
std::map<int32_t, std::unique_ptr<std::ostringstream>>
GenerateModifiedStreams();
- // Generate new stream data with all dirty page objects.
- bool GenerateStreamWithNewObjects(std::ostringstream* buf);
-
// Add buffer as a stream in page's 'Contents'
void UpdateContentStreams(
std::map<int32_t, std::unique_ptr<std::ostringstream>>* buf);
diff --git a/core/fpdfapi/page/cpdf_pageobject.h b/core/fpdfapi/page/cpdf_pageobject.h
index 39e7629541..3fc35aa063 100644
--- a/core/fpdfapi/page/cpdf_pageobject.h
+++ b/core/fpdfapi/page/cpdf_pageobject.h
@@ -65,10 +65,14 @@ class CPDF_PageObject : public CPDF_GraphicStates {
// Get what content stream the object was parsed from in its page. This number
// is the index of the content stream in the "Contents" array, or 0 if there
// is a single content stream. If the object is newly created,
- // kNoContentStream is returned.
+ // |kNoContentStream| is returned.
+ //
// If the object is spread among more than one content stream, this is the
// index of the last stream.
int32_t GetContentStream() const { return m_ContentStream; }
+ void SetContentStream(int32_t new_content_stream) {
+ m_ContentStream = new_content_stream;
+ }
float m_Left;
float m_Right;