blob: 41be55bb53b619762a44f9a1e42e5ad174232320 [file] [log] [blame] [edit]
// 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);
}