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