| Index: fpdfsdk/fpdf_flatten.cpp
 | 
| diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp
 | 
| index 854a99258fddabaac1ad38af267feaae081e68f1..251da34d39035f31d30c7f5af6b2c1a5ffb3a779 100644
 | 
| --- a/fpdfsdk/fpdf_flatten.cpp
 | 
| +++ b/fpdfsdk/fpdf_flatten.cpp
 | 
| @@ -24,6 +24,8 @@ typedef CFX_ArrayTemplate<CFX_FloatRect> 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);
 | 
| 
 |