| 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 |