diff options
Diffstat (limited to 'fpdfsdk/src')
29 files changed, 5051 insertions, 34 deletions
diff --git a/fpdfsdk/src/formfiller/FFL_ComboBox.cpp b/fpdfsdk/src/formfiller/FFL_ComboBox.cpp index 3d78d37894..5e88a5d133 100644 --- a/fpdfsdk/src/formfiller/FFL_ComboBox.cpp +++ b/fpdfsdk/src/formfiller/FFL_ComboBox.cpp @@ -241,6 +241,17 @@ CPWL_Wnd* CFFL_ComboBox::ResetPDFWindow(CPDFSDK_PageView* pPageView, return pRet; } +#ifdef PDF_ENABLE_XFA +FX_BOOL CFFL_ComboBox::IsFieldFull(CPDFSDK_PageView* pPageView) { + if (CPWL_ComboBox* pComboBox = + static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, FALSE))) { + if (CPWL_Edit* pEdit = pComboBox->GetEdit()) + return pEdit->IsTextFull(); + } + return FALSE; +} +#endif // PDF_ENABLE_XFA + void CFFL_ComboBox::OnSetFocus(CPWL_Wnd* pWnd) { ASSERT(m_pApp); diff --git a/fpdfsdk/src/formfiller/FFL_FormFiller.cpp b/fpdfsdk/src/formfiller/FFL_FormFiller.cpp index 61807ee93f..ce73f7d4cb 100644 --- a/fpdfsdk/src/formfiller/FFL_FormFiller.cpp +++ b/fpdfsdk/src/formfiller/FFL_FormFiller.cpp @@ -565,6 +565,12 @@ FX_BOOL CFFL_FormFiller::IsDataChanged(CPDFSDK_PageView* pPageView) { void CFFL_FormFiller::SaveData(CPDFSDK_PageView* pPageView) {} +#ifdef PDF_ENABLE_XFA +FX_BOOL CFFL_FormFiller::IsFieldFull(CPDFSDK_PageView* pPageView) { + return FALSE; +} +#endif // PDF_ENABLE_XFA + void CFFL_FormFiller::SetChangeMark() { m_pApp->FFI_OnChange(); } diff --git a/fpdfsdk/src/formfiller/FFL_IFormFiller.cpp b/fpdfsdk/src/formfiller/FFL_IFormFiller.cpp index d504889e32..36b123e165 100644 --- a/fpdfsdk/src/formfiller/FFL_IFormFiller.cpp +++ b/fpdfsdk/src/formfiller/FFL_IFormFiller.cpp @@ -267,6 +267,11 @@ FX_BOOL CFFL_IFormFiller::OnLButtonUp(CPDFSDK_PageView* pPageView, OnButtonUp(pWidget, pPageView, bReset, bExit, nFlags); if (bExit) return TRUE; +#ifdef PDF_ENABLE_XFA + OnClick(pWidget, pPageView, bReset, bExit, nFlags); + if (bExit) + return TRUE; +#endif // PDF_ENABLE_XFA } return bRet; } @@ -736,6 +741,190 @@ void CFFL_IFormFiller::OnFormat(CPDFSDK_Widget* pWidget, } } +#ifdef PDF_ENABLE_XFA +void CFFL_IFormFiller::OnClick(CPDFSDK_Widget* pWidget, + CPDFSDK_PageView* pPageView, + FX_BOOL& bReset, + FX_BOOL& bExit, + FX_UINT nFlag) { + ASSERT(pWidget != NULL); + + if (!m_bNotifying) { + if (pWidget->HasXFAAAction(PDFSDK_XFA_Click)) { + m_bNotifying = TRUE; + int nAge = pWidget->GetAppearanceAge(); + int nValueAge = pWidget->GetValueAge(); + + PDFSDK_FieldAction fa; + fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag); + fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag); + + pWidget->OnXFAAAction(PDFSDK_XFA_Click, fa, pPageView); + m_bNotifying = FALSE; + + if (!IsValidAnnot(pPageView, pWidget)) { + bExit = TRUE; + return; + } + + if (nAge != pWidget->GetAppearanceAge()) { + if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE)) { + pFormFiller->ResetPDFWindow(pPageView, + nValueAge == pWidget->GetValueAge()); + } + + bReset = TRUE; + } + } + } +} + +void CFFL_IFormFiller::OnFull(CPDFSDK_Widget* pWidget, + CPDFSDK_PageView* pPageView, + FX_BOOL& bReset, + FX_BOOL& bExit, + FX_UINT nFlag) { + ASSERT(pWidget != NULL); + + if (!m_bNotifying) { + if (pWidget->HasXFAAAction(PDFSDK_XFA_Full)) { + m_bNotifying = TRUE; + int nAge = pWidget->GetAppearanceAge(); + int nValueAge = pWidget->GetValueAge(); + + PDFSDK_FieldAction fa; + fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag); + fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag); + + pWidget->OnXFAAAction(PDFSDK_XFA_Full, fa, pPageView); + m_bNotifying = FALSE; + + if (!IsValidAnnot(pPageView, pWidget)) { + bExit = TRUE; + return; + } + + if (nAge != pWidget->GetAppearanceAge()) { + if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE)) { + pFormFiller->ResetPDFWindow(pPageView, + nValueAge == pWidget->GetValueAge()); + } + + bReset = TRUE; + } + } + } +} + +void CFFL_IFormFiller::OnPopupPreOpen(void* pPrivateData, + FX_BOOL& bExit, + FX_DWORD nFlag) { + ASSERT(pPrivateData != NULL); + CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData; + ASSERT(pData->pWidget != NULL); + + FX_BOOL bTempReset = FALSE; + FX_BOOL bTempExit = FALSE; + this->OnPreOpen(pData->pWidget, pData->pPageView, bTempReset, bTempExit, + nFlag); + + if (bTempReset || bTempExit) { + bExit = TRUE; + } +} + +void CFFL_IFormFiller::OnPopupPostOpen(void* pPrivateData, + FX_BOOL& bExit, + FX_DWORD nFlag) { + ASSERT(pPrivateData != NULL); + CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData; + ASSERT(pData->pWidget != NULL); + + FX_BOOL bTempReset = FALSE; + FX_BOOL bTempExit = FALSE; + this->OnPostOpen(pData->pWidget, pData->pPageView, bTempReset, bTempExit, + nFlag); + + if (bTempReset || bTempExit) { + bExit = TRUE; + } +} + +void CFFL_IFormFiller::OnPreOpen(CPDFSDK_Widget* pWidget, + CPDFSDK_PageView* pPageView, + FX_BOOL& bReset, + FX_BOOL& bExit, + FX_UINT nFlag) { + ASSERT(pWidget != NULL); + + if (!m_bNotifying) { + if (pWidget->HasXFAAAction(PDFSDK_XFA_PreOpen)) { + m_bNotifying = TRUE; + int nAge = pWidget->GetAppearanceAge(); + int nValueAge = pWidget->GetValueAge(); + + PDFSDK_FieldAction fa; + fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag); + fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag); + + pWidget->OnXFAAAction(PDFSDK_XFA_PreOpen, fa, pPageView); + m_bNotifying = FALSE; + + if (!IsValidAnnot(pPageView, pWidget)) { + bExit = TRUE; + return; + } + + if (nAge != pWidget->GetAppearanceAge()) { + if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE)) { + pFormFiller->ResetPDFWindow(pPageView, + nValueAge == pWidget->GetValueAge()); + } + + bReset = TRUE; + } + } + } +} + +void CFFL_IFormFiller::OnPostOpen(CPDFSDK_Widget* pWidget, + CPDFSDK_PageView* pPageView, + FX_BOOL& bReset, + FX_BOOL& bExit, + FX_UINT nFlag) { + ASSERT(pWidget != NULL); + + if (!m_bNotifying) { + if (pWidget->HasXFAAAction(PDFSDK_XFA_PostOpen)) { + m_bNotifying = TRUE; + int nAge = pWidget->GetAppearanceAge(); + int nValueAge = pWidget->GetValueAge(); + + PDFSDK_FieldAction fa; + fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag); + fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag); + + pWidget->OnXFAAAction(PDFSDK_XFA_PostOpen, fa, pPageView); + m_bNotifying = FALSE; + + if (!IsValidAnnot(pPageView, pWidget)) { + bExit = TRUE; + return; + } + + if (nAge != pWidget->GetAppearanceAge()) { + if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE)) { + pFormFiller->ResetPDFWindow(pPageView, + nValueAge == pWidget->GetValueAge()); + } + + bReset = TRUE; + } + } + } +} +#endif // PDF_ENABLE_XFA + FX_BOOL CFFL_IFormFiller::IsValidAnnot(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) { if (pPageView) @@ -757,6 +946,20 @@ void CFFL_IFormFiller::OnBeforeKeyStroke(void* pPrivateData, ASSERT(pData->pWidget); CFFL_FormFiller* pFormFiller = GetFormFiller(pData->pWidget, FALSE); + +#ifdef PDF_ENABLE_XFA + if (pFormFiller->IsFieldFull(pData->pPageView)) { + FX_BOOL bFullExit = FALSE; + FX_BOOL bFullReset = FALSE; + OnFull(pData->pWidget, pData->pPageView, bFullReset, bFullExit, nFlag); + + if (bFullReset || bFullExit) { + bExit = TRUE; + return; + } + } +#endif // PDF_ENABLE_XFA + if (!m_bNotifying) { if (pData->pWidget->GetAAction(CPDF_AAction::KeyStroke)) { m_bNotifying = TRUE; diff --git a/fpdfsdk/src/formfiller/FFL_TextField.cpp b/fpdfsdk/src/formfiller/FFL_TextField.cpp index 1141b66e99..ca4e07be4d 100644 --- a/fpdfsdk/src/formfiller/FFL_TextField.cpp +++ b/fpdfsdk/src/formfiller/FFL_TextField.cpp @@ -258,6 +258,16 @@ CPWL_Wnd* CFFL_TextField::ResetPDFWindow(CPDFSDK_PageView* pPageView, return pRet; } +#ifdef PDF_ENABLE_XFA +FX_BOOL CFFL_TextField::IsFieldFull(CPDFSDK_PageView* pPageView) { + if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE)) { + return pWnd->IsTextFull(); + } + + return FALSE; +} +#endif // PDF_ENABLE_XFA + void CFFL_TextField::OnSetFocus(CPWL_Wnd* pWnd) { ASSERT(m_pApp); if (pWnd->GetClassName() == PWL_CLASSNAME_EDIT) { diff --git a/fpdfsdk/src/fpdf_ext.cpp b/fpdfsdk/src/fpdf_ext.cpp index ee542a6453..aa6725b288 100644 --- a/fpdfsdk/src/fpdf_ext.cpp +++ b/fpdfsdk/src/fpdf_ext.cpp @@ -9,6 +9,10 @@ #include "core/include/fxcrt/fx_xml.h" #include "fpdfsdk/include/fsdk_define.h" +#ifdef PDF_ENABLE_XFA +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" +#endif // PDF_ENABLE_XFA + #define FPDFSDK_UNSUPPORT_CALL 100 class CFSDK_UnsupportInfo_Adapter { @@ -16,7 +20,6 @@ class CFSDK_UnsupportInfo_Adapter { CFSDK_UnsupportInfo_Adapter(UNSUPPORT_INFO* unsp_info) { m_unsp_info = unsp_info; } - // FX_BOOL NeedToPauseNow(); void ReportError(int nErrorType); private: @@ -175,12 +178,14 @@ void CheckUnSupportError(CPDF_Document* pDoc, FX_DWORD err_code) { if (pElement) CheckSharedForm(pElement, "workflowType"); +#ifndef PDF_ENABLE_XFA // XFA Forms CPDF_InterForm* pInterForm = new CPDF_InterForm(pDoc, FALSE); if (pInterForm->HasXFAForm()) { FPDF_UnSupportError(FPDF_UNSP_DOC_XFAFORM); } delete pInterForm; +#endif // PDF_ENABLE_XFA } DLLEXPORT int FPDFDoc_GetPageMode(FPDF_DOCUMENT document) { diff --git a/fpdfsdk/src/fpdfeditpage.cpp b/fpdfsdk/src/fpdfeditpage.cpp index 8de928f601..f964172d10 100644 --- a/fpdfsdk/src/fpdfeditpage.cpp +++ b/fpdfsdk/src/fpdfeditpage.cpp @@ -9,6 +9,12 @@ #include "fpdfsdk/include/fsdk_define.h" #include "public/fpdf_formfill.h" +#ifdef PDF_ENABLE_XFA +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_app.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_page.h" +#endif // PDF_ENABLE_XFA + #if _FX_OS_ == _FX_ANDROID_ #include "time.h" #else @@ -78,9 +84,16 @@ DLLEXPORT FPDF_PAGE STDCALL FPDFPage_New(FPDF_DOCUMENT document, pPageDict->SetAt("Rotate", new CPDF_Number(0)); pPageDict->SetAt("Resources", new CPDF_Dictionary); +#ifdef PDF_ENABLE_XFA + CPDFXFA_Page* pPage = + new CPDFXFA_Page((CPDFXFA_Document*)document, page_index); + pPage->LoadPDFPage(pPageDict); +#else // PDF_ENABLE_XFA CPDF_Page* pPage = new CPDF_Page; pPage->Load(pDoc, pPageDict); pPage->ParseContent(nullptr); +#endif // PDF_ENABLE_XFA + return pPage; } diff --git a/fpdfsdk/src/fpdfformfill.cpp b/fpdfsdk/src/fpdfformfill.cpp index 9dc5b70372..5825456b19 100644 --- a/fpdfsdk/src/fpdfformfill.cpp +++ b/fpdfsdk/src/fpdfformfill.cpp @@ -12,6 +12,12 @@ #include "fpdfsdk/include/fsdk_mgr.h" #include "public/fpdfview.h" +#ifdef PDF_ENABLE_XFA +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_app.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_page.h" +#endif // PDF_ENABLE_XFA + namespace { CPDFSDK_InterForm* FormHandleToInterForm(FPDF_FORMHANDLE hHandle) { @@ -38,6 +44,63 @@ DLLEXPORT int STDCALL FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, if (!hHandle) return -1; CPDF_Page* pPage = CPDFPageFromFPDFPage(page); +#ifdef PDF_ENABLE_XFA + if (pPage) { + CPDF_InterForm interform(pPage->m_pDocument, FALSE); + CPDF_FormControl* pFormCtrl = interform.GetControlAtPoint( + pPage, (FX_FLOAT)page_x, (FX_FLOAT)page_y, nullptr); + if (!pFormCtrl) + return -1; + + CPDF_FormField* pFormField = pFormCtrl->GetField(); + if (!pFormField) + return -1; + + int nType = pFormField->GetFieldType(); + return nType; + } + + IXFA_PageView* pPageView = ((CPDFXFA_Page*)page)->GetXFAPageView(); + if (pPageView) { + IXFA_WidgetHandler* pWidgetHandler = NULL; + IXFA_DocView* pDocView = pPageView->GetDocView(); + if (!pDocView) + return -1; + + pWidgetHandler = pDocView->GetWidgetHandler(); + if (!pWidgetHandler) + return -1; + + IXFA_Widget* pXFAAnnot = NULL; + IXFA_WidgetIterator* pWidgetIterator = pPageView->CreateWidgetIterator( + XFA_TRAVERSEWAY_Form, + XFA_WIDGETFILTER_Viewable | XFA_WIDGETFILTER_AllType); + if (!pWidgetIterator) + return -1; + pXFAAnnot = pWidgetIterator->MoveToNext(); + while (pXFAAnnot) { + CFX_RectF rcBBox; + pWidgetHandler->GetBBox(pXFAAnnot, rcBBox, 0); + CFX_FloatRect rcWidget(rcBBox.left, rcBBox.top, + rcBBox.left + rcBBox.width, + rcBBox.top + rcBBox.height); + rcWidget.left -= 1.0f; + rcWidget.right += 1.0f; + rcWidget.bottom -= 1.0f; + rcWidget.top += 1.0f; + + if (rcWidget.Contains(static_cast<FX_FLOAT>(page_x), + static_cast<FX_FLOAT>(page_y))) { + pWidgetIterator->Release(); + return FPDF_FORMFIELD_XFA; + } + pXFAAnnot = pWidgetIterator->MoveToNext(); + } + + pWidgetIterator->Release(); + } + return -1; +#else // PDF_ENABLE_XFA if (!pPage) return -1; CPDF_InterForm interform(pPage->m_pDocument, FALSE); @@ -45,9 +108,9 @@ DLLEXPORT int STDCALL FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, pPage, (FX_FLOAT)page_x, (FX_FLOAT)page_y, nullptr); if (!pFormCtrl) return -1; - CPDF_FormField* pFormField = pFormCtrl->GetField(); return pFormField ? pFormField->GetFieldType() : -1; +#endif // PDF_ENABLE_XFA } DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, @@ -76,7 +139,11 @@ DLLEXPORT int STDCALL FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle, DLLEXPORT FPDF_FORMHANDLE STDCALL FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document, FPDF_FORMFILLINFO* formInfo) { +#ifdef PDF_ENABLE_XFA + const int kRequiredVersion = 2; +#else // PDF_ENABLE_XFA const int kRequiredVersion = 1; +#endif // PDF_ENABLE_XFA if (!formInfo || formInfo->version != kRequiredVersion) return nullptr; @@ -85,7 +152,13 @@ FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document, return nullptr; CPDFDoc_Environment* pEnv = new CPDFDoc_Environment(pDocument, formInfo); +#ifdef PDF_ENABLE_XFA + pEnv->SetSDKDocument(pDocument->GetSDKDocument(pEnv)); + CPDFXFA_App* pApp = CPDFXFA_App::GetInstance(); + pApp->AddFormFillEnv(pEnv); +#else // PDF_ENABLE_XFA pEnv->SetSDKDocument(new CPDFSDK_Document(pDocument, pEnv)); +#endif // PDF_ENABLE_XFA return pEnv; } @@ -93,12 +166,16 @@ DLLEXPORT void STDCALL FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle) { if (!hHandle) return; - CPDFDoc_Environment* pEnv = (CPDFDoc_Environment*)hHandle; +#ifdef PDF_ENABLE_XFA + CPDFXFA_App* pApp = CPDFXFA_App::GetInstance(); + pApp->RemoveFormFillEnv(pEnv); +#else // PDF_ENABLE_XFA if (CPDFSDK_Document* pSDKDoc = pEnv->GetSDKDocument()) { pEnv->SetSDKDocument(NULL); delete pSDKDoc; } +#endif // PDF_ENABLE_XFA delete pEnv; } @@ -141,6 +218,34 @@ DLLEXPORT FPDF_BOOL STDCALL FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle, return pPageView->OnLButtonUp(pt, modifier); } +#ifdef PDF_ENABLE_XFA +DLLEXPORT FPDF_BOOL STDCALL FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return FALSE; + + CPDF_Point pt((FX_FLOAT)page_x, (FX_FLOAT)page_y); + return pPageView->OnRButtonDown(pt, modifier); +} + +DLLEXPORT FPDF_BOOL STDCALL FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return FALSE; + + CPDF_Point pt((FX_FLOAT)page_x, (FX_FLOAT)page_y); + return pPageView->OnRButtonUp(pt, modifier); +} +#endif // PDF_ENABLE_XFA + DLLEXPORT FPDF_BOOL STDCALL FORM_OnKeyDown(FPDF_FORMHANDLE hHandle, FPDF_PAGE page, int nKeyCode, @@ -198,21 +303,32 @@ DLLEXPORT void STDCALL FPDF_FFLDraw(FPDF_FORMHANDLE hHandle, if (!pPage) return; +#ifndef PDF_ENABLE_XFA CPDF_RenderOptions options; if (flags & FPDF_LCD_TEXT) options.m_Flags |= RENDER_CLEARTYPE; else options.m_Flags &= ~RENDER_CLEARTYPE; - // Grayscale output if (flags & FPDF_GRAYSCALE) { options.m_ColorMode = RENDER_COLOR_GRAY; options.m_ForeColor = 0; options.m_BackColor = 0xffffff; } - options.m_AddFlags = flags >> 8; options.m_pOCContext = new CPDF_OCContext(pPage->m_pDocument); +#else // PDF_ENABLE_XFA + CPDFXFA_Document* pDocument = pPage->GetDocument(); + if (!pDocument) + return; + CPDF_Document* pPDFDoc = pDocument->GetPDFDoc(); + if (!pPDFDoc) + return; + CPDFDoc_Environment* pEnv = (CPDFDoc_Environment*)hHandle; + CPDFSDK_Document* pFXDoc = pEnv->GetSDKDocument(); + if (!pFXDoc) + return; +#endif // PDF_ENABLE_XFA CFX_Matrix matrix; pPage->GetDisplayMatrix(matrix, start_x, start_y, size_x, size_y, rotate); @@ -232,12 +348,287 @@ DLLEXPORT void STDCALL FPDF_FFLDraw(FPDF_FORMHANDLE hHandle, pDevice->SaveState(); pDevice->SetClip_Rect(&clip); +#ifndef PDF_ENABLE_XFA if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, pPage)) pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options); +#else // PDF_ENABLE_XFA + CPDF_RenderOptions options; + if (flags & FPDF_LCD_TEXT) + options.m_Flags |= RENDER_CLEARTYPE; + else + options.m_Flags &= ~RENDER_CLEARTYPE; + + // Grayscale output + if (flags & FPDF_GRAYSCALE) { + options.m_ColorMode = RENDER_COLOR_GRAY; + options.m_ForeColor = 0; + options.m_BackColor = 0xffffff; + } + options.m_AddFlags = flags >> 8; + options.m_pOCContext = new CPDF_OCContext(pPDFDoc); + + if (CPDFSDK_PageView* pPageView = pFXDoc->GetPageView(pPage)) + pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options, clip); +#endif // PDF_ENABLE_XFA pDevice->RestoreState(); delete options.m_pOCContext; +#ifdef PDF_ENABLE_XFA + options.m_pOCContext = NULL; +#endif // PDF_ENABLE_XFA +} + +#ifdef PDF_ENABLE_XFA +DLLEXPORT void STDCALL FPDF_Widget_Undo(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget) { + if (NULL == hWidget || NULL == document) + return; + + CPDFXFA_Document* pDocument = (CPDFXFA_Document*)document; + if (pDocument->GetDocType() != XFA_DOCTYPE_Dynamic && + pDocument->GetDocType() != XFA_DOCTYPE_Static) + return; + + IXFA_MenuHandler* pXFAMenuHander = + CPDFXFA_App::GetInstance()->GetXFAApp()->GetMenuHandler(); + if (pXFAMenuHander == NULL) + return; + + pXFAMenuHander->Undo((IXFA_Widget*)hWidget); +} +DLLEXPORT void STDCALL FPDF_Widget_Redo(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget) { + if (NULL == hWidget || NULL == document) + return; + + CPDFXFA_Document* pDocument = (CPDFXFA_Document*)document; + if (pDocument->GetDocType() != XFA_DOCTYPE_Dynamic && + pDocument->GetDocType() != XFA_DOCTYPE_Static) + return; + + IXFA_MenuHandler* pXFAMenuHander = + CPDFXFA_App::GetInstance()->GetXFAApp()->GetMenuHandler(); + if (pXFAMenuHander == NULL) + return; + + pXFAMenuHander->Redo((IXFA_Widget*)hWidget); +} + +DLLEXPORT void STDCALL FPDF_Widget_SelectAll(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget) { + if (NULL == hWidget || NULL == document) + return; + + CPDFXFA_Document* pDocument = (CPDFXFA_Document*)document; + if (pDocument->GetDocType() != XFA_DOCTYPE_Dynamic && + pDocument->GetDocType() != XFA_DOCTYPE_Static) + return; + + IXFA_MenuHandler* pXFAMenuHander = + CPDFXFA_App::GetInstance()->GetXFAApp()->GetMenuHandler(); + if (pXFAMenuHander == NULL) + return; + + pXFAMenuHander->SelectAll((IXFA_Widget*)hWidget); +} +DLLEXPORT void STDCALL FPDF_Widget_Copy(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + FPDF_WIDESTRING wsText, + FPDF_DWORD* size) { + if (NULL == hWidget || NULL == document) + return; + + CPDFXFA_Document* pDocument = (CPDFXFA_Document*)document; + if (pDocument->GetDocType() != XFA_DOCTYPE_Dynamic && + pDocument->GetDocType() != XFA_DOCTYPE_Static) + return; + + IXFA_MenuHandler* pXFAMenuHander = + CPDFXFA_App::GetInstance()->GetXFAApp()->GetMenuHandler(); + if (pXFAMenuHander == NULL) + return; + + CFX_WideString wsCpText; + pXFAMenuHander->Copy((IXFA_Widget*)hWidget, wsCpText); + + CFX_ByteString bsCpText = wsCpText.UTF16LE_Encode(); + int len = bsCpText.GetLength() / sizeof(unsigned short); + if (wsText == NULL) { + *size = len; + return; + } + + int real_size = len < *size ? len : *size; + if (real_size > 0) { + FXSYS_memcpy((void*)wsText, + bsCpText.GetBuffer(real_size * sizeof(unsigned short)), + real_size * sizeof(unsigned short)); + bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short)); + } + *size = real_size; +} +DLLEXPORT void STDCALL FPDF_Widget_Cut(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + FPDF_WIDESTRING wsText, + FPDF_DWORD* size) { + if (NULL == hWidget || NULL == document) + return; + CPDFXFA_Document* pDocument = (CPDFXFA_Document*)document; + if (pDocument->GetDocType() != XFA_DOCTYPE_Dynamic && + pDocument->GetDocType() != XFA_DOCTYPE_Static) + return; + + IXFA_MenuHandler* pXFAMenuHander = + CPDFXFA_App::GetInstance()->GetXFAApp()->GetMenuHandler(); + if (pXFAMenuHander == NULL) + return; + + CFX_WideString wsCpText; + pXFAMenuHander->Cut((IXFA_Widget*)hWidget, wsCpText); + + CFX_ByteString bsCpText = wsCpText.UTF16LE_Encode(); + int len = bsCpText.GetLength() / sizeof(unsigned short); + if (wsText == NULL) { + *size = len; + return; + } + + int real_size = len < *size ? len : *size; + if (real_size > 0) { + FXSYS_memcpy((void*)wsText, + bsCpText.GetBuffer(real_size * sizeof(unsigned short)), + real_size * sizeof(unsigned short)); + bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short)); + } + *size = real_size; +} +DLLEXPORT void STDCALL FPDF_Widget_Paste(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + FPDF_WIDESTRING wsText, + FPDF_DWORD size) { + if (NULL == hWidget || NULL == document) + return; + + CPDFXFA_Document* pDocument = (CPDFXFA_Document*)document; + if (pDocument->GetDocType() != XFA_DOCTYPE_Dynamic && + pDocument->GetDocType() != XFA_DOCTYPE_Static) + return; + + IXFA_MenuHandler* pXFAMenuHander = + CPDFXFA_App::GetInstance()->GetXFAApp()->GetMenuHandler(); + if (pXFAMenuHander == NULL) + return; + + CFX_WideString wstr = CFX_WideString::FromUTF16LE(wsText, size); + pXFAMenuHander->Paste((IXFA_Widget*)hWidget, wstr); +} +DLLEXPORT void STDCALL +FPDF_Widget_ReplaceSpellCheckWord(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + float x, + float y, + FPDF_BYTESTRING bsText) { + if (NULL == hWidget || NULL == document) + return; + + CPDFXFA_Document* pDocument = (CPDFXFA_Document*)document; + if (pDocument->GetDocType() != XFA_DOCTYPE_Dynamic && + pDocument->GetDocType() != XFA_DOCTYPE_Static) + return; + + IXFA_MenuHandler* pXFAMenuHander = + CPDFXFA_App::GetInstance()->GetXFAApp()->GetMenuHandler(); + if (pXFAMenuHander == NULL) + return; + + CFX_PointF ptPopup; + ptPopup.x = x; + ptPopup.y = y; + CFX_ByteStringC bs(bsText); + pXFAMenuHander->ReplaceSpellCheckWord((IXFA_Widget*)hWidget, ptPopup, bs); +} +DLLEXPORT void STDCALL +FPDF_Widget_GetSpellCheckWords(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + float x, + float y, + FPDF_STRINGHANDLE* stringHandle) { + if (NULL == hWidget || NULL == document) + return; + + CPDFXFA_Document* pDocument = (CPDFXFA_Document*)document; + if (pDocument->GetDocType() != XFA_DOCTYPE_Dynamic && + pDocument->GetDocType() != XFA_DOCTYPE_Static) + return; + + IXFA_MenuHandler* pXFAMenuHander = + CPDFXFA_App::GetInstance()->GetXFAApp()->GetMenuHandler(); + if (pXFAMenuHander == NULL) + return; + + CFX_ByteStringArray* sSuggestWords = new CFX_ByteStringArray; + CFX_PointF ptPopup; + ptPopup.x = x; + ptPopup.y = y; + pXFAMenuHander->GetSuggestWords((IXFA_Widget*)hWidget, ptPopup, + *sSuggestWords); + *stringHandle = (FPDF_STRINGHANDLE)sSuggestWords; +} +DLLEXPORT int STDCALL FPDF_StringHandleCounts(FPDF_STRINGHANDLE stringHandle) { + if (stringHandle == NULL) + return -1; + CFX_ByteStringArray* sSuggestWords = (CFX_ByteStringArray*)stringHandle; + return sSuggestWords->GetSize(); +} +DLLEXPORT FPDF_BOOL STDCALL +FPDF_StringHandleGetStringByIndex(FPDF_STRINGHANDLE stringHandle, + int index, + FPDF_BYTESTRING bsText, + FPDF_DWORD* size) { + if (stringHandle == NULL || size == NULL) + return FALSE; + int count = FPDF_StringHandleCounts(stringHandle); + if (index < 0 || index >= count) + return FALSE; + + CFX_ByteStringArray sSuggestWords = *(CFX_ByteStringArray*)stringHandle; + int len = sSuggestWords[index].GetLength(); + + if (bsText == NULL) { + *size = len; + return TRUE; + } + + int real_size = len < *size ? len : *size; + if (real_size > 0) + FXSYS_memcpy((void*)bsText, (const FX_CHAR*)(sSuggestWords[index]), + real_size); + *size = real_size; + + return TRUE; +} +DLLEXPORT void STDCALL +FPDF_StringHandleRelease(FPDF_STRINGHANDLE stringHandle) { + if (stringHandle == NULL) + return; + CFX_ByteStringArray* sSuggestWords = (CFX_ByteStringArray*)stringHandle; + delete sSuggestWords; +} + +DLLEXPORT FPDF_BOOL STDCALL +FPDF_StringHandleAddString(FPDF_STRINGHANDLE stringHandle, + FPDF_BYTESTRING bsText, + FPDF_DWORD size) { + if (stringHandle == NULL || bsText == NULL || size <= 0) + return FALSE; + + CFX_ByteStringArray* stringArr = (CFX_ByteStringArray*)stringHandle; + CFX_ByteString bsStr(bsText, size); + + stringArr->Add(bsStr); + return TRUE; } +#endif // PDF_ENABLE_XFA DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle, int fieldType, diff --git a/fpdfsdk/src/fpdfsave.cpp b/fpdfsdk/src/fpdfsave.cpp index f786396632..b8e9c6e25c 100644 --- a/fpdfsdk/src/fpdfsave.cpp +++ b/fpdfsdk/src/fpdfsave.cpp @@ -10,6 +10,13 @@ #include "fpdfsdk/include/fsdk_define.h" #include "public/fpdf_edit.h" +#ifdef PDF_ENABLE_XFA +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_app.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h" +#include "public/fpdf_formfill.h" +#endif + #if _FX_OS_ == _FX_ANDROID_ #include "time.h" #else @@ -53,6 +60,218 @@ void CFX_IFileWrite::Release() { delete this; } +#ifdef PDF_ENABLE_XFA +FX_BOOL _SaveXFADocumentData(CPDFXFA_Document* pDocument, + CFX_PtrArray& fileList) { + if (!pDocument) + return FALSE; + if (pDocument->GetDocType() != DOCTYPE_DYNAMIC_XFA && + pDocument->GetDocType() != DOCTYPE_STATIC_XFA) + return TRUE; + if (!CPDFXFA_App::GetInstance()->GetXFAApp()) + return TRUE; + + IXFA_DocView* pXFADocView = pDocument->GetXFADocView(); + if (NULL == pXFADocView) + return TRUE; + + IXFA_DocHandler* pXFADocHandler = + CPDFXFA_App::GetInstance()->GetXFAApp()->GetDocHandler(); + CPDF_Document* pPDFDocument = pDocument->GetPDFDoc(); + if (pDocument == NULL) + return FALSE; + + CPDF_Dictionary* pRoot = pPDFDocument->GetRoot(); + if (pRoot == NULL) + return FALSE; + CPDF_Dictionary* pAcroForm = pRoot->GetDictBy("AcroForm"); + if (NULL == pAcroForm) + return FALSE; + CPDF_Object* pXFA = pAcroForm->GetElement("XFA"); + if (pXFA == NULL) + return TRUE; + if (!pXFA->IsArray()) + return FALSE; + CPDF_Array* pArray = pXFA->GetArray(); + if (NULL == pArray) + return FALSE; + int size = pArray->GetCount(); + int iFormIndex = -1; + int iDataSetsIndex = -1; + int iTemplate = -1; + int iLast = size - 2; + for (int i = 0; i < size - 1; i++) { + CPDF_Object* pPDFObj = pArray->GetElement(i); + if (!pPDFObj->IsString()) + continue; + if (pPDFObj->GetString() == "form") + iFormIndex = i + 1; + else if (pPDFObj->GetString() == "datasets") + iDataSetsIndex = i + 1; + else if (pPDFObj->GetString() == "template") + iTemplate = i + 1; + } + IXFA_ChecksumContext* pContext = NULL; + // Checksum + pContext = XFA_Checksum_Create(); + FXSYS_assert(pContext); + pContext->StartChecksum(); + + // template + if (iTemplate > -1) { + CPDF_Stream* pTemplateStream = pArray->GetStreamAt(iTemplate); + CPDF_StreamAcc streamAcc; + streamAcc.LoadAllData(pTemplateStream); + uint8_t* pData = (uint8_t*)streamAcc.GetData(); + FX_DWORD dwSize2 = streamAcc.GetSize(); + IFX_FileStream* pTemplate = FX_CreateMemoryStream(pData, dwSize2); + pContext->UpdateChecksum((IFX_FileRead*)pTemplate); + pTemplate->Release(); + } + CPDF_Stream* pFormStream = NULL; + CPDF_Stream* pDataSetsStream = NULL; + if (iFormIndex != -1) { + // Get form CPDF_Stream + CPDF_Object* pFormPDFObj = pArray->GetElement(iFormIndex); + if (pFormPDFObj->IsReference()) { + CPDF_Object* pFormDirectObj = pFormPDFObj->GetDirect(); + if (pFormDirectObj && pFormDirectObj->IsStream()) { + pFormStream = (CPDF_Stream*)pFormDirectObj; + } + } else if (pFormPDFObj->IsStream()) { + pFormStream = (CPDF_Stream*)pFormPDFObj; + } + } + + if (iDataSetsIndex != -1) { + // Get datasets CPDF_Stream + CPDF_Object* pDataSetsPDFObj = pArray->GetElement(iDataSetsIndex); + if (pDataSetsPDFObj->IsReference()) { + CPDF_Reference* pDataSetsRefObj = (CPDF_Reference*)pDataSetsPDFObj; + CPDF_Object* pDataSetsDirectObj = pDataSetsRefObj->GetDirect(); + if (pDataSetsDirectObj && pDataSetsDirectObj->IsStream()) { + pDataSetsStream = (CPDF_Stream*)pDataSetsDirectObj; + } + } else if (pDataSetsPDFObj->IsStream()) { + pDataSetsStream = (CPDF_Stream*)pDataSetsPDFObj; + } + } + // end + // L"datasets" + { + IFX_FileStream* pDsfileWrite = FX_CreateMemoryStream(); + if (NULL == pDsfileWrite) { + pContext->Release(); + pDsfileWrite->Release(); + return FALSE; + } + if (pXFADocHandler->SavePackage(pXFADocView->GetDoc(), + CFX_WideStringC(L"datasets"), + pDsfileWrite) && + pDsfileWrite->GetSize() > 0) { + // Datasets + pContext->UpdateChecksum((IFX_FileRead*)pDsfileWrite); + pContext->FinishChecksum(); + CPDF_Dictionary* pDataDict = new CPDF_Dictionary; + if (iDataSetsIndex != -1) { + if (pDataSetsStream) + pDataSetsStream->InitStreamFromFile(pDsfileWrite, pDataDict); + } else { + CPDF_Stream* pData = new CPDF_Stream(NULL, 0, NULL); + pData->InitStreamFromFile(pDsfileWrite, pDataDict); + pPDFDocument->AddIndirectObject(pData); + iLast = pArray->GetCount() - 2; + pArray->InsertAt(iLast, new CPDF_String("datasets", FALSE)); + pArray->InsertAt(iLast + 1, pData, pPDFDocument); + } + fileList.Add(pDsfileWrite); + } + } + + // L"form" + { + IFX_FileStream* pfileWrite = FX_CreateMemoryStream(); + if (NULL == pfileWrite) { + pContext->Release(); + return FALSE; + } + if (pXFADocHandler->SavePackage(pXFADocView->GetDoc(), + CFX_WideStringC(L"form"), pfileWrite, + pContext) && + pfileWrite > 0) { + CPDF_Dictionary* pDataDict = new CPDF_Dictionary; + if (iFormIndex != -1) { + if (pFormStream) + pFormStream->InitStreamFromFile(pfileWrite, pDataDict); + } else { + CPDF_Stream* pData = new CPDF_Stream(NULL, 0, NULL); + pData->InitStreamFromFile(pfileWrite, pDataDict); + pPDFDocument->AddIndirectObject(pData); + iLast = pArray->GetCount() - 2; + pArray->InsertAt(iLast, new CPDF_String("form", FALSE)); + pArray->InsertAt(iLast + 1, pData, pPDFDocument); + } + fileList.Add(pfileWrite); + } + } + pContext->Release(); + return TRUE; +} + +FX_BOOL _SendPostSaveToXFADoc(CPDFXFA_Document* pDocument) { + if (!pDocument) + return FALSE; + + if (pDocument->GetDocType() != DOCTYPE_DYNAMIC_XFA && + pDocument->GetDocType() != DOCTYPE_STATIC_XFA) + return TRUE; + + IXFA_DocView* pXFADocView = pDocument->GetXFADocView(); + if (NULL == pXFADocView) + return FALSE; + IXFA_WidgetHandler* pWidgetHander = pXFADocView->GetWidgetHandler(); + + CXFA_WidgetAcc* pWidgetAcc = NULL; + IXFA_WidgetAccIterator* pWidgetAccIterator = + pXFADocView->CreateWidgetAccIterator(); + pWidgetAcc = pWidgetAccIterator->MoveToNext(); + while (pWidgetAcc) { + CXFA_EventParam preParam; + preParam.m_eType = XFA_EVENT_PostSave; + pWidgetHander->ProcessEvent(pWidgetAcc, &preParam); + pWidgetAcc = pWidgetAccIterator->MoveToNext(); + } + pWidgetAccIterator->Release(); + pXFADocView->UpdateDocView(); + pDocument->_ClearChangeMark(); + return TRUE; +} + +FX_BOOL _SendPreSaveToXFADoc(CPDFXFA_Document* pDocument, + CFX_PtrArray& fileList) { + if (pDocument->GetDocType() != DOCTYPE_DYNAMIC_XFA && + pDocument->GetDocType() != DOCTYPE_STATIC_XFA) + return TRUE; + IXFA_DocView* pXFADocView = pDocument->GetXFADocView(); + if (NULL == pXFADocView) + return TRUE; + IXFA_WidgetHandler* pWidgetHander = pXFADocView->GetWidgetHandler(); + CXFA_WidgetAcc* pWidgetAcc = NULL; + IXFA_WidgetAccIterator* pWidgetAccIterator = + pXFADocView->CreateWidgetAccIterator(); + pWidgetAcc = pWidgetAccIterator->MoveToNext(); + while (pWidgetAcc) { + CXFA_EventParam preParam; + preParam.m_eType = XFA_EVENT_PreSave; + pWidgetHander->ProcessEvent(pWidgetAcc, &preParam); + pWidgetAcc = pWidgetAccIterator->MoveToNext(); + } + pWidgetAccIterator->Release(); + pXFADocView->UpdateDocView(); + return _SaveXFADocumentData(pDocument, fileList); +} +#endif // PDF_ENABLE_XFA + FPDF_BOOL _FPDF_Doc_Save(FPDF_DOCUMENT document, FPDF_FILEWRITE* pFileWrite, FPDF_DWORD flags, @@ -62,6 +281,12 @@ FPDF_BOOL _FPDF_Doc_Save(FPDF_DOCUMENT document, if (!pPDFDoc) return 0; +#ifdef PDF_ENABLE_XFA + CPDFXFA_Document* pDoc = (CPDFXFA_Document*)document; + CFX_PtrArray fileList; + _SendPreSaveToXFADoc(pDoc, fileList); +#endif // PDF_ENABLE_XFA + if (flags < FPDF_INCREMENTAL || flags > FPDF_REMOVE_SECURITY) { flags = 0; } @@ -79,6 +304,14 @@ FPDF_BOOL _FPDF_Doc_Save(FPDF_DOCUMENT document, pStreamWrite = new CFX_IFileWrite; pStreamWrite->Init(pFileWrite); bRet = FileMaker.Create(pStreamWrite, flags); +#ifdef PDF_ENABLE_XFA + _SendPostSaveToXFADoc(pDoc); + for (int i = 0; i < fileList.GetSize(); i++) { + IFX_FileStream* pFile = (IFX_FileStream*)fileList.GetAt(i); + pFile->Release(); + } + fileList.RemoveAll(); +#endif // PDF_ENABLE_XFA pStreamWrite->Release(); return bRet; } diff --git a/fpdfsdk/src/fpdftext.cpp b/fpdfsdk/src/fpdftext.cpp index 4659951c3c..c745c26868 100644 --- a/fpdfsdk/src/fpdftext.cpp +++ b/fpdfsdk/src/fpdftext.cpp @@ -10,6 +10,11 @@ #include "core/include/fpdftext/fpdf_text.h" #include "fpdfsdk/include/fsdk_define.h" +#ifdef PDF_ENABLE_XFA +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_page.h" +#endif // PDF_ENABLE_XFA + #ifdef _WIN32 #include <tchar.h> #endif @@ -18,7 +23,13 @@ DLLEXPORT FPDF_TEXTPAGE STDCALL FPDFText_LoadPage(FPDF_PAGE page) { CPDF_Page* pPDFPage = CPDFPageFromFPDFPage(page); if (!pPDFPage) return nullptr; +#ifdef PDF_ENABLE_XFA + CPDFXFA_Page* pPage = (CPDFXFA_Page*)page; + CPDFXFA_Document* pDoc = pPage->GetDocument(); + CPDF_ViewerPreferences viewRef(pDoc->GetPDFDoc()); +#else // PDF_ENABLE_XFA CPDF_ViewerPreferences viewRef(pPDFPage->m_pDocument); +#endif // PDF_ENABLE_XFA IPDF_TextPage* textpage = IPDF_TextPage::CreateTextPage(pPDFPage, viewRef.IsDirectionR2L()); textpage->ParseTextPage(); diff --git a/fpdfsdk/src/fpdfview.cpp b/fpdfsdk/src/fpdfview.cpp index c1feb51434..418d35d720 100644 --- a/fpdfsdk/src/fpdfview.cpp +++ b/fpdfsdk/src/fpdfview.cpp @@ -18,6 +18,15 @@ #include "public/fpdf_progressive.h" #include "third_party/base/numerics/safe_conversions_impl.h" +#ifdef PDF_ENABLE_XFA +#include "core/include/fpdfapi/fpdf_module.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_app.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_page.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h" +#include "public/fpdf_formfill.h" +#endif // PDF_ENABLE_XFA + UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) { return static_cast<UnderlyingDocumentType*>(doc); } @@ -31,21 +40,147 @@ UnderlyingPageType* UnderlyingFromFPDFPage(FPDF_PAGE page) { } CPDF_Document* CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc) { +#ifdef PDF_ENABLE_XFA + return doc ? UnderlyingFromFPDFDocument(doc)->GetPDFDoc() : nullptr; +#else // PDF_ENABLE_XFA return UnderlyingFromFPDFDocument(doc); +#endif // PDF_ENABLE_XFA } FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) { +#ifdef PDF_ENABLE_XFA + return doc ? FPDFDocumentFromUnderlying( + new CPDFXFA_Document(doc, CPDFXFA_App::GetInstance())) + : nullptr; +#else // PDF_ENABLE_XFA return FPDFDocumentFromUnderlying(doc); +#endif // PDF_ENABLE_XFA } CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) { +#ifdef PDF_ENABLE_XFA + return page ? UnderlyingFromFPDFPage(page)->GetPDFPage() : nullptr; +#else // PDF_ENABLE_XFA return UnderlyingFromFPDFPage(page); +#endif // PDF_ENABLE_XFA +} + +#ifdef PDF_ENABLE_XFA +CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) { + m_pFS = pFS; + m_nCurPos = 0; +} + +IFX_FileStream* CFPDF_FileStream::Retain() { + return this; +} + +void CFPDF_FileStream::Release() { + if (m_pFS && m_pFS->Release) + m_pFS->Release(m_pFS->clientData); + delete this; +} + +FX_FILESIZE CFPDF_FileStream::GetSize() { + if (m_pFS && m_pFS->GetSize) + return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData); + return 0; +} + +FX_BOOL CFPDF_FileStream::IsEOF() { + return m_nCurPos >= GetSize(); +} + +FX_BOOL CFPDF_FileStream::ReadBlock(void* buffer, + FX_FILESIZE offset, + size_t size) { + if (!buffer || !size || !m_pFS->ReadBlock) + return FALSE; + + if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer, + (FPDF_DWORD)size) == 0) { + m_nCurPos = offset + size; + return TRUE; + } + return FALSE; +} + +size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) { + if (!buffer || !size || !m_pFS->ReadBlock) + return 0; + + FX_FILESIZE nSize = GetSize(); + if (m_nCurPos >= nSize) + return 0; + FX_FILESIZE dwAvail = nSize - m_nCurPos; + if (dwAvail < (FX_FILESIZE)size) + size = (size_t)dwAvail; + if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer, + (FPDF_DWORD)size) == 0) { + m_nCurPos += size; + return size; + } + + return 0; +} + +FX_BOOL CFPDF_FileStream::WriteBlock(const void* buffer, + FX_FILESIZE offset, + size_t size) { + if (!m_pFS || !m_pFS->WriteBlock) + return FALSE; + + if (m_pFS->WriteBlock(m_pFS->clientData, (FPDF_DWORD)offset, buffer, + (FPDF_DWORD)size) == 0) { + m_nCurPos = offset + size; + return TRUE; + } + return FALSE; } +FX_BOOL CFPDF_FileStream::Flush() { + if (!m_pFS || !m_pFS->Flush) + return TRUE; + + return m_pFS->Flush(m_pFS->clientData) == 0; +} +#endif // PDF_ENABLE_XFA + CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess) { m_FileAccess = *pFileAccess; +#ifdef PDF_ENABLE_XFA + m_BufferOffset = (FX_DWORD)-1; +#endif // PDF_ENABLE_XFA } +#ifdef PDF_ENABLE_XFA +FX_BOOL CPDF_CustomAccess::GetByte(FX_DWORD pos, uint8_t& ch) { + if (pos >= m_FileAccess.m_FileLen) + return FALSE; + if (m_BufferOffset == (FX_DWORD)-1 || pos < m_BufferOffset || + pos >= m_BufferOffset + 512) { + // Need to read from file access + m_BufferOffset = pos; + int size = 512; + if (pos + 512 > m_FileAccess.m_FileLen) + size = m_FileAccess.m_FileLen - pos; + if (!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, m_BufferOffset, m_Buffer, + size)) + return FALSE; + } + ch = m_Buffer[pos - m_BufferOffset]; + return TRUE; +} + +FX_BOOL CPDF_CustomAccess::GetBlock(FX_DWORD pos, + uint8_t* pBuf, + FX_DWORD size) { + if (pos + size > m_FileAccess.m_FileLen) + return FALSE; + return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, pos, pBuf, size); +} +#endif // PDF_ENABLE_XFA + FX_BOOL CPDF_CustomAccess::ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) { @@ -105,15 +240,25 @@ DLLEXPORT void STDCALL FPDF_InitLibraryWithConfig( pModuleMgr->SetCodecModule(g_pCodecModule); pModuleMgr->InitPageModule(); pModuleMgr->InitRenderModule(); +#ifdef PDF_ENABLE_XFA + CPDFXFA_App::GetInstance()->Initialize( + (cfg && cfg->version >= 2) + ? reinterpret_cast<FXJSE_HRUNTIME>(cfg->m_pIsolate) + : nullptr); +#else // PDF_ENABLE_XFA pModuleMgr->LoadEmbeddedGB1CMaps(); pModuleMgr->LoadEmbeddedJapan1CMaps(); pModuleMgr->LoadEmbeddedCNS1CMaps(); pModuleMgr->LoadEmbeddedKorea1CMaps(); +#endif // PDF_ENABLE_XFA if (cfg && cfg->version >= 2) IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate); } DLLEXPORT void STDCALL FPDF_DestroyLibrary() { +#ifdef PDF_ENABLE_XFA + CPDFXFA_App::ReleaseInstance(); +#endif // PDF_ENABLE_XFA CPDF_ModuleMgr::Destroy(); CFX_GEModule::Destroy(); @@ -130,7 +275,7 @@ void SetLastError(int err) { int GetLastError() { return g_LastError; } -#endif +#endif // _WIN32 void ProcessParseError(CPDF_Parser::Error err) { FX_DWORD err_code; @@ -178,8 +323,55 @@ DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path, ProcessParseError(error); return NULL; } +#ifdef PDF_ENABLE_XFA + CPDF_Document* pPDFDoc = pParser->GetDocument(); + if (!pPDFDoc) + return NULL; + + CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance(); + return new CPDFXFA_Document(pPDFDoc, pProvider); +#else // PDF_ENABLE_XFA return pParser->GetDocument(); +#endif // PDF_ENABLE_XFA +} + +#ifdef PDF_ENABLE_XFA +DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document, + int* docType) { + if (!document) + return FALSE; + + CPDF_Document* pdfDoc = + (static_cast<CPDFXFA_Document*>(document))->GetPDFDoc(); + if (!pdfDoc) + return FALSE; + + CPDF_Dictionary* pRoot = pdfDoc->GetRoot(); + if (!pRoot) + return FALSE; + + CPDF_Dictionary* pAcroForm = pRoot->GetDictBy("AcroForm"); + if (!pAcroForm) + return FALSE; + + CPDF_Object* pXFA = pAcroForm->GetElement("XFA"); + if (!pXFA) + return FALSE; + + FX_BOOL bDynamicXFA = pRoot->GetBooleanBy("NeedsRendering", FALSE); + + if (bDynamicXFA) + *docType = DOCTYPE_DYNAMIC_XFA; + else + *docType = DOCTYPE_STATIC_XFA; + + return TRUE; +} + +DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document) { + return document && (static_cast<CPDFXFA_Document*>(document))->LoadXFADoc(); } +#endif // PDF_ENABLE_XFA class CMemFile final : public IFX_FileRead { public: @@ -267,7 +459,11 @@ DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc, DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) +#ifndef PDF_ENABLE_XFA return 0; +#else // PDF_ENABLE_XFA + return (FX_DWORD)-1; +#endif // PDF_ENABLE_XFA CPDF_Dictionary* pDict = pDoc->GetParser()->GetEncryptDict(); return pDict ? pDict->GetIntegerBy("P") : (FX_DWORD)-1; @@ -296,6 +492,9 @@ DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document, if (page_index < 0 || page_index >= pDoc->GetPageCount()) return nullptr; +#ifdef PDF_ENABLE_XFA + return pDoc->GetPage(page_index); +#else // PDF_ENABLE_XFA CPDF_Dictionary* pDict = pDoc->GetPage(page_index); if (!pDict) return NULL; @@ -303,6 +502,7 @@ DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document, pPage->Load(pDoc, pDict); pPage->ParseContent(nullptr); return pPage; +#endif // PDF_ENABLE_XFA } DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page) { @@ -528,6 +728,10 @@ DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap, DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) { if (!page) return; +#ifdef PDF_ENABLE_XFA + CPDFXFA_Page* pPage = (CPDFXFA_Page*)page; + pPage->Release(); +#else // PDF_ENABLE_XFA CPDFSDK_PageView* pPageView = (CPDFSDK_PageView*)(((CPDF_Page*)page))->GetPrivateData((void*)page); if (pPageView && pPageView->IsLocked()) { @@ -535,19 +739,23 @@ DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) { return; } delete (CPDF_Page*)page; +#endif // PDF_ENABLE_XFA } DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document) { +#ifdef PDF_ENABLE_XFA + delete UnderlyingFromFPDFDocument(document); +#else // PDF_ENABLE_XFA CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) return; - - CPDF_Parser* pParser = (CPDF_Parser*)pDoc->GetParser(); + CPDF_Parser* pParser = pDoc->GetParser(); if (!pParser) { delete pDoc; return; } delete pParser; +#endif // PDF_ENABLE_XFA } DLLEXPORT unsigned long STDCALL FPDF_GetLastError() { @@ -567,19 +775,21 @@ DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page, if (!page || !page_x || !page_y) return; UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); - +#ifdef PDF_ENABLE_XFA + pPage->DeviceToPage(start_x, start_y, size_x, size_y, rotate, device_x, + device_y, page_x, page_y); +#else // PDF_ENABLE_XFA CFX_Matrix page2device; pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, rotate); CFX_Matrix device2page; device2page.SetReverse(page2device); - FX_FLOAT page_x_f, page_y_f; device2page.Transform((FX_FLOAT)(device_x), (FX_FLOAT)(device_y), page_x_f, page_y_f); - *page_x = (page_x_f); *page_y = (page_y_f); +#endif // PDF_ENABLE_XFA } DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page, @@ -597,16 +807,19 @@ DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page, UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); if (!pPage) return; +#ifdef PDF_ENABLE_XFA + pPage->PageToDevice(start_x, start_y, size_x, size_y, rotate, page_x, page_y, + device_x, device_y); +#else // PDF_ENABLE_XFA CFX_Matrix page2device; pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, rotate); - FX_FLOAT device_x_f, device_y_f; page2device.Transform(((FX_FLOAT)page_x), ((FX_FLOAT)page_y), device_x_f, device_y_f); - *device_x = FXSYS_round(device_x_f); *device_y = FXSYS_round(device_y_f); +#endif // PDF_ENABLE_XFA } DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width, @@ -713,12 +926,14 @@ void FPDF_RenderPage_Retail(CRenderContext* pContext, pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE; if (flags & FPDF_RENDER_FORCEHALFTONE) pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE; +#ifndef PDF_ENABLE_XFA if (flags & FPDF_RENDER_NO_SMOOTHTEXT) pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH; if (flags & FPDF_RENDER_NO_SMOOTHIMAGE) pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH; if (flags & FPDF_RENDER_NO_SMOOTHPATH) pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH; +#endif // PDF_ENABLE_XFA // Grayscale output if (flags & FPDF_GRAYSCALE) { pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY; @@ -767,14 +982,24 @@ DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, if (!pDoc) return FALSE; +#ifdef PDF_ENABLE_XFA + int count = pDoc->GetPageCount(); + if (page_index < 0 || page_index >= count) + return FALSE; + CPDFXFA_Page* pPage = pDoc->GetPage(page_index); + if (!pPage) + return FALSE; + *width = pPage->GetPageWidth(); + *height = pPage->GetPageHeight(); +#else // PDF_ENABLE_XFA CPDF_Dictionary* pDict = pDoc->GetPage(page_index); if (!pDict) return FALSE; - CPDF_Page page; page.Load(pDoc, pDict); *width = page.GetPageWidth(); *height = page.GetPageHeight(); +#endif // PDF_ENABLE_XFA return TRUE; } @@ -855,6 +1080,60 @@ DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document, return name_tree.LookupNamedDest(pDoc, name); } +#ifdef PDF_ENABLE_XFA +FPDF_RESULT FPDF_BStr_Init(FPDF_BSTR* str) { + if (!str) + return -1; + + FXSYS_memset(str, 0, sizeof(FPDF_BSTR)); + return 0; +} + +FPDF_RESULT FPDF_BStr_Set(FPDF_BSTR* str, FPDF_LPCSTR bstr, int length) { + if (!str) + return -1; + if (!bstr || !length) + return -1; + if (length == -1) + length = FXSYS_strlen(bstr); + + if (length == 0) { + if (str->str) { + FX_Free(str->str); + str->str = NULL; + } + str->len = 0; + return 0; + } + + if (str->str && str->len < length) + str->str = FX_Realloc(char, str->str, length + 1); + else if (!str->str) + str->str = FX_Alloc(char, length + 1); + + str->str[length] = 0; + if (str->str == NULL) + return -1; + + FXSYS_memcpy(str->str, bstr, length); + str->len = length; + + return 0; +} + +FPDF_RESULT FPDF_BStr_Clear(FPDF_BSTR* str) { + if (!str) + return -1; + + if (str->str) { + FX_Free(str->str); + str->str = NULL; + } + str->len = 0; + return 0; +} +#endif // PDF_ENABLE_XFA + DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document, int index, void* buffer, diff --git a/fpdfsdk/src/fpdfview_c_api_test.c b/fpdfsdk/src/fpdfview_c_api_test.c index 5ff3dbf5a4..fdf83bec6d 100644 --- a/fpdfsdk/src/fpdfview_c_api_test.c +++ b/fpdfsdk/src/fpdfview_c_api_test.c @@ -104,6 +104,10 @@ int CheckPDFiumCApi() { CHK(FORM_OnMouseMove); CHK(FORM_OnLButtonDown); CHK(FORM_OnLButtonUp); +#ifdef PDF_ENABLE_XFA + CHK(FORM_OnRButtonDown); + CHK(FORM_OnRButtonUp); +#endif CHK(FORM_OnKeyDown); CHK(FORM_OnKeyUp); CHK(FORM_OnChar); @@ -115,6 +119,22 @@ int CheckPDFiumCApi() { CHK(FPDF_SetFormFieldHighlightAlpha); CHK(FPDF_RemoveFormFieldHighlight); CHK(FPDF_FFLDraw); +#ifdef PDF_ENABLE_XFA + CHK(FPDF_HasXFAField); + CHK(FPDF_LoadXFA); + CHK(FPDF_Widget_Undo); + CHK(FPDF_Widget_Redo); + CHK(FPDF_Widget_SelectAll); + CHK(FPDF_Widget_Copy); + CHK(FPDF_Widget_Cut); + CHK(FPDF_Widget_Paste); + CHK(FPDF_Widget_ReplaceSpellCheckWord); + CHK(FPDF_Widget_GetSpellCheckWords); + CHK(FPDF_StringHandleCounts); + CHK(FPDF_StringHandleGetStringByIndex); + CHK(FPDF_StringHandleRelease); + CHK(FPDF_StringHandleAddString); +#endif // fpdf_ppo.h CHK(FPDF_ImportPages); @@ -211,6 +231,11 @@ int CheckPDFiumCApi() { CHK(FPDF_CountNamedDests); CHK(FPDF_GetNamedDestByName); CHK(FPDF_GetNamedDest); +#ifdef PDF_ENABLE_XFA + CHK(FPDF_BStr_Init); + CHK(FPDF_BStr_Set); + CHK(FPDF_BStr_Clear); +#endif return 1; } diff --git a/fpdfsdk/src/fpdfxfa/fpdfxfa_app.cpp b/fpdfsdk/src/fpdfxfa/fpdfxfa_app.cpp new file mode 100644 index 0000000000..1006bf9c44 --- /dev/null +++ b/fpdfsdk/src/fpdfxfa/fpdfxfa_app.cpp @@ -0,0 +1,539 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fpdfsdk/include/fsdk_define.h" +#include "fpdfsdk/include/fsdk_mgr.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h" +#include "fpdfsdk/include/javascript/IJavaScript.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_app.h" +#include "public/fpdf_formfill.h" + +CPDFXFA_App* CPDFXFA_App::g_pApp = NULL; + +CPDFXFA_App* CPDFXFA_App::GetInstance() { + if (!g_pApp) { + g_pApp = new CPDFXFA_App(); + } + return g_pApp; +} + +void CPDFXFA_App::ReleaseInstance() { + delete g_pApp; + g_pApp = NULL; +} + +CPDFXFA_App::CPDFXFA_App() + : m_bJavaScriptInitialized(FALSE), + m_pXFAApp(NULL), + m_pFontMgr(NULL), + m_hJSERuntime(NULL), + m_csAppType(JS_STR_VIEWERTYPE_STANDARD), + m_bOwnedRuntime(false) { + m_pEnvList.RemoveAll(); +} + +CPDFXFA_App::~CPDFXFA_App() { + delete m_pFontMgr; + m_pFontMgr = NULL; + + delete m_pXFAApp; + m_pXFAApp = NULL; + +#ifdef PDF_ENABLE_XFA + FXJSE_Runtime_Release(m_hJSERuntime, m_bOwnedRuntime); + m_hJSERuntime = NULL; + + FXJSE_Finalize(); + BC_Library_Destory(); +#endif +} + +FX_BOOL CPDFXFA_App::Initialize(FXJSE_HRUNTIME hRuntime) { +#ifdef PDF_ENABLE_XFA + BC_Library_Init(); + FXJSE_Initialize(); + + m_bOwnedRuntime = !hRuntime; + m_hJSERuntime = hRuntime ? hRuntime : FXJSE_Runtime_Create(); + if (!m_hJSERuntime) + return FALSE; + + m_pXFAApp = IXFA_App::Create(this); + if (!m_pXFAApp) + return FALSE; + + m_pFontMgr = IXFA_FontMgr::CreateDefault(); + if (!m_pFontMgr) + return FALSE; + + m_pXFAApp->SetDefaultFontMgr(m_pFontMgr); +#endif + return TRUE; +} + +FX_BOOL CPDFXFA_App::AddFormFillEnv(CPDFDoc_Environment* pEnv) { + if (!pEnv) + return FALSE; + + m_pEnvList.Add(pEnv); + return TRUE; +} + +FX_BOOL CPDFXFA_App::RemoveFormFillEnv(CPDFDoc_Environment* pEnv) { + if (!pEnv) + return FALSE; + + int nFind = m_pEnvList.Find(pEnv); + if (nFind != -1) { + m_pEnvList.RemoveAt(nFind); + return TRUE; + } + + return FALSE; +} + +void CPDFXFA_App::GetAppType(CFX_WideString& wsAppType) { + wsAppType = m_csAppType; +} + +void CPDFXFA_App::GetAppName(CFX_WideString& wsName) { + CPDFDoc_Environment* pEnv = m_pEnvList.GetAt(0); + if (pEnv) { + wsName = pEnv->FFI_GetAppName(); + } +} + +void CPDFXFA_App::SetAppType(const CFX_WideStringC& wsAppType) { + m_csAppType = wsAppType; +} + +void CPDFXFA_App::GetLanguage(CFX_WideString& wsLanguage) { + CPDFDoc_Environment* pEnv = m_pEnvList.GetAt(0); + if (pEnv) { + wsLanguage = pEnv->FFI_GetLanguage(); + } +} + +void CPDFXFA_App::GetPlatform(CFX_WideString& wsPlatform) { + CPDFDoc_Environment* pEnv = m_pEnvList.GetAt(0); + if (pEnv) { + wsPlatform = pEnv->FFI_GetPlatform(); + } +} + +void CPDFXFA_App::GetVariation(CFX_WideString& wsVariation) { + wsVariation = JS_STR_VIEWERVARIATION; +} + +void CPDFXFA_App::GetVersion(CFX_WideString& wsVersion) { + wsVersion = JS_STR_VIEWERVERSION_XFA; +} + +void CPDFXFA_App::Beep(FX_DWORD dwType) { + CPDFDoc_Environment* pEnv = m_pEnvList.GetAt(0); + if (pEnv) { + pEnv->JS_appBeep(dwType); + } +} + +int32_t CPDFXFA_App::MsgBox(const CFX_WideStringC& wsMessage, + const CFX_WideStringC& wsTitle, + FX_DWORD dwIconType, + FX_DWORD dwButtonType) { + CPDFDoc_Environment* pEnv = m_pEnvList.GetAt(0); + if (!pEnv) + return -1; + + FX_DWORD iconType = 0; + int iButtonType = 0; + switch (dwIconType) { + case XFA_MBICON_Error: + iconType |= 0; + break; + case XFA_MBICON_Warning: + iconType |= 1; + break; + case XFA_MBICON_Question: + iconType |= 2; + break; + case XFA_MBICON_Status: + iconType |= 3; + break; + } + switch (dwButtonType) { + case XFA_MB_OK: + iButtonType |= 0; + break; + case XFA_MB_OKCancel: + iButtonType |= 1; + break; + case XFA_MB_YesNo: + iButtonType |= 2; + break; + case XFA_MB_YesNoCancel: + iButtonType |= 3; + break; + } + int32_t iRet = pEnv->JS_appAlert(wsMessage.GetPtr(), wsTitle.GetPtr(), + iButtonType, iconType); + switch (iRet) { + case 1: + return XFA_IDOK; + case 2: + return XFA_IDCancel; + case 3: + return XFA_IDNo; + case 4: + return XFA_IDYes; + } + return XFA_IDYes; +} + +void CPDFXFA_App::Response(CFX_WideString& wsAnswer, + const CFX_WideStringC& wsQuestion, + const CFX_WideStringC& wsTitle, + const CFX_WideStringC& wsDefaultAnswer, + FX_BOOL bMark) { + CPDFDoc_Environment* pEnv = m_pEnvList.GetAt(0); + if (pEnv) { + int nLength = 2048; + char* pBuff = new char[nLength]; + nLength = pEnv->JS_appResponse(wsQuestion.GetPtr(), wsTitle.GetPtr(), + wsDefaultAnswer.GetPtr(), NULL, bMark, pBuff, + nLength); + if (nLength > 0) { + nLength = nLength > 2046 ? 2046 : nLength; + pBuff[nLength] = 0; + pBuff[nLength + 1] = 0; + wsAnswer = CFX_WideString::FromUTF16LE( + reinterpret_cast<const unsigned short*>(pBuff), + nLength / sizeof(unsigned short)); + } + delete[] pBuff; + } +} + +int32_t CPDFXFA_App::GetCurDocumentInBatch() { + CPDFDoc_Environment* pEnv = m_pEnvList.GetAt(0); + if (pEnv) { + return pEnv->FFI_GetCurDocument(); + } + return 0; +} + +int32_t CPDFXFA_App::GetDocumentCountInBatch() { + CPDFDoc_Environment* pEnv = m_pEnvList.GetAt(0); + if (pEnv) { + return pEnv->FFI_GetDocumentCount(); + } + + return 0; +} + +IFX_FileRead* CPDFXFA_App::DownloadURL(const CFX_WideStringC& wsURL) { + CPDFDoc_Environment* pEnv = m_pEnvList.GetAt(0); + if (pEnv) { + return pEnv->FFI_DownloadFromURL(wsURL.GetPtr()); + } + return NULL; +} + +FX_BOOL CPDFXFA_App::PostRequestURL(const CFX_WideStringC& wsURL, + const CFX_WideStringC& wsData, + const CFX_WideStringC& wsContentType, + const CFX_WideStringC& wsEncode, + const CFX_WideStringC& wsHeader, + CFX_WideString& wsResponse) { + CPDFDoc_Environment* pEnv = m_pEnvList.GetAt(0); + if (pEnv) { + wsResponse = pEnv->FFI_PostRequestURL(wsURL.GetPtr(), wsData.GetPtr(), + wsContentType.GetPtr(), + wsEncode.GetPtr(), wsHeader.GetPtr()); + return TRUE; + } + return FALSE; +} + +FX_BOOL CPDFXFA_App::PutRequestURL(const CFX_WideStringC& wsURL, + const CFX_WideStringC& wsData, + const CFX_WideStringC& wsEncode) { + CPDFDoc_Environment* pEnv = m_pEnvList.GetAt(0); + if (pEnv) { + return pEnv->FFI_PutRequestURL(wsURL.GetPtr(), wsData.GetPtr(), + wsEncode.GetPtr()); + } + return FALSE; +} + +void CPDFXFA_App::LoadString(int32_t iStringID, CFX_WideString& wsString) { + switch (iStringID) { + case XFA_IDS_ValidateFailed: + wsString = L"%s validate failed"; + return; + case XFA_IDS_CalcOverride: + wsString = L"Calculate Override"; + return; + case XFA_IDS_ModifyField: + wsString = L"Are you sure you want to modify this field?"; + return; + case XFA_IDS_NotModifyField: + wsString = L"You are not allowed to modify this field."; + return; + case XFA_IDS_AppName: + wsString = L"Foxit"; + return; + case XFA_IDS_ImageFilter: + wsString = + L"Image " + L"Files(*.bmp;*.jpg;*.png;*.gif;*.tif)|*.bmp;*.jpg;*.png;*.gif;*.tif|" + L"All Files(*.*)|*.*||"; + return; + case XFA_IDS_UNKNOW_CATCHED: + wsString = L"unknown error is catched!"; + return; + case XFA_IDS_Unable_TO_SET: + wsString = L"Unable to set "; + return; + case XFA_IDS_VALUE_EXCALMATORY: + wsString = L" value!"; + return; + case XFA_IDS_INVALID_ENUM_VALUE: + wsString = L"Invalid enumerated value: "; + return; + case XFA_IDS_UNSUPPORT_METHOD: + wsString = L"unsupport %s method."; + return; + case XFA_IDS_UNSUPPORT_PROP: + wsString = L"unsupport %s property."; + return; + case XFA_IDS_INVAlID_PROP_SET: + wsString = L"Invalid property set operation;"; + return; + case XFA_IDS_NOT_DEFAUL_VALUE: + wsString = L" doesn't have a default property"; + return; + case XFA_IDS_UNABLE_SET_LANGUAGE: + wsString = L"Unable to set language value!"; + return; + case XFA_IDS_UNABLE_SET_NUMPAGES: + wsString = L"Unable to set numPages value!"; + return; + case XFA_IDS_UNABLE_SET_PLATFORM: + wsString = L"Unable to set platform value!"; + return; + case XFA_IDS_UNABLE_SET_VALIDATIONENABLE: + wsString = L"Unable to set validationsEnabled value!"; + return; + case XFA_IDS_UNABLE_SET_VARIATION: + wsString = L"Unable to set variation value!"; + return; + case XFA_IDS_UNABLE_SET_VERSION: + wsString = L"Unable to set version value!"; + return; + case XFA_IDS_UNABLE_SET_READY: + wsString = L"Unable to set ready value!"; + return; + case XFA_IDS_NUMBER_OF_OCCUR: + wsString = + L"The element [%s] has violated its allowable number of occurrences"; + return; + case XFA_IDS_UNABLE_SET_CLASS_NAME: + wsString = L"Unable to set className value!"; + return; + case XFA_IDS_UNABLE_SET_LENGTH_VALUE: + wsString = L"Unable to set length value!"; + return; + case XFA_IDS_UNSUPPORT_CHAR: + wsString = L"unsupported char '%c'"; + return; + case XFA_IDS_BAD_SUFFIX: + wsString = L"bad suffix on number"; + return; + case XFA_IDS_EXPECTED_IDENT: + wsString = L"expected identifier instead of '%s'"; + return; + case XFA_IDS_EXPECTED_STRING: + wsString = L"expected '%s' instead of '%s'"; + return; + case XFA_IDS_INVALIDATE_CHAR: + wsString = L"invalidate char '%c'"; + return; + case XFA_IDS_REDEFINITION: + wsString = L"'%s' redefinition "; + return; + case XFA_IDS_INVALIDATE_TOKEN: + wsString = L"invalidate token '%s'"; + return; + case XFA_IDS_INVALIDATE_EXPRESSION: + wsString = L"invalidate expression '%s'"; + return; + case XFA_IDS_UNDEFINE_IDENTIFIER: + wsString = L"undefined identifier '%s'"; + return; + case XFA_IDS_INVALIDATE_LEFTVALUE: + wsString = L"invalidate left-value '%s'"; + return; + case XFA_IDS_COMPILER_ERROR: + wsString = L"compiler error"; + return; + case XFA_IDS_CANNOT_MODIFY_VALUE: + wsString = L"can't modify the '%s' value"; + return; + case XFA_IDS_ERROR_PARAMETERS: + wsString = L"function '%s' has not %d parameters"; + return; + case XFA_IDS_EXPECT_ENDIF: + wsString = L"expected 'endif' instead of '%s'"; + return; + case XFA_IDS_UNEXPECTED_EXPRESSION: + wsString = L"unexpected expression '%s'"; + return; + case XFA_IDS_CONDITION_IS_NULL: + wsString = L"condition is null"; + return; + case XFA_IDS_ILLEGALBREAK: + wsString = L"illegal break"; + return; + case XFA_IDS_ILLEGALCONTINUE: + wsString = L"illegal continue"; + return; + case XFA_IDS_EXPECTED_OPERATOR: + wsString = L"expected operator '%s' instead of '%s'"; + return; + case XFA_IDS_DIVIDE_ZERO: + wsString = L"divide by zero"; + return; + case XFA_IDS_CANNOT_COVERT_OBJECT: + wsString = L"%s.%s can not covert to object"; + return; + case XFA_IDS_NOT_FOUND_CONTAINER: + wsString = L"can not found container '%s'"; + return; + case XFA_IDS_NOT_FOUND_PROPERTY: + wsString = L"can not found property '%s'"; + return; + case XFA_IDS_NOT_FOUND_METHOD: + wsString = L"can not found method '%s'"; + return; + case XFA_IDS_NOT_FOUND_CONST: + wsString = L"can not found const '%s'"; + return; + case XFA_IDS_NOT_ASSIGN_OBJECT: + wsString = L"can not direct assign value to object"; + return; + case XFA_IDS_IVALIDATE_INSTRUCTION: + wsString = L"invalidate instruction"; + return; + case XFA_IDS_EXPECT_NUMBER: + wsString = L"expected number instead of '%s'"; + return; + case XFA_IDS_VALIDATE_OUT_ARRAY: + wsString = L"validate access index '%s' out of array"; + return; + case XFA_IDS_CANNOT_ASSIGN_IDENT: + wsString = L"can not assign to %s"; + return; + case XFA_IDS_NOT_FOUNT_FUNCTION: + wsString = L"can not found '%s' function"; + return; + case XFA_IDS_NOT_ARRAY: + wsString = L"'%s' doesn't an array"; + return; + case XFA_IDS_OUT_ARRAY: + wsString = L"out of range of '%s' array"; + return; + case XFA_IDS_NOT_SUPPORT_CALC: + wsString = L"'%s' operator can not support array calculate"; + return; + case XFA_IDS_ARGUMENT_NOT_ARRAY: + wsString = L"'%s' function's %d argument can not be array"; + return; + case XFA_IDS_ARGUMENT_EXPECT_CONTAINER: + wsString = L"'%s' argument expected a container"; + return; + case XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT: + wsString = + L"an attempt was made to reference property '%s' of a non-object in " + L"SOM expression %s"; + return; + case XFA_IDS_FUNCTION_IS_BUILDIN: + wsString = L"function '%s' is buildin"; + return; + case XFA_IDS_ERROR_MSG: + wsString = L"%s : %s"; + return; + case XFA_IDS_INDEX_OUT_OF_BOUNDS: + wsString = L"Index value is out of bounds"; + return; + case XFA_IDS_INCORRECT_NUMBER_OF_METHOD: + wsString = L"Incorrect number of parameters calling method '%s'"; + return; + case XFA_IDS_ARGUMENT_MISMATCH: + wsString = L"Argument mismatch in property or function argument"; + return; + case XFA_IDS_INVALID_ENUMERATE: + wsString = L"Invalid enumerated value: %s"; + return; + case XFA_IDS_INVALID_APPEND: + wsString = + L"Invalid append operation: %s cannot have a child element of %s"; + return; + case XFA_IDS_SOM_EXPECTED_LIST: + wsString = + L"SOM expression returned list when single result was expected"; + return; + case XFA_IDS_NOT_HAVE_PROPERTY: + wsString = L"'%s' doesn't have property '%s'"; + return; + case XFA_IDS_INVALID_NODE_TYPE: + wsString = L"Invalid node type : '%s'"; + return; + case XFA_IDS_VIOLATE_BOUNDARY: + wsString = + L"The element [%s] has violated its allowable number of occurrences"; + return; + case XFA_IDS_SERVER_DENY: + wsString = L"Server does not permit"; + return; + case XFA_IDS_ValidateLimit: + wsString = FX_WSTRC( + L"Message limit exceeded. Remaining %d validation errors not " + L"reported."); + return; + case XFA_IDS_ValidateNullWarning: + wsString = FX_WSTRC( + L"%s cannot be left blank. To ignore validations for %s, click " + L"Ignore."); + return; + case XFA_IDS_ValidateNullError: + wsString = FX_WSTRC(L"%s cannot be left blank."); + return; + case XFA_IDS_ValidateWarning: + wsString = FX_WSTRC( + L"The value you entered for %s is invalid. To ignore validations for " + L"%s, click Ignore."); + return; + case XFA_IDS_ValidateError: + wsString = FX_WSTRC(L"The value you entered for %s is invalid."); + return; + } +} + +FX_BOOL CPDFXFA_App::ShowFileDialog(const CFX_WideStringC& wsTitle, + const CFX_WideStringC& wsFilter, + CFX_WideStringArray& wsPathArr, + FX_BOOL bOpen) { + return FALSE; +} + +IFWL_AdapterTimerMgr* CPDFXFA_App::GetTimerMgr() { + CXFA_FWLAdapterTimerMgr* pAdapter = NULL; + CPDFDoc_Environment* pEnv = m_pEnvList.GetAt(0); + if (pEnv) + pAdapter = new CXFA_FWLAdapterTimerMgr(pEnv); + return pAdapter; +} diff --git a/fpdfsdk/src/fpdfxfa/fpdfxfa_doc.cpp b/fpdfsdk/src/fpdfxfa/fpdfxfa_doc.cpp new file mode 100644 index 0000000000..b8549fce74 --- /dev/null +++ b/fpdfsdk/src/fpdfxfa/fpdfxfa_doc.cpp @@ -0,0 +1,1261 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fpdfsdk/include/fsdk_define.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" +#include "fpdfsdk/include/fsdk_mgr.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_app.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_page.h" +#include "fpdfsdk/include/javascript/IJavaScript.h" +#include "public/fpdf_formfill.h" + +#define IDS_XFA_Validate_Input \ + "At least one required field was empty. Please fill in the required " \ + "fields\r\n(highlighted) before continuing." + +// submit +#define FXFA_CONFIG 0x00000001 +#define FXFA_TEMPLATE 0x00000010 +#define FXFA_LOCALESET 0x00000100 +#define FXFA_DATASETS 0x00001000 +#define FXFA_XMPMETA 0x00010000 +#define FXFA_XFDF 0x00100000 +#define FXFA_FORM 0x01000000 +#define FXFA_PDF 0x10000000 + +#ifndef _WIN32 +extern void SetLastError(int err); + +extern int GetLastError(); +#endif + +CPDFXFA_Document::CPDFXFA_Document(CPDF_Document* pPDFDoc, + CPDFXFA_App* pProvider) + : m_iDocType(DOCTYPE_PDF), + m_pPDFDoc(pPDFDoc), + m_pSDKDoc(nullptr), + m_pXFADoc(nullptr), + m_pXFADocView(nullptr), + m_pApp(pProvider), + m_pJSContext(nullptr) { +} + +CPDFXFA_Document::~CPDFXFA_Document() { + if (m_pJSContext && m_pSDKDoc && m_pSDKDoc->GetEnv()) + m_pSDKDoc->GetEnv()->GetJSRuntime()->ReleaseContext(m_pJSContext); + + delete m_pSDKDoc; + + if (m_pPDFDoc) { + CPDF_Parser* pParser = m_pPDFDoc->GetParser(); + if (pParser) + delete pParser; + else + delete m_pPDFDoc; + } + if (m_pXFADoc) { + IXFA_App* pApp = m_pApp->GetXFAApp(); + if (pApp) { + IXFA_DocHandler* pDocHandler = pApp->GetDocHandler(); + if (pDocHandler) { + CloseXFADoc(pDocHandler); + } + } + delete m_pXFADoc; + } +} + +FX_BOOL CPDFXFA_Document::LoadXFADoc() { + if (!m_pPDFDoc) + return FALSE; + + m_XFAPageList.RemoveAll(); + + IXFA_App* pApp = m_pApp->GetXFAApp(); + if (!pApp) + return FALSE; + + m_pXFADoc = pApp->CreateDoc(this, m_pPDFDoc); + if (!m_pXFADoc) { + SetLastError(FPDF_ERR_XFALOAD); + return FALSE; + } + + IXFA_DocHandler* pDocHandler = pApp->GetDocHandler(); + if (!pDocHandler) { + SetLastError(FPDF_ERR_XFALOAD); + return FALSE; + } + + pDocHandler->StartLoad(m_pXFADoc); + int iStatus = pDocHandler->DoLoad(m_pXFADoc, NULL); + if (iStatus != XFA_PARSESTATUS_Done) { + CloseXFADoc(pDocHandler); + SetLastError(FPDF_ERR_XFALOAD); + return FALSE; + } + pDocHandler->StopLoad(m_pXFADoc); + pDocHandler->SetJSERuntime(m_pXFADoc, m_pApp->GetJSERuntime()); + + if (pDocHandler->GetDocType(m_pXFADoc) == XFA_DOCTYPE_Dynamic) + m_iDocType = DOCTYPE_DYNAMIC_XFA; + else + m_iDocType = DOCTYPE_STATIC_XFA; + + m_pXFADocView = pDocHandler->CreateDocView(m_pXFADoc, XFA_DOCVIEW_View); + if (m_pXFADocView->StartLayout() < 0) { + CloseXFADoc(pDocHandler); + SetLastError(FPDF_ERR_XFALAYOUT); + return FALSE; + } + + m_pXFADocView->DoLayout(NULL); + m_pXFADocView->StopLayout(); + return TRUE; +} + +int CPDFXFA_Document::GetPageCount() { + if (!m_pPDFDoc && !m_pXFADoc) + return 0; + + switch (m_iDocType) { + case DOCTYPE_PDF: + case DOCTYPE_STATIC_XFA: + if (m_pPDFDoc) + return m_pPDFDoc->GetPageCount(); + case DOCTYPE_DYNAMIC_XFA: + if (m_pXFADoc) + return m_pXFADocView->CountPageViews(); + default: + return 0; + } + + return 0; +} + +CPDFXFA_Page* CPDFXFA_Document::GetPage(int page_index) { + if (page_index < 0) + return nullptr; + CPDFXFA_Page* pPage = nullptr; + int nCount = m_XFAPageList.GetSize(); + if (nCount > 0 && page_index < nCount) { + pPage = m_XFAPageList.GetAt(page_index); + if (pPage) + pPage->AddRef(); + } else { + m_XFAPageList.SetSize(GetPageCount()); + } + if (pPage) + return pPage; + pPage = new CPDFXFA_Page(this, page_index); + if (!pPage->LoadPage()) { + delete pPage; + return nullptr; + } + m_XFAPageList.SetAt(page_index, pPage); + return pPage; +} + +CPDFXFA_Page* CPDFXFA_Document::GetPage(IXFA_PageView* pPage) { + if (!pPage) + return NULL; + + if (!m_pXFADoc) + return NULL; + + if (m_iDocType != DOCTYPE_DYNAMIC_XFA) + return NULL; + + int nSize = m_XFAPageList.GetSize(); + for (int i = 0; i < nSize; i++) { + CPDFXFA_Page* pTempPage = m_XFAPageList.GetAt(i); + if (!pTempPage) + continue; + if (pTempPage->GetXFAPageView() && pTempPage->GetXFAPageView() == pPage) + return pTempPage; + } + + return NULL; +} + +void CPDFXFA_Document::RemovePage(CPDFXFA_Page* page) { + m_XFAPageList.SetAt(page->GetPageIndex(), NULL); +} + +CPDFSDK_Document* CPDFXFA_Document::GetSDKDocument( + CPDFDoc_Environment* pFormFillEnv) { + if (!m_pSDKDoc && pFormFillEnv) + m_pSDKDoc = new CPDFSDK_Document(this, pFormFillEnv); + return m_pSDKDoc; +} + +void CPDFXFA_Document::FXRect2PDFRect(const CFX_RectF& fxRectF, + CPDF_Rect& pdfRect) { + pdfRect.left = fxRectF.left; + pdfRect.top = fxRectF.bottom(); + pdfRect.right = fxRectF.right(); + pdfRect.bottom = fxRectF.top; +} + +void CPDFXFA_Document::SetChangeMark(IXFA_Doc* hDoc) { + if (hDoc == m_pXFADoc && m_pSDKDoc) { + m_pSDKDoc->SetChangeMark(); + } +} + +FX_BOOL CPDFXFA_Document::GetChangeMark(IXFA_Doc* hDoc) { + if (hDoc == m_pXFADoc && m_pSDKDoc) + return m_pSDKDoc->GetChangeMark(); + return FALSE; +} + +void CPDFXFA_Document::InvalidateRect(IXFA_PageView* pPageView, + const CFX_RectF& rt, + FX_DWORD dwFlags /* = 0 */) { + if (!m_pXFADoc || !m_pSDKDoc) + return; + + if (m_iDocType != DOCTYPE_DYNAMIC_XFA) + return; + + CPDF_Rect rcPage; + FXRect2PDFRect(rt, rcPage); + + CPDFXFA_Page* pPage = GetPage(pPageView); + + if (pPage == NULL) + return; + + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (!pEnv) + return; + + pEnv->FFI_Invalidate((FPDF_PAGE)pPage, rcPage.left, rcPage.bottom, + rcPage.right, rcPage.top); +} + +void CPDFXFA_Document::InvalidateRect(IXFA_Widget* hWidget, + FX_DWORD dwFlags /* = 0 */) { + if (!hWidget) + return; + + if (!m_pXFADoc || !m_pSDKDoc || !m_pXFADocView) + return; + + if (m_iDocType != DOCTYPE_DYNAMIC_XFA) + return; + + IXFA_WidgetHandler* pWidgetHandler = m_pXFADocView->GetWidgetHandler(); + if (!pWidgetHandler) + return; + + IXFA_PageView* pPageView = pWidgetHandler->GetPageView(hWidget); + if (!pPageView) + return; + + CFX_RectF rect; + pWidgetHandler->GetRect(hWidget, rect); + InvalidateRect(pPageView, rect, dwFlags); +} + +void CPDFXFA_Document::DisplayCaret(IXFA_Widget* hWidget, + FX_BOOL bVisible, + const CFX_RectF* pRtAnchor) { + if (!hWidget || pRtAnchor == NULL) + return; + + if (!m_pXFADoc || !m_pSDKDoc || !m_pXFADocView) + return; + + if (m_iDocType != DOCTYPE_DYNAMIC_XFA) + return; + + IXFA_WidgetHandler* pWidgetHandler = m_pXFADocView->GetWidgetHandler(); + if (!pWidgetHandler) + return; + + IXFA_PageView* pPageView = pWidgetHandler->GetPageView(hWidget); + if (!pPageView) + return; + + CPDFXFA_Page* pPage = GetPage(pPageView); + + if (pPage == NULL) + return; + + CPDF_Rect rcCaret; + FXRect2PDFRect(*pRtAnchor, rcCaret); + + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (!pEnv) + return; + + pEnv->FFI_DisplayCaret((FPDF_PAGE)pPage, bVisible, rcCaret.left, rcCaret.top, + rcCaret.right, rcCaret.bottom); +} + +FX_BOOL CPDFXFA_Document::GetPopupPos(IXFA_Widget* hWidget, + FX_FLOAT fMinPopup, + FX_FLOAT fMaxPopup, + const CFX_RectF& rtAnchor, + CFX_RectF& rtPopup) { + if (NULL == hWidget) { + return FALSE; + } + IXFA_PageView* pXFAPageView = + m_pXFADocView->GetWidgetHandler()->GetPageView(hWidget); + if (NULL == pXFAPageView) { + return FALSE; + } + CPDFXFA_Page* pPage = GetPage(pXFAPageView); + if (pPage == NULL) + return FALSE; + + CXFA_WidgetAcc* pWidgetAcc = + m_pXFADocView->GetWidgetHandler()->GetDataAcc(hWidget); + + int nRotate = 0; +#ifdef PDF_ENABLE_XFA + nRotate = pWidgetAcc->GetRotate(); +#endif + + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (pEnv == NULL) + return FALSE; + FS_RECTF pageViewRect; + pEnv->FFI_GetPageViewRect(pPage, pageViewRect); + + CPDF_Rect rcAnchor; + + rcAnchor.left = rtAnchor.left; + rcAnchor.top = rtAnchor.bottom(); + rcAnchor.right = rtAnchor.right(); + rcAnchor.bottom = rtAnchor.top; + + int t1, t2, t; + FX_DWORD dwPos; + FX_FLOAT fPoupHeight; + switch (nRotate) { + case 90: { + t1 = (int)(pageViewRect.right - rcAnchor.right); + t2 = (int)(rcAnchor.left - pageViewRect.left); + if (rcAnchor.bottom < pageViewRect.bottom) { + rtPopup.left += rcAnchor.bottom - pageViewRect.bottom; + } + + break; + } + + case 180: { + t2 = (int)(pageViewRect.top - rcAnchor.top); + t1 = (int)(rcAnchor.bottom - pageViewRect.bottom); + if (rcAnchor.left < pageViewRect.left) { + rtPopup.left += rcAnchor.left - pageViewRect.left; + } + break; + } + case 270: { + t1 = (int)(rcAnchor.left - pageViewRect.left); + t2 = (int)(pageViewRect.right - rcAnchor.right); + + if (rcAnchor.top > pageViewRect.top) { + rtPopup.left -= rcAnchor.top - pageViewRect.top; + } + break; + } + case 0: + default: { + t1 = (int)(pageViewRect.top - rcAnchor.top); + t2 = (int)(rcAnchor.bottom - pageViewRect.bottom); + if (rcAnchor.right > pageViewRect.right) { + rtPopup.left -= rcAnchor.right - pageViewRect.right; + } + break; + } + } + + if (t1 <= 0 && t2 <= 0) { + return FALSE; + } + if (t1 <= 0) { + t = t2; + dwPos = 1; + } else if (t2 <= 0) { + t = t1; + dwPos = 0; + } else if (t1 > t2) { + t = t1; + dwPos = 0; + } else { + t = t2; + dwPos = 1; + } + if (t < fMinPopup) { + fPoupHeight = fMinPopup; + } else if (t > fMaxPopup) { + fPoupHeight = fMaxPopup; + } else { + fPoupHeight = (FX_FLOAT)t; + } + + switch (nRotate) { + case 0: + case 180: { + if (dwPos == 0) { + rtPopup.top = rtAnchor.height; + rtPopup.height = fPoupHeight; + } else { + rtPopup.top = -fPoupHeight; + rtPopup.height = fPoupHeight; + } + break; + } + case 90: + case 270: { + if (dwPos == 0) { + rtPopup.top = rtAnchor.width; + rtPopup.height = fPoupHeight; + } else { + rtPopup.top = -fPoupHeight; + rtPopup.height = fPoupHeight; + } + break; + } + default: + break; + } + + return TRUE; +} + +FX_BOOL CPDFXFA_Document::PopupMenu(IXFA_Widget* hWidget, + CFX_PointF ptPopup, + const CFX_RectF* pRectExclude) { + if (NULL == hWidget) { + return FALSE; + } + IXFA_PageView* pXFAPageView = + m_pXFADocView->GetWidgetHandler()->GetPageView(hWidget); + if (pXFAPageView == NULL) + return FALSE; + CPDFXFA_Page* pPage = GetPage(pXFAPageView); + + if (pPage == NULL) + return FALSE; + + int menuFlag = 0; + + IXFA_MenuHandler* pXFAMenuHander = m_pApp->GetXFAApp()->GetMenuHandler(); + if (pXFAMenuHander->CanUndo(hWidget)) + menuFlag |= FXFA_MEMU_UNDO; + if (pXFAMenuHander->CanRedo(hWidget)) + menuFlag |= FXFA_MEMU_REDO; + if (pXFAMenuHander->CanPaste(hWidget)) + menuFlag |= FXFA_MEMU_PASTE; + if (pXFAMenuHander->CanCopy(hWidget)) + menuFlag |= FXFA_MEMU_COPY; + if (pXFAMenuHander->CanCut(hWidget)) + menuFlag |= FXFA_MEMU_CUT; + if (pXFAMenuHander->CanSelectAll(hWidget)) + menuFlag |= FXFA_MEMU_SELECTALL; + + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (pEnv == NULL) + return FALSE; + + return pEnv->FFI_PopupMenu(pPage, hWidget, menuFlag, ptPopup, NULL); +} + +void CPDFXFA_Document::PageViewEvent(IXFA_PageView* pPageView, + FX_DWORD dwFlags) { + if (!pPageView || (dwFlags != XFA_PAGEVIEWEVENT_PostAdded && + dwFlags != XFA_PAGEVIEWEVENT_PostRemoved)) { + return; + } + CPDFXFA_Page* pPage = nullptr; + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (dwFlags == XFA_PAGEVIEWEVENT_PostAdded) { + int nPageIndex = pPageView->GetPageViewIndex(); + pPage = GetPage(nPageIndex); + if (pPage) + pPage->SetXFAPageView(pPageView); + pEnv->FFI_PageEvent(nPageIndex, dwFlags); + return; + } + pPage = GetPage(pPageView); + if (!pPage) + return; + pEnv->FFI_PageEvent(pPage->GetPageIndex(), dwFlags); + m_pSDKDoc->GetPageView(pPage)->ClearFXAnnots(); + pPage->Release(); +} + +void CPDFXFA_Document::WidgetEvent(IXFA_Widget* hWidget, + CXFA_WidgetAcc* pWidgetData, + FX_DWORD dwEvent, + void* pParam, + void* pAdditional) { + if (m_iDocType != DOCTYPE_DYNAMIC_XFA || !hWidget) + return; + + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (!pEnv) + return; + + IXFA_PageView* pPageView = + m_pXFADocView->GetWidgetHandler()->GetPageView(hWidget); + if (pPageView == NULL) + return; + + CPDFXFA_Page* pXFAPage = GetPage(pPageView); + if (pXFAPage == NULL) + return; + + CPDFSDK_PageView* pSdkPageView = m_pSDKDoc->GetPageView(pXFAPage); + if (dwEvent == XFA_WIDGETEVENT_PostAdded) { + pSdkPageView->AddAnnot(hWidget); + + } else if (dwEvent == XFA_WIDGETEVENT_PreRemoved) { + CPDFSDK_Annot* pAnnot = pSdkPageView->GetAnnotByXFAWidget(hWidget); + if (pAnnot) { + pSdkPageView->DeleteAnnot(pAnnot); + } + } +} + +int32_t CPDFXFA_Document::CountPages(IXFA_Doc* hDoc) { + if (hDoc == m_pXFADoc && m_pSDKDoc) { + return GetPageCount(); + } + return 0; +} +int32_t CPDFXFA_Document::GetCurrentPage(IXFA_Doc* hDoc) { + if (hDoc != m_pXFADoc || !m_pSDKDoc) + return -1; + if (m_iDocType != DOCTYPE_DYNAMIC_XFA) + return -1; + + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (pEnv == NULL) + return -1; + + return pEnv->FFI_GetCurrentPageIndex(this); +} +void CPDFXFA_Document::SetCurrentPage(IXFA_Doc* hDoc, int32_t iCurPage) { + if (hDoc != m_pXFADoc || !m_pSDKDoc || m_iDocType != DOCTYPE_DYNAMIC_XFA || + iCurPage < 0 || iCurPage >= m_pSDKDoc->GetPageCount()) { + return; + } + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (!pEnv) + return; + pEnv->FFI_SetCurrentPage(this, iCurPage); +} +FX_BOOL CPDFXFA_Document::IsCalculationsEnabled(IXFA_Doc* hDoc) { + if (hDoc != m_pXFADoc || !m_pSDKDoc) + return FALSE; + if (m_pSDKDoc->GetInterForm()) + return m_pSDKDoc->GetInterForm()->IsXfaCalculateEnabled(); + + return FALSE; +} +void CPDFXFA_Document::SetCalculationsEnabled(IXFA_Doc* hDoc, + FX_BOOL bEnabled) { + if (hDoc != m_pXFADoc || !m_pSDKDoc) + return; + if (m_pSDKDoc->GetInterForm()) + m_pSDKDoc->GetInterForm()->XfaEnableCalculate(bEnabled); +} + +void CPDFXFA_Document::GetTitle(IXFA_Doc* hDoc, CFX_WideString& wsTitle) { + if (hDoc != m_pXFADoc) + return; + if (m_pPDFDoc == NULL) + return; + CPDF_Dictionary* pInfoDict = m_pPDFDoc->GetInfo(); + + if (pInfoDict == NULL) + return; + + CFX_ByteString csTitle = pInfoDict->GetStringBy("Title"); + wsTitle = wsTitle.FromLocal(csTitle.GetBuffer(csTitle.GetLength())); + csTitle.ReleaseBuffer(csTitle.GetLength()); +} +void CPDFXFA_Document::SetTitle(IXFA_Doc* hDoc, + const CFX_WideStringC& wsTitle) { + if (hDoc != m_pXFADoc) + return; + if (m_pPDFDoc == NULL) + return; + CPDF_Dictionary* pInfoDict = m_pPDFDoc->GetInfo(); + + if (pInfoDict == NULL) + return; + pInfoDict->SetAt("Title", new CPDF_String(wsTitle)); +} +void CPDFXFA_Document::ExportData(IXFA_Doc* hDoc, + const CFX_WideStringC& wsFilePath, + FX_BOOL bXDP) { + if (hDoc != m_pXFADoc) + return; + if (m_iDocType != DOCTYPE_DYNAMIC_XFA && m_iDocType != DOCTYPE_STATIC_XFA) + return; + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (pEnv == NULL) + return; + int fileType = bXDP ? FXFA_SAVEAS_XDP : FXFA_SAVEAS_XML; + CFX_ByteString bs = CFX_WideString(wsFilePath).UTF16LE_Encode(); + + if (wsFilePath.IsEmpty()) { + if (!pEnv->GetFormFillInfo() || + pEnv->GetFormFillInfo()->m_pJsPlatform == NULL) + return; + CFX_WideString filepath = pEnv->JS_fieldBrowse(); + bs = filepath.UTF16LE_Encode(); + } + int len = bs.GetLength() / sizeof(unsigned short); + FPDF_FILEHANDLER* pFileHandler = pEnv->FFI_OpenFile( + bXDP ? FXFA_SAVEAS_XDP : FXFA_SAVEAS_XML, + (FPDF_WIDESTRING)bs.GetBuffer(len * sizeof(unsigned short)), "wb"); + bs.ReleaseBuffer(len * sizeof(unsigned short)); + + if (pFileHandler == NULL) + return; + + CFPDF_FileStream fileWrite(pFileHandler); + + IXFA_DocHandler* pXFADocHander = m_pApp->GetXFAApp()->GetDocHandler(); + CFX_ByteString content; + if (fileType == FXFA_SAVEAS_XML) { + content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"; + fileWrite.WriteBlock((const FX_CHAR*)content, fileWrite.GetSize(), + content.GetLength()); + CFX_WideStringC data(L"data"); + if (pXFADocHander->SavePackage(m_pXFADocView->GetDoc(), data, &fileWrite)) { + // TODO: Maybe report error. + } + } else if (fileType == FXFA_SAVEAS_XDP) { + if (m_pPDFDoc == NULL) + return; + CPDF_Dictionary* pRoot = m_pPDFDoc->GetRoot(); + if (pRoot == NULL) + return; + CPDF_Dictionary* pAcroForm = pRoot->GetDictBy("AcroForm"); + if (NULL == pAcroForm) + return; + CPDF_Object* pXFA = pAcroForm->GetElement("XFA"); + if (pXFA == NULL) + return; + if (!pXFA->IsArray()) + return; + CPDF_Array* pArray = pXFA->GetArray(); + if (NULL == pArray) + return; + int size = pArray->GetCount(); + for (int i = 1; i < size; i += 2) { + CPDF_Object* pPDFObj = pArray->GetElement(i); + CPDF_Object* pPrePDFObj = pArray->GetElement(i - 1); + if (!pPrePDFObj->IsString()) + continue; + if (!pPDFObj->IsReference()) + continue; + CPDF_Object* pDirectObj = pPDFObj->GetDirect(); + if (!pDirectObj->IsStream()) + continue; + if (pPrePDFObj->GetString() == "form") { + CFX_WideStringC form(L"form"); + pXFADocHander->SavePackage(m_pXFADocView->GetDoc(), form, &fileWrite); + } else if (pPrePDFObj->GetString() == "datasets") { + CFX_WideStringC datasets(L"datasets"); + pXFADocHander->SavePackage(m_pXFADocView->GetDoc(), datasets, + &fileWrite); + } else { + if (i == size - 1) { + CFX_WideString wPath = CFX_WideString::FromUTF16LE( + (unsigned short*)(const FX_CHAR*)bs, + bs.GetLength() / sizeof(unsigned short)); + CFX_ByteString bPath = wPath.UTF8Encode(); + CFX_ByteString szFormat = + "\n<pdf href=\"%s\" xmlns=\"http://ns.adobe.com/xdp/pdf/\"/>"; + content.Format(szFormat, (char*)(const FX_CHAR*)bPath); + fileWrite.WriteBlock((const FX_CHAR*)content, fileWrite.GetSize(), + content.GetLength()); + } + + CPDF_Stream* pStream = (CPDF_Stream*)pDirectObj; + CPDF_StreamAcc* pAcc = new CPDF_StreamAcc; + pAcc->LoadAllData(pStream); + fileWrite.WriteBlock(pAcc->GetData(), fileWrite.GetSize(), + pAcc->GetSize()); + delete pAcc; + } + } + } + if (!fileWrite.Flush()) { + // TODO: Report error. + } +} +void CPDFXFA_Document::ImportData(IXFA_Doc* hDoc, + const CFX_WideStringC& wsFilePath) { + // TODO... +} + +void CPDFXFA_Document::GotoURL(IXFA_Doc* hDoc, + const CFX_WideStringC& bsURL, + FX_BOOL bAppend) { + if (hDoc != m_pXFADoc) + return; + + if (m_iDocType != DOCTYPE_DYNAMIC_XFA) + return; + + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (pEnv == NULL) + return; + + CFX_WideStringC str(bsURL.GetPtr()); + + pEnv->FFI_GotoURL(this, str, bAppend); +} + +FX_BOOL CPDFXFA_Document::IsValidationsEnabled(IXFA_Doc* hDoc) { + if (hDoc != m_pXFADoc || !m_pSDKDoc) + return FALSE; + if (m_pSDKDoc->GetInterForm()) + return m_pSDKDoc->GetInterForm()->IsXfaValidationsEnabled(); + + return TRUE; +} +void CPDFXFA_Document::SetValidationsEnabled(IXFA_Doc* hDoc, FX_BOOL bEnabled) { + if (hDoc != m_pXFADoc || !m_pSDKDoc) + return; + if (m_pSDKDoc->GetInterForm()) + m_pSDKDoc->GetInterForm()->XfaSetValidationsEnabled(bEnabled); +} +void CPDFXFA_Document::SetFocusWidget(IXFA_Doc* hDoc, IXFA_Widget* hWidget) { + if (hDoc != m_pXFADoc) + return; + + if (NULL == hWidget) { + m_pSDKDoc->SetFocusAnnot(NULL); + return; + } + + int pageViewCount = m_pSDKDoc->GetPageViewCount(); + for (int i = 0; i < pageViewCount; i++) { + CPDFSDK_PageView* pPageView = m_pSDKDoc->GetPageView(i); + if (pPageView == NULL) + continue; + CPDFSDK_Annot* pAnnot = pPageView->GetAnnotByXFAWidget(hWidget); + if (pAnnot) { + m_pSDKDoc->SetFocusAnnot(pAnnot); + break; + } + } +} +void CPDFXFA_Document::Print(IXFA_Doc* hDoc, + int32_t nStartPage, + int32_t nEndPage, + FX_DWORD dwOptions) { + if (hDoc != m_pXFADoc) + return; + + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (pEnv == NULL) + return; + + if (!pEnv->GetFormFillInfo() || + pEnv->GetFormFillInfo()->m_pJsPlatform == NULL) + return; + if (pEnv->GetFormFillInfo()->m_pJsPlatform->Doc_print == NULL) + return; + pEnv->GetFormFillInfo()->m_pJsPlatform->Doc_print( + pEnv->GetFormFillInfo()->m_pJsPlatform, + dwOptions & XFA_PRINTOPT_ShowDialog, nStartPage, nEndPage, + dwOptions & XFA_PRINTOPT_CanCancel, dwOptions & XFA_PRINTOPT_ShrinkPage, + dwOptions & XFA_PRINTOPT_AsImage, dwOptions & XFA_PRINTOPT_ReverseOrder, + dwOptions & XFA_PRINTOPT_PrintAnnot); +} + +void CPDFXFA_Document::GetURL(IXFA_Doc* hDoc, CFX_WideString& wsDocURL) { + if (hDoc != m_pXFADoc) + return; + + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (pEnv == NULL) + return; + + pEnv->FFI_GetURL(this, wsDocURL); +} + +FX_ARGB CPDFXFA_Document::GetHighlightColor(IXFA_Doc* hDoc) { + if (hDoc != m_pXFADoc) + return 0; + if (m_pSDKDoc) { + if (CPDFSDK_InterForm* pInterForm = m_pSDKDoc->GetInterForm()) { + FX_COLORREF color = pInterForm->GetHighlightColor(FPDF_FORMFIELD_XFA); + uint8_t alpha = pInterForm->GetHighlightAlpha(); + FX_ARGB argb = ArgbEncode((int)alpha, color); + return argb; + } + } + return 0; +} + +FX_BOOL CPDFXFA_Document::_NotifySubmit(FX_BOOL bPrevOrPost) { + if (bPrevOrPost) + return _OnBeforeNotifySumbit(); + + _OnAfterNotifySumbit(); + return TRUE; +} + +FX_BOOL CPDFXFA_Document::_OnBeforeNotifySumbit() { +#ifdef PDF_ENABLE_XFA + if (m_iDocType != DOCTYPE_DYNAMIC_XFA && m_iDocType != DOCTYPE_STATIC_XFA) + return TRUE; + if (m_pXFADocView == NULL) + return TRUE; + IXFA_WidgetHandler* pWidgetHandler = m_pXFADocView->GetWidgetHandler(); + if (pWidgetHandler == NULL) + return TRUE; + IXFA_WidgetAccIterator* pWidgetAccIterator = + m_pXFADocView->CreateWidgetAccIterator(); + if (pWidgetAccIterator) { + CXFA_EventParam Param; + Param.m_eType = XFA_EVENT_PreSubmit; + CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext(); + while (pWidgetAcc) { + pWidgetHandler->ProcessEvent(pWidgetAcc, &Param); + pWidgetAcc = pWidgetAccIterator->MoveToNext(); + } + pWidgetAccIterator->Release(); + } + pWidgetAccIterator = m_pXFADocView->CreateWidgetAccIterator(); + if (pWidgetAccIterator) { + CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext(); + pWidgetAcc = pWidgetAccIterator->MoveToNext(); + while (pWidgetAcc) { + int fRet = pWidgetAcc->ProcessValidate(-1); + if (fRet == XFA_EVENTERROR_Error) { + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (pEnv == NULL) + return FALSE; + CFX_WideString ws; + ws.FromLocal(IDS_XFA_Validate_Input); + CFX_ByteString bs = ws.UTF16LE_Encode(); + int len = bs.GetLength() / sizeof(unsigned short); + pEnv->FFI_Alert( + (FPDF_WIDESTRING)bs.GetBuffer(len * sizeof(unsigned short)), + (FPDF_WIDESTRING)L"", 0, 1); + bs.ReleaseBuffer(len * sizeof(unsigned short)); + pWidgetAccIterator->Release(); + return FALSE; + } + pWidgetAcc = pWidgetAccIterator->MoveToNext(); + } + pWidgetAccIterator->Release(); + m_pXFADocView->UpdateDocView(); + } +#endif + return TRUE; +} +void CPDFXFA_Document::_OnAfterNotifySumbit() { + if (m_iDocType != DOCTYPE_DYNAMIC_XFA && m_iDocType != DOCTYPE_STATIC_XFA) + return; + if (m_pXFADocView == NULL) + return; + IXFA_WidgetHandler* pWidgetHandler = m_pXFADocView->GetWidgetHandler(); + if (pWidgetHandler == NULL) + return; + IXFA_WidgetAccIterator* pWidgetAccIterator = + m_pXFADocView->CreateWidgetAccIterator(); + if (pWidgetAccIterator == NULL) + return; + CXFA_EventParam Param; + Param.m_eType = XFA_EVENT_PostSubmit; + + CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext(); + while (pWidgetAcc) { + pWidgetHandler->ProcessEvent(pWidgetAcc, &Param); + pWidgetAcc = pWidgetAccIterator->MoveToNext(); + } + pWidgetAccIterator->Release(); + m_pXFADocView->UpdateDocView(); +} + +FX_BOOL CPDFXFA_Document::SubmitData(IXFA_Doc* hDoc, CXFA_Submit submit) { + if (!_NotifySubmit(TRUE)) + return FALSE; + if (NULL == m_pXFADocView) + return FALSE; + m_pXFADocView->UpdateDocView(); + + FX_BOOL ret = _SubmitData(hDoc, submit); + _NotifySubmit(FALSE); + return ret; +} + +IFX_FileRead* CPDFXFA_Document::OpenLinkedFile(IXFA_Doc* hDoc, + const CFX_WideString& wsLink) { + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (pEnv == NULL) + return FALSE; + CFX_ByteString bs = wsLink.UTF16LE_Encode(); + int len = bs.GetLength() / sizeof(unsigned short); + FPDF_FILEHANDLER* pFileHandler = pEnv->FFI_OpenFile( + 0, (FPDF_WIDESTRING)bs.GetBuffer(len * sizeof(unsigned short)), "rb"); + bs.ReleaseBuffer(len * sizeof(unsigned short)); + + if (pFileHandler == NULL) + return NULL; + return new CFPDF_FileStream(pFileHandler); +} +FX_BOOL CPDFXFA_Document::_ExportSubmitFile(FPDF_FILEHANDLER* pFileHandler, + int fileType, + FPDF_DWORD encodeType, + FPDF_DWORD flag) { + if (NULL == m_pXFADocView) + return FALSE; + IXFA_DocHandler* pDocHandler = m_pApp->GetXFAApp()->GetDocHandler(); + CFX_ByteString content; + + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (pEnv == NULL) + return FALSE; + + CFPDF_FileStream fileStream(pFileHandler); + + if (fileType == FXFA_SAVEAS_XML) { + CFX_WideString ws; + ws.FromLocal("data"); + CFX_ByteString content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"; + fileStream.WriteBlock((const FX_CHAR*)content, 0, content.GetLength()); + pDocHandler->SavePackage(m_pXFADoc, ws, &fileStream); + } else if (fileType == FXFA_SAVEAS_XDP) { + if (flag == 0) + flag = FXFA_CONFIG | FXFA_TEMPLATE | FXFA_LOCALESET | FXFA_DATASETS | + FXFA_XMPMETA | FXFA_XFDF | FXFA_FORM; + if (m_pPDFDoc == NULL) { + fileStream.Flush(); + return FALSE; + } + CPDF_Dictionary* pRoot = m_pPDFDoc->GetRoot(); + if (pRoot == NULL) { + fileStream.Flush(); + return FALSE; + } + CPDF_Dictionary* pAcroForm = pRoot->GetDictBy("AcroForm"); + if (NULL == pAcroForm) { + fileStream.Flush(); + return FALSE; + } + CPDF_Object* pXFA = pAcroForm->GetElement("XFA"); + if (pXFA == NULL) { + fileStream.Flush(); + return FALSE; + } + if (!pXFA->IsArray()) { + fileStream.Flush(); + return FALSE; + } + CPDF_Array* pArray = pXFA->GetArray(); + if (NULL == pArray) { + fileStream.Flush(); + return FALSE; + } + int size = pArray->GetCount(); + for (int i = 1; i < size; i += 2) { + CPDF_Object* pPDFObj = pArray->GetElement(i); + CPDF_Object* pPrePDFObj = pArray->GetElement(i - 1); + if (!pPrePDFObj->IsString()) + continue; + if (!pPDFObj->IsReference()) + continue; + CPDF_Object* pDirectObj = pPDFObj->GetDirect(); + if (!pDirectObj->IsStream()) + continue; + if (pPrePDFObj->GetString() == "config" && !(flag & FXFA_CONFIG)) + continue; + if (pPrePDFObj->GetString() == "template" && !(flag & FXFA_TEMPLATE)) + continue; + if (pPrePDFObj->GetString() == "localeSet" && !(flag & FXFA_LOCALESET)) + continue; + if (pPrePDFObj->GetString() == "datasets" && !(flag & FXFA_DATASETS)) + continue; + if (pPrePDFObj->GetString() == "xmpmeta" && !(flag & FXFA_XMPMETA)) + continue; + if (pPrePDFObj->GetString() == "xfdf" && !(flag & FXFA_XFDF)) + continue; + if (pPrePDFObj->GetString() == "form" && !(flag & FXFA_FORM)) + continue; + if (pPrePDFObj->GetString() == "form") { + CFX_WideString ws; + ws.FromLocal("form"); + pDocHandler->SavePackage(m_pXFADoc, ws, &fileStream); + } else if (pPrePDFObj->GetString() == "datasets") { + CFX_WideString ws; + ws.FromLocal("datasets"); + pDocHandler->SavePackage(m_pXFADoc, ws, &fileStream); + } else { + // PDF,creator. + // TODO: + } + } + } + return TRUE; +} + +void CPDFXFA_Document::_ClearChangeMark() { + if (m_pSDKDoc) + m_pSDKDoc->ClearChangeMark(); +} + +void CPDFXFA_Document::_ToXFAContentFlags(CFX_WideString csSrcContent, + FPDF_DWORD& flag) { + if (csSrcContent.Find(L" config ", 0) != -1) + flag |= FXFA_CONFIG; + if (csSrcContent.Find(L" template ", 0) != -1) + flag |= FXFA_TEMPLATE; + if (csSrcContent.Find(L" localeSet ", 0) != -1) + flag |= FXFA_LOCALESET; + if (csSrcContent.Find(L" datasets ", 0) != -1) + flag |= FXFA_DATASETS; + if (csSrcContent.Find(L" xmpmeta ", 0) != -1) + flag |= FXFA_XMPMETA; + if (csSrcContent.Find(L" xfdf ", 0) != -1) + flag |= FXFA_XFDF; + if (csSrcContent.Find(L" form ", 0) != -1) + flag |= FXFA_FORM; + if (flag == 0) + flag = FXFA_CONFIG | FXFA_TEMPLATE | FXFA_LOCALESET | FXFA_DATASETS | + FXFA_XMPMETA | FXFA_XFDF | FXFA_FORM; +} +FX_BOOL CPDFXFA_Document::_MailToInfo(CFX_WideString& csURL, + CFX_WideString& csToAddress, + CFX_WideString& csCCAddress, + CFX_WideString& csBCCAddress, + CFX_WideString& csSubject, + CFX_WideString& csMsg) { + CFX_WideString srcURL = csURL; + srcURL.TrimLeft(); + if (0 != srcURL.Left(7).CompareNoCase(L"mailto:")) + return FALSE; + int pos = srcURL.Find(L'?', 0); + CFX_WideString tmp; + if (pos == -1) { + pos = srcURL.Find(L'@', 0); + if (pos == -1) + return FALSE; + else { + tmp = srcURL.Right(csURL.GetLength() - 7); + tmp.TrimLeft(); + tmp.TrimRight(); + } + } else { + tmp = srcURL.Left(pos); + tmp = tmp.Right(tmp.GetLength() - 7); + tmp.TrimLeft(); + tmp.TrimRight(); + } + + csToAddress = tmp; + + srcURL = srcURL.Right(srcURL.GetLength() - (pos + 1)); + while (!srcURL.IsEmpty()) { + srcURL.TrimLeft(); + srcURL.TrimRight(); + pos = srcURL.Find(L'&', 0); + if (pos == -1) + tmp = srcURL; + else + tmp = srcURL.Left(pos); + + tmp.TrimLeft(); + tmp.TrimRight(); + if (tmp.GetLength() >= 3 && 0 == tmp.Left(3).CompareNoCase(L"cc=")) { + tmp = tmp.Right(tmp.GetLength() - 3); + if (!csCCAddress.IsEmpty()) + csCCAddress += L';'; + csCCAddress += tmp; + + } else if (tmp.GetLength() >= 4 && + 0 == tmp.Left(4).CompareNoCase(L"bcc=")) { + tmp = tmp.Right(tmp.GetLength() - 4); + if (!csBCCAddress.IsEmpty()) + csBCCAddress += L';'; + csBCCAddress += tmp; + } else if (tmp.GetLength() >= 8 && + 0 == tmp.Left(8).CompareNoCase(L"subject=")) { + tmp = tmp.Right(tmp.GetLength() - 8); + csSubject += tmp; + } else if (tmp.GetLength() >= 5 && + 0 == tmp.Left(5).CompareNoCase(L"body=")) { + tmp = tmp.Right(tmp.GetLength() - 5); + csMsg += tmp; + } + if (pos == -1) + srcURL = L""; + else + srcURL = srcURL.Right(csURL.GetLength() - (pos + 1)); + } + csToAddress.Replace(L",", L";"); + csCCAddress.Replace(L",", L";"); + csBCCAddress.Replace(L",", L";"); + return TRUE; +} + +FX_BOOL CPDFXFA_Document::_SubmitData(IXFA_Doc* hDoc, CXFA_Submit submit) { +#ifdef PDF_ENABLE_XFA + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + if (!pEnv) + return FALSE; + CFX_WideStringC csURLC; + submit.GetSubmitTarget(csURLC); + CFX_WideString csURL = csURLC; + if (csURL.IsEmpty()) { + CFX_WideString ws; + ws.FromLocal("Submit cancelled."); + CFX_ByteString bs = ws.UTF16LE_Encode(); + int len = bs.GetLength() / sizeof(unsigned short); + pEnv->FFI_Alert((FPDF_WIDESTRING)bs.GetBuffer(len * sizeof(unsigned short)), + (FPDF_WIDESTRING)L"", 0, 4); + bs.ReleaseBuffer(len * sizeof(unsigned short)); + return FALSE; + } + FPDF_BOOL bRet = TRUE; + FPDF_FILEHANDLER* pFileHandler = nullptr; + int fileFlag = -1; + switch (submit.GetSubmitFormat()) { + case XFA_ATTRIBUTEENUM_Xdp: { + CFX_WideStringC csContentC; + submit.GetSubmitXDPContent(csContentC); + CFX_WideString csContent; + csContent = csContentC; + csContent.TrimLeft(); + csContent.TrimRight(); + CFX_WideString space; + space.FromLocal(" "); + csContent = space + csContent + space; + FPDF_DWORD flag = 0; + if (submit.IsSubmitEmbedPDF()) + flag |= FXFA_PDF; + _ToXFAContentFlags(csContent, flag); + pFileHandler = pEnv->FFI_OpenFile(FXFA_SAVEAS_XDP, nullptr, "wb"); + fileFlag = FXFA_SAVEAS_XDP; + _ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XDP, 0, flag); + break; + } + case XFA_ATTRIBUTEENUM_Xml: + pFileHandler = pEnv->FFI_OpenFile(FXFA_SAVEAS_XML, nullptr, "wb"); + fileFlag = FXFA_SAVEAS_XML; + _ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XML, 0); + break; + case XFA_ATTRIBUTEENUM_Pdf: + break; + case XFA_ATTRIBUTEENUM_Urlencoded: + pFileHandler = pEnv->FFI_OpenFile(FXFA_SAVEAS_XML, nullptr, "wb"); + fileFlag = FXFA_SAVEAS_XML; + _ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XML, 0); + break; + default: + return false; + } + if (!pFileHandler) + return FALSE; + if (0 == csURL.Left(7).CompareNoCase(L"mailto:")) { + CFX_WideString csToAddress; + CFX_WideString csCCAddress; + CFX_WideString csBCCAddress; + CFX_WideString csSubject; + CFX_WideString csMsg; + bRet = _MailToInfo(csURL, csToAddress, csCCAddress, csBCCAddress, csSubject, + csMsg); + if (!bRet) + return FALSE; + CFX_ByteString bsTo = CFX_WideString(csToAddress).UTF16LE_Encode(); + CFX_ByteString bsCC = CFX_WideString(csCCAddress).UTF16LE_Encode(); + CFX_ByteString bsBcc = CFX_WideString(csBCCAddress).UTF16LE_Encode(); + CFX_ByteString bsSubject = CFX_WideString(csSubject).UTF16LE_Encode(); + CFX_ByteString bsMsg = CFX_WideString(csMsg).UTF16LE_Encode(); + FPDF_WIDESTRING pTo = (FPDF_WIDESTRING)bsTo.GetBuffer(bsTo.GetLength()); + FPDF_WIDESTRING pCC = (FPDF_WIDESTRING)bsCC.GetBuffer(bsCC.GetLength()); + FPDF_WIDESTRING pBcc = (FPDF_WIDESTRING)bsBcc.GetBuffer(bsBcc.GetLength()); + FPDF_WIDESTRING pSubject = + (FPDF_WIDESTRING)bsSubject.GetBuffer(bsSubject.GetLength()); + FPDF_WIDESTRING pMsg = (FPDF_WIDESTRING)bsMsg.GetBuffer(bsMsg.GetLength()); + pEnv->FFI_EmailTo(pFileHandler, pTo, pSubject, pCC, pBcc, pMsg); + bsTo.ReleaseBuffer(); + bsCC.ReleaseBuffer(); + bsBcc.ReleaseBuffer(); + bsSubject.ReleaseBuffer(); + bsMsg.ReleaseBuffer(); + } else { + // http¡¢ftp + CFX_WideString ws; + CFX_ByteString bs = csURL.UTF16LE_Encode(); + int len = bs.GetLength() / sizeof(unsigned short); + pEnv->FFI_UploadTo( + pFileHandler, fileFlag, + (FPDF_WIDESTRING)bs.GetBuffer(len * sizeof(unsigned short))); + bs.ReleaseBuffer(len * sizeof(unsigned short)); + } + return bRet; +#else + return TRUE; +#endif +} + +FX_BOOL CPDFXFA_Document::SetGlobalProperty(IXFA_Doc* hDoc, + const CFX_ByteStringC& szPropName, + FXJSE_HVALUE hValue) { + if (hDoc != m_pXFADoc) + return FALSE; + + if (m_pSDKDoc && m_pSDKDoc->GetEnv()->GetJSRuntime()) + return m_pSDKDoc->GetEnv()->GetJSRuntime()->SetHValueByName(szPropName, + hValue); + return FALSE; +} +FX_BOOL CPDFXFA_Document::GetPDFScriptObject(IXFA_Doc* hDoc, + const CFX_ByteStringC& utf8Name, + FXJSE_HVALUE hValue) { + if (hDoc != m_pXFADoc) + return FALSE; + + if (!m_pSDKDoc || !m_pSDKDoc->GetEnv()->GetJSRuntime()) + return FALSE; + + if (!m_pJSContext) { + m_pSDKDoc->GetEnv()->GetJSRuntime()->SetReaderDocument(m_pSDKDoc); + m_pJSContext = m_pSDKDoc->GetEnv()->GetJSRuntime()->NewContext(); + } + + return _GetHValueByName(utf8Name, hValue, + m_pSDKDoc->GetEnv()->GetJSRuntime()); +} +FX_BOOL CPDFXFA_Document::GetGlobalProperty(IXFA_Doc* hDoc, + const CFX_ByteStringC& szPropName, + FXJSE_HVALUE hValue) { + if (hDoc != m_pXFADoc) + return FALSE; + if (!m_pSDKDoc || !m_pSDKDoc->GetEnv()->GetJSRuntime()) + return FALSE; + + if (!m_pJSContext) { + m_pSDKDoc->GetEnv()->GetJSRuntime()->SetReaderDocument(m_pSDKDoc); + m_pJSContext = m_pSDKDoc->GetEnv()->GetJSRuntime()->NewContext(); + } + + return _GetHValueByName(szPropName, hValue, + m_pSDKDoc->GetEnv()->GetJSRuntime()); +} +FX_BOOL CPDFXFA_Document::_GetHValueByName(const CFX_ByteStringC& utf8Name, + FXJSE_HVALUE hValue, + IJS_Runtime* runTime) { + return runTime->GetHValueByName(utf8Name, hValue); +} diff --git a/fpdfsdk/src/fpdfxfa/fpdfxfa_page.cpp b/fpdfsdk/src/fpdfxfa/fpdfxfa_page.cpp new file mode 100644 index 0000000000..24c1ed156d --- /dev/null +++ b/fpdfsdk/src/fpdfxfa/fpdfxfa_page.cpp @@ -0,0 +1,255 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fpdfsdk/include/fsdk_define.h" +#include "fpdfsdk/include/fsdk_mgr.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_page.h" + +CPDFXFA_Page::CPDFXFA_Page(CPDFXFA_Document* pDoc, int page_index) + : m_pPDFPage(NULL), + m_pXFAPageView(NULL), + m_iPageIndex(page_index), + m_pDocument(pDoc), + m_iRef(1) {} + +CPDFXFA_Page::~CPDFXFA_Page() { + if (m_pPDFPage) + delete m_pPDFPage; + m_pPDFPage = NULL; + m_pXFAPageView = NULL; +} + +void CPDFXFA_Page::Release() { + m_iRef--; + if (m_iRef > 0) + return; + + if (m_pDocument) + m_pDocument->RemovePage(this); + + delete this; +} + +FX_BOOL CPDFXFA_Page::LoadPDFPage() { + if (!m_pDocument) + return FALSE; + CPDF_Document* pPDFDoc = m_pDocument->GetPDFDoc(); + if (pPDFDoc) { + CPDF_Dictionary* pDict = pPDFDoc->GetPage(m_iPageIndex); + if (pDict == NULL) + return FALSE; + if (m_pPDFPage) { + if (m_pPDFPage->m_pFormDict == pDict) + return TRUE; + + delete m_pPDFPage; + m_pPDFPage = NULL; + } + + m_pPDFPage = new CPDF_Page; + m_pPDFPage->Load(pPDFDoc, pDict); + m_pPDFPage->ParseContent(nullptr); + return TRUE; + } + + return FALSE; +} + +FX_BOOL CPDFXFA_Page::LoadXFAPageView() { + if (!m_pDocument) + return FALSE; + IXFA_Doc* pXFADoc = m_pDocument->GetXFADoc(); + if (!pXFADoc) + return FALSE; + + IXFA_DocView* pXFADocView = m_pDocument->GetXFADocView(); + if (!pXFADocView) + return FALSE; + + IXFA_PageView* pPageView = pXFADocView->GetPageView(m_iPageIndex); + if (!pPageView) + return FALSE; + + if (m_pXFAPageView == pPageView) + return TRUE; + + m_pXFAPageView = pPageView; + (void)m_pXFAPageView->LoadPageView(nullptr); + return TRUE; +} + +FX_BOOL CPDFXFA_Page::LoadPage() { + if (!m_pDocument || m_iPageIndex < 0) + return FALSE; + + int iDocType = m_pDocument->GetDocType(); + switch (iDocType) { + case DOCTYPE_PDF: + case DOCTYPE_STATIC_XFA: { + return LoadPDFPage(); + } + case DOCTYPE_DYNAMIC_XFA: { + return LoadXFAPageView(); + } + default: + return FALSE; + } + + return FALSE; +} + +FX_BOOL CPDFXFA_Page::LoadPDFPage(CPDF_Dictionary* pageDict) { + if (!m_pDocument || m_iPageIndex < 0 || !pageDict) + return FALSE; + + if (m_pPDFPage) + delete m_pPDFPage; + + m_pPDFPage = new CPDF_Page(); + m_pPDFPage->Load(m_pDocument->GetPDFDoc(), pageDict); + m_pPDFPage->ParseContent(nullptr); + + return TRUE; +} + +FX_FLOAT CPDFXFA_Page::GetPageWidth() { + ASSERT(m_pDocument != NULL); + + if (!m_pPDFPage && !m_pXFAPageView) + return 0.0f; + + int nDocType = m_pDocument->GetDocType(); + switch (nDocType) { + case DOCTYPE_DYNAMIC_XFA: { + if (m_pXFAPageView) { + CFX_RectF rect; + m_pXFAPageView->GetPageViewRect(rect); + return rect.width; + } + } break; + case DOCTYPE_STATIC_XFA: + case DOCTYPE_PDF: { + if (m_pPDFPage) + return m_pPDFPage->GetPageWidth(); + } break; + default: + return 0.0f; + } + + return 0.0f; +} + +FX_FLOAT CPDFXFA_Page::GetPageHeight() { + ASSERT(m_pDocument != NULL); + + if (!m_pPDFPage && !m_pXFAPageView) + return 0.0f; + + int nDocType = m_pDocument->GetDocType(); + switch (nDocType) { + case DOCTYPE_PDF: + case DOCTYPE_STATIC_XFA: { + if (m_pPDFPage) + return m_pPDFPage->GetPageHeight(); + } break; + case DOCTYPE_DYNAMIC_XFA: { + if (m_pXFAPageView) { + CFX_RectF rect; + m_pXFAPageView->GetPageViewRect(rect); + return rect.height; + } + } break; + default: + return 0.0f; + } + + return 0.0f; +} + +void CPDFXFA_Page::DeviceToPage(int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int device_x, + int device_y, + double* page_x, + double* page_y) { + ASSERT(m_pDocument != NULL); + + if (!m_pPDFPage && !m_pXFAPageView) + return; + + CFX_Matrix page2device; + CFX_Matrix device2page; + FX_FLOAT page_x_f, page_y_f; + + GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, rotate); + + device2page.SetReverse(page2device); + device2page.Transform((FX_FLOAT)(device_x), (FX_FLOAT)(device_y), page_x_f, + page_y_f); + + *page_x = (page_x_f); + *page_y = (page_y_f); +} + +void CPDFXFA_Page::PageToDevice(int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + double page_x, + double page_y, + int* device_x, + int* device_y) { + if (!m_pPDFPage && !m_pXFAPageView) + return; + + CFX_Matrix page2device; + FX_FLOAT device_x_f, device_y_f; + + GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, rotate); + + page2device.Transform(((FX_FLOAT)page_x), ((FX_FLOAT)page_y), device_x_f, + device_y_f); + + *device_x = FXSYS_round(device_x_f); + *device_y = FXSYS_round(device_y_f); +} + +void CPDFXFA_Page::GetDisplayMatrix(CFX_Matrix& matrix, + int xPos, + int yPos, + int xSize, + int ySize, + int iRotate) const { + ASSERT(m_pDocument != NULL); + + if (!m_pPDFPage && !m_pXFAPageView) + return; + + int nDocType = m_pDocument->GetDocType(); + switch (nDocType) { + case DOCTYPE_DYNAMIC_XFA: { + if (m_pXFAPageView) { + CFX_Rect rect; + rect.Set(xPos, yPos, xSize, ySize); + m_pXFAPageView->GetDisplayMatrix(matrix, rect, iRotate); + } + } break; + case DOCTYPE_PDF: + case DOCTYPE_STATIC_XFA: { + if (m_pPDFPage) { + m_pPDFPage->GetDisplayMatrix(matrix, xPos, yPos, xSize, ySize, iRotate); + } + } break; + default: + return; + } +} diff --git a/fpdfsdk/src/fpdfxfa/fpdfxfa_util.cpp b/fpdfsdk/src/fpdfxfa/fpdfxfa_util.cpp new file mode 100644 index 0000000000..bd817a45df --- /dev/null +++ b/fpdfsdk/src/fpdfxfa/fpdfxfa_util.cpp @@ -0,0 +1,47 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fpdfsdk/include/fsdk_define.h" +#include "fpdfsdk/include/fsdk_mgr.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h" + +std::vector<CFWL_TimerInfo*> CXFA_FWLAdapterTimerMgr::s_TimerArray; + +FWL_ERR CXFA_FWLAdapterTimerMgr::Start(IFWL_Timer* pTimer, + FX_DWORD dwElapse, + FWL_HTIMER& hTimer, + FX_BOOL bImmediately) { + if (!m_pEnv) + return FWL_ERR_Indefinite; + + uint32_t uIDEvent = m_pEnv->FFI_SetTimer(dwElapse, TimerProc); + s_TimerArray.push_back(new CFWL_TimerInfo(uIDEvent, pTimer)); + hTimer = reinterpret_cast<FWL_HTIMER>(s_TimerArray.back()); + return FWL_ERR_Succeeded; +} + +FWL_ERR CXFA_FWLAdapterTimerMgr::Stop(FWL_HTIMER hTimer) { + if (!hTimer || !m_pEnv) + return FWL_ERR_Indefinite; + + CFWL_TimerInfo* pInfo = reinterpret_cast<CFWL_TimerInfo*>(hTimer); + m_pEnv->FFI_KillTimer(pInfo->uIDEvent); + auto it = std::find(s_TimerArray.begin(), s_TimerArray.end(), pInfo); + if (it != s_TimerArray.end()) { + s_TimerArray.erase(it); + delete pInfo; + } + return FWL_ERR_Succeeded; +} + +void CXFA_FWLAdapterTimerMgr::TimerProc(int32_t idEvent) { + for (CFWL_TimerInfo* pInfo : s_TimerArray) { + if (pInfo->uIDEvent == idEvent) { + pInfo->pTimer->Run(reinterpret_cast<FWL_HTIMER>(pInfo)); + break; + } + } +} diff --git a/fpdfsdk/src/fsdk_annothandler.cpp b/fpdfsdk/src/fsdk_annothandler.cpp index a8dff91fd2..2f204fe27d 100644 --- a/fpdfsdk/src/fsdk_annothandler.cpp +++ b/fpdfsdk/src/fsdk_annothandler.cpp @@ -11,12 +11,22 @@ #include "fpdfsdk/include/fsdk_define.h" #include "fpdfsdk/include/fsdk_mgr.h" +#ifdef PDF_ENABLE_XFA +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h" +#endif // PDF_ENABLE_XFA + CPDFSDK_AnnotHandlerMgr::CPDFSDK_AnnotHandlerMgr(CPDFDoc_Environment* pApp) { m_pApp = pApp; CPDFSDK_BFAnnotHandler* pHandler = new CPDFSDK_BFAnnotHandler(m_pApp); pHandler->SetFormFiller(m_pApp->GetIFormFiller()); RegisterAnnotHandler(pHandler); +#ifdef PDF_ENABLE_XFA + CPDFSDK_XFAAnnotHandler* pXFAAnnotHandler = + new CPDFSDK_XFAAnnotHandler(m_pApp); + RegisterAnnotHandler(pXFAAnnotHandler); +#endif // PDF_ENABLE_XFA } CPDFSDK_AnnotHandlerMgr::~CPDFSDK_AnnotHandlerMgr() { @@ -59,6 +69,21 @@ CPDFSDK_Annot* CPDFSDK_AnnotHandlerMgr::NewAnnot(CPDF_Annot* pAnnot, return new CPDFSDK_BAAnnot(pAnnot, pPageView); } +#ifdef PDF_ENABLE_XFA +CPDFSDK_Annot* CPDFSDK_AnnotHandlerMgr::NewAnnot(IXFA_Widget* pAnnot, + CPDFSDK_PageView* pPageView) { + ASSERT(pAnnot != NULL); + ASSERT(pPageView != NULL); + + if (IPDFSDK_AnnotHandler* pAnnotHandler = + GetAnnotHandler(FSDK_XFAWIDGET_TYPENAME)) { + return pAnnotHandler->NewAnnot(pAnnot, pPageView); + } + + return NULL; +} +#endif // PDF_ENABLE_XFA + void CPDFSDK_AnnotHandlerMgr::ReleaseAnnot(CPDFSDK_Annot* pAnnot) { pAnnot->GetPDFPage(); @@ -93,7 +118,13 @@ void CPDFSDK_AnnotHandlerMgr::Annot_OnLoad(CPDFSDK_Annot* pAnnot) { IPDFSDK_AnnotHandler* CPDFSDK_AnnotHandlerMgr::GetAnnotHandler( CPDFSDK_Annot* pAnnot) const { CPDF_Annot* pPDFAnnot = pAnnot->GetPDFAnnot(); - return pPDFAnnot ? GetAnnotHandler(pPDFAnnot->GetSubType()) : nullptr; + if (pPDFAnnot) + return GetAnnotHandler(pPDFAnnot->GetSubType()); +#ifdef PDF_ENABLE_XFA + if (pAnnot->GetXFAWidget()) + return GetAnnotHandler(FSDK_XFAWIDGET_TYPENAME); +#endif // PDF_ENABLE_XFA + return nullptr; } IPDFSDK_AnnotHandler* CPDFSDK_AnnotHandlerMgr::GetAnnotHandler( @@ -112,6 +143,10 @@ void CPDFSDK_AnnotHandlerMgr::Annot_OnDraw(CPDFSDK_PageView* pPageView, if (IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot)) { pAnnotHandler->OnDraw(pPageView, pAnnot, pDevice, pUser2Device, dwFlags); } else { +#ifdef PDF_ENABLE_XFA + if (pAnnot->IsXFAField()) + return; +#endif // PDF_ENABLE_XFA static_cast<CPDFSDK_BAAnnot*>(pAnnot) ->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal, nullptr); } @@ -279,6 +314,23 @@ FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnKillFocus(CPDFSDK_Annot* pAnnot, return FALSE; } +#ifdef PDF_ENABLE_XFA +FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnChangeFocus( + CPDFSDK_Annot* pSetAnnot, + CPDFSDK_Annot* pKillAnnot) { + FX_BOOL bXFA = (pSetAnnot && pSetAnnot->GetXFAWidget()) || + (pKillAnnot && pKillAnnot->GetXFAWidget()); + + if (bXFA) { + if (IPDFSDK_AnnotHandler* pXFAAnnotHandler = + GetAnnotHandler(FSDK_XFAWIDGET_TYPENAME)) + return pXFAAnnotHandler->OnXFAChangedFocus(pKillAnnot, pSetAnnot); + } + + return TRUE; +} +#endif // PDF_ENABLE_XFA + CPDF_Rect CPDFSDK_AnnotHandlerMgr::Annot_OnGetViewBBox( CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) { @@ -302,8 +354,39 @@ FX_BOOL CPDFSDK_AnnotHandlerMgr::Annot_OnHitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* CPDFSDK_AnnotHandlerMgr::GetNextAnnot(CPDFSDK_Annot* pSDKAnnot, FX_BOOL bNext) { +#ifdef PDF_ENABLE_XFA + CPDFSDK_PageView* pPageView = pSDKAnnot->GetPageView(); + CPDFXFA_Page* pPage = pPageView->GetPDFXFAPage(); + if (pPage == NULL) + return NULL; + if (pPage->GetPDFPage()) { // for pdf annots. + CBA_AnnotIterator ai(pSDKAnnot->GetPageView(), pSDKAnnot->GetType(), ""); + CPDFSDK_Annot* pNext = + bNext ? ai.GetNextAnnot(pSDKAnnot) : ai.GetPrevAnnot(pSDKAnnot); + return pNext; + } + // for xfa annots + IXFA_WidgetIterator* pWidgetIterator = + pPage->GetXFAPageView()->CreateWidgetIterator( + XFA_TRAVERSEWAY_Tranvalse, XFA_WIDGETFILTER_Visible | + XFA_WIDGETFILTER_Viewable | + XFA_WIDGETFILTER_Field); + if (pWidgetIterator == NULL) + return NULL; + if (pWidgetIterator->GetCurrentWidget() != pSDKAnnot->GetXFAWidget()) + pWidgetIterator->SetCurrentWidget(pSDKAnnot->GetXFAWidget()); + IXFA_Widget* hNextFocus = NULL; + hNextFocus = + bNext ? pWidgetIterator->MoveToNext() : pWidgetIterator->MoveToPrevious(); + if (hNextFocus == NULL && pSDKAnnot != NULL) + hNextFocus = pWidgetIterator->MoveToFirst(); + + pWidgetIterator->Release(); + return pPageView->GetAnnotByXFAWidget(hNextFocus); +#else // PDF_ENABLE_XFA CBA_AnnotIterator ai(pSDKAnnot->GetPageView(), "Widget", ""); return bNext ? ai.GetNextAnnot(pSDKAnnot) : ai.GetPrevAnnot(pSDKAnnot); +#endif // PDF_ENABLE_XFA } FX_BOOL CPDFSDK_BFAnnotHandler::CanAnswer(CPDFSDK_Annot* pAnnot) { @@ -347,6 +430,13 @@ CPDFSDK_Annot* CPDFSDK_BFAnnotHandler::NewAnnot(CPDF_Annot* pAnnot, return pWidget; } +#ifdef PDF_ENABLE_XFA +CPDFSDK_Annot* CPDFSDK_BFAnnotHandler::NewAnnot(IXFA_Widget* hWidget, + CPDFSDK_PageView* pPage) { + return NULL; +} +#endif // PDF_ENABLE_XFA + void CPDFSDK_BFAnnotHandler::ReleaseAnnot(CPDFSDK_Annot* pAnnot) { ASSERT(pAnnot); @@ -566,6 +656,15 @@ void CPDFSDK_BFAnnotHandler::OnLoad(CPDFSDK_Annot* pAnnot) { } } +#ifdef PDF_ENABLE_XFA + CPDFSDK_PageView* pPageView = pAnnot->GetPageView(); + CPDFSDK_Document* pSDKDoc = pPageView->GetSDKDocument(); + CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument(); + if (pDoc->GetDocType() == DOCTYPE_STATIC_XFA) { + if (!pWidget->IsAppearanceValid() && !pWidget->GetValue().IsEmpty()) + pWidget->ResetAppearance(FALSE); + } +#endif // PDF_ENABLE_XFA if (m_pFormFiller) m_pFormFiller->OnLoad(pAnnot); } @@ -618,6 +717,421 @@ FX_BOOL CPDFSDK_BFAnnotHandler::HitTest(CPDFSDK_PageView* pPageView, return rect.Contains(point.x, point.y); } +#ifdef PDF_ENABLE_XFA +#define FWL_WGTHITTEST_Unknown 0 +#define FWL_WGTHITTEST_Client 1 // arrow +#define FWL_WGTHITTEST_Titlebar 11 // caption +#define FWL_WGTHITTEST_HScrollBar 15 +#define FWL_WGTHITTEST_VScrollBar 16 +#define FWL_WGTHITTEST_Border 17 +#define FWL_WGTHITTEST_Edit 19 +#define FWL_WGTHITTEST_HyperLink 20 + +CPDFSDK_XFAAnnotHandler::CPDFSDK_XFAAnnotHandler(CPDFDoc_Environment* pApp) + : m_pApp(pApp) {} + +CPDFSDK_Annot* CPDFSDK_XFAAnnotHandler::NewAnnot(IXFA_Widget* pAnnot, + CPDFSDK_PageView* pPage) { + CPDFSDK_Document* pSDKDoc = m_pApp->GetSDKDocument(); + CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)pSDKDoc->GetInterForm(); + CPDFSDK_XFAWidget* pWidget = new CPDFSDK_XFAWidget(pAnnot, pPage, pInterForm); + pInterForm->AddXFAMap(pAnnot, pWidget); + return pWidget; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::CanAnswer(CPDFSDK_Annot* pAnnot) { + return pAnnot->GetXFAWidget() != NULL; +} + +void CPDFSDK_XFAAnnotHandler::OnDraw(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + CFX_RenderDevice* pDevice, + CFX_Matrix* pUser2Device, + FX_DWORD dwFlags) { + ASSERT(pPageView != NULL); + ASSERT(pAnnot != NULL); + + CPDFSDK_Document* pSDKDoc = pPageView->GetSDKDocument(); + ASSERT(pSDKDoc != NULL); + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + CFX_Graphics gs; + gs.Create(pDevice); + + CFX_Matrix mt; + mt = *(CFX_Matrix*)pUser2Device; + + FX_BOOL bIsHighlight = FALSE; + if (pSDKDoc->GetFocusAnnot() != pAnnot) + bIsHighlight = TRUE; + + pWidgetHandler->RenderWidget(pAnnot->GetXFAWidget(), &gs, &mt, bIsHighlight); + + // to do highlight and shadow +} + +void CPDFSDK_XFAAnnotHandler::ReleaseAnnot(CPDFSDK_Annot* pAnnot) { + ASSERT(pAnnot != NULL); + + CPDFSDK_XFAWidget* pWidget = (CPDFSDK_XFAWidget*)pAnnot; + CPDFSDK_InterForm* pInterForm = pWidget->GetInterForm(); + ASSERT(pInterForm != NULL); + + pInterForm->RemoveXFAMap(pWidget->GetXFAWidget()); + + delete pWidget; +} + +CPDF_Rect CPDFSDK_XFAAnnotHandler::GetViewBBox(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot) { + ASSERT(pAnnot != NULL); + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + CFX_RectF rcBBox; + XFA_ELEMENT eType = + pWidgetHandler->GetDataAcc(pAnnot->GetXFAWidget())->GetUIType(); + if (eType == XFA_ELEMENT_Signature) + pWidgetHandler->GetBBox(pAnnot->GetXFAWidget(), rcBBox, + XFA_WIDGETSTATUS_Visible, TRUE); + else + pWidgetHandler->GetBBox(pAnnot->GetXFAWidget(), rcBBox, 0); + + CFX_FloatRect rcWidget(rcBBox.left, rcBBox.top, rcBBox.left + rcBBox.width, + rcBBox.top + rcBBox.height); + rcWidget.left -= 1.0f; + rcWidget.right += 1.0f; + rcWidget.bottom -= 1.0f; + rcWidget.top += 1.0f; + + return rcWidget; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::HitTest(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + const CPDF_Point& point) { + if (!pPageView || !pAnnot) + return FALSE; + + CPDFSDK_Document* pSDKDoc = pPageView->GetSDKDocument(); + if (!pSDKDoc) + return FALSE; + + CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument(); + if (!pDoc) + return FALSE; + + IXFA_DocView* pDocView = pDoc->GetXFADocView(); + if (!pDocView) + return FALSE; + + IXFA_WidgetHandler* pWidgetHandler = pDocView->GetWidgetHandler(); + if (!pWidgetHandler) + return FALSE; + + FX_DWORD dwHitTest = + pWidgetHandler->OnHitTest(pAnnot->GetXFAWidget(), point.x, point.y); + return (dwHitTest != FWL_WGTHITTEST_Unknown); +} + +void CPDFSDK_XFAAnnotHandler::OnMouseEnter(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + FX_DWORD nFlag) { + if (!pPageView || !pAnnot) + return; + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + pWidgetHandler->OnMouseEnter(pAnnot->GetXFAWidget()); +} + +void CPDFSDK_XFAAnnotHandler::OnMouseExit(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + FX_DWORD nFlag) { + if (!pPageView || !pAnnot) + return; + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + pWidgetHandler->OnMouseExit(pAnnot->GetXFAWidget()); +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnLButtonDown(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + FX_DWORD nFlags, + const CPDF_Point& point) { + if (!pPageView || !pAnnot) + return FALSE; + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + FX_BOOL bRet = FALSE; + bRet = pWidgetHandler->OnLButtonDown(pAnnot->GetXFAWidget(), + GetFWLFlags(nFlags), point.x, point.y); + + return bRet; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnLButtonUp(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + FX_DWORD nFlags, + const CPDF_Point& point) { + if (!pPageView || !pAnnot) + return FALSE; + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + FX_BOOL bRet = FALSE; + bRet = pWidgetHandler->OnLButtonUp(pAnnot->GetXFAWidget(), + GetFWLFlags(nFlags), point.x, point.y); + + return bRet; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnLButtonDblClk(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + FX_DWORD nFlags, + const CPDF_Point& point) { + if (!pPageView || !pAnnot) + return FALSE; + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + FX_BOOL bRet = FALSE; + bRet = pWidgetHandler->OnLButtonDblClk(pAnnot->GetXFAWidget(), + GetFWLFlags(nFlags), point.x, point.y); + + return bRet; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnMouseMove(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + FX_DWORD nFlags, + const CPDF_Point& point) { + if (!pPageView || !pAnnot) + return FALSE; + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + FX_BOOL bRet = FALSE; + bRet = pWidgetHandler->OnMouseMove(pAnnot->GetXFAWidget(), + GetFWLFlags(nFlags), point.x, point.y); + + return bRet; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnMouseWheel(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + FX_DWORD nFlags, + short zDelta, + const CPDF_Point& point) { + if (!pPageView || !pAnnot) + return FALSE; + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + FX_BOOL bRet = FALSE; + bRet = pWidgetHandler->OnMouseWheel( + pAnnot->GetXFAWidget(), GetFWLFlags(nFlags), zDelta, point.x, point.y); + + return bRet; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnRButtonDown(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + FX_DWORD nFlags, + const CPDF_Point& point) { + if (!pPageView || !pAnnot) + return FALSE; + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + FX_BOOL bRet = FALSE; + bRet = pWidgetHandler->OnRButtonDown(pAnnot->GetXFAWidget(), + GetFWLFlags(nFlags), point.x, point.y); + + return bRet; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnRButtonUp(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + FX_DWORD nFlags, + const CPDF_Point& point) { + if (!pPageView || !pAnnot) + return FALSE; + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + FX_BOOL bRet = FALSE; + bRet = pWidgetHandler->OnRButtonUp(pAnnot->GetXFAWidget(), + GetFWLFlags(nFlags), point.x, point.y); + + return bRet; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnRButtonDblClk(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + FX_DWORD nFlags, + const CPDF_Point& point) { + if (!pPageView || !pAnnot) + return FALSE; + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + FX_BOOL bRet = FALSE; + bRet = pWidgetHandler->OnRButtonDblClk(pAnnot->GetXFAWidget(), + GetFWLFlags(nFlags), point.x, point.y); + + return bRet; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnChar(CPDFSDK_Annot* pAnnot, + FX_DWORD nChar, + FX_DWORD nFlags) { + if (!pAnnot) + return FALSE; + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + FX_BOOL bRet = FALSE; + bRet = pWidgetHandler->OnChar(pAnnot->GetXFAWidget(), nChar, + GetFWLFlags(nFlags)); + + return bRet; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnKeyDown(CPDFSDK_Annot* pAnnot, + int nKeyCode, + int nFlag) { + if (!pAnnot) + return FALSE; + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + FX_BOOL bRet = FALSE; + bRet = pWidgetHandler->OnKeyDown(pAnnot->GetXFAWidget(), nKeyCode, + GetFWLFlags(nFlag)); + + return bRet; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnKeyUp(CPDFSDK_Annot* pAnnot, + int nKeyCode, + int nFlag) { + if (!pAnnot) + return FALSE; + + IXFA_WidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + ASSERT(pWidgetHandler != NULL); + + FX_BOOL bRet = FALSE; + bRet = pWidgetHandler->OnKeyUp(pAnnot->GetXFAWidget(), nKeyCode, + GetFWLFlags(nFlag)); + + return bRet; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnSetFocus(CPDFSDK_Annot* pAnnot, + FX_DWORD nFlag) { + return TRUE; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnKillFocus(CPDFSDK_Annot* pAnnot, + FX_DWORD nFlag) { + return TRUE; +} + +FX_BOOL CPDFSDK_XFAAnnotHandler::OnXFAChangedFocus(CPDFSDK_Annot* pOldAnnot, + CPDFSDK_Annot* pNewAnnot) { + IXFA_WidgetHandler* pWidgetHandler = NULL; + + if (pOldAnnot) + pWidgetHandler = GetXFAWidgetHandler(pOldAnnot); + else if (pNewAnnot) + pWidgetHandler = GetXFAWidgetHandler(pNewAnnot); + + if (pWidgetHandler) { + FX_BOOL bRet = TRUE; + IXFA_Widget* hWidget = pNewAnnot ? pNewAnnot->GetXFAWidget() : NULL; + if (hWidget) { + IXFA_PageView* pXFAPageView = pWidgetHandler->GetPageView(hWidget); + if (pXFAPageView) { + bRet = pXFAPageView->GetDocView()->SetFocus(hWidget); + if (pXFAPageView->GetDocView()->GetFocusWidget() == hWidget) + bRet = TRUE; + } + } + return bRet; + } + + return TRUE; +} + +IXFA_WidgetHandler* CPDFSDK_XFAAnnotHandler::GetXFAWidgetHandler( + CPDFSDK_Annot* pAnnot) { + if (!pAnnot) + return NULL; + + CPDFSDK_PageView* pPageView = pAnnot->GetPageView(); + if (!pPageView) + return NULL; + + CPDFSDK_Document* pSDKDoc = pPageView->GetSDKDocument(); + if (!pSDKDoc) + return NULL; + + CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument(); + if (!pDoc) + return NULL; + + IXFA_DocView* pDocView = pDoc->GetXFADocView(); + if (!pDocView) + return NULL; + + return pDocView->GetWidgetHandler(); +} + +#define FWL_KEYFLAG_Ctrl (1 << 0) +#define FWL_KEYFLAG_Alt (1 << 1) +#define FWL_KEYFLAG_Shift (1 << 2) +#define FWL_KEYFLAG_LButton (1 << 3) +#define FWL_KEYFLAG_RButton (1 << 4) +#define FWL_KEYFLAG_MButton (1 << 5) + +FX_DWORD CPDFSDK_XFAAnnotHandler::GetFWLFlags(FX_DWORD dwFlag) { + FX_DWORD dwFWLFlag = 0; + + if (dwFlag & FWL_EVENTFLAG_ControlKey) + dwFWLFlag |= FWL_KEYFLAG_Ctrl; + if (dwFlag & FWL_EVENTFLAG_LeftButtonDown) + dwFWLFlag |= FWL_KEYFLAG_LButton; + if (dwFlag & FWL_EVENTFLAG_MiddleButtonDown) + dwFWLFlag |= FWL_KEYFLAG_MButton; + if (dwFlag & FWL_EVENTFLAG_RightButtonDown) + dwFWLFlag |= FWL_KEYFLAG_RButton; + if (dwFlag & FWL_EVENTFLAG_ShiftKey) + dwFWLFlag |= FWL_KEYFLAG_Shift; + if (dwFlag & FWL_EVENTFLAG_AltKey) + dwFWLFlag |= FWL_KEYFLAG_Alt; + + return dwFWLFlag; +} +#endif // PDF_ENABLE_XFA + CPDFSDK_AnnotIterator::CPDFSDK_AnnotIterator(CPDFSDK_PageView* pPageView, bool bReverse) : m_bReverse(bReverse), m_pos(0) { diff --git a/fpdfsdk/src/fsdk_baseannot.cpp b/fpdfsdk/src/fsdk_baseannot.cpp index 6260cf04bd..2495897408 100644 --- a/fpdfsdk/src/fsdk_baseannot.cpp +++ b/fpdfsdk/src/fsdk_baseannot.cpp @@ -11,6 +11,10 @@ #include "fpdfsdk/include/fsdk_define.h" #include "fpdfsdk/include/fsdk_mgr.h" +#ifdef PDF_ENABLE_XFA +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" +#endif // PDF_ENABLE_XFA + int _gAfxGetTimeZoneInSeconds(FX_CHAR tzhour, uint8_t tzminute) { return (int)tzhour * 3600 + (int)tzminute * (tzhour >= 0 ? 60 : -60); } @@ -951,6 +955,12 @@ CPDF_Action CPDFSDK_BAAnnot::GetAAction(CPDF_AAction::AActionType eAAT) { return CPDF_Action(); } +#ifdef PDF_ENABLE_XFA +FX_BOOL CPDFSDK_BAAnnot::IsXFAField() { + return FALSE; +} +#endif // PDF_ENABLE_XFA + void CPDFSDK_BAAnnot::Annot_OnDraw(CFX_RenderDevice* pDevice, CFX_Matrix* pUser2Device, CPDF_RenderOptions* pOptions) { @@ -960,9 +970,19 @@ void CPDFSDK_BAAnnot::Annot_OnDraw(CFX_RenderDevice* pDevice, } UnderlyingPageType* CPDFSDK_Annot::GetUnderlyingPage() { +#ifdef PDF_ENABLE_XFA + return GetPDFXFAPage(); +#else // PDF_ENABLE_XFA return GetPDFPage(); +#endif // PDF_ENABLE_XFA } CPDF_Page* CPDFSDK_Annot::GetPDFPage() { return m_pPageView ? m_pPageView->GetPDFPage() : nullptr; } + +#ifdef PDF_ENABLE_XFA +CPDFXFA_Page* CPDFSDK_Annot::GetPDFXFAPage() { + return m_pPageView ? m_pPageView->GetPDFXFAPage() : nullptr; +} +#endif // PDF_ENABLE_XFA diff --git a/fpdfsdk/src/fsdk_baseform.cpp b/fpdfsdk/src/fsdk_baseform.cpp index 86c41dc048..00ab6c2ef0 100644 --- a/fpdfsdk/src/fsdk_baseform.cpp +++ b/fpdfsdk/src/fsdk_baseform.cpp @@ -17,6 +17,11 @@ #include "fpdfsdk/include/javascript/IJavaScript.h" #include "fpdfsdk/include/pdfwindow/PWL_Utils.h" +#ifdef PDF_ENABLE_XFA +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h" +#endif // PDF_ENABLE_XFA + #define IsFloatZero(f) ((f) < 0.01 && (f) > -0.01) #define IsFloatBigger(fa, fb) ((fa) > (fb) && !IsFloatZero((fa) - (fb))) #define IsFloatSmaller(fa, fb) ((fa) < (fb) && !IsFloatZero((fa) - (fb))) @@ -28,12 +33,431 @@ CPDFSDK_Widget::CPDFSDK_Widget(CPDF_Annot* pAnnot, : CPDFSDK_BAAnnot(pAnnot, pPageView), m_pInterForm(pInterForm), m_nAppAge(0), - m_nValueAge(0) { - ASSERT(m_pInterForm); + m_nValueAge(0) +#ifdef PDF_ENABLE_XFA + , + m_hMixXFAWidget(NULL), + m_pWidgetHandler(NULL) +#endif // PDF_ENABLE_XFA +{ } CPDFSDK_Widget::~CPDFSDK_Widget() {} +#ifdef PDF_ENABLE_XFA +IXFA_Widget* CPDFSDK_Widget::GetMixXFAWidget() const { + CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument(); + CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument(); + if (pDoc->GetDocType() == DOCTYPE_STATIC_XFA) { + if (!m_hMixXFAWidget) { + if (IXFA_DocView* pDocView = pDoc->GetXFADocView()) { + CFX_WideString sName; + if (this->GetFieldType() == FIELDTYPE_RADIOBUTTON) { + sName = this->GetAnnotName(); + if (sName.IsEmpty()) + sName = GetName(); + } else + sName = GetName(); + + if (!sName.IsEmpty()) + m_hMixXFAWidget = pDocView->GetWidgetByName(sName); + } + } + return m_hMixXFAWidget; + } + + return NULL; +} + +IXFA_Widget* CPDFSDK_Widget::GetGroupMixXFAWidget() { + CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument(); + CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument(); + if (pDoc->GetDocType() == DOCTYPE_STATIC_XFA) { + if (IXFA_DocView* pDocView = pDoc->GetXFADocView()) { + CFX_WideString sName = GetName(); + if (!sName.IsEmpty()) + return pDocView->GetWidgetByName(sName); + } + } + + return nullptr; +} + +IXFA_WidgetHandler* CPDFSDK_Widget::GetXFAWidgetHandler() const { + CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument(); + CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument(); + if (pDoc->GetDocType() == DOCTYPE_STATIC_XFA) { + if (!m_pWidgetHandler) { + if (IXFA_DocView* pDocView = pDoc->GetXFADocView()) { + m_pWidgetHandler = pDocView->GetWidgetHandler(); + } + } + return m_pWidgetHandler; + } + + return NULL; +} + +static XFA_EVENTTYPE GetXFAEventType(PDFSDK_XFAAActionType eXFAAAT) { + XFA_EVENTTYPE eEventType = XFA_EVENT_Unknown; + + switch (eXFAAAT) { + case PDFSDK_XFA_Click: + eEventType = XFA_EVENT_Click; + break; + case PDFSDK_XFA_Full: + eEventType = XFA_EVENT_Full; + break; + case PDFSDK_XFA_PreOpen: + eEventType = XFA_EVENT_PreOpen; + break; + case PDFSDK_XFA_PostOpen: + eEventType = XFA_EVENT_PostOpen; + break; + } + + return eEventType; +} + +static XFA_EVENTTYPE GetXFAEventType(CPDF_AAction::AActionType eAAT, + FX_BOOL bWillCommit) { + XFA_EVENTTYPE eEventType = XFA_EVENT_Unknown; + + switch (eAAT) { + case CPDF_AAction::CursorEnter: + eEventType = XFA_EVENT_MouseEnter; + break; + case CPDF_AAction::CursorExit: + eEventType = XFA_EVENT_MouseExit; + break; + case CPDF_AAction::ButtonDown: + eEventType = XFA_EVENT_MouseDown; + break; + case CPDF_AAction::ButtonUp: + eEventType = XFA_EVENT_MouseUp; + break; + case CPDF_AAction::GetFocus: + eEventType = XFA_EVENT_Enter; + break; + case CPDF_AAction::LoseFocus: + eEventType = XFA_EVENT_Exit; + break; + case CPDF_AAction::PageOpen: + break; + case CPDF_AAction::PageClose: + break; + case CPDF_AAction::PageVisible: + break; + case CPDF_AAction::PageInvisible: + break; + case CPDF_AAction::KeyStroke: + if (!bWillCommit) { + eEventType = XFA_EVENT_Change; + } + break; + case CPDF_AAction::Validate: + eEventType = XFA_EVENT_Validate; + break; + case CPDF_AAction::OpenPage: + case CPDF_AAction::ClosePage: + case CPDF_AAction::Format: + case CPDF_AAction::Calculate: + case CPDF_AAction::CloseDocument: + case CPDF_AAction::SaveDocument: + case CPDF_AAction::DocumentSaved: + case CPDF_AAction::PrintDocument: + case CPDF_AAction::DocumentPrinted: + break; + } + + return eEventType; +} + +FX_BOOL CPDFSDK_Widget::HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT) { + if (IXFA_Widget* hWidget = this->GetMixXFAWidget()) { + if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) { + XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT); + + if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) && + GetFieldType() == FIELDTYPE_RADIOBUTTON) { + if (IXFA_Widget* hGroupWidget = GetGroupMixXFAWidget()) { + CXFA_WidgetAcc* pAcc = pXFAWidgetHandler->GetDataAcc(hGroupWidget); + if (pXFAWidgetHandler->HasEvent(pAcc, eEventType)) + return TRUE; + } + } + + { + CXFA_WidgetAcc* pAcc = pXFAWidgetHandler->GetDataAcc(hWidget); + return pXFAWidgetHandler->HasEvent(pAcc, eEventType); + } + } + } + + return FALSE; +} + +FX_BOOL CPDFSDK_Widget::OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT, + PDFSDK_FieldAction& data, + CPDFSDK_PageView* pPageView) { + CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument(); + CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument(); + if (IXFA_Widget* hWidget = GetMixXFAWidget()) { + XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT); + + if (eEventType != XFA_EVENT_Unknown) { + if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) { + CXFA_EventParam param; + param.m_eType = eEventType; + param.m_wsChange = data.sChange; + param.m_iCommitKey = data.nCommitKey; + param.m_bShift = data.bShift; + param.m_iSelStart = data.nSelStart; + param.m_iSelEnd = data.nSelEnd; + param.m_wsFullText = data.sValue; + param.m_bKeyDown = data.bKeyDown; + param.m_bModifier = data.bModifier; + param.m_wsNewText = data.sValue; + if (data.nSelEnd > data.nSelStart) + param.m_wsNewText.Delete(data.nSelStart, + data.nSelEnd - data.nSelStart); + for (int i = 0; i < data.sChange.GetLength(); i++) + param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]); + param.m_wsPrevText = data.sValue; + + if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) && + GetFieldType() == FIELDTYPE_RADIOBUTTON) { + if (IXFA_Widget* hGroupWidget = GetGroupMixXFAWidget()) { + CXFA_WidgetAcc* pAcc = pXFAWidgetHandler->GetDataAcc(hGroupWidget); + param.m_pTarget = pAcc; + pXFAWidgetHandler->ProcessEvent(pAcc, ¶m); + } + + { + CXFA_WidgetAcc* pAcc = pXFAWidgetHandler->GetDataAcc(hWidget); + param.m_pTarget = pAcc; + int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, ¶m); + return nRet == XFA_EVENTERROR_Sucess; + } + } else { + CXFA_WidgetAcc* pAcc = pXFAWidgetHandler->GetDataAcc(hWidget); + param.m_pTarget = pAcc; + int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, ¶m); + return nRet == XFA_EVENTERROR_Sucess; + } + + if (IXFA_DocView* pDocView = pDoc->GetXFADocView()) { + pDocView->UpdateDocView(); + } + } + } + } + + return FALSE; +} + +void CPDFSDK_Widget::Synchronize(FX_BOOL bSynchronizeElse) { + if (IXFA_Widget* hWidget = this->GetMixXFAWidget()) { + if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) { + CPDF_FormField* pFormField = GetFormField(); + ASSERT(pFormField != NULL); + + if (CXFA_WidgetAcc* pWidgetAcc = pXFAWidgetHandler->GetDataAcc(hWidget)) { + switch (GetFieldType()) { + case FIELDTYPE_CHECKBOX: + case FIELDTYPE_RADIOBUTTON: { + CPDF_FormControl* pFormCtrl = GetFormControl(); + ASSERT(pFormCtrl != NULL); + + XFA_CHECKSTATE eCheckState = + pFormCtrl->IsChecked() ? XFA_CHECKSTATE_On : XFA_CHECKSTATE_Off; + pWidgetAcc->SetCheckState(eCheckState); + } break; + case FIELDTYPE_TEXTFIELD: + pWidgetAcc->SetValue(pFormField->GetValue(), XFA_VALUEPICTURE_Edit); + break; + case FIELDTYPE_LISTBOX: { + pWidgetAcc->ClearAllSelections(); + + for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; + i++) { + int nIndex = pFormField->GetSelectedIndex(i); + if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems()) + pWidgetAcc->SetItemState(nIndex, TRUE, FALSE); + } + } break; + case FIELDTYPE_COMBOBOX: { + pWidgetAcc->ClearAllSelections(); + + for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; + i++) { + int nIndex = pFormField->GetSelectedIndex(i); + if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems()) + pWidgetAcc->SetItemState(nIndex, TRUE, FALSE); + } + } + + pWidgetAcc->SetValue(pFormField->GetValue(), XFA_VALUEPICTURE_Edit); + break; + } + + if (bSynchronizeElse) + pWidgetAcc->ProcessValueChanged(); + } + } + } +} + +void CPDFSDK_Widget::SynchronizeXFAValue() { + CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument(); + CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument(); + IXFA_DocView* pXFADocView = pDoc->GetXFADocView(); + if (!pXFADocView) + return; + + if (IXFA_Widget* hWidget = GetMixXFAWidget()) { + if (GetXFAWidgetHandler()) { + CPDFSDK_Widget::SynchronizeXFAValue(pXFADocView, hWidget, GetFormField(), + GetFormControl()); + } + } +} + +void CPDFSDK_Widget::SynchronizeXFAItems() { + CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument(); + CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument(); + IXFA_DocView* pXFADocView = pDoc->GetXFADocView(); + if (!pXFADocView) + return; + + if (IXFA_Widget* hWidget = GetMixXFAWidget()) { + if (GetXFAWidgetHandler()) + SynchronizeXFAItems(pXFADocView, hWidget, GetFormField(), nullptr); + } +} + +void CPDFSDK_Widget::SynchronizeXFAValue(IXFA_DocView* pXFADocView, + IXFA_Widget* hWidget, + CPDF_FormField* pFormField, + CPDF_FormControl* pFormControl) { + ASSERT(pXFADocView != NULL); + ASSERT(hWidget != NULL); + + if (IXFA_WidgetHandler* pXFAWidgetHandler = pXFADocView->GetWidgetHandler()) { + ASSERT(pFormField != NULL); + ASSERT(pFormControl != NULL); + + switch (pFormField->GetFieldType()) { + case FIELDTYPE_CHECKBOX: { + if (CXFA_WidgetAcc* pWidgetAcc = + pXFAWidgetHandler->GetDataAcc(hWidget)) { + FX_BOOL bChecked = pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On; + + pFormField->CheckControl(pFormField->GetControlIndex(pFormControl), + bChecked, TRUE); + } + } break; + case FIELDTYPE_RADIOBUTTON: { + if (CXFA_WidgetAcc* pWidgetAcc = + pXFAWidgetHandler->GetDataAcc(hWidget)) { + FX_BOOL bChecked = pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On; + + pFormField->CheckControl(pFormField->GetControlIndex(pFormControl), + bChecked, TRUE); + } + } break; + case FIELDTYPE_TEXTFIELD: { + if (CXFA_WidgetAcc* pWidgetAcc = + pXFAWidgetHandler->GetDataAcc(hWidget)) { + CFX_WideString sValue; + pWidgetAcc->GetValue(sValue, XFA_VALUEPICTURE_Display); + pFormField->SetValue(sValue, TRUE); + } + } break; + case FIELDTYPE_LISTBOX: { + pFormField->ClearSelection(FALSE); + + if (CXFA_WidgetAcc* pWidgetAcc = + pXFAWidgetHandler->GetDataAcc(hWidget)) { + for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) { + int nIndex = pWidgetAcc->GetSelectedItem(i); + + if (nIndex > -1 && nIndex < pFormField->CountOptions()) { + pFormField->SetItemSelection(nIndex, TRUE, TRUE); + } + } + } + } break; + case FIELDTYPE_COMBOBOX: { + pFormField->ClearSelection(FALSE); + + if (CXFA_WidgetAcc* pWidgetAcc = + pXFAWidgetHandler->GetDataAcc(hWidget)) { + for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) { + int nIndex = pWidgetAcc->GetSelectedItem(i); + + if (nIndex > -1 && nIndex < pFormField->CountOptions()) { + pFormField->SetItemSelection(nIndex, TRUE, TRUE); + } + } + + CFX_WideString sValue; + pWidgetAcc->GetValue(sValue, XFA_VALUEPICTURE_Display); + pFormField->SetValue(sValue, TRUE); + } + } break; + } + } +} + +void CPDFSDK_Widget::SynchronizeXFAItems(IXFA_DocView* pXFADocView, + IXFA_Widget* hWidget, + CPDF_FormField* pFormField, + CPDF_FormControl* pFormControl) { + ASSERT(pXFADocView != NULL); + ASSERT(hWidget != NULL); + + if (IXFA_WidgetHandler* pXFAWidgetHandler = pXFADocView->GetWidgetHandler()) { + ASSERT(pFormField != NULL); + + switch (pFormField->GetFieldType()) { + case FIELDTYPE_LISTBOX: { + pFormField->ClearSelection(FALSE); + pFormField->ClearOptions(TRUE); + + if (CXFA_WidgetAcc* pWidgetAcc = + pXFAWidgetHandler->GetDataAcc(hWidget)) { + for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(); i < sz; + i++) { + CFX_WideString swText; + pWidgetAcc->GetChoiceListItem(swText, i); + + pFormField->InsertOption(swText, i, TRUE); + } + } + } break; + case FIELDTYPE_COMBOBOX: { + pFormField->ClearSelection(FALSE); + pFormField->ClearOptions(FALSE); + + if (CXFA_WidgetAcc* pWidgetAcc = + pXFAWidgetHandler->GetDataAcc(hWidget)) { + for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(); i < sz; + i++) { + CFX_WideString swText; + pWidgetAcc->GetChoiceListItem(swText, i); + + pFormField->InsertOption(swText, i, FALSE); + } + } + + pFormField->SetValue(L"", TRUE); + } break; + } + } +} +#endif // PDF_ENABLE_XFA + FX_BOOL CPDFSDK_Widget::IsWidgetAppearanceValid( CPDF_Annot::AppearanceMode mode) { CPDF_Dictionary* pAP = m_pAnnot->GetAnnotDict()->GetDictBy("AP"); @@ -77,6 +501,13 @@ int CPDFSDK_Widget::GetFieldType() const { } FX_BOOL CPDFSDK_Widget::IsAppearanceValid() { +#ifdef PDF_ENABLE_XFA + CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument(); + CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument(); + int nDocType = pDoc->GetDocType(); + if (nDocType != DOCTYPE_PDF && nDocType != DOCTYPE_STATIC_XFA) + return TRUE; +#endif // PDF_ENABLE_XFA return CPDFSDK_BAAnnot::IsAppearanceValid(); } @@ -117,6 +548,13 @@ int CPDFSDK_Widget::GetRotate() const { return pCtrl->GetRotation() % 360; } +#ifdef PDF_ENABLE_XFA +CFX_WideString CPDFSDK_Widget::GetName() const { + CPDF_FormField* pFormField = GetFormField(); + return pFormField->GetFullName(); +} +#endif // PDF_ENABLE_XFA + FX_BOOL CPDFSDK_Widget::GetFillColor(FX_COLORREF& color) const { CPDF_FormControl* pFormCtrl = GetFormControl(); int iColorType = 0; @@ -159,11 +597,35 @@ FX_FLOAT CPDFSDK_Widget::GetFontSize() const { } int CPDFSDK_Widget::GetSelectedIndex(int nIndex) const { +#ifdef PDF_ENABLE_XFA + if (IXFA_Widget* hWidget = this->GetMixXFAWidget()) { + if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) { + if (CXFA_WidgetAcc* pWidgetAcc = pXFAWidgetHandler->GetDataAcc(hWidget)) { + if (nIndex < pWidgetAcc->CountSelectedItems()) + return pWidgetAcc->GetSelectedItem(nIndex); + } + } + } +#endif // PDF_ENABLE_XFA CPDF_FormField* pFormField = GetFormField(); return pFormField->GetSelectedIndex(nIndex); } +#ifdef PDF_ENABLE_XFA +CFX_WideString CPDFSDK_Widget::GetValue(FX_BOOL bDisplay) const { + if (IXFA_Widget* hWidget = this->GetMixXFAWidget()) { + if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) { + if (CXFA_WidgetAcc* pWidgetAcc = pXFAWidgetHandler->GetDataAcc(hWidget)) { + CFX_WideString sValue; + pWidgetAcc->GetValue(sValue, bDisplay ? XFA_VALUEPICTURE_Display + : XFA_VALUEPICTURE_Edit); + return sValue; + } + } + } +#else CFX_WideString CPDFSDK_Widget::GetValue() const { +#endif // PDF_ENABLE_XFA CPDF_FormField* pFormField = GetFormField(); return pFormField->GetValue(); } @@ -184,6 +646,18 @@ int CPDFSDK_Widget::CountOptions() const { } FX_BOOL CPDFSDK_Widget::IsOptionSelected(int nIndex) const { +#ifdef PDF_ENABLE_XFA + if (IXFA_Widget* hWidget = this->GetMixXFAWidget()) { + if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) { + if (CXFA_WidgetAcc* pWidgetAcc = pXFAWidgetHandler->GetDataAcc(hWidget)) { + if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems()) + return pWidgetAcc->GetItemState(nIndex); + + return FALSE; + } + } + } +#endif // PDF_ENABLE_XFA CPDF_FormField* pFormField = GetFormField(); return pFormField->IsItemSelected(nIndex); } @@ -194,6 +668,16 @@ int CPDFSDK_Widget::GetTopVisibleIndex() const { } FX_BOOL CPDFSDK_Widget::IsChecked() const { +#ifdef PDF_ENABLE_XFA + if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) { + if (IXFA_Widget* hWidget = this->GetMixXFAWidget()) { + if (CXFA_WidgetAcc* pWidgetAcc = pXFAWidgetHandler->GetDataAcc(hWidget)) { + FX_BOOL bChecked = pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On; + return bChecked; + } + } + } +#endif // PDF_ENABLE_XFA CPDF_FormControl* pFormCtrl = GetFormControl(); return pFormCtrl->IsChecked(); } @@ -213,11 +697,21 @@ void CPDFSDK_Widget::SetCheck(FX_BOOL bChecked, FX_BOOL bNotify) { CPDF_FormField* pFormField = pFormCtrl->GetField(); pFormField->CheckControl(pFormField->GetControlIndex(pFormCtrl), bChecked, bNotify); +#ifdef PDF_ENABLE_XFA + if (!IsWidgetAppearanceValid(CPDF_Annot::Normal)) + ResetAppearance(TRUE); + if (!bNotify) + Synchronize(TRUE); +#endif // PDF_ENABLE_XFA } void CPDFSDK_Widget::SetValue(const CFX_WideString& sValue, FX_BOOL bNotify) { CPDF_FormField* pFormField = GetFormField(); pFormField->SetValue(sValue, bNotify); +#ifdef PDF_ENABLE_XFA + if (!bNotify) + Synchronize(TRUE); +#endif // PDF_ENABLE_XFA } void CPDFSDK_Widget::SetDefaultValue(const CFX_WideString& sValue) {} @@ -226,11 +720,19 @@ void CPDFSDK_Widget::SetOptionSelection(int index, FX_BOOL bNotify) { CPDF_FormField* pFormField = GetFormField(); pFormField->SetItemSelection(index, bSelected, bNotify); +#ifdef PDF_ENABLE_XFA + if (!bNotify) + Synchronize(TRUE); +#endif // PDF_ENABLE_XFA } void CPDFSDK_Widget::ClearSelection(FX_BOOL bNotify) { CPDF_FormField* pFormField = GetFormField(); pFormField->ClearSelection(bNotify); +#ifdef PDF_ENABLE_XFA + if (!bNotify) + Synchronize(TRUE); +#endif // PDF_ENABLE_XFA } void CPDFSDK_Widget::SetTopVisibleIndex(int index) {} @@ -247,6 +749,25 @@ FX_BOOL CPDFSDK_Widget::IsAppModified() const { return m_bAppModified; } +#ifdef PDF_ENABLE_XFA +void CPDFSDK_Widget::ResetAppearance(FX_BOOL bValueChanged) { + switch (GetFieldType()) { + case FIELDTYPE_TEXTFIELD: + case FIELDTYPE_COMBOBOX: { + FX_BOOL bFormated = FALSE; + CFX_WideString sValue = this->OnFormat(bFormated); + if (bFormated) + this->ResetAppearance(sValue, TRUE); + else + this->ResetAppearance(NULL, TRUE); + } break; + default: + this->ResetAppearance(NULL, FALSE); + break; + } +} +#endif // PDF_ENABLE_XFA + void CPDFSDK_Widget::ResetAppearance(const FX_WCHAR* sValue, FX_BOOL bValueChanged) { SetAppModified(); @@ -1061,6 +1582,14 @@ void CPDFSDK_Widget::ResetAppearance_TextField(const FX_WCHAR* sValue) { FX_BOOL bCharArray = (dwFieldFlags >> 24) & 1; FX_FLOAT fFontSize = GetFontSize(); +#ifdef PDF_ENABLE_XFA + CFX_WideString sValueTmp; + if (!sValue && (NULL != this->GetMixXFAWidget())) { + sValueTmp = GetValue(TRUE); + sValue = sValueTmp; + } +#endif // PDF_ENABLE_XFA + if (nMaxLen > 0) { if (bCharArray) { pEdit->SetCharArray(nMaxLen); @@ -1353,8 +1882,48 @@ FX_BOOL CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type, CPDFSDK_PageView* pPageView) { CPDFSDK_Document* pDocument = pPageView->GetSDKDocument(); CPDFDoc_Environment* pEnv = pDocument->GetEnv(); - CPDF_Action action = GetAAction(type); +#ifdef PDF_ENABLE_XFA + CPDFXFA_Document* pDoc = pDocument->GetXFADocument(); + if (IXFA_Widget* hWidget = GetMixXFAWidget()) { + XFA_EVENTTYPE eEventType = GetXFAEventType(type, data.bWillCommit); + + if (eEventType != XFA_EVENT_Unknown) { + if (IXFA_WidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler()) { + CXFA_EventParam param; + param.m_eType = eEventType; + param.m_wsChange = data.sChange; + param.m_iCommitKey = data.nCommitKey; + param.m_bShift = data.bShift; + param.m_iSelStart = data.nSelStart; + param.m_iSelEnd = data.nSelEnd; + param.m_wsFullText = data.sValue; + param.m_bKeyDown = data.bKeyDown; + param.m_bModifier = data.bModifier; + param.m_wsNewText = data.sValue; + if (data.nSelEnd > data.nSelStart) + param.m_wsNewText.Delete(data.nSelStart, + data.nSelEnd - data.nSelStart); + for (int i = data.sChange.GetLength() - 1; i >= 0; i--) + param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]); + param.m_wsPrevText = data.sValue; + + CXFA_WidgetAcc* pAcc = pXFAWidgetHandler->GetDataAcc(hWidget); + param.m_pTarget = pAcc; + int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, ¶m); + + if (IXFA_DocView* pDocView = pDoc->GetXFADocView()) { + pDocView->UpdateDocView(); + } + + if (nRet == XFA_EVENTERROR_Sucess) + return TRUE; + } + } + } +#endif // PDF_ENABLE_XFA + + CPDF_Action action = GetAAction(type); if (action && action.GetType() != CPDF_Action::Unknown) { CPDFSDK_ActionHandler* pActionHandler = pEnv->GetActionHander(); return pActionHandler->DoAction_Field(action, type, pDocument, @@ -1423,9 +1992,43 @@ FX_BOOL CPDFSDK_Widget::HitTest(FX_FLOAT pageX, FX_FLOAT pageY) { return FALSE; } +#ifdef PDF_ENABLE_XFA +CPDFSDK_XFAWidget::CPDFSDK_XFAWidget(IXFA_Widget* pAnnot, + CPDFSDK_PageView* pPageView, + CPDFSDK_InterForm* pInterForm) + : CPDFSDK_Annot(pPageView), m_pInterForm(pInterForm), m_hXFAWidget(pAnnot) { +} + +FX_BOOL CPDFSDK_XFAWidget::IsXFAField() { + return TRUE; +} + +CFX_ByteString CPDFSDK_XFAWidget::GetType() const { + return FSDK_XFAWIDGET_TYPENAME; +} + +CFX_FloatRect CPDFSDK_XFAWidget::GetRect() const { + CPDFSDK_PageView* pPageView = GetPageView(); + CPDFSDK_Document* pDocument = pPageView->GetSDKDocument(); + CPDFXFA_Document* pDoc = pDocument->GetXFADocument(); + IXFA_DocView* pDocView = pDoc->GetXFADocView(); + IXFA_WidgetHandler* pWidgetHandler = pDocView->GetWidgetHandler(); + + CFX_RectF rcBBox; + pWidgetHandler->GetRect(GetXFAWidget(), rcBBox); + + return CFX_FloatRect(rcBBox.left, rcBBox.top, rcBBox.left + rcBBox.width, + rcBBox.top + rcBBox.height); +} +#endif // PDF_ENABLE_XFA + CPDFSDK_InterForm::CPDFSDK_InterForm(CPDFSDK_Document* pDocument) : m_pDocument(pDocument), m_pInterForm(NULL), +#ifdef PDF_ENABLE_XFA + m_bXfaCalculate(TRUE), + m_bXfaValidationsEnabled(TRUE), +#endif // PDF_ENABLE_XFA m_bCalculate(TRUE), m_bBusy(FALSE) { m_pInterForm = new CPDF_InterForm(m_pDocument->GetPDFDocument(), FALSE); @@ -1440,6 +2043,9 @@ CPDFSDK_InterForm::~CPDFSDK_InterForm() { delete m_pInterForm; m_pInterForm = nullptr; m_Map.clear(); +#ifdef PDF_ENABLE_XFA + m_XFAMap.RemoveAll(); +#endif // PDF_ENABLE_XFA } FX_BOOL CPDFSDK_InterForm::HighlightWidgets() { @@ -1552,6 +2158,38 @@ FX_BOOL CPDFSDK_InterForm::IsCalculateEnabled() const { return m_bCalculate; } +#ifdef PDF_ENABLE_XFA +void CPDFSDK_InterForm::AddXFAMap(IXFA_Widget* hWidget, + CPDFSDK_XFAWidget* pWidget) { + m_XFAMap.SetAt(hWidget, pWidget); +} + +void CPDFSDK_InterForm::RemoveXFAMap(IXFA_Widget* hWidget) { + m_XFAMap.RemoveKey(hWidget); +} + +CPDFSDK_XFAWidget* CPDFSDK_InterForm::GetXFAWidget(IXFA_Widget* hWidget) { + CPDFSDK_XFAWidget* pWidget = NULL; + m_XFAMap.Lookup(hWidget, pWidget); + + return pWidget; +} + +void CPDFSDK_InterForm::XfaEnableCalculate(FX_BOOL bEnabled) { + m_bXfaCalculate = bEnabled; +} +FX_BOOL CPDFSDK_InterForm::IsXfaCalculateEnabled() const { + return m_bXfaCalculate; +} + +FX_BOOL CPDFSDK_InterForm::IsXfaValidationsEnabled() { + return m_bXfaValidationsEnabled; +} +void CPDFSDK_InterForm::XfaSetValidationsEnabled(FX_BOOL bEnabled) { + m_bXfaValidationsEnabled = bEnabled; +} +#endif // PDF_ENABLE_XFA + void CPDFSDK_InterForm::OnCalculate(CPDF_FormField* pFormField) { CPDFDoc_Environment* pEnv = m_pDocument->GetEnv(); ASSERT(pEnv); @@ -1861,6 +2499,27 @@ FX_BOOL CPDFSDK_InterForm::ExportFieldsToFDFTextBuf( return pFDF ? pFDF->WriteBuf(textBuf) : FALSE; } +#ifdef PDF_ENABLE_XFA +void CPDFSDK_InterForm::SynchronizeField(CPDF_FormField* pFormField, + FX_BOOL bSynchronizeElse) { + ASSERT(pFormField != NULL); + + int x = 0; + if (m_FieldSynchronizeMap.Lookup(pFormField, x)) + return; + + for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) { + CPDF_FormControl* pFormCtrl = pFormField->GetControl(i); + ASSERT(pFormCtrl != NULL); + + ASSERT(m_pInterForm != NULL); + if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl)) { + pWidget->Synchronize(bSynchronizeElse); + } + } +} +#endif // PDF_ENABLE_XFA + CFX_WideString CPDFSDK_InterForm::GetTemporaryFileName( const CFX_WideString& sFileExt) { CFX_WideString sFileName; @@ -1965,6 +2624,9 @@ int CPDFSDK_InterForm::BeforeValueChange(CPDF_FormField* pField, } void CPDFSDK_InterForm::AfterValueChange(CPDF_FormField* pField) { +#ifdef PDF_ENABLE_XFA + SynchronizeField(pField, FALSE); +#endif // PDF_ENABLE_XFA int nType = pField->GetFieldType(); if (nType == FIELDTYPE_COMBOBOX || nType == FIELDTYPE_TEXTFIELD) { OnCalculate(pField); diff --git a/fpdfsdk/src/fsdk_mgr.cpp b/fpdfsdk/src/fsdk_mgr.cpp index 980ffb4534..65dc926fb3 100644 --- a/fpdfsdk/src/fsdk_mgr.cpp +++ b/fpdfsdk/src/fsdk_mgr.cpp @@ -15,6 +15,13 @@ #include "public/fpdf_ext.h" #include "third_party/base/stl_util.h" +#ifdef PDF_ENABLE_XFA +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_app.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_page.h" +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h" +#endif // PDF_ENABLE_XFA + #if _FX_OS_ == _FX_ANDROID_ #include "time.h" #else @@ -218,6 +225,11 @@ CPDFDoc_Environment::CPDFDoc_Environment(UnderlyingDocumentType* pDoc, } CPDFDoc_Environment::~CPDFDoc_Environment() { +#ifdef PDF_ENABLE_XFA + CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance(); + if (pProvider->m_pEnvList.GetSize() == 0) + pProvider->SetJavaScriptInitialized(FALSE); +#endif // PDF_ENABLE_XFA } int CPDFDoc_Environment::JS_appAlert(const FX_WCHAR* Msg, @@ -551,10 +563,17 @@ FX_BOOL CPDFSDK_Document::SetFocusAnnot(CPDFSDK_Annot* pAnnot, FX_UINT nFlag) { if (!pAnnot) return FALSE; +#ifdef PDF_ENABLE_XFA + CPDFSDK_Annot* pLastFocusAnnot = m_pFocusAnnot; +#endif // PDF_ENABLE_XFA CPDFSDK_PageView* pPageView = pAnnot->GetPageView(); if (pPageView && pPageView->IsValid()) { CPDFSDK_AnnotHandlerMgr* pAnnotHandler = m_pEnv->GetAnnotHandlerMgr(); if (!m_pFocusAnnot) { +#ifdef PDF_ENABLE_XFA + if (!pAnnotHandler->Annot_OnChangeFocus(pAnnot, pLastFocusAnnot)) + return FALSE; +#endif // PDF_ENABLE_XFA if (!pAnnotHandler->Annot_OnSetFocus(pAnnot, nFlag)) return FALSE; if (!m_pFocusAnnot) { @@ -571,6 +590,12 @@ FX_BOOL CPDFSDK_Document::KillFocusAnnot(FX_UINT nFlag) { CPDFSDK_AnnotHandlerMgr* pAnnotHandler = m_pEnv->GetAnnotHandlerMgr(); CPDFSDK_Annot* pFocusAnnot = m_pFocusAnnot; m_pFocusAnnot = nullptr; + +#ifdef PDF_ENABLE_XFA + if (!pAnnotHandler->Annot_OnChangeFocus(nullptr, pFocusAnnot)) + return FALSE; +#endif // PDF_ENABLE_XFA + if (pAnnotHandler->Annot_OnKillFocus(pFocusAnnot, nFlag)) { if (pFocusAnnot->GetType() == "Widget") { CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pFocusAnnot; @@ -611,18 +636,27 @@ CPDFSDK_PageView::CPDFSDK_PageView(CPDFSDK_Document* pSDKDoc, : m_page(page), m_pSDKDoc(pSDKDoc), m_CaptureWidget(nullptr), +#ifndef PDF_ENABLE_XFA + m_bTakeOverPage(FALSE), +#endif // PDF_ENABLE_XFA m_bEnterWidget(FALSE), m_bExitWidget(FALSE), m_bOnWidget(FALSE), m_bValid(FALSE), - m_bLocked(FALSE), - m_bTakeOverPage(FALSE) { + m_bLocked(FALSE) { CPDFSDK_InterForm* pInterForm = pSDKDoc->GetInterForm(); if (pInterForm) { CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm(); +#ifdef PDF_ENABLE_XFA + if (page->GetPDFPage()) + pPDFInterForm->FixPageFields(page->GetPDFPage()); +#else // PDF_ENABLE_XFA pPDFInterForm->FixPageFields(page); +#endif // PDF_ENABLE_XFA } +#ifndef PDF_ENABLE_XFA m_page->SetPrivateData((void*)m_page, (void*)this, nullptr); +#endif // PDF_ENABLE_XFA } CPDFSDK_PageView::~CPDFSDK_PageView() { @@ -630,21 +664,66 @@ CPDFSDK_PageView::~CPDFSDK_PageView() { CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = pEnv->GetAnnotHandlerMgr(); for (CPDFSDK_Annot* pAnnot : m_fxAnnotArray) pAnnotHandlerMgr->ReleaseAnnot(pAnnot); - m_fxAnnotArray.clear(); + m_fxAnnotArray.clear(); m_pAnnotList.reset(); - +#ifndef PDF_ENABLE_XFA m_page->RemovePrivateData((void*)m_page); if (m_bTakeOverPage) { delete m_page; } +#endif // PDF_ENABLE_XFA } void CPDFSDK_PageView::PageView_OnDraw(CFX_RenderDevice* pDevice, CFX_Matrix* pUser2Device, +#ifdef PDF_ENABLE_XFA + CPDF_RenderOptions* pOptions, + const FX_RECT& pClip) { +#else CPDF_RenderOptions* pOptions) { +#endif // PDF_ENABLE_XFA m_curMatrix = *pUser2Device; CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + +#ifdef PDF_ENABLE_XFA + CPDFXFA_Page* pPage = GetPDFXFAPage(); + if (!pPage) + return; + + if (pPage->GetDocument()->GetDocType() == DOCTYPE_DYNAMIC_XFA) { + CFX_Graphics gs; + gs.Create(pDevice); + CFX_RectF rectClip; + rectClip.Set(static_cast<FX_FLOAT>(pClip.left), + static_cast<FX_FLOAT>(pClip.top), + static_cast<FX_FLOAT>(pClip.Width()), + static_cast<FX_FLOAT>(pClip.Height())); + gs.SetClipRect(rectClip); + IXFA_RenderContext* pRenderContext = XFA_RenderContext_Create(); + if (!pRenderContext) + return; + CXFA_RenderOptions renderOptions; + renderOptions.m_bHighlight = TRUE; + IXFA_PageView* xfaView = pPage->GetXFAPageView(); + pRenderContext->StartRender(xfaView, &gs, *pUser2Device, renderOptions); + pRenderContext->DoRender(); + pRenderContext->StopRender(); + pRenderContext->Release(); + IXFA_DocView* docView = xfaView->GetDocView(); + if (!docView) + return; + CPDFSDK_Annot* annot = GetFocusAnnot(); + if (!annot) + return; + // Render the focus widget + docView->GetWidgetHandler()->RenderWidget(annot->GetXFAWidget(), &gs, + pUser2Device, FALSE); + return; + } +#endif // PDF_ENABLE_XFA + + // for pdf/static xfa. CPDFSDK_AnnotIterator annotIterator(this, true); while (CPDFSDK_Annot* pSDKAnnot = annotIterator.Next()) { CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = pEnv->GetAnnotHandlerMgr(); @@ -696,7 +775,11 @@ CPDFSDK_Annot* CPDFSDK_PageView::GetFXWidgetAtPoint(FX_FLOAT pageX, CPDFSDK_AnnotHandlerMgr* pAnnotMgr = pEnv->GetAnnotHandlerMgr(); CPDFSDK_AnnotIterator annotIterator(this, false); while (CPDFSDK_Annot* pSDKAnnot = annotIterator.Next()) { - if (pSDKAnnot->GetType() == "Widget") { + bool bHitTest = pSDKAnnot->GetType() == "Widget"; +#ifdef PDF_ENABLE_XFA + bHitTest = bHitTest || pSDKAnnot->GetType() == FSDK_XFAWIDGET_TYPENAME; +#endif // PDF_ENABLE_XFA + if (bHitTest) { pAnnotMgr->Annot_OnGetViewBBox(this, pSDKAnnot); CPDF_Point point(pageX, pageY); if (pAnnotMgr->Annot_OnHitTest(this, pSDKAnnot, point)) @@ -735,6 +818,26 @@ CPDFSDK_Annot* CPDFSDK_PageView::AddAnnot(CPDF_Annot* pPDFAnnot) { return pSDKAnnot; } +#ifdef PDF_ENABLE_XFA +CPDFSDK_Annot* CPDFSDK_PageView::AddAnnot(IXFA_Widget* pPDFAnnot) { + if (!pPDFAnnot) + return nullptr; + + CPDFSDK_Annot* pSDKAnnot = GetAnnotByXFAWidget(pPDFAnnot); + if (pSDKAnnot) + return pSDKAnnot; + + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + CPDFSDK_AnnotHandlerMgr* pAnnotHandler = pEnv->GetAnnotHandlerMgr(); + pSDKAnnot = pAnnotHandler->NewAnnot(pPDFAnnot, this); + if (!pSDKAnnot) + return nullptr; + + m_fxAnnotArray.push_back(pSDKAnnot); + return pSDKAnnot; +} +#endif // PDF_ENABLE_XFA + CPDFSDK_Annot* CPDFSDK_PageView::AddAnnot(CPDF_Dictionary* pDict) { return pDict ? AddAnnot(pDict->GetStringBy("Subtype"), pDict) : nullptr; } @@ -745,16 +848,46 @@ CPDFSDK_Annot* CPDFSDK_PageView::AddAnnot(const FX_CHAR* lpSubType, } FX_BOOL CPDFSDK_PageView::DeleteAnnot(CPDFSDK_Annot* pAnnot) { +#ifdef PDF_ENABLE_XFA + if (!pAnnot) + return FALSE; + CPDFXFA_Page* pPage = pAnnot->GetPDFXFAPage(); + if (!pPage || (pPage->GetDocument()->GetDocType() != DOCTYPE_STATIC_XFA && + pPage->GetDocument()->GetDocType() != DOCTYPE_DYNAMIC_XFA)) + return FALSE; + + auto it = std::find(m_fxAnnotArray.begin(), m_fxAnnotArray.end(), pAnnot); + if (it != m_fxAnnotArray.end()) + m_fxAnnotArray.erase(it); + if (m_CaptureWidget == pAnnot) + m_CaptureWidget = nullptr; + + return TRUE; +#else // PDF_ENABLE_XFA return FALSE; +#endif // PDF_ENABLE_XFA } CPDF_Document* CPDFSDK_PageView::GetPDFDocument() { if (m_page) { +#ifdef PDF_ENABLE_XFA + return m_page->GetDocument()->GetPDFDoc(); +#else // PDF_ENABLE_XFA return m_page->m_pDocument; +#endif // PDF_ENABLE_XFA } return NULL; } +#ifdef PDF_ENABLE_XFA +CPDF_Page* CPDFSDK_PageView::GetPDFPage() { + if (m_page) { + return m_page->GetPDFPage(); + } + return NULL; +} +#endif // PDF_ENABLE_XFA + size_t CPDFSDK_PageView::CountAnnots() const { return m_fxAnnotArray.size(); } @@ -771,6 +904,19 @@ CPDFSDK_Annot* CPDFSDK_PageView::GetAnnotByDict(CPDF_Dictionary* pDict) { return nullptr; } +#ifdef PDF_ENABLE_XFA +CPDFSDK_Annot* CPDFSDK_PageView::GetAnnotByXFAWidget(IXFA_Widget* hWidget) { + if (!hWidget) + return nullptr; + + for (CPDFSDK_Annot* pAnnot : m_fxAnnotArray) { + if (pAnnot->GetXFAWidget() == hWidget) + return pAnnot; + } + return nullptr; +} +#endif // PDF_ENABLE_XFA + FX_BOOL CPDFSDK_PageView::OnLButtonDown(const CPDF_Point& point, FX_UINT nFlag) { CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); @@ -789,6 +935,46 @@ FX_BOOL CPDFSDK_PageView::OnLButtonDown(const CPDF_Point& point, return bRet; } +#ifdef PDF_ENABLE_XFA +FX_BOOL CPDFSDK_PageView::OnRButtonDown(const CPDF_Point& point, + FX_UINT nFlag) { + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + ASSERT(pEnv); + CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = pEnv->GetAnnotHandlerMgr(); + ASSERT(pAnnotHandlerMgr); + + CPDFSDK_Annot* pFXAnnot = GetFXWidgetAtPoint(point.x, point.y); + + if (pFXAnnot == NULL) + return FALSE; + + FX_BOOL bRet = + pAnnotHandlerMgr->Annot_OnRButtonDown(this, pFXAnnot, nFlag, point); + if (bRet) { + SetFocusAnnot(pFXAnnot); + } + return TRUE; +} + +FX_BOOL CPDFSDK_PageView::OnRButtonUp(const CPDF_Point& point, FX_UINT nFlag) { + CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); + ASSERT(pEnv); + CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = pEnv->GetAnnotHandlerMgr(); + + CPDFSDK_Annot* pFXAnnot = GetFXWidgetAtPoint(point.x, point.y); + + if (pFXAnnot == NULL) + return FALSE; + + FX_BOOL bRet = + pAnnotHandlerMgr->Annot_OnRButtonUp(this, pFXAnnot, nFlag, point); + if (bRet) { + SetFocusAnnot(pFXAnnot); + } + return TRUE; +} +#endif // PDF_ENABLE_XFA + FX_BOOL CPDFSDK_PageView::OnLButtonUp(const CPDF_Point& point, FX_UINT nFlag) { CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); ASSERT(pEnv); @@ -874,28 +1060,93 @@ FX_BOOL CPDFSDK_PageView::OnKeyUp(int nKeyCode, int nFlag) { void CPDFSDK_PageView::LoadFXAnnots() { CPDFDoc_Environment* pEnv = m_pSDKDoc->GetEnv(); - +#ifdef PDF_ENABLE_XFA + CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = pEnv->GetAnnotHandlerMgr(); +#else FX_BOOL enableAPUpdate = CPDF_InterForm::UpdatingAPEnabled(); // Disable the default AP construction. CPDF_InterForm::EnableUpdateAP(FALSE); m_pAnnotList.reset(new CPDF_AnnotList(m_page)); CPDF_InterForm::EnableUpdateAP(enableAPUpdate); const size_t nCount = m_pAnnotList->Count(); +#endif // PDF_ENABLE_XFA + SetLock(TRUE); + +#ifdef PDF_ENABLE_XFA + m_page->AddRef(); + if (m_pSDKDoc->GetXFADocument()->GetDocType() == DOCTYPE_DYNAMIC_XFA) { + IXFA_PageView* pageView = NULL; + pageView = m_page->GetXFAPageView(); + ASSERT(pageView != NULL); + + IXFA_WidgetIterator* pWidgetHander = pageView->CreateWidgetIterator( + XFA_TRAVERSEWAY_Form, XFA_WIDGETFILTER_Visible | + XFA_WIDGETFILTER_Viewable | + XFA_WIDGETFILTER_AllType); + if (!pWidgetHander) { + m_page->Release(); + SetLock(FALSE); + return; + } + + while (IXFA_Widget* pXFAAnnot = pWidgetHander->MoveToNext()) { + CPDFSDK_Annot* pAnnot = pAnnotHandlerMgr->NewAnnot(pXFAAnnot, this); + if (!pAnnot) + continue; + + m_fxAnnotArray.push_back(pAnnot); + pAnnotHandlerMgr->Annot_OnLoad(pAnnot); + } + pWidgetHander->Release(); + } else { + CPDF_Page* pPage = m_page->GetPDFPage(); + ASSERT(pPage != NULL); + FX_BOOL enableAPUpdate = CPDF_InterForm::UpdatingAPEnabled(); + // Disable the default AP construction. + CPDF_InterForm::EnableUpdateAP(FALSE); + m_pAnnotList.reset(new CPDF_AnnotList(pPage)); + CPDF_InterForm::EnableUpdateAP(enableAPUpdate); + + const size_t nCount = m_pAnnotList->Count(); + for (size_t i = 0; i < nCount; ++i) { + CPDF_Annot* pPDFAnnot = m_pAnnotList->GetAt(i); + CheckUnSupportAnnot(GetPDFDocument(), pPDFAnnot); + + CPDFSDK_Annot* pAnnot = pAnnotHandlerMgr->NewAnnot(pPDFAnnot, this); + if (!pAnnot) + continue; + m_fxAnnotArray.push_back(pAnnot); + pAnnotHandlerMgr->Annot_OnLoad(pAnnot); + } + } + m_page->Release(); +#else // PDF_ENABLE_XFA for (size_t i = 0; i < nCount; ++i) { CPDF_Annot* pPDFAnnot = m_pAnnotList->GetAt(i); CPDF_Document* pDoc = GetPDFDocument(); - CheckUnSupportAnnot(pDoc, pPDFAnnot); - CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = pEnv->GetAnnotHandlerMgr(); CPDFSDK_Annot* pAnnot = pAnnotHandlerMgr->NewAnnot(pPDFAnnot, this); if (!pAnnot) continue; m_fxAnnotArray.push_back(pAnnot); - pAnnotHandlerMgr->Annot_OnLoad(pAnnot); } +#endif // PDF_ENABLE_XFA + + SetLock(FALSE); +} + +void CPDFSDK_PageView::ClearFXAnnots() { + SetLock(TRUE); + if (m_pSDKDoc && GetFocusAnnot()) + m_pSDKDoc->SetFocusAnnot(nullptr); + m_CaptureWidget = nullptr; + for (CPDFSDK_Annot* pAnnot : m_fxAnnotArray) + m_pSDKDoc->GetEnv()->GetAnnotHandlerMgr()->ReleaseAnnot(pAnnot); + m_fxAnnotArray.clear(); + m_pAnnotList.reset(); SetLock(FALSE); } @@ -916,7 +1167,11 @@ void CPDFSDK_PageView::UpdateView(CPDFSDK_Annot* pAnnot) { int CPDFSDK_PageView::GetPageIndex() { if (m_page) { +#ifdef PDF_ENABLE_XFA + CPDF_Dictionary* pDic = m_page->GetPDFPage()->m_pFormDict; +#else // PDF_ENABLE_XFA CPDF_Dictionary* pDic = m_page->m_pFormDict; +#endif // PDF_ENABLE_XFA CPDF_Document* pDoc = m_pSDKDoc->GetPDFDocument(); if (pDoc && pDic) { return pDoc->GetPageIndex(pDic->GetObjNum()); diff --git a/fpdfsdk/src/javascript/Field.cpp b/fpdfsdk/src/javascript/Field.cpp index 0b78ba24a6..24acd6029c 100644 --- a/fpdfsdk/src/javascript/Field.cpp +++ b/fpdfsdk/src/javascript/Field.cpp @@ -279,10 +279,9 @@ void Field::UpdateFormControl(CPDFSDK_Document* pDocument, CPDFSDK_Widget* Field::GetWidget(CPDFSDK_Document* pDocument, CPDF_FormControl* pFormControl) { - ASSERT(pFormControl); - - CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)pDocument->GetInterForm(); - return pInterForm->GetWidget(pFormControl); + CPDFSDK_InterForm* pInterForm = + static_cast<CPDFSDK_InterForm*>(pDocument->GetInterForm()); + return pInterForm ? pInterForm->GetWidget(pFormControl) : nullptr; } FX_BOOL Field::ValueIsOccur(CPDF_FormField* pFormField, diff --git a/fpdfsdk/src/javascript/JS_Context.cpp b/fpdfsdk/src/javascript/JS_Context.cpp index b9a10e1bc2..9dbf5ed50a 100644 --- a/fpdfsdk/src/javascript/JS_Context.cpp +++ b/fpdfsdk/src/javascript/JS_Context.cpp @@ -33,6 +33,9 @@ CPDFDoc_Environment* CJS_Context::GetReaderApp() { FX_BOOL CJS_Context::RunScript(const CFX_WideString& script, CFX_WideString* info) { v8::Isolate::Scope isolate_scope(m_pRuntime->GetIsolate()); +#ifdef PDF_ENABLE_XFA + v8::Locker locker(m_pRuntime->GetIsolate()); +#endif // PDF_ENABLE_XFA v8::HandleScope handle_scope(m_pRuntime->GetIsolate()); v8::Local<v8::Context> context = m_pRuntime->NewJSContext(); v8::Context::Scope context_scope(context); diff --git a/fpdfsdk/src/javascript/JS_Runtime.cpp b/fpdfsdk/src/javascript/JS_Runtime.cpp index b08823f6ed..95f392487a 100644 --- a/fpdfsdk/src/javascript/JS_Runtime.cpp +++ b/fpdfsdk/src/javascript/JS_Runtime.cpp @@ -28,6 +28,11 @@ #include "util.h" #include "third_party/base/stl_util.h" +#ifdef PDF_ENABLE_XFA +#include "fpdfsdk/include/fpdfxfa/fpdfxfa_app.h" +#include "xfa/src/fxjse/src/value.h" +#endif // PDF_ENABLE_XFA + // static void IJS_Runtime::Initialize(unsigned int slot, void* isolate) { FXJS_Initialize(slot, reinterpret_cast<v8::Isolate*>(isolate)); @@ -50,6 +55,7 @@ CJS_Runtime::CJS_Runtime(CPDFDoc_Environment* pApp) m_bBlocking(FALSE), m_isolate(NULL), m_isolateManaged(false) { +#ifndef PDF_ENABLE_XFA IPDF_JSPLATFORM* pPlatform = m_pApp->GetFormFillInfo()->m_pJsPlatform; if (pPlatform->version <= 2) { unsigned int embedderDataSlot = 0; @@ -57,13 +63,51 @@ CJS_Runtime::CJS_Runtime(CPDFDoc_Environment* pApp) if (pPlatform->version == 2) { pExternalIsolate = reinterpret_cast<v8::Isolate*>(pPlatform->m_isolate); embedderDataSlot = pPlatform->m_v8EmbedderSlot; +#else + if (CPDFXFA_App::GetInstance()->GetJSERuntime()) { + // TODO(tsepez): CPDFXFA_App should also use the embedder provided isolate. + m_isolate = (v8::Isolate*)CPDFXFA_App::GetInstance()->GetJSERuntime(); + } else { + IPDF_JSPLATFORM* pPlatform = m_pApp->GetFormFillInfo()->m_pJsPlatform; + if (pPlatform->version <= 2) { + unsigned int embedderDataSlot = 0; + v8::Isolate* pExternalIsolate = nullptr; + if (pPlatform->version == 2) { + pExternalIsolate = reinterpret_cast<v8::Isolate*>(pPlatform->m_isolate); + embedderDataSlot = pPlatform->m_v8EmbedderSlot; + } + FXJS_Initialize(embedderDataSlot, pExternalIsolate); +#endif } +#ifndef PDF_ENABLE_XFA FXJS_Initialize(embedderDataSlot, pExternalIsolate); +#else + m_isolateManaged = FXJS_GetIsolate(&m_isolate); } + + v8::Isolate* isolate = m_isolate; + v8::Isolate::Scope isolate_scope(isolate); + v8::Locker locker(isolate); + v8::HandleScope handle_scope(isolate); + if (CPDFXFA_App::GetInstance()->IsJavaScriptInitialized()) { + CJS_Context* pContext = (CJS_Context*)NewContext(); + FXJS_InitializeRuntime(GetIsolate(), this, &m_context, &m_StaticObjects); + ReleaseContext(pContext); + return; +#endif + } +#ifndef PDF_ENABLE_XFA m_isolateManaged = FXJS_GetIsolate(&m_isolate); +#else + +#endif if (m_isolateManaged || FXJS_GlobalIsolateRefCount() == 0) DefineJSObjects(); +#ifdef PDF_ENABLE_XFA + CPDFXFA_App::GetInstance()->SetJavaScriptInitialized(TRUE); + +#endif CJS_Context* pContext = (CJS_Context*)NewContext(); FXJS_InitializeRuntime(GetIsolate(), this, &m_context, &m_StaticObjects); ReleaseContext(pContext); @@ -89,6 +133,9 @@ CJS_Runtime::~CJS_Runtime() { void CJS_Runtime::DefineJSObjects() { v8::Isolate::Scope isolate_scope(GetIsolate()); +#ifdef PDF_ENABLE_XFA + v8::Locker locker(GetIsolate()); +#endif v8::HandleScope handle_scope(GetIsolate()); v8::Local<v8::Context> context = v8::Context::New(GetIsolate()); v8::Context::Scope context_scope(context); @@ -161,6 +208,9 @@ IJS_Context* CJS_Runtime::GetCurrentContext() { void CJS_Runtime::SetReaderDocument(CPDFSDK_Document* pReaderDoc) { if (m_pDocument != pReaderDoc) { v8::Isolate::Scope isolate_scope(m_isolate); +#ifdef PDF_ENABLE_XFA + v8::Locker locker(m_isolate); +#endif v8::HandleScope handle_scope(m_isolate); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(m_isolate, m_context); @@ -206,6 +256,74 @@ v8::Local<v8::Context> CJS_Runtime::NewJSContext() { return v8::Local<v8::Context>::New(m_isolate, m_context); } +#ifdef PDF_ENABLE_XFA +CFX_WideString ChangeObjName(const CFX_WideString& str) { + CFX_WideString sRet = str; + sRet.Replace(L"_", L"."); + return sRet; +} +FX_BOOL CJS_Runtime::GetHValueByName(const CFX_ByteStringC& utf8Name, + FXJSE_HVALUE hValue) { +#ifdef PDF_ENABLE_XFA + const FX_CHAR* name = utf8Name.GetCStr(); + + v8::Locker lock(GetIsolate()); + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); + v8::Local<v8::Context> old_context = GetIsolate()->GetCurrentContext(); + v8::Local<v8::Context> context = + v8::Local<v8::Context>::New(GetIsolate(), m_context); + v8::Context::Scope context_scope(context); + + // Caution: We're about to hand to XFA an object that in order to invoke + // methods will require that the current v8::Context always has a pointer + // to a CJS_Runtime in its embedder data slot. Unfortunately, XFA creates + // its own v8::Context which has not initialized the embedder data slot. + // Do so now. + // TODO(tsepez): redesign PDF-side objects to not rely on v8::Context's + // embedder data slots, and/or to always use the right context. + FXJS_SetRuntimeForV8Context(old_context, this); + + v8::Local<v8::Value> propvalue = + context->Global()->Get(v8::String::NewFromUtf8( + GetIsolate(), name, v8::String::kNormalString, utf8Name.GetLength())); + + if (propvalue.IsEmpty()) { + FXJSE_Value_SetUndefined(hValue); + return FALSE; + } + ((CFXJSE_Value*)hValue)->ForceSetValue(propvalue); +#endif + + return TRUE; +} +FX_BOOL CJS_Runtime::SetHValueByName(const CFX_ByteStringC& utf8Name, + FXJSE_HVALUE hValue) { +#ifdef PDF_ENABLE_XFA + if (utf8Name.IsEmpty() || hValue == NULL) + return FALSE; + const FX_CHAR* name = utf8Name.GetCStr(); + v8::Isolate* pIsolate = GetIsolate(); + v8::Locker lock(pIsolate); + v8::Isolate::Scope isolate_scope(pIsolate); + v8::HandleScope handle_scope(pIsolate); + v8::Local<v8::Context> context = + v8::Local<v8::Context>::New(pIsolate, m_context); + v8::Context::Scope context_scope(context); + + // v8::Local<v8::Context> tmpCotext = + // v8::Local<v8::Context>::New(GetIsolate(), m_context); + v8::Local<v8::Value> propvalue = v8::Local<v8::Value>::New( + GetIsolate(), ((CFXJSE_Value*)hValue)->DirectGetValue()); + context->Global()->Set( + v8::String::NewFromUtf8(pIsolate, name, v8::String::kNormalString, + utf8Name.GetLength()), + propvalue); +#endif + return TRUE; +} + +#endif void CJS_Runtime::AddObserver(Observer* observer) { ASSERT(!pdfium::ContainsKey(m_observers, observer)); m_observers.insert(observer); diff --git a/fpdfsdk/src/javascript/JS_Runtime.h b/fpdfsdk/src/javascript/JS_Runtime.h index fcac7a9021..decc553974 100644 --- a/fpdfsdk/src/javascript/JS_Runtime.h +++ b/fpdfsdk/src/javascript/JS_Runtime.h @@ -58,6 +58,13 @@ class CJS_Runtime : public IJS_Runtime { v8::Isolate* GetIsolate() const { return m_isolate; } v8::Local<v8::Context> NewJSContext(); +#ifdef PDF_ENABLE_XFA + FX_BOOL GetHValueByName(const CFX_ByteStringC& utf8Name, + FXJSE_HVALUE hValue) override; + FX_BOOL SetHValueByName(const CFX_ByteStringC& utf8Name, + FXJSE_HVALUE hValue) override; +#endif // PDF_ENABLE_XFA + void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); diff --git a/fpdfsdk/src/javascript/JS_Runtime_Stub.cpp b/fpdfsdk/src/javascript/JS_Runtime_Stub.cpp index ad8d27dae3..e9d5a221f7 100644 --- a/fpdfsdk/src/javascript/JS_Runtime_Stub.cpp +++ b/fpdfsdk/src/javascript/JS_Runtime_Stub.cpp @@ -137,6 +137,18 @@ class CJS_RuntimeStub final : public IJS_Runtime { } CPDFSDK_Document* GetReaderDocument() override { return m_pDoc; } +#ifdef PDF_ENABLE_XFA + virtual FX_BOOL GetHValueByName(const CFX_ByteStringC&, + FXJSE_HVALUE) override { + return FALSE; + } + + virtual FX_BOOL SetHValueByName(const CFX_ByteStringC&, + FXJSE_HVALUE) override { + return FALSE; + } +#endif // PDF_ENABLE_XFA + int Execute(IJS_Context* cc, const wchar_t* script, CFX_WideString* info) override { diff --git a/fpdfsdk/src/javascript/app.cpp b/fpdfsdk/src/javascript/app.cpp index c3acbe6a25..3a971cf146 100644 --- a/fpdfsdk/src/javascript/app.cpp +++ b/fpdfsdk/src/javascript/app.cpp @@ -48,6 +48,9 @@ CJS_Timer* TimerObj::GetTimer() const { #define JS_STR_PLATFORM L"WIN" #define JS_STR_LANGUANGE L"ENU" #define JS_NUM_VIEWERVERSION 8 +#ifdef PDF_ENABLE_XFA +#define JS_NUM_VIEWERVERSION_XFA 11 +#endif // PDF_ENABLE_XFA #define JS_NUM_FORMSVERSION 7 BEGIN_JS_STATIC_CONST(CJS_App) @@ -197,6 +200,15 @@ FX_BOOL app::viewerVersion(IJS_Context* cc, CFX_WideString& sError) { if (!vp.IsGetting()) return FALSE; +#ifdef PDF_ENABLE_XFA + CJS_Context* pContext = (CJS_Context*)cc; + CPDFSDK_Document* pCurDoc = pContext->GetReaderDocument(); + CPDFXFA_Document* pDoc = pCurDoc->GetXFADocument(); + if (pDoc->GetDocType() == 1 || pDoc->GetDocType() == 2) { + vp << JS_NUM_VIEWERVERSION_XFA; + return TRUE; + } +#endif // PDF_ENABLE_XFA vp << JS_NUM_VIEWERVERSION; return TRUE; } @@ -206,6 +218,17 @@ FX_BOOL app::platform(IJS_Context* cc, CFX_WideString& sError) { if (!vp.IsGetting()) return FALSE; +#ifdef PDF_ENABLE_XFA + CPDFDoc_Environment* pEnv = + static_cast<CJS_Context*>(cc)->GetJSRuntime()->GetReaderApp(); + if (!pEnv) + return FALSE; + CFX_WideString platfrom = pEnv->FFI_GetPlatform(); + if (!platfrom.IsEmpty()) { + vp << platfrom; + return TRUE; + } +#endif vp << JS_STR_PLATFORM; return TRUE; } @@ -215,6 +238,17 @@ FX_BOOL app::language(IJS_Context* cc, CFX_WideString& sError) { if (!vp.IsGetting()) return FALSE; +#ifdef PDF_ENABLE_XFA + CPDFDoc_Environment* pEnv = + static_cast<CJS_Context*>(cc)->GetJSRuntime()->GetReaderApp(); + if (!pEnv) + return FALSE; + CFX_WideString language = pEnv->FFI_GetLanguage(); + if (!language.IsEmpty()) { + vp << language; + return TRUE; + } +#endif vp << JS_STR_LANGUANGE; return TRUE; } diff --git a/fpdfsdk/src/javascript/public_methods_embeddertest.cpp b/fpdfsdk/src/javascript/public_methods_embeddertest.cpp index d9e22049f0..c61215aa29 100644 --- a/fpdfsdk/src/javascript/public_methods_embeddertest.cpp +++ b/fpdfsdk/src/javascript/public_methods_embeddertest.cpp @@ -21,6 +21,9 @@ class PublicMethodsEmbedderTest : public JSEmbedderTest {}; TEST_F(PublicMethodsEmbedderTest, MakeRegularDate) { v8::Isolate::Scope isolate_scope(isolate()); +#ifdef PDF_ENABLE_XFA + v8::Locker locker(isolate()); +#endif // PDF_ENABLE_XFA v8::HandleScope handle_scope(isolate()); v8::Context::Scope context_scope(GetV8Context()); bool bWrongFormat; @@ -101,6 +104,9 @@ TEST_F(PublicMethodsEmbedderTest, MakeRegularDate) { TEST_F(PublicMethodsEmbedderTest, MakeFormatDate) { v8::Isolate::Scope isolate_scope(isolate()); +#ifdef PDF_ENABLE_XFA + v8::Locker locker(isolate()); +#endif // PDF_ENABLE_XFA v8::HandleScope handle_scope(isolate()); v8::Context::Scope context_scope(GetV8Context()); CFX_WideString formatted_date; diff --git a/fpdfsdk/src/jsapi/fxjs_v8.cpp b/fpdfsdk/src/jsapi/fxjs_v8.cpp index ed8e2e8563..f015f87136 100644 --- a/fpdfsdk/src/jsapi/fxjs_v8.cpp +++ b/fpdfsdk/src/jsapi/fxjs_v8.cpp @@ -125,6 +125,31 @@ void FXJS_ArrayBufferAllocator::Free(void* data, size_t length) { free(data); } +void V8TemplateMapTraits::Dispose(v8::Isolate* isolate, + v8::Global<v8::Object> value, + void* key) { + v8::Local<v8::Object> obj = value.Get(isolate); + if (obj.IsEmpty()) + return; + int id = FXJS_GetObjDefnID(obj); + if (id == -1) + return; + + CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(isolate, id); + if (!pObjDef) + return; + if (pObjDef->m_pDestructor) + pObjDef->m_pDestructor(obj); + FXJS_FreePrivate(obj); +} + +V8TemplateMapTraits::MapType* V8TemplateMapTraits::MapFromWeakCallbackInfo( + const v8::WeakCallbackInfo<WeakCallbackDataType>& data) { + V8TemplateMap* pMap = + (FXJS_PerIsolateData::Get(data.GetIsolate()))->m_pDynamicObjsMap; + return pMap ? &pMap->m_map : nullptr; +} + void FXJS_Initialize(unsigned int embedderDataSlot, v8::Isolate* pIsolate) { if (g_isolate) { ASSERT(g_embedderDataSlot == embedderDataSlot); @@ -281,12 +306,19 @@ void FXJS_InitializeRuntime( ++g_isolate_ref_count; v8::Isolate::Scope isolate_scope(pIsolate); +#ifdef PDF_ENABLE_XFA + v8::Locker locker(pIsolate); +#endif // PDF_ENABLE_XFA v8::HandleScope handle_scope(pIsolate); v8::Local<v8::Context> v8Context = v8::Context::New(pIsolate, NULL, GetGlobalObjectTemplate(pIsolate)); v8::Context::Scope context_scope(v8Context); FXJS_PerIsolateData::SetUp(pIsolate); + FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate); + if (!pData) + return; + pData->CreateDynamicObjsMap(pIsolate); v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, pIRuntime); int maxID = CFXJS_ObjDefinition::MaxID(pIsolate); @@ -312,7 +344,8 @@ void FXJS_InitializeRuntime( v8::NewStringType::kNormal, bs.GetLength()).ToLocalChecked(); - v8::Local<v8::Object> obj = FXJS_NewFxDynamicObj(pIsolate, pIRuntime, i); + v8::Local<v8::Object> obj = + FXJS_NewFxDynamicObj(pIsolate, pIRuntime, i, true); v8Context->Global()->Set(v8Context, m_ObjName, obj).FromJust(); pStaticObjects->at(i) = new v8::Global<v8::Object>(pIsolate, obj); } @@ -324,6 +357,9 @@ void FXJS_ReleaseRuntime(v8::Isolate* pIsolate, v8::Global<v8::Context>* pV8PersistentContext, std::vector<v8::Global<v8::Object>*>* pStaticObjects) { v8::Isolate::Scope isolate_scope(pIsolate); +#ifdef PDF_ENABLE_XFA + v8::Locker locker(pIsolate); +#endif // PDF_ENABLE_XFA v8::HandleScope handle_scope(pIsolate); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(pIsolate, *pV8PersistentContext); @@ -332,6 +368,7 @@ void FXJS_ReleaseRuntime(v8::Isolate* pIsolate, FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate); if (!pData) return; + pData->ReleaseDynamicObjsMap(); int maxID = CFXJS_ObjDefinition::MaxID(pIsolate); for (int i = 0; i < maxID; ++i) { @@ -369,6 +406,13 @@ IJS_Runtime* FXJS_GetRuntimeFromIsolate(v8::Isolate* pIsolate) { context->GetAlignedPointerFromEmbedderData(kPerContextDataIndex)); } +#ifdef PDF_ENABLE_XFA +void FXJS_SetRuntimeForV8Context(v8::Local<v8::Context> v8Context, + IJS_Runtime* pIRuntime) { + v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, pIRuntime); +} +#endif // PDF_ENABLE_XFA + int FXJS_Execute(v8::Isolate* pIsolate, IJS_Context* pJSContext, const wchar_t* script, @@ -399,7 +443,8 @@ int FXJS_Execute(v8::Isolate* pIsolate, v8::Local<v8::Object> FXJS_NewFxDynamicObj(v8::Isolate* pIsolate, IJS_Runtime* pIRuntime, - int nObjDefnID) { + int nObjDefnID, + bool bStatic) { v8::Isolate::Scope isolate_scope(pIsolate); v8::Local<v8::Context> context = pIsolate->GetCurrentContext(); if (nObjDefnID == -1) { @@ -423,10 +468,15 @@ v8::Local<v8::Object> FXJS_NewFxDynamicObj(v8::Isolate* pIsolate, if (!pObjDef->GetInstanceTemplate()->NewInstance(context).ToLocal(&obj)) return v8::Local<v8::Object>(); - obj->SetAlignedPointerInInternalField(0, new CFXJS_PerObjectData(nObjDefnID)); + CFXJS_PerObjectData* pPerObjData = new CFXJS_PerObjectData(nObjDefnID); + obj->SetAlignedPointerInInternalField(0, pPerObjData); if (pObjDef->m_pConstructor) pObjDef->m_pConstructor(pIRuntime, obj); + if (!bStatic && FXJS_PerIsolateData::Get(pIsolate)->m_pDynamicObjsMap) { + FXJS_PerIsolateData::Get(pIsolate) + ->m_pDynamicObjsMap->set(pPerObjData, obj); + } return obj; } diff --git a/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp b/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp index 316cc10196..8fce27b7c3 100644 --- a/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp +++ b/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp @@ -15,6 +15,9 @@ class FXJSV8EmbedderTest : public JSEmbedderTest {}; TEST_F(FXJSV8EmbedderTest, Getters) { v8::Isolate::Scope isolate_scope(isolate()); +#ifdef PDF_ENABLE_XFA + v8::Locker locker(isolate()); +#endif // PDF_ENABLE_XFA v8::HandleScope handle_scope(isolate()); v8::Context::Scope context_scope(GetV8Context()); diff --git a/fpdfsdk/src/pdfwindow/PWL_ComboBox.cpp b/fpdfsdk/src/pdfwindow/PWL_ComboBox.cpp index f695351bc4..7582ae412b 100644 --- a/fpdfsdk/src/pdfwindow/PWL_ComboBox.cpp +++ b/fpdfsdk/src/pdfwindow/PWL_ComboBox.cpp @@ -466,6 +466,12 @@ void CPWL_ComboBox::SetPopup(FX_BOOL bPopup) { if (bPopup) { if (m_pFillerNotify) { +#ifdef PDF_ENABLE_XFA + FX_BOOL bExit = FALSE; + m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, 0); + if (bExit) + return; +#endif // PDF_ENABLE_XFA int32_t nWhere = 0; FX_FLOAT fPopupRet = 0.0f; FX_FLOAT fPopupMin = 0.0f; @@ -493,6 +499,12 @@ void CPWL_ComboBox::SetPopup(FX_BOOL bPopup) { m_nPopupWhere = nWhere; Move(rcWindow, TRUE, TRUE); +#ifdef PDF_ENABLE_XFA + bExit = FALSE; + m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, 0); + if (bExit) + return; +#endif // PDF_ENABLE_XFA } } } else { @@ -513,6 +525,17 @@ FX_BOOL CPWL_ComboBox::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag) { case FWL_VKEY_Up: if (m_pList->GetCurSel() > 0) { FX_BOOL bExit = FALSE; +#ifdef PDF_ENABLE_XFA + if (m_pFillerNotify) { + m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag); + if (bExit) + return FALSE; + bExit = FALSE; + m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag); + if (bExit) + return FALSE; + } +#endif // PDF_ENABLE_XFA if (m_pList->OnKeyDownWithExit(nChar, bExit, nFlag)) { if (bExit) return FALSE; @@ -523,6 +546,17 @@ FX_BOOL CPWL_ComboBox::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag) { case FWL_VKEY_Down: if (m_pList->GetCurSel() < m_pList->GetCount() - 1) { FX_BOOL bExit = FALSE; +#ifdef PDF_ENABLE_XFA + if (m_pFillerNotify) { + m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag); + if (bExit) + return FALSE; + bExit = FALSE; + m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag); + if (bExit) + return FALSE; + } +#endif // PDF_ENABLE_XFA if (m_pList->OnKeyDownWithExit(nChar, bExit, nFlag)) { if (bExit) return FALSE; @@ -550,6 +584,17 @@ FX_BOOL CPWL_ComboBox::OnChar(FX_WORD nChar, FX_DWORD nFlag) { return m_pEdit->OnChar(nChar, nFlag); FX_BOOL bExit = FALSE; +#ifdef PDF_ENABLE_XFA + if (m_pFillerNotify) { + m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag); + if (bExit) + return FALSE; + + m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag); + if (bExit) + return FALSE; + } +#endif // PDF_ENABLE_XFA return m_pList->OnCharWithExit(nChar, bExit, nFlag) ? bExit : FALSE; } |