Merge to XFA: Kill off some more unreachable fopen's.
[pdfium.git] / fpdfsdk / src / fpdfeditpage.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4  
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../include/fsdk_define.h"
8 #include "../include/fpdfedit.h"
9 #include "../include/fpdfformfill.h"
10 #include "../include/fpdfxfa/fpdfxfa_doc.h"
11 #include "../include/fpdfxfa/fpdfxfa_app.h"
12 #include "../include/fpdfxfa/fpdfxfa_page.h"
13
14
15 #if _FX_OS_ == _FX_ANDROID_
16 #include "time.h"
17 #else
18 #include <ctime>
19 #endif
20
21 DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_CreateNewDocument()
22 {
23         CPDF_Document* pDoc = FX_NEW CPDF_Document;
24         if (!pDoc)
25                 return NULL;
26         pDoc->CreateNewDoc();
27         time_t currentTime;
28
29         CFX_ByteString DateStr;
30
31         if(FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
32         {
33                 if ( -1 != time( &currentTime ) )
34                 {
35                         tm * pTM = localtime( &currentTime );
36                         if ( pTM )
37                         {
38                                 DateStr.Format( "D:%04d%02d%02d%02d%02d%02d", pTM->tm_year+1900, pTM->tm_mon+1,
39                                         pTM->tm_mday, pTM->tm_hour, pTM->tm_min, pTM->tm_sec );
40                         }
41                 }
42         }
43         
44         CPDF_Dictionary* pInfoDict = NULL;
45         pInfoDict = pDoc->GetInfo();
46         if (pInfoDict)
47         {
48                 if(FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
49                         pInfoDict->SetAt("CreationDate", new CPDF_String(DateStr));
50                 pInfoDict->SetAt("Creator",FX_NEW CPDF_String(L"PDFium"));
51         }
52
53         CPDFXFA_App* pApp = FPDFXFA_GetApp();
54         CPDFXFA_Document* document = FX_NEW CPDFXFA_Document(pDoc, pApp);
55
56         return document;
57 }
58
59 DLLEXPORT void STDCALL FPDFPage_Delete(FPDF_DOCUMENT document, int page_index)
60 {
61         CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
62         if (pDoc == NULL) 
63                 return;
64         if (page_index < 0 || page_index >= pDoc->GetPageCount()) 
65                 return;
66
67         pDoc->DeletePage(page_index);
68 }
69
70 DLLEXPORT FPDF_PAGE STDCALL FPDFPage_New(FPDF_DOCUMENT document, int page_index, double width, double height)
71 {
72         if (!document)
73                 return NULL;
74
75 //      CPDF_Parser* pParser = (CPDF_Parser*)document;
76         CPDF_Document* pDoc = ((CPDFXFA_Document*)document)->GetPDFDoc();
77         if(page_index < 0)
78                 page_index = 0;
79         if(pDoc->GetPageCount()<page_index)
80                 page_index = pDoc->GetPageCount();
81 //      if (page_index < 0 || page_index >= pDoc->GetPageCount()) 
82 //              return NULL;
83
84         CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(page_index);
85         if(!pPageDict)
86                 return NULL;
87         CPDF_Array* pMediaBoxArray = FX_NEW CPDF_Array;
88         pMediaBoxArray->Add(FX_NEW CPDF_Number(0));
89         pMediaBoxArray->Add(FX_NEW CPDF_Number(0));
90         pMediaBoxArray->Add(FX_NEW CPDF_Number(FX_FLOAT(width)));
91         pMediaBoxArray->Add(FX_NEW CPDF_Number(FX_FLOAT(height)));
92
93         pPageDict->SetAt("MediaBox", pMediaBoxArray);
94         pPageDict->SetAt("Rotate", FX_NEW CPDF_Number(0));
95         pPageDict->SetAt("Resources", FX_NEW CPDF_Dictionary);
96
97 //      CPDF_Page* pPage = FX_NEW CPDF_Page;
98 //      pPage->Load(pDoc,pPageDict);
99 //      pPage->ParseContent();
100
101         CPDFXFA_Page* pPage = FX_NEW CPDFXFA_Page((CPDFXFA_Document*)document, page_index);
102         pPage->LoadPDFPage(pPageDict);
103
104         return pPage;
105 }
106
107 DLLEXPORT int STDCALL FPDFPage_GetRotation(FPDF_PAGE page)
108 {
109         CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
110         if (!pPage || !pPage->m_pFormDict || !pPage->m_pFormDict->KeyExist("Type") || !pPage->m_pFormDict->GetElement("Type")->GetDirect()
111                 || pPage->m_pFormDict->GetElement("Type")->GetDirect()->GetString().Compare("Page"))
112         {
113                 return -1;
114         }
115         CPDF_Dictionary* pDict = pPage->m_pFormDict;
116
117         int rotate = 0;
118         if(pDict != NULL)
119         {
120                 if (pDict->KeyExist("Rotate"))
121                         rotate = pDict->GetElement("Rotate")->GetDirect()? pDict->GetElement("Rotate")->GetDirect()->GetInteger() / 90 : 0;
122                 else
123                 {
124                         if(pDict->KeyExist("Parent"))
125                         {
126                                 CPDF_Dictionary* pPages = (CPDF_Dictionary*)pDict->GetElement("Parent")->GetDirect();
127                                 while(pPages)
128                                 {
129                                         if(pPages->KeyExist("Rotate"))
130                                         {
131                                                 rotate = pPages->GetElement("Rotate")->GetDirect()? pPages->GetElement("Rotate")->GetDirect()->GetInteger() / 90 : 0;
132                                                 break;
133                                         }
134                                         else if(pPages->KeyExist("Parent"))
135                                                 pPages = (CPDF_Dictionary*)pPages->GetElement("Parent")->GetDirect();
136                                         else break;
137                                 }
138                         }
139                 }
140         }
141         else
142         {
143                 return -1;
144         }
145         
146         return rotate;
147 }
148
149 DLLEXPORT void STDCALL FPDFPage_InsertObject(FPDF_PAGE page, FPDF_PAGEOBJECT page_obj)
150 {
151         CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
152         if (!pPage || !pPage->m_pFormDict || !pPage->m_pFormDict->KeyExist("Type") || !pPage->m_pFormDict->GetElement("Type")->GetDirect()
153                 || pPage->m_pFormDict->GetElement("Type")->GetDirect()->GetString().Compare("Page"))
154         {
155                 return;
156         }
157         CPDF_PageObject* pPageObj = (CPDF_PageObject*)page_obj;
158         if(pPageObj == NULL)
159                 return;
160         FX_POSITION LastPersition = pPage->GetLastObjectPosition();
161
162         pPage->InsertObject(LastPersition, pPageObj);
163         switch(pPageObj->m_Type)
164         {
165         case FPDF_PAGEOBJ_PATH:
166                 {
167                         CPDF_PathObject* pPathObj = (CPDF_PathObject*)pPageObj;
168                         pPathObj->CalcBoundingBox();
169                         break;
170                 }
171         case FPDF_PAGEOBJ_TEXT:
172                 {
173                         //      CPDF_PathObject* pPathObj = (CPDF_PathObject*)pPageObj;
174                         //      pPathObj->CalcBoundingBox();
175                         break;
176                 }
177         case FPDF_PAGEOBJ_IMAGE:
178                 {
179                         CPDF_ImageObject* pImageObj = (CPDF_ImageObject*)pPageObj;
180                         pImageObj->CalcBoundingBox();
181                         break;
182                 }
183         case FPDF_PAGEOBJ_SHADING:
184                 {
185                         CPDF_ShadingObject* pShadingObj = (CPDF_ShadingObject*)pPageObj;
186                         pShadingObj->CalcBoundingBox();
187                         break;
188                 }
189         case FPDF_PAGEOBJ_FORM:
190                 {
191                         CPDF_FormObject* pFormObj = (CPDF_FormObject*)pPageObj;
192                         pFormObj->CalcBoundingBox();
193                         break;
194                 }
195         default:
196                 break;
197         }
198
199         //      pPage->ParseContent();
200         //pPage->GenerateContent();
201
202 }
203
204 DLLEXPORT int STDCALL FPDFPage_CountObject(FPDF_PAGE page)
205 {
206         CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
207         if (!pPage || !pPage->m_pFormDict || !pPage->m_pFormDict->KeyExist("Type") || !pPage->m_pFormDict->GetElement("Type")->GetDirect()
208                 || pPage->m_pFormDict->GetElement("Type")->GetDirect()->GetString().Compare("Page"))
209         {
210                 return -1;
211         }
212         return pPage->CountObjects();
213 //      return 0;
214 }
215
216 DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPage_GetObject(FPDF_PAGE page, int index)
217 {
218         CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
219         if (!pPage || !pPage->m_pFormDict || !pPage->m_pFormDict->KeyExist("Type")
220                 || pPage->m_pFormDict->GetElement("Type")->GetDirect()->GetString().Compare("Page"))
221         {
222                 return NULL;
223         }
224         return pPage->GetObjectByIndex(index);
225 //      return NULL;
226 }
227
228 DLLEXPORT FPDF_BOOL STDCALL FPDFPage_HasTransparency(FPDF_PAGE page)
229 {
230         if(!page) return FALSE;
231         CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
232         if (!pPage) return FALSE;
233
234         return pPage->BackgroundAlphaNeeded();
235 }
236
237 DLLEXPORT FPDF_BOOL STDCALL FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT pageObject)
238 {
239         if(!pageObject) return FALSE;
240         CPDF_PageObject* pPageObj = (CPDF_PageObject*)pageObject;
241
242         const CPDF_GeneralStateData* pGeneralState = pPageObj->m_GeneralState;
243         int blend_type = pGeneralState ? pGeneralState->m_BlendType : FXDIB_BLEND_NORMAL;
244         if (blend_type != FXDIB_BLEND_NORMAL) return TRUE;
245
246         CPDF_Dictionary* pSMaskDict = pGeneralState ? (CPDF_Dictionary*)pGeneralState->m_pSoftMask : NULL;
247         if(pSMaskDict) return TRUE;
248
249         if(pGeneralState && pGeneralState->m_FillAlpha != 1.0f)
250                 return TRUE;
251
252         if(pPageObj->m_Type == PDFPAGE_PATH)
253         {
254                 if(pGeneralState && pGeneralState->m_StrokeAlpha != 1.0f)
255                         return TRUE;
256         }
257
258         if(pPageObj->m_Type == PDFPAGE_FORM)
259         {
260                 CPDF_FormObject* pFormObj = (CPDF_FormObject*)pPageObj;
261                 if(pFormObj->m_pForm && (pFormObj->m_pForm->m_Transparency & PDFTRANS_ISOLATED))
262                         return TRUE;
263                 if(pFormObj->m_pForm && (!(pFormObj->m_pForm->m_Transparency & PDFTRANS_ISOLATED) && (pFormObj->m_pForm->m_Transparency & PDFTRANS_GROUP)))
264                         return TRUE;
265         }
266         return FALSE;
267 }
268
269 DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GenerateContent(FPDF_PAGE page)
270 {
271         CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
272         if (!pPage || !pPage->m_pFormDict || !pPage->m_pFormDict->KeyExist("Type") || !pPage->m_pFormDict->GetElement("Type")->GetDirect()
273                 || pPage->m_pFormDict->GetElement("Type")->GetDirect()->GetString().Compare("Page"))
274         {
275                 return FALSE;
276         }
277         CPDF_PageContentGenerate CG(pPage);
278         CG.GenerateContent();
279
280         return TRUE;
281 }
282
283 DLLEXPORT void STDCALL FPDFPageObj_Transform(FPDF_PAGEOBJECT page_object,
284                          double a, double b, double c, double d, double e, double f)  
285 {
286         CPDF_PageObject* pPageObj = (CPDF_PageObject*)page_object;
287         if(pPageObj == NULL)
288                 return;
289 //PDF_ImageObject* pImageObj = FX_NEW CPDF_ImageObject;
290         CFX_AffineMatrix matrix((FX_FLOAT)a,(FX_FLOAT)b,(FX_FLOAT)c,(FX_FLOAT)d,(FX_FLOAT)e,(FX_FLOAT)f);
291         pPageObj->Transform(matrix);
292 }
293 DLLEXPORT void STDCALL FPDFPage_TransformAnnots(FPDF_PAGE page,
294                                                                                            double a, double b, double c, double d, double e, double f)
295 {
296         if(page == NULL)
297                 return;
298         CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
299         if (!pPage) return;
300         CPDF_AnnotList AnnotList(pPage);
301         for (int i=0; i<AnnotList.Count();i++)
302         {
303                 CPDF_Annot* pAnnot = AnnotList.GetAt(i);
304                 // transformAnnots Rectangle
305                 CPDF_Rect rect;
306                 pAnnot->GetRect(rect);
307                 CFX_AffineMatrix matrix((FX_FLOAT)a,(FX_FLOAT)b,(FX_FLOAT)c,(FX_FLOAT)d,(FX_FLOAT)e,(FX_FLOAT)f);
308                 rect.Transform(&matrix);
309                 CPDF_Array *pRectArray = NULL;
310                 pRectArray = pAnnot->m_pAnnotDict->GetArray("Rect");
311                 if (!pRectArray) pRectArray=CPDF_Array::Create();
312                 pRectArray->SetAt(0,FX_NEW CPDF_Number(rect.left));
313                 pRectArray->SetAt(1,FX_NEW CPDF_Number(rect.bottom));
314                 pRectArray->SetAt(2,FX_NEW CPDF_Number(rect.right));
315                 pRectArray->SetAt(3,FX_NEW CPDF_Number(rect.top));
316                 pAnnot->m_pAnnotDict->SetAt("Rect",pRectArray);
317
318                 //Transform AP's rectangle
319                 //To Do
320
321         }
322
323 }
324
325 DLLEXPORT void STDCALL FPDFPage_SetRotation(FPDF_PAGE page, int rotate)
326 {
327         if (page == NULL)
328                 return;
329         CPDF_Page* pPage = ((CPDFXFA_Page*)page)->GetPDFPage();
330         if (!pPage) return;
331
332         if (!pPage || !pPage->m_pFormDict || !pPage->m_pFormDict->KeyExist("Type") || !pPage->m_pFormDict->GetElement("Type")->GetDirect()
333                 || pPage->m_pFormDict->GetElement("Type")->GetDirect()->GetString().Compare("Page"))
334         {
335                 return;
336         }
337         CPDF_Dictionary* pDict = pPage->m_pFormDict;
338         rotate %=4;
339
340         pDict->SetAt("Rotate", FX_NEW CPDF_Number(rotate * 90));
341 }