// 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 #include #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 { 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(pAcc, XFA_TEXTPROVIDERTYPE_Text); m_pTextLayout = pdfium::MakeUnique(m_pTextProvider.get()); } private: std::unique_ptr m_pTextLayout; std::unique_ptr 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.HasValidNode()) return false; CXFA_ImageData imageData = valueData.GetImageData(); if (!imageData.HasValidNode()) return false; CXFA_FFDoc* pFFDoc = pAcc->GetDoc(); pAcc->SetImageImage(XFA_LoadImageData(pFFDoc, &imageData, m_bNamedImage, m_iImageXDpi, m_iImageYDpi)); return !!m_pDIBitmap; } RetainPtr 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.HasValidNode() || captionData.GetPresence() == XFA_ATTRIBUTEENUM_Hidden) { return false; } m_pCapTextProvider = pdfium::MakeUnique( pAcc, XFA_TEXTPROVIDERTYPE_Caption); m_pCapTextLayout = pdfium::MakeUnique(m_pCapTextProvider.get()); return true; } std::unique_ptr m_pCapTextLayout; std::unique_ptr m_pCapTextProvider; std::unique_ptr m_pTextOut; std::vector 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.HasValidNode()) 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 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.HasValidNode()) { wsValue = imageData.GetContent(); wsContentType = imageData.GetContentType(); wsHref = imageData.GetHref(); } 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(pChild->GetWidgetData()); if (!pAcc) continue; bool done = false; if (wsValue.IsEmpty()) { CXFA_ValueData defValueData = pAcc->GetDefaultValueData(); if (defValueData.HasValidNode()) { wsValue = defValueData.GetChildValueContent(); SetValue(wsValue, XFA_VALUEPICTURE_Raw); pAcc->SetValue(wsValue, XFA_VALUEPICTURE_Raw); done = true; } } if (!done) { 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: { CXFA_ValueData defValueData = GetDefaultValueData(); if (defValueData.HasValidNode()) wsValue = defValueData.GetChildValueContent(); 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.HasValidNode()) { 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(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(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 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.HasValidNode()) 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.HasValidNode()) 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(); if (validateData.GetScriptTest() == 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(); 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(); WideString wsTitle = pAppProvider->GetAppTitle(); if (validateData.GetFormatTest() == 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; XFA_ATTRIBUTEENUM eNullTest = validateData.GetNullTest(); WideString wsNullMsg = validateData.GetNullMessageText(); 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 = WideString::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 = WideString::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) { CXFA_CaptionData captionData = GetCaptionData(); if (captionData.HasValidNode()) { CXFA_ValueData capValue = captionData.GetValueData(); if (capValue.HasValidNode()) { CXFA_TextData captionTextData = capValue.GetTextData(); if (captionTextData.HasValidNode()) wsCaptionName = captionTextData.GetContent(); } } } if (!wsCaptionName.IsEmpty()) return wsCaptionName; return m_pNode->JSNode()->GetCData(XFA_Attribute::Name); } WideString CXFA_WidgetAcc::GetValidateMessage(bool bError, bool bVersionFlag) { WideString wsCaptionName = GetValidateCaptionName(bVersionFlag); if (bVersionFlag) return WideString::Format(L"%s validation failed", wsCaptionName.c_str()); if (bError) { return WideString::Format(L"The value you entered for %s is invalid.", wsCaptionName.c_str()); } return WideString::Format( L"The value you entered for %s is invalid. To ignore " L"validations for %s, click Ignore.", wsCaptionName.c_str(), wsCaptionName.c_str()); } int32_t CXFA_WidgetAcc::ProcessValidate(int32_t iFlags) { if (GetElementType() == XFA_Element::Draw) return XFA_EVENTERROR_NotExist; CXFA_ValidateData validateData = GetValidateData(false); if (!validateData.HasValidNode()) 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.HasValidNode()) { 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(const CXFA_ScriptData& scriptData, CXFA_EventParam* pEventParam) { bool bRet; int32_t iRet; std::tie(iRet, bRet) = ExecuteBoolScript(scriptData, pEventParam); return iRet; } std::pair 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.HasValidNode()) return {XFA_EVENTERROR_NotExist, false}; if (scriptData.GetRunAt() == XFA_ATTRIBUTEENUM_Server) return {XFA_EVENTERROR_Disabled, false}; WideString wsExpression = scriptData.GetExpression(); if (wsExpression.IsEmpty()) return {XFA_EVENTERROR_NotExist, false}; CXFA_ScriptData::Type eScriptType = scriptData.GetContentType(); if (eScriptType == CXFA_ScriptData::Type::Unknown) return {XFA_EVENTERROR_Success, false}; CXFA_FFDoc* pDoc = GetDoc(); CFXJSE_Engine* pContext = pDoc->GetXFADoc()->GetScriptContext(); pContext->SetEventParam(*pEventParam); pContext->SetRunAtType(scriptData.GetRunAt()); std::vector refNodes; if (pEventParam->m_eType == XFA_EVENT_InitCalculate || pEventParam->m_eType == XFA_EVENT_Calculate) { pContext->SetNodesOfRunScript(&refNodes); } auto pTmpRetValue = pdfium::MakeUnique(pContext->GetRuntime()); ++m_nRecursionDepth; bool bRet = pContext->RunScript(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(pRefNode->GetWidgetData()) == this) continue; CXFA_CalcData* pGlobalData = pRefNode->JSNode()->GetCalcData(); if (!pGlobalData) { pRefNode->JSNode()->SetCalcData(pdfium::MakeUnique()); pGlobalData = pRefNode->JSNode()->GetCalcData(); } 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(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.HasValidNode() || 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(m_pLayoutData.get()) ->m_pCapTextLayout.get(); if (pCapTextLayout) { if (!bVert && eUIType != XFA_Element::Button) szCap.width = fCapReserve; CFX_SizeF minSize; szCap = pCapTextLayout->CalcSize(minSize, szCap); if (bReserveExit) bVert ? szCap.height = fCapReserve : szCap.width = fCapReserve; } else { float fFontSize = 10.0f; CXFA_FontData fontData = captionData.GetFontData(); if (fontData.HasValidNode()) { fFontSize = fontData.GetFontSize(); } else { CXFA_FontData widgetfontData = GetFontData(false); if (widgetfontData.HasValidNode()) fFontSize = widgetfontData.GetFontSize(); } if (bVert) { szCap.height = fCapReserve > 0 ? fCapReserve : fFontSize; } else { szCap.width = fCapReserve > 0 ? fCapReserve : 0; szCap.height = fFontSize; } } CXFA_MarginData captionMarginData = captionData.GetMarginData(); if (captionMarginData.HasValidNode()) { float fLeftInset = captionMarginData.GetLeftInset(); float fTopInset = captionMarginData.GetTopInset(); float fRightInset = captionMarginData.GetRightInset(); float fBottomInset = captionMarginData.GetBottomInset(); 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.HasValidNode()) { size.width += marginData.GetLeftInset() + marginData.GetRightInset(); size.height += marginData.GetTopInset() + marginData.GetBottomInset(); } CXFA_ParaData paraData = GetParaData(); if (paraData.HasValidNode()) size.width += paraData.GetMarginLeft() + paraData.GetTextIndent(); pdfium::Optional width = TryWidth(); if (width) { size.width = *width; } else { pdfium::Optional min = TryMinWidth(); if (min) size.width = std::max(size.width, *min); pdfium::Optional max = TryMaxWidth(); if (max && *max > 0) size.width = std::min(size.width, *max); } pdfium::Optional height = TryHeight(); if (height) { size.height = *height; } else { pdfium::Optional min = TryMinHeight(); if (min) size.height = std::max(size.height, *min); pdfium::Optional max = TryMaxHeight(); if (max && *max > 0) size.height = std::min(size.height, *max); } 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(m_pLayoutData.get()); if (!layoutData->m_pTextOut) { layoutData->m_pTextOut = pdfium::MakeUnique(); 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.HasValidNode()) size.width -= marginData.GetLeftInset() + marginData.GetRightInset(); 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); } CFX_SizeF CXFA_WidgetAcc::CalculateImageSize(float img_width, float img_height, float dpi_x, float dpi_y) { CFX_RectF rtImage(0, 0, XFA_UnitPx2Pt(img_width, dpi_x), XFA_UnitPx2Pt(img_height, dpi_y)); CFX_RectF rtFit; pdfium::Optional width = TryWidth(); if (width) { rtFit.width = *width; GetWidthWithoutMargin(rtFit.width); } else { rtFit.width = rtImage.width; } pdfium::Optional height = TryHeight(); if (height) { rtFit.height = *height; GetHeightWithoutMargin(rtFit.height); } else { rtFit.height = rtImage.height; } return rtFit.Size(); } bool CXFA_WidgetAcc::CalculateImageAutoSize(CFX_SizeF& size) { if (!GetImageImage()) LoadImageImage(); size.clear(); RetainPtr pBitmap = GetImageImage(); if (!pBitmap) return CalculateWidgetAutoSize(size); int32_t iImageXDpi = 0; int32_t iImageYDpi = 0; GetImageDpi(iImageXDpi, iImageYDpi); size = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(), iImageXDpi, iImageYDpi); return CalculateWidgetAutoSize(size); } bool CXFA_WidgetAcc::CalculateImageEditAutoSize(CFX_SizeF& size) { if (!GetImageEditImage()) LoadImageEditImage(); size.clear(); RetainPtr pBitmap = GetImageEditImage(); if (!pBitmap) return CalculateFieldAutoSize(size); int32_t iImageXDpi = 0; int32_t iImageYDpi = 0; GetImageEditDpi(iImageXDpi, iImageYDpi); size = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(), iImageXDpi, iImageYDpi); return CalculateFieldAutoSize(size); } bool CXFA_WidgetAcc::LoadImageImage() { InitLayoutData(); return static_cast(m_pLayoutData.get()) ->LoadImageData(this); } bool CXFA_WidgetAcc::LoadImageEditImage() { InitLayoutData(); return static_cast(m_pLayoutData.get()) ->LoadImageData(this); } void CXFA_WidgetAcc::GetImageDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) { CXFA_ImageLayoutData* pData = static_cast(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(m_pLayoutData.get()); iImageXDpi = pData->m_iImageXDpi; iImageYDpi = pData->m_iImageYDpi; } bool CXFA_WidgetAcc::CalculateTextAutoSize(CFX_SizeF& size) { LoadText(); CXFA_TextLayout* pTextLayout = static_cast(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(m_pLayoutData.get())->LoadText(this); } float CXFA_WidgetAcc::CalculateWidgetAutoWidth(float fWidthCalc) { CXFA_MarginData marginData = GetMarginData(); if (marginData.HasValidNode()) fWidthCalc += marginData.GetLeftInset() + marginData.GetRightInset(); pdfium::Optional min = TryMinWidth(); if (min) fWidthCalc = std::max(fWidthCalc, *min); pdfium::Optional max = TryMaxWidth(); if (max && *max > 0) fWidthCalc = std::min(fWidthCalc, *max); return fWidthCalc; } float CXFA_WidgetAcc::GetWidthWithoutMargin(float fWidthCalc) { CXFA_MarginData marginData = GetMarginData(); if (marginData.HasValidNode()) fWidthCalc -= marginData.GetLeftInset() + marginData.GetRightInset(); return fWidthCalc; } float CXFA_WidgetAcc::CalculateWidgetAutoHeight(float fHeightCalc) { CXFA_MarginData marginData = GetMarginData(); if (marginData.HasValidNode()) fHeightCalc += marginData.GetTopInset() + marginData.GetBottomInset(); pdfium::Optional min = TryMinHeight(); if (min) fHeightCalc = std::max(fHeightCalc, *min); pdfium::Optional max = TryMaxHeight(); if (max && *max > 0) fHeightCalc = std::min(fHeightCalc, *max); return fHeightCalc; } float CXFA_WidgetAcc::GetHeightWithoutMargin(float fHeightCalc) { CXFA_MarginData marginData = GetMarginData(); if (marginData.HasValidNode()) fHeightCalc -= marginData.GetTopInset() + marginData.GetBottomInset(); return fHeightCalc; } void CXFA_WidgetAcc::StartWidgetLayout(float& fCalcWidth, float& fCalcHeight) { InitLayoutData(); XFA_Element eUIType = GetUIType(); if (eUIType == XFA_Element::Text) { m_pLayoutData->m_fWidgetHeight = TryHeight().value_or(-1); StartTextLayout(fCalcWidth, fCalcHeight); return; } if (fCalcWidth > 0 && fCalcHeight > 0) return; m_pLayoutData->m_fWidgetHeight = -1; float fWidth = 0; if (fCalcWidth > 0 && fCalcHeight < 0) { pdfium::Optional height = TryHeight(); if (height) fCalcHeight = *height; else CalculateAccWidthAndHeight(eUIType, fCalcWidth, fCalcHeight); m_pLayoutData->m_fWidgetHeight = fCalcHeight; return; } if (fCalcWidth < 0 && fCalcHeight < 0) { pdfium::Optional height; pdfium::Optional width = TryWidth(); if (width) { fWidth = *width; height = TryHeight(); if (height) fCalcHeight = *height; } if (!width || !height) 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.HasValidNode()) { fTopInset = marginData.GetTopInset(); fBottomInset = marginData.GetBottomInset(); } 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(m_pLayoutData.get())->GetTextLayout(); fCalcHeight = 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.HasValidNode() && 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(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) { // TODO(dsinclair): Inline fWidth when the 2nd param of // CalculateAccWidthAndHeight isn't a ref-param. float fWidth = TryWidth().value_or(0); CalculateAccWidthAndHeight(eUIType, fWidth, fHeight); } iLinesCount = pFieldData->m_pTextOut->GetTotalLines(); } std::vector* pFieldArray = &pFieldData->m_FieldSplitArray; int32_t iFieldSplitCount = pdfium::CollectionSize(*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); CXFA_ParaData paraData = GetParaData(); if (paraData.HasValidNode()) { 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; default: NOTREACHED(); 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() ->GetEnum(XFA_Attribute::Layout); 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(); return; case XFA_Element::TextEdit: m_pLayoutData = pdfium::MakeUnique(); return; case XFA_Element::Image: m_pLayoutData = pdfium::MakeUnique(); return; case XFA_Element::ImageEdit: m_pLayoutData = pdfium::MakeUnique(); return; default: break; } if (GetElementType() == XFA_Element::Field) { m_pLayoutData = pdfium::MakeUnique(); return; } m_pLayoutData = pdfium::MakeUnique(); } void CXFA_WidgetAcc::StartTextLayout(float& fCalcWidth, float& fCalcHeight) { LoadText(); CXFA_TextLayout* pTextLayout = static_cast(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) { pdfium::Optional width = TryWidth(); if (width) { pTextLayout->StartLayout(GetWidthWithoutMargin(*width)); fCalcWidth = *width; } else { float fMaxWidth = CalculateWidgetAutoWidth(pTextLayout->StartLayout(-1)); pTextLayout->StartLayout(GetWidthWithoutMargin(fMaxWidth)); 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(m_pLayoutData.get()) ->LoadCaption(this); } CXFA_TextLayout* CXFA_WidgetAcc::GetCaptionTextLayout() { return m_pLayoutData ? static_cast(m_pLayoutData.get()) ->m_pCapTextLayout.get() : nullptr; } CXFA_TextLayout* CXFA_WidgetAcc::GetTextLayout() { return m_pLayoutData ? static_cast(m_pLayoutData.get()) ->GetTextLayout() : nullptr; } RetainPtr CXFA_WidgetAcc::GetImageImage() { return m_pLayoutData ? static_cast(m_pLayoutData.get()) ->m_pDIBitmap : nullptr; } RetainPtr CXFA_WidgetAcc::GetImageEditImage() { return m_pLayoutData ? static_cast(m_pLayoutData.get()) ->m_pDIBitmap : nullptr; } void CXFA_WidgetAcc::SetImageImage(const RetainPtr& newImage) { CXFA_ImageLayoutData* pData = static_cast(m_pLayoutData.get()); if (pData->m_pDIBitmap != newImage) pData->m_pDIBitmap = newImage; } void CXFA_WidgetAcc::SetImageEditImage( const RetainPtr& newImage) { CXFA_ImageEditData* pData = static_cast(m_pLayoutData.get()); if (pData->m_pDIBitmap != newImage) pData->m_pDIBitmap = newImage; } RetainPtr CXFA_WidgetAcc::GetFDEFont() { WideString wsFontName = L"Courier"; uint32_t dwFontStyle = 0; CXFA_FontData fontData = GetFontData(false); if (fontData.HasValidNode()) { if (fontData.IsBold()) dwFontStyle |= FXFONT_BOLD; if (fontData.IsItalic()) dwFontStyle |= FXFONT_ITALIC; wsFontName = fontData.GetTypeface(); } auto* pDoc = GetDoc(); return pDoc->GetApp()->GetXFAFontMgr()->GetFont( pDoc, wsFontName.AsStringView(), dwFontStyle); } float CXFA_WidgetAcc::GetFontSize() { CXFA_FontData fontData = GetFontData(false); float fFontSize = fontData.HasValidNode() ? fontData.GetFontSize() : 10.0f; return fFontSize < 0.1f ? 10.0f : fFontSize; } float CXFA_WidgetAcc::GetLineHeight() { float fLineHeight = 0; CXFA_ParaData paraData = GetParaData(); if (paraData.HasValidNode()) fLineHeight = paraData.GetLineHeight(); if (fLineHeight < 1) fLineHeight = GetFontSize() * 1.2f; return fLineHeight; } FX_ARGB CXFA_WidgetAcc::GetTextColor() { CXFA_FontData fontData = GetFontData(false); return fontData.HasValidNode() ? fontData.GetColor() : 0xFF000000; }