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