Home | History | Annotate | Download | only in src
      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(&currentTime)) {
     33       tm* pTM = localtime(&currentTime);
     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