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