• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
XFA_FFDeleteCalcData(void * pData)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:
CXFA_WidgetLayoutData()45   CXFA_WidgetLayoutData() : m_fWidgetHeight(-1) {}
~CXFA_WidgetLayoutData()46   virtual ~CXFA_WidgetLayoutData() {}
47 
48   FX_FLOAT m_fWidgetHeight;
49 };
50 
51 class CXFA_TextLayoutData : public CXFA_WidgetLayoutData {
52  public:
CXFA_TextLayoutData()53   CXFA_TextLayoutData() {}
~CXFA_TextLayoutData()54   ~CXFA_TextLayoutData() override {}
55 
GetTextLayout() const56   CXFA_TextLayout* GetTextLayout() const { return m_pTextLayout.get(); }
GetTextProvider() const57   CXFA_TextProvider* GetTextProvider() const { return m_pTextProvider.get(); }
58 
LoadText(CXFA_WidgetAcc * pAcc)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:
CXFA_ImageLayoutData()75   CXFA_ImageLayoutData()
76       : m_pDIBitmap(nullptr),
77         m_bNamedImage(false),
78         m_iImageXDpi(0),
79         m_iImageYDpi(0) {}
80 
~CXFA_ImageLayoutData()81   ~CXFA_ImageLayoutData() override {
82     if (m_pDIBitmap && !m_bNamedImage)
83       delete m_pDIBitmap;
84   }
85 
LoadImageData(CXFA_WidgetAcc * pAcc)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:
CXFA_FieldLayoutData()112   CXFA_FieldLayoutData() {}
~CXFA_FieldLayoutData()113   ~CXFA_FieldLayoutData() override {}
114 
LoadCaption(CXFA_WidgetAcc * pAcc)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:
CXFA_ImageEditData()140   CXFA_ImageEditData()
141       : m_pDIBitmap(nullptr),
142         m_bNamedImage(false),
143         m_iImageXDpi(0),
144         m_iImageYDpi(0) {}
145 
~CXFA_ImageEditData()146   ~CXFA_ImageEditData() override {
147     if (m_pDIBitmap && !m_bNamedImage)
148       delete m_pDIBitmap;
149   }
150 
LoadImageData(CXFA_WidgetAcc * pAcc)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 
CXFA_WidgetAcc(CXFA_FFDocView * pDocView,CXFA_Node * pNode)172 CXFA_WidgetAcc::CXFA_WidgetAcc(CXFA_FFDocView* pDocView, CXFA_Node* pNode)
173     : CXFA_WidgetData(pNode),
174       m_pDocView(pDocView),
175       m_nRecursionDepth(0) {}
176 
~CXFA_WidgetAcc()177 CXFA_WidgetAcc::~CXFA_WidgetAcc() {}
178 
GetName(CFX_WideString & wsName,int32_t iNameType)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 }
GetDatasets()193 CXFA_Node* CXFA_WidgetAcc::GetDatasets() {
194   return m_pNode->GetBindData();
195 }
ProcessValueChanged()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 }
ResetData()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 }
SetImageEdit(const CFX_WideString & wsContentType,const CFX_WideString & wsHref,const CFX_WideString & wsData)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 
GetExclGroup()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 }
GetDocView()292 CXFA_FFDocView* CXFA_WidgetAcc::GetDocView() {
293   return m_pDocView;
294 }
GetDoc()295 CXFA_FFDoc* CXFA_WidgetAcc::GetDoc() {
296   return m_pDocView->GetDoc();
297 }
GetApp()298 CXFA_FFApp* CXFA_WidgetAcc::GetApp() {
299   return GetDoc()->GetApp();
300 }
GetAppProvider()301 IXFA_AppProvider* CXFA_WidgetAcc::GetAppProvider() {
302   return GetApp()->GetAppProvider();
303 }
ProcessEvent(int32_t iActivity,CXFA_EventParam * pEventParam)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 }
ProcessEvent(CXFA_Event & event,CXFA_EventParam * pEventParam)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 
ProcessCalculate()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 
ProcessScriptTestValidate(CXFA_Validate validate,int32_t iRet,CFXJSE_Value * pRetValue,bool bVersionFlag)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 }
ProcessFormatTestValidate(CXFA_Validate validate,bool bVersionFlag)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 }
ProcessNullTestValidate(CXFA_Validate validate,int32_t iFlags,bool bVersionFlag)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 
GetValidateCaptionName(bool bVersionFlag)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 
GetValidateMessage(bool bError,bool bVersionFlag)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 
ProcessValidate(int32_t iFlags)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 }
ExecuteScript(CXFA_Script script,CXFA_EventParam * pEventParam,CFXJSE_Value ** pRetValue)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 }
GetNextWidget(CXFA_FFWidget * pWidget)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 }
UpdateUIDisplay(CXFA_FFWidget * pExcept)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 
CalcCaptionSize(CFX_SizeF & szCap)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 }
CalculateFieldAutoSize(CFX_SizeF & size)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 }
CalculateWidgetAutoSize(CFX_SizeF & size)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 
CalculateTextContentSize(CFX_SizeF & size)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 }
CalculateTextEditAutoSize(CFX_SizeF & size)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 }
CalculateCheckButtonAutoSize(CFX_SizeF & size)916 bool CXFA_WidgetAcc::CalculateCheckButtonAutoSize(CFX_SizeF& size) {
917   FX_FLOAT fCheckSize = GetCheckButtonSize();
918   size = CFX_SizeF(fCheckSize, fCheckSize);
919   return CalculateFieldAutoSize(size);
920 }
CalculatePushButtonAutoSize(CFX_SizeF & size)921 bool CXFA_WidgetAcc::CalculatePushButtonAutoSize(CFX_SizeF& size) {
922   CalcCaptionSize(size);
923   return CalculateWidgetAutoSize(size);
924 }
CalculateImageAutoSize(CFX_SizeF & size)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 }
CalculateImageEditAutoSize(CFX_SizeF & size)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 }
LoadImageImage()984 bool CXFA_WidgetAcc::LoadImageImage() {
985   InitLayoutData();
986   return static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get())
987       ->LoadImageData(this);
988 }
LoadImageEditImage()989 bool CXFA_WidgetAcc::LoadImageEditImage() {
990   InitLayoutData();
991   return static_cast<CXFA_ImageEditData*>(m_pLayoutData.get())
992       ->LoadImageData(this);
993 }
GetImageDpi(int32_t & iImageXDpi,int32_t & iImageYDpi)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 }
GetImageEditDpi(int32_t & iImageXDpi,int32_t & iImageYDpi)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 }
CalculateTextAutoSize(CFX_SizeF & size)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 }
LoadText()1016 void CXFA_WidgetAcc::LoadText() {
1017   InitLayoutData();
1018   static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->LoadText(this);
1019 }
CalculateWidgetAutoWidth(FX_FLOAT fWidthCalc)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 }
GetWidthWithoutMargin(FX_FLOAT fWidthCalc)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 }
CalculateWidgetAutoHeight(FX_FLOAT fHeightCalc)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 }
GetHeightWithoutMargin(FX_FLOAT fHeightCalc)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 }
StartWidgetLayout(FX_FLOAT & fCalcWidth,FX_FLOAT & fCalcHeight)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 }
CalculateAccWidthAndHeight(XFA_Element eUIType,FX_FLOAT & fWidth,FX_FLOAT & fCalcHeight)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 }
FindSplitPos(int32_t iBlockIndex,FX_FLOAT & fCalcHeight)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 }
InitLayoutData()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 
StartTextLayout(FX_FLOAT & fCalcWidth,FX_FLOAT & fCalcHeight)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 }
LoadCaption()1439 bool CXFA_WidgetAcc::LoadCaption() {
1440   InitLayoutData();
1441   return static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get())
1442       ->LoadCaption(this);
1443 }
GetCaptionTextLayout()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 }
GetTextLayout()1450 CXFA_TextLayout* CXFA_WidgetAcc::GetTextLayout() {
1451   return m_pLayoutData
1452              ? static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())
1453                    ->GetTextLayout()
1454              : nullptr;
1455 }
GetImageImage()1456 CFX_DIBitmap* CXFA_WidgetAcc::GetImageImage() {
1457   return m_pLayoutData
1458              ? static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get())
1459                    ->m_pDIBitmap
1460              : nullptr;
1461 }
GetImageEditImage()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 
SetImageImage(CFX_DIBitmap * newImage)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 
SetImageEditImage(CFX_DIBitmap * newImage)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 
GetWidgetLayoutData()1493 CXFA_WidgetLayoutData* CXFA_WidgetAcc::GetWidgetLayoutData() {
1494   return m_pLayoutData.get();
1495 }
1496 
GetFDEFont()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 }
GetFontSize()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 }
GetLineHeight()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 }
GetTextColor()1529 FX_ARGB CXFA_WidgetAcc::GetTextColor() {
1530   if (CXFA_Font font = GetFont()) {
1531     return font.GetColor();
1532   }
1533   return 0xFF000000;
1534 }
GetTextNode(bool & bRichText)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 }
GetParaNode()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 }
GetFontNode()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 }
IsCheckButtonAndAutoWidth()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 }
GetEmbbedObj(bool bURI,bool bRaw,const CFX_WideString & wsAttr,CFX_WideString & wsValue)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