| // Copyright 2014 The PDFium Authors |
| // 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_textprovider.h" |
| |
| #include "core/fxcrt/check.h" |
| #include "core/fxcrt/xml/cfx_xmlelement.h" |
| #include "core/fxcrt/xml/cfx_xmlnode.h" |
| #include "fxjs/xfa/cfxjse_engine.h" |
| #include "fxjs/xfa/cfxjse_value.h" |
| #include "fxjs/xfa/cjx_object.h" |
| #include "xfa/fde/cfde_textout.h" |
| #include "xfa/fxfa/cxfa_eventparam.h" |
| #include "xfa/fxfa/cxfa_ffapp.h" |
| #include "xfa/fxfa/cxfa_ffcheckbutton.h" |
| #include "xfa/fxfa/cxfa_ffdoc.h" |
| #include "xfa/fxfa/cxfa_ffdocview.h" |
| #include "xfa/fxfa/cxfa_fffield.h" |
| #include "xfa/fxfa/cxfa_ffpageview.h" |
| #include "xfa/fxfa/cxfa_ffwidget.h" |
| #include "xfa/fxfa/cxfa_fontmgr.h" |
| #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" |
| #include "xfa/fxfa/parser/cxfa_caption.h" |
| #include "xfa/fxfa/parser/cxfa_font.h" |
| #include "xfa/fxfa/parser/cxfa_items.h" |
| #include "xfa/fxfa/parser/cxfa_localevalue.h" |
| #include "xfa/fxfa/parser/cxfa_node.h" |
| #include "xfa/fxfa/parser/cxfa_para.h" |
| #include "xfa/fxfa/parser/cxfa_value.h" |
| #include "xfa/fxfa/parser/xfa_utils.h" |
| |
| CXFA_TextProvider::CXFA_TextProvider(CXFA_Node* pNode, Type eType) |
| : m_pNode(pNode), m_eType(eType) { |
| DCHECK(m_pNode); |
| } |
| |
| CXFA_TextProvider::~CXFA_TextProvider() = default; |
| |
| void CXFA_TextProvider::Trace(cppgc::Visitor* visitor) const { |
| visitor->Trace(m_pNode); |
| } |
| |
| CXFA_Node* CXFA_TextProvider::GetTextNode(bool* bRichText) { |
| *bRichText = false; |
| if (m_eType == Type::kText) { |
| CXFA_Value* pValueNode = |
| m_pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false); |
| if (!pValueNode) |
| return nullptr; |
| |
| CXFA_Node* pChildNode = pValueNode->GetFirstChild(); |
| if (pChildNode && pChildNode->GetElementType() == XFA_Element::ExData) { |
| std::optional<WideString> contentType = |
| pChildNode->JSObject()->TryAttribute(XFA_Attribute::ContentType, |
| false); |
| if (contentType.has_value() && |
| contentType.value().EqualsASCII("text/html")) { |
| *bRichText = true; |
| } |
| } |
| return pChildNode; |
| } |
| |
| if (m_eType == Type::kCaption) { |
| CXFA_Caption* pCaptionNode = |
| m_pNode->GetChild<CXFA_Caption>(0, XFA_Element::Caption, false); |
| if (!pCaptionNode) |
| return nullptr; |
| |
| CXFA_Value* pValueNode = |
| pCaptionNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false); |
| if (!pValueNode) |
| return nullptr; |
| |
| CXFA_Node* pChildNode = pValueNode->GetFirstChild(); |
| if (pChildNode && pChildNode->GetElementType() == XFA_Element::ExData) { |
| std::optional<WideString> contentType = |
| pChildNode->JSObject()->TryAttribute(XFA_Attribute::ContentType, |
| false); |
| if (contentType.has_value() && |
| contentType.value().EqualsASCII("text/html")) { |
| *bRichText = true; |
| } |
| } |
| return pChildNode; |
| } |
| |
| CXFA_Items* pItemNode = |
| m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); |
| if (!pItemNode) |
| return nullptr; |
| |
| CXFA_Node* pNode = pItemNode->GetFirstChild(); |
| while (pNode) { |
| WideString wsName = pNode->JSObject()->GetCData(XFA_Attribute::Name); |
| if (m_eType == Type::kRollover && wsName.EqualsASCII("rollover")) { |
| return pNode; |
| } |
| if (m_eType == Type::kDown && wsName.EqualsASCII("down")) |
| return pNode; |
| |
| pNode = pNode->GetNextSibling(); |
| } |
| return nullptr; |
| } |
| |
| CXFA_Para* CXFA_TextProvider::GetParaIfExists() { |
| if (m_eType == Type::kText) |
| return m_pNode->GetParaIfExists(); |
| |
| CXFA_Caption* pNode = |
| m_pNode->GetChild<CXFA_Caption>(0, XFA_Element::Caption, false); |
| return pNode->GetChild<CXFA_Para>(0, XFA_Element::Para, false); |
| } |
| |
| CXFA_Font* CXFA_TextProvider::GetFontIfExists() { |
| if (m_eType == Type::kText) |
| return m_pNode->GetFontIfExists(); |
| |
| CXFA_Caption* pNode = |
| m_pNode->GetChild<CXFA_Caption>(0, XFA_Element::Caption, false); |
| CXFA_Font* font = pNode->GetChild<CXFA_Font>(0, XFA_Element::Font, false); |
| return font ? font : m_pNode->GetFontIfExists(); |
| } |
| |
| bool CXFA_TextProvider::IsCheckButtonAndAutoWidth() const { |
| if (m_pNode->GetFFWidgetType() != XFA_FFWidgetType::kCheckButton) |
| return false; |
| return !m_pNode->TryWidth().has_value(); |
| } |
| |
| std::optional<WideString> CXFA_TextProvider::GetEmbeddedObj( |
| const WideString& wsAttr) const { |
| if (m_eType != Type::kText) |
| return std::nullopt; |
| |
| CXFA_Node* pParent = m_pNode->GetParent(); |
| CXFA_Document* pDocument = m_pNode->GetDocument(); |
| CXFA_Node* pIDNode = nullptr; |
| if (pParent) |
| pIDNode = pDocument->GetNodeByID(pParent, wsAttr.AsStringView()); |
| |
| if (!pIDNode) { |
| pIDNode = pDocument->GetNodeByID( |
| ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Form)), |
| wsAttr.AsStringView()); |
| } |
| if (!pIDNode || !pIDNode->IsWidgetReady()) |
| return std::nullopt; |
| |
| return pIDNode->GetValue(XFA_ValuePicture::kDisplay); |
| } |