xref: /aosp_15_r20/external/pdfium/xfa/fxfa/cxfa_textprovider.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2014 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker 
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker 
7*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_textprovider.h"
8*3ac0a46fSAndroid Build Coastguard Worker 
9*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/xml/cfx_xmlelement.h"
10*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/xml/cfx_xmlnode.h"
11*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_engine.h"
12*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_value.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cjx_object.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/check.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fde/cfde_textout.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_eventparam.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffapp.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffcheckbutton.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffdoc.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffdocview.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_fffield.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffpageview.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffwidget.h"
24*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_fontmgr.h"
25*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
26*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_caption.h"
27*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_font.h"
28*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_items.h"
29*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_localevalue.h"
30*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_node.h"
31*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_para.h"
32*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_value.h"
33*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/xfa_utils.h"
34*3ac0a46fSAndroid Build Coastguard Worker 
CXFA_TextProvider(CXFA_Node * pNode,Type eType)35*3ac0a46fSAndroid Build Coastguard Worker CXFA_TextProvider::CXFA_TextProvider(CXFA_Node* pNode, Type eType)
36*3ac0a46fSAndroid Build Coastguard Worker     : m_pNode(pNode), m_eType(eType) {
37*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(m_pNode);
38*3ac0a46fSAndroid Build Coastguard Worker }
39*3ac0a46fSAndroid Build Coastguard Worker 
40*3ac0a46fSAndroid Build Coastguard Worker CXFA_TextProvider::~CXFA_TextProvider() = default;
41*3ac0a46fSAndroid Build Coastguard Worker 
Trace(cppgc::Visitor * visitor) const42*3ac0a46fSAndroid Build Coastguard Worker void CXFA_TextProvider::Trace(cppgc::Visitor* visitor) const {
43*3ac0a46fSAndroid Build Coastguard Worker   visitor->Trace(m_pNode);
44*3ac0a46fSAndroid Build Coastguard Worker }
45*3ac0a46fSAndroid Build Coastguard Worker 
GetTextNode(bool * bRichText)46*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CXFA_TextProvider::GetTextNode(bool* bRichText) {
47*3ac0a46fSAndroid Build Coastguard Worker   *bRichText = false;
48*3ac0a46fSAndroid Build Coastguard Worker   if (m_eType == Type::kText) {
49*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Value* pValueNode =
50*3ac0a46fSAndroid Build Coastguard Worker         m_pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false);
51*3ac0a46fSAndroid Build Coastguard Worker     if (!pValueNode)
52*3ac0a46fSAndroid Build Coastguard Worker       return nullptr;
53*3ac0a46fSAndroid Build Coastguard Worker 
54*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Node* pChildNode = pValueNode->GetFirstChild();
55*3ac0a46fSAndroid Build Coastguard Worker     if (pChildNode && pChildNode->GetElementType() == XFA_Element::ExData) {
56*3ac0a46fSAndroid Build Coastguard Worker       absl::optional<WideString> contentType =
57*3ac0a46fSAndroid Build Coastguard Worker           pChildNode->JSObject()->TryAttribute(XFA_Attribute::ContentType,
58*3ac0a46fSAndroid Build Coastguard Worker                                                false);
59*3ac0a46fSAndroid Build Coastguard Worker       if (contentType.has_value() &&
60*3ac0a46fSAndroid Build Coastguard Worker           contentType.value().EqualsASCII("text/html")) {
61*3ac0a46fSAndroid Build Coastguard Worker         *bRichText = true;
62*3ac0a46fSAndroid Build Coastguard Worker       }
63*3ac0a46fSAndroid Build Coastguard Worker     }
64*3ac0a46fSAndroid Build Coastguard Worker     return pChildNode;
65*3ac0a46fSAndroid Build Coastguard Worker   }
66*3ac0a46fSAndroid Build Coastguard Worker 
67*3ac0a46fSAndroid Build Coastguard Worker   if (m_eType == Type::kCaption) {
68*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Caption* pCaptionNode =
69*3ac0a46fSAndroid Build Coastguard Worker         m_pNode->GetChild<CXFA_Caption>(0, XFA_Element::Caption, false);
70*3ac0a46fSAndroid Build Coastguard Worker     if (!pCaptionNode)
71*3ac0a46fSAndroid Build Coastguard Worker       return nullptr;
72*3ac0a46fSAndroid Build Coastguard Worker 
73*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Value* pValueNode =
74*3ac0a46fSAndroid Build Coastguard Worker         pCaptionNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false);
75*3ac0a46fSAndroid Build Coastguard Worker     if (!pValueNode)
76*3ac0a46fSAndroid Build Coastguard Worker       return nullptr;
77*3ac0a46fSAndroid Build Coastguard Worker 
78*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Node* pChildNode = pValueNode->GetFirstChild();
79*3ac0a46fSAndroid Build Coastguard Worker     if (pChildNode && pChildNode->GetElementType() == XFA_Element::ExData) {
80*3ac0a46fSAndroid Build Coastguard Worker       absl::optional<WideString> contentType =
81*3ac0a46fSAndroid Build Coastguard Worker           pChildNode->JSObject()->TryAttribute(XFA_Attribute::ContentType,
82*3ac0a46fSAndroid Build Coastguard Worker                                                false);
83*3ac0a46fSAndroid Build Coastguard Worker       if (contentType.has_value() &&
84*3ac0a46fSAndroid Build Coastguard Worker           contentType.value().EqualsASCII("text/html")) {
85*3ac0a46fSAndroid Build Coastguard Worker         *bRichText = true;
86*3ac0a46fSAndroid Build Coastguard Worker       }
87*3ac0a46fSAndroid Build Coastguard Worker     }
88*3ac0a46fSAndroid Build Coastguard Worker     return pChildNode;
89*3ac0a46fSAndroid Build Coastguard Worker   }
90*3ac0a46fSAndroid Build Coastguard Worker 
91*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Items* pItemNode =
92*3ac0a46fSAndroid Build Coastguard Worker       m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
93*3ac0a46fSAndroid Build Coastguard Worker   if (!pItemNode)
94*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
95*3ac0a46fSAndroid Build Coastguard Worker 
96*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pNode = pItemNode->GetFirstChild();
97*3ac0a46fSAndroid Build Coastguard Worker   while (pNode) {
98*3ac0a46fSAndroid Build Coastguard Worker     WideString wsName = pNode->JSObject()->GetCData(XFA_Attribute::Name);
99*3ac0a46fSAndroid Build Coastguard Worker     if (m_eType == Type::kRollover && wsName.EqualsASCII("rollover")) {
100*3ac0a46fSAndroid Build Coastguard Worker       return pNode;
101*3ac0a46fSAndroid Build Coastguard Worker     }
102*3ac0a46fSAndroid Build Coastguard Worker     if (m_eType == Type::kDown && wsName.EqualsASCII("down"))
103*3ac0a46fSAndroid Build Coastguard Worker       return pNode;
104*3ac0a46fSAndroid Build Coastguard Worker 
105*3ac0a46fSAndroid Build Coastguard Worker     pNode = pNode->GetNextSibling();
106*3ac0a46fSAndroid Build Coastguard Worker   }
107*3ac0a46fSAndroid Build Coastguard Worker   return nullptr;
108*3ac0a46fSAndroid Build Coastguard Worker }
109*3ac0a46fSAndroid Build Coastguard Worker 
GetParaIfExists()110*3ac0a46fSAndroid Build Coastguard Worker CXFA_Para* CXFA_TextProvider::GetParaIfExists() {
111*3ac0a46fSAndroid Build Coastguard Worker   if (m_eType == Type::kText)
112*3ac0a46fSAndroid Build Coastguard Worker     return m_pNode->GetParaIfExists();
113*3ac0a46fSAndroid Build Coastguard Worker 
114*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Caption* pNode =
115*3ac0a46fSAndroid Build Coastguard Worker       m_pNode->GetChild<CXFA_Caption>(0, XFA_Element::Caption, false);
116*3ac0a46fSAndroid Build Coastguard Worker   return pNode->GetChild<CXFA_Para>(0, XFA_Element::Para, false);
117*3ac0a46fSAndroid Build Coastguard Worker }
118*3ac0a46fSAndroid Build Coastguard Worker 
GetFontIfExists()119*3ac0a46fSAndroid Build Coastguard Worker CXFA_Font* CXFA_TextProvider::GetFontIfExists() {
120*3ac0a46fSAndroid Build Coastguard Worker   if (m_eType == Type::kText)
121*3ac0a46fSAndroid Build Coastguard Worker     return m_pNode->GetFontIfExists();
122*3ac0a46fSAndroid Build Coastguard Worker 
123*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Caption* pNode =
124*3ac0a46fSAndroid Build Coastguard Worker       m_pNode->GetChild<CXFA_Caption>(0, XFA_Element::Caption, false);
125*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Font* font = pNode->GetChild<CXFA_Font>(0, XFA_Element::Font, false);
126*3ac0a46fSAndroid Build Coastguard Worker   return font ? font : m_pNode->GetFontIfExists();
127*3ac0a46fSAndroid Build Coastguard Worker }
128*3ac0a46fSAndroid Build Coastguard Worker 
IsCheckButtonAndAutoWidth() const129*3ac0a46fSAndroid Build Coastguard Worker bool CXFA_TextProvider::IsCheckButtonAndAutoWidth() const {
130*3ac0a46fSAndroid Build Coastguard Worker   if (m_pNode->GetFFWidgetType() != XFA_FFWidgetType::kCheckButton)
131*3ac0a46fSAndroid Build Coastguard Worker     return false;
132*3ac0a46fSAndroid Build Coastguard Worker   return !m_pNode->TryWidth().has_value();
133*3ac0a46fSAndroid Build Coastguard Worker }
134*3ac0a46fSAndroid Build Coastguard Worker 
GetEmbeddedObj(const WideString & wsAttr) const135*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> CXFA_TextProvider::GetEmbeddedObj(
136*3ac0a46fSAndroid Build Coastguard Worker     const WideString& wsAttr) const {
137*3ac0a46fSAndroid Build Coastguard Worker   if (m_eType != Type::kText)
138*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
139*3ac0a46fSAndroid Build Coastguard Worker 
140*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pParent = m_pNode->GetParent();
141*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Document* pDocument = m_pNode->GetDocument();
142*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pIDNode = nullptr;
143*3ac0a46fSAndroid Build Coastguard Worker   if (pParent)
144*3ac0a46fSAndroid Build Coastguard Worker     pIDNode = pDocument->GetNodeByID(pParent, wsAttr.AsStringView());
145*3ac0a46fSAndroid Build Coastguard Worker 
146*3ac0a46fSAndroid Build Coastguard Worker   if (!pIDNode) {
147*3ac0a46fSAndroid Build Coastguard Worker     pIDNode = pDocument->GetNodeByID(
148*3ac0a46fSAndroid Build Coastguard Worker         ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Form)),
149*3ac0a46fSAndroid Build Coastguard Worker         wsAttr.AsStringView());
150*3ac0a46fSAndroid Build Coastguard Worker   }
151*3ac0a46fSAndroid Build Coastguard Worker   if (!pIDNode || !pIDNode->IsWidgetReady())
152*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
153*3ac0a46fSAndroid Build Coastguard Worker 
154*3ac0a46fSAndroid Build Coastguard Worker   return pIDNode->GetValue(XFA_ValuePicture::kDisplay);
155*3ac0a46fSAndroid Build Coastguard Worker }
156