diff options
Diffstat (limited to 'xfa/fxfa')
-rw-r--r-- | xfa/fxfa/cxfa_ffbarcode.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_ffcheckbutton.h | 2 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_ffcombobox.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_fffield.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_ffimage.cpp | 2 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_ffimageedit.cpp | 2 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_fflistbox.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_ffpasswordedit.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_ffpushbutton.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_fftext.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_fftextedit.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_ffwidget.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_fwltheme.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_textprovider.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_widgetacc.cpp | 2500 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_widgetacc.h | 209 | ||||
-rw-r--r-- | xfa/fxfa/parser/cxfa_localevalue.h | 2 | ||||
-rw-r--r-- | xfa/fxfa/parser/cxfa_node.cpp | 2443 | ||||
-rw-r--r-- | xfa/fxfa/parser/cxfa_node.h | 174 | ||||
-rw-r--r-- | xfa/fxfa/parser/xfa_document_datamerger_imp.cpp | 1 |
20 files changed, 2608 insertions, 2738 deletions
diff --git a/xfa/fxfa/cxfa_ffbarcode.cpp b/xfa/fxfa/cxfa_ffbarcode.cpp index caef3df2fb..86b06185e4 100644 --- a/xfa/fxfa/cxfa_ffbarcode.cpp +++ b/xfa/fxfa/cxfa_ffbarcode.cpp @@ -17,7 +17,6 @@ #include "xfa/fxfa/cxfa_ffpageview.h" #include "xfa/fxfa/cxfa_ffwidget.h" #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_border.h" namespace { diff --git a/xfa/fxfa/cxfa_ffcheckbutton.h b/xfa/fxfa/cxfa_ffcheckbutton.h index 2ee2a7df44..230695f85a 100644 --- a/xfa/fxfa/cxfa_ffcheckbutton.h +++ b/xfa/fxfa/cxfa_ffcheckbutton.h @@ -9,7 +9,7 @@ #include "xfa/fxfa/cxfa_fffield.h" #include "xfa/fxfa/cxfa_ffpageview.h" -#include "xfa/fxfa/cxfa_widgetacc.h" +#include "xfa/fxfa/parser/cxfa_node.h" class CXFA_FFCheckButton : public CXFA_FFField { public: diff --git a/xfa/fxfa/cxfa_ffcombobox.cpp b/xfa/fxfa/cxfa_ffcombobox.cpp index fcb8eb1aa5..7e9a855b16 100644 --- a/xfa/fxfa/cxfa_ffcombobox.cpp +++ b/xfa/fxfa/cxfa_ffcombobox.cpp @@ -14,7 +14,6 @@ #include "xfa/fwl/cfwl_notedriver.h" #include "xfa/fxfa/cxfa_eventparam.h" #include "xfa/fxfa/cxfa_ffdocview.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_para.h" namespace { diff --git a/xfa/fxfa/cxfa_fffield.cpp b/xfa/fxfa/cxfa_fffield.cpp index 64e8e00340..8ac287641d 100644 --- a/xfa/fxfa/cxfa_fffield.cpp +++ b/xfa/fxfa/cxfa_fffield.cpp @@ -22,7 +22,6 @@ #include "xfa/fxfa/cxfa_ffwidget.h" #include "xfa/fxfa/cxfa_fwltheme.h" #include "xfa/fxfa/cxfa_textlayout.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_border.h" #include "xfa/fxfa/parser/cxfa_calculate.h" #include "xfa/fxfa/parser/cxfa_caption.h" diff --git a/xfa/fxfa/cxfa_ffimage.cpp b/xfa/fxfa/cxfa_ffimage.cpp index 608ca3cc10..a5a2ee7464 100644 --- a/xfa/fxfa/cxfa_ffimage.cpp +++ b/xfa/fxfa/cxfa_ffimage.cpp @@ -6,12 +6,12 @@ #include "xfa/fxfa/cxfa_ffimage.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "xfa/fxfa/cxfa_ffapp.h" #include "xfa/fxfa/cxfa_ffdoc.h" #include "xfa/fxfa/cxfa_ffdraw.h" #include "xfa/fxfa/cxfa_ffpageview.h" #include "xfa/fxfa/cxfa_ffwidget.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_image.h" #include "xfa/fxfa/parser/cxfa_para.h" #include "xfa/fxfa/parser/cxfa_value.h" diff --git a/xfa/fxfa/cxfa_ffimageedit.cpp b/xfa/fxfa/cxfa_ffimageedit.cpp index 3ef05e9e47..8b97c2b3be 100644 --- a/xfa/fxfa/cxfa_ffimageedit.cpp +++ b/xfa/fxfa/cxfa_ffimageedit.cpp @@ -8,6 +8,7 @@ #include <utility> +#include "core/fxge/dib/cfx_dibitmap.h" #include "third_party/base/ptr_util.h" #include "xfa/fwl/cfwl_app.h" #include "xfa/fwl/cfwl_messagemouse.h" @@ -18,7 +19,6 @@ #include "xfa/fxfa/cxfa_fffield.h" #include "xfa/fxfa/cxfa_ffpageview.h" #include "xfa/fxfa/cxfa_ffwidget.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_border.h" #include "xfa/fxfa/parser/cxfa_image.h" #include "xfa/fxfa/parser/cxfa_para.h" diff --git a/xfa/fxfa/cxfa_fflistbox.cpp b/xfa/fxfa/cxfa_fflistbox.cpp index 12a2c8a8c9..64fb8e58a4 100644 --- a/xfa/fxfa/cxfa_fflistbox.cpp +++ b/xfa/fxfa/cxfa_fflistbox.cpp @@ -14,7 +14,6 @@ #include "xfa/fwl/cfwl_notedriver.h" #include "xfa/fwl/cfwl_widget.h" #include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_para.h" namespace { diff --git a/xfa/fxfa/cxfa_ffpasswordedit.cpp b/xfa/fxfa/cxfa_ffpasswordedit.cpp index d639d1e57e..15bd5faaae 100644 --- a/xfa/fxfa/cxfa_ffpasswordedit.cpp +++ b/xfa/fxfa/cxfa_ffpasswordedit.cpp @@ -11,7 +11,6 @@ #include "xfa/fwl/cfwl_edit.h" #include "xfa/fwl/cfwl_notedriver.h" #include "xfa/fxfa/cxfa_ffdoc.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_node.h" CXFA_FFPasswordEdit::CXFA_FFPasswordEdit(CXFA_Node* pNode) diff --git a/xfa/fxfa/cxfa_ffpushbutton.cpp b/xfa/fxfa/cxfa_ffpushbutton.cpp index ce05cf5d03..d4d591f87a 100644 --- a/xfa/fxfa/cxfa_ffpushbutton.cpp +++ b/xfa/fxfa/cxfa_ffpushbutton.cpp @@ -18,7 +18,6 @@ #include "xfa/fxfa/cxfa_ffwidget.h" #include "xfa/fxfa/cxfa_textlayout.h" #include "xfa/fxfa/cxfa_textprovider.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_border.h" #include "xfa/fxfa/parser/cxfa_caption.h" #include "xfa/fxfa/parser/cxfa_edge.h" diff --git a/xfa/fxfa/cxfa_fftext.cpp b/xfa/fxfa/cxfa_fftext.cpp index 05749642e8..7ae3cb6f5c 100644 --- a/xfa/fxfa/cxfa_fftext.cpp +++ b/xfa/fxfa/cxfa_fftext.cpp @@ -17,7 +17,6 @@ #include "xfa/fxfa/cxfa_pieceline.h" #include "xfa/fxfa/cxfa_textlayout.h" #include "xfa/fxfa/cxfa_textpiece.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_margin.h" #include "xfa/fxgraphics/cxfa_graphics.h" diff --git a/xfa/fxfa/cxfa_fftextedit.cpp b/xfa/fxfa/cxfa_fftextedit.cpp index 8464aa97e7..89a7c90155 100644 --- a/xfa/fxfa/cxfa_fftextedit.cpp +++ b/xfa/fxfa/cxfa_fftextedit.cpp @@ -19,7 +19,6 @@ #include "xfa/fxfa/cxfa_eventparam.h" #include "xfa/fxfa/cxfa_ffapp.h" #include "xfa/fxfa/cxfa_ffdoc.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_node.h" #include "xfa/fxfa/parser/cxfa_para.h" diff --git a/xfa/fxfa/cxfa_ffwidget.cpp b/xfa/fxfa/cxfa_ffwidget.cpp index fa3136ca77..c3e0d4de4d 100644 --- a/xfa/fxfa/cxfa_ffwidget.cpp +++ b/xfa/fxfa/cxfa_ffwidget.cpp @@ -25,7 +25,6 @@ #include "xfa/fxfa/cxfa_ffdocview.h" #include "xfa/fxfa/cxfa_ffpageview.h" #include "xfa/fxfa/cxfa_imagerenderer.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_border.h" #include "xfa/fxfa/parser/cxfa_box.h" #include "xfa/fxfa/parser/cxfa_image.h" diff --git a/xfa/fxfa/cxfa_fwltheme.cpp b/xfa/fxfa/cxfa_fwltheme.cpp index a3679f8127..c7c521ea66 100644 --- a/xfa/fxfa/cxfa_fwltheme.cpp +++ b/xfa/fxfa/cxfa_fwltheme.cpp @@ -24,7 +24,6 @@ #include "xfa/fwl/cfwl_themetext.h" #include "xfa/fxfa/cxfa_ffapp.h" #include "xfa/fxfa/cxfa_ffwidget.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_para.h" #include "xfa/fxgraphics/cxfa_gecolor.h" diff --git a/xfa/fxfa/cxfa_textprovider.cpp b/xfa/fxfa/cxfa_textprovider.cpp index 9ea083831f..d1f9256d34 100644 --- a/xfa/fxfa/cxfa_textprovider.cpp +++ b/xfa/fxfa/cxfa_textprovider.cpp @@ -28,7 +28,6 @@ #include "xfa/fxfa/cxfa_ffwidget.h" #include "xfa/fxfa/cxfa_fontmgr.h" #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_caption.h" #include "xfa/fxfa/parser/cxfa_font.h" #include "xfa/fxfa/parser/cxfa_items.h" diff --git a/xfa/fxfa/cxfa_widgetacc.cpp b/xfa/fxfa/cxfa_widgetacc.cpp deleted file mode 100644 index 0e73dfb4e8..0000000000 --- a/xfa/fxfa/cxfa_widgetacc.cpp +++ /dev/null @@ -1,2500 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/cxfa_widgetacc.h" - -#include <algorithm> -#include <tuple> -#include <vector> - -#include "core/fxcrt/cfx_decimal.h" -#include "core/fxcrt/cfx_memorystream.h" -#include "core/fxcrt/fx_extension.h" -#include "core/fxcrt/xml/cfx_xmlelement.h" -#include "core/fxcrt/xml/cfx_xmlnode.h" -#include "fxjs/cfxjse_engine.h" -#include "fxjs/xfa/cjx_object.h" -#include "third_party/base/stl_util.h" -#include "xfa/fde/cfde_textout.h" -#include "xfa/fxfa/cxfa_ffapp.h" -#include "xfa/fxfa/cxfa_ffdoc.h" -#include "xfa/fxfa/cxfa_ffdocview.h" -#include "xfa/fxfa/cxfa_ffnotify.h" -#include "xfa/fxfa/cxfa_ffwidget.h" -#include "xfa/fxfa/cxfa_fontmgr.h" -#include "xfa/fxfa/cxfa_textlayout.h" -#include "xfa/fxfa/cxfa_textprovider.h" -#include "xfa/fxfa/parser/cxfa_bind.h" -#include "xfa/fxfa/parser/cxfa_border.h" -#include "xfa/fxfa/parser/cxfa_calculate.h" -#include "xfa/fxfa/parser/cxfa_caption.h" -#include "xfa/fxfa/parser/cxfa_comb.h" -#include "xfa/fxfa/parser/cxfa_decimal.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_event.h" -#include "xfa/fxfa/parser/cxfa_font.h" -#include "xfa/fxfa/parser/cxfa_format.h" -#include "xfa/fxfa/parser/cxfa_image.h" -#include "xfa/fxfa/parser/cxfa_items.h" -#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" -#include "xfa/fxfa/parser/cxfa_localevalue.h" -#include "xfa/fxfa/parser/cxfa_margin.h" -#include "xfa/fxfa/parser/cxfa_measurement.h" -#include "xfa/fxfa/parser/cxfa_node.h" -#include "xfa/fxfa/parser/cxfa_para.h" -#include "xfa/fxfa/parser/cxfa_picture.h" -#include "xfa/fxfa/parser/cxfa_script.h" -#include "xfa/fxfa/parser/cxfa_stroke.h" -#include "xfa/fxfa/parser/cxfa_ui.h" -#include "xfa/fxfa/parser/cxfa_validate.h" -#include "xfa/fxfa/parser/cxfa_value.h" -#include "xfa/fxfa/parser/xfa_utils.h" - -class CXFA_WidgetLayoutData { - public: - CXFA_WidgetLayoutData() : m_fWidgetHeight(-1) {} - virtual ~CXFA_WidgetLayoutData() {} - - float m_fWidgetHeight; -}; - -namespace { - -constexpr uint8_t g_inv_base64[128] = { - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, - 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, - 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 255, 255, 255, 255, 255, -}; - -uint8_t* XFA_RemoveBase64Whitespace(const uint8_t* pStr, int32_t iLen) { - uint8_t* pCP; - int32_t i = 0, j = 0; - if (iLen == 0) { - iLen = strlen((char*)pStr); - } - pCP = FX_Alloc(uint8_t, iLen + 1); - for (; i < iLen; i++) { - if ((pStr[i] & 128) == 0) { - if (g_inv_base64[pStr[i]] != 0xFF || pStr[i] == '=') { - pCP[j++] = pStr[i]; - } - } - } - pCP[j] = '\0'; - return pCP; -} - -int32_t XFA_Base64Decode(const char* pStr, uint8_t* pOutBuffer) { - if (!pStr) { - return 0; - } - uint8_t* pBuffer = - XFA_RemoveBase64Whitespace((uint8_t*)pStr, strlen((char*)pStr)); - if (!pBuffer) { - return 0; - } - int32_t iLen = strlen((char*)pBuffer); - int32_t i = 0, j = 0; - uint32_t dwLimb = 0; - for (; i + 3 < iLen; i += 4) { - if (pBuffer[i] == '=' || pBuffer[i + 1] == '=' || pBuffer[i + 2] == '=' || - pBuffer[i + 3] == '=') { - if (pBuffer[i] == '=' || pBuffer[i + 1] == '=') { - break; - } - if (pBuffer[i + 2] == '=') { - dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 6) | - ((uint32_t)g_inv_base64[pBuffer[i + 1]]); - pOutBuffer[j] = (uint8_t)(dwLimb >> 4) & 0xFF; - j++; - } else { - dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 12) | - ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 6) | - ((uint32_t)g_inv_base64[pBuffer[i + 2]]); - pOutBuffer[j] = (uint8_t)(dwLimb >> 10) & 0xFF; - pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 2) & 0xFF; - j += 2; - } - } else { - dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 18) | - ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 12) | - ((uint32_t)g_inv_base64[pBuffer[i + 2]] << 6) | - ((uint32_t)g_inv_base64[pBuffer[i + 3]]); - pOutBuffer[j] = (uint8_t)(dwLimb >> 16) & 0xff; - pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 8) & 0xff; - pOutBuffer[j + 2] = (uint8_t)(dwLimb)&0xff; - j += 3; - } - } - FX_Free(pBuffer); - return j; -} - -FXCODEC_IMAGE_TYPE XFA_GetImageType(const WideString& wsType) { - WideString wsContentType(wsType); - wsContentType.MakeLower(); - if (wsContentType == L"image/jpg") - return FXCODEC_IMAGE_JPG; - if (wsContentType == L"image/png") - return FXCODEC_IMAGE_PNG; - if (wsContentType == L"image/gif") - return FXCODEC_IMAGE_GIF; - if (wsContentType == L"image/bmp") - return FXCODEC_IMAGE_BMP; - if (wsContentType == L"image/tif") - return FXCODEC_IMAGE_TIF; - return FXCODEC_IMAGE_UNKNOWN; -} - -RetainPtr<CFX_DIBitmap> XFA_LoadImageData(CXFA_FFDoc* pDoc, - CXFA_Image* pImage, - bool& bNameImage, - int32_t& iImageXDpi, - int32_t& iImageYDpi) { - WideString wsHref = pImage->GetHref(); - WideString wsImage = pImage->GetContent(); - if (wsHref.IsEmpty() && wsImage.IsEmpty()) - return nullptr; - - FXCODEC_IMAGE_TYPE type = XFA_GetImageType(pImage->GetContentType()); - ByteString bsContent; - uint8_t* pImageBuffer = nullptr; - RetainPtr<IFX_SeekableReadStream> pImageFileRead; - if (wsImage.GetLength() > 0) { - XFA_AttributeEnum iEncoding = pImage->GetTransferEncoding(); - if (iEncoding == XFA_AttributeEnum::Base64) { - ByteString bsData = wsImage.UTF8Encode(); - int32_t iLength = bsData.GetLength(); - pImageBuffer = FX_Alloc(uint8_t, iLength); - int32_t iRead = XFA_Base64Decode(bsData.c_str(), pImageBuffer); - if (iRead > 0) { - pImageFileRead = - pdfium::MakeRetain<CFX_MemoryStream>(pImageBuffer, iRead, false); - } - } else { - bsContent = ByteString::FromUnicode(wsImage); - pImageFileRead = pdfium::MakeRetain<CFX_MemoryStream>( - const_cast<uint8_t*>(bsContent.raw_str()), bsContent.GetLength(), - false); - } - } else { - WideString wsURL = wsHref; - if (wsURL.Left(7) != L"http://" && wsURL.Left(6) != L"ftp://") { - RetainPtr<CFX_DIBitmap> pBitmap = - pDoc->GetPDFNamedImage(wsURL.AsStringView(), iImageXDpi, iImageYDpi); - if (pBitmap) { - bNameImage = true; - return pBitmap; - } - } - pImageFileRead = pDoc->GetDocEnvironment()->OpenLinkedFile(pDoc, wsURL); - } - if (!pImageFileRead) { - FX_Free(pImageBuffer); - return nullptr; - } - bNameImage = false; - RetainPtr<CFX_DIBitmap> pBitmap = - XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi); - FX_Free(pImageBuffer); - return pBitmap; -} - -class CXFA_TextLayoutData : public CXFA_WidgetLayoutData { - public: - CXFA_TextLayoutData() {} - ~CXFA_TextLayoutData() override {} - - CXFA_TextLayout* GetTextLayout() const { return m_pTextLayout.get(); } - CXFA_TextProvider* GetTextProvider() const { return m_pTextProvider.get(); } - - void LoadText(CXFA_FFDoc* doc, CXFA_WidgetAcc* pAcc) { - if (m_pTextLayout) - return; - - m_pTextProvider = pdfium::MakeUnique<CXFA_TextProvider>( - pAcc->GetNode(), XFA_TEXTPROVIDERTYPE_Text); - m_pTextLayout = - pdfium::MakeUnique<CXFA_TextLayout>(doc, m_pTextProvider.get()); - } - - private: - std::unique_ptr<CXFA_TextLayout> m_pTextLayout; - std::unique_ptr<CXFA_TextProvider> m_pTextProvider; -}; - -class CXFA_ImageLayoutData : public CXFA_WidgetLayoutData { - public: - CXFA_ImageLayoutData() - : m_bNamedImage(false), m_iImageXDpi(0), m_iImageYDpi(0) {} - - ~CXFA_ImageLayoutData() override {} - - bool LoadImageData(CXFA_FFDoc* doc, CXFA_WidgetAcc* pAcc) { - if (m_pDIBitmap) - return true; - - CXFA_Value* value = pAcc->GetNode()->GetFormValueIfExists(); - if (!value) - return false; - - CXFA_Image* image = value->GetImageIfExists(); - if (!image) - return false; - - pAcc->SetImageImage(XFA_LoadImageData(doc, image, m_bNamedImage, - m_iImageXDpi, m_iImageYDpi)); - return !!m_pDIBitmap; - } - - RetainPtr<CFX_DIBitmap> m_pDIBitmap; - bool m_bNamedImage; - int32_t m_iImageXDpi; - int32_t m_iImageYDpi; -}; - -class CXFA_FieldLayoutData : public CXFA_WidgetLayoutData { - public: - CXFA_FieldLayoutData() {} - ~CXFA_FieldLayoutData() override {} - - bool LoadCaption(CXFA_FFDoc* doc, CXFA_WidgetAcc* pAcc) { - if (m_pCapTextLayout) - return true; - CXFA_Caption* caption = pAcc->GetNode()->GetCaptionIfExists(); - if (!caption || caption->IsHidden()) - return false; - - m_pCapTextProvider = pdfium::MakeUnique<CXFA_TextProvider>( - pAcc->GetNode(), XFA_TEXTPROVIDERTYPE_Caption); - m_pCapTextLayout = - pdfium::MakeUnique<CXFA_TextLayout>(doc, m_pCapTextProvider.get()); - return true; - } - - std::unique_ptr<CXFA_TextLayout> m_pCapTextLayout; - std::unique_ptr<CXFA_TextProvider> m_pCapTextProvider; - std::unique_ptr<CFDE_TextOut> m_pTextOut; - std::vector<float> m_FieldSplitArray; -}; - -class CXFA_TextEditData : public CXFA_FieldLayoutData {}; - -class CXFA_ImageEditData : public CXFA_FieldLayoutData { - public: - CXFA_ImageEditData() - : m_bNamedImage(false), m_iImageXDpi(0), m_iImageYDpi(0) {} - - ~CXFA_ImageEditData() override {} - - bool LoadImageData(CXFA_FFDoc* doc, CXFA_WidgetAcc* pAcc) { - if (m_pDIBitmap) - return true; - - CXFA_Value* value = pAcc->GetNode()->GetFormValueIfExists(); - if (!value) - return false; - - CXFA_Image* image = value->GetImageIfExists(); - if (!image) - return false; - - pAcc->SetImageEditImage(XFA_LoadImageData(doc, image, m_bNamedImage, - m_iImageXDpi, m_iImageYDpi)); - return !!m_pDIBitmap; - } - - RetainPtr<CFX_DIBitmap> m_pDIBitmap; - bool m_bNamedImage; - int32_t m_iImageXDpi; - int32_t m_iImageYDpi; -}; - -bool SplitDateTime(const WideString& wsDateTime, - WideString& wsDate, - WideString& wsTime) { - wsDate = L""; - wsTime = L""; - if (wsDateTime.IsEmpty()) - return false; - - auto nSplitIndex = wsDateTime.Find('T'); - if (!nSplitIndex.has_value()) - nSplitIndex = wsDateTime.Find(' '); - if (!nSplitIndex.has_value()) - return false; - - wsDate = wsDateTime.Left(nSplitIndex.value()); - if (!wsDate.IsEmpty()) { - if (!std::any_of(wsDate.begin(), wsDate.end(), std::iswdigit)) - return false; - } - wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex.value() - 1); - if (!wsTime.IsEmpty()) { - if (!std::any_of(wsTime.begin(), wsTime.end(), std::iswdigit)) - return false; - } - return true; -} - -} // namespace - -CXFA_WidgetAcc::CXFA_WidgetAcc(CXFA_Node* pNode) : m_pNode(pNode) { - ASSERT(m_pNode); -} - -CXFA_WidgetAcc::~CXFA_WidgetAcc() = default; - -void CXFA_WidgetAcc::ResetData() { - WideString wsValue; - switch (m_pNode->GetUIType()) { - case XFA_Element::ImageEdit: { - CXFA_Value* imageValue = m_pNode->GetDefaultValueIfExists(); - CXFA_Image* image = imageValue ? imageValue->GetImageIfExists() : nullptr; - WideString wsContentType, wsHref; - if (image) { - wsValue = image->GetContent(); - wsContentType = image->GetContentType(); - wsHref = image->GetHref(); - } - SetImageEdit(wsContentType, wsHref, wsValue); - break; - } - case XFA_Element::ExclGroup: { - CXFA_Node* pNextChild = m_pNode->GetFirstContainerChild(); - while (pNextChild) { - CXFA_Node* pChild = pNextChild; - if (!pChild->IsWidgetReady()) - continue; - - CXFA_WidgetAcc* pAcc = pChild->GetWidgetAcc(); - bool done = false; - if (wsValue.IsEmpty()) { - CXFA_Value* defValue = pAcc->GetNode()->GetDefaultValueIfExists(); - if (defValue) { - wsValue = defValue->GetChildValueContent(); - SetValue(XFA_VALUEPICTURE_Raw, wsValue); - pAcc->SetValue(XFA_VALUEPICTURE_Raw, wsValue); - done = true; - } - } - if (!done) { - CXFA_Items* pItems = - pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false); - if (!pItems) - continue; - - WideString itemText; - if (pItems->CountChildren(XFA_Element::Unknown, false) > 1) { - itemText = - pItems->GetChild<CXFA_Node>(1, XFA_Element::Unknown, false) - ->JSObject() - ->GetContent(false); - } - pAcc->SetValue(XFA_VALUEPICTURE_Raw, itemText); - } - pNextChild = pChild->GetNextContainerSibling(); - } - break; - } - case XFA_Element::ChoiceList: - ClearAllSelections(); - default: { - CXFA_Value* defValue = m_pNode->GetDefaultValueIfExists(); - if (defValue) - wsValue = defValue->GetChildValueContent(); - - SetValue(XFA_VALUEPICTURE_Raw, wsValue); - break; - } - } -} - -void CXFA_WidgetAcc::SetImageEdit(const WideString& wsContentType, - const WideString& wsHref, - const WideString& wsData) { - CXFA_Value* formValue = m_pNode->GetFormValueIfExists(); - CXFA_Image* image = formValue ? formValue->GetImageIfExists() : nullptr; - if (image) { - image->SetContentType(WideString(wsContentType)); - image->SetHref(wsHref); - } - - m_pNode->JSObject()->SetContent(wsData, GetFormatDataValue(wsData), true, - false, true); - - CXFA_Node* pBind = m_pNode->GetBindData(); - if (!pBind) { - if (image) - image->SetTransferEncoding(XFA_AttributeEnum::Base64); - return; - } - pBind->JSObject()->SetCData(XFA_Attribute::ContentType, wsContentType, false, - false); - CXFA_Node* pHrefNode = pBind->GetFirstChild(); - if (pHrefNode) { - pHrefNode->JSObject()->SetCData(XFA_Attribute::Value, wsHref, false, false); - } else { - CFX_XMLNode* pXMLNode = pBind->GetXMLMappingNode(); - ASSERT(pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element); - static_cast<CFX_XMLElement*>(pXMLNode)->SetString(L"href", wsHref); - } -} - -CXFA_FFWidget* CXFA_WidgetAcc::GetNextWidget(CXFA_FFWidget* pWidget) { - return static_cast<CXFA_FFWidget*>(pWidget->GetNext()); -} - -void CXFA_WidgetAcc::UpdateUIDisplay(CXFA_FFDocView* docView, - CXFA_FFWidget* pExcept) { - CXFA_FFWidget* pWidget = docView->GetWidgetForNode(m_pNode); - for (; pWidget; pWidget = GetNextWidget(pWidget)) { - if (pWidget == pExcept || !pWidget->IsLoaded() || - (m_pNode->GetUIType() != XFA_Element::CheckButton && - pWidget->IsFocused())) { - continue; - } - pWidget->UpdateFWLData(); - pWidget->AddInvalidateRect(); - } -} - -void CXFA_WidgetAcc::CalcCaptionSize(CXFA_FFDoc* doc, CFX_SizeF& szCap) { - CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); - if (!caption || !caption->IsVisible()) - return; - - LoadCaption(doc); - - XFA_Element eUIType = m_pNode->GetUIType(); - XFA_AttributeEnum iCapPlacement = caption->GetPlacementType(); - float fCapReserve = caption->GetReserve(); - const bool bVert = iCapPlacement == XFA_AttributeEnum::Top || - iCapPlacement == XFA_AttributeEnum::Bottom; - const bool bReserveExit = fCapReserve > 0.01; - CXFA_TextLayout* pCapTextLayout = - static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) - ->m_pCapTextLayout.get(); - if (pCapTextLayout) { - if (!bVert && eUIType != XFA_Element::Button) - szCap.width = fCapReserve; - - CFX_SizeF minSize; - szCap = pCapTextLayout->CalcSize(minSize, szCap); - if (bReserveExit) - bVert ? szCap.height = fCapReserve : szCap.width = fCapReserve; - } else { - float fFontSize = 10.0f; - CXFA_Font* font = caption->GetFontIfExists(); - if (font) { - fFontSize = font->GetFontSize(); - } else { - CXFA_Font* widgetfont = m_pNode->GetFontIfExists(); - if (widgetfont) - fFontSize = widgetfont->GetFontSize(); - } - - if (bVert) { - szCap.height = fCapReserve > 0 ? fCapReserve : fFontSize; - } else { - szCap.width = fCapReserve > 0 ? fCapReserve : 0; - szCap.height = fFontSize; - } - } - - CXFA_Margin* captionMargin = caption->GetMarginIfExists(); - if (!captionMargin) - return; - - float fLeftInset = captionMargin->GetLeftInset(); - float fTopInset = captionMargin->GetTopInset(); - float fRightInset = captionMargin->GetRightInset(); - float fBottomInset = captionMargin->GetBottomInset(); - if (bReserveExit) { - bVert ? (szCap.width += fLeftInset + fRightInset) - : (szCap.height += fTopInset + fBottomInset); - } else { - szCap.width += fLeftInset + fRightInset; - szCap.height += fTopInset + fBottomInset; - } -} - -bool CXFA_WidgetAcc::CalculateFieldAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size) { - CFX_SizeF szCap; - CalcCaptionSize(doc, szCap); - - CFX_RectF rtUIMargin = m_pNode->GetUIMargin(); - size.width += rtUIMargin.left + rtUIMargin.width; - size.height += rtUIMargin.top + rtUIMargin.height; - if (szCap.width > 0 && szCap.height > 0) { - CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); - XFA_AttributeEnum placement = caption ? caption->GetPlacementType() - : CXFA_Caption::kDefaultPlacementType; - switch (placement) { - case XFA_AttributeEnum::Left: - case XFA_AttributeEnum::Right: - case XFA_AttributeEnum::Inline: { - size.width += szCap.width; - size.height = std::max(size.height, szCap.height); - } break; - case XFA_AttributeEnum::Top: - case XFA_AttributeEnum::Bottom: { - size.height += szCap.height; - size.width = std::max(size.width, szCap.width); - } - default: - break; - } - } - return CalculateWidgetAutoSize(size); -} - -bool CXFA_WidgetAcc::CalculateWidgetAutoSize(CFX_SizeF& size) { - CXFA_Margin* margin = m_pNode->GetMarginIfExists(); - if (margin) { - size.width += margin->GetLeftInset() + margin->GetRightInset(); - size.height += margin->GetTopInset() + margin->GetBottomInset(); - } - - CXFA_Para* para = m_pNode->GetParaIfExists(); - if (para) - size.width += para->GetMarginLeft() + para->GetTextIndent(); - - Optional<float> width = m_pNode->TryWidth(); - if (width) { - size.width = *width; - } else { - Optional<float> min = m_pNode->TryMinWidth(); - if (min) - size.width = std::max(size.width, *min); - - Optional<float> max = m_pNode->TryMaxWidth(); - if (max && *max > 0) - size.width = std::min(size.width, *max); - } - - Optional<float> height = m_pNode->TryHeight(); - if (height) { - size.height = *height; - } else { - Optional<float> min = m_pNode->TryMinHeight(); - if (min) - size.height = std::max(size.height, *min); - - Optional<float> max = m_pNode->TryMaxHeight(); - if (max && *max > 0) - size.height = std::min(size.height, *max); - } - return true; -} - -void CXFA_WidgetAcc::CalculateTextContentSize(CXFA_FFDoc* doc, - CFX_SizeF& size) { - float fFontSize = m_pNode->GetFontSize(); - WideString wsText = GetValue(XFA_VALUEPICTURE_Display); - if (wsText.IsEmpty()) { - size.height += fFontSize; - return; - } - - wchar_t wcEnter = '\n'; - wchar_t wsLast = wsText[wsText.GetLength() - 1]; - if (wsLast == wcEnter) - wsText = wsText + wcEnter; - - CXFA_FieldLayoutData* layoutData = - static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()); - if (!layoutData->m_pTextOut) { - layoutData->m_pTextOut = pdfium::MakeUnique<CFDE_TextOut>(); - CFDE_TextOut* pTextOut = layoutData->m_pTextOut.get(); - pTextOut->SetFont(GetFDEFont(doc)); - pTextOut->SetFontSize(fFontSize); - pTextOut->SetLineBreakTolerance(fFontSize * 0.2f); - pTextOut->SetLineSpace(m_pNode->GetLineHeight()); - - FDE_TextStyle dwStyles; - dwStyles.last_line_height_ = true; - if (m_pNode->GetUIType() == XFA_Element::TextEdit && IsMultiLine()) - dwStyles.line_wrap_ = true; - - pTextOut->SetStyles(dwStyles); - } - layoutData->m_pTextOut->CalcLogicSize(wsText, size); -} - -bool CXFA_WidgetAcc::CalculateTextEditAutoSize(CXFA_FFDoc* doc, - CFX_SizeF& size) { - if (size.width > 0) { - CFX_SizeF szOrz = size; - CFX_SizeF szCap; - CalcCaptionSize(doc, szCap); - bool bCapExit = szCap.width > 0.01 && szCap.height > 0.01; - XFA_AttributeEnum iCapPlacement = XFA_AttributeEnum::Unknown; - if (bCapExit) { - CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); - iCapPlacement = caption ? caption->GetPlacementType() - : CXFA_Caption::kDefaultPlacementType; - switch (iCapPlacement) { - case XFA_AttributeEnum::Left: - case XFA_AttributeEnum::Right: - case XFA_AttributeEnum::Inline: { - size.width -= szCap.width; - } - default: - break; - } - } - CFX_RectF rtUIMargin = m_pNode->GetUIMargin(); - size.width -= rtUIMargin.left + rtUIMargin.width; - CXFA_Margin* margin = m_pNode->GetMarginIfExists(); - if (margin) - size.width -= margin->GetLeftInset() + margin->GetRightInset(); - - CalculateTextContentSize(doc, size); - size.height += rtUIMargin.top + rtUIMargin.height; - if (bCapExit) { - switch (iCapPlacement) { - case XFA_AttributeEnum::Left: - case XFA_AttributeEnum::Right: - case XFA_AttributeEnum::Inline: { - size.height = std::max(size.height, szCap.height); - } break; - case XFA_AttributeEnum::Top: - case XFA_AttributeEnum::Bottom: { - size.height += szCap.height; - } - default: - break; - } - } - size.width = szOrz.width; - return CalculateWidgetAutoSize(size); - } - CalculateTextContentSize(doc, size); - return CalculateFieldAutoSize(doc, size); -} - -bool CXFA_WidgetAcc::CalculateCheckButtonAutoSize(CXFA_FFDoc* doc, - CFX_SizeF& size) { - float fCheckSize = GetCheckButtonSize(); - size = CFX_SizeF(fCheckSize, fCheckSize); - return CalculateFieldAutoSize(doc, size); -} - -bool CXFA_WidgetAcc::CalculatePushButtonAutoSize(CXFA_FFDoc* doc, - CFX_SizeF& size) { - CalcCaptionSize(doc, size); - return CalculateWidgetAutoSize(size); -} - -CFX_SizeF CXFA_WidgetAcc::CalculateImageSize(float img_width, - float img_height, - float dpi_x, - float dpi_y) { - CFX_RectF rtImage(0, 0, XFA_UnitPx2Pt(img_width, dpi_x), - XFA_UnitPx2Pt(img_height, dpi_y)); - - CFX_RectF rtFit; - Optional<float> width = m_pNode->TryWidth(); - if (width) { - rtFit.width = *width; - GetWidthWithoutMargin(rtFit.width); - } else { - rtFit.width = rtImage.width; - } - - Optional<float> height = m_pNode->TryHeight(); - if (height) { - rtFit.height = *height; - GetHeightWithoutMargin(rtFit.height); - } else { - rtFit.height = rtImage.height; - } - - return rtFit.Size(); -} - -bool CXFA_WidgetAcc::CalculateImageAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size) { - if (!GetImageImage()) - LoadImageImage(doc); - - size.clear(); - RetainPtr<CFX_DIBitmap> pBitmap = GetImageImage(); - if (!pBitmap) - return CalculateWidgetAutoSize(size); - - int32_t iImageXDpi = 0; - int32_t iImageYDpi = 0; - GetImageDpi(iImageXDpi, iImageYDpi); - - size = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(), - iImageXDpi, iImageYDpi); - return CalculateWidgetAutoSize(size); -} - -bool CXFA_WidgetAcc::CalculateImageEditAutoSize(CXFA_FFDoc* doc, - CFX_SizeF& size) { - if (!GetImageEditImage()) - LoadImageEditImage(doc); - - size.clear(); - RetainPtr<CFX_DIBitmap> pBitmap = GetImageEditImage(); - if (!pBitmap) - return CalculateFieldAutoSize(doc, size); - - int32_t iImageXDpi = 0; - int32_t iImageYDpi = 0; - GetImageEditDpi(iImageXDpi, iImageYDpi); - - size = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(), - iImageXDpi, iImageYDpi); - return CalculateFieldAutoSize(doc, size); -} - -bool CXFA_WidgetAcc::LoadImageImage(CXFA_FFDoc* doc) { - InitLayoutData(); - return static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()) - ->LoadImageData(doc, this); -} - -bool CXFA_WidgetAcc::LoadImageEditImage(CXFA_FFDoc* doc) { - InitLayoutData(); - return static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()) - ->LoadImageData(doc, this); -} - -void CXFA_WidgetAcc::GetImageDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) { - CXFA_ImageLayoutData* pData = - static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()); - iImageXDpi = pData->m_iImageXDpi; - iImageYDpi = pData->m_iImageYDpi; -} - -void CXFA_WidgetAcc::GetImageEditDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) { - CXFA_ImageEditData* pData = - static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()); - iImageXDpi = pData->m_iImageXDpi; - iImageYDpi = pData->m_iImageYDpi; -} - -void CXFA_WidgetAcc::LoadText(CXFA_FFDoc* doc) { - InitLayoutData(); - static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->LoadText(doc, this); -} - -float CXFA_WidgetAcc::CalculateWidgetAutoWidth(float fWidthCalc) { - CXFA_Margin* margin = m_pNode->GetMarginIfExists(); - if (margin) - fWidthCalc += margin->GetLeftInset() + margin->GetRightInset(); - - Optional<float> min = m_pNode->TryMinWidth(); - if (min) - fWidthCalc = std::max(fWidthCalc, *min); - - Optional<float> max = m_pNode->TryMaxWidth(); - if (max && *max > 0) - fWidthCalc = std::min(fWidthCalc, *max); - - return fWidthCalc; -} - -float CXFA_WidgetAcc::GetWidthWithoutMargin(float fWidthCalc) { - CXFA_Margin* margin = m_pNode->GetMarginIfExists(); - if (margin) - fWidthCalc -= margin->GetLeftInset() + margin->GetRightInset(); - return fWidthCalc; -} - -float CXFA_WidgetAcc::CalculateWidgetAutoHeight(float fHeightCalc) { - CXFA_Margin* margin = m_pNode->GetMarginIfExists(); - if (margin) - fHeightCalc += margin->GetTopInset() + margin->GetBottomInset(); - - Optional<float> min = m_pNode->TryMinHeight(); - if (min) - fHeightCalc = std::max(fHeightCalc, *min); - - Optional<float> max = m_pNode->TryMaxHeight(); - if (max && *max > 0) - fHeightCalc = std::min(fHeightCalc, *max); - - return fHeightCalc; -} - -float CXFA_WidgetAcc::GetHeightWithoutMargin(float fHeightCalc) { - CXFA_Margin* margin = m_pNode->GetMarginIfExists(); - if (margin) - fHeightCalc -= margin->GetTopInset() + margin->GetBottomInset(); - return fHeightCalc; -} - -void CXFA_WidgetAcc::StartWidgetLayout(CXFA_FFDoc* doc, - float& fCalcWidth, - float& fCalcHeight) { - InitLayoutData(); - - XFA_Element eUIType = m_pNode->GetUIType(); - if (eUIType == XFA_Element::Text) { - m_pLayoutData->m_fWidgetHeight = m_pNode->TryHeight().value_or(-1); - StartTextLayout(doc, fCalcWidth, fCalcHeight); - return; - } - if (fCalcWidth > 0 && fCalcHeight > 0) - return; - - m_pLayoutData->m_fWidgetHeight = -1; - float fWidth = 0; - if (fCalcWidth > 0 && fCalcHeight < 0) { - Optional<float> height = m_pNode->TryHeight(); - if (height) - fCalcHeight = *height; - else - CalculateAccWidthAndHeight(doc, eUIType, fCalcWidth, fCalcHeight); - - m_pLayoutData->m_fWidgetHeight = fCalcHeight; - return; - } - if (fCalcWidth < 0 && fCalcHeight < 0) { - Optional<float> height; - Optional<float> width = m_pNode->TryWidth(); - if (width) { - fWidth = *width; - - height = m_pNode->TryHeight(); - if (height) - fCalcHeight = *height; - } - if (!width || !height) - CalculateAccWidthAndHeight(doc, eUIType, fWidth, fCalcHeight); - - fCalcWidth = fWidth; - } - m_pLayoutData->m_fWidgetHeight = fCalcHeight; -} - -void CXFA_WidgetAcc::CalculateAccWidthAndHeight(CXFA_FFDoc* doc, - XFA_Element eUIType, - float& fWidth, - float& fCalcHeight) { - CFX_SizeF sz(fWidth, m_pLayoutData->m_fWidgetHeight); - switch (eUIType) { - case XFA_Element::Barcode: - case XFA_Element::ChoiceList: - case XFA_Element::Signature: - CalculateFieldAutoSize(doc, sz); - break; - case XFA_Element::ImageEdit: - CalculateImageEditAutoSize(doc, sz); - break; - case XFA_Element::Button: - CalculatePushButtonAutoSize(doc, sz); - break; - case XFA_Element::CheckButton: - CalculateCheckButtonAutoSize(doc, sz); - break; - case XFA_Element::DateTimeEdit: - case XFA_Element::NumericEdit: - case XFA_Element::PasswordEdit: - case XFA_Element::TextEdit: - CalculateTextEditAutoSize(doc, sz); - break; - case XFA_Element::Image: - CalculateImageAutoSize(doc, sz); - break; - case XFA_Element::Arc: - case XFA_Element::Line: - case XFA_Element::Rectangle: - case XFA_Element::Subform: - case XFA_Element::ExclGroup: - CalculateWidgetAutoSize(sz); - break; - default: - break; - } - fWidth = sz.width; - m_pLayoutData->m_fWidgetHeight = sz.height; - fCalcHeight = sz.height; -} - -bool CXFA_WidgetAcc::FindSplitPos(CXFA_FFDocView* docView, - int32_t iBlockIndex, - float& fCalcHeight) { - XFA_Element eUIType = m_pNode->GetUIType(); - if (eUIType == XFA_Element::Subform) - return false; - - if (eUIType != XFA_Element::Text && eUIType != XFA_Element::TextEdit && - eUIType != XFA_Element::NumericEdit && - eUIType != XFA_Element::PasswordEdit) { - fCalcHeight = 0; - return true; - } - - float fTopInset = 0; - float fBottomInset = 0; - if (iBlockIndex == 0) { - CXFA_Margin* margin = m_pNode->GetMarginIfExists(); - if (margin) { - fTopInset = margin->GetTopInset(); - fBottomInset = margin->GetBottomInset(); - } - - CFX_RectF rtUIMargin = m_pNode->GetUIMargin(); - fTopInset += rtUIMargin.top; - fBottomInset += rtUIMargin.width; - } - if (eUIType == XFA_Element::Text) { - float fHeight = fCalcHeight; - if (iBlockIndex == 0) { - fCalcHeight = fCalcHeight - fTopInset; - if (fCalcHeight < 0) - fCalcHeight = 0; - } - - CXFA_TextLayout* pTextLayout = - static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout(); - fCalcHeight = - pTextLayout->DoLayout(iBlockIndex, fCalcHeight, fCalcHeight, - m_pLayoutData->m_fWidgetHeight - fTopInset); - if (fCalcHeight != 0) { - if (iBlockIndex == 0) - fCalcHeight = fCalcHeight + fTopInset; - if (fabs(fHeight - fCalcHeight) < XFA_FLOAT_PERCISION) - return false; - } - return true; - } - XFA_AttributeEnum iCapPlacement = XFA_AttributeEnum::Unknown; - float fCapReserve = 0; - if (iBlockIndex == 0) { - CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); - if (caption && !caption->IsHidden()) { - iCapPlacement = caption->GetPlacementType(); - fCapReserve = caption->GetReserve(); - } - if (iCapPlacement == XFA_AttributeEnum::Top && - fCalcHeight < fCapReserve + fTopInset) { - fCalcHeight = 0; - return true; - } - if (iCapPlacement == XFA_AttributeEnum::Bottom && - m_pLayoutData->m_fWidgetHeight - fCapReserve - fBottomInset) { - fCalcHeight = 0; - return true; - } - if (iCapPlacement != XFA_AttributeEnum::Top) - fCapReserve = 0; - } - CXFA_FieldLayoutData* pFieldData = - static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()); - int32_t iLinesCount = 0; - float fHeight = m_pLayoutData->m_fWidgetHeight; - if (GetValue(XFA_VALUEPICTURE_Display).IsEmpty()) { - iLinesCount = 1; - } else { - if (!pFieldData->m_pTextOut) { - // TODO(dsinclair): Inline fWidth when the 2nd param of - // CalculateAccWidthAndHeight isn't a ref-param. - float fWidth = m_pNode->TryWidth().value_or(0); - CalculateAccWidthAndHeight(docView->GetDoc(), eUIType, fWidth, fHeight); - } - iLinesCount = pFieldData->m_pTextOut->GetTotalLines(); - } - std::vector<float>* pFieldArray = &pFieldData->m_FieldSplitArray; - int32_t iFieldSplitCount = pdfium::CollectionSize<int32_t>(*pFieldArray); - for (int32_t i = 0; i < iBlockIndex * 3; i += 3) { - iLinesCount -= (int32_t)(*pFieldArray)[i + 1]; - fHeight -= (*pFieldArray)[i + 2]; - } - if (iLinesCount == 0) - return false; - - float fLineHeight = m_pNode->GetLineHeight(); - float fFontSize = m_pNode->GetFontSize(); - float fTextHeight = iLinesCount * fLineHeight - fLineHeight + fFontSize; - float fSpaceAbove = 0; - float fStartOffset = 0; - if (fHeight > 0.1f && iBlockIndex == 0) { - fStartOffset = fTopInset; - fHeight -= (fTopInset + fBottomInset); - CXFA_Para* para = m_pNode->GetParaIfExists(); - if (para) { - fSpaceAbove = para->GetSpaceAbove(); - float fSpaceBelow = para->GetSpaceBelow(); - fHeight -= (fSpaceAbove + fSpaceBelow); - switch (para->GetVerticalAlign()) { - case XFA_AttributeEnum::Top: - fStartOffset += fSpaceAbove; - break; - case XFA_AttributeEnum::Middle: - fStartOffset += ((fHeight - fTextHeight) / 2 + fSpaceAbove); - break; - case XFA_AttributeEnum::Bottom: - fStartOffset += (fHeight - fTextHeight + fSpaceAbove); - break; - default: - NOTREACHED(); - break; - } - } - if (fStartOffset < 0.1f) - fStartOffset = 0; - } - for (int32_t i = iBlockIndex - 1; iBlockIndex > 0 && i < iBlockIndex; i++) { - fStartOffset = (*pFieldArray)[i * 3] - (*pFieldArray)[i * 3 + 2]; - if (fStartOffset < 0.1f) - fStartOffset = 0; - } - if (iFieldSplitCount / 3 == (iBlockIndex + 1)) - (*pFieldArray)[0] = fStartOffset; - else - pFieldArray->push_back(fStartOffset); - - XFA_VERSION version = docView->GetDoc()->GetXFADoc()->GetCurVersionMode(); - bool bCanSplitNoContent = false; - XFA_AttributeEnum eLayoutMode = GetNode() - ->GetParent() - ->JSObject() - ->TryEnum(XFA_Attribute::Layout, true) - .value_or(XFA_AttributeEnum::Position); - if ((eLayoutMode == XFA_AttributeEnum::Position || - eLayoutMode == XFA_AttributeEnum::Tb || - eLayoutMode == XFA_AttributeEnum::Row || - eLayoutMode == XFA_AttributeEnum::Table) && - version > XFA_VERSION_208) { - bCanSplitNoContent = true; - } - if ((eLayoutMode == XFA_AttributeEnum::Tb || - eLayoutMode == XFA_AttributeEnum::Row || - eLayoutMode == XFA_AttributeEnum::Table) && - version <= XFA_VERSION_208) { - if (fStartOffset < fCalcHeight) { - bCanSplitNoContent = true; - } else { - fCalcHeight = 0; - return true; - } - } - if (bCanSplitNoContent) { - if ((fCalcHeight - fTopInset - fSpaceAbove < fLineHeight)) { - fCalcHeight = 0; - return true; - } - if (fStartOffset + XFA_FLOAT_PERCISION >= fCalcHeight) { - if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { - (*pFieldArray)[iBlockIndex * 3 + 1] = 0; - (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; - } else { - pFieldArray->push_back(0); - pFieldArray->push_back(fCalcHeight); - } - return false; - } - if (fCalcHeight - fStartOffset < fLineHeight) { - fCalcHeight = fStartOffset; - if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { - (*pFieldArray)[iBlockIndex * 3 + 1] = 0; - (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; - } else { - pFieldArray->push_back(0); - pFieldArray->push_back(fCalcHeight); - } - return true; - } - float fTextNum = - fCalcHeight + XFA_FLOAT_PERCISION - fCapReserve - fStartOffset; - int32_t iLineNum = - (int32_t)((fTextNum + (fLineHeight - fFontSize)) / fLineHeight); - if (iLineNum >= iLinesCount) { - if (fCalcHeight - fStartOffset - fTextHeight >= fFontSize) { - if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { - (*pFieldArray)[iBlockIndex * 3 + 1] = (float)iLinesCount; - (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; - } else { - pFieldArray->push_back((float)iLinesCount); - pFieldArray->push_back(fCalcHeight); - } - return false; - } - if (fHeight - fStartOffset - fTextHeight < fFontSize) { - iLineNum -= 1; - if (iLineNum == 0) { - fCalcHeight = 0; - return true; - } - } else { - iLineNum = (int32_t)(fTextNum / fLineHeight); - } - } - if (iLineNum > 0) { - float fSplitHeight = iLineNum * fLineHeight + fCapReserve + fStartOffset; - if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { - (*pFieldArray)[iBlockIndex * 3 + 1] = (float)iLineNum; - (*pFieldArray)[iBlockIndex * 3 + 2] = fSplitHeight; - } else { - pFieldArray->push_back((float)iLineNum); - pFieldArray->push_back(fSplitHeight); - } - if (fabs(fSplitHeight - fCalcHeight) < XFA_FLOAT_PERCISION) - return false; - - fCalcHeight = fSplitHeight; - return true; - } - } - fCalcHeight = 0; - return true; -} - -void CXFA_WidgetAcc::InitLayoutData() { - if (m_pLayoutData) - return; - - switch (m_pNode->GetUIType()) { - case XFA_Element::Text: - m_pLayoutData = pdfium::MakeUnique<CXFA_TextLayoutData>(); - return; - case XFA_Element::TextEdit: - m_pLayoutData = pdfium::MakeUnique<CXFA_TextEditData>(); - return; - case XFA_Element::Image: - m_pLayoutData = pdfium::MakeUnique<CXFA_ImageLayoutData>(); - return; - case XFA_Element::ImageEdit: - m_pLayoutData = pdfium::MakeUnique<CXFA_ImageEditData>(); - return; - default: - break; - } - if (m_pNode && m_pNode->GetElementType() == XFA_Element::Field) { - m_pLayoutData = pdfium::MakeUnique<CXFA_FieldLayoutData>(); - return; - } - m_pLayoutData = pdfium::MakeUnique<CXFA_WidgetLayoutData>(); -} - -void CXFA_WidgetAcc::StartTextLayout(CXFA_FFDoc* doc, - float& fCalcWidth, - float& fCalcHeight) { - LoadText(doc); - - CXFA_TextLayout* pTextLayout = - static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout(); - float fTextHeight = 0; - if (fCalcWidth > 0 && fCalcHeight > 0) { - float fWidth = GetWidthWithoutMargin(fCalcWidth); - pTextLayout->StartLayout(fWidth); - fTextHeight = fCalcHeight; - fTextHeight = GetHeightWithoutMargin(fTextHeight); - pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight); - return; - } - if (fCalcWidth > 0 && fCalcHeight < 0) { - float fWidth = GetWidthWithoutMargin(fCalcWidth); - pTextLayout->StartLayout(fWidth); - } - - if (fCalcWidth < 0 && fCalcHeight < 0) { - Optional<float> width = m_pNode->TryWidth(); - if (width) { - pTextLayout->StartLayout(GetWidthWithoutMargin(*width)); - fCalcWidth = *width; - } else { - float fMaxWidth = CalculateWidgetAutoWidth(pTextLayout->StartLayout(-1)); - pTextLayout->StartLayout(GetWidthWithoutMargin(fMaxWidth)); - fCalcWidth = fMaxWidth; - } - } - - if (m_pLayoutData->m_fWidgetHeight < 0) { - m_pLayoutData->m_fWidgetHeight = pTextLayout->GetLayoutHeight(); - m_pLayoutData->m_fWidgetHeight = - CalculateWidgetAutoHeight(m_pLayoutData->m_fWidgetHeight); - } - fTextHeight = m_pLayoutData->m_fWidgetHeight; - fTextHeight = GetHeightWithoutMargin(fTextHeight); - pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight); - fCalcHeight = m_pLayoutData->m_fWidgetHeight; -} - -bool CXFA_WidgetAcc::LoadCaption(CXFA_FFDoc* doc) { - InitLayoutData(); - return static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) - ->LoadCaption(doc, this); -} - -CXFA_TextLayout* CXFA_WidgetAcc::GetCaptionTextLayout() { - return m_pLayoutData - ? static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) - ->m_pCapTextLayout.get() - : nullptr; -} - -CXFA_TextLayout* CXFA_WidgetAcc::GetTextLayout() { - return m_pLayoutData - ? static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get()) - ->GetTextLayout() - : nullptr; -} - -RetainPtr<CFX_DIBitmap> CXFA_WidgetAcc::GetImageImage() { - return m_pLayoutData - ? static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()) - ->m_pDIBitmap - : nullptr; -} - -RetainPtr<CFX_DIBitmap> CXFA_WidgetAcc::GetImageEditImage() { - return m_pLayoutData - ? static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()) - ->m_pDIBitmap - : nullptr; -} - -void CXFA_WidgetAcc::SetImageImage(const RetainPtr<CFX_DIBitmap>& newImage) { - CXFA_ImageLayoutData* pData = - static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()); - if (pData->m_pDIBitmap != newImage) - pData->m_pDIBitmap = newImage; -} - -void CXFA_WidgetAcc::SetImageEditImage( - const RetainPtr<CFX_DIBitmap>& newImage) { - CXFA_ImageEditData* pData = - static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()); - if (pData->m_pDIBitmap != newImage) - pData->m_pDIBitmap = newImage; -} - -RetainPtr<CFGAS_GEFont> CXFA_WidgetAcc::GetFDEFont(CXFA_FFDoc* doc) { - WideString wsFontName = L"Courier"; - uint32_t dwFontStyle = 0; - CXFA_Font* font = m_pNode->GetFontIfExists(); - if (font) { - if (font->IsBold()) - dwFontStyle |= FXFONT_BOLD; - if (font->IsItalic()) - dwFontStyle |= FXFONT_ITALIC; - - wsFontName = font->GetTypeface(); - } - return doc->GetApp()->GetXFAFontMgr()->GetFont(doc, wsFontName.AsStringView(), - dwFontStyle); -} - -bool CXFA_WidgetAcc::IsOpenAccess() const { - return m_pNode && m_pNode->IsOpenAccess(); -} - -XFA_AttributeEnum CXFA_WidgetAcc::GetButtonHighlight() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - if (pUIChild) - return pUIChild->JSObject()->GetEnum(XFA_Attribute::Highlight); - return XFA_AttributeEnum::Inverted; -} - -bool CXFA_WidgetAcc::HasButtonRollover() const { - CXFA_Items* pItems = - m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); - if (!pItems) - return false; - - for (CXFA_Node* pText = pItems->GetFirstChild(); pText; - pText = pText->GetNextSibling()) { - if (pText->JSObject()->GetCData(XFA_Attribute::Name) == L"rollover") - return !pText->JSObject()->GetContent(false).IsEmpty(); - } - return false; -} - -bool CXFA_WidgetAcc::HasButtonDown() const { - CXFA_Items* pItems = - m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); - if (!pItems) - return false; - - for (CXFA_Node* pText = pItems->GetFirstChild(); pText; - pText = pText->GetNextSibling()) { - if (pText->JSObject()->GetCData(XFA_Attribute::Name) == L"down") - return !pText->JSObject()->GetContent(false).IsEmpty(); - } - return false; -} - -bool CXFA_WidgetAcc::IsCheckButtonRound() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - if (pUIChild) - return pUIChild->JSObject()->GetEnum(XFA_Attribute::Shape) == - XFA_AttributeEnum::Round; - return false; -} - -XFA_AttributeEnum CXFA_WidgetAcc::GetCheckButtonMark() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - if (pUIChild) - return pUIChild->JSObject()->GetEnum(XFA_Attribute::Mark); - return XFA_AttributeEnum::Default; -} - -bool CXFA_WidgetAcc::IsRadioButton() { - CXFA_Node* pParent = m_pNode->GetParent(); - return pParent && pParent->GetElementType() == XFA_Element::ExclGroup; -} - -float CXFA_WidgetAcc::GetCheckButtonSize() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - if (pUIChild) { - return pUIChild->JSObject() - ->GetMeasure(XFA_Attribute::Size) - .ToUnit(XFA_Unit::Pt); - } - return CXFA_Measurement(10, XFA_Unit::Pt).ToUnit(XFA_Unit::Pt); -} - -bool CXFA_WidgetAcc::IsAllowNeutral() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - return pUIChild && - pUIChild->JSObject()->GetBoolean(XFA_Attribute::AllowNeutral); -} - -XFA_CHECKSTATE CXFA_WidgetAcc::GetCheckState() { - WideString wsValue = m_pNode->GetRawValue(); - if (wsValue.IsEmpty()) - return XFA_CHECKSTATE_Off; - - auto* pItems = m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); - if (!pItems) - return XFA_CHECKSTATE_Off; - - CXFA_Node* pText = pItems->GetFirstChild(); - int32_t i = 0; - while (pText) { - Optional<WideString> wsContent = pText->JSObject()->TryContent(false, true); - if (wsContent && *wsContent == wsValue) - return static_cast<XFA_CHECKSTATE>(i); - - i++; - pText = pText->GetNextSibling(); - } - return XFA_CHECKSTATE_Off; -} - -void CXFA_WidgetAcc::SetCheckState(XFA_CHECKSTATE eCheckState, bool bNotify) { - CXFA_Node* node = m_pNode->GetExclGroupIfExists(); - if (!node) { - CXFA_Items* pItems = - m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); - if (!pItems) - return; - - int32_t i = -1; - CXFA_Node* pText = pItems->GetFirstChild(); - WideString wsContent; - while (pText) { - i++; - if (i == eCheckState) { - wsContent = pText->JSObject()->GetContent(false); - break; - } - pText = pText->GetNextSibling(); - } - m_pNode->SyncValue(wsContent, bNotify); - - return; - } - - WideString wsValue; - if (eCheckState != XFA_CHECKSTATE_Off) { - if (CXFA_Items* pItems = - m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false)) { - CXFA_Node* pText = pItems->GetFirstChild(); - if (pText) - wsValue = pText->JSObject()->GetContent(false); - } - } - CXFA_Node* pChild = node->GetFirstChild(); - for (; pChild; pChild = pChild->GetNextSibling()) { - if (pChild->GetElementType() != XFA_Element::Field) - continue; - - CXFA_Items* pItem = - pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false); - if (!pItem) - continue; - - CXFA_Node* pItemchild = pItem->GetFirstChild(); - if (!pItemchild) - continue; - - WideString text = pItemchild->JSObject()->GetContent(false); - WideString wsChildValue = text; - if (wsValue != text) { - pItemchild = pItemchild->GetNextSibling(); - if (pItemchild) - wsChildValue = pItemchild->JSObject()->GetContent(false); - else - wsChildValue.clear(); - } - pChild->SyncValue(wsChildValue, bNotify); - } - node->SyncValue(wsValue, bNotify); -} - -CXFA_Node* CXFA_WidgetAcc::GetSelectedMember() { - CXFA_Node* pSelectedMember = nullptr; - WideString wsState = m_pNode->GetRawValue(); - if (wsState.IsEmpty()) - return pSelectedMember; - - for (CXFA_Node* pNode = ToNode(m_pNode->GetFirstChild()); pNode; - pNode = pNode->GetNextSibling()) { - CXFA_WidgetAcc widgetData(pNode); - if (widgetData.GetCheckState() == XFA_CHECKSTATE_On) { - pSelectedMember = pNode; - break; - } - } - return pSelectedMember; -} - -CXFA_Node* CXFA_WidgetAcc::SetSelectedMember(const WideStringView& wsName, - bool bNotify) { - uint32_t nameHash = FX_HashCode_GetW(wsName, false); - for (CXFA_Node* pNode = ToNode(m_pNode->GetFirstChild()); pNode; - pNode = pNode->GetNextSibling()) { - if (pNode->GetNameHash() == nameHash) { - CXFA_WidgetAcc widgetData(pNode); - widgetData.SetCheckState(XFA_CHECKSTATE_On, bNotify); - return pNode; - } - } - return nullptr; -} - -void CXFA_WidgetAcc::SetSelectedMemberByValue(const WideStringView& wsValue, - bool bNotify, - bool bScriptModify, - bool bSyncData) { - WideString wsExclGroup; - for (CXFA_Node* pNode = m_pNode->GetFirstChild(); pNode; - pNode = pNode->GetNextSibling()) { - if (pNode->GetElementType() != XFA_Element::Field) - continue; - - CXFA_Items* pItem = - pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); - if (!pItem) - continue; - - CXFA_Node* pItemchild = pItem->GetFirstChild(); - if (!pItemchild) - continue; - - WideString wsChildValue = pItemchild->JSObject()->GetContent(false); - if (wsValue != wsChildValue) { - pItemchild = pItemchild->GetNextSibling(); - if (pItemchild) - wsChildValue = pItemchild->JSObject()->GetContent(false); - else - wsChildValue.clear(); - } else { - wsExclGroup = wsValue; - } - pNode->JSObject()->SetContent(wsChildValue, wsChildValue, bNotify, - bScriptModify, false); - } - m_pNode->JSObject()->SetContent(wsExclGroup, wsExclGroup, bNotify, - bScriptModify, bSyncData); -} - -CXFA_Node* CXFA_WidgetAcc::GetExclGroupFirstMember() { - CXFA_Node* pExcl = GetNode(); - if (!pExcl) - return nullptr; - - CXFA_Node* pNode = pExcl->GetFirstChild(); - while (pNode) { - if (pNode->GetElementType() == XFA_Element::Field) - return pNode; - - pNode = pNode->GetNextSibling(); - } - return nullptr; -} -CXFA_Node* CXFA_WidgetAcc::GetExclGroupNextMember(CXFA_Node* pNode) { - if (!pNode) - return nullptr; - - CXFA_Node* pNodeField = pNode->GetNextSibling(); - while (pNodeField) { - if (pNodeField->GetElementType() == XFA_Element::Field) - return pNodeField; - - pNodeField = pNodeField->GetNextSibling(); - } - return nullptr; -} - -bool CXFA_WidgetAcc::IsChoiceListCommitOnSelect() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - if (pUIChild) { - return pUIChild->JSObject()->GetEnum(XFA_Attribute::CommitOn) == - XFA_AttributeEnum::Select; - } - return true; -} - -bool CXFA_WidgetAcc::IsChoiceListAllowTextEntry() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - return pUIChild && pUIChild->JSObject()->GetBoolean(XFA_Attribute::TextEntry); -} - -bool CXFA_WidgetAcc::IsChoiceListMultiSelect() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - if (pUIChild) { - return pUIChild->JSObject()->GetEnum(XFA_Attribute::Open) == - XFA_AttributeEnum::MultiSelect; - } - return false; -} - -bool CXFA_WidgetAcc::IsListBox() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - if (!pUIChild) - return false; - - XFA_AttributeEnum attr = pUIChild->JSObject()->GetEnum(XFA_Attribute::Open); - return attr == XFA_AttributeEnum::Always || - attr == XFA_AttributeEnum::MultiSelect; -} - -int32_t CXFA_WidgetAcc::CountChoiceListItems(bool bSaveValue) { - std::vector<CXFA_Node*> pItems; - int32_t iCount = 0; - for (CXFA_Node* pNode = m_pNode->GetFirstChild(); pNode; - pNode = pNode->GetNextSibling()) { - if (pNode->GetElementType() != XFA_Element::Items) - continue; - iCount++; - pItems.push_back(pNode); - if (iCount == 2) - break; - } - if (iCount == 0) - return 0; - - CXFA_Node* pItem = pItems[0]; - if (iCount > 1) { - bool bItemOneHasSave = - pItems[0]->JSObject()->GetBoolean(XFA_Attribute::Save); - bool bItemTwoHasSave = - pItems[1]->JSObject()->GetBoolean(XFA_Attribute::Save); - if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave) - pItem = pItems[1]; - } - return pItem->CountChildren(XFA_Element::Unknown, false); -} - -Optional<WideString> CXFA_WidgetAcc::GetChoiceListItem(int32_t nIndex, - bool bSaveValue) { - std::vector<CXFA_Node*> pItemsArray; - int32_t iCount = 0; - for (CXFA_Node* pNode = m_pNode->GetFirstChild(); pNode; - pNode = pNode->GetNextSibling()) { - if (pNode->GetElementType() != XFA_Element::Items) - continue; - - ++iCount; - pItemsArray.push_back(pNode); - if (iCount == 2) - break; - } - if (iCount == 0) - return {}; - - CXFA_Node* pItems = pItemsArray[0]; - if (iCount > 1) { - bool bItemOneHasSave = - pItemsArray[0]->JSObject()->GetBoolean(XFA_Attribute::Save); - bool bItemTwoHasSave = - pItemsArray[1]->JSObject()->GetBoolean(XFA_Attribute::Save); - if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave) - pItems = pItemsArray[1]; - } - if (!pItems) - return {}; - - CXFA_Node* pItem = - pItems->GetChild<CXFA_Node>(nIndex, XFA_Element::Unknown, false); - if (pItem) - return {pItem->JSObject()->GetContent(false)}; - return {}; -} - -std::vector<WideString> CXFA_WidgetAcc::GetChoiceListItems(bool bSaveValue) { - std::vector<CXFA_Node*> items; - for (CXFA_Node* pNode = m_pNode->GetFirstChild(); pNode && items.size() < 2; - pNode = pNode->GetNextSibling()) { - if (pNode->GetElementType() == XFA_Element::Items) - items.push_back(pNode); - } - if (items.empty()) - return std::vector<WideString>(); - - CXFA_Node* pItem = items.front(); - if (items.size() > 1) { - bool bItemOneHasSave = - items[0]->JSObject()->GetBoolean(XFA_Attribute::Save); - bool bItemTwoHasSave = - items[1]->JSObject()->GetBoolean(XFA_Attribute::Save); - if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave) - pItem = items[1]; - } - - std::vector<WideString> wsTextArray; - for (CXFA_Node* pNode = pItem->GetFirstChild(); pNode; - pNode = pNode->GetNextSibling()) { - wsTextArray.emplace_back(pNode->JSObject()->GetContent(false)); - } - return wsTextArray; -} - -int32_t CXFA_WidgetAcc::CountSelectedItems() { - std::vector<WideString> wsValueArray = GetSelectedItemsValue(); - if (IsListBox() || !IsChoiceListAllowTextEntry()) - return pdfium::CollectionSize<int32_t>(wsValueArray); - - int32_t iSelected = 0; - std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); - for (const auto& value : wsValueArray) { - if (pdfium::ContainsValue(wsSaveTextArray, value)) - iSelected++; - } - return iSelected; -} - -int32_t CXFA_WidgetAcc::GetSelectedItem(int32_t nIndex) { - std::vector<WideString> wsValueArray = GetSelectedItemsValue(); - if (!pdfium::IndexInBounds(wsValueArray, nIndex)) - return -1; - - std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); - auto it = std::find(wsSaveTextArray.begin(), wsSaveTextArray.end(), - wsValueArray[nIndex]); - return it != wsSaveTextArray.end() ? it - wsSaveTextArray.begin() : -1; -} - -std::vector<int32_t> CXFA_WidgetAcc::GetSelectedItems() { - std::vector<int32_t> iSelArray; - std::vector<WideString> wsValueArray = GetSelectedItemsValue(); - std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); - for (const auto& value : wsValueArray) { - auto it = std::find(wsSaveTextArray.begin(), wsSaveTextArray.end(), value); - if (it != wsSaveTextArray.end()) - iSelArray.push_back(it - wsSaveTextArray.begin()); - } - return iSelArray; -} - -std::vector<WideString> CXFA_WidgetAcc::GetSelectedItemsValue() { - std::vector<WideString> wsSelTextArray; - WideString wsValue = m_pNode->GetRawValue(); - if (IsChoiceListMultiSelect()) { - if (!wsValue.IsEmpty()) { - size_t iStart = 0; - size_t iLength = wsValue.GetLength(); - auto iEnd = wsValue.Find(L'\n', iStart); - iEnd = (!iEnd.has_value()) ? iLength : iEnd; - while (iEnd >= iStart) { - wsSelTextArray.push_back(wsValue.Mid(iStart, iEnd.value() - iStart)); - iStart = iEnd.value() + 1; - if (iStart >= iLength) - break; - iEnd = wsValue.Find(L'\n', iStart); - if (!iEnd.has_value()) - wsSelTextArray.push_back(wsValue.Mid(iStart, iLength - iStart)); - } - } - } else { - wsSelTextArray.push_back(wsValue); - } - return wsSelTextArray; -} - -bool CXFA_WidgetAcc::GetItemState(int32_t nIndex) { - std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); - return pdfium::IndexInBounds(wsSaveTextArray, nIndex) && - pdfium::ContainsValue(GetSelectedItemsValue(), - wsSaveTextArray[nIndex]); -} - -void CXFA_WidgetAcc::SetItemState(int32_t nIndex, - bool bSelected, - bool bNotify, - bool bScriptModify, - bool bSyncData) { - std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); - if (!pdfium::IndexInBounds(wsSaveTextArray, nIndex)) - return; - - int32_t iSel = -1; - std::vector<WideString> wsValueArray = GetSelectedItemsValue(); - auto it = std::find(wsValueArray.begin(), wsValueArray.end(), - wsSaveTextArray[nIndex]); - if (it != wsValueArray.end()) - iSel = it - wsValueArray.begin(); - - if (IsChoiceListMultiSelect()) { - if (bSelected) { - if (iSel < 0) { - WideString wsValue = m_pNode->GetRawValue(); - if (!wsValue.IsEmpty()) { - wsValue += L"\n"; - } - wsValue += wsSaveTextArray[nIndex]; - m_pNode->JSObject()->SetContent(wsValue, wsValue, bNotify, - bScriptModify, bSyncData); - } - } else if (iSel >= 0) { - std::vector<int32_t> iSelArray = GetSelectedItems(); - auto it = std::find(iSelArray.begin(), iSelArray.end(), nIndex); - if (it != iSelArray.end()) - iSelArray.erase(it); - SetSelectedItems(iSelArray, bNotify, bScriptModify, bSyncData); - } - } else { - if (bSelected) { - if (iSel < 0) { - WideString wsSaveText = wsSaveTextArray[nIndex]; - m_pNode->JSObject()->SetContent(wsSaveText, - GetFormatDataValue(wsSaveText), bNotify, - bScriptModify, bSyncData); - } - } else if (iSel >= 0) { - m_pNode->JSObject()->SetContent(WideString(), WideString(), bNotify, - bScriptModify, bSyncData); - } - } -} - -void CXFA_WidgetAcc::SetSelectedItems(const std::vector<int32_t>& iSelArray, - bool bNotify, - bool bScriptModify, - bool bSyncData) { - WideString wsValue; - int32_t iSize = pdfium::CollectionSize<int32_t>(iSelArray); - if (iSize >= 1) { - std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); - WideString wsItemValue; - for (int32_t i = 0; i < iSize; i++) { - wsItemValue = (iSize == 1) ? wsSaveTextArray[iSelArray[i]] - : wsSaveTextArray[iSelArray[i]] + L"\n"; - wsValue += wsItemValue; - } - } - WideString wsFormat(wsValue); - if (!IsChoiceListMultiSelect()) - wsFormat = GetFormatDataValue(wsValue); - - m_pNode->JSObject()->SetContent(wsValue, wsFormat, bNotify, bScriptModify, - bSyncData); -} - -void CXFA_WidgetAcc::ClearAllSelections() { - CXFA_Node* pBind = m_pNode->GetBindData(); - if (!pBind || !IsChoiceListMultiSelect()) { - m_pNode->SyncValue(WideString(), false); - return; - } - - while (CXFA_Node* pChildNode = pBind->GetFirstChild()) - pBind->RemoveChild(pChildNode, true); -} - -void CXFA_WidgetAcc::InsertItem(const WideString& wsLabel, - const WideString& wsValue, - bool bNotify) { - int32_t nIndex = -1; - WideString wsNewValue(wsValue); - if (wsNewValue.IsEmpty()) - wsNewValue = wsLabel; - - std::vector<CXFA_Node*> listitems; - for (CXFA_Node* pItem = m_pNode->GetFirstChild(); pItem; - pItem = pItem->GetNextSibling()) { - if (pItem->GetElementType() == XFA_Element::Items) - listitems.push_back(pItem); - } - if (listitems.empty()) { - CXFA_Node* pItems = m_pNode->CreateSamePacketNode(XFA_Element::Items); - m_pNode->InsertChild(-1, pItems); - InsertListTextItem(pItems, wsLabel, nIndex); - CXFA_Node* pSaveItems = m_pNode->CreateSamePacketNode(XFA_Element::Items); - m_pNode->InsertChild(-1, pSaveItems); - pSaveItems->JSObject()->SetBoolean(XFA_Attribute::Save, true, false); - InsertListTextItem(pSaveItems, wsNewValue, nIndex); - } else if (listitems.size() > 1) { - for (int32_t i = 0; i < 2; i++) { - CXFA_Node* pNode = listitems[i]; - bool bHasSave = pNode->JSObject()->GetBoolean(XFA_Attribute::Save); - if (bHasSave) - InsertListTextItem(pNode, wsNewValue, nIndex); - else - InsertListTextItem(pNode, wsLabel, nIndex); - } - } else { - CXFA_Node* pNode = listitems[0]; - pNode->JSObject()->SetBoolean(XFA_Attribute::Save, false, false); - pNode->JSObject()->SetEnum(XFA_Attribute::Presence, - XFA_AttributeEnum::Visible, false); - CXFA_Node* pSaveItems = m_pNode->CreateSamePacketNode(XFA_Element::Items); - m_pNode->InsertChild(-1, pSaveItems); - pSaveItems->JSObject()->SetBoolean(XFA_Attribute::Save, true, false); - pSaveItems->JSObject()->SetEnum(XFA_Attribute::Presence, - XFA_AttributeEnum::Hidden, false); - CXFA_Node* pListNode = pNode->GetFirstChild(); - int32_t i = 0; - while (pListNode) { - InsertListTextItem(pSaveItems, pListNode->JSObject()->GetContent(false), - i); - ++i; - - pListNode = pListNode->GetNextSibling(); - } - InsertListTextItem(pNode, wsLabel, nIndex); - InsertListTextItem(pSaveItems, wsNewValue, nIndex); - } - if (!bNotify) - return; - - m_pNode->GetDocument()->GetNotify()->OnWidgetListItemAdded( - m_pNode, wsLabel.c_str(), wsValue.c_str(), nIndex); -} - -void CXFA_WidgetAcc::GetItemLabel(const WideStringView& wsValue, - WideString& wsLabel) { - int32_t iCount = 0; - std::vector<CXFA_Node*> listitems; - CXFA_Node* pItems = m_pNode->GetFirstChild(); - for (; pItems; pItems = pItems->GetNextSibling()) { - if (pItems->GetElementType() != XFA_Element::Items) - continue; - iCount++; - listitems.push_back(pItems); - } - - if (iCount <= 1) { - wsLabel = wsValue; - return; - } - - CXFA_Node* pLabelItems = listitems[0]; - bool bSave = pLabelItems->JSObject()->GetBoolean(XFA_Attribute::Save); - CXFA_Node* pSaveItems = nullptr; - if (bSave) { - pSaveItems = pLabelItems; - pLabelItems = listitems[1]; - } else { - pSaveItems = listitems[1]; - } - iCount = 0; - - int32_t iSearch = -1; - for (CXFA_Node* pChildItem = pSaveItems->GetFirstChild(); pChildItem; - pChildItem = pChildItem->GetNextSibling()) { - if (pChildItem->JSObject()->GetContent(false) == wsValue) { - iSearch = iCount; - break; - } - iCount++; - } - if (iSearch < 0) - return; - - CXFA_Node* pText = - pLabelItems->GetChild<CXFA_Node>(iSearch, XFA_Element::Unknown, false); - if (pText) - wsLabel = pText->JSObject()->GetContent(false); -} - -WideString CXFA_WidgetAcc::GetItemValue(const WideStringView& wsLabel) { - int32_t iCount = 0; - std::vector<CXFA_Node*> listitems; - for (CXFA_Node* pItems = m_pNode->GetFirstChild(); pItems; - pItems = pItems->GetNextSibling()) { - if (pItems->GetElementType() != XFA_Element::Items) - continue; - iCount++; - listitems.push_back(pItems); - } - if (iCount <= 1) - return WideString(wsLabel); - - CXFA_Node* pLabelItems = listitems[0]; - bool bSave = pLabelItems->JSObject()->GetBoolean(XFA_Attribute::Save); - CXFA_Node* pSaveItems = nullptr; - if (bSave) { - pSaveItems = pLabelItems; - pLabelItems = listitems[1]; - } else { - pSaveItems = listitems[1]; - } - iCount = 0; - - int32_t iSearch = -1; - WideString wsContent; - CXFA_Node* pChildItem = pLabelItems->GetFirstChild(); - for (; pChildItem; pChildItem = pChildItem->GetNextSibling()) { - if (pChildItem->JSObject()->GetContent(false) == wsLabel) { - iSearch = iCount; - break; - } - iCount++; - } - if (iSearch < 0) - return L""; - - CXFA_Node* pText = - pSaveItems->GetChild<CXFA_Node>(iSearch, XFA_Element::Unknown, false); - return pText ? pText->JSObject()->GetContent(false) : L""; -} - -bool CXFA_WidgetAcc::DeleteItem(int32_t nIndex, - bool bNotify, - bool bScriptModify) { - bool bSetValue = false; - CXFA_Node* pItems = m_pNode->GetFirstChild(); - for (; pItems; pItems = pItems->GetNextSibling()) { - if (pItems->GetElementType() != XFA_Element::Items) - continue; - - if (nIndex < 0) { - while (CXFA_Node* pNode = pItems->GetFirstChild()) { - pItems->RemoveChild(pNode, true); - } - } else { - if (!bSetValue && pItems->JSObject()->GetBoolean(XFA_Attribute::Save)) { - SetItemState(nIndex, false, true, bScriptModify, true); - bSetValue = true; - } - int32_t i = 0; - CXFA_Node* pNode = pItems->GetFirstChild(); - while (pNode) { - if (i == nIndex) { - pItems->RemoveChild(pNode, true); - break; - } - i++; - pNode = pNode->GetNextSibling(); - } - } - } - if (bNotify) - m_pNode->GetDocument()->GetNotify()->OnWidgetListItemRemoved(m_pNode, - nIndex); - return true; -} - -bool CXFA_WidgetAcc::IsHorizontalScrollPolicyOff() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - if (pUIChild) { - return pUIChild->JSObject()->GetEnum(XFA_Attribute::HScrollPolicy) == - XFA_AttributeEnum::Off; - } - return false; -} - -bool CXFA_WidgetAcc::IsVerticalScrollPolicyOff() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - if (pUIChild) { - return pUIChild->JSObject()->GetEnum(XFA_Attribute::VScrollPolicy) == - XFA_AttributeEnum::Off; - } - return false; -} - -Optional<int32_t> CXFA_WidgetAcc::GetNumberOfCells() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - if (!pUIChild) - return {}; - if (CXFA_Comb* pNode = - pUIChild->GetChild<CXFA_Comb>(0, XFA_Element::Comb, false)) - return {pNode->JSObject()->GetInteger(XFA_Attribute::NumberOfCells)}; - return {}; -} - -WideString CXFA_WidgetAcc::GetPasswordChar() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - return pUIChild ? pUIChild->JSObject()->GetCData(XFA_Attribute::PasswordChar) - : L"*"; -} - -bool CXFA_WidgetAcc::IsMultiLine() { - CXFA_Node* pUIChild = m_pNode->GetUIChild(); - return pUIChild && pUIChild->JSObject()->GetBoolean(XFA_Attribute::MultiLine); -} - -std::pair<XFA_Element, int32_t> CXFA_WidgetAcc::GetMaxChars() { - if (CXFA_Value* pNode = - m_pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false)) { - if (CXFA_Node* pChild = pNode->GetFirstChild()) { - switch (pChild->GetElementType()) { - case XFA_Element::Text: - return {XFA_Element::Text, - pChild->JSObject()->GetInteger(XFA_Attribute::MaxChars)}; - case XFA_Element::ExData: { - int32_t iMax = - pChild->JSObject()->GetInteger(XFA_Attribute::MaxLength); - return {XFA_Element::ExData, iMax < 0 ? 0 : iMax}; - } - default: - break; - } - } - } - return {XFA_Element::Unknown, 0}; -} - -int32_t CXFA_WidgetAcc::GetFracDigits() { - CXFA_Value* pNode = - m_pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false); - if (!pNode) - return -1; - - CXFA_Decimal* pChild = - pNode->GetChild<CXFA_Decimal>(0, XFA_Element::Decimal, false); - if (!pChild) - return -1; - - return pChild->JSObject() - ->TryInteger(XFA_Attribute::FracDigits, true) - .value_or(-1); -} - -int32_t CXFA_WidgetAcc::GetLeadDigits() { - CXFA_Value* pNode = - m_pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false); - if (!pNode) - return -1; - - CXFA_Decimal* pChild = - pNode->GetChild<CXFA_Decimal>(0, XFA_Element::Decimal, false); - if (!pChild) - return -1; - - return pChild->JSObject() - ->TryInteger(XFA_Attribute::LeadDigits, true) - .value_or(-1); -} - -bool CXFA_WidgetAcc::SetValue(XFA_VALUEPICTURE eValueType, - const WideString& wsValue) { - if (wsValue.IsEmpty()) { - m_pNode->SyncValue(wsValue, true); - return true; - } - - m_pNode->SetPreNull(m_pNode->IsNull()); - m_pNode->SetIsNull(false); - - WideString wsNewText(wsValue); - WideString wsPicture = GetPictureContent(eValueType); - bool bValidate = true; - bool bSyncData = false; - CXFA_Node* pNode = m_pNode->GetUIChild(); - if (!pNode) - return true; - - XFA_Element eType = pNode->GetElementType(); - if (!wsPicture.IsEmpty()) { - CXFA_LocaleMgr* pLocalMgr = m_pNode->GetDocument()->GetLocalMgr(); - IFX_Locale* pLocale = m_pNode->GetLocale(); - CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(GetNode()); - bValidate = - widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture); - if (bValidate) { - widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsNewText, - wsPicture, pLocale, pLocalMgr); - wsNewText = widgetValue.GetValue(); - if (eType == XFA_Element::NumericEdit) - wsNewText = NumericLimit(wsNewText, GetLeadDigits(), GetFracDigits()); - - bSyncData = true; - } - } else { - if (eType == XFA_Element::NumericEdit) { - if (wsNewText != L"0") - wsNewText = NumericLimit(wsNewText, GetLeadDigits(), GetFracDigits()); - - bSyncData = true; - } - } - if (eType != XFA_Element::NumericEdit || bSyncData) - m_pNode->SyncValue(wsNewText, true); - - return bValidate; -} - -WideString CXFA_WidgetAcc::GetPictureContent(XFA_VALUEPICTURE ePicture) { - if (ePicture == XFA_VALUEPICTURE_Raw) - return L""; - - CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(GetNode()); - switch (ePicture) { - case XFA_VALUEPICTURE_Display: { - if (CXFA_Format* pFormat = - m_pNode->GetChild<CXFA_Format>(0, XFA_Element::Format, false)) { - if (CXFA_Picture* pPicture = pFormat->GetChild<CXFA_Picture>( - 0, XFA_Element::Picture, false)) { - Optional<WideString> picture = - pPicture->JSObject()->TryContent(false, true); - if (picture) - return *picture; - } - } - - IFX_Locale* pLocale = m_pNode->GetLocale(); - if (!pLocale) - return L""; - - uint32_t dwType = widgetValue.GetType(); - switch (dwType) { - case XFA_VT_DATE: - return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium); - case XFA_VT_TIME: - return pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium); - case XFA_VT_DATETIME: - return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium) + - L"T" + - pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium); - case XFA_VT_DECIMAL: - case XFA_VT_FLOAT: - default: - return L""; - } - } - case XFA_VALUEPICTURE_Edit: { - CXFA_Ui* pUI = m_pNode->GetChild<CXFA_Ui>(0, XFA_Element::Ui, false); - if (pUI) { - if (CXFA_Picture* pPicture = - pUI->GetChild<CXFA_Picture>(0, XFA_Element::Picture, false)) { - Optional<WideString> picture = - pPicture->JSObject()->TryContent(false, true); - if (picture) - return *picture; - } - } - - IFX_Locale* pLocale = m_pNode->GetLocale(); - if (!pLocale) - return L""; - - uint32_t dwType = widgetValue.GetType(); - switch (dwType) { - case XFA_VT_DATE: - return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short); - case XFA_VT_TIME: - return pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short); - case XFA_VT_DATETIME: - return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short) + - L"T" + - pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short); - default: - return L""; - } - } - case XFA_VALUEPICTURE_DataBind: { - CXFA_Bind* bind = m_pNode->GetBindIfExists(); - if (bind) - return bind->GetPicture(); - break; - } - default: - break; - } - return L""; -} - -WideString CXFA_WidgetAcc::GetValue(XFA_VALUEPICTURE eValueType) { - WideString wsValue = m_pNode->JSObject()->GetContent(false); - - if (eValueType == XFA_VALUEPICTURE_Display) - GetItemLabel(wsValue.AsStringView(), wsValue); - - WideString wsPicture = GetPictureContent(eValueType); - CXFA_Node* pNode = m_pNode->GetUIChild(); - if (!pNode) - return wsValue; - - switch (m_pNode->GetUIChild()->GetElementType()) { - case XFA_Element::ChoiceList: { - if (eValueType == XFA_VALUEPICTURE_Display) { - int32_t iSelItemIndex = GetSelectedItem(0); - if (iSelItemIndex >= 0) { - wsValue = GetChoiceListItem(iSelItemIndex, false).value_or(L""); - wsPicture.clear(); - } - } - } break; - case XFA_Element::NumericEdit: - if (eValueType != XFA_VALUEPICTURE_Raw && wsPicture.IsEmpty()) { - IFX_Locale* pLocale = m_pNode->GetLocale(); - if (eValueType == XFA_VALUEPICTURE_Display && pLocale) - wsValue = FormatNumStr(NormalizeNumStr(wsValue), pLocale); - } - break; - default: - break; - } - if (wsPicture.IsEmpty()) - return wsValue; - - if (IFX_Locale* pLocale = m_pNode->GetLocale()) { - CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(GetNode()); - CXFA_LocaleMgr* pLocalMgr = m_pNode->GetDocument()->GetLocalMgr(); - switch (widgetValue.GetType()) { - case XFA_VT_DATE: { - WideString wsDate, wsTime; - if (SplitDateTime(wsValue, wsDate, wsTime)) { - CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocalMgr); - if (date.FormatPatterns(wsValue, wsPicture, pLocale, eValueType)) - return wsValue; - } - break; - } - case XFA_VT_TIME: { - WideString wsDate, wsTime; - if (SplitDateTime(wsValue, wsDate, wsTime)) { - CXFA_LocaleValue time(XFA_VT_TIME, wsTime, pLocalMgr); - if (time.FormatPatterns(wsValue, wsPicture, pLocale, eValueType)) - return wsValue; - } - break; - } - default: - break; - } - widgetValue.FormatPatterns(wsValue, wsPicture, pLocale, eValueType); - } - return wsValue; -} - -WideString CXFA_WidgetAcc::GetNormalizeDataValue(const WideString& wsValue) { - if (wsValue.IsEmpty()) - return L""; - - WideString wsPicture = GetPictureContent(XFA_VALUEPICTURE_DataBind); - if (wsPicture.IsEmpty()) - return wsValue; - - ASSERT(GetNode()); - CXFA_LocaleMgr* pLocalMgr = GetNode()->GetDocument()->GetLocalMgr(); - IFX_Locale* pLocale = m_pNode->GetLocale(); - CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(GetNode()); - if (widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture)) { - widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsValue, wsPicture, - pLocale, pLocalMgr); - return widgetValue.GetValue(); - } - return wsValue; -} - -WideString CXFA_WidgetAcc::GetFormatDataValue(const WideString& wsValue) { - if (wsValue.IsEmpty()) - return L""; - - WideString wsPicture = GetPictureContent(XFA_VALUEPICTURE_DataBind); - if (wsPicture.IsEmpty()) - return wsValue; - - WideString wsFormattedValue = wsValue; - if (IFX_Locale* pLocale = m_pNode->GetLocale()) { - ASSERT(GetNode()); - CXFA_Value* pNodeValue = - GetNode()->GetChild<CXFA_Value>(0, XFA_Element::Value, false); - if (!pNodeValue) - return wsValue; - - CXFA_Node* pValueChild = pNodeValue->GetFirstChild(); - if (!pValueChild) - return wsValue; - - int32_t iVTType = XFA_VT_NULL; - switch (pValueChild->GetElementType()) { - case XFA_Element::Decimal: - iVTType = XFA_VT_DECIMAL; - break; - case XFA_Element::Float: - iVTType = XFA_VT_FLOAT; - break; - case XFA_Element::Date: - iVTType = XFA_VT_DATE; - break; - case XFA_Element::Time: - iVTType = XFA_VT_TIME; - break; - case XFA_Element::DateTime: - iVTType = XFA_VT_DATETIME; - break; - case XFA_Element::Boolean: - iVTType = XFA_VT_BOOLEAN; - break; - case XFA_Element::Integer: - iVTType = XFA_VT_INTEGER; - break; - case XFA_Element::Text: - iVTType = XFA_VT_TEXT; - break; - default: - iVTType = XFA_VT_NULL; - break; - } - CXFA_LocaleMgr* pLocalMgr = GetNode()->GetDocument()->GetLocalMgr(); - CXFA_LocaleValue widgetValue(iVTType, wsValue, pLocalMgr); - switch (widgetValue.GetType()) { - case XFA_VT_DATE: { - WideString wsDate, wsTime; - if (SplitDateTime(wsValue, wsDate, wsTime)) { - CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocalMgr); - if (date.FormatPatterns(wsFormattedValue, wsPicture, pLocale, - XFA_VALUEPICTURE_DataBind)) { - return wsFormattedValue; - } - } - break; - } - case XFA_VT_TIME: { - WideString wsDate, wsTime; - if (SplitDateTime(wsValue, wsDate, wsTime)) { - CXFA_LocaleValue time(XFA_VT_TIME, wsTime, pLocalMgr); - if (time.FormatPatterns(wsFormattedValue, wsPicture, pLocale, - XFA_VALUEPICTURE_DataBind)) { - return wsFormattedValue; - } - } - break; - } - default: - break; - } - widgetValue.FormatPatterns(wsFormattedValue, wsPicture, pLocale, - XFA_VALUEPICTURE_DataBind); - } - return wsFormattedValue; -} - -WideString CXFA_WidgetAcc::NormalizeNumStr(const WideString& wsValue) { - if (wsValue.IsEmpty()) - return L""; - - WideString wsOutput = wsValue; - wsOutput.TrimLeft('0'); - - if (!wsOutput.IsEmpty() && wsOutput.Contains('.') && GetFracDigits() != -1) { - wsOutput.TrimRight(L"0"); - wsOutput.TrimRight(L"."); - } - if (wsOutput.IsEmpty() || wsOutput[0] == '.') - wsOutput.InsertAtFront('0'); - - return wsOutput; -} - -WideString CXFA_WidgetAcc::FormatNumStr(const WideString& wsValue, - IFX_Locale* pLocale) { - if (wsValue.IsEmpty()) - return L""; - - WideString wsSrcNum = wsValue; - WideString wsGroupSymbol = - pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping); - bool bNeg = false; - if (wsSrcNum[0] == '-') { - bNeg = true; - wsSrcNum.Delete(0, 1); - } - - auto dot_index = wsSrcNum.Find('.'); - dot_index = !dot_index.has_value() ? wsSrcNum.GetLength() : dot_index; - - if (dot_index.value() < 1) - return L""; - - size_t nPos = dot_index.value() % 3; - WideString wsOutput; - for (size_t i = 0; i < dot_index.value(); i++) { - if (i % 3 == nPos && i != 0) - wsOutput += wsGroupSymbol; - - wsOutput += wsSrcNum[i]; - } - if (dot_index.value() < wsSrcNum.GetLength()) { - wsOutput += pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal); - wsOutput += wsSrcNum.Right(wsSrcNum.GetLength() - dot_index.value() - 1); - } - if (bNeg) - return pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus) + wsOutput; - - return wsOutput; -} - -void CXFA_WidgetAcc::InsertListTextItem(CXFA_Node* pItems, - const WideString& wsText, - int32_t nIndex) { - CXFA_Node* pText = pItems->CreateSamePacketNode(XFA_Element::Text); - pItems->InsertChild(nIndex, pText); - pText->JSObject()->SetContent(wsText, wsText, false, false, false); -} - -WideString CXFA_WidgetAcc::NumericLimit(const WideString& wsValue, - int32_t iLead, - int32_t iTread) const { - if ((iLead == -1) && (iTread == -1)) - return wsValue; - - WideString wsRet; - int32_t iLead_ = 0, iTread_ = -1; - int32_t iCount = wsValue.GetLength(); - if (iCount == 0) - return wsValue; - - int32_t i = 0; - if (wsValue[i] == L'-') { - wsRet += L'-'; - i++; - } - for (; i < iCount; i++) { - wchar_t wc = wsValue[i]; - if (FXSYS_isDecimalDigit(wc)) { - if (iLead >= 0) { - iLead_++; - if (iLead_ > iLead) - return L"0"; - } else if (iTread_ >= 0) { - iTread_++; - if (iTread_ > iTread) { - if (iTread != -1) { - CFX_Decimal wsDeci = CFX_Decimal(wsValue.AsStringView()); - wsDeci.SetScale(iTread); - wsRet = wsDeci; - } - return wsRet; - } - } - } else if (wc == L'.') { - iTread_ = 0; - iLead = -1; - } - wsRet += wc; - } - return wsRet; -} diff --git a/xfa/fxfa/cxfa_widgetacc.h b/xfa/fxfa/cxfa_widgetacc.h deleted file mode 100644 index 8e0301865d..0000000000 --- a/xfa/fxfa/cxfa_widgetacc.h +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_CXFA_WIDGETACC_H_ -#define XFA_FXFA_CXFA_WIDGETACC_H_ - -#include <memory> -#include <utility> -#include <vector> - -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxcrt/retain_ptr.h" -#include "core/fxge/dib/cfx_dibitmap.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fxfa/fxfa_basic.h" - -enum XFA_CHECKSTATE { - XFA_CHECKSTATE_On = 0, - XFA_CHECKSTATE_Off = 1, - XFA_CHECKSTATE_Neutral = 2, -}; - -enum XFA_VALUEPICTURE { - XFA_VALUEPICTURE_Raw = 0, - XFA_VALUEPICTURE_Display, - XFA_VALUEPICTURE_Edit, - XFA_VALUEPICTURE_DataBind, -}; - -class CFGAS_GEFont; -class CXFA_Bind; -class CXFA_Border; -class CXFA_Calculate; -class CXFA_Caption; -class CXFA_Event; -class CXFA_EventParam; -class CXFA_FFApp; -class CXFA_FFDoc; -class CXFA_FFDocView; -class CXFA_FFWidget; -class CXFA_Font; -class CXFA_Margin; -class CXFA_Node; -class CXFA_Script; -class CXFA_Para; -class CXFA_TextLayout; -class CXFA_Value; -class CXFA_Validate; -class CXFA_WidgetLayoutData; -class IFX_Locale; - -class CXFA_WidgetAcc { - public: - explicit CXFA_WidgetAcc(CXFA_Node* pNode); - ~CXFA_WidgetAcc(); - - void ResetData(); - - CXFA_FFWidget* GetNextWidget(CXFA_FFWidget* pWidget); - void StartWidgetLayout(CXFA_FFDoc* doc, - float& fCalcWidth, - float& fCalcHeight); - bool FindSplitPos(CXFA_FFDocView* docView, - int32_t iBlockIndex, - float& fCalcHeight); - - bool LoadCaption(CXFA_FFDoc* doc); - CXFA_TextLayout* GetCaptionTextLayout(); - - void LoadText(CXFA_FFDoc* doc); - CXFA_TextLayout* GetTextLayout(); - - bool LoadImageImage(CXFA_FFDoc* doc); - bool LoadImageEditImage(CXFA_FFDoc* doc); - void GetImageDpi(int32_t& iImageXDpi, int32_t& iImageYDpi); - void GetImageEditDpi(int32_t& iImageXDpi, int32_t& iImageYDpi); - - RetainPtr<CFX_DIBitmap> GetImageImage(); - RetainPtr<CFX_DIBitmap> GetImageEditImage(); - void SetImageEdit(const WideString& wsContentType, - const WideString& wsHref, - const WideString& wsData); - void SetImageImage(const RetainPtr<CFX_DIBitmap>& newImage); - void SetImageEditImage(const RetainPtr<CFX_DIBitmap>& newImage); - void UpdateUIDisplay(CXFA_FFDocView* docView, CXFA_FFWidget* pExcept); - - RetainPtr<CFGAS_GEFont> GetFDEFont(CXFA_FFDoc* doc); - - CXFA_Node* GetNode() const { return m_pNode; } - - bool IsOpenAccess() const; - bool IsListBox(); - bool IsAllowNeutral(); - bool IsRadioButton(); - bool IsChoiceListAllowTextEntry(); - bool IsMultiLine(); - - XFA_AttributeEnum GetButtonHighlight(); - bool HasButtonRollover() const; - bool HasButtonDown() const; - - bool IsCheckButtonRound(); - XFA_AttributeEnum GetCheckButtonMark(); - float GetCheckButtonSize(); - - XFA_CHECKSTATE GetCheckState(); - void SetCheckState(XFA_CHECKSTATE eCheckState, bool bNotify); - - CXFA_Node* GetSelectedMember(); - CXFA_Node* SetSelectedMember(const WideStringView& wsName, bool bNotify); - void SetSelectedMemberByValue(const WideStringView& wsValue, - bool bNotify, - bool bScriptModify, - bool bSyncData); - - CXFA_Node* GetExclGroupFirstMember(); - CXFA_Node* GetExclGroupNextMember(CXFA_Node* pNode); - - int32_t CountChoiceListItems(bool bSaveValue); - Optional<WideString> GetChoiceListItem(int32_t nIndex, bool bSaveValue); - bool IsChoiceListMultiSelect(); - bool IsChoiceListCommitOnSelect(); - std::vector<WideString> GetChoiceListItems(bool bSaveValue); - - int32_t CountSelectedItems(); - int32_t GetSelectedItem(int32_t nIndex); - std::vector<int32_t> GetSelectedItems(); - std::vector<WideString> GetSelectedItemsValue(); - void SetSelectedItems(const std::vector<int32_t>& iSelArray, - bool bNotify, - bool bScriptModify, - bool bSyncData); - void InsertItem(const WideString& wsLabel, - const WideString& wsValue, - bool bNotify); - bool DeleteItem(int32_t nIndex, bool bNotify, bool bScriptModify); - void ClearAllSelections(); - - bool GetItemState(int32_t nIndex); - void SetItemState(int32_t nIndex, - bool bSelected, - bool bNotify, - bool bScriptModify, - bool bSyncData); - - WideString GetItemValue(const WideStringView& wsLabel); - - bool IsHorizontalScrollPolicyOff(); - bool IsVerticalScrollPolicyOff(); - Optional<int32_t> GetNumberOfCells(); - - bool SetValue(XFA_VALUEPICTURE eValueType, const WideString& wsValue); - WideString GetValue(XFA_VALUEPICTURE eValueType); - - WideString GetPictureContent(XFA_VALUEPICTURE ePicture); - WideString GetNormalizeDataValue(const WideString& wsValue); - WideString GetFormatDataValue(const WideString& wsValue); - WideString NormalizeNumStr(const WideString& wsValue); - - WideString GetPasswordChar(); - std::pair<XFA_Element, int32_t> GetMaxChars(); - int32_t GetFracDigits(); - int32_t GetLeadDigits(); - - WideString NumericLimit(const WideString& wsValue, - int32_t iLead, - int32_t iTread) const; - - private: - void CalcCaptionSize(CXFA_FFDoc* doc, CFX_SizeF& szCap); - bool CalculateFieldAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); - bool CalculateWidgetAutoSize(CFX_SizeF& size); - bool CalculateTextEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); - bool CalculateCheckButtonAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); - bool CalculatePushButtonAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); - CFX_SizeF CalculateImageSize(float img_width, - float img_height, - float dpi_x, - float dpi_y); - bool CalculateImageEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); - bool CalculateImageAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); - float CalculateWidgetAutoHeight(float fHeightCalc); - float CalculateWidgetAutoWidth(float fWidthCalc); - float GetWidthWithoutMargin(float fWidthCalc); - float GetHeightWithoutMargin(float fHeightCalc); - void CalculateTextContentSize(CXFA_FFDoc* doc, CFX_SizeF& size); - void CalculateAccWidthAndHeight(CXFA_FFDoc* doc, - XFA_Element eUIType, - float& fWidth, - float& fCalcHeight); - void InitLayoutData(); - void StartTextLayout(CXFA_FFDoc* doc, float& fCalcWidth, float& fCalcHeight); - - void InsertListTextItem(CXFA_Node* pItems, - const WideString& wsText, - int32_t nIndex); - WideString FormatNumStr(const WideString& wsValue, IFX_Locale* pLocale); - void GetItemLabel(const WideStringView& wsValue, WideString& wsLabel); - - std::unique_ptr<CXFA_WidgetLayoutData> m_pLayoutData; - CXFA_Node* m_pNode; -}; - -#endif // XFA_FXFA_CXFA_WIDGETACC_H_ diff --git a/xfa/fxfa/parser/cxfa_localevalue.h b/xfa/fxfa/parser/cxfa_localevalue.h index 60de601c02..44db7b15d9 100644 --- a/xfa/fxfa/parser/cxfa_localevalue.h +++ b/xfa/fxfa/parser/cxfa_localevalue.h @@ -9,7 +9,7 @@ #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" -#include "xfa/fxfa/cxfa_widgetacc.h" +#include "xfa/fxfa/parser/cxfa_node.h" class IFX_Locale; class CFX_DateTime; diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp index ba882a2b9d..988d1e2ee5 100644 --- a/xfa/fxfa/parser/cxfa_node.cpp +++ b/xfa/fxfa/parser/cxfa_node.cpp @@ -6,6 +6,7 @@ #include "xfa/fxfa/parser/cxfa_node.h" +#include <algorithm> #include <map> #include <memory> #include <set> @@ -20,26 +21,35 @@ #include "core/fxcrt/xml/cfx_xmlelement.h" #include "core/fxcrt/xml/cfx_xmlnode.h" #include "core/fxcrt/xml/cfx_xmltext.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "fxjs/cfxjse_engine.h" #include "fxjs/cfxjse_value.h" #include "fxjs/xfa/cjx_node.h" #include "third_party/base/logging.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" +#include "xfa/fde/cfde_textout.h" +#include "xfa/fgas/font/cfgas_fontmgr.h" #include "xfa/fxfa/cxfa_eventparam.h" #include "xfa/fxfa/cxfa_ffapp.h" #include "xfa/fxfa/cxfa_ffdocview.h" #include "xfa/fxfa/cxfa_ffnotify.h" #include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_fontmgr.h" +#include "xfa/fxfa/cxfa_textprovider.h" #include "xfa/fxfa/parser/cxfa_arraynodelist.h" #include "xfa/fxfa/parser/cxfa_attachnodelist.h" #include "xfa/fxfa/parser/cxfa_bind.h" #include "xfa/fxfa/parser/cxfa_border.h" #include "xfa/fxfa/parser/cxfa_calculate.h" #include "xfa/fxfa/parser/cxfa_caption.h" +#include "xfa/fxfa/parser/cxfa_comb.h" +#include "xfa/fxfa/parser/cxfa_decimal.h" #include "xfa/fxfa/parser/cxfa_document.h" #include "xfa/fxfa/parser/cxfa_event.h" #include "xfa/fxfa/parser/cxfa_font.h" +#include "xfa/fxfa/parser/cxfa_format.h" +#include "xfa/fxfa/parser/cxfa_image.h" #include "xfa/fxfa/parser/cxfa_items.h" #include "xfa/fxfa/parser/cxfa_keep.h" #include "xfa/fxfa/parser/cxfa_layoutprocessor.h" @@ -49,6 +59,7 @@ #include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" #include "xfa/fxfa/parser/cxfa_occur.h" #include "xfa/fxfa/parser/cxfa_para.h" +#include "xfa/fxfa/parser/cxfa_picture.h" #include "xfa/fxfa/parser/cxfa_simple_parser.h" #include "xfa/fxfa/parser/cxfa_stroke.h" #include "xfa/fxfa/parser/cxfa_subform.h" @@ -59,10 +70,301 @@ #include "xfa/fxfa/parser/xfa_basic_data.h" #include "xfa/fxfa/parser/xfa_utils.h" +class CXFA_WidgetLayoutData { + public: + CXFA_WidgetLayoutData() : m_fWidgetHeight(-1) {} + virtual ~CXFA_WidgetLayoutData() {} + + float m_fWidgetHeight; +}; + namespace { constexpr uint8_t kMaxExecuteRecursion = 2; +constexpr uint8_t g_inv_base64[128] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, + 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, + 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 255, 255, 255, 255, 255, +}; + +uint8_t* XFA_RemoveBase64Whitespace(const uint8_t* pStr, int32_t iLen) { + uint8_t* pCP; + int32_t i = 0, j = 0; + if (iLen == 0) { + iLen = strlen((char*)pStr); + } + pCP = FX_Alloc(uint8_t, iLen + 1); + for (; i < iLen; i++) { + if ((pStr[i] & 128) == 0) { + if (g_inv_base64[pStr[i]] != 0xFF || pStr[i] == '=') { + pCP[j++] = pStr[i]; + } + } + } + pCP[j] = '\0'; + return pCP; +} + +int32_t XFA_Base64Decode(const char* pStr, uint8_t* pOutBuffer) { + if (!pStr) { + return 0; + } + uint8_t* pBuffer = + XFA_RemoveBase64Whitespace((uint8_t*)pStr, strlen((char*)pStr)); + if (!pBuffer) { + return 0; + } + int32_t iLen = strlen((char*)pBuffer); + int32_t i = 0, j = 0; + uint32_t dwLimb = 0; + for (; i + 3 < iLen; i += 4) { + if (pBuffer[i] == '=' || pBuffer[i + 1] == '=' || pBuffer[i + 2] == '=' || + pBuffer[i + 3] == '=') { + if (pBuffer[i] == '=' || pBuffer[i + 1] == '=') { + break; + } + if (pBuffer[i + 2] == '=') { + dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 6) | + ((uint32_t)g_inv_base64[pBuffer[i + 1]]); + pOutBuffer[j] = (uint8_t)(dwLimb >> 4) & 0xFF; + j++; + } else { + dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 12) | + ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 6) | + ((uint32_t)g_inv_base64[pBuffer[i + 2]]); + pOutBuffer[j] = (uint8_t)(dwLimb >> 10) & 0xFF; + pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 2) & 0xFF; + j += 2; + } + } else { + dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 18) | + ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 12) | + ((uint32_t)g_inv_base64[pBuffer[i + 2]] << 6) | + ((uint32_t)g_inv_base64[pBuffer[i + 3]]); + pOutBuffer[j] = (uint8_t)(dwLimb >> 16) & 0xff; + pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 8) & 0xff; + pOutBuffer[j + 2] = (uint8_t)(dwLimb)&0xff; + j += 3; + } + } + FX_Free(pBuffer); + return j; +} + +FXCODEC_IMAGE_TYPE XFA_GetImageType(const WideString& wsType) { + WideString wsContentType(wsType); + wsContentType.MakeLower(); + if (wsContentType == L"image/jpg") + return FXCODEC_IMAGE_JPG; + if (wsContentType == L"image/png") + return FXCODEC_IMAGE_PNG; + if (wsContentType == L"image/gif") + return FXCODEC_IMAGE_GIF; + if (wsContentType == L"image/bmp") + return FXCODEC_IMAGE_BMP; + if (wsContentType == L"image/tif") + return FXCODEC_IMAGE_TIF; + return FXCODEC_IMAGE_UNKNOWN; +} + +RetainPtr<CFX_DIBitmap> XFA_LoadImageData(CXFA_FFDoc* pDoc, + CXFA_Image* pImage, + bool& bNameImage, + int32_t& iImageXDpi, + int32_t& iImageYDpi) { + WideString wsHref = pImage->GetHref(); + WideString wsImage = pImage->GetContent(); + if (wsHref.IsEmpty() && wsImage.IsEmpty()) + return nullptr; + + FXCODEC_IMAGE_TYPE type = XFA_GetImageType(pImage->GetContentType()); + ByteString bsContent; + uint8_t* pImageBuffer = nullptr; + RetainPtr<IFX_SeekableReadStream> pImageFileRead; + if (wsImage.GetLength() > 0) { + XFA_AttributeEnum iEncoding = pImage->GetTransferEncoding(); + if (iEncoding == XFA_AttributeEnum::Base64) { + ByteString bsData = wsImage.UTF8Encode(); + int32_t iLength = bsData.GetLength(); + pImageBuffer = FX_Alloc(uint8_t, iLength); + int32_t iRead = XFA_Base64Decode(bsData.c_str(), pImageBuffer); + if (iRead > 0) { + pImageFileRead = + pdfium::MakeRetain<CFX_MemoryStream>(pImageBuffer, iRead, false); + } + } else { + bsContent = ByteString::FromUnicode(wsImage); + pImageFileRead = pdfium::MakeRetain<CFX_MemoryStream>( + const_cast<uint8_t*>(bsContent.raw_str()), bsContent.GetLength(), + false); + } + } else { + WideString wsURL = wsHref; + if (wsURL.Left(7) != L"http://" && wsURL.Left(6) != L"ftp://") { + RetainPtr<CFX_DIBitmap> pBitmap = + pDoc->GetPDFNamedImage(wsURL.AsStringView(), iImageXDpi, iImageYDpi); + if (pBitmap) { + bNameImage = true; + return pBitmap; + } + } + pImageFileRead = pDoc->GetDocEnvironment()->OpenLinkedFile(pDoc, wsURL); + } + if (!pImageFileRead) { + FX_Free(pImageBuffer); + return nullptr; + } + bNameImage = false; + RetainPtr<CFX_DIBitmap> pBitmap = + XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi); + FX_Free(pImageBuffer); + return pBitmap; +} + +class CXFA_TextLayoutData : public CXFA_WidgetLayoutData { + public: + CXFA_TextLayoutData() {} + ~CXFA_TextLayoutData() override {} + + CXFA_TextLayout* GetTextLayout() const { return m_pTextLayout.get(); } + CXFA_TextProvider* GetTextProvider() const { return m_pTextProvider.get(); } + + void LoadText(CXFA_FFDoc* doc, CXFA_Node* pNode) { + if (m_pTextLayout) + return; + + m_pTextProvider = + pdfium::MakeUnique<CXFA_TextProvider>(pNode, XFA_TEXTPROVIDERTYPE_Text); + m_pTextLayout = + pdfium::MakeUnique<CXFA_TextLayout>(doc, m_pTextProvider.get()); + } + + private: + std::unique_ptr<CXFA_TextLayout> m_pTextLayout; + std::unique_ptr<CXFA_TextProvider> m_pTextProvider; +}; + +class CXFA_ImageLayoutData : public CXFA_WidgetLayoutData { + public: + CXFA_ImageLayoutData() + : m_bNamedImage(false), m_iImageXDpi(0), m_iImageYDpi(0) {} + + ~CXFA_ImageLayoutData() override {} + + bool LoadImageData(CXFA_FFDoc* doc, CXFA_Node* pNode) { + if (m_pDIBitmap) + return true; + + CXFA_Value* value = pNode->GetFormValueIfExists(); + if (!value) + return false; + + CXFA_Image* image = value->GetImageIfExists(); + if (!image) + return false; + + pNode->SetImageImage(XFA_LoadImageData(doc, image, m_bNamedImage, + m_iImageXDpi, m_iImageYDpi)); + return !!m_pDIBitmap; + } + + RetainPtr<CFX_DIBitmap> m_pDIBitmap; + bool m_bNamedImage; + int32_t m_iImageXDpi; + int32_t m_iImageYDpi; +}; + +class CXFA_FieldLayoutData : public CXFA_WidgetLayoutData { + public: + CXFA_FieldLayoutData() {} + ~CXFA_FieldLayoutData() override {} + + bool LoadCaption(CXFA_FFDoc* doc, CXFA_Node* pNode) { + if (m_pCapTextLayout) + return true; + CXFA_Caption* caption = pNode->GetCaptionIfExists(); + if (!caption || caption->IsHidden()) + return false; + + m_pCapTextProvider = pdfium::MakeUnique<CXFA_TextProvider>( + pNode, XFA_TEXTPROVIDERTYPE_Caption); + m_pCapTextLayout = + pdfium::MakeUnique<CXFA_TextLayout>(doc, m_pCapTextProvider.get()); + return true; + } + + std::unique_ptr<CXFA_TextLayout> m_pCapTextLayout; + std::unique_ptr<CXFA_TextProvider> m_pCapTextProvider; + std::unique_ptr<CFDE_TextOut> m_pTextOut; + std::vector<float> m_FieldSplitArray; +}; + +class CXFA_TextEditData : public CXFA_FieldLayoutData {}; + +class CXFA_ImageEditData : public CXFA_FieldLayoutData { + public: + CXFA_ImageEditData() + : m_bNamedImage(false), m_iImageXDpi(0), m_iImageYDpi(0) {} + + ~CXFA_ImageEditData() override {} + + bool LoadImageData(CXFA_FFDoc* doc, CXFA_Node* pNode) { + if (m_pDIBitmap) + return true; + + CXFA_Value* value = pNode->GetFormValueIfExists(); + if (!value) + return false; + + CXFA_Image* image = value->GetImageIfExists(); + if (!image) + return false; + + pNode->SetImageEditImage(XFA_LoadImageData(doc, image, m_bNamedImage, + m_iImageXDpi, m_iImageYDpi)); + return !!m_pDIBitmap; + } + + RetainPtr<CFX_DIBitmap> m_pDIBitmap; + bool m_bNamedImage; + int32_t m_iImageXDpi; + int32_t m_iImageYDpi; +}; + +bool SplitDateTime(const WideString& wsDateTime, + WideString& wsDate, + WideString& wsTime) { + wsDate = L""; + wsTime = L""; + if (wsDateTime.IsEmpty()) + return false; + + auto nSplitIndex = wsDateTime.Find('T'); + if (!nSplitIndex.has_value()) + nSplitIndex = wsDateTime.Find(' '); + if (!nSplitIndex.has_value()) + return false; + + wsDate = wsDateTime.Left(nSplitIndex.value()); + if (!wsDate.IsEmpty()) { + if (!std::any_of(wsDate.begin(), wsDate.end(), std::iswdigit)) + return false; + } + wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex.value() - 1); + if (!wsTime.IsEmpty()) { + if (!std::any_of(wsTime.begin(), wsTime.end(), std::iswdigit)) + return false; + } + return true; +} + std::vector<CXFA_Node*> NodesSortedByDocumentIdx( const std::set<CXFA_Node*>& rgNodeSet) { if (rgNodeSet.empty()) @@ -360,7 +662,8 @@ CXFA_Node::CXFA_Node(CXFA_Document* pDoc, m_ePacket(ePacket), m_uNodeFlags(XFA_NodeFlag_None), m_dwNameHash(0), - m_pAuxNode(nullptr) { + m_pAuxNode(nullptr), + m_pNode(this) { ASSERT(m_pDocument); } @@ -735,7 +1038,7 @@ CXFA_Node* CXFA_Node::GetContainerNode() { return nullptr; if (eType == XFA_Element::Field) { - CXFA_WidgetAcc* pFieldWidgetAcc = GetWidgetAcc(); + CXFA_Node* pFieldWidgetAcc = GetWidgetAcc(); if (pFieldWidgetAcc && pFieldWidgetAcc->IsChoiceListMultiSelect()) return nullptr; @@ -1829,11 +2132,6 @@ CXFA_Node* CXFA_Node::GetExclGroupIfExists() { return pExcl; } -void CXFA_Node::SetWidgetReady() { - acc_ = pdfium::MakeUnique<CXFA_WidgetAcc>(AsNode()); - is_widget_ready_ = true; -} - int32_t CXFA_Node::ProcessEvent(CXFA_FFDocView* docView, XFA_AttributeEnum iActivity, CXFA_EventParam* pEventParam) { @@ -2457,3 +2755,2134 @@ std::vector<CXFA_Event*> CXFA_Node::GetEventByActivity( } return events; } + +void CXFA_Node::ResetData() { + WideString wsValue; + switch (m_pNode->GetUIType()) { + case XFA_Element::ImageEdit: { + CXFA_Value* imageValue = m_pNode->GetDefaultValueIfExists(); + CXFA_Image* image = imageValue ? imageValue->GetImageIfExists() : nullptr; + WideString wsContentType, wsHref; + if (image) { + wsValue = image->GetContent(); + wsContentType = image->GetContentType(); + wsHref = image->GetHref(); + } + SetImageEdit(wsContentType, wsHref, wsValue); + break; + } + case XFA_Element::ExclGroup: { + CXFA_Node* pNextChild = m_pNode->GetFirstContainerChild(); + while (pNextChild) { + CXFA_Node* pChild = pNextChild; + if (!pChild->IsWidgetReady()) + continue; + + CXFA_Node* pAcc = pChild->GetWidgetAcc(); + bool done = false; + if (wsValue.IsEmpty()) { + CXFA_Value* defValue = pAcc->GetNode()->GetDefaultValueIfExists(); + if (defValue) { + wsValue = defValue->GetChildValueContent(); + SetValue(XFA_VALUEPICTURE_Raw, wsValue); + pAcc->SetValue(XFA_VALUEPICTURE_Raw, wsValue); + done = true; + } + } + if (!done) { + CXFA_Items* pItems = + pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItems) + continue; + + WideString itemText; + if (pItems->CountChildren(XFA_Element::Unknown, false) > 1) { + itemText = + pItems->GetChild<CXFA_Node>(1, XFA_Element::Unknown, false) + ->JSObject() + ->GetContent(false); + } + pAcc->SetValue(XFA_VALUEPICTURE_Raw, itemText); + } + pNextChild = pChild->GetNextContainerSibling(); + } + break; + } + case XFA_Element::ChoiceList: + ClearAllSelections(); + default: { + CXFA_Value* defValue = m_pNode->GetDefaultValueIfExists(); + if (defValue) + wsValue = defValue->GetChildValueContent(); + + SetValue(XFA_VALUEPICTURE_Raw, wsValue); + break; + } + } +} + +void CXFA_Node::SetImageEdit(const WideString& wsContentType, + const WideString& wsHref, + const WideString& wsData) { + CXFA_Value* formValue = m_pNode->GetFormValueIfExists(); + CXFA_Image* image = formValue ? formValue->GetImageIfExists() : nullptr; + if (image) { + image->SetContentType(WideString(wsContentType)); + image->SetHref(wsHref); + } + + m_pNode->JSObject()->SetContent(wsData, GetFormatDataValue(wsData), true, + false, true); + + CXFA_Node* pBind = m_pNode->GetBindData(); + if (!pBind) { + if (image) + image->SetTransferEncoding(XFA_AttributeEnum::Base64); + return; + } + pBind->JSObject()->SetCData(XFA_Attribute::ContentType, wsContentType, false, + false); + CXFA_Node* pHrefNode = pBind->GetFirstChild(); + if (pHrefNode) { + pHrefNode->JSObject()->SetCData(XFA_Attribute::Value, wsHref, false, false); + } else { + CFX_XMLNode* pXMLNode = pBind->GetXMLMappingNode(); + ASSERT(pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element); + static_cast<CFX_XMLElement*>(pXMLNode)->SetString(L"href", wsHref); + } +} + +CXFA_FFWidget* CXFA_Node::GetNextWidget(CXFA_FFWidget* pWidget) { + return static_cast<CXFA_FFWidget*>(pWidget->GetNext()); +} + +void CXFA_Node::UpdateUIDisplay(CXFA_FFDocView* docView, + CXFA_FFWidget* pExcept) { + CXFA_FFWidget* pWidget = docView->GetWidgetForNode(m_pNode); + for (; pWidget; pWidget = GetNextWidget(pWidget)) { + if (pWidget == pExcept || !pWidget->IsLoaded() || + (m_pNode->GetUIType() != XFA_Element::CheckButton && + pWidget->IsFocused())) { + continue; + } + pWidget->UpdateFWLData(); + pWidget->AddInvalidateRect(); + } +} + +void CXFA_Node::CalcCaptionSize(CXFA_FFDoc* doc, CFX_SizeF& szCap) { + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + if (!caption || !caption->IsVisible()) + return; + + LoadCaption(doc); + + XFA_Element eUIType = m_pNode->GetUIType(); + XFA_AttributeEnum iCapPlacement = caption->GetPlacementType(); + float fCapReserve = caption->GetReserve(); + const bool bVert = iCapPlacement == XFA_AttributeEnum::Top || + iCapPlacement == XFA_AttributeEnum::Bottom; + const bool bReserveExit = fCapReserve > 0.01; + CXFA_TextLayout* pCapTextLayout = + static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) + ->m_pCapTextLayout.get(); + if (pCapTextLayout) { + if (!bVert && eUIType != XFA_Element::Button) + szCap.width = fCapReserve; + + CFX_SizeF minSize; + szCap = pCapTextLayout->CalcSize(minSize, szCap); + if (bReserveExit) + bVert ? szCap.height = fCapReserve : szCap.width = fCapReserve; + } else { + float fFontSize = 10.0f; + CXFA_Font* font = caption->GetFontIfExists(); + if (font) { + fFontSize = font->GetFontSize(); + } else { + CXFA_Font* widgetfont = m_pNode->GetFontIfExists(); + if (widgetfont) + fFontSize = widgetfont->GetFontSize(); + } + + if (bVert) { + szCap.height = fCapReserve > 0 ? fCapReserve : fFontSize; + } else { + szCap.width = fCapReserve > 0 ? fCapReserve : 0; + szCap.height = fFontSize; + } + } + + CXFA_Margin* captionMargin = caption->GetMarginIfExists(); + if (!captionMargin) + return; + + float fLeftInset = captionMargin->GetLeftInset(); + float fTopInset = captionMargin->GetTopInset(); + float fRightInset = captionMargin->GetRightInset(); + float fBottomInset = captionMargin->GetBottomInset(); + if (bReserveExit) { + bVert ? (szCap.width += fLeftInset + fRightInset) + : (szCap.height += fTopInset + fBottomInset); + } else { + szCap.width += fLeftInset + fRightInset; + szCap.height += fTopInset + fBottomInset; + } +} + +bool CXFA_Node::CalculateFieldAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size) { + CFX_SizeF szCap; + CalcCaptionSize(doc, szCap); + + CFX_RectF rtUIMargin = m_pNode->GetUIMargin(); + size.width += rtUIMargin.left + rtUIMargin.width; + size.height += rtUIMargin.top + rtUIMargin.height; + if (szCap.width > 0 && szCap.height > 0) { + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + XFA_AttributeEnum placement = caption ? caption->GetPlacementType() + : CXFA_Caption::kDefaultPlacementType; + switch (placement) { + case XFA_AttributeEnum::Left: + case XFA_AttributeEnum::Right: + case XFA_AttributeEnum::Inline: { + size.width += szCap.width; + size.height = std::max(size.height, szCap.height); + } break; + case XFA_AttributeEnum::Top: + case XFA_AttributeEnum::Bottom: { + size.height += szCap.height; + size.width = std::max(size.width, szCap.width); + } + default: + break; + } + } + return CalculateWidgetAutoSize(size); +} + +bool CXFA_Node::CalculateWidgetAutoSize(CFX_SizeF& size) { + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) { + size.width += margin->GetLeftInset() + margin->GetRightInset(); + size.height += margin->GetTopInset() + margin->GetBottomInset(); + } + + CXFA_Para* para = m_pNode->GetParaIfExists(); + if (para) + size.width += para->GetMarginLeft() + para->GetTextIndent(); + + Optional<float> width = m_pNode->TryWidth(); + if (width) { + size.width = *width; + } else { + Optional<float> min = m_pNode->TryMinWidth(); + if (min) + size.width = std::max(size.width, *min); + + Optional<float> max = m_pNode->TryMaxWidth(); + if (max && *max > 0) + size.width = std::min(size.width, *max); + } + + Optional<float> height = m_pNode->TryHeight(); + if (height) { + size.height = *height; + } else { + Optional<float> min = m_pNode->TryMinHeight(); + if (min) + size.height = std::max(size.height, *min); + + Optional<float> max = m_pNode->TryMaxHeight(); + if (max && *max > 0) + size.height = std::min(size.height, *max); + } + return true; +} + +void CXFA_Node::CalculateTextContentSize(CXFA_FFDoc* doc, CFX_SizeF& size) { + float fFontSize = m_pNode->GetFontSize(); + WideString wsText = GetValue(XFA_VALUEPICTURE_Display); + if (wsText.IsEmpty()) { + size.height += fFontSize; + return; + } + + wchar_t wcEnter = '\n'; + wchar_t wsLast = wsText[wsText.GetLength() - 1]; + if (wsLast == wcEnter) + wsText = wsText + wcEnter; + + CXFA_FieldLayoutData* layoutData = + static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()); + if (!layoutData->m_pTextOut) { + layoutData->m_pTextOut = pdfium::MakeUnique<CFDE_TextOut>(); + CFDE_TextOut* pTextOut = layoutData->m_pTextOut.get(); + pTextOut->SetFont(GetFDEFont(doc)); + pTextOut->SetFontSize(fFontSize); + pTextOut->SetLineBreakTolerance(fFontSize * 0.2f); + pTextOut->SetLineSpace(m_pNode->GetLineHeight()); + + FDE_TextStyle dwStyles; + dwStyles.last_line_height_ = true; + if (m_pNode->GetUIType() == XFA_Element::TextEdit && IsMultiLine()) + dwStyles.line_wrap_ = true; + + pTextOut->SetStyles(dwStyles); + } + layoutData->m_pTextOut->CalcLogicSize(wsText, size); +} + +bool CXFA_Node::CalculateTextEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size) { + if (size.width > 0) { + CFX_SizeF szOrz = size; + CFX_SizeF szCap; + CalcCaptionSize(doc, szCap); + bool bCapExit = szCap.width > 0.01 && szCap.height > 0.01; + XFA_AttributeEnum iCapPlacement = XFA_AttributeEnum::Unknown; + if (bCapExit) { + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + iCapPlacement = caption ? caption->GetPlacementType() + : CXFA_Caption::kDefaultPlacementType; + switch (iCapPlacement) { + case XFA_AttributeEnum::Left: + case XFA_AttributeEnum::Right: + case XFA_AttributeEnum::Inline: { + size.width -= szCap.width; + } + default: + break; + } + } + CFX_RectF rtUIMargin = m_pNode->GetUIMargin(); + size.width -= rtUIMargin.left + rtUIMargin.width; + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + size.width -= margin->GetLeftInset() + margin->GetRightInset(); + + CalculateTextContentSize(doc, size); + size.height += rtUIMargin.top + rtUIMargin.height; + if (bCapExit) { + switch (iCapPlacement) { + case XFA_AttributeEnum::Left: + case XFA_AttributeEnum::Right: + case XFA_AttributeEnum::Inline: { + size.height = std::max(size.height, szCap.height); + } break; + case XFA_AttributeEnum::Top: + case XFA_AttributeEnum::Bottom: { + size.height += szCap.height; + } + default: + break; + } + } + size.width = szOrz.width; + return CalculateWidgetAutoSize(size); + } + CalculateTextContentSize(doc, size); + return CalculateFieldAutoSize(doc, size); +} + +bool CXFA_Node::CalculateCheckButtonAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size) { + float fCheckSize = GetCheckButtonSize(); + size = CFX_SizeF(fCheckSize, fCheckSize); + return CalculateFieldAutoSize(doc, size); +} + +bool CXFA_Node::CalculatePushButtonAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size) { + CalcCaptionSize(doc, size); + return CalculateWidgetAutoSize(size); +} + +CFX_SizeF CXFA_Node::CalculateImageSize(float img_width, + float img_height, + float dpi_x, + float dpi_y) { + CFX_RectF rtImage(0, 0, XFA_UnitPx2Pt(img_width, dpi_x), + XFA_UnitPx2Pt(img_height, dpi_y)); + + CFX_RectF rtFit; + Optional<float> width = m_pNode->TryWidth(); + if (width) { + rtFit.width = *width; + GetWidthWithoutMargin(rtFit.width); + } else { + rtFit.width = rtImage.width; + } + + Optional<float> height = m_pNode->TryHeight(); + if (height) { + rtFit.height = *height; + GetHeightWithoutMargin(rtFit.height); + } else { + rtFit.height = rtImage.height; + } + + return rtFit.Size(); +} + +bool CXFA_Node::CalculateImageAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size) { + if (!GetImageImage()) + LoadImageImage(doc); + + size.clear(); + RetainPtr<CFX_DIBitmap> pBitmap = GetImageImage(); + if (!pBitmap) + return CalculateWidgetAutoSize(size); + + int32_t iImageXDpi = 0; + int32_t iImageYDpi = 0; + GetImageDpi(iImageXDpi, iImageYDpi); + + size = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(), + iImageXDpi, iImageYDpi); + return CalculateWidgetAutoSize(size); +} + +bool CXFA_Node::CalculateImageEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size) { + if (!GetImageEditImage()) + LoadImageEditImage(doc); + + size.clear(); + RetainPtr<CFX_DIBitmap> pBitmap = GetImageEditImage(); + if (!pBitmap) + return CalculateFieldAutoSize(doc, size); + + int32_t iImageXDpi = 0; + int32_t iImageYDpi = 0; + GetImageEditDpi(iImageXDpi, iImageYDpi); + + size = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(), + iImageXDpi, iImageYDpi); + return CalculateFieldAutoSize(doc, size); +} + +bool CXFA_Node::LoadImageImage(CXFA_FFDoc* doc) { + InitLayoutData(); + return static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()) + ->LoadImageData(doc, this); +} + +bool CXFA_Node::LoadImageEditImage(CXFA_FFDoc* doc) { + InitLayoutData(); + return static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()) + ->LoadImageData(doc, this); +} + +void CXFA_Node::GetImageDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) { + CXFA_ImageLayoutData* pData = + static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()); + iImageXDpi = pData->m_iImageXDpi; + iImageYDpi = pData->m_iImageYDpi; +} + +void CXFA_Node::GetImageEditDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) { + CXFA_ImageEditData* pData = + static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()); + iImageXDpi = pData->m_iImageXDpi; + iImageYDpi = pData->m_iImageYDpi; +} + +void CXFA_Node::LoadText(CXFA_FFDoc* doc) { + InitLayoutData(); + static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->LoadText(doc, this); +} + +float CXFA_Node::CalculateWidgetAutoWidth(float fWidthCalc) { + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + fWidthCalc += margin->GetLeftInset() + margin->GetRightInset(); + + Optional<float> min = m_pNode->TryMinWidth(); + if (min) + fWidthCalc = std::max(fWidthCalc, *min); + + Optional<float> max = m_pNode->TryMaxWidth(); + if (max && *max > 0) + fWidthCalc = std::min(fWidthCalc, *max); + + return fWidthCalc; +} + +float CXFA_Node::GetWidthWithoutMargin(float fWidthCalc) { + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + fWidthCalc -= margin->GetLeftInset() + margin->GetRightInset(); + return fWidthCalc; +} + +float CXFA_Node::CalculateWidgetAutoHeight(float fHeightCalc) { + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + fHeightCalc += margin->GetTopInset() + margin->GetBottomInset(); + + Optional<float> min = m_pNode->TryMinHeight(); + if (min) + fHeightCalc = std::max(fHeightCalc, *min); + + Optional<float> max = m_pNode->TryMaxHeight(); + if (max && *max > 0) + fHeightCalc = std::min(fHeightCalc, *max); + + return fHeightCalc; +} + +float CXFA_Node::GetHeightWithoutMargin(float fHeightCalc) { + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + fHeightCalc -= margin->GetTopInset() + margin->GetBottomInset(); + return fHeightCalc; +} + +void CXFA_Node::StartWidgetLayout(CXFA_FFDoc* doc, + float& fCalcWidth, + float& fCalcHeight) { + InitLayoutData(); + + XFA_Element eUIType = m_pNode->GetUIType(); + if (eUIType == XFA_Element::Text) { + m_pLayoutData->m_fWidgetHeight = m_pNode->TryHeight().value_or(-1); + StartTextLayout(doc, fCalcWidth, fCalcHeight); + return; + } + if (fCalcWidth > 0 && fCalcHeight > 0) + return; + + m_pLayoutData->m_fWidgetHeight = -1; + float fWidth = 0; + if (fCalcWidth > 0 && fCalcHeight < 0) { + Optional<float> height = m_pNode->TryHeight(); + if (height) + fCalcHeight = *height; + else + CalculateAccWidthAndHeight(doc, eUIType, fCalcWidth, fCalcHeight); + + m_pLayoutData->m_fWidgetHeight = fCalcHeight; + return; + } + if (fCalcWidth < 0 && fCalcHeight < 0) { + Optional<float> height; + Optional<float> width = m_pNode->TryWidth(); + if (width) { + fWidth = *width; + + height = m_pNode->TryHeight(); + if (height) + fCalcHeight = *height; + } + if (!width || !height) + CalculateAccWidthAndHeight(doc, eUIType, fWidth, fCalcHeight); + + fCalcWidth = fWidth; + } + m_pLayoutData->m_fWidgetHeight = fCalcHeight; +} + +void CXFA_Node::CalculateAccWidthAndHeight(CXFA_FFDoc* doc, + XFA_Element eUIType, + float& fWidth, + float& fCalcHeight) { + CFX_SizeF sz(fWidth, m_pLayoutData->m_fWidgetHeight); + switch (eUIType) { + case XFA_Element::Barcode: + case XFA_Element::ChoiceList: + case XFA_Element::Signature: + CalculateFieldAutoSize(doc, sz); + break; + case XFA_Element::ImageEdit: + CalculateImageEditAutoSize(doc, sz); + break; + case XFA_Element::Button: + CalculatePushButtonAutoSize(doc, sz); + break; + case XFA_Element::CheckButton: + CalculateCheckButtonAutoSize(doc, sz); + break; + case XFA_Element::DateTimeEdit: + case XFA_Element::NumericEdit: + case XFA_Element::PasswordEdit: + case XFA_Element::TextEdit: + CalculateTextEditAutoSize(doc, sz); + break; + case XFA_Element::Image: + CalculateImageAutoSize(doc, sz); + break; + case XFA_Element::Arc: + case XFA_Element::Line: + case XFA_Element::Rectangle: + case XFA_Element::Subform: + case XFA_Element::ExclGroup: + CalculateWidgetAutoSize(sz); + break; + default: + break; + } + fWidth = sz.width; + m_pLayoutData->m_fWidgetHeight = sz.height; + fCalcHeight = sz.height; +} + +bool CXFA_Node::FindSplitPos(CXFA_FFDocView* docView, + int32_t iBlockIndex, + float& fCalcHeight) { + XFA_Element eUIType = m_pNode->GetUIType(); + if (eUIType == XFA_Element::Subform) + return false; + + if (eUIType != XFA_Element::Text && eUIType != XFA_Element::TextEdit && + eUIType != XFA_Element::NumericEdit && + eUIType != XFA_Element::PasswordEdit) { + fCalcHeight = 0; + return true; + } + + float fTopInset = 0; + float fBottomInset = 0; + if (iBlockIndex == 0) { + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) { + fTopInset = margin->GetTopInset(); + fBottomInset = margin->GetBottomInset(); + } + + CFX_RectF rtUIMargin = m_pNode->GetUIMargin(); + fTopInset += rtUIMargin.top; + fBottomInset += rtUIMargin.width; + } + if (eUIType == XFA_Element::Text) { + float fHeight = fCalcHeight; + if (iBlockIndex == 0) { + fCalcHeight = fCalcHeight - fTopInset; + if (fCalcHeight < 0) + fCalcHeight = 0; + } + + CXFA_TextLayout* pTextLayout = + static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout(); + fCalcHeight = + pTextLayout->DoLayout(iBlockIndex, fCalcHeight, fCalcHeight, + m_pLayoutData->m_fWidgetHeight - fTopInset); + if (fCalcHeight != 0) { + if (iBlockIndex == 0) + fCalcHeight = fCalcHeight + fTopInset; + if (fabs(fHeight - fCalcHeight) < XFA_FLOAT_PERCISION) + return false; + } + return true; + } + XFA_AttributeEnum iCapPlacement = XFA_AttributeEnum::Unknown; + float fCapReserve = 0; + if (iBlockIndex == 0) { + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + if (caption && !caption->IsHidden()) { + iCapPlacement = caption->GetPlacementType(); + fCapReserve = caption->GetReserve(); + } + if (iCapPlacement == XFA_AttributeEnum::Top && + fCalcHeight < fCapReserve + fTopInset) { + fCalcHeight = 0; + return true; + } + if (iCapPlacement == XFA_AttributeEnum::Bottom && + m_pLayoutData->m_fWidgetHeight - fCapReserve - fBottomInset) { + fCalcHeight = 0; + return true; + } + if (iCapPlacement != XFA_AttributeEnum::Top) + fCapReserve = 0; + } + CXFA_FieldLayoutData* pFieldData = + static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()); + int32_t iLinesCount = 0; + float fHeight = m_pLayoutData->m_fWidgetHeight; + if (GetValue(XFA_VALUEPICTURE_Display).IsEmpty()) { + iLinesCount = 1; + } else { + if (!pFieldData->m_pTextOut) { + // TODO(dsinclair): Inline fWidth when the 2nd param of + // CalculateAccWidthAndHeight isn't a ref-param. + float fWidth = m_pNode->TryWidth().value_or(0); + CalculateAccWidthAndHeight(docView->GetDoc(), eUIType, fWidth, fHeight); + } + iLinesCount = pFieldData->m_pTextOut->GetTotalLines(); + } + std::vector<float>* pFieldArray = &pFieldData->m_FieldSplitArray; + int32_t iFieldSplitCount = pdfium::CollectionSize<int32_t>(*pFieldArray); + for (int32_t i = 0; i < iBlockIndex * 3; i += 3) { + iLinesCount -= (int32_t)(*pFieldArray)[i + 1]; + fHeight -= (*pFieldArray)[i + 2]; + } + if (iLinesCount == 0) + return false; + + float fLineHeight = m_pNode->GetLineHeight(); + float fFontSize = m_pNode->GetFontSize(); + float fTextHeight = iLinesCount * fLineHeight - fLineHeight + fFontSize; + float fSpaceAbove = 0; + float fStartOffset = 0; + if (fHeight > 0.1f && iBlockIndex == 0) { + fStartOffset = fTopInset; + fHeight -= (fTopInset + fBottomInset); + CXFA_Para* para = m_pNode->GetParaIfExists(); + if (para) { + fSpaceAbove = para->GetSpaceAbove(); + float fSpaceBelow = para->GetSpaceBelow(); + fHeight -= (fSpaceAbove + fSpaceBelow); + switch (para->GetVerticalAlign()) { + case XFA_AttributeEnum::Top: + fStartOffset += fSpaceAbove; + break; + case XFA_AttributeEnum::Middle: + fStartOffset += ((fHeight - fTextHeight) / 2 + fSpaceAbove); + break; + case XFA_AttributeEnum::Bottom: + fStartOffset += (fHeight - fTextHeight + fSpaceAbove); + break; + default: + NOTREACHED(); + break; + } + } + if (fStartOffset < 0.1f) + fStartOffset = 0; + } + for (int32_t i = iBlockIndex - 1; iBlockIndex > 0 && i < iBlockIndex; i++) { + fStartOffset = (*pFieldArray)[i * 3] - (*pFieldArray)[i * 3 + 2]; + if (fStartOffset < 0.1f) + fStartOffset = 0; + } + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) + (*pFieldArray)[0] = fStartOffset; + else + pFieldArray->push_back(fStartOffset); + + XFA_VERSION version = docView->GetDoc()->GetXFADoc()->GetCurVersionMode(); + bool bCanSplitNoContent = false; + XFA_AttributeEnum eLayoutMode = GetNode() + ->GetParent() + ->JSObject() + ->TryEnum(XFA_Attribute::Layout, true) + .value_or(XFA_AttributeEnum::Position); + if ((eLayoutMode == XFA_AttributeEnum::Position || + eLayoutMode == XFA_AttributeEnum::Tb || + eLayoutMode == XFA_AttributeEnum::Row || + eLayoutMode == XFA_AttributeEnum::Table) && + version > XFA_VERSION_208) { + bCanSplitNoContent = true; + } + if ((eLayoutMode == XFA_AttributeEnum::Tb || + eLayoutMode == XFA_AttributeEnum::Row || + eLayoutMode == XFA_AttributeEnum::Table) && + version <= XFA_VERSION_208) { + if (fStartOffset < fCalcHeight) { + bCanSplitNoContent = true; + } else { + fCalcHeight = 0; + return true; + } + } + if (bCanSplitNoContent) { + if ((fCalcHeight - fTopInset - fSpaceAbove < fLineHeight)) { + fCalcHeight = 0; + return true; + } + if (fStartOffset + XFA_FLOAT_PERCISION >= fCalcHeight) { + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { + (*pFieldArray)[iBlockIndex * 3 + 1] = 0; + (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; + } else { + pFieldArray->push_back(0); + pFieldArray->push_back(fCalcHeight); + } + return false; + } + if (fCalcHeight - fStartOffset < fLineHeight) { + fCalcHeight = fStartOffset; + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { + (*pFieldArray)[iBlockIndex * 3 + 1] = 0; + (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; + } else { + pFieldArray->push_back(0); + pFieldArray->push_back(fCalcHeight); + } + return true; + } + float fTextNum = + fCalcHeight + XFA_FLOAT_PERCISION - fCapReserve - fStartOffset; + int32_t iLineNum = + (int32_t)((fTextNum + (fLineHeight - fFontSize)) / fLineHeight); + if (iLineNum >= iLinesCount) { + if (fCalcHeight - fStartOffset - fTextHeight >= fFontSize) { + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { + (*pFieldArray)[iBlockIndex * 3 + 1] = (float)iLinesCount; + (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; + } else { + pFieldArray->push_back((float)iLinesCount); + pFieldArray->push_back(fCalcHeight); + } + return false; + } + if (fHeight - fStartOffset - fTextHeight < fFontSize) { + iLineNum -= 1; + if (iLineNum == 0) { + fCalcHeight = 0; + return true; + } + } else { + iLineNum = (int32_t)(fTextNum / fLineHeight); + } + } + if (iLineNum > 0) { + float fSplitHeight = iLineNum * fLineHeight + fCapReserve + fStartOffset; + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { + (*pFieldArray)[iBlockIndex * 3 + 1] = (float)iLineNum; + (*pFieldArray)[iBlockIndex * 3 + 2] = fSplitHeight; + } else { + pFieldArray->push_back((float)iLineNum); + pFieldArray->push_back(fSplitHeight); + } + if (fabs(fSplitHeight - fCalcHeight) < XFA_FLOAT_PERCISION) + return false; + + fCalcHeight = fSplitHeight; + return true; + } + } + fCalcHeight = 0; + return true; +} + +void CXFA_Node::InitLayoutData() { + if (m_pLayoutData) + return; + + switch (m_pNode->GetUIType()) { + case XFA_Element::Text: + m_pLayoutData = pdfium::MakeUnique<CXFA_TextLayoutData>(); + return; + case XFA_Element::TextEdit: + m_pLayoutData = pdfium::MakeUnique<CXFA_TextEditData>(); + return; + case XFA_Element::Image: + m_pLayoutData = pdfium::MakeUnique<CXFA_ImageLayoutData>(); + return; + case XFA_Element::ImageEdit: + m_pLayoutData = pdfium::MakeUnique<CXFA_ImageEditData>(); + return; + default: + break; + } + if (m_pNode && m_pNode->GetElementType() == XFA_Element::Field) { + m_pLayoutData = pdfium::MakeUnique<CXFA_FieldLayoutData>(); + return; + } + m_pLayoutData = pdfium::MakeUnique<CXFA_WidgetLayoutData>(); +} + +void CXFA_Node::StartTextLayout(CXFA_FFDoc* doc, + float& fCalcWidth, + float& fCalcHeight) { + LoadText(doc); + + CXFA_TextLayout* pTextLayout = + static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout(); + float fTextHeight = 0; + if (fCalcWidth > 0 && fCalcHeight > 0) { + float fWidth = GetWidthWithoutMargin(fCalcWidth); + pTextLayout->StartLayout(fWidth); + fTextHeight = fCalcHeight; + fTextHeight = GetHeightWithoutMargin(fTextHeight); + pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight); + return; + } + if (fCalcWidth > 0 && fCalcHeight < 0) { + float fWidth = GetWidthWithoutMargin(fCalcWidth); + pTextLayout->StartLayout(fWidth); + } + + if (fCalcWidth < 0 && fCalcHeight < 0) { + Optional<float> width = m_pNode->TryWidth(); + if (width) { + pTextLayout->StartLayout(GetWidthWithoutMargin(*width)); + fCalcWidth = *width; + } else { + float fMaxWidth = CalculateWidgetAutoWidth(pTextLayout->StartLayout(-1)); + pTextLayout->StartLayout(GetWidthWithoutMargin(fMaxWidth)); + fCalcWidth = fMaxWidth; + } + } + + if (m_pLayoutData->m_fWidgetHeight < 0) { + m_pLayoutData->m_fWidgetHeight = pTextLayout->GetLayoutHeight(); + m_pLayoutData->m_fWidgetHeight = + CalculateWidgetAutoHeight(m_pLayoutData->m_fWidgetHeight); + } + fTextHeight = m_pLayoutData->m_fWidgetHeight; + fTextHeight = GetHeightWithoutMargin(fTextHeight); + pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight); + fCalcHeight = m_pLayoutData->m_fWidgetHeight; +} + +bool CXFA_Node::LoadCaption(CXFA_FFDoc* doc) { + InitLayoutData(); + return static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) + ->LoadCaption(doc, this); +} + +CXFA_TextLayout* CXFA_Node::GetCaptionTextLayout() { + return m_pLayoutData ? static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) + ->m_pCapTextLayout.get() + : nullptr; +} + +CXFA_TextLayout* CXFA_Node::GetTextLayout() { + return m_pLayoutData ? static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get()) + ->GetTextLayout() + : nullptr; +} + +RetainPtr<CFX_DIBitmap> CXFA_Node::GetImageImage() { + return m_pLayoutData ? static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()) + ->m_pDIBitmap + : nullptr; +} + +RetainPtr<CFX_DIBitmap> CXFA_Node::GetImageEditImage() { + return m_pLayoutData ? static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()) + ->m_pDIBitmap + : nullptr; +} + +void CXFA_Node::SetImageImage(const RetainPtr<CFX_DIBitmap>& newImage) { + CXFA_ImageLayoutData* pData = + static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()); + if (pData->m_pDIBitmap != newImage) + pData->m_pDIBitmap = newImage; +} + +void CXFA_Node::SetImageEditImage(const RetainPtr<CFX_DIBitmap>& newImage) { + CXFA_ImageEditData* pData = + static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()); + if (pData->m_pDIBitmap != newImage) + pData->m_pDIBitmap = newImage; +} + +RetainPtr<CFGAS_GEFont> CXFA_Node::GetFDEFont(CXFA_FFDoc* doc) { + WideString wsFontName = L"Courier"; + uint32_t dwFontStyle = 0; + CXFA_Font* font = m_pNode->GetFontIfExists(); + if (font) { + if (font->IsBold()) + dwFontStyle |= FXFONT_BOLD; + if (font->IsItalic()) + dwFontStyle |= FXFONT_ITALIC; + + wsFontName = font->GetTypeface(); + } + return doc->GetApp()->GetXFAFontMgr()->GetFont(doc, wsFontName.AsStringView(), + dwFontStyle); +} + +bool CXFA_Node::IsOpenAccess() const { + return m_pNode && m_pNode->IsOpenAccess(); +} + +XFA_AttributeEnum CXFA_Node::GetButtonHighlight() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + if (pUIChild) + return pUIChild->JSObject()->GetEnum(XFA_Attribute::Highlight); + return XFA_AttributeEnum::Inverted; +} + +bool CXFA_Node::HasButtonRollover() const { + CXFA_Items* pItems = + m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItems) + return false; + + for (CXFA_Node* pText = pItems->GetFirstChild(); pText; + pText = pText->GetNextSibling()) { + if (pText->JSObject()->GetCData(XFA_Attribute::Name) == L"rollover") + return !pText->JSObject()->GetContent(false).IsEmpty(); + } + return false; +} + +bool CXFA_Node::HasButtonDown() const { + CXFA_Items* pItems = + m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItems) + return false; + + for (CXFA_Node* pText = pItems->GetFirstChild(); pText; + pText = pText->GetNextSibling()) { + if (pText->JSObject()->GetCData(XFA_Attribute::Name) == L"down") + return !pText->JSObject()->GetContent(false).IsEmpty(); + } + return false; +} + +bool CXFA_Node::IsCheckButtonRound() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + if (pUIChild) + return pUIChild->JSObject()->GetEnum(XFA_Attribute::Shape) == + XFA_AttributeEnum::Round; + return false; +} + +XFA_AttributeEnum CXFA_Node::GetCheckButtonMark() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + if (pUIChild) + return pUIChild->JSObject()->GetEnum(XFA_Attribute::Mark); + return XFA_AttributeEnum::Default; +} + +bool CXFA_Node::IsRadioButton() { + CXFA_Node* pParent = m_pNode->GetParent(); + return pParent && pParent->GetElementType() == XFA_Element::ExclGroup; +} + +float CXFA_Node::GetCheckButtonSize() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + if (pUIChild) { + return pUIChild->JSObject() + ->GetMeasure(XFA_Attribute::Size) + .ToUnit(XFA_Unit::Pt); + } + return CXFA_Measurement(10, XFA_Unit::Pt).ToUnit(XFA_Unit::Pt); +} + +bool CXFA_Node::IsAllowNeutral() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + return pUIChild && + pUIChild->JSObject()->GetBoolean(XFA_Attribute::AllowNeutral); +} + +XFA_CHECKSTATE CXFA_Node::GetCheckState() { + WideString wsValue = m_pNode->GetRawValue(); + if (wsValue.IsEmpty()) + return XFA_CHECKSTATE_Off; + + auto* pItems = m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItems) + return XFA_CHECKSTATE_Off; + + CXFA_Node* pText = pItems->GetFirstChild(); + int32_t i = 0; + while (pText) { + Optional<WideString> wsContent = pText->JSObject()->TryContent(false, true); + if (wsContent && *wsContent == wsValue) + return static_cast<XFA_CHECKSTATE>(i); + + i++; + pText = pText->GetNextSibling(); + } + return XFA_CHECKSTATE_Off; +} + +void CXFA_Node::SetCheckState(XFA_CHECKSTATE eCheckState, bool bNotify) { + CXFA_Node* node = m_pNode->GetExclGroupIfExists(); + if (!node) { + CXFA_Items* pItems = + m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItems) + return; + + int32_t i = -1; + CXFA_Node* pText = pItems->GetFirstChild(); + WideString wsContent; + while (pText) { + i++; + if (i == eCheckState) { + wsContent = pText->JSObject()->GetContent(false); + break; + } + pText = pText->GetNextSibling(); + } + m_pNode->SyncValue(wsContent, bNotify); + + return; + } + + WideString wsValue; + if (eCheckState != XFA_CHECKSTATE_Off) { + if (CXFA_Items* pItems = + m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false)) { + CXFA_Node* pText = pItems->GetFirstChild(); + if (pText) + wsValue = pText->JSObject()->GetContent(false); + } + } + CXFA_Node* pChild = node->GetFirstChild(); + for (; pChild; pChild = pChild->GetNextSibling()) { + if (pChild->GetElementType() != XFA_Element::Field) + continue; + + CXFA_Items* pItem = + pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItem) + continue; + + CXFA_Node* pItemchild = pItem->GetFirstChild(); + if (!pItemchild) + continue; + + WideString text = pItemchild->JSObject()->GetContent(false); + WideString wsChildValue = text; + if (wsValue != text) { + pItemchild = pItemchild->GetNextSibling(); + if (pItemchild) + wsChildValue = pItemchild->JSObject()->GetContent(false); + else + wsChildValue.clear(); + } + pChild->SyncValue(wsChildValue, bNotify); + } + node->SyncValue(wsValue, bNotify); +} + +CXFA_Node* CXFA_Node::GetSelectedMember() { + CXFA_Node* pSelectedMember = nullptr; + WideString wsState = m_pNode->GetRawValue(); + if (wsState.IsEmpty()) + return pSelectedMember; + + for (CXFA_Node* pNode = ToNode(m_pNode->GetFirstChild()); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetCheckState() == XFA_CHECKSTATE_On) { + pSelectedMember = pNode; + break; + } + } + return pSelectedMember; +} + +CXFA_Node* CXFA_Node::SetSelectedMember(const WideStringView& wsName, + bool bNotify) { + uint32_t nameHash = FX_HashCode_GetW(wsName, false); + for (CXFA_Node* pNode = ToNode(m_pNode->GetFirstChild()); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetNameHash() == nameHash) { + pNode->SetCheckState(XFA_CHECKSTATE_On, bNotify); + return pNode; + } + } + return nullptr; +} + +void CXFA_Node::SetSelectedMemberByValue(const WideStringView& wsValue, + bool bNotify, + bool bScriptModify, + bool bSyncData) { + WideString wsExclGroup; + for (CXFA_Node* pNode = m_pNode->GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetElementType() != XFA_Element::Field) + continue; + + CXFA_Items* pItem = + pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItem) + continue; + + CXFA_Node* pItemchild = pItem->GetFirstChild(); + if (!pItemchild) + continue; + + WideString wsChildValue = pItemchild->JSObject()->GetContent(false); + if (wsValue != wsChildValue) { + pItemchild = pItemchild->GetNextSibling(); + if (pItemchild) + wsChildValue = pItemchild->JSObject()->GetContent(false); + else + wsChildValue.clear(); + } else { + wsExclGroup = wsValue; + } + pNode->JSObject()->SetContent(wsChildValue, wsChildValue, bNotify, + bScriptModify, false); + } + m_pNode->JSObject()->SetContent(wsExclGroup, wsExclGroup, bNotify, + bScriptModify, bSyncData); +} + +CXFA_Node* CXFA_Node::GetExclGroupFirstMember() { + CXFA_Node* pExcl = GetNode(); + if (!pExcl) + return nullptr; + + CXFA_Node* pNode = pExcl->GetFirstChild(); + while (pNode) { + if (pNode->GetElementType() == XFA_Element::Field) + return pNode; + + pNode = pNode->GetNextSibling(); + } + return nullptr; +} +CXFA_Node* CXFA_Node::GetExclGroupNextMember(CXFA_Node* pNode) { + if (!pNode) + return nullptr; + + CXFA_Node* pNodeField = pNode->GetNextSibling(); + while (pNodeField) { + if (pNodeField->GetElementType() == XFA_Element::Field) + return pNodeField; + + pNodeField = pNodeField->GetNextSibling(); + } + return nullptr; +} + +bool CXFA_Node::IsChoiceListCommitOnSelect() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + if (pUIChild) { + return pUIChild->JSObject()->GetEnum(XFA_Attribute::CommitOn) == + XFA_AttributeEnum::Select; + } + return true; +} + +bool CXFA_Node::IsChoiceListAllowTextEntry() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + return pUIChild && pUIChild->JSObject()->GetBoolean(XFA_Attribute::TextEntry); +} + +bool CXFA_Node::IsChoiceListMultiSelect() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + if (pUIChild) { + return pUIChild->JSObject()->GetEnum(XFA_Attribute::Open) == + XFA_AttributeEnum::MultiSelect; + } + return false; +} + +bool CXFA_Node::IsListBox() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + if (!pUIChild) + return false; + + XFA_AttributeEnum attr = pUIChild->JSObject()->GetEnum(XFA_Attribute::Open); + return attr == XFA_AttributeEnum::Always || + attr == XFA_AttributeEnum::MultiSelect; +} + +int32_t CXFA_Node::CountChoiceListItems(bool bSaveValue) { + std::vector<CXFA_Node*> pItems; + int32_t iCount = 0; + for (CXFA_Node* pNode = m_pNode->GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetElementType() != XFA_Element::Items) + continue; + iCount++; + pItems.push_back(pNode); + if (iCount == 2) + break; + } + if (iCount == 0) + return 0; + + CXFA_Node* pItem = pItems[0]; + if (iCount > 1) { + bool bItemOneHasSave = + pItems[0]->JSObject()->GetBoolean(XFA_Attribute::Save); + bool bItemTwoHasSave = + pItems[1]->JSObject()->GetBoolean(XFA_Attribute::Save); + if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave) + pItem = pItems[1]; + } + return pItem->CountChildren(XFA_Element::Unknown, false); +} + +Optional<WideString> CXFA_Node::GetChoiceListItem(int32_t nIndex, + bool bSaveValue) { + std::vector<CXFA_Node*> pItemsArray; + int32_t iCount = 0; + for (CXFA_Node* pNode = m_pNode->GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetElementType() != XFA_Element::Items) + continue; + + ++iCount; + pItemsArray.push_back(pNode); + if (iCount == 2) + break; + } + if (iCount == 0) + return {}; + + CXFA_Node* pItems = pItemsArray[0]; + if (iCount > 1) { + bool bItemOneHasSave = + pItemsArray[0]->JSObject()->GetBoolean(XFA_Attribute::Save); + bool bItemTwoHasSave = + pItemsArray[1]->JSObject()->GetBoolean(XFA_Attribute::Save); + if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave) + pItems = pItemsArray[1]; + } + if (!pItems) + return {}; + + CXFA_Node* pItem = + pItems->GetChild<CXFA_Node>(nIndex, XFA_Element::Unknown, false); + if (pItem) + return {pItem->JSObject()->GetContent(false)}; + return {}; +} + +std::vector<WideString> CXFA_Node::GetChoiceListItems(bool bSaveValue) { + std::vector<CXFA_Node*> items; + for (CXFA_Node* pNode = m_pNode->GetFirstChild(); pNode && items.size() < 2; + pNode = pNode->GetNextSibling()) { + if (pNode->GetElementType() == XFA_Element::Items) + items.push_back(pNode); + } + if (items.empty()) + return std::vector<WideString>(); + + CXFA_Node* pItem = items.front(); + if (items.size() > 1) { + bool bItemOneHasSave = + items[0]->JSObject()->GetBoolean(XFA_Attribute::Save); + bool bItemTwoHasSave = + items[1]->JSObject()->GetBoolean(XFA_Attribute::Save); + if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave) + pItem = items[1]; + } + + std::vector<WideString> wsTextArray; + for (CXFA_Node* pNode = pItem->GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + wsTextArray.emplace_back(pNode->JSObject()->GetContent(false)); + } + return wsTextArray; +} + +int32_t CXFA_Node::CountSelectedItems() { + std::vector<WideString> wsValueArray = GetSelectedItemsValue(); + if (IsListBox() || !IsChoiceListAllowTextEntry()) + return pdfium::CollectionSize<int32_t>(wsValueArray); + + int32_t iSelected = 0; + std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); + for (const auto& value : wsValueArray) { + if (pdfium::ContainsValue(wsSaveTextArray, value)) + iSelected++; + } + return iSelected; +} + +int32_t CXFA_Node::GetSelectedItem(int32_t nIndex) { + std::vector<WideString> wsValueArray = GetSelectedItemsValue(); + if (!pdfium::IndexInBounds(wsValueArray, nIndex)) + return -1; + + std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); + auto it = std::find(wsSaveTextArray.begin(), wsSaveTextArray.end(), + wsValueArray[nIndex]); + return it != wsSaveTextArray.end() ? it - wsSaveTextArray.begin() : -1; +} + +std::vector<int32_t> CXFA_Node::GetSelectedItems() { + std::vector<int32_t> iSelArray; + std::vector<WideString> wsValueArray = GetSelectedItemsValue(); + std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); + for (const auto& value : wsValueArray) { + auto it = std::find(wsSaveTextArray.begin(), wsSaveTextArray.end(), value); + if (it != wsSaveTextArray.end()) + iSelArray.push_back(it - wsSaveTextArray.begin()); + } + return iSelArray; +} + +std::vector<WideString> CXFA_Node::GetSelectedItemsValue() { + std::vector<WideString> wsSelTextArray; + WideString wsValue = m_pNode->GetRawValue(); + if (IsChoiceListMultiSelect()) { + if (!wsValue.IsEmpty()) { + size_t iStart = 0; + size_t iLength = wsValue.GetLength(); + auto iEnd = wsValue.Find(L'\n', iStart); + iEnd = (!iEnd.has_value()) ? iLength : iEnd; + while (iEnd >= iStart) { + wsSelTextArray.push_back(wsValue.Mid(iStart, iEnd.value() - iStart)); + iStart = iEnd.value() + 1; + if (iStart >= iLength) + break; + iEnd = wsValue.Find(L'\n', iStart); + if (!iEnd.has_value()) + wsSelTextArray.push_back(wsValue.Mid(iStart, iLength - iStart)); + } + } + } else { + wsSelTextArray.push_back(wsValue); + } + return wsSelTextArray; +} + +bool CXFA_Node::GetItemState(int32_t nIndex) { + std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); + return pdfium::IndexInBounds(wsSaveTextArray, nIndex) && + pdfium::ContainsValue(GetSelectedItemsValue(), + wsSaveTextArray[nIndex]); +} + +void CXFA_Node::SetItemState(int32_t nIndex, + bool bSelected, + bool bNotify, + bool bScriptModify, + bool bSyncData) { + std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); + if (!pdfium::IndexInBounds(wsSaveTextArray, nIndex)) + return; + + int32_t iSel = -1; + std::vector<WideString> wsValueArray = GetSelectedItemsValue(); + auto it = std::find(wsValueArray.begin(), wsValueArray.end(), + wsSaveTextArray[nIndex]); + if (it != wsValueArray.end()) + iSel = it - wsValueArray.begin(); + + if (IsChoiceListMultiSelect()) { + if (bSelected) { + if (iSel < 0) { + WideString wsValue = m_pNode->GetRawValue(); + if (!wsValue.IsEmpty()) { + wsValue += L"\n"; + } + wsValue += wsSaveTextArray[nIndex]; + m_pNode->JSObject()->SetContent(wsValue, wsValue, bNotify, + bScriptModify, bSyncData); + } + } else if (iSel >= 0) { + std::vector<int32_t> iSelArray = GetSelectedItems(); + auto it = std::find(iSelArray.begin(), iSelArray.end(), nIndex); + if (it != iSelArray.end()) + iSelArray.erase(it); + SetSelectedItems(iSelArray, bNotify, bScriptModify, bSyncData); + } + } else { + if (bSelected) { + if (iSel < 0) { + WideString wsSaveText = wsSaveTextArray[nIndex]; + m_pNode->JSObject()->SetContent(wsSaveText, + GetFormatDataValue(wsSaveText), bNotify, + bScriptModify, bSyncData); + } + } else if (iSel >= 0) { + m_pNode->JSObject()->SetContent(WideString(), WideString(), bNotify, + bScriptModify, bSyncData); + } + } +} + +void CXFA_Node::SetSelectedItems(const std::vector<int32_t>& iSelArray, + bool bNotify, + bool bScriptModify, + bool bSyncData) { + WideString wsValue; + int32_t iSize = pdfium::CollectionSize<int32_t>(iSelArray); + if (iSize >= 1) { + std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); + WideString wsItemValue; + for (int32_t i = 0; i < iSize; i++) { + wsItemValue = (iSize == 1) ? wsSaveTextArray[iSelArray[i]] + : wsSaveTextArray[iSelArray[i]] + L"\n"; + wsValue += wsItemValue; + } + } + WideString wsFormat(wsValue); + if (!IsChoiceListMultiSelect()) + wsFormat = GetFormatDataValue(wsValue); + + m_pNode->JSObject()->SetContent(wsValue, wsFormat, bNotify, bScriptModify, + bSyncData); +} + +void CXFA_Node::ClearAllSelections() { + CXFA_Node* pBind = m_pNode->GetBindData(); + if (!pBind || !IsChoiceListMultiSelect()) { + m_pNode->SyncValue(WideString(), false); + return; + } + + while (CXFA_Node* pChildNode = pBind->GetFirstChild()) + pBind->RemoveChild(pChildNode, true); +} + +void CXFA_Node::InsertItem(const WideString& wsLabel, + const WideString& wsValue, + bool bNotify) { + int32_t nIndex = -1; + WideString wsNewValue(wsValue); + if (wsNewValue.IsEmpty()) + wsNewValue = wsLabel; + + std::vector<CXFA_Node*> listitems; + for (CXFA_Node* pItem = m_pNode->GetFirstChild(); pItem; + pItem = pItem->GetNextSibling()) { + if (pItem->GetElementType() == XFA_Element::Items) + listitems.push_back(pItem); + } + if (listitems.empty()) { + CXFA_Node* pItems = m_pNode->CreateSamePacketNode(XFA_Element::Items); + m_pNode->InsertChild(-1, pItems); + InsertListTextItem(pItems, wsLabel, nIndex); + CXFA_Node* pSaveItems = m_pNode->CreateSamePacketNode(XFA_Element::Items); + m_pNode->InsertChild(-1, pSaveItems); + pSaveItems->JSObject()->SetBoolean(XFA_Attribute::Save, true, false); + InsertListTextItem(pSaveItems, wsNewValue, nIndex); + } else if (listitems.size() > 1) { + for (int32_t i = 0; i < 2; i++) { + CXFA_Node* pNode = listitems[i]; + bool bHasSave = pNode->JSObject()->GetBoolean(XFA_Attribute::Save); + if (bHasSave) + InsertListTextItem(pNode, wsNewValue, nIndex); + else + InsertListTextItem(pNode, wsLabel, nIndex); + } + } else { + CXFA_Node* pNode = listitems[0]; + pNode->JSObject()->SetBoolean(XFA_Attribute::Save, false, false); + pNode->JSObject()->SetEnum(XFA_Attribute::Presence, + XFA_AttributeEnum::Visible, false); + CXFA_Node* pSaveItems = m_pNode->CreateSamePacketNode(XFA_Element::Items); + m_pNode->InsertChild(-1, pSaveItems); + pSaveItems->JSObject()->SetBoolean(XFA_Attribute::Save, true, false); + pSaveItems->JSObject()->SetEnum(XFA_Attribute::Presence, + XFA_AttributeEnum::Hidden, false); + CXFA_Node* pListNode = pNode->GetFirstChild(); + int32_t i = 0; + while (pListNode) { + InsertListTextItem(pSaveItems, pListNode->JSObject()->GetContent(false), + i); + ++i; + + pListNode = pListNode->GetNextSibling(); + } + InsertListTextItem(pNode, wsLabel, nIndex); + InsertListTextItem(pSaveItems, wsNewValue, nIndex); + } + if (!bNotify) + return; + + m_pNode->GetDocument()->GetNotify()->OnWidgetListItemAdded( + m_pNode, wsLabel.c_str(), wsValue.c_str(), nIndex); +} + +void CXFA_Node::GetItemLabel(const WideStringView& wsValue, + WideString& wsLabel) { + int32_t iCount = 0; + std::vector<CXFA_Node*> listitems; + CXFA_Node* pItems = m_pNode->GetFirstChild(); + for (; pItems; pItems = pItems->GetNextSibling()) { + if (pItems->GetElementType() != XFA_Element::Items) + continue; + iCount++; + listitems.push_back(pItems); + } + + if (iCount <= 1) { + wsLabel = wsValue; + return; + } + + CXFA_Node* pLabelItems = listitems[0]; + bool bSave = pLabelItems->JSObject()->GetBoolean(XFA_Attribute::Save); + CXFA_Node* pSaveItems = nullptr; + if (bSave) { + pSaveItems = pLabelItems; + pLabelItems = listitems[1]; + } else { + pSaveItems = listitems[1]; + } + iCount = 0; + + int32_t iSearch = -1; + for (CXFA_Node* pChildItem = pSaveItems->GetFirstChild(); pChildItem; + pChildItem = pChildItem->GetNextSibling()) { + if (pChildItem->JSObject()->GetContent(false) == wsValue) { + iSearch = iCount; + break; + } + iCount++; + } + if (iSearch < 0) + return; + + CXFA_Node* pText = + pLabelItems->GetChild<CXFA_Node>(iSearch, XFA_Element::Unknown, false); + if (pText) + wsLabel = pText->JSObject()->GetContent(false); +} + +WideString CXFA_Node::GetItemValue(const WideStringView& wsLabel) { + int32_t iCount = 0; + std::vector<CXFA_Node*> listitems; + for (CXFA_Node* pItems = m_pNode->GetFirstChild(); pItems; + pItems = pItems->GetNextSibling()) { + if (pItems->GetElementType() != XFA_Element::Items) + continue; + iCount++; + listitems.push_back(pItems); + } + if (iCount <= 1) + return WideString(wsLabel); + + CXFA_Node* pLabelItems = listitems[0]; + bool bSave = pLabelItems->JSObject()->GetBoolean(XFA_Attribute::Save); + CXFA_Node* pSaveItems = nullptr; + if (bSave) { + pSaveItems = pLabelItems; + pLabelItems = listitems[1]; + } else { + pSaveItems = listitems[1]; + } + iCount = 0; + + int32_t iSearch = -1; + WideString wsContent; + CXFA_Node* pChildItem = pLabelItems->GetFirstChild(); + for (; pChildItem; pChildItem = pChildItem->GetNextSibling()) { + if (pChildItem->JSObject()->GetContent(false) == wsLabel) { + iSearch = iCount; + break; + } + iCount++; + } + if (iSearch < 0) + return L""; + + CXFA_Node* pText = + pSaveItems->GetChild<CXFA_Node>(iSearch, XFA_Element::Unknown, false); + return pText ? pText->JSObject()->GetContent(false) : L""; +} + +bool CXFA_Node::DeleteItem(int32_t nIndex, bool bNotify, bool bScriptModify) { + bool bSetValue = false; + CXFA_Node* pItems = m_pNode->GetFirstChild(); + for (; pItems; pItems = pItems->GetNextSibling()) { + if (pItems->GetElementType() != XFA_Element::Items) + continue; + + if (nIndex < 0) { + while (CXFA_Node* pNode = pItems->GetFirstChild()) { + pItems->RemoveChild(pNode, true); + } + } else { + if (!bSetValue && pItems->JSObject()->GetBoolean(XFA_Attribute::Save)) { + SetItemState(nIndex, false, true, bScriptModify, true); + bSetValue = true; + } + int32_t i = 0; + CXFA_Node* pNode = pItems->GetFirstChild(); + while (pNode) { + if (i == nIndex) { + pItems->RemoveChild(pNode, true); + break; + } + i++; + pNode = pNode->GetNextSibling(); + } + } + } + if (bNotify) + m_pNode->GetDocument()->GetNotify()->OnWidgetListItemRemoved(m_pNode, + nIndex); + return true; +} + +bool CXFA_Node::IsHorizontalScrollPolicyOff() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + if (pUIChild) { + return pUIChild->JSObject()->GetEnum(XFA_Attribute::HScrollPolicy) == + XFA_AttributeEnum::Off; + } + return false; +} + +bool CXFA_Node::IsVerticalScrollPolicyOff() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + if (pUIChild) { + return pUIChild->JSObject()->GetEnum(XFA_Attribute::VScrollPolicy) == + XFA_AttributeEnum::Off; + } + return false; +} + +Optional<int32_t> CXFA_Node::GetNumberOfCells() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + if (!pUIChild) + return {}; + if (CXFA_Comb* pNode = + pUIChild->GetChild<CXFA_Comb>(0, XFA_Element::Comb, false)) + return {pNode->JSObject()->GetInteger(XFA_Attribute::NumberOfCells)}; + return {}; +} + +WideString CXFA_Node::GetPasswordChar() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + return pUIChild ? pUIChild->JSObject()->GetCData(XFA_Attribute::PasswordChar) + : L"*"; +} + +bool CXFA_Node::IsMultiLine() { + CXFA_Node* pUIChild = m_pNode->GetUIChild(); + return pUIChild && pUIChild->JSObject()->GetBoolean(XFA_Attribute::MultiLine); +} + +std::pair<XFA_Element, int32_t> CXFA_Node::GetMaxChars() { + if (CXFA_Value* pNode = + m_pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false)) { + if (CXFA_Node* pChild = pNode->GetFirstChild()) { + switch (pChild->GetElementType()) { + case XFA_Element::Text: + return {XFA_Element::Text, + pChild->JSObject()->GetInteger(XFA_Attribute::MaxChars)}; + case XFA_Element::ExData: { + int32_t iMax = + pChild->JSObject()->GetInteger(XFA_Attribute::MaxLength); + return {XFA_Element::ExData, iMax < 0 ? 0 : iMax}; + } + default: + break; + } + } + } + return {XFA_Element::Unknown, 0}; +} + +int32_t CXFA_Node::GetFracDigits() { + CXFA_Value* pNode = + m_pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false); + if (!pNode) + return -1; + + CXFA_Decimal* pChild = + pNode->GetChild<CXFA_Decimal>(0, XFA_Element::Decimal, false); + if (!pChild) + return -1; + + return pChild->JSObject() + ->TryInteger(XFA_Attribute::FracDigits, true) + .value_or(-1); +} + +int32_t CXFA_Node::GetLeadDigits() { + CXFA_Value* pNode = + m_pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false); + if (!pNode) + return -1; + + CXFA_Decimal* pChild = + pNode->GetChild<CXFA_Decimal>(0, XFA_Element::Decimal, false); + if (!pChild) + return -1; + + return pChild->JSObject() + ->TryInteger(XFA_Attribute::LeadDigits, true) + .value_or(-1); +} + +bool CXFA_Node::SetValue(XFA_VALUEPICTURE eValueType, + const WideString& wsValue) { + if (wsValue.IsEmpty()) { + m_pNode->SyncValue(wsValue, true); + return true; + } + + m_pNode->SetPreNull(m_pNode->IsNull()); + m_pNode->SetIsNull(false); + + WideString wsNewText(wsValue); + WideString wsPicture = GetPictureContent(eValueType); + bool bValidate = true; + bool bSyncData = false; + CXFA_Node* pNode = m_pNode->GetUIChild(); + if (!pNode) + return true; + + XFA_Element eType = pNode->GetElementType(); + if (!wsPicture.IsEmpty()) { + CXFA_LocaleMgr* pLocalMgr = m_pNode->GetDocument()->GetLocalMgr(); + IFX_Locale* pLocale = m_pNode->GetLocale(); + CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(GetNode()); + bValidate = + widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture); + if (bValidate) { + widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsNewText, + wsPicture, pLocale, pLocalMgr); + wsNewText = widgetValue.GetValue(); + if (eType == XFA_Element::NumericEdit) + wsNewText = NumericLimit(wsNewText, GetLeadDigits(), GetFracDigits()); + + bSyncData = true; + } + } else { + if (eType == XFA_Element::NumericEdit) { + if (wsNewText != L"0") + wsNewText = NumericLimit(wsNewText, GetLeadDigits(), GetFracDigits()); + + bSyncData = true; + } + } + if (eType != XFA_Element::NumericEdit || bSyncData) + m_pNode->SyncValue(wsNewText, true); + + return bValidate; +} + +WideString CXFA_Node::GetPictureContent(XFA_VALUEPICTURE ePicture) { + if (ePicture == XFA_VALUEPICTURE_Raw) + return L""; + + CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(GetNode()); + switch (ePicture) { + case XFA_VALUEPICTURE_Display: { + if (CXFA_Format* pFormat = + m_pNode->GetChild<CXFA_Format>(0, XFA_Element::Format, false)) { + if (CXFA_Picture* pPicture = pFormat->GetChild<CXFA_Picture>( + 0, XFA_Element::Picture, false)) { + Optional<WideString> picture = + pPicture->JSObject()->TryContent(false, true); + if (picture) + return *picture; + } + } + + IFX_Locale* pLocale = m_pNode->GetLocale(); + if (!pLocale) + return L""; + + uint32_t dwType = widgetValue.GetType(); + switch (dwType) { + case XFA_VT_DATE: + return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium); + case XFA_VT_TIME: + return pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium); + case XFA_VT_DATETIME: + return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium) + + L"T" + + pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium); + case XFA_VT_DECIMAL: + case XFA_VT_FLOAT: + default: + return L""; + } + } + case XFA_VALUEPICTURE_Edit: { + CXFA_Ui* pUI = m_pNode->GetChild<CXFA_Ui>(0, XFA_Element::Ui, false); + if (pUI) { + if (CXFA_Picture* pPicture = + pUI->GetChild<CXFA_Picture>(0, XFA_Element::Picture, false)) { + Optional<WideString> picture = + pPicture->JSObject()->TryContent(false, true); + if (picture) + return *picture; + } + } + + IFX_Locale* pLocale = m_pNode->GetLocale(); + if (!pLocale) + return L""; + + uint32_t dwType = widgetValue.GetType(); + switch (dwType) { + case XFA_VT_DATE: + return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short); + case XFA_VT_TIME: + return pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short); + case XFA_VT_DATETIME: + return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short) + + L"T" + + pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short); + default: + return L""; + } + } + case XFA_VALUEPICTURE_DataBind: { + CXFA_Bind* bind = m_pNode->GetBindIfExists(); + if (bind) + return bind->GetPicture(); + break; + } + default: + break; + } + return L""; +} + +WideString CXFA_Node::GetValue(XFA_VALUEPICTURE eValueType) { + WideString wsValue = m_pNode->JSObject()->GetContent(false); + + if (eValueType == XFA_VALUEPICTURE_Display) + GetItemLabel(wsValue.AsStringView(), wsValue); + + WideString wsPicture = GetPictureContent(eValueType); + CXFA_Node* pNode = m_pNode->GetUIChild(); + if (!pNode) + return wsValue; + + switch (m_pNode->GetUIChild()->GetElementType()) { + case XFA_Element::ChoiceList: { + if (eValueType == XFA_VALUEPICTURE_Display) { + int32_t iSelItemIndex = GetSelectedItem(0); + if (iSelItemIndex >= 0) { + wsValue = GetChoiceListItem(iSelItemIndex, false).value_or(L""); + wsPicture.clear(); + } + } + } break; + case XFA_Element::NumericEdit: + if (eValueType != XFA_VALUEPICTURE_Raw && wsPicture.IsEmpty()) { + IFX_Locale* pLocale = m_pNode->GetLocale(); + if (eValueType == XFA_VALUEPICTURE_Display && pLocale) + wsValue = FormatNumStr(NormalizeNumStr(wsValue), pLocale); + } + break; + default: + break; + } + if (wsPicture.IsEmpty()) + return wsValue; + + if (IFX_Locale* pLocale = m_pNode->GetLocale()) { + CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(GetNode()); + CXFA_LocaleMgr* pLocalMgr = m_pNode->GetDocument()->GetLocalMgr(); + switch (widgetValue.GetType()) { + case XFA_VT_DATE: { + WideString wsDate, wsTime; + if (SplitDateTime(wsValue, wsDate, wsTime)) { + CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocalMgr); + if (date.FormatPatterns(wsValue, wsPicture, pLocale, eValueType)) + return wsValue; + } + break; + } + case XFA_VT_TIME: { + WideString wsDate, wsTime; + if (SplitDateTime(wsValue, wsDate, wsTime)) { + CXFA_LocaleValue time(XFA_VT_TIME, wsTime, pLocalMgr); + if (time.FormatPatterns(wsValue, wsPicture, pLocale, eValueType)) + return wsValue; + } + break; + } + default: + break; + } + widgetValue.FormatPatterns(wsValue, wsPicture, pLocale, eValueType); + } + return wsValue; +} + +WideString CXFA_Node::GetNormalizeDataValue(const WideString& wsValue) { + if (wsValue.IsEmpty()) + return L""; + + WideString wsPicture = GetPictureContent(XFA_VALUEPICTURE_DataBind); + if (wsPicture.IsEmpty()) + return wsValue; + + ASSERT(GetNode()); + CXFA_LocaleMgr* pLocalMgr = GetNode()->GetDocument()->GetLocalMgr(); + IFX_Locale* pLocale = m_pNode->GetLocale(); + CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(GetNode()); + if (widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture)) { + widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsValue, wsPicture, + pLocale, pLocalMgr); + return widgetValue.GetValue(); + } + return wsValue; +} + +WideString CXFA_Node::GetFormatDataValue(const WideString& wsValue) { + if (wsValue.IsEmpty()) + return L""; + + WideString wsPicture = GetPictureContent(XFA_VALUEPICTURE_DataBind); + if (wsPicture.IsEmpty()) + return wsValue; + + WideString wsFormattedValue = wsValue; + if (IFX_Locale* pLocale = m_pNode->GetLocale()) { + ASSERT(GetNode()); + CXFA_Value* pNodeValue = + GetNode()->GetChild<CXFA_Value>(0, XFA_Element::Value, false); + if (!pNodeValue) + return wsValue; + + CXFA_Node* pValueChild = pNodeValue->GetFirstChild(); + if (!pValueChild) + return wsValue; + + int32_t iVTType = XFA_VT_NULL; + switch (pValueChild->GetElementType()) { + case XFA_Element::Decimal: + iVTType = XFA_VT_DECIMAL; + break; + case XFA_Element::Float: + iVTType = XFA_VT_FLOAT; + break; + case XFA_Element::Date: + iVTType = XFA_VT_DATE; + break; + case XFA_Element::Time: + iVTType = XFA_VT_TIME; + break; + case XFA_Element::DateTime: + iVTType = XFA_VT_DATETIME; + break; + case XFA_Element::Boolean: + iVTType = XFA_VT_BOOLEAN; + break; + case XFA_Element::Integer: + iVTType = XFA_VT_INTEGER; + break; + case XFA_Element::Text: + iVTType = XFA_VT_TEXT; + break; + default: + iVTType = XFA_VT_NULL; + break; + } + CXFA_LocaleMgr* pLocalMgr = GetNode()->GetDocument()->GetLocalMgr(); + CXFA_LocaleValue widgetValue(iVTType, wsValue, pLocalMgr); + switch (widgetValue.GetType()) { + case XFA_VT_DATE: { + WideString wsDate, wsTime; + if (SplitDateTime(wsValue, wsDate, wsTime)) { + CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocalMgr); + if (date.FormatPatterns(wsFormattedValue, wsPicture, pLocale, + XFA_VALUEPICTURE_DataBind)) { + return wsFormattedValue; + } + } + break; + } + case XFA_VT_TIME: { + WideString wsDate, wsTime; + if (SplitDateTime(wsValue, wsDate, wsTime)) { + CXFA_LocaleValue time(XFA_VT_TIME, wsTime, pLocalMgr); + if (time.FormatPatterns(wsFormattedValue, wsPicture, pLocale, + XFA_VALUEPICTURE_DataBind)) { + return wsFormattedValue; + } + } + break; + } + default: + break; + } + widgetValue.FormatPatterns(wsFormattedValue, wsPicture, pLocale, + XFA_VALUEPICTURE_DataBind); + } + return wsFormattedValue; +} + +WideString CXFA_Node::NormalizeNumStr(const WideString& wsValue) { + if (wsValue.IsEmpty()) + return L""; + + WideString wsOutput = wsValue; + wsOutput.TrimLeft('0'); + + if (!wsOutput.IsEmpty() && wsOutput.Contains('.') && GetFracDigits() != -1) { + wsOutput.TrimRight(L"0"); + wsOutput.TrimRight(L"."); + } + if (wsOutput.IsEmpty() || wsOutput[0] == '.') + wsOutput.InsertAtFront('0'); + + return wsOutput; +} + +WideString CXFA_Node::FormatNumStr(const WideString& wsValue, + IFX_Locale* pLocale) { + if (wsValue.IsEmpty()) + return L""; + + WideString wsSrcNum = wsValue; + WideString wsGroupSymbol = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping); + bool bNeg = false; + if (wsSrcNum[0] == '-') { + bNeg = true; + wsSrcNum.Delete(0, 1); + } + + auto dot_index = wsSrcNum.Find('.'); + dot_index = !dot_index.has_value() ? wsSrcNum.GetLength() : dot_index; + + if (dot_index.value() < 1) + return L""; + + size_t nPos = dot_index.value() % 3; + WideString wsOutput; + for (size_t i = 0; i < dot_index.value(); i++) { + if (i % 3 == nPos && i != 0) + wsOutput += wsGroupSymbol; + + wsOutput += wsSrcNum[i]; + } + if (dot_index.value() < wsSrcNum.GetLength()) { + wsOutput += pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal); + wsOutput += wsSrcNum.Right(wsSrcNum.GetLength() - dot_index.value() - 1); + } + if (bNeg) + return pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus) + wsOutput; + + return wsOutput; +} + +void CXFA_Node::InsertListTextItem(CXFA_Node* pItems, + const WideString& wsText, + int32_t nIndex) { + CXFA_Node* pText = pItems->CreateSamePacketNode(XFA_Element::Text); + pItems->InsertChild(nIndex, pText); + pText->JSObject()->SetContent(wsText, wsText, false, false, false); +} + +WideString CXFA_Node::NumericLimit(const WideString& wsValue, + int32_t iLead, + int32_t iTread) const { + if ((iLead == -1) && (iTread == -1)) + return wsValue; + + WideString wsRet; + int32_t iLead_ = 0, iTread_ = -1; + int32_t iCount = wsValue.GetLength(); + if (iCount == 0) + return wsValue; + + int32_t i = 0; + if (wsValue[i] == L'-') { + wsRet += L'-'; + i++; + } + for (; i < iCount; i++) { + wchar_t wc = wsValue[i]; + if (FXSYS_isDecimalDigit(wc)) { + if (iLead >= 0) { + iLead_++; + if (iLead_ > iLead) + return L"0"; + } else if (iTread_ >= 0) { + iTread_++; + if (iTread_ > iTread) { + if (iTread != -1) { + CFX_Decimal wsDeci = CFX_Decimal(wsValue.AsStringView()); + wsDeci.SetScale(iTread); + wsRet = wsDeci; + } + return wsRet; + } + } + } else if (wc == L'.') { + iTread_ = 0; + iLead = -1; + } + wsRet += wc; + } + return wsRet; +} diff --git a/xfa/fxfa/parser/cxfa_node.h b/xfa/fxfa/parser/cxfa_node.h index 0991a533c8..6b6e865353 100644 --- a/xfa/fxfa/parser/cxfa_node.h +++ b/xfa/fxfa/parser/cxfa_node.h @@ -18,6 +18,8 @@ #include "third_party/base/optional.h" #include "xfa/fxfa/parser/cxfa_object.h" +class CFGAS_GEFont; +class CFX_DIBitmap; class CFX_XMLNode; class CXFA_Bind; class CXFA_Border; @@ -25,21 +27,37 @@ class CXFA_Calculate; class CXFA_Caption; class CXFA_Event; class CXFA_EventParam; +class CXFA_FFDoc; class CXFA_FFDocView; +class CXFA_FFWidget; class CXFA_Font; class CXFA_Margin; class CXFA_Occur; class CXFA_Para; class CXFA_Script; +class CXFA_TextLayout; class CXFA_Validate; class CXFA_Value; -class CXFA_WidgetAcc; +class CXFA_WidgetLayoutData; class IFX_Locale; #define XFA_NODEFILTER_Children 0x01 #define XFA_NODEFILTER_Properties 0x02 #define XFA_NODEFILTER_OneOfProperty 0x04 +enum XFA_CHECKSTATE { + XFA_CHECKSTATE_On = 0, + XFA_CHECKSTATE_Off = 1, + XFA_CHECKSTATE_Neutral = 2, +}; + +enum XFA_VALUEPICTURE { + XFA_VALUEPICTURE_Raw = 0, + XFA_VALUEPICTURE_Display, + XFA_VALUEPICTURE_Edit, + XFA_VALUEPICTURE_DataBind, +}; + enum XFA_NodeFlag { XFA_NodeFlag_None = 0, XFA_NodeFlag_Initialized = 1 << 0, @@ -304,17 +322,130 @@ class CXFA_Node : public CXFA_Object { bool IsNull() const { return m_bIsNull; } void SetIsNull(bool val) { m_bIsNull = val; } - void SetWidgetReady(); + void SetWidgetReady() { is_widget_ready_ = true; } bool IsWidgetReady() const { return is_widget_ready_; } - CXFA_WidgetAcc* GetWidgetAcc() { + // TODO(dsinclair): Remove post WidgetAcc merge. + CXFA_Node* GetWidgetAcc() { ASSERT(IsWidgetReady()); - ASSERT(acc_.get() != nullptr); - return acc_.get(); + return this; } std::vector<CXFA_Event*> GetEventByActivity(XFA_AttributeEnum iActivity, bool bIsFormReady); + void ResetData(); + + CXFA_FFWidget* GetNextWidget(CXFA_FFWidget* pWidget); + void StartWidgetLayout(CXFA_FFDoc* doc, + float& fCalcWidth, + float& fCalcHeight); + bool FindSplitPos(CXFA_FFDocView* docView, + int32_t iBlockIndex, + float& fCalcHeight); + + bool LoadCaption(CXFA_FFDoc* doc); + CXFA_TextLayout* GetCaptionTextLayout(); + + void LoadText(CXFA_FFDoc* doc); + CXFA_TextLayout* GetTextLayout(); + + bool LoadImageImage(CXFA_FFDoc* doc); + bool LoadImageEditImage(CXFA_FFDoc* doc); + void GetImageDpi(int32_t& iImageXDpi, int32_t& iImageYDpi); + void GetImageEditDpi(int32_t& iImageXDpi, int32_t& iImageYDpi); + + RetainPtr<CFX_DIBitmap> GetImageImage(); + RetainPtr<CFX_DIBitmap> GetImageEditImage(); + void SetImageEdit(const WideString& wsContentType, + const WideString& wsHref, + const WideString& wsData); + void SetImageImage(const RetainPtr<CFX_DIBitmap>& newImage); + void SetImageEditImage(const RetainPtr<CFX_DIBitmap>& newImage); + void UpdateUIDisplay(CXFA_FFDocView* docView, CXFA_FFWidget* pExcept); + + RetainPtr<CFGAS_GEFont> GetFDEFont(CXFA_FFDoc* doc); + + // TODO(dsinclair): Remove post WidgetAcc merge. + CXFA_Node* GetNode() { return this; } + + bool IsOpenAccess() const; + bool IsListBox(); + bool IsAllowNeutral(); + bool IsRadioButton(); + bool IsChoiceListAllowTextEntry(); + bool IsMultiLine(); + + XFA_AttributeEnum GetButtonHighlight(); + bool HasButtonRollover() const; + bool HasButtonDown() const; + + bool IsCheckButtonRound(); + XFA_AttributeEnum GetCheckButtonMark(); + float GetCheckButtonSize(); + + XFA_CHECKSTATE GetCheckState(); + void SetCheckState(XFA_CHECKSTATE eCheckState, bool bNotify); + + CXFA_Node* GetSelectedMember(); + CXFA_Node* SetSelectedMember(const WideStringView& wsName, bool bNotify); + void SetSelectedMemberByValue(const WideStringView& wsValue, + bool bNotify, + bool bScriptModify, + bool bSyncData); + + CXFA_Node* GetExclGroupFirstMember(); + CXFA_Node* GetExclGroupNextMember(CXFA_Node* pNode); + + int32_t CountChoiceListItems(bool bSaveValue); + Optional<WideString> GetChoiceListItem(int32_t nIndex, bool bSaveValue); + bool IsChoiceListMultiSelect(); + bool IsChoiceListCommitOnSelect(); + std::vector<WideString> GetChoiceListItems(bool bSaveValue); + + int32_t CountSelectedItems(); + int32_t GetSelectedItem(int32_t nIndex); + std::vector<int32_t> GetSelectedItems(); + std::vector<WideString> GetSelectedItemsValue(); + void SetSelectedItems(const std::vector<int32_t>& iSelArray, + bool bNotify, + bool bScriptModify, + bool bSyncData); + void InsertItem(const WideString& wsLabel, + const WideString& wsValue, + bool bNotify); + bool DeleteItem(int32_t nIndex, bool bNotify, bool bScriptModify); + void ClearAllSelections(); + + bool GetItemState(int32_t nIndex); + void SetItemState(int32_t nIndex, + bool bSelected, + bool bNotify, + bool bScriptModify, + bool bSyncData); + + WideString GetItemValue(const WideStringView& wsLabel); + + bool IsHorizontalScrollPolicyOff(); + bool IsVerticalScrollPolicyOff(); + Optional<int32_t> GetNumberOfCells(); + + bool SetValue(XFA_VALUEPICTURE eValueType, const WideString& wsValue); + WideString GetValue(XFA_VALUEPICTURE eValueType); + + WideString GetPictureContent(XFA_VALUEPICTURE ePicture); + WideString GetNormalizeDataValue(const WideString& wsValue); + WideString GetFormatDataValue(const WideString& wsValue); + WideString NormalizeNumStr(const WideString& wsValue); + + WideString GetPasswordChar(); + std::pair<XFA_Element, int32_t> GetMaxChars(); + int32_t GetFracDigits(); + int32_t GetLeadDigits(); + + WideString NumericLimit(const WideString& wsValue, + int32_t iLead, + int32_t iTread) const; + protected: CXFA_Node(CXFA_Document* pDoc, XFA_PacketType ePacket, @@ -363,6 +494,35 @@ class CXFA_Node : public CXFA_Object { CXFA_Node* GetNextSameNameSiblingInternal( const WideStringView& wsNodeName) const; CXFA_Node* GetNextSameClassSiblingInternal(XFA_Element eType) const; + void CalcCaptionSize(CXFA_FFDoc* doc, CFX_SizeF& szCap); + bool CalculateFieldAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); + bool CalculateWidgetAutoSize(CFX_SizeF& size); + bool CalculateTextEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); + bool CalculateCheckButtonAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); + bool CalculatePushButtonAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); + CFX_SizeF CalculateImageSize(float img_width, + float img_height, + float dpi_x, + float dpi_y); + bool CalculateImageEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); + bool CalculateImageAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); + float CalculateWidgetAutoHeight(float fHeightCalc); + float CalculateWidgetAutoWidth(float fWidthCalc); + float GetWidthWithoutMargin(float fWidthCalc); + float GetHeightWithoutMargin(float fHeightCalc); + void CalculateTextContentSize(CXFA_FFDoc* doc, CFX_SizeF& size); + void CalculateAccWidthAndHeight(CXFA_FFDoc* doc, + XFA_Element eUIType, + float& fWidth, + float& fCalcHeight); + void InitLayoutData(); + void StartTextLayout(CXFA_FFDoc* doc, float& fCalcWidth, float& fCalcHeight); + + void InsertListTextItem(CXFA_Node* pItems, + const WideString& wsText, + int32_t nIndex); + WideString FormatNumStr(const WideString& wsValue, IFX_Locale* pLocale); + void GetItemLabel(const WideStringView& wsValue, WideString& wsLabel); const PropertyData* const m_Properties; const AttributeData* const m_Attributes; @@ -383,7 +543,9 @@ class CXFA_Node : public CXFA_Object { bool m_bIsNull = true; bool m_bPreNull = true; bool is_widget_ready_ = false; - std::unique_ptr<CXFA_WidgetAcc> acc_; + std::unique_ptr<CXFA_WidgetLayoutData> m_pLayoutData; + // TODO(dsinclair): Remove post WidgetAcc merge. + CXFA_Node* m_pNode; }; #endif // XFA_FXFA_PARSER_CXFA_NODE_H_ diff --git a/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp b/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp index d843fa8896..8b0fa40250 100644 --- a/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp +++ b/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp @@ -16,7 +16,6 @@ #include "fxjs/xfa/cjx_object.h" #include "third_party/base/logging.h" #include "third_party/base/stl_util.h" -#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_bind.h" #include "xfa/fxfa/parser/cxfa_datagroup.h" #include "xfa/fxfa/parser/cxfa_document.h" |