// Copyright 2016 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/cpdfsdk_widget.h" #include <memory> #include <sstream> #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_reference.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_string.h" #include "core/fpdfdoc/cpdf_defaultappearance.h" #include "core/fpdfdoc/cpdf_formcontrol.h" #include "core/fpdfdoc/cpdf_formfield.h" #include "core/fpdfdoc/cpdf_iconfit.h" #include "core/fpdfdoc/cpdf_interform.h" #include "core/fxge/cfx_graphstatedata.h" #include "core/fxge/cfx_pathdata.h" #include "core/fxge/cfx_renderdevice.h" #include "fpdfsdk/cpdfsdk_formfillenvironment.h" #include "fpdfsdk/cpdfsdk_interform.h" #include "fpdfsdk/cpdfsdk_pageview.h" #include "fpdfsdk/formfiller/cba_fontmap.h" #include "fpdfsdk/fsdk_actionhandler.h" #include "fpdfsdk/fsdk_define.h" #include "fpdfsdk/pwl/cpwl_appstream.h" #include "fpdfsdk/pwl/cpwl_edit.h" #ifdef PDF_ENABLE_XFA #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" #include "xfa/fxfa/cxfa_eventparam.h" #include "xfa/fxfa/cxfa_ffdocview.h" #include "xfa/fxfa/cxfa_ffwidget.h" #include "xfa/fxfa/cxfa_ffwidgethandler.h" #include "xfa/fxfa/cxfa_widgetacc.h" #endif // PDF_ENABLE_XFA namespace { // Convert a FX_ARGB to a FX_COLORREF. FX_COLORREF ARGBToColorRef(FX_ARGB argb) { return (((static_cast<uint32_t>(argb) & 0x00FF0000) >> 16) | (static_cast<uint32_t>(argb) & 0x0000FF00) | ((static_cast<uint32_t>(argb) & 0x000000FF) << 16)); } } // namespace CPDFSDK_Widget::CPDFSDK_Widget(CPDF_Annot* pAnnot, CPDFSDK_PageView* pPageView, CPDFSDK_InterForm* pInterForm) : CPDFSDK_BAAnnot(pAnnot, pPageView), m_pInterForm(pInterForm), m_nAppAge(0), m_nValueAge(0) #ifdef PDF_ENABLE_XFA , m_hMixXFAWidget(nullptr), m_pWidgetHandler(nullptr) #endif // PDF_ENABLE_XFA { } CPDFSDK_Widget::~CPDFSDK_Widget() {} #ifdef PDF_ENABLE_XFA CXFA_FFWidget* CPDFSDK_Widget::GetMixXFAWidget() const { CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext(); if (pContext->GetDocType() == XFA_DocType::Static) { if (!m_hMixXFAWidget) { if (CXFA_FFDocView* pDocView = pContext->GetXFADocView()) { CFX_WideString sName; if (GetFieldType() == FIELDTYPE_RADIOBUTTON) { sName = GetAnnotName(); if (sName.IsEmpty()) sName = GetName(); } else { sName = GetName(); } if (!sName.IsEmpty()) m_hMixXFAWidget = pDocView->GetWidgetByName(sName, nullptr); } } return m_hMixXFAWidget.Get(); } return nullptr; } CXFA_FFWidget* CPDFSDK_Widget::GetGroupMixXFAWidget() { CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext(); if (pContext->GetDocType() != XFA_DocType::Static) return nullptr; CXFA_FFDocView* pDocView = pContext->GetXFADocView(); if (!pDocView) return nullptr; CFX_WideString sName = GetName(); return !sName.IsEmpty() ? pDocView->GetWidgetByName(sName, nullptr) : nullptr; } CXFA_FFWidgetHandler* CPDFSDK_Widget::GetXFAWidgetHandler() const { CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext(); if (pContext->GetDocType() != XFA_DocType::Static) return nullptr; if (!m_pWidgetHandler) { CXFA_FFDocView* pDocView = pContext->GetXFADocView(); if (pDocView) m_pWidgetHandler = pDocView->GetWidgetHandler(); } return m_pWidgetHandler.Get(); } 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, 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; } bool CPDFSDK_Widget::HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT) { CXFA_FFWidget* hWidget = GetMixXFAWidget(); if (!hWidget) return false; CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler(); if (!pXFAWidgetHandler) return false; XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT); CXFA_WidgetAcc* pAcc; if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) && GetFieldType() == FIELDTYPE_RADIOBUTTON) { if (CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget()) { pAcc = hGroupWidget->GetDataAcc(); if (pXFAWidgetHandler->HasEvent(pAcc, eEventType)) return true; } } pAcc = hWidget->GetDataAcc(); return pXFAWidgetHandler->HasEvent(pAcc, eEventType); } bool CPDFSDK_Widget::OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT, PDFSDK_FieldAction& data, CPDFSDK_PageView* pPageView) { CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext(); CXFA_FFWidget* hWidget = GetMixXFAWidget(); if (!hWidget) return false; XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT); if (eEventType == XFA_EVENT_Unknown) return false; CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler(); if (!pXFAWidgetHandler) return false; 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 (const auto& c : data.sChange) param.m_wsNewText.Insert(data.nSelStart, c); param.m_wsPrevText = data.sValue; if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) && GetFieldType() == FIELDTYPE_RADIOBUTTON) { if (CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget()) { CXFA_WidgetAcc* pAcc = hGroupWidget->GetDataAcc(); param.m_pTarget = pAcc; if (pXFAWidgetHandler->ProcessEvent(pAcc, ¶m) != XFA_EVENTERROR_Success) { return false; } } } CXFA_WidgetAcc* pAcc = hWidget->GetDataAcc(); param.m_pTarget = pAcc; int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, ¶m); if (CXFA_FFDocView* pDocView = pContext->GetXFADocView()) pDocView->UpdateDocView(); return nRet == XFA_EVENTERROR_Success; } void CPDFSDK_Widget::Synchronize(bool bSynchronizeElse) { CXFA_FFWidget* hWidget = GetMixXFAWidget(); if (!hWidget) return; CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc(); if (!pWidgetAcc) return; CPDF_FormField* pFormField = GetFormField(); switch (GetFieldType()) { case FIELDTYPE_CHECKBOX: case FIELDTYPE_RADIOBUTTON: { CPDF_FormControl* pFormCtrl = GetFormControl(); XFA_CHECKSTATE eCheckState = pFormCtrl->IsChecked() ? XFA_CHECKSTATE_On : XFA_CHECKSTATE_Off; pWidgetAcc->SetCheckState(eCheckState, true); 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(false)) pWidgetAcc->SetItemState(nIndex, true, false, false, true); } 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(false)) pWidgetAcc->SetItemState(nIndex, true, false, false, true); } pWidgetAcc->SetValue(pFormField->GetValue(), XFA_VALUEPICTURE_Edit); break; } } if (bSynchronizeElse) pWidgetAcc->ProcessValueChanged(); } void CPDFSDK_Widget::SynchronizeXFAValue() { CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext(); CXFA_FFDocView* pXFADocView = pContext->GetXFADocView(); if (!pXFADocView) return; if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) { if (GetXFAWidgetHandler()) { CPDFSDK_Widget::SynchronizeXFAValue(pXFADocView, hWidget, GetFormField(), GetFormControl()); } } } void CPDFSDK_Widget::SynchronizeXFAItems() { CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext(); CXFA_FFDocView* pXFADocView = pContext->GetXFADocView(); if (!pXFADocView) return; if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) { if (GetXFAWidgetHandler()) SynchronizeXFAItems(pXFADocView, hWidget, GetFormField(), nullptr); } } void CPDFSDK_Widget::SynchronizeXFAValue(CXFA_FFDocView* pXFADocView, CXFA_FFWidget* hWidget, CPDF_FormField* pFormField, CPDF_FormControl* pFormControl) { ASSERT(hWidget); ASSERT(pFormControl); switch (pFormField->GetFieldType()) { case FIELDTYPE_CHECKBOX: { if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { pFormField->CheckControl( pFormField->GetControlIndex(pFormControl), pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On, true); } break; } case FIELDTYPE_RADIOBUTTON: { // TODO(weili): Check whether we need to handle checkbox and radio // button differently, otherwise, merge these two cases. if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { pFormField->CheckControl( pFormField->GetControlIndex(pFormControl), pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On, true); } break; } case FIELDTYPE_TEXTFIELD: { if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { CFX_WideString sValue; pWidgetAcc->GetValue(sValue, XFA_VALUEPICTURE_Display); pFormField->SetValue(sValue, true); } break; } case FIELDTYPE_LISTBOX: { pFormField->ClearSelection(false); if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { 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 = hWidget->GetDataAcc()) { 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(CXFA_FFDocView* pXFADocView, CXFA_FFWidget* hWidget, CPDF_FormField* pFormField, CPDF_FormControl* pFormControl) { ASSERT(hWidget); switch (pFormField->GetFieldType()) { case FIELDTYPE_LISTBOX: { pFormField->ClearSelection(false); pFormField->ClearOptions(true); if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(false); i < sz; i++) { CFX_WideString swText; pWidgetAcc->GetChoiceListItem(swText, i, false); pFormField->InsertOption(swText, i, true); } } break; } case FIELDTYPE_COMBOBOX: { pFormField->ClearSelection(false); pFormField->ClearOptions(false); if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(false); i < sz; i++) { CFX_WideString swText; pWidgetAcc->GetChoiceListItem(swText, i, false); pFormField->InsertOption(swText, i, false); } } pFormField->SetValue(L"", true); break; } } } #endif // PDF_ENABLE_XFA bool CPDFSDK_Widget::IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode) { CPDF_Dictionary* pAP = m_pAnnot->GetAnnotDict()->GetDictFor("AP"); if (!pAP) return false; // Choose the right sub-ap const char* ap_entry = "N"; if (mode == CPDF_Annot::Down) ap_entry = "D"; else if (mode == CPDF_Annot::Rollover) ap_entry = "R"; if (!pAP->KeyExist(ap_entry)) ap_entry = "N"; // Get the AP stream or subdirectory CPDF_Object* psub = pAP->GetDirectObjectFor(ap_entry); if (!psub) return false; int nFieldType = GetFieldType(); switch (nFieldType) { case FIELDTYPE_PUSHBUTTON: case FIELDTYPE_COMBOBOX: case FIELDTYPE_LISTBOX: case FIELDTYPE_TEXTFIELD: case FIELDTYPE_SIGNATURE: return psub->IsStream(); case FIELDTYPE_CHECKBOX: case FIELDTYPE_RADIOBUTTON: if (CPDF_Dictionary* pSubDict = psub->AsDictionary()) { return !!pSubDict->GetStreamFor(GetAppState()); } return false; } return true; } int CPDFSDK_Widget::GetFieldType() const { CPDF_FormField* pField = GetFormField(); return pField ? pField->GetFieldType() : FIELDTYPE_UNKNOWN; } bool CPDFSDK_Widget::IsAppearanceValid() { #ifdef PDF_ENABLE_XFA CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext(); XFA_DocType nDocType = pContext->GetDocType(); if (nDocType != XFA_DocType::PDF && nDocType != XFA_DocType::Static) return true; #endif // PDF_ENABLE_XFA return CPDFSDK_BAAnnot::IsAppearanceValid(); } int CPDFSDK_Widget::GetLayoutOrder() const { return 2; } int CPDFSDK_Widget::GetFieldFlags() const { CPDF_InterForm* pPDFInterForm = m_pInterForm->GetInterForm(); CPDF_FormControl* pFormControl = pPDFInterForm->GetControlByDict(m_pAnnot->GetAnnotDict()); CPDF_FormField* pFormField = pFormControl->GetField(); return pFormField->GetFieldFlags(); } bool CPDFSDK_Widget::IsSignatureWidget() const { return GetFieldType() == FIELDTYPE_SIGNATURE; } CPDF_FormField* CPDFSDK_Widget::GetFormField() const { CPDF_FormControl* pControl = GetFormControl(); return pControl ? pControl->GetField() : nullptr; } CPDF_FormControl* CPDFSDK_Widget::GetFormControl() const { CPDF_InterForm* pPDFInterForm = m_pInterForm->GetInterForm(); return pPDFInterForm->GetControlByDict(GetAnnotDict()); } CPDF_FormControl* CPDFSDK_Widget::GetFormControl( CPDF_InterForm* pInterForm, const CPDF_Dictionary* pAnnotDict) { ASSERT(pAnnotDict); return pInterForm->GetControlByDict(pAnnotDict); } int CPDFSDK_Widget::GetRotate() const { CPDF_FormControl* pCtrl = GetFormControl(); 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 bool CPDFSDK_Widget::GetFillColor(FX_COLORREF& color) const { CPDF_FormControl* pFormCtrl = GetFormControl(); int iColorType = 0; color = ARGBToColorRef(pFormCtrl->GetBackgroundColor(iColorType)); return iColorType != COLORTYPE_TRANSPARENT; } bool CPDFSDK_Widget::GetBorderColor(FX_COLORREF& color) const { CPDF_FormControl* pFormCtrl = GetFormControl(); int iColorType = 0; color = ARGBToColorRef(pFormCtrl->GetBorderColor(iColorType)); return iColorType != COLORTYPE_TRANSPARENT; } bool CPDFSDK_Widget::GetTextColor(FX_COLORREF& color) const { CPDF_FormControl* pFormCtrl = GetFormControl(); CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance(); if (!da.HasColor()) return false; FX_ARGB argb; int iColorType = COLORTYPE_TRANSPARENT; da.GetColor(argb, iColorType); color = ARGBToColorRef(argb); return iColorType != COLORTYPE_TRANSPARENT; } float CPDFSDK_Widget::GetFontSize() const { CPDF_FormControl* pFormCtrl = GetFormControl(); CPDF_DefaultAppearance pDa = pFormCtrl->GetDefaultAppearance(); float fFontSize; pDa.GetFont(&fFontSize); return fFontSize; } int CPDFSDK_Widget::GetSelectedIndex(int nIndex) const { #ifdef PDF_ENABLE_XFA if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) { if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { 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(bool bDisplay) const { if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) { if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { 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(); } CFX_WideString CPDFSDK_Widget::GetDefaultValue() const { CPDF_FormField* pFormField = GetFormField(); return pFormField->GetDefaultValue(); } CFX_WideString CPDFSDK_Widget::GetOptionLabel(int nIndex) const { CPDF_FormField* pFormField = GetFormField(); return pFormField->GetOptionLabel(nIndex); } int CPDFSDK_Widget::CountOptions() const { CPDF_FormField* pFormField = GetFormField(); return pFormField->CountOptions(); } bool CPDFSDK_Widget::IsOptionSelected(int nIndex) const { #ifdef PDF_ENABLE_XFA if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) { if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems(false)) return pWidgetAcc->GetItemState(nIndex); return false; } } #endif // PDF_ENABLE_XFA CPDF_FormField* pFormField = GetFormField(); return pFormField->IsItemSelected(nIndex); } int CPDFSDK_Widget::GetTopVisibleIndex() const { CPDF_FormField* pFormField = GetFormField(); return pFormField->GetTopVisibleIndex(); } bool CPDFSDK_Widget::IsChecked() const { #ifdef PDF_ENABLE_XFA if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) { if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) return pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On; } #endif // PDF_ENABLE_XFA CPDF_FormControl* pFormCtrl = GetFormControl(); return pFormCtrl->IsChecked(); } int CPDFSDK_Widget::GetAlignment() const { CPDF_FormControl* pFormCtrl = GetFormControl(); return pFormCtrl->GetControlAlignment(); } int CPDFSDK_Widget::GetMaxLen() const { CPDF_FormField* pFormField = GetFormField(); return pFormField->GetMaxLen(); } void CPDFSDK_Widget::SetCheck(bool bChecked, bool bNotify) { CPDF_FormControl* pFormCtrl = GetFormControl(); 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, 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) {} void CPDFSDK_Widget::SetOptionSelection(int index, bool bSelected, 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(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) {} void CPDFSDK_Widget::SetAppModified() { m_bAppModified = true; } void CPDFSDK_Widget::ClearAppModified() { m_bAppModified = false; } bool CPDFSDK_Widget::IsAppModified() const { return m_bAppModified; } #ifdef PDF_ENABLE_XFA void CPDFSDK_Widget::ResetAppearance(bool bValueChanged) { switch (GetFieldType()) { case FIELDTYPE_TEXTFIELD: case FIELDTYPE_COMBOBOX: { bool bFormatted = false; CFX_WideString sValue = OnFormat(bFormatted); ResetAppearance(bFormatted ? &sValue : nullptr, true); break; } default: ResetAppearance(nullptr, false); break; } } #endif // PDF_ENABLE_XFA void CPDFSDK_Widget::ResetAppearance(const CFX_WideString* sValue, bool bValueChanged) { SetAppModified(); m_nAppAge++; if (m_nAppAge > 999999) m_nAppAge = 0; if (bValueChanged) m_nValueAge++; CPWL_AppStream appStream(this, GetAPDict()); switch (GetFieldType()) { case FIELDTYPE_PUSHBUTTON: appStream.SetAsPushButton(); break; case FIELDTYPE_CHECKBOX: appStream.SetAsCheckBox(); break; case FIELDTYPE_RADIOBUTTON: appStream.SetAsRadioButton(); break; case FIELDTYPE_COMBOBOX: appStream.SetAsComboBox(sValue); break; case FIELDTYPE_LISTBOX: appStream.SetAsListBox(); break; case FIELDTYPE_TEXTFIELD: appStream.SetAsTextField(sValue); break; } m_pAnnot->ClearCachedAP(); } CFX_WideString CPDFSDK_Widget::OnFormat(bool& bFormatted) { CPDF_FormField* pFormField = GetFormField(); ASSERT(pFormField); return m_pInterForm->OnFormat(pFormField, bFormatted); } void CPDFSDK_Widget::ResetFieldAppearance(bool bValueChanged) { CPDF_FormField* pFormField = GetFormField(); ASSERT(pFormField); m_pInterForm->ResetFieldAppearance(pFormField, nullptr, bValueChanged); } void CPDFSDK_Widget::DrawAppearance(CFX_RenderDevice* pDevice, const CFX_Matrix* pUser2Device, CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions) { int nFieldType = GetFieldType(); if ((nFieldType == FIELDTYPE_CHECKBOX || nFieldType == FIELDTYPE_RADIOBUTTON) && mode == CPDF_Annot::Normal && !IsWidgetAppearanceValid(CPDF_Annot::Normal)) { CFX_PathData pathData; CFX_FloatRect rcAnnot = GetRect(); pathData.AppendRect(rcAnnot.left, rcAnnot.bottom, rcAnnot.right, rcAnnot.top); CFX_GraphStateData gsd; gsd.m_LineWidth = 0.0f; pDevice->DrawPath(&pathData, pUser2Device, &gsd, 0, 0xFFAAAAAA, FXFILL_ALTERNATE); } else { CPDFSDK_BAAnnot::DrawAppearance(pDevice, pUser2Device, mode, pOptions); } } void CPDFSDK_Widget::UpdateField() { CPDF_FormField* pFormField = GetFormField(); ASSERT(pFormField); m_pInterForm->UpdateField(pFormField); } void CPDFSDK_Widget::DrawShadow(CFX_RenderDevice* pDevice, CPDFSDK_PageView* pPageView) { int nFieldType = GetFieldType(); if (!m_pInterForm->IsNeedHighLight(nFieldType)) return; CFX_Matrix page2device; pPageView->GetCurrentMatrix(page2device); CFX_FloatRect rcDevice = GetRect(); CFX_PointF tmp = page2device.Transform(CFX_PointF(rcDevice.left, rcDevice.bottom)); rcDevice.left = tmp.x; rcDevice.bottom = tmp.y; tmp = page2device.Transform(CFX_PointF(rcDevice.right, rcDevice.top)); rcDevice.right = tmp.x; rcDevice.top = tmp.y; rcDevice.Normalize(); FX_RECT rcDev = rcDevice.ToFxRect(); pDevice->FillRect( &rcDev, ArgbEncode(static_cast<int>(m_pInterForm->GetHighlightAlpha()), m_pInterForm->GetHighlightColor(nFieldType))); } CFX_FloatRect CPDFSDK_Widget::GetClientRect() const { CFX_FloatRect rcWindow = GetRotatedRect(); float fBorderWidth = (float)GetBorderWidth(); switch (GetBorderStyle()) { case BorderStyle::BEVELED: case BorderStyle::INSET: fBorderWidth *= 2.0f; break; default: break; } return rcWindow.GetDeflated(fBorderWidth, fBorderWidth); } CFX_FloatRect CPDFSDK_Widget::GetRotatedRect() const { CFX_FloatRect rectAnnot = GetRect(); float fWidth = rectAnnot.right - rectAnnot.left; float fHeight = rectAnnot.top - rectAnnot.bottom; CPDF_FormControl* pControl = GetFormControl(); CFX_FloatRect rcPDFWindow; switch (abs(pControl->GetRotation() % 360)) { case 0: case 180: default: rcPDFWindow = CFX_FloatRect(0, 0, fWidth, fHeight); break; case 90: case 270: rcPDFWindow = CFX_FloatRect(0, 0, fHeight, fWidth); break; } return rcPDFWindow; } CFX_Matrix CPDFSDK_Widget::GetMatrix() const { CFX_Matrix mt; CPDF_FormControl* pControl = GetFormControl(); CFX_FloatRect rcAnnot = GetRect(); float fWidth = rcAnnot.right - rcAnnot.left; float fHeight = rcAnnot.top - rcAnnot.bottom; switch (abs(pControl->GetRotation() % 360)) { default: case 0: break; case 90: mt = CFX_Matrix(0, 1, -1, 0, fWidth, 0); break; case 180: mt = CFX_Matrix(-1, 0, 0, -1, fWidth, fHeight); break; case 270: mt = CFX_Matrix(0, -1, 1, 0, 0, fHeight); break; } return mt; } CFX_Color CPDFSDK_Widget::GetTextPWLColor() const { CFX_Color crText = CFX_Color(COLORTYPE_GRAY, 0); CPDF_FormControl* pFormCtrl = GetFormControl(); CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance(); if (da.HasColor()) { int32_t iColorType; float fc[4]; da.GetColor(iColorType, fc); crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); } return crText; } CFX_Color CPDFSDK_Widget::GetBorderPWLColor() const { CFX_Color crBorder; CPDF_FormControl* pFormCtrl = GetFormControl(); int32_t iColorType; float fc[4]; pFormCtrl->GetOriginalBorderColor(iColorType, fc); if (iColorType > 0) crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); return crBorder; } CFX_Color CPDFSDK_Widget::GetFillPWLColor() const { CFX_Color crFill; CPDF_FormControl* pFormCtrl = GetFormControl(); int32_t iColorType; float fc[4]; pFormCtrl->GetOriginalBackgroundColor(iColorType, fc); if (iColorType > 0) crFill = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); return crFill; } bool CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type, PDFSDK_FieldAction& data, CPDFSDK_PageView* pPageView) { CPDFSDK_FormFillEnvironment* pFormFillEnv = pPageView->GetFormFillEnv(); #ifdef PDF_ENABLE_XFA CPDFXFA_Context* pContext = pFormFillEnv->GetXFAContext(); if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) { XFA_EVENTTYPE eEventType = GetXFAEventType(type, data.bWillCommit); if (eEventType != XFA_EVENT_Unknown) { if (CXFA_FFWidgetHandler* 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 = hWidget->GetDataAcc(); param.m_pTarget = pAcc; int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, ¶m); if (CXFA_FFDocView* pDocView = pContext->GetXFADocView()) pDocView->UpdateDocView(); if (nRet == XFA_EVENTERROR_Success) return true; } } } #endif // PDF_ENABLE_XFA CPDF_Action action = GetAAction(type); if (action.GetDict() && action.GetType() != CPDF_Action::Unknown) { CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHandler(); return pActionHandler->DoAction_Field(action, type, pFormFillEnv, GetFormField(), data); } return false; } CPDF_Action CPDFSDK_Widget::GetAAction(CPDF_AAction::AActionType eAAT) { switch (eAAT) { case CPDF_AAction::CursorEnter: case CPDF_AAction::CursorExit: case CPDF_AAction::ButtonDown: case CPDF_AAction::ButtonUp: case CPDF_AAction::GetFocus: case CPDF_AAction::LoseFocus: case CPDF_AAction::PageOpen: case CPDF_AAction::PageClose: case CPDF_AAction::PageVisible: case CPDF_AAction::PageInvisible: return CPDFSDK_BAAnnot::GetAAction(eAAT); case CPDF_AAction::KeyStroke: case CPDF_AAction::Format: case CPDF_AAction::Validate: case CPDF_AAction::Calculate: { CPDF_FormField* pField = GetFormField(); if (pField->GetAdditionalAction().GetDict()) return pField->GetAdditionalAction().GetAction(eAAT); return CPDFSDK_BAAnnot::GetAAction(eAAT); } default: break; } return CPDF_Action(); } CFX_WideString CPDFSDK_Widget::GetAlternateName() const { CPDF_FormField* pFormField = GetFormField(); return pFormField->GetAlternateName(); } int32_t CPDFSDK_Widget::GetAppearanceAge() const { return m_nAppAge; } int32_t CPDFSDK_Widget::GetValueAge() const { return m_nValueAge; }