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