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