From 381fc833ac9e6ea58762b7e7ac8b7f2129e8477f Mon Sep 17 00:00:00 2001 From: tsepez Date: Mon, 10 Oct 2016 14:06:44 -0700 Subject: Add method to convert to an indirect object in a dictionary. Avoid an assert which previously could only be overcome by removing/re-inserting. Back-fill a unit test for the equivalent Array method. BUG=654387 Review-Url: https://codereview.chromium.org/2403143002 --- fpdfsdk/fpdf_flatten.cpp | 131 ++++++++++++++--------------------------------- 1 file changed, 38 insertions(+), 93 deletions(-) (limited to 'fpdfsdk') diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp index 854a99258f..251da34d39 100644 --- a/fpdfsdk/fpdf_flatten.cpp +++ b/fpdfsdk/fpdf_flatten.cpp @@ -24,6 +24,8 @@ typedef CFX_ArrayTemplate CPDF_RectArray; enum FPDF_TYPE { MAX, MIN }; enum FPDF_VALUE { TOP, LEFT, RIGHT, BOTTOM }; +namespace { + FX_BOOL IsValiableRect(CFX_FloatRect rect, CFX_FloatRect rcPage) { if (rect.left - rect.right > 0.000001f || rect.bottom - rect.top > 0.000001f) return FALSE; @@ -182,67 +184,48 @@ CFX_FloatRect CalculateRect(CPDF_RectArray* pRectArray) { return rcRet; } -void SetPageContents(CFX_ByteString key, +uint32_t NewIndirectContentsStream(const CFX_ByteString& key, + CPDF_Document* pDocument) { + CPDF_Stream* pNewContents = new CPDF_Stream( + nullptr, 0, new CPDF_Dictionary(pDocument->GetByteStringPool())); + CFX_ByteString sStream; + sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str()); + pNewContents->SetData(sStream.raw_str(), sStream.GetLength()); + return pDocument->AddIndirectObject(pNewContents); +} + +void SetPageContents(const CFX_ByteString& key, CPDF_Dictionary* pPage, CPDF_Document* pDocument) { - CPDF_Object* pContentsObj = pPage->GetStreamFor("Contents"); - if (!pContentsObj) { - pContentsObj = pPage->GetArrayFor("Contents"); - } - - if (!pContentsObj) { - // Create a new contents dictionary - if (!key.IsEmpty()) { - CPDF_Stream* pNewContents = new CPDF_Stream( - nullptr, 0, new CPDF_Dictionary(pDocument->GetByteStringPool())); - CFX_ByteString sStream; - sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str()); - pNewContents->SetData(sStream.raw_str(), sStream.GetLength()); - pPage->SetReferenceFor("Contents", pDocument, - pDocument->AddIndirectObject(pNewContents)); - } - return; - } - CPDF_Array* pContentsArray = nullptr; - switch (pContentsObj->GetType()) { - case CPDF_Object::STREAM: { - pContentsArray = new CPDF_Array; - CPDF_Stream* pContents = pContentsObj->AsStream(); - uint32_t dwObjNum = pDocument->AddIndirectObject(pContents); - CPDF_StreamAcc acc; - acc.LoadAllData(pContents); - CFX_ByteString sStream = "q\n"; - CFX_ByteString sBody = - CFX_ByteString((const FX_CHAR*)acc.GetData(), acc.GetSize()); - sStream = sStream + sBody + "\nQ"; - pContents->SetData(sStream.raw_str(), sStream.GetLength()); - pContentsArray->AddReference(pDocument, dwObjNum); - break; - } - - case CPDF_Object::ARRAY: { - pContentsArray = pContentsObj->AsArray(); - break; + CPDF_Stream* pContentsStream = pPage->GetStreamFor("Contents"); + if (!pContentsStream) { + pContentsArray = pPage->GetArrayFor("Contents"); + if (!pContentsArray) { + if (!key.IsEmpty()) { + pPage->SetReferenceFor("Contents", pDocument, + NewIndirectContentsStream(key, pDocument)); + } + return; } - default: - break; } - - if (!pContentsArray) - return; - - pPage->SetReferenceFor("Contents", pDocument, - pDocument->AddIndirectObject(pContentsArray)); - + pPage->ConvertToIndirectObjectFor("Contents", pDocument); + if (!pContentsArray) { + pContentsArray = new CPDF_Array; + CPDF_StreamAcc acc; + acc.LoadAllData(pContentsStream); + CFX_ByteString sStream = "q\n"; + CFX_ByteString sBody = + CFX_ByteString((const FX_CHAR*)acc.GetData(), acc.GetSize()); + sStream = sStream + sBody + "\nQ"; + pContentsStream->SetData(sStream.raw_str(), sStream.GetLength()); + pContentsArray->AddReference(pDocument, pContentsStream->GetObjNum()); + pPage->SetReferenceFor("Contents", pDocument, + pDocument->AddIndirectObject(pContentsArray)); + } if (!key.IsEmpty()) { - CPDF_Stream* pNewContents = new CPDF_Stream( - nullptr, 0, new CPDF_Dictionary(pDocument->GetByteStringPool())); - CFX_ByteString sStream; - sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str()); - pNewContents->SetData(sStream.raw_str(), sStream.GetLength()); pContentsArray->AddReference(pDocument, - pDocument->AddIndirectObject(pNewContents)); + NewIndirectContentsStream(key, pDocument)); } } @@ -263,45 +246,7 @@ CFX_Matrix GetMatrix(CFX_FloatRect rcAnnot, return CFX_Matrix(a, 0, 0, d, e, f); } -void GetOffset(FX_FLOAT& fa, - FX_FLOAT& fd, - FX_FLOAT& fe, - FX_FLOAT& ff, - CFX_FloatRect rcAnnot, - CFX_FloatRect rcStream, - const CFX_Matrix& matrix) { - FX_FLOAT fStreamWidth = 0.0f; - FX_FLOAT fStreamHeight = 0.0f; - - if (matrix.a != 0 && matrix.d != 0) { - fStreamWidth = rcStream.right - rcStream.left; - fStreamHeight = rcStream.top - rcStream.bottom; - } else { - fStreamWidth = rcStream.top - rcStream.bottom; - fStreamHeight = rcStream.right - rcStream.left; - } - - FX_FLOAT x1 = - matrix.a * rcStream.left + matrix.c * rcStream.bottom + matrix.e; - FX_FLOAT y1 = - matrix.b * rcStream.left + matrix.d * rcStream.bottom + matrix.f; - FX_FLOAT x2 = matrix.a * rcStream.left + matrix.c * rcStream.top + matrix.e; - FX_FLOAT y2 = matrix.b * rcStream.left + matrix.d * rcStream.top + matrix.f; - FX_FLOAT x3 = - matrix.a * rcStream.right + matrix.c * rcStream.bottom + matrix.e; - FX_FLOAT y3 = - matrix.b * rcStream.right + matrix.d * rcStream.bottom + matrix.f; - FX_FLOAT x4 = matrix.a * rcStream.right + matrix.c * rcStream.top + matrix.e; - FX_FLOAT y4 = matrix.b * rcStream.right + matrix.d * rcStream.top + matrix.f; - - FX_FLOAT left = std::min(std::min(x1, x2), std::min(x3, x4)); - FX_FLOAT bottom = std::min(std::min(y1, y2), std::min(y3, y4)); - - fa = (rcAnnot.right - rcAnnot.left) / fStreamWidth; - fd = (rcAnnot.top - rcAnnot.bottom) / fStreamHeight; - fe = rcAnnot.left - left * fa; - ff = rcAnnot.bottom - bottom * fd; -} +} // namespace DLLEXPORT int STDCALL FPDFPage_Flatten(FPDF_PAGE page, int nFlag) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); -- cgit v1.2.3