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 
FPDF_CreateNewDocument()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 
FPDFPage_Delete(FPDF_DOCUMENT document,int page_index)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 
FPDFPage_New(FPDF_DOCUMENT document,int page_index,double width,double height)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 
FPDFPage_GetRotation(FPDF_PAGE page)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 
FPDFPage_InsertObject(FPDF_PAGE page,FPDF_PAGEOBJECT page_obj)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 
FPDFPage_CountObject(FPDF_PAGE page)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 
FPDFPage_GetObject(FPDF_PAGE page,int index)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 
FPDFPage_HasTransparency(FPDF_PAGE page)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 
FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT pageObject)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 
FPDFPage_GenerateContent(FPDF_PAGE page)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 
FPDFPageObj_Transform(FPDF_PAGEOBJECT page_object,double a,double b,double c,double d,double e,double f)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 }
FPDFPage_TransformAnnots(FPDF_PAGE page,double a,double b,double c,double d,double e,double f)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->m_pAnnotDict->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->m_pAnnotDict->SetAt("Rect",pRectArray);
302 
303 		//Transform AP's rectangle
304 		//To Do
305 	}
306 
307 }
308 
FPDFPage_SetRotation(FPDF_PAGE page,int rotate)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 }
322