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