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