// Copyright 2016 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/parser/cxfa_node.h" #include #include #include #include #include #include #include #include #include "core/fxcrt/autorestorer.h" #include "core/fxcrt/cfx_read_only_string_stream.h" #include "core/fxcrt/cfx_read_only_vector_stream.h" #include "core/fxcrt/data_vector.h" #include "core/fxcrt/fx_codepage.h" #include "core/fxcrt/fx_extension.h" #include "core/fxcrt/stl_util.h" #include "core/fxcrt/xml/cfx_xmldocument.h" #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 "core/fxge/fx_font.h" #include "fxjs/gc/container_trace.h" #include "fxjs/xfa/cfxjse_engine.h" #include "fxjs/xfa/cfxjse_value.h" #include "fxjs/xfa/cjx_node.h" #include "third_party/base/check.h" #include "third_party/base/check_op.h" #include "third_party/base/containers/contains.h" #include "third_party/base/containers/span.h" #include "third_party/base/notreached.h" #include "xfa/fde/cfde_textout.h" #include "xfa/fgas/crt/cfgas_decimal.h" #include "xfa/fgas/crt/locale_iface.h" #include "xfa/fgas/font/cfgas_fontmgr.h" #include "xfa/fgas/font/cfgas_gefont.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_fontmgr.h" #include "xfa/fxfa/cxfa_textprovider.h" #include "xfa/fxfa/parser/cxfa_accessiblecontent.h" #include "xfa/fxfa/parser/cxfa_acrobat.h" #include "xfa/fxfa/parser/cxfa_acrobat7.h" #include "xfa/fxfa/parser/cxfa_adbe_jsconsole.h" #include "xfa/fxfa/parser/cxfa_adbe_jsdebugger.h" #include "xfa/fxfa/parser/cxfa_addsilentprint.h" #include "xfa/fxfa/parser/cxfa_addviewerpreferences.h" #include "xfa/fxfa/parser/cxfa_adjustdata.h" #include "xfa/fxfa/parser/cxfa_adobeextensionlevel.h" #include "xfa/fxfa/parser/cxfa_agent.h" #include "xfa/fxfa/parser/cxfa_alwaysembed.h" #include "xfa/fxfa/parser/cxfa_amd.h" #include "xfa/fxfa/parser/cxfa_appearancefilter.h" #include "xfa/fxfa/parser/cxfa_arc.h" #include "xfa/fxfa/parser/cxfa_area.h" #include "xfa/fxfa/parser/cxfa_arraynodelist.h" #include "xfa/fxfa/parser/cxfa_assist.h" #include "xfa/fxfa/parser/cxfa_attachnodelist.h" #include "xfa/fxfa/parser/cxfa_attributes.h" #include "xfa/fxfa/parser/cxfa_autosave.h" #include "xfa/fxfa/parser/cxfa_barcode.h" #include "xfa/fxfa/parser/cxfa_base.h" #include "xfa/fxfa/parser/cxfa_batchoutput.h" #include "xfa/fxfa/parser/cxfa_behavioroverride.h" #include "xfa/fxfa/parser/cxfa_bind.h" #include "xfa/fxfa/parser/cxfa_binditems.h" #include "xfa/fxfa/parser/cxfa_bookend.h" #include "xfa/fxfa/parser/cxfa_boolean.h" #include "xfa/fxfa/parser/cxfa_border.h" #include "xfa/fxfa/parser/cxfa_break.h" #include "xfa/fxfa/parser/cxfa_breakafter.h" #include "xfa/fxfa/parser/cxfa_breakbefore.h" #include "xfa/fxfa/parser/cxfa_button.h" #include "xfa/fxfa/parser/cxfa_cache.h" #include "xfa/fxfa/parser/cxfa_calculate.h" #include "xfa/fxfa/parser/cxfa_calendarsymbols.h" #include "xfa/fxfa/parser/cxfa_caption.h" #include "xfa/fxfa/parser/cxfa_certificate.h" #include "xfa/fxfa/parser/cxfa_certificates.h" #include "xfa/fxfa/parser/cxfa_change.h" #include "xfa/fxfa/parser/cxfa_checkbutton.h" #include "xfa/fxfa/parser/cxfa_choicelist.h" #include "xfa/fxfa/parser/cxfa_color.h" #include "xfa/fxfa/parser/cxfa_comb.h" #include "xfa/fxfa/parser/cxfa_command.h" #include "xfa/fxfa/parser/cxfa_common.h" #include "xfa/fxfa/parser/cxfa_compress.h" #include "xfa/fxfa/parser/cxfa_compression.h" #include "xfa/fxfa/parser/cxfa_compresslogicalstructure.h" #include "xfa/fxfa/parser/cxfa_compressobjectstream.h" #include "xfa/fxfa/parser/cxfa_config.h" #include "xfa/fxfa/parser/cxfa_conformance.h" #include "xfa/fxfa/parser/cxfa_connect.h" #include "xfa/fxfa/parser/cxfa_connectionset.h" #include "xfa/fxfa/parser/cxfa_connectstring.h" #include "xfa/fxfa/parser/cxfa_contentarea.h" #include "xfa/fxfa/parser/cxfa_contentcopy.h" #include "xfa/fxfa/parser/cxfa_copies.h" #include "xfa/fxfa/parser/cxfa_corner.h" #include "xfa/fxfa/parser/cxfa_creator.h" #include "xfa/fxfa/parser/cxfa_currencysymbol.h" #include "xfa/fxfa/parser/cxfa_currencysymbols.h" #include "xfa/fxfa/parser/cxfa_currentpage.h" #include "xfa/fxfa/parser/cxfa_data.h" #include "xfa/fxfa/parser/cxfa_datagroup.h" #include "xfa/fxfa/parser/cxfa_datamodel.h" #include "xfa/fxfa/parser/cxfa_datavalue.h" #include "xfa/fxfa/parser/cxfa_date.h" #include "xfa/fxfa/parser/cxfa_datepattern.h" #include "xfa/fxfa/parser/cxfa_datepatterns.h" #include "xfa/fxfa/parser/cxfa_datetime.h" #include "xfa/fxfa/parser/cxfa_datetimeedit.h" #include "xfa/fxfa/parser/cxfa_datetimesymbols.h" #include "xfa/fxfa/parser/cxfa_day.h" #include "xfa/fxfa/parser/cxfa_daynames.h" #include "xfa/fxfa/parser/cxfa_debug.h" #include "xfa/fxfa/parser/cxfa_decimal.h" #include "xfa/fxfa/parser/cxfa_defaulttypeface.h" #include "xfa/fxfa/parser/cxfa_defaultui.h" #include "xfa/fxfa/parser/cxfa_delete.h" #include "xfa/fxfa/parser/cxfa_delta.h" #include "xfa/fxfa/parser/cxfa_desc.h" #include "xfa/fxfa/parser/cxfa_destination.h" #include "xfa/fxfa/parser/cxfa_digestmethod.h" #include "xfa/fxfa/parser/cxfa_digestmethods.h" #include "xfa/fxfa/parser/cxfa_document.h" #include "xfa/fxfa/parser/cxfa_document_builder.h" #include "xfa/fxfa/parser/cxfa_documentassembly.h" #include "xfa/fxfa/parser/cxfa_draw.h" #include "xfa/fxfa/parser/cxfa_driver.h" #include "xfa/fxfa/parser/cxfa_dsigdata.h" #include "xfa/fxfa/parser/cxfa_duplexoption.h" #include "xfa/fxfa/parser/cxfa_dynamicrender.h" #include "xfa/fxfa/parser/cxfa_edge.h" #include "xfa/fxfa/parser/cxfa_effectiveinputpolicy.h" #include "xfa/fxfa/parser/cxfa_effectiveoutputpolicy.h" #include "xfa/fxfa/parser/cxfa_embed.h" #include "xfa/fxfa/parser/cxfa_encoding.h" #include "xfa/fxfa/parser/cxfa_encodings.h" #include "xfa/fxfa/parser/cxfa_encrypt.h" #include "xfa/fxfa/parser/cxfa_encryption.h" #include "xfa/fxfa/parser/cxfa_encryptionlevel.h" #include "xfa/fxfa/parser/cxfa_encryptionmethod.h" #include "xfa/fxfa/parser/cxfa_encryptionmethods.h" #include "xfa/fxfa/parser/cxfa_enforce.h" #include "xfa/fxfa/parser/cxfa_equate.h" #include "xfa/fxfa/parser/cxfa_equaterange.h" #include "xfa/fxfa/parser/cxfa_era.h" #include "xfa/fxfa/parser/cxfa_eranames.h" #include "xfa/fxfa/parser/cxfa_event.h" #include "xfa/fxfa/parser/cxfa_exclgroup.h" #include "xfa/fxfa/parser/cxfa_exclude.h" #include "xfa/fxfa/parser/cxfa_excludens.h" #include "xfa/fxfa/parser/cxfa_exdata.h" #include "xfa/fxfa/parser/cxfa_execute.h" #include "xfa/fxfa/parser/cxfa_exobject.h" #include "xfa/fxfa/parser/cxfa_extras.h" #include "xfa/fxfa/parser/cxfa_field.h" #include "xfa/fxfa/parser/cxfa_fill.h" #include "xfa/fxfa/parser/cxfa_filter.h" #include "xfa/fxfa/parser/cxfa_fliplabel.h" #include "xfa/fxfa/parser/cxfa_float.h" #include "xfa/fxfa/parser/cxfa_font.h" #include "xfa/fxfa/parser/cxfa_fontinfo.h" #include "xfa/fxfa/parser/cxfa_form.h" #include "xfa/fxfa/parser/cxfa_format.h" #include "xfa/fxfa/parser/cxfa_formfieldfilling.h" #include "xfa/fxfa/parser/cxfa_groupparent.h" #include "xfa/fxfa/parser/cxfa_handler.h" #include "xfa/fxfa/parser/cxfa_hyphenation.h" #include "xfa/fxfa/parser/cxfa_ifempty.h" #include "xfa/fxfa/parser/cxfa_image.h" #include "xfa/fxfa/parser/cxfa_imageedit.h" #include "xfa/fxfa/parser/cxfa_includexdpcontent.h" #include "xfa/fxfa/parser/cxfa_incrementalload.h" #include "xfa/fxfa/parser/cxfa_incrementalmerge.h" #include "xfa/fxfa/parser/cxfa_insert.h" #include "xfa/fxfa/parser/cxfa_instancemanager.h" #include "xfa/fxfa/parser/cxfa_integer.h" #include "xfa/fxfa/parser/cxfa_interactive.h" #include "xfa/fxfa/parser/cxfa_issuers.h" #include "xfa/fxfa/parser/cxfa_items.h" #include "xfa/fxfa/parser/cxfa_jog.h" #include "xfa/fxfa/parser/cxfa_keep.h" #include "xfa/fxfa/parser/cxfa_keyusage.h" #include "xfa/fxfa/parser/cxfa_labelprinter.h" #include "xfa/fxfa/parser/cxfa_layout.h" #include "xfa/fxfa/parser/cxfa_level.h" #include "xfa/fxfa/parser/cxfa_line.h" #include "xfa/fxfa/parser/cxfa_linear.h" #include "xfa/fxfa/parser/cxfa_linearized.h" #include "xfa/fxfa/parser/cxfa_locale.h" #include "xfa/fxfa/parser/cxfa_localeset.h" #include "xfa/fxfa/parser/cxfa_localevalue.h" #include "xfa/fxfa/parser/cxfa_lockdocument.h" #include "xfa/fxfa/parser/cxfa_log.h" #include "xfa/fxfa/parser/cxfa_manifest.h" #include "xfa/fxfa/parser/cxfa_map.h" #include "xfa/fxfa/parser/cxfa_margin.h" #include "xfa/fxfa/parser/cxfa_mdp.h" #include "xfa/fxfa/parser/cxfa_measurement.h" #include "xfa/fxfa/parser/cxfa_medium.h" #include "xfa/fxfa/parser/cxfa_mediuminfo.h" #include "xfa/fxfa/parser/cxfa_meridiem.h" #include "xfa/fxfa/parser/cxfa_meridiemnames.h" #include "xfa/fxfa/parser/cxfa_message.h" #include "xfa/fxfa/parser/cxfa_messaging.h" #include "xfa/fxfa/parser/cxfa_mode.h" #include "xfa/fxfa/parser/cxfa_modifyannots.h" #include "xfa/fxfa/parser/cxfa_month.h" #include "xfa/fxfa/parser/cxfa_monthnames.h" #include "xfa/fxfa/parser/cxfa_msgid.h" #include "xfa/fxfa/parser/cxfa_nameattr.h" #include "xfa/fxfa/parser/cxfa_neverembed.h" #include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" #include "xfa/fxfa/parser/cxfa_numberofcopies.h" #include "xfa/fxfa/parser/cxfa_numberpattern.h" #include "xfa/fxfa/parser/cxfa_numberpatterns.h" #include "xfa/fxfa/parser/cxfa_numbersymbol.h" #include "xfa/fxfa/parser/cxfa_numbersymbols.h" #include "xfa/fxfa/parser/cxfa_numericedit.h" #include "xfa/fxfa/parser/cxfa_occur.h" #include "xfa/fxfa/parser/cxfa_oid.h" #include "xfa/fxfa/parser/cxfa_oids.h" #include "xfa/fxfa/parser/cxfa_openaction.h" #include "xfa/fxfa/parser/cxfa_operation.h" #include "xfa/fxfa/parser/cxfa_output.h" #include "xfa/fxfa/parser/cxfa_outputbin.h" #include "xfa/fxfa/parser/cxfa_outputxsl.h" #include "xfa/fxfa/parser/cxfa_overflow.h" #include "xfa/fxfa/parser/cxfa_overprint.h" #include "xfa/fxfa/parser/cxfa_packet.h" #include "xfa/fxfa/parser/cxfa_packets.h" #include "xfa/fxfa/parser/cxfa_pagearea.h" #include "xfa/fxfa/parser/cxfa_pageoffset.h" #include "xfa/fxfa/parser/cxfa_pagerange.h" #include "xfa/fxfa/parser/cxfa_pageset.h" #include "xfa/fxfa/parser/cxfa_pagination.h" #include "xfa/fxfa/parser/cxfa_paginationoverride.h" #include "xfa/fxfa/parser/cxfa_para.h" #include "xfa/fxfa/parser/cxfa_part.h" #include "xfa/fxfa/parser/cxfa_password.h" #include "xfa/fxfa/parser/cxfa_passwordedit.h" #include "xfa/fxfa/parser/cxfa_pattern.h" #include "xfa/fxfa/parser/cxfa_pcl.h" #include "xfa/fxfa/parser/cxfa_pdf.h" #include "xfa/fxfa/parser/cxfa_pdfa.h" #include "xfa/fxfa/parser/cxfa_permissions.h" #include "xfa/fxfa/parser/cxfa_picktraybypdfsize.h" #include "xfa/fxfa/parser/cxfa_picture.h" #include "xfa/fxfa/parser/cxfa_plaintextmetadata.h" #include "xfa/fxfa/parser/cxfa_presence.h" #include "xfa/fxfa/parser/cxfa_present.h" #include "xfa/fxfa/parser/cxfa_print.h" #include "xfa/fxfa/parser/cxfa_printername.h" #include "xfa/fxfa/parser/cxfa_printhighquality.h" #include "xfa/fxfa/parser/cxfa_printscaling.h" #include "xfa/fxfa/parser/cxfa_producer.h" #include "xfa/fxfa/parser/cxfa_proto.h" #include "xfa/fxfa/parser/cxfa_ps.h" #include "xfa/fxfa/parser/cxfa_psmap.h" #include "xfa/fxfa/parser/cxfa_query.h" #include "xfa/fxfa/parser/cxfa_radial.h" #include "xfa/fxfa/parser/cxfa_range.h" #include "xfa/fxfa/parser/cxfa_reason.h" #include "xfa/fxfa/parser/cxfa_reasons.h" #include "xfa/fxfa/parser/cxfa_record.h" #include "xfa/fxfa/parser/cxfa_recordset.h" #include "xfa/fxfa/parser/cxfa_rectangle.h" #include "xfa/fxfa/parser/cxfa_ref.h" #include "xfa/fxfa/parser/cxfa_relevant.h" #include "xfa/fxfa/parser/cxfa_rename.h" #include "xfa/fxfa/parser/cxfa_renderpolicy.h" #include "xfa/fxfa/parser/cxfa_rootelement.h" #include "xfa/fxfa/parser/cxfa_runscripts.h" #include "xfa/fxfa/parser/cxfa_script.h" #include "xfa/fxfa/parser/cxfa_scriptmodel.h" #include "xfa/fxfa/parser/cxfa_select.h" #include "xfa/fxfa/parser/cxfa_setproperty.h" #include "xfa/fxfa/parser/cxfa_severity.h" #include "xfa/fxfa/parser/cxfa_sharptext.h" #include "xfa/fxfa/parser/cxfa_sharpxhtml.h" #include "xfa/fxfa/parser/cxfa_sharpxml.h" #include "xfa/fxfa/parser/cxfa_signature.h" #include "xfa/fxfa/parser/cxfa_signatureproperties.h" #include "xfa/fxfa/parser/cxfa_signdata.h" #include "xfa/fxfa/parser/cxfa_signing.h" #include "xfa/fxfa/parser/cxfa_silentprint.h" #include "xfa/fxfa/parser/cxfa_soapaction.h" #include "xfa/fxfa/parser/cxfa_soapaddress.h" #include "xfa/fxfa/parser/cxfa_solid.h" #include "xfa/fxfa/parser/cxfa_source.h" #include "xfa/fxfa/parser/cxfa_sourceset.h" #include "xfa/fxfa/parser/cxfa_speak.h" #include "xfa/fxfa/parser/cxfa_staple.h" #include "xfa/fxfa/parser/cxfa_startnode.h" #include "xfa/fxfa/parser/cxfa_startpage.h" #include "xfa/fxfa/parser/cxfa_stipple.h" #include "xfa/fxfa/parser/cxfa_stroke.h" #include "xfa/fxfa/parser/cxfa_subform.h" #include "xfa/fxfa/parser/cxfa_subformset.h" #include "xfa/fxfa/parser/cxfa_subjectdn.h" #include "xfa/fxfa/parser/cxfa_subjectdns.h" #include "xfa/fxfa/parser/cxfa_submit.h" #include "xfa/fxfa/parser/cxfa_submitformat.h" #include "xfa/fxfa/parser/cxfa_submiturl.h" #include "xfa/fxfa/parser/cxfa_subsetbelow.h" #include "xfa/fxfa/parser/cxfa_suppressbanner.h" #include "xfa/fxfa/parser/cxfa_tagged.h" #include "xfa/fxfa/parser/cxfa_template.h" #include "xfa/fxfa/parser/cxfa_templatecache.h" #include "xfa/fxfa/parser/cxfa_text.h" #include "xfa/fxfa/parser/cxfa_textedit.h" #include "xfa/fxfa/parser/cxfa_threshold.h" #include "xfa/fxfa/parser/cxfa_time.h" #include "xfa/fxfa/parser/cxfa_timepattern.h" #include "xfa/fxfa/parser/cxfa_timepatterns.h" #include "xfa/fxfa/parser/cxfa_timestamp.h" #include "xfa/fxfa/parser/cxfa_to.h" #include "xfa/fxfa/parser/cxfa_tooltip.h" #include "xfa/fxfa/parser/cxfa_trace.h" #include "xfa/fxfa/parser/cxfa_transform.h" #include "xfa/fxfa/parser/cxfa_traversal.h" #include "xfa/fxfa/parser/cxfa_traverse.h" #include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h" #include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h" #include "xfa/fxfa/parser/cxfa_type.h" #include "xfa/fxfa/parser/cxfa_typeface.h" #include "xfa/fxfa/parser/cxfa_typefaces.h" #include "xfa/fxfa/parser/cxfa_ui.h" #include "xfa/fxfa/parser/cxfa_update.h" #include "xfa/fxfa/parser/cxfa_uri.h" #include "xfa/fxfa/parser/cxfa_user.h" #include "xfa/fxfa/parser/cxfa_validate.h" #include "xfa/fxfa/parser/cxfa_validateapprovalsignatures.h" #include "xfa/fxfa/parser/cxfa_validationmessaging.h" #include "xfa/fxfa/parser/cxfa_value.h" #include "xfa/fxfa/parser/cxfa_variables.h" #include "xfa/fxfa/parser/cxfa_version.h" #include "xfa/fxfa/parser/cxfa_versioncontrol.h" #include "xfa/fxfa/parser/cxfa_viewerpreferences.h" #include "xfa/fxfa/parser/cxfa_webclient.h" #include "xfa/fxfa/parser/cxfa_whitespace.h" #include "xfa/fxfa/parser/cxfa_window.h" #include "xfa/fxfa/parser/cxfa_wsdladdress.h" #include "xfa/fxfa/parser/cxfa_wsdlconnection.h" #include "xfa/fxfa/parser/cxfa_xdc.h" #include "xfa/fxfa/parser/cxfa_xdp.h" #include "xfa/fxfa/parser/cxfa_xfa.h" #include "xfa/fxfa/parser/cxfa_xmlconnection.h" #include "xfa/fxfa/parser/cxfa_xsdconnection.h" #include "xfa/fxfa/parser/cxfa_xsl.h" #include "xfa/fxfa/parser/cxfa_zpl.h" #include "xfa/fxfa/parser/xfa_basic_data.h" #include "xfa/fxfa/parser/xfa_utils.h" class CXFA_FieldLayoutData; class CXFA_ImageEditData; class CXFA_ImageLayoutData; class CXFA_TextEditData; class CXFA_TextLayoutData; namespace { constexpr uint8_t kMaxExecuteRecursion = 2; constexpr uint8_t kInvBase64[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, }; inline uint8_t GetInvBase64(uint8_t x) { return (x & 128) == 0 ? kInvBase64[x] : 255; } DataVector XFA_RemoveBase64Whitespace( pdfium::span spStr) { DataVector result; result.reserve(spStr.size()); for (uint8_t ch : spStr) { if (GetInvBase64(ch) != 255 || ch == '=') result.push_back(ch); } return result; } DataVector XFA_Base64Decode(const ByteString& bsStr) { DataVector result; if (bsStr.IsEmpty()) return result; DataVector buffer = XFA_RemoveBase64Whitespace(bsStr.raw_span()); result.reserve(3 * (buffer.size() / 4)); uint32_t dwLimb = 0; for (size_t i = 0; i + 3 < buffer.size(); i += 4) { if (buffer[i] == '=' || buffer[i + 1] == '=' || buffer[i + 2] == '=' || buffer[i + 3] == '=') { if (buffer[i] == '=' || buffer[i + 1] == '=') { break; } if (buffer[i + 2] == '=') { dwLimb = ((uint32_t)kInvBase64[buffer[i]] << 6) | ((uint32_t)kInvBase64[buffer[i + 1]]); result.push_back((uint8_t)(dwLimb >> 4) & 0xFF); } else { dwLimb = ((uint32_t)kInvBase64[buffer[i]] << 12) | ((uint32_t)kInvBase64[buffer[i + 1]] << 6) | ((uint32_t)kInvBase64[buffer[i + 2]]); result.push_back((uint8_t)(dwLimb >> 10) & 0xFF); result.push_back((uint8_t)(dwLimb >> 2) & 0xFF); } } else { dwLimb = ((uint32_t)kInvBase64[buffer[i]] << 18) | ((uint32_t)kInvBase64[buffer[i + 1]] << 12) | ((uint32_t)kInvBase64[buffer[i + 2]] << 6) | ((uint32_t)kInvBase64[buffer[i + 3]]); result.push_back((uint8_t)(dwLimb >> 16) & 0xff); result.push_back((uint8_t)(dwLimb >> 8) & 0xff); result.push_back((uint8_t)(dwLimb)&0xff); } } return result; } FXCODEC_IMAGE_TYPE XFA_GetImageType(const WideString& wsType) { WideString wsContentType(wsType); if (wsContentType.EqualsASCIINoCase("image/jpg")) return FXCODEC_IMAGE_JPG; #ifdef PDF_ENABLE_XFA_BMP if (wsContentType.EqualsASCIINoCase("image/bmp")) return FXCODEC_IMAGE_BMP; #endif // PDF_ENABLE_XFA_BMP #ifdef PDF_ENABLE_XFA_GIF if (wsContentType.EqualsASCIINoCase("image/gif")) return FXCODEC_IMAGE_GIF; #endif // PDF_ENABLE_XFA_GIF #ifdef PDF_ENABLE_XFA_PNG if (wsContentType.EqualsASCIINoCase("image/png")) return FXCODEC_IMAGE_PNG; #endif // PDF_ENABLE_XFA_PNG #ifdef PDF_ENABLE_XFA_TIFF if (wsContentType.EqualsASCII("image/tif")) return FXCODEC_IMAGE_TIFF; #endif // PDF_ENABLE_XFA_TIFF return FXCODEC_IMAGE_UNKNOWN; } RetainPtr 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()); RetainPtr pImageFileRead; if (wsImage.GetLength() > 0) { XFA_AttributeValue iEncoding = pImage->GetTransferEncoding(); if (iEncoding == XFA_AttributeValue::Base64) { DataVector buffer = XFA_Base64Decode(wsImage.ToUTF8()); if (!buffer.empty()) { pImageFileRead = pdfium::MakeRetain(std::move(buffer)); } } else { pImageFileRead = pdfium::MakeRetain(wsImage.ToDefANSI()); } } else { WideString wsURL = wsHref; if (!(wsURL.First(7).EqualsASCII("http://") || wsURL.First(6).EqualsASCII("ftp://"))) { RetainPtr pBitmap = pDoc->GetPDFNamedImage(wsURL.AsStringView(), iImageXDpi, iImageYDpi); if (pBitmap) { bNameImage = true; return pBitmap; } } pImageFileRead = pDoc->OpenLinkedFile(wsURL); } if (!pImageFileRead) return nullptr; bNameImage = false; return XFA_LoadImageFromBuffer(std::move(pImageFileRead), type, iImageXDpi, iImageYDpi); } bool SplitDateTime(const WideString& wsDateTime, WideString& wsDate, WideString& wsTime) { wsDate.clear(); wsTime.clear(); 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.First(nSplitIndex.value()); if (!wsDate.IsEmpty()) { if (!std::any_of(wsDate.begin(), wsDate.end(), [](wchar_t c) { return FXSYS_IsDecimalDigit(c); })) { return false; } } wsTime = wsDateTime.Last(wsDateTime.GetLength() - nSplitIndex.value() - 1); if (!wsTime.IsEmpty()) { if (!std::any_of(wsTime.begin(), wsTime.end(), [](wchar_t c) { return FXSYS_IsDecimalDigit(c); })) { return false; } } return true; } // Stack allocated. Using containers of members would be correct here // if advanced GC worked with STL. using NodeSet = std::set>; using NodeSetPair = std::pair; using NodeSetPairMap = std::map; using NodeSetPairMapMap = std::map; using NodeVector = std::vector>; NodeVector NodesSortedByDocumentIdx(const NodeSet& rgNodeSet) { if (rgNodeSet.empty()) return NodeVector(); NodeVector rgNodeArray; CXFA_Node* pCommonParent = (*rgNodeSet.begin())->GetParent(); for (CXFA_Node* pNode = pCommonParent->GetFirstChild(); pNode; pNode = pNode->GetNextSibling()) { if (pdfium::Contains(rgNodeSet, pNode)) rgNodeArray.push_back(pNode); } return rgNodeArray; } NodeSetPair* NodeSetPairForNode(CXFA_Node* pNode, NodeSetPairMapMap* pMap) { CXFA_Node* pParentNode = pNode->GetParent(); uint32_t dwNameHash = pNode->GetNameHash(); if (!pParentNode || !dwNameHash) return nullptr; return &((*pMap)[pParentNode][dwNameHash]); } void ReorderDataNodes(const NodeSet& sSet1, const NodeSet& sSet2, bool bInsertBefore) { NodeSetPairMapMap rgMap; for (CXFA_Node* pNode : sSet1) { NodeSetPair* pNodeSetPair = NodeSetPairForNode(pNode, &rgMap); if (pNodeSetPair) pNodeSetPair->first.insert(pNode); } for (CXFA_Node* pNode : sSet2) { NodeSetPair* pNodeSetPair = NodeSetPairForNode(pNode, &rgMap); if (pNodeSetPair) { if (pdfium::Contains(pNodeSetPair->first, pNode)) pNodeSetPair->first.erase(pNode); else pNodeSetPair->second.insert(pNode); } } for (auto& iter1 : rgMap) { NodeSetPairMap* pNodeSetPairMap = &iter1.second; for (auto& iter2 : *pNodeSetPairMap) { NodeSetPair* pNodeSetPair = &iter2.second; if (!pNodeSetPair->first.empty() && !pNodeSetPair->second.empty()) { NodeVector rgNodeArray1 = NodesSortedByDocumentIdx(pNodeSetPair->first); NodeVector rgNodeArray2 = NodesSortedByDocumentIdx(pNodeSetPair->second); CXFA_Node* pParentNode = nullptr; CXFA_Node* pBeforeNode = nullptr; if (bInsertBefore) { pBeforeNode = rgNodeArray2.front(); pParentNode = pBeforeNode->GetParent(); } else { CXFA_Node* pLastNode = rgNodeArray2.back(); pParentNode = pLastNode->GetParent(); pBeforeNode = pLastNode->GetNextSibling(); } for (auto& pCurNode : rgNodeArray1) { pParentNode->RemoveChildAndNotify(pCurNode, true); pParentNode->InsertChildAndNotify(pCurNode, pBeforeNode); } } } pNodeSetPairMap->clear(); } } float GetEdgeThickness(const std::vector& strokes, bool b3DStyle, int32_t nIndex) { float fThickness = 0.0f; CXFA_Stroke* stroke = strokes[nIndex * 2 + 1]; if (stroke->IsVisible()) { if (nIndex == 0) fThickness += 2.5f; fThickness += stroke->GetThickness() * (b3DStyle ? 4 : 2); } return fThickness; } WideString FormatNumStr(const WideString& wsValue, LocaleIface* pLocale) { if (wsValue.IsEmpty()) return WideString(); WideString wsSrcNum = wsValue; WideString wsGroupSymbol = pLocale->GetGroupingSymbol(); bool bNeg = false; if (wsSrcNum[0] == '-') { bNeg = true; wsSrcNum.Delete(0, 1); } size_t dot_index = wsSrcNum.Find('.').value_or(wsSrcNum.GetLength()); if (dot_index == 0) return WideString(); size_t nPos = dot_index % 3; WideString wsOutput; for (size_t i = 0; i < dot_index; i++) { if (i % 3 == nPos && i != 0) wsOutput += wsGroupSymbol; wsOutput += wsSrcNum[i]; } if (dot_index < wsSrcNum.GetLength()) { wsOutput += pLocale->GetDecimalSymbol(); wsOutput += wsSrcNum.Last(wsSrcNum.GetLength() - dot_index - 1); } if (bNeg) return pLocale->GetMinusSymbol() + wsOutput; return wsOutput; } CXFA_Node* FindFirstSiblingNamedInList(CXFA_Node* parent, uint32_t dwNameHash, Mask dwFilter); CXFA_Node* FindFirstSiblingOfClassInList(CXFA_Node* parent, XFA_Element element, Mask dwFilter); CXFA_Node* FindFirstSiblingNamed(CXFA_Node* parent, uint32_t dwNameHash) { CXFA_Node* result = FindFirstSiblingNamedInList(parent, dwNameHash, XFA_NodeFilter::kProperties); if (result) return result; return FindFirstSiblingNamedInList(parent, dwNameHash, XFA_NodeFilter::kChildren); } CXFA_Node* FindFirstSiblingNamedInList(CXFA_Node* parent, uint32_t dwNameHash, Mask dwFilter) { for (CXFA_Node* child : parent->GetNodeListWithFilter(dwFilter)) { if (child->GetNameHash() == dwNameHash) return child; CXFA_Node* result = FindFirstSiblingNamed(child, dwNameHash); if (result) return result; } return nullptr; } CXFA_Node* FindFirstSiblingOfClass(CXFA_Node* parent, XFA_Element element) { CXFA_Node* result = FindFirstSiblingOfClassInList( parent, element, XFA_NodeFilter::kProperties); if (result) return result; return FindFirstSiblingOfClassInList(parent, element, XFA_NodeFilter::kChildren); } CXFA_Node* FindFirstSiblingOfClassInList(CXFA_Node* parent, XFA_Element element, Mask dwFilter) { for (CXFA_Node* child : parent->GetNodeListWithFilter(dwFilter)) { if (child->GetElementType() == element) return child; CXFA_Node* result = FindFirstSiblingOfClass(child, element); if (result) return result; } return nullptr; } WideString GetNameExpressionSinglePath(CXFA_Node* pNode) { const bool bIsProperty = pNode->IsProperty(); const bool bIsClassIndex = pNode->IsUnnamed() || (bIsProperty && pNode->GetElementType() != XFA_Element::PageSet); const wchar_t* pszFormat; WideString ws; if (bIsClassIndex) { pszFormat = L"#%ls[%zu]"; ws = WideString::FromASCII(pNode->GetClassName()); } else { pszFormat = L"%ls[%zu]"; ws = pNode->JSObject()->GetCData(XFA_Attribute::Name); ws.Replace(L".", L"\\."); } return WideString::Format(pszFormat, ws.c_str(), pNode->GetIndex(bIsProperty, bIsClassIndex)); } void TraverseSiblings(CXFA_Node* parent, uint32_t dwNameHash, std::vector* pSiblings, bool bIsClassName) { DCHECK(parent); DCHECK(pSiblings); for (CXFA_Node* child : parent->GetNodeListWithFilter(XFA_NodeFilter::kChildren)) { if (child->GetElementType() == XFA_Element::Variables) continue; if (bIsClassName) { if (child->GetClassHashCode() == dwNameHash) pSiblings->push_back(child); } else { if (child->GetNameHash() == dwNameHash) pSiblings->push_back(child); } if (child->IsTransparent() && child->GetElementType() != XFA_Element::PageSet) { TraverseSiblings(child, dwNameHash, pSiblings, bIsClassName); } } } void TraversePropertiesOrSiblings(CXFA_Node* parent, uint32_t dwNameHash, std::vector* pSiblings, bool bIsClassName) { DCHECK(parent); DCHECK(pSiblings); for (CXFA_Node* child : parent->GetNodeListWithFilter(XFA_NodeFilter::kProperties)) { if (bIsClassName) { if (child->GetClassHashCode() == dwNameHash) pSiblings->push_back(child); } else { if (child->GetNameHash() == dwNameHash) { if (child->GetElementType() != XFA_Element::PageSet && child->GetElementType() != XFA_Element::Extras && child->GetElementType() != XFA_Element::Items) { pSiblings->push_back(child); } } } if (child->IsUnnamed() && child->GetElementType() == XFA_Element::PageSet) { TraverseSiblings(child, dwNameHash, pSiblings, bIsClassName); } } if (pSiblings->empty()) TraverseSiblings(parent, dwNameHash, pSiblings, bIsClassName); } } // namespace class CXFA_WidgetLayoutData : public cppgc::GarbageCollected { public: CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED; virtual ~CXFA_WidgetLayoutData() = default; virtual void Trace(cppgc::Visitor* visitor) const {} virtual CXFA_FieldLayoutData* AsFieldLayoutData() { return nullptr; } virtual CXFA_ImageLayoutData* AsImageLayoutData() { return nullptr; } virtual CXFA_TextLayoutData* AsTextLayoutData() { return nullptr; } float GetWidgetHeight() const { return m_fWidgetHeight; } void SetWidgetHeight(float height) { m_fWidgetHeight = height; } protected: CXFA_WidgetLayoutData() = default; private: float m_fWidgetHeight = -1.0f; }; class CXFA_TextLayoutData final : public CXFA_WidgetLayoutData { public: CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED; ~CXFA_TextLayoutData() override = default; void Trace(cppgc::Visitor* visitor) const override { CXFA_WidgetLayoutData::Trace(visitor); visitor->Trace(m_pTextLayout); visitor->Trace(m_pTextProvider); } CXFA_TextLayoutData* AsTextLayoutData() override { return this; } CXFA_TextLayout* GetTextLayout() const { return m_pTextLayout; } CXFA_TextProvider* GetTextProvider() const { return m_pTextProvider; } void LoadText(CXFA_FFDoc* doc, CXFA_Node* pNode) { if (m_pTextLayout) return; m_pTextProvider = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), pNode, CXFA_TextProvider::Type::kText); m_pTextLayout = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, m_pTextProvider); } private: CXFA_TextLayoutData() = default; cppgc::Member m_pTextLayout; cppgc::Member m_pTextProvider; }; class CXFA_ImageLayoutData final : public CXFA_WidgetLayoutData { public: CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED; ~CXFA_ImageLayoutData() override = default; CXFA_ImageLayoutData* AsImageLayoutData() override { return this; } 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->SetLayoutImage(XFA_LoadImageData(doc, image, m_bNamedImage, m_iImageXDpi, m_iImageYDpi)); return !!m_pDIBitmap; } CFX_Size GetDpi() const { return CFX_Size(m_iImageXDpi, m_iImageYDpi); } RetainPtr GetBitmap() { return m_pDIBitmap; } void SetBitmap(RetainPtr pBitmap) { m_pDIBitmap = std::move(pBitmap); } private: CXFA_ImageLayoutData() = default; bool m_bNamedImage = false; int32_t m_iImageXDpi = 0; int32_t m_iImageYDpi = 0; RetainPtr m_pDIBitmap; }; class CXFA_FieldLayoutData : public CXFA_WidgetLayoutData { public: CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED; ~CXFA_FieldLayoutData() override = default; void Trace(cppgc::Visitor* visitor) const override { CXFA_WidgetLayoutData::Trace(visitor); visitor->Trace(m_pCapTextLayout); visitor->Trace(m_pCapTextProvider); } CXFA_FieldLayoutData* AsFieldLayoutData() override { return this; } virtual CXFA_ImageEditData* AsImageEditData() { return nullptr; } virtual CXFA_TextEditData* AsTextEditData() { return nullptr; } 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 = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), pNode, CXFA_TextProvider::Type::kCaption); m_pCapTextLayout = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, m_pCapTextProvider); return true; } cppgc::Member m_pCapTextLayout; cppgc::Member m_pCapTextProvider; std::unique_ptr m_pTextOut; std::vector m_FieldSplitArray; protected: CXFA_FieldLayoutData() = default; }; class CXFA_TextEditData final : public CXFA_FieldLayoutData { public: CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED; ~CXFA_TextEditData() override = default; CXFA_TextEditData* AsTextEditData() override { return this; } protected: CXFA_TextEditData() = default; }; class CXFA_ImageEditData final : public CXFA_FieldLayoutData { public: CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED; ~CXFA_ImageEditData() override = default; CXFA_ImageEditData* AsImageEditData() override { return this; } 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->SetEditImage(XFA_LoadImageData(doc, image, m_bNamedImage, m_iImageXDpi, m_iImageYDpi)); return !!m_pDIBitmap; } CFX_Size GetDpi() const { return CFX_Size(m_iImageXDpi, m_iImageYDpi); } RetainPtr GetBitmap() { return m_pDIBitmap; } void SetBitmap(RetainPtr pBitmap) { m_pDIBitmap = std::move(pBitmap); } private: CXFA_ImageEditData() = default; bool m_bNamedImage = false; int32_t m_iImageXDpi = 0; int32_t m_iImageYDpi = 0; RetainPtr m_pDIBitmap; }; CXFA_Node::CXFA_Node(CXFA_Document* pDoc, XFA_PacketType ePacket, Mask validPackets, XFA_ObjectType oType, XFA_Element eType, pdfium::span properties, pdfium::span attributes, CJX_Object* js_object) : CXFA_Object(pDoc, oType, eType, js_object), m_Properties(properties), m_Attributes(attributes), m_ValidPackets(validPackets), m_ePacket(ePacket) { DCHECK(m_pDocument); } CXFA_Node::~CXFA_Node() = default; void CXFA_Node::Trace(cppgc::Visitor* visitor) const { CXFA_Object::Trace(visitor); GCedTreeNodeMixin::Trace(visitor); visitor->Trace(m_pAuxNode); ContainerTrace(visitor, binding_nodes_); visitor->Trace(m_pLayoutData); visitor->Trace(ui_); } CXFA_Node* CXFA_Node::Clone(bool bRecursive) { CXFA_Node* pClone = m_pDocument->CreateNode(m_ePacket, m_elementType); if (!pClone) return nullptr; JSObject()->MergeAllData(pClone); pClone->UpdateNameHash(); if (IsNeedSavingXMLNode()) { CFX_XMLNode* pCloneXML; if (IsAttributeInXML()) { WideString wsName = JSObject() ->TryAttribute(XFA_Attribute::Name, false) .value_or(WideString()); auto* pCloneXMLElement = GetXMLDocument()->CreateNode(wsName); WideString wsValue = JSObject()->GetCData(XFA_Attribute::Value); if (!wsValue.IsEmpty()) { auto* text = GetXMLDocument()->CreateNode(wsValue); pCloneXMLElement->AppendLastChild(text); } pCloneXML = pCloneXMLElement; pClone->JSObject()->SetEnum(XFA_Attribute::Contains, XFA_AttributeValue::Unknown, false); } else { pCloneXML = xml_node_->Clone(GetXMLDocument()); } pClone->SetXMLMappingNode(pCloneXML); } if (bRecursive) { for (CXFA_Node* pChild = GetFirstChild(); pChild; pChild = pChild->GetNextSibling()) { pClone->InsertChildAndNotify(pChild->Clone(bRecursive), nullptr); } } pClone->SetInitializedFlagAndNotify(); pClone->SetBindingNode(nullptr); return pClone; } CXFA_Node* CXFA_Node::GetNextContainerSibling() const { for (auto* pNode = GetNextSibling(); pNode; pNode = pNode->GetNextSibling()) { if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode) return pNode; } return nullptr; } CXFA_Node* CXFA_Node::GetPrevContainerSibling() const { for (auto* pNode = GetPrevSibling(); pNode; pNode = pNode->GetPrevSibling()) { if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode) return pNode; } return nullptr; } CXFA_Node* CXFA_Node::GetFirstContainerChild() const { for (auto* pNode = GetFirstChild(); pNode; pNode = pNode->GetNextSibling()) { if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode) return pNode; } return nullptr; } CXFA_Node* CXFA_Node::GetContainerParent() const { for (auto* pNode = GetParent(); pNode; pNode = pNode->GetParent()) { if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode) return pNode; } return nullptr; } bool CXFA_Node::IsValidInPacket(XFA_PacketType packet) const { uint32_t bitflag = 1 << static_cast(packet); return !!(m_ValidPackets & static_cast(bitflag)); } const CXFA_Node::PropertyData* CXFA_Node::GetPropertyData( XFA_Element property) const { DCHECK(property != XFA_Element::Unknown); for (const auto& prop : m_Properties) { if (prop.property == property) return ∝ } return nullptr; } bool CXFA_Node::HasProperty(XFA_Element property) const { return !!GetPropertyData(property); } bool CXFA_Node::HasPropertyFlag(XFA_Element property, XFA_PropertyFlag flag) const { const PropertyData* data = GetPropertyData(property); return data && !!(data->flags & flag); } uint8_t CXFA_Node::PropertyOccurrenceCount(XFA_Element property) const { const PropertyData* data = GetPropertyData(property); return data ? data->occurrence_count : 0; } std::pair CXFA_Node::GetProperty( int32_t index, XFA_Element eProperty) const { if (index < 0 || index >= PropertyOccurrenceCount(eProperty)) return {nullptr, 0}; int32_t iCount = 0; for (CXFA_Node* pNode = GetFirstChild(); pNode; pNode = pNode->GetNextSibling()) { if (pNode->GetElementType() == eProperty) { iCount++; if (iCount > index) return {pNode, iCount}; } } return {nullptr, iCount}; } CXFA_Node* CXFA_Node::GetOrCreateProperty(int32_t index, XFA_Element eProperty) { if (index < 0 || index >= PropertyOccurrenceCount(eProperty)) return nullptr; int32_t iCount = 0; CXFA_Node* node; std::tie(node, iCount) = GetProperty(index, eProperty); if (node) return node; if (HasPropertyFlag(eProperty, XFA_PropertyFlag::kOneOf)) { for (CXFA_Node* pNode = GetFirstChild(); pNode; pNode = pNode->GetNextSibling()) { if (HasPropertyFlag(pNode->GetElementType(), XFA_PropertyFlag::kOneOf)) { return nullptr; } } } CXFA_Node* pNewNode = nullptr; for (; iCount <= index; ++iCount) { pNewNode = GetDocument()->CreateNode(GetPacketType(), eProperty); if (!pNewNode) return nullptr; InsertChildAndNotify(pNewNode, nullptr); pNewNode->SetInitializedFlagAndNotify(); } return pNewNode; } absl::optional CXFA_Node::GetFirstPropertyWithFlag( XFA_PropertyFlag flag) const { for (const auto& prop : m_Properties) { if (prop.flags & flag) return prop.property; } return absl::nullopt; } const CXFA_Node::AttributeData* CXFA_Node::GetAttributeData( XFA_Attribute attr) const { DCHECK(attr != XFA_Attribute::Unknown); for (const auto& cur_attr : m_Attributes) { if (cur_attr.attribute == attr) return &cur_attr; } return nullptr; } bool CXFA_Node::HasAttribute(XFA_Attribute attr) const { return !!GetAttributeData(attr); } XFA_Attribute CXFA_Node::GetAttribute(size_t i) const { return i < m_Attributes.size() ? m_Attributes[i].attribute : XFA_Attribute::Unknown; } XFA_AttributeType CXFA_Node::GetAttributeType(XFA_Attribute type) const { const AttributeData* data = GetAttributeData(type); return data ? data->type : XFA_AttributeType::CData; } std::vector CXFA_Node::GetNodeListForType(XFA_Element eTypeFilter) { std::vector nodes; for (CXFA_Node* pChild = GetFirstChild(); pChild; pChild = pChild->GetNextSibling()) { if (pChild->GetElementType() == eTypeFilter) nodes.push_back(pChild); } return nodes; } std::vector CXFA_Node::GetNodeListWithFilter( Mask dwFilter) { if (!dwFilter) return std::vector(); const bool bFilterChildren = !!(dwFilter & XFA_NodeFilter::kChildren); const bool bFilterProperties = !!(dwFilter & XFA_NodeFilter::kProperties); const bool bFilterOneOfProperties = !!(dwFilter & XFA_NodeFilter::kOneOfProperty); std::vector nodes; if (bFilterChildren && bFilterProperties && !bFilterOneOfProperties) { for (CXFA_Node* pChild = GetFirstChild(); pChild; pChild = pChild->GetNextSibling()) { nodes.push_back(pChild); } return nodes; } for (CXFA_Node* pChild = GetFirstChild(); pChild; pChild = pChild->GetNextSibling()) { if (HasProperty(pChild->GetElementType())) { if (bFilterProperties) { nodes.push_back(pChild); } else if (bFilterOneOfProperties && HasPropertyFlag(pChild->GetElementType(), XFA_PropertyFlag::kOneOf)) { nodes.push_back(pChild); } else if (bFilterChildren && (pChild->GetElementType() == XFA_Element::Variables || pChild->GetElementType() == XFA_Element::PageSet)) { nodes.push_back(pChild); } } else if (bFilterChildren) { nodes.push_back(pChild); } } if (!bFilterOneOfProperties || !nodes.empty()) return nodes; absl::optional property = GetFirstPropertyWithFlag(XFA_PropertyFlag::kDefaultOneOf); if (!property.has_value()) return nodes; CXFA_Node* pNewNode = m_pDocument->CreateNode(GetPacketType(), property.value()); if (pNewNode) { InsertChildAndNotify(pNewNode, nullptr); pNewNode->SetInitializedFlagAndNotify(); nodes.push_back(pNewNode); } return nodes; } CXFA_Node* CXFA_Node::CreateSamePacketNode(XFA_Element eType) { CXFA_Node* pNode = m_pDocument->CreateNode(m_ePacket, eType); if (!pNode) return nullptr; pNode->SetInitializedFlagAndNotify(); return pNode; } CXFA_Node* CXFA_Node::CloneTemplateToForm(bool bRecursive) { DCHECK_EQ(m_ePacket, XFA_PacketType::Template); CXFA_Node* pClone = m_pDocument->CreateNode(XFA_PacketType::Form, m_elementType); if (!pClone) return nullptr; pClone->SetTemplateNode(this); pClone->UpdateNameHash(); pClone->SetXMLMappingNode(GetXMLMappingNode()); if (bRecursive) { for (CXFA_Node* pChild = GetFirstChild(); pChild; pChild = pChild->GetNextSibling()) { pClone->InsertChildAndNotify(pChild->CloneTemplateToForm(bRecursive), nullptr); } } pClone->SetInitializedFlagAndNotify(); return pClone; } CXFA_Node* CXFA_Node::GetTemplateNodeIfExists() const { return m_pAuxNode; } void CXFA_Node::SetTemplateNode(CXFA_Node* pTemplateNode) { m_pAuxNode = pTemplateNode; } CXFA_Node* CXFA_Node::GetBindData() { DCHECK_EQ(GetPacketType(), XFA_PacketType::Form); return GetBindingNode(); } std::vector CXFA_Node::GetBindItemsCopy() const { return std::vector(binding_nodes_.begin(), binding_nodes_.end()); } void CXFA_Node::AddBindItem(CXFA_Node* pFormNode) { DCHECK(pFormNode); if (BindsFormItems()) { if (!pdfium::Contains(binding_nodes_, pFormNode)) binding_nodes_.emplace_back(pFormNode); return; } CXFA_Node* pOldFormItem = GetBindingNode(); if (!pOldFormItem) { SetBindingNode(pFormNode); return; } if (pOldFormItem == pFormNode) return; binding_nodes_.clear(); binding_nodes_.push_back(pOldFormItem); binding_nodes_.push_back(pFormNode); m_uNodeFlags |= XFA_NodeFlag::kBindFormItems; } bool CXFA_Node::RemoveBindItem(CXFA_Node* pFormNode) { if (BindsFormItems()) { auto it = std::find(binding_nodes_.begin(), binding_nodes_.end(), pFormNode); if (it != binding_nodes_.end()) binding_nodes_.erase(it); if (binding_nodes_.size() == 1) { m_uNodeFlags.Clear(XFA_NodeFlag::kBindFormItems); return true; } return !binding_nodes_.empty(); } CXFA_Node* pOldFormItem = GetBindingNode(); if (pOldFormItem != pFormNode) return !!pOldFormItem; SetBindingNode(nullptr); return false; } bool CXFA_Node::HasBindItem() const { return GetPacketType() == XFA_PacketType::Datasets && GetBindingNode(); } CXFA_Node* CXFA_Node::GetContainerNode() { if (GetPacketType() != XFA_PacketType::Form) return nullptr; XFA_Element eType = GetElementType(); if (eType == XFA_Element::ExclGroup) return nullptr; CXFA_Node* pParentNode = GetParent(); if (pParentNode && pParentNode->GetElementType() == XFA_Element::ExclGroup) return nullptr; if (eType == XFA_Element::Field) { if (IsChoiceListMultiSelect()) return nullptr; WideString wsPicture = GetPictureContent(XFA_ValuePicture::kDataBind); if (!wsPicture.IsEmpty()) return this; CXFA_Node* pDataNode = GetBindData(); if (!pDataNode) return nullptr; CXFA_Node* pFieldNode = nullptr; for (auto* pFormNode : pDataNode->GetBindItemsCopy()) { if (!pFormNode || pFormNode->HasRemovedChildren()) continue; pFieldNode = pFormNode->IsWidgetReady() ? pFormNode : nullptr; if (pFieldNode) wsPicture = pFieldNode->GetPictureContent(XFA_ValuePicture::kDataBind); if (!wsPicture.IsEmpty()) break; pFieldNode = nullptr; } return pFieldNode; } CXFA_Node* pGrandNode = pParentNode ? pParentNode->GetParent() : nullptr; CXFA_Node* pValueNode = (pParentNode && pParentNode->GetElementType() == XFA_Element::Value) ? pParentNode : nullptr; if (!pValueNode) { pValueNode = (pGrandNode && pGrandNode->GetElementType() == XFA_Element::Value) ? pGrandNode : nullptr; } CXFA_Node* pParentOfValueNode = pValueNode ? pValueNode->GetParent() : nullptr; return pParentOfValueNode ? pParentOfValueNode->GetContainerNode() : nullptr; } GCedLocaleIface* CXFA_Node::GetLocale() { absl::optional localeName = GetLocaleName(); if (!localeName.has_value()) return nullptr; if (localeName.value().EqualsASCII("ambient")) return GetDocument()->GetLocaleMgr()->GetDefLocale(); return GetDocument()->GetLocaleMgr()->GetLocaleByName(localeName.value()); } absl::optional CXFA_Node::GetLocaleName() { CXFA_Node* pForm = ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form)); if (!pForm) return absl::nullopt; CXFA_Subform* pTopSubform = pForm->GetFirstChildByClass(XFA_Element::Subform); if (!pTopSubform) return absl::nullopt; absl::optional localeName; CXFA_Node* pLocaleNode = this; do { localeName = pLocaleNode->JSObject()->TryCData(XFA_Attribute::Locale, false); if (localeName.has_value()) return localeName; pLocaleNode = pLocaleNode->GetParent(); } while (pLocaleNode && pLocaleNode != pTopSubform); CXFA_Node* pConfig = ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Config)); localeName = GetDocument()->GetLocaleMgr()->GetConfigLocaleName(pConfig); if (localeName.has_value()) return localeName; if (pTopSubform) { localeName = pTopSubform->JSObject()->TryCData(XFA_Attribute::Locale, false); if (localeName.has_value()) return localeName; } LocaleIface* pLocale = GetDocument()->GetLocaleMgr()->GetDefLocale(); if (!pLocale) return absl::nullopt; return pLocale->GetName(); } XFA_AttributeValue CXFA_Node::GetIntact() { CXFA_Keep* pKeep = GetFirstChildByClass(XFA_Element::Keep); auto layout = JSObject()->TryEnum(XFA_Attribute::Layout, true); XFA_AttributeValue eLayoutType = layout.value_or(XFA_AttributeValue::Position); if (pKeep) { absl::optional intact = GetIntactFromKeep(pKeep, eLayoutType); if (intact.has_value()) return intact.value(); } switch (GetElementType()) { case XFA_Element::Subform: switch (eLayoutType) { case XFA_AttributeValue::Position: case XFA_AttributeValue::Row: return XFA_AttributeValue::ContentArea; default: return XFA_AttributeValue::None; } case XFA_Element::Field: { CXFA_Node* parent = GetParent(); if (!parent || parent->GetElementType() == XFA_Element::PageArea) return XFA_AttributeValue::ContentArea; if (parent->GetIntact() != XFA_AttributeValue::None) return XFA_AttributeValue::ContentArea; auto value = parent->JSObject()->TryEnum(XFA_Attribute::Layout, true); XFA_AttributeValue eParLayout = value.value_or(XFA_AttributeValue::Position); if (eParLayout == XFA_AttributeValue::Position || eParLayout == XFA_AttributeValue::Row || eParLayout == XFA_AttributeValue::Table) { return XFA_AttributeValue::None; } XFA_VERSION version = m_pDocument->GetCurVersionMode(); if (eParLayout == XFA_AttributeValue::Tb && version < XFA_VERSION_208) { absl::optional measureH = JSObject()->TryMeasure(XFA_Attribute::H, false); if (measureH.has_value()) return XFA_AttributeValue::ContentArea; } return XFA_AttributeValue::None; } case XFA_Element::Draw: return XFA_AttributeValue::ContentArea; default: return XFA_AttributeValue::None; } } WideString CXFA_Node::GetNameExpression() { WideString wsName = GetNameExpressionSinglePath(this); CXFA_Node* parent = GetParent(); while (parent) { WideString wsParent = GetNameExpressionSinglePath(parent); wsParent += L"."; wsParent += wsName; wsName = std::move(wsParent); parent = parent->GetParent(); } return wsName; } CXFA_Node* CXFA_Node::GetDataDescriptionNode() { if (m_ePacket == XFA_PacketType::Datasets) return m_pAuxNode; return nullptr; } void CXFA_Node::SetDataDescriptionNode(CXFA_Node* pDataDescriptionNode) { DCHECK_EQ(m_ePacket, XFA_PacketType::Datasets); m_pAuxNode = pDataDescriptionNode; } CXFA_Node* CXFA_Node::GetModelNode() { switch (GetPacketType()) { case XFA_PacketType::Xdp: return m_pDocument->GetRoot(); case XFA_PacketType::Config: return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Config)); case XFA_PacketType::Template: return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Template)); case XFA_PacketType::Form: return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Form)); case XFA_PacketType::Datasets: return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Datasets)); case XFA_PacketType::LocaleSet: return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_LocaleSet)); case XFA_PacketType::ConnectionSet: return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_ConnectionSet)); case XFA_PacketType::SourceSet: return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_SourceSet)); case XFA_PacketType::Xdc: return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Xdc)); default: return this; } } size_t CXFA_Node::CountChildren(XFA_Element eType, bool bOnlyChild) { size_t count = 0; for (CXFA_Node* pNode = GetFirstChild(); pNode; pNode = pNode->GetNextSibling()) { if (pNode->GetElementType() != eType && eType != XFA_Element::Unknown) continue; if (bOnlyChild && HasProperty(pNode->GetElementType())) continue; ++count; } return count; } CXFA_Node* CXFA_Node::GetChildInternal(size_t index, XFA_Element eType, bool bOnlyChild) const { size_t count = 0; for (CXFA_Node* pNode = GetFirstChild(); pNode; pNode = pNode->GetNextSibling()) { if (pNode->GetElementType() != eType && eType != XFA_Element::Unknown) continue; if (bOnlyChild && HasProperty(pNode->GetElementType())) continue; if (count == index) return pNode; ++count; } return nullptr; } bool CXFA_Node::IsAncestorOf(const CXFA_Node* that) const { while (that) { if (this == that) return true; that = that->GetParent(); } return false; } void CXFA_Node::InsertChildAndNotify(int32_t index, CXFA_Node* pNode) { InsertChildAndNotify(pNode, GetNthChild(index)); } void CXFA_Node::InsertChildAndNotify(CXFA_Node* pNode, CXFA_Node* pBeforeNode) { CHECK(!pNode->GetParent()); CHECK(!pBeforeNode || pBeforeNode->GetParent() == this); pNode->ClearFlag(XFA_NodeFlag::kHasRemovedChildren); InsertBefore(pNode, pBeforeNode); CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); if (pNotify) pNotify->OnChildAdded(this); if (!IsNeedSavingXMLNode() || !pNode->xml_node_) return; DCHECK(!pNode->xml_node_->GetParent()); xml_node_->InsertBefore(pNode->xml_node_, pBeforeNode ? pBeforeNode->xml_node_ : nullptr); } void CXFA_Node::RemoveChildAndNotify(CXFA_Node* pNode, bool bNotify) { CHECK(pNode); if (pNode->GetParent() != this) return; pNode->SetFlag(XFA_NodeFlag::kHasRemovedChildren); GCedTreeNodeMixin::RemoveChild(pNode); OnRemoved(bNotify); if (!IsNeedSavingXMLNode() || !pNode->xml_node_) return; if (!pNode->IsAttributeInXML()) { xml_node_->RemoveChild(pNode->xml_node_); return; } DCHECK_EQ(pNode->xml_node_, xml_node_); CFX_XMLElement* pXMLElement = ToXMLElement(pNode->xml_node_); if (pXMLElement) { WideString wsAttributeName = pNode->JSObject()->GetCData(XFA_Attribute::QualifiedName); pXMLElement->RemoveAttribute(wsAttributeName); } WideString wsName = pNode->JSObject() ->TryAttribute(XFA_Attribute::Name, false) .value_or(WideString()); auto* pNewXMLElement = GetXMLDocument()->CreateNode(wsName); WideString wsValue = JSObject()->GetCData(XFA_Attribute::Value); if (!wsValue.IsEmpty()) { auto* text = GetXMLDocument()->CreateNode(wsValue); pNewXMLElement->AppendLastChild(text); } pNode->xml_node_ = pNewXMLElement; pNode->JSObject()->SetEnum(XFA_Attribute::Contains, XFA_AttributeValue::Unknown, false); } CXFA_Node* CXFA_Node::GetFirstChildByName(WideStringView wsName) const { return GetFirstChildByName(FX_HashCode_GetW(wsName)); } CXFA_Node* CXFA_Node::GetFirstChildByName(uint32_t dwNameHash) const { for (CXFA_Node* pNode = GetFirstChild(); pNode; pNode = pNode->GetNextSibling()) { if (pNode->GetNameHash() == dwNameHash) return pNode; } return nullptr; } CXFA_Node* CXFA_Node::GetFirstChildByClassInternal(XFA_Element eType) const { for (CXFA_Node* pNode = GetFirstChild(); pNode; pNode = pNode->GetNextSibling()) { if (pNode->GetElementType() == eType) return pNode; } return nullptr; } CXFA_Node* CXFA_Node::GetNextSameNameSibling(uint32_t dwNameHash) const { for (CXFA_Node* pNode = GetNextSibling(); pNode; pNode = pNode->GetNextSibling()) { if (pNode->GetNameHash() == dwNameHash) return pNode; } return nullptr; } CXFA_Node* CXFA_Node::GetNextSameNameSiblingInternal( WideStringView wsNodeName) const { return GetNextSameNameSibling(FX_HashCode_GetW(wsNodeName)); } CXFA_Node* CXFA_Node::GetNextSameClassSiblingInternal(XFA_Element eType) const { for (CXFA_Node* pNode = GetNextSibling(); pNode; pNode = pNode->GetNextSibling()) { if (pNode->GetElementType() == eType) return pNode; } return nullptr; } CXFA_Node* CXFA_Node::GetOneChildNamed(WideStringView wsName) { return FindFirstSiblingNamed(this, FX_HashCode_GetW(wsName)); } CXFA_Node* CXFA_Node::GetOneChildOfClass(WideStringView wsClass) { XFA_Element element = XFA_GetElementByName(wsClass); if (element == XFA_Element::Unknown) return nullptr; return FindFirstSiblingOfClass(this, element); } std::vector CXFA_Node::GetSiblings(bool bIsClassName) { std::vector siblings; CXFA_Node* parent = GetParent(); if (!parent) return siblings; if (!parent->HasProperty(GetElementType())) { parent = GetTransparentParent(); if (!parent) return siblings; } uint32_t dwNameHash = bIsClassName ? GetClassHashCode() : GetNameHash(); TraversePropertiesOrSiblings(parent, dwNameHash, &siblings, bIsClassName); return siblings; } size_t CXFA_Node::GetIndex(bool bIsProperty, bool bIsClassIndex) { CXFA_Node* parent = GetParent(); if (!parent) return 0; if (!bIsProperty) { parent = GetTransparentParent(); if (!parent) return 0; } uint32_t dwHashName = bIsClassIndex ? GetClassHashCode() : GetNameHash(); std::vector siblings; TraversePropertiesOrSiblings(parent, dwHashName, &siblings, bIsClassIndex); for (size_t i = 0; i < siblings.size(); ++i) { if (siblings[i] == this) return i; } return 0; } size_t CXFA_Node::GetIndexByName() { return GetIndex(IsProperty(), /*bIsClassIndex=*/false); } size_t CXFA_Node::GetIndexByClassName() { return GetIndex(IsProperty(), /*bIsClassIndex=*/true); } CXFA_Node* CXFA_Node::GetInstanceMgrOfSubform() { CXFA_Node* pInstanceMgr = nullptr; if (m_ePacket == XFA_PacketType::Form) { CXFA_Node* pParentNode = GetParent(); if (!pParentNode || pParentNode->GetElementType() == XFA_Element::Area) return pInstanceMgr; for (CXFA_Node* pNode = GetPrevSibling(); pNode; pNode = pNode->GetPrevSibling()) { XFA_Element eType = pNode->GetElementType(); if ((eType == XFA_Element::Subform || eType == XFA_Element::SubformSet) && pNode->m_dwNameHash != m_dwNameHash) { break; } if (eType == XFA_Element::InstanceManager) { WideString wsName = JSObject()->GetCData(XFA_Attribute::Name); WideString wsInstName = pNode->JSObject()->GetCData(XFA_Attribute::Name); if (wsInstName.GetLength() > 0 && wsInstName[0] == '_' && wsInstName.Last(wsInstName.GetLength() - 1) == wsName) { pInstanceMgr = pNode; } break; } } } return pInstanceMgr; } CXFA_Occur* CXFA_Node::GetOccurIfExists() { return GetFirstChildByClass(XFA_Element::Occur); } bool CXFA_Node::HasFlag(XFA_NodeFlag dwFlag) const { if (m_uNodeFlags & dwFlag) return true; if (dwFlag == XFA_NodeFlag::kHasRemovedChildren) return GetParent() && GetParent()->HasFlag(dwFlag); return false; } void CXFA_Node::SetInitializedFlagAndNotify() { if (!IsInitialized()) { CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); if (pNotify) pNotify->OnNodeReady(this); } m_uNodeFlags |= XFA_NodeFlag::kInitialized; } void CXFA_Node::SetFlag(XFA_NodeFlag dwFlag) { m_uNodeFlags |= dwFlag; } void CXFA_Node::ClearFlag(XFA_NodeFlag dwFlag) { m_uNodeFlags.Clear(dwFlag); } bool CXFA_Node::IsAttributeInXML() { return JSObject()->GetEnum(XFA_Attribute::Contains) == XFA_AttributeValue::MetaData; } void CXFA_Node::OnRemoved(bool bNotify) const { if (!bNotify) return; CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); if (pNotify) pNotify->OnChildRemoved(); } void CXFA_Node::UpdateNameHash() { WideString wsName = JSObject()->GetCData(XFA_Attribute::Name); m_dwNameHash = FX_HashCode_GetW(wsName.AsStringView()); } CFX_XMLNode* CXFA_Node::CreateXMLMappingNode() { if (!xml_node_) { xml_node_ = GetXMLDocument()->CreateNode( JSObject()->GetCData(XFA_Attribute::Name)); } return xml_node_; } bool CXFA_Node::IsNeedSavingXMLNode() const { return xml_node_ && (GetPacketType() == XFA_PacketType::Datasets || GetElementType() == XFA_Element::Xfa); } CXFA_Node* CXFA_Node::GetItemIfExists(int32_t iIndex) { int32_t iCount = 0; uint32_t dwNameHash = 0; for (CXFA_Node* pNode = GetNextSibling(); pNode; pNode = pNode->GetNextSibling()) { XFA_Element eCurType = pNode->GetElementType(); if (eCurType == XFA_Element::InstanceManager) break; if ((eCurType != XFA_Element::Subform) && (eCurType != XFA_Element::SubformSet)) { continue; } if (iCount == 0) { WideString wsName = pNode->JSObject()->GetCData(XFA_Attribute::Name); WideString wsInstName = JSObject()->GetCData(XFA_Attribute::Name); if (wsInstName.GetLength() < 1 || wsInstName[0] != '_' || wsInstName.Last(wsInstName.GetLength() - 1) != wsName) { return nullptr; } dwNameHash = pNode->GetNameHash(); } if (dwNameHash != pNode->GetNameHash()) break; iCount++; if (iCount > iIndex) return pNode; } return nullptr; } int32_t CXFA_Node::GetCount() { int32_t iCount = 0; uint32_t dwNameHash = 0; for (CXFA_Node* pNode = GetNextSibling(); pNode; pNode = pNode->GetNextSibling()) { XFA_Element eCurType = pNode->GetElementType(); if (eCurType == XFA_Element::InstanceManager) break; if ((eCurType != XFA_Element::Subform) && (eCurType != XFA_Element::SubformSet)) { continue; } if (iCount == 0) { WideString wsName = pNode->JSObject()->GetCData(XFA_Attribute::Name); WideString wsInstName = JSObject()->GetCData(XFA_Attribute::Name); if (wsInstName.GetLength() < 1 || wsInstName[0] != '_' || wsInstName.Last(wsInstName.GetLength() - 1) != wsName) { return iCount; } dwNameHash = pNode->GetNameHash(); } if (dwNameHash != pNode->GetNameHash()) break; iCount++; } return iCount; } void CXFA_Node::InsertItem(CXFA_Node* pNewInstance, int32_t iPos, int32_t iCount, bool bMoveDataBindingNodes) { if (iCount < 0) iCount = GetCount(); if (iPos < 0) iPos = iCount; if (iPos == iCount) { CXFA_Node* item = GetItemIfExists(iCount - 1); if (!item) return; CXFA_Node* pNextSibling = iCount > 0 ? item->GetNextSibling() : GetNextSibling(); GetParent()->InsertChildAndNotify(pNewInstance, pNextSibling); if (bMoveDataBindingNodes) { NodeSet sNew; CXFA_NodeIteratorTemplate sIteratorNew(pNewInstance); for (CXFA_Node* pNode = sIteratorNew.GetCurrent(); pNode; pNode = sIteratorNew.MoveToNext()) { CXFA_Node* pDataNode = pNode->GetBindData(); if (pDataNode) sNew.insert(pDataNode); } NodeSet sAfter; CXFA_NodeIteratorTemplate sIteratorAfter(pNextSibling); for (CXFA_Node* pNode = sIteratorAfter.GetCurrent(); pNode; pNode = sIteratorAfter.MoveToNext()) { CXFA_Node* pDataNode = pNode->GetBindData(); if (pDataNode) sAfter.insert(pDataNode); } ReorderDataNodes(sNew, sAfter, false); } } else { CXFA_Node* pBeforeInstance = GetItemIfExists(iPos); if (!pBeforeInstance) { // TODO(dsinclair): What should happen here? return; } GetParent()->InsertChildAndNotify(pNewInstance, pBeforeInstance); if (bMoveDataBindingNodes) { NodeSet sNew; CXFA_NodeIteratorTemplate sIteratorNew(pNewInstance); for (CXFA_Node* pNode = sIteratorNew.GetCurrent(); pNode; pNode = sIteratorNew.MoveToNext()) { CXFA_Node* pDataNode = pNode->GetBindData(); if (pDataNode) sNew.insert(pDataNode); } NodeSet sBefore; CXFA_NodeIteratorTemplate sIteratorBefore(pBeforeInstance); for (CXFA_Node* pNode = sIteratorBefore.GetCurrent(); pNode; pNode = sIteratorBefore.MoveToNext()) { CXFA_Node* pDataNode = pNode->GetBindData(); if (pDataNode) sBefore.insert(pDataNode); } ReorderDataNodes(sNew, sBefore, true); } } } void CXFA_Node::RemoveItem(CXFA_Node* pRemoveInstance, bool bRemoveDataBinding) { GetParent()->RemoveChildAndNotify(pRemoveInstance, true); if (!bRemoveDataBinding) return; CXFA_NodeIteratorTemplate sIterator(pRemoveInstance); for (CXFA_Node* pFormNode = sIterator.GetCurrent(); pFormNode; pFormNode = sIterator.MoveToNext()) { CXFA_Node* pDataNode = pFormNode->GetBindData(); if (!pDataNode) continue; if (!pDataNode->RemoveBindItem(pFormNode)) { if (CXFA_Node* pDataParent = pDataNode->GetParent()) { pDataParent->RemoveChildAndNotify(pDataNode, true); } } pFormNode->SetBindingNode(nullptr); } } CXFA_Node* CXFA_Node::CreateInstanceIfPossible(bool bDataMerge) { CXFA_Document* pDocument = GetDocument(); CXFA_Node* pTemplateNode = GetTemplateNodeIfExists(); if (!pTemplateNode) return nullptr; CXFA_Node* pFormParent = GetParent(); CXFA_Node* pDataScope = nullptr; for (CXFA_Node* pRootBoundNode = pFormParent; pRootBoundNode && pRootBoundNode->IsContainerNode(); pRootBoundNode = pRootBoundNode->GetParent()) { pDataScope = pRootBoundNode->GetBindData(); if (pDataScope) break; } if (!pDataScope) { pDataScope = ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Record)); DCHECK(pDataScope); } CXFA_Node* pInstance = pDocument->DataMerge_CopyContainer( pTemplateNode, pFormParent, pDataScope, true, bDataMerge, true); if (pInstance) { pDocument->DataMerge_UpdateBindingRelations(pInstance); pFormParent->RemoveChildAndNotify(pInstance, true); } return pInstance; } absl::optional CXFA_Node::GetDefaultBoolean(XFA_Attribute attr) const { absl::optional value = GetDefaultValue(attr, XFA_AttributeType::Boolean); if (!value.has_value()) return absl::nullopt; return !!value.value(); } absl::optional CXFA_Node::GetDefaultInteger(XFA_Attribute attr) const { absl::optional value = GetDefaultValue(attr, XFA_AttributeType::Integer); if (!value.has_value()) return absl::nullopt; return static_cast(reinterpret_cast(value.value())); } absl::optional CXFA_Node::GetDefaultMeasurement( XFA_Attribute attr) const { absl::optional value = GetDefaultValue(attr, XFA_AttributeType::Measure); if (!value.has_value()) return absl::nullopt; WideString str = WideString(static_cast(value.value())); return CXFA_Measurement(str.AsStringView()); } absl::optional CXFA_Node::GetDefaultCData( XFA_Attribute attr) const { absl::optional value = GetDefaultValue(attr, XFA_AttributeType::CData); if (!value.has_value()) return absl::nullopt; return WideString(static_cast(value.value())); } absl::optional CXFA_Node::GetDefaultEnum( XFA_Attribute attr) const { absl::optional value = GetDefaultValue(attr, XFA_AttributeType::Enum); if (!value.has_value()) return absl::nullopt; return static_cast( reinterpret_cast(value.value())); } absl::optional CXFA_Node::GetDefaultValue( XFA_Attribute attr, XFA_AttributeType eType) const { const AttributeData* data = GetAttributeData(attr); if (!data || data->type != eType) return absl::nullopt; return data->default_value; } void CXFA_Node::SendAttributeChangeMessage(XFA_Attribute eAttribute, bool bScriptModify) { CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); if (!pNotify) return; if (GetPacketType() != XFA_PacketType::Form) { pNotify->OnValueChanged(this, eAttribute, this, this); return; } bool bNeedFindContainer = false; switch (GetElementType()) { case XFA_Element::Caption: bNeedFindContainer = true; pNotify->OnValueChanged(this, eAttribute, this, GetParent()); break; case XFA_Element::Font: case XFA_Element::Para: { bNeedFindContainer = true; CXFA_Node* pParentNode = GetParent(); if (pParentNode->GetElementType() == XFA_Element::Caption) { pNotify->OnValueChanged(this, eAttribute, pParentNode, pParentNode->GetParent()); } else { pNotify->OnValueChanged(this, eAttribute, this, pParentNode); } break; } case XFA_Element::Margin: { bNeedFindContainer = true; CXFA_Node* pParentNode = GetParent(); XFA_Element eParentType = pParentNode->GetElementType(); if (pParentNode->IsContainerNode()) { pNotify->OnValueChanged(this, eAttribute, this, pParentNode); } else if (eParentType == XFA_Element::Caption) { pNotify->OnValueChanged(this, eAttribute, pParentNode, pParentNode->GetParent()); } else { CXFA_Node* pNode = pParentNode->GetParent(); if (pNode && pNode->GetElementType() == XFA_Element::Ui) pNotify->OnValueChanged(this, eAttribute, pNode, pNode->GetParent()); } break; } case XFA_Element::Comb: { CXFA_Node* pEditNode = GetParent(); XFA_Element eUIType = pEditNode->GetElementType(); if (pEditNode && (eUIType == XFA_Element::DateTimeEdit || eUIType == XFA_Element::NumericEdit || eUIType == XFA_Element::TextEdit)) { CXFA_Node* pUINode = pEditNode->GetParent(); if (pUINode) { pNotify->OnValueChanged(this, eAttribute, pUINode, pUINode->GetParent()); } } break; } case XFA_Element::Button: case XFA_Element::Barcode: case XFA_Element::ChoiceList: case XFA_Element::DateTimeEdit: case XFA_Element::NumericEdit: case XFA_Element::PasswordEdit: case XFA_Element::TextEdit: { CXFA_Node* pUINode = GetParent(); if (pUINode) { pNotify->OnValueChanged(this, eAttribute, pUINode, pUINode->GetParent()); } break; } case XFA_Element::CheckButton: { bNeedFindContainer = true; CXFA_Node* pUINode = GetParent(); if (pUINode) { pNotify->OnValueChanged(this, eAttribute, pUINode, pUINode->GetParent()); } break; } case XFA_Element::Keep: case XFA_Element::Bookend: case XFA_Element::Break: case XFA_Element::BreakAfter: case XFA_Element::BreakBefore: case XFA_Element::Overflow: bNeedFindContainer = true; break; case XFA_Element::Area: case XFA_Element::Draw: case XFA_Element::ExclGroup: case XFA_Element::Field: case XFA_Element::Subform: case XFA_Element::SubformSet: pNotify->OnContainerChanged(); pNotify->OnValueChanged(this, eAttribute, this, this); break; case XFA_Element::Sharptext: case XFA_Element::Sharpxml: case XFA_Element::SharpxHTML: { CXFA_Node* pTextNode = GetParent(); if (!pTextNode) return; CXFA_Node* pValueNode = pTextNode->GetParent(); if (!pValueNode) return; XFA_Element eType = pValueNode->GetElementType(); if (eType == XFA_Element::Value) { bNeedFindContainer = true; CXFA_Node* pNode = pValueNode->GetParent(); if (pNode && pNode->IsContainerNode()) { if (bScriptModify) pValueNode = pNode; pNotify->OnValueChanged(this, eAttribute, pValueNode, pNode); } else { pNotify->OnValueChanged(this, eAttribute, pNode, pNode->GetParent()); } } else { if (eType == XFA_Element::Items) { CXFA_Node* pNode = pValueNode->GetParent(); if (pNode && pNode->IsContainerNode()) { pNotify->OnValueChanged(this, eAttribute, pValueNode, pNode); } } } break; } default: break; } if (!bNeedFindContainer) return; CXFA_Node* pParent = this; while (pParent && !pParent->IsContainerNode()) pParent = pParent->GetParent(); if (pParent) pNotify->OnContainerChanged(); } void CXFA_Node::SyncValue(const WideString& wsValue, bool bNotify) { WideString wsFormatValue = wsValue; CXFA_Node* pContainerNode = GetContainerNode(); if (pContainerNode) wsFormatValue = pContainerNode->GetFormatDataValue(wsValue); JSObject()->SetContent(wsValue, wsFormatValue, bNotify, false, true); } WideString CXFA_Node::GetRawValue() const { return JSObject()->GetContent(false); } int32_t CXFA_Node::GetRotate() const { absl::optional degrees = JSObject()->TryInteger(XFA_Attribute::Rotate, false); return degrees.has_value() ? XFA_MapRotation(degrees.value()) / 90 * 90 : 0; } CXFA_Border* CXFA_Node::GetBorderIfExists() const { return JSObject()->GetProperty(0, XFA_Element::Border); } CXFA_Border* CXFA_Node::GetOrCreateBorderIfPossible() { return JSObject()->GetOrCreateProperty(0, XFA_Element::Border); } CXFA_Caption* CXFA_Node::GetCaptionIfExists() const { return JSObject()->GetProperty(0, XFA_Element::Caption); } CXFA_Font* CXFA_Node::GetOrCreateFontIfPossible() { return JSObject()->GetOrCreateProperty(0, XFA_Element::Font); } CXFA_Font* CXFA_Node::GetFontIfExists() const { return JSObject()->GetProperty(0, XFA_Element::Font); } float CXFA_Node::GetFontSize() const { CXFA_Font* font = GetFontIfExists(); float fFontSize = font ? font->GetFontSize() : 10.0f; return fFontSize < 0.1f ? 10.0f : fFontSize; } float CXFA_Node::GetLineHeight() const { float fLineHeight = 0; CXFA_Para* para = GetParaIfExists(); if (para) fLineHeight = para->GetLineHeight(); if (fLineHeight < 1) fLineHeight = GetFontSize() * 1.2f; return fLineHeight; } FX_ARGB CXFA_Node::GetTextColor() const { CXFA_Font* font = GetFontIfExists(); return font ? font->GetColor() : 0xFF000000; } CXFA_Margin* CXFA_Node::GetMarginIfExists() const { return JSObject()->GetProperty(0, XFA_Element::Margin); } CXFA_Para* CXFA_Node::GetParaIfExists() const { return JSObject()->GetProperty(0, XFA_Element::Para); } bool CXFA_Node::IsOpenAccess() const { for (auto* pNode = this; pNode; pNode = pNode->GetContainerParent()) { XFA_AttributeValue iAcc = pNode->JSObject()->GetEnum(XFA_Attribute::Access); if (iAcc != XFA_AttributeValue::Open) return false; } return true; } CXFA_Value* CXFA_Node::GetDefaultValueIfExists() { CXFA_Node* pTemNode = GetTemplateNodeIfExists(); return pTemNode ? pTemNode->JSObject()->GetProperty( 0, XFA_Element::Value) : nullptr; } CXFA_Value* CXFA_Node::GetFormValueIfExists() const { return JSObject()->GetProperty(0, XFA_Element::Value); } CXFA_Calculate* CXFA_Node::GetCalculateIfExists() const { return JSObject()->GetProperty(0, XFA_Element::Calculate); } CXFA_Validate* CXFA_Node::GetValidateIfExists() const { return JSObject()->GetProperty(0, XFA_Element::Validate); } CXFA_Validate* CXFA_Node::GetOrCreateValidateIfPossible() { return JSObject()->GetOrCreateProperty(0, XFA_Element::Validate); } CXFA_Bind* CXFA_Node::GetBindIfExists() const { return JSObject()->GetProperty(0, XFA_Element::Bind); } absl::optional CXFA_Node::GetIntactFromKeep( const CXFA_Keep* pKeep, XFA_AttributeValue eLayoutType) const { absl::optional intact = pKeep->JSObject()->TryEnum(XFA_Attribute::Intact, false); if (!intact.has_value()) return absl::nullopt; if (intact.value() != XFA_AttributeValue::None || eLayoutType != XFA_AttributeValue::Row || m_pDocument->GetCurVersionMode() >= XFA_VERSION_208) { return intact; } CXFA_Node* pPreviewRow = GetPrevContainerSibling(); if (!pPreviewRow || pPreviewRow->JSObject()->GetEnum(XFA_Attribute::Layout) != XFA_AttributeValue::Row) { return intact; } absl::optional value = pKeep->JSObject()->TryEnum(XFA_Attribute::Previous, false); if (value == XFA_AttributeValue::ContentArea || value == XFA_AttributeValue::PageArea) { return XFA_AttributeValue::ContentArea; } CXFA_Keep* pNode = pPreviewRow->GetFirstChildByClass(XFA_Element::Keep); if (!pNode) return intact; absl::optional ret = pNode->JSObject()->TryEnum(XFA_Attribute::Next, false); if (ret == XFA_AttributeValue::ContentArea || ret == XFA_AttributeValue::PageArea) { return XFA_AttributeValue::ContentArea; } return intact; } absl::optional CXFA_Node::TryWidth() { return JSObject()->TryMeasureAsFloat(XFA_Attribute::W); } absl::optional CXFA_Node::TryHeight() { return JSObject()->TryMeasureAsFloat(XFA_Attribute::H); } absl::optional CXFA_Node::TryMinWidth() { return JSObject()->TryMeasureAsFloat(XFA_Attribute::MinW); } absl::optional CXFA_Node::TryMinHeight() { return JSObject()->TryMeasureAsFloat(XFA_Attribute::MinH); } absl::optional CXFA_Node::TryMaxWidth() { return JSObject()->TryMeasureAsFloat(XFA_Attribute::MaxW); } absl::optional CXFA_Node::TryMaxHeight() { return JSObject()->TryMeasureAsFloat(XFA_Attribute::MaxH); } CXFA_Node* CXFA_Node::GetExclGroupIfExists() { CXFA_Node* pExcl = GetParent(); if (!pExcl || pExcl->GetElementType() != XFA_Element::ExclGroup) return nullptr; return pExcl; } XFA_EventError CXFA_Node::ProcessEvent(CXFA_FFDocView* pDocView, XFA_AttributeValue iActivity, CXFA_EventParam* pEventParam) { if (GetElementType() == XFA_Element::Draw) return XFA_EventError::kNotExist; std::vector eventArray = GetEventByActivity(iActivity, pEventParam->m_bIsFormReady); bool first = true; XFA_EventError iRet = XFA_EventError::kNotExist; for (CXFA_Event* event : eventArray) { XFA_EventError result = ProcessEventInternal(pDocView, iActivity, event, pEventParam); if (first || result == XFA_EventError::kSuccess) iRet = result; first = false; } return iRet; } XFA_EventError CXFA_Node::ProcessEventInternal(CXFA_FFDocView* pDocView, XFA_AttributeValue iActivity, CXFA_Event* event, CXFA_EventParam* pEventParam) { if (!event) return XFA_EventError::kNotExist; switch (event->GetEventType()) { case XFA_Element::Execute: break; case XFA_Element::Script: if (iActivity == XFA_AttributeValue::DocClose) { // Too late, scripting engine already gone. return XFA_EventError::kNotExist; } return ExecuteScript(pDocView, event->GetScriptIfExists(), pEventParam); case XFA_Element::SignData: break; case XFA_Element::Submit: { // TODO(crbug.com/867485): Submit is disabled for now. Fix it and reenable this // code. #ifdef PDF_XFA_ELEMENT_SUBMIT_ENABLED CXFA_Submit* submit = event->GetSubmitIfExists(); if (!submit) return XFA_EventError::kNotExist; return pDocView->GetDoc()->GetDocEnvironment()->Submit(pDocView->GetDoc(), submit); #else return XFA_EventError::kDisabled; #endif // PDF_XFA_ELEMENT_SUBMIT_ENABLED } default: break; } return XFA_EventError::kNotExist; } XFA_EventError CXFA_Node::ProcessCalculate(CXFA_FFDocView* pDocView) { if (GetElementType() == XFA_Element::Draw) return XFA_EventError::kNotExist; CXFA_Calculate* calc = GetCalculateIfExists(); if (!calc) return XFA_EventError::kNotExist; if (IsUserInteractive()) return XFA_EventError::kDisabled; CXFA_EventParam EventParam; EventParam.m_eType = XFA_EVENT_Calculate; EventParam.m_bTargeted = false; XFA_EventError iRet = ExecuteScript(pDocView, calc->GetScriptIfExists(), &EventParam); if (iRet != XFA_EventError::kSuccess) return iRet; if (GetRawValue() != EventParam.m_wsResult) { SetValue(XFA_ValuePicture::kRaw, EventParam.m_wsResult); pDocView->UpdateUIDisplay(this, nullptr); } return XFA_EventError::kSuccess; } void CXFA_Node::ProcessScriptTestValidate(CXFA_FFDocView* pDocView, CXFA_Validate* validate, bool bVersionFlag) { CXFA_FFApp::CallbackIface* pAppProvider = pDocView->GetDoc()->GetApp()->GetAppProvider(); if (!pAppProvider) return; WideString wsTitle = pAppProvider->GetAppTitle(); WideString wsScriptMsg = validate->GetScriptMessageText(); if (validate->GetScriptTest() == XFA_AttributeValue::Warning) { if (IsUserInteractive()) return; if (wsScriptMsg.IsEmpty()) wsScriptMsg = GetValidateMessage(false, bVersionFlag); if (bVersionFlag) { pAppProvider->MsgBox(wsScriptMsg, wsTitle, static_cast(AlertIcon::kWarning), static_cast(AlertButton::kOK)); return; } if (pAppProvider->MsgBox(wsScriptMsg, wsTitle, static_cast(AlertIcon::kWarning), static_cast(AlertButton::kYesNo)) == static_cast(AlertReturn::kYes)) { SetFlag(XFA_NodeFlag::kUserInteractive); } return; } if (wsScriptMsg.IsEmpty()) wsScriptMsg = GetValidateMessage(true, bVersionFlag); pAppProvider->MsgBox(wsScriptMsg, wsTitle, static_cast(AlertIcon::kError), static_cast(AlertButton::kOK)); } XFA_EventError CXFA_Node::ProcessFormatTestValidate(CXFA_FFDocView* pDocView, CXFA_Validate* validate, bool bVersionFlag) { WideString wsPicture = validate->GetPicture(); if (wsPicture.IsEmpty()) return XFA_EventError::kNotExist; WideString wsRawValue = GetRawValue(); if (wsRawValue.IsEmpty()) return XFA_EventError::kError; GCedLocaleIface* pLocale = GetLocale(); if (!pLocale) return XFA_EventError::kNotExist; CXFA_LocaleValue lcValue = XFA_GetLocaleValue(this); if (lcValue.ValidateValue(lcValue.GetValue(), wsPicture, pLocale, nullptr)) return XFA_EventError::kSuccess; CXFA_FFApp::CallbackIface* pAppProvider = pDocView->GetDoc()->GetApp()->GetAppProvider(); if (!pAppProvider) return XFA_EventError::kNotExist; WideString wsFormatMsg = validate->GetFormatMessageText(); WideString wsTitle = pAppProvider->GetAppTitle(); if (validate->GetFormatTest() == XFA_AttributeValue::Error) { if (wsFormatMsg.IsEmpty()) wsFormatMsg = GetValidateMessage(true, bVersionFlag); pAppProvider->MsgBox(wsFormatMsg, wsTitle, static_cast(AlertIcon::kError), static_cast(AlertButton::kOK)); return XFA_EventError::kError; } if (wsFormatMsg.IsEmpty()) wsFormatMsg = GetValidateMessage(false, bVersionFlag); if (bVersionFlag) { pAppProvider->MsgBox(wsFormatMsg, wsTitle, static_cast(AlertIcon::kWarning), static_cast(AlertButton::kOK)); return XFA_EventError::kError; } if (pAppProvider->MsgBox(wsFormatMsg, wsTitle, static_cast(AlertIcon::kWarning), static_cast(AlertButton::kYesNo)) == static_cast(AlertReturn::kYes)) { SetFlag(XFA_NodeFlag::kUserInteractive); } return XFA_EventError::kError; } XFA_EventError CXFA_Node::ProcessNullTestValidate(CXFA_FFDocView* pDocView, CXFA_Validate* validate, int32_t iFlags, bool bVersionFlag) { if (!GetValue(XFA_ValuePicture::kRaw).IsEmpty()) return XFA_EventError::kSuccess; if (m_bIsNull && m_bPreNull) return XFA_EventError::kSuccess; XFA_AttributeValue eNullTest = validate->GetNullTest(); WideString wsNullMsg = validate->GetNullMessageText(); if (iFlags & 0x01) { if (eNullTest == XFA_AttributeValue::Disabled) return XFA_EventError::kSuccess; if (!wsNullMsg.IsEmpty()) pDocView->AddNullTestMsg(wsNullMsg); return XFA_EventError::kError; } if (wsNullMsg.IsEmpty() && bVersionFlag && eNullTest != XFA_AttributeValue::Disabled) { return XFA_EventError::kError; } CXFA_FFApp::CallbackIface* pAppProvider = pDocView->GetDoc()->GetApp()->GetAppProvider(); if (!pAppProvider) return XFA_EventError::kNotExist; WideString wsCaptionName; WideString wsTitle = pAppProvider->GetAppTitle(); switch (eNullTest) { case XFA_AttributeValue::Error: { if (wsNullMsg.IsEmpty()) { wsCaptionName = GetValidateCaptionName(bVersionFlag); wsNullMsg = wsCaptionName + L" cannot be blank."; } pAppProvider->MsgBox(wsNullMsg, wsTitle, static_cast(AlertIcon::kStatus), static_cast(AlertButton::kOK)); return XFA_EventError::kError; } case XFA_AttributeValue::Warning: { if (IsUserInteractive()) return XFA_EventError::kSuccess; if (wsNullMsg.IsEmpty()) { wsCaptionName = GetValidateCaptionName(bVersionFlag); wsNullMsg = wsCaptionName + L" cannot be blank. To ignore validations for " + wsCaptionName + L", click Ignore."; } if (pAppProvider->MsgBox(wsNullMsg, wsTitle, static_cast(AlertIcon::kWarning), static_cast(AlertButton::kYesNo)) == static_cast(AlertReturn::kYes)) { SetFlag(XFA_NodeFlag::kUserInteractive); } return XFA_EventError::kError; } case XFA_AttributeValue::Disabled: default: break; } return XFA_EventError::kSuccess; } XFA_EventError CXFA_Node::ProcessValidate(CXFA_FFDocView* pDocView, int32_t iFlags) { if (GetElementType() == XFA_Element::Draw) return XFA_EventError::kNotExist; CXFA_Validate* validate = GetValidateIfExists(); if (!validate) return XFA_EventError::kNotExist; const bool bInitDoc = validate->NeedsInitApp(); const bool bStatus = pDocView->GetLayoutStatus() != CXFA_FFDocView::LayoutStatus::kEnd; XFA_EventError iFormat = XFA_EventError::kNotExist; XFA_EventError iRet = XFA_EventError::kNotExist; CXFA_Script* script = validate->GetScriptIfExists(); bool bRet = false; bool hasBoolResult = (bInitDoc || bStatus) && GetRawValue().IsEmpty(); if (script) { CXFA_EventParam eParam; eParam.m_eType = XFA_EVENT_Validate; std::tie(iRet, bRet) = ExecuteBoolScript(pDocView, script, &eParam); } XFA_VERSION version = pDocView->GetDoc()->GetXFADoc()->GetCurVersionMode(); bool bVersionFlag = version < XFA_VERSION_208; if (bInitDoc) { validate->ClearFlag(XFA_NodeFlag::kNeedsInitApp); } else { iFormat = ProcessFormatTestValidate(pDocView, validate, bVersionFlag); if (!bVersionFlag) bVersionFlag = pDocView->GetDoc()->GetXFADoc()->is_scripting(); XFA_EventErrorAccumulate( &iRet, ProcessNullTestValidate(pDocView, validate, iFlags, bVersionFlag)); } if (iRet == XFA_EventError::kSuccess && iFormat != XFA_EventError::kSuccess && hasBoolResult && !bRet) { ProcessScriptTestValidate(pDocView, validate, bVersionFlag); } XFA_EventErrorAccumulate(&iRet, iFormat); return iRet; } WideString CXFA_Node::GetValidateCaptionName(bool bVersionFlag) { WideString wsCaptionName; if (!bVersionFlag) { CXFA_Caption* caption = GetCaptionIfExists(); if (caption) { CXFA_Value* capValue = caption->GetValueIfExists(); if (capValue) { CXFA_Text* captionText = capValue->GetTextIfExists(); if (captionText) wsCaptionName = captionText->GetContent(); } } } if (!wsCaptionName.IsEmpty()) return wsCaptionName; return JSObject()->GetCData(XFA_Attribute::Name); } WideString CXFA_Node::GetValidateMessage(bool bError, bool bVersionFlag) { WideString wsCaptionName = GetValidateCaptionName(bVersionFlag); if (bVersionFlag) return wsCaptionName + L" validation failed"; WideString result = L"The value you entered for " + wsCaptionName + L" is invalid."; if (!bError) { result += L" To ignore validations for " + wsCaptionName + L", click Ignore."; } return result; } XFA_EventError CXFA_Node::ExecuteScript(CXFA_FFDocView* pDocView, CXFA_Script* script, CXFA_EventParam* pEventParam) { return ExecuteBoolScript(pDocView, script, pEventParam).first; } std::pair CXFA_Node::ExecuteBoolScript( CXFA_FFDocView* pDocView, CXFA_Script* script, CXFA_EventParam* pEventParam) { if (m_ExecuteRecursionDepth > kMaxExecuteRecursion) return {XFA_EventError::kSuccess, false}; DCHECK(pEventParam); if (!script) return {XFA_EventError::kNotExist, false}; if (script->GetRunAt() == XFA_AttributeValue::Server) return {XFA_EventError::kDisabled, false}; WideString wsExpression = script->GetExpression(); if (wsExpression.IsEmpty()) return {XFA_EventError::kNotExist, false}; CXFA_Script::Type eScriptType = script->GetContentType(); if (eScriptType == CXFA_Script::Type::Unknown) return {XFA_EventError::kSuccess, false}; CXFA_FFDoc* pDoc = pDocView->GetDoc(); CFXJSE_Engine* pContext = pDoc->GetXFADoc()->GetScriptContext(); CFXJSE_Engine::EventParamScope paramScope( pContext, pEventParam->m_bTargeted ? this : nullptr, pEventParam); pContext->SetRunAtType(script->GetRunAt()); std::vector> refNodes; if (pEventParam->m_eType == XFA_EVENT_InitCalculate || pEventParam->m_eType == XFA_EVENT_Calculate) { pContext->SetNodesOfRunScript(&refNodes); } auto pTmpRetValue = std::make_unique(); bool bRet = false; { AutoRestorer restorer(&m_ExecuteRecursionDepth); ++m_ExecuteRecursionDepth; bRet = pContext->RunScript(eScriptType, wsExpression.AsStringView(), pTmpRetValue.get(), this); } XFA_EventError iRet = XFA_EventError::kError; if (bRet) { iRet = XFA_EventError::kSuccess; if (pEventParam->m_eType == XFA_EVENT_Calculate || pEventParam->m_eType == XFA_EVENT_InitCalculate) { if (!pTmpRetValue->IsUndefined(pContext->GetIsolate())) { if (!pTmpRetValue->IsNull(pContext->GetIsolate())) pEventParam->m_wsResult = pTmpRetValue->ToWideString(pContext->GetIsolate()); iRet = XFA_EventError::kSuccess; } else { iRet = XFA_EventError::kError; } if (pEventParam->m_eType == XFA_EVENT_InitCalculate) { if ((iRet == XFA_EventError::kSuccess) && (GetRawValue() != pEventParam->m_wsResult)) { SetValue(XFA_ValuePicture::kRaw, pEventParam->m_wsResult); pDocView->AddValidateNode(this); } } for (CXFA_Node* pRefNode : refNodes) { if (pRefNode == this) continue; CJX_Object::CalcData* pGlobalData = pRefNode->JSObject()->GetOrCreateCalcData(pDoc->GetHeap()); if (!pdfium::Contains(pGlobalData->m_Globals, this)) pGlobalData->m_Globals.push_back(this); } } } pContext->SetNodesOfRunScript(nullptr); return {iRet, pTmpRetValue->IsBoolean(pContext->GetIsolate()) && pTmpRetValue->ToBoolean(pContext->GetIsolate())}; } std::pair CXFA_Node::CreateChildUIAndValueNodesIfNeeded() { XFA_Element eType = GetElementType(); DCHECK(eType == XFA_Element::Field || eType == XFA_Element::Draw); // Both Field and Draw have a UI property. We should always be able to // retrieve or create the UI element. If we can't something is wrong. CXFA_Ui* pUI = JSObject()->GetOrCreateProperty(0, XFA_Element::Ui); DCHECK(pUI); CXFA_Node* pUIChild = nullptr; // Search through the children of the UI node to see if we have any of our // One-Of entries. If so, that is the node associated with our UI. for (CXFA_Node* pChild = pUI->GetFirstChild(); pChild; pChild = pChild->GetNextSibling()) { if (pUI->IsAOneOfChild(pChild)) { pUIChild = pChild; break; } } XFA_FFWidgetType widget_type = XFA_FFWidgetType::kNone; XFA_Element expected_ui_child_type = XFA_Element::Unknown; // Both Field and Draw nodes have a Value child. So, we should either always // have it, or always create it. If we don't get the Value child for some // reason something has gone really wrong. CXFA_Value* value = JSObject()->GetOrCreateProperty(0, XFA_Element::Value); DCHECK(value); // The Value nodes only have One-Of children. So, if we have a first child // that child must be the type we want to use. CXFA_Node* child = value->GetFirstChild(); if (child) { switch (child->GetElementType()) { case XFA_Element::Boolean: expected_ui_child_type = XFA_Element::CheckButton; break; case XFA_Element::Integer: case XFA_Element::Decimal: case XFA_Element::Float: expected_ui_child_type = XFA_Element::NumericEdit; break; case XFA_Element::ExData: case XFA_Element::Text: expected_ui_child_type = XFA_Element::TextEdit; widget_type = XFA_FFWidgetType::kText; break; case XFA_Element::Date: case XFA_Element::Time: case XFA_Element::DateTime: expected_ui_child_type = XFA_Element::DateTimeEdit; break; case XFA_Element::Image: expected_ui_child_type = XFA_Element::ImageEdit; widget_type = XFA_FFWidgetType::kImage; break; case XFA_Element::Arc: expected_ui_child_type = XFA_Element::DefaultUi; widget_type = XFA_FFWidgetType::kArc; break; case XFA_Element::Line: expected_ui_child_type = XFA_Element::DefaultUi; widget_type = XFA_FFWidgetType::kLine; break; case XFA_Element::Rectangle: expected_ui_child_type = XFA_Element::DefaultUi; widget_type = XFA_FFWidgetType::kRectangle; break; default: break; } } if (eType == XFA_Element::Draw) { if (pUIChild && pUIChild->GetElementType() == XFA_Element::TextEdit) { widget_type = XFA_FFWidgetType::kText; } else if (pUIChild && pUIChild->GetElementType() == XFA_Element::ImageEdit) { widget_type = XFA_FFWidgetType::kImage; } else if (widget_type == XFA_FFWidgetType::kNone) { widget_type = XFA_FFWidgetType::kText; } } else if (eType == XFA_Element::Field) { if (pUIChild && pUIChild->GetElementType() == XFA_Element::DefaultUi) { widget_type = XFA_FFWidgetType::kTextEdit; } else if (pUIChild) { widget_type = pUIChild->GetDefaultFFWidgetType(); } else if (expected_ui_child_type == XFA_Element::Unknown) { widget_type = XFA_FFWidgetType::kTextEdit; } } else { NOTREACHED_NORETURN(); } if (!pUIChild) { if (expected_ui_child_type == XFA_Element::Unknown) expected_ui_child_type = XFA_Element::TextEdit; pUIChild = pUI->JSObject()->GetOrCreateProperty( 0, expected_ui_child_type); } CreateValueNodeIfNeeded(value, pUIChild); return {widget_type, pUI}; } XFA_FFWidgetType CXFA_Node::GetDefaultFFWidgetType() const { NOTREACHED_NORETURN(); } CXFA_Node* CXFA_Node::CreateUINodeIfNeeded(CXFA_Ui* ui, XFA_Element type) { return ui->JSObject()->GetOrCreateProperty(0, type); } void CXFA_Node::CreateValueNodeIfNeeded(CXFA_Value* value, CXFA_Node* pUIChild) { // Value nodes only have one child. If we have one already we're done. if (value->GetFirstChild()) return; // Create the Value node for our UI if needed. XFA_Element valueType = pUIChild->GetValueNodeType(); if (pUIChild->GetElementType() == XFA_Element::CheckButton) { CXFA_Items* pItems = GetChild(0, XFA_Element::Items, false); if (pItems) { CXFA_Node* pItem = pItems->GetChild(0, XFA_Element::Unknown, false); if (pItem) valueType = pItem->GetElementType(); } } value->JSObject()->GetOrCreateProperty(0, valueType); } XFA_Element CXFA_Node::GetValueNodeType() const { return XFA_Element::Text; } CXFA_Node* CXFA_Node::GetUIChildNode() { DCHECK(HasCreatedUIWidget()); if (ff_widget_type_ != XFA_FFWidgetType::kNone) return ui_ ? ui_->GetFirstChild() : nullptr; XFA_Element type = GetElementType(); if (type == XFA_Element::Field || type == XFA_Element::Draw) { std::tie(ff_widget_type_, ui_) = CreateChildUIAndValueNodesIfNeeded(); } else if (type == XFA_Element::Subform) { ff_widget_type_ = XFA_FFWidgetType::kSubform; } else if (type == XFA_Element::ExclGroup) { ff_widget_type_ = XFA_FFWidgetType::kExclGroup; } else { NOTREACHED_NORETURN(); } return ui_ ? ui_->GetFirstChild() : nullptr; } XFA_FFWidgetType CXFA_Node::GetFFWidgetType() { GetUIChildNode(); return ff_widget_type_; } CXFA_Border* CXFA_Node::GetUIBorder() { CXFA_Node* pUIChild = GetUIChildNode(); return pUIChild ? pUIChild->JSObject()->GetProperty( 0, XFA_Element::Border) : nullptr; } CFX_RectF CXFA_Node::GetUIMargin() { CXFA_Node* pUIChild = GetUIChildNode(); if (!pUIChild) return CFX_RectF(); CXFA_Margin* mgUI = pUIChild->JSObject()->GetProperty(0, XFA_Element::Margin); if (!mgUI) return CFX_RectF(); CXFA_Border* border = GetUIBorder(); if (border && border->GetPresence() != XFA_AttributeValue::Visible) return CFX_RectF(); absl::optional left = mgUI->TryLeftInset(); absl::optional top = mgUI->TryTopInset(); absl::optional right = mgUI->TryRightInset(); absl::optional bottom = mgUI->TryBottomInset(); if (border) { bool bVisible = false; float fThickness = 0; XFA_AttributeValue iType = XFA_AttributeValue::Unknown; std::tie(iType, bVisible, fThickness) = border->Get3DStyle(); if (!left.has_value() || !top.has_value() || !right.has_value() || !bottom.has_value()) { std::vector strokes = border->GetStrokes(); if (!top.has_value()) top = GetEdgeThickness(strokes, bVisible, 0); if (!right.has_value()) right = GetEdgeThickness(strokes, bVisible, 1); if (!bottom.has_value()) bottom = GetEdgeThickness(strokes, bVisible, 2); if (!left.has_value()) left = GetEdgeThickness(strokes, bVisible, 3); } } return CFX_RectF(left.value_or(0.0), top.value_or(0.0), right.value_or(0.0), bottom.value_or(0.0)); } std::vector CXFA_Node::GetEventByActivity( XFA_AttributeValue iActivity, bool bIsFormReady) { std::vector events; for (CXFA_Node* node : GetNodeListForType(XFA_Element::Event)) { auto* event = static_cast(node); if (event->GetActivity() != iActivity) continue; if (iActivity != XFA_AttributeValue::Ready) { events.push_back(event); continue; } WideString wsRef = event->GetRef(); if (bIsFormReady) { if (wsRef == WideStringView(L"$form")) events.push_back(event); continue; } if (wsRef == WideStringView(L"$layout")) events.push_back(event); } return events; } void CXFA_Node::ResetData() { WideString wsValue; switch (GetFFWidgetType()) { case XFA_FFWidgetType::kImageEdit: { CXFA_Value* imageValue = 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_FFWidgetType::kExclGroup: { CXFA_Node* pNextChild = GetFirstContainerChild(); while (pNextChild) { CXFA_Node* pChild = pNextChild; if (!pChild->IsWidgetReady()) continue; bool done = false; if (wsValue.IsEmpty()) { CXFA_Value* defValue = pChild->GetDefaultValueIfExists(); if (defValue) { wsValue = defValue->GetChildValueContent(); SetValue(XFA_ValuePicture::kRaw, wsValue); pChild->SetValue(XFA_ValuePicture::kRaw, wsValue); done = true; } } if (!done) { CXFA_Items* pItems = pChild->GetChild(0, XFA_Element::Items, false); if (!pItems) continue; WideString itemText; if (pItems->CountChildren(XFA_Element::Unknown, false) > 1) { itemText = pItems->GetChild(1, XFA_Element::Unknown, false) ->JSObject() ->GetContent(false); } pChild->SetValue(XFA_ValuePicture::kRaw, itemText); } pNextChild = pChild->GetNextContainerSibling(); } break; } case XFA_FFWidgetType::kChoiceList: ClearAllSelections(); [[fallthrough]]; default: { CXFA_Value* defValue = GetDefaultValueIfExists(); if (defValue) wsValue = defValue->GetChildValueContent(); SetValue(XFA_ValuePicture::kRaw, wsValue); break; } } } void CXFA_Node::SetImageEdit(const WideString& wsContentType, const WideString& wsHref, const WideString& wsData) { CXFA_Value* formValue = GetFormValueIfExists(); CXFA_Image* image = formValue ? formValue->GetImageIfExists() : nullptr; if (image) { image->SetContentType(WideString(wsContentType)); image->SetHref(wsHref); } JSObject()->SetContent(wsData, GetFormatDataValue(wsData), true, false, true); CXFA_Node* pBind = GetBindData(); if (!pBind) { if (image) image->SetTransferEncoding(XFA_AttributeValue::Base64); return; } pBind->JSObject()->SetCData(XFA_Attribute::ContentType, wsContentType); CXFA_Node* pHrefNode = pBind->GetFirstChild(); if (pHrefNode) { pHrefNode->JSObject()->SetCData(XFA_Attribute::Value, wsHref); return; } CFX_XMLElement* pElement = ToXMLElement(pBind->GetXMLMappingNode()); pElement->SetAttribute(L"href", wsHref); } void CXFA_Node::CalcCaptionSize(CXFA_FFDoc* doc, CFX_SizeF* pszCap) { CXFA_Caption* caption = GetCaptionIfExists(); if (!caption || !caption->IsVisible()) return; LoadCaption(doc); const float fCapReserve = caption->GetReserve(); const XFA_AttributeValue iCapPlacement = caption->GetPlacementType(); const bool bReserveExit = fCapReserve > 0.01; const bool bVert = iCapPlacement == XFA_AttributeValue::Top || iCapPlacement == XFA_AttributeValue::Bottom; CXFA_TextLayout* pCapTextLayout = m_pLayoutData->AsFieldLayoutData()->m_pCapTextLayout; if (pCapTextLayout) { if (!bVert && GetFFWidgetType() != XFA_FFWidgetType::kButton) pszCap->width = fCapReserve; CFX_SizeF minSize; *pszCap = pCapTextLayout->CalcSize(minSize, *pszCap); if (bReserveExit) bVert ? pszCap->height = fCapReserve : pszCap->width = fCapReserve; } else { float fFontSize = 10.0f; CXFA_Font* font = caption->GetFontIfExists(); if (font) { fFontSize = font->GetFontSize(); } else { CXFA_Font* widgetfont = GetFontIfExists(); if (widgetfont) fFontSize = widgetfont->GetFontSize(); } if (bVert) { pszCap->height = fCapReserve > 0 ? fCapReserve : fFontSize; } else { pszCap->width = fCapReserve > 0 ? fCapReserve : 0; pszCap->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 ? (pszCap->width += fLeftInset + fRightInset) : (pszCap->height += fTopInset + fBottomInset); } else { pszCap->width += fLeftInset + fRightInset; pszCap->height += fTopInset + fBottomInset; } } bool CXFA_Node::CalculateFieldAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) { CFX_SizeF szCap; CalcCaptionSize(doc, &szCap); CFX_RectF rtUIMargin = GetUIMargin(); pSize->width += rtUIMargin.left + rtUIMargin.width; pSize->height += rtUIMargin.top + rtUIMargin.height; if (szCap.width > 0 && szCap.height > 0) { CXFA_Caption* caption = GetCaptionIfExists(); XFA_AttributeValue placement = caption ? caption->GetPlacementType() : CXFA_Caption::kDefaultPlacementType; switch (placement) { case XFA_AttributeValue::Left: case XFA_AttributeValue::Right: case XFA_AttributeValue::Inline: { pSize->width += szCap.width; pSize->height = std::max(pSize->height, szCap.height); } break; case XFA_AttributeValue::Top: case XFA_AttributeValue::Bottom: { pSize->height += szCap.height; pSize->width = std::max(pSize->width, szCap.width); break; } default: break; } } return CalculateWidgetAutoSize(pSize); } bool CXFA_Node::CalculateWidgetAutoSize(CFX_SizeF* pSize) { CXFA_Margin* margin = GetMarginIfExists(); if (margin) { pSize->width += margin->GetLeftInset() + margin->GetRightInset(); pSize->height += margin->GetTopInset() + margin->GetBottomInset(); } CXFA_Para* para = GetParaIfExists(); if (para) pSize->width += para->GetMarginLeft() + para->GetTextIndent(); absl::optional width = TryWidth(); if (width.has_value()) { pSize->width = width.value(); } else { absl::optional min = TryMinWidth(); if (min.has_value()) pSize->width = std::max(pSize->width, min.value()); absl::optional max = TryMaxWidth(); if (max.has_value() && max.value() > 0) pSize->width = std::min(pSize->width, max.value()); } absl::optional height = TryHeight(); if (height.has_value()) { pSize->height = height.value(); } else { absl::optional min = TryMinHeight(); if (min.has_value()) pSize->height = std::max(pSize->height, min.value()); absl::optional max = TryMaxHeight(); if (max.has_value() && max.value() > 0) pSize->height = std::min(pSize->height, max.value()); } return true; } void CXFA_Node::CalculateTextContentSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) { float fFontSize = GetFontSize(); WideString wsText = GetValue(XFA_ValuePicture::kDisplay); if (wsText.IsEmpty()) { pSize->height += fFontSize; return; } if (wsText.Back() == L'\n') wsText += L'\n'; CXFA_FieldLayoutData* layoutData = m_pLayoutData->AsFieldLayoutData(); if (!layoutData->m_pTextOut) { layoutData->m_pTextOut = std::make_unique(); CFDE_TextOut* pTextOut = layoutData->m_pTextOut.get(); pTextOut->SetFont(GetFGASFont(doc)); pTextOut->SetFontSize(fFontSize); pTextOut->SetLineBreakTolerance(fFontSize * 0.2f); pTextOut->SetLineSpace(GetLineHeight()); FDE_TextStyle dwStyles; dwStyles.last_line_height_ = true; if (GetFFWidgetType() == XFA_FFWidgetType::kTextEdit && IsMultiLine()) dwStyles.line_wrap_ = true; pTextOut->SetStyles(dwStyles); } layoutData->m_pTextOut->CalcLogicSize(wsText.AsStringView(), pSize); } bool CXFA_Node::CalculateTextEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) { if (pSize->width > 0) { CFX_SizeF szOrz = *pSize; CFX_SizeF szCap; CalcCaptionSize(doc, &szCap); bool bCapExit = szCap.width > 0.01 && szCap.height > 0.01; XFA_AttributeValue iCapPlacement = XFA_AttributeValue::Unknown; if (bCapExit) { CXFA_Caption* caption = GetCaptionIfExists(); iCapPlacement = caption ? caption->GetPlacementType() : CXFA_Caption::kDefaultPlacementType; switch (iCapPlacement) { case XFA_AttributeValue::Left: case XFA_AttributeValue::Right: case XFA_AttributeValue::Inline: { pSize->width -= szCap.width; break; } default: break; } } CFX_RectF rtUIMargin = GetUIMargin(); pSize->width -= rtUIMargin.left + rtUIMargin.width; CXFA_Margin* margin = GetMarginIfExists(); if (margin) pSize->width -= margin->GetLeftInset() + margin->GetRightInset(); CalculateTextContentSize(doc, pSize); pSize->height += rtUIMargin.top + rtUIMargin.height; if (bCapExit) { switch (iCapPlacement) { case XFA_AttributeValue::Left: case XFA_AttributeValue::Right: case XFA_AttributeValue::Inline: { pSize->height = std::max(pSize->height, szCap.height); } break; case XFA_AttributeValue::Top: case XFA_AttributeValue::Bottom: { pSize->height += szCap.height; break; } default: break; } } pSize->width = szOrz.width; return CalculateWidgetAutoSize(pSize); } CalculateTextContentSize(doc, pSize); return CalculateFieldAutoSize(doc, pSize); } bool CXFA_Node::CalculateCheckButtonAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) { float fCheckSize = GetCheckButtonSize(); *pSize = CFX_SizeF(fCheckSize, fCheckSize); return CalculateFieldAutoSize(doc, pSize); } bool CXFA_Node::CalculatePushButtonAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) { CalcCaptionSize(doc, pSize); return CalculateWidgetAutoSize(pSize); } CFX_SizeF CXFA_Node::CalculateImageSize(float img_width, float img_height, const CFX_Size& dpi) { CFX_RectF rtImage(0, 0, XFA_UnitPx2Pt(img_width, dpi.width), XFA_UnitPx2Pt(img_height, dpi.height)); CFX_RectF rtFit; absl::optional width = TryWidth(); if (width.has_value()) { rtFit.width = width.value(); GetWidthWithoutMargin(rtFit.width); } else { rtFit.width = rtImage.width; } absl::optional height = TryHeight(); if (height.has_value()) { rtFit.height = height.value(); GetHeightWithoutMargin(rtFit.height); } else { rtFit.height = rtImage.height; } return rtFit.Size(); } bool CXFA_Node::CalculateImageAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) { if (!GetLayoutImage()) LoadLayoutImage(doc); pSize->clear(); RetainPtr pBitmap = GetLayoutImage(); if (!pBitmap) return CalculateWidgetAutoSize(pSize); *pSize = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(), GetLayoutImageDpi()); return CalculateWidgetAutoSize(pSize); } bool CXFA_Node::CalculateImageEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) { if (!GetEditImage()) LoadEditImage(doc); pSize->clear(); RetainPtr pBitmap = GetEditImage(); if (!pBitmap) return CalculateFieldAutoSize(doc, pSize); *pSize = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(), GetEditImageDpi()); return CalculateFieldAutoSize(doc, pSize); } bool CXFA_Node::LoadLayoutImage(CXFA_FFDoc* doc) { InitLayoutData(doc); return m_pLayoutData->AsImageLayoutData()->LoadImageData(doc, this); } bool CXFA_Node::LoadEditImage(CXFA_FFDoc* doc) { InitLayoutData(doc); return m_pLayoutData->AsFieldLayoutData()->AsImageEditData()->LoadImageData( doc, this); } CFX_Size CXFA_Node::GetLayoutImageDpi() const { return m_pLayoutData->AsImageLayoutData()->GetDpi(); } CFX_Size CXFA_Node::GetEditImageDpi() const { CXFA_ImageEditData* pData = m_pLayoutData->AsFieldLayoutData()->AsImageEditData(); return pData->GetDpi(); } float CXFA_Node::CalculateWidgetAutoWidth(float fWidthCalc) { CXFA_Margin* margin = GetMarginIfExists(); if (margin) fWidthCalc += margin->GetLeftInset() + margin->GetRightInset(); absl::optional min = TryMinWidth(); if (min.has_value()) fWidthCalc = std::max(fWidthCalc, min.value()); absl::optional max = TryMaxWidth(); if (max.has_value() && max.value() > 0) fWidthCalc = std::min(fWidthCalc, max.value()); return fWidthCalc; } float CXFA_Node::GetWidthWithoutMargin(float fWidthCalc) const { CXFA_Margin* margin = GetMarginIfExists(); if (margin) fWidthCalc -= margin->GetLeftInset() + margin->GetRightInset(); return fWidthCalc; } float CXFA_Node::CalculateWidgetAutoHeight(float fHeightCalc) { CXFA_Margin* margin = GetMarginIfExists(); if (margin) fHeightCalc += margin->GetTopInset() + margin->GetBottomInset(); absl::optional min = TryMinHeight(); if (min.has_value()) fHeightCalc = std::max(fHeightCalc, min.value()); absl::optional max = TryMaxHeight(); if (max.has_value() && max.value() > 0) fHeightCalc = std::min(fHeightCalc, max.value()); return fHeightCalc; } float CXFA_Node::GetHeightWithoutMargin(float fHeightCalc) const { CXFA_Margin* margin = GetMarginIfExists(); if (margin) fHeightCalc -= margin->GetTopInset() + margin->GetBottomInset(); return fHeightCalc; } void CXFA_Node::StartWidgetLayout(CXFA_FFDoc* doc, float* pCalcWidth, float* pCalcHeight) { InitLayoutData(doc); if (GetFFWidgetType() == XFA_FFWidgetType::kText) { m_pLayoutData->SetWidgetHeight(TryHeight().value_or(-1)); StartTextLayout(doc, pCalcWidth, pCalcHeight); return; } if (*pCalcWidth > 0 && *pCalcHeight > 0) return; m_pLayoutData->SetWidgetHeight(-1.0f); float fWidth = 0; if (*pCalcWidth > 0 && *pCalcHeight < 0) { absl::optional height = TryHeight(); if (height.has_value()) { *pCalcHeight = height.value(); } else { CFX_SizeF size = CalculateAccWidthAndHeight(doc, *pCalcWidth); *pCalcWidth = size.width; *pCalcHeight = size.height; } m_pLayoutData->SetWidgetHeight(*pCalcHeight); return; } if (*pCalcWidth < 0 && *pCalcHeight < 0) { absl::optional height; absl::optional width = TryWidth(); if (width.has_value()) { fWidth = width.value(); height = TryHeight(); if (height.has_value()) *pCalcHeight = height.value(); } if (!width.has_value() || !height.has_value()) { CFX_SizeF size = CalculateAccWidthAndHeight(doc, fWidth); *pCalcWidth = size.width; *pCalcHeight = size.height; } else { *pCalcWidth = fWidth; } } m_pLayoutData->SetWidgetHeight(*pCalcHeight); } CFX_SizeF CXFA_Node::CalculateAccWidthAndHeight(CXFA_FFDoc* doc, float fWidth) { CFX_SizeF sz(fWidth, m_pLayoutData->GetWidgetHeight()); switch (GetFFWidgetType()) { case XFA_FFWidgetType::kBarcode: case XFA_FFWidgetType::kChoiceList: case XFA_FFWidgetType::kSignature: CalculateFieldAutoSize(doc, &sz); break; case XFA_FFWidgetType::kImageEdit: CalculateImageEditAutoSize(doc, &sz); break; case XFA_FFWidgetType::kButton: CalculatePushButtonAutoSize(doc, &sz); break; case XFA_FFWidgetType::kCheckButton: CalculateCheckButtonAutoSize(doc, &sz); break; case XFA_FFWidgetType::kDateTimeEdit: case XFA_FFWidgetType::kNumericEdit: case XFA_FFWidgetType::kPasswordEdit: case XFA_FFWidgetType::kTextEdit: CalculateTextEditAutoSize(doc, &sz); break; case XFA_FFWidgetType::kImage: CalculateImageAutoSize(doc, &sz); break; case XFA_FFWidgetType::kArc: case XFA_FFWidgetType::kLine: case XFA_FFWidgetType::kRectangle: case XFA_FFWidgetType::kSubform: case XFA_FFWidgetType::kExclGroup: CalculateWidgetAutoSize(&sz); break; case XFA_FFWidgetType::kText: case XFA_FFWidgetType::kNone: break; } m_pLayoutData->SetWidgetHeight(sz.height); return sz; } absl::optional CXFA_Node::FindSplitPos(CXFA_FFDocView* pDocView, size_t szBlockIndex, float fCalcHeight) { if (!HasCreatedUIWidget()) return absl::nullopt; if (GetFFWidgetType() == XFA_FFWidgetType::kSubform) return absl::nullopt; switch (GetFFWidgetType()) { case XFA_FFWidgetType::kText: case XFA_FFWidgetType::kTextEdit: case XFA_FFWidgetType::kNumericEdit: case XFA_FFWidgetType::kPasswordEdit: break; default: return 0.0f; } float fTopInset = 0; float fBottomInset = 0; if (szBlockIndex == 0) { CXFA_Margin* margin = GetMarginIfExists(); if (margin) { fTopInset = margin->GetTopInset(); fBottomInset = margin->GetBottomInset(); } CFX_RectF rtUIMargin = GetUIMargin(); fTopInset += rtUIMargin.top; fBottomInset += rtUIMargin.width; } if (GetFFWidgetType() == XFA_FFWidgetType::kText) { float fHeight = fCalcHeight; if (szBlockIndex == 0) { fCalcHeight -= fTopInset; fCalcHeight = std::max(fCalcHeight, 0.0f); } CXFA_TextLayout* pTextLayout = m_pLayoutData->AsTextLayoutData()->GetTextLayout(); fCalcHeight = pTextLayout->DoSplitLayout( szBlockIndex, fCalcHeight, m_pLayoutData->GetWidgetHeight() - fTopInset); if (fCalcHeight != 0) { if (szBlockIndex == 0) fCalcHeight += fTopInset; if (fabs(fHeight - fCalcHeight) < kXFAWidgetPrecision) return absl::nullopt; } return fCalcHeight; } XFA_AttributeValue iCapPlacement = XFA_AttributeValue::Unknown; float fCapReserve = 0; if (szBlockIndex == 0) { CXFA_Caption* caption = GetCaptionIfExists(); if (caption && !caption->IsHidden()) { iCapPlacement = caption->GetPlacementType(); fCapReserve = caption->GetReserve(); } if (iCapPlacement == XFA_AttributeValue::Top && fCalcHeight < fCapReserve + fTopInset) { return 0.0f; } if (iCapPlacement == XFA_AttributeValue::Bottom && m_pLayoutData->GetWidgetHeight() - fCapReserve - fBottomInset) { return 0.0f; } if (iCapPlacement != XFA_AttributeValue::Top) fCapReserve = 0; } CXFA_FieldLayoutData* pFieldData = m_pLayoutData->AsFieldLayoutData(); int32_t iLinesCount = 0; float fHeight = m_pLayoutData->GetWidgetHeight(); if (GetValue(XFA_ValuePicture::kDisplay).IsEmpty()) { iLinesCount = 1; } else { if (!pFieldData->m_pTextOut) { CFX_SizeF size = CalculateAccWidthAndHeight(pDocView->GetDoc(), TryWidth().value_or(0)); fHeight = size.height; } iLinesCount = pFieldData->m_pTextOut->GetTotalLines(); } std::vector* pFieldArray = &pFieldData->m_FieldSplitArray; size_t szFieldSplitCount = pFieldArray->size(); if (szFieldSplitCount < szBlockIndex * 3) return absl::nullopt; for (size_t i = 0; i < szBlockIndex * 3; i += 3) { iLinesCount -= static_cast((*pFieldArray)[i + 1]); fHeight -= (*pFieldArray)[i + 2]; } if (iLinesCount == 0) return absl::nullopt; float fLineHeight = GetLineHeight(); float fFontSize = GetFontSize(); float fTextHeight = iLinesCount * fLineHeight - fLineHeight + fFontSize; float fSpaceAbove = 0; float fStartOffset = 0; if (fHeight > 0.1f && szBlockIndex == 0) { fStartOffset = fTopInset; fHeight -= (fTopInset + fBottomInset); CXFA_Para* para = GetParaIfExists(); if (para) { fSpaceAbove = para->GetSpaceAbove(); float fSpaceBelow = para->GetSpaceBelow(); fHeight -= (fSpaceAbove + fSpaceBelow); switch (para->GetVerticalAlign()) { case XFA_AttributeValue::Top: fStartOffset += fSpaceAbove; break; case XFA_AttributeValue::Middle: fStartOffset += ((fHeight - fTextHeight) / 2 + fSpaceAbove); break; case XFA_AttributeValue::Bottom: fStartOffset += (fHeight - fTextHeight + fSpaceAbove); break; default: NOTREACHED_NORETURN(); } } if (fStartOffset < 0.1f) fStartOffset = 0; } if (szBlockIndex > 0) { size_t i = szBlockIndex - 1; fStartOffset = (*pFieldArray)[i * 3] - (*pFieldArray)[i * 3 + 2]; if (fStartOffset < 0.1f) fStartOffset = 0; } if (szFieldSplitCount / 3 == (szBlockIndex + 1)) (*pFieldArray)[0] = fStartOffset; else pFieldArray->push_back(fStartOffset); XFA_VERSION version = pDocView->GetDoc()->GetXFADoc()->GetCurVersionMode(); bool bCanSplitNoContent = false; auto value = GetParent()->JSObject()->TryEnum(XFA_Attribute::Layout, true); XFA_AttributeValue eLayoutMode = value.value_or(XFA_AttributeValue::Position); if ((eLayoutMode == XFA_AttributeValue::Position || eLayoutMode == XFA_AttributeValue::Tb || eLayoutMode == XFA_AttributeValue::Row || eLayoutMode == XFA_AttributeValue::Table) && version > XFA_VERSION_208) { bCanSplitNoContent = true; } if ((eLayoutMode == XFA_AttributeValue::Tb || eLayoutMode == XFA_AttributeValue::Row || eLayoutMode == XFA_AttributeValue::Table) && version <= XFA_VERSION_208) { if (fStartOffset >= fCalcHeight) return 0.0f; bCanSplitNoContent = true; } if (!bCanSplitNoContent || fCalcHeight - fTopInset - fSpaceAbove < fLineHeight) { return 0.0f; } if (fStartOffset + kXFAWidgetPrecision >= fCalcHeight) { if (szFieldSplitCount / 3 == (szBlockIndex + 1)) { (*pFieldArray)[szBlockIndex * 3 + 1] = 0; (*pFieldArray)[szBlockIndex * 3 + 2] = fCalcHeight; } else { pFieldArray->push_back(0); pFieldArray->push_back(fCalcHeight); } return absl::nullopt; } if (fCalcHeight - fStartOffset < fLineHeight) { fCalcHeight = fStartOffset; if (szFieldSplitCount / 3 == (szBlockIndex + 1)) { (*pFieldArray)[szBlockIndex * 3 + 1] = 0; (*pFieldArray)[szBlockIndex * 3 + 2] = fCalcHeight; } else { pFieldArray->push_back(0); pFieldArray->push_back(fCalcHeight); } return fCalcHeight; } float fTextNum = fCalcHeight + kXFAWidgetPrecision - fCapReserve - fStartOffset; int32_t iLineNum = static_cast( (fTextNum + (fLineHeight - fFontSize)) / fLineHeight); if (iLineNum >= iLinesCount) { if (fCalcHeight - fStartOffset - fTextHeight >= fFontSize) { if (szFieldSplitCount / 3 == (szBlockIndex + 1)) { (*pFieldArray)[szBlockIndex * 3 + 1] = iLinesCount; (*pFieldArray)[szBlockIndex * 3 + 2] = fCalcHeight; } else { pFieldArray->push_back(iLinesCount); pFieldArray->push_back(fCalcHeight); } return absl::nullopt; } if (fHeight - fStartOffset - fTextHeight < fFontSize) { iLineNum -= 1; if (iLineNum == 0) return 0.0f; } else { iLineNum = static_cast(fTextNum / fLineHeight); } } if (iLineNum <= 0) return 0.0f; float fSplitHeight = iLineNum * fLineHeight + fCapReserve + fStartOffset; if (szFieldSplitCount / 3 == (szBlockIndex + 1)) { (*pFieldArray)[szBlockIndex * 3 + 1] = iLineNum; (*pFieldArray)[szBlockIndex * 3 + 2] = fSplitHeight; } else { pFieldArray->push_back(iLineNum); pFieldArray->push_back(fSplitHeight); } if (fabs(fSplitHeight - fCalcHeight) < kXFAWidgetPrecision) return absl::nullopt; return fSplitHeight; } void CXFA_Node::InitLayoutData(CXFA_FFDoc* doc) { if (m_pLayoutData) return; switch (GetFFWidgetType()) { case XFA_FFWidgetType::kText: m_pLayoutData = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle()); return; case XFA_FFWidgetType::kTextEdit: m_pLayoutData = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle()); return; case XFA_FFWidgetType::kImage: m_pLayoutData = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle()); return; case XFA_FFWidgetType::kImageEdit: m_pLayoutData = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle()); return; default: break; } if (GetElementType() == XFA_Element::Field) { m_pLayoutData = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle()); return; } m_pLayoutData = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle()); } void CXFA_Node::StartTextLayout(CXFA_FFDoc* doc, float* pCalcWidth, float* pCalcHeight) { InitLayoutData(doc); CXFA_TextLayoutData* pTextLayoutData = m_pLayoutData->AsTextLayoutData(); pTextLayoutData->LoadText(doc, this); CXFA_TextLayout* pTextLayout = pTextLayoutData->GetTextLayout(); float fTextHeight = 0; if (*pCalcWidth > 0 && *pCalcHeight > 0) { float fWidth = GetWidthWithoutMargin(*pCalcWidth); pTextLayout->StartLayout(fWidth); fTextHeight = *pCalcHeight; fTextHeight = GetHeightWithoutMargin(fTextHeight); pTextLayout->DoLayout(fTextHeight); return; } if (*pCalcWidth > 0 && *pCalcHeight < 0) { float fWidth = GetWidthWithoutMargin(*pCalcWidth); pTextLayout->StartLayout(fWidth); } if (*pCalcWidth < 0 && *pCalcHeight < 0) { absl::optional width = TryWidth(); if (width.has_value()) { pTextLayout->StartLayout(GetWidthWithoutMargin(width.value())); *pCalcWidth = width.value(); } else { float fMaxWidth = CalculateWidgetAutoWidth(pTextLayout->StartLayout(-1)); pTextLayout->StartLayout(GetWidthWithoutMargin(fMaxWidth)); *pCalcWidth = fMaxWidth; } } if (m_pLayoutData->GetWidgetHeight() < 0) { m_pLayoutData->SetWidgetHeight( CalculateWidgetAutoHeight(pTextLayout->GetLayoutHeight())); } fTextHeight = m_pLayoutData->GetWidgetHeight(); fTextHeight = GetHeightWithoutMargin(fTextHeight); pTextLayout->DoLayout(fTextHeight); *pCalcHeight = m_pLayoutData->GetWidgetHeight(); } bool CXFA_Node::LoadCaption(CXFA_FFDoc* doc) { InitLayoutData(doc); return m_pLayoutData->AsFieldLayoutData()->LoadCaption(doc, this); } CXFA_TextLayout* CXFA_Node::GetCaptionTextLayout() { return m_pLayoutData ? m_pLayoutData->AsFieldLayoutData()->m_pCapTextLayout : nullptr; } CXFA_TextLayout* CXFA_Node::GetTextLayout() { return m_pLayoutData ? m_pLayoutData->AsTextLayoutData()->GetTextLayout() : nullptr; } RetainPtr CXFA_Node::GetLayoutImage() { return m_pLayoutData ? m_pLayoutData->AsImageLayoutData()->GetBitmap() : nullptr; } RetainPtr CXFA_Node::GetEditImage() { return m_pLayoutData ? m_pLayoutData->AsFieldLayoutData() ->AsImageEditData() ->GetBitmap() : nullptr; } void CXFA_Node::SetLayoutImage(RetainPtr newImage) { CXFA_ImageLayoutData* pData = m_pLayoutData->AsImageLayoutData(); if (pData->GetBitmap() != newImage) pData->SetBitmap(std::move(newImage)); } void CXFA_Node::SetEditImage(RetainPtr newImage) { CXFA_ImageEditData* pData = m_pLayoutData->AsFieldLayoutData()->AsImageEditData(); if (pData->GetBitmap() != newImage) pData->SetBitmap(std::move(newImage)); } RetainPtr CXFA_Node::GetFGASFont(CXFA_FFDoc* doc) { WideString wsFontName = L"Courier"; uint32_t dwFontStyle = 0; CXFA_Font* font = GetFontIfExists(); if (font) { if (font->IsBold()) dwFontStyle |= FXFONT_FORCE_BOLD; if (font->IsItalic()) dwFontStyle |= FXFONT_ITALIC; wsFontName = font->GetTypeface(); } return doc->GetApp()->GetXFAFontMgr()->GetFont(doc, wsFontName, dwFontStyle); } bool CXFA_Node::HasButtonRollover() const { const auto* pItems = GetChild(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) .EqualsASCII("rollover")) { return !pText->JSObject()->GetContent(false).IsEmpty(); } } return false; } bool CXFA_Node::HasButtonDown() const { const auto* pItems = GetChild(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).EqualsASCII("down")) { return !pText->JSObject()->GetContent(false).IsEmpty(); } } return false; } bool CXFA_Node::IsRadioButton() { CXFA_Node* pParent = GetParent(); return pParent && pParent->GetElementType() == XFA_Element::ExclGroup; } float CXFA_Node::GetCheckButtonSize() { CXFA_Node* pUIChild = GetUIChildNode(); if (pUIChild) { return pUIChild->JSObject()->GetMeasureInUnit(XFA_Attribute::Size, XFA_Unit::Pt); } return CXFA_Measurement(10, XFA_Unit::Pt).ToUnit(XFA_Unit::Pt); } XFA_CheckState CXFA_Node::GetCheckState() { WideString wsValue = GetRawValue(); if (wsValue.IsEmpty()) return XFA_CheckState::kOff; auto* pItems = GetChild(0, XFA_Element::Items, false); if (!pItems) return XFA_CheckState::kOff; CXFA_Node* pText = pItems->GetFirstChild(); int32_t i = 0; while (pText) { absl::optional wsContent = pText->JSObject()->TryContent(false, true); if (wsContent == wsValue) return static_cast(i); i++; pText = pText->GetNextSibling(); } return XFA_CheckState::kOff; } void CXFA_Node::SetCheckState(XFA_CheckState eCheckState) { CXFA_Node* node = GetExclGroupIfExists(); if (!node) { CXFA_Items* pItems = GetChild(0, XFA_Element::Items, false); if (!pItems) return; int32_t i = -1; CXFA_Node* pText = pItems->GetFirstChild(); WideString wsContent; while (pText) { i++; if (i == static_cast(eCheckState)) { wsContent = pText->JSObject()->GetContent(false); break; } pText = pText->GetNextSibling(); } SyncValue(wsContent, true); return; } WideString wsValue; if (eCheckState != XFA_CheckState::kOff) { if (CXFA_Items* pItems = GetChild(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(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, true); } node->SyncValue(wsValue, true); } CXFA_Node* CXFA_Node::GetSelectedMember() { CXFA_Node* pSelectedMember = nullptr; WideString wsState = GetRawValue(); if (wsState.IsEmpty()) return pSelectedMember; for (CXFA_Node* pNode = ToNode(GetFirstChild()); pNode; pNode = pNode->GetNextSibling()) { if (pNode->GetCheckState() == XFA_CheckState::kOn) { pSelectedMember = pNode; break; } } return pSelectedMember; } CXFA_Node* CXFA_Node::SetSelectedMember(WideStringView wsName) { uint32_t nameHash = FX_HashCode_GetW(wsName); for (CXFA_Node* pNode = ToNode(GetFirstChild()); pNode; pNode = pNode->GetNextSibling()) { if (pNode->GetNameHash() == nameHash) { pNode->SetCheckState(XFA_CheckState::kOn); return pNode; } } return nullptr; } void CXFA_Node::SetSelectedMemberByValue(WideStringView wsValue, bool bNotify, bool bScriptModify, bool bSyncData) { WideString wsExclGroup; for (CXFA_Node* pNode = GetFirstChild(); pNode; pNode = pNode->GetNextSibling()) { if (pNode->GetElementType() != XFA_Element::Field) continue; CXFA_Items* pItem = pNode->GetChild(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); } JSObject()->SetContent(wsExclGroup, wsExclGroup, bNotify, bScriptModify, bSyncData); } CXFA_Node* CXFA_Node::GetExclGroupFirstMember() { CXFA_Node* pNode = 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 = GetUIChildNode(); if (pUIChild) { return pUIChild->JSObject()->GetEnum(XFA_Attribute::CommitOn) == XFA_AttributeValue::Select; } return true; } bool CXFA_Node::IsChoiceListAllowTextEntry() { CXFA_Node* pUIChild = GetUIChildNode(); return pUIChild && pUIChild->JSObject()->GetBoolean(XFA_Attribute::TextEntry); } bool CXFA_Node::IsChoiceListMultiSelect() { CXFA_Node* pUIChild = GetUIChildNode(); if (pUIChild) { return pUIChild->JSObject()->GetEnum(XFA_Attribute::Open) == XFA_AttributeValue::MultiSelect; } return false; } bool CXFA_Node::IsListBox() { CXFA_Node* pUIChild = GetUIChildNode(); if (!pUIChild) return false; XFA_AttributeValue attr = pUIChild->JSObject()->GetEnum(XFA_Attribute::Open); return attr == XFA_AttributeValue::Always || attr == XFA_AttributeValue::MultiSelect; } size_t CXFA_Node::CountChoiceListItems(bool bSaveValue) { std::vector pItems; int32_t iCount = 0; for (CXFA_Node* 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); } absl::optional CXFA_Node::GetChoiceListItem(int32_t nIndex, bool bSaveValue) { std::vector pItemsArray; int32_t iCount = 0; for (CXFA_Node* 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 absl::nullopt; 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 absl::nullopt; CXFA_Node* pItem = pItems->GetChild(nIndex, XFA_Element::Unknown, false); if (!pItem) return absl::nullopt; return pItem->JSObject()->GetContent(false); } std::vector CXFA_Node::GetChoiceListItems(bool bSaveValue) { std::vector items; for (CXFA_Node* 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(); 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 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 wsValueArray = GetSelectedItemsValue(); if (IsListBox() || !IsChoiceListAllowTextEntry()) return fxcrt::CollectionSize(wsValueArray); int32_t iSelected = 0; std::vector wsSaveTextArray = GetChoiceListItems(true); for (const auto& value : wsValueArray) { if (pdfium::Contains(wsSaveTextArray, value)) iSelected++; } return iSelected; } int32_t CXFA_Node::GetSelectedItem(int32_t nIndex) { std::vector wsValueArray = GetSelectedItemsValue(); if (!fxcrt::IndexInBounds(wsValueArray, nIndex)) return -1; std::vector wsSaveTextArray = GetChoiceListItems(true); auto it = std::find(wsSaveTextArray.begin(), wsSaveTextArray.end(), wsValueArray[nIndex]); return it != wsSaveTextArray.end() ? pdfium::base::checked_cast(it - wsSaveTextArray.begin()) : -1; } std::vector CXFA_Node::GetSelectedItems() { std::vector iSelArray; std::vector wsValueArray = GetSelectedItemsValue(); std::vector wsSaveTextArray = GetChoiceListItems(true); for (const auto& value : wsValueArray) { auto it = std::find(wsSaveTextArray.begin(), wsSaveTextArray.end(), value); if (it != wsSaveTextArray.end()) { iSelArray.push_back( pdfium::base::checked_cast(it - wsSaveTextArray.begin())); } } return iSelArray; } std::vector CXFA_Node::GetSelectedItemsValue() { WideString wsValue = GetRawValue(); if (IsChoiceListMultiSelect()) return fxcrt::Split(wsValue, L'\n'); std::vector wsSelTextArray; wsSelTextArray.push_back(wsValue); return wsSelTextArray; } bool CXFA_Node::GetItemState(int32_t nIndex) { std::vector wsSaveTextArray = GetChoiceListItems(true); return fxcrt::IndexInBounds(wsSaveTextArray, nIndex) && pdfium::Contains(GetSelectedItemsValue(), wsSaveTextArray[nIndex]); } void CXFA_Node::SetItemState(int32_t nIndex, bool bSelected, bool bNotify, bool bScriptModify) { std::vector wsSaveTextArray = GetChoiceListItems(true); if (!fxcrt::IndexInBounds(wsSaveTextArray, nIndex)) return; int32_t iSel = -1; std::vector wsValueArray = GetSelectedItemsValue(); auto value_iter = std::find(wsValueArray.begin(), wsValueArray.end(), wsSaveTextArray[nIndex]); if (value_iter != wsValueArray.end()) { iSel = pdfium::base::checked_cast(value_iter - wsValueArray.begin()); } if (IsChoiceListMultiSelect()) { if (bSelected) { if (iSel < 0) { WideString wsValue = GetRawValue(); if (!wsValue.IsEmpty()) { wsValue += L"\n"; } wsValue += wsSaveTextArray[nIndex]; JSObject()->SetContent(wsValue, wsValue, bNotify, bScriptModify, true); } } else if (iSel >= 0) { std::vector iSelArray = GetSelectedItems(); auto selected_iter = std::find(iSelArray.begin(), iSelArray.end(), nIndex); if (selected_iter != iSelArray.end()) iSelArray.erase(selected_iter); SetSelectedItems(iSelArray, bNotify, bScriptModify, true); } } else { if (bSelected) { if (iSel < 0) { WideString wsSaveText = wsSaveTextArray[nIndex]; JSObject()->SetContent(wsSaveText, GetFormatDataValue(wsSaveText), bNotify, bScriptModify, true); } } else if (iSel >= 0) { JSObject()->SetContent(WideString(), WideString(), bNotify, bScriptModify, true); } } } void CXFA_Node::SetSelectedItems(const std::vector& iSelArray, bool bNotify, bool bScriptModify, bool bSyncData) { WideString wsValue; int32_t iSize = fxcrt::CollectionSize(iSelArray); if (iSize >= 1) { std::vector 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); JSObject()->SetContent(wsValue, wsFormat, bNotify, bScriptModify, bSyncData); } void CXFA_Node::ClearAllSelections() { CXFA_Node* pBind = GetBindData(); if (!pBind || !IsChoiceListMultiSelect()) { SyncValue(WideString(), false); return; } while (CXFA_Node* pChildNode = pBind->GetFirstChild()) pBind->RemoveChildAndNotify(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 listitems; for (CXFA_Node* pItem = GetFirstChild(); pItem; pItem = pItem->GetNextSibling()) { if (pItem->GetElementType() == XFA_Element::Items) listitems.push_back(pItem); } if (listitems.empty()) { CXFA_Node* pItems = CreateSamePacketNode(XFA_Element::Items); InsertChildAndNotify(-1, pItems); InsertListTextItem(pItems, wsLabel, nIndex); CXFA_Node* pSaveItems = CreateSamePacketNode(XFA_Element::Items); InsertChildAndNotify(-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_AttributeValue::Visible, false); CXFA_Node* pSaveItems = CreateSamePacketNode(XFA_Element::Items); InsertChildAndNotify(-1, pSaveItems); pSaveItems->JSObject()->SetBoolean(XFA_Attribute::Save, true, false); pSaveItems->JSObject()->SetEnum(XFA_Attribute::Presence, XFA_AttributeValue::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) GetDocument()->GetNotify()->OnWidgetListItemAdded(this, wsLabel, nIndex); } WideString CXFA_Node::GetItemLabel(WideStringView wsValue) const { std::vector listitems; CXFA_Node* pItems = GetFirstChild(); for (; pItems; pItems = pItems->GetNextSibling()) { if (pItems->GetElementType() != XFA_Element::Items) continue; listitems.push_back(pItems); } if (listitems.size() <= 1) return WideString(wsValue); 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]; } int32_t 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 WideString(); CXFA_Node* pText = pLabelItems->GetChild(iSearch, XFA_Element::Unknown, false); return pText ? pText->JSObject()->GetContent(false) : WideString(); } WideString CXFA_Node::GetItemValue(WideStringView wsLabel) { int32_t iCount = 0; std::vector listitems; for (CXFA_Node* pItems = 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 WideString(); CXFA_Node* pText = pSaveItems->GetChild(iSearch, XFA_Element::Unknown, false); return pText ? pText->JSObject()->GetContent(false) : WideString(); } bool CXFA_Node::DeleteItem(int32_t nIndex, bool bNotify, bool bScriptModify) { bool bSetValue = false; CXFA_Node* pItems = GetFirstChild(); for (; pItems; pItems = pItems->GetNextSibling()) { if (pItems->GetElementType() != XFA_Element::Items) continue; if (nIndex < 0) { while (CXFA_Node* pNode = pItems->GetFirstChild()) { pItems->RemoveChildAndNotify(pNode, true); } } else { if (!bSetValue && pItems->JSObject()->GetBoolean(XFA_Attribute::Save)) { SetItemState(nIndex, false, true, bScriptModify); bSetValue = true; } int32_t i = 0; CXFA_Node* pNode = pItems->GetFirstChild(); while (pNode) { if (i == nIndex) { pItems->RemoveChildAndNotify(pNode, true); break; } i++; pNode = pNode->GetNextSibling(); } } } if (bNotify) GetDocument()->GetNotify()->OnWidgetListItemRemoved(this, nIndex); return true; } bool CXFA_Node::IsHorizontalScrollPolicyOff() { CXFA_Node* pUIChild = GetUIChildNode(); if (pUIChild) { return pUIChild->JSObject()->GetEnum(XFA_Attribute::HScrollPolicy) == XFA_AttributeValue::Off; } return false; } bool CXFA_Node::IsVerticalScrollPolicyOff() { CXFA_Node* pUIChild = GetUIChildNode(); if (pUIChild) { return pUIChild->JSObject()->GetEnum(XFA_Attribute::VScrollPolicy) == XFA_AttributeValue::Off; } return false; } absl::optional CXFA_Node::GetNumberOfCells() { CXFA_Node* pUIChild = GetUIChildNode(); if (!pUIChild) return absl::nullopt; CXFA_Comb* pNode = pUIChild->GetChild(0, XFA_Element::Comb, false); if (!pNode) return absl::nullopt; return pNode->JSObject()->GetInteger(XFA_Attribute::NumberOfCells); } bool CXFA_Node::IsMultiLine() { CXFA_Node* pUIChild = GetUIChildNode(); return pUIChild && pUIChild->JSObject()->GetBoolean(XFA_Attribute::MultiLine); } std::pair CXFA_Node::GetMaxChars() const { const auto* pNode = GetChild(0, XFA_Element::Value, false); if (pNode) { 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() const { const auto* pNode = GetChild(0, XFA_Element::Value, false); if (!pNode) return -1; const auto* pChild = pNode->GetChild(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() const { const auto* pNode = GetChild(0, XFA_Element::Value, false); if (!pNode) return -1; const auto* pChild = pNode->GetChild(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()) { SyncValue(wsValue, true); return true; } SetPreNull(IsNull()); SetIsNull(false); WideString wsNewText(wsValue); WideString wsPicture = GetPictureContent(eValueType); bool bValidate = true; bool bSyncData = false; CXFA_Node* pNode = GetUIChildNode(); if (!pNode) return true; XFA_Element eType = pNode->GetElementType(); if (!wsPicture.IsEmpty()) { CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr(); GCedLocaleIface* pLocale = GetLocale(); CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this); bValidate = widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture); if (bValidate) { widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsNewText, wsPicture, pLocale, pLocaleMgr); wsNewText = widgetValue.GetValue(); if (eType == XFA_Element::NumericEdit) wsNewText = NumericLimit(wsNewText); bSyncData = true; } } else if (eType == XFA_Element::NumericEdit) { if (!wsNewText.EqualsASCII("0")) wsNewText = NumericLimit(wsNewText); bSyncData = true; } if (eType != XFA_Element::NumericEdit || bSyncData) SyncValue(wsNewText, true); return bValidate; } WideString CXFA_Node::GetPictureContent(XFA_ValuePicture ePicture) { if (ePicture == XFA_ValuePicture::kRaw) return WideString(); CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this); switch (ePicture) { case XFA_ValuePicture::kDisplay: { auto* pFormat = GetChild(0, XFA_Element::Format, false); if (pFormat) { auto* pPicture = pFormat->GetChild(0, XFA_Element::Picture, false); if (pPicture) { absl::optional picture = pPicture->JSObject()->TryContent(false, true); if (picture.has_value()) return picture.value(); } } LocaleIface* pLocale = GetLocale(); if (!pLocale) return WideString(); switch (widgetValue.GetType()) { case CXFA_LocaleValue::ValueType::kDate: return pLocale->GetDatePattern( LocaleIface::DateTimeSubcategory::kMedium); case CXFA_LocaleValue::ValueType::kTime: return pLocale->GetTimePattern( LocaleIface::DateTimeSubcategory::kMedium); case CXFA_LocaleValue::ValueType::kDateTime: return pLocale->GetDatePattern( LocaleIface::DateTimeSubcategory::kMedium) + L"T" + pLocale->GetTimePattern( LocaleIface::DateTimeSubcategory::kMedium); case CXFA_LocaleValue::ValueType::kDecimal: case CXFA_LocaleValue::ValueType::kFloat: default: return WideString(); } } case XFA_ValuePicture::kEdit: { CXFA_Ui* pUI = GetChild(0, XFA_Element::Ui, false); if (pUI) { if (CXFA_Picture* pPicture = pUI->GetChild(0, XFA_Element::Picture, false)) { absl::optional picture = pPicture->JSObject()->TryContent(false, true); if (picture.has_value()) return picture.value(); } } LocaleIface* pLocale = GetLocale(); if (!pLocale) return WideString(); switch (widgetValue.GetType()) { case CXFA_LocaleValue::ValueType::kDate: return pLocale->GetDatePattern( LocaleIface::DateTimeSubcategory::kShort); case CXFA_LocaleValue::ValueType::kTime: return pLocale->GetTimePattern( LocaleIface::DateTimeSubcategory::kShort); case CXFA_LocaleValue::ValueType::kDateTime: return pLocale->GetDatePattern( LocaleIface::DateTimeSubcategory::kShort) + L"T" + pLocale->GetTimePattern( LocaleIface::DateTimeSubcategory::kShort); default: return WideString(); } } case XFA_ValuePicture::kDataBind: { CXFA_Bind* bind = GetBindIfExists(); if (bind) return bind->GetPicture(); break; } default: break; } return WideString(); } WideString CXFA_Node::GetValue(XFA_ValuePicture eValueType) { WideString wsValue = JSObject()->GetContent(false); if (eValueType == XFA_ValuePicture::kDisplay) wsValue = GetItemLabel(wsValue.AsStringView()); WideString wsPicture = GetPictureContent(eValueType); CXFA_Node* pNode = GetUIChildNode(); if (!pNode) return wsValue; switch (pNode->GetElementType()) { case XFA_Element::ChoiceList: { if (eValueType == XFA_ValuePicture::kDisplay) { int32_t iSelItemIndex = GetSelectedItem(0); if (iSelItemIndex >= 0) { wsValue = GetChoiceListItem(iSelItemIndex, false).value_or(WideString()); wsPicture.clear(); } } break; } case XFA_Element::NumericEdit: if (eValueType != XFA_ValuePicture::kRaw && wsPicture.IsEmpty()) { LocaleIface* pLocale = GetLocale(); if (eValueType == XFA_ValuePicture::kDisplay && pLocale) wsValue = FormatNumStr(NormalizeNumStr(wsValue), pLocale); } break; default: break; } if (wsPicture.IsEmpty()) return wsValue; GCedLocaleIface* pLocale = GetLocale(); if (pLocale) { CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this); CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr(); switch (widgetValue.GetType()) { case CXFA_LocaleValue::ValueType::kDate: { WideString wsDate, wsTime; if (SplitDateTime(wsValue, wsDate, wsTime)) { CXFA_LocaleValue date(CXFA_LocaleValue::ValueType::kDate, wsDate, pLocaleMgr); if (date.FormatPatterns(wsValue, wsPicture, pLocale, eValueType)) return wsValue; } break; } case CXFA_LocaleValue::ValueType::kTime: { WideString wsDate, wsTime; if (SplitDateTime(wsValue, wsDate, wsTime)) { CXFA_LocaleValue time(CXFA_LocaleValue::ValueType::kTime, wsTime, pLocaleMgr); 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 WideString(); WideString wsPicture = GetPictureContent(XFA_ValuePicture::kDataBind); if (wsPicture.IsEmpty()) return wsValue; CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr(); GCedLocaleIface* pLocale = GetLocale(); CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this); if (widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture)) { widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsValue, wsPicture, pLocale, pLocaleMgr); return widgetValue.GetValue(); } return wsValue; } WideString CXFA_Node::GetFormatDataValue(const WideString& wsValue) { if (wsValue.IsEmpty()) return WideString(); WideString wsPicture = GetPictureContent(XFA_ValuePicture::kDataBind); if (wsPicture.IsEmpty()) return wsValue; WideString wsFormattedValue = wsValue; GCedLocaleIface* pLocale = GetLocale(); if (pLocale) { CXFA_Value* pNodeValue = GetChild(0, XFA_Element::Value, false); if (!pNodeValue) return wsValue; CXFA_Node* pValueChild = pNodeValue->GetFirstChild(); if (!pValueChild) return wsValue; CXFA_LocaleValue::ValueType iVTType = XFA_GetLocaleValueType(pValueChild->GetElementType()); CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr(); CXFA_LocaleValue widgetValue(iVTType, wsValue, pLocaleMgr); switch (widgetValue.GetType()) { case CXFA_LocaleValue::ValueType::kDate: { WideString wsDate, wsTime; if (SplitDateTime(wsValue, wsDate, wsTime)) { CXFA_LocaleValue date(CXFA_LocaleValue::ValueType::kDate, wsDate, pLocaleMgr); if (date.FormatPatterns(wsFormattedValue, wsPicture, pLocale, XFA_ValuePicture::kDataBind)) { return wsFormattedValue; } } break; } case CXFA_LocaleValue::ValueType::kTime: { WideString wsDate, wsTime; if (SplitDateTime(wsValue, wsDate, wsTime)) { CXFA_LocaleValue time(CXFA_LocaleValue::ValueType::kTime, wsTime, pLocaleMgr); if (time.FormatPatterns(wsFormattedValue, wsPicture, pLocale, XFA_ValuePicture::kDataBind)) { return wsFormattedValue; } } break; } default: break; } widgetValue.FormatPatterns(wsFormattedValue, wsPicture, pLocale, XFA_ValuePicture::kDataBind); } return wsFormattedValue; } WideString CXFA_Node::NormalizeNumStr(const WideString& wsValue) { if (wsValue.IsEmpty()) return WideString(); 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; } void CXFA_Node::InsertListTextItem(CXFA_Node* pItems, const WideString& wsText, int32_t nIndex) { CXFA_Node* pText = pItems->CreateSamePacketNode(XFA_Element::Text); pItems->InsertChildAndNotify(nIndex, pText); pText->JSObject()->SetContent(wsText, wsText, false, false, false); } WideString CXFA_Node::NumericLimit(const WideString& wsValue) { int32_t iLead = GetLeadDigits(); int32_t iTread = GetFracDigits(); if (iLead == -1 && iTread == -1) return wsValue; int32_t iCount = pdfium::base::checked_cast(wsValue.GetLength()); if (iCount == 0) return wsValue; WideString wsRet; int32_t i = 0; if (wsValue[i] == L'-') { wsRet += L'-'; i++; } int32_t iLead2 = 0; int32_t iTread2 = -1; for (; i < iCount; i++) { wchar_t wc = wsValue[i]; if (FXSYS_IsDecimalDigit(wc)) { if (iLead >= 0) { iLead2++; if (iLead2 > iLead) return L"0"; } else if (iTread2 >= 0) { iTread2++; if (iTread2 > iTread) { if (iTread != -1) { CFGAS_Decimal wsDeci = CFGAS_Decimal(wsValue.AsStringView()); wsDeci.SetScale(iTread); wsRet = wsDeci.ToWideString(); } return wsRet; } } } else if (wc == L'.') { iTread2 = 0; iLead = -1; } wsRet += wc; } return wsRet; } bool CXFA_Node::IsTransparent() const { XFA_Element type = GetElementType(); return type == XFA_Element::SubformSet || type == XFA_Element::Area || type == XFA_Element::Proto || (IsUnnamed() && IsContainerNode()); } bool CXFA_Node::IsProperty() const { CXFA_Node* parent = GetParent(); return parent && parent->HasProperty(GetElementType()); } bool CXFA_Node::PresenceRequiresSpace() const { auto value = JSObject()->TryEnum(XFA_Attribute::Presence, true); XFA_AttributeValue ePresence = value.value_or(XFA_AttributeValue::Visible); return ePresence == XFA_AttributeValue::Visible || ePresence == XFA_AttributeValue::Invisible; } void CXFA_Node::SetBindingNode(CXFA_Node* node) { binding_nodes_.clear(); if (node) binding_nodes_.emplace_back(node); } void CXFA_Node::SetNodeAndDescendantsUnused() { CXFA_NodeIterator sIterator(this); for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode; pNode = sIterator.MoveToNext()) { pNode->SetFlag(XFA_NodeFlag::kUnusedNode); } } void CXFA_Node::SetToXML(const WideString& value) { auto* pNode = GetXMLMappingNode(); switch (pNode->GetType()) { case CFX_XMLNode::Type::kElement: { auto* elem = static_cast(pNode); if (IsAttributeInXML()) { elem->SetAttribute(JSObject()->GetCData(XFA_Attribute::QualifiedName), value); return; } bool bDeleteChildren = true; if (GetPacketType() == XFA_PacketType::Datasets) { for (CXFA_Node* pChildDataNode = GetFirstChild(); pChildDataNode; pChildDataNode = pChildDataNode->GetNextSibling()) { if (pChildDataNode->HasBindItems()) { bDeleteChildren = false; break; } } } if (bDeleteChildren) elem->RemoveAllChildren(); auto* text = GetXMLDocument()->CreateNode(value); elem->AppendLastChild(text); break; } case CFX_XMLNode::Type::kText: ToXMLText(GetXMLMappingNode())->SetText(value); break; default: NOTREACHED_NORETURN(); } } CXFA_Node* CXFA_Node::GetTransparentParent() { CXFA_Node* parent = GetParent(); while (parent) { XFA_Element type = parent->GetElementType(); if (type == XFA_Element::Variables || (type != XFA_Element::SubformSet && !parent->IsUnnamed())) { return parent; } parent = parent->GetParent(); } return nullptr; } CFX_XMLDocument* CXFA_Node::GetXMLDocument() const { return GetDocument()->GetNotify()->GetFFDoc()->GetXMLDocument(); } // static CXFA_Node* CXFA_Node::Create(CXFA_Document* doc, XFA_Element element, XFA_PacketType packet) { CXFA_Node* node = nullptr; switch (element) { case XFA_Element::Ps: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::To: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Ui: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::RecordSet: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SubsetBelow: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SubformSet: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::AdobeExtensionLevel: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Typeface: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Break: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::FontInfo: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::NumberPattern: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DynamicRender: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::PrintScaling: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::CheckButton: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DatePatterns: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SourceSet: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Amd: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Arc: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Day: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Era: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Jog: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Log: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Map: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Mdp: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::BreakBefore: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Oid: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Pcl: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Pdf: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Ref: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Uri: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Xdc: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Xdp: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Xfa: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Xsl: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Zpl: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Cache: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Margin: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::KeyUsage: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Exclude: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ChoiceList: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Level: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::LabelPrinter: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::CalendarSymbols: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Para: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Part: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Pdfa: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Filter: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Present: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Pagination: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Encoding: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Event: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Whitespace: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DefaultUi: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DataModel: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Barcode: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::TimePattern: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::BatchOutput: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Enforce: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::CurrencySymbols: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::AddSilentPrint: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Rename: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Operation: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Typefaces: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SubjectDNs: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Issuers: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::WsdlConnection: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Debug: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Delta: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::EraNames: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ModifyAnnots: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::StartNode: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Button: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Format: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Border: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Area: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Hyphenation: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Text: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Time: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Type: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Overprint: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Certificates: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::EncryptionMethods: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SetProperty: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::PrinterName: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::StartPage: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::PageOffset: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DateTime: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Comb: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Pattern: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::IfEmpty: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SuppressBanner: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::OutputBin: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Field: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Agent: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::OutputXSL: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::AdjustData: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::AutoSave: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ContentArea: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::WsdlAddress: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Solid: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DateTimeSymbols: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::EncryptionLevel: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Edge: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Stipple: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Attributes: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::VersionControl: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Meridiem: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ExclGroup: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ToolTip: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Compress: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Reason: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Execute: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ContentCopy: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DateTimeEdit: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Config: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Image: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SharpxHTML: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::NumberOfCopies: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::BehaviorOverride: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::TimeStamp: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Month: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ViewerPreferences: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ScriptModel: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Decimal: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Subform: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Select: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Window: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::LocaleSet: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Handler: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Presence: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Record: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Embed: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Version: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Command: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Copies: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Staple: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SubmitFormat: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Boolean: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Message: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Output: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::PsMap: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ExcludeNS: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Assist: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Picture: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Traversal: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SilentPrint: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::WebClient: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Producer: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Corner: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::MsgId: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Color: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Keep: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Query: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Insert: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ImageEdit: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Validate: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DigestMethods: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::NumberPatterns: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::PageSet: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Integer: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SoapAddress: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Equate: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::FormFieldFilling: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::PageRange: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Update: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ConnectString: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Mode: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Layout: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Sharpxml: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::XsdConnection: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Traverse: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Encodings: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Template: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Acrobat: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ValidationMessaging: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Signing: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Script: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::AddViewerPreferences: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::AlwaysEmbed: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::PasswordEdit: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::NumericEdit: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::EncryptionMethod: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Change: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::PageArea: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SubmitUrl: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Oids: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Signature: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ADBE_JSConsole: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Caption: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Relevant: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::FlipLabel: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ExData: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DayNames: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SoapAction: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DefaultTypeface: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Manifest: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Overflow: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Linear: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::CurrencySymbol: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Delete: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DigestMethod: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::InstanceManager: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::EquateRange: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Medium: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::TextEdit: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::TemplateCache: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::CompressObjectStream: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DataValue: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::AccessibleContent: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::IncludeXDPContent: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::XmlConnection: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ValidateApprovalSignatures: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SignData: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Packets: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DatePattern: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DuplexOption: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Base: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Bind: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Compression: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::User: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Rectangle: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::EffectiveOutputPolicy: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ADBE_JSDebugger: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Acrobat7: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Interactive: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Locale: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::CurrentPage: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Data: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Date: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Desc: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Encrypt: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Draw: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Encryption: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::MeridiemNames: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Messaging: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Speak: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DataGroup: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Common: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Sharptext: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::PaginationOverride: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Reasons: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SignatureProperties: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Threshold: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::AppearanceFilter: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Fill: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Font: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Form: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::MediumInfo: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Certificate: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Password: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::RunScripts: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Trace: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Float: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::RenderPolicy: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Destination: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Value: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Bookend: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ExObject: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::OpenAction: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::NeverEmbed: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::BindItems: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Calculate: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Print: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Extras: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Proto: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DSigData: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Creator: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Connect: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Permissions: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::ConnectionSet: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Submit: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Range: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Linearized: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Packet: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::RootElement: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::PlaintextMetadata: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::NumberSymbols: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::PrintHighQuality: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Driver: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::IncrementalLoad: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::SubjectDN: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::CompressLogicalStructure: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::IncrementalMerge: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Radial: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Variables: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::TimePatterns: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::EffectiveInputPolicy: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::NameAttr: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Conformance: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Transform: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::LockDocument: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::BreakAfter: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Line: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Source: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Occur: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::PickTrayByPDFSize: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::MonthNames: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Severity: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::GroupParent: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DocumentAssembly: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::NumberSymbol: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Tagged: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::Items: node = cppgc::MakeGarbageCollected( doc->GetHeap()->GetAllocationHandle(), doc, packet); break; case XFA_Element::DataWindow: case XFA_Element::Deltas: case XFA_Element::EventPseudoModel: case XFA_Element::HostPseudoModel: case XFA_Element::LayoutPseudoModel: case XFA_Element::List: case XFA_Element::ListDuplicate: case XFA_Element::LogPseudoModel: case XFA_Element::Model: case XFA_Element::Node: case XFA_Element::NodeWithDesc: case XFA_Element::NodeWithUse: case XFA_Element::NodeWithValue: case XFA_Element::Object: case XFA_Element::SignaturePseudoModel: case XFA_Element::Tree: case XFA_Element::TreeList: case XFA_Element::Unknown: // These defined elements can not be made from an XML parse. Some are // not CXFA_Node sub-classes, some are only used as intermediate classes, // and so forth. return nullptr; } if (!node || !node->IsValidInPacket(packet)) return nullptr; return node; }