1e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved.
2e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Use of this source code is governed by a BSD-style license that can be
3e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// found in the LICENSE file.
4ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
5e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
7ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "public/fpdf_flatten.h"
8ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
9ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include <algorithm>
10ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
11ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "fpdfsdk/include/fsdk_define.h"
12e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
13e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovtypedef CFX_ArrayTemplate<CPDF_Dictionary*> CPDF_ObjectArray;
14e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovtypedef CFX_ArrayTemplate<CPDF_Rect> CPDF_RectArray;
15e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
16e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovenum FPDF_TYPE { MAX, MIN };
17e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovenum FPDF_VALUE { TOP, LEFT, RIGHT, BOTTOM };
18e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
19ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannFX_BOOL IsValiableRect(CPDF_Rect rect, CPDF_Rect rcPage) {
20ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (rect.left - rect.right > 0.000001f || rect.bottom - rect.top > 0.000001f)
21ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return FALSE;
22ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
23ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (rect.left == 0.0f && rect.top == 0.0f && rect.right == 0.0f &&
24ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      rect.bottom == 0.0f)
25ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return FALSE;
26e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
27ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!rcPage.IsEmpty()) {
28ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (rect.left - rcPage.left < -10.000001f ||
29ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        rect.right - rcPage.right > 10.000001f ||
30ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        rect.top - rcPage.top > 10.000001f ||
31ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        rect.bottom - rcPage.bottom < -10.000001f)
32ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      return FALSE;
33ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
34e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
35ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return TRUE;
36e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
37e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
38ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannFX_BOOL GetContentsRect(CPDF_Document* pDoc,
39ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        CPDF_Dictionary* pDict,
40ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        CPDF_RectArray* pRectArray) {
41ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Page* pPDFPage = new CPDF_Page;
42ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  pPDFPage->Load(pDoc, pDict, FALSE);
43ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  pPDFPage->ParseContent();
44ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
45ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_POSITION pos = pPDFPage->GetFirstObjectPosition();
46ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
47ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  while (pos) {
48ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_PageObject* pPageObject = pPDFPage->GetNextObject(pos);
49ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (!pPageObject)
50ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      continue;
51ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
52ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Rect rc;
53ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rc.left = pPageObject->m_Left;
54ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rc.right = pPageObject->m_Right;
55ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rc.bottom = pPageObject->m_Bottom;
56ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rc.top = pPageObject->m_Top;
57ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
58ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (IsValiableRect(rc, pDict->GetRect("MediaBox"))) {
59ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pRectArray->Add(rc);
60ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
61ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
62ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
63ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  delete pPDFPage;
64ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return TRUE;
65ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
66e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
67ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid ParserStream(CPDF_Dictionary* pPageDic,
68ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  CPDF_Dictionary* pStream,
69ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  CPDF_RectArray* pRectArray,
70ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  CPDF_ObjectArray* pObjectArray) {
71ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pStream)
72ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
73ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Rect rect;
74ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pStream->KeyExist("Rect"))
75ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rect = pStream->GetRect("Rect");
76ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  else if (pStream->KeyExist("BBox"))
77ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rect = pStream->GetRect("BBox");
78ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
79ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (IsValiableRect(rect, pPageDic->GetRect("MediaBox")))
80ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pRectArray->Add(rect);
81ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
82ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  pObjectArray->Add(pStream);
83e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
84e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
85ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannint ParserAnnots(CPDF_Document* pSourceDoc,
86ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                 CPDF_Dictionary* pPageDic,
87ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                 CPDF_RectArray* pRectArray,
88ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                 CPDF_ObjectArray* pObjectArray,
89ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                 int nUsage) {
90ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pSourceDoc || !pPageDic)
91ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return FLATTEN_FAIL;
92ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
93ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  GetContentsRect(pSourceDoc, pPageDic, pRectArray);
94ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Array* pAnnots = pPageDic->GetArray("Annots");
95ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pAnnots)
96ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return FLATTEN_NOTHINGTODO;
97ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
98ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_DWORD dwSize = pAnnots->GetCount();
99ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int i = 0; i < (int)dwSize; i++) {
100ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Dictionary* pAnnotDic = ToDictionary(pAnnots->GetElementValue(i));
101ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (!pAnnotDic)
102ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      continue;
103ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
104ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CFX_ByteString sSubtype = pAnnotDic->GetString("Subtype");
105ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (sSubtype == "Popup")
106ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      continue;
107ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
108ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int nAnnotFlag = pAnnotDic->GetInteger("F");
109ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (nAnnotFlag & ANNOTFLAG_HIDDEN)
110ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      continue;
111ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
112ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (nUsage == FLAT_NORMALDISPLAY) {
113ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (nAnnotFlag & ANNOTFLAG_INVISIBLE)
114ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        continue;
115ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
116ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      ParserStream(pPageDic, pAnnotDic, pRectArray, pObjectArray);
117ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } else {
118ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (nAnnotFlag & ANNOTFLAG_PRINT)
119ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        ParserStream(pPageDic, pAnnotDic, pRectArray, pObjectArray);
120ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
121ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
122ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return FLATTEN_SUCCESS;
123ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
124e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
125ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannFX_FLOAT GetMinMaxValue(CPDF_RectArray& array,
126ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        FPDF_TYPE type,
127ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        FPDF_VALUE value) {
128ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int nRects = array.GetSize();
129ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT fRet = 0.0f;
130e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
131ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (nRects <= 0)
132ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return 0.0f;
133e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
134ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT* pArray = new FX_FLOAT[nRects];
135ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  switch (value) {
136ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case LEFT: {
137ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      for (int i = 0; i < nRects; i++)
138ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pArray[i] = CPDF_Rect(array.GetAt(i)).left;
139e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
140ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
141ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
142ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case TOP: {
143ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      for (int i = 0; i < nRects; i++)
144ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pArray[i] = CPDF_Rect(array.GetAt(i)).top;
145e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
146ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
147ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
148ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case RIGHT: {
149ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      for (int i = 0; i < nRects; i++)
150ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pArray[i] = CPDF_Rect(array.GetAt(i)).right;
151e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
152ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
153ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
154ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case BOTTOM: {
155ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      for (int i = 0; i < nRects; i++)
156ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pArray[i] = CPDF_Rect(array.GetAt(i)).bottom;
157e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
158ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
159e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
160ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    default:
161ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
162ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
163ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  fRet = pArray[0];
164ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (type == MAX) {
165ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int i = 1; i < nRects; i++)
166ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (fRet <= pArray[i])
167ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        fRet = pArray[i];
168ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else {
169ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int i = 1; i < nRects; i++)
170ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (fRet >= pArray[i])
171ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        fRet = pArray[i];
172ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
173ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  delete[] pArray;
174ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return fRet;
175e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
176e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
177ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannCPDF_Rect CalculateRect(CPDF_RectArray* pRectArray) {
178ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Rect rcRet;
179e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
180ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  rcRet.left = GetMinMaxValue(*pRectArray, MIN, LEFT);
181ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  rcRet.top = GetMinMaxValue(*pRectArray, MAX, TOP);
182ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  rcRet.right = GetMinMaxValue(*pRectArray, MAX, RIGHT);
183ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  rcRet.bottom = GetMinMaxValue(*pRectArray, MIN, BOTTOM);
184e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
185ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return rcRet;
186e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
187e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
188ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid SetPageContents(CFX_ByteString key,
189ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     CPDF_Dictionary* pPage,
190ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     CPDF_Document* pDocument) {
191ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Object* pContentsObj = pPage->GetStream("Contents");
192ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pContentsObj) {
193ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pContentsObj = pPage->GetArray("Contents");
194ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
195ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
196ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pContentsObj) {
197ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    // Create a new contents dictionary
198ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (!key.IsEmpty()) {
199ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      CPDF_Stream* pNewContents = new CPDF_Stream(NULL, 0, new CPDF_Dictionary);
200ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pPage->SetAtReference("Contents", pDocument,
201ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                            pDocument->AddIndirectObject(pNewContents));
202ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
203ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      CFX_ByteString sStream;
204ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str());
205ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pNewContents->SetData((const uint8_t*)sStream, sStream.GetLength(), FALSE,
206ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                            FALSE);
207ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
208ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
209ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
210ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
211ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int iType = pContentsObj->GetType();
212ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Array* pContentsArray = NULL;
213ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
214ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  switch (iType) {
215ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case PDFOBJ_STREAM: {
216ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pContentsArray = new CPDF_Array;
217ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      CPDF_Stream* pContents = pContentsObj->AsStream();
218ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_DWORD dwObjNum = pDocument->AddIndirectObject(pContents);
219ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      CPDF_StreamAcc acc;
220ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      acc.LoadAllData(pContents);
221ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      CFX_ByteString sStream = "q\n";
222ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      CFX_ByteString sBody =
223ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          CFX_ByteString((const FX_CHAR*)acc.GetData(), acc.GetSize());
224ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      sStream = sStream + sBody + "\nQ";
225ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pContents->SetData((const uint8_t*)sStream, sStream.GetLength(), FALSE,
226ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                         FALSE);
227ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pContentsArray->AddReference(pDocument, dwObjNum);
228ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
229ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
230e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
231ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case PDFOBJ_ARRAY: {
232ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pContentsArray = pContentsObj->AsArray();
233ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
234ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
235ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    default:
236ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
237ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
238ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
239ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pContentsArray)
240ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
241ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
242ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_DWORD dwObjNum = pDocument->AddIndirectObject(pContentsArray);
243ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  pPage->SetAtReference("Contents", pDocument, dwObjNum);
244ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
245ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!key.IsEmpty()) {
246ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Stream* pNewContents = new CPDF_Stream(NULL, 0, new CPDF_Dictionary);
247ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    dwObjNum = pDocument->AddIndirectObject(pNewContents);
248ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pContentsArray->AddReference(pDocument, dwObjNum);
249ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
250ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CFX_ByteString sStream;
251ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str());
252ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pNewContents->SetData((const uint8_t*)sStream, sStream.GetLength(), FALSE,
253ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                          FALSE);
254ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
255e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
256ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
257ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannCFX_Matrix GetMatrix(CPDF_Rect rcAnnot,
258ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     CPDF_Rect rcStream,
259ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     const CFX_Matrix& matrix) {
260ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (rcStream.IsEmpty())
261ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return CFX_Matrix();
262ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
263ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  matrix.TransformRect(rcStream);
264ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  rcStream.Normalize();
265ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
266ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT a = rcAnnot.Width() / rcStream.Width();
267ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT d = rcAnnot.Height() / rcStream.Height();
268ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
269ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT e = rcAnnot.left - rcStream.left * a;
270ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT f = rcAnnot.bottom - rcStream.bottom * d;
271ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return CFX_Matrix(a, 0, 0, d, e, f);
272e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
273e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
274ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid GetOffset(FX_FLOAT& fa,
275ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann               FX_FLOAT& fd,
276ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann               FX_FLOAT& fe,
277ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann               FX_FLOAT& ff,
278ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann               CPDF_Rect rcAnnot,
279ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann               CPDF_Rect rcStream,
280ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann               const CFX_Matrix& matrix) {
281ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT fStreamWidth = 0.0f;
282ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT fStreamHeight = 0.0f;
283ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
284ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (matrix.a != 0 && matrix.d != 0) {
285ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    fStreamWidth = rcStream.right - rcStream.left;
286ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    fStreamHeight = rcStream.top - rcStream.bottom;
287ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else {
288ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    fStreamWidth = rcStream.top - rcStream.bottom;
289ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    fStreamHeight = rcStream.right - rcStream.left;
290ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
291ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
292ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT x1 =
293ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      matrix.a * rcStream.left + matrix.c * rcStream.bottom + matrix.e;
294ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT y1 =
295ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      matrix.b * rcStream.left + matrix.d * rcStream.bottom + matrix.f;
296ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT x2 = matrix.a * rcStream.left + matrix.c * rcStream.top + matrix.e;
297ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT y2 = matrix.b * rcStream.left + matrix.d * rcStream.top + matrix.f;
298ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT x3 =
299ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      matrix.a * rcStream.right + matrix.c * rcStream.bottom + matrix.e;
300ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT y3 =
301ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      matrix.b * rcStream.right + matrix.d * rcStream.bottom + matrix.f;
302ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT x4 = matrix.a * rcStream.right + matrix.c * rcStream.top + matrix.e;
303ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT y4 = matrix.b * rcStream.right + matrix.d * rcStream.top + matrix.f;
304ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
305ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT left = std::min(std::min(x1, x2), std::min(x3, x4));
306ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT bottom = std::min(std::min(y1, y2), std::min(y3, y4));
307ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
308ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  fa = (rcAnnot.right - rcAnnot.left) / fStreamWidth;
309ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  fd = (rcAnnot.top - rcAnnot.bottom) / fStreamHeight;
310ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  fe = rcAnnot.left - left * fa;
311ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ff = rcAnnot.bottom - bottom * fd;
312e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
313e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
314ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannDLLEXPORT int STDCALL FPDFPage_Flatten(FPDF_PAGE page, int nFlag) {
315ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
316ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!page) {
317ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return FLATTEN_FAIL;
318ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
319ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
320ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Document* pDocument = pPage->m_pDocument;
321ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
322ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
323ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pDocument || !pPageDict) {
324ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return FLATTEN_FAIL;
325ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
326ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
327ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_ObjectArray ObjectArray;
328ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_RectArray RectArray;
329ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
330ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int iRet = FLATTEN_FAIL;
331ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  iRet = ParserAnnots(pDocument, pPageDict, &RectArray, &ObjectArray, nFlag);
332ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (iRet == FLATTEN_NOTHINGTODO || iRet == FLATTEN_FAIL)
333ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return iRet;
334ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
335ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Rect rcOriginalCB;
336ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Rect rcMerger = CalculateRect(&RectArray);
337ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Rect rcOriginalMB = pPageDict->GetRect("MediaBox");
338ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
339ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pPageDict->KeyExist("CropBox"))
340ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rcOriginalMB = pPageDict->GetRect("CropBox");
341ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
342ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (rcOriginalMB.IsEmpty()) {
343ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rcOriginalMB = CPDF_Rect(0.0f, 0.0f, 612.0f, 792.0f);
344ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
345ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
346ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  rcMerger.left =
347ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      rcMerger.left < rcOriginalMB.left ? rcOriginalMB.left : rcMerger.left;
348ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  rcMerger.right =
349ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      rcMerger.right > rcOriginalMB.right ? rcOriginalMB.right : rcMerger.right;
350ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  rcMerger.top =
351ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      rcMerger.top > rcOriginalMB.top ? rcOriginalMB.top : rcMerger.top;
352ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  rcMerger.bottom = rcMerger.bottom < rcOriginalMB.bottom ? rcOriginalMB.bottom
353ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                                          : rcMerger.bottom;
354ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
355ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pPageDict->KeyExist("ArtBox"))
356ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rcOriginalCB = pPageDict->GetRect("ArtBox");
357ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  else
358ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rcOriginalCB = rcOriginalMB;
359ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
360ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!rcOriginalMB.IsEmpty()) {
361ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Array* pMediaBox = new CPDF_Array();
362ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pMediaBox->Add(new CPDF_Number(rcOriginalMB.left));
363ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pMediaBox->Add(new CPDF_Number(rcOriginalMB.bottom));
364ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pMediaBox->Add(new CPDF_Number(rcOriginalMB.right));
365ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pMediaBox->Add(new CPDF_Number(rcOriginalMB.top));
366ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pPageDict->SetAt("MediaBox", pMediaBox);
367ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
368ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
369ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!rcOriginalCB.IsEmpty()) {
370ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Array* pCropBox = new CPDF_Array();
371ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pCropBox->Add(new CPDF_Number(rcOriginalCB.left));
372ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pCropBox->Add(new CPDF_Number(rcOriginalCB.bottom));
373ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pCropBox->Add(new CPDF_Number(rcOriginalCB.right));
374ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pCropBox->Add(new CPDF_Number(rcOriginalCB.top));
375ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pPageDict->SetAt("ArtBox", pCropBox);
376ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
377ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
378ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Dictionary* pRes = pPageDict->GetDict("Resources");
379ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pRes) {
380ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pRes = new CPDF_Dictionary;
381ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pPageDict->SetAt("Resources", pRes);
382ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
383ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
384ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Stream* pNewXObject = new CPDF_Stream(NULL, 0, new CPDF_Dictionary);
385ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_DWORD dwObjNum = pDocument->AddIndirectObject(pNewXObject);
386ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Dictionary* pPageXObject = pRes->GetDict("XObject");
387ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pPageXObject) {
388ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pPageXObject = new CPDF_Dictionary;
389ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pRes->SetAt("XObject", pPageXObject);
390ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
391ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
392ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_ByteString key = "";
393ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int nStreams = ObjectArray.GetSize();
394ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
395ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (nStreams > 0) {
396ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int iKey = 0; /*iKey < 100*/; iKey++) {
397ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      char sExtend[5] = {};
398ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FXSYS_itoa(iKey, sExtend, 10);
399ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      key = CFX_ByteString("FFT") + CFX_ByteString(sExtend);
400ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
401ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (!pPageXObject->KeyExist(key))
402ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        break;
403ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
404ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
405ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
406ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  SetPageContents(key, pPageDict, pDocument);
407ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
408ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Dictionary* pNewXORes = NULL;
409ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
410ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!key.IsEmpty()) {
411ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pPageXObject->SetAtReference(key, pDocument, dwObjNum);
412ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Dictionary* pNewOXbjectDic = pNewXObject->GetDict();
413ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pNewXORes = new CPDF_Dictionary;
414ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pNewOXbjectDic->SetAt("Resources", pNewXORes);
415ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pNewOXbjectDic->SetAtName("Type", "XObject");
416ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pNewOXbjectDic->SetAtName("Subtype", "Form");
417ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pNewOXbjectDic->SetAtInteger("FormType", 1);
418ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pNewOXbjectDic->SetAtName("Name", "FRM");
419ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Rect rcBBox = pPageDict->GetRect("ArtBox");
420ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pNewOXbjectDic->SetAtRect("BBox", rcBBox);
421ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
422ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
423ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int i = 0; i < nStreams; i++) {
424ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Dictionary* pAnnotDic = ObjectArray.GetAt(i);
425ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (!pAnnotDic)
426ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      continue;
427ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
428ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Rect rcAnnot = pAnnotDic->GetRect("Rect");
429ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rcAnnot.Normalize();
430ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
431ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CFX_ByteString sAnnotState = pAnnotDic->GetString("AS");
432ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Dictionary* pAnnotAP = pAnnotDic->GetDict("AP");
433ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (!pAnnotAP)
434ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      continue;
435ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
436ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Stream* pAPStream = pAnnotAP->GetStream("N");
437ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (!pAPStream) {
438ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      CPDF_Dictionary* pAPDic = pAnnotAP->GetDict("N");
439ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (!pAPDic)
440ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        continue;
441ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
442ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (!sAnnotState.IsEmpty()) {
443ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pAPStream = pAPDic->GetStream(sAnnotState);
444ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else {
445ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        auto it = pAPDic->begin();
446ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (it != pAPDic->end()) {
447ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          CPDF_Object* pFirstObj = it->second;
448ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          if (pFirstObj) {
449ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            if (pFirstObj->IsReference())
450ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              pFirstObj = pFirstObj->GetDirect();
451ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            if (!pFirstObj->IsStream())
452ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              continue;
453ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            pAPStream = pFirstObj->AsStream();
454ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          }
455ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
456ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
457ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
458ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (!pAPStream)
459ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      continue;
460ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
461ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Dictionary* pAPDic = pAPStream->GetDict();
462ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CFX_Matrix matrix = pAPDic->GetMatrix("Matrix");
463ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
464ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Rect rcStream;
465ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (pAPDic->KeyExist("Rect"))
466ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      rcStream = pAPDic->GetRect("Rect");
467ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    else if (pAPDic->KeyExist("BBox"))
468ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      rcStream = pAPDic->GetRect("BBox");
469ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
470ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (rcStream.IsEmpty())
471ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      continue;
472ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
473ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Object* pObj = pAPStream;
474ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
475ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (pObj) {
476ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      CPDF_Dictionary* pObjDic = pObj->GetDict();
477ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (pObjDic) {
478ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pObjDic->SetAtName("Type", "XObject");
479ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pObjDic->SetAtName("Subtype", "Form");
480ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
481ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
482ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
483ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Dictionary* pXObject = pNewXORes->GetDict("XObject");
484ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (!pXObject) {
485ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pXObject = new CPDF_Dictionary;
486ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pNewXORes->SetAt("XObject", pXObject);
487ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
488ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
489ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CFX_ByteString sFormName;
490ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    sFormName.Format("F%d", i);
491ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_DWORD dwObjNum = pDocument->AddIndirectObject(pObj);
492ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pXObject->SetAtReference(sFormName, pDocument, dwObjNum);
493ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
494ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_StreamAcc acc;
495ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    acc.LoadAllData(pNewXObject);
496ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
497ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    const uint8_t* pData = acc.GetData();
498ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CFX_ByteString sStream(pData, acc.GetSize());
499ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CFX_ByteString sTemp;
500ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
501ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (matrix.IsIdentity()) {
502ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      matrix.a = 1.0f;
503ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      matrix.b = 0.0f;
504ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      matrix.c = 0.0f;
505ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      matrix.d = 1.0f;
506ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      matrix.e = 0.0f;
507ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      matrix.f = 0.0f;
508ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
509ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
510ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CFX_Matrix m = GetMatrix(rcAnnot, rcStream, matrix);
511ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    sTemp.Format("q %f 0 0 %f %f %f cm /%s Do Q\n", m.a, m.d, m.e, m.f,
512ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                 sFormName.c_str());
513ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    sStream += sTemp;
514ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
515ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pNewXObject->SetData((const uint8_t*)sStream, sStream.GetLength(), FALSE,
516ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                         FALSE);
517ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
518ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  pPageDict->RemoveAt("Annots");
519ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
520ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ObjectArray.RemoveAll();
521ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  RectArray.RemoveAll();
522e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
523ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return FLATTEN_SUCCESS;
524e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
525