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