blob: 07745eabe6cc5c716b3b9801a4d8c1484bc044dd [file] [log] [blame]
// 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 "core/fxcrt/xml/cfx_xmlelement.h"
#include "core/fxcrt/xml/cfx_xmlnode.h"
#include "fxjs/cfxjse_engine.h"
#include "third_party/base/stl_util.h"
#include "xfa/fde/cfde_textout.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/cxfa_textlayout.h"
#include "xfa/fxfa/cxfa_textprovider.h"
#include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
#include "xfa/fxfa/parser/cxfa_localevalue.h"
#include "xfa/fxfa/parser/cxfa_node.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_bNamedImage(false), m_iImageXDpi(0), m_iImageYDpi(0) {}
~CXFA_ImageLayoutData() override {}
bool LoadImageData(CXFA_WidgetAcc* pAcc) {
if (m_pDIBitmap)
return true;
CXFA_ValueData valueData = pAcc->GetFormValueData();
if (!valueData)
return false;
CXFA_ImageData imageData = valueData.GetImageData();
if (!imageData)
return false;
CXFA_FFDoc* pFFDoc = pAcc->GetDoc();
pAcc->SetImageImage(XFA_LoadImageData(pFFDoc, &imageData, m_bNamedImage,
m_iImageXDpi, m_iImageYDpi));
return !!m_pDIBitmap;
}
RetainPtr<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_CaptionData captionData = pAcc->GetCaptionData();
if (!captionData || captionData.GetPresence() == XFA_ATTRIBUTEENUM_Hidden)
return false;
m_pCapTextProvider = pdfium::MakeUnique<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_bNamedImage(false), m_iImageXDpi(0), m_iImageYDpi(0) {}
~CXFA_ImageEditData() override {}
bool LoadImageData(CXFA_WidgetAcc* pAcc) {
if (m_pDIBitmap)
return true;
CXFA_ValueData valueData = pAcc->GetFormValueData();
if (!valueData)
return false;
CXFA_ImageData imageData = valueData.GetImageData();
CXFA_FFDoc* pFFDoc = pAcc->GetDoc();
pAcc->SetImageEditImage(XFA_LoadImageData(pFFDoc, &imageData, m_bNamedImage,
m_iImageXDpi, m_iImageYDpi));
return !!m_pDIBitmap;
}
RetainPtr<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() {}
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() {
WideString wsValue;
XFA_Element eUIType = GetUIType();
switch (eUIType) {
case XFA_Element::ImageEdit: {
CXFA_ValueData imageValueData = GetDefaultValueData();
CXFA_ImageData imageData = imageValueData.GetImageData();
WideString wsContentType, wsHref;
if (imageData) {
imageData.GetContent(wsValue);
imageData.GetContentType(wsContentType);
imageData.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_ValueData defValueData(nullptr);
if (wsValue.IsEmpty() && (defValueData = pAcc->GetDefaultValueData())) {
defValueData.GetChildValueContent(wsValue);
SetValue(wsValue, XFA_VALUEPICTURE_Raw);
pAcc->SetValue(wsValue, XFA_VALUEPICTURE_Raw);
} else {
CXFA_Node* pItems = pChild->GetChild(0, XFA_Element::Items, false);
if (!pItems)
continue;
WideString itemText;
if (pItems->CountChildren(XFA_Element::Unknown, false) > 1) {
itemText = pItems->GetChild(1, XFA_Element::Unknown, false)
->JSNode()
->GetContent(false);
}
pAcc->SetValue(itemText, XFA_VALUEPICTURE_Raw);
}
pNextChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling,
XFA_ObjectType::ContainerNode);
}
break;
}
case XFA_Element::ChoiceList:
ClearAllSelections();
default:
if (CXFA_ValueData defValueData = GetDefaultValueData())
defValueData.GetChildValueContent(wsValue);
SetValue(wsValue, XFA_VALUEPICTURE_Raw);
break;
}
}
void CXFA_WidgetAcc::SetImageEdit(const WideString& wsContentType,
const WideString& wsHref,
const WideString& wsData) {
CXFA_ImageData imageData = GetFormValueData().GetImageData();
if (imageData) {
imageData.SetContentType(WideString(wsContentType));
imageData.SetHref(wsHref);
}
WideString wsFormatValue(wsData);
GetFormatDataValue(wsData, wsFormatValue);
m_pNode->JSNode()->SetContent(wsData, wsFormatValue, true, false, true);
CXFA_Node* pBind = GetDatasets();
if (!pBind) {
imageData.SetTransferEncoding(XFA_ATTRIBUTEENUM_Base64);
return;
}
pBind->JSNode()->SetCData(XFA_ATTRIBUTE_ContentType, wsContentType, false,
false);
CXFA_Node* pHrefNode = pBind->GetNodeItem(XFA_NODEITEM_FirstChild);
if (pHrefNode) {
pHrefNode->JSNode()->SetCData(XFA_ATTRIBUTE_Value, wsHref, false, false);
} else {
CFX_XMLNode* pXMLNode = pBind->GetXMLMappingNode();
ASSERT(pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element);
static_cast<CFX_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_FFDoc* CXFA_WidgetAcc::GetDoc() {
return m_pDocView->GetDoc();
}
IXFA_AppProvider* CXFA_WidgetAcc::GetAppProvider() {
return GetDoc()->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_EventData(pNode), pEventParam);
if (first || result == XFA_EVENTERROR_Success)
iRet = result;
first = false;
}
return iRet;
}
int32_t CXFA_WidgetAcc::ProcessEvent(const CXFA_EventData& eventData,
CXFA_EventParam* pEventParam) {
if (!eventData)
return XFA_EVENTERROR_NotExist;
switch (eventData.GetEventType()) {
case XFA_Element::Execute:
break;
case XFA_Element::Script:
return ExecuteScript(eventData.GetScriptData(), pEventParam);
case XFA_Element::SignData:
break;
case XFA_Element::Submit:
return GetDoc()->GetDocEnvironment()->SubmitData(
GetDoc(), eventData.GetSubmitData());
default:
break;
}
return XFA_EVENTERROR_NotExist;
}
int32_t CXFA_WidgetAcc::ProcessCalculate() {
if (GetElementType() == XFA_Element::Draw)
return XFA_EVENTERROR_NotExist;
CXFA_CalculateData calcData = GetCalculateData();
if (!calcData)
return XFA_EVENTERROR_NotExist;
if (GetNode()->IsUserInteractive())
return XFA_EVENTERROR_Disabled;
CXFA_EventParam EventParam;
EventParam.m_eType = XFA_EVENT_Calculate;
int32_t iRet = ExecuteScript(calcData.GetScriptData(), &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_ValidateData validateData,
int32_t iRet,
bool bRetValue,
bool bVersionFlag) {
if (iRet != XFA_EVENTERROR_Success)
return;
if (bRetValue)
return;
IXFA_AppProvider* pAppProvider = GetAppProvider();
if (!pAppProvider)
return;
WideString wsTitle = pAppProvider->GetAppTitle();
WideString wsScriptMsg;
validateData.GetScriptMessageText(wsScriptMsg);
int32_t eScriptTest = validateData.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);
}
return;
}
if (wsScriptMsg.IsEmpty())
wsScriptMsg = GetValidateMessage(true, bVersionFlag);
pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK);
}
int32_t CXFA_WidgetAcc::ProcessFormatTestValidate(
CXFA_ValidateData validateData,
bool bVersionFlag) {
WideString wsRawValue = GetRawValue();
if (!wsRawValue.IsEmpty()) {
WideString wsPicture;
validateData.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,
nullptr)) {
IXFA_AppProvider* pAppProvider = GetAppProvider();
if (!pAppProvider)
return XFA_EVENTERROR_NotExist;
WideString wsFormatMsg;
validateData.GetFormatMessageText(wsFormatMsg);
WideString wsTitle = pAppProvider->GetAppTitle();
int32_t eFormatTest = validateData.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_ValidateData validateData,
int32_t iFlags,
bool bVersionFlag) {
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 = validateData.GetNullTest();
WideString wsNullMsg;
validateData.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;
WideString wsCaptionName;
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;
}
WideString CXFA_WidgetAcc::GetValidateCaptionName(bool bVersionFlag) {
WideString wsCaptionName;
if (!bVersionFlag) {
if (CXFA_CaptionData captionData = GetCaptionData()) {
if (CXFA_ValueData capValue = captionData.GetValueData()) {
if (CXFA_TextData captionTextData = capValue.GetTextData())
captionTextData.GetContent(wsCaptionName);
}
}
}
if (wsCaptionName.IsEmpty())
m_pNode->JSNode()->TryCData(XFA_ATTRIBUTE_Name, wsCaptionName, true);
return wsCaptionName;
}
WideString CXFA_WidgetAcc::GetValidateMessage(bool bError, bool bVersionFlag) {
WideString wsCaptionName = GetValidateCaptionName(bVersionFlag);
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_ValidateData validateData = GetValidateData(false);
if (!validateData)
return XFA_EVENTERROR_NotExist;
bool bInitDoc = validateData.GetNode()->NeedsInitApp();
bool bStatus = m_pDocView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End;
int32_t iFormat = 0;
int32_t iRet = XFA_EVENTERROR_NotExist;
CXFA_ScriptData scriptData = validateData.GetScriptData();
bool bRet = false;
bool hasBoolResult = (bInitDoc || bStatus) && GetRawValue().IsEmpty();
if (scriptData) {
CXFA_EventParam eParam;
eParam.m_eType = XFA_EVENT_Validate;
eParam.m_pTarget = this;
std::tie(iRet, bRet) = ExecuteBoolScript(scriptData, &eParam);
}
XFA_VERSION version = GetDoc()->GetXFADoc()->GetCurVersionMode();
bool bVersionFlag = false;
if (version < XFA_VERSION_208)
bVersionFlag = true;
if (bInitDoc) {
validateData.GetNode()->ClearFlag(XFA_NodeFlag_NeedsInitApp);
} else {
iFormat = ProcessFormatTestValidate(validateData, bVersionFlag);
if (!bVersionFlag)
bVersionFlag = GetDoc()->GetXFADoc()->HasFlag(XFA_DOCFLAG_Scripting);
iRet |= ProcessNullTestValidate(validateData, iFlags, bVersionFlag);
}
if (iFormat != XFA_EVENTERROR_Success && hasBoolResult)
ProcessScriptTestValidate(validateData, iRet, bRet, bVersionFlag);
return iRet | iFormat;
}
int32_t CXFA_WidgetAcc::ExecuteScript(CXFA_ScriptData scriptData,
CXFA_EventParam* pEventParam) {
bool bRet;
int32_t iRet;
std::tie(iRet, bRet) = ExecuteBoolScript(scriptData, pEventParam);
return iRet;
}
std::pair<int32_t, bool> CXFA_WidgetAcc::ExecuteBoolScript(
CXFA_ScriptData scriptData,
CXFA_EventParam* pEventParam) {
static const uint32_t MAX_RECURSION_DEPTH = 2;
if (m_nRecursionDepth > MAX_RECURSION_DEPTH)
return {XFA_EVENTERROR_Success, false};
ASSERT(pEventParam);
if (!scriptData)
return {XFA_EVENTERROR_NotExist, false};
if (scriptData.GetRunAt() == XFA_ATTRIBUTEENUM_Server)
return {XFA_EVENTERROR_Disabled, false};
WideString wsExpression;
scriptData.GetExpression(wsExpression);
if (wsExpression.IsEmpty())
return {XFA_EVENTERROR_NotExist, false};
XFA_SCRIPTTYPE eScriptType = scriptData.GetContentType();
if (eScriptType == XFA_SCRIPTTYPE_Unkown)
return {XFA_EVENTERROR_Success, false};
CXFA_FFDoc* pDoc = GetDoc();
CFXJSE_Engine* pContext = pDoc->GetXFADoc()->GetScriptContext();
pContext->SetEventParam(*pEventParam);
pContext->SetRunAtType((XFA_ATTRIBUTEENUM)scriptData.GetRunAt());
std::vector<CXFA_Node*> refNodes;
if (pEventParam->m_eType == XFA_EVENT_InitCalculate ||
pEventParam->m_eType == XFA_EVENT_Calculate) {
pContext->SetNodesOfRunScript(&refNodes);
}
auto pTmpRetValue = pdfium::MakeUnique<CFXJSE_Value>(pContext->GetRuntime());
++m_nRecursionDepth;
bool bRet = pContext->RunScript((XFA_SCRIPTLANGTYPE)eScriptType,
wsExpression.AsStringView(),
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->JSNode()->GetUserData(XFA_CalcData, false));
if (!pGlobalData) {
pGlobalData = new CXFA_CalcData;
pRefNode->JSNode()->SetUserData(XFA_CalcData, pGlobalData,
&gs_XFADeleteCalcData);
}
if (!pdfium::ContainsValue(pGlobalData->m_Globals, this))
pGlobalData->m_Globals.push_back(this);
}
}
}
pContext->SetNodesOfRunScript(nullptr);
return {iRet, pTmpRetValue->IsBoolean() ? pTmpRetValue->ToBoolean() : false};
}
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_CaptionData captionData = GetCaptionData();
if (!captionData || captionData.GetPresence() != XFA_ATTRIBUTEENUM_Visible)
return;
LoadCaption();
XFA_Element eUIType = GetUIType();
int32_t iCapPlacement = captionData.GetPlacementType();
float fCapReserve = captionData.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_FontData fontData = captionData.GetFontData())
fFontSize = fontData.GetFontSize();
else if (CXFA_FontData widgetfontData = GetFontData(false))
fFontSize = widgetfontData.GetFontSize();
if (bVert) {
szCap.height = fCapReserve > 0 ? fCapReserve : fFontSize;
} else {
szCap.width = fCapReserve > 0 ? fCapReserve : 0;
szCap.height = fFontSize;
}
}
if (CXFA_MarginData captionMarginData = captionData.GetMarginData()) {
float fLeftInset, fTopInset, fRightInset, fBottomInset;
captionMarginData.GetLeftInset(fLeftInset);
captionMarginData.GetTopInset(fTopInset);
captionMarginData.GetRightInset(fRightInset);
captionMarginData.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 = GetCaptionData().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_MarginData marginData = GetMarginData();
if (marginData) {
float fLeftInset, fTopInset, fRightInset, fBottomInset;
marginData.GetLeftInset(fLeftInset);
marginData.GetTopInset(fTopInset);
marginData.GetRightInset(fRightInset);
marginData.GetBottomInset(fBottomInset);
size.width += fLeftInset + fRightInset;
size.height += fTopInset + fBottomInset;
}
CXFA_ParaData paraData = GetParaData();
if (paraData)
size.width += paraData.GetMarginLeft() + paraData.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();
WideString wsText;
GetValue(wsText, XFA_VALUEPICTURE_Display);
if (wsText.IsEmpty()) {
size.height += fFontSize;
return;
}
wchar_t wcEnter = '\n';
wchar_t wsLast = wsText[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());
FDE_TextStyle dwStyles;
dwStyles.last_line_height_ = true;
if (GetUIType() == XFA_Element::TextEdit && IsMultiLine())
dwStyles.line_wrap_ = true;
pTextOut->SetStyles(dwStyles);
}
layoutData->m_pTextOut->CalcLogicSize(wsText, 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 = GetCaptionData().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_MarginData marginData = GetMarginData();
if (marginData) {
float fLeftInset;
float fRightInset;
marginData.GetLeftInset(fLeftInset);
marginData.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();
RetainPtr<CFX_DIBitmap> pBitmap = GetImageImage();
if (pBitmap) {
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();
RetainPtr<CFX_DIBitmap> pBitmap = GetImageEditImage();
if (pBitmap) {
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_MarginData marginData = GetMarginData();
if (marginData) {
float fLeftInset;
float fRightInset;
marginData.GetLeftInset(fLeftInset);
marginData.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_MarginData marginData = GetMarginData();
if (marginData) {
float fLeftInset;
float fRightInset;
marginData.GetLeftInset(fLeftInset);
marginData.GetRightInset(fRightInset);
fWidthCalc -= fLeftInset + fRightInset;
}
return fWidthCalc;
}
float CXFA_WidgetAcc::CalculateWidgetAutoHeight(float fHeightCalc) {
CXFA_MarginData marginData = GetMarginData();
if (marginData) {
float fTopInset;
float fBottomInset;
marginData.GetTopInset(fTopInset);
marginData.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_MarginData marginData = GetMarginData();
if (marginData) {
float fTopInset;
float fBottomInset;
marginData.GetTopInset(fTopInset);
marginData.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_MarginData marginData = GetMarginData();
if (marginData) {
marginData.GetTopInset(fTopInset);
marginData.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_CaptionData captionData = GetCaptionData();
if (captionData && captionData.GetPresence() != XFA_ATTRIBUTEENUM_Hidden) {
iCapPlacement = (XFA_ATTRIBUTEENUM)captionData.GetPlacementType();
fCapReserve = captionData.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;
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_ParaData paraData = GetParaData()) {
fSpaceAbove = paraData.GetSpaceAbove();
float fSpaceBelow = paraData.GetSpaceBelow();
fHeight -= (fSpaceAbove + fSpaceBelow);
switch (paraData.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)
->JSNode()
->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;
}
RetainPtr<CFX_DIBitmap> CXFA_WidgetAcc::GetImageImage() {
return m_pLayoutData
? static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get())
->m_pDIBitmap
: nullptr;
}
RetainPtr<CFX_DIBitmap> CXFA_WidgetAcc::GetImageEditImage() {
return m_pLayoutData
? static_cast<CXFA_ImageEditData*>(m_pLayoutData.get())
->m_pDIBitmap
: nullptr;
}
void CXFA_WidgetAcc::SetImageImage(const RetainPtr<CFX_DIBitmap>& newImage) {
CXFA_ImageLayoutData* pData =
static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get());
if (pData->m_pDIBitmap != newImage)
pData->m_pDIBitmap = newImage;
}
void CXFA_WidgetAcc::SetImageEditImage(
const RetainPtr<CFX_DIBitmap>& newImage) {
CXFA_ImageEditData* pData =
static_cast<CXFA_ImageEditData*>(m_pLayoutData.get());
if (pData->m_pDIBitmap != newImage)
pData->m_pDIBitmap = newImage;
}
RetainPtr<CFGAS_GEFont> CXFA_WidgetAcc::GetFDEFont() {
WideStringView wsFontName = L"Courier";
uint32_t dwFontStyle = 0;
if (CXFA_FontData fontData = GetFontData(false)) {
if (fontData.IsBold())
dwFontStyle |= FXFONT_BOLD;
if (fontData.IsItalic())
dwFontStyle |= FXFONT_ITALIC;
fontData.GetTypeface(wsFontName);
}
auto* pDoc = GetDoc();
return pDoc->GetApp()->GetXFAFontMgr()->GetFont(pDoc, wsFontName,
dwFontStyle);
}
float CXFA_WidgetAcc::GetFontSize() {
CXFA_FontData fontData = GetFontData(false);
float fFontSize = fontData ? fontData.GetFontSize() : 10.0f;
return fFontSize < 0.1f ? 10.0f : fFontSize;
}
float CXFA_WidgetAcc::GetLineHeight() {
float fLineHeight = 0;
if (CXFA_ParaData paraData = GetParaData())
fLineHeight = paraData.GetLineHeight();
if (fLineHeight < 1)
fLineHeight = GetFontSize() * 1.2f;
return fLineHeight;
}
FX_ARGB CXFA_WidgetAcc::GetTextColor() {
CXFA_FontData fontData = GetFontData(false);
return fontData ? fontData.GetColor() : 0xFF000000;
}