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