diff options
author | Dan Sinclair <dsinclair@chromium.org> | 2017-03-23 12:11:20 -0400 |
---|---|---|
committer | Chromium commit bot <commit-bot@chromium.org> | 2017-03-23 17:37:55 +0000 |
commit | 80c487809858b74783a00e05cc8164edf4b1307c (patch) | |
tree | 6aecc491645c428fb298f21b54ef80864a7dd331 /xfa/fxfa/cxfa_widgetacc.cpp | |
parent | 6bdd824188bc9a2e6b24b5752a3170ce10185c1d (diff) | |
download | pdfium-80c487809858b74783a00e05cc8164edf4b1307c.tar.xz |
Cleanup some xfa/fxfa code.
This CL moves the .h files to have names corresponding to the contained
classes. The .cpp files are moved alongside the .h files. Any extra
classes in the .h files have been split into their own files.
Change-Id: I14b4efc02417f0df946500e87b6c502e77020db8
Reviewed-on: https://pdfium-review.googlesource.com/3160
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Nicolás Peña <npm@chromium.org>
Commit-Queue: dsinclair <dsinclair@chromium.org>
Diffstat (limited to 'xfa/fxfa/cxfa_widgetacc.cpp')
-rw-r--r-- | xfa/fxfa/cxfa_widgetacc.cpp | 1549 |
1 files changed, 1549 insertions, 0 deletions
diff --git a/xfa/fxfa/cxfa_widgetacc.cpp b/xfa/fxfa/cxfa_widgetacc.cpp new file mode 100644 index 0000000000..4c8e37291a --- /dev/null +++ b/xfa/fxfa/cxfa_widgetacc.cpp @@ -0,0 +1,1549 @@ +// Copyright 2017 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 "xfa/fxfa/cxfa_widgetacc.h" + +#include <algorithm> +#include <vector> + +#include "third_party/base/stl_util.h" +#include "xfa/fde/tto/fde_textout.h" +#include "xfa/fde/xml/fde_xml_imp.h" +#include "xfa/fxfa/app/cxfa_textlayout.h" +#include "xfa/fxfa/app/xfa_ffwidgetacc.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_fontmgr.h" +#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_scriptcontext.h" +#include "xfa/fxfa/parser/xfa_localevalue.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +class CXFA_WidgetLayoutData { + public: + CXFA_WidgetLayoutData() : m_fWidgetHeight(-1) {} + virtual ~CXFA_WidgetLayoutData() {} + + float m_fWidgetHeight; +}; + +namespace { + +void FFDeleteCalcData(void* pData) { + if (pData) + delete ((CXFA_CalcData*)pData); +} + +static XFA_MAPDATABLOCKCALLBACKINFO gs_XFADeleteCalcData = {FFDeleteCalcData, + nullptr}; + +class CXFA_TextLayoutData : public CXFA_WidgetLayoutData { + public: + CXFA_TextLayoutData() {} + ~CXFA_TextLayoutData() override {} + + CXFA_TextLayout* GetTextLayout() const { return m_pTextLayout.get(); } + CXFA_TextProvider* GetTextProvider() const { return m_pTextProvider.get(); } + + void LoadText(CXFA_WidgetAcc* pAcc) { + if (m_pTextLayout) + return; + + m_pTextProvider = + pdfium::MakeUnique<CXFA_TextProvider>(pAcc, XFA_TEXTPROVIDERTYPE_Text); + m_pTextLayout = pdfium::MakeUnique<CXFA_TextLayout>(m_pTextProvider.get()); + } + + private: + std::unique_ptr<CXFA_TextLayout> m_pTextLayout; + std::unique_ptr<CXFA_TextProvider> m_pTextProvider; +}; + +class CXFA_ImageLayoutData : public CXFA_WidgetLayoutData { + public: + CXFA_ImageLayoutData() + : m_pDIBitmap(nullptr), + m_bNamedImage(false), + m_iImageXDpi(0), + m_iImageYDpi(0) {} + + ~CXFA_ImageLayoutData() override { + if (m_pDIBitmap && !m_bNamedImage) + delete m_pDIBitmap; + } + + bool LoadImageData(CXFA_WidgetAcc* pAcc) { + if (m_pDIBitmap) + return true; + + CXFA_Value value = pAcc->GetFormValue(); + if (!value) + return false; + + CXFA_Image imageObj = value.GetImage(); + if (!imageObj) + return false; + + CXFA_FFDoc* pFFDoc = pAcc->GetDoc(); + pAcc->SetImageImage(XFA_LoadImageData(pFFDoc, &imageObj, m_bNamedImage, + m_iImageXDpi, m_iImageYDpi)); + return !!m_pDIBitmap; + } + + CFX_DIBitmap* m_pDIBitmap; + bool m_bNamedImage; + int32_t m_iImageXDpi; + int32_t m_iImageYDpi; +}; + +class CXFA_FieldLayoutData : public CXFA_WidgetLayoutData { + public: + CXFA_FieldLayoutData() {} + ~CXFA_FieldLayoutData() override {} + + bool LoadCaption(CXFA_WidgetAcc* pAcc) { + if (m_pCapTextLayout) + return true; + CXFA_Caption caption = pAcc->GetCaption(); + if (!caption || caption.GetPresence() == XFA_ATTRIBUTEENUM_Hidden) + return false; + m_pCapTextProvider.reset( + new CXFA_TextProvider(pAcc, XFA_TEXTPROVIDERTYPE_Caption)); + m_pCapTextLayout = + pdfium::MakeUnique<CXFA_TextLayout>(m_pCapTextProvider.get()); + return true; + } + + std::unique_ptr<CXFA_TextLayout> m_pCapTextLayout; + std::unique_ptr<CXFA_TextProvider> m_pCapTextProvider; + std::unique_ptr<CFDE_TextOut> m_pTextOut; + std::vector<float> m_FieldSplitArray; +}; + +class CXFA_TextEditData : public CXFA_FieldLayoutData { + public: +}; + +class CXFA_ImageEditData : public CXFA_FieldLayoutData { + public: + CXFA_ImageEditData() + : m_pDIBitmap(nullptr), + m_bNamedImage(false), + m_iImageXDpi(0), + m_iImageYDpi(0) {} + + ~CXFA_ImageEditData() override { + if (m_pDIBitmap && !m_bNamedImage) + delete m_pDIBitmap; + } + + bool LoadImageData(CXFA_WidgetAcc* pAcc) { + if (m_pDIBitmap) + return true; + + CXFA_Value value = pAcc->GetFormValue(); + if (!value) + return false; + + CXFA_Image imageObj = value.GetImage(); + CXFA_FFDoc* pFFDoc = pAcc->GetDoc(); + pAcc->SetImageEditImage(XFA_LoadImageData(pFFDoc, &imageObj, m_bNamedImage, + m_iImageXDpi, m_iImageYDpi)); + return !!m_pDIBitmap; + } + + CFX_DIBitmap* m_pDIBitmap; + bool m_bNamedImage; + int32_t m_iImageXDpi; + int32_t m_iImageYDpi; +}; + +} // namespace + +CXFA_WidgetAcc::CXFA_WidgetAcc(CXFA_FFDocView* pDocView, CXFA_Node* pNode) + : CXFA_WidgetData(pNode), m_pDocView(pDocView), m_nRecursionDepth(0) {} + +CXFA_WidgetAcc::~CXFA_WidgetAcc() {} + +bool CXFA_WidgetAcc::GetName(CFX_WideString& wsName, int32_t iNameType) { + if (iNameType == 0) { + m_pNode->TryCData(XFA_ATTRIBUTE_Name, wsName); + return !wsName.IsEmpty(); + } + m_pNode->GetSOMExpression(wsName); + if (iNameType == 2 && wsName.GetLength() >= 15) { + CFX_WideStringC wsPre = L"xfa[0].form[0]."; + if (wsPre == CFX_WideStringC(wsName.c_str(), wsPre.GetLength())) + wsName.Delete(0, wsPre.GetLength()); + } + return true; +} + +CXFA_Node* CXFA_WidgetAcc::GetDatasets() { + return m_pNode->GetBindData(); +} + +bool CXFA_WidgetAcc::ProcessValueChanged() { + m_pDocView->AddValidateWidget(this); + m_pDocView->AddCalculateWidgetAcc(this); + m_pDocView->RunCalculateWidgets(); + m_pDocView->RunValidate(); + return true; +} + +void CXFA_WidgetAcc::ResetData() { + CFX_WideString wsValue; + XFA_Element eUIType = GetUIType(); + switch (eUIType) { + case XFA_Element::ImageEdit: { + CXFA_Value imageValue = GetDefaultValue(); + CXFA_Image image = imageValue.GetImage(); + CFX_WideString wsContentType, wsHref; + if (image) { + image.GetContent(wsValue); + image.GetContentType(wsContentType); + image.GetHref(wsHref); + } + SetImageEdit(wsContentType, wsHref, wsValue); + break; + } + case XFA_Element::ExclGroup: { + CXFA_Node* pNextChild = m_pNode->GetNodeItem( + XFA_NODEITEM_FirstChild, XFA_ObjectType::ContainerNode); + while (pNextChild) { + CXFA_Node* pChild = pNextChild; + CXFA_WidgetAcc* pAcc = + static_cast<CXFA_WidgetAcc*>(pChild->GetWidgetData()); + if (!pAcc) + continue; + + CXFA_Value defValue(nullptr); + if (wsValue.IsEmpty() && (defValue = pAcc->GetDefaultValue())) { + defValue.GetChildValueContent(wsValue); + SetValue(wsValue, XFA_VALUEPICTURE_Raw); + pAcc->SetValue(wsValue, XFA_VALUEPICTURE_Raw); + } else { + CXFA_Node* pItems = pChild->GetChild(0, XFA_Element::Items); + if (!pItems) + continue; + + CFX_WideString itemText; + if (pItems->CountChildren(XFA_Element::Unknown) > 1) + itemText = pItems->GetChild(1, XFA_Element::Unknown)->GetContent(); + + pAcc->SetValue(itemText, XFA_VALUEPICTURE_Raw); + } + pNextChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling, + XFA_ObjectType::ContainerNode); + } + break; + } + case XFA_Element::ChoiceList: + ClearAllSelections(); + default: + if (CXFA_Value defValue = GetDefaultValue()) + defValue.GetChildValueContent(wsValue); + + SetValue(wsValue, XFA_VALUEPICTURE_Raw); + break; + } +} + +void CXFA_WidgetAcc::SetImageEdit(const CFX_WideString& wsContentType, + const CFX_WideString& wsHref, + const CFX_WideString& wsData) { + CXFA_Image image = GetFormValue().GetImage(); + if (image) { + image.SetContentType(CFX_WideString(wsContentType)); + image.SetHref(wsHref); + } + CFX_WideString wsFormatValue(wsData); + GetFormatDataValue(wsData, wsFormatValue); + m_pNode->SetContent(wsData, wsFormatValue, true); + CXFA_Node* pBind = GetDatasets(); + if (!pBind) { + image.SetTransferEncoding(XFA_ATTRIBUTEENUM_Base64); + return; + } + pBind->SetCData(XFA_ATTRIBUTE_ContentType, wsContentType); + CXFA_Node* pHrefNode = pBind->GetNodeItem(XFA_NODEITEM_FirstChild); + if (pHrefNode) { + pHrefNode->SetCData(XFA_ATTRIBUTE_Value, wsHref); + } else { + CFDE_XMLNode* pXMLNode = pBind->GetXMLMappingNode(); + ASSERT(pXMLNode && pXMLNode->GetType() == FDE_XMLNODE_Element); + static_cast<CFDE_XMLElement*>(pXMLNode)->SetString(L"href", wsHref); + } +} + +CXFA_WidgetAcc* CXFA_WidgetAcc::GetExclGroup() { + CXFA_Node* pExcl = m_pNode->GetNodeItem(XFA_NODEITEM_Parent); + if (!pExcl || pExcl->GetElementType() != XFA_Element::ExclGroup) + return nullptr; + return static_cast<CXFA_WidgetAcc*>(pExcl->GetWidgetData()); +} + +CXFA_FFDocView* CXFA_WidgetAcc::GetDocView() { + return m_pDocView; +} + +CXFA_FFDoc* CXFA_WidgetAcc::GetDoc() { + return m_pDocView->GetDoc(); +} + +CXFA_FFApp* CXFA_WidgetAcc::GetApp() { + return GetDoc()->GetApp(); +} + +IXFA_AppProvider* CXFA_WidgetAcc::GetAppProvider() { + return GetApp()->GetAppProvider(); +} + +int32_t CXFA_WidgetAcc::ProcessEvent(int32_t iActivity, + CXFA_EventParam* pEventParam) { + if (GetElementType() == XFA_Element::Draw) + return XFA_EVENTERROR_NotExist; + + std::vector<CXFA_Node*> eventArray = + GetEventByActivity(iActivity, pEventParam->m_bIsFormReady); + bool first = true; + int32_t iRet = XFA_EVENTERROR_NotExist; + for (CXFA_Node* pNode : eventArray) { + int32_t result = ProcessEvent(CXFA_Event(pNode), pEventParam); + if (first || result == XFA_EVENTERROR_Success) + iRet = result; + first = false; + } + return iRet; +} + +int32_t CXFA_WidgetAcc::ProcessEvent(const CXFA_Event& event, + CXFA_EventParam* pEventParam) { + if (!event) + return XFA_EVENTERROR_NotExist; + + switch (event.GetEventType()) { + case XFA_Element::Execute: + break; + case XFA_Element::Script: + return ExecuteScript(event.GetScript(), pEventParam); + case XFA_Element::SignData: + break; + case XFA_Element::Submit: + return GetDoc()->GetDocEnvironment()->SubmitData(GetDoc(), + event.GetSubmit()); + default: + break; + } + return XFA_EVENTERROR_NotExist; +} + +int32_t CXFA_WidgetAcc::ProcessCalculate() { + if (GetElementType() == XFA_Element::Draw) + return XFA_EVENTERROR_NotExist; + + CXFA_Calculate calc = GetCalculate(); + if (!calc) + return XFA_EVENTERROR_NotExist; + if (GetNode()->IsUserInteractive()) + return XFA_EVENTERROR_Disabled; + + CXFA_EventParam EventParam; + EventParam.m_eType = XFA_EVENT_Calculate; + CXFA_Script script = calc.GetScript(); + int32_t iRet = ExecuteScript(script, &EventParam); + if (iRet != XFA_EVENTERROR_Success) + return iRet; + + if (GetRawValue() != EventParam.m_wsResult) { + SetValue(EventParam.m_wsResult, XFA_VALUEPICTURE_Raw); + UpdateUIDisplay(); + } + return XFA_EVENTERROR_Success; +} + +void CXFA_WidgetAcc::ProcessScriptTestValidate(CXFA_Validate validate, + int32_t iRet, + CFXJSE_Value* pRetValue, + bool bVersionFlag) { + if (iRet == XFA_EVENTERROR_Success && pRetValue) { + if (pRetValue->IsBoolean() && !pRetValue->ToBoolean()) { + IXFA_AppProvider* pAppProvider = GetAppProvider(); + if (!pAppProvider) { + return; + } + CFX_WideString wsTitle = pAppProvider->GetAppTitle(); + CFX_WideString wsScriptMsg; + validate.GetScriptMessageText(wsScriptMsg); + int32_t eScriptTest = validate.GetScriptTest(); + if (eScriptTest == XFA_ATTRIBUTEENUM_Warning) { + if (GetNode()->IsUserInteractive()) + return; + if (wsScriptMsg.IsEmpty()) + wsScriptMsg = GetValidateMessage(false, bVersionFlag); + + if (bVersionFlag) { + pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning, + XFA_MB_OK); + return; + } + if (pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning, + XFA_MB_YesNo) == XFA_IDYes) { + GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false); + } + } else { + if (wsScriptMsg.IsEmpty()) + wsScriptMsg = GetValidateMessage(true, bVersionFlag); + pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK); + } + } + } +} + +int32_t CXFA_WidgetAcc::ProcessFormatTestValidate(CXFA_Validate validate, + bool bVersionFlag) { + CFX_WideString wsRawValue = GetRawValue(); + if (!wsRawValue.IsEmpty()) { + CFX_WideString wsPicture; + validate.GetPicture(wsPicture); + if (wsPicture.IsEmpty()) + return XFA_EVENTERROR_NotExist; + + IFX_Locale* pLocale = GetLocal(); + if (!pLocale) + return XFA_EVENTERROR_NotExist; + + CXFA_LocaleValue lcValue = XFA_GetLocaleValue(this); + if (!lcValue.ValidateValue(lcValue.GetValue(), wsPicture, pLocale)) { + IXFA_AppProvider* pAppProvider = GetAppProvider(); + if (!pAppProvider) + return XFA_EVENTERROR_NotExist; + + CFX_WideString wsFormatMsg; + validate.GetFormatMessageText(wsFormatMsg); + CFX_WideString wsTitle = pAppProvider->GetAppTitle(); + int32_t eFormatTest = validate.GetFormatTest(); + if (eFormatTest == XFA_ATTRIBUTEENUM_Error) { + if (wsFormatMsg.IsEmpty()) + wsFormatMsg = GetValidateMessage(true, bVersionFlag); + pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK); + return XFA_EVENTERROR_Success; + } + if (GetNode()->IsUserInteractive()) + return XFA_EVENTERROR_NotExist; + if (wsFormatMsg.IsEmpty()) + wsFormatMsg = GetValidateMessage(false, bVersionFlag); + + if (bVersionFlag) { + pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning, + XFA_MB_OK); + return XFA_EVENTERROR_Success; + } + if (pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning, + XFA_MB_YesNo) == XFA_IDYes) { + GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false); + } + return XFA_EVENTERROR_Success; + } + } + return XFA_EVENTERROR_NotExist; +} + +int32_t CXFA_WidgetAcc::ProcessNullTestValidate(CXFA_Validate validate, + int32_t iFlags, + bool bVersionFlag) { + CFX_WideString wsValue; + GetValue(wsValue, XFA_VALUEPICTURE_Raw); + if (!wsValue.IsEmpty()) + return XFA_EVENTERROR_Success; + if (m_bIsNull && (m_bPreNull == m_bIsNull)) + return XFA_EVENTERROR_Success; + + int32_t eNullTest = validate.GetNullTest(); + CFX_WideString wsNullMsg; + validate.GetNullMessageText(wsNullMsg); + if (iFlags & 0x01) { + int32_t iRet = XFA_EVENTERROR_Success; + if (eNullTest != XFA_ATTRIBUTEENUM_Disabled) + iRet = XFA_EVENTERROR_Error; + + if (!wsNullMsg.IsEmpty()) { + if (eNullTest != XFA_ATTRIBUTEENUM_Disabled) { + m_pDocView->m_arrNullTestMsg.push_back(wsNullMsg); + return XFA_EVENTERROR_Error; + } + return XFA_EVENTERROR_Success; + } + return iRet; + } + if (wsNullMsg.IsEmpty() && bVersionFlag && + eNullTest != XFA_ATTRIBUTEENUM_Disabled) { + return XFA_EVENTERROR_Error; + } + IXFA_AppProvider* pAppProvider = GetAppProvider(); + if (!pAppProvider) + return XFA_EVENTERROR_NotExist; + + CFX_WideString wsCaptionName; + CFX_WideString wsTitle = pAppProvider->GetAppTitle(); + switch (eNullTest) { + case XFA_ATTRIBUTEENUM_Error: { + if (wsNullMsg.IsEmpty()) { + wsCaptionName = GetValidateCaptionName(bVersionFlag); + wsNullMsg.Format(L"%s cannot be blank.", wsCaptionName.c_str()); + } + pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Status, XFA_MB_OK); + return XFA_EVENTERROR_Error; + } + case XFA_ATTRIBUTEENUM_Warning: { + if (GetNode()->IsUserInteractive()) + return true; + + if (wsNullMsg.IsEmpty()) { + wsCaptionName = GetValidateCaptionName(bVersionFlag); + wsNullMsg.Format( + L"%s cannot be blank. To ignore validations for %s, click Ignore.", + wsCaptionName.c_str(), wsCaptionName.c_str()); + } + if (pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Warning, + XFA_MB_YesNo) == XFA_IDYes) { + GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false); + } + return XFA_EVENTERROR_Error; + } + case XFA_ATTRIBUTEENUM_Disabled: + default: + break; + } + return XFA_EVENTERROR_Success; +} + +CFX_WideString CXFA_WidgetAcc::GetValidateCaptionName(bool bVersionFlag) { + CFX_WideString wsCaptionName; + + if (!bVersionFlag) { + if (CXFA_Caption caption = GetCaption()) { + if (CXFA_Value capValue = caption.GetValue()) { + if (CXFA_Text capText = capValue.GetText()) + capText.GetContent(wsCaptionName); + } + } + } + if (wsCaptionName.IsEmpty()) + GetName(wsCaptionName); + + return wsCaptionName; +} + +CFX_WideString CXFA_WidgetAcc::GetValidateMessage(bool bError, + bool bVersionFlag) { + CFX_WideString wsCaptionName = GetValidateCaptionName(bVersionFlag); + CFX_WideString wsMessage; + if (bVersionFlag) { + wsMessage.Format(L"%s validation failed", wsCaptionName.c_str()); + return wsMessage; + } + if (bError) { + wsMessage.Format(L"The value you entered for %s is invalid.", + wsCaptionName.c_str()); + return wsMessage; + } + wsMessage.Format( + L"The value you entered for %s is invalid. To ignore " + L"validations for %s, click Ignore.", + wsCaptionName.c_str(), wsCaptionName.c_str()); + return wsMessage; +} + +int32_t CXFA_WidgetAcc::ProcessValidate(int32_t iFlags) { + if (GetElementType() == XFA_Element::Draw) + return XFA_EVENTERROR_NotExist; + + CXFA_Validate validate = GetValidate(); + if (!validate) + return XFA_EVENTERROR_NotExist; + + bool bInitDoc = validate.GetNode()->NeedsInitApp(); + bool bStatus = m_pDocView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End; + int32_t iFormat = 0; + CFXJSE_Value* pRetValue = nullptr; + int32_t iRet = XFA_EVENTERROR_NotExist; + CXFA_Script script = validate.GetScript(); + if (script) { + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_Validate; + eParam.m_pTarget = this; + iRet = ExecuteScript(script, &eParam, + ((bInitDoc || bStatus) && GetRawValue().IsEmpty()) + ? nullptr + : &pRetValue); + } + XFA_VERSION version = GetDoc()->GetXFADoc()->GetCurVersionMode(); + bool bVersionFlag = false; + if (version < XFA_VERSION_208) + bVersionFlag = true; + + if (bInitDoc) { + validate.GetNode()->ClearFlag(XFA_NodeFlag_NeedsInitApp); + } else { + iFormat = ProcessFormatTestValidate(validate, bVersionFlag); + if (!bVersionFlag) + bVersionFlag = GetDoc()->GetXFADoc()->HasFlag(XFA_DOCFLAG_Scripting); + + iRet |= ProcessNullTestValidate(validate, iFlags, bVersionFlag); + } + if (iFormat != XFA_EVENTERROR_Success) + ProcessScriptTestValidate(validate, iRet, pRetValue, bVersionFlag); + + delete pRetValue; + + return iRet | iFormat; +} + +int32_t CXFA_WidgetAcc::ExecuteScript(CXFA_Script script, + CXFA_EventParam* pEventParam, + CFXJSE_Value** pRetValue) { + static const uint32_t MAX_RECURSION_DEPTH = 2; + if (m_nRecursionDepth > MAX_RECURSION_DEPTH) + return XFA_EVENTERROR_Success; + + ASSERT(pEventParam); + if (!script) + return XFA_EVENTERROR_NotExist; + if (script.GetRunAt() == XFA_ATTRIBUTEENUM_Server) + return XFA_EVENTERROR_Disabled; + + CFX_WideString wsExpression; + script.GetExpression(wsExpression); + if (wsExpression.IsEmpty()) + return XFA_EVENTERROR_NotExist; + + XFA_SCRIPTTYPE eScriptType = script.GetContentType(); + if (eScriptType == XFA_SCRIPTTYPE_Unkown) + return XFA_EVENTERROR_Success; + + CXFA_FFDoc* pDoc = GetDoc(); + CXFA_ScriptContext* pContext = pDoc->GetXFADoc()->GetScriptContext(); + pContext->SetEventParam(*pEventParam); + pContext->SetRunAtType((XFA_ATTRIBUTEENUM)script.GetRunAt()); + std::vector<CXFA_Node*> refNodes; + if (pEventParam->m_eType == XFA_EVENT_InitCalculate || + pEventParam->m_eType == XFA_EVENT_Calculate) { + pContext->SetNodesOfRunScript(&refNodes); + } + std::unique_ptr<CFXJSE_Value> pTmpRetValue( + new CFXJSE_Value(pContext->GetRuntime())); + ++m_nRecursionDepth; + bool bRet = pContext->RunScript((XFA_SCRIPTLANGTYPE)eScriptType, + wsExpression.AsStringC(), pTmpRetValue.get(), + m_pNode); + --m_nRecursionDepth; + int32_t iRet = XFA_EVENTERROR_Error; + if (bRet) { + iRet = XFA_EVENTERROR_Success; + if (pEventParam->m_eType == XFA_EVENT_Calculate || + pEventParam->m_eType == XFA_EVENT_InitCalculate) { + if (!pTmpRetValue->IsUndefined()) { + if (!pTmpRetValue->IsNull()) + pEventParam->m_wsResult = pTmpRetValue->ToWideString(); + + iRet = XFA_EVENTERROR_Success; + } else { + iRet = XFA_EVENTERROR_Error; + } + if (pEventParam->m_eType == XFA_EVENT_InitCalculate) { + if ((iRet == XFA_EVENTERROR_Success) && + (GetRawValue() != pEventParam->m_wsResult)) { + SetValue(pEventParam->m_wsResult, XFA_VALUEPICTURE_Raw); + m_pDocView->AddValidateWidget(this); + } + } + for (CXFA_Node* pRefNode : refNodes) { + if (static_cast<CXFA_WidgetAcc*>(pRefNode->GetWidgetData()) == this) + continue; + + auto* pGlobalData = + static_cast<CXFA_CalcData*>(pRefNode->GetUserData(XFA_CalcData)); + if (!pGlobalData) { + pGlobalData = new CXFA_CalcData; + pRefNode->SetUserData(XFA_CalcData, pGlobalData, + &gs_XFADeleteCalcData); + } + if (!pdfium::ContainsValue(pGlobalData->m_Globals, this)) + pGlobalData->m_Globals.push_back(this); + } + } + } + if (pRetValue) + *pRetValue = pTmpRetValue.release(); + + pContext->SetNodesOfRunScript(nullptr); + return iRet; +} + +CXFA_FFWidget* CXFA_WidgetAcc::GetNextWidget(CXFA_FFWidget* pWidget) { + CXFA_LayoutItem* pLayout = nullptr; + if (pWidget) + pLayout = pWidget->GetNext(); + else + pLayout = m_pDocView->GetXFALayout()->GetLayoutItem(m_pNode); + + return static_cast<CXFA_FFWidget*>(pLayout); +} + +void CXFA_WidgetAcc::UpdateUIDisplay(CXFA_FFWidget* pExcept) { + CXFA_FFWidget* pWidget = nullptr; + while ((pWidget = GetNextWidget(pWidget)) != nullptr) { + if (pWidget == pExcept || !pWidget->IsLoaded() || + (GetUIType() != XFA_Element::CheckButton && pWidget->IsFocused())) { + continue; + } + pWidget->UpdateFWLData(); + pWidget->AddInvalidateRect(); + } +} + +void CXFA_WidgetAcc::CalcCaptionSize(CFX_SizeF& szCap) { + CXFA_Caption caption = GetCaption(); + if (!caption || caption.GetPresence() != XFA_ATTRIBUTEENUM_Visible) + return; + + LoadCaption(); + XFA_Element eUIType = GetUIType(); + int32_t iCapPlacement = caption.GetPlacementType(); + float fCapReserve = caption.GetReserve(); + const bool bVert = iCapPlacement == XFA_ATTRIBUTEENUM_Top || + iCapPlacement == XFA_ATTRIBUTEENUM_Bottom; + const bool bReserveExit = fCapReserve > 0.01; + CXFA_TextLayout* pCapTextLayout = + static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) + ->m_pCapTextLayout.get(); + if (pCapTextLayout) { + if (!bVert && eUIType != XFA_Element::Button) + szCap.width = fCapReserve; + + CFX_SizeF minSize; + pCapTextLayout->CalcSize(minSize, szCap, szCap); + if (bReserveExit) + bVert ? szCap.height = fCapReserve : szCap.width = fCapReserve; + } else { + float fFontSize = 10.0f; + if (CXFA_Font font = caption.GetFont()) + fFontSize = font.GetFontSize(); + else if (CXFA_Font widgetfont = GetFont()) + fFontSize = widgetfont.GetFontSize(); + + if (bVert) { + szCap.height = fCapReserve > 0 ? fCapReserve : fFontSize; + } else { + szCap.width = fCapReserve > 0 ? fCapReserve : 0; + szCap.height = fFontSize; + } + } + if (CXFA_Margin mgCap = caption.GetMargin()) { + float fLeftInset, fTopInset, fRightInset, fBottomInset; + mgCap.GetLeftInset(fLeftInset); + mgCap.GetTopInset(fTopInset); + mgCap.GetRightInset(fRightInset); + mgCap.GetBottomInset(fBottomInset); + if (bReserveExit) { + bVert ? (szCap.width += fLeftInset + fRightInset) + : (szCap.height += fTopInset + fBottomInset); + } else { + szCap.width += fLeftInset + fRightInset; + szCap.height += fTopInset + fBottomInset; + } + } +} + +bool CXFA_WidgetAcc::CalculateFieldAutoSize(CFX_SizeF& size) { + CFX_SizeF szCap; + CalcCaptionSize(szCap); + CFX_RectF rtUIMargin = GetUIMargin(); + size.width += rtUIMargin.left + rtUIMargin.width; + size.height += rtUIMargin.top + rtUIMargin.height; + if (szCap.width > 0 && szCap.height > 0) { + int32_t iCapPlacement = GetCaption().GetPlacementType(); + switch (iCapPlacement) { + case XFA_ATTRIBUTEENUM_Left: + case XFA_ATTRIBUTEENUM_Right: + case XFA_ATTRIBUTEENUM_Inline: { + size.width += szCap.width; + size.height = std::max(size.height, szCap.height); + } break; + case XFA_ATTRIBUTEENUM_Top: + case XFA_ATTRIBUTEENUM_Bottom: { + size.height += szCap.height; + size.width = std::max(size.width, szCap.width); + } + default: + break; + } + } + return CalculateWidgetAutoSize(size); +} + +bool CXFA_WidgetAcc::CalculateWidgetAutoSize(CFX_SizeF& size) { + CXFA_Margin mgWidget = GetMargin(); + if (mgWidget) { + float fLeftInset, fTopInset, fRightInset, fBottomInset; + mgWidget.GetLeftInset(fLeftInset); + mgWidget.GetTopInset(fTopInset); + mgWidget.GetRightInset(fRightInset); + mgWidget.GetBottomInset(fBottomInset); + size.width += fLeftInset + fRightInset; + size.height += fTopInset + fBottomInset; + } + CXFA_Para para = GetPara(); + if (para) + size.width += para.GetMarginLeft() + para.GetTextIndent(); + + float fVal = 0; + float fMin = 0; + float fMax = 0; + if (GetWidth(fVal)) { + size.width = fVal; + } else { + if (GetMinWidth(fMin)) + size.width = std::max(size.width, fMin); + if (GetMaxWidth(fMax) && fMax > 0) + size.width = std::min(size.width, fMax); + } + fVal = 0; + fMin = 0; + fMax = 0; + if (GetHeight(fVal)) { + size.height = fVal; + } else { + if (GetMinHeight(fMin)) + size.height = std::max(size.height, fMin); + if (GetMaxHeight(fMax) && fMax > 0) + size.height = std::min(size.height, fMax); + } + return true; +} + +void CXFA_WidgetAcc::CalculateTextContentSize(CFX_SizeF& size) { + float fFontSize = GetFontSize(); + CFX_WideString wsText; + GetValue(wsText, XFA_VALUEPICTURE_Display); + if (wsText.IsEmpty()) { + size.height += fFontSize; + return; + } + + wchar_t wcEnter = '\n'; + wchar_t wsLast = wsText.GetAt(wsText.GetLength() - 1); + if (wsLast == wcEnter) + wsText = wsText + wcEnter; + + CXFA_FieldLayoutData* layoutData = + static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()); + if (!layoutData->m_pTextOut) { + layoutData->m_pTextOut = pdfium::MakeUnique<CFDE_TextOut>(); + CFDE_TextOut* pTextOut = layoutData->m_pTextOut.get(); + pTextOut->SetFont(GetFDEFont()); + pTextOut->SetFontSize(fFontSize); + pTextOut->SetLineBreakTolerance(fFontSize * 0.2f); + pTextOut->SetLineSpace(GetLineHeight()); + uint32_t dwStyles = FDE_TTOSTYLE_LastLineHeight; + if (GetUIType() == XFA_Element::TextEdit && IsMultiLine()) + dwStyles |= FDE_TTOSTYLE_LineWrap; + + pTextOut->SetStyles(dwStyles); + } + layoutData->m_pTextOut->CalcLogicSize(wsText.c_str(), wsText.GetLength(), + size); +} + +bool CXFA_WidgetAcc::CalculateTextEditAutoSize(CFX_SizeF& size) { + if (size.width > 0) { + CFX_SizeF szOrz = size; + CFX_SizeF szCap; + CalcCaptionSize(szCap); + bool bCapExit = szCap.width > 0.01 && szCap.height > 0.01; + int32_t iCapPlacement = XFA_ATTRIBUTEENUM_Unknown; + if (bCapExit) { + iCapPlacement = GetCaption().GetPlacementType(); + switch (iCapPlacement) { + case XFA_ATTRIBUTEENUM_Left: + case XFA_ATTRIBUTEENUM_Right: + case XFA_ATTRIBUTEENUM_Inline: { + size.width -= szCap.width; + } + default: + break; + } + } + CFX_RectF rtUIMargin = GetUIMargin(); + size.width -= rtUIMargin.left + rtUIMargin.width; + CXFA_Margin mgWidget = GetMargin(); + if (mgWidget) { + float fLeftInset, fRightInset; + mgWidget.GetLeftInset(fLeftInset); + mgWidget.GetRightInset(fRightInset); + size.width -= fLeftInset + fRightInset; + } + CalculateTextContentSize(size); + size.height += rtUIMargin.top + rtUIMargin.height; + if (bCapExit) { + switch (iCapPlacement) { + case XFA_ATTRIBUTEENUM_Left: + case XFA_ATTRIBUTEENUM_Right: + case XFA_ATTRIBUTEENUM_Inline: { + size.height = std::max(size.height, szCap.height); + } break; + case XFA_ATTRIBUTEENUM_Top: + case XFA_ATTRIBUTEENUM_Bottom: { + size.height += szCap.height; + } + default: + break; + } + } + size.width = szOrz.width; + return CalculateWidgetAutoSize(size); + } + CalculateTextContentSize(size); + return CalculateFieldAutoSize(size); +} + +bool CXFA_WidgetAcc::CalculateCheckButtonAutoSize(CFX_SizeF& size) { + float fCheckSize = GetCheckButtonSize(); + size = CFX_SizeF(fCheckSize, fCheckSize); + return CalculateFieldAutoSize(size); +} + +bool CXFA_WidgetAcc::CalculatePushButtonAutoSize(CFX_SizeF& size) { + CalcCaptionSize(size); + return CalculateWidgetAutoSize(size); +} + +bool CXFA_WidgetAcc::CalculateImageAutoSize(CFX_SizeF& size) { + if (!GetImageImage()) + LoadImageImage(); + + size.clear(); + if (CFX_DIBitmap* pBitmap = GetImageImage()) { + int32_t iImageXDpi = 0; + int32_t iImageYDpi = 0; + GetImageDpi(iImageXDpi, iImageYDpi); + CFX_RectF rtImage( + 0, 0, XFA_UnitPx2Pt((float)pBitmap->GetWidth(), (float)iImageXDpi), + XFA_UnitPx2Pt((float)pBitmap->GetHeight(), (float)iImageYDpi)); + + CFX_RectF rtFit; + if (GetWidth(rtFit.width)) + GetWidthWithoutMargin(rtFit.width); + else + rtFit.width = rtImage.width; + + if (GetHeight(rtFit.height)) + GetHeightWithoutMargin(rtFit.height); + else + rtFit.height = rtImage.height; + + size = rtFit.Size(); + } + return CalculateWidgetAutoSize(size); +} + +bool CXFA_WidgetAcc::CalculateImageEditAutoSize(CFX_SizeF& size) { + if (!GetImageEditImage()) + LoadImageEditImage(); + + size.clear(); + if (CFX_DIBitmap* pBitmap = GetImageEditImage()) { + int32_t iImageXDpi = 0; + int32_t iImageYDpi = 0; + GetImageEditDpi(iImageXDpi, iImageYDpi); + CFX_RectF rtImage( + 0, 0, XFA_UnitPx2Pt((float)pBitmap->GetWidth(), (float)iImageXDpi), + XFA_UnitPx2Pt((float)pBitmap->GetHeight(), (float)iImageYDpi)); + + CFX_RectF rtFit; + if (GetWidth(rtFit.width)) + GetWidthWithoutMargin(rtFit.width); + else + rtFit.width = rtImage.width; + + if (GetHeight(rtFit.height)) + GetHeightWithoutMargin(rtFit.height); + else + rtFit.height = rtImage.height; + + size.width = rtFit.width; + size.height = rtFit.height; + } + return CalculateFieldAutoSize(size); +} + +bool CXFA_WidgetAcc::LoadImageImage() { + InitLayoutData(); + return static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()) + ->LoadImageData(this); +} + +bool CXFA_WidgetAcc::LoadImageEditImage() { + InitLayoutData(); + return static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()) + ->LoadImageData(this); +} + +void CXFA_WidgetAcc::GetImageDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) { + CXFA_ImageLayoutData* pData = + static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()); + iImageXDpi = pData->m_iImageXDpi; + iImageYDpi = pData->m_iImageYDpi; +} + +void CXFA_WidgetAcc::GetImageEditDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) { + CXFA_ImageEditData* pData = + static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()); + iImageXDpi = pData->m_iImageXDpi; + iImageYDpi = pData->m_iImageYDpi; +} + +bool CXFA_WidgetAcc::CalculateTextAutoSize(CFX_SizeF& size) { + LoadText(); + CXFA_TextLayout* pTextLayout = + static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout(); + if (pTextLayout) { + size.width = pTextLayout->StartLayout(size.width); + size.height = pTextLayout->GetLayoutHeight(); + } + return CalculateWidgetAutoSize(size); +} + +void CXFA_WidgetAcc::LoadText() { + InitLayoutData(); + static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->LoadText(this); +} + +float CXFA_WidgetAcc::CalculateWidgetAutoWidth(float fWidthCalc) { + CXFA_Margin mgWidget = GetMargin(); + if (mgWidget) { + float fLeftInset, fRightInset; + mgWidget.GetLeftInset(fLeftInset); + mgWidget.GetRightInset(fRightInset); + fWidthCalc += fLeftInset + fRightInset; + } + + float fMin = 0, fMax = 0; + if (GetMinWidth(fMin)) + fWidthCalc = std::max(fWidthCalc, fMin); + if (GetMaxWidth(fMax) && fMax > 0) + fWidthCalc = std::min(fWidthCalc, fMax); + + return fWidthCalc; +} + +float CXFA_WidgetAcc::GetWidthWithoutMargin(float fWidthCalc) { + CXFA_Margin mgWidget = GetMargin(); + if (mgWidget) { + float fLeftInset, fRightInset; + mgWidget.GetLeftInset(fLeftInset); + mgWidget.GetRightInset(fRightInset); + fWidthCalc -= fLeftInset + fRightInset; + } + return fWidthCalc; +} + +float CXFA_WidgetAcc::CalculateWidgetAutoHeight(float fHeightCalc) { + CXFA_Margin mgWidget = GetMargin(); + if (mgWidget) { + float fTopInset, fBottomInset; + mgWidget.GetTopInset(fTopInset); + mgWidget.GetBottomInset(fBottomInset); + fHeightCalc += fTopInset + fBottomInset; + } + + float fMin = 0, fMax = 0; + if (GetMinHeight(fMin)) + fHeightCalc = std::max(fHeightCalc, fMin); + if (GetMaxHeight(fMax) && fMax > 0) + fHeightCalc = std::min(fHeightCalc, fMax); + + return fHeightCalc; +} + +float CXFA_WidgetAcc::GetHeightWithoutMargin(float fHeightCalc) { + CXFA_Margin mgWidget = GetMargin(); + if (mgWidget) { + float fTopInset, fBottomInset; + mgWidget.GetTopInset(fTopInset); + mgWidget.GetBottomInset(fBottomInset); + fHeightCalc -= fTopInset + fBottomInset; + } + return fHeightCalc; +} + +void CXFA_WidgetAcc::StartWidgetLayout(float& fCalcWidth, float& fCalcHeight) { + InitLayoutData(); + XFA_Element eUIType = GetUIType(); + if (eUIType == XFA_Element::Text) { + m_pLayoutData->m_fWidgetHeight = -1; + GetHeight(m_pLayoutData->m_fWidgetHeight); + StartTextLayout(fCalcWidth, fCalcHeight); + return; + } + if (fCalcWidth > 0 && fCalcHeight > 0) + return; + + m_pLayoutData->m_fWidgetHeight = -1; + float fWidth = 0; + if (fCalcWidth > 0 && fCalcHeight < 0) { + if (!GetHeight(fCalcHeight)) + CalculateAccWidthAndHeight(eUIType, fCalcWidth, fCalcHeight); + + m_pLayoutData->m_fWidgetHeight = fCalcHeight; + return; + } + if (fCalcWidth < 0 && fCalcHeight < 0) { + if (!GetWidth(fWidth) || !GetHeight(fCalcHeight)) + CalculateAccWidthAndHeight(eUIType, fWidth, fCalcHeight); + + fCalcWidth = fWidth; + } + m_pLayoutData->m_fWidgetHeight = fCalcHeight; +} + +void CXFA_WidgetAcc::CalculateAccWidthAndHeight(XFA_Element eUIType, + float& fWidth, + float& fCalcHeight) { + CFX_SizeF sz(fWidth, m_pLayoutData->m_fWidgetHeight); + switch (eUIType) { + case XFA_Element::Barcode: + case XFA_Element::ChoiceList: + case XFA_Element::Signature: + CalculateFieldAutoSize(sz); + break; + case XFA_Element::ImageEdit: + CalculateImageEditAutoSize(sz); + break; + case XFA_Element::Button: + CalculatePushButtonAutoSize(sz); + break; + case XFA_Element::CheckButton: + CalculateCheckButtonAutoSize(sz); + break; + case XFA_Element::DateTimeEdit: + case XFA_Element::NumericEdit: + case XFA_Element::PasswordEdit: + case XFA_Element::TextEdit: + CalculateTextEditAutoSize(sz); + break; + case XFA_Element::Image: + CalculateImageAutoSize(sz); + break; + case XFA_Element::Arc: + case XFA_Element::Line: + case XFA_Element::Rectangle: + case XFA_Element::Subform: + case XFA_Element::ExclGroup: + CalculateWidgetAutoSize(sz); + break; + default: + break; + } + fWidth = sz.width; + m_pLayoutData->m_fWidgetHeight = sz.height; + fCalcHeight = sz.height; +} + +bool CXFA_WidgetAcc::FindSplitPos(int32_t iBlockIndex, float& fCalcHeight) { + XFA_Element eUIType = GetUIType(); + if (eUIType == XFA_Element::Subform) + return false; + + if (eUIType != XFA_Element::Text && eUIType != XFA_Element::TextEdit && + eUIType != XFA_Element::NumericEdit && + eUIType != XFA_Element::PasswordEdit) { + fCalcHeight = 0; + return true; + } + + float fTopInset = 0; + float fBottomInset = 0; + if (iBlockIndex == 0) { + CXFA_Margin mgWidget = GetMargin(); + if (mgWidget) { + mgWidget.GetTopInset(fTopInset); + mgWidget.GetBottomInset(fBottomInset); + } + CFX_RectF rtUIMargin = GetUIMargin(); + fTopInset += rtUIMargin.top; + fBottomInset += rtUIMargin.width; + } + if (eUIType == XFA_Element::Text) { + float fHeight = fCalcHeight; + if (iBlockIndex == 0) { + fCalcHeight = fCalcHeight - fTopInset; + if (fCalcHeight < 0) + fCalcHeight = 0; + } + + CXFA_TextLayout* pTextLayout = + static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout(); + pTextLayout->DoLayout(iBlockIndex, fCalcHeight, fCalcHeight, + m_pLayoutData->m_fWidgetHeight - fTopInset); + if (fCalcHeight != 0) { + if (iBlockIndex == 0) + fCalcHeight = fCalcHeight + fTopInset; + if (fabs(fHeight - fCalcHeight) < XFA_FLOAT_PERCISION) + return false; + } + return true; + } + XFA_ATTRIBUTEENUM iCapPlacement = XFA_ATTRIBUTEENUM_Unknown; + float fCapReserve = 0; + if (iBlockIndex == 0) { + CXFA_Caption caption = GetCaption(); + if (caption && caption.GetPresence() != XFA_ATTRIBUTEENUM_Hidden) { + iCapPlacement = (XFA_ATTRIBUTEENUM)caption.GetPlacementType(); + fCapReserve = caption.GetReserve(); + } + if (iCapPlacement == XFA_ATTRIBUTEENUM_Top && + fCalcHeight < fCapReserve + fTopInset) { + fCalcHeight = 0; + return true; + } + if (iCapPlacement == XFA_ATTRIBUTEENUM_Bottom && + m_pLayoutData->m_fWidgetHeight - fCapReserve - fBottomInset) { + fCalcHeight = 0; + return true; + } + if (iCapPlacement != XFA_ATTRIBUTEENUM_Top) + fCapReserve = 0; + } + CXFA_FieldLayoutData* pFieldData = + static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()); + int32_t iLinesCount = 0; + float fHeight = m_pLayoutData->m_fWidgetHeight; + CFX_WideString wsText; + GetValue(wsText, XFA_VALUEPICTURE_Display); + if (wsText.IsEmpty()) { + iLinesCount = 1; + } else { + if (!pFieldData->m_pTextOut) { + float fWidth = 0; + GetWidth(fWidth); + CalculateAccWidthAndHeight(eUIType, fWidth, fHeight); + } + iLinesCount = pFieldData->m_pTextOut->GetTotalLines(); + } + std::vector<float>* pFieldArray = &pFieldData->m_FieldSplitArray; + int32_t iFieldSplitCount = pdfium::CollectionSize<int32_t>(*pFieldArray); + for (int32_t i = 0; i < iBlockIndex * 3; i += 3) { + iLinesCount -= (int32_t)(*pFieldArray)[i + 1]; + fHeight -= (*pFieldArray)[i + 2]; + } + if (iLinesCount == 0) + return false; + + float fLineHeight = GetLineHeight(); + float fFontSize = GetFontSize(); + float fTextHeight = iLinesCount * fLineHeight - fLineHeight + fFontSize; + float fSpaceAbove = 0; + float fStartOffset = 0; + if (fHeight > 0.1f && iBlockIndex == 0) { + fStartOffset = fTopInset; + fHeight -= (fTopInset + fBottomInset); + if (CXFA_Para para = GetPara()) { + fSpaceAbove = para.GetSpaceAbove(); + float fSpaceBelow = para.GetSpaceBelow(); + fHeight -= (fSpaceAbove + fSpaceBelow); + switch (para.GetVerticalAlign()) { + case XFA_ATTRIBUTEENUM_Top: + fStartOffset += fSpaceAbove; + break; + case XFA_ATTRIBUTEENUM_Middle: + fStartOffset += ((fHeight - fTextHeight) / 2 + fSpaceAbove); + break; + case XFA_ATTRIBUTEENUM_Bottom: + fStartOffset += (fHeight - fTextHeight + fSpaceAbove); + break; + } + } + if (fStartOffset < 0.1f) + fStartOffset = 0; + } + for (int32_t i = iBlockIndex - 1; iBlockIndex > 0 && i < iBlockIndex; i++) { + fStartOffset = (*pFieldArray)[i * 3] - (*pFieldArray)[i * 3 + 2]; + if (fStartOffset < 0.1f) + fStartOffset = 0; + } + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) + (*pFieldArray)[0] = fStartOffset; + else + pFieldArray->push_back(fStartOffset); + + XFA_VERSION version = GetDoc()->GetXFADoc()->GetCurVersionMode(); + bool bCanSplitNoContent = false; + XFA_ATTRIBUTEENUM eLayoutMode; + GetNode() + ->GetNodeItem(XFA_NODEITEM_Parent) + ->TryEnum(XFA_ATTRIBUTE_Layout, eLayoutMode, true); + if ((eLayoutMode == XFA_ATTRIBUTEENUM_Position || + eLayoutMode == XFA_ATTRIBUTEENUM_Tb || + eLayoutMode == XFA_ATTRIBUTEENUM_Row || + eLayoutMode == XFA_ATTRIBUTEENUM_Table) && + version > XFA_VERSION_208) { + bCanSplitNoContent = true; + } + if ((eLayoutMode == XFA_ATTRIBUTEENUM_Tb || + eLayoutMode == XFA_ATTRIBUTEENUM_Row || + eLayoutMode == XFA_ATTRIBUTEENUM_Table) && + version <= XFA_VERSION_208) { + if (fStartOffset < fCalcHeight) { + bCanSplitNoContent = true; + } else { + fCalcHeight = 0; + return true; + } + } + if (bCanSplitNoContent) { + if ((fCalcHeight - fTopInset - fSpaceAbove < fLineHeight)) { + fCalcHeight = 0; + return true; + } + if (fStartOffset + XFA_FLOAT_PERCISION >= fCalcHeight) { + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { + (*pFieldArray)[iBlockIndex * 3 + 1] = 0; + (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; + } else { + pFieldArray->push_back(0); + pFieldArray->push_back(fCalcHeight); + } + return false; + } + if (fCalcHeight - fStartOffset < fLineHeight) { + fCalcHeight = fStartOffset; + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { + (*pFieldArray)[iBlockIndex * 3 + 1] = 0; + (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; + } else { + pFieldArray->push_back(0); + pFieldArray->push_back(fCalcHeight); + } + return true; + } + float fTextNum = + fCalcHeight + XFA_FLOAT_PERCISION - fCapReserve - fStartOffset; + int32_t iLineNum = + (int32_t)((fTextNum + (fLineHeight - fFontSize)) / fLineHeight); + if (iLineNum >= iLinesCount) { + if (fCalcHeight - fStartOffset - fTextHeight >= fFontSize) { + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { + (*pFieldArray)[iBlockIndex * 3 + 1] = (float)iLinesCount; + (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; + } else { + pFieldArray->push_back((float)iLinesCount); + pFieldArray->push_back(fCalcHeight); + } + return false; + } + if (fHeight - fStartOffset - fTextHeight < fFontSize) { + iLineNum -= 1; + if (iLineNum == 0) { + fCalcHeight = 0; + return true; + } + } else { + iLineNum = (int32_t)(fTextNum / fLineHeight); + } + } + if (iLineNum > 0) { + float fSplitHeight = iLineNum * fLineHeight + fCapReserve + fStartOffset; + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { + (*pFieldArray)[iBlockIndex * 3 + 1] = (float)iLineNum; + (*pFieldArray)[iBlockIndex * 3 + 2] = fSplitHeight; + } else { + pFieldArray->push_back((float)iLineNum); + pFieldArray->push_back(fSplitHeight); + } + if (fabs(fSplitHeight - fCalcHeight) < XFA_FLOAT_PERCISION) + return false; + + fCalcHeight = fSplitHeight; + return true; + } + } + fCalcHeight = 0; + return true; +} + +void CXFA_WidgetAcc::InitLayoutData() { + if (m_pLayoutData) + return; + + switch (GetUIType()) { + case XFA_Element::Text: + m_pLayoutData = pdfium::MakeUnique<CXFA_TextLayoutData>(); + return; + case XFA_Element::TextEdit: + m_pLayoutData = pdfium::MakeUnique<CXFA_TextEditData>(); + return; + case XFA_Element::Image: + m_pLayoutData = pdfium::MakeUnique<CXFA_ImageLayoutData>(); + return; + case XFA_Element::ImageEdit: + m_pLayoutData = pdfium::MakeUnique<CXFA_ImageEditData>(); + return; + default: + break; + } + if (GetElementType() == XFA_Element::Field) { + m_pLayoutData = pdfium::MakeUnique<CXFA_FieldLayoutData>(); + return; + } + m_pLayoutData = pdfium::MakeUnique<CXFA_WidgetLayoutData>(); +} + +void CXFA_WidgetAcc::StartTextLayout(float& fCalcWidth, float& fCalcHeight) { + LoadText(); + CXFA_TextLayout* pTextLayout = + static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout(); + float fTextHeight = 0; + if (fCalcWidth > 0 && fCalcHeight > 0) { + float fWidth = GetWidthWithoutMargin(fCalcWidth); + pTextLayout->StartLayout(fWidth); + fTextHeight = fCalcHeight; + fTextHeight = GetHeightWithoutMargin(fTextHeight); + pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight); + return; + } + if (fCalcWidth > 0 && fCalcHeight < 0) { + float fWidth = GetWidthWithoutMargin(fCalcWidth); + pTextLayout->StartLayout(fWidth); + } + if (fCalcWidth < 0 && fCalcHeight < 0) { + float fMaxWidth = -1; + bool bRet = GetWidth(fMaxWidth); + if (bRet) { + float fWidth = GetWidthWithoutMargin(fMaxWidth); + pTextLayout->StartLayout(fWidth); + } else { + float fWidth = pTextLayout->StartLayout(fMaxWidth); + fMaxWidth = CalculateWidgetAutoWidth(fWidth); + fWidth = GetWidthWithoutMargin(fMaxWidth); + pTextLayout->StartLayout(fWidth); + } + fCalcWidth = fMaxWidth; + } + if (m_pLayoutData->m_fWidgetHeight < 0) { + m_pLayoutData->m_fWidgetHeight = pTextLayout->GetLayoutHeight(); + m_pLayoutData->m_fWidgetHeight = + CalculateWidgetAutoHeight(m_pLayoutData->m_fWidgetHeight); + } + fTextHeight = m_pLayoutData->m_fWidgetHeight; + fTextHeight = GetHeightWithoutMargin(fTextHeight); + pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight); + fCalcHeight = m_pLayoutData->m_fWidgetHeight; +} + +bool CXFA_WidgetAcc::LoadCaption() { + InitLayoutData(); + return static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) + ->LoadCaption(this); +} + +CXFA_TextLayout* CXFA_WidgetAcc::GetCaptionTextLayout() { + return m_pLayoutData + ? static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) + ->m_pCapTextLayout.get() + : nullptr; +} + +CXFA_TextLayout* CXFA_WidgetAcc::GetTextLayout() { + return m_pLayoutData + ? static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get()) + ->GetTextLayout() + : nullptr; +} + +CFX_DIBitmap* CXFA_WidgetAcc::GetImageImage() { + return m_pLayoutData + ? static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()) + ->m_pDIBitmap + : nullptr; +} + +CFX_DIBitmap* CXFA_WidgetAcc::GetImageEditImage() { + return m_pLayoutData + ? static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()) + ->m_pDIBitmap + : nullptr; +} + +void CXFA_WidgetAcc::SetImageImage(CFX_DIBitmap* newImage) { + CXFA_ImageLayoutData* pData = + static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()); + if (pData->m_pDIBitmap == newImage) + return; + + if (pData->m_pDIBitmap && !pData->m_bNamedImage) + delete pData->m_pDIBitmap; + + pData->m_pDIBitmap = newImage; +} + +void CXFA_WidgetAcc::SetImageEditImage(CFX_DIBitmap* newImage) { + CXFA_ImageEditData* pData = + static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()); + if (pData->m_pDIBitmap == newImage) + return; + + if (pData->m_pDIBitmap && !pData->m_bNamedImage) + delete pData->m_pDIBitmap; + + pData->m_pDIBitmap = newImage; +} + +CXFA_WidgetLayoutData* CXFA_WidgetAcc::GetWidgetLayoutData() { + return m_pLayoutData.get(); +} + +CFX_RetainPtr<CFGAS_GEFont> CXFA_WidgetAcc::GetFDEFont() { + CFX_WideStringC wsFontName = L"Courier"; + uint32_t dwFontStyle = 0; + if (CXFA_Font font = GetFont()) { + if (font.IsBold()) + dwFontStyle |= FX_FONTSTYLE_Bold; + if (font.IsItalic()) + dwFontStyle |= FX_FONTSTYLE_Italic; + font.GetTypeface(wsFontName); + } + + auto* pDoc = GetDoc(); + return pDoc->GetApp()->GetXFAFontMgr()->GetFont(pDoc, wsFontName, + dwFontStyle); +} + +float CXFA_WidgetAcc::GetFontSize() { + float fFontSize = 10.0f; + if (CXFA_Font font = GetFont()) + fFontSize = font.GetFontSize(); + return fFontSize < 0.1f ? 10.0f : fFontSize; +} + +float CXFA_WidgetAcc::GetLineHeight() { + float fLineHeight = 0; + if (CXFA_Para para = GetPara()) + fLineHeight = para.GetLineHeight(); + if (fLineHeight < 1) + fLineHeight = GetFontSize() * 1.2f; + return fLineHeight; +} + +FX_ARGB CXFA_WidgetAcc::GetTextColor() { + if (CXFA_Font font = GetFont()) { + return font.GetColor(); + } + return 0xFF000000; +} |