diff options
author | Lei Zhang <thestig@chromium.org> | 2018-10-18 17:46:52 +0000 |
---|---|---|
committer | Chromium commit bot <commit-bot@chromium.org> | 2018-10-18 17:46:52 +0000 |
commit | 0233af4f241c712b41a5d5dfc337cdfce8c63bc9 (patch) | |
tree | ec353562109786de34b60362bccfd4d76435cdfe /fpdfsdk/fpdf_flatten.cpp | |
parent | 2486456feae06bd0dd2254f1569cf2cfb8d04104 (diff) | |
download | pdfium-0233af4f241c712b41a5d5dfc337cdfce8c63bc9.tar.xz |
Push/pop the graphics state stack when flattening.
When FPDFPage_Flatten() manipulates a content stream, it replaces the
content stream with a content stream array. The first element in the
array is the original content stream and the second element in the array
is the flattened annotations content. To make sure the original content
stream's graphics state stack does not affect the flattened annotations,
FPDFPage_Flatten() rewrites the original content stream to be:
q
$contents
Q
When FPDFPage_Flatten() manipulates a content stream array, it just
appends the flattened annotations as a new element in the array. This
may result in graphics state stack leaking out.
To fix this, wrap the content stream array to be:
["q", $content1, ..., $contentN, "Q"]
And then append the flattened annotations.
BUG=chromium:896366
Change-Id: Ic6499e39eb4c9f1fe45d037622bf02be724b6cae
Reviewed-on: https://pdfium-review.googlesource.com/c/44252
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Diffstat (limited to 'fpdfsdk/fpdf_flatten.cpp')
-rw-r--r-- | fpdfsdk/fpdf_flatten.cpp | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp index 98529c53c8..0cee611144 100644 --- a/fpdfsdk/fpdf_flatten.cpp +++ b/fpdfsdk/fpdf_flatten.cpp @@ -167,52 +167,61 @@ CFX_FloatRect CalculateRect(std::vector<CFX_FloatRect>* pRectArray) { return rcRet; } -CPDF_Object* NewIndirectContentsStream(const ByteString& key, - CPDF_Document* pDocument) { +ByteString GenerateFlattenedContent(const ByteString& key) { + return "q 1 0 0 1 0 0 cm /" + key + " Do Q"; +} + +CPDF_Object* NewIndirectContentsStream(CPDF_Document* pDocument, + const ByteString& contents) { CPDF_Stream* pNewContents = pDocument->NewIndirect<CPDF_Stream>( nullptr, 0, pdfium::MakeUnique<CPDF_Dictionary>(pDocument->GetByteStringPool())); - ByteString sStream = - ByteString::Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str()); - pNewContents->SetData(sStream.AsRawSpan()); + pNewContents->SetData(contents.AsRawSpan()); return pNewContents; } void SetPageContents(const ByteString& key, CPDF_Dictionary* pPage, CPDF_Document* pDocument) { - CPDF_Array* pContentsArray = nullptr; + CPDF_Array* pContentsArray = + pPage->GetArrayFor(pdfium::page_object::kContents); CPDF_Stream* pContentsStream = pPage->GetStreamFor(pdfium::page_object::kContents); - if (!pContentsStream) { - pContentsArray = pPage->GetArrayFor(pdfium::page_object::kContents); - if (!pContentsArray) { - if (!key.IsEmpty()) { - pPage->SetFor(pdfium::page_object::kContents, - NewIndirectContentsStream(key, pDocument) - ->MakeReference(pDocument)); - } - return; + if (!pContentsStream && !pContentsArray) { + if (!key.IsEmpty()) { + pPage->SetFor( + pdfium::page_object::kContents, + NewIndirectContentsStream(pDocument, GenerateFlattenedContent(key)) + ->MakeReference(pDocument)); } + return; } + pPage->ConvertToIndirectObjectFor(pdfium::page_object::kContents, pDocument); - if (!pContentsArray) { - pContentsArray = pDocument->NewIndirect<CPDF_Array>(); + if (pContentsArray) { + pContentsArray->InsertAt( + 0, NewIndirectContentsStream(pDocument, "q")->MakeReference(pDocument)); + pContentsArray->Add( + NewIndirectContentsStream(pDocument, "Q")->MakeReference(pDocument)); + } else { ByteString sStream = "q\n"; { auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pContentsStream); pAcc->LoadAllDataFiltered(); - sStream += ByteString(pAcc->GetData(), pAcc->GetSize()); + sStream += ByteString(pAcc->GetSpan()); sStream += "\nQ"; } pContentsStream->SetDataAndRemoveFilter(sStream.AsRawSpan()); + + pContentsArray = pDocument->NewIndirect<CPDF_Array>(); pContentsArray->Add(pContentsStream->MakeReference(pDocument)); pPage->SetFor(pdfium::page_object::kContents, pContentsArray->MakeReference(pDocument)); } if (!key.IsEmpty()) { pContentsArray->Add( - NewIndirectContentsStream(key, pDocument)->MakeReference(pDocument)); + NewIndirectContentsStream(pDocument, GenerateFlattenedContent(key)) + ->MakeReference(pDocument)); } } |