Home | History | Annotate | Download | only in app
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "xfa/fxfa/app/xfa_ffwidgetacc.h"
      8 
      9 #include <algorithm>
     10 #include <memory>
     11 #include <vector>
     12 
     13 #include "fxjs/cfxjse_value.h"
     14 #include "third_party/base/ptr_util.h"
     15 #include "third_party/base/stl_util.h"
     16 #include "xfa/fde/tto/fde_textout.h"
     17 #include "xfa/fde/xml/fde_xml_imp.h"
     18 #include "xfa/fxfa/app/xfa_ffcheckbutton.h"
     19 #include "xfa/fxfa/app/xfa_ffchoicelist.h"
     20 #include "xfa/fxfa/app/xfa_fffield.h"
     21 #include "xfa/fxfa/app/xfa_fwladapter.h"
     22 #include "xfa/fxfa/cxfa_eventparam.h"
     23 #include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
     24 #include "xfa/fxfa/parser/cxfa_scriptcontext.h"
     25 #include "xfa/fxfa/parser/xfa_localevalue.h"
     26 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
     27 #include "xfa/fxfa/xfa_ffapp.h"
     28 #include "xfa/fxfa/xfa_ffdoc.h"
     29 #include "xfa/fxfa/xfa_ffdocview.h"
     30 #include "xfa/fxfa/xfa_ffpageview.h"
     31 #include "xfa/fxfa/xfa_ffwidget.h"
     32 #include "xfa/fxfa/xfa_fontmgr.h"
     33 
     34 static void XFA_FFDeleteCalcData(void* pData) {
     35   if (pData) {
     36     delete ((CXFA_CalcData*)pData);
     37   }
     38 }
     39 
     40 static XFA_MAPDATABLOCKCALLBACKINFO gs_XFADeleteCalcData = {
     41     XFA_FFDeleteCalcData, nullptr};
     42 
     43 class CXFA_WidgetLayoutData {
     44  public:
     45   CXFA_WidgetLayoutData() : m_fWidgetHeight(-1) {}
     46   virtual ~CXFA_WidgetLayoutData() {}
     47 
     48   FX_FLOAT m_fWidgetHeight;
     49 };
     50 
     51 class CXFA_TextLayoutData : public CXFA_WidgetLayoutData {
     52  public:
     53   CXFA_TextLayoutData() {}
     54   ~CXFA_TextLayoutData() override {}
     55 
     56   CXFA_TextLayout* GetTextLayout() const { return m_pTextLayout.get(); }
     57   CXFA_TextProvider* GetTextProvider() const { return m_pTextProvider.get(); }
     58 
     59   void LoadText(CXFA_WidgetAcc* pAcc) {
     60     if (m_pTextLayout)
     61       return;
     62 
     63     m_pTextProvider =
     64         pdfium::MakeUnique<CXFA_TextProvider>(pAcc, XFA_TEXTPROVIDERTYPE_Text);
     65     m_pTextLayout = pdfium::MakeUnique<CXFA_TextLayout>(m_pTextProvider.get());
     66   }
     67 
     68  private:
     69   std::unique_ptr<CXFA_TextLayout> m_pTextLayout;
     70   std::unique_ptr<CXFA_TextProvider> m_pTextProvider;
     71 };
     72 
     73 class CXFA_ImageLayoutData : public CXFA_WidgetLayoutData {
     74  public:
     75   CXFA_ImageLayoutData()
     76       : m_pDIBitmap(nullptr),
     77         m_bNamedImage(false),
     78         m_iImageXDpi(0),
     79         m_iImageYDpi(0) {}
     80 
     81   ~CXFA_ImageLayoutData() override {
     82     if (m_pDIBitmap && !m_bNamedImage)
     83       delete m_pDIBitmap;
     84   }
     85 
     86   bool LoadImageData(CXFA_WidgetAcc* pAcc) {
     87     if (m_pDIBitmap)
     88       return true;
     89 
     90     CXFA_Value value = pAcc->GetFormValue();
     91     if (!value)
     92       return false;
     93 
     94     CXFA_Image imageObj = value.GetImage();
     95     if (!imageObj)
     96       return false;
     97 
     98     CXFA_FFDoc* pFFDoc = pAcc->GetDoc();
     99     pAcc->SetImageImage(XFA_LoadImageData(pFFDoc, &imageObj, m_bNamedImage,
    100                                           m_iImageXDpi, m_iImageYDpi));
    101     return !!m_pDIBitmap;
    102   }
    103 
    104   CFX_DIBitmap* m_pDIBitmap;
    105   bool m_bNamedImage;
    106   int32_t m_iImageXDpi;
    107   int32_t m_iImageYDpi;
    108 };
    109 
    110 class CXFA_FieldLayoutData : public CXFA_WidgetLayoutData {
    111  public:
    112   CXFA_FieldLayoutData() {}
    113   ~CXFA_FieldLayoutData() override {}
    114 
    115   bool LoadCaption(CXFA_WidgetAcc* pAcc) {
    116     if (m_pCapTextLayout)
    117       return true;
    118     CXFA_Caption caption = pAcc->GetCaption();
    119     if (!caption || caption.GetPresence() == XFA_ATTRIBUTEENUM_Hidden)
    120       return false;
    121     m_pCapTextProvider.reset(
    122         new CXFA_TextProvider(pAcc, XFA_TEXTPROVIDERTYPE_Caption));
    123     m_pCapTextLayout =
    124         pdfium::MakeUnique<CXFA_TextLayout>(m_pCapTextProvider.get());
    125     return true;
    126   }
    127 
    128   std::unique_ptr<CXFA_TextLayout> m_pCapTextLayout;
    129   std::unique_ptr<CXFA_TextProvider> m_pCapTextProvider;
    130   std::unique_ptr<CFDE_TextOut> m_pTextOut;
    131   std::vector<FX_FLOAT> m_FieldSplitArray;
    132 };
    133 
    134 class CXFA_TextEditData : public CXFA_FieldLayoutData {
    135  public:
    136 };
    137 
    138 class CXFA_ImageEditData : public CXFA_FieldLayoutData {
    139  public:
    140   CXFA_ImageEditData()
    141       : m_pDIBitmap(nullptr),
    142         m_bNamedImage(false),
    143         m_iImageXDpi(0),
    144         m_iImageYDpi(0) {}
    145 
    146   ~CXFA_ImageEditData() override {
    147     if (m_pDIBitmap && !m_bNamedImage)
    148       delete m_pDIBitmap;
    149   }
    150 
    151   bool LoadImageData(CXFA_WidgetAcc* pAcc) {
    152     if (m_pDIBitmap)
    153       return true;
    154 
    155     CXFA_Value value = pAcc->GetFormValue();
    156     if (!value)
    157       return false;
    158 
    159     CXFA_Image imageObj = value.GetImage();
    160     CXFA_FFDoc* pFFDoc = pAcc->GetDoc();
    161     pAcc->SetImageEditImage(XFA_LoadImageData(pFFDoc, &imageObj, m_bNamedImage,
    162                                               m_iImageXDpi, m_iImageYDpi));
    163     return !!m_pDIBitmap;
    164   }
    165 
    166   CFX_DIBitmap* m_pDIBitmap;
    167   bool m_bNamedImage;
    168   int32_t m_iImageXDpi;
    169   int32_t m_iImageYDpi;
    170 };
    171 
    172 CXFA_WidgetAcc::CXFA_WidgetAcc(CXFA_FFDocView* pDocView, CXFA_Node* pNode)
    173     : CXFA_WidgetData(pNode),
    174       m_pDocView(pDocView),
    175       m_nRecursionDepth(0) {}
    176 
    177 CXFA_WidgetAcc::~CXFA_WidgetAcc() {}
    178 
    179 bool CXFA_WidgetAcc::GetName(CFX_WideString& wsName, int32_t iNameType) {
    180   if (iNameType == 0) {
    181     m_pNode->TryCData(XFA_ATTRIBUTE_Name, wsName);
    182     return !wsName.IsEmpty();
    183   }
    184   m_pNode->GetSOMExpression(wsName);
    185   if (iNameType == 2 && wsName.GetLength() >= 15) {
    186     CFX_WideStringC wsPre = L"xfa[0].form[0].";
    187     if (wsPre == CFX_WideStringC(wsName.c_str(), wsPre.GetLength())) {
    188       wsName.Delete(0, wsPre.GetLength());
    189     }
    190   }
    191   return true;
    192 }
    193 CXFA_Node* CXFA_WidgetAcc::GetDatasets() {
    194   return m_pNode->GetBindData();
    195 }
    196 bool CXFA_WidgetAcc::ProcessValueChanged() {
    197   m_pDocView->AddValidateWidget(this);
    198   m_pDocView->AddCalculateWidgetAcc(this);
    199   m_pDocView->RunCalculateWidgets();
    200   m_pDocView->RunValidate();
    201   return true;
    202 }
    203 void CXFA_WidgetAcc::ResetData() {
    204   CFX_WideString wsValue;
    205   XFA_Element eUIType = GetUIType();
    206   switch (eUIType) {
    207     case XFA_Element::ImageEdit: {
    208       CXFA_Value imageValue = GetDefaultValue();
    209       CXFA_Image image = imageValue.GetImage();
    210       CFX_WideString wsContentType, wsHref;
    211       if (image) {
    212         image.GetContent(wsValue);
    213         image.GetContentType(wsContentType);
    214         image.GetHref(wsHref);
    215       }
    216       SetImageEdit(wsContentType, wsHref, wsValue);
    217     } break;
    218     case XFA_Element::ExclGroup: {
    219       CXFA_Node* pNextChild = m_pNode->GetNodeItem(
    220           XFA_NODEITEM_FirstChild, XFA_ObjectType::ContainerNode);
    221       while (pNextChild) {
    222         CXFA_Node* pChild = pNextChild;
    223         CXFA_WidgetAcc* pAcc =
    224             static_cast<CXFA_WidgetAcc*>(pChild->GetWidgetData());
    225         if (!pAcc) {
    226           continue;
    227         }
    228         CXFA_Value defValue(nullptr);
    229         if (wsValue.IsEmpty() && (defValue = pAcc->GetDefaultValue())) {
    230           defValue.GetChildValueContent(wsValue);
    231           SetValue(wsValue, XFA_VALUEPICTURE_Raw);
    232           pAcc->SetValue(wsValue, XFA_VALUEPICTURE_Raw);
    233         } else {
    234           CXFA_Node* pItems = pChild->GetChild(0, XFA_Element::Items);
    235           if (!pItems) {
    236             continue;
    237           }
    238           CFX_WideString itemText;
    239           if (pItems->CountChildren(XFA_Element::Unknown) > 1) {
    240             itemText = pItems->GetChild(1, XFA_Element::Unknown)->GetContent();
    241           }
    242           pAcc->SetValue(itemText, XFA_VALUEPICTURE_Raw);
    243         }
    244         pNextChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling,
    245                                          XFA_ObjectType::ContainerNode);
    246       }
    247     } break;
    248     case XFA_Element::ChoiceList:
    249       ClearAllSelections();
    250     default:
    251       if (CXFA_Value defValue = GetDefaultValue()) {
    252         defValue.GetChildValueContent(wsValue);
    253       }
    254       SetValue(wsValue, XFA_VALUEPICTURE_Raw);
    255       break;
    256   }
    257 }
    258 void CXFA_WidgetAcc::SetImageEdit(const CFX_WideString& wsContentType,
    259                                   const CFX_WideString& wsHref,
    260                                   const CFX_WideString& wsData) {
    261   CXFA_Image image = GetFormValue().GetImage();
    262   if (image) {
    263     image.SetContentType(CFX_WideString(wsContentType));
    264     image.SetHref(wsHref);
    265   }
    266   CFX_WideString wsFormatValue(wsData);
    267   GetFormatDataValue(wsData, wsFormatValue);
    268   m_pNode->SetContent(wsData, wsFormatValue, true);
    269   CXFA_Node* pBind = GetDatasets();
    270   if (!pBind) {
    271     image.SetTransferEncoding(XFA_ATTRIBUTEENUM_Base64);
    272     return;
    273   }
    274   pBind->SetCData(XFA_ATTRIBUTE_ContentType, wsContentType);
    275   CXFA_Node* pHrefNode = pBind->GetNodeItem(XFA_NODEITEM_FirstChild);
    276   if (pHrefNode) {
    277     pHrefNode->SetCData(XFA_ATTRIBUTE_Value, wsHref);
    278   } else {
    279     CFDE_XMLNode* pXMLNode = pBind->GetXMLMappingNode();
    280     ASSERT(pXMLNode && pXMLNode->GetType() == FDE_XMLNODE_Element);
    281     static_cast<CFDE_XMLElement*>(pXMLNode)->SetString(L"href", wsHref);
    282   }
    283 }
    284 
    285 CXFA_WidgetAcc* CXFA_WidgetAcc::GetExclGroup() {
    286   CXFA_Node* pExcl = m_pNode->GetNodeItem(XFA_NODEITEM_Parent);
    287   if (!pExcl || pExcl->GetElementType() != XFA_Element::ExclGroup) {
    288     return nullptr;
    289   }
    290   return static_cast<CXFA_WidgetAcc*>(pExcl->GetWidgetData());
    291 }
    292 CXFA_FFDocView* CXFA_WidgetAcc::GetDocView() {
    293   return m_pDocView;
    294 }
    295 CXFA_FFDoc* CXFA_WidgetAcc::GetDoc() {
    296   return m_pDocView->GetDoc();
    297 }
    298 CXFA_FFApp* CXFA_WidgetAcc::GetApp() {
    299   return GetDoc()->GetApp();
    300 }
    301 IXFA_AppProvider* CXFA_WidgetAcc::GetAppProvider() {
    302   return GetApp()->GetAppProvider();
    303 }
    304 int32_t CXFA_WidgetAcc::ProcessEvent(int32_t iActivity,
    305                                      CXFA_EventParam* pEventParam) {
    306   if (GetElementType() == XFA_Element::Draw) {
    307     return XFA_EVENTERROR_NotExist;
    308   }
    309   int32_t iRet = XFA_EVENTERROR_NotExist;
    310   CXFA_NodeArray eventArray;
    311   int32_t iCounts =
    312       GetEventByActivity(iActivity, eventArray, pEventParam->m_bIsFormReady);
    313   for (int32_t i = 0; i < iCounts; i++) {
    314     CXFA_Event event(eventArray[i]);
    315     int32_t result = ProcessEvent(event, pEventParam);
    316     if (i == 0) {
    317       iRet = result;
    318     } else if (result == XFA_EVENTERROR_Success) {
    319       iRet = result;
    320     }
    321   }
    322   return iRet;
    323 }
    324 int32_t CXFA_WidgetAcc::ProcessEvent(CXFA_Event& event,
    325                                      CXFA_EventParam* pEventParam) {
    326   if (!event)
    327     return XFA_EVENTERROR_NotExist;
    328 
    329   switch (event.GetEventType()) {
    330     case XFA_Element::Execute:
    331       break;
    332     case XFA_Element::Script: {
    333       CXFA_Script script = event.GetScript();
    334       return ExecuteScript(script, pEventParam);
    335     } break;
    336     case XFA_Element::SignData:
    337       break;
    338     case XFA_Element::Submit: {
    339       CXFA_Submit submit = event.GetSubmit();
    340       return GetDoc()->GetDocEnvironment()->SubmitData(GetDoc(), submit);
    341     }
    342     default:
    343       break;
    344   }
    345   return XFA_EVENTERROR_NotExist;
    346 }
    347 
    348 int32_t CXFA_WidgetAcc::ProcessCalculate() {
    349   if (GetElementType() == XFA_Element::Draw)
    350     return XFA_EVENTERROR_NotExist;
    351 
    352   CXFA_Calculate calc = GetCalculate();
    353   if (!calc)
    354     return XFA_EVENTERROR_NotExist;
    355   if (GetNode()->IsUserInteractive())
    356     return XFA_EVENTERROR_Disabled;
    357 
    358   CXFA_EventParam EventParam;
    359   EventParam.m_eType = XFA_EVENT_Calculate;
    360   CXFA_Script script = calc.GetScript();
    361   int32_t iRet = ExecuteScript(script, &EventParam);
    362   if (iRet != XFA_EVENTERROR_Success)
    363     return iRet;
    364 
    365   if (GetRawValue() != EventParam.m_wsResult) {
    366     SetValue(EventParam.m_wsResult, XFA_VALUEPICTURE_Raw);
    367     UpdateUIDisplay();
    368   }
    369   return XFA_EVENTERROR_Success;
    370 }
    371 
    372 void CXFA_WidgetAcc::ProcessScriptTestValidate(CXFA_Validate validate,
    373                                                int32_t iRet,
    374                                                CFXJSE_Value* pRetValue,
    375                                                bool bVersionFlag) {
    376   if (iRet == XFA_EVENTERROR_Success && pRetValue) {
    377     if (pRetValue->IsBoolean() && !pRetValue->ToBoolean()) {
    378       IXFA_AppProvider* pAppProvider = GetAppProvider();
    379       if (!pAppProvider) {
    380         return;
    381       }
    382       CFX_WideString wsTitle = pAppProvider->GetAppTitle();
    383       CFX_WideString wsScriptMsg;
    384       validate.GetScriptMessageText(wsScriptMsg);
    385       int32_t eScriptTest = validate.GetScriptTest();
    386       if (eScriptTest == XFA_ATTRIBUTEENUM_Warning) {
    387         if (GetNode()->IsUserInteractive())
    388           return;
    389         if (wsScriptMsg.IsEmpty())
    390           wsScriptMsg = GetValidateMessage(false, bVersionFlag);
    391 
    392         if (bVersionFlag) {
    393           pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning,
    394                                XFA_MB_OK);
    395           return;
    396         }
    397         if (pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning,
    398                                  XFA_MB_YesNo) == XFA_IDYes) {
    399           GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false);
    400         }
    401       } else {
    402         if (wsScriptMsg.IsEmpty())
    403           wsScriptMsg = GetValidateMessage(true, bVersionFlag);
    404         pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK);
    405       }
    406     }
    407   }
    408 }
    409 int32_t CXFA_WidgetAcc::ProcessFormatTestValidate(CXFA_Validate validate,
    410                                                   bool bVersionFlag) {
    411   CFX_WideString wsRawValue = GetRawValue();
    412   if (!wsRawValue.IsEmpty()) {
    413     CFX_WideString wsPicture;
    414     validate.GetPicture(wsPicture);
    415     if (wsPicture.IsEmpty()) {
    416       return XFA_EVENTERROR_NotExist;
    417     }
    418     IFX_Locale* pLocale = GetLocal();
    419     if (!pLocale) {
    420       return XFA_EVENTERROR_NotExist;
    421     }
    422     CXFA_LocaleValue lcValue = XFA_GetLocaleValue(this);
    423     if (!lcValue.ValidateValue(lcValue.GetValue(), wsPicture, pLocale)) {
    424       IXFA_AppProvider* pAppProvider = GetAppProvider();
    425       if (!pAppProvider) {
    426         return XFA_EVENTERROR_NotExist;
    427       }
    428       CFX_WideString wsFormatMsg;
    429       validate.GetFormatMessageText(wsFormatMsg);
    430       CFX_WideString wsTitle = pAppProvider->GetAppTitle();
    431       int32_t eFormatTest = validate.GetFormatTest();
    432       if (eFormatTest == XFA_ATTRIBUTEENUM_Error) {
    433         if (wsFormatMsg.IsEmpty())
    434           wsFormatMsg = GetValidateMessage(true, bVersionFlag);
    435         pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK);
    436         return XFA_EVENTERROR_Success;
    437       }
    438       if (GetNode()->IsUserInteractive())
    439         return XFA_EVENTERROR_NotExist;
    440       if (wsFormatMsg.IsEmpty())
    441         wsFormatMsg = GetValidateMessage(false, bVersionFlag);
    442 
    443       if (bVersionFlag) {
    444         pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning,
    445                              XFA_MB_OK);
    446         return XFA_EVENTERROR_Success;
    447       }
    448       if (pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning,
    449                                XFA_MB_YesNo) == XFA_IDYes) {
    450         GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false);
    451       }
    452       return XFA_EVENTERROR_Success;
    453     }
    454   }
    455   return XFA_EVENTERROR_NotExist;
    456 }
    457 int32_t CXFA_WidgetAcc::ProcessNullTestValidate(CXFA_Validate validate,
    458                                                 int32_t iFlags,
    459                                                 bool bVersionFlag) {
    460   CFX_WideString wsValue;
    461   GetValue(wsValue, XFA_VALUEPICTURE_Raw);
    462   if (!wsValue.IsEmpty()) {
    463     return XFA_EVENTERROR_Success;
    464   }
    465   if (m_bIsNull && (m_bPreNull == m_bIsNull)) {
    466     return XFA_EVENTERROR_Success;
    467   }
    468   int32_t eNullTest = validate.GetNullTest();
    469   CFX_WideString wsNullMsg;
    470   validate.GetNullMessageText(wsNullMsg);
    471   if (iFlags & 0x01) {
    472     int32_t iRet = XFA_EVENTERROR_Success;
    473     if (eNullTest != XFA_ATTRIBUTEENUM_Disabled) {
    474       iRet = XFA_EVENTERROR_Error;
    475     }
    476     if (!wsNullMsg.IsEmpty()) {
    477       if (eNullTest != XFA_ATTRIBUTEENUM_Disabled) {
    478         m_pDocView->m_arrNullTestMsg.push_back(wsNullMsg);
    479         return XFA_EVENTERROR_Error;
    480       }
    481       return XFA_EVENTERROR_Success;
    482     }
    483     return iRet;
    484   }
    485   if (wsNullMsg.IsEmpty() && bVersionFlag &&
    486       eNullTest != XFA_ATTRIBUTEENUM_Disabled) {
    487     return XFA_EVENTERROR_Error;
    488   }
    489   IXFA_AppProvider* pAppProvider = GetAppProvider();
    490   if (!pAppProvider) {
    491     return XFA_EVENTERROR_NotExist;
    492   }
    493   CFX_WideString wsCaptionName;
    494   CFX_WideString wsTitle = pAppProvider->GetAppTitle();
    495   switch (eNullTest) {
    496     case XFA_ATTRIBUTEENUM_Error: {
    497       if (wsNullMsg.IsEmpty()) {
    498         wsCaptionName = GetValidateCaptionName(bVersionFlag);
    499         wsNullMsg.Format(L"%s cannot be blank.", wsCaptionName.c_str());
    500       }
    501       pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Status, XFA_MB_OK);
    502       return XFA_EVENTERROR_Error;
    503     }
    504     case XFA_ATTRIBUTEENUM_Warning: {
    505       if (GetNode()->IsUserInteractive())
    506         return true;
    507 
    508       if (wsNullMsg.IsEmpty()) {
    509         wsCaptionName = GetValidateCaptionName(bVersionFlag);
    510         wsNullMsg.Format(
    511             L"%s cannot be blank. To ignore validations for %s, click Ignore.",
    512             wsCaptionName.c_str(), wsCaptionName.c_str());
    513       }
    514       if (pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Warning,
    515                                XFA_MB_YesNo) == XFA_IDYes) {
    516         GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false);
    517       }
    518       return XFA_EVENTERROR_Error;
    519     }
    520     case XFA_ATTRIBUTEENUM_Disabled:
    521     default:
    522       break;
    523   }
    524   return XFA_EVENTERROR_Success;
    525 }
    526 
    527 CFX_WideString CXFA_WidgetAcc::GetValidateCaptionName(bool bVersionFlag) {
    528   CFX_WideString wsCaptionName;
    529 
    530   if (!bVersionFlag) {
    531     if (CXFA_Caption caption = GetCaption()) {
    532       if (CXFA_Value capValue = caption.GetValue()) {
    533         if (CXFA_Text capText = capValue.GetText())
    534           capText.GetContent(wsCaptionName);
    535       }
    536     }
    537   }
    538   if (wsCaptionName.IsEmpty())
    539     GetName(wsCaptionName);
    540 
    541   return wsCaptionName;
    542 }
    543 
    544 CFX_WideString CXFA_WidgetAcc::GetValidateMessage(bool bError,
    545                                                   bool bVersionFlag) {
    546   CFX_WideString wsCaptionName = GetValidateCaptionName(bVersionFlag);
    547   CFX_WideString wsMessage;
    548   if (bVersionFlag) {
    549     wsMessage.Format(L"%s validation failed", wsCaptionName.c_str());
    550     return wsMessage;
    551   }
    552   if (bError) {
    553     wsMessage.Format(L"The value you entered for %s is invalid.",
    554                      wsCaptionName.c_str());
    555     return wsMessage;
    556   }
    557   wsMessage.Format(
    558       L"The value you entered for %s is invalid. To ignore "
    559       L"validations for %s, click Ignore.",
    560       wsCaptionName.c_str(), wsCaptionName.c_str());
    561   return wsMessage;
    562 }
    563 
    564 int32_t CXFA_WidgetAcc::ProcessValidate(int32_t iFlags) {
    565   if (GetElementType() == XFA_Element::Draw) {
    566     return XFA_EVENTERROR_NotExist;
    567   }
    568   CXFA_Validate validate = GetValidate();
    569   if (!validate) {
    570     return XFA_EVENTERROR_NotExist;
    571   }
    572   bool bInitDoc = validate.GetNode()->NeedsInitApp();
    573   bool bStatus = m_pDocView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End;
    574   int32_t iFormat = 0;
    575   CFXJSE_Value* pRetValue = nullptr;
    576   int32_t iRet = XFA_EVENTERROR_NotExist;
    577   CXFA_Script script = validate.GetScript();
    578   if (script) {
    579     CXFA_EventParam eParam;
    580     eParam.m_eType = XFA_EVENT_Validate;
    581     eParam.m_pTarget = this;
    582     iRet = ExecuteScript(script, &eParam,
    583                          ((bInitDoc || bStatus) && GetRawValue().IsEmpty())
    584                              ? nullptr
    585                              : &pRetValue);
    586   }
    587   XFA_VERSION version = GetDoc()->GetXFADoc()->GetCurVersionMode();
    588   bool bVersionFlag = false;
    589   if (version < XFA_VERSION_208) {
    590     bVersionFlag = true;
    591   }
    592   if (bInitDoc) {
    593     validate.GetNode()->ClearFlag(XFA_NodeFlag_NeedsInitApp);
    594   } else {
    595     iFormat = ProcessFormatTestValidate(validate, bVersionFlag);
    596     if (!bVersionFlag) {
    597       bVersionFlag = GetDoc()->GetXFADoc()->HasFlag(XFA_DOCFLAG_Scripting);
    598     }
    599     iRet |= ProcessNullTestValidate(validate, iFlags, bVersionFlag);
    600   }
    601   if (iFormat != XFA_EVENTERROR_Success) {
    602     ProcessScriptTestValidate(validate, iRet, pRetValue, bVersionFlag);
    603   }
    604   delete pRetValue;
    605 
    606   return iRet | iFormat;
    607 }
    608 int32_t CXFA_WidgetAcc::ExecuteScript(CXFA_Script script,
    609                                       CXFA_EventParam* pEventParam,
    610                                       CFXJSE_Value** pRetValue) {
    611   static const uint32_t MAX_RECURSION_DEPTH = 2;
    612   if (m_nRecursionDepth > MAX_RECURSION_DEPTH)
    613     return XFA_EVENTERROR_Success;
    614   ASSERT(pEventParam);
    615   if (!script) {
    616     return XFA_EVENTERROR_NotExist;
    617   }
    618   if (script.GetRunAt() == XFA_ATTRIBUTEENUM_Server) {
    619     return XFA_EVENTERROR_Disabled;
    620   }
    621   CFX_WideString wsExpression;
    622   script.GetExpression(wsExpression);
    623   if (wsExpression.IsEmpty()) {
    624     return XFA_EVENTERROR_NotExist;
    625   }
    626   XFA_SCRIPTTYPE eScriptType = script.GetContentType();
    627   if (eScriptType == XFA_SCRIPTTYPE_Unkown) {
    628     return XFA_EVENTERROR_Success;
    629   }
    630   CXFA_FFDoc* pDoc = GetDoc();
    631   CXFA_ScriptContext* pContext = pDoc->GetXFADoc()->GetScriptContext();
    632   pContext->SetEventParam(*pEventParam);
    633   pContext->SetRunAtType((XFA_ATTRIBUTEENUM)script.GetRunAt());
    634   CXFA_NodeArray refNodes;
    635   if (pEventParam->m_eType == XFA_EVENT_InitCalculate ||
    636       pEventParam->m_eType == XFA_EVENT_Calculate) {
    637     pContext->SetNodesOfRunScript(&refNodes);
    638   }
    639   std::unique_ptr<CFXJSE_Value> pTmpRetValue(
    640       new CFXJSE_Value(pContext->GetRuntime()));
    641   ++m_nRecursionDepth;
    642   bool bRet = pContext->RunScript((XFA_SCRIPTLANGTYPE)eScriptType,
    643                                   wsExpression.AsStringC(), pTmpRetValue.get(),
    644                                   m_pNode);
    645   --m_nRecursionDepth;
    646   int32_t iRet = XFA_EVENTERROR_Error;
    647   if (bRet) {
    648     iRet = XFA_EVENTERROR_Success;
    649     if (pEventParam->m_eType == XFA_EVENT_Calculate ||
    650         pEventParam->m_eType == XFA_EVENT_InitCalculate) {
    651       if (!pTmpRetValue->IsUndefined()) {
    652         if (!pTmpRetValue->IsNull())
    653           pEventParam->m_wsResult = pTmpRetValue->ToWideString();
    654 
    655         iRet = XFA_EVENTERROR_Success;
    656       } else {
    657         iRet = XFA_EVENTERROR_Error;
    658       }
    659       if (pEventParam->m_eType == XFA_EVENT_InitCalculate) {
    660         if ((iRet == XFA_EVENTERROR_Success) &&
    661             (GetRawValue() != pEventParam->m_wsResult)) {
    662           SetValue(pEventParam->m_wsResult, XFA_VALUEPICTURE_Raw);
    663           m_pDocView->AddValidateWidget(this);
    664         }
    665       }
    666       int32_t iRefs = refNodes.GetSize();
    667       for (int32_t r = 0; r < iRefs; r++) {
    668         CXFA_WidgetAcc* pRefAcc =
    669             static_cast<CXFA_WidgetAcc*>(refNodes[r]->GetWidgetData());
    670         if (pRefAcc && pRefAcc == this) {
    671           continue;
    672         }
    673         CXFA_Node* pRefNode = refNodes[r];
    674         CXFA_CalcData* pGlobalData =
    675             (CXFA_CalcData*)pRefNode->GetUserData(XFA_CalcData);
    676         if (!pGlobalData) {
    677           pGlobalData = new CXFA_CalcData;
    678           pRefNode->SetUserData(XFA_CalcData, pGlobalData,
    679                                 &gs_XFADeleteCalcData);
    680         }
    681         if (!pdfium::ContainsValue(pGlobalData->m_Globals, this))
    682           pGlobalData->m_Globals.push_back(this);
    683       }
    684     }
    685   }
    686   if (pRetValue)
    687     *pRetValue = pTmpRetValue.release();
    688 
    689   pContext->SetNodesOfRunScript(nullptr);
    690   return iRet;
    691 }
    692 CXFA_FFWidget* CXFA_WidgetAcc::GetNextWidget(CXFA_FFWidget* pWidget) {
    693   CXFA_LayoutItem* pLayout = nullptr;
    694   if (pWidget) {
    695     pLayout = pWidget->GetNext();
    696   } else {
    697     pLayout = m_pDocView->GetXFALayout()->GetLayoutItem(m_pNode);
    698   }
    699   return static_cast<CXFA_FFWidget*>(pLayout);
    700 }
    701 void CXFA_WidgetAcc::UpdateUIDisplay(CXFA_FFWidget* pExcept) {
    702   CXFA_FFWidget* pWidget = nullptr;
    703   while ((pWidget = GetNextWidget(pWidget)) != nullptr) {
    704     if (pWidget == pExcept || !pWidget->IsLoaded() ||
    705         (GetUIType() != XFA_Element::CheckButton && pWidget->IsFocused())) {
    706       continue;
    707     }
    708     pWidget->UpdateFWLData();
    709     pWidget->AddInvalidateRect();
    710   }
    711 }
    712 
    713 void CXFA_WidgetAcc::CalcCaptionSize(CFX_SizeF& szCap) {
    714   CXFA_Caption caption = GetCaption();
    715   if (!caption || caption.GetPresence() != XFA_ATTRIBUTEENUM_Visible) {
    716     return;
    717   }
    718   LoadCaption();
    719   XFA_Element eUIType = GetUIType();
    720   int32_t iCapPlacement = caption.GetPlacementType();
    721   FX_FLOAT fCapReserve = caption.GetReserve();
    722   const bool bVert = iCapPlacement == XFA_ATTRIBUTEENUM_Top ||
    723                      iCapPlacement == XFA_ATTRIBUTEENUM_Bottom;
    724   const bool bReserveExit = fCapReserve > 0.01;
    725   CXFA_TextLayout* pCapTextLayout =
    726       static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get())
    727           ->m_pCapTextLayout.get();
    728   if (pCapTextLayout) {
    729     if (!bVert && eUIType != XFA_Element::Button) {
    730       szCap.width = fCapReserve;
    731     }
    732     CFX_SizeF minSize;
    733     pCapTextLayout->CalcSize(minSize, szCap, szCap);
    734     if (bReserveExit) {
    735       bVert ? szCap.height = fCapReserve : szCap.width = fCapReserve;
    736     }
    737   } else {
    738     FX_FLOAT fFontSize = 10.0f;
    739     if (CXFA_Font font = caption.GetFont()) {
    740       fFontSize = font.GetFontSize();
    741     } else if (CXFA_Font widgetfont = GetFont()) {
    742       fFontSize = widgetfont.GetFontSize();
    743     }
    744     if (bVert) {
    745       szCap.height = fCapReserve > 0 ? fCapReserve : fFontSize;
    746     } else {
    747       szCap.width = fCapReserve > 0 ? fCapReserve : 0;
    748       szCap.height = fFontSize;
    749     }
    750   }
    751   if (CXFA_Margin mgCap = caption.GetMargin()) {
    752     FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset;
    753     mgCap.GetLeftInset(fLeftInset);
    754     mgCap.GetTopInset(fTopInset);
    755     mgCap.GetRightInset(fRightInset);
    756     mgCap.GetBottomInset(fBottomInset);
    757     if (bReserveExit) {
    758       bVert ? (szCap.width += fLeftInset + fRightInset)
    759             : (szCap.height += fTopInset + fBottomInset);
    760     } else {
    761       szCap.width += fLeftInset + fRightInset;
    762       szCap.height += fTopInset + fBottomInset;
    763     }
    764   }
    765 }
    766 bool CXFA_WidgetAcc::CalculateFieldAutoSize(CFX_SizeF& size) {
    767   CFX_SizeF szCap;
    768   CalcCaptionSize(szCap);
    769   CFX_RectF rtUIMargin = GetUIMargin();
    770   size.width += rtUIMargin.left + rtUIMargin.width;
    771   size.height += rtUIMargin.top + rtUIMargin.height;
    772   if (szCap.width > 0 && szCap.height > 0) {
    773     int32_t iCapPlacement = GetCaption().GetPlacementType();
    774     switch (iCapPlacement) {
    775       case XFA_ATTRIBUTEENUM_Left:
    776       case XFA_ATTRIBUTEENUM_Right:
    777       case XFA_ATTRIBUTEENUM_Inline: {
    778         size.width += szCap.width;
    779         size.height = std::max(size.height, szCap.height);
    780       } break;
    781       case XFA_ATTRIBUTEENUM_Top:
    782       case XFA_ATTRIBUTEENUM_Bottom: {
    783         size.height += szCap.height;
    784         size.width = std::max(size.width, szCap.width);
    785       }
    786       default:
    787         break;
    788     }
    789   }
    790   return CalculateWidgetAutoSize(size);
    791 }
    792 bool CXFA_WidgetAcc::CalculateWidgetAutoSize(CFX_SizeF& size) {
    793   CXFA_Margin mgWidget = GetMargin();
    794   if (mgWidget) {
    795     FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset;
    796     mgWidget.GetLeftInset(fLeftInset);
    797     mgWidget.GetTopInset(fTopInset);
    798     mgWidget.GetRightInset(fRightInset);
    799     mgWidget.GetBottomInset(fBottomInset);
    800     size.width += fLeftInset + fRightInset;
    801     size.height += fTopInset + fBottomInset;
    802   }
    803   CXFA_Para para = GetPara();
    804   if (para)
    805     size.width += para.GetMarginLeft() + para.GetTextIndent();
    806 
    807   FX_FLOAT fVal = 0;
    808   FX_FLOAT fMin = 0;
    809   FX_FLOAT fMax = 0;
    810   if (GetWidth(fVal)) {
    811     size.width = fVal;
    812   } else {
    813     if (GetMinWidth(fMin))
    814       size.width = std::max(size.width, fMin);
    815     if (GetMaxWidth(fMax) && fMax > 0)
    816       size.width = std::min(size.width, fMax);
    817   }
    818   fVal = 0;
    819   fMin = 0;
    820   fMax = 0;
    821   if (GetHeight(fVal)) {
    822     size.height = fVal;
    823   } else {
    824     if (GetMinHeight(fMin))
    825       size.height = std::max(size.height, fMin);
    826     if (GetMaxHeight(fMax) && fMax > 0)
    827       size.height = std::min(size.height, fMax);
    828   }
    829   return true;
    830 }
    831 
    832 void CXFA_WidgetAcc::CalculateTextContentSize(CFX_SizeF& size) {
    833   FX_FLOAT fFontSize = GetFontSize();
    834   CFX_WideString wsText;
    835   GetValue(wsText, XFA_VALUEPICTURE_Display);
    836   if (wsText.IsEmpty()) {
    837     size.height += fFontSize;
    838     return;
    839   }
    840 
    841   FX_WCHAR wcEnter = '\n';
    842   FX_WCHAR wsLast = wsText.GetAt(wsText.GetLength() - 1);
    843   if (wsLast == wcEnter) {
    844     wsText = wsText + wcEnter;
    845   }
    846 
    847   CXFA_FieldLayoutData* layoutData =
    848       static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get());
    849   if (!layoutData->m_pTextOut) {
    850     layoutData->m_pTextOut = pdfium::MakeUnique<CFDE_TextOut>();
    851     CFDE_TextOut* pTextOut = layoutData->m_pTextOut.get();
    852     pTextOut->SetFont(GetFDEFont());
    853     pTextOut->SetFontSize(fFontSize);
    854     pTextOut->SetLineBreakTolerance(fFontSize * 0.2f);
    855     pTextOut->SetLineSpace(GetLineHeight());
    856     uint32_t dwStyles = FDE_TTOSTYLE_LastLineHeight;
    857     if (GetUIType() == XFA_Element::TextEdit && IsMultiLine()) {
    858       dwStyles |= FDE_TTOSTYLE_LineWrap;
    859     }
    860     pTextOut->SetStyles(dwStyles);
    861   }
    862   layoutData->m_pTextOut->CalcLogicSize(wsText.c_str(), wsText.GetLength(),
    863                                         size);
    864 }
    865 bool CXFA_WidgetAcc::CalculateTextEditAutoSize(CFX_SizeF& size) {
    866   if (size.width > 0) {
    867     CFX_SizeF szOrz = size;
    868     CFX_SizeF szCap;
    869     CalcCaptionSize(szCap);
    870     bool bCapExit = szCap.width > 0.01 && szCap.height > 0.01;
    871     int32_t iCapPlacement = XFA_ATTRIBUTEENUM_Unknown;
    872     if (bCapExit) {
    873       iCapPlacement = GetCaption().GetPlacementType();
    874       switch (iCapPlacement) {
    875         case XFA_ATTRIBUTEENUM_Left:
    876         case XFA_ATTRIBUTEENUM_Right:
    877         case XFA_ATTRIBUTEENUM_Inline: {
    878           size.width -= szCap.width;
    879         }
    880         default:
    881           break;
    882       }
    883     }
    884     CFX_RectF rtUIMargin = GetUIMargin();
    885     size.width -= rtUIMargin.left + rtUIMargin.width;
    886     CXFA_Margin mgWidget = GetMargin();
    887     if (mgWidget) {
    888       FX_FLOAT fLeftInset, fRightInset;
    889       mgWidget.GetLeftInset(fLeftInset);
    890       mgWidget.GetRightInset(fRightInset);
    891       size.width -= fLeftInset + fRightInset;
    892     }
    893     CalculateTextContentSize(size);
    894     size.height += rtUIMargin.top + rtUIMargin.height;
    895     if (bCapExit) {
    896       switch (iCapPlacement) {
    897         case XFA_ATTRIBUTEENUM_Left:
    898         case XFA_ATTRIBUTEENUM_Right:
    899         case XFA_ATTRIBUTEENUM_Inline: {
    900           size.height = std::max(size.height, szCap.height);
    901         } break;
    902         case XFA_ATTRIBUTEENUM_Top:
    903         case XFA_ATTRIBUTEENUM_Bottom: {
    904           size.height += szCap.height;
    905         }
    906         default:
    907           break;
    908       }
    909     }
    910     size.width = szOrz.width;
    911     return CalculateWidgetAutoSize(size);
    912   }
    913   CalculateTextContentSize(size);
    914   return CalculateFieldAutoSize(size);
    915 }
    916 bool CXFA_WidgetAcc::CalculateCheckButtonAutoSize(CFX_SizeF& size) {
    917   FX_FLOAT fCheckSize = GetCheckButtonSize();
    918   size = CFX_SizeF(fCheckSize, fCheckSize);
    919   return CalculateFieldAutoSize(size);
    920 }
    921 bool CXFA_WidgetAcc::CalculatePushButtonAutoSize(CFX_SizeF& size) {
    922   CalcCaptionSize(size);
    923   return CalculateWidgetAutoSize(size);
    924 }
    925 bool CXFA_WidgetAcc::CalculateImageAutoSize(CFX_SizeF& size) {
    926   if (!GetImageImage()) {
    927     LoadImageImage();
    928   }
    929   size.clear();
    930   if (CFX_DIBitmap* pBitmap = GetImageImage()) {
    931     int32_t iImageXDpi = 0;
    932     int32_t iImageYDpi = 0;
    933     GetImageDpi(iImageXDpi, iImageYDpi);
    934     CFX_RectF rtImage(
    935         0, 0,
    936         XFA_UnitPx2Pt((FX_FLOAT)pBitmap->GetWidth(), (FX_FLOAT)iImageXDpi),
    937         XFA_UnitPx2Pt((FX_FLOAT)pBitmap->GetHeight(), (FX_FLOAT)iImageYDpi));
    938 
    939     CFX_RectF rtFit;
    940     if (GetWidth(rtFit.width)) {
    941       GetWidthWithoutMargin(rtFit.width);
    942     } else {
    943       rtFit.width = rtImage.width;
    944     }
    945     if (GetHeight(rtFit.height)) {
    946       GetHeightWithoutMargin(rtFit.height);
    947     } else {
    948       rtFit.height = rtImage.height;
    949     }
    950     size = rtFit.Size();
    951   }
    952   return CalculateWidgetAutoSize(size);
    953 }
    954 bool CXFA_WidgetAcc::CalculateImageEditAutoSize(CFX_SizeF& size) {
    955   if (!GetImageEditImage()) {
    956     LoadImageEditImage();
    957   }
    958   size.clear();
    959   if (CFX_DIBitmap* pBitmap = GetImageEditImage()) {
    960     int32_t iImageXDpi = 0;
    961     int32_t iImageYDpi = 0;
    962     GetImageEditDpi(iImageXDpi, iImageYDpi);
    963     CFX_RectF rtImage(
    964         0, 0,
    965         XFA_UnitPx2Pt((FX_FLOAT)pBitmap->GetWidth(), (FX_FLOAT)iImageXDpi),
    966         XFA_UnitPx2Pt((FX_FLOAT)pBitmap->GetHeight(), (FX_FLOAT)iImageYDpi));
    967 
    968     CFX_RectF rtFit;
    969     if (GetWidth(rtFit.width)) {
    970       GetWidthWithoutMargin(rtFit.width);
    971     } else {
    972       rtFit.width = rtImage.width;
    973     }
    974     if (GetHeight(rtFit.height)) {
    975       GetHeightWithoutMargin(rtFit.height);
    976     } else {
    977       rtFit.height = rtImage.height;
    978     }
    979     size.width = rtFit.width;
    980     size.height = rtFit.height;
    981   }
    982   return CalculateFieldAutoSize(size);
    983 }
    984 bool CXFA_WidgetAcc::LoadImageImage() {
    985   InitLayoutData();
    986   return static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get())
    987       ->LoadImageData(this);
    988 }
    989 bool CXFA_WidgetAcc::LoadImageEditImage() {
    990   InitLayoutData();
    991   return static_cast<CXFA_ImageEditData*>(m_pLayoutData.get())
    992       ->LoadImageData(this);
    993 }
    994 void CXFA_WidgetAcc::GetImageDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) {
    995   CXFA_ImageLayoutData* pData =
    996       static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get());
    997   iImageXDpi = pData->m_iImageXDpi;
    998   iImageYDpi = pData->m_iImageYDpi;
    999 }
   1000 void CXFA_WidgetAcc::GetImageEditDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) {
   1001   CXFA_ImageEditData* pData =
   1002       static_cast<CXFA_ImageEditData*>(m_pLayoutData.get());
   1003   iImageXDpi = pData->m_iImageXDpi;
   1004   iImageYDpi = pData->m_iImageYDpi;
   1005 }
   1006 bool CXFA_WidgetAcc::CalculateTextAutoSize(CFX_SizeF& size) {
   1007   LoadText();
   1008   CXFA_TextLayout* pTextLayout =
   1009       static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout();
   1010   if (pTextLayout) {
   1011     size.width = pTextLayout->StartLayout(size.width);
   1012     size.height = pTextLayout->GetLayoutHeight();
   1013   }
   1014   return CalculateWidgetAutoSize(size);
   1015 }
   1016 void CXFA_WidgetAcc::LoadText() {
   1017   InitLayoutData();
   1018   static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->LoadText(this);
   1019 }
   1020 FX_FLOAT CXFA_WidgetAcc::CalculateWidgetAutoWidth(FX_FLOAT fWidthCalc) {
   1021   CXFA_Margin mgWidget = GetMargin();
   1022   if (mgWidget) {
   1023     FX_FLOAT fLeftInset, fRightInset;
   1024     mgWidget.GetLeftInset(fLeftInset);
   1025     mgWidget.GetRightInset(fRightInset);
   1026     fWidthCalc += fLeftInset + fRightInset;
   1027   }
   1028   FX_FLOAT fMin = 0, fMax = 0;
   1029   if (GetMinWidth(fMin)) {
   1030     fWidthCalc = std::max(fWidthCalc, fMin);
   1031   }
   1032   if (GetMaxWidth(fMax) && fMax > 0) {
   1033     fWidthCalc = std::min(fWidthCalc, fMax);
   1034   }
   1035   return fWidthCalc;
   1036 }
   1037 FX_FLOAT CXFA_WidgetAcc::GetWidthWithoutMargin(FX_FLOAT fWidthCalc) {
   1038   CXFA_Margin mgWidget = GetMargin();
   1039   if (mgWidget) {
   1040     FX_FLOAT fLeftInset, fRightInset;
   1041     mgWidget.GetLeftInset(fLeftInset);
   1042     mgWidget.GetRightInset(fRightInset);
   1043     fWidthCalc -= fLeftInset + fRightInset;
   1044   }
   1045   return fWidthCalc;
   1046 }
   1047 FX_FLOAT CXFA_WidgetAcc::CalculateWidgetAutoHeight(FX_FLOAT fHeightCalc) {
   1048   CXFA_Margin mgWidget = GetMargin();
   1049   if (mgWidget) {
   1050     FX_FLOAT fTopInset, fBottomInset;
   1051     mgWidget.GetTopInset(fTopInset);
   1052     mgWidget.GetBottomInset(fBottomInset);
   1053     fHeightCalc += fTopInset + fBottomInset;
   1054   }
   1055   FX_FLOAT fMin = 0, fMax = 0;
   1056   if (GetMinHeight(fMin)) {
   1057     fHeightCalc = std::max(fHeightCalc, fMin);
   1058   }
   1059   if (GetMaxHeight(fMax) && fMax > 0) {
   1060     fHeightCalc = std::min(fHeightCalc, fMax);
   1061   }
   1062   return fHeightCalc;
   1063 }
   1064 FX_FLOAT CXFA_WidgetAcc::GetHeightWithoutMargin(FX_FLOAT fHeightCalc) {
   1065   CXFA_Margin mgWidget = GetMargin();
   1066   if (mgWidget) {
   1067     FX_FLOAT fTopInset, fBottomInset;
   1068     mgWidget.GetTopInset(fTopInset);
   1069     mgWidget.GetBottomInset(fBottomInset);
   1070     fHeightCalc -= fTopInset + fBottomInset;
   1071   }
   1072   return fHeightCalc;
   1073 }
   1074 void CXFA_WidgetAcc::StartWidgetLayout(FX_FLOAT& fCalcWidth,
   1075                                        FX_FLOAT& fCalcHeight) {
   1076   InitLayoutData();
   1077   XFA_Element eUIType = GetUIType();
   1078   if (eUIType == XFA_Element::Text) {
   1079     m_pLayoutData->m_fWidgetHeight = -1;
   1080     GetHeight(m_pLayoutData->m_fWidgetHeight);
   1081     StartTextLayout(fCalcWidth, fCalcHeight);
   1082     return;
   1083   }
   1084   if (fCalcWidth > 0 && fCalcHeight > 0) {
   1085     return;
   1086   }
   1087   m_pLayoutData->m_fWidgetHeight = -1;
   1088   FX_FLOAT fWidth = 0;
   1089   if (fCalcWidth > 0 && fCalcHeight < 0) {
   1090     if (!GetHeight(fCalcHeight)) {
   1091       CalculateAccWidthAndHeight(eUIType, fCalcWidth, fCalcHeight);
   1092     }
   1093     m_pLayoutData->m_fWidgetHeight = fCalcHeight;
   1094     return;
   1095   }
   1096   if (fCalcWidth < 0 && fCalcHeight < 0) {
   1097     if (!GetWidth(fWidth) || !GetHeight(fCalcHeight)) {
   1098       CalculateAccWidthAndHeight(eUIType, fWidth, fCalcHeight);
   1099     }
   1100     fCalcWidth = fWidth;
   1101   }
   1102   m_pLayoutData->m_fWidgetHeight = fCalcHeight;
   1103 }
   1104 void CXFA_WidgetAcc::CalculateAccWidthAndHeight(XFA_Element eUIType,
   1105                                                 FX_FLOAT& fWidth,
   1106                                                 FX_FLOAT& fCalcHeight) {
   1107   CFX_SizeF sz(fWidth, m_pLayoutData->m_fWidgetHeight);
   1108   switch (eUIType) {
   1109     case XFA_Element::Barcode:
   1110     case XFA_Element::ChoiceList:
   1111     case XFA_Element::Signature:
   1112       CalculateFieldAutoSize(sz);
   1113       break;
   1114     case XFA_Element::ImageEdit:
   1115       CalculateImageEditAutoSize(sz);
   1116       break;
   1117     case XFA_Element::Button:
   1118       CalculatePushButtonAutoSize(sz);
   1119       break;
   1120     case XFA_Element::CheckButton:
   1121       CalculateCheckButtonAutoSize(sz);
   1122       break;
   1123     case XFA_Element::DateTimeEdit:
   1124     case XFA_Element::NumericEdit:
   1125     case XFA_Element::PasswordEdit:
   1126     case XFA_Element::TextEdit:
   1127       CalculateTextEditAutoSize(sz);
   1128       break;
   1129     case XFA_Element::Image:
   1130       CalculateImageAutoSize(sz);
   1131       break;
   1132     case XFA_Element::Arc:
   1133     case XFA_Element::Line:
   1134     case XFA_Element::Rectangle:
   1135     case XFA_Element::Subform:
   1136     case XFA_Element::ExclGroup:
   1137       CalculateWidgetAutoSize(sz);
   1138       break;
   1139     default:
   1140       break;
   1141   }
   1142   fWidth = sz.width;
   1143   m_pLayoutData->m_fWidgetHeight = sz.height;
   1144   fCalcHeight = sz.height;
   1145 }
   1146 bool CXFA_WidgetAcc::FindSplitPos(int32_t iBlockIndex, FX_FLOAT& fCalcHeight) {
   1147   XFA_Element eUIType = GetUIType();
   1148   if (eUIType == XFA_Element::Subform) {
   1149     return false;
   1150   }
   1151   if (eUIType != XFA_Element::Text && eUIType != XFA_Element::TextEdit &&
   1152       eUIType != XFA_Element::NumericEdit &&
   1153       eUIType != XFA_Element::PasswordEdit) {
   1154     fCalcHeight = 0;
   1155     return true;
   1156   }
   1157   FX_FLOAT fTopInset = 0;
   1158   FX_FLOAT fBottomInset = 0;
   1159   if (iBlockIndex == 0) {
   1160     CXFA_Margin mgWidget = GetMargin();
   1161     if (mgWidget) {
   1162       mgWidget.GetTopInset(fTopInset);
   1163       mgWidget.GetBottomInset(fBottomInset);
   1164     }
   1165     CFX_RectF rtUIMargin = GetUIMargin();
   1166     fTopInset += rtUIMargin.top;
   1167     fBottomInset += rtUIMargin.width;
   1168   }
   1169   if (eUIType == XFA_Element::Text) {
   1170     FX_FLOAT fHeight = fCalcHeight;
   1171     if (iBlockIndex == 0) {
   1172       fCalcHeight = fCalcHeight - fTopInset;
   1173       if (fCalcHeight < 0) {
   1174         fCalcHeight = 0;
   1175       }
   1176     }
   1177     CXFA_TextLayout* pTextLayout =
   1178         static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout();
   1179     pTextLayout->DoLayout(iBlockIndex, fCalcHeight, fCalcHeight,
   1180                           m_pLayoutData->m_fWidgetHeight - fTopInset);
   1181     if (fCalcHeight != 0) {
   1182       if (iBlockIndex == 0) {
   1183         fCalcHeight = fCalcHeight + fTopInset;
   1184       }
   1185       if (fabs(fHeight - fCalcHeight) < XFA_FLOAT_PERCISION) {
   1186         return false;
   1187       }
   1188     }
   1189     return true;
   1190   }
   1191   XFA_ATTRIBUTEENUM iCapPlacement = XFA_ATTRIBUTEENUM_Unknown;
   1192   FX_FLOAT fCapReserve = 0;
   1193   if (iBlockIndex == 0) {
   1194     CXFA_Caption caption = GetCaption();
   1195     if (caption && caption.GetPresence() != XFA_ATTRIBUTEENUM_Hidden) {
   1196       iCapPlacement = (XFA_ATTRIBUTEENUM)caption.GetPlacementType();
   1197       fCapReserve = caption.GetReserve();
   1198     }
   1199     if (iCapPlacement == XFA_ATTRIBUTEENUM_Top &&
   1200         fCalcHeight < fCapReserve + fTopInset) {
   1201       fCalcHeight = 0;
   1202       return true;
   1203     }
   1204     if (iCapPlacement == XFA_ATTRIBUTEENUM_Bottom &&
   1205         m_pLayoutData->m_fWidgetHeight - fCapReserve - fBottomInset) {
   1206       fCalcHeight = 0;
   1207       return true;
   1208     }
   1209     if (iCapPlacement != XFA_ATTRIBUTEENUM_Top) {
   1210       fCapReserve = 0;
   1211     }
   1212   }
   1213   CXFA_FieldLayoutData* pFieldData =
   1214       static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get());
   1215   int32_t iLinesCount = 0;
   1216   FX_FLOAT fHeight = m_pLayoutData->m_fWidgetHeight;
   1217   CFX_WideString wsText;
   1218   GetValue(wsText, XFA_VALUEPICTURE_Display);
   1219   if (wsText.IsEmpty()) {
   1220     iLinesCount = 1;
   1221   } else {
   1222     if (!pFieldData->m_pTextOut) {
   1223       FX_FLOAT fWidth = 0;
   1224       GetWidth(fWidth);
   1225       CalculateAccWidthAndHeight(eUIType, fWidth, fHeight);
   1226     }
   1227     iLinesCount = pFieldData->m_pTextOut->GetTotalLines();
   1228   }
   1229   std::vector<FX_FLOAT>* pFieldArray = &pFieldData->m_FieldSplitArray;
   1230   int32_t iFieldSplitCount = pdfium::CollectionSize<int32_t>(*pFieldArray);
   1231   for (int32_t i = 0; i < iBlockIndex * 3; i += 3) {
   1232     iLinesCount -= (int32_t)(*pFieldArray)[i + 1];
   1233     fHeight -= (*pFieldArray)[i + 2];
   1234   }
   1235   if (iLinesCount == 0) {
   1236     return false;
   1237   }
   1238   FX_FLOAT fLineHeight = GetLineHeight();
   1239   FX_FLOAT fFontSize = GetFontSize();
   1240   FX_FLOAT fTextHeight = iLinesCount * fLineHeight - fLineHeight + fFontSize;
   1241   FX_FLOAT fSpaceAbove = 0;
   1242   FX_FLOAT fStartOffset = 0;
   1243   if (fHeight > 0.1f && iBlockIndex == 0) {
   1244     fStartOffset = fTopInset;
   1245     fHeight -= (fTopInset + fBottomInset);
   1246     if (CXFA_Para para = GetPara()) {
   1247       fSpaceAbove = para.GetSpaceAbove();
   1248       FX_FLOAT fSpaceBelow = para.GetSpaceBelow();
   1249       fHeight -= (fSpaceAbove + fSpaceBelow);
   1250       switch (para.GetVerticalAlign()) {
   1251         case XFA_ATTRIBUTEENUM_Top:
   1252           fStartOffset += fSpaceAbove;
   1253           break;
   1254         case XFA_ATTRIBUTEENUM_Middle:
   1255           fStartOffset += ((fHeight - fTextHeight) / 2 + fSpaceAbove);
   1256           break;
   1257         case XFA_ATTRIBUTEENUM_Bottom:
   1258           fStartOffset += (fHeight - fTextHeight + fSpaceAbove);
   1259           break;
   1260       }
   1261     }
   1262     if (fStartOffset < 0.1f)
   1263       fStartOffset = 0;
   1264   }
   1265   for (int32_t i = iBlockIndex - 1; iBlockIndex > 0 && i < iBlockIndex; i++) {
   1266     fStartOffset = (*pFieldArray)[i * 3] - (*pFieldArray)[i * 3 + 2];
   1267     if (fStartOffset < 0.1f)
   1268       fStartOffset = 0;
   1269   }
   1270   if (iFieldSplitCount / 3 == (iBlockIndex + 1)) {
   1271     (*pFieldArray)[0] = fStartOffset;
   1272   } else {
   1273     pFieldArray->push_back(fStartOffset);
   1274   }
   1275   XFA_VERSION version = GetDoc()->GetXFADoc()->GetCurVersionMode();
   1276   bool bCanSplitNoContent = false;
   1277   XFA_ATTRIBUTEENUM eLayoutMode;
   1278   GetNode()
   1279       ->GetNodeItem(XFA_NODEITEM_Parent)
   1280       ->TryEnum(XFA_ATTRIBUTE_Layout, eLayoutMode, true);
   1281   if ((eLayoutMode == XFA_ATTRIBUTEENUM_Position ||
   1282        eLayoutMode == XFA_ATTRIBUTEENUM_Tb ||
   1283        eLayoutMode == XFA_ATTRIBUTEENUM_Row ||
   1284        eLayoutMode == XFA_ATTRIBUTEENUM_Table) &&
   1285       version > XFA_VERSION_208) {
   1286     bCanSplitNoContent = true;
   1287   }
   1288   if ((eLayoutMode == XFA_ATTRIBUTEENUM_Tb ||
   1289        eLayoutMode == XFA_ATTRIBUTEENUM_Row ||
   1290        eLayoutMode == XFA_ATTRIBUTEENUM_Table) &&
   1291       version <= XFA_VERSION_208) {
   1292     if (fStartOffset < fCalcHeight) {
   1293       bCanSplitNoContent = true;
   1294     } else {
   1295       fCalcHeight = 0;
   1296       return true;
   1297     }
   1298   }
   1299   if (bCanSplitNoContent) {
   1300     if ((fCalcHeight - fTopInset - fSpaceAbove < fLineHeight)) {
   1301       fCalcHeight = 0;
   1302       return true;
   1303     }
   1304     if (fStartOffset + XFA_FLOAT_PERCISION >= fCalcHeight) {
   1305       if (iFieldSplitCount / 3 == (iBlockIndex + 1)) {
   1306         (*pFieldArray)[iBlockIndex * 3 + 1] = 0;
   1307         (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight;
   1308       } else {
   1309         pFieldArray->push_back(0);
   1310         pFieldArray->push_back(fCalcHeight);
   1311       }
   1312       return false;
   1313     }
   1314     if (fCalcHeight - fStartOffset < fLineHeight) {
   1315       fCalcHeight = fStartOffset;
   1316       if (iFieldSplitCount / 3 == (iBlockIndex + 1)) {
   1317         (*pFieldArray)[iBlockIndex * 3 + 1] = 0;
   1318         (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight;
   1319       } else {
   1320         pFieldArray->push_back(0);
   1321         pFieldArray->push_back(fCalcHeight);
   1322       }
   1323       return true;
   1324     }
   1325     FX_FLOAT fTextNum =
   1326         fCalcHeight + XFA_FLOAT_PERCISION - fCapReserve - fStartOffset;
   1327     int32_t iLineNum =
   1328         (int32_t)((fTextNum + (fLineHeight - fFontSize)) / fLineHeight);
   1329     if (iLineNum >= iLinesCount) {
   1330       if (fCalcHeight - fStartOffset - fTextHeight >= fFontSize) {
   1331         if (iFieldSplitCount / 3 == (iBlockIndex + 1)) {
   1332           (*pFieldArray)[iBlockIndex * 3 + 1] = (FX_FLOAT)iLinesCount;
   1333           (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight;
   1334         } else {
   1335           pFieldArray->push_back((FX_FLOAT)iLinesCount);
   1336           pFieldArray->push_back(fCalcHeight);
   1337         }
   1338         return false;
   1339       }
   1340       if (fHeight - fStartOffset - fTextHeight < fFontSize) {
   1341         iLineNum -= 1;
   1342         if (iLineNum == 0) {
   1343           fCalcHeight = 0;
   1344           return true;
   1345         }
   1346       } else {
   1347         iLineNum = (int32_t)(fTextNum / fLineHeight);
   1348       }
   1349     }
   1350     if (iLineNum > 0) {
   1351       FX_FLOAT fSplitHeight =
   1352           iLineNum * fLineHeight + fCapReserve + fStartOffset;
   1353       if (iFieldSplitCount / 3 == (iBlockIndex + 1)) {
   1354         (*pFieldArray)[iBlockIndex * 3 + 1] = (FX_FLOAT)iLineNum;
   1355         (*pFieldArray)[iBlockIndex * 3 + 2] = fSplitHeight;
   1356       } else {
   1357         pFieldArray->push_back((FX_FLOAT)iLineNum);
   1358         pFieldArray->push_back(fSplitHeight);
   1359       }
   1360       if (fabs(fSplitHeight - fCalcHeight) < XFA_FLOAT_PERCISION) {
   1361         return false;
   1362       }
   1363       fCalcHeight = fSplitHeight;
   1364       return true;
   1365     }
   1366   }
   1367   fCalcHeight = 0;
   1368   return true;
   1369 }
   1370 void CXFA_WidgetAcc::InitLayoutData() {
   1371   if (m_pLayoutData) {
   1372     return;
   1373   }
   1374   switch (GetUIType()) {
   1375     case XFA_Element::Text:
   1376       m_pLayoutData = pdfium::MakeUnique<CXFA_TextLayoutData>();
   1377       return;
   1378     case XFA_Element::TextEdit:
   1379       m_pLayoutData = pdfium::MakeUnique<CXFA_TextEditData>();
   1380       return;
   1381     case XFA_Element::Image:
   1382       m_pLayoutData = pdfium::MakeUnique<CXFA_ImageLayoutData>();
   1383       return;
   1384     case XFA_Element::ImageEdit:
   1385       m_pLayoutData = pdfium::MakeUnique<CXFA_ImageEditData>();
   1386       return;
   1387     default:
   1388       break;
   1389   }
   1390   if (GetElementType() == XFA_Element::Field) {
   1391     m_pLayoutData = pdfium::MakeUnique<CXFA_FieldLayoutData>();
   1392     return;
   1393   }
   1394   m_pLayoutData = pdfium::MakeUnique<CXFA_WidgetLayoutData>();
   1395 }
   1396 
   1397 void CXFA_WidgetAcc::StartTextLayout(FX_FLOAT& fCalcWidth,
   1398                                      FX_FLOAT& fCalcHeight) {
   1399   LoadText();
   1400   CXFA_TextLayout* pTextLayout =
   1401       static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout();
   1402   FX_FLOAT fTextHeight = 0;
   1403   if (fCalcWidth > 0 && fCalcHeight > 0) {
   1404     FX_FLOAT fWidth = GetWidthWithoutMargin(fCalcWidth);
   1405     pTextLayout->StartLayout(fWidth);
   1406     fTextHeight = fCalcHeight;
   1407     fTextHeight = GetHeightWithoutMargin(fTextHeight);
   1408     pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight);
   1409     return;
   1410   }
   1411   if (fCalcWidth > 0 && fCalcHeight < 0) {
   1412     FX_FLOAT fWidth = GetWidthWithoutMargin(fCalcWidth);
   1413     pTextLayout->StartLayout(fWidth);
   1414   }
   1415   if (fCalcWidth < 0 && fCalcHeight < 0) {
   1416     FX_FLOAT fMaxWidth = -1;
   1417     bool bRet = GetWidth(fMaxWidth);
   1418     if (bRet) {
   1419       FX_FLOAT fWidth = GetWidthWithoutMargin(fMaxWidth);
   1420       pTextLayout->StartLayout(fWidth);
   1421     } else {
   1422       FX_FLOAT fWidth = pTextLayout->StartLayout(fMaxWidth);
   1423       fMaxWidth = CalculateWidgetAutoWidth(fWidth);
   1424       fWidth = GetWidthWithoutMargin(fMaxWidth);
   1425       pTextLayout->StartLayout(fWidth);
   1426     }
   1427     fCalcWidth = fMaxWidth;
   1428   }
   1429   if (m_pLayoutData->m_fWidgetHeight < 0) {
   1430     m_pLayoutData->m_fWidgetHeight = pTextLayout->GetLayoutHeight();
   1431     m_pLayoutData->m_fWidgetHeight =
   1432         CalculateWidgetAutoHeight(m_pLayoutData->m_fWidgetHeight);
   1433   }
   1434   fTextHeight = m_pLayoutData->m_fWidgetHeight;
   1435   fTextHeight = GetHeightWithoutMargin(fTextHeight);
   1436   pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight);
   1437   fCalcHeight = m_pLayoutData->m_fWidgetHeight;
   1438 }
   1439 bool CXFA_WidgetAcc::LoadCaption() {
   1440   InitLayoutData();
   1441   return static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get())
   1442       ->LoadCaption(this);
   1443 }
   1444 CXFA_TextLayout* CXFA_WidgetAcc::GetCaptionTextLayout() {
   1445   return m_pLayoutData
   1446              ? static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get())
   1447                    ->m_pCapTextLayout.get()
   1448              : nullptr;
   1449 }
   1450 CXFA_TextLayout* CXFA_WidgetAcc::GetTextLayout() {
   1451   return m_pLayoutData
   1452              ? static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())
   1453                    ->GetTextLayout()
   1454              : nullptr;
   1455 }
   1456 CFX_DIBitmap* CXFA_WidgetAcc::GetImageImage() {
   1457   return m_pLayoutData
   1458              ? static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get())
   1459                    ->m_pDIBitmap
   1460              : nullptr;
   1461 }
   1462 CFX_DIBitmap* CXFA_WidgetAcc::GetImageEditImage() {
   1463   return m_pLayoutData
   1464              ? static_cast<CXFA_ImageEditData*>(m_pLayoutData.get())
   1465                    ->m_pDIBitmap
   1466              : nullptr;
   1467 }
   1468 
   1469 void CXFA_WidgetAcc::SetImageImage(CFX_DIBitmap* newImage) {
   1470   CXFA_ImageLayoutData* pData =
   1471       static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get());
   1472   if (pData->m_pDIBitmap == newImage)
   1473     return;
   1474 
   1475   if (pData->m_pDIBitmap && !pData->m_bNamedImage)
   1476     delete pData->m_pDIBitmap;
   1477 
   1478   pData->m_pDIBitmap = newImage;
   1479 }
   1480 
   1481 void CXFA_WidgetAcc::SetImageEditImage(CFX_DIBitmap* newImage) {
   1482   CXFA_ImageEditData* pData =
   1483       static_cast<CXFA_ImageEditData*>(m_pLayoutData.get());
   1484   if (pData->m_pDIBitmap == newImage)
   1485     return;
   1486 
   1487   if (pData->m_pDIBitmap && !pData->m_bNamedImage)
   1488     delete pData->m_pDIBitmap;
   1489 
   1490   pData->m_pDIBitmap = newImage;
   1491 }
   1492 
   1493 CXFA_WidgetLayoutData* CXFA_WidgetAcc::GetWidgetLayoutData() {
   1494   return m_pLayoutData.get();
   1495 }
   1496 
   1497 CFX_RetainPtr<CFGAS_GEFont> CXFA_WidgetAcc::GetFDEFont() {
   1498   CFX_WideStringC wsFontName = L"Courier";
   1499   uint32_t dwFontStyle = 0;
   1500   if (CXFA_Font font = GetFont()) {
   1501     if (font.IsBold())
   1502       dwFontStyle |= FX_FONTSTYLE_Bold;
   1503     if (font.IsItalic())
   1504       dwFontStyle |= FX_FONTSTYLE_Italic;
   1505     font.GetTypeface(wsFontName);
   1506   }
   1507 
   1508   auto pDoc = GetDoc();
   1509   return pDoc->GetApp()->GetXFAFontMgr()->GetFont(pDoc, wsFontName,
   1510                                                   dwFontStyle);
   1511 }
   1512 FX_FLOAT CXFA_WidgetAcc::GetFontSize() {
   1513   FX_FLOAT fFontSize = 10.0f;
   1514   if (CXFA_Font font = GetFont()) {
   1515     fFontSize = font.GetFontSize();
   1516   }
   1517   return fFontSize < 0.1f ? 10.0f : fFontSize;
   1518 }
   1519 FX_FLOAT CXFA_WidgetAcc::GetLineHeight() {
   1520   FX_FLOAT fLineHeight = 0;
   1521   if (CXFA_Para para = GetPara()) {
   1522     fLineHeight = para.GetLineHeight();
   1523   }
   1524   if (fLineHeight < 1) {
   1525     fLineHeight = GetFontSize() * 1.2f;
   1526   }
   1527   return fLineHeight;
   1528 }
   1529 FX_ARGB CXFA_WidgetAcc::GetTextColor() {
   1530   if (CXFA_Font font = GetFont()) {
   1531     return font.GetColor();
   1532   }
   1533   return 0xFF000000;
   1534 }
   1535 CXFA_Node* CXFA_TextProvider::GetTextNode(bool& bRichText) {
   1536   bRichText = false;
   1537   if (m_pTextNode) {
   1538     if (m_pTextNode->GetElementType() == XFA_Element::ExData) {
   1539       CFX_WideString wsContentType;
   1540       m_pTextNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType,
   1541                                 false);
   1542       if (wsContentType == L"text/html") {
   1543         bRichText = true;
   1544       }
   1545     }
   1546     return m_pTextNode;
   1547   }
   1548   if (m_eType == XFA_TEXTPROVIDERTYPE_Text) {
   1549     CXFA_Node* pElementNode = m_pWidgetAcc->GetNode();
   1550     CXFA_Node* pValueNode = pElementNode->GetChild(0, XFA_Element::Value);
   1551     if (!pValueNode) {
   1552       return nullptr;
   1553     }
   1554     CXFA_Node* pChildNode = pValueNode->GetNodeItem(XFA_NODEITEM_FirstChild);
   1555     if (pChildNode && pChildNode->GetElementType() == XFA_Element::ExData) {
   1556       CFX_WideString wsContentType;
   1557       pChildNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, false);
   1558       if (wsContentType == L"text/html") {
   1559         bRichText = true;
   1560       }
   1561     }
   1562     return pChildNode;
   1563   } else if (m_eType == XFA_TEXTPROVIDERTYPE_Datasets) {
   1564     CXFA_Node* pBind = m_pWidgetAcc->GetDatasets();
   1565     CFDE_XMLNode* pXMLNode = pBind->GetXMLMappingNode();
   1566     ASSERT(pXMLNode);
   1567     for (CFDE_XMLNode* pXMLChild =
   1568              pXMLNode->GetNodeItem(CFDE_XMLNode::FirstChild);
   1569          pXMLChild;
   1570          pXMLChild = pXMLChild->GetNodeItem(CFDE_XMLNode::NextSibling)) {
   1571       if (pXMLChild->GetType() == FDE_XMLNODE_Element) {
   1572         CFDE_XMLElement* pElement = static_cast<CFDE_XMLElement*>(pXMLChild);
   1573         if (XFA_RecognizeRichText(pElement)) {
   1574           bRichText = true;
   1575         }
   1576       }
   1577     }
   1578     return pBind;
   1579   } else if (m_eType == XFA_TEXTPROVIDERTYPE_Caption) {
   1580     CXFA_Node* pCaptionNode =
   1581         m_pWidgetAcc->GetNode()->GetChild(0, XFA_Element::Caption);
   1582     if (!pCaptionNode) {
   1583       return nullptr;
   1584     }
   1585     CXFA_Node* pValueNode = pCaptionNode->GetChild(0, XFA_Element::Value);
   1586     if (!pValueNode) {
   1587       return nullptr;
   1588     }
   1589     CXFA_Node* pChildNode = pValueNode->GetNodeItem(XFA_NODEITEM_FirstChild);
   1590     if (pChildNode && pChildNode->GetElementType() == XFA_Element::ExData) {
   1591       CFX_WideString wsContentType;
   1592       pChildNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, false);
   1593       if (wsContentType == L"text/html") {
   1594         bRichText = true;
   1595       }
   1596     }
   1597     return pChildNode;
   1598   }
   1599   CXFA_Node* pItemNode =
   1600       m_pWidgetAcc->GetNode()->GetChild(0, XFA_Element::Items);
   1601   if (!pItemNode) {
   1602     return nullptr;
   1603   }
   1604   CXFA_Node* pNode = pItemNode->GetNodeItem(XFA_NODEITEM_FirstChild);
   1605   while (pNode) {
   1606     CFX_WideStringC wsName;
   1607     pNode->TryCData(XFA_ATTRIBUTE_Name, wsName);
   1608     if (m_eType == XFA_TEXTPROVIDERTYPE_Rollover && wsName == L"rollover") {
   1609       return pNode;
   1610     }
   1611     if (m_eType == XFA_TEXTPROVIDERTYPE_Down && wsName == L"down") {
   1612       return pNode;
   1613     }
   1614     pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling);
   1615   }
   1616   return nullptr;
   1617 }
   1618 CXFA_Para CXFA_TextProvider::GetParaNode() {
   1619   if (m_eType == XFA_TEXTPROVIDERTYPE_Text) {
   1620     return m_pWidgetAcc->GetPara();
   1621   }
   1622   CXFA_Node* pNode = m_pWidgetAcc->GetNode()->GetChild(0, XFA_Element::Caption);
   1623   return CXFA_Para(pNode->GetChild(0, XFA_Element::Para));
   1624 }
   1625 CXFA_Font CXFA_TextProvider::GetFontNode() {
   1626   if (m_eType == XFA_TEXTPROVIDERTYPE_Text) {
   1627     return m_pWidgetAcc->GetFont();
   1628   }
   1629   CXFA_Node* pNode = m_pWidgetAcc->GetNode()->GetChild(0, XFA_Element::Caption);
   1630   pNode = pNode->GetChild(0, XFA_Element::Font);
   1631   if (pNode) {
   1632     return CXFA_Font(pNode);
   1633   }
   1634   return m_pWidgetAcc->GetFont();
   1635 }
   1636 bool CXFA_TextProvider::IsCheckButtonAndAutoWidth() {
   1637   XFA_Element eType = m_pWidgetAcc->GetUIType();
   1638   if (eType == XFA_Element::CheckButton) {
   1639     FX_FLOAT fWidth = 0;
   1640     return !m_pWidgetAcc->GetWidth(fWidth);
   1641   }
   1642   return false;
   1643 }
   1644 bool CXFA_TextProvider::GetEmbbedObj(bool bURI,
   1645                                      bool bRaw,
   1646                                      const CFX_WideString& wsAttr,
   1647                                      CFX_WideString& wsValue) {
   1648   if (m_eType != XFA_TEXTPROVIDERTYPE_Text) {
   1649     return false;
   1650   }
   1651   if (bURI) {
   1652     CXFA_Node* pWidgetNode = m_pWidgetAcc->GetNode();
   1653     CXFA_Node* pParent = pWidgetNode->GetNodeItem(XFA_NODEITEM_Parent);
   1654     CXFA_Document* pDocument = pWidgetNode->GetDocument();
   1655     CXFA_Node* pIDNode = nullptr;
   1656     CXFA_WidgetAcc* pEmbAcc = nullptr;
   1657     if (pParent) {
   1658       pIDNode = pDocument->GetNodeByID(pParent, wsAttr.AsStringC());
   1659     }
   1660     if (!pIDNode) {
   1661       pIDNode = pDocument->GetNodeByID(
   1662           ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Form)),
   1663           wsAttr.AsStringC());
   1664     }
   1665     if (pIDNode) {
   1666       pEmbAcc = static_cast<CXFA_WidgetAcc*>(pIDNode->GetWidgetData());
   1667     }
   1668     if (pEmbAcc) {
   1669       pEmbAcc->GetValue(wsValue, XFA_VALUEPICTURE_Display);
   1670       return true;
   1671     }
   1672   }
   1673   return false;
   1674 }
   1675